[kernel] r10422 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series

Maximilian Attems maks at alioth.debian.org
Wed Feb 6 23:27:58 UTC 2008


Author: maks
Date: Wed Feb  6 23:27:43 2008
New Revision: 10422

Log:
update to patch-2.6.24-git15

net, ide, alpha, arm, ia64, m68k, s390, x86 merges

disable bunch of m68 patches presumably all merged, need to check
disable arm feature patches, first conflicts and brings all other
down..


Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git15
      - copied, changed from r10419, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git13
Removed:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git13
Modified:
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra

Copied: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git15 (from r10419, /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git13)
==============================================================================
--- /dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git13	(original)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.24-git15	Wed Feb  6 23:27:43 2008
@@ -11,10 +11,33 @@
  #
  # Top-level generic files
 diff --git a/CREDITS b/CREDITS
-index ee909f2..edff310 100644
+index ee909f2..da0a56e 100644
 --- a/CREDITS
 +++ b/CREDITS
-@@ -1353,6 +1353,14 @@ S: Gen Stedmanstraat 212
+@@ -508,12 +508,8 @@ D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver
+ S: Germany
+ 
+ N: Adrian Bunk
+-E: bunk at stusta.de
+ P: 1024D/4F12B400  B29C E71E FE19 6755 5C8A  84D4 99FC EA98 4F12 B400
+ D: misc kernel hacking and testing
+-S: Grasmeierstrasse 11
+-S: 80805 Muenchen
+-S: Germany
+ 
+ N: Ray Burr
+ E: ryb at nightmare.com
+@@ -1124,6 +1120,9 @@ S: 1150 Ringwood Court
+ S: San Jose, California 95131
+ S: USA
+ 
++N: Adam Fritzler
++E: mid at zigamorph.net
++
+ N: Fernando Fuganti
+ E: fuganti at conectiva.com.br
+ E: fuganti at netbank.com.br
+@@ -1353,6 +1352,14 @@ S: Gen Stedmanstraat 212
  S: 5623 HZ Eindhoven
  S: The Netherlands
  
@@ -29,7 +52,7 @@
  N: Andrew Haylett
  E: ajh at primag.co.uk
  D: Selection mechanism
-@@ -3306,6 +3314,14 @@ S: Universit=E9 de Rennes I
+@@ -3306,6 +3313,14 @@ S: Universit=E9 de Rennes I
  S: F-35042 Rennes Cedex
  S: France
  
@@ -44,6 +67,28 @@
  N: Jon Tombs
  E: jon at gte.esi.us.es
  W: http://www.esi.us.es/~jon
+diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
+index c3014df..40ac775 100644
+--- a/Documentation/00-INDEX
++++ b/Documentation/00-INDEX
+@@ -154,7 +154,7 @@ firmware_class/
+ 	- request_firmware() hotplug interface info.
+ floppy.txt
+ 	- notes and driver options for the floppy disk driver.
+-fujitsu/
++frv/
+ 	- Fujitsu FR-V Linux documentation.
+ gpio.txt
+ 	- overview of GPIO (General Purpose Input/Output) access conventions.
+@@ -364,8 +364,6 @@ sharedsubtree.txt
+ 	- a description of shared subtrees for namespaces.
+ smart-config.txt
+ 	- description of the Smart Config makefile feature.
+-smp.txt
+-	- a few notes on symmetric multi-processing.
+ sony-laptop.txt
+ 	- Sony Notebook Control Driver (SNC) Readme.
+ sonypi.txt
 diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
 index 9734577..11a3c16 100644
 --- a/Documentation/ABI/testing/sysfs-bus-usb
@@ -85,6 +130,78 @@
 +Users:
 +		PowerTOP <power at bughost.org>
 +		http://www.lesswatts.org/projects/powertop/
+diff --git a/Documentation/BUG-HUNTING b/Documentation/BUG-HUNTING
+index 35f5bd2..6c81675 100644
+--- a/Documentation/BUG-HUNTING
++++ b/Documentation/BUG-HUNTING
+@@ -53,7 +53,7 @@ Finding it the old way
+ 
+ [Sat Mar  2 10:32:33 PST 1996 KERNEL_BUG-HOWTO lm at sgi.com (Larry McVoy)]
+ 
+-This is how to track down a bug if you know nothing about kernel hacking.  
++This is how to track down a bug if you know nothing about kernel hacking.
+ It's a brute force approach but it works pretty well.
+ 
+ You need:
+@@ -66,12 +66,12 @@ You will then do:
+ 
+         . Rebuild a revision that you believe works, install, and verify that.
+         . Do a binary search over the kernels to figure out which one
+-          introduced the bug.  I.e., suppose 1.3.28 didn't have the bug, but 
++          introduced the bug.  I.e., suppose 1.3.28 didn't have the bug, but
+           you know that 1.3.69 does.  Pick a kernel in the middle and build
+           that, like 1.3.50.  Build & test; if it works, pick the mid point
+           between .50 and .69, else the mid point between .28 and .50.
+         . You'll narrow it down to the kernel that introduced the bug.  You
+-          can probably do better than this but it gets tricky.  
++          can probably do better than this but it gets tricky.
+ 
+         . Narrow it down to a subdirectory
+ 
+@@ -81,27 +81,27 @@ You will then do:
+             directories:
+ 
+                 Copy the non-working directory next to the working directory
+-                as "dir.63".  
++                as "dir.63".
+                 One directory at time, try moving the working directory to
+-                "dir.62" and mv dir.63 dir"time, try 
++                "dir.62" and mv dir.63 dir"time, try
+ 
+                         mv dir dir.62
+                         mv dir.63 dir
+                         find dir -name '*.[oa]' -print | xargs rm -f
+ 
+                 And then rebuild and retest.  Assuming that all related
+-                changes were contained in the sub directory, this should 
+-                isolate the change to a directory.  
++                changes were contained in the sub directory, this should
++                isolate the change to a directory.
+ 
+                 Problems: changes in header files may have occurred; I've
+-                found in my case that they were self explanatory - you may 
++                found in my case that they were self explanatory - you may
+                 or may not want to give up when that happens.
+ 
+         . Narrow it down to a file
+ 
+           - You can apply the same technique to each file in the directory,
+-            hoping that the changes in that file are self contained.  
+-            
++            hoping that the changes in that file are self contained.
++
+         . Narrow it down to a routine
+ 
+           - You can take the old file and the new file and manually create
+@@ -130,7 +130,7 @@ You will then do:
+             that makes the difference.
+ 
+ Finally, you take all the info that you have, kernel revisions, bug
+-description, the extent to which you have narrowed it down, and pass 
++description, the extent to which you have narrowed it down, and pass
+ that off to whomever you believe is the maintainer of that section.
+ A post to linux.dev.kernel isn't such a bad idea if you've done some
+ work to narrow it down.
 diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
 index 4953bc2..6a0ad47 100644
 --- a/Documentation/DocBook/Makefile
@@ -135,17 +252,48 @@
    </chapter>
  
 diff --git a/Documentation/DocBook/s390-drivers.tmpl b/Documentation/DocBook/s390-drivers.tmpl
-index 254e769..3d2f31b 100644
+index 254e769..4acc732 100644
 --- a/Documentation/DocBook/s390-drivers.tmpl
 +++ b/Documentation/DocBook/s390-drivers.tmpl
-@@ -116,6 +116,7 @@
- !Iinclude/asm-s390/ccwdev.h
- !Edrivers/s390/cio/device.c
- !Edrivers/s390/cio/device_ops.c
+@@ -59,7 +59,7 @@
+    <title>Introduction</title>
+   <para>
+     This document describes the interfaces available for device drivers that
+-    drive s390 based channel attached devices. This includes interfaces for
++    drive s390 based channel attached I/O devices. This includes interfaces for
+     interaction with the hardware and interfaces for interacting with the
+     common driver core. Those interfaces are provided by the s390 common I/O
+     layer.
+@@ -86,9 +86,10 @@
+ 	The ccw bus typically contains the majority of devices available to
+ 	a s390 system. Named after the channel command word (ccw), the basic
+ 	command structure used to address its devices, the ccw bus contains
+-	so-called channel attached devices. They are addressed via subchannels,
+-	visible on the css bus. A device driver, however, will never interact
+-	with the subchannel directly, but only via the device on the ccw bus,
++	so-called channel attached devices. They are addressed via I/O
++	subchannels, visible on the css bus. A device driver for
++	channel-attached devices, however, will never interact	with the
++	subchannel directly, but only via the I/O device on the ccw bus,
+ 	the ccw device.
+   </para>
+     <sect1 id="channelIO">
+@@ -146,4 +147,15 @@
+    </sect1>
+   </chapter>
+ 
++  <chapter id="genericinterfaces">
++   <title>Generic interfaces</title>
++  <para>
++	Some interfaces are available to other drivers that do not necessarily
++	have anything to do with the busses described above, but still are
++	indirectly using basic infrastructure in the common I/O layer.
++	One example is the support for adapter interrupts.
++  </para>
 +!Edrivers/s390/cio/airq.c
-     </sect1>
-     <sect1 id="cmf">
-      <title>The channel-measurement facility</title>
++  </chapter>
++
+ </book>
 diff --git a/Documentation/DocBook/scsi.tmpl b/Documentation/DocBook/scsi.tmpl
 new file mode 100644
 index 0000000..f299ab1
@@ -937,6 +1085,545 @@
  	"Reader Batch" list than in the "Reader Pipe" list.
  
  o	"Free-Block Circulation": Shows the number of torture structures
+diff --git a/Documentation/Smack.txt b/Documentation/Smack.txt
+new file mode 100644
+index 0000000..989c2fc
+--- /dev/null
++++ b/Documentation/Smack.txt
+@@ -0,0 +1,493 @@
++
++
++    "Good for you, you've decided to clean the elevator!"
++    - The Elevator, from Dark Star
++
++Smack is the the Simplified Mandatory Access Control Kernel.
++Smack is a kernel based implementation of mandatory access
++control that includes simplicity in its primary design goals.
++
++Smack is not the only Mandatory Access Control scheme
++available for Linux. Those new to Mandatory Access Control
++are encouraged to compare Smack with the other mechanisms
++available to determine which is best suited to the problem
++at hand.
++
++Smack consists of three major components:
++    - The kernel
++    - A start-up script and a few modified applications
++    - Configuration data
++
++The kernel component of Smack is implemented as a Linux
++Security Modules (LSM) module. It requires netlabel and
++works best with file systems that support extended attributes,
++although xattr support is not strictly required.
++It is safe to run a Smack kernel under a "vanilla" distribution.
++Smack kernels use the CIPSO IP option. Some network
++configurations are intolerant of IP options and can impede
++access to systems that use them as Smack does.
++
++The startup script etc-init.d-smack should be installed
++in /etc/init.d/smack and should be invoked early in the
++start-up process. On Fedora rc5.d/S02smack is recommended.
++This script ensures that certain devices have the correct
++Smack attributes and loads the Smack configuration if
++any is defined. This script invokes two programs that
++ensure configuration data is properly formatted. These
++programs are /usr/sbin/smackload and /usr/sin/smackcipso.
++The system will run just fine without these programs,
++but it will be difficult to set access rules properly.
++
++A version of "ls" that provides a "-M" option to display
++Smack labels on long listing is available.
++
++A hacked version of sshd that allows network logins by users
++with specific Smack labels is available. This version does
++not work for scp. You must set the /etc/ssh/sshd_config
++line:
++   UsePrivilegeSeparation no
++
++The format of /etc/smack/usr is:
++
++   username smack
++
++In keeping with the intent of Smack, configuration data is
++minimal and not strictly required. The most important
++configuration step is mounting the smackfs pseudo filesystem.
++
++Add this line to /etc/fstab:
++
++    smackfs /smack smackfs smackfsdef=* 0 0
++
++and create the /smack directory for mounting.
++
++Smack uses extended attributes (xattrs) to store file labels.
++The command to set a Smack label on a file is:
++
++    # attr -S -s SMACK64 -V "value" path
++
++NOTE: Smack labels are limited to 23 characters. The attr command
++      does not enforce this restriction and can be used to set
++      invalid Smack labels on files.
++
++If you don't do anything special all users will get the floor ("_")
++label when they log in. If you do want to log in via the hacked ssh
++at other labels use the attr command to set the smack value on the
++home directory and it's contents.
++
++You can add access rules in /etc/smack/accesses. They take the form:
++
++    subjectlabel objectlabel access
++
++access is a combination of the letters rwxa which specify the
++kind of access permitted a subject with subjectlabel on an
++object with objectlabel. If there is no rule no access is allowed.
++
++A process can see the smack label it is running with by
++reading /proc/self/attr/current. A privileged process can
++set the process smack by writing there.
++
++Look for additional programs on http://schaufler-ca.com
++
++From the Smack Whitepaper:
++
++The Simplified Mandatory Access Control Kernel
++
++Casey Schaufler
++casey at schaufler-ca.com
++
++Mandatory Access Control
++
++Computer systems employ a variety of schemes to constrain how information is
++shared among the people and services using the machine. Some of these schemes
++allow the program or user to decide what other programs or users are allowed
++access to pieces of data. These schemes are called discretionary access
++control mechanisms because the access control is specified at the discretion
++of the user. Other schemes do not leave the decision regarding what a user or
++program can access up to users or programs. These schemes are called mandatory
++access control mechanisms because you don't have a choice regarding the users
++or programs that have access to pieces of data.
++
++Bell & LaPadula
++
++From the middle of the 1980's until the turn of the century Mandatory Access
++Control (MAC) was very closely associated with the Bell & LaPadula security
++model, a mathematical description of the United States Department of Defense
++policy for marking paper documents. MAC in this form enjoyed a following
++within the Capital Beltway and Scandinavian supercomputer centers but was
++often sited as failing to address general needs.
++
++Domain Type Enforcement
++
++Around the turn of the century Domain Type Enforcement (DTE) became popular.
++This scheme organizes users, programs, and data into domains that are
++protected from each other. This scheme has been widely deployed as a component
++of popular Linux distributions. The administrative overhead required to
++maintain this scheme and the detailed understanding of the whole system
++necessary to provide a secure domain mapping leads to the scheme being
++disabled or used in limited ways in the majority of cases.
++
++Smack
++
++Smack is a Mandatory Access Control mechanism designed to provide useful MAC
++while avoiding the pitfalls of its predecessors. The limitations of Bell &
++LaPadula are addressed by providing a scheme whereby access can be controlled
++according to the requirements of the system and its purpose rather than those
++imposed by an arcane government policy. The complexity of Domain Type
++Enforcement and avoided by defining access controls in terms of the access
++modes already in use.
++
++Smack Terminology
++
++The jargon used to talk about Smack will be familiar to those who have dealt
++with other MAC systems and shouldn't be too difficult for the uninitiated to
++pick up. There are four terms that are used in a specific way and that are
++especially important:
++
++	Subject: A subject is an active entity on the computer system.
++	On Smack a subject is a task, which is in turn the basic unit
++	of execution.
++
++	Object: An object is a passive entity on the computer system.
++	On Smack files of all types, IPC, and tasks can be objects.
++
++	Access: Any attempt by a subject to put information into or get
++	information from an object is an access.
++
++	Label: Data that identifies the Mandatory Access Control
++	characteristics of a subject or an object.
++
++These definitions are consistent with the traditional use in the security
++community. There are also some terms from Linux that are likely to crop up:
++
++	Capability: A task that possesses a capability has permission to
++	violate an aspect of the system security policy, as identified by
++	the specific capability. A task that possesses one or more
++	capabilities is a privileged task, whereas a task with no
++	capabilities is an unprivileged task.
++
++	Privilege: A task that is allowed to violate the system security
++	policy is said to have privilege. As of this writing a task can
++	have privilege either by possessing capabilities or by having an
++	effective user of root.
++
++Smack Basics
++
++Smack is an extension to a Linux system. It enforces additional restrictions
++on what subjects can access which objects, based on the labels attached to
++each of the subject and the object.
++
++Labels
++
++Smack labels are ASCII character strings, one to twenty-three characters in
++length. Single character labels using special characters, that being anything
++other than a letter or digit, are reserved for use by the Smack development
++team. Smack labels are unstructured, case sensitive, and the only operation
++ever performed on them is comparison for equality. Smack labels cannot
++contain unprintable characters or the "/" (slash) character.
++
++There are some predefined labels:
++
++	_ Pronounced "floor", a single underscore character.
++	^ Pronounced "hat", a single circumflex character.
++	* Pronounced "star", a single asterisk character.
++	? Pronounced "huh", a single question mark character.
++
++Every task on a Smack system is assigned a label. System tasks, such as
++init(8) and systems daemons, are run with the floor ("_") label. User tasks
++are assigned labels according to the specification found in the
++/etc/smack/user configuration file.
++
++Access Rules
++
++Smack uses the traditional access modes of Linux. These modes are read,
++execute, write, and occasionally append. There are a few cases where the
++access mode may not be obvious. These include:
++
++	Signals: A signal is a write operation from the subject task to
++	the object task.
++	Internet Domain IPC: Transmission of a packet is considered a
++	write operation from the source task to the destination task.
++
++Smack restricts access based on the label attached to a subject and the label
++attached to the object it is trying to access. The rules enforced are, in
++order:
++
++	1. Any access requested by a task labeled "*" is denied.
++	2. A read or execute access requested by a task labeled "^"
++	   is permitted.
++	3. A read or execute access requested on an object labeled "_"
++	   is permitted.
++	4. Any access requested on an object labeled "*" is permitted.
++	5. Any access requested by a task on an object with the same
++	   label is permitted.
++	6. Any access requested that is explicitly defined in the loaded
++	   rule set is permitted.
++	7. Any other access is denied.
++
++Smack Access Rules
++
++With the isolation provided by Smack access separation is simple. There are
++many interesting cases where limited access by subjects to objects with
++different labels is desired. One example is the familiar spy model of
++sensitivity, where a scientist working on a highly classified project would be
++able to read documents of lower classifications and anything she writes will
++be "born" highly classified. To accommodate such schemes Smack includes a
++mechanism for specifying rules allowing access between labels.
++
++Access Rule Format
++
++The format of an access rule is:
++
++	subject-label object-label access
++
++Where subject-label is the Smack label of the task, object-label is the Smack
++label of the thing being accessed, and access is a string specifying the sort
++of access allowed. The Smack labels are limited to 23 characters. The access
++specification is searched for letters that describe access modes:
++
++	a: indicates that append access should be granted.
++	r: indicates that read access should be granted.
++	w: indicates that write access should be granted.
++	x: indicates that execute access should be granted.
++
++Uppercase values for the specification letters are allowed as well.
++Access mode specifications can be in any order. Examples of acceptable rules
++are:
++
++	TopSecret Secret  rx
++	Secret    Unclass R
++	Manager   Game    x
++	User      HR      w
++	New       Old     rRrRr
++	Closed    Off     -
++
++Examples of unacceptable rules are:
++
++	Top Secret Secret     rx
++	Ace        Ace        r
++	Odd        spells     waxbeans
++
++Spaces are not allowed in labels. Since a subject always has access to files
++with the same label specifying a rule for that case is pointless. Only
++valid letters (rwxaRWXA) and the dash ('-') character are allowed in
++access specifications. The dash is a placeholder, so "a-r" is the same
++as "ar". A lone dash is used to specify that no access should be allowed.
++
++Applying Access Rules
++
++The developers of Linux rarely define new sorts of things, usually importing
++schemes and concepts from other systems. Most often, the other systems are
++variants of Unix. Unix has many endearing properties, but consistency of
++access control models is not one of them. Smack strives to treat accesses as
++uniformly as is sensible while keeping with the spirit of the underlying
++mechanism.
++
++File system objects including files, directories, named pipes, symbolic links,
++and devices require access permissions that closely match those used by mode
++bit access. To open a file for reading read access is required on the file. To
++search a directory requires execute access. Creating a file with write access
++requires both read and write access on the containing directory. Deleting a
++file requires read and write access to the file and to the containing
++directory. It is possible that a user may be able to see that a file exists
++but not any of its attributes by the circumstance of having read access to the
++containing directory but not to the differently labeled file. This is an
++artifact of the file name being data in the directory, not a part of the file.
++
++IPC objects, message queues, semaphore sets, and memory segments exist in flat
++namespaces and access requests are only required to match the object in
++question.
++
++Process objects reflect tasks on the system and the Smack label used to access
++them is the same Smack label that the task would use for its own access
++attempts. Sending a signal via the kill() system call is a write operation
++from the signaler to the recipient. Debugging a process requires both reading
++and writing. Creating a new task is an internal operation that results in two
++tasks with identical Smack labels and requires no access checks.
++
++Sockets are data structures attached to processes and sending a packet from
++one process to another requires that the sender have write access to the
++receiver. The receiver is not required to have read access to the sender.
++
++Setting Access Rules
++
++The configuration file /etc/smack/accesses contains the rules to be set at
++system startup. The contents are written to the special file /smack/load.
++Rules can be written to /smack/load at any time and take effect immediately.
++For any pair of subject and object labels there can be only one rule, with the
++most recently specified overriding any earlier specification.
++
++The program smackload is provided to ensure data is formatted
++properly when written to /smack/load. This program reads lines
++of the form
++
++    subjectlabel objectlabel mode.
++
++Task Attribute
++
++The Smack label of a process can be read from /proc/<pid>/attr/current. A
++process can read its own Smack label from /proc/self/attr/current. A
++privileged process can change its own Smack label by writing to
++/proc/self/attr/current but not the label of another process.
++
++File Attribute
++
++The Smack label of a filesystem object is stored as an extended attribute
++named SMACK64 on the file. This attribute is in the security namespace. It can
++only be changed by a process with privilege.
++
++Privilege
++
++A process with CAP_MAC_OVERRIDE is privileged.
++
++Smack Networking
++
++As mentioned before, Smack enforces access control on network protocol
++transmissions. Every packet sent by a Smack process is tagged with its Smack
++label. This is done by adding a CIPSO tag to the header of the IP packet. Each
++packet received is expected to have a CIPSO tag that identifies the label and
++if it lacks such a tag the network ambient label is assumed. Before the packet
++is delivered a check is made to determine that a subject with the label on the
++packet has write access to the receiving process and if that is not the case
++the packet is dropped.
++
++CIPSO Configuration
++
++It is normally unnecessary to specify the CIPSO configuration. The default
++values used by the system handle all internal cases. Smack will compose CIPSO
++label values to match the Smack labels being used without administrative
++intervention. Unlabeled packets that come into the system will be given the
++ambient label.
++
++Smack requires configuration in the case where packets from a system that is
++not smack that speaks CIPSO may be encountered. Usually this will be a Trusted
++Solaris system, but there are other, less widely deployed systems out there.
++CIPSO provides 3 important values, a Domain Of Interpretation (DOI), a level,
++and a category set with each packet. The DOI is intended to identify a group
++of systems that use compatible labeling schemes, and the DOI specified on the
++smack system must match that of the remote system or packets will be
++discarded. The DOI is 3 by default. The value can be read from /smack/doi and
++can be changed by writing to /smack/doi.
++
++The label and category set are mapped to a Smack label as defined in
++/etc/smack/cipso.
++
++A Smack/CIPSO mapping has the form:
++
++	smack level [category [category]*]
++
++Smack does not expect the level or category sets to be related in any
++particular way and does not assume or assign accesses based on them. Some
++examples of mappings:
++
++	TopSecret 7
++	TS:A,B    7 1 2
++	SecBDE    5 2 4 6
++	RAFTERS   7 12 26
++
++The ":" and "," characters are permitted in a Smack label but have no special
++meaning.
++
++The mapping of Smack labels to CIPSO values is defined by writing to
++/smack/cipso. Again, the format of data written to this special file
++is highly restrictive, so the program smackcipso is provided to
++ensure the writes are done properly. This program takes mappings
++on the standard input and sends them to /smack/cipso properly.
++
++In addition to explicit mappings Smack supports direct CIPSO mappings. One
++CIPSO level is used to indicate that the category set passed in the packet is
++in fact an encoding of the Smack label. The level used is 250 by default. The
++value can be read from /smack/direct and changed by writing to /smack/direct.
++
++Socket Attributes
++
++There are two attributes that are associated with sockets. These attributes
++can only be set by privileged tasks, but any task can read them for their own
++sockets.
++
++	SMACK64IPIN: The Smack label of the task object. A privileged
++	program that will enforce policy may set this to the star label.
++
++	SMACK64IPOUT: The Smack label transmitted with outgoing packets.
++	A privileged program may set this to match the label of another
++	task with which it hopes to communicate.
++
++Writing Applications for Smack
++
++There are three sorts of applications that will run on a Smack system. How an
++application interacts with Smack will determine what it will have to do to
++work properly under Smack.
++
++Smack Ignorant Applications
++
++By far the majority of applications have no reason whatever to care about the
++unique properties of Smack. Since invoking a program has no impact on the
++Smack label associated with the process the only concern likely to arise is
++whether the process has execute access to the program.
++
++Smack Relevant Applications
++
++Some programs can be improved by teaching them about Smack, but do not make
++any security decisions themselves. The utility ls(1) is one example of such a
++program.
++
++Smack Enforcing Applications
++
++These are special programs that not only know about Smack, but participate in
++the enforcement of system policy. In most cases these are the programs that
++set up user sessions. There are also network services that provide information
++to processes running with various labels.
++
++File System Interfaces
++
++Smack maintains labels on file system objects using extended attributes. The
++Smack label of a file, directory, or other file system object can be obtained
++using getxattr(2).
++
++	len = getxattr("/", "security.SMACK64", value, sizeof (value));
++
++will put the Smack label of the root directory into value. A privileged
++process can set the Smack label of a file system object with setxattr(2).
++
++	len = strlen("Rubble");
++	rc = setxattr("/foo", "security.SMACK64", "Rubble", len, 0);
++
++will set the Smack label of /foo to "Rubble" if the program has appropriate
++privilege.
++
++Socket Interfaces
++
++The socket attributes can be read using fgetxattr(2).
++
++A privileged process can set the Smack label of outgoing packets with
++fsetxattr(2).
++
++	len = strlen("Rubble");
++	rc = fsetxattr(fd, "security.SMACK64IPOUT", "Rubble", len, 0);
++
++will set the Smack label "Rubble" on packets going out from the socket if the
++program has appropriate privilege.
++
++	rc = fsetxattr(fd, "security.SMACK64IPIN, "*", strlen("*"), 0);
++
++will set the Smack label "*" as the object label against which incoming
++packets will be checked if the program has appropriate privilege.
++
++Administration
++
++Smack supports some mount options:
++
++	smackfsdef=label: specifies the label to give files that lack
++	the Smack label extended attribute.
++
++	smackfsroot=label: specifies the label to assign the root of the
++	file system if it lacks the Smack extended attribute.
++
++	smackfshat=label: specifies a label that must have read access to
++	all labels set on the filesystem. Not yet enforced.
++
++	smackfsfloor=label: specifies a label to which all labels set on the
++	filesystem must have read access. Not yet enforced.
++
++These mount options apply to all file system types.
++
+diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
+index 681e2b3..08a1ed1 100644
+--- a/Documentation/SubmittingPatches
++++ b/Documentation/SubmittingPatches
+@@ -220,20 +220,8 @@ decreasing the likelihood of your MIME-attached change being accepted.
+ Exception:  If your mailer is mangling patches then someone may ask
+ you to re-send them using MIME.
+ 
+-
+-WARNING: Some mailers like Mozilla send your messages with
+----- message header ----
+-Content-Type: text/plain; charset=us-ascii; format=flowed
+----- message header ----
+-The problem is that "format=flowed" makes some of the mailers
+-on receiving side to replace TABs with spaces and do similar
+-changes. Thus the patches from you can look corrupted.
+-
+-To fix this just make your mozilla defaults/pref/mailnews.js file to look like:
+-pref("mailnews.send_plaintext_flowed", false); // RFC 2646=======
+-pref("mailnews.display.disable_format_flowed_support", true);
+-
+-
++See Documentation/email-clients.txt for hints about configuring
++your e-mail client so that it sends your patches untouched.
+ 
+ 8) E-mail size.
+ 
+diff --git a/Documentation/arm/Sharp-LH/IOBarrier b/Documentation/arm/Sharp-LH/IOBarrier
+index c0d8853..2e953e2 100644
+--- a/Documentation/arm/Sharp-LH/IOBarrier
++++ b/Documentation/arm/Sharp-LH/IOBarrier
+@@ -32,7 +32,7 @@ BARRIER IO before the access to the SMC chip because the AEN latch
+ only needs occurs after the SMC IO write cycle.  The routines that
+ implement this work-around make an additional concession which is to
+ disable interrupts during the IO sequence.  Other hardware devices
+-(the LogicPD CPLD) have registers in the same the physical memory
++(the LogicPD CPLD) have registers in the same physical memory
+ region as the SMC chip.  An interrupt might allow an access to one of
+ those registers while SMC IO is being performed.
+ 
 diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt
 index 555c8cf..af3b925 100644
 --- a/Documentation/cpu-freq/user-guide.txt
@@ -1050,6 +1737,18 @@
  
  
  FURTHER INFORMATION
+diff --git a/Documentation/debugging-modules.txt b/Documentation/debugging-modules.txt
+index 24029f6..172ad4a 100644
+--- a/Documentation/debugging-modules.txt
++++ b/Documentation/debugging-modules.txt
+@@ -16,3 +16,7 @@ echo 'echo "$@" >> /tmp/modprobe.log' >> /tmp/modprobe
+ echo 'exec /sbin/modprobe "$@"' >> /tmp/modprobe
+ chmod a+x /tmp/modprobe
+ echo /tmp/modprobe > /proc/sys/kernel/modprobe
++
++Note that the above applies only when the *kernel* is requesting
++that the module be loaded -- it won't have any effect if that module
++is being loaded explicitly using "modprobe" from userspace.
 diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt
 new file mode 100644
 index 0000000..de4804e
@@ -1248,6 +1947,29 @@
  53c8xx_d.h*
  BitKeeper
  COPYING
+diff --git a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt
+index 2a97320..83009fd 100644
+--- a/Documentation/driver-model/platform.txt
++++ b/Documentation/driver-model/platform.txt
+@@ -122,15 +122,15 @@ None the less, there are some APIs to support such legacy drivers.  Avoid
+ using these calls except with such hotplug-deficient drivers.
+ 
+ 	struct platform_device *platform_device_alloc(
+-			char *name, unsigned id);
++			const char *name, int id);
+ 
+ You can use platform_device_alloc() to dynamically allocate a device, which
+ you will then initialize with resources and platform_device_register().
+ A better solution is usually:
+ 
+ 	struct platform_device *platform_device_register_simple(
+-			char *name, unsigned id,
+-			struct resource *res, unsigned nres);
++			const char *name, int id,
++			struct resource *res, unsigned int nres);
+ 
+ You can use platform_device_register_simple() as a one-step call to allocate
+ and register a device.
 diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt
 index ecb47ad..b7b1d1b 100644
 --- a/Documentation/dvb/bt8xx.txt
@@ -1455,6 +2177,19 @@
 +	and slightly hurts runtime performance. Bugfixes for the old firmware
 +	are not provided by Broadcom anymore.
 +Who:	Michael Buesch <mb at bu3sch.de>
+diff --git a/Documentation/filesystems/configfs/configfs.txt b/Documentation/filesystems/configfs/configfs.txt
+index d1b9825..44c97e6 100644
+--- a/Documentation/filesystems/configfs/configfs.txt
++++ b/Documentation/filesystems/configfs/configfs.txt
+@@ -377,7 +377,7 @@ more explicit to have a method whereby userspace sees this divergence.
+ Rather than have a group where some items behave differently than
+ others, configfs provides a method whereby one or many subgroups are
+ automatically created inside the parent at its creation.  Thus,
+-mkdir("parent) results in "parent", "parent/subgroup1", up through
++mkdir("parent") results in "parent", "parent/subgroup1", up through
+ "parent/subgroupN".  Items of type 1 can now be created in
+ "parent/subgroup1", and items of type N can be created in
+ "parent/subgroupN".
 diff --git a/Documentation/filesystems/ext4.txt b/Documentation/filesystems/ext4.txt
 index 6a4adca..560f88d 100644
 --- a/Documentation/filesystems/ext4.txt
@@ -1526,11 +2261,49 @@
 +			large, the fs will silently revert it to the default.
 +			Localalloc is not enabled for local mounts.
 +localflocks		This disables cluster aware flock.
+diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting
+index dac45c9..0f33c77 100644
+--- a/Documentation/filesystems/porting
++++ b/Documentation/filesystems/porting
+@@ -1,6 +1,6 @@
+ Changes since 2.5.0:
+ 
+---- 
++---
+ [recommended]
+ 
+ New helpers: sb_bread(), sb_getblk(), sb_find_get_block(), set_bh(),
+@@ -10,7 +10,7 @@ Use them.
+ 
+ (sb_find_get_block() replaces 2.4's get_hash_table())
+ 
+---- 
++---
+ [recommended]
+ 
+ New methods: ->alloc_inode() and ->destroy_inode().
+@@ -28,7 +28,7 @@ Declare
+ 
+ Use FOO_I(inode) instead of &inode->u.foo_inode_i;
+ 
+-Add foo_alloc_inode() and foo_destory_inode() - the former should allocate
++Add foo_alloc_inode() and foo_destroy_inode() - the former should allocate
+ foo_inode_info and return the address of ->vfs_inode, the latter should free
+ FOO_I(inode) (see in-tree filesystems for examples).
+ 
 diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
-index dec9945..194c8f3 100644
+index dec9945..e2799b5 100644
 --- a/Documentation/filesystems/proc.txt
 +++ b/Documentation/filesystems/proc.txt
-@@ -857,6 +857,45 @@ CPUs.
+@@ -216,6 +216,7 @@ Table 1-3: Contents of the stat files (as of 2.6.22-rc3)
+   priority      priority level
+   nice          nice level
+   num_threads   number of threads
++  it_real_value	(obsolete, always 0)
+   start_time    time the process started after system boot
+   vsize         virtual memory size
+   rss           resident set memory size
+@@ -857,6 +858,45 @@ CPUs.
  The   "procs_blocked" line gives  the  number of  processes currently blocked,
  waiting for I/O to complete.
  
@@ -1576,7 +2349,7 @@
  
  ------------------------------------------------------------------------------
  Summary
-@@ -1095,13 +1134,6 @@ check the amount of free space (value is in seconds). Default settings are: 4,
+@@ -1095,13 +1135,6 @@ check the amount of free space (value is in seconds). Default settings are: 4,
  resume it  if we have a value of 3 or more percent; consider information about
  the amount of free space valid for 30 seconds
  
@@ -1590,7 +2363,125 @@
  ctrl-alt-del
  ------------
  
-@@ -1880,11 +1912,6 @@ max_size
+@@ -1282,13 +1315,28 @@ for writeout by the pdflush daemons.  It is expressed in 100'ths of a second.
+ Data which has been dirty in-memory for longer than this interval will be
+ written out next time a pdflush daemon wakes up.
+ 
++highmem_is_dirtyable
++--------------------
++
++Only present if CONFIG_HIGHMEM is set.
++
++This defaults to 0 (false), meaning that the ratios set above are calculated
++as a percentage of lowmem only.  This protects against excessive scanning
++in page reclaim, swapping and general VM distress.
++
++Setting this to 1 can be useful on 32 bit machines where you want to make
++random changes within an MMAPed file that is larger than your available
++lowmem without causing large quantities of random IO.  Is is safe if the
++behavior of all programs running on the machine is known and memory will
++not be otherwise stressed.
++
+ legacy_va_layout
+ ----------------
+ 
+ If non-zero, this sysctl disables the new 32-bit mmap mmap layout - the kernel
+ will use the legacy (2.4) layout for all processes.
+ 
+-lower_zone_protection
++lowmem_reserve_ratio
+ ---------------------
+ 
+ For some specialised workloads on highmem machines it is dangerous for
+@@ -1308,25 +1356,71 @@ captured into pinned user memory.
+ mechanism will also defend that region from allocations which could use
+ highmem or lowmem).
+ 
+-The `lower_zone_protection' tunable determines how aggressive the kernel is
+-in defending these lower zones.  The default value is zero - no
+-protection at all.
++The `lowmem_reserve_ratio' tunable determines how aggressive the kernel is
++in defending these lower zones.
+ 
+ If you have a machine which uses highmem or ISA DMA and your
+ applications are using mlock(), or if you are running with no swap then
+-you probably should increase the lower_zone_protection setting.
+-
+-The units of this tunable are fairly vague.  It is approximately equal
+-to "megabytes," so setting lower_zone_protection=100 will protect around 100
+-megabytes of the lowmem zone from user allocations.  It will also make
+-those 100 megabytes unavailable for use by applications and by
+-pagecache, so there is a cost.
+-
+-The effects of this tunable may be observed by monitoring
+-/proc/meminfo:LowFree.  Write a single huge file and observe the point
+-at which LowFree ceases to fall.
+-
+-A reasonable value for lower_zone_protection is 100.
++you probably should change the lowmem_reserve_ratio setting.
++
++The lowmem_reserve_ratio is an array. You can see them by reading this file.
++-
++% cat /proc/sys/vm/lowmem_reserve_ratio
++256     256     32
++-
++Note: # of this elements is one fewer than number of zones. Because the highest
++      zone's value is not necessary for following calculation.
++
++But, these values are not used directly. The kernel calculates # of protection
++pages for each zones from them. These are shown as array of protection pages
++in /proc/zoneinfo like followings. (This is an example of x86-64 box).
++Each zone has an array of protection pages like this.
++
++-
++Node 0, zone      DMA
++  pages free     1355
++        min      3
++        low      3
++        high     4
++	:
++	:
++    numa_other   0
++        protection: (0, 2004, 2004, 2004)
++	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++  pagesets
++    cpu: 0 pcp: 0
++        :
++-
++These protections are added to score to judge whether this zone should be used
++for page allocation or should be reclaimed.
++
++In this example, if normal pages (index=2) are required to this DMA zone and
++pages_high is used for watermark, the kernel judges this zone should not be
++used because pages_free(1355) is smaller than watermark + protection[2]
++(4 + 2004 = 2008). If this protection value is 0, this zone would be used for
++normal page requirement. If requirement is DMA zone(index=0), protection[0]
++(=0) is used.
++
++zone[i]'s protection[j] is calculated by following exprssion.
++
++(i < j):
++  zone[i]->protection[j]
++  = (total sums of present_pages from zone[i+1] to zone[j] on the node)
++    / lowmem_reserve_ratio[i];
++(i = j):
++   (should not be protected. = 0;
++(i > j):
++   (not necessary, but looks 0)
++
++The default values of lowmem_reserve_ratio[i] are
++    256 (if zone[i] means DMA or DMA32 zone)
++    32  (others).
++As above expression, they are reciprocal number of ratio.
++256 means 1/256. # of protection pages becomes about "0.39%" of total present
++pages of higher zones on the node.
++
++If you would like to protect more pages, smaller values are effective.
++The minimum value is 1 (1/1 -> 100%).
+ 
+ page-cluster
+ ------------
+@@ -1880,11 +1974,6 @@ max_size
  Maximum size  of  the routing cache. Old entries will be purged once the cache
  reached has this size.
  
@@ -1602,6 +2493,3700 @@
  redirect_load, redirect_number
  ------------------------------
  
+diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.txt b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+index 339c6a4..7be232b 100644
+--- a/Documentation/filesystems/ramfs-rootfs-initramfs.txt
++++ b/Documentation/filesystems/ramfs-rootfs-initramfs.txt
+@@ -118,7 +118,7 @@ All this differs from the old initrd in several ways:
+     with the new root (cd /newmount; mount --move . /; chroot .), attach
+     stdin/stdout/stderr to the new /dev/console, and exec the new init.
+ 
+-    Since this is a remarkably persnickity process (and involves deleting
++    Since this is a remarkably persnickety process (and involves deleting
+     commands before you can run them), the klibc package introduced a helper
+     program (utils/run_init.c) to do all this for you.  Most other packages
+     (such as busybox) have named this command "switch_root".
+diff --git a/Documentation/filesystems/relay.txt b/Documentation/filesystems/relay.txt
+index 18d23f9..094f2d2 100644
+--- a/Documentation/filesystems/relay.txt
++++ b/Documentation/filesystems/relay.txt
+@@ -140,7 +140,7 @@ close()     decrements the channel buffer's refcount.  When the refcount
+ In order for a user application to make use of relay files, the
+ host filesystem must be mounted.  For example,
+ 
+-	mount -t debugfs debugfs /debug
++	mount -t debugfs debugfs /sys/kernel/debug
+ 
+ NOTE:   the host filesystem doesn't need to be mounted for kernel
+ 	clients to create or use channels - it only needs to be
+diff --git a/Documentation/frv/README.txt b/Documentation/frv/README.txt
+new file mode 100644
+index 0000000..a984faa
+--- /dev/null
++++ b/Documentation/frv/README.txt
+@@ -0,0 +1,51 @@
++		       ================================
++		       Fujitsu FR-V LINUX DOCUMENTATION
++		       ================================
++
++This directory contains documentation for the Fujitsu FR-V CPU architecture
++port of Linux.
++
++The following documents are available:
++
++ (*) features.txt
++
++     A description of the basic features inherent in this architecture port.
++
++
++ (*) configuring.txt
++
++     A summary of the configuration options particular to this architecture.
++
++
++ (*) booting.txt
++
++     A description of how to boot the kernel image and a summary of the kernel
++     command line options.
++
++
++ (*) gdbstub.txt
++
++     A description of how to debug the kernel using GDB attached by serial
++     port, and a summary of the services available.
++
++
++ (*) mmu-layout.txt
++
++     A description of the virtual and physical memory layout used in the
++     MMU linux kernel, and the registers used to support it.
++
++
++ (*) gdbinit
++
++     An example .gdbinit file for use with GDB. It includes macros for viewing
++     MMU state on the FR451. See mmu-layout.txt for more information.
++
++
++ (*) clock.txt
++
++     A description of the CPU clock scaling interface.
++
++
++ (*) atomic-ops.txt
++
++     A description of how the FR-V kernel's atomic operations work.
+diff --git a/Documentation/frv/atomic-ops.txt b/Documentation/frv/atomic-ops.txt
+new file mode 100644
+index 0000000..96638e9
+--- /dev/null
++++ b/Documentation/frv/atomic-ops.txt
+@@ -0,0 +1,134 @@
++			       =====================================
++			       FUJITSU FR-V KERNEL ATOMIC OPERATIONS
++			       =====================================
++
++On the FR-V CPUs, there is only one atomic Read-Modify-Write operation: the SWAP/SWAPI
++instruction. Unfortunately, this alone can't be used to implement the following operations:
++
++ (*) Atomic add to memory
++
++ (*) Atomic subtract from memory
++
++ (*) Atomic bit modification (set, clear or invert)
++
++ (*) Atomic compare and exchange
++
++On such CPUs, the standard way of emulating such operations in uniprocessor mode is to disable
++interrupts, but on the FR-V CPUs, modifying the PSR takes a lot of clock cycles, and it has to be
++done twice. This means the CPU runs for a relatively long time with interrupts disabled,
++potentially having a great effect on interrupt latency.
++
++
++=============
++NEW ALGORITHM
++=============
++
++To get around this, the following algorithm has been implemented. It operates in a way similar to
++the LL/SC instruction pairs supported on a number of platforms.
++
++ (*) The CCCR.CC3 register is reserved within the kernel to act as an atomic modify abort flag.
++
++ (*) In the exception prologues run on kernel->kernel entry, CCCR.CC3 is set to 0 (Undefined
++     state).
++
++ (*) All atomic operations can then be broken down into the following algorithm:
++
++     (1) Set ICC3.Z to true and set CC3 to True (ORCC/CKEQ/ORCR).
++
++     (2) Load the value currently in the memory to be modified into a register.
++
++     (3) Make changes to the value.
++
++     (4) If CC3 is still True, simultaneously and atomically (by VLIW packing):
++
++	 (a) Store the modified value back to memory.
++
++	 (b) Set ICC3.Z to false (CORCC on GR29 is sufficient for this - GR29 holds the current
++	     task pointer in the kernel, and so is guaranteed to be non-zero).
++
++     (5) If ICC3.Z is still true, go back to step (1).
++
++This works in a non-SMP environment because any interrupt or other exception that happens between
++steps (1) and (4) will set CC3 to the Undefined, thus aborting the store in (4a), and causing the
++condition in ICC3 to remain with the Z flag set, thus causing step (5) to loop back to step (1).
++
++
++This algorithm suffers from two problems:
++
++ (1) The condition CCCR.CC3 is cleared unconditionally by an exception, irrespective of whether or
++     not any changes were made to the target memory location during that exception.
++
++ (2) The branch from step (5) back to step (1) may have to happen more than once until the store
++     manages to take place. In theory, this loop could cycle forever because there are too many
++     interrupts coming in, but it's unlikely.
++
++
++=======
++EXAMPLE
++=======
++
++Taking an example from include/asm-frv/atomic.h:
++
++	static inline int atomic_add_return(int i, atomic_t *v)
++	{
++		unsigned long val;
++
++		asm("0:						\n"
++
++It starts by setting ICC3.Z to true for later use, and also transforming that into CC3 being in the
++True state.
++
++		    "	orcc		gr0,gr0,gr0,icc3	\n"	<-- (1)
++		    "	ckeq		icc3,cc7		\n"	<-- (1)
++
++Then it does the load. Note that the final phase of step (1) is done at the same time as the
++load. The VLIW packing ensures they are done simultaneously. The ".p" on the load must not be
++removed without swapping the order of these two instructions.
++
++		    "	ld.p		%M0,%1			\n"	<-- (2)
++		    "	orcr		cc7,cc7,cc3		\n"	<-- (1)
++
++Then the proposed modification is generated. Note that the old value can be retained if required
++(such as in test_and_set_bit()).
++
++		    "	add%I2		%1,%2,%1		\n"	<-- (3)
++
++Then it attempts to store the value back, contingent on no exception having cleared CC3 since it
++was set to True.
++
++		    "	cst.p		%1,%M0		,cc3,#1	\n"	<-- (4a)
++
++It simultaneously records the success or failure of the store in ICC3.Z.
++
++		    "	corcc		gr29,gr29,gr0	,cc3,#1	\n"	<-- (4b)
++
++Such that the branch can then be taken if the operation was aborted.
++
++		    "	beq		icc3,#0,0b		\n"	<-- (5)
++		    : "+U"(v->counter), "=&r"(val)
++		    : "NPr"(i)
++		    : "memory", "cc7", "cc3", "icc3"
++		    );
++
++		return val;
++	}
++
++
++=============
++CONFIGURATION
++=============
++
++The atomic ops implementation can be made inline or out-of-line by changing the
++CONFIG_FRV_OUTOFLINE_ATOMIC_OPS configuration variable. Making it out-of-line has a number of
++advantages:
++
++ - The resulting kernel image may be smaller
++ - Debugging is easier as atomic ops can just be stepped over and they can be breakpointed
++
++Keeping it inline also has a number of advantages:
++
++ - The resulting kernel may be Faster
++   - no out-of-line function calls need to be made
++   - the compiler doesn't have half its registers clobbered by making a call
++
++The out-of-line implementations live in arch/frv/lib/atomic-ops.S.
+diff --git a/Documentation/frv/booting.txt b/Documentation/frv/booting.txt
+new file mode 100644
+index 0000000..ace200b
+--- /dev/null
++++ b/Documentation/frv/booting.txt
+@@ -0,0 +1,181 @@
++			  =========================
++			  BOOTING FR-V LINUX KERNEL
++			  =========================
++
++======================
++PROVIDING A FILESYSTEM
++======================
++
++First of all, a root filesystem must be made available. This can be done in
++one of two ways:
++
++  (1) NFS Export
++
++      A filesystem should be constructed in a directory on an NFS server that
++      the target board can reach. This directory should then be NFS exported
++      such that the target board can read and write into it as root.
++
++  (2) Flash Filesystem (JFFS2 Recommended)
++
++      In this case, the image must be stored or built up on flash before it
++      can be used. A complete image can be built using the mkfs.jffs2 or
++      similar program and then downloaded and stored into flash by RedBoot.
++
++
++========================
++LOADING THE KERNEL IMAGE
++========================
++
++The kernel will need to be loaded into RAM by RedBoot (or by some alternative
++boot loader) before it can be run. The kernel image (arch/frv/boot/Image) may
++be loaded in one of three ways:
++
++  (1) Load from Flash
++
++      This is the simplest. RedBoot can store an image in the flash (see the
++      RedBoot documentation) and then load it back into RAM. RedBoot keeps
++      track of the load address, entry point and size, so the command to do
++      this is simply:
++
++	fis load linux
++
++      The image is then ready to be executed.
++
++  (2) Load by TFTP
++
++      The following command will download a raw binary kernel image from the
++      default server (as negotiated by BOOTP) and store it into RAM:
++
++	load -b 0x00100000 -r /tftpboot/image.bin
++
++      The image is then ready to be executed.
++
++  (3) Load by Y-Modem
++
++      The following command will download a raw binary kernel image across the
++      serial port that RedBoot is currently using:
++
++	load -m ymodem -b 0x00100000 -r zImage
++
++      The serial client (such as minicom) must then be told to transmit the
++      program by Y-Modem.
++
++      When finished, the image will then be ready to be executed.
++
++
++==================
++BOOTING THE KERNEL
++==================
++
++Boot the image with the following RedBoot command:
++
++	exec -c "<CMDLINE>" 0x00100000
++
++For example:
++
++	exec -c "console=ttySM0,115200 ip=:::::dhcp root=/dev/mtdblock2 rw"
++
++This will start the kernel running. Note that if the GDB-stub is compiled in,
++then the kernel will immediately wait for GDB to connect over serial before
++doing anything else. See the section on kernel debugging with GDB.
++
++The kernel command line <CMDLINE> tells the kernel where its console is and
++how to find its root filesystem. This is made up of the following components,
++separated by spaces:
++
++  (*) console=ttyS<x>[,<baud>[<parity>[<bits>[<flow>]]]]
++
++      This specifies that the system console should output through on-chip
++      serial port <x> (which can be "0" or "1").
++
++      <baud> is a standard baud rate between 1200 and 115200 (default 9600).
++
++      <parity> is a parity setting of "N", "O", "E", "M" or "S" for None, Odd,
++      Even, Mark or Space. "None" is the default.
++
++      <stop> is "7" or "8" for the number of bits per character. "8" is the
++      default.
++
++      <flow> is "r" to use flow control (XCTS on serial port 2 only). The
++      default is to not use flow control.
++
++      For example:
++
++	console=ttyS0,115200
++
++      To use the first on-chip serial port at baud rate 115200, no parity, 8
++      bits, and no flow control.
++
++  (*) root=/dev/<xxxx>
++
++      This specifies the device upon which the root filesystem resides. For
++      example:
++
++	/dev/nfs	NFS root filesystem
++	/dev/mtdblock3	Fourth RedBoot partition on the System Flash
++
++  (*) rw
++
++      Start with the root filesystem mounted Read/Write.
++
++  The remaining components are all optional:
++
++  (*) ip=<ip>::::<host>:<iface>:<cfg>
++
++      Configure the network interface. If <cfg> is "off" then <ip> should
++      specify the IP address for the network device <iface>. <host> provide
++      the hostname for the device.
++
++      If <cfg> is "bootp" or "dhcp", then all of these parameters will be
++      discovered by consulting a BOOTP or DHCP server.
++
++      For example, the following might be used:
++
++	ip=192.168.73.12::::frv:eth0:off
++
++      This sets the IP address on the VDK motherboard RTL8029 ethernet chipset
++      (eth0) to be 192.168.73.12, and sets the board's hostname to be "frv".
++
++  (*) nfsroot=<server>:<dir>[,v<vers>]
++
++      This is mandatory if "root=/dev/nfs" is given as an option. It tells the
++      kernel the IP address of the NFS server providing its root filesystem,
++      and the pathname on that server of the filesystem.
++
++      The NFS version to use can also be specified. v2 and v3 are supported by
++      Linux.
++
++      For example:
++
++	nfsroot=192.168.73.1:/nfsroot-frv
++
++  (*) profile=1
++
++      Turns on the kernel profiler (accessible through /proc/profile).
++
++  (*) console=gdb0
++
++      This can be used as an alternative to the "console=ttyS..." listed
++      above. I tells the kernel to pass the console output to GDB if the
++      gdbstub is compiled in to the kernel.
++
++      If this is used, then the gdbstub passes the text to GDB, which then
++      simply dumps it to its standard output.
++
++  (*) mem=<xxx>M
++
++      Normally the kernel will work out how much SDRAM it has by reading the
++      SDRAM controller registers. That can be overridden with this
++      option. This allows the kernel to be told that it has <xxx> megabytes of
++      memory available.
++
++  (*) init=<prog> [<arg> [<arg> [<arg> ...]]]
++
++      This tells the kernel what program to run initially. By default this is
++      /sbin/init, but /sbin/sash or /bin/sh are common alternatives.
++
++  (*) vdc=...
++
++      This option configures the MB93493 companion chip visual display
++      driver. Please see Documentation/frv/mb93493/vdc.txt for more
++      information.
+diff --git a/Documentation/frv/clock.txt b/Documentation/frv/clock.txt
+new file mode 100644
+index 0000000..c72d350
+--- /dev/null
++++ b/Documentation/frv/clock.txt
+@@ -0,0 +1,65 @@
++Clock scaling
++-------------
++
++The kernel supports scaling of CLCK.CMODE, CLCK.CM and CLKC.P0 clock
++registers. If built with CONFIG_PM and CONFIG_SYSCTL options enabled, four
++extra files will appear in the directory /proc/sys/pm/. Reading these files
++will show:
++
++      p0		-- current value of the P0 bit in CLKC register.
++      cm		-- current value of the CM bits in CLKC register.
++      cmode		-- current value of the CMODE bits in CLKC register.
++
++On all boards, the 'p0' file should also be writable, and either '1' or '0'
++can be rewritten, to set or clear the CLKC_P0 bit respectively, hence
++controlling whether the resource bus rate clock is halved.
++
++The 'cm' file should also be available on all boards. '0' can be written to it
++to shift the board into High-Speed mode (normal), and '1' can be written to
++shift the board into Medium-Speed mode. Selecting Low-Speed mode is not
++supported by this interface, even though some CPUs do support it.
++
++On the boards with FR405 CPU (i.e. CB60 and CB70), the 'cmode' file is also
++writable, allowing the CPU core speed (and other clock speeds) to be
++controlled from userspace.
++
++
++Determining current and possible settings
++-----------------------------------------
++
++The current state and the available masks can be found in /proc/cpuinfo. For
++example, on the CB70:
++
++	# cat /proc/cpuinfo
++	CPU-Series:     fr400
++	CPU-Core:       fr405, gr0-31, BE, CCCR
++	CPU:            mb93405
++	MMU:            Prot
++	FP-Media:       fr0-31, Media
++	System:         mb93091-cb70, mb93090-mb00
++	PM-Controls:    cmode=0xd31f, cm=0x3, p0=0x3, suspend=0x9
++	PM-Status:      cmode=3, cm=0, p0=0
++	Clock-In:       50.00 MHz
++	Clock-Core:     300.00 MHz
++	Clock-SDRAM:    100.00 MHz
++	Clock-CBus:     100.00 MHz
++	Clock-Res:      50.00 MHz
++	Clock-Ext:      50.00 MHz
++	Clock-DSU:      25.00 MHz
++	BogoMips:       300.00
++
++And on the PDK, the PM lines look like the following:
++
++	PM-Controls:    cm=0x3, p0=0x3, suspend=0x9
++	PM-Status:      cmode=9, cm=0, p0=0
++
++The PM-Controls line, if present, will indicate which /proc/sys/pm files can
++be set to what values. The specification values are bitmasks; so, for example,
++"suspend=0x9" indicates that 0 and 3 can be written validly to
++/proc/sys/pm/suspend.
++
++The PM-Controls line will only be present if CONFIG_PM is configured to Y.
++
++The PM-Status line indicates which clock controls are set to which value. If
++the file can be read, then the suspend value must be 0, and so that's not
++included.
+diff --git a/Documentation/frv/configuring.txt b/Documentation/frv/configuring.txt
+new file mode 100644
+index 0000000..36e76a2
+--- /dev/null
++++ b/Documentation/frv/configuring.txt
+@@ -0,0 +1,125 @@
++		   =======================================
++		   FUJITSU FR-V LINUX KERNEL CONFIGURATION
++		   =======================================
++
++=====================
++CONFIGURATION OPTIONS
++=====================
++
++The most important setting is in the "MMU support options" tab (the first
++presented in the configuration tools available):
++
++ (*) "Kernel Type"
++
++     This options allows selection of normal, MMU-requiring linux, and uClinux
++     (which doesn't require an MMU and doesn't have inter-process protection).
++
++There are a number of settings in the "Processor type and features" section of
++the kernel configuration that need to be considered.
++
++ (*) "CPU"
++
++     The register and instruction sets at the core of the processor. This can
++     only be set to "FR40x/45x/55x" at the moment - but this permits usage of
++     the kernel with MB93091 CB10, CB11, CB30, CB41, CB60, CB70 and CB451
++     CPU boards, and with the MB93093 PDK board.
++
++ (*) "System"
++
++     This option allows a choice of basic system. This governs the peripherals
++     that are expected to be available.
++
++ (*) "Motherboard"
++
++     This specifies the type of motherboard being used, and the peripherals
++     upon it. Currently only "MB93090-MB00" can be set here.
++
++ (*) "Default cache-write mode"
++
++     This controls the initial data cache write management mode. By default
++     Write-Through is selected, but Write-Back (Copy-Back) can also be
++     selected. This can be changed dynamically once the kernel is running (see
++     features.txt).
++
++There are some architecture specific configuration options in the "General
++Setup" section of the kernel configuration too:
++
++ (*) "Reserve memory uncached for (PCI) DMA"
++
++     This requests that a uClinux kernel set aside some memory in an uncached
++     window for the use as consistent DMA memory (mainly for PCI). At least a
++     megabyte will be allocated in this way, possibly more. Any memory so
++     reserved will not be available for normal allocations.
++
++ (*) "Kernel support for ELF-FDPIC binaries"
++
++     This enables the binary-format driver for the new FDPIC ELF binaries that
++     this platform normally uses. These binaries are totally relocatable -
++     their separate sections can relocated independently, allowing them to be
++     shared on uClinux where possible. This should normally be enabled.
++
++ (*) "Kernel image protection"
++
++     This makes the protection register governing access to the core kernel
++     image prohibit access by userspace programs. This option is available on
++     uClinux only.
++
++There are also a number of settings in the "Kernel Hacking" section of the
++kernel configuration especially for debugging a kernel on this
++architecture. See the "gdbstub.txt" file for information about those.
++
++
++======================
++DEFAULT CONFIGURATIONS
++======================
++
++The kernel sources include a number of example default configurations:
++
++ (*) defconfig-mb93091
++
++     Default configuration for the MB93091-VDK with both CPU board and
++     MB93090-MB00 motherboard running uClinux.
++
++
++ (*) defconfig-mb93091-fb
++
++     Default configuration for the MB93091-VDK with CPU board,
++     MB93090-MB00 motherboard, and DAV board running uClinux.
++     Includes framebuffer driver.
++
++
++ (*) defconfig-mb93093
++
++     Default configuration for the MB93093-PDK board running uClinux.
++
++
++ (*) defconfig-cb70-standalone
++
++     Default configuration for the MB93091-VDK with only CB70 CPU board
++     running uClinux. This will use the CB70's DM9000 for network access.
++
++
++ (*) defconfig-mmu
++
++     Default configuration for the MB93091-VDK with both CB451 CPU board and
++     MB93090-MB00 motherboard running MMU linux.
++
++ (*) defconfig-mmu-audio
++
++     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
++     board, and MB93090-MB00 motherboard running MMU linux. Includes
++     audio driver.
++
++ (*) defconfig-mmu-fb
++
++     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
++     board, and MB93090-MB00 motherboard running MMU linux. Includes
++     framebuffer driver.
++
++ (*) defconfig-mmu-standalone
++
++     Default configuration for the MB93091-VDK with only CB451 CPU board
++     running MMU linux.
++
++
++
+diff --git a/Documentation/frv/features.txt b/Documentation/frv/features.txt
+new file mode 100644
+index 0000000..fa20c0e
+--- /dev/null
++++ b/Documentation/frv/features.txt
+@@ -0,0 +1,310 @@
++			 ===========================
++			 FUJITSU FR-V LINUX FEATURES
++			 ===========================
++
++This kernel port has a number of features of which the user should be aware:
++
++ (*) Linux and uClinux
++
++     The FR-V architecture port supports both normal MMU linux and uClinux out
++     of the same sources.
++
++
++ (*) CPU support
++
++     Support for the FR401, FR403, FR405, FR451 and FR555 CPUs should work with
++     the same uClinux kernel configuration.
++
++     In normal (MMU) Linux mode, only the FR451 CPU will work as that is the
++     only one with a suitably featured CPU.
++
++     The kernel is written and compiled with the assumption that only the
++     bottom 32 GR registers and no FR registers will be used by the kernel
++     itself, however all extra userspace registers will be saved on context
++     switch. Note that since most CPUs can't support lazy switching, no attempt
++     is made to do lazy register saving where that would be possible (FR555
++     only currently).
++
++
++ (*) Board support
++
++     The board on which the kernel will run can be configured on the "Processor
++     type and features" configuration tab.
++
++     Set the System to "MB93093-PDK" to boot from the MB93093 (FR403) PDK.
++
++     Set the System to "MB93091-VDK" to boot from the CB11, CB30, CB41, CB60,
++     CB70 or CB451 VDK boards. Set the Motherboard setting to "MB93090-MB00" to
++     boot with the standard ATA90590B VDK motherboard, and set it to "None" to
++     boot without any motherboard.
++
++
++ (*) Binary Formats
++
++     The only userspace binary format supported is FDPIC ELF. Normal ELF, FLAT
++     and AOUT binaries are not supported for this architecture.
++
++     FDPIC ELF supports shared library and program interpreter facilities.
++
++
++ (*) Scheduler Speed
++
++     The kernel scheduler runs at 100Hz irrespective of the clock speed on this
++     architecture. This value is set in asm/param.h (see the HZ macro defined
++     there).
++
++
++ (*) Normal (MMU) Linux Memory Layout.
++
++     See mmu-layout.txt in this directory for a description of the normal linux
++     memory layout
++
++     See include/asm-frv/mem-layout.h for constants pertaining to the memory
++     layout.
++
++     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
++     controller configuration.
++
++
++ (*) uClinux Memory Layout
++
++     The memory layout used by the uClinux kernel is as follows:
++
++	0x00000000 - 0x00000FFF		Null pointer catch page
++	0x20000000 - 0x200FFFFF CS2#    [PDK] FPGA
++	0xC0000000 - 0xCFFFFFFF		SDRAM
++	0xC0000000			Base of Linux kernel image
++	0xE0000000 - 0xEFFFFFFF	CS2#	[VDK] SLBUS/PCI window
++	0xF0000000 - 0xF0FFFFFF	CS5#	MB93493 CSC area (DAV daughter board)
++	0xF1000000 - 0xF1FFFFFF	CS7#	[CB70/CB451] CPU-card PCMCIA port space
++	0xFC000000 - 0xFC0FFFFF	CS1#	[VDK] MB86943 config space
++	0xFC100000 - 0xFC1FFFFF	CS6#	[CB70/CB451] CPU-card DM9000 NIC space
++	0xFC100000 - 0xFC1FFFFF	CS6#	[PDK] AX88796 NIC space
++	0xFC200000 - 0xFC2FFFFF	CS3#	MB93493 CSR area (DAV daughter board)
++	0xFD000000 - 0xFDFFFFFF	CS4#	[CB70/CB451] CPU-card extra flash space
++	0xFE000000 - 0xFEFFFFFF		Internal CPU peripherals
++	0xFF000000 - 0xFF1FFFFF	CS0#	Flash 1
++	0xFF200000 - 0xFF3FFFFF	CS0#	Flash 2
++	0xFFC00000 - 0xFFC0001F	CS0#	[VDK] FPGA
++
++     The kernel reads the size of the SDRAM from the memory bus controller
++     registers by default.
++
++     The kernel initialisation code (1) adjusts the SDRAM base addresses to
++     move the SDRAM to desired address, (2) moves the kernel image down to the
++     bottom of SDRAM, (3) adjusts the bus controller registers to move I/O
++     windows, and (4) rearranges the protection registers to protect all of
++     this.
++
++     The reasons for doing this are: (1) the page at address 0 should be
++     inaccessible so that NULL pointer errors can be caught; and (2) the bottom
++     three quarters are left unoccupied so that an FR-V CPU with an MMU can use
++     it for virtual userspace mappings.
++
++     See include/asm-frv/mem-layout.h for constants pertaining to the memory
++     layout.
++
++     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
++     controller configuration.
++
++
++ (*) uClinux Memory Protection
++
++     A DAMPR register is used to cover the entire region used for I/O
++     (0xE0000000 - 0xFFFFFFFF). This permits the kernel to make uncached
++     accesses to this region. Userspace is not permitted to access it.
++
++     The DAMPR/IAMPR protection registers not in use for any other purpose are
++     tiled over the top of the SDRAM such that:
++
++	(1) The core kernel image is covered by as small a tile as possible
++            granting only the kernel access to the underlying data, whilst
++            making sure no SDRAM is actually made unavailable by this approach.
++
++	(2) All other tiles are arranged to permit userspace access to the rest
++            of the SDRAM.
++
++     Barring point (1), there is nothing to protect kernel data against
++     userspace damage - but this is uClinux.
++
++
++ (*) Exceptions and Fixups
++
++     Since the FR40x and FR55x CPUs that do not have full MMUs generate
++     imprecise data error exceptions, there are currently no automatic fixup
++     services available in uClinux. This includes misaligned memory access
++     fixups.
++
++     Userspace EFAULT errors can be trapped by issuing a MEMBAR instruction and
++     forcing the fault to happen there.
++
++     On the FR451, however, data exceptions are mostly precise, and so
++     exception fixup handling is implemented as normal.
++
++
++ (*) Userspace Breakpoints
++
++     The ptrace() system call supports the following userspace debugging
++     features:
++
++	(1) Hardware assisted single step.
++
++	(2) Breakpoint via the FR-V "BREAK" instruction.
++
++	(3) Breakpoint via the FR-V "TIRA GR0, #1" instruction.
++
++	(4) Syscall entry/exit trap.
++
++     Each of the above generates a SIGTRAP.
++
++
++ (*) On-Chip Serial Ports
++
++     The FR-V on-chip serial ports are made available as ttyS0 and ttyS1. Note
++     that if the GDB stub is compiled in, ttyS1 will not actually be available
++     as it will be being used for the GDB stub.
++
++     These ports can be made by:
++
++	mknod /dev/ttyS0 c 4 64
++	mknod /dev/ttyS1 c 4 65
++
++
++ (*) Maskable Interrupts
++
++     Level 15 (Non-maskable) interrupts are dealt with by the GDB stub if
++     present, and cause a panic if not. If the GDB stub is present, ttyS1's
++     interrupts are rated at level 15.
++
++     All other interrupts are distributed over the set of available priorities
++     so that no IRQs are shared where possible. The arch interrupt handling
++     routines attempt to disentangle the various sources available through the
++     CPU's own multiplexor, and those on off-CPU peripherals.
++
++
++ (*) Accessing PCI Devices
++
++     Where PCI is available, care must be taken when dealing with drivers that
++     access PCI devices. PCI devices present their data in little-endian form,
++     but the CPU sees it in big-endian form. The macros in asm/io.h try to get
++     this right, but may not under all circumstances...
++
++
++ (*) Ax88796 Ethernet Driver
++
++     The MB93093 PDK board has an Ax88796 ethernet chipset (an NE2000 clone). A
++     driver has been written to deal specifically with this. The driver
++     provides MII services for the card.
++
++     The driver can be configured by running make xconfig, and going to:
++
++	(*) Network device support
++	    - turn on "Network device support"
++	    (*) Ethernet (10 or 100Mbit)
++		- turn on "Ethernet (10 or 100Mbit)"
++		- turn on "AX88796 NE2000 compatible chipset"
++
++     The driver can be found in:
++
++	drivers/net/ax88796.c
++	include/asm/ax88796.h
++
++
++ (*) WorkRAM Driver
++
++     This driver provides a character device that permits access to the WorkRAM
++     that can be found on the FR451 CPU. Each page is accessible through a
++     separate minor number, thereby permitting each page to have its own
++     filesystem permissions set on the device file.
++
++     The device files should be:
++
++	mknod /dev/frv/workram0 c 240 0
++	mknod /dev/frv/workram1 c 240 1
++	mknod /dev/frv/workram2 c 240 2
++	...
++
++     The driver will not permit the opening of any device file that does not
++     correspond to at least a partial page of WorkRAM. So the first device file
++     is the only one available on the FR451. If any other CPU is detected, none
++     of the devices will be openable.
++
++     The devices can be accessed with read, write and llseek, and can also be
++     mmapped. If they're mmapped, they will only map at the appropriate
++     0x7e8nnnnn address on linux and at the 0xfe8nnnnn address on uClinux. If
++     MAP_FIXED is not specified, the appropriate address will be chosen anyway.
++
++     The mappings must be MAP_SHARED not MAP_PRIVATE, and must not be
++     PROT_EXEC. They must also start at file offset 0, and must not be longer
++     than one page in size.
++
++     This driver can be configured by running make xconfig, and going to:
++
++	(*) Character devices
++	    - turn on "Fujitsu FR-V CPU WorkRAM support"
++
++
++ (*) Dynamic data cache write mode changing
++
++     It is possible to view and to change the data cache's write mode through
++     the /proc/sys/frv/cache-mode file while the kernel is running. There are
++     two modes available:
++
++	NAME	MEANING
++	=====	==========================================
++	wthru	Data cache is in Write-Through mode
++	wback	Data cache is in Write-Back/Copy-Back mode
++
++     To read the cache mode:
++
++	# cat /proc/sys/frv/cache-mode
++	wthru
++
++     To change the cache mode:
++
++	# echo wback >/proc/sys/frv/cache-mode
++	# cat /proc/sys/frv/cache-mode
++	wback
++
++
++ (*) MMU Context IDs and Pinning
++
++     On MMU Linux the CPU supports the concept of a context ID in its MMU to
++     make it more efficient (TLB entries are labelled with a context ID to link
++     them to specific tasks).
++
++     Normally once a context ID is allocated, it will remain affixed to a task
++     or CLONE_VM'd group of tasks for as long as it exists. However, since the
++     kernel is capable of supporting more tasks than there are possible ID
++     numbers, the kernel will pass context IDs from one task to another if
++     there are insufficient available.
++
++     The context ID currently in use by a task can be viewed in /proc:
++
++	# grep CXNR /proc/1/status
++	CXNR: 1
++
++     Note that kernel threads do not have a userspace context, and so will not
++     show a CXNR entry in that file.
++
++     Under some circumstances, however, it is desirable to pin a context ID on
++     a process such that the kernel won't pass it on. This can be done by
++     writing the process ID of the target process to a special file:
++
++	# echo 17 >/proc/sys/frv/pin-cxnr
++
++     Reading from the file will then show the context ID pinned.
++
++	# cat /proc/sys/frv/pin-cxnr
++	4
++
++     The context ID will remain pinned as long as any process is using that
++     context, i.e.: when the all the subscribing processes have exited or
++     exec'd; or when an unpinning request happens:
++
++	# echo 0 >/proc/sys/frv/pin-cxnr
++
++     When there isn't a pinned context, the file shows -1:
++
++	# cat /proc/sys/frv/pin-cxnr
++	-1
+diff --git a/Documentation/frv/gdbinit b/Documentation/frv/gdbinit
+new file mode 100644
+index 0000000..51517b6
+--- /dev/null
++++ b/Documentation/frv/gdbinit
+@@ -0,0 +1,102 @@
++set remotebreak 1
++
++define _amr
++
++printf "AMRx           DAMR                    IAMR         \n"
++printf "====   =====================   =====================\n"
++printf "amr0 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x0].L,__debug_mmu.damr[0x0].P,__debug_mmu.iamr[0x0].L,__debug_mmu.iamr[0x0].P
++printf "amr1 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x1].L,__debug_mmu.damr[0x1].P,__debug_mmu.iamr[0x1].L,__debug_mmu.iamr[0x1].P
++printf "amr2 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x2].L,__debug_mmu.damr[0x2].P,__debug_mmu.iamr[0x2].L,__debug_mmu.iamr[0x2].P
++printf "amr3 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x3].L,__debug_mmu.damr[0x3].P,__debug_mmu.iamr[0x3].L,__debug_mmu.iamr[0x3].P
++printf "amr4 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x4].L,__debug_mmu.damr[0x4].P,__debug_mmu.iamr[0x4].L,__debug_mmu.iamr[0x4].P
++printf "amr5 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x5].L,__debug_mmu.damr[0x5].P,__debug_mmu.iamr[0x5].L,__debug_mmu.iamr[0x5].P
++printf "amr6 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x6].L,__debug_mmu.damr[0x6].P,__debug_mmu.iamr[0x6].L,__debug_mmu.iamr[0x6].P
++printf "amr7 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x7].L,__debug_mmu.damr[0x7].P,__debug_mmu.iamr[0x7].L,__debug_mmu.iamr[0x7].P
++
++printf "amr8 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x8].L,__debug_mmu.damr[0x8].P
++printf "amr9 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x9].L,__debug_mmu.damr[0x9].P
++printf "amr10: L:%08lx P:%08lx\n",__debug_mmu.damr[0xa].L,__debug_mmu.damr[0xa].P
++printf "amr11: L:%08lx P:%08lx\n",__debug_mmu.damr[0xb].L,__debug_mmu.damr[0xb].P
++
++end
++
++
++define _tlb
++printf "tlb[0x00]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x0].L,__debug_mmu.tlb[0x0].P,__debug_mmu.tlb[0x40+0x0].L,__debug_mmu.tlb[0x40+0x0].P
++printf "tlb[0x01]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1].L,__debug_mmu.tlb[0x1].P,__debug_mmu.tlb[0x40+0x1].L,__debug_mmu.tlb[0x40+0x1].P
++printf "tlb[0x02]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2].L,__debug_mmu.tlb[0x2].P,__debug_mmu.tlb[0x40+0x2].L,__debug_mmu.tlb[0x40+0x2].P
++printf "tlb[0x03]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3].L,__debug_mmu.tlb[0x3].P,__debug_mmu.tlb[0x40+0x3].L,__debug_mmu.tlb[0x40+0x3].P
++printf "tlb[0x04]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x4].L,__debug_mmu.tlb[0x4].P,__debug_mmu.tlb[0x40+0x4].L,__debug_mmu.tlb[0x40+0x4].P
++printf "tlb[0x05]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x5].L,__debug_mmu.tlb[0x5].P,__debug_mmu.tlb[0x40+0x5].L,__debug_mmu.tlb[0x40+0x5].P
++printf "tlb[0x06]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x6].L,__debug_mmu.tlb[0x6].P,__debug_mmu.tlb[0x40+0x6].L,__debug_mmu.tlb[0x40+0x6].P
++printf "tlb[0x07]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x7].L,__debug_mmu.tlb[0x7].P,__debug_mmu.tlb[0x40+0x7].L,__debug_mmu.tlb[0x40+0x7].P
++printf "tlb[0x08]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x8].L,__debug_mmu.tlb[0x8].P,__debug_mmu.tlb[0x40+0x8].L,__debug_mmu.tlb[0x40+0x8].P
++printf "tlb[0x09]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x9].L,__debug_mmu.tlb[0x9].P,__debug_mmu.tlb[0x40+0x9].L,__debug_mmu.tlb[0x40+0x9].P
++printf "tlb[0x0a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xa].L,__debug_mmu.tlb[0xa].P,__debug_mmu.tlb[0x40+0xa].L,__debug_mmu.tlb[0x40+0xa].P
++printf "tlb[0x0b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xb].L,__debug_mmu.tlb[0xb].P,__debug_mmu.tlb[0x40+0xb].L,__debug_mmu.tlb[0x40+0xb].P
++printf "tlb[0x0c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xc].L,__debug_mmu.tlb[0xc].P,__debug_mmu.tlb[0x40+0xc].L,__debug_mmu.tlb[0x40+0xc].P
++printf "tlb[0x0d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xd].L,__debug_mmu.tlb[0xd].P,__debug_mmu.tlb[0x40+0xd].L,__debug_mmu.tlb[0x40+0xd].P
++printf "tlb[0x0e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xe].L,__debug_mmu.tlb[0xe].P,__debug_mmu.tlb[0x40+0xe].L,__debug_mmu.tlb[0x40+0xe].P
++printf "tlb[0x0f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xf].L,__debug_mmu.tlb[0xf].P,__debug_mmu.tlb[0x40+0xf].L,__debug_mmu.tlb[0x40+0xf].P
++printf "tlb[0x10]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x10].L,__debug_mmu.tlb[0x10].P,__debug_mmu.tlb[0x40+0x10].L,__debug_mmu.tlb[0x40+0x10].P
++printf "tlb[0x11]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x11].L,__debug_mmu.tlb[0x11].P,__debug_mmu.tlb[0x40+0x11].L,__debug_mmu.tlb[0x40+0x11].P
++printf "tlb[0x12]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x12].L,__debug_mmu.tlb[0x12].P,__debug_mmu.tlb[0x40+0x12].L,__debug_mmu.tlb[0x40+0x12].P
++printf "tlb[0x13]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x13].L,__debug_mmu.tlb[0x13].P,__debug_mmu.tlb[0x40+0x13].L,__debug_mmu.tlb[0x40+0x13].P
++printf "tlb[0x14]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x14].L,__debug_mmu.tlb[0x14].P,__debug_mmu.tlb[0x40+0x14].L,__debug_mmu.tlb[0x40+0x14].P
++printf "tlb[0x15]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x15].L,__debug_mmu.tlb[0x15].P,__debug_mmu.tlb[0x40+0x15].L,__debug_mmu.tlb[0x40+0x15].P
++printf "tlb[0x16]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x16].L,__debug_mmu.tlb[0x16].P,__debug_mmu.tlb[0x40+0x16].L,__debug_mmu.tlb[0x40+0x16].P
++printf "tlb[0x17]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x17].L,__debug_mmu.tlb[0x17].P,__debug_mmu.tlb[0x40+0x17].L,__debug_mmu.tlb[0x40+0x17].P
++printf "tlb[0x18]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x18].L,__debug_mmu.tlb[0x18].P,__debug_mmu.tlb[0x40+0x18].L,__debug_mmu.tlb[0x40+0x18].P
++printf "tlb[0x19]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x19].L,__debug_mmu.tlb[0x19].P,__debug_mmu.tlb[0x40+0x19].L,__debug_mmu.tlb[0x40+0x19].P
++printf "tlb[0x1a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1a].L,__debug_mmu.tlb[0x1a].P,__debug_mmu.tlb[0x40+0x1a].L,__debug_mmu.tlb[0x40+0x1a].P
++printf "tlb[0x1b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1b].L,__debug_mmu.tlb[0x1b].P,__debug_mmu.tlb[0x40+0x1b].L,__debug_mmu.tlb[0x40+0x1b].P
++printf "tlb[0x1c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1c].L,__debug_mmu.tlb[0x1c].P,__debug_mmu.tlb[0x40+0x1c].L,__debug_mmu.tlb[0x40+0x1c].P
++printf "tlb[0x1d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1d].L,__debug_mmu.tlb[0x1d].P,__debug_mmu.tlb[0x40+0x1d].L,__debug_mmu.tlb[0x40+0x1d].P
++printf "tlb[0x1e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1e].L,__debug_mmu.tlb[0x1e].P,__debug_mmu.tlb[0x40+0x1e].L,__debug_mmu.tlb[0x40+0x1e].P
++printf "tlb[0x1f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1f].L,__debug_mmu.tlb[0x1f].P,__debug_mmu.tlb[0x40+0x1f].L,__debug_mmu.tlb[0x40+0x1f].P
++printf "tlb[0x20]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x20].L,__debug_mmu.tlb[0x20].P,__debug_mmu.tlb[0x40+0x20].L,__debug_mmu.tlb[0x40+0x20].P
++printf "tlb[0x21]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x21].L,__debug_mmu.tlb[0x21].P,__debug_mmu.tlb[0x40+0x21].L,__debug_mmu.tlb[0x40+0x21].P
++printf "tlb[0x22]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x22].L,__debug_mmu.tlb[0x22].P,__debug_mmu.tlb[0x40+0x22].L,__debug_mmu.tlb[0x40+0x22].P
++printf "tlb[0x23]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x23].L,__debug_mmu.tlb[0x23].P,__debug_mmu.tlb[0x40+0x23].L,__debug_mmu.tlb[0x40+0x23].P
++printf "tlb[0x24]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x24].L,__debug_mmu.tlb[0x24].P,__debug_mmu.tlb[0x40+0x24].L,__debug_mmu.tlb[0x40+0x24].P
++printf "tlb[0x25]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x25].L,__debug_mmu.tlb[0x25].P,__debug_mmu.tlb[0x40+0x25].L,__debug_mmu.tlb[0x40+0x25].P
++printf "tlb[0x26]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x26].L,__debug_mmu.tlb[0x26].P,__debug_mmu.tlb[0x40+0x26].L,__debug_mmu.tlb[0x40+0x26].P
++printf "tlb[0x27]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x27].L,__debug_mmu.tlb[0x27].P,__debug_mmu.tlb[0x40+0x27].L,__debug_mmu.tlb[0x40+0x27].P
++printf "tlb[0x28]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x28].L,__debug_mmu.tlb[0x28].P,__debug_mmu.tlb[0x40+0x28].L,__debug_mmu.tlb[0x40+0x28].P
++printf "tlb[0x29]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x29].L,__debug_mmu.tlb[0x29].P,__debug_mmu.tlb[0x40+0x29].L,__debug_mmu.tlb[0x40+0x29].P
++printf "tlb[0x2a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2a].L,__debug_mmu.tlb[0x2a].P,__debug_mmu.tlb[0x40+0x2a].L,__debug_mmu.tlb[0x40+0x2a].P
++printf "tlb[0x2b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2b].L,__debug_mmu.tlb[0x2b].P,__debug_mmu.tlb[0x40+0x2b].L,__debug_mmu.tlb[0x40+0x2b].P
++printf "tlb[0x2c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2c].L,__debug_mmu.tlb[0x2c].P,__debug_mmu.tlb[0x40+0x2c].L,__debug_mmu.tlb[0x40+0x2c].P
++printf "tlb[0x2d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2d].L,__debug_mmu.tlb[0x2d].P,__debug_mmu.tlb[0x40+0x2d].L,__debug_mmu.tlb[0x40+0x2d].P
++printf "tlb[0x2e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2e].L,__debug_mmu.tlb[0x2e].P,__debug_mmu.tlb[0x40+0x2e].L,__debug_mmu.tlb[0x40+0x2e].P
++printf "tlb[0x2f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2f].L,__debug_mmu.tlb[0x2f].P,__debug_mmu.tlb[0x40+0x2f].L,__debug_mmu.tlb[0x40+0x2f].P
++printf "tlb[0x30]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x30].L,__debug_mmu.tlb[0x30].P,__debug_mmu.tlb[0x40+0x30].L,__debug_mmu.tlb[0x40+0x30].P
++printf "tlb[0x31]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x31].L,__debug_mmu.tlb[0x31].P,__debug_mmu.tlb[0x40+0x31].L,__debug_mmu.tlb[0x40+0x31].P
++printf "tlb[0x32]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x32].L,__debug_mmu.tlb[0x32].P,__debug_mmu.tlb[0x40+0x32].L,__debug_mmu.tlb[0x40+0x32].P
++printf "tlb[0x33]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x33].L,__debug_mmu.tlb[0x33].P,__debug_mmu.tlb[0x40+0x33].L,__debug_mmu.tlb[0x40+0x33].P
++printf "tlb[0x34]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x34].L,__debug_mmu.tlb[0x34].P,__debug_mmu.tlb[0x40+0x34].L,__debug_mmu.tlb[0x40+0x34].P
++printf "tlb[0x35]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x35].L,__debug_mmu.tlb[0x35].P,__debug_mmu.tlb[0x40+0x35].L,__debug_mmu.tlb[0x40+0x35].P
++printf "tlb[0x36]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x36].L,__debug_mmu.tlb[0x36].P,__debug_mmu.tlb[0x40+0x36].L,__debug_mmu.tlb[0x40+0x36].P
++printf "tlb[0x37]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x37].L,__debug_mmu.tlb[0x37].P,__debug_mmu.tlb[0x40+0x37].L,__debug_mmu.tlb[0x40+0x37].P
++printf "tlb[0x38]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x38].L,__debug_mmu.tlb[0x38].P,__debug_mmu.tlb[0x40+0x38].L,__debug_mmu.tlb[0x40+0x38].P
++printf "tlb[0x39]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x39].L,__debug_mmu.tlb[0x39].P,__debug_mmu.tlb[0x40+0x39].L,__debug_mmu.tlb[0x40+0x39].P
++printf "tlb[0x3a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3a].L,__debug_mmu.tlb[0x3a].P,__debug_mmu.tlb[0x40+0x3a].L,__debug_mmu.tlb[0x40+0x3a].P
++printf "tlb[0x3b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3b].L,__debug_mmu.tlb[0x3b].P,__debug_mmu.tlb[0x40+0x3b].L,__debug_mmu.tlb[0x40+0x3b].P
++printf "tlb[0x3c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3c].L,__debug_mmu.tlb[0x3c].P,__debug_mmu.tlb[0x40+0x3c].L,__debug_mmu.tlb[0x40+0x3c].P
++printf "tlb[0x3d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3d].L,__debug_mmu.tlb[0x3d].P,__debug_mmu.tlb[0x40+0x3d].L,__debug_mmu.tlb[0x40+0x3d].P
++printf "tlb[0x3e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3e].L,__debug_mmu.tlb[0x3e].P,__debug_mmu.tlb[0x40+0x3e].L,__debug_mmu.tlb[0x40+0x3e].P
++printf "tlb[0x3f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3f].L,__debug_mmu.tlb[0x3f].P,__debug_mmu.tlb[0x40+0x3f].L,__debug_mmu.tlb[0x40+0x3f].P
++end
++
++
++define _pgd
++p (pgd_t[0x40])*(pgd_t*)(__debug_mmu.damr[0x3].L)
++end
++
++define _ptd_i
++p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x4].L)
++end
++
++define _ptd_d
++p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x5].L)
++end
+diff --git a/Documentation/frv/gdbstub.txt b/Documentation/frv/gdbstub.txt
+new file mode 100644
+index 0000000..b92bfd9
+--- /dev/null
++++ b/Documentation/frv/gdbstub.txt
+@@ -0,0 +1,130 @@
++			     ====================
++			     DEBUGGING FR-V LINUX
++			     ====================
++
++
++The kernel contains a GDB stub that talks GDB remote protocol across a serial
++port. This permits GDB to single step through the kernel, set breakpoints and
++trap exceptions that happen in kernel space and interrupt execution. It also
++permits the NMI interrupt button or serial port events to jump the kernel into
++the debugger.
++
++On the CPUs that have on-chip UARTs (FR400, FR403, FR405, FR555), the
++GDB stub hijacks a serial port for its own purposes, and makes it
++generate level 15 interrupts (NMI). The kernel proper cannot see the serial
++port in question under these conditions.
++
++On the MB93091-VDK CPU boards, the GDB stub uses UART1, which would otherwise
++be /dev/ttyS1. On the MB93093-PDK, the GDB stub uses UART0. Therefore, on the
++PDK there is no externally accessible serial port and the serial port to
++which the touch screen is attached becomes /dev/ttyS0.
++
++Note that the GDB stub runs entirely within CPU debug mode, and so should not
++incur any exceptions or interrupts whilst it is active. In particular, note
++that the clock will lose time since it is implemented in software.
++
++
++==================
++KERNEL PREPARATION
++==================
++
++Firstly, a debuggable kernel must be built. To do this, unpack the kernel tree
++and copy the configuration that you wish to use to .config. Then reconfigure
++the following things on the "Kernel Hacking" tab:
++
++  (*) "Include debugging information"
++
++      Set this to "Y". This causes all C and Assembly files to be compiled
++      to include debugging information.
++
++  (*) "In-kernel GDB stub"
++
++      Set this to "Y". This causes the GDB stub to be compiled into the
++      kernel.
++
++  (*) "Immediate activation"
++
++      Set this to "Y" if you want the GDB stub to activate as soon as possible
++      and wait for GDB to connect. This allows you to start tracing right from
++      the beginning of start_kernel() in init/main.c.
++
++  (*) "Console through GDB stub"
++
++      Set this to "Y" if you wish to be able to use "console=gdb0" on the
++      command line. That tells the kernel to pass system console messages to
++      GDB (which then prints them on its standard output). This is useful when
++      debugging the serial drivers that'd otherwise be used to pass console
++      messages to the outside world.
++
++Then build as usual, download to the board and execute. Note that if
++"Immediate activation" was selected, then the kernel will wait for GDB to
++attach. If not, then the kernel will boot immediately and GDB will have to
++interrupt it or wait for an exception to occur before doing anything with
++the kernel.
++
++
++=========================
++KERNEL DEBUGGING WITH GDB
++=========================
++
++Set the serial port on the computer that's going to run GDB to the appropriate
++baud rate. Assuming the board's debug port is connected to ttyS0/COM1 on the
++computer doing the debugging:
++
++	stty -F /dev/ttyS0 115200
++
++Then start GDB in the base of the kernel tree:
++
++	frv-uclinux-gdb linux		[uClinux]
++
++Or:
++
++	frv-uclinux-gdb vmlinux		[MMU linux]
++
++When the prompt appears:
++
++	GNU gdb frv-031024
++	Copyright 2003 Free Software Foundation, Inc.
++	GDB is free software, covered by the GNU General Public License, and you are
++	welcome to change it and/or distribute copies of it under certain conditions.
++	Type "show copying" to see the conditions.
++	There is absolutely no warranty for GDB.  Type "show warranty" for details.
++	This GDB was configured as "--host=i686-pc-linux-gnu --target=frv-uclinux"...
++	(gdb)
++
++Attach to the board like this:
++
++        (gdb) target remote /dev/ttyS0
++	Remote debugging using /dev/ttyS0
++	start_kernel () at init/main.c:395
++	(gdb)
++
++This should show the appropriate lines from the source too. The kernel can
++then be debugged almost as if it's any other program.
++
++
++===============================
++INTERRUPTING THE RUNNING KERNEL
++===============================
++
++The kernel can be interrupted whilst it is running, causing a jump back to the
++GDB stub and the debugger:
++
++  (*) Pressing Ctrl-C in GDB. This will cause GDB to try and interrupt the
++      kernel by sending an RS232 BREAK over the serial line to the GDB
++      stub. This will (mostly) immediately interrupt the kernel and return it
++      to the debugger.
++
++  (*) Pressing the NMI button on the board will also cause a jump into the
++      debugger.
++
++  (*) Setting a software breakpoint. This sets a break instruction at the
++      desired location which the GDB stub then traps the exception for.
++
++  (*) Setting a hardware breakpoint. The GDB stub is capable of using the IBAR
++      and DBAR registers to assist debugging.
++
++Furthermore, the GDB stub will intercept a number of exceptions automatically
++if they are caused by kernel execution. It will also intercept BUG() macro
++invocation.
++
+diff --git a/Documentation/frv/kernel-ABI.txt b/Documentation/frv/kernel-ABI.txt
+new file mode 100644
+index 0000000..aaa1cec
+--- /dev/null
++++ b/Documentation/frv/kernel-ABI.txt
+@@ -0,0 +1,262 @@
++			=================================
++			INTERNAL KERNEL ABI FOR FR-V ARCH
++			=================================
++
++The internal FRV kernel ABI is not quite the same as the userspace ABI. A
++number of the registers are used for special purposed, and the ABI is not
++consistent between modules vs core, and MMU vs no-MMU.
++
++This partly stems from the fact that FRV CPUs do not have a separate
++supervisor stack pointer, and most of them do not have any scratch
++registers, thus requiring at least one general purpose register to be
++clobbered in such an event. Also, within the kernel core, it is possible to
++simply jump or call directly between functions using a relative offset.
++This cannot be extended to modules for the displacement is likely to be too
++far. Thus in modules the address of a function to call must be calculated
++in a register and then used, requiring two extra instructions.
++
++This document has the following sections:
++
++ (*) System call register ABI
++ (*) CPU operating modes
++ (*) Internal kernel-mode register ABI
++ (*) Internal debug-mode register ABI
++ (*) Virtual interrupt handling
++
++
++========================
++SYSTEM CALL REGISTER ABI
++========================
++
++When a system call is made, the following registers are effective:
++
++	REGISTERS	CALL			RETURN
++	===============	=======================	=======================
++	GR7		System call number	Preserved
++	GR8		Syscall arg #1		Return value
++	GR9-GR13	Syscall arg #2-6	Preserved
++
++
++===================
++CPU OPERATING MODES
++===================
++
++The FR-V CPU has three basic operating modes. In order of increasing
++capability:
++
++  (1) User mode.
++
++      Basic userspace running mode.
++
++  (2) Kernel mode.
++
++      Normal kernel mode. There are many additional control registers
++      available that may be accessed in this mode, in addition to all the
++      stuff available to user mode. This has two submodes:
++
++      (a) Exceptions enabled (PSR.T == 1).
++
++	  Exceptions will invoke the appropriate normal kernel mode
++	  handler. On entry to the handler, the PSR.T bit will be cleared.
++
++      (b) Exceptions disabled (PSR.T == 0).
++
++	  No exceptions or interrupts may happen. Any mandatory exceptions
++	  will cause the CPU to halt unless the CPU is told to jump into
++	  debug mode instead.
++
++  (3) Debug mode.
++
++      No exceptions may happen in this mode. Memory protection and
++      management exceptions will be flagged for later consideration, but
++      the exception handler won't be invoked. Debugging traps such as
++      hardware breakpoints and watchpoints will be ignored. This mode is
++      entered only by debugging events obtained from the other two modes.
++
++      All kernel mode registers may be accessed, plus a few extra debugging
++      specific registers.
++
++
++=================================
++INTERNAL KERNEL-MODE REGISTER ABI
++=================================
++
++There are a number of permanent register assignments that are set up by
++entry.S in the exception prologue. Note that there is a complete set of
++exception prologues for each of user->kernel transition and kernel->kernel
++transition. There are also user->debug and kernel->debug mode transition
++prologues.
++
++
++	REGISTER	FLAVOUR	USE
++	===============	=======	==============================================
++	GR1			Supervisor stack pointer
++	GR15			Current thread info pointer
++	GR16			GP-Rel base register for small data
++	GR28			Current exception frame pointer (__frame)
++	GR29			Current task pointer (current)
++	GR30			Destroyed by kernel mode entry
++	GR31		NOMMU	Destroyed by debug mode entry
++	GR31		MMU	Destroyed by TLB miss kernel mode entry
++	CCR.ICC2		Virtual interrupt disablement tracking
++	CCCR.CC3		Cleared by exception prologue 
++				(atomic op emulation)
++	SCR0		MMU	See mmu-layout.txt.
++	SCR1		MMU	See mmu-layout.txt.
++	SCR2		MMU	Save for EAR0 (destroyed by icache insns 
++					       in debug mode)
++	SCR3		MMU	Save for GR31 during debug exceptions
++	DAMR/IAMR	NOMMU	Fixed memory protection layout.
++	DAMR/IAMR	MMU	See mmu-layout.txt.
++
++
++Certain registers are also used or modified across function calls:
++
++	REGISTER	CALL				RETURN
++	===============	===============================	======================
++	GR0		Fixed Zero			-
++	GR2		Function call frame pointer
++	GR3		Special				Preserved
++	GR3-GR7		-				Clobbered
++	GR8		Function call arg #1		Return value 
++							(or clobbered)
++	GR9		Function call arg #2		Return value MSW 
++							(or clobbered)
++	GR10-GR13	Function call arg #3-#6		Clobbered
++	GR14		-				Clobbered
++	GR15-GR16	Special				Preserved
++	GR17-GR27	-				Preserved
++	GR28-GR31	Special				Only accessed 
++							explicitly
++	LR		Return address after CALL	Clobbered
++	CCR/CCCR	-				Mostly Clobbered
++
++
++================================
++INTERNAL DEBUG-MODE REGISTER ABI
++================================
++
++This is the same as the kernel-mode register ABI for functions calls. The
++difference is that in debug-mode there's a different stack and a different
++exception frame. Almost all the global registers from kernel-mode
++(including the stack pointer) may be changed.
++
++	REGISTER	FLAVOUR	USE
++	===============	=======	==============================================
++	GR1			Debug stack pointer
++	GR16			GP-Rel base register for small data
++	GR31			Current debug exception frame pointer 
++				(__debug_frame)
++	SCR3		MMU	Saved value of GR31
++
++
++Note that debug mode is able to interfere with the kernel's emulated atomic
++ops, so it must be exceedingly careful not to do any that would interact
++with the main kernel in this regard. Hence the debug mode code (gdbstub) is
++almost completely self-contained. The only external code used is the
++sprintf family of functions.
++
++Furthermore, break.S is so complicated because single-step mode does not
++switch off on entry to an exception. That means unless manually disabled,
++single-stepping will blithely go on stepping into things like interrupts.
++See gdbstub.txt for more information.
++
++
++==========================
++VIRTUAL INTERRUPT HANDLING
++==========================
++
++Because accesses to the PSR is so slow, and to disable interrupts we have
++to access it twice (once to read and once to write), we don't actually
++disable interrupts at all if we don't have to. What we do instead is use
++the ICC2 condition code flags to note virtual disablement, such that if we
++then do take an interrupt, we note the flag, really disable interrupts, set
++another flag and resume execution at the point the interrupt happened.
++Setting condition flags as a side effect of an arithmetic or logical
++instruction is really fast. This use of the ICC2 only occurs within the
++kernel - it does not affect userspace.
++
++The flags we use are:
++
++ (*) CCR.ICC2.Z [Zero flag]
++
++     Set to virtually disable interrupts, clear when interrupts are
++     virtually enabled. Can be modified by logical instructions without
++     affecting the Carry flag.
++
++ (*) CCR.ICC2.C [Carry flag]
++
++     Clear to indicate hardware interrupts are really disabled, set otherwise.
++
++
++What happens is this:
++
++ (1) Normal kernel-mode operation.
++
++	ICC2.Z is 0, ICC2.C is 1.
++
++ (2) An interrupt occurs. The exception prologue examines ICC2.Z and
++     determines that nothing needs doing. This is done simply with an
++     unlikely BEQ instruction.
++
++ (3) The interrupts are disabled (local_irq_disable)
++
++	ICC2.Z is set to 1.
++
++ (4) If interrupts were then re-enabled (local_irq_enable):
++
++	ICC2.Z would be set to 0.
++
++     A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
++     be used to trap if interrupts were now virtually enabled, but
++     physically disabled - which they're not, so the trap isn't taken. The
++     kernel would then be back to state (1).
++
++ (5) An interrupt occurs. The exception prologue examines ICC2.Z and
++     determines that the interrupt shouldn't actually have happened. It
++     jumps aside, and there disabled interrupts by setting PSR.PIL to 14
++     and then it clears ICC2.C.
++
++ (6) If interrupts were then saved and disabled again (local_irq_save):
++
++	ICC2.Z would be shifted into the save variable and masked off 
++	(giving a 1).
++
++	ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
++	unaffected (ie: 0).
++
++ (7) If interrupts were then restored from state (6) (local_irq_restore):
++
++	ICC2.Z would be set to indicate the result of XOR'ing the saved
++	value (ie: 1) with 1, which gives a result of 0 - thus leaving
++	ICC2.Z set.
++
++	ICC2.C would remain unaffected (ie: 0).
++
++     A TIHI #2 instruction would be used to again assay the current state,
++     but this would do nothing as Z==1.
++
++ (8) If interrupts were then enabled (local_irq_enable):
++
++	ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
++	flags would now be 0.
++
++     A TIHI #2 instruction again issued to assay the current state would
++     then trap as both Z==0 [interrupts virtually enabled] and C==0
++     [interrupts really disabled] would then be true.
++
++ (9) The trap #2 handler would simply enable hardware interrupts 
++     (set PSR.PIL to 0), set ICC2.C to 1 and return.
++
++(10) Immediately upon returning, the pending interrupt would be taken.
++
++(11) The interrupt handler would take the path of actually processing the
++     interrupt (ICC2.Z is clear, BEQ fails as per step (2)).
++
++(12) The interrupt handler would then set ICC2.C to 1 since hardware
++     interrupts are definitely enabled - or else the kernel wouldn't be here.
++
++(13) On return from the interrupt handler, things would be back to state (1).
++
++This trap (#2) is only available in kernel mode. In user mode it will
++result in SIGILL.
+diff --git a/Documentation/frv/mmu-layout.txt b/Documentation/frv/mmu-layout.txt
+new file mode 100644
+index 0000000..db10250
+--- /dev/null
++++ b/Documentation/frv/mmu-layout.txt
+@@ -0,0 +1,306 @@
++				 =================================
++				 FR451 MMU LINUX MEMORY MANAGEMENT
++				 =================================
++
++============
++MMU HARDWARE
++============
++
++FR451 MMU Linux puts the MMU into EDAT mode whilst running. This means that it uses both the SAT
++registers and the DAT TLB to perform address translation.
++
++There are 8 IAMLR/IAMPR register pairs and 16 DAMLR/DAMPR register pairs for SAT mode.
++
++In DAT mode, there is also a TLB organised in cache format as 64 lines x 2 ways. Each line spans a
++16KB range of addresses, but can match a larger region.
++
++
++===========================
++MEMORY MANAGEMENT REGISTERS
++===========================
++
++Certain control registers are used by the kernel memory management routines:
++
++	REGISTERS		USAGE
++	======================	==================================================
++	IAMR0, DAMR0		Kernel image and data mappings
++	IAMR1, DAMR1		First-chance TLB lookup mapping
++	DAMR2			Page attachment for cache flush by page
++	DAMR3			Current PGD mapping
++	SCR0, DAMR4		Instruction TLB PGE/PTD cache
++	SCR1, DAMR5		Data TLB PGE/PTD cache
++	DAMR6-10		kmap_atomic() mappings
++	DAMR11			I/O mapping
++	CXNR			mm_struct context ID
++	TTBR			Page directory (PGD) pointer (physical address)
++
++
++=====================
++GENERAL MEMORY LAYOUT
++=====================
++
++The physical memory layout is as follows:
++
++  PHYSICAL ADDRESS	CONTROLLER	DEVICE
++  ===================	==============	=======================================
++  00000000 - BFFFFFFF	SDRAM		SDRAM area
++  E0000000 - EFFFFFFF	L-BUS CS2#	VDK SLBUS/PCI window
++  F0000000 - F0FFFFFF	L-BUS CS5#	MB93493 CSC area (DAV daughter board)
++  F1000000 - F1FFFFFF	L-BUS CS7#	(CB70 CPU-card PCMCIA port I/O space)
++  FC000000 - FC0FFFFF	L-BUS CS1#	VDK MB86943 config space
++  FC100000 - FC1FFFFF	L-BUS CS6#	DM9000 NIC I/O space
++  FC200000 - FC2FFFFF	L-BUS CS3#	MB93493 CSR area (DAV daughter board)
++  FD000000 - FDFFFFFF	L-BUS CS4#	(CB70 CPU-card extra flash space)
++  FE000000 - FEFFFFFF			Internal CPU peripherals
++  FF000000 - FF1FFFFF	L-BUS CS0#	Flash 1
++  FF200000 - FF3FFFFF	L-BUS CS0#	Flash 2
++  FFC00000 - FFC0001F	L-BUS CS0#	FPGA
++
++The virtual memory layout is:
++
++  VIRTUAL ADDRESS    PHYSICAL	TRANSLATOR	FLAGS	SIZE	OCCUPATION
++  =================  ========	==============	=======	=======	===================================
++  00004000-BFFFFFFF  various	TLB,xAMR1	D-N-??V	3GB	Userspace
++  C0000000-CFFFFFFF  00000000	xAMPR0		-L-S--V	256MB	Kernel image and data
++  D0000000-D7FFFFFF  various	TLB,xAMR1	D-NS??V	128MB	vmalloc area
++  D8000000-DBFFFFFF  various	TLB,xAMR1	D-NS??V	64MB	kmap() area
++  DC000000-DCFFFFFF  various	TLB			1MB	Secondary kmap_atomic() frame
++  DD000000-DD27FFFF  various	DAMR			160KB	Primary kmap_atomic() frame
++  DD040000			DAMR2/IAMR2	-L-S--V	page	Page cache flush attachment point
++  DD080000			DAMR3		-L-SC-V	page	Page Directory (PGD)
++  DD0C0000			DAMR4		-L-SC-V	page	Cached insn TLB Page Table lookup
++  DD100000			DAMR5		-L-SC-V	page	Cached data TLB Page Table lookup
++  DD140000			DAMR6		-L-S--V	page	kmap_atomic(KM_BOUNCE_READ)
++  DD180000			DAMR7		-L-S--V	page	kmap_atomic(KM_SKB_SUNRPC_DATA)
++  DD1C0000			DAMR8		-L-S--V	page	kmap_atomic(KM_SKB_DATA_SOFTIRQ)
++  DD200000			DAMR9		-L-S--V	page	kmap_atomic(KM_USER0)
++  DD240000			DAMR10		-L-S--V	page	kmap_atomic(KM_USER1)
++  E0000000-FFFFFFFF  E0000000	DAMR11		-L-SC-V	512MB	I/O region
++
++IAMPR1 and DAMPR1 are used as an extension to the TLB.
++
++
++====================
++KMAP AND KMAP_ATOMIC
++====================
++
++To access pages in the page cache (which may not be directly accessible if highmem is available),
++the kernel calls kmap(), does the access and then calls kunmap(); or it calls kmap_atomic(), does
++the access and then calls kunmap_atomic().
++
++kmap() creates an attachment between an arbitrary inaccessible page and a range of virtual
++addresses by installing a PTE in a special page table. The kernel can then access this page as it
++wills. When it's finished, the kernel calls kunmap() to clear the PTE.
++
++kmap_atomic() does something slightly different. In the interests of speed, it chooses one of two
++strategies:
++
++ (1) If possible, kmap_atomic() attaches the requested page to one of DAMPR5 through DAMPR10
++     register pairs; and the matching kunmap_atomic() clears the DAMPR. This makes high memory
++     support really fast as there's no need to flush the TLB or modify the page tables. The DAMLR
++     registers being used for this are preset during boot and don't change over the lifetime of the
++     process. There's a direct mapping between the first few kmap_atomic() types, DAMR number and
++     virtual address slot.
++
++     However, there are more kmap_atomic() types defined than there are DAMR registers available,
++     so we fall back to:
++
++ (2) kmap_atomic() uses a slot in the secondary frame (determined by the type parameter), and then
++     locks an entry in the TLB to translate that slot to the specified page. The number of slots is
++     obviously limited, and their positions are controlled such that each slot is matched by a
++     different line in the TLB. kunmap() ejects the entry from the TLB.
++
++Note that the first three kmap atomic types are really just declared as placeholders. The DAMPR
++registers involved are actually modified directly.
++
++Also note that kmap() itself may sleep, kmap_atomic() may never sleep and both always succeed;
++furthermore, a driver using kmap() may sleep before calling kunmap(), but may not sleep before
++calling kunmap_atomic() if it had previously called kmap_atomic().
++
++
++===============================
++USING MORE THAN 256MB OF MEMORY
++===============================
++
++The kernel cannot access more than 256MB of memory directly. The physical layout, however, permits
++up to 3GB of SDRAM (possibly 3.25GB) to be made available. By using CONFIG_HIGHMEM, the kernel can
++allow userspace (by way of page tables) and itself (by way of kmap) to deal with the memory
++allocation.
++
++External devices can, of course, still DMA to and from all of the SDRAM, even if the kernel can't
++see it directly. The kernel translates page references into real addresses for communicating to the
++devices.
++
++
++===================
++PAGE TABLE TOPOLOGY
++===================
++
++The page tables are arranged in 2-layer format. There is a middle layer (PMD) that would be used in
++3-layer format tables but that is folded into the top layer (PGD) and so consumes no extra memory
++or processing power.
++
++  +------+     PGD    PMD
++  | TTBR |--->+-------------------+
++  +------+    |      |      : STE |
++              | PGE0 | PME0 : STE |
++              |      |      : STE |
++              +-------------------+              Page Table
++              |      |      : STE -------------->+--------+ +0x0000
++              | PGE1 | PME0 : STE -----------+   | PTE0   |
++              |      |      : STE -------+   |   +--------+
++              +-------------------+      |   |   | PTE63  |
++              |      |      : STE |      |   +-->+--------+ +0x0100
++              | PGE2 | PME0 : STE |      |       | PTE64  |
++              |      |      : STE |      |       +--------+
++              +-------------------+      |       | PTE127 |
++              |      |      : STE |      +------>+--------+ +0x0200
++              | PGE3 | PME0 : STE |              | PTE128 |
++              |      |      : STE |              +--------+
++              +-------------------+              | PTE191 |
++                                                 +--------+ +0x0300
++
++Each Page Directory (PGD) is 16KB (page size) in size and is divided into 64 entries (PGEs). Each
++PGE contains one Page Mid Directory (PMD).
++
++Each PMD is 256 bytes in size and contains a single entry (PME). Each PME holds 64 FR451 MMU
++segment table entries of 4 bytes apiece. Each PME "points to" a page table. In practice, each STE
++points to a subset of the page table, the first to PT+0x0000, the second to PT+0x0100, the third to
++PT+0x200, and so on.
++
++Each PGE and PME covers 64MB of the total virtual address space.
++
++Each Page Table (PTD) is 16KB (page size) in size, and is divided into 4096 entries (PTEs). Each
++entry can point to one 16KB page. In practice, each Linux page table is subdivided into 64 FR451
++MMU page tables. But they are all grouped together to make management easier, in particular rmap
++support is then trivial.
++
++Grouping page tables in this fashion makes PGE caching in SCR0/SCR1 more efficient because the
++coverage of the cached item is greater.
++
++Page tables for the vmalloc area are allocated at boot time and shared between all mm_structs.
++
++
++=================
++USER SPACE LAYOUT
++=================
++
++For MMU capable Linux, the regions userspace code are allowed to access are kept entirely separate
++from those dedicated to the kernel:
++
++	VIRTUAL ADDRESS    SIZE   PURPOSE
++	=================  =====  ===================================
++	00000000-00003fff  4KB    NULL pointer access trap
++	00004000-01ffffff  ~32MB  lower mmap space (grows up)
++	02000000-021fffff  2MB    Stack space (grows down from top)
++	02200000-nnnnnnnn         Executable mapping
++        nnnnnnnn-                 brk space (grows up)
++	        -bfffffff         upper mmap space (grows down)
++
++This is so arranged so as to make best use of the 16KB page tables and the way in which PGEs/PMEs
++are cached by the TLB handler. The lower mmap space is filled first, and then the upper mmap space
++is filled.
++
++
++===============================
++GDB-STUB MMU DEBUGGING SERVICES
++===============================
++
++The gdb-stub included in this kernel provides a number of services to aid in the debugging of MMU
++related kernel services:
++
++ (*) Every time the kernel stops, certain state information is dumped into __debug_mmu. This
++     variable is defined in arch/frv/kernel/gdb-stub.c. Note that the gdbinit file in this
++     directory has some useful macros for dealing with this.
++
++     (*) __debug_mmu.tlb[]
++
++	 This receives the current TLB contents. This can be viewed with the _tlb GDB macro:
++
++		(gdb) _tlb
++		tlb[0x00]: 01000005 00718203  01000002 00718203
++		tlb[0x01]: 01004002 006d4201  01004005 006d4203
++		tlb[0x02]: 01008002 006d0201  01008006 00004200
++		tlb[0x03]: 0100c006 007f4202  0100c002 0064c202
++		tlb[0x04]: 01110005 00774201  01110002 00774201
++		tlb[0x05]: 01114005 00770201  01114002 00770201
++		tlb[0x06]: 01118002 0076c201  01118005 0076c201
++		...
++		tlb[0x3d]: 010f4002 00790200  001f4002 0054ca02
++		tlb[0x3e]: 010f8005 0078c201  010f8002 0078c201
++		tlb[0x3f]: 001fc002 0056ca01  001fc005 00538a01
++
++     (*) __debug_mmu.iamr[]
++     (*) __debug_mmu.damr[]
++
++	 These receive the current IAMR and DAMR contents. These can be viewed with the _amr
++	 GDB macro:
++
++		(gdb) _amr
++		AMRx           DAMR                    IAMR
++		====   =====================   =====================
++		amr0 : L:c0000000 P:00000cb9 : L:c0000000 P:000004b9
++		amr1 : L:01070005 P:006f9203 : L:0102c005 P:006a1201
++		amr2 : L:d8d00000 P:00000000 : L:d8d00000 P:00000000
++		amr3 : L:d8d04000 P:00534c0d : L:00000000 P:00000000
++		amr4 : L:d8d08000 P:00554c0d : L:00000000 P:00000000
++		amr5 : L:d8d0c000 P:00554c0d : L:00000000 P:00000000
++		amr6 : L:d8d10000 P:00000000 : L:00000000 P:00000000
++		amr7 : L:d8d14000 P:00000000 : L:00000000 P:00000000
++		amr8 : L:d8d18000 P:00000000
++		amr9 : L:d8d1c000 P:00000000
++		amr10: L:d8d20000 P:00000000
++		amr11: L:e0000000 P:e0000ccd
++
++ (*) The current task's page directory is bound to DAMR3.
++
++     This can be viewed with the _pgd GDB macro:
++
++	(gdb) _pgd
++	$3 = {{pge = {{ste = {0x554001, 0x554101, 0x554201, 0x554301, 0x554401,
++		  0x554501, 0x554601, 0x554701, 0x554801, 0x554901, 0x554a01,
++		  0x554b01, 0x554c01, 0x554d01, 0x554e01, 0x554f01, 0x555001,
++		  0x555101, 0x555201, 0x555301, 0x555401, 0x555501, 0x555601,
++		  0x555701, 0x555801, 0x555901, 0x555a01, 0x555b01, 0x555c01,
++		  0x555d01, 0x555e01, 0x555f01, 0x556001, 0x556101, 0x556201,
++		  0x556301, 0x556401, 0x556501, 0x556601, 0x556701, 0x556801,
++		  0x556901, 0x556a01, 0x556b01, 0x556c01, 0x556d01, 0x556e01,
++		  0x556f01, 0x557001, 0x557101, 0x557201, 0x557301, 0x557401,
++		  0x557501, 0x557601, 0x557701, 0x557801, 0x557901, 0x557a01,
++		  0x557b01, 0x557c01, 0x557d01, 0x557e01, 0x557f01}}}}, {pge = {{
++		ste = {0x0 <repeats 64 times>}}}} <repeats 51 times>, {pge = {{ste = {
++		  0x248001, 0x248101, 0x248201, 0x248301, 0x248401, 0x248501,
++		  0x248601, 0x248701, 0x248801, 0x248901, 0x248a01, 0x248b01,
++		  0x248c01, 0x248d01, 0x248e01, 0x248f01, 0x249001, 0x249101,
++		  0x249201, 0x249301, 0x249401, 0x249501, 0x249601, 0x249701,
++		  0x249801, 0x249901, 0x249a01, 0x249b01, 0x249c01, 0x249d01,
++		  0x249e01, 0x249f01, 0x24a001, 0x24a101, 0x24a201, 0x24a301,
++		  0x24a401, 0x24a501, 0x24a601, 0x24a701, 0x24a801, 0x24a901,
++		  0x24aa01, 0x24ab01, 0x24ac01, 0x24ad01, 0x24ae01, 0x24af01,
++		  0x24b001, 0x24b101, 0x24b201, 0x24b301, 0x24b401, 0x24b501,
++		  0x24b601, 0x24b701, 0x24b801, 0x24b901, 0x24ba01, 0x24bb01,
++		  0x24bc01, 0x24bd01, 0x24be01, 0x24bf01}}}}, {pge = {{ste = {
++		  0x0 <repeats 64 times>}}}} <repeats 11 times>}
++
++ (*) The PTD last used by the instruction TLB miss handler is attached to DAMR4.
++ (*) The PTD last used by the data TLB miss handler is attached to DAMR5.
++
++     These can be viewed with the _ptd_i and _ptd_d GDB macros:
++
++	(gdb) _ptd_d
++	$5 = {{pte = 0x0} <repeats 127 times>, {pte = 0x539b01}, {
++	    pte = 0x0} <repeats 896 times>, {pte = 0x719303}, {pte = 0x6d5303}, {
++	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
++	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x6a1303}, {
++	    pte = 0x0} <repeats 12 times>, {pte = 0x709303}, {pte = 0x0}, {pte = 0x0},
++	  {pte = 0x6fd303}, {pte = 0x6f9303}, {pte = 0x6f5303}, {pte = 0x0}, {
++	    pte = 0x6ed303}, {pte = 0x531b01}, {pte = 0x50db01}, {
++	    pte = 0x0} <repeats 13 times>, {pte = 0x5303}, {pte = 0x7f5303}, {
++	    pte = 0x509b01}, {pte = 0x505b01}, {pte = 0x7c9303}, {pte = 0x7b9303}, {
++	    pte = 0x7b5303}, {pte = 0x7b1303}, {pte = 0x7ad303}, {pte = 0x0}, {
++	    pte = 0x0}, {pte = 0x7a1303}, {pte = 0x0}, {pte = 0x795303}, {pte = 0x0}, {
++	    pte = 0x78d303}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
++	    pte = 0x0}, {pte = 0x775303}, {pte = 0x771303}, {pte = 0x76d303}, {
++	    pte = 0x0}, {pte = 0x765303}, {pte = 0x7c5303}, {pte = 0x501b01}, {
++	    pte = 0x4f1b01}, {pte = 0x4edb01}, {pte = 0x0}, {pte = 0x4f9b01}, {
++	    pte = 0x4fdb01}, {pte = 0x0} <repeats 2992 times>}
+diff --git a/Documentation/fujitsu/frv/README.txt b/Documentation/fujitsu/frv/README.txt
+deleted file mode 100644
+index a984faa..0000000
+--- a/Documentation/fujitsu/frv/README.txt
++++ /dev/null
+@@ -1,51 +0,0 @@
+-		       ================================
+-		       Fujitsu FR-V LINUX DOCUMENTATION
+-		       ================================
+-
+-This directory contains documentation for the Fujitsu FR-V CPU architecture
+-port of Linux.
+-
+-The following documents are available:
+-
+- (*) features.txt
+-
+-     A description of the basic features inherent in this architecture port.
+-
+-
+- (*) configuring.txt
+-
+-     A summary of the configuration options particular to this architecture.
+-
+-
+- (*) booting.txt
+-
+-     A description of how to boot the kernel image and a summary of the kernel
+-     command line options.
+-
+-
+- (*) gdbstub.txt
+-
+-     A description of how to debug the kernel using GDB attached by serial
+-     port, and a summary of the services available.
+-
+-
+- (*) mmu-layout.txt
+-
+-     A description of the virtual and physical memory layout used in the
+-     MMU linux kernel, and the registers used to support it.
+-
+-
+- (*) gdbinit
+-
+-     An example .gdbinit file for use with GDB. It includes macros for viewing
+-     MMU state on the FR451. See mmu-layout.txt for more information.
+-
+-
+- (*) clock.txt
+-
+-     A description of the CPU clock scaling interface.
+-
+-
+- (*) atomic-ops.txt
+-
+-     A description of how the FR-V kernel's atomic operations work.
+diff --git a/Documentation/fujitsu/frv/atomic-ops.txt b/Documentation/fujitsu/frv/atomic-ops.txt
+deleted file mode 100644
+index 96638e9..0000000
+--- a/Documentation/fujitsu/frv/atomic-ops.txt
++++ /dev/null
+@@ -1,134 +0,0 @@
+-			       =====================================
+-			       FUJITSU FR-V KERNEL ATOMIC OPERATIONS
+-			       =====================================
+-
+-On the FR-V CPUs, there is only one atomic Read-Modify-Write operation: the SWAP/SWAPI
+-instruction. Unfortunately, this alone can't be used to implement the following operations:
+-
+- (*) Atomic add to memory
+-
+- (*) Atomic subtract from memory
+-
+- (*) Atomic bit modification (set, clear or invert)
+-
+- (*) Atomic compare and exchange
+-
+-On such CPUs, the standard way of emulating such operations in uniprocessor mode is to disable
+-interrupts, but on the FR-V CPUs, modifying the PSR takes a lot of clock cycles, and it has to be
+-done twice. This means the CPU runs for a relatively long time with interrupts disabled,
+-potentially having a great effect on interrupt latency.
+-
+-
+-=============
+-NEW ALGORITHM
+-=============
+-
+-To get around this, the following algorithm has been implemented. It operates in a way similar to
+-the LL/SC instruction pairs supported on a number of platforms.
+-
+- (*) The CCCR.CC3 register is reserved within the kernel to act as an atomic modify abort flag.
+-
+- (*) In the exception prologues run on kernel->kernel entry, CCCR.CC3 is set to 0 (Undefined
+-     state).
+-
+- (*) All atomic operations can then be broken down into the following algorithm:
+-
+-     (1) Set ICC3.Z to true and set CC3 to True (ORCC/CKEQ/ORCR).
+-
+-     (2) Load the value currently in the memory to be modified into a register.
+-
+-     (3) Make changes to the value.
+-
+-     (4) If CC3 is still True, simultaneously and atomically (by VLIW packing):
+-
+-	 (a) Store the modified value back to memory.
+-
+-	 (b) Set ICC3.Z to false (CORCC on GR29 is sufficient for this - GR29 holds the current
+-	     task pointer in the kernel, and so is guaranteed to be non-zero).
+-
+-     (5) If ICC3.Z is still true, go back to step (1).
+-
+-This works in a non-SMP environment because any interrupt or other exception that happens between
+-steps (1) and (4) will set CC3 to the Undefined, thus aborting the store in (4a), and causing the
+-condition in ICC3 to remain with the Z flag set, thus causing step (5) to loop back to step (1).
+-
+-
+-This algorithm suffers from two problems:
+-
+- (1) The condition CCCR.CC3 is cleared unconditionally by an exception, irrespective of whether or
+-     not any changes were made to the target memory location during that exception.
+-
+- (2) The branch from step (5) back to step (1) may have to happen more than once until the store
+-     manages to take place. In theory, this loop could cycle forever because there are too many
+-     interrupts coming in, but it's unlikely.
+-
+-
+-=======
+-EXAMPLE
+-=======
+-
+-Taking an example from include/asm-frv/atomic.h:
+-
+-	static inline int atomic_add_return(int i, atomic_t *v)
+-	{
+-		unsigned long val;
+-
+-		asm("0:						\n"
+-
+-It starts by setting ICC3.Z to true for later use, and also transforming that into CC3 being in the
+-True state.
+-
+-		    "	orcc		gr0,gr0,gr0,icc3	\n"	<-- (1)
+-		    "	ckeq		icc3,cc7		\n"	<-- (1)
+-
+-Then it does the load. Note that the final phase of step (1) is done at the same time as the
+-load. The VLIW packing ensures they are done simultaneously. The ".p" on the load must not be
+-removed without swapping the order of these two instructions.
+-
+-		    "	ld.p		%M0,%1			\n"	<-- (2)
+-		    "	orcr		cc7,cc7,cc3		\n"	<-- (1)
+-
+-Then the proposed modification is generated. Note that the old value can be retained if required
+-(such as in test_and_set_bit()).
+-
+-		    "	add%I2		%1,%2,%1		\n"	<-- (3)
+-
+-Then it attempts to store the value back, contingent on no exception having cleared CC3 since it
+-was set to True.
+-
+-		    "	cst.p		%1,%M0		,cc3,#1	\n"	<-- (4a)
+-
+-It simultaneously records the success or failure of the store in ICC3.Z.
+-
+-		    "	corcc		gr29,gr29,gr0	,cc3,#1	\n"	<-- (4b)
+-
+-Such that the branch can then be taken if the operation was aborted.
+-
+-		    "	beq		icc3,#0,0b		\n"	<-- (5)
+-		    : "+U"(v->counter), "=&r"(val)
+-		    : "NPr"(i)
+-		    : "memory", "cc7", "cc3", "icc3"
+-		    );
+-
+-		return val;
+-	}
+-
+-
+-=============
+-CONFIGURATION
+-=============
+-
+-The atomic ops implementation can be made inline or out-of-line by changing the
+-CONFIG_FRV_OUTOFLINE_ATOMIC_OPS configuration variable. Making it out-of-line has a number of
+-advantages:
+-
+- - The resulting kernel image may be smaller
+- - Debugging is easier as atomic ops can just be stepped over and they can be breakpointed
+-
+-Keeping it inline also has a number of advantages:
+-
+- - The resulting kernel may be Faster
+-   - no out-of-line function calls need to be made
+-   - the compiler doesn't have half its registers clobbered by making a call
+-
+-The out-of-line implementations live in arch/frv/lib/atomic-ops.S.
+diff --git a/Documentation/fujitsu/frv/booting.txt b/Documentation/fujitsu/frv/booting.txt
+deleted file mode 100644
+index 4e22905..0000000
+--- a/Documentation/fujitsu/frv/booting.txt
++++ /dev/null
+@@ -1,181 +0,0 @@
+-			  =========================
+-			  BOOTING FR-V LINUX KERNEL
+-			  =========================
+-
+-======================
+-PROVIDING A FILESYSTEM
+-======================
+-
+-First of all, a root filesystem must be made available. This can be done in
+-one of two ways:
+-
+-  (1) NFS Export
+-
+-      A filesystem should be constructed in a directory on an NFS server that
+-      the target board can reach. This directory should then be NFS exported
+-      such that the target board can read and write into it as root.
+-
+-  (2) Flash Filesystem (JFFS2 Recommended)
+-
+-      In this case, the image must be stored or built up on flash before it
+-      can be used. A complete image can be built using the mkfs.jffs2 or
+-      similar program and then downloaded and stored into flash by RedBoot.
+-
+-
+-========================
+-LOADING THE KERNEL IMAGE
+-========================
+-
+-The kernel will need to be loaded into RAM by RedBoot (or by some alternative
+-boot loader) before it can be run. The kernel image (arch/frv/boot/Image) may
+-be loaded in one of three ways:
+-
+-  (1) Load from Flash
+-
+-      This is the simplest. RedBoot can store an image in the flash (see the
+-      RedBoot documentation) and then load it back into RAM. RedBoot keeps
+-      track of the load address, entry point and size, so the command to do
+-      this is simply:
+-
+-	fis load linux
+-
+-      The image is then ready to be executed.
+-
+-  (2) Load by TFTP
+-
+-      The following command will download a raw binary kernel image from the
+-      default server (as negotiated by BOOTP) and store it into RAM:
+-
+-	load -b 0x00100000 -r /tftpboot/image.bin
+-
+-      The image is then ready to be executed.
+-
+-  (3) Load by Y-Modem
+-
+-      The following command will download a raw binary kernel image across the
+-      serial port that RedBoot is currently using:
+-
+-	load -m ymodem -b 0x00100000 -r zImage
+-
+-      The serial client (such as minicom) must then be told to transmit the
+-      program by Y-Modem.
+-
+-      When finished, the image will then be ready to be executed.
+-
+-
+-==================
+-BOOTING THE KERNEL
+-==================
+-
+-Boot the image with the following RedBoot command:
+-
+-	exec -c "<CMDLINE>" 0x00100000
+-
+-For example:
+-
+-	exec -c "console=ttySM0,115200 ip=:::::dhcp root=/dev/mtdblock2 rw"
+-
+-This will start the kernel running. Note that if the GDB-stub is compiled in,
+-then the kernel will immediately wait for GDB to connect over serial before
+-doing anything else. See the section on kernel debugging with GDB.
+-
+-The kernel command line <CMDLINE> tells the kernel where its console is and
+-how to find its root filesystem. This is made up of the following components,
+-separated by spaces:
+-
+-  (*) console=ttyS<x>[,<baud>[<parity>[<bits>[<flow>]]]]
+-
+-      This specifies that the system console should output through on-chip
+-      serial port <x> (which can be "0" or "1").
+-
+-      <baud> is a standard baud rate between 1200 and 115200 (default 9600).
+-
+-      <parity> is a parity setting of "N", "O", "E", "M" or "S" for None, Odd,
+-      Even, Mark or Space. "None" is the default.
+-
+-      <stop> is "7" or "8" for the number of bits per character. "8" is the
+-      default.
+-
+-      <flow> is "r" to use flow control (XCTS on serial port 2 only). The
+-      default is to not use flow control.
+-
+-      For example:
+-
+-	console=ttyS0,115200
+-
+-      To use the first on-chip serial port at baud rate 115200, no parity, 8
+-      bits, and no flow control.
+-
+-  (*) root=/dev/<xxxx>
+-
+-      This specifies the device upon which the root filesystem resides. For
+-      example:
+-
+-	/dev/nfs	NFS root filesystem
+-	/dev/mtdblock3	Fourth RedBoot partition on the System Flash
+-
+-  (*) rw
+-
+-      Start with the root filesystem mounted Read/Write.
+-
+-  The remaining components are all optional:
+-
+-  (*) ip=<ip>::::<host>:<iface>:<cfg>
+-
+-      Configure the network interface. If <cfg> is "off" then <ip> should
+-      specify the IP address for the network device <iface>. <host> provide
+-      the hostname for the device.
+-
+-      If <cfg> is "bootp" or "dhcp", then all of these parameters will be
+-      discovered by consulting a BOOTP or DHCP server.
+-
+-      For example, the following might be used:
+-
+-	ip=192.168.73.12::::frv:eth0:off
+-
+-      This sets the IP address on the VDK motherboard RTL8029 ethernet chipset
+-      (eth0) to be 192.168.73.12, and sets the board's hostname to be "frv".
+-
+-  (*) nfsroot=<server>:<dir>[,v<vers>]
+-
+-      This is mandatory if "root=/dev/nfs" is given as an option. It tells the
+-      kernel the IP address of the NFS server providing its root filesystem,
+-      and the pathname on that server of the filesystem.
+-
+-      The NFS version to use can also be specified. v2 and v3 are supported by
+-      Linux.
+-
+-      For example:
+-
+-	nfsroot=192.168.73.1:/nfsroot-frv
+-
+-  (*) profile=1
+-
+-      Turns on the kernel profiler (accessible through /proc/profile).
+-
+-  (*) console=gdb0
+-
+-      This can be used as an alternative to the "console=ttyS..." listed
+-      above. I tells the kernel to pass the console output to GDB if the
+-      gdbstub is compiled in to the kernel.
+-
+-      If this is used, then the gdbstub passes the text to GDB, which then
+-      simply dumps it to its standard output.
+-
+-  (*) mem=<xxx>M
+-
+-      Normally the kernel will work out how much SDRAM it has by reading the
+-      SDRAM controller registers. That can be overridden with this
+-      option. This allows the kernel to be told that it has <xxx> megabytes of
+-      memory available.
+-
+-  (*) init=<prog> [<arg> [<arg> [<arg> ...]]]
+-
+-      This tells the kernel what program to run initially. By default this is
+-      /sbin/init, but /sbin/sash or /bin/sh are common alternatives.
+-
+-  (*) vdc=...
+-
+-      This option configures the MB93493 companion chip visual display
+-      driver. Please see Documentation/fujitsu/mb93493/vdc.txt for more
+-      information.
+diff --git a/Documentation/fujitsu/frv/clock.txt b/Documentation/fujitsu/frv/clock.txt
+deleted file mode 100644
+index c72d350..0000000
+--- a/Documentation/fujitsu/frv/clock.txt
++++ /dev/null
+@@ -1,65 +0,0 @@
+-Clock scaling
+--------------
+-
+-The kernel supports scaling of CLCK.CMODE, CLCK.CM and CLKC.P0 clock
+-registers. If built with CONFIG_PM and CONFIG_SYSCTL options enabled, four
+-extra files will appear in the directory /proc/sys/pm/. Reading these files
+-will show:
+-
+-      p0		-- current value of the P0 bit in CLKC register.
+-      cm		-- current value of the CM bits in CLKC register.
+-      cmode		-- current value of the CMODE bits in CLKC register.
+-
+-On all boards, the 'p0' file should also be writable, and either '1' or '0'
+-can be rewritten, to set or clear the CLKC_P0 bit respectively, hence
+-controlling whether the resource bus rate clock is halved.
+-
+-The 'cm' file should also be available on all boards. '0' can be written to it
+-to shift the board into High-Speed mode (normal), and '1' can be written to
+-shift the board into Medium-Speed mode. Selecting Low-Speed mode is not
+-supported by this interface, even though some CPUs do support it.
+-
+-On the boards with FR405 CPU (i.e. CB60 and CB70), the 'cmode' file is also
+-writable, allowing the CPU core speed (and other clock speeds) to be
+-controlled from userspace.
+-
+-
+-Determining current and possible settings
+------------------------------------------
+-
+-The current state and the available masks can be found in /proc/cpuinfo. For
+-example, on the CB70:
+-
+-	# cat /proc/cpuinfo
+-	CPU-Series:     fr400
+-	CPU-Core:       fr405, gr0-31, BE, CCCR
+-	CPU:            mb93405
+-	MMU:            Prot
+-	FP-Media:       fr0-31, Media
+-	System:         mb93091-cb70, mb93090-mb00
+-	PM-Controls:    cmode=0xd31f, cm=0x3, p0=0x3, suspend=0x9
+-	PM-Status:      cmode=3, cm=0, p0=0
+-	Clock-In:       50.00 MHz
+-	Clock-Core:     300.00 MHz
+-	Clock-SDRAM:    100.00 MHz
+-	Clock-CBus:     100.00 MHz
+-	Clock-Res:      50.00 MHz
+-	Clock-Ext:      50.00 MHz
+-	Clock-DSU:      25.00 MHz
+-	BogoMips:       300.00
+-
+-And on the PDK, the PM lines look like the following:
+-
+-	PM-Controls:    cm=0x3, p0=0x3, suspend=0x9
+-	PM-Status:      cmode=9, cm=0, p0=0
+-
+-The PM-Controls line, if present, will indicate which /proc/sys/pm files can
+-be set to what values. The specification values are bitmasks; so, for example,
+-"suspend=0x9" indicates that 0 and 3 can be written validly to
+-/proc/sys/pm/suspend.
+-
+-The PM-Controls line will only be present if CONFIG_PM is configured to Y.
+-
+-The PM-Status line indicates which clock controls are set to which value. If
+-the file can be read, then the suspend value must be 0, and so that's not
+-included.
+diff --git a/Documentation/fujitsu/frv/configuring.txt b/Documentation/fujitsu/frv/configuring.txt
+deleted file mode 100644
+index 36e76a2..0000000
+--- a/Documentation/fujitsu/frv/configuring.txt
++++ /dev/null
+@@ -1,125 +0,0 @@
+-		   =======================================
+-		   FUJITSU FR-V LINUX KERNEL CONFIGURATION
+-		   =======================================
+-
+-=====================
+-CONFIGURATION OPTIONS
+-=====================
+-
+-The most important setting is in the "MMU support options" tab (the first
+-presented in the configuration tools available):
+-
+- (*) "Kernel Type"
+-
+-     This options allows selection of normal, MMU-requiring linux, and uClinux
+-     (which doesn't require an MMU and doesn't have inter-process protection).
+-
+-There are a number of settings in the "Processor type and features" section of
+-the kernel configuration that need to be considered.
+-
+- (*) "CPU"
+-
+-     The register and instruction sets at the core of the processor. This can
+-     only be set to "FR40x/45x/55x" at the moment - but this permits usage of
+-     the kernel with MB93091 CB10, CB11, CB30, CB41, CB60, CB70 and CB451
+-     CPU boards, and with the MB93093 PDK board.
+-
+- (*) "System"
+-
+-     This option allows a choice of basic system. This governs the peripherals
+-     that are expected to be available.
+-
+- (*) "Motherboard"
+-
+-     This specifies the type of motherboard being used, and the peripherals
+-     upon it. Currently only "MB93090-MB00" can be set here.
+-
+- (*) "Default cache-write mode"
+-
+-     This controls the initial data cache write management mode. By default
+-     Write-Through is selected, but Write-Back (Copy-Back) can also be
+-     selected. This can be changed dynamically once the kernel is running (see
+-     features.txt).
+-
+-There are some architecture specific configuration options in the "General
+-Setup" section of the kernel configuration too:
+-
+- (*) "Reserve memory uncached for (PCI) DMA"
+-
+-     This requests that a uClinux kernel set aside some memory in an uncached
+-     window for the use as consistent DMA memory (mainly for PCI). At least a
+-     megabyte will be allocated in this way, possibly more. Any memory so
+-     reserved will not be available for normal allocations.
+-
+- (*) "Kernel support for ELF-FDPIC binaries"
+-
+-     This enables the binary-format driver for the new FDPIC ELF binaries that
+-     this platform normally uses. These binaries are totally relocatable -
+-     their separate sections can relocated independently, allowing them to be
+-     shared on uClinux where possible. This should normally be enabled.
+-
+- (*) "Kernel image protection"
+-
+-     This makes the protection register governing access to the core kernel
+-     image prohibit access by userspace programs. This option is available on
+-     uClinux only.
+-
+-There are also a number of settings in the "Kernel Hacking" section of the
+-kernel configuration especially for debugging a kernel on this
+-architecture. See the "gdbstub.txt" file for information about those.
+-
+-
+-======================
+-DEFAULT CONFIGURATIONS
+-======================
+-
+-The kernel sources include a number of example default configurations:
+-
+- (*) defconfig-mb93091
+-
+-     Default configuration for the MB93091-VDK with both CPU board and
+-     MB93090-MB00 motherboard running uClinux.
+-
+-
+- (*) defconfig-mb93091-fb
+-
+-     Default configuration for the MB93091-VDK with CPU board,
+-     MB93090-MB00 motherboard, and DAV board running uClinux.
+-     Includes framebuffer driver.
+-
+-
+- (*) defconfig-mb93093
+-
+-     Default configuration for the MB93093-PDK board running uClinux.
+-
+-
+- (*) defconfig-cb70-standalone
+-
+-     Default configuration for the MB93091-VDK with only CB70 CPU board
+-     running uClinux. This will use the CB70's DM9000 for network access.
+-
+-
+- (*) defconfig-mmu
+-
+-     Default configuration for the MB93091-VDK with both CB451 CPU board and
+-     MB93090-MB00 motherboard running MMU linux.
+-
+- (*) defconfig-mmu-audio
+-
+-     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
+-     board, and MB93090-MB00 motherboard running MMU linux. Includes
+-     audio driver.
+-
+- (*) defconfig-mmu-fb
+-
+-     Default configuration for the MB93091-VDK with CB451 CPU board, DAV
+-     board, and MB93090-MB00 motherboard running MMU linux. Includes
+-     framebuffer driver.
+-
+- (*) defconfig-mmu-standalone
+-
+-     Default configuration for the MB93091-VDK with only CB451 CPU board
+-     running MMU linux.
+-
+-
+-
+diff --git a/Documentation/fujitsu/frv/features.txt b/Documentation/fujitsu/frv/features.txt
+deleted file mode 100644
+index fa20c0e..0000000
+--- a/Documentation/fujitsu/frv/features.txt
++++ /dev/null
+@@ -1,310 +0,0 @@
+-			 ===========================
+-			 FUJITSU FR-V LINUX FEATURES
+-			 ===========================
+-
+-This kernel port has a number of features of which the user should be aware:
+-
+- (*) Linux and uClinux
+-
+-     The FR-V architecture port supports both normal MMU linux and uClinux out
+-     of the same sources.
+-
+-
+- (*) CPU support
+-
+-     Support for the FR401, FR403, FR405, FR451 and FR555 CPUs should work with
+-     the same uClinux kernel configuration.
+-
+-     In normal (MMU) Linux mode, only the FR451 CPU will work as that is the
+-     only one with a suitably featured CPU.
+-
+-     The kernel is written and compiled with the assumption that only the
+-     bottom 32 GR registers and no FR registers will be used by the kernel
+-     itself, however all extra userspace registers will be saved on context
+-     switch. Note that since most CPUs can't support lazy switching, no attempt
+-     is made to do lazy register saving where that would be possible (FR555
+-     only currently).
+-
+-
+- (*) Board support
+-
+-     The board on which the kernel will run can be configured on the "Processor
+-     type and features" configuration tab.
+-
+-     Set the System to "MB93093-PDK" to boot from the MB93093 (FR403) PDK.
+-
+-     Set the System to "MB93091-VDK" to boot from the CB11, CB30, CB41, CB60,
+-     CB70 or CB451 VDK boards. Set the Motherboard setting to "MB93090-MB00" to
+-     boot with the standard ATA90590B VDK motherboard, and set it to "None" to
+-     boot without any motherboard.
+-
+-
+- (*) Binary Formats
+-
+-     The only userspace binary format supported is FDPIC ELF. Normal ELF, FLAT
+-     and AOUT binaries are not supported for this architecture.
+-
+-     FDPIC ELF supports shared library and program interpreter facilities.
+-
+-
+- (*) Scheduler Speed
+-
+-     The kernel scheduler runs at 100Hz irrespective of the clock speed on this
+-     architecture. This value is set in asm/param.h (see the HZ macro defined
+-     there).
+-
+-
+- (*) Normal (MMU) Linux Memory Layout.
+-
+-     See mmu-layout.txt in this directory for a description of the normal linux
+-     memory layout
+-
+-     See include/asm-frv/mem-layout.h for constants pertaining to the memory
+-     layout.
+-
+-     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
+-     controller configuration.
+-
+-
+- (*) uClinux Memory Layout
+-
+-     The memory layout used by the uClinux kernel is as follows:
+-
+-	0x00000000 - 0x00000FFF		Null pointer catch page
+-	0x20000000 - 0x200FFFFF CS2#    [PDK] FPGA
+-	0xC0000000 - 0xCFFFFFFF		SDRAM
+-	0xC0000000			Base of Linux kernel image
+-	0xE0000000 - 0xEFFFFFFF	CS2#	[VDK] SLBUS/PCI window
+-	0xF0000000 - 0xF0FFFFFF	CS5#	MB93493 CSC area (DAV daughter board)
+-	0xF1000000 - 0xF1FFFFFF	CS7#	[CB70/CB451] CPU-card PCMCIA port space
+-	0xFC000000 - 0xFC0FFFFF	CS1#	[VDK] MB86943 config space
+-	0xFC100000 - 0xFC1FFFFF	CS6#	[CB70/CB451] CPU-card DM9000 NIC space
+-	0xFC100000 - 0xFC1FFFFF	CS6#	[PDK] AX88796 NIC space
+-	0xFC200000 - 0xFC2FFFFF	CS3#	MB93493 CSR area (DAV daughter board)
+-	0xFD000000 - 0xFDFFFFFF	CS4#	[CB70/CB451] CPU-card extra flash space
+-	0xFE000000 - 0xFEFFFFFF		Internal CPU peripherals
+-	0xFF000000 - 0xFF1FFFFF	CS0#	Flash 1
+-	0xFF200000 - 0xFF3FFFFF	CS0#	Flash 2
+-	0xFFC00000 - 0xFFC0001F	CS0#	[VDK] FPGA
+-
+-     The kernel reads the size of the SDRAM from the memory bus controller
+-     registers by default.
+-
+-     The kernel initialisation code (1) adjusts the SDRAM base addresses to
+-     move the SDRAM to desired address, (2) moves the kernel image down to the
+-     bottom of SDRAM, (3) adjusts the bus controller registers to move I/O
+-     windows, and (4) rearranges the protection registers to protect all of
+-     this.
+-
+-     The reasons for doing this are: (1) the page at address 0 should be
+-     inaccessible so that NULL pointer errors can be caught; and (2) the bottom
+-     three quarters are left unoccupied so that an FR-V CPU with an MMU can use
+-     it for virtual userspace mappings.
+-
+-     See include/asm-frv/mem-layout.h for constants pertaining to the memory
+-     layout.
+-
+-     See include/asm-frv/mb-regs.h for the constants pertaining to the I/O bus
+-     controller configuration.
+-
+-
+- (*) uClinux Memory Protection
+-
+-     A DAMPR register is used to cover the entire region used for I/O
+-     (0xE0000000 - 0xFFFFFFFF). This permits the kernel to make uncached
+-     accesses to this region. Userspace is not permitted to access it.
+-
+-     The DAMPR/IAMPR protection registers not in use for any other purpose are
+-     tiled over the top of the SDRAM such that:
+-
+-	(1) The core kernel image is covered by as small a tile as possible
+-            granting only the kernel access to the underlying data, whilst
+-            making sure no SDRAM is actually made unavailable by this approach.
+-
+-	(2) All other tiles are arranged to permit userspace access to the rest
+-            of the SDRAM.
+-
+-     Barring point (1), there is nothing to protect kernel data against
+-     userspace damage - but this is uClinux.
+-
+-
+- (*) Exceptions and Fixups
+-
+-     Since the FR40x and FR55x CPUs that do not have full MMUs generate
+-     imprecise data error exceptions, there are currently no automatic fixup
+-     services available in uClinux. This includes misaligned memory access
+-     fixups.
+-
+-     Userspace EFAULT errors can be trapped by issuing a MEMBAR instruction and
+-     forcing the fault to happen there.
+-
+-     On the FR451, however, data exceptions are mostly precise, and so
+-     exception fixup handling is implemented as normal.
+-
+-
+- (*) Userspace Breakpoints
+-
+-     The ptrace() system call supports the following userspace debugging
+-     features:
+-
+-	(1) Hardware assisted single step.
+-
+-	(2) Breakpoint via the FR-V "BREAK" instruction.
+-
+-	(3) Breakpoint via the FR-V "TIRA GR0, #1" instruction.
+-
+-	(4) Syscall entry/exit trap.
+-
+-     Each of the above generates a SIGTRAP.
+-
+-
+- (*) On-Chip Serial Ports
+-
+-     The FR-V on-chip serial ports are made available as ttyS0 and ttyS1. Note
+-     that if the GDB stub is compiled in, ttyS1 will not actually be available
+-     as it will be being used for the GDB stub.
+-
+-     These ports can be made by:
+-
+-	mknod /dev/ttyS0 c 4 64
+-	mknod /dev/ttyS1 c 4 65
+-
+-
+- (*) Maskable Interrupts
+-
+-     Level 15 (Non-maskable) interrupts are dealt with by the GDB stub if
+-     present, and cause a panic if not. If the GDB stub is present, ttyS1's
+-     interrupts are rated at level 15.
+-
+-     All other interrupts are distributed over the set of available priorities
+-     so that no IRQs are shared where possible. The arch interrupt handling
+-     routines attempt to disentangle the various sources available through the
+-     CPU's own multiplexor, and those on off-CPU peripherals.
+-
+-
+- (*) Accessing PCI Devices
+-
+-     Where PCI is available, care must be taken when dealing with drivers that
+-     access PCI devices. PCI devices present their data in little-endian form,
+-     but the CPU sees it in big-endian form. The macros in asm/io.h try to get
+-     this right, but may not under all circumstances...
+-
+-
+- (*) Ax88796 Ethernet Driver
+-
+-     The MB93093 PDK board has an Ax88796 ethernet chipset (an NE2000 clone). A
+-     driver has been written to deal specifically with this. The driver
+-     provides MII services for the card.
+-
+-     The driver can be configured by running make xconfig, and going to:
+-
+-	(*) Network device support
+-	    - turn on "Network device support"
+-	    (*) Ethernet (10 or 100Mbit)
+-		- turn on "Ethernet (10 or 100Mbit)"
+-		- turn on "AX88796 NE2000 compatible chipset"
+-
+-     The driver can be found in:
+-
+-	drivers/net/ax88796.c
+-	include/asm/ax88796.h
+-
+-
+- (*) WorkRAM Driver
+-
+-     This driver provides a character device that permits access to the WorkRAM
+-     that can be found on the FR451 CPU. Each page is accessible through a
+-     separate minor number, thereby permitting each page to have its own
+-     filesystem permissions set on the device file.
+-
+-     The device files should be:
+-
+-	mknod /dev/frv/workram0 c 240 0
+-	mknod /dev/frv/workram1 c 240 1
+-	mknod /dev/frv/workram2 c 240 2
+-	...
+-
+-     The driver will not permit the opening of any device file that does not
+-     correspond to at least a partial page of WorkRAM. So the first device file
+-     is the only one available on the FR451. If any other CPU is detected, none
+-     of the devices will be openable.
+-
+-     The devices can be accessed with read, write and llseek, and can also be
+-     mmapped. If they're mmapped, they will only map at the appropriate
+-     0x7e8nnnnn address on linux and at the 0xfe8nnnnn address on uClinux. If
+-     MAP_FIXED is not specified, the appropriate address will be chosen anyway.
+-
+-     The mappings must be MAP_SHARED not MAP_PRIVATE, and must not be
+-     PROT_EXEC. They must also start at file offset 0, and must not be longer
+-     than one page in size.
+-
+-     This driver can be configured by running make xconfig, and going to:
+-
+-	(*) Character devices
+-	    - turn on "Fujitsu FR-V CPU WorkRAM support"
+-
+-
+- (*) Dynamic data cache write mode changing
+-
+-     It is possible to view and to change the data cache's write mode through
+-     the /proc/sys/frv/cache-mode file while the kernel is running. There are
+-     two modes available:
+-
+-	NAME	MEANING
+-	=====	==========================================
+-	wthru	Data cache is in Write-Through mode
+-	wback	Data cache is in Write-Back/Copy-Back mode
+-
+-     To read the cache mode:
+-
+-	# cat /proc/sys/frv/cache-mode
+-	wthru
+-
+-     To change the cache mode:
+-
+-	# echo wback >/proc/sys/frv/cache-mode
+-	# cat /proc/sys/frv/cache-mode
+-	wback
+-
+-
+- (*) MMU Context IDs and Pinning
+-
+-     On MMU Linux the CPU supports the concept of a context ID in its MMU to
+-     make it more efficient (TLB entries are labelled with a context ID to link
+-     them to specific tasks).
+-
+-     Normally once a context ID is allocated, it will remain affixed to a task
+-     or CLONE_VM'd group of tasks for as long as it exists. However, since the
+-     kernel is capable of supporting more tasks than there are possible ID
+-     numbers, the kernel will pass context IDs from one task to another if
+-     there are insufficient available.
+-
+-     The context ID currently in use by a task can be viewed in /proc:
+-
+-	# grep CXNR /proc/1/status
+-	CXNR: 1
+-
+-     Note that kernel threads do not have a userspace context, and so will not
+-     show a CXNR entry in that file.
+-
+-     Under some circumstances, however, it is desirable to pin a context ID on
+-     a process such that the kernel won't pass it on. This can be done by
+-     writing the process ID of the target process to a special file:
+-
+-	# echo 17 >/proc/sys/frv/pin-cxnr
+-
+-     Reading from the file will then show the context ID pinned.
+-
+-	# cat /proc/sys/frv/pin-cxnr
+-	4
+-
+-     The context ID will remain pinned as long as any process is using that
+-     context, i.e.: when the all the subscribing processes have exited or
+-     exec'd; or when an unpinning request happens:
+-
+-	# echo 0 >/proc/sys/frv/pin-cxnr
+-
+-     When there isn't a pinned context, the file shows -1:
+-
+-	# cat /proc/sys/frv/pin-cxnr
+-	-1
+diff --git a/Documentation/fujitsu/frv/gdbinit b/Documentation/fujitsu/frv/gdbinit
+deleted file mode 100644
+index 51517b6..0000000
+--- a/Documentation/fujitsu/frv/gdbinit
++++ /dev/null
+@@ -1,102 +0,0 @@
+-set remotebreak 1
+-
+-define _amr
+-
+-printf "AMRx           DAMR                    IAMR         \n"
+-printf "====   =====================   =====================\n"
+-printf "amr0 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x0].L,__debug_mmu.damr[0x0].P,__debug_mmu.iamr[0x0].L,__debug_mmu.iamr[0x0].P
+-printf "amr1 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x1].L,__debug_mmu.damr[0x1].P,__debug_mmu.iamr[0x1].L,__debug_mmu.iamr[0x1].P
+-printf "amr2 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x2].L,__debug_mmu.damr[0x2].P,__debug_mmu.iamr[0x2].L,__debug_mmu.iamr[0x2].P
+-printf "amr3 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x3].L,__debug_mmu.damr[0x3].P,__debug_mmu.iamr[0x3].L,__debug_mmu.iamr[0x3].P
+-printf "amr4 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x4].L,__debug_mmu.damr[0x4].P,__debug_mmu.iamr[0x4].L,__debug_mmu.iamr[0x4].P
+-printf "amr5 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x5].L,__debug_mmu.damr[0x5].P,__debug_mmu.iamr[0x5].L,__debug_mmu.iamr[0x5].P
+-printf "amr6 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x6].L,__debug_mmu.damr[0x6].P,__debug_mmu.iamr[0x6].L,__debug_mmu.iamr[0x6].P
+-printf "amr7 : L:%08lx P:%08lx : L:%08lx P:%08lx\n",__debug_mmu.damr[0x7].L,__debug_mmu.damr[0x7].P,__debug_mmu.iamr[0x7].L,__debug_mmu.iamr[0x7].P
+-
+-printf "amr8 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x8].L,__debug_mmu.damr[0x8].P
+-printf "amr9 : L:%08lx P:%08lx\n",__debug_mmu.damr[0x9].L,__debug_mmu.damr[0x9].P
+-printf "amr10: L:%08lx P:%08lx\n",__debug_mmu.damr[0xa].L,__debug_mmu.damr[0xa].P
+-printf "amr11: L:%08lx P:%08lx\n",__debug_mmu.damr[0xb].L,__debug_mmu.damr[0xb].P
+-
+-end
+-
+-
+-define _tlb
+-printf "tlb[0x00]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x0].L,__debug_mmu.tlb[0x0].P,__debug_mmu.tlb[0x40+0x0].L,__debug_mmu.tlb[0x40+0x0].P
+-printf "tlb[0x01]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1].L,__debug_mmu.tlb[0x1].P,__debug_mmu.tlb[0x40+0x1].L,__debug_mmu.tlb[0x40+0x1].P
+-printf "tlb[0x02]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2].L,__debug_mmu.tlb[0x2].P,__debug_mmu.tlb[0x40+0x2].L,__debug_mmu.tlb[0x40+0x2].P
+-printf "tlb[0x03]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3].L,__debug_mmu.tlb[0x3].P,__debug_mmu.tlb[0x40+0x3].L,__debug_mmu.tlb[0x40+0x3].P
+-printf "tlb[0x04]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x4].L,__debug_mmu.tlb[0x4].P,__debug_mmu.tlb[0x40+0x4].L,__debug_mmu.tlb[0x40+0x4].P
+-printf "tlb[0x05]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x5].L,__debug_mmu.tlb[0x5].P,__debug_mmu.tlb[0x40+0x5].L,__debug_mmu.tlb[0x40+0x5].P
+-printf "tlb[0x06]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x6].L,__debug_mmu.tlb[0x6].P,__debug_mmu.tlb[0x40+0x6].L,__debug_mmu.tlb[0x40+0x6].P
+-printf "tlb[0x07]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x7].L,__debug_mmu.tlb[0x7].P,__debug_mmu.tlb[0x40+0x7].L,__debug_mmu.tlb[0x40+0x7].P
+-printf "tlb[0x08]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x8].L,__debug_mmu.tlb[0x8].P,__debug_mmu.tlb[0x40+0x8].L,__debug_mmu.tlb[0x40+0x8].P
+-printf "tlb[0x09]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x9].L,__debug_mmu.tlb[0x9].P,__debug_mmu.tlb[0x40+0x9].L,__debug_mmu.tlb[0x40+0x9].P
+-printf "tlb[0x0a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xa].L,__debug_mmu.tlb[0xa].P,__debug_mmu.tlb[0x40+0xa].L,__debug_mmu.tlb[0x40+0xa].P
+-printf "tlb[0x0b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xb].L,__debug_mmu.tlb[0xb].P,__debug_mmu.tlb[0x40+0xb].L,__debug_mmu.tlb[0x40+0xb].P
+-printf "tlb[0x0c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xc].L,__debug_mmu.tlb[0xc].P,__debug_mmu.tlb[0x40+0xc].L,__debug_mmu.tlb[0x40+0xc].P
+-printf "tlb[0x0d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xd].L,__debug_mmu.tlb[0xd].P,__debug_mmu.tlb[0x40+0xd].L,__debug_mmu.tlb[0x40+0xd].P
+-printf "tlb[0x0e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xe].L,__debug_mmu.tlb[0xe].P,__debug_mmu.tlb[0x40+0xe].L,__debug_mmu.tlb[0x40+0xe].P
+-printf "tlb[0x0f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0xf].L,__debug_mmu.tlb[0xf].P,__debug_mmu.tlb[0x40+0xf].L,__debug_mmu.tlb[0x40+0xf].P
+-printf "tlb[0x10]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x10].L,__debug_mmu.tlb[0x10].P,__debug_mmu.tlb[0x40+0x10].L,__debug_mmu.tlb[0x40+0x10].P
+-printf "tlb[0x11]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x11].L,__debug_mmu.tlb[0x11].P,__debug_mmu.tlb[0x40+0x11].L,__debug_mmu.tlb[0x40+0x11].P
+-printf "tlb[0x12]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x12].L,__debug_mmu.tlb[0x12].P,__debug_mmu.tlb[0x40+0x12].L,__debug_mmu.tlb[0x40+0x12].P
+-printf "tlb[0x13]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x13].L,__debug_mmu.tlb[0x13].P,__debug_mmu.tlb[0x40+0x13].L,__debug_mmu.tlb[0x40+0x13].P
+-printf "tlb[0x14]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x14].L,__debug_mmu.tlb[0x14].P,__debug_mmu.tlb[0x40+0x14].L,__debug_mmu.tlb[0x40+0x14].P
+-printf "tlb[0x15]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x15].L,__debug_mmu.tlb[0x15].P,__debug_mmu.tlb[0x40+0x15].L,__debug_mmu.tlb[0x40+0x15].P
+-printf "tlb[0x16]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x16].L,__debug_mmu.tlb[0x16].P,__debug_mmu.tlb[0x40+0x16].L,__debug_mmu.tlb[0x40+0x16].P
+-printf "tlb[0x17]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x17].L,__debug_mmu.tlb[0x17].P,__debug_mmu.tlb[0x40+0x17].L,__debug_mmu.tlb[0x40+0x17].P
+-printf "tlb[0x18]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x18].L,__debug_mmu.tlb[0x18].P,__debug_mmu.tlb[0x40+0x18].L,__debug_mmu.tlb[0x40+0x18].P
+-printf "tlb[0x19]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x19].L,__debug_mmu.tlb[0x19].P,__debug_mmu.tlb[0x40+0x19].L,__debug_mmu.tlb[0x40+0x19].P
+-printf "tlb[0x1a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1a].L,__debug_mmu.tlb[0x1a].P,__debug_mmu.tlb[0x40+0x1a].L,__debug_mmu.tlb[0x40+0x1a].P
+-printf "tlb[0x1b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1b].L,__debug_mmu.tlb[0x1b].P,__debug_mmu.tlb[0x40+0x1b].L,__debug_mmu.tlb[0x40+0x1b].P
+-printf "tlb[0x1c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1c].L,__debug_mmu.tlb[0x1c].P,__debug_mmu.tlb[0x40+0x1c].L,__debug_mmu.tlb[0x40+0x1c].P
+-printf "tlb[0x1d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1d].L,__debug_mmu.tlb[0x1d].P,__debug_mmu.tlb[0x40+0x1d].L,__debug_mmu.tlb[0x40+0x1d].P
+-printf "tlb[0x1e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1e].L,__debug_mmu.tlb[0x1e].P,__debug_mmu.tlb[0x40+0x1e].L,__debug_mmu.tlb[0x40+0x1e].P
+-printf "tlb[0x1f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x1f].L,__debug_mmu.tlb[0x1f].P,__debug_mmu.tlb[0x40+0x1f].L,__debug_mmu.tlb[0x40+0x1f].P
+-printf "tlb[0x20]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x20].L,__debug_mmu.tlb[0x20].P,__debug_mmu.tlb[0x40+0x20].L,__debug_mmu.tlb[0x40+0x20].P
+-printf "tlb[0x21]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x21].L,__debug_mmu.tlb[0x21].P,__debug_mmu.tlb[0x40+0x21].L,__debug_mmu.tlb[0x40+0x21].P
+-printf "tlb[0x22]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x22].L,__debug_mmu.tlb[0x22].P,__debug_mmu.tlb[0x40+0x22].L,__debug_mmu.tlb[0x40+0x22].P
+-printf "tlb[0x23]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x23].L,__debug_mmu.tlb[0x23].P,__debug_mmu.tlb[0x40+0x23].L,__debug_mmu.tlb[0x40+0x23].P
+-printf "tlb[0x24]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x24].L,__debug_mmu.tlb[0x24].P,__debug_mmu.tlb[0x40+0x24].L,__debug_mmu.tlb[0x40+0x24].P
+-printf "tlb[0x25]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x25].L,__debug_mmu.tlb[0x25].P,__debug_mmu.tlb[0x40+0x25].L,__debug_mmu.tlb[0x40+0x25].P
+-printf "tlb[0x26]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x26].L,__debug_mmu.tlb[0x26].P,__debug_mmu.tlb[0x40+0x26].L,__debug_mmu.tlb[0x40+0x26].P
+-printf "tlb[0x27]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x27].L,__debug_mmu.tlb[0x27].P,__debug_mmu.tlb[0x40+0x27].L,__debug_mmu.tlb[0x40+0x27].P
+-printf "tlb[0x28]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x28].L,__debug_mmu.tlb[0x28].P,__debug_mmu.tlb[0x40+0x28].L,__debug_mmu.tlb[0x40+0x28].P
+-printf "tlb[0x29]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x29].L,__debug_mmu.tlb[0x29].P,__debug_mmu.tlb[0x40+0x29].L,__debug_mmu.tlb[0x40+0x29].P
+-printf "tlb[0x2a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2a].L,__debug_mmu.tlb[0x2a].P,__debug_mmu.tlb[0x40+0x2a].L,__debug_mmu.tlb[0x40+0x2a].P
+-printf "tlb[0x2b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2b].L,__debug_mmu.tlb[0x2b].P,__debug_mmu.tlb[0x40+0x2b].L,__debug_mmu.tlb[0x40+0x2b].P
+-printf "tlb[0x2c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2c].L,__debug_mmu.tlb[0x2c].P,__debug_mmu.tlb[0x40+0x2c].L,__debug_mmu.tlb[0x40+0x2c].P
+-printf "tlb[0x2d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2d].L,__debug_mmu.tlb[0x2d].P,__debug_mmu.tlb[0x40+0x2d].L,__debug_mmu.tlb[0x40+0x2d].P
+-printf "tlb[0x2e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2e].L,__debug_mmu.tlb[0x2e].P,__debug_mmu.tlb[0x40+0x2e].L,__debug_mmu.tlb[0x40+0x2e].P
+-printf "tlb[0x2f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x2f].L,__debug_mmu.tlb[0x2f].P,__debug_mmu.tlb[0x40+0x2f].L,__debug_mmu.tlb[0x40+0x2f].P
+-printf "tlb[0x30]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x30].L,__debug_mmu.tlb[0x30].P,__debug_mmu.tlb[0x40+0x30].L,__debug_mmu.tlb[0x40+0x30].P
+-printf "tlb[0x31]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x31].L,__debug_mmu.tlb[0x31].P,__debug_mmu.tlb[0x40+0x31].L,__debug_mmu.tlb[0x40+0x31].P
+-printf "tlb[0x32]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x32].L,__debug_mmu.tlb[0x32].P,__debug_mmu.tlb[0x40+0x32].L,__debug_mmu.tlb[0x40+0x32].P
+-printf "tlb[0x33]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x33].L,__debug_mmu.tlb[0x33].P,__debug_mmu.tlb[0x40+0x33].L,__debug_mmu.tlb[0x40+0x33].P
+-printf "tlb[0x34]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x34].L,__debug_mmu.tlb[0x34].P,__debug_mmu.tlb[0x40+0x34].L,__debug_mmu.tlb[0x40+0x34].P
+-printf "tlb[0x35]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x35].L,__debug_mmu.tlb[0x35].P,__debug_mmu.tlb[0x40+0x35].L,__debug_mmu.tlb[0x40+0x35].P
+-printf "tlb[0x36]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x36].L,__debug_mmu.tlb[0x36].P,__debug_mmu.tlb[0x40+0x36].L,__debug_mmu.tlb[0x40+0x36].P
+-printf "tlb[0x37]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x37].L,__debug_mmu.tlb[0x37].P,__debug_mmu.tlb[0x40+0x37].L,__debug_mmu.tlb[0x40+0x37].P
+-printf "tlb[0x38]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x38].L,__debug_mmu.tlb[0x38].P,__debug_mmu.tlb[0x40+0x38].L,__debug_mmu.tlb[0x40+0x38].P
+-printf "tlb[0x39]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x39].L,__debug_mmu.tlb[0x39].P,__debug_mmu.tlb[0x40+0x39].L,__debug_mmu.tlb[0x40+0x39].P
+-printf "tlb[0x3a]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3a].L,__debug_mmu.tlb[0x3a].P,__debug_mmu.tlb[0x40+0x3a].L,__debug_mmu.tlb[0x40+0x3a].P
+-printf "tlb[0x3b]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3b].L,__debug_mmu.tlb[0x3b].P,__debug_mmu.tlb[0x40+0x3b].L,__debug_mmu.tlb[0x40+0x3b].P
+-printf "tlb[0x3c]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3c].L,__debug_mmu.tlb[0x3c].P,__debug_mmu.tlb[0x40+0x3c].L,__debug_mmu.tlb[0x40+0x3c].P
+-printf "tlb[0x3d]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3d].L,__debug_mmu.tlb[0x3d].P,__debug_mmu.tlb[0x40+0x3d].L,__debug_mmu.tlb[0x40+0x3d].P
+-printf "tlb[0x3e]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3e].L,__debug_mmu.tlb[0x3e].P,__debug_mmu.tlb[0x40+0x3e].L,__debug_mmu.tlb[0x40+0x3e].P
+-printf "tlb[0x3f]: %08lx %08lx  %08lx %08lx\n",__debug_mmu.tlb[0x3f].L,__debug_mmu.tlb[0x3f].P,__debug_mmu.tlb[0x40+0x3f].L,__debug_mmu.tlb[0x40+0x3f].P
+-end
+-
+-
+-define _pgd
+-p (pgd_t[0x40])*(pgd_t*)(__debug_mmu.damr[0x3].L)
+-end
+-
+-define _ptd_i
+-p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x4].L)
+-end
+-
+-define _ptd_d
+-p (pte_t[0x1000])*(pte_t*)(__debug_mmu.damr[0x5].L)
+-end
+diff --git a/Documentation/fujitsu/frv/gdbstub.txt b/Documentation/fujitsu/frv/gdbstub.txt
+deleted file mode 100644
+index b92bfd9..0000000
+--- a/Documentation/fujitsu/frv/gdbstub.txt
++++ /dev/null
+@@ -1,130 +0,0 @@
+-			     ====================
+-			     DEBUGGING FR-V LINUX
+-			     ====================
+-
+-
+-The kernel contains a GDB stub that talks GDB remote protocol across a serial
+-port. This permits GDB to single step through the kernel, set breakpoints and
+-trap exceptions that happen in kernel space and interrupt execution. It also
+-permits the NMI interrupt button or serial port events to jump the kernel into
+-the debugger.
+-
+-On the CPUs that have on-chip UARTs (FR400, FR403, FR405, FR555), the
+-GDB stub hijacks a serial port for its own purposes, and makes it
+-generate level 15 interrupts (NMI). The kernel proper cannot see the serial
+-port in question under these conditions.
+-
+-On the MB93091-VDK CPU boards, the GDB stub uses UART1, which would otherwise
+-be /dev/ttyS1. On the MB93093-PDK, the GDB stub uses UART0. Therefore, on the
+-PDK there is no externally accessible serial port and the serial port to
+-which the touch screen is attached becomes /dev/ttyS0.
+-
+-Note that the GDB stub runs entirely within CPU debug mode, and so should not
+-incur any exceptions or interrupts whilst it is active. In particular, note
+-that the clock will lose time since it is implemented in software.
+-
+-
+-==================
+-KERNEL PREPARATION
+-==================
+-
+-Firstly, a debuggable kernel must be built. To do this, unpack the kernel tree
+-and copy the configuration that you wish to use to .config. Then reconfigure
+-the following things on the "Kernel Hacking" tab:
+-
+-  (*) "Include debugging information"
+-
+-      Set this to "Y". This causes all C and Assembly files to be compiled
+-      to include debugging information.
+-
+-  (*) "In-kernel GDB stub"
+-
+-      Set this to "Y". This causes the GDB stub to be compiled into the
+-      kernel.
+-
+-  (*) "Immediate activation"
+-
+-      Set this to "Y" if you want the GDB stub to activate as soon as possible
+-      and wait for GDB to connect. This allows you to start tracing right from
+-      the beginning of start_kernel() in init/main.c.
+-
+-  (*) "Console through GDB stub"
+-
+-      Set this to "Y" if you wish to be able to use "console=gdb0" on the
+-      command line. That tells the kernel to pass system console messages to
+-      GDB (which then prints them on its standard output). This is useful when
+-      debugging the serial drivers that'd otherwise be used to pass console
+-      messages to the outside world.
+-
+-Then build as usual, download to the board and execute. Note that if
+-"Immediate activation" was selected, then the kernel will wait for GDB to
+-attach. If not, then the kernel will boot immediately and GDB will have to
+-interrupt it or wait for an exception to occur before doing anything with
+-the kernel.
+-
+-
+-=========================
+-KERNEL DEBUGGING WITH GDB
+-=========================
+-
+-Set the serial port on the computer that's going to run GDB to the appropriate
+-baud rate. Assuming the board's debug port is connected to ttyS0/COM1 on the
+-computer doing the debugging:
+-
+-	stty -F /dev/ttyS0 115200
+-
+-Then start GDB in the base of the kernel tree:
+-
+-	frv-uclinux-gdb linux		[uClinux]
+-
+-Or:
+-
+-	frv-uclinux-gdb vmlinux		[MMU linux]
+-
+-When the prompt appears:
+-
+-	GNU gdb frv-031024
+-	Copyright 2003 Free Software Foundation, Inc.
+-	GDB is free software, covered by the GNU General Public License, and you are
+-	welcome to change it and/or distribute copies of it under certain conditions.
+-	Type "show copying" to see the conditions.
+-	There is absolutely no warranty for GDB.  Type "show warranty" for details.
+-	This GDB was configured as "--host=i686-pc-linux-gnu --target=frv-uclinux"...
+-	(gdb)
+-
+-Attach to the board like this:
+-
+-        (gdb) target remote /dev/ttyS0
+-	Remote debugging using /dev/ttyS0
+-	start_kernel () at init/main.c:395
+-	(gdb)
+-
+-This should show the appropriate lines from the source too. The kernel can
+-then be debugged almost as if it's any other program.
+-
+-
+-===============================
+-INTERRUPTING THE RUNNING KERNEL
+-===============================
+-
+-The kernel can be interrupted whilst it is running, causing a jump back to the
+-GDB stub and the debugger:
+-
+-  (*) Pressing Ctrl-C in GDB. This will cause GDB to try and interrupt the
+-      kernel by sending an RS232 BREAK over the serial line to the GDB
+-      stub. This will (mostly) immediately interrupt the kernel and return it
+-      to the debugger.
+-
+-  (*) Pressing the NMI button on the board will also cause a jump into the
+-      debugger.
+-
+-  (*) Setting a software breakpoint. This sets a break instruction at the
+-      desired location which the GDB stub then traps the exception for.
+-
+-  (*) Setting a hardware breakpoint. The GDB stub is capable of using the IBAR
+-      and DBAR registers to assist debugging.
+-
+-Furthermore, the GDB stub will intercept a number of exceptions automatically
+-if they are caused by kernel execution. It will also intercept BUG() macro
+-invocation.
+-
+diff --git a/Documentation/fujitsu/frv/kernel-ABI.txt b/Documentation/fujitsu/frv/kernel-ABI.txt
+deleted file mode 100644
+index aaa1cec..0000000
+--- a/Documentation/fujitsu/frv/kernel-ABI.txt
++++ /dev/null
+@@ -1,262 +0,0 @@
+-			=================================
+-			INTERNAL KERNEL ABI FOR FR-V ARCH
+-			=================================
+-
+-The internal FRV kernel ABI is not quite the same as the userspace ABI. A
+-number of the registers are used for special purposed, and the ABI is not
+-consistent between modules vs core, and MMU vs no-MMU.
+-
+-This partly stems from the fact that FRV CPUs do not have a separate
+-supervisor stack pointer, and most of them do not have any scratch
+-registers, thus requiring at least one general purpose register to be
+-clobbered in such an event. Also, within the kernel core, it is possible to
+-simply jump or call directly between functions using a relative offset.
+-This cannot be extended to modules for the displacement is likely to be too
+-far. Thus in modules the address of a function to call must be calculated
+-in a register and then used, requiring two extra instructions.
+-
+-This document has the following sections:
+-
+- (*) System call register ABI
+- (*) CPU operating modes
+- (*) Internal kernel-mode register ABI
+- (*) Internal debug-mode register ABI
+- (*) Virtual interrupt handling
+-
+-
+-========================
+-SYSTEM CALL REGISTER ABI
+-========================
+-
+-When a system call is made, the following registers are effective:
+-
+-	REGISTERS	CALL			RETURN
+-	===============	=======================	=======================
+-	GR7		System call number	Preserved
+-	GR8		Syscall arg #1		Return value
+-	GR9-GR13	Syscall arg #2-6	Preserved
+-
+-
+-===================
+-CPU OPERATING MODES
+-===================
+-
+-The FR-V CPU has three basic operating modes. In order of increasing
+-capability:
+-
+-  (1) User mode.
+-
+-      Basic userspace running mode.
+-
+-  (2) Kernel mode.
+-
+-      Normal kernel mode. There are many additional control registers
+-      available that may be accessed in this mode, in addition to all the
+-      stuff available to user mode. This has two submodes:
+-
+-      (a) Exceptions enabled (PSR.T == 1).
+-
+-	  Exceptions will invoke the appropriate normal kernel mode
+-	  handler. On entry to the handler, the PSR.T bit will be cleared.
+-
+-      (b) Exceptions disabled (PSR.T == 0).
+-
+-	  No exceptions or interrupts may happen. Any mandatory exceptions
+-	  will cause the CPU to halt unless the CPU is told to jump into
+-	  debug mode instead.
+-
+-  (3) Debug mode.
+-
+-      No exceptions may happen in this mode. Memory protection and
+-      management exceptions will be flagged for later consideration, but
+-      the exception handler won't be invoked. Debugging traps such as
+-      hardware breakpoints and watchpoints will be ignored. This mode is
+-      entered only by debugging events obtained from the other two modes.
+-
+-      All kernel mode registers may be accessed, plus a few extra debugging
+-      specific registers.
+-
+-
+-=================================
+-INTERNAL KERNEL-MODE REGISTER ABI
+-=================================
+-
+-There are a number of permanent register assignments that are set up by
+-entry.S in the exception prologue. Note that there is a complete set of
+-exception prologues for each of user->kernel transition and kernel->kernel
+-transition. There are also user->debug and kernel->debug mode transition
+-prologues.
+-
+-
+-	REGISTER	FLAVOUR	USE
+-	===============	=======	==============================================
+-	GR1			Supervisor stack pointer
+-	GR15			Current thread info pointer
+-	GR16			GP-Rel base register for small data
+-	GR28			Current exception frame pointer (__frame)
+-	GR29			Current task pointer (current)
+-	GR30			Destroyed by kernel mode entry
+-	GR31		NOMMU	Destroyed by debug mode entry
+-	GR31		MMU	Destroyed by TLB miss kernel mode entry
+-	CCR.ICC2		Virtual interrupt disablement tracking
+-	CCCR.CC3		Cleared by exception prologue 
+-				(atomic op emulation)
+-	SCR0		MMU	See mmu-layout.txt.
+-	SCR1		MMU	See mmu-layout.txt.
+-	SCR2		MMU	Save for EAR0 (destroyed by icache insns 
+-					       in debug mode)
+-	SCR3		MMU	Save for GR31 during debug exceptions
+-	DAMR/IAMR	NOMMU	Fixed memory protection layout.
+-	DAMR/IAMR	MMU	See mmu-layout.txt.
+-
+-
+-Certain registers are also used or modified across function calls:
+-
+-	REGISTER	CALL				RETURN
+-	===============	===============================	======================
+-	GR0		Fixed Zero			-
+-	GR2		Function call frame pointer
+-	GR3		Special				Preserved
+-	GR3-GR7		-				Clobbered
+-	GR8		Function call arg #1		Return value 
+-							(or clobbered)
+-	GR9		Function call arg #2		Return value MSW 
+-							(or clobbered)
+-	GR10-GR13	Function call arg #3-#6		Clobbered
+-	GR14		-				Clobbered
+-	GR15-GR16	Special				Preserved
+-	GR17-GR27	-				Preserved
+-	GR28-GR31	Special				Only accessed 
+-							explicitly
+-	LR		Return address after CALL	Clobbered
+-	CCR/CCCR	-				Mostly Clobbered
+-
+-
+-================================
+-INTERNAL DEBUG-MODE REGISTER ABI
+-================================
+-
+-This is the same as the kernel-mode register ABI for functions calls. The
+-difference is that in debug-mode there's a different stack and a different
+-exception frame. Almost all the global registers from kernel-mode
+-(including the stack pointer) may be changed.
+-
+-	REGISTER	FLAVOUR	USE
+-	===============	=======	==============================================
+-	GR1			Debug stack pointer
+-	GR16			GP-Rel base register for small data
+-	GR31			Current debug exception frame pointer 
+-				(__debug_frame)
+-	SCR3		MMU	Saved value of GR31
+-
+-
+-Note that debug mode is able to interfere with the kernel's emulated atomic
+-ops, so it must be exceedingly careful not to do any that would interact
+-with the main kernel in this regard. Hence the debug mode code (gdbstub) is
+-almost completely self-contained. The only external code used is the
+-sprintf family of functions.
+-
+-Furthermore, break.S is so complicated because single-step mode does not
+-switch off on entry to an exception. That means unless manually disabled,
+-single-stepping will blithely go on stepping into things like interrupts.
+-See gdbstub.txt for more information.
+-
+-
+-==========================
+-VIRTUAL INTERRUPT HANDLING
+-==========================
+-
+-Because accesses to the PSR is so slow, and to disable interrupts we have
+-to access it twice (once to read and once to write), we don't actually
+-disable interrupts at all if we don't have to. What we do instead is use
+-the ICC2 condition code flags to note virtual disablement, such that if we
+-then do take an interrupt, we note the flag, really disable interrupts, set
+-another flag and resume execution at the point the interrupt happened.
+-Setting condition flags as a side effect of an arithmetic or logical
+-instruction is really fast. This use of the ICC2 only occurs within the
+-kernel - it does not affect userspace.
+-
+-The flags we use are:
+-
+- (*) CCR.ICC2.Z [Zero flag]
+-
+-     Set to virtually disable interrupts, clear when interrupts are
+-     virtually enabled. Can be modified by logical instructions without
+-     affecting the Carry flag.
+-
+- (*) CCR.ICC2.C [Carry flag]
+-
+-     Clear to indicate hardware interrupts are really disabled, set otherwise.
+-
+-
+-What happens is this:
+-
+- (1) Normal kernel-mode operation.
+-
+-	ICC2.Z is 0, ICC2.C is 1.
+-
+- (2) An interrupt occurs. The exception prologue examines ICC2.Z and
+-     determines that nothing needs doing. This is done simply with an
+-     unlikely BEQ instruction.
+-
+- (3) The interrupts are disabled (local_irq_disable)
+-
+-	ICC2.Z is set to 1.
+-
+- (4) If interrupts were then re-enabled (local_irq_enable):
+-
+-	ICC2.Z would be set to 0.
+-
+-     A TIHI #2 instruction (trap #2 if condition HI - Z==0 && C==0) would
+-     be used to trap if interrupts were now virtually enabled, but
+-     physically disabled - which they're not, so the trap isn't taken. The
+-     kernel would then be back to state (1).
+-
+- (5) An interrupt occurs. The exception prologue examines ICC2.Z and
+-     determines that the interrupt shouldn't actually have happened. It
+-     jumps aside, and there disabled interrupts by setting PSR.PIL to 14
+-     and then it clears ICC2.C.
+-
+- (6) If interrupts were then saved and disabled again (local_irq_save):
+-
+-	ICC2.Z would be shifted into the save variable and masked off 
+-	(giving a 1).
+-
+-	ICC2.Z would then be set to 1 (thus unchanged), and ICC2.C would be
+-	unaffected (ie: 0).
+-
+- (7) If interrupts were then restored from state (6) (local_irq_restore):
+-
+-	ICC2.Z would be set to indicate the result of XOR'ing the saved
+-	value (ie: 1) with 1, which gives a result of 0 - thus leaving
+-	ICC2.Z set.
+-
+-	ICC2.C would remain unaffected (ie: 0).
+-
+-     A TIHI #2 instruction would be used to again assay the current state,
+-     but this would do nothing as Z==1.
+-
+- (8) If interrupts were then enabled (local_irq_enable):
+-
+-	ICC2.Z would be cleared. ICC2.C would be left unaffected. Both
+-	flags would now be 0.
+-
+-     A TIHI #2 instruction again issued to assay the current state would
+-     then trap as both Z==0 [interrupts virtually enabled] and C==0
+-     [interrupts really disabled] would then be true.
+-
+- (9) The trap #2 handler would simply enable hardware interrupts 
+-     (set PSR.PIL to 0), set ICC2.C to 1 and return.
+-
+-(10) Immediately upon returning, the pending interrupt would be taken.
+-
+-(11) The interrupt handler would take the path of actually processing the
+-     interrupt (ICC2.Z is clear, BEQ fails as per step (2)).
+-
+-(12) The interrupt handler would then set ICC2.C to 1 since hardware
+-     interrupts are definitely enabled - or else the kernel wouldn't be here.
+-
+-(13) On return from the interrupt handler, things would be back to state (1).
+-
+-This trap (#2) is only available in kernel mode. In user mode it will
+-result in SIGILL.
+diff --git a/Documentation/fujitsu/frv/mmu-layout.txt b/Documentation/fujitsu/frv/mmu-layout.txt
+deleted file mode 100644
+index db10250..0000000
+--- a/Documentation/fujitsu/frv/mmu-layout.txt
++++ /dev/null
+@@ -1,306 +0,0 @@
+-				 =================================
+-				 FR451 MMU LINUX MEMORY MANAGEMENT
+-				 =================================
+-
+-============
+-MMU HARDWARE
+-============
+-
+-FR451 MMU Linux puts the MMU into EDAT mode whilst running. This means that it uses both the SAT
+-registers and the DAT TLB to perform address translation.
+-
+-There are 8 IAMLR/IAMPR register pairs and 16 DAMLR/DAMPR register pairs for SAT mode.
+-
+-In DAT mode, there is also a TLB organised in cache format as 64 lines x 2 ways. Each line spans a
+-16KB range of addresses, but can match a larger region.
+-
+-
+-===========================
+-MEMORY MANAGEMENT REGISTERS
+-===========================
+-
+-Certain control registers are used by the kernel memory management routines:
+-
+-	REGISTERS		USAGE
+-	======================	==================================================
+-	IAMR0, DAMR0		Kernel image and data mappings
+-	IAMR1, DAMR1		First-chance TLB lookup mapping
+-	DAMR2			Page attachment for cache flush by page
+-	DAMR3			Current PGD mapping
+-	SCR0, DAMR4		Instruction TLB PGE/PTD cache
+-	SCR1, DAMR5		Data TLB PGE/PTD cache
+-	DAMR6-10		kmap_atomic() mappings
+-	DAMR11			I/O mapping
+-	CXNR			mm_struct context ID
+-	TTBR			Page directory (PGD) pointer (physical address)
+-
+-
+-=====================
+-GENERAL MEMORY LAYOUT
+-=====================
+-
+-The physical memory layout is as follows:
+-
+-  PHYSICAL ADDRESS	CONTROLLER	DEVICE
+-  ===================	==============	=======================================
+-  00000000 - BFFFFFFF	SDRAM		SDRAM area
+-  E0000000 - EFFFFFFF	L-BUS CS2#	VDK SLBUS/PCI window
+-  F0000000 - F0FFFFFF	L-BUS CS5#	MB93493 CSC area (DAV daughter board)
+-  F1000000 - F1FFFFFF	L-BUS CS7#	(CB70 CPU-card PCMCIA port I/O space)
+-  FC000000 - FC0FFFFF	L-BUS CS1#	VDK MB86943 config space
+-  FC100000 - FC1FFFFF	L-BUS CS6#	DM9000 NIC I/O space
+-  FC200000 - FC2FFFFF	L-BUS CS3#	MB93493 CSR area (DAV daughter board)
+-  FD000000 - FDFFFFFF	L-BUS CS4#	(CB70 CPU-card extra flash space)
+-  FE000000 - FEFFFFFF			Internal CPU peripherals
+-  FF000000 - FF1FFFFF	L-BUS CS0#	Flash 1
+-  FF200000 - FF3FFFFF	L-BUS CS0#	Flash 2
+-  FFC00000 - FFC0001F	L-BUS CS0#	FPGA
+-
+-The virtual memory layout is:
+-
+-  VIRTUAL ADDRESS    PHYSICAL	TRANSLATOR	FLAGS	SIZE	OCCUPATION
+-  =================  ========	==============	=======	=======	===================================
+-  00004000-BFFFFFFF  various	TLB,xAMR1	D-N-??V	3GB	Userspace
+-  C0000000-CFFFFFFF  00000000	xAMPR0		-L-S--V	256MB	Kernel image and data
+-  D0000000-D7FFFFFF  various	TLB,xAMR1	D-NS??V	128MB	vmalloc area
+-  D8000000-DBFFFFFF  various	TLB,xAMR1	D-NS??V	64MB	kmap() area
+-  DC000000-DCFFFFFF  various	TLB			1MB	Secondary kmap_atomic() frame
+-  DD000000-DD27FFFF  various	DAMR			160KB	Primary kmap_atomic() frame
+-  DD040000			DAMR2/IAMR2	-L-S--V	page	Page cache flush attachment point
+-  DD080000			DAMR3		-L-SC-V	page	Page Directory (PGD)
+-  DD0C0000			DAMR4		-L-SC-V	page	Cached insn TLB Page Table lookup
+-  DD100000			DAMR5		-L-SC-V	page	Cached data TLB Page Table lookup
+-  DD140000			DAMR6		-L-S--V	page	kmap_atomic(KM_BOUNCE_READ)
+-  DD180000			DAMR7		-L-S--V	page	kmap_atomic(KM_SKB_SUNRPC_DATA)
+-  DD1C0000			DAMR8		-L-S--V	page	kmap_atomic(KM_SKB_DATA_SOFTIRQ)
+-  DD200000			DAMR9		-L-S--V	page	kmap_atomic(KM_USER0)
+-  DD240000			DAMR10		-L-S--V	page	kmap_atomic(KM_USER1)
+-  E0000000-FFFFFFFF  E0000000	DAMR11		-L-SC-V	512MB	I/O region
+-
+-IAMPR1 and DAMPR1 are used as an extension to the TLB.
+-
+-
+-====================
+-KMAP AND KMAP_ATOMIC
+-====================
+-
+-To access pages in the page cache (which may not be directly accessible if highmem is available),
+-the kernel calls kmap(), does the access and then calls kunmap(); or it calls kmap_atomic(), does
+-the access and then calls kunmap_atomic().
+-
+-kmap() creates an attachment between an arbitrary inaccessible page and a range of virtual
+-addresses by installing a PTE in a special page table. The kernel can then access this page as it
+-wills. When it's finished, the kernel calls kunmap() to clear the PTE.
+-
+-kmap_atomic() does something slightly different. In the interests of speed, it chooses one of two
+-strategies:
+-
+- (1) If possible, kmap_atomic() attaches the requested page to one of DAMPR5 through DAMPR10
+-     register pairs; and the matching kunmap_atomic() clears the DAMPR. This makes high memory
+-     support really fast as there's no need to flush the TLB or modify the page tables. The DAMLR
+-     registers being used for this are preset during boot and don't change over the lifetime of the
+-     process. There's a direct mapping between the first few kmap_atomic() types, DAMR number and
+-     virtual address slot.
+-
+-     However, there are more kmap_atomic() types defined than there are DAMR registers available,
+-     so we fall back to:
+-
+- (2) kmap_atomic() uses a slot in the secondary frame (determined by the type parameter), and then
+-     locks an entry in the TLB to translate that slot to the specified page. The number of slots is
+-     obviously limited, and their positions are controlled such that each slot is matched by a
+-     different line in the TLB. kunmap() ejects the entry from the TLB.
+-
+-Note that the first three kmap atomic types are really just declared as placeholders. The DAMPR
+-registers involved are actually modified directly.
+-
+-Also note that kmap() itself may sleep, kmap_atomic() may never sleep and both always succeed;
+-furthermore, a driver using kmap() may sleep before calling kunmap(), but may not sleep before
+-calling kunmap_atomic() if it had previously called kmap_atomic().
+-
+-
+-===============================
+-USING MORE THAN 256MB OF MEMORY
+-===============================
+-
+-The kernel cannot access more than 256MB of memory directly. The physical layout, however, permits
+-up to 3GB of SDRAM (possibly 3.25GB) to be made available. By using CONFIG_HIGHMEM, the kernel can
+-allow userspace (by way of page tables) and itself (by way of kmap) to deal with the memory
+-allocation.
+-
+-External devices can, of course, still DMA to and from all of the SDRAM, even if the kernel can't
+-see it directly. The kernel translates page references into real addresses for communicating to the
+-devices.
+-
+-
+-===================
+-PAGE TABLE TOPOLOGY
+-===================
+-
+-The page tables are arranged in 2-layer format. There is a middle layer (PMD) that would be used in
+-3-layer format tables but that is folded into the top layer (PGD) and so consumes no extra memory
+-or processing power.
+-
+-  +------+     PGD    PMD
+-  | TTBR |--->+-------------------+
+-  +------+    |      |      : STE |
+-              | PGE0 | PME0 : STE |
+-              |      |      : STE |
+-              +-------------------+              Page Table
+-              |      |      : STE -------------->+--------+ +0x0000
+-              | PGE1 | PME0 : STE -----------+   | PTE0   |
+-              |      |      : STE -------+   |   +--------+
+-              +-------------------+      |   |   | PTE63  |
+-              |      |      : STE |      |   +-->+--------+ +0x0100
+-              | PGE2 | PME0 : STE |      |       | PTE64  |
+-              |      |      : STE |      |       +--------+
+-              +-------------------+      |       | PTE127 |
+-              |      |      : STE |      +------>+--------+ +0x0200
+-              | PGE3 | PME0 : STE |              | PTE128 |
+-              |      |      : STE |              +--------+
+-              +-------------------+              | PTE191 |
+-                                                 +--------+ +0x0300
+-
+-Each Page Directory (PGD) is 16KB (page size) in size and is divided into 64 entries (PGEs). Each
+-PGE contains one Page Mid Directory (PMD).
+-
+-Each PMD is 256 bytes in size and contains a single entry (PME). Each PME holds 64 FR451 MMU
+-segment table entries of 4 bytes apiece. Each PME "points to" a page table. In practice, each STE
+-points to a subset of the page table, the first to PT+0x0000, the second to PT+0x0100, the third to
+-PT+0x200, and so on.
+-
+-Each PGE and PME covers 64MB of the total virtual address space.
+-
+-Each Page Table (PTD) is 16KB (page size) in size, and is divided into 4096 entries (PTEs). Each
+-entry can point to one 16KB page. In practice, each Linux page table is subdivided into 64 FR451
+-MMU page tables. But they are all grouped together to make management easier, in particular rmap
+-support is then trivial.
+-
+-Grouping page tables in this fashion makes PGE caching in SCR0/SCR1 more efficient because the
+-coverage of the cached item is greater.
+-
+-Page tables for the vmalloc area are allocated at boot time and shared between all mm_structs.
+-
+-
+-=================
+-USER SPACE LAYOUT
+-=================
+-
+-For MMU capable Linux, the regions userspace code are allowed to access are kept entirely separate
+-from those dedicated to the kernel:
+-
+-	VIRTUAL ADDRESS    SIZE   PURPOSE
+-	=================  =====  ===================================
+-	00000000-00003fff  4KB    NULL pointer access trap
+-	00004000-01ffffff  ~32MB  lower mmap space (grows up)
+-	02000000-021fffff  2MB    Stack space (grows down from top)
+-	02200000-nnnnnnnn         Executable mapping
+-        nnnnnnnn-                 brk space (grows up)
+-	        -bfffffff         upper mmap space (grows down)
+-
+-This is so arranged so as to make best use of the 16KB page tables and the way in which PGEs/PMEs
+-are cached by the TLB handler. The lower mmap space is filled first, and then the upper mmap space
+-is filled.
+-
+-
+-===============================
+-GDB-STUB MMU DEBUGGING SERVICES
+-===============================
+-
+-The gdb-stub included in this kernel provides a number of services to aid in the debugging of MMU
+-related kernel services:
+-
+- (*) Every time the kernel stops, certain state information is dumped into __debug_mmu. This
+-     variable is defined in arch/frv/kernel/gdb-stub.c. Note that the gdbinit file in this
+-     directory has some useful macros for dealing with this.
+-
+-     (*) __debug_mmu.tlb[]
+-
+-	 This receives the current TLB contents. This can be viewed with the _tlb GDB macro:
+-
+-		(gdb) _tlb
+-		tlb[0x00]: 01000005 00718203  01000002 00718203
+-		tlb[0x01]: 01004002 006d4201  01004005 006d4203
+-		tlb[0x02]: 01008002 006d0201  01008006 00004200
+-		tlb[0x03]: 0100c006 007f4202  0100c002 0064c202
+-		tlb[0x04]: 01110005 00774201  01110002 00774201
+-		tlb[0x05]: 01114005 00770201  01114002 00770201
+-		tlb[0x06]: 01118002 0076c201  01118005 0076c201
+-		...
+-		tlb[0x3d]: 010f4002 00790200  001f4002 0054ca02
+-		tlb[0x3e]: 010f8005 0078c201  010f8002 0078c201
+-		tlb[0x3f]: 001fc002 0056ca01  001fc005 00538a01
+-
+-     (*) __debug_mmu.iamr[]
+-     (*) __debug_mmu.damr[]
+-
+-	 These receive the current IAMR and DAMR contents. These can be viewed with the _amr
+-	 GDB macro:
+-
+-		(gdb) _amr
+-		AMRx           DAMR                    IAMR
+-		====   =====================   =====================
+-		amr0 : L:c0000000 P:00000cb9 : L:c0000000 P:000004b9
+-		amr1 : L:01070005 P:006f9203 : L:0102c005 P:006a1201
+-		amr2 : L:d8d00000 P:00000000 : L:d8d00000 P:00000000
+-		amr3 : L:d8d04000 P:00534c0d : L:00000000 P:00000000
+-		amr4 : L:d8d08000 P:00554c0d : L:00000000 P:00000000
+-		amr5 : L:d8d0c000 P:00554c0d : L:00000000 P:00000000
+-		amr6 : L:d8d10000 P:00000000 : L:00000000 P:00000000
+-		amr7 : L:d8d14000 P:00000000 : L:00000000 P:00000000
+-		amr8 : L:d8d18000 P:00000000
+-		amr9 : L:d8d1c000 P:00000000
+-		amr10: L:d8d20000 P:00000000
+-		amr11: L:e0000000 P:e0000ccd
+-
+- (*) The current task's page directory is bound to DAMR3.
+-
+-     This can be viewed with the _pgd GDB macro:
+-
+-	(gdb) _pgd
+-	$3 = {{pge = {{ste = {0x554001, 0x554101, 0x554201, 0x554301, 0x554401,
+-		  0x554501, 0x554601, 0x554701, 0x554801, 0x554901, 0x554a01,
+-		  0x554b01, 0x554c01, 0x554d01, 0x554e01, 0x554f01, 0x555001,
+-		  0x555101, 0x555201, 0x555301, 0x555401, 0x555501, 0x555601,
+-		  0x555701, 0x555801, 0x555901, 0x555a01, 0x555b01, 0x555c01,
+-		  0x555d01, 0x555e01, 0x555f01, 0x556001, 0x556101, 0x556201,
+-		  0x556301, 0x556401, 0x556501, 0x556601, 0x556701, 0x556801,
+-		  0x556901, 0x556a01, 0x556b01, 0x556c01, 0x556d01, 0x556e01,
+-		  0x556f01, 0x557001, 0x557101, 0x557201, 0x557301, 0x557401,
+-		  0x557501, 0x557601, 0x557701, 0x557801, 0x557901, 0x557a01,
+-		  0x557b01, 0x557c01, 0x557d01, 0x557e01, 0x557f01}}}}, {pge = {{
+-		ste = {0x0 <repeats 64 times>}}}} <repeats 51 times>, {pge = {{ste = {
+-		  0x248001, 0x248101, 0x248201, 0x248301, 0x248401, 0x248501,
+-		  0x248601, 0x248701, 0x248801, 0x248901, 0x248a01, 0x248b01,
+-		  0x248c01, 0x248d01, 0x248e01, 0x248f01, 0x249001, 0x249101,
+-		  0x249201, 0x249301, 0x249401, 0x249501, 0x249601, 0x249701,
+-		  0x249801, 0x249901, 0x249a01, 0x249b01, 0x249c01, 0x249d01,
+-		  0x249e01, 0x249f01, 0x24a001, 0x24a101, 0x24a201, 0x24a301,
+-		  0x24a401, 0x24a501, 0x24a601, 0x24a701, 0x24a801, 0x24a901,
+-		  0x24aa01, 0x24ab01, 0x24ac01, 0x24ad01, 0x24ae01, 0x24af01,
+-		  0x24b001, 0x24b101, 0x24b201, 0x24b301, 0x24b401, 0x24b501,
+-		  0x24b601, 0x24b701, 0x24b801, 0x24b901, 0x24ba01, 0x24bb01,
+-		  0x24bc01, 0x24bd01, 0x24be01, 0x24bf01}}}}, {pge = {{ste = {
+-		  0x0 <repeats 64 times>}}}} <repeats 11 times>}
+-
+- (*) The PTD last used by the instruction TLB miss handler is attached to DAMR4.
+- (*) The PTD last used by the data TLB miss handler is attached to DAMR5.
+-
+-     These can be viewed with the _ptd_i and _ptd_d GDB macros:
+-
+-	(gdb) _ptd_d
+-	$5 = {{pte = 0x0} <repeats 127 times>, {pte = 0x539b01}, {
+-	    pte = 0x0} <repeats 896 times>, {pte = 0x719303}, {pte = 0x6d5303}, {
+-	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
+-	    pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x6a1303}, {
+-	    pte = 0x0} <repeats 12 times>, {pte = 0x709303}, {pte = 0x0}, {pte = 0x0},
+-	  {pte = 0x6fd303}, {pte = 0x6f9303}, {pte = 0x6f5303}, {pte = 0x0}, {
+-	    pte = 0x6ed303}, {pte = 0x531b01}, {pte = 0x50db01}, {
+-	    pte = 0x0} <repeats 13 times>, {pte = 0x5303}, {pte = 0x7f5303}, {
+-	    pte = 0x509b01}, {pte = 0x505b01}, {pte = 0x7c9303}, {pte = 0x7b9303}, {
+-	    pte = 0x7b5303}, {pte = 0x7b1303}, {pte = 0x7ad303}, {pte = 0x0}, {
+-	    pte = 0x0}, {pte = 0x7a1303}, {pte = 0x0}, {pte = 0x795303}, {pte = 0x0}, {
+-	    pte = 0x78d303}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {pte = 0x0}, {
+-	    pte = 0x0}, {pte = 0x775303}, {pte = 0x771303}, {pte = 0x76d303}, {
+-	    pte = 0x0}, {pte = 0x765303}, {pte = 0x7c5303}, {pte = 0x501b01}, {
+-	    pte = 0x4f1b01}, {pte = 0x4edb01}, {pte = 0x0}, {pte = 0x4f9b01}, {
+-	    pte = 0x4fdb01}, {pte = 0x0} <repeats 2992 times>}
+diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
+index 6bc2ba2..8da724e 100644
+--- a/Documentation/gpio.txt
++++ b/Documentation/gpio.txt
+@@ -32,7 +32,7 @@ The exact capabilities of GPIOs vary between systems.  Common options:
+   - Input values are likewise readable (1, 0).  Some chips support readback
+     of pins configured as "output", which is very useful in such "wire-OR"
+     cases (to support bidirectional signaling).  GPIO controllers may have
+-    input de-glitch logic, sometimes with software controls.
++    input de-glitch/debounce logic, sometimes with software controls.
+ 
+   - Inputs can often be used as IRQ signals, often edge triggered but
+     sometimes level triggered.  Such IRQs may be configurable as system
+@@ -60,10 +60,13 @@ used on a board that's wired differently.  Only least-common-denominator
+ functionality can be very portable.  Other features are platform-specific,
+ and that can be critical for glue logic.
+ 
+-Plus, this doesn't define an implementation framework, just an interface.
++Plus, this doesn't require any implementation framework, just an interface.
+ One platform might implement it as simple inline functions accessing chip
+ registers; another might implement it by delegating through abstractions
+-used for several very different kinds of GPIO controller.
++used for several very different kinds of GPIO controller.  (There is some
++optional code supporting such an implementation strategy, described later
++in this document, but drivers acting as clients to the GPIO interface must
++not care how it's implemented.)
+ 
+ That said, if the convention is supported on their platform, drivers should
+ use it when possible.  Platforms should declare GENERIC_GPIO support in
+@@ -121,6 +124,11 @@ before tasking is enabled, as part of early board setup.
+ For output GPIOs, the value provided becomes the initial output value.
+ This helps avoid signal glitching during system startup.
+ 
++For compatibility with legacy interfaces to GPIOs, setting the direction
++of a GPIO implicitly requests that GPIO (see below) if it has not been
++requested already.  That compatibility may be removed in the future;
++explicitly requesting GPIOs is strongly preferred.
++
+ Setting the direction can fail if the GPIO number is invalid, or when
+ that particular GPIO can't be used in that mode.  It's generally a bad
+ idea to rely on boot firmware to have set the direction correctly, since
+@@ -133,6 +141,7 @@ Spinlock-Safe GPIO access
+ -------------------------
+ Most GPIO controllers can be accessed with memory read/write instructions.
+ That doesn't need to sleep, and can safely be done from inside IRQ handlers.
++(That includes hardirq contexts on RT kernels.)
+ 
+ Use these calls to access such GPIOs:
+ 
+@@ -145,7 +154,7 @@ Use these calls to access such GPIOs:
+ The values are boolean, zero for low, nonzero for high.  When reading the
+ value of an output pin, the value returned should be what's seen on the
+ pin ... that won't always match the specified output value, because of
+-issues including wire-OR and output latencies.
++issues including open-drain signaling and output latencies.
+ 
+ The get/set calls have no error returns because "invalid GPIO" should have
+ been reported earlier from gpio_direction_*().  However, note that not all
+@@ -170,7 +179,8 @@ get to the head of a queue to transmit a command and get its response.
+ This requires sleeping, which can't be done from inside IRQ handlers.
+ 
+ Platforms that support this type of GPIO distinguish them from other GPIOs
+-by returning nonzero from this call:
++by returning nonzero from this call (which requires a valid GPIO number,
++either explicitly or implicitly requested):
+ 
+ 	int gpio_cansleep(unsigned gpio);
+ 
+@@ -209,8 +219,11 @@ before tasking is enabled, as part of early board setup.
+ These calls serve two basic purposes.  One is marking the signals which
+ are actually in use as GPIOs, for better diagnostics; systems may have
+ several hundred potential GPIOs, but often only a dozen are used on any
+-given board.  Another is to catch conflicts between drivers, reporting
+-errors when drivers wrongly think they have exclusive use of that signal.
++given board.  Another is to catch conflicts, identifying errors when
++(a) two or more drivers wrongly think they have exclusive use of that
++signal, or (b) something wrongly believes it's safe to remove drivers
++needed to manage a signal that's in active use.  That is, requesting a
++GPIO can serve as a kind of lock.
+ 
+ These two calls are optional because not not all current Linux platforms
+ offer such functionality in their GPIO support; a valid implementation
+@@ -223,6 +236,9 @@ Note that requesting a GPIO does NOT cause it to be configured in any
+ way; it just marks that GPIO as in use.  Separate code must handle any
+ pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
+ 
++Also note that it's your responsibility to have stopped using a GPIO
++before you free it.
++
+ 
+ GPIOs mapped to IRQs
+ --------------------
+@@ -238,7 +254,7 @@ map between them using calls like:
+ 
+ Those return either the corresponding number in the other namespace, or
+ else a negative errno code if the mapping can't be done.  (For example,
+-some GPIOs can't used as IRQs.)  It is an unchecked error to use a GPIO
++some GPIOs can't be used as IRQs.)  It is an unchecked error to use a GPIO
+ number that wasn't set up as an input using gpio_direction_input(), or
+ to use an IRQ number that didn't originally come from gpio_to_irq().
+ 
+@@ -299,17 +315,110 @@ Related to multiplexing is configuration and enabling of the pullups or
+ pulldowns integrated on some platforms.  Not all platforms support them,
+ or support them in the same way; and any given board might use external
+ pullups (or pulldowns) so that the on-chip ones should not be used.
++(When a circuit needs 5 kOhm, on-chip 100 kOhm resistors won't do.)
+ 
+ There are other system-specific mechanisms that are not specified here,
+ like the aforementioned options for input de-glitching and wire-OR output.
+ Hardware may support reading or writing GPIOs in gangs, but that's usually
+ configuration dependent:  for GPIOs sharing the same bank.  (GPIOs are
+ commonly grouped in banks of 16 or 32, with a given SOC having several such
+-banks.)  Some systems can trigger IRQs from output GPIOs.  Code relying on
+-such mechanisms will necessarily be nonportable.
++banks.)  Some systems can trigger IRQs from output GPIOs, or read values
++from pins not managed as GPIOs.  Code relying on such mechanisms will
++necessarily be nonportable.
+ 
+-Dynamic definition of GPIOs is not currently supported; for example, as
++Dynamic definition of GPIOs is not currently standard; for example, as
+ a side effect of configuring an add-on board with some GPIO expanders.
+ 
+ These calls are purely for kernel space, but a userspace API could be built
+-on top of it.
++on top of them.
++
++
++GPIO implementor's framework (OPTIONAL)
++=======================================
++As noted earlier, there is an optional implementation framework making it
++easier for platforms to support different kinds of GPIO controller using
++the same programming interface.
++
++As a debugging aid, if debugfs is available a /sys/kernel/debug/gpio file
++will be found there.  That will list all the controllers registered through
++this framework, and the state of the GPIOs currently in use.
++
++
++Controller Drivers: gpio_chip
++-----------------------------
++In this framework each GPIO controller is packaged as a "struct gpio_chip"
++with information common to each controller of that type:
++
++ - methods to establish GPIO direction
++ - methods used to access GPIO values
++ - flag saying whether calls to its methods may sleep
++ - optional debugfs dump method (showing extra state like pullup config)
++ - label for diagnostics
++
++There is also per-instance data, which may come from device.platform_data:
++the number of its first GPIO, and how many GPIOs it exposes.
++
++The code implementing a gpio_chip should support multiple instances of the
++controller, possibly using the driver model.  That code will configure each
++gpio_chip and issue gpiochip_add().  Removing a GPIO controller should be
++rare; use gpiochip_remove() when it is unavoidable.
++
++Most often a gpio_chip is part of an instance-specific structure with state
++not exposed by the GPIO interfaces, such as addressing, power management,
++and more.  Chips such as codecs will have complex non-GPIO state,
++
++Any debugfs dump method should normally ignore signals which haven't been
++requested as GPIOs.  They can use gpiochip_is_requested(), which returns
++either NULL or the label associated with that GPIO when it was requested.
++
++
++Platform Support
++----------------
++To support this framework, a platform's Kconfig will "select HAVE_GPIO_LIB"
++and arrange that its <asm/gpio.h> includes <asm-generic/gpio.h> and defines
++three functions: gpio_get_value(), gpio_set_value(), and gpio_cansleep().
++They may also want to provide a custom value for ARCH_NR_GPIOS.
++
++Trivial implementations of those functions can directly use framework
++code, which always dispatches through the gpio_chip:
++
++  #define gpio_get_value	__gpio_get_value
++  #define gpio_set_value	__gpio_set_value
++  #define gpio_cansleep		__gpio_cansleep
++
++Fancier implementations could instead define those as inline functions with
++logic optimizing access to specific SOC-based GPIOs.  For example, if the
++referenced GPIO is the constant "12", getting or setting its value could
++cost as little as two or three instructions, never sleeping.  When such an
++optimization is not possible those calls must delegate to the framework
++code, costing at least a few dozen instructions.  For bitbanged I/O, such
++instruction savings can be significant.
++
++For SOCs, platform-specific code defines and registers gpio_chip instances
++for each bank of on-chip GPIOs.  Those GPIOs should be numbered/labeled to
++match chip vendor documentation, and directly match board schematics.  They
++may well start at zero and go up to a platform-specific limit.  Such GPIOs
++are normally integrated into platform initialization to make them always be
++available, from arch_initcall() or earlier; they can often serve as IRQs.
++
++
++Board Support
++-------------
++For external GPIO controllers -- such as I2C or SPI expanders, ASICs, multi
++function devices, FPGAs or CPLDs -- most often board-specific code handles
++registering controller devices and ensures that their drivers know what GPIO
++numbers to use with gpiochip_add().  Their numbers often start right after
++platform-specific GPIOs.
++
++For example, board setup code could create structures identifying the range
++of GPIOs that chip will expose, and passes them to each GPIO expander chip
++using platform_data.  Then the chip driver's probe() routine could pass that
++data to gpiochip_add().
++
++Initialization order can be important.  For example, when a device relies on
++an I2C-based GPIO, its probe() routine should only be called after that GPIO
++becomes available.  That may mean the device should not be registered until
++calls for that GPIO can work.  One way to address such dependencies is for
++such gpio_chip controllers to provide setup() and teardown() callbacks to
++board specific code; those board specific callbacks would register devices
++once all the necessary resources are available.
 diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801
 index fde4420..3bd9583 100644
 --- a/Documentation/i2c/busses/i2c-i801
@@ -1647,6 +6232,20 @@
   device 1106:3287   (VT8251)
   device 1106:8324   (CX700)
  
+diff --git a/Documentation/i2c/chips/pca9539 b/Documentation/i2c/chips/pca9539
+index c4fce6a..1d81c53 100644
+--- a/Documentation/i2c/chips/pca9539
++++ b/Documentation/i2c/chips/pca9539
+@@ -1,6 +1,9 @@
+ Kernel driver pca9539
+ =====================
+ 
++NOTE: this driver is deprecated and will be dropped soon, use
++drivers/gpio/pca9539.c instead.
++
+ Supported chips:
+   * Philips PCA9539
+     Prefix: 'pca9539'
 diff --git a/Documentation/i2c/chips/pcf8575 b/Documentation/i2c/chips/pcf8575
 new file mode 100644
 index 0000000..25f5698
@@ -1766,6 +6365,74 @@
  
    /* Magic definition of all other variables and things */
    I2C_CLIENT_INSMOD;
+diff --git a/Documentation/ia64/aliasing-test.c b/Documentation/ia64/aliasing-test.c
+index 773a814..d23610f 100644
+--- a/Documentation/ia64/aliasing-test.c
++++ b/Documentation/ia64/aliasing-test.c
+@@ -16,6 +16,7 @@
+ #include <fcntl.h>
+ #include <fnmatch.h>
+ #include <string.h>
++#include <sys/ioctl.h>
+ #include <sys/mman.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+@@ -65,7 +66,7 @@ int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
+ {
+ 	struct dirent **namelist;
+ 	char *name, *path2;
+-	int i, n, r, rc, result = 0;
++	int i, n, r, rc = 0, result = 0;
+ 	struct stat buf;
+ 
+ 	n = scandir(path, &namelist, 0, alphasort);
+@@ -113,7 +114,7 @@ skip:
+ 		free(namelist[i]);
+ 	}
+ 	free(namelist);
+-	return rc;
++	return result;
+ }
+ 
+ char buf[1024];
+@@ -149,7 +150,7 @@ int scan_rom(char *path, char *file)
+ {
+ 	struct dirent **namelist;
+ 	char *name, *path2;
+-	int i, n, r, rc, result = 0;
++	int i, n, r, rc = 0, result = 0;
+ 	struct stat buf;
+ 
+ 	n = scandir(path, &namelist, 0, alphasort);
+@@ -180,7 +181,7 @@ int scan_rom(char *path, char *file)
+ 			 * important thing is that no MCA happened.
+ 			 */
+ 			if (rc > 0)
+-				fprintf(stderr, "PASS: %s read %ld bytes\n", path2, rc);
++				fprintf(stderr, "PASS: %s read %d bytes\n", path2, rc);
+ 			else {
+ 				fprintf(stderr, "PASS: %s not readable\n", path2);
+ 				return rc;
+@@ -201,10 +202,10 @@ skip:
+ 		free(namelist[i]);
+ 	}
+ 	free(namelist);
+-	return rc;
++	return result;
+ }
+ 
+-int main()
++int main(void)
+ {
+ 	int rc;
+ 
+@@ -256,4 +257,6 @@ int main()
+ 	scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
+ 	scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
+ 	scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
++
++	return rc;
+ }
 diff --git a/Documentation/ide.txt b/Documentation/ide.txt
 index 1d50f23..94e2e3b 100644
 --- a/Documentation/ide.txt
@@ -2569,6 +7236,19 @@
 + *		a method by which we can achieve higher throughput when
 + *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
 + */
+diff --git a/Documentation/initrd.txt b/Documentation/initrd.txt
+index 74f68b3..1ba84f3 100644
+--- a/Documentation/initrd.txt
++++ b/Documentation/initrd.txt
+@@ -85,7 +85,7 @@ involve special block devices or loopbacks; you merely create a directory on
+ disk with the desired initrd content, cd to that directory, and run (as an
+ example):
+ 
+-find . | cpio --quiet -c -o | gzip -9 -n > /boot/imagefile.img
++find . | cpio --quiet -H newc -o | gzip -9 -n > /boot/imagefile.img
+ 
+ Examining the contents of an existing image file is just as simple:
+ 
 diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt
 index 5c7fbf9..c18363b 100644
 --- a/Documentation/ioctl-number.txt
@@ -2581,6 +7261,91 @@
  'p'	00-0F	linux/phantom.h		conflict! (OpenHaptics needs this)
  'p'	00-3F	linux/mc146818rtc.h	conflict!
  'p'	40-7F	linux/nvram.h
+diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/ja_JP/stable_kernel_rules.txt
+new file mode 100644
+index 0000000..17d8751
+--- /dev/null
++++ b/Documentation/ja_JP/stable_kernel_rules.txt
+@@ -0,0 +1,79 @@
++NOTE:
++This is Japanese translated version of "Documentation/stable_kernel_rules.txt".
++This one is maintained by Tsugikazu Shibata <tshibata at ab.jp.nec.com>
++and JF Project team <www.linux.or.jp/JF>.
++If you find difference with original file or problem in translation,
++please contact maintainer of this file or JF project.
++
++Please also note that purpose of this file is easier to read for non
++English natives and do no intended to fork. So, if you have any
++comment or update of this file, please try to update Original(English)
++file at first.
++
++==================================
++これは、
++linux-2.6.24/Documentation/stable_kernel_rules.txt
++の和訳です。
++
++翻訳団体: JF プロジェクト < http://www.linux.or.jp/JF/ >
++翻訳日: 2007/12/30
++翻訳è€
: Tsugikazu Shibata <tshibata at ab dot jp dot nec dot com>
++æ ¡æ­£è€
: 武井伸å
‰ã•ã‚“、<takei at webmasters dot gr dot jp>
++         かねこさん (Seiji Kaneko) <skaneko at a2 dot mbn dot or dot jp>
++         小林 é›
å
¸ã•ã‚“ (Masanori Kobayasi) <zap03216 at nifty dot ne dot jp>
++         野口さん (Kenji Noguchi) <tokyo246 at gmail dot com>
++         神宮信太郎さん <jin at libjingu dot jp>
++==================================
++
++ずっと知りたかった Linux 2.6 -stable リリースのå
¨ã¦
++
++"-stable" ツリーにどのような種類のパッチが受けå
¥ã‚Œã‚‰ã‚Œã‚‹ã‹ã€ã©ã®ã‚ˆã†ãª
++ものが受けå
¥ã‚Œã‚‰ã‚Œãªã„か、についての規則-
++
++ - 明らかに正しく、テストされているものでなければならない。
++ - 文脈(変更行の前後)を含めて 100 行より大きくてはいけない。
++ - ただ一個のことだけを修正しているべき。
++ - 皆を悩ませている本物のバグを修正しなければならない。("これはバグで
++   あるかもしれないが..." のようなものではない)
++ - ビルドエラー(CONFIG_BROKENになっているものを除く), oops, ハング、デー
++   タ破壊、現実のセキュリティ問題、その他 "ああ、これはダメだね"という
++   ようなものを修正しなければならない。短く言えば、重大な問題。
++ - どのように競合状æ
‹ãŒç™ºç”Ÿã™ã‚‹ã‹ã®èª¬æ˜Žã‚‚一緒に書かれていない限り、
++   "理論的には競合状æ
‹ã«ãªã‚‹"ようなものは不可。
++ - いかなる些細な修正も含めることはできない。(スペルの修正、空白のクリー
++   ンアップなど)
++ - 対応するサブシステムメンテナが受けå
¥ã‚ŒãŸã‚‚のでなければならない。
++ - Documentation/SubmittingPatches の規則に従ったものでなければならない。
++
++-stable ツリーにパッチを送付する手続き-
++
++ - 上記の規則に従っているかを確認した後に、stable at kernel.org にパッチ
++   を送る。
++ - 送信è€
はパッチがキューに受け付けられた際には ACK を、却下された場合
++   には NAK を受け取る。この反応は開発è€
たちのスケジュールによって、数
++   日かかる場合がある。
++ - もし受け取られたら、パッチは他の開発è€
たちのレビューのために
++   -stable キューに追加される。
++ - セキュリティパッチはこのエイリアス (stable at kernel.org) に送られるべ
++   きではなく、代わりに security at kernel.org のアドレスに送られる。
++
++レビューサイクル-
++
++ - -stable メンテナがレビューサイクルを決めるとき、パッチはレビュー委
++   員会とパッチが影響する領域のメンテナ(提供è€
がその領域のメンテナで無
++   い限り)に送られ、linux-kernel メーリングリストにCCされる。
++ - レビュー委員会は 48時間の間に ACK か NAK を出す。
++ - もしパッチが委員会のメンバから却下れるか、メンテナ達やメンバが気付
++   かなかった問題が持ちあがり、linux-kernel メンバがパッチに異議を唱え
++   た場合には、パッチはキューから削除される。
++ - レビューサイクルの最後に、ACK を受けたパッチは最新の -stable リリー
++   スに追加され、その後に新しい -stable リリースが行われる。
++ - セキュリティパッチは、通常のレビューサイクルを通らず、セキュリティ
++   カーネルチームから直接 -stable ツリーに受け付けられる。
++   この手続きの詳細については kernel security チームに問い合わせること。
++
++レビュー委員会-
++
++ - この委員会は、このタスクについて活動する多くのボランティアと、少数の
++   非ボランティアのカーネル開発è€
達で構成されている。
++
 diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
 index 616043a..649cb87 100644
 --- a/Documentation/kbuild/kconfig-language.txt
@@ -2736,7 +7501,7 @@
 +$ find . -name Kconfig\* | xargs grep -ns "depends on.*=.*||.*=" | grep -v orig
 +
 diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
-index c417877..cf38689 100644
+index c417877..8fd5aa4 100644
 --- a/Documentation/kernel-parameters.txt
 +++ b/Documentation/kernel-parameters.txt
 @@ -34,6 +34,7 @@ parameter is applicable:
@@ -2806,6 +7571,15 @@
  			Range: 0 - 8192
  			Default: 64
  
+@@ -523,7 +549,7 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			1 will print _a lot_ more information - normally
+ 			only useful to kernel developers.
+ 
+-	decnet=		[HW,NET]
++	decnet.addr=	[HW,NET]
+ 			Format: <area>[,<node>]
+ 			See also Documentation/networking/decnet.txt.
+ 
 @@ -562,6 +588,12 @@ and is between 256 and 4096 characters. It is defined in the file
  			See drivers/char/README.epca and
  			Documentation/digiepca.txt.
@@ -2838,7 +7612,17 @@
  
  	i8042.direct	[HW] Put keyboard port into non-translated mode
  	i8042.dumbkbd	[HW] Pretend that controller can only read data from
-@@ -786,6 +823,16 @@ and is between 256 and 4096 characters. It is defined in the file
+@@ -743,6 +780,9 @@ and is between 256 and 4096 characters. It is defined in the file
+ 			loop use the MONITOR/MWAIT idle loop anyways. Performance should be the same
+ 			as idle=poll.
+ 
++	ide-pci-generic.all-generic-ide [HW] (E)IDE subsystem
++			Claim all unknown PCI IDE storage controllers.
++
+ 	ignore_loglevel	[KNL]
+ 			Ignore loglevel setting - this will print /all/
+ 			kernel messages to the console. Useful for debugging.
+@@ -786,6 +826,16 @@ and is between 256 and 4096 characters. It is defined in the file
  			for translation below 32 bit and if not available
  			then look in the higher range.
  
@@ -2855,7 +7639,7 @@
  	io7=		[HW] IO7 for Marvel based alpha systems
  			See comment before marvel_specify_io7 in
  			arch/alpha/kernel/core_marvel.c.
-@@ -1051,6 +1098,11 @@ and is between 256 and 4096 characters. It is defined in the file
+@@ -1051,6 +1101,11 @@ and is between 256 and 4096 characters. It is defined in the file
  			Multi-Function General Purpose Timers on AMD Geode
  			platforms.
  
@@ -2867,7 +7651,7 @@
  	mga=		[HW,DRM]
  
  	mousedev.tap_time=
-@@ -1123,6 +1175,10 @@ and is between 256 and 4096 characters. It is defined in the file
+@@ -1123,6 +1178,10 @@ and is between 256 and 4096 characters. It is defined in the file
  			of returning the full 64-bit number.
  			The default is to return 64-bit inode numbers.
  
@@ -2878,7 +7662,7 @@
  	nmi_watchdog=	[KNL,BUGS=X86-32] Debugging features for SMP kernels
  
  	no387		[BUGS=X86-32] Tells the kernel to use the 387 maths
-@@ -1147,6 +1203,8 @@ and is between 256 and 4096 characters. It is defined in the file
+@@ -1147,6 +1206,8 @@ and is between 256 and 4096 characters. It is defined in the file
  
  	nodisconnect	[HW,SCSI,M68K] Disables SCSI disconnects.
  
@@ -2887,7 +7671,7 @@
  	noexec		[IA-64]
  
  	noexec		[X86-32,X86-64]
-@@ -1157,6 +1215,8 @@ and is between 256 and 4096 characters. It is defined in the file
+@@ -1157,6 +1218,8 @@ and is between 256 and 4096 characters. It is defined in the file
  			register save and restore. The kernel will only save
  			legacy floating-point registers on task switch.
  
@@ -2896,7 +7680,30 @@
  	nohlt		[BUGS=ARM]
  
  	no-hlt		[BUGS=X86-32] Tells the kernel that the hlt
-@@ -1593,7 +1653,13 @@ and is between 256 and 4096 characters. It is defined in the file
+@@ -1501,14 +1564,17 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	ramdisk_size=	[RAM] Sizes of RAM disks in kilobytes
+ 			See Documentation/ramdisk.txt.
+ 
+-	rcu.blimit=	[KNL,BOOT] Set maximum number of finished
+-			RCU callbacks to process in one batch.
++	rcupdate.blimit=	[KNL,BOOT]
++			Set maximum number of finished RCU callbacks to process
++			in one batch.
+ 
+-	rcu.qhimark=	[KNL,BOOT] Set threshold of queued
++	rcupdate.qhimark=	[KNL,BOOT]
++			Set threshold of queued
+ 			RCU callbacks over which batch limiting is disabled.
+ 
+-	rcu.qlowmark=	[KNL,BOOT] Set threshold of queued
+-			RCU callbacks below which batch limiting is re-enabled.
++	rcupdate.qlowmark=	[KNL,BOOT]
++			Set threshold of queued RCU callbacks below which
++			batch limiting is re-enabled.
+ 
+ 	rdinit=		[KNL]
+ 			Format: <full_path>
+@@ -1593,7 +1659,13 @@ and is between 256 and 4096 characters. It is defined in the file
  			Format: <vendor>:<model>:<flags>
  			(flags are integer value)
  
@@ -2911,6 +7718,26 @@
  
  	scsi_mod.scan=	[SCSI] sync (default) scans SCSI busses as they are
  			discovered.  async scans them in kernel threads,
+@@ -1822,9 +1894,6 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.)
+ 			See Documentation/scsi/st.txt.
+ 
+-	st0x=		[HW,SCSI]
+-			See header of drivers/scsi/seagate.c.
+-
+ 	sti=		[PARISC,HW]
+ 			Format: <num>
+ 			Set the STI (builtin display/keyboard on the HP-PARISC
+@@ -1909,9 +1978,6 @@ and is between 256 and 4096 characters. It is defined in the file
+ 	tipar.delay=	[HW,PPT]
+ 			Set inter-bit delay in microseconds (default 10).
+ 
+-	tmc8xx=		[HW,SCSI]
+-			See header of drivers/scsi/seagate.c.
+-
+ 	tmscsim=	[HW,SCSI]
+ 			See comment before function dc390_setup() in
+ 			drivers/scsi/tmscsim.c.
 @@ -1960,6 +2026,11 @@ and is between 256 and 4096 characters. It is defined in the file
  			vdso=1: enable VDSO (default)
  			vdso=0: disable VDSO mapping
@@ -3523,10 +8350,19 @@
  3. Configuring Kprobes
  
 diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
-index 9b0e322..6c8a238 100644
+index 9b0e322..0f23d67 100644
 --- a/Documentation/lguest/lguest.c
 +++ b/Documentation/lguest/lguest.c
-@@ -79,6 +79,9 @@ static void *guest_base;
+@@ -34,6 +34,8 @@
+ #include <zlib.h>
+ #include <assert.h>
+ #include <sched.h>
++#include <limits.h>
++#include <stddef.h>
+ #include "linux/lguest_launcher.h"
+ #include "linux/virtio_config.h"
+ #include "linux/virtio_net.h"
+@@ -79,6 +81,9 @@ static void *guest_base;
  /* The maximum guest physical address allowed, and maximum possible. */
  static unsigned long guest_limit, guest_max;
  
@@ -3536,6 +8372,23 @@
  /* This is our list of devices. */
  struct device_list
  {
+@@ -96,13 +101,11 @@ struct device_list
+ 	/* The descriptor page for the devices. */
+ 	u8 *descpage;
+ 
+-	/* The tail of the last descriptor. */
+-	unsigned int desc_used;
+-
+ 	/* A single linked list of devices. */
+ 	struct device *dev;
+-	/* ... And an end pointer so we can easily append new devices */
+-	struct device **lastdev;
++	/* And a pointer to the last device for easy append and also for
++	 * configuration appending. */
++	struct device *lastdev;
+ };
+ 
+ /* The list of Guest devices, based on command line arguments. */
 @@ -153,6 +156,9 @@ struct virtqueue
  	void (*handle_output)(int fd, struct virtqueue *me);
  };
@@ -3546,7 +8399,23 @@
  /* Since guest is UP and we don't run at the same time, we don't need barriers.
   * But I include them in the code in case others copy it. */
  #define wmb()
-@@ -554,7 +560,7 @@ static void wake_parent(int pipefd, int lguest_fd)
+@@ -185,7 +191,14 @@ static void *_convert(struct iovec *iov, size_t size, size_t align,
+ #define cpu_to_le64(v64) (v64)
+ #define le16_to_cpu(v16) (v16)
+ #define le32_to_cpu(v32) (v32)
+-#define le64_to_cpu(v32) (v64)
++#define le64_to_cpu(v64) (v64)
++
++/* The device virtqueue descriptors are followed by feature bitmasks. */
++static u8 *get_feature_bits(struct device *dev)
++{
++	return (u8 *)(dev->desc + 1)
++		+ dev->desc->num_vq * sizeof(struct lguest_vqconfig);
++}
+ 
+ /*L:100 The Launcher code itself takes us out into userspace, that scary place
+  * where pointers run wild and free!  Unfortunately, like most userspace
+@@ -554,7 +567,7 @@ static void wake_parent(int pipefd, int lguest_fd)
  			else
  				FD_CLR(-fd - 1, &devices.infds);
  		} else /* Send LHREQ_BREAK command. */
@@ -3555,7 +8424,309 @@
  	}
  }
  
-@@ -1489,7 +1495,9 @@ static void setup_block_file(const char *filename)
+@@ -908,21 +921,58 @@ static void enable_fd(int fd, struct virtqueue *vq)
+ 	write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd));
+ }
+ 
++/* Resetting a device is fairly easy. */
++static void reset_device(struct device *dev)
++{
++	struct virtqueue *vq;
++
++	verbose("Resetting device %s\n", dev->name);
++	/* Clear the status. */
++	dev->desc->status = 0;
++
++	/* Clear any features they've acked. */
++	memset(get_feature_bits(dev) + dev->desc->feature_len, 0,
++	       dev->desc->feature_len);
++
++	/* Zero out the virtqueues. */
++	for (vq = dev->vq; vq; vq = vq->next) {
++		memset(vq->vring.desc, 0,
++		       vring_size(vq->config.num, getpagesize()));
++		vq->last_avail_idx = 0;
++	}
++}
++
+ /* This is the generic routine we call when the Guest uses LHCALL_NOTIFY. */
+ static void handle_output(int fd, unsigned long addr)
+ {
+ 	struct device *i;
+ 	struct virtqueue *vq;
+ 
+-	/* Check each virtqueue. */
++	/* Check each device and virtqueue. */
+ 	for (i = devices.dev; i; i = i->next) {
++		/* Notifications to device descriptors reset the device. */
++		if (from_guest_phys(addr) == i->desc) {
++			reset_device(i);
++			return;
++		}
++
++		/* Notifications to virtqueues mean output has occurred. */
+ 		for (vq = i->vq; vq; vq = vq->next) {
+-			if (vq->config.pfn == addr/getpagesize()
+-			    && vq->handle_output) {
+-				verbose("Output to %s\n", vq->dev->name);
+-				vq->handle_output(fd, vq);
++			if (vq->config.pfn != addr/getpagesize())
++				continue;
++
++			/* Guest should acknowledge (and set features!)  before
++			 * using the device. */
++			if (i->desc->status == 0) {
++				warnx("%s gave early output", i->name);
+ 				return;
+ 			}
++
++			if (strcmp(vq->dev->name, "console") != 0)
++				verbose("Output to %s\n", vq->dev->name);
++			if (vq->handle_output)
++				vq->handle_output(fd, vq);
++			return;
+ 		}
+ 	}
+ 
+@@ -980,54 +1030,44 @@ static void handle_input(int fd)
+  *
+  * All devices need a descriptor so the Guest knows it exists, and a "struct
+  * device" so the Launcher can keep track of it.  We have common helper
+- * routines to allocate them.
+- *
+- * This routine allocates a new "struct lguest_device_desc" from descriptor
+- * table just above the Guest's normal memory.  It returns a pointer to that
+- * descriptor. */
+-static struct lguest_device_desc *new_dev_desc(u16 type)
+-{
+-	struct lguest_device_desc *d;
++ * routines to allocate and manage them. */
+ 
+-	/* We only have one page for all the descriptors. */
+-	if (devices.desc_used + sizeof(*d) > getpagesize())
+-		errx(1, "Too many devices");
+-
+-	/* We don't need to set config_len or status: page is 0 already. */
+-	d = (void *)devices.descpage + devices.desc_used;
+-	d->type = type;
+-	devices.desc_used += sizeof(*d);
+-
+-	return d;
++/* The layout of the device page is a "struct lguest_device_desc" followed by a
++ * number of virtqueue descriptors, then two sets of feature bits, then an
++ * array of configuration bytes.  This routine returns the configuration
++ * pointer. */
++static u8 *device_config(const struct device *dev)
++{
++	return (void *)(dev->desc + 1)
++		+ dev->desc->num_vq * sizeof(struct lguest_vqconfig)
++		+ dev->desc->feature_len * 2;
+ }
+ 
+-/* Each device descriptor is followed by some configuration information.
+- * Each configuration field looks like: u8 type, u8 len, [... len bytes...].
+- *
+- * This routine adds a new field to an existing device's descriptor.  It only
+- * works for the last device, but that's OK because that's how we use it. */
+-static void add_desc_field(struct device *dev, u8 type, u8 len, const void *c)
++/* This routine allocates a new "struct lguest_device_desc" from descriptor
++ * table page just above the Guest's normal memory.  It returns a pointer to
++ * that descriptor. */
++static struct lguest_device_desc *new_dev_desc(u16 type)
+ {
+-	/* This is the last descriptor, right? */
+-	assert(devices.descpage + devices.desc_used
+-	       == (u8 *)(dev->desc + 1) + dev->desc->config_len);
++	struct lguest_device_desc d = { .type = type };
++	void *p;
+ 
+-	/* We only have one page of device descriptions. */
+-	if (devices.desc_used + 2 + len > getpagesize())
+-		errx(1, "Too many devices");
++	/* Figure out where the next device config is, based on the last one. */
++	if (devices.lastdev)
++		p = device_config(devices.lastdev)
++			+ devices.lastdev->desc->config_len;
++	else
++		p = devices.descpage;
+ 
+-	/* Copy in the new config header: type then length. */
+-	devices.descpage[devices.desc_used++] = type;
+-	devices.descpage[devices.desc_used++] = len;
+-	memcpy(devices.descpage + devices.desc_used, c, len);
+-	devices.desc_used += len;
++	/* We only have one page for all the descriptors. */
++	if (p + sizeof(d) > (void *)devices.descpage + getpagesize())
++		errx(1, "Too many devices");
+ 
+-	/* Update the device descriptor length: two byte head then data. */
+-	dev->desc->config_len += 2 + len;
++	/* p might not be aligned, so we memcpy in. */
++	return memcpy(p, &d, sizeof(d));
+ }
+ 
+-/* This routine adds a virtqueue to a device.  We specify how many descriptors
+- * the virtqueue is to have. */
++/* Each device descriptor is followed by the description of its virtqueues.  We
++ * specify how many descriptors the virtqueue is to have. */
+ static void add_virtqueue(struct device *dev, unsigned int num_descs,
+ 			  void (*handle_output)(int fd, struct virtqueue *me))
+ {
+@@ -1053,9 +1093,15 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
+ 	/* Initialize the vring. */
+ 	vring_init(&vq->vring, num_descs, p, getpagesize());
+ 
+-	/* Add the configuration information to this device's descriptor. */
+-	add_desc_field(dev, VIRTIO_CONFIG_F_VIRTQUEUE,
+-		       sizeof(vq->config), &vq->config);
++	/* Append virtqueue to this device's descriptor.  We use
++	 * device_config() to get the end of the device's current virtqueues;
++	 * we check that we haven't added any config or feature information
++	 * yet, otherwise we'd be overwriting them. */
++	assert(dev->desc->config_len == 0 && dev->desc->feature_len == 0);
++	memcpy(device_config(dev), &vq->config, sizeof(vq->config));
++	dev->desc->num_vq++;
++
++	verbose("Virtqueue page %#lx\n", to_guest_phys(p));
+ 
+ 	/* Add to tail of list, so dev->vq is first vq, dev->vq->next is
+ 	 * second.  */
+@@ -1066,11 +1112,41 @@ static void add_virtqueue(struct device *dev, unsigned int num_descs,
+ 	 * virtqueue. */
+ 	vq->handle_output = handle_output;
+ 
+-	/* Set the "Don't Notify Me" flag if we don't have a handler */
++	/* As an optimization, set the advisory "Don't Notify Me" flag if we
++	 * don't have a handler */
+ 	if (!handle_output)
+ 		vq->vring.used->flags = VRING_USED_F_NO_NOTIFY;
+ }
+ 
++/* The first half of the feature bitmask is for us to advertise features.  The
++ * second half if for the Guest to accept features. */
++static void add_feature(struct device *dev, unsigned bit)
++{
++	u8 *features = get_feature_bits(dev);
++
++	/* We can't extend the feature bits once we've added config bytes */
++	if (dev->desc->feature_len <= bit / CHAR_BIT) {
++		assert(dev->desc->config_len == 0);
++		dev->desc->feature_len = (bit / CHAR_BIT) + 1;
++	}
++
++	features[bit / CHAR_BIT] |= (1 << (bit % CHAR_BIT));
++}
++
++/* This routine sets the configuration fields for an existing device's
++ * descriptor.  It only works for the last device, but that's OK because that's
++ * how we use it. */
++static void set_config(struct device *dev, unsigned len, const void *conf)
++{
++	/* Check we haven't overflowed our single page. */
++	if (device_config(dev) + len > devices.descpage + getpagesize())
++		errx(1, "Too many devices");
++
++	/* Copy in the config information, and store the length. */
++	memcpy(device_config(dev), conf, len);
++	dev->desc->config_len = len;
++}
++
+ /* This routine does all the creation and setup of a new device, including
+  * calling new_dev_desc() to allocate the descriptor and device memory. */
+ static struct device *new_device(const char *name, u16 type, int fd,
+@@ -1078,14 +1154,6 @@ static struct device *new_device(const char *name, u16 type, int fd,
+ {
+ 	struct device *dev = malloc(sizeof(*dev));
+ 
+-	/* Append to device list.  Prepending to a single-linked list is
+-	 * easier, but the user expects the devices to be arranged on the bus
+-	 * in command-line order.  The first network device on the command line
+-	 * is eth0, the first block device /dev/vda, etc. */
+-	*devices.lastdev = dev;
+-	dev->next = NULL;
+-	devices.lastdev = &dev->next;
+-
+ 	/* Now we populate the fields one at a time. */
+ 	dev->fd = fd;
+ 	/* If we have an input handler for this file descriptor, then we add it
+@@ -1096,6 +1164,17 @@ static struct device *new_device(const char *name, u16 type, int fd,
+ 	dev->handle_input = handle_input;
+ 	dev->name = name;
+ 	dev->vq = NULL;
++
++	/* Append to device list.  Prepending to a single-linked list is
++	 * easier, but the user expects the devices to be arranged on the bus
++	 * in command-line order.  The first network device on the command line
++	 * is eth0, the first block device /dev/vda, etc. */
++	if (devices.lastdev)
++		devices.lastdev->next = dev;
++	else
++		devices.dev = dev;
++	devices.lastdev = dev;
++
+ 	return dev;
+ }
+ 
+@@ -1220,7 +1299,7 @@ static void setup_tun_net(const char *arg)
+ 	int netfd, ipfd;
+ 	u32 ip;
+ 	const char *br_name = NULL;
+-	u8 hwaddr[6];
++	struct virtio_net_config conf;
+ 
+ 	/* We open the /dev/net/tun device and tell it we want a tap device.  A
+ 	 * tap device is like a tun device, only somehow different.  To tell
+@@ -1259,12 +1338,13 @@ static void setup_tun_net(const char *arg)
+ 		ip = str2ip(arg);
+ 
+ 	/* Set up the tun device, and get the mac address for the interface. */
+-	configure_device(ipfd, ifr.ifr_name, ip, hwaddr);
++	configure_device(ipfd, ifr.ifr_name, ip, conf.mac);
+ 
+ 	/* Tell Guest what MAC address to use. */
+-	add_desc_field(dev, VIRTIO_CONFIG_NET_MAC_F, sizeof(hwaddr), hwaddr);
++	add_feature(dev, VIRTIO_NET_F_MAC);
++	set_config(dev, sizeof(conf), &conf);
+ 
+-	/* We don't seed the socket any more; setup is done. */
++	/* We don't need the socket any more; setup is done. */
+ 	close(ipfd);
+ 
+ 	verbose("device %u: tun net %u.%u.%u.%u\n",
+@@ -1452,8 +1532,7 @@ static void setup_block_file(const char *filename)
+ 	struct device *dev;
+ 	struct vblk_info *vblk;
+ 	void *stack;
+-	u64 cap;
+-	unsigned int val;
++	struct virtio_blk_config conf;
+ 
+ 	/* This is the pipe the I/O thread will use to tell us I/O is done. */
+ 	pipe(p);
+@@ -1471,14 +1550,18 @@ static void setup_block_file(const char *filename)
+ 	vblk->fd = open_or_die(filename, O_RDWR|O_LARGEFILE);
+ 	vblk->len = lseek64(vblk->fd, 0, SEEK_END);
+ 
++	/* We support barriers. */
++	add_feature(dev, VIRTIO_BLK_F_BARRIER);
++
+ 	/* Tell Guest how many sectors this device has. */
+-	cap = cpu_to_le64(vblk->len / 512);
+-	add_desc_field(dev, VIRTIO_CONFIG_BLK_F_CAPACITY, sizeof(cap), &cap);
++	conf.capacity = cpu_to_le64(vblk->len / 512);
+ 
+ 	/* Tell Guest not to put in too many descriptors at once: two are used
+ 	 * for the in and out elements. */
+-	val = cpu_to_le32(VIRTQUEUE_NUM - 2);
+-	add_desc_field(dev, VIRTIO_CONFIG_BLK_F_SEG_MAX, sizeof(val), &val);
++	add_feature(dev, VIRTIO_BLK_F_SEG_MAX);
++	conf.seg_max = cpu_to_le32(VIRTQUEUE_NUM - 2);
++
++	set_config(dev, sizeof(conf), &conf);
+ 
+ 	/* The I/O thread writes to this end of the pipe when done. */
+ 	vblk->done_fd = p[1];
+@@ -1489,7 +1572,9 @@ static void setup_block_file(const char *filename)
  
  	/* Create stack for thread and run it */
  	stack = malloc(32768);
@@ -3566,11 +8737,13 @@
  		err(1, "Creating clone");
  
  	/* We don't need to keep the I/O thread's end of the pipes open. */
-@@ -1499,7 +1507,21 @@ static void setup_block_file(const char *filename)
+@@ -1497,9 +1582,23 @@ static void setup_block_file(const char *filename)
+ 	close(vblk->workpipe[0]);
+ 
  	verbose("device %u: virtblock %llu sectors\n",
- 		devices.device_num, cap);
- }
--/* That's the end of device setup. */
+-		devices.device_num, cap);
++		devices.device_num, le64_to_cpu(conf.capacity));
++}
 +/* That's the end of device setup. :*/
 +
 +/* Reboot */
@@ -3585,11 +8758,12 @@
 +		close(i);
 +	execv(main_args[0], main_args);
 +	err(1, "Could not exec %s", main_args[0]);
-+}
+ }
+-/* That's the end of device setup. */
  
  /*L:220 Finally we reach the core of the Launcher, which runs the Guest, serves
   * its input and output, and finally, lays it to rest. */
-@@ -1511,7 +1533,8 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
+@@ -1511,7 +1610,8 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
  		int readval;
  
  		/* We read from the /dev/lguest device to run the Guest. */
@@ -3599,7 +8773,7 @@
  
  		/* One unsigned long means the Guest did HCALL_NOTIFY */
  		if (readval == sizeof(notify_addr)) {
-@@ -1521,16 +1544,23 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
+@@ -1521,16 +1621,23 @@ static void __attribute__((noreturn)) run_guest(int lguest_fd)
  		/* ENOENT means the Guest died.  Reading tells us why. */
  		} else if (errno == ENOENT) {
  			char reason[1024] = { 0 };
@@ -3625,7 +8799,7 @@
  			err(1, "Resetting break");
  	}
  }
-@@ -1571,6 +1601,12 @@ int main(int argc, char *argv[])
+@@ -1571,17 +1678,24 @@ int main(int argc, char *argv[])
  	/* If they specify an initrd file to load. */
  	const char *initrd_name = NULL;
  
@@ -3638,8 +8812,16 @@
  	/* First we initialize the device list.  Since console and network
  	 * device receive input from a file descriptor, we keep an fdset
  	 * (infds) and the maximum fd number (max_infd) with the head of the
-@@ -1582,6 +1618,7 @@ int main(int argc, char *argv[])
- 	devices.lastdev = &devices.dev;
+-	 * list.  We also keep a pointer to the last device, for easy appending
+-	 * to the list.  Finally, we keep the next interrupt number to hand out
+-	 * (1: remember that 0 is used by the timer). */
++	 * list.  We also keep a pointer to the last device.  Finally, we keep
++	 * the next interrupt number to hand out (1: remember that 0 is used by
++	 * the timer). */
+ 	FD_ZERO(&devices.infds);
+ 	devices.max_infd = -1;
+-	devices.lastdev = &devices.dev;
++	devices.lastdev = NULL;
  	devices.next_irq = 1;
  
 +	cpu_id = 0;
@@ -4848,6 +10030,19 @@
  Notes
  =====
  
+diff --git a/Documentation/networking/decnet.txt b/Documentation/networking/decnet.txt
+index badb748..d896895 100644
+--- a/Documentation/networking/decnet.txt
++++ b/Documentation/networking/decnet.txt
+@@ -60,7 +60,7 @@ operation of the local communications in any other way though.
+ 
+ The kernel command line takes options looking like the following:
+ 
+-    decnet=1,2
++    decnet.addr=1,2
+ 
+ the two numbers are the node address 1,2 = 1.2 For 2.2.xx kernels
+ and early 2.3.xx kernels, you must use a comma when specifying the
 diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
 index 6f7872b..17a6e46 100644
 --- a/Documentation/networking/ip-sysctl.txt
@@ -5088,6 +10283,86 @@
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  Converting a driver from using I/O Port space to using MMIO space
+diff --git a/Documentation/pcmcia/driver-changes.txt b/Documentation/pcmcia/driver-changes.txt
+index 4739c5c..96f155e 100644
+--- a/Documentation/pcmcia/driver-changes.txt
++++ b/Documentation/pcmcia/driver-changes.txt
+@@ -33,8 +33,8 @@ This file details changes in 2.6 which affect PCMCIA card driver authors:
+    and can be used (e.g. for SET_NETDEV_DEV) by using
+    handle_to_dev(client_handle_t * handle).
+ 
+-* Convert internal I/O port addresses to unsigned long (as of 2.6.11)
+-   ioaddr_t should be replaced by kio_addr_t in PCMCIA card drivers.
++* Convert internal I/O port addresses to unsigned int (as of 2.6.11)
++   ioaddr_t should be replaced by unsigned int in PCMCIA card drivers.
+ 
+ * irq_mask and irq_list parameters (as of 2.6.11)
+    The irq_mask and irq_list parameters should no longer be used in
+diff --git a/Documentation/pm_qos_interface.txt b/Documentation/pm_qos_interface.txt
+new file mode 100644
+index 0000000..49adb1a
+--- /dev/null
++++ b/Documentation/pm_qos_interface.txt
+@@ -0,0 +1,59 @@
++PM quality of Service interface.
++
++This interface provides a kernel and user mode interface for registering
++performance expectations by drivers, subsystems and user space applications on
++one of the parameters.
++
++Currently we have {cpu_dma_latency, network_latency, network_throughput} as the
++initial set of pm_qos parameters.
++
++The infrastructure exposes multiple misc device nodes one per implemented
++parameter.  The set of parameters implement is defined by pm_qos_power_init()
++and pm_qos_params.h.  This is done because having the available parameters
++being runtime configurable or changeable from a driver was seen as too easy to
++abuse.
++
++For each parameter a list of performance requirements is maintained along with
++an aggregated target value.  The aggregated target value is updated with
++changes to the requirement list or elements of the list.  Typically the
++aggregated target value is simply the max or min of the requirement values held
++in the parameter list elements.
++
++From kernel mode the use of this interface is simple:
++pm_qos_add_requirement(param_id, name, target_value):
++Will insert a named element in the list for that identified PM_QOS parameter
++with the target value.  Upon change to this list the new target is recomputed
++and any registered notifiers are called only if the target value is now
++different.
++
++pm_qos_update_requirement(param_id, name, new_target_value):
++Will search the list identified by the param_id for the named list element and
++then update its target value, calling the notification tree if the aggregated
++target is changed.  with that name is already registered.
++
++pm_qos_remove_requirement(param_id, name):
++Will search the identified list for the named element and remove it, after
++removal it will update the aggregate target and call the notification tree if
++the target was changed as a result of removing the named requirement.
++
++
++From user mode:
++Only processes can register a pm_qos requirement.  To provide for automatic
++cleanup for process the interface requires the process to register its
++parameter requirements in the following way:
++
++To register the default pm_qos target for the specific parameter, the process
++must open one of /dev/[cpu_dma_latency, network_latency, network_throughput]
++
++As long as the device node is held open that process has a registered
++requirement on the parameter.  The name of the requirement is "process_<PID>"
++derived from the current->pid from within the open system call.
++
++To change the requested target value the process needs to write a s32 value to
++the open device node.  This translates to a pm_qos_update_requirement call.
++
++To remove the user mode request for a target value simply close the device
++node.
++
++
++
 diff --git a/Documentation/pnp.txt b/Documentation/pnp.txt
 index 481faf5..a327db6 100644
 --- a/Documentation/pnp.txt
@@ -6946,6 +12221,34 @@
 -Please try these options and post any problems/successes to me.
 -
 -Alan Hourihane <alanh at fairlite.demon.co.uk>
+diff --git a/Documentation/smp.txt b/Documentation/smp.txt
+deleted file mode 100644
+index 82fc50b..0000000
+--- a/Documentation/smp.txt
++++ /dev/null
+@@ -1,22 +0,0 @@
+-To set up SMP
+-
+-Configure the kernel and answer Y to CONFIG_SMP.
+-
+-If you are using LILO, it is handy to have both SMP and non-SMP
+-kernel images on hand. Edit /etc/lilo.conf to create an entry
+-for another kernel image called "linux-smp" or something.
+-
+-The next time you compile the kernel, when running a SMP kernel,
+-edit linux/Makefile and change "MAKE=make" to "MAKE=make -jN"
+-(where N = number of CPU + 1, or if you have tons of memory/swap
+- you can just use "-j" without a number). Feel free to experiment
+-with this one.
+-
+-Of course you should time how long each build takes :-)
+-Example:
+-   make config
+-   time -v sh -c 'make clean install modules modules_install'
+-
+-If you are using some Compaq MP compliant machines you will need to set
+-the operating system in the BIOS settings to "Unixware" - don't ask me
+-why Compaqs don't work otherwise.
 diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
 index 4b48c2e..e985cf5 100644
 --- a/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -10632,6 +15935,31 @@
  
   Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
  
+diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
+index 6f31f0a..24eac1b 100644
+--- a/Documentation/sysctl/vm.txt
++++ b/Documentation/sysctl/vm.txt
+@@ -22,6 +22,7 @@ Currently, these files are in /proc/sys/vm:
+ - dirty_background_ratio
+ - dirty_expire_centisecs
+ - dirty_writeback_centisecs
++- highmem_is_dirtyable   (only if CONFIG_HIGHMEM set)
+ - max_map_count
+ - min_free_kbytes
+ - laptop_mode
+@@ -40,9 +41,9 @@ Currently, these files are in /proc/sys/vm:
+ ==============================================================
+ 
+ dirty_ratio, dirty_background_ratio, dirty_expire_centisecs,
+-dirty_writeback_centisecs, vfs_cache_pressure, laptop_mode,
+-block_dump, swap_token_timeout, drop-caches,
+-hugepages_treat_as_movable:
++dirty_writeback_centisecs, highmem_is_dirtyable,
++vfs_cache_pressure, laptop_mode, block_dump, swap_token_timeout,
++drop-caches, hugepages_treat_as_movable:
+ 
+ See Documentation/filesystems/proc.txt
+ 
 diff --git a/Documentation/usb/gadget_printer.txt b/Documentation/usb/gadget_printer.txt
 new file mode 100644
 index 0000000..ad995bf
@@ -12344,6 +17672,28 @@
  
  Look at the writable files. Writing 1 to them will enable the
  corresponding debug option. All options can be set on a slab that does
+diff --git a/Documentation/x86_64/00-INDEX b/Documentation/x86_64/00-INDEX
+new file mode 100644
+index 0000000..92fc20a
+--- /dev/null
++++ b/Documentation/x86_64/00-INDEX
+@@ -0,0 +1,16 @@
++00-INDEX
++	- This file
++boot-options.txt
++	- AMD64-specific boot options.
++cpu-hotplug-spec
++	- Firmware support for CPU hotplug under Linux/x86-64
++fake-numa-for-cpusets
++	- Using numa=fake and CPUSets for Resource Management
++kernel-stacks
++	- Context-specific per-processor interrupt stacks.
++machinecheck
++	- Configurable sysfs parameters for the x86-64 machine check code.
++mm.txt
++	- Memory layout of x86-64 (4 level page tables, 46 bits physical).
++uefi.txt
++	- Booting Linux via Unified Extensible Firmware Interface.
 diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
 index 9453118..34abae4 100644
 --- a/Documentation/x86_64/boot-options.txt
@@ -14247,10 +19597,24 @@
 +参考Satyam Sharma,Johannes Stezenbach,Jesper Juhl,Heikki Orsila,
 +H. Peter Anvin,Philipp Hahn和Stefan Richter的意见改善了本档。
 diff --git a/MAINTAINERS b/MAINTAINERS
-index 2340cfb..58b1603 100644
+index 2340cfb..4f3da8b 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
-@@ -646,6 +646,17 @@ M:	ecashin at coraid.com
+@@ -84,13 +84,6 @@ S: Status, one of the following:
+ 			it has been replaced by a better system and you
+ 			should be using that.
+ 
+-3C359 NETWORK DRIVER
+-P:	Mike Phillips
+-M:	mikep at linuxtr.net
+-L:	netdev at vger.kernel.org
+-W:	http://www.linuxtr.net
+-S:	Maintained
+-
+ 3C505 NETWORK DRIVER
+ P:	Philip Blundell
+ M:	philb at gnu.org
+@@ -646,6 +639,17 @@ M:	ecashin at coraid.com
  W:	http://www.coraid.com/support/linux
  S:	Supported
  
@@ -14268,7 +19632,7 @@
  ATL1 ETHERNET DRIVER
  P:	Jay Cliburn
  M:	jcliburn at gmail.com
-@@ -758,22 +769,20 @@ S:	Supported
+@@ -758,22 +762,20 @@ S:	Supported
  
  BLACKFIN RTC DRIVER
  P:	Mike Frysinger
@@ -14293,7 +19657,7 @@
  M:	vapier.adi at gmail.com
  L:	uclinux-dist-devel at blackfin.uclinux.org (subscribers-only)
  W:	http://blackfin.uclinux.org
-@@ -811,7 +820,7 @@ P:	Stefano Brivio
+@@ -811,7 +813,7 @@ P:	Stefano Brivio
  M:	stefano.brivio at polimi.it
  L:	linux-wireless at vger.kernel.org
  W:	http://bcm43xx.berlios.de/
@@ -14302,7 +19666,16 @@
  
  BEFS FILE SYSTEM
  P:	Sergey S. Kostyliov
-@@ -984,6 +993,15 @@ M:	corbet at lwn.net
+@@ -930,8 +932,6 @@ M:	maxk at qualcomm.com
+ S:	Maintained
+ 
+ BONDING DRIVER
+-P:	Chad Tindel
+-M:	ctindel at users.sourceforge.net
+ P:	Jay Vosburgh
+ M:	fubar at us.ibm.com
+ L:	bonding-devel at lists.sourceforge.net
+@@ -984,6 +984,15 @@ M:	corbet at lwn.net
  L:	video4linux-list at redhat.com
  S:	Maintained
  
@@ -14318,7 +19691,7 @@
  CALGARY x86-64 IOMMU
  P:	Muli Ben-Yehuda
  M:	muli at il.ibm.com
-@@ -1577,7 +1595,7 @@ P:	Alexander Viro
+@@ -1577,7 +1586,7 @@ P:	Alexander Viro
  M:	viro at zeniv.linux.org.uk
  S:	Maintained
  
@@ -14327,7 +19700,7 @@
  P:	Kristian Hoegsberg, Stefan Richter
  M:	krh at redhat.com, stefanr at s5r6.in-berlin.de
  L:	linux1394-devel at lists.sourceforge.net
-@@ -1899,7 +1917,7 @@ L:	linux-ide at vger.kernel.org
+@@ -1899,7 +1908,7 @@ L:	linux-ide at vger.kernel.org
  L:	linux-scsi at vger.kernel.org
  S:	Orphan
  
@@ -14336,7 +19709,7 @@
  P:	Ben Collins
  M:	ben.collins at ubuntu.com
  P:	Stefan Richter
-@@ -2029,10 +2047,12 @@ W:	http://sourceforge.net/projects/e1000/
+@@ -2029,10 +2038,12 @@ W:	http://sourceforge.net/projects/e1000/
  S:	Supported
  
  INTEL PRO/WIRELESS 2100 NETWORK CONNECTION SUPPORT
@@ -14350,7 +19723,7 @@
  L:	linux-wireless at vger.kernel.org
  L:	ipw2100-devel at lists.sourceforge.net
  W:	http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
-@@ -2040,10 +2060,12 @@ W:	http://ipw2100.sourceforge.net
+@@ -2040,10 +2051,12 @@ W:	http://ipw2100.sourceforge.net
  S:	Supported
  
  INTEL PRO/WIRELESS 2915ABG NETWORK CONNECTION SUPPORT
@@ -14364,7 +19737,7 @@
  L:	linux-wireless at vger.kernel.org
  L:	ipw2100-devel at lists.sourceforge.net
  W:	http://lists.sourceforge.net/mailman/listinfo/ipw2100-devel
-@@ -2053,6 +2075,8 @@ S:	Supported
+@@ -2053,6 +2066,8 @@ S:	Supported
  INTEL WIRELESS WIFI LINK (iwlwifi)
  P:	Zhu Yi
  M:	yi.zhu at intel.com
@@ -14373,7 +19746,7 @@
  L:	linux-wireless at vger.kernel.org
  L:	ipw3945-devel at lists.sourceforge.net
  W:	http://intellinuxwireless.org
-@@ -2141,6 +2165,15 @@ L:	isdn4linux at listserv.isdn4linux.de
+@@ -2141,6 +2156,15 @@ L:	isdn4linux at listserv.isdn4linux.de
  W:	http://www.melware.de
  S:	Maintained
  
@@ -14389,7 +19762,7 @@
  JOURNALLING FLASH FILE SYSTEM V2 (JFFS2)
  P:	David Woodhouse
  M:	dwmw2 at infradead.org
-@@ -2214,7 +2247,7 @@ P:	J. Bruce Fields
+@@ -2214,7 +2238,7 @@ P:	J. Bruce Fields
  M:	bfields at fieldses.org
  P:	Neil Brown
  M:	neilb at suse.de
@@ -14398,6 +19771,22 @@
  W:	http://nfs.sourceforge.net/
  S:	Supported
  
+@@ -2225,6 +2249,15 @@ L:	kvm-devel at lists.sourceforge.net
+ W:	kvm.sourceforge.net
+ S:	Supported
+ 
++KERNEL VIRTUAL MACHINE For Itanium(KVM/IA64)
++P:	Anthony Xu
++M:	anthony.xu at intel.com
++P:	Xiantao Zhang
++M:	xiantao.zhang at intel.com
++L:	kvm-ia64-devel at lists.sourceforge.net
++W:	kvm.sourceforge.net
++S:	Supported
++
+ KEXEC
+ P:	Eric Biederman
+ M:	ebiederm at xmission.com
 @@ -2475,6 +2508,16 @@ W:	http://linuxwireless.org/
  T:	git kernel.org:/pub/scm/linux/kernel/git/linville/wireless-2.6.git
  S:	Maintained
@@ -14415,7 +19804,40 @@
  MACVLAN DRIVER
  P:	Patrick McHardy
  M:	kaber at trash.net
-@@ -3010,7 +3053,6 @@ M:	cbou at mail.ru
+@@ -2647,6 +2690,16 @@ M:	James.Bottomley at HansenPartnership.com
+ L:	linux-scsi at vger.kernel.org
+ S:	Maintained
+ 
++NETEFFECT IWARP RNIC DRIVER (IW_NES)
++P:	Faisal Latif
++M:	flatif at neteffect.com
++P:	Glenn Streiff
++M:	gstreiff at neteffect.com
++L:	general at lists.openfabrics.org
++W:	http://www.neteffect.com
++S:	Supported
++F:	drivers/infiniband/hw/nes/
++
+ NETEM NETWORK EMULATOR
+ P:	Stephen Hemminger
+ M:	shemminger at linux-foundation.org
+@@ -2821,15 +2874,6 @@ L:	ocfs2-devel at oss.oracle.com
+ W:	http://oss.oracle.com/projects/ocfs2/
+ S:	Supported
+ 
+-OLYMPIC NETWORK DRIVER
+-P:	Peter De Shrijver
+-M:	p2 at ace.ulyssis.student.kuleuven.ac.be
+-P:	Mike Phillips
+-M:	mikep at linuxtr.net
+-L:	netdev at vger.kernel.org
+-W:	http://www.linuxtr.net
+-S:	Maintained
+-
+ OMNIKEY CARDMAN 4000 DRIVER
+ P:	Harald Welte
+ M:	laforge at gnumonks.org
+@@ -3010,7 +3054,6 @@ M:	cbou at mail.ru
  P:	David Woodhouse
  M:	dwmw2 at infradead.org
  L:	linux-kernel at vger.kernel.org
@@ -14423,7 +19845,16 @@
  T:	git git.infradead.org/battery-2.6.git
  S:	Maintained
  
-@@ -3176,6 +3218,12 @@ M:	mporter at kernel.crashing.org
+@@ -3153,7 +3196,7 @@ S:	Maintained
+ 
+ RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
+ P:	Corey Thomas
+-M:	corey at world.std.com
++M:	coreythomas at charter.net
+ L:	linux-wireless at vger.kernel.org
+ S:	Maintained
+ 
+@@ -3176,6 +3219,12 @@ M:	mporter at kernel.crashing.org
  L:	linux-kernel at vger.kernel.org
  S:	Maintained
  
@@ -14436,7 +19867,7 @@
  READ-COPY UPDATE (RCU)
  P:	Dipankar Sarma
  M:	dipankar at in.ibm.com
-@@ -3260,8 +3308,10 @@ W:	http://www.ibm.com/developerworks/linux/linux390/
+@@ -3260,8 +3309,10 @@ W:	http://www.ibm.com/developerworks/linux/linux390/
  S:	Supported
  
  S390 ZFCP DRIVER
@@ -14449,7 +19880,7 @@
  M:	linux390 at de.ibm.com
  L:	linux-s390 at vger.kernel.org
  W:	http://www.ibm.com/developerworks/linux/linux390/
-@@ -3520,6 +3570,9 @@ S:	Maintained
+@@ -3520,6 +3571,9 @@ S:	Maintained
  SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
  P:	Liam Girdwood
  M:	liam.girdwood at wolfsonmicro.com
@@ -14459,7 +19890,41 @@
  L:	alsa-devel at alsa-project.org (subscribers-only)
  S:	Supported
  
-@@ -4031,6 +4084,12 @@ L:	video4linux-list at redhat.com
+@@ -3735,13 +3789,6 @@ L:	tlan-devel at lists.sourceforge.net (subscribers-only)
+ W:	http://sourceforge.net/projects/tlan/
+ S:	Maintained
+ 
+-TOKEN-RING NETWORK DRIVER
+-P:	Mike Phillips
+-M:	mikep at linuxtr.net
+-L:	netdev at vger.kernel.org
+-W:	http://www.linuxtr.net
+-S:	Maintained
+-
+ TOSHIBA ACPI EXTRAS DRIVER
+ P:	John Belmonte
+ M:	toshiba_acpi at memebeam.org
+@@ -3762,18 +3809,9 @@ L:	linux-kernel at vger.kernel.org
+ S:	Maintained
+ 
+ TRIVIAL PATCHES
+-P:	Adrian Bunk
++P:	Jesper Juhl
+ M:	trivial at kernel.org
+ L:	linux-kernel at vger.kernel.org
+-W:	http://www.kernel.org/pub/linux/kernel/people/bunk/trivial/
+-T:	git kernel.org:/pub/scm/linux/kernel/git/bunk/trivial.git
+-S:	Maintained
+-
+-TMS380 TOKEN-RING NETWORK DRIVER
+-P:	Adam Fritzler
+-M:	mid at auk.cx
+-L:	linux-tr at linuxtr.net
+-W:	http://www.auk.cx/tms380tr/
+ S:	Maintained
+ 
+ TULIP NETWORK DRIVER
+@@ -4031,6 +4069,12 @@ L:	video4linux-list at redhat.com
  W:	http://www.linux-projects.org
  S:	Maintained
  
@@ -14472,11 +19937,56 @@
  USB ZC0301 DRIVER
  P:	Luca Risolia
  M:	luca.risolia at studio.unibo.it
+diff --git a/arch/Kconfig b/arch/Kconfig
+new file mode 100644
+index 0000000..3d72dc3
+--- /dev/null
++++ b/arch/Kconfig
+@@ -0,0 +1,31 @@
++#
++# General architecture dependent options
++#
++
++config OPROFILE
++	tristate "OProfile system profiling (EXPERIMENTAL)"
++	depends on PROFILING
++	depends on HAVE_OPROFILE
++	help
++	  OProfile is a profiling system capable of profiling the
++	  whole system, include the kernel, kernel modules, libraries,
++	  and applications.
++
++	  If unsure, say N.
++
++config HAVE_OPROFILE
++	def_bool n
++
++config KPROBES
++	bool "Kprobes"
++	depends on KALLSYMS && MODULES
++	depends on HAVE_KPROBES
++	help
++	  Kprobes allows you to trap at almost any kernel address and
++	  execute a callback function.  register_kprobe() establishes
++	  a probepoint and specifies the callback.  Kprobes is useful
++	  for kernel debugging, non-intrusive instrumentation and testing.
++	  If in doubt, say "N".
++
++config HAVE_KPROBES
++	def_bool n
 diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
-index 4c002ba..c613d5f 100644
+index 4c002ba..01b10ab 100644
 --- a/arch/alpha/Kconfig
 +++ b/arch/alpha/Kconfig
-@@ -318,11 +318,6 @@ config PCI
+@@ -5,6 +5,7 @@
+ config ALPHA
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
+ 	help
+ 	  The Alpha is a 64-bit general-purpose processor designed and
+ 	  marketed by the Digital Equipment Corporation of blessed memory,
+@@ -318,11 +319,6 @@ config PCI
  	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
  	  VESA. If you have PCI, say Y, otherwise N.
  
@@ -14488,6 +19998,178 @@
  config PCI_DOMAINS
  	bool
  	default y
+@@ -536,8 +532,8 @@ config SMP
+ 	  singleprocessor machines. On a singleprocessor machine, the kernel
+ 	  will run faster if you say N here.
+ 
+-	  See also the <file:Documentation/smp.txt>, and the SMP-HOWTO
+-	  available at <http://www.tldp.org/docs.html#howto>.
++	  See also the SMP-HOWTO available at
++	  <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
+ 
+@@ -654,8 +650,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/alpha/Kconfig.debug"
+ 
+ # DUMMY_CONSOLE may be defined in drivers/video/console/Kconfig
+diff --git a/arch/alpha/kernel/pci-noop.c b/arch/alpha/kernel/pci-noop.c
+index 468b76c..8ac0831 100644
+--- a/arch/alpha/kernel/pci-noop.c
++++ b/arch/alpha/kernel/pci-noop.c
+@@ -165,7 +165,7 @@ dma_alloc_coherent(struct device *dev, size_t size,
+ 	ret = (void *)__get_free_pages(gfp, get_order(size));
+ 	if (ret) {
+ 		memset(ret, 0, size);
+-		*dma_handle = virt_to_bus(ret);
++		*dma_handle = virt_to_phys(ret);
+ 	}
+ 	return ret;
+ }
+@@ -184,7 +184,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
+ 
+ 		BUG_ON(!sg_page(sg));
+ 		va = sg_virt(sg);
+-		sg_dma_address(sg) = (dma_addr_t)virt_to_bus(va);
++		sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va);
+ 		sg_dma_len(sg) = sg->length;
+ 	}
+ 
+diff --git a/arch/alpha/kernel/pci_iommu.c b/arch/alpha/kernel/pci_iommu.c
+index 2d00a08..26d3789 100644
+--- a/arch/alpha/kernel/pci_iommu.c
++++ b/arch/alpha/kernel/pci_iommu.c
+@@ -9,6 +9,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/scatterlist.h>
+ #include <linux/log2.h>
++#include <linux/dma-mapping.h>
+ 
+ #include <asm/io.h>
+ #include <asm/hwrpb.h>
+@@ -470,22 +471,29 @@ EXPORT_SYMBOL(pci_free_consistent);
+ #define SG_ENT_PHYS_ADDRESS(SG) __pa(SG_ENT_VIRT_ADDRESS(SG))
+ 
+ static void
+-sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
++sg_classify(struct device *dev, struct scatterlist *sg, struct scatterlist *end,
++	    int virt_ok)
+ {
+ 	unsigned long next_paddr;
+ 	struct scatterlist *leader;
+ 	long leader_flag, leader_length;
++	unsigned int max_seg_size;
+ 
+ 	leader = sg;
+ 	leader_flag = 0;
+ 	leader_length = leader->length;
+ 	next_paddr = SG_ENT_PHYS_ADDRESS(leader) + leader_length;
+ 
++	/* we will not marge sg without device. */
++	max_seg_size = dev ? dma_get_max_seg_size(dev) : 0;
+ 	for (++sg; sg < end; ++sg) {
+ 		unsigned long addr, len;
+ 		addr = SG_ENT_PHYS_ADDRESS(sg);
+ 		len = sg->length;
+ 
++		if (leader_length + len > max_seg_size)
++			goto new_segment;
++
+ 		if (next_paddr == addr) {
+ 			sg->dma_address = -1;
+ 			leader_length += len;
+@@ -494,6 +502,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
+ 			leader_flag = 1;
+ 			leader_length += len;
+ 		} else {
++new_segment:
+ 			leader->dma_address = leader_flag;
+ 			leader->dma_length = leader_length;
+ 			leader = sg;
+@@ -512,7 +521,7 @@ sg_classify(struct scatterlist *sg, struct scatterlist *end, int virt_ok)
+    in the blanks.  */
+ 
+ static int
+-sg_fill(struct scatterlist *leader, struct scatterlist *end,
++sg_fill(struct device *dev, struct scatterlist *leader, struct scatterlist *end,
+ 	struct scatterlist *out, struct pci_iommu_arena *arena,
+ 	dma_addr_t max_dma, int dac_allowed)
+ {
+@@ -562,8 +571,8 @@ sg_fill(struct scatterlist *leader, struct scatterlist *end,
+ 
+ 		/* Otherwise, break up the remaining virtually contiguous
+ 		   hunks into individual direct maps and retry.  */
+-		sg_classify(leader, end, 0);
+-		return sg_fill(leader, end, out, arena, max_dma, dac_allowed);
++		sg_classify(dev, leader, end, 0);
++		return sg_fill(dev, leader, end, out, arena, max_dma, dac_allowed);
+ 	}
+ 
+ 	out->dma_address = arena->dma_base + dma_ofs*PAGE_SIZE + paddr;
+@@ -619,12 +628,15 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
+ 	struct pci_iommu_arena *arena;
+ 	dma_addr_t max_dma;
+ 	int dac_allowed;
++	struct device *dev;
+ 
+ 	if (direction == PCI_DMA_NONE)
+ 		BUG();
+ 
+ 	dac_allowed = pdev ? pci_dac_dma_supported(pdev, pdev->dma_mask) : 0;
+ 
++	dev = pdev ? &pdev->dev : NULL;
++
+ 	/* Fast path single entry scatterlists.  */
+ 	if (nents == 1) {
+ 		sg->dma_length = sg->length;
+@@ -638,7 +650,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
+ 	end = sg + nents;
+ 
+ 	/* First, prepare information about the entries.  */
+-	sg_classify(sg, end, alpha_mv.mv_pci_tbi != 0);
++	sg_classify(dev, sg, end, alpha_mv.mv_pci_tbi != 0);
+ 
+ 	/* Second, figure out where we're going to map things.  */
+ 	if (alpha_mv.mv_pci_tbi) {
+@@ -658,7 +670,7 @@ pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg, int nents,
+ 	for (out = sg; sg < end; ++sg) {
+ 		if ((int) sg->dma_address < 0)
+ 			continue;
+-		if (sg_fill(sg, end, out, arena, max_dma, dac_allowed) < 0)
++		if (sg_fill(dev, sg, end, out, arena, max_dma, dac_allowed) < 0)
+ 			goto error;
+ 		out++;
+ 	}
+diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
+index bd5e68c..beff629 100644
+--- a/arch/alpha/kernel/setup.c
++++ b/arch/alpha/kernel/setup.c
+@@ -58,7 +58,6 @@ static struct notifier_block alpha_panic_block = {
+ #include <asm/system.h>
+ #include <asm/hwrpb.h>
+ #include <asm/dma.h>
+-#include <asm/io.h>
+ #include <asm/mmu_context.h>
+ #include <asm/console.h>
+ 
+diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
+index 79de99e..ba914af 100644
+--- a/arch/alpha/kernel/systbls.S
++++ b/arch/alpha/kernel/systbls.S
+@@ -495,7 +495,7 @@ sys_call_table:
+ 	.quad sys_epoll_pwait
+ 	.quad sys_utimensat			/* 475 */
+ 	.quad sys_signalfd
+-	.quad sys_timerfd
++	.quad sys_ni_syscall
+ 	.quad sys_eventfd
+ 
+ 	.size sys_call_table, . - sys_call_table
 diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S
 index 55c05b5..f13249b 100644
 --- a/arch/alpha/kernel/vmlinux.lds.S
@@ -14532,10 +20214,31 @@
  	/* Slow path */
  	spin_lock(lock);
 diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
-index a04f507..4b1a8e3 100644
+index a04f507..e19e774 100644
 --- a/arch/arm/Kconfig
 +++ b/arch/arm/Kconfig
-@@ -91,6 +91,11 @@ config GENERIC_IRQ_PROBE
+@@ -10,6 +10,8 @@ config ARM
+ 	default y
+ 	select RTC_LIB
+ 	select SYS_SUPPORTS_APM_EMULATION
++	select HAVE_OPROFILE
++	select HAVE_KPROBES if (!XIP_KERNEL)
+ 	help
+ 	  The ARM series is a line of low-power-consumption RISC chip designs
+ 	  licensed by ARM Ltd and targeted at embedded applications and
+@@ -33,6 +35,11 @@ config GENERIC_CLOCKEVENTS
+ 	bool
+ 	default n
+ 
++config GENERIC_CLOCKEVENTS_BROADCAST
++	bool
++	depends on GENERIC_CLOCKEVENTS
++	default y if SMP && !LOCAL_TIMERS
++
+ config MMU
+ 	bool
+ 	default y
+@@ -91,6 +98,11 @@ config GENERIC_IRQ_PROBE
  	bool
  	default y
  
@@ -14547,7 +20250,40 @@
  config RWSEM_GENERIC_SPINLOCK
  	bool
  	default y
-@@ -180,8 +185,8 @@ config ARCH_AT91
+@@ -130,6 +142,23 @@ config FIQ
+ config ARCH_MTD_XIP
+ 	bool
+ 
++if OPROFILE
++
++config OPROFILE_ARMV6
++	def_bool y
++	depends on CPU_V6 && !SMP
++	select OPROFILE_ARM11_CORE
++
++config OPROFILE_MPCORE
++	def_bool y
++	depends on CPU_V6 && SMP
++	select OPROFILE_ARM11_CORE
++
++config OPROFILE_ARM11_CORE
++	bool
++
++endif
++
+ config VECTORS_BASE
+ 	hex
+ 	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
+@@ -163,6 +192,8 @@ config ARCH_REALVIEW
+ 	bool "ARM Ltd. RealView family"
+ 	select ARM_AMBA
+ 	select ICST307
++	select GENERIC_TIME
++	select GENERIC_CLOCKEVENTS
+ 	help
+ 	  This enables support for ARM Ltd RealView boards.
+ 
+@@ -180,8 +211,8 @@ config ARCH_AT91
  	bool "Atmel AT91"
  	select GENERIC_GPIO
  	help
@@ -14558,7 +20294,7 @@
  
  config ARCH_CLPS7500
  	bool "Cirrus CL-PS7500FE"
-@@ -217,6 +222,7 @@ config ARCH_EP93XX
+@@ -217,6 +248,7 @@ config ARCH_EP93XX
  	bool "EP93xx-based"
  	select ARM_AMBA
  	select ARM_VIC
@@ -14566,7 +20302,7 @@
  	help
  	  This enables support for the Cirrus EP93xx series of CPUs.
  
-@@ -333,6 +339,16 @@ config ARCH_MXC
+@@ -333,6 +365,16 @@ config ARCH_MXC
  	help
  	  Support for Freescale MXC/iMX-based family of processors
  
@@ -14583,15 +20319,18 @@
  config ARCH_PNX4008
  	bool "Philips Nexperia PNX4008 Mobile"
  	help
-@@ -345,6 +361,7 @@ config ARCH_PXA
+@@ -343,8 +385,10 @@ config ARCH_PXA
+ 	depends on MMU
+ 	select ARCH_MTD_XIP
  	select GENERIC_GPIO
++	select HAVE_GPIO_LIB
  	select GENERIC_TIME
  	select GENERIC_CLOCKEVENTS
 +	select TICK_ONESHOT
  	help
  	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.
  
-@@ -366,6 +383,7 @@ config ARCH_SA1100
+@@ -366,6 +410,7 @@ config ARCH_SA1100
  	select ARCH_DISCONTIGMEM_ENABLE
  	select ARCH_MTD_XIP
  	select GENERIC_GPIO
@@ -14599,7 +20338,7 @@
  	help
  	  Support for StrongARM 11x0 based boards.
  
-@@ -409,6 +427,17 @@ config ARCH_OMAP
+@@ -409,6 +454,17 @@ config ARCH_OMAP
  	help
  	  Support for TI's OMAP platform (OMAP1 and OMAP2).
  
@@ -14617,7 +20356,7 @@
  endchoice
  
  source "arch/arm/mach-clps711x/Kconfig"
-@@ -441,6 +470,8 @@ source "arch/arm/mach-omap1/Kconfig"
+@@ -441,6 +497,8 @@ source "arch/arm/mach-omap1/Kconfig"
  
  source "arch/arm/mach-omap2/Kconfig"
  
@@ -14626,7 +20365,7 @@
  source "arch/arm/plat-s3c24xx/Kconfig"
  source "arch/arm/plat-s3c/Kconfig"
  
-@@ -477,6 +508,8 @@ source "arch/arm/mach-davinci/Kconfig"
+@@ -477,6 +535,8 @@ source "arch/arm/mach-davinci/Kconfig"
  
  source "arch/arm/mach-ks8695/Kconfig"
  
@@ -14635,7 +20374,7 @@
  # Definitions to make life easier
  config ARCH_ACORN
  	bool
-@@ -544,11 +577,6 @@ config PCI
+@@ -544,11 +604,6 @@ config PCI
  	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
  	  VESA. If you have PCI, say Y, otherwise N.
  
@@ -14647,7 +20386,35 @@
  config PCI_SYSCALL
  	def_bool PCI
  
-@@ -657,6 +685,7 @@ config HZ
+@@ -576,7 +631,7 @@ source "kernel/time/Kconfig"
+ 
+ config SMP
+ 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
+-	depends on EXPERIMENTAL && REALVIEW_MPCORE
++	depends on EXPERIMENTAL && REALVIEW_EB_ARM11MP
+ 	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
+@@ -588,8 +643,7 @@ config SMP
+ 	  processor machines. On a single processor machine, the kernel will
+ 	  run faster if you say N here.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  <file:Documentation/i386/IO-APIC.txt>,
++	  See also <file:Documentation/i386/IO-APIC.txt>,
+ 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+ 	  <http://www.linuxdoc.org/docs.html#howto>.
+ 
+@@ -610,7 +664,7 @@ config HOTPLUG_CPU
+ 
+ config LOCAL_TIMERS
+ 	bool "Use local timer interrupts"
+-	depends on SMP && REALVIEW_MPCORE
++	depends on SMP && REALVIEW_EB_ARM11MP
+ 	default y
+ 	help
+ 	  Enable support for local timers on SMP platforms, rather then the
+@@ -657,6 +711,7 @@ config HZ
  	default 128 if ARCH_L7200
  	default 200 if ARCH_EBSA110 || ARCH_S3C2410
  	default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
@@ -14655,7 +20422,7 @@
  	default 100
  
  config AEABI
-@@ -716,7 +745,7 @@ config LEDS
+@@ -716,7 +771,7 @@ config LEDS
  		   ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
  		   ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE || \
  		   ARCH_AT91 || MACH_TRIZEPS4 || ARCH_DAVINCI || \
@@ -14664,8 +20431,17 @@
  	help
  	  If you say Y here, the LEDs on your machine will be used
  	  to provide useful information about your current system status.
-@@ -867,7 +896,7 @@ config KEXEC
+@@ -865,9 +920,16 @@ config KEXEC
+ 	  initially work for you.  It may help to enable device hotplugging
+ 	  support.
  
++config ATAGS_PROC
++	bool "Export atags in procfs"
++	default n
++	help
++	  Should the atags used to boot the kernel be exported in an "atags"
++	  file in procfs. Useful with kexec.
++
  endmenu
  
 -if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
@@ -14673,7 +20449,7 @@
  
  menu "CPU Frequency scaling"
  
-@@ -903,6 +932,12 @@ config CPU_FREQ_IMX
+@@ -903,6 +965,12 @@ config CPU_FREQ_IMX
  
  	  If in doubt, say N.
  
@@ -14686,7 +20462,7 @@
  endmenu
  
  endif
-@@ -951,7 +986,7 @@ config FPE_FASTFPE
+@@ -951,7 +1019,7 @@ config FPE_FASTFPE
  
  config VFP
  	bool "VFP-format floating point maths"
@@ -14695,7 +20471,7 @@
  	help
  	  Say Y to include VFP support code in the kernel. This is needed
  	  if your hardware includes a VFP unit.
-@@ -961,6 +996,18 @@ config VFP
+@@ -961,6 +1029,18 @@ config VFP
  
  	  Say N if your target does not have VFP hardware.
  
@@ -14714,7 +20490,7 @@
  endmenu
  
  menu "Userspace binary formats"
-@@ -983,6 +1030,9 @@ menu "Power management options"
+@@ -983,6 +1063,9 @@ menu "Power management options"
  
  source "kernel/power/Kconfig"
  
@@ -14724,6 +20500,24 @@
  endmenu
  
  source "net/Kconfig"
+@@ -1040,6 +1123,8 @@ source "drivers/i2c/Kconfig"
+ 
+ source "drivers/spi/Kconfig"
+ 
++source "drivers/gpio/Kconfig"
++
+ source "drivers/w1/Kconfig"
+ 
+ source "drivers/power/Kconfig"
+@@ -1078,8 +1163,6 @@ endmenu
+ 
+ source "fs/Kconfig"
+ 
+-source "arch/arm/Kconfig.instrumentation"
+-
+ source "arch/arm/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
 index 18101f5..192ee01 100644
 --- a/arch/arm/Kconfig.debug
@@ -14742,26 +20536,63 @@
  # These options are only for real kernel hackers who want to get their hands dirty.
  config DEBUG_LL
 diff --git a/arch/arm/Kconfig.instrumentation b/arch/arm/Kconfig.instrumentation
-index 63b8c6d..453ad8e 100644
+deleted file mode 100644
+index 63b8c6d..0000000
 --- a/arch/arm/Kconfig.instrumentation
-+++ b/arch/arm/Kconfig.instrumentation
-@@ -43,6 +43,16 @@ config OPROFILE_MPCORE
- config OPROFILE_ARM11_CORE
- 	bool
- 
-+config KPROBES
-+	bool "Kprobes"
-+	depends on KALLSYMS && MODULES && !UML && !XIP_KERNEL
-+	help
-+	  Kprobes allows you to trap at almost any kernel address and
-+	  execute a callback function.  register_kprobe() establishes
-+	  a probepoint and specifies the callback.  Kprobes is useful
-+	  for kernel debugging, non-intrusive instrumentation and testing.
-+	  If in doubt, say "N".
-+
- config MARKERS
- 	bool "Activate markers"
- 	help
++++ /dev/null
+@@ -1,52 +0,0 @@
+-menuconfig INSTRUMENTATION
+-	bool "Instrumentation Support"
+-	default y
+-	---help---
+-	  Say Y here to get to see options related to performance measurement,
+-	  system-wide debugging, and testing. This option alone does not add any
+-	  kernel code.
+-
+-	  If you say N, all options in this submenu will be skipped and
+-	  disabled. If you're trying to debug the kernel itself, go see the
+-	  Kernel Hacking menu.
+-
+-if INSTRUMENTATION
+-
+-config PROFILING
+-	bool "Profiling support (EXPERIMENTAL)"
+-	help
+-	  Say Y here to enable the extended profiling support mechanisms used
+-	  by profilers such as OProfile.
+-
+-config OPROFILE
+-	tristate "OProfile system profiling (EXPERIMENTAL)"
+-	depends on PROFILING && !UML
+-	help
+-	  OProfile is a profiling system capable of profiling the
+-	  whole system, include the kernel, kernel modules, libraries,
+-	  and applications.
+-
+-	  If unsure, say N.
+-
+-config OPROFILE_ARMV6
+-	bool
+-	depends on OPROFILE && CPU_V6 && !SMP
+-	default y
+-	select OPROFILE_ARM11_CORE
+-
+-config OPROFILE_MPCORE
+-	bool
+-	depends on OPROFILE && CPU_V6 && SMP
+-	default y
+-	select OPROFILE_ARM11_CORE
+-
+-config OPROFILE_ARM11_CORE
+-	bool
+-
+-config MARKERS
+-	bool "Activate markers"
+-	help
+-	  Place an empty function call at each marker site. Can be
+-	  dynamically changed for a probe function.
+-
+-endif # INSTRUMENTATION
 diff --git a/arch/arm/Makefile b/arch/arm/Makefile
 index 35e56c9..7b8ff66 100644
 --- a/arch/arm/Makefile
@@ -14929,6 +20760,20 @@
  
  #include <asm/rtc.h>
  #include <asm/semaphore.h>
+diff --git a/arch/arm/common/time-acorn.c b/arch/arm/common/time-acorn.c
+index 34038ec..d544da4 100644
+--- a/arch/arm/common/time-acorn.c
++++ b/arch/arm/common/time-acorn.c
+@@ -69,9 +69,7 @@ void __init ioctime_init(void)
+ static irqreturn_t
+ ioc_timer_interrupt(int irq, void *dev_id)
+ {
+-	write_seqlock(&xtime_lock);
+ 	timer_tick();
+-	write_sequnlock(&xtime_lock);
+ 	return IRQ_HANDLED;
+ }
+ 
 diff --git a/arch/arm/configs/at91cap9adk_defconfig b/arch/arm/configs/at91cap9adk_defconfig
 new file mode 100644
 index 0000000..e32e736
@@ -20688,23 +26533,25 @@
  CONFIG_XOR_BLOCKS=y
  CONFIG_ASYNC_CORE=y
  CONFIG_ASYNC_MEMCPY=y
-diff --git a/arch/arm/configs/littleton_defconfig b/arch/arm/configs/littleton_defconfig
-new file mode 100644
-index 0000000..1db4969
---- /dev/null
-+++ b/arch/arm/configs/littleton_defconfig
-@@ -0,0 +1,783 @@
-+#
-+# Automatically generated make config: don't edit
-+# Linux kernel version: 2.6.24-rc5
-+# Fri Dec 21 11:06:19 2007
-+#
-+CONFIG_ARM=y
+diff --git a/arch/arm/configs/ixp4xx_defconfig b/arch/arm/configs/ixp4xx_defconfig
+index db850a5..efa0485 100644
+--- a/arch/arm/configs/ixp4xx_defconfig
++++ b/arch/arm/configs/ixp4xx_defconfig
+@@ -1,69 +1,96 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.15
+-# Tue Jan  3 03:20:40 2006
++# Linux kernel version: 2.6.24
++# Sun Jan 27 07:33:38 2008
+ #
+ CONFIG_ARM=y
 +CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 +CONFIG_GENERIC_GPIO=y
 +CONFIG_GENERIC_TIME=y
 +CONFIG_GENERIC_CLOCKEVENTS=y
-+CONFIG_MMU=y
+ CONFIG_MMU=y
+-CONFIG_UID16=y
 +# CONFIG_NO_IOPORT is not set
 +CONFIG_GENERIC_HARDIRQS=y
 +CONFIG_STACKTRACE_SUPPORT=y
@@ -20712,35 +26559,43 @@
 +CONFIG_TRACE_IRQFLAGS_SUPPORT=y
 +CONFIG_HARDIRQS_SW_RESEND=y
 +CONFIG_GENERIC_IRQ_PROBE=y
-+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+ CONFIG_RWSEM_GENERIC_SPINLOCK=y
 +# CONFIG_ARCH_HAS_ILOG2_U32 is not set
 +# CONFIG_ARCH_HAS_ILOG2_U64 is not set
 +CONFIG_GENERIC_HWEIGHT=y
-+CONFIG_GENERIC_CALIBRATE_DELAY=y
+ CONFIG_GENERIC_CALIBRATE_DELAY=y
 +CONFIG_ZONE_DMA=y
-+CONFIG_ARCH_MTD_XIP=y
 +CONFIG_VECTORS_BASE=0xffff0000
 +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-+
-+#
+ 
+ #
+-# Code maturity level options
 +# General setup
-+#
-+CONFIG_EXPERIMENTAL=y
-+CONFIG_BROKEN_ON_SMP=y
-+CONFIG_LOCK_KERNEL=y
-+CONFIG_INIT_ENV_ARG_LIMIT=32
-+CONFIG_LOCALVERSION=""
-+CONFIG_LOCALVERSION_AUTO=y
-+CONFIG_SWAP=y
-+CONFIG_SYSVIPC=y
+ #
+ CONFIG_EXPERIMENTAL=y
+-CONFIG_CLEAN_COMPILE=y
+ CONFIG_BROKEN_ON_SMP=y
+ CONFIG_INIT_ENV_ARG_LIMIT=32
+-
+-#
+-# General setup
+-#
+ CONFIG_LOCALVERSION=""
+ CONFIG_LOCALVERSION_AUTO=y
+ CONFIG_SWAP=y
+ CONFIG_SYSVIPC=y
 +CONFIG_SYSVIPC_SYSCTL=y
-+# CONFIG_POSIX_MQUEUE is not set
-+# CONFIG_BSD_PROCESS_ACCT is not set
+ # CONFIG_POSIX_MQUEUE is not set
+ CONFIG_BSD_PROCESS_ACCT=y
+ # CONFIG_BSD_PROCESS_ACCT_V3 is not set
+-CONFIG_SYSCTL=y
 +# CONFIG_TASKSTATS is not set
 +# CONFIG_USER_NS is not set
 +# CONFIG_PID_NS is not set
-+# CONFIG_AUDIT is not set
-+# CONFIG_IKCONFIG is not set
+ # CONFIG_AUDIT is not set
+-# CONFIG_HOTPLUG is not set
+-CONFIG_KOBJECT_UEVENT=y
+ # CONFIG_IKCONFIG is not set
 +CONFIG_LOG_BUF_SHIFT=14
 +# CONFIG_CGROUPS is not set
 +CONFIG_FAIR_GROUP_SCHED=y
@@ -20749,72 +26604,79 @@
 +CONFIG_SYSFS_DEPRECATED=y
 +# CONFIG_RELAY is not set
 +CONFIG_BLK_DEV_INITRD=y
-+CONFIG_INITRAMFS_SOURCE=""
-+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+ CONFIG_INITRAMFS_SOURCE=""
+ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 +CONFIG_SYSCTL=y
-+# CONFIG_EMBEDDED is not set
+ CONFIG_EMBEDDED=y
 +CONFIG_UID16=y
 +CONFIG_SYSCTL_SYSCALL=y
-+CONFIG_KALLSYMS=y
-+# CONFIG_KALLSYMS_ALL is not set
-+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+ CONFIG_KALLSYMS=y
+ # CONFIG_KALLSYMS_ALL is not set
+ # CONFIG_KALLSYMS_EXTRA_PASS is not set
 +CONFIG_HOTPLUG=y
-+CONFIG_PRINTK=y
-+CONFIG_BUG=y
+ CONFIG_PRINTK=y
+ CONFIG_BUG=y
 +CONFIG_ELF_CORE=y
-+CONFIG_BASE_FULL=y
-+CONFIG_FUTEX=y
+ CONFIG_BASE_FULL=y
+ CONFIG_FUTEX=y
 +CONFIG_ANON_INODES=y
-+CONFIG_EPOLL=y
+ CONFIG_EPOLL=y
 +CONFIG_SIGNALFD=y
 +CONFIG_EVENTFD=y
-+CONFIG_SHMEM=y
+ CONFIG_SHMEM=y
+-CONFIG_CC_ALIGN_FUNCTIONS=0
+-CONFIG_CC_ALIGN_LABELS=0
+-CONFIG_CC_ALIGN_LOOPS=0
+-CONFIG_CC_ALIGN_JUMPS=0
 +CONFIG_VM_EVENT_COUNTERS=y
-+CONFIG_SLAB=y
-+# CONFIG_SLUB is not set
++CONFIG_SLUB_DEBUG=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
 +# CONFIG_SLOB is not set
++CONFIG_SLABINFO=y
 +CONFIG_RT_MUTEXES=y
-+# CONFIG_TINY_SHMEM is not set
-+CONFIG_BASE_SMALL=0
-+CONFIG_MODULES=y
-+CONFIG_MODULE_UNLOAD=y
-+CONFIG_MODULE_FORCE_UNLOAD=y
-+# CONFIG_MODVERSIONS is not set
-+# CONFIG_MODULE_SRCVERSION_ALL is not set
-+# CONFIG_KMOD is not set
+ # CONFIG_TINY_SHMEM is not set
+ CONFIG_BASE_SMALL=0
+-
+-#
+-# Loadable module support
+-#
+ CONFIG_MODULES=y
+ # CONFIG_MODULE_UNLOAD is not set
+-CONFIG_OBSOLETE_MODPARM=y
+ CONFIG_MODVERSIONS=y
+ # CONFIG_MODULE_SRCVERSION_ALL is not set
+ CONFIG_KMOD=y
+-
+-#
+-# Block layer
+-#
 +CONFIG_BLOCK=y
 +# CONFIG_LBD is not set
 +# CONFIG_BLK_DEV_IO_TRACE is not set
 +# CONFIG_LSF is not set
 +# CONFIG_BLK_DEV_BSG is not set
-+
-+#
-+# IO Schedulers
-+#
-+CONFIG_IOSCHED_NOOP=y
-+CONFIG_IOSCHED_AS=y
-+CONFIG_IOSCHED_DEADLINE=y
-+CONFIG_IOSCHED_CFQ=y
-+# CONFIG_DEFAULT_AS is not set
-+# CONFIG_DEFAULT_DEADLINE is not set
-+CONFIG_DEFAULT_CFQ=y
-+# CONFIG_DEFAULT_NOOP is not set
-+CONFIG_DEFAULT_IOSCHED="cfq"
-+
-+#
-+# System Type
-+#
+ 
+ #
+ # IO Schedulers
+@@ -81,28 +108,39 @@ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ #
+ # System Type
+ #
 +# CONFIG_ARCH_AAEC2000 is not set
 +# CONFIG_ARCH_INTEGRATOR is not set
 +# CONFIG_ARCH_REALVIEW is not set
 +# CONFIG_ARCH_VERSATILE is not set
 +# CONFIG_ARCH_AT91 is not set
-+# CONFIG_ARCH_CLPS7500 is not set
-+# CONFIG_ARCH_CLPS711X is not set
-+# CONFIG_ARCH_CO285 is not set
-+# CONFIG_ARCH_EBSA110 is not set
+ # CONFIG_ARCH_CLPS7500 is not set
+ # CONFIG_ARCH_CLPS711X is not set
+ # CONFIG_ARCH_CO285 is not set
+ # CONFIG_ARCH_EBSA110 is not set
 +# CONFIG_ARCH_EP93XX is not set
-+# CONFIG_ARCH_FOOTBRIDGE is not set
+ # CONFIG_ARCH_FOOTBRIDGE is not set
+-# CONFIG_ARCH_INTEGRATOR is not set
+-# CONFIG_ARCH_IOP3XX is not set
+-CONFIG_ARCH_IXP4XX=y
 +# CONFIG_ARCH_NETX is not set
 +# CONFIG_ARCH_H720X is not set
 +# CONFIG_ARCH_IMX is not set
@@ -20822,44 +26684,61 @@
 +# CONFIG_ARCH_IOP32X is not set
 +# CONFIG_ARCH_IOP33X is not set
 +# CONFIG_ARCH_IXP23XX is not set
-+# CONFIG_ARCH_IXP2000 is not set
-+# CONFIG_ARCH_IXP4XX is not set
-+# CONFIG_ARCH_L7200 is not set
+ # CONFIG_ARCH_IXP2000 is not set
++CONFIG_ARCH_IXP4XX=y
+ # CONFIG_ARCH_L7200 is not set
 +# CONFIG_ARCH_KS8695 is not set
 +# CONFIG_ARCH_NS9XXX is not set
 +# CONFIG_ARCH_MXC is not set
 +# CONFIG_ARCH_PNX4008 is not set
-+CONFIG_ARCH_PXA=y
-+# CONFIG_ARCH_RPC is not set
-+# CONFIG_ARCH_SA1100 is not set
-+# CONFIG_ARCH_S3C2410 is not set
-+# CONFIG_ARCH_SHARK is not set
-+# CONFIG_ARCH_LH7A40X is not set
+ # CONFIG_ARCH_PXA is not set
+ # CONFIG_ARCH_RPC is not set
+ # CONFIG_ARCH_SA1100 is not set
+ # CONFIG_ARCH_S3C2410 is not set
+ # CONFIG_ARCH_SHARK is not set
+ # CONFIG_ARCH_LH7A40X is not set
 +# CONFIG_ARCH_DAVINCI is not set
-+# CONFIG_ARCH_OMAP is not set
-+
-+#
-+# Intel PXA2xx/PXA3xx Implementations
-+#
-+
-+#
-+# Supported PXA3xx Processor Variants
-+#
-+CONFIG_CPU_PXA300=y
-+CONFIG_CPU_PXA310=y
-+# CONFIG_CPU_PXA320 is not set
-+# CONFIG_ARCH_LUBBOCK is not set
-+# CONFIG_MACH_LOGICPD_PXA270 is not set
-+# CONFIG_MACH_MAINSTONE is not set
-+# CONFIG_ARCH_PXA_IDP is not set
-+# CONFIG_PXA_SHARPSL is not set
-+# CONFIG_MACH_TRIZEPS4 is not set
-+# CONFIG_MACH_EM_X270 is not set
-+# CONFIG_MACH_ZYLONITE is not set
-+CONFIG_MACH_LITTLETON=y
-+# CONFIG_MACH_ARMCORE is not set
-+CONFIG_PXA3xx=y
-+CONFIG_PXA_SSP=y
+ # CONFIG_ARCH_OMAP is not set
+-# CONFIG_ARCH_VERSATILE is not set
+-# CONFIG_ARCH_REALVIEW is not set
+-# CONFIG_ARCH_IMX is not set
+-# CONFIG_ARCH_H720X is not set
+-# CONFIG_ARCH_AAEC2000 is not set
+ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+ 
+ #
+@@ -112,8 +150,12 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
+ #
+ # IXP4xx Platforms
+ #
+-CONFIG_ARCH_AVILA=y
++CONFIG_MACH_NSLU2=y
++CONFIG_MACH_AVILA=y
++CONFIG_MACH_LOFT=y
+ CONFIG_ARCH_ADI_COYOTE=y
++CONFIG_MACH_GATEWAY7001=y
++CONFIG_MACH_WG302V2=y
+ CONFIG_ARCH_IXDP425=y
+ CONFIG_MACH_IXDPG425=y
+ CONFIG_MACH_IXDP465=y
+@@ -121,15 +163,27 @@ CONFIG_MACH_KIXRP435=y
+ CONFIG_ARCH_IXCDP1100=y
+ CONFIG_ARCH_PRPMC1100=y
+ CONFIG_MACH_NAS100D=y
++CONFIG_MACH_DSMG600=y
+ CONFIG_ARCH_IXDP4XX=y
+ CONFIG_CPU_IXP46X=y
+ CONFIG_CPU_IXP43X=y
+-# CONFIG_MACH_GTWX5715 is not set
++CONFIG_MACH_GTWX5715=y
+ 
+ #
+ # IXP4xx Options
+ #
++CONFIG_DMABOUNCE=y
+ # CONFIG_IXP4XX_INDIRECT_PCI is not set
++CONFIG_IXP4XX_QMGR=y
++CONFIG_IXP4XX_NPE=y
 +
 +#
 +# Boot options
@@ -20868,173 +26747,335 @@
 +#
 +# Power management
 +#
-+
-+#
-+# Processor Type
-+#
-+CONFIG_CPU_32=y
-+CONFIG_CPU_XSC3=y
-+CONFIG_CPU_32v5=y
-+CONFIG_CPU_ABRT_EV5T=y
-+CONFIG_CPU_CACHE_VIVT=y
-+CONFIG_CPU_TLB_V4WBI=y
+ 
+ #
+ # Processor Type
+@@ -140,33 +194,40 @@ CONFIG_CPU_32v5=y
+ CONFIG_CPU_ABRT_EV5T=y
+ CONFIG_CPU_CACHE_VIVT=y
+ CONFIG_CPU_TLB_V4WBI=y
 +CONFIG_CPU_CP15=y
 +CONFIG_CPU_CP15_MMU=y
-+CONFIG_IO_36=y
-+
-+#
-+# Processor Features
-+#
-+# CONFIG_ARM_THUMB is not set
+ 
+ #
+ # Processor Features
+ #
+ # CONFIG_ARM_THUMB is not set
+ CONFIG_CPU_BIG_ENDIAN=y
 +# CONFIG_CPU_DCACHE_DISABLE is not set
-+# CONFIG_CPU_BPREDICT_DISABLE is not set
 +# CONFIG_OUTER_CACHE is not set
-+CONFIG_IWMMXT=y
-+
-+#
-+# Bus support
-+#
-+# CONFIG_PCI_SYSCALL is not set
++# CONFIG_IWMMXT is not set
+ CONFIG_XSCALE_PMU=y
+-CONFIG_DMABOUNCE=y
+ 
+ #
+ # Bus support
+ #
+-CONFIG_ISA_DMA_API=y
+ CONFIG_PCI=y
+-CONFIG_PCI_LEGACY_PROC=y
++CONFIG_PCI_SYSCALL=y
 +# CONFIG_ARCH_SUPPORTS_MSI is not set
-+# CONFIG_PCCARD is not set
-+
-+#
-+# Kernel Features
-+#
-+CONFIG_TICK_ONESHOT=y
++CONFIG_PCI_LEGACY=y
+ # CONFIG_PCI_DEBUG is not set
+-
+-#
+-# PCCARD (PCMCIA/CardBus) support
+-#
+ # CONFIG_PCCARD is not set
+ 
+ #
+ # Kernel Features
+ #
++# CONFIG_TICK_ONESHOT is not set
 +# CONFIG_NO_HZ is not set
 +# CONFIG_HIGH_RES_TIMERS is not set
 +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-+CONFIG_PREEMPT=y
+ # CONFIG_PREEMPT is not set
+-# CONFIG_NO_IDLE_HZ is not set
 +CONFIG_HZ=100
 +CONFIG_AEABI=y
 +CONFIG_OABI_COMPAT=y
-+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
-+CONFIG_SELECT_MEMORY_MODEL=y
-+CONFIG_FLATMEM_MANUAL=y
-+# CONFIG_DISCONTIGMEM_MANUAL is not set
-+# CONFIG_SPARSEMEM_MANUAL is not set
-+CONFIG_FLATMEM=y
-+CONFIG_FLAT_NODE_MEM_MAP=y
-+# CONFIG_SPARSEMEM_STATIC is not set
+ # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+ CONFIG_SELECT_MEMORY_MODEL=y
+ CONFIG_FLATMEM_MANUAL=y
+@@ -175,7 +236,12 @@ CONFIG_FLATMEM_MANUAL=y
+ CONFIG_FLATMEM=y
+ CONFIG_FLAT_NODE_MEM_MAP=y
+ # CONFIG_SPARSEMEM_STATIC is not set
 +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-+CONFIG_SPLIT_PTLOCK_CPUS=4096
+ CONFIG_SPLIT_PTLOCK_CPUS=4096
 +# CONFIG_RESOURCES_64BIT is not set
 +CONFIG_ZONE_DMA_FLAG=1
 +CONFIG_BOUNCE=y
 +CONFIG_VIRT_TO_BUS=y
-+CONFIG_ALIGNMENT_TRAP=y
-+
-+#
-+# Boot options
-+#
-+CONFIG_ZBOOT_ROM_TEXT=0x0
-+CONFIG_ZBOOT_ROM_BSS=0x0
-+CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS2,38400 mem=64M"
-+# CONFIG_XIP_KERNEL is not set
+ CONFIG_ALIGNMENT_TRAP=y
+ 
+ #
+@@ -185,6 +251,7 @@ CONFIG_ZBOOT_ROM_TEXT=0x0
+ CONFIG_ZBOOT_ROM_BSS=0x0
+ CONFIG_CMDLINE="console=ttyS0,115200 ip=bootp root=/dev/nfs"
+ # CONFIG_XIP_KERNEL is not set
 +# CONFIG_KEXEC is not set
-+
-+#
-+# CPU Frequency scaling
-+#
-+# CONFIG_CPU_FREQ is not set
-+
-+#
-+# Floating point emulation
-+#
-+
-+#
-+# At least one emulation must be selected
-+#
-+CONFIG_FPE_NWFPE=y
-+# CONFIG_FPE_NWFPE_XP is not set
-+# CONFIG_FPE_FASTFPE is not set
-+
-+#
-+# Userspace binary formats
-+#
-+CONFIG_BINFMT_ELF=y
-+# CONFIG_BINFMT_AOUT is not set
-+# CONFIG_BINFMT_MISC is not set
-+
-+#
-+# Power management options
-+#
-+# CONFIG_PM is not set
+ 
+ #
+ # Floating point emulation
+@@ -203,13 +270,12 @@ CONFIG_FPE_NWFPE=y
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_AOUT is not set
+ # CONFIG_BINFMT_MISC is not set
+-# CONFIG_ARTHUR is not set
+ 
+ #
+ # Power management options
+ #
+ # CONFIG_PM is not set
+-# CONFIG_APM is not set
 +CONFIG_SUSPEND_UP_POSSIBLE=y
-+
-+#
-+# Networking
-+#
-+CONFIG_NET=y
-+
-+#
-+# Networking options
-+#
+ 
+ #
+ # Networking
+@@ -219,11 +285,13 @@ CONFIG_NET=y
+ #
+ # Networking options
+ #
+-CONFIG_PACKET=m
 +CONFIG_PACKET=y
-+# CONFIG_PACKET_MMAP is not set
-+CONFIG_UNIX=y
-+CONFIG_XFRM=y
-+# CONFIG_XFRM_USER is not set
+ CONFIG_PACKET_MMAP=y
+ CONFIG_UNIX=y
+ CONFIG_XFRM=y
+ # CONFIG_XFRM_USER is not set
 +# CONFIG_XFRM_SUB_POLICY is not set
 +# CONFIG_XFRM_MIGRATE is not set
-+# CONFIG_NET_KEY is not set
-+CONFIG_INET=y
-+# CONFIG_IP_MULTICAST is not set
-+# CONFIG_IP_ADVANCED_ROUTER is not set
-+CONFIG_IP_FIB_HASH=y
-+CONFIG_IP_PNP=y
-+# CONFIG_IP_PNP_DHCP is not set
-+# CONFIG_IP_PNP_BOOTP is not set
-+# CONFIG_IP_PNP_RARP is not set
-+# CONFIG_NET_IPIP is not set
-+# CONFIG_NET_IPGRE is not set
-+# CONFIG_ARPD is not set
-+# CONFIG_SYN_COOKIES is not set
-+# CONFIG_INET_AH is not set
-+# CONFIG_INET_ESP is not set
-+# CONFIG_INET_IPCOMP is not set
+ # CONFIG_NET_KEY is not set
+ CONFIG_INET=y
+ CONFIG_IP_MULTICAST=y
+@@ -232,9 +300,7 @@ CONFIG_ASK_IP_FIB_HASH=y
+ # CONFIG_IP_FIB_TRIE is not set
+ CONFIG_IP_FIB_HASH=y
+ CONFIG_IP_MULTIPLE_TABLES=y
+-CONFIG_IP_ROUTE_FWMARK=y
+ CONFIG_IP_ROUTE_MULTIPATH=y
+-# CONFIG_IP_ROUTE_MULTIPATH_CACHED is not set
+ CONFIG_IP_ROUTE_VERBOSE=y
+ CONFIG_IP_PNP=y
+ CONFIG_IP_PNP_DHCP=y
+@@ -251,15 +317,18 @@ CONFIG_SYN_COOKIES=y
+ # CONFIG_INET_AH is not set
+ # CONFIG_INET_ESP is not set
+ # CONFIG_INET_IPCOMP is not set
+-CONFIG_INET_TUNNEL=m
 +# CONFIG_INET_XFRM_TUNNEL is not set
 +# CONFIG_INET_TUNNEL is not set
 +CONFIG_INET_XFRM_MODE_TRANSPORT=y
 +CONFIG_INET_XFRM_MODE_TUNNEL=y
 +CONFIG_INET_XFRM_MODE_BEET=y
 +# CONFIG_INET_LRO is not set
-+CONFIG_INET_DIAG=y
-+CONFIG_INET_TCP_DIAG=y
-+# CONFIG_TCP_CONG_ADVANCED is not set
+ CONFIG_INET_DIAG=y
+ CONFIG_INET_TCP_DIAG=y
+ # CONFIG_TCP_CONG_ADVANCED is not set
+-CONFIG_TCP_CONG_BIC=y
+-
+-#
+-# IP: Virtual Server Configuration
+-#
 +CONFIG_TCP_CONG_CUBIC=y
 +CONFIG_DEFAULT_TCP_CONG="cubic"
 +# CONFIG_TCP_MD5SIG is not set
-+# CONFIG_IPV6 is not set
+ CONFIG_IP_VS=m
+ CONFIG_IP_VS_DEBUG=y
+ CONFIG_IP_VS_TAB_BITS=12
+@@ -290,6 +359,9 @@ CONFIG_IP_VS_SH=m
+ # IPVS application helper
+ #
+ # CONFIG_IPV6 is not set
 +# CONFIG_INET6_XFRM_TUNNEL is not set
 +# CONFIG_INET6_TUNNEL is not set
 +# CONFIG_NETWORK_SECMARK is not set
-+# CONFIG_NETFILTER is not set
-+# CONFIG_IP_DCCP is not set
-+# CONFIG_IP_SCTP is not set
+ CONFIG_NETFILTER=y
+ # CONFIG_NETFILTER_DEBUG is not set
+ CONFIG_BRIDGE_NETFILTER=y
+@@ -298,70 +370,57 @@ CONFIG_BRIDGE_NETFILTER=y
+ # Core Netfilter Configuration
+ #
+ # CONFIG_NETFILTER_NETLINK is not set
++# CONFIG_NF_CONNTRACK_ENABLED is not set
++# CONFIG_NF_CONNTRACK is not set
++CONFIG_NETFILTER_XTABLES=m
++# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set
++# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
++# CONFIG_NETFILTER_XT_TARGET_MARK is not set
++# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set
++# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
++# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
++# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
++# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
++# CONFIG_NETFILTER_XT_MATCH_ESP is not set
++# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
++# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set
++# CONFIG_NETFILTER_XT_MATCH_MAC is not set
++# CONFIG_NETFILTER_XT_MATCH_MARK is not set
++# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
++# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set
++# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
++# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
++# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
++# CONFIG_NETFILTER_XT_MATCH_REALM is not set
++# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
++# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
++# CONFIG_NETFILTER_XT_MATCH_STRING is not set
++# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
++# CONFIG_NETFILTER_XT_MATCH_TIME is not set
++# CONFIG_NETFILTER_XT_MATCH_U32 is not set
++# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+ 
+ #
+ # IP: Netfilter Configuration
+ #
+-CONFIG_IP_NF_CONNTRACK=m
+-# CONFIG_IP_NF_CT_ACCT is not set
+-# CONFIG_IP_NF_CONNTRACK_MARK is not set
+-# CONFIG_IP_NF_CONNTRACK_EVENTS is not set
+-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
+-CONFIG_IP_NF_FTP=m
+-CONFIG_IP_NF_IRC=m
+-# CONFIG_IP_NF_NETBIOS_NS is not set
+-# CONFIG_IP_NF_TFTP is not set
+-# CONFIG_IP_NF_AMANDA is not set
+-# CONFIG_IP_NF_PPTP is not set
+ CONFIG_IP_NF_QUEUE=m
+ CONFIG_IP_NF_IPTABLES=m
+-CONFIG_IP_NF_MATCH_LIMIT=m
+ # CONFIG_IP_NF_MATCH_IPRANGE is not set
+-CONFIG_IP_NF_MATCH_MAC=m
+-# CONFIG_IP_NF_MATCH_PKTTYPE is not set
+-CONFIG_IP_NF_MATCH_MARK=m
+-CONFIG_IP_NF_MATCH_MULTIPORT=m
+ CONFIG_IP_NF_MATCH_TOS=m
+ # CONFIG_IP_NF_MATCH_RECENT is not set
+ # CONFIG_IP_NF_MATCH_ECN is not set
+-# CONFIG_IP_NF_MATCH_DSCP is not set
+-CONFIG_IP_NF_MATCH_AH_ESP=m
+-CONFIG_IP_NF_MATCH_LENGTH=m
++# CONFIG_IP_NF_MATCH_AH is not set
+ CONFIG_IP_NF_MATCH_TTL=m
+-CONFIG_IP_NF_MATCH_TCPMSS=m
+-# CONFIG_IP_NF_MATCH_HELPER is not set
+-CONFIG_IP_NF_MATCH_STATE=m
+-# CONFIG_IP_NF_MATCH_CONNTRACK is not set
+ CONFIG_IP_NF_MATCH_OWNER=m
+-# CONFIG_IP_NF_MATCH_PHYSDEV is not set
+ # CONFIG_IP_NF_MATCH_ADDRTYPE is not set
+-# CONFIG_IP_NF_MATCH_REALM is not set
+-# CONFIG_IP_NF_MATCH_SCTP is not set
+-# CONFIG_IP_NF_MATCH_DCCP is not set
+-# CONFIG_IP_NF_MATCH_COMMENT is not set
+-# CONFIG_IP_NF_MATCH_HASHLIMIT is not set
+-# CONFIG_IP_NF_MATCH_STRING is not set
+ CONFIG_IP_NF_FILTER=m
+ CONFIG_IP_NF_TARGET_REJECT=m
+ CONFIG_IP_NF_TARGET_LOG=m
+ CONFIG_IP_NF_TARGET_ULOG=m
+-CONFIG_IP_NF_TARGET_TCPMSS=m
+-# CONFIG_IP_NF_TARGET_NFQUEUE is not set
+-CONFIG_IP_NF_NAT=m
+-CONFIG_IP_NF_NAT_NEEDED=y
+-CONFIG_IP_NF_TARGET_MASQUERADE=m
+-CONFIG_IP_NF_TARGET_REDIRECT=m
+-# CONFIG_IP_NF_TARGET_NETMAP is not set
+-# CONFIG_IP_NF_TARGET_SAME is not set
+-CONFIG_IP_NF_NAT_SNMP_BASIC=m
+-CONFIG_IP_NF_NAT_IRC=m
+-CONFIG_IP_NF_NAT_FTP=m
+ CONFIG_IP_NF_MANGLE=m
+ CONFIG_IP_NF_TARGET_TOS=m
+ # CONFIG_IP_NF_TARGET_ECN is not set
+-# CONFIG_IP_NF_TARGET_DSCP is not set
+-CONFIG_IP_NF_TARGET_MARK=m
+-# CONFIG_IP_NF_TARGET_CLASSIFY is not set
+ # CONFIG_IP_NF_TARGET_TTL is not set
+ # CONFIG_IP_NF_RAW is not set
+ CONFIG_IP_NF_ARPTABLES=m
+@@ -372,16 +431,9 @@ CONFIG_IP_NF_ARPFILTER=m
+ # Bridge: Netfilter Configuration
+ #
+ # CONFIG_BRIDGE_NF_EBTABLES is not set
+-
+-#
+-# DCCP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_DCCP is not set
+-
+-#
+-# SCTP Configuration (EXPERIMENTAL)
+-#
+ # CONFIG_IP_SCTP is not set
 +# CONFIG_TIPC is not set
-+# CONFIG_ATM is not set
-+# CONFIG_BRIDGE is not set
-+# CONFIG_VLAN_8021Q is not set
-+# CONFIG_DECNET is not set
-+# CONFIG_LLC2 is not set
-+# CONFIG_IPX is not set
-+# CONFIG_ATALK is not set
-+# CONFIG_X25 is not set
-+# CONFIG_LAPB is not set
-+# CONFIG_ECONET is not set
-+# CONFIG_WAN_ROUTER is not set
-+# CONFIG_NET_SCHED is not set
-+
-+#
-+# Network testing
-+#
-+# CONFIG_NET_PKTGEN is not set
-+# CONFIG_HAMRADIO is not set
-+# CONFIG_IRDA is not set
-+# CONFIG_BT is not set
+ CONFIG_ATM=y
+ CONFIG_ATM_CLIP=y
+ # CONFIG_ATM_CLIP_NO_ICMP is not set
+@@ -397,25 +449,17 @@ CONFIG_LLC=m
+ CONFIG_IPX=m
+ # CONFIG_IPX_INTERN is not set
+ CONFIG_ATALK=m
+-CONFIG_DEV_APPLETALK=y
++CONFIG_DEV_APPLETALK=m
+ CONFIG_IPDDP=m
+ CONFIG_IPDDP_ENCAP=y
+ CONFIG_IPDDP_DECAP=y
+ CONFIG_X25=m
+ CONFIG_LAPB=m
+-# CONFIG_NET_DIVERT is not set
+ CONFIG_ECONET=m
+ CONFIG_ECONET_AUNUDP=y
+ CONFIG_ECONET_NATIVE=y
+ CONFIG_WAN_ROUTER=m
+-
+-#
+-# QoS and/or fair queueing
+-#
+ CONFIG_NET_SCHED=y
+-CONFIG_NET_SCH_CLK_JIFFIES=y
+-# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+-# CONFIG_NET_SCH_CLK_CPU is not set
+ 
+ #
+ # Queueing/Scheduling
+@@ -425,6 +469,7 @@ CONFIG_NET_SCH_HTB=m
+ # CONFIG_NET_SCH_HFSC is not set
+ # CONFIG_NET_SCH_ATM is not set
+ CONFIG_NET_SCH_PRIO=m
++# CONFIG_NET_SCH_RR is not set
+ CONFIG_NET_SCH_RED=m
+ CONFIG_NET_SCH_SFQ=m
+ CONFIG_NET_SCH_TEQL=m
+@@ -449,10 +494,17 @@ CONFIG_NET_CLS_U32=m
+ 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_ACT=y
++CONFIG_NET_ACT_POLICE=y
++# CONFIG_NET_ACT_GACT is not set
++# CONFIG_NET_ACT_MIRRED is not set
++# CONFIG_NET_ACT_IPT is not set
++# CONFIG_NET_ACT_NAT is not set
++# CONFIG_NET_ACT_PEDIT is not set
++# CONFIG_NET_ACT_SIMP is not set
+ CONFIG_NET_CLS_POLICE=y
+ # CONFIG_NET_CLS_IND is not set
+-CONFIG_NET_ESTIMATOR=y
++CONFIG_NET_SCH_FIFO=y
+ 
+ #
+ # Network testing
+@@ -461,7 +513,18 @@ CONFIG_NET_PKTGEN=m
+ # CONFIG_HAMRADIO is not set
+ # CONFIG_IRDA is not set
+ # CONFIG_BT is not set
 +# CONFIG_AF_RXRPC is not set
++CONFIG_FIB_RULES=y
 +
 +#
 +# Wireless
@@ -21042,172 +27083,1675 @@
 +# CONFIG_CFG80211 is not set
 +# CONFIG_WIRELESS_EXT is not set
 +# CONFIG_MAC80211 is not set
-+# CONFIG_IEEE80211 is not set
+ # CONFIG_IEEE80211 is not set
 +# CONFIG_RFKILL is not set
 +# CONFIG_NET_9P is not set
-+
-+#
-+# Device Drivers
-+#
-+
-+#
-+# Generic Driver Options
-+#
+ 
+ #
+ # Device Drivers
+@@ -470,19 +533,14 @@ CONFIG_NET_PKTGEN=m
+ #
+ # Generic Driver Options
+ #
 +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-+# CONFIG_STANDALONE is not set
-+# CONFIG_PREVENT_FIRMWARE_BUILD is not set
+ CONFIG_STANDALONE=y
+ CONFIG_PREVENT_FIRMWARE_BUILD=y
+-# CONFIG_FW_LOADER is not set
 +CONFIG_FW_LOADER=y
-+# CONFIG_DEBUG_DRIVER is not set
+ # CONFIG_DEBUG_DRIVER is not set
+-
+-#
+-# Connector - unified userspace <-> kernelspace linker
+-#
 +# CONFIG_DEBUG_DEVRES is not set
 +# CONFIG_SYS_HYPERVISOR is not set
-+# CONFIG_CONNECTOR is not set
-+# CONFIG_MTD is not set
-+# CONFIG_PARPORT is not set
-+# CONFIG_BLK_DEV is not set
-+# CONFIG_MISC_DEVICES is not set
-+# CONFIG_IDE is not set
+ # CONFIG_CONNECTOR is not set
+-
+-#
+-# Memory Technology Devices (MTD)
+-#
+ CONFIG_MTD=y
+ # CONFIG_MTD_DEBUG is not set
+ # CONFIG_MTD_CONCAT is not set
+@@ -498,11 +556,14 @@ CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+ # User Modules And Translation Layers
+ #
+ CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
+ CONFIG_MTD_BLOCK=y
+ # CONFIG_FTL is not set
+ # CONFIG_NFTL is not set
+ # CONFIG_INFTL is not set
+ # CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
+ 
+ #
+ # RAM/ROM/Flash chip drivers
+@@ -528,7 +589,6 @@ CONFIG_MTD_CFI_UTIL=y
+ # CONFIG_MTD_RAM is not set
+ # CONFIG_MTD_ROM is not set
+ # CONFIG_MTD_ABSENT is not set
+-# CONFIG_MTD_XIP is not set
+ 
+ #
+ # Mapping drivers for chip access
+@@ -538,6 +598,7 @@ CONFIG_MTD_COMPLEX_MAPPINGS=y
+ # CONFIG_MTD_ARM_INTEGRATOR is not set
+ CONFIG_MTD_IXP4XX=y
+ # CONFIG_MTD_PCI is not set
++# CONFIG_MTD_INTEL_VR_NOR is not set
+ # CONFIG_MTD_PLATRAM is not set
+ 
+ #
+@@ -547,7 +608,6 @@ CONFIG_MTD_IXP4XX=y
+ # CONFIG_MTD_SLRAM is not set
+ # CONFIG_MTD_PHRAM is not set
+ # CONFIG_MTD_MTDRAM is not set
+-# CONFIG_MTD_BLKMTD is not set
+ # CONFIG_MTD_BLOCK2MTD is not set
+ 
+ #
+@@ -556,33 +616,24 @@ CONFIG_MTD_IXP4XX=y
+ # CONFIG_MTD_DOC2000 is not set
+ # CONFIG_MTD_DOC2001 is not set
+ # CONFIG_MTD_DOC2001PLUS is not set
+-
+-#
+-# NAND Flash Device Drivers
+-#
+ CONFIG_MTD_NAND=m
+ # CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_NAND_ECC_SMC is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+ CONFIG_MTD_NAND_IDS=m
+ # CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_CAFE is not set
+ # CONFIG_MTD_NAND_NANDSIM is not set
+-
+-#
+-# OneNAND Flash Device Drivers
+-#
++# CONFIG_MTD_NAND_PLATFORM is not set
++# CONFIG_MTD_ALAUDA is not set
+ # CONFIG_MTD_ONENAND is not set
+ 
+ #
+-# Parallel port support
++# UBI - Unsorted block images
+ #
++# CONFIG_MTD_UBI is not set
+ # CONFIG_PARPORT is not set
+-
+-#
+-# Plug and Play support
+-#
+-
+-#
+-# Block devices
+-#
++CONFIG_BLK_DEV=y
+ # CONFIG_BLK_CPQ_DA is not set
+ # CONFIG_BLK_CPQ_CISS_DA is not set
+ # CONFIG_BLK_DEV_DAC960 is not set
+@@ -592,17 +643,20 @@ CONFIG_BLK_DEV_LOOP=y
+ # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+ # CONFIG_BLK_DEV_NBD is not set
+ # CONFIG_BLK_DEV_SX8 is not set
++# CONFIG_BLK_DEV_UB is not set
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_COUNT=16
+ CONFIG_BLK_DEV_RAM_SIZE=8192
+-CONFIG_BLK_DEV_INITRD=y
++CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+ # CONFIG_CDROM_PKTCDVD is not set
+ # CONFIG_ATA_OVER_ETH is not set
+-
+-#
+-# ATA/ATAPI/MFM/RLL support
+-#
++CONFIG_MISC_DEVICES=y
++# CONFIG_PHANTOM is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_SGI_IOC4 is not set
++# CONFIG_TIFM_CORE is not set
+ CONFIG_IDE=y
++CONFIG_IDE_MAX_HWIFS=4
+ CONFIG_BLK_DEV_IDE=y
+ 
+ #
+@@ -614,24 +668,28 @@ CONFIG_BLK_DEV_IDEDISK=y
+ # CONFIG_BLK_DEV_IDECD is not set
+ # CONFIG_BLK_DEV_IDETAPE is not set
+ # CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
+ # CONFIG_IDE_TASK_IOCTL is not set
++CONFIG_IDE_PROC_FS=y
+ 
+ #
+ # IDE chipset support/bugfixes
+ #
+ CONFIG_IDE_GENERIC=y
++# CONFIG_BLK_DEV_PLATFORM is not set
 +
 +#
-+# SCSI device support
++# PCI IDE chipsets support
 +#
-+# CONFIG_RAID_ATTRS is not set
-+# CONFIG_SCSI is not set
-+# CONFIG_SCSI_DMA is not set
+ CONFIG_BLK_DEV_IDEPCI=y
+ # CONFIG_IDEPCI_SHARE_IRQ is not set
++CONFIG_IDEPCI_PCIBUS_ORDER=y
+ # CONFIG_BLK_DEV_OFFBOARD is not set
+ # CONFIG_BLK_DEV_GENERIC is not set
+ # CONFIG_BLK_DEV_OPTI621 is not set
+-# CONFIG_BLK_DEV_SL82C105 is not set
+ CONFIG_BLK_DEV_IDEDMA_PCI=y
+-# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+-# CONFIG_IDEDMA_PCI_AUTO is not set
+ # CONFIG_BLK_DEV_AEC62XX is not set
+ # CONFIG_BLK_DEV_ALI15X3 is not set
+-# CONFIG_BLK_DEV_AMD74XX is not set
+ CONFIG_BLK_DEV_CMD64X=y
+ # CONFIG_BLK_DEV_TRIFLEX is not set
+ # CONFIG_BLK_DEV_CY82C693 is not set
+@@ -639,93 +697,163 @@ CONFIG_BLK_DEV_CMD64X=y
+ # CONFIG_BLK_DEV_CS5530 is not set
+ # CONFIG_BLK_DEV_HPT34X is not set
+ CONFIG_BLK_DEV_HPT366=y
++# CONFIG_BLK_DEV_JMICRON is not set
+ # CONFIG_BLK_DEV_SC1200 is not set
+ # CONFIG_BLK_DEV_PIIX is not set
++# CONFIG_BLK_DEV_IT8213 is not set
+ # CONFIG_BLK_DEV_IT821X is not set
+ # CONFIG_BLK_DEV_NS87415 is not set
+ # CONFIG_BLK_DEV_PDC202XX_OLD is not set
+ CONFIG_BLK_DEV_PDC202XX_NEW=y
+-# CONFIG_PDC202XX_FORCE is not set
+ # CONFIG_BLK_DEV_SVWKS is not set
+ # CONFIG_BLK_DEV_SIIMAGE is not set
++# CONFIG_BLK_DEV_SL82C105 is not set
+ # CONFIG_BLK_DEV_SLC90E66 is not set
+ # CONFIG_BLK_DEV_TRM290 is not set
+ # CONFIG_BLK_DEV_VIA82CXXX is not set
++# CONFIG_BLK_DEV_TC86C001 is not set
+ # CONFIG_IDE_ARM is not set
+ CONFIG_BLK_DEV_IDEDMA=y
+-# CONFIG_IDEDMA_IVB is not set
+-# CONFIG_IDEDMA_AUTO is not set
++CONFIG_IDE_ARCH_OBSOLETE_INIT=y
+ # CONFIG_BLK_DEV_HD is not set
+ 
+ #
+ # SCSI device support
+ #
+ # CONFIG_RAID_ATTRS is not set
+-# CONFIG_SCSI is not set
+-
+-#
+-# Multi-device support (RAID and LVM)
+-#
++CONFIG_SCSI=y
++CONFIG_SCSI_DMA=y
++# CONFIG_SCSI_TGT is not set
 +# CONFIG_SCSI_NETLINK is not set
-+# CONFIG_ATA is not set
-+# CONFIG_MD is not set
-+CONFIG_NETDEVICES=y
-+# CONFIG_NETDEVICES_MULTIQUEUE is not set
-+# CONFIG_DUMMY is not set
-+# CONFIG_BONDING is not set
-+# CONFIG_MACVLAN is not set
-+# CONFIG_EQUALIZER is not set
-+# CONFIG_TUN is not set
-+# CONFIG_VETH is not set
-+# CONFIG_PHYLIB is not set
-+CONFIG_NET_ETHERNET=y
-+CONFIG_MII=y
-+# CONFIG_AX88796 is not set
-+CONFIG_SMC91X=y
-+# CONFIG_DM9000 is not set
-+# CONFIG_SMC911X is not set
-+# CONFIG_IBM_NEW_EMAC_ZMII is not set
-+# CONFIG_IBM_NEW_EMAC_RGMII is not set
-+# CONFIG_IBM_NEW_EMAC_TAH is not set
-+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-+# CONFIG_B44 is not set
-+# CONFIG_NETDEV_1000 is not set
-+# CONFIG_NETDEV_10000 is not set
-+
-+#
-+# Wireless LAN
-+#
-+# CONFIG_WLAN_PRE80211 is not set
-+# CONFIG_WLAN_80211 is not set
-+# CONFIG_WAN is not set
-+# CONFIG_PPP is not set
-+# CONFIG_SLIP is not set
-+# CONFIG_SHAPER is not set
-+# CONFIG_NETCONSOLE is not set
-+# CONFIG_NETPOLL is not set
-+# CONFIG_NET_POLL_CONTROLLER is not set
-+# CONFIG_ISDN is not set
-+
-+#
-+# Input device support
-+#
-+CONFIG_INPUT=y
-+# CONFIG_INPUT_FF_MEMLESS is not set
-+# CONFIG_INPUT_POLLDEV is not set
-+
-+#
-+# Userland interfaces
-+#
-+CONFIG_INPUT_MOUSEDEV=y
-+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-+# CONFIG_INPUT_JOYDEV is not set
-+# CONFIG_INPUT_EVDEV is not set
-+# CONFIG_INPUT_EVBUG is not set
-+
-+#
-+# Input Device Drivers
-+#
-+# CONFIG_INPUT_KEYBOARD is not set
-+# CONFIG_INPUT_MOUSE is not set
-+# CONFIG_INPUT_JOYSTICK is not set
-+# CONFIG_INPUT_TABLET is not set
-+# CONFIG_INPUT_TOUCHSCREEN is not set
-+# CONFIG_INPUT_MISC is not set
-+
-+#
-+# Hardware I/O ports
-+#
-+# CONFIG_SERIO is not set
-+# CONFIG_GAMEPORT is not set
-+
-+#
-+# Character devices
-+#
-+CONFIG_VT=y
-+CONFIG_VT_CONSOLE=y
-+CONFIG_HW_CONSOLE=y
-+# CONFIG_VT_HW_CONSOLE_BINDING is not set
-+# CONFIG_SERIAL_NONSTANDARD is not set
-+
-+#
-+# Serial drivers
-+#
-+# CONFIG_SERIAL_8250 is not set
-+
-+#
-+# Non-8250 serial port support
-+#
-+CONFIG_SERIAL_PXA=y
-+CONFIG_SERIAL_PXA_CONSOLE=y
-+CONFIG_SERIAL_CORE=y
-+CONFIG_SERIAL_CORE_CONSOLE=y
-+CONFIG_UNIX98_PTYS=y
-+# CONFIG_LEGACY_PTYS is not set
-+# CONFIG_IPMI_HANDLER is not set
-+# CONFIG_HW_RANDOM is not set
-+# CONFIG_NVRAM is not set
-+# CONFIG_R3964 is not set
-+# CONFIG_RAW_DRIVER is not set
-+# CONFIG_TCG_TPM is not set
-+# CONFIG_I2C is not set
-+
-+#
-+# SPI support
-+#
-+# CONFIG_SPI is not set
-+# CONFIG_SPI_MASTER is not set
-+# CONFIG_W1 is not set
-+# CONFIG_POWER_SUPPLY is not set
-+# CONFIG_HWMON is not set
-+# CONFIG_WATCHDOG is not set
++# CONFIG_SCSI_PROC_FS is not set
 +
 +#
-+# Sonics Silicon Backplane
++# SCSI support type (disk, tape, CD-ROM)
 +#
-+CONFIG_SSB_POSSIBLE=y
-+# CONFIG_SSB is not set
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
 +
 +#
-+# Multifunction device drivers
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 +#
-+# CONFIG_MFD_SM501 is not set
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++CONFIG_SCSI_WAIT_SCAN=m
 +
 +#
-+# Multimedia devices
-+#
-+# CONFIG_VIDEO_DEV is not set
-+# CONFIG_DVB_CORE is not set
-+# CONFIG_DAB is not set
-+
++# SCSI Transports
 +#
-+# Graphics support
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_LIBSAS is not set
++# CONFIG_SCSI_SRP_ATTRS is not set
++# CONFIG_SCSI_LOWLEVEL is not set
++CONFIG_ATA=y
++# CONFIG_ATA_NONSTANDARD is not set
++# CONFIG_SATA_AHCI is not set
++# CONFIG_SATA_SVW is not set
++# CONFIG_ATA_PIIX is not set
++# CONFIG_SATA_MV is not set
++# CONFIG_SATA_NV is not set
++# CONFIG_PDC_ADMA is not set
++# CONFIG_SATA_QSTOR is not set
++# CONFIG_SATA_PROMISE is not set
++# CONFIG_SATA_SX4 is not set
++# CONFIG_SATA_SIL is not set
++# CONFIG_SATA_SIL24 is not set
++# CONFIG_SATA_SIS is not set
++# CONFIG_SATA_ULI is not set
++# CONFIG_SATA_VIA is not set
++# CONFIG_SATA_VITESSE is not set
++# CONFIG_SATA_INIC162X is not set
++# CONFIG_PATA_ALI is not set
++# CONFIG_PATA_AMD is not set
++CONFIG_PATA_ARTOP=y
++# CONFIG_PATA_ATIIXP is not set
++# CONFIG_PATA_CMD640_PCI is not set
++# CONFIG_PATA_CMD64X is not set
++# CONFIG_PATA_CS5520 is not set
++# CONFIG_PATA_CS5530 is not set
++# CONFIG_PATA_CYPRESS is not set
++# CONFIG_PATA_EFAR is not set
++# CONFIG_ATA_GENERIC is not set
++# CONFIG_PATA_HPT366 is not set
++# CONFIG_PATA_HPT37X is not set
++# CONFIG_PATA_HPT3X2N is not set
++# CONFIG_PATA_HPT3X3 is not set
++# CONFIG_PATA_IT821X is not set
++# CONFIG_PATA_IT8213 is not set
++# CONFIG_PATA_JMICRON is not set
++# CONFIG_PATA_TRIFLEX is not set
++# CONFIG_PATA_MARVELL is not set
++# CONFIG_PATA_MPIIX is not set
++# CONFIG_PATA_OLDPIIX is not set
++# CONFIG_PATA_NETCELL is not set
++# CONFIG_PATA_NS87410 is not set
++# CONFIG_PATA_NS87415 is not set
++# CONFIG_PATA_OPTI is not set
++# CONFIG_PATA_OPTIDMA is not set
++# CONFIG_PATA_PDC_OLD is not set
++# CONFIG_PATA_RADISYS is not set
++# CONFIG_PATA_RZ1000 is not set
++# CONFIG_PATA_SC1200 is not set
++# CONFIG_PATA_SERVERWORKS is not set
++# CONFIG_PATA_PDC2027X is not set
++# CONFIG_PATA_SIL680 is not set
++# CONFIG_PATA_SIS is not set
++# CONFIG_PATA_VIA is not set
++# CONFIG_PATA_WINBOND is not set
++# CONFIG_PATA_PLATFORM is not set
++CONFIG_PATA_IXP4XX_CF=y
+ # CONFIG_MD is not set
+-
+-#
+-# Fusion MPT device support
+-#
+ # CONFIG_FUSION is not set
+ 
+ #
+ # IEEE 1394 (FireWire) support
+ #
++# CONFIG_FIREWIRE is not set
+ # CONFIG_IEEE1394 is not set
+-
+-#
+-# I2O device support
+-#
+ # CONFIG_I2O is not set
+-
+-#
+-# Network device support
+-#
+ CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_IFB is not set
+ CONFIG_DUMMY=y
+ # CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+-
+-#
+-# ARCnet devices
+-#
++# CONFIG_VETH is not set
+ # CONFIG_ARCNET is not set
+-
+-#
+-# PHY device support
+-#
+ # CONFIG_PHYLIB is not set
+-
+-#
+-# Ethernet (10 or 100Mbit)
+-#
+ CONFIG_NET_ETHERNET=y
+ CONFIG_MII=y
++CONFIG_IXP4XX_ETH=y
++# CONFIG_AX88796 is not set
+ # CONFIG_HAPPYMEAL is not set
+ # CONFIG_SUNGEM is not set
+ # CONFIG_CASSINI is not set
+ # CONFIG_NET_VENDOR_3COM is not set
+ # CONFIG_SMC91X is not set
+ # CONFIG_DM9000 is not set
+-
+-#
+-# Tulip family network device support
+-#
+ # CONFIG_NET_TULIP is not set
+ # CONFIG_HP100 is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+ CONFIG_NET_PCI=y
+ # CONFIG_PCNET32 is not set
+ # CONFIG_AMD8111_ETH is not set
+ # CONFIG_ADAPTEC_STARFIRE is not set
+ # CONFIG_B44 is not set
+ # CONFIG_FORCEDETH is not set
+-# CONFIG_DGRS is not set
+ CONFIG_EEPRO100=y
+ # CONFIG_E100 is not set
+ # CONFIG_FEALNX is not set
+@@ -738,93 +866,76 @@ CONFIG_EEPRO100=y
+ # CONFIG_SUNDANCE is not set
+ # CONFIG_TLAN is not set
+ # CONFIG_VIA_RHINE is not set
+-
+-#
+-# Ethernet (1000 Mbit)
+-#
++# CONFIG_SC92031 is not set
++CONFIG_NETDEV_1000=y
+ # CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ # CONFIG_E1000 is not set
++# CONFIG_E1000E is not set
++# CONFIG_IP1000 is not set
+ # CONFIG_NS83820 is not set
+ # CONFIG_HAMACHI is not set
+ # CONFIG_YELLOWFIN is not set
+ # CONFIG_R8169 is not set
+ # CONFIG_SIS190 is not set
+ # CONFIG_SKGE is not set
++# CONFIG_SKY2 is not set
+ # CONFIG_SK98LIN is not set
+ # CONFIG_VIA_VELOCITY is not set
+ # CONFIG_TIGON3 is not set
+ # CONFIG_BNX2 is not set
+-
+-#
+-# Ethernet (10000 Mbit)
+-#
++# CONFIG_QLA3XXX is not set
++# CONFIG_ATL1 is not set
++CONFIG_NETDEV_10000=y
+ # CONFIG_CHELSIO_T1 is not set
++# CONFIG_CHELSIO_T3 is not set
++# CONFIG_IXGBE is not set
+ # CONFIG_IXGB is not set
+ # CONFIG_S2IO is not set
+-
+-#
+-# Token Ring devices
+-#
++# CONFIG_MYRI10GE is not set
++# CONFIG_NETXEN_NIC is not set
++# CONFIG_NIU is not set
++# CONFIG_MLX4_CORE is not set
++# CONFIG_TEHUTI is not set
+ # CONFIG_TR is not set
+ 
+ #
+-# Wireless LAN (non-hamradio)
+-#
+-CONFIG_NET_RADIO=y
+-
+-#
+-# Obsolete Wireless cards support (pre-802.11)
+-#
+-# CONFIG_STRIP is not set
+-
+-#
+-# Wireless 802.11b ISA/PCI cards support
+-#
+-# CONFIG_AIRO is not set
+-CONFIG_HERMES=y
+-# CONFIG_PLX_HERMES is not set
+-# CONFIG_TMD_HERMES is not set
+-# CONFIG_NORTEL_HERMES is not set
+-CONFIG_PCI_HERMES=y
+-# CONFIG_ATMEL is not set
+-
+-#
+-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
++# Wireless LAN
+ #
+-# CONFIG_PRISM54 is not set
+-# CONFIG_HOSTAP is not set
+-CONFIG_NET_WIRELESS=y
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
+ 
+ #
+-# Wan interfaces
++# USB Network Adapters
+ #
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
+ CONFIG_WAN=y
+-# CONFIG_DSCC4 is not set
+ # CONFIG_LANMEDIA is not set
+-# CONFIG_SYNCLINK_SYNCPPP is not set
+ CONFIG_HDLC=m
+-CONFIG_HDLC_RAW=y
++CONFIG_HDLC_RAW=m
+ # CONFIG_HDLC_RAW_ETH is not set
+-CONFIG_HDLC_CISCO=y
+-CONFIG_HDLC_FR=y
+-CONFIG_HDLC_PPP=y
+-CONFIG_HDLC_X25=y
++CONFIG_HDLC_CISCO=m
++CONFIG_HDLC_FR=m
++CONFIG_HDLC_PPP=m
++CONFIG_HDLC_X25=m
+ # CONFIG_PCI200SYN is not set
+ # CONFIG_WANXL is not set
+ # CONFIG_PC300 is not set
++# CONFIG_PC300TOO is not set
+ # CONFIG_FARSYNC is not set
++# CONFIG_DSCC4 is not set
++# CONFIG_IXP4XX_HSS is not set
+ CONFIG_DLCI=m
+-CONFIG_DLCI_COUNT=24
+ CONFIG_DLCI_MAX=8
+-CONFIG_WAN_ROUTER_DRIVERS=y
++CONFIG_WAN_ROUTER_DRIVERS=m
+ # CONFIG_CYCLADES_SYNC is not set
+ # CONFIG_LAPBETHER is not set
+ # CONFIG_X25_ASY is not set
+-
+-#
+-# ATM drivers
+-#
++CONFIG_ATM_DRIVERS=y
+ # CONFIG_ATM_DUMMY is not set
+ CONFIG_ATM_TCP=m
+ # CONFIG_ATM_LANAI is not set
+@@ -842,20 +953,19 @@ CONFIG_ATM_TCP=m
+ # CONFIG_HIPPI is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
++# CONFIG_NET_FC is not set
+ # CONFIG_SHAPER is not set
+ # CONFIG_NETCONSOLE is not set
+ # CONFIG_NETPOLL is not set
+ # CONFIG_NET_POLL_CONTROLLER is not set
+-
+-#
+-# ISDN subsystem
+-#
+ # CONFIG_ISDN is not set
+ 
+ #
+ # Input device support
+ #
+ CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
+ 
+ #
+ # Userland interfaces
+@@ -865,7 +975,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
+ CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_JOYDEV is not set
+-# CONFIG_INPUT_TSDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_EVBUG is not set
+ 
+@@ -875,8 +984,16 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ # CONFIG_INPUT_KEYBOARD is not set
+ # CONFIG_INPUT_MOUSE is not set
+ # CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
+ # CONFIG_INPUT_TOUCHSCREEN is not set
+-# CONFIG_INPUT_MISC is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_IXP4XX_BEEPER=y
++# CONFIG_INPUT_ATI_REMOTE is not set
++# CONFIG_INPUT_ATI_REMOTE2 is not set
++# CONFIG_INPUT_KEYSPAN_REMOTE is not set
++# CONFIG_INPUT_POWERMATE is not set
++# CONFIG_INPUT_YEALINK is not set
++# CONFIG_INPUT_UINPUT is not set
+ 
+ #
+ # Hardware I/O ports
+@@ -895,7 +1012,9 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+ #
+ CONFIG_SERIAL_8250=y
+ CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_PCI=y
+ CONFIG_SERIAL_8250_NR_UARTS=2
++CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+ # CONFIG_SERIAL_8250_EXTENDED is not set
+ 
+ #
+@@ -907,51 +1026,17 @@ CONFIG_SERIAL_CORE_CONSOLE=y
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+ CONFIG_LEGACY_PTY_COUNT=256
+-
+-#
+-# IPMI
+-#
+ # CONFIG_IPMI_HANDLER is not set
+-
+-#
+-# Watchdog Cards
+-#
+-CONFIG_WATCHDOG=y
+-# CONFIG_WATCHDOG_NOWAYOUT is not set
+-
+-#
+-# Watchdog Device Drivers
+-#
+-# CONFIG_SOFT_WATCHDOG is not set
+-CONFIG_IXP4XX_WATCHDOG=y
+-
+-#
+-# PCI-based Watchdog Cards
+-#
+-# CONFIG_PCIPCWATCHDOG is not set
+-# CONFIG_WDTPCI is not set
++CONFIG_HW_RANDOM=m
++CONFIG_HW_RANDOM_IXP4XX=m
+ # CONFIG_NVRAM is not set
+-# CONFIG_RTC is not set
+-# CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_APPLICOM is not set
+-
+-#
+-# Ftape, the floppy tape device driver
+-#
+-# CONFIG_DRM is not set
+ # CONFIG_RAW_DRIVER is not set
+-
+-#
+-# TPM devices
+-#
+ # CONFIG_TCG_TPM is not set
+-# CONFIG_TELCLOCK is not set
+-
+-#
+-# I2C support
+-#
++CONFIG_DEVPORT=y
+ CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
+ CONFIG_I2C_CHARDEV=y
+ 
+ #
+@@ -969,57 +1054,68 @@ CONFIG_I2C_ALGOBIT=y
+ # CONFIG_I2C_ALI15X3 is not set
+ # CONFIG_I2C_AMD756 is not set
+ # CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_GPIO is not set
+ # CONFIG_I2C_I801 is not set
+ # CONFIG_I2C_I810 is not set
+ # CONFIG_I2C_PIIX4 is not set
+ # CONFIG_I2C_IOP3XX is not set
+ CONFIG_I2C_IXP4XX=y
+ # CONFIG_I2C_NFORCE2 is not set
++# CONFIG_I2C_OCORES is not set
+ # CONFIG_I2C_PARPORT_LIGHT is not set
+ # CONFIG_I2C_PROSAVAGE is not set
+ # CONFIG_I2C_SAVAGE4 is not set
+-# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_SIMTEC is not set
+ # CONFIG_I2C_SIS5595 is not set
+ # CONFIG_I2C_SIS630 is not set
+ # CONFIG_I2C_SIS96X is not set
++# CONFIG_I2C_TAOS_EVM is not set
+ # CONFIG_I2C_STUB is not set
++# CONFIG_I2C_TINY_USB is not set
+ # CONFIG_I2C_VIA is not set
+ # CONFIG_I2C_VIAPRO is not set
+ # CONFIG_I2C_VOODOO3 is not set
+-# CONFIG_I2C_PCA_ISA is not set
+ 
+ #
+ # Miscellaneous I2C Chip support
+ #
+ # CONFIG_SENSORS_DS1337 is not set
+ # CONFIG_SENSORS_DS1374 is not set
++# CONFIG_DS1682 is not set
+ CONFIG_SENSORS_EEPROM=y
+ # CONFIG_SENSORS_PCF8574 is not set
+ # CONFIG_SENSORS_PCA9539 is not set
+ # CONFIG_SENSORS_PCF8591 is not set
+-# CONFIG_SENSORS_RTC8564 is not set
+ # CONFIG_SENSORS_MAX6875 is not set
+-# CONFIG_RTC_X1205_I2C is not set
++# CONFIG_SENSORS_TSL2550 is not set
+ # CONFIG_I2C_DEBUG_CORE is not set
+ # CONFIG_I2C_DEBUG_ALGO is not set
+ # CONFIG_I2C_DEBUG_BUS is not set
+ # CONFIG_I2C_DEBUG_CHIP is not set
+ 
+ #
+-# Hardware Monitoring support
++# SPI support
+ #
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
+ CONFIG_HWMON=y
+ # CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_AD7418 is not set
+ # CONFIG_SENSORS_ADM1021 is not set
+ # CONFIG_SENSORS_ADM1025 is not set
+ # CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
+ # CONFIG_SENSORS_ADM1031 is not set
+ # CONFIG_SENSORS_ADM9240 is not set
+-# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ADT7470 is not set
+ # CONFIG_SENSORS_ATXP1 is not set
+ # CONFIG_SENSORS_DS1621 is not set
+-# CONFIG_SENSORS_FSCHER is not set
+-# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_I5K_AMB is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
+ # CONFIG_SENSORS_GL518SM is not set
+ # CONFIG_SENSORS_GL520SM is not set
+ # CONFIG_SENSORS_IT87 is not set
+@@ -1033,67 +1129,268 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_LM87 is not set
+ # CONFIG_SENSORS_LM90 is not set
+ # CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
+ # CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
+ # CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
+ # CONFIG_SENSORS_SIS5595 is not set
++# CONFIG_SENSORS_DME1737 is not set
+ # CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
+ # CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_THMC50 is not set
+ # CONFIG_SENSORS_VIA686A is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_VT8231 is not set
+ # CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
+ # CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
+ # CONFIG_SENSORS_W83L785TS is not set
+ # CONFIG_SENSORS_W83627HF is not set
+ # CONFIG_SENSORS_W83627EHF is not set
+ # CONFIG_HWMON_DEBUG_CHIP is not set
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
+ 
+ #
+-# Misc devices
++# Watchdog Device Drivers
+ #
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_IXP4XX_WATCHDOG=y
+ 
+ #
+-# Multimedia Capabilities Port drivers
++# PCI-based Watchdog Cards
+ #
++# CONFIG_PCIPCWATCHDOG is not set
++# CONFIG_WDTPCI is not set
+ 
+ #
+-# Multimedia devices
++# USB-based Watchdog Cards
+ #
+-# CONFIG_VIDEO_DEV is not set
++# CONFIG_USBPCWATCHDOG is not set
+ 
+ #
+-# Digital Video Broadcasting Devices
++# Sonics Silicon Backplane
+ #
+-# CONFIG_DVB is not set
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++CONFIG_DAB=y
++# CONFIG_USB_DABUSB is not set
+ 
+ #
+ # Graphics support
+ #
++# CONFIG_DRM is not set
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+ # CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
+ 
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HID_DEBUG is not set
++# CONFIG_HIDRAW is not set
+ 
+ #
+-# USB support
++# USB Input Devices
+ #
++CONFIG_USB_HID=y
++# CONFIG_USB_HIDINPUT_POWERBOOK is not set
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++CONFIG_USB_SUPPORT=y
+ CONFIG_USB_ARCH_HAS_HCD=y
+ CONFIG_USB_ARCH_HAS_OHCI=y
+-# CONFIG_USB is not set
++CONFIG_USB_ARCH_HAS_EHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_DEVICE_CLASS is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++CONFIG_USB_EHCI_HCD=y
++# CONFIG_USB_EHCI_SPLIT_ISO is not set
++# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
++# CONFIG_USB_EHCI_TT_NEWSCHED is not set
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
++# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++CONFIG_USB_UHCI_HCD=y
++# CONFIG_USB_SL811_HCD is not set
++# CONFIG_USB_R8A66597_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
+ 
+ #
+ # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+ #
+ 
+ #
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG 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_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
++# CONFIG_USB_STORAGE_ALAUDA is not set
++# CONFIG_USB_STORAGE_KARMA is not set
++# CONFIG_USB_LIBUSUAL is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_MON is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_ADUTUX is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_BERRY_CHARGE is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYPRESS_CY7C63 is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGET is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_FTDI_ELAN is not set
++# CONFIG_USB_APPLEDISPLAY is not set
++# CONFIG_USB_SISUSBVGA is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TRANCEVIBRATOR is not set
++# CONFIG_USB_IOWARRIOR is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++# CONFIG_USB_ATM is not set
++
++#
+ # USB Gadget Support
+ #
+ # CONFIG_USB_GADGET is not set
++# CONFIG_MMC is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
+ 
+ #
+-# MMC/SD Card support
++# LED drivers
++#
++# CONFIG_LEDS_IXP4XX is not set
++CONFIG_LEDS_GPIO=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGERS=y
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_IDE_DISK=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++# CONFIG_RTC_DRV_DS1307 is not set
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++CONFIG_RTC_DRV_X1205=y
++CONFIG_RTC_DRV_PCF8563=y
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++
++#
++# SPI RTC drivers
++#
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
+ #
+-# CONFIG_MMC is not set
+ 
+ #
+ # File systems
+@@ -1107,16 +1404,19 @@ CONFIG_EXT3_FS=y
+ CONFIG_EXT3_FS_XATTR=y
+ CONFIG_EXT3_FS_POSIX_ACL=y
+ # CONFIG_EXT3_FS_SECURITY is not set
++# CONFIG_EXT4DEV_FS is not set
+ CONFIG_JBD=y
+-# CONFIG_JBD_DEBUG is not set
+ CONFIG_FS_MBCACHE=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_JFS_FS is not set
+ CONFIG_FS_POSIX_ACL=y
+ # CONFIG_XFS_FS is not set
++# CONFIG_GFS2_FS is not set
++# CONFIG_OCFS2_FS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_ROMFS_FS is not set
+ CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
+ # CONFIG_QUOTA is not set
+ CONFIG_DNOTIFY=y
+ # CONFIG_AUTOFS_FS is not set
+@@ -1140,11 +1440,12 @@ CONFIG_DNOTIFY=y
+ # Pseudo filesystems
+ #
+ CONFIG_PROC_FS=y
++CONFIG_PROC_SYSCTL=y
+ CONFIG_SYSFS=y
+ CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
+ # CONFIG_HUGETLB_PAGE is not set
+-CONFIG_RAMFS=y
+-# CONFIG_RELAYFS_FS is not set
++# CONFIG_CONFIGFS_FS is not set
+ 
+ #
+ # Miscellaneous filesystems
+@@ -1156,13 +1457,15 @@ CONFIG_RAMFS=y
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BFS_FS is not set
+ # CONFIG_EFS_FS is not set
+-# CONFIG_JFFS_FS is not set
+ CONFIG_JFFS2_FS=y
+ CONFIG_JFFS2_FS_DEBUG=0
+ CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+ # CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
+ # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+ CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
+ CONFIG_JFFS2_RTIME=y
+ # CONFIG_JFFS2_RUBIN is not set
+ # CONFIG_CRAMFS is not set
+@@ -1171,10 +1474,7 @@ CONFIG_JFFS2_RTIME=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UFS_FS is not set
+-
+-#
+-# Network File Systems
+-#
++CONFIG_NETWORK_FILESYSTEMS=y
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_V3_ACL is not set
+@@ -1186,6 +1486,7 @@ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+ CONFIG_NFS_COMMON=y
+ CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_BIND34 is not set
+ # CONFIG_RPCSEC_GSS_KRB5 is not set
+ # CONFIG_RPCSEC_GSS_SPKM3 is not set
+ # CONFIG_SMB_FS is not set
+@@ -1193,7 +1494,6 @@ CONFIG_SUNRPC=y
+ # CONFIG_NCP_FS is not set
+ # CONFIG_CODA_FS is not set
+ # CONFIG_AFS_FS is not set
+-# CONFIG_9P_FS is not set
+ 
+ #
+ # Partition Types
+@@ -1213,37 +1513,53 @@ CONFIG_MSDOS_PARTITION=y
+ # CONFIG_SGI_PARTITION is not set
+ # CONFIG_ULTRIX_PARTITION is not set
+ # CONFIG_SUN_PARTITION is not set
++# CONFIG_KARMA_PARTITION is not set
+ # CONFIG_EFI_PARTITION is not set
+-
+-#
+-# Native Language Support
+-#
++# CONFIG_SYSV68_PARTITION is not set
+ # CONFIG_NLS is not set
+-
+-#
+-# Profiling support
+-#
++# CONFIG_DLM is not set
++CONFIG_INSTRUMENTATION=y
+ # CONFIG_PROFILING is not set
++# CONFIG_MARKERS is not set
+ 
+ #
+ # Kernel hacking
+ #
+ # CONFIG_PRINTK_TIME is not set
+-CONFIG_DEBUG_KERNEL=y
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
+ CONFIG_MAGIC_SYSRQ=y
+-CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_DEBUG_SHIRQ is not set
+ CONFIG_DETECT_SOFTLOCKUP=y
++CONFIG_SCHED_DEBUG=y
+ # CONFIG_SCHEDSTATS is not set
+-# CONFIG_DEBUG_SLAB is not set
++# CONFIG_TIMER_STATS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_DEBUG_RT_MUTEXES is not set
++# CONFIG_RT_MUTEX_TESTER is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_MUTEXES is not set
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
+ # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+ # CONFIG_DEBUG_KOBJECT is not set
+ CONFIG_DEBUG_BUGVERBOSE=y
+ # CONFIG_DEBUG_INFO is not set
+-# CONFIG_DEBUG_FS is not set
+ # CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_LIST is not set
++# CONFIG_DEBUG_SG is not set
+ CONFIG_FRAME_POINTER=y
++CONFIG_FORCED_INLINING=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
+ # CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_SAMPLES is not set
+ # CONFIG_DEBUG_USER is not set
+ CONFIG_DEBUG_ERRORS=y
+ CONFIG_DEBUG_LL=y
+@@ -1254,22 +1570,22 @@ CONFIG_DEBUG_LL=y
+ #
+ # CONFIG_KEYS is not set
+ # CONFIG_SECURITY is not set
+-
+-#
+-# Cryptographic options
+-#
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+ # CONFIG_CRYPTO is not set
+ 
+ #
+-# Hardware crypto devices
+-#
+-
+-#
+ # Library routines
+ #
++CONFIG_BITREVERSE=y
+ # CONFIG_CRC_CCITT is not set
+ # CONFIG_CRC16 is not set
++# CONFIG_CRC_ITU_T is not set
+ CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
+ # CONFIG_LIBCRC32C is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
+diff --git a/arch/arm/configs/littleton_defconfig b/arch/arm/configs/littleton_defconfig
+new file mode 100644
+index 0000000..1db4969
+--- /dev/null
++++ b/arch/arm/configs/littleton_defconfig
+@@ -0,0 +1,783 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.24-rc5
++# Fri Dec 21 11:06:19 2007
++#
++CONFIG_ARM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++# CONFIG_NO_IOPORT is not set
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++CONFIG_HARDIRQS_SW_RESEND=y
++CONFIG_GENERIC_IRQ_PROBE=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++# CONFIG_ARCH_HAS_ILOG2_U32 is not set
++# CONFIG_ARCH_HAS_ILOG2_U64 is not set
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_ZONE_DMA=y
++CONFIG_ARCH_MTD_XIP=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++# CONFIG_TASKSTATS is not set
++# CONFIG_USER_NS is not set
++# CONFIG_PID_NS is not set
++# CONFIG_AUDIT is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_CGROUPS is not set
++CONFIG_FAIR_GROUP_SCHED=y
++CONFIG_FAIR_USER_SCHED=y
++# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_SYSFS_DEPRECATED=y
++# CONFIG_RELAY is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++# CONFIG_EMBEDDED is not set
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_ANON_INODES=y
++CONFIG_EPOLL=y
++CONFIG_SIGNALFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_VM_EVENT_COUNTERS=y
++CONFIG_SLAB=y
++# CONFIG_SLUB is not set
++# CONFIG_SLOB is not set
++CONFIG_RT_MUTEXES=y
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_LSF is not set
++# CONFIG_BLK_DEV_BSG is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++
++#
++# System Type
++#
++# CONFIG_ARCH_AAEC2000 is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_NETX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_IOP13XX is not set
++# CONFIG_ARCH_IOP32X is not set
++# CONFIG_ARCH_IOP33X is not set
++# CONFIG_ARCH_IXP23XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_MXC is not set
++# CONFIG_ARCH_PNX4008 is not set
++CONFIG_ARCH_PXA=y
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++
++#
++# Intel PXA2xx/PXA3xx Implementations
++#
++
++#
++# Supported PXA3xx Processor Variants
++#
++CONFIG_CPU_PXA300=y
++CONFIG_CPU_PXA310=y
++# CONFIG_CPU_PXA320 is not set
++# CONFIG_ARCH_LUBBOCK is not set
++# CONFIG_MACH_LOGICPD_PXA270 is not set
++# CONFIG_MACH_MAINSTONE is not set
++# CONFIG_ARCH_PXA_IDP is not set
++# CONFIG_PXA_SHARPSL is not set
++# CONFIG_MACH_TRIZEPS4 is not set
++# CONFIG_MACH_EM_X270 is not set
++# CONFIG_MACH_ZYLONITE is not set
++CONFIG_MACH_LITTLETON=y
++# CONFIG_MACH_ARMCORE is not set
++CONFIG_PXA3xx=y
++CONFIG_PXA_SSP=y
++
++#
++# Boot options
++#
++
++#
++# Power management
++#
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_XSC3=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5T=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_TLB_V4WBI=y
++CONFIG_CPU_CP15=y
++CONFIG_CPU_CP15_MMU=y
++CONFIG_IO_36=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_BPREDICT_DISABLE is not set
++# CONFIG_OUTER_CACHE is not set
++CONFIG_IWMMXT=y
++
++#
++# Bus support
++#
++# CONFIG_PCI_SYSCALL is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++CONFIG_TICK_ONESHOT=y
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++CONFIG_OABI_COMPAT=y
++# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++# CONFIG_SPARSEMEM_STATIC is not set
++# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++# CONFIG_RESOURCES_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=1
++CONFIG_BOUNCE=y
++CONFIG_VIRT_TO_BUS=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on console=ttyS2,38400 mem=64M"
++# CONFIG_XIP_KERNEL is not set
++# CONFIG_KEXEC is not set
++
++#
++# CPU Frequency scaling
++#
++# CONFIG_CPU_FREQ is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_SUSPEND_UP_POSSIBLE=y
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_XFRM_MODE_TRANSPORT=y
++CONFIG_INET_XFRM_MODE_TUNNEL=y
++CONFIG_INET_XFRM_MODE_BEET=y
++# CONFIG_INET_LRO is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_INET6_XFRM_TUNNEL is not set
++# CONFIG_INET6_TUNNEL is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++
++#
++# Wireless
++#
++# CONFIG_CFG80211 is not set
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_IEEE80211 is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++# CONFIG_STANDALONE is not set
++# CONFIG_PREVENT_FIRMWARE_BUILD is not set
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++# CONFIG_BLK_DEV is not set
++# CONFIG_MISC_DEVICES is not set
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_NETDEVICES_MULTIQUEUE is not set
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++# CONFIG_AX88796 is not set
++CONFIG_SMC91X=y
++# CONFIG_DM9000 is not set
++# CONFIG_SMC911X is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_B44 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_PXA=y
++CONFIG_SERIAL_PXA_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_NVRAM is not set
++# CONFIG_R3964 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++
++#
++# SPI support
++#
++# CONFIG_SPI is not set
++# CONFIG_SPI_MASTER is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_WATCHDOG is not set
++
++#
++# Sonics Silicon Backplane
++#
++CONFIG_SSB_POSSIBLE=y
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_SM501 is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_DAB is not set
++
++#
++# Graphics support
 +#
 +# CONFIG_VGASTATE is not set
 +# CONFIG_VIDEO_OUTPUT_CONTROL is not set
@@ -24871,17 +32415,134 @@
 +CONFIG_HAS_IOPORT=y
 +CONFIG_HAS_DMA=y
 diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
-index 593b565..faa7619 100644
+index 593b565..00d44c6 100644
 --- a/arch/arm/kernel/Makefile
 +++ b/arch/arm/kernel/Makefile
-@@ -19,6 +19,7 @@ obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
+@@ -19,6 +19,8 @@ obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
  obj-$(CONFIG_PCI)		+= bios32.o isa.o
  obj-$(CONFIG_SMP)		+= smp.o
  obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 +obj-$(CONFIG_KPROBES)		+= kprobes.o kprobes-decode.o
++obj-$(CONFIG_ATAGS_PROC)	+= atags.o
  obj-$(CONFIG_OABI_COMPAT)	+= sys_oabi-compat.o
  
  obj-$(CONFIG_CRUNCH)		+= crunch.o crunch-bits.o
+diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c
+new file mode 100644
+index 0000000..e2e934c
+--- /dev/null
++++ b/arch/arm/kernel/atags.c
+@@ -0,0 +1,86 @@
++#include <linux/slab.h>
++#include <linux/kexec.h>
++#include <linux/proc_fs.h>
++#include <asm/setup.h>
++#include <asm/types.h>
++#include <asm/page.h>
++
++struct buffer {
++	size_t size;
++	char *data;
++};
++static struct buffer tags_buffer;
++
++static int
++read_buffer(char* page, char** start, off_t off, int count,
++	int* eof, void* data)
++{
++	struct buffer *buffer = (struct buffer *)data;
++
++	if (off >= buffer->size) {
++		*eof = 1;
++		return 0;
++	}
++
++	count = min((int) (buffer->size - off), count);
++
++	memcpy(page, &buffer->data[off], count);
++
++	return count;
++}
++
++
++static int
++create_proc_entries(void)
++{
++	struct proc_dir_entry* tags_entry;
++
++	tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer);
++	if (!tags_entry)
++		return -ENOMEM;
++
++	return 0;
++}
++
++
++static char __initdata atags_copy_buf[KEXEC_BOOT_PARAMS_SIZE];
++static char __initdata *atags_copy;
++
++void __init save_atags(const struct tag *tags)
++{
++	atags_copy = atags_copy_buf;
++	memcpy(atags_copy, tags, KEXEC_BOOT_PARAMS_SIZE);
++}
++
++
++static int __init init_atags_procfs(void)
++{
++	struct tag *tag;
++	int error;
++
++	if (!atags_copy) {
++		printk(KERN_WARNING "Exporting ATAGs: No saved tags found\n");
++		return -EIO;
++	}
++
++	for (tag = (struct tag *) atags_copy; tag->hdr.size; tag = tag_next(tag))
++		;
++
++	tags_buffer.size = ((char *) tag - atags_copy) + sizeof(tag->hdr);
++	tags_buffer.data = kmalloc(tags_buffer.size, GFP_KERNEL);
++	if (tags_buffer.data == NULL)
++		return -ENOMEM;
++	memcpy(tags_buffer.data, atags_copy, tags_buffer.size);
++
++	error = create_proc_entries();
++	if (error) {
++		printk(KERN_ERR "Exporting ATAGs: not enough memory\n");
++		kfree(tags_buffer.data);
++		tags_buffer.size = 0;
++		tags_buffer.data = NULL;
++	}
++
++	return error;
++}
++
++arch_initcall(init_atags_procfs);
+diff --git a/arch/arm/kernel/atags.h b/arch/arm/kernel/atags.h
+new file mode 100644
+index 0000000..e5f028d
+--- /dev/null
++++ b/arch/arm/kernel/atags.h
+@@ -0,0 +1,5 @@
++#ifdef CONFIG_ATAGS_PROC
++extern void save_atags(struct tag *tags);
++#else
++static inline void save_atags(struct tag *tags) { }
++#endif
+diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
+index cecf658..283e14f 100644
+--- a/arch/arm/kernel/calls.S
++++ b/arch/arm/kernel/calls.S
+@@ -359,7 +359,7 @@
+ 		CALL(sys_kexec_load)
+ 		CALL(sys_utimensat)
+ 		CALL(sys_signalfd)
+-/* 350 */	CALL(sys_timerfd)
++/* 350 */	CALL(sys_ni_syscall)
+ 		CALL(sys_eventfd)
+ 		CALL(sys_fallocate)
+ #ifndef syscalls_counted
 diff --git a/arch/arm/kernel/dma-isa.c b/arch/arm/kernel/dma-isa.c
 index 0a3e9ad..2f080a3 100644
 --- a/arch/arm/kernel/dma-isa.c
@@ -27027,6 +34688,247 @@
 +	register_undef_hook(&kprobes_break_hook);
 +	return 0;
 +}
+diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
+index 863c664..db8f54a 100644
+--- a/arch/arm/kernel/machine_kexec.c
++++ b/arch/arm/kernel/machine_kexec.c
+@@ -21,6 +21,7 @@ extern void setup_mm_for_reboot(char mode);
+ extern unsigned long kexec_start_address;
+ extern unsigned long kexec_indirection_page;
+ extern unsigned long kexec_mach_type;
++extern unsigned long kexec_boot_atags;
+ 
+ /*
+  * Provide a dummy crash_notes definition while crash dump arrives to arm.
+@@ -62,6 +63,7 @@ void machine_kexec(struct kimage *image)
+ 	kexec_start_address = image->start;
+ 	kexec_indirection_page = page_list;
+ 	kexec_mach_type = machine_arch_type;
++	kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
+ 
+ 	/* copy our kernel relocation code to the control code page */
+ 	memcpy(reboot_code_buffer,
+diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S
+index 062c111..61930eb 100644
+--- a/arch/arm/kernel/relocate_kernel.S
++++ b/arch/arm/kernel/relocate_kernel.S
+@@ -7,23 +7,6 @@
+ 	.globl relocate_new_kernel
+ relocate_new_kernel:
+ 
+-	/* Move boot params back to where the kernel expects them */
+-
+-	ldr	r0,kexec_boot_params_address
+-	teq	r0,#0
+-	beq	8f
+-
+-	ldr	r1,kexec_boot_params_copy
+-	mov	r6,#KEXEC_BOOT_PARAMS_SIZE/4
+-7:
+-	ldr	r5,[r1],#4
+-	str	r5,[r0],#4
+-	subs	r6,r6,#1
+-	bne	7b
+-
+-8:
+-	/* Boot params moved, now go on with the kernel */
+-
+ 	ldr	r0,kexec_indirection_page
+ 	ldr	r1,kexec_start_address
+ 
+@@ -67,7 +50,7 @@ relocate_new_kernel:
+ 	mov lr,r1
+ 	mov r0,#0
+ 	ldr r1,kexec_mach_type
+-	ldr r2,kexec_boot_params_address
++	ldr r2,kexec_boot_atags
+ 	mov pc,lr
+ 
+ 	.globl kexec_start_address
+@@ -82,14 +65,9 @@ kexec_indirection_page:
+ kexec_mach_type:
+ 	.long	0x0
+ 
+-	/* phy addr where new kernel will expect to find boot params */
+-	.globl kexec_boot_params_address
+-kexec_boot_params_address:
+-	.long	0x0
+-
+-	/* phy addr where old kernel put a copy of orig boot params */
+-	.globl kexec_boot_params_copy
+-kexec_boot_params_copy:
++	/* phy addr of the atags for the new kernel */
++	.globl kexec_boot_atags
++kexec_boot_atags:
+ 	.long	0x0
+ 
+ relocate_new_kernel_end:
+diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
+index bf56eb3..d3941a7 100644
+--- a/arch/arm/kernel/setup.c
++++ b/arch/arm/kernel/setup.c
+@@ -24,7 +24,6 @@
+ #include <linux/interrupt.h>
+ #include <linux/smp.h>
+ #include <linux/fs.h>
+-#include <linux/kexec.h>
+ 
+ #include <asm/cpu.h>
+ #include <asm/elf.h>
+@@ -39,6 +38,7 @@
+ #include <asm/mach/time.h>
+ 
+ #include "compat.h"
++#include "atags.h"
+ 
+ #ifndef MEM_SIZE
+ #define MEM_SIZE	(16*1024*1024)
+@@ -62,6 +62,7 @@ extern int root_mountflags;
+ extern void _stext, _text, _etext, __data_start, _edata, _end;
+ 
+ unsigned int processor_id;
++EXPORT_SYMBOL(processor_id);
+ unsigned int __machine_arch_type;
+ EXPORT_SYMBOL(__machine_arch_type);
+ 
+@@ -784,23 +785,6 @@ static int __init customize_machine(void)
+ }
+ arch_initcall(customize_machine);
+ 
+-#ifdef CONFIG_KEXEC
+-
+-/* Physical addr of where the boot params should be for this machine */
+-extern unsigned long kexec_boot_params_address;
+-
+-/* Physical addr of the buffer into which the boot params are copied */
+-extern unsigned long kexec_boot_params_copy;
+-
+-/* Pointer to the boot params buffer, for manipulation and display */
+-unsigned long kexec_boot_params;
+-EXPORT_SYMBOL(kexec_boot_params);
+-
+-/* The buffer itself - make sure it is sized correctly */
+-static unsigned long kexec_boot_params_buf[(KEXEC_BOOT_PARAMS_SIZE + 3) / 4];
+-
+-#endif
+-
+ void __init setup_arch(char **cmdline_p)
+ {
+ 	struct tag *tags = (struct tag *)&init_tags;
+@@ -819,18 +803,6 @@ void __init setup_arch(char **cmdline_p)
+ 	else if (mdesc->boot_params)
+ 		tags = phys_to_virt(mdesc->boot_params);
+ 
+-#ifdef CONFIG_KEXEC
+-	kexec_boot_params_copy = virt_to_phys(kexec_boot_params_buf);
+-	kexec_boot_params = (unsigned long)kexec_boot_params_buf;
+-	if (__atags_pointer) {
+-		kexec_boot_params_address = __atags_pointer;
+-		memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
+-	} else if (mdesc->boot_params) {
+-		kexec_boot_params_address = mdesc->boot_params;
+-		memcpy((void *)kexec_boot_params, tags, KEXEC_BOOT_PARAMS_SIZE);
+-	}
+-#endif
+-
+ 	/*
+ 	 * If we have the old style parameters, convert them to
+ 	 * a tag list.
+@@ -846,6 +818,7 @@ void __init setup_arch(char **cmdline_p)
+ 	if (tags->hdr.tag == ATAG_CORE) {
+ 		if (meminfo.nr_banks != 0)
+ 			squash_mem_tags(tags);
++		save_atags(tags);
+ 		parse_tags(tags);
+ 	}
+ 
+diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
+index eafbb2b..eefae1d 100644
+--- a/arch/arm/kernel/smp.c
++++ b/arch/arm/kernel/smp.c
+@@ -150,7 +150,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
+ 	secondary_data.pgdir = 0;
+ 
+ 	*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
+-	pgd_free(pgd);
++	pgd_free(&init_mm, pgd);
+ 
+ 	if (ret) {
+ 		printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
+@@ -290,6 +290,11 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
+ 	local_irq_enable();
+ 	local_fiq_enable();
+ 
++	/*
++	 * Setup local timer for this CPU.
++	 */
++	local_timer_setup(cpu);
++
+ 	calibrate_delay();
+ 
+ 	smp_store_cpu_info(cpu);
+@@ -300,11 +305,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
+ 	cpu_set(cpu, cpu_online_map);
+ 
+ 	/*
+-	 * Setup local timer for this CPU.
+-	 */
+-	local_timer_setup(cpu);
+-
+-	/*
+ 	 * OK, it's off to the idle thread for us
+ 	 */
+ 	cpu_idle();
+@@ -454,6 +454,27 @@ int smp_call_function(void (*func)(void *info), void *info, int retry,
+ }
+ EXPORT_SYMBOL_GPL(smp_call_function);
+ 
++int smp_call_function_single(int cpu, void (*func)(void *info), void *info,
++			     int retry, int wait)
++{
++	/* prevent preemption and reschedule on another processor */
++	int current_cpu = get_cpu();
++	int ret = 0;
++
++	if (cpu == current_cpu) {
++		local_irq_disable();
++		func(info);
++		local_irq_enable();
++	} else
++		ret = smp_call_function_on_cpu(func, info, retry, wait,
++					       cpumask_of_cpu(cpu));
++
++	put_cpu();
++
++	return ret;
++}
++EXPORT_SYMBOL_GPL(smp_call_function_single);
++
+ void show_ipi_list(struct seq_file *p)
+ {
+ 	unsigned int cpu;
+@@ -481,8 +502,7 @@ void show_local_irqs(struct seq_file *p)
+ static void ipi_timer(void)
+ {
+ 	irq_enter();
+-	profile_tick(CPU_PROFILING);
+-	update_process_times(user_mode(get_irq_regs()));
++	local_timer_interrupt();
+ 	irq_exit();
+ }
+ 
+@@ -621,6 +641,11 @@ void smp_send_timer(void)
+ 	send_ipi_message(mask, IPI_TIMER);
+ }
+ 
++void smp_timer_broadcast(cpumask_t mask)
++{
++	send_ipi_message(mask, IPI_TIMER);
++}
++
+ void smp_send_stop(void)
+ {
+ 	cpumask_t mask = cpu_online_map;
 diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
 index 1533d3e..b5867ec 100644
 --- a/arch/arm/kernel/time.c
@@ -27191,7 +35093,7 @@
  }
  
 diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
-index 05a9f8a..5b0422c 100644
+index 05a9f8a..074dcd5 100644
 --- a/arch/arm/mach-at91/Kconfig
 +++ b/arch/arm/mach-at91/Kconfig
 @@ -22,6 +22,9 @@ config ARCH_AT91SAM9263
@@ -27242,7 +35144,7 @@
  	help
  	  On AT91SAM926x boards both types of NAND flash can be present
  	  (8 and 16 bit data bus width).
-@@ -219,6 +237,22 @@ config AT91_PROGRAMMABLE_CLOCKS
+@@ -219,6 +237,52 @@ config AT91_PROGRAMMABLE_CLOCKS
  	  Select this if you need to program one or more of the PCK0..PCK3
  	  programmable clock outputs.
  
@@ -27262,6 +35164,36 @@
 +	  system clock (of at least several MHz), rounding is less of a
 +	  problem so it can be safer to use a decimal values like 100.
 +
++choice
++	prompt "Select a UART for early kernel messages"
++
++config AT91_EARLY_DBGU
++	bool "DBGU"
++
++config AT91_EARLY_USART0
++	bool "USART0"
++
++config AT91_EARLY_USART1
++	bool "USART1"
++
++config AT91_EARLY_USART2
++	bool "USART2"
++	depends on ! ARCH_AT91X40
++
++config AT91_EARLY_USART3
++	bool "USART3"
++	depends on (ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9260)
++
++config AT91_EARLY_USART4
++	bool "USART4"
++	depends on ARCH_AT91SAM9260
++
++config AT91_EARLY_USART5
++	bool "USART5"
++	depends on ARCH_AT91SAM9260
++
++endchoice
++
  endmenu
  
  endif
@@ -31340,6 +39272,27 @@
  	return 0;
  }
  
+diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
+index 5c090c9..e38d237 100644
+--- a/arch/arm/mach-at91/at91sam926x_time.c
++++ b/arch/arm/mach-at91/at91sam926x_time.c
+@@ -49,8 +49,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
+ 	volatile long nr_ticks;
+ 
+ 	if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) {	/* This is a shared interrupt */
+-		write_seqlock(&xtime_lock);
+-
+ 		/* Get number to ticks performed before interrupt and clear PIT interrupt */
+ 		nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR));
+ 		do {
+@@ -58,7 +56,6 @@ static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id)
+ 			nr_ticks--;
+ 		} while (nr_ticks);
+ 
+-		write_sequnlock(&xtime_lock);
+ 		return IRQ_HANDLED;
+ 	} else
+ 		return IRQ_NONE;		/* not handled */
 diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
 index 2bd60a3..f43b5c3 100644
 --- a/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -32707,7 +40660,7 @@
  	at91_sys_write(AT91_CKGR_PLLBR, 0);
  
 diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
-index 77d4c0a..b5daf7f 100644
+index 77d4c0a..7b9ce7a 100644
 --- a/arch/arm/mach-at91/generic.h
 +++ b/arch/arm/mach-at91/generic.h
 @@ -15,6 +15,7 @@ extern void __init at91sam9261_initialize(unsigned long main_clock);
@@ -32726,8 +40679,18 @@
  extern void __init at91_aic_init(unsigned int priority[]);
  
   /* Timer */
+@@ -45,6 +47,9 @@ extern void at91_irq_resume(void);
+ #define AT91RM9200_BGA		4	/* AT91RM9200 BGA package has 4 banks */
+ 
+ struct at91_gpio_bank {
++	unsigned chipbase;		/* bank's first GPIO number */
++	void __iomem *regbase;		/* base of register bank */
++	struct at91_gpio_bank *next;	/* bank sharing same IRQ/clock/... */
+ 	unsigned short id;		/* peripheral ID */
+ 	unsigned long offset;		/* offset from system peripheral base */
+ 	struct clk *clock;		/* associated clock */
 diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
-index aa2d365..6aeddd6 100644
+index aa2d365..f629c2b 100644
 --- a/arch/arm/mach-at91/gpio.c
 +++ b/arch/arm/mach-at91/gpio.c
 @@ -13,6 +13,8 @@
@@ -32739,7 +40702,105 @@
  #include <linux/kernel.h>
  #include <linux/list.h>
  #include <linux/module.h>
-@@ -414,6 +416,66 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+@@ -31,12 +33,10 @@ static int gpio_banks;
+ 
+ static inline void __iomem *pin_to_controller(unsigned pin)
+ {
+-	void __iomem *sys_base = (void __iomem *) AT91_VA_BASE_SYS;
+-
+ 	pin -= PIN_BASE;
+ 	pin /= 32;
+ 	if (likely(pin < gpio_banks))
+-		return sys_base + gpio[pin].offset;
++		return gpio[pin].regbase;
+ 
+ 	return NULL;
+ }
+@@ -292,11 +292,11 @@ void at91_gpio_suspend(void)
+ 	int i;
+ 
+ 	for (i = 0; i < gpio_banks; i++) {
+-		u32 pio = gpio[i].offset;
++		void __iomem	*pio = gpio[i].regbase;
+ 
+-		backups[i] = at91_sys_read(pio + PIO_IMR);
+-		at91_sys_write(pio + PIO_IDR, backups[i]);
+-		at91_sys_write(pio + PIO_IER, wakeups[i]);
++		backups[i] = __raw_readl(pio + PIO_IMR);
++		__raw_writel(backups[i], pio + PIO_IDR);
++		__raw_writel(wakeups[i], pio + PIO_IER);
+ 
+ 		if (!wakeups[i])
+ 			clk_disable(gpio[i].clock);
+@@ -313,13 +313,13 @@ void at91_gpio_resume(void)
+ 	int i;
+ 
+ 	for (i = 0; i < gpio_banks; i++) {
+-		u32 pio = gpio[i].offset;
++		void __iomem	*pio = gpio[i].regbase;
+ 
+ 		if (!wakeups[i])
+ 			clk_enable(gpio[i].clock);
+ 
+-		at91_sys_write(pio + PIO_IDR, wakeups[i]);
+-		at91_sys_write(pio + PIO_IER, backups[i]);
++		__raw_writel(wakeups[i], pio + PIO_IDR);
++		__raw_writel(backups[i], pio + PIO_IER);
+ 	}
+ }
+ 
+@@ -359,7 +359,13 @@ static void gpio_irq_unmask(unsigned pin)
+ 
+ static int gpio_irq_type(unsigned pin, unsigned type)
+ {
+-	return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL;
++	switch (type) {
++	case IRQ_TYPE_NONE:
++	case IRQ_TYPE_EDGE_BOTH:
++		return 0;
++	default:
++		return -EINVAL;
++	}
+ }
+ 
+ static struct irq_chip gpio_irqchip = {
+@@ -374,20 +380,30 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
+ {
+ 	unsigned	pin;
+ 	struct irq_desc	*gpio;
++	struct at91_gpio_bank *bank;
+ 	void __iomem	*pio;
+ 	u32		isr;
+ 
+-	pio = get_irq_chip_data(irq);
++	bank = get_irq_chip_data(irq);
++	pio = bank->regbase;
+ 
+ 	/* temporarily mask (level sensitive) parent IRQ */
+ 	desc->chip->ack(irq);
+ 	for (;;) {
+-		/* reading ISR acks the pending (edge triggered) GPIO interrupt */
++		/* Reading ISR acks pending (edge triggered) GPIO interrupts.
++		 * When there none are pending, we're finished unless we need
++		 * to process multiple banks (like ID_PIOCDE on sam9263).
++		 */
+ 		isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR);
+-		if (!isr)
+-			break;
++		if (!isr) {
++			if (!bank->next)
++				break;
++			bank = bank->next;
++			pio = bank->regbase;
++			continue;
++		}
+ 
+-		pin = (unsigned) get_irq_data(irq);
++		pin = bank->chipbase;
+ 		gpio = &irq_desc[pin];
+ 
+ 		while (isr) {
+@@ -414,29 +430,86 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
  
  /*--------------------------------------------------------------------------*/
  
@@ -32806,6 +40867,75 @@
  /*
   * Called from the processor-specific init to enable GPIO interrupt support.
   */
+ void __init at91_gpio_irq_setup(void)
+ {
+-	unsigned	pioc, pin;
++	unsigned		pioc, pin;
++	struct at91_gpio_bank	*this, *prev;
+ 
+-	for (pioc = 0, pin = PIN_BASE;
+-			pioc < gpio_banks;
+-			pioc++) {
+-		void __iomem	*controller;
+-		unsigned	id = gpio[pioc].id;
++	for (pioc = 0, pin = PIN_BASE, this = gpio, prev = NULL;
++			pioc++ < gpio_banks;
++			prev = this, this++) {
++		unsigned	id = this->id;
+ 		unsigned	i;
+ 
+-		clk_enable(gpio[pioc].clock);	/* enable PIO controller's clock */
++		/* enable PIO controller's clock */
++		clk_enable(this->clock);
+ 
+-		controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset;
+-		__raw_writel(~0, controller + PIO_IDR);
++		__raw_writel(~0, this->regbase + PIO_IDR);
+ 
+-		set_irq_data(id, (void *) pin);
+-		set_irq_chip_data(id, controller);
+-
+-		for (i = 0; i < 32; i++, pin++) {
++		for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
+ 			/*
+ 			 * Can use the "simple" and not "edge" handler since it's
+ 			 * shorter, and the AIC handles interrupts sanely.
+@@ -446,6 +519,14 @@ void __init at91_gpio_irq_setup(void)
+ 			set_irq_flags(pin, IRQF_VALID);
+ 		}
+ 
++		/* The toplevel handler handles one bank of GPIOs, except
++		 * AT91SAM9263_ID_PIOCDE handles three... PIOC is first in
++		 * the list, so we only set up that handler.
++		 */
++		if (prev && prev->next == this)
++			continue;
++
++		set_irq_chip_data(id, this);
+ 		set_irq_chained_handler(id, gpio_irq_handler);
+ 	}
+ 	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
+@@ -456,8 +537,20 @@ void __init at91_gpio_irq_setup(void)
+  */
+ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
+ {
++	unsigned		i;
++	struct at91_gpio_bank	*last;
++
+ 	BUG_ON(nr_banks > MAX_GPIO_BANKS);
+ 
+ 	gpio = data;
+ 	gpio_banks = nr_banks;
++
++	for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) {
++		data->chipbase = PIN_BASE + i * 32;
++		data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS;
++
++		/* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
++		if (last && last->id == data->id)
++			last->next = data;
++	}
+ }
 diff --git a/arch/arm/mach-at91/leds.c b/arch/arm/mach-at91/leds.c
 index 0d51449..9cdcda5 100644
 --- a/arch/arm/mach-at91/leds.c
@@ -33695,6 +41825,51 @@
  #include <asm/mach/pci.h>
  
  /*
+diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
+index 61b2dfc..e774447 100644
+--- a/arch/arm/mach-ixp4xx/Kconfig
++++ b/arch/arm/mach-ixp4xx/Kconfig
+@@ -189,6 +189,20 @@ config IXP4XX_INDIRECT_PCI
+ 	  need to use the indirect method instead. If you don't know
+ 	  what you need, leave this option unselected.
+ 
++config IXP4XX_QMGR
++	tristate "IXP4xx Queue Manager support"
++	help
++	  This driver supports IXP4xx built-in hardware queue manager
++	  and is automatically selected by Ethernet and HSS drivers.
++
++config IXP4XX_NPE
++	tristate "IXP4xx Network Processor Engine support"
++	select HOTPLUG
++	select FW_LOADER
++	help
++	  This driver supports IXP4xx built-in network coprocessors
++	  and is automatically selected by Ethernet and HSS drivers.
++
+ endmenu
+ 
+ endif
+diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
+index 77e00ad..c195688 100644
+--- a/arch/arm/mach-ixp4xx/Makefile
++++ b/arch/arm/mach-ixp4xx/Makefile
+@@ -23,10 +23,12 @@ obj-$(CONFIG_MACH_AVILA)	+= avila-setup.o
+ obj-$(CONFIG_MACH_IXDPG425)	+= coyote-setup.o
+ obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-setup.o
+ obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-setup.o
+-obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o nslu2-power.o
+-obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o nas100d-power.o
+-obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
++obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o
++obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o
++obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o
+ obj-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-setup.o
+ obj-$(CONFIG_MACH_WG302V2)	+= wg302v2-setup.o
+ 
+ obj-$(CONFIG_PCI)		+= $(obj-pci-$(CONFIG_PCI)) common-pci.o
++obj-$(CONFIG_IXP4XX_QMGR)	+= ixp4xx_qmgr.o
++obj-$(CONFIG_IXP4XX_NPE)	+= ixp4xx_npe.o
 diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
 index d59b8dc..e38f45f 100644
 --- a/arch/arm/mach-ixp4xx/avila-setup.c
@@ -33740,19 +41915,183 @@
  	&avila_flash,
  	&avila_uart
  };
+diff --git a/arch/arm/mach-ixp4xx/dsmg600-power.c b/arch/arm/mach-ixp4xx/dsmg600-power.c
+deleted file mode 100644
+index 3471787..0000000
+--- a/arch/arm/mach-ixp4xx/dsmg600-power.c
++++ /dev/null
+@@ -1,125 +0,0 @@
+-/*
+- * arch/arm/mach-ixp4xx/dsmg600-power.c
+- *
+- * DSM-G600 Power/Reset driver
+- * Author: Michael Westerhof <mwester at dls.net>
+- *
+- * Based on nslu2-power.c
+- *  Copyright (C) 2005 Tower Technologies
+- *  Author: Alessandro Zummo <a.zummo at towertech.it>
+- *
+- * which was based on nslu2-io.c
+- *  Copyright (C) 2004 Karen Spearel
+- *
+- * Maintainers: http://www.nslu2-linux.org/
+- *
+- * 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/module.h>
+-#include <linux/reboot.h>
+-#include <linux/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/jiffies.h>
+-#include <linux/timer.h>
+-
+-#include <asm/mach-types.h>
+-
+-extern void ctrl_alt_del(void);
+-
+-/* This is used to make sure the power-button pusher is serious.  The button
+- * must be held until the value of this counter reaches zero.
+- */
+-static volatile int power_button_countdown;
+-
+-/* Must hold the button down for at least this many counts to be processed */
+-#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
+-
+-static void dsmg600_power_handler(unsigned long data);
+-static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
+-
+-static void dsmg600_power_handler(unsigned long data)
+-{
+-	/* This routine is called twice per second to check the
+-	 * state of the power button.
+-	 */
+-
+-	if (*IXP4XX_GPIO_GPINR & DSMG600_PB_BM) {
+-
+-		/* IO Pin is 1 (button pushed) */
+-		if (power_button_countdown == 0) {
+-			/* Signal init to do the ctrlaltdel action, this will bypass
+-			 * init if it hasn't started and do a kernel_restart.
+-			 */
+-			ctrl_alt_del();
+-
+-			/* Change the state of the power LED to "blink" */
+-			gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
+-		}
+-		power_button_countdown--;
+-
+-	} else {
+-		power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+-	}
+-
+-	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+-}
+-
+-static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
+-{
+-	/* This is the paper-clip reset, it shuts the machine down directly. */
+-	machine_power_off();
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static int __init dsmg600_power_init(void)
+-{
+-	if (!(machine_is_dsmg600()))
+-		return 0;
+-
+-	if (request_irq(DSMG600_RB_IRQ, &dsmg600_reset_handler,
+-		IRQF_DISABLED | IRQF_TRIGGER_LOW, "DSM-G600 reset button",
+-		NULL) < 0) {
+-
+-		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+-			DSMG600_RB_IRQ);
+-
+-		return -EIO;
+-	}
+-
+-	/* The power button on the D-Link DSM-G600 is on GPIO 15, but
+-	 * it cannot handle interrupts on that GPIO line.  So we'll
+-	 * have to poll it with a kernel timer.
+-	 */
+-
+-	/* Make sure that the power button GPIO is set up as an input */
+-	gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
+-
+-	/* Set the initial value for the power button IRQ handler */
+-	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
+-
+-	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+-
+-	return 0;
+-}
+-
+-static void __exit dsmg600_power_exit(void)
+-{
+-	if (!(machine_is_dsmg600()))
+-		return;
+-
+-	del_timer_sync(&dsmg600_power_timer);
+-
+-	free_irq(DSMG600_RB_IRQ, NULL);
+-}
+-
+-module_init(dsmg600_power_init);
+-module_exit(dsmg600_power_exit);
+-
+-MODULE_AUTHOR("Michael Westerhof <mwester at dls.net>");
+-MODULE_DESCRIPTION("DSM-G600 Power/Reset driver");
+-MODULE_LICENSE("GPL");
 diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
-index 1e75e10..c473d40 100644
+index 1e75e10..6886596 100644
 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
 +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
-@@ -14,6 +14,7 @@
- #include <linux/kernel.h>
+@@ -1,24 +1,37 @@
+ /*
+  * DSM-G600 board-setup
+  *
++ * Copyright (C) 2008 Rod Whitby <rod at whitby.id.au>
+  * Copyright (C) 2006 Tower Technologies
+- * Author: Alessandro Zummo <a.zummo at towertech.it>
+  *
+- * based ixdp425-setup.c:
++ * based on ixdp425-setup.c:
+  *      Copyright (C) 2003-2004 MontaVista Software, Inc.
++ * based on nslu2-power.c:
++ *	Copyright (C) 2005 Tower Technologies
++ * based on nslu2-io.c:
++ *	Copyright (C) 2004 Karen Spearel
+  *
+  * Author: Alessandro Zummo <a.zummo at towertech.it>
++ * Author: Michael Westerhof <mwester at dls.net>
++ * Author: Rod Whitby <rod at whitby.id.au>
+  * Maintainers: http://www.nslu2-linux.org/
+  */
+ 
+-#include <linux/kernel.h>
++#include <linux/irq.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
  #include <linux/serial.h>
  #include <linux/serial_8250.h>
++#include <linux/leds.h>
++#include <linux/reboot.h>
++#include <linux/i2c.h>
 +#include <linux/i2c-gpio.h>
  
  #include <asm/mach-types.h>
  #include <asm/mach/arch.h>
-@@ -37,15 +38,17 @@ static struct platform_device dsmg600_flash = {
+ #include <asm/mach/flash.h>
+ #include <asm/mach/time.h>
++#include <asm/gpio.h>
+ 
+ static struct flash_platform_data dsmg600_flash_data = {
+ 	.map_name		= "cfi_probe",
+@@ -37,40 +50,47 @@ static struct platform_device dsmg600_flash = {
  	.resource		= &dsmg600_flash_resource,
  };
  
@@ -33773,18 +42112,166 @@
 +	},
  };
  
- #ifdef CONFIG_LEDS_CLASS
-@@ -116,7 +119,7 @@ static struct platform_device dsmg600_uart = {
+-#ifdef CONFIG_LEDS_CLASS
+-static struct resource dsmg600_led_resources[] = {
++static struct i2c_board_info __initdata dsmg600_i2c_board_info [] = {
+ 	{
+-		.name           = "power",
+-		.start          = DSMG600_LED_PWR_GPIO,
+-		.end            = DSMG600_LED_PWR_GPIO,
+-		.flags          = IXP4XX_GPIO_HIGH,
++		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
+ 	},
++};
++
++static struct gpio_led dsmg600_led_pins[] = {
+ 	{
+-		.name           = "wlan",
+-		.start		= DSMG600_LED_WLAN_GPIO,
+-		.end            = DSMG600_LED_WLAN_GPIO,
+-		.flags          = IXP4XX_GPIO_LOW,
++		.name		= "power",
++		.gpio		= DSMG600_LED_PWR_GPIO,
+ 	},
++	{
++		.name		= "wlan",
++		.gpio		= DSMG600_LED_WLAN_GPIO,
++		.active_low	= true,
++	},
++};
++
++static struct gpio_led_platform_data dsmg600_led_data = {
++	.num_leds		= ARRAY_SIZE(dsmg600_led_pins),
++	.leds			= dsmg600_led_pins,
+ };
+ 
+ static struct platform_device dsmg600_leds = {
+-        .name                   = "IXP4XX-GPIO-LED",
+-        .id                     = -1,
+-        .num_resources          = ARRAY_SIZE(dsmg600_led_resources),
+-        .resource               = dsmg600_led_resources,
++	.name			= "leds-gpio",
++	.id			= -1,
++	.dev.platform_data	= &dsmg600_led_data,
+ };
+-#endif
+ 
+ static struct resource dsmg600_uart_resources[] = {
+ 	{
+@@ -116,8 +136,9 @@ static struct platform_device dsmg600_uart = {
  };
  
  static struct platform_device *dsmg600_devices[] __initdata = {
 -	&dsmg600_i2c_controller,
 +	&dsmg600_i2c_gpio,
  	&dsmg600_flash,
++	&dsmg600_leds,
  };
  
+ static void dsmg600_power_off(void)
+@@ -129,6 +150,57 @@ static void dsmg600_power_off(void)
+ 	gpio_line_set(DSMG600_PO_GPIO, IXP4XX_GPIO_HIGH);
+ }
+ 
++/* This is used to make sure the power-button pusher is serious.  The button
++ * must be held until the value of this counter reaches zero.
++ */
++static int power_button_countdown;
++
++/* Must hold the button down for at least this many counts to be processed */
++#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
++
++static void dsmg600_power_handler(unsigned long data);
++static DEFINE_TIMER(dsmg600_power_timer, dsmg600_power_handler, 0, 0);
++
++static void dsmg600_power_handler(unsigned long data)
++{
++	/* This routine is called twice per second to check the
++	 * state of the power button.
++	 */
++
++	if (gpio_get_value(DSMG600_PB_GPIO)) {
++
++		/* IO Pin is 1 (button pushed) */
++		if (power_button_countdown > 0)
++			power_button_countdown--;
++
++	} else {
++
++		/* Done on button release, to allow for auto-power-on mods. */
++		if (power_button_countdown == 0) {
++			/* Signal init to do the ctrlaltdel action,
++			 * this will bypass init if it hasn't started
++			 * and do a kernel_restart.
++			 */
++			ctrl_alt_del();
++
++			/* Change the state of the power LED to "blink" */
++			gpio_line_set(DSMG600_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
++		} else {
++			power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
++		}
++	}
++
++	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
++}
++
++static irqreturn_t dsmg600_reset_handler(int irq, void *dev_id)
++{
++	/* This is the paper-clip reset, it shuts the machine down directly. */
++	machine_power_off();
++
++	return IRQ_HANDLED;
++}
++
+ static void __init dsmg600_timer_init(void)
+ {
+     /* The xtal on this machine is non-standard. */
+@@ -153,7 +225,8 @@ static void __init dsmg600_init(void)
+ 	dsmg600_flash_resource.end =
+ 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+ 
+-	pm_power_off = dsmg600_power_off;
++	i2c_register_board_info(0, dsmg600_i2c_board_info,
++				ARRAY_SIZE(dsmg600_i2c_board_info));
+ 
+ 	/* The UART is required on the DSM-G600 (Redboot cannot use the
+ 	 * NIC) -- do it here so that it does *not* get removed if
+@@ -163,10 +236,28 @@ static void __init dsmg600_init(void)
+ 
+ 	platform_add_devices(dsmg600_devices, ARRAY_SIZE(dsmg600_devices));
+ 
+-#ifdef CONFIG_LEDS_CLASS
+-        /* We don't care whether or not this works. */
+-        (void)platform_device_register(&dsmg600_leds);
+-#endif
++	pm_power_off = dsmg600_power_off;
++
++	if (request_irq(gpio_to_irq(DSMG600_RB_GPIO), &dsmg600_reset_handler,
++		IRQF_DISABLED | IRQF_TRIGGER_LOW,
++		"DSM-G600 reset button", NULL) < 0) {
++
++		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
++			gpio_to_irq(DSMG600_RB_GPIO));
++	}
++
++	/* The power button on the D-Link DSM-G600 is on GPIO 15, but
++	 * it cannot handle interrupts on that GPIO line.  So we'll
++	 * have to poll it with a kernel timer.
++	 */
++
++	/* Make sure that the power button GPIO is set up as an input */
++	gpio_line_config(DSMG600_PB_GPIO, IXP4XX_GPIO_IN);
++
++	/* Set the initial value for the power button IRQ handler */
++	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
++
++	mod_timer(&dsmg600_power_timer, jiffies + msecs_to_jiffies(500));
+ }
+ 
+ MACHINE_START(DSMG600, "D-Link DSM-G600 RevA")
 diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
-index d5008d8..e89070d 100644
+index d5008d8..44584af 100644
 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
 +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
 @@ -15,6 +15,7 @@
@@ -33819,387 +42306,2038 @@
  };
  
  static struct resource ixdp425_uart_resources[] = {
-@@ -178,7 +178,7 @@ static struct platform_device ixdp425_uart = {
+@@ -177,14 +177,41 @@ static struct platform_device ixdp425_uart = {
+ 	.resource		= ixdp425_uart_resources
  };
  
++/* Built-in 10/100 Ethernet MAC interfaces */
++static struct eth_plat_info ixdp425_plat_eth[] = {
++	{
++		.phy		= 0,
++		.rxq		= 3,
++		.txreadyq	= 20,
++	}, {
++		.phy		= 1,
++		.rxq		= 4,
++		.txreadyq	= 21,
++	}
++};
++
++static struct platform_device ixdp425_eth[] = {
++	{
++		.name			= "ixp4xx_eth",
++		.id			= IXP4XX_ETH_NPEB,
++		.dev.platform_data	= ixdp425_plat_eth,
++	}, {
++		.name			= "ixp4xx_eth",
++		.id			= IXP4XX_ETH_NPEC,
++		.dev.platform_data	= ixdp425_plat_eth + 1,
++	}
++};
++
  static struct platform_device *ixdp425_devices[] __initdata = {
 -	&ixdp425_i2c_controller,
 +	&ixdp425_i2c_gpio,
  	&ixdp425_flash,
  #if defined(CONFIG_MTD_NAND_PLATFORM) || \
      defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
-diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
-index 78a1741..54d884f 100644
---- a/arch/arm/mach-ixp4xx/nas100d-setup.c
-+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
-@@ -16,6 +16,7 @@
- #include <linux/serial.h>
- #include <linux/serial_8250.h>
- #include <linux/leds.h>
-+#include <linux/i2c-gpio.h>
- 
- #include <asm/mach-types.h>
- #include <asm/mach/arch.h>
-@@ -68,16 +69,17 @@ static struct platform_device nas100d_leds = {
- };
- #endif
- 
--static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = {
-+static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
- 	.sda_pin		= NAS100D_SDA_PIN,
- 	.scl_pin		= NAS100D_SCL_PIN,
- };
- 
--static struct platform_device nas100d_i2c_controller = {
--	.name			= "IXP4XX-I2C",
-+static struct platform_device nas100d_i2c_gpio = {
-+	.name			= "i2c-gpio",
- 	.id			= 0,
--	.dev.platform_data	= &nas100d_i2c_gpio_pins,
--	.num_resources		= 0,
-+	.dev	 = {
-+		.platform_data	= &nas100d_i2c_gpio_data,
-+	},
- };
- 
- static struct resource nas100d_uart_resources[] = {
-@@ -124,7 +126,7 @@ static struct platform_device nas100d_uart = {
- };
- 
- static struct platform_device *nas100d_devices[] __initdata = {
--	&nas100d_i2c_controller,
-+	&nas100d_i2c_gpio,
- 	&nas100d_flash,
- #ifdef CONFIG_LEDS_IXP4XX
- 	&nas100d_leds,
-diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
-index acd71e9..6f10dc2 100644
---- a/arch/arm/mach-ixp4xx/nslu2-power.c
-+++ b/arch/arm/mach-ixp4xx/nslu2-power.c
-@@ -21,7 +21,6 @@
- #include <linux/reboot.h>
- #include <linux/irq.h>
- #include <linux/interrupt.h>
--#include <linux/reboot.h>
- 
- #include <asm/mach-types.h>
- 
-diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
-index 9bf8ccb..77277d2 100644
---- a/arch/arm/mach-ixp4xx/nslu2-setup.c
-+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
-@@ -18,6 +18,7 @@
- #include <linux/serial.h>
- #include <linux/serial_8250.h>
- #include <linux/leds.h>
-+#include <linux/i2c-gpio.h>
- 
- #include <asm/mach-types.h>
- #include <asm/mach/arch.h>
-@@ -41,7 +42,7 @@ static struct platform_device nslu2_flash = {
- 	.resource		= &nslu2_flash_resource,
- };
- 
--static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = {
-+static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
- 	.sda_pin		= NSLU2_SDA_PIN,
- 	.scl_pin		= NSLU2_SCL_PIN,
- };
-@@ -82,11 +83,12 @@ static struct platform_device nslu2_leds = {
- };
+ 	&ixdp425_flash_nand,
  #endif
- 
--static struct platform_device nslu2_i2c_controller = {
--	.name			= "IXP4XX-I2C",
-+static struct platform_device nslu2_i2c_gpio = {
-+	.name			= "i2c-gpio",
- 	.id			= 0,
--	.dev.platform_data	= &nslu2_i2c_gpio_pins,
--	.num_resources		= 0,
-+	.dev	 = {
-+		.platform_data	= &nslu2_i2c_gpio_data,
-+	},
- };
- 
- static struct platform_device nslu2_beeper = {
-@@ -139,7 +141,7 @@ static struct platform_device nslu2_uart = {
+-	&ixdp425_uart
++	&ixdp425_uart,
++	&ixdp425_eth[0],
++	&ixdp425_eth[1],
  };
  
- static struct platform_device *nslu2_devices[] __initdata = {
--	&nslu2_i2c_controller,
-+	&nslu2_i2c_gpio,
- 	&nslu2_flash,
- 	&nslu2_beeper,
- #ifdef CONFIG_LEDS_IXP4XX
-diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
-index 2a07a28..730a3af 100644
---- a/arch/arm/mach-ks8695/Makefile
-+++ b/arch/arm/mach-ks8695/Makefile
-@@ -9,7 +9,7 @@ obj-n				:=
- obj-				:=
- 
- # PCI support is optional
--#obj-$(CONFIG_PCI)		+= pci.o
-+obj-$(CONFIG_PCI)		+= pci.o
- 
- # Board-specific support
- obj-$(CONFIG_MACH_KS8695)	+= board-micrel.o
-diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
-index 2feeef8..05ac2bd 100644
---- a/arch/arm/mach-ks8695/board-micrel.c
-+++ b/arch/arm/mach-ks8695/board-micrel.c
-@@ -40,7 +40,7 @@ static void __init micrel_init(void)
- 	printk(KERN_INFO "Micrel KS8695 Development Board initializing\n");
- 
- #ifdef CONFIG_PCI
--//	ks8695_init_pci(&micrel_pci);
-+	ks8695_init_pci(&micrel_pci);
- #endif
- 
- 	/* Add devices */
-diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
-index b1aa3cb..5e46191 100644
---- a/arch/arm/mach-ks8695/gpio.c
-+++ b/arch/arm/mach-ks8695/gpio.c
-@@ -20,6 +20,8 @@
- #include <linux/kernel.h>
- #include <linux/mm.h>
- #include <linux/init.h>
-+#include <linux/debugfs.h>
-+#include <linux/seq_file.h>
- #include <linux/module.h>
- 
- #include <asm/io.h>
-@@ -216,3 +218,84 @@ int irq_to_gpio(unsigned int irq)
- 	return (irq - KS8695_IRQ_EXTERN0);
- }
- EXPORT_SYMBOL(irq_to_gpio);
+ static void __init ixdp425_init(void)
+diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+new file mode 100644
+index 0000000..83c137e
+--- /dev/null
++++ b/arch/arm/mach-ixp4xx/ixp4xx_npe.c
+@@ -0,0 +1,741 @@
++/*
++ * Intel IXP4xx Network Processor Engine driver for Linux
++ *
++ * Copyright (C) 2007 Krzysztof Halasa <khc at pm.waw.pl>
++ *
++ * 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 published by the Free Software Foundation.
++ *
++ * The code is based on publicly available information:
++ * - Intel IXP4xx Developer's Manual and other e-papers
++ * - Intel IXP400 Access Library Software (BSD license)
++ * - previous works by Christian Hohnstaedt <chohnstaedt at innominate.com>
++ *   Thanks, Christian.
++ */
++
++#include <linux/delay.h>
++#include <linux/dma-mapping.h>
++#include <linux/firmware.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <asm/arch/npe.h>
 +
++#define DEBUG_MSG			0
++#define DEBUG_FW			0
 +
-+/* .... Debug interface ..................................................... */
++#define NPE_COUNT			3
++#define MAX_RETRIES			1000	/* microseconds */
++#define NPE_42X_DATA_SIZE		0x800	/* in dwords */
++#define NPE_46X_DATA_SIZE		0x1000
++#define NPE_A_42X_INSTR_SIZE		0x1000
++#define NPE_B_AND_C_42X_INSTR_SIZE	0x800
++#define NPE_46X_INSTR_SIZE		0x1000
++#define REGS_SIZE			0x1000
++
++#define NPE_PHYS_REG			32
++
++#define FW_MAGIC			0xFEEDF00D
++#define FW_BLOCK_TYPE_INSTR		0x0
++#define FW_BLOCK_TYPE_DATA		0x1
++#define FW_BLOCK_TYPE_EOF		0xF
++
++/* NPE exec status (read) and command (write) */
++#define CMD_NPE_STEP			0x01
++#define CMD_NPE_START			0x02
++#define CMD_NPE_STOP			0x03
++#define CMD_NPE_CLR_PIPE		0x04
++#define CMD_CLR_PROFILE_CNT		0x0C
++#define CMD_RD_INS_MEM			0x10 /* instruction memory */
++#define CMD_WR_INS_MEM			0x11
++#define CMD_RD_DATA_MEM			0x12 /* data memory */
++#define CMD_WR_DATA_MEM			0x13
++#define CMD_RD_ECS_REG			0x14 /* exec access register */
++#define CMD_WR_ECS_REG			0x15
++
++#define STAT_RUN			0x80000000
++#define STAT_STOP			0x40000000
++#define STAT_CLEAR			0x20000000
++#define STAT_ECS_K			0x00800000 /* pipeline clean */
++
++#define NPE_STEVT			0x1B
++#define NPE_STARTPC			0x1C
++#define NPE_REGMAP			0x1E
++#define NPE_CINDEX			0x1F
++
++#define INSTR_WR_REG_SHORT		0x0000C000
++#define INSTR_WR_REG_BYTE		0x00004000
++#define INSTR_RD_FIFO			0x0F888220
++#define INSTR_RESET_MBOX		0x0FAC8210
++
++#define ECS_BG_CTXT_REG_0		0x00 /* Background Executing Context */
++#define ECS_BG_CTXT_REG_1		0x01 /*		Stack level */
++#define ECS_BG_CTXT_REG_2		0x02
++#define ECS_PRI_1_CTXT_REG_0		0x04 /* Priority 1 Executing Context */
++#define ECS_PRI_1_CTXT_REG_1		0x05 /*		Stack level */
++#define ECS_PRI_1_CTXT_REG_2		0x06
++#define ECS_PRI_2_CTXT_REG_0		0x08 /* Priority 2 Executing Context */
++#define ECS_PRI_2_CTXT_REG_1		0x09 /*		Stack level */
++#define ECS_PRI_2_CTXT_REG_2		0x0A
++#define ECS_DBG_CTXT_REG_0		0x0C /* Debug Executing Context */
++#define ECS_DBG_CTXT_REG_1		0x0D /*		Stack level */
++#define ECS_DBG_CTXT_REG_2		0x0E
++#define ECS_INSTRUCT_REG		0x11 /* NPE Instruction Register */
++
++#define ECS_REG_0_ACTIVE		0x80000000 /* all levels */
++#define ECS_REG_0_NEXTPC_MASK		0x1FFF0000 /* BG/PRI1/PRI2 levels */
++#define ECS_REG_0_LDUR_BITS		8
++#define ECS_REG_0_LDUR_MASK		0x00000700 /* all levels */
++#define ECS_REG_1_CCTXT_BITS		16
++#define ECS_REG_1_CCTXT_MASK		0x000F0000 /* all levels */
++#define ECS_REG_1_SELCTXT_BITS		0
++#define ECS_REG_1_SELCTXT_MASK		0x0000000F /* all levels */
++#define ECS_DBG_REG_2_IF		0x00100000 /* debug level */
++#define ECS_DBG_REG_2_IE		0x00080000 /* debug level */
++
++/* NPE watchpoint_fifo register bit */
++#define WFIFO_VALID			0x80000000
++
++/* NPE messaging_status register bit definitions */
++#define MSGSTAT_OFNE	0x00010000 /* OutFifoNotEmpty */
++#define MSGSTAT_IFNF	0x00020000 /* InFifoNotFull */
++#define MSGSTAT_OFNF	0x00040000 /* OutFifoNotFull */
++#define MSGSTAT_IFNE	0x00080000 /* InFifoNotEmpty */
++#define MSGSTAT_MBINT	0x00100000 /* Mailbox interrupt */
++#define MSGSTAT_IFINT	0x00200000 /* InFifo interrupt */
++#define MSGSTAT_OFINT	0x00400000 /* OutFifo interrupt */
++#define MSGSTAT_WFINT	0x00800000 /* WatchFifo interrupt */
++
++/* NPE messaging_control register bit definitions */
++#define MSGCTL_OUT_FIFO			0x00010000 /* enable output FIFO */
++#define MSGCTL_IN_FIFO			0x00020000 /* enable input FIFO */
++#define MSGCTL_OUT_FIFO_WRITE		0x01000000 /* enable FIFO + WRITE */
++#define MSGCTL_IN_FIFO_WRITE		0x02000000
++
++/* NPE mailbox_status value for reset */
++#define RESET_MBOX_STAT			0x0000F0F0
++
++const char *npe_names[] = { "NPE-A", "NPE-B", "NPE-C" };
++
++#define print_npe(pri, npe, fmt, ...)					\
++	printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__)
++
++#if DEBUG_MSG
++#define debug_msg(npe, fmt, ...)					\
++	print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__)
++#else
++#define debug_msg(npe, fmt, ...)
++#endif
 +
-+#ifdef CONFIG_DEBUG_FS
++static struct {
++	u32 reg, val;
++} ecs_reset[] = {
++	{ ECS_BG_CTXT_REG_0,	0xA0000000 },
++	{ ECS_BG_CTXT_REG_1,	0x01000000 },
++	{ ECS_BG_CTXT_REG_2,	0x00008000 },
++	{ ECS_PRI_1_CTXT_REG_0,	0x20000080 },
++	{ ECS_PRI_1_CTXT_REG_1,	0x01000000 },
++	{ ECS_PRI_1_CTXT_REG_2,	0x00008000 },
++	{ ECS_PRI_2_CTXT_REG_0,	0x20000080 },
++	{ ECS_PRI_2_CTXT_REG_1,	0x01000000 },
++	{ ECS_PRI_2_CTXT_REG_2,	0x00008000 },
++	{ ECS_DBG_CTXT_REG_0,	0x20000000 },
++	{ ECS_DBG_CTXT_REG_1,	0x00000000 },
++	{ ECS_DBG_CTXT_REG_2,	0x001E0000 },
++	{ ECS_INSTRUCT_REG,	0x1003C00F },
++};
 +
-+static int ks8695_gpio_show(struct seq_file *s, void *unused)
++static struct npe npe_tab[NPE_COUNT] = {
++	{
++		.id	= 0,
++		.regs	= (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT,
++		.regs_phys = IXP4XX_NPEA_BASE_PHYS,
++	}, {
++		.id	= 1,
++		.regs	= (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT,
++		.regs_phys = IXP4XX_NPEB_BASE_PHYS,
++	}, {
++		.id	= 2,
++		.regs	= (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT,
++		.regs_phys = IXP4XX_NPEC_BASE_PHYS,
++	}
++};
++
++int npe_running(struct npe *npe)
 +{
-+	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
-+	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
-+	unsigned long mode, ctrl, data;
-+	int i;
++	return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0;
++}
 +
-+	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
-+	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
-+	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
++static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data)
++{
++	__raw_writel(data, &npe->regs->exec_data);
++	__raw_writel(addr, &npe->regs->exec_addr);
++	__raw_writel(cmd, &npe->regs->exec_status_cmd);
++}
 +
-+	seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
++static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd)
++{
++	__raw_writel(addr, &npe->regs->exec_addr);
++	__raw_writel(cmd, &npe->regs->exec_status_cmd);
++	/* Iintroduce extra read cycles after issuing read command to NPE
++	   so that we read the register after the NPE has updated it.
++	   This is to overcome race condition between XScale and NPE */
++	__raw_readl(&npe->regs->exec_data);
++	__raw_readl(&npe->regs->exec_data);
++	return __raw_readl(&npe->regs->exec_data);
++}
 +
-+	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
-+		seq_printf(s, "%i:\t", i);
++static void npe_clear_active(struct npe *npe, u32 reg)
++{
++	u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG);
++	npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE);
++}
 +
-+		seq_printf(s, "%s\t", (mode & IOPM_(i)) ? "Output" : "Input");
++static void npe_start(struct npe *npe)
++{
++	/* ensure only Background Context Stack Level is active */
++	npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0);
++	npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0);
++	npe_clear_active(npe, ECS_DBG_CTXT_REG_0);
 +
-+		if (i <= KS8695_GPIO_3) {
-+			if (ctrl & enable[i]) {
-+				seq_printf(s, "EXT%i ", i);
++	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
++	__raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd);
++}
 +
-+				switch ((ctrl & intmask[i]) >> (4 * i)) {
-+					case IOPC_TM_LOW:
-+						seq_printf(s, "(Low)");		break;
-+					case IOPC_TM_HIGH:
-+						seq_printf(s, "(High)");	break;
-+					case IOPC_TM_RISING:
-+						seq_printf(s, "(Rising)");	break;
-+					case IOPC_TM_FALLING:
-+						seq_printf(s, "(Falling)");	break;
-+					case IOPC_TM_EDGE:
-+						seq_printf(s, "(Edges)");	break;
-+				}
-+			}
-+			else
-+				seq_printf(s, "GPIO\t");
-+		}
-+		else if (i <= KS8695_GPIO_5) {
-+			if (ctrl & enable[i])
-+				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
-+			else
-+				seq_printf(s, "GPIO\t");
-+		}
-+		else
-+			seq_printf(s, "GPIO\t");
++static void npe_stop(struct npe *npe)
++{
++	__raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd);
++	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/
++}
 +
-+		seq_printf(s, "\t");
++static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx,
++					u32 ldur)
++{
++	u32 wc;
++	int i;
 +
-+		seq_printf(s, "%i\n", (data & IOPD_(i)) ? 1 : 0);
++	/* set the Active bit, and the LDUR, in the debug level */
++	npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG,
++		      ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS));
++
++	/* set CCTXT at ECS DEBUG L3 to specify in which context to execute
++	   the instruction, and set SELCTXT at ECS DEBUG Level to specify
++	   which context store to access.
++	   Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
++	*/
++	npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG,
++		      (ctx << ECS_REG_1_CCTXT_BITS) |
++		      (ctx << ECS_REG_1_SELCTXT_BITS));
++
++	/* clear the pipeline */
++	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
++
++	/* load NPE instruction into the instruction register */
++	npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr);
++
++	/* we need this value later to wait for completion of NPE execution
++	   step */
++	wc = __raw_readl(&npe->regs->watch_count);
++
++	/* issue a Step One command via the Execution Control register */
++	__raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd);
++
++	/* Watch Count register increments when NPE completes an instruction */
++	for (i = 0; i < MAX_RETRIES; i++) {
++		if (wc != __raw_readl(&npe->regs->watch_count))
++			return 0;
++		udelay(1);
 +	}
-+	return 0;
++
++	print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n");
++	return -ETIMEDOUT;
 +}
 +
-+static int ks8695_gpio_open(struct inode *inode, struct file *file)
++static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr,
++					       u8 val, u32 ctx)
 +{
-+	return single_open(file, ks8695_gpio_show, NULL);
++	/* here we build the NPE assembler instruction: mov8 d0, #0 */
++	u32 instr = INSTR_WR_REG_BYTE |	/* OpCode */
++		addr << 9 |		/* base Operand */
++		(val & 0x1F) << 4 |	/* lower 5 bits to immediate data */
++		(val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */
++	return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
 +}
 +
-+static const struct file_operations ks8695_gpio_operations = {
-+	.open		= ks8695_gpio_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
-+};
-+
-+static int __init ks8695_gpio_debugfs_init(void)
++static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr,
++						u16 val, u32 ctx)
 +{
-+	/* /sys/kernel/debug/ks8695_gpio */
-+	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
-+	return 0;
++	/* here we build the NPE assembler instruction: mov16 d0, #0 */
++	u32 instr = INSTR_WR_REG_SHORT | /* OpCode */
++		addr << 9 |		/* base Operand */
++		(val & 0x1F) << 4 |	/* lower 5 bits to immediate data */
++		(val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */
++	return npe_debug_instr(npe, instr, ctx, 1); /* execute it */
 +}
-+postcore_initcall(ks8695_gpio_debugfs_init);
-+
-+#endif
-diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c
-new file mode 100644
-index 0000000..3f4e033
---- /dev/null
-+++ b/arch/arm/mach-ks8695/pci.c
-@@ -0,0 +1,326 @@
-+/*
-+ * arch/arm/mach-ks8695/pci.c
-+ *
-+ *  Copyright (C) 2003, Micrel Semiconductors
-+ *  Copyright (C) 2006, Greg Ungerer <gerg at snapgear.com>
-+ *  Copyright (C) 2006, Ben Dooks
-+ *  Copyright (C) 2007, Andrew Victor
-+ *
-+ * 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 <linux/kernel.h>
-+#include <linux/pci.h>
-+#include <linux/mm.h>
-+#include <linux/init.h>
-+#include <linux/irq.h>
-+#include <linux/delay.h>
 +
-+#include <asm/io.h>
-+#include <asm/signal.h>
-+#include <asm/mach/pci.h>
-+#include <asm/hardware.h>
++static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr,
++						u32 val, u32 ctx)
++{
++	/* write in 16 bit steps first the high and then the low value */
++	if (npe_logical_reg_write16(npe, addr, val >> 16, ctx))
++		return -ETIMEDOUT;
++	return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx);
++}
 +
-+#include <asm/arch/devices.h>
-+#include <asm/arch/regs-pci.h>
++static int npe_reset(struct npe *npe)
++{
++	u32 val, ctl, exec_count, ctx_reg2;
++	int i;
 +
++	ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) &
++		0x3F3FFFFF;
 +
-+static int pci_dbg;
-+static int pci_cfg_dbg;
++	/* disable parity interrupt */
++	__raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control);
 +
++	/* pre exec - debug instruction */
++	/* turn off the halt bit by clearing Execution Count register. */
++	exec_count = __raw_readl(&npe->regs->exec_count);
++	__raw_writel(0, &npe->regs->exec_count);
++	/* ensure that IF and IE are on (temporarily), so that we don't end up
++	   stepping forever */
++	ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG);
++	npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 |
++		      ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE);
 +
-+static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where)
-+{
-+	unsigned long pbca;
++	/* clear the FIFOs */
++	while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID)
++		;
++	while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE)
++		/* read from the outFIFO until empty */
++		print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n",
++			  __raw_readl(&npe->regs->in_out_fifo));
++
++	while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)
++		/* step execution of the NPE intruction to read inFIFO using
++		   the Debug Executing Context stack */
++		if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0))
++			return -ETIMEDOUT;
 +
-+	pbca = PBCA_ENABLE | (where & ~3);
-+	pbca |= PCI_SLOT(devfn) << 11 ;
-+	pbca |= PCI_FUNC(devfn) << 8;
-+	pbca |= bus_nr << 16;
++	/* reset the mailbox reg from the XScale side */
++	__raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status);
++	/* from NPE side */
++	if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0))
++		return -ETIMEDOUT;
 +
-+	if (bus_nr == 0) {
-+		/* use Type-0 transaction */
-+		__raw_writel(pbca, KS8695_PCI_VA + KS8695_PBCA);
-+	} else {
-+		/* use Type-1 transaction */
-+		__raw_writel(pbca | PBCA_TYPE1, KS8695_PCI_VA + KS8695_PBCA);
++	/* Reset the physical registers in the NPE register file */
++	for (val = 0; val < NPE_PHYS_REG; val++) {
++		if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0))
++			return -ETIMEDOUT;
++		/* address is either 0 or 4 */
++		if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0))
++			return -ETIMEDOUT;
 +	}
-+}
-+
 +
-+/*
-+ * The KS8695 datasheet prohibits anything other than 32bit accesses
-+ * to the IO registers, so all our configuration must be done with
-+ * 32bit operations, and the correct bit masking and shifting.
-+ */
++	/* Reset the context store = each context's Context Store registers */
 +
-+static int ks8695_pci_readconfig(struct pci_bus *bus,
-+			unsigned int devfn, int where, int size, u32 *value)
-+{
-+	ks8695_pci_setupconfig(bus->number, devfn, where);
++	/* Context 0 has no STARTPC. Instead, this value is used to set NextPC
++	   for Background ECS, to set where NPE starts executing code */
++	val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG);
++	val &= ~ECS_REG_0_NEXTPC_MASK;
++	val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK;
++	npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val);
 +
-+	*value = __raw_readl(KS8695_PCI_VA +  KS8695_PBCD);
++	for (i = 0; i < 16; i++) {
++		if (i) {	/* Context 0 has no STEVT nor STARTPC */
++			/* STEVT = off, 0x80 */
++			if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i))
++				return -ETIMEDOUT;
++			if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i))
++				return -ETIMEDOUT;
++		}
++		/* REGMAP = d0->p0, d8->p2, d16->p4 */
++		if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i))
++			return -ETIMEDOUT;
++		if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i))
++			return -ETIMEDOUT;
++	}
 +
-+	switch (size) {
-+		case 4:
-+			break;
-+		case 2:
-+			*value = *value >> ((where & 2) * 8);
-+			*value &= 0xffff;
-+			break;
-+		case 1:
-+			*value = *value >> ((where & 3) * 8);
-+			*value &= 0xff;
-+			break;
++	/* post exec */
++	/* clear active bit in debug level */
++	npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0);
++	/* clear the pipeline */
++	__raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd);
++	/* restore previous values */
++	__raw_writel(exec_count, &npe->regs->exec_count);
++	npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2);
++
++	/* write reset values to Execution Context Stack registers */
++	for (val = 0; val < ARRAY_SIZE(ecs_reset); val++)
++		npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG,
++			      ecs_reset[val].val);
++
++	/* clear the profile counter */
++	__raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd);
++
++	__raw_writel(0, &npe->regs->exec_count);
++	__raw_writel(0, &npe->regs->action_points[0]);
++	__raw_writel(0, &npe->regs->action_points[1]);
++	__raw_writel(0, &npe->regs->action_points[2]);
++	__raw_writel(0, &npe->regs->action_points[3]);
++	__raw_writel(0, &npe->regs->watch_count);
++
++	val = ixp4xx_read_feature_bits();
++	/* reset the NPE */
++	ixp4xx_write_feature_bits(val &
++				  ~(IXP4XX_FEATURE_RESET_NPEA << npe->id));
++	for (i = 0; i < MAX_RETRIES; i++) {
++		if (!(ixp4xx_read_feature_bits() &
++		      (IXP4XX_FEATURE_RESET_NPEA << npe->id)))
++			break;	/* reset completed */
++		udelay(1);
 +	}
++	if (i == MAX_RETRIES)
++		return -ETIMEDOUT;
 +
-+	if (pci_cfg_dbg) {
-+		printk("read: %d,%08x,%02x,%d: %08x (%08x)\n",
-+			bus->number, devfn, where, size, *value,
-+			__raw_readl(KS8695_PCI_VA +  KS8695_PBCD));
++	/* deassert reset */
++	ixp4xx_write_feature_bits(val |
++				  (IXP4XX_FEATURE_RESET_NPEA << npe->id));
++	for (i = 0; i < MAX_RETRIES; i++) {
++		if (ixp4xx_read_feature_bits() &
++		    (IXP4XX_FEATURE_RESET_NPEA << npe->id))
++			break;	/* NPE is back alive */
++		udelay(1);
 +	}
++	if (i == MAX_RETRIES)
++		return -ETIMEDOUT;
 +
-+	return PCIBIOS_SUCCESSFUL;
++	npe_stop(npe);
++
++	/* restore NPE configuration bus Control Register - parity settings */
++	__raw_writel(ctl, &npe->regs->messaging_control);
++	return 0;
 +}
 +
-+static int ks8695_pci_writeconfig(struct pci_bus *bus,
-+			unsigned int devfn, int where, int size, u32 value)
++
++int npe_send_message(struct npe *npe, const void *msg, const char *what)
 +{
-+	unsigned long tmp;
++	const u32 *send = msg;
++	int cycles = 0;
 +
-+	if (pci_cfg_dbg) {
-+		printk("write: %d,%08x,%02x,%d: %08x\n",
-+			bus->number, devfn, where, size, value);
++	debug_msg(npe, "Trying to send message %s [%08X:%08X]\n",
++		  what, send[0], send[1]);
++
++	if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) {
++		debug_msg(npe, "NPE input FIFO not empty\n");
++		return -EIO;
 +	}
 +
-+	ks8695_pci_setupconfig(bus->number, devfn, where);
++	__raw_writel(send[0], &npe->regs->in_out_fifo);
 +
-+	switch (size) {
-+		case 4:
-+			__raw_writel(value, KS8695_PCI_VA +  KS8695_PBCD);
-+			break;
-+		case 2:
-+			tmp = __raw_readl(KS8695_PCI_VA +  KS8695_PBCD);
-+			tmp &= ~(0xffff << ((where & 2) * 8));
-+			tmp |= value << ((where & 2) * 8);
++	if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) {
++		debug_msg(npe, "NPE input FIFO full\n");
++		return -EIO;
++	}
 +
-+			__raw_writel(tmp, KS8695_PCI_VA +  KS8695_PBCD);
-+			break;
-+		case 1:
-+			tmp = __raw_readl(KS8695_PCI_VA +  KS8695_PBCD);
-+			tmp &= ~(0xff << ((where & 3) * 8));
-+			tmp |= value << ((where & 3) * 8);
++	__raw_writel(send[1], &npe->regs->in_out_fifo);
 +
-+			__raw_writel(tmp, KS8695_PCI_VA +  KS8695_PBCD);
-+			break;
++	while ((cycles < MAX_RETRIES) &&
++	       (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) {
++		udelay(1);
++		cycles++;
 +	}
 +
-+	return PCIBIOS_SUCCESSFUL;
++	if (cycles == MAX_RETRIES) {
++		debug_msg(npe, "Timeout sending message\n");
++		return -ETIMEDOUT;
++	}
++
++	debug_msg(npe, "Sending a message took %i cycles\n", cycles);
++	return 0;
 +}
 +
-+static void ks8695_local_writeconfig(int where, u32 value)
++int npe_recv_message(struct npe *npe, void *msg, const char *what)
 +{
-+	ks8695_pci_setupconfig(0, 0, where);
-+	__raw_writel(value, KS8695_PCI_VA + KS8695_PBCD);
-+}
++	u32 *recv = msg;
++	int cycles = 0, cnt = 0;
 +
-+static struct pci_ops ks8695_pci_ops = {
++	debug_msg(npe, "Trying to receive message %s\n", what);
++
++	while (cycles < MAX_RETRIES) {
++		if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) {
++			recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo);
++			if (cnt == 2)
++				break;
++		} else {
++			udelay(1);
++			cycles++;
++		}
++	}
++
++	switch(cnt) {
++	case 1:
++		debug_msg(npe, "Received [%08X]\n", recv[0]);
++		break;
++	case 2:
++		debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]);
++		break;
++	}
++
++	if (cycles == MAX_RETRIES) {
++		debug_msg(npe, "Timeout waiting for message\n");
++		return -ETIMEDOUT;
++	}
++
++	debug_msg(npe, "Receiving a message took %i cycles\n", cycles);
++	return 0;
++}
++
++int npe_send_recv_message(struct npe *npe, void *msg, const char *what)
++{
++	int result;
++	u32 *send = msg, recv[2];
++
++	if ((result = npe_send_message(npe, msg, what)) != 0)
++		return result;
++	if ((result = npe_recv_message(npe, recv, what)) != 0)
++		return result;
++
++	if ((recv[0] != send[0]) || (recv[1] != send[1])) {
++		debug_msg(npe, "Message %s: unexpected message received\n",
++			  what);
++		return -EIO;
++	}
++	return 0;
++}
++
++
++int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
++{
++	const struct firmware *fw_entry;
++
++	struct dl_block {
++		u32 type;
++		u32 offset;
++	} *blk;
++
++	struct dl_image {
++		u32 magic;
++		u32 id;
++		u32 size;
++		union {
++			u32 data[0];
++			struct dl_block blocks[0];
++		};
++	} *image;
++
++	struct dl_codeblock {
++		u32 npe_addr;
++		u32 size;
++		u32 data[0];
++	} *cb;
++
++	int i, j, err, data_size, instr_size, blocks, table_end;
++	u32 cmd;
++
++	if ((err = request_firmware(&fw_entry, name, dev)) != 0)
++		return err;
++
++	err = -EINVAL;
++	if (fw_entry->size < sizeof(struct dl_image)) {
++		print_npe(KERN_ERR, npe, "incomplete firmware file\n");
++		goto err;
++	}
++	image = (struct dl_image*)fw_entry->data;
++
++#if DEBUG_FW
++	print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n",
++		  image->magic, image->id, image->size, image->size * 4);
++#endif
++
++	if (image->magic == swab32(FW_MAGIC)) { /* swapped file */
++		image->id = swab32(image->id);
++		image->size = swab32(image->size);
++	} else if (image->magic != FW_MAGIC) {
++		print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n",
++			  image->magic);
++		goto err;
++	}
++	if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) {
++		print_npe(KERN_ERR, npe,
++			  "inconsistent size of firmware file\n");
++		goto err;
++	}
++	if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) {
++		print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n");
++		goto err;
++	}
++	if (image->magic == swab32(FW_MAGIC))
++		for (i = 0; i < image->size; i++)
++			image->data[i] = swab32(image->data[i]);
++
++	if (!cpu_is_ixp46x() && ((image->id >> 28) & 0xF /* device ID */)) {
++		print_npe(KERN_INFO, npe, "IXP46x firmware ignored on "
++			  "IXP42x\n");
++		goto err;
++	}
++
++	if (npe_running(npe)) {
++		print_npe(KERN_INFO, npe, "unable to load firmware, NPE is "
++			  "already running\n");
++		err = -EBUSY;
++		goto err;
++	}
++#if 0
++	npe_stop(npe);
++	npe_reset(npe);
++#endif
++
++	print_npe(KERN_INFO, npe, "firmware functionality 0x%X, "
++		  "revision 0x%X:%X\n", (image->id >> 16) & 0xFF,
++		  (image->id >> 8) & 0xFF, image->id & 0xFF);
++
++	if (!cpu_is_ixp46x()) {
++		if (!npe->id)
++			instr_size = NPE_A_42X_INSTR_SIZE;
++		else
++			instr_size = NPE_B_AND_C_42X_INSTR_SIZE;
++		data_size = NPE_42X_DATA_SIZE;
++	} else {
++		instr_size = NPE_46X_INSTR_SIZE;
++		data_size = NPE_46X_DATA_SIZE;
++	}
++
++	for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size;
++	     blocks++)
++		if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF)
++			break;
++	if (blocks * sizeof(struct dl_block) / 4 >= image->size) {
++		print_npe(KERN_INFO, npe, "firmware EOF block marker not "
++			  "found\n");
++		goto err;
++	}
++
++#if DEBUG_FW
++	print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks);
++#endif
++
++	table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */;
++	for (i = 0, blk = image->blocks; i < blocks; i++, blk++) {
++		if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4
++		    || blk->offset < table_end) {
++			print_npe(KERN_INFO, npe, "invalid offset 0x%X of "
++				  "firmware block #%i\n", blk->offset, i);
++			goto err;
++		}
++
++		cb = (struct dl_codeblock*)&image->data[blk->offset];
++		if (blk->type == FW_BLOCK_TYPE_INSTR) {
++			if (cb->npe_addr + cb->size > instr_size)
++				goto too_big;
++			cmd = CMD_WR_INS_MEM;
++		} else if (blk->type == FW_BLOCK_TYPE_DATA) {
++			if (cb->npe_addr + cb->size > data_size)
++				goto too_big;
++			cmd = CMD_WR_DATA_MEM;
++		} else {
++			print_npe(KERN_INFO, npe, "invalid firmware block #%i "
++				  "type 0x%X\n", i, blk->type);
++			goto err;
++		}
++		if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) {
++			print_npe(KERN_INFO, npe, "firmware block #%i doesn't "
++				  "fit in firmware image: type %c, start 0x%X,"
++				  " length 0x%X\n", i,
++				  blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
++				  cb->npe_addr, cb->size);
++			goto err;
++		}
++
++		for (j = 0; j < cb->size; j++)
++			npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]);
++	}
++
++	npe_start(npe);
++	if (!npe_running(npe))
++		print_npe(KERN_ERR, npe, "unable to start\n");
++	release_firmware(fw_entry);
++	return 0;
++
++too_big:
++	print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE "
++		  "memory: type %c, start 0x%X, length 0x%X\n", i,
++		  blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D',
++		  cb->npe_addr, cb->size);
++err:
++	release_firmware(fw_entry);
++	return err;
++}
++
++
++struct npe *npe_request(int id)
++{
++	if (id < NPE_COUNT)
++		if (npe_tab[id].valid)
++			if (try_module_get(THIS_MODULE))
++				return &npe_tab[id];
++	return NULL;
++}
++
++void npe_release(struct npe *npe)
++{
++	module_put(THIS_MODULE);
++}
++
++
++static int __init npe_init_module(void)
++{
++
++	int i, found = 0;
++
++	for (i = 0; i < NPE_COUNT; i++) {
++		struct npe *npe = &npe_tab[i];
++		if (!(ixp4xx_read_feature_bits() &
++		      (IXP4XX_FEATURE_RESET_NPEA << i)))
++			continue; /* NPE already disabled or not present */
++		if (!(npe->mem_res = request_mem_region(npe->regs_phys,
++							REGS_SIZE,
++							npe_name(npe)))) {
++			print_npe(KERN_ERR, npe,
++				  "failed to request memory region\n");
++			continue;
++		}
++
++		if (npe_reset(npe))
++			continue;
++		npe->valid = 1;
++		found++;
++	}
++
++	if (!found)
++		return -ENOSYS;
++	return 0;
++}
++
++static void __exit npe_cleanup_module(void)
++{
++	int i;
++
++	for (i = 0; i < NPE_COUNT; i++)
++		if (npe_tab[i].mem_res) {
++			npe_reset(&npe_tab[i]);
++			release_resource(npe_tab[i].mem_res);
++		}
++}
++
++module_init(npe_init_module);
++module_exit(npe_cleanup_module);
++
++MODULE_AUTHOR("Krzysztof Halasa");
++MODULE_LICENSE("GPL v2");
++
++EXPORT_SYMBOL(npe_names);
++EXPORT_SYMBOL(npe_running);
++EXPORT_SYMBOL(npe_request);
++EXPORT_SYMBOL(npe_release);
++EXPORT_SYMBOL(npe_load_firmware);
++EXPORT_SYMBOL(npe_send_message);
++EXPORT_SYMBOL(npe_recv_message);
++EXPORT_SYMBOL(npe_send_recv_message);
+diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+new file mode 100644
+index 0000000..e833013
+--- /dev/null
++++ b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
+@@ -0,0 +1,274 @@
++/*
++ * Intel IXP4xx Queue Manager driver for Linux
++ *
++ * Copyright (C) 2007 Krzysztof Halasa <khc at pm.waw.pl>
++ *
++ * 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 published by the Free Software Foundation.
++ */
++
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <asm/arch/qmgr.h>
++
++#define DEBUG		0
++
++struct qmgr_regs __iomem *qmgr_regs;
++static struct resource *mem_res;
++static spinlock_t qmgr_lock;
++static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
++static void (*irq_handlers[HALF_QUEUES])(void *pdev);
++static void *irq_pdevs[HALF_QUEUES];
++
++void qmgr_set_irq(unsigned int queue, int src,
++		  void (*handler)(void *pdev), void *pdev)
++{
++	u32 __iomem *reg = &qmgr_regs->irqsrc[queue / 8]; /* 8 queues / u32 */
++	int bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */
++	unsigned long flags;
++
++	src &= 7;
++	spin_lock_irqsave(&qmgr_lock, flags);
++	__raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), reg);
++	irq_handlers[queue] = handler;
++	irq_pdevs[queue] = pdev;
++	spin_unlock_irqrestore(&qmgr_lock, flags);
++}
++
++
++static irqreturn_t qmgr_irq1(int irq, void *pdev)
++{
++	int i;
++	u32 val = __raw_readl(&qmgr_regs->irqstat[0]);
++	__raw_writel(val, &qmgr_regs->irqstat[0]); /* ACK */
++
++	for (i = 0; i < HALF_QUEUES; i++)
++		if (val & (1 << i))
++			irq_handlers[i](irq_pdevs[i]);
++
++	return val ? IRQ_HANDLED : 0;
++}
++
++
++void qmgr_enable_irq(unsigned int queue)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&qmgr_lock, flags);
++	__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) | (1 << queue),
++		     &qmgr_regs->irqen[0]);
++	spin_unlock_irqrestore(&qmgr_lock, flags);
++}
++
++void qmgr_disable_irq(unsigned int queue)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&qmgr_lock, flags);
++	__raw_writel(__raw_readl(&qmgr_regs->irqen[0]) & ~(1 << queue),
++		     &qmgr_regs->irqen[0]);
++	spin_unlock_irqrestore(&qmgr_lock, flags);
++}
++
++static inline void shift_mask(u32 *mask)
++{
++	mask[3] = mask[3] << 1 | mask[2] >> 31;
++	mask[2] = mask[2] << 1 | mask[1] >> 31;
++	mask[1] = mask[1] << 1 | mask[0] >> 31;
++	mask[0] <<= 1;
++}
++
++int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
++		       unsigned int nearly_empty_watermark,
++		       unsigned int nearly_full_watermark)
++{
++	u32 cfg, addr = 0, mask[4]; /* in 16-dwords */
++	int err;
++
++	if (queue >= HALF_QUEUES)
++		return -ERANGE;
++
++	if ((nearly_empty_watermark | nearly_full_watermark) & ~7)
++		return -EINVAL;
++
++	switch (len) {
++	case  16:
++		cfg = 0 << 24;
++		mask[0] = 0x1;
++		break;
++	case  32:
++		cfg = 1 << 24;
++		mask[0] = 0x3;
++		break;
++	case  64:
++		cfg = 2 << 24;
++		mask[0] = 0xF;
++		break;
++	case 128:
++		cfg = 3 << 24;
++		mask[0] = 0xFF;
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	cfg |= nearly_empty_watermark << 26;
++	cfg |= nearly_full_watermark << 29;
++	len /= 16;		/* in 16-dwords: 1, 2, 4 or 8 */
++	mask[1] = mask[2] = mask[3] = 0;
++
++	if (!try_module_get(THIS_MODULE))
++		return -ENODEV;
++
++	spin_lock_irq(&qmgr_lock);
++	if (__raw_readl(&qmgr_regs->sram[queue])) {
++		err = -EBUSY;
++		goto err;
++	}
++
++	while (1) {
++		if (!(used_sram_bitmap[0] & mask[0]) &&
++		    !(used_sram_bitmap[1] & mask[1]) &&
++		    !(used_sram_bitmap[2] & mask[2]) &&
++		    !(used_sram_bitmap[3] & mask[3]))
++			break; /* found free space */
++
++		addr++;
++		shift_mask(mask);
++		if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) {
++			printk(KERN_ERR "qmgr: no free SRAM space for"
++			       " queue %i\n", queue);
++			err = -ENOMEM;
++			goto err;
++		}
++	}
++
++	used_sram_bitmap[0] |= mask[0];
++	used_sram_bitmap[1] |= mask[1];
++	used_sram_bitmap[2] |= mask[2];
++	used_sram_bitmap[3] |= mask[3];
++	__raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]);
++	spin_unlock_irq(&qmgr_lock);
++
++#if DEBUG
++	printk(KERN_DEBUG "qmgr: requested queue %i, addr = 0x%02X\n",
++	       queue, addr);
++#endif
++	return 0;
++
++err:
++	spin_unlock_irq(&qmgr_lock);
++	module_put(THIS_MODULE);
++	return err;
++}
++
++void qmgr_release_queue(unsigned int queue)
++{
++	u32 cfg, addr, mask[4];
++
++	BUG_ON(queue >= HALF_QUEUES); /* not in valid range */
++
++	spin_lock_irq(&qmgr_lock);
++	cfg = __raw_readl(&qmgr_regs->sram[queue]);
++	addr = (cfg >> 14) & 0xFF;
++
++	BUG_ON(!addr);		/* not requested */
++
++	switch ((cfg >> 24) & 3) {
++	case 0: mask[0] = 0x1; break;
++	case 1: mask[0] = 0x3; break;
++	case 2: mask[0] = 0xF; break;
++	case 3: mask[0] = 0xFF; break;
++	}
++
++	while (addr--)
++		shift_mask(mask);
++
++	__raw_writel(0, &qmgr_regs->sram[queue]);
++
++	used_sram_bitmap[0] &= ~mask[0];
++	used_sram_bitmap[1] &= ~mask[1];
++	used_sram_bitmap[2] &= ~mask[2];
++	used_sram_bitmap[3] &= ~mask[3];
++	irq_handlers[queue] = NULL; /* catch IRQ bugs */
++	spin_unlock_irq(&qmgr_lock);
++
++	module_put(THIS_MODULE);
++#if DEBUG
++	printk(KERN_DEBUG "qmgr: released queue %i\n", queue);
++#endif
++}
++
++static int qmgr_init(void)
++{
++	int i, err;
++	mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
++				     IXP4XX_QMGR_REGION_SIZE,
++				     "IXP4xx Queue Manager");
++	if (mem_res == NULL)
++		return -EBUSY;
++
++	qmgr_regs = ioremap(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
++	if (qmgr_regs == NULL) {
++		err = -ENOMEM;
++		goto error_map;
++	}
++
++	/* reset qmgr registers */
++	for (i = 0; i < 4; i++) {
++		__raw_writel(0x33333333, &qmgr_regs->stat1[i]);
++		__raw_writel(0, &qmgr_regs->irqsrc[i]);
++	}
++	for (i = 0; i < 2; i++) {
++		__raw_writel(0, &qmgr_regs->stat2[i]);
++		__raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */
++		__raw_writel(0, &qmgr_regs->irqen[i]);
++	}
++
++	for (i = 0; i < QUEUES; i++)
++		__raw_writel(0, &qmgr_regs->sram[i]);
++
++	err = request_irq(IRQ_IXP4XX_QM1, qmgr_irq1, 0,
++			  "IXP4xx Queue Manager", NULL);
++	if (err) {
++		printk(KERN_ERR "qmgr: failed to request IRQ%i\n",
++		       IRQ_IXP4XX_QM1);
++		goto error_irq;
++	}
++
++	used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
++	spin_lock_init(&qmgr_lock);
++
++	printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
++	return 0;
++
++error_irq:
++	iounmap(qmgr_regs);
++error_map:
++	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
++	return err;
++}
++
++static void qmgr_remove(void)
++{
++	free_irq(IRQ_IXP4XX_QM1, NULL);
++	synchronize_irq(IRQ_IXP4XX_QM1);
++	iounmap(qmgr_regs);
++	release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE);
++}
++
++module_init(qmgr_init);
++module_exit(qmgr_remove);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Krzysztof Halasa");
++
++EXPORT_SYMBOL(qmgr_regs);
++EXPORT_SYMBOL(qmgr_set_irq);
++EXPORT_SYMBOL(qmgr_enable_irq);
++EXPORT_SYMBOL(qmgr_disable_irq);
++EXPORT_SYMBOL(qmgr_request_queue);
++EXPORT_SYMBOL(qmgr_release_queue);
+diff --git a/arch/arm/mach-ixp4xx/nas100d-power.c b/arch/arm/mach-ixp4xx/nas100d-power.c
+deleted file mode 100644
+index 29aa98d..0000000
+--- a/arch/arm/mach-ixp4xx/nas100d-power.c
++++ /dev/null
+@@ -1,69 +0,0 @@
+-/*
+- * arch/arm/mach-ixp4xx/nas100d-power.c
+- *
+- * NAS 100d Power/Reset driver
+- *
+- * Copyright (C) 2005 Tower Technologies
+- *
+- * based on nas100d-io.c
+- *  Copyright (C) 2004 Karen Spearel
+- *
+- * Author: Alessandro Zummo <a.zummo at towertech.it>
+- * Maintainers: http://www.nslu2-linux.org/
+- *
+- * 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/interrupt.h>
+-#include <linux/irq.h>
+-#include <linux/module.h>
+-#include <linux/reboot.h>
+-
+-#include <asm/mach-types.h>
+-
+-static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
+-{
+-	/* Signal init to do the ctrlaltdel action, this will bypass init if
+-	 * it hasn't started and do a kernel_restart.
+-	 */
+-	ctrl_alt_del();
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static int __init nas100d_power_init(void)
+-{
+-	if (!(machine_is_nas100d()))
+-		return 0;
+-
+-	set_irq_type(NAS100D_RB_IRQ, IRQT_LOW);
+-
+-	if (request_irq(NAS100D_RB_IRQ, &nas100d_reset_handler,
+-		IRQF_DISABLED, "NAS100D reset button", NULL) < 0) {
+-
+-		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+-			NAS100D_RB_IRQ);
+-
+-		return -EIO;
+-	}
+-
+-	return 0;
+-}
+-
+-static void __exit nas100d_power_exit(void)
+-{
+-	if (!(machine_is_nas100d()))
+-		return;
+-
+-	free_irq(NAS100D_RB_IRQ, NULL);
+-}
+-
+-module_init(nas100d_power_init);
+-module_exit(nas100d_power_exit);
+-
+-MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+-MODULE_DESCRIPTION("NAS100D Power/Reset driver");
+-MODULE_LICENSE("GPL");
+diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
+index 78a1741..4cecae8 100644
+--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
++++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
+@@ -3,8 +3,14 @@
+  *
+  * NAS 100d board-setup
+  *
+- * based ixdp425-setup.c:
++ * Copyright (C) 2008 Rod Whitby <rod at whitby.id.au>
++ *
++ * based on ixdp425-setup.c:
+  *      Copyright (C) 2003-2004 MontaVista Software, Inc.
++ * based on nas100d-power.c:
++ *	Copyright (C) 2005 Tower Technologies
++ * based on nas100d-io.c
++ *	Copyright (C) 2004 Karen Spearel
+  *
+  * Author: Alessandro Zummo <a.zummo at towertech.it>
+  * Author: Rod Whitby <rod at whitby.id.au>
+@@ -12,14 +18,22 @@
+  *
+  */
+ 
+-#include <linux/kernel.h>
++#include <linux/if_ether.h>
++#include <linux/irq.h>
++#include <linux/jiffies.h>
++#include <linux/timer.h>
+ #include <linux/serial.h>
+ #include <linux/serial_8250.h>
+ #include <linux/leds.h>
++#include <linux/reboot.h>
++#include <linux/i2c.h>
++#include <linux/i2c-gpio.h>
+ 
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/mach/flash.h>
++#include <asm/io.h>
++#include <asm/gpio.h>
+ 
+ static struct flash_platform_data nas100d_flash_data = {
+ 	.map_name		= "cfi_probe",
+@@ -38,46 +52,52 @@ static struct platform_device nas100d_flash = {
+ 	.resource		= &nas100d_flash_resource,
+ };
+ 
+-#ifdef CONFIG_LEDS_IXP4XX
+-static struct resource nas100d_led_resources[] = {
++static struct i2c_board_info __initdata nas100d_i2c_board_info [] = {
++	{
++		I2C_BOARD_INFO("rtc-pcf8563", 0x51),
++	},
++};
++
++static struct gpio_led nas100d_led_pins[] = {
+ 	{
+ 		.name		= "wlan",   /* green led */
+-		.start		= 0,
+-		.end		= 0,
+-		.flags		= IXP4XX_GPIO_LOW,
++		.gpio		= NAS100D_LED_WLAN_GPIO,
++		.active_low	= true,
+ 	},
+ 	{
+-		.name		= "ready",  /* blue power led (off is flashing!) */
+-		.start		= 15,
+-		.end		= 15,
+-		.flags		= IXP4XX_GPIO_LOW,
++		.name		= "power",  /* blue power led (off=flashing) */
++		.gpio		= NAS100D_LED_PWR_GPIO,
++		.active_low	= true,
+ 	},
+ 	{
+ 		.name		= "disk",   /* yellow led */
+-		.start		= 3,
+-		.end		= 3,
+-		.flags		= IXP4XX_GPIO_LOW,
++		.gpio		= NAS100D_LED_DISK_GPIO,
++		.active_low	= true,
+ 	},
+ };
+ 
++static struct gpio_led_platform_data nas100d_led_data = {
++	.num_leds		= ARRAY_SIZE(nas100d_led_pins),
++	.leds			= nas100d_led_pins,
++};
++
+ static struct platform_device nas100d_leds = {
+-	.name			= "IXP4XX-GPIO-LED",
++	.name			= "leds-gpio",
+ 	.id			= -1,
+-	.num_resources		= ARRAY_SIZE(nas100d_led_resources),
+-	.resource		= nas100d_led_resources,
++	.dev.platform_data	= &nas100d_led_data,
+ };
+-#endif
+ 
+-static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = {
++static struct i2c_gpio_platform_data nas100d_i2c_gpio_data = {
+ 	.sda_pin		= NAS100D_SDA_PIN,
+ 	.scl_pin		= NAS100D_SCL_PIN,
+ };
+ 
+-static struct platform_device nas100d_i2c_controller = {
+-	.name			= "IXP4XX-I2C",
++static struct platform_device nas100d_i2c_gpio = {
++	.name			= "i2c-gpio",
+ 	.id			= 0,
+-	.dev.platform_data	= &nas100d_i2c_gpio_pins,
+-	.num_resources		= 0,
++	.dev	 = {
++		.platform_data	= &nas100d_i2c_gpio_data,
++	},
+ };
+ 
+ static struct resource nas100d_uart_resources[] = {
+@@ -123,12 +143,28 @@ static struct platform_device nas100d_uart = {
+ 	.resource		= nas100d_uart_resources,
+ };
+ 
++/* Built-in 10/100 Ethernet MAC interfaces */
++static struct eth_plat_info nas100d_plat_eth[] = {
++	{
++		.phy		= 0,
++		.rxq		= 3,
++		.txreadyq	= 20,
++	}
++};
++
++static struct platform_device nas100d_eth[] = {
++	{
++		.name			= "ixp4xx_eth",
++		.id			= IXP4XX_ETH_NPEB,
++		.dev.platform_data	= nas100d_plat_eth,
++	}
++};
++
+ static struct platform_device *nas100d_devices[] __initdata = {
+-	&nas100d_i2c_controller,
++	&nas100d_i2c_gpio,
+ 	&nas100d_flash,
+-#ifdef CONFIG_LEDS_IXP4XX
+ 	&nas100d_leds,
+-#endif
++	&nas100d_eth[0],
+ };
+ 
+ static void nas100d_power_off(void)
+@@ -142,8 +178,63 @@ static void nas100d_power_off(void)
+ 	gpio_line_set(NAS100D_PO_GPIO, IXP4XX_GPIO_HIGH);
+ }
+ 
++/* This is used to make sure the power-button pusher is serious.  The button
++ * must be held until the value of this counter reaches zero.
++ */
++static int power_button_countdown;
++
++/* Must hold the button down for at least this many counts to be processed */
++#define PBUTTON_HOLDDOWN_COUNT 4 /* 2 secs */
++
++static void nas100d_power_handler(unsigned long data);
++static DEFINE_TIMER(nas100d_power_timer, nas100d_power_handler, 0, 0);
++
++static void nas100d_power_handler(unsigned long data)
++{
++	/* This routine is called twice per second to check the
++	 * state of the power button.
++	 */
++
++	if (gpio_get_value(NAS100D_PB_GPIO)) {
++
++		/* IO Pin is 1 (button pushed) */
++		if (power_button_countdown > 0)
++			power_button_countdown--;
++
++	} else {
++
++		/* Done on button release, to allow for auto-power-on mods. */
++		if (power_button_countdown == 0) {
++			/* Signal init to do the ctrlaltdel action,
++			 * this will bypass init if it hasn't started
++			 * and do a kernel_restart.
++			 */
++			ctrl_alt_del();
++
++			/* Change the state of the power LED to "blink" */
++			gpio_line_set(NAS100D_LED_PWR_GPIO, IXP4XX_GPIO_LOW);
++		} else {
++			power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
++		}
++	}
++
++	mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
++}
++
++static irqreturn_t nas100d_reset_handler(int irq, void *dev_id)
++{
++	/* This is the paper-clip reset, it shuts the machine down directly. */
++	machine_power_off();
++
++	return IRQ_HANDLED;
++}
++
+ static void __init nas100d_init(void)
+ {
++	DECLARE_MAC_BUF(mac_buf);
++	uint8_t __iomem *f;
++	int i;
++
+ 	ixp4xx_sys_init();
+ 
+ 	/* gpio 14 and 15 are _not_ clocks */
+@@ -153,7 +244,8 @@ static void __init nas100d_init(void)
+ 	nas100d_flash_resource.end =
+ 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+ 
+-	pm_power_off = nas100d_power_off;
++	i2c_register_board_info(0, nas100d_i2c_board_info,
++				ARRAY_SIZE(nas100d_i2c_board_info));
+ 
+ 	/*
+ 	 * This is only useful on a modified machine, but it is valuable
+@@ -163,6 +255,48 @@ static void __init nas100d_init(void)
+ 	(void)platform_device_register(&nas100d_uart);
+ 
+ 	platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
++
++	pm_power_off = nas100d_power_off;
++
++	if (request_irq(gpio_to_irq(NAS100D_RB_GPIO), &nas100d_reset_handler,
++		IRQF_DISABLED | IRQF_TRIGGER_LOW,
++		"NAS100D reset button", NULL) < 0) {
++
++		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
++			gpio_to_irq(NAS100D_RB_GPIO));
++	}
++
++	/* The power button on the Iomega NAS100d is on GPIO 14, but
++	 * it cannot handle interrupts on that GPIO line.  So we'll
++	 * have to poll it with a kernel timer.
++	 */
++
++	/* Make sure that the power button GPIO is set up as an input */
++	gpio_line_config(NAS100D_PB_GPIO, IXP4XX_GPIO_IN);
++
++	/* Set the initial value for the power button IRQ handler */
++	power_button_countdown = PBUTTON_HOLDDOWN_COUNT;
++
++	mod_timer(&nas100d_power_timer, jiffies + msecs_to_jiffies(500));
++
++	/*
++	 * Map in a portion of the flash and read the MAC address.
++	 * Since it is stored in BE in the flash itself, we need to
++	 * byteswap it if we're in LE mode.
++	 */
++	f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x1000000);
++	if (f) {
++		for (i = 0; i < 6; i++)
++#ifdef __ARMEB__
++			nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + i);
++#else
++			nas100d_plat_eth[0].hwaddr[i] = readb(f + 0xFC0FD8 + (i^3));
++#endif
++		iounmap(f);
++	}
++	printk(KERN_INFO "NAS100D: Using MAC address %s for port 0\n",
++	       print_mac(mac_buf, nas100d_plat_eth[0].hwaddr));
++
+ }
+ 
+ MACHINE_START(NAS100D, "Iomega NAS 100d")
+diff --git a/arch/arm/mach-ixp4xx/nslu2-power.c b/arch/arm/mach-ixp4xx/nslu2-power.c
+deleted file mode 100644
+index acd71e9..0000000
+--- a/arch/arm/mach-ixp4xx/nslu2-power.c
++++ /dev/null
+@@ -1,92 +0,0 @@
+-/*
+- * arch/arm/mach-ixp4xx/nslu2-power.c
+- *
+- * NSLU2 Power/Reset driver
+- *
+- * Copyright (C) 2005 Tower Technologies
+- *
+- * based on nslu2-io.c
+- *  Copyright (C) 2004 Karen Spearel
+- *
+- * Author: Alessandro Zummo <a.zummo at towertech.it>
+- * Maintainers: http://www.nslu2-linux.org/
+- *
+- * 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/module.h>
+-#include <linux/reboot.h>
+-#include <linux/irq.h>
+-#include <linux/interrupt.h>
+-#include <linux/reboot.h>
+-
+-#include <asm/mach-types.h>
+-
+-static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
+-{
+-	/* Signal init to do the ctrlaltdel action, this will bypass init if
+-	 * it hasn't started and do a kernel_restart.
+-	 */
+-	ctrl_alt_del();
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
+-{
+-	/* This is the paper-clip reset, it shuts the machine down directly.
+-	 */
+-	machine_power_off();
+-
+-	return IRQ_HANDLED;
+-}
+-
+-static int __init nslu2_power_init(void)
+-{
+-	if (!(machine_is_nslu2()))
+-		return 0;
+-
+-	*IXP4XX_GPIO_GPISR = 0x20400000;	/* read the 2 irqs to clr */
+-
+-	set_irq_type(NSLU2_RB_IRQ, IRQT_LOW);
+-	set_irq_type(NSLU2_PB_IRQ, IRQT_HIGH);
+-
+-	if (request_irq(NSLU2_RB_IRQ, &nslu2_reset_handler,
+-		IRQF_DISABLED, "NSLU2 reset button", NULL) < 0) {
+-
+-		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
+-			NSLU2_RB_IRQ);
+-
+-		return -EIO;
+-	}
+-
+-	if (request_irq(NSLU2_PB_IRQ, &nslu2_power_handler,
+-		IRQF_DISABLED, "NSLU2 power button", NULL) < 0) {
+-
+-		printk(KERN_DEBUG "Power Button IRQ %d not available\n",
+-			NSLU2_PB_IRQ);
+-
+-		return -EIO;
+-	}
+-
+-	return 0;
+-}
+-
+-static void __exit nslu2_power_exit(void)
+-{
+-	if (!(machine_is_nslu2()))
+-		return;
+-
+-	free_irq(NSLU2_RB_IRQ, NULL);
+-	free_irq(NSLU2_PB_IRQ, NULL);
+-}
+-
+-module_init(nslu2_power_init);
+-module_exit(nslu2_power_exit);
+-
+-MODULE_AUTHOR("Alessandro Zummo <a.zummo at towertech.it>");
+-MODULE_DESCRIPTION("NSLU2 Power/Reset driver");
+-MODULE_LICENSE("GPL");
+diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
+index 9bf8ccb..acaebcb 100644
+--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
++++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
+@@ -3,26 +3,35 @@
+  *
+  * NSLU2 board-setup
+  *
+- * based ixdp425-setup.c:
++ * Copyright (C) 2008 Rod Whitby <rod at whitby.id.au>
++ *
++ * based on ixdp425-setup.c:
+  *      Copyright (C) 2003-2004 MontaVista Software, Inc.
++ * based on nslu2-power.c:
++ *	Copyright (C) 2005 Tower Technologies
+  *
+  * Author: Mark Rakes <mrakes at mac.com>
+  * Author: Rod Whitby <rod at whitby.id.au>
++ * Author: Alessandro Zummo <a.zummo at towertech.it>
+  * Maintainers: http://www.nslu2-linux.org/
+  *
+- * Fixed missing init_time in MACHINE_START kas11 10/22/04
+- * Changed to conform to new style __init ixdp425 kas11 10/22/04
+  */
+ 
+-#include <linux/kernel.h>
++#include <linux/if_ether.h>
++#include <linux/irq.h>
+ #include <linux/serial.h>
+ #include <linux/serial_8250.h>
+ #include <linux/leds.h>
++#include <linux/reboot.h>
++#include <linux/i2c.h>
++#include <linux/i2c-gpio.h>
+ 
+ #include <asm/mach-types.h>
+ #include <asm/mach/arch.h>
+ #include <asm/mach/flash.h>
+ #include <asm/mach/time.h>
++#include <asm/io.h>
++#include <asm/gpio.h>
+ 
+ static struct flash_platform_data nslu2_flash_data = {
+ 	.map_name		= "cfi_probe",
+@@ -41,52 +50,55 @@ static struct platform_device nslu2_flash = {
+ 	.resource		= &nslu2_flash_resource,
+ };
+ 
+-static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = {
++static struct i2c_gpio_platform_data nslu2_i2c_gpio_data = {
+ 	.sda_pin		= NSLU2_SDA_PIN,
+ 	.scl_pin		= NSLU2_SCL_PIN,
+ };
+ 
+-#ifdef CONFIG_LEDS_IXP4XX
+-static struct resource nslu2_led_resources[] = {
++static struct i2c_board_info __initdata nslu2_i2c_board_info [] = {
++	{
++		I2C_BOARD_INFO("rtc-x1205", 0x6f),
++	},
++};
++
++static struct gpio_led nslu2_led_pins[] = {
+ 	{
+ 		.name		= "ready",  /* green led */
+-		.start		= NSLU2_LED_GRN_GPIO,
+-		.end		= NSLU2_LED_GRN_GPIO,
+-		.flags		= IXP4XX_GPIO_HIGH,
++		.gpio		= NSLU2_LED_GRN_GPIO,
+ 	},
+ 	{
+ 		.name		= "status", /* red led */
+-		.start		= NSLU2_LED_RED_GPIO,
+-		.end		= NSLU2_LED_RED_GPIO,
+-		.flags		= IXP4XX_GPIO_HIGH,
++		.gpio		= NSLU2_LED_RED_GPIO,
+ 	},
+ 	{
+ 		.name		= "disk-1",
+-		.start		= NSLU2_LED_DISK1_GPIO,
+-		.end		= NSLU2_LED_DISK1_GPIO,
+-		.flags		= IXP4XX_GPIO_LOW,
++		.gpio		= NSLU2_LED_DISK1_GPIO,
++		.active_low	= true,
+ 	},
+ 	{
+ 		.name		= "disk-2",
+-		.start		= NSLU2_LED_DISK2_GPIO,
+-		.end		= NSLU2_LED_DISK2_GPIO,
+-		.flags		= IXP4XX_GPIO_LOW,
++		.gpio		= NSLU2_LED_DISK2_GPIO,
++		.active_low	= true,
+ 	},
+ };
+ 
++static struct gpio_led_platform_data nslu2_led_data = {
++	.num_leds		= ARRAY_SIZE(nslu2_led_pins),
++	.leds			= nslu2_led_pins,
++};
++
+ static struct platform_device nslu2_leds = {
+-	.name			= "IXP4XX-GPIO-LED",
++	.name			= "leds-gpio",
+ 	.id			= -1,
+-	.num_resources		= ARRAY_SIZE(nslu2_led_resources),
+-	.resource		= nslu2_led_resources,
++	.dev.platform_data	= &nslu2_led_data,
+ };
+-#endif
+ 
+-static struct platform_device nslu2_i2c_controller = {
+-	.name			= "IXP4XX-I2C",
++static struct platform_device nslu2_i2c_gpio = {
++	.name			= "i2c-gpio",
+ 	.id			= 0,
+-	.dev.platform_data	= &nslu2_i2c_gpio_pins,
+-	.num_resources		= 0,
++	.dev	 = {
++		.platform_data	= &nslu2_i2c_gpio_data,
++	},
+ };
+ 
+ static struct platform_device nslu2_beeper = {
+@@ -138,13 +150,29 @@ static struct platform_device nslu2_uart = {
+ 	.resource		= nslu2_uart_resources,
+ };
+ 
++/* Built-in 10/100 Ethernet MAC interfaces */
++static struct eth_plat_info nslu2_plat_eth[] = {
++	{
++		.phy		= 1,
++		.rxq		= 3,
++		.txreadyq	= 20,
++	}
++};
++
++static struct platform_device nslu2_eth[] = {
++	{
++		.name			= "ixp4xx_eth",
++		.id			= IXP4XX_ETH_NPEB,
++		.dev.platform_data	= nslu2_plat_eth,
++	}
++};
++
+ static struct platform_device *nslu2_devices[] __initdata = {
+-	&nslu2_i2c_controller,
++	&nslu2_i2c_gpio,
+ 	&nslu2_flash,
+ 	&nslu2_beeper,
+-#ifdef CONFIG_LEDS_IXP4XX
+ 	&nslu2_leds,
+-#endif
++	&nslu2_eth[0],
+ };
+ 
+ static void nslu2_power_off(void)
+@@ -158,6 +186,25 @@ static void nslu2_power_off(void)
+ 	gpio_line_set(NSLU2_PO_GPIO, IXP4XX_GPIO_HIGH);
+ }
+ 
++static irqreturn_t nslu2_power_handler(int irq, void *dev_id)
++{
++	/* Signal init to do the ctrlaltdel action, this will bypass init if
++	 * it hasn't started and do a kernel_restart.
++	 */
++	ctrl_alt_del();
++
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t nslu2_reset_handler(int irq, void *dev_id)
++{
++	/* This is the paper-clip reset, it shuts the machine down directly.
++	 */
++	machine_power_off();
++
++	return IRQ_HANDLED;
++}
++
+ static void __init nslu2_timer_init(void)
+ {
+     /* The xtal on this machine is non-standard. */
+@@ -173,13 +220,18 @@ static struct sys_timer nslu2_timer = {
+ 
+ static void __init nslu2_init(void)
+ {
++	DECLARE_MAC_BUF(mac_buf);
++	uint8_t __iomem *f;
++	int i;
++
+ 	ixp4xx_sys_init();
+ 
+ 	nslu2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0);
+ 	nslu2_flash_resource.end =
+ 		IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1;
+ 
+-	pm_power_off = nslu2_power_off;
++	i2c_register_board_info(0, nslu2_i2c_board_info,
++				ARRAY_SIZE(nslu2_i2c_board_info));
+ 
+ 	/*
+ 	 * This is only useful on a modified machine, but it is valuable
+@@ -189,6 +241,43 @@ static void __init nslu2_init(void)
+ 	(void)platform_device_register(&nslu2_uart);
+ 
+ 	platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
++
++	pm_power_off = nslu2_power_off;
++
++	if (request_irq(gpio_to_irq(NSLU2_RB_GPIO), &nslu2_reset_handler,
++		IRQF_DISABLED | IRQF_TRIGGER_LOW,
++		"NSLU2 reset button", NULL) < 0) {
++
++		printk(KERN_DEBUG "Reset Button IRQ %d not available\n",
++			gpio_to_irq(NSLU2_RB_GPIO));
++	}
++
++	if (request_irq(gpio_to_irq(NSLU2_PB_GPIO), &nslu2_power_handler,
++		IRQF_DISABLED | IRQF_TRIGGER_HIGH,
++		"NSLU2 power button", NULL) < 0) {
++
++		printk(KERN_DEBUG "Power Button IRQ %d not available\n",
++			gpio_to_irq(NSLU2_PB_GPIO));
++	}
++
++	/*
++	 * Map in a portion of the flash and read the MAC address.
++	 * Since it is stored in BE in the flash itself, we need to
++	 * byteswap it if we're in LE mode.
++	 */
++	f = ioremap(IXP4XX_EXP_BUS_BASE(0), 0x40000);
++	if (f) {
++		for (i = 0; i < 6; i++)
++#ifdef __ARMEB__
++			nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + i);
++#else
++			nslu2_plat_eth[0].hwaddr[i] = readb(f + 0x3FFB0 + (i^3));
++#endif
++		iounmap(f);
++	}
++	printk(KERN_INFO "NSLU2: Using MAC address %s for port 0\n",
++	       print_mac(mac_buf, nslu2_plat_eth[0].hwaddr));
++
+ }
+ 
+ MACHINE_START(NSLU2, "Linksys NSLU2")
+diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile
+index 2a07a28..730a3af 100644
+--- a/arch/arm/mach-ks8695/Makefile
++++ b/arch/arm/mach-ks8695/Makefile
+@@ -9,7 +9,7 @@ obj-n				:=
+ obj-				:=
+ 
+ # PCI support is optional
+-#obj-$(CONFIG_PCI)		+= pci.o
++obj-$(CONFIG_PCI)		+= pci.o
+ 
+ # Board-specific support
+ obj-$(CONFIG_MACH_KS8695)	+= board-micrel.o
+diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
+index 2feeef8..05ac2bd 100644
+--- a/arch/arm/mach-ks8695/board-micrel.c
++++ b/arch/arm/mach-ks8695/board-micrel.c
+@@ -40,7 +40,7 @@ static void __init micrel_init(void)
+ 	printk(KERN_INFO "Micrel KS8695 Development Board initializing\n");
+ 
+ #ifdef CONFIG_PCI
+-//	ks8695_init_pci(&micrel_pci);
++	ks8695_init_pci(&micrel_pci);
+ #endif
+ 
+ 	/* Add devices */
+diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c
+index b1aa3cb..5e46191 100644
+--- a/arch/arm/mach-ks8695/gpio.c
++++ b/arch/arm/mach-ks8695/gpio.c
+@@ -20,6 +20,8 @@
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/init.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
+ #include <linux/module.h>
+ 
+ #include <asm/io.h>
+@@ -216,3 +218,84 @@ int irq_to_gpio(unsigned int irq)
+ 	return (irq - KS8695_IRQ_EXTERN0);
+ }
+ EXPORT_SYMBOL(irq_to_gpio);
++
++
++/* .... Debug interface ..................................................... */
++
++#ifdef CONFIG_DEBUG_FS
++
++static int ks8695_gpio_show(struct seq_file *s, void *unused)
++{
++	unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN };
++	unsigned int intmask[] = { IOPC_IOEINT0TM, IOPC_IOEINT1TM, IOPC_IOEINT2TM, IOPC_IOEINT3TM };
++	unsigned long mode, ctrl, data;
++	int i;
++
++	mode = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM);
++	ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC);
++	data = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD);
++
++	seq_printf(s, "Pin\tI/O\tFunction\tState\n\n");
++
++	for (i = KS8695_GPIO_0; i <= KS8695_GPIO_15 ; i++) {
++		seq_printf(s, "%i:\t", i);
++
++		seq_printf(s, "%s\t", (mode & IOPM_(i)) ? "Output" : "Input");
++
++		if (i <= KS8695_GPIO_3) {
++			if (ctrl & enable[i]) {
++				seq_printf(s, "EXT%i ", i);
++
++				switch ((ctrl & intmask[i]) >> (4 * i)) {
++					case IOPC_TM_LOW:
++						seq_printf(s, "(Low)");		break;
++					case IOPC_TM_HIGH:
++						seq_printf(s, "(High)");	break;
++					case IOPC_TM_RISING:
++						seq_printf(s, "(Rising)");	break;
++					case IOPC_TM_FALLING:
++						seq_printf(s, "(Falling)");	break;
++					case IOPC_TM_EDGE:
++						seq_printf(s, "(Edges)");	break;
++				}
++			}
++			else
++				seq_printf(s, "GPIO\t");
++		}
++		else if (i <= KS8695_GPIO_5) {
++			if (ctrl & enable[i])
++				seq_printf(s, "TOUT%i\t", i - KS8695_GPIO_4);
++			else
++				seq_printf(s, "GPIO\t");
++		}
++		else
++			seq_printf(s, "GPIO\t");
++
++		seq_printf(s, "\t");
++
++		seq_printf(s, "%i\n", (data & IOPD_(i)) ? 1 : 0);
++	}
++	return 0;
++}
++
++static int ks8695_gpio_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, ks8695_gpio_show, NULL);
++}
++
++static const struct file_operations ks8695_gpio_operations = {
++	.open		= ks8695_gpio_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
++static int __init ks8695_gpio_debugfs_init(void)
++{
++	/* /sys/kernel/debug/ks8695_gpio */
++	(void) debugfs_create_file("ks8695_gpio", S_IFREG | S_IRUGO, NULL, NULL, &ks8695_gpio_operations);
++	return 0;
++}
++postcore_initcall(ks8695_gpio_debugfs_init);
++
++#endif
+diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c
+new file mode 100644
+index 0000000..3f4e033
+--- /dev/null
++++ b/arch/arm/mach-ks8695/pci.c
+@@ -0,0 +1,326 @@
++/*
++ * arch/arm/mach-ks8695/pci.c
++ *
++ *  Copyright (C) 2003, Micrel Semiconductors
++ *  Copyright (C) 2006, Greg Ungerer <gerg at snapgear.com>
++ *  Copyright (C) 2006, Ben Dooks
++ *  Copyright (C) 2007, Andrew Victor
++ *
++ * 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 <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++#include <linux/delay.h>
++
++#include <asm/io.h>
++#include <asm/signal.h>
++#include <asm/mach/pci.h>
++#include <asm/hardware.h>
++
++#include <asm/arch/devices.h>
++#include <asm/arch/regs-pci.h>
++
++
++static int pci_dbg;
++static int pci_cfg_dbg;
++
++
++static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where)
++{
++	unsigned long pbca;
++
++	pbca = PBCA_ENABLE | (where & ~3);
++	pbca |= PCI_SLOT(devfn) << 11 ;
++	pbca |= PCI_FUNC(devfn) << 8;
++	pbca |= bus_nr << 16;
++
++	if (bus_nr == 0) {
++		/* use Type-0 transaction */
++		__raw_writel(pbca, KS8695_PCI_VA + KS8695_PBCA);
++	} else {
++		/* use Type-1 transaction */
++		__raw_writel(pbca | PBCA_TYPE1, KS8695_PCI_VA + KS8695_PBCA);
++	}
++}
++
++
++/*
++ * The KS8695 datasheet prohibits anything other than 32bit accesses
++ * to the IO registers, so all our configuration must be done with
++ * 32bit operations, and the correct bit masking and shifting.
++ */
++
++static int ks8695_pci_readconfig(struct pci_bus *bus,
++			unsigned int devfn, int where, int size, u32 *value)
++{
++	ks8695_pci_setupconfig(bus->number, devfn, where);
++
++	*value = __raw_readl(KS8695_PCI_VA +  KS8695_PBCD);
++
++	switch (size) {
++		case 4:
++			break;
++		case 2:
++			*value = *value >> ((where & 2) * 8);
++			*value &= 0xffff;
++			break;
++		case 1:
++			*value = *value >> ((where & 3) * 8);
++			*value &= 0xff;
++			break;
++	}
++
++	if (pci_cfg_dbg) {
++		printk("read: %d,%08x,%02x,%d: %08x (%08x)\n",
++			bus->number, devfn, where, size, *value,
++			__raw_readl(KS8695_PCI_VA +  KS8695_PBCD));
++	}
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static int ks8695_pci_writeconfig(struct pci_bus *bus,
++			unsigned int devfn, int where, int size, u32 value)
++{
++	unsigned long tmp;
++
++	if (pci_cfg_dbg) {
++		printk("write: %d,%08x,%02x,%d: %08x\n",
++			bus->number, devfn, where, size, value);
++	}
++
++	ks8695_pci_setupconfig(bus->number, devfn, where);
++
++	switch (size) {
++		case 4:
++			__raw_writel(value, KS8695_PCI_VA +  KS8695_PBCD);
++			break;
++		case 2:
++			tmp = __raw_readl(KS8695_PCI_VA +  KS8695_PBCD);
++			tmp &= ~(0xffff << ((where & 2) * 8));
++			tmp |= value << ((where & 2) * 8);
++
++			__raw_writel(tmp, KS8695_PCI_VA +  KS8695_PBCD);
++			break;
++		case 1:
++			tmp = __raw_readl(KS8695_PCI_VA +  KS8695_PBCD);
++			tmp &= ~(0xff << ((where & 3) * 8));
++			tmp |= value << ((where & 3) * 8);
++
++			__raw_writel(tmp, KS8695_PCI_VA +  KS8695_PBCD);
++			break;
++	}
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++static void ks8695_local_writeconfig(int where, u32 value)
++{
++	ks8695_pci_setupconfig(0, 0, where);
++	__raw_writel(value, KS8695_PCI_VA + KS8695_PBCD);
++}
++
++static struct pci_ops ks8695_pci_ops = {
 +	.read	= ks8695_pci_readconfig,
 +	.write	= ks8695_pci_writeconfig,
 +};
@@ -39715,19 +49853,24 @@
  
  if PXA_SHARPSL
 diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
-index 4263527..b5c916c 100644
+index 4263527..6e0c4f5 100644
 --- a/arch/arm/mach-pxa/Makefile
 +++ b/arch/arm/mach-pxa/Makefile
-@@ -3,7 +3,7 @@
+@@ -3,10 +3,11 @@
  #
  
  # Common support (must be linked before board specific support)
 -obj-y				+= clock.o generic.o irq.o dma.o time.o
-+obj-y				+= clock.o devices.o generic.o irq.o dma.o time.o
++obj-y				+= clock.o devices.o generic.o irq.o dma.o \
++				   time.o gpio.o
  obj-$(CONFIG_PXA25x)		+= pxa25x.o
  obj-$(CONFIG_PXA27x)		+= pxa27x.o
- obj-$(CONFIG_PXA3xx)		+= pxa3xx.o mfp.o
-@@ -16,18 +16,24 @@ obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
+-obj-$(CONFIG_PXA3xx)		+= pxa3xx.o mfp.o
++obj-$(CONFIG_PXA3xx)		+= pxa3xx.o mfp.o smemc.o
+ obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
+ obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
+ 
+@@ -16,18 +17,24 @@ obj-$(CONFIG_MACH_LOGICPD_PXA270) += lpd270.o
  obj-$(CONFIG_MACH_MAINSTONE)	+= mainstone.o
  obj-$(CONFIG_ARCH_PXA_IDP)	+= idp.o
  obj-$(CONFIG_MACH_TRIZEPS4)	+= trizeps4.o
@@ -39752,7 +49895,7 @@
  
  obj-$(CONFIG_MACH_ARMCORE)      += cm-x270.o
  
-@@ -41,13 +47,10 @@ led-$(CONFIG_MACH_TRIZEPS4)	+= leds-trizeps4.o
+@@ -41,13 +48,10 @@ led-$(CONFIG_MACH_TRIZEPS4)	+= leds-trizeps4.o
  obj-$(CONFIG_LEDS)		+= $(led-y)
  
  # Misc features
@@ -39782,10 +49925,18 @@
  /* I2C Magic */
  I2C_CLIENT_INSMOD;
 diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c
-index 177664c..28cfd71 100644
+index 177664c..6012177 100644
 --- a/arch/arm/mach-pxa/cm-x270.c
 +++ b/arch/arm/mach-pxa/cm-x270.c
-@@ -487,18 +487,15 @@ static int cmx270_mci_init(struct device *dev,
+@@ -29,6 +29,7 @@
+ #include <asm/mach/map.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-regs.h>
+ #include <asm/arch/pxafb.h>
+ #include <asm/arch/ohci.h>
+ #include <asm/arch/mmc.h>
+@@ -487,18 +488,15 @@ static int cmx270_mci_init(struct device *dev,
  
  	/* card detect IRQ on GPIO 83 */
  	pxa_gpio_mode(IRQ_TO_GPIO(CMX270_MMC_IRQ));
@@ -39806,7 +49957,7 @@
  }
  
  static void cmx270_mci_setpower(struct device *dev, unsigned int vdd)
-@@ -566,7 +563,7 @@ static int cmx270_resume(struct sys_device *dev)
+@@ -566,7 +564,7 @@ static int cmx270_resume(struct sys_device *dev)
  }
  
  static struct sysdev_class cmx270_pm_sysclass = {
@@ -40517,7 +50668,7 @@
 -}
 -#endif
 diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
-index 40dea3d..efba65e 100644
+index 40dea3d..3170622 100644
 --- a/arch/arm/mach-pxa/corgi_ssp.c
 +++ b/arch/arm/mach-pxa/corgi_ssp.c
 @@ -21,6 +21,7 @@
@@ -40528,6 +50679,15 @@
  #include "sharpsl.h"
  
  static DEFINE_SPINLOCK(corgi_ssp_lock);
+@@ -31,7 +32,7 @@ static struct corgissp_machinfo *ssp_machinfo;
+ /*
+  * There are three devices connected to the SSP interface:
+  *   1. A touchscreen controller (TI ADS7846 compatible)
+- *   2. An LCD contoller (with some Backlight functionality)
++ *   2. An LCD controller (with some Backlight functionality)
+  *   3. A battery monitoring IC (Maxim MAX1111)
+  *
+  * Each device uses a different speed/mode of communication.
 diff --git a/arch/arm/mach-pxa/cpu-pxa.c b/arch/arm/mach-pxa/cpu-pxa.c
 new file mode 100644
 index 0000000..cbc583b
@@ -40830,10 +50990,10 @@
 +module_exit(pxa_cpu_exit);
 diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
 new file mode 100644
-index 0000000..50ff453
+index 0000000..bfccb80
 --- /dev/null
 +++ b/arch/arm/mach-pxa/devices.c
-@@ -0,0 +1,662 @@
+@@ -0,0 +1,663 @@
 +#include <linux/module.h>
 +#include <linux/kernel.h>
 +#include <linux/init.h>
@@ -40846,6 +51006,7 @@
 +#include <asm/arch/mmc.h>
 +#include <asm/arch/irda.h>
 +#include <asm/arch/i2c.h>
++#include <asm/arch/ohci.h>
 +
 +#include "devices.h"
 +
@@ -41629,10 +51790,10 @@
 +#endif
 +
 diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c
-index 1c34946..698aeec 100644
+index 1c34946..80721c6 100644
 --- a/arch/arm/mach-pxa/generic.c
 +++ b/arch/arm/mach-pxa/generic.c
-@@ -20,7 +20,6 @@
+@@ -20,10 +20,10 @@
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/delay.h>
@@ -41640,10 +51801,15 @@
  #include <linux/ioport.h>
  #include <linux/pm.h>
  #include <linux/string.h>
-@@ -33,13 +32,7 @@
++#include <linux/sysdev.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -32,14 +32,7 @@
+ #include <asm/mach/map.h>
  
  #include <asm/arch/pxa-regs.h>
- #include <asm/arch/gpio.h>
+-#include <asm/arch/gpio.h>
 -#include <asm/arch/udc.h>
 -#include <asm/arch/pxafb.h>
 -#include <asm/arch/mmc.h>
@@ -41654,7 +51820,113 @@
  #include "generic.h"
  
  /*
-@@ -203,7 +196,7 @@ static struct map_desc standard_io_desc[] __initdata = {
+@@ -73,97 +66,6 @@ unsigned int get_memclk_frequency_10khz(void)
+ EXPORT_SYMBOL(get_memclk_frequency_10khz);
+ 
+ /*
+- * Handy function to set GPIO alternate functions
+- */
+-int pxa_last_gpio;
+-
+-int pxa_gpio_mode(int gpio_mode)
+-{
+-	unsigned long flags;
+-	int gpio = gpio_mode & GPIO_MD_MASK_NR;
+-	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
+-	int gafr;
+-
+-	if (gpio > pxa_last_gpio)
+-		return -EINVAL;
+-
+-	local_irq_save(flags);
+-	if (gpio_mode & GPIO_DFLT_LOW)
+-		GPCR(gpio) = GPIO_bit(gpio);
+-	else if (gpio_mode & GPIO_DFLT_HIGH)
+-		GPSR(gpio) = GPIO_bit(gpio);
+-	if (gpio_mode & GPIO_MD_MASK_DIR)
+-		GPDR(gpio) |= GPIO_bit(gpio);
+-	else
+-		GPDR(gpio) &= ~GPIO_bit(gpio);
+-	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
+-	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
+-	local_irq_restore(flags);
+-
+-	return 0;
+-}
+-
+-EXPORT_SYMBOL(pxa_gpio_mode);
+-
+-int gpio_direction_input(unsigned gpio)
+-{
+-	unsigned long flags;
+-	u32 mask;
+-
+-	if (gpio > pxa_last_gpio)
+-		return -EINVAL;
+-
+-	mask = GPIO_bit(gpio);
+-	local_irq_save(flags);
+-	GPDR(gpio) &= ~mask;
+-	local_irq_restore(flags);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_input);
+-
+-int gpio_direction_output(unsigned gpio, int value)
+-{
+-	unsigned long flags;
+-	u32 mask;
+-
+-	if (gpio > pxa_last_gpio)
+-		return -EINVAL;
+-
+-	mask = GPIO_bit(gpio);
+-	local_irq_save(flags);
+-	if (value)
+-		GPSR(gpio) = mask;
+-	else
+-		GPCR(gpio) = mask;
+-	GPDR(gpio) |= mask;
+-	local_irq_restore(flags);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_output);
+-
+-/*
+- * Return GPIO level
+- */
+-int pxa_gpio_get_value(unsigned gpio)
+-{
+-	return __gpio_get_value(gpio);
+-}
+-
+-EXPORT_SYMBOL(pxa_gpio_get_value);
+-
+-/*
+- * Set output GPIO level
+- */
+-void pxa_gpio_set_value(unsigned gpio, int value)
+-{
+-	__gpio_set_value(gpio, value);
+-}
+-
+-EXPORT_SYMBOL(pxa_gpio_set_value);
+-
+-/*
+  * Routine to safely enable or disable a clock in the CKEN
+  */
+ void __pxa_set_cken(int clock, int enable)
+@@ -178,7 +80,6 @@ void __pxa_set_cken(int clock, int enable)
+ 
+ 	local_irq_restore(flags);
+ }
+-
+ EXPORT_SYMBOL(__pxa_set_cken);
+ 
+ /*
+@@ -203,7 +104,7 @@ static struct map_desc standard_io_desc[] __initdata = {
  	}, {	/* Mem Ctl */
  		.virtual	=  0xf6000000,
  		.pfn		= __phys_to_pfn(0x48000000),
@@ -41663,12 +51935,12 @@
  		.type		= MT_DEVICE
  	}, {	/* USB host */
  		.virtual	=  0xf8000000,
-@@ -233,245 +226,3 @@ void __init pxa_map_io(void)
- 	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+@@ -234,244 +135,58 @@ void __init pxa_map_io(void)
  	get_clk_frequency_khz(1);
  }
--
--
+ 
++#ifdef CONFIG_PM
+ 
 -static struct resource pxamci_resources[] = {
 -	[0] = {
 -		.start	= 0x41100000,
@@ -41702,9 +51974,14 @@
 -
 -
 -static struct pxa2xx_udc_mach_info pxa_udc_info;
--
++static unsigned long saved_gplr[4];
++static unsigned long saved_gpdr[4];
++static unsigned long saved_grer[4];
++static unsigned long saved_gfer[4];
+ 
 -void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info)
--{
++static int pxa_gpio_suspend(struct sys_device *dev, pm_message_t state)
+ {
 -	memcpy(&pxa_udc_info, info, sizeof *info);
 -}
 -
@@ -41720,9 +51997,15 @@
 -		.flags	= IORESOURCE_IRQ,
 -	},
 -};
--
++	int i, gpio;
+ 
 -static u64 udc_dma_mask = ~(u32)0;
--
++	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
++		saved_gplr[i] = GPLR(gpio);
++		saved_gpdr[i] = GPDR(gpio);
++		saved_grer[i] = GRER(gpio);
++		saved_gfer[i] = GFER(gpio);
+ 
 -struct platform_device pxa_device_udc = {
 -	.name		= "pxa2xx-udc",
 -	.id		= -1,
@@ -41731,7 +52014,9 @@
 -	.dev		=  {
 -		.platform_data	= &pxa_udc_info,
 -		.dma_mask	= &udc_dma_mask,
--	}
++		/* Clear GPIO transition detect bits */
++		GEDR(gpio) = GEDR(gpio);
+ 	}
 -};
 -
 -static struct resource pxafb_resources[] = {
@@ -41763,10 +52048,12 @@
 -void __init set_pxa_fb_info(struct pxafb_mach_info *info)
 -{
 -	pxa_device_fb.dev.platform_data = info;
--}
--
++	return 0;
+ }
+ 
 -void __init set_pxa_fb_parent(struct device *parent_dev)
--{
++static int pxa_gpio_resume(struct sys_device *dev)
+ {
 -	pxa_device_fb.dev.parent = parent_dev;
 -}
 -
@@ -41781,14 +52068,19 @@
 -		.flags	= IORESOURCE_IRQ,
 -	}
 -};
--
++	int i, gpio;
+ 
 -struct platform_device pxa_device_ffuart= {
 -	.name		= "pxa2xx-uart",
 -	.id		= 0,
 -	.resource	= pxa_resource_ffuart,
 -	.num_resources	= ARRAY_SIZE(pxa_resource_ffuart),
 -};
--
++	for (gpio = 0, i = 0; gpio < pxa_last_gpio; gpio += 32, i++) {
++		/* restore level with set/clear */
++		GPSR(gpio) = saved_gplr[i];
++		GPCR(gpio) = ~saved_gplr[i];
+ 
 -static struct resource pxa_resource_btuart[] = {
 -	{
 -		.start	= __PREG(BTUART),
@@ -41798,7 +52090,10 @@
 -		.start	= IRQ_BTUART,
 -		.end	= IRQ_BTUART,
 -		.flags	= IORESOURCE_IRQ,
--	}
++		GRER(gpio) = saved_grer[i];
++		GFER(gpio) = saved_gfer[i];
++		GPDR(gpio) = saved_gpdr[i];
+ 	}
 -};
 -
 -struct platform_device pxa_device_btuart = {
@@ -41868,8 +52163,13 @@
 -void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
 -{
 -	pxa_device_i2c.dev.platform_data = info;
--}
--
++	return 0;
+ }
++#else
++#define pxa_gpio_suspend	NULL
++#define pxa_gpio_resume		NULL
++#endif
+ 
 -static struct resource pxai2s_resources[] = {
 -	{
 -		.start	= 0x40400000,
@@ -41880,8 +52180,12 @@
 -		.end	= IRQ_I2S,
 -		.flags	= IORESOURCE_IRQ,
 -	},
--};
--
++struct sysdev_class pxa_gpio_sysclass = {
++	.name		= "gpio",
++	.suspend	= pxa_gpio_suspend,
++	.resume		= pxa_gpio_resume,
+ };
+ 
 -struct platform_device pxa_device_i2s = {
 -	.name		= "pxa2xx-i2s",
 -	.id		= -1,
@@ -41901,14 +52205,239 @@
 -};
 -
 -void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
--{
++static int __init pxa_gpio_init(void)
+ {
 -	pxa_device_ficp.dev.platform_data = info;
--}
--
++	return sysdev_class_register(&pxa_gpio_sysclass);
+ }
+ 
 -struct platform_device pxa_device_rtc = {
 -	.name		= "sa1100-rtc",
 -	.id		= -1,
 -};
++core_initcall(pxa_gpio_init);
+diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
+index b30f240..b3d10b0 100644
+--- a/arch/arm/mach-pxa/generic.h
++++ b/arch/arm/mach-pxa/generic.h
+@@ -16,6 +16,7 @@ extern void __init pxa_init_irq_low(void);
+ extern void __init pxa_init_irq_high(void);
+ extern void __init pxa_init_irq_gpio(int gpio_nr);
+ extern void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int));
++extern void __init pxa_init_gpio(int gpio_nr);
+ extern void __init pxa25x_init_irq(void);
+ extern void __init pxa27x_init_irq(void);
+ extern void __init pxa3xx_init_irq(void);
+@@ -52,3 +53,6 @@ extern unsigned pxa3xx_get_memclk_frequency_10khz(void);
+ #define pxa3xx_get_clk_frequency_khz(x)		(0)
+ #define pxa3xx_get_memclk_frequency_10khz()	(0)
+ #endif
++
++extern struct sysdev_class pxa_irq_sysclass;
++extern struct sysdev_class pxa_gpio_sysclass;
+diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
+new file mode 100644
+index 0000000..8638dd7
+--- /dev/null
++++ b/arch/arm/mach-pxa/gpio.c
+@@ -0,0 +1,197 @@
++/*
++ *  linux/arch/arm/mach-pxa/gpio.c
++ *
++ *  Generic PXA GPIO handling
++ *
++ *  Author:	Nicolas Pitre
++ *  Created:	Jun 15, 2001
++ *  Copyright:	MontaVista Software Inc.
++ *
++ *  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/init.h>
++#include <linux/module.h>
++
++#include <asm/gpio.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/arch/pxa-regs.h>
++
++#include "generic.h"
++
++
++struct pxa_gpio_chip {
++	struct gpio_chip chip;
++	void __iomem     *regbase;
++};
++
++int pxa_last_gpio;
++
++/*
++ * Configure pins for GPIO or other functions
++ */
++int pxa_gpio_mode(int gpio_mode)
++{
++	unsigned long flags;
++	int gpio = gpio_mode & GPIO_MD_MASK_NR;
++	int fn = (gpio_mode & GPIO_MD_MASK_FN) >> 8;
++	int gafr;
++
++	if (gpio > pxa_last_gpio)
++		return -EINVAL;
++
++	local_irq_save(flags);
++	if (gpio_mode & GPIO_DFLT_LOW)
++		GPCR(gpio) = GPIO_bit(gpio);
++	else if (gpio_mode & GPIO_DFLT_HIGH)
++		GPSR(gpio) = GPIO_bit(gpio);
++	if (gpio_mode & GPIO_MD_MASK_DIR)
++		GPDR(gpio) |= GPIO_bit(gpio);
++	else
++		GPDR(gpio) &= ~GPIO_bit(gpio);
++	gafr = GAFR(gpio) & ~(0x3 << (((gpio) & 0xf)*2));
++	GAFR(gpio) = gafr |  (fn  << (((gpio) & 0xf)*2));
++	local_irq_restore(flags);
++
++	return 0;
++}
++EXPORT_SYMBOL(pxa_gpio_mode);
++
++static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++	unsigned long        flags;
++	u32                  mask = 1 << offset;
++	u32                  value;
++	struct pxa_gpio_chip *pxa;
++	void __iomem         *gpdr;
++
++	pxa = container_of(chip, struct pxa_gpio_chip, chip);
++	gpdr = pxa->regbase + GPDR_OFFSET;
++	local_irq_save(flags);
++	value = __raw_readl(gpdr);
++	value &= ~mask;
++	__raw_writel(value, gpdr);
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++static int pxa_gpio_direction_output(struct gpio_chip *chip,
++					unsigned offset, int value)
++{
++	unsigned long        flags;
++	u32                  mask = 1 << offset;
++	u32                  tmp;
++	struct pxa_gpio_chip *pxa;
++	void __iomem         *gpdr;
++
++	pxa = container_of(chip, struct pxa_gpio_chip, chip);
++	__raw_writel(mask,
++			pxa->regbase + (value ? GPSR_OFFSET : GPCR_OFFSET));
++	gpdr = pxa->regbase + GPDR_OFFSET;
++	local_irq_save(flags);
++	tmp = __raw_readl(gpdr);
++	tmp |= mask;
++	__raw_writel(tmp, gpdr);
++	local_irq_restore(flags);
++
++	return 0;
++}
++
++/*
++ * Return GPIO level
++ */
++static int pxa_gpio_get(struct gpio_chip *chip, unsigned offset)
++{
++	u32                  mask = 1 << offset;
++	struct pxa_gpio_chip *pxa;
++
++	pxa = container_of(chip, struct pxa_gpio_chip, chip);
++	return __raw_readl(pxa->regbase + GPLR_OFFSET) & mask;
++}
++
++/*
++ * Set output GPIO level
++ */
++static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	u32                  mask = 1 << offset;
++	struct pxa_gpio_chip *pxa;
++
++	pxa = container_of(chip, struct pxa_gpio_chip, chip);
++
++	if (value)
++		__raw_writel(mask, pxa->regbase + GPSR_OFFSET);
++	else
++		__raw_writel(mask, pxa->regbase + GPCR_OFFSET);
++}
++
++static struct pxa_gpio_chip pxa_gpio_chip[] = {
++	[0] = {
++		.regbase = GPIO0_BASE,
++		.chip = {
++			.label            = "gpio-0",
++			.direction_input  = pxa_gpio_direction_input,
++			.direction_output = pxa_gpio_direction_output,
++			.get              = pxa_gpio_get,
++			.set              = pxa_gpio_set,
++			.base             = 0,
++			.ngpio            = 32,
++		},
++	},
++	[1] = {
++		.regbase = GPIO1_BASE,
++		.chip = {
++			.label            = "gpio-1",
++			.direction_input  = pxa_gpio_direction_input,
++			.direction_output = pxa_gpio_direction_output,
++			.get              = pxa_gpio_get,
++			.set              = pxa_gpio_set,
++			.base             = 32,
++			.ngpio            = 32,
++		},
++	},
++	[2] = {
++		.regbase = GPIO2_BASE,
++		.chip = {
++			.label            = "gpio-2",
++			.direction_input  = pxa_gpio_direction_input,
++			.direction_output = pxa_gpio_direction_output,
++			.get              = pxa_gpio_get,
++			.set              = pxa_gpio_set,
++			.base             = 64,
++			.ngpio            = 32, /* 21 for PXA25x */
++		},
++	},
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
++	[3] = {
++		.regbase = GPIO3_BASE,
++		.chip = {
++			.label            = "gpio-3",
++			.direction_input  = pxa_gpio_direction_input,
++			.direction_output = pxa_gpio_direction_output,
++			.get              = pxa_gpio_get,
++			.set              = pxa_gpio_set,
++			.base             = 96,
++			.ngpio            = 32,
++		},
++	},
++#endif
++};
++
++void __init pxa_init_gpio(int gpio_nr)
++{
++	int i;
++
++	/* add a GPIO chip for each register bank.
++	 * the last PXA25x register only contains 21 GPIOs
++	 */
++	for (i = 0; i < gpio_nr; i += 32) {
++		if (i+32 > gpio_nr)
++			pxa_gpio_chip[i/32].chip.ngpio = gpio_nr - i;
++		gpiochip_add(&pxa_gpio_chip[i/32].chip);
++	}
++}
 diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
 index 465108d..0a94344 100644
 --- a/arch/arm/mach-pxa/idp.c
@@ -41922,6 +52451,92 @@
  	}
  };
  
+diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
+index 07acb45..36c6a68 100644
+--- a/arch/arm/mach-pxa/irq.c
++++ b/arch/arm/mach-pxa/irq.c
+@@ -15,6 +15,7 @@
+ #include <linux/init.h>
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
++#include <linux/sysdev.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/irq.h>
+@@ -310,6 +311,8 @@ void __init pxa_init_irq_gpio(int gpio_nr)
+ 	/* Install handler for GPIO>=2 edge detect interrupts */
+ 	set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low);
+ 	set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler);
++
++	pxa_init_gpio(gpio_nr);
+ }
+ 
+ void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
+@@ -321,3 +324,64 @@ void __init pxa_init_irq_set_wake(int (*set_wake)(unsigned int, unsigned int))
+ 	pxa_low_gpio_chip.set_wake = set_wake;
+ 	pxa_muxed_gpio_chip.set_wake = set_wake;
+ }
++
++#ifdef CONFIG_PM
++static unsigned long saved_icmr[2];
++
++static int pxa_irq_suspend(struct sys_device *dev, pm_message_t state)
++{
++	switch (dev->id) {
++	case 0:
++		saved_icmr[0] = ICMR;
++		ICMR = 0;
++		break;
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
++	case 1:
++		saved_icmr[1] = ICMR2;
++		ICMR2 = 0;
++		break;
++#endif
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int pxa_irq_resume(struct sys_device *dev)
++{
++	switch (dev->id) {
++	case 0:
++		ICMR = saved_icmr[0];
++		ICLR = 0;
++		ICCR = 1;
++		break;
++#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
++	case 1:
++		ICMR2 = saved_icmr[1];
++		ICLR2 = 0;
++		break;
++#endif
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++#else
++#define pxa_irq_suspend		NULL
++#define pxa_irq_resume		NULL
++#endif
++
++struct sysdev_class pxa_irq_sysclass = {
++	.name		= "irq",
++	.suspend	= pxa_irq_suspend,
++	.resume		= pxa_irq_resume,
++};
++
++static int __init pxa_irq_init(void)
++{
++	return sysdev_class_register(&pxa_irq_sysclass);
++}
++
++core_initcall(pxa_irq_init);
 diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
 new file mode 100644
 index 0000000..0a4b54c
@@ -42733,10 +53348,10 @@
  	pxa_set_mci_info(&mainstone_mci_platform_data);
  	pxa_set_ficp_info(&mainstone_ficp_platform_data);
 diff --git a/arch/arm/mach-pxa/mfp.c b/arch/arm/mach-pxa/mfp.c
-index 436f965..ec1b2d8 100644
+index 436f965..f5809ad 100644
 --- a/arch/arm/mach-pxa/mfp.c
 +++ b/arch/arm/mach-pxa/mfp.c
-@@ -17,9 +17,11 @@
+@@ -17,9 +17,12 @@
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/io.h>
@@ -42745,10 +53360,11 @@
  #include <asm/hardware.h>
  #include <asm/arch/mfp.h>
 +#include <asm/arch/mfp-pxa3xx.h>
++#include <asm/arch/pxa3xx-regs.h>
  
  /* mfp_spin_lock is used to ensure that MFP register configuration
   * (most likely a read-modify-write operation) is atomic, and that
-@@ -28,43 +30,110 @@
+@@ -28,43 +31,110 @@
  static DEFINE_SPINLOCK(mfp_spin_lock);
  
  static void __iomem *mfpr_mmio_base = (void __iomem *)&__REG(MFPR_BASE);
@@ -42872,7 +53488,7 @@
  	}
  
  	mfpr_sync();
-@@ -96,140 +165,82 @@ void pxa3xx_mfp_write(int mfp, unsigned long val)
+@@ -96,140 +166,90 @@ void pxa3xx_mfp_write(int mfp, unsigned long val)
  	spin_unlock_irqrestore(&mfp_spin_lock, flags);
  }
  
@@ -42980,8 +53596,7 @@
 -	BUG_ON(mfp >= MFP_PIN_MAX);
 -
 -	spin_lock_irqsave(&mfp_spin_lock, flags);
-+	int pin;
- 
+-
 -	mfpr_off = mfp_table[mfp].mfpr_off;
 -	mfpr_val = mfpr_readl(mfpr_off);
 -	mfpr_val &= ~MFPR_PULL_MASK;
@@ -42989,7 +53604,8 @@
 -
 -	mfpr_writel(mfpr_off, mfpr_val);
 -	mfpr_sync();
--
++	int pin;
+ 
 -	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 +	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
 +		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
@@ -43010,20 +53626,26 @@
 -
 -	mfpr_off = mfp_table[mfp].mfpr_off;
 -	mfpr_val = mfpr_readl(mfpr_off);
--
++	int pin;
+ 
 -	mfpr_val &= ~MFPR_EDGE_MASK;
 -	mfpr_val |= (edge & 0x3u) << MFPR_ERE_OFFSET;
 -	mfpr_val |= (!edge & 0x1) << MFPR_EC_OFFSET;
-+	int pin;
- 
--	mfpr_writel(mfpr_off, mfpr_val);
--	mfpr_sync();
--
--	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 +	for (pin = 0; pin < ARRAY_SIZE(mfp_table); pin++) {
 +		struct pxa3xx_mfp_pin *p = &mfp_table[pin];
 +		__mfp_config_run(p);
 +	}
+ 
+-	mfpr_writel(mfpr_off, mfpr_val);
+-	mfpr_sync();
++	/* clear RDH bit when MFP settings are restored
++	 *
++	 * NOTE: the last 3 bits DxS are write-1-to-clear so carefully
++	 * preserve them here in case they will be referenced later
++	 */
++	ASCR &= ~(ASCR_RDH | ASCR_D1S | ASCR_D2S | ASCR_D3S);
+ 
+-	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 +	return 0;
  }
  
@@ -43032,9 +53654,18 @@
 -	struct pxa3xx_mfp_addr_map *p;
 -	unsigned long offset, flags;
 -	int i;
--
++static struct sysdev_class mfp_sysclass = {
++	.name		= "mfp",
++	.suspend	= pxa3xx_mfp_suspend,
++	.resume 	= pxa3xx_mfp_resume,
++};
+ 
 -	spin_lock_irqsave(&mfp_spin_lock, flags);
--
++static struct sys_device mfp_device = {
++	.id		= 0,
++	.cls		= &mfp_sysclass,
++};
+ 
 -	for (p = map; p->start != MFP_PIN_INVALID; p++) {
 -		offset = p->offset;
 -		i = p->start;
@@ -43045,19 +53676,10 @@
 -			offset += 4; i++;
 -		} while ((i <= p->end) && (p->end != -1));
 -	}
-+static struct sysdev_class mfp_sysclass = {
-+	set_kset_name("mfp"),
-+	.suspend	= pxa3xx_mfp_suspend,
-+	.resume 	= pxa3xx_mfp_resume,
-+};
- 
+-
 -	spin_unlock_irqrestore(&mfp_spin_lock, flags);
 -}
-+static struct sys_device mfp_device = {
-+	.id		= 0,
-+	.cls		= &mfp_sysclass,
-+};
- 
+-
 -void __init pxa3xx_init_mfp(void)
 +static int __init mfp_init_devicefs(void)
  {
@@ -43069,10 +53691,10 @@
 +#endif
 diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
 new file mode 100644
-index 0000000..540c3bb
+index 0000000..c14696b
 --- /dev/null
 +++ b/arch/arm/mach-pxa/pcm027.c
-@@ -0,0 +1,216 @@
+@@ -0,0 +1,217 @@
 +/*
 + *  linux/arch/arm/mach-pxa/pcm027.c
 + *  Support for the Phytec phyCORE-PXA270 CPU card (aka PCM-027).
@@ -43104,6 +53726,7 @@
 +#include <asm/mach/arch.h>
 +#include <asm/arch/hardware.h>
 +#include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-regs.h>
 +#include <asm/arch/pxa2xx_spi.h>
 +#include <asm/arch/pcm027.h>
 +#include "generic.h"
@@ -43683,9 +54306,31 @@
  
  	return 0;
 diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
-index 655668d..dd54496 100644
+index 655668d..209eabf 100644
 --- a/arch/arm/mach-pxa/poodle.c
 +++ b/arch/arm/mach-pxa/poodle.c
+@@ -164,7 +164,7 @@ static struct resource poodlets_resources[] = {
+ 	},
+ };
+ 
+-static unsigned long poodle_get_hsync_len(void)
++static unsigned long poodle_get_hsync_invperiod(void)
+ {
+ 	return 0;
+ }
+@@ -174,9 +174,9 @@ static void poodle_null_hsync(void)
+ }
+ 
+ static struct corgits_machinfo  poodle_ts_machinfo = {
+-	.get_hsync_len   = poodle_get_hsync_len,
+-	.put_hsync       = poodle_null_hsync,
+-	.wait_hsync      = poodle_null_hsync,
++	.get_hsync_invperiod	= poodle_get_hsync_invperiod,
++	.put_hsync       	= poodle_null_hsync,
++	.wait_hsync      	= poodle_null_hsync,
+ };
+ 
+ static struct platform_device poodle_ts_device = {
 @@ -215,12 +215,10 @@ static int poodle_mci_init(struct device *dev, irq_handler_t poodle_detect_int,
  	err = request_irq(POODLE_IRQ_GPIO_nSD_DETECT, poodle_detect_int,
  			  IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
@@ -43702,10 +54347,18 @@
  
  static void poodle_mci_setpower(struct device *dev, unsigned int vdd)
 diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
-index 9732d5d..ddd05bf 100644
+index 9732d5d..599e53f 100644
 --- a/arch/arm/mach-pxa/pxa25x.c
 +++ b/arch/arm/mach-pxa/pxa25x.c
-@@ -111,21 +111,27 @@ static const struct clkops clk_pxa25x_lcd_ops = {
+@@ -21,6 +21,7 @@
+ #include <linux/init.h>
+ #include <linux/platform_device.h>
+ #include <linux/suspend.h>
++#include <linux/sysdev.h>
+ 
+ #include <asm/hardware.h>
+ #include <asm/arch/irqs.h>
+@@ -111,21 +112,27 @@ static const struct clkops clk_pxa25x_lcd_ops = {
   * 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
   * 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
   */
@@ -43736,7 +54389,77 @@
  	*/
  	INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
  };
-@@ -213,8 +219,6 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
+@@ -135,11 +142,6 @@ static struct clk pxa25x_clks[] = {
+ #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
+ #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
+ 
+-#define RESTORE_GPLEVEL(n) do { \
+-	GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
+-	GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
+-} while (0)
+-
+ /*
+  * List of global PXA peripheral registers to preserve.
+  * More ones like CP and general purpose register values are preserved
+@@ -147,10 +149,6 @@ static struct clk pxa25x_clks[] = {
+  */
+ enum {	SLEEP_SAVE_START = 0,
+ 
+-	SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
+-	SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
+-	SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
+-	SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
+ 	SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2,
+ 
+ 	SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
+@@ -159,7 +157,6 @@ enum {	SLEEP_SAVE_START = 0,
+ 
+ 	SLEEP_SAVE_PSTR,
+ 
+-	SLEEP_SAVE_ICMR,
+ 	SLEEP_SAVE_CKEN,
+ 
+ 	SLEEP_SAVE_SIZE
+@@ -168,17 +165,12 @@ enum {	SLEEP_SAVE_START = 0,
+ 
+ static void pxa25x_cpu_pm_save(unsigned long *sleep_save)
+ {
+-	SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2);
+-	SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
+-	SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
+-	SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
+ 	SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
+ 
+ 	SAVE(GAFR0_L); SAVE(GAFR0_U);
+ 	SAVE(GAFR1_L); SAVE(GAFR1_U);
+ 	SAVE(GAFR2_L); SAVE(GAFR2_U);
+ 
+-	SAVE(ICMR); ICMR = 0;
+ 	SAVE(CKEN);
+ 	SAVE(PSTR);
+ 
+@@ -192,29 +184,19 @@ static void pxa25x_cpu_pm_restore(unsigned long *sleep_save)
+ 	PSPR = 0;
+ 
+ 	/* restore registers */
+-	RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1); RESTORE_GPLEVEL(2);
+-	RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
+ 	RESTORE(GAFR0_L); RESTORE(GAFR0_U);
+ 	RESTORE(GAFR1_L); RESTORE(GAFR1_U);
+ 	RESTORE(GAFR2_L); RESTORE(GAFR2_U);
+-	RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
+-	RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
+ 	RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
+ 
+ 	PSSR = PSSR_RDH | PSSR_PH;
+ 
+ 	RESTORE(CKEN);
+-
+-	ICLR = 0;
+-	ICCR = 1;
+-	RESTORE(ICMR);
+ 	RESTORE(PSTR);
+ }
  
  static void pxa25x_cpu_pm_enter(suspend_state_t state)
  {
@@ -43745,7 +54468,7 @@
  	switch (state) {
  	case PM_SUSPEND_MEM:
  		/* set resume return address */
-@@ -236,6 +240,8 @@ static void __init pxa25x_init_pm(void)
+@@ -236,6 +218,8 @@ static void __init pxa25x_init_pm(void)
  {
  	pxa_cpu_pm_fns = &pxa25x_cpu_pm_fns;
  }
@@ -43754,7 +54477,7 @@
  #endif
  
  /* PXA25x: supports wakeup from GPIO0..GPIO15 and RTC alarm
-@@ -287,30 +293,33 @@ void __init pxa25x_init_irq(void)
+@@ -287,33 +271,53 @@ void __init pxa25x_init_irq(void)
  }
  
  static struct platform_device *pxa25x_devices[] __initdata = {
@@ -43771,16 +54494,25 @@
 +	&pxa25x_device_ssp,
 +	&pxa25x_device_nssp,
 +	&pxa25x_device_assp,
++};
++
++static struct sys_device pxa25x_sysdev[] = {
++	{
++		.cls	= &pxa_irq_sysclass,
++	}, {
++		.cls	= &pxa_gpio_sysclass,
++	},
  };
  
  static int __init pxa25x_init(void)
  {
- 	int ret = 0;
- 
+-	int ret = 0;
++	int i, ret = 0;
++
 +	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
 +	if (cpu_is_pxa25x())
 +		clks_register(&pxa25x_hwuart_clk, 1);
-+
+ 
  	if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
  		clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
  
@@ -43791,14 +54523,32 @@
  		pxa25x_init_pm();
 -#endif
 +
++		for (i = 0; i < ARRAY_SIZE(pxa25x_sysdev); i++) {
++			ret = sysdev_register(&pxa25x_sysdev[i]);
++			if (ret)
++				pr_err("failed to register sysdev[%d]\n", i);
++		}
++
  		ret = platform_add_devices(pxa25x_devices,
  					   ARRAY_SIZE(pxa25x_devices));
++		if (ret)
++			return ret;
  	}
++
+ 	/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
+ 	if (cpu_is_pxa25x())
+ 		ret = platform_device_register(&pxa_device_hwuart);
 diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
-index 8e126e6..96cf274 100644
+index 8e126e6..46a951c 100644
 --- a/arch/arm/mach-pxa/pxa27x.c
 +++ b/arch/arm/mach-pxa/pxa27x.c
-@@ -21,9 +21,11 @@
+@@ -16,14 +16,17 @@
+ #include <linux/init.h>
+ #include <linux/suspend.h>
+ #include <linux/platform_device.h>
++#include <linux/sysdev.h>
+ 
+ #include <asm/hardware.h>
  #include <asm/irq.h>
  #include <asm/arch/irqs.h>
  #include <asm/arch/pxa-regs.h>
@@ -43810,7 +54560,7 @@
  
  #include "generic.h"
  #include "devices.h"
-@@ -150,11 +152,12 @@ static struct clk pxa27x_clks[] = {
+@@ -150,11 +153,12 @@ static struct clk pxa27x_clks[] = {
  	INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
  	INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
  
@@ -43826,7 +54576,88 @@
  	INIT_CKEN("MSLCLK",  MSL,  48000000, 0, NULL),
  	INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
  	INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
-@@ -263,12 +266,6 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
+@@ -168,11 +172,6 @@ static struct clk pxa27x_clks[] = {
+ #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
+ #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
+ 
+-#define RESTORE_GPLEVEL(n) do { \
+-	GPSR##n = sleep_save[SLEEP_SAVE_GPLR##n]; \
+-	GPCR##n = ~sleep_save[SLEEP_SAVE_GPLR##n]; \
+-} while (0)
+-
+ /*
+  * List of global PXA peripheral registers to preserve.
+  * More ones like CP and general purpose register values are preserved
+@@ -180,10 +179,6 @@ static struct clk pxa27x_clks[] = {
+  */
+ enum {	SLEEP_SAVE_START = 0,
+ 
+-	SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
+-	SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
+-	SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
+-	SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
+ 	SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
+ 
+ 	SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
+@@ -193,7 +188,6 @@ enum {	SLEEP_SAVE_START = 0,
+ 
+ 	SLEEP_SAVE_PSTR,
+ 
+-	SLEEP_SAVE_ICMR,
+ 	SLEEP_SAVE_CKEN,
+ 
+ 	SLEEP_SAVE_MDREFR,
+@@ -205,10 +199,6 @@ enum {	SLEEP_SAVE_START = 0,
+ 
+ void pxa27x_cpu_pm_save(unsigned long *sleep_save)
+ {
+-	SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPLR3);
+-	SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GPDR3);
+-	SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); SAVE(GRER3);
+-	SAVE(GFER0); SAVE(GFER1); SAVE(GFER2); SAVE(GFER3);
+ 	SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2); SAVE(PGSR3);
+ 
+ 	SAVE(GAFR0_L); SAVE(GAFR0_U);
+@@ -220,12 +210,8 @@ void pxa27x_cpu_pm_save(unsigned long *sleep_save)
+ 	SAVE(PWER); SAVE(PCFR); SAVE(PRER);
+ 	SAVE(PFER); SAVE(PKWR);
+ 
+-	SAVE(ICMR); ICMR = 0;
+ 	SAVE(CKEN);
+ 	SAVE(PSTR);
+-
+-	/* Clear GPIO transition detect bits */
+-	GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2; GEDR3 = GEDR3;
+ }
+ 
+ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
+@@ -234,15 +220,10 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
+ 	PSPR = 0;
+ 
+ 	/* restore registers */
+-	RESTORE_GPLEVEL(0); RESTORE_GPLEVEL(1);
+-	RESTORE_GPLEVEL(2); RESTORE_GPLEVEL(3);
+-	RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2); RESTORE(GPDR3);
+ 	RESTORE(GAFR0_L); RESTORE(GAFR0_U);
+ 	RESTORE(GAFR1_L); RESTORE(GAFR1_U);
+ 	RESTORE(GAFR2_L); RESTORE(GAFR2_U);
+ 	RESTORE(GAFR3_L); RESTORE(GAFR3_U);
+-	RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2); RESTORE(GRER3);
+-	RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2); RESTORE(GFER3);
+ 	RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2); RESTORE(PGSR3);
+ 
+ 	RESTORE(MDREFR);
+@@ -253,9 +234,6 @@ void pxa27x_cpu_pm_restore(unsigned long *sleep_save)
+ 
+ 	RESTORE(CKEN);
+ 
+-	ICLR = 0;
+-	ICCR = 1;
+-	RESTORE(ICMR);
+ 	RESTORE(PSTR);
+ }
+ 
+@@ -263,12 +241,6 @@ void pxa27x_cpu_pm_enter(suspend_state_t state)
  {
  	extern void pxa_cpu_standby(void);
  
@@ -43839,7 +54670,7 @@
  	/* ensure voltage-change sequencer not initiated, which hangs */
  	PCFR &= ~PCFR_FVC;
  
-@@ -304,6 +301,8 @@ static void __init pxa27x_init_pm(void)
+@@ -304,6 +276,8 @@ static void __init pxa27x_init_pm(void)
  {
  	pxa_cpu_pm_fns = &pxa27x_cpu_pm_fns;
  }
@@ -43848,7 +54679,7 @@
  #endif
  
  /* PXA27x:  Various gpios can issue wakeup events.  This logic only
-@@ -373,37 +372,6 @@ void __init pxa27x_init_irq(void)
+@@ -373,37 +347,6 @@ void __init pxa27x_init_irq(void)
   * device registration specific to PXA27x.
   */
  
@@ -43886,7 +54717,7 @@
  static struct resource i2c_power_resources[] = {
  	{
  		.start	= 0x40f00180,
-@@ -423,19 +391,22 @@ struct platform_device pxa27x_device_i2c_power = {
+@@ -423,34 +366,57 @@ struct platform_device pxa27x_device_i2c_power = {
  	.num_resources	= ARRAY_SIZE(i2c_power_resources),
  };
  
@@ -43911,10 +54742,27 @@
 +	&pxa27x_device_ssp1,
 +	&pxa27x_device_ssp2,
 +	&pxa27x_device_ssp3,
++};
++
++static struct sys_device pxa27x_sysdev[] = {
++	{
++		.id	= 0,
++		.cls	= &pxa_irq_sysclass,
++	}, {
++		.id	= 1,
++		.cls	= &pxa_irq_sysclass,
++	}, {
++		.cls	= &pxa_gpio_sysclass,
++	},
  };
  
  static int __init pxa27x_init(void)
-@@ -446,9 +417,9 @@ static int __init pxa27x_init(void)
+ {
+-	int ret = 0;
++	int i, ret = 0;
++
+ 	if (cpu_is_pxa27x()) {
+ 		clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
  
  		if ((ret = pxa_init_dma(32)))
  			return ret;
@@ -43923,22 +54771,40 @@
  		pxa27x_init_pm();
 -#endif
 +
++		for (i = 0; i < ARRAY_SIZE(pxa27x_sysdev); i++) {
++			ret = sysdev_register(&pxa27x_sysdev[i]);
++			if (ret)
++				pr_err("failed to register sysdev[%d]\n", i);
++		}
++
  		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
  	}
++
  	return ret;
+ }
+ 
 diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
-index 61d9c9d..5cbf057 100644
+index 61d9c9d..e47e67c 100644
 --- a/arch/arm/mach-pxa/pxa3xx.c
 +++ b/arch/arm/mach-pxa/pxa3xx.c
-@@ -19,6 +19,7 @@
+@@ -19,6 +19,8 @@
  #include <linux/pm.h>
  #include <linux/platform_device.h>
  #include <linux/irq.h>
 +#include <linux/io.h>
++#include <linux/sysdev.h>
  
  #include <asm/hardware.h>
  #include <asm/arch/pxa3xx-regs.h>
-@@ -86,7 +87,7 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info)
+@@ -38,6 +40,7 @@
+ #define RO_CLK		60000000
+ 
+ #define ACCR_D0CS	(1 << 26)
++#define ACCR_PCCE	(1 << 11)
+ 
+ /* crystal frequency to static memory controller multiplier (SMCFS) */
+ static unsigned char smcfs_mult[8] = { 6, 0, 8, 0, 0, 16, };
+@@ -86,7 +89,7 @@ unsigned int pxa3xx_get_clk_frequency_khz(int info)
  			HSS / 1000000, (HSS % 1000000) / 10000);
  	}
  
@@ -43947,7 +54813,7 @@
  }
  
  /*
-@@ -189,8 +190,237 @@ static struct clk pxa3xx_clks[] = {
+@@ -189,8 +192,281 @@ static struct clk pxa3xx_clks[] = {
  
  	PXA3xx_CKEN("I2CCLK", I2C,  32842000, 0, &pxa_device_i2c.dev),
  	PXA3xx_CKEN("UDCCLK", UDC,  48000000, 5, &pxa_device_udc.dev),
@@ -43964,7 +54830,6 @@
 +};
 +
 +#ifdef CONFIG_PM
-+#define SLEEP_SAVE_SIZE	4
 +
 +#define ISRAM_START	0x5c000000
 +#define ISRAM_SIZE	SZ_256K
@@ -43972,25 +54837,29 @@
 +static void __iomem *sram;
 +static unsigned long wakeup_src;
 +
-+static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
-+{
-+	pr_debug("PM: CKENA=%08x CKENB=%08x\n", CKENA, CKENB);
++#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
++#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
 +
-+	if (CKENA & (1 << CKEN_USBH)) {
-+		printk(KERN_ERR "PM: USB host clock not stopped?\n");
-+		CKENA &= ~(1 << CKEN_USBH);
-+	}
-+//	CKENA |= 1 << (CKEN_ISC & 31);
++enum {	SLEEP_SAVE_START = 0,
++	SLEEP_SAVE_CKENA,
++	SLEEP_SAVE_CKENB,
++	SLEEP_SAVE_ACCR,
 +
-+	/*
-+	 * Low power modes require the HSIO2 clock to be enabled.
-+	 */
-+	CKENB |= 1 << (CKEN_HSIO2 & 31);
++	SLEEP_SAVE_SIZE,
++};
++
++static void pxa3xx_cpu_pm_save(unsigned long *sleep_save)
++{
++	SAVE(CKENA);
++	SAVE(CKENB);
++	SAVE(ACCR);
 +}
 +
 +static void pxa3xx_cpu_pm_restore(unsigned long *sleep_save)
 +{
-+	CKENB &= ~(1 << (CKEN_HSIO2 & 31));
++	RESTORE(ACCR);
++	RESTORE(CKENA);
++	RESTORE(CKENB);
 +}
 +
 +/*
@@ -44026,6 +54895,46 @@
 +	printk("PM: AD2D0SR=%08x ASCR=%08x\n", AD2D0SR, ASCR);
 +}
 +
++/*
++ * NOTE:  currently, the OBM (OEM Boot Module) binary comes along with
++ * PXA3xx development kits assumes that the resuming process continues
++ * with the address stored within the first 4 bytes of SDRAM. The PSPR
++ * register is used privately by BootROM and OBM, and _must_ be set to
++ * 0x5c014000 for the moment.
++ */
++static void pxa3xx_cpu_pm_suspend(void)
++{
++	volatile unsigned long *p = (volatile void *)0xc0000000;
++	unsigned long saved_data = *p;
++
++	extern void pxa3xx_cpu_suspend(void);
++	extern void pxa3xx_cpu_resume(void);
++
++	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
++	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
++	CKENB |= 1 << (CKEN_HSIO2 & 0x1f);
++
++	/* clear and setup wakeup source */
++	AD3SR = ~0;
++	AD3ER = wakeup_src;
++	ASCR = ASCR;
++	ARSR = ARSR;
++
++	PCFR |= (1u << 13);			/* L1_DIS */
++	PCFR &= ~((1u << 12) | (1u << 1));	/* L0_EN | SL_ROD */
++
++	PSPR = 0x5c014000;
++
++	/* overwrite with the resume address */
++	*p = virt_to_phys(pxa3xx_cpu_resume);
++
++	pxa3xx_cpu_suspend();
++
++	*p = saved_data;
++
++	AD3ER = 0;
++}
++
 +static void pxa3xx_cpu_pm_enter(suspend_state_t state)
 +{
 +	/*
@@ -44040,6 +54949,7 @@
 +		break;
 +
 +	case PM_SUSPEND_MEM:
++		pxa3xx_cpu_pm_suspend();
 +		break;
 +	}
 +}
@@ -44185,7 +55095,7 @@
  void __init pxa3xx_init_irq(void)
  {
  	/* enable CP6 access */
-@@ -202,6 +432,7 @@ void __init pxa3xx_init_irq(void)
+@@ -202,6 +478,7 @@ void __init pxa3xx_init_irq(void)
  	pxa_init_irq_low();
  	pxa_init_irq_high();
  	pxa_init_irq_gpio(128);
@@ -44193,7 +55103,7 @@
  }
  
  /*
-@@ -209,16 +440,16 @@ void __init pxa3xx_init_irq(void)
+@@ -209,21 +486,33 @@ void __init pxa3xx_init_irq(void)
   */
  
  static struct platform_device *devices[] __initdata = {
@@ -44211,18 +55121,48 @@
 +	&pxa27x_device_ssp2,
 +	&pxa27x_device_ssp3,
 +	&pxa3xx_device_ssp4,
++};
++
++static struct sys_device pxa3xx_sysdev[] = {
++	{
++		.id	= 0,
++		.cls	= &pxa_irq_sysclass,
++	}, {
++		.id	= 1,
++		.cls	= &pxa_irq_sysclass,
++	}, {
++		.cls	= &pxa_gpio_sysclass,
++	},
  };
  
  static int __init pxa3xx_init(void)
-@@ -231,6 +462,8 @@ static int __init pxa3xx_init(void)
+ {
+-	int ret = 0;
++	int i, ret = 0;
+ 
+ 	if (cpu_is_pxa3xx()) {
+ 		clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+@@ -231,9 +520,18 @@ static int __init pxa3xx_init(void)
  		if ((ret = pxa_init_dma(32)))
  			return ret;
  
+-		return platform_add_devices(devices, ARRAY_SIZE(devices));
 +		pxa3xx_init_pm();
 +
- 		return platform_add_devices(devices, ARRAY_SIZE(devices));
++		for (i = 0; i < ARRAY_SIZE(pxa3xx_sysdev); i++) {
++			ret = sysdev_register(&pxa3xx_sysdev[i]);
++			if (ret)
++				pr_err("failed to register sysdev[%d]\n", i);
++		}
++
++		ret = platform_add_devices(devices, ARRAY_SIZE(devices));
  	}
- 	return 0;
+-	return 0;
++
++	return ret;
+ }
+ 
+ subsys_initcall(pxa3xx_init);
 diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h
 index da4769c..047909a 100644
 --- a/arch/arm/mach-pxa/sharpsl.h
@@ -44260,7 +55200,7 @@
  
  /* MAX1111 Channel Definitions */
 diff --git a/arch/arm/mach-pxa/sleep.S b/arch/arm/mach-pxa/sleep.S
-index d044772..14bb4a9 100644
+index d044772..784716e 100644
 --- a/arch/arm/mach-pxa/sleep.S
 +++ b/arch/arm/mach-pxa/sleep.S
 @@ -16,6 +16,7 @@
@@ -44271,15 +55211,117 @@
  
  #define MDREFR_KDIV	0x200a4000	// all banks
  #define CCCR_SLEEP	0x00000107	// L=7 2N=2 A=0 PPDIS=0 CPDIS=0
-@@ -49,6 +50,7 @@ pxa_cpu_save_sp:
+@@ -49,6 +50,109 @@ pxa_cpu_save_sp:
  	str	r0, [r1]
  	ldr	pc, [sp], #4
  
++#ifdef CONFIG_PXA3xx
++/*
++ * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
++ *
++ * NOTE:  unfortunately, pxa_cpu_save_cp can not be reused here since
++ * the auxiliary control register address is different between pxa3xx
++ * and pxa{25x,27x}
++ */
++
++ENTRY(pxa3xx_cpu_suspend)
++
++#ifndef CONFIG_IWMMXT
++	mra	r2, r3, acc0
++#endif
++	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
++
++	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
++	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
++	mrc	p15, 0, r5, c13, c0, 0		@ PID
++	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
++	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
++	mrc	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
++	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
++
++	bic	r3, r3, #2			@ clear frequency change bit
++
++	@ store them plus current virtual stack ptr on stack
++	mov	r10, sp
++	stmfd	sp!, {r3 - r10}
++
++	@ store physical address of stack pointer
++	mov	r0, sp
++	bl	sleep_phys_sp
++	ldr	r1, =sleep_save_sp
++	str	r0, [r1]
++
++	@ clean data cache
++	bl	xsc3_flush_kern_cache_all
++
++	mov	r0, #0x06		@ S2D3C4 mode
++	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
++
++20:	b	20b			@ waiting for sleep
++
++	.data
++	.align 5
++/*
++ * pxa3xx_cpu_resume
++ */
++
++ENTRY(pxa3xx_cpu_resume)
++
++	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
++	msr	cpsr_c, r0
++
++	ldr	r0, sleep_save_sp		@ stack phys addr
++	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
++
++	mov	r1, #0
++	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
++	mcr	p15, 0, r1, c7, c10, 4		@ drain write (&fill) buffer
++	mcr	p15, 0, r1, c7, c5, 4		@ flush prefetch buffer
++	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
++
++	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
++	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
++	mcr	p15, 0, r5, c13, c0, 0		@ PID
++	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
++	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
++	mcr	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
++
++	@ temporarily map resume_turn_on_mmu into the page table,
++	@ otherwise prefetch abort occurs after MMU is turned on
++	mov	r1, r7
++	bic	r1, r1, #0x00ff
++	bic	r1, r1, #0x3f00
++	ldr	r2, =0x542e
++
++	adr	r3, resume_turn_on_mmu
++	mov	r3, r3, lsr #20
++	orr	r4, r2, r3, lsl #20
++	ldr	r5, [r1, r3, lsl #2]
++	str     r4, [r1, r3, lsl #2]
++
++	@ Mapping page table address in the page table
++	mov	r6, r1, lsr #20
++	orr	r7, r2, r6, lsl #20
++	ldr	r8, [r1, r6, lsl #2]
++	str	r7, [r1, r6, lsl #2]
++
++	ldr	r2, =pxa3xx_resume_after_mmu	@ absolute virtual address
++	b	resume_turn_on_mmu		@ cache align execution
++
++	.text
++pxa3xx_resume_after_mmu:
++	/* restore the temporary mapping */
++	str	r5, [r1, r3, lsl #2]
++	str	r8, [r1, r6, lsl #2]
++	b	resume_after_mmu
++
++#endif /* CONFIG_PXA3xx */
++
 +#ifdef CONFIG_PXA27x
  /*
   * pxa27x_cpu_suspend()
   *
-@@ -104,9 +106,11 @@ ENTRY(pxa27x_cpu_suspend)
+@@ -104,9 +208,11 @@ ENTRY(pxa27x_cpu_suspend)
  
  	@ align execution to a cache line
  	b	pxa_cpu_do_suspend
@@ -44292,7 +55334,7 @@
   *
   * Forces CPU into sleep state.
   *
-@@ -169,6 +173,7 @@ ENTRY(pxa25x_cpu_suspend)
+@@ -169,6 +275,7 @@ ENTRY(pxa25x_cpu_suspend)
  	mcr	p14, 0, r0, c6, c0, 0
  	orr	r0, r0, #2			@ initiate change bit
  	b	pxa_cpu_do_suspend
@@ -44300,7 +55342,7 @@
  
  	.ltorg
  	.align	5
-@@ -208,7 +213,7 @@ pxa_cpu_do_suspend:
+@@ -208,7 +315,7 @@ pxa_cpu_do_suspend:
  20:	b	20b				@ loop waiting for sleep
  
  /*
@@ -44309,11 +55351,113 @@
   *
   * entry point from bootloader into kernel during resume
   *
+diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c
+new file mode 100644
+index 0000000..ad346ad
+--- /dev/null
++++ b/arch/arm/mach-pxa/smemc.c
+@@ -0,0 +1,88 @@
++/*
++ * Static Memory Controller
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/sysdev.h>
++
++#define SMEMC_PHYS_BASE	(0x4A000000)
++#define SMEMC_PHYS_SIZE	(0x90)
++
++#define MSC0		(0x08)	/* Static Memory Controller Register 0 */
++#define MSC1		(0x0C)	/* Static Memory Controller Register 1 */
++#define SXCNFG		(0x1C)	/* Synchronous Static Memory Control Register */
++#define MEMCLKCFG	(0x68)	/* Clock Configuration */
++#define CSADRCFG0	(0x80)	/* Address Configuration Register for CS0 */
++#define CSADRCFG1	(0x84)	/* Address Configuration Register for CS1 */
++#define CSADRCFG2	(0x88)	/* Address Configuration Register for CS2 */
++#define CSADRCFG3	(0x8C)	/* Address Configuration Register for CS3 */
++
++#ifdef CONFIG_PM
++static void __iomem *smemc_mmio_base;
++
++static unsigned long msc[2];
++static unsigned long sxcnfg, memclkcfg;
++static unsigned long csadrcfg[4];
++
++static int pxa3xx_smemc_suspend(struct sys_device *dev, pm_message_t state)
++{
++	msc[0] = __raw_readl(smemc_mmio_base + MSC0);
++	msc[1] = __raw_readl(smemc_mmio_base + MSC1);
++	sxcnfg = __raw_readl(smemc_mmio_base + SXCNFG);
++	memclkcfg = __raw_readl(smemc_mmio_base + MEMCLKCFG);
++	csadrcfg[0] = __raw_readl(smemc_mmio_base + CSADRCFG0);
++	csadrcfg[1] = __raw_readl(smemc_mmio_base + CSADRCFG1);
++	csadrcfg[2] = __raw_readl(smemc_mmio_base + CSADRCFG2);
++	csadrcfg[3] = __raw_readl(smemc_mmio_base + CSADRCFG3);
++
++	return 0;
++}
++
++static int pxa3xx_smemc_resume(struct sys_device *dev)
++{
++	__raw_writel(msc[0], smemc_mmio_base + MSC0);
++	__raw_writel(msc[1], smemc_mmio_base + MSC1);
++	__raw_writel(sxcnfg, smemc_mmio_base + SXCNFG);
++	__raw_writel(memclkcfg, smemc_mmio_base + MEMCLKCFG);
++	__raw_writel(csadrcfg[0], smemc_mmio_base + CSADRCFG0);
++	__raw_writel(csadrcfg[1], smemc_mmio_base + CSADRCFG1);
++	__raw_writel(csadrcfg[2], smemc_mmio_base + CSADRCFG2);
++	__raw_writel(csadrcfg[3], smemc_mmio_base + CSADRCFG3);
++
++	return 0;
++}
++
++static struct sysdev_class smemc_sysclass = {
++	.name		= "smemc",
++	.suspend	= pxa3xx_smemc_suspend,
++	.resume		= pxa3xx_smemc_resume,
++};
++
++static struct sys_device smemc_sysdev = {
++	.id		= 0,
++	.cls		= &smemc_sysclass,
++};
++
++static int __init smemc_init(void)
++{
++	int ret = 0;
++
++	if (cpu_is_pxa3xx()) {
++		smemc_mmio_base = ioremap(SMEMC_PHYS_BASE, SMEMC_PHYS_SIZE);
++		if (smemc_mmio_base == NULL)
++			return -ENODEV;
++
++		ret = sysdev_class_register(&smemc_sysclass);
++		if (ret)
++			return ret;
++
++		ret = sysdev_register(&smemc_sysdev);
++	}
++
++	return ret;
++}
++subsys_initcall(smemc_init);
++#endif
 diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
-index 2d78199..5078ede 100644
+index 2d78199..9e7773f 100644
 --- a/arch/arm/mach-pxa/spitz.c
 +++ b/arch/arm/mach-pxa/spitz.c
-@@ -271,6 +271,55 @@ static struct platform_device spitzled_device = {
+@@ -36,6 +36,7 @@
+ #include <asm/mach/irq.h>
+ 
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-regs.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/ohci.h>
+@@ -271,6 +272,55 @@ static struct platform_device spitzled_device = {
  /*
   * Spitz Touch Screen Device
   */
@@ -44369,7 +55513,7 @@
  static struct resource spitzts_resources[] = {
  	[0] = {
  		.start		= SPITZ_IRQ_GPIO_TP_INT,
-@@ -280,9 +329,9 @@ static struct resource spitzts_resources[] = {
+@@ -280,9 +330,9 @@ static struct resource spitzts_resources[] = {
  };
  
  static struct corgits_machinfo  spitz_ts_machinfo = {
@@ -44382,7 +55526,7 @@
  };
  
  static struct platform_device spitzts_device = {
-@@ -325,12 +374,10 @@ static int spitz_mci_init(struct device *dev, irq_handler_t spitz_detect_int, vo
+@@ -325,12 +375,10 @@ static int spitz_mci_init(struct device *dev, irq_handler_t spitz_detect_int, vo
  	err = request_irq(SPITZ_IRQ_GPIO_nSD_DETECT, spitz_detect_int,
  			  IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
  			  "MMC card detect", data);
@@ -44397,7 +55541,7 @@
  }
  
  static void spitz_mci_setpower(struct device *dev, unsigned int vdd)
-@@ -423,6 +470,14 @@ static struct pxaficp_platform_data spitz_ficp_platform_data = {
+@@ -423,6 +471,14 @@ static struct pxaficp_platform_data spitz_ficp_platform_data = {
   * Spitz PXA Framebuffer
   */
  
@@ -44412,7 +55556,7 @@
  static struct pxafb_mode_info spitz_pxafb_modes[] = {
  {
  	.pixclock       = 19231,
-@@ -520,6 +575,27 @@ static void __init common_init(void)
+@@ -520,6 +576,27 @@ static void __init common_init(void)
  	set_pxa_fb_info(&spitz_pxafb_info);
  }
  
@@ -44440,7 +55584,7 @@
  static void __init spitz_init(void)
  {
  	platform_scoop_config = &spitz_pcmcia_config;
-@@ -530,6 +606,7 @@ static void __init spitz_init(void)
+@@ -530,6 +607,7 @@ static void __init spitz_init(void)
  
  	platform_device_register(&spitzscoop2_device);
  }
@@ -44448,7 +55592,7 @@
  
  #ifdef CONFIG_MACH_AKITA
  /*
-@@ -542,6 +619,26 @@ struct platform_device akitaioexp_device = {
+@@ -542,6 +620,26 @@ struct platform_device akitaioexp_device = {
  
  EXPORT_SYMBOL_GPL(akitaioexp_device);
  
@@ -44475,7 +55619,7 @@
  static void __init akita_init(void)
  {
  	spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode;
-@@ -558,7 +655,6 @@ static void __init akita_init(void)
+@@ -558,7 +656,6 @@ static void __init akita_init(void)
  }
  #endif
  
@@ -45266,10 +56410,18 @@
  #else
  #define pxa_timer_suspend NULL
 diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
-index 240fd04..1a9c844 100644
+index 240fd04..9b26fa5 100644
 --- a/arch/arm/mach-pxa/tosa.c
 +++ b/arch/arm/mach-pxa/tosa.c
-@@ -157,15 +157,10 @@ static void tosa_udc_command(int cmd)
+@@ -29,6 +29,7 @@
+ #include <asm/irq.h>
+ #include <asm/system.h>
+ #include <asm/arch/pxa-regs.h>
++#include <asm/arch/pxa2xx-regs.h>
+ #include <asm/arch/irda.h>
+ #include <asm/arch/mmc.h>
+ #include <asm/arch/udc.h>
+@@ -157,15 +158,10 @@ static void tosa_udc_command(int cmd)
  	}
  }
  
@@ -45287,7 +56439,7 @@
  };
  
  /*
-@@ -184,16 +179,13 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
+@@ -184,16 +180,13 @@ static int tosa_mci_init(struct device *dev, irq_handler_t tosa_detect_int, void
  
  	tosa_mci_platform_data.detect_delay = msecs_to_jiffies(250);
  
@@ -45666,28 +56818,950 @@
 +		zylonite_mmc_slot[0].gpio_wp  = mfp_to_gpio(MFP_PIN_GPIO5);
  	}
  }
+diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig
+index 35156ca..39b3bb7 100644
+--- a/arch/arm/mach-realview/Kconfig
++++ b/arch/arm/mach-realview/Kconfig
+@@ -7,24 +7,21 @@ config MACH_REALVIEW_EB
+ 	help
+ 	  Include support for the ARM(R) RealView Emulation Baseboard platform.
+ 
+-config REALVIEW_MPCORE
+-	bool "Support MPcore tile"
++config REALVIEW_EB_ARM11MP
++	bool "Support ARM11MPCore tile"
+ 	depends on MACH_REALVIEW_EB
+ 	select CACHE_L2X0
+ 	help
+-	  Enable support for the MPCore tile on the Realview platform.
+-	  Since there are device address and interrupt differences, a
+-	  kernel built with this option enabled is not compatible with
+-	  other tiles.
++	  Enable support for the ARM11MPCore tile on the Realview platform.
+ 
+-config REALVIEW_MPCORE_REVB
+-	bool "Support MPcore RevB tile"
+-	depends on REALVIEW_MPCORE
++config REALVIEW_EB_ARM11MP_REVB
++	bool "Support ARM11MPCore RevB tile"
++	depends on REALVIEW_EB_ARM11MP
+ 	default n
+ 	help
+-	  Enable support for the MPCore RevB tile on the Realview platform.
+-	  Since there are device address differences, a
++	  Enable support for the ARM11MPCore RevB tile on the Realview
++	  platform. Since there are device address differences, a
+ 	  kernel built with this option enabled is not compatible with
+-	  other tiles.
++	  other revisions of the ARM11MPCore tile.
+ 
+ endmenu
+diff --git a/arch/arm/mach-realview/Makefile b/arch/arm/mach-realview/Makefile
+index 36e76ba..ca1e390 100644
+--- a/arch/arm/mach-realview/Makefile
++++ b/arch/arm/mach-realview/Makefile
+@@ -4,6 +4,5 @@
+ 
+ obj-y					:= core.o clock.o
+ obj-$(CONFIG_MACH_REALVIEW_EB)		+= realview_eb.o
+-obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
++obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o localtimer.o
+ obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
+-obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
 diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
-index c7f1b44..61d7021 100644
+index c7f1b44..98aefc9 100644
 --- a/arch/arm/mach-realview/core.c
 +++ b/arch/arm/mach-realview/core.c
-@@ -530,8 +530,6 @@ static unsigned long realview_gettimeoffset(void)
+@@ -25,6 +25,8 @@
+ #include <linux/interrupt.h>
+ #include <linux/amba/bus.h>
+ #include <linux/amba/clcd.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
+ 
+ #include <asm/system.h>
+ #include <asm/hardware.h>
+@@ -37,7 +39,6 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/flash.h>
+ #include <asm/mach/irq.h>
+-#include <asm/mach/time.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/mmc.h>
+ 
+@@ -48,6 +49,9 @@
+ 
+ #define REALVIEW_REFCOUNTER	(__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
+ 
++/* used by entry-macro.S */
++void __iomem *gic_cpu_base_addr;
++
+ /*
+  * This is the RealView sched_clock implementation.  This has
+  * a resolution of 41.7ns, and a maximum value of about 179s.
+@@ -121,26 +125,6 @@ struct platform_device realview_flash_device = {
+ 	.resource		= &realview_flash_resource,
+ };
+ 
+-static struct resource realview_smc91x_resources[] = {
+-	[0] = {
+-		.start		= REALVIEW_ETH_BASE,
+-		.end		= REALVIEW_ETH_BASE + SZ_64K - 1,
+-		.flags		= IORESOURCE_MEM,
+-	},
+-	[1] = {
+-		.start		= IRQ_ETH,
+-		.end		= IRQ_ETH,
+-		.flags		= IORESOURCE_IRQ,
+-	},
+-};
+-
+-struct platform_device realview_smc91x_device = {
+-	.name		= "smc91x",
+-	.id		= 0,
+-	.num_resources	= ARRAY_SIZE(realview_smc91x_resources),
+-	.resource	= realview_smc91x_resources,
+-};
+-
+ static struct resource realview_i2c_resource = {
+ 	.start		= REALVIEW_I2C_BASE,
+ 	.end		= REALVIEW_I2C_BASE + SZ_4K - 1,
+@@ -484,45 +468,64 @@ void realview_leds_event(led_event_t ledevt)
+ #define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
+ #endif
+ 
+-/*
+- * Returns number of ms since last clock interrupt.  Note that interrupts
+- * will have been disabled by do_gettimeoffset()
+- */
+-static unsigned long realview_gettimeoffset(void)
++static void timer_set_mode(enum clock_event_mode mode,
++			   struct clock_event_device *clk)
+ {
+-	unsigned long ticks1, ticks2, status;
++	unsigned long ctrl;
+ 
+-	/*
+-	 * Get the current number of ticks.  Note that there is a race
+-	 * condition between us reading the timer and checking for
+-	 * an interrupt.  We get around this by ensuring that the
+-	 * counter has not reloaded between our two reads.
+-	 */
+-	ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
+-	do {
+-		ticks1 = ticks2;
+-		status = __raw_readl(__io_address(REALVIEW_GIC_DIST_BASE + GIC_DIST_PENDING_SET)
+-				     + ((IRQ_TIMERINT0_1 >> 5) << 2));
+-		ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
+-	} while (ticks2 > ticks1);
++	switch(mode) {
++	case CLOCK_EVT_MODE_PERIODIC:
++		writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
+ 
+-	/*
+-	 * Number of ticks since last interrupt.
+-	 */
+-	ticks1 = TIMER_RELOAD - ticks2;
++		ctrl = TIMER_CTRL_PERIODIC;
++		ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE | TIMER_CTRL_ENABLE;
++		break;
++	case CLOCK_EVT_MODE_ONESHOT:
++		/* period set, and timer enabled in 'next_event' hook */
++		ctrl = TIMER_CTRL_ONESHOT;
++		ctrl |= TIMER_CTRL_32BIT | TIMER_CTRL_IE;
++		break;
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++	default:
++		ctrl = 0;
++	}
+ 
+-	/*
+-	 * Interrupt pending?  If so, we've reloaded once already.
+-	 *
+-	 * FIXME: Need to check this is effectively timer 0 that expires
+-	 */
+-	if (status & IRQMASK_TIMERINT0_1)
+-		ticks1 += TIMER_RELOAD;
++	writel(ctrl, TIMER0_VA_BASE + TIMER_CTRL);
++}
+ 
+-	/*
+-	 * Convert the ticks to usecs
+-	 */
+-	return TICKS2USECS(ticks1);
++static int timer_set_next_event(unsigned long evt,
++				struct clock_event_device *unused)
++{
++	unsigned long ctrl = readl(TIMER0_VA_BASE + TIMER_CTRL);
++
++	writel(evt, TIMER0_VA_BASE + TIMER_LOAD);
++	writel(ctrl | TIMER_CTRL_ENABLE, TIMER0_VA_BASE + TIMER_CTRL);
++
++	return 0;
++}
++
++static struct clock_event_device timer0_clockevent =	 {
++	.name		= "timer0",
++	.shift		= 32,
++	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
++	.set_mode	= timer_set_mode,
++	.set_next_event	= timer_set_next_event,
++	.rating		= 300,
++	.cpumask	= CPU_MASK_ALL,
++};
++
++static void __init realview_clockevents_init(unsigned int timer_irq)
++{
++	timer0_clockevent.irq = timer_irq;
++	timer0_clockevent.mult =
++		div_sc(1000000, NSEC_PER_SEC, timer0_clockevent.shift);
++	timer0_clockevent.max_delta_ns =
++		clockevent_delta2ns(0xffffffff, &timer0_clockevent);
++	timer0_clockevent.min_delta_ns =
++		clockevent_delta2ns(0xf, &timer0_clockevent);
++
++	clockevents_register_device(&timer0_clockevent);
+ }
+ 
+ /*
+@@ -530,19 +533,12 @@ static unsigned long realview_gettimeoffset(void)
   */
  static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
  {
 -	write_seqlock(&xtime_lock);
--
- 	// ...clear the interrupt
- 	writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
++	struct clock_event_device *evt = &timer0_clockevent;
  
-@@ -542,8 +540,6 @@ static irqreturn_t realview_timer_interrupt(int irq, void *dev_id)
- 	update_process_times(user_mode(get_irq_regs()));
- #endif
+-	// ...clear the interrupt
++	/* clear the interrupt */
+ 	writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
  
--	write_sequnlock(&xtime_lock);
+-	timer_tick();
 -
+-#if defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
+-	smp_send_timer();
+-	update_process_times(user_mode(get_irq_regs()));
+-#endif
+-
+-	write_sequnlock(&xtime_lock);
++	evt->event_handler(evt);
+ 
  	return IRQ_HANDLED;
  }
+@@ -553,13 +549,49 @@ static struct irqaction realview_timer_irq = {
+ 	.handler	= realview_timer_interrupt,
+ };
+ 
++static cycle_t realview_get_cycles(void)
++{
++	return ~readl(TIMER3_VA_BASE + TIMER_VALUE);
++}
++
++static struct clocksource clocksource_realview = {
++	.name	= "timer3",
++	.rating	= 200,
++	.read	= realview_get_cycles,
++	.mask	= CLOCKSOURCE_MASK(32),
++	.shift	= 20,
++	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
++};
++
++static void __init realview_clocksource_init(void)
++{
++	/* setup timer 0 as free-running clocksource */
++	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
++	writel(0xffffffff, TIMER3_VA_BASE + TIMER_LOAD);
++	writel(0xffffffff, TIMER3_VA_BASE + TIMER_VALUE);
++	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
++		TIMER3_VA_BASE + TIMER_CTRL);
++
++	clocksource_realview.mult =
++		clocksource_khz2mult(1000, clocksource_realview.shift);
++	clocksource_register(&clocksource_realview);
++}
++
+ /*
+- * Set up timer interrupt, and return the current time in seconds.
++ * Set up the clock source and clock events devices
+  */
+-static void __init realview_timer_init(void)
++void __init realview_timer_init(unsigned int timer_irq)
+ {
+ 	u32 val;
+ 
++#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
++	/*
++	 * The dummy clock device has to be registered before the main device
++	 * so that the latter will broadcast the clock events
++	 */
++	local_timer_setup(smp_processor_id());
++#endif
++
+ 	/* 
+ 	 * set clock frequency: 
+ 	 *	REALVIEW_REFCLK is 32KHz
+@@ -580,18 +612,11 @@ static void __init realview_timer_init(void)
+ 	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+ 	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+ 
+-	writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
+-	writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
+-	writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
+-	       TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
+-
+ 	/* 
+ 	 * Make irqs happen for the system timer
+ 	 */
+-	setup_irq(IRQ_TIMERINT0_1, &realview_timer_irq);
+-}
++	setup_irq(timer_irq, &realview_timer_irq);
+ 
+-struct sys_timer realview_timer = {
+-	.init		= realview_timer_init,
+-	.offset		= realview_gettimeoffset,
+-};
++	realview_clocksource_init();
++	realview_clockevents_init(timer_irq);
++}
+diff --git a/arch/arm/mach-realview/core.h b/arch/arm/mach-realview/core.h
+index 2b53420..492a14c 100644
+--- a/arch/arm/mach-realview/core.h
++++ b/arch/arm/mach-realview/core.h
+@@ -27,8 +27,6 @@
+ #include <asm/leds.h>
+ #include <asm/io.h>
+ 
+-extern struct sys_timer realview_timer;
+-
+ #define AMBA_DEVICE(name,busid,base,plat)			\
+ static struct amba_device name##_device = {			\
+ 	.dev		= {					\
+@@ -38,7 +36,7 @@ static struct amba_device name##_device = {			\
+ 	},							\
+ 	.res		= {					\
+ 		.start	= REALVIEW_##base##_BASE,		\
+-		.end	= (REALVIEW_##base##_BASE) + SZ_4K - 1,\
++		.end	= (REALVIEW_##base##_BASE) + SZ_4K - 1,	\
+ 		.flags	= IORESOURCE_MEM,			\
+ 	},							\
+ 	.dma_mask	= ~0,					\
+@@ -46,74 +44,19 @@ static struct amba_device name##_device = {			\
+ 	/* .dma		= base##_DMA,*/				\
+ }
+ 
+-/*
+- * These devices are connected via the core APB bridge
+- */
+-#define GPIO2_IRQ	{ IRQ_GPIOINT2, NO_IRQ }
+-#define GPIO2_DMA	{ 0, 0 }
+-#define GPIO3_IRQ	{ IRQ_GPIOINT3, NO_IRQ }
+-#define GPIO3_DMA	{ 0, 0 }
+-
+-#define AACI_IRQ	{ IRQ_AACI, NO_IRQ }
+-#define AACI_DMA	{ 0x80, 0x81 }
+-#define MMCI0_IRQ	{ IRQ_MMCI0A,IRQ_MMCI0B }
+-#define MMCI0_DMA	{ 0x84, 0 }
+-#define KMI0_IRQ	{ IRQ_KMI0, NO_IRQ }
+-#define KMI0_DMA	{ 0, 0 }
+-#define KMI1_IRQ	{ IRQ_KMI1, NO_IRQ }
+-#define KMI1_DMA	{ 0, 0 }
+-
+-/*
+- * These devices are connected directly to the multi-layer AHB switch
+- */
+-#define SMC_IRQ		{ NO_IRQ, NO_IRQ }
+-#define SMC_DMA		{ 0, 0 }
+-#define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
+-#define MPMC_DMA	{ 0, 0 }
+-#define CLCD_IRQ	{ IRQ_CLCDINT, NO_IRQ }
+-#define CLCD_DMA	{ 0, 0 }
+-#define DMAC_IRQ	{ IRQ_DMAINT, NO_IRQ }
+-#define DMAC_DMA	{ 0, 0 }
+-
+-/*
+- * These devices are connected via the core APB bridge
+- */
+-#define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
+-#define SCTL_DMA	{ 0, 0 }
+-#define WATCHDOG_IRQ	{ IRQ_WDOGINT, NO_IRQ }
+-#define WATCHDOG_DMA	{ 0, 0 }
+-#define GPIO0_IRQ	{ IRQ_GPIOINT0, NO_IRQ }
+-#define GPIO0_DMA	{ 0, 0 }
+-#define GPIO1_IRQ	{ IRQ_GPIOINT1, NO_IRQ }
+-#define GPIO1_DMA	{ 0, 0 }
+-#define RTC_IRQ		{ IRQ_RTCINT, NO_IRQ }
+-#define RTC_DMA		{ 0, 0 }
+-
+-/*
+- * These devices are connected via the DMA APB bridge
+- */
+-#define SCI_IRQ		{ IRQ_SCIINT, NO_IRQ }
+-#define SCI_DMA		{ 7, 6 }
+-#define UART0_IRQ	{ IRQ_UARTINT0, NO_IRQ }
+-#define UART0_DMA	{ 15, 14 }
+-#define UART1_IRQ	{ IRQ_UARTINT1, NO_IRQ }
+-#define UART1_DMA	{ 13, 12 }
+-#define UART2_IRQ	{ IRQ_UARTINT2, NO_IRQ }
+-#define UART2_DMA	{ 11, 10 }
+-#define UART3_IRQ	{ IRQ_UART3, NO_IRQ }
+-#define UART3_DMA	{ 0x86, 0x87 }
+-#define SSP_IRQ		{ IRQ_SSPINT, NO_IRQ }
+-#define SSP_DMA		{ 9, 8 }
+-
+-
+ extern struct platform_device realview_flash_device;
+-extern struct platform_device realview_smc91x_device;
+ extern struct platform_device realview_i2c_device;
+ extern struct mmc_platform_data realview_mmc0_plat_data;
+ extern struct mmc_platform_data realview_mmc1_plat_data;
+ extern struct clk realview_clcd_clk;
+ extern struct clcd_board clcd_plat_data;
++extern void __iomem *gic_cpu_base_addr;
++#ifdef CONFIG_LOCAL_TIMERS
++extern void __iomem *twd_base_addr;
++extern unsigned int twd_size;
++#endif
+ 
+ extern void realview_leds_event(led_event_t ledevt);
++extern void realview_timer_init(unsigned int timer_irq);
+ 
+ #endif
+diff --git a/arch/arm/mach-realview/localtimer.c b/arch/arm/mach-realview/localtimer.c
+index c7bdf04..5060436 100644
+--- a/arch/arm/mach-realview/localtimer.c
++++ b/arch/arm/mach-realview/localtimer.c
+@@ -14,19 +14,75 @@
+ #include <linux/device.h>
+ #include <linux/smp.h>
+ #include <linux/jiffies.h>
++#include <linux/percpu.h>
++#include <linux/clockchips.h>
++#include <linux/irq.h>
+ 
+-#include <asm/mach/time.h>
+ #include <asm/hardware/arm_twd.h>
+ #include <asm/hardware/gic.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/irq.h>
+ 
+-#define TWD_BASE(cpu)	(__io_address(REALVIEW_TWD_BASE) + \
+-			 ((cpu) * REALVIEW_TWD_SIZE))
++static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
++
++/*
++ * Used on SMP for either the local timer or IPI_TIMER
++ */
++void local_timer_interrupt(void)
++{
++	struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
++
++	clk->event_handler(clk);
++}
++
++#ifdef CONFIG_LOCAL_TIMERS
++
++#define TWD_BASE(cpu)	(twd_base_addr + (cpu) * twd_size)
++
++/* set up by the platform code */
++void __iomem *twd_base_addr;
++unsigned int twd_size;
+ 
+ static unsigned long mpcore_timer_rate;
+ 
++static void local_timer_set_mode(enum clock_event_mode mode,
++				 struct clock_event_device *clk)
++{
++	void __iomem *base = TWD_BASE(smp_processor_id());
++	unsigned long ctrl;
++
++	switch(mode) {
++	case CLOCK_EVT_MODE_PERIODIC:
++		/* timer load already set up */
++		ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
++			| TWD_TIMER_CONTROL_PERIODIC;
++		break;
++	case CLOCK_EVT_MODE_ONESHOT:
++		/* period set, and timer enabled in 'next_event' hook */
++		ctrl = TWD_TIMER_CONTROL_IT_ENABLE | TWD_TIMER_CONTROL_ONESHOT;
++		break;
++	case CLOCK_EVT_MODE_UNUSED:
++	case CLOCK_EVT_MODE_SHUTDOWN:
++	default:
++		ctrl = 0;
++	}
++
++	__raw_writel(ctrl, base + TWD_TIMER_CONTROL);
++}
++
++static int local_timer_set_next_event(unsigned long evt,
++				      struct clock_event_device *unused)
++{
++	void __iomem *base = TWD_BASE(smp_processor_id());
++	unsigned long ctrl = __raw_readl(base + TWD_TIMER_CONTROL);
++
++	__raw_writel(evt, base + TWD_TIMER_COUNTER);
++	__raw_writel(ctrl | TWD_TIMER_CONTROL_ENABLE, base + TWD_TIMER_CONTROL);
++
++	return 0;
++}
++
+ /*
+  * local_timer_ack: checks for a local timer interrupt.
+  *
+@@ -45,12 +101,11 @@ int local_timer_ack(void)
+ 	return 0;
+ }
+ 
+-void __cpuinit local_timer_setup(unsigned int cpu)
++static void __cpuinit twd_calibrate_rate(unsigned int cpu)
+ {
+ 	void __iomem *base = TWD_BASE(cpu);
+-	unsigned int load, offset;
++	unsigned long load, count;
+ 	u64 waitjiffies;
+-	unsigned int count;
+ 
+ 	/*
+ 	 * If this is the first time round, we need to work out how fast
+@@ -88,36 +143,36 @@ void __cpuinit local_timer_setup(unsigned int cpu)
+ 	load = mpcore_timer_rate / HZ;
+ 
+ 	__raw_writel(load, base + TWD_TIMER_LOAD);
+-	__raw_writel(0x7,  base + TWD_TIMER_CONTROL);
+-
+-	/*
+-	 * Now maneuver our local tick into the right part of the jiffy.
+-	 * Start by working out where within the tick our local timer
+-	 * interrupt should go.
+-	 */
+-	offset = ((mpcore_timer_rate / HZ) / (NR_CPUS + 1)) * (cpu + 1);
+-
+-	/*
+-	 * gettimeoffset() will return a number of us since the last tick.
+-	 * Convert this number of us to a local timer tick count.
+-	 * Be careful of integer overflow whilst keeping maximum precision.
+-	 *
+-	 * with HZ=100 and 1MHz (fpga) ~ 1GHz processor:
+-	 * load = 1 ~ 10,000
+-	 * mpcore_timer_rate/10000 = 100 ~ 100,000
+-	 *
+-	 * so the multiply value will be less than 10^9 always.
+-	 */
+-	load = (system_timer->offset() * (mpcore_timer_rate / 10000)) / 100;
+-
+-	/* Add on our offset to get the load value */
+-	load = (load + offset) % (mpcore_timer_rate / HZ);
++}
+ 
+-	__raw_writel(load, base + TWD_TIMER_COUNTER);
++/*
++ * Setup the local clock events for a CPU.
++ */
++void __cpuinit local_timer_setup(unsigned int cpu)
++{
++	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
++	unsigned long flags;
++
++	twd_calibrate_rate(cpu);
++
++	clk->name		= "local_timer";
++	clk->features		= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
++	clk->rating		= 350;
++	clk->set_mode		= local_timer_set_mode;
++	clk->set_next_event	= local_timer_set_next_event;
++	clk->irq		= IRQ_LOCALTIMER;
++	clk->cpumask		= cpumask_of_cpu(cpu);
++	clk->shift		= 20;
++	clk->mult		= div_sc(mpcore_timer_rate, NSEC_PER_SEC, clk->shift);
++	clk->max_delta_ns	= clockevent_delta2ns(0xffffffff, clk);
++	clk->min_delta_ns	= clockevent_delta2ns(0xf, clk);
+ 
+ 	/* Make sure our local interrupt controller has this enabled */
+-	__raw_writel(1 << IRQ_LOCALTIMER,
+-		     __io_address(REALVIEW_GIC_DIST_BASE) + GIC_DIST_ENABLE_SET);
++	local_irq_save(flags);
++	get_irq_chip(IRQ_LOCALTIMER)->unmask(IRQ_LOCALTIMER);
++	local_irq_restore(flags);
++
++	clockevents_register_device(clk);
+ }
+ 
+ /*
+@@ -127,3 +182,26 @@ void __cpuexit local_timer_stop(unsigned int cpu)
+ {
+ 	__raw_writel(0, TWD_BASE(cpu) + TWD_TIMER_CONTROL);
+ }
++
++#else	/* CONFIG_LOCAL_TIMERS */
++
++static void dummy_timer_set_mode(enum clock_event_mode mode,
++				 struct clock_event_device *clk)
++{
++}
++
++void __cpuinit local_timer_setup(unsigned int cpu)
++{
++	struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
++
++	clk->name		= "dummy_timer";
++	clk->features		= CLOCK_EVT_FEAT_DUMMY;
++	clk->rating		= 200;
++	clk->set_mode		= dummy_timer_set_mode;
++	clk->broadcast		= smp_timer_broadcast;
++	clk->cpumask		= cpumask_of_cpu(cpu);
++
++	clockevents_register_device(clk);
++}
++
++#endif	/* !CONFIG_LOCAL_TIMERS */
+diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
+index fce3596..de2b715 100644
+--- a/arch/arm/mach-realview/platsmp.c
++++ b/arch/arm/mach-realview/platsmp.c
+@@ -18,6 +18,7 @@
+ #include <asm/hardware/arm_scu.h>
+ #include <asm/hardware.h>
+ #include <asm/io.h>
++#include <asm/mach-types.h>
+ 
+ extern void realview_secondary_startup(void);
+ 
+@@ -31,9 +32,13 @@ static unsigned int __init get_core_count(void)
+ {
+ 	unsigned int ncores;
+ 
+-	ncores = __raw_readl(__io_address(REALVIEW_MPCORE_SCU_BASE) + SCU_CONFIG);
++	if (machine_is_realview_eb() && core_tile_eb11mp()) {
++		ncores = __raw_readl(__io_address(REALVIEW_EB11MP_SCU_BASE) + SCU_CONFIG);
++		ncores = (ncores & 0x03) + 1;
++	} else
++		ncores = 1;
+ 
+-	return (ncores & 0x03) + 1;
++	return ncores;
+ }
+ 
+ static DEFINE_SPINLOCK(boot_lock);
+@@ -52,7 +57,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
+ 	 * core (e.g. timer irq), then they will not have been enabled
+ 	 * for us: do so
+ 	 */
+-	gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
++	gic_cpu_init(0, __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
+ 
+ 	/*
+ 	 * let the primary processor know we're out of the
+@@ -187,10 +192,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
+ 	if (max_cpus > ncores)
+ 		max_cpus = ncores;
+ 
++#ifdef CONFIG_LOCAL_TIMERS
+ 	/*
+-	 * Enable the local timer for primary CPU
++	 * Enable the local timer for primary CPU. If the device is
++	 * dummy (!CONFIG_LOCAL_TIMERS), it was already registers in
++	 * realview_timer_init
+ 	 */
+-	local_timer_setup(cpu);
++	if (machine_is_realview_eb() && core_tile_eb11mp())
++		local_timer_setup(cpu);
++#endif
+ 
+ 	/*
+ 	 * Initialise the present map, which describes the set of CPUs
+diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
+index ecec2f8..60d9eb8 100644
+--- a/arch/arm/mach-realview/realview_eb.c
++++ b/arch/arm/mach-realview/realview_eb.c
+@@ -36,7 +36,9 @@
+ #include <asm/mach/arch.h>
+ #include <asm/mach/map.h>
+ #include <asm/mach/mmc.h>
++#include <asm/mach/time.h>
+ 
++#include <asm/arch/board-eb.h>
+ #include <asm/arch/irqs.h>
+ 
+ #include "core.h"
+@@ -58,26 +60,7 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
+ 		.pfn		= __phys_to_pfn(REALVIEW_GIC_DIST_BASE),
+ 		.length		= SZ_4K,
+ 		.type		= MT_DEVICE,
+-	},
+-#ifdef CONFIG_REALVIEW_MPCORE
+-	{
+-		.virtual	= IO_ADDRESS(REALVIEW_GIC1_CPU_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_GIC1_CPU_BASE),
+-		.length		= SZ_4K,
+-		.type		= MT_DEVICE,
+ 	}, {
+-		.virtual	= IO_ADDRESS(REALVIEW_GIC1_DIST_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_GIC1_DIST_BASE),
+-		.length		= SZ_4K,
+-		.type		= MT_DEVICE,
+-	}, {
+-		.virtual	= IO_ADDRESS(REALVIEW_MPCORE_L220_BASE),
+-		.pfn		= __phys_to_pfn(REALVIEW_MPCORE_L220_BASE),
+-		.length		= SZ_8K,
+-		.type		= MT_DEVICE,
+-	},
+-#endif
+-	{
+ 		.virtual	= IO_ADDRESS(REALVIEW_SCTL_BASE),
+ 		.pfn		= __phys_to_pfn(REALVIEW_SCTL_BASE),
+ 		.length		= SZ_4K,
+@@ -103,11 +86,95 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
+ #endif
+ };
+ 
++static struct map_desc realview_eb11mp_io_desc[] __initdata = {
++	{
++		.virtual	= IO_ADDRESS(REALVIEW_EB11MP_GIC_CPU_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB11MP_GIC_CPU_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_EB11MP_GIC_DIST_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB11MP_GIC_DIST_BASE),
++		.length		= SZ_4K,
++		.type		= MT_DEVICE,
++	}, {
++		.virtual	= IO_ADDRESS(REALVIEW_EB11MP_L220_BASE),
++		.pfn		= __phys_to_pfn(REALVIEW_EB11MP_L220_BASE),
++		.length		= SZ_8K,
++		.type		= MT_DEVICE,
++	}
++};
++
+ static void __init realview_eb_map_io(void)
+ {
+ 	iotable_init(realview_eb_io_desc, ARRAY_SIZE(realview_eb_io_desc));
++	if (core_tile_eb11mp())
++		iotable_init(realview_eb11mp_io_desc, ARRAY_SIZE(realview_eb11mp_io_desc));
+ }
+ 
++/*
++ * RealView EB AMBA devices
++ */
++
++/*
++ * These devices are connected via the core APB bridge
++ */
++#define GPIO2_IRQ	{ IRQ_EB_GPIO2, NO_IRQ }
++#define GPIO2_DMA	{ 0, 0 }
++#define GPIO3_IRQ	{ IRQ_EB_GPIO3, NO_IRQ }
++#define GPIO3_DMA	{ 0, 0 }
++
++#define AACI_IRQ	{ IRQ_EB_AACI, NO_IRQ }
++#define AACI_DMA	{ 0x80, 0x81 }
++#define MMCI0_IRQ	{ IRQ_EB_MMCI0A, IRQ_EB_MMCI0B }
++#define MMCI0_DMA	{ 0x84, 0 }
++#define KMI0_IRQ	{ IRQ_EB_KMI0, NO_IRQ }
++#define KMI0_DMA	{ 0, 0 }
++#define KMI1_IRQ	{ IRQ_EB_KMI1, NO_IRQ }
++#define KMI1_DMA	{ 0, 0 }
++
++/*
++ * These devices are connected directly to the multi-layer AHB switch
++ */
++#define SMC_IRQ		{ NO_IRQ, NO_IRQ }
++#define SMC_DMA		{ 0, 0 }
++#define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
++#define MPMC_DMA	{ 0, 0 }
++#define CLCD_IRQ	{ IRQ_EB_CLCD, NO_IRQ }
++#define CLCD_DMA	{ 0, 0 }
++#define DMAC_IRQ	{ IRQ_EB_DMA, NO_IRQ }
++#define DMAC_DMA	{ 0, 0 }
++
++/*
++ * These devices are connected via the core APB bridge
++ */
++#define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
++#define SCTL_DMA	{ 0, 0 }
++#define WATCHDOG_IRQ	{ IRQ_EB_WDOG, NO_IRQ }
++#define WATCHDOG_DMA	{ 0, 0 }
++#define GPIO0_IRQ	{ IRQ_EB_GPIO0, NO_IRQ }
++#define GPIO0_DMA	{ 0, 0 }
++#define GPIO1_IRQ	{ IRQ_EB_GPIO1, NO_IRQ }
++#define GPIO1_DMA	{ 0, 0 }
++#define RTC_IRQ		{ IRQ_EB_RTC, NO_IRQ }
++#define RTC_DMA		{ 0, 0 }
++
++/*
++ * These devices are connected via the DMA APB bridge
++ */
++#define SCI_IRQ		{ IRQ_EB_SCI, NO_IRQ }
++#define SCI_DMA		{ 7, 6 }
++#define UART0_IRQ	{ IRQ_EB_UART0, NO_IRQ }
++#define UART0_DMA	{ 15, 14 }
++#define UART1_IRQ	{ IRQ_EB_UART1, NO_IRQ }
++#define UART1_DMA	{ 13, 12 }
++#define UART2_IRQ	{ IRQ_EB_UART2, NO_IRQ }
++#define UART2_DMA	{ 11, 10 }
++#define UART3_IRQ	{ IRQ_EB_UART3, NO_IRQ }
++#define UART3_DMA	{ 0x86, 0x87 }
++#define SSP_IRQ		{ IRQ_EB_SSP, NO_IRQ }
++#define SSP_DMA		{ 9, 8 }
++
+ /* FPGA Primecells */
+ AMBA_DEVICE(aaci,  "fpga:04", AACI,     NULL);
+ AMBA_DEVICE(mmc0,  "fpga:05", MMCI0,    &realview_mmc0_plat_data);
+@@ -153,38 +220,127 @@ static struct amba_device *amba_devs[] __initdata = {
+ 	&kmi1_device,
+ };
+ 
++/*
++ * RealView EB platform devices
++ */
++
++static struct resource realview_eb_smc91x_resources[] = {
++	[0] = {
++		.start		= REALVIEW_ETH_BASE,
++		.end		= REALVIEW_ETH_BASE + SZ_64K - 1,
++		.flags		= IORESOURCE_MEM,
++	},
++	[1] = {
++		.start		= IRQ_EB_ETH,
++		.end		= IRQ_EB_ETH,
++		.flags		= IORESOURCE_IRQ,
++	},
++};
++
++static struct platform_device realview_eb_smc91x_device = {
++	.name		= "smc91x",
++	.id		= 0,
++	.num_resources	= ARRAY_SIZE(realview_eb_smc91x_resources),
++	.resource	= realview_eb_smc91x_resources,
++};
++
+ static void __init gic_init_irq(void)
+ {
+-#ifdef CONFIG_REALVIEW_MPCORE
+-	unsigned int pldctrl;
+-	writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
+-	pldctrl = readl(__io_address(REALVIEW_SYS_BASE)	+ REALVIEW_MPCORE_SYS_PLD_CTRL1);
+-	pldctrl |= 0x00800000;	/* New irq mode */
+-	writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_MPCORE_SYS_PLD_CTRL1);
+-	writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
++	if (core_tile_eb11mp()) {
++		unsigned int pldctrl;
++
++		/* new irq mode */
++		writel(0x0000a05f, __io_address(REALVIEW_SYS_LOCK));
++		pldctrl = readl(__io_address(REALVIEW_SYS_BASE)	+ REALVIEW_EB11MP_SYS_PLD_CTRL1);
++		pldctrl |= 0x00800000;
++		writel(pldctrl, __io_address(REALVIEW_SYS_BASE) + REALVIEW_EB11MP_SYS_PLD_CTRL1);
++		writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
++
++		/* core tile GIC, primary */
++		gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
++		gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
++		gic_cpu_init(0, gic_cpu_base_addr);
++
++#ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
++		/* board GIC, secondary */
++		gic_dist_init(1, __io_address(REALVIEW_GIC_DIST_BASE), 64);
++		gic_cpu_init(1, __io_address(REALVIEW_GIC_CPU_BASE));
++		gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
+ #endif
+-	gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
+-	gic_cpu_init(0, __io_address(REALVIEW_GIC_CPU_BASE));
+-#if defined(CONFIG_REALVIEW_MPCORE) && !defined(CONFIG_REALVIEW_MPCORE_REVB)
+-	gic_dist_init(1, __io_address(REALVIEW_GIC1_DIST_BASE), 64);
+-	gic_cpu_init(1, __io_address(REALVIEW_GIC1_CPU_BASE));
+-	gic_cascade_irq(1, IRQ_EB_IRQ1);
++	} else {
++		/* board GIC, primary */
++		gic_cpu_base_addr = __io_address(REALVIEW_GIC_CPU_BASE);
++		gic_dist_init(0, __io_address(REALVIEW_GIC_DIST_BASE), 29);
++		gic_cpu_init(0, gic_cpu_base_addr);
++	}
++}
++
++/*
++ * Fix up the IRQ numbers for the RealView EB/ARM11MPCore tile
++ */
++static void realview_eb11mp_fixup(void)
++{
++	/* AMBA devices */
++	dmac_device.irq[0]	= IRQ_EB11MP_DMA;
++	uart0_device.irq[0]	= IRQ_EB11MP_UART0;
++	uart1_device.irq[0]	= IRQ_EB11MP_UART1;
++	uart2_device.irq[0]	= IRQ_EB11MP_UART2;
++	uart3_device.irq[0]	= IRQ_EB11MP_UART3;
++	clcd_device.irq[0]	= IRQ_EB11MP_CLCD;
++	wdog_device.irq[0]	= IRQ_EB11MP_WDOG;
++	gpio0_device.irq[0]	= IRQ_EB11MP_GPIO0;
++	gpio1_device.irq[0]	= IRQ_EB11MP_GPIO1;
++	gpio2_device.irq[0]	= IRQ_EB11MP_GPIO2;
++	rtc_device.irq[0]	= IRQ_EB11MP_RTC;
++	sci0_device.irq[0]	= IRQ_EB11MP_SCI;
++	ssp0_device.irq[0]	= IRQ_EB11MP_SSP;
++	aaci_device.irq[0]	= IRQ_EB11MP_AACI;
++	mmc0_device.irq[0]	= IRQ_EB11MP_MMCI0A;
++	mmc0_device.irq[1]	= IRQ_EB11MP_MMCI0B;
++	kmi0_device.irq[0]	= IRQ_EB11MP_KMI0;
++	kmi1_device.irq[0]	= IRQ_EB11MP_KMI1;
++
++	/* platform devices */
++	realview_eb_smc91x_resources[1].start	= IRQ_EB11MP_ETH;
++	realview_eb_smc91x_resources[1].end	= IRQ_EB11MP_ETH;
++}
++
++static void __init realview_eb_timer_init(void)
++{
++	unsigned int timer_irq;
++
++	if (core_tile_eb11mp()) {
++#ifdef CONFIG_LOCAL_TIMERS
++		twd_base_addr = __io_address(REALVIEW_EB11MP_TWD_BASE);
++		twd_size = REALVIEW_EB11MP_TWD_SIZE;
+ #endif
++		timer_irq = IRQ_EB11MP_TIMER0_1;
++	} else
++		timer_irq = IRQ_EB_TIMER0_1;
++
++	realview_timer_init(timer_irq);
+ }
+ 
++static struct sys_timer realview_eb_timer = {
++	.init		= realview_eb_timer_init,
++};
++
+ static void __init realview_eb_init(void)
+ {
+ 	int i;
  
+-#ifdef CONFIG_REALVIEW_MPCORE
+-	/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
+-	 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
+-	l2x0_init(__io_address(REALVIEW_MPCORE_L220_BASE), 0x00790000, 0xfe000fff);
+-#endif
++	if (core_tile_eb11mp()) {
++		realview_eb11mp_fixup();
++
++		/* 1MB (128KB/way), 8-way associativity, evmon/parity/share enabled
++		 * Bits:  .... ...0 0111 1001 0000 .... .... .... */
++		l2x0_init(__io_address(REALVIEW_EB11MP_L220_BASE), 0x00790000, 0xfe000fff);
++	}
++
+ 	clk_register(&realview_clcd_clk);
+ 
+ 	platform_device_register(&realview_flash_device);
+-	platform_device_register(&realview_smc91x_device);
++	platform_device_register(&realview_eb_smc91x_device);
+ 	platform_device_register(&realview_i2c_device);
+ 
+ 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
+@@ -204,6 +360,6 @@ MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
+ 	.boot_params	= 0x00000100,
+ 	.map_io		= realview_eb_map_io,
+ 	.init_irq	= gic_init_irq,
+-	.timer		= &realview_timer,
++	.timer		= &realview_eb_timer,
+ 	.init_machine	= realview_eb_init,
+ MACHINE_END
 diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
 index 587864f..6617547 100644
 --- a/arch/arm/mach-s3c2410/mach-bast.c
@@ -46396,6 +58470,32 @@
  };
  
  static struct sys_device s3c2443_sysdev = {
+diff --git a/arch/arm/mach-sa1100/collie_pm.c b/arch/arm/mach-sa1100/collie_pm.c
+index 1e25b1d..94620be 100644
+--- a/arch/arm/mach-sa1100/collie_pm.c
++++ b/arch/arm/mach-sa1100/collie_pm.c
+@@ -165,7 +165,7 @@ int collie_read_temp(void)
+ 
+ 	ucb1x00_adc_enable(ucb);
+ 	ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
+-	/* >1010 = battery removed, 460 = 22C ?, higer = lower temp ? */
++	/* >1010 = battery removed, 460 = 22C ?, higher = lower temp ? */
+ 	voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_SYNC);
+ 	ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
+ 	ucb1x00_adc_disable(ucb);
+diff --git a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c
+index 9e13c83..5c84c60 100644
+--- a/arch/arm/mach-sa1100/generic.c
++++ b/arch/arm/mach-sa1100/generic.c
+@@ -470,7 +470,7 @@ void __init sa1110_mb_disable(void)
+  * If the system is going to use the SA-1111 DMA engines, set up
+  * the memory bus request/grant pins.
+  */
+-void __init sa1110_mb_enable(void)
++void __devinit sa1110_mb_enable(void)
+ {
+ 	unsigned long flags;
+ 
 diff --git a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c
 index edf3347..3dc17d7 100644
 --- a/arch/arm/mach-sa1100/irq.c
@@ -46682,6 +58782,51 @@
  do_translation_fault(unsigned long addr, unsigned int fsr,
  		     struct pt_regs *regs)
  {
+diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
+index 7595277..303a7ff 100644
+--- a/arch/arm/mm/ioremap.c
++++ b/arch/arm/mm/ioremap.c
+@@ -162,7 +162,7 @@ static void unmap_area_sections(unsigned long virt, unsigned long size)
+ 			 * Free the page table, if there was one.
+ 			 */
+ 			if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
+-				pte_free_kernel(pmd_page_vaddr(pmd));
++				pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
+ 		}
+ 
+ 		addr += PGDIR_SIZE;
+diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
+index 50b9aed..500c961 100644
+--- a/arch/arm/mm/pgd.c
++++ b/arch/arm/mm/pgd.c
+@@ -65,14 +65,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
+ 	return new_pgd;
+ 
+ no_pte:
+-	pmd_free(new_pmd);
++	pmd_free(mm, new_pmd);
+ no_pmd:
+ 	free_pages((unsigned long)new_pgd, 2);
+ no_pgd:
+ 	return NULL;
+ }
+ 
+-void free_pgd_slow(pgd_t *pgd)
++void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	pmd_t *pmd;
+ 	struct page *pte;
+@@ -94,8 +94,8 @@ void free_pgd_slow(pgd_t *pgd)
+ 	pmd_clear(pmd);
+ 	dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
+ 	pte_lock_deinit(pte);
+-	pte_free(pte);
+-	pmd_free(pmd);
++	pte_free(mm, pte);
++	pmd_free(mm, pmd);
+ free:
+ 	free_pages((unsigned long) pgd, 2);
+ }
 diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S
 new file mode 100644
 index 0000000..fa0dc7e
@@ -47207,6 +59352,28 @@
  	.resume		= op_arm_resume,
  	.suspend	= op_arm_suspend,
  };
+diff --git a/arch/arm/plat-iop/time.c b/arch/arm/plat-iop/time.c
+index ba3d21d..6fe481f 100644
+--- a/arch/arm/plat-iop/time.c
++++ b/arch/arm/plat-iop/time.c
+@@ -57,8 +57,6 @@ unsigned long iop_gettimeoffset(void)
+ static irqreturn_t
+ iop_timer_interrupt(int irq, void *dev_id)
+ {
+-	write_seqlock(&xtime_lock);
+-
+ 	write_tisr(1);
+ 
+ 	while ((signed long)(next_jiffy_time - read_tcr1())
+@@ -67,8 +65,6 @@ iop_timer_interrupt(int irq, void *dev_id)
+ 		next_jiffy_time -= ticks_per_jiffy;
+ 	}
+ 
+-	write_sequnlock(&xtime_lock);
+-
+ 	return IRQ_HANDLED;
+ }
+ 
 diff --git a/arch/arm/plat-omap/debug-devices.c b/arch/arm/plat-omap/debug-devices.c
 index 83a5f8b..f455233 100644
 --- a/arch/arm/plat-omap/debug-devices.c
@@ -47586,9 +59753,18 @@
 +
 +EXPORT_SYMBOL(s3c2410_gpio_irq2pin);
 diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
-index 8fbc884..d486f51 100644
+index 8fbc884..ae2c5d7 100644
 --- a/arch/arm/plat-s3c24xx/irq.c
 +++ b/arch/arm/plat-s3c24xx/irq.c
+@@ -47,7 +47,7 @@
+  *		  Mark IRQ_LCD valid
+  *
+  *   25-Jul-2005  Ben Dooks
+- *		  Split the S3C2440 IRQ code to seperate file
++ *		  Split the S3C2440 IRQ code to separate file
+ */
+ 
+ #include <linux/init.h>
 @@ -187,7 +187,7 @@ struct irq_chip s3c_irq_level_chip = {
  	.set_wake	= s3c_irq_wake
  };
@@ -48042,6 +60218,20 @@
  	.suspend	= s3c244x_suspend,
  	.resume		= s3c244x_resume
  };
+diff --git a/arch/arm/plat-s3c24xx/time.c b/arch/arm/plat-s3c24xx/time.c
+index 2ec1daa..766473b 100644
+--- a/arch/arm/plat-s3c24xx/time.c
++++ b/arch/arm/plat-s3c24xx/time.c
+@@ -130,9 +130,7 @@ static unsigned long s3c2410_gettimeoffset (void)
+ static irqreturn_t
+ s3c2410_timer_interrupt(int irq, void *dev_id)
+ {
+-	write_seqlock(&xtime_lock);
+ 	timer_tick();
+-	write_sequnlock(&xtime_lock);
+ 	return IRQ_HANDLED;
+ }
+ 
 diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
 index 0a9a5e7..7ed58c0 100644
 --- a/arch/arm/tools/mach-types
@@ -48706,22 +60896,23 @@
  	} else {
  		smp_call_function(vfp_enable, NULL, 1, 1);
 diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
-index b77abce..e34e2c9 100644
+index b77abce..28e0caf 100644
 --- a/arch/avr32/Kconfig
 +++ b/arch/avr32/Kconfig
-@@ -54,6 +54,9 @@ config ARCH_HAS_ILOG2_U32
- config ARCH_HAS_ILOG2_U64
- 	def_bool n
- 
-+config ARCH_SUPPORTS_OPROFILE
-+	def_bool y
-+
- config GENERIC_HWEIGHT
- 	def_bool y
- 
-@@ -81,19 +84,23 @@ config PLATFORM_AT32AP
+@@ -10,6 +10,8 @@ config AVR32
+ 	# With EMBEDDED=n, we get lots of stuff automatically selected
+ 	# that we usually don't need on AVR32.
+ 	select EMBEDDED
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
+ 	help
+ 	  AVR32 is a high-performance 32-bit RISC microprocessor core,
+ 	  designed for cost-sensitive embedded applications, with particular
+@@ -80,20 +82,25 @@ config PLATFORM_AT32AP
+ 	select SUBARCH_AVR32B
  	select MMU
  	select PERFORMANCE_COUNTERS
++	select HAVE_GPIO_LIB
  
 -choice
 -	prompt "AVR32 CPU type"
@@ -48801,15 +60992,6 @@
  # FPU emulation goes here
  
  source "kernel/Kconfig.hz"
-@@ -219,6 +236,8 @@ source "drivers/Kconfig"
- 
- source "fs/Kconfig"
- 
-+source "kernel/Kconfig.instrumentation"
-+
- source "arch/avr32/Kconfig.debug"
- 
- source "security/Kconfig"
 diff --git a/arch/avr32/Kconfig.debug b/arch/avr32/Kconfig.debug
 index 64ace00..2283933 100644
 --- a/arch/avr32/Kconfig.debug
@@ -53796,6 +65978,18 @@
  	if (syscall) {
  		switch (regs->r12) {
  		case -ERESTART_RESTARTBLOCK:
+diff --git a/arch/avr32/kernel/syscall_table.S b/arch/avr32/kernel/syscall_table.S
+index 75c81f2..478bda4 100644
+--- a/arch/avr32/kernel/syscall_table.S
++++ b/arch/avr32/kernel/syscall_table.S
+@@ -293,6 +293,6 @@ sys_call_table:
+ 	.long	sys_shmctl
+ 	.long	sys_utimensat
+ 	.long	sys_signalfd
+-	.long	sys_timerfd		/* 280 */
++	.long	sys_ni_syscall		/* 280, was sys_timerfd */
+ 	.long	sys_eventfd
+ 	.long	sys_ni_syscall		/* r8 is saturated at nr_syscalls */
 diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
 index 7014a35..36a46c3 100644
 --- a/arch/avr32/kernel/time.c
@@ -57539,6 +69733,279 @@
  	dev_info(&pdev->dev,
  		 "External Interrupt Controller at 0x%p, IRQ %u\n",
  		 eic->regs, int_irq);
+diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c
+index d61a02d..38a8fa3 100644
+--- a/arch/avr32/mach-at32ap/pio.c
++++ b/arch/avr32/mach-at32ap/pio.c
+@@ -24,11 +24,11 @@
+ #define MAX_NR_PIO_DEVICES		8
+ 
+ struct pio_device {
++	struct gpio_chip chip;
+ 	void __iomem *regs;
+ 	const struct platform_device *pdev;
+ 	struct clk *clk;
+ 	u32 pinmux_mask;
+-	u32 gpio_mask;
+ 	char name[8];
+ };
+ 
+@@ -64,7 +64,8 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
+ 		goto fail;
+ 	}
+ 
+-	if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask))) {
++	if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask)
++			 || gpiochip_is_requested(&pio->chip, pin_index))) {
+ 		printk("%s: pin %u is busy\n", pio->name, pin_index);
+ 		goto fail;
+ 	}
+@@ -79,9 +80,6 @@ void __init at32_select_periph(unsigned int pin, unsigned int periph,
+ 	if (!(flags & AT32_GPIOF_PULLUP))
+ 		pio_writel(pio, PUDR, mask);
+ 
+-	/* gpio_request NOT allowed */
+-	set_bit(pin_index, &pio->gpio_mask);
+-
+ 	return;
+ 
+ fail:
+@@ -130,9 +128,6 @@ void __init at32_select_gpio(unsigned int pin, unsigned long flags)
+ 
+ 	pio_writel(pio, PER, mask);
+ 
+-	/* gpio_request now allowed */
+-	clear_bit(pin_index, &pio->gpio_mask);
+-
+ 	return;
+ 
+ fail:
+@@ -166,96 +161,50 @@ fail:
+ 
+ /* GPIO API */
+ 
+-int gpio_request(unsigned int gpio, const char *label)
++static int direction_input(struct gpio_chip *chip, unsigned offset)
+ {
+-	struct pio_device *pio;
+-	unsigned int pin;
+-
+-	pio = gpio_to_pio(gpio);
+-	if (!pio)
+-		return -ENODEV;
++	struct pio_device *pio = container_of(chip, struct pio_device, chip);
++	u32 mask = 1 << offset;
+ 
+-	pin = gpio & 0x1f;
+-	if (test_and_set_bit(pin, &pio->gpio_mask))
+-		return -EBUSY;
++	if (!(pio_readl(pio, PSR) & mask))
++		return -EINVAL;
+ 
++	pio_writel(pio, ODR, mask);
+ 	return 0;
+ }
+-EXPORT_SYMBOL(gpio_request);
+ 
+-void gpio_free(unsigned int gpio)
++static int gpio_get(struct gpio_chip *chip, unsigned offset)
+ {
+-	struct pio_device *pio;
+-	unsigned int pin;
++	struct pio_device *pio = container_of(chip, struct pio_device, chip);
+ 
+-	pio = gpio_to_pio(gpio);
+-	if (!pio) {
+-		printk(KERN_ERR
+-		       "gpio: attempted to free invalid pin %u\n", gpio);
+-		return;
+-	}
+-
+-	pin = gpio & 0x1f;
+-	if (!test_and_clear_bit(pin, &pio->gpio_mask))
+-		printk(KERN_ERR "gpio: freeing free or non-gpio pin %s-%u\n",
+-		       pio->name, pin);
++	return (pio_readl(pio, PDSR) >> offset) & 1;
+ }
+-EXPORT_SYMBOL(gpio_free);
+ 
+-int gpio_direction_input(unsigned int gpio)
+-{
+-	struct pio_device *pio;
+-	unsigned int pin;
+-
+-	pio = gpio_to_pio(gpio);
+-	if (!pio)
+-		return -ENODEV;
+-
+-	pin = gpio & 0x1f;
+-	pio_writel(pio, ODR, 1 << pin);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(gpio_direction_input);
++static void gpio_set(struct gpio_chip *chip, unsigned offset, int value);
+ 
+-int gpio_direction_output(unsigned int gpio, int value)
++static int direction_output(struct gpio_chip *chip, unsigned offset, int value)
+ {
+-	struct pio_device *pio;
+-	unsigned int pin;
+-
+-	pio = gpio_to_pio(gpio);
+-	if (!pio)
+-		return -ENODEV;
++	struct pio_device *pio = container_of(chip, struct pio_device, chip);
++	u32 mask = 1 << offset;
+ 
+-	gpio_set_value(gpio, value);
+-
+-	pin = gpio & 0x1f;
+-	pio_writel(pio, OER, 1 << pin);
++	if (!(pio_readl(pio, PSR) & mask))
++		return -EINVAL;
+ 
++	gpio_set(chip, offset, value);
++	pio_writel(pio, OER, mask);
+ 	return 0;
+ }
+-EXPORT_SYMBOL(gpio_direction_output);
+ 
+-int gpio_get_value(unsigned int gpio)
++static void gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+ {
+-	struct pio_device *pio = &pio_dev[gpio >> 5];
++	struct pio_device *pio = container_of(chip, struct pio_device, chip);
++	u32 mask = 1 << offset;
+ 
+-	return (pio_readl(pio, PDSR) >> (gpio & 0x1f)) & 1;
+-}
+-EXPORT_SYMBOL(gpio_get_value);
+-
+-void gpio_set_value(unsigned int gpio, int value)
+-{
+-	struct pio_device *pio = &pio_dev[gpio >> 5];
+-	u32 mask;
+-
+-	mask = 1 << (gpio & 0x1f);
+ 	if (value)
+ 		pio_writel(pio, SODR, mask);
+ 	else
+ 		pio_writel(pio, CODR, mask);
+ }
+-EXPORT_SYMBOL(gpio_set_value);
+ 
+ /*--------------------------------------------------------------------------*/
+ 
+@@ -339,6 +288,63 @@ gpio_irq_setup(struct pio_device *pio, int irq, int gpio_irq)
+ 
+ /*--------------------------------------------------------------------------*/
+ 
++#ifdef CONFIG_DEBUG_FS
++
++#include <linux/seq_file.h>
++
++/*
++ * This shows more info than the generic gpio dump code:
++ * pullups, deglitching, open drain drive.
++ */
++static void pio_bank_show(struct seq_file *s, struct gpio_chip *chip)
++{
++	struct pio_device *pio = container_of(chip, struct pio_device, chip);
++	u32			psr, osr, imr, pdsr, pusr, ifsr, mdsr;
++	unsigned		i;
++	u32			mask;
++	char			bank;
++
++	psr = pio_readl(pio, PSR);
++	osr = pio_readl(pio, OSR);
++	imr = pio_readl(pio, IMR);
++	pdsr = pio_readl(pio, PDSR);
++	pusr = pio_readl(pio, PUSR);
++	ifsr = pio_readl(pio, IFSR);
++	mdsr = pio_readl(pio, MDSR);
++
++	bank = 'A' + pio->pdev->id;
++
++	for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
++		const char *label;
++
++		label = gpiochip_is_requested(chip, i);
++		if (!label)
++			continue;
++
++		seq_printf(s, " gpio-%-3d P%c%-2d (%-12s) %s %s %s",
++			chip->base + i, bank, i,
++			label,
++			(osr & mask) ? "out" : "in ",
++			(mask & pdsr) ? "hi" : "lo",
++			(mask & pusr) ? "  " : "up");
++		if (ifsr & mask)
++			seq_printf(s, " deglitch");
++		if ((osr & mdsr) & mask)
++			seq_printf(s, " open-drain");
++		if (imr & mask)
++			seq_printf(s, " irq-%d edge-both",
++				gpio_to_irq(chip->base + i));
++		seq_printf(s, "\n");
++	}
++}
++
++#else
++#define pio_bank_show	NULL
++#endif
++
++
++/*--------------------------------------------------------------------------*/
++
+ static int __init pio_probe(struct platform_device *pdev)
+ {
+ 	struct pio_device *pio = NULL;
+@@ -349,6 +355,18 @@ static int __init pio_probe(struct platform_device *pdev)
+ 	pio = &pio_dev[pdev->id];
+ 	BUG_ON(!pio->regs);
+ 
++	pio->chip.label = pio->name;
++	pio->chip.base = pdev->id * 32;
++	pio->chip.ngpio = 32;
++
++	pio->chip.direction_input = direction_input;
++	pio->chip.get = gpio_get;
++	pio->chip.direction_output = direction_output;
++	pio->chip.set = gpio_set;
++	pio->chip.dbg_show = pio_bank_show;
++
++	gpiochip_add(&pio->chip);
++
+ 	gpio_irq_setup(pio, irq, gpio_irq_base);
+ 
+ 	platform_set_drvdata(pdev, pio);
+@@ -406,12 +424,6 @@ void __init at32_init_pio(struct platform_device *pdev)
+ 	pio->pdev = pdev;
+ 	pio->regs = ioremap(regs->start, regs->end - regs->start + 1);
+ 
+-	/*
+-	 * request_gpio() is only valid for pins that have been
+-	 * explicitly configured as GPIO and not previously requested
+-	 */
+-	pio->gpio_mask = ~0UL;
+-
+ 	/* start with irqs disabled and acked */
+ 	pio_writel(pio, IDR, ~0UL);
+ 	(void) pio_readl(pio, ISR);
+diff --git a/arch/avr32/mach-at32ap/pio.h b/arch/avr32/mach-at32ap/pio.h
+index 50fa3ac..7795116 100644
+--- a/arch/avr32/mach-at32ap/pio.h
++++ b/arch/avr32/mach-at32ap/pio.h
+@@ -19,7 +19,7 @@
+ #define PIO_OSR                                0x0018
+ #define PIO_IFER                               0x0020
+ #define PIO_IFDR                               0x0024
+-#define PIO_ISFR                               0x0028
++#define PIO_IFSR                               0x0028
+ #define PIO_SODR                               0x0030
+ #define PIO_CODR                               0x0034
+ #define PIO_ODSR                               0x0038
 diff --git a/arch/avr32/mm/dma-coherent.c b/arch/avr32/mm/dma-coherent.c
 index 177fea8..6d8c794 100644
 --- a/arch/avr32/mm/dma-coherent.c
@@ -57826,10 +70293,18 @@
 +
 +}
 diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig
-index 25232ba..4802eb7 100644
+index 25232ba..ba21e33 100644
 --- a/arch/blackfin/Kconfig
 +++ b/arch/blackfin/Kconfig
-@@ -85,11 +85,26 @@ config BF522
+@@ -24,6 +24,7 @@ config RWSEM_XCHGADD_ALGORITHM
+ config BLACKFIN
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
+ 
+ config ZONE_DMA
+ 	bool
+@@ -85,11 +86,26 @@ config BF522
  	help
  	  BF522 Processor Support.
  
@@ -57856,7 +70331,7 @@
  config BF527
  	bool "BF527"
  	help
-@@ -198,7 +213,7 @@ endchoice
+@@ -198,7 +214,7 @@ endchoice
  
  config BF52x
  	bool
@@ -57865,7 +70340,7 @@
  	default y
  
  config BF53x
-@@ -253,11 +268,6 @@ config MEM_MT48LC32M16A2TG_75
+@@ -253,11 +269,6 @@ config MEM_MT48LC32M16A2TG_75
  	depends on (BFIN527_EZKIT)
  	default y
  
@@ -57877,7 +70352,7 @@
  source "arch/blackfin/mach-bf527/Kconfig"
  source "arch/blackfin/mach-bf533/Kconfig"
  source "arch/blackfin/mach-bf561/Kconfig"
-@@ -317,7 +327,7 @@ config VCO_MULT
+@@ -317,7 +328,7 @@ config VCO_MULT
  	range 1 64
  	default "22" if BFIN533_EZKIT
  	default "45" if BFIN533_STAMP
@@ -57886,7 +70361,7 @@
  	default "22" if BFIN533_BLUETECHNIX_CM
  	default "20" if BFIN537_BLUETECHNIX_CM
  	default "20" if BFIN561_BLUETECHNIX_CM
-@@ -354,7 +364,7 @@ config SCLK_DIV
+@@ -354,7 +365,7 @@ config SCLK_DIV
  	range 1 15
  	default 5 if BFIN533_EZKIT
  	default 5 if BFIN533_STAMP
@@ -57895,7 +70370,7 @@
  	default 5 if BFIN533_BLUETECHNIX_CM
  	default 4 if BFIN537_BLUETECHNIX_CM
  	default 4 if BFIN561_BLUETECHNIX_CM
-@@ -371,7 +381,10 @@ config SCLK_DIV
+@@ -371,7 +382,10 @@ config SCLK_DIV
  config MAX_VCO_HZ
  	int
  	default 600000000 if BF522
@@ -57906,7 +70381,7 @@
  	default 600000000 if BF527
  	default 400000000 if BF531
  	default 400000000 if BF532
-@@ -383,6 +396,8 @@ config MAX_VCO_HZ
+@@ -383,6 +397,8 @@ config MAX_VCO_HZ
  	default 533333333 if BF539
  	default 600000000 if BF542
  	default 533333333 if BF544
@@ -57915,7 +70390,7 @@
  	default 533333333 if BF549
  	default 600000000 if BF561
  
-@@ -409,6 +424,7 @@ config MEM_SIZE
+@@ -409,6 +425,7 @@ config MEM_SIZE
  	default  32 if BFIN533_EZKIT
  	default  64 if BFIN527_EZKIT
  	default  64 if BFIN537_STAMP
@@ -57923,7 +70398,7 @@
  	default  64 if BFIN561_EZKIT
  	default 128 if BFIN533_STAMP
  	default  64 if PNAV10
-@@ -416,6 +432,7 @@ config MEM_SIZE
+@@ -416,6 +433,7 @@ config MEM_SIZE
  
  config MEM_ADD_WIDTH
  	int "SDRAM Memory Address Width"
@@ -57931,7 +70406,7 @@
  	default  9 if BFIN533_EZKIT
  	default  9 if BFIN561_EZKIT
  	default  9 if H8606_HVSISTEMAS
-@@ -424,6 +441,19 @@ config MEM_ADD_WIDTH
+@@ -424,6 +442,19 @@ config MEM_ADD_WIDTH
  	default 11 if BFIN533_STAMP
  	default 10 if PNAV10
  
@@ -57951,7 +70426,7 @@
  config ENET_FLASH_PIN
  	int "PF port/pin used for flash and ethernet sharing"
  	depends on (BFIN533_STAMP)
-@@ -448,40 +478,6 @@ config BOOT_LOAD
+@@ -448,40 +479,6 @@ config BOOT_LOAD
  	  memory region is used to capture NULL pointer references as well
  	  as some core kernel functions.
  
@@ -57992,7 +70467,7 @@
  choice
  	prompt "Blackfin Exception Scratch Register"
  	default BFIN_SCRATCH_REG_RETN
-@@ -528,41 +524,6 @@ config BFIN_SCRATCH_REG_CYCLES
+@@ -528,41 +525,6 @@ config BFIN_SCRATCH_REG_CYCLES
  
  endchoice
  
@@ -58034,7 +70509,7 @@
  endmenu
  
  
-@@ -799,6 +760,15 @@ config L1_MAX_PIECE
+@@ -799,6 +761,15 @@ config L1_MAX_PIECE
  	  Set the max memory pieces for the L1 SRAM allocation algorithm.
  	  Min value is 16. Max value is 1024.
  
@@ -58050,7 +70525,7 @@
  comment "Asynchonous Memory Configuration"
  
  menu "EBIU_AMGCTL Global Control"
-@@ -808,7 +778,6 @@ config C_AMCKEN
+@@ -808,7 +779,6 @@ config C_AMCKEN
  
  config C_CDPRIO
  	bool "DMA has priority over core for ext. accesses"
@@ -58058,7 +70533,7 @@
  	default n
  
  config C_B0PEN
-@@ -929,6 +898,10 @@ endmenu
+@@ -929,6 +899,10 @@ endmenu
  menu "Power management options"
  source "kernel/power/Kconfig"
  
@@ -58069,7 +70544,7 @@
  choice
  	prompt "Select PM Wakeup Event Source"
  	default PM_WAKEUP_GPIO_BY_SIC_IWR
-@@ -949,8 +922,10 @@ endchoice
+@@ -949,8 +923,10 @@ endchoice
  config PM_WAKEUP_SIC_IWR
  	hex "Wakeup Events (SIC_IWR)"
  	depends on PM_WAKEUP_GPIO_BY_SIC_IWR
@@ -58082,6 +70557,15 @@
  
  config PM_WAKEUP_GPIO_NUMBER
  	int "Wakeup GPIO number"
+@@ -998,8 +974,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/blackfin/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/blackfin/Makefile b/arch/blackfin/Makefile
 index c47e000..0edc402 100644
 --- a/arch/blackfin/Makefile
@@ -65635,7 +78119,7 @@
  	SSYNC;
  	RTS;
 diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
-index dc9d3ee..56ff51b 100644
+index dc9d3ee..fdd9bf4 100644
 --- a/arch/blackfin/mach-common/entry.S
 +++ b/arch/blackfin/mach-common/entry.S
 @@ -95,6 +95,9 @@ ENTRY(_ex_workaround_261)
@@ -65702,6 +78186,15 @@
  	r0 = r2 & r0;
  	cc = r0 == 0;
  	if !cc jump 4f;	/* if not return to user mode, get out */
+@@ -1356,7 +1373,7 @@ ENTRY(_sys_call_table)
+ 	.long _sys_epoll_pwait
+ 	.long _sys_utimensat
+ 	.long _sys_signalfd
+-	.long _sys_timerfd
++	.long _sys_ni_syscall
+ 	.long _sys_eventfd	/* 350 */
+ 	.long _sys_pread64
+ 	.long _sys_pwrite64
 @@ -1364,6 +1381,7 @@ ENTRY(_sys_call_table)
  	.long _sys_set_robust_list
  	.long _sys_get_robust_list	/* 355 */
@@ -66224,6 +78717,83 @@
  	free_init_pages("unused kernel memory",
  			(unsigned long)(&__init_begin),
  			(unsigned long)(&__init_end));
+diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
+index 222da15..27b082a 100644
+--- a/arch/cris/Kconfig
++++ b/arch/cris/Kconfig
+@@ -150,6 +150,7 @@ config ETRAX_FLASH_BUSWIDTH
+ 	  Width in bytes of the Flash bus (1, 2 or 4). Is usually 2.
+ 
+ source arch/cris/arch-v10/Kconfig
++source arch/cris/arch-v32/Kconfig
+ 
+ endmenu
+ 
+@@ -157,8 +158,8 @@ source "net/Kconfig"
+ 
+ # bring in ETRAX built-in drivers
+ menu "Drivers for built-in interfaces"
+-# arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
+-source arch/cris/arch/drivers/Kconfig
++source arch/cris/arch-v10/drivers/Kconfig
++source arch/cris/arch-v32/drivers/Kconfig
+ 
+ endmenu
+ 
+@@ -213,8 +214,6 @@ source "drivers/pci/Kconfig"
+ 
+ source "drivers/usb/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/cris/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/cris/arch-v10/Kconfig b/arch/cris/arch-v10/Kconfig
+index f1ce6f6..1d61fae 100644
+--- a/arch/cris/arch-v10/Kconfig
++++ b/arch/cris/arch-v10/Kconfig
+@@ -1,3 +1,5 @@
++if ETRAX_ARCH_V10
++
+ # ETRAX 100LX v1 has a MMU "feature" requiring a low mapping
+ config CRIS_LOW_MAP
+ 	bool
+@@ -451,3 +453,5 @@ config ETRAX_POWERBUTTON_BIT
+ 	default "25"
+ 	help
+ 	  Configure where power button is connected.
++
++endif
+diff --git a/arch/cris/arch-v10/drivers/Kconfig b/arch/cris/arch-v10/drivers/Kconfig
+index e3c0f29..96740ef 100644
+--- a/arch/cris/arch-v10/drivers/Kconfig
++++ b/arch/cris/arch-v10/drivers/Kconfig
+@@ -1,3 +1,5 @@
++if ETRAX_ARCH_V10
++
+ config ETRAX_ETHERNET
+ 	bool "Ethernet support"
+ 	depends on ETRAX_ARCH_V10
+@@ -806,3 +808,5 @@ config ETRAX_DS1302_TRICKLE_CHARGE
+ 	  1 = 2kohm, 2 = 4kohm, 3 = 4kohm
+ 	  4 = 1 diode, 8 = 2 diodes
+ 	  Allowed values are (increasing current): 0, 11, 10, 9, 7, 6, 5
++
++endif
+diff --git a/arch/cris/arch-v10/kernel/entry.S b/arch/cris/arch-v10/kernel/entry.S
+index ec62c95..d1361dc 100644
+--- a/arch/cris/arch-v10/kernel/entry.S
++++ b/arch/cris/arch-v10/kernel/entry.S
+@@ -1167,7 +1167,7 @@ sys_call_table:
+ 	.long sys_epoll_pwait
+ 	.long sys_utimensat		/* 320 */
+ 	.long sys_signalfd
+-	.long sys_timerfd
++	.long sys_ni_syscall
+ 	.long sys_eventfd
+ 	.long sys_fallocate
+ 
 diff --git a/arch/cris/arch-v10/vmlinux.lds.S b/arch/cris/arch-v10/vmlinux.lds.S
 index 97a7876..93c9f0e 100644
 --- a/arch/cris/arch-v10/vmlinux.lds.S
@@ -66252,6 +78822,22 @@
  		*(.exitcall.exit)
          }
  
+diff --git a/arch/cris/arch-v32/Kconfig b/arch/cris/arch-v32/Kconfig
+index 4f79d8e..d8acaa9 100644
+--- a/arch/cris/arch-v32/Kconfig
++++ b/arch/cris/arch-v32/Kconfig
+@@ -1,3 +1,5 @@
++if ETRAX_ARCH_V32
++
+ config ETRAX_DRAM_VIRTUAL_BASE
+ 	hex
+ 	depends on ETRAX_ARCH_V32
+@@ -294,3 +296,5 @@ config ETRAX_DEF_GIO_PE_OUT
+ 	help
+ 	  Configures the initial data for the general port E bits.  Most
+ 	  products should use 00000 here.
++
++endif
 diff --git a/arch/cris/arch-v32/boot/compressed/Makefile b/arch/cris/arch-v32/boot/compressed/Makefile
 index 9f77eda..609692f 100644
 --- a/arch/cris/arch-v32/boot/compressed/Makefile
@@ -66265,6 +78851,22 @@
  CFLAGS = -O2
  LD = gcc-cris -mlinux -march=v32 -nostdlib
  OBJCOPY = objcopy-cris
+diff --git a/arch/cris/arch-v32/drivers/Kconfig b/arch/cris/arch-v32/drivers/Kconfig
+index 9bccb5e..c329cce 100644
+--- a/arch/cris/arch-v32/drivers/Kconfig
++++ b/arch/cris/arch-v32/drivers/Kconfig
+@@ -1,3 +1,5 @@
++if ETRAX_ARCH_V32
++
+ config ETRAX_ETHERNET
+ 	bool "Ethernet support"
+ 	depends on ETRAX_ARCH_V32
+@@ -610,3 +612,5 @@ config ETRAX_STREAMCOPROC
+ 	help
+ 	  This option enables a driver for the stream co-processor
+ 	  for cryptographic operations.
++
++endif
 diff --git a/arch/cris/arch-v32/drivers/iop_fw_load.c b/arch/cris/arch-v32/drivers/iop_fw_load.c
 index 11f9895..f4bdc1d 100644
 --- a/arch/cris/arch-v32/drivers/iop_fw_load.c
@@ -66301,6 +78903,28 @@
  	return 0;
  }
  
+diff --git a/arch/cris/arch-v32/drivers/pci/dma.c b/arch/cris/arch-v32/drivers/pci/dma.c
+index 66f9500..e036465 100644
+--- a/arch/cris/arch-v32/drivers/pci/dma.c
++++ b/arch/cris/arch-v32/drivers/pci/dma.c
+@@ -93,7 +93,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+ 
+ 	dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
+ 	if (!dev->dma_mem)
+-		goto out;
++		goto iounmap_out;
+ 	dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ 	if (!dev->dma_mem->bitmap)
+ 		goto free1_out;
+@@ -110,6 +110,8 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
+ 
+  free1_out:
+ 	kfree(dev->dma_mem);
++ iounmap_out:
++	iounmap(mem_base);
+  out:
+ 	return 0;
+ }
 diff --git a/arch/cris/arch-v32/vmlinux.lds.S b/arch/cris/arch-v32/vmlinux.lds.S
 index b076c13..fead8c5 100644
 --- a/arch/cris/arch-v32/vmlinux.lds.S
@@ -66330,10 +78954,35 @@
          }
  
 diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
-index 43153e7..e3f965c 100644
+index 43153e7..96f7d70 100644
 --- a/arch/frv/Kconfig
 +++ b/arch/frv/Kconfig
-@@ -322,11 +322,6 @@ config PCI
+@@ -79,7 +79,7 @@ config FRV_OUTOFLINE_ATOMIC_OPS
+ 	  Setting this option causes the FR-V atomic operations to be mostly
+ 	  implemented out-of-line.
+ 
+-	  See Documentation/fujitsu/frv/atomic-ops.txt for more information.
++	  See Documentation/frv/atomic-ops.txt for more information.
+ 
+ config HIGHMEM
+ 	bool "High memory support"
+@@ -138,6 +138,15 @@ config UCPAGE_OFFSET_C0000000
+ 
+ endchoice
+ 
++config PAGE_OFFSET
++	hex
++	default 0x20000000 if UCPAGE_OFFSET_20000000
++	default 0x40000000 if UCPAGE_OFFSET_40000000
++	default 0x60000000 if UCPAGE_OFFSET_60000000
++	default 0x80000000 if UCPAGE_OFFSET_80000000
++	default 0xA0000000 if UCPAGE_OFFSET_A0000000
++	default 0xC0000000
++
+ config PROTECT_KERNEL
+ 	bool "Protect core kernel against userspace"
+ 	depends on !MMU
+@@ -322,11 +331,6 @@ config PCI
  	  onboard. If you have one of these boards and you wish to use the PCI
  	  facilities, say Y here.
  
@@ -66345,7 +78994,7 @@
  config RESERVE_DMA_COHERENT
  	bool "Reserve DMA coherent memory"
  	depends on PCI && !MMU
-@@ -357,6 +352,11 @@ source "drivers/pcmcia/Kconfig"
+@@ -357,6 +361,11 @@ source "drivers/pcmcia/Kconfig"
  #	  should probably wait a while.
  
  menu "Power management options"
@@ -66357,6 +79006,15 @@
  source kernel/power/Kconfig
  endmenu
  
+@@ -375,8 +384,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/frv/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile
 index dc6f038..6ae3254 100644
 --- a/arch/frv/boot/Makefile
@@ -66392,6 +79050,37 @@
  
  #
  # miscellany
+diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S
+index f926c70..ca6a345 100644
+--- a/arch/frv/kernel/entry.S
++++ b/arch/frv/kernel/entry.S
+@@ -253,7 +253,7 @@ __entry_kernel_external_interrupt_reentry:
+ 	andi.p		gr5,#~PSR_ET,gr5
+ 
+ 	# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
+-	# - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
++	# - for an explanation of how it works, see: Documentation/frv/atomic-ops.txt
+ 	andi		gr25,#~0xc0,gr25
+ 
+ 	sti		gr20,@(gr28,#REG_TBR)
+@@ -445,7 +445,7 @@ __entry_kernel_softprog_interrupt_reentry:
+ 	sti		gr22,@(sp,#REG_SP)
+ 
+ 	# set CCCR.CC3 to Undefined to abort atomic-modify completion inside the kernel
+-	# - for an explanation of how it works, see: Documentation/fujitsu/frv/atomic-ops.txt
++	# - for an explanation of how it works, see: Documentation/frv/atomic-ops.txt
+ 	movsg		cccr,gr20
+ 	andi		gr20,#~0xc0,gr20
+ 	movgs		gr20,cccr
+@@ -1494,7 +1494,7 @@ sys_call_table:
+ 	.long sys_epoll_pwait
+ 	.long sys_utimensat		/* 320 */
+ 	.long sys_signalfd
+-	.long sys_timerfd
++	.long sys_ni_syscall
+ 	.long sys_eventfd
+ 	.long sys_fallocate
+ 
 diff --git a/arch/frv/kernel/gdb-stub.c b/arch/frv/kernel/gdb-stub.c
 index e89cad1..48a0393 100644
 --- a/arch/frv/kernel/gdb-stub.c
@@ -66406,9 +79095,18 @@
   *  Step 3:
   *  Download the kernel to the remote target and start
 diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S
-index a17a81d..f42b328 100644
+index a17a81d..ef7527b 100644
 --- a/arch/frv/kernel/vmlinux.lds.S
 +++ b/arch/frv/kernel/vmlinux.lds.S
+@@ -13,7 +13,7 @@ ENTRY(_start)
+ 
+ jiffies = jiffies_64 + 4;
+ 
+-__page_offset = 0xc0000000;		/* start of area covered by struct pages */
++__page_offset = CONFIG_PAGE_OFFSET;	/* start of area covered by struct pages */
+ __kernel_image_start = __page_offset;	/* address at which kernel image resides */
+ 
+ SECTIONS
 @@ -28,14 +28,14 @@ SECTIONS
    .init.text : {
  	*(.text.head)
@@ -66448,6 +79146,58 @@
  	CONSTRUCTORS
  	}
  
+diff --git a/arch/frv/lib/atomic-ops.S b/arch/frv/lib/atomic-ops.S
+index 545cd32..ee0ac90 100644
+--- a/arch/frv/lib/atomic-ops.S
++++ b/arch/frv/lib/atomic-ops.S
+@@ -1,7 +1,7 @@
+ /* atomic-ops.S: kernel atomic operations
+  *
+  * For an explanation of how atomic ops work in this arch, see:
+- *   Documentation/fujitsu/frv/atomic-ops.txt
++ *   Documentation/frv/atomic-ops.txt
+  *
+  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+  * Written by David Howells (dhowells at redhat.com)
+diff --git a/arch/frv/mm/mmu-context.c b/arch/frv/mm/mmu-context.c
+index 1530a41..81757d5 100644
+--- a/arch/frv/mm/mmu-context.c
++++ b/arch/frv/mm/mmu-context.c
+@@ -181,7 +181,7 @@ int cxn_pin_by_pid(pid_t pid)
+ 
+ 	/* get a handle on the mm_struct */
+ 	read_lock(&tasklist_lock);
+-	tsk = find_task_by_pid(pid);
++	tsk = find_task_by_vpid(pid);
+ 	if (tsk) {
+ 		ret = -EINVAL;
+ 
+diff --git a/arch/frv/mm/pgalloc.c b/arch/frv/mm/pgalloc.c
+index 7787c3c..1a2e5c8 100644
+--- a/arch/frv/mm/pgalloc.c
++++ b/arch/frv/mm/pgalloc.c
+@@ -140,7 +140,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return pgd;
+ }
+ 
+-void pgd_free(pgd_t *pgd)
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	/* in the non-PAE case, clear_page_tables() clears user pgd entries */
+  	quicklist_free(0, pgd_dtor, pgd);
+diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
+index ff6a871..dc61222 100644
+--- a/arch/h8300/Kconfig
++++ b/arch/h8300/Kconfig
+@@ -223,8 +223,6 @@ endmenu
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/h8300/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S
 index a2e72d4..43a87b9 100644
 --- a/arch/h8300/kernel/vmlinux.lds.S
@@ -66475,11 +79225,33 @@
  #if defined(CONFIG_BLK_DEV_INITRD)
  		. = ALIGN(4);
  	___initramfs_start = .;
+diff --git a/arch/h8300/platform/h8s/ints.c b/arch/h8300/platform/h8s/ints.c
+index 551fd5f..ac10b97 100644
+--- a/arch/h8300/platform/h8s/ints.c
++++ b/arch/h8300/platform/h8s/ints.c
+@@ -121,7 +121,7 @@ void __init init_IRQ(void)
+ 		printk("virtual vector at 0x%08lx\n",(unsigned long)ramvec);
+ 
+ #if defined(CONFIG_GDB_DEBUG)
+-	/* save orignal break vector */
++	/* save original break vector */
+ 	break_vec = ramvec[TRAP3_VEC];
+ #else
+ 	break_vec = VECTOR(trace_break);
 diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
-index bef4772..c9307c9 100644
+index bef4772..b0de113 100644
 --- a/arch/ia64/Kconfig
 +++ b/arch/ia64/Kconfig
-@@ -42,6 +42,11 @@ config MMU
+@@ -15,6 +15,8 @@ config IA64
+ 	select ACPI if (!IA64_HP_SIM)
+ 	select PM if (!IA64_HP_SIM)
+ 	select ARCH_SUPPORTS_MSI
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
+ 	default y
+ 	help
+ 	  The Itanium Processor Family is Intel's 64-bit successor to
+@@ -42,6 +44,11 @@ config MMU
  config SWIOTLB
         bool
  
@@ -66491,7 +79263,7 @@
  config RWSEM_XCHGADD_ALGORITHM
  	bool
  	default y
-@@ -75,6 +80,9 @@ config GENERIC_TIME_VSYSCALL
+@@ -75,6 +82,9 @@ config GENERIC_TIME_VSYSCALL
  	bool
  	default y
  
@@ -66501,6 +79273,75 @@
  config DMI
  	bool
  	default y
+@@ -275,8 +285,8 @@ config SMP
+ 	  single processor systems.  On a single processor system, the kernel
+ 	  will run faster if you say N here.
+ 
+-	  See also the <file:Documentation/smp.txt> and the SMP-HOWTO
+-	  available at <http://www.tldp.org/docs.html#howto>.
++	  See also the SMP-HOWTO available at
++	  <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
+ 
+@@ -592,8 +602,6 @@ config IRQ_PER_CPU
+ 
+ source "arch/ia64/hp/sim/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/ia64/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
+index 45bf04e..a944454 100644
+--- a/arch/ia64/hp/common/sba_iommu.c
++++ b/arch/ia64/hp/common/sba_iommu.c
+@@ -1265,7 +1265,7 @@ sba_fill_pdir(
+  * the sglist do both.
+  */
+ static SBA_INLINE int
+-sba_coalesce_chunks( struct ioc *ioc,
++sba_coalesce_chunks(struct ioc *ioc, struct device *dev,
+ 	struct scatterlist *startsg,
+ 	int nents)
+ {
+@@ -1275,6 +1275,7 @@ sba_coalesce_chunks( struct ioc *ioc,
+ 	struct scatterlist *dma_sg;        /* next DMA stream head */
+ 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+ 	int n_mappings = 0;
++	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+ 
+ 	while (nents > 0) {
+ 		unsigned long vaddr = (unsigned long) sba_sg_address(startsg);
+@@ -1314,6 +1315,9 @@ sba_coalesce_chunks( struct ioc *ioc,
+ 			    > DMA_CHUNK_SIZE)
+ 				break;
+ 
++			if (dma_len + startsg->length > max_seg_size)
++				break;
++
+ 			/*
+ 			** Then look for virtually contiguous blocks.
+ 			**
+@@ -1441,7 +1445,7 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di
+ 	** w/o this association, we wouldn't have coherent DMA!
+ 	** Access to the virtual address is what forces a two pass algorithm.
+ 	*/
+-	coalesced = sba_coalesce_chunks(ioc, sglist, nents);
++	coalesced = sba_coalesce_chunks(ioc, dev, sglist, nents);
+ 
+ 	/*
+ 	** Program the I/O Pdir
+@@ -1871,7 +1875,7 @@ ioc_show(struct seq_file *s, void *v)
+ 	return 0;
+ }
+ 
+-static struct seq_operations ioc_seq_ops = {
++static const struct seq_operations ioc_seq_ops = {
+ 	.start = ioc_start,
+ 	.next  = ioc_next,
+ 	.stop  = ioc_stop,
 diff --git a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c
 index 08b117e..9898feb 100644
 --- a/arch/ia64/hp/sim/simeth.c
@@ -66543,40 +79384,1103 @@
  {
  	unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
  
-diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
-index 1962879..e58f436 100644
---- a/arch/ia64/kernel/module.c
-+++ b/arch/ia64/kernel/module.c
-@@ -940,14 +940,3 @@ module_arch_cleanup (struct module *mod)
- 	if (mod->arch.core_unw_table)
- 		unw_remove_unwind_table(mod->arch.core_unw_table);
+diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c
+index d1d50cd..896b1eb 100644
+--- a/arch/ia64/ia32/ia32_support.c
++++ b/arch/ia64/ia32/ia32_support.c
+@@ -27,7 +27,7 @@
+ 
+ #include "ia32priv.h"
+ 
+-extern void die_if_kernel (char *str, struct pt_regs *regs, long err);
++extern int die_if_kernel (char *str, struct pt_regs *regs, long err);
+ 
+ struct exec_domain ia32_exec_domain;
+ struct page *ia32_shared_page[NR_CPUS];
+@@ -217,7 +217,8 @@ ia32_bad_interrupt (unsigned long int_num, struct pt_regs *regs)
+ {
+ 	siginfo_t siginfo;
+ 
+-	die_if_kernel("Bad IA-32 interrupt", regs, int_num);
++	if (die_if_kernel("Bad IA-32 interrupt", regs, int_num))
++		return;
+ 
+ 	siginfo.si_signo = SIGTRAP;
+ 	siginfo.si_errno = int_num;	/* XXX is it OK to abuse si_errno like this? */
+diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
+index 242d793..919070a 100644
+--- a/arch/ia64/kernel/efi.c
++++ b/arch/ia64/kernel/efi.c
+@@ -1,7 +1,8 @@
+ /*
+  * Extensible Firmware Interface
+  *
+- * Based on Extensible Firmware Interface Specification version 0.9 April 30, 1999
++ * Based on Extensible Firmware Interface Specification version 0.9
++ * April 30, 1999
+  *
+  * Copyright (C) 1999 VA Linux Systems
+  * Copyright (C) 1999 Walt Drummond <drummond at valinux.com>
+@@ -48,145 +49,157 @@ static unsigned long mem_limit = ~0UL, max_addr = ~0UL, min_addr = 0UL;
+ 
+ #define efi_call_virt(f, args...)	(*(f))(args)
+ 
+-#define STUB_GET_TIME(prefix, adjust_arg)							  \
+-static efi_status_t										  \
+-prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)						  \
+-{												  \
+-	struct ia64_fpreg fr[6];								  \
+-	efi_time_cap_t *atc = NULL;								  \
+-	efi_status_t ret;									  \
+-												  \
+-	if (tc)											  \
+-		atc = adjust_arg(tc);								  \
+-	ia64_save_scratch_fpregs(fr);								  \
+-	ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time), adjust_arg(tm), atc); \
+-	ia64_load_scratch_fpregs(fr);								  \
+-	return ret;										  \
++#define STUB_GET_TIME(prefix, adjust_arg)				       \
++static efi_status_t							       \
++prefix##_get_time (efi_time_t *tm, efi_time_cap_t *tc)			       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_time_cap_t *atc = NULL;					       \
++	efi_status_t ret;						       \
++									       \
++	if (tc)								       \
++		atc = adjust_arg(tc);					       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix((efi_get_time_t *) __va(runtime->get_time),    \
++				adjust_arg(tm), atc);			       \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_SET_TIME(prefix, adjust_arg)							\
+-static efi_status_t										\
+-prefix##_set_time (efi_time_t *tm)								\
+-{												\
+-	struct ia64_fpreg fr[6];								\
+-	efi_status_t ret;									\
+-												\
+-	ia64_save_scratch_fpregs(fr);								\
+-	ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time), adjust_arg(tm));	\
+-	ia64_load_scratch_fpregs(fr);								\
+-	return ret;										\
++#define STUB_SET_TIME(prefix, adjust_arg)				       \
++static efi_status_t							       \
++prefix##_set_time (efi_time_t *tm)					       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_status_t ret;						       \
++									       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix((efi_set_time_t *) __va(runtime->set_time),    \
++				adjust_arg(tm));			       \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg)						\
+-static efi_status_t										\
+-prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending, efi_time_t *tm)		\
+-{												\
+-	struct ia64_fpreg fr[6];								\
+-	efi_status_t ret;									\
+-												\
+-	ia64_save_scratch_fpregs(fr);								\
+-	ret = efi_call_##prefix((efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time),	\
+-				adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm));	\
+-	ia64_load_scratch_fpregs(fr);								\
+-	return ret;										\
++#define STUB_GET_WAKEUP_TIME(prefix, adjust_arg)			       \
++static efi_status_t							       \
++prefix##_get_wakeup_time (efi_bool_t *enabled, efi_bool_t *pending,	       \
++			  efi_time_t *tm)				       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_status_t ret;						       \
++									       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix(					       \
++		(efi_get_wakeup_time_t *) __va(runtime->get_wakeup_time),      \
++		adjust_arg(enabled), adjust_arg(pending), adjust_arg(tm));     \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg)						\
+-static efi_status_t										\
+-prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)					\
+-{												\
+-	struct ia64_fpreg fr[6];								\
+-	efi_time_t *atm = NULL;									\
+-	efi_status_t ret;									\
+-												\
+-	if (tm)											\
+-		atm = adjust_arg(tm);								\
+-	ia64_save_scratch_fpregs(fr);								\
+-	ret = efi_call_##prefix((efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time),	\
+-				enabled, atm);							\
+-	ia64_load_scratch_fpregs(fr);								\
+-	return ret;										\
++#define STUB_SET_WAKEUP_TIME(prefix, adjust_arg)			       \
++static efi_status_t							       \
++prefix##_set_wakeup_time (efi_bool_t enabled, efi_time_t *tm)		       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_time_t *atm = NULL;						       \
++	efi_status_t ret;						       \
++									       \
++	if (tm)								       \
++		atm = adjust_arg(tm);					       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix(					       \
++		(efi_set_wakeup_time_t *) __va(runtime->set_wakeup_time),      \
++		enabled, atm);						       \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_GET_VARIABLE(prefix, adjust_arg)						\
+-static efi_status_t									\
+-prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,		\
+-		       unsigned long *data_size, void *data)				\
+-{											\
+-	struct ia64_fpreg fr[6];							\
+-	u32 *aattr = NULL;									\
+-	efi_status_t ret;								\
+-											\
+-	if (attr)									\
+-		aattr = adjust_arg(attr);						\
+-	ia64_save_scratch_fpregs(fr);							\
+-	ret = efi_call_##prefix((efi_get_variable_t *) __va(runtime->get_variable),	\
+-				adjust_arg(name), adjust_arg(vendor), aattr,		\
+-				adjust_arg(data_size), adjust_arg(data));		\
+-	ia64_load_scratch_fpregs(fr);							\
+-	return ret;									\
++#define STUB_GET_VARIABLE(prefix, adjust_arg)				       \
++static efi_status_t							       \
++prefix##_get_variable (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,      \
++		       unsigned long *data_size, void *data)		       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	u32 *aattr = NULL;						       \
++	efi_status_t ret;						       \
++									       \
++	if (attr)							       \
++		aattr = adjust_arg(attr);				       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix(					       \
++		(efi_get_variable_t *) __va(runtime->get_variable),	       \
++		adjust_arg(name), adjust_arg(vendor), aattr,		       \
++		adjust_arg(data_size), adjust_arg(data));		       \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg)						\
+-static efi_status_t										\
+-prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name, efi_guid_t *vendor)	\
+-{												\
+-	struct ia64_fpreg fr[6];								\
+-	efi_status_t ret;									\
+-												\
+-	ia64_save_scratch_fpregs(fr);								\
+-	ret = efi_call_##prefix((efi_get_next_variable_t *) __va(runtime->get_next_variable),	\
+-				adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor));	\
+-	ia64_load_scratch_fpregs(fr);								\
+-	return ret;										\
++#define STUB_GET_NEXT_VARIABLE(prefix, adjust_arg)			       \
++static efi_status_t							       \
++prefix##_get_next_variable (unsigned long *name_size, efi_char16_t *name,      \
++			    efi_guid_t *vendor)				       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_status_t ret;						       \
++									       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix(					       \
++		(efi_get_next_variable_t *) __va(runtime->get_next_variable),  \
++		adjust_arg(name_size), adjust_arg(name), adjust_arg(vendor));  \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_SET_VARIABLE(prefix, adjust_arg)						\
+-static efi_status_t									\
+-prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor, unsigned long attr,	\
+-		       unsigned long data_size, void *data)				\
+-{											\
+-	struct ia64_fpreg fr[6];							\
+-	efi_status_t ret;								\
+-											\
+-	ia64_save_scratch_fpregs(fr);							\
+-	ret = efi_call_##prefix((efi_set_variable_t *) __va(runtime->set_variable),	\
+-				adjust_arg(name), adjust_arg(vendor), attr, data_size,	\
+-				adjust_arg(data));					\
+-	ia64_load_scratch_fpregs(fr);							\
+-	return ret;									\
++#define STUB_SET_VARIABLE(prefix, adjust_arg)				       \
++static efi_status_t							       \
++prefix##_set_variable (efi_char16_t *name, efi_guid_t *vendor,		       \
++		       unsigned long attr, unsigned long data_size,	       \
++		       void *data)					       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_status_t ret;						       \
++									       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix(					       \
++		(efi_set_variable_t *) __va(runtime->set_variable),	       \
++		adjust_arg(name), adjust_arg(vendor), attr, data_size,	       \
++		adjust_arg(data));					       \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg)					\
+-static efi_status_t										\
+-prefix##_get_next_high_mono_count (u32 *count)							\
+-{												\
+-	struct ia64_fpreg fr[6];								\
+-	efi_status_t ret;									\
+-												\
+-	ia64_save_scratch_fpregs(fr);								\
+-	ret = efi_call_##prefix((efi_get_next_high_mono_count_t *)				\
+-				__va(runtime->get_next_high_mono_count), adjust_arg(count));	\
+-	ia64_load_scratch_fpregs(fr);								\
+-	return ret;										\
++#define STUB_GET_NEXT_HIGH_MONO_COUNT(prefix, adjust_arg)		       \
++static efi_status_t							       \
++prefix##_get_next_high_mono_count (u32 *count)				       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_status_t ret;						       \
++									       \
++	ia64_save_scratch_fpregs(fr);					       \
++	ret = efi_call_##prefix((efi_get_next_high_mono_count_t *)	       \
++				__va(runtime->get_next_high_mono_count),       \
++				adjust_arg(count));			       \
++	ia64_load_scratch_fpregs(fr);					       \
++	return ret;							       \
+ }
+ 
+-#define STUB_RESET_SYSTEM(prefix, adjust_arg)					\
+-static void									\
+-prefix##_reset_system (int reset_type, efi_status_t status,			\
+-		       unsigned long data_size, efi_char16_t *data)		\
+-{										\
+-	struct ia64_fpreg fr[6];						\
+-	efi_char16_t *adata = NULL;						\
+-										\
+-	if (data)								\
+-		adata = adjust_arg(data);					\
+-										\
+-	ia64_save_scratch_fpregs(fr);						\
+-	efi_call_##prefix((efi_reset_system_t *) __va(runtime->reset_system),	\
+-			  reset_type, status, data_size, adata);		\
+-	/* should not return, but just in case... */				\
+-	ia64_load_scratch_fpregs(fr);						\
++#define STUB_RESET_SYSTEM(prefix, adjust_arg)				       \
++static void								       \
++prefix##_reset_system (int reset_type, efi_status_t status,		       \
++		       unsigned long data_size, efi_char16_t *data)	       \
++{									       \
++	struct ia64_fpreg fr[6];					       \
++	efi_char16_t *adata = NULL;					       \
++									       \
++	if (data)							       \
++		adata = adjust_arg(data);				       \
++									       \
++	ia64_save_scratch_fpregs(fr);					       \
++	efi_call_##prefix(						       \
++		(efi_reset_system_t *) __va(runtime->reset_system),	       \
++		reset_type, status, data_size, adata);			       \
++	/* should not return, but just in case... */			       \
++	ia64_load_scratch_fpregs(fr);					       \
  }
--
--#ifdef CONFIG_SMP
--void
--percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
--{
--	unsigned int i;
--	for_each_possible_cpu(i) {
--		memcpy(pcpudst + __per_cpu_offset[i], src, size);
--	}
--}
--#endif /* CONFIG_SMP */
-diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
-index 73e7c2e..5ae177f 100644
---- a/arch/ia64/kernel/perfmon.c
-+++ b/arch/ia64/kernel/perfmon.c
-@@ -2631,7 +2631,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
- 	 */
- 	if (task == current) return 0;
  
--	if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
-+	if (!task_is_stopped_or_traced(task)) {
- 		DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task_pid_nr(task), task->state));
- 		return -EBUSY;
+ #define phys_ptr(arg)	((__typeof__(arg)) ia64_tpa(arg))
+@@ -223,7 +236,8 @@ efi_gettimeofday (struct timespec *ts)
+ 		return;
  	}
-@@ -4792,7 +4792,7 @@ recheck:
- 	 * the task must be stopped.
+ 
+-	ts->tv_sec = mktime(tm.year, tm.month, tm.day, tm.hour, tm.minute, tm.second);
++	ts->tv_sec = mktime(tm.year, tm.month, tm.day,
++			    tm.hour, tm.minute, tm.second);
+ 	ts->tv_nsec = tm.nanosecond;
+ }
+ 
+@@ -297,8 +311,8 @@ walk (efi_freemem_callback_t callback, void *arg, u64 attr)
+ }
+ 
+ /*
+- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
+- * has memory that is available for OS use.
++ * Walk the EFI memory map and call CALLBACK once for each EFI memory
++ * descriptor that has memory that is available for OS use.
+  */
+ void
+ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
+@@ -307,8 +321,8 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
+ }
+ 
+ /*
+- * Walks the EFI memory map and calls CALLBACK once for each EFI memory descriptor that
+- * has memory that is available for uncached allocator.
++ * Walk the EFI memory map and call CALLBACK once for each EFI memory
++ * descriptor that has memory that is available for uncached allocator.
+  */
+ void
+ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
+@@ -317,11 +331,10 @@ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg)
+ }
+ 
+ /*
+- * Look for the PAL_CODE region reported by EFI and maps it using an
++ * Look for the PAL_CODE region reported by EFI and map it using an
+  * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
+  * Abstraction Layer chapter 11 in ADAG
+  */
+-
+ void *
+ efi_get_pal_addr (void)
+ {
+@@ -341,45 +354,47 @@ efi_get_pal_addr (void)
+ 			continue;
+ 
+ 		if (++pal_code_count > 1) {
+-			printk(KERN_ERR "Too many EFI Pal Code memory ranges, dropped @ %lx\n",
+-			       md->phys_addr);
++			printk(KERN_ERR "Too many EFI Pal Code memory ranges, "
++			       "dropped @ %lx\n", md->phys_addr);
+ 			continue;
+ 		}
+ 		/*
+-		 * The only ITLB entry in region 7 that is used is the one installed by
+-		 * __start().  That entry covers a 64MB range.
++		 * The only ITLB entry in region 7 that is used is the one
++		 * installed by __start().  That entry covers a 64MB range.
+ 		 */
+ 		mask  = ~((1 << KERNEL_TR_PAGE_SHIFT) - 1);
+ 		vaddr = PAGE_OFFSET + md->phys_addr;
+ 
+ 		/*
+-		 * We must check that the PAL mapping won't overlap with the kernel
+-		 * mapping.
++		 * We must check that the PAL mapping won't overlap with the
++		 * kernel mapping.
+ 		 *
+-		 * PAL code is guaranteed to be aligned on a power of 2 between 4k and
+-		 * 256KB and that only one ITR is needed to map it. This implies that the
+-		 * PAL code is always aligned on its size, i.e., the closest matching page
+-		 * size supported by the TLB. Therefore PAL code is guaranteed never to
+-		 * cross a 64MB unless it is bigger than 64MB (very unlikely!).  So for
+-		 * now the following test is enough to determine whether or not we need a
+-		 * dedicated ITR for the PAL code.
++		 * PAL code is guaranteed to be aligned on a power of 2 between
++		 * 4k and 256KB and that only one ITR is needed to map it. This
++		 * implies that the PAL code is always aligned on its size,
++		 * i.e., the closest matching page size supported by the TLB.
++		 * Therefore PAL code is guaranteed never to cross a 64MB unless
++		 * it is bigger than 64MB (very unlikely!).  So for now the
++		 * following test is enough to determine whether or not we need
++		 * a dedicated ITR for the PAL code.
+ 		 */
+ 		if ((vaddr & mask) == (KERNEL_START & mask)) {
+-			printk(KERN_INFO "%s: no need to install ITR for PAL code\n",
+-			       __FUNCTION__);
++			printk(KERN_INFO "%s: no need to install ITR for "
++			       "PAL code\n", __FUNCTION__);
+ 			continue;
+ 		}
+ 
+ 		if (efi_md_size(md) > IA64_GRANULE_SIZE)
+-			panic("Woah!  PAL code size bigger than a granule!");
++			panic("Whoa!  PAL code size bigger than a granule!");
+ 
+ #if EFI_DEBUG
+ 		mask  = ~((1 << IA64_GRANULE_SHIFT) - 1);
+ 
+-		printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
+-			smp_processor_id(), md->phys_addr,
+-			md->phys_addr + efi_md_size(md),
+-			vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
++		printk(KERN_INFO "CPU %d: mapping PAL code "
++                       "[0x%lx-0x%lx) into [0x%lx-0x%lx)\n",
++                       smp_processor_id(), md->phys_addr,
++                       md->phys_addr + efi_md_size(md),
++                       vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE);
+ #endif
+ 		return __va(md->phys_addr);
+ 	}
+@@ -401,11 +416,11 @@ efi_map_pal_code (void)
+ 	 * Cannot write to CRx with PSR.ic=1
+ 	 */
+ 	psr = ia64_clear_ic();
+-	ia64_itr(0x1, IA64_TR_PALCODE, GRANULEROUNDDOWN((unsigned long) pal_vaddr),
++	ia64_itr(0x1, IA64_TR_PALCODE,
++		 GRANULEROUNDDOWN((unsigned long) pal_vaddr),
+ 		 pte_val(pfn_pte(__pa(pal_vaddr) >> PAGE_SHIFT, PAGE_KERNEL)),
+ 		 IA64_GRANULE_SHIFT);
+ 	ia64_set_psr(psr);		/* restore psr */
+-	ia64_srlz_i();
+ }
+ 
+ void __init
+@@ -418,7 +433,10 @@ efi_init (void)
+ 	char *cp, vendor[100] = "unknown";
+ 	int i;
+ 
+-	/* it's too early to be able to use the standard kernel command line support... */
++	/*
++	 * It's too early to be able to use the standard kernel command line
++	 * support...
++	 */
+ 	for (cp = boot_command_line; *cp; ) {
+ 		if (memcmp(cp, "mem=", 4) == 0) {
+ 			mem_limit = memparse(cp + 4, &cp);
+@@ -434,9 +452,11 @@ efi_init (void)
+ 		}
+ 	}
+ 	if (min_addr != 0UL)
+-		printk(KERN_INFO "Ignoring memory below %luMB\n", min_addr >> 20);
++		printk(KERN_INFO "Ignoring memory below %luMB\n",
++		       min_addr >> 20);
+ 	if (max_addr != ~0UL)
+-		printk(KERN_INFO "Ignoring memory above %luMB\n", max_addr >> 20);
++		printk(KERN_INFO "Ignoring memory above %luMB\n",
++		       max_addr >> 20);
+ 
+ 	efi.systab = __va(ia64_boot_param->efi_systab);
+ 
+@@ -444,9 +464,9 @@ efi_init (void)
+ 	 * Verify the EFI Table
+ 	 */
+ 	if (efi.systab == NULL)
+-		panic("Woah! Can't find EFI system table.\n");
++		panic("Whoa! Can't find EFI system table.\n");
+ 	if (efi.systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+-		panic("Woah! EFI system table signature incorrect\n");
++		panic("Whoa! EFI system table signature incorrect\n");
+ 	if ((efi.systab->hdr.revision >> 16) == 0)
+ 		printk(KERN_WARNING "Warning: EFI system table version "
+ 		       "%d.%02d, expected 1.00 or greater\n",
+@@ -464,7 +484,8 @@ efi_init (void)
+ 	}
+ 
+ 	printk(KERN_INFO "EFI v%u.%.02u by %s:",
+-	       efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor);
++	       efi.systab->hdr.revision >> 16,
++	       efi.systab->hdr.revision & 0xffff, vendor);
+ 
+ 	efi.mps        = EFI_INVALID_TABLE_ADDR;
+ 	efi.acpi       = EFI_INVALID_TABLE_ADDR;
+@@ -519,9 +540,12 @@ efi_init (void)
+ 		efi_memory_desc_t *md;
+ 		void *p;
+ 
+-		for (i = 0, p = efi_map_start; p < efi_map_end; ++i, p += efi_desc_size) {
++		for (i = 0, p = efi_map_start; p < efi_map_end;
++		     ++i, p += efi_desc_size)
++		{
+ 			md = p;
+-			printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n",
++			printk("mem%02u: type=%u, attr=0x%lx, "
++			       "range=[0x%016lx-0x%016lx) (%luMB)\n",
+ 			       i, md->type, md->attribute, md->phys_addr,
+ 			       md->phys_addr + efi_md_size(md),
+ 			       md->num_pages >> (20 - EFI_PAGE_SHIFT));
+@@ -549,8 +573,8 @@ efi_enter_virtual_mode (void)
+ 		md = p;
+ 		if (md->attribute & EFI_MEMORY_RUNTIME) {
+ 			/*
+-			 * Some descriptors have multiple bits set, so the order of
+-			 * the tests is relevant.
++			 * Some descriptors have multiple bits set, so the
++			 * order of the tests is relevant.
+ 			 */
+ 			if (md->attribute & EFI_MEMORY_WB) {
+ 				md->virt_addr = (u64) __va(md->phys_addr);
+@@ -558,21 +582,26 @@ efi_enter_virtual_mode (void)
+ 				md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+ 			} else if (md->attribute & EFI_MEMORY_WC) {
+ #if 0
+-				md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
+-									   | _PAGE_D
+-									   | _PAGE_MA_WC
+-									   | _PAGE_PL_0
+-									   | _PAGE_AR_RW));
++				md->virt_addr = ia64_remap(md->phys_addr,
++							   (_PAGE_A |
++							    _PAGE_P |
++							    _PAGE_D |
++							    _PAGE_MA_WC |
++							    _PAGE_PL_0 |
++							    _PAGE_AR_RW));
+ #else
+ 				printk(KERN_INFO "EFI_MEMORY_WC mapping\n");
+ 				md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+ #endif
+ 			} else if (md->attribute & EFI_MEMORY_WT) {
+ #if 0
+-				md->virt_addr = ia64_remap(md->phys_addr, (_PAGE_A | _PAGE_P
+-									   | _PAGE_D | _PAGE_MA_WT
+-									   | _PAGE_PL_0
+-									   | _PAGE_AR_RW));
++				md->virt_addr = ia64_remap(md->phys_addr,
++							   (_PAGE_A |
++							    _PAGE_P |
++							    _PAGE_D |
++							    _PAGE_MA_WT |
++							    _PAGE_PL_0 |
++							    _PAGE_AR_RW));
+ #else
+ 				printk(KERN_INFO "EFI_MEMORY_WT mapping\n");
+ 				md->virt_addr = (u64) ioremap(md->phys_addr, 0);
+@@ -583,16 +612,18 @@ efi_enter_virtual_mode (void)
+ 
+ 	status = efi_call_phys(__va(runtime->set_virtual_address_map),
+ 			       ia64_boot_param->efi_memmap_size,
+-			       efi_desc_size, ia64_boot_param->efi_memdesc_version,
++			       efi_desc_size,
++			       ia64_boot_param->efi_memdesc_version,
+ 			       ia64_boot_param->efi_memmap);
+ 	if (status != EFI_SUCCESS) {
+-		printk(KERN_WARNING "warning: unable to switch EFI into virtual mode "
+-		       "(status=%lu)\n", status);
++		printk(KERN_WARNING "warning: unable to switch EFI into "
++		       "virtual mode (status=%lu)\n", status);
+ 		return;
+ 	}
+ 
+ 	/*
+-	 * Now that EFI is in virtual mode, we call the EFI functions more efficiently:
++	 * Now that EFI is in virtual mode, we call the EFI functions more
++	 * efficiently:
+ 	 */
+ 	efi.get_time = virt_get_time;
+ 	efi.set_time = virt_set_time;
+@@ -606,8 +637,8 @@ efi_enter_virtual_mode (void)
+ }
+ 
+ /*
+- * Walk the EFI memory map looking for the I/O port range.  There can only be one entry of
+- * this type, other I/O port ranges should be described via ACPI.
++ * Walk the EFI memory map looking for the I/O port range.  There can only be
++ * one entry of this type, other I/O port ranges should be described via ACPI.
+  */
+ u64
+ efi_get_iobase (void)
+@@ -678,7 +709,6 @@ efi_memmap_intersects (unsigned long phys_addr, unsigned long size)
+ 
+ 	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ 		md = p;
+-
+ 		if (md->phys_addr < end && efi_md_end(md) > phys_addr)
+ 			return 1;
+ 	}
+@@ -731,7 +761,7 @@ efi_mem_attribute (unsigned long phys_addr, unsigned long size)
+ 		if (!md || (md->attribute & ~EFI_MEMORY_RUNTIME) != attr)
+ 			return 0;
+ 	} while (md);
+-	return 0;
++	return 0;	/* never reached */
+ }
+ 
+ u64
+@@ -767,7 +797,7 @@ kern_mem_attribute (unsigned long phys_addr, unsigned long size)
+ 		if (!md || md->attribute != attr)
+ 			return 0;
+ 	} while (md);
+-	return 0;
++	return 0;	/* never reached */
+ }
+ EXPORT_SYMBOL(kern_mem_attribute);
+ 
+@@ -883,7 +913,7 @@ efi_uart_console_only(void)
+ 				return 1;
+ 			uart = 0;
+ 		}
+-		hdr = (struct efi_generic_dev_path *) ((u8 *) hdr + hdr->length);
++		hdr = (struct efi_generic_dev_path *)((u8 *) hdr + hdr->length);
+ 	}
+ 	printk(KERN_ERR "Malformed %s value\n", name);
+ 	return 0;
+@@ -921,10 +951,12 @@ find_memmap_space (void)
+ 		if (!efi_wb(md)) {
+ 			continue;
+ 		}
+-		if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
++		if (pmd == NULL || !efi_wb(pmd) ||
++		    efi_md_end(pmd) != md->phys_addr) {
+ 			contig_low = GRANULEROUNDUP(md->phys_addr);
+ 			contig_high = efi_md_end(md);
+-			for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
++			for (q = p + efi_desc_size; q < efi_map_end;
++			     q += efi_desc_size) {
+ 				check_md = q;
+ 				if (!efi_wb(check_md))
+ 					break;
+@@ -988,8 +1020,9 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
+ 	for (p = efi_map_start; p < efi_map_end; pmd = md, p += efi_desc_size) {
+ 		md = p;
+ 		if (!efi_wb(md)) {
+-			if (efi_uc(md) && (md->type == EFI_CONVENTIONAL_MEMORY ||
+-				    	   md->type == EFI_BOOT_SERVICES_DATA)) {
++			if (efi_uc(md) &&
++			    (md->type == EFI_CONVENTIONAL_MEMORY ||
++			     md->type == EFI_BOOT_SERVICES_DATA)) {
+ 				k->attribute = EFI_MEMORY_UC;
+ 				k->start = md->phys_addr;
+ 				k->num_pages = md->num_pages;
+@@ -997,10 +1030,12 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
+ 			}
+ 			continue;
+ 		}
+-		if (pmd == NULL || !efi_wb(pmd) || efi_md_end(pmd) != md->phys_addr) {
++		if (pmd == NULL || !efi_wb(pmd) ||
++		    efi_md_end(pmd) != md->phys_addr) {
+ 			contig_low = GRANULEROUNDUP(md->phys_addr);
+ 			contig_high = efi_md_end(md);
+-			for (q = p + efi_desc_size; q < efi_map_end; q += efi_desc_size) {
++			for (q = p + efi_desc_size; q < efi_map_end;
++			     q += efi_desc_size) {
+ 				check_md = q;
+ 				if (!efi_wb(check_md))
+ 					break;
+@@ -1025,13 +1060,17 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
+ 		if (md->phys_addr < contig_low) {
+ 			lim = min(efi_md_end(md), contig_low);
+ 			if (efi_uc(md)) {
+-				if (k > kern_memmap && (k-1)->attribute == EFI_MEMORY_UC &&
++				if (k > kern_memmap &&
++				    (k-1)->attribute == EFI_MEMORY_UC &&
+ 				    kmd_end(k-1) == md->phys_addr) {
+-					(k-1)->num_pages += (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
++					(k-1)->num_pages +=
++						(lim - md->phys_addr)
++						>> EFI_PAGE_SHIFT;
+ 				} else {
+ 					k->attribute = EFI_MEMORY_UC;
+ 					k->start = md->phys_addr;
+-					k->num_pages = (lim - md->phys_addr) >> EFI_PAGE_SHIFT;
++					k->num_pages = (lim - md->phys_addr)
++						>> EFI_PAGE_SHIFT;
+ 					k++;
+ 				}
+ 			}
+@@ -1049,7 +1088,8 @@ efi_memmap_init(unsigned long *s, unsigned long *e)
+ 				} else {
+ 					k->attribute = EFI_MEMORY_UC;
+ 					k->start = lim;
+-					k->num_pages = (efi_md_end(md) - lim) >> EFI_PAGE_SHIFT;
++					k->num_pages = (efi_md_end(md) - lim)
++						>> EFI_PAGE_SHIFT;
+ 					k++;
+ 				}
+ 			}
+@@ -1151,8 +1191,10 @@ efi_initialize_iomem_resources(struct resource *code_resource,
+ 				break;
+ 		}
+ 
+-		if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
+-			printk(KERN_ERR "failed to alocate resource for iomem\n");
++		if ((res = kzalloc(sizeof(struct resource),
++				   GFP_KERNEL)) == NULL) {
++			printk(KERN_ERR
++			       "failed to allocate resource for iomem\n");
+ 			return;
+ 		}
+ 
+@@ -1187,44 +1229,44 @@ efi_initialize_iomem_resources(struct resource *code_resource,
+    rsvd_regions are sorted
+  */
+ unsigned long __init
+-kdump_find_rsvd_region (unsigned long size,
+-		struct rsvd_region *r, int n)
++kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n)
+ {
+-  int i;
+-  u64 start, end;
+-  u64 alignment = 1UL << _PAGE_SIZE_64M;
+-  void *efi_map_start, *efi_map_end, *p;
+-  efi_memory_desc_t *md;
+-  u64 efi_desc_size;
+-
+-  efi_map_start = __va(ia64_boot_param->efi_memmap);
+-  efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
+-  efi_desc_size = ia64_boot_param->efi_memdesc_size;
+-
+-  for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+-	  md = p;
+-	  if (!efi_wb(md))
+-		  continue;
+-	  start = ALIGN(md->phys_addr, alignment);
+-	  end = efi_md_end(md);
+-	  for (i = 0; i < n; i++) {
+-		if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
+-			if (__pa(r[i].start) > start + size)
+-				return start;
+-			start = ALIGN(__pa(r[i].end), alignment);
+-			if (i < n-1 && __pa(r[i+1].start) < start + size)
+-				continue;
+-			else
+-				break;
++	int i;
++	u64 start, end;
++	u64 alignment = 1UL << _PAGE_SIZE_64M;
++	void *efi_map_start, *efi_map_end, *p;
++	efi_memory_desc_t *md;
++	u64 efi_desc_size;
++
++	efi_map_start = __va(ia64_boot_param->efi_memmap);
++	efi_map_end   = efi_map_start + ia64_boot_param->efi_memmap_size;
++	efi_desc_size = ia64_boot_param->efi_memdesc_size;
++
++	for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
++		md = p;
++		if (!efi_wb(md))
++			continue;
++		start = ALIGN(md->phys_addr, alignment);
++		end = efi_md_end(md);
++		for (i = 0; i < n; i++) {
++			if (__pa(r[i].start) >= start && __pa(r[i].end) < end) {
++				if (__pa(r[i].start) > start + size)
++					return start;
++				start = ALIGN(__pa(r[i].end), alignment);
++				if (i < n-1 &&
++				    __pa(r[i+1].start) < start + size)
++					continue;
++				else
++					break;
++			}
+ 		}
+-	  }
+-	  if (end > start + size)
+-		return start;
+-  }
+-
+-  printk(KERN_WARNING "Cannot reserve 0x%lx byte of memory for crashdump\n",
+-	size);
+-  return ~0UL;
++		if (end > start + size)
++			return start;
++	}
++
++	printk(KERN_WARNING
++	       "Cannot reserve 0x%lx byte of memory for crashdump\n", size);
++	return ~0UL;
+ }
+ #endif
+ 
+diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
+index c36f43c..f5d3efb 100644
+--- a/arch/ia64/kernel/entry.S
++++ b/arch/ia64/kernel/entry.S
+@@ -1586,7 +1586,7 @@ sys_call_table:
+ 	data8 sys_epoll_pwait			// 1305
+ 	data8 sys_utimensat
+ 	data8 sys_signalfd
+-	data8 sys_timerfd
++	data8 sys_ni_syscall
+ 	data8 sys_eventfd
+ 
+ 	.org sys_call_table + 8*NR_syscalls	// guard against failures to increase NR_syscalls
+diff --git a/arch/ia64/kernel/fsyscall_gtod_data.h b/arch/ia64/kernel/fsyscall_gtod_data.h
+index 490dab5..57d2ee6 100644
+--- a/arch/ia64/kernel/fsyscall_gtod_data.h
++++ b/arch/ia64/kernel/fsyscall_gtod_data.h
+@@ -14,10 +14,10 @@ struct fsyscall_gtod_data_t {
+ 	u32		clk_shift;
+ 	void		*clk_fsys_mmio;
+ 	cycle_t		clk_cycle_last;
+-} __attribute__ ((aligned (L1_CACHE_BYTES)));
++} ____cacheline_aligned;
+ 
+ struct itc_jitter_data_t {
+ 	int		itc_jitter;
+ 	cycle_t		itc_lastcycle;
+-} __attribute__ ((aligned (L1_CACHE_BYTES)));
++} ____cacheline_aligned;
+ 
+diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
+index c3b4412..8e7193d 100644
+--- a/arch/ia64/kernel/ia64_ksyms.c
++++ b/arch/ia64/kernel/ia64_ksyms.c
+@@ -12,6 +12,9 @@ EXPORT_SYMBOL(memset);
+ EXPORT_SYMBOL(memcpy);
+ EXPORT_SYMBOL(strlen);
+ 
++#include<asm/pgtable.h>
++EXPORT_SYMBOL_GPL(empty_zero_page);
++
+ #include <asm/checksum.h>
+ EXPORT_SYMBOL(ip_fast_csum);		/* hand-coded assembly */
+ EXPORT_SYMBOL(csum_ipv6_magic);
+diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
+index fc4d267..b618487 100644
+--- a/arch/ia64/kernel/kprobes.c
++++ b/arch/ia64/kernel/kprobes.c
+@@ -381,9 +381,10 @@ static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+ static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+ {
+ 	unsigned int i;
+-	i = atomic_sub_return(1, &kcb->prev_kprobe_index);
+-	__get_cpu_var(current_kprobe) = kcb->prev_kprobe[i].kp;
+-	kcb->kprobe_status = kcb->prev_kprobe[i].status;
++	i = atomic_read(&kcb->prev_kprobe_index);
++	__get_cpu_var(current_kprobe) = kcb->prev_kprobe[i-1].kp;
++	kcb->kprobe_status = kcb->prev_kprobe[i-1].status;
++	atomic_sub(1, &kcb->prev_kprobe_index);
+ }
+ 
+ static void __kprobes set_current_kprobe(struct kprobe *p,
+diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
+index 6dbf591..846e7e0 100644
+--- a/arch/ia64/kernel/mca.c
++++ b/arch/ia64/kernel/mca.c
+@@ -2,61 +2,69 @@
+  * File:	mca.c
+  * Purpose:	Generic MCA handling layer
+  *
+- * Updated for latest kernel
+  * Copyright (C) 2003 Hewlett-Packard Co
+  *	David Mosberger-Tang <davidm at hpl.hp.com>
+  *
+  * Copyright (C) 2002 Dell Inc.
+- * Copyright (C) Matt Domsch (Matt_Domsch at dell.com)
++ * Copyright (C) Matt Domsch <Matt_Domsch at dell.com>
+  *
+  * Copyright (C) 2002 Intel
+- * Copyright (C) Jenna Hall (jenna.s.hall at intel.com)
++ * Copyright (C) Jenna Hall <jenna.s.hall at intel.com>
+  *
+  * Copyright (C) 2001 Intel
+- * Copyright (C) Fred Lewis (frederick.v.lewis at intel.com)
++ * Copyright (C) Fred Lewis <frederick.v.lewis at intel.com>
+  *
+  * Copyright (C) 2000 Intel
+- * Copyright (C) Chuck Fleckenstein (cfleck at co.intel.com)
++ * Copyright (C) Chuck Fleckenstein <cfleck at co.intel.com>
+  *
+  * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
+- * Copyright (C) Vijay Chander(vijay at engr.sgi.com)
++ * Copyright (C) Vijay Chander <vijay at engr.sgi.com>
+  *
+- * 03/04/15 D. Mosberger Added INIT backtrace support.
+- * 02/03/25 M. Domsch	GUID cleanups
++ * Copyright (C) 2006 FUJITSU LIMITED
++ * Copyright (C) Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+  *
+- * 02/01/04 J. Hall	Aligned MCA stack to 16 bytes, added platform vs. CPU
+- *			error flag, set SAL default return values, changed
+- *			error record structure to linked list, added init call
+- *			to sal_get_state_info_size().
++ * 2000-03-29 Chuck Fleckenstein <cfleck at co.intel.com>
++ *	      Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
++ *	      added min save state dump, added INIT handler.
+  *
+- * 01/01/03 F. Lewis    Added setup of CMCI and CPEI IRQs, logging of corrected
+- *                      platform errors, completed code for logging of
+- *                      corrected & uncorrected machine check errors, and
+- *                      updated for conformance with Nov. 2000 revision of the
+- *                      SAL 3.0 spec.
+- * 00/03/29 C. Fleckenstein  Fixed PAL/SAL update issues, began MCA bug fixes, logging issues,
+- *                           added min save state dump, added INIT handler.
++ * 2001-01-03 Fred Lewis <frederick.v.lewis at intel.com>
++ *	      Added setup of CMCI and CPEI IRQs, logging of corrected platform
++ *	      errors, completed code for logging of corrected & uncorrected
++ *	      machine check errors, and updated for conformance with Nov. 2000
++ *	      revision of the SAL 3.0 spec.
++ *
++ * 2002-01-04 Jenna Hall <jenna.s.hall at intel.com>
++ *	      Aligned MCA stack to 16 bytes, added platform vs. CPU error flag,
++ *	      set SAL default return values, changed error record structure to
++ *	      linked list, added init call to sal_get_state_info_size().
++ *
++ * 2002-03-25 Matt Domsch <Matt_Domsch at dell.com>
++ *	      GUID cleanups.
++ *
++ * 2003-04-15 David Mosberger-Tang <davidm at hpl.hp.com>
++ *	      Added INIT backtrace support.
+  *
+  * 2003-12-08 Keith Owens <kaos at sgi.com>
+- *            smp_call_function() must not be called from interrupt context (can
+- *            deadlock on tasklist_lock).  Use keventd to call smp_call_function().
++ *	      smp_call_function() must not be called from interrupt context
++ *	      (can deadlock on tasklist_lock).
++ *	      Use keventd to call smp_call_function().
+  *
+  * 2004-02-01 Keith Owens <kaos at sgi.com>
+- *            Avoid deadlock when using printk() for MCA and INIT records.
+- *            Delete all record printing code, moved to salinfo_decode in user space.
+- *            Mark variables and functions static where possible.
+- *            Delete dead variables and functions.
+- *            Reorder to remove the need for forward declarations and to consolidate
+- *            related code.
++ *	      Avoid deadlock when using printk() for MCA and INIT records.
++ *	      Delete all record printing code, moved to salinfo_decode in user
++ *	      space.  Mark variables and functions static where possible.
++ *	      Delete dead variables and functions.  Reorder to remove the need
++ *	      for forward declarations and to consolidate related code.
+  *
+  * 2005-08-12 Keith Owens <kaos at sgi.com>
+- *	      Convert MCA/INIT handlers to use per event stacks and SAL/OS state.
++ *	      Convert MCA/INIT handlers to use per event stacks and SAL/OS
++ *	      state.
+  *
+  * 2005-10-07 Keith Owens <kaos at sgi.com>
+  *	      Add notify_die() hooks.
+  *
+  * 2006-09-15 Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+- * 	      Add printing support for MCA/INIT.
++ *	      Add printing support for MCA/INIT.
+  *
+  * 2007-04-27 Russ Anderson <rja at sgi.com>
+  *	      Support multiple cpus going through OS_MCA in the same event.
+diff --git a/arch/ia64/kernel/mca_asm.S b/arch/ia64/kernel/mca_asm.S
+index 0f5965f..8bc7d25 100644
+--- a/arch/ia64/kernel/mca_asm.S
++++ b/arch/ia64/kernel/mca_asm.S
+@@ -1,24 +1,28 @@
+-//
+-// assembly portion of the IA64 MCA handling
+-//
+-// Mods by cfleck to integrate into kernel build
+-// 00/03/15 davidm Added various stop bits to get a clean compile
+-//
+-// 00/03/29 cfleck Added code to save INIT handoff state in pt_regs format, switch to temp
+-//		   kstack, switch modes, jump to C INIT handler
+-//
+-// 02/01/04 J.Hall <jenna.s.hall at intel.com>
+-//		   Before entering virtual mode code:
+-//		   1. Check for TLB CPU error
+-//		   2. Restore current thread pointer to kr6
+-//		   3. Move stack ptr 16 bytes to conform to C calling convention
+-//
+-// 04/11/12 Russ Anderson <rja at sgi.com>
+-//		   Added per cpu MCA/INIT stack save areas.
+-//
+-// 12/08/05 Keith Owens <kaos at sgi.com>
+-//		   Use per cpu MCA/INIT stacks for all data.
+-//
++/*
++ * File:	mca_asm.S
++ * Purpose:	assembly portion of the IA64 MCA handling
++ *
++ * Mods by cfleck to integrate into kernel build
++ *
++ * 2000-03-15 David Mosberger-Tang <davidm at hpl.hp.com>
++ *		Added various stop bits to get a clean compile
++ *
++ * 2000-03-29 Chuck Fleckenstein <cfleck at co.intel.com>
++ *		Added code to save INIT handoff state in pt_regs format,
++ *		switch to temp kstack, switch modes, jump to C INIT handler
++ *
++ * 2002-01-04 J.Hall <jenna.s.hall at intel.com>
++ *		Before entering virtual mode code:
++ *		 1. Check for TLB CPU error
++ *		 2. Restore current thread pointer to kr6
++ *		 3. Move stack ptr 16 bytes to conform to C calling convention
++ *
++ * 2004-11-12 Russ Anderson <rja at sgi.com>
++ *		Added per cpu MCA/INIT stack save areas.
++ *
++ * 2005-12-08 Keith Owens <kaos at sgi.com>
++ *		Use per cpu MCA/INIT stacks for all data.
++ */
+ #include <linux/threads.h>
+ 
+ #include <asm/asmmacro.h>
+diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
+index aba813c..fab1d21 100644
+--- a/arch/ia64/kernel/mca_drv.c
++++ b/arch/ia64/kernel/mca_drv.c
+@@ -3,7 +3,7 @@
+  * Purpose:	Generic MCA handling layer
+  *
+  * Copyright (C) 2004 FUJITSU LIMITED
+- * Copyright (C) Hidetoshi Seto (seto.hidetoshi at jp.fujitsu.com)
++ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+  * Copyright (C) 2005 Silicon Graphics, Inc
+  * Copyright (C) 2005 Keith Owens <kaos at sgi.com>
+  * Copyright (C) 2006 Russ Anderson <rja at sgi.com>
+diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h
+index 485e34d..53b8ecb 100644
+--- a/arch/ia64/kernel/mca_drv.h
++++ b/arch/ia64/kernel/mca_drv.h
+@@ -3,7 +3,7 @@
+  * Purpose:	Define helpers for Generic MCA handling
+  *
+  * Copyright (C) 2004 FUJITSU LIMITED
+- * Copyright (C) Hidetoshi Seto (seto.hidetoshi at jp.fujitsu.com)
++ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+  */
+ /*
+  * Processor error section:
+diff --git a/arch/ia64/kernel/mca_drv_asm.S b/arch/ia64/kernel/mca_drv_asm.S
+index 3bccb06..767ac2c 100644
+--- a/arch/ia64/kernel/mca_drv_asm.S
++++ b/arch/ia64/kernel/mca_drv_asm.S
+@@ -3,7 +3,7 @@
+  * Purpose:     Assembly portion of Generic MCA handling
+  *
+  * Copyright (C) 2004 FUJITSU LIMITED
+- * Copyright (C) Hidetoshi Seto (seto.hidetoshi at jp.fujitsu.com)
++ * Copyright (C) 2004 Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
+  */
+ #include <linux/threads.h>
+ 
+diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
+index 1962879..e58f436 100644
+--- a/arch/ia64/kernel/module.c
++++ b/arch/ia64/kernel/module.c
+@@ -940,14 +940,3 @@ module_arch_cleanup (struct module *mod)
+ 	if (mod->arch.core_unw_table)
+ 		unw_remove_unwind_table(mod->arch.core_unw_table);
+ }
+-
+-#ifdef CONFIG_SMP
+-void
+-percpu_modcopy (void *pcpudst, const void *src, unsigned long size)
+-{
+-	unsigned int i;
+-	for_each_possible_cpu(i) {
+-		memcpy(pcpudst + __per_cpu_offset[i], src, size);
+-	}
+-}
+-#endif /* CONFIG_SMP */
+diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
+index 73e7c2e..78acd9f 100644
+--- a/arch/ia64/kernel/perfmon.c
++++ b/arch/ia64/kernel/perfmon.c
+@@ -2631,7 +2631,7 @@ pfm_task_incompatible(pfm_context_t *ctx, struct task_struct *task)
+ 	 */
+ 	if (task == current) return 0;
+ 
+-	if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
++	if (!task_is_stopped_or_traced(task)) {
+ 		DPRINT(("cannot attach to non-stopped task [%d] state=%ld\n", task_pid_nr(task), task->state));
+ 		return -EBUSY;
+ 	}
+@@ -2654,11 +2654,11 @@ pfm_get_task(pfm_context_t *ctx, pid_t pid, struct task_struct **task)
+ 	/* XXX: need to add more checks here */
+ 	if (pid < 2) return -EPERM;
+ 
+-	if (pid != current->pid) {
++	if (pid != task_pid_vnr(current)) {
+ 
+ 		read_lock(&tasklist_lock);
+ 
+-		p = find_task_by_pid(pid);
++		p = find_task_by_vpid(pid);
+ 
+ 		/* make sure task cannot go away while we operate on it */
+ 		if (p) get_task_struct(p);
+@@ -4792,7 +4792,7 @@ recheck:
+ 	 * the task must be stopped.
  	 */
  	if (PFM_CMD_STOPPED(cmd)) {
 -		if ((task->state != TASK_STOPPED) && (task->state != TASK_TRACED)) {
@@ -66584,8 +80488,46 @@
  			DPRINT(("[%d] task not in stopped state\n", task_pid_nr(task)));
  			return -EBUSY;
  		}
+@@ -5795,7 +5795,7 @@ pfm_proc_show(struct seq_file *m, void *v)
+ 	return 0;
+ }
+ 
+-struct seq_operations pfm_seq_ops = {
++const struct seq_operations pfm_seq_ops = {
+ 	.start =	pfm_proc_start,
+  	.next =		pfm_proc_next,
+  	.stop =		pfm_proc_stop,
+diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c
+index 27c2ef4..f44fe84 100644
+--- a/arch/ia64/kernel/sal.c
++++ b/arch/ia64/kernel/sal.c
+@@ -284,6 +284,7 @@ ia64_sal_cache_flush (u64 cache_type)
+ 	SAL_CALL(isrv, SAL_CACHE_FLUSH, cache_type, 0, 0, 0, 0, 0, 0);
+ 	return isrv.status;
+ }
++EXPORT_SYMBOL_GPL(ia64_sal_cache_flush);
+ 
+ void __init
+ ia64_sal_init (struct ia64_sal_systab *systab)
+@@ -372,3 +373,16 @@ ia64_sal_oemcall_reentrant(struct ia64_sal_retval *isrvp, u64 oemfunc,
+ 	return 0;
+ }
+ EXPORT_SYMBOL(ia64_sal_oemcall_reentrant);
++
++long
++ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
++		    unsigned long *drift_info)
++{
++	struct ia64_sal_retval isrv;
++
++	SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
++	*ticks_per_second = isrv.v0;
++	*drift_info = isrv.v1;
++	return isrv.status;
++}
++EXPORT_SYMBOL_GPL(ia64_sal_freq_base);
 diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
-index 4ac2b1f..86028c6 100644
+index 4ac2b1f..ebd1a09 100644
 --- a/arch/ia64/kernel/setup.c
 +++ b/arch/ia64/kernel/setup.c
 @@ -71,8 +71,6 @@ unsigned long __per_cpu_offset[NR_CPUS];
@@ -66606,6 +80548,37 @@
  #ifdef CONFIG_SMP
  	cpu_physical_id(0) = hard_smp_processor_id();
  #endif
+@@ -658,7 +654,7 @@ c_stop (struct seq_file *m, void *v)
+ {
+ }
+ 
+-struct seq_operations cpuinfo_op = {
++const struct seq_operations cpuinfo_op = {
+ 	.start =	c_start,
+ 	.next =		c_next,
+ 	.stop =		c_stop,
+diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
+index f0fc4d8..480b1a5 100644
+--- a/arch/ia64/kernel/smpboot.c
++++ b/arch/ia64/kernel/smpboot.c
+@@ -767,17 +767,6 @@ void __cpu_die(unsigned int cpu)
+ 	}
+  	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+ }
+-#else /* !CONFIG_HOTPLUG_CPU */
+-int __cpu_disable(void)
+-{
+-	return -ENOSYS;
+-}
+-
+-void __cpu_die(unsigned int cpu)
+-{
+-	/* We said "no" in __cpu_disable */
+-	BUG();
+-}
+ #endif /* CONFIG_HOTPLUG_CPU */
+ 
+ void
 diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
 index 2bb8421..3ab0427 100644
 --- a/arch/ia64/kernel/time.c
@@ -66700,6 +80673,152 @@
  		memset(&all_cpu_cache_info[cpu].kobj,
  			0,
  			sizeof(struct kobject));
+diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
+index 78d65cb..f0cda76 100644
+--- a/arch/ia64/kernel/traps.c
++++ b/arch/ia64/kernel/traps.c
+@@ -35,7 +35,7 @@ trap_init (void)
+ 		fpswa_interface = __va(ia64_boot_param->fpswa);
+ }
+ 
+-void
++int
+ die (const char *str, struct pt_regs *regs, long err)
+ {
+ 	static struct {
+@@ -62,8 +62,11 @@ die (const char *str, struct pt_regs *regs, long err)
+ 	if (++die.lock_owner_depth < 3) {
+ 		printk("%s[%d]: %s %ld [%d]\n",
+ 		current->comm, task_pid_nr(current), str, err, ++die_counter);
+-		(void) notify_die(DIE_OOPS, (char *)str, regs, err, 255, SIGSEGV);
+-		show_regs(regs);
++		if (notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV)
++	            != NOTIFY_STOP)
++			show_regs(regs);
++		else
++			regs = NULL;
+   	} else
+ 		printk(KERN_ERR "Recursive die() failure, output suppressed\n");
+ 
+@@ -72,17 +75,22 @@ die (const char *str, struct pt_regs *regs, long err)
+ 	add_taint(TAINT_DIE);
+ 	spin_unlock_irq(&die.lock);
+ 
++	if (!regs)
++		return 1;
++
+ 	if (panic_on_oops)
+ 		panic("Fatal exception");
+ 
+   	do_exit(SIGSEGV);
++	return 0;
+ }
+ 
+-void
++int
+ die_if_kernel (char *str, struct pt_regs *regs, long err)
+ {
+ 	if (!user_mode(regs))
+-		die(str, regs, err);
++		return die(str, regs, err);
++	return 0;
+ }
+ 
+ void
+@@ -102,7 +110,8 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
+ 		if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
+ 			       	== NOTIFY_STOP)
+ 			return;
+-		die_if_kernel("bugcheck!", regs, break_num);
++		if (die_if_kernel("bugcheck!", regs, break_num))
++			return;
+ 		sig = SIGILL; code = ILL_ILLOPC;
+ 		break;
+ 
+@@ -155,8 +164,9 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
+ 		break;
+ 
+ 	      default:
+-		if (break_num < 0x40000 || break_num > 0x100000)
+-			die_if_kernel("Bad break", regs, break_num);
++		if ((break_num < 0x40000 || break_num > 0x100000)
++		    && die_if_kernel("Bad break", regs, break_num))
++			return;
+ 
+ 		if (break_num < 0x80000) {
+ 			sig = SIGILL; code = __ILL_BREAK;
+@@ -402,14 +412,15 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
+ #endif
+ 
+ 	sprintf(buf, "IA-64 Illegal operation fault");
+-	die_if_kernel(buf, &regs, 0);
++	rv.fkt = 0;
++	if (die_if_kernel(buf, &regs, 0))
++		return rv;
+ 
+ 	memset(&si, 0, sizeof(si));
+ 	si.si_signo = SIGILL;
+ 	si.si_code = ILL_ILLOPC;
+ 	si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(&regs)->ri);
+ 	force_sig_info(SIGILL, &si, current);
+-	rv.fkt = 0;
+ 	return rv;
+ }
+ 
+@@ -644,6 +655,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
+ 		sprintf(buf, "Fault %lu", vector);
+ 		break;
+ 	}
+-	die_if_kernel(buf, &regs, error);
+-	force_sig(SIGILL, current);
++	if (!die_if_kernel(buf, &regs, error))
++		force_sig(SIGILL, current);
+ }
+diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c
+index f6a1aeb..52f70bb 100644
+--- a/arch/ia64/kernel/unaligned.c
++++ b/arch/ia64/kernel/unaligned.c
+@@ -23,7 +23,7 @@
+ #include <asm/uaccess.h>
+ #include <asm/unaligned.h>
+ 
+-extern void die_if_kernel(char *str, struct pt_regs *regs, long err);
++extern int die_if_kernel(char *str, struct pt_regs *regs, long err);
+ 
+ #undef DEBUG_UNALIGNED_TRAP
+ 
+@@ -675,8 +675,9 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi
+ 	 */
+ 	if (ld.x6_op == 1 || ld.x6_op == 3) {
+ 		printk(KERN_ERR "%s: register update on speculative load, error\n", __FUNCTION__);
+-		die_if_kernel("unaligned reference on speculative load with register update\n",
+-			      regs, 30);
++		if (die_if_kernel("unaligned reference on speculative load with register update\n",
++				  regs, 30))
++			return;
+ 	}
+ 
+ 
+@@ -1317,7 +1318,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
+ 
+ 	if (ia64_psr(regs)->be) {
+ 		/* we don't support big-endian accesses */
+-		die_if_kernel("big-endian unaligned accesses are not supported", regs, 0);
++		if (die_if_kernel("big-endian unaligned accesses are not supported", regs, 0))
++			return;
+ 		goto force_sigbus;
+ 	}
+ 
+@@ -1534,7 +1536,8 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
+ 			ia64_handle_exception(regs, eh);
+ 			goto done;
+ 		}
+-		die_if_kernel("error during unaligned kernel access\n", regs, ret);
++		if (die_if_kernel("error during unaligned kernel access\n", regs, ret))
++			return;
+ 		/* NOT_REACHED */
+ 	}
+   force_sigbus:
 diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S
 index 757e419..80622ac 100644
 --- a/arch/ia64/kernel/vmlinux.lds.S
@@ -66730,6 +80849,33 @@
  
  #ifdef CONFIG_BLK_DEV_INITRD
    .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET)
+diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
+index 7571076..3e69881 100644
+--- a/arch/ia64/mm/fault.c
++++ b/arch/ia64/mm/fault.c
+@@ -16,7 +16,7 @@
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ 
+-extern void die (char *, struct pt_regs *, long);
++extern int die(char *, struct pt_regs *, long);
+ 
+ #ifdef CONFIG_KPROBES
+ static inline int notify_page_fault(struct pt_regs *regs, int trap)
+@@ -267,9 +267,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
+ 	else
+ 		printk(KERN_ALERT "Unable to handle kernel paging request at "
+ 		       "virtual address %016lx\n", address);
+-	die("Oops", regs, isr);
++	if (die("Oops", regs, isr))
++		regs = NULL;
+ 	bust_spinlocks(0);
+-	do_exit(SIGKILL);
++	if (regs)
++		do_exit(SIGKILL);
+ 	return;
+ 
+   out_of_memory:
 diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
 index 1f38a3a..bb1d249 100644
 --- a/arch/ia64/sn/kernel/setup.c
@@ -66766,11 +80912,84 @@
  	printk("SGI SAL version %x.%02x\n", version >> 8, version & 0x00FF);
  
  	/*
+diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c
+index f3c6932..dfc6bf1 100644
+--- a/arch/ia64/sn/kernel/sn2/sn2_smp.c
++++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c
+@@ -523,7 +523,7 @@ static ssize_t sn2_ptc_proc_write(struct file *file, const char __user *user, si
+ 	return count;
+ }
+ 
+-static struct seq_operations sn2_ptc_seq_ops = {
++static const struct seq_operations sn2_ptc_seq_ops = {
+ 	.start = sn2_ptc_seq_start,
+ 	.next = sn2_ptc_seq_next,
+ 	.stop = sn2_ptc_seq_stop,
+diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+index 1a8e496..4b0d153 100644
+--- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c
++++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c
+@@ -33,6 +33,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/nodemask.h>
+ #include <linux/smp.h>
++#include <linux/mutex.h>
+ 
+ #include <asm/processor.h>
+ #include <asm/topology.h>
+@@ -50,7 +51,7 @@ static void *sn_hwperf_salheap = NULL;
+ static int sn_hwperf_obj_cnt = 0;
+ static nasid_t sn_hwperf_master_nasid = INVALID_NASID;
+ static int sn_hwperf_init(void);
+-static DECLARE_MUTEX(sn_hwperf_init_mutex);
++static DEFINE_MUTEX(sn_hwperf_init_mutex);
+ 
+ #define cnode_possible(n)	((n) < num_cnodes)
+ 
+@@ -577,7 +578,7 @@ static void sn_topology_stop(struct seq_file *m, void *v)
+ /*
+  * /proc/sgi_sn/sn_topology, read-only using seq_file
+  */
+-static struct seq_operations sn_topology_seq_ops = {
++static const struct seq_operations sn_topology_seq_ops = {
+ 	.start = sn_topology_start,
+ 	.next = sn_topology_next,
+ 	.stop = sn_topology_stop,
+@@ -884,10 +885,10 @@ static int sn_hwperf_init(void)
+ 	int e = 0;
+ 
+ 	/* single threaded, once-only initialization */
+-	down(&sn_hwperf_init_mutex);
++	mutex_lock(&sn_hwperf_init_mutex);
+ 
+ 	if (sn_hwperf_salheap) {
+-		up(&sn_hwperf_init_mutex);
++		mutex_unlock(&sn_hwperf_init_mutex);
+ 		return e;
+ 	}
+ 
+@@ -936,7 +937,7 @@ out:
+ 		sn_hwperf_salheap = NULL;
+ 		sn_hwperf_obj_cnt = 0;
+ 	}
+-	up(&sn_hwperf_init_mutex);
++	mutex_unlock(&sn_hwperf_init_mutex);
+ 	return e;
+ }
+ 
 diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
-index ab9a264..49326e9 100644
+index ab9a264..795180b 100644
 --- a/arch/m32r/Kconfig
 +++ b/arch/m32r/Kconfig
-@@ -235,6 +235,11 @@ config IRAM_SIZE
+@@ -8,6 +8,7 @@ mainmenu "Linux/M32R Kernel Configuration"
+ config M32R
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
+ 
+ config SBUS
+ 	bool
+@@ -235,6 +236,11 @@ config IRAM_SIZE
  # Define implied options from the CPU selection here
  #
  
@@ -66782,6 +81001,16 @@
  config RWSEM_GENERIC_SPINLOCK
  	bool
  	depends on M32R
+@@ -297,8 +303,7 @@ config SMP
+ 	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+ 	  Management" code will be disabled if you say Y here.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  and the SMP-HOWTO available at
++	  See also the SMP-HOWTO available at
+ 	  <http://www.linuxdoc.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
 @@ -354,11 +359,6 @@ config PCI
  	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
  	  VESA. If you have PCI, say Y, otherwise N.
@@ -66794,6 +81023,62 @@
  choice
  	prompt "PCI access mode"
  	depends on PCI
+@@ -426,8 +426,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/m32r/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
+index ee3c8be..01d877c 100644
+--- a/arch/m32r/boot/compressed/m32r_sio.c
++++ b/arch/m32r/boot/compressed/m32r_sio.c
+@@ -17,7 +17,7 @@ static int puts(const char *s)
+ 	return 0;
+ }
+ 
+-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
++#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_OPSPUT)
+ #include <asm/m32r.h>
+ #include <asm/io.h>
+ 
+@@ -52,7 +52,7 @@ static void putc(char c)
+ 	}
+ 	*BOOT_SIO0TXB = c;
+ }
+-#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
++#else /* !(CONFIG_PLAT_M32700UT) */
+ #if defined(CONFIG_PLAT_MAPPI2)
+ #define SIO0STS	(volatile unsigned short *)(0xa0efd000 + 14)
+ #define SIO0TXB	(volatile unsigned short *)(0xa0efd000 + 30)
+diff --git a/arch/m32r/kernel/ptrace.c b/arch/m32r/kernel/ptrace.c
+index ed4d075..9aa615d 100644
+--- a/arch/m32r/kernel/ptrace.c
++++ b/arch/m32r/kernel/ptrace.c
+@@ -476,7 +476,7 @@ unregister_debug_trap(struct task_struct *child, unsigned long addr,
+ 		return 0;
+ 	}
+ 
+-	/* Recover orignal instruction code. */
++	/* Recover original instruction code. */
+ 	*code = p->insn[i];
+ 
+ 	/* Shift debug trap entries. */
+diff --git a/arch/m32r/kernel/syscall_table.S b/arch/m32r/kernel/syscall_table.S
+index 95aa798..aa3bf4c 100644
+--- a/arch/m32r/kernel/syscall_table.S
++++ b/arch/m32r/kernel/syscall_table.S
+@@ -321,6 +321,6 @@ ENTRY(sys_call_table)
+ 	.long sys_epoll_pwait
+ 	.long sys_utimensat		/* 320 */
+ 	.long sys_signalfd
+-	.long sys_timerfd
++	.long sys_ni_syscall
+ 	.long sys_eventfd
+ 	.long sys_fallocate
 diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S
 index 942a8c7..41b0785 100644
 --- a/arch/m32r/kernel/vmlinux.lds.S
@@ -66834,7 +81119,7 @@
  	}
  
 diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
-index 01dee84..24e6bc0 100644
+index 01dee84..ffabd01 100644
 --- a/arch/m68k/Kconfig
 +++ b/arch/m68k/Kconfig
 @@ -145,11 +145,6 @@ config PCI
@@ -66849,6 +81134,655 @@
  config MAC
  	bool "Macintosh support"
  	depends on !MMU_SUN3
+@@ -582,20 +577,6 @@ config MAC_HID
+ 	depends on INPUT_ADBHID
+ 	default y
+ 
+-config MAC_ADBKEYCODES
+-	bool "Support for ADB raw keycodes"
+-	depends on INPUT_ADBHID
+-	help
+-	  This provides support for sending raw ADB keycodes to console
+-	  devices.  This is the default up to 2.4.0, but in future this may be
+-	  phased out in favor of generic Linux keycodes.  If you say Y here,
+-	  you can dynamically switch via the
+-	  /proc/sys/dev/mac_hid/keyboard_sends_linux_keycodes
+-	  sysctl and with the "keyboard_sends_linux_keycodes=" kernel
+-	  argument.
+-
+-	  If unsure, say Y here.
+-
+ config ADB_KEYBOARD
+ 	bool "Support for ADB keyboard (old driver)"
+ 	depends on MAC && !INPUT_ADBHID
+@@ -683,8 +664,6 @@ endmenu
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/m68k/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/m68k/Makefile b/arch/m68k/Makefile
+index 4a1bd44..2cba605 100644
+--- a/arch/m68k/Makefile
++++ b/arch/m68k/Makefile
+@@ -13,16 +13,15 @@
+ # Copyright (C) 1994 by Hamish Macdonald
+ #
+ 
+-# test for cross compiling
+-COMPILE_ARCH = $(shell uname -m)
+-
+ # override top level makefile
+ AS += -m68020
+ LDFLAGS := -m m68kelf
+ LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
+-ifneq ($(COMPILE_ARCH),$(ARCH))
+-	# prefix for cross-compiling binaries
+-	CROSS_COMPILE = m68k-linux-gnu-
++ifneq ($(SUBARCH),$(ARCH))
++	ifeq ($(CROSS_COMPILE),)
++		CROSS_COMPILE := $(call cc-cross-prefix, \
++			m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
++	endif
+ endif
+ 
+ ifdef CONFIG_SUN3
+diff --git a/arch/m68k/amiga/Makefile b/arch/m68k/amiga/Makefile
+index 8b41565..6a0d765 100644
+--- a/arch/m68k/amiga/Makefile
++++ b/arch/m68k/amiga/Makefile
+@@ -2,6 +2,6 @@
+ # Makefile for Linux arch/m68k/amiga source directory
+ #
+ 
+-obj-y		:= config.o amiints.o cia.o chipram.o amisound.o amiga_ksyms.o
++obj-y		:= config.o amiints.o cia.o chipram.o amisound.o
+ 
+ obj-$(CONFIG_AMIGA_PCMCIA)	+= pcmcia.o
+diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c
+deleted file mode 100644
+index 7fdcf6b..0000000
+--- a/arch/m68k/amiga/amiga_ksyms.c
++++ /dev/null
+@@ -1,33 +0,0 @@
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <asm/ptrace.h>
+-#include <asm/amigahw.h>
+-#include <asm/amigaints.h>
+-#include <asm/amipcmcia.h>
+-
+-extern volatile u_short amiga_audio_min_period;
+-extern u_short amiga_audio_period;
+-
+-/*
+- * Add things here when you find the need for it.
+- */
+-EXPORT_SYMBOL(amiga_model);
+-EXPORT_SYMBOL(amiga_chipset);
+-EXPORT_SYMBOL(amiga_hw_present);
+-EXPORT_SYMBOL(amiga_eclock);
+-EXPORT_SYMBOL(amiga_colorclock);
+-EXPORT_SYMBOL(amiga_chip_alloc);
+-EXPORT_SYMBOL(amiga_chip_free);
+-EXPORT_SYMBOL(amiga_chip_avail);
+-EXPORT_SYMBOL(amiga_chip_size);
+-EXPORT_SYMBOL(amiga_audio_period);
+-EXPORT_SYMBOL(amiga_audio_min_period);
+-
+-#ifdef CONFIG_AMIGA_PCMCIA
+-  EXPORT_SYMBOL(pcmcia_reset);
+-  EXPORT_SYMBOL(pcmcia_copy_tuple);
+-  EXPORT_SYMBOL(pcmcia_program_voltage);
+-  EXPORT_SYMBOL(pcmcia_access_speed);
+-  EXPORT_SYMBOL(pcmcia_write_enable);
+-  EXPORT_SYMBOL(pcmcia_write_disable);
+-#endif
+diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c
+index 1f5bfb5..61e5c54 100644
+--- a/arch/m68k/amiga/amisound.c
++++ b/arch/m68k/amiga/amisound.c
+@@ -12,6 +12,7 @@
+ #include <linux/timer.h>
+ #include <linux/init.h>
+ #include <linux/string.h>
++#include <linux/module.h>
+ 
+ #include <asm/system.h>
+ #include <asm/amigahw.h>
+@@ -21,7 +22,7 @@ static const signed char sine_data[] = {
+ 	0,  39,  75,  103,  121,  127,  121,  103,  75,  39,
+ 	0, -39, -75, -103, -121, -127, -121, -103, -75, -39
+ };
+-#define DATA_SIZE	(sizeof(sine_data)/sizeof(sine_data[0]))
++#define DATA_SIZE	ARRAY_SIZE(sine_data)
+ 
+ #define custom amiga_custom
+ 
+@@ -31,6 +32,7 @@ static const signed char sine_data[] = {
+      */
+ 
+ volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
++EXPORT_SYMBOL(amiga_audio_min_period);
+ 
+ #define MAX_PERIOD	(65535)
+ 
+@@ -40,6 +42,7 @@ volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
+      */
+ 
+ unsigned short amiga_audio_period = MAX_PERIOD;
++EXPORT_SYMBOL(amiga_audio_period);
+ 
+ static unsigned long clock_constant;
+ 
+diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
+index fa015d8..d10726f 100644
+--- a/arch/m68k/amiga/chipram.c
++++ b/arch/m68k/amiga/chipram.c
+@@ -13,10 +13,13 @@
+ #include <linux/ioport.h>
+ #include <linux/slab.h>
+ #include <linux/string.h>
++#include <linux/module.h>
++
+ #include <asm/page.h>
+ #include <asm/amigahw.h>
+ 
+ unsigned long amiga_chip_size;
++EXPORT_SYMBOL(amiga_chip_size);
+ 
+ static struct resource chipram_res = {
+     .name = "Chip RAM", .start = CHIP_PHYSADDR
+@@ -67,6 +70,7 @@ void *amiga_chip_alloc(unsigned long size, const char *name)
+ #endif
+     return (void *)ZTWO_VADDR(res->start);
+ }
++EXPORT_SYMBOL(amiga_chip_alloc);
+ 
+ 
+     /*
+@@ -120,6 +124,7 @@ void amiga_chip_free(void *ptr)
+     }
+     printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr);
+ }
++EXPORT_SYMBOL(amiga_chip_free);
+ 
+ 
+ unsigned long amiga_chip_avail(void)
+@@ -129,3 +134,5 @@ unsigned long amiga_chip_avail(void)
+ #endif
+ 	return chipavail;
+ }
++EXPORT_SYMBOL(amiga_chip_avail);
++
+diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
+index 3574853..50f5daa 100644
+--- a/arch/m68k/amiga/config.c
++++ b/arch/m68k/amiga/config.c
+@@ -23,6 +23,7 @@
+ #include <linux/delay.h>
+ #include <linux/interrupt.h>
+ #include <linux/zorro.h>
++#include <linux/module.h>
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/setup.h>
+@@ -36,13 +37,24 @@
+ #include <asm/io.h>
+ 
+ unsigned long amiga_model;
++EXPORT_SYMBOL(amiga_model);
++
+ unsigned long amiga_eclock;
++EXPORT_SYMBOL(amiga_eclock);
++
+ unsigned long amiga_masterclock;
++
+ unsigned long amiga_colorclock;
++EXPORT_SYMBOL(amiga_colorclock);
++
+ unsigned long amiga_chipset;
++EXPORT_SYMBOL(amiga_chipset);
++
+ unsigned char amiga_vblank;
+ unsigned char amiga_psfreq;
++
+ struct amiga_hw_present amiga_hw_present;
++EXPORT_SYMBOL(amiga_hw_present);
+ 
+ static char s_a500[] __initdata = "A500";
+ static char s_a500p[] __initdata = "A500+";
+diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c
+index 186662c..7106f0c 100644
+--- a/arch/m68k/amiga/pcmcia.c
++++ b/arch/m68k/amiga/pcmcia.c
+@@ -15,6 +15,8 @@
+ #include <linux/types.h>
+ #include <linux/jiffies.h>
+ #include <linux/timer.h>
++#include <linux/module.h>
++
+ #include <asm/amigayle.h>
+ #include <asm/amipcmcia.h>
+ 
+@@ -30,6 +32,7 @@ void pcmcia_reset(void)
+ 	while (time_before(jiffies, reset_start_time + 1*HZ/100));
+ 	b = gayle_reset;
+ }
++EXPORT_SYMBOL(pcmcia_reset);
+ 
+ 
+ /* copy a tuple, including tuple header. return nb bytes copied */
+@@ -61,6 +64,7 @@ int pcmcia_copy_tuple(unsigned char tuple_id, void *tuple, int max_len)
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL(pcmcia_copy_tuple);
+ 
+ void pcmcia_program_voltage(int voltage)
+ {
+@@ -84,6 +88,7 @@ void pcmcia_program_voltage(int voltage)
+ 	gayle.config = cfg_byte;
+ 
+ }
++EXPORT_SYMBOL(pcmcia_program_voltage);
+ 
+ void pcmcia_access_speed(int speed)
+ {
+@@ -101,13 +106,17 @@ void pcmcia_access_speed(int speed)
+ 	cfg_byte = (cfg_byte & 0xf3) | s;
+ 	gayle.config = cfg_byte;
+ }
++EXPORT_SYMBOL(pcmcia_access_speed);
+ 
+ void pcmcia_write_enable(void)
+ {
+ 	gayle.cardstatus = GAYLE_CS_WR|GAYLE_CS_DA;
+ }
++EXPORT_SYMBOL(pcmcia_write_enable);
+ 
+ void pcmcia_write_disable(void)
+ {
+ 	gayle.cardstatus = 0;
+ }
++EXPORT_SYMBOL(pcmcia_write_disable);
++
+diff --git a/arch/m68k/atari/Makefile b/arch/m68k/atari/Makefile
+index 2cb8619..2cd905e 100644
+--- a/arch/m68k/atari/Makefile
++++ b/arch/m68k/atari/Makefile
+@@ -3,7 +3,7 @@
+ #
+ 
+ obj-y		:= config.o time.o debug.o ataints.o stdma.o \
+-			atasound.o stram.o atari_ksyms.o
++			atasound.o stram.o
+ 
+ ifeq ($(CONFIG_PCI),y)
+ obj-$(CONFIG_HADES)	+= hades-pci.o
+diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
+index b85ca22..b45593a 100644
+--- a/arch/m68k/atari/ataints.c
++++ b/arch/m68k/atari/ataints.c
+@@ -40,6 +40,7 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/init.h>
+ #include <linux/seq_file.h>
++#include <linux/module.h>
+ 
+ #include <asm/system.h>
+ #include <asm/traps.h>
+@@ -446,6 +447,7 @@ unsigned long atari_register_vme_int(void)
+ 	free_vme_vec_bitmap |= 1 << i;
+ 	return VME_SOURCE_BASE + i;
+ }
++EXPORT_SYMBOL(atari_register_vme_int);
+ 
+ 
+ void atari_unregister_vme_int(unsigned long irq)
+@@ -455,5 +457,6 @@ void atari_unregister_vme_int(unsigned long irq)
+ 		free_vme_vec_bitmap &= ~(1 << irq);
+ 	}
+ }
++EXPORT_SYMBOL(atari_unregister_vme_int);
+ 
+ 
+diff --git a/arch/m68k/atari/atari_ksyms.c b/arch/m68k/atari/atari_ksyms.c
+deleted file mode 100644
+index a047571..0000000
+--- a/arch/m68k/atari/atari_ksyms.c
++++ /dev/null
+@@ -1,35 +0,0 @@
+-#include <linux/module.h>
+-
+-#include <asm/ptrace.h>
+-#include <asm/traps.h>
+-#include <asm/atarihw.h>
+-#include <asm/atariints.h>
+-#include <asm/atarikb.h>
+-#include <asm/atari_joystick.h>
+-#include <asm/atari_stdma.h>
+-#include <asm/atari_stram.h>
+-
+-extern void atari_microwire_cmd( int cmd );
+-extern int atari_MFP_init_done;
+-extern int atari_SCC_init_done;
+-extern int atari_SCC_reset_done;
+-
+-EXPORT_SYMBOL(atari_mch_cookie);
+-EXPORT_SYMBOL(atari_mch_type);
+-EXPORT_SYMBOL(atari_hw_present);
+-EXPORT_SYMBOL(atari_switches);
+-EXPORT_SYMBOL(atari_dont_touch_floppy_select);
+-EXPORT_SYMBOL(atari_register_vme_int);
+-EXPORT_SYMBOL(atari_unregister_vme_int);
+-EXPORT_SYMBOL(stdma_lock);
+-EXPORT_SYMBOL(stdma_release);
+-EXPORT_SYMBOL(stdma_others_waiting);
+-EXPORT_SYMBOL(stdma_islocked);
+-EXPORT_SYMBOL(atari_stram_alloc);
+-EXPORT_SYMBOL(atari_stram_free);
+-
+-EXPORT_SYMBOL(atari_MFP_init_done);
+-EXPORT_SYMBOL(atari_SCC_init_done);
+-EXPORT_SYMBOL(atari_SCC_reset_done);
+-
+-EXPORT_SYMBOL(atari_microwire_cmd);
+diff --git a/arch/m68k/atari/atasound.c b/arch/m68k/atari/atasound.c
+index ee04250..d266fe8 100644
+--- a/arch/m68k/atari/atasound.c
++++ b/arch/m68k/atari/atasound.c
+@@ -22,6 +22,7 @@
+ #include <linux/fcntl.h>
+ #include <linux/errno.h>
+ #include <linux/mm.h>
++#include <linux/module.h>
+ 
+ #include <asm/atarihw.h>
+ #include <asm/system.h>
+@@ -43,6 +44,7 @@ void atari_microwire_cmd (int cmd)
+ 	while( tt_microwire.mask != 0x7ff)
+ 		;
+ }
++EXPORT_SYMBOL(atari_microwire_cmd);
+ 
+ 
+ /* PSG base frequency */
+diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
+index e40e5dc..5945e15 100644
+--- a/arch/m68k/atari/config.c
++++ b/arch/m68k/atari/config.c
+@@ -31,6 +31,7 @@
+ #include <linux/delay.h>
+ #include <linux/ioport.h>
+ #include <linux/vt_kern.h>
++#include <linux/module.h>
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/setup.h>
+@@ -43,10 +44,20 @@
+ #include <asm/io.h>
+ 
+ u_long atari_mch_cookie;
++EXPORT_SYMBOL(atari_mch_cookie);
++
+ u_long atari_mch_type;
++EXPORT_SYMBOL(atari_mch_type);
++
+ struct atari_hw_present atari_hw_present;
++EXPORT_SYMBOL(atari_hw_present);
++
+ u_long atari_switches;
++EXPORT_SYMBOL(atari_switches);
++
+ int atari_dont_touch_floppy_select;
++EXPORT_SYMBOL(atari_dont_touch_floppy_select);
++
+ int atari_rtc_year_offset;
+ 
+ /* local function prototypes */
+diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
+index fbeed8c..043ddbc 100644
+--- a/arch/m68k/atari/debug.c
++++ b/arch/m68k/atari/debug.c
+@@ -15,17 +15,23 @@
+ #include <linux/console.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
++#include <linux/module.h>
+ 
+ #include <asm/atarihw.h>
+ #include <asm/atariints.h>
+ 
+ /* Flag that Modem1 port is already initialized and used */
+ int atari_MFP_init_done;
++EXPORT_SYMBOL(atari_MFP_init_done);
++
+ /* Flag that Modem1 port is already initialized and used */
+ int atari_SCC_init_done;
++EXPORT_SYMBOL(atari_SCC_init_done);
++
+ /* Can be set somewhere, if a SCC master reset has already be done and should
+  * not be repeated; used by kgdb */
+ int atari_SCC_reset_done;
++EXPORT_SYMBOL(atari_SCC_reset_done);
+ 
+ static struct console atari_console_driver = {
+ 	.name	= "debug",
+diff --git a/arch/m68k/atari/hades-pci.c b/arch/m68k/atari/hades-pci.c
+index bee2b14..2bbabc0 100644
+--- a/arch/m68k/atari/hades-pci.c
++++ b/arch/m68k/atari/hades-pci.c
+@@ -376,8 +376,8 @@ struct pci_bus_info * __init init_hades_pci(void)
+ 	 */
+ 
+ 	bus = kzalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
+-	if (!bus)
+-		return NULL;
++	if (unlikely(!bus))
++		goto iounmap_base_virt;
+ 
+ 	/*
+ 	 * Claim resources. The m68k has no separate I/O space, both
+@@ -385,43 +385,25 @@ struct pci_bus_info * __init init_hades_pci(void)
+ 	 * the I/O resources are requested in memory space as well.
+ 	 */
+ 
+-	if (request_resource(&iomem_resource, &config_space) != 0)
+-	{
+-		kfree(bus);
+-		return NULL;
+-	}
++	if (unlikely(request_resource(&iomem_resource, &config_space) != 0))
++		goto free_bus;
+ 
+-	if (request_resource(&iomem_resource, &io_space) != 0)
+-	{
+-		release_resource(&config_space);
+-		kfree(bus);
+-		return NULL;
+-	}
++	if (unlikely(request_resource(&iomem_resource, &io_space) != 0))
++		goto release_config_space;
+ 
+ 	bus->mem_space.start = HADES_MEM_BASE;
+ 	bus->mem_space.end = HADES_MEM_BASE + HADES_MEM_SIZE - 1;
+ 	bus->mem_space.name = pci_mem_name;
+ #if 1
+-	if (request_resource(&iomem_resource, &bus->mem_space) != 0)
+-	{
+-		release_resource(&io_space);
+-		release_resource(&config_space);
+-		kfree(bus);
+-		return NULL;
+-	}
++	if (unlikely(request_resource(&iomem_resource, &bus->mem_space) != 0))
++		goto release_io_space;
+ #endif
+ 	bus->io_space.start = pci_io_base_virt;
+ 	bus->io_space.end = pci_io_base_virt + HADES_VIRT_IO_SIZE - 1;
+ 	bus->io_space.name = pci_io_name;
+ #if 1
+-	if (request_resource(&ioport_resource, &bus->io_space) != 0)
+-	{
+-		release_resource(&bus->mem_space);
+-		release_resource(&io_space);
+-		release_resource(&config_space);
+-		kfree(bus);
+-		return NULL;
+-	}
++	if (unlikely(request_resource(&ioport_resource, &bus->io_space) != 0))
++		goto release_bus_mem_space;
+ #endif
+ 	/*
+ 	 * Set hardware dependent functions.
+@@ -438,5 +420,21 @@ struct pci_bus_info * __init init_hades_pci(void)
+ 	tt_mfp.active_edge &= ~0x27;
+ 
+ 	return bus;
++
++release_bus_mem_space:
++	release_resource(&bus->mem_space);
++release_io_space:
++	release_resource(&io_space);
++release_config_space:
++	release_resource(&config_space);
++free_bus:
++	kfree(bus);
++iounmap_base_virt:
++	iounmap((void *)pci_io_base_virt);
++
++	for (i = 0; i < N_SLOTS; i++)
++		iounmap((void *)pci_conf_base_virt[i]);
++
++	return NULL;
+ }
+ #endif
+diff --git a/arch/m68k/atari/stdma.c b/arch/m68k/atari/stdma.c
+index ab3fd52..d1bd029 100644
+--- a/arch/m68k/atari/stdma.c
++++ b/arch/m68k/atari/stdma.c
+@@ -35,6 +35,7 @@
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/wait.h>
++#include <linux/module.h>
+ 
+ #include <asm/atari_stdma.h>
+ #include <asm/atariints.h>
+@@ -91,6 +92,7 @@ void stdma_lock(irq_handler_t handler, void *data)
+ 	stdma_isr_data = data;
+ 	local_irq_restore(flags);
+ }
++EXPORT_SYMBOL(stdma_lock);
+ 
+ 
+ /*
+@@ -117,6 +119,7 @@ void stdma_release(void)
+ 
+ 	local_irq_restore(flags);
+ }
++EXPORT_SYMBOL(stdma_release);
+ 
+ 
+ /*
+@@ -134,6 +137,7 @@ int stdma_others_waiting(void)
+ {
+ 	return waitqueue_active(&stdma_wait);
+ }
++EXPORT_SYMBOL(stdma_others_waiting);
+ 
+ 
+ /*
+@@ -155,6 +159,7 @@ int stdma_islocked(void)
+ {
+ 	return stdma_locked;
+ }
++EXPORT_SYMBOL(stdma_islocked);
+ 
+ 
+ /*
+diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
+index bf4588c..8dda651 100644
+--- a/arch/m68k/atari/stram.c
++++ b/arch/m68k/atari/stram.c
+@@ -20,6 +20,7 @@
+ #include <linux/bootmem.h>
+ #include <linux/mount.h>
+ #include <linux/blkdev.h>
++#include <linux/module.h>
+ 
+ #include <asm/setup.h>
+ #include <asm/machdep.h>
+@@ -208,6 +209,7 @@ void *atari_stram_alloc(long size, const char *owner)
+ 	}
+ 	return( addr );
+ }
++EXPORT_SYMBOL(atari_stram_alloc);
+ 
+ void atari_stram_free( void *addr )
+ 
+@@ -237,6 +239,7 @@ void atari_stram_free( void *addr )
+ 	printk( KERN_ERR "atari_stram_free: cannot free block at %p "
+ 			"(called from %p)\n", addr, __builtin_return_address(0) );
+ }
++EXPORT_SYMBOL(atari_stram_free);
+ 
+ 
+ /* ------------------------------------------------------------------------ */
+diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
+index 15b80ab..ff9dffa 100644
+--- a/arch/m68k/configs/mac_defconfig
++++ b/arch/m68k/configs/mac_defconfig
+@@ -678,7 +678,6 @@ CONFIG_LOGO_MAC_CLUT224=y
+ #
+ CONFIG_MAC_SCC=y
+ CONFIG_MAC_HID=y
+-CONFIG_MAC_ADBKEYCODES=y
+ CONFIG_SERIAL_CONSOLE=y
+ 
+ #
+diff --git a/arch/m68k/hp300/Makefile b/arch/m68k/hp300/Makefile
+index 288b9c6..96d4244 100644
+--- a/arch/m68k/hp300/Makefile
++++ b/arch/m68k/hp300/Makefile
+@@ -2,4 +2,4 @@
+ # Makefile for Linux arch/m68k/hp300 source directory
+ #
+ 
+-obj-y		:= ksyms.o config.o time.o reboot.o
++obj-y		:= config.o time.o reboot.o
+diff --git a/arch/m68k/hp300/ksyms.c b/arch/m68k/hp300/ksyms.c
+deleted file mode 100644
+index 8202830..0000000
+--- a/arch/m68k/hp300/ksyms.c
++++ /dev/null
+@@ -1,9 +0,0 @@
+-/*
+- *  linux/arch/m68k/hp300/ksyms.c
+- *
+- *  Copyright (C) 1998 Philip Blundell <philb at gnu.org>
+- *
+- *  This file contains the HP300-specific kernel symbols.  None yet. :-)
+- */
+-
+-#include <linux/module.h>
+diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S
+index 918f5db..6dfa3b3 100644
+--- a/arch/m68k/kernel/entry.S
++++ b/arch/m68k/kernel/entry.S
+@@ -742,7 +742,7 @@ sys_call_table:
+ 	.long sys_epoll_pwait		/* 315 */
+ 	.long sys_utimensat
+ 	.long sys_signalfd
+-	.long sys_timerfd
++	.long sys_ni_syscall
+ 	.long sys_eventfd
+ 	.long sys_fallocate		/* 320 */
+ 
 diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds
 index 59fe285..7537cc5 100644
 --- a/arch/m68k/kernel/vmlinux-std.lds
@@ -66905,8 +81839,110 @@
  	*(.exitcall.exit)
  	}
  
+diff --git a/arch/m68k/mac/Makefile b/arch/m68k/mac/Makefile
+index 995a09d..1d265ba 100644
+--- a/arch/m68k/mac/Makefile
++++ b/arch/m68k/mac/Makefile
+@@ -3,4 +3,4 @@
+ #
+ 
+ obj-y		:= config.o bootparse.o macints.o iop.o via.o oss.o psc.o \
+-			baboon.o macboing.o debug.o misc.o mac_ksyms.o
++			baboon.o macboing.o debug.o misc.o
+diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
+index 01b468b..735a49b 100644
+--- a/arch/m68k/mac/config.c
++++ b/arch/m68k/mac/config.c
+@@ -58,8 +58,6 @@ extern struct mem_info m68k_memory[NUM_MEMINFO];
+ 
+ extern struct mem_info m68k_ramdisk;
+ 
+-extern char m68k_command_line[CL_SIZE];
+-
+ void *mac_env;					/* Loaded by the boot asm */
+ 
+ /* The phys. video addr. - might be bogus on some machines */
+diff --git a/arch/m68k/mac/mac_ksyms.c b/arch/m68k/mac/mac_ksyms.c
+deleted file mode 100644
+index 6e37ceb..0000000
+--- a/arch/m68k/mac/mac_ksyms.c
++++ /dev/null
+@@ -1,8 +0,0 @@
+-#include <linux/module.h>
+-#include <asm/ptrace.h>
+-#include <asm/traps.h>
+-
+-/* Says whether we're using A/UX interrupts or not */
+-extern int via_alt_mapping;
+-
+-EXPORT_SYMBOL(via_alt_mapping);
+diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
+index 8df270e..fa485df 100644
+--- a/arch/m68k/mac/via.c
++++ b/arch/m68k/mac/via.c
+@@ -28,6 +28,7 @@
+ #include <linux/delay.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
++#include <linux/module.h>
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/macintosh.h>
+@@ -41,7 +42,9 @@ volatile __u8 *via1, *via2;
+ /* See note in mac_via.h about how this is possibly not useful */
+ volatile long *via_memory_bogon=(long *)&via_memory_bogon;
+ #endif
+-int rbv_present, via_alt_mapping;
++int rbv_present;
++int via_alt_mapping;
++EXPORT_SYMBOL(via_alt_mapping);
+ __u8 rbv_clear;
+ 
+ /*
+diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
+index 950e82f..edb3f6e 100644
+--- a/arch/m68k/mvme16x/Makefile
++++ b/arch/m68k/mvme16x/Makefile
+@@ -2,4 +2,4 @@
+ # Makefile for Linux arch/m68k/mvme16x source directory
+ #
+ 
+-obj-y		:= config.o rtc.o mvme16x_ksyms.o
++obj-y		:= config.o rtc.o
+diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
+index daa7851..24cbc30 100644
+--- a/arch/m68k/mvme16x/config.c
++++ b/arch/m68k/mvme16x/config.c
+@@ -25,6 +25,7 @@
+ #include <linux/genhd.h>
+ #include <linux/rtc.h>
+ #include <linux/interrupt.h>
++#include <linux/module.h>
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/system.h>
+@@ -58,6 +59,7 @@ static irq_handler_t tick_handler;
+ 
+ 
+ unsigned short mvme16x_config;
++EXPORT_SYMBOL(mvme16x_config);
+ 
+ 
+ int mvme16x_parse_bootinfo(const struct bi_record *bi)
+diff --git a/arch/m68k/mvme16x/mvme16x_ksyms.c b/arch/m68k/mvme16x/mvme16x_ksyms.c
+deleted file mode 100644
+index 4a8a363..0000000
+--- a/arch/m68k/mvme16x/mvme16x_ksyms.c
++++ /dev/null
+@@ -1,6 +0,0 @@
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <asm/ptrace.h>
+-#include <asm/mvme16xhw.h>
+-
+-EXPORT_SYMBOL(mvme16x_config);
 diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
-index f4b582c..bd92137 100644
+index f4b582c..6abbbb8 100644
 --- a/arch/m68knommu/Kconfig
 +++ b/arch/m68knommu/Kconfig
 @@ -53,6 +53,10 @@ config GENERIC_CALIBRATE_DELAY
@@ -66920,6 +81956,33 @@
  config TIME_LOW_RES
  	bool
  	default y
+@@ -707,8 +711,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/m68knommu/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/m68knommu/Kconfig.debug b/arch/m68knommu/Kconfig.debug
+index 9ff47bd..ed6d9a8 100644
+--- a/arch/m68knommu/Kconfig.debug
++++ b/arch/m68knommu/Kconfig.debug
+@@ -21,13 +21,6 @@ config BOOTPARAM_STRING
+ 	default 'console=ttyS0,19200'
+ 	depends on BOOTPARAM
+ 
+-config DUMPTOFLASH
+-	bool "Panic/Dump to FLASH"
+-	depends on COLDFIRE
+-	help
+-	  Dump any panic of trap output into a flash memory segment
+-	  for later analysis.
+-
+ config NO_KERNEL_MSG
+ 	bool "Suppress Kernel BUG Messages"
+ 	help
 diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile
 index 30aa255..e0b5f62 100644
 --- a/arch/m68knommu/Makefile
@@ -66953,6 +82016,74 @@
  cpuclass-$(CONFIG_M68328)	:= 68328
  cpuclass-$(CONFIG_M68EZ328)	:= 68328
  cpuclass-$(CONFIG_M68VZ328)	:= 68328
+diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig
+index 5a0ecaa..6481130 100644
+--- a/arch/m68knommu/defconfig
++++ b/arch/m68knommu/defconfig
+@@ -597,7 +597,6 @@ CONFIG_MSDOS_PARTITION=y
+ # CONFIG_FULLDEBUG is not set
+ # CONFIG_HIGHPROFILE is not set
+ # CONFIG_BOOTPARAM is not set
+-# CONFIG_DUMPTOFLASH is not set
+ # CONFIG_NO_KERNEL_MSG is not set
+ # CONFIG_BDM_DISABLE is not set
+ 
+diff --git a/arch/m68knommu/kernel/m68k_ksyms.c b/arch/m68knommu/kernel/m68k_ksyms.c
+index f795062..53fad14 100644
+--- a/arch/m68knommu/kernel/m68k_ksyms.c
++++ b/arch/m68knommu/kernel/m68k_ksyms.c
+@@ -24,14 +24,6 @@ extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+ EXPORT_SYMBOL(__ioremap);
+ EXPORT_SYMBOL(iounmap);
+ EXPORT_SYMBOL(dump_fpu);
+-EXPORT_SYMBOL(strnlen);
+-EXPORT_SYMBOL(strrchr);
+-EXPORT_SYMBOL(strstr);
+-EXPORT_SYMBOL(strchr);
+-EXPORT_SYMBOL(strcat);
+-EXPORT_SYMBOL(strlen);
+-EXPORT_SYMBOL(strcmp);
+-EXPORT_SYMBOL(strncmp);
+ 
+ EXPORT_SYMBOL(ip_fast_csum);
+ 
+@@ -46,9 +38,6 @@ EXPORT_SYMBOL(csum_partial_copy_nocheck);
+    it's OK to leave it out of version control.  */
+ EXPORT_SYMBOL(memcpy);
+ EXPORT_SYMBOL(memset);
+-EXPORT_SYMBOL(memcmp);
+-EXPORT_SYMBOL(memscan);
+-EXPORT_SYMBOL(memmove);
+ 
+ EXPORT_SYMBOL(__down_failed);
+ EXPORT_SYMBOL(__down_failed_interruptible);
+diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c
+index 332345d..81507c5 100644
+--- a/arch/m68knommu/kernel/setup.c
++++ b/arch/m68knommu/kernel/setup.c
+@@ -64,9 +64,6 @@ void (*mach_power_off)(void);
+ #ifdef CONFIG_M68VZ328
+ 	#define CPU "MC68VZ328"
+ #endif
+-#ifdef CONFIG_M68332
+-	#define CPU "MC68332"
+-#endif
+ #ifdef CONFIG_M68360
+ 	#define CPU "MC68360"
+ #endif
+diff --git a/arch/m68knommu/kernel/syscalltable.S b/arch/m68knommu/kernel/syscalltable.S
+index 9620093..1b02b88 100644
+--- a/arch/m68knommu/kernel/syscalltable.S
++++ b/arch/m68knommu/kernel/syscalltable.S
+@@ -336,7 +336,7 @@ ENTRY(sys_call_table)
+ 	.long sys_epoll_pwait		/* 315 */
+ 	.long sys_utimensat
+ 	.long sys_signalfd
+-	.long sys_timerfd
++	.long sys_ni_syscall
+ 	.long sys_eventfd
+ 	.long sys_fallocate		/* 320 */
+ 
 diff --git a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c
 index 77e5375..89cdbca 100644
 --- a/arch/m68knommu/kernel/time.c
@@ -70341,10 +85472,18 @@
 +
 +/***************************************************************************/
 diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
-index b22c043..36a4018 100644
+index b22c043..ec78a57 100644
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -37,16 +37,6 @@ config BASLER_EXCITE
+@@ -1,6 +1,7 @@
+ config MIPS
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
+ 	# Horrible source of confusion.  Die, die, die ...
+ 	select EMBEDDED
+ 	select RTC_LIB
+@@ -37,16 +38,6 @@ config BASLER_EXCITE
  	  The eXcite is a smart camera platform manufactured by
  	  Basler Vision Technologies AG.
  
@@ -70361,7 +85500,7 @@
  config BCM47XX
  	bool "BCM47XX based boards"
  	select CEVT_R4K
-@@ -82,7 +72,7 @@ config MIPS_COBALT
+@@ -82,7 +73,7 @@ config MIPS_COBALT
  	select SYS_HAS_CPU_NEVADA
  	select SYS_HAS_EARLY_PRINTK
  	select SYS_SUPPORTS_32BIT_KERNEL
@@ -70370,7 +85509,7 @@
  	select SYS_SUPPORTS_LITTLE_ENDIAN
  	select GENERIC_HARDIRQS_NO__DO_IRQ
  
-@@ -91,6 +81,9 @@ config MACH_DECSTATION
+@@ -91,6 +82,9 @@ config MACH_DECSTATION
  	select BOOT_ELF32
  	select CEVT_R4K
  	select CSRC_R4K
@@ -70380,7 +85519,7 @@
  	select DMA_NONCOHERENT
  	select NO_IOPORT
  	select IRQ_CPU
-@@ -124,12 +117,12 @@ config MACH_JAZZ
+@@ -124,12 +118,12 @@ config MACH_JAZZ
  	select ARCH_MAY_HAVE_PC_FDC
  	select CEVT_R4K
  	select CSRC_R4K
@@ -70394,7 +85533,7 @@
  	select SYS_HAS_CPU_R4X00
  	select SYS_SUPPORTS_32BIT_KERNEL
  	select SYS_SUPPORTS_64BIT_KERNEL if EXPERIMENTAL
-@@ -187,6 +180,7 @@ config LEMOTE_FULONG
+@@ -187,6 +181,7 @@ config LEMOTE_FULONG
  config MIPS_ATLAS
  	bool "MIPS Atlas board"
  	select BOOT_ELF32
@@ -70402,7 +85541,7 @@
  	select CEVT_R4K
  	select CSRC_R4K
  	select DMA_NONCOHERENT
-@@ -219,6 +213,7 @@ config MIPS_MALTA
+@@ -219,6 +214,7 @@ config MIPS_MALTA
  	bool "MIPS Malta board"
  	select ARCH_MAY_HAVE_PC_FDC
  	select BOOT_ELF32
@@ -70410,7 +85549,7 @@
  	select CEVT_R4K
  	select CSRC_R4K
  	select DMA_NONCOHERENT
-@@ -364,35 +359,6 @@ config PMC_YOSEMITE
+@@ -364,35 +360,6 @@ config PMC_YOSEMITE
  	  Yosemite is an evaluation board for the RM9000x2 processor
  	  manufactured by PMC-Sierra.
  
@@ -70446,7 +85585,7 @@
  config SGI_IP22
  	bool "SGI IP22 (Indy/Indigo2)"
  	select ARC
-@@ -400,6 +366,7 @@ config SGI_IP22
+@@ -400,6 +367,7 @@ config SGI_IP22
  	select BOOT_ELF32
  	select CEVT_R4K
  	select CSRC_R4K
@@ -70454,7 +85593,7 @@
  	select DMA_NONCOHERENT
  	select HW_HAS_EISA
  	select I8253
-@@ -407,6 +374,12 @@ config SGI_IP22
+@@ -407,6 +375,12 @@ config SGI_IP22
  	select IP22_CPU_SCACHE
  	select IRQ_CPU
  	select GENERIC_ISA_DMA_SUPPORT_BROKEN
@@ -70467,7 +85606,7 @@
  	select SWAP_IO_SPACE
  	select SYS_HAS_CPU_R4X00
  	select SYS_HAS_CPU_R5000
-@@ -424,6 +397,7 @@ config SGI_IP27
+@@ -424,6 +398,7 @@ config SGI_IP27
  	select ARC
  	select ARC64
  	select BOOT_ELF64
@@ -70475,7 +85614,7 @@
  	select DMA_IP27
  	select SYS_HAS_EARLY_PRINTK
  	select HW_HAS_PCI
-@@ -440,6 +414,36 @@ config SGI_IP27
+@@ -440,6 +415,36 @@ config SGI_IP27
  	  workstations.  To compile a Linux kernel that runs on these, say Y
  	  here.
  
@@ -70512,7 +85651,7 @@
  config SGI_IP32
  	bool "SGI IP32 (O2)"
  	select ARC
-@@ -545,19 +549,6 @@ config SIBYTE_SENTOSA
+@@ -545,19 +550,6 @@ config SIBYTE_SENTOSA
  	select SYS_SUPPORTS_BIG_ENDIAN
  	select SYS_SUPPORTS_LITTLE_ENDIAN
  
@@ -70532,7 +85671,7 @@
  config SIBYTE_BIGSUR
  	bool "Sibyte BCM91480B-BigSur"
  	select BOOT_ELF32
-@@ -575,10 +566,12 @@ config SNI_RM
+@@ -575,10 +567,12 @@ config SNI_RM
  	bool "SNI RM200/300/400"
  	select ARC if CPU_LITTLE_ENDIAN
  	select ARC32 if CPU_LITTLE_ENDIAN
@@ -70545,7 +85684,7 @@
  	select DMA_NONCOHERENT
  	select GENERIC_ISA_DMA
  	select HW_HAS_EISA
-@@ -587,7 +580,6 @@ config SNI_RM
+@@ -587,7 +581,6 @@ config SNI_RM
  	select I8253
  	select I8259
  	select ISA
@@ -70553,7 +85692,7 @@
  	select SWAP_IO_SPACE if CPU_BIG_ENDIAN
  	select SYS_HAS_CPU_R4X00
  	select SYS_HAS_CPU_R5000
-@@ -690,6 +682,7 @@ config WR_PPMC
+@@ -690,6 +683,7 @@ config WR_PPMC
  endchoice
  
  source "arch/mips/au1000/Kconfig"
@@ -70561,7 +85700,7 @@
  source "arch/mips/jazz/Kconfig"
  source "arch/mips/lasat/Kconfig"
  source "arch/mips/pmc-sierra/Kconfig"
-@@ -701,6 +694,11 @@ source "arch/mips/vr41xx/Kconfig"
+@@ -701,6 +695,11 @@ source "arch/mips/vr41xx/Kconfig"
  
  endmenu
  
@@ -70573,7 +85712,7 @@
  config RWSEM_GENERIC_SPINLOCK
  	bool
  	default y
-@@ -797,10 +795,6 @@ config DMA_COHERENT
+@@ -797,10 +796,6 @@ config DMA_COHERENT
  config DMA_IP27
  	bool
  
@@ -70584,7 +85723,7 @@
  config DMA_NONCOHERENT
  	bool
  	select DMA_NEED_PCI_MAP_STATE
-@@ -956,16 +950,40 @@ config EMMA2RH
+@@ -956,16 +951,40 @@ config EMMA2RH
  config SERIAL_RM9000
  	bool
  
@@ -70626,7 +85765,7 @@
  	default "4" if PMC_MSP4200_EVAL
  	default "5"
  
-@@ -974,7 +992,7 @@ config HAVE_STD_PC_SERIAL_PORT
+@@ -974,7 +993,7 @@ config HAVE_STD_PC_SERIAL_PORT
  
  config ARC_CONSOLE
  	bool "ARC console support"
@@ -70635,7 +85774,7 @@
  
  config ARC_MEMORY
  	bool
-@@ -983,7 +1001,7 @@ config ARC_MEMORY
+@@ -983,7 +1002,7 @@ config ARC_MEMORY
  
  config ARC_PROMLIB
  	bool
@@ -70644,7 +85783,7 @@
  	default y
  
  config ARC64
-@@ -1443,7 +1461,9 @@ config MIPS_MT_SMP
+@@ -1443,7 +1462,9 @@ config MIPS_MT_SMP
  	select MIPS_MT
  	select NR_CPUS_DEFAULT_2
  	select SMP
@@ -70654,7 +85793,7 @@
  	help
  	  This is a kernel model which is also known a VSMP or lately
  	  has been marketesed into SMVP.
-@@ -1460,6 +1480,7 @@ config MIPS_MT_SMTC
+@@ -1460,6 +1481,7 @@ config MIPS_MT_SMTC
  	select NR_CPUS_DEFAULT_8
  	select SMP
  	select SYS_SUPPORTS_SMP
@@ -70662,7 +85801,7 @@
  	help
  	  This is a kernel model which is known a SMTC or lately has been
  	  marketesed into SMVP.
-@@ -1469,6 +1490,19 @@ endchoice
+@@ -1469,6 +1491,19 @@ endchoice
  config MIPS_MT
  	bool
  
@@ -70682,7 +85821,7 @@
  config SYS_SUPPORTS_MULTITHREADING
  	bool
  
-@@ -1589,15 +1623,6 @@ config CPU_HAS_SMARTMIPS
+@@ -1589,15 +1624,6 @@ config CPU_HAS_SMARTMIPS
  config CPU_HAS_WB
  	bool
  
@@ -70698,7 +85837,7 @@
  #
  # Vectored interrupt mode is an R2 feature
  #
-@@ -1619,6 +1644,19 @@ config GENERIC_CLOCKEVENTS_BROADCAST
+@@ -1619,6 +1645,19 @@ config GENERIC_CLOCKEVENTS_BROADCAST
  	bool
  
  #
@@ -70718,7 +85857,14 @@
  # Use the generic interrupt handling code in kernel/irq/:
  #
  config GENERIC_HARDIRQS
-@@ -1721,6 +1759,9 @@ config SMP
+@@ -1716,11 +1755,14 @@ config SMP
+ 	  People using multiprocessor machines who say Y here should also say
+ 	  Y to "Enhanced Real Time Clock Support", below.
+ 
+-	  See also the <file:Documentation/smp.txt> and the SMP-HOWTO
+-	  available at <http://www.tldp.org/docs.html#howto>.
++	  See also the SMP-HOWTO available at
++	  <http://www.tldp.org/docs.html#howto>.
  
  	  If you don't know what to do here, say N.
  
@@ -70728,7 +85874,7 @@
  config SYS_SUPPORTS_SMP
  	bool
  
-@@ -1920,11 +1961,6 @@ config PCI
+@@ -1920,11 +1962,6 @@ config PCI
  	  your box. Other bus systems are ISA, EISA, or VESA. If you have PCI,
  	  say Y, otherwise N.
  
@@ -70740,7 +85886,7 @@
  config PCI_DOMAINS
  	bool
  
-@@ -1978,9 +2014,6 @@ config MMU
+@@ -1978,9 +2015,6 @@ config MMU
  config I8253
  	bool
  
@@ -70750,7 +85896,7 @@
  config ZONE_DMA32
  	bool
  
-@@ -2048,6 +2081,10 @@ endmenu
+@@ -2048,6 +2082,10 @@ endmenu
  
  menu "Power management options"
  
@@ -70761,6 +85907,15 @@
  source "kernel/power/Kconfig"
  
  endmenu
+@@ -2058,8 +2096,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/mips/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/mips/Makefile b/arch/mips/Makefile
 index a1f8d8b..3fb7f30 100644
 --- a/arch/mips/Makefile
@@ -70962,6 +86117,19 @@
  	prom_init_cmdline();
  
  	memsize_str = prom_getenv("memsize");
+diff --git a/arch/mips/au1000/mtx-1/board_setup.c b/arch/mips/au1000/mtx-1/board_setup.c
+index abfc4bc..310d5df 100644
+--- a/arch/mips/au1000/mtx-1/board_setup.c
++++ b/arch/mips/au1000/mtx-1/board_setup.c
+@@ -99,7 +99,7 @@ mtx1_pci_idsel(unsigned int devsel, int assert)
+ #endif
+ 
+        if (assert && devsel != 0) {
+-               // supress signal to cardbus
++               // suppress signal to cardbus
+                au_writel( 0x00000002, SYS_OUTPUTCLR ); // set EXT_IO3 OFF
+        }
+        else {
 diff --git a/arch/mips/au1000/mtx-1/init.c b/arch/mips/au1000/mtx-1/init.c
 index cdeae32..e700fd3 100644
 --- a/arch/mips/au1000/mtx-1/init.c
@@ -73330,6 +88498,32 @@
 +{
 +}
 +EXPORT_SYMBOL(clk_put);
+diff --git a/arch/mips/kernel/binfmt_elfn32.c b/arch/mips/kernel/binfmt_elfn32.c
+index 9b34238..77db347 100644
+--- a/arch/mips/kernel/binfmt_elfn32.c
++++ b/arch/mips/kernel/binfmt_elfn32.c
+@@ -98,7 +98,7 @@ static __inline__ void
+ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+ {
+ 	/*
+-	 * Convert jiffies to nanoseconds and seperate with
++	 * Convert jiffies to nanoseconds and separate with
+ 	 * one divide.
+ 	 */
+ 	u64 nsec = (u64)jiffies * TICK_NSEC;
+diff --git a/arch/mips/kernel/binfmt_elfo32.c b/arch/mips/kernel/binfmt_elfo32.c
+index da41eac..08f4cd7 100644
+--- a/arch/mips/kernel/binfmt_elfo32.c
++++ b/arch/mips/kernel/binfmt_elfo32.c
+@@ -100,7 +100,7 @@ static inline void
+ jiffies_to_compat_timeval(unsigned long jiffies, struct compat_timeval *value)
+ {
+ 	/*
+-	 * Convert jiffies to nanoseconds and seperate with
++	 * Convert jiffies to nanoseconds and separate with
+ 	 * one divide.
+ 	 */
+ 	u64 nsec = (u64)jiffies * TICK_NSEC;
 diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c
 index af78456..417bb3e 100644
 --- a/arch/mips/kernel/cpu-bugs64.c
@@ -73548,7 +88742,7 @@
  	.shutdown = i8259A_shutdown,
  };
 diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c
-index d2c2e00..f6704ab 100644
+index d2c2e00..998c4ef 100644
 --- a/arch/mips/kernel/kspd.c
 +++ b/arch/mips/kernel/kspd.c
 @@ -161,8 +161,7 @@ static unsigned int translate_open_flags(int flags)
@@ -73561,6 +88755,15 @@
  		if( (flags & open_flags_table[i].sp) ) {
  			ret |= open_flags_table[i].ap;
  		}
+@@ -222,7 +221,7 @@ void sp_work_handle_request(void)
+ 		}
+ 	}
+ 
+-	/* Run the syscall at the priviledge of the user who loaded the
++	/* Run the syscall at the privilege of the user who loaded the
+ 	   SP program */
+ 
+ 	if (vpe_getuid(tclimit))
 diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
 index 2b8ec11..65af3cc 100644
 --- a/arch/mips/kernel/linux32.c
@@ -73733,8 +88936,60 @@
  #include <asm/system.h>
  #include <asm/vpe.h>
  #include <asm/rtlx.h>
+diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
+index 82480a1..f798139 100644
+--- a/arch/mips/kernel/scall32-o32.S
++++ b/arch/mips/kernel/scall32-o32.S
+@@ -660,7 +660,7 @@ einval:	li	v0, -EINVAL
+ 	sys	sys_ioprio_get		2	/* 4315 */
+ 	sys	sys_utimensat		4
+ 	sys	sys_signalfd		3
+-	sys	sys_timerfd		4
++	sys	sys_ni_syscall		0
+ 	sys	sys_eventfd		1
+ 	sys	sys_fallocate		6	/* 4320 */
+ 	.endm
+diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
+index c2c1087..a626be6 100644
+--- a/arch/mips/kernel/scall64-64.S
++++ b/arch/mips/kernel/scall64-64.S
+@@ -475,7 +475,7 @@ sys_call_table:
+ 	PTR	sys_ioprio_get
+ 	PTR	sys_utimensat			/* 5275 */
+ 	PTR	sys_signalfd
+-	PTR	sys_timerfd
++	PTR	sys_ni_syscall
+ 	PTR	sys_eventfd
+ 	PTR	sys_fallocate
+ 	.size	sys_call_table,.-sys_call_table
+diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
+index 01993ec..9d5bcaf 100644
+--- a/arch/mips/kernel/scall64-n32.S
++++ b/arch/mips/kernel/scall64-n32.S
+@@ -401,7 +401,7 @@ EXPORT(sysn32_call_table)
+ 	PTR	sys_ioprio_get
+ 	PTR	compat_sys_utimensat
+ 	PTR	compat_sys_signalfd		/* 5280 */
+-	PTR	compat_sys_timerfd
++	PTR	sys_ni_syscall
+ 	PTR	sys_eventfd
+ 	PTR	sys_fallocate
+ 	.size	sysn32_call_table,.-sysn32_call_table
+diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
+index dd68afc..fd2019c 100644
+--- a/arch/mips/kernel/scall64-o32.S
++++ b/arch/mips/kernel/scall64-o32.S
+@@ -523,7 +523,7 @@ sys_call_table:
+ 	PTR	sys_ioprio_get			/* 4315 */
+ 	PTR	compat_sys_utimensat
+ 	PTR	compat_sys_signalfd
+-	PTR	compat_sys_timerfd
++	PTR	sys_ni_syscall
+ 	PTR	sys_eventfd
+ 	PTR	sys32_fallocate			/* 4320 */
+ 	.size	sys_call_table,.-sys_call_table
 diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
-index f8a535a..269c252 100644
+index f8a535a..c032409 100644
 --- a/arch/mips/kernel/setup.c
 +++ b/arch/mips/kernel/setup.c
 @@ -8,7 +8,7 @@
@@ -73759,6 +89014,22 @@
  #include <asm/system.h>
  
  struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
+@@ -422,13 +424,13 @@ static void __init bootmem_init(void)
+ #endif	/* CONFIG_SGI_IP27 */
+ 
+ /*
+- * arch_mem_init - initialize memory managment subsystem
++ * arch_mem_init - initialize memory management subsystem
+  *
+  *  o plat_mem_setup() detects the memory configuration and will record detected
+  *    memory areas using add_memory_region.
+  *
+  * At this stage the memory configuration of the system is known to the
+- * kernel but generic memory managment system is still entirely uninitialized.
++ * kernel but generic memory management system is still entirely uninitialized.
+  *
+  *  o bootmem_init()
+  *  o sparse_init()
 @@ -561,6 +563,7 @@ void __init setup_arch(char **cmdline_p)
  	}
  #endif
@@ -74165,7 +89436,7 @@
  #include <asm/cacheflush.h>
  #include <linux/proc_fs.h>
 diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
-index 9c92d42..85f700e 100644
+index 9c92d42..b42e71c 100644
 --- a/arch/mips/kernel/smtc.c
 +++ b/arch/mips/kernel/smtc.c
 @@ -16,7 +16,6 @@
@@ -74176,6 +89447,33 @@
  #include <asm/mipsregs.h>
  #include <asm/cacheflush.h>
  #include <asm/time.h>
+@@ -66,7 +65,7 @@ asiduse smtc_live_asid[MAX_SMTC_TLBS][MAX_SMTC_ASIDS];
+ static atomic_t ipi_timer_latch[NR_CPUS];
+ 
+ /*
+- * Number of InterProcessor Interupt (IPI) message buffers to allocate
++ * Number of InterProcessor Interrupt (IPI) message buffers to allocate
+  */
+ 
+ #define IPIBUF_PER_CPU 4
+@@ -781,7 +780,7 @@ void smtc_send_ipi(int cpu, int type, unsigned int action)
+ 	if (cpu_data[cpu].vpe_id != cpu_data[smp_processor_id()].vpe_id) {
+ 		if (type == SMTC_CLOCK_TICK)
+ 			atomic_inc(&ipi_timer_latch[cpu]);
+-		/* If not on same VPE, enqueue and send cross-VPE interupt */
++		/* If not on same VPE, enqueue and send cross-VPE interrupt */
+ 		smtc_ipi_nq(&IPIQ[cpu], pipi);
+ 		LOCK_CORE_PRA();
+ 		settc(cpu_data[cpu].tc_id);
+@@ -1064,7 +1063,7 @@ static void setup_cross_vpe_interrupts(unsigned int nvpe)
+ 		return;
+ 
+ 	if (!cpu_has_vint)
+-		panic("SMTC Kernel requires Vectored Interupt support");
++		panic("SMTC Kernel requires Vectored Interrupt support");
+ 
+ 	set_vi_handler(MIPS_CPU_IPI_IRQ, ipi_irq_dispatch);
+ 
 diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
 index 2995be1..9f85d4c 100644
 --- a/arch/mips/kernel/time.c
@@ -76951,7 +92249,7 @@
  obj-$(CONFIG_32BIT)		+= ioremap.o pgtable-32.o
  obj-$(CONFIG_64BIT)		+= pgtable-64.o
 diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
-index 9355f1c..02bd180 100644
+index 9355f1c..53ec052 100644
 --- a/arch/mips/mm/c-r4k.c
 +++ b/arch/mips/mm/c-r4k.c
 @@ -449,7 +449,7 @@ static inline void local_r4k_flush_cache_page(void *args)
@@ -77013,6 +92311,15 @@
  		c->icache.flags |= MIPS_CACHE_IC_F_DC;
  		break;
  	}
+@@ -1108,7 +1101,7 @@ static void __init setup_scache(void)
+ 	/*
+ 	 * Do the probing thing on R4000SC and R4400SC processors.  Other
+ 	 * processors don't have a S-cache that would be relevant to the
+-	 * Linux memory managment.
++	 * Linux memory management.
+ 	 */
+ 	switch (c->cputype) {
+ 	case CPU_R4000SC:
 diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c
 index 810535d..ae39dd8 100644
 --- a/arch/mips/mm/dma-default.c
@@ -81246,6 +96553,19 @@
 +	return 1;
 +}
 +__setup("ip28_debug_be", debug_be_setup);
+diff --git a/arch/mips/sgi-ip27/ip27-hubio.c b/arch/mips/sgi-ip27/ip27-hubio.c
+index 524b371..a1fa4ab 100644
+--- a/arch/mips/sgi-ip27/ip27-hubio.c
++++ b/arch/mips/sgi-ip27/ip27-hubio.c
+@@ -168,7 +168,7 @@ static void hub_set_piomode(nasid_t nasid)
+ }
+ 
+ /*
+- * hub_pio_init  -  PIO-related hub initalization
++ * hub_pio_init  -  PIO-related hub initialization
+  *
+  * @hub:	hubinfo structure for our hub
+  */
 diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c
 index 3305fa9..a49e7c8 100644
 --- a/arch/mips/sgi-ip27/ip27-init.c
@@ -83452,10 +98772,18 @@
  #ifdef CONFIG_ROCKHOPPER
  	ali_m5229_preinit();
 diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
-index b8ef178..2b649c4 100644
+index b8ef178..028d8a0 100644
 --- a/arch/parisc/Kconfig
 +++ b/arch/parisc/Kconfig
-@@ -19,6 +19,11 @@ config MMU
+@@ -7,6 +7,7 @@ mainmenu "Linux/PA-RISC Kernel Configuration"
+ 
+ config PARISC
+ 	def_bool y
++	select HAVE_OPROFILE
+ 	help
+ 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
+ 	  in many of their workstations & servers (HP9000 700 and 800 series,
+@@ -19,6 +20,11 @@ config MMU
  config STACK_GROWSUP
  	def_bool y
  
@@ -83467,6 +98795,66 @@
  config RWSEM_GENERIC_SPINLOCK
  	def_bool y
  
+@@ -200,9 +206,8 @@ config SMP
+ 	  singleprocessor machines. On a singleprocessor machine, the kernel
+ 	  will run faster if you say N here.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available
+-	  at <http://www.tldp.org/docs.html#howto>.
++	  See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
++	  available at <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
+ 
+@@ -267,8 +272,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/parisc/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
+index 395bbce..e10d25d 100644
+--- a/arch/parisc/kernel/cache.c
++++ b/arch/parisc/kernel/cache.c
+@@ -305,7 +305,7 @@ flush_user_cache_page_non_current(struct vm_area_struct *vma,
+ 	/* save the current process space and pgd */
+ 	unsigned long space = mfsp(3), pgd = mfctl(25);
+ 
+-	/* we don't mind taking interrups since they may not
++	/* we don't mind taking interrupts since they may not
+ 	 * do anything with user space, but we can't
+ 	 * be preempted here */
+ 	preempt_disable();
+diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
+index 04848b2..84b9611 100644
+--- a/arch/parisc/kernel/hardware.c
++++ b/arch/parisc/kernel/hardware.c
+@@ -1187,7 +1187,7 @@ static struct hp_hardware hp_hardware_list[] __devinitdata = {
+ 	{HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"}, 
+ 	{HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"}, 
+ 	{HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"}, 
+-	{HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"}, 
++	{HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscellaneous PCI Plug-in"},
+ 	{HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"}, 
+ 	{HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"}, 
+ 	{HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"}, 
+diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
+index 2ce3806..58fccc9 100644
+--- a/arch/parisc/kernel/signal.c
++++ b/arch/parisc/kernel/signal.c
+@@ -333,7 +333,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ 	flush_user_icache_range((unsigned long) &frame->tramp[0],
+ 			   (unsigned long) &frame->tramp[TRAMP_SIZE]);
+ 
+-	/* TRAMP Words 0-4, Lenght 5 = SIGRESTARTBLOCK_TRAMP
++	/* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
+ 	 * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
+ 	 * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
+ 	 */
 diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
 index 40d0ff9..50b4a3a 100644
 --- a/arch/parisc/kernel/vmlinux.lds.S
@@ -83499,7 +98887,7 @@
  #ifdef CONFIG_BLK_DEV_INITRD
  	. = ALIGN(PAGE_SIZE);
 diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
-index 232c298..4a22c99 100644
+index 232c298..cf030b0 100644
 --- a/arch/powerpc/Kconfig
 +++ b/arch/powerpc/Kconfig
 @@ -42,6 +42,9 @@ config GENERIC_HARDIRQS
@@ -83524,30 +98912,39 @@
  config ARCH_HAS_ILOG2_U32
  	bool
  	default y
-@@ -140,11 +148,28 @@ config DEFAULT_UIMAGE
+@@ -79,6 +87,8 @@ config ARCH_NO_VIRT_TO_BUS
+ config PPC
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
+ 
+ config EARLY_PRINTK
+ 	bool
+@@ -140,11 +150,28 @@ config DEFAULT_UIMAGE
  	  Used to allow a board to specify it wants a uImage built by default
  	default n
  
 -config PPC64_SWSUSP
 +config REDBOOT
- 	bool
--	depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
++	bool
 +
 +config HIBERNATE_32
 +	bool
 +	depends on (PPC_PMAC && !SMP) || BROKEN
- 	default y
- 
++	default y
++
 +config HIBERNATE_64
 +	bool
 +	depends on BROKEN || (PPC_PMAC64 && EXPERIMENTAL)
 +	default y
 +
 +config ARCH_HIBERNATION_POSSIBLE
-+	bool
+ 	bool
+-	depends on PPC64 && (BROKEN || (PPC_PMAC64 && EXPERIMENTAL))
 +	depends on (PPC64 && HIBERNATE_64) || (PPC32 && HIBERNATE_32)
-+	default y
-+
+ 	default y
+ 
 +config ARCH_SUSPEND_POSSIBLE
 +	def_bool y
 +	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200
@@ -83555,7 +98952,7 @@
  config PPC_DCR_NATIVE
  	bool
  	default n
-@@ -160,11 +185,13 @@ config PPC_DCR
+@@ -160,11 +187,13 @@ config PPC_DCR
  
  config PPC_OF_PLATFORM_PCI
  	bool
@@ -83569,7 +98966,17 @@
  source "arch/powerpc/platforms/Kconfig"
  
  menu "Kernel options"
-@@ -340,6 +367,14 @@ config PPC_64K_PAGES
+@@ -227,6 +256,9 @@ config IOMMU_VMERGE
+ 
+ 	  Most drivers don't have this problem; it is safe to say Y here.
+ 
++config IOMMU_HELPER
++	def_bool PPC64
++
+ config HOTPLUG_CPU
+ 	bool "Support for enabling/disabling CPUs"
+ 	depends on SMP && HOTPLUG && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
+@@ -340,6 +372,14 @@ config PPC_64K_PAGES
  	  while on hardware with such support, it will be used to map
  	  normal application pages.
  
@@ -83584,7 +98991,7 @@
  config SCHED_SMT
  	bool "SMT (Hyperthreading) scheduler support"
  	depends on PPC64 && SMP
-@@ -370,6 +405,10 @@ config CMDLINE
+@@ -370,6 +410,10 @@ config CMDLINE
  	  most cases you will need to specify the root device here.
  
  if !44x || BROKEN
@@ -83595,7 +99002,7 @@
  source kernel/power/Kconfig
  endif
  
-@@ -417,7 +456,7 @@ endmenu
+@@ -417,7 +461,7 @@ endmenu
  
  config ISA_DMA_API
  	bool
@@ -83604,7 +99011,7 @@
  
  menu "Bus options"
  
-@@ -467,7 +506,7 @@ config MCA
+@@ -467,7 +511,7 @@ config MCA
  config PCI
  	bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx \
  		|| PPC_MPC52xx || (EMBEDDED && (PPC_PSERIES || PPC_ISERIES)) \
@@ -83613,6 +99020,15 @@
  	default y if !40x && !CPM2 && !8xx && !PPC_83xx \
  		&& !PPC_85xx && !PPC_86xx
  	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx
+@@ -674,8 +718,6 @@ source "arch/powerpc/sysdev/qe_lib/Kconfig"
+ 
+ source "lib/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/powerpc/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
 index 6a79fe4..db7cc34 100644
 --- a/arch/powerpc/Kconfig.debug
@@ -139648,9 +155064,38 @@
  	/*
  	 * Make a note of crashing cpu. Will be used in machine_kexec
 diff --git a/arch/powerpc/kernel/dma_64.c b/arch/powerpc/kernel/dma_64.c
-index 14206e3..8423907 100644
+index 14206e3..3a317cb 100644
 --- a/arch/powerpc/kernel/dma_64.c
 +++ b/arch/powerpc/kernel/dma_64.c
+@@ -31,8 +31,8 @@ static inline unsigned long device_to_mask(struct device *dev)
+ static void *dma_iommu_alloc_coherent(struct device *dev, size_t size,
+ 				      dma_addr_t *dma_handle, gfp_t flag)
+ {
+-	return iommu_alloc_coherent(dev->archdata.dma_data, size, dma_handle,
+-				    device_to_mask(dev), flag,
++	return iommu_alloc_coherent(dev, dev->archdata.dma_data, size,
++				    dma_handle, device_to_mask(dev), flag,
+ 				    dev->archdata.numa_node);
+ }
+ 
+@@ -52,7 +52,7 @@ static dma_addr_t dma_iommu_map_single(struct device *dev, void *vaddr,
+ 				       size_t size,
+ 				       enum dma_data_direction direction)
+ {
+-	return iommu_map_single(dev->archdata.dma_data, vaddr, size,
++	return iommu_map_single(dev, dev->archdata.dma_data, vaddr, size,
+ 			        device_to_mask(dev), direction);
+ }
+ 
+@@ -68,7 +68,7 @@ static void dma_iommu_unmap_single(struct device *dev, dma_addr_t dma_handle,
+ static int dma_iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+ 			    int nelems, enum dma_data_direction direction)
+ {
+-	return iommu_map_sg(dev->archdata.dma_data, sglist, nelems,
++	return iommu_map_sg(dev, sglist, nelems,
+ 			    device_to_mask(dev), direction);
+ }
+ 
 @@ -112,10 +112,16 @@ EXPORT_SYMBOL(dma_iommu_ops);
  /*
   * Generic direct DMA implementation
@@ -139875,10 +155320,211 @@
  EXPORT_SYMBOL(ibmebus_unregister_driver);
  
 diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
-index 79a85d6..a3c406a 100644
+index 79a85d6..8f1f4e5 100644
 --- a/arch/powerpc/kernel/iommu.c
 +++ b/arch/powerpc/kernel/iommu.c
-@@ -532,16 +532,14 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
+@@ -31,6 +31,7 @@
+ #include <linux/string.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/bitops.h>
++#include <linux/iommu-helper.h>
+ #include <asm/io.h>
+ #include <asm/prom.h>
+ #include <asm/iommu.h>
+@@ -81,17 +82,19 @@ static int __init setup_iommu(char *str)
+ __setup("protect4gb=", setup_protect4gb);
+ __setup("iommu=", setup_iommu);
+ 
+-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
++static unsigned long iommu_range_alloc(struct device *dev,
++				       struct iommu_table *tbl,
+                                        unsigned long npages,
+                                        unsigned long *handle,
+                                        unsigned long mask,
+                                        unsigned int align_order)
+ { 
+-	unsigned long n, end, i, start;
++	unsigned long n, end, start;
+ 	unsigned long limit;
+ 	int largealloc = npages > 15;
+ 	int pass = 0;
+ 	unsigned long align_mask;
++	unsigned long boundary_size;
+ 
+ 	align_mask = 0xffffffffffffffffl >> (64 - align_order);
+ 
+@@ -136,14 +139,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+ 			start &= mask;
+ 	}
+ 
+-	n = find_next_zero_bit(tbl->it_map, limit, start);
+-
+-	/* Align allocation */
+-	n = (n + align_mask) & ~align_mask;
+-
+-	end = n + npages;
++	if (dev)
++		boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
++				      1 << IOMMU_PAGE_SHIFT);
++	else
++		boundary_size = ALIGN(1UL << 32, 1 << IOMMU_PAGE_SHIFT);
++	/* 4GB boundary for iseries_hv_alloc and iseries_hv_map */
+ 
+-	if (unlikely(end >= limit)) {
++	n = iommu_area_alloc(tbl->it_map, limit, start, npages,
++			     tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
++			     align_mask);
++	if (n == -1) {
+ 		if (likely(pass < 2)) {
+ 			/* First failure, just rescan the half of the table.
+ 			 * Second failure, rescan the other half of the table.
+@@ -158,14 +164,7 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+ 		}
+ 	}
+ 
+-	for (i = n; i < end; i++)
+-		if (test_bit(i, tbl->it_map)) {
+-			start = i+1;
+-			goto again;
+-		}
+-
+-	for (i = n; i < end; i++)
+-		__set_bit(i, tbl->it_map);
++	end = n + npages;
+ 
+ 	/* Bump the hint to a new block for small allocs. */
+ 	if (largealloc) {
+@@ -184,16 +183,17 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+ 	return n;
+ }
+ 
+-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page,
+-		       unsigned int npages, enum dma_data_direction direction,
+-		       unsigned long mask, unsigned int align_order)
++static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
++			      void *page, unsigned int npages,
++			      enum dma_data_direction direction,
++			      unsigned long mask, unsigned int align_order)
+ {
+ 	unsigned long entry, flags;
+ 	dma_addr_t ret = DMA_ERROR_CODE;
+ 
+ 	spin_lock_irqsave(&(tbl->it_lock), flags);
+ 
+-	entry = iommu_range_alloc(tbl, npages, NULL, mask, align_order);
++	entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
+ 
+ 	if (unlikely(entry == DMA_ERROR_CODE)) {
+ 		spin_unlock_irqrestore(&(tbl->it_lock), flags);
+@@ -224,7 +224,6 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+ 			 unsigned int npages)
+ {
+ 	unsigned long entry, free_entry;
+-	unsigned long i;
+ 
+ 	entry = dma_addr >> IOMMU_PAGE_SHIFT;
+ 	free_entry = entry - tbl->it_offset;
+@@ -246,9 +245,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+ 	}
+ 
+ 	ppc_md.tce_free(tbl, entry, npages);
+-	
+-	for (i = 0; i < npages; i++)
+-		__clear_bit(free_entry+i, tbl->it_map);
++	iommu_area_free(tbl->it_map, free_entry, npages);
+ }
+ 
+ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+@@ -270,16 +267,18 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+ 	spin_unlock_irqrestore(&(tbl->it_lock), flags);
+ }
+ 
+-int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
++int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+ 		 int nelems, unsigned long mask,
+ 		 enum dma_data_direction direction)
+ {
++	struct iommu_table *tbl = dev->archdata.dma_data;
+ 	dma_addr_t dma_next = 0, dma_addr;
+ 	unsigned long flags;
+ 	struct scatterlist *s, *outs, *segstart;
+ 	int outcount, incount, i;
+ 	unsigned int align;
+ 	unsigned long handle;
++	unsigned int max_seg_size;
+ 
+ 	BUG_ON(direction == DMA_NONE);
+ 
+@@ -298,6 +297,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+ 
+ 	spin_lock_irqsave(&(tbl->it_lock), flags);
+ 
++	max_seg_size = dma_get_max_seg_size(dev);
+ 	for_each_sg(sglist, s, nelems, i) {
+ 		unsigned long vaddr, npages, entry, slen;
+ 
+@@ -314,7 +314,7 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+ 		if (IOMMU_PAGE_SHIFT < PAGE_SHIFT && slen >= PAGE_SIZE &&
+ 		    (vaddr & ~PAGE_MASK) == 0)
+ 			align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
+-		entry = iommu_range_alloc(tbl, npages, &handle,
++		entry = iommu_range_alloc(dev, tbl, npages, &handle,
+ 					  mask >> IOMMU_PAGE_SHIFT, align);
+ 
+ 		DBG("  - vaddr: %lx, size: %lx\n", vaddr, slen);
+@@ -344,7 +344,8 @@ int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+ 			/* We cannot merge if:
+ 			 * - allocated dma_addr isn't contiguous to previous allocation
+ 			 */
+-			if (novmerge || (dma_addr != dma_next)) {
++			if (novmerge || (dma_addr != dma_next) ||
++			    (outs->dma_length + s->length > max_seg_size)) {
+ 				/* Can't merge: create a new segment */
+ 				segstart = s;
+ 				outcount++;
+@@ -452,9 +453,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
+ {
+ 	unsigned long sz;
+-	unsigned long start_index, end_index;
+-	unsigned long entries_per_4g;
+-	unsigned long index;
+ 	static int welcomed = 0;
+ 	struct page *page;
+ 
+@@ -476,6 +474,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
+ 
+ #ifdef CONFIG_CRASH_DUMP
+ 	if (ppc_md.tce_get) {
++		unsigned long index;
+ 		unsigned long tceval;
+ 		unsigned long tcecount = 0;
+ 
+@@ -506,23 +505,6 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
+ 	ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+ #endif
+ 
+-	/*
+-	 * DMA cannot cross 4 GB boundary.  Mark last entry of each 4
+-	 * GB chunk as reserved.
+-	 */
+-	if (protect4gb) {
+-		entries_per_4g = 0x100000000l >> IOMMU_PAGE_SHIFT;
+-
+-		/* Mark the last bit before a 4GB boundary as used */
+-		start_index = tbl->it_offset | (entries_per_4g - 1);
+-		start_index -= tbl->it_offset;
+-
+-		end_index = tbl->it_size;
+-
+-		for (index = start_index; index < end_index - 1; index += entries_per_4g)
+-			__set_bit(index, tbl->it_map);
+-	}
+-
+ 	if (!welcomed) {
+ 		printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
+ 		       novmerge ? "disabled" : "enabled");
+@@ -532,16 +514,14 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
  	return tbl;
  }
  
@@ -139897,7 +155543,7 @@
  		return;
  	}
  
-@@ -550,7 +548,7 @@ void iommu_free_table(struct device_node *dn)
+@@ -550,7 +530,7 @@ void iommu_free_table(struct device_node *dn)
  	for (i = 0; i < (tbl->it_size/64); i++) {
  		if (tbl->it_map[i] != 0) {
  			printk(KERN_WARNING "%s: Unexpected TCEs for %s\n",
@@ -139906,6 +155552,49 @@
  			break;
  		}
  	}
+@@ -572,9 +552,9 @@ void iommu_free_table(struct device_node *dn)
+  * need not be page aligned, the dma_addr_t returned will point to the same
+  * byte within the page as vaddr.
+  */
+-dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
+-		size_t size, unsigned long mask,
+-		enum dma_data_direction direction)
++dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
++			    void *vaddr, size_t size, unsigned long mask,
++			    enum dma_data_direction direction)
+ {
+ 	dma_addr_t dma_handle = DMA_ERROR_CODE;
+ 	unsigned long uaddr;
+@@ -591,7 +571,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
+ 		    ((unsigned long)vaddr & ~PAGE_MASK) == 0)
+ 			align = PAGE_SHIFT - IOMMU_PAGE_SHIFT;
+ 
+-		dma_handle = iommu_alloc(tbl, vaddr, npages, direction,
++		dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction,
+ 					 mask >> IOMMU_PAGE_SHIFT, align);
+ 		if (dma_handle == DMA_ERROR_CODE) {
+ 			if (printk_ratelimit())  {
+@@ -623,8 +603,9 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
+  * Returns the virtual address of the buffer and sets dma_handle
+  * to the dma address (mapping) of the first page.
+  */
+-void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+-		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
++void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
++			   size_t size,	dma_addr_t *dma_handle,
++			   unsigned long mask, gfp_t flag, int node)
+ {
+ 	void *ret = NULL;
+ 	dma_addr_t mapping;
+@@ -658,7 +639,7 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+ 	/* Set up tces to cover the allocated range */
+ 	nio_pages = size >> IOMMU_PAGE_SHIFT;
+ 	io_order = get_iommu_order(size);
+-	mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
++	mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL,
+ 			      mask >> IOMMU_PAGE_SHIFT, io_order);
+ 	if (mapping == DMA_ERROR_CODE) {
+ 		free_pages((unsigned long)ret, order);
 diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c
 index f0f49d1..ee172aa 100644
 --- a/arch/powerpc/kernel/isa-bridge.c
@@ -145316,6 +161005,37 @@
  		}
  		totalram_pages += totalhigh_pages;
  		printk(KERN_DEBUG "High memory: %luk\n",
+diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
+index 6448872..f80f90c 100644
+--- a/arch/powerpc/mm/pgtable_32.c
++++ b/arch/powerpc/mm/pgtable_32.c
+@@ -86,7 +86,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return ret;
+ }
+ 
+-void pgd_free(pgd_t *pgd)
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_pages((unsigned long)pgd, PGDIR_ORDER);
+ }
+@@ -123,7 +123,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+ 	return ptepage;
+ }
+ 
+-void pte_free_kernel(pte_t *pte)
++void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ #ifdef CONFIG_SMP
+ 	hash_page_sync();
+@@ -131,7 +131,7 @@ void pte_free_kernel(pte_t *pte)
+ 	free_page((unsigned long)pte);
+ }
+ 
+-void pte_free(struct page *ptepage)
++void pte_free(struct mm_struct *mm, struct page *ptepage)
+ {
+ #ifdef CONFIG_SMP
+ 	hash_page_sync();
 diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c
 index 50d7372..47b06ba 100644
 --- a/arch/powerpc/mm/slb.c
@@ -155954,7 +171674,7 @@
  obj-$(CONFIG_VIOPATH) += viopath.o vio.o
  obj-$(CONFIG_MODULES) += ksyms.o
 diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
-index 49e9c66..6a0c6f6 100644
+index 49e9c66..11fa3c7 100644
 --- a/arch/powerpc/platforms/iseries/iommu.c
 +++ b/arch/powerpc/platforms/iseries/iommu.c
 @@ -163,8 +163,10 @@ static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
@@ -155969,6 +171689,24 @@
  	}
  	return NULL;
  }
+@@ -197,7 +199,7 @@ static struct iommu_table vio_iommu_table;
+ 
+ void *iseries_hv_alloc(size_t size, dma_addr_t *dma_handle, gfp_t flag)
+ {
+-	return iommu_alloc_coherent(&vio_iommu_table, size, dma_handle,
++	return iommu_alloc_coherent(NULL, &vio_iommu_table, size, dma_handle,
+ 				DMA_32BIT_MASK, flag, -1);
+ }
+ EXPORT_SYMBOL_GPL(iseries_hv_alloc);
+@@ -211,7 +213,7 @@ EXPORT_SYMBOL_GPL(iseries_hv_free);
+ dma_addr_t iseries_hv_map(void *vaddr, size_t size,
+ 			enum dma_data_direction direction)
+ {
+-	return iommu_map_single(&vio_iommu_table, vaddr, size,
++	return iommu_map_single(NULL, &vio_iommu_table, vaddr, size,
+ 				DMA_32BIT_MASK, direction);
+ }
+ 
 diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c
 index 275f494..e5b40e3 100644
 --- a/arch/powerpc/platforms/iseries/lpevents.c
@@ -169922,10 +185660,19 @@
  /*
   * I2C/SPI relocation patch arrays.
 diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
-index 6473fa7..db5934c 100644
+index 6473fa7..531156f 100644
 --- a/arch/ppc/Kconfig
 +++ b/arch/ppc/Kconfig
-@@ -78,18 +78,18 @@ choice
+@@ -42,6 +42,8 @@ config GENERIC_CALIBRATE_DELAY
+ config PPC
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
+ 
+ config PPC32
+ 	bool
+@@ -78,18 +80,18 @@ choice
  	default 6xx
  
  config 6xx
@@ -169947,7 +185694,7 @@
  	  core, specific support for that chipset is asked later on.
  
  config 40x
-@@ -104,12 +104,6 @@ config 8xx
+@@ -104,12 +106,6 @@ config 8xx
  	bool "8xx"
  	select PPC_LIB_RHEAP
  
@@ -169960,7 +185707,7 @@
  endchoice
  
  config PPC_FPU
-@@ -124,25 +118,14 @@ config PPC_DCR
+@@ -124,25 +120,14 @@ config PPC_DCR
  	depends on PPC_DCR_NATIVE
  	default y
  
@@ -169989,7 +185736,7 @@
  	default y if 44x
  	---help---
  	  This option enables kernel support for larger than 32-bit physical
-@@ -153,7 +136,7 @@ config PHYS_64BIT
+@@ -153,7 +138,7 @@ config PHYS_64BIT
  config ALTIVEC
  	bool "AltiVec Support"
  	depends on 6xx
@@ -169998,7 +185745,7 @@
  	---help---
  	  This option enables kernel support for the Altivec extensions to the
  	  PowerPC processor. The kernel currently supports saving and restoring
-@@ -167,24 +150,9 @@ config ALTIVEC
+@@ -167,24 +152,9 @@ config ALTIVEC
  
  	  If in doubt, say Y here.
  
@@ -170024,7 +185771,7 @@
  	help
  	  G3 and G4 processors have an on-chip temperature sensor called the
  	  'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
-@@ -228,7 +196,7 @@ config TAU_AVERAGE
+@@ -228,7 +198,7 @@ config TAU_AVERAGE
  
  config MATH_EMULATION
  	bool "Math emulation"
@@ -170033,7 +185780,7 @@
  	---help---
  	  Some PowerPC chips designed for embedded applications do not have
  	  a floating-point unit and therefore do not implement the
-@@ -279,7 +247,6 @@ config PPC601_SYNC_FIX
+@@ -279,7 +249,6 @@ config PPC601_SYNC_FIX
  	  If in doubt, say Y here.
  
  source arch/ppc/platforms/4xx/Kconfig
@@ -170041,7 +185788,7 @@
  
  config PPC_STD_MMU
  	bool
-@@ -288,7 +255,7 @@ config PPC_STD_MMU
+@@ -288,7 +257,7 @@ config PPC_STD_MMU
  
  config NOT_COHERENT_CACHE
  	bool
@@ -170050,7 +185797,7 @@
  	default y
  
  endmenu
-@@ -721,16 +688,6 @@ config LITE5200B
+@@ -721,16 +690,6 @@ config LITE5200B
  	  Support for the LITE5200B dev board for the MPC5200 from Freescale.
  	  This is the new board with 2 PCI slots.
  
@@ -170067,7 +185814,7 @@
  config EV64360
  	bool "Marvell-EV64360BP"
  	help
-@@ -774,18 +731,6 @@ config 8272
+@@ -774,18 +733,6 @@ config 8272
  	  The MPC8272 CPM has a different internal dpram setup than other CPM2
  	  devices
  
@@ -170086,7 +185833,7 @@
  config CPM1
  	bool
  	depends on 8xx
-@@ -811,8 +756,7 @@ config PPC_GEN550
+@@ -811,8 +758,7 @@ config PPC_GEN550
  	bool
  	depends on SANDPOINT || SPRUCE || PPLUS || \
  		PRPMC750 || PRPMC800 || LOPEC || \
@@ -170096,7 +185843,7 @@
  	default y
  
  config FORCE
-@@ -1068,13 +1012,13 @@ config GENERIC_ISA_DMA
+@@ -1068,13 +1014,13 @@ config GENERIC_ISA_DMA
  
  config PPC_I8259
  	bool
@@ -170112,7 +185859,7 @@
  	default n
  
  config EISA
-@@ -1091,8 +1035,8 @@ config MCA
+@@ -1091,8 +1037,8 @@ config MCA
  	bool
  
  config PCI
@@ -170123,7 +185870,7 @@
  	default PCI_QSPAN if !4xx && !CPM2 && 8xx
  	help
  	  Find out whether your system includes a PCI bus. PCI is the name of
-@@ -1106,11 +1050,6 @@ config PCI_DOMAINS
+@@ -1106,11 +1052,6 @@ config PCI_DOMAINS
  config PCI_SYSCALL
  	def_bool PCI
  
@@ -170135,6 +185882,15 @@
  config PCI_QSPAN
  	bool "QSpan PCI"
  	depends on !4xx && !CPM2 && 8xx
+@@ -1317,8 +1258,6 @@ endmenu
+ 
+ source "lib/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/ppc/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
 index 95894ef..8df7f0e 100644
 --- a/arch/ppc/Makefile
@@ -180991,7 +196747,7 @@
  /* anything except 4xx or 8xx */
  extern void MMU_init_hw(void);
 diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
-index 1f51e6c..fadacfd 100644
+index 1f51e6c..409fcaa 100644
 --- a/arch/ppc/mm/pgtable.c
 +++ b/arch/ppc/mm/pgtable.c
 @@ -42,10 +42,6 @@ int io_bat_index;
@@ -181021,6 +196777,33 @@
  #ifdef CONFIG_PTE_64BIT
  /* 44x uses an 8kB pgdir because it has 8-byte Linux PTEs. */
  #define PGDIR_ORDER	1
+@@ -87,7 +74,7 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return ret;
+ }
+ 
+-void pgd_free(pgd_t *pgd)
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_pages((unsigned long)pgd, PGDIR_ORDER);
+ }
+@@ -124,7 +111,7 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+ 	return ptepage;
+ }
+ 
+-void pte_free_kernel(pte_t *pte)
++void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ #ifdef CONFIG_SMP
+ 	hash_page_sync();
+@@ -132,7 +119,7 @@ void pte_free_kernel(pte_t *pte)
+ 	free_page((unsigned long)pte);
+ }
+ 
+-void pte_free(struct page *ptepage)
++void pte_free(struct mm_struct *mm, struct page *ptepage)
+ {
+ #ifdef CONFIG_SMP
+ 	hash_page_sync();
 @@ -213,9 +200,6 @@ __ioremap(phys_addr_t addr, unsigned long size, unsigned long flags)
  	if ((v = p_mapped_by_bats(p)) /*&& p_mapped_by_bats(p+size-1)*/ )
  		goto out;
@@ -189270,10 +205053,49 @@
  extern void xmon_printf(const char *fmt, ...);
  extern int xmon_8xx_write(char *str, int nb);
 diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
-index 1330061..6ef54d2 100644
+index 1330061..92a4f7b 100644
 --- a/arch/s390/Kconfig
 +++ b/arch/s390/Kconfig
-@@ -276,9 +276,6 @@ source "kernel/Kconfig.preempt"
+@@ -16,6 +16,9 @@ config LOCKDEP_SUPPORT
+ config STACKTRACE_SUPPORT
+ 	def_bool y
+ 
++config HAVE_LATENCYTOP_SUPPORT
++	def_bool y
++
+ config RWSEM_GENERIC_SPINLOCK
+ 	bool
+ 
+@@ -47,10 +50,17 @@ config NO_IOMEM
+ config NO_DMA
+ 	def_bool y
+ 
++config GENERIC_LOCKBREAK
++	bool
++	default y
++	depends on SMP && PREEMPT
++
+ mainmenu "Linux Kernel Configuration"
+ 
+ config S390
+ 	def_bool y
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
+ 
+ source "init/Kconfig"
+ 
+@@ -81,8 +91,8 @@ config SMP
+ 	  singleprocessor machines. On a singleprocessor machine, the kernel
+ 	  will run faster if you say N here.
+ 
+-	  See also the <file:Documentation/smp.txt> and the SMP-HOWTO
+-	  available at <http://www.tldp.org/docs.html#howto>.
++	  See also the SMP-HOWTO available at
++	  <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  Even if you don't know what to do here, say Y.
+ 
+@@ -276,9 +286,6 @@ source "kernel/Kconfig.preempt"
  
  source "mm/Kconfig"
  
@@ -189283,6 +205105,32 @@
  comment "I/O subsystem configuration"
  
  config MACHCHK_WARNING
+@@ -529,8 +536,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/s390/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug
+index 2283933..4599fa0 100644
+--- a/arch/s390/Kconfig.debug
++++ b/arch/s390/Kconfig.debug
+@@ -6,4 +6,12 @@ config TRACE_IRQFLAGS_SUPPORT
+ 
+ source "lib/Kconfig.debug"
+ 
++config DEBUG_PAGEALLOC
++	bool "Debug page memory allocations"
++	depends on DEBUG_KERNEL
++	help
++	  Unmap pages from the kernel linear mapping after free_pages().
++	  This results in a slowdown, but helps to find certain types of
++	  memory corruptions.
++
+ endmenu
 diff --git a/arch/s390/crypto/Kconfig b/arch/s390/crypto/Kconfig
 deleted file mode 100644
 index d1defbb..0000000
@@ -189809,6 +205657,25 @@
 -# This is just to get the dependencies...
 -#
 -binfmt_elf32.o:	$(TOPDIR)/fs/binfmt_elf.c
+diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
+index 6ee1bed..062c3d4 100644
+--- a/arch/s390/kernel/compat_wrapper.S
++++ b/arch/s390/kernel/compat_wrapper.S
+@@ -1698,14 +1698,6 @@ compat_sys_signalfd_wrapper:
+ 	llgfr	%r4,%r4			# compat_size_t
+ 	jg	compat_sys_signalfd
+ 
+-	.globl	compat_sys_timerfd_wrapper
+-compat_sys_timerfd_wrapper:
+-	lgfr	%r2,%r2			# int
+-	lgfr	%r3,%r3			# int
+-	lgfr	%r4,%r4			# int
+-	llgtr	%r5,%r5			# struct compat_itimerspec *
+-	jg	compat_sys_timerfd
+-
+ 	.globl	sys_eventfd_wrapper
+ sys_eventfd_wrapper:
+ 	llgfr	%r2,%r2			# unsigned int
 diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c
 index 1b3af7d..9f7b73b 100644
 --- a/arch/s390/kernel/early.c
@@ -189822,6 +205689,72 @@
  	sclp_facilities_detect();
  	memsize = sclp_memory_detect();
  #ifndef CONFIG_64BIT
+diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
+index 1a6dac8..6766e37 100644
+--- a/arch/s390/kernel/entry.S
++++ b/arch/s390/kernel/entry.S
+@@ -11,6 +11,7 @@
+ 
+ #include <linux/sys.h>
+ #include <linux/linkage.h>
++#include <linux/init.h>
+ #include <asm/cache.h>
+ #include <asm/lowcore.h>
+ #include <asm/errno.h>
+@@ -830,9 +831,7 @@ mcck_return:
+  * Restart interruption handler, kick starter for additional CPUs
+  */
+ #ifdef CONFIG_SMP
+-#ifndef CONFIG_HOTPLUG_CPU
+-	.section .init.text,"ax"
+-#endif
++	__CPUINIT
+ 	.globl restart_int_handler
+ restart_int_handler:
+ 	l	%r15,__LC_SAVE_AREA+60	# load ksp
+@@ -845,9 +844,7 @@ restart_int_handler:
+ 	br	%r14			# branch to start_secondary
+ restart_addr:
+ 	.long	start_secondary
+-#ifndef CONFIG_HOTPLUG_CPU
+ 	.previous
+-#endif
+ #else
+ /*
+  * If we do not run with SMP enabled, let the new CPU crash ...
+diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
+index a3e47b8..efde6e1 100644
+--- a/arch/s390/kernel/entry64.S
++++ b/arch/s390/kernel/entry64.S
+@@ -11,6 +11,7 @@
+ 
+ #include <linux/sys.h>
+ #include <linux/linkage.h>
++#include <linux/init.h>
+ #include <asm/cache.h>
+ #include <asm/lowcore.h>
+ #include <asm/errno.h>
+@@ -801,9 +802,7 @@ mcck_return:
+  * Restart interruption handler, kick starter for additional CPUs
+  */
+ #ifdef CONFIG_SMP
+-#ifndef CONFIG_HOTPLUG_CPU
+-	.section .init.text,"ax"
+-#endif
++	__CPUINIT
+ 	.globl restart_int_handler
+ restart_int_handler:
+ 	lg	%r15,__LC_SAVE_AREA+120 # load ksp
+@@ -814,9 +813,7 @@ restart_int_handler:
+ 	lmg	%r6,%r15,__SF_GPRS(%r15) # load registers from clone
+ 	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
+ 	jg	start_secondary
+-#ifndef CONFIG_HOTPLUG_CPU
+ 	.previous
+-#endif
+ #else
+ /*
+  * If we do not run with SMP enabled, let the new CPU crash ...
 diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
 index a87b197..79dccd2 100644
 --- a/arch/s390/kernel/head64.S
@@ -189836,7 +205769,7 @@
  	.long	0xb98e2001
  	oi	7(%r12),0x80		# set IDTE flag
 diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
-index ce0856d..db28cca 100644
+index ce0856d..60acdc2 100644
 --- a/arch/s390/kernel/ipl.c
 +++ b/arch/s390/kernel/ipl.c
 @@ -2,7 +2,7 @@
@@ -190085,7 +206018,7 @@
  	__ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
  
  static struct attribute *ipl_ccw_attrs[] = {
-@@ -418,10 +406,76 @@ static struct attribute_group ipl_unknown_attr_group = {
+@@ -418,10 +406,79 @@ static struct attribute_group ipl_unknown_attr_group = {
  	.attrs = ipl_unknown_attrs,
  };
  
@@ -190123,7 +206056,7 @@
 +		reipl_ccw_dev(&ipl_info.data.ccw.dev_id);
 +}
 +
-+static int ipl_init(void)
++static int __init ipl_init(void)
 +{
 +	int rc;
 +
@@ -190155,8 +206088,11 @@
 +	return 0;
 +}
 +
-+static struct shutdown_action ipl_action = {SHUTDOWN_ACTION_IPL_STR, ipl_run,
-+					    ipl_init};
++static struct shutdown_action __refdata ipl_action = {
++	.name	= SHUTDOWN_ACTION_IPL_STR,
++	.fn	= ipl_run,
++	.init	= ipl_init,
++};
  
  /*
 - * reipl section
@@ -190164,7 +206100,7 @@
   */
  
  /* FCP reipl device attributes */
-@@ -465,7 +519,8 @@ static void reipl_get_ascii_loadparm(char *loadparm)
+@@ -465,7 +522,8 @@ static void reipl_get_ascii_loadparm(char *loadparm)
  	strstrip(loadparm);
  }
  
@@ -190174,7 +206110,7 @@
  {
  	char buf[LOADPARM_LEN + 1];
  
-@@ -473,7 +528,8 @@ static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
+@@ -473,7 +531,8 @@ static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
  	return sprintf(page, "%s\n", buf);
  }
  
@@ -190184,7 +206120,7 @@
  					const char *buf, size_t len)
  {
  	int i, lp_len;
-@@ -500,7 +556,7 @@ static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
+@@ -500,7 +559,7 @@ static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
  	return len;
  }
  
@@ -190193,7 +206129,7 @@
  	__ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
  	       reipl_ccw_loadparm_store);
  
-@@ -539,7 +595,9 @@ static int reipl_set_type(enum ipl_type type)
+@@ -539,7 +598,9 @@ static int reipl_set_type(enum ipl_type type)
  
  	switch(type) {
  	case IPL_TYPE_CCW:
@@ -190204,7 +206140,7 @@
  			reipl_method = REIPL_METHOD_CCW_VM;
  		else
  			reipl_method = REIPL_METHOD_CCW_CIO;
-@@ -568,13 +626,15 @@ static int reipl_set_type(enum ipl_type type)
+@@ -568,13 +629,15 @@ static int reipl_set_type(enum ipl_type type)
  	return 0;
  }
  
@@ -190223,7 +206159,7 @@
  {
  	int rc = -EINVAL;
  
-@@ -587,140 +647,12 @@ static ssize_t reipl_type_store(struct kset *kset, const char *buf,
+@@ -587,140 +650,12 @@ static ssize_t reipl_type_store(struct kset *kset, const char *buf,
  	return (rc != 0) ? rc : len;
  }
  
@@ -190368,7 +206304,7 @@
  {
  	struct ccw_dev_id devid;
  	static char buf[100];
-@@ -729,8 +661,6 @@ void do_reipl(void)
+@@ -729,8 +664,6 @@ void do_reipl(void)
  	switch (reipl_method) {
  	case REIPL_METHOD_CCW_CIO:
  		devid.devno = reipl_block_ccw->ipl_info.ccw.devno;
@@ -190377,7 +206313,7 @@
  		devid.ssid  = 0;
  		reipl_ccw_dev(&devid);
  		break;
-@@ -771,98 +701,6 @@ void do_reipl(void)
+@@ -771,98 +704,6 @@ void do_reipl(void)
  	default:
  		break;
  	}
@@ -190476,7 +206412,7 @@
  }
  
  static void __init reipl_probe(void)
-@@ -883,7 +721,7 @@ static int __init reipl_nss_init(void)
+@@ -883,7 +724,7 @@ static int __init reipl_nss_init(void)
  
  	if (!MACHINE_IS_VM)
  		return 0;
@@ -190485,7 +206421,7 @@
  	if (rc)
  		return rc;
  	strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1);
-@@ -898,7 +736,7 @@ static int __init reipl_ccw_init(void)
+@@ -898,7 +739,7 @@ static int __init reipl_ccw_init(void)
  	reipl_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
  	if (!reipl_block_ccw)
  		return -ENOMEM;
@@ -190494,7 +206430,7 @@
  	if (rc) {
  		free_page((unsigned long)reipl_block_ccw);
  		return rc;
-@@ -907,6 +745,7 @@ static int __init reipl_ccw_init(void)
+@@ -907,6 +748,7 @@ static int __init reipl_ccw_init(void)
  	reipl_block_ccw->hdr.version = IPL_PARM_BLOCK_VERSION;
  	reipl_block_ccw->hdr.blk0_len = IPL_PARM_BLK0_CCW_LEN;
  	reipl_block_ccw->hdr.pbt = DIAG308_IPL_TYPE_CCW;
@@ -190502,7 +206438,7 @@
  	/* check if read scp info worked and set loadparm */
  	if (sclp_ipl_info.is_valid)
  		memcpy(reipl_block_ccw->ipl_info.ccw.load_param,
-@@ -915,8 +754,7 @@ static int __init reipl_ccw_init(void)
+@@ -915,8 +757,7 @@ static int __init reipl_ccw_init(void)
  		/* read scp info failed: set empty loadparm (EBCDIC blanks) */
  		memset(reipl_block_ccw->ipl_info.ccw.load_param, 0x40,
  		       LOADPARM_LEN);
@@ -190512,7 +206448,7 @@
  		sys_reipl_ccw_loadparm_attr.attr.mode = S_IRUGO;
  	if (ipl_info.type == IPL_TYPE_CCW)
  		reipl_block_ccw->ipl_info.ccw.devno = ipl_devno;
-@@ -936,7 +774,7 @@ static int __init reipl_fcp_init(void)
+@@ -936,7 +777,7 @@ static int __init reipl_fcp_init(void)
  	reipl_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
  	if (!reipl_block_fcp)
  		return -ENOMEM;
@@ -190521,12 +206457,7 @@
  	if (rc) {
  		free_page((unsigned long)reipl_block_fcp);
  		return rc;
-@@ -954,16 +792,16 @@ static int __init reipl_fcp_init(void)
- 	return 0;
- }
- 
--static int __init reipl_init(void)
-+static int reipl_init(void)
+@@ -958,12 +799,12 @@ static int __init reipl_init(void)
  {
  	int rc;
  
@@ -190544,12 +206475,15 @@
  		return rc;
  	}
  	rc = reipl_ccw_init();
-@@ -981,6 +819,140 @@ static int __init reipl_init(void)
+@@ -981,6 +822,143 @@ static int __init reipl_init(void)
  	return 0;
  }
  
-+static struct shutdown_action reipl_action = {SHUTDOWN_ACTION_REIPL_STR,
-+					      reipl_run, reipl_init};
++static struct shutdown_action __refdata reipl_action = {
++	.name	= SHUTDOWN_ACTION_REIPL_STR,
++	.fn	= reipl_run,
++	.init	= reipl_init,
++};
 +
 +/*
 + * dump shutdown action: Dump Linux on shutdown.
@@ -190685,7 +206619,7 @@
  static int __init dump_ccw_init(void)
  {
  	int rc;
-@@ -988,7 +960,7 @@ static int __init dump_ccw_init(void)
+@@ -988,7 +966,7 @@ static int __init dump_ccw_init(void)
  	dump_block_ccw = (void *) get_zeroed_page(GFP_KERNEL);
  	if (!dump_block_ccw)
  		return -ENOMEM;
@@ -190694,7 +206628,7 @@
  	if (rc) {
  		free_page((unsigned long)dump_block_ccw);
  		return rc;
-@@ -1012,7 +984,7 @@ static int __init dump_fcp_init(void)
+@@ -1012,7 +990,7 @@ static int __init dump_fcp_init(void)
  	dump_block_fcp = (void *) get_zeroed_page(GFP_KERNEL);
  	if (!dump_block_fcp)
  		return -ENOMEM;
@@ -190703,7 +206637,7 @@
  	if (rc) {
  		free_page((unsigned long)dump_block_fcp);
  		return rc;
-@@ -1026,33 +998,16 @@ static int __init dump_fcp_init(void)
+@@ -1026,33 +1004,16 @@ static int __init dump_fcp_init(void)
  	return 0;
  }
  
@@ -190724,8 +206658,7 @@
 -	.priority = SHUTDOWN_ON_PANIC_PRIO
 -};
 -
--static int __init dump_init(void)
-+static int dump_init(void)
+ static int __init dump_init(void)
  {
  	int rc;
  
@@ -190743,13 +206676,16 @@
  		return rc;
  	}
  	rc = dump_ccw_init();
-@@ -1065,46 +1020,381 @@ static int __init dump_init(void)
+@@ -1065,46 +1026,384 @@ static int __init dump_init(void)
  	return 0;
  }
  
 -static int __init shutdown_actions_init(void)
-+static struct shutdown_action dump_action = {SHUTDOWN_ACTION_DUMP_STR,
-+					     dump_run, dump_init};
++static struct shutdown_action __refdata dump_action = {
++	.name	= SHUTDOWN_ACTION_DUMP_STR,
++	.fn	= dump_run,
++	.init	= dump_init,
++};
 +
 +/*
 + * vmcmd shutdown action: Trigger vm command on shutdown.
@@ -190780,7 +206716,8 @@
 +static struct kset *vmcmd_kset;
 +
 +static void vmcmd_run(struct shutdown_trigger *trigger)
-+{
+ {
+-	int rc;
 +	char *cmd, *next_cmd;
 +
 +	if (strcmp(trigger->name, ON_REIPL_STR) == 0)
@@ -190793,7 +206730,14 @@
 +		cmd = vmcmd_on_poff;
 +	else
 +		return;
-+
+ 
+-	rc = firmware_register(&shutdown_actions_subsys);
+-	if (rc)
+-		return rc;
+-	rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
+-	if (rc) {
+-		firmware_unregister(&shutdown_actions_subsys);
+-		return rc;
 +	if (strlen(cmd) == 0)
 +		return;
 +	do {
@@ -190808,8 +206752,7 @@
 +}
 +
 +static int vmcmd_init(void)
- {
--	int rc;
++{
 +	if (!MACHINE_IS_VM)
 +		return -ENOTSUPP;
 +	vmcmd_kset = kset_create_and_add("vmcmd", NULL, firmware_kobj);
@@ -190817,14 +206760,7 @@
 +		return -ENOMEM;
 +	return sysfs_create_group(&vmcmd_kset->kobj, &vmcmd_attr_group);
 +}
- 
--	rc = firmware_register(&shutdown_actions_subsys);
--	if (rc)
--		return rc;
--	rc = subsys_create_file(&shutdown_actions_subsys, &on_panic_attr);
--	if (rc) {
--		firmware_unregister(&shutdown_actions_subsys);
--		return rc;
++
 +static struct shutdown_action vmcmd_action = {SHUTDOWN_ACTION_VMCMD_STR,
 +					      vmcmd_run, vmcmd_init};
 +
@@ -191152,7 +207088,7 @@
  void __init ipl_save_parameters(void)
  {
  	struct cio_iplinfo iplinfo;
-@@ -1185,3 +1475,4 @@ void s390_reset_system(void)
+@@ -1185,3 +1484,4 @@ void s390_reset_system(void)
  
  	do_reset_calls();
  }
@@ -191253,9 +207189,18 @@
  		wake_up_process(child);
  		return 0;
 diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
-index 577aa7d..766c783 100644
+index 577aa7d..29ae165 100644
 --- a/arch/s390/kernel/setup.c
 +++ b/arch/s390/kernel/setup.c
+@@ -77,7 +77,7 @@ unsigned long machine_flags = 0;
+ unsigned long elf_hwcap = 0;
+ char elf_platform[ELF_PLATFORM_SIZE];
+ 
+-struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
++struct mem_chunk __meminitdata memory_chunk[MEMORY_CHUNKS];
+ volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
+ static unsigned long __initdata memory_end;
+ 
 @@ -126,75 +126,6 @@ void __cpuinit cpu_init(void)
  }
  
@@ -191332,6 +207277,51 @@
   * condev= and conmode= setup parameter.
   */
  
+@@ -214,7 +145,7 @@ __setup("condev=", condev_setup);
+ 
+ static int __init conmode_setup(char *str)
+ {
+-#if defined(CONFIG_SCLP_CONSOLE)
++#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
+ 	if (strncmp(str, "hwc", 4) == 0 || strncmp(str, "sclp", 5) == 0)
+                 SET_CONSOLE_SCLP;
+ #endif
+@@ -252,7 +183,7 @@ static void __init conmode_default(void)
+ 		 */
+ 		cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
+ 		if (ptr == NULL) {
+-#if defined(CONFIG_SCLP_CONSOLE)
++#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
+ 			SET_CONSOLE_SCLP;
+ #endif
+ 			return;
+@@ -262,7 +193,7 @@ static void __init conmode_default(void)
+ 			SET_CONSOLE_3270;
+ #elif defined(CONFIG_TN3215_CONSOLE)
+ 			SET_CONSOLE_3215;
+-#elif defined(CONFIG_SCLP_CONSOLE)
++#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
+ 			SET_CONSOLE_SCLP;
+ #endif
+ 		} else if (strncmp(ptr + 8, "3215", 4) == 0) {
+@@ -270,7 +201,7 @@ static void __init conmode_default(void)
+ 			SET_CONSOLE_3215;
+ #elif defined(CONFIG_TN3270_CONSOLE)
+ 			SET_CONSOLE_3270;
+-#elif defined(CONFIG_SCLP_CONSOLE)
++#elif defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
+ 			SET_CONSOLE_SCLP;
+ #endif
+ 		}
+@@ -281,7 +212,7 @@ static void __init conmode_default(void)
+ 		SET_CONSOLE_3270;
+ #endif
+ 	} else {
+-#if defined(CONFIG_SCLP_CONSOLE)
++#if defined(CONFIG_SCLP_CONSOLE) || defined(CONFIG_SCLP_VT220_CONSOLE)
+ 		SET_CONSOLE_SCLP;
+ #endif
+ 	}
 @@ -308,38 +239,6 @@ static void __init setup_zfcpdump(unsigned int console_devno)
  static inline void setup_zfcpdump(unsigned int console_devno) {}
  #endif /* CONFIG_ZFCPDUMP */
@@ -191399,7 +207389,7 @@
  	memory_end &= PAGE_MASK;
  
 -	max_mem = memory_end ? min(max_phys, memory_end) : max_phys;
-+	max_mem = memory_end ? min(VMALLOC_START, memory_end) : VMALLOC_START;
++	max_mem = memory_end ? min(VMEM_MAX_PHYS, memory_end) : VMEM_MAX_PHYS;
 +	memory_end = min(max_mem, memory_end);
 +
 +	/*
@@ -191508,7 +207498,7 @@
  		return;
  	}
 diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
-index 264ea90..aa37fa1 100644
+index 264ea90..8506065 100644
 --- a/arch/s390/kernel/smp.c
 +++ b/arch/s390/kernel/smp.c
 @@ -42,6 +42,7 @@
@@ -191548,7 +207538,7 @@
  static void smp_ext_bitcall(int, ec_bit_sig);
  
  /*
-@@ -193,6 +210,33 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
+@@ -193,6 +210,32 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
  }
  EXPORT_SYMBOL(smp_call_function_single);
  
@@ -191567,12 +207557,11 @@
 + * You must not call this function with disabled interrupts or from a
 + * hardware interrupt handler or from a bottom half handler.
 + */
-+int
-+smp_call_function_mask(cpumask_t mask,
-+			void (*func)(void *), void *info,
-+			int wait)
++int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
++			   int wait)
 +{
 +	preempt_disable();
++	cpu_clear(smp_processor_id(), mask);
 +	__smp_call_function_map(func, info, 0, wait, mask);
 +	preempt_enable();
 +	return 0;
@@ -191582,7 +207571,7 @@
  void smp_send_stop(void)
  {
  	int cpu, rc;
-@@ -217,33 +261,6 @@ void smp_send_stop(void)
+@@ -217,33 +260,6 @@ void smp_send_stop(void)
  }
  
  /*
@@ -191616,7 +207605,7 @@
   * This is the main routine where commands issued by other
   * cpus are handled.
   */
-@@ -355,6 +372,13 @@ void smp_ctl_clear_bit(int cr, int bit)
+@@ -355,6 +371,13 @@ void smp_ctl_clear_bit(int cr, int bit)
  }
  EXPORT_SYMBOL(smp_ctl_clear_bit);
  
@@ -191630,7 +207619,7 @@
  #if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
  
  /*
-@@ -375,9 +399,10 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
+@@ -375,9 +398,10 @@ static void __init smp_get_save_area(unsigned int cpu, unsigned int phy_cpu)
  		       "kernel was compiled with NR_CPUS=%i\n", cpu, NR_CPUS);
  		return;
  	}
@@ -191644,7 +207633,7 @@
  		cpu_relax();
  	memcpy(zfcpdump_save_areas[cpu],
  	       (void *)(unsigned long) store_prefix() + SAVE_AREA_BASE,
-@@ -397,32 +422,155 @@ static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
+@@ -397,32 +421,155 @@ static inline void smp_get_save_area(unsigned int cpu, unsigned int phy_cpu) { }
  
  #endif /* CONFIG_ZFCPDUMP || CONFIG_ZFCPDUMP_MODULE */
  
@@ -191820,7 +207809,7 @@
  }
  
  /*
-@@ -453,8 +601,6 @@ int __cpuinit start_secondary(void *cpuvoid)
+@@ -453,8 +600,6 @@ int __cpuinit start_secondary(void *cpuvoid)
  	return 0;
  }
  
@@ -191829,7 +207818,7 @@
  static void __init smp_create_idle(unsigned int cpu)
  {
  	struct task_struct *p;
-@@ -470,37 +616,82 @@ static void __init smp_create_idle(unsigned int cpu)
+@@ -470,37 +615,82 @@ static void __init smp_create_idle(unsigned int cpu)
  	spin_lock_init(&(&per_cpu(s390_idle, cpu))->lock);
  }
  
@@ -191930,7 +207919,7 @@
  
  	ccode = signal_processor_p((__u32)(unsigned long)(lowcore_ptr[cpu]),
  				   cpu, sigp_set_prefix);
-@@ -515,6 +706,7 @@ int __cpu_up(unsigned int cpu)
+@@ -515,6 +705,7 @@ int __cpu_up(unsigned int cpu)
  	cpu_lowcore = lowcore_ptr[cpu];
  	cpu_lowcore->kernel_stack = (unsigned long)
  		task_stack_page(idle) + THREAD_SIZE;
@@ -191938,7 +207927,7 @@
  	sf = (struct stack_frame *) (cpu_lowcore->kernel_stack
  				     - sizeof(struct pt_regs)
  				     - sizeof(struct stack_frame));
-@@ -528,6 +720,8 @@ int __cpu_up(unsigned int cpu)
+@@ -528,6 +719,8 @@ int __cpu_up(unsigned int cpu)
  	cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
  	cpu_lowcore->current_task = (unsigned long) idle;
  	cpu_lowcore->cpu_data.cpu_nr = cpu;
@@ -191947,7 +207936,7 @@
  	eieio();
  
  	while (signal_processor(cpu, sigp_restart) == sigp_busy)
-@@ -538,44 +732,20 @@ int __cpu_up(unsigned int cpu)
+@@ -538,44 +731,20 @@ int __cpu_up(unsigned int cpu)
  	return 0;
  }
  
@@ -191999,7 +207988,7 @@
  int __cpu_disable(void)
  {
  	struct ec_creg_mask_parms cr_parms;
-@@ -612,7 +782,8 @@ void __cpu_die(unsigned int cpu)
+@@ -612,7 +781,8 @@ void __cpu_die(unsigned int cpu)
  	/* Wait until target cpu is down */
  	while (!smp_cpu_not_running(cpu))
  		cpu_relax();
@@ -192009,7 +207998,7 @@
  }
  
  void cpu_die(void)
-@@ -625,49 +796,19 @@ void cpu_die(void)
+@@ -625,49 +795,19 @@ void cpu_die(void)
  
  #endif /* CONFIG_HOTPLUG_CPU */
  
@@ -192062,7 +208051,7 @@
  #ifndef CONFIG_64BIT
  	if (MACHINE_HAS_IEEE)
  		ctl_set_bit(14, 29); /* enable extended save area */
-@@ -683,15 +824,17 @@ void __init smp_prepare_boot_cpu(void)
+@@ -683,15 +823,17 @@ void __init smp_prepare_boot_cpu(void)
  {
  	BUG_ON(smp_processor_id() != 0);
  
@@ -192081,7 +208070,7 @@
  }
  
  /*
-@@ -705,7 +848,79 @@ int setup_profiling_timer(unsigned int multiplier)
+@@ -705,7 +847,79 @@ int setup_profiling_timer(unsigned int multiplier)
  	return 0;
  }
  
@@ -192162,7 +208151,7 @@
  
  static ssize_t show_capability(struct sys_device *dev, char *buf)
  {
-@@ -750,15 +965,15 @@ static ssize_t show_idle_time(struct sys_device *dev, char *buf)
+@@ -750,15 +964,15 @@ static ssize_t show_idle_time(struct sys_device *dev, char *buf)
  }
  static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL);
  
@@ -192181,7 +208170,7 @@
  };
  
  static int __cpuinit smp_cpu_notify(struct notifier_block *self,
-@@ -778,12 +993,12 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
+@@ -778,12 +992,12 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
  		idle->idle_time = 0;
  		idle->idle_count = 0;
  		spin_unlock_irq(&idle->lock);
@@ -192196,11 +208185,11 @@
  		break;
  	}
  	return NOTIFY_OK;
-@@ -793,6 +1008,62 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
+@@ -793,6 +1007,62 @@ static struct notifier_block __cpuinitdata smp_cpu_nb = {
  	.notifier_call = smp_cpu_notify,
  };
  
-+static int smp_add_present_cpu(int cpu)
++static int __devinit smp_add_present_cpu(int cpu)
 +{
 +	struct cpu *c = &per_cpu(cpu_devices, cpu);
 +	struct sys_device *s = &c->sysdev;
@@ -192228,8 +208217,8 @@
 +}
 +
 +#ifdef CONFIG_HOTPLUG_CPU
-+static ssize_t rescan_store(struct sys_device *dev, const char *buf,
-+			    size_t count)
++static ssize_t __ref rescan_store(struct sys_device *dev,
++				  const char *buf, size_t count)
 +{
 +	cpumask_t newcpus;
 +	int cpu;
@@ -192259,7 +208248,7 @@
  static int __init topology_init(void)
  {
  	int cpu;
-@@ -800,16 +1071,14 @@ static int __init topology_init(void)
+@@ -800,16 +1070,14 @@ static int __init topology_init(void)
  
  	register_cpu_notifier(&smp_cpu_nb);
  
@@ -192284,6 +208273,79 @@
  		if (rc)
  			return rc;
  	}
+diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
+index da69247..85e46a5 100644
+--- a/arch/s390/kernel/stacktrace.c
++++ b/arch/s390/kernel/stacktrace.c
+@@ -14,7 +14,8 @@
+ static unsigned long save_context_stack(struct stack_trace *trace,
+ 					unsigned long sp,
+ 					unsigned long low,
+-					unsigned long high)
++					unsigned long high,
++					int savesched)
+ {
+ 	struct stack_frame *sf;
+ 	struct pt_regs *regs;
+@@ -47,10 +48,12 @@ static unsigned long save_context_stack(struct stack_trace *trace,
+ 			return sp;
+ 		regs = (struct pt_regs *)sp;
+ 		addr = regs->psw.addr & PSW_ADDR_INSN;
+-		if (!trace->skip)
+-			trace->entries[trace->nr_entries++] = addr;
+-		else
+-			trace->skip--;
++		if (savesched || !in_sched_functions(addr)) {
++			if (!trace->skip)
++				trace->entries[trace->nr_entries++] = addr;
++			else
++				trace->skip--;
++		}
+ 		if (trace->nr_entries >= trace->max_entries)
+ 			return sp;
+ 		low = sp;
+@@ -66,15 +69,27 @@ void save_stack_trace(struct stack_trace *trace)
+ 	orig_sp = sp & PSW_ADDR_INSN;
+ 	new_sp = save_context_stack(trace, orig_sp,
+ 				    S390_lowcore.panic_stack - PAGE_SIZE,
+-				    S390_lowcore.panic_stack);
++				    S390_lowcore.panic_stack, 1);
+ 	if (new_sp != orig_sp)
+ 		return;
+ 	new_sp = save_context_stack(trace, new_sp,
+ 				    S390_lowcore.async_stack - ASYNC_SIZE,
+-				    S390_lowcore.async_stack);
++				    S390_lowcore.async_stack, 1);
+ 	if (new_sp != orig_sp)
+ 		return;
+ 	save_context_stack(trace, new_sp,
+ 			   S390_lowcore.thread_info,
+-			   S390_lowcore.thread_info + THREAD_SIZE);
++			   S390_lowcore.thread_info + THREAD_SIZE, 1);
++}
++
++void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
++{
++	unsigned long sp, low, high;
++
++	sp = tsk->thread.ksp & PSW_ADDR_INSN;
++	low = (unsigned long) task_stack_page(tsk);
++	high = (unsigned long) task_pt_regs(tsk);
++	save_context_stack(trace, sp, low, high, 0);
++	if (trace->nr_entries < trace->max_entries)
++		trace->entries[trace->nr_entries++] = ULONG_MAX;
+ }
+diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
+index 9e26ed9..25eac78 100644
+--- a/arch/s390/kernel/syscalls.S
++++ b/arch/s390/kernel/syscalls.S
+@@ -325,5 +325,5 @@ SYSCALL(sys_utimes,sys_utimes,compat_sys_utimes_wrapper)
+ SYSCALL(s390_fallocate,sys_fallocate,sys_fallocate_wrapper)
+ SYSCALL(sys_utimensat,sys_utimensat,compat_sys_utimensat_wrapper)	/* 315 */
+ SYSCALL(sys_signalfd,sys_signalfd,compat_sys_signalfd_wrapper)
+-SYSCALL(sys_timerfd,sys_timerfd,compat_sys_timerfd_wrapper)
++NI_SYSCALL						/* 317 old sys_timer_fd */
+ SYSCALL(sys_eventfd,sys_eventfd,sys_eventfd_wrapper)
 diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
 index 22b800c..3bbac12 100644
 --- a/arch/s390/kernel/time.c
@@ -192298,7 +208360,7 @@
  
  static struct sys_device etr_port0_dev = {
 diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
-index 8ed16a8..52b8342 100644
+index 8ed16a8..1a2fdb6 100644
 --- a/arch/s390/kernel/traps.c
 +++ b/arch/s390/kernel/traps.c
 @@ -31,6 +31,7 @@
@@ -192327,7 +208389,7 @@
  EXPORT_SYMBOL(dump_stack);
  
  static inline int mask_bits(struct pt_regs *regs, unsigned long bits)
-@@ -258,8 +266,14 @@ void die(const char * str, struct pt_regs * regs, long err)
+@@ -258,8 +266,17 @@ void die(const char * str, struct pt_regs * regs, long err)
  	console_verbose();
  	spin_lock_irq(&die_lock);
  	bust_spinlocks(1);
@@ -192338,14 +208400,17 @@
 +	printk("PREEMPT ");
 +#endif
 +#ifdef CONFIG_SMP
-+	printk("SMP");
++	printk("SMP ");
++#endif
++#ifdef CONFIG_DEBUG_PAGEALLOC
++	printk("DEBUG_PAGEALLOC");
 +#endif
 +	printk("\n");
  	notify_die(DIE_OOPS, str, regs, err, current->thread.trap_no, SIGSEGV);
  	show_regs(regs);
  	bust_spinlocks(0);
 diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
-index 849120e..7d43c3c 100644
+index 849120e..b460715 100644
 --- a/arch/s390/kernel/vmlinux.lds.S
 +++ b/arch/s390/kernel/vmlinux.lds.S
 @@ -17,6 +17,12 @@ ENTRY(_start)
@@ -192361,7 +208426,12 @@
  SECTIONS
  {
  	. = 0x00000000;
-@@ -33,6 +39,9 @@ SECTIONS
+@@ -29,10 +35,13 @@ SECTIONS
+ 		KPROBES_TEXT
+ 		*(.fixup)
+ 		*(.gnu.warning)
+-	} = 0x0700
++	} :text = 0x0700
  
  	_etext = .;		/* End of text section */
  
@@ -192492,8 +208562,46 @@
  static char *segtype_string[] = { "SW", "EW", "SR", "ER", "SN", "EN", "SC",
  					"EW/EN-MIXED" };
  
+diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
+index b234bb4..983ec6e 100644
+--- a/arch/s390/mm/init.c
++++ b/arch/s390/mm/init.c
+@@ -167,6 +167,33 @@ void __init mem_init(void)
+ 	       PFN_ALIGN((unsigned long)&_eshared) - 1);
+ }
+ 
++#ifdef CONFIG_DEBUG_PAGEALLOC
++void kernel_map_pages(struct page *page, int numpages, int enable)
++{
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *pte;
++	unsigned long address;
++	int i;
++
++	for (i = 0; i < numpages; i++) {
++		address = page_to_phys(page + i);
++		pgd = pgd_offset_k(address);
++		pud = pud_offset(pgd, address);
++		pmd = pmd_offset(pud, address);
++		pte = pte_offset_kernel(pmd, address);
++		if (!enable) {
++			ptep_invalidate(address, pte);
++			continue;
++		}
++		*pte = mk_pte_phys(address, __pgprot(_PAGE_TYPE_RW));
++		/* Flush cpu write queue. */
++		mb();
++	}
++}
++#endif
++
+ void free_initmem(void)
+ {
+         unsigned long addr;
 diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
-index fb9c5a8..79d13a1 100644
+index fb9c5a8..7c1287c 100644
 --- a/arch/s390/mm/vmem.c
 +++ b/arch/s390/mm/vmem.c
 @@ -15,10 +15,6 @@
@@ -192507,6 +208615,15 @@
  static DEFINE_MUTEX(vmem_mutex);
  
  struct memory_segment {
+@@ -66,7 +62,7 @@ void __meminit memmap_init(unsigned long size, int nid, unsigned long zone,
+ 	}
+ }
+ 
+-static void __init_refok *vmem_alloc_pages(unsigned int order)
++static void __ref *vmem_alloc_pages(unsigned int order)
+ {
+ 	if (slab_is_available())
+ 		return (void *)__get_free_pages(GFP_KERNEL, order);
 @@ -188,8 +184,8 @@ static int vmem_add_mem_map(unsigned long start, unsigned long size)
  	pte_t  pte;
  	int ret = -ENOMEM;
@@ -192536,11 +208653,11 @@
  	struct memory_segment *tmp;
  
 -	if (PFN_DOWN(seg->start + seg->size) > max_pfn ||
-+	if (seg->start + seg->size >= VMALLOC_START ||
++	if (seg->start + seg->size >= VMEM_MAX_PHYS ||
  	    seg->start + seg->size < seg->start)
  		return -ERANGE;
  
-@@ -357,17 +353,15 @@ out:
+@@ -357,17 +353,14 @@ out:
  
  /*
   * map whole physical memory to virtual memory (identity mapping)
@@ -192557,12 +208674,11 @@
 -	vmem_map = (struct page *) vmalloc_end;
 -	NODE_DATA(0)->node_mem_map = vmem_map;
 -
-+	BUILD_BUG_ON((unsigned long)VMEM_MAP + VMEM_MAP_SIZE > VMEM_MAP_MAX);
 +	NODE_DATA(0)->node_mem_map = VMEM_MAP;
  	for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++)
  		vmem_add_mem(memory_chunk[i].addr, memory_chunk[i].size);
  }
-@@ -382,7 +376,7 @@ static int __init vmem_convert_memory_chunk(void)
+@@ -382,7 +375,7 @@ static int __init vmem_convert_memory_chunk(void)
  	int i;
  
  	mutex_lock(&vmem_mutex);
@@ -192572,10 +208688,10 @@
  			continue;
  		seg = kzalloc(sizeof(*seg), GFP_KERNEL);
 diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
-index 496d635..b30c4c3 100644
+index 496d635..1c3a908 100644
 --- a/arch/sh/Kconfig
 +++ b/arch/sh/Kconfig
-@@ -6,8 +6,7 @@
+@@ -6,45 +6,45 @@
  mainmenu "Linux/SuperH Kernel Configuration"
  
  config SUPERH
@@ -192583,9 +208699,10 @@
 -	default y
 +	def_bool y
  	select EMBEDDED
++	select HAVE_OPROFILE
  	help
  	  The SuperH is a RISC processor targeted for use in embedded systems
-@@ -15,36 +14,36 @@ config SUPERH
+ 	  and consumer electronics; it was also used in the Sega Dreamcast
  	  gaming console.  The SuperH port has a home page at
  	  <http://www.linux-sh.org/>.
  
@@ -192635,7 +208752,7 @@
  
  config GENERIC_IOMAP
  	bool
-@@ -75,20 +74,16 @@ config ARCH_MAY_HAVE_PC_FDC
+@@ -75,20 +75,16 @@ config ARCH_MAY_HAVE_PC_FDC
  	bool
  
  config STACKTRACE_SUPPORT
@@ -192660,7 +208777,7 @@
  
  config ARCH_NO_VIRT_TO_BUS
  	def_bool y
-@@ -97,110 +92,234 @@ source "init/Kconfig"
+@@ -97,110 +93,234 @@ source "init/Kconfig"
  
  menu "System type"
  
@@ -192699,11 +208816,11 @@
 +config CPU_SH5
 +	bool
 +	select CPU_HAS_FPU
-+
-+config CPU_SHX2
-+	bool
  
 -menu "Processor features"
++config CPU_SHX2
++	bool
++
 +config CPU_SHX3
 +	bool
  
@@ -192747,15 +208864,15 @@
 +	select CPU_HAS_FPU
 +
 +# SH-3 Processor Support
++
++config CPU_SUBTYPE_SH7705
++	bool "Support SH7705 processor"
++	select CPU_SH3
  
 -config SH_FPU
 -	bool "FPU support"
 -	depends on CPU_HAS_FPU
 -	default y
-+config CPU_SUBTYPE_SH7705
-+	bool "Support SH7705 processor"
-+	select CPU_SH3
-+
 +config CPU_SUBTYPE_SH7706
 +	bool "Support SH7706 processor"
 +	select CPU_SH3
@@ -192837,12 +208954,12 @@
 -	  Selecting this option will enable an in-kernel API for manipulating
 -	  the store queues integrated in the SH-4 processors.
 +	  Select SH7721 if you have a SH3-DSP SH7721 CPU.
-+
-+# SH-4 Processor Support
  
 -config SPECULATIVE_EXECUTION
 -	bool "Speculative subroutine return"
 -	depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL
++# SH-4 Processor Support
++
 +config CPU_SUBTYPE_SH7750
 +	bool "Support SH7750 processor"
 +	select CPU_SH4
@@ -192967,7 +209084,7 @@
  
  menu "Board support"
  
-@@ -321,13 +440,6 @@ config SH_SECUREEDGE5410
+@@ -321,13 +441,6 @@ config SH_SECUREEDGE5410
  	  This includes both the OEM SecureEdge products as well as the
  	  SME product line.
  
@@ -192981,7 +209098,7 @@
  config SH_7710VOIPGW
  	bool "SH7710-VOIP-GW"
  	depends on CPU_SUBTYPE_SH7710
-@@ -343,6 +455,14 @@ config SH_RTS7751R2D
+@@ -343,6 +456,14 @@ config SH_RTS7751R2D
  	  Select RTS7751R2D if configuring for a Renesas Technology
  	  Sales SH-Graphics board.
  
@@ -192996,7 +209113,7 @@
  config SH_HIGHLANDER
  	bool "Highlander"
  	depends on CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785
-@@ -399,41 +519,47 @@ config SH_MAGIC_PANEL_R2
+@@ -399,41 +520,47 @@ config SH_MAGIC_PANEL_R2
  	help
  	  Select Magic Panel R2 if configuring for Magic Panel R2.
  
@@ -193052,7 +209169,7 @@
  	default "86" if CPU_SUBTYPE_SH7619
  	default "140" if CPU_SUBTYPE_SH7206
  	default "16"
-@@ -445,7 +571,8 @@ config SH_PCLK_FREQ
+@@ -445,7 +572,8 @@ config SH_PCLK_FREQ
  	default "32000000" if CPU_SUBTYPE_SH7722
  	default "33333333" if CPU_SUBTYPE_SH7770 || \
  			      CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \
@@ -193062,7 +209179,7 @@
  	default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R
  	default "66000000" if CPU_SUBTYPE_SH4_202
  	default "50000000"
-@@ -456,7 +583,7 @@ config SH_PCLK_FREQ
+@@ -456,7 +584,7 @@ config SH_PCLK_FREQ
  
  config SH_CLK_MD
  	int "CPU Mode Pin Setting"
@@ -193071,7 +209188,7 @@
  	default 6 if CPU_SUBTYPE_SH7206
  	default 5 if CPU_SUBTYPE_SH7619
  	default 0
-@@ -490,9 +617,8 @@ source "arch/sh/drivers/Kconfig"
+@@ -490,9 +618,8 @@ source "arch/sh/drivers/Kconfig"
  endmenu
  
  config ISA_DMA_API
@@ -193082,6 +209199,18 @@
  
  menu "Kernel features"
  
+@@ -546,9 +673,8 @@ config SMP
+ 	  People using multiprocessor machines who say Y here should also say
+ 	  Y to "Enhanced Real Time Clock Support", below.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available
+-	  at <http://www.tldp.org/docs.html#howto>.
++	  See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
++	  available at <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
+ 
 @@ -570,7 +696,7 @@ source "kernel/Kconfig.preempt"
  
  config GUSA
@@ -193119,6 +209248,15 @@
  source kernel/power/Kconfig
  
  endmenu
+@@ -756,8 +896,6 @@ source "drivers/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/sh/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/sh/Kconfig.cpu b/arch/sh/Kconfig.cpu
 new file mode 100644
 index 0000000..d850184
@@ -217530,7 +233668,7 @@
 -	.long sys_fallocate
 diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
 new file mode 100644
-index 0000000..10bec45
+index 0000000..719e127
 --- /dev/null
 +++ b/arch/sh/kernel/syscalls_32.S
 @@ -0,0 +1,343 @@
@@ -217874,12 +234012,12 @@
 +	.long sys_epoll_pwait
 +	.long sys_utimensat		/* 320 */
 +	.long sys_signalfd
-+	.long sys_timerfd
++	.long sys_ni_syscall
 +	.long sys_eventfd
 +	.long sys_fallocate
 diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
 new file mode 100644
-index 0000000..98a93ef
+index 0000000..12c7340
 --- /dev/null
 +++ b/arch/sh/kernel/syscalls_64.S
 @@ -0,0 +1,381 @@
@@ -218261,7 +234399,7 @@
 +	.long sys_epoll_pwait
 +	.long sys_utimensat
 +	.long sys_signalfd
-+	.long sys_timerfd		/* 350 */
++	.long sys_ni_syscall		/* 350 */
 +	.long sys_eventfd
 +	.long sys_fallocate
 diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
@@ -249031,6 +265169,74 @@
 -{
 -}
 -
+diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
+index 527adc8..99f8971 100644
+--- a/arch/sparc/Kconfig
++++ b/arch/sparc/Kconfig
+@@ -48,9 +48,8 @@ config SMP
+ 	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+ 	  Management" code will be disabled if you say Y here.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+-	  <http://www.tldp.org/docs.html#howto>.
++	  See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
++	  available at <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
+ 
+@@ -63,6 +62,7 @@ config NR_CPUS
+ config SPARC
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
+ 
+ # Identify this as a Sparc32 build
+ config SPARC32
+@@ -320,8 +320,6 @@ endmenu
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/sparc/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
+index 97aa50d..ad0ede2 100644
+--- a/arch/sparc/kernel/ioport.c
++++ b/arch/sparc/kernel/ioport.c
+@@ -305,7 +305,7 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
+ 	struct resource *res;
+ 	int order;
+ 
+-	/* XXX why are some lenghts signed, others unsigned? */
++	/* XXX why are some lengths signed, others unsigned? */
+ 	if (len <= 0) {
+ 		return NULL;
+ 	}
+@@ -393,7 +393,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba)
+  */
+ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int direction)
+ {
+-	/* XXX why are some lenghts signed, others unsigned? */
++	/* XXX why are some lengths signed, others unsigned? */
+ 	if (len <= 0) {
+ 		return 0;
+ 	}
+diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
+index 5572284..ee010f4 100644
+--- a/arch/sparc/kernel/systbls.S
++++ b/arch/sparc/kernel/systbls.S
+@@ -79,7 +79,7 @@ sys_call_table:
+ /*295*/	.long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
+ /*300*/	.long sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
+ /*305*/	.long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+-/*310*/	.long sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
++/*310*/	.long sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
+ 
+ #ifdef CONFIG_SUNOS_EMUL
+ 	/* Now the SunOS syscall table. */
 diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
 index a8b4200..216147d 100644
 --- a/arch/sparc/kernel/vmlinux.lds.S
@@ -249075,10 +265281,19 @@
  
  	.globl		___down_read
 diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
-index 10b212a..158522f 100644
+index 10b212a..a8c6366 100644
 --- a/arch/sparc64/Kconfig
 +++ b/arch/sparc64/Kconfig
-@@ -66,6 +66,9 @@ config AUDIT_ARCH
+@@ -8,6 +8,8 @@ mainmenu "Linux/UltraSPARC Kernel Configuration"
+ config SPARC
+ 	bool
+ 	default y
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
+ 
+ config SPARC64
+ 	bool
+@@ -66,6 +68,9 @@ config AUDIT_ARCH
  	bool
  	default y
  
@@ -249088,7 +265303,19 @@
  config ARCH_NO_VIRT_TO_BUS
  	def_bool y
  
-@@ -200,6 +203,11 @@ config US2E_FREQ
+@@ -163,9 +168,8 @@ config SMP
+ 	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+ 	  Management" code will be disabled if you say Y here.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+-	  <http://www.tldp.org/docs.html#howto>.
++	  See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
++	  available at <http://www.tldp.org/docs.html#howto>.
+ 
+ 	  If you don't know what to do here, say N.
+ 
+@@ -200,6 +204,11 @@ config US2E_FREQ
  	  If in doubt, say N.
  
  # Global things across all Sun machines.
@@ -249100,7 +265327,7 @@
  config RWSEM_GENERIC_SPINLOCK
  	bool
  
-@@ -343,11 +351,6 @@ config PCI
+@@ -343,11 +352,6 @@ config PCI
  	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
  	  VESA. If you have PCI, say Y, otherwise N.
  
@@ -249112,6 +265339,140 @@
  config PCI_DOMAINS
  	def_bool PCI
  
+@@ -462,8 +466,6 @@ source "drivers/sbus/char/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/sparc64/Kconfig.debug"
+ 
+ source "security/Kconfig"
+diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
+index 070a484..4b9115a 100644
+--- a/arch/sparc64/kernel/iommu.c
++++ b/arch/sparc64/kernel/iommu.c
+@@ -580,7 +580,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
+ 
+ 	/* Step 1: Prepare scatter list. */
+ 
+-	npages = prepare_sg(sglist, nelems);
++	npages = prepare_sg(dev, sglist, nelems);
+ 
+ 	/* Step 2: Allocate a cluster and context, if necessary. */
+ 
+diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
+index efd5dff..72a4acf 100644
+--- a/arch/sparc64/kernel/iommu_common.c
++++ b/arch/sparc64/kernel/iommu_common.c
+@@ -4,6 +4,7 @@
+  * Copyright (C) 1999 David S. Miller (davem at redhat.com)
+  */
+ 
++#include <linux/dma-mapping.h>
+ #include "iommu_common.h"
+ 
+ /* You are _strongly_ advised to enable the following debugging code
+@@ -201,21 +202,24 @@ void verify_sglist(struct scatterlist *sglist, int nents, iopte_t *iopte, int np
+ }
+ #endif
+ 
+-unsigned long prepare_sg(struct scatterlist *sg, int nents)
++unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents)
+ {
+ 	struct scatterlist *dma_sg = sg;
+ 	unsigned long prev;
+ 	u32 dent_addr, dent_len;
++	unsigned int max_seg_size;
+ 
+ 	prev  = (unsigned long) sg_virt(sg);
+ 	prev += (unsigned long) (dent_len = sg->length);
+ 	dent_addr = (u32) ((unsigned long)(sg_virt(sg)) & (IO_PAGE_SIZE - 1UL));
++	max_seg_size = dma_get_max_seg_size(dev);
+ 	while (--nents) {
+ 		unsigned long addr;
+ 
+ 		sg = sg_next(sg);
+ 		addr = (unsigned long) sg_virt(sg);
+-		if (! VCONTIG(prev, addr)) {
++		if (! VCONTIG(prev, addr) ||
++			dent_len + sg->length > max_seg_size) {
+ 			dma_sg->dma_address = dent_addr;
+ 			dma_sg->dma_length = dent_len;
+ 			dma_sg = sg_next(dma_sg);
+diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
+index 75b5a58..a90d046 100644
+--- a/arch/sparc64/kernel/iommu_common.h
++++ b/arch/sparc64/kernel/iommu_common.h
+@@ -9,6 +9,7 @@
+ #include <linux/sched.h>
+ #include <linux/mm.h>
+ #include <linux/scatterlist.h>
++#include <linux/device.h>
+ 
+ #include <asm/iommu.h>
+ #include <asm/scatterlist.h>
+@@ -46,4 +47,4 @@ extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int
+ #define VCONTIG(__X, __Y)	(((__X) == (__Y)) || \
+ 				 (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
+ 
+-extern unsigned long prepare_sg(struct scatterlist *sg, int nents);
++extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents);
+diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
+index 1aa8e04..5ea2eab 100644
+--- a/arch/sparc64/kernel/pci_sun4v.c
++++ b/arch/sparc64/kernel/pci_sun4v.c
+@@ -490,7 +490,7 @@ static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
+ 		goto bad;
+ 
+ 	/* Step 1: Prepare scatter list. */
+-	npages = prepare_sg(sglist, nelems);
++	npages = prepare_sg(dev, sglist, nelems);
+ 
+ 	/* Step 2: Allocate a cluster and context, if necessary. */
+ 	spin_lock_irqsave(&iommu->lock, flags);
+@@ -625,8 +625,8 @@ static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
+ 	/* XXX register error interrupt handlers XXX */
+ }
+ 
+-static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
+-					    struct iommu *iommu)
++static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm,
++						   struct iommu *iommu)
+ {
+ 	struct iommu_arena *arena = &iommu->arena;
+ 	unsigned long i, cnt = 0;
+@@ -653,7 +653,7 @@ static unsigned long probe_existing_entries(struct pci_pbm_info *pbm,
+ 	return cnt;
+ }
+ 
+-static void pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
++static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm)
+ {
+ 	struct iommu *iommu = pbm->iommu;
+ 	struct property *prop;
+diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
+index 06d1090..b805890 100644
+--- a/arch/sparc64/kernel/systbls.S
++++ b/arch/sparc64/kernel/systbls.S
+@@ -80,7 +80,7 @@ sys_call_table32:
+ 	.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
+ /*300*/	.word compat_sys_set_robust_list, compat_sys_get_robust_list, compat_sys_migrate_pages, compat_sys_mbind, compat_sys_get_mempolicy
+ 	.word compat_sys_set_mempolicy, compat_sys_kexec_load, compat_sys_move_pages, sys_getcpu, compat_sys_epoll_pwait
+-/*310*/	.word compat_sys_utimensat, compat_sys_signalfd, compat_sys_timerfd, sys_eventfd, compat_sys_fallocate
++/*310*/	.word compat_sys_utimensat, compat_sys_signalfd, sys_ni_syscall, sys_eventfd, compat_sys_fallocate
+ 
+ #endif /* CONFIG_COMPAT */
+ 
+@@ -152,7 +152,7 @@ sys_call_table:
+ 	.word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare
+ /*300*/	.word sys_set_robust_list, sys_get_robust_list, sys_migrate_pages, sys_mbind, sys_get_mempolicy
+ 	.word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait
+-/*310*/	.word sys_utimensat, sys_signalfd, sys_timerfd, sys_eventfd, sys_fallocate
++/*310*/	.word sys_utimensat, sys_signalfd, sys_ni_syscall, sys_eventfd, sys_fallocate
+ 
+ #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
+     defined(CONFIG_SOLARIS_EMUL_MODULE)
 diff --git a/arch/sparc64/kernel/unaligned.c b/arch/sparc64/kernel/unaligned.c
 index 953be81..dc7bf1b 100644
 --- a/arch/sparc64/kernel/unaligned.c
@@ -249209,11 +265570,723 @@
  void __init paging_init(void)
  {
  	unsigned long end_pfn, pages_avail, shift, phys_base;
+diff --git a/arch/um/Kconfig b/arch/um/Kconfig
+index dd1689b..99e51d0 100644
+--- a/arch/um/Kconfig
++++ b/arch/um/Kconfig
+@@ -68,6 +68,10 @@ config IRQ_RELEASE_METHOD
+ 	bool
+ 	default y
+ 
++config HZ
++	int
++	default 100
++
+ menu "UML-specific options"
+ 
+ config STATIC_LINK
+@@ -95,23 +99,6 @@ config LD_SCRIPT_DYN
+ 	default y
+ 	depends on !LD_SCRIPT_STATIC
+ 
+-config NET
+-	bool "Networking support"
+-	help
+-	  Unless you really know what you are doing, you should say Y here.
+-	  The reason is that some programs need kernel networking support even
+-	  when running on a stand-alone machine that isn't connected to any
+-	  other computer. If you are upgrading from an older kernel, you
+-	  should consider updating your networking tools too because changes
+-	  in the kernel and the tools often go hand in hand. The tools are
+-	  contained in the package net-tools, the location and version number
+-	  of which are given in <file:Documentation/Changes>.
+-
+-	  For a general introduction to Linux networking, it is highly
+-	  recommended to read the NET-HOWTO, available from
+-	  <http://www.tldp.org/docs.html#howto>.
+-
+-
+ source "fs/Kconfig.binfmt"
+ 
+ config HOSTFS
+@@ -145,7 +132,7 @@ config HPPFS
+ 	  by removing or changing anything in /proc which gives away the
+ 	  identity of a UML.
+ 
+-	  See <http://user-mode-linux.sf.net/hppfs.html> for more information.
++	  See <http://user-mode-linux.sf.net/old/hppfs.html> for more information.
+ 
+ 	  You only need this if you are setting up a UML honeypot.  Otherwise,
+ 	  it is safe to say 'N' here.
+@@ -189,8 +176,7 @@ config MAGIC_SYSRQ
+ config SMP
+ 	bool "Symmetric multi-processing support (EXPERIMENTAL)"
+ 	default n
+-	#SMP_BROKEN is for x86_64.
+-	depends on EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN))
++	depends on BROKEN
+ 	help
+ 	  This option enables UML SMP support.
+ 	  It is NOT related to having a real SMP box. Not directly, at least.
+@@ -289,6 +275,4 @@ config INPUT
+ 	bool
+ 	default n
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/um/Kconfig.debug"
+diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char
+index 9a78d35..3a4b396 100644
+--- a/arch/um/Kconfig.char
++++ b/arch/um/Kconfig.char
+@@ -18,7 +18,7 @@ config SSL
+           lines on the UML that are usually made to show up on the host as
+           ttys or ptys.
+ 
+-          See <http://user-mode-linux.sourceforge.net/input.html> for more
++          See <http://user-mode-linux.sourceforge.net/old/input.html> for more
+           information and command line examples of how to use this facility.
+ 
+           Unless you have a specific reason for disabling this, say Y.
+diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
+index 1f6462f..8fce5e5 100644
+--- a/arch/um/Kconfig.debug
++++ b/arch/um/Kconfig.debug
+@@ -4,12 +4,12 @@ source "lib/Kconfig.debug"
+ 
+ config GPROF
+ 	bool "Enable gprof support"
+-	depends on DEBUG_INFO
++	depends on DEBUG_INFO && FRAME_POINTER
+ 	help
+ 	  This allows profiling of a User-Mode Linux kernel with the gprof
+ 	  utility.
+ 
+-	  See <http://user-mode-linux.sourceforge.net/gprof.html> for more
++	  See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
+ 	  details.
+ 
+ 	  If you're involved in UML kernel development and want to use gprof,
+@@ -22,7 +22,7 @@ config GCOV
+ 	  This option allows developers to retrieve coverage data from a UML
+ 	  session.
+ 
+-	  See <http://user-mode-linux.sourceforge.net/gprof.html> for more
++	  See <http://user-mode-linux.sourceforge.net/old/gprof.html> for more
+ 	  details.
+ 
+ 	  If you're involved in UML kernel development and want to use gcov,
+diff --git a/arch/um/Kconfig.net b/arch/um/Kconfig.net
+index 66e5002..9e9a4aa 100644
+--- a/arch/um/Kconfig.net
++++ b/arch/um/Kconfig.net
+@@ -14,7 +14,7 @@ config UML_NET
+ 
+         For more information, including explanations of the networking and
+         sample configurations, see
+-        <http://user-mode-linux.sourceforge.net/networking.html>.
++        <http://user-mode-linux.sourceforge.net/old/networking.html>.
+ 
+         If you'd like to be able to enable networking in the User-Mode
+         linux environment, say Y; otherwise say N.  Note that you must
+@@ -38,7 +38,7 @@ config UML_NET_ETHERTAP
+         CONFIG_NETLINK_DEV configured as Y or M.
+ 
+         For more information, see
+-        <http://user-mode-linux.sourceforge.net/networking.html>  That site
++        <http://user-mode-linux.sourceforge.net/old/networking.html>  That site
+         has examples of the UML command line to use to enable Ethertap
+         networking.
+ 
+@@ -72,7 +72,7 @@ config UML_NET_SLIP
+         To use this, your host must support slip devices.
+ 
+         For more information, see
+-        <http://user-mode-linux.sourceforge.net/networking.html>.  That site
++        <http://user-mode-linux.sourceforge.net/old/networking.html>.
+         has examples of the UML command line to use to enable slip
+         networking, and details of a few quirks with it.
+ 
+@@ -96,7 +96,7 @@ config UML_NET_DAEMON
+         networking daemon on the host.
+ 
+         For more information, see
+-        <http://user-mode-linux.sourceforge.net/networking.html>  That site
++        <http://user-mode-linux.sourceforge.net/old/networking.html>  That site
+         has examples of the UML command line to use to enable Daemon
+         networking.
+ 
+@@ -144,7 +144,7 @@ config UML_NET_MCAST
+         To use this, your host kernel(s) must support IP Multicasting.
+ 
+         For more information, see
+-        <http://user-mode-linux.sourceforge.net/networking.html>  That site
++        <http://user-mode-linux.sourceforge.net/old/networking.html>  That site
+         has examples of the UML command line to use to enable Multicast
+         networking, and notes about the security of this approach.
+ 
+@@ -165,7 +165,7 @@ config UML_NET_PCAP
+ 	installed in order to build the pcap transport into UML.
+ 
+         For more information, see
+-        <http://user-mode-linux.sourceforge.net/networking.html>  That site
++        <http://user-mode-linux.sourceforge.net/old/networking.html>  That site
+         has examples of the UML command line to use to enable this option.
+ 
+ 	If you intend to use UML as a network monitor for the host, say
+diff --git a/arch/um/Makefile b/arch/um/Makefile
+index ba6813a..cb4af9b 100644
+--- a/arch/um/Makefile
++++ b/arch/um/Makefile
+@@ -49,7 +49,7 @@ SYS_DIR		:= $(ARCH_DIR)/include/sysdep-$(SUBARCH)
+ #
+ # These apply to USER_CFLAGS to.
+ 
+-KBUILD_CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\"	\
++KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
+ 	$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap	\
+ 	-Din6addr_loopback=kernel_in6addr_loopback \
+ 	-Din6addr_any=kernel_in6addr_any
+@@ -58,7 +58,7 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
+ 
+ USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\
+ 	$(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \
+-	-D_FILE_OFFSET_BITS=64
++	$(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64
+ 
+ include $(srctree)/$(ARCH_DIR)/Makefile-$(SUBARCH)
+ 
+@@ -130,7 +130,9 @@ CPPFLAGS_vmlinux.lds = -U$(SUBARCH) -DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
+ # The wrappers will select whether using "malloc" or the kernel allocator.
+ LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
+ 
+-CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS)
++LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
++
++CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
+ define cmd_vmlinux__
+ 	$(CC) $(CFLAGS_vmlinux) -o $@ \
+ 	-Wl,-T,$(vmlinux-lds) $(vmlinux-init) \
+@@ -158,7 +160,7 @@ ifneq ($(KBUILD_SRC),)
+ 	$(Q)mkdir -p $(objtree)/include/asm-um
+ 	$(Q)ln -fsn $(srctree)/include/asm-um/$(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $@
+ else
+-	$(Q)cd $(TOPDIR)/$(dir $@) ; \
++	$(Q)cd $(srctree)/$(dir $@) ; \
+ 	ln -sf $(basename $(notdir $@))-$(SUBARCH)$(suffix $@) $(notdir $@)
+ endif
+ 
+@@ -168,7 +170,7 @@ ifneq ($(KBUILD_SRC),)
+ 	$(Q)mkdir -p $(objtree)/include/asm-um
+ 	$(Q)ln -fsn $(srctree)/include/asm-$(HEADER_ARCH) include/asm-um/arch
+ else
+-	$(Q)cd $(TOPDIR)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
++	$(Q)cd $(srctree)/include/asm-um && ln -fsn ../asm-$(HEADER_ARCH) arch
+ endif
+ 
+ $(objtree)/$(ARCH_DIR)/include:
+diff --git a/arch/um/Makefile-tt b/arch/um/Makefile-tt
+deleted file mode 100644
+index 03f7b10..0000000
+--- a/arch/um/Makefile-tt
++++ /dev/null
+@@ -1,5 +0,0 @@
+-# 
+-# Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
+-# Licensed under the GPL
+-#
+-
+diff --git a/arch/um/defconfig b/arch/um/defconfig
+index f609ede..86db286 100644
+--- a/arch/um/defconfig
++++ b/arch/um/defconfig
+@@ -77,7 +77,7 @@ CONFIG_LD_SCRIPT_DYN=y
+ CONFIG_NET=y
+ CONFIG_BINFMT_ELF=y
+ CONFIG_BINFMT_MISC=m
+-# CONFIG_HOSTFS is not set
++CONFIG_HOSTFS=y
+ # CONFIG_HPPFS is not set
+ CONFIG_MCONSOLE=y
+ CONFIG_MAGIC_SYSRQ=y
+@@ -188,7 +188,7 @@ CONFIG_CON_CHAN="xterm"
+ CONFIG_SSL_CHAN="pts"
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_LEGACY_PTYS=y
+-CONFIG_LEGACY_PTY_COUNT=256
++CONFIG_LEGACY_PTY_COUNT=32
+ # CONFIG_WATCHDOG is not set
+ CONFIG_UML_SOUND=m
+ CONFIG_SOUND=m
+@@ -508,7 +508,7 @@ CONFIG_DEBUG_KERNEL=y
+ CONFIG_LOG_BUF_SHIFT=14
+ CONFIG_DETECT_SOFTLOCKUP=y
+ # CONFIG_SCHEDSTATS is not set
+-CONFIG_DEBUG_SLAB=y
++# CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_SLAB_LEAK is not set
+ # CONFIG_DEBUG_MUTEXES is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
+index 83bf15a..2c898c4 100644
+--- a/arch/um/drivers/line.c
++++ b/arch/um/drivers/line.c
+@@ -8,6 +8,7 @@
+ #include "chan_kern.h"
+ #include "irq_kern.h"
+ #include "irq_user.h"
++#include "kern_util.h"
+ #include "os.h"
+ 
+ #define LINE_BUFSIZE 4096
+@@ -48,7 +49,7 @@ static int write_room(struct line *line)
+ 	n = line->head - line->tail;
+ 
+ 	if (n <= 0)
+-		n = LINE_BUFSIZE + n; /* The other case */
++		n += LINE_BUFSIZE; /* The other case */
+ 	return n - 1;
+ }
+ 
+@@ -58,17 +59,10 @@ int line_write_room(struct tty_struct *tty)
+ 	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;
+ }
+ 
+@@ -79,8 +73,7 @@ int line_chars_in_buffer(struct tty_struct *tty)
+ 	int ret;
+ 
+ 	spin_lock_irqsave(&line->lock, flags);
+-
+-	/*write_room subtracts 1 for the needed NULL, so we readd it.*/
++	/* 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);
+ 
+@@ -184,10 +177,6 @@ void line_flush_buffer(struct tty_struct *tty)
+ 	unsigned long flags;
+ 	int err;
+ 
+-	/*XXX: copied from line_write, verify if it is correct!*/
+-	if (tty->stopped)
+-		return;
+-
+ 	spin_lock_irqsave(&line->lock, flags);
+ 	err = flush_buffer(line);
+ 	spin_unlock_irqrestore(&line->lock, flags);
+@@ -213,9 +202,6 @@ int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
+ 	unsigned long flags;
+ 	int n, ret = 0;
+ 
+-	if (tty->stopped)
+-		return 0;
+-
+ 	spin_lock_irqsave(&line->lock, flags);
+ 	if (line->head != line->tail)
+ 		ret = buffer_data(line, buf, len);
+@@ -788,9 +774,11 @@ static irqreturn_t winch_interrupt(int irq, void *data)
+ 	tty = winch->tty;
+ 	if (tty != NULL) {
+ 		line = tty->driver_data;
+-		chan_window_size(&line->chan_list, &tty->winsize.ws_row,
+-				 &tty->winsize.ws_col);
+-		kill_pgrp(tty->pgrp, SIGWINCH, 1);
++		if (line != NULL) {
++			chan_window_size(&line->chan_list, &tty->winsize.ws_row,
++					 &tty->winsize.ws_col);
++			kill_pgrp(tty->pgrp, SIGWINCH, 1);
++		}
+ 	}
+  out:
+ 	if (winch->fd != -1)
+diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
+index 0f3c7d1..ebb265c 100644
+--- a/arch/um/drivers/mconsole_kern.c
++++ b/arch/um/drivers/mconsole_kern.c
+@@ -1,23 +1,25 @@
+ /*
+  * Copyright (C) 2001 Lennert Buytenhek (buytenh at gnu.org)
+- * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
++ * Copyright (C) 2001 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+-#include "linux/console.h"
+-#include "linux/ctype.h"
+-#include "linux/interrupt.h"
+-#include "linux/list.h"
+-#include "linux/mm.h"
+-#include "linux/module.h"
+-#include "linux/notifier.h"
+-#include "linux/reboot.h"
+-#include "linux/proc_fs.h"
+-#include "linux/slab.h"
+-#include "linux/syscalls.h"
+-#include "linux/utsname.h"
+-#include "linux/workqueue.h"
+-#include "asm/uaccess.h"
++#include <linux/console.h>
++#include <linux/ctype.h>
++#include <linux/interrupt.h>
++#include <linux/list.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/notifier.h>
++#include <linux/reboot.h>
++#include <linux/proc_fs.h>
++#include <linux/slab.h>
++#include <linux/syscalls.h>
++#include <linux/utsname.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
++#include <asm/uaccess.h>
++
+ #include "init.h"
+ #include "irq_kern.h"
+ #include "irq_user.h"
+@@ -305,7 +307,9 @@ void mconsole_stop(struct mc_request *req)
+ 	deactivate_fd(req->originating_fd, MCONSOLE_IRQ);
+ 	os_set_fd_block(req->originating_fd, 1);
+ 	mconsole_reply(req, "stopped", 0, 0);
+-	while (mconsole_get_request(req->originating_fd, req)) {
++	for (;;) {
++		if (!mconsole_get_request(req->originating_fd, req))
++			continue;
+ 		if (req->cmd->handler == mconsole_go)
+ 			break;
+ 		if (req->cmd->handler == mconsole_stop) {
+@@ -358,7 +362,7 @@ struct unplugged_pages {
+ 	void *pages[UNPLUGGED_PER_PAGE];
+ };
+ 
+-static DECLARE_MUTEX(plug_mem_mutex);
++static DEFINE_MUTEX(plug_mem_mutex);
+ static unsigned long long unplugged_pages_count = 0;
+ static LIST_HEAD(unplugged_pages);
+ static int unplug_index = UNPLUGGED_PER_PAGE;
+@@ -394,7 +398,7 @@ static int mem_config(char *str, char **error_out)
+ 
+ 	diff /= PAGE_SIZE;
+ 
+-	down(&plug_mem_mutex);
++	mutex_lock(&plug_mem_mutex);
+ 	for (i = 0; i < diff; i++) {
+ 		struct unplugged_pages *unplugged;
+ 		void *addr;
+@@ -451,7 +455,7 @@ static int mem_config(char *str, char **error_out)
+ 
+ 	err = 0;
+ out_unlock:
+-	up(&plug_mem_mutex);
++	mutex_unlock(&plug_mem_mutex);
+ out:
+ 	return err;
+ }
+@@ -741,7 +745,6 @@ void mconsole_stack(struct mc_request *req)
+ {
+ 	char *ptr = req->request.data;
+ 	int pid_requested= -1;
+-	struct task_struct *from = NULL;
+ 	struct task_struct *to = NULL;
+ 
+ 	/*
+@@ -763,9 +766,7 @@ void mconsole_stack(struct mc_request *req)
+ 		return;
+ 	}
+ 
+-	from = current;
+-
+-	to = find_task_by_pid(pid_requested);
++	to = find_task_by_pid_ns(pid_requested, &init_pid_ns);
+ 	if ((to == NULL) || (pid_requested == 0)) {
+ 		mconsole_reply(req, "Couldn't find that pid", 1, 0);
+ 		return;
+@@ -795,6 +796,8 @@ static int __init mconsole_init(void)
+ 		printk(KERN_ERR "Failed to initialize management console\n");
+ 		return 1;
+ 	}
++	if (os_set_fd_block(sock, 0))
++		goto out;
+ 
+ 	register_reboot_notifier(&reboot_notifier);
+ 
+@@ -803,7 +806,7 @@ static int __init mconsole_init(void)
+ 			     "mconsole", (void *)sock);
+ 	if (err) {
+ 		printk(KERN_ERR "Failed to get IRQ for management console\n");
+-		return 1;
++		goto out;
+ 	}
+ 
+ 	if (notify_socket != NULL) {
+@@ -819,6 +822,10 @@ static int __init mconsole_init(void)
+ 	printk(KERN_INFO "mconsole (version %d) initialized on %s\n",
+ 	       MCONSOLE_VERSION, mconsole_socket_name);
+ 	return 0;
++
++ out:
++	os_close_file(sock);
++	return 1;
+ }
+ 
+ __initcall(mconsole_init);
+diff --git a/arch/um/drivers/mconsole_user.c b/arch/um/drivers/mconsole_user.c
+index 430c024..13af2f0 100644
+--- a/arch/um/drivers/mconsole_user.c
++++ b/arch/um/drivers/mconsole_user.c
+@@ -83,9 +83,8 @@ int mconsole_get_request(int fd, struct mc_request *req)
+ 	int len;
+ 
+ 	req->originlen = sizeof(req->origin);
+-	req->len = recvfrom(fd, &req->request, sizeof(req->request),
+-			    MSG_DONTWAIT, (struct sockaddr *) req->origin,
+-			    &req->originlen);
++	req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
++			    (struct sockaddr *) req->origin, &req->originlen);
+ 	if (req->len < 0)
+ 		return 0;
+ 
+diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
+index 3c6c44c..1e8f41a 100644
+--- a/arch/um/drivers/net_kern.c
++++ b/arch/um/drivers/net_kern.c
+@@ -318,7 +318,7 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
+ 	if (str == NULL)
+ 		goto random;
+ 
+-	for (i = 0;i < 6; i++) {
++	for (i = 0; i < 6; i++) {
+ 		addr[i] = simple_strtoul(str, &end, 16);
+ 		if ((end == str) ||
+ 		   ((*end != ':') && (*end != ',') && (*end != '\0'))) {
+@@ -343,14 +343,13 @@ static void setup_etheraddr(char *str, unsigned char *addr, char *name)
+ 	}
+ 	if (!is_local_ether_addr(addr)) {
+ 		printk(KERN_WARNING
+-		       "Warning: attempt to assign a globally valid ethernet "
++		       "Warning: Assigning a globally valid ethernet "
+ 		       "address to a device\n");
+-		printk(KERN_WARNING "You should better enable the 2nd "
+-		       "rightmost bit in the first byte of the MAC,\n");
++		printk(KERN_WARNING "You should set the 2nd rightmost bit in "
++		       "the first byte of the MAC,\n");
+ 		printk(KERN_WARNING "i.e. %02x:%02x:%02x:%02x:%02x:%02x\n",
+ 		       addr[0] | 0x02, addr[1], addr[2], addr[3], addr[4],
+ 		       addr[5]);
+-		goto random;
+ 	}
+ 	return;
+ 
+@@ -368,7 +367,6 @@ static struct platform_driver uml_net_driver = {
+ 		.name  = DRIVER_NAME,
+ 	},
+ };
+-static int driver_registered;
+ 
+ static void net_device_release(struct device *dev)
+ {
+@@ -383,6 +381,12 @@ static void net_device_release(struct device *dev)
+ 	free_netdev(netdev);
+ }
+ 
++/*
++ * Ensures that platform_driver_register is called only once by
++ * eth_configure.  Will be set in an initcall.
++ */
++static int driver_registered;
++
+ static void eth_configure(int n, void *init, char *mac,
+ 			  struct transport *transport)
+ {
+diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
+index 29185ca..abf2653 100644
+--- a/arch/um/drivers/net_user.c
++++ b/arch/um/drivers/net_user.c
+@@ -201,7 +201,7 @@ static int change_tramp(char **argv, char *output, int output_len)
+ 	close(fds[1]);
+ 
+ 	if (pid > 0)
+-		helper_wait(pid, 0, "change_tramp");
++		helper_wait(pid);
+ 	return pid;
+ }
+ 
+diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
+index 330543b..1993008 100644
+--- a/arch/um/drivers/port_kern.c
++++ b/arch/um/drivers/port_kern.c
+@@ -6,6 +6,7 @@
+ #include "linux/completion.h"
+ #include "linux/interrupt.h"
+ #include "linux/list.h"
++#include "linux/mutex.h"
+ #include "asm/atomic.h"
+ #include "init.h"
+ #include "irq_kern.h"
+@@ -120,7 +121,7 @@ static int port_accept(struct port_list *port)
+ 	return 0;
+ }
+ 
+-static DECLARE_MUTEX(ports_sem);
++static DEFINE_MUTEX(ports_mutex);
+ static LIST_HEAD(ports);
+ 
+ static void port_work_proc(struct work_struct *unused)
+@@ -161,7 +162,7 @@ void *port_data(int port_num)
+ 	struct port_dev *dev = NULL;
+ 	int fd;
+ 
+-	down(&ports_sem);
++	mutex_lock(&ports_mutex);
+ 	list_for_each(ele, &ports) {
+ 		port = list_entry(ele, struct port_list, list);
+ 		if (port->port == port_num)
+@@ -216,7 +217,7 @@ void *port_data(int port_num)
+  out_free:
+ 	kfree(port);
+  out:
+-	up(&ports_sem);
++	mutex_unlock(&ports_mutex);
+ 	return dev;
+ }
+ 
+diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
+index e942e83..71f0959 100644
+--- a/arch/um/drivers/random.c
++++ b/arch/um/drivers/random.c
+@@ -5,6 +5,7 @@
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License, incorporated herein by reference.
+  */
++#include <linux/sched.h>
+ #include <linux/module.h>
+ #include <linux/fs.h>
+ #include <linux/miscdevice.h>
+diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
+index b8711e5..8b80505 100644
+--- a/arch/um/drivers/slip_user.c
++++ b/arch/um/drivers/slip_user.c
+@@ -109,7 +109,7 @@ static int slip_tramp(char **argv, int fd)
+ 	read_output(fds[0], output, output_len);
+ 	printk("%s", output);
+ 
+-	err = helper_wait(pid, 0, argv[0]);
++	err = helper_wait(pid);
+ 	close(fds[0]);
+ 
+ out_free:
+diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
+index 89c1be2..a0ada8f 100644
+--- a/arch/um/drivers/slirp_user.c
++++ b/arch/um/drivers/slirp_user.c
+@@ -98,7 +98,7 @@ static void slirp_close(int fd, void *data)
+ 		       "(%d)\n", pri->pid, errno);
+ 	}
+ #endif
+-	err = helper_wait(pri->pid, 1, "slirp_close");
++	err = helper_wait(pri->pid);
+ 	if (err < 0)
+ 		return;
+ 
+diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
+index 875d60d..f1786e6 100644
+--- a/arch/um/drivers/ssl.c
++++ b/arch/um/drivers/ssl.c
+@@ -15,7 +15,6 @@
+ #include "line.h"
+ #include "ssl.h"
+ #include "chan_kern.h"
+-#include "kern_util.h"
+ #include "kern.h"
+ #include "init.h"
+ #include "irq_user.h"
+diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
+index 656036e..cec0c33 100644
+--- a/arch/um/drivers/stdio_console.c
++++ b/arch/um/drivers/stdio_console.c
+@@ -22,7 +22,6 @@
+ #include "stdio_console.h"
+ #include "line.h"
+ #include "chan_kern.h"
+-#include "kern_util.h"
+ #include "irq_user.h"
+ #include "mconsole_kern.h"
+ #include "init.h"
 diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
-index b1a77b1..99f9f96 100644
+index b1a77b1..be3a279 100644
 --- a/arch/um/drivers/ubd_kern.c
 +++ b/arch/um/drivers/ubd_kern.c
-@@ -475,17 +475,9 @@ static void do_ubd_request(struct request_queue * q);
+@@ -49,6 +49,7 @@
+ #include "irq_user.h"
+ #include "irq_kern.h"
+ #include "ubd_user.h"
++#include "kern_util.h"
+ #include "os.h"
+ #include "mem.h"
+ #include "mem_kern.h"
+@@ -229,7 +230,7 @@ static int proc_ide_read_media(char *page, char **start, off_t off, int count,
+ 	return len;
+ }
+ 
+-static void make_ide_entries(char *dev_name)
++static void make_ide_entries(const char *dev_name)
+ {
+ 	struct proc_dir_entry *dir, *ent;
+ 	char name[64];
+@@ -244,7 +245,7 @@ static void make_ide_entries(char *dev_name)
+ 	ent->data = NULL;
+ 	ent->read_proc = proc_ide_read_media;
+ 	ent->write_proc = NULL;
+-	sprintf(name,"ide0/%s", dev_name);
++	snprintf(name, sizeof(name), "ide0/%s", dev_name);
+ 	proc_symlink(dev_name, proc_ide_root, name);
+ }
+ 
+@@ -437,7 +438,10 @@ __uml_help(ubd_setup,
+ "    machine by running 'dd' on the device. <n> must be in the range\n"
+ "    0 to 7. Appending an 'r' to the number will cause that device\n"
+ "    to be mounted read-only. For example ubd1r=./ext_fs. Appending\n"
+-"    an 's' will cause data to be written to disk on the host immediately.\n\n"
++"    an 's' will cause data to be written to disk on the host immediately.\n"
++"    'c' will cause the device to be treated as being shared between multiple\n"
++"    UMLs and file locking will be turned off - this is appropriate for a\n"
++"    cluster filesystem and inappropriate at almost all other times.\n\n"
+ );
+ 
+ static int udb_setup(char *str)
+@@ -456,36 +460,14 @@ __uml_help(udb_setup,
+ "    in the boot output.\n\n"
+ );
+ 
+-static int fakehd_set = 0;
+-static int fakehd(char *str)
+-{
+-	printk(KERN_INFO "fakehd : Changing ubd name to \"hd\".\n");
+-	fakehd_set = 1;
+-	return 1;
+-}
+-
+-__setup("fakehd", fakehd);
+-__uml_help(fakehd,
+-"fakehd\n"
+-"    Change the ubd device name to \"hd\".\n\n"
+-);
+-
+ static void do_ubd_request(struct request_queue * q);
+ 
  /* Only changed by ubd_init, which is an initcall. */
  int thread_fd = -1;
  
@@ -249233,7 +266306,7 @@
  }
  
  /* Callable only from interrupt context - otherwise you need to do
-@@ -493,10 +485,10 @@ static void ubd_end_request(struct request *req, int bytes, int uptodate)
+@@ -493,10 +475,10 @@ static void ubd_end_request(struct request *req, int bytes, int uptodate)
  static inline void ubd_finish(struct request *req, int bytes)
  {
  	if(bytes < 0){
@@ -249246,12 +266319,152 @@
  }
  
  static LIST_HEAD(restart);
+@@ -726,8 +708,10 @@ static int ubd_add(int n, char **error_out)
+ 		ubd_disk_register(fake_major, ubd_dev->size, n,
+ 				  &fake_gendisk[n]);
+ 
+-	/* perhaps this should also be under the "if (fake_major)" above */
+-	/* using the fake_disk->disk_name and also the fakehd_set name */
++	/*
++	 * Perhaps this should also be under the "if (fake_major)" above
++	 * using the fake_disk->disk_name
++	 */
+ 	if (fake_ide)
+ 		make_ide_entries(ubd_gendisk[n]->disk_name);
+ 
+diff --git a/arch/um/drivers/ubd_user.c b/arch/um/drivers/ubd_user.c
+index 48fc745..b591bb9 100644
+--- a/arch/um/drivers/ubd_user.c
++++ b/arch/um/drivers/ubd_user.c
+@@ -16,7 +16,6 @@
+ #include <sys/mman.h>
+ #include <sys/param.h>
+ #include "asm/types.h"
+-#include "kern_util.h"
+ #include "user.h"
+ #include "ubd_user.h"
+ #include "os.h"
+diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
+index d9941fe..56533db 100644
+--- a/arch/um/drivers/vde_user.c
++++ b/arch/um/drivers/vde_user.c
+@@ -80,7 +80,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
+ 
+ 	vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
+ 	if (vpri->args == NULL) {
+-		printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args"
++		printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
+ 		       "allocation failed");
+ 		return;
+ 	}
+diff --git a/arch/um/include/arch.h b/arch/um/include/arch.h
+index 49c601f..2de92a0 100644
+--- a/arch/um/include/arch.h
++++ b/arch/um/include/arch.h
+@@ -10,6 +10,6 @@
+ 
+ extern void arch_check_bugs(void);
+ extern int arch_fixup(unsigned long address, struct uml_pt_regs *regs);
+-extern int arch_handle_signal(int sig, struct uml_pt_regs *regs);
++extern void arch_examine_signal(int sig, struct uml_pt_regs *regs);
+ 
+ #endif
+diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h
+index a5cdf95..606bb5c 100644
+--- a/arch/um/include/as-layout.h
++++ b/arch/um/include/as-layout.h
+@@ -10,23 +10,31 @@
+ #include "kern_constants.h"
+ 
+ /*
+- * Assembly doesn't want any casting, but C does, so define these
+- * without casts here, and define new symbols with casts inside the C
+- * section.
++ * Stolen from linux/const.h, which can't be directly included since
++ * this is used in userspace code, which has no access to the kernel
++ * headers.  Changed to be suitable for adding casts to the start,
++ * rather than "UL" to the end.
+  */
+-#define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE)
+-#define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE)
+-#define ASM_STUB_START ASM_STUB_CODE
+ 
+-/*
+- * This file is included by the assembly stubs, which just want the
+- * definitions above.
++/* Some constant macros are used in both assembler and
++ * C code.  Therefore we cannot annotate them always with
++ * 'UL' and other type specifiers unilaterally.  We
++ * use the following macros to deal with this.
+  */
+-#ifndef __ASSEMBLY__
+ 
+-#define STUB_CODE ((unsigned long) ASM_STUB_CODE)
+-#define STUB_DATA ((unsigned long) ASM_STUB_DATA)
+-#define STUB_START ((unsigned long) ASM_STUB_START)
++#ifdef __ASSEMBLY__
++#define _AC(X, Y)	(Y)
++#else
++#define __AC(X, Y)	(X (Y))
++#define _AC(X, Y)	__AC(X, Y)
++#endif
++
++#define STUB_START _AC(, 0x100000)
++#define STUB_CODE _AC((unsigned long), STUB_START)
++#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE)
++#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE)
++
++#ifndef __ASSEMBLY__
+ 
+ #include "sysdep/ptrace.h"
+ 
+diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h
+index 5a2263e..9b9ced8 100644
+--- a/arch/um/include/chan_user.h
++++ b/arch/um/include/chan_user.h
+@@ -48,7 +48,7 @@ extern void register_winch_irq(int fd, int tty_fd, int pid,
+ #define __channel_help(fn, prefix) \
+ __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
+ "    Attach a console or serial line to a host channel.  See\n" \
+-"    http://user-mode-linux.sourceforge.net/input.html for a complete\n" \
++"    http://user-mode-linux.sourceforge.net/old/input.html for a complete\n" \
+ "    description of this switch.\n\n" \
+ );
+ 
+diff --git a/arch/um/include/common-offsets.h b/arch/um/include/common-offsets.h
+index 0edab69..b54bd35 100644
+--- a/arch/um/include/common-offsets.h
++++ b/arch/um/include/common-offsets.h
+@@ -18,6 +18,7 @@ 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);
++DEFINE_STR(UM_KERN_CONT, KERN_CONT);
+ 
+ DEFINE(UM_ELF_CLASS, ELF_CLASS);
+ DEFINE(UM_ELFCLASS32, ELFCLASS32);
 diff --git a/arch/um/include/init.h b/arch/um/include/init.h
-index d4de7c0..cebc6ca 100644
+index d4de7c0..b00a957 100644
 --- a/arch/um/include/init.h
 +++ b/arch/um/include/init.h
-@@ -42,15 +42,15 @@ typedef void (*exitcall_t)(void);
+@@ -40,17 +40,31 @@
+ typedef int (*initcall_t)(void);
+ typedef void (*exitcall_t)(void);
  
++#ifndef __KERNEL__
++#ifndef __section
++# define __section(S) __attribute__ ((__section__(#S)))
++#endif
++
++#if __GNUC_MINOR__ >= 3
++# define __used			__attribute__((__used__))
++#else
++# define __used			__attribute__((__unused__))
++#endif
++
++#else
++#include <linux/compiler.h>
++#endif
  /* These are for everybody (although not all archs will actually
     discard it in modules) */
 -#define __init		__attribute__ ((__section__ (".init.text")))
@@ -249272,7 +266485,7 @@
  #endif
  
  #endif
-@@ -103,16 +103,16 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
+@@ -103,16 +117,16 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
   * Mark functions and data as being only used at initialization
   * or exit time.
   */
@@ -249295,7 +266508,7 @@
  	__attribute__((__section__(".initcall" level ".init"))) = fn
  
  /* Userspace initcalls shouldn't depend on anything in the kernel, so we'll
-@@ -122,7 +122,7 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
+@@ -122,19 +136,8 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
  
  #define __exitcall(fn) static exitcall_t __exitcall_##fn __exit_call = fn
  
@@ -249304,6 +266517,526 @@
  
  #endif
  
+ #endif /* _LINUX_UML_INIT_H */
+-
+-/*
+- * 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/irq_user.h b/arch/um/include/irq_user.h
+index 884a9c1..e60b318 100644
+--- a/arch/um/include/irq_user.h
++++ b/arch/um/include/irq_user.h
+@@ -14,7 +14,6 @@ struct irq_fd {
+ 	int fd;
+ 	int type;
+ 	int irq;
+-	int pid;
+ 	int events;
+ 	int current_events;
+ };
+diff --git a/arch/um/include/kern_util.h b/arch/um/include/kern_util.h
+index 74ce8e5..3c34122 100644
+--- a/arch/um/include/kern_util.h
++++ b/arch/um/include/kern_util.h
+@@ -9,107 +9,61 @@
+ #include "sysdep/ptrace.h"
+ #include "sysdep/faultinfo.h"
+ 
+-typedef void (*kern_hndl)(int, struct uml_pt_regs *);
+-
+-struct kern_handlers {
+-	kern_hndl relay_signal;
+-	kern_hndl winch;
+-	kern_hndl bus_handler;
+-	kern_hndl page_fault;
+-	kern_hndl sigio_handler;
+-	kern_hndl timer_handler;
+-};
+-
+-extern const struct kern_handlers handlinfo_kern;
++extern int uml_exitcode;
+ 
+ extern int ncpus;
+-extern char *gdb_init;
+ extern int kmalloc_ok;
+-extern int jail;
+-extern int nsyscalls;
+ 
+-#define UML_ROUND_DOWN(addr) ((void *)(((unsigned long) addr) & PAGE_MASK))
+ #define UML_ROUND_UP(addr) \
+-	UML_ROUND_DOWN(((unsigned long) addr) + PAGE_SIZE - 1)
++	((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
+ 
+-extern int kernel_fork(unsigned long flags, int (*fn)(void *), void * arg);
+-extern int kernel_thread_proc(void *data);
+-extern void syscall_segv(int sig);
+-extern int current_pid(void);
+ extern unsigned long alloc_stack(int order, int atomic);
++extern void free_stack(unsigned long stack, int order);
++
+ extern int do_signal(void);
+-extern int is_stack_fault(unsigned long sp);
++extern void copy_sc(struct uml_pt_regs *regs, void *from);
++extern void interrupt_end(void);
++extern void relay_signal(int sig, struct uml_pt_regs *regs);
++
+ extern unsigned long segv(struct faultinfo fi, unsigned long ip,
+ 			  int is_user, struct uml_pt_regs *regs);
+ 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);
+-extern void set_tracing(void *t, int tracing);
+-extern int is_tracing(void *task);
+-extern int segv_syscall(void);
+-extern void kern_finish_exec(void *task, int new_pid, unsigned long stack);
+-extern unsigned long page_mask(void);
+-extern int need_finish_fork(void);
+-extern void free_stack(unsigned long stack, int order);
+-extern void add_input_request(int op, void (*proc)(int), void *arg);
+-extern char *current_cmd(void);
+-extern void timer_handler(int sig, struct uml_pt_regs *regs);
+-extern int set_signals(int enable);
+-extern int pid_to_processor_id(int pid);
+-extern void deliver_signals(void *t);
+-extern int next_trap_index(int max);
+-extern void default_idle(void);
+-extern void finish_fork(void);
+-extern void paging_init(void);
+-extern void init_flush_vm(void);
+-extern void *syscall_sp(void *t);
+-extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
++
+ extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
+-extern void interrupt_end(void);
+-extern void initial_thread_cb(void (*proc)(void *), void *arg);
+-extern int debugger_signal(int status, int pid);
+-extern void debugger_parent_signal(int status, int pid);
+-extern void child_signal(int pid, int status);
+-extern int init_ptrace_proxy(int idle_pid, int startup, int stop);
+-extern int init_parent_proxy(int pid);
+-extern int singlestepping(void *t);
+-extern void check_stack_overflow(void *ptr);
+-extern void relay_signal(int sig, struct uml_pt_regs *regs);
+-extern int user_context(unsigned long sp);
+-extern void timer_irq(struct uml_pt_regs *regs);
+-extern void do_uml_exitcalls(void);
+-extern int attach_debugger(int idle_pid, int pid, int stop);
+-extern int config_gdb(char *str);
+-extern int remove_gdb(void);
+-extern char *uml_strdup(char *string);
+-extern void unprotect_kernel_mem(void);
+-extern void protect_kernel_mem(void);
+-extern void uml_cleanup(void);
+-extern void lock_signalled_task(void *t);
+-extern void IPI_handler(int cpu);
+-extern int jail_setup(char *line, int *add);
+-extern void *get_init_task(void);
+-extern int clear_user_proc(void *buf, int size);
+-extern int copy_to_user_proc(void *to, void *from, int size);
+-extern int copy_from_user_proc(void *to, void *from, int size);
+-extern int strlen_user_proc(char *str);
+-extern long execute_syscall(void *r);
+ extern int smp_sigio_handler(void);
+-extern void *get_current(void);
+-extern struct task_struct *get_task(int pid, int require);
+-extern void machine_halt(void);
++extern void initial_thread_cb(void (*proc)(void *), void *arg);
+ extern int is_syscall(unsigned long addr);
++extern void timer_handler(int sig, struct uml_pt_regs *regs);
+ 
+-extern void free_irq(unsigned int, void *);
+-extern int cpu(void);
++extern void timer_handler(int sig, struct uml_pt_regs *regs);
+ 
+-extern void time_init_kern(void);
++extern int start_uml(void);
++extern void paging_init(void);
+ 
+-/* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
++extern void uml_cleanup(void);
++extern void do_uml_exitcalls(void);
++
++/*
++ * Are we disallowed to sleep? Used to choose between GFP_KERNEL and
++ * GFP_ATOMIC.
++ */
+ extern int __cant_sleep(void);
+-extern void sigio_handler(int sig, struct uml_pt_regs *regs);
+-extern void copy_sc(struct uml_pt_regs *regs, void *from);
++extern void *get_current(void);
++extern int copy_from_user_proc(void *to, void *from, int size);
++extern int cpu(void);
++extern char *uml_strdup(const char *string);
++
+ extern unsigned long to_irq_stack(unsigned long *mask_out);
+-unsigned long from_irq_stack(int nested);
+-extern int start_uml(void);
++extern unsigned long from_irq_stack(int nested);
++
++extern void syscall_trace(struct uml_pt_regs *regs, int entryexit);
++extern int singlestepping(void *t);
++
++extern void segv_handler(int sig, struct uml_pt_regs *regs);
++extern void bus_handler(int sig, struct uml_pt_regs *regs);
++extern void winch(int sig, struct uml_pt_regs *regs);
++extern void fatal_sigsegv(void) __attribute__ ((noreturn));
++
++
+ #endif
+diff --git a/arch/um/include/mem_user.h b/arch/um/include/mem_user.h
+index a54514d..46384ac 100644
+--- a/arch/um/include/mem_user.h
++++ b/arch/um/include/mem_user.h
+@@ -46,9 +46,6 @@ extern int iomem_size;
+ 
+ #define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
+ 
+-extern unsigned long host_task_size;
+-extern unsigned long task_size;
+-
+ extern int init_mem_user(void);
+ extern void setup_memory(void *entry);
+ extern unsigned long find_iomem(char *driver, unsigned long *len_out);
+@@ -59,9 +56,7 @@ extern void setup_physmem(unsigned long start, unsigned long usable,
+ 			  unsigned long len, unsigned long long highmem);
+ extern void add_iomem(char *name, int fd, unsigned long size);
+ extern unsigned long phys_offset(unsigned long phys);
+-extern void unmap_physmem(void);
+ extern void map_memory(unsigned long virt, unsigned long phys,
+ 		       unsigned long len, int r, int w, int x);
+-extern unsigned long get_kmem_end(void);
+ 
+ #endif
+diff --git a/arch/um/include/misc_constants.h b/arch/um/include/misc_constants.h
+deleted file mode 100644
+index 989bc08..0000000
+--- a/arch/um/include/misc_constants.h
++++ /dev/null
+@@ -1,6 +0,0 @@
+-#ifndef __MISC_CONSTANT_H_
+-#define __MISC_CONSTANT_H_
+-
+-#include <user_constants.h>
+-
+-#endif
+diff --git a/arch/um/include/os.h b/arch/um/include/os.h
+index 6f0d1c7..0b6b627 100644
+--- a/arch/um/include/os.h
++++ b/arch/um/include/os.h
+@@ -8,7 +8,6 @@
+ 
+ #include <stdarg.h>
+ #include "irq_user.h"
+-#include "kern_util.h"
+ #include "longjmp.h"
+ #include "mm_id.h"
+ #include "sysdep/tls.h"
+@@ -128,33 +127,31 @@ static inline struct openflags of_cloexec(struct openflags flags)
+ extern int os_stat_file(const char *file_name, struct uml_stat *buf);
+ extern int os_stat_fd(const int fd, struct uml_stat *buf);
+ extern int os_access(const char *file, int mode);
+-extern int os_get_exec_close(int fd, int *close_on_exec);
+ extern int os_set_exec_close(int fd);
+ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
+ extern int os_get_ifname(int fd, char *namebuf);
+ extern int os_set_slip(int fd);
+-extern int os_set_owner(int fd, int pid);
+ extern int os_mode_fd(int fd, int mode);
+ 
+ extern int os_seek_file(int fd, unsigned long long offset);
+-extern int os_open_file(char *file, struct openflags flags, int mode);
++extern int os_open_file(const char *file, struct openflags flags, int mode);
+ extern int os_read_file(int fd, void *buf, int len);
+ extern int os_write_file(int fd, const void *buf, int count);
+-extern int os_file_size(char *file, unsigned long long *size_out);
+-extern int os_file_modtime(char *file, unsigned long *modtime);
++extern int os_file_size(const char *file, unsigned long long *size_out);
++extern int os_file_modtime(const char *file, unsigned long *modtime);
+ extern int os_pipe(int *fd, int stream, int close_on_exec);
+-extern int os_set_fd_async(int fd, int owner);
++extern int os_set_fd_async(int fd);
+ extern int os_clear_fd_async(int fd);
+ extern int os_set_fd_block(int fd, int blocking);
+ extern int os_accept_connection(int fd);
+-extern int os_create_unix_socket(char *file, int len, int close_on_exec);
++extern int os_create_unix_socket(const char *file, int len, int close_on_exec);
+ extern int os_shutdown_socket(int fd, int r, int w);
+ extern void os_close_file(int fd);
+ extern int os_rcv_fd(int fd, int *helper_pid_out);
+ extern int create_unix_socket(char *file, int len, int close_on_exec);
+-extern int os_connect_socket(char *name);
++extern int os_connect_socket(const char *name);
+ extern int os_file_type(char *file);
+-extern int os_file_mode(char *file, struct openflags *mode_out);
++extern int os_file_mode(const char *file, struct openflags *mode_out);
+ extern int os_lock_file(int fd, int excl);
+ extern void os_flush_stdout(void);
+ extern int os_stat_filesystem(char *path, long *bsize_out,
+@@ -168,14 +165,10 @@ extern int os_fchange_dir(int fd);
+ 
+ /* start_up.c */
+ extern void os_early_checks(void);
+-extern int can_do_skas(void);
++extern void can_do_skas(void);
+ extern void os_check_bugs(void);
+ extern void check_host_supports_tls(int *supports_tls, int *tls_min);
+ 
+-/* Make sure they are clear when running in TT mode. Required by
+- * SEGV_MAYBE_FIXABLE */
+-#define clear_can_do_skas() do { ptrace_faultinfo = proc_mm = 0; } while (0)
+-
+ /* mem.c */
+ extern int create_mem_file(unsigned long long len);
+ 
+@@ -214,7 +207,7 @@ extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
+ extern int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv);
+ extern int run_helper_thread(int (*proc)(void *), void *arg,
+ 			     unsigned int flags, unsigned long *stack_out);
+-extern int helper_wait(int pid, int nohang, char *pname);
++extern int helper_wait(int pid);
+ 
+ 
+ /* tls.c */
+@@ -237,16 +230,12 @@ extern void unblock_signals(void);
+ extern int get_signals(void);
+ extern int set_signals(int enable);
+ 
+-/* trap.c */
+-extern void os_fill_handlinfo(struct kern_handlers h);
+-
+ /* util.c */
+ extern void stack_protections(unsigned long address);
+ extern int raw(int fd);
+ extern void setup_machinename(char *machine_out);
+ extern void setup_hostinfo(char *buf, int len);
+-extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
+-extern void os_dump_core(void);
++extern void os_dump_core(void) __attribute__ ((noreturn));
+ 
+ /* time.c */
+ extern void idle_sleep(unsigned long long nsecs);
+@@ -275,11 +264,9 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr,
+ extern int is_skas_winch(int pid, int fd, void *data);
+ extern int start_userspace(unsigned long stub_stack);
+ extern int copy_context_skas0(unsigned long stack, int pid);
+-extern void save_registers(int pid, struct uml_pt_regs *regs);
+-extern void restore_registers(int pid, struct uml_pt_regs *regs);
+ extern void userspace(struct uml_pt_regs *regs);
+-extern void map_stub_pages(int fd, unsigned long code,
+-			   unsigned long data, unsigned long stack);
++extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
++			  unsigned long stack);
+ extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
+ extern void switch_threads(jmp_buf *me, jmp_buf *you);
+ extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
+@@ -298,16 +285,12 @@ extern void os_free_irq_later(struct irq_fd *active_fds,
+ extern int os_get_pollfd(int i);
+ extern void os_set_pollfd(int i, int fd);
+ extern void os_set_ioignore(void);
+-extern void init_irq_signals(int on_sigstack);
+ 
+ /* sigio.c */
+ extern int add_sigio_fd(int fd);
+ extern int ignore_sigio_fd(int fd);
+ extern void maybe_sigio_broken(int fd, int read);
+ 
+-/* skas/trap */
+-extern void sig_handler_common_skas(int sig, void *sc_ptr);
+-
+ /* sys-x86_64/prctl.c */
+ extern int os_arch_prctl(int pid, int code, unsigned long *addr);
+ 
+diff --git a/arch/um/include/ptrace_user.h b/arch/um/include/ptrace_user.h
+index f3450e6..4bce6e0 100644
+--- a/arch/um/include/ptrace_user.h
++++ b/arch/um/include/ptrace_user.h
+@@ -1,5 +1,5 @@
+ /* 
+- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+@@ -10,12 +10,6 @@
+ 
+ extern int ptrace_getregs(long pid, unsigned long *regs_out);
+ extern int ptrace_setregs(long pid, unsigned long *regs_in);
+-extern int ptrace_getfpregs(long pid, unsigned long *regs_out);
+-extern int ptrace_setfpregs(long pid, unsigned long *regs);
+-extern void arch_enter_kernel(void *task, int pid);
+-extern void arch_leave_kernel(void *task, int pid);
+-extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
+-
+ 
+ /* syscall emulation path in ptrace */
+ 
+@@ -54,7 +48,8 @@ extern int sysemu_supported;
+ 	(((int[3][3] ) { \
+ 		{ PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \
+ 		{ PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \
+-		{ PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, PTRACE_SYSEMU_SINGLESTEP }}) \
++		{ PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \
++		  PTRACE_SYSEMU_SINGLESTEP } }) \
+ 		[sysemu_mode][singlestep_mode])
+ 
+ #endif
+diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h
+index 0e27406..9ea1ae3 100644
+--- a/arch/um/include/registers.h
++++ b/arch/um/include/registers.h
+@@ -9,14 +9,13 @@
+ #include "sysdep/ptrace.h"
+ #include "sysdep/archsetjmp.h"
+ 
+-extern void init_thread_registers(struct uml_pt_regs *to);
+ extern int save_fp_registers(int pid, unsigned long *fp_regs);
+ extern int restore_fp_registers(int pid, unsigned long *fp_regs);
+ extern int save_fpx_registers(int pid, unsigned long *fp_regs);
+ extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
+-extern void save_registers(int pid, struct uml_pt_regs *regs);
+-extern void restore_registers(int pid, struct uml_pt_regs *regs);
+-extern void init_registers(int pid);
++extern int save_registers(int pid, struct uml_pt_regs *regs);
++extern int restore_registers(int pid, struct uml_pt_regs *regs);
++extern int init_registers(int pid);
+ extern void get_safe_registers(unsigned long *regs);
+ extern unsigned long get_thread_reg(int reg, jmp_buf *buf);
+ 
+diff --git a/arch/um/include/signal_kern.h b/arch/um/include/signal_kern.h
+deleted file mode 100644
+index aeb5d5a..0000000
+--- a/arch/um/include/signal_kern.h
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/* 
+- * Copyright (C) 2001, 2002 Jeff Dike (jdike at karaya.com)
+- * Licensed under the GPL
+- */
+-
+-#ifndef __SIGNAL_KERN_H__
+-#define __SIGNAL_KERN_H__
+-
+-extern int have_signals(void *t);
+-
+-#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/skas/mode-skas.h b/arch/um/include/skas/mode-skas.h
+deleted file mode 100644
+index e065feb..0000000
+--- a/arch/um/include/skas/mode-skas.h
++++ /dev/null
+@@ -1,11 +0,0 @@
+-/*
+- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
+- * Licensed under the GPL
+- */
+-
+-#ifndef __MODE_SKAS_H__
+-#define __MODE_SKAS_H__
+-
+-extern void kill_off_processes_skas(void);
+-
+-#endif
+diff --git a/arch/um/include/sysdep-i386/syscalls.h b/arch/um/include/sysdep-i386/syscalls.h
+index 57bd79e..9056981 100644
+--- a/arch/um/include/sysdep-i386/syscalls.h
++++ b/arch/um/include/sysdep-i386/syscalls.h
+@@ -1,5 +1,5 @@
+ /* 
+- * Copyright (C) 2000 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+@@ -18,7 +18,8 @@ extern syscall_handler_t old_mmap_i386;
+ extern syscall_handler_t *sys_call_table[];
+ 
+ #define EXECUTE_SYSCALL(syscall, regs) \
+-	((long (*)(struct syscall_args)) (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
++	((long (*)(struct syscall_args)) \
++	 (*sys_call_table[syscall]))(SYSCALL_ARGS(&regs->regs))
+ 
+ extern long sys_mmap2(unsigned long addr, unsigned long len,
+ 		      unsigned long prot, unsigned long flags,
+diff --git a/arch/um/include/sysdep-x86_64/kernel-offsets.h b/arch/um/include/sysdep-x86_64/kernel-offsets.h
+index c978b58..a307237 100644
+--- a/arch/um/include/sysdep-x86_64/kernel-offsets.h
++++ b/arch/um/include/sysdep-x86_64/kernel-offsets.h
+@@ -17,16 +17,7 @@
+ #define OFFSET(sym, str, mem) \
+ 	DEFINE(sym, offsetof(struct str, mem));
+ 
+-#define __NO_STUBS 1
+-#undef __SYSCALL
+-#undef _ASM_X86_64_UNISTD_H_
+-#define __SYSCALL(nr, sym) [nr] = 1,
+-static char syscalls[] = {
+-#include <asm/arch/unistd.h>
+-};
+-
+ void foo(void)
+ {
+ #include <common-offsets.h>
+-DEFINE(UM_NR_syscall_max, sizeof(syscalls) - 1);
+ }
+diff --git a/arch/um/include/sysdep-x86_64/syscalls.h b/arch/um/include/sysdep-x86_64/syscalls.h
+index cf72256..7cfb0b0 100644
+--- a/arch/um/include/sysdep-x86_64/syscalls.h
++++ b/arch/um/include/sysdep-x86_64/syscalls.h
+@@ -30,6 +30,4 @@ extern long old_mmap(unsigned long addr, unsigned long len,
+ extern syscall_handler_t sys_modify_ldt;
+ extern syscall_handler_t sys_arch_prctl;
+ 
+-#define NR_syscalls (UM_NR_syscall_max + 1)
+-
+ #endif
+diff --git a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
+index 8855d8d..82865fc 100644
+--- a/arch/um/include/um_mmu.h
++++ b/arch/um/include/um_mmu.h
+@@ -12,10 +12,6 @@
+ 
+ typedef struct mm_context {
+ 	struct mm_id id;
+-	unsigned long last_page_table;
+-#ifdef CONFIG_3_LEVEL_PGTABLES
+-	unsigned long last_pmd;
+-#endif
+ 	struct uml_ldt ldt;
+ } mm_context_t;
+ 
+diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h
+index fdfc06b..2b6fc8e 100644
+--- a/arch/um/include/um_uaccess.h
++++ b/arch/um/include/um_uaccess.h
+@@ -6,7 +6,9 @@
+ #ifndef __ARCH_UM_UACCESS_H
+ #define __ARCH_UM_UACCESS_H
+ 
+-#include "asm/fixmap.h"
++#include <asm/elf.h>
++#include <asm/fixmap.h>
++#include "sysdep/archsetjmp.h"
+ 
+ #define __under_task_size(addr, size) \
+ 	(((unsigned long) (addr) < TASK_SIZE) && \
 diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
 index 3866f49..26090b7 100644
 --- a/arch/um/kernel/dyn.lds.S
@@ -249326,5260 +267059,11479 @@
  
    /* Ensure the __preinit_array_start label is properly aligned.  We
       could instead move the label definition inside the section, but
-diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
-index 1b388b4..7c7142b 100644
---- a/arch/um/kernel/ksyms.c
-+++ b/arch/um/kernel/ksyms.c
-@@ -71,10 +71,10 @@ EXPORT_SYMBOL(dump_thread);
- 
- /* required for SMP */
- 
--extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-+extern void __write_lock_failed(rwlock_t *rw);
- EXPORT_SYMBOL(__write_lock_failed);
- 
--extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
-+extern void __read_lock_failed(rwlock_t *rw);
- EXPORT_SYMBOL(__read_lock_failed);
- 
- #endif
-diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
-index 13df191..5828c1d 100644
---- a/arch/um/kernel/uml.lds.S
-+++ b/arch/um/kernel/uml.lds.S
-@@ -23,7 +23,7 @@ SECTIONS
-   __init_begin = .;
-   .init.text : {
- 	_sinittext = .;
--	*(.init.text)
-+	INIT_TEXT
- 	_einittext = .;
-   }
-   . = ALIGN(4096);
-@@ -48,7 +48,7 @@ SECTIONS
+diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
+index 8196450..76a62c0 100644
+--- a/arch/um/kernel/exec.c
++++ b/arch/um/kernel/exec.c
+@@ -19,12 +19,13 @@
+ void flush_thread(void)
+ {
+ 	void *data = NULL;
+-	unsigned long end = proc_mm ? task_size : STUB_START;
+ 	int ret;
  
-   #include "asm/common.lds.S"
+ 	arch_flush_thread(&current->thread.arch);
  
--  init.data : { *(init.data) }
-+  init.data : { INIT_DATA }
-   .data    :
-   {
-     . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
-diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
-index 0147227..19053d4 100644
---- a/arch/um/sys-i386/signal.c
-+++ b/arch/um/sys-i386/signal.c
-@@ -3,10 +3,10 @@
+-	ret = unmap(&current->mm->context.id, 0, end, 1, &data);
++	ret = unmap(&current->mm->context.id, 0, STUB_START, 0, &data);
++	ret = ret || unmap(&current->mm->context.id, STUB_END,
++			   TASK_SIZE - STUB_END, 1, &data);
+ 	if (ret) {
+ 		printk(KERN_ERR "flush_thread - clearing address space failed, "
+ 		       "err = %d\n", ret);
+diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c
+index c716b5a..984f80e 100644
+--- a/arch/um/kernel/exitcode.c
++++ b/arch/um/kernel/exitcode.c
+@@ -1,15 +1,17 @@
+ /*
+- * Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   * Licensed under the GPL
   */
  
--#include "linux/ptrace.h"
--#include "asm/unistd.h"
+-#include "linux/kernel.h"
+-#include "linux/init.h"
+-#include "linux/ctype.h"
+-#include "linux/proc_fs.h"
 -#include "asm/uaccess.h"
--#include "asm/ucontext.h"
-+#include <linux/ptrace.h>
-+#include <asm/unistd.h>
++#include <linux/ctype.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/proc_fs.h>
++#include <linux/types.h>
 +#include <asm/uaccess.h>
-+#include <asm/ucontext.h>
- #include "frame_kern.h"
- #include "skas.h"
  
-@@ -18,17 +18,17 @@ void copy_sc(struct uml_pt_regs *regs, void *from)
- 	REGS_FS(regs->gp) = sc->fs;
- 	REGS_ES(regs->gp) = sc->es;
- 	REGS_DS(regs->gp) = sc->ds;
--	REGS_EDI(regs->gp) = sc->edi;
--	REGS_ESI(regs->gp) = sc->esi;
--	REGS_EBP(regs->gp) = sc->ebp;
--	REGS_SP(regs->gp) = sc->esp;
--	REGS_EBX(regs->gp) = sc->ebx;
--	REGS_EDX(regs->gp) = sc->edx;
--	REGS_ECX(regs->gp) = sc->ecx;
--	REGS_EAX(regs->gp) = sc->eax;
--	REGS_IP(regs->gp) = sc->eip;
-+	REGS_EDI(regs->gp) = sc->di;
-+	REGS_ESI(regs->gp) = sc->si;
-+	REGS_EBP(regs->gp) = sc->bp;
-+	REGS_SP(regs->gp) = sc->sp;
-+	REGS_EBX(regs->gp) = sc->bx;
-+	REGS_EDX(regs->gp) = sc->dx;
-+	REGS_ECX(regs->gp) = sc->cx;
-+	REGS_EAX(regs->gp) = sc->ax;
-+	REGS_IP(regs->gp) = sc->ip;
- 	REGS_CS(regs->gp) = sc->cs;
--	REGS_EFLAGS(regs->gp) = sc->eflags;
-+	REGS_EFLAGS(regs->gp) = sc->flags;
- 	REGS_SS(regs->gp) = sc->ss;
+-/* If read and write race, the read will still atomically read a valid
++/*
++ * If read and write race, the read will still atomically read a valid
+  * value.
+  */
+ int uml_exitcode = 0;
+@@ -19,18 +21,19 @@ static int read_proc_exitcode(char *page, char **start, off_t off,
+ {
+ 	int len, val;
+ 
+-	/* Save uml_exitcode in a local so that we don't need to guarantee
++	/*
++	 * Save uml_exitcode in a local so that we don't need to guarantee
+ 	 * that sprintf accesses it atomically.
+ 	 */
+ 	val = uml_exitcode;
+ 	len = sprintf(page, "%d\n", val);
+ 	len -= off;
+-	if(len <= off+count)
++	if (len <= off+count)
+ 		*eof = 1;
+ 	*start = page + off;
+-	if(len > count)
++	if (len > count)
+ 		len = count;
+-	if(len < 0)
++	if (len < 0)
+ 		len = 0;
+ 	return len;
  }
+@@ -41,11 +44,11 @@ static int write_proc_exitcode(struct file *file, const char __user *buffer,
+ 	char *end, buf[sizeof("nnnnn\0")];
+ 	int tmp;
  
-@@ -229,18 +229,18 @@ static int copy_sc_to_user(struct sigcontext __user *to,
- 	sc.fs = REGS_FS(regs->regs.gp);
- 	sc.es = REGS_ES(regs->regs.gp);
- 	sc.ds = REGS_DS(regs->regs.gp);
--	sc.edi = REGS_EDI(regs->regs.gp);
--	sc.esi = REGS_ESI(regs->regs.gp);
--	sc.ebp = REGS_EBP(regs->regs.gp);
--	sc.esp = sp;
--	sc.ebx = REGS_EBX(regs->regs.gp);
--	sc.edx = REGS_EDX(regs->regs.gp);
--	sc.ecx = REGS_ECX(regs->regs.gp);
--	sc.eax = REGS_EAX(regs->regs.gp);
--	sc.eip = REGS_IP(regs->regs.gp);
-+	sc.di = REGS_EDI(regs->regs.gp);
-+	sc.si = REGS_ESI(regs->regs.gp);
-+	sc.bp = REGS_EBP(regs->regs.gp);
-+	sc.sp = sp;
-+	sc.bx = REGS_EBX(regs->regs.gp);
-+	sc.dx = REGS_EDX(regs->regs.gp);
-+	sc.cx = REGS_ECX(regs->regs.gp);
-+	sc.ax = REGS_EAX(regs->regs.gp);
-+	sc.ip = REGS_IP(regs->regs.gp);
- 	sc.cs = REGS_CS(regs->regs.gp);
--	sc.eflags = REGS_EFLAGS(regs->regs.gp);
--	sc.esp_at_signal = regs->regs.gp[UESP];
-+	sc.flags = REGS_EFLAGS(regs->regs.gp);
-+	sc.sp_at_signal = regs->regs.gp[UESP];
- 	sc.ss = regs->regs.gp[SS];
- 	sc.cr2 = fi->cr2;
- 	sc.err = fi->error_code;
-diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
-index 1778d33..7457436 100644
---- a/arch/um/sys-x86_64/signal.c
-+++ b/arch/um/sys-x86_64/signal.c
-@@ -4,11 +4,11 @@
+-	if(copy_from_user(buf, buffer, count))
++	if (copy_from_user(buf, buffer, count))
+ 		return -EFAULT;
+ 
+ 	tmp = simple_strtol(buf, &end, 0);
+-	if((*end != '\0') && !isspace(*end))
++	if ((*end != '\0') && !isspace(*end))
+ 		return -EINVAL;
+ 
+ 	uml_exitcode = tmp;
+@@ -57,7 +60,7 @@ static int make_proc_exitcode(void)
+ 	struct proc_dir_entry *ent;
+ 
+ 	ent = create_proc_entry("exitcode", 0600, &proc_root);
+-	if(ent == NULL){
++	if (ent == NULL) {
+ 		printk(KERN_WARNING "make_proc_exitcode : Failed to register "
+ 		       "/proc/exitcode\n");
+ 		return 0;
+diff --git a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
+index 734f873..72eccd2 100644
+--- a/arch/um/kernel/gmon_syms.c
++++ b/arch/um/kernel/gmon_syms.c
+@@ -1,5 +1,5 @@
+-/* 
+- * Copyright (C) 2001, 2002 Jeff Dike (jdike at karaya.com)
++/*
++ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   * Licensed under the GPL
   */
  
--#include "linux/personality.h"
--#include "linux/ptrace.h"
--#include "asm/unistd.h"
--#include "asm/uaccess.h"
--#include "asm/ucontext.h"
-+#include <linux/personality.h>
-+#include <linux/ptrace.h>
-+#include <asm/unistd.h>
-+#include <asm/uaccess.h>
-+#include <asm/ucontext.h>
- #include "frame_kern.h"
- #include "skas.h"
+@@ -8,12 +8,13 @@
+ extern void __bb_init_func(void *)  __attribute__((weak));
+ EXPORT_SYMBOL(__bb_init_func);
+ 
+-/* This is defined (and referred to in profiling stub code) only by some GCC
++/*
++ * This is defined (and referred to in profiling stub code) only by some GCC
+  * versions in libgcov.
+  *
+  * Since SuSE backported the fix, we cannot handle it depending on GCC version.
+- * So, unconditionally export it. But also give it a weak declaration, which will
+- * be overridden by any other one.
++ * So, unconditionally export it. But also give it a weak declaration, which
++ * will be overridden by any other one.
+  */
+ 
+ extern void __gcov_init(void *) __attribute__((weak));
+diff --git a/arch/um/kernel/gprof_syms.c b/arch/um/kernel/gprof_syms.c
+index 9244f01..e2f043d 100644
+--- a/arch/um/kernel/gprof_syms.c
++++ b/arch/um/kernel/gprof_syms.c
+@@ -1,5 +1,5 @@
+ /* 
+- * Copyright (C) 2001, 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
  
-@@ -27,16 +27,16 @@ void copy_sc(struct uml_pt_regs *regs, void *from)
- 	GETREG(regs, R13, sc, r13);
- 	GETREG(regs, R14, sc, r14);
- 	GETREG(regs, R15, sc, r15);
--	GETREG(regs, RDI, sc, rdi);
--	GETREG(regs, RSI, sc, rsi);
--	GETREG(regs, RBP, sc, rbp);
--	GETREG(regs, RBX, sc, rbx);
--	GETREG(regs, RDX, sc, rdx);
--	GETREG(regs, RAX, sc, rax);
--	GETREG(regs, RCX, sc, rcx);
--	GETREG(regs, RSP, sc, rsp);
--	GETREG(regs, RIP, sc, rip);
--	GETREG(regs, EFLAGS, sc, eflags);
-+	GETREG(regs, RDI, sc, di);
-+	GETREG(regs, RSI, sc, si);
-+	GETREG(regs, RBP, sc, bp);
-+	GETREG(regs, RBX, sc, bx);
-+	GETREG(regs, RDX, sc, dx);
-+	GETREG(regs, RAX, sc, ax);
-+	GETREG(regs, RCX, sc, cx);
-+	GETREG(regs, RSP, sc, sp);
-+	GETREG(regs, RIP, sc, ip);
-+	GETREG(regs, EFLAGS, sc, flags);
- 	GETREG(regs, CS, sc, cs);
+@@ -7,14 +7,3 @@
  
- #undef GETREG
-@@ -61,16 +61,16 @@ static int copy_sc_from_user(struct pt_regs *regs,
- 	err |= GETREG(regs, R13, from, r13);
- 	err |= GETREG(regs, R14, from, r14);
- 	err |= GETREG(regs, R15, from, r15);
--	err |= GETREG(regs, RDI, from, rdi);
--	err |= GETREG(regs, RSI, from, rsi);
--	err |= GETREG(regs, RBP, from, rbp);
--	err |= GETREG(regs, RBX, from, rbx);
--	err |= GETREG(regs, RDX, from, rdx);
--	err |= GETREG(regs, RAX, from, rax);
--	err |= GETREG(regs, RCX, from, rcx);
--	err |= GETREG(regs, RSP, from, rsp);
--	err |= GETREG(regs, RIP, from, rip);
--	err |= GETREG(regs, EFLAGS, from, eflags);
-+	err |= GETREG(regs, RDI, from, di);
-+	err |= GETREG(regs, RSI, from, si);
-+	err |= GETREG(regs, RBP, from, bp);
-+	err |= GETREG(regs, RBX, from, bx);
-+	err |= GETREG(regs, RDX, from, dx);
-+	err |= GETREG(regs, RAX, from, ax);
-+	err |= GETREG(regs, RCX, from, cx);
-+	err |= GETREG(regs, RSP, from, sp);
-+	err |= GETREG(regs, RIP, from, ip);
-+	err |= GETREG(regs, EFLAGS, from, flags);
- 	err |= GETREG(regs, CS, from, cs);
- 	if (err)
- 		return 1;
-@@ -108,19 +108,19 @@ static int copy_sc_to_user(struct sigcontext __user *to,
- 	__put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
- 		   &(sc)->regname)
+ extern void mcount(void);
+ EXPORT_SYMBOL(mcount);
+-
+-/*
+- * 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/kernel/initrd.c b/arch/um/kernel/initrd.c
+index 16dc43e..fa01556 100644
+--- a/arch/um/kernel/initrd.c
++++ b/arch/um/kernel/initrd.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
  
--	err |= PUTREG(regs, RDI, to, rdi);
--	err |= PUTREG(regs, RSI, to, rsi);
--	err |= PUTREG(regs, RBP, to, rbp);
-+	err |= PUTREG(regs, RDI, to, di);
-+	err |= PUTREG(regs, RSI, to, si);
-+	err |= PUTREG(regs, RBP, to, bp);
- 	/*
- 	 * Must use orignal RSP, which is passed in, rather than what's in
- 	 * the pt_regs, because that's already been updated to point at the
- 	 * signal frame.
- 	 */
--	err |= __put_user(sp, &to->rsp);
--	err |= PUTREG(regs, RBX, to, rbx);
--	err |= PUTREG(regs, RDX, to, rdx);
--	err |= PUTREG(regs, RCX, to, rcx);
--	err |= PUTREG(regs, RAX, to, rax);
-+	err |= __put_user(sp, &to->sp);
-+	err |= PUTREG(regs, RBX, to, bx);
-+	err |= PUTREG(regs, RDX, to, dx);
-+	err |= PUTREG(regs, RCX, to, cx);
-+	err |= PUTREG(regs, RAX, to, ax);
- 	err |= PUTREG(regs, R8, to, r8);
- 	err |= PUTREG(regs, R9, to, r9);
- 	err |= PUTREG(regs, R10, to, r10);
-@@ -135,8 +135,8 @@ static int copy_sc_to_user(struct sigcontext __user *to,
- 	err |= __put_user(fi->error_code, &to->err);
- 	err |= __put_user(fi->trap_no, &to->trapno);
+@@ -7,7 +7,6 @@
+ #include "linux/bootmem.h"
+ #include "linux/initrd.h"
+ #include "asm/types.h"
+-#include "kern_util.h"
+ #include "initrd.h"
+ #include "init.h"
+ #include "os.h"
+@@ -21,18 +20,27 @@ static int __init read_initrd(void)
+ 	long long size;
+ 	int err;
  
--	err |= PUTREG(regs, RIP, to, rip);
--	err |= PUTREG(regs, EFLAGS, to, eflags);
-+	err |= PUTREG(regs, RIP, to, ip);
-+	err |= PUTREG(regs, EFLAGS, to, flags);
- #undef PUTREG
+-	if(initrd == NULL)
++	if (initrd == NULL)
+ 		return 0;
  
- 	err |= __put_user(mask, &to->oldmask);
-diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
-index 6172599..d08cd1d 100644
---- a/arch/v850/kernel/vmlinux.lds.S
-+++ b/arch/v850/kernel/vmlinux.lds.S
-@@ -114,7 +114,7 @@
- #define DATA_CONTENTS							      \
- 		__sdata = . ;						      \
- 		DATA_DATA						      \
--			*(.exit.data)	/* 2.5 convention */		      \
-+			EXIT_DATA	/* 2.5 convention */		      \
- 			*(.data.exit)	/* 2.4 convention */		      \
- 		. = ALIGN (16) ;					      \
- 		*(.data.cacheline_aligned)				      \
-@@ -157,9 +157,9 @@
- 		. = ALIGN (4096) ;					      \
- 		__init_start = . ;					      \
- 			__sinittext = .;				      \
--			*(.init.text)	/* 2.5 convention */		      \
-+			INIT_TEXT	/* 2.5 convention */		      \
- 			__einittext = .;				      \
--			*(.init.data)					      \
-+			INIT_DATA					      \
- 			*(.text.init)	/* 2.4 convention */		      \
- 			*(.data.init)					      \
- 		INITCALL_CONTENTS					      \
-@@ -170,7 +170,7 @@
- #define ROMK_INIT_RAM_CONTENTS						      \
- 		. = ALIGN (4096) ;					      \
- 		__init_start = . ;					      \
--			*(.init.data)	/* 2.5 convention */		      \
-+			INIT_DATA	/* 2.5 convention */		      \
- 			*(.data.init)	/* 2.4 convention */		      \
- 		__init_end = . ;					      \
- 		. = ALIGN (4096) ;
-@@ -179,7 +179,7 @@
-    should go into ROM.  */	
- #define ROMK_INIT_ROM_CONTENTS						      \
- 			_sinittext = .;					      \
--			*(.init.text)	/* 2.5 convention */		      \
-+			INIT_TEXT	/* 2.5 convention */		      \
- 			_einittext = .;					      \
- 			*(.text.init)	/* 2.4 convention */		      \
- 		INITCALL_CONTENTS					      \
-diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index 80b7ba4..7109037 100644
---- a/arch/x86/Kconfig
-+++ b/arch/x86/Kconfig
-@@ -17,81 +17,72 @@ config X86_64
+ 	err = os_file_size(initrd, &size);
+-	if(err)
++	if (err)
+ 		return 0;
  
- ### Arch settings
- config X86
--	bool
--	default y
-+	def_bool y
++	/*
++	 * This is necessary because alloc_bootmem craps out if you
++	 * ask for no memory.
++	 */
++	if (size == 0) {
++		printk(KERN_ERR "\"%\" is a zero-size initrd\n");
++		return 0;
++	}
 +
-+config GENERIC_LOCKBREAK
-+	def_bool n
+ 	area = alloc_bootmem(size);
+-	if(area == NULL)
++	if (area == NULL)
+ 		return 0;
  
- config GENERIC_TIME
--	bool
--	default y
-+	def_bool y
+-	if(load_initrd(initrd, area, size) == -1)
++	if (load_initrd(initrd, area, size) == -1)
+ 		return 0;
  
- config GENERIC_CMOS_UPDATE
--	bool
--	default y
-+	def_bool y
+ 	initrd_start = (unsigned long) area;
+@@ -59,13 +67,15 @@ int load_initrd(char *filename, void *buf, int size)
+ 	int fd, n;
+ 
+ 	fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+-	if(fd < 0){
+-		printk("Opening '%s' failed - err = %d\n", filename, -fd);
++	if (fd < 0) {
++		printk(KERN_ERR "Opening '%s' failed - err = %d\n", filename,
++		       -fd);
+ 		return -1;
+ 	}
+ 	n = os_read_file(fd, buf, size);
+-	if(n != size){
+-		printk("Read of %d bytes from '%s' failed, err = %d\n", size,
++	if (n != size) {
++		printk(KERN_ERR "Read of %d bytes from '%s' failed, "
++		       "err = %d\n", size,
+ 		       filename, -n);
+ 		return -1;
+ 	}
+diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
+index ba11ccd..91587f8 100644
+--- a/arch/um/kernel/irq.c
++++ b/arch/um/kernel/irq.c
+@@ -107,10 +107,9 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
+ 	struct pollfd *tmp_pfd;
+ 	struct irq_fd *new_fd, *irq_fd;
+ 	unsigned long flags;
+-	int pid, events, err, n;
++	int events, err, n;
  
- config CLOCKSOURCE_WATCHDOG
--	bool
--	default y
-+	def_bool y
+-	pid = os_getpid();
+-	err = os_set_fd_async(fd, pid);
++	err = os_set_fd_async(fd);
+ 	if (err < 0)
+ 		goto out;
  
- config GENERIC_CLOCKEVENTS
--	bool
--	default y
-+	def_bool y
+@@ -127,7 +126,6 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
+ 				     .fd 		= fd,
+ 				     .type 		= type,
+ 				     .irq 		= irq,
+-				     .pid  		= pid,
+ 				     .events 		= events,
+ 				     .current_events 	= 0 } );
  
- config GENERIC_CLOCKEVENTS_BROADCAST
--	bool
--	default y
-+	def_bool y
- 	depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
+diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
+index 1b388b4..5311ee9 100644
+--- a/arch/um/kernel/ksyms.c
++++ b/arch/um/kernel/ksyms.c
+@@ -18,15 +18,11 @@ EXPORT_SYMBOL(set_signals);
+ EXPORT_SYMBOL(get_signals);
+ EXPORT_SYMBOL(kernel_thread);
+ EXPORT_SYMBOL(sys_waitpid);
+-EXPORT_SYMBOL(task_size);
+ EXPORT_SYMBOL(flush_tlb_range);
+-EXPORT_SYMBOL(host_task_size);
+ EXPORT_SYMBOL(arch_validate);
+-EXPORT_SYMBOL(get_kmem_end);
  
- config LOCKDEP_SUPPORT
--	bool
--	default y
-+	def_bool y
+ EXPORT_SYMBOL(high_physmem);
+ EXPORT_SYMBOL(empty_zero_page);
+-EXPORT_SYMBOL(um_virt_to_phys);
+ EXPORT_SYMBOL(handle_page_fault);
+ EXPORT_SYMBOL(find_iomem);
+ 
+@@ -40,7 +36,6 @@ EXPORT_SYMBOL(uml_strdup);
+ EXPORT_SYMBOL(os_stat_fd);
+ EXPORT_SYMBOL(os_stat_file);
+ EXPORT_SYMBOL(os_access);
+-EXPORT_SYMBOL(os_get_exec_close);
+ EXPORT_SYMBOL(os_set_exec_close);
+ EXPORT_SYMBOL(os_getpid);
+ EXPORT_SYMBOL(os_open_file);
+@@ -71,10 +66,10 @@ EXPORT_SYMBOL(dump_thread);
  
- config STACKTRACE_SUPPORT
--	bool
--	default y
-+	def_bool y
+ /* required for SMP */
+ 
+-extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
++extern void __write_lock_failed(rwlock_t *rw);
+ EXPORT_SYMBOL(__write_lock_failed);
+ 
+-extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
++extern void __read_lock_failed(rwlock_t *rw);
+ EXPORT_SYMBOL(__read_lock_failed);
+ 
+ #endif
+diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
+index 59822de..d872fdc 100644
+--- a/arch/um/kernel/mem.c
++++ b/arch/um/kernel/mem.c
+@@ -1,49 +1,41 @@
+ /*
+- * Copyright (C) 2000 - 2003 Jeff Dike (jdike at addtoit.com)
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+-#include "linux/stddef.h"
+-#include "linux/kernel.h"
+-#include "linux/mm.h"
+-#include "linux/bootmem.h"
+-#include "linux/swap.h"
+-#include "linux/highmem.h"
+-#include "linux/gfp.h"
+-#include "asm/page.h"
+-#include "asm/fixmap.h"
+-#include "asm/pgalloc.h"
+-#include "kern_util.h"
++#include <linux/stddef.h>
++#include <linux/bootmem.h>
++#include <linux/gfp.h>
++#include <linux/highmem.h>
++#include <linux/mm.h>
++#include <linux/swap.h>
++#include <asm/fixmap.h>
++#include <asm/page.h>
+ #include "as-layout.h"
++#include "init.h"
+ #include "kern.h"
++#include "kern_util.h"
+ #include "mem_user.h"
+-#include "um_uaccess.h"
+ #include "os.h"
+-#include "linux/types.h"
+-#include "linux/string.h"
+-#include "init.h"
+-#include "kern_constants.h"
+ 
+ /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
+ unsigned long *empty_zero_page = NULL;
+ /* allocated in paging_init and unchanged thereafter */
+ unsigned long *empty_bad_page = NULL;
 +
-+config HAVE_LATENCYTOP_SUPPORT
-+	def_bool y
++/*
++ * Initialized during boot, and readonly for initializing page tables
++ * afterwards
++ */
+ pgd_t swapper_pg_dir[PTRS_PER_PGD];
++
++/* Initialized at boot time, and readonly after that */
+ unsigned long long highmem;
+ int kmalloc_ok = 0;
  
- config SEMAPHORE_SLEEPERS
--	bool
--	default y
-+	def_bool y
++/* Used during early boot */
+ static unsigned long brk_end;
  
- config MMU
--	bool
--	default y
-+	def_bool y
+-void unmap_physmem(void)
+-{
+-	os_unmap_memory((void *) brk_end, uml_reserved - brk_end);
+-}
+-
+-static void map_cb(void *unused)
+-{
+-	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
+-}
+-
+ #ifdef CONFIG_HIGHMEM
+ static void setup_highmem(unsigned long highmem_start,
+ 			  unsigned long highmem_len)
+@@ -53,7 +45,7 @@ static void setup_highmem(unsigned long highmem_start,
+ 	int i;
  
- config ZONE_DMA
--	bool
--	default y
-+	def_bool y
+ 	highmem_pfn = __pa(highmem_start) >> PAGE_SHIFT;
+-	for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
++	for (i = 0; i < highmem_len >> PAGE_SHIFT; i++) {
+ 		page = &mem_map[highmem_pfn + i];
+ 		ClearPageReserved(page);
+ 		init_page_count(page);
+@@ -65,14 +57,13 @@ static void setup_highmem(unsigned long highmem_start,
+ void __init mem_init(void)
+ {
+ 	/* clear the zero-page */
+-	memset((void *) empty_zero_page, 0, PAGE_SIZE);
++	memset(empty_zero_page, 0, PAGE_SIZE);
  
- config QUICKLIST
--	bool
--	default X86_32
-+	def_bool X86_32
+ 	/* Map in the area just after the brk now that kmalloc is about
+ 	 * to be turned on.
+ 	 */
+ 	brk_end = (unsigned long) UML_ROUND_UP(sbrk(0));
+-	map_cb(NULL);
+-	initial_thread_cb(map_cb, NULL);
++	map_memory(brk_end, __pa(brk_end), uml_reserved - brk_end, 1, 1, 0);
+ 	free_bootmem(__pa(brk_end), uml_reserved - brk_end);
+ 	uml_reserved = brk_end;
  
- config SBUS
- 	bool
+@@ -85,7 +76,7 @@ void __init mem_init(void)
+ #endif
+ 	num_physpages = totalram_pages;
+ 	max_pfn = totalram_pages;
+-	printk(KERN_INFO "Memory: %luk available\n", 
++	printk(KERN_INFO "Memory: %luk available\n",
+ 	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10));
+ 	kmalloc_ok = 1;
  
- config GENERIC_ISA_DMA
--	bool
--	default y
-+	def_bool y
+@@ -119,7 +110,7 @@ static void __init one_md_table_init(pud_t *pud)
+ #endif
+ }
  
- config GENERIC_IOMAP
--	bool
--	default y
-+	def_bool y
+-static void __init fixrange_init(unsigned long start, unsigned long end, 
++static void __init fixrange_init(unsigned long start, unsigned long end,
+ 				 pgd_t *pgd_base)
+ {
+ 	pgd_t *pgd;
+@@ -138,7 +129,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
+ 		if (pud_none(*pud))
+ 			one_md_table_init(pud);
+ 		pmd = pmd_offset(pud, vaddr);
+-		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
++		for (; (j < PTRS_PER_PMD) && (vaddr < end); pmd++, j++) {
+ 			one_page_table_init(pmd);
+ 			vaddr += PMD_SIZE;
+ 		}
+@@ -152,7 +143,7 @@ pgprot_t kmap_prot;
  
- config GENERIC_BUG
--	bool
--	default y
-+	def_bool y
- 	depends on BUG
+ #define kmap_get_fixmap_pte(vaddr)					\
+ 	pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)),\
+- 			  (vaddr)), (vaddr))
++				     (vaddr)), (vaddr))
  
- config GENERIC_HWEIGHT
--	bool
--	default y
-+	def_bool y
-+
-+config GENERIC_GPIO
-+	def_bool n
+ static void __init kmap_init(void)
+ {
+@@ -197,21 +188,23 @@ static void __init fixaddr_user_init( void)
+ 	pud_t *pud;
+ 	pmd_t *pmd;
+ 	pte_t *pte;
+-	unsigned long paddr, vaddr = FIXADDR_USER_START;
++	phys_t p;
++	unsigned long v, vaddr = FIXADDR_USER_START;
  
- config ARCH_MAY_HAVE_PC_FDC
--	bool
--	default y
-+	def_bool y
+-	if (  ! size )
++	if (!size)
+ 		return;
  
- config DMI
--	bool
--	default y
-+	def_bool y
+ 	fixrange_init( FIXADDR_USER_START, FIXADDR_USER_END, swapper_pg_dir);
+-	paddr = (unsigned long)alloc_bootmem_low_pages( size);
+-	memcpy( (void *)paddr, (void *)FIXADDR_USER_START, size);
+-	paddr = __pa(paddr);
+-	for ( ; size > 0; size-=PAGE_SIZE, vaddr+=PAGE_SIZE, paddr+=PAGE_SIZE){
++	v = (unsigned long) alloc_bootmem_low_pages(size);
++	memcpy((void *) v , (void *) FIXADDR_USER_START, size);
++	p = __pa(v);
++	for ( ; size > 0; size -= PAGE_SIZE, vaddr += PAGE_SIZE,
++		      p += PAGE_SIZE) {
+ 		pgd = swapper_pg_dir + pgd_index(vaddr);
+ 		pud = pud_offset(pgd, vaddr);
+ 		pmd = pmd_offset(pud, vaddr);
+ 		pte = pte_offset_kernel(pmd, vaddr);
+-		pte_set_val( (*pte), paddr, PAGE_READONLY);
++		pte_set_val(*pte, p, PAGE_READONLY);
+ 	}
+ #endif
+ }
+@@ -223,7 +216,7 @@ void __init paging_init(void)
+ 
+ 	empty_zero_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
+ 	empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE);
+-	for(i = 0; i < ARRAY_SIZE(zones_size); i++)
++	for (i = 0; i < ARRAY_SIZE(zones_size); i++)
+ 		zones_size[i] = 0;
  
- config RWSEM_GENERIC_SPINLOCK
- 	def_bool !X86_XADD
-@@ -112,10 +103,22 @@ config GENERIC_TIME_VSYSCALL
- 	bool
- 	default X86_64
+ 	zones_size[ZONE_NORMAL] = (end_iomem >> PAGE_SHIFT) -
+@@ -253,32 +246,33 @@ struct page *arch_validate(struct page *page, gfp_t mask, int order)
+ 	int i;
  
-+config HAVE_SETUP_PER_CPU_AREA
-+	def_bool X86_64
-+
- config ARCH_SUPPORTS_OPROFILE
- 	bool
- 	default y
+  again:
+-	if(page == NULL)
++	if (page == NULL)
+ 		return page;
+-	if(PageHighMem(page))
++	if (PageHighMem(page))
+ 		return page;
  
-+select HAVE_KVM
-+
-+config ARCH_HIBERNATION_POSSIBLE
-+	def_bool y
-+	depends on !SMP || !X86_VOYAGER
-+
-+config ARCH_SUSPEND_POSSIBLE
-+	def_bool y
-+	depends on !X86_VOYAGER
+ 	addr = (unsigned long) page_address(page);
+-	for(i = 0; i < (1 << order); i++){
++	for (i = 0; i < (1 << order); i++) {
+ 		current->thread.fault_addr = (void *) addr;
+-		if(__do_copy_to_user((void __user *) addr, &zero,
++		if (__do_copy_to_user((void __user *) addr, &zero,
+ 				     sizeof(zero),
+ 				     &current->thread.fault_addr,
+-				     &current->thread.fault_catcher)){
+-			if(!(mask & __GFP_WAIT))
++				     &current->thread.fault_catcher)) {
++			if (!(mask & __GFP_WAIT))
+ 				return NULL;
+ 			else break;
+ 		}
+ 		addr += PAGE_SIZE;
+ 	}
+ 
+-	if(i == (1 << order))
++	if (i == (1 << order))
+ 		return page;
+ 	page = alloc_pages(mask, order);
+ 	goto again;
+ }
+ 
+-/* This can't do anything because nothing in the kernel image can be freed
++/*
++ * This can't do anything because nothing in the kernel image can be freed
+  * since it's not in kernel physical memory.
+  */
+ 
+@@ -290,8 +284,8 @@ void free_initmem(void)
+ void free_initrd_mem(unsigned long start, unsigned long end)
+ {
+ 	if (start < end)
+-		printk ("Freeing initrd memory: %ldk freed\n", 
+-			(end - start) >> 10);
++		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n",
++		       (end - start) >> 10);
+ 	for (; start < end; start += PAGE_SIZE) {
+ 		ClearPageReserved(virt_to_page(start));
+ 		init_page_count(virt_to_page(start));
+@@ -308,32 +302,31 @@ void show_mem(void)
+ 	int highmem = 0;
+ 	struct page *page;
  
- config ZONE_DMA32
- 	bool
-@@ -144,9 +147,17 @@ config GENERIC_PENDING_IRQ
+-	printk("Mem-info:\n");
++	printk(KERN_INFO "Mem-info:\n");
+ 	show_free_areas();
+-	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
++	printk(KERN_INFO "Free swap:       %6ldkB\n",
++	       nr_swap_pages<<(PAGE_SHIFT-10));
+ 	pfn = max_mapnr;
+-	while(pfn-- > 0) {
++	while (pfn-- > 0) {
+ 		page = pfn_to_page(pfn);
+ 		total++;
+-		if(PageHighMem(page))
++		if (PageHighMem(page))
+ 			highmem++;
+-		if(PageReserved(page))
++		if (PageReserved(page))
+ 			reserved++;
+-		else if(PageSwapCache(page))
++		else if (PageSwapCache(page))
+ 			cached++;
+-		else if(page_count(page))
++		else if (page_count(page))
+ 			shared += page_count(page) - 1;
+ 	}
+-	printk("%d pages of RAM\n", total);
+-	printk("%d pages of HIGHMEM\n", highmem);
+-	printk("%d reserved pages\n", reserved);
+-	printk("%d pages shared\n", shared);
+-	printk("%d pages swap cached\n", cached);
++	printk(KERN_INFO "%d pages of RAM\n", total);
++	printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
++	printk(KERN_INFO "%d reserved pages\n", reserved);
++	printk(KERN_INFO "%d pages shared\n", shared);
++	printk(KERN_INFO "%d pages swap cached\n", cached);
+ }
  
- config X86_SMP
- 	bool
--	depends on X86_32 && SMP && !X86_VOYAGER
-+	depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64)
- 	default y
+-/*
+- * Allocate and free page tables.
+- */
++/* Allocate and free page tables. */
  
-+config X86_32_SMP
-+	def_bool y
-+	depends on X86_32 && SMP
+ pgd_t *pgd_alloc(struct mm_struct *mm)
+ {
+@@ -341,14 +334,14 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 
+ 	if (pgd) {
+ 		memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+-		memcpy(pgd + USER_PTRS_PER_PGD, 
+-		       swapper_pg_dir + USER_PTRS_PER_PGD, 
++		memcpy(pgd + USER_PTRS_PER_PGD,
++		       swapper_pg_dir + USER_PTRS_PER_PGD,
+ 		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ 	}
+ 	return pgd;
+ }
+ 
+-void pgd_free(pgd_t *pgd)
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_page((unsigned long) pgd);
+ }
+@@ -368,3 +361,15 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+ 	pte = alloc_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
+ 	return pte;
+ }
 +
-+config X86_64_SMP
-+	def_bool y
-+	depends on X86_64 && SMP
++#ifdef CONFIG_3_LEVEL_PGTABLES
++pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
++{
++	pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
 +
- config X86_HT
- 	bool
- 	depends on SMP
-@@ -292,6 +303,18 @@ config X86_ES7000
- 	  Only choose this option if you have such a system, otherwise you
- 	  should say N here.
- 
-+config X86_RDC321X
-+	bool "RDC R-321x SoC"
-+	depends on X86_32
-+	select M486
-+	select X86_REBOOTFIXUPS
-+	select GENERIC_GPIO
-+	select LEDS_GPIO
-+	help
-+	  This option is needed for RDC R-321x system-on-chip, also known
-+	  as R-8610-(G).
-+	  If you don't have one of these chips, you should say N here.
++	if (pmd)
++		memset(pmd, 0, PAGE_SIZE);
 +
- config X86_VSMP
- 	bool "Support for ScaleMP vSMP"
- 	depends on X86_64 && PCI
-@@ -303,8 +326,8 @@ config X86_VSMP
- endchoice
++	return pmd;
++}
++#endif
+diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
+index e66432f..9757085 100644
+--- a/arch/um/kernel/physmem.c
++++ b/arch/um/kernel/physmem.c
+@@ -55,16 +55,6 @@ int __init init_maps(unsigned long physmem, unsigned long iomem,
+ 	return 0;
+ }
  
- config SCHED_NO_NO_OMIT_FRAME_POINTER
--	bool "Single-depth WCHAN output"
--	default y
-+	def_bool y
-+	prompt "Single-depth WCHAN output"
- 	depends on X86_32
- 	help
- 	  Calculate simpler /proc/<PID>/wchan values. If this option
-@@ -314,18 +337,8 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
+-/* Changed during early boot */
+-static unsigned long kmem_top = 0;
+-
+-unsigned long get_kmem_end(void)
+-{
+-	if (kmem_top == 0)
+-		kmem_top = host_task_size - 1024 * 1024;
+-	return kmem_top;
+-}
+-
+ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
+ 		int r, int w, int x)
+ {
+@@ -174,10 +164,10 @@ __uml_setup("iomem=", parse_iomem,
+  * setup_iomem, both of which run during early boot.  Afterwards, it's
+  * unchanged.
+  */
+-struct iomem_region *iomem_regions = NULL;
++struct iomem_region *iomem_regions;
  
- 	  If in doubt, say "Y".
+-/* Initialized in parse_iomem */
+-int iomem_size = 0;
++/* Initialized in parse_iomem and unchanged thereafter */
++int iomem_size;
  
--config PARAVIRT
--	bool
--	depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
--	help
--	  This changes the kernel so it can modify itself when it is run
--	  under a hypervisor, potentially improving performance significantly
--	  over full virtualization.  However, when run without a hypervisor
--	  the kernel is theoretically slower and slightly larger.
--
- menuconfig PARAVIRT_GUEST
- 	bool "Paravirtualized guest support"
--	depends on X86_32
- 	help
- 	  Say Y here to get to see options related to running Linux under
- 	  various hypervisors.  This option alone does not add any kernel code.
-@@ -339,6 +352,7 @@ source "arch/x86/xen/Kconfig"
- config VMI
- 	bool "VMI Guest support"
- 	select PARAVIRT
-+	depends on X86_32
- 	depends on !(X86_VISWS || X86_VOYAGER)
- 	help
- 	  VMI provides a paravirtualized interface to the VMware ESX server
-@@ -348,40 +362,43 @@ config VMI
+ unsigned long find_iomem(char *driver, unsigned long *len_out)
+ {
+diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
+index 0eae00b..c07961b 100644
+--- a/arch/um/kernel/process.c
++++ b/arch/um/kernel/process.c
+@@ -4,19 +4,21 @@
+  * Licensed under the GPL
+  */
  
- source "arch/x86/lguest/Kconfig"
+-#include "linux/stddef.h"
+-#include "linux/err.h"
+-#include "linux/hardirq.h"
+-#include "linux/mm.h"
+-#include "linux/personality.h"
+-#include "linux/proc_fs.h"
+-#include "linux/ptrace.h"
+-#include "linux/random.h"
+-#include "linux/sched.h"
+-#include "linux/tick.h"
+-#include "linux/threads.h"
+-#include "asm/pgtable.h"
+-#include "asm/uaccess.h"
++#include <linux/stddef.h>
++#include <linux/err.h>
++#include <linux/hardirq.h>
++#include <linux/gfp.h>
++#include <linux/mm.h>
++#include <linux/personality.h>
++#include <linux/proc_fs.h>
++#include <linux/ptrace.h>
++#include <linux/random.h>
++#include <linux/sched.h>
++#include <linux/tick.h>
++#include <linux/threads.h>
++#include <asm/current.h>
++#include <asm/pgtable.h>
++#include <asm/uaccess.h>
+ #include "as-layout.h"
+ #include "kern_util.h"
+ #include "os.h"
+@@ -30,7 +32,7 @@
+  */
+ struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
+ 
+-static inline int external_pid(struct task_struct *task)
++static inline int external_pid(void)
+ {
+ 	/* FIXME: Need to look up userspace_pid by cpu */
+ 	return userspace_pid[0];
+@@ -40,7 +42,7 @@ int pid_to_processor_id(int pid)
+ {
+ 	int i;
  
-+config PARAVIRT
-+	bool "Enable paravirtualization code"
-+	depends on !(X86_VISWS || X86_VOYAGER)
-+	help
-+	  This changes the kernel so it can modify itself when it is run
-+	  under a hypervisor, potentially improving performance significantly
-+	  over full virtualization.  However, when run without a hypervisor
-+	  the kernel is theoretically slower and slightly larger.
-+
- endif
+-	for(i = 0; i < ncpus; i++) {
++	for (i = 0; i < ncpus; i++) {
+ 		if (cpu_tasks[i].pid == pid)
+ 			return i;
+ 	}
+@@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic)
+ 	if (atomic)
+ 		flags = GFP_ATOMIC;
+ 	page = __get_free_pages(flags, order);
+-	if (page == 0)
+-		return 0;
  
- config ACPI_SRAT
--	bool
--	default y
-+	def_bool y
- 	depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
- 	select ACPI_NUMA
+ 	return page;
+ }
+@@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+ static inline void set_current(struct task_struct *task)
+ {
+ 	cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
+-		{ external_pid(task), task });
++		{ external_pid(), task });
+ }
  
- config HAVE_ARCH_PARSE_SRAT
--       bool
--       default y
--       depends on ACPI_SRAT
-+	def_bool y
-+	depends on ACPI_SRAT
+-extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
++extern void arch_switch_to(struct task_struct *to);
  
- config X86_SUMMIT_NUMA
--	bool
--	default y
-+	def_bool y
- 	depends on X86_32 && NUMA && (X86_SUMMIT || X86_GENERICARCH)
+ void *_switch_to(void *prev, void *next, void *last)
+ {
+ 	struct task_struct *from = prev;
+-	struct task_struct *to= next;
++	struct task_struct *to = next;
  
- config X86_CYCLONE_TIMER
--	bool
--	default y
-+	def_bool y
- 	depends on X86_32 && X86_SUMMIT || X86_GENERICARCH
+ 	to->thread.prev_sched = from;
+ 	set_current(to);
+@@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last)
+ 		switch_threads(&from->thread.switch_buf,
+ 			       &to->thread.switch_buf);
  
- config ES7000_CLUSTERED_APIC
--	bool
--	default y
-+	def_bool y
- 	depends on SMP && X86_ES7000 && MPENTIUMIII
+-		arch_switch_to(current->thread.prev_sched, current);
++		arch_switch_to(current);
  
- source "arch/x86/Kconfig.cpu"
+ 		if (current->thread.saved_task)
+ 			show_regs(&(current->thread.regs));
+-		next= current->thread.saved_task;
+-		prev= current;
+-	} while(current->thread.saved_task);
++		to = current->thread.saved_task;
++		from = current;
++	} while (current->thread.saved_task);
  
- config HPET_TIMER
--	bool
-+	def_bool X86_64
- 	prompt "HPET Timer Support" if X86_32
--	default X86_64
- 	help
-          Use the IA-PC HPET (High Precision Event Timer) to manage
-          time in preference to the PIT and RTC, if a HPET is
-@@ -399,9 +416,8 @@ config HPET_TIMER
-          Choose N to continue using the legacy 8254 timer.
+ 	return current->thread.prev_sched;
  
- config HPET_EMULATE_RTC
--	bool
--	depends on HPET_TIMER && RTC=y
--	default y
-+	def_bool y
-+	depends on HPET_TIMER && (RTC=y || RTC=m)
+@@ -163,8 +163,6 @@ void new_thread_handler(void)
+ void fork_handler(void)
+ {
+ 	force_flush_all();
+-	if (current->thread.prev_sched == NULL)
+-		panic("blech");
  
- # Mark as embedded because too many people got it wrong.
- # The code disables itself when not needed.
-@@ -441,8 +457,8 @@ config CALGARY_IOMMU
- 	  If unsure, say Y.
+ 	schedule_tail(current->thread.prev_sched);
  
- config CALGARY_IOMMU_ENABLED_BY_DEFAULT
--	bool "Should Calgary be enabled by default?"
--	default y
-+	def_bool y
-+	prompt "Should Calgary be enabled by default?"
- 	depends on CALGARY_IOMMU
- 	help
- 	  Should Calgary be enabled by default? if you choose 'y', Calgary
-@@ -486,9 +502,9 @@ config SCHED_SMT
- 	  N here.
+@@ -173,7 +171,7 @@ void fork_handler(void)
+ 	 * arch_switch_to isn't needed. We could want to apply this to
+ 	 * improve performance. -bb
+ 	 */
+-	arch_switch_to(current->thread.prev_sched, current);
++	arch_switch_to(current);
  
- config SCHED_MC
--	bool "Multi-core scheduler support"
-+	def_bool y
-+	prompt "Multi-core scheduler support"
- 	depends on (X86_64 && SMP) || (X86_32 && X86_HT)
--	default y
- 	help
- 	  Multi-core scheduler support improves the CPU scheduler's decision
- 	  making when dealing with multi-core CPU chips at a cost of slightly
-@@ -522,19 +538,16 @@ config X86_UP_IOAPIC
- 	  an IO-APIC, then the kernel will still run with no slowdown at all.
+ 	current->thread.prev_sched = NULL;
  
- config X86_LOCAL_APIC
--	bool
-+	def_bool y
- 	depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH))
--	default y
+@@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
+ 		arch_copy_thread(&current->thread.arch, &p->thread.arch);
+ 	}
+ 	else {
+-		init_thread_registers(&p->thread.regs.regs);
++		get_safe_registers(p->thread.regs.regs.gp);
+ 		p->thread.request.u.thread = current->thread.request.u.thread;
+ 		handler = new_thread_handler;
+ 	}
+@@ -237,7 +235,7 @@ void default_idle(void)
+ {
+ 	unsigned long long nsecs;
  
- config X86_IO_APIC
--	bool
-+	def_bool y
- 	depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH))
--	default y
+-	while(1) {
++	while (1) {
+ 		/* endless idle loop with no priority at all */
  
- config X86_VISWS_APIC
--	bool
-+	def_bool y
- 	depends on X86_32 && X86_VISWS
--	default y
+ 		/*
+@@ -256,53 +254,10 @@ void default_idle(void)
  
- config X86_MCE
- 	bool "Machine Check Exception"
-@@ -554,17 +567,17 @@ config X86_MCE
- 	  the 386 and 486, so nearly everyone can say Y here.
+ void cpu_idle(void)
+ {
+-	cpu_tasks[current_thread->cpu].pid = os_getpid();
++	cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
+ 	default_idle();
+ }
  
- config X86_MCE_INTEL
--	bool "Intel MCE features"
-+	def_bool y
-+	prompt "Intel MCE features"
- 	depends on X86_64 && X86_MCE && X86_LOCAL_APIC
--	default y
- 	help
- 	   Additional support for intel specific MCE features such as
- 	   the thermal monitor.
+-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+-		      pte_t *pte_out)
+-{
+-	pgd_t *pgd;
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *pte;
+-	pte_t ptent;
+-
+-	if (task->mm == NULL)
+-		return ERR_PTR(-EINVAL);
+-	pgd = pgd_offset(task->mm, addr);
+-	if (!pgd_present(*pgd))
+-		return ERR_PTR(-EINVAL);
+-
+-	pud = pud_offset(pgd, addr);
+-	if (!pud_present(*pud))
+-		return ERR_PTR(-EINVAL);
+-
+-	pmd = pmd_offset(pud, addr);
+-	if (!pmd_present(*pmd))
+-		return ERR_PTR(-EINVAL);
+-
+-	pte = pte_offset_kernel(pmd, addr);
+-	ptent = *pte;
+-	if (!pte_present(ptent))
+-		return ERR_PTR(-EINVAL);
+-
+-	if (pte_out != NULL)
+-		*pte_out = ptent;
+-	return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
+-}
+-
+-char *current_cmd(void)
+-{
+-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
+-	return "(Unknown)";
+-#else
+-	void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
+-	return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
+-#endif
+-}
+-
+ void dump_thread(struct pt_regs *regs, struct user *u)
+ {
+ }
+@@ -317,7 +272,7 @@ int user_context(unsigned long sp)
+ 	unsigned long stack;
  
- config X86_MCE_AMD
--	bool "AMD MCE features"
-+	def_bool y
-+	prompt "AMD MCE features"
- 	depends on X86_64 && X86_MCE && X86_LOCAL_APIC
--	default y
- 	help
- 	   Additional support for AMD specific MCE features such as
- 	   the DRAM Error Threshold.
-@@ -637,9 +650,9 @@ config I8K
- 	  Say N otherwise.
+ 	stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
+-	return stack != (unsigned long) current_thread;
++	return stack != (unsigned long) current_thread_info();
+ }
  
- config X86_REBOOTFIXUPS
--	bool "Enable X86 board specific fixups for reboot"
-+	def_bool n
-+	prompt "Enable X86 board specific fixups for reboot"
- 	depends on X86_32 && 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
-@@ -648,7 +661,7 @@ config X86_REBOOTFIXUPS
- 	  system.
+ extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
+@@ -331,7 +286,7 @@ void do_uml_exitcalls(void)
+ 		(*call)();
+ }
  
- 	  Currently, the only fixup is for the Geode machines using
--	  CS5530A and CS5536 chipsets.
-+	  CS5530A and CS5536 chipsets and the RDC R-321x SoC.
+-char *uml_strdup(char *string)
++char *uml_strdup(const char *string)
+ {
+ 	return kstrdup(string, GFP_KERNEL);
+ }
+@@ -359,7 +314,7 @@ int strlen_user_proc(char __user *str)
+ int smp_sigio_handler(void)
+ {
+ #ifdef CONFIG_SMP
+-	int cpu = current_thread->cpu;
++	int cpu = current_thread_info()->cpu;
+ 	IPI_handler(cpu);
+ 	if (cpu != 0)
+ 		return 1;
+@@ -369,7 +324,7 @@ int smp_sigio_handler(void)
  
- 	  Say Y if you want to enable the fixup. Currently, it's safe to
- 	  enable this option even if you don't need it.
-@@ -672,9 +685,8 @@ config MICROCODE
- 	  module will be called microcode.
+ int cpu(void)
+ {
+-	return current_thread->cpu;
++	return current_thread_info()->cpu;
+ }
  
- config MICROCODE_OLD_INTERFACE
--	bool
-+	def_bool y
- 	depends on MICROCODE
--	default y
+ static atomic_t using_sysemu = ATOMIC_INIT(0);
+@@ -435,7 +390,7 @@ int singlestepping(void * t)
+ {
+ 	struct task_struct *task = t ? t : current;
  
- config X86_MSR
- 	tristate "/dev/cpu/*/msr - Model-specific register support"
-@@ -798,13 +810,12 @@ config PAGE_OFFSET
- 	depends on X86_32
+-	if ( ! (task->ptrace & PT_DTRACE) )
++	if (!(task->ptrace & PT_DTRACE))
+ 		return 0;
  
- config HIGHMEM
--	bool
-+	def_bool y
- 	depends on X86_32 && (HIGHMEM64G || HIGHMEM4G)
--	default y
+ 	if (task->thread.singlestep_syscall)
+@@ -459,3 +414,46 @@ unsigned long arch_align_stack(unsigned long sp)
+ 	return sp & ~0xf;
+ }
+ #endif
++
++unsigned long get_wchan(struct task_struct *p)
++{
++	unsigned long stack_page, sp, ip;
++	bool seen_sched = 0;
++
++	if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
++		return 0;
++
++	stack_page = (unsigned long) task_stack_page(p);
++	/* Bail if the process has no kernel stack for some reason */
++	if (stack_page == 0)
++		return 0;
++
++	sp = p->thread.switch_buf->JB_SP;
++	/*
++	 * Bail if the stack pointer is below the bottom of the kernel
++	 * stack for some reason
++	 */
++	if (sp < stack_page)
++		return 0;
++
++	while (sp < stack_page + THREAD_SIZE) {
++		ip = *((unsigned long *) sp);
++		if (in_sched_functions(ip))
++			/* Ignore everything until we're above the scheduler */
++			seen_sched = 1;
++		else if (kernel_text_address(ip) && seen_sched)
++			return ip;
++
++		sp += sizeof(unsigned long);
++	}
++
++	return 0;
++}
++
++int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
++{
++	int cpu = current_thread_info()->cpu;
++
++	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
++}
++
+diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
+index 04cebcf..00197d3 100644
+--- a/arch/um/kernel/reboot.c
++++ b/arch/um/kernel/reboot.c
+@@ -4,6 +4,7 @@
+  */
  
- config X86_PAE
--	bool "PAE (Physical Address Extension) Support"
--	default n
-+	def_bool n
-+	prompt "PAE (Physical Address Extension) Support"
- 	depends on X86_32 && !HIGHMEM4G
- 	select RESOURCES_64BIT
- 	help
-@@ -836,10 +847,10 @@ comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
- 	depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI)
+ #include "linux/sched.h"
++#include "kern_util.h"
+ #include "os.h"
+ #include "skas.h"
  
- config K8_NUMA
--       bool "Old style AMD Opteron NUMA detection"
--       depends on X86_64 && NUMA && PCI
--       default y
--       help
-+	def_bool y
-+	prompt "Old style AMD Opteron NUMA detection"
-+	depends on X86_64 && NUMA && PCI
-+	help
- 	 Enable K8 NUMA node topology detection.  You should say Y here if
- 	 you have a multi processor AMD K8 system. This uses an old
- 	 method to read the NUMA configuration directly from the builtin
-@@ -847,10 +858,10 @@ config K8_NUMA
- 	 instead, which also takes priority if both are compiled in.
+@@ -11,7 +12,7 @@ void (*pm_power_off)(void);
  
- config X86_64_ACPI_NUMA
--	bool "ACPI NUMA detection"
-+	def_bool y
-+	prompt "ACPI NUMA detection"
- 	depends on X86_64 && NUMA && ACPI && PCI
- 	select ACPI_NUMA
--	default y
- 	help
- 	  Enable ACPI SRAT based node topology detection.
+ static void kill_off_processes(void)
+ {
+-	if(proc_mm)
++	if (proc_mm)
+ 		/*
+ 		 * FIXME: need to loop over userspace_pids
+ 		 */
+@@ -21,8 +22,8 @@ static void kill_off_processes(void)
+ 		int pid, me;
  
-@@ -864,52 +875,53 @@ config NUMA_EMU
+ 		me = os_getpid();
+-		for_each_process(p){
+-			if(p->mm == NULL)
++		for_each_process(p) {
++			if (p->mm == NULL)
+ 				continue;
  
- config NODES_SHIFT
- 	int
-+	range 1 15  if X86_64
- 	default "6" if X86_64
- 	default "4" if X86_NUMAQ
- 	default "3"
- 	depends on NEED_MULTIPLE_NODES
+ 			pid = p->mm->context.id.u.pid;
+diff --git a/arch/um/kernel/sigio.c b/arch/um/kernel/sigio.c
+index 89f9866..2b272b6 100644
+--- a/arch/um/kernel/sigio.c
++++ b/arch/um/kernel/sigio.c
+@@ -1,18 +1,12 @@
+ /*
+- * Copyright (C) 2002 - 2003 Jeff Dike (jdike at addtoit.com)
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
+  * Licensed under the GPL
+  */
  
- config HAVE_ARCH_BOOTMEM_NODE
--	bool
-+	def_bool y
- 	depends on X86_32 && NUMA
--	default y
+-#include "linux/kernel.h"
+-#include "linux/list.h"
+-#include "linux/slab.h"
+-#include "linux/signal.h"
+-#include "linux/interrupt.h"
+-#include "init.h"
+-#include "sigio.h"
+-#include "irq_user.h"
++#include <linux/interrupt.h>
+ #include "irq_kern.h"
+ #include "os.h"
++#include "sigio.h"
+ 
+ /* Protected by sigio_lock() called from write_sigio_workaround */
+ static int sigio_irq_fd = -1;
+@@ -33,9 +27,9 @@ int write_sigio_irq(int fd)
+ 	err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt,
+ 			     IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio",
+ 			     NULL);
+-	if(err){
+-		printk("write_sigio_irq : um_request_irq failed, err = %d\n",
+-		       err);
++	if (err) {
++		printk(KERN_ERR "write_sigio_irq : um_request_irq failed, "
++		       "err = %d\n", err);
+ 		return -1;
+ 	}
+ 	sigio_irq_fd = fd;
+diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
+index 19cb977..b0fce72 100644
+--- a/arch/um/kernel/signal.c
++++ b/arch/um/kernel/signal.c
+@@ -3,12 +3,12 @@
+  * Licensed under the GPL
+  */
  
- config ARCH_HAVE_MEMORY_PRESENT
--	bool
-+	def_bool y
- 	depends on X86_32 && DISCONTIGMEM
--	default y
+-#include "linux/module.h"
+-#include "linux/ptrace.h"
+-#include "linux/sched.h"
+-#include "asm/siginfo.h"
+-#include "asm/signal.h"
+-#include "asm/unistd.h"
++#include <linux/module.h>
++#include <linux/ptrace.h>
++#include <linux/sched.h>
++#include <asm/siginfo.h>
++#include <asm/signal.h>
++#include <asm/unistd.h>
+ #include "frame_kern.h"
+ #include "kern_util.h"
+ #include "sigcontext.h"
+@@ -36,7 +36,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
+ 	/* Did we come from a system call? */
+ 	if (PT_REGS_SYSCALL_NR(regs) >= 0) {
+ 		/* If so, check system call restarting.. */
+-		switch(PT_REGS_SYSCALL_RET(regs)) {
++		switch (PT_REGS_SYSCALL_RET(regs)) {
+ 		case -ERESTART_RESTARTBLOCK:
+ 		case -ERESTARTNOHAND:
+ 			PT_REGS_SYSCALL_RET(regs) = -EINTR;
+@@ -116,7 +116,7 @@ static int kern_do_signal(struct pt_regs *regs)
+ 	/* Did we come from a system call? */
+ 	if (!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)) {
+ 		/* Restart the system call - no handlers present */
+-		switch(PT_REGS_SYSCALL_RET(regs)) {
++		switch (PT_REGS_SYSCALL_RET(regs)) {
+ 		case -ERESTARTNOHAND:
+ 		case -ERESTARTSYS:
+ 		case -ERESTARTNOINTR:
+diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c
+index 8d07a7a..2c8583c 100644
+--- a/arch/um/kernel/skas/clone.c
++++ b/arch/um/kernel/skas/clone.c
+@@ -1,17 +1,20 @@
+-#include <sched.h>
++/*
++ * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
++ * Licensed under the GPL
++ */
++
+ #include <signal.h>
+-#include <sys/mman.h>
+-#include <sys/time.h>
++#include <sched.h>
+ #include <asm/unistd.h>
++#include <sys/time.h>
+ #include "as-layout.h"
++#include "kern_constants.h"
+ #include "ptrace_user.h"
+-#include "skas.h"
+ #include "stub-data.h"
+-#include "uml-config.h"
+ #include "sysdep/stub.h"
+-#include "kern_constants.h"
+ 
+-/* This is in a separate file because it needs to be compiled with any
++/*
++ * This is in a separate file because it needs to be compiled with any
+  * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
+  *
+  * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize
+@@ -26,25 +29,26 @@ stub_clone_handler(void)
+ 
+ 	err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
+ 			    STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *));
+-	if(err != 0)
++	if (err != 0)
+ 		goto out;
  
- config NEED_NODE_MEMMAP_SIZE
--	bool
-+	def_bool y
- 	depends on X86_32 && (DISCONTIGMEM || SPARSEMEM)
--	default y
+ 	err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
+-	if(err)
++	if (err)
+ 		goto out;
  
- config HAVE_ARCH_ALLOC_REMAP
--	bool
-+	def_bool y
- 	depends on X86_32 && NUMA
--	default y
+-	err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, 
++	err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
+ 			    (long) &data->timer, 0);
+-	if(err)
++	if (err)
+ 		goto out;
  
- config ARCH_FLATMEM_ENABLE
- 	def_bool y
--	depends on (X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC) || (X86_64 && !NUMA)
-+	depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC && !NUMA
+ 	remap_stack(data->fd, data->offset);
+ 	goto done;
  
- config ARCH_DISCONTIGMEM_ENABLE
- 	def_bool y
--	depends on NUMA
-+	depends on NUMA && X86_32
+  out:
+-	/* save current result. 
+-	 * Parent: pid; 
+-	 * child: retcode of mmap already saved and it jumps around this 
++	/*
++	 * save current result.
++	 * Parent: pid;
++	 * child: retcode of mmap already saved and it jumps around this
+ 	 * assignment
+ 	 */
+ 	data->err = err;
+diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
+index f859ec3..78b3e9f 100644
+--- a/arch/um/kernel/skas/mmu.c
++++ b/arch/um/kernel/skas/mmu.c
+@@ -34,33 +34,14 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc,
+ 	if (!pte)
+ 		goto out_pte;
  
- config ARCH_DISCONTIGMEM_DEFAULT
- 	def_bool y
--	depends on NUMA
-+	depends on NUMA && X86_32
+-	/*
+-	 * There's an interaction between the skas0 stub pages, stack
+-	 * randomization, and the BUG at the end of exit_mmap.  exit_mmap
+-	 * checks that the number of page tables freed is the same as had
+-	 * been allocated.  If the stack is on the last page table page,
+-	 * then the stack pte page will be freed, and if not, it won't.  To
+-	 * avoid having to know where the stack is, or if the process mapped
+-	 * something at the top of its address space for some other reason,
+-	 * we set TASK_SIZE to end at the start of the last page table.
+-	 * This keeps exit_mmap off the last page, but introduces a leak
+-	 * of that page.  So, we hang onto it here and free it in
+-	 * destroy_context_skas.
+-	 */
+-
+-	mm->context.last_page_table = pmd_page_vaddr(*pmd);
+-#ifdef CONFIG_3_LEVEL_PGTABLES
+-	mm->context.last_pmd = (unsigned long) __va(pud_val(*pud));
+-#endif
+-
+ 	*pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT));
+ 	*pte = pte_mkread(*pte);
+ 	return 0;
+ 
+  out_pmd:
+-	pud_free(pud);
++	pud_free(mm, pud);
+  out_pte:
+-	pmd_free(pmd);
++	pmd_free(mm, pmd);
+  out:
+ 	return -ENOMEM;
+ }
+@@ -76,24 +57,6 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
+ 		stack = get_zeroed_page(GFP_KERNEL);
+ 		if (stack == 0)
+ 			goto out;
+-
+-		/*
+-		 * This zeros the entry that pgd_alloc didn't, needed since
+-		 * we are about to reinitialize it, and want mm.nr_ptes to
+-		 * be accurate.
+-		 */
+-		mm->pgd[USER_PTRS_PER_PGD] = __pgd(0);
+-
+-		ret = init_stub_pte(mm, STUB_CODE,
+-				    (unsigned long) &__syscall_stub_start);
+-		if (ret)
+-			goto out_free;
+-
+-		ret = init_stub_pte(mm, STUB_DATA, stack);
+-		if (ret)
+-			goto out_free;
+-
+-		mm->nr_ptes--;
+ 	}
+ 
+ 	to_mm->id.stack = stack;
+@@ -114,6 +77,11 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
+ 			to_mm->id.u.pid = copy_context_skas0(stack,
+ 							     from_mm->id.u.pid);
+ 		else to_mm->id.u.pid = start_userspace(stack);
 +
-+config ARCH_SPARSEMEM_DEFAULT
-+	def_bool y
-+	depends on X86_64
++		if (to_mm->id.u.pid < 0) {
++			ret = to_mm->id.u.pid;
++			goto out_free;
++		}
+ 	}
  
- config ARCH_SPARSEMEM_ENABLE
- 	def_bool y
--	depends on NUMA || (EXPERIMENTAL && (X86_PC || X86_64))
-+	depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC)
- 	select SPARSEMEM_STATIC if X86_32
- 	select SPARSEMEM_VMEMMAP_ENABLE if X86_64
+ 	ret = init_new_ldt(to_mm, from_mm);
+@@ -132,24 +100,87 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
+ 	return ret;
+ }
  
- config ARCH_SELECT_MEMORY_MODEL
- 	def_bool y
--	depends on X86_32 && ARCH_SPARSEMEM_ENABLE
-+	depends on ARCH_SPARSEMEM_ENABLE
++void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
++{
++	struct page **pages;
++	int err, ret;
++
++	if (!skas_needs_stub)
++		return;
++
++	ret = init_stub_pte(mm, STUB_CODE,
++			    (unsigned long) &__syscall_stub_start);
++	if (ret)
++		goto out;
++
++	ret = init_stub_pte(mm, STUB_DATA, mm->context.id.stack);
++	if (ret)
++		goto out;
++
++	pages = kmalloc(2 * sizeof(struct page *), GFP_KERNEL);
++	if (pages == NULL) {
++		printk(KERN_ERR "arch_dup_mmap failed to allocate 2 page "
++		       "pointers\n");
++		goto out;
++	}
++
++	pages[0] = virt_to_page(&__syscall_stub_start);
++	pages[1] = virt_to_page(mm->context.id.stack);
++
++	/* dup_mmap already holds mmap_sem */
++	err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
++				      VM_READ | VM_MAYREAD | VM_EXEC |
++				      VM_MAYEXEC | VM_DONTCOPY, pages);
++	if (err) {
++		printk(KERN_ERR "install_special_mapping returned %d\n", err);
++		goto out_free;
++	}
++	return;
++
++out_free:
++	kfree(pages);
++out:
++	force_sigsegv(SIGSEGV, current);
++}
++
++void arch_exit_mmap(struct mm_struct *mm)
++{
++	pte_t *pte;
++
++	pte = virt_to_pte(mm, STUB_CODE);
++	if (pte != NULL)
++		pte_clear(mm, STUB_CODE, pte);
++
++	pte = virt_to_pte(mm, STUB_DATA);
++	if (pte == NULL)
++		return;
++
++	pte_clear(mm, STUB_DATA, pte);
++}
++
+ void destroy_context(struct mm_struct *mm)
+ {
+ 	struct mm_context *mmu = &mm->context;
  
- config ARCH_MEMORY_PROBE
- 	def_bool X86_64
-@@ -987,42 +999,32 @@ config MTRR
- 	  See <file:Documentation/mtrr.txt> for more information.
+ 	if (proc_mm)
+ 		os_close_file(mmu->id.u.mm_fd);
+-	else
++	else {
++		/*
++		 * If init_new_context wasn't called, this will be
++		 * zero, resulting in a kill(0), which will result in the
++		 * whole UML suddenly dying.  Also, cover negative and
++		 * 1 cases, since they shouldn't happen either.
++		 */
++		if (mmu->id.u.pid < 2) {
++			printk(KERN_ERR "corrupt mm_context - pid = %d\n",
++			       mmu->id.u.pid);
++			return;
++		}
+ 		os_kill_ptraced_process(mmu->id.u.pid, 1);
++	}
  
- config EFI
--	bool "Boot from EFI support"
--	depends on X86_32 && ACPI
--	default n
-+	def_bool n
-+	prompt "EFI runtime service support"
-+	depends on ACPI
- 	---help---
--	This enables the kernel to boot on EFI platforms using
--	system configuration information passed to it from the firmware.
--	This also enables the kernel to use any EFI runtime services that are
-+	This enables the kernel to use EFI runtime services that are
- 	available (such as the EFI variable services).
+-	if (!proc_mm || !ptrace_faultinfo) {
++	if (skas_needs_stub)
+ 		free_page(mmu->id.stack);
+-		pte_lock_deinit(virt_to_page(mmu->last_page_table));
+-		pte_free_kernel((pte_t *) mmu->last_page_table);
+-		dec_zone_page_state(virt_to_page(mmu->last_page_table), NR_PAGETABLE);
+-#ifdef CONFIG_3_LEVEL_PGTABLES
+-		pmd_free((pmd_t *) mmu->last_pmd);
+-#endif
+-	}
  
--	This option is only useful on systems that have EFI firmware
--	and will result in a kernel image that is ~8k larger.  In addition,
--	you must use the latest ELILO loader available at
--	<http://elilo.sourceforge.net> in order to take advantage of
--	kernel initialization using EFI information (neither GRUB nor LILO know
--	anything about EFI).  However, even with this option, the resultant
--	kernel should continue to boot on existing non-EFI platforms.
-+	This option is only useful on systems that have EFI firmware.
-+  	In addition, you should use the latest ELILO loader available
-+  	at <http://elilo.sourceforge.net> in order to take advantage
-+  	of EFI runtime services. However, even with this option, the
-+  	resultant kernel should continue to boot on existing non-EFI
-+  	platforms.
+ 	free_ldt(mmu);
+ }
+diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
+index fce389c..2e9852c 100644
+--- a/arch/um/kernel/skas/process.c
++++ b/arch/um/kernel/skas/process.c
+@@ -6,19 +6,25 @@
+ #include "linux/init.h"
+ #include "linux/sched.h"
+ #include "as-layout.h"
++#include "kern.h"
+ #include "os.h"
+ #include "skas.h"
  
- config IRQBALANCE
--	bool "Enable kernel irq balancing"
-+	def_bool y
-+	prompt "Enable kernel irq balancing"
- 	depends on X86_32 && SMP && X86_IO_APIC
--	default y
- 	help
- 	  The default yes will allow the kernel to do irq load balancing.
- 	  Saying no will keep the kernel from doing irq load balancing.
+ int new_mm(unsigned long stack)
+ {
+-	int fd;
++	int fd, err;
  
--# turning this on wastes a bunch of space.
--# Summit needs it only when NUMA is on
--config BOOT_IOREMAP
--	bool
--	depends on X86_32 && (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
--	default y
--
- config SECCOMP
--	bool "Enable seccomp to safely compute untrusted bytecode"
-+	def_bool y
-+	prompt "Enable seccomp to safely compute untrusted bytecode"
- 	depends on PROC_FS
--	default y
- 	help
- 	  This kernel feature is useful for number crunching applications
- 	  that may need to compute untrusted bytecode during their
-@@ -1189,11 +1191,11 @@ config HOTPLUG_CPU
- 	  suspend.
+ 	fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
+ 	if (fd < 0)
+ 		return fd;
+ 
+-	if (skas_needs_stub)
+-		map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
++	if (skas_needs_stub) {
++		err = map_stub_pages(fd, STUB_CODE, STUB_DATA, stack);
++		if (err) {
++			os_close_file(fd);
++			return err;
++		}
++	}
  
- config COMPAT_VDSO
--	bool "Compat VDSO support"
--	default y
--	depends on X86_32
-+	def_bool y
-+	prompt "Compat VDSO support"
-+	depends on X86_32 || IA32_EMULATION
- 	help
--	  Map the VDSO to the predictable old-style address too.
-+	  Map the 32-bit VDSO to the predictable old-style address too.
- 	---help---
- 	  Say N here if you are running a sufficiently recent glibc
- 	  version (2.3.3 or later), to remove the high-mapped
-@@ -1207,30 +1209,26 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
- 	def_bool y
- 	depends on X86_64 || (X86_32 && HIGHMEM)
+ 	return fd;
+ }
+@@ -49,8 +55,14 @@ int __init start_uml(void)
+ {
+ 	stack_protections((unsigned long) &cpu0_irqstack);
+ 	set_sigstack(cpu0_irqstack, THREAD_SIZE);
+-	if (proc_mm)
++	if (proc_mm) {
+ 		userspace_pid[0] = start_userspace(0);
++		if (userspace_pid[0] < 0) {
++			printf("start_uml - start_userspace returned %d\n",
++			       userspace_pid[0]);
++			exit(1);
++		}
++	}
  
--config MEMORY_HOTPLUG_RESERVE
--	def_bool X86_64
--	depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
--
- config HAVE_ARCH_EARLY_PFN_TO_NID
- 	def_bool X86_64
- 	depends on NUMA
+ 	init_new_thread_signals();
  
--config OUT_OF_LINE_PFN_TO_PAGE
--	def_bool X86_64
--	depends on DISCONTIGMEM
--
- menu "Power management options"
- 	depends on !X86_VOYAGER
+diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
+index 50b476f..4e3b820 100644
+--- a/arch/um/kernel/skas/syscall.c
++++ b/arch/um/kernel/skas/syscall.c
+@@ -9,6 +9,9 @@
+ #include "sysdep/ptrace.h"
+ #include "sysdep/syscalls.h"
  
- config ARCH_HIBERNATION_HEADER
--	bool
-+	def_bool y
- 	depends on X86_64 && HIBERNATION
--	default y
++extern int syscall_table_size;
++#define NR_syscalls (syscall_table_size / sizeof(void *))
++
+ void handle_syscall(struct uml_pt_regs *r)
+ {
+ 	struct pt_regs *regs = container_of(r, struct pt_regs, regs);
+@@ -17,9 +20,6 @@ void handle_syscall(struct uml_pt_regs *r)
  
- source "kernel/power/Kconfig"
+ 	syscall_trace(r, 0);
  
- source "drivers/acpi/Kconfig"
+-	current->thread.nsyscalls++;
+-	nsyscalls++;
+-
+ 	/*
+ 	 * This should go in the declaration of syscall, but when I do that,
+ 	 * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
+diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c
+index 1d8b119..e22c969 100644
+--- a/arch/um/kernel/skas/uaccess.c
++++ b/arch/um/kernel/skas/uaccess.c
+@@ -3,128 +3,130 @@
+  * Licensed under the GPL
+  */
  
-+config X86_APM_BOOT
-+	bool
-+	default y
-+	depends on APM || APM_MODULE
-+
- menuconfig APM
- 	tristate "APM (Advanced Power Management) BIOS support"
- 	depends on X86_32 && PM_SLEEP && !X86_VISWS
-@@ -1371,7 +1369,7 @@ menu "Bus options (PCI etc.)"
- config PCI
- 	bool "PCI support" if !X86_VISWS
- 	depends on !X86_VOYAGER
--	default y if X86_VISWS
-+	default y
- 	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
- 	help
- 	  Find out whether you have a PCI motherboard. PCI is the name of a
-@@ -1379,11 +1377,6 @@ config PCI
- 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
- 	  VESA. If you have PCI, say Y, otherwise N.
+-#include "linux/err.h"
+-#include "linux/highmem.h"
+-#include "linux/mm.h"
+-#include "asm/current.h"
+-#include "asm/page.h"
+-#include "asm/pgtable.h"
++#include <linux/err.h>
++#include <linux/highmem.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <asm/current.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
+ #include "kern_util.h"
+ #include "os.h"
  
--	  The PCI-HOWTO, available from
--	  <http://www.tldp.org/docs.html#howto>, contains valuable
--	  information about which PCI hardware does work under Linux and which
--	  doesn't.
+-extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
+-			     pte_t *pte_out);
 -
- choice
- 	prompt "PCI access mode"
- 	depends on X86_32 && PCI && !X86_VISWS
-@@ -1418,25 +1411,21 @@ config PCI_GOANY
- endchoice
+-static unsigned long maybe_map(unsigned long virt, int is_write)
++pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr)
+ {
+-	pte_t pte;
+-	int err;
++	pgd_t *pgd;
++	pud_t *pud;
++	pmd_t *pmd;
++
++	if (mm == NULL)
++		return NULL;
++
++	pgd = pgd_offset(mm, addr);
++	if (!pgd_present(*pgd))
++		return NULL;
++
++	pud = pud_offset(pgd, addr);
++	if (!pud_present(*pud))
++		return NULL;
  
- config PCI_BIOS
--	bool
-+	def_bool y
- 	depends on X86_32 && !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
--	default y
+-	void *phys = um_virt_to_phys(current, virt, &pte);
+-	int dummy_code;
++	pmd = pmd_offset(pud, addr);
++	if (!pmd_present(*pmd))
++		return NULL;
++
++	return pte_offset_kernel(pmd, addr);
++}
++
++static pte_t *maybe_map(unsigned long virt, int is_write)
++{
++	pte_t *pte = virt_to_pte(current->mm, virt);
++	int err, dummy_code;
  
- # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
- config PCI_DIRECT
--	bool
-+	def_bool y
- 	depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
--	default y
+-	if (IS_ERR(phys) || (is_write && !pte_write(pte))) {
++	if ((pte == NULL) || !pte_present(*pte) ||
++	    (is_write && !pte_write(*pte))) {
+ 		err = handle_page_fault(virt, 0, is_write, 1, &dummy_code);
+ 		if (err)
+-			return -1UL;
+-		phys = um_virt_to_phys(current, virt, NULL);
++			return NULL;
++		pte = virt_to_pte(current->mm, virt);
+ 	}
+-	if (IS_ERR(phys))
+-		phys = (void *) -1;
++	if (!pte_present(*pte))
++		pte = NULL;
  
- config PCI_MMCONFIG
--	bool
-+	def_bool y
- 	depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
--	default y
+-	return (unsigned long) phys;
++	return pte;
+ }
  
- config PCI_DOMAINS
--	bool
-+	def_bool y
- 	depends on PCI
--	default y
+ static int do_op_one_page(unsigned long addr, int len, int is_write,
+ 		 int (*op)(unsigned long addr, int len, void *arg), void *arg)
+ {
++	jmp_buf buf;
+ 	struct page *page;
+-	int n;
++	pte_t *pte;
++	int n, faulted;
  
- config PCI_MMCONFIG
- 	bool "Support mmconfig PCI config space access"
-@@ -1453,9 +1442,9 @@ config DMAR
- 	  remapping devices.
+-	addr = maybe_map(addr, is_write);
+-	if (addr == -1UL)
++	pte = maybe_map(addr, is_write);
++	if (pte == NULL)
+ 		return -1;
  
- config DMAR_GFX_WA
--	bool "Support for Graphics workaround"
-+	def_bool y
-+	prompt "Support for Graphics workaround"
- 	depends on DMAR
--	default y
- 	help
- 	 Current Graphics drivers tend to use physical address
- 	 for DMA and avoid using DMA APIs. Setting this config
-@@ -1464,9 +1453,8 @@ config DMAR_GFX_WA
- 	 to use physical addresses for DMA.
+-	page = phys_to_page(addr);
++	page = pte_page(*pte);
+ 	addr = (unsigned long) kmap_atomic(page, KM_UML_USERCOPY) +
+ 		(addr & ~PAGE_MASK);
+ 
+-	n = (*op)(addr, len, arg);
++	current->thread.fault_catcher = &buf;
++
++	faulted = UML_SETJMP(&buf);
++	if (faulted == 0)
++		n = (*op)(addr, len, arg);
++	else
++		n = -1;
++
++	current->thread.fault_catcher = NULL;
  
- config DMAR_FLOPPY_WA
--	bool
-+	def_bool y
- 	depends on DMAR
--	default y
- 	help
- 	 Floppy disk drivers are know to bypass DMA API calls
- 	 thereby failing to work when IOMMU is enabled. This
-@@ -1479,8 +1467,7 @@ source "drivers/pci/Kconfig"
+ 	kunmap_atomic(page, KM_UML_USERCOPY);
  
- # x86_64 have no ISA slots, but do have ISA-style DMA.
- config ISA_DMA_API
--	bool
--	default y
-+	def_bool y
+ 	return n;
+ }
  
- if X86_32
+-static void do_buffer_op(void *jmpbuf, void *arg_ptr)
++static int buffer_op(unsigned long addr, int len, int is_write,
++		     int (*op)(unsigned long, int, void *), void *arg)
+ {
+-	va_list args;
+-	unsigned long addr;
+-	int len, is_write, size, remain, n;
+-	int (*op)(unsigned long, int, void *);
+-	void *arg;
+-	int *res;
+-
+-	va_copy(args, *(va_list *)arg_ptr);
+-	addr = va_arg(args, unsigned long);
+-	len = va_arg(args, int);
+-	is_write = va_arg(args, int);
+-	op = va_arg(args, void *);
+-	arg = va_arg(args, void *);
+-	res = va_arg(args, int *);
+-	va_end(args);
++	int size, remain, n;
++
+ 	size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len);
+ 	remain = len;
  
-@@ -1546,9 +1533,9 @@ config SCx200HR_TIMER
- 	  other workaround is idle=poll boot option.
+-	current->thread.fault_catcher = jmpbuf;
+ 	n = do_op_one_page(addr, size, is_write, op, arg);
+ 	if (n != 0) {
+-		*res = (n < 0 ? remain : 0);
++		remain = (n < 0 ? remain : 0);
+ 		goto out;
+ 	}
  
- config GEODE_MFGPT_TIMER
--	bool "Geode Multi-Function General Purpose Timer (MFGPT) events"
-+	def_bool y
-+	prompt "Geode Multi-Function General Purpose Timer (MFGPT) events"
- 	depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS
--	default y
- 	help
- 	  This driver provides a clock event source based on the MFGPT
- 	  timer(s) in the CS5535 and CS5536 companion chip for the geode.
-@@ -1575,6 +1562,7 @@ source "fs/Kconfig.binfmt"
- config IA32_EMULATION
- 	bool "IA32 Emulation"
- 	depends on X86_64
-+	select COMPAT_BINFMT_ELF
- 	help
- 	  Include code to run 32-bit programs under a 64-bit kernel. You should
- 	  likely turn this on, unless you're 100% sure that you don't have any
-@@ -1587,18 +1575,16 @@ config IA32_AOUT
-          Support old a.out binaries in the 32bit emulation.
+ 	addr += size;
+ 	remain -= size;
+-	if (remain == 0) {
+-		*res = 0;
++	if (remain == 0)
+ 		goto out;
+-	}
  
- config COMPAT
--	bool
-+	def_bool y
- 	depends on IA32_EMULATION
--	default y
+-	while(addr < ((addr + remain) & PAGE_MASK)) {
++	while (addr < ((addr + remain) & PAGE_MASK)) {
+ 		n = do_op_one_page(addr, PAGE_SIZE, is_write, op, arg);
+ 		if (n != 0) {
+-			*res = (n < 0 ? remain : 0);
++			remain = (n < 0 ? remain : 0);
+ 			goto out;
+ 		}
  
- config COMPAT_FOR_U64_ALIGNMENT
- 	def_bool COMPAT
- 	depends on X86_64
+ 		addr += PAGE_SIZE;
+ 		remain -= PAGE_SIZE;
+ 	}
+-	if (remain == 0) {
+-		*res = 0;
++	if (remain == 0)
+ 		goto out;
+-	}
  
- config SYSVIPC_COMPAT
--	bool
-+	def_bool y
- 	depends on X86_64 && COMPAT && SYSVIPC
--	default y
+ 	n = do_op_one_page(addr, remain, is_write, op, arg);
+-	if (n != 0)
+-		*res = (n < 0 ? remain : 0);
+-	else *res = 0;
+- out:
+-	current->thread.fault_catcher = NULL;
+-}
+-
+-static int buffer_op(unsigned long addr, int len, int is_write,
+-		     int (*op)(unsigned long addr, int len, void *arg),
+-		     void *arg)
+-{
+-	int faulted, res;
+-
+-	faulted = setjmp_wrapper(do_buffer_op, addr, len, is_write, op, arg,
+-				 &res);
+-	if (!faulted)
+-		return res;
++	if (n != 0) {
++		remain = (n < 0 ? remain : 0);
++		goto out;
++	}
  
- endmenu
+-	return addr + len - (unsigned long) current->thread.fault_addr;
++	return 0;
++ out:
++	return remain;
+ }
  
-@@ -1619,4 +1605,6 @@ source "security/Kconfig"
+ static int copy_chunk_from_user(unsigned long from, int len, void *arg)
+diff --git a/arch/um/kernel/smp.c b/arch/um/kernel/smp.c
+index 36d89cf..e1062ec 100644
+--- a/arch/um/kernel/smp.c
++++ b/arch/um/kernel/smp.c
+@@ -21,7 +21,6 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+ #include "asm/smp.h"
+ #include "asm/processor.h"
+ #include "asm/spinlock.h"
+-#include "kern_util.h"
+ #include "kern.h"
+ #include "irq_user.h"
+ #include "os.h"
+@@ -61,7 +60,7 @@ void smp_send_stop(void)
+ 			continue;
+ 		os_write_file(cpu_data[i].ipi_pipe[1], "S", 1);
+ 	}
+-	printk(KERN_INFO "done\n");
++	printk(KERN_CONT "done\n");
+ }
  
- source "crypto/Kconfig"
+ static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
+@@ -75,8 +74,7 @@ static int idle_proc(void *cpup)
+ 	if (err < 0)
+ 		panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err);
  
-+source "arch/x86/kvm/Kconfig"
-+
- source "lib/Kconfig"
-diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
-index c301622..e09a6b7 100644
---- a/arch/x86/Kconfig.cpu
-+++ b/arch/x86/Kconfig.cpu
-@@ -219,10 +219,10 @@ config MGEODEGX1
- 	  Select this for a Geode GX1 (Cyrix MediaGX) chip.
+-	os_set_fd_async(cpu_data[cpu].ipi_pipe[0],
+-		     current->thread.mode.tt.extern_pid);
++	os_set_fd_async(cpu_data[cpu].ipi_pipe[0]);
  
- config MGEODE_LX
--       bool "Geode GX/LX"
-+	bool "Geode GX/LX"
- 	depends on X86_32
--       help
--         Select this for AMD Geode GX and LX processors.
-+	help
-+	  Select this for AMD Geode GX and LX processors.
+ 	wmb();
+ 	if (cpu_test_and_set(cpu, cpu_callin_map)) {
+@@ -129,8 +127,7 @@ void smp_prepare_cpus(unsigned int maxcpus)
+ 	if (err < 0)
+ 		panic("CPU#0 failed to create IPI pipe, errno = %d", -err);
  
- config MCYRIXIII
- 	bool "CyrixIII/VIA-C3"
-@@ -258,7 +258,7 @@ config MPSC
- 	  Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey
- 	  Xeon CPUs with Intel 64bit which is compatible with x86-64.
- 	  Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
--          Netburst core and shouldn't use this option. You can distinguish them
-+	  Netburst core and shouldn't use this option. You can distinguish them
- 	  using the cpu family field
- 	  in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
+-	os_set_fd_async(cpu_data[me].ipi_pipe[0],
+-		     current->thread.mode.tt.extern_pid);
++	os_set_fd_async(cpu_data[me].ipi_pipe[0]);
+ 
+ 	for (cpu = 1; cpu < ncpus; cpu++) {
+ 		printk(KERN_INFO "Booting processor %d...\n", cpu);
+@@ -143,9 +140,8 @@ void smp_prepare_cpus(unsigned int maxcpus)
+ 		while (waittime-- && !cpu_isset(cpu, cpu_callin_map))
+ 			cpu_relax();
  
-@@ -317,81 +317,75 @@ config X86_L1_CACHE_SHIFT
- 	default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7
+-		if (cpu_isset(cpu, cpu_callin_map))
+-			printk(KERN_INFO "done\n");
+-		else printk(KERN_INFO "failed\n");
++		printk(KERN_INFO "%s\n",
++		       cpu_isset(cpu, cpu_calling_map) ? "done" : "failed");
+ 	}
+ }
  
- config X86_XADD
--	bool
-+	def_bool y
- 	depends on X86_32 && !M386
--	default y
+diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
+index b9d92b2..9cffc62 100644
+--- a/arch/um/kernel/syscall.c
++++ b/arch/um/kernel/syscall.c
+@@ -13,9 +13,6 @@
+ #include "asm/uaccess.h"
+ #include "asm/unistd.h"
  
- config X86_PPRO_FENCE
--	bool
-+	bool "PentiumPro memory ordering errata workaround"
- 	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1
--	default y
-+	help
-+	  Old PentiumPro multiprocessor systems had errata that could cause memory
-+	  operations to violate the x86 ordering standard in rare cases. Enabling this
-+	  option will attempt to work around some (but not all) occurances of
-+	  this problem, at the cost of much heavier spinlock and memory barrier
-+	  operations.
-+
-+	  If unsure, say n here. Even distro kernels should think twice before enabling
-+	  this: there are few systems, and an unlikely bug.
+-/*  Unlocked, I don't care if this is a bit off */
+-int nsyscalls = 0;
+-
+ long sys_fork(void)
+ {
+ 	long ret;
+diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
+index 9326357..56d43d0 100644
+--- a/arch/um/kernel/sysrq.c
++++ b/arch/um/kernel/sysrq.c
+@@ -1,38 +1,37 @@
+-/* 
+- * Copyright (C) 2001 Jeff Dike (jdike at karaya.com)
++/*
++ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
  
- config X86_F00F_BUG
--	bool
-+	def_bool y
- 	depends on M586MMX || M586TSC || M586 || M486 || M386
--	default y
+-#include "linux/sched.h"
+-#include "linux/kernel.h"
+-#include "linux/module.h"
+-#include "linux/kallsyms.h"
+-#include "asm/page.h"
+-#include "asm/processor.h"
++#include <linux/kallsyms.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
+ #include "sysrq.h"
  
- config X86_WP_WORKS_OK
--	bool
-+	def_bool y
- 	depends on X86_32 && !M386
--	default y
+ /* Catch non-i386 SUBARCH's. */
+ #if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
+ void show_trace(struct task_struct *task, unsigned long * stack)
+ {
+-        unsigned long addr;
++	unsigned long addr;
  
- config X86_INVLPG
--	bool
-+	def_bool y
- 	depends on X86_32 && !M386
--	default y
+-        if (!stack) {
++	if (!stack) {
+ 		stack = (unsigned long*) &stack;
+ 		WARN_ON(1);
+ 	}
  
- config X86_BSWAP
--	bool
-+	def_bool y
- 	depends on X86_32 && !M386
--	default y
+-        printk("Call Trace: \n");
+-        while (((long) stack & (THREAD_SIZE-1)) != 0) {
+-                addr = *stack;
++	printk(KERN_INFO "Call Trace: \n");
++	while (((long) stack & (THREAD_SIZE-1)) != 0) {
++		addr = *stack;
+ 		if (__kernel_text_address(addr)) {
+-			printk("%08lx:  [<%08lx>]", (unsigned long) stack, addr);
+-			print_symbol(" %s", addr);
+-			printk("\n");
+-                }
+-                stack++;
+-        }
+-        printk("\n");
++			printk(KERN_INFO "%08lx:  [<%08lx>]",
++			       (unsigned long) stack, addr);
++			print_symbol(KERN_CONT " %s", addr);
++			printk(KERN_CONT "\n");
++		}
++		stack++;
++	}
++	printk(KERN_INFO "\n");
+ }
+ #endif
  
- config X86_POPAD_OK
--	bool
-+	def_bool y
- 	depends on X86_32 && !M386
--	default y
+@@ -67,14 +66,13 @@ void show_stack(struct task_struct *task, unsigned long *esp)
+ 	}
  
- config X86_ALIGNMENT_16
--	bool
-+	def_bool y
- 	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
--	default y
+ 	stack = esp;
+-	for(i = 0; i < kstack_depth_to_print; i++) {
++	for (i = 0; i < kstack_depth_to_print; i++) {
+ 		if (kstack_end(stack))
+ 			break;
+ 		if (i && ((i % 8) == 0))
+-			printk("\n       ");
++			printk("\n" KERN_INFO "       ");
+ 		printk("%08lx ", *stack++);
+ 	}
  
- config X86_GOOD_APIC
--	bool
-+	def_bool y
- 	depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64
--	default y
+-	printk("Call Trace: \n");
+ 	show_trace(task, esp);
+ }
+diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
+index 1ac746a..e066e84 100644
+--- a/arch/um/kernel/time.c
++++ b/arch/um/kernel/time.c
+@@ -3,12 +3,12 @@
+  * Licensed under the GPL
+  */
  
- config X86_INTEL_USERCOPY
--	bool
-+	def_bool y
- 	depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
--	default y
+-#include "linux/clockchips.h"
+-#include "linux/interrupt.h"
+-#include "linux/jiffies.h"
+-#include "linux/threads.h"
+-#include "asm/irq.h"
+-#include "asm/param.h"
++#include <linux/clockchips.h>
++#include <linux/interrupt.h>
++#include <linux/jiffies.h>
++#include <linux/threads.h>
++#include <asm/irq.h>
++#include <asm/param.h>
+ #include "kern_util.h"
+ #include "os.h"
  
- config X86_USE_PPRO_CHECKSUM
--	bool
-+	def_bool y
- 	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2
--	default y
+@@ -32,7 +32,7 @@ void timer_handler(int sig, struct uml_pt_regs *regs)
+ static void itimer_set_mode(enum clock_event_mode mode,
+ 			    struct clock_event_device *evt)
+ {
+-	switch(mode) {
++	switch (mode) {
+ 	case CLOCK_EVT_MODE_PERIODIC:
+ 		set_interval();
+ 		break;
+diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
+index f4a0e40..d175d05 100644
+--- a/arch/um/kernel/tlb.c
++++ b/arch/um/kernel/tlb.c
+@@ -3,9 +3,10 @@
+  * Licensed under the GPL
+  */
  
- config X86_USE_3DNOW
--	bool
-+	def_bool y
- 	depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML
--	default y
+-#include "linux/mm.h"
+-#include "asm/pgtable.h"
+-#include "asm/tlbflush.h"
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
+ #include "as-layout.h"
+ #include "mem_user.h"
+ #include "os.h"
+@@ -56,7 +57,7 @@ static int do_ops(struct host_vm_change *hvc, int end,
+ 
+ 	for (i = 0; i < end && !ret; i++) {
+ 		op = &hvc->ops[i];
+-		switch(op->type) {
++		switch (op->type) {
+ 		case MMAP:
+ 			ret = map(hvc->id, op->u.mmap.addr, op->u.mmap.len,
+ 				  op->u.mmap.prot, op->u.mmap.fd,
+@@ -183,27 +184,30 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
  
- config X86_OOSTORE
--	bool
-+	def_bool y
- 	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
--	default y
+ 	pte = pte_offset_kernel(pmd, addr);
+ 	do {
++		if ((addr >= STUB_START) && (addr < STUB_END))
++			continue;
++
+ 		r = pte_read(*pte);
+ 		w = pte_write(*pte);
+ 		x = pte_exec(*pte);
+ 		if (!pte_young(*pte)) {
+ 			r = 0;
+ 			w = 0;
+-		} else if (!pte_dirty(*pte)) {
++		} else if (!pte_dirty(*pte))
+ 			w = 0;
+-		}
++
+ 		prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
+ 			(x ? UM_PROT_EXEC : 0));
+ 		if (hvc->force || pte_newpage(*pte)) {
+ 			if (pte_present(*pte))
+ 				ret = add_mmap(addr, pte_val(*pte) & PAGE_MASK,
+ 					       PAGE_SIZE, prot, hvc);
+-			else ret = add_munmap(addr, PAGE_SIZE, hvc);
+-		}
+-		else if (pte_newprot(*pte))
++			else
++				ret = add_munmap(addr, PAGE_SIZE, hvc);
++		} else if (pte_newprot(*pte))
+ 			ret = add_mprotect(addr, PAGE_SIZE, prot, hvc);
+ 		*pte = pte_mkuptodate(*pte);
+-	} while (pte++, addr += PAGE_SIZE, ((addr != end) && !ret));
++	} while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
+ 	return ret;
+ }
  
- config X86_TSC
--	bool
-+	def_bool y
- 	depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64
--	default y
+@@ -225,7 +229,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
+ 			}
+ 		}
+ 		else ret = update_pte_range(pmd, addr, next, hvc);
+-	} while (pmd++, addr = next, ((addr != end) && !ret));
++	} while (pmd++, addr = next, ((addr < end) && !ret));
+ 	return ret;
+ }
  
- # this should be set for all -march=.. options where the compiler
- # generates cmov.
- config X86_CMOV
--	bool
-+	def_bool y
- 	depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
--	default y
+@@ -247,7 +251,7 @@ static inline int update_pud_range(pgd_t *pgd, unsigned long addr,
+ 			}
+ 		}
+ 		else ret = update_pmd_range(pud, addr, next, hvc);
+-	} while (pud++, addr = next, ((addr != end) && !ret));
++	} while (pud++, addr = next, ((addr < end) && !ret));
+ 	return ret;
+ }
  
- config X86_MINIMUM_CPU_FAMILY
- 	int
-@@ -399,3 +393,6 @@ config X86_MINIMUM_CPU_FAMILY
- 	default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK)
- 	default "3"
+@@ -270,7 +274,7 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
+ 			}
+ 		}
+ 		else ret = update_pud_range(pgd, addr, next, &hvc);
+-	} while (pgd++, addr = next, ((addr != end_addr) && !ret));
++	} while (pgd++, addr = next, ((addr < end_addr) && !ret));
  
-+config X86_DEBUGCTLMSR
-+	def_bool y
-+	depends on !(M586MMX || M586TSC || M586 || M486 || M386)
-diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
-index 761ca7b..2e1e3af 100644
---- a/arch/x86/Kconfig.debug
-+++ b/arch/x86/Kconfig.debug
-@@ -6,7 +6,7 @@ config TRACE_IRQFLAGS_SUPPORT
- source "lib/Kconfig.debug"
+ 	if (!ret)
+ 		ret = do_ops(&hvc, hvc.index, 1);
+@@ -485,9 +489,6 @@ void __flush_tlb_one(unsigned long addr)
+ static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+ 		      unsigned long end_addr, int force)
+ {
+-	if (!proc_mm && (end_addr > STUB_START))
+-		end_addr = STUB_START;
+-
+ 	fix_range_common(mm, start_addr, end_addr, force);
+ }
  
- config EARLY_PRINTK
--	bool "Early printk" if EMBEDDED && DEBUG_KERNEL && X86_32
-+	bool "Early printk" if EMBEDDED
- 	default y
- 	help
- 	  Write kernel log output directly into the VGA buffer or to a serial
-@@ -40,22 +40,49 @@ comment "Page alloc debug is incompatible with Software Suspend on i386"
+@@ -499,10 +500,9 @@ void flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ 	else fix_range(vma->vm_mm, start, end, 0);
+ }
  
- config DEBUG_PAGEALLOC
- 	bool "Debug page memory allocations"
--	depends on DEBUG_KERNEL && !HIBERNATION && !HUGETLBFS
--	depends on X86_32
-+	depends on DEBUG_KERNEL && X86_32
- 	help
- 	  Unmap pages from the kernel linear mapping after free_pages().
- 	  This results in a large slowdown, but helps to find certain types
- 	  of memory corruptions.
+-void flush_tlb_mm(struct mm_struct *mm)
++void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
++			unsigned long end)
+ {
+-	unsigned long end;
+-
+ 	/*
+ 	 * Don't bother flushing if this address space is about to be
+ 	 * destroyed.
+@@ -510,8 +510,17 @@ void flush_tlb_mm(struct mm_struct *mm)
+ 	if (atomic_read(&mm->mm_users) == 0)
+ 		return;
  
-+config DEBUG_PER_CPU_MAPS
-+	bool "Debug access to per_cpu maps"
-+	depends on DEBUG_KERNEL
-+	depends on X86_64_SMP
-+	default n
-+	help
-+	  Say Y to verify that the per_cpu map being accessed has
-+	  been setup.  Adds a fair amount of code to kernel memory
-+	  and decreases performance.
+-	end = proc_mm ? task_size : STUB_START;
+-	fix_range(mm, 0, end, 0);
++	fix_range(mm, start, end, 0);
++}
 +
-+	  Say N if unsure.
++void flush_tlb_mm(struct mm_struct *mm)
++{
++	struct vm_area_struct *vma = mm->mmap;
 +
- config DEBUG_RODATA
- 	bool "Write protect kernel read-only data structures"
-+	default y
- 	depends on DEBUG_KERNEL
- 	help
- 	  Mark the kernel read-only data as write-protected in the pagetables,
- 	  in order to catch accidental (and incorrect) writes to such const
--	  data. This option may have a slight performance impact because a
--	  portion of the kernel code won't be covered by a 2MB TLB anymore.
--	  If in doubt, say "N".
-+	  data. This is recommended so that we can catch kernel bugs sooner.
-+	  If in doubt, say "Y".
++	while (vma != NULL) {
++		fix_range(mm, vma->vm_start, vma->vm_end, 0);
++		vma = vma->vm_next;
++	}
+ }
+ 
+ void force_flush_all(void)
+diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
+index cb3321f..44e4904 100644
+--- a/arch/um/kernel/trap.c
++++ b/arch/um/kernel/trap.c
+@@ -13,6 +13,7 @@
+ #include "as-layout.h"
+ #include "kern_util.h"
+ #include "os.h"
++#include "skas.h"
+ #include "sysdep/sigcontext.h"
+ 
+ /*
+@@ -128,7 +129,19 @@ static void bad_segv(struct faultinfo fi, unsigned long ip)
+ 	force_sig_info(SIGSEGV, &si, current);
+ }
+ 
+-static void segv_handler(int sig, struct uml_pt_regs *regs)
++void fatal_sigsegv(void)
++{
++	force_sigsegv(SIGSEGV, current);
++	do_signal();
++	/*
++	 * This is to tell gcc that we're not returning - do_signal
++	 * can, in general, return, but in this case, it's not, since
++	 * we just got a fatal SIGSEGV queued.
++	 */
++	os_dump_core();
++}
 +
-+config DEBUG_RODATA_TEST
-+	bool "Testcase for the DEBUG_RODATA feature"
-+	depends on DEBUG_RODATA
-+	help
-+	  This option enables a testcase for the DEBUG_RODATA
-+	  feature as well as for the change_page_attr() infrastructure.
-+	  If in doubt, say "N"
++void segv_handler(int sig, struct uml_pt_regs *regs)
+ {
+ 	struct faultinfo * fi = UPT_FAULTINFO(regs);
+ 
+@@ -216,9 +229,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
+ 
+ void relay_signal(int sig, struct uml_pt_regs *regs)
+ {
+-	if (arch_handle_signal(sig, regs))
+-		return;
+-
+ 	if (!UPT_IS_USER(regs)) {
+ 		if (sig == SIGBUS)
+ 			printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
+@@ -226,31 +236,24 @@ void relay_signal(int sig, struct uml_pt_regs *regs)
+ 		panic("Kernel mode signal %d", sig);
+ 	}
+ 
++	arch_examine_signal(sig, regs);
 +
-+config DEBUG_NX_TEST
-+	tristate "Testcase for the NX non-executable stack feature"
-+	depends on DEBUG_KERNEL && m
-+	help
-+	  This option enables a testcase for the CPU NX capability
-+	  and the software setup of this feature.
-+	  If in doubt, say "N"
+ 	current->thread.arch.faultinfo = *UPT_FAULTINFO(regs);
+ 	force_sig(sig, current);
+ }
  
- config 4KSTACKS
- 	bool "Use 4Kb for kernel stacks instead of 8Kb"
-@@ -75,8 +102,7 @@ config X86_FIND_SMP_CONFIG
+-static void bus_handler(int sig, struct uml_pt_regs *regs)
++void bus_handler(int sig, struct uml_pt_regs *regs)
+ {
+ 	if (current->thread.fault_catcher != NULL)
+ 		UML_LONGJMP(current->thread.fault_catcher, 1);
+ 	else relay_signal(sig, regs);
+ }
  
- config X86_MPPARSE
- 	def_bool y
--	depends on X86_LOCAL_APIC && !X86_VISWS
--	depends on X86_32
-+	depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+-static void winch(int sig, struct uml_pt_regs *regs)
++void winch(int sig, struct uml_pt_regs *regs)
+ {
+ 	do_IRQ(WINCH_IRQ, regs);
+ }
  
- config DOUBLEFAULT
- 	default y
-@@ -112,4 +138,91 @@ config IOMMU_LEAK
- 	  Add a simple leak tracer to the IOMMU code. This is useful when you
- 	  are debugging a buggy device driver that leaks IOMMU mappings.
+-const struct kern_handlers handlinfo_kern = {
+-	.relay_signal = relay_signal,
+-	.winch = winch,
+-	.bus_handler = bus_handler,
+-	.page_fault = segv_handler,
+-	.sigio_handler = sigio_handler,
+-	.timer_handler = timer_handler
+-};
+-
+ void trap_init(void)
+ {
+ }
+diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c
+index d7436aa..f0f4b04 100644
+--- a/arch/um/kernel/uaccess.c
++++ b/arch/um/kernel/uaccess.c
+@@ -1,10 +1,11 @@
+ /*
+  * Copyright (C) 2001 Chris Emerson (cemerson at chiark.greenend.org.uk)
+- * Copyright (C) 2001, 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
  
-+#
-+# IO delay types:
-+#
-+
-+config IO_DELAY_TYPE_0X80
-+	int
-+	default "0"
-+
-+config IO_DELAY_TYPE_0XED
-+	int
-+	default "1"
-+
-+config IO_DELAY_TYPE_UDELAY
-+	int
-+	default "2"
-+
-+config IO_DELAY_TYPE_NONE
-+	int
-+	default "3"
-+
-+choice
-+	prompt "IO delay type"
-+	default IO_DELAY_0XED
-+
-+config IO_DELAY_0X80
-+	bool "port 0x80 based port-IO delay [recommended]"
-+	help
-+	  This is the traditional Linux IO delay used for in/out_p.
-+	  It is the most tested hence safest selection here.
-+
-+config IO_DELAY_0XED
-+	bool "port 0xed based port-IO delay"
-+	help
-+	  Use port 0xed as the IO delay. This frees up port 0x80 which is
-+	  often used as a hardware-debug port.
-+
-+config IO_DELAY_UDELAY
-+	bool "udelay based port-IO delay"
-+	help
-+	  Use udelay(2) as the IO delay method. This provides the delay
-+	  while not having any side-effect on the IO port space.
-+
-+config IO_DELAY_NONE
-+	bool "no port-IO delay"
-+	help
-+	  No port-IO delay. Will break on old boxes that require port-IO
-+	  delay for certain operations. Should work on most new machines.
-+
-+endchoice
-+
-+if IO_DELAY_0X80
-+config DEFAULT_IO_DELAY_TYPE
-+	int
-+	default IO_DELAY_TYPE_0X80
-+endif
-+
-+if IO_DELAY_0XED
-+config DEFAULT_IO_DELAY_TYPE
-+	int
-+	default IO_DELAY_TYPE_0XED
-+endif
-+
-+if IO_DELAY_UDELAY
-+config DEFAULT_IO_DELAY_TYPE
-+	int
-+	default IO_DELAY_TYPE_UDELAY
-+endif
-+
-+if IO_DELAY_NONE
-+config DEFAULT_IO_DELAY_TYPE
-+	int
-+	default IO_DELAY_TYPE_NONE
-+endif
-+
-+config DEBUG_BOOT_PARAMS
-+	bool "Debug boot parameters"
-+	depends on DEBUG_KERNEL
-+	depends on DEBUG_FS
-+	help
-+	  This option will cause struct boot_params to be exported via debugfs.
-+
-+config CPA_DEBUG
-+	bool "CPA self test code"
-+	depends on DEBUG_KERNEL
-+	help
-+	  Do change_page_attr self tests at boot.
-+
- endmenu
-diff --git a/arch/x86/Makefile b/arch/x86/Makefile
-index 7aa1dc6..8978e98 100644
---- a/arch/x86/Makefile
-+++ b/arch/x86/Makefile
-@@ -7,13 +7,254 @@ else
-         KBUILD_DEFCONFIG := $(ARCH)_defconfig
- endif
+-/* These are here rather than tt/uaccess.c because skas mode needs them in
++/*
++ * These are here rather than tt/uaccess.c because skas mode needs them in
+  * order to do SIGBUS recovery when a tmpfs mount runs out of room.
+  */
  
--# No need to remake these files
--$(srctree)/arch/x86/Makefile%: ;
-+core-$(CONFIG_KVM) += arch/x86/kvm/
-+
-+# BITS is used as extension for files which are available in a 32 bit
-+# and a 64 bit version to simplify shared Makefiles.
-+# e.g.: obj-y += foo_$(BITS).o
-+export BITS
+@@ -25,6 +26,8 @@ int __do_copy_to_user(void *to, const void *from, int n,
  
- ifeq ($(CONFIG_X86_32),y)
-+        BITS := 32
-         UTS_MACHINE := i386
--        include $(srctree)/arch/x86/Makefile_32
-+        CHECKFLAGS += -D__i386__
-+
-+        biarch := $(call cc-option,-m32)
-+        KBUILD_AFLAGS += $(biarch)
-+        KBUILD_CFLAGS += $(biarch)
-+
-+        ifdef CONFIG_RELOCATABLE
-+                LDFLAGS_vmlinux := --emit-relocs
-+        endif
-+
-+        KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return
-+
-+        # prevent gcc from keeping the stack 16 byte aligned
-+        KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
-+
-+        # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
-+        # a lot more stack due to the lack of sharing of stacklots:
-+        KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
-+                echo $(call cc-option,-fno-unit-at-a-time); fi ;)
-+
-+        # CPU-specific tuning. Anything which can be shared with UML should go here.
-+        include $(srctree)/arch/x86/Makefile_32.cpu
-+        KBUILD_CFLAGS += $(cflags-y)
-+
-+        # temporary until string.h is fixed
-+        KBUILD_CFLAGS += -ffreestanding
- else
-+        BITS := 64
-         UTS_MACHINE := x86_64
--        include $(srctree)/arch/x86/Makefile_64
-+        CHECKFLAGS += -D__x86_64__ -m64
-+
-+        KBUILD_AFLAGS += -m64
-+        KBUILD_CFLAGS += -m64
-+
-+        # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
-+        cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
-+        cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
-+
-+        cflags-$(CONFIG_MCORE2) += \
-+                $(call cc-option,-march=core2,$(call cc-option,-mtune=generic))
-+        cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
-+        KBUILD_CFLAGS += $(cflags-y)
-+
-+        KBUILD_CFLAGS += -mno-red-zone
-+        KBUILD_CFLAGS += -mcmodel=kernel
-+
-+        # -funit-at-a-time shrinks the kernel .text considerably
-+        # unfortunately it makes reading oopses harder.
-+        KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
-+
-+        # this works around some issues with generating unwind tables in older gccs
-+        # newer gccs do it by default
-+        KBUILD_CFLAGS += -maccumulate-outgoing-args
-+
-+        stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh
-+        stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \
-+                "$(CC)" -fstack-protector )
-+        stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \
-+                "$(CC)" -fstack-protector-all )
-+
-+        KBUILD_CFLAGS += $(stackp-y)
- endif
-+
-+# Stackpointer is addressed different for 32 bit and 64 bit x86
-+sp-$(CONFIG_X86_32) := esp
-+sp-$(CONFIG_X86_64) := rsp
-+
-+# do binutils support CFI?
-+cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_endproc,-DCONFIG_AS_CFI=1)
-+# is .cfi_signal_frame supported too?
-+cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
-+KBUILD_AFLAGS += $(cfi) $(cfi-sigframe)
-+KBUILD_CFLAGS += $(cfi) $(cfi-sigframe)
-+
-+LDFLAGS := -m elf_$(UTS_MACHINE)
-+OBJCOPYFLAGS := -O binary -R .note -R .comment -S
-+
-+# Speed up the build
-+KBUILD_CFLAGS += -pipe
-+# Workaround for a gcc prelease that unfortunately was shipped in a suse release
-+KBUILD_CFLAGS += -Wno-sign-compare
-+#
-+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
-+# prevent gcc from generating any FP code by mistake
-+KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
-+
-+###
-+# Sub architecture support
-+# fcore-y is linked before mcore-y files.
-+
-+# Default subarch .c files
-+mcore-y  := arch/x86/mach-default/
-+
-+# Voyager subarch support
-+mflags-$(CONFIG_X86_VOYAGER)	:= -Iinclude/asm-x86/mach-voyager
-+mcore-$(CONFIG_X86_VOYAGER)	:= arch/x86/mach-voyager/
-+
-+# VISWS subarch support
-+mflags-$(CONFIG_X86_VISWS)	:= -Iinclude/asm-x86/mach-visws
-+mcore-$(CONFIG_X86_VISWS)	:= arch/x86/mach-visws/
-+
-+# NUMAQ subarch support
-+mflags-$(CONFIG_X86_NUMAQ)	:= -Iinclude/asm-x86/mach-numaq
-+mcore-$(CONFIG_X86_NUMAQ)	:= arch/x86/mach-default/
-+
-+# BIGSMP subarch support
-+mflags-$(CONFIG_X86_BIGSMP)	:= -Iinclude/asm-x86/mach-bigsmp
-+mcore-$(CONFIG_X86_BIGSMP)	:= arch/x86/mach-default/
-+
-+#Summit subarch support
-+mflags-$(CONFIG_X86_SUMMIT)	:= -Iinclude/asm-x86/mach-summit
-+mcore-$(CONFIG_X86_SUMMIT)	:= arch/x86/mach-default/
-+
-+# generic subarchitecture
-+mflags-$(CONFIG_X86_GENERICARCH):= -Iinclude/asm-x86/mach-generic
-+fcore-$(CONFIG_X86_GENERICARCH)	+= arch/x86/mach-generic/
-+mcore-$(CONFIG_X86_GENERICARCH)	:= arch/x86/mach-default/
-+
-+
-+# ES7000 subarch support
-+mflags-$(CONFIG_X86_ES7000)	:= -Iinclude/asm-x86/mach-es7000
-+fcore-$(CONFIG_X86_ES7000)	:= arch/x86/mach-es7000/
-+mcore-$(CONFIG_X86_ES7000)	:= arch/x86/mach-default/
-+
-+# RDC R-321x subarch support
-+mflags-$(CONFIG_X86_RDC321X)	:= -Iinclude/asm-x86/mach-rdc321x
-+mcore-$(CONFIG_X86_RDC321X)	:= arch/x86/mach-default/
-+core-$(CONFIG_X86_RDC321X)	+= arch/x86/mach-rdc321x/
-+
-+# default subarch .h files
-+mflags-y += -Iinclude/asm-x86/mach-default
-+
-+# 64 bit does not support subarch support - clear sub arch variables
-+fcore-$(CONFIG_X86_64)  :=
-+mcore-$(CONFIG_X86_64)  :=
-+mflags-$(CONFIG_X86_64) :=
-+
-+KBUILD_CFLAGS += $(mflags-y)
-+KBUILD_AFLAGS += $(mflags-y)
-+
-+###
-+# Kernel objects
-+
-+head-y                := arch/x86/kernel/head_$(BITS).o
-+head-$(CONFIG_X86_64) += arch/x86/kernel/head64.o
-+head-y                += arch/x86/kernel/init_task.o
-+
-+libs-y  += arch/x86/lib/
-+
-+# Sub architecture files that needs linking first
-+core-y += $(fcore-y)
-+
-+# Xen paravirtualization support
-+core-$(CONFIG_XEN) += arch/x86/xen/
-+
-+# lguest paravirtualization support
-+core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/
-+
-+core-y += arch/x86/kernel/
-+core-y += arch/x86/mm/
-+
-+# Remaining sub architecture files
-+core-y += $(mcore-y)
-+
-+core-y += arch/x86/crypto/
-+core-y += arch/x86/vdso/
-+core-$(CONFIG_IA32_EMULATION) += arch/x86/ia32/
-+
-+# drivers-y are linked after core-y
-+drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
-+drivers-$(CONFIG_PCI)            += arch/x86/pci/
-+
-+# must be linked after kernel/
-+drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/
-+
-+ifeq ($(CONFIG_X86_32),y)
-+drivers-$(CONFIG_PM) += arch/x86/power/
-+drivers-$(CONFIG_FB) += arch/x86/video/
-+endif
-+
-+####
-+# boot loader support. Several targets are kept for legacy purposes
-+
-+boot := arch/x86/boot
-+
-+PHONY += zImage bzImage compressed zlilo bzlilo \
-+         zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
-+
-+# Default kernel to build
-+all: bzImage
-+
-+# KBUILD_IMAGE specify target image being built
-+                    KBUILD_IMAGE := $(boot)/bzImage
-+zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage
-+
-+zImage bzImage: vmlinux
-+	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
-+	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
-+	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/bzImage
-+
-+compressed: zImage
-+
-+zlilo bzlilo: vmlinux
-+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo
-+
-+zdisk bzdisk: vmlinux
-+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
-+
-+fdimage fdimage144 fdimage288 isoimage: vmlinux
-+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
-+
-+install: vdso_install
-+	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
-+
-+PHONY += vdso_install
-+vdso_install:
-+	$(Q)$(MAKE) $(build)=arch/x86/vdso $@
-+
-+archclean:
-+	$(Q)rm -rf $(objtree)/arch/i386
-+	$(Q)rm -rf $(objtree)/arch/x86_64
-+	$(Q)$(MAKE) $(clean)=$(boot)
+ 	fault = __do_user_copy(to, from, n, fault_addr, fault_catcher,
+ 			       __do_copy, &faulted);
+-	if(!faulted) return(0);
+-	else return(n - (fault - (unsigned long) to));
++	if (!faulted)
++		return 0;
++	else
++		return n - (fault - (unsigned long) to);
+ }
+diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
+index f1c7139..468aba9 100644
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -3,22 +3,23 @@
+  * Licensed under the GPL
+  */
+ 
+-#include "linux/delay.h"
+-#include "linux/mm.h"
+-#include "linux/module.h"
+-#include "linux/seq_file.h"
+-#include "linux/string.h"
+-#include "linux/utsname.h"
+-#include "asm/pgtable.h"
+-#include "asm/processor.h"
+-#include "asm/setup.h"
+-#include "arch.h"
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/seq_file.h>
++#include <linux/string.h>
++#include <linux/utsname.h>
++#include <asm/pgtable.h>
++#include <asm/processor.h>
++#include <asm/setup.h>
+ #include "as-layout.h"
++#include "arch.h"
+ #include "init.h"
+ #include "kern.h"
++#include "kern_util.h"
+ #include "mem_user.h"
+ #include "os.h"
+-#include "skas.h"
+ 
+ #define DEFAULT_COMMAND_LINE "root=98:0"
+ 
+@@ -100,8 +101,6 @@ const struct seq_operations cpuinfo_op = {
+ };
+ 
+ /* Set in linux_main */
+-unsigned long host_task_size;
+-unsigned long task_size;
+ unsigned long uml_physmem;
+ unsigned long uml_reserved; /* Also modified in mem_init */
+ unsigned long start_vm;
+@@ -197,20 +196,19 @@ __uml_setup("--help", Usage,
+ "    Prints this message.\n\n"
+ );
+ 
+-static int __init uml_checksetup(char *line, int *add)
++static void __init uml_checksetup(char *line, int *add)
+ {
+ 	struct uml_param *p;
+ 
+ 	p = &__uml_setup_start;
+-	while(p < &__uml_setup_end) {
++	while (p < &__uml_setup_end) {
+ 		int n;
+ 
+ 		n = strlen(p->str);
+ 		if (!strncmp(line, p->str, n) && p->setup_func(line + n, add))
+-			return 1;
++			return;
+ 		p++;
+ 	}
+-	return 0;
+ }
+ 
+ static void __init uml_postsetup(void)
+@@ -218,13 +216,30 @@ static void __init uml_postsetup(void)
+ 	initcall_t *p;
+ 
+ 	p = &__uml_postsetup_start;
+-	while(p < &__uml_postsetup_end) {
++	while (p < &__uml_postsetup_end) {
+ 		(*p)();
+ 		p++;
+ 	}
+ 	return;
+ }
+ 
++static int panic_exit(struct notifier_block *self, unsigned long unused1,
++		      void *unused2)
++{
++	bust_spinlocks(1);
++	show_regs(&(current->thread.regs));
++	bust_spinlocks(0);
++	uml_exitcode = 1;
++	os_dump_core();
++	return 0;
++}
 +
-+define archhelp
-+  echo  '* bzImage      - Compressed kernel image (arch/x86/boot/bzImage)'
-+  echo  '  install      - Install kernel using'
-+  echo  '                  (your) ~/bin/installkernel or'
-+  echo  '                  (distribution) /sbin/installkernel or'
-+  echo  '                  install to $$(INSTALL_PATH) and run lilo'
-+  echo  '  fdimage      - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)'
-+  echo  '  fdimage144   - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)'
-+  echo  '  fdimage288   - Create 2.8MB boot floppy image (arch/x86/boot/fdimage)'
-+  echo  '  isoimage     - Create a boot CD-ROM image (arch/x86/boot/image.iso)'
-+  echo  '                  bzdisk/fdimage*/isoimage also accept:'
-+  echo  '                  FDARGS="..."  arguments for the booted kernel'
-+  echo  '                  FDINITRD=file initrd for the booted kernel'
-+endef
++static struct notifier_block panic_exit_notifier = {
++	.notifier_call 		= panic_exit,
++	.next 			= NULL,
++	.priority 		= 0
++};
 +
-+CLEAN_FILES += arch/x86/boot/fdimage \
-+	       arch/x86/boot/image.iso \
-+	       arch/x86/boot/mtools.conf
-diff --git a/arch/x86/Makefile_32 b/arch/x86/Makefile_32
-deleted file mode 100644
-index 50394da..0000000
---- a/arch/x86/Makefile_32
-+++ /dev/null
-@@ -1,175 +0,0 @@
--#
--# i386 Makefile
--#
--# This file is included by the global makefile so that you can add your own
--# architecture-specific flags and dependencies. Remember to do have actions
--# for "archclean" cleaning up for this architecture.
--#
--# 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) 1994 by Linus Torvalds
--#
--# 19990713  Artur Skawina <skawina at geocities.com>
--#           Added '-march' and '-mpreferred-stack-boundary' support
--#
--# 20050320  Kianusch Sayah Karadji <kianusch at sk-tech.net>
--#           Added support for GEODE CPU
--
--# BITS is used as extension for files which are available in a 32 bit
--# and a 64 bit version to simplify shared Makefiles.
--# e.g.: obj-y += foo_$(BITS).o
--BITS := 32
--export BITS
--
--HAS_BIARCH      := $(call cc-option-yn, -m32)
--ifeq ($(HAS_BIARCH),y)
--AS              := $(AS) --32
--LD              := $(LD) -m elf_i386
--CC              := $(CC) -m32
--endif
--
--LDFLAGS		:= -m elf_i386
--OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
--ifdef CONFIG_RELOCATABLE
--LDFLAGS_vmlinux := --emit-relocs
--endif
--CHECKFLAGS	+= -D__i386__
--
--KBUILD_CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return
--
--# prevent gcc from keeping the stack 16 byte aligned
--KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
--
--# CPU-specific tuning. Anything which can be shared with UML should go here.
--include $(srctree)/arch/x86/Makefile_32.cpu
--
--# temporary until string.h is fixed
--cflags-y += -ffreestanding
--
--# this works around some issues with generating unwind tables in older gccs
--# newer gccs do it by default
--cflags-y += -maccumulate-outgoing-args
--
--# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
--# a lot more stack due to the lack of sharing of stacklots:
--KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
--
--# do binutils support CFI?
--cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
--KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
--
--# is .cfi_signal_frame supported too?
--cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
--KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
--
--KBUILD_CFLAGS += $(cflags-y)
--
--# Default subarch .c files
--mcore-y  := arch/x86/mach-default
--
--# Voyager subarch support
--mflags-$(CONFIG_X86_VOYAGER)	:= -Iinclude/asm-x86/mach-voyager
--mcore-$(CONFIG_X86_VOYAGER)	:= arch/x86/mach-voyager
--
--# VISWS subarch support
--mflags-$(CONFIG_X86_VISWS)	:= -Iinclude/asm-x86/mach-visws
--mcore-$(CONFIG_X86_VISWS)	:= arch/x86/mach-visws
--
--# NUMAQ subarch support
--mflags-$(CONFIG_X86_NUMAQ)	:= -Iinclude/asm-x86/mach-numaq
--mcore-$(CONFIG_X86_NUMAQ)	:= arch/x86/mach-default
--
--# BIGSMP subarch support
--mflags-$(CONFIG_X86_BIGSMP)	:= -Iinclude/asm-x86/mach-bigsmp
--mcore-$(CONFIG_X86_BIGSMP)	:= arch/x86/mach-default
--
--#Summit subarch support
--mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-x86/mach-summit
--mcore-$(CONFIG_X86_SUMMIT)  := arch/x86/mach-default
--
--# generic subarchitecture
--mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-x86/mach-generic
--mcore-$(CONFIG_X86_GENERICARCH) := arch/x86/mach-default
--core-$(CONFIG_X86_GENERICARCH) += arch/x86/mach-generic/
--
--# ES7000 subarch support
--mflags-$(CONFIG_X86_ES7000)	:= -Iinclude/asm-x86/mach-es7000
--mcore-$(CONFIG_X86_ES7000)	:= arch/x86/mach-default
--core-$(CONFIG_X86_ES7000)	:= arch/x86/mach-es7000/
--
--# Xen paravirtualization support
--core-$(CONFIG_XEN)		+= arch/x86/xen/
--
--# lguest paravirtualization support
--core-$(CONFIG_LGUEST_GUEST)	+= arch/x86/lguest/
--
--# default subarch .h files
--mflags-y += -Iinclude/asm-x86/mach-default
--
--head-y := arch/x86/kernel/head_32.o arch/x86/kernel/init_task.o
--
--libs-y 					+= arch/x86/lib/
--core-y					+= arch/x86/kernel/ \
--					   arch/x86/mm/ \
--					   $(mcore-y)/ \
--					   arch/x86/crypto/
--drivers-$(CONFIG_MATH_EMULATION)	+= arch/x86/math-emu/
--drivers-$(CONFIG_PCI)			+= arch/x86/pci/
--# must be linked after kernel/
--drivers-$(CONFIG_OPROFILE)		+= arch/x86/oprofile/
--drivers-$(CONFIG_PM)			+= arch/x86/power/
--drivers-$(CONFIG_FB)                    += arch/x86/video/
--
--KBUILD_CFLAGS += $(mflags-y)
--KBUILD_AFLAGS += $(mflags-y)
--
--boot := arch/x86/boot
--
--PHONY += zImage bzImage compressed zlilo bzlilo \
--         zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
--
--all: bzImage
--
--# KBUILD_IMAGE specify target image being built
--                    KBUILD_IMAGE := $(boot)/bzImage
--zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage
--
--zImage bzImage: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
--	$(Q)mkdir -p $(objtree)/arch/i386/boot
--	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/i386/boot/bzImage
--
--compressed: zImage
--
--zlilo bzlilo: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo
--
--zdisk bzdisk: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
--
--fdimage fdimage144 fdimage288 isoimage: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
--
--install:
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
--
--archclean:
--	$(Q)rm -rf $(objtree)/arch/i386/boot
--	$(Q)$(MAKE) $(clean)=arch/x86/boot
--
--define archhelp
--  echo  '* bzImage	- Compressed kernel image (arch/x86/boot/bzImage)'
--  echo  '  install	- Install kernel using'
--  echo  '		   (your) ~/bin/installkernel or'
--  echo  '		   (distribution) /sbin/installkernel or'
--  echo  '		   install to $$(INSTALL_PATH) and run lilo'
--  echo  '  bzdisk       - Create a boot floppy in /dev/fd0'
--  echo  '  fdimage      - Create a boot floppy image'
--  echo  '  isoimage     - Create a boot CD-ROM image'
--endef
--
--CLEAN_FILES += arch/x86/boot/fdimage \
--	       arch/x86/boot/image.iso \
--	       arch/x86/boot/mtools.conf
-diff --git a/arch/x86/Makefile_64 b/arch/x86/Makefile_64
-deleted file mode 100644
-index a804860..0000000
---- a/arch/x86/Makefile_64
-+++ /dev/null
-@@ -1,144 +0,0 @@
--#
--# x86_64 Makefile
--#
--# This file is included by the global makefile so that you can add your own
--# architecture-specific flags and dependencies. Remember to do have actions
--# for "archclean" and "archdep" for cleaning up and making dependencies for
--# this architecture
--#
--# 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) 1994 by Linus Torvalds
--#
--# 19990713  Artur Skawina <skawina at geocities.com>
--#           Added '-march' and '-mpreferred-stack-boundary' support
--# 20000913  Pavel Machek <pavel at suse.cz>
--#	    Converted for x86_64 architecture
--# 20010105  Andi Kleen, add IA32 compiler.
--#           ....and later removed it again....
--#
--# $Id: Makefile,v 1.31 2002/03/22 15:56:07 ak Exp $
--
--# BITS is used as extension for files which are available in a 32 bit
--# and a 64 bit version to simplify shared Makefiles.
--# e.g.: obj-y += foo_$(BITS).o
--BITS := 64
--export BITS
--
--LDFLAGS		:= -m elf_x86_64
--OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
--LDFLAGS_vmlinux :=
--CHECKFLAGS      += -D__x86_64__ -m64
--
--cflags-y	:=
--cflags-kernel-y	:=
--cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
--cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
--# gcc doesn't support -march=core2 yet as of gcc 4.3, but I hope it
--# will eventually. Use -mtune=generic as fallback
--cflags-$(CONFIG_MCORE2) += \
--	$(call cc-option,-march=core2,$(call cc-option,-mtune=generic))
--cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
--
--cflags-y += -m64
--cflags-y += -mno-red-zone
--cflags-y += -mcmodel=kernel
--cflags-y += -pipe
--cflags-y += -Wno-sign-compare
--cflags-y += -fno-asynchronous-unwind-tables
--ifneq ($(CONFIG_DEBUG_INFO),y)
--# -fweb shrinks the kernel a bit, but the difference is very small
--# it also messes up debugging, so don't use it for now.
--#cflags-y += $(call cc-option,-fweb)
--endif
--# -funit-at-a-time shrinks the kernel .text considerably
--# unfortunately it makes reading oopses harder.
--cflags-y += $(call cc-option,-funit-at-a-time)
--# prevent gcc from generating any FP code by mistake
--cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
--# this works around some issues with generating unwind tables in older gccs
--# newer gccs do it by default
--cflags-y += -maccumulate-outgoing-args
--
--# do binutils support CFI?
--cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
--KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
--
--# is .cfi_signal_frame supported too?
--cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
--KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
--
--cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector )
--cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector-all )
--
--KBUILD_CFLAGS += $(cflags-y)
--CFLAGS_KERNEL += $(cflags-kernel-y)
--KBUILD_AFLAGS += -m64
--
--head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task.o
--
--libs-y 					+= arch/x86/lib/
--core-y					+= arch/x86/kernel/ \
--					   arch/x86/mm/ \
--					   arch/x86/crypto/ \
--					   arch/x86/vdso/
--core-$(CONFIG_IA32_EMULATION)		+= arch/x86/ia32/
--drivers-$(CONFIG_PCI)			+= arch/x86/pci/
--drivers-$(CONFIG_OPROFILE)		+= arch/x86/oprofile/
--
--boot := arch/x86/boot
--
--PHONY += bzImage bzlilo install archmrproper \
--	 fdimage fdimage144 fdimage288 isoimage archclean
--
--#Default target when executing "make"
--all: bzImage
--
--BOOTIMAGE                     := arch/x86/boot/bzImage
--KBUILD_IMAGE                  := $(BOOTIMAGE)
--
--bzImage: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
--	$(Q)mkdir -p $(objtree)/arch/x86_64/boot
--	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/x86_64/boot/bzImage
--
--bzlilo: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo
--
--bzdisk: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
+ /* Set during early boot */
+ unsigned long brk_start;
+ unsigned long end_iomem;
+@@ -234,20 +249,6 @@ EXPORT_SYMBOL(end_iomem);
+ 
+ extern char __binary_start;
+ 
+-static unsigned long set_task_sizes_skas(unsigned long *task_size_out)
+-{
+-	/* Round up to the nearest 4M */
+-	unsigned long host_task_size = ROUND_4M((unsigned long)
+-						&host_task_size);
 -
--fdimage fdimage144 fdimage288 isoimage: vmlinux
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
+-	if (!skas_needs_stub)
+-		*task_size_out = host_task_size;
+-	else
+-		*task_size_out = STUB_START & PGDIR_MASK;
 -
--install: vdso_install
--	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ 
+-	return host_task_size;
+-}
 -
--vdso_install:
--ifeq ($(CONFIG_IA32_EMULATION),y)
--	$(Q)$(MAKE) $(build)=arch/x86/ia32 $@
--endif
--	$(Q)$(MAKE) $(build)=arch/x86/vdso $@
+ int __init linux_main(int argc, char **argv)
+ {
+ 	unsigned long avail, diff;
+@@ -278,13 +279,6 @@ int __init linux_main(int argc, char **argv)
+ 
+ 	printf("UML running in %s mode\n", mode);
+ 
+-	host_task_size = set_task_sizes_skas(&task_size);
 -
--archclean:
--	$(Q)rm -rf $(objtree)/arch/x86_64/boot
--	$(Q)$(MAKE) $(clean)=$(boot)
+-	/*
+-	 * Setting up handlers to 'sig_info' struct
+-	 */
+-	os_fill_handlinfo(handlinfo_kern);
 -
--define archhelp
--  echo  '* bzImage	- Compressed kernel image (arch/x86/boot/bzImage)'
--  echo  '  install	- Install kernel using'
--  echo  '		   (your) ~/bin/installkernel or'
--  echo  '		   (distribution) /sbin/installkernel or'
--  echo  '		   install to $$(INSTALL_PATH) and run lilo'
--  echo  '  bzdisk       - Create a boot floppy in /dev/fd0'
--  echo  '  fdimage      - Create a boot floppy image'
--  echo  '  isoimage     - Create a boot CD-ROM image'
--endef
+ 	brk_start = (unsigned long) sbrk(0);
+ 
+ 	/*
+@@ -309,7 +303,7 @@ int __init linux_main(int argc, char **argv)
+ 
+ 	highmem = 0;
+ 	iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+-	max_physmem = get_kmem_end() - uml_physmem - iomem_size - MIN_VMALLOC;
++	max_physmem = CONFIG_TOP_ADDR - uml_physmem - iomem_size - MIN_VMALLOC;
+ 
+ 	/*
+ 	 * Zones have to begin on a 1 << MAX_ORDER page boundary,
+@@ -341,7 +335,7 @@ int __init linux_main(int argc, char **argv)
+ 	}
+ 
+ 	virtmem_size = physmem_size;
+-	avail = get_kmem_end() - start_vm;
++	avail = CONFIG_TOP_ADDR - start_vm;
+ 	if (physmem_size > avail)
+ 		virtmem_size = avail;
+ 	end_vm = start_vm + virtmem_size;
+@@ -350,6 +344,9 @@ int __init linux_main(int argc, char **argv)
+ 		printf("Kernel virtual memory size shrunk to %lu bytes\n",
+ 		       virtmem_size);
+ 
++	atomic_notifier_chain_register(&panic_notifier_list,
++				       &panic_exit_notifier);
++
+ 	uml_postsetup();
+ 
+ 	stack_protections((unsigned long) &init_thread_info);
+@@ -358,29 +355,8 @@ int __init linux_main(int argc, char **argv)
+ 	return start_uml();
+ }
+ 
+-extern int uml_exitcode;
 -
--CLEAN_FILES += arch/x86/boot/fdimage \
--	       arch/x86/boot/image.iso \
--	       arch/x86/boot/mtools.conf
+-static int panic_exit(struct notifier_block *self, unsigned long unused1,
+-		      void *unused2)
+-{
+-	bust_spinlocks(1);
+-	show_regs(&(current->thread.regs));
+-	bust_spinlocks(0);
+-	uml_exitcode = 1;
+-	os_dump_core();
+-	return 0;
+-}
 -
+-static struct notifier_block panic_exit_notifier = {
+-	.notifier_call 		= panic_exit,
+-	.next 			= NULL,
+-	.priority 		= 0
+-};
 -
-diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
-index 7a3116c..349b81a 100644
---- a/arch/x86/boot/Makefile
-+++ b/arch/x86/boot/Makefile
-@@ -28,9 +28,11 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
- targets		:= vmlinux.bin setup.bin setup.elf zImage bzImage
- subdir- 	:= compressed
+ void __init setup_arch(char **cmdline_p)
+ {
+-	atomic_notifier_chain_register(&panic_notifier_list,
+-			&panic_exit_notifier);
+ 	paging_init();
+ 	strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ 	*cmdline_p = command_line;
+diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c
+index 039e16e..81e07e2 100644
+--- a/arch/um/kernel/umid.c
++++ b/arch/um/kernel/umid.c
+@@ -1,13 +1,12 @@
+-/* 
+- * Copyright (C) 2001, 2002 Jeff Dike (jdike at karaya.com)
++/*
++ * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
  
--setup-y		+= a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o
-+setup-y		+= a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
- setup-y		+= header.o main.o mca.o memory.o pm.o pmjump.o
--setup-y		+= printf.o string.o tty.o video.o version.o voyager.o
-+setup-y		+= printf.o string.o tty.o video.o version.o
-+setup-$(CONFIG_X86_APM_BOOT) += apm.o
-+setup-$(CONFIG_X86_VOYAGER) += voyager.o
+-#include "asm/errno.h"
++#include <asm/errno.h>
+ #include "init.h"
+-#include "os.h"
+ #include "kern.h"
+-#include "linux/kernel.h"
++#include "os.h"
+ 
+ /* Changed by set_umid_arg */
+ static int umid_inited = 0;
+@@ -16,16 +15,16 @@ static int __init set_umid_arg(char *name, int *add)
+ {
+ 	int err;
  
- # The link order of the video-*.o modules can matter.  In particular,
- # video-vga.o *must* be listed first, followed by video-vesa.o.
-@@ -49,10 +51,7 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE)
+-	if(umid_inited){
++	if (umid_inited) {
+ 		printf("umid already set\n");
+ 		return 0;
+ 	}
  
- # How to compile the 16-bit code.  Note we always compile for -march=i386,
- # that way we can complain to the user if the CPU is insufficient.
--cflags-$(CONFIG_X86_32) :=
--cflags-$(CONFIG_X86_64) := -m32
- KBUILD_CFLAGS	:= $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
--		   $(cflags-y) \
- 		   -Wall -Wstrict-prototypes \
- 		   -march=i386 -mregparm=3 \
- 		   -include $(srctree)/$(src)/code16gcc.h \
-@@ -62,6 +61,7 @@ KBUILD_CFLAGS	:= $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
- 			$(call cc-option, -fno-unit-at-a-time)) \
- 		   $(call cc-option, -fno-stack-protector) \
- 		   $(call cc-option, -mpreferred-stack-boundary=2)
-+KBUILD_CFLAGS +=   $(call cc-option,-m32)
- KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
+ 	*add = 0;
+ 	err = set_umid(name);
+-	if(err == -EEXIST)
++	if (err == -EEXIST)
+ 		printf("umid '%s' already in use\n", name);
+-	else if(!err)
++	else if (!err)
+ 		umid_inited = 1;
  
- $(obj)/zImage:  IMAGE_OFFSET := 0x1000
-diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
-index eab50c5..c117c7f 100644
---- a/arch/x86/boot/apm.c
-+++ b/arch/x86/boot/apm.c
-@@ -19,8 +19,6 @@
+ 	return 0;
+diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
+index 13df191..5828c1d 100644
+--- a/arch/um/kernel/uml.lds.S
++++ b/arch/um/kernel/uml.lds.S
+@@ -23,7 +23,7 @@ SECTIONS
+   __init_begin = .;
+   .init.text : {
+ 	_sinittext = .;
+-	*(.init.text)
++	INIT_TEXT
+ 	_einittext = .;
+   }
+   . = ALIGN(4096);
+@@ -48,7 +48,7 @@ SECTIONS
  
- #include "boot.h"
+   #include "asm/common.lds.S"
  
--#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
+-  init.data : { *(init.data) }
++  init.data : { INIT_DATA }
+   .data    :
+   {
+     . = ALIGN(KERNEL_STACK_SIZE);		/* init_task */
+diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
+index 8e129af..8a48d6a 100644
+--- a/arch/um/os-Linux/Makefile
++++ b/arch/um/os-Linux/Makefile
+@@ -4,7 +4,7 @@
+ #
+ 
+ obj-y = aio.o elf_aux.o execvp.o file.o helper.o irq.o main.o mem.o process.o \
+-	registers.o sigio.o signal.o start_up.o time.o trap.o tty.o uaccess.o \
++	registers.o sigio.o signal.o start_up.o time.o tty.o uaccess.o \
+ 	umid.o tls.o user_syms.o util.o drivers/ sys-$(SUBARCH)/ skas/
+ 
+ obj-$(CONFIG_TTY_LOG) += tty_log.o
+@@ -12,7 +12,7 @@ user-objs-$(CONFIG_TTY_LOG) += tty_log.o
+ 
+ USER_OBJS := $(user-objs-y) aio.o elf_aux.o execvp.o file.o helper.o irq.o \
+ 	main.o mem.o process.o registers.o sigio.o signal.o start_up.o time.o \
+-	trap.o tty.o tls.o uaccess.o umid.o util.o
++	tty.o tls.o uaccess.o umid.o util.o
+ 
+ CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
+ 
+diff --git a/arch/um/os-Linux/aio.c b/arch/um/os-Linux/aio.c
+index 93dc0c8..b8d8c9c 100644
+--- a/arch/um/os-Linux/aio.c
++++ b/arch/um/os-Linux/aio.c
+@@ -12,6 +12,7 @@
+ #include "aio.h"
+ #include "init.h"
+ #include "kern_constants.h"
++#include "kern_util.h"
+ #include "os.h"
+ #include "user.h"
+ 
+diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
+index 07ca0cb..6fb0b17 100644
+--- a/arch/um/os-Linux/drivers/ethertap_user.c
++++ b/arch/um/os-Linux/drivers/ethertap_user.c
+@@ -131,7 +131,7 @@ static int etap_tramp(char *dev, char *gate, int control_me,
+ 	}
+ 	if (c != 1) {
+ 		printk(UM_KERN_ERR "etap_tramp : uml_net failed\n");
+-		err = helper_wait(pid, 0, "uml_net");
++		err = helper_wait(pid);
+ 	}
+ 	return err;
+ }
+diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
+index 1037a3b..2448be0 100644
+--- a/arch/um/os-Linux/drivers/tuntap_user.c
++++ b/arch/um/os-Linux/drivers/tuntap_user.c
+@@ -14,6 +14,7 @@
+ #include <sys/wait.h>
+ #include <sys/uio.h>
+ #include "kern_constants.h"
++#include "kern_util.h"
+ #include "os.h"
+ #include "tuntap.h"
+ #include "user.h"
+@@ -107,7 +108,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote,
+ 		       "errno = %d\n", errno);
+ 		return err;
+ 	}
+-	helper_wait(pid, 0, "tuntap_open_tramp");
++	helper_wait(pid);
+ 
+ 	cmsg = CMSG_FIRSTHDR(&msg);
+ 	if (cmsg == NULL) {
+@@ -148,7 +149,7 @@ static int tuntap_open(void *data)
+ 		memset(&ifr, 0, sizeof(ifr));
+ 		ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ 		strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
+-		if (ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0) {
++		if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
+ 			err = -errno;
+ 			printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
+ 			       errno);
+diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
+index f834627..b5afcfd 100644
+--- a/arch/um/os-Linux/file.c
++++ b/arch/um/os-Linux/file.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+@@ -8,18 +8,16 @@
+ #include <errno.h>
+ #include <fcntl.h>
+ #include <signal.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include <sys/socket.h>
+-#include <sys/un.h>
+ #include <sys/ioctl.h>
+ #include <sys/mount.h>
+-#include <sys/uio.h>
++#include <sys/socket.h>
++#include <sys/stat.h>
++#include <sys/un.h>
++#include "kern_constants.h"
+ #include "os.h"
+ #include "user.h"
+-#include "kern_util.h"
+ 
+-static void copy_stat(struct uml_stat *dst, struct stat64 *src)
++static void copy_stat(struct uml_stat *dst, const struct stat64 *src)
+ {
+ 	*dst = ((struct uml_stat) {
+ 		.ust_dev     = src->st_dev,     /* device */
+@@ -43,10 +41,10 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
+ 	int err;
+ 
+ 	CATCH_EINTR(err = fstat64(fd, &sbuf));
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
+ 
+-	if(ubuf != NULL)
++	if (ubuf != NULL)
+ 		copy_stat(ubuf, &sbuf);
+ 	return err;
+ }
+@@ -56,27 +54,26 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
+ 	struct stat64 sbuf;
+ 	int err;
+ 
+-	do {
+-		err = stat64(file_name, &sbuf);
+-	} while((err < 0) && (errno == EINTR)) ;
 -
- int query_apm_bios(void)
+-	if(err < 0)
++	CATCH_EINTR(err = stat64(file_name, &sbuf));
++	if (err < 0)
+ 		return -errno;
+ 
+-	if(ubuf != NULL)
++	if (ubuf != NULL)
+ 		copy_stat(ubuf, &sbuf);
+ 	return err;
+ }
+ 
+-int os_access(const char* file, int mode)
++int os_access(const char *file, int mode)
  {
- 	u16 ax, bx, cx, dx, di;
-@@ -95,4 +93,3 @@ int query_apm_bios(void)
+ 	int amode, err;
+ 
+-	amode=(mode&OS_ACC_R_OK ? R_OK : 0) | (mode&OS_ACC_W_OK ? W_OK : 0) |
+-	      (mode&OS_ACC_X_OK ? X_OK : 0) | (mode&OS_ACC_F_OK ? F_OK : 0) ;
++	amode = (mode & OS_ACC_R_OK ? R_OK : 0) |
++		(mode & OS_ACC_W_OK ? W_OK : 0) |
++		(mode & OS_ACC_X_OK ? X_OK : 0) |
++		(mode & OS_ACC_F_OK ? F_OK : 0);
+ 
+ 	err = access(file, amode);
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
+ 
+ 	return 0;
+@@ -88,7 +85,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
+ 	int err;
+ 
+ 	err = ioctl(fd, cmd, arg);
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
+ 
+ 	return err;
+@@ -97,7 +94,7 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
+ /* FIXME: ensure namebuf in os_get_if_name is big enough */
+ int os_get_ifname(int fd, char* namebuf)
+ {
+-	if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
++	if (ioctl(fd, SIOCGIFNAME, namebuf) < 0)
+ 		return -errno;
+ 
+ 	return 0;
+@@ -108,37 +105,22 @@ int os_set_slip(int fd)
+ 	int disc, sencap;
+ 
+ 	disc = N_SLIP;
+-	if(ioctl(fd, TIOCSETD, &disc) < 0)
++	if (ioctl(fd, TIOCSETD, &disc) < 0)
+ 		return -errno;
+ 
+ 	sencap = 0;
+-	if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
++	if (ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
+ 		return -errno;
+ 
  	return 0;
  }
  
--#endif
-diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
-index d2b5adf..7822a49 100644
---- a/arch/x86/boot/boot.h
-+++ b/arch/x86/boot/boot.h
-@@ -109,7 +109,7 @@ typedef unsigned int addr_t;
- static inline u8 rdfs8(addr_t addr)
+-int os_set_owner(int fd, int pid)
+-{
+-	if(fcntl(fd, F_SETOWN, pid) < 0){
+-		int save_errno = errno;
+-
+-		if(fcntl(fd, F_GETOWN, 0) != pid)
+-			return -save_errno;
+-	}
+-
+-	return 0;
+-}
+-
+ int os_mode_fd(int fd, int mode)
  {
- 	u8 v;
--	asm volatile("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
-+	asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
- 	return v;
+ 	int err;
+ 
+-	do {
+-		err = fchmod(fd, mode);
+-	} while((err < 0) && (errno==EINTR)) ;
+-
+-	if(err < 0)
++	CATCH_EINTR(err = fchmod(fd, mode));
++	if (err < 0)
+ 		return -errno;
+ 
+ 	return 0;
+@@ -150,64 +132,73 @@ int os_file_type(char *file)
+ 	int err;
+ 
+ 	err = os_stat_file(file, &buf);
+-	if(err < 0)
++	if (err < 0)
+ 		return err;
+ 
+-	if(S_ISDIR(buf.ust_mode))
++	if (S_ISDIR(buf.ust_mode))
+ 		return OS_TYPE_DIR;
+-	else if(S_ISLNK(buf.ust_mode))
++	else if (S_ISLNK(buf.ust_mode))
+ 		return OS_TYPE_SYMLINK;
+-	else if(S_ISCHR(buf.ust_mode))
++	else if (S_ISCHR(buf.ust_mode))
+ 		return OS_TYPE_CHARDEV;
+-	else if(S_ISBLK(buf.ust_mode))
++	else if (S_ISBLK(buf.ust_mode))
+ 		return OS_TYPE_BLOCKDEV;
+-	else if(S_ISFIFO(buf.ust_mode))
++	else if (S_ISFIFO(buf.ust_mode))
+ 		return OS_TYPE_FIFO;
+-	else if(S_ISSOCK(buf.ust_mode))
++	else if (S_ISSOCK(buf.ust_mode))
+ 		return OS_TYPE_SOCK;
+ 	else return OS_TYPE_FILE;
  }
- static inline u16 rdfs16(addr_t addr)
-@@ -127,21 +127,21 @@ static inline u32 rdfs32(addr_t addr)
  
- static inline void wrfs8(u8 v, addr_t addr)
+-int os_file_mode(char *file, struct openflags *mode_out)
++int os_file_mode(const char *file, struct openflags *mode_out)
  {
--	asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v));
-+	asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
+ 	int err;
+ 
+ 	*mode_out = OPENFLAGS();
+ 
+ 	err = access(file, W_OK);
+-	if(err && (errno != EACCES))
++	if (err && (errno != EACCES))
+ 		return -errno;
+-	else if(!err)
++	else if (!err)
+ 		*mode_out = of_write(*mode_out);
+ 
+ 	err = access(file, R_OK);
+-	if(err && (errno != EACCES))
++	if (err && (errno != EACCES))
+ 		return -errno;
+-	else if(!err)
++	else if (!err)
+ 		*mode_out = of_read(*mode_out);
+ 
+ 	return err;
  }
- static inline void wrfs16(u16 v, addr_t addr)
+ 
+-int os_open_file(char *file, struct openflags flags, int mode)
++int os_open_file(const char *file, struct openflags flags, int mode)
  {
--	asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v));
-+	asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
+ 	int fd, err, f = 0;
+ 
+-	if(flags.r && flags.w) f = O_RDWR;
+-	else if(flags.r) f = O_RDONLY;
+-	else if(flags.w) f = O_WRONLY;
++	if (flags.r && flags.w)
++		f = O_RDWR;
++	else if (flags.r)
++		f = O_RDONLY;
++	else if (flags.w)
++		f = O_WRONLY;
+ 	else f = 0;
+ 
+-	if(flags.s) f |= O_SYNC;
+-	if(flags.c) f |= O_CREAT;
+-	if(flags.t) f |= O_TRUNC;
+-	if(flags.e) f |= O_EXCL;
++	if (flags.s)
++		f |= O_SYNC;
++	if (flags.c)
++		f |= O_CREAT;
++	if (flags.t)
++		f |= O_TRUNC;
++	if (flags.e)
++		f |= O_EXCL;
++	if (flags.a)
++		f |= O_APPEND;
+ 
+ 	fd = open64(file, f, mode);
+-	if(fd < 0)
++	if (fd < 0)
+ 		return -errno;
+ 
+-	if(flags.cl && fcntl(fd, F_SETFD, 1)){
++	if (flags.cl && fcntl(fd, F_SETFD, 1)) {
+ 		err = -errno;
+ 		close(fd);
+ 		return err;
+@@ -216,7 +207,7 @@ int os_open_file(char *file, struct openflags flags, int mode)
+ 	return fd;
  }
- static inline void wrfs32(u32 v, addr_t addr)
+ 
+-int os_connect_socket(char *name)
++int os_connect_socket(const char *name)
  {
--	asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v));
-+	asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
+ 	struct sockaddr_un sock;
+ 	int fd, err;
+@@ -225,13 +216,13 @@ int os_connect_socket(char *name)
+ 	snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name);
+ 
+ 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
+-	if(fd < 0) {
++	if (fd < 0) {
+ 		err = -errno;
+ 		goto out;
+ 	}
+ 
+ 	err = connect(fd, (struct sockaddr *) &sock, sizeof(sock));
+-	if(err) {
++	if (err) {
+ 		err = -errno;
+ 		goto out_close;
+ 	}
+@@ -254,7 +245,7 @@ int os_seek_file(int fd, unsigned long long offset)
+ 	unsigned long long actual;
+ 
+ 	actual = lseek64(fd, offset, SEEK_SET);
+-	if(actual != offset)
++	if (actual != offset)
+ 		return -errno;
+ 	return 0;
  }
+@@ -263,7 +254,7 @@ int os_read_file(int fd, void *buf, int len)
+ {
+ 	int n = read(fd, buf, len);
  
- static inline u8 rdgs8(addr_t addr)
+-	if(n < 0)
++	if (n < 0)
+ 		return -errno;
+ 	return n;
+ }
+@@ -272,37 +263,38 @@ int os_write_file(int fd, const void *buf, int len)
  {
- 	u8 v;
--	asm volatile("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
-+	asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
- 	return v;
+ 	int n = write(fd, (void *) buf, len);
+ 
+-	if(n < 0)
++	if (n < 0)
+ 		return -errno;
+ 	return n;
  }
- static inline u16 rdgs16(addr_t addr)
-@@ -159,15 +159,15 @@ static inline u32 rdgs32(addr_t addr)
  
- static inline void wrgs8(u8 v, addr_t addr)
+-int os_file_size(char *file, unsigned long long *size_out)
++int os_file_size(const char *file, unsigned long long *size_out)
  {
--	asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v));
-+	asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
+ 	struct uml_stat buf;
+ 	int err;
+ 
+ 	err = os_stat_file(file, &buf);
+-	if(err < 0){
+-		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
++	if (err < 0) {
++		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
++		       -err);
+ 		return err;
+ 	}
+ 
+-	if(S_ISBLK(buf.ust_mode)){
++	if (S_ISBLK(buf.ust_mode)) {
+ 		int fd;
+ 		long blocks;
+ 
+ 		fd = open(file, O_RDONLY, 0);
+-		if(fd < 0) {
++		if (fd < 0) {
+ 			err = -errno;
+-			printk("Couldn't open \"%s\", errno = %d\n", file,
+-			       errno);
++			printk(UM_KERN_ERR "Couldn't open \"%s\", "
++			       "errno = %d\n", file, errno);
+ 			return err;
+ 		}
+-		if(ioctl(fd, BLKGETSIZE, &blocks) < 0){
++		if (ioctl(fd, BLKGETSIZE, &blocks) < 0) {
+ 			err = -errno;
+-			printk("Couldn't get the block size of \"%s\", "
+-			       "errno = %d\n", file, errno);
++			printk(UM_KERN_ERR "Couldn't get the block size of "
++			       "\"%s\", errno = %d\n", file, errno);
+ 			close(fd);
+ 			return err;
+ 		}
+@@ -314,14 +306,15 @@ int os_file_size(char *file, unsigned long long *size_out)
+ 	return 0;
  }
- static inline void wrgs16(u16 v, addr_t addr)
+ 
+-int os_file_modtime(char *file, unsigned long *modtime)
++int os_file_modtime(const char *file, unsigned long *modtime)
  {
--	asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v));
-+	asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
+ 	struct uml_stat buf;
+ 	int err;
+ 
+ 	err = os_stat_file(file, &buf);
+-	if(err < 0){
+-		printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
++	if (err < 0) {
++		printk(UM_KERN_ERR "Couldn't stat \"%s\" : err = %d\n", file,
++		       -err);
+ 		return err;
+ 	}
+ 
+@@ -329,26 +322,13 @@ int os_file_modtime(char *file, unsigned long *modtime)
+ 	return 0;
  }
- static inline void wrgs32(u32 v, addr_t addr)
+ 
+-int os_get_exec_close(int fd, int *close_on_exec)
+-{
+-	int ret;
+-
+-	CATCH_EINTR(ret = fcntl(fd, F_GETFD));
+-
+-	if(ret < 0)
+-		return -errno;
+-
+-	*close_on_exec = (ret & FD_CLOEXEC) ? 1 : 0;
+-	return ret;
+-}
+-
+ int os_set_exec_close(int fd)
  {
--	asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v));
-+	asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
+ 	int err;
+ 
+ 	CATCH_EINTR(err = fcntl(fd, F_SETFD, FD_CLOEXEC));
+ 
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
+ 	return err;
  }
+@@ -358,53 +338,51 @@ int os_pipe(int *fds, int stream, int close_on_exec)
+ 	int err, type = stream ? SOCK_STREAM : SOCK_DGRAM;
  
- /* Note: these only return true/false, not a signed return value! */
-@@ -241,6 +241,7 @@ int query_apm_bios(void);
+ 	err = socketpair(AF_UNIX, type, 0, fds);
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
  
- /* cmdline.c */
- int cmdline_find_option(const char *option, char *buffer, int bufsize);
-+int cmdline_find_option_bool(const char *option);
+-	if(!close_on_exec)
++	if (!close_on_exec)
+ 		return 0;
  
- /* cpu.c, cpucheck.c */
- int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
-diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
-index 34bb778..680408a 100644
---- a/arch/x86/boot/cmdline.c
-+++ b/arch/x86/boot/cmdline.c
-@@ -95,3 +95,68 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize)
+ 	err = os_set_exec_close(fds[0]);
+-	if(err < 0)
++	if (err < 0)
+ 		goto error;
  
- 	return len;
+ 	err = os_set_exec_close(fds[1]);
+-	if(err < 0)
++	if (err < 0)
+ 		goto error;
+ 
+ 	return 0;
+ 
+  error:
+-	printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
++	printk(UM_KERN_ERR "os_pipe : Setting FD_CLOEXEC failed, err = %d\n",
++	       -err);
+ 	close(fds[1]);
+ 	close(fds[0]);
+ 	return err;
  }
+ 
+-int os_set_fd_async(int fd, int owner)
++int os_set_fd_async(int fd)
+ {
+-	int err;
++	int err, flags;
 +
-+/*
-+ * Find a boolean option (like quiet,noapic,nosmp....)
-+ *
-+ * Returns the position of that option (starts counting with 1)
-+ * or 0 on not found
-+ */
-+int cmdline_find_option_bool(const char *option)
-+{
-+	u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
-+	addr_t cptr;
-+	char c;
-+	int pos = 0, wstart = 0;
-+	const char *opptr = NULL;
-+	enum {
-+		st_wordstart,	/* Start of word/after whitespace */
-+		st_wordcmp,	/* Comparing this word */
-+		st_wordskip,	/* Miscompare, skip */
-+	} state = st_wordstart;
-+
-+	if (!cmdline_ptr || cmdline_ptr >= 0x100000)
-+		return -1;	/* No command line, or inaccessible */
-+
-+	cptr = cmdline_ptr & 0xf;
-+	set_fs(cmdline_ptr >> 4);
-+
-+	while (cptr < 0x10000) {
-+		c = rdfs8(cptr++);
-+		pos++;
-+
-+		switch (state) {
-+		case st_wordstart:
-+			if (!c)
-+				return 0;
-+			else if (myisspace(c))
-+				break;
-+
-+			state = st_wordcmp;
-+			opptr = option;
-+			wstart = pos;
-+			/* fall through */
++	flags = fcntl(fd, F_GETFL);
++	if (flags < 0)
++		return -errno;
+ 
+-	/* XXX This should do F_GETFL first */
+-	if(fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK) < 0){
++	flags |= O_ASYNC | O_NONBLOCK;
++	if (fcntl(fd, F_SETFL, flags) < 0) {
+ 		err = -errno;
+-		printk("os_set_fd_async : failed to set O_ASYNC and "
+-		       "O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
++		printk(UM_KERN_ERR "os_set_fd_async : failed to set O_ASYNC "
++		       "and O_NONBLOCK on fd # %d, errno = %d\n", fd, errno);
+ 		return err;
+ 	}
+-#ifdef notdef
+-	if(fcntl(fd, F_SETFD, 1) < 0){
+-		printk("os_set_fd_async : Setting FD_CLOEXEC failed, "
+-		       "errno = %d\n", errno);
+-	}
+-#endif
+ 
+-	if((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
+-	   (fcntl(fd, F_SETOWN, owner) < 0)){
++	if ((fcntl(fd, F_SETSIG, SIGIO) < 0) ||
++	    (fcntl(fd, F_SETOWN, os_getpid()) < 0)) {
+ 		err = -errno;
+-		printk("os_set_fd_async : Failed to fcntl F_SETOWN "
+-		       "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
+-		       owner, errno);
++		printk(UM_KERN_ERR "os_set_fd_async : Failed to fcntl F_SETOWN "
++		       "(or F_SETSIG) fd %d, errno = %d\n", fd, errno);
+ 		return err;
+ 	}
+ 
+@@ -413,10 +391,14 @@ int os_set_fd_async(int fd, int owner)
+ 
+ int os_clear_fd_async(int fd)
+ {
+-	int flags = fcntl(fd, F_GETFL);
++	int flags;
 +
-+		case st_wordcmp:
-+			if (!*opptr)
-+				if (!c || myisspace(c))
-+					return wstart;
-+				else
-+					state = st_wordskip;
-+			else if (!c)
-+				return 0;
-+			else if (c != *opptr++)
-+				state = st_wordskip;
-+			break;
-+
-+		case st_wordskip:
-+			if (!c)
-+				return 0;
-+			else if (myisspace(c))
-+				state = st_wordstart;
-+			break;
-+		}
-+	}
-+
-+	return 0;	/* Buffer overrun */
-+}
-diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
-index 52c1db8..fe24cea 100644
---- a/arch/x86/boot/compressed/Makefile
-+++ b/arch/x86/boot/compressed/Makefile
-@@ -1,5 +1,63 @@
-+#
-+# linux/arch/x86/boot/compressed/Makefile
-+#
-+# create a compressed vmlinux image from the original vmlinux
-+#
-+
-+targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o
-+
-+KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
-+KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
-+cflags-$(CONFIG_X86_64) := -mcmodel=small
-+KBUILD_CFLAGS += $(cflags-y)
-+KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
-+KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
-+
-+KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
-+
-+LDFLAGS := -m elf_$(UTS_MACHINE)
-+LDFLAGS_vmlinux := -T
-+
-+$(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
-+	$(call if_changed,ld)
-+	@:
-+
-+$(obj)/vmlinux.bin: vmlinux FORCE
-+	$(call if_changed,objcopy)
-+
-+
- ifeq ($(CONFIG_X86_32),y)
--include ${srctree}/arch/x86/boot/compressed/Makefile_32
-+targets += vmlinux.bin.all vmlinux.relocs
-+hostprogs-y := relocs
-+
-+quiet_cmd_relocs = RELOCS  $@
-+      cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
-+$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
-+	$(call if_changed,relocs)
-+
-+vmlinux.bin.all-y := $(obj)/vmlinux.bin
-+vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
-+quiet_cmd_relocbin = BUILD   $@
-+      cmd_relocbin = cat $(filter-out FORCE,$^) > $@
-+$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
-+	$(call if_changed,relocbin)
-+
-+ifdef CONFIG_RELOCATABLE
-+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
-+	$(call if_changed,gzip)
- else
--include ${srctree}/arch/x86/boot/compressed/Makefile_64
-+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
-+	$(call if_changed,gzip)
- endif
-+LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
-+
-+else
-+$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
-+	$(call if_changed,gzip)
-+
-+LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
-+endif
++	flags = fcntl(fd, F_GETFL);
++	if (flags < 0)
++		return -errno;
+ 
+ 	flags &= ~(O_ASYNC | O_NONBLOCK);
+-	if(fcntl(fd, F_SETFL, flags) < 0)
++	if (fcntl(fd, F_SETFL, flags) < 0)
+ 		return -errno;
+ 	return 0;
+ }
+@@ -426,11 +408,15 @@ int os_set_fd_block(int fd, int blocking)
+ 	int flags;
+ 
+ 	flags = fcntl(fd, F_GETFL);
++	if (flags < 0)
++		return -errno;
+ 
+-	if(blocking) flags &= ~O_NONBLOCK;
+-	else flags |= O_NONBLOCK;
++	if (blocking)
++		flags &= ~O_NONBLOCK;
++	else
++		flags |= O_NONBLOCK;
+ 
+-	if(fcntl(fd, F_SETFL, flags) < 0)
++	if (fcntl(fd, F_SETFL, flags) < 0)
+ 		return -errno;
+ 
+ 	return 0;
+@@ -441,7 +427,7 @@ int os_accept_connection(int fd)
+ 	int new;
+ 
+ 	new = accept(fd, NULL, 0);
+-	if(new < 0)
++	if (new < 0)
+ 		return -errno;
+ 	return new;
+ }
+@@ -462,15 +448,17 @@ int os_shutdown_socket(int fd, int r, int w)
+ {
+ 	int what, err;
+ 
+-	if(r && w) what = SHUT_RDWR;
+-	else if(r) what = SHUT_RD;
+-	else if(w) what = SHUT_WR;
+-	else {
+-		printk("os_shutdown_socket : neither r or w was set\n");
++	if (r && w)
++		what = SHUT_RDWR;
++	else if (r)
++		what = SHUT_RD;
++	else if (w)
++		what = SHUT_WR;
++	else
+ 		return -EINVAL;
+-	}
 +
+ 	err = shutdown(fd, what);
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
+ 	return 0;
+ }
+@@ -494,19 +482,20 @@ int os_rcv_fd(int fd, int *helper_pid_out)
+ 	msg.msg_flags = 0;
+ 
+ 	n = recvmsg(fd, &msg, 0);
+-	if(n < 0)
++	if (n < 0)
+ 		return -errno;
+-	else if(n != iov.iov_len)
++	else if (n != iov.iov_len)
+ 		*helper_pid_out = -1;
+ 
+ 	cmsg = CMSG_FIRSTHDR(&msg);
+-	if(cmsg == NULL){
+-		printk("rcv_fd didn't receive anything, error = %d\n", errno);
++	if (cmsg == NULL) {
++		printk(UM_KERN_ERR "rcv_fd didn't receive anything, "
++		       "error = %d\n", errno);
+ 		return -1;
+ 	}
+-	if((cmsg->cmsg_level != SOL_SOCKET) ||
+-	   (cmsg->cmsg_type != SCM_RIGHTS)){
+-		printk("rcv_fd didn't receive a descriptor\n");
++	if ((cmsg->cmsg_level != SOL_SOCKET) ||
++	    (cmsg->cmsg_type != SCM_RIGHTS)) {
++		printk(UM_KERN_ERR "rcv_fd didn't receive a descriptor\n");
+ 		return -1;
+ 	}
+ 
+@@ -514,29 +503,28 @@ int os_rcv_fd(int fd, int *helper_pid_out)
+ 	return new;
+ }
+ 
+-int os_create_unix_socket(char *file, int len, int close_on_exec)
++int os_create_unix_socket(const char *file, int len, int close_on_exec)
+ {
+ 	struct sockaddr_un addr;
+ 	int sock, err;
+ 
+ 	sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+-	if(sock < 0)
++	if (sock < 0)
+ 		return -errno;
+ 
+-	if(close_on_exec) {
++	if (close_on_exec) {
+ 		err = os_set_exec_close(sock);
+-		if(err < 0)
+-			printk("create_unix_socket : close_on_exec failed, "
+-		       "err = %d", -err);
++		if (err < 0)
++			printk(UM_KERN_ERR "create_unix_socket : "
++			       "close_on_exec failed, err = %d", -err);
+ 	}
+ 
+ 	addr.sun_family = AF_UNIX;
+ 
+-	/* XXX Be more careful about overflow */
+ 	snprintf(addr.sun_path, len, "%s", file);
+ 
+ 	err = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
+-	if(err < 0)
++	if (err < 0)
+ 		return -errno;
+ 
+ 	return sock;
+@@ -557,17 +545,18 @@ int os_lock_file(int fd, int excl)
+ 	int err, save;
+ 
+ 	err = fcntl(fd, F_SETLK, &lock);
+-	if(!err)
++	if (!err)
+ 		goto out;
+ 
+ 	save = -errno;
+ 	err = fcntl(fd, F_GETLK, &lock);
+-	if(err){
++	if (err) {
+ 		err = -errno;
+ 		goto out;
+ 	}
+ 
+-	printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
++	printk(UM_KERN_ERR "F_SETLK failed, file already locked by pid %d\n",
++	       lock.l_pid);
+ 	err = save;
+  out:
+ 	return err;
+diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
+index fba3f0f..f4bd349 100644
+--- a/arch/um/os-Linux/helper.c
++++ b/arch/um/os-Linux/helper.c
+@@ -1,22 +1,19 @@
+ /*
+- * Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+-#include <stdio.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <errno.h>
+ #include <sched.h>
+-#include <limits.h>
+-#include <sys/signal.h>
+-#include <sys/wait.h>
+ #include <sys/socket.h>
+-#include "user.h"
++#include <sys/wait.h>
++#include "kern_constants.h"
+ #include "kern_util.h"
+ #include "os.h"
+ #include "um_malloc.h"
+-#include "kern_constants.h"
++#include "user.h"
+ 
+ struct helper_data {
+ 	void (*pre_exec)(void*);
+@@ -30,21 +27,19 @@ static int helper_child(void *arg)
+ {
+ 	struct helper_data *data = arg;
+ 	char **argv = data->argv;
+-	int errval;
++	int err;
+ 
+ 	if (data->pre_exec != NULL)
+ 		(*data->pre_exec)(data->pre_data);
+-	errval = execvp_noalloc(data->buf, argv[0], argv);
+-	printk("helper_child - execvp of '%s' failed - errno = %d\n", argv[0],
+-	       -errval);
+-	write(data->fd, &errval, sizeof(errval));
+-	kill(os_getpid(), SIGKILL);
++	err = execvp_noalloc(data->buf, argv[0], argv);
++
++	/* If the exec succeeds, we don't get here */
++	write(data->fd, &err, sizeof(err));
 +
-+$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
-+	$(call if_changed,ld)
-diff --git a/arch/x86/boot/compressed/Makefile_32 b/arch/x86/boot/compressed/Makefile_32
-deleted file mode 100644
-index e43ff7c..0000000
---- a/arch/x86/boot/compressed/Makefile_32
-+++ /dev/null
-@@ -1,50 +0,0 @@
--#
--# linux/arch/x86/boot/compressed/Makefile
--#
--# create a compressed vmlinux image from the original vmlinux
--#
--
--targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head_32.o misc_32.o piggy.o \
--			vmlinux.bin.all vmlinux.relocs
--EXTRA_AFLAGS	:= -traditional
--
--LDFLAGS_vmlinux := -T
--hostprogs-y	:= relocs
--
--KBUILD_CFLAGS  := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
--	   -fno-strict-aliasing -fPIC \
--	   $(call cc-option,-ffreestanding) \
--	   $(call cc-option,-fno-stack-protector)
--LDFLAGS := -m elf_i386
--
--$(obj)/vmlinux: $(src)/vmlinux_32.lds $(obj)/head_32.o $(obj)/misc_32.o $(obj)/piggy.o FORCE
--	$(call if_changed,ld)
--	@:
--
--$(obj)/vmlinux.bin: vmlinux FORCE
--	$(call if_changed,objcopy)
--
--quiet_cmd_relocs = RELOCS  $@
--      cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
--$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
--	$(call if_changed,relocs)
--
--vmlinux.bin.all-y := $(obj)/vmlinux.bin
--vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
--quiet_cmd_relocbin = BUILD   $@
--      cmd_relocbin = cat $(filter-out FORCE,$^) > $@
--$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
--	$(call if_changed,relocbin)
--
--ifdef CONFIG_RELOCATABLE
--$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
--	$(call if_changed,gzip)
--else
--$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
--	$(call if_changed,gzip)
--endif
+ 	return 0;
+ }
+ 
+-/* Returns either the pid of the child process we run or -E* on failure.
+- * XXX The alloc_stack here breaks if this is called in the tracing thread, so
+- * we need to receive a preallocated stack (a local buffer is ok). */
++/* Returns either the pid of the child process we run or -E* on failure. */
+ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
+ {
+ 	struct helper_data data;
+@@ -58,14 +53,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
+ 	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+ 	if (ret < 0) {
+ 		ret = -errno;
+-		printk("run_helper : pipe failed, errno = %d\n", errno);
++		printk(UM_KERN_ERR "run_helper : pipe failed, errno = %d\n",
++		       errno);
+ 		goto out_free;
+ 	}
+ 
+ 	ret = os_set_exec_close(fds[1]);
+ 	if (ret < 0) {
+-		printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n",
+-		       -ret);
++		printk(UM_KERN_ERR "run_helper : setting FD_CLOEXEC failed, "
++		       "ret = %d\n", -ret);
+ 		goto out_close;
+ 	}
+ 
+@@ -79,7 +75,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
+ 	pid = clone(helper_child, (void *) sp, CLONE_VM, &data);
+ 	if (pid < 0) {
+ 		ret = -errno;
+-		printk("run_helper : clone failed, errno = %d\n", errno);
++		printk(UM_KERN_ERR "run_helper : clone failed, errno = %d\n",
++		       errno);
+ 		goto out_free2;
+ 	}
+ 
+@@ -96,10 +93,9 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv)
+ 	} else {
+ 		if (n < 0) {
+ 			n = -errno;
+-			printk("run_helper : read on pipe failed, ret = %d\n",
+-			       -n);
++			printk(UM_KERN_ERR "run_helper : read on pipe failed, "
++			       "ret = %d\n", -n);
+ 			ret = n;
+-			kill(pid, SIGKILL);
+ 		}
+ 		CATCH_EINTR(waitpid(pid, NULL, __WCLONE));
+ 	}
+@@ -129,50 +125,40 @@ int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags,
+ 	pid = clone(proc, (void *) sp, flags, arg);
+ 	if (pid < 0) {
+ 		err = -errno;
+-		printk("run_helper_thread : clone failed, errno = %d\n",
+-		       errno);
++		printk(UM_KERN_ERR "run_helper_thread : clone failed, "
++		       "errno = %d\n", errno);
+ 		return err;
+ 	}
+ 	if (stack_out == NULL) {
+ 		CATCH_EINTR(pid = waitpid(pid, &status, __WCLONE));
+ 		if (pid < 0) {
+ 			err = -errno;
+-			printk("run_helper_thread - wait failed, errno = %d\n",
+-			       errno);
++			printk(UM_KERN_ERR "run_helper_thread - wait failed, "
++			       "errno = %d\n", errno);
+ 			pid = err;
+ 		}
+ 		if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0))
+-			printk("run_helper_thread - thread returned status "
+-			       "0x%x\n", status);
++			printk(UM_KERN_ERR "run_helper_thread - thread "
++			       "returned status 0x%x\n", status);
+ 		free_stack(stack, 0);
+ 	} else
+ 		*stack_out = stack;
+ 	return pid;
+ }
+ 
+-int helper_wait(int pid, int nohang, char *pname)
++int helper_wait(int pid)
+ {
+ 	int ret, status;
+ 	int wflags = __WCLONE;
+ 
+-	if (nohang)
+-		wflags |= WNOHANG;
 -
--LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
+-	if (!pname)
+-		pname = "helper_wait";
 -
--$(obj)/piggy.o: $(src)/vmlinux_32.scr $(obj)/vmlinux.bin.gz FORCE
--	$(call if_changed,ld)
-diff --git a/arch/x86/boot/compressed/Makefile_64 b/arch/x86/boot/compressed/Makefile_64
-deleted file mode 100644
-index 7801e8d..0000000
---- a/arch/x86/boot/compressed/Makefile_64
-+++ /dev/null
-@@ -1,30 +0,0 @@
--#
--# linux/arch/x86/boot/compressed/Makefile
--#
--# create a compressed vmlinux image from the original vmlinux
--#
+ 	CATCH_EINTR(ret = waitpid(pid, &status, wflags));
+ 	if (ret < 0) {
+-		printk(UM_KERN_ERR "%s : waitpid process %d failed, "
+-		       "errno = %d\n", pname, pid, errno);
++		printk(UM_KERN_ERR "helper_wait : waitpid process %d failed, "
++		       "errno = %d\n", pid, errno);
+ 		return -errno;
+-	} else if (nohang && ret == 0) {
+-		printk(UM_KERN_ERR "%s : process %d has not exited\n",
+-		       pname, pid);
+-		return -ECHILD;
+ 	} else if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+-		printk(UM_KERN_ERR "%s : process %d didn't exit with "
+-		       "status 0\n", pname, pid);
++		printk(UM_KERN_ERR "helper_wait : process %d exited with "
++		       "status 0x%x\n", pid, status);
+ 		return -ECHILD;
+ 	} else
+ 		return 0;
+diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
+index 6aa6f95..0348b97 100644
+--- a/arch/um/os-Linux/irq.c
++++ b/arch/um/os-Linux/irq.c
+@@ -1,23 +1,19 @@
+ /*
+- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+ #include <stdlib.h>
+-#include <unistd.h>
+ #include <errno.h>
++#include <poll.h>
+ #include <signal.h>
+ #include <string.h>
+-#include <sys/poll.h>
+-#include <sys/types.h>
+-#include <sys/time.h>
+-#include "kern_util.h"
+-#include "user.h"
+-#include "process.h"
+-#include "sigio.h"
+ #include "irq_user.h"
++#include "kern_constants.h"
+ #include "os.h"
++#include "process.h"
+ #include "um_malloc.h"
++#include "user.h"
+ 
+ /*
+  * Locked by irq_lock in arch/um/kernel/irq.c.  Changed by os_create_pollfd
+@@ -36,7 +32,7 @@ int os_waiting_for_events(struct irq_fd *active_fds)
+ 	if (n < 0) {
+ 		err = -errno;
+ 		if (errno != EINTR)
+-			printk("sigio_handler: os_waiting_for_events:"
++			printk(UM_KERN_ERR "os_waiting_for_events:"
+ 			       " poll returned %d, errno = %d\n", n, errno);
+ 		return err;
+ 	}
+@@ -95,24 +91,26 @@ void os_free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg,
+ 			struct irq_fd *old_fd = *prev;
+ 			if ((pollfds[i].fd != -1) &&
+ 			    (pollfds[i].fd != (*prev)->fd)) {
+-				printk("os_free_irq_by_cb - mismatch between "
+-				       "active_fds and pollfds, fd %d vs %d\n",
++				printk(UM_KERN_ERR "os_free_irq_by_cb - "
++				       "mismatch between active_fds and "
++				       "pollfds, fd %d vs %d\n",
+ 				       (*prev)->fd, pollfds[i].fd);
+ 				goto out;
+ 			}
+ 
+ 			pollfds_num--;
+ 
+-			/* This moves the *whole* array after pollfds[i]
++			/*
++			 * This moves the *whole* array after pollfds[i]
+ 			 * (though it doesn't spot as such)!
+ 			 */
+ 			memmove(&pollfds[i], &pollfds[i + 1],
+ 			       (pollfds_num - i) * sizeof(pollfds[0]));
+-			if(*last_irq_ptr2 == &old_fd->next)
++			if (*last_irq_ptr2 == &old_fd->next)
+ 				*last_irq_ptr2 = prev;
+ 
+ 			*prev = (*prev)->next;
+-			if(old_fd->type == IRQ_WRITE)
++			if (old_fd->type == IRQ_WRITE)
+ 				ignore_sigio_fd(old_fd->fd);
+ 			kfree(old_fd);
+ 			continue;
+@@ -138,14 +136,3 @@ void os_set_ioignore(void)
+ {
+ 	signal(SIGIO, SIG_IGN);
+ }
 -
--targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head_64.o misc_64.o piggy.o
+-void init_irq_signals(int on_sigstack)
+-{
+-	int flags;
 -
--KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2  \
--	  -fno-strict-aliasing -fPIC -mcmodel=small \
--	   $(call cc-option, -ffreestanding) \
--	   $(call cc-option, -fno-stack-protector)
--KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
--LDFLAGS := -m elf_x86_64
+-	flags = on_sigstack ? SA_ONSTACK : 0;
 -
--LDFLAGS_vmlinux := -T
--$(obj)/vmlinux: $(src)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o $(obj)/piggy.o FORCE
--	$(call if_changed,ld)
--	@:
+-	set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
+-		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+-	signal(SIGWINCH, SIG_IGN);
+-}
+diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
+index 82c3778..abb9b0f 100644
+--- a/arch/um/os-Linux/main.c
++++ b/arch/um/os-Linux/main.c
+@@ -73,7 +73,7 @@ static void install_fatal_handler(int sig)
+ 	action.sa_handler = last_ditch_exit;
+ 	if (sigaction(sig, &action, NULL) < 0) {
+ 		printf("failed to install handler for signal %d - errno = %d\n",
+-		       errno);
++		       sig, errno);
+ 		exit(1);
+ 	}
+ }
+@@ -92,7 +92,8 @@ static void setup_env_path(void)
+ 	 * just use the default + /usr/lib/uml
+ 	 */
+ 	if (!old_path || (path_len = strlen(old_path)) == 0) {
+-		putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH);
++		if (putenv("PATH=:/bin:/usr/bin/" UML_LIB_PATH))
++			perror("couldn't putenv");
+ 		return;
+ 	}
+ 
+@@ -100,15 +101,16 @@ static void setup_env_path(void)
+ 	path_len += strlen("PATH=" UML_LIB_PATH) + 1;
+ 	new_path = malloc(path_len);
+ 	if (!new_path) {
+-		perror("coudn't malloc to set a new PATH");
++		perror("couldn't malloc to set a new PATH");
+ 		return;
+ 	}
+ 	snprintf(new_path, path_len, "PATH=%s" UML_LIB_PATH, old_path);
+-	putenv(new_path);
++	if (putenv(new_path)) {
++		perror("couldn't putenv to set a new PATH");
++		free(new_path);
++	}
+ }
+ 
+-extern int uml_exitcode;
 -
--$(obj)/vmlinux.bin: vmlinux FORCE
--	$(call if_changed,objcopy)
+ extern void scan_elf_aux( char **envp);
+ 
+ int __init main(int argc, char **argv, char **envp)
+diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
+index 436f8d2..eedc2d8 100644
+--- a/arch/um/os-Linux/mem.c
++++ b/arch/um/os-Linux/mem.c
+@@ -9,7 +9,6 @@
+ #include <sys/types.h>
+ #include <sys/mman.h>
+ #include <sys/statfs.h>
+-#include "kern_util.h"
+ #include "user.h"
+ #include "mem_user.h"
+ #include "init.h"
+@@ -30,7 +29,7 @@ static char *tempdir = NULL;
+ 
+ static void __init find_tempdir(void)
+ {
+-	char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
++	const char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL };
+ 	int i;
+ 	char *dir = NULL;
+ 
+@@ -59,9 +58,10 @@ static void __init find_tempdir(void)
+  * read the file as needed.  If there's an error, -errno is returned;
+  * if the end of the file is reached, 0 is returned.
+  */
+-static int next(int fd, char *buf, int size, char c)
++static int next(int fd, char *buf, size_t size, char c)
+ {
+-	int n, len;
++	ssize_t n;
++	size_t len;
+ 	char *ptr;
+ 
+ 	while((ptr = strchr(buf, c)) == NULL){
+@@ -172,13 +172,15 @@ int __init make_tempfile(const char *template, char **out_tempname,
+ 
+ 	which_tmpdir();
+ 	tempname = malloc(MAXPATHLEN);
++	if (!tempname)
++		goto out;
+ 
+ 	find_tempdir();
+ 	if (template[0] != '/')
+ 		strcpy(tempname, tempdir);
+ 	else
+ 		tempname[0] = '\0';
+-	strcat(tempname, template);
++	strncat(tempname, template, MAXPATHLEN-1-strlen(tempname));
+ 	fd = mkstemp(tempname);
+ 	if(fd < 0){
+ 		fprintf(stderr, "open - cannot create %s: %s\n", tempname,
+@@ -268,6 +270,7 @@ void __init check_tmpexec(void)
+ 	if(addr == MAP_FAILED){
+ 		err = errno;
+ 		perror("failed");
++		close(fd);
+ 		if(err == EPERM)
+ 			printf("%s must be not mounted noexec\n",tempdir);
+ 		exit(1);
+diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
+index bda5c31..abf6bea 100644
+--- a/arch/um/os-Linux/process.c
++++ b/arch/um/os-Linux/process.c
+@@ -249,7 +249,10 @@ void init_new_thread_signals(void)
+ 		    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
+ 	signal(SIGHUP, SIG_IGN);
+ 
+-	init_irq_signals(1);
++	set_handler(SIGIO, (__sighandler_t) sig_handler,
++		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
++		    SIGVTALRM, -1);
++	signal(SIGWINCH, SIG_IGN);
+ }
+ 
+ int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
+diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
+index a32ba6a..830fe6a 100644
+--- a/arch/um/os-Linux/registers.c
++++ b/arch/um/os-Linux/registers.c
+@@ -8,47 +8,41 @@
+ #include <string.h>
+ #include <sys/ptrace.h>
+ #include "sysdep/ptrace.h"
+-#include "user.h"
+ 
+-/* This is set once at boot time and not changed thereafter */
 -
--$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
--	$(call if_changed,gzip)
+-static unsigned long exec_regs[MAX_REG_NR];
 -
--LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
+-void init_thread_registers(struct uml_pt_regs *to)
+-{
+-	memcpy(to->gp, exec_regs, sizeof(to->gp));
+-}
 -
--$(obj)/piggy.o: $(obj)/vmlinux_64.scr $(obj)/vmlinux.bin.gz FORCE
--	$(call if_changed,ld)
-diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
-new file mode 100644
-index 0000000..8182e32
---- /dev/null
-+++ b/arch/x86/boot/compressed/misc.c
-@@ -0,0 +1,413 @@
-+/*
-+ * misc.c
-+ *
-+ * This is a collection of several routines from gzip-1.0.3
-+ * adapted for Linux.
-+ *
-+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
-+ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
-+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
-+ */
-+
-+/*
-+ * we have to be careful, because no indirections are allowed here, and
-+ * paravirt_ops is a kind of one. As it will only run in baremetal anyway,
-+ * we just keep it from happening
-+ */
-+#undef CONFIG_PARAVIRT
-+#ifdef CONFIG_X86_64
-+#define _LINUX_STRING_H_ 1
-+#define __LINUX_BITMAP_H 1
-+#endif
-+
-+#include <linux/linkage.h>
-+#include <linux/screen_info.h>
-+#include <asm/io.h>
-+#include <asm/page.h>
-+#include <asm/boot.h>
-+
-+/* WARNING!!
-+ * This code is compiled with -fPIC and it is relocated dynamically
-+ * at run time, but no relocation processing is performed.
-+ * This means that it is not safe to place pointers in static structures.
-+ */
+-void save_registers(int pid, struct uml_pt_regs *regs)
++int save_registers(int pid, struct uml_pt_regs *regs)
+ {
+ 	int err;
+ 
+ 	err = ptrace(PTRACE_GETREGS, pid, 0, regs->gp);
+ 	if (err < 0)
+-		panic("save_registers - saving registers failed, errno = %d\n",
+-		      errno);
++		return -errno;
++	return 0;
+ }
+ 
+-void restore_registers(int pid, struct uml_pt_regs *regs)
++int restore_registers(int pid, struct uml_pt_regs *regs)
+ {
+ 	int err;
+ 
+ 	err = ptrace(PTRACE_SETREGS, pid, 0, regs->gp);
+ 	if (err < 0)
+-		panic("restore_registers - saving registers failed, "
+-		      "errno = %d\n", errno);
++		return -errno;
++	return 0;
+ }
+ 
+-void init_registers(int pid)
++/* This is set once at boot time and not changed thereafter */
 +
-+/*
-+ * Getting to provable safe in place decompression is hard.
-+ * Worst case behaviours need to be analyzed.
-+ * Background information:
-+ *
-+ * The file layout is:
-+ *    magic[2]
-+ *    method[1]
-+ *    flags[1]
-+ *    timestamp[4]
-+ *    extraflags[1]
-+ *    os[1]
-+ *    compressed data blocks[N]
-+ *    crc[4] orig_len[4]
-+ *
-+ * resulting in 18 bytes of non compressed data overhead.
-+ *
-+ * Files divided into blocks
-+ * 1 bit (last block flag)
-+ * 2 bits (block type)
-+ *
-+ * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
-+ * The smallest block type encoding is always used.
-+ *
-+ * stored:
-+ *    32 bits length in bytes.
-+ *
-+ * fixed:
-+ *    magic fixed tree.
-+ *    symbols.
-+ *
-+ * dynamic:
-+ *    dynamic tree encoding.
-+ *    symbols.
-+ *
-+ *
-+ * The buffer for decompression in place is the length of the
-+ * uncompressed data, plus a small amount extra to keep the algorithm safe.
-+ * The compressed data is placed at the end of the buffer.  The output
-+ * pointer is placed at the start of the buffer and the input pointer
-+ * is placed where the compressed data starts.  Problems will occur
-+ * when the output pointer overruns the input pointer.
-+ *
-+ * The output pointer can only overrun the input pointer if the input
-+ * pointer is moving faster than the output pointer.  A condition only
-+ * triggered by data whose compressed form is larger than the uncompressed
-+ * form.
-+ *
-+ * The worst case at the block level is a growth of the compressed data
-+ * of 5 bytes per 32767 bytes.
-+ *
-+ * The worst case internal to a compressed block is very hard to figure.
-+ * The worst case can at least be boundined by having one bit that represents
-+ * 32764 bytes and then all of the rest of the bytes representing the very
-+ * very last byte.
-+ *
-+ * All of which is enough to compute an amount of extra data that is required
-+ * to be safe.  To avoid problems at the block level allocating 5 extra bytes
-+ * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
-+ * adding an extra 32767 bytes (the worst case uncompressed block size) is
-+ * sufficient, to ensure that in the worst case the decompressed data for
-+ * block will stop the byte before the compressed data for a block begins.
-+ * To avoid problems with the compressed data's meta information an extra 18
-+ * bytes are needed.  Leading to the formula:
-+ *
-+ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
-+ *
-+ * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
-+ * Adding 32768 instead of 32767 just makes for round numbers.
-+ * Adding the decompressor_size is necessary as it musht live after all
-+ * of the data as well.  Last I measured the decompressor is about 14K.
-+ * 10K of actual data and 4K of bss.
-+ *
-+ */
++static unsigned long exec_regs[MAX_REG_NR];
 +
++int init_registers(int pid)
+ {
+ 	int err;
+ 
+ 	err = ptrace(PTRACE_GETREGS, pid, 0, exec_regs);
+-	if (err)
+-		panic("check_ptrace : PTRACE_GETREGS failed, errno = %d",
+-		      errno);
++	if (err < 0)
++		return -errno;
+ 
+ 	arch_init_registers(pid);
++	return 0;
+ }
+ 
+ void get_safe_registers(unsigned long *regs)
+diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
+index dc03e9c..abf47a7 100644
+--- a/arch/um/os-Linux/sigio.c
++++ b/arch/um/os-Linux/sigio.c
+@@ -1,34 +1,33 @@
+ /*
+- * Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+ #include <unistd.h>
+-#include <stdlib.h>
+-#include <termios.h>
++#include <errno.h>
++#include <fcntl.h>
++#include <poll.h>
+ #include <pty.h>
++#include <sched.h>
+ #include <signal.h>
+-#include <fcntl.h>
+-#include <errno.h>
+ #include <string.h>
+-#include <sched.h>
+-#include <sys/socket.h>
+-#include <sys/poll.h>
+-#include "init.h"
+-#include "user.h"
++#include "kern_constants.h"
+ #include "kern_util.h"
+-#include "sigio.h"
++#include "init.h"
+ #include "os.h"
++#include "sigio.h"
+ #include "um_malloc.h"
+-#include "init.h"
++#include "user.h"
+ 
+-/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
++/*
++ * Protected by sigio_lock(), also used by sigio_cleanup, which is an
+  * exitcall.
+  */
+ static int write_sigio_pid = -1;
+ static unsigned long write_sigio_stack;
+ 
+-/* These arrays are initialized before the sigio thread is started, and
++/*
++ * These arrays are initialized before the sigio thread is started, and
+  * the descriptors closed after it is killed.  So, it can't see them change.
+  * On the UML side, they are changed under the sigio_lock.
+  */
+@@ -43,7 +42,8 @@ struct pollfds {
+ 	int used;
+ };
+ 
+-/* Protected by sigio_lock().  Used by the sigio thread, but the UML thread
 +/*
-+ * gzip declarations
-+ */
-+
-+#define OF(args)  args
-+#define STATIC static
-+
-+#undef memset
-+#undef memcpy
-+#define memzero(s, n)     memset ((s), 0, (n))
-+
-+typedef unsigned char  uch;
-+typedef unsigned short ush;
-+typedef unsigned long  ulg;
-+
-+#define WSIZE 0x80000000	/* Window size must be at least 32k,
-+				 * and a power of two
-+				 * We don't actually have a window just
-+				 * a huge output buffer so I report
-+				 * a 2G windows size, as that should
-+				 * always be larger than our output buffer.
-+				 */
-+
-+static uch *inbuf;	/* input buffer */
-+static uch *window;	/* Sliding window buffer, (and final output buffer) */
-+
-+static unsigned insize;  /* valid bytes in inbuf */
-+static unsigned inptr;   /* index of next byte to be processed in inbuf */
-+static unsigned outcnt;  /* bytes in output buffer */
-+
-+/* gzip flag byte */
-+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
-+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
-+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
-+#define COMMENT      0x10 /* bit 4 set: file comment present */
-+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
-+#define RESERVED     0xC0 /* bit 6,7:   reserved */
-+
-+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
-+		
-+/* Diagnostic functions */
-+#ifdef DEBUG
-+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
-+#  define Trace(x) fprintf x
-+#  define Tracev(x) {if (verbose) fprintf x ;}
-+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
-+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
-+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
-+#else
-+#  define Assert(cond,msg)
-+#  define Trace(x)
-+#  define Tracev(x)
-+#  define Tracevv(x)
-+#  define Tracec(c,x)
-+#  define Tracecv(c,x)
-+#endif
-+
-+static int  fill_inbuf(void);
-+static void flush_window(void);
-+static void error(char *m);
-+static void gzip_mark(void **);
-+static void gzip_release(void **);
-+  
++ * Protected by sigio_lock().  Used by the sigio thread, but the UML thread
+  * synchronizes with it.
+  */
+ static struct pollfds current_poll;
+@@ -57,23 +57,26 @@ static int write_sigio_thread(void *unused)
+ 	int i, n, respond_fd;
+ 	char c;
+ 
+-        signal(SIGWINCH, SIG_IGN);
++	signal(SIGWINCH, SIG_IGN);
+ 	fds = &current_poll;
+-	while(1){
++	while (1) {
+ 		n = poll(fds->poll, fds->used, -1);
+-		if(n < 0){
+-			if(errno == EINTR) continue;
+-			printk("write_sigio_thread : poll returned %d, "
+-			       "errno = %d\n", n, errno);
++		if (n < 0) {
++			if (errno == EINTR)
++				continue;
++			printk(UM_KERN_ERR "write_sigio_thread : poll returned "
++			       "%d, errno = %d\n", n, errno);
+ 		}
+-		for(i = 0; i < fds->used; i++){
++		for (i = 0; i < fds->used; i++) {
+ 			p = &fds->poll[i];
+-			if(p->revents == 0) continue;
+-			if(p->fd == sigio_private[1]){
++			if (p->revents == 0)
++				continue;
++			if (p->fd == sigio_private[1]) {
+ 				CATCH_EINTR(n = read(sigio_private[1], &c,
+ 						     sizeof(c)));
+-				if(n != sizeof(c))
+-					printk("write_sigio_thread : "
++				if (n != sizeof(c))
++					printk(UM_KERN_ERR
++					       "write_sigio_thread : "
+ 					       "read on socket failed, "
+ 					       "err = %d\n", errno);
+ 				tmp = current_poll;
+@@ -89,9 +92,10 @@ static int write_sigio_thread(void *unused)
+ 			}
+ 
+ 			CATCH_EINTR(n = write(respond_fd, &c, sizeof(c)));
+-			if(n != sizeof(c))
+-				printk("write_sigio_thread : write on socket "
+-				       "failed, err = %d\n", errno);
++			if (n != sizeof(c))
++				printk(UM_KERN_ERR "write_sigio_thread : "
++				       "write on socket failed, err = %d\n",
++				       errno);
+ 		}
+ 	}
+ 
+@@ -102,12 +106,13 @@ static int need_poll(struct pollfds *polls, int n)
+ {
+ 	struct pollfd *new;
+ 
+-	if(n <= polls->size)
++	if (n <= polls->size)
+ 		return 0;
+ 
+ 	new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC);
+-	if(new == NULL){
+-		printk("need_poll : failed to allocate new pollfds\n");
++	if (new == NULL) {
++		printk(UM_KERN_ERR "need_poll : failed to allocate new "
++		       "pollfds\n");
+ 		return -ENOMEM;
+ 	}
+ 
+@@ -119,7 +124,8 @@ static int need_poll(struct pollfds *polls, int n)
+ 	return 0;
+ }
+ 
+-/* Must be called with sigio_lock held, because it's needed by the marked
 +/*
-+ * This is set up by the setup-routine at boot-time
-+ */
-+static unsigned char *real_mode; /* Pointer to real-mode data */
-+
-+#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
-+#ifndef STANDARD_MEMORY_BIOS_CALL
-+#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
-+#endif
-+#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
-+
-+extern unsigned char input_data[];
-+extern int input_len;
-+
-+static long bytes_out = 0;
-+
-+static void *malloc(int size);
-+static void free(void *where);
-+
-+static void *memset(void *s, int c, unsigned n);
-+static void *memcpy(void *dest, const void *src, unsigned n);
-+
-+static void putstr(const char *);
-+
-+#ifdef CONFIG_X86_64
-+#define memptr long
-+#else
-+#define memptr unsigned
-+#endif
-+
-+static memptr free_mem_ptr;
-+static memptr free_mem_end_ptr;
-+
-+#ifdef CONFIG_X86_64
-+#define HEAP_SIZE             0x7000
-+#else
-+#define HEAP_SIZE             0x4000
-+#endif
-+
-+static char *vidmem = (char *)0xb8000;
-+static int vidport;
-+static int lines, cols;
-+
-+#ifdef CONFIG_X86_NUMAQ
-+void *xquad_portio;
-+#endif
-+
-+#include "../../../../lib/inflate.c"
-+
-+static void *malloc(int size)
-+{
-+	void *p;
-+
-+	if (size <0) error("Malloc error");
-+	if (free_mem_ptr <= 0) error("Memory error");
-+
-+	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
-+
-+	p = (void *)free_mem_ptr;
-+	free_mem_ptr += size;
-+
-+	if (free_mem_ptr >= free_mem_end_ptr)
-+		error("Out of memory");
-+
-+	return p;
-+}
-+
-+static void free(void *where)
-+{	/* Don't care */
-+}
-+
-+static void gzip_mark(void **ptr)
-+{
-+	*ptr = (void *) free_mem_ptr;
-+}
++ * Must be called with sigio_lock held, because it's needed by the marked
+  * critical section.
+  */
+ static void update_thread(void)
+@@ -129,15 +135,17 @@ static void update_thread(void)
+ 	char c;
+ 
+ 	flags = set_signals(0);
+-	n = write(sigio_private[0], &c, sizeof(c));
+-	if(n != sizeof(c)){
+-		printk("update_thread : write failed, err = %d\n", errno);
++	CATCH_EINTR(n = write(sigio_private[0], &c, sizeof(c)));
++	if (n != sizeof(c)) {
++		printk(UM_KERN_ERR "update_thread : write failed, err = %d\n",
++		       errno);
+ 		goto fail;
+ 	}
+ 
+ 	CATCH_EINTR(n = read(sigio_private[0], &c, sizeof(c)));
+-	if(n != sizeof(c)){
+-		printk("update_thread : read failed, err = %d\n", errno);
++	if (n != sizeof(c)) {
++		printk(UM_KERN_ERR "update_thread : read failed, err = %d\n",
++		       errno);
+ 		goto fail;
+ 	}
+ 
+@@ -164,23 +172,23 @@ int add_sigio_fd(int fd)
+ 	int err = 0, i, n;
+ 
+ 	sigio_lock();
+-	for(i = 0; i < all_sigio_fds.used; i++){
+-		if(all_sigio_fds.poll[i].fd == fd)
++	for (i = 0; i < all_sigio_fds.used; i++) {
++		if (all_sigio_fds.poll[i].fd == fd)
+ 			break;
+ 	}
+-	if(i == all_sigio_fds.used)
++	if (i == all_sigio_fds.used)
+ 		goto out;
+ 
+ 	p = &all_sigio_fds.poll[i];
+ 
+-	for(i = 0; i < current_poll.used; i++){
+-		if(current_poll.poll[i].fd == fd)
++	for (i = 0; i < current_poll.used; i++) {
++		if (current_poll.poll[i].fd == fd)
+ 			goto out;
+ 	}
+ 
+ 	n = current_poll.used;
+ 	err = need_poll(&next_poll, n + 1);
+-	if(err)
++	if (err)
+ 		goto out;
+ 
+ 	memcpy(next_poll.poll, current_poll.poll,
+@@ -198,27 +206,29 @@ int ignore_sigio_fd(int fd)
+ 	struct pollfd *p;
+ 	int err = 0, i, n = 0;
+ 
+-	/* This is called from exitcalls elsewhere in UML - if
++	/*
++	 * This is called from exitcalls elsewhere in UML - if
+ 	 * sigio_cleanup has already run, then update_thread will hang
+ 	 * or fail because the thread is no longer running.
+ 	 */
+-	if(write_sigio_pid == -1)
++	if (write_sigio_pid == -1)
+ 		return -EIO;
+ 
+ 	sigio_lock();
+-	for(i = 0; i < current_poll.used; i++){
+-		if(current_poll.poll[i].fd == fd) break;
++	for (i = 0; i < current_poll.used; i++) {
++		if (current_poll.poll[i].fd == fd)
++			break;
+ 	}
+-	if(i == current_poll.used)
++	if (i == current_poll.used)
+ 		goto out;
+ 
+ 	err = need_poll(&next_poll, current_poll.used - 1);
+-	if(err)
++	if (err)
+ 		goto out;
+ 
+-	for(i = 0; i < current_poll.used; i++){
++	for (i = 0; i < current_poll.used; i++) {
+ 		p = &current_poll.poll[i];
+-		if(p->fd != fd)
++		if (p->fd != fd)
+ 			next_poll.poll[n++] = *p;
+ 	}
+ 	next_poll.used = current_poll.used - 1;
+@@ -235,7 +245,8 @@ static struct pollfd *setup_initial_poll(int fd)
+ 
+ 	p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL);
+ 	if (p == NULL) {
+-		printk("setup_initial_poll : failed to allocate poll\n");
++		printk(UM_KERN_ERR "setup_initial_poll : failed to allocate "
++		       "poll\n");
+ 		return NULL;
+ 	}
+ 	*p = ((struct pollfd) { .fd		= fd,
+@@ -261,27 +272,29 @@ static void write_sigio_workaround(void)
+ 		return;
+ 
+ 	err = os_pipe(l_write_sigio_fds, 1, 1);
+-	if(err < 0){
+-		printk("write_sigio_workaround - os_pipe 1 failed, "
++	if (err < 0) {
++		printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 1 failed, "
+ 		       "err = %d\n", -err);
+ 		return;
+ 	}
+ 	err = os_pipe(l_sigio_private, 1, 1);
+-	if(err < 0){
+-		printk("write_sigio_workaround - os_pipe 2 failed, "
++	if (err < 0) {
++		printk(UM_KERN_ERR "write_sigio_workaround - os_pipe 2 failed, "
+ 		       "err = %d\n", -err);
+ 		goto out_close1;
+ 	}
+ 
+ 	p = setup_initial_poll(l_sigio_private[1]);
+-	if(!p)
++	if (!p)
+ 		goto out_close2;
+ 
+ 	sigio_lock();
+ 
+-	/* Did we race? Don't try to optimize this, please, it's not so likely
+-	 * to happen, and no more than once at the boot. */
+-	if(write_sigio_pid != -1)
++	/*
++	 * Did we race? Don't try to optimize this, please, it's not so likely
++	 * to happen, and no more than once at the boot.
++	 */
++	if (write_sigio_pid != -1)
+ 		goto out_free;
+ 
+ 	current_poll = ((struct pollfds) { .poll 	= p,
+@@ -333,19 +346,19 @@ void maybe_sigio_broken(int fd, int read)
+ {
+ 	int err;
+ 
+-	if(!isatty(fd))
++	if (!isatty(fd))
+ 		return;
+ 
+-	if((read || pty_output_sigio) && (!read || pty_close_sigio))
++	if ((read || pty_output_sigio) && (!read || pty_close_sigio))
+ 		return;
+ 
+ 	write_sigio_workaround();
+ 
+ 	sigio_lock();
+ 	err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
+-	if(err){
+-		printk("maybe_sigio_broken - failed to add pollfd for "
+-		       "descriptor %d\n", fd);
++	if (err) {
++		printk(UM_KERN_ERR "maybe_sigio_broken - failed to add pollfd "
++		       "for descriptor %d\n", fd);
+ 		goto out;
+ 	}
+ 
+@@ -388,7 +401,7 @@ static void openpty_cb(void *arg)
+ 	struct openpty_arg *info = arg;
+ 
+ 	info->err = 0;
+-	if(openpty(&info->master, &info->slave, NULL, NULL, NULL))
++	if (openpty(&info->master, &info->slave, NULL, NULL, NULL))
+ 		info->err = -errno;
+ }
+ 
+@@ -397,17 +410,17 @@ static int async_pty(int master, int slave)
+ 	int flags;
+ 
+ 	flags = fcntl(master, F_GETFL);
+-	if(flags < 0)
++	if (flags < 0)
+ 		return -errno;
+ 
+-	if((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
+-	   (fcntl(master, F_SETOWN, os_getpid()) < 0))
++	if ((fcntl(master, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0) ||
++	    (fcntl(master, F_SETOWN, os_getpid()) < 0))
+ 		return -errno;
+ 
+-	if((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
++	if ((fcntl(slave, F_SETFL, flags | O_NONBLOCK) < 0))
+ 		return -errno;
+ 
+-	return(0);
++	return 0;
+ }
+ 
+ static void __init check_one_sigio(void (*proc)(int, int))
+@@ -417,34 +430,49 @@ static void __init check_one_sigio(void (*proc)(int, int))
+ 	int master, slave, err;
+ 
+ 	initial_thread_cb(openpty_cb, &pty);
+-	if(pty.err){
+-		printk("openpty failed, errno = %d\n", -pty.err);
++	if (pty.err) {
++		printk(UM_KERN_ERR "check_one_sigio failed, errno = %d\n",
++		       -pty.err);
+ 		return;
+ 	}
+ 
+ 	master = pty.master;
+ 	slave = pty.slave;
+ 
+-	if((master == -1) || (slave == -1)){
+-		printk("openpty failed to allocate a pty\n");
++	if ((master == -1) || (slave == -1)) {
++		printk(UM_KERN_ERR "check_one_sigio failed to allocate a "
++		       "pty\n");
+ 		return;
+ 	}
+ 
+ 	/* Not now, but complain so we now where we failed. */
+ 	err = raw(master);
+-	if (err < 0)
+-		panic("check_sigio : __raw failed, errno = %d\n", -err);
++	if (err < 0) {
++		printk(UM_KERN_ERR "check_one_sigio : raw failed, errno = %d\n",
++		      -err);
++		return;
++	}
+ 
+ 	err = async_pty(master, slave);
+-	if(err < 0)
+-		panic("tty_fds : sigio_async failed, err = %d\n", -err);
++	if (err < 0) {
++		printk(UM_KERN_ERR "check_one_sigio : sigio_async failed, "
++		       "err = %d\n", -err);
++		return;
++	}
 +
-+static void gzip_release(void **ptr)
-+{
-+	free_mem_ptr = (memptr) *ptr;
-+}
-+ 
-+static void scroll(void)
-+{
-+	int i;
++	if (sigaction(SIGIO, NULL, &old) < 0) {
++		printk(UM_KERN_ERR "check_one_sigio : sigaction 1 failed, "
++		       "errno = %d\n", errno);
++		return;
++	}
+ 
+-	if(sigaction(SIGIO, NULL, &old) < 0)
+-		panic("check_sigio : sigaction 1 failed, errno = %d\n", errno);
+ 	new = old;
+ 	new.sa_handler = handler;
+-	if(sigaction(SIGIO, &new, NULL) < 0)
+-		panic("check_sigio : sigaction 2 failed, errno = %d\n", errno);
++	if (sigaction(SIGIO, &new, NULL) < 0) {
++		printk(UM_KERN_ERR "check_one_sigio : sigaction 2 failed, "
++		       "errno = %d\n", errno);
++		return;
++	}
+ 
+ 	got_sigio = 0;
+ 	(*proc)(master, slave);
+@@ -452,8 +480,9 @@ static void __init check_one_sigio(void (*proc)(int, int))
+ 	close(master);
+ 	close(slave);
+ 
+-	if(sigaction(SIGIO, &old, NULL) < 0)
+-		panic("check_sigio : sigaction 3 failed, errno = %d\n", errno);
++	if (sigaction(SIGIO, &old, NULL) < 0)
++		printk(UM_KERN_ERR "check_one_sigio : sigaction 3 failed, "
++		       "errno = %d\n", errno);
+ }
+ 
+ static void tty_output(int master, int slave)
+@@ -461,42 +490,45 @@ static void tty_output(int master, int slave)
+ 	int n;
+ 	char buf[512];
+ 
+-	printk("Checking that host ptys support output SIGIO...");
++	printk(UM_KERN_INFO "Checking that host ptys support output SIGIO...");
+ 
+ 	memset(buf, 0, sizeof(buf));
+ 
+-	while(write(master, buf, sizeof(buf)) > 0) ;
+-	if(errno != EAGAIN)
+-		panic("tty_output : write failed, errno = %d\n", errno);
+-	while(((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) ;
++	while (write(master, buf, sizeof(buf)) > 0) ;
++	if (errno != EAGAIN)
++		printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n",
++		       errno);
++	while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio)
++		;
+ 
+-	if(got_sigio){
+-		printk("Yes\n");
++	if (got_sigio) {
++		printk(UM_KERN_CONT "Yes\n");
+ 		pty_output_sigio = 1;
+-	}
+-	else if(n == -EAGAIN)
+-		printk("No, enabling workaround\n");
+-	else panic("tty_output : read failed, err = %d\n", n);
++	} else if (n == -EAGAIN)
++		printk(UM_KERN_CONT "No, enabling workaround\n");
++	else
++		printk(UM_KERN_CONT "tty_output : read failed, err = %d\n", n);
+ }
+ 
+ static void tty_close(int master, int slave)
+ {
+-	printk("Checking that host ptys support SIGIO on close...");
++	printk(UM_KERN_INFO "Checking that host ptys support SIGIO on "
++	       "close...");
+ 
+ 	close(slave);
+-	if(got_sigio){
+-		printk("Yes\n");
++	if (got_sigio) {
++		printk(UM_KERN_CONT "Yes\n");
+ 		pty_close_sigio = 1;
+-	}
+-	else printk("No, enabling workaround\n");
++	} else
++		printk(UM_KERN_CONT "No, enabling workaround\n");
+ }
+ 
+ void __init check_sigio(void)
+ {
+-	if((os_access("/dev/ptmx", OS_ACC_R_OK) < 0) &&
+-	   (os_access("/dev/ptyp0", OS_ACC_R_OK) < 0)){
+-		printk("No pseudo-terminals available - skipping pty SIGIO "
+-		       "check\n");
++	if ((access("/dev/ptmx", R_OK) < 0) &&
++	    (access("/dev/ptyp0", R_OK) < 0)) {
++		printk(UM_KERN_WARNING "No pseudo-terminals available - "
++		       "skipping pty SIGIO check\n");
+ 		return;
+ 	}
+ 	check_one_sigio(tty_output);
+diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
+index e9800b0..0fb0cc8 100644
+--- a/arch/um/os-Linux/signal.c
++++ b/arch/um/os-Linux/signal.c
+@@ -9,11 +9,47 @@
+ #include <errno.h>
+ #include <signal.h>
+ #include <strings.h>
++#include "as-layout.h"
++#include "kern_util.h"
+ #include "os.h"
+ #include "sysdep/barrier.h"
+ #include "sysdep/sigcontext.h"
+ #include "user.h"
+ 
++/* Copied from linux/compiler-gcc.h since we can't include it directly */
++#define barrier() __asm__ __volatile__("": : :"memory")
 +
-+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
-+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
-+		vidmem[i] = ' ';
-+}
++void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
++	[SIGTRAP]	= relay_signal,
++	[SIGFPE]	= relay_signal,
++	[SIGILL]	= relay_signal,
++	[SIGWINCH]	= winch,
++	[SIGBUS]	= bus_handler,
++	[SIGSEGV]	= segv_handler,
++	[SIGIO]		= sigio_handler,
++	[SIGVTALRM]	= timer_handler };
 +
-+static void putstr(const char *s)
++static void sig_handler_common(int sig, struct sigcontext *sc)
 +{
-+	int x,y,pos;
-+	char c;
-+
-+#ifdef CONFIG_X86_32
-+	if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
-+		return;
-+#endif
++	struct uml_pt_regs r;
++	int save_errno = errno;
 +
-+	x = RM_SCREEN_INFO.orig_x;
-+	y = RM_SCREEN_INFO.orig_y;
-+
-+	while ( ( c = *s++ ) != '\0' ) {
-+		if ( c == '\n' ) {
-+			x = 0;
-+			if ( ++y >= lines ) {
-+				scroll();
-+				y--;
-+			}
-+		} else {
-+			vidmem [(x + cols * y) * 2] = c;
-+			if ( ++x >= cols ) {
-+				x = 0;
-+				if ( ++y >= lines ) {
-+					scroll();
-+					y--;
-+				}
-+			}
-+		}
++	r.is_user = 0;
++	if (sig == SIGSEGV) {
++		/* For segfaults, we want the data from the sigcontext. */
++		copy_sc(&r, sc);
++		GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
 +	}
 +
-+	RM_SCREEN_INFO.orig_x = x;
-+	RM_SCREEN_INFO.orig_y = y;
-+
-+	pos = (x + cols * y) * 2;	/* Update cursor position */
-+	outb(14, vidport);
-+	outb(0xff & (pos >> 9), vidport+1);
-+	outb(15, vidport);
-+	outb(0xff & (pos >> 1), vidport+1);
-+}
++	/* enable signals if sig isn't IRQ signal */
++	if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
++		unblock_signals();
 +
-+static void* memset(void* s, int c, unsigned n)
-+{
-+	int i;
-+	char *ss = s;
++	(*sig_info[sig])(sig, &r);
 +
-+	for (i=0;i<n;i++) ss[i] = c;
-+	return s;
++	errno = save_errno;
 +}
 +
-+static void* memcpy(void* dest, const void* src, unsigned n)
-+{
-+	int i;
-+	const char *s = src;
-+	char *d = dest;
+ /*
+  * These are the asynchronous signals.  SIGPROF is excluded because we want to
+  * be able to profile all of UML, not just the non-critical sections.  If
+@@ -26,13 +62,8 @@
+ #define SIGVTALRM_BIT 1
+ #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
+ 
+-/*
+- * These are used by both the signal handlers and
+- * block/unblock_signals.  I don't want modifications cached in a
+- * register - they must go straight to memory.
+- */
+-static volatile int signals_enabled = 1;
+-static volatile int pending = 0;
++static int signals_enabled;
++static unsigned int signals_pending;
+ 
+ void sig_handler(int sig, struct sigcontext *sc)
+ {
+@@ -40,13 +71,13 @@ void sig_handler(int sig, struct sigcontext *sc)
+ 
+ 	enabled = signals_enabled;
+ 	if (!enabled && (sig == SIGIO)) {
+-		pending |= SIGIO_MASK;
++		signals_pending |= SIGIO_MASK;
+ 		return;
+ 	}
+ 
+ 	block_signals();
+ 
+-	sig_handler_common_skas(sig, sc);
++	sig_handler_common(sig, sc);
+ 
+ 	set_signals(enabled);
+ }
+@@ -68,7 +99,7 @@ void alarm_handler(int sig, struct sigcontext *sc)
+ 
+ 	enabled = signals_enabled;
+ 	if (!signals_enabled) {
+-		pending |= SIGVTALRM_MASK;
++		signals_pending |= SIGVTALRM_MASK;
+ 		return;
+ 	}
+ 
+@@ -94,16 +125,6 @@ void set_sigstack(void *sig_stack, int size)
+ 		panic("enabling signal stack failed, errno = %d\n", errno);
+ }
+ 
+-void remove_sigstack(void)
+-{
+-	stack_t stack = ((stack_t) { .ss_flags	= SS_DISABLE,
+-				     .ss_sp	= NULL,
+-				     .ss_size	= 0 });
+-
+-	if (sigaltstack(&stack, NULL) != 0)
+-		panic("disabling signal stack failed, errno = %d\n", errno);
+-}
+-
+ void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+ 
+ void handle_signal(int sig, struct sigcontext *sc)
+@@ -166,6 +187,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
+ 		sigaddset(&action.sa_mask, mask);
+ 	va_end(ap);
+ 
++	if (sig == SIGSEGV)
++		flags |= SA_NODEFER;
 +
-+	for (i=0;i<n;i++) d[i] = s[i];
-+	return dest;
-+}
+ 	action.sa_flags = flags;
+ 	action.sa_restorer = NULL;
+ 	if (sigaction(sig, &action, NULL) < 0)
+@@ -179,12 +203,14 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
+ 
+ int change_sig(int signal, int on)
+ {
+-	sigset_t sigset, old;
++	sigset_t sigset;
+ 
+ 	sigemptyset(&sigset);
+ 	sigaddset(&sigset, signal);
+-	sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
+-	return !sigismember(&old, signal);
++	if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
++		return -errno;
 +
-+/* ===========================================================================
-+ * Fill the input buffer. This is called only when the buffer is empty
-+ * and at least one byte is really needed.
-+ */
-+static int fill_inbuf(void)
-+{
-+	error("ran out of input data");
 +	return 0;
-+}
+ }
+ 
+ void block_signals(void)
+@@ -196,7 +222,7 @@ void block_signals(void)
+ 	 * This might matter if gcc figures out how to inline this and
+ 	 * decides to shuffle this code into the caller.
+ 	 */
+-	mb();
++	barrier();
+ }
+ 
+ void unblock_signals(void)
+@@ -209,36 +235,26 @@ void unblock_signals(void)
+ 	/*
+ 	 * We loop because the IRQ handler returns with interrupts off.  So,
+ 	 * interrupts may have arrived and we need to re-enable them and
+-	 * recheck pending.
++	 * recheck signals_pending.
+ 	 */
+ 	while(1) {
+ 		/*
+ 		 * Save and reset save_pending after enabling signals.  This
+-		 * way, pending won't be changed while we're reading it.
++		 * way, signals_pending won't be changed while we're reading it.
+ 		 */
+ 		signals_enabled = 1;
+ 
+ 		/*
+-		 * Setting signals_enabled and reading pending must
++		 * Setting signals_enabled and reading signals_pending must
+ 		 * happen in this order.
+ 		 */
+-		mb();
+-
+-		save_pending = pending;
+-		if (save_pending == 0) {
+-			/*
+-			 * This must return with signals enabled, so
+-			 * this barrier ensures that writes are
+-			 * flushed out before the return.  This might
+-			 * matter if gcc figures out how to inline
+-			 * this (unlikely, given its size) and decides
+-			 * to shuffle this code into the caller.
+-			 */
+-			mb();
++		barrier();
 +
-+/* ===========================================================================
-+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
-+ * (Used for the decompressed data only.)
-+ */
-+static void flush_window(void)
-+{
-+	/* With my window equal to my output buffer
-+	 * I only need to compute the crc here.
-+	 */
-+	ulg c = crc;         /* temporary variable */
-+	unsigned n;
-+	uch *in, ch;
++		save_pending = signals_pending;
++		if (save_pending == 0)
+ 			return;
+-		}
+ 
+-		pending = 0;
++		signals_pending = 0;
+ 
+ 		/*
+ 		 * We have pending interrupts, so disable signals, as the
+@@ -254,7 +270,7 @@ void unblock_signals(void)
+ 		 * back here.
+ 		 */
+ 		if (save_pending & SIGIO_MASK)
+-			sig_handler_common_skas(SIGIO, NULL);
++			sig_handler_common(SIGIO, NULL);
+ 
+ 		if (save_pending & SIGVTALRM_MASK)
+ 			real_alarm_handler(NULL);
+diff --git a/arch/um/os-Linux/skas/Makefile b/arch/um/os-Linux/skas/Makefile
+index 5fd8d4d..d2ea340 100644
+--- a/arch/um/os-Linux/skas/Makefile
++++ b/arch/um/os-Linux/skas/Makefile
+@@ -1,10 +1,10 @@
+ #
+-# Copyright (C) 2002 - 2004 Jeff Dike (jdike at addtoit.com)
++# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
+ # Licensed under the GPL
+ #
+ 
+-obj-y := mem.o process.o trap.o
++obj-y := mem.o process.o
+ 
+-USER_OBJS := mem.o process.o trap.o
++USER_OBJS := $(obj-y)
+ 
+ include arch/um/scripts/Makefile.rules
+diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
+index e8b7a97..d36c89c 100644
+--- a/arch/um/os-Linux/skas/process.c
++++ b/arch/um/os-Linux/skas/process.c
+@@ -15,6 +15,7 @@
+ #include "as-layout.h"
+ #include "chan_user.h"
+ #include "kern_constants.h"
++#include "kern_util.h"
+ #include "mem.h"
+ #include "os.h"
+ #include "process.h"
+@@ -37,27 +38,27 @@ int is_skas_winch(int pid, int fd, void *data)
+ 
+ static int ptrace_dump_regs(int pid)
+ {
+-        unsigned long regs[MAX_REG_NR];
+-        int i;
++	unsigned long regs[MAX_REG_NR];
++	int i;
+ 
+-        if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
+-                return -errno;
++	if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
++		return -errno;
+ 
+ 	printk(UM_KERN_ERR "Stub registers -\n");
+ 	for (i = 0; i < ARRAY_SIZE(regs); i++)
+ 		printk(UM_KERN_ERR "\t%d - %lx\n", i, regs[i]);
+ 
+-        return 0;
++	return 0;
+ }
+ 
+ /*
+  * Signals that are OK to receive in the stub - we'll just continue it.
+  * SIGWINCH will happen when UML is inside a detached screen.
+  */
+-#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
++#define STUB_SIG_MASK (1 << SIGVTALRM)
+ 
+ /* Signals that the stub will finish with - anything else is an error */
+-#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
++#define STUB_DONE_MASK (1 << SIGTRAP)
+ 
+ void wait_stub_done(int pid)
+ {
+@@ -72,9 +73,11 @@ void wait_stub_done(int pid)
+ 			break;
+ 
+ 		err = ptrace(PTRACE_CONT, pid, 0, 0);
+-		if (err)
+-			panic("wait_stub_done : continue failed, errno = %d\n",
+-			      errno);
++		if (err) {
++			printk(UM_KERN_ERR "wait_stub_done : continue failed, "
++			       "errno = %d\n", errno);
++			fatal_sigsegv();
++		}
+ 	}
+ 
+ 	if (((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
+@@ -85,8 +88,10 @@ bad_wait:
+ 	if (err)
+ 		printk(UM_KERN_ERR "Failed to get registers from stub, "
+ 		       "errno = %d\n", -err);
+-	panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
+-	      "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
++	printk(UM_KERN_ERR "wait_stub_done : failed to wait for SIGTRAP, "
++	       "pid = %d, n = %d, errno = %d, status = 0x%x\n", pid, n, errno,
++	       status);
++	fatal_sigsegv();
+ }
+ 
+ extern unsigned long current_stub_stack(void);
+@@ -97,9 +102,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
+ 
+ 	if (ptrace_faultinfo) {
+ 		err = ptrace(PTRACE_FAULTINFO, pid, 0, fi);
+-		if (err)
+-			panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, "
+-			      "errno = %d\n", errno);
++		if (err) {
++			printk(UM_KERN_ERR "get_skas_faultinfo - "
++			       "PTRACE_FAULTINFO failed, errno = %d\n", errno);
++			fatal_sigsegv();
++		}
+ 
+ 		/* Special handling for i386, which has different structs */
+ 		if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo))
+@@ -109,9 +116,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
+ 	}
+ 	else {
+ 		err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
+-		if (err)
+-			panic("Failed to continue stub, pid = %d, errno = %d\n",
+-			      pid, errno);
++		if (err) {
++			printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
++			       "errno = %d\n", pid, errno);
++			fatal_sigsegv();
++		}
+ 		wait_stub_done(pid);
+ 
+ 		/*
+@@ -137,6 +146,9 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
+ {
+ 	int err, status;
+ 
++	if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
++		fatal_sigsegv();
 +
-+	in = window;
-+	for (n = 0; n < outcnt; n++) {
-+		ch = *in++;
-+		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+ 	/* Mark this as a syscall */
+ 	UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
+ 
+@@ -144,25 +156,31 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
+ 	{
+ 		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
+ 			     __NR_getpid);
+-		if (err < 0)
+-			panic("handle_trap - nullifying syscall failed, "
+-			      "errno = %d\n", errno);
++		if (err < 0) {
++			printk(UM_KERN_ERR "handle_trap - nullifying syscall "
++			       "failed, errno = %d\n", errno);
++			fatal_sigsegv();
++		}
+ 
+ 		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+-		if (err < 0)
+-			panic("handle_trap - continuing to end of syscall "
+-			      "failed, errno = %d\n", errno);
++		if (err < 0) {
++			printk(UM_KERN_ERR "handle_trap - continuing to end of "
++			       "syscall failed, errno = %d\n", errno);
++			fatal_sigsegv();
++		}
+ 
+ 		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
+ 		if ((err < 0) || !WIFSTOPPED(status) ||
+-		   (WSTOPSIG(status) != SIGTRAP + 0x80)) {
+-                        err = ptrace_dump_regs(pid);
+-                        if (err)
+-                                printk(UM_KERN_ERR "Failed to get registers "
++		    (WSTOPSIG(status) != SIGTRAP + 0x80)) {
++			err = ptrace_dump_regs(pid);
++			if (err)
++				printk(UM_KERN_ERR "Failed to get registers "
+ 				       "from process, errno = %d\n", -err);
+-			panic("handle_trap - failed to wait at end of syscall, "
+-			      "errno = %d, status = %d\n", errno, status);
+-                }
++			printk(UM_KERN_ERR "handle_trap - failed to wait at "
++			       "end of syscall, errno = %d, status = %d\n",
++			       errno, status);
++			fatal_sigsegv();
++		}
+ 	}
+ 
+ 	handle_syscall(regs);
+@@ -178,10 +196,13 @@ static int userspace_tramp(void *stack)
+ 	ptrace(PTRACE_TRACEME, 0, 0, 0);
+ 
+ 	signal(SIGTERM, SIG_DFL);
++	signal(SIGWINCH, SIG_IGN);
+ 	err = set_interval();
+-	if (err)
+-		panic("userspace_tramp - setting timer failed, errno = %d\n",
+-		      err);
++	if (err) {
++		printk(UM_KERN_ERR "userspace_tramp - setting timer failed, "
++		       "errno = %d\n", err);
++		exit(1);
++	}
+ 
+ 	if (!proc_mm) {
+ 		/*
+@@ -221,16 +242,14 @@ static int userspace_tramp(void *stack)
+ 
+ 		set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);
+ 		sigemptyset(&sa.sa_mask);
+-		sigaddset(&sa.sa_mask, SIGIO);
+-		sigaddset(&sa.sa_mask, SIGWINCH);
+-		sigaddset(&sa.sa_mask, SIGVTALRM);
+-		sigaddset(&sa.sa_mask, SIGUSR1);
+-		sa.sa_flags = SA_ONSTACK;
++		sa.sa_flags = SA_ONSTACK | SA_NODEFER;
+ 		sa.sa_handler = (void *) v;
+ 		sa.sa_restorer = NULL;
+-		if (sigaction(SIGSEGV, &sa, NULL) < 0)
+-			panic("userspace_tramp - setting SIGSEGV handler "
+-			      "failed - errno = %d\n", errno);
++		if (sigaction(SIGSEGV, &sa, NULL) < 0) {
++			printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV "
++			       "handler failed - errno = %d\n", errno);
++			exit(1);
++		}
+ 	}
+ 
+ 	kill(os_getpid(), SIGSTOP);
+@@ -246,13 +265,18 @@ int start_userspace(unsigned long stub_stack)
+ {
+ 	void *stack;
+ 	unsigned long sp;
+-	int pid, status, n, flags;
++	int pid, status, n, flags, err;
+ 
+ 	stack = mmap(NULL, UM_KERN_PAGE_SIZE,
+ 		     PROT_READ | PROT_WRITE | PROT_EXEC,
+ 		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+-	if (stack == MAP_FAILED)
+-		panic("start_userspace : mmap failed, errno = %d", errno);
++	if (stack == MAP_FAILED) {
++		err = -errno;
++		printk(UM_KERN_ERR "start_userspace : mmap failed, "
++		       "errno = %d\n", errno);
++		return err;
 +	}
-+	crc = c;
-+	bytes_out += (ulg)outcnt;
-+	outcnt = 0;
-+}
-+
-+static void error(char *x)
-+{
-+	putstr("\n\n");
-+	putstr(x);
-+	putstr("\n\n -- System halted");
 +
-+	while (1)
-+		asm("hlt");
-+}
+ 	sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *);
+ 
+ 	flags = CLONE_FILES;
+@@ -262,29 +286,50 @@ int start_userspace(unsigned long stub_stack)
+ 		flags |= SIGCHLD;
+ 
+ 	pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
+-	if (pid < 0)
+-		panic("start_userspace : clone failed, errno = %d", errno);
++	if (pid < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "start_userspace : clone failed, "
++		       "errno = %d\n", errno);
++		return err;
++	}
+ 
+ 	do {
+ 		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED | __WALL));
+-		if (n < 0)
+-			panic("start_userspace : wait failed, errno = %d",
+-			      errno);
++		if (n < 0) {
++			err = -errno;
++			printk(UM_KERN_ERR "start_userspace : wait failed, "
++			       "errno = %d\n", errno);
++			goto out_kill;
++		}
+ 	} while (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGVTALRM));
+ 
+-	if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
+-		panic("start_userspace : expected SIGSTOP, got status = %d",
+-		      status);
++	if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
++		err = -EINVAL;
++		printk(UM_KERN_ERR "start_userspace : expected SIGSTOP, got "
++		       "status = %d\n", status);
++		goto out_kill;
++	}
+ 
+ 	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
+-		   (void *) PTRACE_O_TRACESYSGOOD) < 0)
+-		panic("start_userspace : PTRACE_OLDSETOPTIONS failed, "
+-		      "errno = %d\n", errno);
++		   (void *) PTRACE_O_TRACESYSGOOD) < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "start_userspace : PTRACE_OLDSETOPTIONS "
++		       "failed, errno = %d\n", errno);
++		goto out_kill;
++	}
+ 
+-	if (munmap(stack, UM_KERN_PAGE_SIZE) < 0)
+-		panic("start_userspace : munmap failed, errno = %d\n", errno);
++	if (munmap(stack, UM_KERN_PAGE_SIZE) < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "start_userspace : munmap failed, "
++		       "errno = %d\n", errno);
++		goto out_kill;
++	}
+ 
+ 	return pid;
 +
-+asmlinkage void decompress_kernel(void *rmode, memptr heap,
-+				  uch *input_data, unsigned long input_len,
-+				  uch *output)
-+{
-+	real_mode = rmode;
++ out_kill:
++	os_kill_ptraced_process(pid, 1);
++	return err;
+ }
+ 
+ void userspace(struct uml_pt_regs *regs)
+@@ -302,7 +347,16 @@ void userspace(struct uml_pt_regs *regs)
+ 	nsecs += os_nsecs();
+ 
+ 	while (1) {
+-		restore_registers(pid, regs);
++		/*
++		 * This can legitimately fail if the process loads a
++		 * bogus value into a segment register.  It will
++		 * segfault and PTRACE_GETREGS will read that value
++		 * out of the process.  However, PTRACE_SETREGS will
++		 * fail.  In this case, there is nothing to do but
++		 * just kill the process.
++		 */
++		if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))
++			fatal_sigsegv();
+ 
+ 		/* Now we set local_using_sysemu to be used for one loop */
+ 		local_using_sysemu = get_using_sysemu();
+@@ -310,19 +364,26 @@ void userspace(struct uml_pt_regs *regs)
+ 		op = SELECT_PTRACE_OPERATION(local_using_sysemu,
+ 					     singlestepping(NULL));
+ 
+-		err = ptrace(op, pid, 0, 0);
+-		if (err)
+-			panic("userspace - could not resume userspace process, "
+-			      "pid=%d, ptrace operation = %d, errno = %d\n",
+-			      pid, op, errno);
++		if (ptrace(op, pid, 0, 0)) {
++			printk(UM_KERN_ERR "userspace - ptrace continue "
++			       "failed, op = %d, errno = %d\n", op, errno);
++			fatal_sigsegv();
++		}
+ 
+ 		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
+-		if (err < 0)
+-			panic("userspace - waitpid failed, errno = %d\n",
+-			      errno);
++		if (err < 0) {
++			printk(UM_KERN_ERR "userspace - wait failed, "
++			       "errno = %d\n", errno);
++			fatal_sigsegv();
++		}
+ 
+ 		regs->is_user = 1;
+-		save_registers(pid, regs);
++		if (ptrace(PTRACE_GETREGS, pid, 0, regs->gp)) {
++			printk(UM_KERN_ERR "userspace - PTRACE_GETREGS failed, "
++			       "errno = %d\n", errno);
++			fatal_sigsegv();
++		}
 +
-+	if (RM_SCREEN_INFO.orig_video_mode == 7) {
-+		vidmem = (char *) 0xb0000;
-+		vidport = 0x3b4;
-+	} else {
-+		vidmem = (char *) 0xb8000;
-+		vidport = 0x3d4;
+ 		UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
+ 
+ 		if (WIFSTOPPED(status)) {
+@@ -345,7 +406,7 @@ void userspace(struct uml_pt_regs *regs)
+ 				break;
+ 			case SIGVTALRM:
+ 				now = os_nsecs();
+-				if(now < nsecs)
++				if (now < nsecs)
+ 					break;
+ 				block_signals();
+ 				(*sig_info[sig])(sig, regs);
+@@ -368,6 +429,7 @@ void userspace(struct uml_pt_regs *regs)
+ 			default:
+ 			        printk(UM_KERN_ERR "userspace - child stopped "
+ 				       "with signal %d\n", sig);
++				fatal_sigsegv();
+ 			}
+ 			pid = userspace_pid[0];
+ 			interrupt_end();
+@@ -419,9 +481,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
+ 						     .it_interval = tv }) });
+ 
+ 	err = ptrace_setregs(pid, thread_regs);
+-	if (err < 0)
+-		panic("copy_context_skas0 : PTRACE_SETREGS failed, "
+-		      "pid = %d, errno = %d\n", pid, -err);
++	if (err < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_SETREGS "
++		       "failed, pid = %d, errno = %d\n", pid, -err);
++		return err;
++	}
+ 
+ 	/* set a well known return code for detection of child write failure */
+ 	child_data->err = 12345678;
+@@ -431,31 +496,47 @@ int copy_context_skas0(unsigned long new_stack, int pid)
+ 	 * parent's stack, and check, if bad result.
+ 	 */
+ 	err = ptrace(PTRACE_CONT, pid, 0, 0);
+-	if (err)
+-		panic("Failed to continue new process, pid = %d, "
+-		      "errno = %d\n", pid, errno);
++	if (err) {
++		err = -errno;
++		printk(UM_KERN_ERR "Failed to continue new process, pid = %d, "
++		       "errno = %d\n", pid, errno);
++		return err;
 +	}
 +
-+	lines = RM_SCREEN_INFO.orig_video_lines;
-+	cols = RM_SCREEN_INFO.orig_video_cols;
-+
-+	window = output;		/* Output buffer (Normally at 1M) */
-+	free_mem_ptr     = heap;	/* Heap */
-+	free_mem_end_ptr = heap + HEAP_SIZE;
-+	inbuf  = input_data;		/* Input buffer */
-+	insize = input_len;
-+	inptr  = 0;
+ 	wait_stub_done(pid);
+ 
+ 	pid = data->err;
+-	if (pid < 0)
+-		panic("copy_context_skas0 - stub-parent reports error %d\n",
+-		      -pid);
++	if (pid < 0) {
++		printk(UM_KERN_ERR "copy_context_skas0 - stub-parent reports "
++		       "error %d\n", -pid);
++		return pid;
++	}
+ 
+ 	/*
+ 	 * Wait, until child has finished too: read child's result from
+ 	 * child's stack and check it.
+ 	 */
+ 	wait_stub_done(pid);
+-	if (child_data->err != STUB_DATA)
+-		panic("copy_context_skas0 - stub-child reports error %ld\n",
+-		      child_data->err);
++	if (child_data->err != STUB_DATA) {
++		printk(UM_KERN_ERR "copy_context_skas0 - stub-child reports "
++		       "error %ld\n", child_data->err);
++		err = child_data->err;
++		goto out_kill;
++	}
+ 
+ 	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
+-		   (void *)PTRACE_O_TRACESYSGOOD) < 0)
+-		panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, "
+-		      "errno = %d\n", errno);
++		   (void *)PTRACE_O_TRACESYSGOOD) < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "copy_context_skas0 : PTRACE_OLDSETOPTIONS "
++		       "failed, errno = %d\n", errno);
++		goto out_kill;
++	}
+ 
+ 	return pid;
 +
-+#ifdef CONFIG_X86_64
-+	if ((ulg)output & (__KERNEL_ALIGN - 1))
-+		error("Destination address not 2M aligned");
-+	if ((ulg)output >= 0xffffffffffUL)
-+		error("Destination address too large");
-+#else
-+	if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
-+		error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
-+	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
-+		error("Destination address too large");
-+#ifndef CONFIG_RELOCATABLE
-+	if ((u32)output != LOAD_PHYSICAL_ADDR)
-+		error("Wrong destination address");
-+#endif
-+#endif
++ out_kill:
++	os_kill_ptraced_process(pid, 1);
++	return err;
+ }
+ 
+ /*
+@@ -463,8 +544,8 @@ int copy_context_skas0(unsigned long new_stack, int pid)
+  * available. Opening /proc/mm creates a new mm_context, which lacks
+  * the stub-pages. Thus, we map them using /proc/mm-fd
+  */
+-void map_stub_pages(int fd, unsigned long code,
+-		    unsigned long data, unsigned long stack)
++int map_stub_pages(int fd, unsigned long code, unsigned long data,
++		   unsigned long stack)
+ {
+ 	struct proc_mm_op mmop;
+ 	int n;
+@@ -488,8 +569,9 @@ void map_stub_pages(int fd, unsigned long code,
+ 		printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, "
+ 		       "offset = %llx\n", code, code_fd,
+ 		       (unsigned long long) code_offset);
+-		panic("map_stub_pages : /proc/mm map for code failed, "
+-		      "err = %d\n", n);
++		printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for code "
++		       "failed, err = %d\n", n);
++		return -n;
+ 	}
+ 
+ 	if (stack) {
+@@ -507,10 +589,15 @@ void map_stub_pages(int fd, unsigned long code,
+ 				      .offset  = map_offset
+ 		} } });
+ 		CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
+-		if (n != sizeof(mmop))
+-			panic("map_stub_pages : /proc/mm map for data failed, "
+-			      "err = %d\n", errno);
++		if (n != sizeof(mmop)) {
++			n = errno;
++			printk(UM_KERN_ERR "map_stub_pages : /proc/mm map for "
++			       "data failed, err = %d\n", n);
++			return -n;
++		}
+ 	}
 +
-+	makecrc();
-+	putstr("\nDecompressing Linux... ");
-+	gunzip();
-+	putstr("done.\nBooting the kernel.\n");
-+	return;
-+}
-diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
++	return 0;
+ }
+ 
+ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
+@@ -571,7 +658,9 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
+ 		kmalloc_ok = 0;
+ 		return 1;
+ 	default:
+-		panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
++		printk(UM_KERN_ERR "Bad sigsetjmp return in "
++		       "start_idle_thread - %d\n", n);
++		fatal_sigsegv();
+ 	}
+ 	longjmp(*switch_buf, 1);
+ }
+@@ -614,9 +703,11 @@ void __switch_mm(struct mm_id *mm_idp)
+ 	if (proc_mm) {
+ 		err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,
+ 			     mm_idp->u.mm_fd);
+-		if (err)
+-			panic("__switch_mm - PTRACE_SWITCH_MM failed, "
+-			      "errno = %d\n", errno);
++		if (err) {
++			printk(UM_KERN_ERR "__switch_mm - PTRACE_SWITCH_MM "
++			       "failed, errno = %d\n", errno);
++			fatal_sigsegv();
++		}
+ 	}
+ 	else userspace_pid[0] = mm_idp->u.pid;
+ }
+diff --git a/arch/um/os-Linux/skas/trap.c b/arch/um/os-Linux/skas/trap.c
 deleted file mode 100644
-index b74d60d..0000000
---- a/arch/x86/boot/compressed/misc_32.c
+index 3b1b924..0000000
+--- a/arch/um/os-Linux/skas/trap.c
 +++ /dev/null
-@@ -1,382 +0,0 @@
--/*
-- * misc.c
-- * 
-- * This is a collection of several routines from gzip-1.0.3 
-- * adapted for Linux.
-- *
-- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
-- * puts by Nick Holloway 1993, better puts by Martin Mares 1995
-- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
-- */
--
--#undef CONFIG_PARAVIRT
--#include <linux/linkage.h>
--#include <linux/vmalloc.h>
--#include <linux/screen_info.h>
--#include <asm/io.h>
--#include <asm/page.h>
--#include <asm/boot.h>
--
--/* WARNING!!
-- * This code is compiled with -fPIC and it is relocated dynamically
-- * at run time, but no relocation processing is performed.
-- * This means that it is not safe to place pointers in static structures.
-- */
--
+@@ -1,69 +0,0 @@
 -/*
-- * Getting to provable safe in place decompression is hard.
-- * Worst case behaviours need to be analyzed.
-- * Background information:
-- *
-- * The file layout is:
-- *    magic[2]
-- *    method[1]
-- *    flags[1]
-- *    timestamp[4]
-- *    extraflags[1]
-- *    os[1]
-- *    compressed data blocks[N]
-- *    crc[4] orig_len[4]
-- *
-- * resulting in 18 bytes of non compressed data overhead.
-- *
-- * Files divided into blocks
-- * 1 bit (last block flag)
-- * 2 bits (block type)
-- *
-- * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
-- * The smallest block type encoding is always used.
-- *
-- * stored:
-- *    32 bits length in bytes.
-- *
-- * fixed:
-- *    magic fixed tree.
-- *    symbols.
-- *
-- * dynamic:
-- *    dynamic tree encoding.
-- *    symbols.
-- *
-- *
-- * The buffer for decompression in place is the length of the
-- * uncompressed data, plus a small amount extra to keep the algorithm safe.
-- * The compressed data is placed at the end of the buffer.  The output
-- * pointer is placed at the start of the buffer and the input pointer
-- * is placed where the compressed data starts.  Problems will occur
-- * when the output pointer overruns the input pointer.
-- *
-- * The output pointer can only overrun the input pointer if the input
-- * pointer is moving faster than the output pointer.  A condition only
-- * triggered by data whose compressed form is larger than the uncompressed
-- * form.
-- *
-- * The worst case at the block level is a growth of the compressed data
-- * of 5 bytes per 32767 bytes.
-- *
-- * The worst case internal to a compressed block is very hard to figure.
-- * The worst case can at least be boundined by having one bit that represents
-- * 32764 bytes and then all of the rest of the bytes representing the very
-- * very last byte.
-- *
-- * All of which is enough to compute an amount of extra data that is required
-- * to be safe.  To avoid problems at the block level allocating 5 extra bytes
-- * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
-- * adding an extra 32767 bytes (the worst case uncompressed block size) is
-- * sufficient, to ensure that in the worst case the decompressed data for
-- * block will stop the byte before the compressed data for a block begins.
-- * To avoid problems with the compressed data's meta information an extra 18
-- * bytes are needed.  Leading to the formula:
-- *
-- * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
-- *
-- * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
-- * Adding 32768 instead of 32767 just makes for round numbers.
-- * Adding the decompressor_size is necessary as it musht live after all
-- * of the data as well.  Last I measured the decompressor is about 14K.
-- * 10K of actual data and 4K of bss.
-- *
+- * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+- * Licensed under the GPL
 - */
 -
--/*
-- * gzip declarations
-- */
+-#if 0
+-#include "kern_util.h"
+-#include "skas.h"
+-#include "ptrace_user.h"
+-#include "sysdep/ptrace_user.h"
+-#endif
 -
--#define OF(args)  args
--#define STATIC static
+-#include <errno.h>
+-#include <signal.h>
+-#include "sysdep/ptrace.h"
+-#include "kern_constants.h"
+-#include "as-layout.h"
+-#include "os.h"
+-#include "sigcontext.h"
+-#include "task.h"
+-
+-static struct uml_pt_regs ksig_regs[UM_NR_CPUS];
+-
+-void sig_handler_common_skas(int sig, void *sc_ptr)
+-{
+-	struct sigcontext *sc = sc_ptr;
+-	struct uml_pt_regs *r;
+-	void (*handler)(int, struct uml_pt_regs *);
+-	int save_user, save_errno = errno;
 -
--#undef memset
--#undef memcpy
--#define memzero(s, n)     memset ((s), 0, (n))
+-	/*
+-	 * This is done because to allow SIGSEGV to be delivered inside a SEGV
+-	 * handler.  This can happen in copy_user, and if SEGV is disabled,
+-	 * the process will die.
+-	 * XXX Figure out why this is better than SA_NODEFER
+-	 */
+-	if (sig == SIGSEGV) {
+-		change_sig(SIGSEGV, 1);
+-		/*
+-		 * For segfaults, we want the data from the
+-		 * sigcontext.  In this case, we don't want to mangle
+-		 * the process registers, so use a static set of
+-		 * registers.  For other signals, the process
+-		 * registers are OK.
+-		 */
+-		r = &ksig_regs[cpu()];
+-		copy_sc(r, sc_ptr);
+-	}
+-	else r = TASK_REGS(get_current());
 -
--typedef unsigned char  uch;
--typedef unsigned short ush;
--typedef unsigned long  ulg;
+-	save_user = r->is_user;
+-	r->is_user = 0;
+-	if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
+-	    (sig == SIGILL) || (sig == SIGTRAP))
+-		GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
 -
--#define WSIZE 0x80000000	/* Window size must be at least 32k,
--				 * and a power of two
--				 * We don't actually have a window just
--				 * a huge output buffer so I report
--				 * a 2G windows size, as that should
--				 * always be larger than our output buffer.
--				 */
+-	change_sig(SIGUSR1, 1);
 -
--static uch *inbuf;	/* input buffer */
--static uch *window;	/* Sliding window buffer, (and final output buffer) */
+-	handler = sig_info[sig];
 -
--static unsigned insize;  /* valid bytes in inbuf */
--static unsigned inptr;   /* index of next byte to be processed in inbuf */
--static unsigned outcnt;  /* bytes in output buffer */
+-	/* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */
+-	if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
+-		unblock_signals();
 -
--/* gzip flag byte */
--#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
--#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
--#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
--#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
--#define COMMENT      0x10 /* bit 4 set: file comment present */
--#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
--#define RESERVED     0xC0 /* bit 6,7:   reserved */
+-	handler(sig, r);
 -
--#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
--		
--/* Diagnostic functions */
--#ifdef DEBUG
--#  define Assert(cond,msg) {if(!(cond)) error(msg);}
--#  define Trace(x) fprintf x
--#  define Tracev(x) {if (verbose) fprintf x ;}
--#  define Tracevv(x) {if (verbose>1) fprintf x ;}
--#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
--#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
--#else
--#  define Assert(cond,msg)
--#  define Trace(x)
--#  define Tracev(x)
--#  define Tracevv(x)
--#  define Tracec(c,x)
--#  define Tracecv(c,x)
--#endif
+-	errno = save_errno;
+-	r->is_user = save_user;
+-}
+diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
+index 7b81f6c..b616e15 100644
+--- a/arch/um/os-Linux/start_up.c
++++ b/arch/um/os-Linux/start_up.c
+@@ -60,10 +60,11 @@ static int ptrace_child(void)
+ 		 * the UML code itself.
+ 		 */
+ 		ret = 2;
+-	_exit(ret);
++
++	exit(ret);
+ }
+ 
+-static void fatal_perror(char *str)
++static void fatal_perror(const char *str)
+ {
+ 	perror(str);
+ 	exit(1);
+@@ -341,6 +342,8 @@ static void __init check_coredump_limit(void)
+ 
+ void __init os_early_checks(void)
+ {
++	int pid;
++
+ 	/* Print out the core dump limits early */
+ 	check_coredump_limit();
+ 
+@@ -350,6 +353,11 @@ void __init os_early_checks(void)
+ 	 * kernel is running.
+ 	 */
+ 	check_tmpexec();
++
++	pid = start_ptraced_child();
++	if (init_registers(pid))
++		fatal("Failed to initialize default registers");
++	stop_ptraced_child(pid, 1, 1);
+ }
+ 
+ static int __init noprocmm_cmd_param(char *str, int* add)
+@@ -411,7 +419,6 @@ static inline void check_skas3_ptrace_faultinfo(void)
+ 			non_fatal("found\n");
+ 	}
+ 
+-	init_registers(pid);
+ 	stop_ptraced_child(pid, 1, 1);
+ }
+ 
+@@ -466,7 +473,7 @@ static inline void check_skas3_proc_mm(void)
+ 	else non_fatal("found\n");
+ }
+ 
+-int can_do_skas(void)
++void can_do_skas(void)
+ {
+ 	non_fatal("Checking for the skas3 patch in the host:\n");
+ 
+@@ -476,8 +483,6 @@ int can_do_skas(void)
+ 
+ 	if (!proc_mm || !ptrace_faultinfo || !ptrace_ldt)
+ 		skas_needs_stub = 1;
 -
--static int  fill_inbuf(void);
--static void flush_window(void);
--static void error(char *m);
--static void gzip_mark(void **);
--static void gzip_release(void **);
--  
+-	return 1;
+ }
+ 
+ int __init parse_iomem(char *str, int *add)
+diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
+deleted file mode 100644
+index 2a1c984..0000000
+--- a/arch/um/os-Linux/trap.c
++++ /dev/null
+@@ -1,23 +0,0 @@
 -/*
-- * This is set up by the setup-routine at boot-time
+- * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+- * Licensed under the GPL
 - */
--static unsigned char *real_mode; /* Pointer to real-mode data */
--
--#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
--#ifndef STANDARD_MEMORY_BIOS_CALL
--#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
--#endif
--#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
--
--extern unsigned char input_data[];
--extern int input_len;
 -
--static long bytes_out = 0;
--
--static void *malloc(int size);
--static void free(void *where);
--
--static void *memset(void *s, int c, unsigned n);
--static void *memcpy(void *dest, const void *src, unsigned n);
--
--static void putstr(const char *);
--
--static unsigned long free_mem_ptr;
--static unsigned long free_mem_end_ptr;
--
--#define HEAP_SIZE             0x4000
--
--static char *vidmem = (char *)0xb8000;
--static int vidport;
--static int lines, cols;
--
--#ifdef CONFIG_X86_NUMAQ
--void *xquad_portio;
--#endif
+-#include <signal.h>
+-#include "os.h"
+-#include "sysdep/ptrace.h"
 -
--#include "../../../../lib/inflate.c"
+-/* Initialized from linux_main() */
+-void (*sig_info[NSIG])(int, struct uml_pt_regs *);
 -
--static void *malloc(int size)
+-void os_fill_handlinfo(struct kern_handlers h)
 -{
--	void *p;
--
--	if (size <0) error("Malloc error");
--	if (free_mem_ptr <= 0) error("Memory error");
--
--	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
--
--	p = (void *)free_mem_ptr;
--	free_mem_ptr += size;
+-	sig_info[SIGTRAP] = h.relay_signal;
+-	sig_info[SIGFPE] = h.relay_signal;
+-	sig_info[SIGILL] = h.relay_signal;
+-	sig_info[SIGWINCH] = h.winch;
+-	sig_info[SIGBUS] = h.bus_handler;
+-	sig_info[SIGSEGV] = h.page_fault;
+-	sig_info[SIGIO] = h.sigio_handler;
+-	sig_info[SIGVTALRM] = h.timer_handler;
+-}
+diff --git a/arch/um/os-Linux/tty.c b/arch/um/os-Linux/tty.c
+index 4cfdd18..b09ff66 100644
+--- a/arch/um/os-Linux/tty.c
++++ b/arch/um/os-Linux/tty.c
+@@ -1,13 +1,16 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
++/*
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+ #include <stdlib.h>
++#include <unistd.h>
+ #include <errno.h>
++#include <fcntl.h>
++#include "kern_constants.h"
++#include "kern_util.h"
+ #include "os.h"
+ #include "user.h"
+-#include "kern_util.h"
+ 
+ struct grantpt_info {
+ 	int fd;
+@@ -26,36 +29,34 @@ static void grantpt_cb(void *arg)
+ int get_pty(void)
+ {
+ 	struct grantpt_info info;
+-	int fd;
 -
--	if (free_mem_ptr >= free_mem_end_ptr)
--		error("Out of memory");
+-	fd = os_open_file("/dev/ptmx", of_rdwr(OPENFLAGS()), 0);
+-	if(fd < 0){
+-		printk("get_pty : Couldn't open /dev/ptmx - err = %d\n", -fd);
+-		return(fd);
++	int fd, err;
++
++	fd = open("/dev/ptmx", O_RDWR);
++	if (fd < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "get_pty : Couldn't open /dev/ptmx - "
++		       "err = %d\n", errno);
++		return err;
+ 	}
+ 
+ 	info.fd = fd;
+ 	initial_thread_cb(grantpt_cb, &info);
+ 
+-	if(info.res < 0){
+-		printk("get_pty : Couldn't grant pty - errno = %d\n", 
+-		       -info.err);
+-		return(-1);
++	if (info.res < 0) {
++		err = -info.err;
++		printk(UM_KERN_ERR "get_pty : Couldn't grant pty - "
++		       "errno = %d\n", -info.err);
++		goto out;
+ 	}
+-	if(unlockpt(fd) < 0){
+-		printk("get_pty : Couldn't unlock pty - errno = %d\n", errno);
+-		return(-1);
++
++	if (unlockpt(fd) < 0) {
++		err = -errno;
++		printk(UM_KERN_ERR "get_pty : Couldn't unlock pty - "
++		       "errno = %d\n", errno);
++		goto out;
+ 	}
+-	return(fd);
++	return fd;
++out:
++	close(fd);
++	return err;
+ }
 -
--	return p;
--}
+-/*
+- * 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/os-Linux/tty_log.c b/arch/um/os-Linux/tty_log.c
+index d11a55b..cc648e6 100644
+--- a/arch/um/os-Linux/tty_log.c
++++ b/arch/um/os-Linux/tty_log.c
+@@ -12,7 +12,6 @@
+ #include <sys/time.h>
+ #include "init.h"
+ #include "user.h"
+-#include "kern_util.h"
+ #include "os.h"
+ 
+ #define TTY_LOG_DIR "./"
+diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
+index 3e058ce..a6f31d4 100644
+--- a/arch/um/os-Linux/util.c
++++ b/arch/um/os-Linux/util.c
+@@ -88,21 +88,6 @@ void setup_hostinfo(char *buf, int len)
+ 		 host.release, host.version, host.machine);
+ }
+ 
+-int setjmp_wrapper(void (*proc)(void *, void *), ...)
+-{
+-	va_list args;
+-	jmp_buf buf;
+-	int n;
 -
--static void free(void *where)
--{	/* Don't care */
+-	n = UML_SETJMP(&buf);
+-	if(n == 0){
+-		va_start(args, proc);
+-		(*proc)(&buf, &args);
+-	}
+-	va_end(args);
+-	return n;
 -}
 -
--static void gzip_mark(void **ptr)
--{
--	*ptr = (void *) free_mem_ptr;
--}
+ void os_dump_core(void)
+ {
+ 	int pid;
+diff --git a/arch/um/sys-i386/bug.c b/arch/um/sys-i386/bug.c
+index a4360b5..8d4f273 100644
+--- a/arch/um/sys-i386/bug.c
++++ b/arch/um/sys-i386/bug.c
+@@ -4,6 +4,7 @@
+  */
+ 
+ #include <linux/uaccess.h>
++#include <asm/errno.h>
+ 
+ /* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+  * that's not relevant in skas mode.
+diff --git a/arch/um/sys-i386/bugs.c b/arch/um/sys-i386/bugs.c
+index 806895d..a74442d 100644
+--- a/arch/um/sys-i386/bugs.c
++++ b/arch/um/sys-i386/bugs.c
+@@ -3,171 +3,47 @@
+  * Licensed under the GPL
+  */
+ 
+-#include <errno.h>
+ #include <signal.h>
+-#include <string.h>
+ #include "kern_constants.h"
+-#include "os.h"
++#include "kern_util.h"
++#include "longjmp.h"
+ #include "task.h"
+ #include "user.h"
 -
--static void gzip_release(void **ptr)
--{
--	free_mem_ptr = (unsigned long) *ptr;
--}
-- 
--static void scroll(void)
--{
--	int i;
+-#define MAXTOKEN 64
++#include "sysdep/ptrace.h"
+ 
+ /* Set during early boot */
+ int host_has_cmov = 1;
+-int host_has_xmm = 0;
++static jmp_buf cmov_test_return;
+ 
+-static char token(int fd, char *buf, int len, char stop)
++static void cmov_sigill_test_handler(int sig)
+ {
+-	int n;
+-	char *ptr, *end, c;
 -
--	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
--	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
--		vidmem[i] = ' ';
+-	ptr = buf;
+-	end = &buf[len];
+-	do {
+-		n = os_read_file(fd, ptr, sizeof(*ptr));
+-		c = *ptr++;
+-		if (n != sizeof(*ptr)) {
+-			if (n == 0)
+-				return 0;
+-			printk(UM_KERN_ERR "Reading /proc/cpuinfo failed, "
+-			       "err = %d\n", -n);
+-			if (n < 0)
+-				return n;
+-			else return -EIO;
+-		}
+-	} while ((c != '\n') && (c != stop) && (ptr < end));
+-
+-	if (ptr == end) {
+-		printk(UM_KERN_ERR "Failed to find '%c' in /proc/cpuinfo\n",
+-		       stop);
+-		return -1;
+-	}
+-	*(ptr - 1) = '\0';
+-	return c;
 -}
 -
--static void putstr(const char *s)
+-static int find_cpuinfo_line(int fd, char *key, char *scratch, int len)
 -{
--	int x,y,pos;
+-	int n;
 -	char c;
 -
--	if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
--		return;
+-	scratch[len - 1] = '\0';
+-	while (1) {
+-		c = token(fd, scratch, len - 1, ':');
+-		if (c <= 0)
+-			return 0;
+-		else if (c != ':') {
+-			printk(UM_KERN_ERR "Failed to find ':' in "
+-			       "/proc/cpuinfo\n");
+-			return 0;
+-		}
 -
--	x = RM_SCREEN_INFO.orig_x;
--	y = RM_SCREEN_INFO.orig_y;
+-		if (!strncmp(scratch, key, strlen(key)))
+-			return 1;
 -
--	while ( ( c = *s++ ) != '\0' ) {
--		if ( c == '\n' ) {
--			x = 0;
--			if ( ++y >= lines ) {
--				scroll();
--				y--;
--			}
--		} else {
--			vidmem [ ( x + cols * y ) * 2 ] = c;
--			if ( ++x >= cols ) {
--				x = 0;
--				if ( ++y >= lines ) {
--					scroll();
--					y--;
--				}
+-		do {
+-			n = os_read_file(fd, &c, sizeof(c));
+-			if (n != sizeof(c)) {
+-				printk(UM_KERN_ERR "Failed to find newline in "
+-				       "/proc/cpuinfo, err = %d\n", -n);
+-				return 0;
 -			}
--		}
+-		} while (c != '\n');
 -	}
+-	return 0;
++	host_has_cmov = 0;
++	longjmp(cmov_test_return, 1);
+ }
+ 
+-static int check_cpu_flag(char *feature, int *have_it)
+-{
+-	char buf[MAXTOKEN], c;
+-	int fd, len = ARRAY_SIZE(buf);
 -
--	RM_SCREEN_INFO.orig_x = x;
--	RM_SCREEN_INFO.orig_y = y;
--
--	pos = (x + cols * y) * 2;	/* Update cursor position */
--	outb_p(14, vidport);
--	outb_p(0xff & (pos >> 9), vidport+1);
--	outb_p(15, vidport);
--	outb_p(0xff & (pos >> 1), vidport+1);
--}
+-	printk(UM_KERN_INFO "Checking for host processor %s support...",
+-	       feature);
+-	fd = os_open_file("/proc/cpuinfo", of_read(OPENFLAGS()), 0);
+-	if (fd < 0) {
+-		printk(UM_KERN_ERR "Couldn't open /proc/cpuinfo, err = %d\n",
+-		       -fd);
+-		return 0;
+-	}
 -
--static void* memset(void* s, int c, unsigned n)
--{
--	int i;
--	char *ss = (char*)s;
+-	*have_it = 0;
+-	if (!find_cpuinfo_line(fd, "flags", buf, ARRAY_SIZE(buf)))
+-		goto out;
 -
--	for (i=0;i<n;i++) ss[i] = c;
--	return s;
--}
+-	c = token(fd, buf, len - 1, ' ');
+-	if (c < 0)
+-		goto out;
+-	else if (c != ' ') {
+-		printk(UM_KERN_ERR "Failed to find ' ' in /proc/cpuinfo\n");
+-		goto out;
+-	}
 -
--static void* memcpy(void* dest, const void* src, unsigned n)
--{
--	int i;
--	char *d = (char *)dest, *s = (char *)src;
+-	while (1) {
+-		c = token(fd, buf, len - 1, ' ');
+-		if (c < 0)
+-			goto out;
+-		else if (c == '\n')
+-			break;
 -
--	for (i=0;i<n;i++) d[i] = s[i];
--	return dest;
+-		if (!strcmp(buf, feature)) {
+-			*have_it = 1;
+-			goto out;
+-		}
+-	}
+- out:
+-	if (*have_it == 0)
+-		printk("No\n");
+-	else if (*have_it == 1)
+-		printk("Yes\n");
+-	os_close_file(fd);
+-	return 1;
 -}
 -
--/* ===========================================================================
-- * Fill the input buffer. This is called only when the buffer is empty
-- * and at least one byte is really needed.
-- */
--static int fill_inbuf(void)
+-#if 0 /*
+-       * This doesn't work in tt mode, plus it's causing compilation problems
+-       * for some people.
+-       */
+-static void disable_lcall(void)
++void arch_check_bugs(void)
+ {
+-	struct modify_ldt_ldt_s ldt;
+-	int err;
++	struct sigaction old, new;
+ 
+-	bzero(&ldt, sizeof(ldt));
+-	ldt.entry_number = 7;
+-	ldt.base_addr = 0;
+-	ldt.limit = 0;
+-	err = modify_ldt(1, &ldt, sizeof(ldt));
+-	if (err)
+-		printk(UM_KERN_ERR "Failed to disable lcall7 - errno = %d\n",
+-		       errno);
+-}
+-#endif
++	printk(UM_KERN_INFO "Checking for host processor cmov support...");
++	new.sa_handler = cmov_sigill_test_handler;
+ 
+-void arch_init_thread(void)
 -{
--	error("ran out of input data");
--	return 0;
+-#if 0
+-	disable_lcall();
+-#endif
 -}
--
--/* ===========================================================================
-- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
-- * (Used for the decompressed data only.)
-- */
--static void flush_window(void)
++	/* Make sure that SIGILL is enabled after the handler longjmps back */
++	new.sa_flags = SA_NODEFER;
++	sigemptyset(&new.sa_mask);
++	sigaction(SIGILL, &new, &old);
+ 
+-void arch_check_bugs(void)
 -{
--	/* With my window equal to my output buffer
--	 * I only need to compute the crc here.
--	 */
--	ulg c = crc;         /* temporary variable */
--	unsigned n;
--	uch *in, ch;
--
--	in = window;
--	for (n = 0; n < outcnt; n++) {
--		ch = *in++;
--		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+-	int have_it;
++	if (setjmp(cmov_test_return) == 0) {
++		unsigned long foo = 0;
++		__asm__ __volatile__("cmovz %0, %1" : "=r" (foo) : "0" (foo));
++		printk(UM_KERN_CONT "Yes\n");
++	} else
++		printk(UM_KERN_CONT "No\n");
+ 
+-	if (os_access("/proc/cpuinfo", OS_ACC_R_OK) < 0) {
+-		printk(UM_KERN_ERR "/proc/cpuinfo not available - skipping CPU "
+-		       "capability checks\n");
+-		return;
 -	}
--	crc = c;
--	bytes_out += (ulg)outcnt;
--	outcnt = 0;
--}
+-	if (check_cpu_flag("cmov", &have_it))
+-		host_has_cmov = have_it;
+-	if (check_cpu_flag("xmm", &have_it))
+-		host_has_xmm = have_it;
++	sigaction(SIGILL, &old, &new);
+ }
+ 
+-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
++void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+ {
+ 	unsigned char tmp[2];
+ 
+@@ -176,24 +52,25 @@ int arch_handle_signal(int sig, struct uml_pt_regs *regs)
+ 	 * SIGILL in init.
+ 	 */
+ 	if ((sig != SIGILL) || (TASK_PID(get_current()) != 1))
+-		return 0;
++		return;
++
++	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2)) {
++		printk(UM_KERN_ERR "SIGILL in init, could not read "
++		       "instructions!\n");
++		return;
++	}
+ 
+-	if (copy_from_user_proc(tmp, (void *) UPT_IP(regs), 2))
+-		panic("SIGILL in init, could not read instructions!\n");
+ 	if ((tmp[0] != 0x0f) || ((tmp[1] & 0xf0) != 0x40))
+-		return 0;
++		return;
+ 
+ 	if (host_has_cmov == 0)
+-		panic("SIGILL caused by cmov, which this processor doesn't "
+-		      "implement, boot a filesystem compiled for older "
+-		      "processors");
++		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
++		       "processor doesn't implement.  Boot a filesystem "
++		       "compiled for older processors");
+ 	else if (host_has_cmov == 1)
+-		panic("SIGILL caused by cmov, which this processor claims to "
+-		      "implement");
+-	else if (host_has_cmov == -1)
+-		panic("SIGILL caused by cmov, couldn't tell if this processor "
+-		      "implements it, boot a filesystem compiled for older "
+-		      "processors");
+-	else panic("Bad value for host_has_cmov (%d)", host_has_cmov);
+-	return 0;
++		printk(UM_KERN_ERR "SIGILL caused by cmov, which this "
++		       "processor claims to implement");
++	else
++		printk(UM_KERN_ERR "Bad value for host_has_cmov (%d)",
++			host_has_cmov);
+ }
+diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c
+index 67c0958..a34263e 100644
+--- a/arch/um/sys-i386/ldt.c
++++ b/arch/um/sys-i386/ldt.c
+@@ -3,8 +3,9 @@
+  * Licensed under the GPL
+  */
+ 
+-#include "linux/mm.h"
+-#include "asm/unistd.h"
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <asm/unistd.h>
+ #include "os.h"
+ #include "proc_mm.h"
+ #include "skas.h"
+@@ -146,7 +147,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
+ 	if (ptrace_ldt)
+ 		return read_ldt_from_host(ptr, bytecount);
+ 
+-	down(&ldt->semaphore);
++	mutex_lock(&ldt->lock);
+ 	if (ldt->entry_count <= LDT_DIRECT_ENTRIES) {
+ 		size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES;
+ 		if (size > bytecount)
+@@ -170,7 +171,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount)
+ 			ptr += size;
+ 		}
+ 	}
+-	up(&ldt->semaphore);
++	mutex_unlock(&ldt->lock);
+ 
+ 	if (bytecount == 0 || err == -EFAULT)
+ 		goto out;
+@@ -228,7 +229,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+ 	}
+ 
+ 	if (!ptrace_ldt)
+-		down(&ldt->semaphore);
++		mutex_lock(&ldt->lock);
+ 
+ 	err = write_ldt_entry(mm_idp, func, &ldt_info, &addr, 1);
+ 	if (err)
+@@ -288,7 +289,7 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func)
+ 	err = 0;
+ 
+ out_unlock:
+-	up(&ldt->semaphore);
++	mutex_unlock(&ldt->lock);
+ out:
+ 	return err;
+ }
+@@ -395,7 +396,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
+ 
+ 
+ 	if (!ptrace_ldt)
+-		init_MUTEX(&new_mm->ldt.semaphore);
++		mutex_init(&new_mm->ldt.lock);
+ 
+ 	if (!from_mm) {
+ 		memset(&desc, 0, sizeof(desc));
+@@ -455,7 +456,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
+ 		 * i.e., we have to use the stub for modify_ldt, which
+ 		 * can't handle the big read buffer of up to 64kB.
+ 		 */
+-		down(&from_mm->ldt.semaphore);
++		mutex_lock(&from_mm->ldt.lock);
+ 		if (from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES)
+ 			memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries,
+ 			       sizeof(new_mm->ldt.u.entries));
+@@ -474,7 +475,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm)
+ 			}
+ 		}
+ 		new_mm->ldt.entry_count = from_mm->ldt.entry_count;
+-		up(&from_mm->ldt.semaphore);
++		mutex_unlock(&from_mm->ldt.lock);
+ 	}
+ 
+     out:
+diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
+index bd3da8a..6b44999 100644
+--- a/arch/um/sys-i386/ptrace.c
++++ b/arch/um/sys-i386/ptrace.c
+@@ -8,11 +8,11 @@
+ #include "asm/uaccess.h"
+ #include "skas.h"
+ 
+-extern int arch_switch_tls(struct task_struct *from, struct task_struct *to);
++extern int arch_switch_tls(struct task_struct *to);
+ 
+-void arch_switch_to(struct task_struct *from, struct task_struct *to)
++void arch_switch_to(struct task_struct *to)
+ {
+-	int err = arch_switch_tls(from, to);
++	int err = arch_switch_tls(to);
+ 	if (!err)
+ 		return;
+ 
+diff --git a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
+index 5cf97bc..0b10c3e 100644
+--- a/arch/um/sys-i386/ptrace_user.c
++++ b/arch/um/sys-i386/ptrace_user.c
+@@ -19,17 +19,3 @@ int ptrace_setregs(long pid, unsigned long *regs)
+ 		return -errno;
+ 	return 0;
+ }
 -
--static void error(char *x)
+-int ptrace_getfpregs(long pid, unsigned long *regs)
 -{
--	putstr("\n\n");
--	putstr(x);
--	putstr("\n\n -- System halted");
--
--	while(1);	/* Halt */
+-	if (ptrace(PTRACE_GETFPREGS, pid, 0, regs) < 0)
+-		return -errno;
+-	return 0;
 -}
 -
--asmlinkage void decompress_kernel(void *rmode, unsigned long end,
--			uch *input_data, unsigned long input_len, uch *output)
+-int ptrace_setfpregs(long pid, unsigned long *regs)
 -{
--	real_mode = rmode;
--
--	if (RM_SCREEN_INFO.orig_video_mode == 7) {
--		vidmem = (char *) 0xb0000;
--		vidport = 0x3b4;
--	} else {
--		vidmem = (char *) 0xb8000;
--		vidport = 0x3d4;
--	}
--
--	lines = RM_SCREEN_INFO.orig_video_lines;
--	cols = RM_SCREEN_INFO.orig_video_cols;
--
--	window = output;  	/* Output buffer (Normally at 1M) */
--	free_mem_ptr     = end;	/* Heap  */
--	free_mem_end_ptr = end + HEAP_SIZE;
--	inbuf  = input_data;	/* Input buffer */
--	insize = input_len;
--	inptr  = 0;
--
--	if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
--		error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
--	if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
--		error("Destination address too large");
--#ifndef CONFIG_RELOCATABLE
--	if ((u32)output != LOAD_PHYSICAL_ADDR)
--		error("Wrong destination address");
--#endif
--
--	makecrc();
--	putstr("Uncompressing Linux... ");
--	gunzip();
--	putstr("Ok, booting the kernel.\n");
--	return;
+-	if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
+-		return -errno;
+-	return 0;
 -}
-diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
-deleted file mode 100644
-index 6ea015a..0000000
---- a/arch/x86/boot/compressed/misc_64.c
-+++ /dev/null
-@@ -1,371 +0,0 @@
--/*
-- * misc.c
-- * 
-- * This is a collection of several routines from gzip-1.0.3 
-- * adapted for Linux.
-- *
-- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
-- * puts by Nick Holloway 1993, better puts by Martin Mares 1995
-- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
-- */
--
--#define _LINUX_STRING_H_ 1
--#define __LINUX_BITMAP_H 1
--
--#include <linux/linkage.h>
--#include <linux/screen_info.h>
--#include <asm/io.h>
--#include <asm/page.h>
--
--/* WARNING!!
-- * This code is compiled with -fPIC and it is relocated dynamically
-- * at run time, but no relocation processing is performed.
-- * This means that it is not safe to place pointers in static structures.
-- */
--
--/*
-- * Getting to provable safe in place decompression is hard.
-- * Worst case behaviours need to be analyzed.
-- * Background information:
-- *
-- * The file layout is:
-- *    magic[2]
-- *    method[1]
-- *    flags[1]
-- *    timestamp[4]
-- *    extraflags[1]
-- *    os[1]
-- *    compressed data blocks[N]
-- *    crc[4] orig_len[4]
-- *
-- * resulting in 18 bytes of non compressed data overhead.
-- *
-- * Files divided into blocks
-- * 1 bit (last block flag)
-- * 2 bits (block type)
-- *
-- * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
-- * The smallest block type encoding is always used.
-- *
-- * stored:
-- *    32 bits length in bytes.
-- *
-- * fixed:
-- *    magic fixed tree.
-- *    symbols.
-- *
-- * dynamic:
-- *    dynamic tree encoding.
-- *    symbols.
-- *
-- *
-- * The buffer for decompression in place is the length of the
-- * uncompressed data, plus a small amount extra to keep the algorithm safe.
-- * The compressed data is placed at the end of the buffer.  The output
-- * pointer is placed at the start of the buffer and the input pointer
-- * is placed where the compressed data starts.  Problems will occur
-- * when the output pointer overruns the input pointer.
-- *
-- * The output pointer can only overrun the input pointer if the input
-- * pointer is moving faster than the output pointer.  A condition only
-- * triggered by data whose compressed form is larger than the uncompressed
-- * form.
-- *
-- * The worst case at the block level is a growth of the compressed data
-- * of 5 bytes per 32767 bytes.
-- *
-- * The worst case internal to a compressed block is very hard to figure.
-- * The worst case can at least be boundined by having one bit that represents
-- * 32764 bytes and then all of the rest of the bytes representing the very
-- * very last byte.
-- *
-- * All of which is enough to compute an amount of extra data that is required
-- * to be safe.  To avoid problems at the block level allocating 5 extra bytes
-- * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
-- * adding an extra 32767 bytes (the worst case uncompressed block size) is
-- * sufficient, to ensure that in the worst case the decompressed data for
-- * block will stop the byte before the compressed data for a block begins.
-- * To avoid problems with the compressed data's meta information an extra 18
-- * bytes are needed.  Leading to the formula:
-- *
-- * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
-- *
-- * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
-- * Adding 32768 instead of 32767 just makes for round numbers.
-- * Adding the decompressor_size is necessary as it musht live after all
-- * of the data as well.  Last I measured the decompressor is about 14K.
-- * 10K of actual data and 4K of bss.
-- *
-- */
--
--/*
-- * gzip declarations
-- */
--
--#define OF(args)  args
--#define STATIC static
--
--#undef memset
--#undef memcpy
--#define memzero(s, n)     memset ((s), 0, (n))
--
--typedef unsigned char  uch;
--typedef unsigned short ush;
--typedef unsigned long  ulg;
--
--#define WSIZE 0x80000000	/* Window size must be at least 32k,
--				 * and a power of two
--				 * We don't actually have a window just
--				 * a huge output buffer so I report
--				 * a 2G windows size, as that should
--				 * always be larger than our output buffer.
--				 */
--
--static uch *inbuf;	/* input buffer */
--static uch *window;	/* Sliding window buffer, (and final output buffer) */
--
--static unsigned insize;  /* valid bytes in inbuf */
--static unsigned inptr;   /* index of next byte to be processed in inbuf */
--static unsigned outcnt;  /* bytes in output buffer */
--
--/* gzip flag byte */
--#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
--#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
--#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
--#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
--#define COMMENT      0x10 /* bit 4 set: file comment present */
--#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
--#define RESERVED     0xC0 /* bit 6,7:   reserved */
--
--#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
--		
--/* Diagnostic functions */
--#ifdef DEBUG
--#  define Assert(cond,msg) {if(!(cond)) error(msg);}
--#  define Trace(x) fprintf x
--#  define Tracev(x) {if (verbose) fprintf x ;}
--#  define Tracevv(x) {if (verbose>1) fprintf x ;}
--#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
--#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
--#else
--#  define Assert(cond,msg)
--#  define Trace(x)
--#  define Tracev(x)
--#  define Tracevv(x)
--#  define Tracec(c,x)
--#  define Tracecv(c,x)
--#endif
--
--static int  fill_inbuf(void);
--static void flush_window(void);
--static void error(char *m);
--static void gzip_mark(void **);
--static void gzip_release(void **);
--  
--/*
-- * This is set up by the setup-routine at boot-time
-- */
--static unsigned char *real_mode; /* Pointer to real-mode data */
--
--#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
--#ifndef STANDARD_MEMORY_BIOS_CALL
--#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
--#endif
--#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
--
--extern unsigned char input_data[];
--extern int input_len;
--
--static long bytes_out = 0;
--
--static void *malloc(int size);
--static void free(void *where);
--
--static void *memset(void *s, int c, unsigned n);
--static void *memcpy(void *dest, const void *src, unsigned n);
--
--static void putstr(const char *);
--
--static long free_mem_ptr;
--static long free_mem_end_ptr;
--
--#define HEAP_SIZE             0x7000
--
--static char *vidmem = (char *)0xb8000;
--static int vidport;
--static int lines, cols;
+diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
+index 0147227..fd0c25a 100644
+--- a/arch/um/sys-i386/signal.c
++++ b/arch/um/sys-i386/signal.c
+@@ -3,10 +3,10 @@
+  * Licensed under the GPL
+  */
+ 
+-#include "linux/ptrace.h"
+-#include "asm/unistd.h"
+-#include "asm/uaccess.h"
+-#include "asm/ucontext.h"
++#include <linux/ptrace.h>
++#include <asm/unistd.h>
++#include <asm/uaccess.h>
++#include <asm/ucontext.h>
+ #include "frame_kern.h"
+ #include "skas.h"
+ 
+@@ -18,17 +18,17 @@ void copy_sc(struct uml_pt_regs *regs, void *from)
+ 	REGS_FS(regs->gp) = sc->fs;
+ 	REGS_ES(regs->gp) = sc->es;
+ 	REGS_DS(regs->gp) = sc->ds;
+-	REGS_EDI(regs->gp) = sc->edi;
+-	REGS_ESI(regs->gp) = sc->esi;
+-	REGS_EBP(regs->gp) = sc->ebp;
+-	REGS_SP(regs->gp) = sc->esp;
+-	REGS_EBX(regs->gp) = sc->ebx;
+-	REGS_EDX(regs->gp) = sc->edx;
+-	REGS_ECX(regs->gp) = sc->ecx;
+-	REGS_EAX(regs->gp) = sc->eax;
+-	REGS_IP(regs->gp) = sc->eip;
++	REGS_EDI(regs->gp) = sc->di;
++	REGS_ESI(regs->gp) = sc->si;
++	REGS_EBP(regs->gp) = sc->bp;
++	REGS_SP(regs->gp) = sc->sp;
++	REGS_EBX(regs->gp) = sc->bx;
++	REGS_EDX(regs->gp) = sc->dx;
++	REGS_ECX(regs->gp) = sc->cx;
++	REGS_EAX(regs->gp) = sc->ax;
++	REGS_IP(regs->gp) = sc->ip;
+ 	REGS_CS(regs->gp) = sc->cs;
+-	REGS_EFLAGS(regs->gp) = sc->eflags;
++	REGS_EFLAGS(regs->gp) = sc->flags;
+ 	REGS_SS(regs->gp) = sc->ss;
+ }
+ 
+@@ -168,12 +168,13 @@ static int copy_sc_from_user(struct pt_regs *regs,
+ 			     struct sigcontext __user *from)
+ {
+ 	struct sigcontext sc;
+-	int err;
++	int err, pid;
+ 
+ 	err = copy_from_user(&sc, from, sizeof(sc));
+ 	if (err)
+ 		return err;
+ 
++	pid = userspace_pid[current_thread_info()->cpu];
+ 	copy_sc(&regs->regs, &sc);
+ 	if (have_fpx_regs) {
+ 		struct user_fxsr_struct fpx;
+@@ -187,8 +188,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
+ 		if (err)
+ 			return 1;
+ 
+-		err = restore_fpx_registers(userspace_pid[current_thread->cpu],
+-					    (unsigned long *) &fpx);
++		err = restore_fpx_registers(pid, (unsigned long *) &fpx);
+ 		if (err < 0) {
+ 			printk(KERN_ERR "copy_sc_from_user - "
+ 			       "restore_fpx_registers failed, errno = %d\n",
+@@ -204,8 +204,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
+ 		if (err)
+ 			return 1;
+ 
+-		err = restore_fp_registers(userspace_pid[current_thread->cpu],
+-					   (unsigned long *) &fp);
++		err = restore_fp_registers(pid, (unsigned long *) &fp);
+ 		if (err < 0) {
+ 			printk(KERN_ERR "copy_sc_from_user - "
+ 			       "restore_fp_registers failed, errno = %d\n",
+@@ -223,24 +222,24 @@ static int copy_sc_to_user(struct sigcontext __user *to,
+ {
+ 	struct sigcontext sc;
+ 	struct faultinfo * fi = &current->thread.arch.faultinfo;
+-	int err;
++	int err, pid;
+ 
+ 	sc.gs = REGS_GS(regs->regs.gp);
+ 	sc.fs = REGS_FS(regs->regs.gp);
+ 	sc.es = REGS_ES(regs->regs.gp);
+ 	sc.ds = REGS_DS(regs->regs.gp);
+-	sc.edi = REGS_EDI(regs->regs.gp);
+-	sc.esi = REGS_ESI(regs->regs.gp);
+-	sc.ebp = REGS_EBP(regs->regs.gp);
+-	sc.esp = sp;
+-	sc.ebx = REGS_EBX(regs->regs.gp);
+-	sc.edx = REGS_EDX(regs->regs.gp);
+-	sc.ecx = REGS_ECX(regs->regs.gp);
+-	sc.eax = REGS_EAX(regs->regs.gp);
+-	sc.eip = REGS_IP(regs->regs.gp);
++	sc.di = REGS_EDI(regs->regs.gp);
++	sc.si = REGS_ESI(regs->regs.gp);
++	sc.bp = REGS_EBP(regs->regs.gp);
++	sc.sp = sp;
++	sc.bx = REGS_EBX(regs->regs.gp);
++	sc.dx = REGS_EDX(regs->regs.gp);
++	sc.cx = REGS_ECX(regs->regs.gp);
++	sc.ax = REGS_EAX(regs->regs.gp);
++	sc.ip = REGS_IP(regs->regs.gp);
+ 	sc.cs = REGS_CS(regs->regs.gp);
+-	sc.eflags = REGS_EFLAGS(regs->regs.gp);
+-	sc.esp_at_signal = regs->regs.gp[UESP];
++	sc.flags = REGS_EFLAGS(regs->regs.gp);
++	sc.sp_at_signal = regs->regs.gp[UESP];
+ 	sc.ss = regs->regs.gp[SS];
+ 	sc.cr2 = fi->cr2;
+ 	sc.err = fi->error_code;
+@@ -249,11 +248,11 @@ static int copy_sc_to_user(struct sigcontext __user *to,
+ 	to_fp = (to_fp ? to_fp : (struct _fpstate __user *) (to + 1));
+ 	sc.fpstate = to_fp;
+ 
++	pid = userspace_pid[current_thread_info()->cpu];
+ 	if (have_fpx_regs) {
+ 		struct user_fxsr_struct fpx;
+ 
+-		err = save_fpx_registers(userspace_pid[current_thread->cpu],
+-					 (unsigned long *) &fpx);
++		err = save_fpx_registers(pid, (unsigned long *) &fpx);
+ 		if (err < 0){
+ 			printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
+ 			       "failed, errno = %d\n", err);
+@@ -276,8 +275,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
+ 	else {
+ 		struct user_i387_struct fp;
+ 
+-		err = save_fp_registers(userspace_pid[current_thread->cpu],
+-					(unsigned long *) &fp);
++		err = save_fp_registers(pid, (unsigned long *) &fp);
+ 		if (copy_to_user(to_fp, &fp, sizeof(struct user_i387_struct)))
+ 			return 1;
+ 	}
+diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S
+index e730772..7699e89 100644
+--- a/arch/um/sys-i386/stub.S
++++ b/arch/um/sys-i386/stub.S
+@@ -7,7 +7,7 @@
+ 	.globl batch_syscall_stub
+ batch_syscall_stub:
+ 	/* load pointer to first operation */
+-	mov	$(ASM_STUB_DATA+8), %esp
++	mov	$(STUB_DATA+8), %esp
+ 
+ again:
+ 	/* load length of additional data */
+@@ -15,12 +15,12 @@ again:
+ 
+ 	/* if(length == 0) : end of list */
+ 	/* write possible 0 to header */
+-	mov	%eax, ASM_STUB_DATA+4
++	mov	%eax, STUB_DATA+4
+ 	cmpl	$0, %eax
+ 	jz	done
+ 
+ 	/* save current pointer */
+-	mov	%esp, ASM_STUB_DATA+4
++	mov	%esp, STUB_DATA+4
+ 
+ 	/* skip additional data */
+ 	add	%eax, %esp
+@@ -46,7 +46,7 @@ again:
+ 
+ done:
+ 	/* save return value */
+-	mov	%eax, ASM_STUB_DATA
++	mov	%eax, STUB_DATA
+ 
+ 	/* stop */
+ 	int3
+diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c
+index b3999cb..28ccf73 100644
+--- a/arch/um/sys-i386/stub_segv.c
++++ b/arch/um/sys-i386/stub_segv.c
+@@ -1,32 +1,17 @@
+ /*
+- * Copyright (C) 2004 Jeff Dike (jdike at addtoit.com)
++ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+-#include <signal.h>
+-#include <sys/select.h> /* The only way I can see to get sigset_t */
+-#include <asm/unistd.h>
+-#include "as-layout.h"
+-#include "uml-config.h"
+ #include "sysdep/stub.h"
+ #include "sysdep/sigcontext.h"
+-#include "sysdep/faultinfo.h"
+ 
+ void __attribute__ ((__section__ (".__syscall_stub")))
+ stub_segv_handler(int sig)
+ {
+ 	struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
+-	int pid;
+ 
+ 	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA), sc);
+ 
+-	pid = stub_syscall0(__NR_getpid);
+-	stub_syscall2(__NR_kill, pid, SIGUSR1);
 -
--#include "../../../../lib/inflate.c"
+-	/* Load pointer to sigcontext into esp, since we need to leave
+-	 * the stack in its original form when we do the sigreturn here, by
+-	 * hand.
+-	 */
+-	__asm__ __volatile__("mov %0,%%esp ; movl %1, %%eax ; "
+-			     "int $0x80" : : "a" (sc), "g" (__NR_sigreturn));
++	trap_myself();
+ }
+diff --git a/arch/um/sys-i386/sys_call_table.S b/arch/um/sys-i386/sys_call_table.S
+index 12d4148..00e5f52 100644
+--- a/arch/um/sys-i386/sys_call_table.S
++++ b/arch/um/sys-i386/sys_call_table.S
+@@ -9,4 +9,9 @@
+ 
+ #define old_mmap old_mmap_i386
+ 
++.section .rodata,"a"
++
+ #include "../../x86/kernel/syscall_table_32.S"
++
++ENTRY(syscall_table_size)
++.long .-sys_call_table
+diff --git a/arch/um/sys-i386/tls.c b/arch/um/sys-i386/tls.c
+index fcaff86..c6c7131 100644
+--- a/arch/um/sys-i386/tls.c
++++ b/arch/um/sys-i386/tls.c
+@@ -26,6 +26,11 @@ int do_set_thread_area(struct user_desc *info)
+ 	cpu = get_cpu();
+ 	ret = os_set_thread_area(info, userspace_pid[cpu]);
+ 	put_cpu();
++
++	if (ret)
++		printk(KERN_ERR "PTRACE_SET_THREAD_AREA failed, err = %d, "
++		       "index = %d\n", ret, info->entry_number);
++
+ 	return ret;
+ }
+ 
+@@ -37,6 +42,11 @@ int do_get_thread_area(struct user_desc *info)
+ 	cpu = get_cpu();
+ 	ret = os_get_thread_area(info, userspace_pid[cpu]);
+ 	put_cpu();
++
++	if (ret)
++		printk(KERN_ERR "PTRACE_GET_THREAD_AREA failed, err = %d, "
++		       "index = %d\n", ret, info->entry_number);
++
+ 	return ret;
+ }
+ 
+@@ -172,7 +182,7 @@ void clear_flushed_tls(struct task_struct *task)
+  * SKAS patch.
+  */
+ 
+-int arch_switch_tls(struct task_struct *from, struct task_struct *to)
++int arch_switch_tls(struct task_struct *to)
+ {
+ 	if (!host_supports_tls)
+ 		return 0;
+@@ -225,7 +235,8 @@ out:
+ }
+ 
+ /* XXX: use do_get_thread_area to read the host value? I'm not at all sure! */
+-static int get_tls_entry(struct task_struct* task, struct user_desc *info, int idx)
++static int get_tls_entry(struct task_struct *task, struct user_desc *info,
++			 int idx)
+ {
+ 	struct thread_struct *t = &task->thread;
+ 
+@@ -263,7 +274,7 @@ clear:
+ 	goto out;
+ }
+ 
+-asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
++int sys_set_thread_area(struct user_desc __user *user_desc)
+ {
+ 	struct user_desc info;
+ 	int idx, ret;
+@@ -298,7 +309,7 @@ asmlinkage int sys_set_thread_area(struct user_desc __user *user_desc)
+  * i386. However the only possible error are caused by bugs.
+  */
+ int ptrace_set_thread_area(struct task_struct *child, int idx,
+-		struct user_desc __user *user_desc)
++			   struct user_desc __user *user_desc)
+ {
+ 	struct user_desc info;
+ 
+@@ -311,7 +322,7 @@ int ptrace_set_thread_area(struct task_struct *child, int idx,
+ 	return set_tls_entry(child, &info, idx, 0);
+ }
+ 
+-asmlinkage int sys_get_thread_area(struct user_desc __user *user_desc)
++int sys_get_thread_area(struct user_desc __user *user_desc)
+ {
+ 	struct user_desc info;
+ 	int idx, ret;
+@@ -355,10 +366,9 @@ out:
+ 	return ret;
+ }
+ 
 -
--static void *malloc(int size)
+ /*
+- * XXX: This part is probably common to i386 and x86-64. Don't create a common
+- * file for now, do that when implementing x86-64 support.
++ * This code is really i386-only, but it detects and logs x86_64 GDT indexes
++ * if a 32-bit UML is running on a 64-bit host.
+  */
+ static int __init __setup_host_supports_tls(void)
+ {
+@@ -367,13 +377,16 @@ static int __init __setup_host_supports_tls(void)
+ 		printk(KERN_INFO "Host TLS support detected\n");
+ 		printk(KERN_INFO "Detected host type: ");
+ 		switch (host_gdt_entry_tls_min) {
+-			case GDT_ENTRY_TLS_MIN_I386:
+-				printk("i386\n");
+-				break;
+-			case GDT_ENTRY_TLS_MIN_X86_64:
+-				printk("x86_64\n");
+-				break;
++		case GDT_ENTRY_TLS_MIN_I386:
++			printk(KERN_CONT "i386");
++			break;
++		case GDT_ENTRY_TLS_MIN_X86_64:
++			printk(KERN_CONT "x86_64");
++			break;
+ 		}
++		printk(KERN_CONT " (GDT indexes %d to %d)\n",
++		       host_gdt_entry_tls_min,
++		       host_gdt_entry_tls_min + GDT_ENTRY_TLS_ENTRIES);
+ 	} else
+ 		printk(KERN_ERR "  Host TLS support NOT detected! "
+ 				"TLS support inside UML will not work\n");
+diff --git a/arch/um/sys-ppc/Makefile b/arch/um/sys-ppc/Makefile
+index a9814a7..0890152 100644
+--- a/arch/um/sys-ppc/Makefile
++++ b/arch/um/sys-ppc/Makefile
+@@ -6,7 +6,7 @@ OBJ = built-in.o
+ OBJS = ptrace.o sigcontext.o semaphore.o checksum.o miscthings.o misc.o \
+ 	ptrace_user.o sysrq.o
+ 
+-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(TOPDIR)/arch/ppc/kernel
++EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
+ 
+ all: $(OBJ)
+ 
+@@ -22,25 +22,25 @@ sigcontext.o: sigcontext.c
+ 
+ semaphore.c:
+ 	rm -f $@
+-	ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
++	ln -s $(srctree)/arch/ppc/kernel/$@ $@
+ 
+ checksum.S:
+ 	rm -f $@
+-	ln -s $(TOPDIR)/arch/ppc/lib/$@ $@
++	ln -s $(srctree)/arch/ppc/lib/$@ $@
+ 
+ mk_defs.c:
+ 	rm -f $@
+-	ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
++	ln -s $(srctree)/arch/ppc/kernel/$@ $@
+ 
+ ppc_defs.head:
+ 	rm -f $@
+-	ln -s $(TOPDIR)/arch/ppc/kernel/$@ $@
++	ln -s $(srctree)/arch/ppc/kernel/$@ $@
+ 
+ ppc_defs.h: mk_defs.c ppc_defs.head \
+-		$(TOPDIR)/include/asm-ppc/mmu.h \
+-		$(TOPDIR)/include/asm-ppc/processor.h \
+-		$(TOPDIR)/include/asm-ppc/pgtable.h \
+-		$(TOPDIR)/include/asm-ppc/ptrace.h
++		$(srctree)/include/asm-ppc/mmu.h \
++		$(srctree)/include/asm-ppc/processor.h \
++		$(srctree)/include/asm-ppc/pgtable.h \
++		$(srctree)/include/asm-ppc/ptrace.h
+ #	$(CC) $(CFLAGS) -S mk_defs.c
+ 	cp ppc_defs.head ppc_defs.h
+ # for bk, this way we can write to the file even if it's not checked out
+@@ -56,13 +56,13 @@ ppc_defs.h: mk_defs.c ppc_defs.head \
+ 
+ checksum.o: checksum.S
+ 	rm -f asm
+-	ln -s $(TOPDIR)/include/asm-ppc asm
++	ln -s $(srctree)/include/asm-ppc asm
+ 	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ 	rm -f asm
+ 
+ misc.o: misc.S ppc_defs.h
+ 	rm -f asm
+-	ln -s $(TOPDIR)/include/asm-ppc asm
++	ln -s $(srctree)/include/asm-ppc asm
+ 	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+ 	rm -f asm
+ 
+diff --git a/arch/um/sys-x86_64/bug.c b/arch/um/sys-x86_64/bug.c
+index a4360b5..e8034e3 100644
+--- a/arch/um/sys-x86_64/bug.c
++++ b/arch/um/sys-x86_64/bug.c
+@@ -5,7 +5,8 @@
+ 
+ #include <linux/uaccess.h>
+ 
+-/* Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
++/*
++ * Mostly copied from i386/x86_86 - eliminated the eip < PAGE_OFFSET because
+  * that's not relevant in skas mode.
+  */
+ 
+diff --git a/arch/um/sys-x86_64/bugs.c b/arch/um/sys-x86_64/bugs.c
+index 506b676..44e02ba 100644
+--- a/arch/um/sys-x86_64/bugs.c
++++ b/arch/um/sys-x86_64/bugs.c
+@@ -6,15 +6,10 @@
+ 
+ #include "sysdep/ptrace.h"
+ 
+-void arch_init_thread(void)
 -{
--	void *p;
--
--	if (size <0) error("Malloc error");
--	if (free_mem_ptr <= 0) error("Memory error");
--
--	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
--
--	p = (void *)free_mem_ptr;
--	free_mem_ptr += size;
--
--	if (free_mem_ptr >= free_mem_end_ptr)
--		error("Out of memory");
--
--	return p;
 -}
 -
--static void free(void *where)
--{	/* Don't care */
+ void arch_check_bugs(void)
+ {
+ }
+ 
+-int arch_handle_signal(int sig, struct uml_pt_regs *regs)
++void arch_examine_signal(int sig, struct uml_pt_regs *regs)
+ {
+-	return 0;
+ }
+diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
+index b7631b0..f3458d7 100644
+--- a/arch/um/sys-x86_64/ptrace.c
++++ b/arch/um/sys-x86_64/ptrace.c
+@@ -5,13 +5,12 @@
+  * Licensed under the GPL
+  */
+ 
+-#define __FRAME_OFFSETS
+-#include <asm/ptrace.h>
++#include <linux/mm.h>
+ #include <linux/sched.h>
+ #include <linux/errno.h>
+-#include <linux/mm.h>
++#define __FRAME_OFFSETS
++#include <asm/ptrace.h>
+ #include <asm/uaccess.h>
+-#include <asm/elf.h>
+ 
+ /*
+  * determines which flags the user has access to.
+@@ -24,12 +23,14 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
+ 	unsigned long tmp;
+ 
+ #ifdef TIF_IA32
+-	/* Some code in the 64bit emulation may not be 64bit clean.
+-	   Don't take any chances. */
++	/*
++	 * Some code in the 64bit emulation may not be 64bit clean.
++	 * Don't take any chances.
++	 */
+ 	if (test_tsk_thread_flag(child, TIF_IA32))
+ 		value &= 0xffffffff;
+ #endif
+-	switch (regno){
++	switch (regno) {
+ 	case FS:
+ 	case GS:
+ 	case DS:
+@@ -66,7 +67,7 @@ int poke_user(struct task_struct *child, long addr, long data)
+ 	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[7]))) {
+ 		addr -= offsetof(struct user, u_debugreg[0]);
+ 		addr = addr >> 2;
+ 		if ((addr == 4) || (addr == 5))
+@@ -108,11 +109,10 @@ int peek_user(struct task_struct *child, long addr, long data)
+ 		return -EIO;
+ 
+ 	tmp = 0;  /* Default return condition */
+-	if (addr < MAX_REG_OFFSET){
++	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[7]))) {
+ 		addr -= offsetof(struct user, u_debugreg[0]);
+ 		addr = addr >> 2;
+ 		tmp = child->thread.arch.debugregs[addr];
+@@ -127,8 +127,9 @@ int is_syscall(unsigned long addr)
+ 	int n;
+ 
+ 	n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
+-	if (n){
+-		/* access_process_vm() grants access to vsyscall and stub,
++	if (n) {
++		/*
++		 * access_process_vm() grants access to vsyscall and stub,
+ 		 * while copy_from_user doesn't. Maybe access_process_vm is
+ 		 * slow, but that doesn't matter, since it will be called only
+ 		 * in case of singlestepping, if copy_from_user failed.
+@@ -155,7 +156,7 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
+ 		return err;
+ 
+ 	n = copy_to_user(buf, fpregs, sizeof(fpregs));
+-	if(n > 0)
++	if (n > 0)
+ 		return -EFAULT;
+ 
+ 	return n;
+diff --git a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
+index b5f9c33..c57a496 100644
+--- a/arch/um/sys-x86_64/ptrace_user.c
++++ b/arch/um/sys-x86_64/ptrace_user.c
+@@ -4,55 +4,19 @@
+  * Licensed under the GPL
+  */
+ 
+-#include <stddef.h>
+ #include <errno.h>
+ #include "ptrace_user.h"
+-#include "user.h"
+-#include "kern_constants.h"
+ 
+ int ptrace_getregs(long pid, unsigned long *regs_out)
+ {
+-	if(ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
+-		return(-errno);
+-	return(0);
 -}
 -
--static void gzip_mark(void **ptr)
+-int ptrace_setregs(long pid, unsigned long *regs)
 -{
--	*ptr = (void *) free_mem_ptr;
+-	if(ptrace(PTRACE_SETREGS, pid, 0, regs) < 0)
+-		return(-errno);
++	if (ptrace(PTRACE_GETREGS, pid, 0, regs_out) < 0)
++		return -errno;
+ 	return(0);
+ }
+ 
+-int ptrace_setfpregs(long pid, unsigned long *regs)
++int ptrace_setregs(long pid, unsigned long *regs_out)
+ {
+-	if (ptrace(PTRACE_SETFPREGS, pid, 0, regs) < 0)
++	if (ptrace(PTRACE_SETREGS, pid, 0, regs_out) < 0)
+ 		return -errno;
+-	return 0;
 -}
 -
--static void gzip_release(void **ptr)
+-void ptrace_pokeuser(unsigned long addr, unsigned long data)
 -{
--	free_mem_ptr = (long) *ptr;
+-	panic("ptrace_pokeuser");
 -}
-- 
--static void scroll(void)
--{
--	int i;
 -
--	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
--	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
--		vidmem[i] = ' ';
--}
+-#define DS 184
+-#define ES 192
+-#define __USER_DS     0x2b
 -
--static void putstr(const char *s)
+-void arch_enter_kernel(void *task, int pid)
 -{
--	int x,y,pos;
--	char c;
+-}
 -
--	x = RM_SCREEN_INFO.orig_x;
--	y = RM_SCREEN_INFO.orig_y;
+-void arch_leave_kernel(void *task, int pid)
+-{
+-#ifdef UM_USER_CS
+-        if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
+-                printk("POKEUSR CS failed");
+-#endif
 -
--	while ( ( c = *s++ ) != '\0' ) {
--		if ( c == '\n' ) {
--			x = 0;
--			if ( ++y >= lines ) {
--				scroll();
--				y--;
--			}
--		} else {
--			vidmem [ ( x + cols * y ) * 2 ] = c; 
--			if ( ++x >= cols ) {
--				x = 0;
--				if ( ++y >= lines ) {
--					scroll();
--					y--;
--				}
--			}
--		}
--	}
--
--	RM_SCREEN_INFO.orig_x = x;
--	RM_SCREEN_INFO.orig_y = y;
--
--	pos = (x + cols * y) * 2;	/* Update cursor position */
--	outb_p(14, vidport);
--	outb_p(0xff & (pos >> 9), vidport+1);
--	outb_p(15, vidport);
--	outb_p(0xff & (pos >> 1), vidport+1);
--}
--
--static void* memset(void* s, int c, unsigned n)
--{
--	int i;
--	char *ss = (char*)s;
--
--	for (i=0;i<n;i++) ss[i] = c;
--	return s;
--}
--
--static void* memcpy(void* dest, const void* src, unsigned n)
--{
--	int i;
--	char *d = (char *)dest, *s = (char *)src;
--
--	for (i=0;i<n;i++) d[i] = s[i];
--	return dest;
--}
--
--/* ===========================================================================
-- * Fill the input buffer. This is called only when the buffer is empty
-- * and at least one byte is really needed.
-- */
--static int fill_inbuf(void)
--{
--	error("ran out of input data");
--	return 0;
--}
--
--/* ===========================================================================
-- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
-- * (Used for the decompressed data only.)
-- */
--static void flush_window(void)
--{
--	/* With my window equal to my output buffer
--	 * I only need to compute the crc here.
--	 */
--	ulg c = crc;         /* temporary variable */
--	unsigned n;
--	uch *in, ch;
--
--	in = window;
--	for (n = 0; n < outcnt; n++) {
--		ch = *in++;
--		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
--	}
--	crc = c;
--	bytes_out += (ulg)outcnt;
--	outcnt = 0;
--}
--
--static void error(char *x)
--{
--	putstr("\n\n");
--	putstr(x);
--	putstr("\n\n -- System halted");
--
--	while(1);	/* Halt */
--}
--
--asmlinkage void decompress_kernel(void *rmode, unsigned long heap,
--	uch *input_data, unsigned long input_len, uch *output)
--{
--	real_mode = rmode;
--
--	if (RM_SCREEN_INFO.orig_video_mode == 7) {
--		vidmem = (char *) 0xb0000;
--		vidport = 0x3b4;
--	} else {
--		vidmem = (char *) 0xb8000;
--		vidport = 0x3d4;
--	}
--
--	lines = RM_SCREEN_INFO.orig_video_lines;
--	cols = RM_SCREEN_INFO.orig_video_cols;
--
--	window = output;  		/* Output buffer (Normally at 1M) */
--	free_mem_ptr     = heap;	/* Heap  */
--	free_mem_end_ptr = heap + HEAP_SIZE;
--	inbuf  = input_data;		/* Input buffer */
--	insize = input_len;
--	inptr  = 0;
--
--	if ((ulg)output & (__KERNEL_ALIGN - 1))
--		error("Destination address not 2M aligned");
--	if ((ulg)output >= 0xffffffffffUL)
--		error("Destination address too large");
--
--	makecrc();
--	putstr(".\nDecompressing Linux...");
--	gunzip();
--	putstr("done.\nBooting the kernel.\n");
--	return;
--}
-diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
-index 7a0d00b..d01ea42 100644
---- a/arch/x86/boot/compressed/relocs.c
-+++ b/arch/x86/boot/compressed/relocs.c
-@@ -27,11 +27,6 @@ static unsigned long *relocs;
-  * absolute relocations present w.r.t these symbols.
+-        if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
+-                printk("POKEUSR DS failed");
+-        if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
+-                printk("POKEUSR ES failed");
++	return(0);
+ }
+diff --git a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
+index 1778d33..1a899a7 100644
+--- a/arch/um/sys-x86_64/signal.c
++++ b/arch/um/sys-x86_64/signal.c
+@@ -4,11 +4,11 @@
+  * Licensed under the GPL
   */
- static const char* safe_abs_relocs[] = {
--		"__kernel_vsyscall",
--		"__kernel_rt_sigreturn",
--		"__kernel_sigreturn",
--		"SYSENTER_RETURN",
--		"VDSO_NOTE_MASK",
- 		"xen_irq_disable_direct_reloc",
- 		"xen_save_fl_direct_reloc",
- };
-@@ -45,6 +40,8 @@ static int is_safe_abs_reloc(const char* sym_name)
- 			/* Match found */
- 			return 1;
- 	}
-+	if (strncmp(sym_name, "VDSO", 4) == 0)
-+		return 1;
- 	if (strncmp(sym_name, "__crc_", 6) == 0)
+ 
+-#include "linux/personality.h"
+-#include "linux/ptrace.h"
+-#include "asm/unistd.h"
+-#include "asm/uaccess.h"
+-#include "asm/ucontext.h"
++#include <linux/personality.h>
++#include <linux/ptrace.h>
++#include <asm/unistd.h>
++#include <asm/uaccess.h>
++#include <asm/ucontext.h>
+ #include "frame_kern.h"
+ #include "skas.h"
+ 
+@@ -27,16 +27,16 @@ void copy_sc(struct uml_pt_regs *regs, void *from)
+ 	GETREG(regs, R13, sc, r13);
+ 	GETREG(regs, R14, sc, r14);
+ 	GETREG(regs, R15, sc, r15);
+-	GETREG(regs, RDI, sc, rdi);
+-	GETREG(regs, RSI, sc, rsi);
+-	GETREG(regs, RBP, sc, rbp);
+-	GETREG(regs, RBX, sc, rbx);
+-	GETREG(regs, RDX, sc, rdx);
+-	GETREG(regs, RAX, sc, rax);
+-	GETREG(regs, RCX, sc, rcx);
+-	GETREG(regs, RSP, sc, rsp);
+-	GETREG(regs, RIP, sc, rip);
+-	GETREG(regs, EFLAGS, sc, eflags);
++	GETREG(regs, RDI, sc, di);
++	GETREG(regs, RSI, sc, si);
++	GETREG(regs, RBP, sc, bp);
++	GETREG(regs, RBX, sc, bx);
++	GETREG(regs, RDX, sc, dx);
++	GETREG(regs, RAX, sc, ax);
++	GETREG(regs, RCX, sc, cx);
++	GETREG(regs, RSP, sc, sp);
++	GETREG(regs, RIP, sc, ip);
++	GETREG(regs, EFLAGS, sc, flags);
+ 	GETREG(regs, CS, sc, cs);
+ 
+ #undef GETREG
+@@ -61,16 +61,16 @@ static int copy_sc_from_user(struct pt_regs *regs,
+ 	err |= GETREG(regs, R13, from, r13);
+ 	err |= GETREG(regs, R14, from, r14);
+ 	err |= GETREG(regs, R15, from, r15);
+-	err |= GETREG(regs, RDI, from, rdi);
+-	err |= GETREG(regs, RSI, from, rsi);
+-	err |= GETREG(regs, RBP, from, rbp);
+-	err |= GETREG(regs, RBX, from, rbx);
+-	err |= GETREG(regs, RDX, from, rdx);
+-	err |= GETREG(regs, RAX, from, rax);
+-	err |= GETREG(regs, RCX, from, rcx);
+-	err |= GETREG(regs, RSP, from, rsp);
+-	err |= GETREG(regs, RIP, from, rip);
+-	err |= GETREG(regs, EFLAGS, from, eflags);
++	err |= GETREG(regs, RDI, from, di);
++	err |= GETREG(regs, RSI, from, si);
++	err |= GETREG(regs, RBP, from, bp);
++	err |= GETREG(regs, RBX, from, bx);
++	err |= GETREG(regs, RDX, from, dx);
++	err |= GETREG(regs, RAX, from, ax);
++	err |= GETREG(regs, RCX, from, cx);
++	err |= GETREG(regs, RSP, from, sp);
++	err |= GETREG(regs, RIP, from, ip);
++	err |= GETREG(regs, EFLAGS, from, flags);
+ 	err |= GETREG(regs, CS, from, cs);
+ 	if (err)
  		return 1;
- 	return 0;
-diff --git a/arch/x86/boot/compressed/vmlinux.scr b/arch/x86/boot/compressed/vmlinux.scr
-new file mode 100644
-index 0000000..f02382a
---- /dev/null
-+++ b/arch/x86/boot/compressed/vmlinux.scr
-@@ -0,0 +1,10 @@
-+SECTIONS
-+{
-+  .rodata.compressed : {
-+	input_len = .;
-+	LONG(input_data_end - input_data) input_data = .;
-+	*(.data)
-+	output_len = . - 4;
-+	input_data_end = .;
-+	}
-+}
-diff --git a/arch/x86/boot/compressed/vmlinux_32.lds b/arch/x86/boot/compressed/vmlinux_32.lds
-index cc4854f..bb3c483 100644
---- a/arch/x86/boot/compressed/vmlinux_32.lds
-+++ b/arch/x86/boot/compressed/vmlinux_32.lds
-@@ -3,17 +3,17 @@ OUTPUT_ARCH(i386)
- ENTRY(startup_32)
- SECTIONS
- {
--        /* Be careful parts of head.S assume startup_32 is at
--         * address 0.
-+	/* Be careful parts of head_32.S assume startup_32 is at
-+	 * address 0.
- 	 */
--	. =  0 	;
-+	. = 0;
- 	.text.head : {
- 		_head = . ;
- 		*(.text.head)
- 		_ehead = . ;
- 	}
--	.data.compressed : {
--		*(.data.compressed)
-+	.rodata.compressed : {
-+		*(.rodata.compressed)
- 	}
- 	.text :	{
- 		_text = .; 	/* Text */
-diff --git a/arch/x86/boot/compressed/vmlinux_32.scr b/arch/x86/boot/compressed/vmlinux_32.scr
-deleted file mode 100644
-index 707a88f..0000000
---- a/arch/x86/boot/compressed/vmlinux_32.scr
-+++ /dev/null
-@@ -1,10 +0,0 @@
--SECTIONS
--{
--  .data.compressed : {
--	input_len = .;
--	LONG(input_data_end - input_data) input_data = .; 
--	*(.data) 
--	output_len = . - 4;
--	input_data_end = .; 
--	}
--}
-diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux_64.lds
-index 94c13e5..7e5c720 100644
---- a/arch/x86/boot/compressed/vmlinux_64.lds
-+++ b/arch/x86/boot/compressed/vmlinux_64.lds
-@@ -3,15 +3,19 @@ OUTPUT_ARCH(i386:x86-64)
- ENTRY(startup_64)
- SECTIONS
- {
--	/* Be careful parts of head.S assume startup_32 is at
-- 	 * address 0.
-+	/* Be careful parts of head_64.S assume startup_32 is at
-+	 * address 0.
+@@ -81,7 +81,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
+ 	if (err)
+ 		return 1;
+ 
+-	err = restore_fp_registers(userspace_pid[current_thread->cpu],
++	err = restore_fp_registers(userspace_pid[current_thread_info()->cpu],
+ 				   (unsigned long *) &fp);
+ 	if (err < 0) {
+ 		printk(KERN_ERR "copy_sc_from_user - "
+@@ -108,19 +108,19 @@ static int copy_sc_to_user(struct sigcontext __user *to,
+ 	__put_user((regs)->regs.gp[(regno) / sizeof(unsigned long)],	\
+ 		   &(sc)->regname)
+ 
+-	err |= PUTREG(regs, RDI, to, rdi);
+-	err |= PUTREG(regs, RSI, to, rsi);
+-	err |= PUTREG(regs, RBP, to, rbp);
++	err |= PUTREG(regs, RDI, to, di);
++	err |= PUTREG(regs, RSI, to, si);
++	err |= PUTREG(regs, RBP, to, bp);
+ 	/*
+-	 * Must use orignal RSP, which is passed in, rather than what's in
++	 * Must use original RSP, which is passed in, rather than what's in
+ 	 * the pt_regs, because that's already been updated to point at the
+ 	 * signal frame.
  	 */
- 	. = 0;
--	.text :	{
-+	.text.head : {
- 		_head = . ;
- 		*(.text.head)
- 		_ehead = . ;
--		*(.text.compressed)
-+	}
-+	.rodata.compressed : {
-+		*(.rodata.compressed)
-+	}
-+	.text :	{
- 		_text = .; 	/* Text */
- 		*(.text)
- 		*(.text.*)
-diff --git a/arch/x86/boot/compressed/vmlinux_64.scr b/arch/x86/boot/compressed/vmlinux_64.scr
-deleted file mode 100644
-index bd1429c..0000000
---- a/arch/x86/boot/compressed/vmlinux_64.scr
-+++ /dev/null
-@@ -1,10 +0,0 @@
--SECTIONS
+-	err |= __put_user(sp, &to->rsp);
+-	err |= PUTREG(regs, RBX, to, rbx);
+-	err |= PUTREG(regs, RDX, to, rdx);
+-	err |= PUTREG(regs, RCX, to, rcx);
+-	err |= PUTREG(regs, RAX, to, rax);
++	err |= __put_user(sp, &to->sp);
++	err |= PUTREG(regs, RBX, to, bx);
++	err |= PUTREG(regs, RDX, to, dx);
++	err |= PUTREG(regs, RCX, to, cx);
++	err |= PUTREG(regs, RAX, to, ax);
+ 	err |= PUTREG(regs, R8, to, r8);
+ 	err |= PUTREG(regs, R9, to, r9);
+ 	err |= PUTREG(regs, R10, to, r10);
+@@ -135,15 +135,15 @@ static int copy_sc_to_user(struct sigcontext __user *to,
+ 	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);
++	err |= PUTREG(regs, RIP, to, ip);
++	err |= PUTREG(regs, EFLAGS, to, flags);
+ #undef PUTREG
+ 
+ 	err |= __put_user(mask, &to->oldmask);
+ 	if (err)
+ 		return 1;
+ 
+-	err = save_fp_registers(userspace_pid[current_thread->cpu],
++	err = save_fp_registers(userspace_pid[current_thread_info()->cpu],
+ 				(unsigned long *) &fp);
+ 	if (err < 0) {
+ 		printk(KERN_ERR "copy_sc_from_user - restore_fp_registers "
+diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S
+index 4afe204..5687687 100644
+--- a/arch/um/sys-x86_64/stub.S
++++ b/arch/um/sys-x86_64/stub.S
+@@ -8,18 +8,18 @@ syscall_stub:
+ 	/* We don't have 64-bit constants, so this constructs the address
+ 	 * we need.
+ 	 */
+-	movq	$(ASM_STUB_DATA >> 32), %rbx
++	movq	$(STUB_DATA >> 32), %rbx
+ 	salq	$32, %rbx
+-	movq	$(ASM_STUB_DATA & 0xffffffff), %rcx
++	movq	$(STUB_DATA & 0xffffffff), %rcx
+ 	or	%rcx, %rbx
+ 	movq	%rax, (%rbx)
+ 	int3
+ 
+ 	.globl batch_syscall_stub
+ batch_syscall_stub:
+-	mov	$(ASM_STUB_DATA >> 32), %rbx
++	mov	$(STUB_DATA >> 32), %rbx
+ 	sal	$32, %rbx
+-	mov	$(ASM_STUB_DATA & 0xffffffff), %rax
++	mov	$(STUB_DATA & 0xffffffff), %rax
+ 	or	%rax, %rbx
+ 	/* load pointer to first operation */
+ 	mov	%rbx, %rsp
+diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c
+index 3afb590..ced051a 100644
+--- a/arch/um/sys-x86_64/stub_segv.c
++++ b/arch/um/sys-x86_64/stub_segv.c
+@@ -1,51 +1,22 @@
+ /*
+- * Copyright (C) 2004 Jeff Dike (jdike at addtoit.com)
++ * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+-#include <stddef.h>
+ #include <signal.h>
+-#include <asm/unistd.h>
+ #include "as-layout.h"
+-#include "uml-config.h"
+-#include "sysdep/sigcontext.h"
+-#include "sysdep/faultinfo.h"
+ #include "sysdep/stub.h"
+-
+-/* Copied from sys-x86_64/signal.c - Can't find an equivalent definition
+- * in the libc headers anywhere.
+- */
+-struct rt_sigframe
 -{
--  .text.compressed : {
--	input_len = .;
--	LONG(input_data_end - input_data) input_data = .;
--	*(.data)
--	output_len = . - 4;
--	input_data_end = .;
--	}
--}
-diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
-index bd138e4..8721dc4 100644
---- a/arch/x86/boot/edd.c
-+++ b/arch/x86/boot/edd.c
-@@ -129,6 +129,7 @@ void query_edd(void)
- 	char eddarg[8];
- 	int do_mbr = 1;
- 	int do_edd = 1;
-+	int be_quiet;
- 	int devno;
- 	struct edd_info ei, *edp;
- 	u32 *mbrptr;
-@@ -140,12 +141,21 @@ void query_edd(void)
- 			do_edd = 0;
- 	}
+-	char *pretcode;
+-	struct ucontext uc;
+-	struct siginfo info;
+-};
+-
+-/* Copied here from <linux/kernel.h> - we're userspace. */
+-#define container_of(ptr, type, member) ({                   \
+-	const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+-	(type *)( (char *)__mptr - offsetof(type,member) );})
++#include "sysdep/faultinfo.h"
++#include "sysdep/sigcontext.h"
+ 
+ void __attribute__ ((__section__ (".__syscall_stub")))
+ stub_segv_handler(int sig)
+ {
+ 	struct ucontext *uc;
+-        int pid;
+ 
+ 	__asm__ __volatile__("movq %%rdx, %0" : "=g" (uc) :);
+ 	GET_FAULTINFO_FROM_SC(*((struct faultinfo *) STUB_DATA),
+ 			      &uc->uc_mcontext);
+-
+-	pid = stub_syscall0(__NR_getpid);
+-	stub_syscall2(__NR_kill, pid, SIGUSR1);
+-
+-	/* sys_sigreturn expects that the stack pointer will be 8 bytes into
+-	 * the signal frame.  So, we use the ucontext pointer, which we know
+-	 * already, to get the signal frame pointer, and add 8 to that.
+-	 */
+-	__asm__ __volatile__("movq %0, %%rsp; movq %1, %%rax ; syscall": :
+-                             "g" ((unsigned long)
+-                                  container_of(uc, struct rt_sigframe, uc) + 8),
+-                             "g" (__NR_rt_sigreturn));
++	trap_myself();
+ }
++
+diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c
+index 71b2ae4..c128eb8 100644
+--- a/arch/um/sys-x86_64/syscall_table.c
++++ b/arch/um/sys-x86_64/syscall_table.c
+@@ -1,5 +1,7 @@
+-/* System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
+- * with some changes for UML. */
++/*
++ * System call table for UML/x86-64, copied from arch/x86_64/kernel/syscall.c
++ * with some changes for UML.
++ */
  
-+	be_quiet = cmdline_find_option_bool("quiet");
-+
- 	edp    = boot_params.eddbuf;
- 	mbrptr = boot_params.edd_mbr_sig_buffer;
+ #include <linux/linkage.h>
+ #include <linux/sys.h>
+@@ -8,22 +10,26 @@
  
- 	if (!do_edd)
- 		return;
+ #define __NO_STUBS
  
-+	/* Bugs in OnBoard or AddOnCards Bios may hang the EDD probe,
-+	 * so give a hint if this happens.
-+	 */
-+
-+	if (!be_quiet)
-+		printf("Probing EDD (edd=off to disable)... ");
+-/* Below you can see, in terms of #define's, the differences between the x86-64
+- * and the UML syscall table. */
++/*
++ * 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*/
++/*
++ * The UML TLS problem. Note that x86_64 does not implement this, so the below
++ * is needed only for the ia32 compatibility.
++ */
+ 
+ /* 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 */
++/*
++ * 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
+@@ -46,8 +52,19 @@ typedef void (*sys_call_ptr_t)(void);
+ 
+ extern void sys_ni_syscall(void);
+ 
+-sys_call_ptr_t sys_call_table[UM_NR_syscall_max+1] __cacheline_aligned = {
+-	/* Smells like a like a compiler bug -- it doesn't work when the & below is removed. */
+-	[0 ... UM_NR_syscall_max] = &sys_ni_syscall,
++/*
++ * We used to have a trick here which made sure that holes in the
++ * x86_64 table were filled in with sys_ni_syscall, but a comment in
++ * unistd_64.h says that holes aren't allowed, so the trick was
++ * removed.
++ * The trick looked like this
++ *	[0 ... UM_NR_syscall_max] = &sys_ni_syscall
++ * before including unistd_64.h - the later initializations overwrote
++ * the sys_ni_syscall filler.
++ */
 +
- 	for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) {
- 		/*
- 		 * Scan the BIOS-supported hard disks and query EDD
-@@ -162,6 +172,9 @@ void query_edd(void)
- 		if (do_mbr && !read_mbr_sig(devno, &ei, mbrptr++))
- 			boot_params.edd_mbr_sig_buf_entries = devno-0x80+1;
- 	}
++sys_call_ptr_t sys_call_table[] __cacheline_aligned = {
+ #include <asm-x86/unistd_64.h>
+ };
 +
-+	if (!be_quiet)
-+		printf("ok\n");
++int syscall_table_size = sizeof(sys_call_table);
+diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
+index 86f6b18..f1199fd 100644
+--- a/arch/um/sys-x86_64/syscalls.c
++++ b/arch/um/sys-x86_64/syscalls.c
+@@ -48,7 +48,9 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
+ 	switch (code) {
+ 	case ARCH_SET_FS:
+ 	case ARCH_SET_GS:
+-		restore_registers(pid, &current->thread.regs.regs);
++		ret = restore_registers(pid, &current->thread.regs.regs);
++		if (ret)
++			return ret;
+ 		break;
+ 	case ARCH_GET_FS:
+ 	case ARCH_GET_GS:
+@@ -70,10 +72,10 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
+ 	switch (code) {
+ 	case ARCH_SET_FS:
+ 		current->thread.arch.fs = (unsigned long) ptr;
+-		save_registers(pid, &current->thread.regs.regs);
++		ret = save_registers(pid, &current->thread.regs.regs);
+ 		break;
+ 	case ARCH_SET_GS:
+-		save_registers(pid, &current->thread.regs.regs);
++		ret = save_registers(pid, &current->thread.regs.regs);
+ 		break;
+ 	case ARCH_GET_FS:
+ 		ret = put_user(tmp, addr);
+@@ -105,7 +107,7 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
+ 	return ret;
  }
  
- #endif
-diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
-index 4cc5b04..64ad901 100644
---- a/arch/x86/boot/header.S
-+++ b/arch/x86/boot/header.S
-@@ -195,10 +195,13 @@ cmd_line_ptr:	.long	0		# (Header version 0x0202 or later)
- 					# can be located anywhere in
- 					# low memory 0x10000 or higher.
+-void arch_switch_to(struct task_struct *from, struct task_struct *to)
++void arch_switch_to(struct task_struct *to)
+ {
+ 	if ((to->thread.arch.fs == 0) || (to->mm == NULL))
+ 		return;
+diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
+index 7654440..f4f82be 100644
+--- a/arch/um/sys-x86_64/sysrq.c
++++ b/arch/um/sys-x86_64/sysrq.c
+@@ -4,32 +4,33 @@
+  * Licensed under the GPL
+  */
  
--ramdisk_max:	.long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
-+ramdisk_max:	.long 0x7fffffff
- 					# (Header version 0x0203 or later)
- 					# The highest safe address for
- 					# the contents of an initrd
-+					# The current kernel allows up to 4 GB,
-+					# but leave it at 2 GB to avoid
-+					# possible bootloader bugs.
+-#include "linux/kernel.h"
+-#include "linux/utsname.h"
+-#include "linux/module.h"
+-#include "asm/current.h"
+-#include "asm/ptrace.h"
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/utsname.h>
++#include <asm/current.h>
++#include <asm/ptrace.h>
+ #include "sysrq.h"
  
- kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN	#physical addr alignment
- 						#required for protected mode
-diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
-index 1f95750..7828da5 100644
---- a/arch/x86/boot/main.c
-+++ b/arch/x86/boot/main.c
-@@ -100,20 +100,32 @@ static void set_bios_mode(void)
- #endif
- }
+-void __show_regs(struct pt_regs * regs)
++void __show_regs(struct pt_regs *regs)
+ {
+ 	printk("\n");
+ 	print_modules();
+-	printk("Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
++	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
+ 		current->comm, print_tainted(), init_utsname()->release);
+-	printk("RIP: %04lx:[<%016lx>] ", PT_REGS_CS(regs) & 0xffff,
++	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
+ 	       PT_REGS_RIP(regs));
+-	printk("\nRSP: %016lx  EFLAGS: %08lx\n", PT_REGS_RSP(regs),
++	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_RSP(regs),
+ 	       PT_REGS_EFLAGS(regs));
+-	printk("RAX: %016lx RBX: %016lx RCX: %016lx\n",
++	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
+ 	       PT_REGS_RAX(regs), PT_REGS_RBX(regs), PT_REGS_RCX(regs));
+-	printk("RDX: %016lx RSI: %016lx RDI: %016lx\n",
++	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
+ 	       PT_REGS_RDX(regs), PT_REGS_RSI(regs), PT_REGS_RDI(regs));
+-	printk("RBP: %016lx R08: %016lx R09: %016lx\n",
++	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
+ 	       PT_REGS_RBP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
+-	printk("R10: %016lx R11: %016lx R12: %016lx\n",
++	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
+ 	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
+-	printk("R13: %016lx R14: %016lx R15: %016lx\n",
++	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
+ 	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
+ }
+ 
+diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c
+index 8b8eff1..3dead39 100644
+--- a/arch/um/sys-x86_64/um_module.c
++++ b/arch/um/sys-x86_64/um_module.c
+@@ -1,7 +1,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/moduleloader.h>
  
--void main(void)
-+static void init_heap(void)
+-/*Copied from i386 arch/i386/kernel/module.c */
++/* Copied from i386 arch/i386/kernel/module.c */
+ void *module_alloc(unsigned long size)
  {
--	/* First, copy the boot header into the "zeropage" */
--	copy_boot_params();
-+	char *stack_end;
+ 	if (size == 0)
+@@ -13,7 +13,9 @@ void *module_alloc(unsigned long size)
+ void module_free(struct module *mod, void *module_region)
+ {
+ 	vfree(module_region);
+-	/* FIXME: If module_region == mod->init_region, trim exception
+-           table entries. */
++	/*
++	 * FIXME: If module_region == mod->init_region, trim exception
++	 * table entries.
++	 */
+ }
  
--	/* End of heap check */
- 	if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
--		heap_end = (char *)(boot_params.hdr.heap_end_ptr
--				    +0x200-STACK_SIZE);
-+		asm("leal %P1(%%esp),%0"
-+		    : "=r" (stack_end) : "i" (-STACK_SIZE));
-+
-+		heap_end = (char *)
-+			((size_t)boot_params.hdr.heap_end_ptr + 0x200);
-+		if (heap_end > stack_end)
-+			heap_end = stack_end;
- 	} else {
- 		/* Boot protocol 2.00 only, no heap available */
- 		puts("WARNING: Ancient bootloader, some functionality "
- 		     "may be limited!\n");
- 	}
-+}
-+
-+void main(void)
-+{
-+	/* First, copy the boot header into the "zeropage" */
-+	copy_boot_params();
-+
-+	/* End of heap check */
-+	init_heap();
+diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
+index b6a50b8..ace479a 100644
+--- a/arch/v850/Kconfig
++++ b/arch/v850/Kconfig
+@@ -331,8 +331,6 @@ source "sound/Kconfig"
  
- 	/* Make sure we have all the proper CPU support */
- 	if (validate_cpu()) {
-@@ -131,9 +143,6 @@ void main(void)
- 	/* Set keyboard repeat rate (why?) */
- 	keyboard_set_repeat();
+ source "drivers/usb/Kconfig"
  
--	/* Set the video mode */
--	set_video();
+-source "kernel/Kconfig.instrumentation"
 -
- 	/* Query MCA information */
- 	query_mca();
+ source "arch/v850/Kconfig.debug"
  
-@@ -154,6 +163,10 @@ void main(void)
- #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
- 	query_edd();
- #endif
+ source "security/Kconfig"
+diff --git a/arch/v850/kernel/vmlinux.lds.S b/arch/v850/kernel/vmlinux.lds.S
+index 6172599..d08cd1d 100644
+--- a/arch/v850/kernel/vmlinux.lds.S
++++ b/arch/v850/kernel/vmlinux.lds.S
+@@ -114,7 +114,7 @@
+ #define DATA_CONTENTS							      \
+ 		__sdata = . ;						      \
+ 		DATA_DATA						      \
+-			*(.exit.data)	/* 2.5 convention */		      \
++			EXIT_DATA	/* 2.5 convention */		      \
+ 			*(.data.exit)	/* 2.4 convention */		      \
+ 		. = ALIGN (16) ;					      \
+ 		*(.data.cacheline_aligned)				      \
+@@ -157,9 +157,9 @@
+ 		. = ALIGN (4096) ;					      \
+ 		__init_start = . ;					      \
+ 			__sinittext = .;				      \
+-			*(.init.text)	/* 2.5 convention */		      \
++			INIT_TEXT	/* 2.5 convention */		      \
+ 			__einittext = .;				      \
+-			*(.init.data)					      \
++			INIT_DATA					      \
+ 			*(.text.init)	/* 2.4 convention */		      \
+ 			*(.data.init)					      \
+ 		INITCALL_CONTENTS					      \
+@@ -170,7 +170,7 @@
+ #define ROMK_INIT_RAM_CONTENTS						      \
+ 		. = ALIGN (4096) ;					      \
+ 		__init_start = . ;					      \
+-			*(.init.data)	/* 2.5 convention */		      \
++			INIT_DATA	/* 2.5 convention */		      \
+ 			*(.data.init)	/* 2.4 convention */		      \
+ 		__init_end = . ;					      \
+ 		. = ALIGN (4096) ;
+@@ -179,7 +179,7 @@
+    should go into ROM.  */	
+ #define ROMK_INIT_ROM_CONTENTS						      \
+ 			_sinittext = .;					      \
+-			*(.init.text)	/* 2.5 convention */		      \
++			INIT_TEXT	/* 2.5 convention */		      \
+ 			_einittext = .;					      \
+ 			*(.text.init)	/* 2.4 convention */		      \
+ 		INITCALL_CONTENTS					      \
+diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
+index 80b7ba4..4348211 100644
+--- a/arch/x86/Kconfig
++++ b/arch/x86/Kconfig
+@@ -17,81 +17,74 @@ config X86_64
+ 
+ ### Arch settings
+ config X86
+-	bool
+-	default y
++	def_bool y
++	select HAVE_OPROFILE
++	select HAVE_KPROBES
 +
-+	/* Set the video mode */
-+	set_video();
++config GENERIC_LOCKBREAK
++	def_bool n
+ 
+ config GENERIC_TIME
+-	bool
+-	default y
++	def_bool y
+ 
+ config GENERIC_CMOS_UPDATE
+-	bool
+-	default y
++	def_bool y
+ 
+ config CLOCKSOURCE_WATCHDOG
+-	bool
+-	default y
++	def_bool y
+ 
+ config GENERIC_CLOCKEVENTS
+-	bool
+-	default y
++	def_bool y
+ 
+ config GENERIC_CLOCKEVENTS_BROADCAST
+-	bool
+-	default y
++	def_bool y
+ 	depends on X86_64 || (X86_32 && X86_LOCAL_APIC)
+ 
+ config LOCKDEP_SUPPORT
+-	bool
+-	default y
++	def_bool y
+ 
+ config STACKTRACE_SUPPORT
+-	bool
+-	default y
++	def_bool y
 +
- 	/* Do the last things and invoke protected mode */
- 	go_to_protected_mode();
- }
-diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
-index 09fb342..1a0f936 100644
---- a/arch/x86/boot/pm.c
-+++ b/arch/x86/boot/pm.c
-@@ -104,7 +104,7 @@ static void reset_coprocessor(void)
- 	(((u64)(base & 0xff000000) << 32) |	\
- 	 ((u64)flags << 40) |			\
- 	 ((u64)(limit & 0x00ff0000) << 32) |	\
--	 ((u64)(base & 0x00ffff00) << 16) |	\
-+	 ((u64)(base & 0x00ffffff) << 16) |	\
- 	 ((u64)(limit & 0x0000ffff)))
++config HAVE_LATENCYTOP_SUPPORT
++	def_bool y
  
- struct gdt_ptr {
-@@ -121,6 +121,10 @@ static void setup_gdt(void)
- 		[GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
- 		/* DS: data, read/write, 4 GB, base 0 */
- 		[GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
-+		/* TSS: 32-bit tss, 104 bytes, base 4096 */
-+		/* We only have a TSS here to keep Intel VT happy;
-+		   we don't actually use it for anything. */
-+		[GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
- 	};
- 	/* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
- 	   of the gdt_ptr contents.  Thus, make it static so it will
-diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
-index fa6bed1..f5402d5 100644
---- a/arch/x86/boot/pmjump.S
-+++ b/arch/x86/boot/pmjump.S
-@@ -15,6 +15,7 @@
-  */
+ config SEMAPHORE_SLEEPERS
+-	bool
+-	default y
++	def_bool y
  
- #include <asm/boot.h>
-+#include <asm/processor-flags.h>
- #include <asm/segment.h>
+ config MMU
+-	bool
+-	default y
++	def_bool y
  
- 	.text
-@@ -29,28 +30,55 @@
-  */
- protected_mode_jump:
- 	movl	%edx, %esi		# Pointer to boot_params table
--	movl	%eax, 2f		# Patch ljmpl instruction
+ config ZONE_DMA
+-	bool
+-	default y
++	def_bool y
+ 
+ config QUICKLIST
+-	bool
+-	default X86_32
++	def_bool X86_32
+ 
+ config SBUS
+ 	bool
+ 
+ config GENERIC_ISA_DMA
+-	bool
+-	default y
++	def_bool y
+ 
+ config GENERIC_IOMAP
+-	bool
+-	default y
++	def_bool y
+ 
+ config GENERIC_BUG
+-	bool
+-	default y
++	def_bool y
+ 	depends on BUG
+ 
+ config GENERIC_HWEIGHT
+-	bool
+-	default y
++	def_bool y
 +
-+	xorl	%ebx, %ebx
-+	movw	%cs, %bx
-+	shll	$4, %ebx
-+	addl	%ebx, 2f
++config GENERIC_GPIO
++	def_bool n
  
- 	movw	$__BOOT_DS, %cx
--	xorl	%ebx, %ebx		# Per the 32-bit boot protocol
--	xorl	%ebp, %ebp		# Per the 32-bit boot protocol
--	xorl	%edi, %edi		# Per the 32-bit boot protocol
-+	movw	$__BOOT_TSS, %di
+ config ARCH_MAY_HAVE_PC_FDC
+-	bool
+-	default y
++	def_bool y
  
- 	movl	%cr0, %edx
--	orb	$1, %dl			# Protected mode (PE) bit
-+	orb	$X86_CR0_PE, %dl	# Protected mode
- 	movl	%edx, %cr0
- 	jmp	1f			# Short jump to serialize on 386/486
- 1:
+ config DMI
+-	bool
+-	default y
++	def_bool y
  
--	movw	%cx, %ds
--	movw	%cx, %es
--	movw	%cx, %fs
--	movw	%cx, %gs
--	movw	%cx, %ss
--
--	# Jump to the 32-bit entrypoint
-+	# Transition to 32-bit mode
- 	.byte	0x66, 0xea		# ljmpl opcode
--2:	.long	0			# offset
-+2:	.long	in_pm32			# offset
- 	.word	__BOOT_CS		# segment
+ config RWSEM_GENERIC_SPINLOCK
+ 	def_bool !X86_XADD
+@@ -112,10 +105,18 @@ config GENERIC_TIME_VSYSCALL
+ 	bool
+ 	default X86_64
  
- 	.size	protected_mode_jump, .-protected_mode_jump
+-config ARCH_SUPPORTS_OPROFILE
+-	bool
+-	default y
++config HAVE_SETUP_PER_CPU_AREA
++	def_bool X86_64
 +
-+	.code32
-+	.type	in_pm32, @function
-+in_pm32:
-+	# Set up data segments for flat 32-bit mode
-+	movl	%ecx, %ds
-+	movl	%ecx, %es
-+	movl	%ecx, %fs
-+	movl	%ecx, %gs
-+	movl	%ecx, %ss
-+	# The 32-bit code sets up its own stack, but this way we do have
-+	# a valid stack if some debugging hack wants to use it.
-+	addl	%ebx, %esp
++select HAVE_KVM
+ 
++config ARCH_HIBERNATION_POSSIBLE
++	def_bool y
++	depends on !SMP || !X86_VOYAGER
 +
-+	# Set up TR to make Intel VT happy
-+	ltr	%di
++config ARCH_SUSPEND_POSSIBLE
++	def_bool y
++	depends on !X86_VOYAGER
+ 
+ config ZONE_DMA32
+ 	bool
+@@ -144,9 +145,17 @@ config GENERIC_PENDING_IRQ
+ 
+ config X86_SMP
+ 	bool
+-	depends on X86_32 && SMP && !X86_VOYAGER
++	depends on SMP && ((X86_32 && !X86_VOYAGER) || X86_64)
+ 	default y
+ 
++config X86_32_SMP
++	def_bool y
++	depends on X86_32 && SMP
 +
-+	# Clear registers to allow for future extensions to the
-+	# 32-bit boot protocol
-+	xorl	%ecx, %ecx
-+	xorl	%edx, %edx
-+	xorl	%ebx, %ebx
-+	xorl	%ebp, %ebp
-+	xorl	%edi, %edi
++config X86_64_SMP
++	def_bool y
++	depends on X86_64 && SMP
 +
-+	# Set up LDTR to make Intel VT happy
-+	lldt	%cx
+ config X86_HT
+ 	bool
+ 	depends on SMP
+@@ -193,8 +202,7 @@ config SMP
+ 	  Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
+ 	  Management" code will be disabled if you say Y here.
+ 
+-	  See also the <file:Documentation/smp.txt>,
+-	  <file:Documentation/i386/IO-APIC.txt>,
++	  See also <file:Documentation/i386/IO-APIC.txt>,
+ 	  <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+ 	  <http://www.tldp.org/docs.html#howto>.
+ 
+@@ -292,6 +300,19 @@ config X86_ES7000
+ 	  Only choose this option if you have such a system, otherwise you
+ 	  should say N here.
+ 
++config X86_RDC321X
++	bool "RDC R-321x SoC"
++	depends on X86_32
++	select M486
++	select X86_REBOOTFIXUPS
++	select GENERIC_GPIO
++	select LEDS_CLASS
++	select LEDS_GPIO
++	help
++	  This option is needed for RDC R-321x system-on-chip, also known
++	  as R-8610-(G).
++	  If you don't have one of these chips, you should say N here.
 +
-+	jmpl	*%eax			# Jump to the 32-bit entrypoint
+ config X86_VSMP
+ 	bool "Support for ScaleMP vSMP"
+ 	depends on X86_64 && PCI
+@@ -303,8 +324,8 @@ config X86_VSMP
+ endchoice
+ 
+ config SCHED_NO_NO_OMIT_FRAME_POINTER
+-	bool "Single-depth WCHAN output"
+-	default y
++	def_bool y
++	prompt "Single-depth WCHAN output"
+ 	depends on X86_32
+ 	help
+ 	  Calculate simpler /proc/<PID>/wchan values. If this option
+@@ -314,18 +335,8 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
+ 
+ 	  If in doubt, say "Y".
+ 
+-config PARAVIRT
+-	bool
+-	depends on X86_32 && !(X86_VISWS || X86_VOYAGER)
+-	help
+-	  This changes the kernel so it can modify itself when it is run
+-	  under a hypervisor, potentially improving performance significantly
+-	  over full virtualization.  However, when run without a hypervisor
+-	  the kernel is theoretically slower and slightly larger.
+-
+ menuconfig PARAVIRT_GUEST
+ 	bool "Paravirtualized guest support"
+-	depends on X86_32
+ 	help
+ 	  Say Y here to get to see options related to running Linux under
+ 	  various hypervisors.  This option alone does not add any kernel code.
+@@ -339,6 +350,7 @@ source "arch/x86/xen/Kconfig"
+ config VMI
+ 	bool "VMI Guest support"
+ 	select PARAVIRT
++	depends on X86_32
+ 	depends on !(X86_VISWS || X86_VOYAGER)
+ 	help
+ 	  VMI provides a paravirtualized interface to the VMware ESX server
+@@ -348,40 +360,43 @@ config VMI
+ 
+ source "arch/x86/lguest/Kconfig"
+ 
++config PARAVIRT
++	bool "Enable paravirtualization code"
++	depends on !(X86_VISWS || X86_VOYAGER)
++	help
++	  This changes the kernel so it can modify itself when it is run
++	  under a hypervisor, potentially improving performance significantly
++	  over full virtualization.  However, when run without a hypervisor
++	  the kernel is theoretically slower and slightly larger.
 +
-+	.size	in_pm32, .-in_pm32
-diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
-index ed0672a..ff664a1 100644
---- a/arch/x86/boot/video-bios.c
-+++ b/arch/x86/boot/video-bios.c
-@@ -104,6 +104,7 @@ static int bios_probe(void)
+ endif
  
- 		mi = GET_HEAP(struct mode_info, 1);
- 		mi->mode = VIDEO_FIRST_BIOS+mode;
-+		mi->depth = 0;	/* text */
- 		mi->x = rdfs16(0x44a);
- 		mi->y = rdfs8(0x484)+1;
- 		nmodes++;
-@@ -116,7 +117,7 @@ static int bios_probe(void)
+ config ACPI_SRAT
+-	bool
+-	default y
++	def_bool y
+ 	depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH)
+ 	select ACPI_NUMA
  
- __videocard video_bios =
- {
--	.card_name	= "BIOS (scanned)",
-+	.card_name	= "BIOS",
- 	.probe		= bios_probe,
- 	.set_mode	= bios_set_mode,
- 	.unsafe		= 1,
-diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
-index 4716b9a..662dd2f 100644
---- a/arch/x86/boot/video-vesa.c
-+++ b/arch/x86/boot/video-vesa.c
-@@ -79,20 +79,28 @@ static int vesa_probe(void)
- 			/* Text Mode, TTY BIOS supported,
- 			   supported by hardware */
- 			mi = GET_HEAP(struct mode_info, 1);
--			mi->mode = mode + VIDEO_FIRST_VESA;
--			mi->x    = vminfo.h_res;
--			mi->y    = vminfo.v_res;
-+			mi->mode  = mode + VIDEO_FIRST_VESA;
-+			mi->depth = 0; /* text */
-+			mi->x     = vminfo.h_res;
-+			mi->y     = vminfo.v_res;
- 			nmodes++;
--		} else if ((vminfo.mode_attr & 0x99) == 0x99) {
-+		} else if ((vminfo.mode_attr & 0x99) == 0x99 &&
-+			   (vminfo.memory_layout == 4 ||
-+			    vminfo.memory_layout == 6) &&
-+			   vminfo.memory_planes == 1) {
- #ifdef CONFIG_FB
- 			/* Graphics mode, color, linear frame buffer
--			   supported -- register the mode but hide from
--			   the menu.  Only do this if framebuffer is
--			   configured, however, otherwise the user will
--			   be left without a screen. */
-+			   supported.  Only register the mode if
-+			   if framebuffer is configured, however,
-+			   otherwise the user will be left without a screen.
-+			   We don't require CONFIG_FB_VESA, however, since
-+			   some of the other framebuffer drivers can use
-+			   this mode-setting, too. */
- 			mi = GET_HEAP(struct mode_info, 1);
- 			mi->mode = mode + VIDEO_FIRST_VESA;
--			mi->x = mi->y = 0;
-+			mi->depth = vminfo.bpp;
-+			mi->x = vminfo.h_res;
-+			mi->y = vminfo.v_res;
- 			nmodes++;
- #endif
- 		}
-diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
-index aef02f9..7259387 100644
---- a/arch/x86/boot/video-vga.c
-+++ b/arch/x86/boot/video-vga.c
-@@ -18,22 +18,22 @@
- #include "video.h"
+ config HAVE_ARCH_PARSE_SRAT
+-       bool
+-       default y
+-       depends on ACPI_SRAT
++	def_bool y
++	depends on ACPI_SRAT
  
- static struct mode_info vga_modes[] = {
--	{ VIDEO_80x25,  80, 25 },
--	{ VIDEO_8POINT, 80, 50 },
--	{ VIDEO_80x43,  80, 43 },
--	{ VIDEO_80x28,  80, 28 },
--	{ VIDEO_80x30,  80, 30 },
--	{ VIDEO_80x34,  80, 34 },
--	{ VIDEO_80x60,  80, 60 },
-+	{ VIDEO_80x25,  80, 25, 0 },
-+	{ VIDEO_8POINT, 80, 50, 0 },
-+	{ VIDEO_80x43,  80, 43, 0 },
-+	{ VIDEO_80x28,  80, 28, 0 },
-+	{ VIDEO_80x30,  80, 30, 0 },
-+	{ VIDEO_80x34,  80, 34, 0 },
-+	{ VIDEO_80x60,  80, 60, 0 },
- };
+ config X86_SUMMIT_NUMA
+-	bool
+-	default y
++	def_bool y
+ 	depends on X86_32 && NUMA && (X86_SUMMIT || X86_GENERICARCH)
  
- static struct mode_info ega_modes[] = {
--	{ VIDEO_80x25,  80, 25 },
--	{ VIDEO_8POINT, 80, 43 },
-+	{ VIDEO_80x25,  80, 25, 0 },
-+	{ VIDEO_8POINT, 80, 43, 0 },
- };
+ config X86_CYCLONE_TIMER
+-	bool
+-	default y
++	def_bool y
+ 	depends on X86_32 && X86_SUMMIT || X86_GENERICARCH
  
- static struct mode_info cga_modes[] = {
--	{ VIDEO_80x25,  80, 25 },
-+	{ VIDEO_80x25,  80, 25, 0 },
- };
+ config ES7000_CLUSTERED_APIC
+-	bool
+-	default y
++	def_bool y
+ 	depends on SMP && X86_ES7000 && MPENTIUMIII
  
- __videocard video_vga;
-diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
-index ad9712f..696d08f 100644
---- a/arch/x86/boot/video.c
-+++ b/arch/x86/boot/video.c
-@@ -293,13 +293,28 @@ static void display_menu(void)
- 	struct mode_info *mi;
- 	char ch;
- 	int i;
-+	int nmodes;
-+	int modes_per_line;
-+	int col;
+ source "arch/x86/Kconfig.cpu"
  
--	puts("Mode:    COLSxROWS:\n");
-+	nmodes = 0;
-+	for (card = video_cards; card < video_cards_end; card++)
-+		nmodes += card->nmodes;
+ config HPET_TIMER
+-	bool
++	def_bool X86_64
+ 	prompt "HPET Timer Support" if X86_32
+-	default X86_64
+ 	help
+          Use the IA-PC HPET (High Precision Event Timer) to manage
+          time in preference to the PIT and RTC, if a HPET is
+@@ -399,9 +414,8 @@ config HPET_TIMER
+          Choose N to continue using the legacy 8254 timer.
  
-+	modes_per_line = 1;
-+	if (nmodes >= 20)
-+		modes_per_line = 3;
-+
-+	for (col = 0; col < modes_per_line; col++)
-+		puts("Mode: Resolution:  Type: ");
-+	putchar('\n');
-+
-+	col = 0;
- 	ch = '0';
- 	for (card = video_cards; card < video_cards_end; card++) {
- 		mi = card->modes;
- 		for (i = 0; i < card->nmodes; i++, mi++) {
-+			char resbuf[32];
- 			int visible = mi->x && mi->y;
- 			u16 mode_id = mi->mode ? mi->mode :
- 				(mi->y << 8)+mi->x;
-@@ -307,8 +322,18 @@ static void display_menu(void)
- 			if (!visible)
- 				continue; /* Hidden mode */
+ config HPET_EMULATE_RTC
+-	bool
+-	depends on HPET_TIMER && RTC=y
+-	default y
++	def_bool y
++	depends on HPET_TIMER && (RTC=y || RTC=m)
  
--			printf("%c  %04X  %3dx%-3d  %s\n",
--			       ch, mode_id, mi->x, mi->y, card->card_name);
-+			if (mi->depth)
-+				sprintf(resbuf, "%dx%d", mi->y, mi->depth);
-+			else
-+				sprintf(resbuf, "%d", mi->y);
-+
-+			printf("%c %03X %4dx%-7s %-6s",
-+			       ch, mode_id, mi->x, resbuf, card->card_name);
-+			col++;
-+			if (col >= modes_per_line) {
-+				putchar('\n');
-+				col = 0;
-+			}
+ # Mark as embedded because too many people got it wrong.
+ # The code disables itself when not needed.
+@@ -441,8 +455,8 @@ config CALGARY_IOMMU
+ 	  If unsure, say Y.
  
- 			if (ch == '9')
- 				ch = 'a';
-@@ -318,6 +343,8 @@ static void display_menu(void)
- 				ch++;
- 		}
- 	}
-+	if (col)
-+		putchar('\n');
- }
+ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
+-	bool "Should Calgary be enabled by default?"
+-	default y
++	def_bool y
++	prompt "Should Calgary be enabled by default?"
+ 	depends on CALGARY_IOMMU
+ 	help
+ 	  Should Calgary be enabled by default? if you choose 'y', Calgary
+@@ -451,6 +465,9 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT
+ 	  Calgary anyway, pass 'iommu=calgary' on the kernel command line.
+ 	  If unsure, say Y.
  
- #define H(x)	((x)-'a'+10)
-diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h
-index b92447d..d69347f 100644
---- a/arch/x86/boot/video.h
-+++ b/arch/x86/boot/video.h
-@@ -83,7 +83,8 @@ void store_screen(void);
++config IOMMU_HELPER
++	def_bool (CALGARY_IOMMU || GART_IOMMU)
++
+ # need this always selected by IOMMU for the VIA workaround
+ config SWIOTLB
+ 	bool
+@@ -486,9 +503,9 @@ config SCHED_SMT
+ 	  N here.
  
- struct mode_info {
- 	u16 mode;		/* Mode number (vga= style) */
--	u8  x, y;		/* Width, height */
-+	u16 x, y;		/* Width, height */
-+	u16 depth;		/* Bits per pixel, 0 for text mode */
- };
+ config SCHED_MC
+-	bool "Multi-core scheduler support"
++	def_bool y
++	prompt "Multi-core scheduler support"
+ 	depends on (X86_64 && SMP) || (X86_32 && X86_HT)
+-	default y
+ 	help
+ 	  Multi-core scheduler support improves the CPU scheduler's decision
+ 	  making when dealing with multi-core CPU chips at a cost of slightly
+@@ -522,19 +539,16 @@ config X86_UP_IOAPIC
+ 	  an IO-APIC, then the kernel will still run with no slowdown at all.
  
- struct card_info {
-diff --git a/arch/x86/boot/voyager.c b/arch/x86/boot/voyager.c
-index 61c8fe0..6499e32 100644
---- a/arch/x86/boot/voyager.c
-+++ b/arch/x86/boot/voyager.c
-@@ -16,8 +16,6 @@
+ config X86_LOCAL_APIC
+-	bool
++	def_bool y
+ 	depends on X86_64 || (X86_32 && (X86_UP_APIC || ((X86_VISWS || SMP) && !X86_VOYAGER) || X86_GENERICARCH))
+-	default y
  
- #include "boot.h"
+ config X86_IO_APIC
+-	bool
++	def_bool y
+ 	depends on X86_64 || (X86_32 && (X86_UP_IOAPIC || (SMP && !(X86_VISWS || X86_VOYAGER)) || X86_GENERICARCH))
+-	default y
  
--#ifdef CONFIG_X86_VOYAGER
--
- int query_voyager(void)
- {
- 	u8 err;
-@@ -42,5 +40,3 @@ int query_voyager(void)
- 	copy_from_fs(data_ptr, di, 7);	/* Table is 7 bytes apparently */
- 	return 0;
- }
--
--#endif /* CONFIG_X86_VOYAGER */
-diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
-index 54ee176..77562e7 100644
---- a/arch/x86/configs/i386_defconfig
-+++ b/arch/x86/configs/i386_defconfig
-@@ -99,9 +99,9 @@ CONFIG_IOSCHED_NOOP=y
- CONFIG_IOSCHED_AS=y
- CONFIG_IOSCHED_DEADLINE=y
- CONFIG_IOSCHED_CFQ=y
--CONFIG_DEFAULT_AS=y
-+# CONFIG_DEFAULT_AS is not set
- # CONFIG_DEFAULT_DEADLINE is not set
--# CONFIG_DEFAULT_CFQ is not set
-+CONFIG_DEFAULT_CFQ=y
- # CONFIG_DEFAULT_NOOP is not set
- CONFIG_DEFAULT_IOSCHED="anticipatory"
+ config X86_VISWS_APIC
+-	bool
++	def_bool y
+ 	depends on X86_32 && X86_VISWS
+-	default y
  
-diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
-index 38a83f9..9e2b0ef 100644
---- a/arch/x86/configs/x86_64_defconfig
-+++ b/arch/x86/configs/x86_64_defconfig
-@@ -145,15 +145,6 @@ CONFIG_K8_NUMA=y
- CONFIG_NODES_SHIFT=6
- CONFIG_X86_64_ACPI_NUMA=y
- CONFIG_NUMA_EMU=y
--CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
--CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
--CONFIG_ARCH_SPARSEMEM_ENABLE=y
--CONFIG_SELECT_MEMORY_MODEL=y
--# CONFIG_FLATMEM_MANUAL is not set
--CONFIG_DISCONTIGMEM_MANUAL=y
--# CONFIG_SPARSEMEM_MANUAL is not set
--CONFIG_DISCONTIGMEM=y
--CONFIG_FLAT_NODE_MEM_MAP=y
- CONFIG_NEED_MULTIPLE_NODES=y
- # CONFIG_SPARSEMEM_STATIC is not set
- CONFIG_SPLIT_PTLOCK_CPUS=4
-diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
-index 46bb609..3874c2d 100644
---- a/arch/x86/crypto/Makefile
-+++ b/arch/x86/crypto/Makefile
-@@ -4,12 +4,16 @@
+ config X86_MCE
+ 	bool "Machine Check Exception"
+@@ -554,17 +568,17 @@ config X86_MCE
+ 	  the 386 and 486, so nearly everyone can say Y here.
  
- obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
- obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
-+obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
+ config X86_MCE_INTEL
+-	bool "Intel MCE features"
++	def_bool y
++	prompt "Intel MCE features"
+ 	depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+-	default y
+ 	help
+ 	   Additional support for intel specific MCE features such as
+ 	   the thermal monitor.
  
- obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
- obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
-+obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
+ config X86_MCE_AMD
+-	bool "AMD MCE features"
++	def_bool y
++	prompt "AMD MCE features"
+ 	depends on X86_64 && X86_MCE && X86_LOCAL_APIC
+-	default y
+ 	help
+ 	   Additional support for AMD specific MCE features such as
+ 	   the DRAM Error Threshold.
+@@ -637,9 +651,9 @@ config I8K
+ 	  Say N otherwise.
  
--aes-i586-y := aes-i586-asm_32.o aes_32.o
--twofish-i586-y := twofish-i586-asm_32.o twofish_32.o
-+aes-i586-y := aes-i586-asm_32.o aes_glue.o
-+twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
-+salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
+ config X86_REBOOTFIXUPS
+-	bool "Enable X86 board specific fixups for reboot"
++	def_bool n
++	prompt "Enable X86 board specific fixups for reboot"
+ 	depends on X86_32 && 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
+@@ -648,7 +662,7 @@ config X86_REBOOTFIXUPS
+ 	  system.
  
--aes-x86_64-y := aes-x86_64-asm_64.o aes_64.o
--twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_64.o
-+aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
-+twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
-+salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
-diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S
-index f942f0c..1093bed 100644
---- a/arch/x86/crypto/aes-i586-asm_32.S
-+++ b/arch/x86/crypto/aes-i586-asm_32.S
-@@ -46,9 +46,9 @@
- #define in_blk 16
+ 	  Currently, the only fixup is for the Geode machines using
+-	  CS5530A and CS5536 chipsets.
++	  CS5530A and CS5536 chipsets and the RDC R-321x SoC.
  
- /* offsets in crypto_tfm structure */
--#define ekey (crypto_tfm_ctx_offset + 0)
--#define nrnd (crypto_tfm_ctx_offset + 256)
--#define dkey (crypto_tfm_ctx_offset + 260)
-+#define klen (crypto_tfm_ctx_offset + 0)
-+#define ekey (crypto_tfm_ctx_offset + 4)
-+#define dkey (crypto_tfm_ctx_offset + 244)
+ 	  Say Y if you want to enable the fixup. Currently, it's safe to
+ 	  enable this option even if you don't need it.
+@@ -672,9 +686,8 @@ config MICROCODE
+ 	  module will be called microcode.
  
- // register mapping for encrypt and decrypt subroutines
+ config MICROCODE_OLD_INTERFACE
+-	bool
++	def_bool y
+ 	depends on MICROCODE
+-	default y
  
-@@ -221,8 +221,8 @@
+ config X86_MSR
+ 	tristate "/dev/cpu/*/msr - Model-specific register support"
+@@ -798,13 +811,12 @@ config PAGE_OFFSET
+ 	depends on X86_32
  
- .global  aes_enc_blk
+ config HIGHMEM
+-	bool
++	def_bool y
+ 	depends on X86_32 && (HIGHMEM64G || HIGHMEM4G)
+-	default y
  
--.extern  ft_tab
--.extern  fl_tab
-+.extern  crypto_ft_tab
-+.extern  crypto_fl_tab
+ config X86_PAE
+-	bool "PAE (Physical Address Extension) Support"
+-	default n
++	def_bool n
++	prompt "PAE (Physical Address Extension) Support"
+ 	depends on X86_32 && !HIGHMEM4G
+ 	select RESOURCES_64BIT
+ 	help
+@@ -836,10 +848,10 @@ comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
+ 	depends on X86_32 && X86_SUMMIT && (!HIGHMEM64G || !ACPI)
  
- .align 4
+ config K8_NUMA
+-       bool "Old style AMD Opteron NUMA detection"
+-       depends on X86_64 && NUMA && PCI
+-       default y
+-       help
++	def_bool y
++	prompt "Old style AMD Opteron NUMA detection"
++	depends on X86_64 && NUMA && PCI
++	help
+ 	 Enable K8 NUMA node topology detection.  You should say Y here if
+ 	 you have a multi processor AMD K8 system. This uses an old
+ 	 method to read the NUMA configuration directly from the builtin
+@@ -847,10 +859,10 @@ config K8_NUMA
+ 	 instead, which also takes priority if both are compiled in.
  
-@@ -236,7 +236,7 @@ aes_enc_blk:
- 1:	push    %ebx
- 	mov     in_blk+4(%esp),%r2
- 	push    %esi
--	mov     nrnd(%ebp),%r3   // number of rounds
-+	mov     klen(%ebp),%r3   // key size
- 	push    %edi
- #if ekey != 0
- 	lea     ekey(%ebp),%ebp  // key pointer
-@@ -255,26 +255,26 @@ aes_enc_blk:
+ config X86_64_ACPI_NUMA
+-	bool "ACPI NUMA detection"
++	def_bool y
++	prompt "ACPI NUMA detection"
+ 	depends on X86_64 && NUMA && ACPI && PCI
+ 	select ACPI_NUMA
+-	default y
+ 	help
+ 	  Enable ACPI SRAT based node topology detection.
  
- 	sub     $8,%esp		// space for register saves on stack
- 	add     $16,%ebp	// increment to next round key
--	cmp     $12,%r3
-+	cmp     $24,%r3
- 	jb      4f		// 10 rounds for 128-bit key
- 	lea     32(%ebp),%ebp
- 	je      3f		// 12 rounds for 192-bit key
- 	lea     32(%ebp),%ebp
+@@ -864,52 +876,53 @@ config NUMA_EMU
  
--2:	fwd_rnd1( -64(%ebp) ,ft_tab)	// 14 rounds for 256-bit key
--	fwd_rnd2( -48(%ebp) ,ft_tab)
--3:	fwd_rnd1( -32(%ebp) ,ft_tab)	// 12 rounds for 192-bit key
--	fwd_rnd2( -16(%ebp) ,ft_tab)
--4:	fwd_rnd1(    (%ebp) ,ft_tab)	// 10 rounds for 128-bit key
--	fwd_rnd2( +16(%ebp) ,ft_tab)
--	fwd_rnd1( +32(%ebp) ,ft_tab)
--	fwd_rnd2( +48(%ebp) ,ft_tab)
--	fwd_rnd1( +64(%ebp) ,ft_tab)
--	fwd_rnd2( +80(%ebp) ,ft_tab)
--	fwd_rnd1( +96(%ebp) ,ft_tab)
--	fwd_rnd2(+112(%ebp) ,ft_tab)
--	fwd_rnd1(+128(%ebp) ,ft_tab)
--	fwd_rnd2(+144(%ebp) ,fl_tab)	// last round uses a different table
-+2:	fwd_rnd1( -64(%ebp), crypto_ft_tab)	// 14 rounds for 256-bit key
-+	fwd_rnd2( -48(%ebp), crypto_ft_tab)
-+3:	fwd_rnd1( -32(%ebp), crypto_ft_tab)	// 12 rounds for 192-bit key
-+	fwd_rnd2( -16(%ebp), crypto_ft_tab)
-+4:	fwd_rnd1(    (%ebp), crypto_ft_tab)	// 10 rounds for 128-bit key
-+	fwd_rnd2( +16(%ebp), crypto_ft_tab)
-+	fwd_rnd1( +32(%ebp), crypto_ft_tab)
-+	fwd_rnd2( +48(%ebp), crypto_ft_tab)
-+	fwd_rnd1( +64(%ebp), crypto_ft_tab)
-+	fwd_rnd2( +80(%ebp), crypto_ft_tab)
-+	fwd_rnd1( +96(%ebp), crypto_ft_tab)
-+	fwd_rnd2(+112(%ebp), crypto_ft_tab)
-+	fwd_rnd1(+128(%ebp), crypto_ft_tab)
-+	fwd_rnd2(+144(%ebp), crypto_fl_tab)	// last round uses a different table
+ config NODES_SHIFT
+ 	int
++	range 1 15  if X86_64
+ 	default "6" if X86_64
+ 	default "4" if X86_NUMAQ
+ 	default "3"
+ 	depends on NEED_MULTIPLE_NODES
  
- // move final values to the output array.  CAUTION: the 
- // order of these assigns rely on the register mappings
-@@ -297,8 +297,8 @@ aes_enc_blk:
+ config HAVE_ARCH_BOOTMEM_NODE
+-	bool
++	def_bool y
+ 	depends on X86_32 && NUMA
+-	default y
  
- .global  aes_dec_blk
+ config ARCH_HAVE_MEMORY_PRESENT
+-	bool
++	def_bool y
+ 	depends on X86_32 && DISCONTIGMEM
+-	default y
  
--.extern  it_tab
--.extern  il_tab
-+.extern  crypto_it_tab
-+.extern  crypto_il_tab
+ config NEED_NODE_MEMMAP_SIZE
+-	bool
++	def_bool y
+ 	depends on X86_32 && (DISCONTIGMEM || SPARSEMEM)
+-	default y
  
- .align 4
+ config HAVE_ARCH_ALLOC_REMAP
+-	bool
++	def_bool y
+ 	depends on X86_32 && NUMA
+-	default y
  
-@@ -312,14 +312,11 @@ aes_dec_blk:
- 1:	push    %ebx
- 	mov     in_blk+4(%esp),%r2
- 	push    %esi
--	mov     nrnd(%ebp),%r3   // number of rounds
-+	mov     klen(%ebp),%r3   // key size
- 	push    %edi
- #if dkey != 0
- 	lea     dkey(%ebp),%ebp  // key pointer
- #endif
--	mov     %r3,%r0
--	shl     $4,%r0
--	add     %r0,%ebp
- 	
- // input four columns and xor in first round key
+ config ARCH_FLATMEM_ENABLE
+ 	def_bool y
+-	depends on (X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC) || (X86_64 && !NUMA)
++	depends on X86_32 && ARCH_SELECT_MEMORY_MODEL && X86_PC && !NUMA
  
-@@ -333,27 +330,27 @@ aes_dec_blk:
- 	xor     12(%ebp),%r5
+ config ARCH_DISCONTIGMEM_ENABLE
+ 	def_bool y
+-	depends on NUMA
++	depends on NUMA && X86_32
  
- 	sub     $8,%esp		// space for register saves on stack
--	sub     $16,%ebp	// increment to next round key
--	cmp     $12,%r3
-+	add     $16,%ebp	// increment to next round key
-+	cmp     $24,%r3
- 	jb      4f		// 10 rounds for 128-bit key
--	lea     -32(%ebp),%ebp
-+	lea     32(%ebp),%ebp
- 	je      3f		// 12 rounds for 192-bit key
--	lea     -32(%ebp),%ebp
--
--2:	inv_rnd1( +64(%ebp), it_tab)	// 14 rounds for 256-bit key
--	inv_rnd2( +48(%ebp), it_tab)
--3:	inv_rnd1( +32(%ebp), it_tab)	// 12 rounds for 192-bit key
--	inv_rnd2( +16(%ebp), it_tab)
--4:	inv_rnd1(    (%ebp), it_tab)	// 10 rounds for 128-bit key
--	inv_rnd2( -16(%ebp), it_tab)
--	inv_rnd1( -32(%ebp), it_tab)
--	inv_rnd2( -48(%ebp), it_tab)
--	inv_rnd1( -64(%ebp), it_tab)
--	inv_rnd2( -80(%ebp), it_tab)
--	inv_rnd1( -96(%ebp), it_tab)
--	inv_rnd2(-112(%ebp), it_tab)
--	inv_rnd1(-128(%ebp), it_tab)
--	inv_rnd2(-144(%ebp), il_tab)	// last round uses a different table
-+	lea     32(%ebp),%ebp
+ config ARCH_DISCONTIGMEM_DEFAULT
+ 	def_bool y
+-	depends on NUMA
++	depends on NUMA && X86_32
 +
-+2:	inv_rnd1( -64(%ebp), crypto_it_tab)	// 14 rounds for 256-bit key
-+	inv_rnd2( -48(%ebp), crypto_it_tab)
-+3:	inv_rnd1( -32(%ebp), crypto_it_tab)	// 12 rounds for 192-bit key
-+	inv_rnd2( -16(%ebp), crypto_it_tab)
-+4:	inv_rnd1(    (%ebp), crypto_it_tab)	// 10 rounds for 128-bit key
-+	inv_rnd2( +16(%ebp), crypto_it_tab)
-+	inv_rnd1( +32(%ebp), crypto_it_tab)
-+	inv_rnd2( +48(%ebp), crypto_it_tab)
-+	inv_rnd1( +64(%ebp), crypto_it_tab)
-+	inv_rnd2( +80(%ebp), crypto_it_tab)
-+	inv_rnd1( +96(%ebp), crypto_it_tab)
-+	inv_rnd2(+112(%ebp), crypto_it_tab)
-+	inv_rnd1(+128(%ebp), crypto_it_tab)
-+	inv_rnd2(+144(%ebp), crypto_il_tab)	// last round uses a different table
++config ARCH_SPARSEMEM_DEFAULT
++	def_bool y
++	depends on X86_64
  
- // move final values to the output array.  CAUTION: the 
- // order of these assigns rely on the register mappings
-diff --git a/arch/x86/crypto/aes-x86_64-asm_64.S b/arch/x86/crypto/aes-x86_64-asm_64.S
-index 26b40de..a120f52 100644
---- a/arch/x86/crypto/aes-x86_64-asm_64.S
-+++ b/arch/x86/crypto/aes-x86_64-asm_64.S
-@@ -8,10 +8,10 @@
-  * including this sentence is retained in full.
-  */
+ config ARCH_SPARSEMEM_ENABLE
+ 	def_bool y
+-	depends on NUMA || (EXPERIMENTAL && (X86_PC || X86_64))
++	depends on X86_64 || NUMA || (EXPERIMENTAL && X86_PC)
+ 	select SPARSEMEM_STATIC if X86_32
+ 	select SPARSEMEM_VMEMMAP_ENABLE if X86_64
  
--.extern aes_ft_tab
--.extern aes_it_tab
--.extern aes_fl_tab
--.extern aes_il_tab
-+.extern crypto_ft_tab
-+.extern crypto_it_tab
-+.extern crypto_fl_tab
-+.extern crypto_il_tab
+ config ARCH_SELECT_MEMORY_MODEL
+ 	def_bool y
+-	depends on X86_32 && ARCH_SPARSEMEM_ENABLE
++	depends on ARCH_SPARSEMEM_ENABLE
  
- .text
+ config ARCH_MEMORY_PROBE
+ 	def_bool X86_64
+@@ -987,42 +1000,32 @@ config MTRR
+ 	  See <file:Documentation/mtrr.txt> for more information.
  
-@@ -56,13 +56,13 @@
- 	.align	8;			\
- FUNC:	movq	r1,r2;			\
- 	movq	r3,r4;			\
--	leaq	BASE+KEY+52(r8),r9;	\
-+	leaq	BASE+KEY+48+4(r8),r9;	\
- 	movq	r10,r11;		\
- 	movl	(r7),r5 ## E;		\
- 	movl	4(r7),r1 ## E;		\
- 	movl	8(r7),r6 ## E;		\
- 	movl	12(r7),r7 ## E;		\
--	movl	BASE(r8),r10 ## E;	\
-+	movl	BASE+0(r8),r10 ## E;	\
- 	xorl	-48(r9),r5 ## E;	\
- 	xorl	-44(r9),r1 ## E;	\
- 	xorl	-40(r9),r6 ## E;	\
-@@ -154,37 +154,37 @@ FUNC:	movq	r1,r2;			\
- /* void aes_enc_blk(stuct crypto_tfm *tfm, u8 *out, const u8 *in) */
+ config EFI
+-	bool "Boot from EFI support"
+-	depends on X86_32 && ACPI
+-	default n
++	def_bool n
++	prompt "EFI runtime service support"
++	depends on ACPI
+ 	---help---
+-	This enables the kernel to boot on EFI platforms using
+-	system configuration information passed to it from the firmware.
+-	This also enables the kernel to use any EFI runtime services that are
++	This enables the kernel to use EFI runtime services that are
+ 	available (such as the EFI variable services).
  
- 	entry(aes_enc_blk,0,enc128,enc192)
--	encrypt_round(aes_ft_tab,-96)
--	encrypt_round(aes_ft_tab,-80)
--enc192:	encrypt_round(aes_ft_tab,-64)
--	encrypt_round(aes_ft_tab,-48)
--enc128:	encrypt_round(aes_ft_tab,-32)
--	encrypt_round(aes_ft_tab,-16)
--	encrypt_round(aes_ft_tab,  0)
--	encrypt_round(aes_ft_tab, 16)
--	encrypt_round(aes_ft_tab, 32)
--	encrypt_round(aes_ft_tab, 48)
--	encrypt_round(aes_ft_tab, 64)
--	encrypt_round(aes_ft_tab, 80)
--	encrypt_round(aes_ft_tab, 96)
--	encrypt_final(aes_fl_tab,112)
-+	encrypt_round(crypto_ft_tab,-96)
-+	encrypt_round(crypto_ft_tab,-80)
-+enc192:	encrypt_round(crypto_ft_tab,-64)
-+	encrypt_round(crypto_ft_tab,-48)
-+enc128:	encrypt_round(crypto_ft_tab,-32)
-+	encrypt_round(crypto_ft_tab,-16)
-+	encrypt_round(crypto_ft_tab,  0)
-+	encrypt_round(crypto_ft_tab, 16)
-+	encrypt_round(crypto_ft_tab, 32)
-+	encrypt_round(crypto_ft_tab, 48)
-+	encrypt_round(crypto_ft_tab, 64)
-+	encrypt_round(crypto_ft_tab, 80)
-+	encrypt_round(crypto_ft_tab, 96)
-+	encrypt_final(crypto_fl_tab,112)
- 	return
+-	This option is only useful on systems that have EFI firmware
+-	and will result in a kernel image that is ~8k larger.  In addition,
+-	you must use the latest ELILO loader available at
+-	<http://elilo.sourceforge.net> in order to take advantage of
+-	kernel initialization using EFI information (neither GRUB nor LILO know
+-	anything about EFI).  However, even with this option, the resultant
+-	kernel should continue to boot on existing non-EFI platforms.
++	This option is only useful on systems that have EFI firmware.
++  	In addition, you should use the latest ELILO loader available
++  	at <http://elilo.sourceforge.net> in order to take advantage
++  	of EFI runtime services. However, even with this option, the
++  	resultant kernel should continue to boot on existing non-EFI
++  	platforms.
  
- /* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in) */
+ config IRQBALANCE
+-	bool "Enable kernel irq balancing"
++	def_bool y
++	prompt "Enable kernel irq balancing"
+ 	depends on X86_32 && SMP && X86_IO_APIC
+-	default y
+ 	help
+ 	  The default yes will allow the kernel to do irq load balancing.
+ 	  Saying no will keep the kernel from doing irq load balancing.
  
- 	entry(aes_dec_blk,240,dec128,dec192)
--	decrypt_round(aes_it_tab,-96)
--	decrypt_round(aes_it_tab,-80)
--dec192:	decrypt_round(aes_it_tab,-64)
--	decrypt_round(aes_it_tab,-48)
--dec128:	decrypt_round(aes_it_tab,-32)
--	decrypt_round(aes_it_tab,-16)
--	decrypt_round(aes_it_tab,  0)
--	decrypt_round(aes_it_tab, 16)
--	decrypt_round(aes_it_tab, 32)
--	decrypt_round(aes_it_tab, 48)
--	decrypt_round(aes_it_tab, 64)
--	decrypt_round(aes_it_tab, 80)
--	decrypt_round(aes_it_tab, 96)
--	decrypt_final(aes_il_tab,112)
-+	decrypt_round(crypto_it_tab,-96)
-+	decrypt_round(crypto_it_tab,-80)
-+dec192:	decrypt_round(crypto_it_tab,-64)
-+	decrypt_round(crypto_it_tab,-48)
-+dec128:	decrypt_round(crypto_it_tab,-32)
-+	decrypt_round(crypto_it_tab,-16)
-+	decrypt_round(crypto_it_tab,  0)
-+	decrypt_round(crypto_it_tab, 16)
-+	decrypt_round(crypto_it_tab, 32)
-+	decrypt_round(crypto_it_tab, 48)
-+	decrypt_round(crypto_it_tab, 64)
-+	decrypt_round(crypto_it_tab, 80)
-+	decrypt_round(crypto_it_tab, 96)
-+	decrypt_final(crypto_il_tab,112)
- 	return
-diff --git a/arch/x86/crypto/aes_32.c b/arch/x86/crypto/aes_32.c
-deleted file mode 100644
-index 49aad93..0000000
---- a/arch/x86/crypto/aes_32.c
-+++ /dev/null
-@@ -1,515 +0,0 @@
--/* 
-- * 
-- * Glue Code for optimized 586 assembler version of AES
-- *
-- * Copyright (c) 2002, Dr Brian Gladman <>, Worcester, UK.
-- * All rights reserved.
-- *
-- * LICENSE TERMS
-- *
-- * The free distribution and use of this software in both source and binary
-- * form is allowed (with or without changes) provided that:
-- *
-- *   1. distributions of this source code include the above copyright
-- *      notice, this list of conditions and the following disclaimer;
-- *
-- *   2. distributions in binary form include the above copyright
-- *      notice, this list of conditions and the following disclaimer
-- *      in the documentation and/or other associated materials;
-- *
-- *   3. the copyright holder's name is not used to endorse products
-- *      built using this software without specific written permission.
-- *
-- * ALTERNATIVELY, provided that this notice is retained in full, this product
-- * may be distributed under the terms of the GNU General Public License (GPL),
-- * in which case the provisions of the GPL apply INSTEAD OF those given above.
-- *
-- * DISCLAIMER
-- *
-- * This software is provided 'as is' with no explicit or implied warranties
-- * in respect of its properties, including, but not limited to, correctness
-- * and/or fitness for purpose.
-- *
-- * Copyright (c) 2003, Adam J. Richter <adam at yggdrasil.com> (conversion to
-- * 2.5 API).
-- * Copyright (c) 2003, 2004 Fruhwirth Clemens <clemens at endorphin.org>
-- * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris at redhat.com>
-- *
-- */
--
--#include <asm/byteorder.h>
--#include <linux/kernel.h>
--#include <linux/module.h>
--#include <linux/init.h>
--#include <linux/types.h>
--#include <linux/crypto.h>
--#include <linux/linkage.h>
--
--asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
--asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
--
--#define AES_MIN_KEY_SIZE	16
--#define AES_MAX_KEY_SIZE	32
--#define AES_BLOCK_SIZE		16
--#define AES_KS_LENGTH		4 * AES_BLOCK_SIZE
--#define RC_LENGTH		29
--
--struct aes_ctx {
--	u32 ekey[AES_KS_LENGTH];
--	u32 rounds;
--	u32 dkey[AES_KS_LENGTH];
--};
--
--#define WPOLY 0x011b
--#define bytes2word(b0, b1, b2, b3)  \
--	(((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0))
--
--/* define the finite field multiplies required for Rijndael */
--#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
--#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
--#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
--#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
--#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
--#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
--#define fi(x) ((x) ?   pow[255 - log[x]]: 0)
--
--static inline u32 upr(u32 x, int n)
--{
--	return (x << 8 * n) | (x >> (32 - 8 * n));
--}
--
--static inline u8 bval(u32 x, int n)
--{
--	return x >> 8 * n;
--}
--
--/* The forward and inverse affine transformations used in the S-box */
--#define fwd_affine(x) \
--	(w = (u32)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(u8)(w^(w>>8)))
--
--#define inv_affine(x) \
--	(w = (u32)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(u8)(w^(w>>8)))
--
--static u32 rcon_tab[RC_LENGTH];
--
--u32 ft_tab[4][256];
--u32 fl_tab[4][256];
--static u32 im_tab[4][256];
--u32 il_tab[4][256];
--u32 it_tab[4][256];
--
--static void gen_tabs(void)
--{
--	u32 i, w;
--	u8 pow[512], log[256];
--
--	/*
--	 * log and power tables for GF(2^8) finite field with
--	 * WPOLY as modular polynomial - the simplest primitive
--	 * root is 0x03, used here to generate the tables.
--	 */
--	i = 0; w = 1; 
--	
--	do {
--		pow[i] = (u8)w;
--		pow[i + 255] = (u8)w;
--		log[w] = (u8)i++;
--		w ^=  (w << 1) ^ (w & 0x80 ? WPOLY : 0);
--	} while (w != 1);
--	
--	for(i = 0, w = 1; i < RC_LENGTH; ++i) {
--		rcon_tab[i] = bytes2word(w, 0, 0, 0);
--		w = f2(w);
--	}
--
--	for(i = 0; i < 256; ++i) {
--		u8 b;
--		
--		b = fwd_affine(fi((u8)i));
--		w = bytes2word(f2(b), b, b, f3(b));
--
--		/* tables for a normal encryption round */
--		ft_tab[0][i] = w;
--		ft_tab[1][i] = upr(w, 1);
--		ft_tab[2][i] = upr(w, 2);
--		ft_tab[3][i] = upr(w, 3);
--		w = bytes2word(b, 0, 0, 0);
--		
--		/*
--		 * tables for last encryption round
--		 * (may also be used in the key schedule)
--		 */
--		fl_tab[0][i] = w;
--		fl_tab[1][i] = upr(w, 1);
--		fl_tab[2][i] = upr(w, 2);
--		fl_tab[3][i] = upr(w, 3);
--		
--		b = fi(inv_affine((u8)i));
--		w = bytes2word(fe(b), f9(b), fd(b), fb(b));
--
--		/* tables for the inverse mix column operation  */
--		im_tab[0][b] = w;
--		im_tab[1][b] = upr(w, 1);
--		im_tab[2][b] = upr(w, 2);
--		im_tab[3][b] = upr(w, 3);
--
--		/* tables for a normal decryption round */
--		it_tab[0][i] = w;
--		it_tab[1][i] = upr(w,1);
--		it_tab[2][i] = upr(w,2);
--		it_tab[3][i] = upr(w,3);
--
--		w = bytes2word(b, 0, 0, 0);
--		
--		/* tables for last decryption round */
--		il_tab[0][i] = w;
--		il_tab[1][i] = upr(w,1);
--		il_tab[2][i] = upr(w,2);
--		il_tab[3][i] = upr(w,3);
--    }
--}
--
--#define four_tables(x,tab,vf,rf,c)		\
--(	tab[0][bval(vf(x,0,c),rf(0,c))]	^	\
--	tab[1][bval(vf(x,1,c),rf(1,c))] ^	\
--	tab[2][bval(vf(x,2,c),rf(2,c))] ^	\
--	tab[3][bval(vf(x,3,c),rf(3,c))]		\
--)
--
--#define vf1(x,r,c)  (x)
--#define rf1(r,c)    (r)
--#define rf2(r,c)    ((r-c)&3)
--
--#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0)
--#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c)
--
--#define ff(x) inv_mcol(x)
--
--#define ke4(k,i)							\
--{									\
--	k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i];		\
--	k[4*(i)+5] = ss[1] ^= ss[0];					\
--	k[4*(i)+6] = ss[2] ^= ss[1];					\
--	k[4*(i)+7] = ss[3] ^= ss[2];					\
--}
--
--#define kel4(k,i)							\
--{									\
--	k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i];		\
--	k[4*(i)+5] = ss[1] ^= ss[0];					\
--	k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2];	\
--}
--
--#define ke6(k,i)							\
--{									\
--	k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];		\
--	k[6*(i)+ 7] = ss[1] ^= ss[0];					\
--	k[6*(i)+ 8] = ss[2] ^= ss[1];					\
--	k[6*(i)+ 9] = ss[3] ^= ss[2];					\
--	k[6*(i)+10] = ss[4] ^= ss[3];					\
--	k[6*(i)+11] = ss[5] ^= ss[4];					\
--}
--
--#define kel6(k,i)							\
--{									\
--	k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];		\
--	k[6*(i)+ 7] = ss[1] ^= ss[0];					\
--	k[6*(i)+ 8] = ss[2] ^= ss[1];					\
--	k[6*(i)+ 9] = ss[3] ^= ss[2];					\
--}
--
--#define ke8(k,i)							\
--{									\
--	k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];		\
--	k[8*(i)+ 9] = ss[1] ^= ss[0];					\
--	k[8*(i)+10] = ss[2] ^= ss[1];					\
--	k[8*(i)+11] = ss[3] ^= ss[2];					\
--	k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0);				\
--	k[8*(i)+13] = ss[5] ^= ss[4];					\
--	k[8*(i)+14] = ss[6] ^= ss[5];					\
--	k[8*(i)+15] = ss[7] ^= ss[6];					\
--}
+-# turning this on wastes a bunch of space.
+-# Summit needs it only when NUMA is on
+-config BOOT_IOREMAP
+-	bool
+-	depends on X86_32 && (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI))
+-	default y
 -
--#define kel8(k,i)							\
--{									\
--	k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];		\
--	k[8*(i)+ 9] = ss[1] ^= ss[0];					\
--	k[8*(i)+10] = ss[2] ^= ss[1];					\
--	k[8*(i)+11] = ss[3] ^= ss[2];					\
--}
+ config SECCOMP
+-	bool "Enable seccomp to safely compute untrusted bytecode"
++	def_bool y
++	prompt "Enable seccomp to safely compute untrusted bytecode"
+ 	depends on PROC_FS
+-	default y
+ 	help
+ 	  This kernel feature is useful for number crunching applications
+ 	  that may need to compute untrusted bytecode during their
+@@ -1189,11 +1192,11 @@ config HOTPLUG_CPU
+ 	  suspend.
+ 
+ config COMPAT_VDSO
+-	bool "Compat VDSO support"
+-	default y
+-	depends on X86_32
++	def_bool y
++	prompt "Compat VDSO support"
++	depends on X86_32 || IA32_EMULATION
+ 	help
+-	  Map the VDSO to the predictable old-style address too.
++	  Map the 32-bit VDSO to the predictable old-style address too.
+ 	---help---
+ 	  Say N here if you are running a sufficiently recent glibc
+ 	  version (2.3.3 or later), to remove the high-mapped
+@@ -1207,30 +1210,26 @@ config ARCH_ENABLE_MEMORY_HOTPLUG
+ 	def_bool y
+ 	depends on X86_64 || (X86_32 && HIGHMEM)
+ 
+-config MEMORY_HOTPLUG_RESERVE
+-	def_bool X86_64
+-	depends on (MEMORY_HOTPLUG && DISCONTIGMEM)
 -
--#define kdf4(k,i)							\
--{									\
--	ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3];				\
--	ss[1] = ss[1] ^ ss[3];						\
--	ss[2] = ss[2] ^ ss[3];						\
--	ss[3] = ss[3];							\
--	ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i];			\
--	ss[i % 4] ^= ss[4];						\
--	ss[4] ^= k[4*(i)];						\
--	k[4*(i)+4] = ff(ss[4]);						\
--	ss[4] ^= k[4*(i)+1];						\
--	k[4*(i)+5] = ff(ss[4]);						\
--	ss[4] ^= k[4*(i)+2];						\
--	k[4*(i)+6] = ff(ss[4]);						\
--	ss[4] ^= k[4*(i)+3];						\
--	k[4*(i)+7] = ff(ss[4]);						\
--}
+ config HAVE_ARCH_EARLY_PFN_TO_NID
+ 	def_bool X86_64
+ 	depends on NUMA
+ 
+-config OUT_OF_LINE_PFN_TO_PAGE
+-	def_bool X86_64
+-	depends on DISCONTIGMEM
 -
--#define kd4(k,i)							\
--{									\
--	ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i];			\
--	ss[i % 4] ^= ss[4];						\
--	ss[4] = ff(ss[4]);						\
--	k[4*(i)+4] = ss[4] ^= k[4*(i)];					\
--	k[4*(i)+5] = ss[4] ^= k[4*(i)+1];				\
--	k[4*(i)+6] = ss[4] ^= k[4*(i)+2];				\
--	k[4*(i)+7] = ss[4] ^= k[4*(i)+3];				\
--}
+ menu "Power management options"
+ 	depends on !X86_VOYAGER
+ 
+ config ARCH_HIBERNATION_HEADER
+-	bool
++	def_bool y
+ 	depends on X86_64 && HIBERNATION
+-	default y
+ 
+ source "kernel/power/Kconfig"
+ 
+ source "drivers/acpi/Kconfig"
+ 
++config X86_APM_BOOT
++	bool
++	default y
++	depends on APM || APM_MODULE
++
+ menuconfig APM
+ 	tristate "APM (Advanced Power Management) BIOS support"
+ 	depends on X86_32 && PM_SLEEP && !X86_VISWS
+@@ -1371,7 +1370,7 @@ menu "Bus options (PCI etc.)"
+ config PCI
+ 	bool "PCI support" if !X86_VISWS
+ 	depends on !X86_VOYAGER
+-	default y if X86_VISWS
++	default y
+ 	select ARCH_SUPPORTS_MSI if (X86_LOCAL_APIC && X86_IO_APIC)
+ 	help
+ 	  Find out whether you have a PCI motherboard. PCI is the name of a
+@@ -1379,11 +1378,6 @@ config PCI
+ 	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+ 	  VESA. If you have PCI, say Y, otherwise N.
+ 
+-	  The PCI-HOWTO, available from
+-	  <http://www.tldp.org/docs.html#howto>, contains valuable
+-	  information about which PCI hardware does work under Linux and which
+-	  doesn't.
 -
--#define kdl4(k,i)							\
--{									\
--	ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i];			\
--	ss[i % 4] ^= ss[4];						\
--	k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3];			\
--	k[4*(i)+5] = ss[1] ^ ss[3];					\
--	k[4*(i)+6] = ss[0];						\
--	k[4*(i)+7] = ss[1];						\
--}
+ choice
+ 	prompt "PCI access mode"
+ 	depends on X86_32 && PCI && !X86_VISWS
+@@ -1418,25 +1412,21 @@ config PCI_GOANY
+ endchoice
+ 
+ config PCI_BIOS
+-	bool
++	def_bool y
+ 	depends on X86_32 && !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
+-	default y
+ 
+ # x86-64 doesn't support PCI BIOS access from long mode so always go direct.
+ config PCI_DIRECT
+-	bool
++	def_bool y
+ 	depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS)
+-	default y
+ 
+ config PCI_MMCONFIG
+-	bool
++	def_bool y
+ 	depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
+-	default y
+ 
+ config PCI_DOMAINS
+-	bool
++	def_bool y
+ 	depends on PCI
+-	default y
+ 
+ config PCI_MMCONFIG
+ 	bool "Support mmconfig PCI config space access"
+@@ -1453,9 +1443,9 @@ config DMAR
+ 	  remapping devices.
+ 
+ config DMAR_GFX_WA
+-	bool "Support for Graphics workaround"
++	def_bool y
++	prompt "Support for Graphics workaround"
+ 	depends on DMAR
+-	default y
+ 	help
+ 	 Current Graphics drivers tend to use physical address
+ 	 for DMA and avoid using DMA APIs. Setting this config
+@@ -1464,9 +1454,8 @@ config DMAR_GFX_WA
+ 	 to use physical addresses for DMA.
+ 
+ config DMAR_FLOPPY_WA
+-	bool
++	def_bool y
+ 	depends on DMAR
+-	default y
+ 	help
+ 	 Floppy disk drivers are know to bypass DMA API calls
+ 	 thereby failing to work when IOMMU is enabled. This
+@@ -1479,8 +1468,7 @@ source "drivers/pci/Kconfig"
+ 
+ # x86_64 have no ISA slots, but do have ISA-style DMA.
+ config ISA_DMA_API
+-	bool
+-	default y
++	def_bool y
+ 
+ if X86_32
+ 
+@@ -1546,9 +1534,9 @@ config SCx200HR_TIMER
+ 	  other workaround is idle=poll boot option.
+ 
+ config GEODE_MFGPT_TIMER
+-	bool "Geode Multi-Function General Purpose Timer (MFGPT) events"
++	def_bool y
++	prompt "Geode Multi-Function General Purpose Timer (MFGPT) events"
+ 	depends on MGEODE_LX && GENERIC_TIME && GENERIC_CLOCKEVENTS
+-	default y
+ 	help
+ 	  This driver provides a clock event source based on the MFGPT
+ 	  timer(s) in the CS5535 and CS5536 companion chip for the geode.
+@@ -1575,6 +1563,7 @@ source "fs/Kconfig.binfmt"
+ config IA32_EMULATION
+ 	bool "IA32 Emulation"
+ 	depends on X86_64
++	select COMPAT_BINFMT_ELF
+ 	help
+ 	  Include code to run 32-bit programs under a 64-bit kernel. You should
+ 	  likely turn this on, unless you're 100% sure that you don't have any
+@@ -1587,18 +1576,16 @@ config IA32_AOUT
+          Support old a.out binaries in the 32bit emulation.
+ 
+ config COMPAT
+-	bool
++	def_bool y
+ 	depends on IA32_EMULATION
+-	default y
+ 
+ config COMPAT_FOR_U64_ALIGNMENT
+ 	def_bool COMPAT
+ 	depends on X86_64
+ 
+ config SYSVIPC_COMPAT
+-	bool
++	def_bool y
+ 	depends on X86_64 && COMPAT && SYSVIPC
+-	default y
+ 
+ endmenu
+ 
+@@ -1611,12 +1598,12 @@ source "drivers/firmware/Kconfig"
+ 
+ source "fs/Kconfig"
+ 
+-source "kernel/Kconfig.instrumentation"
 -
--#define kdf6(k,i)							\
--{									\
--	ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];				\
--	k[6*(i)+ 6] = ff(ss[0]);					\
--	ss[1] ^= ss[0];							\
--	k[6*(i)+ 7] = ff(ss[1]);					\
--	ss[2] ^= ss[1];							\
--	k[6*(i)+ 8] = ff(ss[2]);					\
--	ss[3] ^= ss[2];							\
--	k[6*(i)+ 9] = ff(ss[3]);					\
--	ss[4] ^= ss[3];							\
--	k[6*(i)+10] = ff(ss[4]);					\
--	ss[5] ^= ss[4];							\
--	k[6*(i)+11] = ff(ss[5]);					\
--}
+ source "arch/x86/Kconfig.debug"
+ 
+ source "security/Kconfig"
+ 
+ source "crypto/Kconfig"
+ 
++source "arch/x86/kvm/Kconfig"
++
+ source "lib/Kconfig"
+diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu
+index c301622..e09a6b7 100644
+--- a/arch/x86/Kconfig.cpu
++++ b/arch/x86/Kconfig.cpu
+@@ -219,10 +219,10 @@ config MGEODEGX1
+ 	  Select this for a Geode GX1 (Cyrix MediaGX) chip.
+ 
+ config MGEODE_LX
+-       bool "Geode GX/LX"
++	bool "Geode GX/LX"
+ 	depends on X86_32
+-       help
+-         Select this for AMD Geode GX and LX processors.
++	help
++	  Select this for AMD Geode GX and LX processors.
+ 
+ config MCYRIXIII
+ 	bool "CyrixIII/VIA-C3"
+@@ -258,7 +258,7 @@ config MPSC
+ 	  Optimize for Intel Pentium 4, Pentium D and older Nocona/Dempsey
+ 	  Xeon CPUs with Intel 64bit which is compatible with x86-64.
+ 	  Note that the latest Xeons (Xeon 51xx and 53xx) are not based on the
+-          Netburst core and shouldn't use this option. You can distinguish them
++	  Netburst core and shouldn't use this option. You can distinguish them
+ 	  using the cpu family field
+ 	  in /proc/cpuinfo. Family 15 is an older Xeon, Family 6 a newer one.
+ 
+@@ -317,81 +317,75 @@ config X86_L1_CACHE_SHIFT
+ 	default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7
+ 
+ config X86_XADD
+-	bool
++	def_bool y
+ 	depends on X86_32 && !M386
+-	default y
+ 
+ config X86_PPRO_FENCE
+-	bool
++	bool "PentiumPro memory ordering errata workaround"
+ 	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODEGX1
+-	default y
++	help
++	  Old PentiumPro multiprocessor systems had errata that could cause memory
++	  operations to violate the x86 ordering standard in rare cases. Enabling this
++	  option will attempt to work around some (but not all) occurances of
++	  this problem, at the cost of much heavier spinlock and memory barrier
++	  operations.
++
++	  If unsure, say n here. Even distro kernels should think twice before enabling
++	  this: there are few systems, and an unlikely bug.
+ 
+ config X86_F00F_BUG
+-	bool
++	def_bool y
+ 	depends on M586MMX || M586TSC || M586 || M486 || M386
+-	default y
+ 
+ config X86_WP_WORKS_OK
+-	bool
++	def_bool y
+ 	depends on X86_32 && !M386
+-	default y
+ 
+ config X86_INVLPG
+-	bool
++	def_bool y
+ 	depends on X86_32 && !M386
+-	default y
+ 
+ config X86_BSWAP
+-	bool
++	def_bool y
+ 	depends on X86_32 && !M386
+-	default y
+ 
+ config X86_POPAD_OK
+-	bool
++	def_bool y
+ 	depends on X86_32 && !M386
+-	default y
+ 
+ config X86_ALIGNMENT_16
+-	bool
++	def_bool y
+ 	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
+-	default y
+ 
+ config X86_GOOD_APIC
+-	bool
++	def_bool y
+ 	depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 || MEFFICEON || MCORE2 || MVIAC7 || X86_64
+-	default y
+ 
+ config X86_INTEL_USERCOPY
+-	bool
++	def_bool y
+ 	depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 || MEFFICEON || MCORE2
+-	default y
+ 
+ config X86_USE_PPRO_CHECKSUM
+-	bool
++	def_bool y
+ 	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2
+-	default y
+ 
+ config X86_USE_3DNOW
+-	bool
++	def_bool y
+ 	depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML
+-	default y
+ 
+ config X86_OOSTORE
+-	bool
++	def_bool y
+ 	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
+-	default y
+ 
+ config X86_TSC
+-	bool
++	def_bool y
+ 	depends on ((MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ) || X86_64
+-	default y
+ 
+ # this should be set for all -march=.. options where the compiler
+ # generates cmov.
+ config X86_CMOV
+-	bool
++	def_bool y
+ 	depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7)
+-	default y
+ 
+ config X86_MINIMUM_CPU_FAMILY
+ 	int
+@@ -399,3 +393,6 @@ config X86_MINIMUM_CPU_FAMILY
+ 	default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK)
+ 	default "3"
+ 
++config X86_DEBUGCTLMSR
++	def_bool y
++	depends on !(M586MMX || M586TSC || M586 || M486 || M386)
+diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
+index 761ca7b..2e1e3af 100644
+--- a/arch/x86/Kconfig.debug
++++ b/arch/x86/Kconfig.debug
+@@ -6,7 +6,7 @@ config TRACE_IRQFLAGS_SUPPORT
+ source "lib/Kconfig.debug"
+ 
+ config EARLY_PRINTK
+-	bool "Early printk" if EMBEDDED && DEBUG_KERNEL && X86_32
++	bool "Early printk" if EMBEDDED
+ 	default y
+ 	help
+ 	  Write kernel log output directly into the VGA buffer or to a serial
+@@ -40,22 +40,49 @@ comment "Page alloc debug is incompatible with Software Suspend on i386"
+ 
+ config DEBUG_PAGEALLOC
+ 	bool "Debug page memory allocations"
+-	depends on DEBUG_KERNEL && !HIBERNATION && !HUGETLBFS
+-	depends on X86_32
++	depends on DEBUG_KERNEL && X86_32
+ 	help
+ 	  Unmap pages from the kernel linear mapping after free_pages().
+ 	  This results in a large slowdown, but helps to find certain types
+ 	  of memory corruptions.
+ 
++config DEBUG_PER_CPU_MAPS
++	bool "Debug access to per_cpu maps"
++	depends on DEBUG_KERNEL
++	depends on X86_64_SMP
++	default n
++	help
++	  Say Y to verify that the per_cpu map being accessed has
++	  been setup.  Adds a fair amount of code to kernel memory
++	  and decreases performance.
++
++	  Say N if unsure.
++
+ config DEBUG_RODATA
+ 	bool "Write protect kernel read-only data structures"
++	default y
+ 	depends on DEBUG_KERNEL
+ 	help
+ 	  Mark the kernel read-only data as write-protected in the pagetables,
+ 	  in order to catch accidental (and incorrect) writes to such const
+-	  data. This option may have a slight performance impact because a
+-	  portion of the kernel code won't be covered by a 2MB TLB anymore.
+-	  If in doubt, say "N".
++	  data. This is recommended so that we can catch kernel bugs sooner.
++	  If in doubt, say "Y".
++
++config DEBUG_RODATA_TEST
++	bool "Testcase for the DEBUG_RODATA feature"
++	depends on DEBUG_RODATA
++	help
++	  This option enables a testcase for the DEBUG_RODATA
++	  feature as well as for the change_page_attr() infrastructure.
++	  If in doubt, say "N"
++
++config DEBUG_NX_TEST
++	tristate "Testcase for the NX non-executable stack feature"
++	depends on DEBUG_KERNEL && m
++	help
++	  This option enables a testcase for the CPU NX capability
++	  and the software setup of this feature.
++	  If in doubt, say "N"
+ 
+ config 4KSTACKS
+ 	bool "Use 4Kb for kernel stacks instead of 8Kb"
+@@ -75,8 +102,7 @@ config X86_FIND_SMP_CONFIG
+ 
+ config X86_MPPARSE
+ 	def_bool y
+-	depends on X86_LOCAL_APIC && !X86_VISWS
+-	depends on X86_32
++	depends on (X86_32 && (X86_LOCAL_APIC && !X86_VISWS)) || X86_64
+ 
+ config DOUBLEFAULT
+ 	default y
+@@ -112,4 +138,91 @@ config IOMMU_LEAK
+ 	  Add a simple leak tracer to the IOMMU code. This is useful when you
+ 	  are debugging a buggy device driver that leaks IOMMU mappings.
+ 
++#
++# IO delay types:
++#
++
++config IO_DELAY_TYPE_0X80
++	int
++	default "0"
++
++config IO_DELAY_TYPE_0XED
++	int
++	default "1"
++
++config IO_DELAY_TYPE_UDELAY
++	int
++	default "2"
++
++config IO_DELAY_TYPE_NONE
++	int
++	default "3"
++
++choice
++	prompt "IO delay type"
++	default IO_DELAY_0XED
++
++config IO_DELAY_0X80
++	bool "port 0x80 based port-IO delay [recommended]"
++	help
++	  This is the traditional Linux IO delay used for in/out_p.
++	  It is the most tested hence safest selection here.
++
++config IO_DELAY_0XED
++	bool "port 0xed based port-IO delay"
++	help
++	  Use port 0xed as the IO delay. This frees up port 0x80 which is
++	  often used as a hardware-debug port.
++
++config IO_DELAY_UDELAY
++	bool "udelay based port-IO delay"
++	help
++	  Use udelay(2) as the IO delay method. This provides the delay
++	  while not having any side-effect on the IO port space.
++
++config IO_DELAY_NONE
++	bool "no port-IO delay"
++	help
++	  No port-IO delay. Will break on old boxes that require port-IO
++	  delay for certain operations. Should work on most new machines.
++
++endchoice
++
++if IO_DELAY_0X80
++config DEFAULT_IO_DELAY_TYPE
++	int
++	default IO_DELAY_TYPE_0X80
++endif
++
++if IO_DELAY_0XED
++config DEFAULT_IO_DELAY_TYPE
++	int
++	default IO_DELAY_TYPE_0XED
++endif
++
++if IO_DELAY_UDELAY
++config DEFAULT_IO_DELAY_TYPE
++	int
++	default IO_DELAY_TYPE_UDELAY
++endif
++
++if IO_DELAY_NONE
++config DEFAULT_IO_DELAY_TYPE
++	int
++	default IO_DELAY_TYPE_NONE
++endif
++
++config DEBUG_BOOT_PARAMS
++	bool "Debug boot parameters"
++	depends on DEBUG_KERNEL
++	depends on DEBUG_FS
++	help
++	  This option will cause struct boot_params to be exported via debugfs.
++
++config CPA_DEBUG
++	bool "CPA self test code"
++	depends on DEBUG_KERNEL
++	help
++	  Do change_page_attr self tests at boot.
++
+ endmenu
+diff --git a/arch/x86/Makefile b/arch/x86/Makefile
+index 7aa1dc6..364865b 100644
+--- a/arch/x86/Makefile
++++ b/arch/x86/Makefile
+@@ -7,13 +7,253 @@ else
+         KBUILD_DEFCONFIG := $(ARCH)_defconfig
+ endif
+ 
+-# No need to remake these files
+-$(srctree)/arch/x86/Makefile%: ;
++core-$(CONFIG_KVM) += arch/x86/kvm/
++
++# BITS is used as extension for files which are available in a 32 bit
++# and a 64 bit version to simplify shared Makefiles.
++# e.g.: obj-y += foo_$(BITS).o
++export BITS
+ 
+ ifeq ($(CONFIG_X86_32),y)
++        BITS := 32
+         UTS_MACHINE := i386
+-        include $(srctree)/arch/x86/Makefile_32
++        CHECKFLAGS += -D__i386__
++
++        biarch := $(call cc-option,-m32)
++        KBUILD_AFLAGS += $(biarch)
++        KBUILD_CFLAGS += $(biarch)
++
++        ifdef CONFIG_RELOCATABLE
++                LDFLAGS_vmlinux := --emit-relocs
++        endif
++
++        KBUILD_CFLAGS += -msoft-float -mregparm=3 -freg-struct-return
++
++        # prevent gcc from keeping the stack 16 byte aligned
++        KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
++
++        # Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
++        # a lot more stack due to the lack of sharing of stacklots:
++        KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then \
++                echo $(call cc-option,-fno-unit-at-a-time); fi ;)
++
++        # CPU-specific tuning. Anything which can be shared with UML should go here.
++        include $(srctree)/arch/x86/Makefile_32.cpu
++        KBUILD_CFLAGS += $(cflags-y)
++
++        # temporary until string.h is fixed
++        KBUILD_CFLAGS += -ffreestanding
+ else
++        BITS := 64
+         UTS_MACHINE := x86_64
+-        include $(srctree)/arch/x86/Makefile_64
++        CHECKFLAGS += -D__x86_64__ -m64
++
++        KBUILD_AFLAGS += -m64
++        KBUILD_CFLAGS += -m64
++
++        # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
++        cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
++        cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
++
++        cflags-$(CONFIG_MCORE2) += \
++                $(call cc-option,-march=core2,$(call cc-option,-mtune=generic))
++        cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
++        KBUILD_CFLAGS += $(cflags-y)
++
++        KBUILD_CFLAGS += -mno-red-zone
++        KBUILD_CFLAGS += -mcmodel=kernel
++
++        # -funit-at-a-time shrinks the kernel .text considerably
++        # unfortunately it makes reading oopses harder.
++        KBUILD_CFLAGS += $(call cc-option,-funit-at-a-time)
++
++        # this works around some issues with generating unwind tables in older gccs
++        # newer gccs do it by default
++        KBUILD_CFLAGS += -maccumulate-outgoing-args
++
++        stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh
++        stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \
++                "$(CC)" -fstack-protector )
++        stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \
++                "$(CC)" -fstack-protector-all )
++
++        KBUILD_CFLAGS += $(stackp-y)
+ endif
++
++# Stackpointer is addressed different for 32 bit and 64 bit x86
++sp-$(CONFIG_X86_32) := esp
++sp-$(CONFIG_X86_64) := rsp
++
++# do binutils support CFI?
++cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_endproc,-DCONFIG_AS_CFI=1)
++# is .cfi_signal_frame supported too?
++cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
++KBUILD_AFLAGS += $(cfi) $(cfi-sigframe)
++KBUILD_CFLAGS += $(cfi) $(cfi-sigframe)
++
++LDFLAGS := -m elf_$(UTS_MACHINE)
++
++# Speed up the build
++KBUILD_CFLAGS += -pipe
++# Workaround for a gcc prelease that unfortunately was shipped in a suse release
++KBUILD_CFLAGS += -Wno-sign-compare
++#
++KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
++# prevent gcc from generating any FP code by mistake
++KBUILD_CFLAGS += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
++
++###
++# Sub architecture support
++# fcore-y is linked before mcore-y files.
++
++# Default subarch .c files
++mcore-y  := arch/x86/mach-default/
++
++# Voyager subarch support
++mflags-$(CONFIG_X86_VOYAGER)	:= -Iinclude/asm-x86/mach-voyager
++mcore-$(CONFIG_X86_VOYAGER)	:= arch/x86/mach-voyager/
++
++# VISWS subarch support
++mflags-$(CONFIG_X86_VISWS)	:= -Iinclude/asm-x86/mach-visws
++mcore-$(CONFIG_X86_VISWS)	:= arch/x86/mach-visws/
++
++# NUMAQ subarch support
++mflags-$(CONFIG_X86_NUMAQ)	:= -Iinclude/asm-x86/mach-numaq
++mcore-$(CONFIG_X86_NUMAQ)	:= arch/x86/mach-default/
++
++# BIGSMP subarch support
++mflags-$(CONFIG_X86_BIGSMP)	:= -Iinclude/asm-x86/mach-bigsmp
++mcore-$(CONFIG_X86_BIGSMP)	:= arch/x86/mach-default/
++
++#Summit subarch support
++mflags-$(CONFIG_X86_SUMMIT)	:= -Iinclude/asm-x86/mach-summit
++mcore-$(CONFIG_X86_SUMMIT)	:= arch/x86/mach-default/
++
++# generic subarchitecture
++mflags-$(CONFIG_X86_GENERICARCH):= -Iinclude/asm-x86/mach-generic
++fcore-$(CONFIG_X86_GENERICARCH)	+= arch/x86/mach-generic/
++mcore-$(CONFIG_X86_GENERICARCH)	:= arch/x86/mach-default/
++
++
++# ES7000 subarch support
++mflags-$(CONFIG_X86_ES7000)	:= -Iinclude/asm-x86/mach-es7000
++fcore-$(CONFIG_X86_ES7000)	:= arch/x86/mach-es7000/
++mcore-$(CONFIG_X86_ES7000)	:= arch/x86/mach-default/
++
++# RDC R-321x subarch support
++mflags-$(CONFIG_X86_RDC321X)	:= -Iinclude/asm-x86/mach-rdc321x
++mcore-$(CONFIG_X86_RDC321X)	:= arch/x86/mach-default/
++core-$(CONFIG_X86_RDC321X)	+= arch/x86/mach-rdc321x/
++
++# default subarch .h files
++mflags-y += -Iinclude/asm-x86/mach-default
++
++# 64 bit does not support subarch support - clear sub arch variables
++fcore-$(CONFIG_X86_64)  :=
++mcore-$(CONFIG_X86_64)  :=
++mflags-$(CONFIG_X86_64) :=
++
++KBUILD_CFLAGS += $(mflags-y)
++KBUILD_AFLAGS += $(mflags-y)
++
++###
++# Kernel objects
++
++head-y                := arch/x86/kernel/head_$(BITS).o
++head-$(CONFIG_X86_64) += arch/x86/kernel/head64.o
++head-y                += arch/x86/kernel/init_task.o
++
++libs-y  += arch/x86/lib/
++
++# Sub architecture files that needs linking first
++core-y += $(fcore-y)
++
++# Xen paravirtualization support
++core-$(CONFIG_XEN) += arch/x86/xen/
++
++# lguest paravirtualization support
++core-$(CONFIG_LGUEST_GUEST) += arch/x86/lguest/
++
++core-y += arch/x86/kernel/
++core-y += arch/x86/mm/
++
++# Remaining sub architecture files
++core-y += $(mcore-y)
++
++core-y += arch/x86/crypto/
++core-y += arch/x86/vdso/
++core-$(CONFIG_IA32_EMULATION) += arch/x86/ia32/
++
++# drivers-y are linked after core-y
++drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
++drivers-$(CONFIG_PCI)            += arch/x86/pci/
++
++# must be linked after kernel/
++drivers-$(CONFIG_OPROFILE) += arch/x86/oprofile/
++
++ifeq ($(CONFIG_X86_32),y)
++drivers-$(CONFIG_PM) += arch/x86/power/
++drivers-$(CONFIG_FB) += arch/x86/video/
++endif
++
++####
++# boot loader support. Several targets are kept for legacy purposes
++
++boot := arch/x86/boot
++
++PHONY += zImage bzImage compressed zlilo bzlilo \
++         zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
++
++# Default kernel to build
++all: bzImage
++
++# KBUILD_IMAGE specify target image being built
++                    KBUILD_IMAGE := $(boot)/bzImage
++zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage
++
++zImage bzImage: vmlinux
++	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
++	$(Q)mkdir -p $(objtree)/arch/$(UTS_MACHINE)/boot
++	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/$(UTS_MACHINE)/boot/bzImage
++
++compressed: zImage
++
++zlilo bzlilo: vmlinux
++	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo
++
++zdisk bzdisk: vmlinux
++	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
++
++fdimage fdimage144 fdimage288 isoimage: vmlinux
++	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
++
++install: vdso_install
++	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
++
++PHONY += vdso_install
++vdso_install:
++	$(Q)$(MAKE) $(build)=arch/x86/vdso $@
++
++archclean:
++	$(Q)rm -rf $(objtree)/arch/i386
++	$(Q)rm -rf $(objtree)/arch/x86_64
++	$(Q)$(MAKE) $(clean)=$(boot)
++
++define archhelp
++  echo  '* bzImage      - Compressed kernel image (arch/x86/boot/bzImage)'
++  echo  '  install      - Install kernel using'
++  echo  '                  (your) ~/bin/installkernel or'
++  echo  '                  (distribution) /sbin/installkernel or'
++  echo  '                  install to $$(INSTALL_PATH) and run lilo'
++  echo  '  fdimage      - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)'
++  echo  '  fdimage144   - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)'
++  echo  '  fdimage288   - Create 2.8MB boot floppy image (arch/x86/boot/fdimage)'
++  echo  '  isoimage     - Create a boot CD-ROM image (arch/x86/boot/image.iso)'
++  echo  '                  bzdisk/fdimage*/isoimage also accept:'
++  echo  '                  FDARGS="..."  arguments for the booted kernel'
++  echo  '                  FDINITRD=file initrd for the booted kernel'
++endef
++
++CLEAN_FILES += arch/x86/boot/fdimage \
++	       arch/x86/boot/image.iso \
++	       arch/x86/boot/mtools.conf
+diff --git a/arch/x86/Makefile_32 b/arch/x86/Makefile_32
+deleted file mode 100644
+index 50394da..0000000
+--- a/arch/x86/Makefile_32
++++ /dev/null
+@@ -1,175 +0,0 @@
+-#
+-# i386 Makefile
+-#
+-# This file is included by the global makefile so that you can add your own
+-# architecture-specific flags and dependencies. Remember to do have actions
+-# for "archclean" cleaning up for this architecture.
+-#
+-# 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) 1994 by Linus Torvalds
+-#
+-# 19990713  Artur Skawina <skawina at geocities.com>
+-#           Added '-march' and '-mpreferred-stack-boundary' support
+-#
+-# 20050320  Kianusch Sayah Karadji <kianusch at sk-tech.net>
+-#           Added support for GEODE CPU
 -
--#define kd6(k,i)							\
--{									\
--	ss[6] = ls_box(ss[5],3) ^ rcon_tab[i];				\
--	ss[0] ^= ss[6]; ss[6] = ff(ss[6]);				\
--	k[6*(i)+ 6] = ss[6] ^= k[6*(i)];				\
--	ss[1] ^= ss[0];							\
--	k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1];				\
--	ss[2] ^= ss[1];							\
--	k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2];				\
--	ss[3] ^= ss[2];							\
--	k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3];				\
--	ss[4] ^= ss[3];							\
--	k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4];				\
--	ss[5] ^= ss[4];							\
--	k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5];				\
--}
+-# BITS is used as extension for files which are available in a 32 bit
+-# and a 64 bit version to simplify shared Makefiles.
+-# e.g.: obj-y += foo_$(BITS).o
+-BITS := 32
+-export BITS
 -
--#define kdl6(k,i)							\
--{									\
--	ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];				\
--	k[6*(i)+ 6] = ss[0];						\
--	ss[1] ^= ss[0];							\
--	k[6*(i)+ 7] = ss[1];						\
--	ss[2] ^= ss[1];							\
--	k[6*(i)+ 8] = ss[2];						\
--	ss[3] ^= ss[2];							\
--	k[6*(i)+ 9] = ss[3];						\
--}
+-HAS_BIARCH      := $(call cc-option-yn, -m32)
+-ifeq ($(HAS_BIARCH),y)
+-AS              := $(AS) --32
+-LD              := $(LD) -m elf_i386
+-CC              := $(CC) -m32
+-endif
 -
--#define kdf8(k,i)							\
--{									\
--	ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];				\
--	k[8*(i)+ 8] = ff(ss[0]);					\
--	ss[1] ^= ss[0];							\
--	k[8*(i)+ 9] = ff(ss[1]);					\
--	ss[2] ^= ss[1];							\
--	k[8*(i)+10] = ff(ss[2]);					\
--	ss[3] ^= ss[2];							\
--	k[8*(i)+11] = ff(ss[3]);					\
--	ss[4] ^= ls_box(ss[3],0);					\
--	k[8*(i)+12] = ff(ss[4]);					\
--	ss[5] ^= ss[4];							\
--	k[8*(i)+13] = ff(ss[5]);					\
--	ss[6] ^= ss[5];							\
--	k[8*(i)+14] = ff(ss[6]);					\
--	ss[7] ^= ss[6];							\
--	k[8*(i)+15] = ff(ss[7]);					\
--}
+-LDFLAGS		:= -m elf_i386
+-OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
+-ifdef CONFIG_RELOCATABLE
+-LDFLAGS_vmlinux := --emit-relocs
+-endif
+-CHECKFLAGS	+= -D__i386__
 -
--#define kd8(k,i)							\
--{									\
--	u32 __g = ls_box(ss[7],3) ^ rcon_tab[i];			\
--	ss[0] ^= __g;							\
--	__g = ff(__g);							\
--	k[8*(i)+ 8] = __g ^= k[8*(i)];					\
--	ss[1] ^= ss[0];							\
--	k[8*(i)+ 9] = __g ^= k[8*(i)+ 1];				\
--	ss[2] ^= ss[1];							\
--	k[8*(i)+10] = __g ^= k[8*(i)+ 2];				\
--	ss[3] ^= ss[2];							\
--	k[8*(i)+11] = __g ^= k[8*(i)+ 3];				\
--	__g = ls_box(ss[3],0);						\
--	ss[4] ^= __g;							\
--	__g = ff(__g);							\
--	k[8*(i)+12] = __g ^= k[8*(i)+ 4];				\
--	ss[5] ^= ss[4];							\
--	k[8*(i)+13] = __g ^= k[8*(i)+ 5];				\
--	ss[6] ^= ss[5];							\
--	k[8*(i)+14] = __g ^= k[8*(i)+ 6];				\
--	ss[7] ^= ss[6];							\
--	k[8*(i)+15] = __g ^= k[8*(i)+ 7];				\
--}
+-KBUILD_CFLAGS += -pipe -msoft-float -mregparm=3 -freg-struct-return
 -
--#define kdl8(k,i)							\
--{									\
--	ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];				\
--	k[8*(i)+ 8] = ss[0];						\
--	ss[1] ^= ss[0];							\
--	k[8*(i)+ 9] = ss[1];						\
--	ss[2] ^= ss[1];							\
--	k[8*(i)+10] = ss[2];						\
--	ss[3] ^= ss[2];							\
--	k[8*(i)+11] = ss[3];						\
--}
+-# prevent gcc from keeping the stack 16 byte aligned
+-KBUILD_CFLAGS += $(call cc-option,-mpreferred-stack-boundary=2)
 -
--static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
--		       unsigned int key_len)
--{
--	int i;
--	u32 ss[8];
--	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
--	const __le32 *key = (const __le32 *)in_key;
--	u32 *flags = &tfm->crt_flags;
+-# CPU-specific tuning. Anything which can be shared with UML should go here.
+-include $(srctree)/arch/x86/Makefile_32.cpu
 -
--	/* encryption schedule */
--	
--	ctx->ekey[0] = ss[0] = le32_to_cpu(key[0]);
--	ctx->ekey[1] = ss[1] = le32_to_cpu(key[1]);
--	ctx->ekey[2] = ss[2] = le32_to_cpu(key[2]);
--	ctx->ekey[3] = ss[3] = le32_to_cpu(key[3]);
+-# temporary until string.h is fixed
+-cflags-y += -ffreestanding
 -
--	switch(key_len) {
--	case 16:
--		for (i = 0; i < 9; i++)
--			ke4(ctx->ekey, i);
--		kel4(ctx->ekey, 9);
--		ctx->rounds = 10;
--		break;
--		
--	case 24:
--		ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
--		ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
--		for (i = 0; i < 7; i++)
--			ke6(ctx->ekey, i);
--		kel6(ctx->ekey, 7); 
--		ctx->rounds = 12;
--		break;
+-# this works around some issues with generating unwind tables in older gccs
+-# newer gccs do it by default
+-cflags-y += -maccumulate-outgoing-args
 -
--	case 32:
--		ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
--		ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
--		ctx->ekey[6] = ss[6] = le32_to_cpu(key[6]);
--		ctx->ekey[7] = ss[7] = le32_to_cpu(key[7]);
--		for (i = 0; i < 6; i++)
--			ke8(ctx->ekey, i);
--		kel8(ctx->ekey, 6);
--		ctx->rounds = 14;
--		break;
+-# Disable unit-at-a-time mode on pre-gcc-4.0 compilers, it makes gcc use
+-# a lot more stack due to the lack of sharing of stacklots:
+-KBUILD_CFLAGS += $(shell if [ $(call cc-version) -lt 0400 ] ; then echo $(call cc-option,-fno-unit-at-a-time); fi ;)
 -
--	default:
--		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
--		return -EINVAL;
--	}
--	
--	/* decryption schedule */
--	
--	ctx->dkey[0] = ss[0] = le32_to_cpu(key[0]);
--	ctx->dkey[1] = ss[1] = le32_to_cpu(key[1]);
--	ctx->dkey[2] = ss[2] = le32_to_cpu(key[2]);
--	ctx->dkey[3] = ss[3] = le32_to_cpu(key[3]);
+-# do binutils support CFI?
+-cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+-KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset esp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
 -
--	switch (key_len) {
--	case 16:
--		kdf4(ctx->dkey, 0);
--		for (i = 1; i < 9; i++)
--			kd4(ctx->dkey, i);
--		kdl4(ctx->dkey, 9);
--		break;
--		
--	case 24:
--		ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
--		ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
--		kdf6(ctx->dkey, 0);
--		for (i = 1; i < 7; i++)
--			kd6(ctx->dkey, i);
--		kdl6(ctx->dkey, 7);
--		break;
+-# is .cfi_signal_frame supported too?
+-cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+-KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
 -
--	case 32:
--		ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
--		ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
--		ctx->dkey[6] = ff(ss[6] = le32_to_cpu(key[6]));
--		ctx->dkey[7] = ff(ss[7] = le32_to_cpu(key[7]));
--		kdf8(ctx->dkey, 0);
--		for (i = 1; i < 6; i++)
--			kd8(ctx->dkey, i);
--		kdl8(ctx->dkey, 6);
--		break;
--	}
--	return 0;
--}
+-KBUILD_CFLAGS += $(cflags-y)
 -
--static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
--{
--	aes_enc_blk(tfm, dst, src);
--}
+-# Default subarch .c files
+-mcore-y  := arch/x86/mach-default
 -
--static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
--{
--	aes_dec_blk(tfm, dst, src);
--}
+-# Voyager subarch support
+-mflags-$(CONFIG_X86_VOYAGER)	:= -Iinclude/asm-x86/mach-voyager
+-mcore-$(CONFIG_X86_VOYAGER)	:= arch/x86/mach-voyager
 -
--static struct crypto_alg aes_alg = {
--	.cra_name		=	"aes",
--	.cra_driver_name	=	"aes-i586",
--	.cra_priority		=	200,
--	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
--	.cra_blocksize		=	AES_BLOCK_SIZE,
--	.cra_ctxsize		=	sizeof(struct aes_ctx),
--	.cra_module		=	THIS_MODULE,
--	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
--	.cra_u			=	{
--		.cipher = {
--			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
--			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
--			.cia_setkey	   	= 	aes_set_key,
--			.cia_encrypt	 	=	aes_encrypt,
--			.cia_decrypt	  	=	aes_decrypt
--		}
--	}
--};
+-# VISWS subarch support
+-mflags-$(CONFIG_X86_VISWS)	:= -Iinclude/asm-x86/mach-visws
+-mcore-$(CONFIG_X86_VISWS)	:= arch/x86/mach-visws
 -
--static int __init aes_init(void)
--{
--	gen_tabs();
--	return crypto_register_alg(&aes_alg);
--}
+-# NUMAQ subarch support
+-mflags-$(CONFIG_X86_NUMAQ)	:= -Iinclude/asm-x86/mach-numaq
+-mcore-$(CONFIG_X86_NUMAQ)	:= arch/x86/mach-default
 -
--static void __exit aes_fini(void)
--{
--	crypto_unregister_alg(&aes_alg);
--}
+-# BIGSMP subarch support
+-mflags-$(CONFIG_X86_BIGSMP)	:= -Iinclude/asm-x86/mach-bigsmp
+-mcore-$(CONFIG_X86_BIGSMP)	:= arch/x86/mach-default
 -
--module_init(aes_init);
--module_exit(aes_fini);
+-#Summit subarch support
+-mflags-$(CONFIG_X86_SUMMIT) := -Iinclude/asm-x86/mach-summit
+-mcore-$(CONFIG_X86_SUMMIT)  := arch/x86/mach-default
 -
--MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, i586 asm optimized");
--MODULE_LICENSE("Dual BSD/GPL");
--MODULE_AUTHOR("Fruhwirth Clemens, James Morris, Brian Gladman, Adam Richter");
--MODULE_ALIAS("aes");
-diff --git a/arch/x86/crypto/aes_64.c b/arch/x86/crypto/aes_64.c
-deleted file mode 100644
-index 5cdb13e..0000000
---- a/arch/x86/crypto/aes_64.c
-+++ /dev/null
-@@ -1,336 +0,0 @@
--/*
-- * Cryptographic API.
-- *
-- * AES Cipher Algorithm.
-- *
-- * Based on Brian Gladman's code.
-- *
-- * Linux developers:
-- *  Alexander Kjeldaas <astor at fast.no>
-- *  Herbert Valerio Riedel <hvr at hvrlab.org>
-- *  Kyle McMartin <kyle at debian.org>
-- *  Adam J. Richter <adam at yggdrasil.com> (conversion to 2.5 API).
-- *  Andreas Steinmetz <ast at domdv.de> (adapted to x86_64 assembler)
-- *
-- * 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.
-- *
-- * ---------------------------------------------------------------------------
-- * Copyright (c) 2002, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
-- * All rights reserved.
-- *
-- * LICENSE TERMS
-- *
-- * The free distribution and use of this software in both source and binary
-- * form is allowed (with or without changes) provided that:
-- *
-- *   1. distributions of this source code include the above copyright
-- *      notice, this list of conditions and the following disclaimer;
-- *
-- *   2. distributions in binary form include the above copyright
-- *      notice, this list of conditions and the following disclaimer
-- *      in the documentation and/or other associated materials;
-- *
-- *   3. the copyright holder's name is not used to endorse products
-- *      built using this software without specific written permission.
-- *
-- * ALTERNATIVELY, provided that this notice is retained in full, this product
-- * may be distributed under the terms of the GNU General Public License (GPL),
-- * in which case the provisions of the GPL apply INSTEAD OF those given above.
-- *
-- * DISCLAIMER
-- *
-- * This software is provided 'as is' with no explicit or implied warranties
-- * in respect of its properties, including, but not limited to, correctness
-- * and/or fitness for purpose.
-- * ---------------------------------------------------------------------------
-- */
+-# generic subarchitecture
+-mflags-$(CONFIG_X86_GENERICARCH) := -Iinclude/asm-x86/mach-generic
+-mcore-$(CONFIG_X86_GENERICARCH) := arch/x86/mach-default
+-core-$(CONFIG_X86_GENERICARCH) += arch/x86/mach-generic/
 -
--/* Some changes from the Gladman version:
--    s/RIJNDAEL(e_key)/E_KEY/g
--    s/RIJNDAEL(d_key)/D_KEY/g
--*/
+-# ES7000 subarch support
+-mflags-$(CONFIG_X86_ES7000)	:= -Iinclude/asm-x86/mach-es7000
+-mcore-$(CONFIG_X86_ES7000)	:= arch/x86/mach-default
+-core-$(CONFIG_X86_ES7000)	:= arch/x86/mach-es7000/
 -
--#include <asm/byteorder.h>
--#include <linux/bitops.h>
--#include <linux/crypto.h>
--#include <linux/errno.h>
--#include <linux/init.h>
--#include <linux/module.h>
--#include <linux/types.h>
+-# Xen paravirtualization support
+-core-$(CONFIG_XEN)		+= arch/x86/xen/
 -
--#define AES_MIN_KEY_SIZE	16
--#define AES_MAX_KEY_SIZE	32
+-# lguest paravirtualization support
+-core-$(CONFIG_LGUEST_GUEST)	+= arch/x86/lguest/
 -
--#define AES_BLOCK_SIZE		16
+-# default subarch .h files
+-mflags-y += -Iinclude/asm-x86/mach-default
 -
--/*
-- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
-- */
--static inline u8 byte(const u32 x, const unsigned n)
--{
--	return x >> (n << 3);
--}
+-head-y := arch/x86/kernel/head_32.o arch/x86/kernel/init_task.o
 -
--struct aes_ctx
--{
--	u32 key_length;
--	u32 buf[120];
--};
+-libs-y 					+= arch/x86/lib/
+-core-y					+= arch/x86/kernel/ \
+-					   arch/x86/mm/ \
+-					   $(mcore-y)/ \
+-					   arch/x86/crypto/
+-drivers-$(CONFIG_MATH_EMULATION)	+= arch/x86/math-emu/
+-drivers-$(CONFIG_PCI)			+= arch/x86/pci/
+-# must be linked after kernel/
+-drivers-$(CONFIG_OPROFILE)		+= arch/x86/oprofile/
+-drivers-$(CONFIG_PM)			+= arch/x86/power/
+-drivers-$(CONFIG_FB)                    += arch/x86/video/
 -
--#define E_KEY (&ctx->buf[0])
--#define D_KEY (&ctx->buf[60])
+-KBUILD_CFLAGS += $(mflags-y)
+-KBUILD_AFLAGS += $(mflags-y)
 -
--static u8 pow_tab[256] __initdata;
--static u8 log_tab[256] __initdata;
--static u8 sbx_tab[256] __initdata;
--static u8 isb_tab[256] __initdata;
--static u32 rco_tab[10];
--u32 aes_ft_tab[4][256];
--u32 aes_it_tab[4][256];
+-boot := arch/x86/boot
 -
--u32 aes_fl_tab[4][256];
--u32 aes_il_tab[4][256];
+-PHONY += zImage bzImage compressed zlilo bzlilo \
+-         zdisk bzdisk fdimage fdimage144 fdimage288 isoimage install
 -
--static inline u8 f_mult(u8 a, u8 b)
--{
--	u8 aa = log_tab[a], cc = aa + log_tab[b];
+-all: bzImage
 -
--	return pow_tab[cc + (cc < aa ? 1 : 0)];
--}
+-# KBUILD_IMAGE specify target image being built
+-                    KBUILD_IMAGE := $(boot)/bzImage
+-zImage zlilo zdisk: KBUILD_IMAGE := arch/x86/boot/zImage
 -
--#define ff_mult(a, b) (a && b ? f_mult(a, b) : 0)
+-zImage bzImage: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) $(KBUILD_IMAGE)
+-	$(Q)mkdir -p $(objtree)/arch/i386/boot
+-	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/i386/boot/bzImage
 -
--#define ls_box(x)				\
--	(aes_fl_tab[0][byte(x, 0)] ^		\
--	 aes_fl_tab[1][byte(x, 1)] ^		\
--	 aes_fl_tab[2][byte(x, 2)] ^		\
--	 aes_fl_tab[3][byte(x, 3)])
+-compressed: zImage
 -
--static void __init gen_tabs(void)
--{
--	u32 i, t;
--	u8 p, q;
+-zlilo bzlilo: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zlilo
 -
--	/* log and power tables for GF(2**8) finite field with
--	   0x011b as modular polynomial - the simplest primitive
--	   root is 0x03, used here to generate the tables */
+-zdisk bzdisk: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) zdisk
 -
--	for (i = 0, p = 1; i < 256; ++i) {
--		pow_tab[i] = (u8)p;
--		log_tab[p] = (u8)i;
+-fdimage fdimage144 fdimage288 isoimage: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) $@
 -
--		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
--	}
+-install:
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(KBUILD_IMAGE) install
 -
--	log_tab[1] = 0;
+-archclean:
+-	$(Q)rm -rf $(objtree)/arch/i386/boot
+-	$(Q)$(MAKE) $(clean)=arch/x86/boot
 -
--	for (i = 0, p = 1; i < 10; ++i) {
--		rco_tab[i] = p;
+-define archhelp
+-  echo  '* bzImage	- Compressed kernel image (arch/x86/boot/bzImage)'
+-  echo  '  install	- Install kernel using'
+-  echo  '		   (your) ~/bin/installkernel or'
+-  echo  '		   (distribution) /sbin/installkernel or'
+-  echo  '		   install to $$(INSTALL_PATH) and run lilo'
+-  echo  '  bzdisk       - Create a boot floppy in /dev/fd0'
+-  echo  '  fdimage      - Create a boot floppy image'
+-  echo  '  isoimage     - Create a boot CD-ROM image'
+-endef
 -
--		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
--	}
+-CLEAN_FILES += arch/x86/boot/fdimage \
+-	       arch/x86/boot/image.iso \
+-	       arch/x86/boot/mtools.conf
+diff --git a/arch/x86/Makefile_64 b/arch/x86/Makefile_64
+deleted file mode 100644
+index a804860..0000000
+--- a/arch/x86/Makefile_64
++++ /dev/null
+@@ -1,144 +0,0 @@
+-#
+-# x86_64 Makefile
+-#
+-# This file is included by the global makefile so that you can add your own
+-# architecture-specific flags and dependencies. Remember to do have actions
+-# for "archclean" and "archdep" for cleaning up and making dependencies for
+-# this architecture
+-#
+-# 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) 1994 by Linus Torvalds
+-#
+-# 19990713  Artur Skawina <skawina at geocities.com>
+-#           Added '-march' and '-mpreferred-stack-boundary' support
+-# 20000913  Pavel Machek <pavel at suse.cz>
+-#	    Converted for x86_64 architecture
+-# 20010105  Andi Kleen, add IA32 compiler.
+-#           ....and later removed it again....
+-#
+-# $Id: Makefile,v 1.31 2002/03/22 15:56:07 ak Exp $
 -
--	for (i = 0; i < 256; ++i) {
--		p = (i ? pow_tab[255 - log_tab[i]] : 0);
--		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
--		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
--		sbx_tab[i] = p;
--		isb_tab[p] = (u8)i;
--	}
+-# BITS is used as extension for files which are available in a 32 bit
+-# and a 64 bit version to simplify shared Makefiles.
+-# e.g.: obj-y += foo_$(BITS).o
+-BITS := 64
+-export BITS
 -
--	for (i = 0; i < 256; ++i) {
--		p = sbx_tab[i];
+-LDFLAGS		:= -m elf_x86_64
+-OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
+-LDFLAGS_vmlinux :=
+-CHECKFLAGS      += -D__x86_64__ -m64
 -
--		t = p;
--		aes_fl_tab[0][i] = t;
--		aes_fl_tab[1][i] = rol32(t, 8);
--		aes_fl_tab[2][i] = rol32(t, 16);
--		aes_fl_tab[3][i] = rol32(t, 24);
+-cflags-y	:=
+-cflags-kernel-y	:=
+-cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
+-cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
+-# gcc doesn't support -march=core2 yet as of gcc 4.3, but I hope it
+-# will eventually. Use -mtune=generic as fallback
+-cflags-$(CONFIG_MCORE2) += \
+-	$(call cc-option,-march=core2,$(call cc-option,-mtune=generic))
+-cflags-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=generic)
 -
--		t = ((u32)ff_mult(2, p)) |
--		    ((u32)p << 8) |
--		    ((u32)p << 16) | ((u32)ff_mult(3, p) << 24);
+-cflags-y += -m64
+-cflags-y += -mno-red-zone
+-cflags-y += -mcmodel=kernel
+-cflags-y += -pipe
+-cflags-y += -Wno-sign-compare
+-cflags-y += -fno-asynchronous-unwind-tables
+-ifneq ($(CONFIG_DEBUG_INFO),y)
+-# -fweb shrinks the kernel a bit, but the difference is very small
+-# it also messes up debugging, so don't use it for now.
+-#cflags-y += $(call cc-option,-fweb)
+-endif
+-# -funit-at-a-time shrinks the kernel .text considerably
+-# unfortunately it makes reading oopses harder.
+-cflags-y += $(call cc-option,-funit-at-a-time)
+-# prevent gcc from generating any FP code by mistake
+-cflags-y += $(call cc-option,-mno-sse -mno-mmx -mno-sse2 -mno-3dnow,)
+-# this works around some issues with generating unwind tables in older gccs
+-# newer gccs do it by default
+-cflags-y += -maccumulate-outgoing-args
 -
--		aes_ft_tab[0][i] = t;
--		aes_ft_tab[1][i] = rol32(t, 8);
--		aes_ft_tab[2][i] = rol32(t, 16);
--		aes_ft_tab[3][i] = rol32(t, 24);
+-# do binutils support CFI?
+-cflags-y += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
+-KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_rel_offset rsp${comma}0\n.cfi_endproc,-DCONFIG_AS_CFI=1,)
 -
--		p = isb_tab[i];
+-# is .cfi_signal_frame supported too?
+-cflags-y += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
+-KBUILD_AFLAGS += $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1,)
 -
--		t = p;
--		aes_il_tab[0][i] = t;
--		aes_il_tab[1][i] = rol32(t, 8);
--		aes_il_tab[2][i] = rol32(t, 16);
--		aes_il_tab[3][i] = rol32(t, 24);
+-cflags-$(CONFIG_CC_STACKPROTECTOR) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector )
+-cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh "$(CC)" -fstack-protector-all )
 -
--		t = ((u32)ff_mult(14, p)) |
--		    ((u32)ff_mult(9, p) << 8) |
--		    ((u32)ff_mult(13, p) << 16) |
--		    ((u32)ff_mult(11, p) << 24);
+-KBUILD_CFLAGS += $(cflags-y)
+-CFLAGS_KERNEL += $(cflags-kernel-y)
+-KBUILD_AFLAGS += -m64
 -
--		aes_it_tab[0][i] = t;
--		aes_it_tab[1][i] = rol32(t, 8);
--		aes_it_tab[2][i] = rol32(t, 16);
--		aes_it_tab[3][i] = rol32(t, 24);
--	}
--}
+-head-y := arch/x86/kernel/head_64.o arch/x86/kernel/head64.o arch/x86/kernel/init_task.o
 -
--#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+-libs-y 					+= arch/x86/lib/
+-core-y					+= arch/x86/kernel/ \
+-					   arch/x86/mm/ \
+-					   arch/x86/crypto/ \
+-					   arch/x86/vdso/
+-core-$(CONFIG_IA32_EMULATION)		+= arch/x86/ia32/
+-drivers-$(CONFIG_PCI)			+= arch/x86/pci/
+-drivers-$(CONFIG_OPROFILE)		+= arch/x86/oprofile/
 -
--#define imix_col(y, x)			\
--	u    = star_x(x);		\
--	v    = star_x(u);		\
--	w    = star_x(v);		\
--	t    = w ^ (x);			\
--	(y)  = u ^ v ^ w;		\
--	(y) ^= ror32(u ^ t,  8) ^	\
--	       ror32(v ^ t, 16) ^	\
--	       ror32(t, 24)
+-boot := arch/x86/boot
 -
--/* initialise the key schedule from the user supplied key */
+-PHONY += bzImage bzlilo install archmrproper \
+-	 fdimage fdimage144 fdimage288 isoimage archclean
 -
--#define loop4(i)					\
--{							\
--	t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];	\
--	t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;	\
--	t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;	\
--	t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;	\
--	t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;	\
--}
+-#Default target when executing "make"
+-all: bzImage
 -
--#define loop6(i)					\
--{							\
--	t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];	\
--	t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;	\
--	t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;	\
--	t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;	\
--	t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;	\
--	t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;	\
--	t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;	\
--}
+-BOOTIMAGE                     := arch/x86/boot/bzImage
+-KBUILD_IMAGE                  := $(BOOTIMAGE)
 -
--#define loop8(i)					\
--{							\
--	t = ror32(t,  8); ; t = ls_box(t) ^ rco_tab[i];	\
--	t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;	\
--	t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;	\
--	t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;	\
--	t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;	\
--	t  = E_KEY[8 * i + 4] ^ ls_box(t);		\
--	E_KEY[8 * i + 12] = t;				\
--	t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;	\
--	t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;	\
--	t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;	\
--}
+-bzImage: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE)
+-	$(Q)mkdir -p $(objtree)/arch/x86_64/boot
+-	$(Q)ln -fsn ../../x86/boot/bzImage $(objtree)/arch/x86_64/boot/bzImage
 -
--static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
--		       unsigned int key_len)
--{
--	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
--	const __le32 *key = (const __le32 *)in_key;
--	u32 *flags = &tfm->crt_flags;
--	u32 i, j, t, u, v, w;
+-bzlilo: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zlilo
 -
--	if (key_len % 8) {
--		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
--		return -EINVAL;
--	}
+-bzdisk: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk
 -
--	ctx->key_length = key_len;
+-fdimage fdimage144 fdimage288 isoimage: vmlinux
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
 -
--	D_KEY[key_len + 24] = E_KEY[0] = le32_to_cpu(key[0]);
--	D_KEY[key_len + 25] = E_KEY[1] = le32_to_cpu(key[1]);
--	D_KEY[key_len + 26] = E_KEY[2] = le32_to_cpu(key[2]);
--	D_KEY[key_len + 27] = E_KEY[3] = le32_to_cpu(key[3]);
+-install: vdso_install
+-	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ 
 -
--	switch (key_len) {
--	case 16:
--		t = E_KEY[3];
--		for (i = 0; i < 10; ++i)
--			loop4(i);
--		break;
+-vdso_install:
+-ifeq ($(CONFIG_IA32_EMULATION),y)
+-	$(Q)$(MAKE) $(build)=arch/x86/ia32 $@
+-endif
+-	$(Q)$(MAKE) $(build)=arch/x86/vdso $@
 -
--	case 24:
--		E_KEY[4] = le32_to_cpu(key[4]);
--		t = E_KEY[5] = le32_to_cpu(key[5]);
--		for (i = 0; i < 8; ++i)
--			loop6 (i);
--		break;
+-archclean:
+-	$(Q)rm -rf $(objtree)/arch/x86_64/boot
+-	$(Q)$(MAKE) $(clean)=$(boot)
 -
--	case 32:
--		E_KEY[4] = le32_to_cpu(key[4]);
--		E_KEY[5] = le32_to_cpu(key[5]);
--		E_KEY[6] = le32_to_cpu(key[6]);
--		t = E_KEY[7] = le32_to_cpu(key[7]);
--		for (i = 0; i < 7; ++i)
--			loop8(i);
--		break;
--	}
+-define archhelp
+-  echo  '* bzImage	- Compressed kernel image (arch/x86/boot/bzImage)'
+-  echo  '  install	- Install kernel using'
+-  echo  '		   (your) ~/bin/installkernel or'
+-  echo  '		   (distribution) /sbin/installkernel or'
+-  echo  '		   install to $$(INSTALL_PATH) and run lilo'
+-  echo  '  bzdisk       - Create a boot floppy in /dev/fd0'
+-  echo  '  fdimage      - Create a boot floppy image'
+-  echo  '  isoimage     - Create a boot CD-ROM image'
+-endef
 -
--	D_KEY[0] = E_KEY[key_len + 24];
--	D_KEY[1] = E_KEY[key_len + 25];
--	D_KEY[2] = E_KEY[key_len + 26];
--	D_KEY[3] = E_KEY[key_len + 27];
+-CLEAN_FILES += arch/x86/boot/fdimage \
+-	       arch/x86/boot/image.iso \
+-	       arch/x86/boot/mtools.conf
 -
--	for (i = 4; i < key_len + 24; ++i) {
--		j = key_len + 24 - (i & ~3) + (i & 3);
--		imix_col(D_KEY[j], E_KEY[i]);
--	}
 -
--	return 0;
--}
+diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
+index 7a3116c..f88458e 100644
+--- a/arch/x86/boot/Makefile
++++ b/arch/x86/boot/Makefile
+@@ -26,11 +26,13 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
+ #RAMDISK := -DRAMDISK=512
+ 
+ targets		:= vmlinux.bin setup.bin setup.elf zImage bzImage
+-subdir- 	:= compressed
++subdir-		:= compressed
+ 
+-setup-y		+= a20.o apm.o cmdline.o copy.o cpu.o cpucheck.o edd.o
++setup-y		+= a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
+ setup-y		+= header.o main.o mca.o memory.o pm.o pmjump.o
+-setup-y		+= printf.o string.o tty.o video.o version.o voyager.o
++setup-y		+= printf.o string.o tty.o video.o version.o
++setup-$(CONFIG_X86_APM_BOOT) += apm.o
++setup-$(CONFIG_X86_VOYAGER) += voyager.o
+ 
+ # The link order of the video-*.o modules can matter.  In particular,
+ # video-vga.o *must* be listed first, followed by video-vesa.o.
+@@ -41,18 +43,23 @@ setup-y		+= video-vesa.o
+ setup-y		+= video-bios.o
+ 
+ targets		+= $(setup-y)
+-hostprogs-y	:= tools/build
++hostprogs-y	:= mkcpustr tools/build
+ 
+-HOSTCFLAGS_build.o := $(LINUXINCLUDE)
++HOST_EXTRACFLAGS += $(LINUXINCLUDE)
++
++$(obj)/cpu.o: $(obj)/cpustr.h
++
++quiet_cmd_cpustr = CPUSTR  $@
++      cmd_cpustr = $(obj)/mkcpustr > $@
++targets		+= cpustr.h
++$(obj)/cpustr.h: $(obj)/mkcpustr FORCE
++	$(call if_changed,cpustr)
+ 
+ # ---------------------------------------------------------------------------
+ 
+ # How to compile the 16-bit code.  Note we always compile for -march=i386,
+ # that way we can complain to the user if the CPU is insufficient.
+-cflags-$(CONFIG_X86_32) :=
+-cflags-$(CONFIG_X86_64) := -m32
+ KBUILD_CFLAGS	:= $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+-		   $(cflags-y) \
+ 		   -Wall -Wstrict-prototypes \
+ 		   -march=i386 -mregparm=3 \
+ 		   -include $(srctree)/$(src)/code16gcc.h \
+@@ -62,6 +69,7 @@ KBUILD_CFLAGS	:= $(LINUXINCLUDE) -g -Os -D_SETUP -D__KERNEL__ \
+ 			$(call cc-option, -fno-unit-at-a-time)) \
+ 		   $(call cc-option, -fno-stack-protector) \
+ 		   $(call cc-option, -mpreferred-stack-boundary=2)
++KBUILD_CFLAGS +=   $(call cc-option,-m32)
+ KBUILD_AFLAGS	:= $(KBUILD_CFLAGS) -D__ASSEMBLY__
+ 
+ $(obj)/zImage:  IMAGE_OFFSET := 0x1000
+@@ -80,6 +88,7 @@ $(obj)/zImage $(obj)/bzImage: $(obj)/setup.bin \
+ 	$(call if_changed,image)
+ 	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
+ 
++OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S
+ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
+ 	$(call if_changed,objcopy)
+ 
+@@ -90,7 +99,6 @@ $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE
+ 	$(call if_changed,ld)
+ 
+ OBJCOPYFLAGS_setup.bin	:= -O binary
 -
--asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
--asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+ $(obj)/setup.bin: $(obj)/setup.elf FORCE
+ 	$(call if_changed,objcopy)
+ 
+@@ -98,7 +106,7 @@ $(obj)/compressed/vmlinux: FORCE
+ 	$(Q)$(MAKE) $(build)=$(obj)/compressed IMAGE_OFFSET=$(IMAGE_OFFSET) $@
+ 
+ # Set this if you want to pass append arguments to the zdisk/fdimage/isoimage kernel
+-FDARGS = 
++FDARGS =
+ # Set this if you want an initrd included with the zdisk/fdimage/isoimage kernel
+ FDINITRD =
+ 
+diff --git a/arch/x86/boot/apm.c b/arch/x86/boot/apm.c
+index eab50c5..c117c7f 100644
+--- a/arch/x86/boot/apm.c
++++ b/arch/x86/boot/apm.c
+@@ -19,8 +19,6 @@
+ 
+ #include "boot.h"
+ 
+-#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE)
 -
--static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
--{
--	aes_enc_blk(tfm, dst, src);
--}
+ int query_apm_bios(void)
+ {
+ 	u16 ax, bx, cx, dx, di;
+@@ -95,4 +93,3 @@ int query_apm_bios(void)
+ 	return 0;
+ }
+ 
+-#endif
+diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
+index d2b5adf..7822a49 100644
+--- a/arch/x86/boot/boot.h
++++ b/arch/x86/boot/boot.h
+@@ -109,7 +109,7 @@ typedef unsigned int addr_t;
+ static inline u8 rdfs8(addr_t addr)
+ {
+ 	u8 v;
+-	asm volatile("movb %%fs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
++	asm volatile("movb %%fs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
+ 	return v;
+ }
+ static inline u16 rdfs16(addr_t addr)
+@@ -127,21 +127,21 @@ static inline u32 rdfs32(addr_t addr)
+ 
+ static inline void wrfs8(u8 v, addr_t addr)
+ {
+-	asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "r" (v));
++	asm volatile("movb %1,%%fs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
+ }
+ static inline void wrfs16(u16 v, addr_t addr)
+ {
+-	asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "r" (v));
++	asm volatile("movw %1,%%fs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
+ }
+ static inline void wrfs32(u32 v, addr_t addr)
+ {
+-	asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "r" (v));
++	asm volatile("movl %1,%%fs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
+ }
+ 
+ static inline u8 rdgs8(addr_t addr)
+ {
+ 	u8 v;
+-	asm volatile("movb %%gs:%1,%0" : "=r" (v) : "m" (*(u8 *)addr));
++	asm volatile("movb %%gs:%1,%0" : "=q" (v) : "m" (*(u8 *)addr));
+ 	return v;
+ }
+ static inline u16 rdgs16(addr_t addr)
+@@ -159,15 +159,15 @@ static inline u32 rdgs32(addr_t addr)
+ 
+ static inline void wrgs8(u8 v, addr_t addr)
+ {
+-	asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "r" (v));
++	asm volatile("movb %1,%%gs:%0" : "+m" (*(u8 *)addr) : "qi" (v));
+ }
+ static inline void wrgs16(u16 v, addr_t addr)
+ {
+-	asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "r" (v));
++	asm volatile("movw %1,%%gs:%0" : "+m" (*(u16 *)addr) : "ri" (v));
+ }
+ static inline void wrgs32(u32 v, addr_t addr)
+ {
+-	asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "r" (v));
++	asm volatile("movl %1,%%gs:%0" : "+m" (*(u32 *)addr) : "ri" (v));
+ }
+ 
+ /* Note: these only return true/false, not a signed return value! */
+@@ -241,6 +241,7 @@ int query_apm_bios(void);
+ 
+ /* cmdline.c */
+ int cmdline_find_option(const char *option, char *buffer, int bufsize);
++int cmdline_find_option_bool(const char *option);
+ 
+ /* cpu.c, cpucheck.c */
+ int check_cpu(int *cpu_level_ptr, int *req_level_ptr, u32 **err_flags_ptr);
+diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c
+index 34bb778..680408a 100644
+--- a/arch/x86/boot/cmdline.c
++++ b/arch/x86/boot/cmdline.c
+@@ -95,3 +95,68 @@ int cmdline_find_option(const char *option, char *buffer, int bufsize)
+ 
+ 	return len;
+ }
++
++/*
++ * Find a boolean option (like quiet,noapic,nosmp....)
++ *
++ * Returns the position of that option (starts counting with 1)
++ * or 0 on not found
++ */
++int cmdline_find_option_bool(const char *option)
++{
++	u32 cmdline_ptr = boot_params.hdr.cmd_line_ptr;
++	addr_t cptr;
++	char c;
++	int pos = 0, wstart = 0;
++	const char *opptr = NULL;
++	enum {
++		st_wordstart,	/* Start of word/after whitespace */
++		st_wordcmp,	/* Comparing this word */
++		st_wordskip,	/* Miscompare, skip */
++	} state = st_wordstart;
++
++	if (!cmdline_ptr || cmdline_ptr >= 0x100000)
++		return -1;	/* No command line, or inaccessible */
++
++	cptr = cmdline_ptr & 0xf;
++	set_fs(cmdline_ptr >> 4);
++
++	while (cptr < 0x10000) {
++		c = rdfs8(cptr++);
++		pos++;
++
++		switch (state) {
++		case st_wordstart:
++			if (!c)
++				return 0;
++			else if (myisspace(c))
++				break;
++
++			state = st_wordcmp;
++			opptr = option;
++			wstart = pos;
++			/* fall through */
++
++		case st_wordcmp:
++			if (!*opptr)
++				if (!c || myisspace(c))
++					return wstart;
++				else
++					state = st_wordskip;
++			else if (!c)
++				return 0;
++			else if (c != *opptr++)
++				state = st_wordskip;
++			break;
++
++		case st_wordskip:
++			if (!c)
++				return 0;
++			else if (myisspace(c))
++				state = st_wordstart;
++			break;
++		}
++	}
++
++	return 0;	/* Buffer overrun */
++}
+diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
+index 52c1db8..d2b9f3b 100644
+--- a/arch/x86/boot/compressed/Makefile
++++ b/arch/x86/boot/compressed/Makefile
+@@ -1,5 +1,64 @@
++#
++# linux/arch/x86/boot/compressed/Makefile
++#
++# create a compressed vmlinux image from the original vmlinux
++#
++
++targets := vmlinux vmlinux.bin vmlinux.bin.gz head_$(BITS).o misc.o piggy.o
++
++KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
++KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
++cflags-$(CONFIG_X86_64) := -mcmodel=small
++KBUILD_CFLAGS += $(cflags-y)
++KBUILD_CFLAGS += $(call cc-option,-ffreestanding)
++KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
++
++KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
++
++LDFLAGS := -m elf_$(UTS_MACHINE)
++LDFLAGS_vmlinux := -T
++
++$(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/piggy.o FORCE
++	$(call if_changed,ld)
++	@:
++
++OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S
++$(obj)/vmlinux.bin: vmlinux FORCE
++	$(call if_changed,objcopy)
++
++
+ ifeq ($(CONFIG_X86_32),y)
+-include ${srctree}/arch/x86/boot/compressed/Makefile_32
++targets += vmlinux.bin.all vmlinux.relocs
++hostprogs-y := relocs
++
++quiet_cmd_relocs = RELOCS  $@
++      cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
++$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
++	$(call if_changed,relocs)
++
++vmlinux.bin.all-y := $(obj)/vmlinux.bin
++vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
++quiet_cmd_relocbin = BUILD   $@
++      cmd_relocbin = cat $(filter-out FORCE,$^) > $@
++$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
++	$(call if_changed,relocbin)
++
++ifdef CONFIG_RELOCATABLE
++$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
++	$(call if_changed,gzip)
+ else
+-include ${srctree}/arch/x86/boot/compressed/Makefile_64
++$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
++	$(call if_changed,gzip)
+ endif
++LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
++
++else
++$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
++	$(call if_changed,gzip)
++
++LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
++endif
++
++
++$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE
++	$(call if_changed,ld)
+diff --git a/arch/x86/boot/compressed/Makefile_32 b/arch/x86/boot/compressed/Makefile_32
+deleted file mode 100644
+index e43ff7c..0000000
+--- a/arch/x86/boot/compressed/Makefile_32
++++ /dev/null
+@@ -1,50 +0,0 @@
+-#
+-# linux/arch/x86/boot/compressed/Makefile
+-#
+-# create a compressed vmlinux image from the original vmlinux
+-#
 -
--static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
--{
--	aes_dec_blk(tfm, dst, src);
--}
+-targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head_32.o misc_32.o piggy.o \
+-			vmlinux.bin.all vmlinux.relocs
+-EXTRA_AFLAGS	:= -traditional
 -
--static struct crypto_alg aes_alg = {
--	.cra_name		=	"aes",
--	.cra_driver_name	=	"aes-x86_64",
--	.cra_priority		=	200,
--	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
--	.cra_blocksize		=	AES_BLOCK_SIZE,
--	.cra_ctxsize		=	sizeof(struct aes_ctx),
--	.cra_module		=	THIS_MODULE,
--	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
--	.cra_u			=	{
--		.cipher = {
--			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
--			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
--			.cia_setkey	   	= 	aes_set_key,
--			.cia_encrypt	 	=	aes_encrypt,
--			.cia_decrypt	  	=	aes_decrypt
--		}
--	}
--};
+-LDFLAGS_vmlinux := -T
+-hostprogs-y	:= relocs
 -
--static int __init aes_init(void)
--{
--	gen_tabs();
--	return crypto_register_alg(&aes_alg);
--}
+-KBUILD_CFLAGS  := -m32 -D__KERNEL__ $(LINUX_INCLUDE) -O2 \
+-	   -fno-strict-aliasing -fPIC \
+-	   $(call cc-option,-ffreestanding) \
+-	   $(call cc-option,-fno-stack-protector)
+-LDFLAGS := -m elf_i386
 -
--static void __exit aes_fini(void)
--{
--	crypto_unregister_alg(&aes_alg);
--}
+-$(obj)/vmlinux: $(src)/vmlinux_32.lds $(obj)/head_32.o $(obj)/misc_32.o $(obj)/piggy.o FORCE
+-	$(call if_changed,ld)
+-	@:
 -
--module_init(aes_init);
--module_exit(aes_fini);
+-$(obj)/vmlinux.bin: vmlinux FORCE
+-	$(call if_changed,objcopy)
 -
--MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
--MODULE_LICENSE("GPL");
--MODULE_ALIAS("aes");
-diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
+-quiet_cmd_relocs = RELOCS  $@
+-      cmd_relocs = $(obj)/relocs $< > $@;$(obj)/relocs --abs-relocs $<
+-$(obj)/vmlinux.relocs: vmlinux $(obj)/relocs FORCE
+-	$(call if_changed,relocs)
+-
+-vmlinux.bin.all-y := $(obj)/vmlinux.bin
+-vmlinux.bin.all-$(CONFIG_RELOCATABLE) += $(obj)/vmlinux.relocs
+-quiet_cmd_relocbin = BUILD   $@
+-      cmd_relocbin = cat $(filter-out FORCE,$^) > $@
+-$(obj)/vmlinux.bin.all: $(vmlinux.bin.all-y) FORCE
+-	$(call if_changed,relocbin)
+-
+-ifdef CONFIG_RELOCATABLE
+-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin.all FORCE
+-	$(call if_changed,gzip)
+-else
+-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+-	$(call if_changed,gzip)
+-endif
+-
+-LDFLAGS_piggy.o := -r --format binary --oformat elf32-i386 -T
+-
+-$(obj)/piggy.o: $(src)/vmlinux_32.scr $(obj)/vmlinux.bin.gz FORCE
+-	$(call if_changed,ld)
+diff --git a/arch/x86/boot/compressed/Makefile_64 b/arch/x86/boot/compressed/Makefile_64
+deleted file mode 100644
+index 7801e8d..0000000
+--- a/arch/x86/boot/compressed/Makefile_64
++++ /dev/null
+@@ -1,30 +0,0 @@
+-#
+-# linux/arch/x86/boot/compressed/Makefile
+-#
+-# create a compressed vmlinux image from the original vmlinux
+-#
+-
+-targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head_64.o misc_64.o piggy.o
+-
+-KBUILD_CFLAGS := -m64 -D__KERNEL__ $(LINUXINCLUDE) -O2  \
+-	  -fno-strict-aliasing -fPIC -mcmodel=small \
+-	   $(call cc-option, -ffreestanding) \
+-	   $(call cc-option, -fno-stack-protector)
+-KBUILD_AFLAGS  := $(KBUILD_CFLAGS) -D__ASSEMBLY__
+-LDFLAGS := -m elf_x86_64
+-
+-LDFLAGS_vmlinux := -T
+-$(obj)/vmlinux: $(src)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o $(obj)/piggy.o FORCE
+-	$(call if_changed,ld)
+-	@:
+-
+-$(obj)/vmlinux.bin: vmlinux FORCE
+-	$(call if_changed,objcopy)
+-
+-$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
+-	$(call if_changed,gzip)
+-
+-LDFLAGS_piggy.o := -r --format binary --oformat elf64-x86-64 -T
+-
+-$(obj)/piggy.o: $(obj)/vmlinux_64.scr $(obj)/vmlinux.bin.gz FORCE
+-	$(call if_changed,ld)
+diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
+index 1ccb38a..e8657b9 100644
+--- a/arch/x86/boot/compressed/head_64.S
++++ b/arch/x86/boot/compressed/head_64.S
+@@ -80,8 +80,8 @@ startup_32:
+ 
+ #ifdef CONFIG_RELOCATABLE
+ 	movl	%ebp, %ebx
+-	addl	$(LARGE_PAGE_SIZE -1), %ebx
+-	andl	$LARGE_PAGE_MASK, %ebx
++	addl	$(PMD_PAGE_SIZE -1), %ebx
++	andl	$PMD_PAGE_MASK, %ebx
+ #else
+ 	movl	$CONFIG_PHYSICAL_START, %ebx
+ #endif
+@@ -220,8 +220,8 @@ ENTRY(startup_64)
+ 	/* Start with the delta to where the kernel will run at. */
+ #ifdef CONFIG_RELOCATABLE
+ 	leaq	startup_32(%rip) /* - $startup_32 */, %rbp
+-	addq	$(LARGE_PAGE_SIZE - 1), %rbp
+-	andq	$LARGE_PAGE_MASK, %rbp
++	addq	$(PMD_PAGE_SIZE - 1), %rbp
++	andq	$PMD_PAGE_MASK, %rbp
+ 	movq	%rbp, %rbx
+ #else
+ 	movq	$CONFIG_PHYSICAL_START, %rbp
+diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
 new file mode 100644
-index 0000000..71f4578
+index 0000000..8182e32
 --- /dev/null
-+++ b/arch/x86/crypto/aes_glue.c
-@@ -0,0 +1,57 @@
++++ b/arch/x86/boot/compressed/misc.c
+@@ -0,0 +1,413 @@
 +/*
-+ * Glue Code for the asm optimized version of the AES Cipher Algorithm
++ * misc.c
++ *
++ * This is a collection of several routines from gzip-1.0.3
++ * adapted for Linux.
 + *
++ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
++ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
++ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
 + */
 +
-+#include <crypto/aes.h>
++/*
++ * we have to be careful, because no indirections are allowed here, and
++ * paravirt_ops is a kind of one. As it will only run in baremetal anyway,
++ * we just keep it from happening
++ */
++#undef CONFIG_PARAVIRT
++#ifdef CONFIG_X86_64
++#define _LINUX_STRING_H_ 1
++#define __LINUX_BITMAP_H 1
++#endif
 +
-+asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
-+asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
++#include <linux/linkage.h>
++#include <linux/screen_info.h>
++#include <asm/io.h>
++#include <asm/page.h>
++#include <asm/boot.h>
 +
-+static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++/* WARNING!!
++ * This code is compiled with -fPIC and it is relocated dynamically
++ * at run time, but no relocation processing is performed.
++ * This means that it is not safe to place pointers in static structures.
++ */
++
++/*
++ * Getting to provable safe in place decompression is hard.
++ * Worst case behaviours need to be analyzed.
++ * Background information:
++ *
++ * The file layout is:
++ *    magic[2]
++ *    method[1]
++ *    flags[1]
++ *    timestamp[4]
++ *    extraflags[1]
++ *    os[1]
++ *    compressed data blocks[N]
++ *    crc[4] orig_len[4]
++ *
++ * resulting in 18 bytes of non compressed data overhead.
++ *
++ * Files divided into blocks
++ * 1 bit (last block flag)
++ * 2 bits (block type)
++ *
++ * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
++ * The smallest block type encoding is always used.
++ *
++ * stored:
++ *    32 bits length in bytes.
++ *
++ * fixed:
++ *    magic fixed tree.
++ *    symbols.
++ *
++ * dynamic:
++ *    dynamic tree encoding.
++ *    symbols.
++ *
++ *
++ * The buffer for decompression in place is the length of the
++ * uncompressed data, plus a small amount extra to keep the algorithm safe.
++ * The compressed data is placed at the end of the buffer.  The output
++ * pointer is placed at the start of the buffer and the input pointer
++ * is placed where the compressed data starts.  Problems will occur
++ * when the output pointer overruns the input pointer.
++ *
++ * The output pointer can only overrun the input pointer if the input
++ * pointer is moving faster than the output pointer.  A condition only
++ * triggered by data whose compressed form is larger than the uncompressed
++ * form.
++ *
++ * The worst case at the block level is a growth of the compressed data
++ * of 5 bytes per 32767 bytes.
++ *
++ * The worst case internal to a compressed block is very hard to figure.
++ * The worst case can at least be boundined by having one bit that represents
++ * 32764 bytes and then all of the rest of the bytes representing the very
++ * very last byte.
++ *
++ * All of which is enough to compute an amount of extra data that is required
++ * to be safe.  To avoid problems at the block level allocating 5 extra bytes
++ * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
++ * adding an extra 32767 bytes (the worst case uncompressed block size) is
++ * sufficient, to ensure that in the worst case the decompressed data for
++ * block will stop the byte before the compressed data for a block begins.
++ * To avoid problems with the compressed data's meta information an extra 18
++ * bytes are needed.  Leading to the formula:
++ *
++ * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
++ *
++ * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
++ * Adding 32768 instead of 32767 just makes for round numbers.
++ * Adding the decompressor_size is necessary as it musht live after all
++ * of the data as well.  Last I measured the decompressor is about 14K.
++ * 10K of actual data and 4K of bss.
++ *
++ */
++
++/*
++ * gzip declarations
++ */
++
++#define OF(args)  args
++#define STATIC static
++
++#undef memset
++#undef memcpy
++#define memzero(s, n)     memset ((s), 0, (n))
++
++typedef unsigned char  uch;
++typedef unsigned short ush;
++typedef unsigned long  ulg;
++
++#define WSIZE 0x80000000	/* Window size must be at least 32k,
++				 * and a power of two
++				 * We don't actually have a window just
++				 * a huge output buffer so I report
++				 * a 2G windows size, as that should
++				 * always be larger than our output buffer.
++				 */
++
++static uch *inbuf;	/* input buffer */
++static uch *window;	/* Sliding window buffer, (and final output buffer) */
++
++static unsigned insize;  /* valid bytes in inbuf */
++static unsigned inptr;   /* index of next byte to be processed in inbuf */
++static unsigned outcnt;  /* bytes in output buffer */
++
++/* gzip flag byte */
++#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
++#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
++#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
++#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
++#define COMMENT      0x10 /* bit 4 set: file comment present */
++#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
++#define RESERVED     0xC0 /* bit 6,7:   reserved */
++
++#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
++		
++/* Diagnostic functions */
++#ifdef DEBUG
++#  define Assert(cond,msg) {if(!(cond)) error(msg);}
++#  define Trace(x) fprintf x
++#  define Tracev(x) {if (verbose) fprintf x ;}
++#  define Tracevv(x) {if (verbose>1) fprintf x ;}
++#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
++#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
++#else
++#  define Assert(cond,msg)
++#  define Trace(x)
++#  define Tracev(x)
++#  define Tracevv(x)
++#  define Tracec(c,x)
++#  define Tracecv(c,x)
++#endif
++
++static int  fill_inbuf(void);
++static void flush_window(void);
++static void error(char *m);
++static void gzip_mark(void **);
++static void gzip_release(void **);
++  
++/*
++ * This is set up by the setup-routine at boot-time
++ */
++static unsigned char *real_mode; /* Pointer to real-mode data */
++
++#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
++#ifndef STANDARD_MEMORY_BIOS_CALL
++#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
++#endif
++#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
++
++extern unsigned char input_data[];
++extern int input_len;
++
++static long bytes_out = 0;
++
++static void *malloc(int size);
++static void free(void *where);
++
++static void *memset(void *s, int c, unsigned n);
++static void *memcpy(void *dest, const void *src, unsigned n);
++
++static void putstr(const char *);
++
++#ifdef CONFIG_X86_64
++#define memptr long
++#else
++#define memptr unsigned
++#endif
++
++static memptr free_mem_ptr;
++static memptr free_mem_end_ptr;
++
++#ifdef CONFIG_X86_64
++#define HEAP_SIZE             0x7000
++#else
++#define HEAP_SIZE             0x4000
++#endif
++
++static char *vidmem = (char *)0xb8000;
++static int vidport;
++static int lines, cols;
++
++#ifdef CONFIG_X86_NUMAQ
++void *xquad_portio;
++#endif
++
++#include "../../../../lib/inflate.c"
++
++static void *malloc(int size)
 +{
-+	aes_enc_blk(tfm, dst, src);
++	void *p;
++
++	if (size <0) error("Malloc error");
++	if (free_mem_ptr <= 0) error("Memory error");
++
++	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
++
++	p = (void *)free_mem_ptr;
++	free_mem_ptr += size;
++
++	if (free_mem_ptr >= free_mem_end_ptr)
++		error("Out of memory");
++
++	return p;
 +}
 +
-+static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++static void free(void *where)
++{	/* Don't care */
++}
++
++static void gzip_mark(void **ptr)
 +{
-+	aes_dec_blk(tfm, dst, src);
++	*ptr = (void *) free_mem_ptr;
 +}
 +
-+static struct crypto_alg aes_alg = {
-+	.cra_name		= "aes",
-+	.cra_driver_name	= "aes-asm",
-+	.cra_priority		= 200,
-+	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
-+	.cra_blocksize		= AES_BLOCK_SIZE,
-+	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
-+	.cra_module		= THIS_MODULE,
-+	.cra_list		= LIST_HEAD_INIT(aes_alg.cra_list),
-+	.cra_u	= {
-+		.cipher	= {
-+			.cia_min_keysize	= AES_MIN_KEY_SIZE,
-+			.cia_max_keysize	= AES_MAX_KEY_SIZE,
-+			.cia_setkey		= crypto_aes_set_key,
-+			.cia_encrypt		= aes_encrypt,
-+			.cia_decrypt		= aes_decrypt
++static void gzip_release(void **ptr)
++{
++	free_mem_ptr = (memptr) *ptr;
++}
++ 
++static void scroll(void)
++{
++	int i;
++
++	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
++	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
++		vidmem[i] = ' ';
++}
++
++static void putstr(const char *s)
++{
++	int x,y,pos;
++	char c;
++
++#ifdef CONFIG_X86_32
++	if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
++		return;
++#endif
++
++	x = RM_SCREEN_INFO.orig_x;
++	y = RM_SCREEN_INFO.orig_y;
++
++	while ( ( c = *s++ ) != '\0' ) {
++		if ( c == '\n' ) {
++			x = 0;
++			if ( ++y >= lines ) {
++				scroll();
++				y--;
++			}
++		} else {
++			vidmem [(x + cols * y) * 2] = c;
++			if ( ++x >= cols ) {
++				x = 0;
++				if ( ++y >= lines ) {
++					scroll();
++					y--;
++				}
++			}
 +		}
 +	}
-+};
 +
-+static int __init aes_init(void)
-+{
-+	return crypto_register_alg(&aes_alg);
++	RM_SCREEN_INFO.orig_x = x;
++	RM_SCREEN_INFO.orig_y = y;
++
++	pos = (x + cols * y) * 2;	/* Update cursor position */
++	outb(14, vidport);
++	outb(0xff & (pos >> 9), vidport+1);
++	outb(15, vidport);
++	outb(0xff & (pos >> 1), vidport+1);
 +}
 +
-+static void __exit aes_fini(void)
++static void* memset(void* s, int c, unsigned n)
 +{
-+	crypto_unregister_alg(&aes_alg);
++	int i;
++	char *ss = s;
++
++	for (i=0;i<n;i++) ss[i] = c;
++	return s;
 +}
 +
-+module_init(aes_init);
-+module_exit(aes_fini);
++static void* memcpy(void* dest, const void* src, unsigned n)
++{
++	int i;
++	const char *s = src;
++	char *d = dest;
 +
-+MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized");
-+MODULE_LICENSE("GPL");
-+MODULE_ALIAS("aes");
-+MODULE_ALIAS("aes-asm");
-diff --git a/arch/x86/crypto/salsa20-i586-asm_32.S b/arch/x86/crypto/salsa20-i586-asm_32.S
-new file mode 100644
-index 0000000..72eb306
---- /dev/null
++	for (i=0;i<n;i++) d[i] = s[i];
++	return dest;
++}
++
++/* ===========================================================================
++ * Fill the input buffer. This is called only when the buffer is empty
++ * and at least one byte is really needed.
++ */
++static int fill_inbuf(void)
++{
++	error("ran out of input data");
++	return 0;
++}
++
++/* ===========================================================================
++ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
++ * (Used for the decompressed data only.)
++ */
++static void flush_window(void)
++{
++	/* With my window equal to my output buffer
++	 * I only need to compute the crc here.
++	 */
++	ulg c = crc;         /* temporary variable */
++	unsigned n;
++	uch *in, ch;
++
++	in = window;
++	for (n = 0; n < outcnt; n++) {
++		ch = *in++;
++		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
++	}
++	crc = c;
++	bytes_out += (ulg)outcnt;
++	outcnt = 0;
++}
++
++static void error(char *x)
++{
++	putstr("\n\n");
++	putstr(x);
++	putstr("\n\n -- System halted");
++
++	while (1)
++		asm("hlt");
++}
++
++asmlinkage void decompress_kernel(void *rmode, memptr heap,
++				  uch *input_data, unsigned long input_len,
++				  uch *output)
++{
++	real_mode = rmode;
++
++	if (RM_SCREEN_INFO.orig_video_mode == 7) {
++		vidmem = (char *) 0xb0000;
++		vidport = 0x3b4;
++	} else {
++		vidmem = (char *) 0xb8000;
++		vidport = 0x3d4;
++	}
++
++	lines = RM_SCREEN_INFO.orig_video_lines;
++	cols = RM_SCREEN_INFO.orig_video_cols;
++
++	window = output;		/* Output buffer (Normally at 1M) */
++	free_mem_ptr     = heap;	/* Heap */
++	free_mem_end_ptr = heap + HEAP_SIZE;
++	inbuf  = input_data;		/* Input buffer */
++	insize = input_len;
++	inptr  = 0;
++
++#ifdef CONFIG_X86_64
++	if ((ulg)output & (__KERNEL_ALIGN - 1))
++		error("Destination address not 2M aligned");
++	if ((ulg)output >= 0xffffffffffUL)
++		error("Destination address too large");
++#else
++	if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
++		error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
++	if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
++		error("Destination address too large");
++#ifndef CONFIG_RELOCATABLE
++	if ((u32)output != LOAD_PHYSICAL_ADDR)
++		error("Wrong destination address");
++#endif
++#endif
++
++	makecrc();
++	putstr("\nDecompressing Linux... ");
++	gunzip();
++	putstr("done.\nBooting the kernel.\n");
++	return;
++}
+diff --git a/arch/x86/boot/compressed/misc_32.c b/arch/x86/boot/compressed/misc_32.c
+deleted file mode 100644
+index b74d60d..0000000
+--- a/arch/x86/boot/compressed/misc_32.c
++++ /dev/null
+@@ -1,382 +0,0 @@
+-/*
+- * misc.c
+- * 
+- * This is a collection of several routines from gzip-1.0.3 
+- * adapted for Linux.
+- *
+- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+- * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+- */
+-
+-#undef CONFIG_PARAVIRT
+-#include <linux/linkage.h>
+-#include <linux/vmalloc.h>
+-#include <linux/screen_info.h>
+-#include <asm/io.h>
+-#include <asm/page.h>
+-#include <asm/boot.h>
+-
+-/* WARNING!!
+- * This code is compiled with -fPIC and it is relocated dynamically
+- * at run time, but no relocation processing is performed.
+- * This means that it is not safe to place pointers in static structures.
+- */
+-
+-/*
+- * Getting to provable safe in place decompression is hard.
+- * Worst case behaviours need to be analyzed.
+- * Background information:
+- *
+- * The file layout is:
+- *    magic[2]
+- *    method[1]
+- *    flags[1]
+- *    timestamp[4]
+- *    extraflags[1]
+- *    os[1]
+- *    compressed data blocks[N]
+- *    crc[4] orig_len[4]
+- *
+- * resulting in 18 bytes of non compressed data overhead.
+- *
+- * Files divided into blocks
+- * 1 bit (last block flag)
+- * 2 bits (block type)
+- *
+- * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+- * The smallest block type encoding is always used.
+- *
+- * stored:
+- *    32 bits length in bytes.
+- *
+- * fixed:
+- *    magic fixed tree.
+- *    symbols.
+- *
+- * dynamic:
+- *    dynamic tree encoding.
+- *    symbols.
+- *
+- *
+- * The buffer for decompression in place is the length of the
+- * uncompressed data, plus a small amount extra to keep the algorithm safe.
+- * The compressed data is placed at the end of the buffer.  The output
+- * pointer is placed at the start of the buffer and the input pointer
+- * is placed where the compressed data starts.  Problems will occur
+- * when the output pointer overruns the input pointer.
+- *
+- * The output pointer can only overrun the input pointer if the input
+- * pointer is moving faster than the output pointer.  A condition only
+- * triggered by data whose compressed form is larger than the uncompressed
+- * form.
+- *
+- * The worst case at the block level is a growth of the compressed data
+- * of 5 bytes per 32767 bytes.
+- *
+- * The worst case internal to a compressed block is very hard to figure.
+- * The worst case can at least be boundined by having one bit that represents
+- * 32764 bytes and then all of the rest of the bytes representing the very
+- * very last byte.
+- *
+- * All of which is enough to compute an amount of extra data that is required
+- * to be safe.  To avoid problems at the block level allocating 5 extra bytes
+- * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
+- * adding an extra 32767 bytes (the worst case uncompressed block size) is
+- * sufficient, to ensure that in the worst case the decompressed data for
+- * block will stop the byte before the compressed data for a block begins.
+- * To avoid problems with the compressed data's meta information an extra 18
+- * bytes are needed.  Leading to the formula:
+- *
+- * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
+- *
+- * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
+- * Adding 32768 instead of 32767 just makes for round numbers.
+- * Adding the decompressor_size is necessary as it musht live after all
+- * of the data as well.  Last I measured the decompressor is about 14K.
+- * 10K of actual data and 4K of bss.
+- *
+- */
+-
+-/*
+- * gzip declarations
+- */
+-
+-#define OF(args)  args
+-#define STATIC static
+-
+-#undef memset
+-#undef memcpy
+-#define memzero(s, n)     memset ((s), 0, (n))
+-
+-typedef unsigned char  uch;
+-typedef unsigned short ush;
+-typedef unsigned long  ulg;
+-
+-#define WSIZE 0x80000000	/* Window size must be at least 32k,
+-				 * and a power of two
+-				 * We don't actually have a window just
+-				 * a huge output buffer so I report
+-				 * a 2G windows size, as that should
+-				 * always be larger than our output buffer.
+-				 */
+-
+-static uch *inbuf;	/* input buffer */
+-static uch *window;	/* Sliding window buffer, (and final output buffer) */
+-
+-static unsigned insize;  /* valid bytes in inbuf */
+-static unsigned inptr;   /* index of next byte to be processed in inbuf */
+-static unsigned outcnt;  /* bytes in output buffer */
+-
+-/* gzip flag byte */
+-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+-#define COMMENT      0x10 /* bit 4 set: file comment present */
+-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+-#define RESERVED     0xC0 /* bit 6,7:   reserved */
+-
+-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+-		
+-/* Diagnostic functions */
+-#ifdef DEBUG
+-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+-#  define Trace(x) fprintf x
+-#  define Tracev(x) {if (verbose) fprintf x ;}
+-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+-#else
+-#  define Assert(cond,msg)
+-#  define Trace(x)
+-#  define Tracev(x)
+-#  define Tracevv(x)
+-#  define Tracec(c,x)
+-#  define Tracecv(c,x)
+-#endif
+-
+-static int  fill_inbuf(void);
+-static void flush_window(void);
+-static void error(char *m);
+-static void gzip_mark(void **);
+-static void gzip_release(void **);
+-  
+-/*
+- * This is set up by the setup-routine at boot-time
+- */
+-static unsigned char *real_mode; /* Pointer to real-mode data */
+-
+-#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
+-#ifndef STANDARD_MEMORY_BIOS_CALL
+-#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
+-#endif
+-#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+-
+-extern unsigned char input_data[];
+-extern int input_len;
+-
+-static long bytes_out = 0;
+-
+-static void *malloc(int size);
+-static void free(void *where);
+-
+-static void *memset(void *s, int c, unsigned n);
+-static void *memcpy(void *dest, const void *src, unsigned n);
+-
+-static void putstr(const char *);
+-
+-static unsigned long free_mem_ptr;
+-static unsigned long free_mem_end_ptr;
+-
+-#define HEAP_SIZE             0x4000
+-
+-static char *vidmem = (char *)0xb8000;
+-static int vidport;
+-static int lines, cols;
+-
+-#ifdef CONFIG_X86_NUMAQ
+-void *xquad_portio;
+-#endif
+-
+-#include "../../../../lib/inflate.c"
+-
+-static void *malloc(int size)
+-{
+-	void *p;
+-
+-	if (size <0) error("Malloc error");
+-	if (free_mem_ptr <= 0) error("Memory error");
+-
+-	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+-
+-	p = (void *)free_mem_ptr;
+-	free_mem_ptr += size;
+-
+-	if (free_mem_ptr >= free_mem_end_ptr)
+-		error("Out of memory");
+-
+-	return p;
+-}
+-
+-static void free(void *where)
+-{	/* Don't care */
+-}
+-
+-static void gzip_mark(void **ptr)
+-{
+-	*ptr = (void *) free_mem_ptr;
+-}
+-
+-static void gzip_release(void **ptr)
+-{
+-	free_mem_ptr = (unsigned long) *ptr;
+-}
+- 
+-static void scroll(void)
+-{
+-	int i;
+-
+-	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+-	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+-		vidmem[i] = ' ';
+-}
+-
+-static void putstr(const char *s)
+-{
+-	int x,y,pos;
+-	char c;
+-
+-	if (RM_SCREEN_INFO.orig_video_mode == 0 && lines == 0 && cols == 0)
+-		return;
+-
+-	x = RM_SCREEN_INFO.orig_x;
+-	y = RM_SCREEN_INFO.orig_y;
+-
+-	while ( ( c = *s++ ) != '\0' ) {
+-		if ( c == '\n' ) {
+-			x = 0;
+-			if ( ++y >= lines ) {
+-				scroll();
+-				y--;
+-			}
+-		} else {
+-			vidmem [ ( x + cols * y ) * 2 ] = c;
+-			if ( ++x >= cols ) {
+-				x = 0;
+-				if ( ++y >= lines ) {
+-					scroll();
+-					y--;
+-				}
+-			}
+-		}
+-	}
+-
+-	RM_SCREEN_INFO.orig_x = x;
+-	RM_SCREEN_INFO.orig_y = y;
+-
+-	pos = (x + cols * y) * 2;	/* Update cursor position */
+-	outb_p(14, vidport);
+-	outb_p(0xff & (pos >> 9), vidport+1);
+-	outb_p(15, vidport);
+-	outb_p(0xff & (pos >> 1), vidport+1);
+-}
+-
+-static void* memset(void* s, int c, unsigned n)
+-{
+-	int i;
+-	char *ss = (char*)s;
+-
+-	for (i=0;i<n;i++) ss[i] = c;
+-	return s;
+-}
+-
+-static void* memcpy(void* dest, const void* src, unsigned n)
+-{
+-	int i;
+-	char *d = (char *)dest, *s = (char *)src;
+-
+-	for (i=0;i<n;i++) d[i] = s[i];
+-	return dest;
+-}
+-
+-/* ===========================================================================
+- * Fill the input buffer. This is called only when the buffer is empty
+- * and at least one byte is really needed.
+- */
+-static int fill_inbuf(void)
+-{
+-	error("ran out of input data");
+-	return 0;
+-}
+-
+-/* ===========================================================================
+- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+- * (Used for the decompressed data only.)
+- */
+-static void flush_window(void)
+-{
+-	/* With my window equal to my output buffer
+-	 * I only need to compute the crc here.
+-	 */
+-	ulg c = crc;         /* temporary variable */
+-	unsigned n;
+-	uch *in, ch;
+-
+-	in = window;
+-	for (n = 0; n < outcnt; n++) {
+-		ch = *in++;
+-		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+-	}
+-	crc = c;
+-	bytes_out += (ulg)outcnt;
+-	outcnt = 0;
+-}
+-
+-static void error(char *x)
+-{
+-	putstr("\n\n");
+-	putstr(x);
+-	putstr("\n\n -- System halted");
+-
+-	while(1);	/* Halt */
+-}
+-
+-asmlinkage void decompress_kernel(void *rmode, unsigned long end,
+-			uch *input_data, unsigned long input_len, uch *output)
+-{
+-	real_mode = rmode;
+-
+-	if (RM_SCREEN_INFO.orig_video_mode == 7) {
+-		vidmem = (char *) 0xb0000;
+-		vidport = 0x3b4;
+-	} else {
+-		vidmem = (char *) 0xb8000;
+-		vidport = 0x3d4;
+-	}
+-
+-	lines = RM_SCREEN_INFO.orig_video_lines;
+-	cols = RM_SCREEN_INFO.orig_video_cols;
+-
+-	window = output;  	/* Output buffer (Normally at 1M) */
+-	free_mem_ptr     = end;	/* Heap  */
+-	free_mem_end_ptr = end + HEAP_SIZE;
+-	inbuf  = input_data;	/* Input buffer */
+-	insize = input_len;
+-	inptr  = 0;
+-
+-	if ((u32)output & (CONFIG_PHYSICAL_ALIGN -1))
+-		error("Destination address not CONFIG_PHYSICAL_ALIGN aligned");
+-	if (end > ((-__PAGE_OFFSET-(512 <<20)-1) & 0x7fffffff))
+-		error("Destination address too large");
+-#ifndef CONFIG_RELOCATABLE
+-	if ((u32)output != LOAD_PHYSICAL_ADDR)
+-		error("Wrong destination address");
+-#endif
+-
+-	makecrc();
+-	putstr("Uncompressing Linux... ");
+-	gunzip();
+-	putstr("Ok, booting the kernel.\n");
+-	return;
+-}
+diff --git a/arch/x86/boot/compressed/misc_64.c b/arch/x86/boot/compressed/misc_64.c
+deleted file mode 100644
+index 6ea015a..0000000
+--- a/arch/x86/boot/compressed/misc_64.c
++++ /dev/null
+@@ -1,371 +0,0 @@
+-/*
+- * misc.c
+- * 
+- * This is a collection of several routines from gzip-1.0.3 
+- * adapted for Linux.
+- *
+- * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+- * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+- */
+-
+-#define _LINUX_STRING_H_ 1
+-#define __LINUX_BITMAP_H 1
+-
+-#include <linux/linkage.h>
+-#include <linux/screen_info.h>
+-#include <asm/io.h>
+-#include <asm/page.h>
+-
+-/* WARNING!!
+- * This code is compiled with -fPIC and it is relocated dynamically
+- * at run time, but no relocation processing is performed.
+- * This means that it is not safe to place pointers in static structures.
+- */
+-
+-/*
+- * Getting to provable safe in place decompression is hard.
+- * Worst case behaviours need to be analyzed.
+- * Background information:
+- *
+- * The file layout is:
+- *    magic[2]
+- *    method[1]
+- *    flags[1]
+- *    timestamp[4]
+- *    extraflags[1]
+- *    os[1]
+- *    compressed data blocks[N]
+- *    crc[4] orig_len[4]
+- *
+- * resulting in 18 bytes of non compressed data overhead.
+- *
+- * Files divided into blocks
+- * 1 bit (last block flag)
+- * 2 bits (block type)
+- *
+- * 1 block occurs every 32K -1 bytes or when there 50% compression has been achieved.
+- * The smallest block type encoding is always used.
+- *
+- * stored:
+- *    32 bits length in bytes.
+- *
+- * fixed:
+- *    magic fixed tree.
+- *    symbols.
+- *
+- * dynamic:
+- *    dynamic tree encoding.
+- *    symbols.
+- *
+- *
+- * The buffer for decompression in place is the length of the
+- * uncompressed data, plus a small amount extra to keep the algorithm safe.
+- * The compressed data is placed at the end of the buffer.  The output
+- * pointer is placed at the start of the buffer and the input pointer
+- * is placed where the compressed data starts.  Problems will occur
+- * when the output pointer overruns the input pointer.
+- *
+- * The output pointer can only overrun the input pointer if the input
+- * pointer is moving faster than the output pointer.  A condition only
+- * triggered by data whose compressed form is larger than the uncompressed
+- * form.
+- *
+- * The worst case at the block level is a growth of the compressed data
+- * of 5 bytes per 32767 bytes.
+- *
+- * The worst case internal to a compressed block is very hard to figure.
+- * The worst case can at least be boundined by having one bit that represents
+- * 32764 bytes and then all of the rest of the bytes representing the very
+- * very last byte.
+- *
+- * All of which is enough to compute an amount of extra data that is required
+- * to be safe.  To avoid problems at the block level allocating 5 extra bytes
+- * per 32767 bytes of data is sufficient.  To avoind problems internal to a block
+- * adding an extra 32767 bytes (the worst case uncompressed block size) is
+- * sufficient, to ensure that in the worst case the decompressed data for
+- * block will stop the byte before the compressed data for a block begins.
+- * To avoid problems with the compressed data's meta information an extra 18
+- * bytes are needed.  Leading to the formula:
+- *
+- * extra_bytes = (uncompressed_size >> 12) + 32768 + 18 + decompressor_size.
+- *
+- * Adding 8 bytes per 32K is a bit excessive but much easier to calculate.
+- * Adding 32768 instead of 32767 just makes for round numbers.
+- * Adding the decompressor_size is necessary as it musht live after all
+- * of the data as well.  Last I measured the decompressor is about 14K.
+- * 10K of actual data and 4K of bss.
+- *
+- */
+-
+-/*
+- * gzip declarations
+- */
+-
+-#define OF(args)  args
+-#define STATIC static
+-
+-#undef memset
+-#undef memcpy
+-#define memzero(s, n)     memset ((s), 0, (n))
+-
+-typedef unsigned char  uch;
+-typedef unsigned short ush;
+-typedef unsigned long  ulg;
+-
+-#define WSIZE 0x80000000	/* Window size must be at least 32k,
+-				 * and a power of two
+-				 * We don't actually have a window just
+-				 * a huge output buffer so I report
+-				 * a 2G windows size, as that should
+-				 * always be larger than our output buffer.
+-				 */
+-
+-static uch *inbuf;	/* input buffer */
+-static uch *window;	/* Sliding window buffer, (and final output buffer) */
+-
+-static unsigned insize;  /* valid bytes in inbuf */
+-static unsigned inptr;   /* index of next byte to be processed in inbuf */
+-static unsigned outcnt;  /* bytes in output buffer */
+-
+-/* gzip flag byte */
+-#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+-#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+-#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+-#define COMMENT      0x10 /* bit 4 set: file comment present */
+-#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+-#define RESERVED     0xC0 /* bit 6,7:   reserved */
+-
+-#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+-		
+-/* Diagnostic functions */
+-#ifdef DEBUG
+-#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+-#  define Trace(x) fprintf x
+-#  define Tracev(x) {if (verbose) fprintf x ;}
+-#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+-#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+-#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+-#else
+-#  define Assert(cond,msg)
+-#  define Trace(x)
+-#  define Tracev(x)
+-#  define Tracevv(x)
+-#  define Tracec(c,x)
+-#  define Tracecv(c,x)
+-#endif
+-
+-static int  fill_inbuf(void);
+-static void flush_window(void);
+-static void error(char *m);
+-static void gzip_mark(void **);
+-static void gzip_release(void **);
+-  
+-/*
+- * This is set up by the setup-routine at boot-time
+- */
+-static unsigned char *real_mode; /* Pointer to real-mode data */
+-
+-#define RM_EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
+-#ifndef STANDARD_MEMORY_BIOS_CALL
+-#define RM_ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
+-#endif
+-#define RM_SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+-
+-extern unsigned char input_data[];
+-extern int input_len;
+-
+-static long bytes_out = 0;
+-
+-static void *malloc(int size);
+-static void free(void *where);
+-
+-static void *memset(void *s, int c, unsigned n);
+-static void *memcpy(void *dest, const void *src, unsigned n);
+-
+-static void putstr(const char *);
+-
+-static long free_mem_ptr;
+-static long free_mem_end_ptr;
+-
+-#define HEAP_SIZE             0x7000
+-
+-static char *vidmem = (char *)0xb8000;
+-static int vidport;
+-static int lines, cols;
+-
+-#include "../../../../lib/inflate.c"
+-
+-static void *malloc(int size)
+-{
+-	void *p;
+-
+-	if (size <0) error("Malloc error");
+-	if (free_mem_ptr <= 0) error("Memory error");
+-
+-	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+-
+-	p = (void *)free_mem_ptr;
+-	free_mem_ptr += size;
+-
+-	if (free_mem_ptr >= free_mem_end_ptr)
+-		error("Out of memory");
+-
+-	return p;
+-}
+-
+-static void free(void *where)
+-{	/* Don't care */
+-}
+-
+-static void gzip_mark(void **ptr)
+-{
+-	*ptr = (void *) free_mem_ptr;
+-}
+-
+-static void gzip_release(void **ptr)
+-{
+-	free_mem_ptr = (long) *ptr;
+-}
+- 
+-static void scroll(void)
+-{
+-	int i;
+-
+-	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+-	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+-		vidmem[i] = ' ';
+-}
+-
+-static void putstr(const char *s)
+-{
+-	int x,y,pos;
+-	char c;
+-
+-	x = RM_SCREEN_INFO.orig_x;
+-	y = RM_SCREEN_INFO.orig_y;
+-
+-	while ( ( c = *s++ ) != '\0' ) {
+-		if ( c == '\n' ) {
+-			x = 0;
+-			if ( ++y >= lines ) {
+-				scroll();
+-				y--;
+-			}
+-		} else {
+-			vidmem [ ( x + cols * y ) * 2 ] = c; 
+-			if ( ++x >= cols ) {
+-				x = 0;
+-				if ( ++y >= lines ) {
+-					scroll();
+-					y--;
+-				}
+-			}
+-		}
+-	}
+-
+-	RM_SCREEN_INFO.orig_x = x;
+-	RM_SCREEN_INFO.orig_y = y;
+-
+-	pos = (x + cols * y) * 2;	/* Update cursor position */
+-	outb_p(14, vidport);
+-	outb_p(0xff & (pos >> 9), vidport+1);
+-	outb_p(15, vidport);
+-	outb_p(0xff & (pos >> 1), vidport+1);
+-}
+-
+-static void* memset(void* s, int c, unsigned n)
+-{
+-	int i;
+-	char *ss = (char*)s;
+-
+-	for (i=0;i<n;i++) ss[i] = c;
+-	return s;
+-}
+-
+-static void* memcpy(void* dest, const void* src, unsigned n)
+-{
+-	int i;
+-	char *d = (char *)dest, *s = (char *)src;
+-
+-	for (i=0;i<n;i++) d[i] = s[i];
+-	return dest;
+-}
+-
+-/* ===========================================================================
+- * Fill the input buffer. This is called only when the buffer is empty
+- * and at least one byte is really needed.
+- */
+-static int fill_inbuf(void)
+-{
+-	error("ran out of input data");
+-	return 0;
+-}
+-
+-/* ===========================================================================
+- * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+- * (Used for the decompressed data only.)
+- */
+-static void flush_window(void)
+-{
+-	/* With my window equal to my output buffer
+-	 * I only need to compute the crc here.
+-	 */
+-	ulg c = crc;         /* temporary variable */
+-	unsigned n;
+-	uch *in, ch;
+-
+-	in = window;
+-	for (n = 0; n < outcnt; n++) {
+-		ch = *in++;
+-		c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+-	}
+-	crc = c;
+-	bytes_out += (ulg)outcnt;
+-	outcnt = 0;
+-}
+-
+-static void error(char *x)
+-{
+-	putstr("\n\n");
+-	putstr(x);
+-	putstr("\n\n -- System halted");
+-
+-	while(1);	/* Halt */
+-}
+-
+-asmlinkage void decompress_kernel(void *rmode, unsigned long heap,
+-	uch *input_data, unsigned long input_len, uch *output)
+-{
+-	real_mode = rmode;
+-
+-	if (RM_SCREEN_INFO.orig_video_mode == 7) {
+-		vidmem = (char *) 0xb0000;
+-		vidport = 0x3b4;
+-	} else {
+-		vidmem = (char *) 0xb8000;
+-		vidport = 0x3d4;
+-	}
+-
+-	lines = RM_SCREEN_INFO.orig_video_lines;
+-	cols = RM_SCREEN_INFO.orig_video_cols;
+-
+-	window = output;  		/* Output buffer (Normally at 1M) */
+-	free_mem_ptr     = heap;	/* Heap  */
+-	free_mem_end_ptr = heap + HEAP_SIZE;
+-	inbuf  = input_data;		/* Input buffer */
+-	insize = input_len;
+-	inptr  = 0;
+-
+-	if ((ulg)output & (__KERNEL_ALIGN - 1))
+-		error("Destination address not 2M aligned");
+-	if ((ulg)output >= 0xffffffffffUL)
+-		error("Destination address too large");
+-
+-	makecrc();
+-	putstr(".\nDecompressing Linux...");
+-	gunzip();
+-	putstr("done.\nBooting the kernel.\n");
+-	return;
+-}
+diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
+index 7a0d00b..d01ea42 100644
+--- a/arch/x86/boot/compressed/relocs.c
++++ b/arch/x86/boot/compressed/relocs.c
+@@ -27,11 +27,6 @@ static unsigned long *relocs;
+  * absolute relocations present w.r.t these symbols.
+  */
+ static const char* safe_abs_relocs[] = {
+-		"__kernel_vsyscall",
+-		"__kernel_rt_sigreturn",
+-		"__kernel_sigreturn",
+-		"SYSENTER_RETURN",
+-		"VDSO_NOTE_MASK",
+ 		"xen_irq_disable_direct_reloc",
+ 		"xen_save_fl_direct_reloc",
+ };
+@@ -45,6 +40,8 @@ static int is_safe_abs_reloc(const char* sym_name)
+ 			/* Match found */
+ 			return 1;
+ 	}
++	if (strncmp(sym_name, "VDSO", 4) == 0)
++		return 1;
+ 	if (strncmp(sym_name, "__crc_", 6) == 0)
+ 		return 1;
+ 	return 0;
+diff --git a/arch/x86/boot/compressed/vmlinux.scr b/arch/x86/boot/compressed/vmlinux.scr
+new file mode 100644
+index 0000000..f02382a
+--- /dev/null
++++ b/arch/x86/boot/compressed/vmlinux.scr
+@@ -0,0 +1,10 @@
++SECTIONS
++{
++  .rodata.compressed : {
++	input_len = .;
++	LONG(input_data_end - input_data) input_data = .;
++	*(.data)
++	output_len = . - 4;
++	input_data_end = .;
++	}
++}
+diff --git a/arch/x86/boot/compressed/vmlinux_32.lds b/arch/x86/boot/compressed/vmlinux_32.lds
+index cc4854f..bb3c483 100644
+--- a/arch/x86/boot/compressed/vmlinux_32.lds
++++ b/arch/x86/boot/compressed/vmlinux_32.lds
+@@ -3,17 +3,17 @@ OUTPUT_ARCH(i386)
+ ENTRY(startup_32)
+ SECTIONS
+ {
+-        /* Be careful parts of head.S assume startup_32 is at
+-         * address 0.
++	/* Be careful parts of head_32.S assume startup_32 is at
++	 * address 0.
+ 	 */
+-	. =  0 	;
++	. = 0;
+ 	.text.head : {
+ 		_head = . ;
+ 		*(.text.head)
+ 		_ehead = . ;
+ 	}
+-	.data.compressed : {
+-		*(.data.compressed)
++	.rodata.compressed : {
++		*(.rodata.compressed)
+ 	}
+ 	.text :	{
+ 		_text = .; 	/* Text */
+diff --git a/arch/x86/boot/compressed/vmlinux_32.scr b/arch/x86/boot/compressed/vmlinux_32.scr
+deleted file mode 100644
+index 707a88f..0000000
+--- a/arch/x86/boot/compressed/vmlinux_32.scr
++++ /dev/null
+@@ -1,10 +0,0 @@
+-SECTIONS
+-{
+-  .data.compressed : {
+-	input_len = .;
+-	LONG(input_data_end - input_data) input_data = .; 
+-	*(.data) 
+-	output_len = . - 4;
+-	input_data_end = .; 
+-	}
+-}
+diff --git a/arch/x86/boot/compressed/vmlinux_64.lds b/arch/x86/boot/compressed/vmlinux_64.lds
+index 94c13e5..7e5c720 100644
+--- a/arch/x86/boot/compressed/vmlinux_64.lds
++++ b/arch/x86/boot/compressed/vmlinux_64.lds
+@@ -3,15 +3,19 @@ OUTPUT_ARCH(i386:x86-64)
+ ENTRY(startup_64)
+ SECTIONS
+ {
+-	/* Be careful parts of head.S assume startup_32 is at
+- 	 * address 0.
++	/* Be careful parts of head_64.S assume startup_32 is at
++	 * address 0.
+ 	 */
+ 	. = 0;
+-	.text :	{
++	.text.head : {
+ 		_head = . ;
+ 		*(.text.head)
+ 		_ehead = . ;
+-		*(.text.compressed)
++	}
++	.rodata.compressed : {
++		*(.rodata.compressed)
++	}
++	.text :	{
+ 		_text = .; 	/* Text */
+ 		*(.text)
+ 		*(.text.*)
+diff --git a/arch/x86/boot/compressed/vmlinux_64.scr b/arch/x86/boot/compressed/vmlinux_64.scr
+deleted file mode 100644
+index bd1429c..0000000
+--- a/arch/x86/boot/compressed/vmlinux_64.scr
++++ /dev/null
+@@ -1,10 +0,0 @@
+-SECTIONS
+-{
+-  .text.compressed : {
+-	input_len = .;
+-	LONG(input_data_end - input_data) input_data = .;
+-	*(.data)
+-	output_len = . - 4;
+-	input_data_end = .;
+-	}
+-}
+diff --git a/arch/x86/boot/cpu.c b/arch/x86/boot/cpu.c
+index 2a5c32d..00e19ed 100644
+--- a/arch/x86/boot/cpu.c
++++ b/arch/x86/boot/cpu.c
+@@ -1,7 +1,7 @@
+ /* -*- linux-c -*- ------------------------------------------------------- *
+  *
+  *   Copyright (C) 1991, 1992 Linus Torvalds
+- *   Copyright 2007 rPath, Inc. - All Rights Reserved
++ *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
+  *
+  *   This file is part of the Linux kernel, and is made available under
+  *   the terms of the GNU General Public License version 2.
+@@ -9,7 +9,7 @@
+  * ----------------------------------------------------------------------- */
+ 
+ /*
+- * arch/i386/boot/cpu.c
++ * arch/x86/boot/cpu.c
+  *
+  * Check for obligatory CPU features and abort if the features are not
+  * present.
+@@ -19,6 +19,8 @@
+ #include "bitops.h"
+ #include <asm/cpufeature.h>
+ 
++#include "cpustr.h"
++
+ static char *cpu_name(int level)
+ {
+ 	static char buf[6];
+@@ -35,6 +37,7 @@ int validate_cpu(void)
+ {
+ 	u32 *err_flags;
+ 	int cpu_level, req_level;
++	const unsigned char *msg_strs;
+ 
+ 	check_cpu(&cpu_level, &req_level, &err_flags);
+ 
+@@ -51,13 +54,26 @@ int validate_cpu(void)
+ 		puts("This kernel requires the following features "
+ 		     "not present on the CPU:\n");
+ 
++		msg_strs = (const unsigned char *)x86_cap_strs;
++
+ 		for (i = 0; i < NCAPINTS; i++) {
+ 			u32 e = err_flags[i];
+ 
+ 			for (j = 0; j < 32; j++) {
+-				if (e & 1)
+-					printf("%d:%d ", i, j);
+-
++				int n = (i << 5)+j;
++				if (*msg_strs < n) {
++					/* Skip to the next string */
++					do {
++						msg_strs++;
++					} while (*msg_strs);
++					msg_strs++;
++				}
++				if (e & 1) {
++					if (*msg_strs == n && msg_strs[1])
++						printf("%s ", msg_strs+1);
++					else
++						printf("%d:%d ", i, j);
++				}
+ 				e >>= 1;
+ 			}
+ 		}
+diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c
+index bd138e4..8721dc4 100644
+--- a/arch/x86/boot/edd.c
++++ b/arch/x86/boot/edd.c
+@@ -129,6 +129,7 @@ void query_edd(void)
+ 	char eddarg[8];
+ 	int do_mbr = 1;
+ 	int do_edd = 1;
++	int be_quiet;
+ 	int devno;
+ 	struct edd_info ei, *edp;
+ 	u32 *mbrptr;
+@@ -140,12 +141,21 @@ void query_edd(void)
+ 			do_edd = 0;
+ 	}
+ 
++	be_quiet = cmdline_find_option_bool("quiet");
++
+ 	edp    = boot_params.eddbuf;
+ 	mbrptr = boot_params.edd_mbr_sig_buffer;
+ 
+ 	if (!do_edd)
+ 		return;
+ 
++	/* Bugs in OnBoard or AddOnCards Bios may hang the EDD probe,
++	 * so give a hint if this happens.
++	 */
++
++	if (!be_quiet)
++		printf("Probing EDD (edd=off to disable)... ");
++
+ 	for (devno = 0x80; devno < 0x80+EDD_MBR_SIG_MAX; devno++) {
+ 		/*
+ 		 * Scan the BIOS-supported hard disks and query EDD
+@@ -162,6 +172,9 @@ void query_edd(void)
+ 		if (do_mbr && !read_mbr_sig(devno, &ei, mbrptr++))
+ 			boot_params.edd_mbr_sig_buf_entries = devno-0x80+1;
+ 	}
++
++	if (!be_quiet)
++		printf("ok\n");
+ }
+ 
+ #endif
+diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
+index 4cc5b04..64ad901 100644
+--- a/arch/x86/boot/header.S
++++ b/arch/x86/boot/header.S
+@@ -195,10 +195,13 @@ cmd_line_ptr:	.long	0		# (Header version 0x0202 or later)
+ 					# can be located anywhere in
+ 					# low memory 0x10000 or higher.
+ 
+-ramdisk_max:	.long (-__PAGE_OFFSET-(512 << 20)-1) & 0x7fffffff
++ramdisk_max:	.long 0x7fffffff
+ 					# (Header version 0x0203 or later)
+ 					# The highest safe address for
+ 					# the contents of an initrd
++					# The current kernel allows up to 4 GB,
++					# but leave it at 2 GB to avoid
++					# possible bootloader bugs.
+ 
+ kernel_alignment:  .long CONFIG_PHYSICAL_ALIGN	#physical addr alignment
+ 						#required for protected mode
+diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
+index 1f95750..7828da5 100644
+--- a/arch/x86/boot/main.c
++++ b/arch/x86/boot/main.c
+@@ -100,20 +100,32 @@ static void set_bios_mode(void)
+ #endif
+ }
+ 
+-void main(void)
++static void init_heap(void)
+ {
+-	/* First, copy the boot header into the "zeropage" */
+-	copy_boot_params();
++	char *stack_end;
+ 
+-	/* End of heap check */
+ 	if (boot_params.hdr.loadflags & CAN_USE_HEAP) {
+-		heap_end = (char *)(boot_params.hdr.heap_end_ptr
+-				    +0x200-STACK_SIZE);
++		asm("leal %P1(%%esp),%0"
++		    : "=r" (stack_end) : "i" (-STACK_SIZE));
++
++		heap_end = (char *)
++			((size_t)boot_params.hdr.heap_end_ptr + 0x200);
++		if (heap_end > stack_end)
++			heap_end = stack_end;
+ 	} else {
+ 		/* Boot protocol 2.00 only, no heap available */
+ 		puts("WARNING: Ancient bootloader, some functionality "
+ 		     "may be limited!\n");
+ 	}
++}
++
++void main(void)
++{
++	/* First, copy the boot header into the "zeropage" */
++	copy_boot_params();
++
++	/* End of heap check */
++	init_heap();
+ 
+ 	/* Make sure we have all the proper CPU support */
+ 	if (validate_cpu()) {
+@@ -131,9 +143,6 @@ void main(void)
+ 	/* Set keyboard repeat rate (why?) */
+ 	keyboard_set_repeat();
+ 
+-	/* Set the video mode */
+-	set_video();
+-
+ 	/* Query MCA information */
+ 	query_mca();
+ 
+@@ -154,6 +163,10 @@ void main(void)
+ #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+ 	query_edd();
+ #endif
++
++	/* Set the video mode */
++	set_video();
++
+ 	/* Do the last things and invoke protected mode */
+ 	go_to_protected_mode();
+ }
+diff --git a/arch/x86/boot/mkcpustr.c b/arch/x86/boot/mkcpustr.c
+new file mode 100644
+index 0000000..bbe7695
+--- /dev/null
++++ b/arch/x86/boot/mkcpustr.c
+@@ -0,0 +1,49 @@
++/* ----------------------------------------------------------------------- *
++ *
++ *   Copyright 2008 rPath, Inc. - All Rights Reserved
++ *
++ *   This file is part of the Linux kernel, and is made available under
++ *   the terms of the GNU General Public License version 2 or (at your
++ *   option) any later version; incorporated herein by reference.
++ *
++ * ----------------------------------------------------------------------- */
++
++/*
++ * This is a host program to preprocess the CPU strings into a
++ * compact format suitable for the setup code.
++ */
++
++#include <stdio.h>
++
++#include "../kernel/cpu/feature_names.c"
++
++#if NCAPFLAGS > 8
++# error "Need to adjust the boot code handling of CPUID strings"
++#endif
++
++int main(void)
++{
++	int i;
++	const char *str;
++
++	printf("static const char x86_cap_strs[] = \n");
++
++	for (i = 0; i < NCAPINTS*32; i++) {
++		str = x86_cap_flags[i];
++
++		if (i == NCAPINTS*32-1) {
++			/* The last entry must be unconditional; this
++			   also consumes the compiler-added null character */
++			if (!str)
++				str = "";
++			printf("\t\"\\x%02x\"\"%s\"\n", i, str);
++		} else if (str) {
++			printf("#if REQUIRED_MASK%d & (1 << %d)\n"
++			       "\t\"\\x%02x\"\"%s\\0\"\n"
++			       "#endif\n",
++			       i >> 5, i & 31, i, str);
++		}
++	}
++	printf("\t;\n");
++	return 0;
++}
+diff --git a/arch/x86/boot/pm.c b/arch/x86/boot/pm.c
+index 09fb342..1a0f936 100644
+--- a/arch/x86/boot/pm.c
++++ b/arch/x86/boot/pm.c
+@@ -104,7 +104,7 @@ static void reset_coprocessor(void)
+ 	(((u64)(base & 0xff000000) << 32) |	\
+ 	 ((u64)flags << 40) |			\
+ 	 ((u64)(limit & 0x00ff0000) << 32) |	\
+-	 ((u64)(base & 0x00ffff00) << 16) |	\
++	 ((u64)(base & 0x00ffffff) << 16) |	\
+ 	 ((u64)(limit & 0x0000ffff)))
+ 
+ struct gdt_ptr {
+@@ -121,6 +121,10 @@ static void setup_gdt(void)
+ 		[GDT_ENTRY_BOOT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+ 		/* DS: data, read/write, 4 GB, base 0 */
+ 		[GDT_ENTRY_BOOT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
++		/* TSS: 32-bit tss, 104 bytes, base 4096 */
++		/* We only have a TSS here to keep Intel VT happy;
++		   we don't actually use it for anything. */
++		[GDT_ENTRY_BOOT_TSS] = GDT_ENTRY(0x0089, 4096, 103),
+ 	};
+ 	/* Xen HVM incorrectly stores a pointer to the gdt_ptr, instead
+ 	   of the gdt_ptr contents.  Thus, make it static so it will
+diff --git a/arch/x86/boot/pmjump.S b/arch/x86/boot/pmjump.S
+index fa6bed1..f5402d5 100644
+--- a/arch/x86/boot/pmjump.S
++++ b/arch/x86/boot/pmjump.S
+@@ -15,6 +15,7 @@
+  */
+ 
+ #include <asm/boot.h>
++#include <asm/processor-flags.h>
+ #include <asm/segment.h>
+ 
+ 	.text
+@@ -29,28 +30,55 @@
+  */
+ protected_mode_jump:
+ 	movl	%edx, %esi		# Pointer to boot_params table
+-	movl	%eax, 2f		# Patch ljmpl instruction
++
++	xorl	%ebx, %ebx
++	movw	%cs, %bx
++	shll	$4, %ebx
++	addl	%ebx, 2f
+ 
+ 	movw	$__BOOT_DS, %cx
+-	xorl	%ebx, %ebx		# Per the 32-bit boot protocol
+-	xorl	%ebp, %ebp		# Per the 32-bit boot protocol
+-	xorl	%edi, %edi		# Per the 32-bit boot protocol
++	movw	$__BOOT_TSS, %di
+ 
+ 	movl	%cr0, %edx
+-	orb	$1, %dl			# Protected mode (PE) bit
++	orb	$X86_CR0_PE, %dl	# Protected mode
+ 	movl	%edx, %cr0
+ 	jmp	1f			# Short jump to serialize on 386/486
+ 1:
+ 
+-	movw	%cx, %ds
+-	movw	%cx, %es
+-	movw	%cx, %fs
+-	movw	%cx, %gs
+-	movw	%cx, %ss
+-
+-	# Jump to the 32-bit entrypoint
++	# Transition to 32-bit mode
+ 	.byte	0x66, 0xea		# ljmpl opcode
+-2:	.long	0			# offset
++2:	.long	in_pm32			# offset
+ 	.word	__BOOT_CS		# segment
+ 
+ 	.size	protected_mode_jump, .-protected_mode_jump
++
++	.code32
++	.type	in_pm32, @function
++in_pm32:
++	# Set up data segments for flat 32-bit mode
++	movl	%ecx, %ds
++	movl	%ecx, %es
++	movl	%ecx, %fs
++	movl	%ecx, %gs
++	movl	%ecx, %ss
++	# The 32-bit code sets up its own stack, but this way we do have
++	# a valid stack if some debugging hack wants to use it.
++	addl	%ebx, %esp
++
++	# Set up TR to make Intel VT happy
++	ltr	%di
++
++	# Clear registers to allow for future extensions to the
++	# 32-bit boot protocol
++	xorl	%ecx, %ecx
++	xorl	%edx, %edx
++	xorl	%ebx, %ebx
++	xorl	%ebp, %ebp
++	xorl	%edi, %edi
++
++	# Set up LDTR to make Intel VT happy
++	lldt	%cx
++
++	jmpl	*%eax			# Jump to the 32-bit entrypoint
++
++	.size	in_pm32, .-in_pm32
+diff --git a/arch/x86/boot/video-bios.c b/arch/x86/boot/video-bios.c
+index ed0672a..ff664a1 100644
+--- a/arch/x86/boot/video-bios.c
++++ b/arch/x86/boot/video-bios.c
+@@ -104,6 +104,7 @@ static int bios_probe(void)
+ 
+ 		mi = GET_HEAP(struct mode_info, 1);
+ 		mi->mode = VIDEO_FIRST_BIOS+mode;
++		mi->depth = 0;	/* text */
+ 		mi->x = rdfs16(0x44a);
+ 		mi->y = rdfs8(0x484)+1;
+ 		nmodes++;
+@@ -116,7 +117,7 @@ static int bios_probe(void)
+ 
+ __videocard video_bios =
+ {
+-	.card_name	= "BIOS (scanned)",
++	.card_name	= "BIOS",
+ 	.probe		= bios_probe,
+ 	.set_mode	= bios_set_mode,
+ 	.unsafe		= 1,
+diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c
+index 4716b9a..662dd2f 100644
+--- a/arch/x86/boot/video-vesa.c
++++ b/arch/x86/boot/video-vesa.c
+@@ -79,20 +79,28 @@ static int vesa_probe(void)
+ 			/* Text Mode, TTY BIOS supported,
+ 			   supported by hardware */
+ 			mi = GET_HEAP(struct mode_info, 1);
+-			mi->mode = mode + VIDEO_FIRST_VESA;
+-			mi->x    = vminfo.h_res;
+-			mi->y    = vminfo.v_res;
++			mi->mode  = mode + VIDEO_FIRST_VESA;
++			mi->depth = 0; /* text */
++			mi->x     = vminfo.h_res;
++			mi->y     = vminfo.v_res;
+ 			nmodes++;
+-		} else if ((vminfo.mode_attr & 0x99) == 0x99) {
++		} else if ((vminfo.mode_attr & 0x99) == 0x99 &&
++			   (vminfo.memory_layout == 4 ||
++			    vminfo.memory_layout == 6) &&
++			   vminfo.memory_planes == 1) {
+ #ifdef CONFIG_FB
+ 			/* Graphics mode, color, linear frame buffer
+-			   supported -- register the mode but hide from
+-			   the menu.  Only do this if framebuffer is
+-			   configured, however, otherwise the user will
+-			   be left without a screen. */
++			   supported.  Only register the mode if
++			   if framebuffer is configured, however,
++			   otherwise the user will be left without a screen.
++			   We don't require CONFIG_FB_VESA, however, since
++			   some of the other framebuffer drivers can use
++			   this mode-setting, too. */
+ 			mi = GET_HEAP(struct mode_info, 1);
+ 			mi->mode = mode + VIDEO_FIRST_VESA;
+-			mi->x = mi->y = 0;
++			mi->depth = vminfo.bpp;
++			mi->x = vminfo.h_res;
++			mi->y = vminfo.v_res;
+ 			nmodes++;
+ #endif
+ 		}
+diff --git a/arch/x86/boot/video-vga.c b/arch/x86/boot/video-vga.c
+index aef02f9..7259387 100644
+--- a/arch/x86/boot/video-vga.c
++++ b/arch/x86/boot/video-vga.c
+@@ -18,22 +18,22 @@
+ #include "video.h"
+ 
+ static struct mode_info vga_modes[] = {
+-	{ VIDEO_80x25,  80, 25 },
+-	{ VIDEO_8POINT, 80, 50 },
+-	{ VIDEO_80x43,  80, 43 },
+-	{ VIDEO_80x28,  80, 28 },
+-	{ VIDEO_80x30,  80, 30 },
+-	{ VIDEO_80x34,  80, 34 },
+-	{ VIDEO_80x60,  80, 60 },
++	{ VIDEO_80x25,  80, 25, 0 },
++	{ VIDEO_8POINT, 80, 50, 0 },
++	{ VIDEO_80x43,  80, 43, 0 },
++	{ VIDEO_80x28,  80, 28, 0 },
++	{ VIDEO_80x30,  80, 30, 0 },
++	{ VIDEO_80x34,  80, 34, 0 },
++	{ VIDEO_80x60,  80, 60, 0 },
+ };
+ 
+ static struct mode_info ega_modes[] = {
+-	{ VIDEO_80x25,  80, 25 },
+-	{ VIDEO_8POINT, 80, 43 },
++	{ VIDEO_80x25,  80, 25, 0 },
++	{ VIDEO_8POINT, 80, 43, 0 },
+ };
+ 
+ static struct mode_info cga_modes[] = {
+-	{ VIDEO_80x25,  80, 25 },
++	{ VIDEO_80x25,  80, 25, 0 },
+ };
+ 
+ __videocard video_vga;
+diff --git a/arch/x86/boot/video.c b/arch/x86/boot/video.c
+index ad9712f..696d08f 100644
+--- a/arch/x86/boot/video.c
++++ b/arch/x86/boot/video.c
+@@ -293,13 +293,28 @@ static void display_menu(void)
+ 	struct mode_info *mi;
+ 	char ch;
+ 	int i;
++	int nmodes;
++	int modes_per_line;
++	int col;
+ 
+-	puts("Mode:    COLSxROWS:\n");
++	nmodes = 0;
++	for (card = video_cards; card < video_cards_end; card++)
++		nmodes += card->nmodes;
+ 
++	modes_per_line = 1;
++	if (nmodes >= 20)
++		modes_per_line = 3;
++
++	for (col = 0; col < modes_per_line; col++)
++		puts("Mode: Resolution:  Type: ");
++	putchar('\n');
++
++	col = 0;
+ 	ch = '0';
+ 	for (card = video_cards; card < video_cards_end; card++) {
+ 		mi = card->modes;
+ 		for (i = 0; i < card->nmodes; i++, mi++) {
++			char resbuf[32];
+ 			int visible = mi->x && mi->y;
+ 			u16 mode_id = mi->mode ? mi->mode :
+ 				(mi->y << 8)+mi->x;
+@@ -307,8 +322,18 @@ static void display_menu(void)
+ 			if (!visible)
+ 				continue; /* Hidden mode */
+ 
+-			printf("%c  %04X  %3dx%-3d  %s\n",
+-			       ch, mode_id, mi->x, mi->y, card->card_name);
++			if (mi->depth)
++				sprintf(resbuf, "%dx%d", mi->y, mi->depth);
++			else
++				sprintf(resbuf, "%d", mi->y);
++
++			printf("%c %03X %4dx%-7s %-6s",
++			       ch, mode_id, mi->x, resbuf, card->card_name);
++			col++;
++			if (col >= modes_per_line) {
++				putchar('\n');
++				col = 0;
++			}
+ 
+ 			if (ch == '9')
+ 				ch = 'a';
+@@ -318,6 +343,8 @@ static void display_menu(void)
+ 				ch++;
+ 		}
+ 	}
++	if (col)
++		putchar('\n');
+ }
+ 
+ #define H(x)	((x)-'a'+10)
+diff --git a/arch/x86/boot/video.h b/arch/x86/boot/video.h
+index b92447d..d69347f 100644
+--- a/arch/x86/boot/video.h
++++ b/arch/x86/boot/video.h
+@@ -83,7 +83,8 @@ void store_screen(void);
+ 
+ struct mode_info {
+ 	u16 mode;		/* Mode number (vga= style) */
+-	u8  x, y;		/* Width, height */
++	u16 x, y;		/* Width, height */
++	u16 depth;		/* Bits per pixel, 0 for text mode */
+ };
+ 
+ struct card_info {
+diff --git a/arch/x86/boot/voyager.c b/arch/x86/boot/voyager.c
+index 61c8fe0..6499e32 100644
+--- a/arch/x86/boot/voyager.c
++++ b/arch/x86/boot/voyager.c
+@@ -16,8 +16,6 @@
+ 
+ #include "boot.h"
+ 
+-#ifdef CONFIG_X86_VOYAGER
+-
+ int query_voyager(void)
+ {
+ 	u8 err;
+@@ -42,5 +40,3 @@ int query_voyager(void)
+ 	copy_from_fs(data_ptr, di, 7);	/* Table is 7 bytes apparently */
+ 	return 0;
+ }
+-
+-#endif /* CONFIG_X86_VOYAGER */
+diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
+index 54ee176..77562e7 100644
+--- a/arch/x86/configs/i386_defconfig
++++ b/arch/x86/configs/i386_defconfig
+@@ -99,9 +99,9 @@ CONFIG_IOSCHED_NOOP=y
+ CONFIG_IOSCHED_AS=y
+ CONFIG_IOSCHED_DEADLINE=y
+ CONFIG_IOSCHED_CFQ=y
+-CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_AS is not set
+ # CONFIG_DEFAULT_DEADLINE is not set
+-# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_CFQ=y
+ # CONFIG_DEFAULT_NOOP is not set
+ CONFIG_DEFAULT_IOSCHED="anticipatory"
+ 
+diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
+index 38a83f9..9e2b0ef 100644
+--- a/arch/x86/configs/x86_64_defconfig
++++ b/arch/x86/configs/x86_64_defconfig
+@@ -145,15 +145,6 @@ CONFIG_K8_NUMA=y
+ CONFIG_NODES_SHIFT=6
+ CONFIG_X86_64_ACPI_NUMA=y
+ CONFIG_NUMA_EMU=y
+-CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+-CONFIG_ARCH_DISCONTIGMEM_DEFAULT=y
+-CONFIG_ARCH_SPARSEMEM_ENABLE=y
+-CONFIG_SELECT_MEMORY_MODEL=y
+-# CONFIG_FLATMEM_MANUAL is not set
+-CONFIG_DISCONTIGMEM_MANUAL=y
+-# CONFIG_SPARSEMEM_MANUAL is not set
+-CONFIG_DISCONTIGMEM=y
+-CONFIG_FLAT_NODE_MEM_MAP=y
+ CONFIG_NEED_MULTIPLE_NODES=y
+ # CONFIG_SPARSEMEM_STATIC is not set
+ CONFIG_SPLIT_PTLOCK_CPUS=4
+diff --git a/arch/x86/crypto/Makefile b/arch/x86/crypto/Makefile
+index 46bb609..3874c2d 100644
+--- a/arch/x86/crypto/Makefile
++++ b/arch/x86/crypto/Makefile
+@@ -4,12 +4,16 @@
+ 
+ obj-$(CONFIG_CRYPTO_AES_586) += aes-i586.o
+ obj-$(CONFIG_CRYPTO_TWOFISH_586) += twofish-i586.o
++obj-$(CONFIG_CRYPTO_SALSA20_586) += salsa20-i586.o
+ 
+ obj-$(CONFIG_CRYPTO_AES_X86_64) += aes-x86_64.o
+ obj-$(CONFIG_CRYPTO_TWOFISH_X86_64) += twofish-x86_64.o
++obj-$(CONFIG_CRYPTO_SALSA20_X86_64) += salsa20-x86_64.o
+ 
+-aes-i586-y := aes-i586-asm_32.o aes_32.o
+-twofish-i586-y := twofish-i586-asm_32.o twofish_32.o
++aes-i586-y := aes-i586-asm_32.o aes_glue.o
++twofish-i586-y := twofish-i586-asm_32.o twofish_glue.o
++salsa20-i586-y := salsa20-i586-asm_32.o salsa20_glue.o
+ 
+-aes-x86_64-y := aes-x86_64-asm_64.o aes_64.o
+-twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_64.o
++aes-x86_64-y := aes-x86_64-asm_64.o aes_glue.o
++twofish-x86_64-y := twofish-x86_64-asm_64.o twofish_glue.o
++salsa20-x86_64-y := salsa20-x86_64-asm_64.o salsa20_glue.o
+diff --git a/arch/x86/crypto/aes-i586-asm_32.S b/arch/x86/crypto/aes-i586-asm_32.S
+index f942f0c..1093bed 100644
+--- a/arch/x86/crypto/aes-i586-asm_32.S
++++ b/arch/x86/crypto/aes-i586-asm_32.S
+@@ -46,9 +46,9 @@
+ #define in_blk 16
+ 
+ /* offsets in crypto_tfm structure */
+-#define ekey (crypto_tfm_ctx_offset + 0)
+-#define nrnd (crypto_tfm_ctx_offset + 256)
+-#define dkey (crypto_tfm_ctx_offset + 260)
++#define klen (crypto_tfm_ctx_offset + 0)
++#define ekey (crypto_tfm_ctx_offset + 4)
++#define dkey (crypto_tfm_ctx_offset + 244)
+ 
+ // register mapping for encrypt and decrypt subroutines
+ 
+@@ -221,8 +221,8 @@
+ 
+ .global  aes_enc_blk
+ 
+-.extern  ft_tab
+-.extern  fl_tab
++.extern  crypto_ft_tab
++.extern  crypto_fl_tab
+ 
+ .align 4
+ 
+@@ -236,7 +236,7 @@ aes_enc_blk:
+ 1:	push    %ebx
+ 	mov     in_blk+4(%esp),%r2
+ 	push    %esi
+-	mov     nrnd(%ebp),%r3   // number of rounds
++	mov     klen(%ebp),%r3   // key size
+ 	push    %edi
+ #if ekey != 0
+ 	lea     ekey(%ebp),%ebp  // key pointer
+@@ -255,26 +255,26 @@ aes_enc_blk:
+ 
+ 	sub     $8,%esp		// space for register saves on stack
+ 	add     $16,%ebp	// increment to next round key
+-	cmp     $12,%r3
++	cmp     $24,%r3
+ 	jb      4f		// 10 rounds for 128-bit key
+ 	lea     32(%ebp),%ebp
+ 	je      3f		// 12 rounds for 192-bit key
+ 	lea     32(%ebp),%ebp
+ 
+-2:	fwd_rnd1( -64(%ebp) ,ft_tab)	// 14 rounds for 256-bit key
+-	fwd_rnd2( -48(%ebp) ,ft_tab)
+-3:	fwd_rnd1( -32(%ebp) ,ft_tab)	// 12 rounds for 192-bit key
+-	fwd_rnd2( -16(%ebp) ,ft_tab)
+-4:	fwd_rnd1(    (%ebp) ,ft_tab)	// 10 rounds for 128-bit key
+-	fwd_rnd2( +16(%ebp) ,ft_tab)
+-	fwd_rnd1( +32(%ebp) ,ft_tab)
+-	fwd_rnd2( +48(%ebp) ,ft_tab)
+-	fwd_rnd1( +64(%ebp) ,ft_tab)
+-	fwd_rnd2( +80(%ebp) ,ft_tab)
+-	fwd_rnd1( +96(%ebp) ,ft_tab)
+-	fwd_rnd2(+112(%ebp) ,ft_tab)
+-	fwd_rnd1(+128(%ebp) ,ft_tab)
+-	fwd_rnd2(+144(%ebp) ,fl_tab)	// last round uses a different table
++2:	fwd_rnd1( -64(%ebp), crypto_ft_tab)	// 14 rounds for 256-bit key
++	fwd_rnd2( -48(%ebp), crypto_ft_tab)
++3:	fwd_rnd1( -32(%ebp), crypto_ft_tab)	// 12 rounds for 192-bit key
++	fwd_rnd2( -16(%ebp), crypto_ft_tab)
++4:	fwd_rnd1(    (%ebp), crypto_ft_tab)	// 10 rounds for 128-bit key
++	fwd_rnd2( +16(%ebp), crypto_ft_tab)
++	fwd_rnd1( +32(%ebp), crypto_ft_tab)
++	fwd_rnd2( +48(%ebp), crypto_ft_tab)
++	fwd_rnd1( +64(%ebp), crypto_ft_tab)
++	fwd_rnd2( +80(%ebp), crypto_ft_tab)
++	fwd_rnd1( +96(%ebp), crypto_ft_tab)
++	fwd_rnd2(+112(%ebp), crypto_ft_tab)
++	fwd_rnd1(+128(%ebp), crypto_ft_tab)
++	fwd_rnd2(+144(%ebp), crypto_fl_tab)	// last round uses a different table
+ 
+ // move final values to the output array.  CAUTION: the 
+ // order of these assigns rely on the register mappings
+@@ -297,8 +297,8 @@ aes_enc_blk:
+ 
+ .global  aes_dec_blk
+ 
+-.extern  it_tab
+-.extern  il_tab
++.extern  crypto_it_tab
++.extern  crypto_il_tab
+ 
+ .align 4
+ 
+@@ -312,14 +312,11 @@ aes_dec_blk:
+ 1:	push    %ebx
+ 	mov     in_blk+4(%esp),%r2
+ 	push    %esi
+-	mov     nrnd(%ebp),%r3   // number of rounds
++	mov     klen(%ebp),%r3   // key size
+ 	push    %edi
+ #if dkey != 0
+ 	lea     dkey(%ebp),%ebp  // key pointer
+ #endif
+-	mov     %r3,%r0
+-	shl     $4,%r0
+-	add     %r0,%ebp
+ 	
+ // input four columns and xor in first round key
+ 
+@@ -333,27 +330,27 @@ aes_dec_blk:
+ 	xor     12(%ebp),%r5
+ 
+ 	sub     $8,%esp		// space for register saves on stack
+-	sub     $16,%ebp	// increment to next round key
+-	cmp     $12,%r3
++	add     $16,%ebp	// increment to next round key
++	cmp     $24,%r3
+ 	jb      4f		// 10 rounds for 128-bit key
+-	lea     -32(%ebp),%ebp
++	lea     32(%ebp),%ebp
+ 	je      3f		// 12 rounds for 192-bit key
+-	lea     -32(%ebp),%ebp
+-
+-2:	inv_rnd1( +64(%ebp), it_tab)	// 14 rounds for 256-bit key
+-	inv_rnd2( +48(%ebp), it_tab)
+-3:	inv_rnd1( +32(%ebp), it_tab)	// 12 rounds for 192-bit key
+-	inv_rnd2( +16(%ebp), it_tab)
+-4:	inv_rnd1(    (%ebp), it_tab)	// 10 rounds for 128-bit key
+-	inv_rnd2( -16(%ebp), it_tab)
+-	inv_rnd1( -32(%ebp), it_tab)
+-	inv_rnd2( -48(%ebp), it_tab)
+-	inv_rnd1( -64(%ebp), it_tab)
+-	inv_rnd2( -80(%ebp), it_tab)
+-	inv_rnd1( -96(%ebp), it_tab)
+-	inv_rnd2(-112(%ebp), it_tab)
+-	inv_rnd1(-128(%ebp), it_tab)
+-	inv_rnd2(-144(%ebp), il_tab)	// last round uses a different table
++	lea     32(%ebp),%ebp
++
++2:	inv_rnd1( -64(%ebp), crypto_it_tab)	// 14 rounds for 256-bit key
++	inv_rnd2( -48(%ebp), crypto_it_tab)
++3:	inv_rnd1( -32(%ebp), crypto_it_tab)	// 12 rounds for 192-bit key
++	inv_rnd2( -16(%ebp), crypto_it_tab)
++4:	inv_rnd1(    (%ebp), crypto_it_tab)	// 10 rounds for 128-bit key
++	inv_rnd2( +16(%ebp), crypto_it_tab)
++	inv_rnd1( +32(%ebp), crypto_it_tab)
++	inv_rnd2( +48(%ebp), crypto_it_tab)
++	inv_rnd1( +64(%ebp), crypto_it_tab)
++	inv_rnd2( +80(%ebp), crypto_it_tab)
++	inv_rnd1( +96(%ebp), crypto_it_tab)
++	inv_rnd2(+112(%ebp), crypto_it_tab)
++	inv_rnd1(+128(%ebp), crypto_it_tab)
++	inv_rnd2(+144(%ebp), crypto_il_tab)	// last round uses a different table
+ 
+ // move final values to the output array.  CAUTION: the 
+ // order of these assigns rely on the register mappings
+diff --git a/arch/x86/crypto/aes-x86_64-asm_64.S b/arch/x86/crypto/aes-x86_64-asm_64.S
+index 26b40de..a120f52 100644
+--- a/arch/x86/crypto/aes-x86_64-asm_64.S
++++ b/arch/x86/crypto/aes-x86_64-asm_64.S
+@@ -8,10 +8,10 @@
+  * including this sentence is retained in full.
+  */
+ 
+-.extern aes_ft_tab
+-.extern aes_it_tab
+-.extern aes_fl_tab
+-.extern aes_il_tab
++.extern crypto_ft_tab
++.extern crypto_it_tab
++.extern crypto_fl_tab
++.extern crypto_il_tab
+ 
+ .text
+ 
+@@ -56,13 +56,13 @@
+ 	.align	8;			\
+ FUNC:	movq	r1,r2;			\
+ 	movq	r3,r4;			\
+-	leaq	BASE+KEY+52(r8),r9;	\
++	leaq	BASE+KEY+48+4(r8),r9;	\
+ 	movq	r10,r11;		\
+ 	movl	(r7),r5 ## E;		\
+ 	movl	4(r7),r1 ## E;		\
+ 	movl	8(r7),r6 ## E;		\
+ 	movl	12(r7),r7 ## E;		\
+-	movl	BASE(r8),r10 ## E;	\
++	movl	BASE+0(r8),r10 ## E;	\
+ 	xorl	-48(r9),r5 ## E;	\
+ 	xorl	-44(r9),r1 ## E;	\
+ 	xorl	-40(r9),r6 ## E;	\
+@@ -154,37 +154,37 @@ FUNC:	movq	r1,r2;			\
+ /* void aes_enc_blk(stuct crypto_tfm *tfm, u8 *out, const u8 *in) */
+ 
+ 	entry(aes_enc_blk,0,enc128,enc192)
+-	encrypt_round(aes_ft_tab,-96)
+-	encrypt_round(aes_ft_tab,-80)
+-enc192:	encrypt_round(aes_ft_tab,-64)
+-	encrypt_round(aes_ft_tab,-48)
+-enc128:	encrypt_round(aes_ft_tab,-32)
+-	encrypt_round(aes_ft_tab,-16)
+-	encrypt_round(aes_ft_tab,  0)
+-	encrypt_round(aes_ft_tab, 16)
+-	encrypt_round(aes_ft_tab, 32)
+-	encrypt_round(aes_ft_tab, 48)
+-	encrypt_round(aes_ft_tab, 64)
+-	encrypt_round(aes_ft_tab, 80)
+-	encrypt_round(aes_ft_tab, 96)
+-	encrypt_final(aes_fl_tab,112)
++	encrypt_round(crypto_ft_tab,-96)
++	encrypt_round(crypto_ft_tab,-80)
++enc192:	encrypt_round(crypto_ft_tab,-64)
++	encrypt_round(crypto_ft_tab,-48)
++enc128:	encrypt_round(crypto_ft_tab,-32)
++	encrypt_round(crypto_ft_tab,-16)
++	encrypt_round(crypto_ft_tab,  0)
++	encrypt_round(crypto_ft_tab, 16)
++	encrypt_round(crypto_ft_tab, 32)
++	encrypt_round(crypto_ft_tab, 48)
++	encrypt_round(crypto_ft_tab, 64)
++	encrypt_round(crypto_ft_tab, 80)
++	encrypt_round(crypto_ft_tab, 96)
++	encrypt_final(crypto_fl_tab,112)
+ 	return
+ 
+ /* void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in) */
+ 
+ 	entry(aes_dec_blk,240,dec128,dec192)
+-	decrypt_round(aes_it_tab,-96)
+-	decrypt_round(aes_it_tab,-80)
+-dec192:	decrypt_round(aes_it_tab,-64)
+-	decrypt_round(aes_it_tab,-48)
+-dec128:	decrypt_round(aes_it_tab,-32)
+-	decrypt_round(aes_it_tab,-16)
+-	decrypt_round(aes_it_tab,  0)
+-	decrypt_round(aes_it_tab, 16)
+-	decrypt_round(aes_it_tab, 32)
+-	decrypt_round(aes_it_tab, 48)
+-	decrypt_round(aes_it_tab, 64)
+-	decrypt_round(aes_it_tab, 80)
+-	decrypt_round(aes_it_tab, 96)
+-	decrypt_final(aes_il_tab,112)
++	decrypt_round(crypto_it_tab,-96)
++	decrypt_round(crypto_it_tab,-80)
++dec192:	decrypt_round(crypto_it_tab,-64)
++	decrypt_round(crypto_it_tab,-48)
++dec128:	decrypt_round(crypto_it_tab,-32)
++	decrypt_round(crypto_it_tab,-16)
++	decrypt_round(crypto_it_tab,  0)
++	decrypt_round(crypto_it_tab, 16)
++	decrypt_round(crypto_it_tab, 32)
++	decrypt_round(crypto_it_tab, 48)
++	decrypt_round(crypto_it_tab, 64)
++	decrypt_round(crypto_it_tab, 80)
++	decrypt_round(crypto_it_tab, 96)
++	decrypt_final(crypto_il_tab,112)
+ 	return
+diff --git a/arch/x86/crypto/aes_32.c b/arch/x86/crypto/aes_32.c
+deleted file mode 100644
+index 49aad93..0000000
+--- a/arch/x86/crypto/aes_32.c
++++ /dev/null
+@@ -1,515 +0,0 @@
+-/* 
+- * 
+- * Glue Code for optimized 586 assembler version of AES
+- *
+- * Copyright (c) 2002, Dr Brian Gladman <>, Worcester, UK.
+- * All rights reserved.
+- *
+- * LICENSE TERMS
+- *
+- * The free distribution and use of this software in both source and binary
+- * form is allowed (with or without changes) provided that:
+- *
+- *   1. distributions of this source code include the above copyright
+- *      notice, this list of conditions and the following disclaimer;
+- *
+- *   2. distributions in binary form include the above copyright
+- *      notice, this list of conditions and the following disclaimer
+- *      in the documentation and/or other associated materials;
+- *
+- *   3. the copyright holder's name is not used to endorse products
+- *      built using this software without specific written permission.
+- *
+- * ALTERNATIVELY, provided that this notice is retained in full, this product
+- * may be distributed under the terms of the GNU General Public License (GPL),
+- * in which case the provisions of the GPL apply INSTEAD OF those given above.
+- *
+- * DISCLAIMER
+- *
+- * This software is provided 'as is' with no explicit or implied warranties
+- * in respect of its properties, including, but not limited to, correctness
+- * and/or fitness for purpose.
+- *
+- * Copyright (c) 2003, Adam J. Richter <adam at yggdrasil.com> (conversion to
+- * 2.5 API).
+- * Copyright (c) 2003, 2004 Fruhwirth Clemens <clemens at endorphin.org>
+- * Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris at redhat.com>
+- *
+- */
+-
+-#include <asm/byteorder.h>
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/types.h>
+-#include <linux/crypto.h>
+-#include <linux/linkage.h>
+-
+-asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+-asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+-
+-#define AES_MIN_KEY_SIZE	16
+-#define AES_MAX_KEY_SIZE	32
+-#define AES_BLOCK_SIZE		16
+-#define AES_KS_LENGTH		4 * AES_BLOCK_SIZE
+-#define RC_LENGTH		29
+-
+-struct aes_ctx {
+-	u32 ekey[AES_KS_LENGTH];
+-	u32 rounds;
+-	u32 dkey[AES_KS_LENGTH];
+-};
+-
+-#define WPOLY 0x011b
+-#define bytes2word(b0, b1, b2, b3)  \
+-	(((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0))
+-
+-/* define the finite field multiplies required for Rijndael */
+-#define f2(x) ((x) ? pow[log[x] + 0x19] : 0)
+-#define f3(x) ((x) ? pow[log[x] + 0x01] : 0)
+-#define f9(x) ((x) ? pow[log[x] + 0xc7] : 0)
+-#define fb(x) ((x) ? pow[log[x] + 0x68] : 0)
+-#define fd(x) ((x) ? pow[log[x] + 0xee] : 0)
+-#define fe(x) ((x) ? pow[log[x] + 0xdf] : 0)
+-#define fi(x) ((x) ?   pow[255 - log[x]]: 0)
+-
+-static inline u32 upr(u32 x, int n)
+-{
+-	return (x << 8 * n) | (x >> (32 - 8 * n));
+-}
+-
+-static inline u8 bval(u32 x, int n)
+-{
+-	return x >> 8 * n;
+-}
+-
+-/* The forward and inverse affine transformations used in the S-box */
+-#define fwd_affine(x) \
+-	(w = (u32)x, w ^= (w<<1)^(w<<2)^(w<<3)^(w<<4), 0x63^(u8)(w^(w>>8)))
+-
+-#define inv_affine(x) \
+-	(w = (u32)x, w = (w<<1)^(w<<3)^(w<<6), 0x05^(u8)(w^(w>>8)))
+-
+-static u32 rcon_tab[RC_LENGTH];
+-
+-u32 ft_tab[4][256];
+-u32 fl_tab[4][256];
+-static u32 im_tab[4][256];
+-u32 il_tab[4][256];
+-u32 it_tab[4][256];
+-
+-static void gen_tabs(void)
+-{
+-	u32 i, w;
+-	u8 pow[512], log[256];
+-
+-	/*
+-	 * log and power tables for GF(2^8) finite field with
+-	 * WPOLY as modular polynomial - the simplest primitive
+-	 * root is 0x03, used here to generate the tables.
+-	 */
+-	i = 0; w = 1; 
+-	
+-	do {
+-		pow[i] = (u8)w;
+-		pow[i + 255] = (u8)w;
+-		log[w] = (u8)i++;
+-		w ^=  (w << 1) ^ (w & 0x80 ? WPOLY : 0);
+-	} while (w != 1);
+-	
+-	for(i = 0, w = 1; i < RC_LENGTH; ++i) {
+-		rcon_tab[i] = bytes2word(w, 0, 0, 0);
+-		w = f2(w);
+-	}
+-
+-	for(i = 0; i < 256; ++i) {
+-		u8 b;
+-		
+-		b = fwd_affine(fi((u8)i));
+-		w = bytes2word(f2(b), b, b, f3(b));
+-
+-		/* tables for a normal encryption round */
+-		ft_tab[0][i] = w;
+-		ft_tab[1][i] = upr(w, 1);
+-		ft_tab[2][i] = upr(w, 2);
+-		ft_tab[3][i] = upr(w, 3);
+-		w = bytes2word(b, 0, 0, 0);
+-		
+-		/*
+-		 * tables for last encryption round
+-		 * (may also be used in the key schedule)
+-		 */
+-		fl_tab[0][i] = w;
+-		fl_tab[1][i] = upr(w, 1);
+-		fl_tab[2][i] = upr(w, 2);
+-		fl_tab[3][i] = upr(w, 3);
+-		
+-		b = fi(inv_affine((u8)i));
+-		w = bytes2word(fe(b), f9(b), fd(b), fb(b));
+-
+-		/* tables for the inverse mix column operation  */
+-		im_tab[0][b] = w;
+-		im_tab[1][b] = upr(w, 1);
+-		im_tab[2][b] = upr(w, 2);
+-		im_tab[3][b] = upr(w, 3);
+-
+-		/* tables for a normal decryption round */
+-		it_tab[0][i] = w;
+-		it_tab[1][i] = upr(w,1);
+-		it_tab[2][i] = upr(w,2);
+-		it_tab[3][i] = upr(w,3);
+-
+-		w = bytes2word(b, 0, 0, 0);
+-		
+-		/* tables for last decryption round */
+-		il_tab[0][i] = w;
+-		il_tab[1][i] = upr(w,1);
+-		il_tab[2][i] = upr(w,2);
+-		il_tab[3][i] = upr(w,3);
+-    }
+-}
+-
+-#define four_tables(x,tab,vf,rf,c)		\
+-(	tab[0][bval(vf(x,0,c),rf(0,c))]	^	\
+-	tab[1][bval(vf(x,1,c),rf(1,c))] ^	\
+-	tab[2][bval(vf(x,2,c),rf(2,c))] ^	\
+-	tab[3][bval(vf(x,3,c),rf(3,c))]		\
+-)
+-
+-#define vf1(x,r,c)  (x)
+-#define rf1(r,c)    (r)
+-#define rf2(r,c)    ((r-c)&3)
+-
+-#define inv_mcol(x) four_tables(x,im_tab,vf1,rf1,0)
+-#define ls_box(x,c) four_tables(x,fl_tab,vf1,rf2,c)
+-
+-#define ff(x) inv_mcol(x)
+-
+-#define ke4(k,i)							\
+-{									\
+-	k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i];		\
+-	k[4*(i)+5] = ss[1] ^= ss[0];					\
+-	k[4*(i)+6] = ss[2] ^= ss[1];					\
+-	k[4*(i)+7] = ss[3] ^= ss[2];					\
+-}
+-
+-#define kel4(k,i)							\
+-{									\
+-	k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ rcon_tab[i];		\
+-	k[4*(i)+5] = ss[1] ^= ss[0];					\
+-	k[4*(i)+6] = ss[2] ^= ss[1]; k[4*(i)+7] = ss[3] ^= ss[2];	\
+-}
+-
+-#define ke6(k,i)							\
+-{									\
+-	k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];		\
+-	k[6*(i)+ 7] = ss[1] ^= ss[0];					\
+-	k[6*(i)+ 8] = ss[2] ^= ss[1];					\
+-	k[6*(i)+ 9] = ss[3] ^= ss[2];					\
+-	k[6*(i)+10] = ss[4] ^= ss[3];					\
+-	k[6*(i)+11] = ss[5] ^= ss[4];					\
+-}
+-
+-#define kel6(k,i)							\
+-{									\
+-	k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];		\
+-	k[6*(i)+ 7] = ss[1] ^= ss[0];					\
+-	k[6*(i)+ 8] = ss[2] ^= ss[1];					\
+-	k[6*(i)+ 9] = ss[3] ^= ss[2];					\
+-}
+-
+-#define ke8(k,i)							\
+-{									\
+-	k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];		\
+-	k[8*(i)+ 9] = ss[1] ^= ss[0];					\
+-	k[8*(i)+10] = ss[2] ^= ss[1];					\
+-	k[8*(i)+11] = ss[3] ^= ss[2];					\
+-	k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0);				\
+-	k[8*(i)+13] = ss[5] ^= ss[4];					\
+-	k[8*(i)+14] = ss[6] ^= ss[5];					\
+-	k[8*(i)+15] = ss[7] ^= ss[6];					\
+-}
+-
+-#define kel8(k,i)							\
+-{									\
+-	k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];		\
+-	k[8*(i)+ 9] = ss[1] ^= ss[0];					\
+-	k[8*(i)+10] = ss[2] ^= ss[1];					\
+-	k[8*(i)+11] = ss[3] ^= ss[2];					\
+-}
+-
+-#define kdf4(k,i)							\
+-{									\
+-	ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3];				\
+-	ss[1] = ss[1] ^ ss[3];						\
+-	ss[2] = ss[2] ^ ss[3];						\
+-	ss[3] = ss[3];							\
+-	ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i];			\
+-	ss[i % 4] ^= ss[4];						\
+-	ss[4] ^= k[4*(i)];						\
+-	k[4*(i)+4] = ff(ss[4]);						\
+-	ss[4] ^= k[4*(i)+1];						\
+-	k[4*(i)+5] = ff(ss[4]);						\
+-	ss[4] ^= k[4*(i)+2];						\
+-	k[4*(i)+6] = ff(ss[4]);						\
+-	ss[4] ^= k[4*(i)+3];						\
+-	k[4*(i)+7] = ff(ss[4]);						\
+-}
+-
+-#define kd4(k,i)							\
+-{									\
+-	ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i];			\
+-	ss[i % 4] ^= ss[4];						\
+-	ss[4] = ff(ss[4]);						\
+-	k[4*(i)+4] = ss[4] ^= k[4*(i)];					\
+-	k[4*(i)+5] = ss[4] ^= k[4*(i)+1];				\
+-	k[4*(i)+6] = ss[4] ^= k[4*(i)+2];				\
+-	k[4*(i)+7] = ss[4] ^= k[4*(i)+3];				\
+-}
+-
+-#define kdl4(k,i)							\
+-{									\
+-	ss[4] = ls_box(ss[(i+3) % 4], 3) ^ rcon_tab[i];			\
+-	ss[i % 4] ^= ss[4];						\
+-	k[4*(i)+4] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3];			\
+-	k[4*(i)+5] = ss[1] ^ ss[3];					\
+-	k[4*(i)+6] = ss[0];						\
+-	k[4*(i)+7] = ss[1];						\
+-}
+-
+-#define kdf6(k,i)							\
+-{									\
+-	ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];				\
+-	k[6*(i)+ 6] = ff(ss[0]);					\
+-	ss[1] ^= ss[0];							\
+-	k[6*(i)+ 7] = ff(ss[1]);					\
+-	ss[2] ^= ss[1];							\
+-	k[6*(i)+ 8] = ff(ss[2]);					\
+-	ss[3] ^= ss[2];							\
+-	k[6*(i)+ 9] = ff(ss[3]);					\
+-	ss[4] ^= ss[3];							\
+-	k[6*(i)+10] = ff(ss[4]);					\
+-	ss[5] ^= ss[4];							\
+-	k[6*(i)+11] = ff(ss[5]);					\
+-}
+-
+-#define kd6(k,i)							\
+-{									\
+-	ss[6] = ls_box(ss[5],3) ^ rcon_tab[i];				\
+-	ss[0] ^= ss[6]; ss[6] = ff(ss[6]);				\
+-	k[6*(i)+ 6] = ss[6] ^= k[6*(i)];				\
+-	ss[1] ^= ss[0];							\
+-	k[6*(i)+ 7] = ss[6] ^= k[6*(i)+ 1];				\
+-	ss[2] ^= ss[1];							\
+-	k[6*(i)+ 8] = ss[6] ^= k[6*(i)+ 2];				\
+-	ss[3] ^= ss[2];							\
+-	k[6*(i)+ 9] = ss[6] ^= k[6*(i)+ 3];				\
+-	ss[4] ^= ss[3];							\
+-	k[6*(i)+10] = ss[6] ^= k[6*(i)+ 4];				\
+-	ss[5] ^= ss[4];							\
+-	k[6*(i)+11] = ss[6] ^= k[6*(i)+ 5];				\
+-}
+-
+-#define kdl6(k,i)							\
+-{									\
+-	ss[0] ^= ls_box(ss[5],3) ^ rcon_tab[i];				\
+-	k[6*(i)+ 6] = ss[0];						\
+-	ss[1] ^= ss[0];							\
+-	k[6*(i)+ 7] = ss[1];						\
+-	ss[2] ^= ss[1];							\
+-	k[6*(i)+ 8] = ss[2];						\
+-	ss[3] ^= ss[2];							\
+-	k[6*(i)+ 9] = ss[3];						\
+-}
+-
+-#define kdf8(k,i)							\
+-{									\
+-	ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];				\
+-	k[8*(i)+ 8] = ff(ss[0]);					\
+-	ss[1] ^= ss[0];							\
+-	k[8*(i)+ 9] = ff(ss[1]);					\
+-	ss[2] ^= ss[1];							\
+-	k[8*(i)+10] = ff(ss[2]);					\
+-	ss[3] ^= ss[2];							\
+-	k[8*(i)+11] = ff(ss[3]);					\
+-	ss[4] ^= ls_box(ss[3],0);					\
+-	k[8*(i)+12] = ff(ss[4]);					\
+-	ss[5] ^= ss[4];							\
+-	k[8*(i)+13] = ff(ss[5]);					\
+-	ss[6] ^= ss[5];							\
+-	k[8*(i)+14] = ff(ss[6]);					\
+-	ss[7] ^= ss[6];							\
+-	k[8*(i)+15] = ff(ss[7]);					\
+-}
+-
+-#define kd8(k,i)							\
+-{									\
+-	u32 __g = ls_box(ss[7],3) ^ rcon_tab[i];			\
+-	ss[0] ^= __g;							\
+-	__g = ff(__g);							\
+-	k[8*(i)+ 8] = __g ^= k[8*(i)];					\
+-	ss[1] ^= ss[0];							\
+-	k[8*(i)+ 9] = __g ^= k[8*(i)+ 1];				\
+-	ss[2] ^= ss[1];							\
+-	k[8*(i)+10] = __g ^= k[8*(i)+ 2];				\
+-	ss[3] ^= ss[2];							\
+-	k[8*(i)+11] = __g ^= k[8*(i)+ 3];				\
+-	__g = ls_box(ss[3],0);						\
+-	ss[4] ^= __g;							\
+-	__g = ff(__g);							\
+-	k[8*(i)+12] = __g ^= k[8*(i)+ 4];				\
+-	ss[5] ^= ss[4];							\
+-	k[8*(i)+13] = __g ^= k[8*(i)+ 5];				\
+-	ss[6] ^= ss[5];							\
+-	k[8*(i)+14] = __g ^= k[8*(i)+ 6];				\
+-	ss[7] ^= ss[6];							\
+-	k[8*(i)+15] = __g ^= k[8*(i)+ 7];				\
+-}
+-
+-#define kdl8(k,i)							\
+-{									\
+-	ss[0] ^= ls_box(ss[7],3) ^ rcon_tab[i];				\
+-	k[8*(i)+ 8] = ss[0];						\
+-	ss[1] ^= ss[0];							\
+-	k[8*(i)+ 9] = ss[1];						\
+-	ss[2] ^= ss[1];							\
+-	k[8*(i)+10] = ss[2];						\
+-	ss[3] ^= ss[2];							\
+-	k[8*(i)+11] = ss[3];						\
+-}
+-
+-static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+-		       unsigned int key_len)
+-{
+-	int i;
+-	u32 ss[8];
+-	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+-	const __le32 *key = (const __le32 *)in_key;
+-	u32 *flags = &tfm->crt_flags;
+-
+-	/* encryption schedule */
+-	
+-	ctx->ekey[0] = ss[0] = le32_to_cpu(key[0]);
+-	ctx->ekey[1] = ss[1] = le32_to_cpu(key[1]);
+-	ctx->ekey[2] = ss[2] = le32_to_cpu(key[2]);
+-	ctx->ekey[3] = ss[3] = le32_to_cpu(key[3]);
+-
+-	switch(key_len) {
+-	case 16:
+-		for (i = 0; i < 9; i++)
+-			ke4(ctx->ekey, i);
+-		kel4(ctx->ekey, 9);
+-		ctx->rounds = 10;
+-		break;
+-		
+-	case 24:
+-		ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
+-		ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
+-		for (i = 0; i < 7; i++)
+-			ke6(ctx->ekey, i);
+-		kel6(ctx->ekey, 7); 
+-		ctx->rounds = 12;
+-		break;
+-
+-	case 32:
+-		ctx->ekey[4] = ss[4] = le32_to_cpu(key[4]);
+-		ctx->ekey[5] = ss[5] = le32_to_cpu(key[5]);
+-		ctx->ekey[6] = ss[6] = le32_to_cpu(key[6]);
+-		ctx->ekey[7] = ss[7] = le32_to_cpu(key[7]);
+-		for (i = 0; i < 6; i++)
+-			ke8(ctx->ekey, i);
+-		kel8(ctx->ekey, 6);
+-		ctx->rounds = 14;
+-		break;
+-
+-	default:
+-		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+-		return -EINVAL;
+-	}
+-	
+-	/* decryption schedule */
+-	
+-	ctx->dkey[0] = ss[0] = le32_to_cpu(key[0]);
+-	ctx->dkey[1] = ss[1] = le32_to_cpu(key[1]);
+-	ctx->dkey[2] = ss[2] = le32_to_cpu(key[2]);
+-	ctx->dkey[3] = ss[3] = le32_to_cpu(key[3]);
+-
+-	switch (key_len) {
+-	case 16:
+-		kdf4(ctx->dkey, 0);
+-		for (i = 1; i < 9; i++)
+-			kd4(ctx->dkey, i);
+-		kdl4(ctx->dkey, 9);
+-		break;
+-		
+-	case 24:
+-		ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
+-		ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
+-		kdf6(ctx->dkey, 0);
+-		for (i = 1; i < 7; i++)
+-			kd6(ctx->dkey, i);
+-		kdl6(ctx->dkey, 7);
+-		break;
+-
+-	case 32:
+-		ctx->dkey[4] = ff(ss[4] = le32_to_cpu(key[4]));
+-		ctx->dkey[5] = ff(ss[5] = le32_to_cpu(key[5]));
+-		ctx->dkey[6] = ff(ss[6] = le32_to_cpu(key[6]));
+-		ctx->dkey[7] = ff(ss[7] = le32_to_cpu(key[7]));
+-		kdf8(ctx->dkey, 0);
+-		for (i = 1; i < 6; i++)
+-			kd8(ctx->dkey, i);
+-		kdl8(ctx->dkey, 6);
+-		break;
+-	}
+-	return 0;
+-}
+-
+-static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+-{
+-	aes_enc_blk(tfm, dst, src);
+-}
+-
+-static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+-{
+-	aes_dec_blk(tfm, dst, src);
+-}
+-
+-static struct crypto_alg aes_alg = {
+-	.cra_name		=	"aes",
+-	.cra_driver_name	=	"aes-i586",
+-	.cra_priority		=	200,
+-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+-	.cra_blocksize		=	AES_BLOCK_SIZE,
+-	.cra_ctxsize		=	sizeof(struct aes_ctx),
+-	.cra_module		=	THIS_MODULE,
+-	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
+-	.cra_u			=	{
+-		.cipher = {
+-			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
+-			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
+-			.cia_setkey	   	= 	aes_set_key,
+-			.cia_encrypt	 	=	aes_encrypt,
+-			.cia_decrypt	  	=	aes_decrypt
+-		}
+-	}
+-};
+-
+-static int __init aes_init(void)
+-{
+-	gen_tabs();
+-	return crypto_register_alg(&aes_alg);
+-}
+-
+-static void __exit aes_fini(void)
+-{
+-	crypto_unregister_alg(&aes_alg);
+-}
+-
+-module_init(aes_init);
+-module_exit(aes_fini);
+-
+-MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, i586 asm optimized");
+-MODULE_LICENSE("Dual BSD/GPL");
+-MODULE_AUTHOR("Fruhwirth Clemens, James Morris, Brian Gladman, Adam Richter");
+-MODULE_ALIAS("aes");
+diff --git a/arch/x86/crypto/aes_64.c b/arch/x86/crypto/aes_64.c
+deleted file mode 100644
+index 5cdb13e..0000000
+--- a/arch/x86/crypto/aes_64.c
++++ /dev/null
+@@ -1,336 +0,0 @@
+-/*
+- * Cryptographic API.
+- *
+- * AES Cipher Algorithm.
+- *
+- * Based on Brian Gladman's code.
+- *
+- * Linux developers:
+- *  Alexander Kjeldaas <astor at fast.no>
+- *  Herbert Valerio Riedel <hvr at hvrlab.org>
+- *  Kyle McMartin <kyle at debian.org>
+- *  Adam J. Richter <adam at yggdrasil.com> (conversion to 2.5 API).
+- *  Andreas Steinmetz <ast at domdv.de> (adapted to x86_64 assembler)
+- *
+- * 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.
+- *
+- * ---------------------------------------------------------------------------
+- * Copyright (c) 2002, Dr Brian Gladman <brg at gladman.me.uk>, Worcester, UK.
+- * All rights reserved.
+- *
+- * LICENSE TERMS
+- *
+- * The free distribution and use of this software in both source and binary
+- * form is allowed (with or without changes) provided that:
+- *
+- *   1. distributions of this source code include the above copyright
+- *      notice, this list of conditions and the following disclaimer;
+- *
+- *   2. distributions in binary form include the above copyright
+- *      notice, this list of conditions and the following disclaimer
+- *      in the documentation and/or other associated materials;
+- *
+- *   3. the copyright holder's name is not used to endorse products
+- *      built using this software without specific written permission.
+- *
+- * ALTERNATIVELY, provided that this notice is retained in full, this product
+- * may be distributed under the terms of the GNU General Public License (GPL),
+- * in which case the provisions of the GPL apply INSTEAD OF those given above.
+- *
+- * DISCLAIMER
+- *
+- * This software is provided 'as is' with no explicit or implied warranties
+- * in respect of its properties, including, but not limited to, correctness
+- * and/or fitness for purpose.
+- * ---------------------------------------------------------------------------
+- */
+-
+-/* Some changes from the Gladman version:
+-    s/RIJNDAEL(e_key)/E_KEY/g
+-    s/RIJNDAEL(d_key)/D_KEY/g
+-*/
+-
+-#include <asm/byteorder.h>
+-#include <linux/bitops.h>
+-#include <linux/crypto.h>
+-#include <linux/errno.h>
+-#include <linux/init.h>
+-#include <linux/module.h>
+-#include <linux/types.h>
+-
+-#define AES_MIN_KEY_SIZE	16
+-#define AES_MAX_KEY_SIZE	32
+-
+-#define AES_BLOCK_SIZE		16
+-
+-/*
+- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8)))
+- */
+-static inline u8 byte(const u32 x, const unsigned n)
+-{
+-	return x >> (n << 3);
+-}
+-
+-struct aes_ctx
+-{
+-	u32 key_length;
+-	u32 buf[120];
+-};
+-
+-#define E_KEY (&ctx->buf[0])
+-#define D_KEY (&ctx->buf[60])
+-
+-static u8 pow_tab[256] __initdata;
+-static u8 log_tab[256] __initdata;
+-static u8 sbx_tab[256] __initdata;
+-static u8 isb_tab[256] __initdata;
+-static u32 rco_tab[10];
+-u32 aes_ft_tab[4][256];
+-u32 aes_it_tab[4][256];
+-
+-u32 aes_fl_tab[4][256];
+-u32 aes_il_tab[4][256];
+-
+-static inline u8 f_mult(u8 a, u8 b)
+-{
+-	u8 aa = log_tab[a], cc = aa + log_tab[b];
+-
+-	return pow_tab[cc + (cc < aa ? 1 : 0)];
+-}
+-
+-#define ff_mult(a, b) (a && b ? f_mult(a, b) : 0)
+-
+-#define ls_box(x)				\
+-	(aes_fl_tab[0][byte(x, 0)] ^		\
+-	 aes_fl_tab[1][byte(x, 1)] ^		\
+-	 aes_fl_tab[2][byte(x, 2)] ^		\
+-	 aes_fl_tab[3][byte(x, 3)])
+-
+-static void __init gen_tabs(void)
+-{
+-	u32 i, t;
+-	u8 p, q;
+-
+-	/* log and power tables for GF(2**8) finite field with
+-	   0x011b as modular polynomial - the simplest primitive
+-	   root is 0x03, used here to generate the tables */
+-
+-	for (i = 0, p = 1; i < 256; ++i) {
+-		pow_tab[i] = (u8)p;
+-		log_tab[p] = (u8)i;
+-
+-		p ^= (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+-	}
+-
+-	log_tab[1] = 0;
+-
+-	for (i = 0, p = 1; i < 10; ++i) {
+-		rco_tab[i] = p;
+-
+-		p = (p << 1) ^ (p & 0x80 ? 0x01b : 0);
+-	}
+-
+-	for (i = 0; i < 256; ++i) {
+-		p = (i ? pow_tab[255 - log_tab[i]] : 0);
+-		q = ((p >> 7) | (p << 1)) ^ ((p >> 6) | (p << 2));
+-		p ^= 0x63 ^ q ^ ((q >> 6) | (q << 2));
+-		sbx_tab[i] = p;
+-		isb_tab[p] = (u8)i;
+-	}
+-
+-	for (i = 0; i < 256; ++i) {
+-		p = sbx_tab[i];
+-
+-		t = p;
+-		aes_fl_tab[0][i] = t;
+-		aes_fl_tab[1][i] = rol32(t, 8);
+-		aes_fl_tab[2][i] = rol32(t, 16);
+-		aes_fl_tab[3][i] = rol32(t, 24);
+-
+-		t = ((u32)ff_mult(2, p)) |
+-		    ((u32)p << 8) |
+-		    ((u32)p << 16) | ((u32)ff_mult(3, p) << 24);
+-
+-		aes_ft_tab[0][i] = t;
+-		aes_ft_tab[1][i] = rol32(t, 8);
+-		aes_ft_tab[2][i] = rol32(t, 16);
+-		aes_ft_tab[3][i] = rol32(t, 24);
+-
+-		p = isb_tab[i];
+-
+-		t = p;
+-		aes_il_tab[0][i] = t;
+-		aes_il_tab[1][i] = rol32(t, 8);
+-		aes_il_tab[2][i] = rol32(t, 16);
+-		aes_il_tab[3][i] = rol32(t, 24);
+-
+-		t = ((u32)ff_mult(14, p)) |
+-		    ((u32)ff_mult(9, p) << 8) |
+-		    ((u32)ff_mult(13, p) << 16) |
+-		    ((u32)ff_mult(11, p) << 24);
+-
+-		aes_it_tab[0][i] = t;
+-		aes_it_tab[1][i] = rol32(t, 8);
+-		aes_it_tab[2][i] = rol32(t, 16);
+-		aes_it_tab[3][i] = rol32(t, 24);
+-	}
+-}
+-
+-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+-
+-#define imix_col(y, x)			\
+-	u    = star_x(x);		\
+-	v    = star_x(u);		\
+-	w    = star_x(v);		\
+-	t    = w ^ (x);			\
+-	(y)  = u ^ v ^ w;		\
+-	(y) ^= ror32(u ^ t,  8) ^	\
+-	       ror32(v ^ t, 16) ^	\
+-	       ror32(t, 24)
+-
+-/* initialise the key schedule from the user supplied key */
+-
+-#define loop4(i)					\
+-{							\
+-	t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];	\
+-	t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;	\
+-	t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;	\
+-	t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;	\
+-	t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;	\
+-}
+-
+-#define loop6(i)					\
+-{							\
+-	t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];	\
+-	t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;	\
+-	t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;	\
+-	t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;	\
+-	t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;	\
+-	t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;	\
+-	t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;	\
+-}
+-
+-#define loop8(i)					\
+-{							\
+-	t = ror32(t,  8); ; t = ls_box(t) ^ rco_tab[i];	\
+-	t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;	\
+-	t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;	\
+-	t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;	\
+-	t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;	\
+-	t  = E_KEY[8 * i + 4] ^ ls_box(t);		\
+-	E_KEY[8 * i + 12] = t;				\
+-	t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;	\
+-	t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;	\
+-	t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;	\
+-}
+-
+-static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+-		       unsigned int key_len)
+-{
+-	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
+-	const __le32 *key = (const __le32 *)in_key;
+-	u32 *flags = &tfm->crt_flags;
+-	u32 i, j, t, u, v, w;
+-
+-	if (key_len % 8) {
+-		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+-		return -EINVAL;
+-	}
+-
+-	ctx->key_length = key_len;
+-
+-	D_KEY[key_len + 24] = E_KEY[0] = le32_to_cpu(key[0]);
+-	D_KEY[key_len + 25] = E_KEY[1] = le32_to_cpu(key[1]);
+-	D_KEY[key_len + 26] = E_KEY[2] = le32_to_cpu(key[2]);
+-	D_KEY[key_len + 27] = E_KEY[3] = le32_to_cpu(key[3]);
+-
+-	switch (key_len) {
+-	case 16:
+-		t = E_KEY[3];
+-		for (i = 0; i < 10; ++i)
+-			loop4(i);
+-		break;
+-
+-	case 24:
+-		E_KEY[4] = le32_to_cpu(key[4]);
+-		t = E_KEY[5] = le32_to_cpu(key[5]);
+-		for (i = 0; i < 8; ++i)
+-			loop6 (i);
+-		break;
+-
+-	case 32:
+-		E_KEY[4] = le32_to_cpu(key[4]);
+-		E_KEY[5] = le32_to_cpu(key[5]);
+-		E_KEY[6] = le32_to_cpu(key[6]);
+-		t = E_KEY[7] = le32_to_cpu(key[7]);
+-		for (i = 0; i < 7; ++i)
+-			loop8(i);
+-		break;
+-	}
+-
+-	D_KEY[0] = E_KEY[key_len + 24];
+-	D_KEY[1] = E_KEY[key_len + 25];
+-	D_KEY[2] = E_KEY[key_len + 26];
+-	D_KEY[3] = E_KEY[key_len + 27];
+-
+-	for (i = 4; i < key_len + 24; ++i) {
+-		j = key_len + 24 - (i & ~3) + (i & 3);
+-		imix_col(D_KEY[j], E_KEY[i]);
+-	}
+-
+-	return 0;
+-}
+-
+-asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+-asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
+-
+-static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+-{
+-	aes_enc_blk(tfm, dst, src);
+-}
+-
+-static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+-{
+-	aes_dec_blk(tfm, dst, src);
+-}
+-
+-static struct crypto_alg aes_alg = {
+-	.cra_name		=	"aes",
+-	.cra_driver_name	=	"aes-x86_64",
+-	.cra_priority		=	200,
+-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+-	.cra_blocksize		=	AES_BLOCK_SIZE,
+-	.cra_ctxsize		=	sizeof(struct aes_ctx),
+-	.cra_module		=	THIS_MODULE,
+-	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
+-	.cra_u			=	{
+-		.cipher = {
+-			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
+-			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
+-			.cia_setkey	   	= 	aes_set_key,
+-			.cia_encrypt	 	=	aes_encrypt,
+-			.cia_decrypt	  	=	aes_decrypt
+-		}
+-	}
+-};
+-
+-static int __init aes_init(void)
+-{
+-	gen_tabs();
+-	return crypto_register_alg(&aes_alg);
+-}
+-
+-static void __exit aes_fini(void)
+-{
+-	crypto_unregister_alg(&aes_alg);
+-}
+-
+-module_init(aes_init);
+-module_exit(aes_fini);
+-
+-MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
+-MODULE_LICENSE("GPL");
+-MODULE_ALIAS("aes");
+diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
+new file mode 100644
+index 0000000..71f4578
+--- /dev/null
++++ b/arch/x86/crypto/aes_glue.c
+@@ -0,0 +1,57 @@
++/*
++ * Glue Code for the asm optimized version of the AES Cipher Algorithm
++ *
++ */
++
++#include <crypto/aes.h>
++
++asmlinkage void aes_enc_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
++asmlinkage void aes_dec_blk(struct crypto_tfm *tfm, u8 *out, const u8 *in);
++
++static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++{
++	aes_enc_blk(tfm, dst, src);
++}
++
++static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
++{
++	aes_dec_blk(tfm, dst, src);
++}
++
++static struct crypto_alg aes_alg = {
++	.cra_name		= "aes",
++	.cra_driver_name	= "aes-asm",
++	.cra_priority		= 200,
++	.cra_flags		= CRYPTO_ALG_TYPE_CIPHER,
++	.cra_blocksize		= AES_BLOCK_SIZE,
++	.cra_ctxsize		= sizeof(struct crypto_aes_ctx),
++	.cra_module		= THIS_MODULE,
++	.cra_list		= LIST_HEAD_INIT(aes_alg.cra_list),
++	.cra_u	= {
++		.cipher	= {
++			.cia_min_keysize	= AES_MIN_KEY_SIZE,
++			.cia_max_keysize	= AES_MAX_KEY_SIZE,
++			.cia_setkey		= crypto_aes_set_key,
++			.cia_encrypt		= aes_encrypt,
++			.cia_decrypt		= aes_decrypt
++		}
++	}
++};
++
++static int __init aes_init(void)
++{
++	return crypto_register_alg(&aes_alg);
++}
++
++static void __exit aes_fini(void)
++{
++	crypto_unregister_alg(&aes_alg);
++}
++
++module_init(aes_init);
++module_exit(aes_fini);
++
++MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("aes");
++MODULE_ALIAS("aes-asm");
+diff --git a/arch/x86/crypto/salsa20-i586-asm_32.S b/arch/x86/crypto/salsa20-i586-asm_32.S
+new file mode 100644
+index 0000000..72eb306
+--- /dev/null
 +++ b/arch/x86/crypto/salsa20-i586-asm_32.S
 @@ -0,0 +1,1114 @@
 +# salsa20_pm.s version 20051229
@@ -258836,7 +282788,7 @@
  
  	return 0;
 diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
-index df588f0..0db0a62 100644
+index df588f0..8022d3c 100644
 --- a/arch/x86/ia32/ia32entry.S
 +++ b/arch/x86/ia32/ia32entry.S
 @@ -12,7 +12,6 @@
@@ -258885,6 +282837,17 @@
  	.quad compat_sys_io_setup	/* 245 */
  	.quad sys_io_destroy
  	.quad compat_sys_io_getevents
+@@ -723,7 +722,9 @@ ia32_sys_call_table:
+ 	.quad sys_epoll_pwait
+ 	.quad compat_sys_utimensat	/* 320 */
+ 	.quad compat_sys_signalfd
+-	.quad compat_sys_timerfd
++	.quad sys_timerfd_create
+ 	.quad sys_eventfd
+ 	.quad sys32_fallocate
++	.quad compat_sys_timerfd_settime	/* 325 */
++	.quad compat_sys_timerfd_gettime
+ ia32_syscall_end:
 diff --git a/arch/x86/ia32/ipc32.c b/arch/x86/ia32/ipc32.c
 index 7b3342e..d21991c 100644
 --- a/arch/x86/ia32/ipc32.c
@@ -261087,10 +285050,10 @@
 -/* The ELF entry point can be used to set the AT_SYSINFO value.  */
 -ENTRY(__kernel_vsyscall);
 diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
-index 3857334..6f81300 100644
+index 3857334..21dc1a0 100644
 --- a/arch/x86/kernel/Makefile
 +++ b/arch/x86/kernel/Makefile
-@@ -1,9 +1,91 @@
+@@ -1,9 +1,93 @@
 -ifeq ($(CONFIG_X86_32),y)
 -include ${srctree}/arch/x86/kernel/Makefile_32
 -else
@@ -261134,7 +285097,8 @@
 +obj-$(CONFIG_X86_CPUID)		+= cpuid.o
 +obj-$(CONFIG_MICROCODE)		+= microcode.o
 +obj-$(CONFIG_PCI)		+= early-quirks.o
-+obj-$(CONFIG_APM)		+= apm_32.o
++apm-y				:= apm_32.o
++obj-$(CONFIG_APM)		+= apm.o
 +obj-$(CONFIG_X86_SMP)		+= smp_$(BITS).o smpboot_$(BITS).o tsc_sync.o
 +obj-$(CONFIG_X86_32_SMP)	+= smpcommon_32.o
 +obj-$(CONFIG_X86_64_SMP)	+= smp_64.o smpboot_64.o tsc_sync.o
@@ -261174,7 +285138,8 @@
 -# Workaround to delete .lds files with make clean
 -# The problem is that we do not enter Makefile_32 with make clean.
 -clean-files := vsyscall*.lds vsyscall*.so
-+obj-$(CONFIG_SCx200)		+= scx200_32.o
++obj-$(CONFIG_SCx200)		+= scx200.o
++scx200-y			+= scx200_32.o
 +
 +###
 +# 64 bit specific files
@@ -265460,6 +289425,18 @@
  #if !defined(CONFIG_SMP)
  	printk("CPU: ");
  	print_cpu_info(&boot_cpu_data);
+diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
+index cfdb2f3..a0c4d7c 100644
+--- a/arch/x86/kernel/cpu/Makefile
++++ b/arch/x86/kernel/cpu/Makefile
+@@ -3,6 +3,7 @@
+ #
+ 
+ obj-y			:= intel_cacheinfo.o addon_cpuid_features.o
++obj-y			+= feature_names.o
+ 
+ obj-$(CONFIG_X86_32)	+= common.o proc.o bugs.o
+ obj-$(CONFIG_X86_32)	+= amd.o
 diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c
 index 3e91d3e..238468a 100644
 --- a/arch/x86/kernel/cpu/addon_cpuid_features.c
@@ -265561,7 +289538,7 @@
  #endif
  
 diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
-index e2fcf20..b7b2142 100644
+index e2fcf20..d9313d9 100644
 --- a/arch/x86/kernel/cpu/common.c
 +++ b/arch/x86/kernel/cpu/common.c
 @@ -22,43 +22,48 @@
@@ -265674,7 +289651,7 @@
  
  	c->x86 = 4;
  	if (c->cpuid_level >= 0x00000001) {
-@@ -277,9 +274,38 @@ void __init cpu_detect(struct cpuinfo_x86 *c)
+@@ -277,10 +274,39 @@ void __init cpu_detect(struct cpuinfo_x86 *c)
  		if (c->x86 >= 0x6)
  			c->x86_model += ((tfms >> 16) & 0xF) << 4;
  		c->x86_mask = tfms & 15;
@@ -265683,8 +289660,8 @@
  			c->x86_cache_alignment = ((misc >> 8) & 0xff) * 8;
 +			c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
 +		}
-+	}
-+}
+ 	}
+ }
 +static void __cpuinit early_get_cap(struct cpuinfo_x86 *c)
 +{
 +	u32 tfms, xlvl;
@@ -265709,11 +289686,12 @@
 +			}
 +		}
 +
- 	}
++	}
 +
- }
++}
  
  /* Do minimum CPU detection early.
+    Fields really needed: vendor, cpuid_level, family, model, mask, cache alignment.
 @@ -293,6 +319,7 @@ static void __init early_cpu_detect(void)
  	struct cpuinfo_x86 *c = &boot_cpu_data;
  
@@ -265891,7 +289869,24 @@
  cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
  
  /* This is hacky. :)
-@@ -620,21 +644,13 @@ void __init early_cpu_init(void)
+@@ -599,16 +623,6 @@ cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
+  * They will insert themselves into the cpu_devs structure.
+  * Then, when cpu_init() is called, we can just iterate over that array.
+  */
+-
+-extern int intel_cpu_init(void);
+-extern int cyrix_init_cpu(void);
+-extern int nsc_init_cpu(void);
+-extern int amd_init_cpu(void);
+-extern int centaur_init_cpu(void);
+-extern int transmeta_init_cpu(void);
+-extern int nexgen_init_cpu(void);
+-extern int umc_init_cpu(void);
+-
+ void __init early_cpu_init(void)
+ {
+ 	intel_cpu_init();
+@@ -620,21 +634,13 @@ void __init early_cpu_init(void)
  	nexgen_init_cpu();
  	umc_init_cpu();
  	early_cpu_detect();
@@ -265914,7 +289909,7 @@
  	return regs;
  }
  
-@@ -642,7 +658,7 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
+@@ -642,7 +648,7 @@ struct pt_regs * __devinit idle_regs(struct pt_regs *regs)
   * it's on the real one. */
  void switch_to_new_gdt(void)
  {
@@ -265923,7 +289918,7 @@
  
  	gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id());
  	gdt_descr.size = GDT_SIZE - 1;
-@@ -672,12 +688,6 @@ void __cpuinit cpu_init(void)
+@@ -672,12 +678,6 @@ void __cpuinit cpu_init(void)
  
  	if (cpu_has_vme || cpu_has_tsc || cpu_has_de)
  		clear_in_cr4(X86_CR4_VME|X86_CR4_PVI|X86_CR4_TSD|X86_CR4_DE);
@@ -265936,7 +289931,7 @@
  
  	load_idt(&idt_descr);
  	switch_to_new_gdt();
-@@ -691,7 +701,7 @@ void __cpuinit cpu_init(void)
+@@ -691,7 +691,7 @@ void __cpuinit cpu_init(void)
  		BUG();
  	enter_lazy_tlb(&init_mm, curr);
  
@@ -265946,17 +289941,27 @@
  	load_TR_desc();
  	load_LDT(&init_mm.context);
 diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
-index 2f6432c..ad6527a 100644
+index 2f6432c..e0b38c3 100644
 --- a/arch/x86/kernel/cpu/cpu.h
 +++ b/arch/x86/kernel/cpu/cpu.h
-@@ -24,5 +24,6 @@ extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
+@@ -24,5 +24,15 @@ extern struct cpu_dev * cpu_devs [X86_VENDOR_NUM];
  extern int get_model_name(struct cpuinfo_x86 *c);
  extern void display_cacheinfo(struct cpuinfo_x86 *c);
  
 -extern void early_intel_workaround(struct cpuinfo_x86 *c);
+-
 +extern void early_init_intel(struct cpuinfo_x86 *c);
 +extern void early_init_amd(struct cpuinfo_x86 *c);
- 
++
++/* Specific CPU type init functions */
++int intel_cpu_init(void);
++int amd_init_cpu(void);
++int cyrix_init_cpu(void);
++int nsc_init_cpu(void);
++int centaur_init_cpu(void);
++int transmeta_init_cpu(void);
++int nexgen_init_cpu(void);
++int umc_init_cpu(void);
 diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
 index fea0af0..a962dcb 100644
 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
@@ -266166,20 +290171,110 @@
  	/* CCR2 bit 2: lock NW bit and set WT1 */
  	setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x14 );
  }
+diff --git a/arch/x86/kernel/cpu/feature_names.c b/arch/x86/kernel/cpu/feature_names.c
+new file mode 100644
+index 0000000..ee975ac
+--- /dev/null
++++ b/arch/x86/kernel/cpu/feature_names.c
+@@ -0,0 +1,83 @@
++/*
++ * Strings for the various x86 capability flags.
++ *
++ * This file must not contain any executable code.
++ */
++
++#include "asm/cpufeature.h"
++
++/*
++ * These flag bits must match the definitions in <asm/cpufeature.h>.
++ * NULL means this bit is undefined or reserved; either way it doesn't
++ * have meaning as far as Linux is concerned.  Note that it's important
++ * to realize there is a difference between this table and CPUID -- if
++ * applications want to get the raw CPUID data, they should access
++ * /dev/cpu/<cpu_nr>/cpuid instead.
++ */
++const char * const x86_cap_flags[NCAPINTS*32] = {
++	/* Intel-defined */
++	"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
++	"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
++	"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
++	"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
++
++	/* AMD-defined */
++	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", "pdpe1gb", "rdtscp", NULL, "lm",
++	"3dnowext", "3dnow",
++
++	/* Transmeta-defined */
++	"recovery", "longrun", NULL, "lrti", 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,
++
++	/* Other (Linux-defined) */
++	"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
++	NULL, NULL, NULL, NULL,
++	"constant_tsc", "up", NULL, "arch_perfmon",
++	"pebs", "bts", NULL, NULL,
++	"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++	/* Intel-defined (#2) */
++	"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
++	"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
++	NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
++	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++	/* VIA/Cyrix/Centaur-defined */
++	NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
++	"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", 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", "svm", "extapic",
++	"cr8_legacy", "abm", "sse4a", "misalignsse",
++	"3dnowprefetch", "osvw", "ibs", "sse5",
++	"skinit", "wdt", NULL, NULL,
++	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
++
++	/* Auxiliary (Linux-defined) */
++	"ida", 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,
++};
++
++const char *const x86_power_flags[32] = {
++	"ts",	/* temperature sensor */
++	"fid",  /* frequency id control */
++	"vid",  /* voltage id control */
++	"ttp",  /* thermal trip */
++	"tm",
++	"stc",
++	"100mhzsteps",
++	"hwpstate",
++	"",	/* tsc invariant mapped to constant_tsc */
++		/* nothing */
++};
 diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
-index cc8c501..d1c372b 100644
+index cc8c501..fae31ce 100644
 --- a/arch/x86/kernel/cpu/intel.c
 +++ b/arch/x86/kernel/cpu/intel.c
-@@ -11,6 +11,8 @@
+@@ -11,6 +11,9 @@
  #include <asm/pgtable.h>
  #include <asm/msr.h>
  #include <asm/uaccess.h>
 +#include <asm/ptrace.h>
 +#include <asm/ds.h>
++#include <asm/bugs.h>
  
  #include "cpu.h"
  
-@@ -27,13 +29,14 @@
+@@ -27,13 +30,14 @@
  struct movsl_mask movsl_mask __read_mostly;
  #endif
  
@@ -266197,7 +290292,7 @@
  }
  
  /*
-@@ -113,6 +116,8 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -113,6 +117,8 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
  	unsigned int l2 = 0;
  	char *p = NULL;
  
@@ -266206,7 +290301,7 @@
  #ifdef CONFIG_X86_F00F_BUG
  	/*
  	 * All current models of Pentium and Pentium with MMX technology CPUs
-@@ -132,7 +137,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -132,7 +138,6 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
  	}
  #endif
  
@@ -266214,7 +290309,7 @@
  	l2 = init_intel_cacheinfo(c);
  	if (c->cpuid_level > 9 ) {
  		unsigned eax = cpuid_eax(10);
-@@ -201,16 +205,13 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -201,16 +206,13 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
  	}
  #endif
  
@@ -266233,7 +290328,7 @@
  	if (cpu_has_ds) {
  		unsigned int l1;
  		rdmsr(MSR_IA32_MISC_ENABLE, l1, l2);
-@@ -219,6 +220,9 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
+@@ -219,6 +221,9 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
  		if (!(l1 & (1<<12)))
  			set_bit(X86_FEATURE_PEBS, c->x86_capability);
  	}
@@ -266243,7 +290338,7 @@
  }
  
  static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
-@@ -342,5 +346,22 @@ unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
+@@ -342,5 +347,22 @@ unsigned long cmpxchg_386_u32(volatile void *ptr, u32 old, u32 new)
  EXPORT_SYMBOL(cmpxchg_386_u32);
  #endif
  
@@ -266930,18 +291025,40 @@
  */
  {
 diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
-index 9964be3..8e139c7 100644
+index 9964be3..ff14c32 100644
 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c
 +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
-@@ -4,6 +4,7 @@
+@@ -4,10 +4,9 @@
  #include <asm/msr.h>
  #include <asm/io.h>
  #include <asm/processor-cyrix.h>
 +#include <asm/processor-flags.h>
  #include "mtrr.h"
  
- int arr3_protected;
-@@ -142,7 +143,7 @@ static void prepare_set(void)
+-int arr3_protected;
+-
+ static void
+ cyrix_get_arr(unsigned int reg, unsigned long *base,
+ 	      unsigned long *size, mtrr_type * type)
+@@ -98,8 +97,6 @@ cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
+ 	case 4:
+ 		return replace_reg;
+ 	case 3:
+-		if (arr3_protected)
+-			break;
+ 	case 2:
+ 	case 1:
+ 	case 0:
+@@ -114,8 +111,6 @@ cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg)
+ 	} else {
+ 		for (i = 0; i < 7; i++) {
+ 			cyrix_get_arr(i, &lbase, &lsize, &ltype);
+-			if ((i == 3) && arr3_protected)
+-				continue;
+ 			if (lsize == 0)
+ 				return i;
+ 		}
+@@ -142,7 +137,7 @@ static void prepare_set(void)
  
  	/*  Disable and flush caches. Note that wbinvd flushes the TLBs as
  	    a side-effect  */
@@ -266950,6 +291067,114 @@
  	wbinvd();
  	write_cr0(cr0);
  	wbinvd();
+@@ -259,107 +254,6 @@ static void cyrix_set_all(void)
+ 	post_set();
+ }
+ 
+-#if 0
+-/*
+- * On Cyrix 6x86(MX) and M II the ARR3 is special: it has connection
+- * with the SMM (System Management Mode) mode. So we need the following:
+- * Check whether SMI_LOCK (CCR3 bit 0) is set
+- *   if it is set, write a warning message: ARR3 cannot be changed!
+- *     (it cannot be changed until the next processor reset)
+- *   if it is reset, then we can change it, set all the needed bits:
+- *   - disable access to SMM memory through ARR3 range (CCR1 bit 7 reset)
+- *   - disable access to SMM memory (CCR1 bit 2 reset)
+- *   - disable SMM mode (CCR1 bit 1 reset)
+- *   - disable write protection of ARR3 (CCR6 bit 1 reset)
+- *   - (maybe) disable ARR3
+- * Just to be sure, we enable ARR usage by the processor (CCR5 bit 5 set)
+- */
+-static void __init
+-cyrix_arr_init(void)
+-{
+-	struct set_mtrr_context ctxt;
+-	unsigned char ccr[7];
+-	int ccrc[7] = { 0, 0, 0, 0, 0, 0, 0 };
+-#ifdef CONFIG_SMP
+-	int i;
+-#endif
+-
+-	/* flush cache and enable MAPEN */
+-	set_mtrr_prepare_save(&ctxt);
+-	set_mtrr_cache_disable(&ctxt);
+-
+-	/* Save all CCRs locally */
+-	ccr[0] = getCx86(CX86_CCR0);
+-	ccr[1] = getCx86(CX86_CCR1);
+-	ccr[2] = getCx86(CX86_CCR2);
+-	ccr[3] = ctxt.ccr3;
+-	ccr[4] = getCx86(CX86_CCR4);
+-	ccr[5] = getCx86(CX86_CCR5);
+-	ccr[6] = getCx86(CX86_CCR6);
+-
+-	if (ccr[3] & 1) {
+-		ccrc[3] = 1;
+-		arr3_protected = 1;
+-	} else {
+-		/* Disable SMM mode (bit 1), access to SMM memory (bit 2) and
+-		 * access to SMM memory through ARR3 (bit 7).
+-		 */
+-		if (ccr[1] & 0x80) {
+-			ccr[1] &= 0x7f;
+-			ccrc[1] |= 0x80;
+-		}
+-		if (ccr[1] & 0x04) {
+-			ccr[1] &= 0xfb;
+-			ccrc[1] |= 0x04;
+-		}
+-		if (ccr[1] & 0x02) {
+-			ccr[1] &= 0xfd;
+-			ccrc[1] |= 0x02;
+-		}
+-		arr3_protected = 0;
+-		if (ccr[6] & 0x02) {
+-			ccr[6] &= 0xfd;
+-			ccrc[6] = 1;	/* Disable write protection of ARR3 */
+-			setCx86(CX86_CCR6, ccr[6]);
+-		}
+-		/* Disable ARR3. This is safe now that we disabled SMM. */
+-		/* cyrix_set_arr_up (3, 0, 0, 0, FALSE); */
+-	}
+-	/* If we changed CCR1 in memory, change it in the processor, too. */
+-	if (ccrc[1])
+-		setCx86(CX86_CCR1, ccr[1]);
+-
+-	/* Enable ARR usage by the processor */
+-	if (!(ccr[5] & 0x20)) {
+-		ccr[5] |= 0x20;
+-		ccrc[5] = 1;
+-		setCx86(CX86_CCR5, ccr[5]);
+-	}
+-#ifdef CONFIG_SMP
+-	for (i = 0; i < 7; i++)
+-		ccr_state[i] = ccr[i];
+-	for (i = 0; i < 8; i++)
+-		cyrix_get_arr(i,
+-			      &arr_state[i].base, &arr_state[i].size,
+-			      &arr_state[i].type);
+-#endif
+-
+-	set_mtrr_done(&ctxt);	/* flush cache and disable MAPEN */
+-
+-	if (ccrc[5])
+-		printk(KERN_INFO "mtrr: ARR usage was not enabled, enabled manually\n");
+-	if (ccrc[3])
+-		printk(KERN_INFO "mtrr: ARR3 cannot be changed\n");
+-/*
+-    if ( ccrc[1] & 0x80) printk ("mtrr: SMM memory access through ARR3 disabled\n");
+-    if ( ccrc[1] & 0x04) printk ("mtrr: SMM memory access disabled\n");
+-    if ( ccrc[1] & 0x02) printk ("mtrr: SMM mode disabled\n");
+-*/
+-	if (ccrc[6])
+-		printk(KERN_INFO "mtrr: ARR3 was write protected, unprotected\n");
+-}
+-#endif
+-
+ static struct mtrr_ops cyrix_mtrr_ops = {
+ 	.vendor            = X86_VENDOR_CYRIX,
+ //	.init              = cyrix_arr_init,
 diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
 index 992f08d..103d61a 100644
 --- a/arch/x86/kernel/cpu/mtrr/generic.c
@@ -267154,7 +291379,7 @@
  	}
  	return 0;
 diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
-index 3b20613..7159195 100644
+index 3b20613..1e27b69 100644
 --- a/arch/x86/kernel/cpu/mtrr/main.c
 +++ b/arch/x86/kernel/cpu/mtrr/main.c
 @@ -38,8 +38,8 @@
@@ -267176,7 +291401,20 @@
  static DEFINE_MUTEX(mtrr_mutex);
  
  u64 size_or_mask, size_and_mask;
-@@ -121,13 +121,8 @@ static void __init init_table(void)
+@@ -59,12 +59,6 @@ struct mtrr_ops * mtrr_if = NULL;
+ static void set_mtrr(unsigned int reg, unsigned long base,
+ 		     unsigned long size, mtrr_type type);
+ 
+-#ifndef CONFIG_X86_64
+-extern int arr3_protected;
+-#else
+-#define arr3_protected 0
+-#endif
+-
+ void set_mtrr_ops(struct mtrr_ops * ops)
+ {
+ 	if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
+@@ -121,13 +115,8 @@ static void __init init_table(void)
  	int i, max;
  
  	max = num_var_ranges;
@@ -267191,7 +291429,7 @@
  }
  
  struct set_mtrr_data {
-@@ -311,7 +306,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
+@@ -311,7 +300,7 @@ static void set_mtrr(unsigned int reg, unsigned long base,
   */
  
  int mtrr_add_page(unsigned long base, unsigned long size, 
@@ -267200,7 +291438,7 @@
  {
  	int i, replace, error;
  	mtrr_type ltype;
-@@ -349,7 +344,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
+@@ -349,7 +338,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
  	replace = -1;
  
  	/* No CPU hotplug when we change MTRR entries */
@@ -267209,7 +291447,7 @@
  	/*  Search for existing MTRR  */
  	mutex_lock(&mtrr_mutex);
  	for (i = 0; i < num_var_ranges; ++i) {
-@@ -383,7 +378,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
+@@ -383,7 +372,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
  			goto out;
  		}
  		if (increment)
@@ -267218,7 +291456,7 @@
  		error = i;
  		goto out;
  	}
-@@ -391,13 +386,15 @@ int mtrr_add_page(unsigned long base, unsigned long size,
+@@ -391,13 +380,15 @@ int mtrr_add_page(unsigned long base, unsigned long size,
  	i = mtrr_if->get_free_region(base, size, replace);
  	if (i >= 0) {
  		set_mtrr(i, base, size, type);
@@ -267239,7 +291477,7 @@
  			}
  		}
  	} else
-@@ -405,7 +402,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
+@@ -405,7 +396,7 @@ int mtrr_add_page(unsigned long base, unsigned long size,
  	error = i;
   out:
  	mutex_unlock(&mtrr_mutex);
@@ -267248,7 +291486,7 @@
  	return error;
  }
  
-@@ -460,7 +457,7 @@ static int mtrr_check(unsigned long base, unsigned long size)
+@@ -460,7 +451,7 @@ static int mtrr_check(unsigned long base, unsigned long size)
  
  int
  mtrr_add(unsigned long base, unsigned long size, unsigned int type,
@@ -267257,7 +291495,7 @@
  {
  	if (mtrr_check(base, size))
  		return -EINVAL;
-@@ -495,7 +492,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+@@ -495,7 +486,7 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
  
  	max = num_var_ranges;
  	/* No CPU hotplug when we change MTRR entries */
@@ -267266,7 +291504,18 @@
  	mutex_lock(&mtrr_mutex);
  	if (reg < 0) {
  		/*  Search for existing MTRR  */
-@@ -527,16 +524,16 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+@@ -516,27 +507,21 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
+ 		printk(KERN_WARNING "mtrr: register: %d too big\n", reg);
+ 		goto out;
+ 	}
+-	if (is_cpu(CYRIX) && !use_intel()) {
+-		if ((reg == 3) && arr3_protected) {
+-			printk(KERN_WARNING "mtrr: ARR3 cannot be changed\n");
+-			goto out;
+-		}
+-	}
+ 	mtrr_if->get(reg, &lbase, &lsize, &ltype);
+ 	if (lsize < 1) {
  		printk(KERN_WARNING "mtrr: MTRR %d not used\n", reg);
  		goto out;
  	}
@@ -267286,7 +291535,18 @@
  	return error;
  }
  /**
-@@ -591,16 +588,11 @@ struct mtrr_value {
+@@ -569,10 +554,6 @@ EXPORT_SYMBOL(mtrr_del);
+  * These should be called implicitly, but we can't yet until all the initcall
+  * stuff is done...
+  */
+-extern void amd_init_mtrr(void);
+-extern void cyrix_init_mtrr(void);
+-extern void centaur_init_mtrr(void);
+-
+ static void __init init_ifs(void)
+ {
+ #ifndef CONFIG_X86_64
+@@ -591,16 +572,11 @@ struct mtrr_value {
  	unsigned long	lsize;
  };
  
@@ -267304,7 +291564,7 @@
  
  	for (i = 0; i < num_var_ranges; i++) {
  		mtrr_if->get(i,
-@@ -622,7 +614,6 @@ static int mtrr_restore(struct sys_device * sysdev)
+@@ -622,7 +598,6 @@ static int mtrr_restore(struct sys_device * sysdev)
  				 mtrr_state[i].lsize,
  				 mtrr_state[i].ltype);
  	}
@@ -267312,7 +291572,7 @@
  	return 0;
  }
  
-@@ -633,6 +624,112 @@ static struct sysdev_driver mtrr_sysdev_driver = {
+@@ -633,6 +608,112 @@ static struct sysdev_driver mtrr_sysdev_driver = {
  	.resume		= mtrr_restore,
  };
  
@@ -267426,7 +291686,7 @@
  /**
   * mtrr_bp_init - initialize mtrrs on the boot CPU
 diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
-index 289dfe6..fb74a2c 100644
+index 289dfe6..2cc77eb 100644
 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h
 +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
 @@ -2,10 +2,8 @@
@@ -267459,6 +291719,14 @@
  struct mtrr_ops {
  	u32	vendor;
  	u32	use_intel_if;
+@@ -96,3 +97,7 @@ void mtrr_state_warn(void);
+ const char *mtrr_attrib_to_str(int x);
+ void mtrr_wrmsr(unsigned, unsigned, unsigned);
+ 
++/* CPU specific mtrr init functions */
++int amd_init_mtrr(void);
++int cyrix_init_mtrr(void);
++int centaur_init_mtrr(void);
 diff --git a/arch/x86/kernel/cpu/mtrr/state.c b/arch/x86/kernel/cpu/mtrr/state.c
 index 49e20c2..9f8ba92 100644
 --- a/arch/x86/kernel/cpu/mtrr/state.c
@@ -267493,10 +291761,91 @@
  EXPORT_SYMBOL(reserve_perfctr_nmi);
  EXPORT_SYMBOL(release_perfctr_nmi);
 diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
-index 3900e46..0282132 100644
+index 3900e46..af11d31 100644
 --- a/arch/x86/kernel/cpu/proc.c
 +++ b/arch/x86/kernel/cpu/proc.c
-@@ -188,7 +188,7 @@ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+@@ -10,80 +10,6 @@
+  */
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+-	/* 
+-	 * These flag bits must match the definitions in <asm/cpufeature.h>.
+-	 * NULL means this bit is undefined or reserved; either way it doesn't
+-	 * have meaning as far as Linux is concerned.  Note that it's important
+-	 * to realize there is a difference between this table and CPUID -- if
+-	 * applications want to get the raw CPUID data, they should access
+-	 * /dev/cpu/<cpu_nr>/cpuid instead.
+-	 */
+-	static const char * const x86_cap_flags[] = {
+-		/* Intel-defined */
+-	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+-	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+-	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+-	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
+-
+-		/* AMD-defined */
+-		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", "pdpe1gb", "rdtscp", NULL, "lm",
+-		"3dnowext", "3dnow",
+-
+-		/* Transmeta-defined */
+-		"recovery", "longrun", NULL, "lrti", 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,
+-
+-		/* Other (Linux-defined) */
+-		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+-		NULL, NULL, NULL, NULL,
+-		"constant_tsc", "up", NULL, "arch_perfmon",
+-		"pebs", "bts", NULL, "sync_rdtsc",
+-		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Intel-defined (#2) */
+-		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
+-		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+-		NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* VIA/Cyrix/Centaur-defined */
+-		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
+-		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", 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", "svm", "extapic",
+-		"cr8_legacy", "abm", "sse4a", "misalignsse",
+-		"3dnowprefetch", "osvw", "ibs", "sse5",
+-		"skinit", "wdt", NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Auxiliary (Linux-defined) */
+-		"ida", 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 const char * const x86_power_flags[] = {
+-		"ts",	/* temperature sensor */
+-		"fid",  /* frequency id control */
+-		"vid",  /* voltage id control */
+-		"ttp",  /* thermal trip */
+-		"tm",
+-		"stc",
+-		"100mhzsteps",
+-		"hwpstate",
+-		"",	/* constant_tsc - moved to flags */
+-		/* nothing */
+-	};
+ 	struct cpuinfo_x86 *c = v;
+ 	int i, n = 0;
+ 	int fpu_exception;
+@@ -188,7 +114,7 @@ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  static void c_stop(struct seq_file *m, void *v)
  {
  }
@@ -267506,19 +291855,110 @@
  	.next	= c_next,
  	.stop	= c_stop,
 diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c
-index 05c9936..a63432d 100644
+index 05c9936..288e7a6 100644
 --- a/arch/x86/kernel/cpuid.c
 +++ b/arch/x86/kernel/cpuid.c
-@@ -50,7 +50,7 @@ struct cpuid_command {
+@@ -1,6 +1,6 @@
+ /* ----------------------------------------------------------------------- *
+- *   
+- *   Copyright 2000 H. Peter Anvin - All Rights Reserved
++ *
++ *   Copyright 2000-2008 H. Peter Anvin - All Rights Reserved
+  *
+  *   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
+@@ -17,6 +17,10 @@
+  * and then read in chunks of 16 bytes.  A larger size means multiple
+  * reads of consecutive levels.
+  *
++ * The lower 32 bits of the file position is used as the incoming %eax,
++ * and the upper 32 bits of the file position as the incoming %ecx,
++ * the latter intended for "counting" eax levels like eax=4.
++ *
+  * This driver uses /dev/cpu/%d/cpuid where %d is the minor number, and on
+  * an SMP box will direct the access to CPU %d.
+  */
+@@ -43,35 +47,24 @@
+ 
+ static struct class *cpuid_class;
+ 
+-struct cpuid_command {
+-	u32 reg;
+-	u32 *data;
++struct cpuid_regs {
++	u32 eax, ebx, ecx, edx;
+ };
  
  static void cpuid_smp_cpuid(void *cmd_block)
  {
 -	struct cpuid_command *cmd = (struct cpuid_command *)cmd_block;
-+	struct cpuid_command *cmd = cmd_block;
+-
+-	cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2],
+-		      &cmd->data[3]);
+-}
+-
+-static inline void do_cpuid(int cpu, u32 reg, u32 * data)
+-{
+-	struct cpuid_command cmd;
+-
+-	cmd.reg = reg;
+-	cmd.data = data;
++	struct cpuid_regs *cmd = (struct cpuid_regs *)cmd_block;
+ 
+-	smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
++	cpuid_count(cmd->eax, cmd->ecx,
++		    &cmd->eax, &cmd->ebx, &cmd->ecx, &cmd->edx);
+ }
+ 
+ static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
+ {
+ 	loff_t ret;
++	struct inode *inode = file->f_mapping->host;
+ 
+-	lock_kernel();
+-
++	mutex_lock(&inode->i_mutex);
+ 	switch (orig) {
+ 	case 0:
+ 		file->f_pos = offset;
+@@ -84,8 +77,7 @@ static loff_t cpuid_seek(struct file *file, loff_t offset, int orig)
+ 	default:
+ 		ret = -EINVAL;
+ 	}
+-
+-	unlock_kernel();
++	mutex_unlock(&inode->i_mutex);
+ 	return ret;
+ }
+ 
+@@ -93,19 +85,21 @@ static ssize_t cpuid_read(struct file *file, char __user *buf,
+ 			  size_t count, loff_t * ppos)
+ {
+ 	char __user *tmp = buf;
+-	u32 data[4];
+-	u32 reg = *ppos;
++	struct cpuid_regs cmd;
+ 	int cpu = iminor(file->f_path.dentry->d_inode);
++	u64 pos = *ppos;
+ 
+ 	if (count % 16)
+ 		return -EINVAL;	/* Invalid chunk size */
+ 
+ 	for (; count; count -= 16) {
+-		do_cpuid(cpu, reg, data);
+-		if (copy_to_user(tmp, &data, 16))
++		cmd.eax = pos;
++		cmd.ecx = pos >> 32;
++		smp_call_function_single(cpu, cpuid_smp_cpuid, &cmd, 1, 1);
++		if (copy_to_user(tmp, &cmd, 16))
+ 			return -EFAULT;
+ 		tmp += 16;
+-		*ppos = reg++;
++		*ppos = ++pos;
+ 	}
  
- 	cpuid(cmd->reg, &cmd->data[0], &cmd->data[1], &cmd->data[2],
- 		      &cmd->data[3]);
-@@ -157,20 +157,20 @@ static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb,
+ 	return tmp - buf;
+@@ -157,20 +151,20 @@ static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb,
  
  	switch (action) {
  	case CPU_UP_PREPARE:
@@ -267543,6 +291983,24 @@
  {
  	.notifier_call = cpuid_class_cpu_callback,
  };
+@@ -193,7 +187,7 @@ static int __init cpuid_init(void)
+ 	}
+ 	for_each_online_cpu(i) {
+ 		err = cpuid_device_create(i);
+-		if (err != 0) 
++		if (err != 0)
+ 			goto out_class;
+ 	}
+ 	register_hotcpu_notifier(&cpuid_class_cpu_notifier);
+@@ -208,7 +202,7 @@ out_class:
+ 	}
+ 	class_destroy(cpuid_class);
+ out_chrdev:
+-	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");	
++	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
+ out:
+ 	return err;
+ }
 diff --git a/arch/x86/kernel/doublefault_32.c b/arch/x86/kernel/doublefault_32.c
 index 40978af..a47798b 100644
 --- a/arch/x86/kernel/doublefault_32.c
@@ -269314,10 +293772,10 @@
  void early_printk(const char *fmt, ...)
 diff --git a/arch/x86/kernel/efi.c b/arch/x86/kernel/efi.c
 new file mode 100644
-index 0000000..1411324
+index 0000000..32dd62b
 --- /dev/null
 +++ b/arch/x86/kernel/efi.c
-@@ -0,0 +1,512 @@
+@@ -0,0 +1,515 @@
 +/*
 + * Common EFI (Extensible Firmware Interface) support functions
 + * Based on Extensible Firmware Interface Specification version 1.0
@@ -269699,11 +294157,9 @@
 +#endif
 +}
 +
-+#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 +static void __init runtime_code_page_mkexec(void)
 +{
 +	efi_memory_desc_t *md;
-+	unsigned long end;
 +	void *p;
 +
 +	if (!(__supported_pte_mask & _PAGE_NX))
@@ -269712,18 +294168,13 @@
 +	/* Make EFI runtime service code area executable */
 +	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 +		md = p;
-+		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
-+		if (md->type == EFI_RUNTIME_SERVICES_CODE &&
-+		    (end >> PAGE_SHIFT) <= max_pfn_mapped) {
-+			set_memory_x(md->virt_addr, md->num_pages);
-+			set_memory_uc(md->virt_addr, md->num_pages);
-+		}
++
++		if (md->type != EFI_RUNTIME_SERVICES_CODE)
++			continue;
++
++		set_memory_x(md->virt_addr, md->num_pages << EFI_PAGE_SHIFT);
 +	}
-+	__flush_tlb_all();
 +}
-+#else
-+static inline void __init runtime_code_page_mkexec(void) { }
-+#endif
 +
 +/*
 + * This function will switch the EFI runtime services to virtual mode.
@@ -269737,30 +294188,40 @@
 +{
 +	efi_memory_desc_t *md;
 +	efi_status_t status;
-+	unsigned long end;
-+	void *p;
++	unsigned long size;
++	u64 end, systab;
++	void *p, *va;
 +
 +	efi.systab = NULL;
 +	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 +		md = p;
 +		if (!(md->attribute & EFI_MEMORY_RUNTIME))
 +			continue;
-+		end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
-+		if ((md->attribute & EFI_MEMORY_WB) &&
-+		    ((end >> PAGE_SHIFT) <= max_pfn_mapped))
-+			md->virt_addr = (unsigned long)__va(md->phys_addr);
++
++		size = md->num_pages << EFI_PAGE_SHIFT;
++		end = md->phys_addr + size;
++
++		if ((end >> PAGE_SHIFT) <= max_pfn_mapped)
++			va = __va(md->phys_addr);
 +		else
-+			md->virt_addr = (unsigned long)
-+				efi_ioremap(md->phys_addr,
-+					    md->num_pages << EFI_PAGE_SHIFT);
-+		if (!md->virt_addr)
++			va = efi_ioremap(md->phys_addr, size);
++
++		if (md->attribute & EFI_MEMORY_WB)
++			set_memory_uc(md->virt_addr, size);
++
++		md->virt_addr = (u64) (unsigned long) va;
++
++		if (!va) {
 +			printk(KERN_ERR PFX "ioremap of 0x%llX failed!\n",
 +			       (unsigned long long)md->phys_addr);
-+		if ((md->phys_addr <= (unsigned long)efi_phys.systab) &&
-+		    ((unsigned long)efi_phys.systab < end))
-+			efi.systab = (efi_system_table_t *)(unsigned long)
-+				(md->virt_addr - md->phys_addr +
-+				 (unsigned long)efi_phys.systab);
++			continue;
++		}
++
++		systab = (u64) (unsigned long) efi_phys.systab;
++		if (md->phys_addr <= systab && systab < end) {
++			systab += md->virt_addr - md->phys_addr;
++			efi.systab = (efi_system_table_t *) (unsigned long) systab;
++		}
 +	}
 +
 +	BUG_ON(!efi.systab);
@@ -270505,7 +294966,7 @@
  }
 diff --git a/arch/x86/kernel/efi_64.c b/arch/x86/kernel/efi_64.c
 new file mode 100644
-index 0000000..674f237
+index 0000000..09d5c23
 --- /dev/null
 +++ b/arch/x86/kernel/efi_64.c
 @@ -0,0 +1,134 @@
@@ -270565,10 +295026,10 @@
 +		else
 +			set_pte(kpte, __pte((pte_val(*kpte) | _PAGE_NX) & \
 +					    __supported_pte_mask));
-+		if (level == 4)
-+			start = (start + PMD_SIZE) & PMD_MASK;
-+		else
++		if (level == PG_LEVEL_4K)
 +			start = (start + PAGE_SIZE) & PAGE_MASK;
++		else
++			start = (start + PMD_SIZE) & PMD_MASK;
 +	}
 +}
 +
@@ -270620,23 +295081,23 @@
 +				memmap.nr_map * memmap.desc_size);
 +}
 +
-+void __iomem * __init efi_ioremap(unsigned long offset,
-+				  unsigned long size)
++void __iomem * __init efi_ioremap(unsigned long phys_addr, unsigned long size)
 +{
 +	static unsigned pages_mapped;
-+	unsigned long last_addr;
 +	unsigned i, pages;
 +
-+	last_addr = offset + size - 1;
-+	offset &= PAGE_MASK;
-+	pages = (PAGE_ALIGN(last_addr) - offset) >> PAGE_SHIFT;
++	/* phys_addr and size must be page aligned */
++	if ((phys_addr & ~PAGE_MASK) || (size & ~PAGE_MASK))
++		return NULL;
++
++	pages = size >> PAGE_SHIFT;
 +	if (pages_mapped + pages > MAX_EFI_IO_PAGES)
 +		return NULL;
 +
 +	for (i = 0; i < pages; i++) {
 +		__set_fixmap(FIX_EFI_IO_MAP_FIRST_PAGE - pages_mapped,
-+			     offset, PAGE_KERNEL_EXEC_NOCACHE);
-+		offset += PAGE_SIZE;
++			     phys_addr, PAGE_KERNEL);
++		phys_addr += PAGE_SIZE;
 +		pages_mapped++;
 +	}
 +
@@ -271516,7 +295977,7 @@
  	hlt
  	jmp hlt_loop
 diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
-index b6167fe..1d5a7a3 100644
+index b6167fe..4f283ad 100644
 --- a/arch/x86/kernel/head_64.S
 +++ b/arch/x86/kernel/head_64.S
 @@ -19,6 +19,13 @@
@@ -271533,6 +295994,24 @@
  /* we are not able to switch in one step to the final KERNEL ADRESS SPACE
   * because we need identity-mapped pages.
   *
+@@ -56,7 +63,7 @@ startup_64:
+ 
+ 	/* Is the address not 2M aligned? */
+ 	movq	%rbp, %rax
+-	andl	$~LARGE_PAGE_MASK, %eax
++	andl	$~PMD_PAGE_MASK, %eax
+ 	testl	%eax, %eax
+ 	jnz	bad_address
+ 
+@@ -81,7 +88,7 @@ startup_64:
+ 
+ 	/* Add an Identity mapping if I am above 1G */
+ 	leaq	_text(%rip), %rdi
+-	andq	$LARGE_PAGE_MASK, %rdi
++	andq	$PMD_PAGE_MASK, %rdi
+ 
+ 	movq	%rdi, %rax
+ 	shrq	$PUD_SHIFT, %rax
 @@ -260,14 +267,43 @@ init_rsp:
  bad_address:
  	jmp bad_address
@@ -277093,10 +301572,10 @@
 -}
 diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
 new file mode 100644
-index 0000000..8a7660c
+index 0000000..0224c36
 --- /dev/null
 +++ b/arch/x86/kernel/ldt.c
-@@ -0,0 +1,260 @@
+@@ -0,0 +1,261 @@
 +/*
 + * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
 + * Copyright (C) 1999 Ingo Molnar <mingo at redhat.com>
@@ -277134,7 +301613,8 @@
 +	if (mincount <= pc->size)
 +		return 0;
 +	oldsize = pc->size;
-+	mincount = (mincount + 511) & (~511);
++	mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
++			(~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
 +	if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
 +		newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
 +	else
@@ -278209,10 +302689,45 @@
  
  	cpu_set(cpu, cpu_possible_map);
 diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
-index ee6eba4..bd82850 100644
+index ee6eba4..af51ea8 100644
 --- a/arch/x86/kernel/msr.c
 +++ b/arch/x86/kernel/msr.c
-@@ -155,20 +155,20 @@ static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb,
+@@ -1,6 +1,6 @@
+ /* ----------------------------------------------------------------------- *
+- *   
+- *   Copyright 2000 H. Peter Anvin - All Rights Reserved
++ *
++ *   Copyright 2000-2008 H. Peter Anvin - All Rights Reserved
+  *
+  *   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
+@@ -45,9 +45,10 @@ static struct class *msr_class;
+ 
+ static loff_t msr_seek(struct file *file, loff_t offset, int orig)
+ {
+-	loff_t ret = -EINVAL;
++	loff_t ret;
++	struct inode *inode = file->f_mapping->host;
+ 
+-	lock_kernel();
++	mutex_lock(&inode->i_mutex);
+ 	switch (orig) {
+ 	case 0:
+ 		file->f_pos = offset;
+@@ -56,8 +57,11 @@ static loff_t msr_seek(struct file *file, loff_t offset, int orig)
+ 	case 1:
+ 		file->f_pos += offset;
+ 		ret = file->f_pos;
++		break;
++	default:
++		ret = -EINVAL;
+ 	}
+-	unlock_kernel();
++	mutex_unlock(&inode->i_mutex);
+ 	return ret;
+ }
+ 
+@@ -155,20 +159,20 @@ static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb,
  
  	switch (action) {
  	case CPU_UP_PREPARE:
@@ -279577,10 +304092,10 @@
 +	return ret;
 +}
 diff --git a/arch/x86/kernel/pci-calgary_64.c b/arch/x86/kernel/pci-calgary_64.c
-index 6bf1f71..1fe7f04 100644
+index 6bf1f71..1b5464c 100644
 --- a/arch/x86/kernel/pci-calgary_64.c
 +++ b/arch/x86/kernel/pci-calgary_64.c
-@@ -30,7 +30,6 @@
+@@ -30,12 +30,12 @@
  #include <linux/spinlock.h>
  #include <linux/string.h>
  #include <linux/dma-mapping.h>
@@ -279588,7 +304103,13 @@
  #include <linux/bitops.h>
  #include <linux/pci_ids.h>
  #include <linux/pci.h>
-@@ -183,7 +182,7 @@ static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
+ #include <linux/delay.h>
+ #include <linux/scatterlist.h>
++#include <linux/iommu-helper.h>
+ #include <asm/gart.h>
+ #include <asm/calgary.h>
+ #include <asm/tce.h>
+@@ -183,7 +183,7 @@ static struct calgary_bus_info bus_info[MAX_PHB_BUS_NUM] = { { NULL, 0, 0 }, };
  
  /* enable this to stress test the chip's TCE cache */
  #ifdef CONFIG_IOMMU_DEBUG
@@ -279597,7 +304118,7 @@
  
  static inline unsigned long verify_bit_range(unsigned long* bitmap,
  	int expected, unsigned long start, unsigned long end)
-@@ -202,7 +201,7 @@ static inline unsigned long verify_bit_range(unsigned long* bitmap,
+@@ -202,7 +202,7 @@ static inline unsigned long verify_bit_range(unsigned long* bitmap,
  	return ~0UL;
  }
  #else /* debugging is disabled */
@@ -279606,7 +304127,103 @@
  
  static inline unsigned long verify_bit_range(unsigned long* bitmap,
  	int expected, unsigned long start, unsigned long end)
-@@ -1007,7 +1006,7 @@ static void __init calgary_set_split_completion_timeout(void __iomem *bbar,
+@@ -261,22 +261,28 @@ static void iommu_range_reserve(struct iommu_table *tbl,
+ 	spin_unlock_irqrestore(&tbl->it_lock, flags);
+ }
+ 
+-static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+-	unsigned int npages)
++static unsigned long iommu_range_alloc(struct device *dev,
++				       struct iommu_table *tbl,
++				       unsigned int npages)
+ {
+ 	unsigned long flags;
+ 	unsigned long offset;
++	unsigned long boundary_size;
++
++	boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
++			      PAGE_SIZE) >> PAGE_SHIFT;
+ 
+ 	BUG_ON(npages == 0);
+ 
+ 	spin_lock_irqsave(&tbl->it_lock, flags);
+ 
+-	offset = find_next_zero_string(tbl->it_map, tbl->it_hint,
+-				       tbl->it_size, npages);
++	offset = iommu_area_alloc(tbl->it_map, tbl->it_size, tbl->it_hint,
++				  npages, 0, boundary_size, 0);
+ 	if (offset == ~0UL) {
+ 		tbl->chip_ops->tce_cache_blast(tbl);
+-		offset = find_next_zero_string(tbl->it_map, 0,
+-					       tbl->it_size, npages);
++
++		offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
++					  npages, 0, boundary_size, 0);
+ 		if (offset == ~0UL) {
+ 			printk(KERN_WARNING "Calgary: IOMMU full.\n");
+ 			spin_unlock_irqrestore(&tbl->it_lock, flags);
+@@ -287,7 +293,6 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+ 		}
+ 	}
+ 
+-	set_bit_string(tbl->it_map, offset, npages);
+ 	tbl->it_hint = offset + npages;
+ 	BUG_ON(tbl->it_hint > tbl->it_size);
+ 
+@@ -296,13 +301,13 @@ static unsigned long iommu_range_alloc(struct iommu_table *tbl,
+ 	return offset;
+ }
+ 
+-static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *vaddr,
+-	unsigned int npages, int direction)
++static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
++			      void *vaddr, unsigned int npages, int direction)
+ {
+ 	unsigned long entry;
+ 	dma_addr_t ret = bad_dma_address;
+ 
+-	entry = iommu_range_alloc(tbl, npages);
++	entry = iommu_range_alloc(dev, tbl, npages);
+ 
+ 	if (unlikely(entry == bad_dma_address))
+ 		goto error;
+@@ -355,7 +360,7 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+ 			       badbit, tbl, dma_addr, entry, npages);
+ 	}
+ 
+-	__clear_bit_string(tbl->it_map, entry, npages);
++	iommu_area_free(tbl->it_map, entry, npages);
+ 
+ 	spin_unlock_irqrestore(&tbl->it_lock, flags);
+ }
+@@ -439,7 +444,7 @@ static int calgary_map_sg(struct device *dev, struct scatterlist *sg,
+ 		vaddr = (unsigned long) sg_virt(s);
+ 		npages = num_dma_pages(vaddr, s->length);
+ 
+-		entry = iommu_range_alloc(tbl, npages);
++		entry = iommu_range_alloc(dev, tbl, npages);
+ 		if (entry == bad_dma_address) {
+ 			/* makes sure unmap knows to stop */
+ 			s->dma_length = 0;
+@@ -477,7 +482,7 @@ static dma_addr_t calgary_map_single(struct device *dev, void *vaddr,
+ 	npages = num_dma_pages(uaddr, size);
+ 
+ 	if (translation_enabled(tbl))
+-		dma_handle = iommu_alloc(tbl, vaddr, npages, direction);
++		dma_handle = iommu_alloc(dev, tbl, vaddr, npages, direction);
+ 	else
+ 		dma_handle = virt_to_bus(vaddr);
+ 
+@@ -517,7 +522,7 @@ static void* calgary_alloc_coherent(struct device *dev, size_t size,
+ 
+ 	if (translation_enabled(tbl)) {
+ 		/* set up tces to cover the allocated range */
+-		mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL);
++		mapping = iommu_alloc(dev, tbl, ret, npages, DMA_BIDIRECTIONAL);
+ 		if (mapping == bad_dma_address)
+ 			goto free;
+ 
+@@ -1007,7 +1012,7 @@ static void __init calgary_set_split_completion_timeout(void __iomem *bbar,
  	readq(target); /* flush */
  }
  
@@ -279615,7 +304232,7 @@
  {
  	unsigned char busnum = dev->bus->number;
  	void __iomem *bbar = tbl->bbar;
-@@ -1023,7 +1022,7 @@ static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev)
+@@ -1023,7 +1028,7 @@ static void calioc2_handle_quirks(struct iommu_table *tbl, struct pci_dev *dev)
  	writel(cpu_to_be32(val), target);
  }
  
@@ -279646,7 +304263,7 @@
  	iommu_merge = 1;
  
 diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
-index 06bcba5..4d5cc71 100644
+index 06bcba5..65f6acb 100644
 --- a/arch/x86/kernel/pci-gart_64.c
 +++ b/arch/x86/kernel/pci-gart_64.c
 @@ -1,12 +1,12 @@
@@ -279665,7 +304282,15 @@
   * Copyright 2002 Andi Kleen, SuSE Labs.
   * Subject to the GNU General Public License v2 only.
   */
-@@ -37,23 +37,26 @@
+@@ -25,6 +25,7 @@
+ #include <linux/bitops.h>
+ #include <linux/kdebug.h>
+ #include <linux/scatterlist.h>
++#include <linux/iommu-helper.h>
+ #include <asm/atomic.h>
+ #include <asm/io.h>
+ #include <asm/mtrr.h>
+@@ -37,23 +38,26 @@
  #include <asm/k8.h>
  
  static unsigned long iommu_bus_base;	/* GART remapping area (physical) */
@@ -279702,7 +304327,7 @@
  
  #define GPTE_VALID    1
  #define GPTE_COHERENT 2
-@@ -61,10 +64,10 @@ static u32 gart_unmapped_entry;
+@@ -61,10 +65,10 @@ static u32 gart_unmapped_entry;
  	(((x) & 0xfffff000) | (((x) >> 32) << 4) | GPTE_VALID | GPTE_COHERENT)
  #define GPTE_DECODE(x) (((x) & 0xfffff000) | (((u64)(x) & 0xff0) << 28))
  
@@ -279715,7 +304340,7 @@
  
  #ifdef CONFIG_AGP
  #define AGPEXTERN extern
-@@ -77,130 +80,152 @@ AGPEXTERN int agp_memory_reserved;
+@@ -77,130 +81,159 @@ AGPEXTERN int agp_memory_reserved;
  AGPEXTERN __u32 *agp_gatt_table;
  
  static unsigned long next_bit;  /* protected by iommu_bitmap_lock */
@@ -279724,20 +304349,27 @@
  
 -static unsigned long alloc_iommu(int size) 
 -{ 	
-+static unsigned long alloc_iommu(int size)
++static unsigned long alloc_iommu(struct device *dev, int size)
 +{
  	unsigned long offset, flags;
++	unsigned long boundary_size;
++	unsigned long base_index;
++
++	base_index = ALIGN(iommu_bus_base & dma_get_seg_boundary(dev),
++			   PAGE_SIZE) >> PAGE_SHIFT;
++	boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
++			      PAGE_SIZE) >> PAGE_SHIFT;
  
 -	spin_lock_irqsave(&iommu_bitmap_lock, flags);	
 -	offset = find_next_zero_string(iommu_gart_bitmap,next_bit,iommu_pages,size);
 +	spin_lock_irqsave(&iommu_bitmap_lock, flags);
-+	offset = find_next_zero_string(iommu_gart_bitmap, next_bit,
-+					iommu_pages, size);
++	offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, next_bit,
++				  size, base_index, boundary_size, 0);
  	if (offset == -1) {
  		need_flush = 1;
 -		offset = find_next_zero_string(iommu_gart_bitmap,0,iommu_pages,size);
-+		offset = find_next_zero_string(iommu_gart_bitmap, 0,
-+						iommu_pages, size);
++		offset = iommu_area_alloc(iommu_gart_bitmap, iommu_pages, 0,
++					  size, base_index, boundary_size, 0);
  	}
 -	if (offset != -1) { 
 -		set_bit_string(iommu_gart_bitmap, offset, size); 
@@ -279768,7 +304400,8 @@
  	unsigned long flags;
 +
  	spin_lock_irqsave(&iommu_bitmap_lock, flags);
- 	__clear_bit_string(iommu_gart_bitmap, offset, size);
+-	__clear_bit_string(iommu_gart_bitmap, offset, size);
++	iommu_area_free(iommu_gart_bitmap, offset, size);
  	spin_unlock_irqrestore(&iommu_bitmap_lock, flags);
 -} 
 +}
@@ -279928,14 +304561,15 @@
  }
  
  /* Map a single continuous physical area into the IOMMU.
-@@ -208,13 +233,14 @@ static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t
+@@ -208,13 +241,14 @@ static inline int nonforced_iommu(struct device *dev, unsigned long addr, size_t
   */
  static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
  				size_t size, int dir)
 -{ 
 +{
  	unsigned long npages = to_pages(phys_mem, size);
- 	unsigned long iommu_page = alloc_iommu(npages);
+-	unsigned long iommu_page = alloc_iommu(npages);
++	unsigned long iommu_page = alloc_iommu(dev, npages);
  	int i;
 +
  	if (iommu_page == -1) {
@@ -279945,7 +304579,7 @@
  		if (panic_on_overflow)
  			panic("dma_map_area overflow %lu bytes\n", size);
  		iommu_full(dev, size, dir);
-@@ -229,35 +255,39 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
+@@ -229,35 +263,39 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
  	return iommu_bus_base + iommu_page*PAGE_SIZE + (phys_mem & ~PAGE_MASK);
  }
  
@@ -279992,7 +304626,7 @@
  {
  	unsigned long iommu_page;
  	int npages;
-@@ -266,6 +296,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
+@@ -266,6 +304,7 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
  	if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE ||
  	    dma_addr >= iommu_bus_base + iommu_size)
  		return;
@@ -280000,7 +304634,7 @@
  	iommu_page = (dma_addr - iommu_bus_base)>>PAGE_SHIFT;
  	npages = to_pages(dma_addr, size);
  	for (i = 0; i < npages; i++) {
-@@ -278,7 +309,8 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
+@@ -278,7 +317,8 @@ static void gart_unmap_single(struct device *dev, dma_addr_t dma_addr,
  /*
   * Wrapper for pci_unmap_single working with scatterlists.
   */
@@ -280010,7 +304644,7 @@
  {
  	struct scatterlist *s;
  	int i;
-@@ -303,12 +335,13 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
+@@ -303,12 +343,13 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
  
  	for_each_sg(sg, s, nents, i) {
  		unsigned long addr = sg_phys(s);
@@ -280028,7 +304662,7 @@
  				sg[0].dma_length = 0;
  				break;
  			}
-@@ -317,15 +350,16 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
+@@ -317,15 +358,17 @@ static int dma_map_sg_nonforce(struct device *dev, struct scatterlist *sg,
  		s->dma_length = s->length;
  	}
  	flush_gart();
@@ -280037,17 +304671,20 @@
  }
  
  /* Map multiple scatterlist entries continuous into the first. */
- static int __dma_map_cont(struct scatterlist *start, int nelems,
+-static int __dma_map_cont(struct scatterlist *start, int nelems,
 -		      struct scatterlist *sout, unsigned long pages)
-+			  struct scatterlist *sout, unsigned long pages)
++static int __dma_map_cont(struct device *dev, struct scatterlist *start,
++			  int nelems, struct scatterlist *sout,
++			  unsigned long pages)
  {
- 	unsigned long iommu_start = alloc_iommu(pages);
+-	unsigned long iommu_start = alloc_iommu(pages);
 -	unsigned long iommu_page = iommu_start; 
++	unsigned long iommu_start = alloc_iommu(dev, pages);
 +	unsigned long iommu_page = iommu_start;
  	struct scatterlist *s;
  	int i;
  
-@@ -335,32 +369,33 @@ static int __dma_map_cont(struct scatterlist *start, int nelems,
+@@ -335,32 +378,33 @@ static int __dma_map_cont(struct scatterlist *start, int nelems,
  	for_each_sg(start, s, nelems, i) {
  		unsigned long pages, addr;
  		unsigned long phys_addr = s->dma_address;
@@ -280087,14 +304724,17 @@
 -		      struct scatterlist *sout,
 -		      unsigned long pages, int need)
 +static inline int
-+dma_map_cont(struct scatterlist *start, int nelems, struct scatterlist *sout,
-+	     unsigned long pages, int need)
++dma_map_cont(struct device *dev, struct scatterlist *start, int nelems,
++	     struct scatterlist *sout, unsigned long pages, int need)
  {
  	if (!need) {
  		BUG_ON(nelems != 1);
-@@ -370,22 +405,19 @@ static inline int dma_map_cont(struct scatterlist *start, int nelems,
+@@ -368,24 +412,23 @@ static inline int dma_map_cont(struct scatterlist *start, int nelems,
+ 		sout->dma_length = start->length;
+ 		return 0;
  	}
- 	return __dma_map_cont(start, nelems, sout, pages);
+-	return __dma_map_cont(start, nelems, sout, pages);
++	return __dma_map_cont(dev, start, nelems, sout, pages);
  }
 -		
 +
@@ -280116,13 +304756,20 @@
  	struct scatterlist *s, *ps, *start_sg, *sgmap;
 +	int need = 0, nextneed, i, out, start;
 +	unsigned long pages = 0;
++	unsigned int seg_size;
++	unsigned int max_seg_size;
  
 -	if (nents == 0) 
 +	if (nents == 0)
  		return 0;
  
  	if (!dev)
-@@ -397,15 +429,19 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+@@ -394,24 +437,32 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ 	out = 0;
+ 	start = 0;
+ 	start_sg = sgmap = sg;
++	seg_size = 0;
++	max_seg_size = dma_get_max_seg_size(dev);
  	ps = NULL; /* shut up gcc */
  	for_each_sg(sg, s, nents, i) {
  		dma_addr_t addr = sg_phys(s);
@@ -280144,9 +304791,33 @@
 +			 * offset.
 +			 */
  			if (!iommu_merge || !nextneed || !need || s->offset ||
++			    (s->length + seg_size > max_seg_size) ||
  			    (ps->offset + ps->length) % PAGE_SIZE) {
- 				if (dma_map_cont(start_sg, i - start, sgmap,
-@@ -436,6 +472,7 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+-				if (dma_map_cont(start_sg, i - start, sgmap,
+-						  pages, need) < 0)
++				if (dma_map_cont(dev, start_sg, i - start,
++						 sgmap, pages, need) < 0)
+ 					goto error;
+ 				out++;
++				seg_size = 0;
+ 				sgmap = sg_next(sgmap);
+ 				pages = 0;
+ 				start = i;
+@@ -419,11 +470,12 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ 			}
+ 		}
+ 
++		seg_size += s->length;
+ 		need = nextneed;
+ 		pages += to_pages(s->offset, s->length);
+ 		ps = s;
+ 	}
+-	if (dma_map_cont(start_sg, i - start, sgmap, pages, need) < 0)
++	if (dma_map_cont(dev, start_sg, i - start, sgmap, pages, need) < 0)
+ 		goto error;
+ 	out++;
+ 	flush_gart();
+@@ -436,6 +488,7 @@ static int gart_map_sg(struct device *dev, struct scatterlist *sg, int nents,
  error:
  	flush_gart();
  	gart_unmap_sg(dev, sg, out, dir);
@@ -280154,7 +304825,7 @@
  	/* When it was forced or merged try again in a dumb way */
  	if (force_iommu || iommu_merge) {
  		out = dma_map_sg_nonforce(dev, sg, nents, dir);
-@@ -444,64 +481,68 @@ error:
+@@ -444,64 +497,68 @@ error:
  	}
  	if (panic_on_overflow)
  		panic("dma_map_sg: overflow on %lu pages\n", pages);
@@ -280178,6 +304849,9 @@
 -	} 
 -
 -	a = aper + iommu_size; 
+-	iommu_size -= round_up(a, LARGE_PAGE_SIZE) - a;
+-
+-	if (iommu_size < 64*1024*1024) 
 +{
 +	unsigned long a;
 +
@@ -280188,9 +304862,8 @@
 +	}
 +
 +	a = aper + iommu_size;
- 	iommu_size -= round_up(a, LARGE_PAGE_SIZE) - a;
- 
--	if (iommu_size < 64*1024*1024) 
++	iommu_size -= round_up(a, PMD_PAGE_SIZE) - a;
++
 +	if (iommu_size < 64*1024*1024) {
  		printk(KERN_WARNING
 -  "PCI-DMA: Warning: Small IOMMU %luMB. Consider increasing the AGP aperture in BIOS\n",iommu_size>>20); 
@@ -280252,7 +304925,7 @@
  	int i;
  
  	printk(KERN_INFO "PCI-DMA: Disabling AGP.\n");
-@@ -509,75 +550,75 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
+@@ -509,75 +566,75 @@ static __init int init_k8_gatt(struct agp_kern_info *info)
  	dev = NULL;
  	for (i = 0; i < num_k8_northbridges; i++) {
  		dev = k8_northbridges[i];
@@ -280366,7 +305039,7 @@
  };
  
  void gart_iommu_shutdown(void)
-@@ -588,23 +629,23 @@ void gart_iommu_shutdown(void)
+@@ -588,23 +645,23 @@ void gart_iommu_shutdown(void)
  	if (no_agp && (dma_ops != &gart_dma_ops))
  		return;
  
@@ -280399,7 +305072,7 @@
  	unsigned long scratch;
  	long i;
  
-@@ -614,14 +655,14 @@ void __init gart_iommu_init(void)
+@@ -614,14 +671,14 @@ void __init gart_iommu_init(void)
  	}
  
  #ifndef CONFIG_AGP_AMD64
@@ -280418,7 +305091,7 @@
  
  	if (swiotlb)
  		return;
-@@ -643,77 +684,78 @@ void __init gart_iommu_init(void)
+@@ -643,77 +700,79 @@ void __init gart_iommu_init(void)
  	}
  
  	printk(KERN_INFO "PCI-DMA: using GART IOMMU.\n");
@@ -280493,7 +305166,9 @@
 -	 * devices. 
 +	 * devices.
  	 */
- 	clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size);
+-	clear_kernel_mapping((unsigned long)__va(iommu_bus_base), iommu_size);
++	set_memory_np((unsigned long)__va(iommu_bus_base),
++				iommu_size >> PAGE_SHIFT);
  
 -	/* 
 -	 * Try to workaround a bug (thanks to BenH) 
@@ -280529,7 +305204,7 @@
  		leak_trace = 1;
  		p += 4;
  		if (*p == '=') ++p;
-@@ -723,18 +765,18 @@ void __init gart_parse_options(char *p)
+@@ -723,18 +782,18 @@ void __init gart_parse_options(char *p)
  #endif
  	if (isdigit(*p) && get_option(&p, &arg))
  		iommu_size = arg;
@@ -280587,7 +305262,7 @@
  {
  	/* The Power Management Timer ticks at 3.579545 ticks per microsecond.
 diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
-index 46d391d..968371a 100644
+index 46d391d..dabdbef 100644
 --- a/arch/x86/kernel/process_32.c
 +++ b/arch/x86/kernel/process_32.c
 @@ -55,6 +55,7 @@
@@ -280649,6 +305324,15 @@
  			if (!idle)
  				idle = default_idle;
  
+@@ -238,7 +251,7 @@ void cpu_idle_wait(void)
+ 		 * because it has nothing to do.
+ 		 * Give all the remaining CPUS a kick.
+ 		 */
+-		smp_call_function_mask(map, do_nothing, 0, 0);
++		smp_call_function_mask(map, do_nothing, NULL, 0);
+ 	} while (!cpus_empty(map));
+ 
+ 	set_cpus_allowed(current, tmp);
 @@ -255,13 +268,13 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
   * New with Core Duo processors, MWAIT can take some hints based on CPU
   * capability.
@@ -286892,7 +311576,7 @@
 +
 +subsys_initcall(request_standard_resources);
 diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
-index 30d94d1..18df70c 100644
+index 30d94d1..c8939df 100644
 --- a/arch/x86/kernel/setup_64.c
 +++ b/arch/x86/kernel/setup_64.c
 @@ -30,6 +30,7 @@
@@ -287726,7 +312410,7 @@
  
  	/*
  	 * On SMP, boot_cpu_data holds the common feature set between
-@@ -965,32 +1009,56 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
+@@ -965,31 +1009,55 @@ void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
  	 */
  	if (c != &boot_cpu_data) {
  		/* AND the already accumulated flags with these */
@@ -287750,14 +312434,14 @@
  	numa_add_cpu(smp_processor_id());
  #endif
 +
-+}
+ }
+- 
 +
 +static __init int setup_noclflush(char *arg)
 +{
 +	setup_clear_cpu_cap(X86_FEATURE_CLFLSH);
 +	return 1;
- }
-- 
++}
 +__setup("noclflush", setup_noclflush);
  
  void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
@@ -287773,8 +312457,8 @@
  	else
 -		printk("\n");
 +		printk(KERN_CONT "\n");
- }
- 
++}
++
 +static __init int setup_disablecpuid(char *arg)
 +{
 +	int bit;
@@ -287783,40 +312467,95 @@
 +	else
 +		return 0;
 +	return 1;
-+}
+ }
 +__setup("clearcpuid=", setup_disablecpuid);
-+
+ 
  /*
   *	Get CPU information for use by the procfs.
-  */
-@@ -998,9 +1066,9 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
+@@ -998,116 +1066,41 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
  static int show_cpuinfo(struct seq_file *m, void *v)
  {
  	struct cpuinfo_x86 *c = v;
 -	int cpu = 0;
-+	int cpu = 0, i;
- 
+-
 -	/* 
-+	/*
- 	 * These flag bits must match the definitions in <asm/cpufeature.h>.
- 	 * NULL means this bit is undefined or reserved; either way it doesn't
- 	 * have meaning as far as Linux is concerned.  Note that it's important
-@@ -1010,10 +1078,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
- 	 */
- 	static const char *const x86_cap_flags[] = {
- 		/* Intel-defined */
+-	 * These flag bits must match the definitions in <asm/cpufeature.h>.
+-	 * NULL means this bit is undefined or reserved; either way it doesn't
+-	 * have meaning as far as Linux is concerned.  Note that it's important
+-	 * to realize there is a difference between this table and CPUID -- if
+-	 * applications want to get the raw CPUID data, they should access
+-	 * /dev/cpu/<cpu_nr>/cpuid instead.
+-	 */
+-	static const char *const x86_cap_flags[] = {
+-		/* Intel-defined */
 -	        "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
 -	        "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
 -	        "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
 -	        "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
-+		"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-+		"cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
-+		"pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
-+		"fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
- 
- 		/* AMD-defined */
- 		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-@@ -1080,34 +1148,35 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+-
+-		/* AMD-defined */
+-		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", "pdpe1gb", "rdtscp", NULL, "lm",
+-		"3dnowext", "3dnow",
+-
+-		/* Transmeta-defined */
+-		"recovery", "longrun", NULL, "lrti", 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,
+-
+-		/* Other (Linux-defined) */
+-		"cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+-		NULL, NULL, NULL, NULL,
+-		"constant_tsc", "up", NULL, "arch_perfmon",
+-		"pebs", "bts", NULL, "sync_rdtsc",
+-		"rep_good", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Intel-defined (#2) */
+-		"pni", NULL, NULL, "monitor", "ds_cpl", "vmx", "smx", "est",
+-		"tm2", "ssse3", "cid", NULL, NULL, "cx16", "xtpr", NULL,
+-		NULL, NULL, "dca", "sse4_1", "sse4_2", NULL, NULL, "popcnt",
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* VIA/Cyrix/Centaur-defined */
+-		NULL, NULL, "rng", "rng_en", NULL, NULL, "ace", "ace_en",
+-		"ace2", "ace2_en", "phe", "phe_en", "pmm", "pmm_en", 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", "svm", "extapic",
+-		"cr8_legacy", "abm", "sse4a", "misalignsse",
+-		"3dnowprefetch", "osvw", "ibs", "sse5",
+-		"skinit", "wdt", NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-		NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+-
+-		/* Auxiliary (Linux-defined) */
+-		"ida", 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 const char *const x86_power_flags[] = {
+-		"ts",	/* temperature sensor */
+-		"fid",  /* frequency id control */
+-		"vid",  /* voltage id control */
+-		"ttp",  /* thermal trip */
+-		"tm",
+-		"stc",
+-		"100mhzsteps",
+-		"hwpstate",
+-		"",	/* tsc invariant mapped to constant_tsc */
+-		/* nothing */
+-	};
+-
++	int cpu = 0, i;
+ 
+ #ifdef CONFIG_SMP
  	cpu = c->cpu_index;
  #endif
  
@@ -287868,7 +312607,7 @@
  #ifdef CONFIG_SMP
  	if (smp_num_siblings * c->x86_max_cores > 1) {
  		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
-@@ -1116,48 +1185,43 @@ static int show_cpuinfo(struct seq_file *m, void *v)
+@@ -1116,48 +1109,43 @@ static int show_cpuinfo(struct seq_file *m, void *v)
  		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
  		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
  	}
@@ -287939,7 +312678,7 @@
  	}
  
  	seq_printf(m, "\n\n");
-@@ -1184,8 +1248,8 @@ static void c_stop(struct seq_file *m, void *v)
+@@ -1184,8 +1172,8 @@ static void c_stop(struct seq_file *m, void *v)
  {
  }
  
@@ -290101,6 +314840,20 @@
  asmlinkage long sys_uname(struct new_utsname __user * name)
  {
  	int err;
+diff --git a/arch/x86/kernel/syscall_table_32.S b/arch/x86/kernel/syscall_table_32.S
+index 8344c70..adff556 100644
+--- a/arch/x86/kernel/syscall_table_32.S
++++ b/arch/x86/kernel/syscall_table_32.S
+@@ -321,6 +321,8 @@ ENTRY(sys_call_table)
+ 	.long sys_epoll_pwait
+ 	.long sys_utimensat		/* 320 */
+ 	.long sys_signalfd
+-	.long sys_timerfd
++	.long sys_timerfd_create
+ 	.long sys_eventfd
+ 	.long sys_fallocate
++	.long sys_timerfd_settime	/* 325 */
++	.long sys_timerfd_gettime
 diff --git a/arch/x86/kernel/sysenter_32.c b/arch/x86/kernel/sysenter_32.c
 deleted file mode 100644
 index 5a2d951..0000000
@@ -290455,10 +315208,10 @@
 -}
 diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
 new file mode 100644
-index 0000000..ae0ef2e
+index 0000000..36c100c
 --- /dev/null
 +++ b/arch/x86/kernel/test_nx.c
-@@ -0,0 +1,181 @@
+@@ -0,0 +1,173 @@
 +/*
 + * test_nx.c: functional test for NX functionality
 + *
@@ -290473,6 +315226,7 @@
 +#include <linux/module.h>
 +#include <linux/sort.h>
 +#include <asm/uaccess.h>
++#include <asm/asm.h>
 +
 +extern int rodata_test_data;
 +
@@ -290550,16 +315304,7 @@
 +		"2:	mov %[zero], %[rslt]\n"
 +		"	ret\n"
 +		".previous\n"
-+		".section __ex_table,\"a\"\n"
-+		"       .align 8\n"
-+#ifdef CONFIG_X86_32
-+		"	.long 0b\n"
-+		"	.long 2b\n"
-+#else
-+		"	.quad 0b\n"
-+		"	.quad 2b\n"
-+#endif
-+		".previous\n"
++		_ASM_EXTABLE(0b,2b)
 +		: [rslt] "=r" (result)
 +		: [fake_code] "r" (address), [zero] "r" (0UL), "0" (result)
 +	);
@@ -291442,6 +316187,38 @@
  #endif /*CONFIG_HOTPLUG_CPU*/
  
  static int __init topology_init(void)
+diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
+index 9bcc1c6..6458067 100644
+--- a/arch/x86/kernel/trampoline_32.S
++++ b/arch/x86/kernel/trampoline_32.S
+@@ -11,12 +11,7 @@
+  *	trampoline page to make our stack and everything else
+  *	is a mystery.
+  *
+- *	In fact we don't actually need a stack so we don't
+- *	set one up.
+- *
+- *	We jump into the boot/compressed/head.S code. So you'd
+- *	better be running a compressed kernel image or you
+- *	won't get very far.
++ *	We jump into arch/x86/kernel/head_32.S.
+  *
+  *	On entry to trampoline_data, the processor is in real mode
+  *	with 16-bit addressing and 16-bit data.  CS has some value
+diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
+index e30b67c..4aedd0b 100644
+--- a/arch/x86/kernel/trampoline_64.S
++++ b/arch/x86/kernel/trampoline_64.S
+@@ -10,9 +10,6 @@
+  *	trampoline page to make our stack and everything else
+  *	is a mystery.
+  *
+- *	In fact we don't actually need a stack so we don't
+- *	set one up.
+- *
+  *	On entry to trampoline_data, the processor is in real mode
+  *	with 16-bit addressing and 16-bit data.  CS has some value
+  *	and IP is zero.  Thus, data addresses need to be absolute
 diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c
 index 02d1e1e..3cf7297 100644
 --- a/arch/x86/kernel/traps_32.c
@@ -293603,7 +318380,7 @@
  		if (data32) {
  			set_vflags_long(newflags, regs);
 diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
-index f02bad6..4525bc2 100644
+index f02bad6..12affe1 100644
 --- a/arch/x86/kernel/vmi_32.c
 +++ b/arch/x86/kernel/vmi_32.c
 @@ -62,7 +62,10 @@ static struct {
@@ -293761,21 +318538,21 @@
 +static void vmi_write_idt_entry(gate_desc *dt, int entry, const gate_desc *g)
 +{
 +	u32 *idt_entry = (u32 *)g;
-+	vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[2]);
++	vmi_ops.write_idt_entry(dt, entry, idt_entry[0], idt_entry[1]);
 +}
 +
 +static void vmi_write_gdt_entry(struct desc_struct *dt, int entry,
 +				const void *desc, int type)
 +{
 +	u32 *gdt_entry = (u32 *)desc;
-+	vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[2]);
++	vmi_ops.write_gdt_entry(dt, entry, gdt_entry[0], gdt_entry[1]);
 +}
 +
 +static void vmi_write_ldt_entry(struct desc_struct *dt, int entry,
 +				const void *desc)
 +{
 +	u32 *ldt_entry = (u32 *)desc;
-+	vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[2]);
++	vmi_ops.write_idt_entry(dt, entry, ldt_entry[0], ldt_entry[1]);
 +}
 +
 +static void vmi_load_sp0(struct tss_struct *tss,
@@ -294652,10 +319429,10 @@
 +#endif
 diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
 new file mode 100644
-index 0000000..c83e1c9
+index 0000000..41962e7
 --- /dev/null
 +++ b/arch/x86/kvm/Kconfig
-@@ -0,0 +1,57 @@
+@@ -0,0 +1,58 @@
 +#
 +# KVM configuration
 +#
@@ -294711,6 +319488,7 @@
 +# OK, it's a little counter-intuitive to do this, but it puts it neatly under
 +# the virtualization menu.
 +source drivers/lguest/Kconfig
++source drivers/virtio/Kconfig
 +
 +endif # VIRTUALIZATION
 diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
@@ -304185,7 +328963,7 @@
 +#endif
 diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
 new file mode 100644
-index 0000000..8f94a0b
+index 0000000..cf53081
 --- /dev/null
 +++ b/arch/x86/kvm/x86.c
 @@ -0,0 +1,3287 @@
@@ -305930,7 +330708,7 @@
 +	if (bytes == 8) {
 +		gpa_t gpa;
 +		struct page *page;
-+		char *addr;
++		char *kaddr;
 +		u64 val;
 +
 +		down_read(&current->mm->mmap_sem);
@@ -305945,9 +330723,9 @@
 +
 +		val = *(u64 *)new;
 +		page = gfn_to_page(vcpu->kvm, gpa >> PAGE_SHIFT);
-+		addr = kmap_atomic(page, KM_USER0);
-+		set_64bit((u64 *)(addr + offset_in_page(gpa)), val);
-+		kunmap_atomic(addr, KM_USER0);
++		kaddr = kmap_atomic(page, KM_USER0);
++		set_64bit((u64 *)(kaddr + offset_in_page(gpa)), val);
++		kunmap_atomic(kaddr, KM_USER0);
 +		kvm_release_page_dirty(page);
 +	emul_write:
 +		up_read(&current->mm->mmap_sem);
@@ -309593,7 +334371,7 @@
  	 * to boot as normal.  It never returns. */
  	start_kernel();
 diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
-index 329da27..4876182 100644
+index 329da27..25df1c1 100644
 --- a/arch/x86/lib/Makefile
 +++ b/arch/x86/lib/Makefile
 @@ -1,5 +1,27 @@
@@ -309622,7 +334400,7 @@
 +
 +        lib-y += csum-partial_64.o csum-copy_64.o csum-wrappers_64.o
 +        lib-y += thunk_64.o clear_page_64.o copy_page_64.o
-+        lib-y += bitstr_64.o bitops_64.o
++        lib-y += bitops_64.o
 +        lib-y += memmove_64.o memset_64.o
 +        lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
  endif
@@ -309662,6 +334440,66 @@
 -	usercopy_64.o getuser_64.o putuser_64.o  \
 -	thunk_64.o clear_page_64.o copy_page_64.o bitstr_64.o bitops_64.o
 -lib-y += memcpy_64.o memmove_64.o memset_64.o copy_user_64.o rwlock_64.o copy_user_nocache_64.o
+diff --git a/arch/x86/lib/bitops_32.c b/arch/x86/lib/bitops_32.c
+index afd0045..b654404 100644
+--- a/arch/x86/lib/bitops_32.c
++++ b/arch/x86/lib/bitops_32.c
+@@ -2,7 +2,7 @@
+ #include <linux/module.h>
+ 
+ /**
+- * find_next_bit - find the first set bit in a memory region
++ * find_next_bit - find the next set bit in a memory region
+  * @addr: The address to base the search on
+  * @offset: The bitnumber to start searching at
+  * @size: The maximum size to search
+diff --git a/arch/x86/lib/bitops_64.c b/arch/x86/lib/bitops_64.c
+index 95b6d96..0e8f491 100644
+--- a/arch/x86/lib/bitops_64.c
++++ b/arch/x86/lib/bitops_64.c
+@@ -58,7 +58,7 @@ long find_first_zero_bit(const unsigned long * addr, unsigned long size)
+ }
+ 
+ /**
+- * find_next_zero_bit - find the first zero bit in a memory region
++ * find_next_zero_bit - find the next zero bit in a memory region
+  * @addr: The address to base the search on
+  * @offset: The bitnumber to start searching at
+  * @size: The maximum size to search
+diff --git a/arch/x86/lib/bitstr_64.c b/arch/x86/lib/bitstr_64.c
+deleted file mode 100644
+index 7445caf..0000000
+--- a/arch/x86/lib/bitstr_64.c
++++ /dev/null
+@@ -1,28 +0,0 @@
+-#include <linux/module.h>
+-#include <linux/bitops.h>
+-
+-/* Find string of zero bits in a bitmap */ 
+-unsigned long 
+-find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len)
+-{ 
+-	unsigned long n, end, i; 	
+-
+- again:
+-	n = find_next_zero_bit(bitmap, nbits, start);
+-	if (n == -1) 
+-		return -1;
+-	
+-	/* could test bitsliced, but it's hardly worth it */
+-	end = n+len;
+-	if (end > nbits)
+-		return -1; 
+-	for (i = n+1; i < end; i++) { 
+-		if (test_bit(i, bitmap)) {  
+-			start = i+1; 
+-			goto again; 
+-		} 
+-	}
+-	return n;
+-}
+-
+-EXPORT_SYMBOL(find_next_zero_string);
 diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
 index 8ac51b8..37756b6 100644
 --- a/arch/x86/lib/memcpy_32.c
@@ -309692,6 +334530,90 @@
  		while (count--)
  			*--p = *--s;
  	}
+diff --git a/arch/x86/lib/mmx_32.c b/arch/x86/lib/mmx_32.c
+index 28084d2..cc9b4a4 100644
+--- a/arch/x86/lib/mmx_32.c
++++ b/arch/x86/lib/mmx_32.c
+@@ -4,6 +4,7 @@
+ #include <linux/hardirq.h>
+ #include <linux/module.h>
+ 
++#include <asm/asm.h>
+ #include <asm/i387.h>
+ 
+ 
+@@ -50,10 +51,7 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4\n"
+-		"	.long 1b, 3b\n"
+-		".previous"
++		_ASM_EXTABLE(1b,3b)
+ 		: : "r" (from) );
+ 		
+ 	
+@@ -81,10 +79,7 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
+ 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4\n"
+-		"	.long 1b, 3b\n"
+-		".previous"
++		_ASM_EXTABLE(1b,3b)
+ 		: : "r" (from), "r" (to) : "memory");
+ 		from+=64;
+ 		to+=64;
+@@ -181,10 +176,7 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4\n"
+-		"	.long 1b, 3b\n"
+-		".previous"
++		_ASM_EXTABLE(1b,3b)
+ 		: : "r" (from) );
+ 
+ 	for(i=0; i<(4096-320)/64; i++)
+@@ -211,10 +203,7 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4\n"
+-		"	.long 1b, 3b\n"
+-		".previous"
++		_ASM_EXTABLE(1b,3b)
+ 		: : "r" (from), "r" (to) : "memory");
+ 		from+=64;
+ 		to+=64;
+@@ -311,10 +300,7 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4\n"
+-		"	.long 1b, 3b\n"
+-		".previous"
++		_ASM_EXTABLE(1b,3b)
+ 		: : "r" (from) );
+ 
+ 	for(i=0; i<4096/64; i++)
+@@ -341,10 +327,7 @@ static void fast_copy_page(void *to, void *from)
+ 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
+ 		"   jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"	.align 4\n"
+-		"	.long 1b, 3b\n"
+-		".previous"
++		_ASM_EXTABLE(1b,3b)
+ 		: : "r" (from), "r" (to) : "memory");
+ 		from+=64;
+ 		to+=64;
 diff --git a/arch/x86/lib/semaphore_32.S b/arch/x86/lib/semaphore_32.S
 index 444fba4..3899bd3 100644
 --- a/arch/x86/lib/semaphore_32.S
@@ -309808,10 +334730,36 @@
  	thunk rwsem_down_read_failed_thunk,rwsem_down_read_failed
  	thunk rwsem_down_write_failed_thunk,rwsem_down_write_failed
 diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
-index 8bab2b2..9c4ffd5 100644
+index 8bab2b2..e849b99 100644
 --- a/arch/x86/lib/usercopy_32.c
 +++ b/arch/x86/lib/usercopy_32.c
-@@ -817,6 +817,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
+@@ -48,10 +48,7 @@ do {									   \
+ 		"3:	movl %5,%0\n"					   \
+ 		"	jmp 2b\n"					   \
+ 		".previous\n"						   \
+-		".section __ex_table,\"a\"\n"				   \
+-		"	.align 4\n"					   \
+-		"	.long 0b,3b\n"					   \
+-		".previous"						   \
++		_ASM_EXTABLE(0b,3b)					   \
+ 		: "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),	   \
+ 		  "=&D" (__d2)						   \
+ 		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
+@@ -132,11 +129,8 @@ do {									\
+ 		"3:	lea 0(%2,%0,4),%0\n"				\
+ 		"	jmp 2b\n"					\
+ 		".previous\n"						\
+-		".section __ex_table,\"a\"\n"				\
+-		"	.align 4\n"					\
+-		"	.long 0b,3b\n"					\
+-		"	.long 1b,2b\n"					\
+-		".previous"						\
++		_ASM_EXTABLE(0b,3b)					\
++		_ASM_EXTABLE(1b,2b)					\
+ 		: "=&c"(size), "=&D" (__d0)				\
+ 		: "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0));	\
+ } while (0)
+@@ -817,6 +811,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
  #endif
  	return n;
  }
@@ -309819,7 +334767,7 @@
  
  unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
  					unsigned long n)
-@@ -831,6 +832,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
+@@ -831,6 +826,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
  #endif
  	return n;
  }
@@ -309827,6 +334775,36 @@
  
  /**
   * copy_to_user: - Copy a block of data into user space.
+diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
+index 893d43f..0c89d1b 100644
+--- a/arch/x86/lib/usercopy_64.c
++++ b/arch/x86/lib/usercopy_64.c
+@@ -31,10 +31,7 @@ do {									   \
+ 		"3:	movq %5,%0\n"					   \
+ 		"	jmp 2b\n"					   \
+ 		".previous\n"						   \
+-		".section __ex_table,\"a\"\n"				   \
+-		"	.align 8\n"					   \
+-		"	.quad 0b,3b\n"					   \
+-		".previous"						   \
++		_ASM_EXTABLE(0b,3b)					   \
+ 		: "=r"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1),	   \
+ 		  "=&D" (__d2)						   \
+ 		: "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
+@@ -87,11 +84,8 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
+ 		"3:	lea 0(%[size1],%[size8],8),%[size8]\n"
+ 		"	jmp 2b\n"
+ 		".previous\n"
+-		".section __ex_table,\"a\"\n"
+-		"       .align 8\n"
+-		"	.quad 0b,3b\n"
+-		"	.quad 1b,2b\n"
+-		".previous"
++		_ASM_EXTABLE(0b,3b)
++		_ASM_EXTABLE(1b,2b)
+ 		: [size8] "=c"(size), [dst] "=&D" (__d0)
+ 		: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
+ 		  [zero] "r" (0UL), [eight] "r" (8UL));
 diff --git a/arch/x86/mach-rdc321x/Makefile b/arch/x86/mach-rdc321x/Makefile
 new file mode 100644
 index 0000000..1faac81
@@ -328937,10 +353915,10 @@
 -}
 diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
 new file mode 100644
-index 0000000..e4440d0
+index 0000000..ad8b973
 --- /dev/null
 +++ b/arch/x86/mm/fault.c
-@@ -0,0 +1,986 @@
+@@ -0,0 +1,974 @@
 +/*
 + *  Copyright (C) 1995  Linus Torvalds
 + *  Copyright (C) 2001,2002 Andi Kleen, SuSE Labs.
@@ -329183,7 +354161,8 @@
 +	pud = pud_offset(pgd, address);
 +	if (bad_address(pud)) goto bad;
 +	printk("PUD %lx ", pud_val(*pud));
-+	if (!pud_present(*pud))	goto ret;
++	if (!pud_present(*pud) || pud_large(*pud))
++		goto ret;
 +
 +	pmd = pmd_offset(pud, address);
 +	if (bad_address(pmd)) goto bad;
@@ -329451,6 +354430,10 @@
 +	pmd_t *pmd, *pmd_ref;
 +	pte_t *pte, *pte_ref;
 +
++	/* Make sure we are in vmalloc area */
++	if (!(address >= VMALLOC_START && address < VMALLOC_END))
++		return -1;
++
 +	/* Copy kernel mappings over when needed. This can also
 +	   happen within a race in page table update. In the later
 +	   case just flush. */
@@ -329546,6 +354529,9 @@
 +	 */
 +#ifdef CONFIG_X86_32
 +	if (unlikely(address >= TASK_SIZE)) {
++#else
++	if (unlikely(address >= TASK_SIZE64)) {
++#endif
 +		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
 +		    vmalloc_fault(address) >= 0)
 +			return;
@@ -329561,6 +354547,8 @@
 +		goto bad_area_nosemaphore;
 +	}
 +
++
++#ifdef CONFIG_X86_32
 +	/* It's safe to allow irq's after cr2 has been saved and the vmalloc
 +	   fault has been handled. */
 +	if (regs->flags & (X86_EFLAGS_IF|VM_MASK))
@@ -329573,28 +354561,6 @@
 +	if (in_atomic() || !mm)
 +		goto bad_area_nosemaphore;
 +#else /* CONFIG_X86_64 */
-+	if (unlikely(address >= TASK_SIZE64)) {
-+		/*
-+		 * Don't check for the module range here: its PML4
-+		 * is always initialized because it's shared with the main
-+		 * kernel text. Only vmalloc may need PML4 syncups.
-+		 */
-+		if (!(error_code & (PF_RSVD|PF_USER|PF_PROT)) &&
-+		      ((address >= VMALLOC_START && address < VMALLOC_END))) {
-+			if (vmalloc_fault(address) >= 0)
-+				return;
-+		}
-+
-+		/* Can handle a stale RO->RW TLB */
-+		if (spurious_fault(address, error_code))
-+			return;
-+
-+		/*
-+		 * Don't take the mm semaphore here. If we fixup a prefetch
-+		 * fault we could otherwise deadlock.
-+		 */
-+		goto bad_area_nosemaphore;
-+	}
 +	if (likely(regs->flags & X86_EFLAGS_IF))
 +		local_irq_enable();
 +
@@ -331309,10 +356275,10 @@
  		put_page(virt_to_page(spte));
  	spin_unlock(&mm->page_table_lock);
 diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
-index 3c76d19..f2f36f8 100644
+index 3c76d19..d1bc040 100644
 --- a/arch/x86/mm/init_32.c
 +++ b/arch/x86/mm/init_32.c
-@@ -27,7 +27,6 @@
+@@ -27,11 +27,11 @@
  #include <linux/bootmem.h>
  #include <linux/slab.h>
  #include <linux/proc_fs.h>
@@ -331320,7 +356286,12 @@
  #include <linux/memory_hotplug.h>
  #include <linux/initrd.h>
  #include <linux/cpumask.h>
-@@ -40,8 +39,10 @@
+ 
++#include <asm/asm.h>
+ #include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+@@ -40,8 +40,10 @@
  #include <asm/fixmap.h>
  #include <asm/e820.h>
  #include <asm/apic.h>
@@ -331331,7 +356302,7 @@
  #include <asm/sections.h>
  #include <asm/paravirt.h>
  
-@@ -50,7 +51,7 @@ unsigned int __VMALLOC_RESERVE = 128 << 20;
+@@ -50,7 +52,7 @@ unsigned int __VMALLOC_RESERVE = 128 << 20;
  DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
  unsigned long highstart_pfn, highend_pfn;
  
@@ -331340,7 +356311,7 @@
  
  /*
   * Creates a middle page table and puts a pointer to it in the
-@@ -61,26 +62,26 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
+@@ -61,26 +63,26 @@ static pmd_t * __init one_md_table_init(pgd_t *pgd)
  {
  	pud_t *pud;
  	pmd_t *pmd_table;
@@ -331372,7 +356343,7 @@
   */
  static pte_t * __init one_page_table_init(pmd_t *pmd)
  {
-@@ -90,9 +91,10 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
+@@ -90,9 +92,10 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
  #ifdef CONFIG_DEBUG_PAGEALLOC
  		page_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
  #endif
@@ -331384,7 +356355,7 @@
  
  		paravirt_alloc_pt(&init_mm, __pa(page_table) >> PAGE_SHIFT);
  		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
-@@ -103,22 +105,21 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
+@@ -103,22 +106,21 @@ static pte_t * __init one_page_table_init(pmd_t *pmd)
  }
  
  /*
@@ -331415,7 +356386,7 @@
  
  	vaddr = start;
  	pgd_idx = pgd_index(vaddr);
-@@ -128,7 +129,8 @@ static void __init page_table_range_init (unsigned long start, unsigned long end
+@@ -128,7 +130,8 @@ static void __init page_table_range_init (unsigned long start, unsigned long end
  	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
  		pmd = one_md_table_init(pgd);
  		pmd = pmd + pmd_index(vaddr);
@@ -331425,7 +356396,7 @@
  			one_page_table_init(pmd);
  
  			vaddr += PMD_SIZE;
-@@ -145,17 +147,17 @@ static inline int is_kernel_text(unsigned long addr)
+@@ -145,17 +148,17 @@ static inline int is_kernel_text(unsigned long addr)
  }
  
  /*
@@ -331447,7 +356418,7 @@
  
  	pgd_idx = pgd_index(PAGE_OFFSET);
  	pgd = pgd_base + pgd_idx;
-@@ -165,29 +167,43 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
+@@ -165,29 +168,43 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
  		pmd = one_md_table_init(pgd);
  		if (pfn >= max_low_pfn)
  			continue;
@@ -331510,7 +356481,7 @@
  			}
  		}
  	}
-@@ -200,57 +216,23 @@ static inline int page_kills_ppro(unsigned long pagenr)
+@@ -200,57 +217,23 @@ static inline int page_kills_ppro(unsigned long pagenr)
  	return 0;
  }
  
@@ -331576,7 +356547,7 @@
  	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
  	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
  
-@@ -259,11 +241,11 @@ static void __init kmap_init(void)
+@@ -259,11 +242,11 @@ static void __init kmap_init(void)
  
  static void __init permanent_kmaps_init(pgd_t *pgd_base)
  {
@@ -331589,7 +356560,7 @@
  
  	vaddr = PKMAP_BASE;
  	page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base);
-@@ -272,7 +254,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
+@@ -272,7 +255,7 @@ static void __init permanent_kmaps_init(pgd_t *pgd_base)
  	pud = pud_offset(pgd, vaddr);
  	pmd = pmd_offset(pud, vaddr);
  	pte = pte_offset_kernel(pmd, vaddr);
@@ -331598,7 +356569,7 @@
  }
  
  static void __meminit free_new_highpage(struct page *page)
-@@ -291,7 +273,8 @@ void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
+@@ -291,7 +274,8 @@ void __init add_one_highpage_init(struct page *page, int pfn, int bad_ppro)
  		SetPageReserved(page);
  }
  
@@ -331608,7 +356579,7 @@
  {
  	free_new_highpage(page);
  	totalram_pages++;
-@@ -299,6 +282,7 @@ static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long p
+@@ -299,6 +283,7 @@ static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long p
  	max_mapnr = max(pfn, max_mapnr);
  #endif
  	num_physpages++;
@@ -331616,7 +356587,7 @@
  	return 0;
  }
  
-@@ -306,7 +290,7 @@ static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long p
+@@ -306,7 +291,7 @@ static int __meminit add_one_highpage_hotplug(struct page *page, unsigned long p
   * Not currently handling the NUMA case.
   * Assuming single node and all memory that
   * has been added dynamically that would be
@@ -331625,7 +356596,7 @@
   */
  void __meminit online_page(struct page *page)
  {
-@@ -314,13 +298,11 @@ void __meminit online_page(struct page *page)
+@@ -314,13 +299,11 @@ void __meminit online_page(struct page *page)
  	add_one_highpage_hotplug(page, page_to_pfn(page));
  }
  
@@ -331641,7 +356612,7 @@
  	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++) {
  		/*
  		 * Holes under sparsemem might not have no mem_map[]:
-@@ -330,23 +312,18 @@ static void __init set_highmem_pages_init(int bad_ppro)
+@@ -330,23 +313,18 @@ static void __init set_highmem_pages_init(int bad_ppro)
  	}
  	totalram_pages += totalhigh_pages;
  }
@@ -331671,7 +356642,7 @@
  
  void __init native_pagetable_setup_start(pgd_t *base)
  {
-@@ -372,7 +349,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
+@@ -372,7 +350,7 @@ void __init native_pagetable_setup_start(pgd_t *base)
  	memset(&base[USER_PTRS_PER_PGD], 0,
  	       KERNEL_PGD_PTRS * sizeof(pgd_t));
  #else
@@ -331680,7 +356651,7 @@
  #endif
  }
  
-@@ -410,10 +387,10 @@ void __init native_pagetable_setup_done(pgd_t *base)
+@@ -410,10 +388,10 @@ void __init native_pagetable_setup_done(pgd_t *base)
   * be partially populated, and so it avoids stomping on any existing
   * mappings.
   */
@@ -331693,7 +356664,7 @@
  
  	paravirt_pagetable_setup_start(pgd_base);
  
-@@ -435,34 +412,36 @@ static void __init pagetable_init (void)
+@@ -435,34 +413,36 @@ static void __init pagetable_init (void)
  	 * Fixed mappings, only the page table structure has to be
  	 * created - mappings will be set by set_fixmap():
  	 */
@@ -331737,7 +356708,7 @@
  {
  	int i;
  
-@@ -474,22 +453,24 @@ void zap_low_mappings (void)
+@@ -474,22 +454,24 @@ void zap_low_mappings (void)
  	 * Note that "pgd_clear()" doesn't do it for
  	 * us, because pgd_clear() is a no-op on i386.
  	 */
@@ -331767,7 +356738,7 @@
  
  /*
   * noexec = on|off
-@@ -506,11 +487,14 @@ static int __init noexec_setup(char *str)
+@@ -506,11 +488,14 @@ static int __init noexec_setup(char *str)
  			__supported_pte_mask |= _PAGE_NX;
  			disable_nx = 0;
  		}
@@ -331787,7 +356758,7 @@
  
  	return 0;
  }
-@@ -522,6 +506,7 @@ static void __init set_nx(void)
+@@ -522,6 +507,7 @@ static void __init set_nx(void)
  
  	if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
  		cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
@@ -331795,7 +356766,7 @@
  		if ((v[3] & (1 << 20)) && !disable_nx) {
  			rdmsr(MSR_EFER, l, h);
  			l |= EFER_NX;
-@@ -531,35 +516,6 @@ static void __init set_nx(void)
+@@ -531,35 +517,6 @@ static void __init set_nx(void)
  		}
  	}
  }
@@ -331831,7 +356802,7 @@
  #endif
  
  /*
-@@ -574,9 +530,8 @@ void __init paging_init(void)
+@@ -574,9 +531,8 @@ void __init paging_init(void)
  #ifdef CONFIG_X86_PAE
  	set_nx();
  	if (nx_enabled)
@@ -331842,7 +356813,7 @@
  	pagetable_init();
  
  	load_cr3(swapper_pg_dir);
-@@ -600,10 +555,10 @@ void __init paging_init(void)
+@@ -600,10 +556,10 @@ void __init paging_init(void)
   * used to involve black magic jumps to work around some nasty CPU bugs,
   * but fortunately the switch to using exceptions got rid of all that.
   */
@@ -331855,7 +356826,7 @@
  
  	/* Any page-aligned address will do, the test is non-destructive */
  	__set_fixmap(FIX_WP_TEST, __pa(&swapper_pg_dir), PAGE_READONLY);
-@@ -611,47 +566,46 @@ static void __init test_wp_bit(void)
+@@ -611,47 +567,46 @@ static void __init test_wp_bit(void)
  	clear_fixmap(FIX_WP_TEST);
  
  	if (!boot_cpu_data.wp_works_ok) {
@@ -331915,7 +356886,7 @@
  		 */
  		if (page_is_ram(tmp) && PageReserved(pfn_to_page(tmp)))
  			reservedpages++;
-@@ -662,11 +616,12 @@ void __init mem_init(void)
+@@ -662,11 +617,12 @@ void __init mem_init(void)
  	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
  	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
  
@@ -331931,7 +356902,7 @@
  		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
  		num_physpages << (PAGE_SHIFT-10),
  		codesize >> 10,
-@@ -677,45 +632,46 @@ void __init mem_init(void)
+@@ -677,45 +633,46 @@ void __init mem_init(void)
  	       );
  
  #if 1 /* double-sanity-check paranoia */
@@ -332004,7 +356975,7 @@
  #endif /* double-sanity-check paranoia */
  
  #ifdef CONFIG_X86_PAE
-@@ -746,49 +702,38 @@ int arch_add_memory(int nid, u64 start, u64 size)
+@@ -746,49 +703,35 @@ int arch_add_memory(int nid, u64 start, u64 size)
  
  	return __add_pages(zone, start_pfn, nr_pages);
  }
@@ -332042,11 +357013,10 @@
 +		"	xorl %2, %2	\n"
  		"2:			\n"
 -		".section __ex_table,\"a\"\n"
-+		".section __ex_table, \"a\"\n"
- 		"	.align 4	\n"
+-		"	.align 4	\n"
 -		"	.long 1b,2b	\n"
-+		"	.long 1b, 2b	\n"
- 		".previous		\n"
+-		".previous		\n"
++		_ASM_EXTABLE(1b,2b)
  		:"=m" (*(char *)fix_to_virt(FIX_WP_TEST)),
  		 "=q" (tmp_reg),
  		 "=r" (flag)
@@ -332063,7 +357033,7 @@
  
  void mark_rodata_ro(void)
  {
-@@ -801,32 +746,58 @@ void mark_rodata_ro(void)
+@@ -801,32 +744,58 @@ void mark_rodata_ro(void)
  	if (num_possible_cpus() <= 1)
  #endif
  	{
@@ -332136,7 +357106,7 @@
  	for (addr = begin; addr < end; addr += PAGE_SIZE) {
  		ClearPageReserved(virt_to_page(addr));
  		init_page_count(virt_to_page(addr));
-@@ -835,6 +806,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
+@@ -835,6 +804,7 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
  		totalram_pages++;
  	}
  	printk(KERN_INFO "Freeing %s: %luk freed\n", what, (end - begin) >> 10);
@@ -332144,13 +357114,13 @@
  }
  
  void free_initmem(void)
-@@ -850,4 +822,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
+@@ -850,4 +820,3 @@ void free_initrd_mem(unsigned long start, unsigned long end)
  	free_init_pages("initrd memory", start, end);
  }
  #endif
 -
 diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
-index 0f9c8c8..eabcaed 100644
+index 0f9c8c8..3a98d6f 100644
 --- a/arch/x86/mm/init_64.c
 +++ b/arch/x86/mm/init_64.c
 @@ -43,12 +43,10 @@
@@ -332404,7 +357374,11 @@
  }
  
  static void __meminit
-@@ -259,16 +277,17 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+@@ -255,41 +273,40 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ 	int i = pmd_index(address);
+ 
+ 	for (; i < PTRS_PER_PMD; i++, address += PMD_SIZE) {
+-		unsigned long entry;
  		pmd_t *pmd = pmd_page + pmd_index(address);
  
  		if (address >= end) {
@@ -332420,11 +357394,13 @@
  			continue;
  
 -		entry = _PAGE_NX|_PAGE_PSE|_KERNPG_TABLE|_PAGE_GLOBAL|address;
-+		entry = __PAGE_KERNEL_LARGE|_PAGE_GLOBAL|address;
- 		entry &= __supported_pte_mask;
- 		set_pmd(pmd, __pmd(entry));
+-		entry &= __supported_pte_mask;
+-		set_pmd(pmd, __pmd(entry));
++		set_pte((pte_t *)pmd,
++			pfn_pte(address >> PAGE_SHIFT, PAGE_KERNEL_LARGE));
  	}
-@@ -277,19 +296,19 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end)
+ }
+ 
  static void __meminit
  phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end)
  {
@@ -332449,7 +357425,7 @@
  		unsigned long pmd_phys;
  		pud_t *pud = pud_page + pud_index(addr);
  		pmd_t *pmd;
-@@ -297,10 +316,11 @@ static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigne
+@@ -297,10 +314,11 @@ static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigne
  		if (addr >= end)
  			break;
  
@@ -332464,7 +357440,7 @@
  
  		if (pud_val(*pud)) {
  			phys_pmd_update(pud, addr, end);
-@@ -308,14 +328,16 @@ static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigne
+@@ -308,14 +326,16 @@ static void __meminit phys_pud_init(pud_t *pud_page, unsigned long addr, unsigne
  		}
  
  		pmd = alloc_low_page(&pmd_phys);
@@ -332483,7 +357459,7 @@
  
  static void __init find_early_table_space(unsigned long end)
  {
-@@ -326,11 +348,13 @@ static void __init find_early_table_space(unsigned long end)
+@@ -326,11 +346,13 @@ static void __init find_early_table_space(unsigned long end)
  	tables = round_up(puds * sizeof(pud_t), PAGE_SIZE) +
  		 round_up(pmds * sizeof(pmd_t), PAGE_SIZE);
  
@@ -332502,7 +357478,7 @@
  	if (table_start == -1UL)
  		panic("Cannot find space for the kernel page tables");
  
-@@ -342,20 +366,23 @@ static void __init find_early_table_space(unsigned long end)
+@@ -342,20 +364,23 @@ static void __init find_early_table_space(unsigned long end)
  		(table_start << PAGE_SHIFT) + tables);
  }
  
@@ -332536,7 +357512,7 @@
  	 */
  	if (!after_bootmem)
  		find_early_table_space(end);
-@@ -364,8 +391,8 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+@@ -364,8 +389,8 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
  	end = (unsigned long)__va(end);
  
  	for (; start < end; start = next) {
@@ -332546,7 +357522,7 @@
  		pud_t *pud;
  
  		if (after_bootmem)
-@@ -374,23 +401,28 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
+@@ -374,23 +399,28 @@ void __init_refok init_memory_mapping(unsigned long start, unsigned long end)
  			pud = alloc_low_page(&pud_phys);
  
  		next = start + PGDIR_SIZE;
@@ -332578,7 +357554,7 @@
  	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
  	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
  	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
-@@ -402,39 +434,48 @@ void __init paging_init(void)
+@@ -402,40 +432,6 @@ void __init paging_init(void)
  }
  #endif
  
@@ -332587,64 +357563,39 @@
 -   must be aligned to 2MB boundaries. 
 -   Does nothing when the mapping doesn't exist. */
 -void __init clear_kernel_mapping(unsigned long address, unsigned long size) 
-+/*
-+ * Unmap a kernel mapping if it exists. This is useful to avoid
-+ * prefetches from the CPU leading to inconsistent cache lines.
-+ * address and size must be aligned to 2MB boundaries.
-+ * Does nothing when the mapping doesn't exist.
-+ */
-+void __init clear_kernel_mapping(unsigned long address, unsigned long size)
- {
- 	unsigned long end = address + size;
- 
- 	BUG_ON(address & ~LARGE_PAGE_MASK);
+-{
+-	unsigned long end = address + size;
+-
+-	BUG_ON(address & ~LARGE_PAGE_MASK);
 -	BUG_ON(size & ~LARGE_PAGE_MASK); 
 -	
 -	for (; address < end; address += LARGE_PAGE_SIZE) { 
-+	BUG_ON(size & ~LARGE_PAGE_MASK);
-+
-+	for (; address < end; address += LARGE_PAGE_SIZE) {
- 		pgd_t *pgd = pgd_offset_k(address);
- 		pud_t *pud;
- 		pmd_t *pmd;
-+
- 		if (pgd_none(*pgd))
- 			continue;
-+
- 		pud = pud_offset(pgd, address);
- 		if (pud_none(*pud))
+-		pgd_t *pgd = pgd_offset_k(address);
+-		pud_t *pud;
+-		pmd_t *pmd;
+-		if (pgd_none(*pgd))
+-			continue;
+-		pud = pud_offset(pgd, address);
+-		if (pud_none(*pud))
 -			continue; 
-+			continue;
-+
- 		pmd = pmd_offset(pud, address);
- 		if (!pmd || pmd_none(*pmd))
+-		pmd = pmd_offset(pud, address);
+-		if (!pmd || pmd_none(*pmd))
 -			continue; 
 -		if (0 == (pmd_val(*pmd) & _PAGE_PSE)) { 
 -			/* Could handle this, but it should not happen currently. */
 -			printk(KERN_ERR 
 -	       "clear_kernel_mapping: mapping has been split. will leak memory\n"); 
 -			pmd_ERROR(*pmd); 
-+			continue;
-+
-+		if (!(pmd_val(*pmd) & _PAGE_PSE)) {
-+			/*
-+			 * Could handle this, but it should not happen
-+			 * currently:
-+			 */
-+			printk(KERN_ERR "clear_kernel_mapping: "
-+				"mapping has been split. will leak memory\n");
-+			pmd_ERROR(*pmd);
- 		}
+-		}
 -		set_pmd(pmd, __pmd(0)); 		
-+		set_pmd(pmd, __pmd(0));
- 	}
- 	__flush_tlb_all();
+-	}
+-	__flush_tlb_all();
 -} 
-+}
- 
+-
  /*
   * Memory hotplug specific functions
-@@ -461,16 +502,12 @@ int arch_add_memory(int nid, u64 start, u64 size)
+  */
+@@ -461,16 +457,12 @@ int arch_add_memory(int nid, u64 start, u64 size)
  	unsigned long nr_pages = size >> PAGE_SHIFT;
  	int ret;
  
@@ -332663,7 +357614,7 @@
  }
  EXPORT_SYMBOL_GPL(arch_add_memory);
  
-@@ -484,36 +521,8 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
+@@ -484,36 +476,8 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
  
  #endif /* CONFIG_MEMORY_HOTPLUG */
  
@@ -332702,7 +357653,7 @@
  
  void __init mem_init(void)
  {
-@@ -521,8 +530,15 @@ void __init mem_init(void)
+@@ -521,8 +485,15 @@ void __init mem_init(void)
  
  	pci_iommu_alloc();
  
@@ -332720,7 +357671,7 @@
  
  	reservedpages = 0;
  
-@@ -534,7 +550,6 @@ void __init mem_init(void)
+@@ -534,7 +505,6 @@ void __init mem_init(void)
  #endif
  	reservedpages = end_pfn - totalram_pages -
  					absent_pages_in_range(0, end_pfn);
@@ -332728,7 +357679,7 @@
  	after_bootmem = 1;
  
  	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
-@@ -542,15 +557,16 @@ void __init mem_init(void)
+@@ -542,15 +512,16 @@ void __init mem_init(void)
  	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
  
  	/* Register memory areas for /proc/kcore */
@@ -332749,7 +357700,7 @@
  		(unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
  		end_pfn << (PAGE_SHIFT-10),
  		codesize >> 10,
-@@ -566,19 +582,27 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
+@@ -566,19 +537,27 @@ void free_init_pages(char *what, unsigned long begin, unsigned long end)
  	if (begin >= end)
  		return;
  
@@ -332781,7 +357732,7 @@
  }
  
  void free_initmem(void)
-@@ -589,6 +613,8 @@ void free_initmem(void)
+@@ -589,6 +568,8 @@ void free_initmem(void)
  }
  
  #ifdef CONFIG_DEBUG_RODATA
@@ -332790,7 +357741,7 @@
  
  void mark_rodata_ro(void)
  {
-@@ -603,25 +629,27 @@ void mark_rodata_ro(void)
+@@ -603,25 +584,27 @@ void mark_rodata_ro(void)
  #ifdef CONFIG_KPROBES
  	start = (unsigned long)__start_rodata;
  #endif
@@ -332827,7 +357778,7 @@
  }
  #endif
  
-@@ -632,17 +660,21 @@ void free_initrd_mem(unsigned long start, unsigned long end)
+@@ -632,17 +615,21 @@ void free_initrd_mem(unsigned long start, unsigned long end)
  }
  #endif
  
@@ -332853,7 +357804,7 @@
  		printk(KERN_ERR "reserve_bootmem: illegal reserve %lx %u\n",
  				phys, len);
  		return;
-@@ -650,9 +682,9 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+@@ -650,9 +637,9 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
  
  	/* Should check here against the e820 map to avoid double free */
  #ifdef CONFIG_NUMA
@@ -332866,7 +357817,7 @@
  #endif
  	if (phys+len <= MAX_DMA_PFN*PAGE_SIZE) {
  		dma_reserve += len / PAGE_SIZE;
-@@ -660,46 +692,49 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
+@@ -660,46 +647,49 @@ void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
  	}
  }
  
@@ -332933,7 +357884,7 @@
  };
  
  struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
-@@ -714,14 +749,17 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+@@ -714,14 +704,17 @@ struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
  int in_gate_area(struct task_struct *task, unsigned long addr)
  {
  	struct vm_area_struct *vma = get_gate_vma(task);
@@ -332954,7 +357905,7 @@
   */
  int in_gate_area_no_task(unsigned long addr)
  {
-@@ -741,8 +779,8 @@ const char *arch_vma_name(struct vm_area_struct *vma)
+@@ -741,8 +734,8 @@ const char *arch_vma_name(struct vm_area_struct *vma)
  /*
   * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
   */
@@ -332965,7 +357916,7 @@
  {
  	unsigned long addr = (unsigned long)start_page;
  	unsigned long end = (unsigned long)(start_page + size);
-@@ -757,6 +795,7 @@ int __meminit vmemmap_populate(struct page *start_page,
+@@ -757,6 +750,7 @@ int __meminit vmemmap_populate(struct page *start_page,
  		pgd = vmemmap_pgd_populate(addr, node);
  		if (!pgd)
  			return -ENOMEM;
@@ -332973,7 +357924,7 @@
  		pud = vmemmap_pud_populate(pgd, addr, node);
  		if (!pud)
  			return -ENOMEM;
-@@ -764,20 +803,22 @@ int __meminit vmemmap_populate(struct page *start_page,
+@@ -764,20 +758,22 @@ int __meminit vmemmap_populate(struct page *start_page,
  		pmd = pmd_offset(pud, addr);
  		if (pmd_none(*pmd)) {
  			pte_t entry;
@@ -333003,10 +357954,10 @@
  #endif
 diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
 new file mode 100644
-index 0000000..c004d94
+index 0000000..ee6648f
 --- /dev/null
 +++ b/arch/x86/mm/ioremap.c
-@@ -0,0 +1,502 @@
+@@ -0,0 +1,485 @@
 +/*
 + * Re-map IO memory to kernel address space so that we can access it.
 + * This is needed for high PCI addresses that aren't mapped in the
@@ -333079,25 +358030,12 @@
 + * Fix up the linear direct mapping of the kernel to avoid cache attribute
 + * conflicts.
 + */
-+static int ioremap_change_attr(unsigned long paddr, unsigned long size,
++static int ioremap_change_attr(unsigned long vaddr, unsigned long size,
 +			       enum ioremap_mode mode)
 +{
-+	unsigned long vaddr = (unsigned long)__va(paddr);
 +	unsigned long nrpages = size >> PAGE_SHIFT;
-+	unsigned int level;
 +	int err;
 +
-+	/* No change for pages after the last mapping */
-+	if ((paddr + size - 1) >= (max_pfn_mapped << PAGE_SHIFT))
-+		return 0;
-+
-+	/*
-+	 * If there is no identity map for this address,
-+	 * change_page_attr_addr is unnecessary
-+	 */
-+	if (!lookup_address(vaddr, &level))
-+		return 0;
-+
 +	switch (mode) {
 +	case IOR_MODE_UNCACHED:
 +	default:
@@ -333123,9 +358061,8 @@
 +static void __iomem *__ioremap(unsigned long phys_addr, unsigned long size,
 +			       enum ioremap_mode mode)
 +{
-+	void __iomem *addr;
++	unsigned long pfn, offset, last_addr, vaddr;
 +	struct vm_struct *area;
-+	unsigned long offset, last_addr;
 +	pgprot_t prot;
 +
 +	/* Don't allow wraparound or zero size */
@@ -333142,9 +358079,10 @@
 +	/*
 +	 * Don't allow anybody to remap normal RAM that we're using..
 +	 */
-+	for (offset = phys_addr >> PAGE_SHIFT; offset < max_pfn_mapped &&
-+	     (offset << PAGE_SHIFT) < last_addr; offset++) {
-+		if (page_is_ram(offset))
++	for (pfn = phys_addr >> PAGE_SHIFT; pfn < max_pfn_mapped &&
++	     (pfn << PAGE_SHIFT) < last_addr; pfn++) {
++		if (page_is_ram(pfn) && pfn_valid(pfn) &&
++		    !PageReserved(pfn_to_page(pfn)))
 +			return NULL;
 +	}
 +
@@ -333172,19 +358110,18 @@
 +	if (!area)
 +		return NULL;
 +	area->phys_addr = phys_addr;
-+	addr = (void __iomem *) area->addr;
-+	if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size,
-+			       phys_addr, prot)) {
-+		remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
++	vaddr = (unsigned long) area->addr;
++	if (ioremap_page_range(vaddr, vaddr + size, phys_addr, prot)) {
++		remove_vm_area((void *)(vaddr & PAGE_MASK));
 +		return NULL;
 +	}
 +
-+	if (ioremap_change_attr(phys_addr, size, mode) < 0) {
-+		vunmap(addr);
++	if (ioremap_change_attr(vaddr, size, mode) < 0) {
++		vunmap(area->addr);
 +		return NULL;
 +	}
 +
-+	return (void __iomem *) (offset + (char __iomem *)addr);
++	return (void __iomem *) (vaddr + offset);
 +}
 +
 +/**
@@ -333263,9 +358200,6 @@
 +		return;
 +	}
 +
-+	/* Reset the direct mapping. Can block */
-+	ioremap_change_attr(p->phys_addr, p->size, IOR_MODE_CACHED);
-+
 +	/* Finally remove it */
 +	o = remove_vm_area((void *)addr);
 +	BUG_ON(p != o || o == NULL);
@@ -334518,7 +359452,7 @@
 -}
 -
 diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
-index 3d6926b..a920d09 100644
+index 3d6926b..5a02bf4 100644
 --- a/arch/x86/mm/numa_64.c
 +++ b/arch/x86/mm/numa_64.c
 @@ -1,7 +1,7 @@
@@ -334660,7 +359594,7 @@
  {
  	int i, nodes_used = 0;
  	unsigned long start, end;
-@@ -140,56 +148,57 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
+@@ -140,59 +148,62 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes)
  		shift);
  
  	if (populate_memnodemap(nodes, numnodes, shift) != 1) {
@@ -334738,7 +359672,12 @@
  	if (node_data[nodeid] == NULL)
  		return;
  	nodedata_phys = __pa(node_data[nodeid]);
-@@ -200,75 +209,59 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
++	printk(KERN_INFO "  NODE_DATA [%016lx - %016lx]\n", nodedata_phys,
++		nodedata_phys + pgdat_size - 1);
+ 
+ 	memset(NODE_DATA(nodeid), 0, sizeof(pg_data_t));
+ 	NODE_DATA(nodeid)->bdata = &plat_node_bdata[nodeid];
+@@ -200,75 +211,62 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
  	NODE_DATA(nodeid)->node_spanned_pages = end_pfn - start_pfn;
  
  	/* Find a place for the bootmem map */
@@ -334763,13 +359702,16 @@
  	bootmap_start = __pa(bootmap);
 -	Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages); 
 -	
-+	Dprintk("bootmap start %lu pages %lu\n", bootmap_start, bootmap_pages);
 +
  	bootmap_size = init_bootmem_node(NODE_DATA(nodeid),
 -					 bootmap_start >> PAGE_SHIFT, 
 -					 start_pfn, end_pfn); 
 +					 bootmap_start >> PAGE_SHIFT,
 +					 start_pfn, end_pfn);
++
++	printk(KERN_INFO "  bootmap [%016lx -  %016lx] pages %lx\n",
++		 bootmap_start, bootmap_start + bootmap_size - 1,
++		 bootmap_pages);
  
  	free_bootmem_with_active_regions(nodeid, end);
  
@@ -334840,7 +359782,7 @@
  }
  
  #ifdef CONFIG_NUMA_EMU
-@@ -276,15 +269,17 @@ void __init numa_init_array(void)
+@@ -276,15 +274,17 @@ void __init numa_init_array(void)
  char *cmdline __initdata;
  
  /*
@@ -334862,7 +359804,7 @@
  	nodes[nid].start = *addr;
  	*addr += size;
  	if (*addr >= max_addr) {
-@@ -335,6 +330,7 @@ static int __init split_nodes_equally(struct bootnode *nodes, u64 *addr,
+@@ -335,6 +335,7 @@ static int __init split_nodes_equally(struct bootnode *nodes, u64 *addr,
  
  	for (i = node_start; i < num_nodes + node_start; i++) {
  		u64 end = *addr + size;
@@ -334870,7 +359812,7 @@
  		if (i < big)
  			end += FAKE_NODE_MIN_SIZE;
  		/*
-@@ -380,14 +376,9 @@ static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
+@@ -380,14 +381,9 @@ static int __init split_nodes_by_size(struct bootnode *nodes, u64 *addr,
  static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
  {
  	struct bootnode nodes[MAX_NUMNODES];
@@ -334887,7 +359829,7 @@
  
  	memset(&nodes, 0, sizeof(nodes));
  	/*
-@@ -395,8 +386,9 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
+@@ -395,8 +391,9 @@ static int __init numa_emulation(unsigned long start_pfn, unsigned long end_pfn)
  	 * system RAM into N fake nodes.
  	 */
  	if (!strchr(cmdline, '*') && !strchr(cmdline, ',')) {
@@ -334899,7 +359841,7 @@
  		if (num_nodes < 0)
  			return num_nodes;
  		goto out;
-@@ -483,46 +475,47 @@ out:
+@@ -483,46 +480,47 @@ out:
  	for_each_node_mask(i, node_possible_map) {
  		e820_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
  						nodes[i].end >> PAGE_SHIFT);
@@ -334958,7 +359900,7 @@
  	memnodemap = memnode.embedded_map;
  	memnodemap[0] = 0;
  	nodes_clear(node_online_map);
-@@ -530,36 +523,48 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
+@@ -530,36 +528,48 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
  	node_set(0, node_possible_map);
  	for (i = 0; i < NR_CPUS; i++)
  		numa_set_node(i, 0);
@@ -335019,7 +359961,7 @@
  	memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
  	max_zone_pfns[ZONE_DMA] = MAX_DMA_PFN;
  	max_zone_pfns[ZONE_DMA32] = MAX_DMA32_PFN;
-@@ -568,32 +573,27 @@ void __init paging_init(void)
+@@ -568,32 +578,27 @@ void __init paging_init(void)
  	sparse_memory_present_with_active_regions(MAX_NUMNODES);
  	sparse_init();
  
@@ -335059,7 +360001,7 @@
  early_param("numa", numa_setup);
  
  /*
-@@ -611,38 +611,16 @@ early_param("numa", numa_setup);
+@@ -611,38 +616,16 @@ early_param("numa", numa_setup);
  void __init init_cpu_to_node(void)
  {
  	int i;
@@ -335105,10 +360047,10 @@
 -#endif
 diff --git a/arch/x86/mm/pageattr-test.c b/arch/x86/mm/pageattr-test.c
 new file mode 100644
-index 0000000..7573e78
+index 0000000..398f3a5
 --- /dev/null
 +++ b/arch/x86/mm/pageattr-test.c
-@@ -0,0 +1,224 @@
+@@ -0,0 +1,225 @@
 +/*
 + * self test for change_page_attr.
 + *
@@ -335248,7 +360190,8 @@
 +
 +		for (k = 0; k < len[i]; k++) {
 +			pte = lookup_address(addr[i] + k*PAGE_SIZE, &level);
-+			if (!pte || pgprot_val(pte_pgprot(*pte)) == 0) {
++			if (!pte || pgprot_val(pte_pgprot(*pte)) == 0 ||
++			    !(pte_val(*pte) & _PAGE_PRESENT)) {
 +				addr[i] = 0;
 +				break;
 +			}
@@ -335335,10 +360278,10 @@
 +module_init(exercise_pageattr);
 diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
 new file mode 100644
-index 0000000..e297bd6
+index 0000000..16ce841
 --- /dev/null
 +++ b/arch/x86/mm/pageattr.c
-@@ -0,0 +1,563 @@
+@@ -0,0 +1,796 @@
 +/*
 + * Copyright 2002 Andi Kleen, SuSE Labs.
 + * Thanks to Ben LaHaise for precious feedback.
@@ -335357,6 +360300,17 @@
 +#include <asm/uaccess.h>
 +#include <asm/pgalloc.h>
 +
++/*
++ * The current flushing context - we pass it instead of 5 arguments:
++ */
++struct cpa_data {
++	unsigned long	vaddr;
++	pgprot_t	mask_set;
++	pgprot_t	mask_clr;
++	int		numpages;
++	int		flushtlb;
++};
++
 +static inline int
 +within(unsigned long addr, unsigned long start, unsigned long end)
 +{
@@ -335393,21 +360347,23 @@
 +
 +static void __cpa_flush_all(void *arg)
 +{
++	unsigned long cache = (unsigned long)arg;
++
 +	/*
 +	 * Flush all to work around Errata in early athlons regarding
 +	 * large page flushing.
 +	 */
 +	__flush_tlb_all();
 +
-+	if (boot_cpu_data.x86_model >= 4)
++	if (cache && boot_cpu_data.x86_model >= 4)
 +		wbinvd();
 +}
 +
-+static void cpa_flush_all(void)
++static void cpa_flush_all(unsigned long cache)
 +{
 +	BUG_ON(irqs_disabled());
 +
-+	on_each_cpu(__cpa_flush_all, NULL, 1, 1);
++	on_each_cpu(__cpa_flush_all, (void *) cache, 1, 1);
 +}
 +
 +static void __cpa_flush_range(void *arg)
@@ -335420,7 +360376,7 @@
 +	__flush_tlb_all();
 +}
 +
-+static void cpa_flush_range(unsigned long start, int numpages)
++static void cpa_flush_range(unsigned long start, int numpages, int cache)
 +{
 +	unsigned int i, level;
 +	unsigned long addr;
@@ -335430,6 +360386,9 @@
 +
 +	on_each_cpu(__cpa_flush_range, NULL, 1, 1);
 +
++	if (!cache)
++		return;
++
 +	/*
 +	 * We only need to flush on one CPU,
 +	 * clflush is a MESI-coherent instruction that
@@ -335442,11 +360401,27 @@
 +		/*
 +		 * Only flush present addresses:
 +		 */
-+		if (pte && pte_present(*pte))
++		if (pte && (pte_val(*pte) & _PAGE_PRESENT))
 +			clflush_cache_range((void *) addr, PAGE_SIZE);
 +	}
 +}
 +
++#define HIGH_MAP_START	__START_KERNEL_map
++#define HIGH_MAP_END	(__START_KERNEL_map + KERNEL_TEXT_SIZE)
++
++
++/*
++ * Converts a virtual address to a X86-64 highmap address
++ */
++static unsigned long virt_to_highmap(void *address)
++{
++#ifdef CONFIG_X86_64
++	return __pa((unsigned long)address) + HIGH_MAP_START - phys_base;
++#else
++	return (unsigned long)address;
++#endif
++}
++
 +/*
 + * Certain areas of memory on x86 require very specific protection flags,
 + * for example the BIOS area or kernel text. Callers don't always get this
@@ -335470,12 +360445,24 @@
 +	 */
 +	if (within(address, (unsigned long)_text, (unsigned long)_etext))
 +		pgprot_val(forbidden) |= _PAGE_NX;
++	/*
++	 * Do the same for the x86-64 high kernel mapping
++	 */
++	if (within(address, virt_to_highmap(_text), virt_to_highmap(_etext)))
++		pgprot_val(forbidden) |= _PAGE_NX;
++
 +
 +#ifdef CONFIG_DEBUG_RODATA
 +	/* The .rodata section needs to be read-only */
 +	if (within(address, (unsigned long)__start_rodata,
 +				(unsigned long)__end_rodata))
 +		pgprot_val(forbidden) |= _PAGE_RW;
++	/*
++	 * Do the same for the x86-64 high kernel mapping
++	 */
++	if (within(address, virt_to_highmap(__start_rodata),
++				virt_to_highmap(__end_rodata)))
++		pgprot_val(forbidden) |= _PAGE_RW;
 +#endif
 +
 +	prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
@@ -335483,6 +360470,14 @@
 +	return prot;
 +}
 +
++/*
++ * Lookup the page table entry for a virtual address. Return a pointer
++ * to the entry and the level of the mapping.
++ *
++ * Note: We return pud and pmd either when the entry is marked large
++ * or when the present bit is not set. Otherwise we would return a
++ * pointer to a nonexisting mapping.
++ */
 +pte_t *lookup_address(unsigned long address, int *level)
 +{
 +	pgd_t *pgd = pgd_offset_k(address);
@@ -335493,21 +360488,31 @@
 +
 +	if (pgd_none(*pgd))
 +		return NULL;
++
 +	pud = pud_offset(pgd, address);
 +	if (pud_none(*pud))
 +		return NULL;
++
++	*level = PG_LEVEL_1G;
++	if (pud_large(*pud) || !pud_present(*pud))
++		return (pte_t *)pud;
++
 +	pmd = pmd_offset(pud, address);
 +	if (pmd_none(*pmd))
 +		return NULL;
 +
 +	*level = PG_LEVEL_2M;
-+	if (pmd_large(*pmd))
++	if (pmd_large(*pmd) || !pmd_present(*pmd))
 +		return (pte_t *)pmd;
 +
 +	*level = PG_LEVEL_4K;
++
 +	return pte_offset_kernel(pmd, address);
 +}
 +
++/*
++ * Set the new pmd in all the pgds we know about:
++ */
 +static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte)
 +{
 +	/* change init_mm */
@@ -335530,18 +360535,114 @@
 +#endif
 +}
 +
++static int
++try_preserve_large_page(pte_t *kpte, unsigned long address,
++			struct cpa_data *cpa)
++{
++	unsigned long nextpage_addr, numpages, pmask, psize, flags;
++	pte_t new_pte, old_pte, *tmp;
++	pgprot_t old_prot, new_prot;
++	int level, do_split = 1;
++
++	/*
++	 * An Athlon 64 X2 showed hard hangs if we tried to preserve
++	 * largepages and changed the PSE entry from RW to RO.
++	 *
++	 * As AMD CPUs have a long series of erratas in this area,
++	 * (and none of the known ones seem to explain this hang),
++	 * disable this code until the hang can be debugged:
++	 */
++	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
++		return 1;
++
++	spin_lock_irqsave(&pgd_lock, flags);
++	/*
++	 * Check for races, another CPU might have split this page
++	 * up already:
++	 */
++	tmp = lookup_address(address, &level);
++	if (tmp != kpte)
++		goto out_unlock;
++
++	switch (level) {
++	case PG_LEVEL_2M:
++		psize = PMD_PAGE_SIZE;
++		pmask = PMD_PAGE_MASK;
++		break;
++#ifdef CONFIG_X86_64
++	case PG_LEVEL_1G:
++		psize = PMD_PAGE_SIZE;
++		pmask = PMD_PAGE_MASK;
++		break;
++#endif
++	default:
++		do_split = -EINVAL;
++		goto out_unlock;
++	}
++
++	/*
++	 * Calculate the number of pages, which fit into this large
++	 * page starting at address:
++	 */
++	nextpage_addr = (address + psize) & pmask;
++	numpages = (nextpage_addr - address) >> PAGE_SHIFT;
++	if (numpages < cpa->numpages)
++		cpa->numpages = numpages;
++
++	/*
++	 * We are safe now. Check whether the new pgprot is the same:
++	 */
++	old_pte = *kpte;
++	old_prot = new_prot = pte_pgprot(old_pte);
++
++	pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
++	pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
++	new_prot = static_protections(new_prot, address);
++
++	/*
++	 * If there are no changes, return. maxpages has been updated
++	 * above:
++	 */
++	if (pgprot_val(new_prot) == pgprot_val(old_prot)) {
++		do_split = 0;
++		goto out_unlock;
++	}
++
++	/*
++	 * We need to change the attributes. Check, whether we can
++	 * change the large page in one go. We request a split, when
++	 * the address is not aligned and the number of pages is
++	 * smaller than the number of pages in the large page. Note
++	 * that we limited the number of possible pages already to
++	 * the number of pages in the large page.
++	 */
++	if (address == (nextpage_addr - psize) && cpa->numpages == numpages) {
++		/*
++		 * The address is aligned and the number of pages
++		 * covers the full page.
++		 */
++		new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot));
++		__set_pmd_pte(kpte, address, new_pte);
++		cpa->flushtlb = 1;
++		do_split = 0;
++	}
++
++out_unlock:
++	spin_unlock_irqrestore(&pgd_lock, flags);
++
++	return do_split;
++}
++
 +static int split_large_page(pte_t *kpte, unsigned long address)
 +{
-+	pgprot_t ref_prot = pte_pgprot(pte_clrhuge(*kpte));
++	unsigned long flags, pfn, pfninc = 1;
 +	gfp_t gfp_flags = GFP_KERNEL;
-+	unsigned long flags;
-+	unsigned long addr;
++	unsigned int i, level;
 +	pte_t *pbase, *tmp;
++	pgprot_t ref_prot;
 +	struct page *base;
-+	unsigned int i, level;
 +
 +#ifdef CONFIG_DEBUG_PAGEALLOC
-+	gfp_flags = __GFP_HIGH | __GFP_NOFAIL | __GFP_NOWARN;
 +	gfp_flags = GFP_ATOMIC | __GFP_NOWARN;
 +#endif
 +	base = alloc_pages(gfp_flags, 0);
@@ -335554,30 +360655,41 @@
 +	 * up for us already:
 +	 */
 +	tmp = lookup_address(address, &level);
-+	if (tmp != kpte) {
-+		WARN_ON_ONCE(1);
++	if (tmp != kpte)
 +		goto out_unlock;
-+	}
 +
-+	address = __pa(address);
-+	addr = address & LARGE_PAGE_MASK;
 +	pbase = (pte_t *)page_address(base);
 +#ifdef CONFIG_X86_32
 +	paravirt_alloc_pt(&init_mm, page_to_pfn(base));
 +#endif
++	ref_prot = pte_pgprot(pte_clrhuge(*kpte));
++
++#ifdef CONFIG_X86_64
++	if (level == PG_LEVEL_1G) {
++		pfninc = PMD_PAGE_SIZE >> PAGE_SHIFT;
++		pgprot_val(ref_prot) |= _PAGE_PSE;
++	}
++#endif
 +
-+	pgprot_val(ref_prot) &= ~_PAGE_NX;
-+	for (i = 0; i < PTRS_PER_PTE; i++, addr += PAGE_SIZE)
-+		set_pte(&pbase[i], pfn_pte(addr >> PAGE_SHIFT, ref_prot));
++	/*
++	 * Get the target pfn from the original entry:
++	 */
++	pfn = pte_pfn(*kpte);
++	for (i = 0; i < PTRS_PER_PTE; i++, pfn += pfninc)
++		set_pte(&pbase[i], pfn_pte(pfn, ref_prot));
 +
 +	/*
-+	 * Install the new, split up pagetable. Important detail here:
++	 * Install the new, split up pagetable. Important details here:
 +	 *
 +	 * On Intel the NX bit of all levels must be cleared to make a
 +	 * page executable. See section 4.13.2 of Intel 64 and IA-32
 +	 * Architectures Software Developer's Manual).
++	 *
++	 * Mark the entry present. The current mapping might be
++	 * set to not present, which we preserved above.
 +	 */
 +	ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
++	pgprot_val(ref_prot) |= _PAGE_PRESENT;
 +	__set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
 +	base = NULL;
 +
@@ -335590,18 +360702,12 @@
 +	return 0;
 +}
 +
-+static int
-+__change_page_attr(unsigned long address, unsigned long pfn,
-+		   pgprot_t mask_set, pgprot_t mask_clr)
++static int __change_page_attr(unsigned long address, struct cpa_data *cpa)
 +{
++	int level, do_split, err;
 +	struct page *kpte_page;
-+	int level, err = 0;
 +	pte_t *kpte;
 +
-+#ifdef CONFIG_X86_32
-+	BUG_ON(pfn > max_low_pfn);
-+#endif
-+
 +repeat:
 +	kpte = lookup_address(address, &level);
 +	if (!kpte)
@@ -335612,23 +360718,62 @@
 +	BUG_ON(PageCompound(kpte_page));
 +
 +	if (level == PG_LEVEL_4K) {
-+		pgprot_t new_prot = pte_pgprot(*kpte);
 +		pte_t new_pte, old_pte = *kpte;
++		pgprot_t new_prot = pte_pgprot(old_pte);
++
++		if(!pte_val(old_pte)) {
++			printk(KERN_WARNING "CPA: called for zero pte. "
++			       "vaddr = %lx cpa->vaddr = %lx\n", address,
++				cpa->vaddr);
++			WARN_ON(1);
++			return -EINVAL;
++		}
 +
-+		pgprot_val(new_prot) &= ~pgprot_val(mask_clr);
-+		pgprot_val(new_prot) |= pgprot_val(mask_set);
++		pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
++		pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
 +
 +		new_prot = static_protections(new_prot, address);
 +
-+		new_pte = pfn_pte(pfn, canon_pgprot(new_prot));
-+		BUG_ON(pte_pfn(new_pte) != pte_pfn(old_pte));
++		/*
++		 * We need to keep the pfn from the existing PTE,
++		 * after all we're only going to change it's attributes
++		 * not the memory it points to
++		 */
++		new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot));
 +
-+		set_pte_atomic(kpte, new_pte);
-+	} else {
-+		err = split_large_page(kpte, address);
-+		if (!err)
-+			goto repeat;
++		/*
++		 * Do we really change anything ?
++		 */
++		if (pte_val(old_pte) != pte_val(new_pte)) {
++			set_pte_atomic(kpte, new_pte);
++			cpa->flushtlb = 1;
++		}
++		cpa->numpages = 1;
++		return 0;
++	}
++
++	/*
++	 * Check, whether we can keep the large page intact
++	 * and just change the pte:
++	 */
++	do_split = try_preserve_large_page(kpte, address, cpa);
++	/*
++	 * When the range fits into the existing large page,
++	 * return. cp->numpages and cpa->tlbflush have been updated in
++	 * try_large_page:
++	 */
++	if (do_split <= 0)
++		return do_split;
++
++	/*
++	 * We have to split the large page:
++	 */
++	err = split_large_page(kpte, address);
++	if (!err) {
++		cpa->flushtlb = 1;
++		goto repeat;
 +	}
++
 +	return err;
 +}
 +
@@ -335645,19 +360790,14 @@
 + *
 + * Modules and drivers should use the set_memory_* APIs instead.
 + */
-+
-+#define HIGH_MAP_START	__START_KERNEL_map
-+#define HIGH_MAP_END	(__START_KERNEL_map + KERNEL_TEXT_SIZE)
-+
-+static int
-+change_page_attr_addr(unsigned long address, pgprot_t mask_set,
-+		      pgprot_t mask_clr)
++static int change_page_attr_addr(struct cpa_data *cpa)
 +{
-+	unsigned long phys_addr = __pa(address);
-+	unsigned long pfn = phys_addr >> PAGE_SHIFT;
 +	int err;
++	unsigned long address = cpa->vaddr;
 +
 +#ifdef CONFIG_X86_64
++	unsigned long phys_addr = __pa(address);
++
 +	/*
 +	 * If we are inside the high mapped kernel range, then we
 +	 * fixup the low mapping first. __va() returns the virtual
@@ -335667,7 +360807,7 @@
 +		address = (unsigned long) __va(phys_addr);
 +#endif
 +
-+	err = __change_page_attr(address, pfn, mask_set, mask_clr);
++	err = __change_page_attr(address, cpa);
 +	if (err)
 +		return err;
 +
@@ -335680,42 +360820,89 @@
 +		/*
 +		 * Calc the high mapping address. See __phys_addr()
 +		 * for the non obvious details.
++		 *
++		 * Note that NX and other required permissions are
++		 * checked in static_protections().
 +		 */
 +		address = phys_addr + HIGH_MAP_START - phys_base;
-+		/* Make sure the kernel mappings stay executable */
-+		pgprot_val(mask_clr) |= _PAGE_NX;
 +
 +		/*
 +		 * Our high aliases are imprecise, because we check
 +		 * everything between 0 and KERNEL_TEXT_SIZE, so do
 +		 * not propagate lookup failures back to users:
 +		 */
-+		__change_page_attr(address, pfn, mask_set, mask_clr);
++		__change_page_attr(address, cpa);
 +	}
 +#endif
 +	return err;
 +}
 +
-+static int __change_page_attr_set_clr(unsigned long addr, int numpages,
-+				      pgprot_t mask_set, pgprot_t mask_clr)
++static int __change_page_attr_set_clr(struct cpa_data *cpa)
 +{
-+	unsigned int i;
-+	int ret;
++	int ret, numpages = cpa->numpages;
 +
-+	for (i = 0; i < numpages ; i++, addr += PAGE_SIZE) {
-+		ret = change_page_attr_addr(addr, mask_set, mask_clr);
++	while (numpages) {
++		/*
++		 * Store the remaining nr of pages for the large page
++		 * preservation check.
++		 */
++		cpa->numpages = numpages;
++		ret = change_page_attr_addr(cpa);
 +		if (ret)
 +			return ret;
-+	}
 +
++		/*
++		 * Adjust the number of pages with the result of the
++		 * CPA operation. Either a large page has been
++		 * preserved or a single page update happened.
++		 */
++		BUG_ON(cpa->numpages > numpages);
++		numpages -= cpa->numpages;
++		cpa->vaddr += cpa->numpages * PAGE_SIZE;
++	}
 +	return 0;
 +}
 +
++static inline int cache_attr(pgprot_t attr)
++{
++	return pgprot_val(attr) &
++		(_PAGE_PAT | _PAGE_PAT_LARGE | _PAGE_PWT | _PAGE_PCD);
++}
++
 +static int change_page_attr_set_clr(unsigned long addr, int numpages,
 +				    pgprot_t mask_set, pgprot_t mask_clr)
 +{
-+	int ret = __change_page_attr_set_clr(addr, numpages, mask_set,
-+					     mask_clr);
++	struct cpa_data cpa;
++	int ret, cache;
++
++	/*
++	 * Check, if we are requested to change a not supported
++	 * feature:
++	 */
++	mask_set = canon_pgprot(mask_set);
++	mask_clr = canon_pgprot(mask_clr);
++	if (!pgprot_val(mask_set) && !pgprot_val(mask_clr))
++		return 0;
++
++	cpa.vaddr = addr;
++	cpa.numpages = numpages;
++	cpa.mask_set = mask_set;
++	cpa.mask_clr = mask_clr;
++	cpa.flushtlb = 0;
++
++	ret = __change_page_attr_set_clr(&cpa);
++
++	/*
++	 * Check whether we really changed something:
++	 */
++	if (!cpa.flushtlb)
++		return ret;
++
++	/*
++	 * No need to flush, when we did not set any of the caching
++	 * attributes:
++	 */
++	cache = cache_attr(mask_set);
 +
 +	/*
 +	 * On success we use clflush, when the CPU supports it to
@@ -335724,9 +360911,9 @@
 +	 * wbindv):
 +	 */
 +	if (!ret && cpu_has_clflush)
-+		cpa_flush_range(addr, numpages);
++		cpa_flush_range(addr, numpages, cache);
 +	else
-+		cpa_flush_all();
++		cpa_flush_all(cache);
 +
 +	return ret;
 +}
@@ -335830,37 +361017,26 @@
 +	return set_memory_rw(addr, numpages);
 +}
 +
-+
-+#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_CPA_DEBUG)
-+static inline int __change_page_attr_set(unsigned long addr, int numpages,
-+					 pgprot_t mask)
-+{
-+	return __change_page_attr_set_clr(addr, numpages, mask, __pgprot(0));
-+}
-+
-+static inline int __change_page_attr_clear(unsigned long addr, int numpages,
-+					   pgprot_t mask)
-+{
-+	return __change_page_attr_set_clr(addr, numpages, __pgprot(0), mask);
-+}
-+#endif
-+
 +#ifdef CONFIG_DEBUG_PAGEALLOC
 +
 +static int __set_pages_p(struct page *page, int numpages)
 +{
-+	unsigned long addr = (unsigned long)page_address(page);
++	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
++				.numpages = numpages,
++				.mask_set = __pgprot(_PAGE_PRESENT | _PAGE_RW),
++				.mask_clr = __pgprot(0)};
 +
-+	return __change_page_attr_set(addr, numpages,
-+				      __pgprot(_PAGE_PRESENT | _PAGE_RW));
++	return __change_page_attr_set_clr(&cpa);
 +}
 +
 +static int __set_pages_np(struct page *page, int numpages)
 +{
-+	unsigned long addr = (unsigned long)page_address(page);
++	struct cpa_data cpa = { .vaddr = (unsigned long) page_address(page),
++				.numpages = numpages,
++				.mask_set = __pgprot(0),
++				.mask_clr = __pgprot(_PAGE_PRESENT | _PAGE_RW)};
 +
-+	return __change_page_attr_clear(addr, numpages,
-+					__pgprot(_PAGE_PRESENT));
++	return __change_page_attr_set_clr(&cpa);
 +}
 +
 +void kernel_map_pages(struct page *page, int numpages, int enable)
@@ -336448,7 +361624,7 @@
 -EXPORT_SYMBOL(change_page_attr);
 -EXPORT_SYMBOL(global_flush_tlb);
 diff --git a/arch/x86/mm/pgtable_32.c b/arch/x86/mm/pgtable_32.c
-index be61a1d..cb3aa47 100644
+index be61a1d..6c19146 100644
 --- a/arch/x86/mm/pgtable_32.c
 +++ b/arch/x86/mm/pgtable_32.c
 @@ -195,11 +195,6 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
@@ -336463,7 +361639,7 @@
  /*
   * List of all pgd's needed for non-PAE so it can invalidate entries
   * in both cached and uncached pgd's; not needed for PAE since the
-@@ -210,27 +205,18 @@ void pmd_ctor(struct kmem_cache *cache, void *pmd)
+@@ -210,73 +205,53 @@ void pmd_ctor(struct kmem_cache *cache, void *pmd)
   * vmalloc faults work because attached pagetables are never freed.
   * -- wli
   */
@@ -336490,13 +361666,79 @@
 -	*pprev = next;
 -	if (next)
 -		set_page_private(next, (unsigned long)pprev);
+-}
 +	struct page *page = virt_to_page(pgd);
-+
+ 
 +	list_del(&page->lru);
- }
++}
+ 
++#define UNSHARED_PTRS_PER_PGD				\
++	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+ 
+-#if (PTRS_PER_PMD == 1)
+-/* Non-PAE pgd constructor */
+-static void pgd_ctor(void *pgd)
++static void pgd_ctor(void *p)
+ {
++	pgd_t *pgd = p;
+ 	unsigned long flags;
+ 
+-	/* !PAE, no pagetable sharing */
++	/* Clear usermode parts of PGD */
+ 	memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+ 
+ 	spin_lock_irqsave(&pgd_lock, flags);
+ 
+-	/* must happen under lock */
+-	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+-			swapper_pg_dir + USER_PTRS_PER_PGD,
+-			KERNEL_PGD_PTRS);
+-	paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
+-				__pa(swapper_pg_dir) >> PAGE_SHIFT,
+-				USER_PTRS_PER_PGD,
+-				KERNEL_PGD_PTRS);
+-	pgd_list_add(pgd);
+-	spin_unlock_irqrestore(&pgd_lock, flags);
+-}
+-#else  /* PTRS_PER_PMD > 1 */
+-/* PAE pgd constructor */
+-static void pgd_ctor(void *pgd)
+-{
+-	/* PAE, kernel PMD may be shared */
+-
+-	if (SHARED_KERNEL_PMD) {
+-		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
++	/* If the pgd points to a shared pagetable level (either the
++	   ptes in non-PAE, or shared PMD in PAE), then just copy the
++	   references from swapper_pg_dir. */
++	if (PAGETABLE_LEVELS == 2 ||
++	    (PAGETABLE_LEVELS == 3 && SHARED_KERNEL_PMD)) {
++		clone_pgd_range(pgd + USER_PTRS_PER_PGD,
+ 				swapper_pg_dir + USER_PTRS_PER_PGD,
+ 				KERNEL_PGD_PTRS);
+-	} else {
+-		unsigned long flags;
++		paravirt_alloc_pd_clone(__pa(pgd) >> PAGE_SHIFT,
++					__pa(swapper_pg_dir) >> PAGE_SHIFT,
++					USER_PTRS_PER_PGD,
++					KERNEL_PGD_PTRS);
++	}
  
+-		memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
+-		spin_lock_irqsave(&pgd_lock, flags);
++	/* list required to sync kernel mapping updates */
++	if (!SHARED_KERNEL_PMD)
+ 		pgd_list_add(pgd);
+-		spin_unlock_irqrestore(&pgd_lock, flags);
+-	}
++
++	spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+-#endif	/* PTRS_PER_PMD */
  
-@@ -285,7 +271,6 @@ static void pgd_dtor(void *pgd)
+ static void pgd_dtor(void *pgd)
+ {
+@@ -285,86 +260,101 @@ static void pgd_dtor(void *pgd)
  	if (SHARED_KERNEL_PMD)
  		return;
  
@@ -336504,14 +361746,10 @@
  	spin_lock_irqsave(&pgd_lock, flags);
  	pgd_list_del(pgd);
  	spin_unlock_irqrestore(&pgd_lock, flags);
-@@ -294,77 +279,96 @@ static void pgd_dtor(void *pgd)
- #define UNSHARED_PTRS_PER_PGD				\
- 	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
+ }
  
--/* If we allocate a pmd for part of the kernel address space, then
--   make sure its initialized with the appropriate kernel mappings.
--   Otherwise use a cached zeroed pmd.  */
--static pmd_t *pmd_cache_alloc(int idx)
+-#define UNSHARED_PTRS_PER_PGD				\
+-	(SHARED_KERNEL_PMD ? USER_PTRS_PER_PGD : PTRS_PER_PGD)
 +#ifdef CONFIG_X86_PAE
 +/*
 + * Mop up any pmd pages which may still be attached to the pgd.
@@ -336519,9 +361757,8 @@
 + * preallocate which never got a corresponding vma will need to be
 + * freed manually.
 + */
-+static void pgd_mop_up_pmds(pgd_t *pgdp)
- {
--	pmd_t *pmd;
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
++{
 +	int i;
 +
 +	for(i = 0; i < UNSHARED_PTRS_PER_PGD; i++) {
@@ -336533,11 +361770,15 @@
 +			pgdp[i] = native_make_pgd(0);
 +
 +			paravirt_release_pd(pgd_val(pgd) >> PAGE_SHIFT);
-+			pmd_free(pmd);
++			pmd_free(mm, pmd);
 +		}
 +	}
 +}
-+
+ 
+-/* If we allocate a pmd for part of the kernel address space, then
+-   make sure its initialized with the appropriate kernel mappings.
+-   Otherwise use a cached zeroed pmd.  */
+-static pmd_t *pmd_cache_alloc(int idx)
 +/*
 + * In PAE mode, we need to do a cr3 reload (=tlb flush) when
 + * updating the top-level pagetable entries to guarantee the
@@ -336550,7 +361791,8 @@
 + * and initialize the kernel pmds here.
 + */
 +static int pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd)
-+{
+ {
+-	pmd_t *pmd;
 +	pud_t *pud;
 +	unsigned long addr;
 +	int i;
@@ -336561,15 +361803,15 @@
 + 	for (addr = i = 0; i < UNSHARED_PTRS_PER_PGD;
 +	     i++, pud++, addr += PUD_SIZE) {
 +		pmd_t *pmd = pmd_alloc_one(mm, addr);
++
++		if (!pmd) {
++			pgd_mop_up_pmds(mm, pgd);
++			return 0;
++		}
  
 -		if (pmd)
 -			memcpy(pmd,
 -			       (void *)pgd_page_vaddr(swapper_pg_dir[idx]),
-+		if (!pmd) {
-+			pgd_mop_up_pmds(pgd);
-+			return 0;
-+		}
-+
 +		if (i >= USER_PTRS_PER_PGD)
 +			memcpy(pmd, (pmd_t *)pgd_page_vaddr(swapper_pg_dir[i]),
  			       sizeof(pmd_t) * PTRS_PER_PMD);
@@ -336590,7 +361832,7 @@
  }
  
 -static void pmd_cache_free(pmd_t *pmd, int idx)
-+static void pgd_mop_up_pmds(pgd_t *pgd)
++static void pgd_mop_up_pmds(struct mm_struct *mm, pgd_t *pgdp)
  {
 -	if (idx >= USER_PTRS_PER_PGD)
 -		free_page((unsigned long)pmd);
@@ -336634,7 +361876,8 @@
 +	return pgd;
  }
  
- void pgd_free(pgd_t *pgd)
+-void pgd_free(pgd_t *pgd)
++void pgd_free(struct mm_struct *mm, pgd_t *pgd)
  {
 -	int i;
 -
@@ -336647,11 +361890,11 @@
 -			pmd_cache_free(pmd, i);
 -		}
 -	/* in the non-PAE case, free_pgtables() clears user pgd entries */
-+	pgd_mop_up_pmds(pgd);
++	pgd_mop_up_pmds(mm, pgd);
  	quicklist_free(0, pgd_dtor, pgd);
  }
  
-@@ -373,3 +377,25 @@ void check_pgt_cache(void)
+@@ -373,3 +363,18 @@ void check_pgt_cache(void)
  	quicklist_trim(0, pgd_dtor, 25, 16);
  }
  
@@ -336665,13 +361908,6 @@
 +
 +void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
 +{
-+	/* This is called just after the pmd has been detached from
-+	   the pgd, which requires a full tlb flush to be recognized
-+	   by the CPU.  Rather than incurring multiple tlb flushes
-+	   while the address space is being pulled down, make the tlb
-+	   gathering machinery do a full flush when we're done. */
-+	tlb->fullmm = 1;
-+
 +	paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT);
 +	tlb_remove_page(tlb, virt_to_page(pmd));
 +}
@@ -337538,6 +362774,19 @@
  	}
  }
  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
+diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
+index 42ba0e2..103b9df 100644
+--- a/arch/x86/pci/i386.c
++++ b/arch/x86/pci/i386.c
+@@ -72,7 +72,7 @@ pcibios_align_resource(void *data, struct resource *res,
+ 		}
+ 	}
+ }
+-
++EXPORT_SYMBOL(pcibios_align_resource);
+ 
+ /*
+  *  Handle resources of PCI devices.  If the world were perfect, we could
 diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
 index 88d8f5c..ed07ce6 100644
 --- a/arch/x86/pci/irq.c
@@ -337628,6 +362877,115 @@
  	return 1;
  }
  
+diff --git a/arch/x86/pci/numa.c b/arch/x86/pci/numa.c
+index f5f165f..55270c2 100644
+--- a/arch/x86/pci/numa.c
++++ b/arch/x86/pci/numa.c
+@@ -5,36 +5,62 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/nodemask.h>
++#include <mach_apic.h>
+ #include "pci.h"
+ 
++#define XQUAD_PORTIO_BASE 0xfe400000
++#define XQUAD_PORTIO_QUAD 0x40000  /* 256k per quad. */
++
+ #define BUS2QUAD(global) (mp_bus_id_to_node[global])
+ #define BUS2LOCAL(global) (mp_bus_id_to_local[global])
+ #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local])
+ 
++extern void *xquad_portio;    /* Where the IO area was mapped */
++#define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
++
+ #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
+ 	(0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
+ 
++static void write_cf8(unsigned bus, unsigned devfn, unsigned reg)
++{
++	unsigned val = PCI_CONF1_MQ_ADDRESS(bus, devfn, reg);
++	if (xquad_portio)
++		writel(val, XQUAD_PORT_ADDR(0xcf8, BUS2QUAD(bus)));
++	else
++		outl(val, 0xCF8);
++}
++
+ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
+ 			     unsigned int devfn, int reg, int len, u32 *value)
+ {
+ 	unsigned long flags;
++	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
+ 
+ 	if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
+ 		return -EINVAL;
+ 
+ 	spin_lock_irqsave(&pci_config_lock, flags);
+ 
+-	outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
++	write_cf8(bus, devfn, reg);
+ 
+ 	switch (len) {
+ 	case 1:
+-		*value = inb_quad(0xCFC + (reg & 3), BUS2QUAD(bus));
++		if (xquad_portio)
++			*value = readb(adr + (reg & 3));
++		else
++			*value = inb(0xCFC + (reg & 3));
+ 		break;
+ 	case 2:
+-		*value = inw_quad(0xCFC + (reg & 2), BUS2QUAD(bus));
++		if (xquad_portio)
++			*value = readw(adr + (reg & 2));
++		else
++			*value = inw(0xCFC + (reg & 2));
+ 		break;
+ 	case 4:
+-		*value = inl_quad(0xCFC, BUS2QUAD(bus));
++		if (xquad_portio)
++			*value = readl(adr);
++		else
++			*value = inl(0xCFC);
+ 		break;
+ 	}
+ 
+@@ -47,23 +73,33 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
+ 			      unsigned int devfn, int reg, int len, u32 value)
+ {
+ 	unsigned long flags;
++	void *adr __iomem = XQUAD_PORT_ADDR(0xcfc, BUS2QUAD(bus));
+ 
+ 	if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
+ 		return -EINVAL;
+ 
+ 	spin_lock_irqsave(&pci_config_lock, flags);
+ 
+-	outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus));
++	write_cf8(bus, devfn, reg);
+ 
+ 	switch (len) {
+ 	case 1:
+-		outb_quad((u8)value, 0xCFC + (reg & 3), BUS2QUAD(bus));
++		if (xquad_portio)
++			writeb(value, adr + (reg & 3));
++		else
++			outb((u8)value, 0xCFC + (reg & 3));
+ 		break;
+ 	case 2:
+-		outw_quad((u16)value, 0xCFC + (reg & 2), BUS2QUAD(bus));
++		if (xquad_portio)
++			writew(value, adr + (reg & 2));
++		else
++			outw((u16)value, 0xCFC + (reg & 2));
+ 		break;
+ 	case 4:
+-		outl_quad((u32)value, 0xCFC, BUS2QUAD(bus));
++		if (xquad_portio)
++			writel(value, adr + reg);
++		else
++			outl((u32)value, 0xCFC);
+ 		break;
+ 	}
+ 
 diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
 index 998fd3e..efcf620 100644
 --- a/arch/x86/power/cpu.c
@@ -339608,7 +364966,7 @@
  .pushsection .bss.page_aligned
  	.align PAGE_SIZE_asm
 diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
-index d3cb3d6..844721e 100644
+index d3cb3d6..5d5546c 100644
 --- a/arch/xtensa/Kconfig
 +++ b/arch/xtensa/Kconfig
 @@ -174,11 +174,6 @@ config PCI
@@ -339623,6 +364981,15 @@
  source "drivers/pci/Kconfig"
  
  config HOTPLUG
+@@ -251,8 +246,6 @@ config EMBEDDED_RAMDISK_IMAGE
+ 	  provide one yourself.
+ endmenu
+ 
+-source "kernel/Kconfig.instrumentation"
+-
+ source "arch/xtensa/Kconfig.debug"
+ 
+ source "security/Kconfig"
 diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
 index ac4ed52..7d0f55a 100644
 --- a/arch/xtensa/kernel/vmlinux.lds.S
@@ -349536,3630 +374903,8672 @@
 -	if (unlikely(bio_barrier(bio)))
 -		req->cmd_flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
 -
--	if (bio_sync(bio))
--		req->cmd_flags |= REQ_RW_SYNC;
--	if (bio_rw_meta(bio))
--		req->cmd_flags |= REQ_RW_META;
+-	if (bio_sync(bio))
+-		req->cmd_flags |= REQ_RW_SYNC;
+-	if (bio_rw_meta(bio))
+-		req->cmd_flags |= REQ_RW_META;
+-
+-	req->errors = 0;
+-	req->hard_sector = req->sector = bio->bi_sector;
+-	req->ioprio = bio_prio(bio);
+-	req->start_time = jiffies;
+-	blk_rq_bio_prep(req->q, req, bio);
+-}
+-
+-static int __make_request(struct request_queue *q, struct bio *bio)
+-{
+-	struct request *req;
+-	int el_ret, nr_sectors, barrier, err;
+-	const unsigned short prio = bio_prio(bio);
+-	const int sync = bio_sync(bio);
+-	int rw_flags;
+-
+-	nr_sectors = bio_sectors(bio);
+-
+-	/*
+-	 * low level driver can indicate that it wants pages above a
+-	 * certain limit bounced to low memory (ie for highmem, or even
+-	 * ISA dma in theory)
+-	 */
+-	blk_queue_bounce(q, &bio);
+-
+-	barrier = bio_barrier(bio);
+-	if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) {
+-		err = -EOPNOTSUPP;
+-		goto end_io;
+-	}
+-
+-	spin_lock_irq(q->queue_lock);
+-
+-	if (unlikely(barrier) || elv_queue_empty(q))
+-		goto get_rq;
+-
+-	el_ret = elv_merge(q, &req, bio);
+-	switch (el_ret) {
+-		case ELEVATOR_BACK_MERGE:
+-			BUG_ON(!rq_mergeable(req));
+-
+-			if (!ll_back_merge_fn(q, req, bio))
+-				break;
+-
+-			blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE);
+-
+-			req->biotail->bi_next = bio;
+-			req->biotail = bio;
+-			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+-			req->ioprio = ioprio_best(req->ioprio, prio);
+-			drive_stat_acct(req, 0);
+-			if (!attempt_back_merge(q, req))
+-				elv_merged_request(q, req, el_ret);
+-			goto out;
+-
+-		case ELEVATOR_FRONT_MERGE:
+-			BUG_ON(!rq_mergeable(req));
+-
+-			if (!ll_front_merge_fn(q, req, bio))
+-				break;
+-
+-			blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE);
+-
+-			bio->bi_next = req->bio;
+-			req->bio = bio;
+-
+-			/*
+-			 * may not be valid. if the low level driver said
+-			 * it didn't need a bounce buffer then it better
+-			 * not touch req->buffer either...
+-			 */
+-			req->buffer = bio_data(bio);
+-			req->current_nr_sectors = bio_cur_sectors(bio);
+-			req->hard_cur_sectors = req->current_nr_sectors;
+-			req->sector = req->hard_sector = bio->bi_sector;
+-			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+-			req->ioprio = ioprio_best(req->ioprio, prio);
+-			drive_stat_acct(req, 0);
+-			if (!attempt_front_merge(q, req))
+-				elv_merged_request(q, req, el_ret);
+-			goto out;
+-
+-		/* ELV_NO_MERGE: elevator says don't/can't merge. */
+-		default:
+-			;
+-	}
+-
+-get_rq:
+-	/*
+-	 * This sync check and mask will be re-done in init_request_from_bio(),
+-	 * but we need to set it earlier to expose the sync flag to the
+-	 * rq allocator and io schedulers.
+-	 */
+-	rw_flags = bio_data_dir(bio);
+-	if (sync)
+-		rw_flags |= REQ_RW_SYNC;
+-
+-	/*
+-	 * Grab a free request. This is might sleep but can not fail.
+-	 * Returns with the queue unlocked.
+-	 */
+-	req = get_request_wait(q, rw_flags, bio);
+-
+-	/*
+-	 * After dropping the lock and possibly sleeping here, our request
+-	 * may now be mergeable after it had proven unmergeable (above).
+-	 * We don't worry about that case for efficiency. It won't happen
+-	 * often, and the elevators are able to handle it.
+-	 */
+-	init_request_from_bio(req, bio);
+-
+-	spin_lock_irq(q->queue_lock);
+-	if (elv_queue_empty(q))
+-		blk_plug_device(q);
+-	add_request(q, req);
+-out:
+-	if (sync)
+-		__generic_unplug_device(q);
+-
+-	spin_unlock_irq(q->queue_lock);
+-	return 0;
+-
+-end_io:
+-	bio_endio(bio, err);
+-	return 0;
+-}
+-
+-/*
+- * If bio->bi_dev is a partition, remap the location
+- */
+-static inline void blk_partition_remap(struct bio *bio)
+-{
+-	struct block_device *bdev = bio->bi_bdev;
+-
+-	if (bio_sectors(bio) && bdev != bdev->bd_contains) {
+-		struct hd_struct *p = bdev->bd_part;
+-		const int rw = bio_data_dir(bio);
+-
+-		p->sectors[rw] += bio_sectors(bio);
+-		p->ios[rw]++;
+-
+-		bio->bi_sector += p->start_sect;
+-		bio->bi_bdev = bdev->bd_contains;
+-
+-		blk_add_trace_remap(bdev_get_queue(bio->bi_bdev), bio,
+-				    bdev->bd_dev, bio->bi_sector,
+-				    bio->bi_sector - p->start_sect);
+-	}
+-}
+-
+-static void handle_bad_sector(struct bio *bio)
+-{
+-	char b[BDEVNAME_SIZE];
+-
+-	printk(KERN_INFO "attempt to access beyond end of device\n");
+-	printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n",
+-			bdevname(bio->bi_bdev, b),
+-			bio->bi_rw,
+-			(unsigned long long)bio->bi_sector + bio_sectors(bio),
+-			(long long)(bio->bi_bdev->bd_inode->i_size >> 9));
+-
+-	set_bit(BIO_EOF, &bio->bi_flags);
+-}
+-
+-#ifdef CONFIG_FAIL_MAKE_REQUEST
+-
+-static DECLARE_FAULT_ATTR(fail_make_request);
+-
+-static int __init setup_fail_make_request(char *str)
+-{
+-	return setup_fault_attr(&fail_make_request, str);
+-}
+-__setup("fail_make_request=", setup_fail_make_request);
+-
+-static int should_fail_request(struct bio *bio)
+-{
+-	if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) ||
+-	    (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail))
+-		return should_fail(&fail_make_request, bio->bi_size);
+-
+-	return 0;
+-}
+-
+-static int __init fail_make_request_debugfs(void)
+-{
+-	return init_fault_attr_dentries(&fail_make_request,
+-					"fail_make_request");
+-}
+-
+-late_initcall(fail_make_request_debugfs);
+-
+-#else /* CONFIG_FAIL_MAKE_REQUEST */
+-
+-static inline int should_fail_request(struct bio *bio)
+-{
+-	return 0;
+-}
+-
+-#endif /* CONFIG_FAIL_MAKE_REQUEST */
+-
+-/*
+- * Check whether this bio extends beyond the end of the device.
+- */
+-static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
+-{
+-	sector_t maxsector;
+-
+-	if (!nr_sectors)
+-		return 0;
+-
+-	/* Test device or partition size, when known. */
+-	maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
+-	if (maxsector) {
+-		sector_t sector = bio->bi_sector;
+-
+-		if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
+-			/*
+-			 * This may well happen - the kernel calls bread()
+-			 * without checking the size of the device, e.g., when
+-			 * mounting a device.
+-			 */
+-			handle_bad_sector(bio);
+-			return 1;
+-		}
+-	}
+-
+-	return 0;
+-}
+-
+-/**
+- * generic_make_request: hand a buffer to its device driver for I/O
+- * @bio:  The bio describing the location in memory and on the device.
+- *
+- * generic_make_request() is used to make I/O requests of block
+- * devices. It is passed a &struct bio, which describes the I/O that needs
+- * to be done.
+- *
+- * generic_make_request() does not return any status.  The
+- * success/failure status of the request, along with notification of
+- * completion, is delivered asynchronously through the bio->bi_end_io
+- * function described (one day) else where.
+- *
+- * The caller of generic_make_request must make sure that bi_io_vec
+- * are set to describe the memory buffer, and that bi_dev and bi_sector are
+- * set to describe the device address, and the
+- * bi_end_io and optionally bi_private are set to describe how
+- * completion notification should be signaled.
+- *
+- * generic_make_request and the drivers it calls may use bi_next if this
+- * bio happens to be merged with someone else, and may change bi_dev and
+- * bi_sector for remaps as it sees fit.  So the values of these fields
+- * should NOT be depended on after the call to generic_make_request.
+- */
+-static inline void __generic_make_request(struct bio *bio)
+-{
+-	struct request_queue *q;
+-	sector_t old_sector;
+-	int ret, nr_sectors = bio_sectors(bio);
+-	dev_t old_dev;
+-	int err = -EIO;
+-
+-	might_sleep();
+-
+-	if (bio_check_eod(bio, nr_sectors))
+-		goto end_io;
+-
+-	/*
+-	 * Resolve the mapping until finished. (drivers are
+-	 * still free to implement/resolve their own stacking
+-	 * by explicitly returning 0)
+-	 *
+-	 * NOTE: we don't repeat the blk_size check for each new device.
+-	 * Stacking drivers are expected to know what they are doing.
+-	 */
+-	old_sector = -1;
+-	old_dev = 0;
+-	do {
+-		char b[BDEVNAME_SIZE];
+-
+-		q = bdev_get_queue(bio->bi_bdev);
+-		if (!q) {
+-			printk(KERN_ERR
+-			       "generic_make_request: Trying to access "
+-				"nonexistent block-device %s (%Lu)\n",
+-				bdevname(bio->bi_bdev, b),
+-				(long long) bio->bi_sector);
+-end_io:
+-			bio_endio(bio, err);
+-			break;
+-		}
+-
+-		if (unlikely(nr_sectors > q->max_hw_sectors)) {
+-			printk("bio too big device %s (%u > %u)\n", 
+-				bdevname(bio->bi_bdev, b),
+-				bio_sectors(bio),
+-				q->max_hw_sectors);
+-			goto end_io;
+-		}
+-
+-		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
+-			goto end_io;
+-
+-		if (should_fail_request(bio))
+-			goto end_io;
+-
+-		/*
+-		 * If this device has partitions, remap block n
+-		 * of partition p to block n+start(p) of the disk.
+-		 */
+-		blk_partition_remap(bio);
+-
+-		if (old_sector != -1)
+-			blk_add_trace_remap(q, bio, old_dev, bio->bi_sector,
+-					    old_sector);
+-
+-		blk_add_trace_bio(q, bio, BLK_TA_QUEUE);
+-
+-		old_sector = bio->bi_sector;
+-		old_dev = bio->bi_bdev->bd_dev;
+-
+-		if (bio_check_eod(bio, nr_sectors))
+-			goto end_io;
+-		if (bio_empty_barrier(bio) && !q->prepare_flush_fn) {
+-			err = -EOPNOTSUPP;
+-			goto end_io;
+-		}
+-
+-		ret = q->make_request_fn(q, bio);
+-	} while (ret);
+-}
+-
+-/*
+- * We only want one ->make_request_fn to be active at a time,
+- * else stack usage with stacked devices could be a problem.
+- * So use current->bio_{list,tail} to keep a list of requests
+- * submited by a make_request_fn function.
+- * current->bio_tail is also used as a flag to say if
+- * generic_make_request is currently active in this task or not.
+- * If it is NULL, then no make_request is active.  If it is non-NULL,
+- * then a make_request is active, and new requests should be added
+- * at the tail
+- */
+-void generic_make_request(struct bio *bio)
+-{
+-	if (current->bio_tail) {
+-		/* make_request is active */
+-		*(current->bio_tail) = bio;
+-		bio->bi_next = NULL;
+-		current->bio_tail = &bio->bi_next;
+-		return;
+-	}
+-	/* following loop may be a bit non-obvious, and so deserves some
+-	 * explanation.
+-	 * Before entering the loop, bio->bi_next is NULL (as all callers
+-	 * ensure that) so we have a list with a single bio.
+-	 * We pretend that we have just taken it off a longer list, so
+-	 * we assign bio_list to the next (which is NULL) and bio_tail
+-	 * to &bio_list, thus initialising the bio_list of new bios to be
+-	 * added.  __generic_make_request may indeed add some more bios
+-	 * through a recursive call to generic_make_request.  If it
+-	 * did, we find a non-NULL value in bio_list and re-enter the loop
+-	 * from the top.  In this case we really did just take the bio
+-	 * of the top of the list (no pretending) and so fixup bio_list and
+-	 * bio_tail or bi_next, and call into __generic_make_request again.
+-	 *
+-	 * The loop was structured like this to make only one call to
+-	 * __generic_make_request (which is important as it is large and
+-	 * inlined) and to keep the structure simple.
+-	 */
+-	BUG_ON(bio->bi_next);
+-	do {
+-		current->bio_list = bio->bi_next;
+-		if (bio->bi_next == NULL)
+-			current->bio_tail = &current->bio_list;
+-		else
+-			bio->bi_next = NULL;
+-		__generic_make_request(bio);
+-		bio = current->bio_list;
+-	} while (bio);
+-	current->bio_tail = NULL; /* deactivate */
+-}
+-
+-EXPORT_SYMBOL(generic_make_request);
+-
+-/**
+- * submit_bio: submit a bio to the block device layer for I/O
+- * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
+- * @bio: The &struct bio which describes the I/O
+- *
+- * submit_bio() is very similar in purpose to generic_make_request(), and
+- * uses that function to do most of the work. Both are fairly rough
+- * interfaces, @bio must be presetup and ready for I/O.
+- *
+- */
+-void submit_bio(int rw, struct bio *bio)
+-{
+-	int count = bio_sectors(bio);
+-
+-	bio->bi_rw |= rw;
+-
+-	/*
+-	 * If it's a regular read/write or a barrier with data attached,
+-	 * go through the normal accounting stuff before submission.
+-	 */
+-	if (!bio_empty_barrier(bio)) {
+-
+-		BIO_BUG_ON(!bio->bi_size);
+-		BIO_BUG_ON(!bio->bi_io_vec);
+-
+-		if (rw & WRITE) {
+-			count_vm_events(PGPGOUT, count);
+-		} else {
+-			task_io_account_read(bio->bi_size);
+-			count_vm_events(PGPGIN, count);
+-		}
+-
+-		if (unlikely(block_dump)) {
+-			char b[BDEVNAME_SIZE];
+-			printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
+-			current->comm, task_pid_nr(current),
+-				(rw & WRITE) ? "WRITE" : "READ",
+-				(unsigned long long)bio->bi_sector,
+-				bdevname(bio->bi_bdev,b));
+-		}
+-	}
+-
+-	generic_make_request(bio);
+-}
+-
+-EXPORT_SYMBOL(submit_bio);
+-
+-static void blk_recalc_rq_sectors(struct request *rq, int nsect)
+-{
+-	if (blk_fs_request(rq)) {
+-		rq->hard_sector += nsect;
+-		rq->hard_nr_sectors -= nsect;
+-
+-		/*
+-		 * Move the I/O submission pointers ahead if required.
+-		 */
+-		if ((rq->nr_sectors >= rq->hard_nr_sectors) &&
+-		    (rq->sector <= rq->hard_sector)) {
+-			rq->sector = rq->hard_sector;
+-			rq->nr_sectors = rq->hard_nr_sectors;
+-			rq->hard_cur_sectors = bio_cur_sectors(rq->bio);
+-			rq->current_nr_sectors = rq->hard_cur_sectors;
+-			rq->buffer = bio_data(rq->bio);
+-		}
+-
+-		/*
+-		 * if total number of sectors is less than the first segment
+-		 * size, something has gone terribly wrong
+-		 */
+-		if (rq->nr_sectors < rq->current_nr_sectors) {
+-			printk("blk: request botched\n");
+-			rq->nr_sectors = rq->current_nr_sectors;
+-		}
+-	}
+-}
+-
+-static int __end_that_request_first(struct request *req, int uptodate,
+-				    int nr_bytes)
+-{
+-	int total_bytes, bio_nbytes, error, next_idx = 0;
+-	struct bio *bio;
+-
+-	blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE);
+-
+-	/*
+-	 * extend uptodate bool to allow < 0 value to be direct io error
+-	 */
+-	error = 0;
+-	if (end_io_error(uptodate))
+-		error = !uptodate ? -EIO : uptodate;
+-
+-	/*
+-	 * for a REQ_BLOCK_PC request, we want to carry any eventual
+-	 * sense key with us all the way through
+-	 */
+-	if (!blk_pc_request(req))
+-		req->errors = 0;
+-
+-	if (!uptodate) {
+-		if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
+-			printk("end_request: I/O error, dev %s, sector %llu\n",
+-				req->rq_disk ? req->rq_disk->disk_name : "?",
+-				(unsigned long long)req->sector);
+-	}
+-
+-	if (blk_fs_request(req) && req->rq_disk) {
+-		const int rw = rq_data_dir(req);
+-
+-		disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
+-	}
+-
+-	total_bytes = bio_nbytes = 0;
+-	while ((bio = req->bio) != NULL) {
+-		int nbytes;
+-
+-		/*
+-		 * For an empty barrier request, the low level driver must
+-		 * store a potential error location in ->sector. We pass
+-		 * that back up in ->bi_sector.
+-		 */
+-		if (blk_empty_barrier(req))
+-			bio->bi_sector = req->sector;
+-
+-		if (nr_bytes >= bio->bi_size) {
+-			req->bio = bio->bi_next;
+-			nbytes = bio->bi_size;
+-			req_bio_endio(req, bio, nbytes, error);
+-			next_idx = 0;
+-			bio_nbytes = 0;
+-		} else {
+-			int idx = bio->bi_idx + next_idx;
+-
+-			if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
+-				blk_dump_rq_flags(req, "__end_that");
+-				printk("%s: bio idx %d >= vcnt %d\n",
+-						__FUNCTION__,
+-						bio->bi_idx, bio->bi_vcnt);
+-				break;
+-			}
+-
+-			nbytes = bio_iovec_idx(bio, idx)->bv_len;
+-			BIO_BUG_ON(nbytes > bio->bi_size);
+-
+-			/*
+-			 * not a complete bvec done
+-			 */
+-			if (unlikely(nbytes > nr_bytes)) {
+-				bio_nbytes += nr_bytes;
+-				total_bytes += nr_bytes;
+-				break;
+-			}
+-
+-			/*
+-			 * advance to the next vector
+-			 */
+-			next_idx++;
+-			bio_nbytes += nbytes;
+-		}
+-
+-		total_bytes += nbytes;
+-		nr_bytes -= nbytes;
+-
+-		if ((bio = req->bio)) {
+-			/*
+-			 * end more in this run, or just return 'not-done'
+-			 */
+-			if (unlikely(nr_bytes <= 0))
+-				break;
+-		}
+-	}
+-
+-	/*
+-	 * completely done
+-	 */
+-	if (!req->bio)
+-		return 0;
+-
+-	/*
+-	 * if the request wasn't completed, update state
+-	 */
+-	if (bio_nbytes) {
+-		req_bio_endio(req, bio, bio_nbytes, error);
+-		bio->bi_idx += next_idx;
+-		bio_iovec(bio)->bv_offset += nr_bytes;
+-		bio_iovec(bio)->bv_len -= nr_bytes;
+-	}
+-
+-	blk_recalc_rq_sectors(req, total_bytes >> 9);
+-	blk_recalc_rq_segments(req);
+-	return 1;
+-}
+-
+-/**
+- * end_that_request_first - end I/O on a request
+- * @req:      the request being processed
+- * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
+- * @nr_sectors: number of sectors to end I/O on
+- *
+- * Description:
+- *     Ends I/O on a number of sectors attached to @req, and sets it up
+- *     for the next range of segments (if any) in the cluster.
+- *
+- * Return:
+- *     0 - we are done with this request, call end_that_request_last()
+- *     1 - still buffers pending for this request
+- **/
+-int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
+-{
+-	return __end_that_request_first(req, uptodate, nr_sectors << 9);
+-}
+-
+-EXPORT_SYMBOL(end_that_request_first);
+-
+-/**
+- * end_that_request_chunk - end I/O on a request
+- * @req:      the request being processed
+- * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
+- * @nr_bytes: number of bytes to complete
+- *
+- * Description:
+- *     Ends I/O on a number of bytes attached to @req, and sets it up
+- *     for the next range of segments (if any). Like end_that_request_first(),
+- *     but deals with bytes instead of sectors.
+- *
+- * Return:
+- *     0 - we are done with this request, call end_that_request_last()
+- *     1 - still buffers pending for this request
+- **/
+-int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
+-{
+-	return __end_that_request_first(req, uptodate, nr_bytes);
+-}
+-
+-EXPORT_SYMBOL(end_that_request_chunk);
+-
+-/*
+- * splice the completion data to a local structure and hand off to
+- * process_completion_queue() to complete the requests
+- */
+-static void blk_done_softirq(struct softirq_action *h)
+-{
+-	struct list_head *cpu_list, local_list;
+-
+-	local_irq_disable();
+-	cpu_list = &__get_cpu_var(blk_cpu_done);
+-	list_replace_init(cpu_list, &local_list);
+-	local_irq_enable();
+-
+-	while (!list_empty(&local_list)) {
+-		struct request *rq = list_entry(local_list.next, struct request, donelist);
+-
+-		list_del_init(&rq->donelist);
+-		rq->q->softirq_done_fn(rq);
+-	}
+-}
+-
+-static int __cpuinit blk_cpu_notify(struct notifier_block *self, unsigned long action,
+-			  void *hcpu)
+-{
+-	/*
+-	 * If a CPU goes away, splice its entries to the current CPU
+-	 * and trigger a run of the softirq
+-	 */
+-	if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
+-		int cpu = (unsigned long) hcpu;
+-
+-		local_irq_disable();
+-		list_splice_init(&per_cpu(blk_cpu_done, cpu),
+-				 &__get_cpu_var(blk_cpu_done));
+-		raise_softirq_irqoff(BLOCK_SOFTIRQ);
+-		local_irq_enable();
+-	}
+-
+-	return NOTIFY_OK;
+-}
+-
+-
+-static struct notifier_block blk_cpu_notifier __cpuinitdata = {
+-	.notifier_call	= blk_cpu_notify,
+-};
+-
+-/**
+- * blk_complete_request - end I/O on a request
+- * @req:      the request being processed
+- *
+- * Description:
+- *     Ends all I/O on a request. It does not handle partial completions,
+- *     unless the driver actually implements this in its completion callback
+- *     through requeueing. The actual completion happens out-of-order,
+- *     through a softirq handler. The user must have registered a completion
+- *     callback through blk_queue_softirq_done().
+- **/
+-
+-void blk_complete_request(struct request *req)
+-{
+-	struct list_head *cpu_list;
+-	unsigned long flags;
+-
+-	BUG_ON(!req->q->softirq_done_fn);
+-		
+-	local_irq_save(flags);
+-
+-	cpu_list = &__get_cpu_var(blk_cpu_done);
+-	list_add_tail(&req->donelist, cpu_list);
+-	raise_softirq_irqoff(BLOCK_SOFTIRQ);
+-
+-	local_irq_restore(flags);
+-}
+-
+-EXPORT_SYMBOL(blk_complete_request);
+-	
+-/*
+- * queue lock must be held
+- */
+-void end_that_request_last(struct request *req, int uptodate)
+-{
+-	struct gendisk *disk = req->rq_disk;
+-	int error;
+-
+-	/*
+-	 * extend uptodate bool to allow < 0 value to be direct io error
+-	 */
+-	error = 0;
+-	if (end_io_error(uptodate))
+-		error = !uptodate ? -EIO : uptodate;
+-
+-	if (unlikely(laptop_mode) && blk_fs_request(req))
+-		laptop_io_completion();
+-
+-	/*
+-	 * Account IO completion.  bar_rq isn't accounted as a normal
+-	 * IO on queueing nor completion.  Accounting the containing
+-	 * request is enough.
+-	 */
+-	if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
+-		unsigned long duration = jiffies - req->start_time;
+-		const int rw = rq_data_dir(req);
+-
+-		__disk_stat_inc(disk, ios[rw]);
+-		__disk_stat_add(disk, ticks[rw], duration);
+-		disk_round_stats(disk);
+-		disk->in_flight--;
+-	}
+-	if (req->end_io)
+-		req->end_io(req, error);
+-	else
+-		__blk_put_request(req->q, req);
+-}
+-
+-EXPORT_SYMBOL(end_that_request_last);
+-
+-static inline void __end_request(struct request *rq, int uptodate,
+-				 unsigned int nr_bytes, int dequeue)
+-{
+-	if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
+-		if (dequeue)
+-			blkdev_dequeue_request(rq);
+-		add_disk_randomness(rq->rq_disk);
+-		end_that_request_last(rq, uptodate);
+-	}
+-}
+-
+-static unsigned int rq_byte_size(struct request *rq)
+-{
+-	if (blk_fs_request(rq))
+-		return rq->hard_nr_sectors << 9;
+-
+-	return rq->data_len;
+-}
+-
+-/**
+- * end_queued_request - end all I/O on a queued request
+- * @rq:		the request being processed
+- * @uptodate:	error value or 0/1 uptodate flag
+- *
+- * Description:
+- *     Ends all I/O on a request, and removes it from the block layer queues.
+- *     Not suitable for normal IO completion, unless the driver still has
+- *     the request attached to the block layer.
+- *
+- **/
+-void end_queued_request(struct request *rq, int uptodate)
+-{
+-	__end_request(rq, uptodate, rq_byte_size(rq), 1);
+-}
+-EXPORT_SYMBOL(end_queued_request);
+-
+-/**
+- * end_dequeued_request - end all I/O on a dequeued request
+- * @rq:		the request being processed
+- * @uptodate:	error value or 0/1 uptodate flag
+- *
+- * Description:
+- *     Ends all I/O on a request. The request must already have been
+- *     dequeued using blkdev_dequeue_request(), as is normally the case
+- *     for most drivers.
+- *
+- **/
+-void end_dequeued_request(struct request *rq, int uptodate)
+-{
+-	__end_request(rq, uptodate, rq_byte_size(rq), 0);
+-}
+-EXPORT_SYMBOL(end_dequeued_request);
+-
+-
+-/**
+- * end_request - end I/O on the current segment of the request
+- * @req:	the request being processed
+- * @uptodate:	error value or 0/1 uptodate flag
+- *
+- * Description:
+- *     Ends I/O on the current segment of a request. If that is the only
+- *     remaining segment, the request is also completed and freed.
+- *
+- *     This is a remnant of how older block drivers handled IO completions.
+- *     Modern drivers typically end IO on the full request in one go, unless
+- *     they have a residual value to account for. For that case this function
+- *     isn't really useful, unless the residual just happens to be the
+- *     full current segment. In other words, don't use this function in new
+- *     code. Either use end_request_completely(), or the
+- *     end_that_request_chunk() (along with end_that_request_last()) for
+- *     partial completions.
+- *
+- **/
+-void end_request(struct request *req, int uptodate)
+-{
+-	__end_request(req, uptodate, req->hard_cur_sectors << 9, 1);
+-}
+-EXPORT_SYMBOL(end_request);
+-
+-static void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
+-			    struct bio *bio)
+-{
+-	/* first two bits are identical in rq->cmd_flags and bio->bi_rw */
+-	rq->cmd_flags |= (bio->bi_rw & 3);
+-
+-	rq->nr_phys_segments = bio_phys_segments(q, bio);
+-	rq->nr_hw_segments = bio_hw_segments(q, bio);
+-	rq->current_nr_sectors = bio_cur_sectors(bio);
+-	rq->hard_cur_sectors = rq->current_nr_sectors;
+-	rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
+-	rq->buffer = bio_data(bio);
+-	rq->data_len = bio->bi_size;
+-
+-	rq->bio = rq->biotail = bio;
+-
+-	if (bio->bi_bdev)
+-		rq->rq_disk = bio->bi_bdev->bd_disk;
+-}
+-
+-int kblockd_schedule_work(struct work_struct *work)
+-{
+-	return queue_work(kblockd_workqueue, work);
+-}
+-
+-EXPORT_SYMBOL(kblockd_schedule_work);
+-
+-void kblockd_flush_work(struct work_struct *work)
+-{
+-	cancel_work_sync(work);
+-}
+-EXPORT_SYMBOL(kblockd_flush_work);
+-
+-int __init blk_dev_init(void)
+-{
+-	int i;
+-
+-	kblockd_workqueue = create_workqueue("kblockd");
+-	if (!kblockd_workqueue)
+-		panic("Failed to create kblockd\n");
+-
+-	request_cachep = kmem_cache_create("blkdev_requests",
+-			sizeof(struct request), 0, SLAB_PANIC, NULL);
+-
+-	requestq_cachep = kmem_cache_create("blkdev_queue",
+-			sizeof(struct request_queue), 0, SLAB_PANIC, NULL);
+-
+-	iocontext_cachep = kmem_cache_create("blkdev_ioc",
+-			sizeof(struct io_context), 0, SLAB_PANIC, NULL);
+-
+-	for_each_possible_cpu(i)
+-		INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
+-
+-	open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
+-	register_hotcpu_notifier(&blk_cpu_notifier);
+-
+-	blk_max_low_pfn = max_low_pfn - 1;
+-	blk_max_pfn = max_pfn - 1;
+-
+-	return 0;
+-}
+-
+-/*
+- * IO Context helper functions
+- */
+-void put_io_context(struct io_context *ioc)
+-{
+-	if (ioc == NULL)
+-		return;
+-
+-	BUG_ON(atomic_read(&ioc->refcount) == 0);
+-
+-	if (atomic_dec_and_test(&ioc->refcount)) {
+-		struct cfq_io_context *cic;
+-
+-		rcu_read_lock();
+-		if (ioc->aic && ioc->aic->dtor)
+-			ioc->aic->dtor(ioc->aic);
+-		if (ioc->cic_root.rb_node != NULL) {
+-			struct rb_node *n = rb_first(&ioc->cic_root);
+-
+-			cic = rb_entry(n, struct cfq_io_context, rb_node);
+-			cic->dtor(ioc);
+-		}
+-		rcu_read_unlock();
+-
+-		kmem_cache_free(iocontext_cachep, ioc);
+-	}
+-}
+-EXPORT_SYMBOL(put_io_context);
+-
+-/* Called by the exitting task */
+-void exit_io_context(void)
+-{
+-	struct io_context *ioc;
+-	struct cfq_io_context *cic;
+-
+-	task_lock(current);
+-	ioc = current->io_context;
+-	current->io_context = NULL;
+-	task_unlock(current);
+-
+-	ioc->task = NULL;
+-	if (ioc->aic && ioc->aic->exit)
+-		ioc->aic->exit(ioc->aic);
+-	if (ioc->cic_root.rb_node != NULL) {
+-		cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
+-		cic->exit(ioc);
+-	}
+-
+-	put_io_context(ioc);
+-}
+-
+-/*
+- * If the current task has no IO context then create one and initialise it.
+- * Otherwise, return its existing IO context.
+- *
+- * This returned IO context doesn't have a specifically elevated refcount,
+- * but since the current task itself holds a reference, the context can be
+- * used in general code, so long as it stays within `current` context.
+- */
+-static struct io_context *current_io_context(gfp_t gfp_flags, int node)
+-{
+-	struct task_struct *tsk = current;
+-	struct io_context *ret;
+-
+-	ret = tsk->io_context;
+-	if (likely(ret))
+-		return ret;
+-
+-	ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
+-	if (ret) {
+-		atomic_set(&ret->refcount, 1);
+-		ret->task = current;
+-		ret->ioprio_changed = 0;
+-		ret->last_waited = jiffies; /* doesn't matter... */
+-		ret->nr_batch_requests = 0; /* because this is 0 */
+-		ret->aic = NULL;
+-		ret->cic_root.rb_node = NULL;
+-		ret->ioc_data = NULL;
+-		/* make sure set_task_ioprio() sees the settings above */
+-		smp_wmb();
+-		tsk->io_context = ret;
+-	}
+-
+-	return ret;
+-}
+-
+-/*
+- * If the current task has no IO context then create one and initialise it.
+- * If it does have a context, take a ref on it.
+- *
+- * This is always called in the context of the task which submitted the I/O.
+- */
+-struct io_context *get_io_context(gfp_t gfp_flags, int node)
+-{
+-	struct io_context *ret;
+-	ret = current_io_context(gfp_flags, node);
+-	if (likely(ret))
+-		atomic_inc(&ret->refcount);
+-	return ret;
+-}
+-EXPORT_SYMBOL(get_io_context);
+-
+-void copy_io_context(struct io_context **pdst, struct io_context **psrc)
+-{
+-	struct io_context *src = *psrc;
+-	struct io_context *dst = *pdst;
+-
+-	if (src) {
+-		BUG_ON(atomic_read(&src->refcount) == 0);
+-		atomic_inc(&src->refcount);
+-		put_io_context(dst);
+-		*pdst = src;
+-	}
+-}
+-EXPORT_SYMBOL(copy_io_context);
+-
+-void swap_io_context(struct io_context **ioc1, struct io_context **ioc2)
+-{
+-	struct io_context *temp;
+-	temp = *ioc1;
+-	*ioc1 = *ioc2;
+-	*ioc2 = temp;
+-}
+-EXPORT_SYMBOL(swap_io_context);
+-
+-/*
+- * sysfs parts below
+- */
+-struct queue_sysfs_entry {
+-	struct attribute attr;
+-	ssize_t (*show)(struct request_queue *, char *);
+-	ssize_t (*store)(struct request_queue *, const char *, size_t);
+-};
+-
+-static ssize_t
+-queue_var_show(unsigned int var, char *page)
+-{
+-	return sprintf(page, "%d\n", var);
+-}
+-
+-static ssize_t
+-queue_var_store(unsigned long *var, const char *page, size_t count)
+-{
+-	char *p = (char *) page;
+-
+-	*var = simple_strtoul(p, &p, 10);
+-	return count;
+-}
+-
+-static ssize_t queue_requests_show(struct request_queue *q, char *page)
+-{
+-	return queue_var_show(q->nr_requests, (page));
+-}
+-
+-static ssize_t
+-queue_requests_store(struct request_queue *q, const char *page, size_t count)
+-{
+-	struct request_list *rl = &q->rq;
+-	unsigned long nr;
+-	int ret = queue_var_store(&nr, page, count);
+-	if (nr < BLKDEV_MIN_RQ)
+-		nr = BLKDEV_MIN_RQ;
+-
+-	spin_lock_irq(q->queue_lock);
+-	q->nr_requests = nr;
+-	blk_queue_congestion_threshold(q);
+-
+-	if (rl->count[READ] >= queue_congestion_on_threshold(q))
+-		blk_set_queue_congested(q, READ);
+-	else if (rl->count[READ] < queue_congestion_off_threshold(q))
+-		blk_clear_queue_congested(q, READ);
+-
+-	if (rl->count[WRITE] >= queue_congestion_on_threshold(q))
+-		blk_set_queue_congested(q, WRITE);
+-	else if (rl->count[WRITE] < queue_congestion_off_threshold(q))
+-		blk_clear_queue_congested(q, WRITE);
+-
+-	if (rl->count[READ] >= q->nr_requests) {
+-		blk_set_queue_full(q, READ);
+-	} else if (rl->count[READ]+1 <= q->nr_requests) {
+-		blk_clear_queue_full(q, READ);
+-		wake_up(&rl->wait[READ]);
+-	}
+-
+-	if (rl->count[WRITE] >= q->nr_requests) {
+-		blk_set_queue_full(q, WRITE);
+-	} else if (rl->count[WRITE]+1 <= q->nr_requests) {
+-		blk_clear_queue_full(q, WRITE);
+-		wake_up(&rl->wait[WRITE]);
+-	}
+-	spin_unlock_irq(q->queue_lock);
+-	return ret;
+-}
+-
+-static ssize_t queue_ra_show(struct request_queue *q, char *page)
+-{
+-	int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
+-
+-	return queue_var_show(ra_kb, (page));
+-}
+-
+-static ssize_t
+-queue_ra_store(struct request_queue *q, const char *page, size_t count)
+-{
+-	unsigned long ra_kb;
+-	ssize_t ret = queue_var_store(&ra_kb, page, count);
+-
+-	spin_lock_irq(q->queue_lock);
+-	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
+-	spin_unlock_irq(q->queue_lock);
+-
+-	return ret;
+-}
+-
+-static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
+-{
+-	int max_sectors_kb = q->max_sectors >> 1;
+-
+-	return queue_var_show(max_sectors_kb, (page));
+-}
+-
+-static ssize_t
+-queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+-{
+-	unsigned long max_sectors_kb,
+-			max_hw_sectors_kb = q->max_hw_sectors >> 1,
+-			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
+-	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
+-
+-	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
+-		return -EINVAL;
+-	/*
+-	 * Take the queue lock to update the readahead and max_sectors
+-	 * values synchronously:
+-	 */
+-	spin_lock_irq(q->queue_lock);
+-	q->max_sectors = max_sectors_kb << 1;
+-	spin_unlock_irq(q->queue_lock);
+-
+-	return ret;
+-}
+-
+-static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
+-{
+-	int max_hw_sectors_kb = q->max_hw_sectors >> 1;
+-
+-	return queue_var_show(max_hw_sectors_kb, (page));
+-}
+-
+-
+-static struct queue_sysfs_entry queue_requests_entry = {
+-	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
+-	.show = queue_requests_show,
+-	.store = queue_requests_store,
+-};
+-
+-static struct queue_sysfs_entry queue_ra_entry = {
+-	.attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR },
+-	.show = queue_ra_show,
+-	.store = queue_ra_store,
+-};
+-
+-static struct queue_sysfs_entry queue_max_sectors_entry = {
+-	.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
+-	.show = queue_max_sectors_show,
+-	.store = queue_max_sectors_store,
+-};
+-
+-static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
+-	.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
+-	.show = queue_max_hw_sectors_show,
+-};
+-
+-static struct queue_sysfs_entry queue_iosched_entry = {
+-	.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
+-	.show = elv_iosched_show,
+-	.store = elv_iosched_store,
+-};
+-
+-static struct attribute *default_attrs[] = {
+-	&queue_requests_entry.attr,
+-	&queue_ra_entry.attr,
+-	&queue_max_hw_sectors_entry.attr,
+-	&queue_max_sectors_entry.attr,
+-	&queue_iosched_entry.attr,
+-	NULL,
+-};
+-
+-#define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr)
+-
+-static ssize_t
+-queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+-{
+-	struct queue_sysfs_entry *entry = to_queue(attr);
+-	struct request_queue *q =
+-		container_of(kobj, struct request_queue, kobj);
+-	ssize_t res;
+-
+-	if (!entry->show)
+-		return -EIO;
+-	mutex_lock(&q->sysfs_lock);
+-	if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+-		mutex_unlock(&q->sysfs_lock);
+-		return -ENOENT;
+-	}
+-	res = entry->show(q, page);
+-	mutex_unlock(&q->sysfs_lock);
+-	return res;
+-}
+-
+-static ssize_t
+-queue_attr_store(struct kobject *kobj, struct attribute *attr,
+-		    const char *page, size_t length)
+-{
+-	struct queue_sysfs_entry *entry = to_queue(attr);
+-	struct request_queue *q = container_of(kobj, struct request_queue, kobj);
+-
+-	ssize_t res;
+-
+-	if (!entry->store)
+-		return -EIO;
+-	mutex_lock(&q->sysfs_lock);
+-	if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+-		mutex_unlock(&q->sysfs_lock);
+-		return -ENOENT;
+-	}
+-	res = entry->store(q, page, length);
+-	mutex_unlock(&q->sysfs_lock);
+-	return res;
+-}
+-
+-static struct sysfs_ops queue_sysfs_ops = {
+-	.show	= queue_attr_show,
+-	.store	= queue_attr_store,
+-};
+-
+-static struct kobj_type queue_ktype = {
+-	.sysfs_ops	= &queue_sysfs_ops,
+-	.default_attrs	= default_attrs,
+-	.release	= blk_release_queue,
+-};
+-
+-int blk_register_queue(struct gendisk *disk)
+-{
+-	int ret;
+-
+-	struct request_queue *q = disk->queue;
+-
+-	if (!q || !q->request_fn)
+-		return -ENXIO;
+-
+-	q->kobj.parent = kobject_get(&disk->kobj);
+-
+-	ret = kobject_add(&q->kobj);
+-	if (ret < 0)
+-		return ret;
+-
+-	kobject_uevent(&q->kobj, KOBJ_ADD);
+-
+-	ret = elv_register_queue(q);
+-	if (ret) {
+-		kobject_uevent(&q->kobj, KOBJ_REMOVE);
+-		kobject_del(&q->kobj);
+-		return ret;
+-	}
 -
--	req->errors = 0;
--	req->hard_sector = req->sector = bio->bi_sector;
--	req->ioprio = bio_prio(bio);
--	req->start_time = jiffies;
--	blk_rq_bio_prep(req->q, req, bio);
+-	return 0;
 -}
 -
--static int __make_request(struct request_queue *q, struct bio *bio)
+-void blk_unregister_queue(struct gendisk *disk)
 -{
--	struct request *req;
--	int el_ret, nr_sectors, barrier, err;
--	const unsigned short prio = bio_prio(bio);
--	const int sync = bio_sync(bio);
--	int rw_flags;
--
--	nr_sectors = bio_sectors(bio);
+-	struct request_queue *q = disk->queue;
 -
--	/*
--	 * low level driver can indicate that it wants pages above a
--	 * certain limit bounced to low memory (ie for highmem, or even
--	 * ISA dma in theory)
--	 */
--	blk_queue_bounce(q, &bio);
+-	if (q && q->request_fn) {
+-		elv_unregister_queue(q);
 -
--	barrier = bio_barrier(bio);
--	if (unlikely(barrier) && (q->next_ordered == QUEUE_ORDERED_NONE)) {
--		err = -EOPNOTSUPP;
--		goto end_io;
+-		kobject_uevent(&q->kobj, KOBJ_REMOVE);
+-		kobject_del(&q->kobj);
+-		kobject_put(&disk->kobj);
 -	}
+-}
+diff --git a/crypto/Kconfig b/crypto/Kconfig
+index 083d2e1..c3166a1 100644
+--- a/crypto/Kconfig
++++ b/crypto/Kconfig
+@@ -24,10 +24,6 @@ config CRYPTO_ALGAPI
+ 	help
+ 	  This option provides the API for cryptographic algorithms.
+ 
+-config CRYPTO_ABLKCIPHER
+-	tristate
+-	select CRYPTO_BLKCIPHER
 -
--	spin_lock_irq(q->queue_lock);
+ config CRYPTO_AEAD
+ 	tristate
+ 	select CRYPTO_ALGAPI
+@@ -36,6 +32,15 @@ config CRYPTO_BLKCIPHER
+ 	tristate
+ 	select CRYPTO_ALGAPI
+ 
++config CRYPTO_SEQIV
++	tristate "Sequence Number IV Generator"
++	select CRYPTO_AEAD
++	select CRYPTO_BLKCIPHER
++	help
++	  This IV generator generates an IV based on a sequence number by
++	  xoring it with a salt.  This algorithm is mainly useful for CTR
++	  and similar modes.
++
+ config CRYPTO_HASH
+ 	tristate
+ 	select CRYPTO_ALGAPI
+@@ -91,7 +96,7 @@ config CRYPTO_SHA1
+ 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
+ 
+ config CRYPTO_SHA256
+-	tristate "SHA256 digest algorithm"
++	tristate "SHA224 and SHA256 digest algorithm"
+ 	select CRYPTO_ALGAPI
+ 	help
+ 	  SHA256 secure hash standard (DFIPS 180-2).
+@@ -99,6 +104,9 @@ config CRYPTO_SHA256
+ 	  This version of SHA implements a 256 bit hash with 128 bits of
+ 	  security against collision attacks.
+ 
++          This code also includes SHA-224, a 224 bit hash with 112 bits
++          of security against collision attacks.
++
+ config CRYPTO_SHA512
+ 	tristate "SHA384 and SHA512 digest algorithms"
+ 	select CRYPTO_ALGAPI
+@@ -195,9 +203,34 @@ config CRYPTO_XTS
+ 	  key size 256, 384 or 512 bits. This implementation currently
+ 	  can't handle a sectorsize which is not a multiple of 16 bytes.
+ 
++config CRYPTO_CTR
++	tristate "CTR support"
++	select CRYPTO_BLKCIPHER
++	select CRYPTO_SEQIV
++	select CRYPTO_MANAGER
++	help
++	  CTR: Counter mode
++	  This block cipher algorithm is required for IPSec.
++
++config CRYPTO_GCM
++	tristate "GCM/GMAC support"
++	select CRYPTO_CTR
++	select CRYPTO_AEAD
++	select CRYPTO_GF128MUL
++	help
++	  Support for Galois/Counter Mode (GCM) and Galois Message
++	  Authentication Code (GMAC). Required for IPSec.
++
++config CRYPTO_CCM
++	tristate "CCM support"
++	select CRYPTO_CTR
++	select CRYPTO_AEAD
++	help
++	  Support for Counter with CBC MAC. Required for IPsec.
++
+ config CRYPTO_CRYPTD
+ 	tristate "Software async crypto daemon"
+-	select CRYPTO_ABLKCIPHER
++	select CRYPTO_BLKCIPHER
+ 	select CRYPTO_MANAGER
+ 	help
+ 	  This is a generic software asynchronous crypto daemon that
+@@ -320,6 +353,7 @@ config CRYPTO_AES_586
+ 	tristate "AES cipher algorithms (i586)"
+ 	depends on (X86 || UML_X86) && !64BIT
+ 	select CRYPTO_ALGAPI
++	select CRYPTO_AES
+ 	help
+ 	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
+ 	  algorithm.
+@@ -341,6 +375,7 @@ config CRYPTO_AES_X86_64
+ 	tristate "AES cipher algorithms (x86_64)"
+ 	depends on (X86 || UML_X86) && 64BIT
+ 	select CRYPTO_ALGAPI
++	select CRYPTO_AES
+ 	help
+ 	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
+ 	  algorithm.
+@@ -441,6 +476,46 @@ config CRYPTO_SEED
+ 	  See also:
+ 	  <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
+ 
++config CRYPTO_SALSA20
++	tristate "Salsa20 stream cipher algorithm (EXPERIMENTAL)"
++	depends on EXPERIMENTAL
++	select CRYPTO_BLKCIPHER
++	help
++	  Salsa20 stream cipher algorithm.
++
++	  Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
++	  Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
++
++	  The Salsa20 stream cipher algorithm is designed by Daniel J.
++	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
++
++config CRYPTO_SALSA20_586
++	tristate "Salsa20 stream cipher algorithm (i586) (EXPERIMENTAL)"
++	depends on (X86 || UML_X86) && !64BIT
++	depends on EXPERIMENTAL
++	select CRYPTO_BLKCIPHER
++	help
++	  Salsa20 stream cipher algorithm.
++
++	  Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
++	  Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
++
++	  The Salsa20 stream cipher algorithm is designed by Daniel J.
++	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
++
++config CRYPTO_SALSA20_X86_64
++	tristate "Salsa20 stream cipher algorithm (x86_64) (EXPERIMENTAL)"
++	depends on (X86 || UML_X86) && 64BIT
++	depends on EXPERIMENTAL
++	select CRYPTO_BLKCIPHER
++	help
++	  Salsa20 stream cipher algorithm.
++
++	  Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
++	  Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
++
++	  The Salsa20 stream cipher algorithm is designed by Daniel J.
++	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
+ 
+ config CRYPTO_DEFLATE
+ 	tristate "Deflate compression algorithm"
+@@ -491,6 +566,7 @@ config CRYPTO_TEST
+ 	tristate "Testing module"
+ 	depends on m
+ 	select CRYPTO_ALGAPI
++	select CRYPTO_AEAD
+ 	help
+ 	  Quick & dirty crypto test module.
+ 
+@@ -498,10 +574,19 @@ config CRYPTO_AUTHENC
+ 	tristate "Authenc support"
+ 	select CRYPTO_AEAD
+ 	select CRYPTO_MANAGER
++	select CRYPTO_HASH
+ 	help
+ 	  Authenc: Combined mode wrapper for IPsec.
+ 	  This is required for IPSec.
+ 
++config CRYPTO_LZO
++	tristate "LZO compression algorithm"
++	select CRYPTO_ALGAPI
++	select LZO_COMPRESS
++	select LZO_DECOMPRESS
++	help
++	  This is the LZO algorithm.
++
+ source "drivers/crypto/Kconfig"
+ 
+ endif	# if CRYPTO
+diff --git a/crypto/Makefile b/crypto/Makefile
+index 43c2a0d..48c7583 100644
+--- a/crypto/Makefile
++++ b/crypto/Makefile
+@@ -8,9 +8,14 @@ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
+ crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
+ obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
+ 
+-obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
+ obj-$(CONFIG_CRYPTO_AEAD) += aead.o
+-obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
++
++crypto_blkcipher-objs := ablkcipher.o
++crypto_blkcipher-objs += blkcipher.o
++obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
++obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
++obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
++obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
+ 
+ crypto_hash-objs := hash.o
+ obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
+@@ -32,6 +37,9 @@ obj-$(CONFIG_CRYPTO_CBC) += cbc.o
+ obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
+ obj-$(CONFIG_CRYPTO_LRW) += lrw.o
+ obj-$(CONFIG_CRYPTO_XTS) += xts.o
++obj-$(CONFIG_CRYPTO_CTR) += ctr.o
++obj-$(CONFIG_CRYPTO_GCM) += gcm.o
++obj-$(CONFIG_CRYPTO_CCM) += ccm.o
+ obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
+ obj-$(CONFIG_CRYPTO_DES) += des_generic.o
+ obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
+@@ -48,10 +56,12 @@ obj-$(CONFIG_CRYPTO_TEA) += tea.o
+ obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o
+ obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
+ obj-$(CONFIG_CRYPTO_SEED) += seed.o
++obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
+ obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
+ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
+ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
+ obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
++obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+ 
+ obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+ 
+diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
+index 2731acb..3bcb099 100644
+--- a/crypto/ablkcipher.c
++++ b/crypto/ablkcipher.c
+@@ -13,14 +13,18 @@
+  *
+  */
+ 
+-#include <crypto/algapi.h>
+-#include <linux/errno.h>
++#include <crypto/internal/skcipher.h>
++#include <linux/err.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/rtnetlink.h>
++#include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/seq_file.h>
+ 
++#include "internal.h"
++
+ static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key,
+ 			    unsigned int keylen)
+ {
+@@ -66,6 +70,16 @@ static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type,
+ 	return alg->cra_ctxsize;
+ }
+ 
++int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req)
++{
++	return crypto_ablkcipher_encrypt(&req->creq);
++}
++
++int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req)
++{
++	return crypto_ablkcipher_decrypt(&req->creq);
++}
++
+ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
+ 				      u32 mask)
+ {
+@@ -78,6 +92,11 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
+ 	crt->setkey = setkey;
+ 	crt->encrypt = alg->encrypt;
+ 	crt->decrypt = alg->decrypt;
++	if (!alg->ivsize) {
++		crt->givencrypt = skcipher_null_givencrypt;
++		crt->givdecrypt = skcipher_null_givdecrypt;
++	}
++	crt->base = __crypto_ablkcipher_cast(tfm);
+ 	crt->ivsize = alg->ivsize;
+ 
+ 	return 0;
+@@ -90,10 +109,13 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
+ 	struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
+ 
+ 	seq_printf(m, "type         : ablkcipher\n");
++	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
++					     "yes" : "no");
+ 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+ 	seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
+ 	seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
+ 	seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
++	seq_printf(m, "geniv        : %s\n", ablkcipher->geniv ?: "<default>");
+ }
+ 
+ const struct crypto_type crypto_ablkcipher_type = {
+@@ -105,5 +127,220 @@ const struct crypto_type crypto_ablkcipher_type = {
+ };
+ EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
+ 
++static int no_givdecrypt(struct skcipher_givcrypt_request *req)
++{
++	return -ENOSYS;
++}
++
++static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
++				      u32 mask)
++{
++	struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
++	struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
++
++	if (alg->ivsize > PAGE_SIZE / 8)
++		return -EINVAL;
++
++	crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
++		      alg->setkey : setkey;
++	crt->encrypt = alg->encrypt;
++	crt->decrypt = alg->decrypt;
++	crt->givencrypt = alg->givencrypt;
++	crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt;
++	crt->base = __crypto_ablkcipher_cast(tfm);
++	crt->ivsize = alg->ivsize;
++
++	return 0;
++}
++
++static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
++	__attribute__ ((unused));
++static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
++{
++	struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
++
++	seq_printf(m, "type         : givcipher\n");
++	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
++					     "yes" : "no");
++	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
++	seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
++	seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
++	seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
++	seq_printf(m, "geniv        : %s\n", ablkcipher->geniv ?: "<built-in>");
++}
++
++const struct crypto_type crypto_givcipher_type = {
++	.ctxsize = crypto_ablkcipher_ctxsize,
++	.init = crypto_init_givcipher_ops,
++#ifdef CONFIG_PROC_FS
++	.show = crypto_givcipher_show,
++#endif
++};
++EXPORT_SYMBOL_GPL(crypto_givcipher_type);
++
++const char *crypto_default_geniv(const struct crypto_alg *alg)
++{
++	return alg->cra_flags & CRYPTO_ALG_ASYNC ? "eseqiv" : "chainiv";
++}
++
++static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
++{
++	struct rtattr *tb[3];
++	struct {
++		struct rtattr attr;
++		struct crypto_attr_type data;
++	} ptype;
++	struct {
++		struct rtattr attr;
++		struct crypto_attr_alg data;
++	} palg;
++	struct crypto_template *tmpl;
++	struct crypto_instance *inst;
++	struct crypto_alg *larval;
++	const char *geniv;
++	int err;
++
++	larval = crypto_larval_lookup(alg->cra_driver_name,
++				      CRYPTO_ALG_TYPE_GIVCIPHER,
++				      CRYPTO_ALG_TYPE_MASK);
++	err = PTR_ERR(larval);
++	if (IS_ERR(larval))
++		goto out;
++
++	err = -EAGAIN;
++	if (!crypto_is_larval(larval))
++		goto drop_larval;
++
++	ptype.attr.rta_len = sizeof(ptype);
++	ptype.attr.rta_type = CRYPTOA_TYPE;
++	ptype.data.type = type | CRYPTO_ALG_GENIV;
++	/* GENIV tells the template that we're making a default geniv. */
++	ptype.data.mask = mask | CRYPTO_ALG_GENIV;
++	tb[0] = &ptype.attr;
++
++	palg.attr.rta_len = sizeof(palg);
++	palg.attr.rta_type = CRYPTOA_ALG;
++	/* Must use the exact name to locate ourselves. */
++	memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
++	tb[1] = &palg.attr;
++
++	tb[2] = NULL;
++
++	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
++	    CRYPTO_ALG_TYPE_BLKCIPHER)
++		geniv = alg->cra_blkcipher.geniv;
++	else
++		geniv = alg->cra_ablkcipher.geniv;
++
++	if (!geniv)
++		geniv = crypto_default_geniv(alg);
++
++	tmpl = crypto_lookup_template(geniv);
++	err = -ENOENT;
++	if (!tmpl)
++		goto kill_larval;
++
++	inst = tmpl->alloc(tb);
++	err = PTR_ERR(inst);
++	if (IS_ERR(inst))
++		goto put_tmpl;
++
++	if ((err = crypto_register_instance(tmpl, inst))) {
++		tmpl->free(inst);
++		goto put_tmpl;
++	}
++
++	/* Redo the lookup to use the instance we just registered. */
++	err = -EAGAIN;
++
++put_tmpl:
++	crypto_tmpl_put(tmpl);
++kill_larval:
++	crypto_larval_kill(larval);
++drop_larval:
++	crypto_mod_put(larval);
++out:
++	crypto_mod_put(alg);
++	return err;
++}
++
++static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
++						 u32 mask)
++{
++	struct crypto_alg *alg;
++
++	alg = crypto_alg_mod_lookup(name, type, mask);
++	if (IS_ERR(alg))
++		return alg;
++
++	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
++	    CRYPTO_ALG_TYPE_GIVCIPHER)
++		return alg;
++
++	if (!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
++	      CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
++					  alg->cra_ablkcipher.ivsize))
++		return alg;
++
++	return ERR_PTR(crypto_givcipher_default(alg, type, mask));
++}
++
++int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
++			 u32 type, u32 mask)
++{
++	struct crypto_alg *alg;
++	int err;
++
++	type = crypto_skcipher_type(type);
++	mask = crypto_skcipher_mask(mask);
++
++	alg = crypto_lookup_skcipher(name, type, mask);
++	if (IS_ERR(alg))
++		return PTR_ERR(alg);
++
++	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
++	crypto_mod_put(alg);
++	return err;
++}
++EXPORT_SYMBOL_GPL(crypto_grab_skcipher);
++
++struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
++						  u32 type, u32 mask)
++{
++	struct crypto_tfm *tfm;
++	int err;
++
++	type = crypto_skcipher_type(type);
++	mask = crypto_skcipher_mask(mask);
++
++	for (;;) {
++		struct crypto_alg *alg;
++
++		alg = crypto_lookup_skcipher(alg_name, type, mask);
++		if (IS_ERR(alg)) {
++			err = PTR_ERR(alg);
++			goto err;
++		}
++
++		tfm = __crypto_alloc_tfm(alg, type, mask);
++		if (!IS_ERR(tfm))
++			return __crypto_ablkcipher_cast(tfm);
++
++		crypto_mod_put(alg);
++		err = PTR_ERR(tfm);
++
++err:
++		if (err != -EAGAIN)
++			break;
++		if (signal_pending(current)) {
++			err = -EINTR;
++			break;
++		}
++	}
++
++	return ERR_PTR(err);
++}
++EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
+diff --git a/crypto/aead.c b/crypto/aead.c
+index 84a3501..3a6f3f5 100644
+--- a/crypto/aead.c
++++ b/crypto/aead.c
+@@ -12,14 +12,17 @@
+  *
+  */
+ 
+-#include <crypto/algapi.h>
+-#include <linux/errno.h>
++#include <crypto/internal/aead.h>
++#include <linux/err.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/rtnetlink.h>
+ #include <linux/slab.h>
+ #include <linux/seq_file.h>
+ 
++#include "internal.h"
++
+ static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
+ 			    unsigned int keylen)
+ {
+@@ -53,25 +56,54 @@ static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
+ 	return aead->setkey(tfm, key, keylen);
+ }
+ 
++int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
++{
++	struct aead_tfm *crt = crypto_aead_crt(tfm);
++	int err;
++
++	if (authsize > crypto_aead_alg(tfm)->maxauthsize)
++		return -EINVAL;
++
++	if (crypto_aead_alg(tfm)->setauthsize) {
++		err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize);
++		if (err)
++			return err;
++	}
++
++	crypto_aead_crt(crt->base)->authsize = authsize;
++	crt->authsize = authsize;
++	return 0;
++}
++EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
++
+ static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type,
+ 					u32 mask)
+ {
+ 	return alg->cra_ctxsize;
+ }
+ 
++static int no_givcrypt(struct aead_givcrypt_request *req)
++{
++	return -ENOSYS;
++}
++
+ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+ {
+ 	struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
+ 	struct aead_tfm *crt = &tfm->crt_aead;
+ 
+-	if (max(alg->authsize, alg->ivsize) > PAGE_SIZE / 8)
++	if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
+ 		return -EINVAL;
+ 
+-	crt->setkey = setkey;
++	crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
++		      alg->setkey : setkey;
+ 	crt->encrypt = alg->encrypt;
+ 	crt->decrypt = alg->decrypt;
++	crt->givencrypt = alg->givencrypt ?: no_givcrypt;
++	crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
++	crt->base = __crypto_aead_cast(tfm);
+ 	crt->ivsize = alg->ivsize;
+-	crt->authsize = alg->authsize;
++	crt->authsize = alg->maxauthsize;
+ 
+ 	return 0;
+ }
+@@ -83,9 +115,12 @@ static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
+ 	struct aead_alg *aead = &alg->cra_aead;
+ 
+ 	seq_printf(m, "type         : aead\n");
++	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
++					     "yes" : "no");
+ 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+ 	seq_printf(m, "ivsize       : %u\n", aead->ivsize);
+-	seq_printf(m, "authsize     : %u\n", aead->authsize);
++	seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
++	seq_printf(m, "geniv        : %s\n", aead->geniv ?: "<built-in>");
+ }
+ 
+ const struct crypto_type crypto_aead_type = {
+@@ -97,5 +132,358 @@ const struct crypto_type crypto_aead_type = {
+ };
+ EXPORT_SYMBOL_GPL(crypto_aead_type);
+ 
++static int aead_null_givencrypt(struct aead_givcrypt_request *req)
++{
++	return crypto_aead_encrypt(&req->areq);
++}
++
++static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
++{
++	return crypto_aead_decrypt(&req->areq);
++}
++
++static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
++{
++	struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
++	struct aead_tfm *crt = &tfm->crt_aead;
++
++	if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
++		return -EINVAL;
++
++	crt->setkey = setkey;
++	crt->encrypt = alg->encrypt;
++	crt->decrypt = alg->decrypt;
++	if (!alg->ivsize) {
++		crt->givencrypt = aead_null_givencrypt;
++		crt->givdecrypt = aead_null_givdecrypt;
++	}
++	crt->base = __crypto_aead_cast(tfm);
++	crt->ivsize = alg->ivsize;
++	crt->authsize = alg->maxauthsize;
++
++	return 0;
++}
++
++static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
++	__attribute__ ((unused));
++static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
++{
++	struct aead_alg *aead = &alg->cra_aead;
++
++	seq_printf(m, "type         : nivaead\n");
++	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
++					     "yes" : "no");
++	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
++	seq_printf(m, "ivsize       : %u\n", aead->ivsize);
++	seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
++	seq_printf(m, "geniv        : %s\n", aead->geniv);
++}
++
++const struct crypto_type crypto_nivaead_type = {
++	.ctxsize = crypto_aead_ctxsize,
++	.init = crypto_init_nivaead_ops,
++#ifdef CONFIG_PROC_FS
++	.show = crypto_nivaead_show,
++#endif
++};
++EXPORT_SYMBOL_GPL(crypto_nivaead_type);
++
++static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
++			       const char *name, u32 type, u32 mask)
++{
++	struct crypto_alg *alg;
++	int err;
++
++	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
++	type |= CRYPTO_ALG_TYPE_AEAD;
++	mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;
++
++	alg = crypto_alg_mod_lookup(name, type, mask);
++	if (IS_ERR(alg))
++		return PTR_ERR(alg);
++
++	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
++	crypto_mod_put(alg);
++	return err;
++}
++
++struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
++					 struct rtattr **tb, u32 type,
++					 u32 mask)
++{
++	const char *name;
++	struct crypto_aead_spawn *spawn;
++	struct crypto_attr_type *algt;
++	struct crypto_instance *inst;
++	struct crypto_alg *alg;
++	int err;
++
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
++		return ERR_PTR(err);
++
++	if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
++	    algt->mask)
++		return ERR_PTR(-EINVAL);
++
++	name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(name);
++	if (IS_ERR(name))
++		return ERR_PTR(err);
++
++	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
++	if (!inst)
++		return ERR_PTR(-ENOMEM);
++
++	spawn = crypto_instance_ctx(inst);
++
++	/* Ignore async algorithms if necessary. */
++	mask |= crypto_requires_sync(algt->type, algt->mask);
++
++	crypto_set_aead_spawn(spawn, inst);
++	err = crypto_grab_nivaead(spawn, name, type, mask);
++	if (err)
++		goto err_free_inst;
++
++	alg = crypto_aead_spawn_alg(spawn);
++
++	err = -EINVAL;
++	if (!alg->cra_aead.ivsize)
++		goto err_drop_alg;
++
++	/*
++	 * This is only true if we're constructing an algorithm with its
++	 * default IV generator.  For the default generator we elide the
++	 * template name and double-check the IV generator.
++	 */
++	if (algt->mask & CRYPTO_ALG_GENIV) {
++		if (strcmp(tmpl->name, alg->cra_aead.geniv))
++			goto err_drop_alg;
++
++		memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
++		memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
++		       CRYPTO_MAX_ALG_NAME);
++	} else {
++		err = -ENAMETOOLONG;
++		if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
++			     "%s(%s)", tmpl->name, alg->cra_name) >=
++		    CRYPTO_MAX_ALG_NAME)
++			goto err_drop_alg;
++		if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++			     "%s(%s)", tmpl->name, alg->cra_driver_name) >=
++		    CRYPTO_MAX_ALG_NAME)
++			goto err_drop_alg;
++	}
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
++	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = alg->cra_blocksize;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_aead_type;
++
++	inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
++	inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
++	inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
++
++	inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
++	inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
++	inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
++	inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
++
++out:
++	return inst;
++
++err_drop_alg:
++	crypto_drop_aead(spawn);
++err_free_inst:
++	kfree(inst);
++	inst = ERR_PTR(err);
++	goto out;
++}
++EXPORT_SYMBOL_GPL(aead_geniv_alloc);
++
++void aead_geniv_free(struct crypto_instance *inst)
++{
++	crypto_drop_aead(crypto_instance_ctx(inst));
++	kfree(inst);
++}
++EXPORT_SYMBOL_GPL(aead_geniv_free);
++
++int aead_geniv_init(struct crypto_tfm *tfm)
++{
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_aead *aead;
++
++	aead = crypto_spawn_aead(crypto_instance_ctx(inst));
++	if (IS_ERR(aead))
++		return PTR_ERR(aead);
++
++	tfm->crt_aead.base = aead;
++	tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(aead_geniv_init);
++
++void aead_geniv_exit(struct crypto_tfm *tfm)
++{
++	crypto_free_aead(tfm->crt_aead.base);
++}
++EXPORT_SYMBOL_GPL(aead_geniv_exit);
++
++static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
++{
++	struct rtattr *tb[3];
++	struct {
++		struct rtattr attr;
++		struct crypto_attr_type data;
++	} ptype;
++	struct {
++		struct rtattr attr;
++		struct crypto_attr_alg data;
++	} palg;
++	struct crypto_template *tmpl;
++	struct crypto_instance *inst;
++	struct crypto_alg *larval;
++	const char *geniv;
++	int err;
++
++	larval = crypto_larval_lookup(alg->cra_driver_name,
++				      CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
++				      CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
++	err = PTR_ERR(larval);
++	if (IS_ERR(larval))
++		goto out;
++
++	err = -EAGAIN;
++	if (!crypto_is_larval(larval))
++		goto drop_larval;
++
++	ptype.attr.rta_len = sizeof(ptype);
++	ptype.attr.rta_type = CRYPTOA_TYPE;
++	ptype.data.type = type | CRYPTO_ALG_GENIV;
++	/* GENIV tells the template that we're making a default geniv. */
++	ptype.data.mask = mask | CRYPTO_ALG_GENIV;
++	tb[0] = &ptype.attr;
++
++	palg.attr.rta_len = sizeof(palg);
++	palg.attr.rta_type = CRYPTOA_ALG;
++	/* Must use the exact name to locate ourselves. */
++	memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
++	tb[1] = &palg.attr;
++
++	tb[2] = NULL;
++
++	geniv = alg->cra_aead.geniv;
++
++	tmpl = crypto_lookup_template(geniv);
++	err = -ENOENT;
++	if (!tmpl)
++		goto kill_larval;
++
++	inst = tmpl->alloc(tb);
++	err = PTR_ERR(inst);
++	if (IS_ERR(inst))
++		goto put_tmpl;
++
++	if ((err = crypto_register_instance(tmpl, inst))) {
++		tmpl->free(inst);
++		goto put_tmpl;
++	}
++
++	/* Redo the lookup to use the instance we just registered. */
++	err = -EAGAIN;
++
++put_tmpl:
++	crypto_tmpl_put(tmpl);
++kill_larval:
++	crypto_larval_kill(larval);
++drop_larval:
++	crypto_mod_put(larval);
++out:
++	crypto_mod_put(alg);
++	return err;
++}
++
++static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
++					     u32 mask)
++{
++	struct crypto_alg *alg;
++
++	alg = crypto_alg_mod_lookup(name, type, mask);
++	if (IS_ERR(alg))
++		return alg;
++
++	if (alg->cra_type == &crypto_aead_type)
++		return alg;
++
++	if (!alg->cra_aead.ivsize)
++		return alg;
++
++	return ERR_PTR(crypto_nivaead_default(alg, type, mask));
++}
++
++int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
++		     u32 type, u32 mask)
++{
++	struct crypto_alg *alg;
++	int err;
++
++	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
++	type |= CRYPTO_ALG_TYPE_AEAD;
++	mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
++	mask |= CRYPTO_ALG_TYPE_MASK;
++
++	alg = crypto_lookup_aead(name, type, mask);
++	if (IS_ERR(alg))
++		return PTR_ERR(alg);
++
++	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
++	crypto_mod_put(alg);
++	return err;
++}
++EXPORT_SYMBOL_GPL(crypto_grab_aead);
++
++struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
++{
++	struct crypto_tfm *tfm;
++	int err;
++
++	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
++	type |= CRYPTO_ALG_TYPE_AEAD;
++	mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
++	mask |= CRYPTO_ALG_TYPE_MASK;
++
++	for (;;) {
++		struct crypto_alg *alg;
++
++		alg = crypto_lookup_aead(alg_name, type, mask);
++		if (IS_ERR(alg)) {
++			err = PTR_ERR(alg);
++			goto err;
++		}
++
++		tfm = __crypto_alloc_tfm(alg, type, mask);
++		if (!IS_ERR(tfm))
++			return __crypto_aead_cast(tfm);
++
++		crypto_mod_put(alg);
++		err = PTR_ERR(tfm);
++
++err:
++		if (err != -EAGAIN)
++			break;
++		if (signal_pending(current)) {
++			err = -EINTR;
++			break;
++		}
++	}
++
++	return ERR_PTR(err);
++}
++EXPORT_SYMBOL_GPL(crypto_alloc_aead);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
+diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
+index 9401dca..cf30af7 100644
+--- a/crypto/aes_generic.c
++++ b/crypto/aes_generic.c
+@@ -47,11 +47,7 @@
+  * ---------------------------------------------------------------------------
+  */
+ 
+-/* Some changes from the Gladman version:
+-    s/RIJNDAEL(e_key)/E_KEY/g
+-    s/RIJNDAEL(d_key)/D_KEY/g
+-*/
 -
--	if (unlikely(barrier) || elv_queue_empty(q))
--		goto get_rq;
++#include <crypto/aes.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/types.h>
+@@ -59,88 +55,46 @@
+ #include <linux/crypto.h>
+ #include <asm/byteorder.h>
+ 
+-#define AES_MIN_KEY_SIZE	16
+-#define AES_MAX_KEY_SIZE	32
 -
--	el_ret = elv_merge(q, &req, bio);
--	switch (el_ret) {
--		case ELEVATOR_BACK_MERGE:
--			BUG_ON(!rq_mergeable(req));
+-#define AES_BLOCK_SIZE		16
 -
--			if (!ll_back_merge_fn(q, req, bio))
--				break;
+-/*
+- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) 
+- */
+-static inline u8
+-byte(const u32 x, const unsigned n)
++static inline u8 byte(const u32 x, const unsigned n)
+ {
+ 	return x >> (n << 3);
+ }
+ 
+-struct aes_ctx {
+-	int key_length;
+-	u32 buf[120];
+-};
 -
--			blk_add_trace_bio(q, bio, BLK_TA_BACKMERGE);
+-#define E_KEY (&ctx->buf[0])
+-#define D_KEY (&ctx->buf[60])
 -
--			req->biotail->bi_next = bio;
--			req->biotail = bio;
--			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
--			req->ioprio = ioprio_best(req->ioprio, prio);
--			drive_stat_acct(req, 0);
--			if (!attempt_back_merge(q, req))
--				elv_merged_request(q, req, el_ret);
--			goto out;
+ static u8 pow_tab[256] __initdata;
+ static u8 log_tab[256] __initdata;
+ static u8 sbx_tab[256] __initdata;
+ static u8 isb_tab[256] __initdata;
+ static u32 rco_tab[10];
+-static u32 ft_tab[4][256];
+-static u32 it_tab[4][256];
+ 
+-static u32 fl_tab[4][256];
+-static u32 il_tab[4][256];
++u32 crypto_ft_tab[4][256];
++u32 crypto_fl_tab[4][256];
++u32 crypto_it_tab[4][256];
++u32 crypto_il_tab[4][256];
+ 
+-static inline u8 __init
+-f_mult (u8 a, u8 b)
++EXPORT_SYMBOL_GPL(crypto_ft_tab);
++EXPORT_SYMBOL_GPL(crypto_fl_tab);
++EXPORT_SYMBOL_GPL(crypto_it_tab);
++EXPORT_SYMBOL_GPL(crypto_il_tab);
++
++static inline u8 __init f_mult(u8 a, u8 b)
+ {
+ 	u8 aa = log_tab[a], cc = aa + log_tab[b];
+ 
+ 	return pow_tab[cc + (cc < aa ? 1 : 0)];
+ }
+ 
+-#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
 -
--		case ELEVATOR_FRONT_MERGE:
--			BUG_ON(!rq_mergeable(req));
+-#define f_rn(bo, bi, n, k)					\
+-    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
+-             ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+-             ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
 -
--			if (!ll_front_merge_fn(q, req, bio))
--				break;
+-#define i_rn(bo, bi, n, k)					\
+-    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
+-             it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+-             it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
 -
--			blk_add_trace_bio(q, bio, BLK_TA_FRONTMERGE);
+-#define ls_box(x)				\
+-    ( fl_tab[0][byte(x, 0)] ^			\
+-      fl_tab[1][byte(x, 1)] ^			\
+-      fl_tab[2][byte(x, 2)] ^			\
+-      fl_tab[3][byte(x, 3)] )
 -
--			bio->bi_next = req->bio;
--			req->bio = bio;
+-#define f_rl(bo, bi, n, k)					\
+-    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
+-             fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
+-             fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
 -
--			/*
--			 * may not be valid. if the low level driver said
--			 * it didn't need a bounce buffer then it better
--			 * not touch req->buffer either...
--			 */
--			req->buffer = bio_data(bio);
--			req->current_nr_sectors = bio_cur_sectors(bio);
--			req->hard_cur_sectors = req->current_nr_sectors;
--			req->sector = req->hard_sector = bio->bi_sector;
--			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
--			req->ioprio = ioprio_best(req->ioprio, prio);
--			drive_stat_acct(req, 0);
--			if (!attempt_front_merge(q, req))
--				elv_merged_request(q, req, el_ret);
--			goto out;
+-#define i_rl(bo, bi, n, k)					\
+-    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
+-             il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
+-             il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
+-             il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
 -
--		/* ELV_NO_MERGE: elevator says don't/can't merge. */
--		default:
--			;
--	}
+-static void __init
+-gen_tabs (void)
++#define ff_mult(a, b)	(a && b ? f_mult(a, b) : 0)
++
++static void __init gen_tabs(void)
+ {
+ 	u32 i, t;
+ 	u8 p, q;
+ 
+-	/* log and power tables for GF(2**8) finite field with
+-	   0x011b as modular polynomial - the simplest primitive
+-	   root is 0x03, used here to generate the tables */
++	/*
++	 * log and power tables for GF(2**8) finite field with
++	 * 0x011b as modular polynomial - the simplest primitive
++	 * root is 0x03, used here to generate the tables
++	 */
+ 
+ 	for (i = 0, p = 1; i < 256; ++i) {
+ 		pow_tab[i] = (u8) p;
+@@ -169,92 +123,119 @@ gen_tabs (void)
+ 		p = sbx_tab[i];
+ 
+ 		t = p;
+-		fl_tab[0][i] = t;
+-		fl_tab[1][i] = rol32(t, 8);
+-		fl_tab[2][i] = rol32(t, 16);
+-		fl_tab[3][i] = rol32(t, 24);
++		crypto_fl_tab[0][i] = t;
++		crypto_fl_tab[1][i] = rol32(t, 8);
++		crypto_fl_tab[2][i] = rol32(t, 16);
++		crypto_fl_tab[3][i] = rol32(t, 24);
+ 
+-		t = ((u32) ff_mult (2, p)) |
++		t = ((u32) ff_mult(2, p)) |
+ 		    ((u32) p << 8) |
+-		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
++		    ((u32) p << 16) | ((u32) ff_mult(3, p) << 24);
+ 
+-		ft_tab[0][i] = t;
+-		ft_tab[1][i] = rol32(t, 8);
+-		ft_tab[2][i] = rol32(t, 16);
+-		ft_tab[3][i] = rol32(t, 24);
++		crypto_ft_tab[0][i] = t;
++		crypto_ft_tab[1][i] = rol32(t, 8);
++		crypto_ft_tab[2][i] = rol32(t, 16);
++		crypto_ft_tab[3][i] = rol32(t, 24);
+ 
+ 		p = isb_tab[i];
+ 
+ 		t = p;
+-		il_tab[0][i] = t;
+-		il_tab[1][i] = rol32(t, 8);
+-		il_tab[2][i] = rol32(t, 16);
+-		il_tab[3][i] = rol32(t, 24);
 -
--get_rq:
--	/*
--	 * This sync check and mask will be re-done in init_request_from_bio(),
--	 * but we need to set it earlier to expose the sync flag to the
--	 * rq allocator and io schedulers.
--	 */
--	rw_flags = bio_data_dir(bio);
--	if (sync)
--		rw_flags |= REQ_RW_SYNC;
+-		t = ((u32) ff_mult (14, p)) |
+-		    ((u32) ff_mult (9, p) << 8) |
+-		    ((u32) ff_mult (13, p) << 16) |
+-		    ((u32) ff_mult (11, p) << 24);
 -
--	/*
--	 * Grab a free request. This is might sleep but can not fail.
--	 * Returns with the queue unlocked.
--	 */
--	req = get_request_wait(q, rw_flags, bio);
+-		it_tab[0][i] = t;
+-		it_tab[1][i] = rol32(t, 8);
+-		it_tab[2][i] = rol32(t, 16);
+-		it_tab[3][i] = rol32(t, 24);
++		crypto_il_tab[0][i] = t;
++		crypto_il_tab[1][i] = rol32(t, 8);
++		crypto_il_tab[2][i] = rol32(t, 16);
++		crypto_il_tab[3][i] = rol32(t, 24);
++
++		t = ((u32) ff_mult(14, p)) |
++		    ((u32) ff_mult(9, p) << 8) |
++		    ((u32) ff_mult(13, p) << 16) |
++		    ((u32) ff_mult(11, p) << 24);
++
++		crypto_it_tab[0][i] = t;
++		crypto_it_tab[1][i] = rol32(t, 8);
++		crypto_it_tab[2][i] = rol32(t, 16);
++		crypto_it_tab[3][i] = rol32(t, 24);
+ 	}
+ }
+ 
+-#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
 -
--	/*
--	 * After dropping the lock and possibly sleeping here, our request
--	 * may now be mergeable after it had proven unmergeable (above).
--	 * We don't worry about that case for efficiency. It won't happen
--	 * often, and the elevators are able to handle it.
--	 */
--	init_request_from_bio(req, bio);
+-#define imix_col(y,x)       \
+-    u   = star_x(x);        \
+-    v   = star_x(u);        \
+-    w   = star_x(v);        \
+-    t   = w ^ (x);          \
+-   (y)  = u ^ v ^ w;        \
+-   (y) ^= ror32(u ^ t,  8) ^ \
+-          ror32(v ^ t, 16) ^ \
+-          ror32(t,24)
 -
--	spin_lock_irq(q->queue_lock);
--	if (elv_queue_empty(q))
--		blk_plug_device(q);
--	add_request(q, req);
--out:
--	if (sync)
--		__generic_unplug_device(q);
+ /* initialise the key schedule from the user supplied key */
+ 
+-#define loop4(i)                                    \
+-{   t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+-    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
+-    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
+-    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
+-    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
+-}
 -
--	spin_unlock_irq(q->queue_lock);
--	return 0;
+-#define loop6(i)                                    \
+-{   t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+-    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
+-    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
+-    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
+-    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
+-    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
+-    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
+-}
 -
--end_io:
--	bio_endio(bio, err);
--	return 0;
+-#define loop8(i)                                    \
+-{   t = ror32(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
+-    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
+-    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
+-    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
+-    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
+-    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
+-    E_KEY[8 * i + 12] = t;                \
+-    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
+-    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
+-    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
 -}
++#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
+ 
+-static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+-		       unsigned int key_len)
++#define imix_col(y,x)	do {		\
++	u	= star_x(x);		\
++	v	= star_x(u);		\
++	w	= star_x(v);		\
++	t	= w ^ (x);		\
++	(y)	= u ^ v ^ w;		\
++	(y)	^= ror32(u ^ t, 8) ^	\
++		ror32(v ^ t, 16) ^	\
++		ror32(t, 24);		\
++} while (0)
++
++#define ls_box(x)		\
++	crypto_fl_tab[0][byte(x, 0)] ^	\
++	crypto_fl_tab[1][byte(x, 1)] ^	\
++	crypto_fl_tab[2][byte(x, 2)] ^	\
++	crypto_fl_tab[3][byte(x, 3)]
++
++#define loop4(i)	do {		\
++	t = ror32(t, 8);		\
++	t = ls_box(t) ^ rco_tab[i];	\
++	t ^= ctx->key_enc[4 * i];		\
++	ctx->key_enc[4 * i + 4] = t;		\
++	t ^= ctx->key_enc[4 * i + 1];		\
++	ctx->key_enc[4 * i + 5] = t;		\
++	t ^= ctx->key_enc[4 * i + 2];		\
++	ctx->key_enc[4 * i + 6] = t;		\
++	t ^= ctx->key_enc[4 * i + 3];		\
++	ctx->key_enc[4 * i + 7] = t;		\
++} while (0)
++
++#define loop6(i)	do {		\
++	t = ror32(t, 8);		\
++	t = ls_box(t) ^ rco_tab[i];	\
++	t ^= ctx->key_enc[6 * i];		\
++	ctx->key_enc[6 * i + 6] = t;		\
++	t ^= ctx->key_enc[6 * i + 1];		\
++	ctx->key_enc[6 * i + 7] = t;		\
++	t ^= ctx->key_enc[6 * i + 2];		\
++	ctx->key_enc[6 * i + 8] = t;		\
++	t ^= ctx->key_enc[6 * i + 3];		\
++	ctx->key_enc[6 * i + 9] = t;		\
++	t ^= ctx->key_enc[6 * i + 4];		\
++	ctx->key_enc[6 * i + 10] = t;		\
++	t ^= ctx->key_enc[6 * i + 5];		\
++	ctx->key_enc[6 * i + 11] = t;		\
++} while (0)
++
++#define loop8(i)	do {			\
++	t = ror32(t, 8);			\
++	t = ls_box(t) ^ rco_tab[i];		\
++	t ^= ctx->key_enc[8 * i];			\
++	ctx->key_enc[8 * i + 8] = t;			\
++	t ^= ctx->key_enc[8 * i + 1];			\
++	ctx->key_enc[8 * i + 9] = t;			\
++	t ^= ctx->key_enc[8 * i + 2];			\
++	ctx->key_enc[8 * i + 10] = t;			\
++	t ^= ctx->key_enc[8 * i + 3];			\
++	ctx->key_enc[8 * i + 11] = t;			\
++	t  = ctx->key_enc[8 * i + 4] ^ ls_box(t);	\
++	ctx->key_enc[8 * i + 12] = t;			\
++	t ^= ctx->key_enc[8 * i + 5];			\
++	ctx->key_enc[8 * i + 13] = t;			\
++	t ^= ctx->key_enc[8 * i + 6];			\
++	ctx->key_enc[8 * i + 14] = t;			\
++	t ^= ctx->key_enc[8 * i + 7];			\
++	ctx->key_enc[8 * i + 15] = t;			\
++} while (0)
++
++int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
++		unsigned int key_len)
+ {
+-	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	const __le32 *key = (const __le32 *)in_key;
+ 	u32 *flags = &tfm->crt_flags;
+-	u32 i, t, u, v, w;
++	u32 i, t, u, v, w, j;
+ 
+ 	if (key_len % 8) {
+ 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+@@ -263,95 +244,113 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 
+ 	ctx->key_length = key_len;
+ 
+-	E_KEY[0] = le32_to_cpu(key[0]);
+-	E_KEY[1] = le32_to_cpu(key[1]);
+-	E_KEY[2] = le32_to_cpu(key[2]);
+-	E_KEY[3] = le32_to_cpu(key[3]);
++	ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]);
++	ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]);
++	ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]);
++	ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);
+ 
+ 	switch (key_len) {
+ 	case 16:
+-		t = E_KEY[3];
++		t = ctx->key_enc[3];
+ 		for (i = 0; i < 10; ++i)
+-			loop4 (i);
++			loop4(i);
+ 		break;
+ 
+ 	case 24:
+-		E_KEY[4] = le32_to_cpu(key[4]);
+-		t = E_KEY[5] = le32_to_cpu(key[5]);
++		ctx->key_enc[4] = le32_to_cpu(key[4]);
++		t = ctx->key_enc[5] = le32_to_cpu(key[5]);
+ 		for (i = 0; i < 8; ++i)
+-			loop6 (i);
++			loop6(i);
+ 		break;
+ 
+ 	case 32:
+-		E_KEY[4] = le32_to_cpu(key[4]);
+-		E_KEY[5] = le32_to_cpu(key[5]);
+-		E_KEY[6] = le32_to_cpu(key[6]);
+-		t = E_KEY[7] = le32_to_cpu(key[7]);
++		ctx->key_enc[4] = le32_to_cpu(key[4]);
++		ctx->key_enc[5] = le32_to_cpu(key[5]);
++		ctx->key_enc[6] = le32_to_cpu(key[6]);
++		t = ctx->key_enc[7] = le32_to_cpu(key[7]);
+ 		for (i = 0; i < 7; ++i)
+-			loop8 (i);
++			loop8(i);
+ 		break;
+ 	}
+ 
+-	D_KEY[0] = E_KEY[0];
+-	D_KEY[1] = E_KEY[1];
+-	D_KEY[2] = E_KEY[2];
+-	D_KEY[3] = E_KEY[3];
++	ctx->key_dec[0] = ctx->key_enc[key_len + 24];
++	ctx->key_dec[1] = ctx->key_enc[key_len + 25];
++	ctx->key_dec[2] = ctx->key_enc[key_len + 26];
++	ctx->key_dec[3] = ctx->key_enc[key_len + 27];
+ 
+ 	for (i = 4; i < key_len + 24; ++i) {
+-		imix_col (D_KEY[i], E_KEY[i]);
++		j = key_len + 24 - (i & ~3) + (i & 3);
++		imix_col(ctx->key_dec[j], ctx->key_enc[i]);
+ 	}
 -
--/*
-- * If bio->bi_dev is a partition, remap the location
-- */
--static inline void blk_partition_remap(struct bio *bio)
--{
--	struct block_device *bdev = bio->bi_bdev;
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(crypto_aes_set_key);
+ 
+ /* encrypt a block of text */
+ 
+-#define f_nround(bo, bi, k) \
+-    f_rn(bo, bi, 0, k);     \
+-    f_rn(bo, bi, 1, k);     \
+-    f_rn(bo, bi, 2, k);     \
+-    f_rn(bo, bi, 3, k);     \
+-    k += 4
 -
--	if (bio_sectors(bio) && bdev != bdev->bd_contains) {
--		struct hd_struct *p = bdev->bd_part;
--		const int rw = bio_data_dir(bio);
+-#define f_lround(bo, bi, k) \
+-    f_rl(bo, bi, 0, k);     \
+-    f_rl(bo, bi, 1, k);     \
+-    f_rl(bo, bi, 2, k);     \
+-    f_rl(bo, bi, 3, k)
++#define f_rn(bo, bi, n, k)	do {				\
++	bo[n] = crypto_ft_tab[0][byte(bi[n], 0)] ^			\
++		crypto_ft_tab[1][byte(bi[(n + 1) & 3], 1)] ^		\
++		crypto_ft_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
++		crypto_ft_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n);	\
++} while (0)
++
++#define f_nround(bo, bi, k)	do {\
++	f_rn(bo, bi, 0, k);	\
++	f_rn(bo, bi, 1, k);	\
++	f_rn(bo, bi, 2, k);	\
++	f_rn(bo, bi, 3, k);	\
++	k += 4;			\
++} while (0)
++
++#define f_rl(bo, bi, n, k)	do {				\
++	bo[n] = crypto_fl_tab[0][byte(bi[n], 0)] ^			\
++		crypto_fl_tab[1][byte(bi[(n + 1) & 3], 1)] ^		\
++		crypto_fl_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
++		crypto_fl_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n);	\
++} while (0)
++
++#define f_lround(bo, bi, k)	do {\
++	f_rl(bo, bi, 0, k);	\
++	f_rl(bo, bi, 1, k);	\
++	f_rl(bo, bi, 2, k);	\
++	f_rl(bo, bi, 3, k);	\
++} while (0)
+ 
+ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+-	const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
++	const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	const __le32 *src = (const __le32 *)in;
+ 	__le32 *dst = (__le32 *)out;
+ 	u32 b0[4], b1[4];
+-	const u32 *kp = E_KEY + 4;
++	const u32 *kp = ctx->key_enc + 4;
++	const int key_len = ctx->key_length;
+ 
+-	b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0];
+-	b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1];
+-	b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2];
+-	b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3];
++	b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0];
++	b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1];
++	b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2];
++	b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3];
+ 
+-	if (ctx->key_length > 24) {
+-		f_nround (b1, b0, kp);
+-		f_nround (b0, b1, kp);
++	if (key_len > 24) {
++		f_nround(b1, b0, kp);
++		f_nround(b0, b1, kp);
+ 	}
+ 
+-	if (ctx->key_length > 16) {
+-		f_nround (b1, b0, kp);
+-		f_nround (b0, b1, kp);
++	if (key_len > 16) {
++		f_nround(b1, b0, kp);
++		f_nround(b0, b1, kp);
+ 	}
+ 
+-	f_nround (b1, b0, kp);
+-	f_nround (b0, b1, kp);
+-	f_nround (b1, b0, kp);
+-	f_nround (b0, b1, kp);
+-	f_nround (b1, b0, kp);
+-	f_nround (b0, b1, kp);
+-	f_nround (b1, b0, kp);
+-	f_nround (b0, b1, kp);
+-	f_nround (b1, b0, kp);
+-	f_lround (b0, b1, kp);
++	f_nround(b1, b0, kp);
++	f_nround(b0, b1, kp);
++	f_nround(b1, b0, kp);
++	f_nround(b0, b1, kp);
++	f_nround(b1, b0, kp);
++	f_nround(b0, b1, kp);
++	f_nround(b1, b0, kp);
++	f_nround(b0, b1, kp);
++	f_nround(b1, b0, kp);
++	f_lround(b0, b1, kp);
+ 
+ 	dst[0] = cpu_to_le32(b0[0]);
+ 	dst[1] = cpu_to_le32(b0[1]);
+@@ -361,53 +360,69 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ 
+ /* decrypt a block of text */
+ 
+-#define i_nround(bo, bi, k) \
+-    i_rn(bo, bi, 0, k);     \
+-    i_rn(bo, bi, 1, k);     \
+-    i_rn(bo, bi, 2, k);     \
+-    i_rn(bo, bi, 3, k);     \
+-    k -= 4
 -
--		p->sectors[rw] += bio_sectors(bio);
--		p->ios[rw]++;
+-#define i_lround(bo, bi, k) \
+-    i_rl(bo, bi, 0, k);     \
+-    i_rl(bo, bi, 1, k);     \
+-    i_rl(bo, bi, 2, k);     \
+-    i_rl(bo, bi, 3, k)
++#define i_rn(bo, bi, n, k)	do {				\
++	bo[n] = crypto_it_tab[0][byte(bi[n], 0)] ^			\
++		crypto_it_tab[1][byte(bi[(n + 3) & 3], 1)] ^		\
++		crypto_it_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
++		crypto_it_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n);	\
++} while (0)
++
++#define i_nround(bo, bi, k)	do {\
++	i_rn(bo, bi, 0, k);	\
++	i_rn(bo, bi, 1, k);	\
++	i_rn(bo, bi, 2, k);	\
++	i_rn(bo, bi, 3, k);	\
++	k += 4;			\
++} while (0)
++
++#define i_rl(bo, bi, n, k)	do {			\
++	bo[n] = crypto_il_tab[0][byte(bi[n], 0)] ^		\
++	crypto_il_tab[1][byte(bi[(n + 3) & 3], 1)] ^		\
++	crypto_il_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
++	crypto_il_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n);	\
++} while (0)
++
++#define i_lround(bo, bi, k)	do {\
++	i_rl(bo, bi, 0, k);	\
++	i_rl(bo, bi, 1, k);	\
++	i_rl(bo, bi, 2, k);	\
++	i_rl(bo, bi, 3, k);	\
++} while (0)
+ 
+ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+-	const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
++	const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	const __le32 *src = (const __le32 *)in;
+ 	__le32 *dst = (__le32 *)out;
+ 	u32 b0[4], b1[4];
+ 	const int key_len = ctx->key_length;
+-	const u32 *kp = D_KEY + key_len + 20;
++	const u32 *kp = ctx->key_dec + 4;
+ 
+-	b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24];
+-	b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25];
+-	b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26];
+-	b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27];
++	b0[0] = le32_to_cpu(src[0]) ^  ctx->key_dec[0];
++	b0[1] = le32_to_cpu(src[1]) ^  ctx->key_dec[1];
++	b0[2] = le32_to_cpu(src[2]) ^  ctx->key_dec[2];
++	b0[3] = le32_to_cpu(src[3]) ^  ctx->key_dec[3];
+ 
+ 	if (key_len > 24) {
+-		i_nround (b1, b0, kp);
+-		i_nround (b0, b1, kp);
++		i_nround(b1, b0, kp);
++		i_nround(b0, b1, kp);
+ 	}
+ 
+ 	if (key_len > 16) {
+-		i_nround (b1, b0, kp);
+-		i_nround (b0, b1, kp);
++		i_nround(b1, b0, kp);
++		i_nround(b0, b1, kp);
+ 	}
+ 
+-	i_nround (b1, b0, kp);
+-	i_nround (b0, b1, kp);
+-	i_nround (b1, b0, kp);
+-	i_nround (b0, b1, kp);
+-	i_nround (b1, b0, kp);
+-	i_nround (b0, b1, kp);
+-	i_nround (b1, b0, kp);
+-	i_nround (b0, b1, kp);
+-	i_nround (b1, b0, kp);
+-	i_lround (b0, b1, kp);
++	i_nround(b1, b0, kp);
++	i_nround(b0, b1, kp);
++	i_nround(b1, b0, kp);
++	i_nround(b0, b1, kp);
++	i_nround(b1, b0, kp);
++	i_nround(b0, b1, kp);
++	i_nround(b1, b0, kp);
++	i_nround(b0, b1, kp);
++	i_nround(b1, b0, kp);
++	i_lround(b0, b1, kp);
+ 
+ 	dst[0] = cpu_to_le32(b0[0]);
+ 	dst[1] = cpu_to_le32(b0[1]);
+@@ -415,14 +430,13 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ 	dst[3] = cpu_to_le32(b0[3]);
+ }
+ 
 -
--		bio->bi_sector += p->start_sect;
--		bio->bi_bdev = bdev->bd_contains;
+ static struct crypto_alg aes_alg = {
+ 	.cra_name		=	"aes",
+ 	.cra_driver_name	=	"aes-generic",
+ 	.cra_priority		=	100,
+ 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
+ 	.cra_blocksize		=	AES_BLOCK_SIZE,
+-	.cra_ctxsize		=	sizeof(struct aes_ctx),
++	.cra_ctxsize		=	sizeof(struct crypto_aes_ctx),
+ 	.cra_alignmask		=	3,
+ 	.cra_module		=	THIS_MODULE,
+ 	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
+@@ -430,9 +444,9 @@ static struct crypto_alg aes_alg = {
+ 		.cipher = {
+ 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
+ 			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
+-			.cia_setkey	   	= 	aes_set_key,
+-			.cia_encrypt	 	=	aes_encrypt,
+-			.cia_decrypt	  	=	aes_decrypt
++			.cia_setkey		=	crypto_aes_set_key,
++			.cia_encrypt		=	aes_encrypt,
++			.cia_decrypt		=	aes_decrypt
+ 		}
+ 	}
+ };
+diff --git a/crypto/algapi.c b/crypto/algapi.c
+index 8383282..e65cb50 100644
+--- a/crypto/algapi.c
++++ b/crypto/algapi.c
+@@ -472,7 +472,7 @@ int crypto_check_attr_type(struct rtattr **tb, u32 type)
+ }
+ EXPORT_SYMBOL_GPL(crypto_check_attr_type);
+ 
+-struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
++const char *crypto_attr_alg_name(struct rtattr *rta)
+ {
+ 	struct crypto_attr_alg *alga;
+ 
+@@ -486,7 +486,21 @@ struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
+ 	alga = RTA_DATA(rta);
+ 	alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
+ 
+-	return crypto_alg_mod_lookup(alga->name, type, mask);
++	return alga->name;
++}
++EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
++
++struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
++{
++	const char *name;
++	int err;
++
++	name = crypto_attr_alg_name(rta);
++	err = PTR_ERR(name);
++	if (IS_ERR(name))
++		return ERR_PTR(err);
++
++	return crypto_alg_mod_lookup(name, type, mask);
+ }
+ EXPORT_SYMBOL_GPL(crypto_attr_alg);
+ 
+@@ -605,6 +619,53 @@ int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
+ }
+ EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
+ 
++static inline void crypto_inc_byte(u8 *a, unsigned int size)
++{
++	u8 *b = (a + size);
++	u8 c;
++
++	for (; size; size--) {
++		c = *--b + 1;
++		*b = c;
++		if (c)
++			break;
++	}
++}
++
++void crypto_inc(u8 *a, unsigned int size)
++{
++	__be32 *b = (__be32 *)(a + size);
++	u32 c;
++
++	for (; size >= 4; size -= 4) {
++		c = be32_to_cpu(*--b) + 1;
++		*b = cpu_to_be32(c);
++		if (c)
++			return;
++	}
++
++	crypto_inc_byte(a, size);
++}
++EXPORT_SYMBOL_GPL(crypto_inc);
++
++static inline void crypto_xor_byte(u8 *a, const u8 *b, unsigned int size)
++{
++	for (; size; size--)
++		*a++ ^= *b++;
++}
++
++void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
++{
++	u32 *a = (u32 *)dst;
++	u32 *b = (u32 *)src;
++
++	for (; size >= 4; size -= 4)
++		*a++ ^= *b++;
++
++	crypto_xor_byte((u8 *)a, (u8 *)b, size);
++}
++EXPORT_SYMBOL_GPL(crypto_xor);
++
+ static int __init crypto_algapi_init(void)
+ {
+ 	crypto_init_proc();
+diff --git a/crypto/api.c b/crypto/api.c
+index 1f5c724..a2496d1 100644
+--- a/crypto/api.c
++++ b/crypto/api.c
+@@ -137,7 +137,7 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
+ 	return alg;
+ }
+ 
+-static void crypto_larval_kill(struct crypto_alg *alg)
++void crypto_larval_kill(struct crypto_alg *alg)
+ {
+ 	struct crypto_larval *larval = (void *)alg;
+ 
+@@ -147,6 +147,7 @@ static void crypto_larval_kill(struct crypto_alg *alg)
+ 	complete_all(&larval->completion);
+ 	crypto_alg_put(alg);
+ }
++EXPORT_SYMBOL_GPL(crypto_larval_kill);
+ 
+ static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
+ {
+@@ -176,11 +177,9 @@ static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
+ 	return alg;
+ }
+ 
+-struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
++struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
+ {
+ 	struct crypto_alg *alg;
+-	struct crypto_alg *larval;
+-	int ok;
+ 
+ 	if (!name)
+ 		return ERR_PTR(-ENOENT);
+@@ -193,7 +192,17 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
+ 	if (alg)
+ 		return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
+ 
+-	larval = crypto_larval_alloc(name, type, mask);
++	return crypto_larval_alloc(name, type, mask);
++}
++EXPORT_SYMBOL_GPL(crypto_larval_lookup);
++
++struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
++{
++	struct crypto_alg *alg;
++	struct crypto_alg *larval;
++	int ok;
++
++	larval = crypto_larval_lookup(name, type, mask);
+ 	if (IS_ERR(larval) || !crypto_is_larval(larval))
+ 		return larval;
+ 
+diff --git a/crypto/authenc.c b/crypto/authenc.c
+index 126a529..ed8ac5a 100644
+--- a/crypto/authenc.c
++++ b/crypto/authenc.c
+@@ -10,22 +10,21 @@
+  *
+  */
+ 
+-#include <crypto/algapi.h>
++#include <crypto/aead.h>
++#include <crypto/internal/skcipher.h>
++#include <crypto/authenc.h>
++#include <crypto/scatterwalk.h>
+ #include <linux/err.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/rtnetlink.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
+ 
+-#include "scatterwalk.h"
 -
--		blk_add_trace_remap(bdev_get_queue(bio->bi_bdev), bio,
--				    bdev->bd_dev, bio->bi_sector,
--				    bio->bi_sector - p->start_sect);
+ struct authenc_instance_ctx {
+ 	struct crypto_spawn auth;
+-	struct crypto_spawn enc;
+-
+-	unsigned int authsize;
+-	unsigned int enckeylen;
++	struct crypto_skcipher_spawn enc;
+ };
+ 
+ struct crypto_authenc_ctx {
+@@ -37,19 +36,31 @@ struct crypto_authenc_ctx {
+ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
+ 				 unsigned int keylen)
+ {
+-	struct authenc_instance_ctx *ictx =
+-		crypto_instance_ctx(crypto_aead_alg_instance(authenc));
+-	unsigned int enckeylen = ictx->enckeylen;
+ 	unsigned int authkeylen;
++	unsigned int enckeylen;
+ 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ 	struct crypto_hash *auth = ctx->auth;
+ 	struct crypto_ablkcipher *enc = ctx->enc;
++	struct rtattr *rta = (void *)key;
++	struct crypto_authenc_key_param *param;
+ 	int err = -EINVAL;
+ 
+-	if (keylen < enckeylen) {
+-		crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
+-		goto out;
 -	}
--}
++	if (!RTA_OK(rta, keylen))
++		goto badkey;
++	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
++		goto badkey;
++	if (RTA_PAYLOAD(rta) < sizeof(*param))
++		goto badkey;
++
++	param = RTA_DATA(rta);
++	enckeylen = be32_to_cpu(param->enckeylen);
++
++	key += RTA_ALIGN(rta->rta_len);
++	keylen -= RTA_ALIGN(rta->rta_len);
++
++	if (keylen < enckeylen)
++		goto badkey;
++
+ 	authkeylen = keylen - enckeylen;
+ 
+ 	crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
+@@ -71,21 +82,38 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
+ 
+ out:
+ 	return err;
++
++badkey:
++	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
++	goto out;
+ }
+ 
+-static int crypto_authenc_hash(struct aead_request *req)
++static void authenc_chain(struct scatterlist *head, struct scatterlist *sg,
++			  int chain)
++{
++	if (chain) {
++		head->length += sg->length;
++		sg = scatterwalk_sg_next(sg);
++	}
++
++	if (sg)
++		scatterwalk_sg_chain(head, 2, sg);
++	else
++		sg_mark_end(head);
++}
++
++static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags,
++			       struct scatterlist *cipher,
++			       unsigned int cryptlen)
+ {
+ 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+-	struct authenc_instance_ctx *ictx =
+-		crypto_instance_ctx(crypto_aead_alg_instance(authenc));
+ 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ 	struct crypto_hash *auth = ctx->auth;
+ 	struct hash_desc desc = {
+ 		.tfm = auth,
++		.flags = aead_request_flags(req) & flags,
+ 	};
+ 	u8 *hash = aead_request_ctx(req);
+-	struct scatterlist *dst = req->dst;
+-	unsigned int cryptlen = req->cryptlen;
+ 	int err;
+ 
+ 	hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), 
+@@ -100,7 +128,7 @@ static int crypto_authenc_hash(struct aead_request *req)
+ 	if (err)
+ 		goto auth_unlock;
+ 
+-	err = crypto_hash_update(&desc, dst, cryptlen);
++	err = crypto_hash_update(&desc, cipher, cryptlen);
+ 	if (err)
+ 		goto auth_unlock;
+ 
+@@ -109,17 +137,53 @@ auth_unlock:
+ 	spin_unlock_bh(&ctx->auth_lock);
+ 
+ 	if (err)
+-		return err;
++		return ERR_PTR(err);
++
++	return hash;
++}
+ 
+-	scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1);
++static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
++				 unsigned int flags)
++{
++	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
++	struct scatterlist *dst = req->dst;
++	struct scatterlist cipher[2];
++	struct page *dstp;
++	unsigned int ivsize = crypto_aead_ivsize(authenc);
++	unsigned int cryptlen;
++	u8 *vdst;
++	u8 *hash;
++
++	dstp = sg_page(dst);
++	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
++
++	sg_init_table(cipher, 2);
++	sg_set_buf(cipher, iv, ivsize);
++	authenc_chain(cipher, dst, vdst == iv + ivsize);
++
++	cryptlen = req->cryptlen + ivsize;
++	hash = crypto_authenc_hash(req, flags, cipher, cryptlen);
++	if (IS_ERR(hash))
++		return PTR_ERR(hash);
++
++	scatterwalk_map_and_copy(hash, cipher, cryptlen,
++				 crypto_aead_authsize(authenc), 1);
+ 	return 0;
+ }
+ 
+ static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
+ 					int err)
+ {
+-	if (!err)
+-		err = crypto_authenc_hash(req->data);
++	if (!err) {
++		struct aead_request *areq = req->data;
++		struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
++		struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
++		struct ablkcipher_request *abreq = aead_request_ctx(areq);
++		u8 *iv = (u8 *)(abreq + 1) +
++			 crypto_ablkcipher_reqsize(ctx->enc);
++
++		err = crypto_authenc_genicv(areq, iv, 0);
++	}
+ 
+ 	aead_request_complete(req->data, err);
+ }
+@@ -129,72 +193,99 @@ static int crypto_authenc_encrypt(struct aead_request *req)
+ 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ 	struct ablkcipher_request *abreq = aead_request_ctx(req);
++	struct crypto_ablkcipher *enc = ctx->enc;
++	struct scatterlist *dst = req->dst;
++	unsigned int cryptlen = req->cryptlen;
++	u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc);
+ 	int err;
+ 
+-	ablkcipher_request_set_tfm(abreq, ctx->enc);
++	ablkcipher_request_set_tfm(abreq, enc);
+ 	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ 					crypto_authenc_encrypt_done, req);
+-	ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
+-				     req->iv);
++	ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
++
++	memcpy(iv, req->iv, crypto_aead_ivsize(authenc));
+ 
+ 	err = crypto_ablkcipher_encrypt(abreq);
+ 	if (err)
+ 		return err;
+ 
+-	return crypto_authenc_hash(req);
++	return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+ }
+ 
+-static int crypto_authenc_verify(struct aead_request *req)
++static void crypto_authenc_givencrypt_done(struct crypto_async_request *req,
++					   int err)
+ {
+-	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+-	struct authenc_instance_ctx *ictx =
+-		crypto_instance_ctx(crypto_aead_alg_instance(authenc));
++	if (!err) {
++		struct aead_givcrypt_request *greq = req->data;
++
++		err = crypto_authenc_genicv(&greq->areq, greq->giv, 0);
++	}
++
++	aead_request_complete(req->data, err);
++}
++
++static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
++{
++	struct crypto_aead *authenc = aead_givcrypt_reqtfm(req);
+ 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+-	struct crypto_hash *auth = ctx->auth;
+-	struct hash_desc desc = {
+-		.tfm = auth,
+-		.flags = aead_request_flags(req),
+-	};
+-	u8 *ohash = aead_request_ctx(req);
+-	u8 *ihash;
+-	struct scatterlist *src = req->src;
+-	unsigned int cryptlen = req->cryptlen;
+-	unsigned int authsize;
++	struct aead_request *areq = &req->areq;
++	struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
++	u8 *iv = req->giv;
+ 	int err;
+ 
+-	ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), 
+-			    crypto_hash_alignmask(auth) + 1);
+-	ihash = ohash + crypto_hash_digestsize(auth);
 -
--static void handle_bad_sector(struct bio *bio)
--{
--	char b[BDEVNAME_SIZE];
+-	spin_lock_bh(&ctx->auth_lock);
+-	err = crypto_hash_init(&desc);
+-	if (err)
+-		goto auth_unlock;
++	skcipher_givcrypt_set_tfm(greq, ctx->enc);
++	skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
++				       crypto_authenc_givencrypt_done, areq);
++	skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
++				    areq->iv);
++	skcipher_givcrypt_set_giv(greq, iv, req->seq);
+ 
+-	err = crypto_hash_update(&desc, req->assoc, req->assoclen);
++	err = crypto_skcipher_givencrypt(greq);
+ 	if (err)
+-		goto auth_unlock;
++		return err;
+ 
+-	err = crypto_hash_update(&desc, src, cryptlen);
+-	if (err)
+-		goto auth_unlock;
++	return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
++}
+ 
+-	err = crypto_hash_final(&desc, ohash);
+-auth_unlock:
+-	spin_unlock_bh(&ctx->auth_lock);
++static int crypto_authenc_verify(struct aead_request *req,
++				 struct scatterlist *cipher,
++				 unsigned int cryptlen)
++{
++	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
++	u8 *ohash;
++	u8 *ihash;
++	unsigned int authsize;
+ 
+-	if (err)
+-		return err;
++	ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, cipher,
++				    cryptlen);
++	if (IS_ERR(ohash))
++		return PTR_ERR(ohash);
+ 
+-	authsize = ictx->authsize;
+-	scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0);
+-	return memcmp(ihash, ohash, authsize) ? -EINVAL : 0;
++	authsize = crypto_aead_authsize(authenc);
++	ihash = ohash + authsize;
++	scatterwalk_map_and_copy(ihash, cipher, cryptlen, authsize, 0);
++	return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0;
+ }
+ 
+-static void crypto_authenc_decrypt_done(struct crypto_async_request *req,
+-					int err)
++static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
++				  unsigned int cryptlen)
+ {
+-	aead_request_complete(req->data, err);
++	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
++	struct scatterlist *src = req->src;
++	struct scatterlist cipher[2];
++	struct page *srcp;
++	unsigned int ivsize = crypto_aead_ivsize(authenc);
++	u8 *vsrc;
++
++	srcp = sg_page(src);
++	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
++
++	sg_init_table(cipher, 2);
++	sg_set_buf(cipher, iv, ivsize);
++	authenc_chain(cipher, src, vsrc == iv + ivsize);
++
++	return crypto_authenc_verify(req, cipher, cryptlen + ivsize);
+ }
+ 
+ static int crypto_authenc_decrypt(struct aead_request *req)
+@@ -202,17 +293,23 @@ static int crypto_authenc_decrypt(struct aead_request *req)
+ 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ 	struct ablkcipher_request *abreq = aead_request_ctx(req);
++	unsigned int cryptlen = req->cryptlen;
++	unsigned int authsize = crypto_aead_authsize(authenc);
++	u8 *iv = req->iv;
+ 	int err;
+ 
+-	err = crypto_authenc_verify(req);
++	if (cryptlen < authsize)
++		return -EINVAL;
++	cryptlen -= authsize;
++
++	err = crypto_authenc_iverify(req, iv, cryptlen);
+ 	if (err)
+ 		return err;
+ 
+ 	ablkcipher_request_set_tfm(abreq, ctx->enc);
+ 	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+-					crypto_authenc_decrypt_done, req);
+-	ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
+-				     req->iv);
++					req->base.complete, req->base.data);
++	ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
+ 
+ 	return crypto_ablkcipher_decrypt(abreq);
+ }
+@@ -224,19 +321,13 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
+ 	struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	struct crypto_hash *auth;
+ 	struct crypto_ablkcipher *enc;
+-	unsigned int digestsize;
+ 	int err;
+ 
+ 	auth = crypto_spawn_hash(&ictx->auth);
+ 	if (IS_ERR(auth))
+ 		return PTR_ERR(auth);
+ 
+-	err = -EINVAL;
+-	digestsize = crypto_hash_digestsize(auth);
+-	if (ictx->authsize > digestsize)
+-		goto err_free_hash;
 -
--	printk(KERN_INFO "attempt to access beyond end of device\n");
--	printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n",
--			bdevname(bio->bi_bdev, b),
--			bio->bi_rw,
--			(unsigned long long)bio->bi_sector + bio_sectors(bio),
--			(long long)(bio->bi_bdev->bd_inode->i_size >> 9));
+-	enc = crypto_spawn_ablkcipher(&ictx->enc);
++	enc = crypto_spawn_skcipher(&ictx->enc);
+ 	err = PTR_ERR(enc);
+ 	if (IS_ERR(enc))
+ 		goto err_free_hash;
+@@ -246,9 +337,10 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
+ 	tfm->crt_aead.reqsize = max_t(unsigned int,
+ 				      (crypto_hash_alignmask(auth) &
+ 				       ~(crypto_tfm_ctx_alignment() - 1)) +
+-				      digestsize * 2,
+-				      sizeof(struct ablkcipher_request) +
+-				      crypto_ablkcipher_reqsize(enc));
++				      crypto_hash_digestsize(auth) * 2,
++				      sizeof(struct skcipher_givcrypt_request) +
++				      crypto_ablkcipher_reqsize(enc) +
++				      crypto_ablkcipher_ivsize(enc));
+ 
+ 	spin_lock_init(&ctx->auth_lock);
+ 
+@@ -269,75 +361,74 @@ static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm)
+ 
+ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
+ {
++	struct crypto_attr_type *algt;
+ 	struct crypto_instance *inst;
+ 	struct crypto_alg *auth;
+ 	struct crypto_alg *enc;
+ 	struct authenc_instance_ctx *ctx;
+-	unsigned int authsize;
+-	unsigned int enckeylen;
++	const char *enc_name;
+ 	int err;
+ 
+-	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
+-	if (err)
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
+ 		return ERR_PTR(err);
+ 
++	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
++		return ERR_PTR(-EINVAL);
++
+ 	auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
+ 			       CRYPTO_ALG_TYPE_HASH_MASK);
+ 	if (IS_ERR(auth))
+ 		return ERR_PTR(PTR_ERR(auth));
+ 
+-	err = crypto_attr_u32(tb[2], &authsize);
+-	inst = ERR_PTR(err);
+-	if (err)
+-		goto out_put_auth;
 -
--	set_bit(BIO_EOF, &bio->bi_flags);
--}
+-	enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER,
+-			      CRYPTO_ALG_TYPE_MASK);
+-	inst = ERR_PTR(PTR_ERR(enc));
+-	if (IS_ERR(enc))
++	enc_name = crypto_attr_alg_name(tb[2]);
++	err = PTR_ERR(enc_name);
++	if (IS_ERR(enc_name))
+ 		goto out_put_auth;
+ 
+-	err = crypto_attr_u32(tb[4], &enckeylen);
+-	if (err)
+-		goto out_put_enc;
 -
--#ifdef CONFIG_FAIL_MAKE_REQUEST
+ 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+ 	err = -ENOMEM;
+ 	if (!inst)
+-		goto out_put_enc;
 -
--static DECLARE_FAULT_ATTR(fail_make_request);
+-	err = -ENAMETOOLONG;
+-	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+-		     "authenc(%s,%u,%s,%u)", auth->cra_name, authsize,
+-		     enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
+-		goto err_free_inst;
 -
--static int __init setup_fail_make_request(char *str)
--{
--	return setup_fault_attr(&fail_make_request, str);
--}
--__setup("fail_make_request=", setup_fail_make_request);
+-	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+-		     "authenc(%s,%u,%s,%u)", auth->cra_driver_name,
+-		     authsize, enc->cra_driver_name, enckeylen) >=
+-	    CRYPTO_MAX_ALG_NAME)
+-		goto err_free_inst;
++		goto out_put_auth;
+ 
+ 	ctx = crypto_instance_ctx(inst);
+-	ctx->authsize = authsize;
+-	ctx->enckeylen = enckeylen;
+ 
+ 	err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
+ 	if (err)
+ 		goto err_free_inst;
+ 
+-	err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK);
++	crypto_set_skcipher_spawn(&ctx->enc, inst);
++	err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
++				   crypto_requires_sync(algt->type,
++							algt->mask));
+ 	if (err)
+ 		goto err_drop_auth;
+ 
+-	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
++	enc = crypto_skcipher_spawn_alg(&ctx->enc);
++
++	err = -ENAMETOOLONG;
++	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
++		     "authenc(%s,%s)", auth->cra_name, enc->cra_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		goto err_drop_enc;
++
++	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++		     "authenc(%s,%s)", auth->cra_driver_name,
++		     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
++		goto err_drop_enc;
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
++	inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
+ 	inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority;
+ 	inst->alg.cra_blocksize = enc->cra_blocksize;
+-	inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask);
++	inst->alg.cra_alignmask = auth->cra_alignmask | enc->cra_alignmask;
+ 	inst->alg.cra_type = &crypto_aead_type;
+ 
+-	inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize;
+-	inst->alg.cra_aead.authsize = authsize;
++	inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
++	inst->alg.cra_aead.maxauthsize = auth->cra_type == &crypto_hash_type ?
++					 auth->cra_hash.digestsize :
++					 auth->cra_digest.dia_digestsize;
+ 
+ 	inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
+ 
+@@ -347,18 +438,19 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
+ 	inst->alg.cra_aead.setkey = crypto_authenc_setkey;
+ 	inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
+ 	inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
++	inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt;
+ 
+ out:
+-	crypto_mod_put(enc);
+-out_put_auth:
+ 	crypto_mod_put(auth);
+ 	return inst;
+ 
++err_drop_enc:
++	crypto_drop_skcipher(&ctx->enc);
+ err_drop_auth:
+ 	crypto_drop_spawn(&ctx->auth);
+ err_free_inst:
+ 	kfree(inst);
+-out_put_enc:
++out_put_auth:
+ 	inst = ERR_PTR(err);
+ 	goto out;
+ }
+@@ -367,7 +459,7 @@ static void crypto_authenc_free(struct crypto_instance *inst)
+ {
+ 	struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst);
+ 
+-	crypto_drop_spawn(&ctx->enc);
++	crypto_drop_skcipher(&ctx->enc);
+ 	crypto_drop_spawn(&ctx->auth);
+ 	kfree(inst);
+ }
+diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
+index f6c67f9..4a7e65c 100644
+--- a/crypto/blkcipher.c
++++ b/crypto/blkcipher.c
+@@ -14,7 +14,8 @@
+  *
+  */
+ 
+-#include <linux/crypto.h>
++#include <crypto/internal/skcipher.h>
++#include <crypto/scatterwalk.h>
+ #include <linux/errno.h>
+ #include <linux/hardirq.h>
+ #include <linux/kernel.h>
+@@ -25,7 +26,6 @@
+ #include <linux/string.h>
+ 
+ #include "internal.h"
+-#include "scatterwalk.h"
+ 
+ enum {
+ 	BLKCIPHER_WALK_PHYS = 1 << 0,
+@@ -433,9 +433,8 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
+ 	struct blkcipher_alg *cipher = &alg->cra_blkcipher;
+ 	unsigned int len = alg->cra_ctxsize;
+ 
+-	type ^= CRYPTO_ALG_ASYNC;
+-	mask &= CRYPTO_ALG_ASYNC;
+-	if ((type & mask) && cipher->ivsize) {
++	if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK &&
++	    cipher->ivsize) {
+ 		len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
+ 		len += cipher->ivsize;
+ 	}
+@@ -451,6 +450,11 @@ static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
+ 	crt->setkey = async_setkey;
+ 	crt->encrypt = async_encrypt;
+ 	crt->decrypt = async_decrypt;
++	if (!alg->ivsize) {
++		crt->givencrypt = skcipher_null_givencrypt;
++		crt->givdecrypt = skcipher_null_givdecrypt;
++	}
++	crt->base = __crypto_ablkcipher_cast(tfm);
+ 	crt->ivsize = alg->ivsize;
+ 
+ 	return 0;
+@@ -482,9 +486,7 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+ 	if (alg->ivsize > PAGE_SIZE / 8)
+ 		return -EINVAL;
+ 
+-	type ^= CRYPTO_ALG_ASYNC;
+-	mask &= CRYPTO_ALG_ASYNC;
+-	if (type & mask)
++	if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK)
+ 		return crypto_init_blkcipher_ops_sync(tfm);
+ 	else
+ 		return crypto_init_blkcipher_ops_async(tfm);
+@@ -499,6 +501,8 @@ static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
+ 	seq_printf(m, "min keysize  : %u\n", alg->cra_blkcipher.min_keysize);
+ 	seq_printf(m, "max keysize  : %u\n", alg->cra_blkcipher.max_keysize);
+ 	seq_printf(m, "ivsize       : %u\n", alg->cra_blkcipher.ivsize);
++	seq_printf(m, "geniv        : %s\n", alg->cra_blkcipher.geniv ?:
++					     "<default>");
+ }
+ 
+ const struct crypto_type crypto_blkcipher_type = {
+@@ -510,5 +514,187 @@ const struct crypto_type crypto_blkcipher_type = {
+ };
+ EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
+ 
++static int crypto_grab_nivcipher(struct crypto_skcipher_spawn *spawn,
++				const char *name, u32 type, u32 mask)
++{
++	struct crypto_alg *alg;
++	int err;
++
++	type = crypto_skcipher_type(type);
++	mask = crypto_skcipher_mask(mask) | CRYPTO_ALG_GENIV;
++
++	alg = crypto_alg_mod_lookup(name, type, mask);
++	if (IS_ERR(alg))
++		return PTR_ERR(alg);
++
++	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
++	crypto_mod_put(alg);
++	return err;
++}
++
++struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl,
++					     struct rtattr **tb, u32 type,
++					     u32 mask)
++{
++	struct {
++		int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
++			      unsigned int keylen);
++		int (*encrypt)(struct ablkcipher_request *req);
++		int (*decrypt)(struct ablkcipher_request *req);
++
++		unsigned int min_keysize;
++		unsigned int max_keysize;
++		unsigned int ivsize;
++
++		const char *geniv;
++	} balg;
++	const char *name;
++	struct crypto_skcipher_spawn *spawn;
++	struct crypto_attr_type *algt;
++	struct crypto_instance *inst;
++	struct crypto_alg *alg;
++	int err;
++
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
++		return ERR_PTR(err);
++
++	if ((algt->type ^ (CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV)) &
++	    algt->mask)
++		return ERR_PTR(-EINVAL);
++
++	name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(name);
++	if (IS_ERR(name))
++		return ERR_PTR(err);
++
++	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
++	if (!inst)
++		return ERR_PTR(-ENOMEM);
++
++	spawn = crypto_instance_ctx(inst);
++
++	/* Ignore async algorithms if necessary. */
++	mask |= crypto_requires_sync(algt->type, algt->mask);
++
++	crypto_set_skcipher_spawn(spawn, inst);
++	err = crypto_grab_nivcipher(spawn, name, type, mask);
++	if (err)
++		goto err_free_inst;
++
++	alg = crypto_skcipher_spawn_alg(spawn);
++
++	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
++	    CRYPTO_ALG_TYPE_BLKCIPHER) {
++		balg.ivsize = alg->cra_blkcipher.ivsize;
++		balg.min_keysize = alg->cra_blkcipher.min_keysize;
++		balg.max_keysize = alg->cra_blkcipher.max_keysize;
++
++		balg.setkey = async_setkey;
++		balg.encrypt = async_encrypt;
++		balg.decrypt = async_decrypt;
++
++		balg.geniv = alg->cra_blkcipher.geniv;
++	} else {
++		balg.ivsize = alg->cra_ablkcipher.ivsize;
++		balg.min_keysize = alg->cra_ablkcipher.min_keysize;
++		balg.max_keysize = alg->cra_ablkcipher.max_keysize;
++
++		balg.setkey = alg->cra_ablkcipher.setkey;
++		balg.encrypt = alg->cra_ablkcipher.encrypt;
++		balg.decrypt = alg->cra_ablkcipher.decrypt;
++
++		balg.geniv = alg->cra_ablkcipher.geniv;
++	}
++
++	err = -EINVAL;
++	if (!balg.ivsize)
++		goto err_drop_alg;
++
++	/*
++	 * This is only true if we're constructing an algorithm with its
++	 * default IV generator.  For the default generator we elide the
++	 * template name and double-check the IV generator.
++	 */
++	if (algt->mask & CRYPTO_ALG_GENIV) {
++		if (!balg.geniv)
++			balg.geniv = crypto_default_geniv(alg);
++		err = -EAGAIN;
++		if (strcmp(tmpl->name, balg.geniv))
++			goto err_drop_alg;
++
++		memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
++		memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
++		       CRYPTO_MAX_ALG_NAME);
++	} else {
++		err = -ENAMETOOLONG;
++		if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
++			     "%s(%s)", tmpl->name, alg->cra_name) >=
++		    CRYPTO_MAX_ALG_NAME)
++			goto err_drop_alg;
++		if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++			     "%s(%s)", tmpl->name, alg->cra_driver_name) >=
++		    CRYPTO_MAX_ALG_NAME)
++			goto err_drop_alg;
++	}
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV;
++	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = alg->cra_blocksize;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_givcipher_type;
++
++	inst->alg.cra_ablkcipher.ivsize = balg.ivsize;
++	inst->alg.cra_ablkcipher.min_keysize = balg.min_keysize;
++	inst->alg.cra_ablkcipher.max_keysize = balg.max_keysize;
++	inst->alg.cra_ablkcipher.geniv = balg.geniv;
++
++	inst->alg.cra_ablkcipher.setkey = balg.setkey;
++	inst->alg.cra_ablkcipher.encrypt = balg.encrypt;
++	inst->alg.cra_ablkcipher.decrypt = balg.decrypt;
++
++out:
++	return inst;
++
++err_drop_alg:
++	crypto_drop_skcipher(spawn);
++err_free_inst:
++	kfree(inst);
++	inst = ERR_PTR(err);
++	goto out;
++}
++EXPORT_SYMBOL_GPL(skcipher_geniv_alloc);
++
++void skcipher_geniv_free(struct crypto_instance *inst)
++{
++	crypto_drop_skcipher(crypto_instance_ctx(inst));
++	kfree(inst);
++}
++EXPORT_SYMBOL_GPL(skcipher_geniv_free);
++
++int skcipher_geniv_init(struct crypto_tfm *tfm)
++{
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_ablkcipher *cipher;
++
++	cipher = crypto_spawn_skcipher(crypto_instance_ctx(inst));
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	tfm->crt_ablkcipher.base = cipher;
++	tfm->crt_ablkcipher.reqsize += crypto_ablkcipher_reqsize(cipher);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(skcipher_geniv_init);
++
++void skcipher_geniv_exit(struct crypto_tfm *tfm)
++{
++	crypto_free_ablkcipher(tfm->crt_ablkcipher.base);
++}
++EXPORT_SYMBOL_GPL(skcipher_geniv_exit);
++
+ MODULE_LICENSE("GPL");
+ MODULE_DESCRIPTION("Generic block chaining cipher type");
+diff --git a/crypto/camellia.c b/crypto/camellia.c
+index 6877ecf..493fee7 100644
+--- a/crypto/camellia.c
++++ b/crypto/camellia.c
+@@ -36,176 +36,6 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ 
 -
--static int should_fail_request(struct bio *bio)
--{
--	if ((bio->bi_bdev->bd_disk->flags & GENHD_FL_FAIL) ||
--	    (bio->bi_bdev->bd_part && bio->bi_bdev->bd_part->make_it_fail))
--		return should_fail(&fail_make_request, bio->bi_size);
+-#define CAMELLIA_MIN_KEY_SIZE        16
+-#define CAMELLIA_MAX_KEY_SIZE        32
+-#define CAMELLIA_BLOCK_SIZE 16
+-#define CAMELLIA_TABLE_BYTE_LEN 272
+-#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
 -
--	return 0;
--}
+-typedef u32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
 -
--static int __init fail_make_request_debugfs(void)
--{
--	return init_fault_attr_dentries(&fail_make_request,
--					"fail_make_request");
--}
 -
--late_initcall(fail_make_request_debugfs);
+-/* key constants */
 -
--#else /* CONFIG_FAIL_MAKE_REQUEST */
+-#define CAMELLIA_SIGMA1L (0xA09E667FL)
+-#define CAMELLIA_SIGMA1R (0x3BCC908BL)
+-#define CAMELLIA_SIGMA2L (0xB67AE858L)
+-#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
+-#define CAMELLIA_SIGMA3L (0xC6EF372FL)
+-#define CAMELLIA_SIGMA3R (0xE94F82BEL)
+-#define CAMELLIA_SIGMA4L (0x54FF53A5L)
+-#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
+-#define CAMELLIA_SIGMA5L (0x10E527FAL)
+-#define CAMELLIA_SIGMA5R (0xDE682D1DL)
+-#define CAMELLIA_SIGMA6L (0xB05688C2L)
+-#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
 -
--static inline int should_fail_request(struct bio *bio)
--{
--	return 0;
--}
+-struct camellia_ctx {
+-	int key_length;
+-	KEY_TABLE_TYPE key_table;
+-};
 -
--#endif /* CONFIG_FAIL_MAKE_REQUEST */
 -
 -/*
-- * Check whether this bio extends beyond the end of the device.
-- */
--static inline int bio_check_eod(struct bio *bio, unsigned int nr_sectors)
--{
--	sector_t maxsector;
--
--	if (!nr_sectors)
--		return 0;
--
--	/* Test device or partition size, when known. */
--	maxsector = bio->bi_bdev->bd_inode->i_size >> 9;
--	if (maxsector) {
--		sector_t sector = bio->bi_sector;
--
--		if (maxsector < nr_sectors || maxsector - nr_sectors < sector) {
--			/*
--			 * This may well happen - the kernel calls bread()
--			 * without checking the size of the device, e.g., when
--			 * mounting a device.
--			 */
--			handle_bad_sector(bio);
--			return 1;
--		}
--	}
--
--	return 0;
--}
--
--/**
-- * generic_make_request: hand a buffer to its device driver for I/O
-- * @bio:  The bio describing the location in memory and on the device.
-- *
-- * generic_make_request() is used to make I/O requests of block
-- * devices. It is passed a &struct bio, which describes the I/O that needs
-- * to be done.
-- *
-- * generic_make_request() does not return any status.  The
-- * success/failure status of the request, along with notification of
-- * completion, is delivered asynchronously through the bio->bi_end_io
-- * function described (one day) else where.
-- *
-- * The caller of generic_make_request must make sure that bi_io_vec
-- * are set to describe the memory buffer, and that bi_dev and bi_sector are
-- * set to describe the device address, and the
-- * bi_end_io and optionally bi_private are set to describe how
-- * completion notification should be signaled.
-- *
-- * generic_make_request and the drivers it calls may use bi_next if this
-- * bio happens to be merged with someone else, and may change bi_dev and
-- * bi_sector for remaps as it sees fit.  So the values of these fields
-- * should NOT be depended on after the call to generic_make_request.
+- *  macros
 - */
--static inline void __generic_make_request(struct bio *bio)
--{
--	struct request_queue *q;
--	sector_t old_sector;
--	int ret, nr_sectors = bio_sectors(bio);
--	dev_t old_dev;
--	int err = -EIO;
 -
--	might_sleep();
 -
--	if (bio_check_eod(bio, nr_sectors))
--		goto end_io;
+-# define GETU32(pt) (((u32)(pt)[0] << 24)	\
+-		     ^ ((u32)(pt)[1] << 16)	\
+-		     ^ ((u32)(pt)[2] <<  8)	\
+-		     ^ ((u32)(pt)[3]))
 -
--	/*
--	 * Resolve the mapping until finished. (drivers are
--	 * still free to implement/resolve their own stacking
--	 * by explicitly returning 0)
--	 *
--	 * NOTE: we don't repeat the blk_size check for each new device.
--	 * Stacking drivers are expected to know what they are doing.
--	 */
--	old_sector = -1;
--	old_dev = 0;
--	do {
--		char b[BDEVNAME_SIZE];
+-#define COPY4WORD(dst, src)			\
+-    do {					\
+-	(dst)[0]=(src)[0];			\
+-	(dst)[1]=(src)[1];			\
+-	(dst)[2]=(src)[2];			\
+-	(dst)[3]=(src)[3];			\
+-    }while(0)
 -
--		q = bdev_get_queue(bio->bi_bdev);
--		if (!q) {
--			printk(KERN_ERR
--			       "generic_make_request: Trying to access "
--				"nonexistent block-device %s (%Lu)\n",
--				bdevname(bio->bi_bdev, b),
--				(long long) bio->bi_sector);
--end_io:
--			bio_endio(bio, err);
--			break;
--		}
+-#define SWAP4WORD(word)				\
+-    do {					\
+-	CAMELLIA_SWAP4((word)[0]);		\
+-	CAMELLIA_SWAP4((word)[1]);		\
+-	CAMELLIA_SWAP4((word)[2]);		\
+-	CAMELLIA_SWAP4((word)[3]);		\
+-    }while(0)
 -
--		if (unlikely(nr_sectors > q->max_hw_sectors)) {
--			printk("bio too big device %s (%u > %u)\n", 
--				bdevname(bio->bi_bdev, b),
--				bio_sectors(bio),
--				q->max_hw_sectors);
--			goto end_io;
--		}
+-#define XOR4WORD(a, b)/* a = a ^ b */		\
+-    do {					\
+-	(a)[0]^=(b)[0];				\
+-	(a)[1]^=(b)[1];				\
+-	(a)[2]^=(b)[2];				\
+-	(a)[3]^=(b)[3];				\
+-    }while(0)
 -
--		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
--			goto end_io;
+-#define XOR4WORD2(a, b, c)/* a = b ^ c */	\
+-    do {					\
+-	(a)[0]=(b)[0]^(c)[0];			\
+-	(a)[1]=(b)[1]^(c)[1];			\
+-	(a)[2]=(b)[2]^(c)[2];			\
+-	(a)[3]=(b)[3]^(c)[3];			\
+-    }while(0)
 -
--		if (should_fail_request(bio))
--			goto end_io;
+-#define CAMELLIA_SUBKEY_L(INDEX) (subkey[(INDEX)*2])
+-#define CAMELLIA_SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
 -
--		/*
--		 * If this device has partitions, remap block n
--		 * of partition p to block n+start(p) of the disk.
--		 */
--		blk_partition_remap(bio);
+-/* rotation right shift 1byte */
+-#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
+-/* rotation left shift 1bit */
+-#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
+-/* rotation left shift 1byte */
+-#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
 -
--		if (old_sector != -1)
--			blk_add_trace_remap(q, bio, old_dev, bio->bi_sector,
--					    old_sector);
+-#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)	\
+-    do {						\
+-	w0 = ll;					\
+-	ll = (ll << bits) + (lr >> (32 - bits));	\
+-	lr = (lr << bits) + (rl >> (32 - bits));	\
+-	rl = (rl << bits) + (rr >> (32 - bits));	\
+-	rr = (rr << bits) + (w0 >> (32 - bits));	\
+-    } while(0)
 -
--		blk_add_trace_bio(q, bio, BLK_TA_QUEUE);
+-#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)	\
+-    do {						\
+-	w0 = ll;					\
+-	w1 = lr;					\
+-	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
+-	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
+-	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
+-	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
+-    } while(0)
 -
--		old_sector = bio->bi_sector;
--		old_dev = bio->bi_bdev->bd_dev;
+-#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
+-#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
+-#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
+-#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
 -
--		if (bio_check_eod(bio, nr_sectors))
--			goto end_io;
--		if (bio_empty_barrier(bio) && !q->prepare_flush_fn) {
--			err = -EOPNOTSUPP;
--			goto end_io;
--		}
+-#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+-    do {							\
+-	il = xl ^ kl;						\
+-	ir = xr ^ kr;						\
+-	t0 = il >> 16;						\
+-	t1 = ir >> 16;						\
+-	yl = CAMELLIA_SP1110(ir & 0xff)				\
+-	    ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)			\
+-	    ^ CAMELLIA_SP3033(t1 & 0xff)			\
+-	    ^ CAMELLIA_SP4404((ir >> 8) & 0xff);		\
+-	yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)			\
+-	    ^ CAMELLIA_SP0222(t0 & 0xff)			\
+-	    ^ CAMELLIA_SP3033((il >> 8) & 0xff)			\
+-	    ^ CAMELLIA_SP4404(il & 0xff);			\
+-	yl ^= yr;						\
+-	yr = CAMELLIA_RR8(yr);					\
+-	yr ^= yl;						\
+-    } while(0)
 -
--		ret = q->make_request_fn(q, bio);
--	} while (ret);
--}
 -
 -/*
-- * We only want one ->make_request_fn to be active at a time,
-- * else stack usage with stacked devices could be a problem.
-- * So use current->bio_{list,tail} to keep a list of requests
-- * submited by a make_request_fn function.
-- * current->bio_tail is also used as a flag to say if
-- * generic_make_request is currently active in this task or not.
-- * If it is NULL, then no make_request is active.  If it is non-NULL,
-- * then a make_request is active, and new requests should be added
-- * at the tail
+- * for speed up
+- *
 - */
--void generic_make_request(struct bio *bio)
--{
--	if (current->bio_tail) {
--		/* make_request is active */
--		*(current->bio_tail) = bio;
--		bio->bi_next = NULL;
--		current->bio_tail = &bio->bi_next;
--		return;
--	}
--	/* following loop may be a bit non-obvious, and so deserves some
--	 * explanation.
--	 * Before entering the loop, bio->bi_next is NULL (as all callers
--	 * ensure that) so we have a list with a single bio.
--	 * We pretend that we have just taken it off a longer list, so
--	 * we assign bio_list to the next (which is NULL) and bio_tail
--	 * to &bio_list, thus initialising the bio_list of new bios to be
--	 * added.  __generic_make_request may indeed add some more bios
--	 * through a recursive call to generic_make_request.  If it
--	 * did, we find a non-NULL value in bio_list and re-enter the loop
--	 * from the top.  In this case we really did just take the bio
--	 * of the top of the list (no pretending) and so fixup bio_list and
--	 * bio_tail or bi_next, and call into __generic_make_request again.
--	 *
--	 * The loop was structured like this to make only one call to
--	 * __generic_make_request (which is important as it is large and
--	 * inlined) and to keep the structure simple.
--	 */
--	BUG_ON(bio->bi_next);
--	do {
--		current->bio_list = bio->bi_next;
--		if (bio->bi_next == NULL)
--			current->bio_tail = &current->bio_list;
--		else
--			bio->bi_next = NULL;
--		__generic_make_request(bio);
--		bio = current->bio_list;
--	} while (bio);
--	current->bio_tail = NULL; /* deactivate */
--}
+-#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
+-    do {								\
+-	t0 = kll;							\
+-	t2 = krr;							\
+-	t0 &= ll;							\
+-	t2 |= rr;							\
+-	rl ^= t2;							\
+-	lr ^= CAMELLIA_RL1(t0);						\
+-	t3 = krl;							\
+-	t1 = klr;							\
+-	t3 &= rl;							\
+-	t1 |= lr;							\
+-	ll ^= t1;							\
+-	rr ^= CAMELLIA_RL1(t3);						\
+-    } while(0)
 -
--EXPORT_SYMBOL(generic_make_request);
+-#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
+-    do {								\
+-	ir =  CAMELLIA_SP1110(xr & 0xff);				\
+-	il =  CAMELLIA_SP1110((xl>>24) & 0xff);				\
+-	ir ^= CAMELLIA_SP0222((xr>>24) & 0xff);				\
+-	il ^= CAMELLIA_SP0222((xl>>16) & 0xff);				\
+-	ir ^= CAMELLIA_SP3033((xr>>16) & 0xff);				\
+-	il ^= CAMELLIA_SP3033((xl>>8) & 0xff);				\
+-	ir ^= CAMELLIA_SP4404((xr>>8) & 0xff);				\
+-	il ^= CAMELLIA_SP4404(xl & 0xff);				\
+-	il ^= kl;							\
+-	ir ^= il ^ kr;							\
+-	yl ^= ir;							\
+-	yr ^= CAMELLIA_RR8(il) ^ ir;					\
+-    } while(0)
 -
 -/**
-- * submit_bio: submit a bio to the block device layer for I/O
-- * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead)
-- * @bio: The &struct bio which describes the I/O
-- *
-- * submit_bio() is very similar in purpose to generic_make_request(), and
-- * uses that function to do most of the work. Both are fairly rough
-- * interfaces, @bio must be presetup and ready for I/O.
-- *
+- * Stuff related to the Camellia key schedule
 - */
--void submit_bio(int rw, struct bio *bio)
--{
--	int count = bio_sectors(bio);
--
--	bio->bi_rw |= rw;
--
--	/*
--	 * If it's a regular read/write or a barrier with data attached,
--	 * go through the normal accounting stuff before submission.
--	 */
--	if (!bio_empty_barrier(bio)) {
--
--		BIO_BUG_ON(!bio->bi_size);
--		BIO_BUG_ON(!bio->bi_io_vec);
--
--		if (rw & WRITE) {
--			count_vm_events(PGPGOUT, count);
--		} else {
--			task_io_account_read(bio->bi_size);
--			count_vm_events(PGPGIN, count);
--		}
--
--		if (unlikely(block_dump)) {
--			char b[BDEVNAME_SIZE];
--			printk(KERN_DEBUG "%s(%d): %s block %Lu on %s\n",
--			current->comm, task_pid_nr(current),
--				(rw & WRITE) ? "WRITE" : "READ",
--				(unsigned long long)bio->bi_sector,
--				bdevname(bio->bi_bdev,b));
--		}
--	}
--
--	generic_make_request(bio);
--}
--
--EXPORT_SYMBOL(submit_bio);
--
--static void blk_recalc_rq_sectors(struct request *rq, int nsect)
--{
--	if (blk_fs_request(rq)) {
--		rq->hard_sector += nsect;
--		rq->hard_nr_sectors -= nsect;
--
--		/*
--		 * Move the I/O submission pointers ahead if required.
--		 */
--		if ((rq->nr_sectors >= rq->hard_nr_sectors) &&
--		    (rq->sector <= rq->hard_sector)) {
--			rq->sector = rq->hard_sector;
--			rq->nr_sectors = rq->hard_nr_sectors;
--			rq->hard_cur_sectors = bio_cur_sectors(rq->bio);
--			rq->current_nr_sectors = rq->hard_cur_sectors;
--			rq->buffer = bio_data(rq->bio);
--		}
--
--		/*
--		 * if total number of sectors is less than the first segment
--		 * size, something has gone terribly wrong
--		 */
--		if (rq->nr_sectors < rq->current_nr_sectors) {
--			printk("blk: request botched\n");
--			rq->nr_sectors = rq->current_nr_sectors;
--		}
--	}
--}
--
--static int __end_that_request_first(struct request *req, int uptodate,
--				    int nr_bytes)
--{
--	int total_bytes, bio_nbytes, error, next_idx = 0;
--	struct bio *bio;
--
--	blk_add_trace_rq(req->q, req, BLK_TA_COMPLETE);
+-#define SUBL(x) subL[(x)]
+-#define SUBR(x) subR[(x)]
 -
--	/*
--	 * extend uptodate bool to allow < 0 value to be direct io error
--	 */
--	error = 0;
--	if (end_io_error(uptodate))
--		error = !uptodate ? -EIO : uptodate;
 -
--	/*
--	 * for a REQ_BLOCK_PC request, we want to carry any eventual
--	 * sense key with us all the way through
+ static const u32 camellia_sp1110[256] = {
+ 	0x70707000,0x82828200,0x2c2c2c00,0xececec00,
+ 	0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
+@@ -475,67 +305,348 @@ static const u32 camellia_sp4404[256] = {
+ };
+ 
+ 
++#define CAMELLIA_MIN_KEY_SIZE        16
++#define CAMELLIA_MAX_KEY_SIZE        32
++#define CAMELLIA_BLOCK_SIZE          16
++#define CAMELLIA_TABLE_BYTE_LEN     272
++
++/*
++ * NB: L and R below stand for 'left' and 'right' as in written numbers.
++ * That is, in (xxxL,xxxR) pair xxxL holds most significant digits,
++ * _not_ least significant ones!
++ */
++
++
++/* key constants */
++
++#define CAMELLIA_SIGMA1L (0xA09E667FL)
++#define CAMELLIA_SIGMA1R (0x3BCC908BL)
++#define CAMELLIA_SIGMA2L (0xB67AE858L)
++#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
++#define CAMELLIA_SIGMA3L (0xC6EF372FL)
++#define CAMELLIA_SIGMA3R (0xE94F82BEL)
++#define CAMELLIA_SIGMA4L (0x54FF53A5L)
++#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
++#define CAMELLIA_SIGMA5L (0x10E527FAL)
++#define CAMELLIA_SIGMA5R (0xDE682D1DL)
++#define CAMELLIA_SIGMA6L (0xB05688C2L)
++#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
++
++/*
++ *  macros
++ */
++#define GETU32(v, pt) \
++    do { \
++	/* latest breed of gcc is clever enough to use move */ \
++	memcpy(&(v), (pt), 4); \
++	(v) = be32_to_cpu(v); \
++    } while(0)
++
++/* rotation right shift 1byte */
++#define ROR8(x) (((x) >> 8) + ((x) << 24))
++/* rotation left shift 1bit */
++#define ROL1(x) (((x) << 1) + ((x) >> 31))
++/* rotation left shift 1byte */
++#define ROL8(x) (((x) << 8) + ((x) >> 24))
++
++#define ROLDQ(ll, lr, rl, rr, w0, w1, bits)		\
++    do {						\
++	w0 = ll;					\
++	ll = (ll << bits) + (lr >> (32 - bits));	\
++	lr = (lr << bits) + (rl >> (32 - bits));	\
++	rl = (rl << bits) + (rr >> (32 - bits));	\
++	rr = (rr << bits) + (w0 >> (32 - bits));	\
++    } while(0)
++
++#define ROLDQo32(ll, lr, rl, rr, w0, w1, bits)		\
++    do {						\
++	w0 = ll;					\
++	w1 = lr;					\
++	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
++	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
++	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
++	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
++    } while(0)
++
++#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
++    do {							\
++	il = xl ^ kl;						\
++	ir = xr ^ kr;						\
++	t0 = il >> 16;						\
++	t1 = ir >> 16;						\
++	yl = camellia_sp1110[(u8)(ir     )]			\
++	   ^ camellia_sp0222[    (t1 >> 8)]			\
++	   ^ camellia_sp3033[(u8)(t1     )]			\
++	   ^ camellia_sp4404[(u8)(ir >> 8)];			\
++	yr = camellia_sp1110[    (t0 >> 8)]			\
++	   ^ camellia_sp0222[(u8)(t0     )]			\
++	   ^ camellia_sp3033[(u8)(il >> 8)]			\
++	   ^ camellia_sp4404[(u8)(il     )];			\
++	yl ^= yr;						\
++	yr = ROR8(yr);						\
++	yr ^= yl;						\
++    } while(0)
++
++#define SUBKEY_L(INDEX) (subkey[(INDEX)*2])
++#define SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
++
++static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
++{
++	u32 dw, tl, tr;
++	u32 kw4l, kw4r;
++	int i;
++
++	/* absorb kw2 to other subkeys */
++	/* round 2 */
++	subL[3] ^= subL[1]; subR[3] ^= subR[1];
++	/* round 4 */
++	subL[5] ^= subL[1]; subR[5] ^= subR[1];
++	/* round 6 */
++	subL[7] ^= subL[1]; subR[7] ^= subR[1];
++	subL[1] ^= subR[1] & ~subR[9];
++	dw = subL[1] & subL[9],
++		subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */
++	/* round 8 */
++	subL[11] ^= subL[1]; subR[11] ^= subR[1];
++	/* round 10 */
++	subL[13] ^= subL[1]; subR[13] ^= subR[1];
++	/* round 12 */
++	subL[15] ^= subL[1]; subR[15] ^= subR[1];
++	subL[1] ^= subR[1] & ~subR[17];
++	dw = subL[1] & subL[17],
++		subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */
++	/* round 14 */
++	subL[19] ^= subL[1]; subR[19] ^= subR[1];
++	/* round 16 */
++	subL[21] ^= subL[1]; subR[21] ^= subR[1];
++	/* round 18 */
++	subL[23] ^= subL[1]; subR[23] ^= subR[1];
++	if (max == 24) {
++		/* kw3 */
++		subL[24] ^= subL[1]; subR[24] ^= subR[1];
++
++	/* absorb kw4 to other subkeys */
++		kw4l = subL[25]; kw4r = subR[25];
++	} else {
++		subL[1] ^= subR[1] & ~subR[25];
++		dw = subL[1] & subL[25],
++			subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */
++		/* round 20 */
++		subL[27] ^= subL[1]; subR[27] ^= subR[1];
++		/* round 22 */
++		subL[29] ^= subL[1]; subR[29] ^= subR[1];
++		/* round 24 */
++		subL[31] ^= subL[1]; subR[31] ^= subR[1];
++		/* kw3 */
++		subL[32] ^= subL[1]; subR[32] ^= subR[1];
++
++	/* absorb kw4 to other subkeys */
++		kw4l = subL[33]; kw4r = subR[33];
++		/* round 23 */
++		subL[30] ^= kw4l; subR[30] ^= kw4r;
++		/* round 21 */
++		subL[28] ^= kw4l; subR[28] ^= kw4r;
++		/* round 19 */
++		subL[26] ^= kw4l; subR[26] ^= kw4r;
++		kw4l ^= kw4r & ~subR[24];
++		dw = kw4l & subL[24],
++			kw4r ^= ROL1(dw); /* modified for FL(kl5) */
++	}
++	/* round 17 */
++	subL[22] ^= kw4l; subR[22] ^= kw4r;
++	/* round 15 */
++	subL[20] ^= kw4l; subR[20] ^= kw4r;
++	/* round 13 */
++	subL[18] ^= kw4l; subR[18] ^= kw4r;
++	kw4l ^= kw4r & ~subR[16];
++	dw = kw4l & subL[16],
++		kw4r ^= ROL1(dw); /* modified for FL(kl3) */
++	/* round 11 */
++	subL[14] ^= kw4l; subR[14] ^= kw4r;
++	/* round 9 */
++	subL[12] ^= kw4l; subR[12] ^= kw4r;
++	/* round 7 */
++	subL[10] ^= kw4l; subR[10] ^= kw4r;
++	kw4l ^= kw4r & ~subR[8];
++	dw = kw4l & subL[8],
++		kw4r ^= ROL1(dw); /* modified for FL(kl1) */
++	/* round 5 */
++	subL[6] ^= kw4l; subR[6] ^= kw4r;
++	/* round 3 */
++	subL[4] ^= kw4l; subR[4] ^= kw4r;
++	/* round 1 */
++	subL[2] ^= kw4l; subR[2] ^= kw4r;
++	/* kw1 */
++	subL[0] ^= kw4l; subR[0] ^= kw4r;
++
++	/* key XOR is end of F-function */
++	SUBKEY_L(0) = subL[0] ^ subL[2];/* kw1 */
++	SUBKEY_R(0) = subR[0] ^ subR[2];
++	SUBKEY_L(2) = subL[3];       /* round 1 */
++	SUBKEY_R(2) = subR[3];
++	SUBKEY_L(3) = subL[2] ^ subL[4]; /* round 2 */
++	SUBKEY_R(3) = subR[2] ^ subR[4];
++	SUBKEY_L(4) = subL[3] ^ subL[5]; /* round 3 */
++	SUBKEY_R(4) = subR[3] ^ subR[5];
++	SUBKEY_L(5) = subL[4] ^ subL[6]; /* round 4 */
++	SUBKEY_R(5) = subR[4] ^ subR[6];
++	SUBKEY_L(6) = subL[5] ^ subL[7]; /* round 5 */
++	SUBKEY_R(6) = subR[5] ^ subR[7];
++	tl = subL[10] ^ (subR[10] & ~subR[8]);
++	dw = tl & subL[8],  /* FL(kl1) */
++		tr = subR[10] ^ ROL1(dw);
++	SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */
++	SUBKEY_R(7) = subR[6] ^ tr;
++	SUBKEY_L(8) = subL[8];       /* FL(kl1) */
++	SUBKEY_R(8) = subR[8];
++	SUBKEY_L(9) = subL[9];       /* FLinv(kl2) */
++	SUBKEY_R(9) = subR[9];
++	tl = subL[7] ^ (subR[7] & ~subR[9]);
++	dw = tl & subL[9],  /* FLinv(kl2) */
++		tr = subR[7] ^ ROL1(dw);
++	SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */
++	SUBKEY_R(10) = tr ^ subR[11];
++	SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */
++	SUBKEY_R(11) = subR[10] ^ subR[12];
++	SUBKEY_L(12) = subL[11] ^ subL[13]; /* round 9 */
++	SUBKEY_R(12) = subR[11] ^ subR[13];
++	SUBKEY_L(13) = subL[12] ^ subL[14]; /* round 10 */
++	SUBKEY_R(13) = subR[12] ^ subR[14];
++	SUBKEY_L(14) = subL[13] ^ subL[15]; /* round 11 */
++	SUBKEY_R(14) = subR[13] ^ subR[15];
++	tl = subL[18] ^ (subR[18] & ~subR[16]);
++	dw = tl & subL[16], /* FL(kl3) */
++		tr = subR[18] ^ ROL1(dw);
++	SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */
++	SUBKEY_R(15) = subR[14] ^ tr;
++	SUBKEY_L(16) = subL[16];     /* FL(kl3) */
++	SUBKEY_R(16) = subR[16];
++	SUBKEY_L(17) = subL[17];     /* FLinv(kl4) */
++	SUBKEY_R(17) = subR[17];
++	tl = subL[15] ^ (subR[15] & ~subR[17]);
++	dw = tl & subL[17], /* FLinv(kl4) */
++		tr = subR[15] ^ ROL1(dw);
++	SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */
++	SUBKEY_R(18) = tr ^ subR[19];
++	SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */
++	SUBKEY_R(19) = subR[18] ^ subR[20];
++	SUBKEY_L(20) = subL[19] ^ subL[21]; /* round 15 */
++	SUBKEY_R(20) = subR[19] ^ subR[21];
++	SUBKEY_L(21) = subL[20] ^ subL[22]; /* round 16 */
++	SUBKEY_R(21) = subR[20] ^ subR[22];
++	SUBKEY_L(22) = subL[21] ^ subL[23]; /* round 17 */
++	SUBKEY_R(22) = subR[21] ^ subR[23];
++	if (max == 24) {
++		SUBKEY_L(23) = subL[22];     /* round 18 */
++		SUBKEY_R(23) = subR[22];
++		SUBKEY_L(24) = subL[24] ^ subL[23]; /* kw3 */
++		SUBKEY_R(24) = subR[24] ^ subR[23];
++	} else {
++		tl = subL[26] ^ (subR[26] & ~subR[24]);
++		dw = tl & subL[24], /* FL(kl5) */
++			tr = subR[26] ^ ROL1(dw);
++		SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */
++		SUBKEY_R(23) = subR[22] ^ tr;
++		SUBKEY_L(24) = subL[24];     /* FL(kl5) */
++		SUBKEY_R(24) = subR[24];
++		SUBKEY_L(25) = subL[25];     /* FLinv(kl6) */
++		SUBKEY_R(25) = subR[25];
++		tl = subL[23] ^ (subR[23] & ~subR[25]);
++		dw = tl & subL[25], /* FLinv(kl6) */
++			tr = subR[23] ^ ROL1(dw);
++		SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */
++		SUBKEY_R(26) = tr ^ subR[27];
++		SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */
++		SUBKEY_R(27) = subR[26] ^ subR[28];
++		SUBKEY_L(28) = subL[27] ^ subL[29]; /* round 21 */
++		SUBKEY_R(28) = subR[27] ^ subR[29];
++		SUBKEY_L(29) = subL[28] ^ subL[30]; /* round 22 */
++		SUBKEY_R(29) = subR[28] ^ subR[30];
++		SUBKEY_L(30) = subL[29] ^ subL[31]; /* round 23 */
++		SUBKEY_R(30) = subR[29] ^ subR[31];
++		SUBKEY_L(31) = subL[30];     /* round 24 */
++		SUBKEY_R(31) = subR[30];
++		SUBKEY_L(32) = subL[32] ^ subL[31]; /* kw3 */
++		SUBKEY_R(32) = subR[32] ^ subR[31];
++	}
++
++	/* apply the inverse of the last half of P-function */
++	i = 2;
++	do {
++		dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */
++		SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw;
++		dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */
++		SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw;
++		dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */
++		SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw;
++		dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */
++		SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw;
++		dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */
++		SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw;
++		dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */
++		SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw;
++		i += 8;
++	} while (i < max);
++}
+ 
+ static void camellia_setup128(const unsigned char *key, u32 *subkey)
+ {
+ 	u32 kll, klr, krl, krr;
+ 	u32 il, ir, t0, t1, w0, w1;
+-	u32 kw4l, kw4r, dw, tl, tr;
+ 	u32 subL[26];
+ 	u32 subR[26];
+ 
+ 	/**
+-	 *  k == kll || klr || krl || krr (|| is concatination)
 -	 */
--	if (!blk_pc_request(req))
--		req->errors = 0;
--
--	if (!uptodate) {
--		if (blk_fs_request(req) && !(req->cmd_flags & REQ_QUIET))
--			printk("end_request: I/O error, dev %s, sector %llu\n",
--				req->rq_disk ? req->rq_disk->disk_name : "?",
--				(unsigned long long)req->sector);
--	}
--
--	if (blk_fs_request(req) && req->rq_disk) {
--		const int rw = rq_data_dir(req);
--
--		disk_stat_add(req->rq_disk, sectors[rw], nr_bytes >> 9);
--	}
--
--	total_bytes = bio_nbytes = 0;
--	while ((bio = req->bio) != NULL) {
--		int nbytes;
--
--		/*
--		 * For an empty barrier request, the low level driver must
--		 * store a potential error location in ->sector. We pass
--		 * that back up in ->bi_sector.
--		 */
--		if (blk_empty_barrier(req))
--			bio->bi_sector = req->sector;
+-	kll = GETU32(key     );
+-	klr = GETU32(key +  4);
+-	krl = GETU32(key +  8);
+-	krr = GETU32(key + 12);
+-	/**
+-	 * generate KL dependent subkeys
++	 *  k == kll || klr || krl || krr (|| is concatenation)
+ 	 */
++	GETU32(kll, key     );
++	GETU32(klr, key +  4);
++	GETU32(krl, key +  8);
++	GETU32(krr, key + 12);
++
++	/* generate KL dependent subkeys */
+ 	/* kw1 */
+-	SUBL(0) = kll; SUBR(0) = klr;
++	subL[0] = kll; subR[0] = klr;
+ 	/* kw2 */
+-	SUBL(1) = krl; SUBR(1) = krr;
++	subL[1] = krl; subR[1] = krr;
+ 	/* rotation left shift 15bit */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* k3 */
+-	SUBL(4) = kll; SUBR(4) = klr;
++	subL[4] = kll; subR[4] = klr;
+ 	/* k4 */
+-	SUBL(5) = krl; SUBR(5) = krr;
++	subL[5] = krl; subR[5] = krr;
+ 	/* rotation left shift 15+30bit */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+ 	/* k7 */
+-	SUBL(10) = kll; SUBR(10) = klr;
++	subL[10] = kll; subR[10] = klr;
+ 	/* k8 */
+-	SUBL(11) = krl; SUBR(11) = krr;
++	subL[11] = krl; subR[11] = krr;
+ 	/* rotation left shift 15+30+15bit */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* k10 */
+-	SUBL(13) = krl; SUBR(13) = krr;
++	subL[13] = krl; subR[13] = krr;
+ 	/* rotation left shift 15+30+15+17 bit */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ 	/* kl3 */
+-	SUBL(16) = kll; SUBR(16) = klr;
++	subL[16] = kll; subR[16] = klr;
+ 	/* kl4 */
+-	SUBL(17) = krl; SUBR(17) = krr;
++	subL[17] = krl; subR[17] = krr;
+ 	/* rotation left shift 15+30+15+17+17 bit */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ 	/* k13 */
+-	SUBL(18) = kll; SUBR(18) = klr;
++	subL[18] = kll; subR[18] = klr;
+ 	/* k14 */
+-	SUBL(19) = krl; SUBR(19) = krr;
++	subL[19] = krl; subR[19] = krr;
+ 	/* rotation left shift 15+30+15+17+17+17 bit */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ 	/* k17 */
+-	SUBL(22) = kll; SUBR(22) = klr;
++	subL[22] = kll; subR[22] = klr;
+ 	/* k18 */
+-	SUBL(23) = krl; SUBR(23) = krr;
++	subL[23] = krl; subR[23] = krr;
+ 
+ 	/* generate KA */
+-	kll = SUBL(0); klr = SUBR(0);
+-	krl = SUBL(1); krr = SUBR(1);
++	kll = subL[0]; klr = subR[0];
++	krl = subL[1]; krr = subR[1];
+ 	CAMELLIA_F(kll, klr,
+ 		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+ 		   w0, w1, il, ir, t0, t1);
+@@ -555,306 +666,108 @@ static void camellia_setup128(const unsigned char *key, u32 *subkey)
+ 
+ 	/* generate KA dependent subkeys */
+ 	/* k1, k2 */
+-	SUBL(2) = kll; SUBR(2) = klr;
+-	SUBL(3) = krl; SUBR(3) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	subL[2] = kll; subR[2] = klr;
++	subL[3] = krl; subR[3] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* k5,k6 */
+-	SUBL(6) = kll; SUBR(6) = klr;
+-	SUBL(7) = krl; SUBR(7) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	subL[6] = kll; subR[6] = klr;
++	subL[7] = krl; subR[7] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* kl1, kl2 */
+-	SUBL(8) = kll; SUBR(8) = klr;
+-	SUBL(9) = krl; SUBR(9) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	subL[8] = kll; subR[8] = klr;
++	subL[9] = krl; subR[9] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* k9 */
+-	SUBL(12) = kll; SUBR(12) = klr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	subL[12] = kll; subR[12] = klr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* k11, k12 */
+-	SUBL(14) = kll; SUBR(14) = klr;
+-	SUBL(15) = krl; SUBR(15) = krr;
+-	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
++	subL[14] = kll; subR[14] = klr;
++	subL[15] = krl; subR[15] = krr;
++	ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+ 	/* k15, k16 */
+-	SUBL(20) = kll; SUBR(20) = klr;
+-	SUBL(21) = krl; SUBR(21) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
++	subL[20] = kll; subR[20] = klr;
++	subL[21] = krl; subR[21] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ 	/* kw3, kw4 */
+-	SUBL(24) = kll; SUBR(24) = klr;
+-	SUBL(25) = krl; SUBR(25) = krr;
++	subL[24] = kll; subR[24] = klr;
++	subL[25] = krl; subR[25] = krr;
+ 
 -
--		if (nr_bytes >= bio->bi_size) {
--			req->bio = bio->bi_next;
--			nbytes = bio->bi_size;
--			req_bio_endio(req, bio, nbytes, error);
--			next_idx = 0;
--			bio_nbytes = 0;
--		} else {
--			int idx = bio->bi_idx + next_idx;
+-	/* absorb kw2 to other subkeys */
+-	/* round 2 */
+-	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
+-	/* round 4 */
+-	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
+-	/* round 6 */
+-	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
+-	SUBL(1) ^= SUBR(1) & ~SUBR(9);
+-	dw = SUBL(1) & SUBL(9),
+-		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
+-	/* round 8 */
+-	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
+-	/* round 10 */
+-	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
+-	/* round 12 */
+-	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
+-	SUBL(1) ^= SUBR(1) & ~SUBR(17);
+-	dw = SUBL(1) & SUBL(17),
+-		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
+-	/* round 14 */
+-	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
+-	/* round 16 */
+-	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
+-	/* round 18 */
+-	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
+-	/* kw3 */
+-	SUBL(24) ^= SUBL(1); SUBR(24) ^= SUBR(1);
 -
--			if (unlikely(bio->bi_idx >= bio->bi_vcnt)) {
--				blk_dump_rq_flags(req, "__end_that");
--				printk("%s: bio idx %d >= vcnt %d\n",
--						__FUNCTION__,
--						bio->bi_idx, bio->bi_vcnt);
--				break;
--			}
+-	/* absorb kw4 to other subkeys */
+-	kw4l = SUBL(25); kw4r = SUBR(25);
+-	/* round 17 */
+-	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
+-	/* round 15 */
+-	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
+-	/* round 13 */
+-	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
+-	kw4l ^= kw4r & ~SUBR(16);
+-	dw = kw4l & SUBL(16),
+-		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
+-	/* round 11 */
+-	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
+-	/* round 9 */
+-	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
+-	/* round 7 */
+-	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
+-	kw4l ^= kw4r & ~SUBR(8);
+-	dw = kw4l & SUBL(8),
+-		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
+-	/* round 5 */
+-	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
+-	/* round 3 */
+-	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
+-	/* round 1 */
+-	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
+-	/* kw1 */
+-	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
 -
--			nbytes = bio_iovec_idx(bio, idx)->bv_len;
--			BIO_BUG_ON(nbytes > bio->bi_size);
 -
--			/*
--			 * not a complete bvec done
--			 */
--			if (unlikely(nbytes > nr_bytes)) {
--				bio_nbytes += nr_bytes;
--				total_bytes += nr_bytes;
--				break;
--			}
+-	/* key XOR is end of F-function */
+-	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
+-	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
+-	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
+-	CAMELLIA_SUBKEY_R(2) = SUBR(3);
+-	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
+-	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
+-	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
+-	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
+-	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
+-	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
+-	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
+-	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
+-	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
+-	dw = tl & SUBL(8),  /* FL(kl1) */
+-		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
+-	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
+-	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
+-	CAMELLIA_SUBKEY_R(8) = SUBR(8);
+-	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
+-	CAMELLIA_SUBKEY_R(9) = SUBR(9);
+-	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
+-	dw = tl & SUBL(9),  /* FLinv(kl2) */
+-		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
+-	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
+-	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
+-	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
+-	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
+-	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
+-	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
+-	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
+-	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
+-	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
+-	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
+-	dw = tl & SUBL(16), /* FL(kl3) */
+-		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
+-	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
+-	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
+-	CAMELLIA_SUBKEY_R(16) = SUBR(16);
+-	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
+-	CAMELLIA_SUBKEY_R(17) = SUBR(17);
+-	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
+-	dw = tl & SUBL(17), /* FLinv(kl4) */
+-		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
+-	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
+-	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
+-	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
+-	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
+-	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
+-	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
+-	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
+-	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
+-	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
+-	CAMELLIA_SUBKEY_L(23) = SUBL(22);     /* round 18 */
+-	CAMELLIA_SUBKEY_R(23) = SUBR(22);
+-	CAMELLIA_SUBKEY_L(24) = SUBL(24) ^ SUBL(23); /* kw3 */
+-	CAMELLIA_SUBKEY_R(24) = SUBR(24) ^ SUBR(23);
 -
--			/*
--			 * advance to the next vector
--			 */
--			next_idx++;
--			bio_nbytes += nbytes;
--		}
+-	/* apply the inverse of the last half of P-function */
+-	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
+-		dw = CAMELLIA_RL8(dw);/* round 1 */
+-	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
+-		CAMELLIA_SUBKEY_L(2) = dw;
+-	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
+-		dw = CAMELLIA_RL8(dw);/* round 2 */
+-	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
+-		CAMELLIA_SUBKEY_L(3) = dw;
+-	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
+-		dw = CAMELLIA_RL8(dw);/* round 3 */
+-	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
+-		CAMELLIA_SUBKEY_L(4) = dw;
+-	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
+-		dw = CAMELLIA_RL8(dw);/* round 4 */
+-	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
+-		CAMELLIA_SUBKEY_L(5) = dw;
+-	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
+-		dw = CAMELLIA_RL8(dw);/* round 5 */
+-	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
+-		CAMELLIA_SUBKEY_L(6) = dw;
+-	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
+-		dw = CAMELLIA_RL8(dw);/* round 6 */
+-	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
+-		CAMELLIA_SUBKEY_L(7) = dw;
+-	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
+-		dw = CAMELLIA_RL8(dw);/* round 7 */
+-	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
+-		CAMELLIA_SUBKEY_L(10) = dw;
+-	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
+-		dw = CAMELLIA_RL8(dw);/* round 8 */
+-	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
+-		CAMELLIA_SUBKEY_L(11) = dw;
+-	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
+-		dw = CAMELLIA_RL8(dw);/* round 9 */
+-	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
+-		CAMELLIA_SUBKEY_L(12) = dw;
+-	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
+-		dw = CAMELLIA_RL8(dw);/* round 10 */
+-	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
+-		CAMELLIA_SUBKEY_L(13) = dw;
+-	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
+-		dw = CAMELLIA_RL8(dw);/* round 11 */
+-	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
+-		CAMELLIA_SUBKEY_L(14) = dw;
+-	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
+-		dw = CAMELLIA_RL8(dw);/* round 12 */
+-	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
+-		CAMELLIA_SUBKEY_L(15) = dw;
+-	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
+-		dw = CAMELLIA_RL8(dw);/* round 13 */
+-	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
+-		CAMELLIA_SUBKEY_L(18) = dw;
+-	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
+-		dw = CAMELLIA_RL8(dw);/* round 14 */
+-	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
+-		CAMELLIA_SUBKEY_L(19) = dw;
+-	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
+-		dw = CAMELLIA_RL8(dw);/* round 15 */
+-	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
+-		CAMELLIA_SUBKEY_L(20) = dw;
+-	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
+-		dw = CAMELLIA_RL8(dw);/* round 16 */
+-	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
+-		CAMELLIA_SUBKEY_L(21) = dw;
+-	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
+-		dw = CAMELLIA_RL8(dw);/* round 17 */
+-	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
+-		CAMELLIA_SUBKEY_L(22) = dw;
+-	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
+-		dw = CAMELLIA_RL8(dw);/* round 18 */
+-	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
+-		CAMELLIA_SUBKEY_L(23) = dw;
 -
--		total_bytes += nbytes;
--		nr_bytes -= nbytes;
+-	return;
++	camellia_setup_tail(subkey, subL, subR, 24);
+ }
+ 
 -
--		if ((bio = req->bio)) {
--			/*
--			 * end more in this run, or just return 'not-done'
--			 */
--			if (unlikely(nr_bytes <= 0))
--				break;
--		}
--	}
+ static void camellia_setup256(const unsigned char *key, u32 *subkey)
+ {
+-	u32 kll,klr,krl,krr;           /* left half of key */
+-	u32 krll,krlr,krrl,krrr;       /* right half of key */
++	u32 kll, klr, krl, krr;        /* left half of key */
++	u32 krll, krlr, krrl, krrr;    /* right half of key */
+ 	u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
+-	u32 kw4l, kw4r, dw, tl, tr;
+ 	u32 subL[34];
+ 	u32 subR[34];
+ 
+ 	/**
+ 	 *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
+-	 *  (|| is concatination)
++	 *  (|| is concatenation)
+ 	 */
 -
--	/*
--	 * completely done
--	 */
--	if (!req->bio)
--		return 0;
+-	kll  = GETU32(key     );
+-	klr  = GETU32(key +  4);
+-	krl  = GETU32(key +  8);
+-	krr  = GETU32(key + 12);
+-	krll = GETU32(key + 16);
+-	krlr = GETU32(key + 20);
+-	krrl = GETU32(key + 24);
+-	krrr = GETU32(key + 28);
++	GETU32(kll,  key     );
++	GETU32(klr,  key +  4);
++	GETU32(krl,  key +  8);
++	GETU32(krr,  key + 12);
++	GETU32(krll, key + 16);
++	GETU32(krlr, key + 20);
++	GETU32(krrl, key + 24);
++	GETU32(krrr, key + 28);
+ 
+ 	/* generate KL dependent subkeys */
+ 	/* kw1 */
+-	SUBL(0) = kll; SUBR(0) = klr;
++	subL[0] = kll; subR[0] = klr;
+ 	/* kw2 */
+-	SUBL(1) = krl; SUBR(1) = krr;
+-	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
++	subL[1] = krl; subR[1] = krr;
++	ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
+ 	/* k9 */
+-	SUBL(12) = kll; SUBR(12) = klr;
++	subL[12] = kll; subR[12] = klr;
+ 	/* k10 */
+-	SUBL(13) = krl; SUBR(13) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	subL[13] = krl; subR[13] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* kl3 */
+-	SUBL(16) = kll; SUBR(16) = klr;
++	subL[16] = kll; subR[16] = klr;
+ 	/* kl4 */
+-	SUBL(17) = krl; SUBR(17) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
++	subL[17] = krl; subR[17] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
+ 	/* k17 */
+-	SUBL(22) = kll; SUBR(22) = klr;
++	subL[22] = kll; subR[22] = klr;
+ 	/* k18 */
+-	SUBL(23) = krl; SUBR(23) = krr;
+-	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
++	subL[23] = krl; subR[23] = krr;
++	ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
+ 	/* k23 */
+-	SUBL(30) = kll; SUBR(30) = klr;
++	subL[30] = kll; subR[30] = klr;
+ 	/* k24 */
+-	SUBL(31) = krl; SUBR(31) = krr;
++	subL[31] = krl; subR[31] = krr;
+ 
+ 	/* generate KR dependent subkeys */
+-	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
++	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+ 	/* k3 */
+-	SUBL(4) = krll; SUBR(4) = krlr;
++	subL[4] = krll; subR[4] = krlr;
+ 	/* k4 */
+-	SUBL(5) = krrl; SUBR(5) = krrr;
+-	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
++	subL[5] = krrl; subR[5] = krrr;
++	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
+ 	/* kl1 */
+-	SUBL(8) = krll; SUBR(8) = krlr;
++	subL[8] = krll; subR[8] = krlr;
+ 	/* kl2 */
+-	SUBL(9) = krrl; SUBR(9) = krrr;
+-	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
++	subL[9] = krrl; subR[9] = krrr;
++	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+ 	/* k13 */
+-	SUBL(18) = krll; SUBR(18) = krlr;
++	subL[18] = krll; subR[18] = krlr;
+ 	/* k14 */
+-	SUBL(19) = krrl; SUBR(19) = krrr;
+-	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
++	subL[19] = krrl; subR[19] = krrr;
++	ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+ 	/* k19 */
+-	SUBL(26) = krll; SUBR(26) = krlr;
++	subL[26] = krll; subR[26] = krlr;
+ 	/* k20 */
+-	SUBL(27) = krrl; SUBR(27) = krrr;
+-	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
++	subL[27] = krrl; subR[27] = krrr;
++	ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
+ 
+ 	/* generate KA */
+-	kll = SUBL(0) ^ krll; klr = SUBR(0) ^ krlr;
+-	krl = SUBL(1) ^ krrl; krr = SUBR(1) ^ krrr;
++	kll = subL[0] ^ krll; klr = subR[0] ^ krlr;
++	krl = subL[1] ^ krrl; krr = subR[1] ^ krrr;
+ 	CAMELLIA_F(kll, klr,
+ 		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
+ 		   w0, w1, il, ir, t0, t1);
+@@ -885,310 +798,50 @@ static void camellia_setup256(const unsigned char *key, u32 *subkey)
+ 	krll ^= w0; krlr ^= w1;
+ 
+ 	/* generate KA dependent subkeys */
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
++	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
+ 	/* k5 */
+-	SUBL(6) = kll; SUBR(6) = klr;
++	subL[6] = kll; subR[6] = klr;
+ 	/* k6 */
+-	SUBL(7) = krl; SUBR(7) = krr;
+-	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
++	subL[7] = krl; subR[7] = krr;
++	ROLDQ(kll, klr, krl, krr, w0, w1, 30);
+ 	/* k11 */
+-	SUBL(14) = kll; SUBR(14) = klr;
++	subL[14] = kll; subR[14] = klr;
+ 	/* k12 */
+-	SUBL(15) = krl; SUBR(15) = krr;
++	subL[15] = krl; subR[15] = krr;
+ 	/* rotation left shift 32bit */
+ 	/* kl5 */
+-	SUBL(24) = klr; SUBR(24) = krl;
++	subL[24] = klr; subR[24] = krl;
+ 	/* kl6 */
+-	SUBL(25) = krr; SUBR(25) = kll;
++	subL[25] = krr; subR[25] = kll;
+ 	/* rotation left shift 49 from k11,k12 -> k21,k22 */
+-	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
++	ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
+ 	/* k21 */
+-	SUBL(28) = kll; SUBR(28) = klr;
++	subL[28] = kll; subR[28] = klr;
+ 	/* k22 */
+-	SUBL(29) = krl; SUBR(29) = krr;
++	subL[29] = krl; subR[29] = krr;
+ 
+ 	/* generate KB dependent subkeys */
+ 	/* k1 */
+-	SUBL(2) = krll; SUBR(2) = krlr;
++	subL[2] = krll; subR[2] = krlr;
+ 	/* k2 */
+-	SUBL(3) = krrl; SUBR(3) = krrr;
+-	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
++	subL[3] = krrl; subR[3] = krrr;
++	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+ 	/* k7 */
+-	SUBL(10) = krll; SUBR(10) = krlr;
++	subL[10] = krll; subR[10] = krlr;
+ 	/* k8 */
+-	SUBL(11) = krrl; SUBR(11) = krrr;
+-	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
++	subL[11] = krrl; subR[11] = krrr;
++	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
+ 	/* k15 */
+-	SUBL(20) = krll; SUBR(20) = krlr;
++	subL[20] = krll; subR[20] = krlr;
+ 	/* k16 */
+-	SUBL(21) = krrl; SUBR(21) = krrr;
+-	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
++	subL[21] = krrl; subR[21] = krrr;
++	ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
+ 	/* kw3 */
+-	SUBL(32) = krll; SUBR(32) = krlr;
++	subL[32] = krll; subR[32] = krlr;
+ 	/* kw4 */
+-	SUBL(33) = krrl; SUBR(33) = krrr;
 -
--	/*
--	 * if the request wasn't completed, update state
--	 */
--	if (bio_nbytes) {
--		req_bio_endio(req, bio, bio_nbytes, error);
--		bio->bi_idx += next_idx;
--		bio_iovec(bio)->bv_offset += nr_bytes;
--		bio_iovec(bio)->bv_len -= nr_bytes;
--	}
+-	/* absorb kw2 to other subkeys */
+-	/* round 2 */
+-	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
+-	/* round 4 */
+-	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
+-	/* round 6 */
+-	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
+-	SUBL(1) ^= SUBR(1) & ~SUBR(9);
+-	dw = SUBL(1) & SUBL(9),
+-		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
+-	/* round 8 */
+-	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
+-	/* round 10 */
+-	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
+-	/* round 12 */
+-	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
+-	SUBL(1) ^= SUBR(1) & ~SUBR(17);
+-	dw = SUBL(1) & SUBL(17),
+-		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
+-	/* round 14 */
+-	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
+-	/* round 16 */
+-	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
+-	/* round 18 */
+-	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
+-	SUBL(1) ^= SUBR(1) & ~SUBR(25);
+-	dw = SUBL(1) & SUBL(25),
+-		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl6) */
+-	/* round 20 */
+-	SUBL(27) ^= SUBL(1); SUBR(27) ^= SUBR(1);
+-	/* round 22 */
+-	SUBL(29) ^= SUBL(1); SUBR(29) ^= SUBR(1);
+-	/* round 24 */
+-	SUBL(31) ^= SUBL(1); SUBR(31) ^= SUBR(1);
+-	/* kw3 */
+-	SUBL(32) ^= SUBL(1); SUBR(32) ^= SUBR(1);
 -
--	blk_recalc_rq_sectors(req, total_bytes >> 9);
--	blk_recalc_rq_segments(req);
--	return 1;
--}
 -
--/**
-- * end_that_request_first - end I/O on a request
-- * @req:      the request being processed
-- * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
-- * @nr_sectors: number of sectors to end I/O on
-- *
-- * Description:
-- *     Ends I/O on a number of sectors attached to @req, and sets it up
-- *     for the next range of segments (if any) in the cluster.
-- *
-- * Return:
-- *     0 - we are done with this request, call end_that_request_last()
-- *     1 - still buffers pending for this request
-- **/
--int end_that_request_first(struct request *req, int uptodate, int nr_sectors)
--{
--	return __end_that_request_first(req, uptodate, nr_sectors << 9);
--}
+-	/* absorb kw4 to other subkeys */
+-	kw4l = SUBL(33); kw4r = SUBR(33);
+-	/* round 23 */
+-	SUBL(30) ^= kw4l; SUBR(30) ^= kw4r;
+-	/* round 21 */
+-	SUBL(28) ^= kw4l; SUBR(28) ^= kw4r;
+-	/* round 19 */
+-	SUBL(26) ^= kw4l; SUBR(26) ^= kw4r;
+-	kw4l ^= kw4r & ~SUBR(24);
+-	dw = kw4l & SUBL(24),
+-		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl5) */
+-	/* round 17 */
+-	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
+-	/* round 15 */
+-	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
+-	/* round 13 */
+-	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
+-	kw4l ^= kw4r & ~SUBR(16);
+-	dw = kw4l & SUBL(16),
+-		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
+-	/* round 11 */
+-	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
+-	/* round 9 */
+-	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
+-	/* round 7 */
+-	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
+-	kw4l ^= kw4r & ~SUBR(8);
+-	dw = kw4l & SUBL(8),
+-		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
+-	/* round 5 */
+-	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
+-	/* round 3 */
+-	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
+-	/* round 1 */
+-	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
+-	/* kw1 */
+-	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
++	subL[33] = krrl; subR[33] = krrr;
+ 
+-	/* key XOR is end of F-function */
+-	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
+-	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
+-	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
+-	CAMELLIA_SUBKEY_R(2) = SUBR(3);
+-	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
+-	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
+-	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
+-	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
+-	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
+-	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
+-	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
+-	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
+-	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
+-	dw = tl & SUBL(8),  /* FL(kl1) */
+-		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
+-	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
+-	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
+-	CAMELLIA_SUBKEY_R(8) = SUBR(8);
+-	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
+-	CAMELLIA_SUBKEY_R(9) = SUBR(9);
+-	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
+-	dw = tl & SUBL(9),  /* FLinv(kl2) */
+-		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
+-	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
+-	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
+-	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
+-	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
+-	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
+-	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
+-	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
+-	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
+-	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
+-	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
+-	dw = tl & SUBL(16), /* FL(kl3) */
+-		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
+-	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
+-	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
+-	CAMELLIA_SUBKEY_R(16) = SUBR(16);
+-	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
+-	CAMELLIA_SUBKEY_R(17) = SUBR(17);
+-	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
+-	dw = tl & SUBL(17), /* FLinv(kl4) */
+-		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
+-	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
+-	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
+-	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
+-	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
+-	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
+-	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
+-	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
+-	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
+-	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
+-	tl = SUBL(26) ^ (SUBR(26)
+-			 & ~SUBR(24));
+-	dw = tl & SUBL(24), /* FL(kl5) */
+-		tr = SUBR(26) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(23) = SUBL(22) ^ tl; /* round 18 */
+-	CAMELLIA_SUBKEY_R(23) = SUBR(22) ^ tr;
+-	CAMELLIA_SUBKEY_L(24) = SUBL(24);     /* FL(kl5) */
+-	CAMELLIA_SUBKEY_R(24) = SUBR(24);
+-	CAMELLIA_SUBKEY_L(25) = SUBL(25);     /* FLinv(kl6) */
+-	CAMELLIA_SUBKEY_R(25) = SUBR(25);
+-	tl = SUBL(23) ^ (SUBR(23) &
+-			 ~SUBR(25));
+-	dw = tl & SUBL(25), /* FLinv(kl6) */
+-		tr = SUBR(23) ^ CAMELLIA_RL1(dw);
+-	CAMELLIA_SUBKEY_L(26) = tl ^ SUBL(27); /* round 19 */
+-	CAMELLIA_SUBKEY_R(26) = tr ^ SUBR(27);
+-	CAMELLIA_SUBKEY_L(27) = SUBL(26) ^ SUBL(28); /* round 20 */
+-	CAMELLIA_SUBKEY_R(27) = SUBR(26) ^ SUBR(28);
+-	CAMELLIA_SUBKEY_L(28) = SUBL(27) ^ SUBL(29); /* round 21 */
+-	CAMELLIA_SUBKEY_R(28) = SUBR(27) ^ SUBR(29);
+-	CAMELLIA_SUBKEY_L(29) = SUBL(28) ^ SUBL(30); /* round 22 */
+-	CAMELLIA_SUBKEY_R(29) = SUBR(28) ^ SUBR(30);
+-	CAMELLIA_SUBKEY_L(30) = SUBL(29) ^ SUBL(31); /* round 23 */
+-	CAMELLIA_SUBKEY_R(30) = SUBR(29) ^ SUBR(31);
+-	CAMELLIA_SUBKEY_L(31) = SUBL(30);     /* round 24 */
+-	CAMELLIA_SUBKEY_R(31) = SUBR(30);
+-	CAMELLIA_SUBKEY_L(32) = SUBL(32) ^ SUBL(31); /* kw3 */
+-	CAMELLIA_SUBKEY_R(32) = SUBR(32) ^ SUBR(31);
 -
--EXPORT_SYMBOL(end_that_request_first);
+-	/* apply the inverse of the last half of P-function */
+-	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
+-		dw = CAMELLIA_RL8(dw);/* round 1 */
+-	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
+-		CAMELLIA_SUBKEY_L(2) = dw;
+-	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
+-		dw = CAMELLIA_RL8(dw);/* round 2 */
+-	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
+-		CAMELLIA_SUBKEY_L(3) = dw;
+-	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
+-		dw = CAMELLIA_RL8(dw);/* round 3 */
+-	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
+-		CAMELLIA_SUBKEY_L(4) = dw;
+-	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
+-		dw = CAMELLIA_RL8(dw);/* round 4 */
+-	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
+-	CAMELLIA_SUBKEY_L(5) = dw;
+-	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
+-		dw = CAMELLIA_RL8(dw);/* round 5 */
+-	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
+-		CAMELLIA_SUBKEY_L(6) = dw;
+-	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
+-		dw = CAMELLIA_RL8(dw);/* round 6 */
+-	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
+-		CAMELLIA_SUBKEY_L(7) = dw;
+-	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
+-		dw = CAMELLIA_RL8(dw);/* round 7 */
+-	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
+-		CAMELLIA_SUBKEY_L(10) = dw;
+-	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
+-	    dw = CAMELLIA_RL8(dw);/* round 8 */
+-	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
+-		CAMELLIA_SUBKEY_L(11) = dw;
+-	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
+-		dw = CAMELLIA_RL8(dw);/* round 9 */
+-	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
+-		CAMELLIA_SUBKEY_L(12) = dw;
+-	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
+-		dw = CAMELLIA_RL8(dw);/* round 10 */
+-	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
+-		CAMELLIA_SUBKEY_L(13) = dw;
+-	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
+-		dw = CAMELLIA_RL8(dw);/* round 11 */
+-	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
+-		CAMELLIA_SUBKEY_L(14) = dw;
+-	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
+-		dw = CAMELLIA_RL8(dw);/* round 12 */
+-	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
+-		CAMELLIA_SUBKEY_L(15) = dw;
+-	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
+-		dw = CAMELLIA_RL8(dw);/* round 13 */
+-	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
+-		CAMELLIA_SUBKEY_L(18) = dw;
+-	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
+-		dw = CAMELLIA_RL8(dw);/* round 14 */
+-	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
+-		CAMELLIA_SUBKEY_L(19) = dw;
+-	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
+-		dw = CAMELLIA_RL8(dw);/* round 15 */
+-	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
+-		CAMELLIA_SUBKEY_L(20) = dw;
+-	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
+-		dw = CAMELLIA_RL8(dw);/* round 16 */
+-	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
+-		CAMELLIA_SUBKEY_L(21) = dw;
+-	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
+-		dw = CAMELLIA_RL8(dw);/* round 17 */
+-	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
+-		CAMELLIA_SUBKEY_L(22) = dw;
+-	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
+-		dw = CAMELLIA_RL8(dw);/* round 18 */
+-	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
+-		CAMELLIA_SUBKEY_L(23) = dw;
+-	dw = CAMELLIA_SUBKEY_L(26) ^ CAMELLIA_SUBKEY_R(26),
+-		dw = CAMELLIA_RL8(dw);/* round 19 */
+-	CAMELLIA_SUBKEY_R(26) = CAMELLIA_SUBKEY_L(26) ^ dw,
+-		CAMELLIA_SUBKEY_L(26) = dw;
+-	dw = CAMELLIA_SUBKEY_L(27) ^ CAMELLIA_SUBKEY_R(27),
+-		dw = CAMELLIA_RL8(dw);/* round 20 */
+-	CAMELLIA_SUBKEY_R(27) = CAMELLIA_SUBKEY_L(27) ^ dw,
+-		CAMELLIA_SUBKEY_L(27) = dw;
+-	dw = CAMELLIA_SUBKEY_L(28) ^ CAMELLIA_SUBKEY_R(28),
+-		dw = CAMELLIA_RL8(dw);/* round 21 */
+-	CAMELLIA_SUBKEY_R(28) = CAMELLIA_SUBKEY_L(28) ^ dw,
+-		CAMELLIA_SUBKEY_L(28) = dw;
+-	dw = CAMELLIA_SUBKEY_L(29) ^ CAMELLIA_SUBKEY_R(29),
+-		dw = CAMELLIA_RL8(dw);/* round 22 */
+-	CAMELLIA_SUBKEY_R(29) = CAMELLIA_SUBKEY_L(29) ^ dw,
+-		CAMELLIA_SUBKEY_L(29) = dw;
+-	dw = CAMELLIA_SUBKEY_L(30) ^ CAMELLIA_SUBKEY_R(30),
+-		dw = CAMELLIA_RL8(dw);/* round 23 */
+-	CAMELLIA_SUBKEY_R(30) = CAMELLIA_SUBKEY_L(30) ^ dw,
+-		CAMELLIA_SUBKEY_L(30) = dw;
+-	dw = CAMELLIA_SUBKEY_L(31) ^ CAMELLIA_SUBKEY_R(31),
+-		dw = CAMELLIA_RL8(dw);/* round 24 */
+-	CAMELLIA_SUBKEY_R(31) = CAMELLIA_SUBKEY_L(31) ^ dw,
+-		CAMELLIA_SUBKEY_L(31) = dw;
 -
+-	return;
++	camellia_setup_tail(subkey, subL, subR, 32);
+ }
+ 
+ static void camellia_setup192(const unsigned char *key, u32 *subkey)
+@@ -1197,482 +850,168 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
+ 	u32 krll, krlr, krrl,krrr;
+ 
+ 	memcpy(kk, key, 24);
+-	memcpy((unsigned char *)&krll, key+16,4);
+-	memcpy((unsigned char *)&krlr, key+20,4);
++	memcpy((unsigned char *)&krll, key+16, 4);
++	memcpy((unsigned char *)&krlr, key+20, 4);
+ 	krrl = ~krll;
+ 	krrr = ~krlr;
+ 	memcpy(kk+24, (unsigned char *)&krrl, 4);
+ 	memcpy(kk+28, (unsigned char *)&krrr, 4);
+ 	camellia_setup256(kk, subkey);
+-	return;
+ }
+ 
+ 
 -/**
-- * end_that_request_chunk - end I/O on a request
-- * @req:      the request being processed
-- * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
-- * @nr_bytes: number of bytes to complete
-- *
-- * Description:
-- *     Ends I/O on a number of bytes attached to @req, and sets it up
-- *     for the next range of segments (if any). Like end_that_request_first(),
-- *     but deals with bytes instead of sectors.
-- *
-- * Return:
-- *     0 - we are done with this request, call end_that_request_last()
-- *     1 - still buffers pending for this request
-- **/
--int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
--{
--	return __end_that_request_first(req, uptodate, nr_bytes);
--}
--
--EXPORT_SYMBOL(end_that_request_chunk);
--
--/*
-- * splice the completion data to a local structure and hand off to
-- * process_completion_queue() to complete the requests
-- */
--static void blk_done_softirq(struct softirq_action *h)
+- * Stuff related to camellia encryption/decryption
++/*
++ * Encrypt/decrypt
+  */
+-static void camellia_encrypt128(const u32 *subkey, __be32 *io_text)
 -{
--	struct list_head *cpu_list, local_list;
--
--	local_irq_disable();
--	cpu_list = &__get_cpu_var(blk_cpu_done);
--	list_replace_init(cpu_list, &local_list);
--	local_irq_enable();
--
--	while (!list_empty(&local_list)) {
--		struct request *rq = list_entry(local_list.next, struct request, donelist);
+-	u32 il,ir,t0,t1;               /* temporary valiables */
 -
--		list_del_init(&rq->donelist);
--		rq->q->softirq_done_fn(rq);
--	}
--}
+-	u32 io[4];
 -
--static int __cpuinit blk_cpu_notify(struct notifier_block *self, unsigned long action,
--			  void *hcpu)
--{
--	/*
--	 * If a CPU goes away, splice its entries to the current CPU
--	 * and trigger a run of the softirq
--	 */
--	if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
--		int cpu = (unsigned long) hcpu;
+-	io[0] = be32_to_cpu(io_text[0]);
+-	io[1] = be32_to_cpu(io_text[1]);
+-	io[2] = be32_to_cpu(io_text[2]);
+-	io[3] = be32_to_cpu(io_text[3]);
 -
--		local_irq_disable();
--		list_splice_init(&per_cpu(blk_cpu_done, cpu),
--				 &__get_cpu_var(blk_cpu_done));
--		raise_softirq_irqoff(BLOCK_SOFTIRQ);
--		local_irq_enable();
--	}
+-	/* pre whitening but absorb kw2*/
+-	io[0] ^= CAMELLIA_SUBKEY_L(0);
+-	io[1] ^= CAMELLIA_SUBKEY_R(0);
+-	/* main iteration */
 -
--	return NOTIFY_OK;
--}
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+-			 io[0],io[1],il,ir,t0,t1);
 -
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+-		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+-		     t0,t1,il,ir);
 -
--static struct notifier_block blk_cpu_notifier __cpuinitdata = {
--	.notifier_call	= blk_cpu_notify,
--};
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--/**
-- * blk_complete_request - end I/O on a request
-- * @req:      the request being processed
-- *
-- * Description:
-- *     Ends all I/O on a request. It does not handle partial completions,
-- *     unless the driver actually implements this in its completion callback
-- *     through requeueing. The actual completion happens out-of-order,
-- *     through a softirq handler. The user must have registered a completion
-- *     callback through blk_queue_softirq_done().
-- **/
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+-		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+-		     t0,t1,il,ir);
 -
--void blk_complete_request(struct request *req)
--{
--	struct list_head *cpu_list;
--	unsigned long flags;
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+-			 io[0],io[1],il,ir,t0,t1);
++#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
++    do {								\
++	t0 = kll;							\
++	t2 = krr;							\
++	t0 &= ll;							\
++	t2 |= rr;							\
++	rl ^= t2;							\
++	lr ^= ROL1(t0);							\
++	t3 = krl;							\
++	t1 = klr;							\
++	t3 &= rl;							\
++	t1 |= lr;							\
++	ll ^= t1;							\
++	rr ^= ROL1(t3);							\
++    } while(0)
+ 
+-	/* post whitening but kw4 */
+-	io[2] ^= CAMELLIA_SUBKEY_L(24);
+-	io[3] ^= CAMELLIA_SUBKEY_R(24);
 -
--	BUG_ON(!req->q->softirq_done_fn);
--		
--	local_irq_save(flags);
+-	t0 = io[0];
+-	t1 = io[1];
+-	io[0] = io[2];
+-	io[1] = io[3];
+-	io[2] = t0;
+-	io[3] = t1;
 -
--	cpu_list = &__get_cpu_var(blk_cpu_done);
--	list_add_tail(&req->donelist, cpu_list);
--	raise_softirq_irqoff(BLOCK_SOFTIRQ);
+-	io_text[0] = cpu_to_be32(io[0]);
+-	io_text[1] = cpu_to_be32(io[1]);
+-	io_text[2] = cpu_to_be32(io[2]);
+-	io_text[3] = cpu_to_be32(io[3]);
 -
--	local_irq_restore(flags);
+-	return;
 -}
++#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir)		\
++    do {								\
++	ir =  camellia_sp1110[(u8)xr];					\
++	il =  camellia_sp1110[    (xl >> 24)];				\
++	ir ^= camellia_sp0222[    (xr >> 24)];				\
++	il ^= camellia_sp0222[(u8)(xl >> 16)];				\
++	ir ^= camellia_sp3033[(u8)(xr >> 16)];				\
++	il ^= camellia_sp3033[(u8)(xl >> 8)];				\
++	ir ^= camellia_sp4404[(u8)(xr >> 8)];				\
++	il ^= camellia_sp4404[(u8)xl];					\
++	il ^= kl;							\
++	ir ^= il ^ kr;							\
++	yl ^= ir;							\
++	yr ^= ROR8(il) ^ ir;						\
++    } while(0)
+ 
+-static void camellia_decrypt128(const u32 *subkey, __be32 *io_text)
++/* max = 24: 128bit encrypt, max = 32: 256bit encrypt */
++static void camellia_do_encrypt(const u32 *subkey, u32 *io, unsigned max)
+ {
+-	u32 il,ir,t0,t1;               /* temporary valiables */
++	u32 il,ir,t0,t1;               /* temporary variables */
+ 
+-	u32 io[4];
 -
--EXPORT_SYMBOL(blk_complete_request);
--	
--/*
-- * queue lock must be held
-- */
--void end_that_request_last(struct request *req, int uptodate)
--{
--	struct gendisk *disk = req->rq_disk;
--	int error;
--
--	/*
--	 * extend uptodate bool to allow < 0 value to be direct io error
--	 */
--	error = 0;
--	if (end_io_error(uptodate))
--		error = !uptodate ? -EIO : uptodate;
+-	io[0] = be32_to_cpu(io_text[0]);
+-	io[1] = be32_to_cpu(io_text[1]);
+-	io[2] = be32_to_cpu(io_text[2]);
+-	io[3] = be32_to_cpu(io_text[3]);
 -
--	if (unlikely(laptop_mode) && blk_fs_request(req))
--		laptop_io_completion();
+-	/* pre whitening but absorb kw2*/
+-	io[0] ^= CAMELLIA_SUBKEY_L(24);
+-	io[1] ^= CAMELLIA_SUBKEY_R(24);
++	/* pre whitening but absorb kw2 */
++	io[0] ^= SUBKEY_L(0);
++	io[1] ^= SUBKEY_R(0);
+ 
+ 	/* main iteration */
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--	/*
--	 * Account IO completion.  bar_rq isn't accounted as a normal
--	 * IO on queueing nor completion.  Accounting the containing
--	 * request is enough.
--	 */
--	if (disk && blk_fs_request(req) && req != &req->q->bar_rq) {
--		unsigned long duration = jiffies - req->start_time;
--		const int rw = rq_data_dir(req);
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+-		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+-		     t0,t1,il,ir);
 -
--		__disk_stat_inc(disk, ios[rw]);
--		__disk_stat_add(disk, ticks[rw], duration);
--		disk_round_stats(disk);
--		disk->in_flight--;
--	}
--	if (req->end_io)
--		req->end_io(req, error);
--	else
--		__blk_put_request(req->q, req);
--}
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--EXPORT_SYMBOL(end_that_request_last);
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+-		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+-		     t0,t1,il,ir);
 -
--static inline void __end_request(struct request *rq, int uptodate,
--				 unsigned int nr_bytes, int dequeue)
--{
--	if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
--		if (dequeue)
--			blkdev_dequeue_request(rq);
--		add_disk_randomness(rq->rq_disk);
--		end_that_request_last(rq, uptodate);
--	}
--}
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--static unsigned int rq_byte_size(struct request *rq)
--{
--	if (blk_fs_request(rq))
--		return rq->hard_nr_sectors << 9;
+-	/* post whitening but kw4 */
+-	io[2] ^= CAMELLIA_SUBKEY_L(0);
+-	io[3] ^= CAMELLIA_SUBKEY_R(0);
 -
--	return rq->data_len;
--}
+-	t0 = io[0];
+-	t1 = io[1];
+-	io[0] = io[2];
+-	io[1] = io[3];
+-	io[2] = t0;
+-	io[3] = t1;
 -
--/**
-- * end_queued_request - end all I/O on a queued request
-- * @rq:		the request being processed
-- * @uptodate:	error value or 0/1 uptodate flag
-- *
-- * Description:
-- *     Ends all I/O on a request, and removes it from the block layer queues.
-- *     Not suitable for normal IO completion, unless the driver still has
-- *     the request attached to the block layer.
-- *
-- **/
--void end_queued_request(struct request *rq, int uptodate)
--{
--	__end_request(rq, uptodate, rq_byte_size(rq), 1);
--}
--EXPORT_SYMBOL(end_queued_request);
+-	io_text[0] = cpu_to_be32(io[0]);
+-	io_text[1] = cpu_to_be32(io[1]);
+-	io_text[2] = cpu_to_be32(io[2]);
+-	io_text[3] = cpu_to_be32(io[3]);
 -
--/**
-- * end_dequeued_request - end all I/O on a dequeued request
-- * @rq:		the request being processed
-- * @uptodate:	error value or 0/1 uptodate flag
-- *
-- * Description:
-- *     Ends all I/O on a request. The request must already have been
-- *     dequeued using blkdev_dequeue_request(), as is normally the case
-- *     for most drivers.
-- *
-- **/
--void end_dequeued_request(struct request *rq, int uptodate)
--{
--	__end_request(rq, uptodate, rq_byte_size(rq), 0);
+-	return;
 -}
--EXPORT_SYMBOL(end_dequeued_request);
 -
 -
 -/**
-- * end_request - end I/O on the current segment of the request
-- * @req:	the request being processed
-- * @uptodate:	error value or 0/1 uptodate flag
-- *
-- * Description:
-- *     Ends I/O on the current segment of a request. If that is the only
-- *     remaining segment, the request is also completed and freed.
-- *
-- *     This is a remnant of how older block drivers handled IO completions.
-- *     Modern drivers typically end IO on the full request in one go, unless
-- *     they have a residual value to account for. For that case this function
-- *     isn't really useful, unless the residual just happens to be the
-- *     full current segment. In other words, don't use this function in new
-- *     code. Either use end_request_completely(), or the
-- *     end_that_request_chunk() (along with end_that_request_last()) for
-- *     partial completions.
-- *
-- **/
--void end_request(struct request *req, int uptodate)
--{
--	__end_request(req, uptodate, req->hard_cur_sectors << 9, 1);
--}
--EXPORT_SYMBOL(end_request);
--
--static void blk_rq_bio_prep(struct request_queue *q, struct request *rq,
--			    struct bio *bio)
--{
--	/* first two bits are identical in rq->cmd_flags and bio->bi_rw */
--	rq->cmd_flags |= (bio->bi_rw & 3);
--
--	rq->nr_phys_segments = bio_phys_segments(q, bio);
--	rq->nr_hw_segments = bio_hw_segments(q, bio);
--	rq->current_nr_sectors = bio_cur_sectors(bio);
--	rq->hard_cur_sectors = rq->current_nr_sectors;
--	rq->hard_nr_sectors = rq->nr_sectors = bio_sectors(bio);
--	rq->buffer = bio_data(bio);
--	rq->data_len = bio->bi_size;
--
--	rq->bio = rq->biotail = bio;
--
--	if (bio->bi_bdev)
--		rq->rq_disk = bio->bi_bdev->bd_disk;
--}
--
--int kblockd_schedule_work(struct work_struct *work)
--{
--	return queue_work(kblockd_workqueue, work);
--}
--
--EXPORT_SYMBOL(kblockd_schedule_work);
--
--void kblockd_flush_work(struct work_struct *work)
--{
--	cancel_work_sync(work);
--}
--EXPORT_SYMBOL(kblockd_flush_work);
--
--int __init blk_dev_init(void)
--{
--	int i;
--
--	kblockd_workqueue = create_workqueue("kblockd");
--	if (!kblockd_workqueue)
--		panic("Failed to create kblockd\n");
--
--	request_cachep = kmem_cache_create("blkdev_requests",
--			sizeof(struct request), 0, SLAB_PANIC, NULL);
--
--	requestq_cachep = kmem_cache_create("blkdev_queue",
--			sizeof(struct request_queue), 0, SLAB_PANIC, NULL);
--
--	iocontext_cachep = kmem_cache_create("blkdev_ioc",
--			sizeof(struct io_context), 0, SLAB_PANIC, NULL);
--
--	for_each_possible_cpu(i)
--		INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i));
--
--	open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL);
--	register_hotcpu_notifier(&blk_cpu_notifier);
--
--	blk_max_low_pfn = max_low_pfn - 1;
--	blk_max_pfn = max_pfn - 1;
--
--	return 0;
--}
--
--/*
-- * IO Context helper functions
+- * stuff for 192 and 256bit encryption/decryption
 - */
--void put_io_context(struct io_context *ioc)
+-static void camellia_encrypt256(const u32 *subkey, __be32 *io_text)
 -{
--	if (ioc == NULL)
--		return;
--
--	BUG_ON(atomic_read(&ioc->refcount) == 0);
--
--	if (atomic_dec_and_test(&ioc->refcount)) {
--		struct cfq_io_context *cic;
+-	u32 il,ir,t0,t1;           /* temporary valiables */
 -
--		rcu_read_lock();
--		if (ioc->aic && ioc->aic->dtor)
--			ioc->aic->dtor(ioc->aic);
--		if (ioc->cic_root.rb_node != NULL) {
--			struct rb_node *n = rb_first(&ioc->cic_root);
+-	u32 io[4];
 -
--			cic = rb_entry(n, struct cfq_io_context, rb_node);
--			cic->dtor(ioc);
--		}
--		rcu_read_unlock();
+-	io[0] = be32_to_cpu(io_text[0]);
+-	io[1] = be32_to_cpu(io_text[1]);
+-	io[2] = be32_to_cpu(io_text[2]);
+-	io[3] = be32_to_cpu(io_text[3]);
++#define ROUNDS(i) do { \
++	CAMELLIA_ROUNDSM(io[0],io[1], \
++			 SUBKEY_L(i + 2),SUBKEY_R(i + 2), \
++			 io[2],io[3],il,ir); \
++	CAMELLIA_ROUNDSM(io[2],io[3], \
++			 SUBKEY_L(i + 3),SUBKEY_R(i + 3), \
++			 io[0],io[1],il,ir); \
++	CAMELLIA_ROUNDSM(io[0],io[1], \
++			 SUBKEY_L(i + 4),SUBKEY_R(i + 4), \
++			 io[2],io[3],il,ir); \
++	CAMELLIA_ROUNDSM(io[2],io[3], \
++			 SUBKEY_L(i + 5),SUBKEY_R(i + 5), \
++			 io[0],io[1],il,ir); \
++	CAMELLIA_ROUNDSM(io[0],io[1], \
++			 SUBKEY_L(i + 6),SUBKEY_R(i + 6), \
++			 io[2],io[3],il,ir); \
++	CAMELLIA_ROUNDSM(io[2],io[3], \
++			 SUBKEY_L(i + 7),SUBKEY_R(i + 7), \
++			 io[0],io[1],il,ir); \
++} while (0)
++#define FLS(i) do { \
++	CAMELLIA_FLS(io[0],io[1],io[2],io[3], \
++		     SUBKEY_L(i + 0),SUBKEY_R(i + 0), \
++		     SUBKEY_L(i + 1),SUBKEY_R(i + 1), \
++		     t0,t1,il,ir); \
++} while (0)
++
++	ROUNDS(0);
++	FLS(8);
++	ROUNDS(8);
++	FLS(16);
++	ROUNDS(16);
++	if (max == 32) {
++		FLS(24);
++		ROUNDS(24);
++	}
+ 
+-	/* pre whitening but absorb kw2*/
+-	io[0] ^= CAMELLIA_SUBKEY_L(0);
+-	io[1] ^= CAMELLIA_SUBKEY_R(0);
 -
--		kmem_cache_free(iocontext_cachep, ioc);
--	}
--}
--EXPORT_SYMBOL(put_io_context);
+-	/* main iteration */
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--/* Called by the exitting task */
--void exit_io_context(void)
--{
--	struct io_context *ioc;
--	struct cfq_io_context *cic;
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+-		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+-		     t0,t1,il,ir);
 -
--	task_lock(current);
--	ioc = current->io_context;
--	current->io_context = NULL;
--	task_unlock(current);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--	ioc->task = NULL;
--	if (ioc->aic && ioc->aic->exit)
--		ioc->aic->exit(ioc->aic);
--	if (ioc->cic_root.rb_node != NULL) {
--		cic = rb_entry(rb_first(&ioc->cic_root), struct cfq_io_context, rb_node);
--		cic->exit(ioc);
--	}
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+-		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+-		     t0,t1,il,ir);
 -
--	put_io_context(ioc);
--}
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--/*
-- * If the current task has no IO context then create one and initialise it.
-- * Otherwise, return its existing IO context.
-- *
-- * This returned IO context doesn't have a specifically elevated refcount,
-- * but since the current task itself holds a reference, the context can be
-- * used in general code, so long as it stays within `current` context.
-- */
--static struct io_context *current_io_context(gfp_t gfp_flags, int node)
--{
--	struct task_struct *tsk = current;
--	struct io_context *ret;
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
+-		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
+-		     t0,t1,il,ir);
 -
--	ret = tsk->io_context;
--	if (likely(ret))
--		return ret;
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
+-			 io[0],io[1],il,ir,t0,t1);
++#undef ROUNDS
++#undef FLS
+ 
+ 	/* post whitening but kw4 */
+-	io[2] ^= CAMELLIA_SUBKEY_L(32);
+-	io[3] ^= CAMELLIA_SUBKEY_R(32);
 -
--	ret = kmem_cache_alloc_node(iocontext_cachep, gfp_flags, node);
--	if (ret) {
--		atomic_set(&ret->refcount, 1);
--		ret->task = current;
--		ret->ioprio_changed = 0;
--		ret->last_waited = jiffies; /* doesn't matter... */
--		ret->nr_batch_requests = 0; /* because this is 0 */
--		ret->aic = NULL;
--		ret->cic_root.rb_node = NULL;
--		ret->ioc_data = NULL;
--		/* make sure set_task_ioprio() sees the settings above */
--		smp_wmb();
--		tsk->io_context = ret;
--	}
+-	t0 = io[0];
+-	t1 = io[1];
+-	io[0] = io[2];
+-	io[1] = io[3];
+-	io[2] = t0;
+-	io[3] = t1;
 -
--	return ret;
--}
+-	io_text[0] = cpu_to_be32(io[0]);
+-	io_text[1] = cpu_to_be32(io[1]);
+-	io_text[2] = cpu_to_be32(io[2]);
+-	io_text[3] = cpu_to_be32(io[3]);
 -
--/*
-- * If the current task has no IO context then create one and initialise it.
-- * If it does have a context, take a ref on it.
-- *
-- * This is always called in the context of the task which submitted the I/O.
-- */
--struct io_context *get_io_context(gfp_t gfp_flags, int node)
--{
--	struct io_context *ret;
--	ret = current_io_context(gfp_flags, node);
--	if (likely(ret))
--		atomic_inc(&ret->refcount);
--	return ret;
--}
--EXPORT_SYMBOL(get_io_context);
+-	return;
++	io[2] ^= SUBKEY_L(max);
++	io[3] ^= SUBKEY_R(max);
++	/* NB: io[0],[1] should be swapped with [2],[3] by caller! */
+ }
+ 
 -
--void copy_io_context(struct io_context **pdst, struct io_context **psrc)
--{
--	struct io_context *src = *psrc;
--	struct io_context *dst = *pdst;
+-static void camellia_decrypt256(const u32 *subkey, __be32 *io_text)
++static void camellia_do_decrypt(const u32 *subkey, u32 *io, unsigned i)
+ {
+-	u32 il,ir,t0,t1;           /* temporary valiables */
++	u32 il,ir,t0,t1;               /* temporary variables */
+ 
+-	u32 io[4];
 -
--	if (src) {
--		BUG_ON(atomic_read(&src->refcount) == 0);
--		atomic_inc(&src->refcount);
--		put_io_context(dst);
--		*pdst = src;
--	}
--}
--EXPORT_SYMBOL(copy_io_context);
+-	io[0] = be32_to_cpu(io_text[0]);
+-	io[1] = be32_to_cpu(io_text[1]);
+-	io[2] = be32_to_cpu(io_text[2]);
+-	io[3] = be32_to_cpu(io_text[3]);
 -
--void swap_io_context(struct io_context **ioc1, struct io_context **ioc2)
--{
--	struct io_context *temp;
--	temp = *ioc1;
--	*ioc1 = *ioc2;
--	*ioc2 = temp;
--}
--EXPORT_SYMBOL(swap_io_context);
+-	/* pre whitening but absorb kw2*/
+-	io[0] ^= CAMELLIA_SUBKEY_L(32);
+-	io[1] ^= CAMELLIA_SUBKEY_R(32);
++	/* pre whitening but absorb kw2 */
++	io[0] ^= SUBKEY_L(i);
++	io[1] ^= SUBKEY_R(i);
+ 
+ 	/* main iteration */
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--/*
-- * sysfs parts below
-- */
--struct queue_sysfs_entry {
--	struct attribute attr;
--	ssize_t (*show)(struct request_queue *, char *);
--	ssize_t (*store)(struct request_queue *, const char *, size_t);
--};
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
+-		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
+-		     t0,t1,il,ir);
 -
--static ssize_t
--queue_var_show(unsigned int var, char *page)
--{
--	return sprintf(page, "%d\n", var);
--}
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--static ssize_t
--queue_var_store(unsigned long *var, const char *page, size_t count)
--{
--	char *p = (char *) page;
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
+-		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
+-		     t0,t1,il,ir);
 -
--	*var = simple_strtoul(p, &p, 10);
--	return count;
--}
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
+-			 io[0],io[1],il,ir,t0,t1);
 -
--static ssize_t queue_requests_show(struct request_queue *q, char *page)
--{
--	return queue_var_show(q->nr_requests, (page));
--}
+-	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
+-		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
+-		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
+-		     t0,t1,il,ir);
 -
--static ssize_t
--queue_requests_store(struct request_queue *q, const char *page, size_t count)
--{
--	struct request_list *rl = &q->rq;
--	unsigned long nr;
--	int ret = queue_var_store(&nr, page, count);
--	if (nr < BLKDEV_MIN_RQ)
--		nr = BLKDEV_MIN_RQ;
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
+-			 io[0],io[1],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[0],io[1],
+-			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
+-			 io[2],io[3],il,ir,t0,t1);
+-	CAMELLIA_ROUNDSM(io[2],io[3],
+-			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
+-			 io[0],io[1],il,ir,t0,t1);
++#define ROUNDS(i) do { \
++	CAMELLIA_ROUNDSM(io[0],io[1], \
++			 SUBKEY_L(i + 7),SUBKEY_R(i + 7), \
++			 io[2],io[3],il,ir); \
++	CAMELLIA_ROUNDSM(io[2],io[3], \
++			 SUBKEY_L(i + 6),SUBKEY_R(i + 6), \
++			 io[0],io[1],il,ir); \
++	CAMELLIA_ROUNDSM(io[0],io[1], \
++			 SUBKEY_L(i + 5),SUBKEY_R(i + 5), \
++			 io[2],io[3],il,ir); \
++	CAMELLIA_ROUNDSM(io[2],io[3], \
++			 SUBKEY_L(i + 4),SUBKEY_R(i + 4), \
++			 io[0],io[1],il,ir); \
++	CAMELLIA_ROUNDSM(io[0],io[1], \
++			 SUBKEY_L(i + 3),SUBKEY_R(i + 3), \
++			 io[2],io[3],il,ir); \
++	CAMELLIA_ROUNDSM(io[2],io[3], \
++			 SUBKEY_L(i + 2),SUBKEY_R(i + 2), \
++			 io[0],io[1],il,ir); \
++} while (0)
++#define FLS(i) do { \
++	CAMELLIA_FLS(io[0],io[1],io[2],io[3], \
++		     SUBKEY_L(i + 1),SUBKEY_R(i + 1), \
++		     SUBKEY_L(i + 0),SUBKEY_R(i + 0), \
++		     t0,t1,il,ir); \
++} while (0)
++
++	if (i == 32) {
++		ROUNDS(24);
++		FLS(24);
++	}
++	ROUNDS(16);
++	FLS(16);
++	ROUNDS(8);
++	FLS(8);
++	ROUNDS(0);
++
++#undef ROUNDS
++#undef FLS
+ 
+ 	/* post whitening but kw4 */
+-	io[2] ^= CAMELLIA_SUBKEY_L(0);
+-	io[3] ^= CAMELLIA_SUBKEY_R(0);
 -
--	spin_lock_irq(q->queue_lock);
--	q->nr_requests = nr;
--	blk_queue_congestion_threshold(q);
+-	t0 = io[0];
+-	t1 = io[1];
+-	io[0] = io[2];
+-	io[1] = io[3];
+-	io[2] = t0;
+-	io[3] = t1;
 -
--	if (rl->count[READ] >= queue_congestion_on_threshold(q))
--		blk_set_queue_congested(q, READ);
--	else if (rl->count[READ] < queue_congestion_off_threshold(q))
--		blk_clear_queue_congested(q, READ);
+-	io_text[0] = cpu_to_be32(io[0]);
+-	io_text[1] = cpu_to_be32(io[1]);
+-	io_text[2] = cpu_to_be32(io[2]);
+-	io_text[3] = cpu_to_be32(io[3]);
 -
--	if (rl->count[WRITE] >= queue_congestion_on_threshold(q))
--		blk_set_queue_congested(q, WRITE);
--	else if (rl->count[WRITE] < queue_congestion_off_threshold(q))
--		blk_clear_queue_congested(q, WRITE);
+-	return;
++	io[2] ^= SUBKEY_L(0);
++	io[3] ^= SUBKEY_R(0);
++	/* NB: 0,1 should be swapped with 2,3 by caller! */
+ }
+ 
+ 
++struct camellia_ctx {
++	int key_length;
++	u32 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u32)];
++};
++
+ static int
+ camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 		 unsigned int key_len)
+@@ -1688,7 +1027,7 @@ camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 
+ 	cctx->key_length = key_len;
+ 
+-	switch(key_len) {
++	switch (key_len) {
+ 	case 16:
+ 		camellia_setup128(key, cctx->key_table);
+ 		break;
+@@ -1698,68 +1037,59 @@ camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ 	case 32:
+ 		camellia_setup256(key, cctx->key_table);
+ 		break;
+-	default:
+-		break;
+ 	}
+ 
+ 	return 0;
+ }
+ 
 -
--	if (rl->count[READ] >= q->nr_requests) {
--		blk_set_queue_full(q, READ);
--	} else if (rl->count[READ]+1 <= q->nr_requests) {
--		blk_clear_queue_full(q, READ);
--		wake_up(&rl->wait[READ]);
+ static void camellia_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+ 	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+ 	const __be32 *src = (const __be32 *)in;
+ 	__be32 *dst = (__be32 *)out;
+ 
+-	__be32 tmp[4];
++	u32 tmp[4];
+ 
+-	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
++	tmp[0] = be32_to_cpu(src[0]);
++	tmp[1] = be32_to_cpu(src[1]);
++	tmp[2] = be32_to_cpu(src[2]);
++	tmp[3] = be32_to_cpu(src[3]);
+ 
+-	switch (cctx->key_length) {
+-	case 16:
+-		camellia_encrypt128(cctx->key_table, tmp);
+-		break;
+-	case 24:
+-		/* fall through */
+-	case 32:
+-		camellia_encrypt256(cctx->key_table, tmp);
+-		break;
+-	default:
+-		break;
 -	}
++	camellia_do_encrypt(cctx->key_table, tmp,
++		cctx->key_length == 16 ? 24 : 32 /* for key lengths of 24 and 32 */
++	);
+ 
+-	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
++	/* do_encrypt returns 0,1 swapped with 2,3 */
++	dst[0] = cpu_to_be32(tmp[2]);
++	dst[1] = cpu_to_be32(tmp[3]);
++	dst[2] = cpu_to_be32(tmp[0]);
++	dst[3] = cpu_to_be32(tmp[1]);
+ }
+ 
 -
--	if (rl->count[WRITE] >= q->nr_requests) {
--		blk_set_queue_full(q, WRITE);
--	} else if (rl->count[WRITE]+1 <= q->nr_requests) {
--		blk_clear_queue_full(q, WRITE);
--		wake_up(&rl->wait[WRITE]);
+ static void camellia_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+ 	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
+ 	const __be32 *src = (const __be32 *)in;
+ 	__be32 *dst = (__be32 *)out;
+ 
+-	__be32 tmp[4];
++	u32 tmp[4];
+ 
+-	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
++	tmp[0] = be32_to_cpu(src[0]);
++	tmp[1] = be32_to_cpu(src[1]);
++	tmp[2] = be32_to_cpu(src[2]);
++	tmp[3] = be32_to_cpu(src[3]);
+ 
+-	switch (cctx->key_length) {
+-	case 16:
+-		camellia_decrypt128(cctx->key_table, tmp);
+-		break;
+-	case 24:
+-		/* fall through */
+-	case 32:
+-		camellia_decrypt256(cctx->key_table, tmp);
+-		break;
+-	default:
+-		break;
 -	}
--	spin_unlock_irq(q->queue_lock);
--	return ret;
--}
--
--static ssize_t queue_ra_show(struct request_queue *q, char *page)
--{
--	int ra_kb = q->backing_dev_info.ra_pages << (PAGE_CACHE_SHIFT - 10);
--
--	return queue_var_show(ra_kb, (page));
--}
--
--static ssize_t
--queue_ra_store(struct request_queue *q, const char *page, size_t count)
--{
--	unsigned long ra_kb;
--	ssize_t ret = queue_var_store(&ra_kb, page, count);
++	camellia_do_decrypt(cctx->key_table, tmp,
++		cctx->key_length == 16 ? 24 : 32 /* for key lengths of 24 and 32 */
++	);
+ 
+-	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
++	/* do_decrypt returns 0,1 swapped with 2,3 */
++	dst[0] = cpu_to_be32(tmp[2]);
++	dst[1] = cpu_to_be32(tmp[3]);
++	dst[2] = cpu_to_be32(tmp[0]);
++	dst[3] = cpu_to_be32(tmp[1]);
+ }
+ 
 -
--	spin_lock_irq(q->queue_lock);
--	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_CACHE_SHIFT - 10);
--	spin_unlock_irq(q->queue_lock);
+ static struct crypto_alg camellia_alg = {
+ 	.cra_name		=	"camellia",
+ 	.cra_driver_name	=	"camellia-generic",
+@@ -1786,16 +1116,13 @@ static int __init camellia_init(void)
+ 	return crypto_register_alg(&camellia_alg);
+ }
+ 
 -
--	return ret;
--}
+ static void __exit camellia_fini(void)
+ {
+ 	crypto_unregister_alg(&camellia_alg);
+ }
+ 
 -
--static ssize_t queue_max_sectors_show(struct request_queue *q, char *page)
--{
--	int max_sectors_kb = q->max_sectors >> 1;
+ module_init(camellia_init);
+ module_exit(camellia_fini);
+ 
 -
--	return queue_var_show(max_sectors_kb, (page));
--}
+ MODULE_DESCRIPTION("Camellia Cipher Algorithm");
+ MODULE_LICENSE("GPL");
+diff --git a/crypto/cast6.c b/crypto/cast6.c
+index 136ab6d..5fd9420 100644
+--- a/crypto/cast6.c
++++ b/crypto/cast6.c
+@@ -369,7 +369,7 @@ static const u8 Tr[4][8] = {
+ };
+ 
+ /* forward octave */
+-static inline void W(u32 *key, unsigned int i) {
++static void W(u32 *key, unsigned int i) {
+ 	u32 I;
+ 	key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
+ 	key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
+@@ -428,7 +428,7 @@ static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key,
+ }
+ 
+ /*forward quad round*/
+-static inline void Q (u32 * block, u8 * Kr, u32 * Km) {
++static void Q (u32 * block, u8 * Kr, u32 * Km) {
+ 	u32 I;
+ 	block[2] ^= F1(block[3], Kr[0], Km[0]);
+ 	block[1] ^= F2(block[2], Kr[1], Km[1]);
+@@ -437,7 +437,7 @@ static inline void Q (u32 * block, u8 * Kr, u32 * Km) {
+ }
+ 
+ /*reverse quad round*/
+-static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) {
++static void QBAR (u32 * block, u8 * Kr, u32 * Km) {
+ 	u32 I;
+         block[3] ^= F1(block[0], Kr[3], Km[3]);
+         block[0] ^= F3(block[1], Kr[2], Km[2]);
+diff --git a/crypto/cbc.c b/crypto/cbc.c
+index 1f2649e..6affff8 100644
+--- a/crypto/cbc.c
++++ b/crypto/cbc.c
+@@ -14,13 +14,13 @@
+ #include <linux/err.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
++#include <linux/log2.h>
+ #include <linux/module.h>
+ #include <linux/scatterlist.h>
+ #include <linux/slab.h>
+ 
+ struct crypto_cbc_ctx {
+ 	struct crypto_cipher *child;
+-	void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
+ };
+ 
+ static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
+@@ -41,9 +41,7 @@ static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
+ 
+ static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
+ 				      struct blkcipher_walk *walk,
+-				      struct crypto_cipher *tfm,
+-				      void (*xor)(u8 *, const u8 *,
+-						  unsigned int))
++				      struct crypto_cipher *tfm)
+ {
+ 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+ 		crypto_cipher_alg(tfm)->cia_encrypt;
+@@ -54,7 +52,7 @@ static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
+ 	u8 *iv = walk->iv;
+ 
+ 	do {
+-		xor(iv, src, bsize);
++		crypto_xor(iv, src, bsize);
+ 		fn(crypto_cipher_tfm(tfm), dst, iv);
+ 		memcpy(iv, dst, bsize);
+ 
+@@ -67,9 +65,7 @@ static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
+ 
+ static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc,
+ 				      struct blkcipher_walk *walk,
+-				      struct crypto_cipher *tfm,
+-				      void (*xor)(u8 *, const u8 *,
+-						  unsigned int))
++				      struct crypto_cipher *tfm)
+ {
+ 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+ 		crypto_cipher_alg(tfm)->cia_encrypt;
+@@ -79,7 +75,7 @@ static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc,
+ 	u8 *iv = walk->iv;
+ 
+ 	do {
+-		xor(src, iv, bsize);
++		crypto_xor(src, iv, bsize);
+ 		fn(crypto_cipher_tfm(tfm), src, src);
+ 		iv = src;
+ 
+@@ -99,7 +95,6 @@ static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
+ 	struct crypto_blkcipher *tfm = desc->tfm;
+ 	struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ 	struct crypto_cipher *child = ctx->child;
+-	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
+ 	int err;
+ 
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+@@ -107,11 +102,9 @@ static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
+ 
+ 	while ((nbytes = walk.nbytes)) {
+ 		if (walk.src.virt.addr == walk.dst.virt.addr)
+-			nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child,
+-							    xor);
++			nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child);
+ 		else
+-			nbytes = crypto_cbc_encrypt_segment(desc, &walk, child,
+-							    xor);
++			nbytes = crypto_cbc_encrypt_segment(desc, &walk, child);
+ 		err = blkcipher_walk_done(desc, &walk, nbytes);
+ 	}
+ 
+@@ -120,9 +113,7 @@ static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
+ 
+ static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
+ 				      struct blkcipher_walk *walk,
+-				      struct crypto_cipher *tfm,
+-				      void (*xor)(u8 *, const u8 *,
+-						  unsigned int))
++				      struct crypto_cipher *tfm)
+ {
+ 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+ 		crypto_cipher_alg(tfm)->cia_decrypt;
+@@ -134,7 +125,7 @@ static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
+ 
+ 	do {
+ 		fn(crypto_cipher_tfm(tfm), dst, src);
+-		xor(dst, iv, bsize);
++		crypto_xor(dst, iv, bsize);
+ 		iv = src;
+ 
+ 		src += bsize;
+@@ -148,34 +139,29 @@ static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
+ 
+ static int crypto_cbc_decrypt_inplace(struct blkcipher_desc *desc,
+ 				      struct blkcipher_walk *walk,
+-				      struct crypto_cipher *tfm,
+-				      void (*xor)(u8 *, const u8 *,
+-						  unsigned int))
++				      struct crypto_cipher *tfm)
+ {
+ 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
+ 		crypto_cipher_alg(tfm)->cia_decrypt;
+ 	int bsize = crypto_cipher_blocksize(tfm);
+-	unsigned long alignmask = crypto_cipher_alignmask(tfm);
+ 	unsigned int nbytes = walk->nbytes;
+ 	u8 *src = walk->src.virt.addr;
+-	u8 stack[bsize + alignmask];
+-	u8 *first_iv = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
 -
--static ssize_t
--queue_max_sectors_store(struct request_queue *q, const char *page, size_t count)
+-	memcpy(first_iv, walk->iv, bsize);
++	u8 last_iv[bsize];
+ 
+ 	/* Start of the last block. */
+-	src += nbytes - nbytes % bsize - bsize;
+-	memcpy(walk->iv, src, bsize);
++	src += nbytes - (nbytes & (bsize - 1)) - bsize;
++	memcpy(last_iv, src, bsize);
+ 
+ 	for (;;) {
+ 		fn(crypto_cipher_tfm(tfm), src, src);
+ 		if ((nbytes -= bsize) < bsize)
+ 			break;
+-		xor(src, src - bsize, bsize);
++		crypto_xor(src, src - bsize, bsize);
+ 		src -= bsize;
+ 	}
+ 
+-	xor(src, first_iv, bsize);
++	crypto_xor(src, walk->iv, bsize);
++	memcpy(walk->iv, last_iv, bsize);
+ 
+ 	return nbytes;
+ }
+@@ -188,7 +174,6 @@ static int crypto_cbc_decrypt(struct blkcipher_desc *desc,
+ 	struct crypto_blkcipher *tfm = desc->tfm;
+ 	struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ 	struct crypto_cipher *child = ctx->child;
+-	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
+ 	int err;
+ 
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+@@ -196,48 +181,15 @@ static int crypto_cbc_decrypt(struct blkcipher_desc *desc,
+ 
+ 	while ((nbytes = walk.nbytes)) {
+ 		if (walk.src.virt.addr == walk.dst.virt.addr)
+-			nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child,
+-							    xor);
++			nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child);
+ 		else
+-			nbytes = crypto_cbc_decrypt_segment(desc, &walk, child,
+-							    xor);
++			nbytes = crypto_cbc_decrypt_segment(desc, &walk, child);
+ 		err = blkcipher_walk_done(desc, &walk, nbytes);
+ 	}
+ 
+ 	return err;
+ }
+ 
+-static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
 -{
--	unsigned long max_sectors_kb,
--			max_hw_sectors_kb = q->max_hw_sectors >> 1,
--			page_kb = 1 << (PAGE_CACHE_SHIFT - 10);
--	ssize_t ret = queue_var_store(&max_sectors_kb, page, count);
--
--	if (max_sectors_kb > max_hw_sectors_kb || max_sectors_kb < page_kb)
--		return -EINVAL;
--	/*
--	 * Take the queue lock to update the readahead and max_sectors
--	 * values synchronously:
--	 */
--	spin_lock_irq(q->queue_lock);
--	q->max_sectors = max_sectors_kb << 1;
--	spin_unlock_irq(q->queue_lock);
--
--	return ret;
+-	do {
+-		*a++ ^= *b++;
+-	} while (--bs);
 -}
 -
--static ssize_t queue_max_hw_sectors_show(struct request_queue *q, char *page)
+-static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
 -{
--	int max_hw_sectors_kb = q->max_hw_sectors >> 1;
+-	u32 *a = (u32 *)dst;
+-	u32 *b = (u32 *)src;
 -
--	return queue_var_show(max_hw_sectors_kb, (page));
+-	do {
+-		*a++ ^= *b++;
+-	} while ((bs -= 4));
 -}
 -
--
--static struct queue_sysfs_entry queue_requests_entry = {
--	.attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
--	.show = queue_requests_show,
--	.store = queue_requests_store,
--};
--
--static struct queue_sysfs_entry queue_ra_entry = {
--	.attr = {.name = "read_ahead_kb", .mode = S_IRUGO | S_IWUSR },
--	.show = queue_ra_show,
--	.store = queue_ra_store,
--};
--
--static struct queue_sysfs_entry queue_max_sectors_entry = {
--	.attr = {.name = "max_sectors_kb", .mode = S_IRUGO | S_IWUSR },
--	.show = queue_max_sectors_show,
--	.store = queue_max_sectors_store,
--};
--
--static struct queue_sysfs_entry queue_max_hw_sectors_entry = {
--	.attr = {.name = "max_hw_sectors_kb", .mode = S_IRUGO },
--	.show = queue_max_hw_sectors_show,
--};
--
--static struct queue_sysfs_entry queue_iosched_entry = {
--	.attr = {.name = "scheduler", .mode = S_IRUGO | S_IWUSR },
--	.show = elv_iosched_show,
--	.store = elv_iosched_store,
--};
--
--static struct attribute *default_attrs[] = {
--	&queue_requests_entry.attr,
--	&queue_ra_entry.attr,
--	&queue_max_hw_sectors_entry.attr,
--	&queue_max_sectors_entry.attr,
--	&queue_iosched_entry.attr,
--	NULL,
--};
--
--#define to_queue(atr) container_of((atr), struct queue_sysfs_entry, attr)
--
--static ssize_t
--queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+-static void xor_64(u8 *a, const u8 *b, unsigned int bs)
 -{
--	struct queue_sysfs_entry *entry = to_queue(attr);
--	struct request_queue *q =
--		container_of(kobj, struct request_queue, kobj);
--	ssize_t res;
--
--	if (!entry->show)
--		return -EIO;
--	mutex_lock(&q->sysfs_lock);
--	if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
--		mutex_unlock(&q->sysfs_lock);
--		return -ENOENT;
--	}
--	res = entry->show(q, page);
--	mutex_unlock(&q->sysfs_lock);
--	return res;
+-	((u32 *)a)[0] ^= ((u32 *)b)[0];
+-	((u32 *)a)[1] ^= ((u32 *)b)[1];
 -}
 -
--static ssize_t
--queue_attr_store(struct kobject *kobj, struct attribute *attr,
--		    const char *page, size_t length)
+-static void xor_128(u8 *a, const u8 *b, unsigned int bs)
 -{
--	struct queue_sysfs_entry *entry = to_queue(attr);
--	struct request_queue *q = container_of(kobj, struct request_queue, kobj);
--
--	ssize_t res;
--
--	if (!entry->store)
--		return -EIO;
--	mutex_lock(&q->sysfs_lock);
--	if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
--		mutex_unlock(&q->sysfs_lock);
--		return -ENOENT;
--	}
--	res = entry->store(q, page, length);
--	mutex_unlock(&q->sysfs_lock);
--	return res;
+-	((u32 *)a)[0] ^= ((u32 *)b)[0];
+-	((u32 *)a)[1] ^= ((u32 *)b)[1];
+-	((u32 *)a)[2] ^= ((u32 *)b)[2];
+-	((u32 *)a)[3] ^= ((u32 *)b)[3];
 -}
 -
--static struct sysfs_ops queue_sysfs_ops = {
--	.show	= queue_attr_show,
--	.store	= queue_attr_store,
--};
--
--static struct kobj_type queue_ktype = {
--	.sysfs_ops	= &queue_sysfs_ops,
--	.default_attrs	= default_attrs,
--	.release	= blk_release_queue,
--};
--
--int blk_register_queue(struct gendisk *disk)
--{
--	int ret;
--
--	struct request_queue *q = disk->queue;
--
--	if (!q || !q->request_fn)
--		return -ENXIO;
--
--	q->kobj.parent = kobject_get(&disk->kobj);
--
--	ret = kobject_add(&q->kobj);
--	if (ret < 0)
--		return ret;
+ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
+ {
+ 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
+@@ -245,22 +197,6 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
+ 	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+ 	struct crypto_cipher *cipher;
+ 
+-	switch (crypto_tfm_alg_blocksize(tfm)) {
+-	case 8:
+-		ctx->xor = xor_64;
+-		break;
 -
--	kobject_uevent(&q->kobj, KOBJ_ADD);
+-	case 16:
+-		ctx->xor = xor_128;
+-		break;
 -
--	ret = elv_register_queue(q);
--	if (ret) {
--		kobject_uevent(&q->kobj, KOBJ_REMOVE);
--		kobject_del(&q->kobj);
--		return ret;
+-	default:
+-		if (crypto_tfm_alg_blocksize(tfm) % 4)
+-			ctx->xor = xor_byte;
+-		else
+-			ctx->xor = xor_quad;
 -	}
 -
--	return 0;
--}
--
--void blk_unregister_queue(struct gendisk *disk)
--{
--	struct request_queue *q = disk->queue;
--
--	if (q && q->request_fn) {
--		elv_unregister_queue(q);
--
--		kobject_uevent(&q->kobj, KOBJ_REMOVE);
--		kobject_del(&q->kobj);
--		kobject_put(&disk->kobj);
--	}
--}
-diff --git a/crypto/Kconfig b/crypto/Kconfig
-index 083d2e1..c3166a1 100644
---- a/crypto/Kconfig
-+++ b/crypto/Kconfig
-@@ -24,10 +24,6 @@ config CRYPTO_ALGAPI
- 	help
- 	  This option provides the API for cryptographic algorithms.
+ 	cipher = crypto_spawn_cipher(spawn);
+ 	if (IS_ERR(cipher))
+ 		return PTR_ERR(cipher);
+@@ -290,6 +226,10 @@ static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
+ 	if (IS_ERR(alg))
+ 		return ERR_PTR(PTR_ERR(alg));
  
--config CRYPTO_ABLKCIPHER
--	tristate
--	select CRYPTO_BLKCIPHER
--
- config CRYPTO_AEAD
- 	tristate
- 	select CRYPTO_ALGAPI
-@@ -36,6 +32,15 @@ config CRYPTO_BLKCIPHER
- 	tristate
- 	select CRYPTO_ALGAPI
++	inst = ERR_PTR(-EINVAL);
++	if (!is_power_of_2(alg->cra_blocksize))
++		goto out_put_alg;
++
+ 	inst = crypto_alloc_instance("cbc", alg);
+ 	if (IS_ERR(inst))
+ 		goto out_put_alg;
+@@ -300,8 +240,9 @@ static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
+ 	inst->alg.cra_alignmask = alg->cra_alignmask;
+ 	inst->alg.cra_type = &crypto_blkcipher_type;
  
-+config CRYPTO_SEQIV
-+	tristate "Sequence Number IV Generator"
-+	select CRYPTO_AEAD
-+	select CRYPTO_BLKCIPHER
-+	help
-+	  This IV generator generates an IV based on a sequence number by
-+	  xoring it with a salt.  This algorithm is mainly useful for CTR
-+	  and similar modes.
+-	if (!(alg->cra_blocksize % 4))
+-		inst->alg.cra_alignmask |= 3;
++	/* We access the data as u32s when xoring. */
++	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
++
+ 	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
+ 	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
+ 	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
+diff --git a/crypto/ccm.c b/crypto/ccm.c
+new file mode 100644
+index 0000000..7cf7e5a
+--- /dev/null
++++ b/crypto/ccm.c
+@@ -0,0 +1,889 @@
++/*
++ * CCM: Counter with CBC-MAC
++ *
++ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten at us.ibm.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.
++ *
++ */
++
++#include <crypto/internal/aead.h>
++#include <crypto/internal/skcipher.h>
++#include <crypto/scatterwalk.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++
++#include "internal.h"
++
++struct ccm_instance_ctx {
++	struct crypto_skcipher_spawn ctr;
++	struct crypto_spawn cipher;
++};
++
++struct crypto_ccm_ctx {
++	struct crypto_cipher *cipher;
++	struct crypto_ablkcipher *ctr;
++};
++
++struct crypto_rfc4309_ctx {
++	struct crypto_aead *child;
++	u8 nonce[3];
++};
++
++struct crypto_ccm_req_priv_ctx {
++	u8 odata[16];
++	u8 idata[16];
++	u8 auth_tag[16];
++	u32 ilen;
++	u32 flags;
++	struct scatterlist src[2];
++	struct scatterlist dst[2];
++	struct ablkcipher_request abreq;
++};
++
++static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
++	struct aead_request *req)
++{
++	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
++
++	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
++}
++
++static int set_msg_len(u8 *block, unsigned int msglen, int csize)
++{
++	__be32 data;
++
++	memset(block, 0, csize);
++	block += csize;
++
++	if (csize >= 4)
++		csize = 4;
++	else if (msglen > (1 << (8 * csize)))
++		return -EOVERFLOW;
++
++	data = cpu_to_be32(msglen);
++	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
++
++	return 0;
++}
++
++static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
++			     unsigned int keylen)
++{
++	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_ablkcipher *ctr = ctx->ctr;
++	struct crypto_cipher *tfm = ctx->cipher;
++	int err = 0;
++
++	crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
++	crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
++				    CRYPTO_TFM_REQ_MASK);
++	err = crypto_ablkcipher_setkey(ctr, key, keylen);
++	crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
++			      CRYPTO_TFM_RES_MASK);
++	if (err)
++		goto out;
++
++	crypto_cipher_clear_flags(tfm, CRYPTO_TFM_REQ_MASK);
++	crypto_cipher_set_flags(tfm, crypto_aead_get_flags(aead) &
++				    CRYPTO_TFM_REQ_MASK);
++	err = crypto_cipher_setkey(tfm, key, keylen);
++	crypto_aead_set_flags(aead, crypto_cipher_get_flags(tfm) &
++			      CRYPTO_TFM_RES_MASK);
++
++out:
++	return err;
++}
++
++static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
++				  unsigned int authsize)
++{
++	switch (authsize) {
++	case 4:
++	case 6:
++	case 8:
++	case 10:
++	case 12:
++	case 14:
++	case 16:
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return 0;
++}
++
++static int format_input(u8 *info, struct aead_request *req,
++			unsigned int cryptlen)
++{
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	unsigned int lp = req->iv[0];
++	unsigned int l = lp + 1;
++	unsigned int m;
++
++	m = crypto_aead_authsize(aead);
++
++	memcpy(info, req->iv, 16);
++
++	/* format control info per RFC 3610 and
++	 * NIST Special Publication 800-38C
++	 */
++	*info |= (8 * ((m - 2) / 2));
++	if (req->assoclen)
++		*info |= 64;
++
++	return set_msg_len(info + 16 - l, cryptlen, l);
++}
++
++static int format_adata(u8 *adata, unsigned int a)
++{
++	int len = 0;
++
++	/* add control info for associated data
++	 * RFC 3610 and NIST Special Publication 800-38C
++	 */
++	if (a < 65280) {
++		*(__be16 *)adata = cpu_to_be16(a);
++		len = 2;
++	} else  {
++		*(__be16 *)adata = cpu_to_be16(0xfffe);
++		*(__be32 *)&adata[2] = cpu_to_be32(a);
++		len = 6;
++	}
++
++	return len;
++}
++
++static void compute_mac(struct crypto_cipher *tfm, u8 *data, int n,
++		       struct crypto_ccm_req_priv_ctx *pctx)
++{
++	unsigned int bs = 16;
++	u8 *odata = pctx->odata;
++	u8 *idata = pctx->idata;
++	int datalen, getlen;
++
++	datalen = n;
++
++	/* first time in here, block may be partially filled. */
++	getlen = bs - pctx->ilen;
++	if (datalen >= getlen) {
++		memcpy(idata + pctx->ilen, data, getlen);
++		crypto_xor(odata, idata, bs);
++		crypto_cipher_encrypt_one(tfm, odata, odata);
++		datalen -= getlen;
++		data += getlen;
++		pctx->ilen = 0;
++	}
++
++	/* now encrypt rest of data */
++	while (datalen >= bs) {
++		crypto_xor(odata, data, bs);
++		crypto_cipher_encrypt_one(tfm, odata, odata);
++
++		datalen -= bs;
++		data += bs;
++	}
++
++	/* check and see if there's leftover data that wasn't
++	 * enough to fill a block.
++	 */
++	if (datalen) {
++		memcpy(idata + pctx->ilen, data, datalen);
++		pctx->ilen += datalen;
++	}
++}
++
++static void get_data_to_compute(struct crypto_cipher *tfm,
++			       struct crypto_ccm_req_priv_ctx *pctx,
++			       struct scatterlist *sg, unsigned int len)
++{
++	struct scatter_walk walk;
++	u8 *data_src;
++	int n;
++
++	scatterwalk_start(&walk, sg);
++
++	while (len) {
++		n = scatterwalk_clamp(&walk, len);
++		if (!n) {
++			scatterwalk_start(&walk, sg_next(walk.sg));
++			n = scatterwalk_clamp(&walk, len);
++		}
++		data_src = scatterwalk_map(&walk, 0);
++
++		compute_mac(tfm, data_src, n, pctx);
++		len -= n;
++
++		scatterwalk_unmap(data_src, 0);
++		scatterwalk_advance(&walk, n);
++		scatterwalk_done(&walk, 0, len);
++		if (len)
++			crypto_yield(pctx->flags);
++	}
++
++	/* any leftover needs padding and then encrypted */
++	if (pctx->ilen) {
++		int padlen;
++		u8 *odata = pctx->odata;
++		u8 *idata = pctx->idata;
++
++		padlen = 16 - pctx->ilen;
++		memset(idata + pctx->ilen, 0, padlen);
++		crypto_xor(odata, idata, 16);
++		crypto_cipher_encrypt_one(tfm, odata, odata);
++		pctx->ilen = 0;
++	}
++}
++
++static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
++			   unsigned int cryptlen)
++{
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
++	struct crypto_cipher *cipher = ctx->cipher;
++	unsigned int assoclen = req->assoclen;
++	u8 *odata = pctx->odata;
++	u8 *idata = pctx->idata;
++	int err;
++
++	/* format control data for input */
++	err = format_input(odata, req, cryptlen);
++	if (err)
++		goto out;
++
++	/* encrypt first block to use as start in computing mac  */
++	crypto_cipher_encrypt_one(cipher, odata, odata);
++
++	/* format associated data and compute into mac */
++	if (assoclen) {
++		pctx->ilen = format_adata(idata, assoclen);
++		get_data_to_compute(cipher, pctx, req->assoc, req->assoclen);
++	}
++
++	/* compute plaintext into mac */
++	get_data_to_compute(cipher, pctx, plain, cryptlen);
++
++out:
++	return err;
++}
++
++static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
++{
++	struct aead_request *req = areq->data;
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
++	u8 *odata = pctx->odata;
++
++	if (!err)
++		scatterwalk_map_and_copy(odata, req->dst, req->cryptlen,
++					 crypto_aead_authsize(aead), 1);
++	aead_request_complete(req, err);
++}
++
++static inline int crypto_ccm_check_iv(const u8 *iv)
++{
++	/* 2 <= L <= 8, so 1 <= L' <= 7. */
++	if (1 > iv[0] || iv[0] > 7)
++		return -EINVAL;
++
++	return 0;
++}
++
++static int crypto_ccm_encrypt(struct aead_request *req)
++{
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
++	struct ablkcipher_request *abreq = &pctx->abreq;
++	struct scatterlist *dst;
++	unsigned int cryptlen = req->cryptlen;
++	u8 *odata = pctx->odata;
++	u8 *iv = req->iv;
++	int err;
++
++	err = crypto_ccm_check_iv(iv);
++	if (err)
++		return err;
++
++	pctx->flags = aead_request_flags(req);
++
++	err = crypto_ccm_auth(req, req->src, cryptlen);
++	if (err)
++		return err;
++
++	 /* Note: rfc 3610 and NIST 800-38C require counter of
++	 * zero to encrypt auth tag.
++	 */
++	memset(iv + 15 - iv[0], 0, iv[0] + 1);
++
++	sg_init_table(pctx->src, 2);
++	sg_set_buf(pctx->src, odata, 16);
++	scatterwalk_sg_chain(pctx->src, 2, req->src);
++
++	dst = pctx->src;
++	if (req->src != req->dst) {
++		sg_init_table(pctx->dst, 2);
++		sg_set_buf(pctx->dst, odata, 16);
++		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
++		dst = pctx->dst;
++	}
++
++	ablkcipher_request_set_tfm(abreq, ctx->ctr);
++	ablkcipher_request_set_callback(abreq, pctx->flags,
++					crypto_ccm_encrypt_done, req);
++	ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
++	err = crypto_ablkcipher_encrypt(abreq);
++	if (err)
++		return err;
++
++	/* copy authtag to end of dst */
++	scatterwalk_map_and_copy(odata, req->dst, cryptlen,
++				 crypto_aead_authsize(aead), 1);
++	return err;
++}
++
++static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
++				   int err)
++{
++	struct aead_request *req = areq->data;
++	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	unsigned int authsize = crypto_aead_authsize(aead);
++	unsigned int cryptlen = req->cryptlen - authsize;
++
++	if (!err) {
++		err = crypto_ccm_auth(req, req->dst, cryptlen);
++		if (!err && memcmp(pctx->auth_tag, pctx->odata, authsize))
++			err = -EBADMSG;
++	}
++	aead_request_complete(req, err);
++}
++
++static int crypto_ccm_decrypt(struct aead_request *req)
++{
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
++	struct ablkcipher_request *abreq = &pctx->abreq;
++	struct scatterlist *dst;
++	unsigned int authsize = crypto_aead_authsize(aead);
++	unsigned int cryptlen = req->cryptlen;
++	u8 *authtag = pctx->auth_tag;
++	u8 *odata = pctx->odata;
++	u8 *iv = req->iv;
++	int err;
 +
- config CRYPTO_HASH
- 	tristate
- 	select CRYPTO_ALGAPI
-@@ -91,7 +96,7 @@ config CRYPTO_SHA1
- 	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
- 
- config CRYPTO_SHA256
--	tristate "SHA256 digest algorithm"
-+	tristate "SHA224 and SHA256 digest algorithm"
- 	select CRYPTO_ALGAPI
- 	help
- 	  SHA256 secure hash standard (DFIPS 180-2).
-@@ -99,6 +104,9 @@ config CRYPTO_SHA256
- 	  This version of SHA implements a 256 bit hash with 128 bits of
- 	  security against collision attacks.
- 
-+          This code also includes SHA-224, a 224 bit hash with 112 bits
-+          of security against collision attacks.
++	if (cryptlen < authsize)
++		return -EINVAL;
++	cryptlen -= authsize;
 +
- config CRYPTO_SHA512
- 	tristate "SHA384 and SHA512 digest algorithms"
- 	select CRYPTO_ALGAPI
-@@ -195,9 +203,34 @@ config CRYPTO_XTS
- 	  key size 256, 384 or 512 bits. This implementation currently
- 	  can't handle a sectorsize which is not a multiple of 16 bytes.
- 
-+config CRYPTO_CTR
-+	tristate "CTR support"
-+	select CRYPTO_BLKCIPHER
-+	select CRYPTO_SEQIV
-+	select CRYPTO_MANAGER
-+	help
-+	  CTR: Counter mode
-+	  This block cipher algorithm is required for IPSec.
++	err = crypto_ccm_check_iv(iv);
++	if (err)
++		return err;
 +
-+config CRYPTO_GCM
-+	tristate "GCM/GMAC support"
-+	select CRYPTO_CTR
-+	select CRYPTO_AEAD
-+	select CRYPTO_GF128MUL
-+	help
-+	  Support for Galois/Counter Mode (GCM) and Galois Message
-+	  Authentication Code (GMAC). Required for IPSec.
++	pctx->flags = aead_request_flags(req);
 +
-+config CRYPTO_CCM
-+	tristate "CCM support"
-+	select CRYPTO_CTR
-+	select CRYPTO_AEAD
-+	help
-+	  Support for Counter with CBC MAC. Required for IPsec.
++	scatterwalk_map_and_copy(authtag, req->src, cryptlen, authsize, 0);
 +
- config CRYPTO_CRYPTD
- 	tristate "Software async crypto daemon"
--	select CRYPTO_ABLKCIPHER
-+	select CRYPTO_BLKCIPHER
- 	select CRYPTO_MANAGER
- 	help
- 	  This is a generic software asynchronous crypto daemon that
-@@ -320,6 +353,7 @@ config CRYPTO_AES_586
- 	tristate "AES cipher algorithms (i586)"
- 	depends on (X86 || UML_X86) && !64BIT
- 	select CRYPTO_ALGAPI
-+	select CRYPTO_AES
- 	help
- 	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
- 	  algorithm.
-@@ -341,6 +375,7 @@ config CRYPTO_AES_X86_64
- 	tristate "AES cipher algorithms (x86_64)"
- 	depends on (X86 || UML_X86) && 64BIT
- 	select CRYPTO_ALGAPI
-+	select CRYPTO_AES
- 	help
- 	  AES cipher algorithms (FIPS-197). AES uses the Rijndael 
- 	  algorithm.
-@@ -441,6 +476,46 @@ config CRYPTO_SEED
- 	  See also:
- 	  <http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp>
- 
-+config CRYPTO_SALSA20
-+	tristate "Salsa20 stream cipher algorithm (EXPERIMENTAL)"
-+	depends on EXPERIMENTAL
-+	select CRYPTO_BLKCIPHER
-+	help
-+	  Salsa20 stream cipher algorithm.
++	memset(iv + 15 - iv[0], 0, iv[0] + 1);
 +
-+	  Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
-+	  Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
++	sg_init_table(pctx->src, 2);
++	sg_set_buf(pctx->src, authtag, 16);
++	scatterwalk_sg_chain(pctx->src, 2, req->src);
 +
-+	  The Salsa20 stream cipher algorithm is designed by Daniel J.
-+	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
++	dst = pctx->src;
++	if (req->src != req->dst) {
++		sg_init_table(pctx->dst, 2);
++		sg_set_buf(pctx->dst, authtag, 16);
++		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
++		dst = pctx->dst;
++	}
 +
-+config CRYPTO_SALSA20_586
-+	tristate "Salsa20 stream cipher algorithm (i586) (EXPERIMENTAL)"
-+	depends on (X86 || UML_X86) && !64BIT
-+	depends on EXPERIMENTAL
-+	select CRYPTO_BLKCIPHER
-+	help
-+	  Salsa20 stream cipher algorithm.
++	ablkcipher_request_set_tfm(abreq, ctx->ctr);
++	ablkcipher_request_set_callback(abreq, pctx->flags,
++					crypto_ccm_decrypt_done, req);
++	ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
++	err = crypto_ablkcipher_decrypt(abreq);
++	if (err)
++		return err;
 +
-+	  Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
-+	  Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
++	err = crypto_ccm_auth(req, req->dst, cryptlen);
++	if (err)
++		return err;
 +
-+	  The Salsa20 stream cipher algorithm is designed by Daniel J.
-+	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
++	/* verify */
++	if (memcmp(authtag, odata, authsize))
++		return -EBADMSG;
 +
-+config CRYPTO_SALSA20_X86_64
-+	tristate "Salsa20 stream cipher algorithm (x86_64) (EXPERIMENTAL)"
-+	depends on (X86 || UML_X86) && 64BIT
-+	depends on EXPERIMENTAL
-+	select CRYPTO_BLKCIPHER
-+	help
-+	  Salsa20 stream cipher algorithm.
++	return err;
++}
 +
-+	  Salsa20 is a stream cipher submitted to eSTREAM, the ECRYPT
-+	  Stream Cipher Project. See <http://www.ecrypt.eu.org/stream/>
++static int crypto_ccm_init_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct ccm_instance_ctx *ictx = crypto_instance_ctx(inst);
++	struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_cipher *cipher;
++	struct crypto_ablkcipher *ctr;
++	unsigned long align;
++	int err;
 +
-+	  The Salsa20 stream cipher algorithm is designed by Daniel J.
-+	  Bernstein <djb at cr.yp.to>. See <http://cr.yp.to/snuffle.html>
++	cipher = crypto_spawn_cipher(&ictx->cipher);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	ctr = crypto_spawn_skcipher(&ictx->ctr);
++	err = PTR_ERR(ctr);
++	if (IS_ERR(ctr))
++		goto err_free_cipher;
++
++	ctx->cipher = cipher;
++	ctx->ctr = ctr;
++
++	align = crypto_tfm_alg_alignmask(tfm);
++	align &= ~(crypto_tfm_ctx_alignment() - 1);
++	tfm->crt_aead.reqsize = align +
++				sizeof(struct crypto_ccm_req_priv_ctx) +
++				crypto_ablkcipher_reqsize(ctr);
++
++	return 0;
++
++err_free_cipher:
++	crypto_free_cipher(cipher);
++	return err;
++}
++
++static void crypto_ccm_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	crypto_free_cipher(ctx->cipher);
++	crypto_free_ablkcipher(ctx->ctr);
++}
++
++static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
++						       const char *full_name,
++						       const char *ctr_name,
++						       const char *cipher_name)
++{
++	struct crypto_attr_type *algt;
++	struct crypto_instance *inst;
++	struct crypto_alg *ctr;
++	struct crypto_alg *cipher;
++	struct ccm_instance_ctx *ictx;
++	int err;
++
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
++		return ERR_PTR(err);
++
++	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
++		return ERR_PTR(-EINVAL);
++
++	cipher = crypto_alg_mod_lookup(cipher_name,  CRYPTO_ALG_TYPE_CIPHER,
++				       CRYPTO_ALG_TYPE_MASK);
++	err = PTR_ERR(cipher);
++	if (IS_ERR(cipher))
++		return ERR_PTR(err);
++
++	err = -EINVAL;
++	if (cipher->cra_blocksize != 16)
++		goto out_put_cipher;
++
++	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
++	err = -ENOMEM;
++	if (!inst)
++		goto out_put_cipher;
++
++	ictx = crypto_instance_ctx(inst);
++
++	err = crypto_init_spawn(&ictx->cipher, cipher, inst,
++				CRYPTO_ALG_TYPE_MASK);
++	if (err)
++		goto err_free_inst;
++
++	crypto_set_skcipher_spawn(&ictx->ctr, inst);
++	err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
++				   crypto_requires_sync(algt->type,
++							algt->mask));
++	if (err)
++		goto err_drop_cipher;
++
++	ctr = crypto_skcipher_spawn_alg(&ictx->ctr);
++
++	/* Not a stream cipher? */
++	err = -EINVAL;
++	if (ctr->cra_blocksize != 1)
++		goto err_drop_ctr;
++
++	/* We want the real thing! */
++	if (ctr->cra_ablkcipher.ivsize != 16)
++		goto err_drop_ctr;
++
++	err = -ENAMETOOLONG;
++	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++		     "ccm_base(%s,%s)", ctr->cra_driver_name,
++		     cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
++		goto err_drop_ctr;
++
++	memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
++	inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
++	inst->alg.cra_priority = cipher->cra_priority + ctr->cra_priority;
++	inst->alg.cra_blocksize = 1;
++	inst->alg.cra_alignmask = cipher->cra_alignmask | ctr->cra_alignmask |
++				  (__alignof__(u32) - 1);
++	inst->alg.cra_type = &crypto_aead_type;
++	inst->alg.cra_aead.ivsize = 16;
++	inst->alg.cra_aead.maxauthsize = 16;
++	inst->alg.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
++	inst->alg.cra_init = crypto_ccm_init_tfm;
++	inst->alg.cra_exit = crypto_ccm_exit_tfm;
++	inst->alg.cra_aead.setkey = crypto_ccm_setkey;
++	inst->alg.cra_aead.setauthsize = crypto_ccm_setauthsize;
++	inst->alg.cra_aead.encrypt = crypto_ccm_encrypt;
++	inst->alg.cra_aead.decrypt = crypto_ccm_decrypt;
++
++out:
++	crypto_mod_put(cipher);
++	return inst;
++
++err_drop_ctr:
++	crypto_drop_skcipher(&ictx->ctr);
++err_drop_cipher:
++	crypto_drop_spawn(&ictx->cipher);
++err_free_inst:
++	kfree(inst);
++out_put_cipher:
++	inst = ERR_PTR(err);
++	goto out;
++}
++
++static struct crypto_instance *crypto_ccm_alloc(struct rtattr **tb)
++{
++	int err;
++	const char *cipher_name;
++	char ctr_name[CRYPTO_MAX_ALG_NAME];
++	char full_name[CRYPTO_MAX_ALG_NAME];
++
++	cipher_name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(cipher_name);
++	if (IS_ERR(cipher_name))
++		return ERR_PTR(err);
++
++	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
++		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
++		return ERR_PTR(-ENAMETOOLONG);
++
++	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		return ERR_PTR(-ENAMETOOLONG);
++
++	return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
++}
++
++static void crypto_ccm_free(struct crypto_instance *inst)
++{
++	struct ccm_instance_ctx *ctx = crypto_instance_ctx(inst);
++
++	crypto_drop_spawn(&ctx->cipher);
++	crypto_drop_skcipher(&ctx->ctr);
++	kfree(inst);
++}
++
++static struct crypto_template crypto_ccm_tmpl = {
++	.name = "ccm",
++	.alloc = crypto_ccm_alloc,
++	.free = crypto_ccm_free,
++	.module = THIS_MODULE,
++};
++
++static struct crypto_instance *crypto_ccm_base_alloc(struct rtattr **tb)
++{
++	int err;
++	const char *ctr_name;
++	const char *cipher_name;
++	char full_name[CRYPTO_MAX_ALG_NAME];
++
++	ctr_name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(ctr_name);
++	if (IS_ERR(ctr_name))
++		return ERR_PTR(err);
++
++	cipher_name = crypto_attr_alg_name(tb[2]);
++	err = PTR_ERR(cipher_name);
++	if (IS_ERR(cipher_name))
++		return ERR_PTR(err);
++
++	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
++		     ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
++		return ERR_PTR(-ENAMETOOLONG);
++
++	return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
++}
++
++static struct crypto_template crypto_ccm_base_tmpl = {
++	.name = "ccm_base",
++	.alloc = crypto_ccm_base_alloc,
++	.free = crypto_ccm_free,
++	.module = THIS_MODULE,
++};
++
++static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
++				 unsigned int keylen)
++{
++	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
++	struct crypto_aead *child = ctx->child;
++	int err;
++
++	if (keylen < 3)
++		return -EINVAL;
++
++	keylen -= 3;
++	memcpy(ctx->nonce, key + keylen, 3);
++
++	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
++				     CRYPTO_TFM_REQ_MASK);
++	err = crypto_aead_setkey(child, key, keylen);
++	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
++				      CRYPTO_TFM_RES_MASK);
++
++	return err;
++}
++
++static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
++				      unsigned int authsize)
++{
++	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
++
++	switch (authsize) {
++	case 8:
++	case 12:
++	case 16:
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	return crypto_aead_setauthsize(ctx->child, authsize);
++}
++
++static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
++{
++	struct aead_request *subreq = aead_request_ctx(req);
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_aead *child = ctx->child;
++	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
++			   crypto_aead_alignmask(child) + 1);
++
++	/* L' */
++	iv[0] = 3;
++
++	memcpy(iv + 1, ctx->nonce, 3);
++	memcpy(iv + 4, req->iv, 8);
++
++	aead_request_set_tfm(subreq, child);
++	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
++				  req->base.data);
++	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
++	aead_request_set_assoc(subreq, req->assoc, req->assoclen);
++
++	return subreq;
++}
++
++static int crypto_rfc4309_encrypt(struct aead_request *req)
++{
++	req = crypto_rfc4309_crypt(req);
++
++	return crypto_aead_encrypt(req);
++}
++
++static int crypto_rfc4309_decrypt(struct aead_request *req)
++{
++	req = crypto_rfc4309_crypt(req);
++
++	return crypto_aead_decrypt(req);
++}
++
++static int crypto_rfc4309_init_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
++	struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_aead *aead;
++	unsigned long align;
++
++	aead = crypto_spawn_aead(spawn);
++	if (IS_ERR(aead))
++		return PTR_ERR(aead);
++
++	ctx->child = aead;
++
++	align = crypto_aead_alignmask(aead);
++	align &= ~(crypto_tfm_ctx_alignment() - 1);
++	tfm->crt_aead.reqsize = sizeof(struct aead_request) +
++				ALIGN(crypto_aead_reqsize(aead),
++				      crypto_tfm_ctx_alignment()) +
++				align + 16;
++
++	return 0;
++}
++
++static void crypto_rfc4309_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	crypto_free_aead(ctx->child);
++}
++
++static struct crypto_instance *crypto_rfc4309_alloc(struct rtattr **tb)
++{
++	struct crypto_attr_type *algt;
++	struct crypto_instance *inst;
++	struct crypto_aead_spawn *spawn;
++	struct crypto_alg *alg;
++	const char *ccm_name;
++	int err;
++
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
++		return ERR_PTR(err);
++
++	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
++		return ERR_PTR(-EINVAL);
++
++	ccm_name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(ccm_name);
++	if (IS_ERR(ccm_name))
++		return ERR_PTR(err);
++
++	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
++	if (!inst)
++		return ERR_PTR(-ENOMEM);
++
++	spawn = crypto_instance_ctx(inst);
++	crypto_set_aead_spawn(spawn, inst);
++	err = crypto_grab_aead(spawn, ccm_name, 0,
++			       crypto_requires_sync(algt->type, algt->mask));
++	if (err)
++		goto out_free_inst;
++
++	alg = crypto_aead_spawn_alg(spawn);
++
++	err = -EINVAL;
++
++	/* We only support 16-byte blocks. */
++	if (alg->cra_aead.ivsize != 16)
++		goto out_drop_alg;
++
++	/* Not a stream cipher? */
++	if (alg->cra_blocksize != 1)
++		goto out_drop_alg;
++
++	err = -ENAMETOOLONG;
++	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
++		     "rfc4309(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
++	    snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++		     "rfc4309(%s)", alg->cra_driver_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		goto out_drop_alg;
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
++	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = 1;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_nivaead_type;
++
++	inst->alg.cra_aead.ivsize = 8;
++	inst->alg.cra_aead.maxauthsize = 16;
++
++	inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
++
++	inst->alg.cra_init = crypto_rfc4309_init_tfm;
++	inst->alg.cra_exit = crypto_rfc4309_exit_tfm;
++
++	inst->alg.cra_aead.setkey = crypto_rfc4309_setkey;
++	inst->alg.cra_aead.setauthsize = crypto_rfc4309_setauthsize;
++	inst->alg.cra_aead.encrypt = crypto_rfc4309_encrypt;
++	inst->alg.cra_aead.decrypt = crypto_rfc4309_decrypt;
++
++	inst->alg.cra_aead.geniv = "seqiv";
++
++out:
++	return inst;
++
++out_drop_alg:
++	crypto_drop_aead(spawn);
++out_free_inst:
++	kfree(inst);
++	inst = ERR_PTR(err);
++	goto out;
++}
++
++static void crypto_rfc4309_free(struct crypto_instance *inst)
++{
++	crypto_drop_spawn(crypto_instance_ctx(inst));
++	kfree(inst);
++}
++
++static struct crypto_template crypto_rfc4309_tmpl = {
++	.name = "rfc4309",
++	.alloc = crypto_rfc4309_alloc,
++	.free = crypto_rfc4309_free,
++	.module = THIS_MODULE,
++};
++
++static int __init crypto_ccm_module_init(void)
++{
++	int err;
++
++	err = crypto_register_template(&crypto_ccm_base_tmpl);
++	if (err)
++		goto out;
++
++	err = crypto_register_template(&crypto_ccm_tmpl);
++	if (err)
++		goto out_undo_base;
++
++	err = crypto_register_template(&crypto_rfc4309_tmpl);
++	if (err)
++		goto out_undo_ccm;
++
++out:
++	return err;
++
++out_undo_ccm:
++	crypto_unregister_template(&crypto_ccm_tmpl);
++out_undo_base:
++	crypto_unregister_template(&crypto_ccm_base_tmpl);
++	goto out;
++}
++
++static void __exit crypto_ccm_module_exit(void)
++{
++	crypto_unregister_template(&crypto_rfc4309_tmpl);
++	crypto_unregister_template(&crypto_ccm_tmpl);
++	crypto_unregister_template(&crypto_ccm_base_tmpl);
++}
++
++module_init(crypto_ccm_module_init);
++module_exit(crypto_ccm_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Counter with CBC MAC");
++MODULE_ALIAS("ccm_base");
++MODULE_ALIAS("rfc4309");
+diff --git a/crypto/chainiv.c b/crypto/chainiv.c
+new file mode 100644
+index 0000000..d17fa04
+--- /dev/null
++++ b/crypto/chainiv.c
+@@ -0,0 +1,331 @@
++/*
++ * chainiv: Chain IV Generator
++ *
++ * Generate IVs simply be using the last block of the previous encryption.
++ * This is mainly useful for CBC with a synchronous algorithm.
++ *
++ * Copyright (c) 2007 Herbert Xu <herbert at gondor.apana.org.au>
++ *
++ * 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 <crypto/internal/skcipher.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/random.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/workqueue.h>
++
++enum {
++	CHAINIV_STATE_INUSE = 0,
++};
++
++struct chainiv_ctx {
++	spinlock_t lock;
++	char iv[];
++};
++
++struct async_chainiv_ctx {
++	unsigned long state;
++
++	spinlock_t lock;
++	int err;
++
++	struct crypto_queue queue;
++	struct work_struct postponed;
++
++	char iv[];
++};
++
++static int chainiv_givencrypt(struct skcipher_givcrypt_request *req)
++{
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
++	unsigned int ivsize;
++	int err;
++
++	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
++	ablkcipher_request_set_callback(subreq, req->creq.base.flags &
++						~CRYPTO_TFM_REQ_MAY_SLEEP,
++					req->creq.base.complete,
++					req->creq.base.data);
++	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
++				     req->creq.nbytes, req->creq.info);
++
++	spin_lock_bh(&ctx->lock);
++
++	ivsize = crypto_ablkcipher_ivsize(geniv);
++
++	memcpy(req->giv, ctx->iv, ivsize);
++	memcpy(subreq->info, ctx->iv, ivsize);
++
++	err = crypto_ablkcipher_encrypt(subreq);
++	if (err)
++		goto unlock;
++
++	memcpy(ctx->iv, subreq->info, ivsize);
++
++unlock:
++	spin_unlock_bh(&ctx->lock);
++
++	return err;
++}
++
++static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
++{
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++
++	spin_lock_bh(&ctx->lock);
++	if (crypto_ablkcipher_crt(geniv)->givencrypt !=
++	    chainiv_givencrypt_first)
++		goto unlock;
++
++	crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt;
++	get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
++
++unlock:
++	spin_unlock_bh(&ctx->lock);
++
++	return chainiv_givencrypt(req);
++}
++
++static int chainiv_init_common(struct crypto_tfm *tfm)
++{
++	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
++
++	return skcipher_geniv_init(tfm);
++}
++
++static int chainiv_init(struct crypto_tfm *tfm)
++{
++	struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	spin_lock_init(&ctx->lock);
++
++	return chainiv_init_common(tfm);
++}
++
++static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx)
++{
++	int queued;
++
++	if (!ctx->queue.qlen) {
++		smp_mb__before_clear_bit();
++		clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
++
++		if (!ctx->queue.qlen ||
++		    test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
++			goto out;
++	}
++
++	queued = schedule_work(&ctx->postponed);
++	BUG_ON(!queued);
++
++out:
++	return ctx->err;
++}
++
++static int async_chainiv_postpone_request(struct skcipher_givcrypt_request *req)
++{
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	int err;
++
++	spin_lock_bh(&ctx->lock);
++	err = skcipher_enqueue_givcrypt(&ctx->queue, req);
++	spin_unlock_bh(&ctx->lock);
++
++	if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
++		return err;
++
++	ctx->err = err;
++	return async_chainiv_schedule_work(ctx);
++}
++
++static int async_chainiv_givencrypt_tail(struct skcipher_givcrypt_request *req)
++{
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
++	unsigned int ivsize = crypto_ablkcipher_ivsize(geniv);
++
++	memcpy(req->giv, ctx->iv, ivsize);
++	memcpy(subreq->info, ctx->iv, ivsize);
++
++	ctx->err = crypto_ablkcipher_encrypt(subreq);
++	if (ctx->err)
++		goto out;
++
++	memcpy(ctx->iv, subreq->info, ivsize);
++
++out:
++	return async_chainiv_schedule_work(ctx);
++}
++
++static int async_chainiv_givencrypt(struct skcipher_givcrypt_request *req)
++{
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
++
++	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
++	ablkcipher_request_set_callback(subreq, req->creq.base.flags,
++					req->creq.base.complete,
++					req->creq.base.data);
++	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
++				     req->creq.nbytes, req->creq.info);
++
++	if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
++		goto postpone;
++
++	if (ctx->queue.qlen) {
++		clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
++		goto postpone;
++	}
++
++	return async_chainiv_givencrypt_tail(req);
++
++postpone:
++	return async_chainiv_postpone_request(req);
++}
++
++static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
++{
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++
++	if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
++		goto out;
++
++	if (crypto_ablkcipher_crt(geniv)->givencrypt !=
++	    async_chainiv_givencrypt_first)
++		goto unlock;
++
++	crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt;
++	get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
++
++unlock:
++	clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
++
++out:
++	return async_chainiv_givencrypt(req);
++}
++
++static void async_chainiv_do_postponed(struct work_struct *work)
++{
++	struct async_chainiv_ctx *ctx = container_of(work,
++						     struct async_chainiv_ctx,
++						     postponed);
++	struct skcipher_givcrypt_request *req;
++	struct ablkcipher_request *subreq;
++
++	/* Only handle one request at a time to avoid hogging keventd. */
++	spin_lock_bh(&ctx->lock);
++	req = skcipher_dequeue_givcrypt(&ctx->queue);
++	spin_unlock_bh(&ctx->lock);
++
++	if (!req) {
++		async_chainiv_schedule_work(ctx);
++		return;
++	}
++
++	subreq = skcipher_givcrypt_reqctx(req);
++	subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
++
++	async_chainiv_givencrypt_tail(req);
++}
++
++static int async_chainiv_init(struct crypto_tfm *tfm)
++{
++	struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	spin_lock_init(&ctx->lock);
++
++	crypto_init_queue(&ctx->queue, 100);
++	INIT_WORK(&ctx->postponed, async_chainiv_do_postponed);
++
++	return chainiv_init_common(tfm);
++}
++
++static void async_chainiv_exit(struct crypto_tfm *tfm)
++{
++	struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	BUG_ON(test_bit(CHAINIV_STATE_INUSE, &ctx->state) || ctx->queue.qlen);
++
++	skcipher_geniv_exit(tfm);
++}
++
++static struct crypto_template chainiv_tmpl;
++
++static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
++{
++	struct crypto_attr_type *algt;
++	struct crypto_instance *inst;
++	int err;
++
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
++		return ERR_PTR(err);
++
++	inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0);
++	if (IS_ERR(inst))
++		goto out;
++
++	inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first;
++
++	inst->alg.cra_init = chainiv_init;
++	inst->alg.cra_exit = skcipher_geniv_exit;
++
++	inst->alg.cra_ctxsize = sizeof(struct chainiv_ctx);
++
++	if (!crypto_requires_sync(algt->type, algt->mask)) {
++		inst->alg.cra_flags |= CRYPTO_ALG_ASYNC;
++
++		inst->alg.cra_ablkcipher.givencrypt =
++			async_chainiv_givencrypt_first;
++
++		inst->alg.cra_init = async_chainiv_init;
++		inst->alg.cra_exit = async_chainiv_exit;
++
++		inst->alg.cra_ctxsize = sizeof(struct async_chainiv_ctx);
++	}
++
++	inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
++
++out:
++	return inst;
++}
++
++static struct crypto_template chainiv_tmpl = {
++	.name = "chainiv",
++	.alloc = chainiv_alloc,
++	.free = skcipher_geniv_free,
++	.module = THIS_MODULE,
++};
++
++static int __init chainiv_module_init(void)
++{
++	return crypto_register_template(&chainiv_tmpl);
++}
++
++static void __exit chainiv_module_exit(void)
++{
++	crypto_unregister_template(&chainiv_tmpl);
++}
++
++module_init(chainiv_module_init);
++module_exit(chainiv_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Chain IV Generator");
+diff --git a/crypto/cryptd.c b/crypto/cryptd.c
+index 8bf2da8..074298f 100644
+--- a/crypto/cryptd.c
++++ b/crypto/cryptd.c
+@@ -228,7 +228,7 @@ static struct crypto_instance *cryptd_alloc_blkcipher(
+ 	struct crypto_alg *alg;
  
- config CRYPTO_DEFLATE
- 	tristate "Deflate compression algorithm"
-@@ -491,6 +566,7 @@ config CRYPTO_TEST
- 	tristate "Testing module"
- 	depends on m
- 	select CRYPTO_ALGAPI
-+	select CRYPTO_AEAD
- 	help
- 	  Quick & dirty crypto test module.
+ 	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
+-				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
++				  CRYPTO_ALG_TYPE_MASK);
+ 	if (IS_ERR(alg))
+ 		return ERR_PTR(PTR_ERR(alg));
  
-@@ -498,10 +574,19 @@ config CRYPTO_AUTHENC
- 	tristate "Authenc support"
- 	select CRYPTO_AEAD
- 	select CRYPTO_MANAGER
-+	select CRYPTO_HASH
- 	help
- 	  Authenc: Combined mode wrapper for IPsec.
- 	  This is required for IPSec.
+@@ -236,13 +236,15 @@ static struct crypto_instance *cryptd_alloc_blkcipher(
+ 	if (IS_ERR(inst))
+ 		goto out_put_alg;
  
-+config CRYPTO_LZO
-+	tristate "LZO compression algorithm"
-+	select CRYPTO_ALGAPI
-+	select LZO_COMPRESS
-+	select LZO_DECOMPRESS
-+	help
-+	  This is the LZO algorithm.
-+
- source "drivers/crypto/Kconfig"
+-	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_ASYNC;
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
+ 	inst->alg.cra_type = &crypto_ablkcipher_type;
  
- endif	# if CRYPTO
-diff --git a/crypto/Makefile b/crypto/Makefile
-index 43c2a0d..48c7583 100644
---- a/crypto/Makefile
-+++ b/crypto/Makefile
-@@ -8,9 +8,14 @@ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
- crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
- obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
+ 	inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize;
+ 	inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
+ 	inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
  
--obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
- obj-$(CONFIG_CRYPTO_AEAD) += aead.o
--obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
++	inst->alg.cra_ablkcipher.geniv = alg->cra_blkcipher.geniv;
 +
-+crypto_blkcipher-objs := ablkcipher.o
-+crypto_blkcipher-objs += blkcipher.o
-+obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
-+obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
-+obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
-+obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
- 
- crypto_hash-objs := hash.o
- obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
-@@ -32,6 +37,9 @@ obj-$(CONFIG_CRYPTO_CBC) += cbc.o
- obj-$(CONFIG_CRYPTO_PCBC) += pcbc.o
- obj-$(CONFIG_CRYPTO_LRW) += lrw.o
- obj-$(CONFIG_CRYPTO_XTS) += xts.o
-+obj-$(CONFIG_CRYPTO_CTR) += ctr.o
-+obj-$(CONFIG_CRYPTO_GCM) += gcm.o
-+obj-$(CONFIG_CRYPTO_CCM) += ccm.o
- obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
- obj-$(CONFIG_CRYPTO_DES) += des_generic.o
- obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
-@@ -48,10 +56,12 @@ obj-$(CONFIG_CRYPTO_TEA) += tea.o
- obj-$(CONFIG_CRYPTO_KHAZAD) += khazad.o
- obj-$(CONFIG_CRYPTO_ANUBIS) += anubis.o
- obj-$(CONFIG_CRYPTO_SEED) += seed.o
-+obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o
- obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o
- obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
- obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
- obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
-+obj-$(CONFIG_CRYPTO_LZO) += lzo.o
- 
- obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o
+ 	inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx);
  
-diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
-index 2731acb..3bcb099 100644
---- a/crypto/ablkcipher.c
-+++ b/crypto/ablkcipher.c
-@@ -13,14 +13,18 @@
+ 	inst->alg.cra_init = cryptd_blkcipher_init_tfm;
+diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
+index 29f7747..ff7b3de 100644
+--- a/crypto/crypto_null.c
++++ b/crypto/crypto_null.c
+@@ -16,15 +16,17 @@
+  * (at your option) any later version.
   *
   */
- 
--#include <crypto/algapi.h>
--#include <linux/errno.h>
++
 +#include <crypto/internal/skcipher.h>
-+#include <linux/err.h>
  #include <linux/init.h>
- #include <linux/kernel.h>
  #include <linux/module.h>
-+#include <linux/rtnetlink.h>
-+#include <linux/sched.h>
- #include <linux/slab.h>
- #include <linux/seq_file.h>
+ #include <linux/mm.h>
+-#include <linux/crypto.h>
+ #include <linux/string.h>
  
-+#include "internal.h"
-+
- static int setkey_unaligned(struct crypto_ablkcipher *tfm, const u8 *key,
- 			    unsigned int keylen)
- {
-@@ -66,6 +70,16 @@ static unsigned int crypto_ablkcipher_ctxsize(struct crypto_alg *alg, u32 type,
- 	return alg->cra_ctxsize;
+ #define NULL_KEY_SIZE		0
+ #define NULL_BLOCK_SIZE		1
+ #define NULL_DIGEST_SIZE	0
++#define NULL_IV_SIZE		0
+ 
+ static int null_compress(struct crypto_tfm *tfm, const u8 *src,
+ 			 unsigned int slen, u8 *dst, unsigned int *dlen)
+@@ -55,6 +57,26 @@ static void null_crypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
+ 	memcpy(dst, src, NULL_BLOCK_SIZE);
  }
  
-+int skcipher_null_givencrypt(struct skcipher_givcrypt_request *req)
++static int skcipher_null_crypt(struct blkcipher_desc *desc,
++			       struct scatterlist *dst,
++			       struct scatterlist *src, unsigned int nbytes)
 +{
-+	return crypto_ablkcipher_encrypt(&req->creq);
-+}
++	struct blkcipher_walk walk;
++	int err;
 +
-+int skcipher_null_givdecrypt(struct skcipher_givcrypt_request *req)
-+{
-+	return crypto_ablkcipher_decrypt(&req->creq);
-+}
++	blkcipher_walk_init(&walk, dst, src, nbytes);
++	err = blkcipher_walk_virt(desc, &walk);
 +
- static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
- 				      u32 mask)
- {
-@@ -78,6 +92,11 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
- 	crt->setkey = setkey;
- 	crt->encrypt = alg->encrypt;
- 	crt->decrypt = alg->decrypt;
-+	if (!alg->ivsize) {
-+		crt->givencrypt = skcipher_null_givencrypt;
-+		crt->givdecrypt = skcipher_null_givdecrypt;
++	while (walk.nbytes) {
++		if (walk.src.virt.addr != walk.dst.virt.addr)
++			memcpy(walk.dst.virt.addr, walk.src.virt.addr,
++			       walk.nbytes);
++		err = blkcipher_walk_done(desc, &walk, 0);
 +	}
-+	crt->base = __crypto_ablkcipher_cast(tfm);
- 	crt->ivsize = alg->ivsize;
++
++	return err;
++}
++
+ static struct crypto_alg compress_null = {
+ 	.cra_name		=	"compress_null",
+ 	.cra_flags		=	CRYPTO_ALG_TYPE_COMPRESS,
+@@ -76,6 +98,7 @@ static struct crypto_alg digest_null = {
+ 	.cra_list		=       LIST_HEAD_INIT(digest_null.cra_list),	
+ 	.cra_u			=	{ .digest = {
+ 	.dia_digestsize		=	NULL_DIGEST_SIZE,
++	.dia_setkey   		=	null_setkey,
+ 	.dia_init   		=	null_init,
+ 	.dia_update 		=	null_update,
+ 	.dia_final  		=	null_final } }
+@@ -96,6 +119,25 @@ static struct crypto_alg cipher_null = {
+ 	.cia_decrypt		=	null_crypt } }
+ };
  
- 	return 0;
-@@ -90,10 +109,13 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
- 	struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
++static struct crypto_alg skcipher_null = {
++	.cra_name		=	"ecb(cipher_null)",
++	.cra_driver_name	=	"ecb-cipher_null",
++	.cra_priority		=	100,
++	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
++	.cra_blocksize		=	NULL_BLOCK_SIZE,
++	.cra_type		=	&crypto_blkcipher_type,
++	.cra_ctxsize		=	0,
++	.cra_module		=	THIS_MODULE,
++	.cra_list		=	LIST_HEAD_INIT(skcipher_null.cra_list),
++	.cra_u			=	{ .blkcipher = {
++	.min_keysize		=	NULL_KEY_SIZE,
++	.max_keysize		=	NULL_KEY_SIZE,
++	.ivsize			=	NULL_IV_SIZE,
++	.setkey			= 	null_setkey,
++	.encrypt		=	skcipher_null_crypt,
++	.decrypt		=	skcipher_null_crypt } }
++};
++
+ MODULE_ALIAS("compress_null");
+ MODULE_ALIAS("digest_null");
+ MODULE_ALIAS("cipher_null");
+@@ -108,27 +150,35 @@ static int __init init(void)
+ 	if (ret < 0)
+ 		goto out;
  
- 	seq_printf(m, "type         : ablkcipher\n");
-+	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
-+					     "yes" : "no");
- 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
- 	seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
- 	seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
- 	seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
-+	seq_printf(m, "geniv        : %s\n", ablkcipher->geniv ?: "<default>");
++	ret = crypto_register_alg(&skcipher_null);
++	if (ret < 0)
++		goto out_unregister_cipher;
++
+ 	ret = crypto_register_alg(&digest_null);
+-	if (ret < 0) {
+-		crypto_unregister_alg(&cipher_null);
+-		goto out;
+-	}
++	if (ret < 0)
++		goto out_unregister_skcipher;
+ 
+ 	ret = crypto_register_alg(&compress_null);
+-	if (ret < 0) {
+-		crypto_unregister_alg(&digest_null);
+-		crypto_unregister_alg(&cipher_null);
+-		goto out;
+-	}
++	if (ret < 0)
++		goto out_unregister_digest;
+ 
+ out:	
+ 	return ret;
++
++out_unregister_digest:
++	crypto_unregister_alg(&digest_null);
++out_unregister_skcipher:
++	crypto_unregister_alg(&skcipher_null);
++out_unregister_cipher:
++	crypto_unregister_alg(&cipher_null);
++	goto out;
  }
  
- const struct crypto_type crypto_ablkcipher_type = {
-@@ -105,5 +127,220 @@ const struct crypto_type crypto_ablkcipher_type = {
- };
- EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
+ static void __exit fini(void)
+ {
+ 	crypto_unregister_alg(&compress_null);
+ 	crypto_unregister_alg(&digest_null);
++	crypto_unregister_alg(&skcipher_null);
+ 	crypto_unregister_alg(&cipher_null);
+ }
  
-+static int no_givdecrypt(struct skcipher_givcrypt_request *req)
+diff --git a/crypto/ctr.c b/crypto/ctr.c
+new file mode 100644
+index 0000000..2d7425f
+--- /dev/null
++++ b/crypto/ctr.c
+@@ -0,0 +1,422 @@
++/*
++ * CTR: Counter mode
++ *
++ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten at us.ibm.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.
++ *
++ */
++
++#include <crypto/algapi.h>
++#include <crypto/ctr.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/random.h>
++#include <linux/scatterlist.h>
++#include <linux/slab.h>
++
++struct crypto_ctr_ctx {
++	struct crypto_cipher *child;
++};
++
++struct crypto_rfc3686_ctx {
++	struct crypto_blkcipher *child;
++	u8 nonce[CTR_RFC3686_NONCE_SIZE];
++};
++
++static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
++			     unsigned int keylen)
 +{
-+	return -ENOSYS;
++	struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent);
++	struct crypto_cipher *child = ctx->child;
++	int err;
++
++	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
++				CRYPTO_TFM_REQ_MASK);
++	err = crypto_cipher_setkey(child, key, keylen);
++	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
++			     CRYPTO_TFM_RES_MASK);
++
++	return err;
 +}
 +
-+static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
-+				      u32 mask)
++static void crypto_ctr_crypt_final(struct blkcipher_walk *walk,
++				   struct crypto_cipher *tfm)
 +{
-+	struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
-+	struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
++	unsigned int bsize = crypto_cipher_blocksize(tfm);
++	unsigned long alignmask = crypto_cipher_alignmask(tfm);
++	u8 *ctrblk = walk->iv;
++	u8 tmp[bsize + alignmask];
++	u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
++	u8 *src = walk->src.virt.addr;
++	u8 *dst = walk->dst.virt.addr;
++	unsigned int nbytes = walk->nbytes;
 +
-+	if (alg->ivsize > PAGE_SIZE / 8)
-+		return -EINVAL;
++	crypto_cipher_encrypt_one(tfm, keystream, ctrblk);
++	crypto_xor(keystream, src, nbytes);
++	memcpy(dst, keystream, nbytes);
 +
-+	crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
-+		      alg->setkey : setkey;
-+	crt->encrypt = alg->encrypt;
-+	crt->decrypt = alg->decrypt;
-+	crt->givencrypt = alg->givencrypt;
-+	crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt;
-+	crt->base = __crypto_ablkcipher_cast(tfm);
-+	crt->ivsize = alg->ivsize;
++	crypto_inc(ctrblk, bsize);
++}
 +
-+	return 0;
++static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk,
++				    struct crypto_cipher *tfm)
++{
++	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
++		   crypto_cipher_alg(tfm)->cia_encrypt;
++	unsigned int bsize = crypto_cipher_blocksize(tfm);
++	u8 *ctrblk = walk->iv;
++	u8 *src = walk->src.virt.addr;
++	u8 *dst = walk->dst.virt.addr;
++	unsigned int nbytes = walk->nbytes;
++
++	do {
++		/* create keystream */
++		fn(crypto_cipher_tfm(tfm), dst, ctrblk);
++		crypto_xor(dst, src, bsize);
++
++		/* increment counter in counterblock */
++		crypto_inc(ctrblk, bsize);
++
++		src += bsize;
++		dst += bsize;
++	} while ((nbytes -= bsize) >= bsize);
++
++	return nbytes;
 +}
 +
-+static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
-+	__attribute__ ((unused));
-+static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
++static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk,
++				    struct crypto_cipher *tfm)
 +{
-+	struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
++	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
++		   crypto_cipher_alg(tfm)->cia_encrypt;
++	unsigned int bsize = crypto_cipher_blocksize(tfm);
++	unsigned long alignmask = crypto_cipher_alignmask(tfm);
++	unsigned int nbytes = walk->nbytes;
++	u8 *ctrblk = walk->iv;
++	u8 *src = walk->src.virt.addr;
++	u8 tmp[bsize + alignmask];
++	u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
 +
-+	seq_printf(m, "type         : givcipher\n");
-+	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
-+					     "yes" : "no");
-+	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-+	seq_printf(m, "min keysize  : %u\n", ablkcipher->min_keysize);
-+	seq_printf(m, "max keysize  : %u\n", ablkcipher->max_keysize);
-+	seq_printf(m, "ivsize       : %u\n", ablkcipher->ivsize);
-+	seq_printf(m, "geniv        : %s\n", ablkcipher->geniv ?: "<built-in>");
++	do {
++		/* create keystream */
++		fn(crypto_cipher_tfm(tfm), keystream, ctrblk);
++		crypto_xor(src, keystream, bsize);
++
++		/* increment counter in counterblock */
++		crypto_inc(ctrblk, bsize);
++
++		src += bsize;
++	} while ((nbytes -= bsize) >= bsize);
++
++	return nbytes;
 +}
 +
-+const struct crypto_type crypto_givcipher_type = {
-+	.ctxsize = crypto_ablkcipher_ctxsize,
-+	.init = crypto_init_givcipher_ops,
-+#ifdef CONFIG_PROC_FS
-+	.show = crypto_givcipher_show,
-+#endif
-+};
-+EXPORT_SYMBOL_GPL(crypto_givcipher_type);
++static int crypto_ctr_crypt(struct blkcipher_desc *desc,
++			      struct scatterlist *dst, struct scatterlist *src,
++			      unsigned int nbytes)
++{
++	struct blkcipher_walk walk;
++	struct crypto_blkcipher *tfm = desc->tfm;
++	struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
++	struct crypto_cipher *child = ctx->child;
++	unsigned int bsize = crypto_cipher_blocksize(child);
++	int err;
 +
-+const char *crypto_default_geniv(const struct crypto_alg *alg)
++	blkcipher_walk_init(&walk, dst, src, nbytes);
++	err = blkcipher_walk_virt_block(desc, &walk, bsize);
++
++	while (walk.nbytes >= bsize) {
++		if (walk.src.virt.addr == walk.dst.virt.addr)
++			nbytes = crypto_ctr_crypt_inplace(&walk, child);
++		else
++			nbytes = crypto_ctr_crypt_segment(&walk, child);
++
++		err = blkcipher_walk_done(desc, &walk, nbytes);
++	}
++
++	if (walk.nbytes) {
++		crypto_ctr_crypt_final(&walk, child);
++		err = blkcipher_walk_done(desc, &walk, 0);
++	}
++
++	return err;
++}
++
++static int crypto_ctr_init_tfm(struct crypto_tfm *tfm)
 +{
-+	return alg->cra_flags & CRYPTO_ALG_ASYNC ? "eseqiv" : "chainiv";
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
++	struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_cipher *cipher;
++
++	cipher = crypto_spawn_cipher(spawn);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	ctx->child = cipher;
++
++	return 0;
 +}
 +
-+static int crypto_givcipher_default(struct crypto_alg *alg, u32 type, u32 mask)
++static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	crypto_free_cipher(ctx->child);
++}
++
++static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb)
 +{
-+	struct rtattr *tb[3];
-+	struct {
-+		struct rtattr attr;
-+		struct crypto_attr_type data;
-+	} ptype;
-+	struct {
-+		struct rtattr attr;
-+		struct crypto_attr_alg data;
-+	} palg;
-+	struct crypto_template *tmpl;
 +	struct crypto_instance *inst;
-+	struct crypto_alg *larval;
-+	const char *geniv;
++	struct crypto_alg *alg;
 +	int err;
 +
-+	larval = crypto_larval_lookup(alg->cra_driver_name,
-+				      CRYPTO_ALG_TYPE_GIVCIPHER,
-+				      CRYPTO_ALG_TYPE_MASK);
-+	err = PTR_ERR(larval);
-+	if (IS_ERR(larval))
-+		goto out;
-+
-+	err = -EAGAIN;
-+	if (!crypto_is_larval(larval))
-+		goto drop_larval;
++	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
++	if (err)
++		return ERR_PTR(err);
 +
-+	ptype.attr.rta_len = sizeof(ptype);
-+	ptype.attr.rta_type = CRYPTOA_TYPE;
-+	ptype.data.type = type | CRYPTO_ALG_GENIV;
-+	/* GENIV tells the template that we're making a default geniv. */
-+	ptype.data.mask = mask | CRYPTO_ALG_GENIV;
-+	tb[0] = &ptype.attr;
++	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
++				  CRYPTO_ALG_TYPE_MASK);
++	if (IS_ERR(alg))
++		return ERR_PTR(PTR_ERR(alg));
 +
-+	palg.attr.rta_len = sizeof(palg);
-+	palg.attr.rta_type = CRYPTOA_ALG;
-+	/* Must use the exact name to locate ourselves. */
-+	memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
-+	tb[1] = &palg.attr;
++	/* Block size must be >= 4 bytes. */
++	err = -EINVAL;
++	if (alg->cra_blocksize < 4)
++		goto out_put_alg;
 +
-+	tb[2] = NULL;
++	/* If this is false we'd fail the alignment of crypto_inc. */
++	if (alg->cra_blocksize % 4)
++		goto out_put_alg;
 +
-+	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
-+	    CRYPTO_ALG_TYPE_BLKCIPHER)
-+		geniv = alg->cra_blkcipher.geniv;
-+	else
-+		geniv = alg->cra_ablkcipher.geniv;
++	inst = crypto_alloc_instance("ctr", alg);
++	if (IS_ERR(inst))
++		goto out;
 +
-+	if (!geniv)
-+		geniv = crypto_default_geniv(alg);
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = 1;
++	inst->alg.cra_alignmask = alg->cra_alignmask | (__alignof__(u32) - 1);
++	inst->alg.cra_type = &crypto_blkcipher_type;
 +
-+	tmpl = crypto_lookup_template(geniv);
-+	err = -ENOENT;
-+	if (!tmpl)
-+		goto kill_larval;
++	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
++	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
++	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
 +
-+	inst = tmpl->alloc(tb);
-+	err = PTR_ERR(inst);
-+	if (IS_ERR(inst))
-+		goto put_tmpl;
++	inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx);
 +
-+	if ((err = crypto_register_instance(tmpl, inst))) {
-+		tmpl->free(inst);
-+		goto put_tmpl;
-+	}
++	inst->alg.cra_init = crypto_ctr_init_tfm;
++	inst->alg.cra_exit = crypto_ctr_exit_tfm;
 +
-+	/* Redo the lookup to use the instance we just registered. */
-+	err = -EAGAIN;
++	inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey;
++	inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt;
++	inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt;
 +
-+put_tmpl:
-+	crypto_tmpl_put(tmpl);
-+kill_larval:
-+	crypto_larval_kill(larval);
-+drop_larval:
-+	crypto_mod_put(larval);
 +out:
 +	crypto_mod_put(alg);
-+	return err;
++	return inst;
++
++out_put_alg:
++	inst = ERR_PTR(err);
++	goto out;
 +}
 +
-+static struct crypto_alg *crypto_lookup_skcipher(const char *name, u32 type,
-+						 u32 mask)
++static void crypto_ctr_free(struct crypto_instance *inst)
 +{
-+	struct crypto_alg *alg;
++	crypto_drop_spawn(crypto_instance_ctx(inst));
++	kfree(inst);
++}
 +
-+	alg = crypto_alg_mod_lookup(name, type, mask);
-+	if (IS_ERR(alg))
-+		return alg;
++static struct crypto_template crypto_ctr_tmpl = {
++	.name = "ctr",
++	.alloc = crypto_ctr_alloc,
++	.free = crypto_ctr_free,
++	.module = THIS_MODULE,
++};
 +
-+	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
-+	    CRYPTO_ALG_TYPE_GIVCIPHER)
-+		return alg;
++static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
++				 unsigned int keylen)
++{
++	struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
++	struct crypto_blkcipher *child = ctx->child;
++	int err;
 +
-+	if (!((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
-+	      CRYPTO_ALG_TYPE_BLKCIPHER ? alg->cra_blkcipher.ivsize :
-+					  alg->cra_ablkcipher.ivsize))
-+		return alg;
++	/* the nonce is stored in bytes at end of key */
++	if (keylen < CTR_RFC3686_NONCE_SIZE)
++		return -EINVAL;
 +
-+	return ERR_PTR(crypto_givcipher_default(alg, type, mask));
++	memcpy(ctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
++	       CTR_RFC3686_NONCE_SIZE);
++
++	keylen -= CTR_RFC3686_NONCE_SIZE;
++
++	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
++					  CRYPTO_TFM_REQ_MASK);
++	err = crypto_blkcipher_setkey(child, key, keylen);
++	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
++				     CRYPTO_TFM_RES_MASK);
++
++	return err;
 +}
 +
-+int crypto_grab_skcipher(struct crypto_skcipher_spawn *spawn, const char *name,
-+			 u32 type, u32 mask)
++static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
++				struct scatterlist *dst,
++				struct scatterlist *src, unsigned int nbytes)
 +{
-+	struct crypto_alg *alg;
++	struct crypto_blkcipher *tfm = desc->tfm;
++	struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
++	struct crypto_blkcipher *child = ctx->child;
++	unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
++	u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
++	u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
++	u8 *info = desc->info;
 +	int err;
 +
-+	type = crypto_skcipher_type(type);
-+	mask = crypto_skcipher_mask(mask);
++	/* set up counter block */
++	memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
++	memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
 +
-+	alg = crypto_lookup_skcipher(name, type, mask);
-+	if (IS_ERR(alg))
-+		return PTR_ERR(alg);
++	/* initialize counter portion of counter block */
++	*(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
++		cpu_to_be32(1);
++
++	desc->tfm = child;
++	desc->info = iv;
++	err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
++	desc->tfm = tfm;
++	desc->info = info;
 +
-+	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
-+	crypto_mod_put(alg);
 +	return err;
 +}
-+EXPORT_SYMBOL_GPL(crypto_grab_skcipher);
 +
-+struct crypto_ablkcipher *crypto_alloc_ablkcipher(const char *alg_name,
-+						  u32 type, u32 mask)
++static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
 +{
-+	struct crypto_tfm *tfm;
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
++	struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_blkcipher *cipher;
++
++	cipher = crypto_spawn_blkcipher(spawn);
++	if (IS_ERR(cipher))
++		return PTR_ERR(cipher);
++
++	ctx->child = cipher;
++
++	return 0;
++}
++
++static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	crypto_free_blkcipher(ctx->child);
++}
++
++static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
++{
++	struct crypto_instance *inst;
++	struct crypto_alg *alg;
 +	int err;
 +
-+	type = crypto_skcipher_type(type);
-+	mask = crypto_skcipher_mask(mask);
++	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
++	if (err)
++		return ERR_PTR(err);
 +
-+	for (;;) {
-+		struct crypto_alg *alg;
++	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
++				  CRYPTO_ALG_TYPE_MASK);
++	err = PTR_ERR(alg);
++	if (IS_ERR(alg))
++		return ERR_PTR(err);
 +
-+		alg = crypto_lookup_skcipher(alg_name, type, mask);
-+		if (IS_ERR(alg)) {
-+			err = PTR_ERR(alg);
-+			goto err;
-+		}
++	/* We only support 16-byte blocks. */
++	err = -EINVAL;
++	if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
++		goto out_put_alg;
 +
-+		tfm = __crypto_alloc_tfm(alg, type, mask);
-+		if (!IS_ERR(tfm))
-+			return __crypto_ablkcipher_cast(tfm);
++	/* Not a stream cipher? */
++	if (alg->cra_blocksize != 1)
++		goto out_put_alg;
 +
-+		crypto_mod_put(alg);
-+		err = PTR_ERR(tfm);
++	inst = crypto_alloc_instance("rfc3686", alg);
++	if (IS_ERR(inst))
++		goto out;
 +
-+err:
-+		if (err != -EAGAIN)
-+			break;
-+		if (signal_pending(current)) {
-+			err = -EINTR;
-+			break;
-+		}
-+	}
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = 1;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_blkcipher_type;
 +
-+	return ERR_PTR(err);
++	inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
++	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
++					      + CTR_RFC3686_NONCE_SIZE;
++	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
++					      + CTR_RFC3686_NONCE_SIZE;
++
++	inst->alg.cra_blkcipher.geniv = "seqiv";
++
++	inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
++
++	inst->alg.cra_init = crypto_rfc3686_init_tfm;
++	inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
++
++	inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
++	inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
++	inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
++
++out:
++	crypto_mod_put(alg);
++	return inst;
++
++out_put_alg:
++	inst = ERR_PTR(err);
++	goto out;
 +}
-+EXPORT_SYMBOL_GPL(crypto_alloc_ablkcipher);
 +
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
-diff --git a/crypto/aead.c b/crypto/aead.c
-index 84a3501..3a6f3f5 100644
---- a/crypto/aead.c
-+++ b/crypto/aead.c
-@@ -12,14 +12,17 @@
-  *
-  */
- 
--#include <crypto/algapi.h>
--#include <linux/errno.h>
-+#include <crypto/internal/aead.h>
-+#include <linux/err.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
-+#include <linux/rtnetlink.h>
- #include <linux/slab.h>
- #include <linux/seq_file.h>
- 
-+#include "internal.h"
++static struct crypto_template crypto_rfc3686_tmpl = {
++	.name = "rfc3686",
++	.alloc = crypto_rfc3686_alloc,
++	.free = crypto_ctr_free,
++	.module = THIS_MODULE,
++};
 +
- static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key,
- 			    unsigned int keylen)
- {
-@@ -53,25 +56,54 @@ static int setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)
- 	return aead->setkey(tfm, key, keylen);
- }
- 
-+int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
++static int __init crypto_ctr_module_init(void)
 +{
-+	struct aead_tfm *crt = crypto_aead_crt(tfm);
 +	int err;
 +
-+	if (authsize > crypto_aead_alg(tfm)->maxauthsize)
-+		return -EINVAL;
++	err = crypto_register_template(&crypto_ctr_tmpl);
++	if (err)
++		goto out;
 +
-+	if (crypto_aead_alg(tfm)->setauthsize) {
-+		err = crypto_aead_alg(tfm)->setauthsize(crt->base, authsize);
-+		if (err)
-+			return err;
-+	}
++	err = crypto_register_template(&crypto_rfc3686_tmpl);
++	if (err)
++		goto out_drop_ctr;
 +
-+	crypto_aead_crt(crt->base)->authsize = authsize;
-+	crt->authsize = authsize;
-+	return 0;
++out:
++	return err;
++
++out_drop_ctr:
++	crypto_unregister_template(&crypto_ctr_tmpl);
++	goto out;
 +}
-+EXPORT_SYMBOL_GPL(crypto_aead_setauthsize);
 +
- static unsigned int crypto_aead_ctxsize(struct crypto_alg *alg, u32 type,
- 					u32 mask)
- {
- 	return alg->cra_ctxsize;
- }
- 
-+static int no_givcrypt(struct aead_givcrypt_request *req)
++static void __exit crypto_ctr_module_exit(void)
 +{
-+	return -ENOSYS;
++	crypto_unregister_template(&crypto_rfc3686_tmpl);
++	crypto_unregister_template(&crypto_ctr_tmpl);
 +}
 +
- static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
++module_init(crypto_ctr_module_init);
++module_exit(crypto_ctr_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("CTR Counter block mode");
++MODULE_ALIAS("rfc3686");
+diff --git a/crypto/des_generic.c b/crypto/des_generic.c
+index 59966d1..355ecb7 100644
+--- a/crypto/des_generic.c
++++ b/crypto/des_generic.c
+@@ -20,13 +20,7 @@
+ #include <linux/crypto.h>
+ #include <linux/types.h>
+ 
+-#define DES_KEY_SIZE		8
+-#define DES_EXPKEY_WORDS	32
+-#define DES_BLOCK_SIZE		8
+-
+-#define DES3_EDE_KEY_SIZE	(3 * DES_KEY_SIZE)
+-#define DES3_EDE_EXPKEY_WORDS	(3 * DES_EXPKEY_WORDS)
+-#define DES3_EDE_BLOCK_SIZE	DES_BLOCK_SIZE
++#include <crypto/des.h>
+ 
+ #define ROL(x, r) ((x) = rol32((x), (r)))
+ #define ROR(x, r) ((x) = ror32((x), (r)))
+@@ -634,7 +628,7 @@ static const u32 S8[64] = {
+  *   Choice 1 has operated on the key.
+  *
+  */
+-static unsigned long ekey(u32 *pe, const u8 *k)
++unsigned long des_ekey(u32 *pe, const u8 *k)
  {
- 	struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
- 	struct aead_tfm *crt = &tfm->crt_aead;
+ 	/* K&R: long is at least 32 bits */
+ 	unsigned long a, b, c, d, w;
+@@ -709,6 +703,7 @@ static unsigned long ekey(u32 *pe, const u8 *k)
+ 	/* Zero if weak key */
+ 	return w;
+ }
++EXPORT_SYMBOL_GPL(des_ekey);
  
--	if (max(alg->authsize, alg->ivsize) > PAGE_SIZE / 8)
-+	if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
+ /*
+  * Decryption key expansion
+@@ -792,7 +787,7 @@ static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
+ 	int ret;
+ 
+ 	/* Expand to tmp */
+-	ret = ekey(tmp, key);
++	ret = des_ekey(tmp, key);
+ 
+ 	if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+ 		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
+@@ -879,9 +874,9 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
  		return -EINVAL;
+ 	}
  
--	crt->setkey = setkey;
-+	crt->setkey = tfm->__crt_alg->cra_flags & CRYPTO_ALG_GENIV ?
-+		      alg->setkey : setkey;
- 	crt->encrypt = alg->encrypt;
- 	crt->decrypt = alg->decrypt;
-+	crt->givencrypt = alg->givencrypt ?: no_givcrypt;
-+	crt->givdecrypt = alg->givdecrypt ?: no_givcrypt;
-+	crt->base = __crypto_aead_cast(tfm);
- 	crt->ivsize = alg->ivsize;
--	crt->authsize = alg->authsize;
-+	crt->authsize = alg->maxauthsize;
+-	ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
++	des_ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
+ 	dkey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
+-	ekey(expkey, key);
++	des_ekey(expkey, key);
  
  	return 0;
  }
-@@ -83,9 +115,12 @@ static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
- 	struct aead_alg *aead = &alg->cra_aead;
- 
- 	seq_printf(m, "type         : aead\n");
-+	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
-+					     "yes" : "no");
- 	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
- 	seq_printf(m, "ivsize       : %u\n", aead->ivsize);
--	seq_printf(m, "authsize     : %u\n", aead->authsize);
-+	seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
-+	seq_printf(m, "geniv        : %s\n", aead->geniv ?: "<built-in>");
- }
+diff --git a/crypto/digest.c b/crypto/digest.c
+index 8871dec..6fd43bd 100644
+--- a/crypto/digest.c
++++ b/crypto/digest.c
+@@ -12,6 +12,7 @@
+  *
+  */
  
- const struct crypto_type crypto_aead_type = {
-@@ -97,5 +132,358 @@ const struct crypto_type crypto_aead_type = {
- };
- EXPORT_SYMBOL_GPL(crypto_aead_type);
++#include <crypto/scatterwalk.h>
+ #include <linux/mm.h>
+ #include <linux/errno.h>
+ #include <linux/hardirq.h>
+@@ -20,9 +21,6 @@
+ #include <linux/module.h>
+ #include <linux/scatterlist.h>
  
-+static int aead_null_givencrypt(struct aead_givcrypt_request *req)
-+{
-+	return crypto_aead_encrypt(&req->areq);
-+}
+-#include "internal.h"
+-#include "scatterwalk.h"
+-
+ static int init(struct hash_desc *desc)
+ {
+ 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
+diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
+new file mode 100644
+index 0000000..eb90d27
+--- /dev/null
++++ b/crypto/eseqiv.c
+@@ -0,0 +1,264 @@
++/*
++ * eseqiv: Encrypted Sequence Number IV Generator
++ *
++ * This generator generates an IV based on a sequence number by xoring it
++ * with a salt and then encrypting it with the same key as used to encrypt
++ * the plain text.  This algorithm requires that the block size be equal
++ * to the IV size.  It is mainly useful for CBC.
++ *
++ * Copyright (c) 2007 Herbert Xu <herbert at gondor.apana.org.au>
++ *
++ * 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.
++ *
++ */
 +
-+static int aead_null_givdecrypt(struct aead_givcrypt_request *req)
++#include <crypto/internal/skcipher.h>
++#include <crypto/scatterwalk.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/mm.h>
++#include <linux/module.h>
++#include <linux/random.h>
++#include <linux/scatterlist.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++
++struct eseqiv_request_ctx {
++	struct scatterlist src[2];
++	struct scatterlist dst[2];
++	char tail[];
++};
++
++struct eseqiv_ctx {
++	spinlock_t lock;
++	unsigned int reqoff;
++	char salt[];
++};
++
++static void eseqiv_complete2(struct skcipher_givcrypt_request *req)
 +{
-+	return crypto_aead_decrypt(&req->areq);
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
++
++	memcpy(req->giv, PTR_ALIGN((u8 *)reqctx->tail,
++			 crypto_ablkcipher_alignmask(geniv) + 1),
++	       crypto_ablkcipher_ivsize(geniv));
 +}
 +
-+static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
++static void eseqiv_complete(struct crypto_async_request *base, int err)
 +{
-+	struct aead_alg *alg = &tfm->__crt_alg->cra_aead;
-+	struct aead_tfm *crt = &tfm->crt_aead;
++	struct skcipher_givcrypt_request *req = base->data;
 +
-+	if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8)
-+		return -EINVAL;
++	if (err)
++		goto out;
 +
-+	crt->setkey = setkey;
-+	crt->encrypt = alg->encrypt;
-+	crt->decrypt = alg->decrypt;
-+	if (!alg->ivsize) {
-+		crt->givencrypt = aead_null_givencrypt;
-+		crt->givdecrypt = aead_null_givdecrypt;
++	eseqiv_complete2(req);
++
++out:
++	skcipher_givcrypt_complete(req, err);
++}
++
++static void eseqiv_chain(struct scatterlist *head, struct scatterlist *sg,
++			 int chain)
++{
++	if (chain) {
++		head->length += sg->length;
++		sg = scatterwalk_sg_next(sg);
 +	}
-+	crt->base = __crypto_aead_cast(tfm);
-+	crt->ivsize = alg->ivsize;
-+	crt->authsize = alg->maxauthsize;
 +
-+	return 0;
++	if (sg)
++		scatterwalk_sg_chain(head, 2, sg);
++	else
++		sg_mark_end(head);
 +}
 +
-+static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
-+	__attribute__ ((unused));
-+static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
++static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
 +{
-+	struct aead_alg *aead = &alg->cra_aead;
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
++	struct ablkcipher_request *subreq;
++	crypto_completion_t complete;
++	void *data;
++	struct scatterlist *osrc, *odst;
++	struct scatterlist *dst;
++	struct page *srcp;
++	struct page *dstp;
++	u8 *giv;
++	u8 *vsrc;
++	u8 *vdst;
++	__be64 seq;
++	unsigned int ivsize;
++	unsigned int len;
++	int err;
 +
-+	seq_printf(m, "type         : nivaead\n");
-+	seq_printf(m, "async        : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
-+					     "yes" : "no");
-+	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
-+	seq_printf(m, "ivsize       : %u\n", aead->ivsize);
-+	seq_printf(m, "maxauthsize  : %u\n", aead->maxauthsize);
-+	seq_printf(m, "geniv        : %s\n", aead->geniv);
++	subreq = (void *)(reqctx->tail + ctx->reqoff);
++	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
++
++	giv = req->giv;
++	complete = req->creq.base.complete;
++	data = req->creq.base.data;
++
++	osrc = req->creq.src;
++	odst = req->creq.dst;
++	srcp = sg_page(osrc);
++	dstp = sg_page(odst);
++	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + osrc->offset;
++	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + odst->offset;
++
++	ivsize = crypto_ablkcipher_ivsize(geniv);
++
++	if (vsrc != giv + ivsize && vdst != giv + ivsize) {
++		giv = PTR_ALIGN((u8 *)reqctx->tail,
++				crypto_ablkcipher_alignmask(geniv) + 1);
++		complete = eseqiv_complete;
++		data = req;
++	}
++
++	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
++					data);
++
++	sg_init_table(reqctx->src, 2);
++	sg_set_buf(reqctx->src, giv, ivsize);
++	eseqiv_chain(reqctx->src, osrc, vsrc == giv + ivsize);
++
++	dst = reqctx->src;
++	if (osrc != odst) {
++		sg_init_table(reqctx->dst, 2);
++		sg_set_buf(reqctx->dst, giv, ivsize);
++		eseqiv_chain(reqctx->dst, odst, vdst == giv + ivsize);
++
++		dst = reqctx->dst;
++	}
++
++	ablkcipher_request_set_crypt(subreq, reqctx->src, dst,
++				     req->creq.nbytes, req->creq.info);
++
++	memcpy(req->creq.info, ctx->salt, ivsize);
++
++	len = ivsize;
++	if (ivsize > sizeof(u64)) {
++		memset(req->giv, 0, ivsize - sizeof(u64));
++		len = sizeof(u64);
++	}
++	seq = cpu_to_be64(req->seq);
++	memcpy(req->giv + ivsize - len, &seq, len);
++
++	err = crypto_ablkcipher_encrypt(subreq);
++	if (err)
++		goto out;
++
++	eseqiv_complete2(req);
++
++out:
++	return err;
 +}
 +
-+const struct crypto_type crypto_nivaead_type = {
-+	.ctxsize = crypto_aead_ctxsize,
-+	.init = crypto_init_nivaead_ops,
-+#ifdef CONFIG_PROC_FS
-+	.show = crypto_nivaead_show,
-+#endif
-+};
-+EXPORT_SYMBOL_GPL(crypto_nivaead_type);
-+
-+static int crypto_grab_nivaead(struct crypto_aead_spawn *spawn,
-+			       const char *name, u32 type, u32 mask)
++static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
 +{
-+	struct crypto_alg *alg;
-+	int err;
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
 +
-+	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-+	type |= CRYPTO_ALG_TYPE_AEAD;
-+	mask |= CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV;
++	spin_lock_bh(&ctx->lock);
++	if (crypto_ablkcipher_crt(geniv)->givencrypt != eseqiv_givencrypt_first)
++		goto unlock;
 +
-+	alg = crypto_alg_mod_lookup(name, type, mask);
-+	if (IS_ERR(alg))
-+		return PTR_ERR(alg);
++	crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt;
++	get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
 +
-+	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
-+	crypto_mod_put(alg);
-+	return err;
++unlock:
++	spin_unlock_bh(&ctx->lock);
++
++	return eseqiv_givencrypt(req);
 +}
 +
-+struct crypto_instance *aead_geniv_alloc(struct crypto_template *tmpl,
-+					 struct rtattr **tb, u32 type,
-+					 u32 mask)
++static int eseqiv_init(struct crypto_tfm *tfm)
 +{
-+	const char *name;
-+	struct crypto_aead_spawn *spawn;
-+	struct crypto_attr_type *algt;
-+	struct crypto_instance *inst;
-+	struct crypto_alg *alg;
-+	int err;
++	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
++	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	unsigned long alignmask;
++	unsigned int reqsize;
 +
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
-+		return ERR_PTR(err);
++	spin_lock_init(&ctx->lock);
 +
-+	if ((algt->type ^ (CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV)) &
-+	    algt->mask)
-+		return ERR_PTR(-EINVAL);
++	alignmask = crypto_tfm_ctx_alignment() - 1;
++	reqsize = sizeof(struct eseqiv_request_ctx);
 +
-+	name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(name);
-+	if (IS_ERR(name))
-+		return ERR_PTR(err);
++	if (alignmask & reqsize) {
++		alignmask &= reqsize;
++		alignmask--;
++	}
 +
-+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
-+	if (!inst)
-+		return ERR_PTR(-ENOMEM);
++	alignmask = ~alignmask;
++	alignmask &= crypto_ablkcipher_alignmask(geniv);
 +
-+	spawn = crypto_instance_ctx(inst);
++	reqsize += alignmask;
++	reqsize += crypto_ablkcipher_ivsize(geniv);
++	reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment());
 +
-+	/* Ignore async algorithms if necessary. */
-+	mask |= crypto_requires_sync(algt->type, algt->mask);
++	ctx->reqoff = reqsize - sizeof(struct eseqiv_request_ctx);
 +
-+	crypto_set_aead_spawn(spawn, inst);
-+	err = crypto_grab_nivaead(spawn, name, type, mask);
-+	if (err)
-+		goto err_free_inst;
++	tfm->crt_ablkcipher.reqsize = reqsize +
++				      sizeof(struct ablkcipher_request);
 +
-+	alg = crypto_aead_spawn_alg(spawn);
++	return skcipher_geniv_init(tfm);
++}
 +
-+	err = -EINVAL;
-+	if (!alg->cra_aead.ivsize)
-+		goto err_drop_alg;
++static struct crypto_template eseqiv_tmpl;
 +
-+	/*
-+	 * This is only true if we're constructing an algorithm with its
-+	 * default IV generator.  For the default generator we elide the
-+	 * template name and double-check the IV generator.
-+	 */
-+	if (algt->mask & CRYPTO_ALG_GENIV) {
-+		if (strcmp(tmpl->name, alg->cra_aead.geniv))
-+			goto err_drop_alg;
++static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
++{
++	struct crypto_instance *inst;
++	int err;
 +
-+		memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
-+		memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
-+		       CRYPTO_MAX_ALG_NAME);
-+	} else {
-+		err = -ENAMETOOLONG;
-+		if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-+			     "%s(%s)", tmpl->name, alg->cra_name) >=
-+		    CRYPTO_MAX_ALG_NAME)
-+			goto err_drop_alg;
-+		if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+			     "%s(%s)", tmpl->name, alg->cra_driver_name) >=
-+		    CRYPTO_MAX_ALG_NAME)
-+			goto err_drop_alg;
-+	}
++	inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0);
++	if (IS_ERR(inst))
++		goto out;
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV;
-+	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_priority = alg->cra_priority;
-+	inst->alg.cra_blocksize = alg->cra_blocksize;
-+	inst->alg.cra_alignmask = alg->cra_alignmask;
-+	inst->alg.cra_type = &crypto_aead_type;
++	err = -EINVAL;
++	if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize)
++		goto free_inst;
 +
-+	inst->alg.cra_aead.ivsize = alg->cra_aead.ivsize;
-+	inst->alg.cra_aead.maxauthsize = alg->cra_aead.maxauthsize;
-+	inst->alg.cra_aead.geniv = alg->cra_aead.geniv;
++	inst->alg.cra_ablkcipher.givencrypt = eseqiv_givencrypt_first;
 +
-+	inst->alg.cra_aead.setkey = alg->cra_aead.setkey;
-+	inst->alg.cra_aead.setauthsize = alg->cra_aead.setauthsize;
-+	inst->alg.cra_aead.encrypt = alg->cra_aead.encrypt;
-+	inst->alg.cra_aead.decrypt = alg->cra_aead.decrypt;
++	inst->alg.cra_init = eseqiv_init;
++	inst->alg.cra_exit = skcipher_geniv_exit;
++
++	inst->alg.cra_ctxsize = sizeof(struct eseqiv_ctx);
++	inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
 +
 +out:
 +	return inst;
 +
-+err_drop_alg:
-+	crypto_drop_aead(spawn);
-+err_free_inst:
-+	kfree(inst);
++free_inst:
++	skcipher_geniv_free(inst);
 +	inst = ERR_PTR(err);
 +	goto out;
 +}
-+EXPORT_SYMBOL_GPL(aead_geniv_alloc);
 +
-+void aead_geniv_free(struct crypto_instance *inst)
-+{
-+	crypto_drop_aead(crypto_instance_ctx(inst));
-+	kfree(inst);
-+}
-+EXPORT_SYMBOL_GPL(aead_geniv_free);
++static struct crypto_template eseqiv_tmpl = {
++	.name = "eseqiv",
++	.alloc = eseqiv_alloc,
++	.free = skcipher_geniv_free,
++	.module = THIS_MODULE,
++};
 +
-+int aead_geniv_init(struct crypto_tfm *tfm)
++static int __init eseqiv_module_init(void)
 +{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct crypto_aead *aead;
-+
-+	aead = crypto_spawn_aead(crypto_instance_ctx(inst));
-+	if (IS_ERR(aead))
-+		return PTR_ERR(aead);
-+
-+	tfm->crt_aead.base = aead;
-+	tfm->crt_aead.reqsize += crypto_aead_reqsize(aead);
-+
-+	return 0;
++	return crypto_register_template(&eseqiv_tmpl);
 +}
-+EXPORT_SYMBOL_GPL(aead_geniv_init);
 +
-+void aead_geniv_exit(struct crypto_tfm *tfm)
++static void __exit eseqiv_module_exit(void)
 +{
-+	crypto_free_aead(tfm->crt_aead.base);
++	crypto_unregister_template(&eseqiv_tmpl);
 +}
-+EXPORT_SYMBOL_GPL(aead_geniv_exit);
-+
-+static int crypto_nivaead_default(struct crypto_alg *alg, u32 type, u32 mask)
-+{
-+	struct rtattr *tb[3];
-+	struct {
-+		struct rtattr attr;
-+		struct crypto_attr_type data;
-+	} ptype;
-+	struct {
-+		struct rtattr attr;
-+		struct crypto_attr_alg data;
-+	} palg;
-+	struct crypto_template *tmpl;
-+	struct crypto_instance *inst;
-+	struct crypto_alg *larval;
-+	const char *geniv;
-+	int err;
 +
-+	larval = crypto_larval_lookup(alg->cra_driver_name,
-+				      CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_GENIV,
-+				      CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-+	err = PTR_ERR(larval);
-+	if (IS_ERR(larval))
-+		goto out;
++module_init(eseqiv_module_init);
++module_exit(eseqiv_module_exit);
 +
-+	err = -EAGAIN;
-+	if (!crypto_is_larval(larval))
-+		goto drop_larval;
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
+diff --git a/crypto/gcm.c b/crypto/gcm.c
+new file mode 100644
+index 0000000..e70afd0
+--- /dev/null
++++ b/crypto/gcm.c
+@@ -0,0 +1,823 @@
++/*
++ * GCM: Galois/Counter Mode.
++ *
++ * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1 at iki.fi>
++ *
++ * 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.
++ */
 +
-+	ptype.attr.rta_len = sizeof(ptype);
-+	ptype.attr.rta_type = CRYPTOA_TYPE;
-+	ptype.data.type = type | CRYPTO_ALG_GENIV;
-+	/* GENIV tells the template that we're making a default geniv. */
-+	ptype.data.mask = mask | CRYPTO_ALG_GENIV;
-+	tb[0] = &ptype.attr;
++#include <crypto/gf128mul.h>
++#include <crypto/internal/aead.h>
++#include <crypto/internal/skcipher.h>
++#include <crypto/scatterwalk.h>
++#include <linux/completion.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
 +
-+	palg.attr.rta_len = sizeof(palg);
-+	palg.attr.rta_type = CRYPTOA_ALG;
-+	/* Must use the exact name to locate ourselves. */
-+	memcpy(palg.data.name, alg->cra_driver_name, CRYPTO_MAX_ALG_NAME);
-+	tb[1] = &palg.attr;
++struct gcm_instance_ctx {
++	struct crypto_skcipher_spawn ctr;
++};
 +
-+	tb[2] = NULL;
++struct crypto_gcm_ctx {
++	struct crypto_ablkcipher *ctr;
++	struct gf128mul_4k *gf128;
++};
 +
-+	geniv = alg->cra_aead.geniv;
++struct crypto_rfc4106_ctx {
++	struct crypto_aead *child;
++	u8 nonce[4];
++};
 +
-+	tmpl = crypto_lookup_template(geniv);
-+	err = -ENOENT;
-+	if (!tmpl)
-+		goto kill_larval;
++struct crypto_gcm_ghash_ctx {
++	u32 bytes;
++	u32 flags;
++	struct gf128mul_4k *gf128;
++	u8 buffer[16];
++};
 +
-+	inst = tmpl->alloc(tb);
-+	err = PTR_ERR(inst);
-+	if (IS_ERR(inst))
-+		goto put_tmpl;
++struct crypto_gcm_req_priv_ctx {
++	u8 auth_tag[16];
++	u8 iauth_tag[16];
++	struct scatterlist src[2];
++	struct scatterlist dst[2];
++	struct crypto_gcm_ghash_ctx ghash;
++	struct ablkcipher_request abreq;
++};
 +
-+	if ((err = crypto_register_instance(tmpl, inst))) {
-+		tmpl->free(inst);
-+		goto put_tmpl;
-+	}
++struct crypto_gcm_setkey_result {
++	int err;
++	struct completion completion;
++};
 +
-+	/* Redo the lookup to use the instance we just registered. */
-+	err = -EAGAIN;
++static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_reqctx(
++	struct aead_request *req)
++{
++	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
 +
-+put_tmpl:
-+	crypto_tmpl_put(tmpl);
-+kill_larval:
-+	crypto_larval_kill(larval);
-+drop_larval:
-+	crypto_mod_put(larval);
-+out:
-+	crypto_mod_put(alg);
-+	return err;
++	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
 +}
 +
-+static struct crypto_alg *crypto_lookup_aead(const char *name, u32 type,
-+					     u32 mask)
++static void crypto_gcm_ghash_init(struct crypto_gcm_ghash_ctx *ctx, u32 flags,
++				  struct gf128mul_4k *gf128)
 +{
-+	struct crypto_alg *alg;
-+
-+	alg = crypto_alg_mod_lookup(name, type, mask);
-+	if (IS_ERR(alg))
-+		return alg;
++	ctx->bytes = 0;
++	ctx->flags = flags;
++	ctx->gf128 = gf128;
++	memset(ctx->buffer, 0, 16);
++}
 +
-+	if (alg->cra_type == &crypto_aead_type)
-+		return alg;
++static void crypto_gcm_ghash_update(struct crypto_gcm_ghash_ctx *ctx,
++				    const u8 *src, unsigned int srclen)
++{
++	u8 *dst = ctx->buffer;
 +
-+	if (!alg->cra_aead.ivsize)
-+		return alg;
++	if (ctx->bytes) {
++		int n = min(srclen, ctx->bytes);
++		u8 *pos = dst + (16 - ctx->bytes);
 +
-+	return ERR_PTR(crypto_nivaead_default(alg, type, mask));
-+}
++		ctx->bytes -= n;
++		srclen -= n;
 +
-+int crypto_grab_aead(struct crypto_aead_spawn *spawn, const char *name,
-+		     u32 type, u32 mask)
-+{
-+	struct crypto_alg *alg;
-+	int err;
++		while (n--)
++			*pos++ ^= *src++;
 +
-+	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-+	type |= CRYPTO_ALG_TYPE_AEAD;
-+	mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-+	mask |= CRYPTO_ALG_TYPE_MASK;
++		if (!ctx->bytes)
++			gf128mul_4k_lle((be128 *)dst, ctx->gf128);
++	}
 +
-+	alg = crypto_lookup_aead(name, type, mask);
-+	if (IS_ERR(alg))
-+		return PTR_ERR(alg);
++	while (srclen >= 16) {
++		crypto_xor(dst, src, 16);
++		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
++		src += 16;
++		srclen -= 16;
++	}
 +
-+	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
-+	crypto_mod_put(alg);
-+	return err;
++	if (srclen) {
++		ctx->bytes = 16 - srclen;
++		while (srclen--)
++			*dst++ ^= *src++;
++	}
 +}
-+EXPORT_SYMBOL_GPL(crypto_grab_aead);
 +
-+struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)
++static void crypto_gcm_ghash_update_sg(struct crypto_gcm_ghash_ctx *ctx,
++				       struct scatterlist *sg, int len)
 +{
-+	struct crypto_tfm *tfm;
-+	int err;
++	struct scatter_walk walk;
++	u8 *src;
++	int n;
 +
-+	type &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-+	type |= CRYPTO_ALG_TYPE_AEAD;
-+	mask &= ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV);
-+	mask |= CRYPTO_ALG_TYPE_MASK;
++	if (!len)
++		return;
 +
-+	for (;;) {
-+		struct crypto_alg *alg;
++	scatterwalk_start(&walk, sg);
 +
-+		alg = crypto_lookup_aead(alg_name, type, mask);
-+		if (IS_ERR(alg)) {
-+			err = PTR_ERR(alg);
-+			goto err;
++	while (len) {
++		n = scatterwalk_clamp(&walk, len);
++
++		if (!n) {
++			scatterwalk_start(&walk, scatterwalk_sg_next(walk.sg));
++			n = scatterwalk_clamp(&walk, len);
 +		}
 +
-+		tfm = __crypto_alloc_tfm(alg, type, mask);
-+		if (!IS_ERR(tfm))
-+			return __crypto_aead_cast(tfm);
++		src = scatterwalk_map(&walk, 0);
 +
-+		crypto_mod_put(alg);
-+		err = PTR_ERR(tfm);
++		crypto_gcm_ghash_update(ctx, src, n);
++		len -= n;
 +
-+err:
-+		if (err != -EAGAIN)
-+			break;
-+		if (signal_pending(current)) {
-+			err = -EINTR;
-+			break;
-+		}
++		scatterwalk_unmap(src, 0);
++		scatterwalk_advance(&walk, n);
++		scatterwalk_done(&walk, 0, len);
++		if (len)
++			crypto_yield(ctx->flags);
 +	}
-+
-+	return ERR_PTR(err);
 +}
-+EXPORT_SYMBOL_GPL(crypto_alloc_aead);
 +
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)");
-diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
-index 9401dca..cf30af7 100644
---- a/crypto/aes_generic.c
-+++ b/crypto/aes_generic.c
-@@ -47,11 +47,7 @@
-  * ---------------------------------------------------------------------------
-  */
- 
--/* Some changes from the Gladman version:
--    s/RIJNDAEL(e_key)/E_KEY/g
--    s/RIJNDAEL(d_key)/D_KEY/g
--*/
--
-+#include <crypto/aes.h>
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/types.h>
-@@ -59,88 +55,46 @@
- #include <linux/crypto.h>
- #include <asm/byteorder.h>
- 
--#define AES_MIN_KEY_SIZE	16
--#define AES_MAX_KEY_SIZE	32
--
--#define AES_BLOCK_SIZE		16
--
--/*
-- * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) 
-- */
--static inline u8
--byte(const u32 x, const unsigned n)
-+static inline u8 byte(const u32 x, const unsigned n)
- {
- 	return x >> (n << 3);
- }
- 
--struct aes_ctx {
--	int key_length;
--	u32 buf[120];
--};
--
--#define E_KEY (&ctx->buf[0])
--#define D_KEY (&ctx->buf[60])
--
- static u8 pow_tab[256] __initdata;
- static u8 log_tab[256] __initdata;
- static u8 sbx_tab[256] __initdata;
- static u8 isb_tab[256] __initdata;
- static u32 rco_tab[10];
--static u32 ft_tab[4][256];
--static u32 it_tab[4][256];
- 
--static u32 fl_tab[4][256];
--static u32 il_tab[4][256];
-+u32 crypto_ft_tab[4][256];
-+u32 crypto_fl_tab[4][256];
-+u32 crypto_it_tab[4][256];
-+u32 crypto_il_tab[4][256];
- 
--static inline u8 __init
--f_mult (u8 a, u8 b)
-+EXPORT_SYMBOL_GPL(crypto_ft_tab);
-+EXPORT_SYMBOL_GPL(crypto_fl_tab);
-+EXPORT_SYMBOL_GPL(crypto_it_tab);
-+EXPORT_SYMBOL_GPL(crypto_il_tab);
++static void crypto_gcm_ghash_flush(struct crypto_gcm_ghash_ctx *ctx)
++{
++	u8 *dst = ctx->buffer;
 +
-+static inline u8 __init f_mult(u8 a, u8 b)
- {
- 	u8 aa = log_tab[a], cc = aa + log_tab[b];
- 
- 	return pow_tab[cc + (cc < aa ? 1 : 0)];
- }
- 
--#define ff_mult(a,b)    (a && b ? f_mult(a, b) : 0)
--
--#define f_rn(bo, bi, n, k)					\
--    bo[n] =  ft_tab[0][byte(bi[n],0)] ^				\
--             ft_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
--             ft_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
--             ft_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
--
--#define i_rn(bo, bi, n, k)					\
--    bo[n] =  it_tab[0][byte(bi[n],0)] ^				\
--             it_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
--             it_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
--             it_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
--
--#define ls_box(x)				\
--    ( fl_tab[0][byte(x, 0)] ^			\
--      fl_tab[1][byte(x, 1)] ^			\
--      fl_tab[2][byte(x, 2)] ^			\
--      fl_tab[3][byte(x, 3)] )
--
--#define f_rl(bo, bi, n, k)					\
--    bo[n] =  fl_tab[0][byte(bi[n],0)] ^				\
--             fl_tab[1][byte(bi[(n + 1) & 3],1)] ^		\
--             fl_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
--             fl_tab[3][byte(bi[(n + 3) & 3],3)] ^ *(k + n)
--
--#define i_rl(bo, bi, n, k)					\
--    bo[n] =  il_tab[0][byte(bi[n],0)] ^				\
--             il_tab[1][byte(bi[(n + 3) & 3],1)] ^		\
--             il_tab[2][byte(bi[(n + 2) & 3],2)] ^		\
--             il_tab[3][byte(bi[(n + 1) & 3],3)] ^ *(k + n)
--
--static void __init
--gen_tabs (void)
-+#define ff_mult(a, b)	(a && b ? f_mult(a, b) : 0)
++	if (ctx->bytes) {
++		u8 *tmp = dst + (16 - ctx->bytes);
 +
-+static void __init gen_tabs(void)
- {
- 	u32 i, t;
- 	u8 p, q;
- 
--	/* log and power tables for GF(2**8) finite field with
--	   0x011b as modular polynomial - the simplest primitive
--	   root is 0x03, used here to generate the tables */
-+	/*
-+	 * log and power tables for GF(2**8) finite field with
-+	 * 0x011b as modular polynomial - the simplest primitive
-+	 * root is 0x03, used here to generate the tables
-+	 */
- 
- 	for (i = 0, p = 1; i < 256; ++i) {
- 		pow_tab[i] = (u8) p;
-@@ -169,92 +123,119 @@ gen_tabs (void)
- 		p = sbx_tab[i];
- 
- 		t = p;
--		fl_tab[0][i] = t;
--		fl_tab[1][i] = rol32(t, 8);
--		fl_tab[2][i] = rol32(t, 16);
--		fl_tab[3][i] = rol32(t, 24);
-+		crypto_fl_tab[0][i] = t;
-+		crypto_fl_tab[1][i] = rol32(t, 8);
-+		crypto_fl_tab[2][i] = rol32(t, 16);
-+		crypto_fl_tab[3][i] = rol32(t, 24);
- 
--		t = ((u32) ff_mult (2, p)) |
-+		t = ((u32) ff_mult(2, p)) |
- 		    ((u32) p << 8) |
--		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
-+		    ((u32) p << 16) | ((u32) ff_mult(3, p) << 24);
- 
--		ft_tab[0][i] = t;
--		ft_tab[1][i] = rol32(t, 8);
--		ft_tab[2][i] = rol32(t, 16);
--		ft_tab[3][i] = rol32(t, 24);
-+		crypto_ft_tab[0][i] = t;
-+		crypto_ft_tab[1][i] = rol32(t, 8);
-+		crypto_ft_tab[2][i] = rol32(t, 16);
-+		crypto_ft_tab[3][i] = rol32(t, 24);
- 
- 		p = isb_tab[i];
- 
- 		t = p;
--		il_tab[0][i] = t;
--		il_tab[1][i] = rol32(t, 8);
--		il_tab[2][i] = rol32(t, 16);
--		il_tab[3][i] = rol32(t, 24);
--
--		t = ((u32) ff_mult (14, p)) |
--		    ((u32) ff_mult (9, p) << 8) |
--		    ((u32) ff_mult (13, p) << 16) |
--		    ((u32) ff_mult (11, p) << 24);
--
--		it_tab[0][i] = t;
--		it_tab[1][i] = rol32(t, 8);
--		it_tab[2][i] = rol32(t, 16);
--		it_tab[3][i] = rol32(t, 24);
-+		crypto_il_tab[0][i] = t;
-+		crypto_il_tab[1][i] = rol32(t, 8);
-+		crypto_il_tab[2][i] = rol32(t, 16);
-+		crypto_il_tab[3][i] = rol32(t, 24);
++		while (ctx->bytes--)
++			*tmp++ ^= 0;
 +
-+		t = ((u32) ff_mult(14, p)) |
-+		    ((u32) ff_mult(9, p) << 8) |
-+		    ((u32) ff_mult(13, p) << 16) |
-+		    ((u32) ff_mult(11, p) << 24);
++		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
++	}
 +
-+		crypto_it_tab[0][i] = t;
-+		crypto_it_tab[1][i] = rol32(t, 8);
-+		crypto_it_tab[2][i] = rol32(t, 16);
-+		crypto_it_tab[3][i] = rol32(t, 24);
- 	}
- }
- 
--#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
--
--#define imix_col(y,x)       \
--    u   = star_x(x);        \
--    v   = star_x(u);        \
--    w   = star_x(v);        \
--    t   = w ^ (x);          \
--   (y)  = u ^ v ^ w;        \
--   (y) ^= ror32(u ^ t,  8) ^ \
--          ror32(v ^ t, 16) ^ \
--          ror32(t,24)
--
- /* initialise the key schedule from the user supplied key */
- 
--#define loop4(i)                                    \
--{   t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];    \
--    t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
--    t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
--    t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
--    t ^= E_KEY[4 * i + 3]; E_KEY[4 * i + 7] = t;    \
--}
--
--#define loop6(i)                                    \
--{   t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];    \
--    t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
--    t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
--    t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
--    t ^= E_KEY[6 * i + 3]; E_KEY[6 * i + 9] = t;    \
--    t ^= E_KEY[6 * i + 4]; E_KEY[6 * i + 10] = t;   \
--    t ^= E_KEY[6 * i + 5]; E_KEY[6 * i + 11] = t;   \
--}
--
--#define loop8(i)                                    \
--{   t = ror32(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
--    t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
--    t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
--    t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
--    t ^= E_KEY[8 * i + 3]; E_KEY[8 * i + 11] = t;   \
--    t  = E_KEY[8 * i + 4] ^ ls_box(t);    \
--    E_KEY[8 * i + 12] = t;                \
--    t ^= E_KEY[8 * i + 5]; E_KEY[8 * i + 13] = t;   \
--    t ^= E_KEY[8 * i + 6]; E_KEY[8 * i + 14] = t;   \
--    t ^= E_KEY[8 * i + 7]; E_KEY[8 * i + 15] = t;   \
--}
-+#define star_x(x) (((x) & 0x7f7f7f7f) << 1) ^ ((((x) & 0x80808080) >> 7) * 0x1b)
- 
--static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
--		       unsigned int key_len)
-+#define imix_col(y,x)	do {		\
-+	u	= star_x(x);		\
-+	v	= star_x(u);		\
-+	w	= star_x(v);		\
-+	t	= w ^ (x);		\
-+	(y)	= u ^ v ^ w;		\
-+	(y)	^= ror32(u ^ t, 8) ^	\
-+		ror32(v ^ t, 16) ^	\
-+		ror32(t, 24);		\
-+} while (0)
++	ctx->bytes = 0;
++}
 +
-+#define ls_box(x)		\
-+	crypto_fl_tab[0][byte(x, 0)] ^	\
-+	crypto_fl_tab[1][byte(x, 1)] ^	\
-+	crypto_fl_tab[2][byte(x, 2)] ^	\
-+	crypto_fl_tab[3][byte(x, 3)]
++static void crypto_gcm_ghash_final_xor(struct crypto_gcm_ghash_ctx *ctx,
++				       unsigned int authlen,
++				       unsigned int cryptlen, u8 *dst)
++{
++	u8 *buf = ctx->buffer;
++	u128 lengths;
 +
-+#define loop4(i)	do {		\
-+	t = ror32(t, 8);		\
-+	t = ls_box(t) ^ rco_tab[i];	\
-+	t ^= ctx->key_enc[4 * i];		\
-+	ctx->key_enc[4 * i + 4] = t;		\
-+	t ^= ctx->key_enc[4 * i + 1];		\
-+	ctx->key_enc[4 * i + 5] = t;		\
-+	t ^= ctx->key_enc[4 * i + 2];		\
-+	ctx->key_enc[4 * i + 6] = t;		\
-+	t ^= ctx->key_enc[4 * i + 3];		\
-+	ctx->key_enc[4 * i + 7] = t;		\
-+} while (0)
++	lengths.a = cpu_to_be64(authlen * 8);
++	lengths.b = cpu_to_be64(cryptlen * 8);
 +
-+#define loop6(i)	do {		\
-+	t = ror32(t, 8);		\
-+	t = ls_box(t) ^ rco_tab[i];	\
-+	t ^= ctx->key_enc[6 * i];		\
-+	ctx->key_enc[6 * i + 6] = t;		\
-+	t ^= ctx->key_enc[6 * i + 1];		\
-+	ctx->key_enc[6 * i + 7] = t;		\
-+	t ^= ctx->key_enc[6 * i + 2];		\
-+	ctx->key_enc[6 * i + 8] = t;		\
-+	t ^= ctx->key_enc[6 * i + 3];		\
-+	ctx->key_enc[6 * i + 9] = t;		\
-+	t ^= ctx->key_enc[6 * i + 4];		\
-+	ctx->key_enc[6 * i + 10] = t;		\
-+	t ^= ctx->key_enc[6 * i + 5];		\
-+	ctx->key_enc[6 * i + 11] = t;		\
-+} while (0)
++	crypto_gcm_ghash_flush(ctx);
++	crypto_xor(buf, (u8 *)&lengths, 16);
++	gf128mul_4k_lle((be128 *)buf, ctx->gf128);
++	crypto_xor(dst, buf, 16);
++}
 +
-+#define loop8(i)	do {			\
-+	t = ror32(t, 8);			\
-+	t = ls_box(t) ^ rco_tab[i];		\
-+	t ^= ctx->key_enc[8 * i];			\
-+	ctx->key_enc[8 * i + 8] = t;			\
-+	t ^= ctx->key_enc[8 * i + 1];			\
-+	ctx->key_enc[8 * i + 9] = t;			\
-+	t ^= ctx->key_enc[8 * i + 2];			\
-+	ctx->key_enc[8 * i + 10] = t;			\
-+	t ^= ctx->key_enc[8 * i + 3];			\
-+	ctx->key_enc[8 * i + 11] = t;			\
-+	t  = ctx->key_enc[8 * i + 4] ^ ls_box(t);	\
-+	ctx->key_enc[8 * i + 12] = t;			\
-+	t ^= ctx->key_enc[8 * i + 5];			\
-+	ctx->key_enc[8 * i + 13] = t;			\
-+	t ^= ctx->key_enc[8 * i + 6];			\
-+	ctx->key_enc[8 * i + 14] = t;			\
-+	t ^= ctx->key_enc[8 * i + 7];			\
-+	ctx->key_enc[8 * i + 15] = t;			\
-+} while (0)
++static void crypto_gcm_setkey_done(struct crypto_async_request *req, int err)
++{
++	struct crypto_gcm_setkey_result *result = req->data;
 +
-+int crypto_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
-+		unsigned int key_len)
- {
--	struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
- 	const __le32 *key = (const __le32 *)in_key;
- 	u32 *flags = &tfm->crt_flags;
--	u32 i, t, u, v, w;
-+	u32 i, t, u, v, w, j;
- 
- 	if (key_len % 8) {
- 		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-@@ -263,95 +244,113 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- 
- 	ctx->key_length = key_len;
- 
--	E_KEY[0] = le32_to_cpu(key[0]);
--	E_KEY[1] = le32_to_cpu(key[1]);
--	E_KEY[2] = le32_to_cpu(key[2]);
--	E_KEY[3] = le32_to_cpu(key[3]);
-+	ctx->key_dec[key_len + 24] = ctx->key_enc[0] = le32_to_cpu(key[0]);
-+	ctx->key_dec[key_len + 25] = ctx->key_enc[1] = le32_to_cpu(key[1]);
-+	ctx->key_dec[key_len + 26] = ctx->key_enc[2] = le32_to_cpu(key[2]);
-+	ctx->key_dec[key_len + 27] = ctx->key_enc[3] = le32_to_cpu(key[3]);
- 
- 	switch (key_len) {
- 	case 16:
--		t = E_KEY[3];
-+		t = ctx->key_enc[3];
- 		for (i = 0; i < 10; ++i)
--			loop4 (i);
-+			loop4(i);
- 		break;
- 
- 	case 24:
--		E_KEY[4] = le32_to_cpu(key[4]);
--		t = E_KEY[5] = le32_to_cpu(key[5]);
-+		ctx->key_enc[4] = le32_to_cpu(key[4]);
-+		t = ctx->key_enc[5] = le32_to_cpu(key[5]);
- 		for (i = 0; i < 8; ++i)
--			loop6 (i);
-+			loop6(i);
- 		break;
- 
- 	case 32:
--		E_KEY[4] = le32_to_cpu(key[4]);
--		E_KEY[5] = le32_to_cpu(key[5]);
--		E_KEY[6] = le32_to_cpu(key[6]);
--		t = E_KEY[7] = le32_to_cpu(key[7]);
-+		ctx->key_enc[4] = le32_to_cpu(key[4]);
-+		ctx->key_enc[5] = le32_to_cpu(key[5]);
-+		ctx->key_enc[6] = le32_to_cpu(key[6]);
-+		t = ctx->key_enc[7] = le32_to_cpu(key[7]);
- 		for (i = 0; i < 7; ++i)
--			loop8 (i);
-+			loop8(i);
- 		break;
- 	}
- 
--	D_KEY[0] = E_KEY[0];
--	D_KEY[1] = E_KEY[1];
--	D_KEY[2] = E_KEY[2];
--	D_KEY[3] = E_KEY[3];
-+	ctx->key_dec[0] = ctx->key_enc[key_len + 24];
-+	ctx->key_dec[1] = ctx->key_enc[key_len + 25];
-+	ctx->key_dec[2] = ctx->key_enc[key_len + 26];
-+	ctx->key_dec[3] = ctx->key_enc[key_len + 27];
- 
- 	for (i = 4; i < key_len + 24; ++i) {
--		imix_col (D_KEY[i], E_KEY[i]);
-+		j = key_len + 24 - (i & ~3) + (i & 3);
-+		imix_col(ctx->key_dec[j], ctx->key_enc[i]);
- 	}
--
- 	return 0;
- }
-+EXPORT_SYMBOL_GPL(crypto_aes_set_key);
- 
- /* encrypt a block of text */
- 
--#define f_nround(bo, bi, k) \
--    f_rn(bo, bi, 0, k);     \
--    f_rn(bo, bi, 1, k);     \
--    f_rn(bo, bi, 2, k);     \
--    f_rn(bo, bi, 3, k);     \
--    k += 4
--
--#define f_lround(bo, bi, k) \
--    f_rl(bo, bi, 0, k);     \
--    f_rl(bo, bi, 1, k);     \
--    f_rl(bo, bi, 2, k);     \
--    f_rl(bo, bi, 3, k)
-+#define f_rn(bo, bi, n, k)	do {				\
-+	bo[n] = crypto_ft_tab[0][byte(bi[n], 0)] ^			\
-+		crypto_ft_tab[1][byte(bi[(n + 1) & 3], 1)] ^		\
-+		crypto_ft_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
-+		crypto_ft_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n);	\
-+} while (0)
++	if (err == -EINPROGRESS)
++		return;
 +
-+#define f_nround(bo, bi, k)	do {\
-+	f_rn(bo, bi, 0, k);	\
-+	f_rn(bo, bi, 1, k);	\
-+	f_rn(bo, bi, 2, k);	\
-+	f_rn(bo, bi, 3, k);	\
-+	k += 4;			\
-+} while (0)
++	result->err = err;
++	complete(&result->completion);
++}
 +
-+#define f_rl(bo, bi, n, k)	do {				\
-+	bo[n] = crypto_fl_tab[0][byte(bi[n], 0)] ^			\
-+		crypto_fl_tab[1][byte(bi[(n + 1) & 3], 1)] ^		\
-+		crypto_fl_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
-+		crypto_fl_tab[3][byte(bi[(n + 3) & 3], 3)] ^ *(k + n);	\
-+} while (0)
++static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
++			     unsigned int keylen)
++{
++	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_ablkcipher *ctr = ctx->ctr;
++	struct {
++		be128 hash;
++		u8 iv[8];
 +
-+#define f_lround(bo, bi, k)	do {\
-+	f_rl(bo, bi, 0, k);	\
-+	f_rl(bo, bi, 1, k);	\
-+	f_rl(bo, bi, 2, k);	\
-+	f_rl(bo, bi, 3, k);	\
-+} while (0)
- 
- static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- {
--	const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
-+	const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
- 	const __le32 *src = (const __le32 *)in;
- 	__le32 *dst = (__le32 *)out;
- 	u32 b0[4], b1[4];
--	const u32 *kp = E_KEY + 4;
-+	const u32 *kp = ctx->key_enc + 4;
-+	const int key_len = ctx->key_length;
- 
--	b0[0] = le32_to_cpu(src[0]) ^ E_KEY[0];
--	b0[1] = le32_to_cpu(src[1]) ^ E_KEY[1];
--	b0[2] = le32_to_cpu(src[2]) ^ E_KEY[2];
--	b0[3] = le32_to_cpu(src[3]) ^ E_KEY[3];
-+	b0[0] = le32_to_cpu(src[0]) ^ ctx->key_enc[0];
-+	b0[1] = le32_to_cpu(src[1]) ^ ctx->key_enc[1];
-+	b0[2] = le32_to_cpu(src[2]) ^ ctx->key_enc[2];
-+	b0[3] = le32_to_cpu(src[3]) ^ ctx->key_enc[3];
- 
--	if (ctx->key_length > 24) {
--		f_nround (b1, b0, kp);
--		f_nround (b0, b1, kp);
-+	if (key_len > 24) {
-+		f_nround(b1, b0, kp);
-+		f_nround(b0, b1, kp);
- 	}
- 
--	if (ctx->key_length > 16) {
--		f_nround (b1, b0, kp);
--		f_nround (b0, b1, kp);
-+	if (key_len > 16) {
-+		f_nround(b1, b0, kp);
-+		f_nround(b0, b1, kp);
- 	}
- 
--	f_nround (b1, b0, kp);
--	f_nround (b0, b1, kp);
--	f_nround (b1, b0, kp);
--	f_nround (b0, b1, kp);
--	f_nround (b1, b0, kp);
--	f_nround (b0, b1, kp);
--	f_nround (b1, b0, kp);
--	f_nround (b0, b1, kp);
--	f_nround (b1, b0, kp);
--	f_lround (b0, b1, kp);
-+	f_nround(b1, b0, kp);
-+	f_nround(b0, b1, kp);
-+	f_nround(b1, b0, kp);
-+	f_nround(b0, b1, kp);
-+	f_nround(b1, b0, kp);
-+	f_nround(b0, b1, kp);
-+	f_nround(b1, b0, kp);
-+	f_nround(b0, b1, kp);
-+	f_nround(b1, b0, kp);
-+	f_lround(b0, b1, kp);
- 
- 	dst[0] = cpu_to_le32(b0[0]);
- 	dst[1] = cpu_to_le32(b0[1]);
-@@ -361,53 +360,69 @@ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- 
- /* decrypt a block of text */
- 
--#define i_nround(bo, bi, k) \
--    i_rn(bo, bi, 0, k);     \
--    i_rn(bo, bi, 1, k);     \
--    i_rn(bo, bi, 2, k);     \
--    i_rn(bo, bi, 3, k);     \
--    k -= 4
--
--#define i_lround(bo, bi, k) \
--    i_rl(bo, bi, 0, k);     \
--    i_rl(bo, bi, 1, k);     \
--    i_rl(bo, bi, 2, k);     \
--    i_rl(bo, bi, 3, k)
-+#define i_rn(bo, bi, n, k)	do {				\
-+	bo[n] = crypto_it_tab[0][byte(bi[n], 0)] ^			\
-+		crypto_it_tab[1][byte(bi[(n + 3) & 3], 1)] ^		\
-+		crypto_it_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
-+		crypto_it_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n);	\
-+} while (0)
++		struct crypto_gcm_setkey_result result;
 +
-+#define i_nround(bo, bi, k)	do {\
-+	i_rn(bo, bi, 0, k);	\
-+	i_rn(bo, bi, 1, k);	\
-+	i_rn(bo, bi, 2, k);	\
-+	i_rn(bo, bi, 3, k);	\
-+	k += 4;			\
-+} while (0)
++		struct scatterlist sg[1];
++		struct ablkcipher_request req;
++	} *data;
++	int err;
 +
-+#define i_rl(bo, bi, n, k)	do {			\
-+	bo[n] = crypto_il_tab[0][byte(bi[n], 0)] ^		\
-+	crypto_il_tab[1][byte(bi[(n + 3) & 3], 1)] ^		\
-+	crypto_il_tab[2][byte(bi[(n + 2) & 3], 2)] ^		\
-+	crypto_il_tab[3][byte(bi[(n + 1) & 3], 3)] ^ *(k + n);	\
-+} while (0)
++	crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
++	crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
++				   CRYPTO_TFM_REQ_MASK);
 +
-+#define i_lround(bo, bi, k)	do {\
-+	i_rl(bo, bi, 0, k);	\
-+	i_rl(bo, bi, 1, k);	\
-+	i_rl(bo, bi, 2, k);	\
-+	i_rl(bo, bi, 3, k);	\
-+} while (0)
- 
- static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- {
--	const struct aes_ctx *ctx = crypto_tfm_ctx(tfm);
-+	const struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
- 	const __le32 *src = (const __le32 *)in;
- 	__le32 *dst = (__le32 *)out;
- 	u32 b0[4], b1[4];
- 	const int key_len = ctx->key_length;
--	const u32 *kp = D_KEY + key_len + 20;
-+	const u32 *kp = ctx->key_dec + 4;
- 
--	b0[0] = le32_to_cpu(src[0]) ^ E_KEY[key_len + 24];
--	b0[1] = le32_to_cpu(src[1]) ^ E_KEY[key_len + 25];
--	b0[2] = le32_to_cpu(src[2]) ^ E_KEY[key_len + 26];
--	b0[3] = le32_to_cpu(src[3]) ^ E_KEY[key_len + 27];
-+	b0[0] = le32_to_cpu(src[0]) ^  ctx->key_dec[0];
-+	b0[1] = le32_to_cpu(src[1]) ^  ctx->key_dec[1];
-+	b0[2] = le32_to_cpu(src[2]) ^  ctx->key_dec[2];
-+	b0[3] = le32_to_cpu(src[3]) ^  ctx->key_dec[3];
- 
- 	if (key_len > 24) {
--		i_nround (b1, b0, kp);
--		i_nround (b0, b1, kp);
-+		i_nround(b1, b0, kp);
-+		i_nround(b0, b1, kp);
- 	}
- 
- 	if (key_len > 16) {
--		i_nround (b1, b0, kp);
--		i_nround (b0, b1, kp);
-+		i_nround(b1, b0, kp);
-+		i_nround(b0, b1, kp);
- 	}
- 
--	i_nround (b1, b0, kp);
--	i_nround (b0, b1, kp);
--	i_nround (b1, b0, kp);
--	i_nround (b0, b1, kp);
--	i_nround (b1, b0, kp);
--	i_nround (b0, b1, kp);
--	i_nround (b1, b0, kp);
--	i_nround (b0, b1, kp);
--	i_nround (b1, b0, kp);
--	i_lround (b0, b1, kp);
-+	i_nround(b1, b0, kp);
-+	i_nround(b0, b1, kp);
-+	i_nround(b1, b0, kp);
-+	i_nround(b0, b1, kp);
-+	i_nround(b1, b0, kp);
-+	i_nround(b0, b1, kp);
-+	i_nround(b1, b0, kp);
-+	i_nround(b0, b1, kp);
-+	i_nround(b1, b0, kp);
-+	i_lround(b0, b1, kp);
- 
- 	dst[0] = cpu_to_le32(b0[0]);
- 	dst[1] = cpu_to_le32(b0[1]);
-@@ -415,14 +430,13 @@ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- 	dst[3] = cpu_to_le32(b0[3]);
- }
- 
--
- static struct crypto_alg aes_alg = {
- 	.cra_name		=	"aes",
- 	.cra_driver_name	=	"aes-generic",
- 	.cra_priority		=	100,
- 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
- 	.cra_blocksize		=	AES_BLOCK_SIZE,
--	.cra_ctxsize		=	sizeof(struct aes_ctx),
-+	.cra_ctxsize		=	sizeof(struct crypto_aes_ctx),
- 	.cra_alignmask		=	3,
- 	.cra_module		=	THIS_MODULE,
- 	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
-@@ -430,9 +444,9 @@ static struct crypto_alg aes_alg = {
- 		.cipher = {
- 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
- 			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
--			.cia_setkey	   	= 	aes_set_key,
--			.cia_encrypt	 	=	aes_encrypt,
--			.cia_decrypt	  	=	aes_decrypt
-+			.cia_setkey		=	crypto_aes_set_key,
-+			.cia_encrypt		=	aes_encrypt,
-+			.cia_decrypt		=	aes_decrypt
- 		}
- 	}
- };
-diff --git a/crypto/algapi.c b/crypto/algapi.c
-index 8383282..e65cb50 100644
---- a/crypto/algapi.c
-+++ b/crypto/algapi.c
-@@ -472,7 +472,7 @@ int crypto_check_attr_type(struct rtattr **tb, u32 type)
- }
- EXPORT_SYMBOL_GPL(crypto_check_attr_type);
- 
--struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
-+const char *crypto_attr_alg_name(struct rtattr *rta)
- {
- 	struct crypto_attr_alg *alga;
- 
-@@ -486,7 +486,21 @@ struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
- 	alga = RTA_DATA(rta);
- 	alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;
- 
--	return crypto_alg_mod_lookup(alga->name, type, mask);
-+	return alga->name;
-+}
-+EXPORT_SYMBOL_GPL(crypto_attr_alg_name);
++	err = crypto_ablkcipher_setkey(ctr, key, keylen);
++	if (err)
++		return err;
 +
-+struct crypto_alg *crypto_attr_alg(struct rtattr *rta, u32 type, u32 mask)
-+{
-+	const char *name;
-+	int err;
++	crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
++				       CRYPTO_TFM_RES_MASK);
 +
-+	name = crypto_attr_alg_name(rta);
-+	err = PTR_ERR(name);
-+	if (IS_ERR(name))
-+		return ERR_PTR(err);
++	data = kzalloc(sizeof(*data) + crypto_ablkcipher_reqsize(ctr),
++		       GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
 +
-+	return crypto_alg_mod_lookup(name, type, mask);
- }
- EXPORT_SYMBOL_GPL(crypto_attr_alg);
- 
-@@ -605,6 +619,53 @@ int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
- }
- EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);
- 
-+static inline void crypto_inc_byte(u8 *a, unsigned int size)
-+{
-+	u8 *b = (a + size);
-+	u8 c;
++	init_completion(&data->result.completion);
++	sg_init_one(data->sg, &data->hash, sizeof(data->hash));
++	ablkcipher_request_set_tfm(&data->req, ctr);
++	ablkcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
++						    CRYPTO_TFM_REQ_MAY_BACKLOG,
++					crypto_gcm_setkey_done,
++					&data->result);
++	ablkcipher_request_set_crypt(&data->req, data->sg, data->sg,
++				     sizeof(data->hash), data->iv);
 +
-+	for (; size; size--) {
-+		c = *--b + 1;
-+		*b = c;
-+		if (c)
-+			break;
++	err = crypto_ablkcipher_encrypt(&data->req);
++	if (err == -EINPROGRESS || err == -EBUSY) {
++		err = wait_for_completion_interruptible(
++			&data->result.completion);
++		if (!err)
++			err = data->result.err;
 +	}
-+}
 +
-+void crypto_inc(u8 *a, unsigned int size)
-+{
-+	__be32 *b = (__be32 *)(a + size);
-+	u32 c;
++	if (err)
++		goto out;
 +
-+	for (; size >= 4; size -= 4) {
-+		c = be32_to_cpu(*--b) + 1;
-+		*b = cpu_to_be32(c);
-+		if (c)
-+			return;
-+	}
++	if (ctx->gf128 != NULL)
++		gf128mul_free_4k(ctx->gf128);
 +
-+	crypto_inc_byte(a, size);
-+}
-+EXPORT_SYMBOL_GPL(crypto_inc);
++	ctx->gf128 = gf128mul_init_4k_lle(&data->hash);
 +
-+static inline void crypto_xor_byte(u8 *a, const u8 *b, unsigned int size)
-+{
-+	for (; size; size--)
-+		*a++ ^= *b++;
++	if (ctx->gf128 == NULL)
++		err = -ENOMEM;
++
++out:
++	kfree(data);
++	return err;
 +}
 +
-+void crypto_xor(u8 *dst, const u8 *src, unsigned int size)
++static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
++				  unsigned int authsize)
 +{
-+	u32 *a = (u32 *)dst;
-+	u32 *b = (u32 *)src;
-+
-+	for (; size >= 4; size -= 4)
-+		*a++ ^= *b++;
-+
-+	crypto_xor_byte((u8 *)a, (u8 *)b, size);
-+}
-+EXPORT_SYMBOL_GPL(crypto_xor);
++	switch (authsize) {
++	case 4:
++	case 8:
++	case 12:
++	case 13:
++	case 14:
++	case 15:
++	case 16:
++		break;
++	default:
++		return -EINVAL;
++	}
 +
- static int __init crypto_algapi_init(void)
- {
- 	crypto_init_proc();
-diff --git a/crypto/api.c b/crypto/api.c
-index 1f5c724..a2496d1 100644
---- a/crypto/api.c
-+++ b/crypto/api.c
-@@ -137,7 +137,7 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
- 	return alg;
- }
- 
--static void crypto_larval_kill(struct crypto_alg *alg)
-+void crypto_larval_kill(struct crypto_alg *alg)
- {
- 	struct crypto_larval *larval = (void *)alg;
- 
-@@ -147,6 +147,7 @@ static void crypto_larval_kill(struct crypto_alg *alg)
- 	complete_all(&larval->completion);
- 	crypto_alg_put(alg);
- }
-+EXPORT_SYMBOL_GPL(crypto_larval_kill);
- 
- static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
- {
-@@ -176,11 +177,9 @@ static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
- 	return alg;
- }
- 
--struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
-+struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
- {
- 	struct crypto_alg *alg;
--	struct crypto_alg *larval;
--	int ok;
- 
- 	if (!name)
- 		return ERR_PTR(-ENOENT);
-@@ -193,7 +192,17 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
- 	if (alg)
- 		return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
- 
--	larval = crypto_larval_alloc(name, type, mask);
-+	return crypto_larval_alloc(name, type, mask);
++	return 0;
 +}
-+EXPORT_SYMBOL_GPL(crypto_larval_lookup);
 +
-+struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
++static void crypto_gcm_init_crypt(struct ablkcipher_request *ablk_req,
++				  struct aead_request *req,
++				  unsigned int cryptlen)
 +{
-+	struct crypto_alg *alg;
-+	struct crypto_alg *larval;
-+	int ok;
-+
-+	larval = crypto_larval_lookup(name, type, mask);
- 	if (IS_ERR(larval) || !crypto_is_larval(larval))
- 		return larval;
- 
-diff --git a/crypto/authenc.c b/crypto/authenc.c
-index 126a529..ed8ac5a 100644
---- a/crypto/authenc.c
-+++ b/crypto/authenc.c
-@@ -10,22 +10,21 @@
-  *
-  */
- 
--#include <crypto/algapi.h>
-+#include <crypto/aead.h>
-+#include <crypto/internal/skcipher.h>
-+#include <crypto/authenc.h>
-+#include <crypto/scatterwalk.h>
- #include <linux/err.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
-+#include <linux/rtnetlink.h>
- #include <linux/slab.h>
- #include <linux/spinlock.h>
- 
--#include "scatterwalk.h"
--
- struct authenc_instance_ctx {
- 	struct crypto_spawn auth;
--	struct crypto_spawn enc;
--
--	unsigned int authsize;
--	unsigned int enckeylen;
-+	struct crypto_skcipher_spawn enc;
- };
- 
- struct crypto_authenc_ctx {
-@@ -37,19 +36,31 @@ struct crypto_authenc_ctx {
- static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
- 				 unsigned int keylen)
- {
--	struct authenc_instance_ctx *ictx =
--		crypto_instance_ctx(crypto_aead_alg_instance(authenc));
--	unsigned int enckeylen = ictx->enckeylen;
- 	unsigned int authkeylen;
-+	unsigned int enckeylen;
- 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- 	struct crypto_hash *auth = ctx->auth;
- 	struct crypto_ablkcipher *enc = ctx->enc;
-+	struct rtattr *rta = (void *)key;
-+	struct crypto_authenc_key_param *param;
- 	int err = -EINVAL;
- 
--	if (keylen < enckeylen) {
--		crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
--		goto out;
--	}
-+	if (!RTA_OK(rta, keylen))
-+		goto badkey;
-+	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-+		goto badkey;
-+	if (RTA_PAYLOAD(rta) < sizeof(*param))
-+		goto badkey;
-+
-+	param = RTA_DATA(rta);
-+	enckeylen = be32_to_cpu(param->enckeylen);
-+
-+	key += RTA_ALIGN(rta->rta_len);
-+	keylen -= RTA_ALIGN(rta->rta_len);
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
++	u32 flags = req->base.tfm->crt_flags;
++	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
++	struct scatterlist *dst;
++	__be32 counter = cpu_to_be32(1);
 +
-+	if (keylen < enckeylen)
-+		goto badkey;
++	memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag));
++	memcpy(req->iv + 12, &counter, 4);
 +
- 	authkeylen = keylen - enckeylen;
- 
- 	crypto_hash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
-@@ -71,21 +82,38 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key,
- 
- out:
- 	return err;
++	sg_init_table(pctx->src, 2);
++	sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
++	scatterwalk_sg_chain(pctx->src, 2, req->src);
 +
-+badkey:
-+	crypto_aead_set_flags(authenc, CRYPTO_TFM_RES_BAD_KEY_LEN);
-+	goto out;
- }
- 
--static int crypto_authenc_hash(struct aead_request *req)
-+static void authenc_chain(struct scatterlist *head, struct scatterlist *sg,
-+			  int chain)
-+{
-+	if (chain) {
-+		head->length += sg->length;
-+		sg = scatterwalk_sg_next(sg);
++	dst = pctx->src;
++	if (req->src != req->dst) {
++		sg_init_table(pctx->dst, 2);
++		sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
++		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
++		dst = pctx->dst;
 +	}
 +
-+	if (sg)
-+		scatterwalk_sg_chain(head, 2, sg);
-+	else
-+		sg_mark_end(head);
-+}
++	ablkcipher_request_set_tfm(ablk_req, ctx->ctr);
++	ablkcipher_request_set_crypt(ablk_req, pctx->src, dst,
++				     cryptlen + sizeof(pctx->auth_tag),
++				     req->iv);
 +
-+static u8 *crypto_authenc_hash(struct aead_request *req, unsigned int flags,
-+			       struct scatterlist *cipher,
-+			       unsigned int cryptlen)
- {
- 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
--	struct authenc_instance_ctx *ictx =
--		crypto_instance_ctx(crypto_aead_alg_instance(authenc));
- 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- 	struct crypto_hash *auth = ctx->auth;
- 	struct hash_desc desc = {
- 		.tfm = auth,
-+		.flags = aead_request_flags(req) & flags,
- 	};
- 	u8 *hash = aead_request_ctx(req);
--	struct scatterlist *dst = req->dst;
--	unsigned int cryptlen = req->cryptlen;
- 	int err;
- 
- 	hash = (u8 *)ALIGN((unsigned long)hash + crypto_hash_alignmask(auth), 
-@@ -100,7 +128,7 @@ static int crypto_authenc_hash(struct aead_request *req)
- 	if (err)
- 		goto auth_unlock;
- 
--	err = crypto_hash_update(&desc, dst, cryptlen);
-+	err = crypto_hash_update(&desc, cipher, cryptlen);
- 	if (err)
- 		goto auth_unlock;
- 
-@@ -109,17 +137,53 @@ auth_unlock:
- 	spin_unlock_bh(&ctx->auth_lock);
- 
- 	if (err)
--		return err;
-+		return ERR_PTR(err);
++	crypto_gcm_ghash_init(ghash, flags, ctx->gf128);
 +
-+	return hash;
++	crypto_gcm_ghash_update_sg(ghash, req->assoc, req->assoclen);
++	crypto_gcm_ghash_flush(ghash);
 +}
- 
--	scatterwalk_map_and_copy(hash, dst, cryptlen, ictx->authsize, 1);
-+static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
-+				 unsigned int flags)
++
++static int crypto_gcm_hash(struct aead_request *req)
 +{
-+	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-+	struct scatterlist *dst = req->dst;
-+	struct scatterlist cipher[2];
-+	struct page *dstp;
-+	unsigned int ivsize = crypto_aead_ivsize(authenc);
-+	unsigned int cryptlen;
-+	u8 *vdst;
-+	u8 *hash;
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
++	u8 *auth_tag = pctx->auth_tag;
++	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
 +
-+	dstp = sg_page(dst);
-+	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
++	crypto_gcm_ghash_update_sg(ghash, req->dst, req->cryptlen);
++	crypto_gcm_ghash_final_xor(ghash, req->assoclen, req->cryptlen,
++				   auth_tag);
 +
-+	sg_init_table(cipher, 2);
-+	sg_set_buf(cipher, iv, ivsize);
-+	authenc_chain(cipher, dst, vdst == iv + ivsize);
++	scatterwalk_map_and_copy(auth_tag, req->dst, req->cryptlen,
++				 crypto_aead_authsize(aead), 1);
++	return 0;
++}
 +
-+	cryptlen = req->cryptlen + ivsize;
-+	hash = crypto_authenc_hash(req, flags, cipher, cryptlen);
-+	if (IS_ERR(hash))
-+		return PTR_ERR(hash);
++static void crypto_gcm_encrypt_done(struct crypto_async_request *areq, int err)
++{
++	struct aead_request *req = areq->data;
 +
-+	scatterwalk_map_and_copy(hash, cipher, cryptlen,
-+				 crypto_aead_authsize(authenc), 1);
- 	return 0;
- }
- 
- static void crypto_authenc_encrypt_done(struct crypto_async_request *req,
- 					int err)
- {
--	if (!err)
--		err = crypto_authenc_hash(req->data);
-+	if (!err) {
-+		struct aead_request *areq = req->data;
-+		struct crypto_aead *authenc = crypto_aead_reqtfm(areq);
-+		struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
-+		struct ablkcipher_request *abreq = aead_request_ctx(areq);
-+		u8 *iv = (u8 *)(abreq + 1) +
-+			 crypto_ablkcipher_reqsize(ctx->enc);
++	if (!err)
++		err = crypto_gcm_hash(req);
 +
-+		err = crypto_authenc_genicv(areq, iv, 0);
-+	}
- 
- 	aead_request_complete(req->data, err);
- }
-@@ -129,72 +193,99 @@ static int crypto_authenc_encrypt(struct aead_request *req)
- 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
- 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- 	struct ablkcipher_request *abreq = aead_request_ctx(req);
-+	struct crypto_ablkcipher *enc = ctx->enc;
-+	struct scatterlist *dst = req->dst;
-+	unsigned int cryptlen = req->cryptlen;
-+	u8 *iv = (u8 *)(abreq + 1) + crypto_ablkcipher_reqsize(enc);
- 	int err;
- 
--	ablkcipher_request_set_tfm(abreq, ctx->enc);
-+	ablkcipher_request_set_tfm(abreq, enc);
- 	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
- 					crypto_authenc_encrypt_done, req);
--	ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
--				     req->iv);
-+	ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
++	aead_request_complete(req, err);
++}
 +
-+	memcpy(iv, req->iv, crypto_aead_ivsize(authenc));
- 
- 	err = crypto_ablkcipher_encrypt(abreq);
- 	if (err)
- 		return err;
- 
--	return crypto_authenc_hash(req);
-+	return crypto_authenc_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
- }
- 
--static int crypto_authenc_verify(struct aead_request *req)
-+static void crypto_authenc_givencrypt_done(struct crypto_async_request *req,
-+					   int err)
- {
--	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
--	struct authenc_instance_ctx *ictx =
--		crypto_instance_ctx(crypto_aead_alg_instance(authenc));
-+	if (!err) {
-+		struct aead_givcrypt_request *greq = req->data;
++static int crypto_gcm_encrypt(struct aead_request *req)
++{
++	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
++	struct ablkcipher_request *abreq = &pctx->abreq;
++	int err;
 +
-+		err = crypto_authenc_genicv(&greq->areq, greq->giv, 0);
-+	}
++	crypto_gcm_init_crypt(abreq, req, req->cryptlen);
++	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
++					crypto_gcm_encrypt_done, req);
 +
-+	aead_request_complete(req->data, err);
++	err = crypto_ablkcipher_encrypt(abreq);
++	if (err)
++		return err;
++
++	return crypto_gcm_hash(req);
 +}
 +
-+static int crypto_authenc_givencrypt(struct aead_givcrypt_request *req)
++static int crypto_gcm_verify(struct aead_request *req)
 +{
-+	struct crypto_aead *authenc = aead_givcrypt_reqtfm(req);
- 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
--	struct crypto_hash *auth = ctx->auth;
--	struct hash_desc desc = {
--		.tfm = auth,
--		.flags = aead_request_flags(req),
--	};
--	u8 *ohash = aead_request_ctx(req);
--	u8 *ihash;
--	struct scatterlist *src = req->src;
--	unsigned int cryptlen = req->cryptlen;
--	unsigned int authsize;
-+	struct aead_request *areq = &req->areq;
-+	struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
-+	u8 *iv = req->giv;
- 	int err;
- 
--	ohash = (u8 *)ALIGN((unsigned long)ohash + crypto_hash_alignmask(auth), 
--			    crypto_hash_alignmask(auth) + 1);
--	ihash = ohash + crypto_hash_digestsize(auth);
--
--	spin_lock_bh(&ctx->auth_lock);
--	err = crypto_hash_init(&desc);
--	if (err)
--		goto auth_unlock;
-+	skcipher_givcrypt_set_tfm(greq, ctx->enc);
-+	skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
-+				       crypto_authenc_givencrypt_done, areq);
-+	skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
-+				    areq->iv);
-+	skcipher_givcrypt_set_giv(greq, iv, req->seq);
- 
--	err = crypto_hash_update(&desc, req->assoc, req->assoclen);
-+	err = crypto_skcipher_givencrypt(greq);
- 	if (err)
--		goto auth_unlock;
-+		return err;
- 
--	err = crypto_hash_update(&desc, src, cryptlen);
--	if (err)
--		goto auth_unlock;
-+	return crypto_authenc_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
++	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
++	u8 *auth_tag = pctx->auth_tag;
++	u8 *iauth_tag = pctx->iauth_tag;
++	unsigned int authsize = crypto_aead_authsize(aead);
++	unsigned int cryptlen = req->cryptlen - authsize;
++
++	crypto_gcm_ghash_final_xor(ghash, req->assoclen, cryptlen, auth_tag);
++
++	authsize = crypto_aead_authsize(aead);
++	scatterwalk_map_and_copy(iauth_tag, req->src, cryptlen, authsize, 0);
++	return memcmp(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
 +}
- 
--	err = crypto_hash_final(&desc, ohash);
--auth_unlock:
--	spin_unlock_bh(&ctx->auth_lock);
-+static int crypto_authenc_verify(struct aead_request *req,
-+				 struct scatterlist *cipher,
-+				 unsigned int cryptlen)
++
++static void crypto_gcm_decrypt_done(struct crypto_async_request *areq, int err)
 +{
-+	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-+	u8 *ohash;
-+	u8 *ihash;
-+	unsigned int authsize;
- 
--	if (err)
--		return err;
-+	ohash = crypto_authenc_hash(req, CRYPTO_TFM_REQ_MAY_SLEEP, cipher,
-+				    cryptlen);
-+	if (IS_ERR(ohash))
-+		return PTR_ERR(ohash);
- 
--	authsize = ictx->authsize;
--	scatterwalk_map_and_copy(ihash, src, cryptlen, authsize, 0);
--	return memcmp(ihash, ohash, authsize) ? -EINVAL : 0;
-+	authsize = crypto_aead_authsize(authenc);
-+	ihash = ohash + authsize;
-+	scatterwalk_map_and_copy(ihash, cipher, cryptlen, authsize, 0);
-+	return memcmp(ihash, ohash, authsize) ? -EBADMSG: 0;
- }
- 
--static void crypto_authenc_decrypt_done(struct crypto_async_request *req,
--					int err)
-+static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
-+				  unsigned int cryptlen)
- {
--	aead_request_complete(req->data, err);
-+	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
-+	struct scatterlist *src = req->src;
-+	struct scatterlist cipher[2];
-+	struct page *srcp;
-+	unsigned int ivsize = crypto_aead_ivsize(authenc);
-+	u8 *vsrc;
++	struct aead_request *req = areq->data;
 +
-+	srcp = sg_page(src);
-+	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
++	if (!err)
++		err = crypto_gcm_verify(req);
 +
-+	sg_init_table(cipher, 2);
-+	sg_set_buf(cipher, iv, ivsize);
-+	authenc_chain(cipher, src, vsrc == iv + ivsize);
++	aead_request_complete(req, err);
++}
 +
-+	return crypto_authenc_verify(req, cipher, cryptlen + ivsize);
- }
- 
- static int crypto_authenc_decrypt(struct aead_request *req)
-@@ -202,17 +293,23 @@ static int crypto_authenc_decrypt(struct aead_request *req)
- 	struct crypto_aead *authenc = crypto_aead_reqtfm(req);
- 	struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
- 	struct ablkcipher_request *abreq = aead_request_ctx(req);
++static int crypto_gcm_decrypt(struct aead_request *req)
++{
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
++	struct ablkcipher_request *abreq = &pctx->abreq;
++	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
 +	unsigned int cryptlen = req->cryptlen;
-+	unsigned int authsize = crypto_aead_authsize(authenc);
-+	u8 *iv = req->iv;
- 	int err;
- 
--	err = crypto_authenc_verify(req);
++	unsigned int authsize = crypto_aead_authsize(aead);
++	int err;
++
 +	if (cryptlen < authsize)
 +		return -EINVAL;
 +	cryptlen -= authsize;
 +
-+	err = crypto_authenc_iverify(req, iv, cryptlen);
- 	if (err)
- 		return err;
- 
- 	ablkcipher_request_set_tfm(abreq, ctx->enc);
- 	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
--					crypto_authenc_decrypt_done, req);
--	ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
--				     req->iv);
-+					req->base.complete, req->base.data);
-+	ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
- 
- 	return crypto_ablkcipher_decrypt(abreq);
- }
-@@ -224,19 +321,13 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
- 	struct crypto_authenc_ctx *ctx = crypto_tfm_ctx(tfm);
- 	struct crypto_hash *auth;
- 	struct crypto_ablkcipher *enc;
--	unsigned int digestsize;
- 	int err;
- 
- 	auth = crypto_spawn_hash(&ictx->auth);
- 	if (IS_ERR(auth))
- 		return PTR_ERR(auth);
- 
--	err = -EINVAL;
--	digestsize = crypto_hash_digestsize(auth);
--	if (ictx->authsize > digestsize)
--		goto err_free_hash;
--
--	enc = crypto_spawn_ablkcipher(&ictx->enc);
-+	enc = crypto_spawn_skcipher(&ictx->enc);
- 	err = PTR_ERR(enc);
- 	if (IS_ERR(enc))
- 		goto err_free_hash;
-@@ -246,9 +337,10 @@ static int crypto_authenc_init_tfm(struct crypto_tfm *tfm)
- 	tfm->crt_aead.reqsize = max_t(unsigned int,
- 				      (crypto_hash_alignmask(auth) &
- 				       ~(crypto_tfm_ctx_alignment() - 1)) +
--				      digestsize * 2,
--				      sizeof(struct ablkcipher_request) +
--				      crypto_ablkcipher_reqsize(enc));
-+				      crypto_hash_digestsize(auth) * 2,
-+				      sizeof(struct skcipher_givcrypt_request) +
-+				      crypto_ablkcipher_reqsize(enc) +
-+				      crypto_ablkcipher_ivsize(enc));
- 
- 	spin_lock_init(&ctx->auth_lock);
- 
-@@ -269,75 +361,74 @@ static void crypto_authenc_exit_tfm(struct crypto_tfm *tfm)
- 
- static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
- {
-+	struct crypto_attr_type *algt;
- 	struct crypto_instance *inst;
- 	struct crypto_alg *auth;
- 	struct crypto_alg *enc;
- 	struct authenc_instance_ctx *ctx;
--	unsigned int authsize;
--	unsigned int enckeylen;
-+	const char *enc_name;
- 	int err;
- 
--	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD);
--	if (err)
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
- 		return ERR_PTR(err);
- 
-+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-+		return ERR_PTR(-EINVAL);
++	crypto_gcm_init_crypt(abreq, req, cryptlen);
++	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
++					crypto_gcm_decrypt_done, req);
 +
- 	auth = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
- 			       CRYPTO_ALG_TYPE_HASH_MASK);
- 	if (IS_ERR(auth))
- 		return ERR_PTR(PTR_ERR(auth));
- 
--	err = crypto_attr_u32(tb[2], &authsize);
--	inst = ERR_PTR(err);
--	if (err)
--		goto out_put_auth;
--
--	enc = crypto_attr_alg(tb[3], CRYPTO_ALG_TYPE_BLKCIPHER,
--			      CRYPTO_ALG_TYPE_MASK);
--	inst = ERR_PTR(PTR_ERR(enc));
--	if (IS_ERR(enc))
-+	enc_name = crypto_attr_alg_name(tb[2]);
-+	err = PTR_ERR(enc_name);
-+	if (IS_ERR(enc_name))
- 		goto out_put_auth;
- 
--	err = crypto_attr_u32(tb[4], &enckeylen);
--	if (err)
--		goto out_put_enc;
--
- 	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
- 	err = -ENOMEM;
- 	if (!inst)
--		goto out_put_enc;
--
--	err = -ENAMETOOLONG;
--	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
--		     "authenc(%s,%u,%s,%u)", auth->cra_name, authsize,
--		     enc->cra_name, enckeylen) >= CRYPTO_MAX_ALG_NAME)
--		goto err_free_inst;
--
--	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
--		     "authenc(%s,%u,%s,%u)", auth->cra_driver_name,
--		     authsize, enc->cra_driver_name, enckeylen) >=
--	    CRYPTO_MAX_ALG_NAME)
--		goto err_free_inst;
-+		goto out_put_auth;
- 
- 	ctx = crypto_instance_ctx(inst);
--	ctx->authsize = authsize;
--	ctx->enckeylen = enckeylen;
- 
- 	err = crypto_init_spawn(&ctx->auth, auth, inst, CRYPTO_ALG_TYPE_MASK);
- 	if (err)
- 		goto err_free_inst;
- 
--	err = crypto_init_spawn(&ctx->enc, enc, inst, CRYPTO_ALG_TYPE_MASK);
-+	crypto_set_skcipher_spawn(&ctx->enc, inst);
-+	err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
-+				   crypto_requires_sync(algt->type,
-+							algt->mask));
- 	if (err)
- 		goto err_drop_auth;
- 
--	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC;
-+	enc = crypto_skcipher_spawn_alg(&ctx->enc);
++	crypto_gcm_ghash_update_sg(ghash, req->src, cryptlen);
 +
-+	err = -ENAMETOOLONG;
-+	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-+		     "authenc(%s,%s)", auth->cra_name, enc->cra_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		goto err_drop_enc;
++	err = crypto_ablkcipher_decrypt(abreq);
++	if (err)
++		return err;
 +
-+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+		     "authenc(%s,%s)", auth->cra_driver_name,
-+		     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
-+		goto err_drop_enc;
++	return crypto_gcm_verify(req);
++}
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-+	inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
- 	inst->alg.cra_priority = enc->cra_priority * 10 + auth->cra_priority;
- 	inst->alg.cra_blocksize = enc->cra_blocksize;
--	inst->alg.cra_alignmask = max(auth->cra_alignmask, enc->cra_alignmask);
-+	inst->alg.cra_alignmask = auth->cra_alignmask | enc->cra_alignmask;
- 	inst->alg.cra_type = &crypto_aead_type;
- 
--	inst->alg.cra_aead.ivsize = enc->cra_blkcipher.ivsize;
--	inst->alg.cra_aead.authsize = authsize;
-+	inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
-+	inst->alg.cra_aead.maxauthsize = auth->cra_type == &crypto_hash_type ?
-+					 auth->cra_hash.digestsize :
-+					 auth->cra_digest.dia_digestsize;
- 
- 	inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_ctx);
- 
-@@ -347,18 +438,19 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
- 	inst->alg.cra_aead.setkey = crypto_authenc_setkey;
- 	inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
- 	inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
-+	inst->alg.cra_aead.givencrypt = crypto_authenc_givencrypt;
- 
- out:
--	crypto_mod_put(enc);
--out_put_auth:
- 	crypto_mod_put(auth);
- 	return inst;
- 
-+err_drop_enc:
-+	crypto_drop_skcipher(&ctx->enc);
- err_drop_auth:
- 	crypto_drop_spawn(&ctx->auth);
- err_free_inst:
- 	kfree(inst);
--out_put_enc:
-+out_put_auth:
- 	inst = ERR_PTR(err);
- 	goto out;
- }
-@@ -367,7 +459,7 @@ static void crypto_authenc_free(struct crypto_instance *inst)
- {
- 	struct authenc_instance_ctx *ctx = crypto_instance_ctx(inst);
- 
--	crypto_drop_spawn(&ctx->enc);
-+	crypto_drop_skcipher(&ctx->enc);
- 	crypto_drop_spawn(&ctx->auth);
- 	kfree(inst);
- }
-diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
-index f6c67f9..4a7e65c 100644
---- a/crypto/blkcipher.c
-+++ b/crypto/blkcipher.c
-@@ -14,7 +14,8 @@
-  *
-  */
- 
--#include <linux/crypto.h>
-+#include <crypto/internal/skcipher.h>
-+#include <crypto/scatterwalk.h>
- #include <linux/errno.h>
- #include <linux/hardirq.h>
- #include <linux/kernel.h>
-@@ -25,7 +26,6 @@
- #include <linux/string.h>
- 
- #include "internal.h"
--#include "scatterwalk.h"
- 
- enum {
- 	BLKCIPHER_WALK_PHYS = 1 << 0,
-@@ -433,9 +433,8 @@ static unsigned int crypto_blkcipher_ctxsize(struct crypto_alg *alg, u32 type,
- 	struct blkcipher_alg *cipher = &alg->cra_blkcipher;
- 	unsigned int len = alg->cra_ctxsize;
- 
--	type ^= CRYPTO_ALG_ASYNC;
--	mask &= CRYPTO_ALG_ASYNC;
--	if ((type & mask) && cipher->ivsize) {
-+	if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK &&
-+	    cipher->ivsize) {
- 		len = ALIGN(len, (unsigned long)alg->cra_alignmask + 1);
- 		len += cipher->ivsize;
- 	}
-@@ -451,6 +450,11 @@ static int crypto_init_blkcipher_ops_async(struct crypto_tfm *tfm)
- 	crt->setkey = async_setkey;
- 	crt->encrypt = async_encrypt;
- 	crt->decrypt = async_decrypt;
-+	if (!alg->ivsize) {
-+		crt->givencrypt = skcipher_null_givencrypt;
-+		crt->givdecrypt = skcipher_null_givdecrypt;
-+	}
-+	crt->base = __crypto_ablkcipher_cast(tfm);
- 	crt->ivsize = alg->ivsize;
- 
- 	return 0;
-@@ -482,9 +486,7 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
- 	if (alg->ivsize > PAGE_SIZE / 8)
- 		return -EINVAL;
- 
--	type ^= CRYPTO_ALG_ASYNC;
--	mask &= CRYPTO_ALG_ASYNC;
--	if (type & mask)
-+	if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK)
- 		return crypto_init_blkcipher_ops_sync(tfm);
- 	else
- 		return crypto_init_blkcipher_ops_async(tfm);
-@@ -499,6 +501,8 @@ static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
- 	seq_printf(m, "min keysize  : %u\n", alg->cra_blkcipher.min_keysize);
- 	seq_printf(m, "max keysize  : %u\n", alg->cra_blkcipher.max_keysize);
- 	seq_printf(m, "ivsize       : %u\n", alg->cra_blkcipher.ivsize);
-+	seq_printf(m, "geniv        : %s\n", alg->cra_blkcipher.geniv ?:
-+					     "<default>");
- }
- 
- const struct crypto_type crypto_blkcipher_type = {
-@@ -510,5 +514,187 @@ const struct crypto_type crypto_blkcipher_type = {
- };
- EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
- 
-+static int crypto_grab_nivcipher(struct crypto_skcipher_spawn *spawn,
-+				const char *name, u32 type, u32 mask)
++static int crypto_gcm_init_tfm(struct crypto_tfm *tfm)
 +{
-+	struct crypto_alg *alg;
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct gcm_instance_ctx *ictx = crypto_instance_ctx(inst);
++	struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_ablkcipher *ctr;
++	unsigned long align;
 +	int err;
 +
-+	type = crypto_skcipher_type(type);
-+	mask = crypto_skcipher_mask(mask) | CRYPTO_ALG_GENIV;
++	ctr = crypto_spawn_skcipher(&ictx->ctr);
++	err = PTR_ERR(ctr);
++	if (IS_ERR(ctr))
++		return err;
 +
-+	alg = crypto_alg_mod_lookup(name, type, mask);
-+	if (IS_ERR(alg))
-+		return PTR_ERR(alg);
++	ctx->ctr = ctr;
++	ctx->gf128 = NULL;
 +
-+	err = crypto_init_spawn(&spawn->base, alg, spawn->base.inst, mask);
-+	crypto_mod_put(alg);
-+	return err;
++	align = crypto_tfm_alg_alignmask(tfm);
++	align &= ~(crypto_tfm_ctx_alignment() - 1);
++	tfm->crt_aead.reqsize = align +
++				sizeof(struct crypto_gcm_req_priv_ctx) +
++				crypto_ablkcipher_reqsize(ctr);
++
++	return 0;
 +}
 +
-+struct crypto_instance *skcipher_geniv_alloc(struct crypto_template *tmpl,
-+					     struct rtattr **tb, u32 type,
-+					     u32 mask)
++static void crypto_gcm_exit_tfm(struct crypto_tfm *tfm)
 +{
-+	struct {
-+		int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
-+			      unsigned int keylen);
-+		int (*encrypt)(struct ablkcipher_request *req);
-+		int (*decrypt)(struct ablkcipher_request *req);
++	struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
 +
-+		unsigned int min_keysize;
-+		unsigned int max_keysize;
-+		unsigned int ivsize;
++	if (ctx->gf128 != NULL)
++		gf128mul_free_4k(ctx->gf128);
 +
-+		const char *geniv;
-+	} balg;
-+	const char *name;
-+	struct crypto_skcipher_spawn *spawn;
++	crypto_free_ablkcipher(ctx->ctr);
++}
++
++static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb,
++						       const char *full_name,
++						       const char *ctr_name)
++{
 +	struct crypto_attr_type *algt;
 +	struct crypto_instance *inst;
-+	struct crypto_alg *alg;
++	struct crypto_alg *ctr;
++	struct gcm_instance_ctx *ctx;
 +	int err;
 +
 +	algt = crypto_get_attr_type(tb);
@@ -353167,2204 +383576,589 @@
 +	if (IS_ERR(algt))
 +		return ERR_PTR(err);
 +
-+	if ((algt->type ^ (CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV)) &
-+	    algt->mask)
++	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
 +		return ERR_PTR(-EINVAL);
 +
-+	name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(name);
-+	if (IS_ERR(name))
-+		return ERR_PTR(err);
-+
-+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
++	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
 +	if (!inst)
 +		return ERR_PTR(-ENOMEM);
 +
-+	spawn = crypto_instance_ctx(inst);
-+
-+	/* Ignore async algorithms if necessary. */
-+	mask |= crypto_requires_sync(algt->type, algt->mask);
-+
-+	crypto_set_skcipher_spawn(spawn, inst);
-+	err = crypto_grab_nivcipher(spawn, name, type, mask);
-+	if (err)
-+		goto err_free_inst;
-+
-+	alg = crypto_skcipher_spawn_alg(spawn);
-+
-+	if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
-+	    CRYPTO_ALG_TYPE_BLKCIPHER) {
-+		balg.ivsize = alg->cra_blkcipher.ivsize;
-+		balg.min_keysize = alg->cra_blkcipher.min_keysize;
-+		balg.max_keysize = alg->cra_blkcipher.max_keysize;
-+
-+		balg.setkey = async_setkey;
-+		balg.encrypt = async_encrypt;
-+		balg.decrypt = async_decrypt;
-+
-+		balg.geniv = alg->cra_blkcipher.geniv;
-+	} else {
-+		balg.ivsize = alg->cra_ablkcipher.ivsize;
-+		balg.min_keysize = alg->cra_ablkcipher.min_keysize;
-+		balg.max_keysize = alg->cra_ablkcipher.max_keysize;
-+
-+		balg.setkey = alg->cra_ablkcipher.setkey;
-+		balg.encrypt = alg->cra_ablkcipher.encrypt;
-+		balg.decrypt = alg->cra_ablkcipher.decrypt;
-+
-+		balg.geniv = alg->cra_ablkcipher.geniv;
-+	}
-+
-+	err = -EINVAL;
-+	if (!balg.ivsize)
-+		goto err_drop_alg;
-+
-+	/*
-+	 * This is only true if we're constructing an algorithm with its
-+	 * default IV generator.  For the default generator we elide the
-+	 * template name and double-check the IV generator.
-+	 */
-+	if (algt->mask & CRYPTO_ALG_GENIV) {
-+		if (!balg.geniv)
-+			balg.geniv = crypto_default_geniv(alg);
-+		err = -EAGAIN;
-+		if (strcmp(tmpl->name, balg.geniv))
-+			goto err_drop_alg;
-+
-+		memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
-+		memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
-+		       CRYPTO_MAX_ALG_NAME);
-+	} else {
-+		err = -ENAMETOOLONG;
-+		if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-+			     "%s(%s)", tmpl->name, alg->cra_name) >=
-+		    CRYPTO_MAX_ALG_NAME)
-+			goto err_drop_alg;
-+		if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+			     "%s(%s)", tmpl->name, alg->cra_driver_name) >=
-+		    CRYPTO_MAX_ALG_NAME)
-+			goto err_drop_alg;
-+	}
++	ctx = crypto_instance_ctx(inst);
++	crypto_set_skcipher_spawn(&ctx->ctr, inst);
++	err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0,
++				   crypto_requires_sync(algt->type,
++							algt->mask));
++	if (err)
++		goto err_free_inst;
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_GENIV;
-+	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_priority = alg->cra_priority;
-+	inst->alg.cra_blocksize = alg->cra_blocksize;
-+	inst->alg.cra_alignmask = alg->cra_alignmask;
-+	inst->alg.cra_type = &crypto_givcipher_type;
++	ctr = crypto_skcipher_spawn_alg(&ctx->ctr);
 +
-+	inst->alg.cra_ablkcipher.ivsize = balg.ivsize;
-+	inst->alg.cra_ablkcipher.min_keysize = balg.min_keysize;
-+	inst->alg.cra_ablkcipher.max_keysize = balg.max_keysize;
-+	inst->alg.cra_ablkcipher.geniv = balg.geniv;
++	/* We only support 16-byte blocks. */
++	if (ctr->cra_ablkcipher.ivsize != 16)
++		goto out_put_ctr;
 +
-+	inst->alg.cra_ablkcipher.setkey = balg.setkey;
-+	inst->alg.cra_ablkcipher.encrypt = balg.encrypt;
-+	inst->alg.cra_ablkcipher.decrypt = balg.decrypt;
++	/* Not a stream cipher? */
++	err = -EINVAL;
++	if (ctr->cra_blocksize != 1)
++		goto out_put_ctr;
++
++	err = -ENAMETOOLONG;
++	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++		     "gcm_base(%s)", ctr->cra_driver_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		goto out_put_ctr;
++
++	memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
++	inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
++	inst->alg.cra_priority = ctr->cra_priority;
++	inst->alg.cra_blocksize = 1;
++	inst->alg.cra_alignmask = ctr->cra_alignmask | (__alignof__(u64) - 1);
++	inst->alg.cra_type = &crypto_aead_type;
++	inst->alg.cra_aead.ivsize = 16;
++	inst->alg.cra_aead.maxauthsize = 16;
++	inst->alg.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
++	inst->alg.cra_init = crypto_gcm_init_tfm;
++	inst->alg.cra_exit = crypto_gcm_exit_tfm;
++	inst->alg.cra_aead.setkey = crypto_gcm_setkey;
++	inst->alg.cra_aead.setauthsize = crypto_gcm_setauthsize;
++	inst->alg.cra_aead.encrypt = crypto_gcm_encrypt;
++	inst->alg.cra_aead.decrypt = crypto_gcm_decrypt;
 +
 +out:
 +	return inst;
 +
-+err_drop_alg:
-+	crypto_drop_skcipher(spawn);
++out_put_ctr:
++	crypto_drop_skcipher(&ctx->ctr);
 +err_free_inst:
 +	kfree(inst);
 +	inst = ERR_PTR(err);
 +	goto out;
 +}
-+EXPORT_SYMBOL_GPL(skcipher_geniv_alloc);
 +
-+void skcipher_geniv_free(struct crypto_instance *inst)
++static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
 +{
-+	crypto_drop_skcipher(crypto_instance_ctx(inst));
++	int err;
++	const char *cipher_name;
++	char ctr_name[CRYPTO_MAX_ALG_NAME];
++	char full_name[CRYPTO_MAX_ALG_NAME];
++
++	cipher_name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(cipher_name);
++	if (IS_ERR(cipher_name))
++		return ERR_PTR(err);
++
++	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		return ERR_PTR(-ENAMETOOLONG);
++
++	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm(%s)", cipher_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		return ERR_PTR(-ENAMETOOLONG);
++
++	return crypto_gcm_alloc_common(tb, full_name, ctr_name);
++}
++
++static void crypto_gcm_free(struct crypto_instance *inst)
++{
++	struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst);
++
++	crypto_drop_skcipher(&ctx->ctr);
 +	kfree(inst);
 +}
-+EXPORT_SYMBOL_GPL(skcipher_geniv_free);
 +
-+int skcipher_geniv_init(struct crypto_tfm *tfm)
++static struct crypto_template crypto_gcm_tmpl = {
++	.name = "gcm",
++	.alloc = crypto_gcm_alloc,
++	.free = crypto_gcm_free,
++	.module = THIS_MODULE,
++};
++
++static struct crypto_instance *crypto_gcm_base_alloc(struct rtattr **tb)
 +{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct crypto_ablkcipher *cipher;
++	int err;
++	const char *ctr_name;
++	char full_name[CRYPTO_MAX_ALG_NAME];
 +
-+	cipher = crypto_spawn_skcipher(crypto_instance_ctx(inst));
-+	if (IS_ERR(cipher))
-+		return PTR_ERR(cipher);
++	ctr_name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(ctr_name);
++	if (IS_ERR(ctr_name))
++		return ERR_PTR(err);
 +
-+	tfm->crt_ablkcipher.base = cipher;
-+	tfm->crt_ablkcipher.reqsize += crypto_ablkcipher_reqsize(cipher);
++	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s)",
++		     ctr_name) >= CRYPTO_MAX_ALG_NAME)
++		return ERR_PTR(-ENAMETOOLONG);
 +
-+	return 0;
++	return crypto_gcm_alloc_common(tb, full_name, ctr_name);
 +}
-+EXPORT_SYMBOL_GPL(skcipher_geniv_init);
 +
-+void skcipher_geniv_exit(struct crypto_tfm *tfm)
++static struct crypto_template crypto_gcm_base_tmpl = {
++	.name = "gcm_base",
++	.alloc = crypto_gcm_base_alloc,
++	.free = crypto_gcm_free,
++	.module = THIS_MODULE,
++};
++
++static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key,
++				 unsigned int keylen)
 +{
-+	crypto_free_ablkcipher(tfm->crt_ablkcipher.base);
++	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
++	struct crypto_aead *child = ctx->child;
++	int err;
++
++	if (keylen < 4)
++		return -EINVAL;
++
++	keylen -= 4;
++	memcpy(ctx->nonce, key + keylen, 4);
++
++	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
++	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
++				     CRYPTO_TFM_REQ_MASK);
++	err = crypto_aead_setkey(child, key, keylen);
++	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
++				      CRYPTO_TFM_RES_MASK);
++
++	return err;
 +}
-+EXPORT_SYMBOL_GPL(skcipher_geniv_exit);
 +
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Generic block chaining cipher type");
-diff --git a/crypto/camellia.c b/crypto/camellia.c
-index 6877ecf..493fee7 100644
---- a/crypto/camellia.c
-+++ b/crypto/camellia.c
-@@ -36,176 +36,6 @@
- #include <linux/kernel.h>
- #include <linux/module.h>
- 
--
--#define CAMELLIA_MIN_KEY_SIZE        16
--#define CAMELLIA_MAX_KEY_SIZE        32
--#define CAMELLIA_BLOCK_SIZE 16
--#define CAMELLIA_TABLE_BYTE_LEN 272
--#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / 4)
--
--typedef u32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN];
--
--
--/* key constants */
--
--#define CAMELLIA_SIGMA1L (0xA09E667FL)
--#define CAMELLIA_SIGMA1R (0x3BCC908BL)
--#define CAMELLIA_SIGMA2L (0xB67AE858L)
--#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
--#define CAMELLIA_SIGMA3L (0xC6EF372FL)
--#define CAMELLIA_SIGMA3R (0xE94F82BEL)
--#define CAMELLIA_SIGMA4L (0x54FF53A5L)
--#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
--#define CAMELLIA_SIGMA5L (0x10E527FAL)
--#define CAMELLIA_SIGMA5R (0xDE682D1DL)
--#define CAMELLIA_SIGMA6L (0xB05688C2L)
--#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
--
--struct camellia_ctx {
--	int key_length;
--	KEY_TABLE_TYPE key_table;
--};
--
--
--/*
-- *  macros
-- */
--
--
--# define GETU32(pt) (((u32)(pt)[0] << 24)	\
--		     ^ ((u32)(pt)[1] << 16)	\
--		     ^ ((u32)(pt)[2] <<  8)	\
--		     ^ ((u32)(pt)[3]))
--
--#define COPY4WORD(dst, src)			\
--    do {					\
--	(dst)[0]=(src)[0];			\
--	(dst)[1]=(src)[1];			\
--	(dst)[2]=(src)[2];			\
--	(dst)[3]=(src)[3];			\
--    }while(0)
--
--#define SWAP4WORD(word)				\
--    do {					\
--	CAMELLIA_SWAP4((word)[0]);		\
--	CAMELLIA_SWAP4((word)[1]);		\
--	CAMELLIA_SWAP4((word)[2]);		\
--	CAMELLIA_SWAP4((word)[3]);		\
--    }while(0)
--
--#define XOR4WORD(a, b)/* a = a ^ b */		\
--    do {					\
--	(a)[0]^=(b)[0];				\
--	(a)[1]^=(b)[1];				\
--	(a)[2]^=(b)[2];				\
--	(a)[3]^=(b)[3];				\
--    }while(0)
--
--#define XOR4WORD2(a, b, c)/* a = b ^ c */	\
--    do {					\
--	(a)[0]=(b)[0]^(c)[0];			\
--	(a)[1]=(b)[1]^(c)[1];			\
--	(a)[2]=(b)[2]^(c)[2];			\
--	(a)[3]=(b)[3]^(c)[3];			\
--    }while(0)
--
--#define CAMELLIA_SUBKEY_L(INDEX) (subkey[(INDEX)*2])
--#define CAMELLIA_SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
--
--/* rotation right shift 1byte */
--#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24))
--/* rotation left shift 1bit */
--#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31))
--/* rotation left shift 1byte */
--#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24))
--
--#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits)	\
--    do {						\
--	w0 = ll;					\
--	ll = (ll << bits) + (lr >> (32 - bits));	\
--	lr = (lr << bits) + (rl >> (32 - bits));	\
--	rl = (rl << bits) + (rr >> (32 - bits));	\
--	rr = (rr << bits) + (w0 >> (32 - bits));	\
--    } while(0)
--
--#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits)	\
--    do {						\
--	w0 = ll;					\
--	w1 = lr;					\
--	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
--	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
--	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
--	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
--    } while(0)
--
--#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)])
--#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)])
--#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)])
--#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)])
--
--#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
--    do {							\
--	il = xl ^ kl;						\
--	ir = xr ^ kr;						\
--	t0 = il >> 16;						\
--	t1 = ir >> 16;						\
--	yl = CAMELLIA_SP1110(ir & 0xff)				\
--	    ^ CAMELLIA_SP0222((t1 >> 8) & 0xff)			\
--	    ^ CAMELLIA_SP3033(t1 & 0xff)			\
--	    ^ CAMELLIA_SP4404((ir >> 8) & 0xff);		\
--	yr = CAMELLIA_SP1110((t0 >> 8) & 0xff)			\
--	    ^ CAMELLIA_SP0222(t0 & 0xff)			\
--	    ^ CAMELLIA_SP3033((il >> 8) & 0xff)			\
--	    ^ CAMELLIA_SP4404(il & 0xff);			\
--	yl ^= yr;						\
--	yr = CAMELLIA_RR8(yr);					\
--	yr ^= yl;						\
--    } while(0)
--
--
--/*
-- * for speed up
-- *
-- */
--#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
--    do {								\
--	t0 = kll;							\
--	t2 = krr;							\
--	t0 &= ll;							\
--	t2 |= rr;							\
--	rl ^= t2;							\
--	lr ^= CAMELLIA_RL1(t0);						\
--	t3 = krl;							\
--	t1 = klr;							\
--	t3 &= rl;							\
--	t1 |= lr;							\
--	ll ^= t1;							\
--	rr ^= CAMELLIA_RL1(t3);						\
--    } while(0)
--
--#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
--    do {								\
--	ir =  CAMELLIA_SP1110(xr & 0xff);				\
--	il =  CAMELLIA_SP1110((xl>>24) & 0xff);				\
--	ir ^= CAMELLIA_SP0222((xr>>24) & 0xff);				\
--	il ^= CAMELLIA_SP0222((xl>>16) & 0xff);				\
--	ir ^= CAMELLIA_SP3033((xr>>16) & 0xff);				\
--	il ^= CAMELLIA_SP3033((xl>>8) & 0xff);				\
--	ir ^= CAMELLIA_SP4404((xr>>8) & 0xff);				\
--	il ^= CAMELLIA_SP4404(xl & 0xff);				\
--	il ^= kl;							\
--	ir ^= il ^ kr;							\
--	yl ^= ir;							\
--	yr ^= CAMELLIA_RR8(il) ^ ir;					\
--    } while(0)
--
--/**
-- * Stuff related to the Camellia key schedule
-- */
--#define SUBL(x) subL[(x)]
--#define SUBR(x) subR[(x)]
--
--
- static const u32 camellia_sp1110[256] = {
- 	0x70707000,0x82828200,0x2c2c2c00,0xececec00,
- 	0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500,
-@@ -475,67 +305,348 @@ static const u32 camellia_sp4404[256] = {
- };
- 
- 
-+#define CAMELLIA_MIN_KEY_SIZE        16
-+#define CAMELLIA_MAX_KEY_SIZE        32
-+#define CAMELLIA_BLOCK_SIZE          16
-+#define CAMELLIA_TABLE_BYTE_LEN     272
++static int crypto_rfc4106_setauthsize(struct crypto_aead *parent,
++				      unsigned int authsize)
++{
++	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
 +
-+/*
-+ * NB: L and R below stand for 'left' and 'right' as in written numbers.
-+ * That is, in (xxxL,xxxR) pair xxxL holds most significant digits,
-+ * _not_ least significant ones!
-+ */
++	switch (authsize) {
++	case 8:
++	case 12:
++	case 16:
++		break;
++	default:
++		return -EINVAL;
++	}
 +
++	return crypto_aead_setauthsize(ctx->child, authsize);
++}
 +
-+/* key constants */
++static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
++{
++	struct aead_request *subreq = aead_request_ctx(req);
++	struct crypto_aead *aead = crypto_aead_reqtfm(req);
++	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
++	struct crypto_aead *child = ctx->child;
++	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
++			   crypto_aead_alignmask(child) + 1);
 +
-+#define CAMELLIA_SIGMA1L (0xA09E667FL)
-+#define CAMELLIA_SIGMA1R (0x3BCC908BL)
-+#define CAMELLIA_SIGMA2L (0xB67AE858L)
-+#define CAMELLIA_SIGMA2R (0x4CAA73B2L)
-+#define CAMELLIA_SIGMA3L (0xC6EF372FL)
-+#define CAMELLIA_SIGMA3R (0xE94F82BEL)
-+#define CAMELLIA_SIGMA4L (0x54FF53A5L)
-+#define CAMELLIA_SIGMA4R (0xF1D36F1CL)
-+#define CAMELLIA_SIGMA5L (0x10E527FAL)
-+#define CAMELLIA_SIGMA5R (0xDE682D1DL)
-+#define CAMELLIA_SIGMA6L (0xB05688C2L)
-+#define CAMELLIA_SIGMA6R (0xB3E6C1FDL)
++	memcpy(iv, ctx->nonce, 4);
++	memcpy(iv + 4, req->iv, 8);
 +
-+/*
-+ *  macros
-+ */
-+#define GETU32(v, pt) \
-+    do { \
-+	/* latest breed of gcc is clever enough to use move */ \
-+	memcpy(&(v), (pt), 4); \
-+	(v) = be32_to_cpu(v); \
-+    } while(0)
++	aead_request_set_tfm(subreq, child);
++	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
++				  req->base.data);
++	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
++	aead_request_set_assoc(subreq, req->assoc, req->assoclen);
 +
-+/* rotation right shift 1byte */
-+#define ROR8(x) (((x) >> 8) + ((x) << 24))
-+/* rotation left shift 1bit */
-+#define ROL1(x) (((x) << 1) + ((x) >> 31))
-+/* rotation left shift 1byte */
-+#define ROL8(x) (((x) << 8) + ((x) >> 24))
++	return subreq;
++}
 +
-+#define ROLDQ(ll, lr, rl, rr, w0, w1, bits)		\
-+    do {						\
-+	w0 = ll;					\
-+	ll = (ll << bits) + (lr >> (32 - bits));	\
-+	lr = (lr << bits) + (rl >> (32 - bits));	\
-+	rl = (rl << bits) + (rr >> (32 - bits));	\
-+	rr = (rr << bits) + (w0 >> (32 - bits));	\
-+    } while(0)
++static int crypto_rfc4106_encrypt(struct aead_request *req)
++{
++	req = crypto_rfc4106_crypt(req);
 +
-+#define ROLDQo32(ll, lr, rl, rr, w0, w1, bits)		\
-+    do {						\
-+	w0 = ll;					\
-+	w1 = lr;					\
-+	ll = (lr << (bits - 32)) + (rl >> (64 - bits));	\
-+	lr = (rl << (bits - 32)) + (rr >> (64 - bits));	\
-+	rl = (rr << (bits - 32)) + (w0 >> (64 - bits));	\
-+	rr = (w0 << (bits - 32)) + (w1 >> (64 - bits));	\
-+    } while(0)
++	return crypto_aead_encrypt(req);
++}
 +
-+#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1)	\
-+    do {							\
-+	il = xl ^ kl;						\
-+	ir = xr ^ kr;						\
-+	t0 = il >> 16;						\
-+	t1 = ir >> 16;						\
-+	yl = camellia_sp1110[(u8)(ir     )]			\
-+	   ^ camellia_sp0222[    (t1 >> 8)]			\
-+	   ^ camellia_sp3033[(u8)(t1     )]			\
-+	   ^ camellia_sp4404[(u8)(ir >> 8)];			\
-+	yr = camellia_sp1110[    (t0 >> 8)]			\
-+	   ^ camellia_sp0222[(u8)(t0     )]			\
-+	   ^ camellia_sp3033[(u8)(il >> 8)]			\
-+	   ^ camellia_sp4404[(u8)(il     )];			\
-+	yl ^= yr;						\
-+	yr = ROR8(yr);						\
-+	yr ^= yl;						\
-+    } while(0)
++static int crypto_rfc4106_decrypt(struct aead_request *req)
++{
++	req = crypto_rfc4106_crypt(req);
 +
-+#define SUBKEY_L(INDEX) (subkey[(INDEX)*2])
-+#define SUBKEY_R(INDEX) (subkey[(INDEX)*2 + 1])
++	return crypto_aead_decrypt(req);
++}
 +
-+static void camellia_setup_tail(u32 *subkey, u32 *subL, u32 *subR, int max)
++static int crypto_rfc4106_init_tfm(struct crypto_tfm *tfm)
 +{
-+	u32 dw, tl, tr;
-+	u32 kw4l, kw4r;
-+	int i;
++	struct crypto_instance *inst = (void *)tfm->__crt_alg;
++	struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
++	struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_aead *aead;
++	unsigned long align;
 +
-+	/* absorb kw2 to other subkeys */
-+	/* round 2 */
-+	subL[3] ^= subL[1]; subR[3] ^= subR[1];
-+	/* round 4 */
-+	subL[5] ^= subL[1]; subR[5] ^= subR[1];
-+	/* round 6 */
-+	subL[7] ^= subL[1]; subR[7] ^= subR[1];
-+	subL[1] ^= subR[1] & ~subR[9];
-+	dw = subL[1] & subL[9],
-+		subR[1] ^= ROL1(dw); /* modified for FLinv(kl2) */
-+	/* round 8 */
-+	subL[11] ^= subL[1]; subR[11] ^= subR[1];
-+	/* round 10 */
-+	subL[13] ^= subL[1]; subR[13] ^= subR[1];
-+	/* round 12 */
-+	subL[15] ^= subL[1]; subR[15] ^= subR[1];
-+	subL[1] ^= subR[1] & ~subR[17];
-+	dw = subL[1] & subL[17],
-+		subR[1] ^= ROL1(dw); /* modified for FLinv(kl4) */
-+	/* round 14 */
-+	subL[19] ^= subL[1]; subR[19] ^= subR[1];
-+	/* round 16 */
-+	subL[21] ^= subL[1]; subR[21] ^= subR[1];
-+	/* round 18 */
-+	subL[23] ^= subL[1]; subR[23] ^= subR[1];
-+	if (max == 24) {
-+		/* kw3 */
-+		subL[24] ^= subL[1]; subR[24] ^= subR[1];
++	aead = crypto_spawn_aead(spawn);
++	if (IS_ERR(aead))
++		return PTR_ERR(aead);
 +
-+	/* absorb kw4 to other subkeys */
-+		kw4l = subL[25]; kw4r = subR[25];
-+	} else {
-+		subL[1] ^= subR[1] & ~subR[25];
-+		dw = subL[1] & subL[25],
-+			subR[1] ^= ROL1(dw); /* modified for FLinv(kl6) */
-+		/* round 20 */
-+		subL[27] ^= subL[1]; subR[27] ^= subR[1];
-+		/* round 22 */
-+		subL[29] ^= subL[1]; subR[29] ^= subR[1];
-+		/* round 24 */
-+		subL[31] ^= subL[1]; subR[31] ^= subR[1];
-+		/* kw3 */
-+		subL[32] ^= subL[1]; subR[32] ^= subR[1];
++	ctx->child = aead;
 +
-+	/* absorb kw4 to other subkeys */
-+		kw4l = subL[33]; kw4r = subR[33];
-+		/* round 23 */
-+		subL[30] ^= kw4l; subR[30] ^= kw4r;
-+		/* round 21 */
-+		subL[28] ^= kw4l; subR[28] ^= kw4r;
-+		/* round 19 */
-+		subL[26] ^= kw4l; subR[26] ^= kw4r;
-+		kw4l ^= kw4r & ~subR[24];
-+		dw = kw4l & subL[24],
-+			kw4r ^= ROL1(dw); /* modified for FL(kl5) */
-+	}
-+	/* round 17 */
-+	subL[22] ^= kw4l; subR[22] ^= kw4r;
-+	/* round 15 */
-+	subL[20] ^= kw4l; subR[20] ^= kw4r;
-+	/* round 13 */
-+	subL[18] ^= kw4l; subR[18] ^= kw4r;
-+	kw4l ^= kw4r & ~subR[16];
-+	dw = kw4l & subL[16],
-+		kw4r ^= ROL1(dw); /* modified for FL(kl3) */
-+	/* round 11 */
-+	subL[14] ^= kw4l; subR[14] ^= kw4r;
-+	/* round 9 */
-+	subL[12] ^= kw4l; subR[12] ^= kw4r;
-+	/* round 7 */
-+	subL[10] ^= kw4l; subR[10] ^= kw4r;
-+	kw4l ^= kw4r & ~subR[8];
-+	dw = kw4l & subL[8],
-+		kw4r ^= ROL1(dw); /* modified for FL(kl1) */
-+	/* round 5 */
-+	subL[6] ^= kw4l; subR[6] ^= kw4r;
-+	/* round 3 */
-+	subL[4] ^= kw4l; subR[4] ^= kw4r;
-+	/* round 1 */
-+	subL[2] ^= kw4l; subR[2] ^= kw4r;
-+	/* kw1 */
-+	subL[0] ^= kw4l; subR[0] ^= kw4r;
++	align = crypto_aead_alignmask(aead);
++	align &= ~(crypto_tfm_ctx_alignment() - 1);
++	tfm->crt_aead.reqsize = sizeof(struct aead_request) +
++				ALIGN(crypto_aead_reqsize(aead),
++				      crypto_tfm_ctx_alignment()) +
++				align + 16;
 +
-+	/* key XOR is end of F-function */
-+	SUBKEY_L(0) = subL[0] ^ subL[2];/* kw1 */
-+	SUBKEY_R(0) = subR[0] ^ subR[2];
-+	SUBKEY_L(2) = subL[3];       /* round 1 */
-+	SUBKEY_R(2) = subR[3];
-+	SUBKEY_L(3) = subL[2] ^ subL[4]; /* round 2 */
-+	SUBKEY_R(3) = subR[2] ^ subR[4];
-+	SUBKEY_L(4) = subL[3] ^ subL[5]; /* round 3 */
-+	SUBKEY_R(4) = subR[3] ^ subR[5];
-+	SUBKEY_L(5) = subL[4] ^ subL[6]; /* round 4 */
-+	SUBKEY_R(5) = subR[4] ^ subR[6];
-+	SUBKEY_L(6) = subL[5] ^ subL[7]; /* round 5 */
-+	SUBKEY_R(6) = subR[5] ^ subR[7];
-+	tl = subL[10] ^ (subR[10] & ~subR[8]);
-+	dw = tl & subL[8],  /* FL(kl1) */
-+		tr = subR[10] ^ ROL1(dw);
-+	SUBKEY_L(7) = subL[6] ^ tl; /* round 6 */
-+	SUBKEY_R(7) = subR[6] ^ tr;
-+	SUBKEY_L(8) = subL[8];       /* FL(kl1) */
-+	SUBKEY_R(8) = subR[8];
-+	SUBKEY_L(9) = subL[9];       /* FLinv(kl2) */
-+	SUBKEY_R(9) = subR[9];
-+	tl = subL[7] ^ (subR[7] & ~subR[9]);
-+	dw = tl & subL[9],  /* FLinv(kl2) */
-+		tr = subR[7] ^ ROL1(dw);
-+	SUBKEY_L(10) = tl ^ subL[11]; /* round 7 */
-+	SUBKEY_R(10) = tr ^ subR[11];
-+	SUBKEY_L(11) = subL[10] ^ subL[12]; /* round 8 */
-+	SUBKEY_R(11) = subR[10] ^ subR[12];
-+	SUBKEY_L(12) = subL[11] ^ subL[13]; /* round 9 */
-+	SUBKEY_R(12) = subR[11] ^ subR[13];
-+	SUBKEY_L(13) = subL[12] ^ subL[14]; /* round 10 */
-+	SUBKEY_R(13) = subR[12] ^ subR[14];
-+	SUBKEY_L(14) = subL[13] ^ subL[15]; /* round 11 */
-+	SUBKEY_R(14) = subR[13] ^ subR[15];
-+	tl = subL[18] ^ (subR[18] & ~subR[16]);
-+	dw = tl & subL[16], /* FL(kl3) */
-+		tr = subR[18] ^ ROL1(dw);
-+	SUBKEY_L(15) = subL[14] ^ tl; /* round 12 */
-+	SUBKEY_R(15) = subR[14] ^ tr;
-+	SUBKEY_L(16) = subL[16];     /* FL(kl3) */
-+	SUBKEY_R(16) = subR[16];
-+	SUBKEY_L(17) = subL[17];     /* FLinv(kl4) */
-+	SUBKEY_R(17) = subR[17];
-+	tl = subL[15] ^ (subR[15] & ~subR[17]);
-+	dw = tl & subL[17], /* FLinv(kl4) */
-+		tr = subR[15] ^ ROL1(dw);
-+	SUBKEY_L(18) = tl ^ subL[19]; /* round 13 */
-+	SUBKEY_R(18) = tr ^ subR[19];
-+	SUBKEY_L(19) = subL[18] ^ subL[20]; /* round 14 */
-+	SUBKEY_R(19) = subR[18] ^ subR[20];
-+	SUBKEY_L(20) = subL[19] ^ subL[21]; /* round 15 */
-+	SUBKEY_R(20) = subR[19] ^ subR[21];
-+	SUBKEY_L(21) = subL[20] ^ subL[22]; /* round 16 */
-+	SUBKEY_R(21) = subR[20] ^ subR[22];
-+	SUBKEY_L(22) = subL[21] ^ subL[23]; /* round 17 */
-+	SUBKEY_R(22) = subR[21] ^ subR[23];
-+	if (max == 24) {
-+		SUBKEY_L(23) = subL[22];     /* round 18 */
-+		SUBKEY_R(23) = subR[22];
-+		SUBKEY_L(24) = subL[24] ^ subL[23]; /* kw3 */
-+		SUBKEY_R(24) = subR[24] ^ subR[23];
-+	} else {
-+		tl = subL[26] ^ (subR[26] & ~subR[24]);
-+		dw = tl & subL[24], /* FL(kl5) */
-+			tr = subR[26] ^ ROL1(dw);
-+		SUBKEY_L(23) = subL[22] ^ tl; /* round 18 */
-+		SUBKEY_R(23) = subR[22] ^ tr;
-+		SUBKEY_L(24) = subL[24];     /* FL(kl5) */
-+		SUBKEY_R(24) = subR[24];
-+		SUBKEY_L(25) = subL[25];     /* FLinv(kl6) */
-+		SUBKEY_R(25) = subR[25];
-+		tl = subL[23] ^ (subR[23] & ~subR[25]);
-+		dw = tl & subL[25], /* FLinv(kl6) */
-+			tr = subR[23] ^ ROL1(dw);
-+		SUBKEY_L(26) = tl ^ subL[27]; /* round 19 */
-+		SUBKEY_R(26) = tr ^ subR[27];
-+		SUBKEY_L(27) = subL[26] ^ subL[28]; /* round 20 */
-+		SUBKEY_R(27) = subR[26] ^ subR[28];
-+		SUBKEY_L(28) = subL[27] ^ subL[29]; /* round 21 */
-+		SUBKEY_R(28) = subR[27] ^ subR[29];
-+		SUBKEY_L(29) = subL[28] ^ subL[30]; /* round 22 */
-+		SUBKEY_R(29) = subR[28] ^ subR[30];
-+		SUBKEY_L(30) = subL[29] ^ subL[31]; /* round 23 */
-+		SUBKEY_R(30) = subR[29] ^ subR[31];
-+		SUBKEY_L(31) = subL[30];     /* round 24 */
-+		SUBKEY_R(31) = subR[30];
-+		SUBKEY_L(32) = subL[32] ^ subL[31]; /* kw3 */
-+		SUBKEY_R(32) = subR[32] ^ subR[31];
-+	}
++	return 0;
++}
 +
-+	/* apply the inverse of the last half of P-function */
-+	i = 2;
-+	do {
-+		dw = SUBKEY_L(i + 0) ^ SUBKEY_R(i + 0); dw = ROL8(dw);/* round 1 */
-+		SUBKEY_R(i + 0) = SUBKEY_L(i + 0) ^ dw; SUBKEY_L(i + 0) = dw;
-+		dw = SUBKEY_L(i + 1) ^ SUBKEY_R(i + 1); dw = ROL8(dw);/* round 2 */
-+		SUBKEY_R(i + 1) = SUBKEY_L(i + 1) ^ dw; SUBKEY_L(i + 1) = dw;
-+		dw = SUBKEY_L(i + 2) ^ SUBKEY_R(i + 2); dw = ROL8(dw);/* round 3 */
-+		SUBKEY_R(i + 2) = SUBKEY_L(i + 2) ^ dw; SUBKEY_L(i + 2) = dw;
-+		dw = SUBKEY_L(i + 3) ^ SUBKEY_R(i + 3); dw = ROL8(dw);/* round 4 */
-+		SUBKEY_R(i + 3) = SUBKEY_L(i + 3) ^ dw; SUBKEY_L(i + 3) = dw;
-+		dw = SUBKEY_L(i + 4) ^ SUBKEY_R(i + 4); dw = ROL8(dw);/* round 5 */
-+		SUBKEY_R(i + 4) = SUBKEY_L(i + 4) ^ dw; SUBKEY_L(i + 4) = dw;
-+		dw = SUBKEY_L(i + 5) ^ SUBKEY_R(i + 5); dw = ROL8(dw);/* round 6 */
-+		SUBKEY_R(i + 5) = SUBKEY_L(i + 5) ^ dw; SUBKEY_L(i + 5) = dw;
-+		i += 8;
-+	} while (i < max);
++static void crypto_rfc4106_exit_tfm(struct crypto_tfm *tfm)
++{
++	struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	crypto_free_aead(ctx->child);
 +}
- 
- static void camellia_setup128(const unsigned char *key, u32 *subkey)
- {
- 	u32 kll, klr, krl, krr;
- 	u32 il, ir, t0, t1, w0, w1;
--	u32 kw4l, kw4r, dw, tl, tr;
- 	u32 subL[26];
- 	u32 subR[26];
- 
- 	/**
--	 *  k == kll || klr || krl || krr (|| is concatination)
--	 */
--	kll = GETU32(key     );
--	klr = GETU32(key +  4);
--	krl = GETU32(key +  8);
--	krr = GETU32(key + 12);
--	/**
--	 * generate KL dependent subkeys
-+	 *  k == kll || klr || krl || krr (|| is concatenation)
- 	 */
-+	GETU32(kll, key     );
-+	GETU32(klr, key +  4);
-+	GETU32(krl, key +  8);
-+	GETU32(krr, key + 12);
 +
-+	/* generate KL dependent subkeys */
- 	/* kw1 */
--	SUBL(0) = kll; SUBR(0) = klr;
-+	subL[0] = kll; subR[0] = klr;
- 	/* kw2 */
--	SUBL(1) = krl; SUBR(1) = krr;
-+	subL[1] = krl; subR[1] = krr;
- 	/* rotation left shift 15bit */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* k3 */
--	SUBL(4) = kll; SUBR(4) = klr;
-+	subL[4] = kll; subR[4] = klr;
- 	/* k4 */
--	SUBL(5) = krl; SUBR(5) = krr;
-+	subL[5] = krl; subR[5] = krr;
- 	/* rotation left shift 15+30bit */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 30);
- 	/* k7 */
--	SUBL(10) = kll; SUBR(10) = klr;
-+	subL[10] = kll; subR[10] = klr;
- 	/* k8 */
--	SUBL(11) = krl; SUBR(11) = krr;
-+	subL[11] = krl; subR[11] = krr;
- 	/* rotation left shift 15+30+15bit */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* k10 */
--	SUBL(13) = krl; SUBR(13) = krr;
-+	subL[13] = krl; subR[13] = krr;
- 	/* rotation left shift 15+30+15+17 bit */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
- 	/* kl3 */
--	SUBL(16) = kll; SUBR(16) = klr;
-+	subL[16] = kll; subR[16] = klr;
- 	/* kl4 */
--	SUBL(17) = krl; SUBR(17) = krr;
-+	subL[17] = krl; subR[17] = krr;
- 	/* rotation left shift 15+30+15+17+17 bit */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
- 	/* k13 */
--	SUBL(18) = kll; SUBR(18) = klr;
-+	subL[18] = kll; subR[18] = klr;
- 	/* k14 */
--	SUBL(19) = krl; SUBR(19) = krr;
-+	subL[19] = krl; subR[19] = krr;
- 	/* rotation left shift 15+30+15+17+17+17 bit */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
- 	/* k17 */
--	SUBL(22) = kll; SUBR(22) = klr;
-+	subL[22] = kll; subR[22] = klr;
- 	/* k18 */
--	SUBL(23) = krl; SUBR(23) = krr;
-+	subL[23] = krl; subR[23] = krr;
- 
- 	/* generate KA */
--	kll = SUBL(0); klr = SUBR(0);
--	krl = SUBL(1); krr = SUBR(1);
-+	kll = subL[0]; klr = subR[0];
-+	krl = subL[1]; krr = subR[1];
- 	CAMELLIA_F(kll, klr,
- 		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
- 		   w0, w1, il, ir, t0, t1);
-@@ -555,306 +666,108 @@ static void camellia_setup128(const unsigned char *key, u32 *subkey)
- 
- 	/* generate KA dependent subkeys */
- 	/* k1, k2 */
--	SUBL(2) = kll; SUBR(2) = klr;
--	SUBL(3) = krl; SUBR(3) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	subL[2] = kll; subR[2] = klr;
-+	subL[3] = krl; subR[3] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* k5,k6 */
--	SUBL(6) = kll; SUBR(6) = klr;
--	SUBL(7) = krl; SUBR(7) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	subL[6] = kll; subR[6] = klr;
-+	subL[7] = krl; subR[7] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* kl1, kl2 */
--	SUBL(8) = kll; SUBR(8) = klr;
--	SUBL(9) = krl; SUBR(9) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	subL[8] = kll; subR[8] = klr;
-+	subL[9] = krl; subR[9] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* k9 */
--	SUBL(12) = kll; SUBR(12) = klr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	subL[12] = kll; subR[12] = klr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* k11, k12 */
--	SUBL(14) = kll; SUBR(14) = klr;
--	SUBL(15) = krl; SUBR(15) = krr;
--	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
-+	subL[14] = kll; subR[14] = klr;
-+	subL[15] = krl; subR[15] = krr;
-+	ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
- 	/* k15, k16 */
--	SUBL(20) = kll; SUBR(20) = klr;
--	SUBL(21) = krl; SUBR(21) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-+	subL[20] = kll; subR[20] = klr;
-+	subL[21] = krl; subR[21] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
- 	/* kw3, kw4 */
--	SUBL(24) = kll; SUBR(24) = klr;
--	SUBL(25) = krl; SUBR(25) = krr;
-+	subL[24] = kll; subR[24] = klr;
-+	subL[25] = krl; subR[25] = krr;
- 
--
--	/* absorb kw2 to other subkeys */
--	/* round 2 */
--	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
--	/* round 4 */
--	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
--	/* round 6 */
--	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
--	SUBL(1) ^= SUBR(1) & ~SUBR(9);
--	dw = SUBL(1) & SUBL(9),
--		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
--	/* round 8 */
--	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
--	/* round 10 */
--	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
--	/* round 12 */
--	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
--	SUBL(1) ^= SUBR(1) & ~SUBR(17);
--	dw = SUBL(1) & SUBL(17),
--		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
--	/* round 14 */
--	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
--	/* round 16 */
--	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
--	/* round 18 */
--	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
--	/* kw3 */
--	SUBL(24) ^= SUBL(1); SUBR(24) ^= SUBR(1);
--
--	/* absorb kw4 to other subkeys */
--	kw4l = SUBL(25); kw4r = SUBR(25);
--	/* round 17 */
--	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
--	/* round 15 */
--	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
--	/* round 13 */
--	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
--	kw4l ^= kw4r & ~SUBR(16);
--	dw = kw4l & SUBL(16),
--		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
--	/* round 11 */
--	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
--	/* round 9 */
--	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
--	/* round 7 */
--	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
--	kw4l ^= kw4r & ~SUBR(8);
--	dw = kw4l & SUBL(8),
--		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
--	/* round 5 */
--	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
--	/* round 3 */
--	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
--	/* round 1 */
--	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
--	/* kw1 */
--	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
--
--
--	/* key XOR is end of F-function */
--	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
--	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
--	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
--	CAMELLIA_SUBKEY_R(2) = SUBR(3);
--	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
--	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
--	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
--	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
--	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
--	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
--	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
--	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
--	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
--	dw = tl & SUBL(8),  /* FL(kl1) */
--		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
--	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
--	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
--	CAMELLIA_SUBKEY_R(8) = SUBR(8);
--	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
--	CAMELLIA_SUBKEY_R(9) = SUBR(9);
--	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
--	dw = tl & SUBL(9),  /* FLinv(kl2) */
--		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
--	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
--	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
--	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
--	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
--	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
--	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
--	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
--	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
--	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
--	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
--	dw = tl & SUBL(16), /* FL(kl3) */
--		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
--	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
--	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
--	CAMELLIA_SUBKEY_R(16) = SUBR(16);
--	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
--	CAMELLIA_SUBKEY_R(17) = SUBR(17);
--	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
--	dw = tl & SUBL(17), /* FLinv(kl4) */
--		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
--	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
--	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
--	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
--	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
--	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
--	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
--	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
--	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
--	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
--	CAMELLIA_SUBKEY_L(23) = SUBL(22);     /* round 18 */
--	CAMELLIA_SUBKEY_R(23) = SUBR(22);
--	CAMELLIA_SUBKEY_L(24) = SUBL(24) ^ SUBL(23); /* kw3 */
--	CAMELLIA_SUBKEY_R(24) = SUBR(24) ^ SUBR(23);
--
--	/* apply the inverse of the last half of P-function */
--	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
--		dw = CAMELLIA_RL8(dw);/* round 1 */
--	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
--		CAMELLIA_SUBKEY_L(2) = dw;
--	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
--		dw = CAMELLIA_RL8(dw);/* round 2 */
--	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
--		CAMELLIA_SUBKEY_L(3) = dw;
--	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
--		dw = CAMELLIA_RL8(dw);/* round 3 */
--	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
--		CAMELLIA_SUBKEY_L(4) = dw;
--	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
--		dw = CAMELLIA_RL8(dw);/* round 4 */
--	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
--		CAMELLIA_SUBKEY_L(5) = dw;
--	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
--		dw = CAMELLIA_RL8(dw);/* round 5 */
--	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
--		CAMELLIA_SUBKEY_L(6) = dw;
--	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
--		dw = CAMELLIA_RL8(dw);/* round 6 */
--	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
--		CAMELLIA_SUBKEY_L(7) = dw;
--	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
--		dw = CAMELLIA_RL8(dw);/* round 7 */
--	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
--		CAMELLIA_SUBKEY_L(10) = dw;
--	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
--		dw = CAMELLIA_RL8(dw);/* round 8 */
--	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
--		CAMELLIA_SUBKEY_L(11) = dw;
--	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
--		dw = CAMELLIA_RL8(dw);/* round 9 */
--	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
--		CAMELLIA_SUBKEY_L(12) = dw;
--	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
--		dw = CAMELLIA_RL8(dw);/* round 10 */
--	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
--		CAMELLIA_SUBKEY_L(13) = dw;
--	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
--		dw = CAMELLIA_RL8(dw);/* round 11 */
--	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
--		CAMELLIA_SUBKEY_L(14) = dw;
--	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
--		dw = CAMELLIA_RL8(dw);/* round 12 */
--	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
--		CAMELLIA_SUBKEY_L(15) = dw;
--	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
--		dw = CAMELLIA_RL8(dw);/* round 13 */
--	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
--		CAMELLIA_SUBKEY_L(18) = dw;
--	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
--		dw = CAMELLIA_RL8(dw);/* round 14 */
--	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
--		CAMELLIA_SUBKEY_L(19) = dw;
--	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
--		dw = CAMELLIA_RL8(dw);/* round 15 */
--	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
--		CAMELLIA_SUBKEY_L(20) = dw;
--	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
--		dw = CAMELLIA_RL8(dw);/* round 16 */
--	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
--		CAMELLIA_SUBKEY_L(21) = dw;
--	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
--		dw = CAMELLIA_RL8(dw);/* round 17 */
--	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
--		CAMELLIA_SUBKEY_L(22) = dw;
--	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
--		dw = CAMELLIA_RL8(dw);/* round 18 */
--	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
--		CAMELLIA_SUBKEY_L(23) = dw;
--
--	return;
-+	camellia_setup_tail(subkey, subL, subR, 24);
- }
- 
--
- static void camellia_setup256(const unsigned char *key, u32 *subkey)
- {
--	u32 kll,klr,krl,krr;           /* left half of key */
--	u32 krll,krlr,krrl,krrr;       /* right half of key */
-+	u32 kll, klr, krl, krr;        /* left half of key */
-+	u32 krll, krlr, krrl, krrr;    /* right half of key */
- 	u32 il, ir, t0, t1, w0, w1;    /* temporary variables */
--	u32 kw4l, kw4r, dw, tl, tr;
- 	u32 subL[34];
- 	u32 subR[34];
- 
- 	/**
- 	 *  key = (kll || klr || krl || krr || krll || krlr || krrl || krrr)
--	 *  (|| is concatination)
-+	 *  (|| is concatenation)
- 	 */
--
--	kll  = GETU32(key     );
--	klr  = GETU32(key +  4);
--	krl  = GETU32(key +  8);
--	krr  = GETU32(key + 12);
--	krll = GETU32(key + 16);
--	krlr = GETU32(key + 20);
--	krrl = GETU32(key + 24);
--	krrr = GETU32(key + 28);
-+	GETU32(kll,  key     );
-+	GETU32(klr,  key +  4);
-+	GETU32(krl,  key +  8);
-+	GETU32(krr,  key + 12);
-+	GETU32(krll, key + 16);
-+	GETU32(krlr, key + 20);
-+	GETU32(krrl, key + 24);
-+	GETU32(krrr, key + 28);
- 
- 	/* generate KL dependent subkeys */
- 	/* kw1 */
--	SUBL(0) = kll; SUBR(0) = klr;
-+	subL[0] = kll; subR[0] = klr;
- 	/* kw2 */
--	SUBL(1) = krl; SUBR(1) = krr;
--	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
-+	subL[1] = krl; subR[1] = krr;
-+	ROLDQo32(kll, klr, krl, krr, w0, w1, 45);
- 	/* k9 */
--	SUBL(12) = kll; SUBR(12) = klr;
-+	subL[12] = kll; subR[12] = klr;
- 	/* k10 */
--	SUBL(13) = krl; SUBR(13) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	subL[13] = krl; subR[13] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* kl3 */
--	SUBL(16) = kll; SUBR(16) = klr;
-+	subL[16] = kll; subR[16] = klr;
- 	/* kl4 */
--	SUBL(17) = krl; SUBR(17) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17);
-+	subL[17] = krl; subR[17] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 17);
- 	/* k17 */
--	SUBL(22) = kll; SUBR(22) = klr;
-+	subL[22] = kll; subR[22] = klr;
- 	/* k18 */
--	SUBL(23) = krl; SUBR(23) = krr;
--	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
-+	subL[23] = krl; subR[23] = krr;
-+	ROLDQo32(kll, klr, krl, krr, w0, w1, 34);
- 	/* k23 */
--	SUBL(30) = kll; SUBR(30) = klr;
-+	subL[30] = kll; subR[30] = klr;
- 	/* k24 */
--	SUBL(31) = krl; SUBR(31) = krr;
-+	subL[31] = krl; subR[31] = krr;
- 
- 	/* generate KR dependent subkeys */
--	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
-+	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
- 	/* k3 */
--	SUBL(4) = krll; SUBR(4) = krlr;
-+	subL[4] = krll; subR[4] = krlr;
- 	/* k4 */
--	SUBL(5) = krrl; SUBR(5) = krrr;
--	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
-+	subL[5] = krrl; subR[5] = krrr;
-+	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15);
- 	/* kl1 */
--	SUBL(8) = krll; SUBR(8) = krlr;
-+	subL[8] = krll; subR[8] = krlr;
- 	/* kl2 */
--	SUBL(9) = krrl; SUBR(9) = krrr;
--	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
-+	subL[9] = krrl; subR[9] = krrr;
-+	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
- 	/* k13 */
--	SUBL(18) = krll; SUBR(18) = krlr;
-+	subL[18] = krll; subR[18] = krlr;
- 	/* k14 */
--	SUBL(19) = krrl; SUBR(19) = krrr;
--	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
-+	subL[19] = krrl; subR[19] = krrr;
-+	ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
- 	/* k19 */
--	SUBL(26) = krll; SUBR(26) = krlr;
-+	subL[26] = krll; subR[26] = krlr;
- 	/* k20 */
--	SUBL(27) = krrl; SUBR(27) = krrr;
--	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
-+	subL[27] = krrl; subR[27] = krrr;
-+	ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34);
- 
- 	/* generate KA */
--	kll = SUBL(0) ^ krll; klr = SUBR(0) ^ krlr;
--	krl = SUBL(1) ^ krrl; krr = SUBR(1) ^ krrr;
-+	kll = subL[0] ^ krll; klr = subR[0] ^ krlr;
-+	krl = subL[1] ^ krrl; krr = subR[1] ^ krrr;
- 	CAMELLIA_F(kll, klr,
- 		   CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R,
- 		   w0, w1, il, ir, t0, t1);
-@@ -885,310 +798,50 @@ static void camellia_setup256(const unsigned char *key, u32 *subkey)
- 	krll ^= w0; krlr ^= w1;
- 
- 	/* generate KA dependent subkeys */
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15);
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 15);
- 	/* k5 */
--	SUBL(6) = kll; SUBR(6) = klr;
-+	subL[6] = kll; subR[6] = klr;
- 	/* k6 */
--	SUBL(7) = krl; SUBR(7) = krr;
--	CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30);
-+	subL[7] = krl; subR[7] = krr;
-+	ROLDQ(kll, klr, krl, krr, w0, w1, 30);
- 	/* k11 */
--	SUBL(14) = kll; SUBR(14) = klr;
-+	subL[14] = kll; subR[14] = klr;
- 	/* k12 */
--	SUBL(15) = krl; SUBR(15) = krr;
-+	subL[15] = krl; subR[15] = krr;
- 	/* rotation left shift 32bit */
- 	/* kl5 */
--	SUBL(24) = klr; SUBR(24) = krl;
-+	subL[24] = klr; subR[24] = krl;
- 	/* kl6 */
--	SUBL(25) = krr; SUBR(25) = kll;
-+	subL[25] = krr; subR[25] = kll;
- 	/* rotation left shift 49 from k11,k12 -> k21,k22 */
--	CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
-+	ROLDQo32(kll, klr, krl, krr, w0, w1, 49);
- 	/* k21 */
--	SUBL(28) = kll; SUBR(28) = klr;
-+	subL[28] = kll; subR[28] = klr;
- 	/* k22 */
--	SUBL(29) = krl; SUBR(29) = krr;
-+	subL[29] = krl; subR[29] = krr;
- 
- 	/* generate KB dependent subkeys */
- 	/* k1 */
--	SUBL(2) = krll; SUBR(2) = krlr;
-+	subL[2] = krll; subR[2] = krlr;
- 	/* k2 */
--	SUBL(3) = krrl; SUBR(3) = krrr;
--	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
-+	subL[3] = krrl; subR[3] = krrr;
-+	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
- 	/* k7 */
--	SUBL(10) = krll; SUBR(10) = krlr;
-+	subL[10] = krll; subR[10] = krlr;
- 	/* k8 */
--	SUBL(11) = krrl; SUBR(11) = krrr;
--	CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
-+	subL[11] = krrl; subR[11] = krrr;
-+	ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30);
- 	/* k15 */
--	SUBL(20) = krll; SUBR(20) = krlr;
-+	subL[20] = krll; subR[20] = krlr;
- 	/* k16 */
--	SUBL(21) = krrl; SUBR(21) = krrr;
--	CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
-+	subL[21] = krrl; subR[21] = krrr;
-+	ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51);
- 	/* kw3 */
--	SUBL(32) = krll; SUBR(32) = krlr;
-+	subL[32] = krll; subR[32] = krlr;
- 	/* kw4 */
--	SUBL(33) = krrl; SUBR(33) = krrr;
--
--	/* absorb kw2 to other subkeys */
--	/* round 2 */
--	SUBL(3) ^= SUBL(1); SUBR(3) ^= SUBR(1);
--	/* round 4 */
--	SUBL(5) ^= SUBL(1); SUBR(5) ^= SUBR(1);
--	/* round 6 */
--	SUBL(7) ^= SUBL(1); SUBR(7) ^= SUBR(1);
--	SUBL(1) ^= SUBR(1) & ~SUBR(9);
--	dw = SUBL(1) & SUBL(9),
--		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl2) */
--	/* round 8 */
--	SUBL(11) ^= SUBL(1); SUBR(11) ^= SUBR(1);
--	/* round 10 */
--	SUBL(13) ^= SUBL(1); SUBR(13) ^= SUBR(1);
--	/* round 12 */
--	SUBL(15) ^= SUBL(1); SUBR(15) ^= SUBR(1);
--	SUBL(1) ^= SUBR(1) & ~SUBR(17);
--	dw = SUBL(1) & SUBL(17),
--		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl4) */
--	/* round 14 */
--	SUBL(19) ^= SUBL(1); SUBR(19) ^= SUBR(1);
--	/* round 16 */
--	SUBL(21) ^= SUBL(1); SUBR(21) ^= SUBR(1);
--	/* round 18 */
--	SUBL(23) ^= SUBL(1); SUBR(23) ^= SUBR(1);
--	SUBL(1) ^= SUBR(1) & ~SUBR(25);
--	dw = SUBL(1) & SUBL(25),
--		SUBR(1) ^= CAMELLIA_RL1(dw); /* modified for FLinv(kl6) */
--	/* round 20 */
--	SUBL(27) ^= SUBL(1); SUBR(27) ^= SUBR(1);
--	/* round 22 */
--	SUBL(29) ^= SUBL(1); SUBR(29) ^= SUBR(1);
--	/* round 24 */
--	SUBL(31) ^= SUBL(1); SUBR(31) ^= SUBR(1);
--	/* kw3 */
--	SUBL(32) ^= SUBL(1); SUBR(32) ^= SUBR(1);
--
--
--	/* absorb kw4 to other subkeys */
--	kw4l = SUBL(33); kw4r = SUBR(33);
--	/* round 23 */
--	SUBL(30) ^= kw4l; SUBR(30) ^= kw4r;
--	/* round 21 */
--	SUBL(28) ^= kw4l; SUBR(28) ^= kw4r;
--	/* round 19 */
--	SUBL(26) ^= kw4l; SUBR(26) ^= kw4r;
--	kw4l ^= kw4r & ~SUBR(24);
--	dw = kw4l & SUBL(24),
--		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl5) */
--	/* round 17 */
--	SUBL(22) ^= kw4l; SUBR(22) ^= kw4r;
--	/* round 15 */
--	SUBL(20) ^= kw4l; SUBR(20) ^= kw4r;
--	/* round 13 */
--	SUBL(18) ^= kw4l; SUBR(18) ^= kw4r;
--	kw4l ^= kw4r & ~SUBR(16);
--	dw = kw4l & SUBL(16),
--		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl3) */
--	/* round 11 */
--	SUBL(14) ^= kw4l; SUBR(14) ^= kw4r;
--	/* round 9 */
--	SUBL(12) ^= kw4l; SUBR(12) ^= kw4r;
--	/* round 7 */
--	SUBL(10) ^= kw4l; SUBR(10) ^= kw4r;
--	kw4l ^= kw4r & ~SUBR(8);
--	dw = kw4l & SUBL(8),
--		kw4r ^= CAMELLIA_RL1(dw); /* modified for FL(kl1) */
--	/* round 5 */
--	SUBL(6) ^= kw4l; SUBR(6) ^= kw4r;
--	/* round 3 */
--	SUBL(4) ^= kw4l; SUBR(4) ^= kw4r;
--	/* round 1 */
--	SUBL(2) ^= kw4l; SUBR(2) ^= kw4r;
--	/* kw1 */
--	SUBL(0) ^= kw4l; SUBR(0) ^= kw4r;
-+	subL[33] = krrl; subR[33] = krrr;
- 
--	/* key XOR is end of F-function */
--	CAMELLIA_SUBKEY_L(0) = SUBL(0) ^ SUBL(2);/* kw1 */
--	CAMELLIA_SUBKEY_R(0) = SUBR(0) ^ SUBR(2);
--	CAMELLIA_SUBKEY_L(2) = SUBL(3);       /* round 1 */
--	CAMELLIA_SUBKEY_R(2) = SUBR(3);
--	CAMELLIA_SUBKEY_L(3) = SUBL(2) ^ SUBL(4); /* round 2 */
--	CAMELLIA_SUBKEY_R(3) = SUBR(2) ^ SUBR(4);
--	CAMELLIA_SUBKEY_L(4) = SUBL(3) ^ SUBL(5); /* round 3 */
--	CAMELLIA_SUBKEY_R(4) = SUBR(3) ^ SUBR(5);
--	CAMELLIA_SUBKEY_L(5) = SUBL(4) ^ SUBL(6); /* round 4 */
--	CAMELLIA_SUBKEY_R(5) = SUBR(4) ^ SUBR(6);
--	CAMELLIA_SUBKEY_L(6) = SUBL(5) ^ SUBL(7); /* round 5 */
--	CAMELLIA_SUBKEY_R(6) = SUBR(5) ^ SUBR(7);
--	tl = SUBL(10) ^ (SUBR(10) & ~SUBR(8));
--	dw = tl & SUBL(8),  /* FL(kl1) */
--		tr = SUBR(10) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(7) = SUBL(6) ^ tl; /* round 6 */
--	CAMELLIA_SUBKEY_R(7) = SUBR(6) ^ tr;
--	CAMELLIA_SUBKEY_L(8) = SUBL(8);       /* FL(kl1) */
--	CAMELLIA_SUBKEY_R(8) = SUBR(8);
--	CAMELLIA_SUBKEY_L(9) = SUBL(9);       /* FLinv(kl2) */
--	CAMELLIA_SUBKEY_R(9) = SUBR(9);
--	tl = SUBL(7) ^ (SUBR(7) & ~SUBR(9));
--	dw = tl & SUBL(9),  /* FLinv(kl2) */
--		tr = SUBR(7) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(10) = tl ^ SUBL(11); /* round 7 */
--	CAMELLIA_SUBKEY_R(10) = tr ^ SUBR(11);
--	CAMELLIA_SUBKEY_L(11) = SUBL(10) ^ SUBL(12); /* round 8 */
--	CAMELLIA_SUBKEY_R(11) = SUBR(10) ^ SUBR(12);
--	CAMELLIA_SUBKEY_L(12) = SUBL(11) ^ SUBL(13); /* round 9 */
--	CAMELLIA_SUBKEY_R(12) = SUBR(11) ^ SUBR(13);
--	CAMELLIA_SUBKEY_L(13) = SUBL(12) ^ SUBL(14); /* round 10 */
--	CAMELLIA_SUBKEY_R(13) = SUBR(12) ^ SUBR(14);
--	CAMELLIA_SUBKEY_L(14) = SUBL(13) ^ SUBL(15); /* round 11 */
--	CAMELLIA_SUBKEY_R(14) = SUBR(13) ^ SUBR(15);
--	tl = SUBL(18) ^ (SUBR(18) & ~SUBR(16));
--	dw = tl & SUBL(16), /* FL(kl3) */
--		tr = SUBR(18) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(15) = SUBL(14) ^ tl; /* round 12 */
--	CAMELLIA_SUBKEY_R(15) = SUBR(14) ^ tr;
--	CAMELLIA_SUBKEY_L(16) = SUBL(16);     /* FL(kl3) */
--	CAMELLIA_SUBKEY_R(16) = SUBR(16);
--	CAMELLIA_SUBKEY_L(17) = SUBL(17);     /* FLinv(kl4) */
--	CAMELLIA_SUBKEY_R(17) = SUBR(17);
--	tl = SUBL(15) ^ (SUBR(15) & ~SUBR(17));
--	dw = tl & SUBL(17), /* FLinv(kl4) */
--		tr = SUBR(15) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(18) = tl ^ SUBL(19); /* round 13 */
--	CAMELLIA_SUBKEY_R(18) = tr ^ SUBR(19);
--	CAMELLIA_SUBKEY_L(19) = SUBL(18) ^ SUBL(20); /* round 14 */
--	CAMELLIA_SUBKEY_R(19) = SUBR(18) ^ SUBR(20);
--	CAMELLIA_SUBKEY_L(20) = SUBL(19) ^ SUBL(21); /* round 15 */
--	CAMELLIA_SUBKEY_R(20) = SUBR(19) ^ SUBR(21);
--	CAMELLIA_SUBKEY_L(21) = SUBL(20) ^ SUBL(22); /* round 16 */
--	CAMELLIA_SUBKEY_R(21) = SUBR(20) ^ SUBR(22);
--	CAMELLIA_SUBKEY_L(22) = SUBL(21) ^ SUBL(23); /* round 17 */
--	CAMELLIA_SUBKEY_R(22) = SUBR(21) ^ SUBR(23);
--	tl = SUBL(26) ^ (SUBR(26)
--			 & ~SUBR(24));
--	dw = tl & SUBL(24), /* FL(kl5) */
--		tr = SUBR(26) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(23) = SUBL(22) ^ tl; /* round 18 */
--	CAMELLIA_SUBKEY_R(23) = SUBR(22) ^ tr;
--	CAMELLIA_SUBKEY_L(24) = SUBL(24);     /* FL(kl5) */
--	CAMELLIA_SUBKEY_R(24) = SUBR(24);
--	CAMELLIA_SUBKEY_L(25) = SUBL(25);     /* FLinv(kl6) */
--	CAMELLIA_SUBKEY_R(25) = SUBR(25);
--	tl = SUBL(23) ^ (SUBR(23) &
--			 ~SUBR(25));
--	dw = tl & SUBL(25), /* FLinv(kl6) */
--		tr = SUBR(23) ^ CAMELLIA_RL1(dw);
--	CAMELLIA_SUBKEY_L(26) = tl ^ SUBL(27); /* round 19 */
--	CAMELLIA_SUBKEY_R(26) = tr ^ SUBR(27);
--	CAMELLIA_SUBKEY_L(27) = SUBL(26) ^ SUBL(28); /* round 20 */
--	CAMELLIA_SUBKEY_R(27) = SUBR(26) ^ SUBR(28);
--	CAMELLIA_SUBKEY_L(28) = SUBL(27) ^ SUBL(29); /* round 21 */
--	CAMELLIA_SUBKEY_R(28) = SUBR(27) ^ SUBR(29);
--	CAMELLIA_SUBKEY_L(29) = SUBL(28) ^ SUBL(30); /* round 22 */
--	CAMELLIA_SUBKEY_R(29) = SUBR(28) ^ SUBR(30);
--	CAMELLIA_SUBKEY_L(30) = SUBL(29) ^ SUBL(31); /* round 23 */
--	CAMELLIA_SUBKEY_R(30) = SUBR(29) ^ SUBR(31);
--	CAMELLIA_SUBKEY_L(31) = SUBL(30);     /* round 24 */
--	CAMELLIA_SUBKEY_R(31) = SUBR(30);
--	CAMELLIA_SUBKEY_L(32) = SUBL(32) ^ SUBL(31); /* kw3 */
--	CAMELLIA_SUBKEY_R(32) = SUBR(32) ^ SUBR(31);
--
--	/* apply the inverse of the last half of P-function */
--	dw = CAMELLIA_SUBKEY_L(2) ^ CAMELLIA_SUBKEY_R(2),
--		dw = CAMELLIA_RL8(dw);/* round 1 */
--	CAMELLIA_SUBKEY_R(2) = CAMELLIA_SUBKEY_L(2) ^ dw,
--		CAMELLIA_SUBKEY_L(2) = dw;
--	dw = CAMELLIA_SUBKEY_L(3) ^ CAMELLIA_SUBKEY_R(3),
--		dw = CAMELLIA_RL8(dw);/* round 2 */
--	CAMELLIA_SUBKEY_R(3) = CAMELLIA_SUBKEY_L(3) ^ dw,
--		CAMELLIA_SUBKEY_L(3) = dw;
--	dw = CAMELLIA_SUBKEY_L(4) ^ CAMELLIA_SUBKEY_R(4),
--		dw = CAMELLIA_RL8(dw);/* round 3 */
--	CAMELLIA_SUBKEY_R(4) = CAMELLIA_SUBKEY_L(4) ^ dw,
--		CAMELLIA_SUBKEY_L(4) = dw;
--	dw = CAMELLIA_SUBKEY_L(5) ^ CAMELLIA_SUBKEY_R(5),
--		dw = CAMELLIA_RL8(dw);/* round 4 */
--	CAMELLIA_SUBKEY_R(5) = CAMELLIA_SUBKEY_L(5) ^ dw,
--	CAMELLIA_SUBKEY_L(5) = dw;
--	dw = CAMELLIA_SUBKEY_L(6) ^ CAMELLIA_SUBKEY_R(6),
--		dw = CAMELLIA_RL8(dw);/* round 5 */
--	CAMELLIA_SUBKEY_R(6) = CAMELLIA_SUBKEY_L(6) ^ dw,
--		CAMELLIA_SUBKEY_L(6) = dw;
--	dw = CAMELLIA_SUBKEY_L(7) ^ CAMELLIA_SUBKEY_R(7),
--		dw = CAMELLIA_RL8(dw);/* round 6 */
--	CAMELLIA_SUBKEY_R(7) = CAMELLIA_SUBKEY_L(7) ^ dw,
--		CAMELLIA_SUBKEY_L(7) = dw;
--	dw = CAMELLIA_SUBKEY_L(10) ^ CAMELLIA_SUBKEY_R(10),
--		dw = CAMELLIA_RL8(dw);/* round 7 */
--	CAMELLIA_SUBKEY_R(10) = CAMELLIA_SUBKEY_L(10) ^ dw,
--		CAMELLIA_SUBKEY_L(10) = dw;
--	dw = CAMELLIA_SUBKEY_L(11) ^ CAMELLIA_SUBKEY_R(11),
--	    dw = CAMELLIA_RL8(dw);/* round 8 */
--	CAMELLIA_SUBKEY_R(11) = CAMELLIA_SUBKEY_L(11) ^ dw,
--		CAMELLIA_SUBKEY_L(11) = dw;
--	dw = CAMELLIA_SUBKEY_L(12) ^ CAMELLIA_SUBKEY_R(12),
--		dw = CAMELLIA_RL8(dw);/* round 9 */
--	CAMELLIA_SUBKEY_R(12) = CAMELLIA_SUBKEY_L(12) ^ dw,
--		CAMELLIA_SUBKEY_L(12) = dw;
--	dw = CAMELLIA_SUBKEY_L(13) ^ CAMELLIA_SUBKEY_R(13),
--		dw = CAMELLIA_RL8(dw);/* round 10 */
--	CAMELLIA_SUBKEY_R(13) = CAMELLIA_SUBKEY_L(13) ^ dw,
--		CAMELLIA_SUBKEY_L(13) = dw;
--	dw = CAMELLIA_SUBKEY_L(14) ^ CAMELLIA_SUBKEY_R(14),
--		dw = CAMELLIA_RL8(dw);/* round 11 */
--	CAMELLIA_SUBKEY_R(14) = CAMELLIA_SUBKEY_L(14) ^ dw,
--		CAMELLIA_SUBKEY_L(14) = dw;
--	dw = CAMELLIA_SUBKEY_L(15) ^ CAMELLIA_SUBKEY_R(15),
--		dw = CAMELLIA_RL8(dw);/* round 12 */
--	CAMELLIA_SUBKEY_R(15) = CAMELLIA_SUBKEY_L(15) ^ dw,
--		CAMELLIA_SUBKEY_L(15) = dw;
--	dw = CAMELLIA_SUBKEY_L(18) ^ CAMELLIA_SUBKEY_R(18),
--		dw = CAMELLIA_RL8(dw);/* round 13 */
--	CAMELLIA_SUBKEY_R(18) = CAMELLIA_SUBKEY_L(18) ^ dw,
--		CAMELLIA_SUBKEY_L(18) = dw;
--	dw = CAMELLIA_SUBKEY_L(19) ^ CAMELLIA_SUBKEY_R(19),
--		dw = CAMELLIA_RL8(dw);/* round 14 */
--	CAMELLIA_SUBKEY_R(19) = CAMELLIA_SUBKEY_L(19) ^ dw,
--		CAMELLIA_SUBKEY_L(19) = dw;
--	dw = CAMELLIA_SUBKEY_L(20) ^ CAMELLIA_SUBKEY_R(20),
--		dw = CAMELLIA_RL8(dw);/* round 15 */
--	CAMELLIA_SUBKEY_R(20) = CAMELLIA_SUBKEY_L(20) ^ dw,
--		CAMELLIA_SUBKEY_L(20) = dw;
--	dw = CAMELLIA_SUBKEY_L(21) ^ CAMELLIA_SUBKEY_R(21),
--		dw = CAMELLIA_RL8(dw);/* round 16 */
--	CAMELLIA_SUBKEY_R(21) = CAMELLIA_SUBKEY_L(21) ^ dw,
--		CAMELLIA_SUBKEY_L(21) = dw;
--	dw = CAMELLIA_SUBKEY_L(22) ^ CAMELLIA_SUBKEY_R(22),
--		dw = CAMELLIA_RL8(dw);/* round 17 */
--	CAMELLIA_SUBKEY_R(22) = CAMELLIA_SUBKEY_L(22) ^ dw,
--		CAMELLIA_SUBKEY_L(22) = dw;
--	dw = CAMELLIA_SUBKEY_L(23) ^ CAMELLIA_SUBKEY_R(23),
--		dw = CAMELLIA_RL8(dw);/* round 18 */
--	CAMELLIA_SUBKEY_R(23) = CAMELLIA_SUBKEY_L(23) ^ dw,
--		CAMELLIA_SUBKEY_L(23) = dw;
--	dw = CAMELLIA_SUBKEY_L(26) ^ CAMELLIA_SUBKEY_R(26),
--		dw = CAMELLIA_RL8(dw);/* round 19 */
--	CAMELLIA_SUBKEY_R(26) = CAMELLIA_SUBKEY_L(26) ^ dw,
--		CAMELLIA_SUBKEY_L(26) = dw;
--	dw = CAMELLIA_SUBKEY_L(27) ^ CAMELLIA_SUBKEY_R(27),
--		dw = CAMELLIA_RL8(dw);/* round 20 */
--	CAMELLIA_SUBKEY_R(27) = CAMELLIA_SUBKEY_L(27) ^ dw,
--		CAMELLIA_SUBKEY_L(27) = dw;
--	dw = CAMELLIA_SUBKEY_L(28) ^ CAMELLIA_SUBKEY_R(28),
--		dw = CAMELLIA_RL8(dw);/* round 21 */
--	CAMELLIA_SUBKEY_R(28) = CAMELLIA_SUBKEY_L(28) ^ dw,
--		CAMELLIA_SUBKEY_L(28) = dw;
--	dw = CAMELLIA_SUBKEY_L(29) ^ CAMELLIA_SUBKEY_R(29),
--		dw = CAMELLIA_RL8(dw);/* round 22 */
--	CAMELLIA_SUBKEY_R(29) = CAMELLIA_SUBKEY_L(29) ^ dw,
--		CAMELLIA_SUBKEY_L(29) = dw;
--	dw = CAMELLIA_SUBKEY_L(30) ^ CAMELLIA_SUBKEY_R(30),
--		dw = CAMELLIA_RL8(dw);/* round 23 */
--	CAMELLIA_SUBKEY_R(30) = CAMELLIA_SUBKEY_L(30) ^ dw,
--		CAMELLIA_SUBKEY_L(30) = dw;
--	dw = CAMELLIA_SUBKEY_L(31) ^ CAMELLIA_SUBKEY_R(31),
--		dw = CAMELLIA_RL8(dw);/* round 24 */
--	CAMELLIA_SUBKEY_R(31) = CAMELLIA_SUBKEY_L(31) ^ dw,
--		CAMELLIA_SUBKEY_L(31) = dw;
--
--	return;
-+	camellia_setup_tail(subkey, subL, subR, 32);
- }
- 
- static void camellia_setup192(const unsigned char *key, u32 *subkey)
-@@ -1197,482 +850,168 @@ static void camellia_setup192(const unsigned char *key, u32 *subkey)
- 	u32 krll, krlr, krrl,krrr;
- 
- 	memcpy(kk, key, 24);
--	memcpy((unsigned char *)&krll, key+16,4);
--	memcpy((unsigned char *)&krlr, key+20,4);
-+	memcpy((unsigned char *)&krll, key+16, 4);
-+	memcpy((unsigned char *)&krlr, key+20, 4);
- 	krrl = ~krll;
- 	krrr = ~krlr;
- 	memcpy(kk+24, (unsigned char *)&krrl, 4);
- 	memcpy(kk+28, (unsigned char *)&krrr, 4);
- 	camellia_setup256(kk, subkey);
--	return;
- }
- 
- 
--/**
-- * Stuff related to camellia encryption/decryption
-+/*
-+ * Encrypt/decrypt
-  */
--static void camellia_encrypt128(const u32 *subkey, __be32 *io_text)
--{
--	u32 il,ir,t0,t1;               /* temporary valiables */
--
--	u32 io[4];
--
--	io[0] = be32_to_cpu(io_text[0]);
--	io[1] = be32_to_cpu(io_text[1]);
--	io[2] = be32_to_cpu(io_text[2]);
--	io[3] = be32_to_cpu(io_text[3]);
--
--	/* pre whitening but absorb kw2*/
--	io[0] ^= CAMELLIA_SUBKEY_L(0);
--	io[1] ^= CAMELLIA_SUBKEY_R(0);
--	/* main iteration */
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
--		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
--		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
--			 io[0],io[1],il,ir,t0,t1);
-+#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \
-+    do {								\
-+	t0 = kll;							\
-+	t2 = krr;							\
-+	t0 &= ll;							\
-+	t2 |= rr;							\
-+	rl ^= t2;							\
-+	lr ^= ROL1(t0);							\
-+	t3 = krl;							\
-+	t1 = klr;							\
-+	t3 &= rl;							\
-+	t1 |= lr;							\
-+	ll ^= t1;							\
-+	rr ^= ROL1(t3);							\
-+    } while(0)
- 
--	/* post whitening but kw4 */
--	io[2] ^= CAMELLIA_SUBKEY_L(24);
--	io[3] ^= CAMELLIA_SUBKEY_R(24);
--
--	t0 = io[0];
--	t1 = io[1];
--	io[0] = io[2];
--	io[1] = io[3];
--	io[2] = t0;
--	io[3] = t1;
--
--	io_text[0] = cpu_to_be32(io[0]);
--	io_text[1] = cpu_to_be32(io[1]);
--	io_text[2] = cpu_to_be32(io[2]);
--	io_text[3] = cpu_to_be32(io[3]);
--
--	return;
--}
-+#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir)		\
-+    do {								\
-+	ir =  camellia_sp1110[(u8)xr];					\
-+	il =  camellia_sp1110[    (xl >> 24)];				\
-+	ir ^= camellia_sp0222[    (xr >> 24)];				\
-+	il ^= camellia_sp0222[(u8)(xl >> 16)];				\
-+	ir ^= camellia_sp3033[(u8)(xr >> 16)];				\
-+	il ^= camellia_sp3033[(u8)(xl >> 8)];				\
-+	ir ^= camellia_sp4404[(u8)(xr >> 8)];				\
-+	il ^= camellia_sp4404[(u8)xl];					\
-+	il ^= kl;							\
-+	ir ^= il ^ kr;							\
-+	yl ^= ir;							\
-+	yr ^= ROR8(il) ^ ir;						\
-+    } while(0)
- 
--static void camellia_decrypt128(const u32 *subkey, __be32 *io_text)
-+/* max = 24: 128bit encrypt, max = 32: 256bit encrypt */
-+static void camellia_do_encrypt(const u32 *subkey, u32 *io, unsigned max)
- {
--	u32 il,ir,t0,t1;               /* temporary valiables */
-+	u32 il,ir,t0,t1;               /* temporary variables */
- 
--	u32 io[4];
--
--	io[0] = be32_to_cpu(io_text[0]);
--	io[1] = be32_to_cpu(io_text[1]);
--	io[2] = be32_to_cpu(io_text[2]);
--	io[3] = be32_to_cpu(io_text[3]);
--
--	/* pre whitening but absorb kw2*/
--	io[0] ^= CAMELLIA_SUBKEY_L(24);
--	io[1] ^= CAMELLIA_SUBKEY_R(24);
-+	/* pre whitening but absorb kw2 */
-+	io[0] ^= SUBKEY_L(0);
-+	io[1] ^= SUBKEY_R(0);
- 
- 	/* main iteration */
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
--		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
--		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
--			 io[0],io[1],il,ir,t0,t1);
--
--	/* post whitening but kw4 */
--	io[2] ^= CAMELLIA_SUBKEY_L(0);
--	io[3] ^= CAMELLIA_SUBKEY_R(0);
--
--	t0 = io[0];
--	t1 = io[1];
--	io[0] = io[2];
--	io[1] = io[3];
--	io[2] = t0;
--	io[3] = t1;
--
--	io_text[0] = cpu_to_be32(io[0]);
--	io_text[1] = cpu_to_be32(io[1]);
--	io_text[2] = cpu_to_be32(io[2]);
--	io_text[3] = cpu_to_be32(io[3]);
--
--	return;
--}
--
--
--/**
-- * stuff for 192 and 256bit encryption/decryption
-- */
--static void camellia_encrypt256(const u32 *subkey, __be32 *io_text)
--{
--	u32 il,ir,t0,t1;           /* temporary valiables */
--
--	u32 io[4];
--
--	io[0] = be32_to_cpu(io_text[0]);
--	io[1] = be32_to_cpu(io_text[1]);
--	io[2] = be32_to_cpu(io_text[2]);
--	io[3] = be32_to_cpu(io_text[3]);
-+#define ROUNDS(i) do { \
-+	CAMELLIA_ROUNDSM(io[0],io[1], \
-+			 SUBKEY_L(i + 2),SUBKEY_R(i + 2), \
-+			 io[2],io[3],il,ir); \
-+	CAMELLIA_ROUNDSM(io[2],io[3], \
-+			 SUBKEY_L(i + 3),SUBKEY_R(i + 3), \
-+			 io[0],io[1],il,ir); \
-+	CAMELLIA_ROUNDSM(io[0],io[1], \
-+			 SUBKEY_L(i + 4),SUBKEY_R(i + 4), \
-+			 io[2],io[3],il,ir); \
-+	CAMELLIA_ROUNDSM(io[2],io[3], \
-+			 SUBKEY_L(i + 5),SUBKEY_R(i + 5), \
-+			 io[0],io[1],il,ir); \
-+	CAMELLIA_ROUNDSM(io[0],io[1], \
-+			 SUBKEY_L(i + 6),SUBKEY_R(i + 6), \
-+			 io[2],io[3],il,ir); \
-+	CAMELLIA_ROUNDSM(io[2],io[3], \
-+			 SUBKEY_L(i + 7),SUBKEY_R(i + 7), \
-+			 io[0],io[1],il,ir); \
-+} while (0)
-+#define FLS(i) do { \
-+	CAMELLIA_FLS(io[0],io[1],io[2],io[3], \
-+		     SUBKEY_L(i + 0),SUBKEY_R(i + 0), \
-+		     SUBKEY_L(i + 1),SUBKEY_R(i + 1), \
-+		     t0,t1,il,ir); \
-+} while (0)
++static struct crypto_instance *crypto_rfc4106_alloc(struct rtattr **tb)
++{
++	struct crypto_attr_type *algt;
++	struct crypto_instance *inst;
++	struct crypto_aead_spawn *spawn;
++	struct crypto_alg *alg;
++	const char *ccm_name;
++	int err;
 +
-+	ROUNDS(0);
-+	FLS(8);
-+	ROUNDS(8);
-+	FLS(16);
-+	ROUNDS(16);
-+	if (max == 32) {
-+		FLS(24);
-+		ROUNDS(24);
-+	}
- 
--	/* pre whitening but absorb kw2*/
--	io[0] ^= CAMELLIA_SUBKEY_L(0);
--	io[1] ^= CAMELLIA_SUBKEY_R(0);
--
--	/* main iteration */
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
--		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
--		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
--		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
--			 io[0],io[1],il,ir,t0,t1);
-+#undef ROUNDS
-+#undef FLS
- 
- 	/* post whitening but kw4 */
--	io[2] ^= CAMELLIA_SUBKEY_L(32);
--	io[3] ^= CAMELLIA_SUBKEY_R(32);
--
--	t0 = io[0];
--	t1 = io[1];
--	io[0] = io[2];
--	io[1] = io[3];
--	io[2] = t0;
--	io[3] = t1;
--
--	io_text[0] = cpu_to_be32(io[0]);
--	io_text[1] = cpu_to_be32(io[1]);
--	io_text[2] = cpu_to_be32(io[2]);
--	io_text[3] = cpu_to_be32(io[3]);
--
--	return;
-+	io[2] ^= SUBKEY_L(max);
-+	io[3] ^= SUBKEY_R(max);
-+	/* NB: io[0],[1] should be swapped with [2],[3] by caller! */
- }
- 
--
--static void camellia_decrypt256(const u32 *subkey, __be32 *io_text)
-+static void camellia_do_decrypt(const u32 *subkey, u32 *io, unsigned i)
- {
--	u32 il,ir,t0,t1;           /* temporary valiables */
-+	u32 il,ir,t0,t1;               /* temporary variables */
- 
--	u32 io[4];
--
--	io[0] = be32_to_cpu(io_text[0]);
--	io[1] = be32_to_cpu(io_text[1]);
--	io[2] = be32_to_cpu(io_text[2]);
--	io[3] = be32_to_cpu(io_text[3]);
--
--	/* pre whitening but absorb kw2*/
--	io[0] ^= CAMELLIA_SUBKEY_L(32);
--	io[1] ^= CAMELLIA_SUBKEY_R(32);
-+	/* pre whitening but absorb kw2 */
-+	io[0] ^= SUBKEY_L(i);
-+	io[1] ^= SUBKEY_R(i);
- 
- 	/* main iteration */
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(31),CAMELLIA_SUBKEY_R(31),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(30),CAMELLIA_SUBKEY_R(30),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(29),CAMELLIA_SUBKEY_R(29),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(28),CAMELLIA_SUBKEY_R(28),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(27),CAMELLIA_SUBKEY_R(27),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(26),CAMELLIA_SUBKEY_R(26),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(25),CAMELLIA_SUBKEY_R(25),
--		     CAMELLIA_SUBKEY_L(24),CAMELLIA_SUBKEY_R(24),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(23),CAMELLIA_SUBKEY_R(23),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(22),CAMELLIA_SUBKEY_R(22),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(21),CAMELLIA_SUBKEY_R(21),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(20),CAMELLIA_SUBKEY_R(20),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(19),CAMELLIA_SUBKEY_R(19),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(18),CAMELLIA_SUBKEY_R(18),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(17),CAMELLIA_SUBKEY_R(17),
--		     CAMELLIA_SUBKEY_L(16),CAMELLIA_SUBKEY_R(16),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(15),CAMELLIA_SUBKEY_R(15),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(14),CAMELLIA_SUBKEY_R(14),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(13),CAMELLIA_SUBKEY_R(13),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(12),CAMELLIA_SUBKEY_R(12),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(11),CAMELLIA_SUBKEY_R(11),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(10),CAMELLIA_SUBKEY_R(10),
--			 io[0],io[1],il,ir,t0,t1);
--
--	CAMELLIA_FLS(io[0],io[1],io[2],io[3],
--		     CAMELLIA_SUBKEY_L(9),CAMELLIA_SUBKEY_R(9),
--		     CAMELLIA_SUBKEY_L(8),CAMELLIA_SUBKEY_R(8),
--		     t0,t1,il,ir);
--
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(7),CAMELLIA_SUBKEY_R(7),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(6),CAMELLIA_SUBKEY_R(6),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(5),CAMELLIA_SUBKEY_R(5),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(4),CAMELLIA_SUBKEY_R(4),
--			 io[0],io[1],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[0],io[1],
--			 CAMELLIA_SUBKEY_L(3),CAMELLIA_SUBKEY_R(3),
--			 io[2],io[3],il,ir,t0,t1);
--	CAMELLIA_ROUNDSM(io[2],io[3],
--			 CAMELLIA_SUBKEY_L(2),CAMELLIA_SUBKEY_R(2),
--			 io[0],io[1],il,ir,t0,t1);
-+#define ROUNDS(i) do { \
-+	CAMELLIA_ROUNDSM(io[0],io[1], \
-+			 SUBKEY_L(i + 7),SUBKEY_R(i + 7), \
-+			 io[2],io[3],il,ir); \
-+	CAMELLIA_ROUNDSM(io[2],io[3], \
-+			 SUBKEY_L(i + 6),SUBKEY_R(i + 6), \
-+			 io[0],io[1],il,ir); \
-+	CAMELLIA_ROUNDSM(io[0],io[1], \
-+			 SUBKEY_L(i + 5),SUBKEY_R(i + 5), \
-+			 io[2],io[3],il,ir); \
-+	CAMELLIA_ROUNDSM(io[2],io[3], \
-+			 SUBKEY_L(i + 4),SUBKEY_R(i + 4), \
-+			 io[0],io[1],il,ir); \
-+	CAMELLIA_ROUNDSM(io[0],io[1], \
-+			 SUBKEY_L(i + 3),SUBKEY_R(i + 3), \
-+			 io[2],io[3],il,ir); \
-+	CAMELLIA_ROUNDSM(io[2],io[3], \
-+			 SUBKEY_L(i + 2),SUBKEY_R(i + 2), \
-+			 io[0],io[1],il,ir); \
-+} while (0)
-+#define FLS(i) do { \
-+	CAMELLIA_FLS(io[0],io[1],io[2],io[3], \
-+		     SUBKEY_L(i + 1),SUBKEY_R(i + 1), \
-+		     SUBKEY_L(i + 0),SUBKEY_R(i + 0), \
-+		     t0,t1,il,ir); \
-+} while (0)
++	algt = crypto_get_attr_type(tb);
++	err = PTR_ERR(algt);
++	if (IS_ERR(algt))
++		return ERR_PTR(err);
++
++	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
++		return ERR_PTR(-EINVAL);
++
++	ccm_name = crypto_attr_alg_name(tb[1]);
++	err = PTR_ERR(ccm_name);
++	if (IS_ERR(ccm_name))
++		return ERR_PTR(err);
++
++	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
++	if (!inst)
++		return ERR_PTR(-ENOMEM);
++
++	spawn = crypto_instance_ctx(inst);
++	crypto_set_aead_spawn(spawn, inst);
++	err = crypto_grab_aead(spawn, ccm_name, 0,
++			       crypto_requires_sync(algt->type, algt->mask));
++	if (err)
++		goto out_free_inst;
 +
-+	if (i == 32) {
-+		ROUNDS(24);
-+		FLS(24);
-+	}
-+	ROUNDS(16);
-+	FLS(16);
-+	ROUNDS(8);
-+	FLS(8);
-+	ROUNDS(0);
++	alg = crypto_aead_spawn_alg(spawn);
 +
-+#undef ROUNDS
-+#undef FLS
- 
- 	/* post whitening but kw4 */
--	io[2] ^= CAMELLIA_SUBKEY_L(0);
--	io[3] ^= CAMELLIA_SUBKEY_R(0);
--
--	t0 = io[0];
--	t1 = io[1];
--	io[0] = io[2];
--	io[1] = io[3];
--	io[2] = t0;
--	io[3] = t1;
--
--	io_text[0] = cpu_to_be32(io[0]);
--	io_text[1] = cpu_to_be32(io[1]);
--	io_text[2] = cpu_to_be32(io[2]);
--	io_text[3] = cpu_to_be32(io[3]);
--
--	return;
-+	io[2] ^= SUBKEY_L(0);
-+	io[3] ^= SUBKEY_R(0);
-+	/* NB: 0,1 should be swapped with 2,3 by caller! */
- }
- 
- 
-+struct camellia_ctx {
-+	int key_length;
-+	u32 key_table[CAMELLIA_TABLE_BYTE_LEN / sizeof(u32)];
++	err = -EINVAL;
++
++	/* We only support 16-byte blocks. */
++	if (alg->cra_aead.ivsize != 16)
++		goto out_drop_alg;
++
++	/* Not a stream cipher? */
++	if (alg->cra_blocksize != 1)
++		goto out_drop_alg;
++
++	err = -ENAMETOOLONG;
++	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
++		     "rfc4106(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
++	    snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
++		     "rfc4106(%s)", alg->cra_driver_name) >=
++	    CRYPTO_MAX_ALG_NAME)
++		goto out_drop_alg;
++
++	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
++	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
++	inst->alg.cra_priority = alg->cra_priority;
++	inst->alg.cra_blocksize = 1;
++	inst->alg.cra_alignmask = alg->cra_alignmask;
++	inst->alg.cra_type = &crypto_nivaead_type;
++
++	inst->alg.cra_aead.ivsize = 8;
++	inst->alg.cra_aead.maxauthsize = 16;
++
++	inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx);
++
++	inst->alg.cra_init = crypto_rfc4106_init_tfm;
++	inst->alg.cra_exit = crypto_rfc4106_exit_tfm;
++
++	inst->alg.cra_aead.setkey = crypto_rfc4106_setkey;
++	inst->alg.cra_aead.setauthsize = crypto_rfc4106_setauthsize;
++	inst->alg.cra_aead.encrypt = crypto_rfc4106_encrypt;
++	inst->alg.cra_aead.decrypt = crypto_rfc4106_decrypt;
++
++	inst->alg.cra_aead.geniv = "seqiv";
++
++out:
++	return inst;
++
++out_drop_alg:
++	crypto_drop_aead(spawn);
++out_free_inst:
++	kfree(inst);
++	inst = ERR_PTR(err);
++	goto out;
++}
++
++static void crypto_rfc4106_free(struct crypto_instance *inst)
++{
++	crypto_drop_spawn(crypto_instance_ctx(inst));
++	kfree(inst);
++}
++
++static struct crypto_template crypto_rfc4106_tmpl = {
++	.name = "rfc4106",
++	.alloc = crypto_rfc4106_alloc,
++	.free = crypto_rfc4106_free,
++	.module = THIS_MODULE,
 +};
 +
- static int
- camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- 		 unsigned int key_len)
-@@ -1688,7 +1027,7 @@ camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- 
- 	cctx->key_length = key_len;
- 
--	switch(key_len) {
-+	switch (key_len) {
- 	case 16:
- 		camellia_setup128(key, cctx->key_table);
- 		break;
-@@ -1698,68 +1037,59 @@ camellia_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- 	case 32:
- 		camellia_setup256(key, cctx->key_table);
- 		break;
--	default:
--		break;
- 	}
- 
- 	return 0;
- }
- 
--
- static void camellia_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- {
- 	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
- 	const __be32 *src = (const __be32 *)in;
- 	__be32 *dst = (__be32 *)out;
++static int __init crypto_gcm_module_init(void)
++{
++	int err;
++
++	err = crypto_register_template(&crypto_gcm_base_tmpl);
++	if (err)
++		goto out;
++
++	err = crypto_register_template(&crypto_gcm_tmpl);
++	if (err)
++		goto out_undo_base;
++
++	err = crypto_register_template(&crypto_rfc4106_tmpl);
++	if (err)
++		goto out_undo_gcm;
++
++out:
++	return err;
++
++out_undo_gcm:
++	crypto_unregister_template(&crypto_gcm_tmpl);
++out_undo_base:
++	crypto_unregister_template(&crypto_gcm_base_tmpl);
++	goto out;
++}
++
++static void __exit crypto_gcm_module_exit(void)
++{
++	crypto_unregister_template(&crypto_rfc4106_tmpl);
++	crypto_unregister_template(&crypto_gcm_tmpl);
++	crypto_unregister_template(&crypto_gcm_base_tmpl);
++}
++
++module_init(crypto_gcm_module_init);
++module_exit(crypto_gcm_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Galois/Counter Mode");
++MODULE_AUTHOR("Mikko Herranen <mh1 at iki.fi>");
++MODULE_ALIAS("gcm_base");
++MODULE_ALIAS("rfc4106");
+diff --git a/crypto/hmac.c b/crypto/hmac.c
+index 0f05be7..a1d016a 100644
+--- a/crypto/hmac.c
++++ b/crypto/hmac.c
+@@ -17,6 +17,7 @@
+  */
  
--	__be32 tmp[4];
-+	u32 tmp[4];
+ #include <crypto/algapi.h>
++#include <crypto/scatterwalk.h>
+ #include <linux/err.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+@@ -160,7 +161,7 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
  
--	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
-+	tmp[0] = be32_to_cpu(src[0]);
-+	tmp[1] = be32_to_cpu(src[1]);
-+	tmp[2] = be32_to_cpu(src[2]);
-+	tmp[3] = be32_to_cpu(src[3]);
+ 	sg_init_table(sg1, 2);
+ 	sg_set_buf(sg1, ipad, bs);
+-	sg_set_page(&sg1[1], (void *) sg, 0, 0);
++	scatterwalk_sg_chain(sg1, 2, sg);
  
--	switch (cctx->key_length) {
--	case 16:
--		camellia_encrypt128(cctx->key_table, tmp);
--		break;
--	case 24:
--		/* fall through */
--	case 32:
--		camellia_encrypt256(cctx->key_table, tmp);
--		break;
--	default:
--		break;
--	}
-+	camellia_do_encrypt(cctx->key_table, tmp,
-+		cctx->key_length == 16 ? 24 : 32 /* for key lengths of 24 and 32 */
-+	);
+ 	sg_init_table(sg2, 1);
+ 	sg_set_buf(sg2, opad, bs + ds);
+diff --git a/crypto/internal.h b/crypto/internal.h
+index abb01f7..32f4c21 100644
+--- a/crypto/internal.h
++++ b/crypto/internal.h
+@@ -25,7 +25,6 @@
+ #include <linux/notifier.h>
+ #include <linux/rwsem.h>
+ #include <linux/slab.h>
+-#include <asm/kmap_types.h>
  
--	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
-+	/* do_encrypt returns 0,1 swapped with 2,3 */
-+	dst[0] = cpu_to_be32(tmp[2]);
-+	dst[1] = cpu_to_be32(tmp[3]);
-+	dst[2] = cpu_to_be32(tmp[0]);
-+	dst[3] = cpu_to_be32(tmp[1]);
- }
+ /* Crypto notification events. */
+ enum {
+@@ -50,34 +49,6 @@ extern struct list_head crypto_alg_list;
+ extern struct rw_semaphore crypto_alg_sem;
+ extern struct blocking_notifier_head crypto_chain;
  
+-static inline enum km_type crypto_kmap_type(int out)
+-{
+-	enum km_type type;
 -
- static void camellia_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- {
- 	const struct camellia_ctx *cctx = crypto_tfm_ctx(tfm);
- 	const __be32 *src = (const __be32 *)in;
- 	__be32 *dst = (__be32 *)out;
- 
--	__be32 tmp[4];
-+	u32 tmp[4];
- 
--	memcpy(tmp, src, CAMELLIA_BLOCK_SIZE);
-+	tmp[0] = be32_to_cpu(src[0]);
-+	tmp[1] = be32_to_cpu(src[1]);
-+	tmp[2] = be32_to_cpu(src[2]);
-+	tmp[3] = be32_to_cpu(src[3]);
- 
--	switch (cctx->key_length) {
--	case 16:
--		camellia_decrypt128(cctx->key_table, tmp);
--		break;
--	case 24:
--		/* fall through */
--	case 32:
--		camellia_decrypt256(cctx->key_table, tmp);
--		break;
--	default:
--		break;
--	}
-+	camellia_do_decrypt(cctx->key_table, tmp,
-+		cctx->key_length == 16 ? 24 : 32 /* for key lengths of 24 and 32 */
-+	);
- 
--	memcpy(dst, tmp, CAMELLIA_BLOCK_SIZE);
-+	/* do_decrypt returns 0,1 swapped with 2,3 */
-+	dst[0] = cpu_to_be32(tmp[2]);
-+	dst[1] = cpu_to_be32(tmp[3]);
-+	dst[2] = cpu_to_be32(tmp[0]);
-+	dst[3] = cpu_to_be32(tmp[1]);
- }
- 
+-	if (in_softirq())
+-		type = out * (KM_SOFTIRQ1 - KM_SOFTIRQ0) + KM_SOFTIRQ0;
+-	else
+-		type = out * (KM_USER1 - KM_USER0) + KM_USER0;
 -
- static struct crypto_alg camellia_alg = {
- 	.cra_name		=	"camellia",
- 	.cra_driver_name	=	"camellia-generic",
-@@ -1786,16 +1116,13 @@ static int __init camellia_init(void)
- 	return crypto_register_alg(&camellia_alg);
- }
- 
+-	return type;
+-}
 -
- static void __exit camellia_fini(void)
- {
- 	crypto_unregister_alg(&camellia_alg);
- }
- 
+-static inline void *crypto_kmap(struct page *page, int out)
+-{
+-	return kmap_atomic(page, crypto_kmap_type(out));
+-}
 -
- module_init(camellia_init);
- module_exit(camellia_fini);
- 
+-static inline void crypto_kunmap(void *vaddr, int out)
+-{
+-	kunmap_atomic(vaddr, crypto_kmap_type(out));
+-}
 -
- MODULE_DESCRIPTION("Camellia Cipher Algorithm");
- MODULE_LICENSE("GPL");
-diff --git a/crypto/cast6.c b/crypto/cast6.c
-index 136ab6d..5fd9420 100644
---- a/crypto/cast6.c
-+++ b/crypto/cast6.c
-@@ -369,7 +369,7 @@ static const u8 Tr[4][8] = {
- };
- 
- /* forward octave */
--static inline void W(u32 *key, unsigned int i) {
-+static void W(u32 *key, unsigned int i) {
- 	u32 I;
- 	key[6] ^= F1(key[7], Tr[i % 4][0], Tm[i][0]);
- 	key[5] ^= F2(key[6], Tr[i % 4][1], Tm[i][1]);
-@@ -428,7 +428,7 @@ static int cast6_setkey(struct crypto_tfm *tfm, const u8 *in_key,
- }
+-static inline void crypto_yield(u32 flags)
+-{
+-	if (flags & CRYPTO_TFM_REQ_MAY_SLEEP)
+-		cond_resched();
+-}
+-
+ #ifdef CONFIG_PROC_FS
+ void __init crypto_init_proc(void);
+ void __exit crypto_exit_proc(void);
+@@ -122,6 +93,8 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm);
+ void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
+ void crypto_exit_compress_ops(struct crypto_tfm *tfm);
  
- /*forward quad round*/
--static inline void Q (u32 * block, u8 * Kr, u32 * Km) {
-+static void Q (u32 * block, u8 * Kr, u32 * Km) {
- 	u32 I;
- 	block[2] ^= F1(block[3], Kr[0], Km[0]);
- 	block[1] ^= F2(block[2], Kr[1], Km[1]);
-@@ -437,7 +437,7 @@ static inline void Q (u32 * block, u8 * Kr, u32 * Km) {
- }
++void crypto_larval_kill(struct crypto_alg *alg);
++struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
+ void crypto_larval_error(const char *name, u32 type, u32 mask);
  
- /*reverse quad round*/
--static inline void QBAR (u32 * block, u8 * Kr, u32 * Km) {
-+static void QBAR (u32 * block, u8 * Kr, u32 * Km) {
- 	u32 I;
-         block[3] ^= F1(block[0], Kr[3], Km[3]);
-         block[0] ^= F3(block[1], Kr[2], Km[2]);
-diff --git a/crypto/cbc.c b/crypto/cbc.c
-index 1f2649e..6affff8 100644
---- a/crypto/cbc.c
-+++ b/crypto/cbc.c
-@@ -14,13 +14,13 @@
- #include <linux/err.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
-+#include <linux/log2.h>
- #include <linux/module.h>
- #include <linux/scatterlist.h>
- #include <linux/slab.h>
+ void crypto_shoot_alg(struct crypto_alg *alg);
+diff --git a/crypto/lzo.c b/crypto/lzo.c
+new file mode 100644
+index 0000000..48c3288
+--- /dev/null
++++ b/crypto/lzo.c
+@@ -0,0 +1,106 @@
++/*
++ * Cryptographic API.
++ *
++ * This program is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 as published by
++ * the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
++ * more details.
++ *
++ * You should have received a copy of the GNU General Public License along with
++ * this program; if not, write to the Free Software Foundation, Inc., 51
++ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ *
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/crypto.h>
++#include <linux/vmalloc.h>
++#include <linux/lzo.h>
++
++struct lzo_ctx {
++	void *lzo_comp_mem;
++};
++
++static int lzo_init(struct crypto_tfm *tfm)
++{
++	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
++	if (!ctx->lzo_comp_mem)
++		return -ENOMEM;
++
++	return 0;
++}
++
++static void lzo_exit(struct crypto_tfm *tfm)
++{
++	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
++
++	vfree(ctx->lzo_comp_mem);
++}
++
++static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
++			    unsigned int slen, u8 *dst, unsigned int *dlen)
++{
++	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
++	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
++	int err;
++
++	err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem);
++
++	if (err != LZO_E_OK)
++		return -EINVAL;
++
++	*dlen = tmp_len;
++	return 0;
++}
++
++static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
++			      unsigned int slen, u8 *dst, unsigned int *dlen)
++{
++	int err;
++	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
++
++	err = lzo1x_decompress_safe(src, slen, dst, &tmp_len);
++
++	if (err != LZO_E_OK)
++		return -EINVAL;
++
++	*dlen = tmp_len;
++	return 0;
++
++}
++
++static struct crypto_alg alg = {
++	.cra_name		= "lzo",
++	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
++	.cra_ctxsize		= sizeof(struct lzo_ctx),
++	.cra_module		= THIS_MODULE,
++	.cra_list		= LIST_HEAD_INIT(alg.cra_list),
++	.cra_init		= lzo_init,
++	.cra_exit		= lzo_exit,
++	.cra_u			= { .compress = {
++	.coa_compress 		= lzo_compress,
++	.coa_decompress  	= lzo_decompress } }
++};
++
++static int __init init(void)
++{
++	return crypto_register_alg(&alg);
++}
++
++static void __exit fini(void)
++{
++	crypto_unregister_alg(&alg);
++}
++
++module_init(init);
++module_exit(fini);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("LZO Compression Algorithm");
+diff --git a/crypto/pcbc.c b/crypto/pcbc.c
+index c3ed8a1..fe70477 100644
+--- a/crypto/pcbc.c
++++ b/crypto/pcbc.c
+@@ -24,7 +24,6 @@
  
- struct crypto_cbc_ctx {
+ struct crypto_pcbc_ctx {
  	struct crypto_cipher *child;
 -	void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
  };
  
- static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
-@@ -41,9 +41,7 @@ static int crypto_cbc_setkey(struct crypto_tfm *parent, const u8 *key,
+ static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
+@@ -45,9 +44,7 @@ static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
  
- static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
- 				      struct blkcipher_walk *walk,
--				      struct crypto_cipher *tfm,
--				      void (*xor)(u8 *, const u8 *,
--						  unsigned int))
-+				      struct crypto_cipher *tfm)
+ static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
+ 				       struct blkcipher_walk *walk,
+-				       struct crypto_cipher *tfm,
+-				       void (*xor)(u8 *, const u8 *,
+-						   unsigned int))
++				       struct crypto_cipher *tfm)
  {
  	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
  		crypto_cipher_alg(tfm)->cia_encrypt;
-@@ -54,7 +52,7 @@ static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
+@@ -58,10 +55,10 @@ static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
  	u8 *iv = walk->iv;
  
  	do {
@@ -355372,130 +384166,127 @@
 +		crypto_xor(iv, src, bsize);
  		fn(crypto_cipher_tfm(tfm), dst, iv);
  		memcpy(iv, dst, bsize);
+-		xor(iv, src, bsize);
++		crypto_xor(iv, src, bsize);
  
-@@ -67,9 +65,7 @@ static int crypto_cbc_encrypt_segment(struct blkcipher_desc *desc,
+ 		src += bsize;
+ 		dst += bsize;
+@@ -72,9 +69,7 @@ static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
  
- static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc,
- 				      struct blkcipher_walk *walk,
--				      struct crypto_cipher *tfm,
--				      void (*xor)(u8 *, const u8 *,
--						  unsigned int))
-+				      struct crypto_cipher *tfm)
+ static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
+ 				       struct blkcipher_walk *walk,
+-				       struct crypto_cipher *tfm,
+-				       void (*xor)(u8 *, const u8 *,
+-						   unsigned int))
++				       struct crypto_cipher *tfm)
  {
  	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
  		crypto_cipher_alg(tfm)->cia_encrypt;
-@@ -79,7 +75,7 @@ static int crypto_cbc_encrypt_inplace(struct blkcipher_desc *desc,
- 	u8 *iv = walk->iv;
+@@ -86,10 +81,10 @@ static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
  
  	do {
--		xor(src, iv, bsize);
-+		crypto_xor(src, iv, bsize);
- 		fn(crypto_cipher_tfm(tfm), src, src);
- 		iv = src;
+ 		memcpy(tmpbuf, src, bsize);
+-		xor(iv, tmpbuf, bsize);
++		crypto_xor(iv, src, bsize);
+ 		fn(crypto_cipher_tfm(tfm), src, iv);
+-		memcpy(iv, src, bsize);
+-		xor(iv, tmpbuf, bsize);
++		memcpy(iv, tmpbuf, bsize);
++		crypto_xor(iv, src, bsize);
  
-@@ -99,7 +95,6 @@ static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
+ 		src += bsize;
+ 	} while ((nbytes -= bsize) >= bsize);
+@@ -107,7 +102,6 @@ static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
  	struct crypto_blkcipher *tfm = desc->tfm;
- 	struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ 	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
  	struct crypto_cipher *child = ctx->child;
 -	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
  	int err;
  
  	blkcipher_walk_init(&walk, dst, src, nbytes);
-@@ -107,11 +102,9 @@ static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
+@@ -115,11 +109,11 @@ static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
  
  	while ((nbytes = walk.nbytes)) {
  		if (walk.src.virt.addr == walk.dst.virt.addr)
--			nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child,
--							    xor);
-+			nbytes = crypto_cbc_encrypt_inplace(desc, &walk, child);
+-			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
+-							     xor);
++			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk,
++							     child);
  		else
--			nbytes = crypto_cbc_encrypt_segment(desc, &walk, child,
--							    xor);
-+			nbytes = crypto_cbc_encrypt_segment(desc, &walk, child);
+-			nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
+-							     xor);
++			nbytes = crypto_pcbc_encrypt_segment(desc, &walk,
++							     child);
  		err = blkcipher_walk_done(desc, &walk, nbytes);
  	}
  
-@@ -120,9 +113,7 @@ static int crypto_cbc_encrypt(struct blkcipher_desc *desc,
+@@ -128,9 +122,7 @@ static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
  
- static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
- 				      struct blkcipher_walk *walk,
--				      struct crypto_cipher *tfm,
--				      void (*xor)(u8 *, const u8 *,
--						  unsigned int))
-+				      struct crypto_cipher *tfm)
+ static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
+ 				       struct blkcipher_walk *walk,
+-				       struct crypto_cipher *tfm,
+-				       void (*xor)(u8 *, const u8 *,
+-						   unsigned int))
++				       struct crypto_cipher *tfm)
  {
  	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
  		crypto_cipher_alg(tfm)->cia_decrypt;
-@@ -134,7 +125,7 @@ static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
+@@ -142,9 +134,9 @@ static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
  
  	do {
  		fn(crypto_cipher_tfm(tfm), dst, src);
 -		xor(dst, iv, bsize);
 +		crypto_xor(dst, iv, bsize);
- 		iv = src;
+ 		memcpy(iv, src, bsize);
+-		xor(iv, dst, bsize);
++		crypto_xor(iv, dst, bsize);
  
  		src += bsize;
-@@ -148,34 +139,29 @@ static int crypto_cbc_decrypt_segment(struct blkcipher_desc *desc,
+ 		dst += bsize;
+@@ -157,9 +149,7 @@ static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
  
- static int crypto_cbc_decrypt_inplace(struct blkcipher_desc *desc,
- 				      struct blkcipher_walk *walk,
--				      struct crypto_cipher *tfm,
--				      void (*xor)(u8 *, const u8 *,
--						  unsigned int))
-+				      struct crypto_cipher *tfm)
+ static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
+ 				       struct blkcipher_walk *walk,
+-				       struct crypto_cipher *tfm,
+-				       void (*xor)(u8 *, const u8 *,
+-						   unsigned int))
++				       struct crypto_cipher *tfm)
  {
  	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
  		crypto_cipher_alg(tfm)->cia_decrypt;
- 	int bsize = crypto_cipher_blocksize(tfm);
--	unsigned long alignmask = crypto_cipher_alignmask(tfm);
- 	unsigned int nbytes = walk->nbytes;
- 	u8 *src = walk->src.virt.addr;
--	u8 stack[bsize + alignmask];
--	u8 *first_iv = (u8 *)ALIGN((unsigned long)stack, alignmask + 1);
--
--	memcpy(first_iv, walk->iv, bsize);
-+	u8 last_iv[bsize];
- 
- 	/* Start of the last block. */
--	src += nbytes - nbytes % bsize - bsize;
--	memcpy(walk->iv, src, bsize);
-+	src += nbytes - (nbytes & (bsize - 1)) - bsize;
-+	memcpy(last_iv, src, bsize);
- 
- 	for (;;) {
+@@ -172,9 +162,9 @@ static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
+ 	do {
+ 		memcpy(tmpbuf, src, bsize);
  		fn(crypto_cipher_tfm(tfm), src, src);
- 		if ((nbytes -= bsize) < bsize)
- 			break;
--		xor(src, src - bsize, bsize);
-+		crypto_xor(src, src - bsize, bsize);
- 		src -= bsize;
- 	}
- 
--	xor(src, first_iv, bsize);
-+	crypto_xor(src, walk->iv, bsize);
-+	memcpy(walk->iv, last_iv, bsize);
+-		xor(src, iv, bsize);
++		crypto_xor(src, iv, bsize);
+ 		memcpy(iv, tmpbuf, bsize);
+-		xor(iv, src, bsize);
++		crypto_xor(iv, src, bsize);
  
- 	return nbytes;
- }
-@@ -188,7 +174,6 @@ static int crypto_cbc_decrypt(struct blkcipher_desc *desc,
+ 		src += bsize;
+ 	} while ((nbytes -= bsize) >= bsize);
+@@ -192,7 +182,6 @@ static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
  	struct crypto_blkcipher *tfm = desc->tfm;
- 	struct crypto_cbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
+ 	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
  	struct crypto_cipher *child = ctx->child;
 -	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
  	int err;
  
  	blkcipher_walk_init(&walk, dst, src, nbytes);
-@@ -196,48 +181,15 @@ static int crypto_cbc_decrypt(struct blkcipher_desc *desc,
+@@ -200,48 +189,17 @@ static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
  
  	while ((nbytes = walk.nbytes)) {
  		if (walk.src.virt.addr == walk.dst.virt.addr)
--			nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child,
--							    xor);
-+			nbytes = crypto_cbc_decrypt_inplace(desc, &walk, child);
+-			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
+-							     xor);
++			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk,
++							     child);
  		else
--			nbytes = crypto_cbc_decrypt_segment(desc, &walk, child,
--							    xor);
-+			nbytes = crypto_cbc_decrypt_segment(desc, &walk, child);
+-			nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
+-							     xor);
++			nbytes = crypto_pcbc_decrypt_segment(desc, &walk,
++							     child);
  		err = blkcipher_walk_done(desc, &walk, nbytes);
  	}
  
@@ -355533,11 +384324,11 @@
 -	((u32 *)a)[3] ^= ((u32 *)b)[3];
 -}
 -
- static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
+ static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-@@ -245,22 +197,6 @@ static int crypto_cbc_init_tfm(struct crypto_tfm *tfm)
- 	struct crypto_cbc_ctx *ctx = crypto_tfm_ctx(tfm);
+@@ -249,22 +207,6 @@ static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
+ 	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
  	struct crypto_cipher *cipher;
  
 -	switch (crypto_tfm_alg_blocksize(tfm)) {
@@ -355559,18 +384350,7 @@
  	cipher = crypto_spawn_cipher(spawn);
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
-@@ -290,6 +226,10 @@ static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
- 	if (IS_ERR(alg))
- 		return ERR_PTR(PTR_ERR(alg));
- 
-+	inst = ERR_PTR(-EINVAL);
-+	if (!is_power_of_2(alg->cra_blocksize))
-+		goto out_put_alg;
-+
- 	inst = crypto_alloc_instance("cbc", alg);
- 	if (IS_ERR(inst))
- 		goto out_put_alg;
-@@ -300,8 +240,9 @@ static struct crypto_instance *crypto_cbc_alloc(struct rtattr **tb)
+@@ -304,8 +246,9 @@ static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
  	inst->alg.cra_alignmask = alg->cra_alignmask;
  	inst->alg.cra_type = &crypto_blkcipher_type;
  
@@ -355582,16 +384362,25 @@
  	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
  	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
  	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
-diff --git a/crypto/ccm.c b/crypto/ccm.c
+diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
 new file mode 100644
-index 0000000..7cf7e5a
+index 0000000..1fa4e4d
 --- /dev/null
-+++ b/crypto/ccm.c
-@@ -0,0 +1,889 @@
++++ b/crypto/salsa20_generic.c
+@@ -0,0 +1,255 @@
 +/*
-+ * CCM: Counter with CBC-MAC
++ * Salsa20: Salsa20 stream cipher algorithm
 + *
-+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten at us.ibm.com>
++ * Copyright (c) 2007 Tan Swee Heng <thesweeheng at gmail.com>
++ *
++ * Derived from:
++ * - salsa20.c: Public domain C code by Daniel J. Bernstein <djb at cr.yp.to>
++ *
++ * Salsa20 is a stream cipher candidate in eSTREAM, the ECRYPT Stream
++ * Cipher Project. It is designed by Daniel J. Bernstein <djb at cr.yp.to>.
++ * More information about eSTREAM and Salsa20 can be found here:
++ *   http://www.ecrypt.eu.org/stream/
++ *   http://cr.yp.to/snuffle.html
 + *
 + * 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
@@ -355600,475 +384389,667 @@
 + *
 + */
 +
-+#include <crypto/internal/aead.h>
-+#include <crypto/internal/skcipher.h>
-+#include <crypto/scatterwalk.h>
-+#include <linux/err.h>
 +#include <linux/init.h>
-+#include <linux/kernel.h>
 +#include <linux/module.h>
-+#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/crypto.h>
++#include <linux/types.h>
++#include <crypto/algapi.h>
++#include <asm/byteorder.h>
 +
-+#include "internal.h"
++#define SALSA20_IV_SIZE        8U
++#define SALSA20_MIN_KEY_SIZE  16U
++#define SALSA20_MAX_KEY_SIZE  32U
 +
-+struct ccm_instance_ctx {
-+	struct crypto_skcipher_spawn ctr;
-+	struct crypto_spawn cipher;
-+};
++/*
++ * Start of code taken from D. J. Bernstein's reference implementation.
++ * With some modifications and optimizations made to suit our needs.
++ */
 +
-+struct crypto_ccm_ctx {
-+	struct crypto_cipher *cipher;
-+	struct crypto_ablkcipher *ctr;
-+};
++/*
++salsa20-ref.c version 20051118
++D. J. Bernstein
++Public domain.
++*/
 +
-+struct crypto_rfc4309_ctx {
-+	struct crypto_aead *child;
-+	u8 nonce[3];
-+};
++#define ROTATE(v,n) (((v) << (n)) | ((v) >> (32 - (n))))
++#define XOR(v,w) ((v) ^ (w))
++#define PLUS(v,w) (((v) + (w)))
++#define PLUSONE(v) (PLUS((v),1))
++#define U32TO8_LITTLE(p, v) \
++	{ (p)[0] = (v >>  0) & 0xff; (p)[1] = (v >>  8) & 0xff; \
++	  (p)[2] = (v >> 16) & 0xff; (p)[3] = (v >> 24) & 0xff; }
++#define U8TO32_LITTLE(p)   \
++	(((u32)((p)[0])      ) | ((u32)((p)[1]) <<  8) | \
++	 ((u32)((p)[2]) << 16) | ((u32)((p)[3]) << 24)   )
 +
-+struct crypto_ccm_req_priv_ctx {
-+	u8 odata[16];
-+	u8 idata[16];
-+	u8 auth_tag[16];
-+	u32 ilen;
-+	u32 flags;
-+	struct scatterlist src[2];
-+	struct scatterlist dst[2];
-+	struct ablkcipher_request abreq;
++struct salsa20_ctx
++{
++	u32 input[16];
 +};
 +
-+static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
-+	struct aead_request *req)
++static void salsa20_wordtobyte(u8 output[64], const u32 input[16])
 +{
-+	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
++	u32 x[16];
++	int i;
 +
-+	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
++	memcpy(x, input, sizeof(x));
++	for (i = 20; i > 0; i -= 2) {
++		x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7));
++		x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9));
++		x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13));
++		x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18));
++		x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7));
++		x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9));
++		x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13));
++		x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18));
++		x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7));
++		x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9));
++		x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13));
++		x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18));
++		x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7));
++		x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9));
++		x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13));
++		x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18));
++		x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7));
++		x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9));
++		x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13));
++		x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18));
++		x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7));
++		x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9));
++		x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13));
++		x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18));
++		x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7));
++		x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9));
++		x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13));
++		x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18));
++		x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7));
++		x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9));
++		x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13));
++		x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18));
++	}
++	for (i = 0; i < 16; ++i)
++		x[i] = PLUS(x[i],input[i]);
++	for (i = 0; i < 16; ++i)
++		U32TO8_LITTLE(output + 4 * i,x[i]);
 +}
 +
-+static int set_msg_len(u8 *block, unsigned int msglen, int csize)
-+{
-+	__be32 data;
-+
-+	memset(block, 0, csize);
-+	block += csize;
++static const char sigma[16] = "expand 32-byte k";
++static const char tau[16] = "expand 16-byte k";
 +
-+	if (csize >= 4)
-+		csize = 4;
-+	else if (msglen > (1 << (8 * csize)))
-+		return -EOVERFLOW;
++static void salsa20_keysetup(struct salsa20_ctx *ctx, const u8 *k, u32 kbytes)
++{
++	const char *constants;
 +
-+	data = cpu_to_be32(msglen);
-+	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
++	ctx->input[1] = U8TO32_LITTLE(k + 0);
++	ctx->input[2] = U8TO32_LITTLE(k + 4);
++	ctx->input[3] = U8TO32_LITTLE(k + 8);
++	ctx->input[4] = U8TO32_LITTLE(k + 12);
++	if (kbytes == 32) { /* recommended */
++		k += 16;
++		constants = sigma;
++	} else { /* kbytes == 16 */
++		constants = tau;
++	}
++	ctx->input[11] = U8TO32_LITTLE(k + 0);
++	ctx->input[12] = U8TO32_LITTLE(k + 4);
++	ctx->input[13] = U8TO32_LITTLE(k + 8);
++	ctx->input[14] = U8TO32_LITTLE(k + 12);
++	ctx->input[0] = U8TO32_LITTLE(constants + 0);
++	ctx->input[5] = U8TO32_LITTLE(constants + 4);
++	ctx->input[10] = U8TO32_LITTLE(constants + 8);
++	ctx->input[15] = U8TO32_LITTLE(constants + 12);
++}
 +
-+	return 0;
++static void salsa20_ivsetup(struct salsa20_ctx *ctx, const u8 *iv)
++{
++	ctx->input[6] = U8TO32_LITTLE(iv + 0);
++	ctx->input[7] = U8TO32_LITTLE(iv + 4);
++	ctx->input[8] = 0;
++	ctx->input[9] = 0;
 +}
 +
-+static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
-+			     unsigned int keylen)
++static void salsa20_encrypt_bytes(struct salsa20_ctx *ctx, u8 *dst,
++				  const u8 *src, unsigned int bytes)
 +{
-+	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_ablkcipher *ctr = ctx->ctr;
-+	struct crypto_cipher *tfm = ctx->cipher;
-+	int err = 0;
++	u8 buf[64];
 +
-+	crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
-+	crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
-+				    CRYPTO_TFM_REQ_MASK);
-+	err = crypto_ablkcipher_setkey(ctr, key, keylen);
-+	crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
-+			      CRYPTO_TFM_RES_MASK);
-+	if (err)
-+		goto out;
++	if (dst != src)
++		memcpy(dst, src, bytes);
 +
-+	crypto_cipher_clear_flags(tfm, CRYPTO_TFM_REQ_MASK);
-+	crypto_cipher_set_flags(tfm, crypto_aead_get_flags(aead) &
-+				    CRYPTO_TFM_REQ_MASK);
-+	err = crypto_cipher_setkey(tfm, key, keylen);
-+	crypto_aead_set_flags(aead, crypto_cipher_get_flags(tfm) &
-+			      CRYPTO_TFM_RES_MASK);
++	while (bytes) {
++		salsa20_wordtobyte(buf, ctx->input);
 +
-+out:
-+	return err;
-+}
++		ctx->input[8] = PLUSONE(ctx->input[8]);
++		if (!ctx->input[8])
++			ctx->input[9] = PLUSONE(ctx->input[9]);
 +
-+static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
-+				  unsigned int authsize)
-+{
-+	switch (authsize) {
-+	case 4:
-+	case 6:
-+	case 8:
-+	case 10:
-+	case 12:
-+	case 14:
-+	case 16:
-+		break;
-+	default:
-+		return -EINVAL;
++		if (bytes <= 64) {
++			crypto_xor(dst, buf, bytes);
++			return;
++		}
++
++		crypto_xor(dst, buf, 64);
++		bytes -= 64;
++		dst += 64;
 +	}
++}
++
++/*
++ * End of code taken from D. J. Bernstein's reference implementation.
++ */
 +
++static int setkey(struct crypto_tfm *tfm, const u8 *key,
++		  unsigned int keysize)
++{
++	struct salsa20_ctx *ctx = crypto_tfm_ctx(tfm);
++	salsa20_keysetup(ctx, key, keysize);
 +	return 0;
 +}
 +
-+static int format_input(u8 *info, struct aead_request *req,
-+			unsigned int cryptlen)
++static int encrypt(struct blkcipher_desc *desc,
++		   struct scatterlist *dst, struct scatterlist *src,
++		   unsigned int nbytes)
 +{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	unsigned int lp = req->iv[0];
-+	unsigned int l = lp + 1;
-+	unsigned int m;
++	struct blkcipher_walk walk;
++	struct crypto_blkcipher *tfm = desc->tfm;
++	struct salsa20_ctx *ctx = crypto_blkcipher_ctx(tfm);
++	int err;
 +
-+	m = crypto_aead_authsize(aead);
++	blkcipher_walk_init(&walk, dst, src, nbytes);
++	err = blkcipher_walk_virt_block(desc, &walk, 64);
 +
-+	memcpy(info, req->iv, 16);
++	salsa20_ivsetup(ctx, walk.iv);
 +
-+	/* format control info per RFC 3610 and
-+	 * NIST Special Publication 800-38C
-+	 */
-+	*info |= (8 * ((m - 2) / 2));
-+	if (req->assoclen)
-+		*info |= 64;
++	if (likely(walk.nbytes == nbytes))
++	{
++		salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
++				      walk.src.virt.addr, nbytes);
++		return blkcipher_walk_done(desc, &walk, 0);
++	}
 +
-+	return set_msg_len(info + 16 - l, cryptlen, l);
-+}
++	while (walk.nbytes >= 64) {
++		salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
++				      walk.src.virt.addr,
++				      walk.nbytes - (walk.nbytes % 64));
++		err = blkcipher_walk_done(desc, &walk, walk.nbytes % 64);
++	}
 +
-+static int format_adata(u8 *adata, unsigned int a)
-+{
-+	int len = 0;
++	if (walk.nbytes) {
++		salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
++				      walk.src.virt.addr, walk.nbytes);
++		err = blkcipher_walk_done(desc, &walk, 0);
++	}
 +
-+	/* add control info for associated data
-+	 * RFC 3610 and NIST Special Publication 800-38C
-+	 */
-+	if (a < 65280) {
-+		*(__be16 *)adata = cpu_to_be16(a);
-+		len = 2;
-+	} else  {
-+		*(__be16 *)adata = cpu_to_be16(0xfffe);
-+		*(__be32 *)&adata[2] = cpu_to_be32(a);
-+		len = 6;
++	return err;
++}
++
++static struct crypto_alg alg = {
++	.cra_name           =   "salsa20",
++	.cra_driver_name    =   "salsa20-generic",
++	.cra_priority       =   100,
++	.cra_flags          =   CRYPTO_ALG_TYPE_BLKCIPHER,
++	.cra_type           =   &crypto_blkcipher_type,
++	.cra_blocksize      =   1,
++	.cra_ctxsize        =   sizeof(struct salsa20_ctx),
++	.cra_alignmask      =	3,
++	.cra_module         =   THIS_MODULE,
++	.cra_list           =   LIST_HEAD_INIT(alg.cra_list),
++	.cra_u              =   {
++		.blkcipher = {
++			.setkey         =   setkey,
++			.encrypt        =   encrypt,
++			.decrypt        =   encrypt,
++			.min_keysize    =   SALSA20_MIN_KEY_SIZE,
++			.max_keysize    =   SALSA20_MAX_KEY_SIZE,
++			.ivsize         =   SALSA20_IV_SIZE,
++		}
 +	}
++};
 +
-+	return len;
++static int __init init(void)
++{
++	return crypto_register_alg(&alg);
 +}
 +
-+static void compute_mac(struct crypto_cipher *tfm, u8 *data, int n,
-+		       struct crypto_ccm_req_priv_ctx *pctx)
++static void __exit fini(void)
 +{
-+	unsigned int bs = 16;
-+	u8 *odata = pctx->odata;
-+	u8 *idata = pctx->idata;
-+	int datalen, getlen;
++	crypto_unregister_alg(&alg);
++}
 +
-+	datalen = n;
++module_init(init);
++module_exit(fini);
 +
-+	/* first time in here, block may be partially filled. */
-+	getlen = bs - pctx->ilen;
-+	if (datalen >= getlen) {
-+		memcpy(idata + pctx->ilen, data, getlen);
-+		crypto_xor(odata, idata, bs);
-+		crypto_cipher_encrypt_one(tfm, odata, odata);
-+		datalen -= getlen;
-+		data += getlen;
-+		pctx->ilen = 0;
-+	}
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
++MODULE_ALIAS("salsa20");
+diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
+index b9bbda0..9aeeb52 100644
+--- a/crypto/scatterwalk.c
++++ b/crypto/scatterwalk.c
+@@ -13,6 +13,8 @@
+  * any later version.
+  *
+  */
 +
-+	/* now encrypt rest of data */
-+	while (datalen >= bs) {
-+		crypto_xor(odata, data, bs);
-+		crypto_cipher_encrypt_one(tfm, odata, odata);
++#include <crypto/scatterwalk.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
+@@ -20,9 +22,6 @@
+ #include <linux/highmem.h>
+ #include <linux/scatterlist.h>
+ 
+-#include "internal.h"
+-#include "scatterwalk.h"
+-
+ static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
+ {
+ 	void *src = out ? buf : sgdata;
+@@ -106,6 +105,9 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
+ 	struct scatter_walk walk;
+ 	unsigned int offset = 0;
+ 
++	if (!nbytes)
++		return;
 +
-+		datalen -= bs;
-+		data += bs;
-+	}
+ 	for (;;) {
+ 		scatterwalk_start(&walk, sg);
+ 
+@@ -113,7 +115,7 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
+ 			break;
+ 
+ 		offset += sg->length;
+-		sg = sg_next(sg);
++		sg = scatterwalk_sg_next(sg);
+ 	}
+ 
+ 	scatterwalk_advance(&walk, start - offset);
+diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h
+deleted file mode 100644
+index 87ed681..0000000
+--- a/crypto/scatterwalk.h
++++ /dev/null
+@@ -1,80 +0,0 @@
+-/*
+- * Cryptographic API.
+- *
+- * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
+- * Copyright (c) 2002 Adam J. Richter <adam at yggdrasil.com>
+- * Copyright (c) 2004 Jean-Luc Cooke <jlcooke at certainkey.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.
+- *
+- */
+-
+-#ifndef _CRYPTO_SCATTERWALK_H
+-#define _CRYPTO_SCATTERWALK_H
+-
+-#include <linux/mm.h>
+-#include <linux/scatterlist.h>
+-
+-#include "internal.h"
+-
+-static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
+-{
+-	return (++sg)->length ? sg : (void *) sg_page(sg);
+-}
+-
+-static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in,
+-						struct scatter_walk *walk_out)
+-{
+-	return !(((sg_page(walk_in->sg) - sg_page(walk_out->sg)) << PAGE_SHIFT) +
+-		 (int)(walk_in->offset - walk_out->offset));
+-}
+-
+-static inline unsigned int scatterwalk_pagelen(struct scatter_walk *walk)
+-{
+-	unsigned int len = walk->sg->offset + walk->sg->length - walk->offset;
+-	unsigned int len_this_page = offset_in_page(~walk->offset) + 1;
+-	return len_this_page > len ? len : len_this_page;
+-}
+-
+-static inline unsigned int scatterwalk_clamp(struct scatter_walk *walk,
+-					     unsigned int nbytes)
+-{
+-	unsigned int len_this_page = scatterwalk_pagelen(walk);
+-	return nbytes > len_this_page ? len_this_page : nbytes;
+-}
+-
+-static inline void scatterwalk_advance(struct scatter_walk *walk,
+-				       unsigned int nbytes)
+-{
+-	walk->offset += nbytes;
+-}
+-
+-static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk,
+-					       unsigned int alignmask)
+-{
+-	return !(walk->offset & alignmask);
+-}
+-
+-static inline struct page *scatterwalk_page(struct scatter_walk *walk)
+-{
+-	return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
+-}
+-
+-static inline void scatterwalk_unmap(void *vaddr, int out)
+-{
+-	crypto_kunmap(vaddr, out);
+-}
+-
+-void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
+-void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
+-			    size_t nbytes, int out);
+-void *scatterwalk_map(struct scatter_walk *walk, int out);
+-void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+-
+-void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
+-			      unsigned int start, unsigned int nbytes, int out);
+-
+-#endif  /* _CRYPTO_SCATTERWALK_H */
+diff --git a/crypto/seqiv.c b/crypto/seqiv.c
+new file mode 100644
+index 0000000..b903aab
+--- /dev/null
++++ b/crypto/seqiv.c
+@@ -0,0 +1,345 @@
++/*
++ * seqiv: Sequence Number IV Generator
++ *
++ * This generator generates an IV based on a sequence number by xoring it
++ * with a salt.  This algorithm is mainly useful for CTR and similar modes.
++ *
++ * Copyright (c) 2007 Herbert Xu <herbert at gondor.apana.org.au>
++ *
++ * 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.
++ *
++ */
 +
-+	/* check and see if there's leftover data that wasn't
-+	 * enough to fill a block.
-+	 */
-+	if (datalen) {
-+		memcpy(idata + pctx->ilen, data, datalen);
-+		pctx->ilen += datalen;
-+	}
-+}
++#include <crypto/internal/aead.h>
++#include <crypto/internal/skcipher.h>
++#include <linux/err.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/random.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
 +
-+static void get_data_to_compute(struct crypto_cipher *tfm,
-+			       struct crypto_ccm_req_priv_ctx *pctx,
-+			       struct scatterlist *sg, unsigned int len)
++struct seqiv_ctx {
++	spinlock_t lock;
++	u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
++};
++
++static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err)
 +{
-+	struct scatter_walk walk;
-+	u8 *data_src;
-+	int n;
++	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
++	struct crypto_ablkcipher *geniv;
 +
-+	scatterwalk_start(&walk, sg);
++	if (err == -EINPROGRESS)
++		return;
 +
-+	while (len) {
-+		n = scatterwalk_clamp(&walk, len);
-+		if (!n) {
-+			scatterwalk_start(&walk, sg_next(walk.sg));
-+			n = scatterwalk_clamp(&walk, len);
-+		}
-+		data_src = scatterwalk_map(&walk, 0);
++	if (err)
++		goto out;
 +
-+		compute_mac(tfm, data_src, n, pctx);
-+		len -= n;
++	geniv = skcipher_givcrypt_reqtfm(req);
++	memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv));
 +
-+		scatterwalk_unmap(data_src, 0);
-+		scatterwalk_advance(&walk, n);
-+		scatterwalk_done(&walk, 0, len);
-+		if (len)
-+			crypto_yield(pctx->flags);
-+	}
++out:
++	kfree(subreq->info);
++}
 +
-+	/* any leftover needs padding and then encrypted */
-+	if (pctx->ilen) {
-+		int padlen;
-+		u8 *odata = pctx->odata;
-+		u8 *idata = pctx->idata;
++static void seqiv_complete(struct crypto_async_request *base, int err)
++{
++	struct skcipher_givcrypt_request *req = base->data;
 +
-+		padlen = 16 - pctx->ilen;
-+		memset(idata + pctx->ilen, 0, padlen);
-+		crypto_xor(odata, idata, 16);
-+		crypto_cipher_encrypt_one(tfm, odata, odata);
-+		pctx->ilen = 0;
-+	}
++	seqiv_complete2(req, err);
++	skcipher_givcrypt_complete(req, err);
 +}
 +
-+static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
-+			   unsigned int cryptlen)
++static void seqiv_aead_complete2(struct aead_givcrypt_request *req, int err)
 +{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
-+	struct crypto_cipher *cipher = ctx->cipher;
-+	unsigned int assoclen = req->assoclen;
-+	u8 *odata = pctx->odata;
-+	u8 *idata = pctx->idata;
-+	int err;
++	struct aead_request *subreq = aead_givcrypt_reqctx(req);
++	struct crypto_aead *geniv;
++
++	if (err == -EINPROGRESS)
++		return;
 +
-+	/* format control data for input */
-+	err = format_input(odata, req, cryptlen);
 +	if (err)
 +		goto out;
 +
-+	/* encrypt first block to use as start in computing mac  */
-+	crypto_cipher_encrypt_one(cipher, odata, odata);
-+
-+	/* format associated data and compute into mac */
-+	if (assoclen) {
-+		pctx->ilen = format_adata(idata, assoclen);
-+		get_data_to_compute(cipher, pctx, req->assoc, req->assoclen);
-+	}
-+
-+	/* compute plaintext into mac */
-+	get_data_to_compute(cipher, pctx, plain, cryptlen);
++	geniv = aead_givcrypt_reqtfm(req);
++	memcpy(req->areq.iv, subreq->iv, crypto_aead_ivsize(geniv));
 +
 +out:
-+	return err;
++	kfree(subreq->iv);
 +}
 +
-+static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
++static void seqiv_aead_complete(struct crypto_async_request *base, int err)
 +{
-+	struct aead_request *req = areq->data;
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
-+	u8 *odata = pctx->odata;
++	struct aead_givcrypt_request *req = base->data;
 +
-+	if (!err)
-+		scatterwalk_map_and_copy(odata, req->dst, req->cryptlen,
-+					 crypto_aead_authsize(aead), 1);
-+	aead_request_complete(req, err);
++	seqiv_aead_complete2(req, err);
++	aead_givcrypt_complete(req, err);
 +}
 +
-+static inline int crypto_ccm_check_iv(const u8 *iv)
++static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq,
++			unsigned int ivsize)
 +{
-+	/* 2 <= L <= 8, so 1 <= L' <= 7. */
-+	if (1 > iv[0] || iv[0] > 7)
-+		return -EINVAL;
++	unsigned int len = ivsize;
 +
-+	return 0;
++	if (ivsize > sizeof(u64)) {
++		memset(info, 0, ivsize - sizeof(u64));
++		len = sizeof(u64);
++	}
++	seq = cpu_to_be64(seq);
++	memcpy(info + ivsize - len, &seq, len);
++	crypto_xor(info, ctx->salt, ivsize);
 +}
 +
-+static int crypto_ccm_encrypt(struct aead_request *req)
++static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
 +{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
-+	struct ablkcipher_request *abreq = &pctx->abreq;
-+	struct scatterlist *dst;
-+	unsigned int cryptlen = req->cryptlen;
-+	u8 *odata = pctx->odata;
-+	u8 *iv = req->iv;
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
++	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
++	crypto_completion_t complete;
++	void *data;
++	u8 *info;
++	unsigned int ivsize;
 +	int err;
 +
-+	err = crypto_ccm_check_iv(iv);
-+	if (err)
-+		return err;
-+
-+	pctx->flags = aead_request_flags(req);
++	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
 +
-+	err = crypto_ccm_auth(req, req->src, cryptlen);
-+	if (err)
-+		return err;
++	complete = req->creq.base.complete;
++	data = req->creq.base.data;
++	info = req->creq.info;
 +
-+	 /* Note: rfc 3610 and NIST 800-38C require counter of
-+	 * zero to encrypt auth tag.
-+	 */
-+	memset(iv + 15 - iv[0], 0, iv[0] + 1);
++	ivsize = crypto_ablkcipher_ivsize(geniv);
 +
-+	sg_init_table(pctx->src, 2);
-+	sg_set_buf(pctx->src, odata, 16);
-+	scatterwalk_sg_chain(pctx->src, 2, req->src);
++	if (unlikely(!IS_ALIGNED((unsigned long)info,
++				 crypto_ablkcipher_alignmask(geniv) + 1))) {
++		info = kmalloc(ivsize, req->creq.base.flags &
++				       CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
++								  GFP_ATOMIC);
++		if (!info)
++			return -ENOMEM;
 +
-+	dst = pctx->src;
-+	if (req->src != req->dst) {
-+		sg_init_table(pctx->dst, 2);
-+		sg_set_buf(pctx->dst, odata, 16);
-+		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
-+		dst = pctx->dst;
++		complete = seqiv_complete;
++		data = req;
 +	}
 +
-+	ablkcipher_request_set_tfm(abreq, ctx->ctr);
-+	ablkcipher_request_set_callback(abreq, pctx->flags,
-+					crypto_ccm_encrypt_done, req);
-+	ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
-+	err = crypto_ablkcipher_encrypt(abreq);
-+	if (err)
-+		return err;
++	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
++					data);
++	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
++				     req->creq.nbytes, info);
 +
-+	/* copy authtag to end of dst */
-+	scatterwalk_map_and_copy(odata, req->dst, cryptlen,
-+				 crypto_aead_authsize(aead), 1);
++	seqiv_geniv(ctx, info, req->seq, ivsize);
++	memcpy(req->giv, info, ivsize);
++
++	err = crypto_ablkcipher_encrypt(subreq);
++	if (unlikely(info != req->creq.info))
++		seqiv_complete2(req, err);
 +	return err;
 +}
 +
-+static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
-+				   int err)
++static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
 +{
-+	struct aead_request *req = areq->data;
-+	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	unsigned int authsize = crypto_aead_authsize(aead);
-+	unsigned int cryptlen = req->cryptlen - authsize;
++	struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
++	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
++	struct aead_request *areq = &req->areq;
++	struct aead_request *subreq = aead_givcrypt_reqctx(req);
++	crypto_completion_t complete;
++	void *data;
++	u8 *info;
++	unsigned int ivsize;
++	int err;
 +
-+	if (!err) {
-+		err = crypto_ccm_auth(req, req->dst, cryptlen);
-+		if (!err && memcmp(pctx->auth_tag, pctx->odata, authsize))
-+			err = -EBADMSG;
++	aead_request_set_tfm(subreq, aead_geniv_base(geniv));
++
++	complete = areq->base.complete;
++	data = areq->base.data;
++	info = areq->iv;
++
++	ivsize = crypto_aead_ivsize(geniv);
++
++	if (unlikely(!IS_ALIGNED((unsigned long)info,
++				 crypto_aead_alignmask(geniv) + 1))) {
++		info = kmalloc(ivsize, areq->base.flags &
++				       CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
++								  GFP_ATOMIC);
++		if (!info)
++			return -ENOMEM;
++
++		complete = seqiv_aead_complete;
++		data = req;
 +	}
-+	aead_request_complete(req, err);
++
++	aead_request_set_callback(subreq, areq->base.flags, complete, data);
++	aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
++			       info);
++	aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
++
++	seqiv_geniv(ctx, info, req->seq, ivsize);
++	memcpy(req->giv, info, ivsize);
++
++	err = crypto_aead_encrypt(subreq);
++	if (unlikely(info != areq->iv))
++		seqiv_aead_complete2(req, err);
++	return err;
 +}
 +
-+static int crypto_ccm_decrypt(struct aead_request *req)
++static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
 +{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
-+	struct ablkcipher_request *abreq = &pctx->abreq;
-+	struct scatterlist *dst;
-+	unsigned int authsize = crypto_aead_authsize(aead);
-+	unsigned int cryptlen = req->cryptlen;
-+	u8 *authtag = pctx->auth_tag;
-+	u8 *odata = pctx->odata;
-+	u8 *iv = req->iv;
-+	int err;
++	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
++	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
 +
-+	if (cryptlen < authsize)
-+		return -EINVAL;
-+	cryptlen -= authsize;
++	spin_lock_bh(&ctx->lock);
++	if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first)
++		goto unlock;
 +
-+	err = crypto_ccm_check_iv(iv);
-+	if (err)
-+		return err;
++	crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt;
++	get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
 +
-+	pctx->flags = aead_request_flags(req);
++unlock:
++	spin_unlock_bh(&ctx->lock);
 +
-+	scatterwalk_map_and_copy(authtag, req->src, cryptlen, authsize, 0);
++	return seqiv_givencrypt(req);
++}
 +
-+	memset(iv + 15 - iv[0], 0, iv[0] + 1);
++static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req)
++{
++	struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
++	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
 +
-+	sg_init_table(pctx->src, 2);
-+	sg_set_buf(pctx->src, authtag, 16);
-+	scatterwalk_sg_chain(pctx->src, 2, req->src);
++	spin_lock_bh(&ctx->lock);
++	if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first)
++		goto unlock;
 +
-+	dst = pctx->src;
-+	if (req->src != req->dst) {
-+		sg_init_table(pctx->dst, 2);
-+		sg_set_buf(pctx->dst, authtag, 16);
-+		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
-+		dst = pctx->dst;
-+	}
++	crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt;
++	get_random_bytes(ctx->salt, crypto_aead_ivsize(geniv));
 +
-+	ablkcipher_request_set_tfm(abreq, ctx->ctr);
-+	ablkcipher_request_set_callback(abreq, pctx->flags,
-+					crypto_ccm_decrypt_done, req);
-+	ablkcipher_request_set_crypt(abreq, pctx->src, dst, cryptlen + 16, iv);
-+	err = crypto_ablkcipher_decrypt(abreq);
-+	if (err)
-+		return err;
++unlock:
++	spin_unlock_bh(&ctx->lock);
 +
-+	err = crypto_ccm_auth(req, req->dst, cryptlen);
-+	if (err)
-+		return err;
++	return seqiv_aead_givencrypt(req);
++}
 +
-+	/* verify */
-+	if (memcmp(authtag, odata, authsize))
-+		return -EBADMSG;
++static int seqiv_init(struct crypto_tfm *tfm)
++{
++	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
++	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
 +
-+	return err;
++	spin_lock_init(&ctx->lock);
++
++	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
++
++	return skcipher_geniv_init(tfm);
 +}
 +
-+static int crypto_ccm_init_tfm(struct crypto_tfm *tfm)
++static int seqiv_aead_init(struct crypto_tfm *tfm)
 +{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct ccm_instance_ctx *ictx = crypto_instance_ctx(inst);
-+	struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_cipher *cipher;
-+	struct crypto_ablkcipher *ctr;
-+	unsigned long align;
-+	int err;
++	struct crypto_aead *geniv = __crypto_aead_cast(tfm);
++	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
 +
-+	cipher = crypto_spawn_cipher(&ictx->cipher);
-+	if (IS_ERR(cipher))
-+		return PTR_ERR(cipher);
++	spin_lock_init(&ctx->lock);
 +
-+	ctr = crypto_spawn_skcipher(&ictx->ctr);
-+	err = PTR_ERR(ctr);
-+	if (IS_ERR(ctr))
-+		goto err_free_cipher;
++	tfm->crt_aead.reqsize = sizeof(struct aead_request);
 +
-+	ctx->cipher = cipher;
-+	ctx->ctr = ctr;
++	return aead_geniv_init(tfm);
++}
 +
-+	align = crypto_tfm_alg_alignmask(tfm);
-+	align &= ~(crypto_tfm_ctx_alignment() - 1);
-+	tfm->crt_aead.reqsize = align +
-+				sizeof(struct crypto_ccm_req_priv_ctx) +
-+				crypto_ablkcipher_reqsize(ctr);
++static struct crypto_template seqiv_tmpl;
 +
-+	return 0;
++static struct crypto_instance *seqiv_ablkcipher_alloc(struct rtattr **tb)
++{
++	struct crypto_instance *inst;
 +
-+err_free_cipher:
-+	crypto_free_cipher(cipher);
-+	return err;
++	inst = skcipher_geniv_alloc(&seqiv_tmpl, tb, 0, 0);
++
++	if (IS_ERR(inst))
++		goto out;
++
++	inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt_first;
++
++	inst->alg.cra_init = seqiv_init;
++	inst->alg.cra_exit = skcipher_geniv_exit;
++
++	inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
++
++out:
++	return inst;
 +}
 +
-+static void crypto_ccm_exit_tfm(struct crypto_tfm *tfm)
++static struct crypto_instance *seqiv_aead_alloc(struct rtattr **tb)
 +{
-+	struct crypto_ccm_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct crypto_instance *inst;
 +
-+	crypto_free_cipher(ctx->cipher);
-+	crypto_free_ablkcipher(ctx->ctr);
++	inst = aead_geniv_alloc(&seqiv_tmpl, tb, 0, 0);
++
++	if (IS_ERR(inst))
++		goto out;
++
++	inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt_first;
++
++	inst->alg.cra_init = seqiv_aead_init;
++	inst->alg.cra_exit = aead_geniv_exit;
++
++	inst->alg.cra_ctxsize = inst->alg.cra_aead.ivsize;
++
++out:
++	return inst;
 +}
 +
-+static struct crypto_instance *crypto_ccm_alloc_common(struct rtattr **tb,
-+						       const char *full_name,
-+						       const char *ctr_name,
-+						       const char *cipher_name)
++static struct crypto_instance *seqiv_alloc(struct rtattr **tb)
 +{
 +	struct crypto_attr_type *algt;
 +	struct crypto_instance *inst;
-+	struct crypto_alg *ctr;
-+	struct crypto_alg *cipher;
-+	struct ccm_instance_ctx *ictx;
 +	int err;
 +
 +	algt = crypto_get_attr_type(tb);
@@ -356076,72498 +385057,94634 @@
 +	if (IS_ERR(algt))
 +		return ERR_PTR(err);
 +
-+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-+		return ERR_PTR(-EINVAL);
++	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
++		inst = seqiv_ablkcipher_alloc(tb);
++	else
++		inst = seqiv_aead_alloc(tb);
 +
-+	cipher = crypto_alg_mod_lookup(cipher_name,  CRYPTO_ALG_TYPE_CIPHER,
-+				       CRYPTO_ALG_TYPE_MASK);
-+	err = PTR_ERR(cipher);
-+	if (IS_ERR(cipher))
-+		return ERR_PTR(err);
++	if (IS_ERR(inst))
++		goto out;
 +
-+	err = -EINVAL;
-+	if (cipher->cra_blocksize != 16)
-+		goto out_put_cipher;
++	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
++	inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
 +
-+	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
-+	err = -ENOMEM;
-+	if (!inst)
-+		goto out_put_cipher;
++out:
++	return inst;
++}
 +
-+	ictx = crypto_instance_ctx(inst);
++static void seqiv_free(struct crypto_instance *inst)
++{
++	if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
++		skcipher_geniv_free(inst);
++	else
++		aead_geniv_free(inst);
++}
 +
-+	err = crypto_init_spawn(&ictx->cipher, cipher, inst,
-+				CRYPTO_ALG_TYPE_MASK);
-+	if (err)
-+		goto err_free_inst;
++static struct crypto_template seqiv_tmpl = {
++	.name = "seqiv",
++	.alloc = seqiv_alloc,
++	.free = seqiv_free,
++	.module = THIS_MODULE,
++};
 +
-+	crypto_set_skcipher_spawn(&ictx->ctr, inst);
-+	err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
-+				   crypto_requires_sync(algt->type,
-+							algt->mask));
-+	if (err)
-+		goto err_drop_cipher;
++static int __init seqiv_module_init(void)
++{
++	return crypto_register_template(&seqiv_tmpl);
++}
++
++static void __exit seqiv_module_exit(void)
++{
++	crypto_unregister_template(&seqiv_tmpl);
++}
++
++module_init(seqiv_module_init);
++module_exit(seqiv_module_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Sequence Number IV Generator");
+diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
+index fd3918b..3cc93fd 100644
+--- a/crypto/sha256_generic.c
++++ b/crypto/sha256_generic.c
+@@ -9,6 +9,7 @@
+  * Copyright (c) Jean-Luc Cooke <jlcooke at certainkey.com>
+  * Copyright (c) Andrew McDonald <andrew at mcdonald.org.uk>
+  * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
++ * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch at intel.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
+@@ -218,6 +219,22 @@ static void sha256_transform(u32 *state, const u8 *input)
+ 	memset(W, 0, 64 * sizeof(u32));
+ }
+ 
++
++static void sha224_init(struct crypto_tfm *tfm)
++{
++	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
++	sctx->state[0] = SHA224_H0;
++	sctx->state[1] = SHA224_H1;
++	sctx->state[2] = SHA224_H2;
++	sctx->state[3] = SHA224_H3;
++	sctx->state[4] = SHA224_H4;
++	sctx->state[5] = SHA224_H5;
++	sctx->state[6] = SHA224_H6;
++	sctx->state[7] = SHA224_H7;
++	sctx->count[0] = 0;
++	sctx->count[1] = 0;
++}
++
+ static void sha256_init(struct crypto_tfm *tfm)
+ {
+ 	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
+@@ -294,8 +311,17 @@ static void sha256_final(struct crypto_tfm *tfm, u8 *out)
+ 	memset(sctx, 0, sizeof(*sctx));
+ }
+ 
++static void sha224_final(struct crypto_tfm *tfm, u8 *hash)
++{
++	u8 D[SHA256_DIGEST_SIZE];
++
++	sha256_final(tfm, D);
++
++	memcpy(hash, D, SHA224_DIGEST_SIZE);
++	memset(D, 0, SHA256_DIGEST_SIZE);
++}
+ 
+-static struct crypto_alg alg = {
++static struct crypto_alg sha256 = {
+ 	.cra_name	=	"sha256",
+ 	.cra_driver_name=	"sha256-generic",
+ 	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+@@ -303,28 +329,58 @@ static struct crypto_alg alg = {
+ 	.cra_ctxsize	=	sizeof(struct sha256_ctx),
+ 	.cra_module	=	THIS_MODULE,
+ 	.cra_alignmask	=	3,
+-	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),
++	.cra_list	=	LIST_HEAD_INIT(sha256.cra_list),
+ 	.cra_u		=	{ .digest = {
+ 	.dia_digestsize	=	SHA256_DIGEST_SIZE,
+-	.dia_init   	= 	sha256_init,
+-	.dia_update 	=	sha256_update,
+-	.dia_final  	=	sha256_final } }
++	.dia_init	=	sha256_init,
++	.dia_update	=	sha256_update,
++	.dia_final	=	sha256_final } }
++};
++
++static struct crypto_alg sha224 = {
++	.cra_name	= "sha224",
++	.cra_driver_name = "sha224-generic",
++	.cra_flags	= CRYPTO_ALG_TYPE_DIGEST,
++	.cra_blocksize	= SHA224_BLOCK_SIZE,
++	.cra_ctxsize	= sizeof(struct sha256_ctx),
++	.cra_module	= THIS_MODULE,
++	.cra_alignmask	= 3,
++	.cra_list	= LIST_HEAD_INIT(sha224.cra_list),
++	.cra_u		= { .digest = {
++	.dia_digestsize = SHA224_DIGEST_SIZE,
++	.dia_init	= sha224_init,
++	.dia_update	= sha256_update,
++	.dia_final	= sha224_final } }
+ };
+ 
+ static int __init init(void)
+ {
+-	return crypto_register_alg(&alg);
++	int ret = 0;
++
++	ret = crypto_register_alg(&sha224);
++
++	if (ret < 0)
++		return ret;
++
++	ret = crypto_register_alg(&sha256);
++
++	if (ret < 0)
++		crypto_unregister_alg(&sha224);
++
++	return ret;
+ }
+ 
+ static void __exit fini(void)
+ {
+-	crypto_unregister_alg(&alg);
++	crypto_unregister_alg(&sha224);
++	crypto_unregister_alg(&sha256);
+ }
+ 
+ module_init(init);
+ module_exit(fini);
+ 
+ MODULE_LICENSE("GPL");
+-MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
++MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm");
+ 
++MODULE_ALIAS("sha224");
+ MODULE_ALIAS("sha256");
+diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
+index 24141fb..1ab8c01 100644
+--- a/crypto/tcrypt.c
++++ b/crypto/tcrypt.c
+@@ -6,12 +6,16 @@
+  *
+  * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
+  * Copyright (c) 2002 Jean-Francois Dive <jef at linuxbe.org>
++ * Copyright (c) 2007 Nokia Siemens Networks
+  *
+  * 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.
+  *
++ * 2007-11-13 Added GCM tests
++ * 2007-11-13 Added AEAD support
++ * 2007-11-06 Added SHA-224 and SHA-224-HMAC tests
+  * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
+  * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk at vantronix.net>)
+  * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
+@@ -71,22 +75,23 @@ static unsigned int sec;
+ 
+ static int mode;
+ static char *xbuf;
++static char *axbuf;
+ static char *tvmem;
+ 
+ static char *check[] = {
+-	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
+-	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
++	"des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
++	"blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
++	"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+ 	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+ 	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
+-	"camellia", "seed", NULL
++	"camellia", "seed", "salsa20", "lzo", NULL
+ };
+ 
+ static void hexdump(unsigned char *buf, unsigned int len)
+ {
+-	while (len--)
+-		printk("%02x", *buf++);
+-
+-	printk("\n");
++	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
++			16, 1,
++			buf, len, false);
+ }
+ 
+ static void tcrypt_complete(struct crypto_async_request *req, int err)
+@@ -215,6 +220,238 @@ out:
+ 	crypto_free_hash(tfm);
+ }
+ 
++static void test_aead(char *algo, int enc, struct aead_testvec *template,
++		      unsigned int tcount)
++{
++	unsigned int ret, i, j, k, temp;
++	unsigned int tsize;
++	char *q;
++	struct crypto_aead *tfm;
++	char *key;
++	struct aead_testvec *aead_tv;
++	struct aead_request *req;
++	struct scatterlist sg[8];
++	struct scatterlist asg[8];
++	const char *e;
++	struct tcrypt_result result;
++	unsigned int authsize;
++
++	if (enc == ENCRYPT)
++		e = "encryption";
++	else
++		e = "decryption";
++
++	printk(KERN_INFO "\ntesting %s %s\n", algo, e);
++
++	tsize = sizeof(struct aead_testvec);
++	tsize *= tcount;
++
++	if (tsize > TVMEMSIZE) {
++		printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
++		       tsize, TVMEMSIZE);
++		return;
++	}
++
++	memcpy(tvmem, template, tsize);
++	aead_tv = (void *)tvmem;
++
++	init_completion(&result.completion);
++
++	tfm = crypto_alloc_aead(algo, 0, 0);
++
++	if (IS_ERR(tfm)) {
++		printk(KERN_INFO "failed to load transform for %s: %ld\n",
++		       algo, PTR_ERR(tfm));
++		return;
++	}
++
++	req = aead_request_alloc(tfm, GFP_KERNEL);
++	if (!req) {
++		printk(KERN_INFO "failed to allocate request for %s\n", algo);
++		goto out;
++	}
++
++	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
++				  tcrypt_complete, &result);
++
++	for (i = 0, j = 0; i < tcount; i++) {
++		if (!aead_tv[i].np) {
++			printk(KERN_INFO "test %u (%d bit key):\n",
++			       ++j, aead_tv[i].klen * 8);
++
++			crypto_aead_clear_flags(tfm, ~0);
++			if (aead_tv[i].wk)
++				crypto_aead_set_flags(
++					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
++			key = aead_tv[i].key;
++
++			ret = crypto_aead_setkey(tfm, key,
++						 aead_tv[i].klen);
++			if (ret) {
++				printk(KERN_INFO "setkey() failed flags=%x\n",
++				       crypto_aead_get_flags(tfm));
++
++				if (!aead_tv[i].fail)
++					goto out;
++			}
++
++			authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
++			ret = crypto_aead_setauthsize(tfm, authsize);
++			if (ret) {
++				printk(KERN_INFO
++				       "failed to set authsize = %u\n",
++				       authsize);
++				goto out;
++			}
++
++			sg_init_one(&sg[0], aead_tv[i].input,
++				    aead_tv[i].ilen + (enc ? authsize : 0));
++
++			sg_init_one(&asg[0], aead_tv[i].assoc,
++				    aead_tv[i].alen);
++
++			aead_request_set_crypt(req, sg, sg,
++					       aead_tv[i].ilen,
++					       aead_tv[i].iv);
++
++			aead_request_set_assoc(req, asg, aead_tv[i].alen);
++
++			ret = enc ?
++				crypto_aead_encrypt(req) :
++				crypto_aead_decrypt(req);
++
++			switch (ret) {
++			case 0:
++				break;
++			case -EINPROGRESS:
++			case -EBUSY:
++				ret = wait_for_completion_interruptible(
++					&result.completion);
++				if (!ret && !(ret = result.err)) {
++					INIT_COMPLETION(result.completion);
++					break;
++				}
++				/* fall through */
++			default:
++				printk(KERN_INFO "%s () failed err=%d\n",
++				       e, -ret);
++				goto out;
++			}
++
++			q = kmap(sg_page(&sg[0])) + sg[0].offset;
++			hexdump(q, aead_tv[i].rlen);
++
++			printk(KERN_INFO "enc/dec: %s\n",
++			       memcmp(q, aead_tv[i].result,
++				      aead_tv[i].rlen) ? "fail" : "pass");
++		}
++	}
++
++	printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e);
++	memset(xbuf, 0, XBUFSIZE);
++	memset(axbuf, 0, XBUFSIZE);
++
++	for (i = 0, j = 0; i < tcount; i++) {
++		if (aead_tv[i].np) {
++			printk(KERN_INFO "test %u (%d bit key):\n",
++			       ++j, aead_tv[i].klen * 8);
++
++			crypto_aead_clear_flags(tfm, ~0);
++			if (aead_tv[i].wk)
++				crypto_aead_set_flags(
++					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
++			key = aead_tv[i].key;
++
++			ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
++			if (ret) {
++				printk(KERN_INFO "setkey() failed flags=%x\n",
++				       crypto_aead_get_flags(tfm));
++
++				if (!aead_tv[i].fail)
++					goto out;
++			}
++
++			sg_init_table(sg, aead_tv[i].np);
++			for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
++				memcpy(&xbuf[IDX[k]],
++				       aead_tv[i].input + temp,
++				       aead_tv[i].tap[k]);
++				temp += aead_tv[i].tap[k];
++				sg_set_buf(&sg[k], &xbuf[IDX[k]],
++					   aead_tv[i].tap[k]);
++			}
++
++			authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
++			ret = crypto_aead_setauthsize(tfm, authsize);
++			if (ret) {
++				printk(KERN_INFO
++				       "failed to set authsize = %u\n",
++				       authsize);
++				goto out;
++			}
++
++			if (enc)
++				sg[k - 1].length += authsize;
++
++			sg_init_table(asg, aead_tv[i].anp);
++			for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
++				memcpy(&axbuf[IDX[k]],
++				       aead_tv[i].assoc + temp,
++				       aead_tv[i].atap[k]);
++				temp += aead_tv[i].atap[k];
++				sg_set_buf(&asg[k], &axbuf[IDX[k]],
++					   aead_tv[i].atap[k]);
++			}
++
++			aead_request_set_crypt(req, sg, sg,
++					       aead_tv[i].ilen,
++					       aead_tv[i].iv);
++
++			aead_request_set_assoc(req, asg, aead_tv[i].alen);
++
++			ret = enc ?
++				crypto_aead_encrypt(req) :
++				crypto_aead_decrypt(req);
++
++			switch (ret) {
++			case 0:
++				break;
++			case -EINPROGRESS:
++			case -EBUSY:
++				ret = wait_for_completion_interruptible(
++					&result.completion);
++				if (!ret && !(ret = result.err)) {
++					INIT_COMPLETION(result.completion);
++					break;
++				}
++				/* fall through */
++			default:
++				printk(KERN_INFO "%s () failed err=%d\n",
++				       e, -ret);
++				goto out;
++			}
++
++			for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
++				printk(KERN_INFO "page %u\n", k);
++				q = kmap(sg_page(&sg[k])) + sg[k].offset;
++				hexdump(q, aead_tv[i].tap[k]);
++				printk(KERN_INFO "%s\n",
++				       memcmp(q, aead_tv[i].result + temp,
++					      aead_tv[i].tap[k] -
++					      (k < aead_tv[i].np - 1 || enc ?
++					       0 : authsize)) ?
++				       "fail" : "pass");
++
++				temp += aead_tv[i].tap[k];
++			}
++		}
++	}
 +
-+	ctr = crypto_skcipher_spawn_alg(&ictx->ctr);
++out:
++	crypto_free_aead(tfm);
++	aead_request_free(req);
++}
 +
-+	/* Not a stream cipher? */
-+	err = -EINVAL;
-+	if (ctr->cra_blocksize != 1)
-+		goto err_drop_ctr;
+ static void test_cipher(char *algo, int enc,
+ 			struct cipher_testvec *template, unsigned int tcount)
+ {
+@@ -237,15 +474,11 @@ static void test_cipher(char *algo, int enc,
+ 	printk("\ntesting %s %s\n", algo, e);
+ 
+ 	tsize = sizeof (struct cipher_testvec);
+-	tsize *= tcount;
+-
+ 	if (tsize > TVMEMSIZE) {
+ 		printk("template (%u) too big for tvmem (%u)\n", tsize,
+ 		       TVMEMSIZE);
+ 		return;
+ 	}
+-
+-	memcpy(tvmem, template, tsize);
+ 	cipher_tv = (void *)tvmem;
+ 
+ 	init_completion(&result.completion);
+@@ -269,33 +502,34 @@ static void test_cipher(char *algo, int enc,
+ 
+ 	j = 0;
+ 	for (i = 0; i < tcount; i++) {
+-		if (!(cipher_tv[i].np)) {
++		memcpy(cipher_tv, &template[i], tsize);
++		if (!(cipher_tv->np)) {
+ 			j++;
+ 			printk("test %u (%d bit key):\n",
+-			j, cipher_tv[i].klen * 8);
++			j, cipher_tv->klen * 8);
+ 
+ 			crypto_ablkcipher_clear_flags(tfm, ~0);
+-			if (cipher_tv[i].wk)
++			if (cipher_tv->wk)
+ 				crypto_ablkcipher_set_flags(
+ 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-			key = cipher_tv[i].key;
++			key = cipher_tv->key;
+ 
+ 			ret = crypto_ablkcipher_setkey(tfm, key,
+-						       cipher_tv[i].klen);
++						       cipher_tv->klen);
+ 			if (ret) {
+ 				printk("setkey() failed flags=%x\n",
+ 				       crypto_ablkcipher_get_flags(tfm));
+ 
+-				if (!cipher_tv[i].fail)
++				if (!cipher_tv->fail)
+ 					goto out;
+ 			}
+ 
+-			sg_init_one(&sg[0], cipher_tv[i].input,
+-				    cipher_tv[i].ilen);
++			sg_init_one(&sg[0], cipher_tv->input,
++				    cipher_tv->ilen);
+ 
+ 			ablkcipher_request_set_crypt(req, sg, sg,
+-						     cipher_tv[i].ilen,
+-						     cipher_tv[i].iv);
++						     cipher_tv->ilen,
++						     cipher_tv->iv);
+ 
+ 			ret = enc ?
+ 				crypto_ablkcipher_encrypt(req) :
+@@ -319,11 +553,11 @@ static void test_cipher(char *algo, int enc,
+ 			}
+ 
+ 			q = kmap(sg_page(&sg[0])) + sg[0].offset;
+-			hexdump(q, cipher_tv[i].rlen);
++			hexdump(q, cipher_tv->rlen);
+ 
+ 			printk("%s\n",
+-			       memcmp(q, cipher_tv[i].result,
+-				      cipher_tv[i].rlen) ? "fail" : "pass");
++			       memcmp(q, cipher_tv->result,
++				      cipher_tv->rlen) ? "fail" : "pass");
+ 		}
+ 	}
+ 
+@@ -332,41 +566,42 @@ static void test_cipher(char *algo, int enc,
+ 
+ 	j = 0;
+ 	for (i = 0; i < tcount; i++) {
+-		if (cipher_tv[i].np) {
++		memcpy(cipher_tv, &template[i], tsize);
++		if (cipher_tv->np) {
+ 			j++;
+ 			printk("test %u (%d bit key):\n",
+-			j, cipher_tv[i].klen * 8);
++			j, cipher_tv->klen * 8);
+ 
+ 			crypto_ablkcipher_clear_flags(tfm, ~0);
+-			if (cipher_tv[i].wk)
++			if (cipher_tv->wk)
+ 				crypto_ablkcipher_set_flags(
+ 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
+-			key = cipher_tv[i].key;
++			key = cipher_tv->key;
+ 
+ 			ret = crypto_ablkcipher_setkey(tfm, key,
+-						       cipher_tv[i].klen);
++						       cipher_tv->klen);
+ 			if (ret) {
+ 				printk("setkey() failed flags=%x\n",
+ 				       crypto_ablkcipher_get_flags(tfm));
+ 
+-				if (!cipher_tv[i].fail)
++				if (!cipher_tv->fail)
+ 					goto out;
+ 			}
+ 
+ 			temp = 0;
+-			sg_init_table(sg, cipher_tv[i].np);
+-			for (k = 0; k < cipher_tv[i].np; k++) {
++			sg_init_table(sg, cipher_tv->np);
++			for (k = 0; k < cipher_tv->np; k++) {
+ 				memcpy(&xbuf[IDX[k]],
+-				       cipher_tv[i].input + temp,
+-				       cipher_tv[i].tap[k]);
+-				temp += cipher_tv[i].tap[k];
++				       cipher_tv->input + temp,
++				       cipher_tv->tap[k]);
++				temp += cipher_tv->tap[k];
+ 				sg_set_buf(&sg[k], &xbuf[IDX[k]],
+-					   cipher_tv[i].tap[k]);
++					   cipher_tv->tap[k]);
+ 			}
+ 
+ 			ablkcipher_request_set_crypt(req, sg, sg,
+-						     cipher_tv[i].ilen,
+-						     cipher_tv[i].iv);
++						     cipher_tv->ilen,
++						     cipher_tv->iv);
+ 
+ 			ret = enc ?
+ 				crypto_ablkcipher_encrypt(req) :
+@@ -390,15 +625,15 @@ static void test_cipher(char *algo, int enc,
+ 			}
+ 
+ 			temp = 0;
+-			for (k = 0; k < cipher_tv[i].np; k++) {
++			for (k = 0; k < cipher_tv->np; k++) {
+ 				printk("page %u\n", k);
+ 				q = kmap(sg_page(&sg[k])) + sg[k].offset;
+-				hexdump(q, cipher_tv[i].tap[k]);
++				hexdump(q, cipher_tv->tap[k]);
+ 				printk("%s\n",
+-					memcmp(q, cipher_tv[i].result + temp,
+-						cipher_tv[i].tap[k]) ? "fail" :
++					memcmp(q, cipher_tv->result + temp,
++						cipher_tv->tap[k]) ? "fail" :
+ 					"pass");
+-				temp += cipher_tv[i].tap[k];
++				temp += cipher_tv->tap[k];
+ 			}
+ 		}
+ 	}
+@@ -800,7 +1035,8 @@ out:
+ 	crypto_free_hash(tfm);
+ }
+ 
+-static void test_deflate(void)
++static void test_comp(char *algo, struct comp_testvec *ctemplate,
++		       struct comp_testvec *dtemplate, int ctcount, int dtcount)
+ {
+ 	unsigned int i;
+ 	char result[COMP_BUF_SIZE];
+@@ -808,25 +1044,26 @@ static void test_deflate(void)
+ 	struct comp_testvec *tv;
+ 	unsigned int tsize;
+ 
+-	printk("\ntesting deflate compression\n");
++	printk("\ntesting %s compression\n", algo);
+ 
+-	tsize = sizeof (deflate_comp_tv_template);
++	tsize = sizeof(struct comp_testvec);
++	tsize *= ctcount;
+ 	if (tsize > TVMEMSIZE) {
+ 		printk("template (%u) too big for tvmem (%u)\n", tsize,
+ 		       TVMEMSIZE);
+ 		return;
+ 	}
+ 
+-	memcpy(tvmem, deflate_comp_tv_template, tsize);
++	memcpy(tvmem, ctemplate, tsize);
+ 	tv = (void *)tvmem;
+ 
+-	tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
++	tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC);
+ 	if (IS_ERR(tfm)) {
+-		printk("failed to load transform for deflate\n");
++		printk("failed to load transform for %s\n", algo);
+ 		return;
+ 	}
+ 
+-	for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) {
++	for (i = 0; i < ctcount; i++) {
+ 		int ilen, ret, dlen = COMP_BUF_SIZE;
+ 
+ 		printk("test %u:\n", i + 1);
+@@ -845,19 +1082,20 @@ static void test_deflate(void)
+ 		       ilen, dlen);
+ 	}
+ 
+-	printk("\ntesting deflate decompression\n");
++	printk("\ntesting %s decompression\n", algo);
+ 
+-	tsize = sizeof (deflate_decomp_tv_template);
++	tsize = sizeof(struct comp_testvec);
++	tsize *= dtcount;
+ 	if (tsize > TVMEMSIZE) {
+ 		printk("template (%u) too big for tvmem (%u)\n", tsize,
+ 		       TVMEMSIZE);
+ 		goto out;
+ 	}
+ 
+-	memcpy(tvmem, deflate_decomp_tv_template, tsize);
++	memcpy(tvmem, dtemplate, tsize);
+ 	tv = (void *)tvmem;
+ 
+-	for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
++	for (i = 0; i < dtcount; i++) {
+ 		int ilen, ret, dlen = COMP_BUF_SIZE;
+ 
+ 		printk("test %u:\n", i + 1);
+@@ -918,6 +1156,8 @@ static void do_test(void)
+ 
+ 		test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
+ 
++		test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
 +
-+	/* We want the real thing! */
-+	if (ctr->cra_ablkcipher.ivsize != 16)
-+		goto err_drop_ctr;
+ 		test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
+ 
+ 		//BLOWFISH
+@@ -969,6 +1209,18 @@ static void do_test(void)
+ 			    AES_XTS_ENC_TEST_VECTORS);
+ 		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
+ 			    AES_XTS_DEC_TEST_VECTORS);
++		test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template,
++			    AES_CTR_ENC_TEST_VECTORS);
++		test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template,
++			    AES_CTR_DEC_TEST_VECTORS);
++		test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template,
++			  AES_GCM_ENC_TEST_VECTORS);
++		test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template,
++			  AES_GCM_DEC_TEST_VECTORS);
++		test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template,
++			  AES_CCM_ENC_TEST_VECTORS);
++		test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template,
++			  AES_CCM_DEC_TEST_VECTORS);
+ 
+ 		//CAST5
+ 		test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
+@@ -1057,12 +1309,18 @@ static void do_test(void)
+ 		test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
+ 		test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
+ 		test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
+-		test_deflate();
++		test_comp("deflate", deflate_comp_tv_template,
++			  deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS,
++			  DEFLATE_DECOMP_TEST_VECTORS);
++		test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template,
++			  LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS);
+ 		test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS);
+ 		test_hash("hmac(md5)", hmac_md5_tv_template,
+ 			  HMAC_MD5_TEST_VECTORS);
+ 		test_hash("hmac(sha1)", hmac_sha1_tv_template,
+ 			  HMAC_SHA1_TEST_VECTORS);
++		test_hash("hmac(sha224)", hmac_sha224_tv_template,
++			  HMAC_SHA224_TEST_VECTORS);
+ 		test_hash("hmac(sha256)", hmac_sha256_tv_template,
+ 			  HMAC_SHA256_TEST_VECTORS);
+ 		test_hash("hmac(sha384)", hmac_sha384_tv_template,
+@@ -1156,6 +1414,10 @@ static void do_test(void)
+ 			    AES_XTS_ENC_TEST_VECTORS);
+ 		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
+ 			    AES_XTS_DEC_TEST_VECTORS);
++		test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template,
++			    AES_CTR_ENC_TEST_VECTORS);
++		test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template,
++			    AES_CTR_DEC_TEST_VECTORS);
+ 		break;
+ 
+ 	case 11:
+@@ -1167,7 +1429,9 @@ static void do_test(void)
+ 		break;
+ 
+ 	case 13:
+-		test_deflate();
++		test_comp("deflate", deflate_comp_tv_template,
++			  deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS,
++			  DEFLATE_DECOMP_TEST_VECTORS);
+ 		break;
+ 
+ 	case 14:
+@@ -1291,6 +1555,34 @@ static void do_test(void)
+ 			    camellia_cbc_dec_tv_template,
+ 			    CAMELLIA_CBC_DEC_TEST_VECTORS);
+ 		break;
++	case 33:
++		test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
++		break;
 +
-+	err = -ENAMETOOLONG;
-+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+		     "ccm_base(%s,%s)", ctr->cra_driver_name,
-+		     cipher->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
-+		goto err_drop_ctr;
++	case 34:
++		test_cipher("salsa20", ENCRYPT,
++			    salsa20_stream_enc_tv_template,
++			    SALSA20_STREAM_ENC_TEST_VECTORS);
++		break;
 +
-+	memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
++	case 35:
++		test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template,
++			  AES_GCM_ENC_TEST_VECTORS);
++		test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template,
++			  AES_GCM_DEC_TEST_VECTORS);
++		break;
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-+	inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_priority = cipher->cra_priority + ctr->cra_priority;
-+	inst->alg.cra_blocksize = 1;
-+	inst->alg.cra_alignmask = cipher->cra_alignmask | ctr->cra_alignmask |
-+				  (__alignof__(u32) - 1);
-+	inst->alg.cra_type = &crypto_aead_type;
-+	inst->alg.cra_aead.ivsize = 16;
-+	inst->alg.cra_aead.maxauthsize = 16;
-+	inst->alg.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
-+	inst->alg.cra_init = crypto_ccm_init_tfm;
-+	inst->alg.cra_exit = crypto_ccm_exit_tfm;
-+	inst->alg.cra_aead.setkey = crypto_ccm_setkey;
-+	inst->alg.cra_aead.setauthsize = crypto_ccm_setauthsize;
-+	inst->alg.cra_aead.encrypt = crypto_ccm_encrypt;
-+	inst->alg.cra_aead.decrypt = crypto_ccm_decrypt;
++	case 36:
++		test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template,
++			  LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS);
++		break;
 +
-+out:
-+	crypto_mod_put(cipher);
-+	return inst;
++	case 37:
++		test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template,
++			  AES_CCM_ENC_TEST_VECTORS);
++		test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template,
++			  AES_CCM_DEC_TEST_VECTORS);
++		break;
+ 
+ 	case 100:
+ 		test_hash("hmac(md5)", hmac_md5_tv_template,
+@@ -1317,6 +1609,15 @@ static void do_test(void)
+ 			  HMAC_SHA512_TEST_VECTORS);
+ 		break;
+ 
++	case 105:
++		test_hash("hmac(sha224)", hmac_sha224_tv_template,
++			  HMAC_SHA224_TEST_VECTORS);
++		break;
 +
-+err_drop_ctr:
-+	crypto_drop_skcipher(&ictx->ctr);
-+err_drop_cipher:
-+	crypto_drop_spawn(&ictx->cipher);
-+err_free_inst:
-+	kfree(inst);
-+out_put_cipher:
-+	inst = ERR_PTR(err);
-+	goto out;
-+}
++	case 106:
++		test_hash("xcbc(aes)", aes_xcbc128_tv_template,
++			  XCBC_AES_TEST_VECTORS);
++		break;
+ 
+ 	case 200:
+ 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
+@@ -1400,6 +1701,11 @@ static void do_test(void)
+ 				camellia_speed_template);
+ 		break;
+ 
++	case 206:
++		test_cipher_speed("salsa20", ENCRYPT, sec, NULL, 0,
++				  salsa20_speed_template);
++		break;
 +
-+static struct crypto_instance *crypto_ccm_alloc(struct rtattr **tb)
-+{
-+	int err;
-+	const char *cipher_name;
-+	char ctr_name[CRYPTO_MAX_ALG_NAME];
-+	char full_name[CRYPTO_MAX_ALG_NAME];
+ 	case 300:
+ 		/* fall through */
+ 
+@@ -1451,6 +1757,10 @@ static void do_test(void)
+ 		test_hash_speed("tgr192", sec, generic_hash_speed_template);
+ 		if (mode > 300 && mode < 400) break;
+ 
++	case 313:
++		test_hash_speed("sha224", sec, generic_hash_speed_template);
++		if (mode > 300 && mode < 400) break;
 +
-+	cipher_name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(cipher_name);
-+	if (IS_ERR(cipher_name))
-+		return ERR_PTR(err);
+ 	case 399:
+ 		break;
+ 
+@@ -1467,20 +1777,21 @@ static void do_test(void)
+ 
+ static int __init init(void)
+ {
++	int err = -ENOMEM;
 +
-+	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
-+		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
-+		return ERR_PTR(-ENAMETOOLONG);
+ 	tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
+ 	if (tvmem == NULL)
+-		return -ENOMEM;
++		return err;
+ 
+ 	xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
+-	if (xbuf == NULL) {
+-		kfree(tvmem);
+-		return -ENOMEM;
+-	}
++	if (xbuf == NULL)
++		goto err_free_tv;
+ 
+-	do_test();
++	axbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
++	if (axbuf == NULL)
++		goto err_free_xbuf;
+ 
+-	kfree(xbuf);
+-	kfree(tvmem);
++	do_test();
+ 
+ 	/* We intentionaly return -EAGAIN to prevent keeping
+ 	 * the module. It does all its work from init()
+@@ -1488,7 +1799,15 @@ static int __init init(void)
+ 	 * => we don't need it in the memory, do we?
+ 	 *                                        -- mludvig
+ 	 */
+-	return -EAGAIN;
++	err = -EAGAIN;
 +
-+	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		return ERR_PTR(-ENAMETOOLONG);
++	kfree(axbuf);
++ err_free_xbuf:
++	kfree(xbuf);
++ err_free_tv:
++	kfree(tvmem);
 +
-+	return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
-+}
++	return err;
+ }
+ 
+ /*
+diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
+index ec86138..f785e56 100644
+--- a/crypto/tcrypt.h
++++ b/crypto/tcrypt.h
+@@ -6,12 +6,15 @@
+  *
+  * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
+  * Copyright (c) 2002 Jean-Francois Dive <jef at linuxbe.org>
++ * Copyright (c) 2007 Nokia Siemens Networks
+  *
+  * 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.
+  *
++ * 2007-11-13 Added GCM tests
++ * 2007-11-13 Added AEAD support
+  * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
+  * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk at vantronix.net>
+  * 2003-09-14 Changes by Kartikey Mahendra Bhatt
+@@ -40,14 +43,32 @@ struct hash_testvec {
+ struct cipher_testvec {
+ 	char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
+ 	char iv[MAX_IVLEN];
++	char input[4100];
++	char result[4100];
++	unsigned char tap[MAX_TAP];
++	int np;
++	unsigned char fail;
++	unsigned char wk; /* weak key flag */
++	unsigned char klen;
++	unsigned short ilen;
++	unsigned short rlen;
++};
 +
-+static void crypto_ccm_free(struct crypto_instance *inst)
-+{
-+	struct ccm_instance_ctx *ctx = crypto_instance_ctx(inst);
++struct aead_testvec {
++	char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
++	char iv[MAX_IVLEN];
+ 	char input[512];
++	char assoc[512];
+ 	char result[512];
+ 	unsigned char tap[MAX_TAP];
++	unsigned char atap[MAX_TAP];
+ 	int np;
++	int anp;
+ 	unsigned char fail;
+ 	unsigned char wk; /* weak key flag */
+ 	unsigned char klen;
+ 	unsigned short ilen;
++	unsigned short alen;
+ 	unsigned short rlen;
+ };
+ 
+@@ -173,6 +194,33 @@ static struct hash_testvec sha1_tv_template[] = {
+ 	}
+ };
+ 
 +
-+	crypto_drop_spawn(&ctx->cipher);
-+	crypto_drop_skcipher(&ctx->ctr);
-+	kfree(inst);
-+}
++/*
++ * SHA224 test vectors from from FIPS PUB 180-2
++ */
++#define SHA224_TEST_VECTORS     2
 +
-+static struct crypto_template crypto_ccm_tmpl = {
-+	.name = "ccm",
-+	.alloc = crypto_ccm_alloc,
-+	.free = crypto_ccm_free,
-+	.module = THIS_MODULE,
++static struct hash_testvec sha224_tv_template[] = {
++	{
++		.plaintext = "abc",
++		.psize  = 3,
++		.digest = { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
++			0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
++			0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
++			0xE3, 0x6C, 0x9D, 0xA7},
++	}, {
++		.plaintext =
++		"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
++		.psize  = 56,
++		.digest = { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
++			0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
++			0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
++			0x52, 0x52, 0x25, 0x25 },
++		.np     = 2,
++		.tap    = { 28, 28 }
++	}
 +};
 +
-+static struct crypto_instance *crypto_ccm_base_alloc(struct rtattr **tb)
-+{
-+	int err;
-+	const char *ctr_name;
-+	const char *cipher_name;
-+	char full_name[CRYPTO_MAX_ALG_NAME];
+ /*
+  * SHA256 test vectors from from NIST
+  */
+@@ -817,6 +865,121 @@ static struct hash_testvec hmac_sha1_tv_template[] = {
+ 	},
+ };
+ 
 +
-+	ctr_name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(ctr_name);
-+	if (IS_ERR(ctr_name))
-+		return ERR_PTR(err);
++/*
++ * SHA224 HMAC test vectors from RFC4231
++ */
++#define HMAC_SHA224_TEST_VECTORS    4
 +
-+	cipher_name = crypto_attr_alg_name(tb[2]);
-+	err = PTR_ERR(cipher_name);
-+	if (IS_ERR(cipher_name))
-+		return ERR_PTR(err);
++static struct hash_testvec hmac_sha224_tv_template[] = {
++	{
++		.key    = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
++			0x0b, 0x0b, 0x0b, 0x0b },
++		.ksize  = 20,
++		/*  ("Hi There") */
++		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 },
++		.psize  = 8,
++		.digest = { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
++			0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
++			0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
++			0x53, 0x68, 0x4b, 0x22},
++	}, {
++		.key    = { 0x4a, 0x65, 0x66, 0x65 }, /* ("Jefe") */
++		.ksize  = 4,
++		/* ("what do ya want for nothing?") */
++		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
++			0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
++			0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
++			0x69, 0x6e, 0x67, 0x3f },
++		.psize  = 28,
++		.digest = { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
++			0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
++			0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
++			0x8f, 0xd0, 0x5e, 0x44 },
++		.np = 4,
++		.tap    = { 7, 7, 7, 7 }
++	}, {
++		.key    = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa },
++		.ksize  = 131,
++		/* ("Test Using Larger Than Block-Size Key - Hash Key First") */
++		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
++			0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
++			0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
++			0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
++			0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
++			0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
++			0x20, 0x46, 0x69, 0x72, 0x73, 0x74 },
++		.psize  = 54,
++		.digest = { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
++			0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
++			0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
++			0x3f, 0xa6, 0x87, 0x0e },
++	}, {
++		.key    = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
++			0xaa, 0xaa, 0xaa },
++		.ksize  = 131,
++		/* ("This is a test using a larger than block-size key and a")
++		(" larger than block-size data. The key needs to be")
++			(" hashed before being used by the HMAC algorithm.") */
++		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
++			0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
++			0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
++			0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
++			0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
++			0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
++			0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
++			0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
++			0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
++			0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
++			0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
++			0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
++			0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
++			0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
++			0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
++			0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
++			0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
++			0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
++			0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e },
++		.psize  = 152,
++		.digest = { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
++			0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
++			0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
++			0xf6, 0xf5, 0x65, 0xd1 },
++	},
++};
 +
-+	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
-+		     ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
-+		return ERR_PTR(-ENAMETOOLONG);
+ /*
+  * HMAC-SHA256 test vectors from
+  * draft-ietf-ipsec-ciph-sha-256-01.txt
+@@ -2140,12 +2303,18 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
+  */
+ #define AES_ENC_TEST_VECTORS 3
+ #define AES_DEC_TEST_VECTORS 3
+-#define AES_CBC_ENC_TEST_VECTORS 2
+-#define AES_CBC_DEC_TEST_VECTORS 2
++#define AES_CBC_ENC_TEST_VECTORS 4
++#define AES_CBC_DEC_TEST_VECTORS 4
+ #define AES_LRW_ENC_TEST_VECTORS 8
+ #define AES_LRW_DEC_TEST_VECTORS 8
+ #define AES_XTS_ENC_TEST_VECTORS 4
+ #define AES_XTS_DEC_TEST_VECTORS 4
++#define AES_CTR_ENC_TEST_VECTORS 7
++#define AES_CTR_DEC_TEST_VECTORS 6
++#define AES_GCM_ENC_TEST_VECTORS 9
++#define AES_GCM_DEC_TEST_VECTORS 8
++#define AES_CCM_ENC_TEST_VECTORS 7
++#define AES_CCM_DEC_TEST_VECTORS 7
+ 
+ static struct cipher_testvec aes_enc_tv_template[] = {
+ 	{ /* From FIPS-197 */
+@@ -2249,6 +2418,57 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
+ 			    0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
+ 			    0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
+ 		.rlen   = 32,
++	}, { /* From NIST SP800-38A */
++		.key	= { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
++			    0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
++			    0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
++		.klen	= 24,
++		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
++			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
++			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
++			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
++			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
++			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
++			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
++			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.ilen	= 64,
++		.result	= { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
++			    0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
++			    0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
++			    0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
++			    0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
++			    0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
++			    0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
++			    0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
++		.rlen	= 64,
++	}, {
++		.key	= { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
++			    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
++			    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
++			    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
++		.klen	= 32,
++		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
++			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
++			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
++			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
++			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
++			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
++			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
++			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.ilen	= 64,
++		.result	= { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
++			    0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
++			    0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
++			    0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
++			    0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
++			    0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
++			    0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
++			    0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
++		.rlen	= 64,
+ 	},
+ };
+ 
+@@ -2280,6 +2500,57 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
+ 			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+ 		.rlen   = 32,
++	}, { /* From NIST SP800-38A */
++		.key	= { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
++			    0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
++			    0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
++		.klen	= 24,
++		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
++			    0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
++			    0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
++			    0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
++			    0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
++			    0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
++			    0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
++			    0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
++		.ilen	= 64,
++		.result	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
++			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
++			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
++			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
++			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
++			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
++			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
++			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.rlen	= 64,
++	}, {
++		.key	= { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
++			    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
++			    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
++			    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
++		.klen	= 32,
++		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
++		.input	= { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
++			    0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
++			    0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
++			    0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
++			    0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
++			    0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
++			    0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
++			    0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
++		.ilen	= 64,
++		.result	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
++			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
++			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
++			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
++			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
++			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
++			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
++			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
++		.rlen	= 64,
+ 	},
+ };
+ 
+@@ -3180,6 +3451,1843 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
+ 	}
+ };
+ 
 +
-+	return crypto_ccm_alloc_common(tb, full_name, ctr_name, cipher_name);
-+}
++static struct cipher_testvec aes_ctr_enc_tv_template[] = {
++	{ /* From RFC 3686 */
++		.key	= { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
++			    0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
++			    0x00, 0x00, 0x00, 0x30 },
++		.klen	= 20,
++		.iv 	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input 	= { "Single block msg" },
++		.ilen	= 16,
++		.result = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
++			    0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
++		.rlen	= 16,
++	}, {
++		.key	= { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
++			    0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
++			    0x00, 0x6c, 0xb6, 0xdb },
++		.klen	= 20,
++		.iv 	= { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
++		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.ilen 	= 32,
++		.result = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
++			    0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
++			    0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
++			    0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
++		.rlen	= 32,
++	}, {
++		.key 	= { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
++			    0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
++			    0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
++			    0x00, 0x00, 0x00, 0x48 },
++		.klen 	= 28,
++		.iv	= { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
++		.input	= { "Single block msg" },
++		.ilen 	= 16,
++		.result	= { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
++			    0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
++		.rlen	= 16,
++	}, {
++		.key	= { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
++			    0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
++			    0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
++			    0x00, 0x96, 0xb0, 0x3b },
++		.klen	= 28,
++		.iv 	= { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
++		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.ilen	= 32,
++		.result	= { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
++			    0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
++			    0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
++			    0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
++		.rlen 	= 32,
++	}, {
++		.key 	= { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
++			    0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
++			    0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
++			    0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
++			    0x00, 0x00, 0x00, 0x60 },
++		.klen	= 36,
++		.iv 	= { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
++		.input	= { "Single block msg" },
++		.ilen	= 16,
++		.result = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
++			    0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
++		.rlen 	= 16,
++	}, {
++		.key	= { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
++			    0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
++			    0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
++			    0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
++			    0x00, 0xfa, 0xac, 0x24 },
++		.klen 	= 36,
++		.iv	= { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
++		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.ilen	= 32,
++		.result = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
++			    0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
++			    0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
++			    0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
++		.rlen	= 32,
++	}, {
++	// generated using Crypto++
++		.key = {
++			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++			0x00, 0x00, 0x00, 0x00,
++		},
++		.klen = 32 + 4,
++		.iv = {
++			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++		},
++		.input = {
++			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
++			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
++			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
++			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
++			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
++			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
++			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
++			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
++			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
++			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
++			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
++			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
++			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
++			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
++			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
++			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
++			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
++			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
++			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
++			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
++			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
++			0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
++			0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
++			0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
++			0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
++			0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
++			0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
++			0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
++			0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
++			0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
++			0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
++			0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
++			0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
++			0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
++			0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
++			0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
++			0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
++			0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
++			0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
++			0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
++			0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
++			0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
++			0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
++			0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
++			0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
++			0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
++			0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
++			0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
++			0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
++			0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
++			0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
++			0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
++			0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
++			0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
++			0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
++			0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
++			0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
++			0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
++			0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
++			0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
++			0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
++			0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
++			0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
++			0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
++			0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
++			0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
++			0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
++			0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
++			0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
++			0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
++			0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
++			0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
++			0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
++			0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
++			0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
++			0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
++			0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
++			0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
++			0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
++			0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
++			0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
++			0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
++			0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
++			0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
++			0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
++			0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
++			0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
++			0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
++			0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
++			0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
++			0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
++			0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
++			0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
++			0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
++			0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
++			0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
++			0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
++			0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
++			0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
++			0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
++			0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
++			0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
++			0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
++			0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
++			0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
++			0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
++			0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
++			0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
++			0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
++			0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
++			0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
++			0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
++			0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
++			0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
++			0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
++			0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
++			0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
++			0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
++			0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
++			0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
++			0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
++			0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
++			0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
++			0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
++			0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
++			0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
++			0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
++			0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
++			0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
++			0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
++			0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
++			0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
++			0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
++			0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
++			0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
++			0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
++			0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
++			0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
++			0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
++			0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
++			0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
++			0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
++			0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
++			0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
++			0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
++			0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
++			0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
++			0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
++			0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
++			0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
++			0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
++			0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
++			0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
++			0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
++			0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
++			0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
++			0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
++			0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
++			0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
++			0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
++			0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
++			0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
++			0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
++			0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
++			0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
++			0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
++			0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
++			0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
++			0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
++			0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
++			0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
++			0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
++			0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
++			0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
++			0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
++			0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
++			0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
++			0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
++			0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
++			0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
++			0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
++			0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
++			0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
++			0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
++			0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
++			0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
++			0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
++			0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
++			0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
++			0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
++			0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
++			0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
++			0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
++			0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
++			0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
++			0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
++			0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
++			0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
++			0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
++			0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
++			0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
++			0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
++			0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
++			0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
++			0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
++			0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
++			0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
++			0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
++			0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
++			0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
++			0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
++			0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
++			0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
++			0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
++			0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
++			0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
++			0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
++			0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
++			0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
++			0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
++			0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
++			0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
++			0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
++			0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
++			0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
++			0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
++			0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
++			0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
++			0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
++			0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
++			0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
++			0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
++			0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
++			0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
++			0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
++			0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
++			0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
++			0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
++			0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
++			0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
++			0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
++			0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
++			0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
++			0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
++			0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
++			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
++			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
++			0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
++			0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
++			0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
++			0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
++			0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
++			0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
++			0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
++			0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
++			0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
++			0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
++			0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
++			0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
++			0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
++			0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
++			0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
++			0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
++			0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
++			0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
++			0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
++			0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
++			0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
++			0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
++			0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
++			0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
++			0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
++			0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
++			0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
++			0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
++			0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
++			0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
++			0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
++			0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
++			0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
++			0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
++			0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
++			0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
++			0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
++			0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
++			0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
++			0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
++			0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
++			0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
++			0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
++			0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
++			0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
++			0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
++			0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
++			0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
++			0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
++			0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
++			0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
++			0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
++			0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
++			0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
++			0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
++			0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
++			0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
++			0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
++			0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
++			0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
++			0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
++			0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
++			0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
++			0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
++			0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
++			0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
++			0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
++			0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
++			0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
++			0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
++			0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
++			0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
++			0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
++			0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
++			0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
++			0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
++			0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
++			0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
++			0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
++			0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
++			0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
++			0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
++			0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
++			0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
++			0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
++			0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
++			0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
++			0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
++			0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
++			0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
++			0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
++			0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
++			0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
++			0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
++			0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
++			0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
++			0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
++			0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
++			0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
++			0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
++			0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
++			0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
++			0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
++			0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
++			0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
++			0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
++			0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
++			0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
++			0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
++			0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
++			0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
++			0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
++			0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
++			0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
++			0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
++			0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
++			0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
++			0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
++			0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
++			0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
++			0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
++			0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
++			0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
++			0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
++			0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
++			0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
++			0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
++			0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
++			0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
++			0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
++			0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
++			0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
++			0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
++			0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
++			0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
++			0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
++			0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
++			0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
++			0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
++			0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
++			0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
++			0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
++			0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
++			0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
++			0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
++			0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
++			0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
++			0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
++			0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
++			0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
++			0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
++			0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
++			0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
++			0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
++			0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
++			0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
++			0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
++			0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
++			0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
++			0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
++			0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
++			0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
++			0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
++			0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
++			0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
++			0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
++			0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
++			0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
++			0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
++			0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
++			0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
++			0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
++			0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
++			0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
++			0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
++			0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
++			0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
++			0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
++			0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
++			0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
++			0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
++			0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
++			0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
++			0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
++			0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
++			0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
++			0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
++			0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
++			0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
++			0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
++			0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
++			0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
++			0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
++			0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
++			0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
++			0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
++			0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
++			0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
++			0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
++			0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
++			0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
++			0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
++			0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
++			0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
++			0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
++			0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
++			0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
++			0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
++			0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
++			0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
++			0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
++			0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
++			0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
++			0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
++			0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
++			0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
++			0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
++			0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
++			0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
++			0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
++			0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
++			0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
++			0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
++			0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
++			0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
++			0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
++			0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
++			0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
++			0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
++			0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
++			0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
++			0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
++			0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
++			0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
++			0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
++			0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
++			0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
++			0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
++			0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
++			0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
++			0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
++			0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
++			0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
++			0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
++			0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
++			0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
++			0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
++			0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
++			0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
++			0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
++			0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
++			0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
++			0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
++			0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
++			0x00, 0x21, 0x42, 0x63,
++		},
++		.ilen = 4100,
++		.result = {
++			0xf0, 0x5c, 0x74, 0xad, 0x4e, 0xbc, 0x99, 0xe2,
++			0xae, 0xff, 0x91, 0x3a, 0x44, 0xcf, 0x38, 0x32,
++			0x1e, 0xad, 0xa7, 0xcd, 0xa1, 0x39, 0x95, 0xaa,
++			0x10, 0xb1, 0xb3, 0x2e, 0x04, 0x31, 0x8f, 0x86,
++			0xf2, 0x62, 0x74, 0x70, 0x0c, 0xa4, 0x46, 0x08,
++			0xa8, 0xb7, 0x99, 0xa8, 0xe9, 0xd2, 0x73, 0x79,
++			0x7e, 0x6e, 0xd4, 0x8f, 0x1e, 0xc7, 0x8e, 0x31,
++			0x0b, 0xfa, 0x4b, 0xce, 0xfd, 0xf3, 0x57, 0x71,
++			0xe9, 0x46, 0x03, 0xa5, 0x3d, 0x34, 0x00, 0xe2,
++			0x18, 0xff, 0x75, 0x6d, 0x06, 0x2d, 0x00, 0xab,
++			0xb9, 0x3e, 0x6c, 0x59, 0xc5, 0x84, 0x06, 0xb5,
++			0x8b, 0xd0, 0x89, 0x9c, 0x4a, 0x79, 0x16, 0xc6,
++			0x3d, 0x74, 0x54, 0xfa, 0x44, 0xcd, 0x23, 0x26,
++			0x5c, 0xcf, 0x7e, 0x28, 0x92, 0x32, 0xbf, 0xdf,
++			0xa7, 0x20, 0x3c, 0x74, 0x58, 0x2a, 0x9a, 0xde,
++			0x61, 0x00, 0x1c, 0x4f, 0xff, 0x59, 0xc4, 0x22,
++			0xac, 0x3c, 0xd0, 0xe8, 0x6c, 0xf9, 0x97, 0x1b,
++			0x58, 0x9b, 0xad, 0x71, 0xe8, 0xa9, 0xb5, 0x0d,
++			0xee, 0x2f, 0x04, 0x1f, 0x7f, 0xbc, 0x99, 0xee,
++			0x84, 0xff, 0x42, 0x60, 0xdc, 0x3a, 0x18, 0xa5,
++			0x81, 0xf9, 0xef, 0xdc, 0x7a, 0x0f, 0x65, 0x41,
++			0x2f, 0xa3, 0xd3, 0xf9, 0xc2, 0xcb, 0xc0, 0x4d,
++			0x8f, 0xd3, 0x76, 0x96, 0xad, 0x49, 0x6d, 0x38,
++			0x3d, 0x39, 0x0b, 0x6c, 0x80, 0xb7, 0x54, 0x69,
++			0xf0, 0x2c, 0x90, 0x02, 0x29, 0x0d, 0x1c, 0x12,
++			0xad, 0x55, 0xc3, 0x8b, 0x68, 0xd9, 0xcc, 0xb3,
++			0xb2, 0x64, 0x33, 0x90, 0x5e, 0xca, 0x4b, 0xe2,
++			0xfb, 0x75, 0xdc, 0x63, 0xf7, 0x9f, 0x82, 0x74,
++			0xf0, 0xc9, 0xaa, 0x7f, 0xe9, 0x2a, 0x9b, 0x33,
++			0xbc, 0x88, 0x00, 0x7f, 0xca, 0xb2, 0x1f, 0x14,
++			0xdb, 0xc5, 0x8e, 0x7b, 0x11, 0x3c, 0x3e, 0x08,
++			0xf3, 0x83, 0xe8, 0xe0, 0x94, 0x86, 0x2e, 0x92,
++			0x78, 0x6b, 0x01, 0xc9, 0xc7, 0x83, 0xba, 0x21,
++			0x6a, 0x25, 0x15, 0x33, 0x4e, 0x45, 0x08, 0xec,
++			0x35, 0xdb, 0xe0, 0x6e, 0x31, 0x51, 0x79, 0xa9,
++			0x42, 0x44, 0x65, 0xc1, 0xa0, 0xf1, 0xf9, 0x2a,
++			0x70, 0xd5, 0xb6, 0xc6, 0xc1, 0x8c, 0x39, 0xfc,
++			0x25, 0xa6, 0x55, 0xd9, 0xdd, 0x2d, 0x4c, 0xec,
++			0x49, 0xc6, 0xeb, 0x0e, 0xa8, 0x25, 0x2a, 0x16,
++			0x1b, 0x66, 0x84, 0xda, 0xe2, 0x92, 0xe5, 0xc0,
++			0xc8, 0x53, 0x07, 0xaf, 0x80, 0x84, 0xec, 0xfd,
++			0xcd, 0xd1, 0x6e, 0xcd, 0x6f, 0x6a, 0xf5, 0x36,
++			0xc5, 0x15, 0xe5, 0x25, 0x7d, 0x77, 0xd1, 0x1a,
++			0x93, 0x36, 0xa9, 0xcf, 0x7c, 0xa4, 0x54, 0x4a,
++			0x06, 0x51, 0x48, 0x4e, 0xf6, 0x59, 0x87, 0xd2,
++			0x04, 0x02, 0xef, 0xd3, 0x44, 0xde, 0x76, 0x31,
++			0xb3, 0x34, 0x17, 0x1b, 0x9d, 0x66, 0x11, 0x9f,
++			0x1e, 0xcc, 0x17, 0xe9, 0xc7, 0x3c, 0x1b, 0xe7,
++			0xcb, 0x50, 0x08, 0xfc, 0xdc, 0x2b, 0x24, 0xdb,
++			0x65, 0x83, 0xd0, 0x3b, 0xe3, 0x30, 0xea, 0x94,
++			0x6c, 0xe7, 0xe8, 0x35, 0x32, 0xc7, 0xdb, 0x64,
++			0xb4, 0x01, 0xab, 0x36, 0x2c, 0x77, 0x13, 0xaf,
++			0xf8, 0x2b, 0x88, 0x3f, 0x54, 0x39, 0xc4, 0x44,
++			0xfe, 0xef, 0x6f, 0x68, 0x34, 0xbe, 0x0f, 0x05,
++			0x16, 0x6d, 0xf6, 0x0a, 0x30, 0xe7, 0xe3, 0xed,
++			0xc4, 0xde, 0x3c, 0x1b, 0x13, 0xd8, 0xdb, 0xfe,
++			0x41, 0x62, 0xe5, 0x28, 0xd4, 0x8d, 0xa3, 0xc7,
++			0x93, 0x97, 0xc6, 0x48, 0x45, 0x1d, 0x9f, 0x83,
++			0xdf, 0x4b, 0x40, 0x3e, 0x42, 0x25, 0x87, 0x80,
++			0x4c, 0x7d, 0xa8, 0xd4, 0x98, 0x23, 0x95, 0x75,
++			0x41, 0x8c, 0xda, 0x41, 0x9b, 0xd4, 0xa7, 0x06,
++			0xb5, 0xf1, 0x71, 0x09, 0x53, 0xbe, 0xca, 0xbf,
++			0x32, 0x03, 0xed, 0xf0, 0x50, 0x1c, 0x56, 0x39,
++			0x5b, 0xa4, 0x75, 0x18, 0xf7, 0x9b, 0x58, 0xef,
++			0x53, 0xfc, 0x2a, 0x38, 0x23, 0x15, 0x75, 0xcd,
++			0x45, 0xe5, 0x5a, 0x82, 0x55, 0xba, 0x21, 0xfa,
++			0xd4, 0xbd, 0xc6, 0x94, 0x7c, 0xc5, 0x80, 0x12,
++			0xf7, 0x4b, 0x32, 0xc4, 0x9a, 0x82, 0xd8, 0x28,
++			0x8f, 0xd9, 0xc2, 0x0f, 0x60, 0x03, 0xbe, 0x5e,
++			0x21, 0xd6, 0x5f, 0x58, 0xbf, 0x5c, 0xb1, 0x32,
++			0x82, 0x8d, 0xa9, 0xe5, 0xf2, 0x66, 0x1a, 0xc0,
++			0xa0, 0xbc, 0x58, 0x2f, 0x71, 0xf5, 0x2f, 0xed,
++			0xd1, 0x26, 0xb9, 0xd8, 0x49, 0x5a, 0x07, 0x19,
++			0x01, 0x7c, 0x59, 0xb0, 0xf8, 0xa4, 0xb7, 0xd3,
++			0x7b, 0x1a, 0x8c, 0x38, 0xf4, 0x50, 0xa4, 0x59,
++			0xb0, 0xcc, 0x41, 0x0b, 0x88, 0x7f, 0xe5, 0x31,
++			0xb3, 0x42, 0xba, 0xa2, 0x7e, 0xd4, 0x32, 0x71,
++			0x45, 0x87, 0x48, 0xa9, 0xc2, 0xf2, 0x89, 0xb3,
++			0xe4, 0xa7, 0x7e, 0x52, 0x15, 0x61, 0xfa, 0xfe,
++			0xc9, 0xdd, 0x81, 0xeb, 0x13, 0xab, 0xab, 0xc3,
++			0x98, 0x59, 0xd8, 0x16, 0x3d, 0x14, 0x7a, 0x1c,
++			0x3c, 0x41, 0x9a, 0x16, 0x16, 0x9b, 0xd2, 0xd2,
++			0x69, 0x3a, 0x29, 0x23, 0xac, 0x86, 0x32, 0xa5,
++			0x48, 0x9c, 0x9e, 0xf3, 0x47, 0x77, 0x81, 0x70,
++			0x24, 0xe8, 0x85, 0xd2, 0xf5, 0xb5, 0xfa, 0xff,
++			0x59, 0x6a, 0xd3, 0x50, 0x59, 0x43, 0x59, 0xde,
++			0xd9, 0xf1, 0x55, 0xa5, 0x0c, 0xc3, 0x1a, 0x1a,
++			0x18, 0x34, 0x0d, 0x1a, 0x63, 0x33, 0xed, 0x10,
++			0xe0, 0x1d, 0x2a, 0x18, 0xd2, 0xc0, 0x54, 0xa8,
++			0xca, 0xb5, 0x9a, 0xd3, 0xdd, 0xca, 0x45, 0x84,
++			0x50, 0xe7, 0x0f, 0xfe, 0xa4, 0x99, 0x5a, 0xbe,
++			0x43, 0x2d, 0x9a, 0xcb, 0x92, 0x3f, 0x5a, 0x1d,
++			0x85, 0xd8, 0xc9, 0xdf, 0x68, 0xc9, 0x12, 0x80,
++			0x56, 0x0c, 0xdc, 0x00, 0xdc, 0x3a, 0x7d, 0x9d,
++			0xa3, 0xa2, 0xe8, 0x4d, 0xbf, 0xf9, 0x70, 0xa0,
++			0xa4, 0x13, 0x4f, 0x6b, 0xaf, 0x0a, 0x89, 0x7f,
++			0xda, 0xf0, 0xbf, 0x9b, 0xc8, 0x1d, 0xe5, 0xf8,
++			0x2e, 0x8b, 0x07, 0xb5, 0x73, 0x1b, 0xcc, 0xa2,
++			0xa6, 0xad, 0x30, 0xbc, 0x78, 0x3c, 0x5b, 0x10,
++			0xfa, 0x5e, 0x62, 0x2d, 0x9e, 0x64, 0xb3, 0x33,
++			0xce, 0xf9, 0x1f, 0x86, 0xe7, 0x8b, 0xa2, 0xb8,
++			0xe8, 0x99, 0x57, 0x8c, 0x11, 0xed, 0x66, 0xd9,
++			0x3c, 0x72, 0xb9, 0xc3, 0xe6, 0x4e, 0x17, 0x3a,
++			0x6a, 0xcb, 0x42, 0x24, 0x06, 0xed, 0x3e, 0x4e,
++			0xa3, 0xe8, 0x6a, 0x94, 0xda, 0x0d, 0x4e, 0xd5,
++			0x14, 0x19, 0xcf, 0xb6, 0x26, 0xd8, 0x2e, 0xcc,
++			0x64, 0x76, 0x38, 0x49, 0x4d, 0xfe, 0x30, 0x6d,
++			0xe4, 0xc8, 0x8c, 0x7b, 0xc4, 0xe0, 0x35, 0xba,
++			0x22, 0x6e, 0x76, 0xe1, 0x1a, 0xf2, 0x53, 0xc3,
++			0x28, 0xa2, 0x82, 0x1f, 0x61, 0x69, 0xad, 0xc1,
++			0x7b, 0x28, 0x4b, 0x1e, 0x6c, 0x85, 0x95, 0x9b,
++			0x51, 0xb5, 0x17, 0x7f, 0x12, 0x69, 0x8c, 0x24,
++			0xd5, 0xc7, 0x5a, 0x5a, 0x11, 0x54, 0xff, 0x5a,
++			0xf7, 0x16, 0xc3, 0x91, 0xa6, 0xf0, 0xdc, 0x0a,
++			0xb6, 0xa7, 0x4a, 0x0d, 0x7a, 0x58, 0xfe, 0xa5,
++			0xf5, 0xcb, 0x8f, 0x7b, 0x0e, 0xea, 0x57, 0xe7,
++			0xbd, 0x79, 0xd6, 0x1c, 0x88, 0x23, 0x6c, 0xf2,
++			0x4d, 0x29, 0x77, 0x53, 0x35, 0x6a, 0x00, 0x8d,
++			0xcd, 0xa3, 0x58, 0xbe, 0x77, 0x99, 0x18, 0xf8,
++			0xe6, 0xe1, 0x8f, 0xe9, 0x37, 0x8f, 0xe3, 0xe2,
++			0x5a, 0x8a, 0x93, 0x25, 0xaf, 0xf3, 0x78, 0x80,
++			0xbe, 0xa6, 0x1b, 0xc6, 0xac, 0x8b, 0x1c, 0x91,
++			0x58, 0xe1, 0x9f, 0x89, 0x35, 0x9d, 0x1d, 0x21,
++			0x29, 0x9f, 0xf4, 0x99, 0x02, 0x27, 0x0f, 0xa8,
++			0x4f, 0x79, 0x94, 0x2b, 0x33, 0x2c, 0xda, 0xa2,
++			0x26, 0x39, 0x83, 0x94, 0xef, 0x27, 0xd8, 0x53,
++			0x8f, 0x66, 0x0d, 0xe4, 0x41, 0x7d, 0x34, 0xcd,
++			0x43, 0x7c, 0x95, 0x0a, 0x53, 0xef, 0x66, 0xda,
++			0x7e, 0x9b, 0xf3, 0x93, 0xaf, 0xd0, 0x73, 0x71,
++			0xba, 0x40, 0x9b, 0x74, 0xf8, 0xd7, 0xd7, 0x41,
++			0x6d, 0xaf, 0x72, 0x9c, 0x8d, 0x21, 0x87, 0x3c,
++			0xfd, 0x0a, 0x90, 0xa9, 0x47, 0x96, 0x9e, 0xd3,
++			0x88, 0xee, 0x73, 0xcf, 0x66, 0x2f, 0x52, 0x56,
++			0x6d, 0xa9, 0x80, 0x4c, 0xe2, 0x6f, 0x62, 0x88,
++			0x3f, 0x0e, 0x54, 0x17, 0x48, 0x80, 0x5d, 0xd3,
++			0xc3, 0xda, 0x25, 0x3d, 0xa1, 0xc8, 0xcb, 0x9f,
++			0x9b, 0x70, 0xb3, 0xa1, 0xeb, 0x04, 0x52, 0xa1,
++			0xf2, 0x22, 0x0f, 0xfc, 0xc8, 0x18, 0xfa, 0xf9,
++			0x85, 0x9c, 0xf1, 0xac, 0xeb, 0x0c, 0x02, 0x46,
++			0x75, 0xd2, 0xf5, 0x2c, 0xe3, 0xd2, 0x59, 0x94,
++			0x12, 0xf3, 0x3c, 0xfc, 0xd7, 0x92, 0xfa, 0x36,
++			0xba, 0x61, 0x34, 0x38, 0x7c, 0xda, 0x48, 0x3e,
++			0x08, 0xc9, 0x39, 0x23, 0x5e, 0x02, 0x2c, 0x1a,
++			0x18, 0x7e, 0xb4, 0xd9, 0xfd, 0x9e, 0x40, 0x02,
++			0xb1, 0x33, 0x37, 0x32, 0xe7, 0xde, 0xd6, 0xd0,
++			0x7c, 0x58, 0x65, 0x4b, 0xf8, 0x34, 0x27, 0x9c,
++			0x44, 0xb4, 0xbd, 0xe9, 0xe9, 0x4c, 0x78, 0x7d,
++			0x4b, 0x9f, 0xce, 0xb1, 0xcd, 0x47, 0xa5, 0x37,
++			0xe5, 0x6d, 0xbd, 0xb9, 0x43, 0x94, 0x0a, 0xd4,
++			0xd6, 0xf9, 0x04, 0x5f, 0xb5, 0x66, 0x6c, 0x1a,
++			0x35, 0x12, 0xe3, 0x36, 0x28, 0x27, 0x36, 0x58,
++			0x01, 0x2b, 0x79, 0xe4, 0xba, 0x6d, 0x10, 0x7d,
++			0x65, 0xdf, 0x84, 0x95, 0xf4, 0xd5, 0xb6, 0x8f,
++			0x2b, 0x9f, 0x96, 0x00, 0x86, 0x60, 0xf0, 0x21,
++			0x76, 0xa8, 0x6a, 0x8c, 0x28, 0x1c, 0xb3, 0x6b,
++			0x97, 0xd7, 0xb6, 0x53, 0x2a, 0xcc, 0xab, 0x40,
++			0x9d, 0x62, 0x79, 0x58, 0x52, 0xe6, 0x65, 0xb7,
++			0xab, 0x55, 0x67, 0x9c, 0x89, 0x7c, 0x03, 0xb0,
++			0x73, 0x59, 0xc5, 0x81, 0xf5, 0x18, 0x17, 0x5c,
++			0x89, 0xf3, 0x78, 0x35, 0x44, 0x62, 0x78, 0x72,
++			0xd0, 0x96, 0xeb, 0x31, 0xe7, 0x87, 0x77, 0x14,
++			0x99, 0x51, 0xf2, 0x59, 0x26, 0x9e, 0xb5, 0xa6,
++			0x45, 0xfe, 0x6e, 0xbd, 0x07, 0x4c, 0x94, 0x5a,
++			0xa5, 0x7d, 0xfc, 0xf1, 0x2b, 0x77, 0xe2, 0xfe,
++			0x17, 0xd4, 0x84, 0xa0, 0xac, 0xb5, 0xc7, 0xda,
++			0xa9, 0x1a, 0xb6, 0xf3, 0x74, 0x11, 0xb4, 0x9d,
++			0xfb, 0x79, 0x2e, 0x04, 0x2d, 0x50, 0x28, 0x83,
++			0xbf, 0xc6, 0x52, 0xd3, 0x34, 0xd6, 0xe8, 0x7a,
++			0xb6, 0xea, 0xe7, 0xa8, 0x6c, 0x15, 0x1e, 0x2c,
++			0x57, 0xbc, 0x48, 0x4e, 0x5f, 0x5c, 0xb6, 0x92,
++			0xd2, 0x49, 0x77, 0x81, 0x6d, 0x90, 0x70, 0xae,
++			0x98, 0xa1, 0x03, 0x0d, 0x6b, 0xb9, 0x77, 0x14,
++			0xf1, 0x4e, 0x23, 0xd3, 0xf8, 0x68, 0xbd, 0xc2,
++			0xfe, 0x04, 0xb7, 0x5c, 0xc5, 0x17, 0x60, 0x8f,
++			0x65, 0x54, 0xa4, 0x7a, 0x42, 0xdc, 0x18, 0x0d,
++			0xb5, 0xcf, 0x0f, 0xd3, 0xc7, 0x91, 0x66, 0x1b,
++			0x45, 0x42, 0x27, 0x75, 0x50, 0xe5, 0xee, 0xb8,
++			0x7f, 0x33, 0x2c, 0xba, 0x4a, 0x92, 0x4d, 0x2c,
++			0x3c, 0xe3, 0x0d, 0x80, 0x01, 0xba, 0x0d, 0x29,
++			0xd8, 0x3c, 0xe9, 0x13, 0x16, 0x57, 0xe6, 0xea,
++			0x94, 0x52, 0xe7, 0x00, 0x4d, 0x30, 0xb0, 0x0f,
++			0x35, 0xb8, 0xb8, 0xa7, 0xb1, 0xb5, 0x3b, 0x44,
++			0xe1, 0x2f, 0xfd, 0x88, 0xed, 0x43, 0xe7, 0x52,
++			0x10, 0x93, 0xb3, 0x8a, 0x30, 0x6b, 0x0a, 0xf7,
++			0x23, 0xc6, 0x50, 0x9d, 0x4a, 0xb0, 0xde, 0xc3,
++			0xdc, 0x9b, 0x2f, 0x01, 0x56, 0x36, 0x09, 0xc5,
++			0x2f, 0x6b, 0xfe, 0xf1, 0xd8, 0x27, 0x45, 0x03,
++			0x30, 0x5e, 0x5c, 0x5b, 0xb4, 0x62, 0x0e, 0x1a,
++			0xa9, 0x21, 0x2b, 0x92, 0x94, 0x87, 0x62, 0x57,
++			0x4c, 0x10, 0x74, 0x1a, 0xf1, 0x0a, 0xc5, 0x84,
++			0x3b, 0x9e, 0x72, 0x02, 0xd7, 0xcc, 0x09, 0x56,
++			0xbd, 0x54, 0xc1, 0xf0, 0xc3, 0xe3, 0xb3, 0xf8,
++			0xd2, 0x0d, 0x61, 0xcb, 0xef, 0xce, 0x0d, 0x05,
++			0xb0, 0x98, 0xd9, 0x8e, 0x4f, 0xf9, 0xbc, 0x93,
++			0xa6, 0xea, 0xc8, 0xcf, 0x10, 0x53, 0x4b, 0xf1,
++			0xec, 0xfc, 0x89, 0xf9, 0x64, 0xb0, 0x22, 0xbf,
++			0x9e, 0x55, 0x46, 0x9f, 0x7c, 0x50, 0x8e, 0x84,
++			0x54, 0x20, 0x98, 0xd7, 0x6c, 0x40, 0x1e, 0xdb,
++			0x69, 0x34, 0x78, 0x61, 0x24, 0x21, 0x9c, 0x8a,
++			0xb3, 0x62, 0x31, 0x8b, 0x6e, 0xf5, 0x2a, 0x35,
++			0x86, 0x13, 0xb1, 0x6c, 0x64, 0x2e, 0x41, 0xa5,
++			0x05, 0xf2, 0x42, 0xba, 0xd2, 0x3a, 0x0d, 0x8e,
++			0x8a, 0x59, 0x94, 0x3c, 0xcf, 0x36, 0x27, 0x82,
++			0xc2, 0x45, 0xee, 0x58, 0xcd, 0x88, 0xb4, 0xec,
++			0xde, 0xb2, 0x96, 0x0a, 0xaf, 0x38, 0x6f, 0x88,
++			0xd7, 0xd8, 0xe1, 0xdf, 0xb9, 0x96, 0xa9, 0x0a,
++			0xb1, 0x95, 0x28, 0x86, 0x20, 0xe9, 0x17, 0x49,
++			0xa2, 0x29, 0x38, 0xaa, 0xa5, 0xe9, 0x6e, 0xf1,
++			0x19, 0x27, 0xc0, 0xd5, 0x2a, 0x22, 0xc3, 0x0b,
++			0xdb, 0x7c, 0x73, 0x10, 0xb9, 0xba, 0x89, 0x76,
++			0x54, 0xae, 0x7d, 0x71, 0xb3, 0x93, 0xf6, 0x32,
++			0xe6, 0x47, 0x43, 0x55, 0xac, 0xa0, 0x0d, 0xc2,
++			0x93, 0x27, 0x4a, 0x8e, 0x0e, 0x74, 0x15, 0xc7,
++			0x0b, 0x85, 0xd9, 0x0c, 0xa9, 0x30, 0x7a, 0x3e,
++			0xea, 0x8f, 0x85, 0x6d, 0x3a, 0x12, 0x4f, 0x72,
++			0x69, 0x58, 0x7a, 0x80, 0xbb, 0xb5, 0x97, 0xf3,
++			0xcf, 0x70, 0xd2, 0x5d, 0xdd, 0x4d, 0x21, 0x79,
++			0x54, 0x4d, 0xe4, 0x05, 0xe8, 0xbd, 0xc2, 0x62,
++			0xb1, 0x3b, 0x77, 0x1c, 0xd6, 0x5c, 0xf3, 0xa0,
++			0x79, 0x00, 0xa8, 0x6c, 0x29, 0xd9, 0x18, 0x24,
++			0x36, 0xa2, 0x46, 0xc0, 0x96, 0x65, 0x7f, 0xbd,
++			0x2a, 0xed, 0x36, 0x16, 0x0c, 0xaa, 0x9f, 0xf4,
++			0xc5, 0xb4, 0xe2, 0x12, 0xed, 0x69, 0xed, 0x4f,
++			0x26, 0x2c, 0x39, 0x52, 0x89, 0x98, 0xe7, 0x2c,
++			0x99, 0xa4, 0x9e, 0xa3, 0x9b, 0x99, 0x46, 0x7a,
++			0x3a, 0xdc, 0xa8, 0x59, 0xa3, 0xdb, 0xc3, 0x3b,
++			0x95, 0x0d, 0x3b, 0x09, 0x6e, 0xee, 0x83, 0x5d,
++			0x32, 0x4d, 0xed, 0xab, 0xfa, 0x98, 0x14, 0x4e,
++			0xc3, 0x15, 0x45, 0x53, 0x61, 0xc4, 0x93, 0xbd,
++			0x90, 0xf4, 0x99, 0x95, 0x4c, 0xe6, 0x76, 0x92,
++			0x29, 0x90, 0x46, 0x30, 0x92, 0x69, 0x7d, 0x13,
++			0xf2, 0xa5, 0xcd, 0x69, 0x49, 0x44, 0xb2, 0x0f,
++			0x63, 0x40, 0x36, 0x5f, 0x09, 0xe2, 0x78, 0xf8,
++			0x91, 0xe3, 0xe2, 0xfa, 0x10, 0xf7, 0xc8, 0x24,
++			0xa8, 0x89, 0x32, 0x5c, 0x37, 0x25, 0x1d, 0xb2,
++			0xea, 0x17, 0x8a, 0x0a, 0xa9, 0x64, 0xc3, 0x7c,
++			0x3c, 0x7c, 0xbd, 0xc6, 0x79, 0x34, 0xe7, 0xe2,
++			0x85, 0x8e, 0xbf, 0xf8, 0xde, 0x92, 0xa0, 0xae,
++			0x20, 0xc4, 0xf6, 0xbb, 0x1f, 0x38, 0x19, 0x0e,
++			0xe8, 0x79, 0x9c, 0xa1, 0x23, 0xe9, 0x54, 0x7e,
++			0x37, 0x2f, 0xe2, 0x94, 0x32, 0xaf, 0xa0, 0x23,
++			0x49, 0xe4, 0xc0, 0xb3, 0xac, 0x00, 0x8f, 0x36,
++			0x05, 0xc4, 0xa6, 0x96, 0xec, 0x05, 0x98, 0x4f,
++			0x96, 0x67, 0x57, 0x1f, 0x20, 0x86, 0x1b, 0x2d,
++			0x69, 0xe4, 0x29, 0x93, 0x66, 0x5f, 0xaf, 0x6b,
++			0x88, 0x26, 0x2c, 0x67, 0x02, 0x4b, 0x52, 0xd0,
++			0x83, 0x7a, 0x43, 0x1f, 0xc0, 0x71, 0x15, 0x25,
++			0x77, 0x65, 0x08, 0x60, 0x11, 0x76, 0x4c, 0x8d,
++			0xed, 0xa9, 0x27, 0xc6, 0xb1, 0x2a, 0x2c, 0x6a,
++			0x4a, 0x97, 0xf5, 0xc6, 0xb7, 0x70, 0x42, 0xd3,
++			0x03, 0xd1, 0x24, 0x95, 0xec, 0x6d, 0xab, 0x38,
++			0x72, 0xce, 0xe2, 0x8b, 0x33, 0xd7, 0x51, 0x09,
++			0xdc, 0x45, 0xe0, 0x09, 0x96, 0x32, 0xf3, 0xc4,
++			0x84, 0xdc, 0x73, 0x73, 0x2d, 0x1b, 0x11, 0x98,
++			0xc5, 0x0e, 0x69, 0x28, 0x94, 0xc7, 0xb5, 0x4d,
++			0xc8, 0x8a, 0xd0, 0xaa, 0x13, 0x2e, 0x18, 0x74,
++			0xdd, 0xd1, 0x1e, 0xf3, 0x90, 0xe8, 0xfc, 0x9a,
++			0x72, 0x4a, 0x0e, 0xd1, 0xe4, 0xfb, 0x0d, 0x96,
++			0xd1, 0x0c, 0x79, 0x85, 0x1b, 0x1c, 0xfe, 0xe1,
++			0x62, 0x8f, 0x7a, 0x73, 0x32, 0xab, 0xc8, 0x18,
++			0x69, 0xe3, 0x34, 0x30, 0xdf, 0x13, 0xa6, 0xe5,
++			0xe8, 0x0e, 0x67, 0x7f, 0x81, 0x11, 0xb4, 0x60,
++			0xc7, 0xbd, 0x79, 0x65, 0x50, 0xdc, 0xc4, 0x5b,
++			0xde, 0x39, 0xa4, 0x01, 0x72, 0x63, 0xf3, 0xd1,
++			0x64, 0x4e, 0xdf, 0xfc, 0x27, 0x92, 0x37, 0x0d,
++			0x57, 0xcd, 0x11, 0x4f, 0x11, 0x04, 0x8e, 0x1d,
++			0x16, 0xf7, 0xcd, 0x92, 0x9a, 0x99, 0x30, 0x14,
++			0xf1, 0x7c, 0x67, 0x1b, 0x1f, 0x41, 0x0b, 0xe8,
++			0x32, 0xe8, 0xb8, 0xc1, 0x4f, 0x54, 0x86, 0x4f,
++			0xe5, 0x79, 0x81, 0x73, 0xcd, 0x43, 0x59, 0x68,
++			0x73, 0x02, 0x3b, 0x78, 0x21, 0x72, 0x43, 0x00,
++			0x49, 0x17, 0xf7, 0x00, 0xaf, 0x68, 0x24, 0x53,
++			0x05, 0x0a, 0xc3, 0x33, 0xe0, 0x33, 0x3f, 0x69,
++			0xd2, 0x84, 0x2f, 0x0b, 0xed, 0xde, 0x04, 0xf4,
++			0x11, 0x94, 0x13, 0x69, 0x51, 0x09, 0x28, 0xde,
++			0x57, 0x5c, 0xef, 0xdc, 0x9a, 0x49, 0x1c, 0x17,
++			0x97, 0xf3, 0x96, 0xc1, 0x7f, 0x5d, 0x2e, 0x7d,
++			0x55, 0xb8, 0xb3, 0x02, 0x09, 0xb3, 0x1f, 0xe7,
++			0xc9, 0x8d, 0xa3, 0x36, 0x34, 0x8a, 0x77, 0x13,
++			0x30, 0x63, 0x4c, 0xa5, 0xcd, 0xc3, 0xe0, 0x7e,
++			0x05, 0xa1, 0x7b, 0x0c, 0xcb, 0x74, 0x47, 0x31,
++			0x62, 0x03, 0x43, 0xf1, 0x87, 0xb4, 0xb0, 0x85,
++			0x87, 0x8e, 0x4b, 0x25, 0xc7, 0xcf, 0xae, 0x4b,
++			0x36, 0x46, 0x3e, 0x62, 0xbc, 0x6f, 0xeb, 0x5f,
++			0x73, 0xac, 0xe6, 0x07, 0xee, 0xc1, 0xa1, 0xd6,
++			0xc4, 0xab, 0xc9, 0xd6, 0x89, 0x45, 0xe1, 0xf1,
++			0x04, 0x4e, 0x1a, 0x6f, 0xbb, 0x4f, 0x3a, 0xa3,
++			0xa0, 0xcb, 0xa3, 0x0a, 0xd8, 0x71, 0x35, 0x55,
++			0xe4, 0xbc, 0x2e, 0x04, 0x06, 0xe6, 0xff, 0x5b,
++			0x1c, 0xc0, 0x11, 0x7c, 0xc5, 0x17, 0xf3, 0x38,
++			0xcf, 0xe9, 0xba, 0x0f, 0x0e, 0xef, 0x02, 0xc2,
++			0x8d, 0xc6, 0xbc, 0x4b, 0x67, 0x20, 0x95, 0xd7,
++			0x2c, 0x45, 0x5b, 0x86, 0x44, 0x8c, 0x6f, 0x2e,
++			0x7e, 0x9f, 0x1c, 0x77, 0xba, 0x6b, 0x0e, 0xa3,
++			0x69, 0xdc, 0xab, 0x24, 0x57, 0x60, 0x47, 0xc1,
++			0xd1, 0xa5, 0x9d, 0x23, 0xe6, 0xb1, 0x37, 0xfe,
++			0x93, 0xd2, 0x4c, 0x46, 0xf9, 0x0c, 0xc6, 0xfb,
++			0xd6, 0x9d, 0x99, 0x69, 0xab, 0x7a, 0x07, 0x0c,
++			0x65, 0xe7, 0xc4, 0x08, 0x96, 0xe2, 0xa5, 0x01,
++			0x3f, 0x46, 0x07, 0x05, 0x7e, 0xe8, 0x9a, 0x90,
++			0x50, 0xdc, 0xe9, 0x7a, 0xea, 0xa1, 0x39, 0x6e,
++			0x66, 0xe4, 0x6f, 0xa5, 0x5f, 0xb2, 0xd9, 0x5b,
++			0xf5, 0xdb, 0x2a, 0x32, 0xf0, 0x11, 0x6f, 0x7c,
++			0x26, 0x10, 0x8f, 0x3d, 0x80, 0xe9, 0x58, 0xf7,
++			0xe0, 0xa8, 0x57, 0xf8, 0xdb, 0x0e, 0xce, 0x99,
++			0x63, 0x19, 0x3d, 0xd5, 0xec, 0x1b, 0x77, 0x69,
++			0x98, 0xf6, 0xe4, 0x5f, 0x67, 0x17, 0x4b, 0x09,
++			0x85, 0x62, 0x82, 0x70, 0x18, 0xe2, 0x9a, 0x78,
++			0xe2, 0x62, 0xbd, 0xb4, 0xf1, 0x42, 0xc6, 0xfb,
++			0x08, 0xd0, 0xbd, 0xeb, 0x4e, 0x09, 0xf2, 0xc8,
++			0x1e, 0xdc, 0x3d, 0x32, 0x21, 0x56, 0x9c, 0x4f,
++			0x35, 0xf3, 0x61, 0x06, 0x72, 0x84, 0xc4, 0x32,
++			0xf2, 0xf1, 0xfa, 0x0b, 0x2f, 0xc3, 0xdb, 0x02,
++			0x04, 0xc2, 0xde, 0x57, 0x64, 0x60, 0x8d, 0xcf,
++			0xcb, 0x86, 0x5d, 0x97, 0x3e, 0xb1, 0x9c, 0x01,
++			0xd6, 0x28, 0x8f, 0x99, 0xbc, 0x46, 0xeb, 0x05,
++			0xaf, 0x7e, 0xb8, 0x21, 0x2a, 0x56, 0x85, 0x1c,
++			0xb3, 0x71, 0xa0, 0xde, 0xca, 0x96, 0xf1, 0x78,
++			0x49, 0xa2, 0x99, 0x81, 0x80, 0x5c, 0x01, 0xf5,
++			0xa0, 0xa2, 0x56, 0x63, 0xe2, 0x70, 0x07, 0xa5,
++			0x95, 0xd6, 0x85, 0xeb, 0x36, 0x9e, 0xa9, 0x51,
++			0x66, 0x56, 0x5f, 0x1d, 0x02, 0x19, 0xe2, 0xf6,
++			0x4f, 0x73, 0x38, 0x09, 0x75, 0x64, 0x48, 0xe0,
++			0xf1, 0x7e, 0x0e, 0xe8, 0x9d, 0xf9, 0xed, 0x94,
++			0xfe, 0x16, 0x26, 0x62, 0x49, 0x74, 0xf4, 0xb0,
++			0xd4, 0xa9, 0x6c, 0xb0, 0xfd, 0x53, 0xe9, 0x81,
++			0xe0, 0x7a, 0xbf, 0xcf, 0xb5, 0xc4, 0x01, 0x81,
++			0x79, 0x99, 0x77, 0x01, 0x3b, 0xe9, 0xa2, 0xb6,
++			0xe6, 0x6a, 0x8a, 0x9e, 0x56, 0x1c, 0x8d, 0x1e,
++			0x8f, 0x06, 0x55, 0x2c, 0x6c, 0xdc, 0x92, 0x87,
++			0x64, 0x3b, 0x4b, 0x19, 0xa1, 0x13, 0x64, 0x1d,
++			0x4a, 0xe9, 0xc0, 0x00, 0xb8, 0x95, 0xef, 0x6b,
++			0x1a, 0x86, 0x6d, 0x37, 0x52, 0x02, 0xc2, 0xe0,
++			0xc8, 0xbb, 0x42, 0x0c, 0x02, 0x21, 0x4a, 0xc9,
++			0xef, 0xa0, 0x54, 0xe4, 0x5e, 0x16, 0x53, 0x81,
++			0x70, 0x62, 0x10, 0xaf, 0xde, 0xb8, 0xb5, 0xd3,
++			0xe8, 0x5e, 0x6c, 0xc3, 0x8a, 0x3e, 0x18, 0x07,
++			0xf2, 0x2f, 0x7d, 0xa7, 0xe1, 0x3d, 0x4e, 0xb4,
++			0x26, 0xa7, 0xa3, 0x93, 0x86, 0xb2, 0x04, 0x1e,
++			0x53, 0x5d, 0x86, 0xd6, 0xde, 0x65, 0xca, 0xe3,
++			0x4e, 0xc1, 0xcf, 0xef, 0xc8, 0x70, 0x1b, 0x83,
++			0x13, 0xdd, 0x18, 0x8b, 0x0d, 0x76, 0xd2, 0xf6,
++			0x37, 0x7a, 0x93, 0x7a, 0x50, 0x11, 0x9f, 0x96,
++			0x86, 0x25, 0xfd, 0xac, 0xdc, 0xbe, 0x18, 0x93,
++			0x19, 0x6b, 0xec, 0x58, 0x4f, 0xb9, 0x75, 0xa7,
++			0xdd, 0x3f, 0x2f, 0xec, 0xc8, 0x5a, 0x84, 0xab,
++			0xd5, 0xe4, 0x8a, 0x07, 0xf6, 0x4d, 0x23, 0xd6,
++			0x03, 0xfb, 0x03, 0x6a, 0xea, 0x66, 0xbf, 0xd4,
++			0xb1, 0x34, 0xfb, 0x78, 0xe9, 0x55, 0xdc, 0x7c,
++			0x3d, 0x9c, 0xe5, 0x9a, 0xac, 0xc3, 0x7a, 0x80,
++			0x24, 0x6d, 0xa0, 0xef, 0x25, 0x7c, 0xb7, 0xea,
++			0xce, 0x4d, 0x5f, 0x18, 0x60, 0xce, 0x87, 0x22,
++			0x66, 0x2f, 0xd5, 0xdd, 0xdd, 0x02, 0x21, 0x75,
++			0x82, 0xa0, 0x1f, 0x58, 0xc6, 0xd3, 0x62, 0xf7,
++			0x32, 0xd8, 0xaf, 0x1e, 0x07, 0x77, 0x51, 0x96,
++			0xd5, 0x6b, 0x1e, 0x7e, 0x80, 0x02, 0xe8, 0x67,
++			0xea, 0x17, 0x0b, 0x10, 0xd2, 0x3f, 0x28, 0x25,
++			0x4f, 0x05, 0x77, 0x02, 0x14, 0x69, 0xf0, 0x2c,
++			0xbe, 0x0c, 0xf1, 0x74, 0x30, 0xd1, 0xb9, 0x9b,
++			0xfc, 0x8c, 0xbb, 0x04, 0x16, 0xd9, 0xba, 0xc3,
++			0xbc, 0x91, 0x8a, 0xc4, 0x30, 0xa4, 0xb0, 0x12,
++			0x4c, 0x21, 0x87, 0xcb, 0xc9, 0x1d, 0x16, 0x96,
++			0x07, 0x6f, 0x23, 0x54, 0xb9, 0x6f, 0x79, 0xe5,
++			0x64, 0xc0, 0x64, 0xda, 0xb1, 0xae, 0xdd, 0x60,
++			0x6c, 0x1a, 0x9d, 0xd3, 0x04, 0x8e, 0x45, 0xb0,
++			0x92, 0x61, 0xd0, 0x48, 0x81, 0xed, 0x5e, 0x1d,
++			0xa0, 0xc9, 0xa4, 0x33, 0xc7, 0x13, 0x51, 0x5d,
++			0x7f, 0x83, 0x73, 0xb6, 0x70, 0x18, 0x65, 0x3e,
++			0x2f, 0x0e, 0x7a, 0x12, 0x39, 0x98, 0xab, 0xd8,
++			0x7e, 0x6f, 0xa3, 0xd1, 0xba, 0x56, 0xad, 0xbd,
++			0xf0, 0x03, 0x01, 0x1c, 0x85, 0x35, 0x9f, 0xeb,
++			0x19, 0x63, 0xa1, 0xaf, 0xfe, 0x2d, 0x35, 0x50,
++			0x39, 0xa0, 0x65, 0x7c, 0x95, 0x7e, 0x6b, 0xfe,
++			0xc1, 0xac, 0x07, 0x7c, 0x98, 0x4f, 0xbe, 0x57,
++			0xa7, 0x22, 0xec, 0xe2, 0x7e, 0x29, 0x09, 0x53,
++			0xe8, 0xbf, 0xb4, 0x7e, 0x3f, 0x8f, 0xfc, 0x14,
++			0xce, 0x54, 0xf9, 0x18, 0x58, 0xb5, 0xff, 0x44,
++			0x05, 0x9d, 0xce, 0x1b, 0xb6, 0x82, 0x23, 0xc8,
++			0x2e, 0xbc, 0x69, 0xbb, 0x4a, 0x29, 0x0f, 0x65,
++			0x94, 0xf0, 0x63, 0x06, 0x0e, 0xef, 0x8c, 0xbd,
++			0xff, 0xfd, 0xb0, 0x21, 0x6e, 0x57, 0x05, 0x75,
++			0xda, 0xd5, 0xc4, 0xeb, 0x8d, 0x32, 0xf7, 0x50,
++			0xd3, 0x6f, 0x22, 0xed, 0x5f, 0x8e, 0xa2, 0x5b,
++			0x80, 0x8c, 0xc8, 0x78, 0x40, 0x24, 0x4b, 0x89,
++			0x30, 0xce, 0x7a, 0x97, 0x0e, 0xc4, 0xaf, 0xef,
++			0x9b, 0xb4, 0xcd, 0x66, 0x74, 0x14, 0x04, 0x2b,
++			0xf7, 0xce, 0x0b, 0x1c, 0x6e, 0xc2, 0x78, 0x8c,
++			0xca, 0xc5, 0xd0, 0x1c, 0x95, 0x4a, 0x91, 0x2d,
++			0xa7, 0x20, 0xeb, 0x86, 0x52, 0xb7, 0x67, 0xd8,
++			0x0c, 0xd6, 0x04, 0x14, 0xde, 0x51, 0x74, 0x75,
++			0xe7, 0x11, 0xb4, 0x87, 0xa3, 0x3d, 0x2d, 0xad,
++			0x4f, 0xef, 0xa0, 0x0f, 0x70, 0x00, 0x6d, 0x13,
++			0x19, 0x1d, 0x41, 0x50, 0xe9, 0xd8, 0xf0, 0x32,
++			0x71, 0xbc, 0xd3, 0x11, 0xf2, 0xac, 0xbe, 0xaf,
++			0x75, 0x46, 0x65, 0x4e, 0x07, 0x34, 0x37, 0xa3,
++			0x89, 0xfe, 0x75, 0xd4, 0x70, 0x4c, 0xc6, 0x3f,
++			0x69, 0x24, 0x0e, 0x38, 0x67, 0x43, 0x8c, 0xde,
++			0x06, 0xb5, 0xb8, 0xe7, 0xc4, 0xf0, 0x41, 0x8f,
++			0xf0, 0xbd, 0x2f, 0x0b, 0xb9, 0x18, 0xf8, 0xde,
++			0x64, 0xb1, 0xdb, 0xee, 0x00, 0x50, 0x77, 0xe1,
++			0xc7, 0xff, 0xa6, 0xfa, 0xdd, 0x70, 0xf4, 0xe3,
++			0x93, 0xe9, 0x77, 0x35, 0x3d, 0x4b, 0x2f, 0x2b,
++			0x6d, 0x55, 0xf0, 0xfc, 0x88, 0x54, 0x4e, 0x89,
++			0xc1, 0x8a, 0x23, 0x31, 0x2d, 0x14, 0x2a, 0xb8,
++			0x1b, 0x15, 0xdd, 0x9e, 0x6e, 0x7b, 0xda, 0x05,
++			0x91, 0x7d, 0x62, 0x64, 0x96, 0x72, 0xde, 0xfc,
++			0xc1, 0xec, 0xf0, 0x23, 0x51, 0x6f, 0xdb, 0x5b,
++			0x1d, 0x08, 0x57, 0xce, 0x09, 0xb8, 0xf6, 0xcd,
++			0x8d, 0x95, 0xf2, 0x20, 0xbf, 0x0f, 0x20, 0x57,
++			0x98, 0x81, 0x84, 0x4f, 0x15, 0x5c, 0x76, 0xe7,
++			0x3e, 0x0a, 0x3a, 0x6c, 0xc4, 0x8a, 0xbe, 0x78,
++			0x74, 0x77, 0xc3, 0x09, 0x4b, 0x5d, 0x48, 0xe4,
++			0xc8, 0xcb, 0x0b, 0xea, 0x17, 0x28, 0xcf, 0xcf,
++			0x31, 0x32, 0x44, 0xa4, 0xe5, 0x0e, 0x1a, 0x98,
++			0x94, 0xc4, 0xf0, 0xff, 0xae, 0x3e, 0x44, 0xe8,
++			0xa5, 0xb3, 0xb5, 0x37, 0x2f, 0xe8, 0xaf, 0x6f,
++			0x28, 0xc1, 0x37, 0x5f, 0x31, 0xd2, 0xb9, 0x33,
++			0xb1, 0xb2, 0x52, 0x94, 0x75, 0x2c, 0x29, 0x59,
++			0x06, 0xc2, 0x25, 0xe8, 0x71, 0x65, 0x4e, 0xed,
++			0xc0, 0x9c, 0xb1, 0xbb, 0x25, 0xdc, 0x6c, 0xe7,
++			0x4b, 0xa5, 0x7a, 0x54, 0x7a, 0x60, 0xff, 0x7a,
++			0xe0, 0x50, 0x40, 0x96, 0x35, 0x63, 0xe4, 0x0b,
++			0x76, 0xbd, 0xa4, 0x65, 0x00, 0x1b, 0x57, 0x88,
++			0xae, 0xed, 0x39, 0x88, 0x42, 0x11, 0x3c, 0xed,
++			0x85, 0x67, 0x7d, 0xb9, 0x68, 0x82, 0xe9, 0x43,
++			0x3c, 0x47, 0x53, 0xfa, 0xe8, 0xf8, 0x9f, 0x1f,
++			0x9f, 0xef, 0x0f, 0xf7, 0x30, 0xd9, 0x30, 0x0e,
++			0xb9, 0x9f, 0x69, 0x18, 0x2f, 0x7e, 0xf8, 0xf8,
++			0xf8, 0x8c, 0x0f, 0xd4, 0x02, 0x4d, 0xea, 0xcd,
++			0x0a, 0x9c, 0x6f, 0x71, 0x6d, 0x5a, 0x4c, 0x60,
++			0xce, 0x20, 0x56, 0x32, 0xc6, 0xc5, 0x99, 0x1f,
++			0x09, 0xe6, 0x4e, 0x18, 0x1a, 0x15, 0x13, 0xa8,
++			0x7d, 0xb1, 0x6b, 0xc0, 0xb2, 0x6d, 0xf8, 0x26,
++			0x66, 0xf8, 0x3d, 0x18, 0x74, 0x70, 0x66, 0x7a,
++			0x34, 0x17, 0xde, 0xba, 0x47, 0xf1, 0x06, 0x18,
++			0xcb, 0xaf, 0xeb, 0x4a, 0x1e, 0x8f, 0xa7, 0x77,
++			0xe0, 0x3b, 0x78, 0x62, 0x66, 0xc9, 0x10, 0xea,
++			0x1f, 0xb7, 0x29, 0x0a, 0x45, 0xa1, 0x1d, 0x1e,
++			0x1d, 0xe2, 0x65, 0x61, 0x50, 0x9c, 0xd7, 0x05,
++			0xf2, 0x0b, 0x5b, 0x12, 0x61, 0x02, 0xc8, 0xe5,
++			0x63, 0x4f, 0x20, 0x0c, 0x07, 0x17, 0x33, 0x5e,
++			0x03, 0x9a, 0x53, 0x0f, 0x2e, 0x55, 0xfe, 0x50,
++			0x43, 0x7d, 0xd0, 0xb6, 0x7e, 0x5a, 0xda, 0xae,
++			0x58, 0xef, 0x15, 0xa9, 0x83, 0xd9, 0x46, 0xb1,
++			0x42, 0xaa, 0xf5, 0x02, 0x6c, 0xce, 0x92, 0x06,
++			0x1b, 0xdb, 0x66, 0x45, 0x91, 0x79, 0xc2, 0x2d,
++			0xe6, 0x53, 0xd3, 0x14, 0xfd, 0xbb, 0x44, 0x63,
++			0xc6, 0xd7, 0x3d, 0x7a, 0x0c, 0x75, 0x78, 0x9d,
++			0x5c, 0xa6, 0x39, 0xb3, 0xe5, 0x63, 0xca, 0x8b,
++			0xfe, 0xd3, 0xef, 0x60, 0x83, 0xf6, 0x8e, 0x70,
++			0xb6, 0x67, 0xc7, 0x77, 0xed, 0x23, 0xef, 0x4c,
++			0xf0, 0xed, 0x2d, 0x07, 0x59, 0x6f, 0xc1, 0x01,
++			0x34, 0x37, 0x08, 0xab, 0xd9, 0x1f, 0x09, 0xb1,
++			0xce, 0x5b, 0x17, 0xff, 0x74, 0xf8, 0x9c, 0xd5,
++			0x2c, 0x56, 0x39, 0x79, 0x0f, 0x69, 0x44, 0x75,
++			0x58, 0x27, 0x01, 0xc4, 0xbf, 0xa7, 0xa1, 0x1d,
++			0x90, 0x17, 0x77, 0x86, 0x5a, 0x3f, 0xd9, 0xd1,
++			0x0e, 0xa0, 0x10, 0xf8, 0xec, 0x1e, 0xa5, 0x7f,
++			0x5e, 0x36, 0xd1, 0xe3, 0x04, 0x2c, 0x70, 0xf7,
++			0x8e, 0xc0, 0x98, 0x2f, 0x6c, 0x94, 0x2b, 0x41,
++			0xb7, 0x60, 0x00, 0xb7, 0x2e, 0xb8, 0x02, 0x8d,
++			0xb8, 0xb0, 0xd3, 0x86, 0xba, 0x1d, 0xd7, 0x90,
++			0xd6, 0xb6, 0xe1, 0xfc, 0xd7, 0xd8, 0x28, 0x06,
++			0x63, 0x9b, 0xce, 0x61, 0x24, 0x79, 0xc0, 0x70,
++			0x52, 0xd0, 0xb6, 0xd4, 0x28, 0x95, 0x24, 0x87,
++			0x03, 0x1f, 0xb7, 0x9a, 0xda, 0xa3, 0xfb, 0x52,
++			0x5b, 0x68, 0xe7, 0x4c, 0x8c, 0x24, 0xe1, 0x42,
++			0xf7, 0xd5, 0xfd, 0xad, 0x06, 0x32, 0x9f, 0xba,
++			0xc1, 0xfc, 0xdd, 0xc6, 0xfc, 0xfc, 0xb3, 0x38,
++			0x74, 0x56, 0x58, 0x40, 0x02, 0x37, 0x52, 0x2c,
++			0x55, 0xcc, 0xb3, 0x9e, 0x7a, 0xe9, 0xd4, 0x38,
++			0x41, 0x5e, 0x0c, 0x35, 0xe2, 0x11, 0xd1, 0x13,
++			0xf8, 0xb7, 0x8d, 0x72, 0x6b, 0x22, 0x2a, 0xb0,
++			0xdb, 0x08, 0xba, 0x35, 0xb9, 0x3f, 0xc8, 0xd3,
++			0x24, 0x90, 0xec, 0x58, 0xd2, 0x09, 0xc7, 0x2d,
++			0xed, 0x38, 0x80, 0x36, 0x72, 0x43, 0x27, 0x49,
++			0x4a, 0x80, 0x8a, 0xa2, 0xe8, 0xd3, 0xda, 0x30,
++			0x7d, 0xb6, 0x82, 0x37, 0x86, 0x92, 0x86, 0x3e,
++			0x08, 0xb2, 0x28, 0x5a, 0x55, 0x44, 0x24, 0x7d,
++			0x40, 0x48, 0x8a, 0xb6, 0x89, 0x58, 0x08, 0xa0,
++			0xd6, 0x6d, 0x3a, 0x17, 0xbf, 0xf6, 0x54, 0xa2,
++			0xf5, 0xd3, 0x8c, 0x0f, 0x78, 0x12, 0x57, 0x8b,
++			0xd5, 0xc2, 0xfd, 0x58, 0x5b, 0x7f, 0x38, 0xe3,
++			0xcc, 0xb7, 0x7c, 0x48, 0xb3, 0x20, 0xe8, 0x81,
++			0x14, 0x32, 0x45, 0x05, 0xe0, 0xdb, 0x9f, 0x75,
++			0x85, 0xb4, 0x6a, 0xfc, 0x95, 0xe3, 0x54, 0x22,
++			0x12, 0xee, 0x30, 0xfe, 0xd8, 0x30, 0xef, 0x34,
++			0x50, 0xab, 0x46, 0x30, 0x98, 0x2f, 0xb7, 0xc0,
++			0x15, 0xa2, 0x83, 0xb6, 0xf2, 0x06, 0x21, 0xa2,
++			0xc3, 0x26, 0x37, 0x14, 0xd1, 0x4d, 0xb5, 0x10,
++			0x52, 0x76, 0x4d, 0x6a, 0xee, 0xb5, 0x2b, 0x15,
++			0xb7, 0xf9, 0x51, 0xe8, 0x2a, 0xaf, 0xc7, 0xfa,
++			0x77, 0xaf, 0xb0, 0x05, 0x4d, 0xd1, 0x68, 0x8e,
++			0x74, 0x05, 0x9f, 0x9d, 0x93, 0xa5, 0x3e, 0x7f,
++			0x4e, 0x5f, 0x9d, 0xcb, 0x09, 0xc7, 0x83, 0xe3,
++			0x02, 0x9d, 0x27, 0x1f, 0xef, 0x85, 0x05, 0x8d,
++			0xec, 0x55, 0x88, 0x0f, 0x0d, 0x7c, 0x4c, 0xe8,
++			0xa1, 0x75, 0xa0, 0xd8, 0x06, 0x47, 0x14, 0xef,
++			0xaa, 0x61, 0xcf, 0x26, 0x15, 0xad, 0xd8, 0xa3,
++			0xaa, 0x75, 0xf2, 0x78, 0x4a, 0x5a, 0x61, 0xdf,
++			0x8b, 0xc7, 0x04, 0xbc, 0xb2, 0x32, 0xd2, 0x7e,
++			0x42, 0xee, 0xb4, 0x2f, 0x51, 0xff, 0x7b, 0x2e,
++			0xd3, 0x02, 0xe8, 0xdc, 0x5d, 0x0d, 0x50, 0xdc,
++			0xae, 0xb7, 0x46, 0xf9, 0xa8, 0xe6, 0xd0, 0x16,
++			0xcc, 0xe6, 0x2c, 0x81, 0xc7, 0xad, 0xe9, 0xf0,
++			0x05, 0x72, 0x6d, 0x3d, 0x0a, 0x7a, 0xa9, 0x02,
++			0xac, 0x82, 0x93, 0x6e, 0xb6, 0x1c, 0x28, 0xfc,
++			0x44, 0x12, 0xfb, 0x73, 0x77, 0xd4, 0x13, 0x39,
++			0x29, 0x88, 0x8a, 0xf3, 0x5c, 0xa6, 0x36, 0xa0,
++			0x2a, 0xed, 0x7e, 0xb1, 0x1d, 0xd6, 0x4c, 0x6b,
++			0x41, 0x01, 0x18, 0x5d, 0x5d, 0x07, 0x97, 0xa6,
++			0x4b, 0xef, 0x31, 0x18, 0xea, 0xac, 0xb1, 0x84,
++			0x21, 0xed, 0xda, 0x86,
++		},
++		.rlen = 4100,
++	},
++};
 +
-+static struct crypto_template crypto_ccm_base_tmpl = {
-+	.name = "ccm_base",
-+	.alloc = crypto_ccm_base_alloc,
-+	.free = crypto_ccm_free,
-+	.module = THIS_MODULE,
++static struct cipher_testvec aes_ctr_dec_tv_template[] = {
++	{ /* From RFC 3686 */
++		.key	= { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
++			    0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
++			    0x00, 0x00, 0x00, 0x30 },
++		.klen	= 20,
++		.iv 	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
++			    0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
++		.ilen	= 16,
++		.result	= { "Single block msg" },
++		.rlen	= 16,
++	}, {
++		.key	= { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
++			    0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
++			    0x00, 0x6c, 0xb6, 0xdb },
++		.klen	= 20,
++		.iv 	= { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
++		.input	= { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
++			    0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
++			    0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
++			    0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
++		.ilen 	= 32,
++		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.rlen	= 32,
++	}, {
++		.key 	= { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
++			    0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
++			    0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
++			    0x00, 0x00, 0x00, 0x48 },
++		.klen 	= 28,
++		.iv	= { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
++		.input	= { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
++			    0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
++		.ilen 	= 16,
++		.result	= { "Single block msg" },
++		.rlen	= 16,
++	}, {
++		.key	= { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
++			    0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
++			    0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
++			    0x00, 0x96, 0xb0, 0x3b },
++		.klen	= 28,
++		.iv 	= { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
++		.input	= { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
++			    0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
++			    0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
++			    0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
++		.ilen	= 32,
++		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.rlen 	= 32,
++	}, { 
++		.key 	= { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
++			    0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
++			    0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
++			    0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
++			    0x00, 0x00, 0x00, 0x60 },
++		.klen	= 36,
++		.iv 	= { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
++		.input	= { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
++			    0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
++		.ilen	= 16,
++		.result	= { "Single block msg" },
++		.rlen 	= 16,
++	}, {
++		.key	= { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
++			    0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
++			    0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
++			    0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
++			    0x00, 0xfa, 0xac, 0x24 },
++		.klen 	= 36,
++		.iv	= { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
++		.input	= { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
++			    0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
++			    0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
++			    0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
++		.ilen	= 32,
++		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
++		.rlen	= 32,
++	},
 +};
 +
-+static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
-+				 unsigned int keylen)
-+{
-+	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
-+	struct crypto_aead *child = ctx->child;
-+	int err;
-+
-+	if (keylen < 3)
-+		return -EINVAL;
-+
-+	keylen -= 3;
-+	memcpy(ctx->nonce, key + keylen, 3);
-+
-+	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-+	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
-+				     CRYPTO_TFM_REQ_MASK);
-+	err = crypto_aead_setkey(child, key, keylen);
-+	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
-+				      CRYPTO_TFM_RES_MASK);
-+
-+	return err;
-+}
-+
-+static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
-+				      unsigned int authsize)
-+{
-+	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
-+
-+	switch (authsize) {
-+	case 8:
-+	case 12:
-+	case 16:
-+		break;
-+	default:
-+		return -EINVAL;
++static struct aead_testvec aes_gcm_enc_tv_template[] = {
++	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
++		.klen	= 16,
++		.result	= { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
++			    0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
++		.rlen	= 16,
++	}, {
++		.klen	= 16,
++		.ilen	= 16,
++		.result = { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
++			    0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
++			    0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
++			    0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
++		.rlen	= 32,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.klen	= 16,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.ilen	= 64,
++		.result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
++			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
++			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
++			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
++			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
++			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
++			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
++			    0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
++			    0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
++			    0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
++		.rlen	= 80,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.klen	= 16,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39 },
++		.ilen	= 60,
++		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xab, 0xad, 0xda, 0xd2 },
++		.alen	= 20,
++		.result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
++			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
++			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
++			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
++			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
++			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
++			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
++			    0x3d, 0x58, 0xe0, 0x91,
++			    0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
++			    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
++		.rlen	= 76,
++	}, {
++		.klen	= 24,
++		.result	= { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
++			    0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
++		.rlen	= 16,
++	}, {
++		.klen	= 24,
++		.ilen	= 16,
++		.result = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
++			    0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
++			    0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
++			    0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
++		.rlen	= 32,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
++			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.klen	= 24,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.ilen	= 64,
++		.result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
++			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
++			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
++			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
++			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
++			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
++			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
++			    0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
++			    0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
++			    0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
++		.rlen	= 80,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
++			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.klen	= 24,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39 },
++		.ilen	= 60,
++		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xab, 0xad, 0xda, 0xd2 },
++		.alen	= 20,
++		.result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
++			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
++			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
++			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
++			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
++			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
++			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
++			    0xcc, 0xda, 0x27, 0x10,
++			    0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
++			    0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
++		.rlen	= 76,
++		.np	= 2,
++		.tap	= { 32, 28 },
++		.anp	= 2,
++		.atap	= { 8, 12 }
++	}, {
++		.klen	= 32,
++		.result	= { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
++			    0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
++		.rlen	= 16,
 +	}
++};
 +
-+	return crypto_aead_setauthsize(ctx->child, authsize);
-+}
-+
-+static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
-+{
-+	struct aead_request *subreq = aead_request_ctx(req);
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_aead *child = ctx->child;
-+	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
-+			   crypto_aead_alignmask(child) + 1);
-+
-+	/* L' */
-+	iv[0] = 3;
-+
-+	memcpy(iv + 1, ctx->nonce, 3);
-+	memcpy(iv + 4, req->iv, 8);
-+
-+	aead_request_set_tfm(subreq, child);
-+	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
-+				  req->base.data);
-+	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
-+	aead_request_set_assoc(subreq, req->assoc, req->assoclen);
-+
-+	return subreq;
-+}
-+
-+static int crypto_rfc4309_encrypt(struct aead_request *req)
-+{
-+	req = crypto_rfc4309_crypt(req);
-+
-+	return crypto_aead_encrypt(req);
-+}
-+
-+static int crypto_rfc4309_decrypt(struct aead_request *req)
-+{
-+	req = crypto_rfc4309_crypt(req);
-+
-+	return crypto_aead_decrypt(req);
-+}
-+
-+static int crypto_rfc4309_init_tfm(struct crypto_tfm *tfm)
-+{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
-+	struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_aead *aead;
-+	unsigned long align;
-+
-+	aead = crypto_spawn_aead(spawn);
-+	if (IS_ERR(aead))
-+		return PTR_ERR(aead);
-+
-+	ctx->child = aead;
-+
-+	align = crypto_aead_alignmask(aead);
-+	align &= ~(crypto_tfm_ctx_alignment() - 1);
-+	tfm->crt_aead.reqsize = sizeof(struct aead_request) +
-+				ALIGN(crypto_aead_reqsize(aead),
-+				      crypto_tfm_ctx_alignment()) +
-+				align + 16;
-+
-+	return 0;
-+}
-+
-+static void crypto_rfc4309_exit_tfm(struct crypto_tfm *tfm)
-+{
-+	struct crypto_rfc4309_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	crypto_free_aead(ctx->child);
-+}
-+
-+static struct crypto_instance *crypto_rfc4309_alloc(struct rtattr **tb)
-+{
-+	struct crypto_attr_type *algt;
-+	struct crypto_instance *inst;
-+	struct crypto_aead_spawn *spawn;
-+	struct crypto_alg *alg;
-+	const char *ccm_name;
-+	int err;
-+
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
-+		return ERR_PTR(err);
-+
-+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-+		return ERR_PTR(-EINVAL);
-+
-+	ccm_name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(ccm_name);
-+	if (IS_ERR(ccm_name))
-+		return ERR_PTR(err);
-+
-+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
-+	if (!inst)
-+		return ERR_PTR(-ENOMEM);
-+
-+	spawn = crypto_instance_ctx(inst);
-+	crypto_set_aead_spawn(spawn, inst);
-+	err = crypto_grab_aead(spawn, ccm_name, 0,
-+			       crypto_requires_sync(algt->type, algt->mask));
-+	if (err)
-+		goto out_free_inst;
-+
-+	alg = crypto_aead_spawn_alg(spawn);
-+
-+	err = -EINVAL;
-+
-+	/* We only support 16-byte blocks. */
-+	if (alg->cra_aead.ivsize != 16)
-+		goto out_drop_alg;
-+
-+	/* Not a stream cipher? */
-+	if (alg->cra_blocksize != 1)
-+		goto out_drop_alg;
-+
-+	err = -ENAMETOOLONG;
-+	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-+		     "rfc4309(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
-+	    snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+		     "rfc4309(%s)", alg->cra_driver_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		goto out_drop_alg;
-+
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-+	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_priority = alg->cra_priority;
-+	inst->alg.cra_blocksize = 1;
-+	inst->alg.cra_alignmask = alg->cra_alignmask;
-+	inst->alg.cra_type = &crypto_nivaead_type;
-+
-+	inst->alg.cra_aead.ivsize = 8;
-+	inst->alg.cra_aead.maxauthsize = 16;
-+
-+	inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
-+
-+	inst->alg.cra_init = crypto_rfc4309_init_tfm;
-+	inst->alg.cra_exit = crypto_rfc4309_exit_tfm;
-+
-+	inst->alg.cra_aead.setkey = crypto_rfc4309_setkey;
-+	inst->alg.cra_aead.setauthsize = crypto_rfc4309_setauthsize;
-+	inst->alg.cra_aead.encrypt = crypto_rfc4309_encrypt;
-+	inst->alg.cra_aead.decrypt = crypto_rfc4309_decrypt;
-+
-+	inst->alg.cra_aead.geniv = "seqiv";
-+
-+out:
-+	return inst;
-+
-+out_drop_alg:
-+	crypto_drop_aead(spawn);
-+out_free_inst:
-+	kfree(inst);
-+	inst = ERR_PTR(err);
-+	goto out;
-+}
++static struct aead_testvec aes_gcm_dec_tv_template[] = {
++	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
++		.klen	= 32,
++		.input	= { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
++			    0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18,
++			    0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
++			    0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
++		.ilen	= 32,
++		.rlen	= 16,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
++			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.klen	= 32,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
++			    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
++			    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
++			    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
++			    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
++			    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
++			    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
++			    0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
++			    0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
++			    0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
++		.ilen	= 80,
++		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.rlen	= 64,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
++			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.klen	= 32,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
++			    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
++			    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
++			    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
++			    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
++			    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
++			    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
++			    0xbc, 0xc9, 0xf6, 0x62,
++			    0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
++			    0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
++		.ilen	= 76,
++		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xab, 0xad, 0xda, 0xd2 },
++		.alen	= 20,
++		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39 },
++		.rlen	= 60,
++		.np     = 2,
++		.tap    = { 48, 28 },
++		.anp	= 3,
++		.atap	= { 8, 8, 4 }
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.klen	= 16,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
++			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
++			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
++			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
++			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
++			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
++			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
++			    0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
++			    0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
++			    0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
++		.ilen	= 80,
++		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.rlen	= 64,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
++		.klen	= 16,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
++			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
++			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
++			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
++			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
++			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
++			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
++			    0x3d, 0x58, 0xe0, 0x91,
++			    0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
++			    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
++		.ilen	= 76,
++		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xab, 0xad, 0xda, 0xd2 },
++		.alen	= 20,
++		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39 },
++		.rlen	= 60,
++	}, {
++		.klen	= 24,
++		.input	= { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
++			    0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
++			    0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
++			    0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
++		.ilen	= 32,
++		.rlen	= 16,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
++			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.klen	= 24,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
++			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
++			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
++			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
++			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
++			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
++			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
++			    0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
++			    0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
++			    0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
++		.ilen	= 80,
++		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
++		.rlen	= 64,
++	}, {
++		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
++			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
++			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
++		.klen	= 24,
++		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
++			    0xde, 0xca, 0xf8, 0x88 },
++		.input	= { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
++			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
++			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
++			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
++			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
++			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
++			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
++			    0xcc, 0xda, 0x27, 0x10,
++			    0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
++			    0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
++		.ilen	= 76,
++		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
++			    0xab, 0xad, 0xda, 0xd2 },
++		.alen	= 20,
++		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
++			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
++			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
++			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
++			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
++			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
++			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
++			    0xba, 0x63, 0x7b, 0x39 },
++		.rlen	= 60,
++	}
++};
 +
-+static void crypto_rfc4309_free(struct crypto_instance *inst)
-+{
-+	crypto_drop_spawn(crypto_instance_ctx(inst));
-+	kfree(inst);
-+}
++static struct aead_testvec aes_ccm_enc_tv_template[] = {
++	{ /* From RFC 3610 */
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.alen	= 8,
++		.input	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
++		.ilen	= 23,
++		.result	= { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
++			    0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
++			    0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
++			    0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
++		.rlen	= 31,
++	}, {
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b },
++		.alen	= 12,
++		.input	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
++			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
++			    0x1c, 0x1d, 0x1e, 0x1f },
++		.ilen	= 20,
++		.result	= { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
++			    0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
++			    0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
++			    0x7d, 0x9c, 0x2d, 0x93 },
++		.rlen	= 28,
++	}, {
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.alen	= 8,
++		.input	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++			    0x20 },
++		.ilen	= 25,
++		.result	= { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
++			    0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
++			    0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
++			    0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
++			    0x7e, 0x5f, 0x4e },
++		.rlen	= 35,
++	}, {
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b },
++		.alen	= 12,
++		.input	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
++			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
++			    0x1c, 0x1d, 0x1e },
++		.ilen	= 19,
++		.result	= { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
++			    0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
++			    0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
++			    0x4d, 0x99, 0x99, 0x88, 0xdd },
++		.rlen	= 29,
++	}, {
++		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
++			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
++			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
++		.assoc	= { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
++		.alen	= 8,
++		.input	= { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
++			    0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
++			    0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
++		.ilen	= 24,
++		.result	= { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
++			    0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
++			    0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
++			    0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
++		.rlen	= 32,
++	}, {
++		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
++			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
++			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
++		.assoc	= { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
++			    0x20, 0xea, 0x60, 0xc0 },
++		.alen	= 12,
++		.input	= { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
++			    0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
++			    0x3a, 0x80, 0x3b, 0xa8, 0x7f },
++		.ilen	= 21,
++		.result	= { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
++			    0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
++			    0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
++			    0x5a, 0xe0, 0x70, 0x45, 0x51 },
++		.rlen	= 29,
++	}, {
++		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
++			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
++			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
++		.assoc	= { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
++		.alen	= 8,
++		.input	= { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
++			    0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
++			    0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
++		.ilen	= 23,
++		.result	= { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
++			    0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
++			    0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
++			    0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
++			    0xba },
++		.rlen	= 33,
++	},
++};
 +
-+static struct crypto_template crypto_rfc4309_tmpl = {
-+	.name = "rfc4309",
-+	.alloc = crypto_rfc4309_alloc,
-+	.free = crypto_rfc4309_free,
-+	.module = THIS_MODULE,
++static struct aead_testvec aes_ccm_dec_tv_template[] = {
++	{ /* From RFC 3610 */
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.alen	= 8,
++		.input	= { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
++			    0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
++			    0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
++			    0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
++		.ilen	= 31,
++		.result	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
++		.rlen	= 23,
++	}, {
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b },
++		.alen	= 12,
++		.input	= { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
++			    0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
++			    0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
++			    0x7d, 0x9c, 0x2d, 0x93 },
++		.ilen	= 28,
++		.result	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
++			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
++			    0x1c, 0x1d, 0x1e, 0x1f },
++		.rlen	= 20,
++	}, {
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
++		.alen	= 8,
++		.input	= { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
++			    0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
++			    0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
++			    0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
++			    0x7e, 0x5f, 0x4e },
++		.ilen	= 35,
++		.result	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++			    0x20 },
++		.rlen	= 25,
++	}, {
++		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
++			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
++		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0a, 0x0b },
++		.alen	= 12,
++		.input	= { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
++			    0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
++			    0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
++			    0x4d, 0x99, 0x99, 0x88, 0xdd },
++		.ilen	= 29,
++		.result	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
++			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
++			    0x1c, 0x1d, 0x1e },
++		.rlen	= 19,
++	}, {
++		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
++			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
++			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
++		.assoc	= { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
++		.alen	= 8,
++		.input	= { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
++			    0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
++			    0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
++			    0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
++		.ilen	= 32,
++		.result	= { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
++			    0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
++			    0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
++		.rlen	= 24,
++	}, {
++		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
++			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
++			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
++		.assoc	= { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
++			    0x20, 0xea, 0x60, 0xc0 },
++		.alen	= 12,
++		.input	= { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
++			    0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
++			    0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
++			    0x5a, 0xe0, 0x70, 0x45, 0x51 },
++		.ilen	= 29,
++		.result	= { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
++			    0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
++			    0x3a, 0x80, 0x3b, 0xa8, 0x7f },
++		.rlen	= 21,
++	}, {
++		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
++			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
++		.klen	= 16,
++		.iv	= { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
++			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
++		.assoc	= { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
++		.alen	= 8,
++		.input	= { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
++			    0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
++			    0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
++			    0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
++			    0xba },
++		.ilen	= 33,
++		.result	= { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
++			    0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
++			    0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
++		.rlen	= 23,
++	},
 +};
 +
-+static int __init crypto_ccm_module_init(void)
-+{
-+	int err;
+ /* Cast5 test vectors from RFC 2144 */
+ #define CAST5_ENC_TEST_VECTORS	3
+ #define CAST5_DEC_TEST_VECTORS	3
+@@ -4317,6 +6425,1211 @@ static struct cipher_testvec seed_dec_tv_template[] = {
+ 	}
+ };
+ 
++#define SALSA20_STREAM_ENC_TEST_VECTORS 5
++static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
++	/*
++	* Testvectors from verified.test-vectors submitted to ECRYPT.
++	* They are truncated to size 39, 64, 111, 129 to test a variety
++	* of input length.
++	*/
++	{ /* Set 3, vector 0 */
++		.key	= {
++			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
++			  },
++		.klen	= 16,
++		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= {
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			  },
++		.ilen	= 39,
++		.result	= {
++			    0x2D, 0xD5, 0xC3, 0xF7, 0xBA, 0x2B, 0x20, 0xF7,
++                            0x68, 0x02, 0x41, 0x0C, 0x68, 0x86, 0x88, 0x89,
++                            0x5A, 0xD8, 0xC1, 0xBD, 0x4E, 0xA6, 0xC9, 0xB1,
++                            0x40, 0xFB, 0x9B, 0x90, 0xE2, 0x10, 0x49, 0xBF,
++                            0x58, 0x3F, 0x52, 0x79, 0x70, 0xEB, 0xC1,
++			},
++		.rlen	= 39,
++	}, { /* Set 5, vector 0 */
++		.key	= {
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++			  },
++		.klen	= 16,
++		.iv     = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= {
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			  },
++		.ilen	= 64,
++		.result	= {
++			    0xB6, 0x6C, 0x1E, 0x44, 0x46, 0xDD, 0x95, 0x57,
++                            0xE5, 0x78, 0xE2, 0x23, 0xB0, 0xB7, 0x68, 0x01,
++                            0x7B, 0x23, 0xB2, 0x67, 0xBB, 0x02, 0x34, 0xAE,
++                            0x46, 0x26, 0xBF, 0x44, 0x3F, 0x21, 0x97, 0x76,
++                            0x43, 0x6F, 0xB1, 0x9F, 0xD0, 0xE8, 0x86, 0x6F,
++                            0xCD, 0x0D, 0xE9, 0xA9, 0x53, 0x8F, 0x4A, 0x09,
++                            0xCA, 0x9A, 0xC0, 0x73, 0x2E, 0x30, 0xBC, 0xF9,
++                            0x8E, 0x4F, 0x13, 0xE4, 0xB9, 0xE2, 0x01, 0xD9,
++			  },
++		.rlen	= 64,
++	}, { /* Set 3, vector 27 */
++		.key	= {
++			    0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
++			    0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
++                            0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
++			    0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
++			  },
++		.klen	= 32,
++		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
++		.input	= {
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +
-+	err = crypto_register_template(&crypto_ccm_base_tmpl);
-+	if (err)
-+		goto out;
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			  },
++		.ilen	= 111,
++		.result	= {
++			    0xAE, 0x39, 0x50, 0x8E, 0xAC, 0x9A, 0xEC, 0xE7,
++                            0xBF, 0x97, 0xBB, 0x20, 0xB9, 0xDE, 0xE4, 0x1F,
++                            0x87, 0xD9, 0x47, 0xF8, 0x28, 0x91, 0x35, 0x98,
++                            0xDB, 0x72, 0xCC, 0x23, 0x29, 0x48, 0x56, 0x5E,
++                            0x83, 0x7E, 0x0B, 0xF3, 0x7D, 0x5D, 0x38, 0x7B,
++                            0x2D, 0x71, 0x02, 0xB4, 0x3B, 0xB5, 0xD8, 0x23,
++                            0xB0, 0x4A, 0xDF, 0x3C, 0xEC, 0xB6, 0xD9, 0x3B,
++                            0x9B, 0xA7, 0x52, 0xBE, 0xC5, 0xD4, 0x50, 0x59,
 +
-+	err = crypto_register_template(&crypto_ccm_tmpl);
-+	if (err)
-+		goto out_undo_base;
++                            0x15, 0x14, 0xB4, 0x0E, 0x40, 0xE6, 0x53, 0xD1,
++                            0x83, 0x9C, 0x5B, 0xA0, 0x92, 0x29, 0x6B, 0x5E,
++                            0x96, 0x5B, 0x1E, 0x2F, 0xD3, 0xAC, 0xC1, 0x92,
++                            0xB1, 0x41, 0x3F, 0x19, 0x2F, 0xC4, 0x3B, 0xC6,
++                            0x95, 0x46, 0x45, 0x54, 0xE9, 0x75, 0x03, 0x08,
++                            0x44, 0xAF, 0xE5, 0x8A, 0x81, 0x12, 0x09,
++			  },
++		.rlen	= 111,
 +
-+	err = crypto_register_template(&crypto_rfc4309_tmpl);
-+	if (err)
-+		goto out_undo_ccm;
++	}, { /* Set 5, vector 27 */
++		.key	= {
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++			  },
++		.klen	= 32,
++		.iv     = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 },
++		.input	= {
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +
-+out:
-+	return err;
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 +
-+out_undo_ccm:
-+	crypto_unregister_template(&crypto_ccm_tmpl);
-+out_undo_base:
-+	crypto_unregister_template(&crypto_ccm_base_tmpl);
-+	goto out;
-+}
++			    0x00,
++			  },
++		.ilen	= 129,
++		.result	= {
++			    0xD2, 0xDB, 0x1A, 0x5C, 0xF1, 0xC1, 0xAC, 0xDB,
++                            0xE8, 0x1A, 0x7A, 0x43, 0x40, 0xEF, 0x53, 0x43,
++                            0x5E, 0x7F, 0x4B, 0x1A, 0x50, 0x52, 0x3F, 0x8D,
++                            0x28, 0x3D, 0xCF, 0x85, 0x1D, 0x69, 0x6E, 0x60,
++                            0xF2, 0xDE, 0x74, 0x56, 0x18, 0x1B, 0x84, 0x10,
++                            0xD4, 0x62, 0xBA, 0x60, 0x50, 0xF0, 0x61, 0xF2,
++                            0x1C, 0x78, 0x7F, 0xC1, 0x24, 0x34, 0xAF, 0x58,
++                            0xBF, 0x2C, 0x59, 0xCA, 0x90, 0x77, 0xF3, 0xB0,
 +
-+static void __exit crypto_ccm_module_exit(void)
-+{
-+	crypto_unregister_template(&crypto_rfc4309_tmpl);
-+	crypto_unregister_template(&crypto_ccm_tmpl);
-+	crypto_unregister_template(&crypto_ccm_base_tmpl);
-+}
++                            0x5B, 0x4A, 0xDF, 0x89, 0xCE, 0x2C, 0x2F, 0xFC,
++                            0x67, 0xF0, 0xE3, 0x45, 0xE8, 0xB3, 0xB3, 0x75,
++                            0xA0, 0x95, 0x71, 0xA1, 0x29, 0x39, 0x94, 0xCA,
++                            0x45, 0x2F, 0xBD, 0xCB, 0x10, 0xB6, 0xBE, 0x9F,
++                            0x8E, 0xF9, 0xB2, 0x01, 0x0A, 0x5A, 0x0A, 0xB7,
++                            0x6B, 0x9D, 0x70, 0x8E, 0x4B, 0xD6, 0x2F, 0xCD,
++                            0x2E, 0x40, 0x48, 0x75, 0xE9, 0xE2, 0x21, 0x45,
++                            0x0B, 0xC9, 0xB6, 0xB5, 0x66, 0xBC, 0x9A, 0x59,
 +
-+module_init(crypto_ccm_module_init);
-+module_exit(crypto_ccm_module_exit);
++                            0x5A,
++			  },
++		.rlen	= 129,
++	}, { /* large test vector generated using Crypto++ */
++		.key = {
++			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++		},
++		.klen = 32,
++		.iv = {
++			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++		},
++		.input = {
++			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
++			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
++			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
++			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
++			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
++			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
++			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
++			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
++			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
++			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
++			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
++			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
++			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
++			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
++			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
++			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
++			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
++			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
++			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
++			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
++			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
++			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
++			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
++			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
++			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
++			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
++			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
++			0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
++			0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
++			0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
++			0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
++			0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
++			0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
++			0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
++			0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
++			0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
++			0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
++			0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
++			0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
++			0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
++			0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
++			0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
++			0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
++			0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
++			0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
++			0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
++			0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
++			0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
++			0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
++			0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
++			0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
++			0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
++			0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
++			0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
++			0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
++			0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
++			0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
++			0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
++			0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
++			0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
++			0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
++			0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
++			0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
++			0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
++			0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
++			0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
++			0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
++			0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
++			0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
++			0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
++			0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
++			0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
++			0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
++			0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
++			0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
++			0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
++			0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
++			0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
++			0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
++			0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
++			0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
++			0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
++			0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
++			0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
++			0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
++			0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
++			0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
++			0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
++			0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
++			0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
++			0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
++			0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
++			0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
++			0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
++			0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
++			0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
++			0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
++			0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
++			0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
++			0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
++			0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
++			0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
++			0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
++			0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
++			0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
++			0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
++			0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
++			0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
++			0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
++			0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
++			0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
++			0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
++			0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
++			0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
++			0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
++			0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
++			0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
++			0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
++			0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
++			0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
++			0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
++			0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
++			0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
++			0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
++			0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
++			0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
++			0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
++			0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
++			0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
++			0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
++			0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
++			0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
++			0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
++			0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
++			0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
++			0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
++			0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
++			0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
++			0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
++			0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
++			0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
++			0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
++			0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
++			0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
++			0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
++			0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
++			0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
++			0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
++			0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
++			0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
++			0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
++			0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
++			0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
++			0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
++			0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
++			0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
++			0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
++			0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
++			0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
++			0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
++			0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
++			0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
++			0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
++			0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
++			0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
++			0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
++			0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
++			0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
++			0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
++			0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
++			0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
++			0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
++			0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
++			0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
++			0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
++			0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
++			0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
++			0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
++			0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
++			0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
++			0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
++			0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
++			0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
++			0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
++			0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
++			0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
++			0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
++			0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
++			0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
++			0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
++			0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
++			0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
++			0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
++			0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
++			0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
++			0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
++			0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
++			0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
++			0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
++			0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
++			0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
++			0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
++			0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
++			0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
++			0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
++			0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
++			0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
++			0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
++			0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
++			0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
++			0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
++			0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
++			0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
++			0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
++			0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
++			0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
++			0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
++			0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
++			0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
++			0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
++			0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
++			0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
++			0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
++			0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
++			0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
++			0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
++			0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
++			0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
++			0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
++			0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
++			0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
++			0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
++			0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
++			0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
++			0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
++			0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
++			0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
++			0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
++			0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
++			0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
++			0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
++			0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
++			0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
++			0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
++			0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
++			0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
++			0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
++			0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
++			0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
++			0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
++			0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
++			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
++			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
++			0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
++			0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
++			0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
++			0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
++			0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
++			0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
++			0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
++			0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
++			0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
++			0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
++			0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
++			0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
++			0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
++			0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
++			0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
++			0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
++			0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
++			0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
++			0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
++			0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
++			0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
++			0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
++			0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
++			0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
++			0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
++			0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
++			0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
++			0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
++			0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
++			0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
++			0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
++			0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
++			0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
++			0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
++			0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
++			0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
++			0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
++			0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
++			0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
++			0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
++			0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
++			0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
++			0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
++			0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
++			0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
++			0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
++			0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
++			0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
++			0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
++			0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
++			0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
++			0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
++			0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
++			0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
++			0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
++			0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
++			0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
++			0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
++			0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
++			0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
++			0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
++			0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
++			0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
++			0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
++			0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
++			0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
++			0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
++			0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
++			0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
++			0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
++			0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
++			0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
++			0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
++			0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
++			0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
++			0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
++			0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
++			0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
++			0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
++			0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
++			0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
++			0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
++			0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
++			0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
++			0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
++			0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
++			0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
++			0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
++			0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
++			0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
++			0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
++			0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
++			0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
++			0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
++			0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
++			0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
++			0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
++			0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
++			0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
++			0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
++			0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
++			0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
++			0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
++			0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
++			0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
++			0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
++			0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
++			0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
++			0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
++			0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
++			0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
++			0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
++			0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
++			0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
++			0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
++			0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
++			0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
++			0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
++			0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
++			0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
++			0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
++			0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
++			0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
++			0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
++			0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
++			0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
++			0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
++			0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
++			0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
++			0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
++			0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
++			0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
++			0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
++			0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
++			0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
++			0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
++			0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
++			0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
++			0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
++			0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
++			0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
++			0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
++			0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
++			0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
++			0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
++			0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
++			0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
++			0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
++			0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
++			0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
++			0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
++			0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
++			0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
++			0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
++			0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
++			0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
++			0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
++			0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
++			0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
++			0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
++			0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
++			0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
++			0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
++			0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
++			0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
++			0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
++			0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
++			0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
++			0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
++			0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
++			0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
++			0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
++			0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
++			0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
++			0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
++			0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
++			0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
++			0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
++			0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
++			0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
++			0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
++			0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
++			0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
++			0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
++			0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
++			0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
++			0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
++			0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
++			0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
++			0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
++			0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
++			0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
++			0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
++			0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
++			0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
++			0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
++			0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
++			0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
++			0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
++			0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
++			0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
++			0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
++			0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
++			0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
++			0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
++			0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
++			0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
++			0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
++			0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
++			0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
++			0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
++			0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
++			0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
++			0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
++			0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
++			0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
++			0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
++			0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
++			0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
++			0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
++			0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
++			0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
++			0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
++			0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
++			0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
++			0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
++			0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
++			0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
++			0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
++			0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
++			0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
++			0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
++			0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
++			0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
++			0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
++			0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
++			0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
++			0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
++			0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
++			0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
++			0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
++			0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
++			0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
++			0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
++			0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
++			0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
++			0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
++			0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
++			0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
++			0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
++			0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
++			0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
++			0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
++			0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
++			0x00, 0x21, 0x42, 0x63,
++		},
++		.ilen = 4100,
++		.result = {
++			0xb5, 0x81, 0xf5, 0x64, 0x18, 0x73, 0xe3, 0xf0,
++			0x4c, 0x13, 0xf2, 0x77, 0x18, 0x60, 0x65, 0x5e,
++			0x29, 0x01, 0xce, 0x98, 0x55, 0x53, 0xf9, 0x0c,
++			0x2a, 0x08, 0xd5, 0x09, 0xb3, 0x57, 0x55, 0x56,
++			0xc5, 0xe9, 0x56, 0x90, 0xcb, 0x6a, 0xa3, 0xc0,
++			0xff, 0xc4, 0x79, 0xb4, 0xd2, 0x97, 0x5d, 0xc4,
++			0x43, 0xd1, 0xfe, 0x94, 0x7b, 0x88, 0x06, 0x5a,
++			0xb2, 0x9e, 0x2c, 0xfc, 0x44, 0x03, 0xb7, 0x90,
++			0xa0, 0xc1, 0xba, 0x6a, 0x33, 0xb8, 0xc7, 0xb2,
++			0x9d, 0xe1, 0x12, 0x4f, 0xc0, 0x64, 0xd4, 0x01,
++			0xfe, 0x8c, 0x7a, 0x66, 0xf7, 0xe6, 0x5a, 0x91,
++			0xbb, 0xde, 0x56, 0x86, 0xab, 0x65, 0x21, 0x30,
++			0x00, 0x84, 0x65, 0x24, 0xa5, 0x7d, 0x85, 0xb4,
++			0xe3, 0x17, 0xed, 0x3a, 0xb7, 0x6f, 0xb4, 0x0b,
++			0x0b, 0xaf, 0x15, 0xae, 0x5a, 0x8f, 0xf2, 0x0c,
++			0x2f, 0x27, 0xf4, 0x09, 0xd8, 0xd2, 0x96, 0xb7,
++			0x71, 0xf2, 0xc5, 0x99, 0x4d, 0x7e, 0x7f, 0x75,
++			0x77, 0x89, 0x30, 0x8b, 0x59, 0xdb, 0xa2, 0xb2,
++			0xa0, 0xf3, 0x19, 0x39, 0x2b, 0xc5, 0x7e, 0x3f,
++			0x4f, 0xd9, 0xd3, 0x56, 0x28, 0x97, 0x44, 0xdc,
++			0xc0, 0x8b, 0x77, 0x24, 0xd9, 0x52, 0xe7, 0xc5,
++			0xaf, 0xf6, 0x7d, 0x59, 0xb2, 0x44, 0x05, 0x1d,
++			0xb1, 0xb0, 0x11, 0xa5, 0x0f, 0xec, 0x33, 0xe1,
++			0x6d, 0x1b, 0x4e, 0x1f, 0xff, 0x57, 0x91, 0xb4,
++			0x5b, 0x9a, 0x96, 0xc5, 0x53, 0xbc, 0xae, 0x20,
++			0x3c, 0xbb, 0x14, 0xe2, 0xe8, 0x22, 0x33, 0xc1,
++			0x5e, 0x76, 0x9e, 0x46, 0x99, 0xf6, 0x2a, 0x15,
++			0xc6, 0x97, 0x02, 0xa0, 0x66, 0x43, 0xd1, 0xa6,
++			0x31, 0xa6, 0x9f, 0xfb, 0xf4, 0xd3, 0x69, 0xe5,
++			0xcd, 0x76, 0x95, 0xb8, 0x7a, 0x82, 0x7f, 0x21,
++			0x45, 0xff, 0x3f, 0xce, 0x55, 0xf6, 0x95, 0x10,
++			0x08, 0x77, 0x10, 0x43, 0xc6, 0xf3, 0x09, 0xe5,
++			0x68, 0xe7, 0x3c, 0xad, 0x00, 0x52, 0x45, 0x0d,
++			0xfe, 0x2d, 0xc6, 0xc2, 0x94, 0x8c, 0x12, 0x1d,
++			0xe6, 0x25, 0xae, 0x98, 0x12, 0x8e, 0x19, 0x9c,
++			0x81, 0x68, 0xb1, 0x11, 0xf6, 0x69, 0xda, 0xe3,
++			0x62, 0x08, 0x18, 0x7a, 0x25, 0x49, 0x28, 0xac,
++			0xba, 0x71, 0x12, 0x0b, 0xe4, 0xa2, 0xe5, 0xc7,
++			0x5d, 0x8e, 0xec, 0x49, 0x40, 0x21, 0xbf, 0x5a,
++			0x98, 0xf3, 0x02, 0x68, 0x55, 0x03, 0x7f, 0x8a,
++			0xe5, 0x94, 0x0c, 0x32, 0x5c, 0x07, 0x82, 0x63,
++			0xaf, 0x6f, 0x91, 0x40, 0x84, 0x8e, 0x52, 0x25,
++			0xd0, 0xb0, 0x29, 0x53, 0x05, 0xe2, 0x50, 0x7a,
++			0x34, 0xeb, 0xc9, 0x46, 0x20, 0xa8, 0x3d, 0xde,
++			0x7f, 0x16, 0x5f, 0x36, 0xc5, 0x2e, 0xdc, 0xd1,
++			0x15, 0x47, 0xc7, 0x50, 0x40, 0x6d, 0x91, 0xc5,
++			0xe7, 0x93, 0x95, 0x1a, 0xd3, 0x57, 0xbc, 0x52,
++			0x33, 0xee, 0x14, 0x19, 0x22, 0x52, 0x89, 0xa7,
++			0x4a, 0x25, 0x56, 0x77, 0x4b, 0xca, 0xcf, 0x0a,
++			0xe1, 0xf5, 0x35, 0x85, 0x30, 0x7e, 0x59, 0x4a,
++			0xbd, 0x14, 0x5b, 0xdf, 0xe3, 0x46, 0xcb, 0xac,
++			0x1f, 0x6c, 0x96, 0x0e, 0xf4, 0x81, 0xd1, 0x99,
++			0xca, 0x88, 0x63, 0x3d, 0x02, 0x58, 0x6b, 0xa9,
++			0xe5, 0x9f, 0xb3, 0x00, 0xb2, 0x54, 0xc6, 0x74,
++			0x1c, 0xbf, 0x46, 0xab, 0x97, 0xcc, 0xf8, 0x54,
++			0x04, 0x07, 0x08, 0x52, 0xe6, 0xc0, 0xda, 0x93,
++			0x74, 0x7d, 0x93, 0x99, 0x5d, 0x78, 0x68, 0xa6,
++			0x2e, 0x6b, 0xd3, 0x6a, 0x69, 0xcc, 0x12, 0x6b,
++			0xd4, 0xc7, 0xa5, 0xc6, 0xe7, 0xf6, 0x03, 0x04,
++			0x5d, 0xcd, 0x61, 0x5e, 0x17, 0x40, 0xdc, 0xd1,
++			0x5c, 0xf5, 0x08, 0xdf, 0x5c, 0x90, 0x85, 0xa4,
++			0xaf, 0xf6, 0x78, 0xbb, 0x0d, 0xf1, 0xf4, 0xa4,
++			0x54, 0x26, 0x72, 0x9e, 0x61, 0xfa, 0x86, 0xcf,
++			0xe8, 0x9e, 0xa1, 0xe0, 0xc7, 0x48, 0x23, 0xae,
++			0x5a, 0x90, 0xae, 0x75, 0x0a, 0x74, 0x18, 0x89,
++			0x05, 0xb1, 0x92, 0xb2, 0x7f, 0xd0, 0x1b, 0xa6,
++			0x62, 0x07, 0x25, 0x01, 0xc7, 0xc2, 0x4f, 0xf9,
++			0xe8, 0xfe, 0x63, 0x95, 0x80, 0x07, 0xb4, 0x26,
++			0xcc, 0xd1, 0x26, 0xb6, 0xc4, 0x3f, 0x9e, 0xcb,
++			0x8e, 0x3b, 0x2e, 0x44, 0x16, 0xd3, 0x10, 0x9a,
++			0x95, 0x08, 0xeb, 0xc8, 0xcb, 0xeb, 0xbf, 0x6f,
++			0x0b, 0xcd, 0x1f, 0xc8, 0xca, 0x86, 0xaa, 0xec,
++			0x33, 0xe6, 0x69, 0xf4, 0x45, 0x25, 0x86, 0x3a,
++			0x22, 0x94, 0x4f, 0x00, 0x23, 0x6a, 0x44, 0xc2,
++			0x49, 0x97, 0x33, 0xab, 0x36, 0x14, 0x0a, 0x70,
++			0x24, 0xc3, 0xbe, 0x04, 0x3b, 0x79, 0xa0, 0xf9,
++			0xb8, 0xe7, 0x76, 0x29, 0x22, 0x83, 0xd7, 0xf2,
++			0x94, 0xf4, 0x41, 0x49, 0xba, 0x5f, 0x7b, 0x07,
++			0xb5, 0xfb, 0xdb, 0x03, 0x1a, 0x9f, 0xb6, 0x4c,
++			0xc2, 0x2e, 0x37, 0x40, 0x49, 0xc3, 0x38, 0x16,
++			0xe2, 0x4f, 0x77, 0x82, 0xb0, 0x68, 0x4c, 0x71,
++			0x1d, 0x57, 0x61, 0x9c, 0xd9, 0x4e, 0x54, 0x99,
++			0x47, 0x13, 0x28, 0x73, 0x3c, 0xbb, 0x00, 0x90,
++			0xf3, 0x4d, 0xc9, 0x0e, 0xfd, 0xe7, 0xb1, 0x71,
++			0xd3, 0x15, 0x79, 0xbf, 0xcc, 0x26, 0x2f, 0xbd,
++			0xad, 0x6c, 0x50, 0x69, 0x6c, 0x3e, 0x6d, 0x80,
++			0x9a, 0xea, 0x78, 0xaf, 0x19, 0xb2, 0x0d, 0x4d,
++			0xad, 0x04, 0x07, 0xae, 0x22, 0x90, 0x4a, 0x93,
++			0x32, 0x0e, 0x36, 0x9b, 0x1b, 0x46, 0xba, 0x3b,
++			0xb4, 0xac, 0xc6, 0xd1, 0xa2, 0x31, 0x53, 0x3b,
++			0x2a, 0x3d, 0x45, 0xfe, 0x03, 0x61, 0x10, 0x85,
++			0x17, 0x69, 0xa6, 0x78, 0xcc, 0x6c, 0x87, 0x49,
++			0x53, 0xf9, 0x80, 0x10, 0xde, 0x80, 0xa2, 0x41,
++			0x6a, 0xc3, 0x32, 0x02, 0xad, 0x6d, 0x3c, 0x56,
++			0x00, 0x71, 0x51, 0x06, 0xa7, 0xbd, 0xfb, 0xef,
++			0x3c, 0xb5, 0x9f, 0xfc, 0x48, 0x7d, 0x53, 0x7c,
++			0x66, 0xb0, 0x49, 0x23, 0xc4, 0x47, 0x10, 0x0e,
++			0xe5, 0x6c, 0x74, 0x13, 0xe6, 0xc5, 0x3f, 0xaa,
++			0xde, 0xff, 0x07, 0x44, 0xdd, 0x56, 0x1b, 0xad,
++			0x09, 0x77, 0xfb, 0x5b, 0x12, 0xb8, 0x0d, 0x38,
++			0x17, 0x37, 0x35, 0x7b, 0x9b, 0xbc, 0xfe, 0xd4,
++			0x7e, 0x8b, 0xda, 0x7e, 0x5b, 0x04, 0xa7, 0x22,
++			0xa7, 0x31, 0xa1, 0x20, 0x86, 0xc7, 0x1b, 0x99,
++			0xdb, 0xd1, 0x89, 0xf4, 0x94, 0xa3, 0x53, 0x69,
++			0x8d, 0xe7, 0xe8, 0x74, 0x11, 0x8d, 0x74, 0xd6,
++			0x07, 0x37, 0x91, 0x9f, 0xfd, 0x67, 0x50, 0x3a,
++			0xc9, 0xe1, 0xf4, 0x36, 0xd5, 0xa0, 0x47, 0xd1,
++			0xf9, 0xe5, 0x39, 0xa3, 0x31, 0xac, 0x07, 0x36,
++			0x23, 0xf8, 0x66, 0x18, 0x14, 0x28, 0x34, 0x0f,
++			0xb8, 0xd0, 0xe7, 0x29, 0xb3, 0x04, 0x4b, 0x55,
++			0x01, 0x41, 0xb2, 0x75, 0x8d, 0xcb, 0x96, 0x85,
++			0x3a, 0xfb, 0xab, 0x2b, 0x9e, 0xfa, 0x58, 0x20,
++			0x44, 0x1f, 0xc0, 0x14, 0x22, 0x75, 0x61, 0xe8,
++			0xaa, 0x19, 0xcf, 0xf1, 0x82, 0x56, 0xf4, 0xd7,
++			0x78, 0x7b, 0x3d, 0x5f, 0xb3, 0x9e, 0x0b, 0x8a,
++			0x57, 0x50, 0xdb, 0x17, 0x41, 0x65, 0x4d, 0xa3,
++			0x02, 0xc9, 0x9c, 0x9c, 0x53, 0xfb, 0x39, 0x39,
++			0x9b, 0x1d, 0x72, 0x24, 0xda, 0xb7, 0x39, 0xbe,
++			0x13, 0x3b, 0xfa, 0x29, 0xda, 0x9e, 0x54, 0x64,
++			0x6e, 0xba, 0xd8, 0xa1, 0xcb, 0xb3, 0x36, 0xfa,
++			0xcb, 0x47, 0x85, 0xe9, 0x61, 0x38, 0xbc, 0xbe,
++			0xc5, 0x00, 0x38, 0x2a, 0x54, 0xf7, 0xc4, 0xb9,
++			0xb3, 0xd3, 0x7b, 0xa0, 0xa0, 0xf8, 0x72, 0x7f,
++			0x8c, 0x8e, 0x82, 0x0e, 0xc6, 0x1c, 0x75, 0x9d,
++			0xca, 0x8e, 0x61, 0x87, 0xde, 0xad, 0x80, 0xd2,
++			0xf5, 0xf9, 0x80, 0xef, 0x15, 0x75, 0xaf, 0xf5,
++			0x80, 0xfb, 0xff, 0x6d, 0x1e, 0x25, 0xb7, 0x40,
++			0x61, 0x6a, 0x39, 0x5a, 0x6a, 0xb5, 0x31, 0xab,
++			0x97, 0x8a, 0x19, 0x89, 0x44, 0x40, 0xc0, 0xa6,
++			0xb4, 0x4e, 0x30, 0x32, 0x7b, 0x13, 0xe7, 0x67,
++			0xa9, 0x8b, 0x57, 0x04, 0xc2, 0x01, 0xa6, 0xf4,
++			0x28, 0x99, 0xad, 0x2c, 0x76, 0xa3, 0x78, 0xc2,
++			0x4a, 0xe6, 0xca, 0x5c, 0x50, 0x6a, 0xc1, 0xb0,
++			0x62, 0x4b, 0x10, 0x8e, 0x7c, 0x17, 0x43, 0xb3,
++			0x17, 0x66, 0x1c, 0x3e, 0x8d, 0x69, 0xf0, 0x5a,
++			0x71, 0xf5, 0x97, 0xdc, 0xd1, 0x45, 0xdd, 0x28,
++			0xf3, 0x5d, 0xdf, 0x53, 0x7b, 0x11, 0xe5, 0xbc,
++			0x4c, 0xdb, 0x1b, 0x51, 0x6b, 0xe9, 0xfb, 0x3d,
++			0xc1, 0xc3, 0x2c, 0xb9, 0x71, 0xf5, 0xb6, 0xb2,
++			0x13, 0x36, 0x79, 0x80, 0x53, 0xe8, 0xd3, 0xa6,
++			0x0a, 0xaf, 0xfd, 0x56, 0x97, 0xf7, 0x40, 0x8e,
++			0x45, 0xce, 0xf8, 0xb0, 0x9e, 0x5c, 0x33, 0x82,
++			0xb0, 0x44, 0x56, 0xfc, 0x05, 0x09, 0xe9, 0x2a,
++			0xac, 0x26, 0x80, 0x14, 0x1d, 0xc8, 0x3a, 0x35,
++			0x4c, 0x82, 0x97, 0xfd, 0x76, 0xb7, 0xa9, 0x0a,
++			0x35, 0x58, 0x79, 0x8e, 0x0f, 0x66, 0xea, 0xaf,
++			0x51, 0x6c, 0x09, 0xa9, 0x6e, 0x9b, 0xcb, 0x9a,
++			0x31, 0x47, 0xa0, 0x2f, 0x7c, 0x71, 0xb4, 0x4a,
++			0x11, 0xaa, 0x8c, 0x66, 0xc5, 0x64, 0xe6, 0x3a,
++			0x54, 0xda, 0x24, 0x6a, 0xc4, 0x41, 0x65, 0x46,
++			0x82, 0xa0, 0x0a, 0x0f, 0x5f, 0xfb, 0x25, 0xd0,
++			0x2c, 0x91, 0xa7, 0xee, 0xc4, 0x81, 0x07, 0x86,
++			0x75, 0x5e, 0x33, 0x69, 0x97, 0xe4, 0x2c, 0xa8,
++			0x9d, 0x9f, 0x0b, 0x6a, 0xbe, 0xad, 0x98, 0xda,
++			0x6d, 0x94, 0x41, 0xda, 0x2c, 0x1e, 0x89, 0xc4,
++			0xc2, 0xaf, 0x1e, 0x00, 0x05, 0x0b, 0x83, 0x60,
++			0xbd, 0x43, 0xea, 0x15, 0x23, 0x7f, 0xb9, 0xac,
++			0xee, 0x4f, 0x2c, 0xaf, 0x2a, 0xf3, 0xdf, 0xd0,
++			0xf3, 0x19, 0x31, 0xbb, 0x4a, 0x74, 0x84, 0x17,
++			0x52, 0x32, 0x2c, 0x7d, 0x61, 0xe4, 0xcb, 0xeb,
++			0x80, 0x38, 0x15, 0x52, 0xcb, 0x6f, 0xea, 0xe5,
++			0x73, 0x9c, 0xd9, 0x24, 0x69, 0xc6, 0x95, 0x32,
++			0x21, 0xc8, 0x11, 0xe4, 0xdc, 0x36, 0xd7, 0x93,
++			0x38, 0x66, 0xfb, 0xb2, 0x7f, 0x3a, 0xb9, 0xaf,
++			0x31, 0xdd, 0x93, 0x75, 0x78, 0x8a, 0x2c, 0x94,
++			0x87, 0x1a, 0x58, 0xec, 0x9e, 0x7d, 0x4d, 0xba,
++			0xe1, 0xe5, 0x4d, 0xfc, 0xbc, 0xa4, 0x2a, 0x14,
++			0xef, 0xcc, 0xa7, 0xec, 0xab, 0x43, 0x09, 0x18,
++			0xd3, 0xab, 0x68, 0xd1, 0x07, 0x99, 0x44, 0x47,
++			0xd6, 0x83, 0x85, 0x3b, 0x30, 0xea, 0xa9, 0x6b,
++			0x63, 0xea, 0xc4, 0x07, 0xfb, 0x43, 0x2f, 0xa4,
++			0xaa, 0xb0, 0xab, 0x03, 0x89, 0xce, 0x3f, 0x8c,
++			0x02, 0x7c, 0x86, 0x54, 0xbc, 0x88, 0xaf, 0x75,
++			0xd2, 0xdc, 0x63, 0x17, 0xd3, 0x26, 0xf6, 0x96,
++			0xa9, 0x3c, 0xf1, 0x61, 0x8c, 0x11, 0x18, 0xcc,
++			0xd6, 0xea, 0x5b, 0xe2, 0xcd, 0xf0, 0xf1, 0xb2,
++			0xe5, 0x35, 0x90, 0x1f, 0x85, 0x4c, 0x76, 0x5b,
++			0x66, 0xce, 0x44, 0xa4, 0x32, 0x9f, 0xe6, 0x7b,
++			0x71, 0x6e, 0x9f, 0x58, 0x15, 0x67, 0x72, 0x87,
++			0x64, 0x8e, 0x3a, 0x44, 0x45, 0xd4, 0x76, 0xfa,
++			0xc2, 0xf6, 0xef, 0x85, 0x05, 0x18, 0x7a, 0x9b,
++			0xba, 0x41, 0x54, 0xac, 0xf0, 0xfc, 0x59, 0x12,
++			0x3f, 0xdf, 0xa0, 0xe5, 0x8a, 0x65, 0xfd, 0x3a,
++			0x62, 0x8d, 0x83, 0x2c, 0x03, 0xbe, 0x05, 0x76,
++			0x2e, 0x53, 0x49, 0x97, 0x94, 0x33, 0xae, 0x40,
++			0x81, 0x15, 0xdb, 0x6e, 0xad, 0xaa, 0xf5, 0x4b,
++			0xe3, 0x98, 0x70, 0xdf, 0xe0, 0x7c, 0xcd, 0xdb,
++			0x02, 0xd4, 0x7d, 0x2f, 0xc1, 0xe6, 0xb4, 0xf3,
++			0xd7, 0x0d, 0x7a, 0xd9, 0x23, 0x9e, 0x87, 0x2d,
++			0xce, 0x87, 0xad, 0xcc, 0x72, 0x05, 0x00, 0x29,
++			0xdc, 0x73, 0x7f, 0x64, 0xc1, 0x15, 0x0e, 0xc2,
++			0xdf, 0xa7, 0x5f, 0xeb, 0x41, 0xa1, 0xcd, 0xef,
++			0x5c, 0x50, 0x79, 0x2a, 0x56, 0x56, 0x71, 0x8c,
++			0xac, 0xc0, 0x79, 0x50, 0x69, 0xca, 0x59, 0x32,
++			0x65, 0xf2, 0x54, 0xe4, 0x52, 0x38, 0x76, 0xd1,
++			0x5e, 0xde, 0x26, 0x9e, 0xfb, 0x75, 0x2e, 0x11,
++			0xb5, 0x10, 0xf4, 0x17, 0x73, 0xf5, 0x89, 0xc7,
++			0x4f, 0x43, 0x5c, 0x8e, 0x7c, 0xb9, 0x05, 0x52,
++			0x24, 0x40, 0x99, 0xfe, 0x9b, 0x85, 0x0b, 0x6c,
++			0x22, 0x3e, 0x8b, 0xae, 0x86, 0xa1, 0xd2, 0x79,
++			0x05, 0x68, 0x6b, 0xab, 0xe3, 0x41, 0x49, 0xed,
++			0x15, 0xa1, 0x8d, 0x40, 0x2d, 0x61, 0xdf, 0x1a,
++			0x59, 0xc9, 0x26, 0x8b, 0xef, 0x30, 0x4c, 0x88,
++			0x4b, 0x10, 0xf8, 0x8d, 0xa6, 0x92, 0x9f, 0x4b,
++			0xf3, 0xc4, 0x53, 0x0b, 0x89, 0x5d, 0x28, 0x92,
++			0xcf, 0x78, 0xb2, 0xc0, 0x5d, 0xed, 0x7e, 0xfc,
++			0xc0, 0x12, 0x23, 0x5f, 0x5a, 0x78, 0x86, 0x43,
++			0x6e, 0x27, 0xf7, 0x5a, 0xa7, 0x6a, 0xed, 0x19,
++			0x04, 0xf0, 0xb3, 0x12, 0xd1, 0xbd, 0x0e, 0x89,
++			0x6e, 0xbc, 0x96, 0xa8, 0xd8, 0x49, 0x39, 0x9f,
++			0x7e, 0x67, 0xf0, 0x2e, 0x3e, 0x01, 0xa9, 0xba,
++			0xec, 0x8b, 0x62, 0x8e, 0xcb, 0x4a, 0x70, 0x43,
++			0xc7, 0xc2, 0xc4, 0xca, 0x82, 0x03, 0x73, 0xe9,
++			0x11, 0xdf, 0xcf, 0x54, 0xea, 0xc9, 0xb0, 0x95,
++			0x51, 0xc0, 0x13, 0x3d, 0x92, 0x05, 0xfa, 0xf4,
++			0xa9, 0x34, 0xc8, 0xce, 0x6c, 0x3d, 0x54, 0xcc,
++			0xc4, 0xaf, 0xf1, 0xdc, 0x11, 0x44, 0x26, 0xa2,
++			0xaf, 0xf1, 0x85, 0x75, 0x7d, 0x03, 0x61, 0x68,
++			0x4e, 0x78, 0xc6, 0x92, 0x7d, 0x86, 0x7d, 0x77,
++			0xdc, 0x71, 0x72, 0xdb, 0xc6, 0xae, 0xa1, 0xcb,
++			0x70, 0x9a, 0x0b, 0x19, 0xbe, 0x4a, 0x6c, 0x2a,
++			0xe2, 0xba, 0x6c, 0x64, 0x9a, 0x13, 0x28, 0xdf,
++			0x85, 0x75, 0xe6, 0x43, 0xf6, 0x87, 0x08, 0x68,
++			0x6e, 0xba, 0x6e, 0x79, 0x9f, 0x04, 0xbc, 0x23,
++			0x50, 0xf6, 0x33, 0x5c, 0x1f, 0x24, 0x25, 0xbe,
++			0x33, 0x47, 0x80, 0x45, 0x56, 0xa3, 0xa7, 0xd7,
++			0x7a, 0xb1, 0x34, 0x0b, 0x90, 0x3c, 0x9c, 0xad,
++			0x44, 0x5f, 0x9e, 0x0e, 0x9d, 0xd4, 0xbd, 0x93,
++			0x5e, 0xfa, 0x3c, 0xe0, 0xb0, 0xd9, 0xed, 0xf3,
++			0xd6, 0x2e, 0xff, 0x24, 0xd8, 0x71, 0x6c, 0xed,
++			0xaf, 0x55, 0xeb, 0x22, 0xac, 0x93, 0x68, 0x32,
++			0x05, 0x5b, 0x47, 0xdd, 0xc6, 0x4a, 0xcb, 0xc7,
++			0x10, 0xe1, 0x3c, 0x92, 0x1a, 0xf3, 0x23, 0x78,
++			0x2b, 0xa1, 0xd2, 0x80, 0xf4, 0x12, 0xb1, 0x20,
++			0x8f, 0xff, 0x26, 0x35, 0xdd, 0xfb, 0xc7, 0x4e,
++			0x78, 0xf1, 0x2d, 0x50, 0x12, 0x77, 0xa8, 0x60,
++			0x7c, 0x0f, 0xf5, 0x16, 0x2f, 0x63, 0x70, 0x2a,
++			0xc0, 0x96, 0x80, 0x4e, 0x0a, 0xb4, 0x93, 0x35,
++			0x5d, 0x1d, 0x3f, 0x56, 0xf7, 0x2f, 0xbb, 0x90,
++			0x11, 0x16, 0x8f, 0xa2, 0xec, 0x47, 0xbe, 0xac,
++			0x56, 0x01, 0x26, 0x56, 0xb1, 0x8c, 0xb2, 0x10,
++			0xf9, 0x1a, 0xca, 0xf5, 0xd1, 0xb7, 0x39, 0x20,
++			0x63, 0xf1, 0x69, 0x20, 0x4f, 0x13, 0x12, 0x1f,
++			0x5b, 0x65, 0xfc, 0x98, 0xf7, 0xc4, 0x7a, 0xbe,
++			0xf7, 0x26, 0x4d, 0x2b, 0x84, 0x7b, 0x42, 0xad,
++			0xd8, 0x7a, 0x0a, 0xb4, 0xd8, 0x74, 0xbf, 0xc1,
++			0xf0, 0x6e, 0xb4, 0x29, 0xa3, 0xbb, 0xca, 0x46,
++			0x67, 0x70, 0x6a, 0x2d, 0xce, 0x0e, 0xa2, 0x8a,
++			0xa9, 0x87, 0xbf, 0x05, 0xc4, 0xc1, 0x04, 0xa3,
++			0xab, 0xd4, 0x45, 0x43, 0x8c, 0xb6, 0x02, 0xb0,
++			0x41, 0xc8, 0xfc, 0x44, 0x3d, 0x59, 0xaa, 0x2e,
++			0x44, 0x21, 0x2a, 0x8d, 0x88, 0x9d, 0x57, 0xf4,
++			0xa0, 0x02, 0x77, 0xb8, 0xa6, 0xa0, 0xe6, 0x75,
++			0x5c, 0x82, 0x65, 0x3e, 0x03, 0x5c, 0x29, 0x8f,
++			0x38, 0x55, 0xab, 0x33, 0x26, 0xef, 0x9f, 0x43,
++			0x52, 0xfd, 0x68, 0xaf, 0x36, 0xb4, 0xbb, 0x9a,
++			0x58, 0x09, 0x09, 0x1b, 0xc3, 0x65, 0x46, 0x46,
++			0x1d, 0xa7, 0x94, 0x18, 0x23, 0x50, 0x2c, 0xca,
++			0x2c, 0x55, 0x19, 0x97, 0x01, 0x9d, 0x93, 0x3b,
++			0x63, 0x86, 0xf2, 0x03, 0x67, 0x45, 0xd2, 0x72,
++			0x28, 0x52, 0x6c, 0xf4, 0xe3, 0x1c, 0xb5, 0x11,
++			0x13, 0xf1, 0xeb, 0x21, 0xc7, 0xd9, 0x56, 0x82,
++			0x2b, 0x82, 0x39, 0xbd, 0x69, 0x54, 0xed, 0x62,
++			0xc3, 0xe2, 0xde, 0x73, 0xd4, 0x6a, 0x12, 0xae,
++			0x13, 0x21, 0x7f, 0x4b, 0x5b, 0xfc, 0xbf, 0xe8,
++			0x2b, 0xbe, 0x56, 0xba, 0x68, 0x8b, 0x9a, 0xb1,
++			0x6e, 0xfa, 0xbf, 0x7e, 0x5a, 0x4b, 0xf1, 0xac,
++			0x98, 0x65, 0x85, 0xd1, 0x93, 0x53, 0xd3, 0x7b,
++			0x09, 0xdd, 0x4b, 0x10, 0x6d, 0x84, 0xb0, 0x13,
++			0x65, 0xbd, 0xcf, 0x52, 0x09, 0xc4, 0x85, 0xe2,
++			0x84, 0x74, 0x15, 0x65, 0xb7, 0xf7, 0x51, 0xaf,
++			0x55, 0xad, 0xa4, 0xd1, 0x22, 0x54, 0x70, 0x94,
++			0xa0, 0x1c, 0x90, 0x41, 0xfd, 0x99, 0xd7, 0x5a,
++			0x31, 0xef, 0xaa, 0x25, 0xd0, 0x7f, 0x4f, 0xea,
++			0x1d, 0x55, 0x42, 0xe5, 0x49, 0xb0, 0xd0, 0x46,
++			0x62, 0x36, 0x43, 0xb2, 0x82, 0x15, 0x75, 0x50,
++			0xa4, 0x72, 0xeb, 0x54, 0x27, 0x1f, 0x8a, 0xe4,
++			0x7d, 0xe9, 0x66, 0xc5, 0xf1, 0x53, 0xa4, 0xd1,
++			0x0c, 0xeb, 0xb8, 0xf8, 0xbc, 0xd4, 0xe2, 0xe7,
++			0xe1, 0xf8, 0x4b, 0xcb, 0xa9, 0xa1, 0xaf, 0x15,
++			0x83, 0xcb, 0x72, 0xd0, 0x33, 0x79, 0x00, 0x2d,
++			0x9f, 0xd7, 0xf1, 0x2e, 0x1e, 0x10, 0xe4, 0x45,
++			0xc0, 0x75, 0x3a, 0x39, 0xea, 0x68, 0xf7, 0x5d,
++			0x1b, 0x73, 0x8f, 0xe9, 0x8e, 0x0f, 0x72, 0x47,
++			0xae, 0x35, 0x0a, 0x31, 0x7a, 0x14, 0x4d, 0x4a,
++			0x6f, 0x47, 0xf7, 0x7e, 0x91, 0x6e, 0x74, 0x8b,
++			0x26, 0x47, 0xf9, 0xc3, 0xf9, 0xde, 0x70, 0xf5,
++			0x61, 0xab, 0xa9, 0x27, 0x9f, 0x82, 0xe4, 0x9c,
++			0x89, 0x91, 0x3f, 0x2e, 0x6a, 0xfd, 0xb5, 0x49,
++			0xe9, 0xfd, 0x59, 0x14, 0x36, 0x49, 0x40, 0x6d,
++			0x32, 0xd8, 0x85, 0x42, 0xf3, 0xa5, 0xdf, 0x0c,
++			0xa8, 0x27, 0xd7, 0x54, 0xe2, 0x63, 0x2f, 0xf2,
++			0x7e, 0x8b, 0x8b, 0xe7, 0xf1, 0x9a, 0x95, 0x35,
++			0x43, 0xdc, 0x3a, 0xe4, 0xb6, 0xf4, 0xd0, 0xdf,
++			0x9c, 0xcb, 0x94, 0xf3, 0x21, 0xa0, 0x77, 0x50,
++			0xe2, 0xc6, 0xc4, 0xc6, 0x5f, 0x09, 0x64, 0x5b,
++			0x92, 0x90, 0xd8, 0xe1, 0xd1, 0xed, 0x4b, 0x42,
++			0xd7, 0x37, 0xaf, 0x65, 0x3d, 0x11, 0x39, 0xb6,
++			0x24, 0x8a, 0x60, 0xae, 0xd6, 0x1e, 0xbf, 0x0e,
++			0x0d, 0xd7, 0xdc, 0x96, 0x0e, 0x65, 0x75, 0x4e,
++			0x29, 0x06, 0x9d, 0xa4, 0x51, 0x3a, 0x10, 0x63,
++			0x8f, 0x17, 0x07, 0xd5, 0x8e, 0x3c, 0xf4, 0x28,
++			0x00, 0x5a, 0x5b, 0x05, 0x19, 0xd8, 0xc0, 0x6c,
++			0xe5, 0x15, 0xe4, 0x9c, 0x9d, 0x71, 0x9d, 0x5e,
++			0x94, 0x29, 0x1a, 0xa7, 0x80, 0xfa, 0x0e, 0x33,
++			0x03, 0xdd, 0xb7, 0x3e, 0x9a, 0xa9, 0x26, 0x18,
++			0x37, 0xa9, 0x64, 0x08, 0x4d, 0x94, 0x5a, 0x88,
++			0xca, 0x35, 0xce, 0x81, 0x02, 0xe3, 0x1f, 0x1b,
++			0x89, 0x1a, 0x77, 0x85, 0xe3, 0x41, 0x6d, 0x32,
++			0x42, 0x19, 0x23, 0x7d, 0xc8, 0x73, 0xee, 0x25,
++			0x85, 0x0d, 0xf8, 0x31, 0x25, 0x79, 0x1b, 0x6f,
++			0x79, 0x25, 0xd2, 0xd8, 0xd4, 0x23, 0xfd, 0xf7,
++			0x82, 0x36, 0x6a, 0x0c, 0x46, 0x22, 0x15, 0xe9,
++			0xff, 0x72, 0x41, 0x91, 0x91, 0x7d, 0x3a, 0xb7,
++			0xdd, 0x65, 0x99, 0x70, 0xf6, 0x8d, 0x84, 0xf8,
++			0x67, 0x15, 0x20, 0x11, 0xd6, 0xb2, 0x55, 0x7b,
++			0xdb, 0x87, 0xee, 0xef, 0x55, 0x89, 0x2a, 0x59,
++			0x2b, 0x07, 0x8f, 0x43, 0x8a, 0x59, 0x3c, 0x01,
++			0x8b, 0x65, 0x54, 0xa1, 0x66, 0xd5, 0x38, 0xbd,
++			0xc6, 0x30, 0xa9, 0xcc, 0x49, 0xb6, 0xa8, 0x1b,
++			0xb8, 0xc0, 0x0e, 0xe3, 0x45, 0x28, 0xe2, 0xff,
++			0x41, 0x9f, 0x7e, 0x7c, 0xd1, 0xae, 0x9e, 0x25,
++			0x3f, 0x4c, 0x7c, 0x7c, 0xf4, 0xa8, 0x26, 0x4d,
++			0x5c, 0xfd, 0x4b, 0x27, 0x18, 0xf9, 0x61, 0x76,
++			0x48, 0xba, 0x0c, 0x6b, 0xa9, 0x4d, 0xfc, 0xf5,
++			0x3b, 0x35, 0x7e, 0x2f, 0x4a, 0xa9, 0xc2, 0x9a,
++			0xae, 0xab, 0x86, 0x09, 0x89, 0xc9, 0xc2, 0x40,
++			0x39, 0x2c, 0x81, 0xb3, 0xb8, 0x17, 0x67, 0xc2,
++			0x0d, 0x32, 0x4a, 0x3a, 0x67, 0x81, 0xd7, 0x1a,
++			0x34, 0x52, 0xc5, 0xdb, 0x0a, 0xf5, 0x63, 0x39,
++			0xea, 0x1f, 0xe1, 0x7c, 0xa1, 0x9e, 0xc1, 0x35,
++			0xe3, 0xb1, 0x18, 0x45, 0x67, 0xf9, 0x22, 0x38,
++			0x95, 0xd9, 0x34, 0x34, 0x86, 0xc6, 0x41, 0x94,
++			0x15, 0xf9, 0x5b, 0x41, 0xa6, 0x87, 0x8b, 0xf8,
++			0xd5, 0xe1, 0x1b, 0xe2, 0x5b, 0xf3, 0x86, 0x10,
++			0xff, 0xe6, 0xae, 0x69, 0x76, 0xbc, 0x0d, 0xb4,
++			0x09, 0x90, 0x0c, 0xa2, 0x65, 0x0c, 0xad, 0x74,
++			0xf5, 0xd7, 0xff, 0xda, 0xc1, 0xce, 0x85, 0xbe,
++			0x00, 0xa7, 0xff, 0x4d, 0x2f, 0x65, 0xd3, 0x8c,
++			0x86, 0x2d, 0x05, 0xe8, 0xed, 0x3e, 0x6b, 0x8b,
++			0x0f, 0x3d, 0x83, 0x8c, 0xf1, 0x1d, 0x5b, 0x96,
++			0x2e, 0xb1, 0x9c, 0xc2, 0x98, 0xe1, 0x70, 0xb9,
++			0xba, 0x5c, 0x8a, 0x43, 0xd6, 0x34, 0xa7, 0x2d,
++			0xc9, 0x92, 0xae, 0xf2, 0xa5, 0x7b, 0x05, 0x49,
++			0xa7, 0x33, 0x34, 0x86, 0xca, 0xe4, 0x96, 0x23,
++			0x76, 0x5b, 0xf2, 0xc6, 0xf1, 0x51, 0x28, 0x42,
++			0x7b, 0xcc, 0x76, 0x8f, 0xfa, 0xa2, 0xad, 0x31,
++			0xd4, 0xd6, 0x7a, 0x6d, 0x25, 0x25, 0x54, 0xe4,
++			0x3f, 0x50, 0x59, 0xe1, 0x5c, 0x05, 0xb7, 0x27,
++			0x48, 0xbf, 0x07, 0xec, 0x1b, 0x13, 0xbe, 0x2b,
++			0xa1, 0x57, 0x2b, 0xd5, 0xab, 0xd7, 0xd0, 0x4c,
++			0x1e, 0xcb, 0x71, 0x9b, 0xc5, 0x90, 0x85, 0xd3,
++			0xde, 0x59, 0xec, 0x71, 0xeb, 0x89, 0xbb, 0xd0,
++			0x09, 0x50, 0xe1, 0x16, 0x3f, 0xfd, 0x1c, 0x34,
++			0xc3, 0x1c, 0xa1, 0x10, 0x77, 0x53, 0x98, 0xef,
++			0xf2, 0xfd, 0xa5, 0x01, 0x59, 0xc2, 0x9b, 0x26,
++			0xc7, 0x42, 0xd9, 0x49, 0xda, 0x58, 0x2b, 0x6e,
++			0x9f, 0x53, 0x19, 0x76, 0x7e, 0xd9, 0xc9, 0x0e,
++			0x68, 0xc8, 0x7f, 0x51, 0x22, 0x42, 0xef, 0x49,
++			0xa4, 0x55, 0xb6, 0x36, 0xac, 0x09, 0xc7, 0x31,
++			0x88, 0x15, 0x4b, 0x2e, 0x8f, 0x3a, 0x08, 0xf7,
++			0xd8, 0xf7, 0xa8, 0xc5, 0xa9, 0x33, 0xa6, 0x45,
++			0xe4, 0xc4, 0x94, 0x76, 0xf3, 0x0d, 0x8f, 0x7e,
++			0xc8, 0xf6, 0xbc, 0x23, 0x0a, 0xb6, 0x4c, 0xd3,
++			0x6a, 0xcd, 0x36, 0xc2, 0x90, 0x5c, 0x5c, 0x3c,
++			0x65, 0x7b, 0xc2, 0xd6, 0xcc, 0xe6, 0x0d, 0x87,
++			0x73, 0x2e, 0x71, 0x79, 0x16, 0x06, 0x63, 0x28,
++			0x09, 0x15, 0xd8, 0x89, 0x38, 0x38, 0x3d, 0xb5,
++			0x42, 0x1c, 0x08, 0x24, 0xf7, 0x2a, 0xd2, 0x9d,
++			0xc8, 0xca, 0xef, 0xf9, 0x27, 0xd8, 0x07, 0x86,
++			0xf7, 0x43, 0x0b, 0x55, 0x15, 0x3f, 0x9f, 0x83,
++			0xef, 0xdc, 0x49, 0x9d, 0x2a, 0xc1, 0x54, 0x62,
++			0xbd, 0x9b, 0x66, 0x55, 0x9f, 0xb7, 0x12, 0xf3,
++			0x1b, 0x4d, 0x9d, 0x2a, 0x5c, 0xed, 0x87, 0x75,
++			0x87, 0x26, 0xec, 0x61, 0x2c, 0xb4, 0x0f, 0x89,
++			0xb0, 0xfb, 0x2e, 0x68, 0x5d, 0x15, 0xc7, 0x8d,
++			0x2e, 0xc0, 0xd9, 0xec, 0xaf, 0x4f, 0xd2, 0x25,
++			0x29, 0xe8, 0xd2, 0x26, 0x2b, 0x67, 0xe9, 0xfc,
++			0x2b, 0xa8, 0x67, 0x96, 0x12, 0x1f, 0x5b, 0x96,
++			0xc6, 0x14, 0x53, 0xaf, 0x44, 0xea, 0xd6, 0xe2,
++			0x94, 0x98, 0xe4, 0x12, 0x93, 0x4c, 0x92, 0xe0,
++			0x18, 0xa5, 0x8d, 0x2d, 0xe4, 0x71, 0x3c, 0x47,
++			0x4c, 0xf7, 0xe6, 0x47, 0x9e, 0xc0, 0x68, 0xdf,
++			0xd4, 0xf5, 0x5a, 0x74, 0xb1, 0x2b, 0x29, 0x03,
++			0x19, 0x07, 0xaf, 0x90, 0x62, 0x5c, 0x68, 0x98,
++			0x48, 0x16, 0x11, 0x02, 0x9d, 0xee, 0xb4, 0x9b,
++			0xe5, 0x42, 0x7f, 0x08, 0xfd, 0x16, 0x32, 0x0b,
++			0xd0, 0xb3, 0xfa, 0x2b, 0xb7, 0x99, 0xf9, 0x29,
++			0xcd, 0x20, 0x45, 0x9f, 0xb3, 0x1a, 0x5d, 0xa2,
++			0xaf, 0x4d, 0xe0, 0xbd, 0x42, 0x0d, 0xbc, 0x74,
++			0x99, 0x9c, 0x8e, 0x53, 0x1a, 0xb4, 0x3e, 0xbd,
++			0xa2, 0x9a, 0x2d, 0xf7, 0xf8, 0x39, 0x0f, 0x67,
++			0x63, 0xfc, 0x6b, 0xc0, 0xaf, 0xb3, 0x4b, 0x4f,
++			0x55, 0xc4, 0xcf, 0xa7, 0xc8, 0x04, 0x11, 0x3e,
++			0x14, 0x32, 0xbb, 0x1b, 0x38, 0x77, 0xd6, 0x7f,
++			0x54, 0x4c, 0xdf, 0x75, 0xf3, 0x07, 0x2d, 0x33,
++			0x9b, 0xa8, 0x20, 0xe1, 0x7b, 0x12, 0xb5, 0xf3,
++			0xef, 0x2f, 0xce, 0x72, 0xe5, 0x24, 0x60, 0xc1,
++			0x30, 0xe2, 0xab, 0xa1, 0x8e, 0x11, 0x09, 0xa8,
++			0x21, 0x33, 0x44, 0xfe, 0x7f, 0x35, 0x32, 0x93,
++			0x39, 0xa7, 0xad, 0x8b, 0x79, 0x06, 0xb2, 0xcb,
++			0x4e, 0xa9, 0x5f, 0xc7, 0xba, 0x74, 0x29, 0xec,
++			0x93, 0xa0, 0x4e, 0x54, 0x93, 0xc0, 0xbc, 0x55,
++			0x64, 0xf0, 0x48, 0xe5, 0x57, 0x99, 0xee, 0x75,
++			0xd6, 0x79, 0x0f, 0x66, 0xb7, 0xc6, 0x57, 0x76,
++			0xf7, 0xb7, 0xf3, 0x9c, 0xc5, 0x60, 0xe8, 0x7f,
++			0x83, 0x76, 0xd6, 0x0e, 0xaa, 0xe6, 0x90, 0x39,
++			0x1d, 0xa6, 0x32, 0x6a, 0x34, 0xe3, 0x55, 0xf8,
++			0x58, 0xa0, 0x58, 0x7d, 0x33, 0xe0, 0x22, 0x39,
++			0x44, 0x64, 0x87, 0x86, 0x5a, 0x2f, 0xa7, 0x7e,
++			0x0f, 0x38, 0xea, 0xb0, 0x30, 0xcc, 0x61, 0xa5,
++			0x6a, 0x32, 0xae, 0x1e, 0xf7, 0xe9, 0xd0, 0xa9,
++			0x0c, 0x32, 0x4b, 0xb5, 0x49, 0x28, 0xab, 0x85,
++			0x2f, 0x8e, 0x01, 0x36, 0x38, 0x52, 0xd0, 0xba,
++			0xd6, 0x02, 0x78, 0xf8, 0x0e, 0x3e, 0x9c, 0x8b,
++			0x6b, 0x45, 0x99, 0x3f, 0x5c, 0xfe, 0x58, 0xf1,
++			0x5c, 0x94, 0x04, 0xe1, 0xf5, 0x18, 0x6d, 0x51,
++			0xb2, 0x5d, 0x18, 0x20, 0xb6, 0xc2, 0x9a, 0x42,
++			0x1d, 0xb3, 0xab, 0x3c, 0xb6, 0x3a, 0x13, 0x03,
++			0xb2, 0x46, 0x82, 0x4f, 0xfc, 0x64, 0xbc, 0x4f,
++			0xca, 0xfa, 0x9c, 0xc0, 0xd5, 0xa7, 0xbd, 0x11,
++			0xb7, 0xe4, 0x5a, 0xf6, 0x6f, 0x4d, 0x4d, 0x54,
++			0xea, 0xa4, 0x98, 0x66, 0xd4, 0x22, 0x3b, 0xd3,
++			0x8f, 0x34, 0x47, 0xd9, 0x7c, 0xf4, 0x72, 0x3b,
++			0x4d, 0x02, 0x77, 0xf6, 0xd6, 0xdd, 0x08, 0x0a,
++			0x81, 0xe1, 0x86, 0x89, 0x3e, 0x56, 0x10, 0x3c,
++			0xba, 0xd7, 0x81, 0x8c, 0x08, 0xbc, 0x8b, 0xe2,
++			0x53, 0xec, 0xa7, 0x89, 0xee, 0xc8, 0x56, 0xb5,
++			0x36, 0x2c, 0xb2, 0x03, 0xba, 0x99, 0xdd, 0x7c,
++			0x48, 0xa0, 0xb0, 0xbc, 0x91, 0x33, 0xe9, 0xa8,
++			0xcb, 0xcd, 0xcf, 0x59, 0x5f, 0x1f, 0x15, 0xe2,
++			0x56, 0xf5, 0x4e, 0x01, 0x35, 0x27, 0x45, 0x77,
++			0x47, 0xc8, 0xbc, 0xcb, 0x7e, 0x39, 0xc1, 0x97,
++			0x28, 0xd3, 0x84, 0xfc, 0x2c, 0x3e, 0xc8, 0xad,
++			0x9c, 0xf8, 0x8a, 0x61, 0x9c, 0x28, 0xaa, 0xc5,
++			0x99, 0x20, 0x43, 0x85, 0x9d, 0xa5, 0xe2, 0x8b,
++			0xb8, 0xae, 0xeb, 0xd0, 0x32, 0x0d, 0x52, 0x78,
++			0x09, 0x56, 0x3f, 0xc7, 0xd8, 0x7e, 0x26, 0xfc,
++			0x37, 0xfb, 0x6f, 0x04, 0xfc, 0xfa, 0x92, 0x10,
++			0xac, 0xf8, 0x3e, 0x21, 0xdc, 0x8c, 0x21, 0x16,
++			0x7d, 0x67, 0x6e, 0xf6, 0xcd, 0xda, 0xb6, 0x98,
++			0x23, 0xab, 0x23, 0x3c, 0xb2, 0x10, 0xa0, 0x53,
++			0x5a, 0x56, 0x9f, 0xc5, 0xd0, 0xff, 0xbb, 0xe4,
++			0x98, 0x3c, 0x69, 0x1e, 0xdb, 0x38, 0x8f, 0x7e,
++			0x0f, 0xd2, 0x98, 0x88, 0x81, 0x8b, 0x45, 0x67,
++			0xea, 0x33, 0xf1, 0xeb, 0xe9, 0x97, 0x55, 0x2e,
++			0xd9, 0xaa, 0xeb, 0x5a, 0xec, 0xda, 0xe1, 0x68,
++			0xa8, 0x9d, 0x3c, 0x84, 0x7c, 0x05, 0x3d, 0x62,
++			0x87, 0x8f, 0x03, 0x21, 0x28, 0x95, 0x0c, 0x89,
++			0x25, 0x22, 0x4a, 0xb0, 0x93, 0xa9, 0x50, 0xa2,
++			0x2f, 0x57, 0x6e, 0x18, 0x42, 0x19, 0x54, 0x0c,
++			0x55, 0x67, 0xc6, 0x11, 0x49, 0xf4, 0x5c, 0xd2,
++			0xe9, 0x3d, 0xdd, 0x8b, 0x48, 0x71, 0x21, 0x00,
++			0xc3, 0x9a, 0x6c, 0x85, 0x74, 0x28, 0x83, 0x4a,
++			0x1b, 0x31, 0x05, 0xe1, 0x06, 0x92, 0xe7, 0xda,
++			0x85, 0x73, 0x78, 0x45, 0x20, 0x7f, 0xae, 0x13,
++			0x7c, 0x33, 0x06, 0x22, 0xf4, 0x83, 0xf9, 0x35,
++			0x3f, 0x6c, 0x71, 0xa8, 0x4e, 0x48, 0xbe, 0x9b,
++			0xce, 0x8a, 0xba, 0xda, 0xbe, 0x28, 0x08, 0xf7,
++			0xe2, 0x14, 0x8c, 0x71, 0xea, 0x72, 0xf9, 0x33,
++			0xf2, 0x88, 0x3f, 0xd7, 0xbb, 0x69, 0x6c, 0x29,
++			0x19, 0xdc, 0x84, 0xce, 0x1f, 0x12, 0x4f, 0xc8,
++			0xaf, 0xa5, 0x04, 0xba, 0x5a, 0xab, 0xb0, 0xd9,
++			0x14, 0x1f, 0x6c, 0x68, 0x98, 0x39, 0x89, 0x7a,
++			0xd9, 0xd8, 0x2f, 0xdf, 0xa8, 0x47, 0x4a, 0x25,
++			0xe2, 0xfb, 0x33, 0xf4, 0x59, 0x78, 0xe1, 0x68,
++			0x85, 0xcf, 0xfe, 0x59, 0x20, 0xd4, 0x05, 0x1d,
++			0x80, 0x99, 0xae, 0xbc, 0xca, 0xae, 0x0f, 0x2f,
++			0x65, 0x43, 0x34, 0x8e, 0x7e, 0xac, 0xd3, 0x93,
++			0x2f, 0xac, 0x6d, 0x14, 0x3d, 0x02, 0x07, 0x70,
++			0x9d, 0xa4, 0xf3, 0x1b, 0x5c, 0x36, 0xfc, 0x01,
++			0x73, 0x34, 0x85, 0x0c, 0x6c, 0xd6, 0xf1, 0xbd,
++			0x3f, 0xdf, 0xee, 0xf5, 0xd9, 0xba, 0x56, 0xef,
++			0xf4, 0x9b, 0x6b, 0xee, 0x9f, 0x5a, 0x78, 0x6d,
++			0x32, 0x19, 0xf4, 0xf7, 0xf8, 0x4c, 0x69, 0x0b,
++			0x4b, 0xbc, 0xbb, 0xb7, 0xf2, 0x85, 0xaf, 0x70,
++			0x75, 0x24, 0x6c, 0x54, 0xa7, 0x0e, 0x4d, 0x1d,
++			0x01, 0xbf, 0x08, 0xac, 0xcf, 0x7f, 0x2c, 0xe3,
++			0x14, 0x89, 0x5e, 0x70, 0x5a, 0x99, 0x92, 0xcd,
++			0x01, 0x84, 0xc8, 0xd2, 0xab, 0xe5, 0x4f, 0x58,
++			0xe7, 0x0f, 0x2f, 0x0e, 0xff, 0x68, 0xea, 0xfd,
++			0x15, 0xb3, 0x17, 0xe6, 0xb0, 0xe7, 0x85, 0xd8,
++			0x23, 0x2e, 0x05, 0xc7, 0xc9, 0xc4, 0x46, 0x1f,
++			0xe1, 0x9e, 0x49, 0x20, 0x23, 0x24, 0x4d, 0x7e,
++			0x29, 0x65, 0xff, 0xf4, 0xb6, 0xfd, 0x1a, 0x85,
++			0xc4, 0x16, 0xec, 0xfc, 0xea, 0x7b, 0xd6, 0x2c,
++			0x43, 0xf8, 0xb7, 0xbf, 0x79, 0xc0, 0x85, 0xcd,
++			0xef, 0xe1, 0x98, 0xd3, 0xa5, 0xf7, 0x90, 0x8c,
++			0xe9, 0x7f, 0x80, 0x6b, 0xd2, 0xac, 0x4c, 0x30,
++			0xa7, 0xc6, 0x61, 0x6c, 0xd2, 0xf9, 0x2c, 0xff,
++			0x30, 0xbc, 0x22, 0x81, 0x7d, 0x93, 0x12, 0xe4,
++			0x0a, 0xcd, 0xaf, 0xdd, 0xe8, 0xab, 0x0a, 0x1e,
++			0x13, 0xa4, 0x27, 0xc3, 0x5f, 0xf7, 0x4b, 0xbb,
++			0x37, 0x09, 0x4b, 0x91, 0x6f, 0x92, 0x4f, 0xaf,
++			0x52, 0xee, 0xdf, 0xef, 0x09, 0x6f, 0xf7, 0x5c,
++			0x6e, 0x12, 0x17, 0x72, 0x63, 0x57, 0xc7, 0xba,
++			0x3b, 0x6b, 0x38, 0x32, 0x73, 0x1b, 0x9c, 0x80,
++			0xc1, 0x7a, 0xc6, 0xcf, 0xcd, 0x35, 0xc0, 0x6b,
++			0x31, 0x1a, 0x6b, 0xe9, 0xd8, 0x2c, 0x29, 0x3f,
++			0x96, 0xfb, 0xb6, 0xcd, 0x13, 0x91, 0x3b, 0xc2,
++			0xd2, 0xa3, 0x31, 0x8d, 0xa4, 0xcd, 0x57, 0xcd,
++			0x13, 0x3d, 0x64, 0xfd, 0x06, 0xce, 0xe6, 0xdc,
++			0x0c, 0x24, 0x43, 0x31, 0x40, 0x57, 0xf1, 0x72,
++			0x17, 0xe3, 0x3a, 0x63, 0x6d, 0x35, 0xcf, 0x5d,
++			0x97, 0x40, 0x59, 0xdd, 0xf7, 0x3c, 0x02, 0xf7,
++			0x1c, 0x7e, 0x05, 0xbb, 0xa9, 0x0d, 0x01, 0xb1,
++			0x8e, 0xc0, 0x30, 0xa9, 0x53, 0x24, 0xc9, 0x89,
++			0x84, 0x6d, 0xaa, 0xd0, 0xcd, 0x91, 0xc2, 0x4d,
++			0x91, 0xb0, 0x89, 0xe2, 0xbf, 0x83, 0x44, 0xaa,
++			0x28, 0x72, 0x23, 0xa0, 0xc2, 0xad, 0xad, 0x1c,
++			0xfc, 0x3f, 0x09, 0x7a, 0x0b, 0xdc, 0xc5, 0x1b,
++			0x87, 0x13, 0xc6, 0x5b, 0x59, 0x8d, 0xf2, 0xc8,
++			0xaf, 0xdf, 0x11, 0x95,
++		},
++		.rlen = 4100,
++	},
++};
 +
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Counter with CBC MAC");
-+MODULE_ALIAS("ccm_base");
-+MODULE_ALIAS("rfc4309");
-diff --git a/crypto/chainiv.c b/crypto/chainiv.c
-new file mode 100644
-index 0000000..d17fa04
---- /dev/null
-+++ b/crypto/chainiv.c
-@@ -0,0 +1,331 @@
-+/*
-+ * chainiv: Chain IV Generator
-+ *
-+ * Generate IVs simply be using the last block of the previous encryption.
-+ * This is mainly useful for CBC with a synchronous algorithm.
-+ *
-+ * Copyright (c) 2007 Herbert Xu <herbert at gondor.apana.org.au>
-+ *
-+ * 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.
-+ *
+ /*
+  * Compression stuff.
+  */
+@@ -4408,6 +7721,88 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
+ };
+ 
+ /*
++ * LZO test vectors (null-terminated strings).
 + */
++#define LZO_COMP_TEST_VECTORS 2
++#define LZO_DECOMP_TEST_VECTORS 2
 +
-+#include <crypto/internal/skcipher.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/random.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+#include <linux/workqueue.h>
-+
-+enum {
-+	CHAINIV_STATE_INUSE = 0,
++static struct comp_testvec lzo_comp_tv_template[] = {
++	{
++		.inlen	= 70,
++		.outlen	= 46,
++		.input	= "Join us now and share the software "
++			  "Join us now and share the software ",
++		.output	= {  0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
++			     0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
++			     0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
++			     0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
++			     0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
++			     0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
++	}, {
++		.inlen	= 159,
++		.outlen	= 133,
++		.input	= "This document describes a compression method based on the LZO "
++			  "compression algorithm.  This document defines the application of "
++			  "the LZO algorithm used in UBIFS.",
++		.output	= { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
++			    0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
++			    0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
++			    0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
++			    0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
++			    0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
++			    0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
++			    0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
++			    0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
++			    0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
++			    0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
++			    0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
++			    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
++			    0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
++			    0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
++			    0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
++			    0x53, 0x2e, 0x11, 0x00, 0x00 },
++	},
 +};
 +
-+struct chainiv_ctx {
-+	spinlock_t lock;
-+	char iv[];
++static struct comp_testvec lzo_decomp_tv_template[] = {
++	{
++		.inlen	= 133,
++		.outlen	= 159,
++		.input	= { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
++			    0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
++			    0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
++			    0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
++			    0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
++			    0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
++			    0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
++			    0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
++			    0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
++			    0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
++			    0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
++			    0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
++			    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
++			    0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
++			    0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
++			    0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
++			    0x53, 0x2e, 0x11, 0x00, 0x00 },
++		.output	= "This document describes a compression method based on the LZO "
++			  "compression algorithm.  This document defines the application of "
++			  "the LZO algorithm used in UBIFS.",
++	}, {
++		.inlen	= 46,
++		.outlen	= 70,
++		.input	= { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
++			    0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
++			    0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
++			    0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
++			    0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
++			    0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
++		.output	= "Join us now and share the software "
++			  "Join us now and share the software ",
++	},
 +};
 +
-+struct async_chainiv_ctx {
-+	unsigned long state;
-+
-+	spinlock_t lock;
-+	int err;
-+
-+	struct crypto_queue queue;
-+	struct work_struct postponed;
++/*
+  * Michael MIC test vectors from IEEE 802.11i
+  */
+ #define MICHAEL_MIC_TEST_VECTORS 6
+@@ -4812,4 +8207,20 @@ static struct cipher_speed camellia_speed_template[] = {
+       {  .klen = 0, .blen = 0, }
+ };
+ 
++static struct cipher_speed salsa20_speed_template[] = {
++      { .klen = 16, .blen = 16, },
++      { .klen = 16, .blen = 64, },
++      { .klen = 16, .blen = 256, },
++      { .klen = 16, .blen = 1024, },
++      { .klen = 16, .blen = 8192, },
++      { .klen = 32, .blen = 16, },
++      { .klen = 32, .blen = 64, },
++      { .klen = 32, .blen = 256, },
++      { .klen = 32, .blen = 1024, },
++      { .klen = 32, .blen = 8192, },
 +
-+	char iv[];
++      /* End marker */
++      {  .klen = 0, .blen = 0, }
 +};
 +
-+static int chainiv_givencrypt(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
-+	unsigned int ivsize;
-+	int err;
-+
-+	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
-+	ablkcipher_request_set_callback(subreq, req->creq.base.flags &
-+						~CRYPTO_TFM_REQ_MAY_SLEEP,
-+					req->creq.base.complete,
-+					req->creq.base.data);
-+	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
-+				     req->creq.nbytes, req->creq.info);
-+
-+	spin_lock_bh(&ctx->lock);
-+
-+	ivsize = crypto_ablkcipher_ivsize(geniv);
-+
-+	memcpy(req->giv, ctx->iv, ivsize);
-+	memcpy(subreq->info, ctx->iv, ivsize);
-+
-+	err = crypto_ablkcipher_encrypt(subreq);
-+	if (err)
-+		goto unlock;
-+
-+	memcpy(ctx->iv, subreq->info, ivsize);
-+
-+unlock:
-+	spin_unlock_bh(&ctx->lock);
-+
-+	return err;
-+}
+ #endif	/* _CRYPTO_TCRYPT_H */
+diff --git a/crypto/twofish_common.c b/crypto/twofish_common.c
+index b4b9c0c..0af216c 100644
+--- a/crypto/twofish_common.c
++++ b/crypto/twofish_common.c
+@@ -655,84 +655,48 @@ int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len)
+ 			CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+ 		}
+ 
+-		/* Calculate whitening and round subkeys.  The constants are
+-		 * indices of subkeys, preprocessed through q0 and q1. */
+-		CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
+-		CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
+-		CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
+-		CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
+-		CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
+-		CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
+-		CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
+-		CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
+-		CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
+-		CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
+-		CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71);
+-		CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
+-		CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F);
+-		CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
+-		CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
+-		CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F);
+-		CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
+-		CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
+-		CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00);
+-		CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
++		/* CALC_K256/CALC_K192/CALC_K loops were unrolled.
++		 * Unrolling produced x2.5 more code (+18k on i386),
++		 * and speeded up key setup by 7%:
++		 * unrolled: twofish_setkey/sec: 41128
++		 *     loop: twofish_setkey/sec: 38148
++		 * CALC_K256: ~100 insns each
++		 * CALC_K192: ~90 insns
++		 *    CALC_K: ~70 insns
++		 */
++		/* Calculate whitening and round subkeys */
++		for ( i = 0; i < 8; i += 2 ) {
++			CALC_K256 (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
++		}
++		for ( i = 0; i < 32; i += 2 ) {
++			CALC_K256 (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
++		}
+ 	} else if (key_len == 24) { /* 192-bit key */
+ 		/* Compute the S-boxes. */
+ 		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
+ 		        CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+ 		}
+ 
+-		/* Calculate whitening and round subkeys.  The constants are
+-		 * indices of subkeys, preprocessed through q0 and q1. */
+-		CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
+-		CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
+-		CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
+-		CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
+-		CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
+-		CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
+-		CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
+-		CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
+-		CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
+-		CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
+-		CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71);
+-		CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
+-		CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F);
+-		CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
+-		CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
+-		CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F);
+-		CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
+-		CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
+-		CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00);
+-		CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
++		/* Calculate whitening and round subkeys */
++		for ( i = 0; i < 8; i += 2 ) {
++			CALC_K192 (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
++		}
++		for ( i = 0; i < 32; i += 2 ) {
++			CALC_K192 (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
++		}
+ 	} else { /* 128-bit key */
+ 		/* Compute the S-boxes. */
+ 		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
+ 			CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+ 		}
+ 
+-		/* Calculate whitening and round subkeys.  The constants are
+-		 * indices of subkeys, preprocessed through q0 and q1. */
+-		CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3);
+-		CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
+-		CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
+-		CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
+-		CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
+-		CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B);
+-		CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
+-		CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
+-		CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
+-		CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD);
+-		CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71);
+-		CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
+-		CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F);
+-		CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B);
+-		CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA);
+-		CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F);
+-		CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
+-		CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
+-		CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00);
+-		CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
++		/* Calculate whitening and round subkeys */
++		for ( i = 0; i < 8; i += 2 ) {
++			CALC_K (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
++		}
++		for ( i = 0; i < 32; i += 2 ) {
++			CALC_K (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
++		}
+ 	}
+ 
+ 	return 0;
+diff --git a/crypto/xcbc.c b/crypto/xcbc.c
+index ac68f3b..a82959d 100644
+--- a/crypto/xcbc.c
++++ b/crypto/xcbc.c
+@@ -19,6 +19,7 @@
+  * 	Kazunori Miyazawa <miyazawa at linux-ipv6.org>
+  */
+ 
++#include <crypto/scatterwalk.h>
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+ #include <linux/hardirq.h>
+@@ -27,7 +28,6 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/slab.h>
+ #include <linux/scatterlist.h>
+-#include "internal.h"
+ 
+ static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
+ 			   0x02020202, 0x02020202, 0x02020202, 0x02020202,
+@@ -307,7 +307,8 @@ static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
+ 	case 16:
+ 		break;
+ 	default:
+-		return ERR_PTR(PTR_ERR(alg));
++		inst = ERR_PTR(-EINVAL);
++		goto out_put_alg;
+ 	}
+ 
+ 	inst = crypto_alloc_instance("xcbc", alg);
+@@ -320,10 +321,7 @@ static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
+ 	inst->alg.cra_alignmask = alg->cra_alignmask;
+ 	inst->alg.cra_type = &crypto_hash_type;
+ 
+-	inst->alg.cra_hash.digestsize =
+-		(alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+-		CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
+-				       alg->cra_blocksize;
++	inst->alg.cra_hash.digestsize = alg->cra_blocksize;
+ 	inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) +
+ 				ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *));
+ 	inst->alg.cra_init = xcbc_init_tfm;
+diff --git a/drivers/Kconfig b/drivers/Kconfig
+index f4076d9..d74d9fb 100644
+--- a/drivers/Kconfig
++++ b/drivers/Kconfig
+@@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig"
+ 
+ source "drivers/spi/Kconfig"
+ 
++source "drivers/gpio/Kconfig"
 +
-+static int chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ source "drivers/w1/Kconfig"
+ 
+ source "drivers/power/Kconfig"
+@@ -90,9 +92,5 @@ source "drivers/dca/Kconfig"
+ 
+ source "drivers/auxdisplay/Kconfig"
+ 
+-source "drivers/kvm/Kconfig"
+-
+ source "drivers/uio/Kconfig"
+-
+-source "drivers/virtio/Kconfig"
+ endmenu
+diff --git a/drivers/Makefile b/drivers/Makefile
+index 8cb37e3..f1c11db 100644
+--- a/drivers/Makefile
++++ b/drivers/Makefile
+@@ -5,6 +5,7 @@
+ # Rewritten to use lists instead of if-statements.
+ #
+ 
++obj-$(CONFIG_HAVE_GPIO_LIB)	+= gpio/
+ obj-$(CONFIG_PCI)		+= pci/
+ obj-$(CONFIG_PARISC)		+= parisc/
+ obj-$(CONFIG_RAPIDIO)		+= rapidio/
+@@ -38,7 +39,7 @@ obj-$(CONFIG_SCSI)		+= scsi/
+ obj-$(CONFIG_ATA)		+= ata/
+ obj-$(CONFIG_FUSION)		+= message/
+ obj-$(CONFIG_FIREWIRE)		+= firewire/
+-obj-$(CONFIG_IEEE1394)		+= ieee1394/
++obj-y				+= ieee1394/
+ obj-$(CONFIG_UIO)		+= uio/
+ obj-y				+= cdrom/
+ obj-y				+= auxdisplay/
+@@ -47,7 +48,6 @@ obj-$(CONFIG_SPI)		+= spi/
+ obj-$(CONFIG_PCCARD)		+= pcmcia/
+ obj-$(CONFIG_DIO)		+= dio/
+ obj-$(CONFIG_SBUS)		+= sbus/
+-obj-$(CONFIG_KVM)		+= kvm/
+ obj-$(CONFIG_ZORRO)		+= zorro/
+ obj-$(CONFIG_MAC)		+= macintosh/
+ obj-$(CONFIG_ATA_OVER_ETH)	+= block/aoe/
+@@ -73,7 +73,7 @@ obj-$(CONFIG_ISDN)		+= isdn/
+ obj-$(CONFIG_EDAC)		+= edac/
+ obj-$(CONFIG_MCA)		+= mca/
+ obj-$(CONFIG_EISA)		+= eisa/
+-obj-$(CONFIG_LGUEST_GUEST)	+= lguest/
++obj-y				+= lguest/
+ obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
+ obj-$(CONFIG_CPU_IDLE)		+= cpuidle/
+ obj-$(CONFIG_MMC)		+= mmc/
+diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
+index f4487c3..1b4cf98 100644
+--- a/drivers/acpi/bus.c
++++ b/drivers/acpi/bus.c
+@@ -743,7 +743,7 @@ static int __init acpi_bus_init(void)
+ 	return -ENODEV;
+ }
+ 
+-decl_subsys(acpi, NULL, NULL);
++struct kobject *acpi_kobj;
+ 
+ static int __init acpi_init(void)
+ {
+@@ -755,10 +755,11 @@ static int __init acpi_init(void)
+ 		return -ENODEV;
+ 	}
+ 
+-	result = firmware_register(&acpi_subsys);
+-	if (result < 0)
+-		printk(KERN_WARNING "%s: firmware_register error: %d\n",
+-			__FUNCTION__, result);
++	acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
++	if (!acpi_kobj) {
++		printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__);
++		acpi_kobj = NULL;
++	}
+ 
+ 	result = acpi_bus_init();
+ 
+diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
+index 81b2484..fd1c4ba 100644
+--- a/drivers/acpi/hardware/hwsleep.c
++++ b/drivers/acpi/hardware/hwsleep.c
+@@ -192,18 +192,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
+ 	arg.type = ACPI_TYPE_INTEGER;
+ 	arg.integer.value = sleep_state;
+ 
+-	/* Run the _PTS and _GTS methods */
++	/* Run the _PTS method */
+ 
+ 	status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
+ 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+ 		return_ACPI_STATUS(status);
+ 	}
+ 
+-	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
+-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+-		return_ACPI_STATUS(status);
+-	}
+-
+ 	/* Setup the argument to _SST */
+ 
+ 	switch (sleep_state) {
+@@ -234,10 +229,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
+ 				"While executing method _SST"));
+ 	}
+ 
+-	/* Disable/Clear all GPEs */
+-
+-	status = acpi_hw_disable_all_gpes();
+-
+ 	return_ACPI_STATUS(status);
+ }
+ 
+@@ -262,6 +253,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
+ 	struct acpi_bit_register_info *sleep_type_reg_info;
+ 	struct acpi_bit_register_info *sleep_enable_reg_info;
+ 	u32 in_value;
++	struct acpi_object_list arg_list;
++	union acpi_object arg;
+ 	acpi_status status;
+ 
+ 	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
+@@ -307,6 +300,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
+ 		return_ACPI_STATUS(status);
+ 	}
+ 
++	/* Execute the _GTS method */
 +
-+	spin_lock_bh(&ctx->lock);
-+	if (crypto_ablkcipher_crt(geniv)->givencrypt !=
-+	    chainiv_givencrypt_first)
-+		goto unlock;
++	arg_list.count = 1;
++	arg_list.pointer = &arg;
++	arg.type = ACPI_TYPE_INTEGER;
++	arg.integer.value = sleep_state;
 +
-+	crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt;
-+	get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
++	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
++	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
++		return_ACPI_STATUS(status);
++	}
 +
-+unlock:
-+	spin_unlock_bh(&ctx->lock);
+ 	/* Get current value of PM1A control */
+ 
+ 	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
+@@ -473,17 +478,18 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
+ 
+ /*******************************************************************************
+  *
+- * FUNCTION:    acpi_leave_sleep_state
++ * FUNCTION:    acpi_leave_sleep_state_prep
+  *
+- * PARAMETERS:  sleep_state         - Which sleep state we just exited
++ * PARAMETERS:  sleep_state         - Which sleep state we are exiting
+  *
+  * RETURN:      Status
+  *
+- * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
+- *              Called with interrupts ENABLED.
++ * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
++ *              sleep.
++ *              Called with interrupts DISABLED.
+  *
+  ******************************************************************************/
+-acpi_status acpi_leave_sleep_state(u8 sleep_state)
++acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
+ {
+ 	struct acpi_object_list arg_list;
+ 	union acpi_object arg;
+@@ -493,7 +499,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
+ 	u32 PM1Acontrol;
+ 	u32 PM1Bcontrol;
+ 
+-	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
++	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
+ 
+ 	/*
+ 	 * Set SLP_TYPE and SLP_EN to state S0.
+@@ -540,6 +546,41 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
+ 		}
+ 	}
+ 
++	/* Execute the _BFS method */
 +
-+	return chainiv_givencrypt(req);
-+}
++	arg_list.count = 1;
++	arg_list.pointer = &arg;
++	arg.type = ACPI_TYPE_INTEGER;
++	arg.integer.value = sleep_state;
 +
-+static int chainiv_init_common(struct crypto_tfm *tfm)
-+{
-+	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
++	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
++	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
++		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
++	}
 +
-+	return skcipher_geniv_init(tfm);
++	return_ACPI_STATUS(status);
 +}
 +
-+static int chainiv_init(struct crypto_tfm *tfm)
++/*******************************************************************************
++ *
++ * FUNCTION:    acpi_leave_sleep_state
++ *
++ * PARAMETERS:  sleep_state         - Which sleep state we just exited
++ *
++ * RETURN:      Status
++ *
++ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
++ *              Called with interrupts ENABLED.
++ *
++ ******************************************************************************/
++acpi_status acpi_leave_sleep_state(u8 sleep_state)
 +{
-+	struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	spin_lock_init(&ctx->lock);
++	struct acpi_object_list arg_list;
++	union acpi_object arg;
++	acpi_status status;
 +
-+	return chainiv_init_common(tfm);
-+}
++	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
 +
-+static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx)
+ 	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
+ 
+ 	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
+@@ -558,12 +599,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
+ 		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
+ 	}
+ 
+-	arg.integer.value = sleep_state;
+-	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
+-	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
+-		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+-	}
+-
+ 	/*
+ 	 * GPEs must be enabled before _WAK is called as GPEs
+ 	 * might get fired there
+diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
+index c9f526e..5400ea1 100644
+--- a/drivers/acpi/pci_link.c
++++ b/drivers/acpi/pci_link.c
+@@ -911,7 +911,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set);
+ 
+ /* FIXME: we will remove this interface after all drivers call pci_disable_device */
+ static struct sysdev_class irqrouter_sysdev_class = {
+-	set_kset_name("irqrouter"),
++	.name = "irqrouter",
+ 	.resume = irqrouter_resume,
+ };
+ 
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index 2235f4e..199ea21 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -38,7 +38,7 @@
+ #include <linux/dmi.h>
+ #include <linux/moduleparam.h>
+ #include <linux/sched.h>	/* need_resched() */
+-#include <linux/latency.h>
++#include <linux/pm_qos_params.h>
+ #include <linux/clockchips.h>
+ #include <linux/cpuidle.h>
+ 
+@@ -357,6 +357,26 @@ int acpi_processor_resume(struct acpi_device * device)
+ 	return 0;
+ }
+ 
++#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
++static int tsc_halts_in_c(int state)
 +{
-+	int queued;
-+
-+	if (!ctx->queue.qlen) {
-+		smp_mb__before_clear_bit();
-+		clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
-+
-+		if (!ctx->queue.qlen ||
-+		    test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
-+			goto out;
++	switch (boot_cpu_data.x86_vendor) {
++	case X86_VENDOR_AMD:
++		/*
++		 * AMD Fam10h TSC will tick in all
++		 * C/P/S0/S1 states when this bit is set.
++		 */
++		if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
++			return 0;
++		/*FALL THROUGH*/
++	case X86_VENDOR_INTEL:
++		/* Several cases known where TSC halts in C2 too */
++	default:
++		return state > ACPI_STATE_C1;
 +	}
-+
-+	queued = schedule_work(&ctx->postponed);
-+	BUG_ON(!queued);
-+
-+out:
-+	return ctx->err;
 +}
++#endif
 +
-+static int async_chainiv_postpone_request(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	int err;
-+
-+	spin_lock_bh(&ctx->lock);
-+	err = skcipher_enqueue_givcrypt(&ctx->queue, req);
-+	spin_unlock_bh(&ctx->lock);
-+
-+	if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
-+		return err;
+ #ifndef CONFIG_CPU_IDLE
+ static void acpi_processor_idle(void)
+ {
+@@ -516,7 +536,8 @@ static void acpi_processor_idle(void)
+ 
+ #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
+ 		/* TSC halts in C2, so notify users */
+-		mark_tsc_unstable("possible TSC halt in C2");
++		if (tsc_halts_in_c(ACPI_STATE_C2))
++			mark_tsc_unstable("possible TSC halt in C2");
+ #endif
+ 		/* Compute time (ticks) that we were actually asleep */
+ 		sleep_ticks = ticks_elapsed(t1, t2);
+@@ -534,6 +555,7 @@ static void acpi_processor_idle(void)
+ 		break;
+ 
+ 	case ACPI_STATE_C3:
++		acpi_unlazy_tlb(smp_processor_id());
+ 		/*
+ 		 * Must be done before busmaster disable as we might
+ 		 * need to access HPET !
+@@ -579,7 +601,8 @@ static void acpi_processor_idle(void)
+ 
+ #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
+ 		/* TSC halts in C3, so notify users */
+-		mark_tsc_unstable("TSC halts in C3");
++		if (tsc_halts_in_c(ACPI_STATE_C3))
++			mark_tsc_unstable("TSC halts in C3");
+ #endif
+ 		/* Compute time (ticks) that we were actually asleep */
+ 		sleep_ticks = ticks_elapsed(t1, t2);
+@@ -625,7 +648,8 @@ static void acpi_processor_idle(void)
+ 	if (cx->promotion.state &&
+ 	    ((cx->promotion.state - pr->power.states) <= max_cstate)) {
+ 		if (sleep_ticks > cx->promotion.threshold.ticks &&
+-		  cx->promotion.state->latency <= system_latency_constraint()) {
++		  cx->promotion.state->latency <=
++				pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
+ 			cx->promotion.count++;
+ 			cx->demotion.count = 0;
+ 			if (cx->promotion.count >=
+@@ -669,7 +693,8 @@ static void acpi_processor_idle(void)
+ 	 * or if the latency of the current state is unacceptable
+ 	 */
+ 	if ((pr->power.state - pr->power.states) > max_cstate ||
+-		pr->power.state->latency > system_latency_constraint()) {
++		pr->power.state->latency >
++				pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
+ 		if (cx->demotion.state)
+ 			next_state = cx->demotion.state;
+ 	}
+@@ -1177,7 +1202,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
+ 		   "maximum allowed latency: %d usec\n",
+ 		   pr->power.state ? pr->power.state - pr->power.states : 0,
+ 		   max_cstate, (unsigned)pr->power.bm_activity,
+-		   system_latency_constraint());
++		   pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
+ 
+ 	seq_puts(seq, "states:\n");
+ 
+@@ -1423,6 +1448,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+ 		return 0;
+ 	}
+ 
++	acpi_unlazy_tlb(smp_processor_id());
+ 	/*
+ 	 * Must be done before busmaster disable as we might need to
+ 	 * access HPET !
+@@ -1443,7 +1469,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+ 
+ #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
+ 	/* TSC could halt in idle, so notify users */
+-	mark_tsc_unstable("TSC halts in idle");;
++	if (tsc_halts_in_c(cx->type))
++		mark_tsc_unstable("TSC halts in idle");;
+ #endif
+ 	sleep_ticks = ticks_elapsed(t1, t2);
+ 
+@@ -1554,7 +1581,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+ 
+ #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
+ 	/* TSC could halt in idle, so notify users */
+-	mark_tsc_unstable("TSC halts in idle");
++	if (tsc_halts_in_c(ACPI_STATE_C3))
++		mark_tsc_unstable("TSC halts in idle");
+ #endif
+ 	sleep_ticks = ticks_elapsed(t1, t2);
+ 	/* Tell the scheduler how much we idled: */
+@@ -1692,8 +1720,9 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr,
+ 			       "ACPI: processor limited to max C-state %d\n",
+ 			       max_cstate);
+ 		first_run++;
+-#if !defined (CONFIG_CPU_IDLE) && defined (CONFIG_SMP)
+-		register_latency_notifier(&acpi_processor_latency_notifier);
++#if !defined(CONFIG_CPU_IDLE) && defined(CONFIG_SMP)
++		pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY,
++				&acpi_processor_latency_notifier);
+ #endif
+ 	}
+ 
+@@ -1780,7 +1809,8 @@ int acpi_processor_power_exit(struct acpi_processor *pr,
+ 		 */
+ 		cpu_idle_wait();
+ #ifdef CONFIG_SMP
+-		unregister_latency_notifier(&acpi_processor_latency_notifier);
++		pm_qos_remove_notifier(PM_QOS_CPU_DMA_LATENCY,
++				&acpi_processor_latency_notifier);
+ #endif
+ 	}
+ #endif
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index cbfe9ae..d9d531c 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -830,7 +830,7 @@ static int acpi_bus_get_flags(struct acpi_device *device)
+ 	if (ACPI_SUCCESS(status))
+ 		device->flags.wake_capable = 1;
+ 
+-	/* TBD: Peformance management */
++	/* TBD: Performance management */
+ 
+ 	return 0;
+ }
+diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
+index 2c0b663..485de13 100644
+--- a/drivers/acpi/sleep/main.c
++++ b/drivers/acpi/sleep/main.c
+@@ -26,9 +26,24 @@ u8 sleep_states[ACPI_S_STATE_COUNT];
+ 
+ #ifdef CONFIG_PM_SLEEP
+ static u32 acpi_target_sleep_state = ACPI_STATE_S0;
++static bool acpi_sleep_finish_wake_up;
 +
-+	ctx->err = err;
-+	return async_chainiv_schedule_work(ctx);
-+}
++/*
++ * ACPI 2.0 and later want us to execute _PTS after suspending devices, so we
++ * allow the user to request that behavior by using the 'acpi_new_pts_ordering'
++ * kernel command line option that causes the following variable to be set.
++ */
++static bool new_pts_ordering;
 +
-+static int async_chainiv_givencrypt_tail(struct skcipher_givcrypt_request *req)
++static int __init acpi_new_pts_ordering(char *str)
 +{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
-+	unsigned int ivsize = crypto_ablkcipher_ivsize(geniv);
-+
-+	memcpy(req->giv, ctx->iv, ivsize);
-+	memcpy(subreq->info, ctx->iv, ivsize);
-+
-+	ctx->err = crypto_ablkcipher_encrypt(subreq);
-+	if (ctx->err)
-+		goto out;
-+
-+	memcpy(ctx->iv, subreq->info, ivsize);
-+
-+out:
-+	return async_chainiv_schedule_work(ctx);
++	new_pts_ordering = true;
++	return 1;
 +}
++__setup("acpi_new_pts_ordering", acpi_new_pts_ordering);
+ #endif
+ 
+-int acpi_sleep_prepare(u32 acpi_state)
++static int acpi_sleep_prepare(u32 acpi_state)
+ {
+ #ifdef CONFIG_ACPI_SLEEP
+ 	/* do we have a wakeup address for S2 and S3? */
+@@ -44,6 +59,8 @@ int acpi_sleep_prepare(u32 acpi_state)
+ 	ACPI_FLUSH_CPU_CACHE();
+ 	acpi_enable_wakeup_device_prep(acpi_state);
+ #endif
++	printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
++		acpi_state);
+ 	acpi_enter_sleep_state_prep(acpi_state);
+ 	return 0;
+ }
+@@ -63,17 +80,25 @@ static u32 acpi_suspend_states[] = {
+ static int init_8259A_after_S1;
+ 
+ /**
+- *	acpi_pm_set_target - Set the target system sleep state to the state
++ *	acpi_pm_begin - Set the target system sleep state to the state
+  *		associated with given @pm_state, if supported.
+  */
+ 
+-static int acpi_pm_set_target(suspend_state_t pm_state)
++static int acpi_pm_begin(suspend_state_t pm_state)
+ {
+ 	u32 acpi_state = acpi_suspend_states[pm_state];
+ 	int error = 0;
+ 
+ 	if (sleep_states[acpi_state]) {
+ 		acpi_target_sleep_state = acpi_state;
++		if (new_pts_ordering)
++			return 0;
 +
-+static int async_chainiv_givencrypt(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
-+
-+	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
-+	ablkcipher_request_set_callback(subreq, req->creq.base.flags,
-+					req->creq.base.complete,
-+					req->creq.base.data);
-+	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
-+				     req->creq.nbytes, req->creq.info);
-+
-+	if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
-+		goto postpone;
-+
-+	if (ctx->queue.qlen) {
-+		clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
-+		goto postpone;
++		error = acpi_sleep_prepare(acpi_state);
++		if (error)
++			acpi_target_sleep_state = ACPI_STATE_S0;
++		else
++			acpi_sleep_finish_wake_up = true;
+ 	} else {
+ 		printk(KERN_ERR "ACPI does not support this state: %d\n",
+ 			pm_state);
+@@ -91,12 +116,17 @@ static int acpi_pm_set_target(suspend_state_t pm_state)
+ 
+ static int acpi_pm_prepare(void)
+ {
+-	int error = acpi_sleep_prepare(acpi_target_sleep_state);
++	if (new_pts_ordering) {
++		int error = acpi_sleep_prepare(acpi_target_sleep_state);
+ 
+-	if (error)
+-		acpi_target_sleep_state = ACPI_STATE_S0;
++		if (error) {
++			acpi_target_sleep_state = ACPI_STATE_S0;
++			return error;
++		}
++		acpi_sleep_finish_wake_up = true;
 +	}
+ 
+-	return error;
++	return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
+ }
+ 
+ /**
+@@ -120,10 +150,8 @@ static int acpi_pm_enter(suspend_state_t pm_state)
+ 	if (acpi_state == ACPI_STATE_S3) {
+ 		int error = acpi_save_state_mem();
+ 
+-		if (error) {
+-			acpi_target_sleep_state = ACPI_STATE_S0;
++		if (error)
+ 			return error;
+-		}
+ 	}
+ 
+ 	local_irq_save(flags);
+@@ -139,6 +167,9 @@ static int acpi_pm_enter(suspend_state_t pm_state)
+ 		break;
+ 	}
+ 
++	/* Reprogram control registers and execute _BFS */
++	acpi_leave_sleep_state_prep(acpi_state);
 +
-+	return async_chainiv_givencrypt_tail(req);
+ 	/* ACPI 3.0 specs (P62) says that it's the responsabilty
+ 	 * of the OSPM to clear the status bit [ implying that the
+ 	 * POWER_BUTTON event should not reach userspace ]
+@@ -146,6 +177,13 @@ static int acpi_pm_enter(suspend_state_t pm_state)
+ 	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3))
+ 		acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
+ 
++	/*
++	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
++	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
++	 * acpi_leave_sleep_state will reenable specific GPEs later
++	 */
++	acpi_hw_disable_all_gpes();
 +
-+postpone:
-+	return async_chainiv_postpone_request(req);
-+}
+ 	local_irq_restore(flags);
+ 	printk(KERN_DEBUG "Back to C!\n");
+ 
+@@ -157,7 +195,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
+ }
+ 
+ /**
+- *	acpi_pm_finish - Finish up suspend sequence.
++ *	acpi_pm_finish - Instruct the platform to leave a sleep state.
+  *
+  *	This is called after we wake back up (or if entering the sleep state
+  *	failed). 
+@@ -174,6 +212,7 @@ static void acpi_pm_finish(void)
+ 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+ 
+ 	acpi_target_sleep_state = ACPI_STATE_S0;
++	acpi_sleep_finish_wake_up = false;
+ 
+ #ifdef CONFIG_X86
+ 	if (init_8259A_after_S1) {
+@@ -183,6 +222,20 @@ static void acpi_pm_finish(void)
+ #endif
+ }
+ 
++/**
++ *	acpi_pm_end - Finish up suspend sequence.
++ */
 +
-+static int async_chainiv_givencrypt_first(struct skcipher_givcrypt_request *req)
++static void acpi_pm_end(void)
 +{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct async_chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+
-+	if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
-+		goto out;
-+
-+	if (crypto_ablkcipher_crt(geniv)->givencrypt !=
-+	    async_chainiv_givencrypt_first)
-+		goto unlock;
-+
-+	crypto_ablkcipher_crt(geniv)->givencrypt = async_chainiv_givencrypt;
-+	get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
++	/*
++	 * This is necessary in case acpi_pm_finish() is not called directly
++	 * during a failing transition to a sleep state.
++	 */
++	if (acpi_sleep_finish_wake_up)
++		acpi_pm_finish();
++}
 +
-+unlock:
-+	clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+ static int acpi_pm_state_valid(suspend_state_t pm_state)
+ {
+ 	u32 acpi_state;
+@@ -201,10 +254,11 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)
+ 
+ static struct platform_suspend_ops acpi_pm_ops = {
+ 	.valid = acpi_pm_state_valid,
+-	.set_target = acpi_pm_set_target,
++	.begin = acpi_pm_begin,
+ 	.prepare = acpi_pm_prepare,
+ 	.enter = acpi_pm_enter,
+ 	.finish = acpi_pm_finish,
++	.end = acpi_pm_end,
+ };
+ 
+ /*
+@@ -229,15 +283,36 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
+ #endif /* CONFIG_SUSPEND */
+ 
+ #ifdef CONFIG_HIBERNATION
+-static int acpi_hibernation_start(void)
++static int acpi_hibernation_begin(void)
+ {
++	int error;
 +
-+out:
-+	return async_chainiv_givencrypt(req);
-+}
+ 	acpi_target_sleep_state = ACPI_STATE_S4;
+-	return 0;
++	if (new_pts_ordering)
++		return 0;
 +
-+static void async_chainiv_do_postponed(struct work_struct *work)
-+{
-+	struct async_chainiv_ctx *ctx = container_of(work,
-+						     struct async_chainiv_ctx,
-+						     postponed);
-+	struct skcipher_givcrypt_request *req;
-+	struct ablkcipher_request *subreq;
++	error = acpi_sleep_prepare(ACPI_STATE_S4);
++	if (error)
++		acpi_target_sleep_state = ACPI_STATE_S0;
++	else
++		acpi_sleep_finish_wake_up = true;
 +
-+	/* Only handle one request at a time to avoid hogging keventd. */
-+	spin_lock_bh(&ctx->lock);
-+	req = skcipher_dequeue_givcrypt(&ctx->queue);
-+	spin_unlock_bh(&ctx->lock);
++	return error;
+ }
+ 
+ static int acpi_hibernation_prepare(void)
+ {
+-	return acpi_sleep_prepare(ACPI_STATE_S4);
++	if (new_pts_ordering) {
++		int error = acpi_sleep_prepare(ACPI_STATE_S4);
 +
-+	if (!req) {
-+		async_chainiv_schedule_work(ctx);
-+		return;
++		if (error) {
++			acpi_target_sleep_state = ACPI_STATE_S0;
++			return error;
++		}
++		acpi_sleep_finish_wake_up = true;
 +	}
 +
-+	subreq = skcipher_givcrypt_reqctx(req);
-+	subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
-+
-+	async_chainiv_givencrypt_tail(req);
++	return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
+ }
+ 
+ static int acpi_hibernation_enter(void)
+@@ -251,6 +326,8 @@ static int acpi_hibernation_enter(void)
+ 	acpi_enable_wakeup_device(ACPI_STATE_S4);
+ 	/* This shouldn't return.  If it returns, we have a problem */
+ 	status = acpi_enter_sleep_state(ACPI_STATE_S4);
++	/* Reprogram control registers and execute _BFS */
++	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
+ 	local_irq_restore(flags);
+ 
+ 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
+@@ -263,15 +340,12 @@ static void acpi_hibernation_leave(void)
+ 	 * enable it here.
+ 	 */
+ 	acpi_enable();
++	/* Reprogram control registers and execute _BFS */
++	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
+ }
+ 
+ static void acpi_hibernation_finish(void)
+ {
+-	/*
+-	 * If ACPI is not enabled by the BIOS and the boot kernel, we need to
+-	 * enable it here.
+-	 */
+-	acpi_enable();
+ 	acpi_disable_wakeup_device(ACPI_STATE_S4);
+ 	acpi_leave_sleep_state(ACPI_STATE_S4);
+ 
+@@ -279,6 +353,17 @@ static void acpi_hibernation_finish(void)
+ 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+ 
+ 	acpi_target_sleep_state = ACPI_STATE_S0;
++	acpi_sleep_finish_wake_up = false;
 +}
 +
-+static int async_chainiv_init(struct crypto_tfm *tfm)
++static void acpi_hibernation_end(void)
 +{
-+	struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
++	/*
++	 * This is necessary in case acpi_hibernation_finish() is not called
++	 * directly during a failing transition to the sleep state.
++	 */
++	if (acpi_sleep_finish_wake_up)
++		acpi_hibernation_finish();
+ }
+ 
+ static int acpi_hibernation_pre_restore(void)
+@@ -296,7 +381,8 @@ static void acpi_hibernation_restore_cleanup(void)
+ }
+ 
+ static struct platform_hibernation_ops acpi_hibernation_ops = {
+-	.start = acpi_hibernation_start,
++	.begin = acpi_hibernation_begin,
++	.end = acpi_hibernation_end,
+ 	.pre_snapshot = acpi_hibernation_prepare,
+ 	.finish = acpi_hibernation_finish,
+ 	.prepare = acpi_hibernation_prepare,
+@@ -403,6 +489,7 @@ static void acpi_power_off_prepare(void)
+ {
+ 	/* Prepare to power off the system */
+ 	acpi_sleep_prepare(ACPI_STATE_S5);
++	acpi_hw_disable_all_gpes();
+ }
+ 
+ static void acpi_power_off(void)
+diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
+index a2ea125..cfaf8f5 100644
+--- a/drivers/acpi/sleep/sleep.h
++++ b/drivers/acpi/sleep/sleep.h
+@@ -5,5 +5,3 @@ extern int acpi_suspend (u32 state);
+ extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
+ extern void acpi_enable_wakeup_device(u8 sleep_state);
+ extern void acpi_disable_wakeup_device(u8 sleep_state);
+-
+-extern int acpi_sleep_prepare(u32 acpi_state);
+diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
+index edee280..5ffe0ea 100644
+--- a/drivers/acpi/system.c
++++ b/drivers/acpi/system.c
+@@ -58,7 +58,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
+                               FS Interface (/sys)
+    -------------------------------------------------------------------------- */
+ static LIST_HEAD(acpi_table_attr_list);
+-static struct kobject tables_kobj;
++static struct kobject *tables_kobj;
+ 
+ struct acpi_table_attr {
+ 	struct bin_attribute attr;
+@@ -135,11 +135,9 @@ static int acpi_system_sysfs_init(void)
+ 	int table_index = 0;
+ 	int result;
+ 
+-	tables_kobj.parent = &acpi_subsys.kobj;
+-	kobject_set_name(&tables_kobj, "tables");
+-	result = kobject_register(&tables_kobj);
+-	if (result)
+-		return result;
++	tables_kobj = kobject_create_and_add("tables", acpi_kobj);
++	if (!tables_kobj)
++		return -ENOMEM;
+ 
+ 	do {
+ 		result = acpi_get_table_by_index(table_index, &table_header);
+@@ -153,7 +151,7 @@ static int acpi_system_sysfs_init(void)
+ 
+ 			acpi_table_attr_init(table_attr, table_header);
+ 			result =
+-			    sysfs_create_bin_file(&tables_kobj,
++			    sysfs_create_bin_file(tables_kobj,
+ 						  &table_attr->attr);
+ 			if (result) {
+ 				kfree(table_attr);
+@@ -163,6 +161,7 @@ static int acpi_system_sysfs_init(void)
+ 					      &acpi_table_attr_list);
+ 		}
+ 	} while (!result);
++	kobject_uevent(tables_kobj, KOBJ_ADD);
+ 
+ 	return 0;
+ }
+diff --git a/drivers/acpi/utilities/utresrc.c b/drivers/acpi/utilities/utresrc.c
+index cbbd331..b630ee1 100644
+--- a/drivers/acpi/utilities/utresrc.c
++++ b/drivers/acpi/utilities/utresrc.c
+@@ -1,6 +1,6 @@
+ /*******************************************************************************
+  *
+- * Module Name: utresrc - Resource managment utilities
++ * Module Name: utresrc - Resource management utilities
+  *
+  ******************************************************************************/
+ 
+diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
+index ba63619..ba8f7f4 100644
+--- a/drivers/ata/Kconfig
++++ b/drivers/ata/Kconfig
+@@ -69,7 +69,7 @@ config ATA_PIIX
+ 
+ config SATA_MV
+ 	tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
+-	depends on PCI && EXPERIMENTAL
++	depends on EXPERIMENTAL
+ 	help
+ 	  This option enables support for the Marvell Serial ATA family.
+ 	  Currently supports 88SX[56]0[48][01] chips.
+@@ -184,7 +184,7 @@ config PATA_ACPI
+ 
+ config SATA_FSL
+ 	tristate "Freescale 3.0Gbps SATA support"
+-	depends on PPC_MPC837x
++	depends on FSL_SOC
+ 	help
+ 	  This option enables support for Freescale 3.0Gbps SATA controller.
+ 	  It can be found on MPC837x and MPC8315.
+@@ -459,6 +459,15 @@ config PATA_NETCELL
+ 
+ 	  If unsure, say N.
+ 
++config PATA_NINJA32
++	tristate "Ninja32/Delkin Cardbus ATA support (Experimental)"
++	depends on PCI && EXPERIMENTAL
++	help
++	  This option enables support for the Ninja32, Delkin and
++	  possibly other brands of Cardbus ATA adapter
 +
-+	spin_lock_init(&ctx->lock);
++	  If unsure, say N.
 +
-+	crypto_init_queue(&ctx->queue, 100);
-+	INIT_WORK(&ctx->postponed, async_chainiv_do_postponed);
+ config PATA_NS87410
+ 	tristate "Nat Semi NS87410 PATA support (Experimental)"
+ 	depends on PCI && EXPERIMENTAL
+@@ -607,13 +616,23 @@ config PATA_WINBOND_VLB
+ 
+ config PATA_PLATFORM
+ 	tristate "Generic platform device PATA support"
+-	depends on EMBEDDED || ARCH_RPC
++	depends on EMBEDDED || ARCH_RPC || PPC
+ 	help
+ 	  This option enables support for generic directly connected ATA
+ 	  devices commonly found on embedded systems.
+ 
+ 	  If unsure, say N.
+ 
++config PATA_OF_PLATFORM
++	tristate "OpenFirmware platform device PATA support"
++	depends on PATA_PLATFORM && PPC_OF
++	help
++	  This option enables support for generic directly connected ATA
++	  devices commonly found on embedded systems with OpenFirmware
++	  bindings.
 +
-+	return chainiv_init_common(tfm);
-+}
++	  If unsure, say N.
 +
-+static void async_chainiv_exit(struct crypto_tfm *tfm)
+ config PATA_ICSIDE
+ 	tristate "Acorn ICS PATA support"
+ 	depends on ARM && ARCH_ACORN
+diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
+index b13feb2..701651e 100644
+--- a/drivers/ata/Makefile
++++ b/drivers/ata/Makefile
+@@ -41,6 +41,7 @@ obj-$(CONFIG_PATA_IT821X)	+= pata_it821x.o
+ obj-$(CONFIG_PATA_IT8213)	+= pata_it8213.o
+ obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o
+ obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o
++obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o
+ obj-$(CONFIG_PATA_NS87410)	+= pata_ns87410.o
+ obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o
+ obj-$(CONFIG_PATA_OPTI)		+= pata_opti.o
+@@ -67,6 +68,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF)	+= pata_ixp4xx_cf.o
+ obj-$(CONFIG_PATA_SCC)		+= pata_scc.o
+ obj-$(CONFIG_PATA_BF54X)	+= pata_bf54x.o
+ obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o
++obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o
+ obj-$(CONFIG_PATA_ICSIDE)	+= pata_icside.o
+ # Should be last but two libata driver
+ obj-$(CONFIG_PATA_ACPI)		+= pata_acpi.o
+diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
+index 54f38c2..27c8d56 100644
+--- a/drivers/ata/ahci.c
++++ b/drivers/ata/ahci.c
+@@ -198,18 +198,18 @@ enum {
+ };
+ 
+ struct ahci_cmd_hdr {
+-	u32			opts;
+-	u32			status;
+-	u32			tbl_addr;
+-	u32			tbl_addr_hi;
+-	u32			reserved[4];
++	__le32			opts;
++	__le32			status;
++	__le32			tbl_addr;
++	__le32			tbl_addr_hi;
++	__le32			reserved[4];
+ };
+ 
+ struct ahci_sg {
+-	u32			addr;
+-	u32			addr_hi;
+-	u32			reserved;
+-	u32			flags_size;
++	__le32			addr;
++	__le32			addr_hi;
++	__le32			reserved;
++	__le32			flags_size;
+ };
+ 
+ struct ahci_host_priv {
+@@ -475,6 +475,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
+ 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
+ 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
+ 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
++	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
++	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
+ 
+ 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
+ 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+@@ -597,6 +599,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
+ 	return __ahci_port_base(ap->host, ap->port_no);
+ }
+ 
++static void ahci_enable_ahci(void __iomem *mmio)
 +{
-+	struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	BUG_ON(test_bit(CHAINIV_STATE_INUSE, &ctx->state) || ctx->queue.qlen);
++	u32 tmp;
 +
-+	skcipher_geniv_exit(tfm);
++	/* turn on AHCI_EN */
++	tmp = readl(mmio + HOST_CTL);
++	if (!(tmp & HOST_AHCI_EN)) {
++		tmp |= HOST_AHCI_EN;
++		writel(tmp, mmio + HOST_CTL);
++		tmp = readl(mmio + HOST_CTL);	/* flush && sanity check */
++		WARN_ON(!(tmp & HOST_AHCI_EN));
++	}
 +}
 +
-+static struct crypto_template chainiv_tmpl;
-+
-+static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
-+{
-+	struct crypto_attr_type *algt;
-+	struct crypto_instance *inst;
-+	int err;
-+
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
-+		return ERR_PTR(err);
-+
-+	inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0);
-+	if (IS_ERR(inst))
-+		goto out;
-+
-+	inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt_first;
-+
-+	inst->alg.cra_init = chainiv_init;
-+	inst->alg.cra_exit = skcipher_geniv_exit;
-+
-+	inst->alg.cra_ctxsize = sizeof(struct chainiv_ctx);
-+
-+	if (!crypto_requires_sync(algt->type, algt->mask)) {
-+		inst->alg.cra_flags |= CRYPTO_ALG_ASYNC;
+ /**
+  *	ahci_save_initial_config - Save and fixup initial config values
+  *	@pdev: target PCI device
+@@ -619,6 +635,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
+ 	u32 cap, port_map;
+ 	int i;
+ 
++	/* make sure AHCI mode is enabled before accessing CAP */
++	ahci_enable_ahci(mmio);
 +
-+		inst->alg.cra_ablkcipher.givencrypt =
-+			async_chainiv_givencrypt_first;
+ 	/* Values prefixed with saved_ are written back to host after
+ 	 * reset.  Values without are used for driver operation.
+ 	 */
+@@ -1036,19 +1055,17 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
+ static int ahci_reset_controller(struct ata_host *host)
+ {
+ 	struct pci_dev *pdev = to_pci_dev(host->dev);
++	struct ahci_host_priv *hpriv = host->private_data;
+ 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
+ 	u32 tmp;
+ 
+ 	/* we must be in AHCI mode, before using anything
+ 	 * AHCI-specific, such as HOST_RESET.
+ 	 */
+-	tmp = readl(mmio + HOST_CTL);
+-	if (!(tmp & HOST_AHCI_EN)) {
+-		tmp |= HOST_AHCI_EN;
+-		writel(tmp, mmio + HOST_CTL);
+-	}
++	ahci_enable_ahci(mmio);
+ 
+ 	/* global controller reset */
++	tmp = readl(mmio + HOST_CTL);
+ 	if ((tmp & HOST_RESET) == 0) {
+ 		writel(tmp | HOST_RESET, mmio + HOST_CTL);
+ 		readl(mmio + HOST_CTL); /* flush */
+@@ -1067,8 +1084,7 @@ static int ahci_reset_controller(struct ata_host *host)
+ 	}
+ 
+ 	/* turn on AHCI mode */
+-	writel(HOST_AHCI_EN, mmio + HOST_CTL);
+-	(void) readl(mmio + HOST_CTL);	/* flush */
++	ahci_enable_ahci(mmio);
+ 
+ 	/* some registers might be cleared on reset.  restore initial values */
+ 	ahci_restore_initial_config(host);
+@@ -1078,8 +1094,10 @@ static int ahci_reset_controller(struct ata_host *host)
+ 
+ 		/* configure PCS */
+ 		pci_read_config_word(pdev, 0x92, &tmp16);
+-		tmp16 |= 0xf;
+-		pci_write_config_word(pdev, 0x92, tmp16);
++		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
++			tmp16 |= hpriv->port_map;
++			pci_write_config_word(pdev, 0x92, tmp16);
++		}
+ 	}
+ 
+ 	return 0;
+@@ -1480,35 +1498,31 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
+ {
+ 	struct scatterlist *sg;
+-	struct ahci_sg *ahci_sg;
+-	unsigned int n_sg = 0;
++	struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
++	unsigned int si;
+ 
+ 	VPRINTK("ENTER\n");
+ 
+ 	/*
+ 	 * Next, the S/G list.
+ 	 */
+-	ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		dma_addr_t addr = sg_dma_address(sg);
+ 		u32 sg_len = sg_dma_len(sg);
+ 
+-		ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
+-		ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
+-		ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
+-
+-		ahci_sg++;
+-		n_sg++;
++		ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
++		ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
++		ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
+ 	}
+ 
+-	return n_sg;
++	return si;
+ }
+ 
+ static void ahci_qc_prep(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ahci_port_priv *pp = ap->private_data;
+-	int is_atapi = is_atapi_taskfile(&qc->tf);
++	int is_atapi = ata_is_atapi(qc->tf.protocol);
+ 	void *cmd_tbl;
+ 	u32 opts;
+ 	const u32 cmd_fis_len = 5; /* five dwords */
+diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
+index 9032998..2053420 100644
+--- a/drivers/ata/ata_generic.c
++++ b/drivers/ata/ata_generic.c
+@@ -26,7 +26,7 @@
+ #include <linux/libata.h>
+ 
+ #define DRV_NAME "ata_generic"
+-#define DRV_VERSION "0.2.13"
++#define DRV_VERSION "0.2.15"
+ 
+ /*
+  *	A generic parallel ATA driver using libata
+@@ -48,27 +48,47 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
+ 	struct ata_port *ap = link->ap;
+ 	int dma_enabled = 0;
+ 	struct ata_device *dev;
++	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ 
+ 	/* Bits 5 and 6 indicate if DMA is active on master/slave */
+ 	if (ap->ioaddr.bmdma_addr)
+ 		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ 
++	if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
++		dma_enabled = 0xFF;
 +
-+		inst->alg.cra_init = async_chainiv_init;
-+		inst->alg.cra_exit = async_chainiv_exit;
+ 	ata_link_for_each_dev(dev, link) {
+-		if (ata_dev_enabled(dev)) {
+-			/* We don't really care */
+-			dev->pio_mode = XFER_PIO_0;
+-			dev->dma_mode = XFER_MW_DMA_0;
+-			/* We do need the right mode information for DMA or PIO
+-			   and this comes from the current configuration flags */
+-			if (dma_enabled & (1 << (5 + dev->devno))) {
+-				ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
+-				dev->flags &= ~ATA_DFLAG_PIO;
+-			} else {
+-				ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
+-				dev->xfer_mode = XFER_PIO_0;
+-				dev->xfer_shift = ATA_SHIFT_PIO;
+-				dev->flags |= ATA_DFLAG_PIO;
++		if (!ata_dev_enabled(dev))
++			continue;
 +
-+		inst->alg.cra_ctxsize = sizeof(struct async_chainiv_ctx);
-+	}
++		/* We don't really care */
++		dev->pio_mode = XFER_PIO_0;
++		dev->dma_mode = XFER_MW_DMA_0;
++		/* We do need the right mode information for DMA or PIO
++		   and this comes from the current configuration flags */
++		if (dma_enabled & (1 << (5 + dev->devno))) {
++			unsigned int xfer_mask = ata_id_xfermask(dev->id);
++			const char *name;
 +
-+	inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
++			if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA))
++				name = ata_mode_string(xfer_mask);
++			else {
++				/* SWDMA perhaps? */
++				name = "DMA";
++				xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
+ 			}
 +
-+out:
-+	return inst;
-+}
++			ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
++				       name);
 +
-+static struct crypto_template chainiv_tmpl = {
-+	.name = "chainiv",
-+	.alloc = chainiv_alloc,
-+	.free = skcipher_geniv_free,
-+	.module = THIS_MODULE,
++			dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
++			dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
++			dev->flags &= ~ATA_DFLAG_PIO;
++		} else {
++			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
++			dev->xfer_mode = XFER_PIO_0;
++			dev->xfer_shift = ATA_SHIFT_PIO;
++			dev->flags |= ATA_DFLAG_PIO;
+ 		}
+ 	}
+ 	return 0;
+@@ -185,6 +205,7 @@ static struct pci_device_id ata_generic[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
++	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
+diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
+index b406b39..4b99ed0 100644
+--- a/drivers/ata/ata_piix.c
++++ b/drivers/ata/ata_piix.c
+@@ -101,39 +101,21 @@ enum {
+ 	ICH5_PMR		= 0x90, /* port mapping register */
+ 	ICH5_PCS		= 0x92,	/* port control and status */
+ 	PIIX_SCC		= 0x0A, /* sub-class code register */
++	PIIX_SIDPR_BAR		= 5,
++	PIIX_SIDPR_LEN		= 16,
++	PIIX_SIDPR_IDX		= 0,
++	PIIX_SIDPR_DATA		= 4,
+ 
+-	PIIX_FLAG_SCR		= (1 << 26), /* SCR available */
+ 	PIIX_FLAG_AHCI		= (1 << 27), /* AHCI possible */
+ 	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */
++	PIIX_FLAG_SIDPR		= (1 << 29), /* SATA idx/data pair regs */
+ 
+ 	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,
+ 	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+ 
+-	/* combined mode.  if set, PATA is channel 0.
+-	 * if clear, PATA is channel 1.
+-	 */
+-	PIIX_PORT_ENABLED	= (1 << 0),
+-	PIIX_PORT_PRESENT	= (1 << 4),
+-
+ 	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
+ 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
+ 
+-	/* controller IDs */
+-	piix_pata_mwdma		= 0,	/* PIIX3 MWDMA only */
+-	piix_pata_33,			/* PIIX4 at 33Mhz */
+-	ich_pata_33,			/* ICH up to UDMA 33 only */
+-	ich_pata_66,			/* ICH up to 66 Mhz */
+-	ich_pata_100,			/* ICH up to UDMA 100 */
+-	ich5_sata,
+-	ich6_sata,
+-	ich6_sata_ahci,
+-	ich6m_sata_ahci,
+-	ich8_sata_ahci,
+-	ich8_2port_sata,
+-	ich8m_apple_sata_ahci,		/* locks up on second port enable */
+-	tolapai_sata_ahci,
+-	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
+-
+ 	/* constants for mapping table */
+ 	P0			= 0,  /* port 0 */
+ 	P1			= 1,  /* port 1 */
+@@ -149,6 +131,24 @@ enum {
+ 	PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
+ };
+ 
++enum piix_controller_ids {
++	/* controller IDs */
++	piix_pata_mwdma,	/* PIIX3 MWDMA only */
++	piix_pata_33,		/* PIIX4 at 33Mhz */
++	ich_pata_33,		/* ICH up to UDMA 33 only */
++	ich_pata_66,		/* ICH up to 66 Mhz */
++	ich_pata_100,		/* ICH up to UDMA 100 */
++	ich5_sata,
++	ich6_sata,
++	ich6_sata_ahci,
++	ich6m_sata_ahci,
++	ich8_sata_ahci,
++	ich8_2port_sata,
++	ich8m_apple_sata_ahci,	/* locks up on second port enable */
++	tolapai_sata_ahci,
++	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
 +};
 +
-+static int __init chainiv_module_init(void)
-+{
-+	return crypto_register_template(&chainiv_tmpl);
-+}
-+
-+static void __exit chainiv_module_exit(void)
-+{
-+	crypto_unregister_template(&chainiv_tmpl);
-+}
-+
-+module_init(chainiv_module_init);
-+module_exit(chainiv_module_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Chain IV Generator");
-diff --git a/crypto/cryptd.c b/crypto/cryptd.c
-index 8bf2da8..074298f 100644
---- a/crypto/cryptd.c
-+++ b/crypto/cryptd.c
-@@ -228,7 +228,7 @@ static struct crypto_instance *cryptd_alloc_blkcipher(
- 	struct crypto_alg *alg;
+ struct piix_map_db {
+ 	const u32 mask;
+ 	const u16 port_enable;
+@@ -157,6 +157,7 @@ struct piix_map_db {
  
- 	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER,
--				  CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
-+				  CRYPTO_ALG_TYPE_MASK);
- 	if (IS_ERR(alg))
- 		return ERR_PTR(PTR_ERR(alg));
+ struct piix_host_priv {
+ 	const int *map;
++	void __iomem *sidpr;
+ };
  
-@@ -236,13 +236,15 @@ static struct crypto_instance *cryptd_alloc_blkcipher(
- 	if (IS_ERR(inst))
- 		goto out_put_alg;
+ static int piix_init_one(struct pci_dev *pdev,
+@@ -167,6 +168,9 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
+ static int ich_pata_cable_detect(struct ata_port *ap);
+ static u8 piix_vmw_bmdma_status(struct ata_port *ap);
++static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
++static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
++static void piix_sidpr_error_handler(struct ata_port *ap);
+ #ifdef CONFIG_PM
+ static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
+ static int piix_pci_device_resume(struct pci_dev *pdev);
+@@ -263,6 +267,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
+ 	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
+ 	/* SATA Controller IDE (Tolapai) */
+ 	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci },
++	/* SATA Controller IDE (ICH10) */
++	{ 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	/* SATA Controller IDE (ICH10) */
++	{ 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
++	/* SATA Controller IDE (ICH10) */
++	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
++	/* SATA Controller IDE (ICH10) */
++	{ 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
  
--	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
- 	inst->alg.cra_type = &crypto_ablkcipher_type;
+ 	{ }	/* terminate list */
+ };
+@@ -321,7 +333,6 @@ static const struct ata_port_operations piix_pata_ops = {
+ 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= ata_cable_40wire,
  
- 	inst->alg.cra_ablkcipher.ivsize = alg->cra_blkcipher.ivsize;
- 	inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
- 	inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+-	.irq_handler		= ata_interrupt,
+ 	.irq_clear		= ata_bmdma_irq_clear,
+ 	.irq_on			= ata_irq_on,
  
-+	inst->alg.cra_ablkcipher.geniv = alg->cra_blkcipher.geniv;
-+
- 	inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx);
+@@ -353,7 +364,6 @@ static const struct ata_port_operations ich_pata_ops = {
+ 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+ 	.cable_detect		= ich_pata_cable_detect,
  
- 	inst->alg.cra_init = cryptd_blkcipher_init_tfm;
-diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
-index 29f7747..ff7b3de 100644
---- a/crypto/crypto_null.c
-+++ b/crypto/crypto_null.c
-@@ -16,15 +16,17 @@
-  * (at your option) any later version.
-  *
-  */
-+
-+#include <crypto/internal/skcipher.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/mm.h>
--#include <linux/crypto.h>
- #include <linux/string.h>
+-	.irq_handler		= ata_interrupt,
+ 	.irq_clear		= ata_bmdma_irq_clear,
+ 	.irq_on			= ata_irq_on,
  
- #define NULL_KEY_SIZE		0
- #define NULL_BLOCK_SIZE		1
- #define NULL_DIGEST_SIZE	0
-+#define NULL_IV_SIZE		0
+@@ -380,7 +390,6 @@ static const struct ata_port_operations piix_sata_ops = {
+ 	.error_handler		= ata_bmdma_error_handler,
+ 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
  
- static int null_compress(struct crypto_tfm *tfm, const u8 *src,
- 			 unsigned int slen, u8 *dst, unsigned int *dlen)
-@@ -55,6 +57,26 @@ static void null_crypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
- 	memcpy(dst, src, NULL_BLOCK_SIZE);
- }
+-	.irq_handler		= ata_interrupt,
+ 	.irq_clear		= ata_bmdma_irq_clear,
+ 	.irq_on			= ata_irq_on,
  
-+static int skcipher_null_crypt(struct blkcipher_desc *desc,
-+			       struct scatterlist *dst,
-+			       struct scatterlist *src, unsigned int nbytes)
-+{
-+	struct blkcipher_walk walk;
-+	int err;
+@@ -419,6 +428,35 @@ static const struct ata_port_operations piix_vmw_ops = {
+ 	.port_start		= ata_port_start,
+ };
+ 
++static const struct ata_port_operations piix_sidpr_sata_ops = {
++	.tf_load		= ata_tf_load,
++	.tf_read		= ata_tf_read,
++	.check_status		= ata_check_status,
++	.exec_command		= ata_exec_command,
++	.dev_select		= ata_std_dev_select,
 +
-+	blkcipher_walk_init(&walk, dst, src, nbytes);
-+	err = blkcipher_walk_virt(desc, &walk);
++	.bmdma_setup		= ata_bmdma_setup,
++	.bmdma_start		= ata_bmdma_start,
++	.bmdma_stop		= ata_bmdma_stop,
++	.bmdma_status		= ata_bmdma_status,
++	.qc_prep		= ata_qc_prep,
++	.qc_issue		= ata_qc_issue_prot,
++	.data_xfer		= ata_data_xfer,
 +
-+	while (walk.nbytes) {
-+		if (walk.src.virt.addr != walk.dst.virt.addr)
-+			memcpy(walk.dst.virt.addr, walk.src.virt.addr,
-+			       walk.nbytes);
-+		err = blkcipher_walk_done(desc, &walk, 0);
-+	}
++	.scr_read		= piix_sidpr_scr_read,
++	.scr_write		= piix_sidpr_scr_write,
 +
-+	return err;
-+}
++	.freeze			= ata_bmdma_freeze,
++	.thaw			= ata_bmdma_thaw,
++	.error_handler		= piix_sidpr_error_handler,
++	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
 +
- static struct crypto_alg compress_null = {
- 	.cra_name		=	"compress_null",
- 	.cra_flags		=	CRYPTO_ALG_TYPE_COMPRESS,
-@@ -76,6 +98,7 @@ static struct crypto_alg digest_null = {
- 	.cra_list		=       LIST_HEAD_INIT(digest_null.cra_list),	
- 	.cra_u			=	{ .digest = {
- 	.dia_digestsize		=	NULL_DIGEST_SIZE,
-+	.dia_setkey   		=	null_setkey,
- 	.dia_init   		=	null_init,
- 	.dia_update 		=	null_update,
- 	.dia_final  		=	null_final } }
-@@ -96,6 +119,25 @@ static struct crypto_alg cipher_null = {
- 	.cia_decrypt		=	null_crypt } }
- };
- 
-+static struct crypto_alg skcipher_null = {
-+	.cra_name		=	"ecb(cipher_null)",
-+	.cra_driver_name	=	"ecb-cipher_null",
-+	.cra_priority		=	100,
-+	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
-+	.cra_blocksize		=	NULL_BLOCK_SIZE,
-+	.cra_type		=	&crypto_blkcipher_type,
-+	.cra_ctxsize		=	0,
-+	.cra_module		=	THIS_MODULE,
-+	.cra_list		=	LIST_HEAD_INIT(skcipher_null.cra_list),
-+	.cra_u			=	{ .blkcipher = {
-+	.min_keysize		=	NULL_KEY_SIZE,
-+	.max_keysize		=	NULL_KEY_SIZE,
-+	.ivsize			=	NULL_IV_SIZE,
-+	.setkey			= 	null_setkey,
-+	.encrypt		=	skcipher_null_crypt,
-+	.decrypt		=	skcipher_null_crypt } }
++	.irq_clear		= ata_bmdma_irq_clear,
++	.irq_on			= ata_irq_on,
++
++	.port_start		= ata_port_start,
 +};
 +
- MODULE_ALIAS("compress_null");
- MODULE_ALIAS("digest_null");
- MODULE_ALIAS("cipher_null");
-@@ -108,27 +150,35 @@ static int __init init(void)
- 	if (ret < 0)
- 		goto out;
+ static const struct piix_map_db ich5_map_db = {
+ 	.mask = 0x7,
+ 	.port_enable = 0x3,
+@@ -526,7 +564,6 @@ static const struct piix_map_db *piix_map_db_table[] = {
+ static struct ata_port_info piix_port_info[] = {
+ 	[piix_pata_mwdma] = 	/* PIIX3 MWDMA only */
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_PATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+@@ -535,7 +572,6 @@ static struct ata_port_info piix_port_info[] = {
  
-+	ret = crypto_register_alg(&skcipher_null);
-+	if (ret < 0)
-+		goto out_unregister_cipher;
-+
- 	ret = crypto_register_alg(&digest_null);
--	if (ret < 0) {
--		crypto_unregister_alg(&cipher_null);
--		goto out;
--	}
-+	if (ret < 0)
-+		goto out_unregister_skcipher;
+ 	[piix_pata_33] =	/* PIIX4 at 33MHz */
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_PATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
+@@ -545,7 +581,6 @@ static struct ata_port_info piix_port_info[] = {
  
- 	ret = crypto_register_alg(&compress_null);
--	if (ret < 0) {
--		crypto_unregister_alg(&digest_null);
--		crypto_unregister_alg(&cipher_null);
--		goto out;
--	}
-+	if (ret < 0)
-+		goto out_unregister_digest;
+ 	[ich_pata_33] = 	/* ICH0 - ICH at 33Mhz*/
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_PATA_FLAGS,
+ 		.pio_mask 	= 0x1f,	/* pio 0-4 */
+ 		.mwdma_mask	= 0x06, /* Check: maybe 0x07  */
+@@ -555,7 +590,6 @@ static struct ata_port_info piix_port_info[] = {
  
- out:	
- 	return ret;
-+
-+out_unregister_digest:
-+	crypto_unregister_alg(&digest_null);
-+out_unregister_skcipher:
-+	crypto_unregister_alg(&skcipher_null);
-+out_unregister_cipher:
-+	crypto_unregister_alg(&cipher_null);
-+	goto out;
- }
+ 	[ich_pata_66] = 	/* ICH controllers up to 66MHz */
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_PATA_FLAGS,
+ 		.pio_mask 	= 0x1f,	/* pio 0-4 */
+ 		.mwdma_mask	= 0x06, /* MWDMA0 is broken on chip */
+@@ -565,7 +599,6 @@ static struct ata_port_info piix_port_info[] = {
  
- static void __exit fini(void)
- {
- 	crypto_unregister_alg(&compress_null);
- 	crypto_unregister_alg(&digest_null);
-+	crypto_unregister_alg(&skcipher_null);
- 	crypto_unregister_alg(&cipher_null);
+ 	[ich_pata_100] =
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x06, /* mwdma1-2 */
+@@ -575,7 +608,6 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich5_sata] =
+ 	{
+-		.sht		= &piix_sht,
+ 		.flags		= PIIX_SATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+@@ -585,8 +617,7 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich6_sata] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
++		.flags		= PIIX_SATA_FLAGS,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -595,9 +626,7 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich6_sata_ahci] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+-				  PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -606,9 +635,7 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich6m_sata_ahci] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+-				  PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -617,9 +644,8 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich8_sata_ahci] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+-				  PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
++				  PIIX_FLAG_SIDPR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -628,9 +654,8 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich8_2port_sata] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+-				  PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
++				  PIIX_FLAG_SIDPR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -639,9 +664,7 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[tolapai_sata_ahci] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+-				  PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -650,9 +673,8 @@ static struct ata_port_info piix_port_info[] = {
+ 
+ 	[ich8m_apple_sata_ahci] =
+ 	{
+-		.sht		= &piix_sht,
+-		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
+-				  PIIX_FLAG_AHCI,
++		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
++				  PIIX_FLAG_SIDPR,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.mwdma_mask	= 0x07, /* mwdma0-2 */
+ 		.udma_mask	= ATA_UDMA6,
+@@ -815,7 +837,7 @@ static void piix_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 	if (is_slave) {
+ 		/* clear TIME1|IE1|PPE1|DTE1 */
+ 		master_data &= 0xff0f;
+-		/* Enable SITRE (seperate slave timing register) */
++		/* Enable SITRE (separate slave timing register) */
+ 		master_data |= 0x4000;
+ 		/* enable PPE1, IE1 and TIME1 as needed */
+ 		master_data |= (control << 4);
+@@ -1001,6 +1023,180 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ 	do_pata_set_dmamode(ap, adev, 1);
  }
  
-diff --git a/crypto/ctr.c b/crypto/ctr.c
-new file mode 100644
-index 0000000..2d7425f
---- /dev/null
-+++ b/crypto/ctr.c
-@@ -0,0 +1,422 @@
 +/*
-+ * CTR: Counter mode
++ * Serial ATA Index/Data Pair Superset Registers access
 + *
-+ * (C) Copyright IBM Corp. 2007 - Joy Latten <latten at us.ibm.com>
++ * Beginning from ICH8, there's a sane way to access SCRs using index
++ * and data register pair located at BAR5.  This creates an
++ * interesting problem of mapping two SCRs to one port.
 + *
-+ * 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.
++ * Although they have separate SCRs, the master and slave aren't
++ * independent enough to be treated as separate links - e.g. softreset
++ * resets both.  Also, there's no protocol defined for hard resetting
++ * singled device sharing the virtual port (no defined way to acquire
++ * device signature).  This is worked around by merging the SCR values
++ * into one sensible value and requesting follow-up SRST after
++ * hardreset.
 + *
++ * SCR merging is perfomed in nibbles which is the unit contents in
++ * SCRs are organized.  If two values are equal, the value is used.
++ * When they differ, merge table which lists precedence of possible
++ * values is consulted and the first match or the last entry when
++ * nothing matches is used.  When there's no merge table for the
++ * specific nibble, value from the first port is used.
 + */
-+
-+#include <crypto/algapi.h>
-+#include <crypto/ctr.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/random.h>
-+#include <linux/scatterlist.h>
-+#include <linux/slab.h>
-+
-+struct crypto_ctr_ctx {
-+	struct crypto_cipher *child;
++static const int piix_sidx_map[] = {
++	[SCR_STATUS]	= 0,
++	[SCR_ERROR]	= 2,
++	[SCR_CONTROL]	= 1,
 +};
 +
-+struct crypto_rfc3686_ctx {
-+	struct crypto_blkcipher *child;
-+	u8 nonce[CTR_RFC3686_NONCE_SIZE];
-+};
++static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
++{
++	struct ata_port *ap = dev->link->ap;
++	struct piix_host_priv *hpriv = ap->host->private_data;
 +
-+static int crypto_ctr_setkey(struct crypto_tfm *parent, const u8 *key,
-+			     unsigned int keylen)
++	iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
++		  hpriv->sidpr + PIIX_SIDPR_IDX);
++}
++
++static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
 +{
-+	struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(parent);
-+	struct crypto_cipher *child = ctx->child;
-+	int err;
++	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
 +
-+	crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-+	crypto_cipher_set_flags(child, crypto_tfm_get_flags(parent) &
-+				CRYPTO_TFM_REQ_MASK);
-+	err = crypto_cipher_setkey(child, key, keylen);
-+	crypto_tfm_set_flags(parent, crypto_cipher_get_flags(child) &
-+			     CRYPTO_TFM_RES_MASK);
++	piix_sidpr_sel(dev, reg);
++	return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
++}
 +
-+	return err;
++static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
++{
++	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
++
++	piix_sidpr_sel(dev, reg);
++	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
 +}
 +
-+static void crypto_ctr_crypt_final(struct blkcipher_walk *walk,
-+				   struct crypto_cipher *tfm)
++static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
 +{
-+	unsigned int bsize = crypto_cipher_blocksize(tfm);
-+	unsigned long alignmask = crypto_cipher_alignmask(tfm);
-+	u8 *ctrblk = walk->iv;
-+	u8 tmp[bsize + alignmask];
-+	u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
-+	u8 *src = walk->src.virt.addr;
-+	u8 *dst = walk->dst.virt.addr;
-+	unsigned int nbytes = walk->nbytes;
++	u32 val = 0;
++	int i, mi;
 +
-+	crypto_cipher_encrypt_one(tfm, keystream, ctrblk);
-+	crypto_xor(keystream, src, nbytes);
-+	memcpy(dst, keystream, nbytes);
++	for (i = 0, mi = 0; i < 32 / 4; i++) {
++		u8 c0 = (val0 >> (i * 4)) & 0xf;
++		u8 c1 = (val1 >> (i * 4)) & 0xf;
++		u8 merged = c0;
++		const int *cur;
++
++		/* if no merge preference, assume the first value */
++		cur = merge_tbl[mi];
++		if (!cur)
++			goto done;
++		mi++;
++
++		/* if two values equal, use it */
++		if (c0 == c1)
++			goto done;
++
++		/* choose the first match or the last from the merge table */
++		while (*cur != -1) {
++			if (c0 == *cur || c1 == *cur)
++				break;
++			cur++;
++		}
++		if (*cur == -1)
++			cur--;
++		merged = *cur;
++	done:
++		val |= merged << (i * 4);
++	}
 +
-+	crypto_inc(ctrblk, bsize);
++	return val;
 +}
 +
-+static int crypto_ctr_crypt_segment(struct blkcipher_walk *walk,
-+				    struct crypto_cipher *tfm)
++static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
 +{
-+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-+		   crypto_cipher_alg(tfm)->cia_encrypt;
-+	unsigned int bsize = crypto_cipher_blocksize(tfm);
-+	u8 *ctrblk = walk->iv;
-+	u8 *src = walk->src.virt.addr;
-+	u8 *dst = walk->dst.virt.addr;
-+	unsigned int nbytes = walk->nbytes;
++	const int * const sstatus_merge_tbl[] = {
++		/* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
++		/* SPD */ (const int []){ 2, 1, 0, -1 },
++		/* IPM */ (const int []){ 6, 2, 1, 0, -1 },
++		NULL,
++	};
++	const int * const scontrol_merge_tbl[] = {
++		/* DET */ (const int []){ 1, 0, 4, 0, -1 },
++		/* SPD */ (const int []){ 0, 2, 1, 0, -1 },
++		/* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
++		NULL,
++	};
++	u32 v0, v1;
 +
-+	do {
-+		/* create keystream */
-+		fn(crypto_cipher_tfm(tfm), dst, ctrblk);
-+		crypto_xor(dst, src, bsize);
++	if (reg >= ARRAY_SIZE(piix_sidx_map))
++		return -EINVAL;
 +
-+		/* increment counter in counterblock */
-+		crypto_inc(ctrblk, bsize);
++	if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
++		*val = piix_sidpr_read(&ap->link.device[0], reg);
++		return 0;
++	}
 +
-+		src += bsize;
-+		dst += bsize;
-+	} while ((nbytes -= bsize) >= bsize);
++	v0 = piix_sidpr_read(&ap->link.device[0], reg);
++	v1 = piix_sidpr_read(&ap->link.device[1], reg);
 +
-+	return nbytes;
++	switch (reg) {
++	case SCR_STATUS:
++		*val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
++		break;
++	case SCR_ERROR:
++		*val = v0 | v1;
++		break;
++	case SCR_CONTROL:
++		*val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
++		break;
++	}
++
++	return 0;
 +}
 +
-+static int crypto_ctr_crypt_inplace(struct blkcipher_walk *walk,
-+				    struct crypto_cipher *tfm)
++static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
 +{
-+	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
-+		   crypto_cipher_alg(tfm)->cia_encrypt;
-+	unsigned int bsize = crypto_cipher_blocksize(tfm);
-+	unsigned long alignmask = crypto_cipher_alignmask(tfm);
-+	unsigned int nbytes = walk->nbytes;
-+	u8 *ctrblk = walk->iv;
-+	u8 *src = walk->src.virt.addr;
-+	u8 tmp[bsize + alignmask];
-+	u8 *keystream = PTR_ALIGN(tmp + 0, alignmask + 1);
-+
-+	do {
-+		/* create keystream */
-+		fn(crypto_cipher_tfm(tfm), keystream, ctrblk);
-+		crypto_xor(src, keystream, bsize);
++	if (reg >= ARRAY_SIZE(piix_sidx_map))
++		return -EINVAL;
 +
-+		/* increment counter in counterblock */
-+		crypto_inc(ctrblk, bsize);
++	piix_sidpr_write(&ap->link.device[0], reg, val);
 +
-+		src += bsize;
-+	} while ((nbytes -= bsize) >= bsize);
++	if (ap->flags & ATA_FLAG_SLAVE_POSS)
++		piix_sidpr_write(&ap->link.device[1], reg, val);
 +
-+	return nbytes;
++	return 0;
 +}
 +
-+static int crypto_ctr_crypt(struct blkcipher_desc *desc,
-+			      struct scatterlist *dst, struct scatterlist *src,
-+			      unsigned int nbytes)
++static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
++				unsigned long deadline)
 +{
-+	struct blkcipher_walk walk;
-+	struct crypto_blkcipher *tfm = desc->tfm;
-+	struct crypto_ctr_ctx *ctx = crypto_blkcipher_ctx(tfm);
-+	struct crypto_cipher *child = ctx->child;
-+	unsigned int bsize = crypto_cipher_blocksize(child);
-+	int err;
-+
-+	blkcipher_walk_init(&walk, dst, src, nbytes);
-+	err = blkcipher_walk_virt_block(desc, &walk, bsize);
-+
-+	while (walk.nbytes >= bsize) {
-+		if (walk.src.virt.addr == walk.dst.virt.addr)
-+			nbytes = crypto_ctr_crypt_inplace(&walk, child);
-+		else
-+			nbytes = crypto_ctr_crypt_segment(&walk, child);
++	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
++	int rc;
 +
-+		err = blkcipher_walk_done(desc, &walk, nbytes);
++	/* do hardreset */
++	rc = sata_link_hardreset(link, timing, deadline);
++	if (rc) {
++		ata_link_printk(link, KERN_ERR,
++				"COMRESET failed (errno=%d)\n", rc);
++		return rc;
 +	}
 +
-+	if (walk.nbytes) {
-+		crypto_ctr_crypt_final(&walk, child);
-+		err = blkcipher_walk_done(desc, &walk, 0);
++	/* TODO: phy layer with polling, timeouts, etc. */
++	if (ata_link_offline(link)) {
++		*class = ATA_DEV_NONE;
++		return 0;
 +	}
 +
-+	return err;
++	return -EAGAIN;
 +}
 +
-+static int crypto_ctr_init_tfm(struct crypto_tfm *tfm)
++static void piix_sidpr_error_handler(struct ata_port *ap)
 +{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-+	struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_cipher *cipher;
-+
-+	cipher = crypto_spawn_cipher(spawn);
-+	if (IS_ERR(cipher))
-+		return PTR_ERR(cipher);
-+
-+	ctx->child = cipher;
++	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
++			   piix_sidpr_hardreset, ata_std_postreset);
++}
 +
-+	return 0;
+ #ifdef CONFIG_PM
+ static int piix_broken_suspend(void)
+ {
+@@ -1034,6 +1230,13 @@ static int piix_broken_suspend(void)
+ 			},
+ 		},
+ 		{
++			.ident = "TECRA M6",
++			.matches = {
++				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
++				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"),
++			},
++		},
++		{
+ 			.ident = "TECRA M7",
+ 			.matches = {
+ 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+@@ -1048,6 +1251,13 @@ static int piix_broken_suspend(void)
+ 			},
+ 		},
+ 		{
++			.ident = "Satellite R20",
++			.matches = {
++				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
++				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"),
++			},
++		},
++		{
+ 			.ident = "Satellite R25",
+ 			.matches = {
+ 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+@@ -1253,10 +1463,10 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
+ 	return no_piix_dma;
+ }
+ 
+-static void __devinit piix_init_pcs(struct pci_dev *pdev,
+-				    struct ata_port_info *pinfo,
++static void __devinit piix_init_pcs(struct ata_host *host,
+ 				    const struct piix_map_db *map_db)
+ {
++	struct pci_dev *pdev = to_pci_dev(host->dev);
+ 	u16 pcs, new_pcs;
+ 
+ 	pci_read_config_word(pdev, ICH5_PCS, &pcs);
+@@ -1270,11 +1480,10 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
+ 	}
+ }
+ 
+-static void __devinit piix_init_sata_map(struct pci_dev *pdev,
+-					 struct ata_port_info *pinfo,
+-					 const struct piix_map_db *map_db)
++static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
++					       struct ata_port_info *pinfo,
++					       const struct piix_map_db *map_db)
+ {
+-	struct piix_host_priv *hpriv = pinfo[0].private_data;
+ 	const int *map;
+ 	int i, invalid_map = 0;
+ 	u8 map_value;
+@@ -1298,7 +1507,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
+ 		case IDE:
+ 			WARN_ON((i & 1) || map[i + 1] != IDE);
+ 			pinfo[i / 2] = piix_port_info[ich_pata_100];
+-			pinfo[i / 2].private_data = hpriv;
+ 			i++;
+ 			printk(" IDE IDE");
+ 			break;
+@@ -1316,7 +1524,33 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
+ 		dev_printk(KERN_ERR, &pdev->dev,
+ 			   "invalid MAP value %u\n", map_value);
+ 
+-	hpriv->map = map;
++	return map;
 +}
 +
-+static void crypto_ctr_exit_tfm(struct crypto_tfm *tfm)
++static void __devinit piix_init_sidpr(struct ata_host *host)
 +{
-+	struct crypto_ctr_ctx *ctx = crypto_tfm_ctx(tfm);
++	struct pci_dev *pdev = to_pci_dev(host->dev);
++	struct piix_host_priv *hpriv = host->private_data;
++	int i;
 +
-+	crypto_free_cipher(ctx->child);
-+}
++	/* check for availability */
++	for (i = 0; i < 4; i++)
++		if (hpriv->map[i] == IDE)
++			return;
 +
-+static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb)
-+{
-+	struct crypto_instance *inst;
-+	struct crypto_alg *alg;
-+	int err;
++	if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
++		return;
 +
-+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
-+	if (err)
-+		return ERR_PTR(err);
++	if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
++	    pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
++		return;
 +
-+	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_CIPHER,
-+				  CRYPTO_ALG_TYPE_MASK);
-+	if (IS_ERR(alg))
-+		return ERR_PTR(PTR_ERR(alg));
++	if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
++		return;
 +
-+	/* Block size must be >= 4 bytes. */
-+	err = -EINVAL;
-+	if (alg->cra_blocksize < 4)
-+		goto out_put_alg;
++	hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
++	host->ports[0]->ops = &piix_sidpr_sata_ops;
++	host->ports[1]->ops = &piix_sidpr_sata_ops;
+ }
+ 
+ static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
+@@ -1375,8 +1609,10 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	struct device *dev = &pdev->dev;
+ 	struct ata_port_info port_info[2];
+ 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
+-	struct piix_host_priv *hpriv;
+ 	unsigned long port_flags;
++	struct ata_host *host;
++	struct piix_host_priv *hpriv;
++	int rc;
+ 
+ 	if (!printed_version++)
+ 		dev_printk(KERN_DEBUG, &pdev->dev,
+@@ -1386,17 +1622,31 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	if (!in_module_init)
+ 		return -ENODEV;
+ 
++	port_info[0] = piix_port_info[ent->driver_data];
++	port_info[1] = piix_port_info[ent->driver_data];
 +
-+	/* If this is false we'd fail the alignment of crypto_inc. */
-+	if (alg->cra_blocksize % 4)
-+		goto out_put_alg;
++	port_flags = port_info[0].flags;
 +
-+	inst = crypto_alloc_instance("ctr", alg);
-+	if (IS_ERR(inst))
-+		goto out;
++	/* enable device and prepare host */
++	rc = pcim_enable_device(pdev);
++	if (rc)
++		return rc;
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
-+	inst->alg.cra_priority = alg->cra_priority;
-+	inst->alg.cra_blocksize = 1;
-+	inst->alg.cra_alignmask = alg->cra_alignmask | (__alignof__(u32) - 1);
-+	inst->alg.cra_type = &crypto_blkcipher_type;
++	/* SATA map init can change port_info, do it before prepping host */
+ 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
+ 	if (!hpriv)
+ 		return -ENOMEM;
+ 
+-	port_info[0] = piix_port_info[ent->driver_data];
+-	port_info[1] = piix_port_info[ent->driver_data];
+-	port_info[0].private_data = hpriv;
+-	port_info[1].private_data = hpriv;
++	if (port_flags & ATA_FLAG_SATA)
++		hpriv->map = piix_init_sata_map(pdev, port_info,
++					piix_map_db_table[ent->driver_data]);
+ 
+-	port_flags = port_info[0].flags;
++	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
++	if (rc)
++		return rc;
++	host->private_data = hpriv;
+ 
++	/* initialize controller */
+ 	if (port_flags & PIIX_FLAG_AHCI) {
+ 		u8 tmp;
+ 		pci_read_config_byte(pdev, PIIX_SCC, &tmp);
+@@ -1407,12 +1657,9 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		}
+ 	}
+ 
+-	/* Initialize SATA map */
+ 	if (port_flags & ATA_FLAG_SATA) {
+-		piix_init_sata_map(pdev, port_info,
+-				   piix_map_db_table[ent->driver_data]);
+-		piix_init_pcs(pdev, port_info,
+-			      piix_map_db_table[ent->driver_data]);
++		piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
++		piix_init_sidpr(host);
+ 	}
+ 
+ 	/* apply IOCFG bit18 quirk */
+@@ -1431,12 +1678,14 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		/* This writes into the master table but it does not
+ 		   really matter for this errata as we will apply it to
+ 		   all the PIIX devices on the board */
+-		port_info[0].mwdma_mask = 0;
+-		port_info[0].udma_mask = 0;
+-		port_info[1].mwdma_mask = 0;
+-		port_info[1].udma_mask = 0;
++		host->ports[0]->mwdma_mask = 0;
++		host->ports[0]->udma_mask = 0;
++		host->ports[1]->mwdma_mask = 0;
++		host->ports[1]->udma_mask = 0;
+ 	}
+-	return ata_pci_init_one(pdev, ppi);
 +
-+	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
-+	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
-+	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
++	pci_set_master(pdev);
++	return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
+ }
+ 
+ static int __init piix_init(void)
+diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
+index 7bf4bef..9e8ec19 100644
+--- a/drivers/ata/libata-acpi.c
++++ b/drivers/ata/libata-acpi.c
+@@ -442,40 +442,77 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
+ }
+ 
+ /**
++ * ata_acpi_gtm_xfermode - determine xfermode from GTM parameter
++ * @dev: target device
++ * @gtm: GTM parameter to use
++ *
++ * Determine xfermask for @dev from @gtm.
++ *
++ * LOCKING:
++ * None.
++ *
++ * RETURNS:
++ * Determined xfermask.
++ */
++unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
++				    const struct ata_acpi_gtm *gtm)
++{
++	unsigned long xfer_mask = 0;
++	unsigned int type;
++	int unit;
++	u8 mode;
 +
-+	inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx);
++	/* we always use the 0 slot for crap hardware */
++	unit = dev->devno;
++	if (!(gtm->flags & 0x10))
++		unit = 0;
 +
-+	inst->alg.cra_init = crypto_ctr_init_tfm;
-+	inst->alg.cra_exit = crypto_ctr_exit_tfm;
++	/* PIO */
++	mode = ata_timing_cycle2mode(ATA_SHIFT_PIO, gtm->drive[unit].pio);
++	xfer_mask |= ata_xfer_mode2mask(mode);
 +
-+	inst->alg.cra_blkcipher.setkey = crypto_ctr_setkey;
-+	inst->alg.cra_blkcipher.encrypt = crypto_ctr_crypt;
-+	inst->alg.cra_blkcipher.decrypt = crypto_ctr_crypt;
++	/* See if we have MWDMA or UDMA data. We don't bother with
++	 * MWDMA if UDMA is available as this means the BIOS set UDMA
++	 * and our error changedown if it works is UDMA to PIO anyway.
++	 */
++	if (!(gtm->flags & (1 << (2 * unit))))
++		type = ATA_SHIFT_MWDMA;
++	else
++		type = ATA_SHIFT_UDMA;
 +
-+out:
-+	crypto_mod_put(alg);
-+	return inst;
++	mode = ata_timing_cycle2mode(type, gtm->drive[unit].dma);
++	xfer_mask |= ata_xfer_mode2mask(mode);
 +
-+out_put_alg:
-+	inst = ERR_PTR(err);
-+	goto out;
++	return xfer_mask;
 +}
++EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask);
 +
-+static void crypto_ctr_free(struct crypto_instance *inst)
-+{
-+	crypto_drop_spawn(crypto_instance_ctx(inst));
-+	kfree(inst);
-+}
++/**
+  * ata_acpi_cbl_80wire		-	Check for 80 wire cable
+  * @ap: Port to check
++ * @gtm: GTM data to use
+  *
+- * Return 1 if the ACPI mode data for this port indicates the BIOS selected
+- * an 80wire mode.
++ * Return 1 if the @gtm indicates the BIOS selected an 80wire mode.
+  */
+-
+-int ata_acpi_cbl_80wire(struct ata_port *ap)
++int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm)
+ {
+-	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
+-	int valid = 0;
++	struct ata_device *dev;
+ 
+-	if (!gtm)
+-		return 0;
++	ata_link_for_each_dev(dev, &ap->link) {
++		unsigned long xfer_mask, udma_mask;
 +
-+static struct crypto_template crypto_ctr_tmpl = {
-+	.name = "ctr",
-+	.alloc = crypto_ctr_alloc,
-+	.free = crypto_ctr_free,
-+	.module = THIS_MODULE,
-+};
++		if (!ata_dev_enabled(dev))
++			continue;
 +
-+static int crypto_rfc3686_setkey(struct crypto_tfm *parent, const u8 *key,
-+				 unsigned int keylen)
++		xfer_mask = ata_acpi_gtm_xfermask(dev, gtm);
++		ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask);
++
++		if (udma_mask & ~ATA_UDMA_MASK_40C)
++			return 1;
++	}
+ 
+-	/* Split timing, DMA enabled */
+-	if ((gtm->flags & 0x11) == 0x11 && gtm->drive[0].dma < 55)
+-		valid |= 1;
+-	if ((gtm->flags & 0x14) == 0x14 && gtm->drive[1].dma < 55)
+-		valid |= 2;
+-	/* Shared timing, DMA enabled */
+-	if ((gtm->flags & 0x11) == 0x01 && gtm->drive[0].dma < 55)
+-		valid |= 1;
+-	if ((gtm->flags & 0x14) == 0x04 && gtm->drive[0].dma < 55)
+-		valid |= 2;
+-
+-	/* Drive check */
+-	if ((valid & 1) && ata_dev_enabled(&ap->link.device[0]))
+-		return 1;
+-	if ((valid & 2) && ata_dev_enabled(&ap->link.device[1]))
+-		return 1;
+ 	return 0;
+ }
+-
+ EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
+ 
+ static void ata_acpi_gtf_to_tf(struct ata_device *dev,
+@@ -776,6 +813,36 @@ void ata_acpi_on_resume(struct ata_port *ap)
+ }
+ 
+ /**
++ * ata_acpi_set_state - set the port power state
++ * @ap: target ATA port
++ * @state: state, on/off
++ *
++ * This function executes the _PS0/_PS3 ACPI method to set the power state.
++ * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
++ */
++void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
 +{
-+	struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(parent);
-+	struct crypto_blkcipher *child = ctx->child;
-+	int err;
++	struct ata_device *dev;
 +
-+	/* the nonce is stored in bytes at end of key */
-+	if (keylen < CTR_RFC3686_NONCE_SIZE)
-+		return -EINVAL;
++	if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA))
++		return;
 +
-+	memcpy(ctx->nonce, key + (keylen - CTR_RFC3686_NONCE_SIZE),
-+	       CTR_RFC3686_NONCE_SIZE);
++	/* channel first and then drives for power on and vica versa
++	   for power off */
++	if (state.event == PM_EVENT_ON)
++		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0);
 +
-+	keylen -= CTR_RFC3686_NONCE_SIZE;
++	ata_link_for_each_dev(dev, &ap->link) {
++		if (dev->acpi_handle && ata_dev_enabled(dev))
++			acpi_bus_set_power(dev->acpi_handle,
++				state.event == PM_EVENT_ON ?
++					ACPI_STATE_D0 : ACPI_STATE_D3);
++	}
++	if (state.event != PM_EVENT_ON)
++		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3);
++}
 +
-+	crypto_blkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-+	crypto_blkcipher_set_flags(child, crypto_tfm_get_flags(parent) &
-+					  CRYPTO_TFM_REQ_MASK);
-+	err = crypto_blkcipher_setkey(child, key, keylen);
-+	crypto_tfm_set_flags(parent, crypto_blkcipher_get_flags(child) &
-+				     CRYPTO_TFM_RES_MASK);
++/**
+  * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
+  * @dev: target ATA device
+  *
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index 6380726..361cf50 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -119,6 +119,10 @@ int libata_noacpi = 0;
+ module_param_named(noacpi, libata_noacpi, int, 0444);
+ MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in probe/suspend/resume when set");
+ 
++int libata_allow_tpm = 0;
++module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
++MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands");
 +
-+	return err;
+ MODULE_AUTHOR("Jeff Garzik");
+ MODULE_DESCRIPTION("Library module for ATA devices");
+ MODULE_LICENSE("GPL");
+@@ -450,9 +454,9 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
+  *	RETURNS:
+  *	Packed xfer_mask.
+  */
+-static unsigned int ata_pack_xfermask(unsigned int pio_mask,
+-				      unsigned int mwdma_mask,
+-				      unsigned int udma_mask)
++unsigned long ata_pack_xfermask(unsigned long pio_mask,
++				unsigned long mwdma_mask,
++				unsigned long udma_mask)
+ {
+ 	return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
+ 		((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
+@@ -469,10 +473,8 @@ static unsigned int ata_pack_xfermask(unsigned int pio_mask,
+  *	Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
+  *	Any NULL distination masks will be ignored.
+  */
+-static void ata_unpack_xfermask(unsigned int xfer_mask,
+-				unsigned int *pio_mask,
+-				unsigned int *mwdma_mask,
+-				unsigned int *udma_mask)
++void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask,
++			 unsigned long *mwdma_mask, unsigned long *udma_mask)
+ {
+ 	if (pio_mask)
+ 		*pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
+@@ -486,9 +488,9 @@ static const struct ata_xfer_ent {
+ 	int shift, bits;
+ 	u8 base;
+ } ata_xfer_tbl[] = {
+-	{ ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
+-	{ ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 },
+-	{ ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 },
++	{ ATA_SHIFT_PIO, ATA_NR_PIO_MODES, XFER_PIO_0 },
++	{ ATA_SHIFT_MWDMA, ATA_NR_MWDMA_MODES, XFER_MW_DMA_0 },
++	{ ATA_SHIFT_UDMA, ATA_NR_UDMA_MODES, XFER_UDMA_0 },
+ 	{ -1, },
+ };
+ 
+@@ -503,9 +505,9 @@ static const struct ata_xfer_ent {
+  *	None.
+  *
+  *	RETURNS:
+- *	Matching XFER_* value, 0 if no match found.
++ *	Matching XFER_* value, 0xff if no match found.
+  */
+-static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
++u8 ata_xfer_mask2mode(unsigned long xfer_mask)
+ {
+ 	int highbit = fls(xfer_mask) - 1;
+ 	const struct ata_xfer_ent *ent;
+@@ -513,7 +515,7 @@ static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
+ 	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+ 		if (highbit >= ent->shift && highbit < ent->shift + ent->bits)
+ 			return ent->base + highbit - ent->shift;
+-	return 0;
++	return 0xff;
+ }
+ 
+ /**
+@@ -528,13 +530,14 @@ static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
+  *	RETURNS:
+  *	Matching xfer_mask, 0 if no match found.
+  */
+-static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
++unsigned long ata_xfer_mode2mask(u8 xfer_mode)
+ {
+ 	const struct ata_xfer_ent *ent;
+ 
+ 	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
+ 		if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
+-			return 1 << (ent->shift + xfer_mode - ent->base);
++			return ((2 << (ent->shift + xfer_mode - ent->base)) - 1)
++				& ~((1 << ent->shift) - 1);
+ 	return 0;
+ }
+ 
+@@ -550,7 +553,7 @@ static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
+  *	RETURNS:
+  *	Matching xfer_shift, -1 if no match found.
+  */
+-static int ata_xfer_mode2shift(unsigned int xfer_mode)
++int ata_xfer_mode2shift(unsigned long xfer_mode)
+ {
+ 	const struct ata_xfer_ent *ent;
+ 
+@@ -574,7 +577,7 @@ static int ata_xfer_mode2shift(unsigned int xfer_mode)
+  *	Constant C string representing highest speed listed in
+  *	@mode_mask, or the constant C string "<n/a>".
+  */
+-static const char *ata_mode_string(unsigned int xfer_mask)
++const char *ata_mode_string(unsigned long xfer_mask)
+ {
+ 	static const char * const xfer_mode_str[] = {
+ 		"PIO0",
+@@ -947,8 +950,8 @@ unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
+ 	if (r_err)
+ 		*r_err = err;
+ 
+-	/* see if device passed diags: if master then continue and warn later */
+-	if (err == 0 && dev->devno == 0)
++	/* see if device passed diags: continue and warn later */
++	if (err == 0)
+ 		/* diagnostic fail : do nothing _YET_ */
+ 		dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
+ 	else if (err == 1)
+@@ -1286,48 +1289,6 @@ static int ata_hpa_resize(struct ata_device *dev)
+ }
+ 
+ /**
+- *	ata_id_to_dma_mode	-	Identify DMA mode from id block
+- *	@dev: device to identify
+- *	@unknown: mode to assume if we cannot tell
+- *
+- *	Set up the timing values for the device based upon the identify
+- *	reported values for the DMA mode. This function is used by drivers
+- *	which rely upon firmware configured modes, but wish to report the
+- *	mode correctly when possible.
+- *
+- *	In addition we emit similarly formatted messages to the default
+- *	ata_dev_set_mode handler, in order to provide consistency of
+- *	presentation.
+- */
+-
+-void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
+-{
+-	unsigned int mask;
+-	u8 mode;
+-
+-	/* Pack the DMA modes */
+-	mask = ((dev->id[63] >> 8) << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA;
+-	if (dev->id[53] & 0x04)
+-		mask |= ((dev->id[88] >> 8) << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
+-
+-	/* Select the mode in use */
+-	mode = ata_xfer_mask2mode(mask);
+-
+-	if (mode != 0) {
+-		ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
+-		       ata_mode_string(mask));
+-	} else {
+-		/* SWDMA perhaps ? */
+-		mode = unknown;
+-		ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
+-	}
+-
+-	/* Configure the device reporting */
+-	dev->xfer_mode = mode;
+-	dev->xfer_shift = ata_xfer_mode2shift(mode);
+-}
+-
+-/**
+  *	ata_noop_dev_select - Select device 0/1 on ATA bus
+  *	@ap: ATA channel to manipulate
+  *	@device: ATA device (numbered from zero) to select
+@@ -1464,9 +1425,9 @@ static inline void ata_dump_id(const u16 *id)
+  *	RETURNS:
+  *	Computed xfermask
+  */
+-static unsigned int ata_id_xfermask(const u16 *id)
++unsigned long ata_id_xfermask(const u16 *id)
+ {
+-	unsigned int pio_mask, mwdma_mask, udma_mask;
++	unsigned long pio_mask, mwdma_mask, udma_mask;
+ 
+ 	/* Usual case. Word 53 indicates word 64 is valid */
+ 	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
+@@ -1519,7 +1480,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
+ }
+ 
+ /**
+- *	ata_port_queue_task - Queue port_task
++ *	ata_pio_queue_task - Queue port_task
+  *	@ap: The ata_port to queue port_task for
+  *	@fn: workqueue function to be scheduled
+  *	@data: data for @fn to use
+@@ -1531,16 +1492,15 @@ static unsigned int ata_id_xfermask(const u16 *id)
+  *	one task is active at any given time.
+  *
+  *	libata core layer takes care of synchronization between
+- *	port_task and EH.  ata_port_queue_task() may be ignored for EH
++ *	port_task and EH.  ata_pio_queue_task() may be ignored for EH
+  *	synchronization.
+  *
+  *	LOCKING:
+  *	Inherited from caller.
+  */
+-void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
+-			 unsigned long delay)
++static void ata_pio_queue_task(struct ata_port *ap, void *data,
++			       unsigned long delay)
+ {
+-	PREPARE_DELAYED_WORK(&ap->port_task, fn);
+ 	ap->port_task_data = data;
+ 
+ 	/* may fail if ata_port_flush_task() in progress */
+@@ -2090,7 +2050,7 @@ int ata_dev_configure(struct ata_device *dev)
+ 	struct ata_eh_context *ehc = &dev->link->eh_context;
+ 	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
+ 	const u16 *id = dev->id;
+-	unsigned int xfer_mask;
++	unsigned long xfer_mask;
+ 	char revbuf[7];		/* XYZ-99\0 */
+ 	char fwrevbuf[ATA_ID_FW_REV_LEN+1];
+ 	char modelbuf[ATA_ID_PROD_LEN+1];
+@@ -2161,8 +2121,14 @@ int ata_dev_configure(struct ata_device *dev)
+ 					       "supports DRM functions and may "
+ 					       "not be fully accessable.\n");
+ 			snprintf(revbuf, 7, "CFA");
+-		} else
++		} else {
+ 			snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
++			/* Warn the user if the device has TPM extensions */
++			if (ata_id_has_tpm(id))
++				ata_dev_printk(dev, KERN_WARNING,
++					       "supports DRM functions and may "
++					       "not be fully accessable.\n");
++		}
+ 
+ 		dev->n_sectors = ata_id_n_sectors(id);
+ 
+@@ -2295,19 +2261,8 @@ int ata_dev_configure(struct ata_device *dev)
+ 			dev->flags |= ATA_DFLAG_DIPM;
+ 	}
+ 
+-	if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
+-		/* Let the user know. We don't want to disallow opens for
+-		   rescue purposes, or in case the vendor is just a blithering
+-		   idiot */
+-		if (print_info) {
+-			ata_dev_printk(dev, KERN_WARNING,
+-"Drive reports diagnostics failure. This may indicate a drive\n");
+-			ata_dev_printk(dev, KERN_WARNING,
+-"fault or invalid emulation. Contact drive vendor for information.\n");
+-		}
+-	}
+-
+-	/* limit bridge transfers to udma5, 200 sectors */
++	/* Limit PATA drive on SATA cable bridge transfers to udma5,
++	   200 sectors */
+ 	if (ata_dev_knobble(dev)) {
+ 		if (ata_msg_drv(ap) && print_info)
+ 			ata_dev_printk(dev, KERN_INFO,
+@@ -2336,6 +2291,21 @@ int ata_dev_configure(struct ata_device *dev)
+ 	if (ap->ops->dev_config)
+ 		ap->ops->dev_config(dev);
+ 
++	if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
++		/* Let the user know. We don't want to disallow opens for
++		   rescue purposes, or in case the vendor is just a blithering
++		   idiot. Do this after the dev_config call as some controllers
++		   with buggy firmware may want to avoid reporting false device
++		   bugs */
++
++		if (print_info) {
++			ata_dev_printk(dev, KERN_WARNING,
++"Drive reports diagnostics failure. This may indicate a drive\n");
++			ata_dev_printk(dev, KERN_WARNING,
++"fault or invalid emulation. Contact drive vendor for information.\n");
++		}
++	}
++
+ 	if (ata_msg_probe(ap))
+ 		ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
+ 			__FUNCTION__, ata_chk_status(ap));
+@@ -2387,6 +2357,18 @@ int ata_cable_unknown(struct ata_port *ap)
+ }
+ 
+ /**
++ *	ata_cable_ignore	-	return ignored PATA cable.
++ *	@ap: port
++ *
++ *	Helper method for drivers which don't use cable type to limit
++ *	transfer mode.
++ */
++int ata_cable_ignore(struct ata_port *ap)
++{
++	return ATA_CBL_PATA_IGN;
 +}
 +
-+static int crypto_rfc3686_crypt(struct blkcipher_desc *desc,
-+				struct scatterlist *dst,
-+				struct scatterlist *src, unsigned int nbytes)
++/**
+  *	ata_cable_sata	-	return SATA cable type
+  *	@ap: port
+  *
+@@ -2781,38 +2763,33 @@ int sata_set_spd(struct ata_link *link)
+  */
+ 
+ static const struct ata_timing ata_timing[] = {
++/*	{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 }, */
++	{ XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
++	{ XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
++	{ XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
++	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
++	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
++	{ XFER_PIO_5,     15,  65,  25, 100,  65,  25, 100,   0 },
++	{ XFER_PIO_6,     10,  55,  20,  80,  55,  20,  80,   0 },
+ 
+-	{ XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
+-	{ XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
+-	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
+-	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
++	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
++	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
++	{ XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
+ 
+-	{ XFER_MW_DMA_4,  25,   0,   0,   0,  55,  20,  80,   0 },
++	{ XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
++	{ XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
++	{ XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
+ 	{ XFER_MW_DMA_3,  25,   0,   0,   0,  65,  25, 100,   0 },
+-	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
+-	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
+-	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
++	{ XFER_MW_DMA_4,  25,   0,   0,   0,  55,  20,  80,   0 },
+ 
+ /*	{ XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 }, */
+-
+-	{ XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
+-	{ XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
+-	{ XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
+-
+-	{ XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
+-	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
+-	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
+-
+-	{ XFER_PIO_6,     10,  55,  20,  80,  55,  20,  80,   0 },
+-	{ XFER_PIO_5,     15,  65,  25, 100,  65,  25, 100,   0 },
+-	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
+-	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
+-
+-	{ XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
+-	{ XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
+-	{ XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
+-
+-/*	{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 }, */
++	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
++	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
++	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
++	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
++	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
++	{ XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
++	{ XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
+ 
+ 	{ 0xFF }
+ };
+@@ -2845,14 +2822,16 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
+ 	if (what & ATA_TIMING_UDMA   ) m->udma    = max(a->udma,    b->udma);
+ }
+ 
+-static const struct ata_timing *ata_timing_find_mode(unsigned short speed)
++const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
+ {
+-	const struct ata_timing *t;
++	const struct ata_timing *t = ata_timing;
+ 
+-	for (t = ata_timing; t->mode != speed; t++)
+-		if (t->mode == 0xFF)
+-			return NULL;
+-	return t;
++	while (xfer_mode > t->mode)
++		t++;
++
++	if (xfer_mode == t->mode)
++		return t;
++	return NULL;
+ }
+ 
+ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+@@ -2927,6 +2906,57 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+ }
+ 
+ /**
++ *	ata_timing_cycle2mode - find xfer mode for the specified cycle duration
++ *	@xfer_shift: ATA_SHIFT_* value for transfer type to examine.
++ *	@cycle: cycle duration in ns
++ *
++ *	Return matching xfer mode for @cycle.  The returned mode is of
++ *	the transfer type specified by @xfer_shift.  If @cycle is too
++ *	slow for @xfer_shift, 0xff is returned.  If @cycle is faster
++ *	than the fastest known mode, the fasted mode is returned.
++ *
++ *	LOCKING:
++ *	None.
++ *
++ *	RETURNS:
++ *	Matching xfer_mode, 0xff if no match found.
++ */
++u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
 +{
-+	struct crypto_blkcipher *tfm = desc->tfm;
-+	struct crypto_rfc3686_ctx *ctx = crypto_blkcipher_ctx(tfm);
-+	struct crypto_blkcipher *child = ctx->child;
-+	unsigned long alignmask = crypto_blkcipher_alignmask(tfm);
-+	u8 ivblk[CTR_RFC3686_BLOCK_SIZE + alignmask];
-+	u8 *iv = PTR_ALIGN(ivblk + 0, alignmask + 1);
-+	u8 *info = desc->info;
-+	int err;
++	u8 base_mode = 0xff, last_mode = 0xff;
++	const struct ata_xfer_ent *ent;
++	const struct ata_timing *t;
 +
-+	/* set up counter block */
-+	memcpy(iv, ctx->nonce, CTR_RFC3686_NONCE_SIZE);
-+	memcpy(iv + CTR_RFC3686_NONCE_SIZE, info, CTR_RFC3686_IV_SIZE);
++	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
++		if (ent->shift == xfer_shift)
++			base_mode = ent->base;
 +
-+	/* initialize counter portion of counter block */
-+	*(__be32 *)(iv + CTR_RFC3686_NONCE_SIZE + CTR_RFC3686_IV_SIZE) =
-+		cpu_to_be32(1);
++	for (t = ata_timing_find_mode(base_mode);
++	     t && ata_xfer_mode2shift(t->mode) == xfer_shift; t++) {
++		unsigned short this_cycle;
 +
-+	desc->tfm = child;
-+	desc->info = iv;
-+	err = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
-+	desc->tfm = tfm;
-+	desc->info = info;
++		switch (xfer_shift) {
++		case ATA_SHIFT_PIO:
++		case ATA_SHIFT_MWDMA:
++			this_cycle = t->cycle;
++			break;
++		case ATA_SHIFT_UDMA:
++			this_cycle = t->udma;
++			break;
++		default:
++			return 0xff;
++		}
 +
-+	return err;
++		if (cycle > this_cycle)
++			break;
++
++		last_mode = t->mode;
++	}
++
++	return last_mode;
 +}
 +
-+static int crypto_rfc3686_init_tfm(struct crypto_tfm *tfm)
-+{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
-+	struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_blkcipher *cipher;
++/**
+  *	ata_down_xfermask_limit - adjust dev xfer masks downward
+  *	@dev: Device to adjust xfer masks
+  *	@sel: ATA_DNXFER_* selector
+@@ -2944,8 +2974,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
+ {
+ 	char buf[32];
+-	unsigned int orig_mask, xfer_mask;
+-	unsigned int pio_mask, mwdma_mask, udma_mask;
++	unsigned long orig_mask, xfer_mask;
++	unsigned long pio_mask, mwdma_mask, udma_mask;
+ 	int quiet, highbit;
+ 
+ 	quiet = !!(sel & ATA_DNXFER_QUIET);
+@@ -3039,7 +3069,7 @@ static int ata_dev_set_mode(struct ata_device *dev)
+ 
+ 	/* Early MWDMA devices do DMA but don't allow DMA mode setting.
+ 	   Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
+-	if (dev->xfer_shift == ATA_SHIFT_MWDMA && 
++	if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
+ 	    dev->dma_mode == XFER_MW_DMA_0 &&
+ 	    (dev->id[63] >> 8) & 1)
+ 		err_mask &= ~AC_ERR_DEV;
+@@ -3067,7 +3097,7 @@ static int ata_dev_set_mode(struct ata_device *dev)
+ /**
+  *	ata_do_set_mode - Program timings and issue SET FEATURES - XFER
+  *	@link: link on which timings will be programmed
+- *	@r_failed_dev: out paramter for failed device
++ *	@r_failed_dev: out parameter for failed device
+  *
+  *	Standard implementation of the function used to tune and set
+  *	ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
+@@ -3089,7 +3119,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ 
+ 	/* step 1: calculate xfer_mask */
+ 	ata_link_for_each_dev(dev, link) {
+-		unsigned int pio_mask, dma_mask;
++		unsigned long pio_mask, dma_mask;
+ 		unsigned int mode_mask;
+ 
+ 		if (!ata_dev_enabled(dev))
+@@ -3115,7 +3145,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ 		dev->dma_mode = ata_xfer_mask2mode(dma_mask);
+ 
+ 		found = 1;
+-		if (dev->dma_mode)
++		if (dev->dma_mode != 0xff)
+ 			used_dma = 1;
+ 	}
+ 	if (!found)
+@@ -3126,7 +3156,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ 		if (!ata_dev_enabled(dev))
+ 			continue;
+ 
+-		if (!dev->pio_mode) {
++		if (dev->pio_mode == 0xff) {
+ 			ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
+ 			rc = -EINVAL;
+ 			goto out;
+@@ -3140,7 +3170,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ 
+ 	/* step 3: set host DMA timings */
+ 	ata_link_for_each_dev(dev, link) {
+-		if (!ata_dev_enabled(dev) || !dev->dma_mode)
++		if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff)
+ 			continue;
+ 
+ 		dev->xfer_mode = dev->dma_mode;
+@@ -3173,31 +3203,6 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ }
+ 
+ /**
+- *	ata_set_mode - Program timings and issue SET FEATURES - XFER
+- *	@link: link on which timings will be programmed
+- *	@r_failed_dev: out paramter for failed device
+- *
+- *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
+- *	ata_set_mode() fails, pointer to the failing device is
+- *	returned in @r_failed_dev.
+- *
+- *	LOCKING:
+- *	PCI/etc. bus probe sem.
+- *
+- *	RETURNS:
+- *	0 on success, negative errno otherwise
+- */
+-int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+-{
+-	struct ata_port *ap = link->ap;
+-
+-	/* has private set_mode? */
+-	if (ap->ops->set_mode)
+-		return ap->ops->set_mode(link, r_failed_dev);
+-	return ata_do_set_mode(link, r_failed_dev);
+-}
+-
+-/**
+  *	ata_tf_to_host - issue ATA taskfile to host controller
+  *	@ap: port to which command is being issued
+  *	@tf: ATA taskfile register set
+@@ -4363,7 +4368,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
+ 	tf.feature = SETFEATURES_XFER;
+ 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING;
+ 	tf.protocol = ATA_PROT_NODATA;
+-	tf.nsect = dev->xfer_mode;
++	/* If we are using IORDY we must send the mode setting command */
++	if (ata_pio_need_iordy(dev))
++		tf.nsect = dev->xfer_mode;
++	/* If the device has IORDY and the controller does not - turn it off */
++ 	else if (ata_id_has_iordy(dev->id))
++		tf.nsect = 0x01;
++	else /* In the ancient relic department - skip all of this */
++		return 0;
+ 
+ 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ 
+@@ -4462,17 +4474,13 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
+ void ata_sg_clean(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+-	struct scatterlist *sg = qc->__sg;
++	struct scatterlist *sg = qc->sg;
+ 	int dir = qc->dma_dir;
+ 	void *pad_buf = NULL;
+ 
+-	WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+ 	WARN_ON(sg == NULL);
+ 
+-	if (qc->flags & ATA_QCFLAG_SINGLE)
+-		WARN_ON(qc->n_elem > 1);
+-
+-	VPRINTK("unmapping %u sg elements\n", qc->n_elem);
++	VPRINTK("unmapping %u sg elements\n", qc->mapped_n_elem);
+ 
+ 	/* if we padded the buffer out to 32-bit bound, and data
+ 	 * xfer direction is from-device, we must copy from the
+@@ -4481,31 +4489,20 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
+ 	if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
+ 		pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+ 
+-	if (qc->flags & ATA_QCFLAG_SG) {
+-		if (qc->n_elem)
+-			dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
+-		/* restore last sg */
+-		sg_last(sg, qc->orig_n_elem)->length += qc->pad_len;
+-		if (pad_buf) {
+-			struct scatterlist *psg = &qc->pad_sgent;
+-			void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
+-			memcpy(addr + psg->offset, pad_buf, qc->pad_len);
+-			kunmap_atomic(addr, KM_IRQ0);
+-		}
+-	} else {
+-		if (qc->n_elem)
+-			dma_unmap_single(ap->dev,
+-				sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
+-				dir);
+-		/* restore sg */
+-		sg->length += qc->pad_len;
+-		if (pad_buf)
+-			memcpy(qc->buf_virt + sg->length - qc->pad_len,
+-			       pad_buf, qc->pad_len);
++	if (qc->mapped_n_elem)
++		dma_unmap_sg(ap->dev, sg, qc->mapped_n_elem, dir);
++	/* restore last sg */
++	if (qc->last_sg)
++		*qc->last_sg = qc->saved_last_sg;
++	if (pad_buf) {
++		struct scatterlist *psg = &qc->extra_sg[1];
++		void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
++		memcpy(addr + psg->offset, pad_buf, qc->pad_len);
++		kunmap_atomic(addr, KM_IRQ0);
+ 	}
+ 
+ 	qc->flags &= ~ATA_QCFLAG_DMAMAP;
+-	qc->__sg = NULL;
++	qc->sg = NULL;
+ }
+ 
+ /**
+@@ -4523,13 +4520,10 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct scatterlist *sg;
+-	unsigned int idx;
++	unsigned int si, pi;
+ 
+-	WARN_ON(qc->__sg == NULL);
+-	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+-
+-	idx = 0;
+-	ata_for_each_sg(sg, qc) {
++	pi = 0;
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		u32 addr, offset;
+ 		u32 sg_len, len;
+ 
+@@ -4546,18 +4540,17 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
+ 			if ((offset + sg_len) > 0x10000)
+ 				len = 0x10000 - offset;
+ 
+-			ap->prd[idx].addr = cpu_to_le32(addr);
+-			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
+-			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
++			ap->prd[pi].addr = cpu_to_le32(addr);
++			ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
++			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+ 
+-			idx++;
++			pi++;
+ 			sg_len -= len;
+ 			addr += len;
+ 		}
+ 	}
+ 
+-	if (idx)
+-		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ }
+ 
+ /**
+@@ -4577,13 +4570,10 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct scatterlist *sg;
+-	unsigned int idx;
+-
+-	WARN_ON(qc->__sg == NULL);
+-	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
++	unsigned int si, pi;
+ 
+-	idx = 0;
+-	ata_for_each_sg(sg, qc) {
++	pi = 0;
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		u32 addr, offset;
+ 		u32 sg_len, len, blen;
+ 
+@@ -4601,25 +4591,24 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
+ 				len = 0x10000 - offset;
+ 
+ 			blen = len & 0xffff;
+-			ap->prd[idx].addr = cpu_to_le32(addr);
++			ap->prd[pi].addr = cpu_to_le32(addr);
+ 			if (blen == 0) {
+ 			   /* Some PATA chipsets like the CS5530 can't
+ 			      cope with 0x0000 meaning 64K as the spec says */
+-				ap->prd[idx].flags_len = cpu_to_le32(0x8000);
++				ap->prd[pi].flags_len = cpu_to_le32(0x8000);
+ 				blen = 0x8000;
+-				ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
++				ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
+ 			}
+-			ap->prd[idx].flags_len = cpu_to_le32(blen);
+-			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
++			ap->prd[pi].flags_len = cpu_to_le32(blen);
++			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+ 
+-			idx++;
++			pi++;
+ 			sg_len -= len;
+ 			addr += len;
+ 		}
+ 	}
+ 
+-	if (idx)
+-		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ }
+ 
+ /**
+@@ -4669,8 +4658,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
+  */
+ static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
+ {
+-	if (qc->tf.protocol != ATA_PROT_ATAPI &&
+-	    qc->tf.protocol != ATA_PROT_ATAPI_DMA)
++	if (qc->tf.protocol != ATAPI_PROT_PIO &&
++	    qc->tf.protocol != ATAPI_PROT_DMA)
+ 		return 0;
+ 
+ 	if (qc->tf.flags & ATA_TFLAG_WRITE)
+@@ -4756,33 +4745,6 @@ void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
+ void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+ 
+ /**
+- *	ata_sg_init_one - Associate command with memory buffer
+- *	@qc: Command to be associated
+- *	@buf: Memory buffer
+- *	@buflen: Length of memory buffer, in bytes.
+- *
+- *	Initialize the data-related elements of queued_cmd @qc
+- *	to point to a single memory buffer, @buf of byte length @buflen.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- */
+-
+-void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
+-{
+-	qc->flags |= ATA_QCFLAG_SINGLE;
+-
+-	qc->__sg = &qc->sgent;
+-	qc->n_elem = 1;
+-	qc->orig_n_elem = 1;
+-	qc->buf_virt = buf;
+-	qc->nbytes = buflen;
+-	qc->cursg = qc->__sg;
+-
+-	sg_init_one(&qc->sgent, buf, buflen);
+-}
+-
+-/**
+  *	ata_sg_init - Associate command with scatter-gather table.
+  *	@qc: Command to be associated
+  *	@sg: Scatter-gather table.
+@@ -4795,84 +4757,103 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
+  *	LOCKING:
+  *	spin_lock_irqsave(host lock)
+  */
+-
+ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
+ 		 unsigned int n_elem)
+ {
+-	qc->flags |= ATA_QCFLAG_SG;
+-	qc->__sg = sg;
++	qc->sg = sg;
+ 	qc->n_elem = n_elem;
+-	qc->orig_n_elem = n_elem;
+-	qc->cursg = qc->__sg;
++	qc->cursg = qc->sg;
+ }
+ 
+-/**
+- *	ata_sg_setup_one - DMA-map the memory buffer associated with a command.
+- *	@qc: Command with memory buffer to be mapped.
+- *
+- *	DMA-map the memory buffer associated with queued_cmd @qc.
+- *
+- *	LOCKING:
+- *	spin_lock_irqsave(host lock)
+- *
+- *	RETURNS:
+- *	Zero on success, negative on error.
+- */
+-
+-static int ata_sg_setup_one(struct ata_queued_cmd *qc)
++static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
++				       unsigned int *n_elem_extra,
++				       unsigned int *nbytes_extra)
+ {
+ 	struct ata_port *ap = qc->ap;
+-	int dir = qc->dma_dir;
+-	struct scatterlist *sg = qc->__sg;
+-	dma_addr_t dma_address;
+-	int trim_sg = 0;
++	unsigned int n_elem = qc->n_elem;
++	struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL;
 +
-+	cipher = crypto_spawn_blkcipher(spawn);
-+	if (IS_ERR(cipher))
-+		return PTR_ERR(cipher);
++	*n_elem_extra = 0;
++	*nbytes_extra = 0;
 +
-+	ctx->child = cipher;
++	/* needs padding? */
++	qc->pad_len = qc->nbytes & 3;
 +
-+	return 0;
-+}
++	if (likely(!qc->pad_len))
++		return n_elem;
 +
-+static void crypto_rfc3686_exit_tfm(struct crypto_tfm *tfm)
-+{
-+	struct crypto_rfc3686_ctx *ctx = crypto_tfm_ctx(tfm);
++	/* locate last sg and save it */
++	lsg = sg_last(qc->sg, n_elem);
++	qc->last_sg = lsg;
++	qc->saved_last_sg = *lsg;
 +
-+	crypto_free_blkcipher(ctx->child);
-+}
++	sg_init_table(qc->extra_sg, ARRAY_SIZE(qc->extra_sg));
+ 
+-	/* we must lengthen transfers to end on a 32-bit boundary */
+-	qc->pad_len = sg->length & 3;
+ 	if (qc->pad_len) {
++		struct scatterlist *psg = &qc->extra_sg[1];
+ 		void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+-		struct scatterlist *psg = &qc->pad_sgent;
++		unsigned int offset;
+ 
+ 		WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
+ 
+ 		memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+ 
+-		if (qc->tf.flags & ATA_TFLAG_WRITE)
+-			memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
+-			       qc->pad_len);
++		/* psg->page/offset are used to copy to-be-written
++		 * data in this function or read data in ata_sg_clean.
++		 */
++		offset = lsg->offset + lsg->length - qc->pad_len;
++		sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
++			    qc->pad_len, offset_in_page(offset));
 +
-+static struct crypto_instance *crypto_rfc3686_alloc(struct rtattr **tb)
-+{
-+	struct crypto_instance *inst;
-+	struct crypto_alg *alg;
-+	int err;
++		if (qc->tf.flags & ATA_TFLAG_WRITE) {
++			void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
++			memcpy(pad_buf, addr + psg->offset, qc->pad_len);
++			kunmap_atomic(addr, KM_IRQ0);
++		}
+ 
+ 		sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+ 		sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+-		/* trim sg */
+-		sg->length -= qc->pad_len;
+-		if (sg->length == 0)
+-			trim_sg = 1;
+ 
+-		DPRINTK("padding done, sg->length=%u pad_len=%u\n",
+-			sg->length, qc->pad_len);
+-	}
++		/* Trim the last sg entry and chain the original and
++		 * padding sg lists.
++		 *
++		 * Because chaining consumes one sg entry, one extra
++		 * sg entry is allocated and the last sg entry is
++		 * copied to it if the length isn't zero after padded
++		 * amount is removed.
++		 *
++		 * If the last sg entry is completely replaced by
++		 * padding sg entry, the first sg entry is skipped
++		 * while chaining.
++		 */
++		lsg->length -= qc->pad_len;
++		if (lsg->length) {
++			copy_lsg = &qc->extra_sg[0];
++			tsg = &qc->extra_sg[0];
++		} else {
++			n_elem--;
++			tsg = &qc->extra_sg[1];
++		}
+ 
+-	if (trim_sg) {
+-		qc->n_elem--;
+-		goto skip_map;
+-	}
++		esg = &qc->extra_sg[1];
+ 
+-	dma_address = dma_map_single(ap->dev, qc->buf_virt,
+-				     sg->length, dir);
+-	if (dma_mapping_error(dma_address)) {
+-		/* restore sg */
+-		sg->length += qc->pad_len;
+-		return -1;
++		(*n_elem_extra)++;
++		(*nbytes_extra) += 4 - qc->pad_len;
+ 	}
+ 
+-	sg_dma_address(sg) = dma_address;
+-	sg_dma_len(sg) = sg->length;
++	if (copy_lsg)
++		sg_set_page(copy_lsg, sg_page(lsg), lsg->length, lsg->offset);
+ 
+-skip_map:
+-	DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
+-		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
++	sg_chain(lsg, 1, tsg);
++	sg_mark_end(esg);
+ 
+-	return 0;
++	/* sglist can't start with chaining sg entry, fast forward */
++	if (qc->sg == lsg) {
++		qc->sg = tsg;
++		qc->cursg = tsg;
++	}
 +
-+	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_BLKCIPHER);
-+	if (err)
-+		return ERR_PTR(err);
++	return n_elem;
+ }
+ 
+ /**
+@@ -4888,75 +4869,30 @@ skip_map:
+  *	Zero on success, negative on error.
+  *
+  */
+-
+ static int ata_sg_setup(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+-	struct scatterlist *sg = qc->__sg;
+-	struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
+-	int n_elem, pre_n_elem, dir, trim_sg = 0;
++	unsigned int n_elem, n_elem_extra, nbytes_extra;
+ 
+ 	VPRINTK("ENTER, ata%u\n", ap->print_id);
+-	WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
+ 
+-	/* we must lengthen transfers to end on a 32-bit boundary */
+-	qc->pad_len = lsg->length & 3;
+-	if (qc->pad_len) {
+-		void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+-		struct scatterlist *psg = &qc->pad_sgent;
+-		unsigned int offset;
+-
+-		WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
++	n_elem = ata_sg_setup_extra(qc, &n_elem_extra, &nbytes_extra);
+ 
+-		memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+-
+-		/*
+-		 * psg->page/offset are used to copy to-be-written
+-		 * data in this function or read data in ata_sg_clean.
+-		 */
+-		offset = lsg->offset + lsg->length - qc->pad_len;
+-		sg_init_table(psg, 1);
+-		sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
+-				qc->pad_len, offset_in_page(offset));
+-
+-		if (qc->tf.flags & ATA_TFLAG_WRITE) {
+-			void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
+-			memcpy(pad_buf, addr + psg->offset, qc->pad_len);
+-			kunmap_atomic(addr, KM_IRQ0);
++	if (n_elem) {
++		n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir);
++		if (n_elem < 1) {
++			/* restore last sg */
++			if (qc->last_sg)
++				*qc->last_sg = qc->saved_last_sg;
++			return -1;
+ 		}
+-
+-		sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+-		sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+-		/* trim last sg */
+-		lsg->length -= qc->pad_len;
+-		if (lsg->length == 0)
+-			trim_sg = 1;
+-
+-		DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
+-			qc->n_elem - 1, lsg->length, qc->pad_len);
+-	}
+-
+-	pre_n_elem = qc->n_elem;
+-	if (trim_sg && pre_n_elem)
+-		pre_n_elem--;
+-
+-	if (!pre_n_elem) {
+-		n_elem = 0;
+-		goto skip_map;
+-	}
+-
+-	dir = qc->dma_dir;
+-	n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir);
+-	if (n_elem < 1) {
+-		/* restore last sg */
+-		lsg->length += qc->pad_len;
+-		return -1;
++		DPRINTK("%d sg elements mapped\n", n_elem);
+ 	}
+ 
+-	DPRINTK("%d sg elements mapped\n", n_elem);
+-
+-skip_map:
+-	qc->n_elem = n_elem;
++	qc->n_elem = qc->mapped_n_elem = n_elem;
++	qc->n_elem += n_elem_extra;
++	qc->nbytes += nbytes_extra;
++	qc->flags |= ATA_QCFLAG_DMAMAP;
+ 
+ 	return 0;
+ }
+@@ -4985,63 +4921,77 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
+ 
+ /**
+  *	ata_data_xfer - Transfer data by PIO
+- *	@adev: device to target
++ *	@dev: device to target
+  *	@buf: data buffer
+  *	@buflen: buffer length
+- *	@write_data: read/write
++ *	@rw: read/write
+  *
+  *	Transfer data from/to the device data register by PIO.
+  *
+  *	LOCKING:
+  *	Inherited from caller.
++ *
++ *	RETURNS:
++ *	Bytes consumed.
+  */
+-void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
+-		   unsigned int buflen, int write_data)
++unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
++			   unsigned int buflen, int rw)
+ {
+-	struct ata_port *ap = adev->link->ap;
++	struct ata_port *ap = dev->link->ap;
++	void __iomem *data_addr = ap->ioaddr.data_addr;
+ 	unsigned int words = buflen >> 1;
+ 
+ 	/* Transfer multiple of 2 bytes */
+-	if (write_data)
+-		iowrite16_rep(ap->ioaddr.data_addr, buf, words);
++	if (rw == READ)
++		ioread16_rep(data_addr, buf, words);
+ 	else
+-		ioread16_rep(ap->ioaddr.data_addr, buf, words);
++		iowrite16_rep(data_addr, buf, words);
+ 
+ 	/* Transfer trailing 1 byte, if any. */
+ 	if (unlikely(buflen & 0x01)) {
+-		u16 align_buf[1] = { 0 };
++		__le16 align_buf[1] = { 0 };
+ 		unsigned char *trailing_buf = buf + buflen - 1;
+ 
+-		if (write_data) {
+-			memcpy(align_buf, trailing_buf, 1);
+-			iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
+-		} else {
+-			align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
++		if (rw == READ) {
++			align_buf[0] = cpu_to_le16(ioread16(data_addr));
+ 			memcpy(trailing_buf, align_buf, 1);
++		} else {
++			memcpy(align_buf, trailing_buf, 1);
++			iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+ 		}
++		words++;
+ 	}
 +
-+	alg = crypto_attr_alg(tb[1], CRYPTO_ALG_TYPE_BLKCIPHER,
-+				  CRYPTO_ALG_TYPE_MASK);
-+	err = PTR_ERR(alg);
-+	if (IS_ERR(alg))
-+		return ERR_PTR(err);
++	return words << 1;
+ }
+ 
+ /**
+  *	ata_data_xfer_noirq - Transfer data by PIO
+- *	@adev: device to target
++ *	@dev: device to target
+  *	@buf: data buffer
+  *	@buflen: buffer length
+- *	@write_data: read/write
++ *	@rw: read/write
+  *
+  *	Transfer data from/to the device data register by PIO. Do the
+  *	transfer with interrupts disabled.
+  *
+  *	LOCKING:
+  *	Inherited from caller.
++ *
++ *	RETURNS:
++ *	Bytes consumed.
+  */
+-void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
+-			 unsigned int buflen, int write_data)
++unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
++				 unsigned int buflen, int rw)
+ {
+ 	unsigned long flags;
++	unsigned int consumed;
 +
-+	/* We only support 16-byte blocks. */
-+	err = -EINVAL;
-+	if (alg->cra_blkcipher.ivsize != CTR_RFC3686_BLOCK_SIZE)
-+		goto out_put_alg;
+ 	local_irq_save(flags);
+-	ata_data_xfer(adev, buf, buflen, write_data);
++	consumed = ata_data_xfer(dev, buf, buflen, rw);
+ 	local_irq_restore(flags);
 +
-+	/* Not a stream cipher? */
-+	if (alg->cra_blocksize != 1)
-+		goto out_put_alg;
++	return consumed;
+ }
+ 
+ 
+@@ -5152,13 +5102,13 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
+ 	ata_altstatus(ap); /* flush */
+ 
+ 	switch (qc->tf.protocol) {
+-	case ATA_PROT_ATAPI:
++	case ATAPI_PROT_PIO:
+ 		ap->hsm_task_state = HSM_ST;
+ 		break;
+-	case ATA_PROT_ATAPI_NODATA:
++	case ATAPI_PROT_NODATA:
+ 		ap->hsm_task_state = HSM_ST_LAST;
+ 		break;
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		ap->hsm_task_state = HSM_ST_LAST;
+ 		/* initiate bmdma */
+ 		ap->ops->bmdma_start(qc);
+@@ -5300,12 +5250,15 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
+ 	bytes = (bc_hi << 8) | bc_lo;
+ 
+ 	/* shall be cleared to zero, indicating xfer of data */
+-	if (ireason & (1 << 0))
++	if (unlikely(ireason & (1 << 0)))
+ 		goto err_out;
+ 
+ 	/* make sure transfer direction matches expected */
+ 	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
+-	if (do_write != i_write)
++	if (unlikely(do_write != i_write))
++		goto err_out;
 +
-+	inst = crypto_alloc_instance("rfc3686", alg);
-+	if (IS_ERR(inst))
-+		goto out;
++	if (unlikely(!bytes))
+ 		goto err_out;
+ 
+ 	VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
+@@ -5341,7 +5294,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q
+ 		    (qc->tf.flags & ATA_TFLAG_WRITE))
+ 		    return 1;
+ 
+-		if (is_atapi_taskfile(&qc->tf) &&
++		if (ata_is_atapi(qc->tf.protocol) &&
+ 		    !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+ 			return 1;
+ 	}
+@@ -5506,7 +5459,7 @@ fsm_start:
+ 
+ 	case HSM_ST:
+ 		/* complete command or read/write the data register */
+-		if (qc->tf.protocol == ATA_PROT_ATAPI) {
++		if (qc->tf.protocol == ATAPI_PROT_PIO) {
+ 			/* ATAPI PIO protocol */
+ 			if ((status & ATA_DRQ) == 0) {
+ 				/* No more data to transfer or device error.
+@@ -5664,7 +5617,7 @@ fsm_start:
+ 		msleep(2);
+ 		status = ata_busy_wait(ap, ATA_BUSY, 10);
+ 		if (status & ATA_BUSY) {
+-			ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
++			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
+ 			return;
+ 		}
+ 	}
+@@ -5805,6 +5758,22 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
+ 	ap->ops->tf_read(ap, &qc->result_tf);
+ }
+ 
++static void ata_verify_xfer(struct ata_queued_cmd *qc)
++{
++	struct ata_device *dev = qc->dev;
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER;
-+	inst->alg.cra_priority = alg->cra_priority;
-+	inst->alg.cra_blocksize = 1;
-+	inst->alg.cra_alignmask = alg->cra_alignmask;
-+	inst->alg.cra_type = &crypto_blkcipher_type;
++	if (ata_tag_internal(qc->tag))
++		return;
 +
-+	inst->alg.cra_blkcipher.ivsize = CTR_RFC3686_IV_SIZE;
-+	inst->alg.cra_blkcipher.min_keysize = alg->cra_blkcipher.min_keysize
-+					      + CTR_RFC3686_NONCE_SIZE;
-+	inst->alg.cra_blkcipher.max_keysize = alg->cra_blkcipher.max_keysize
-+					      + CTR_RFC3686_NONCE_SIZE;
++	if (ata_is_nodata(qc->tf.protocol))
++		return;
 +
-+	inst->alg.cra_blkcipher.geniv = "seqiv";
++	if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol))
++		return;
 +
-+	inst->alg.cra_ctxsize = sizeof(struct crypto_rfc3686_ctx);
++	dev->flags &= ~ATA_DFLAG_DUBIOUS_XFER;
++}
 +
-+	inst->alg.cra_init = crypto_rfc3686_init_tfm;
-+	inst->alg.cra_exit = crypto_rfc3686_exit_tfm;
+ /**
+  *	ata_qc_complete - Complete an active ATA command
+  *	@qc: Command to complete
+@@ -5876,6 +5845,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
+ 			break;
+ 		}
+ 
++		if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER))
++			ata_verify_xfer(qc);
 +
-+	inst->alg.cra_blkcipher.setkey = crypto_rfc3686_setkey;
-+	inst->alg.cra_blkcipher.encrypt = crypto_rfc3686_crypt;
-+	inst->alg.cra_blkcipher.decrypt = crypto_rfc3686_crypt;
+ 		__ata_qc_complete(qc);
+ 	} else {
+ 		if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
+@@ -5938,30 +5910,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
+ 	return nr_done;
+ }
+ 
+-static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
+-{
+-	struct ata_port *ap = qc->ap;
+-
+-	switch (qc->tf.protocol) {
+-	case ATA_PROT_NCQ:
+-	case ATA_PROT_DMA:
+-	case ATA_PROT_ATAPI_DMA:
+-		return 1;
+-
+-	case ATA_PROT_ATAPI:
+-	case ATA_PROT_PIO:
+-		if (ap->flags & ATA_FLAG_PIO_DMA)
+-			return 1;
+-
+-		/* fall through */
+-
+-	default:
+-		return 0;
+-	}
+-
+-	/* never reached */
+-}
+-
+ /**
+  *	ata_qc_issue - issue taskfile to device
+  *	@qc: command to issue to device
+@@ -5978,6 +5926,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct ata_link *link = qc->dev->link;
++	u8 prot = qc->tf.protocol;
+ 
+ 	/* Make sure only one non-NCQ command is outstanding.  The
+ 	 * check is skipped for old EH because it reuses active qc to
+@@ -5985,7 +5934,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ 	 */
+ 	WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
+ 
+-	if (qc->tf.protocol == ATA_PROT_NCQ) {
++	if (ata_is_ncq(prot)) {
+ 		WARN_ON(link->sactive & (1 << qc->tag));
+ 
+ 		if (!link->sactive)
+@@ -6001,17 +5950,18 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ 	qc->flags |= ATA_QCFLAG_ACTIVE;
+ 	ap->qc_active |= 1 << qc->tag;
+ 
+-	if (ata_should_dma_map(qc)) {
+-		if (qc->flags & ATA_QCFLAG_SG) {
+-			if (ata_sg_setup(qc))
+-				goto sg_err;
+-		} else if (qc->flags & ATA_QCFLAG_SINGLE) {
+-			if (ata_sg_setup_one(qc))
+-				goto sg_err;
+-		}
+-	} else {
+-		qc->flags &= ~ATA_QCFLAG_DMAMAP;
+-	}
++	/* We guarantee to LLDs that they will have at least one
++	 * non-zero sg if the command is a data command.
++	 */
++	BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes));
 +
-+out:
-+	crypto_mod_put(alg);
-+	return inst;
++	/* ata_sg_setup() may update nbytes */
++	qc->raw_nbytes = qc->nbytes;
++
++	if (ata_is_dma(prot) || (ata_is_pio(prot) &&
++				 (ap->flags & ATA_FLAG_PIO_DMA)))
++		if (ata_sg_setup(qc))
++			goto sg_err;
+ 
+ 	/* if device is sleeping, schedule softreset and abort the link */
+ 	if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
+@@ -6029,7 +5979,6 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
+ 	return;
+ 
+ sg_err:
+-	qc->flags &= ~ATA_QCFLAG_DMAMAP;
+ 	qc->err_mask |= AC_ERR_SYSTEM;
+ err:
+ 	ata_qc_complete(qc);
+@@ -6064,11 +6013,11 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		switch (qc->tf.protocol) {
+ 		case ATA_PROT_PIO:
+ 		case ATA_PROT_NODATA:
+-		case ATA_PROT_ATAPI:
+-		case ATA_PROT_ATAPI_NODATA:
++		case ATAPI_PROT_PIO:
++		case ATAPI_PROT_NODATA:
+ 			qc->tf.flags |= ATA_TFLAG_POLLING;
+ 			break;
+-		case ATA_PROT_ATAPI_DMA:
++		case ATAPI_PROT_DMA:
+ 			if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+ 				/* see ata_dma_blacklisted() */
+ 				BUG();
+@@ -6091,7 +6040,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		ap->hsm_task_state = HSM_ST_LAST;
+ 
+ 		if (qc->tf.flags & ATA_TFLAG_POLLING)
+-			ata_port_queue_task(ap, ata_pio_task, qc, 0);
++			ata_pio_queue_task(ap, qc, 0);
+ 
+ 		break;
+ 
+@@ -6113,7 +6062,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		if (qc->tf.flags & ATA_TFLAG_WRITE) {
+ 			/* PIO data out protocol */
+ 			ap->hsm_task_state = HSM_ST_FIRST;
+-			ata_port_queue_task(ap, ata_pio_task, qc, 0);
++			ata_pio_queue_task(ap, qc, 0);
+ 
+ 			/* always send first data block using
+ 			 * the ata_pio_task() codepath.
+@@ -6123,7 +6072,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 			ap->hsm_task_state = HSM_ST;
+ 
+ 			if (qc->tf.flags & ATA_TFLAG_POLLING)
+-				ata_port_queue_task(ap, ata_pio_task, qc, 0);
++				ata_pio_queue_task(ap, qc, 0);
+ 
+ 			/* if polling, ata_pio_task() handles the rest.
+ 			 * otherwise, interrupt handler takes over from here.
+@@ -6132,8 +6081,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 
+ 		break;
+ 
+-	case ATA_PROT_ATAPI:
+-	case ATA_PROT_ATAPI_NODATA:
++	case ATAPI_PROT_PIO:
++	case ATAPI_PROT_NODATA:
+ 		if (qc->tf.flags & ATA_TFLAG_POLLING)
+ 			ata_qc_set_polling(qc);
+ 
+@@ -6144,10 +6093,10 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		/* send cdb by polling if no cdb interrupt */
+ 		if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
+ 		    (qc->tf.flags & ATA_TFLAG_POLLING))
+-			ata_port_queue_task(ap, ata_pio_task, qc, 0);
++			ata_pio_queue_task(ap, qc, 0);
+ 		break;
+ 
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+ 
+ 		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
+@@ -6156,7 +6105,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ 
+ 		/* send cdb by polling if no cdb interrupt */
+ 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+-			ata_port_queue_task(ap, ata_pio_task, qc, 0);
++			ata_pio_queue_task(ap, qc, 0);
+ 		break;
+ 
+ 	default:
+@@ -6200,15 +6149,15 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
+ 		 */
+ 
+ 		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+-		 * The flag was turned on only for atapi devices.
+-		 * No need to check is_atapi_taskfile(&qc->tf) again.
++		 * The flag was turned on only for atapi devices.  No
++		 * need to check ata_is_atapi(qc->tf.protocol) again.
+ 		 */
+ 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+ 			goto idle_irq;
+ 		break;
+ 	case HSM_ST_LAST:
+ 		if (qc->tf.protocol == ATA_PROT_DMA ||
+-		    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
++		    qc->tf.protocol == ATAPI_PROT_DMA) {
+ 			/* check status of DMA engine */
+ 			host_stat = ap->ops->bmdma_status(ap);
+ 			VPRINTK("ata%u: host_stat 0x%X\n",
+@@ -6250,7 +6199,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
+ 	ata_hsm_move(ap, qc, status, 0);
+ 
+ 	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+-				       qc->tf.protocol == ATA_PROT_ATAPI_DMA))
++				       qc->tf.protocol == ATAPI_PROT_DMA))
+ 		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+ 
+ 	return 1;	/* irq handled */
+@@ -6772,7 +6721,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
+ 	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
+ #endif
+ 
+-	INIT_DELAYED_WORK(&ap->port_task, NULL);
++	INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
+ 	INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
+ 	INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
+ 	INIT_LIST_HEAD(&ap->eh_done_q);
+@@ -7589,7 +7538,6 @@ EXPORT_SYMBOL_GPL(ata_host_register);
+ EXPORT_SYMBOL_GPL(ata_host_activate);
+ EXPORT_SYMBOL_GPL(ata_host_detach);
+ EXPORT_SYMBOL_GPL(ata_sg_init);
+-EXPORT_SYMBOL_GPL(ata_sg_init_one);
+ EXPORT_SYMBOL_GPL(ata_hsm_move);
+ EXPORT_SYMBOL_GPL(ata_qc_complete);
+ EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
+@@ -7601,6 +7549,13 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select);
+ EXPORT_SYMBOL_GPL(sata_print_link_status);
+ EXPORT_SYMBOL_GPL(ata_tf_to_fis);
+ EXPORT_SYMBOL_GPL(ata_tf_from_fis);
++EXPORT_SYMBOL_GPL(ata_pack_xfermask);
++EXPORT_SYMBOL_GPL(ata_unpack_xfermask);
++EXPORT_SYMBOL_GPL(ata_xfer_mask2mode);
++EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
++EXPORT_SYMBOL_GPL(ata_xfer_mode2shift);
++EXPORT_SYMBOL_GPL(ata_mode_string);
++EXPORT_SYMBOL_GPL(ata_id_xfermask);
+ EXPORT_SYMBOL_GPL(ata_check_status);
+ EXPORT_SYMBOL_GPL(ata_altstatus);
+ EXPORT_SYMBOL_GPL(ata_exec_command);
+@@ -7643,7 +7598,6 @@ EXPORT_SYMBOL_GPL(ata_wait_register);
+ EXPORT_SYMBOL_GPL(ata_busy_sleep);
+ EXPORT_SYMBOL_GPL(ata_wait_after_reset);
+ EXPORT_SYMBOL_GPL(ata_wait_ready);
+-EXPORT_SYMBOL_GPL(ata_port_queue_task);
+ EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
+ EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
+ EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
+@@ -7662,18 +7616,20 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
+ #endif /* CONFIG_PM */
+ EXPORT_SYMBOL_GPL(ata_id_string);
+ EXPORT_SYMBOL_GPL(ata_id_c_string);
+-EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
+ EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+ 
+ EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
++EXPORT_SYMBOL_GPL(ata_timing_find_mode);
+ EXPORT_SYMBOL_GPL(ata_timing_compute);
+ EXPORT_SYMBOL_GPL(ata_timing_merge);
++EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
+ 
+ #ifdef CONFIG_PCI
+ EXPORT_SYMBOL_GPL(pci_test_config_bits);
+ EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
+ EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
+ EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
++EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host);
+ EXPORT_SYMBOL_GPL(ata_pci_init_one);
+ EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+ #ifdef CONFIG_PM
+@@ -7715,4 +7671,5 @@ EXPORT_SYMBOL_GPL(ata_dev_try_classify);
+ EXPORT_SYMBOL_GPL(ata_cable_40wire);
+ EXPORT_SYMBOL_GPL(ata_cable_80wire);
+ EXPORT_SYMBOL_GPL(ata_cable_unknown);
++EXPORT_SYMBOL_GPL(ata_cable_ignore);
+ EXPORT_SYMBOL_GPL(ata_cable_sata);
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index 21a81cd..4e31071 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -46,9 +46,26 @@
+ #include "libata.h"
+ 
+ enum {
++	/* speed down verdicts */
+ 	ATA_EH_SPDN_NCQ_OFF		= (1 << 0),
+ 	ATA_EH_SPDN_SPEED_DOWN		= (1 << 1),
+ 	ATA_EH_SPDN_FALLBACK_TO_PIO	= (1 << 2),
++	ATA_EH_SPDN_KEEP_ERRORS		= (1 << 3),
++
++	/* error flags */
++	ATA_EFLAG_IS_IO			= (1 << 0),
++	ATA_EFLAG_DUBIOUS_XFER		= (1 << 1),
++
++	/* error categories */
++	ATA_ECAT_NONE			= 0,
++	ATA_ECAT_ATA_BUS		= 1,
++	ATA_ECAT_TOUT_HSM		= 2,
++	ATA_ECAT_UNK_DEV		= 3,
++	ATA_ECAT_DUBIOUS_NONE		= 4,
++	ATA_ECAT_DUBIOUS_ATA_BUS	= 5,
++	ATA_ECAT_DUBIOUS_TOUT_HSM	= 6,
++	ATA_ECAT_DUBIOUS_UNK_DEV	= 7,
++	ATA_ECAT_NR			= 8,
+ };
+ 
+ /* Waiting in ->prereset can never be reliable.  It's sometimes nice
+@@ -213,12 +230,13 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
+ 	if (offset < 0)
+ 		ata_port_desc(ap, "%s %s%llu at 0x%llx", name, type, len, start);
+ 	else
+-		ata_port_desc(ap, "%s 0x%llx", name, start + offset);
++		ata_port_desc(ap, "%s 0x%llx", name,
++				start + (unsigned long long)offset);
+ }
+ 
+ #endif /* CONFIG_PCI */
+ 
+-static void ata_ering_record(struct ata_ering *ering, int is_io,
++static void ata_ering_record(struct ata_ering *ering, unsigned int eflags,
+ 			     unsigned int err_mask)
+ {
+ 	struct ata_ering_entry *ent;
+@@ -229,11 +247,20 @@ static void ata_ering_record(struct ata_ering *ering, int is_io,
+ 	ering->cursor %= ATA_ERING_SIZE;
+ 
+ 	ent = &ering->ring[ering->cursor];
+-	ent->is_io = is_io;
++	ent->eflags = eflags;
+ 	ent->err_mask = err_mask;
+ 	ent->timestamp = get_jiffies_64();
+ }
+ 
++static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
++{
++	struct ata_ering_entry *ent = &ering->ring[ering->cursor];
 +
-+out_put_alg:
-+	inst = ERR_PTR(err);
-+	goto out;
++	if (ent->err_mask)
++		return ent;
++	return NULL;
 +}
 +
-+static struct crypto_template crypto_rfc3686_tmpl = {
-+	.name = "rfc3686",
-+	.alloc = crypto_rfc3686_alloc,
-+	.free = crypto_ctr_free,
-+	.module = THIS_MODULE,
-+};
+ static void ata_ering_clear(struct ata_ering *ering)
+ {
+ 	memset(ering, 0, sizeof(*ering));
+@@ -445,9 +472,20 @@ void ata_scsi_error(struct Scsi_Host *host)
+ 		spin_lock_irqsave(ap->lock, flags);
+ 
+ 		__ata_port_for_each_link(link, ap) {
++			struct ata_eh_context *ehc = &link->eh_context;
++			struct ata_device *dev;
 +
-+static int __init crypto_ctr_module_init(void)
-+{
-+	int err;
+ 			memset(&link->eh_context, 0, sizeof(link->eh_context));
+ 			link->eh_context.i = link->eh_info;
+ 			memset(&link->eh_info, 0, sizeof(link->eh_info));
 +
-+	err = crypto_register_template(&crypto_ctr_tmpl);
-+	if (err)
-+		goto out;
++			ata_link_for_each_dev(dev, link) {
++				int devno = dev->devno;
 +
-+	err = crypto_register_template(&crypto_rfc3686_tmpl);
-+	if (err)
-+		goto out_drop_ctr;
++				ehc->saved_xfer_mode[devno] = dev->xfer_mode;
++				if (ata_ncq_enabled(dev))
++					ehc->saved_ncq_enabled |= 1 << devno;
++			}
+ 		}
+ 
+ 		ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
+@@ -1260,10 +1298,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
+ 
+ 	/* is it pointless to prefer PIO for "safety reasons"? */
+ 	if (ap->flags & ATA_FLAG_PIO_DMA) {
+-		tf.protocol = ATA_PROT_ATAPI_DMA;
++		tf.protocol = ATAPI_PROT_DMA;
+ 		tf.feature |= ATAPI_PKT_DMA;
+ 	} else {
+-		tf.protocol = ATA_PROT_ATAPI;
++		tf.protocol = ATAPI_PROT_PIO;
+ 		tf.lbam = SCSI_SENSE_BUFFERSIZE;
+ 		tf.lbah = 0;
+ 	}
+@@ -1451,20 +1489,29 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
+ 	return action;
+ }
+ 
+-static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
++static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
++				   int *xfer_ok)
+ {
++	int base = 0;
 +
-+out:
-+	return err;
++	if (!(eflags & ATA_EFLAG_DUBIOUS_XFER))
++		*xfer_ok = 1;
 +
-+out_drop_ctr:
-+	crypto_unregister_template(&crypto_ctr_tmpl);
-+	goto out;
-+}
++	if (!*xfer_ok)
++		base = ATA_ECAT_DUBIOUS_NONE;
 +
-+static void __exit crypto_ctr_module_exit(void)
-+{
-+	crypto_unregister_template(&crypto_rfc3686_tmpl);
-+	crypto_unregister_template(&crypto_ctr_tmpl);
-+}
+ 	if (err_mask & AC_ERR_ATA_BUS)
+-		return 1;
++		return base + ATA_ECAT_ATA_BUS;
+ 
+ 	if (err_mask & AC_ERR_TIMEOUT)
+-		return 2;
++		return base + ATA_ECAT_TOUT_HSM;
+ 
+-	if (is_io) {
++	if (eflags & ATA_EFLAG_IS_IO) {
+ 		if (err_mask & AC_ERR_HSM)
+-			return 2;
++			return base + ATA_ECAT_TOUT_HSM;
+ 		if ((err_mask &
+ 		     (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
+-			return 3;
++			return base + ATA_ECAT_UNK_DEV;
+ 	}
+ 
+ 	return 0;
+@@ -1472,18 +1519,22 @@ static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
+ 
+ struct speed_down_verdict_arg {
+ 	u64 since;
+-	int nr_errors[4];
++	int xfer_ok;
++	int nr_errors[ATA_ECAT_NR];
+ };
+ 
+ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
+ {
+ 	struct speed_down_verdict_arg *arg = void_arg;
+-	int cat = ata_eh_categorize_error(ent->is_io, ent->err_mask);
++	int cat;
+ 
+ 	if (ent->timestamp < arg->since)
+ 		return -1;
+ 
++	cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
++				      &arg->xfer_ok);
+ 	arg->nr_errors[cat]++;
 +
-+module_init(crypto_ctr_module_init);
-+module_exit(crypto_ctr_module_exit);
+ 	return 0;
+ }
+ 
+@@ -1495,22 +1546,48 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
+  *	whether NCQ needs to be turned off, transfer speed should be
+  *	stepped down, or falling back to PIO is necessary.
+  *
+- *	Cat-1 is ATA_BUS error for any command.
++ *	ECAT_ATA_BUS	: ATA_BUS error for any command
++ *
++ *	ECAT_TOUT_HSM	: TIMEOUT for any command or HSM violation for
++ *			  IO commands
++ *
++ *	ECAT_UNK_DEV	: Unknown DEV error for IO commands
++ *
++ *	ECAT_DUBIOUS_*	: Identical to above three but occurred while
++ *			  data transfer hasn't been verified.
++ *
++ *	Verdicts are
++ *
++ *	NCQ_OFF		: Turn off NCQ.
++ *
++ *	SPEED_DOWN	: Speed down transfer speed but don't fall back
++ *			  to PIO.
++ *
++ *	FALLBACK_TO_PIO	: Fall back to PIO.
++ *
++ *	Even if multiple verdicts are returned, only one action is
++ *	taken per error.  An action triggered by non-DUBIOUS errors
++ *	clears ering, while one triggered by DUBIOUS_* errors doesn't.
++ *	This is to expedite speed down decisions right after device is
++ *	initially configured.
+  *
+- *	Cat-2 is TIMEOUT for any command or HSM violation for known
+- *	supported commands.
++ *	The followings are speed down rules.  #1 and #2 deal with
++ *	DUBIOUS errors.
+  *
+- *	Cat-3 is is unclassified DEV error for known supported
+- *	command.
++ *	1. If more than one DUBIOUS_ATA_BUS or DUBIOUS_TOUT_HSM errors
++ *	   occurred during last 5 mins, SPEED_DOWN and FALLBACK_TO_PIO.
+  *
+- *	NCQ needs to be turned off if there have been more than 3
+- *	Cat-2 + Cat-3 errors during last 10 minutes.
++ *	2. If more than one DUBIOUS_TOUT_HSM or DUBIOUS_UNK_DEV errors
++ *	   occurred during last 5 mins, NCQ_OFF.
+  *
+- *	Speed down is necessary if there have been more than 3 Cat-1 +
+- *	Cat-2 errors or 10 Cat-3 errors during last 10 minutes.
++ *	3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors
++ *	   ocurred during last 5 mins, FALLBACK_TO_PIO
+  *
+- *	Falling back to PIO mode is necessary if there have been more
+- *	than 10 Cat-1 + Cat-2 + Cat-3 errors during last 5 minutes.
++ *	4. If more than 3 TOUT_HSM or UNK_DEV errors occurred
++ *	   during last 10 mins, NCQ_OFF.
++ *
++ *	5. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6
++ *	   UNK_DEV errors occurred during last 10 mins, SPEED_DOWN.
+  *
+  *	LOCKING:
+  *	Inherited from caller.
+@@ -1525,23 +1602,38 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
+ 	struct speed_down_verdict_arg arg;
+ 	unsigned int verdict = 0;
+ 
+-	/* scan past 10 mins of error history */
++	/* scan past 5 mins of error history */
+ 	memset(&arg, 0, sizeof(arg));
+-	arg.since = j64 - min(j64, j10mins);
++	arg.since = j64 - min(j64, j5mins);
+ 	ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
+ 
+-	if (arg.nr_errors[2] + arg.nr_errors[3] > 3)
+-		verdict |= ATA_EH_SPDN_NCQ_OFF;
+-	if (arg.nr_errors[1] + arg.nr_errors[2] > 3 || arg.nr_errors[3] > 10)
+-		verdict |= ATA_EH_SPDN_SPEED_DOWN;
++	if (arg.nr_errors[ATA_ECAT_DUBIOUS_ATA_BUS] +
++	    arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] > 1)
++		verdict |= ATA_EH_SPDN_SPEED_DOWN |
++			ATA_EH_SPDN_FALLBACK_TO_PIO | ATA_EH_SPDN_KEEP_ERRORS;
+ 
+-	/* scan past 3 mins of error history */
++	if (arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] +
++	    arg.nr_errors[ATA_ECAT_DUBIOUS_UNK_DEV] > 1)
++		verdict |= ATA_EH_SPDN_NCQ_OFF | ATA_EH_SPDN_KEEP_ERRORS;
 +
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("CTR Counter block mode");
-+MODULE_ALIAS("rfc3686");
-diff --git a/crypto/des_generic.c b/crypto/des_generic.c
-index 59966d1..355ecb7 100644
---- a/crypto/des_generic.c
-+++ b/crypto/des_generic.c
-@@ -20,13 +20,7 @@
- #include <linux/crypto.h>
- #include <linux/types.h>
++	if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
++	    arg.nr_errors[ATA_ECAT_TOUT_HSM] +
++	    arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
++		verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
++
++	/* scan past 10 mins of error history */
+ 	memset(&arg, 0, sizeof(arg));
+-	arg.since = j64 - min(j64, j5mins);
++	arg.since = j64 - min(j64, j10mins);
+ 	ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
  
--#define DES_KEY_SIZE		8
--#define DES_EXPKEY_WORDS	32
--#define DES_BLOCK_SIZE		8
--
--#define DES3_EDE_KEY_SIZE	(3 * DES_KEY_SIZE)
--#define DES3_EDE_EXPKEY_WORDS	(3 * DES_EXPKEY_WORDS)
--#define DES3_EDE_BLOCK_SIZE	DES_BLOCK_SIZE
-+#include <crypto/des.h>
+-	if (arg.nr_errors[1] + arg.nr_errors[2] + arg.nr_errors[3] > 10)
+-		verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
++	if (arg.nr_errors[ATA_ECAT_TOUT_HSM] +
++	    arg.nr_errors[ATA_ECAT_UNK_DEV] > 3)
++		verdict |= ATA_EH_SPDN_NCQ_OFF;
++
++	if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
++	    arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 ||
++	    arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
++		verdict |= ATA_EH_SPDN_SPEED_DOWN;
  
- #define ROL(x, r) ((x) = rol32((x), (r)))
- #define ROR(x, r) ((x) = ror32((x), (r)))
-@@ -634,7 +628,7 @@ static const u32 S8[64] = {
-  *   Choice 1 has operated on the key.
+ 	return verdict;
+ }
+@@ -1549,7 +1641,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
+ /**
+  *	ata_eh_speed_down - record error and speed down if necessary
+  *	@dev: Failed device
+- *	@is_io: Did the device fail during normal IO?
++ *	@eflags: mask of ATA_EFLAG_* flags
+  *	@err_mask: err_mask of the error
   *
+  *	Record error and examine error history to determine whether
+@@ -1563,18 +1655,20 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
+  *	RETURNS:
+  *	Determined recovery action.
   */
--static unsigned long ekey(u32 *pe, const u8 *k)
-+unsigned long des_ekey(u32 *pe, const u8 *k)
+-static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
+-				      unsigned int err_mask)
++static unsigned int ata_eh_speed_down(struct ata_device *dev,
++				unsigned int eflags, unsigned int err_mask)
  {
- 	/* K&R: long is at least 32 bits */
- 	unsigned long a, b, c, d, w;
-@@ -709,6 +703,7 @@ static unsigned long ekey(u32 *pe, const u8 *k)
- 	/* Zero if weak key */
- 	return w;
- }
-+EXPORT_SYMBOL_GPL(des_ekey);
++	struct ata_link *link = dev->link;
++	int xfer_ok = 0;
+ 	unsigned int verdict;
+ 	unsigned int action = 0;
  
- /*
-  * Decryption key expansion
-@@ -792,7 +787,7 @@ static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
- 	int ret;
+ 	/* don't bother if Cat-0 error */
+-	if (ata_eh_categorize_error(is_io, err_mask) == 0)
++	if (ata_eh_categorize_error(eflags, err_mask, &xfer_ok) == 0)
+ 		return 0;
  
- 	/* Expand to tmp */
--	ret = ekey(tmp, key);
-+	ret = des_ekey(tmp, key);
+ 	/* record error and determine whether speed down is necessary */
+-	ata_ering_record(&dev->ering, is_io, err_mask);
++	ata_ering_record(&dev->ering, eflags, err_mask);
+ 	verdict = ata_eh_speed_down_verdict(dev);
  
- 	if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
- 		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
-@@ -879,9 +874,9 @@ static int des3_ede_setkey(struct crypto_tfm *tfm, const u8 *key,
- 		return -EINVAL;
+ 	/* turn off NCQ? */
+@@ -1590,7 +1684,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
+ 	/* speed down? */
+ 	if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
+ 		/* speed down SATA link speed if possible */
+-		if (sata_down_spd_limit(dev->link) == 0) {
++		if (sata_down_spd_limit(link) == 0) {
+ 			action |= ATA_EH_HARDRESET;
+ 			goto done;
+ 		}
+@@ -1618,10 +1712,10 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
  	}
  
--	ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
-+	des_ekey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
- 	dkey(expkey, key); expkey += DES_EXPKEY_WORDS; key += DES_KEY_SIZE;
--	ekey(expkey, key);
-+	des_ekey(expkey, key);
- 
+ 	/* Fall back to PIO?  Slowing down to PIO is meaningless for
+-	 * SATA.  Consider it only for PATA.
++	 * SATA ATA devices.  Consider it only for PATA and SATAPI.
+ 	 */
+ 	if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
+-	    (dev->link->ap->cbl != ATA_CBL_SATA) &&
++	    (link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) &&
+ 	    (dev->xfer_shift != ATA_SHIFT_PIO)) {
+ 		if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
+ 			dev->spdn_cnt = 0;
+@@ -1633,7 +1727,8 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
  	return 0;
+  done:
+ 	/* device has been slowed down, blow error history */
+-	ata_ering_clear(&dev->ering);
++	if (!(verdict & ATA_EH_SPDN_KEEP_ERRORS))
++		ata_ering_clear(&dev->ering);
+ 	return action;
  }
-diff --git a/crypto/digest.c b/crypto/digest.c
-index 8871dec..6fd43bd 100644
---- a/crypto/digest.c
-+++ b/crypto/digest.c
-@@ -12,6 +12,7 @@
-  *
-  */
  
-+#include <crypto/scatterwalk.h>
- #include <linux/mm.h>
- #include <linux/errno.h>
- #include <linux/hardirq.h>
-@@ -20,9 +21,6 @@
- #include <linux/module.h>
- #include <linux/scatterlist.h>
+@@ -1653,8 +1748,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ 	struct ata_port *ap = link->ap;
+ 	struct ata_eh_context *ehc = &link->eh_context;
+ 	struct ata_device *dev;
+-	unsigned int all_err_mask = 0;
+-	int tag, is_io = 0;
++	unsigned int all_err_mask = 0, eflags = 0;
++	int tag;
+ 	u32 serror;
+ 	int rc;
  
--#include "internal.h"
--#include "scatterwalk.h"
--
- static int init(struct hash_desc *desc)
- {
- 	struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
-diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
-new file mode 100644
-index 0000000..eb90d27
---- /dev/null
-+++ b/crypto/eseqiv.c
-@@ -0,0 +1,264 @@
-+/*
-+ * eseqiv: Encrypted Sequence Number IV Generator
-+ *
-+ * This generator generates an IV based on a sequence number by xoring it
-+ * with a salt and then encrypting it with the same key as used to encrypt
-+ * the plain text.  This algorithm requires that the block size be equal
-+ * to the IV size.  It is mainly useful for CBC.
+@@ -1713,15 +1808,15 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ 		ehc->i.dev = qc->dev;
+ 		all_err_mask |= qc->err_mask;
+ 		if (qc->flags & ATA_QCFLAG_IO)
+-			is_io = 1;
++			eflags |= ATA_EFLAG_IS_IO;
+ 	}
+ 
+ 	/* enforce default EH actions */
+ 	if (ap->pflags & ATA_PFLAG_FROZEN ||
+ 	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
+ 		ehc->i.action |= ATA_EH_SOFTRESET;
+-	else if ((is_io && all_err_mask) ||
+-		 (!is_io && (all_err_mask & ~AC_ERR_DEV)))
++	else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
++		 (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
+ 		ehc->i.action |= ATA_EH_REVALIDATE;
+ 
+ 	/* If we have offending qcs and the associated failed device,
+@@ -1743,8 +1838,11 @@ static void ata_eh_link_autopsy(struct ata_link *link)
+ 		      ata_dev_enabled(link->device))))
+ 	    dev = link->device;
+ 
+-	if (dev)
+-		ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);
++	if (dev) {
++		if (dev->flags & ATA_DFLAG_DUBIOUS_XFER)
++			eflags |= ATA_EFLAG_DUBIOUS_XFER;
++		ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
++	}
+ 
+ 	DPRINTK("EXIT\n");
+ }
+@@ -1880,8 +1978,8 @@ static void ata_eh_link_report(struct ata_link *link)
+ 				[ATA_PROT_PIO]		= "pio",
+ 				[ATA_PROT_DMA]		= "dma",
+ 				[ATA_PROT_NCQ]		= "ncq",
+-				[ATA_PROT_ATAPI]	= "pio",
+-				[ATA_PROT_ATAPI_DMA]	= "dma",
++				[ATAPI_PROT_PIO]	= "pio",
++				[ATAPI_PROT_DMA]	= "dma",
+ 			};
+ 
+ 			snprintf(data_buf, sizeof(data_buf), " %s %u %s",
+@@ -1889,7 +1987,7 @@ static void ata_eh_link_report(struct ata_link *link)
+ 				 dma_str[qc->dma_dir]);
+ 		}
+ 
+-		if (is_atapi_taskfile(&qc->tf))
++		if (ata_is_atapi(qc->tf.protocol))
+ 			snprintf(cdb_buf, sizeof(cdb_buf),
+ 				 "cdb %02x %02x %02x %02x %02x %02x %02x %02x  "
+ 				 "%02x %02x %02x %02x %02x %02x %02x %02x\n         ",
+@@ -2329,6 +2427,58 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
+ 	return rc;
+ }
+ 
++/**
++ *	ata_set_mode - Program timings and issue SET FEATURES - XFER
++ *	@link: link on which timings will be programmed
++ *	@r_failed_dev: out paramter for failed device
 + *
-+ * Copyright (c) 2007 Herbert Xu <herbert at gondor.apana.org.au>
++ *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
++ *	ata_set_mode() fails, pointer to the failing device is
++ *	returned in @r_failed_dev.
 + *
-+ * 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.
++ *	LOCKING:
++ *	PCI/etc. bus probe sem.
 + *
++ *	RETURNS:
++ *	0 on success, negative errno otherwise
 + */
++int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
++{
++	struct ata_port *ap = link->ap;
++	struct ata_device *dev;
++	int rc;
 +
-+#include <crypto/internal/skcipher.h>
-+#include <crypto/scatterwalk.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/module.h>
-+#include <linux/random.h>
-+#include <linux/scatterlist.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
++	/* if data transfer is verified, clear DUBIOUS_XFER on ering top */
++	ata_link_for_each_dev(dev, link) {
++		if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) {
++			struct ata_ering_entry *ent;
 +
-+struct eseqiv_request_ctx {
-+	struct scatterlist src[2];
-+	struct scatterlist dst[2];
-+	char tail[];
-+};
++			ent = ata_ering_top(&dev->ering);
++			if (ent)
++				ent->eflags &= ~ATA_EFLAG_DUBIOUS_XFER;
++		}
++	}
 +
-+struct eseqiv_ctx {
-+	spinlock_t lock;
-+	unsigned int reqoff;
-+	char salt[];
-+};
++	/* has private set_mode? */
++	if (ap->ops->set_mode)
++		rc = ap->ops->set_mode(link, r_failed_dev);
++	else
++		rc = ata_do_set_mode(link, r_failed_dev);
 +
-+static void eseqiv_complete2(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
++	/* if transfer mode has changed, set DUBIOUS_XFER on device */
++	ata_link_for_each_dev(dev, link) {
++		struct ata_eh_context *ehc = &link->eh_context;
++		u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
++		u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
 +
-+	memcpy(req->giv, PTR_ALIGN((u8 *)reqctx->tail,
-+			 crypto_ablkcipher_alignmask(geniv) + 1),
-+	       crypto_ablkcipher_ivsize(geniv));
++		if (dev->xfer_mode != saved_xfer_mode ||
++		    ata_ncq_enabled(dev) != saved_ncq)
++			dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
++	}
++
++	return rc;
 +}
 +
-+static void eseqiv_complete(struct crypto_async_request *base, int err)
+ static int ata_link_nr_enabled(struct ata_link *link)
+ {
+ 	struct ata_device *dev;
+@@ -2375,6 +2525,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
+ 	return 1;
+ }
+ 
++static int ata_eh_schedule_probe(struct ata_device *dev)
 +{
-+	struct skcipher_givcrypt_request *req = base->data;
++	struct ata_eh_context *ehc = &dev->link->eh_context;
 +
-+	if (err)
-+		goto out;
++	if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
++	    (ehc->did_probe_mask & (1 << dev->devno)))
++		return 0;
 +
-+	eseqiv_complete2(req);
++	ata_eh_detach_dev(dev);
++	ata_dev_init(dev);
++	ehc->did_probe_mask |= (1 << dev->devno);
++	ehc->i.action |= ATA_EH_SOFTRESET;
++	ehc->saved_xfer_mode[dev->devno] = 0;
++	ehc->saved_ncq_enabled &= ~(1 << dev->devno);
 +
-+out:
-+	skcipher_givcrypt_complete(req, err);
++	return 1;
 +}
 +
-+static void eseqiv_chain(struct scatterlist *head, struct scatterlist *sg,
-+			 int chain)
-+{
-+	if (chain) {
-+		head->length += sg->length;
-+		sg = scatterwalk_sg_next(sg);
-+	}
-+
-+	if (sg)
-+		scatterwalk_sg_chain(head, 2, sg);
-+	else
-+		sg_mark_end(head);
-+}
+ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+ {
+ 	struct ata_eh_context *ehc = &dev->link->eh_context;
+@@ -2406,16 +2574,9 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
+ 		if (ata_link_offline(dev->link))
+ 			ata_eh_detach_dev(dev);
+ 
+-		/* probe if requested */
+-		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
+-		    !(ehc->did_probe_mask & (1 << dev->devno))) {
+-			ata_eh_detach_dev(dev);
+-			ata_dev_init(dev);
+-
++		/* schedule probe if necessary */
++		if (ata_eh_schedule_probe(dev))
+ 			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
+-			ehc->did_probe_mask |= (1 << dev->devno);
+-			ehc->i.action |= ATA_EH_SOFTRESET;
+-		}
+ 
+ 		return 1;
+ 	} else {
+@@ -2492,14 +2653,9 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 			if (dev->flags & ATA_DFLAG_DETACH)
+ 				ata_eh_detach_dev(dev);
+ 
+-			if (!ata_dev_enabled(dev) &&
+-			    ((ehc->i.probe_mask & (1 << dev->devno)) &&
+-			     !(ehc->did_probe_mask & (1 << dev->devno)))) {
+-				ata_eh_detach_dev(dev);
+-				ata_dev_init(dev);
+-				ehc->did_probe_mask |= (1 << dev->devno);
+-				ehc->i.action |= ATA_EH_SOFTRESET;
+-			}
++			/* schedule probe if necessary */
++			if (!ata_dev_enabled(dev))
++				ata_eh_schedule_probe(dev);
+ 		}
+ 	}
+ 
+@@ -2747,6 +2903,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
+ 	if (ap->ops->port_suspend)
+ 		rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+ 
++	ata_acpi_set_state(ap, PMSG_SUSPEND);
+  out:
+ 	/* report result */
+ 	spin_lock_irqsave(ap->lock, flags);
+@@ -2792,6 +2949,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
+ 
+ 	WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
+ 
++	ata_acpi_set_state(ap, PMSG_ON);
 +
-+static int eseqiv_givencrypt(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	struct eseqiv_request_ctx *reqctx = skcipher_givcrypt_reqctx(req);
-+	struct ablkcipher_request *subreq;
-+	crypto_completion_t complete;
-+	void *data;
-+	struct scatterlist *osrc, *odst;
-+	struct scatterlist *dst;
-+	struct page *srcp;
-+	struct page *dstp;
-+	u8 *giv;
-+	u8 *vsrc;
-+	u8 *vdst;
-+	__be64 seq;
-+	unsigned int ivsize;
-+	unsigned int len;
-+	int err;
+ 	if (ap->ops->port_resume)
+ 		rc = ap->ops->port_resume(ap);
+ 
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 14daf48..c02c490 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
+ 		qc->scsicmd = cmd;
+ 		qc->scsidone = done;
+ 
+-		qc->__sg = scsi_sglist(cmd);
++		qc->sg = scsi_sglist(cmd);
+ 		qc->n_elem = scsi_sg_count(cmd);
+ 	} else {
+ 		cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
+@@ -839,7 +839,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
+ 	if (dev->class == ATA_DEV_ATAPI) {
+ 		struct request_queue *q = sdev->request_queue;
+ 		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
+-	}
 +
-+	subreq = (void *)(reqctx->tail + ctx->reqoff);
-+	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
++		/* set the min alignment */
++		blk_queue_update_dma_alignment(sdev->request_queue,
++					       ATA_DMA_PAD_SZ - 1);
++	} else
++		/* ATA devices must be sector aligned */
++		blk_queue_update_dma_alignment(sdev->request_queue,
++					       ATA_SECT_SIZE - 1);
+ 
+ 	if (dev->class == ATA_DEV_ATA)
+ 		sdev->manage_start_stop = 1;
+@@ -878,7 +885,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
+ 	if (dev)
+ 		ata_scsi_dev_config(sdev, dev);
+ 
+-	return 0;	/* scsi layer doesn't check return value, sigh */
++	return 0;
+ }
+ 
+ /**
+@@ -2210,7 +2217,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+ 
+ 		/* sector size */
+ 		ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
+-		ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE);
++		ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
+ 	} else {
+ 		/* sector count, 64-bit */
+ 		ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
+@@ -2224,7 +2231,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+ 
+ 		/* sector size */
+ 		ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
+-		ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE);
++		ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
+ 	}
+ 
+ 	return 0;
+@@ -2331,7 +2338,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
+ 	DPRINTK("ATAPI request sense\n");
+ 
+ 	/* FIXME: is this needed? */
+-	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
++	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ 
+ 	ap->ops->tf_read(ap, &qc->tf);
+ 
+@@ -2341,7 +2348,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
+ 
+ 	ata_qc_reinit(qc);
+ 
+-	ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
++	/* setup sg table and init transfer direction */
++	sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
++	ata_sg_init(qc, &qc->sgent, 1);
+ 	qc->dma_dir = DMA_FROM_DEVICE;
+ 
+ 	memset(&qc->cdb, 0, qc->dev->cdb_len);
+@@ -2352,10 +2361,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
+ 	qc->tf.command = ATA_CMD_PACKET;
+ 
+ 	if (ata_pio_use_silly(ap)) {
+-		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
++		qc->tf.protocol = ATAPI_PROT_DMA;
+ 		qc->tf.feature |= ATAPI_PKT_DMA;
+ 	} else {
+-		qc->tf.protocol = ATA_PROT_ATAPI;
++		qc->tf.protocol = ATAPI_PROT_PIO;
+ 		qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
+ 		qc->tf.lbah = 0;
+ 	}
+@@ -2526,12 +2535,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
+ 	if (using_pio || nodata) {
+ 		/* no data, or PIO data xfer */
+ 		if (nodata)
+-			qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
++			qc->tf.protocol = ATAPI_PROT_NODATA;
+ 		else
+-			qc->tf.protocol = ATA_PROT_ATAPI;
++			qc->tf.protocol = ATAPI_PROT_PIO;
+ 	} else {
+ 		/* DMA data xfer */
+-		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
++		qc->tf.protocol = ATAPI_PROT_DMA;
+ 		qc->tf.feature |= ATAPI_PKT_DMA;
+ 
+ 		if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
+@@ -2690,6 +2699,24 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
+ 	if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
+ 		goto invalid_fld;
+ 
++	/*
++	 * Filter TPM commands by default. These provide an
++	 * essentially uncontrolled encrypted "back door" between
++	 * applications and the disk. Set libata.allow_tpm=1 if you
++	 * have a real reason for wanting to use them. This ensures
++	 * that installed software cannot easily mess stuff up without
++	 * user intent. DVR type users will probably ship with this enabled
++	 * for movie content management.
++	 *
++	 * Note that for ATA8 we can issue a DCS change and DCS freeze lock
++	 * for this and should do in future but that it is not sufficient as
++	 * DCS is an optional feature set. Thus we also do the software filter
++	 * so that we comply with the TC consortium stated goal that the user
++	 * can turn off TC features of their system.
++	 */
++	if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm)
++		goto invalid_fld;
 +
-+	giv = req->giv;
-+	complete = req->creq.base.complete;
-+	data = req->creq.base.data;
+ 	/* We may not issue DMA commands if no DMA mode is set */
+ 	if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
+ 		goto invalid_fld;
+diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
+index b7ac80b..60cd4b1 100644
+--- a/drivers/ata/libata-sff.c
++++ b/drivers/ata/libata-sff.c
+@@ -147,7 +147,9 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
+  *	@tf: ATA taskfile register set for storing input
+  *
+  *	Reads ATA taskfile registers for currently-selected device
+- *	into @tf.
++ *	into @tf. Assumes the device has a fully SFF compliant task file
++ *	layout and behaviour. If you device does not (eg has a different
++ *	status method) then you will need to provide a replacement tf_read
+  *
+  *	LOCKING:
+  *	Inherited from caller.
+@@ -156,7 +158,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ {
+ 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 
+-	tf->command = ata_chk_status(ap);
++	tf->command = ata_check_status(ap);
+ 	tf->feature = ioread8(ioaddr->error_addr);
+ 	tf->nsect = ioread8(ioaddr->nsect_addr);
+ 	tf->lbal = ioread8(ioaddr->lbal_addr);
+@@ -415,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 	ap->hsm_task_state = HSM_ST_IDLE;
+ 
+ 	if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
+-		   qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
++		   qc->tf.protocol == ATAPI_PROT_DMA)) {
+ 		u8 host_stat;
+ 
+ 		host_stat = ap->ops->bmdma_status(ap);
+@@ -549,7 +551,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
+ 		return rc;
+ 
+ 	/* request and iomap DMA region */
+-	rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
++	rc = pcim_iomap_regions(pdev, 1 << 4, dev_driver_string(gdev));
+ 	if (rc) {
+ 		dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n");
+ 		return -ENOMEM;
+@@ -619,7 +621,8 @@ int ata_pci_init_sff_host(struct ata_host *host)
+ 			continue;
+ 		}
+ 
+-		rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME);
++		rc = pcim_iomap_regions(pdev, 0x3 << base,
++					dev_driver_string(gdev));
+ 		if (rc) {
+ 			dev_printk(KERN_WARNING, gdev,
+ 				   "failed to request/iomap BARs for port %d "
+@@ -711,6 +714,99 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ }
+ 
+ /**
++ *	ata_pci_activate_sff_host - start SFF host, request IRQ and register it
++ *	@host: target SFF ATA host
++ *	@irq_handler: irq_handler used when requesting IRQ(s)
++ *	@sht: scsi_host_template to use when registering the host
++ *
++ *	This is the counterpart of ata_host_activate() for SFF ATA
++ *	hosts.  This separate helper is necessary because SFF hosts
++ *	use two separate interrupts in legacy mode.
++ *
++ *	LOCKING:
++ *	Inherited from calling layer (may sleep).
++ *
++ *	RETURNS:
++ *	0 on success, -errno otherwise.
++ */
++int ata_pci_activate_sff_host(struct ata_host *host,
++			      irq_handler_t irq_handler,
++			      struct scsi_host_template *sht)
++{
++	struct device *dev = host->dev;
++	struct pci_dev *pdev = to_pci_dev(dev);
++	const char *drv_name = dev_driver_string(host->dev);
++	int legacy_mode = 0, rc;
 +
-+	osrc = req->creq.src;
-+	odst = req->creq.dst;
-+	srcp = sg_page(osrc);
-+	dstp = sg_page(odst);
-+	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + osrc->offset;
-+	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + odst->offset;
++	rc = ata_host_start(host);
++	if (rc)
++		return rc;
 +
-+	ivsize = crypto_ablkcipher_ivsize(geniv);
++	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
++		u8 tmp8, mask;
 +
-+	if (vsrc != giv + ivsize && vdst != giv + ivsize) {
-+		giv = PTR_ALIGN((u8 *)reqctx->tail,
-+				crypto_ablkcipher_alignmask(geniv) + 1);
-+		complete = eseqiv_complete;
-+		data = req;
++		/* TODO: What if one channel is in native mode ... */
++		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
++		mask = (1 << 2) | (1 << 0);
++		if ((tmp8 & mask) != mask)
++			legacy_mode = 1;
++#if defined(CONFIG_NO_ATA_LEGACY)
++		/* Some platforms with PCI limits cannot address compat
++		   port space. In that case we punt if their firmware has
++		   left a device in compatibility mode */
++		if (legacy_mode) {
++			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
++			return -EOPNOTSUPP;
++		}
++#endif
 +	}
 +
-+	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
-+					data);
-+
-+	sg_init_table(reqctx->src, 2);
-+	sg_set_buf(reqctx->src, giv, ivsize);
-+	eseqiv_chain(reqctx->src, osrc, vsrc == giv + ivsize);
++	if (!devres_open_group(dev, NULL, GFP_KERNEL))
++		return -ENOMEM;
 +
-+	dst = reqctx->src;
-+	if (osrc != odst) {
-+		sg_init_table(reqctx->dst, 2);
-+		sg_set_buf(reqctx->dst, giv, ivsize);
-+		eseqiv_chain(reqctx->dst, odst, vdst == giv + ivsize);
++	if (!legacy_mode && pdev->irq) {
++		rc = devm_request_irq(dev, pdev->irq, irq_handler,
++				      IRQF_SHARED, drv_name, host);
++		if (rc)
++			goto out;
 +
-+		dst = reqctx->dst;
-+	}
++		ata_port_desc(host->ports[0], "irq %d", pdev->irq);
++		ata_port_desc(host->ports[1], "irq %d", pdev->irq);
++	} else if (legacy_mode) {
++		if (!ata_port_is_dummy(host->ports[0])) {
++			rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
++					      irq_handler, IRQF_SHARED,
++					      drv_name, host);
++			if (rc)
++				goto out;
 +
-+	ablkcipher_request_set_crypt(subreq, reqctx->src, dst,
-+				     req->creq.nbytes, req->creq.info);
++			ata_port_desc(host->ports[0], "irq %d",
++				      ATA_PRIMARY_IRQ(pdev));
++		}
 +
-+	memcpy(req->creq.info, ctx->salt, ivsize);
++		if (!ata_port_is_dummy(host->ports[1])) {
++			rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
++					      irq_handler, IRQF_SHARED,
++					      drv_name, host);
++			if (rc)
++				goto out;
 +
-+	len = ivsize;
-+	if (ivsize > sizeof(u64)) {
-+		memset(req->giv, 0, ivsize - sizeof(u64));
-+		len = sizeof(u64);
++			ata_port_desc(host->ports[1], "irq %d",
++				      ATA_SECONDARY_IRQ(pdev));
++		}
 +	}
-+	seq = cpu_to_be64(req->seq);
-+	memcpy(req->giv + ivsize - len, &seq, len);
-+
-+	err = crypto_ablkcipher_encrypt(subreq);
-+	if (err)
-+		goto out;
 +
-+	eseqiv_complete2(req);
++	rc = ata_host_register(host, sht);
++ out:
++	if (rc == 0)
++		devres_remove_group(dev, NULL);
++	else
++		devres_release_group(dev, NULL);
 +
-+out:
-+	return err;
++	return rc;
 +}
 +
-+static int eseqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+
-+	spin_lock_bh(&ctx->lock);
-+	if (crypto_ablkcipher_crt(geniv)->givencrypt != eseqiv_givencrypt_first)
-+		goto unlock;
-+
-+	crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt;
-+	get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
++/**
+  *	ata_pci_init_one - Initialize/register PCI IDE host controller
+  *	@pdev: Controller to be initialized
+  *	@ppi: array of port_info, must be enough for two ports
+@@ -739,8 +835,6 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ 	struct device *dev = &pdev->dev;
+ 	const struct ata_port_info *pi = NULL;
+ 	struct ata_host *host = NULL;
+-	u8 mask;
+-	int legacy_mode = 0;
+ 	int i, rc;
+ 
+ 	DPRINTK("ENTER\n");
+@@ -762,95 +856,24 @@ int ata_pci_init_one(struct pci_dev *pdev,
+ 	if (!devres_open_group(dev, NULL, GFP_KERNEL))
+ 		return -ENOMEM;
+ 
+-	/* FIXME: Really for ATA it isn't safe because the device may be
+-	   multi-purpose and we want to leave it alone if it was already
+-	   enabled. Secondly for shared use as Arjan says we want refcounting
+-
+-	   Checking dev->is_enabled is insufficient as this is not set at
+-	   boot for the primary video which is BIOS enabled
+-	  */
+-
+ 	rc = pcim_enable_device(pdev);
+ 	if (rc)
+-		goto err_out;
++		goto out;
+ 
+-	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+-		u8 tmp8;
+-
+-		/* TODO: What if one channel is in native mode ... */
+-		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
+-		mask = (1 << 2) | (1 << 0);
+-		if ((tmp8 & mask) != mask)
+-			legacy_mode = 1;
+-#if defined(CONFIG_NO_ATA_LEGACY)
+-		/* Some platforms with PCI limits cannot address compat
+-		   port space. In that case we punt if their firmware has
+-		   left a device in compatibility mode */
+-		if (legacy_mode) {
+-			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
+-			rc = -EOPNOTSUPP;
+-			goto err_out;
+-		}
+-#endif
+-	}
+-
+-	/* prepare host */
++	/* prepare and activate SFF host */
+ 	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
+ 	if (rc)
+-		goto err_out;
++		goto out;
+ 
+ 	pci_set_master(pdev);
++	rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
++				       pi->sht);
++ out:
++	if (rc == 0)
++		devres_remove_group(&pdev->dev, NULL);
++	else
++		devres_release_group(&pdev->dev, NULL);
+ 
+-	/* start host and request IRQ */
+-	rc = ata_host_start(host);
+-	if (rc)
+-		goto err_out;
+-
+-	if (!legacy_mode && pdev->irq) {
+-		/* We may have no IRQ assigned in which case we can poll. This
+-		   shouldn't happen on a sane system but robustness is cheap
+-		   in this case */
+-		rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
+-				      IRQF_SHARED, DRV_NAME, host);
+-		if (rc)
+-			goto err_out;
+-
+-		ata_port_desc(host->ports[0], "irq %d", pdev->irq);
+-		ata_port_desc(host->ports[1], "irq %d", pdev->irq);
+-	} else if (legacy_mode) {
+-		if (!ata_port_is_dummy(host->ports[0])) {
+-			rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
+-					      pi->port_ops->irq_handler,
+-					      IRQF_SHARED, DRV_NAME, host);
+-			if (rc)
+-				goto err_out;
+-
+-			ata_port_desc(host->ports[0], "irq %d",
+-				      ATA_PRIMARY_IRQ(pdev));
+-		}
+-
+-		if (!ata_port_is_dummy(host->ports[1])) {
+-			rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
+-					      pi->port_ops->irq_handler,
+-					      IRQF_SHARED, DRV_NAME, host);
+-			if (rc)
+-				goto err_out;
+-
+-			ata_port_desc(host->ports[1], "irq %d",
+-				      ATA_SECONDARY_IRQ(pdev));
+-		}
+-	}
+-
+-	/* register */
+-	rc = ata_host_register(host, pi->sht);
+-	if (rc)
+-		goto err_out;
+-
+-	devres_remove_group(dev, NULL);
+-	return 0;
+-
+-err_out:
+-	devres_release_group(dev, NULL);
+ 	return rc;
+ }
+ 
+diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
+index bbe59c2..409ffb9 100644
+--- a/drivers/ata/libata.h
++++ b/drivers/ata/libata.h
+@@ -60,6 +60,7 @@ extern int atapi_dmadir;
+ extern int atapi_passthru16;
+ extern int libata_fua;
+ extern int libata_noacpi;
++extern int libata_allow_tpm;
+ extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
+ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
+ 			   u64 block, u32 n_block, unsigned int tf_flags,
+@@ -85,7 +86,6 @@ extern int ata_dev_configure(struct ata_device *dev);
+ extern int sata_down_spd_limit(struct ata_link *link);
+ extern int sata_set_spd_needed(struct ata_link *link);
+ extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
+-extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
+ extern void ata_sg_clean(struct ata_queued_cmd *qc);
+ extern void ata_qc_free(struct ata_queued_cmd *qc);
+ extern void ata_qc_issue(struct ata_queued_cmd *qc);
+@@ -113,6 +113,7 @@ extern int ata_acpi_on_suspend(struct ata_port *ap);
+ extern void ata_acpi_on_resume(struct ata_port *ap);
+ extern int ata_acpi_on_devcfg(struct ata_device *dev);
+ extern void ata_acpi_on_disable(struct ata_device *dev);
++extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
+ #else
+ static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
+ static inline void ata_acpi_associate(struct ata_host *host) { }
+@@ -121,6 +122,8 @@ static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
+ static inline void ata_acpi_on_resume(struct ata_port *ap) { }
+ static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
+ static inline void ata_acpi_on_disable(struct ata_device *dev) { }
++static inline void ata_acpi_set_state(struct ata_port *ap,
++				      pm_message_t state) { }
+ #endif
+ 
+ /* libata-scsi.c */
+@@ -183,6 +186,7 @@ extern void ata_eh_report(struct ata_port *ap);
+ extern int ata_eh_reset(struct ata_link *link, int classify,
+ 			ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
+ 			ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
++extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
+ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
+ 			  ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
+ 			  ata_postreset_fn_t postreset,
+diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
+index e4542ab..244098a 100644
+--- a/drivers/ata/pata_acpi.c
++++ b/drivers/ata/pata_acpi.c
+@@ -81,17 +81,6 @@ static void pacpi_error_handler(struct ata_port *ap)
+ 				  NULL, ata_std_postreset);
+ }
+ 
+-/* Welcome to ACPI, bring a bucket */
+-static const unsigned int pio_cycle[7] = {
+-	600, 383, 240, 180, 120, 100, 80
+-};
+-static const unsigned int mwdma_cycle[5] = {
+-	480, 150, 120, 100, 80
+-};
+-static const unsigned int udma_cycle[7] = {
+-	120, 80, 60, 45, 30, 20, 15
+-};
+-
+ /**
+  *	pacpi_discover_modes	-	filter non ACPI modes
+  *	@adev: ATA device
+@@ -103,56 +92,20 @@ static const unsigned int udma_cycle[7] = {
+ 
+ static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
+ {
+-	int unit = adev->devno;
+ 	struct pata_acpi *acpi = ap->private_data;
+-	int i;
+-	u32 t;
+-	unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);
+-
+ 	struct ata_acpi_gtm probe;
++	unsigned int xfer_mask;
+ 
+ 	probe = acpi->gtm;
+ 
+-	/* We always use the 0 slot for crap hardware */
+-	if (!(probe.flags & 0x10))
+-		unit = 0;
+-
+ 	ata_acpi_gtm(ap, &probe);
+ 
+-	/* Start by scanning for PIO modes */
+-	for (i = 0; i < 7; i++) {
+-		t = probe.drive[unit].pio;
+-		if (t <= pio_cycle[i]) {
+-			mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
+-			break;
+-		}
+-	}
++	xfer_mask = ata_acpi_gtm_xfermask(adev, &probe);
+ 
+-	/* See if we have MWDMA or UDMA data. We don't bother with MWDMA
+-	   if UDMA is availabe as this means the BIOS set UDMA and our
+-	   error changedown if it works is UDMA to PIO anyway */
+-	if (probe.flags & (1 << (2 * unit))) {
+-		/* MWDMA */
+-		for (i = 0; i < 5; i++) {
+-			t = probe.drive[unit].dma;
+-			if (t <= mwdma_cycle[i]) {
+-				mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
+-				break;
+-			}
+-		}
+-	} else {
+-		/* UDMA */
+-		for (i = 0; i < 7; i++) {
+-			t = probe.drive[unit].dma;
+-			if (t <= udma_cycle[i]) {
+-				mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
+-				break;
+-			}
+-		}
+-	}
+-	if (mask & (0xF8 << ATA_SHIFT_UDMA))
++	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
+ 		ap->cbl = ATA_CBL_PATA80;
+-	return mask;
 +
-+unlock:
-+	spin_unlock_bh(&ctx->lock);
++	return xfer_mask;
+ }
+ 
+ /**
+@@ -180,12 +133,14 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ {
+ 	int unit = adev->devno;
+ 	struct pata_acpi *acpi = ap->private_data;
++	const struct ata_timing *t;
+ 
+ 	if (!(acpi->gtm.flags & 0x10))
+ 		unit = 0;
+ 
+ 	/* Now stuff the nS values into the structure */
+-	acpi->gtm.drive[unit].pio = pio_cycle[adev->pio_mode - XFER_PIO_0];
++	t = ata_timing_find_mode(adev->pio_mode);
++	acpi->gtm.drive[unit].pio = t->cycle;
+ 	ata_acpi_stm(ap, &acpi->gtm);
+ 	/* See what mode we actually got */
+ 	ata_acpi_gtm(ap, &acpi->gtm);
+@@ -201,16 +156,18 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ {
+ 	int unit = adev->devno;
+ 	struct pata_acpi *acpi = ap->private_data;
++	const struct ata_timing *t;
+ 
+ 	if (!(acpi->gtm.flags & 0x10))
+ 		unit = 0;
+ 
+ 	/* Now stuff the nS values into the structure */
++	t = ata_timing_find_mode(adev->dma_mode);
+ 	if (adev->dma_mode >= XFER_UDMA_0) {
+-		acpi->gtm.drive[unit].dma = udma_cycle[adev->dma_mode - XFER_UDMA_0];
++		acpi->gtm.drive[unit].dma = t->udma;
+ 		acpi->gtm.flags |= (1 << (2 * unit));
+ 	} else {
+-		acpi->gtm.drive[unit].dma = mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
++		acpi->gtm.drive[unit].dma = t->cycle;
+ 		acpi->gtm.flags &= ~(1 << (2 * unit));
+ 	}
+ 	ata_acpi_stm(ap, &acpi->gtm);
+diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
+index 8caf9af..7e68edf 100644
+--- a/drivers/ata/pata_ali.c
++++ b/drivers/ata/pata_ali.c
+@@ -64,7 +64,7 @@ static int ali_cable_override(struct pci_dev *pdev)
+ 	if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
+ 	   	return 1;
+ 	/* Mitac 8317 (Winbook-A) and relatives */
+-	if (pdev->subsystem_vendor == 0x1071  && pdev->subsystem_device == 0x8317)
++	if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
+ 		return 1;
+ 	/* Systems by DMI */
+ 	if (dmi_check_system(cable_dmi_table))
+diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
+index 3cc27b5..761a666 100644
+--- a/drivers/ata/pata_amd.c
++++ b/drivers/ata/pata_amd.c
+@@ -220,6 +220,62 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ 	timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
+ }
+ 
++/* Both host-side and drive-side detection results are worthless on NV
++ * PATAs.  Ignore them and just follow what BIOS configured.  Both the
++ * current configuration in PCI config reg and ACPI GTM result are
++ * cached during driver attach and are consulted to select transfer
++ * mode.
++ */
++static unsigned long nv_mode_filter(struct ata_device *dev,
++				    unsigned long xfer_mask)
++{
++	static const unsigned int udma_mask_map[] =
++		{ ATA_UDMA2, ATA_UDMA1, ATA_UDMA0, 0,
++		  ATA_UDMA3, ATA_UDMA4, ATA_UDMA5, ATA_UDMA6 };
++	struct ata_port *ap = dev->link->ap;
++	char acpi_str[32] = "";
++	u32 saved_udma, udma;
++	const struct ata_acpi_gtm *gtm;
++	unsigned long bios_limit = 0, acpi_limit = 0, limit;
 +
-+	return eseqiv_givencrypt(req);
-+}
++	/* find out what BIOS configured */
++	udma = saved_udma = (unsigned long)ap->host->private_data;
 +
-+static int eseqiv_init(struct crypto_tfm *tfm)
-+{
-+	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
-+	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	unsigned long alignmask;
-+	unsigned int reqsize;
++	if (ap->port_no == 0)
++		udma >>= 16;
++	if (dev->devno == 0)
++		udma >>= 8;
 +
-+	spin_lock_init(&ctx->lock);
++	if ((udma & 0xc0) == 0xc0)
++		bios_limit = ata_pack_xfermask(0, 0, udma_mask_map[udma & 0x7]);
 +
-+	alignmask = crypto_tfm_ctx_alignment() - 1;
-+	reqsize = sizeof(struct eseqiv_request_ctx);
++	/* consult ACPI GTM too */
++	gtm = ata_acpi_init_gtm(ap);
++	if (gtm) {
++		acpi_limit = ata_acpi_gtm_xfermask(dev, gtm);
 +
-+	if (alignmask & reqsize) {
-+		alignmask &= reqsize;
-+		alignmask--;
++		snprintf(acpi_str, sizeof(acpi_str), " (%u:%u:0x%x)",
++			 gtm->drive[0].dma, gtm->drive[1].dma, gtm->flags);
 +	}
 +
-+	alignmask = ~alignmask;
-+	alignmask &= crypto_ablkcipher_alignmask(geniv);
-+
-+	reqsize += alignmask;
-+	reqsize += crypto_ablkcipher_ivsize(geniv);
-+	reqsize = ALIGN(reqsize, crypto_tfm_ctx_alignment());
++	/* be optimistic, EH can take care of things if something goes wrong */
++	limit = bios_limit | acpi_limit;
 +
-+	ctx->reqoff = reqsize - sizeof(struct eseqiv_request_ctx);
++	/* If PIO or DMA isn't configured at all, don't limit.  Let EH
++	 * handle it.
++	 */
++	if (!(limit & ATA_MASK_PIO))
++		limit |= ATA_MASK_PIO;
++	if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA)))
++		limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA;
 +
-+	tfm->crt_ablkcipher.reqsize = reqsize +
-+				      sizeof(struct ablkcipher_request);
++	ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
++			"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
++			xfer_mask, limit, xfer_mask & limit, bios_limit,
++			saved_udma, acpi_limit, acpi_str);
 +
-+	return skcipher_geniv_init(tfm);
++	return xfer_mask & limit;
 +}
-+
-+static struct crypto_template eseqiv_tmpl;
-+
-+static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
+ 
+ /**
+  *	nv_probe_init	-	cable detection
+@@ -252,31 +308,6 @@ static void nv_error_handler(struct ata_port *ap)
+ 			       ata_std_postreset);
+ }
+ 
+-static int nv_cable_detect(struct ata_port *ap)
+-{
+-	static const u8 bitmask[2] = {0x03, 0x0C};
+-	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+-	u8 ata66;
+-	u16 udma;
+-	int cbl;
+-
+-	pci_read_config_byte(pdev, 0x52, &ata66);
+-	if (ata66 & bitmask[ap->port_no])
+-		cbl = ATA_CBL_PATA80;
+-	else
+-		cbl = ATA_CBL_PATA40;
+-
+- 	/* We now have to double check because the Nvidia boxes BIOS
+- 	   doesn't always set the cable bits but does set mode bits */
+- 	pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma);
+- 	if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400)
+-		cbl = ATA_CBL_PATA80;
+-	/* And a triple check across suspend/resume with ACPI around */
+-	if (ata_acpi_cbl_80wire(ap))
+-		cbl = ATA_CBL_PATA80;
+-	return cbl;
+-}
+-
+ /**
+  *	nv100_set_piomode	-	set initial PIO mode data
+  *	@ap: ATA interface
+@@ -314,6 +345,14 @@ static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ 	timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
+ }
+ 
++static void nv_host_stop(struct ata_host *host)
 +{
-+	struct crypto_instance *inst;
-+	int err;
-+
-+	inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0);
-+	if (IS_ERR(inst))
-+		goto out;
-+
-+	err = -EINVAL;
-+	if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize)
-+		goto free_inst;
++	u32 udma = (unsigned long)host->private_data;
 +
-+	inst->alg.cra_ablkcipher.givencrypt = eseqiv_givencrypt_first;
++	/* restore PCI config register 0x60 */
++	pci_write_config_dword(to_pci_dev(host->dev), 0x60, udma);
++}
 +
-+	inst->alg.cra_init = eseqiv_init;
-+	inst->alg.cra_exit = skcipher_geniv_exit;
+ static struct scsi_host_template amd_sht = {
+ 	.module			= THIS_MODULE,
+ 	.name			= DRV_NAME,
+@@ -478,7 +517,8 @@ static struct ata_port_operations nv100_port_ops = {
+ 	.thaw		= ata_bmdma_thaw,
+ 	.error_handler	= nv_error_handler,
+ 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= nv_cable_detect,
++	.cable_detect	= ata_cable_ignore,
++	.mode_filter	= nv_mode_filter,
+ 
+ 	.bmdma_setup 	= ata_bmdma_setup,
+ 	.bmdma_start 	= ata_bmdma_start,
+@@ -495,6 +535,7 @@ static struct ata_port_operations nv100_port_ops = {
+ 	.irq_on		= ata_irq_on,
+ 
+ 	.port_start	= ata_sff_port_start,
++	.host_stop	= nv_host_stop,
+ };
+ 
+ static struct ata_port_operations nv133_port_ops = {
+@@ -511,7 +552,8 @@ static struct ata_port_operations nv133_port_ops = {
+ 	.thaw		= ata_bmdma_thaw,
+ 	.error_handler	= nv_error_handler,
+ 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= nv_cable_detect,
++	.cable_detect	= ata_cable_ignore,
++	.mode_filter	= nv_mode_filter,
+ 
+ 	.bmdma_setup 	= ata_bmdma_setup,
+ 	.bmdma_start 	= ata_bmdma_start,
+@@ -528,6 +570,7 @@ static struct ata_port_operations nv133_port_ops = {
+ 	.irq_on		= ata_irq_on,
+ 
+ 	.port_start	= ata_sff_port_start,
++	.host_stop	= nv_host_stop,
+ };
+ 
+ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+@@ -614,7 +657,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 			.port_ops = &amd100_port_ops
+ 		}
+ 	};
+-	const struct ata_port_info *ppi[] = { NULL, NULL };
++	struct ata_port_info pi;
++	const struct ata_port_info *ppi[] = { &pi, NULL };
+ 	static int printed_version;
+ 	int type = id->driver_data;
+ 	u8 fifo;
+@@ -628,6 +672,19 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	if (type == 1 && pdev->revision > 0x7)
+ 		type = 2;
+ 
++	/* Serenade ? */
++	if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
++			 pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
++		type = 6;	/* UDMA 100 only */
 +
-+	inst->alg.cra_ctxsize = sizeof(struct eseqiv_ctx);
-+	inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
++	/*
++	 * Okay, type is determined now.  Apply type-specific workarounds.
++	 */
++	pi = info[type];
 +
-+out:
-+	return inst;
++	if (type < 3)
++		ata_pci_clear_simplex(pdev);
 +
-+free_inst:
-+	skcipher_geniv_free(inst);
-+	inst = ERR_PTR(err);
-+	goto out;
-+}
+ 	/* Check for AMD7411 */
+ 	if (type == 3)
+ 		/* FIFO is broken */
+@@ -635,16 +692,17 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	else
+ 		pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
+ 
+-	/* Serenade ? */
+-	if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+-			 pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+-		type = 6;	/* UDMA 100 only */
++	/* Cable detection on Nvidia chips doesn't work too well,
++	 * cache BIOS programmed UDMA mode.
++	 */
++	if (type == 7 || type == 8) {
++		u32 udma;
+ 
+-	if (type < 3)
+-		ata_pci_clear_simplex(pdev);
++		pci_read_config_dword(pdev, 0x60, &udma);
++		pi.private_data = (void *)(unsigned long)udma;
++	}
+ 
+ 	/* And fire it up */
+-	ppi[0] = &info[type];
+ 	return ata_pci_init_one(pdev, ppi);
+ }
+ 
+diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c
+index 67e574d..db057b1 100644
+--- a/drivers/ata/pata_at32.c
++++ b/drivers/ata/pata_at32.c
+@@ -324,7 +324,7 @@ static int __init pata_at32_probe(struct platform_device *pdev)
+ 	if (irq < 0)
+ 		return irq;
+ 
+-	/* Setup struct containing private infomation */
++	/* Setup struct containing private information */
+ 	info = kzalloc(sizeof(struct at32_ide_info), GFP_KERNEL);
+ 	if (!info)
+ 		return -ENOMEM;
+diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
+index 7842cc4..7f87f10 100644
+--- a/drivers/ata/pata_bf54x.c
++++ b/drivers/ata/pata_bf54x.c
+@@ -299,7 +299,7 @@ static void bfin_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 	*/
+ 	n6 = num_clocks_min(t6min, fsclk);
+ 	if (mode >= 0 && mode <= 4 && n6 >= 1) {
+-		pr_debug("set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
++		dev_dbg(adev->link->ap->dev, "set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
+ 		/* calculate the timing values for register transfers. */
+ 		while (mode > 0 && pio_fsclk[mode] > fsclk)
+ 			mode--;
+@@ -376,7 +376,7 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ 
+ 	mode = adev->dma_mode - XFER_UDMA_0;
+ 	if (mode >= 0 && mode <= 5) {
+-		pr_debug("set udmamode: mode=%d\n", mode);
++		dev_dbg(adev->link->ap->dev, "set udmamode: mode=%d\n", mode);
+ 		/* the most restrictive timing value is t6 and tc,
+ 		 * the DIOW - data hold. If one SCLK pulse is longer
+ 		 * than this minimum value then register
+@@ -433,7 +433,7 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ 
+ 	mode = adev->dma_mode - XFER_MW_DMA_0;
+ 	if (mode >= 0 && mode <= 2) {
+-		pr_debug("set mdmamode: mode=%d\n", mode);
++		dev_dbg(adev->link->ap->dev, "set mdmamode: mode=%d\n", mode);
+ 		/* the most restrictive timing value is tf, the DMACK to
+ 		 * read data released. If one SCLK pulse is longer than
+ 		 * this maximum value then the MDMA mode
+@@ -697,7 +697,7 @@ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ 			write_atapi_register(base, ATA_REG_LBAL, tf->hob_lbal);
+ 			write_atapi_register(base, ATA_REG_LBAM, tf->hob_lbam);
+ 			write_atapi_register(base, ATA_REG_LBAH, tf->hob_lbah);
+-			pr_debug("hob: feat 0x%X nsect 0x%X, lba 0x%X "
++			dev_dbg(ap->dev, "hob: feat 0x%X nsect 0x%X, lba 0x%X "
+ 				 "0x%X 0x%X\n",
+ 				tf->hob_feature,
+ 				tf->hob_nsect,
+@@ -711,7 +711,7 @@ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ 		write_atapi_register(base, ATA_REG_LBAL, tf->lbal);
+ 		write_atapi_register(base, ATA_REG_LBAM, tf->lbam);
+ 		write_atapi_register(base, ATA_REG_LBAH, tf->lbah);
+-		pr_debug("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
++		dev_dbg(ap->dev, "feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
+ 			tf->feature,
+ 			tf->nsect,
+ 			tf->lbal,
+@@ -721,7 +721,7 @@ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ 
+ 	if (tf->flags & ATA_TFLAG_DEVICE) {
+ 		write_atapi_register(base, ATA_REG_DEVICE, tf->device);
+-		pr_debug("device 0x%X\n", tf->device);
++		dev_dbg(ap->dev, "device 0x%X\n", tf->device);
+ 	}
+ 
+ 	ata_wait_idle(ap);
+@@ -782,7 +782,7 @@ static void bfin_exec_command(struct ata_port *ap,
+ 			      const struct ata_taskfile *tf)
+ {
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+-	pr_debug("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
++	dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+ 
+ 	write_atapi_register(base, ATA_REG_CMD, tf->command);
+ 	ata_pause(ap);
+@@ -832,14 +832,15 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
+ {
+ 	unsigned short config = WDSIZE_16;
+ 	struct scatterlist *sg;
++	unsigned int si;
+ 
+-	pr_debug("in atapi dma setup\n");
++	dev_dbg(qc->ap->dev, "in atapi dma setup\n");
+ 	/* Program the ATA_CTRL register with dir */
+ 	if (qc->tf.flags & ATA_TFLAG_WRITE) {
+ 		/* fill the ATAPI DMA controller */
+ 		set_dma_config(CH_ATAPI_TX, config);
+ 		set_dma_x_modify(CH_ATAPI_TX, 2);
+-		ata_for_each_sg(sg, qc) {
++		for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 			set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
+ 			set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
+ 		}
+@@ -848,7 +849,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
+ 		/* fill the ATAPI DMA controller */
+ 		set_dma_config(CH_ATAPI_RX, config);
+ 		set_dma_x_modify(CH_ATAPI_RX, 2);
+-		ata_for_each_sg(sg, qc) {
++		for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 			set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
+ 			set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
+ 		}
+@@ -867,8 +868,9 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
+ 	struct ata_port *ap = qc->ap;
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 	struct scatterlist *sg;
++	unsigned int si;
+ 
+-	pr_debug("in atapi dma start\n");
++	dev_dbg(qc->ap->dev, "in atapi dma start\n");
+ 	if (!(ap->udma_mask || ap->mwdma_mask))
+ 		return;
+ 
+@@ -881,12 +883,12 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
+ 		 * data cache is enabled. Otherwise, this loop
+ 		 * is an empty loop and optimized out.
+ 		 */
+-		ata_for_each_sg(sg, qc) {
++		for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 			flush_dcache_range(sg_dma_address(sg),
+ 				sg_dma_address(sg) + sg_dma_len(sg));
+ 		}
+ 		enable_dma(CH_ATAPI_TX);
+-		pr_debug("enable udma write\n");
++		dev_dbg(qc->ap->dev, "enable udma write\n");
+ 
+ 		/* Send ATA DMA write command */
+ 		bfin_exec_command(ap, &qc->tf);
+@@ -896,7 +898,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
+ 			| XFER_DIR));
+ 	} else {
+ 		enable_dma(CH_ATAPI_RX);
+-		pr_debug("enable udma read\n");
++		dev_dbg(qc->ap->dev, "enable udma read\n");
+ 
+ 		/* Send ATA DMA read command */
+ 		bfin_exec_command(ap, &qc->tf);
+@@ -910,7 +912,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
+ 	ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
+ 
+ 		/* Set transfer length to buffer len */
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
+ 	}
+ 
+@@ -932,8 +934,9 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct scatterlist *sg;
++	unsigned int si;
+ 
+-	pr_debug("in atapi dma stop\n");
++	dev_dbg(qc->ap->dev, "in atapi dma stop\n");
+ 	if (!(ap->udma_mask || ap->mwdma_mask))
+ 		return;
+ 
+@@ -950,7 +953,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
+ 			 * data cache is enabled. Otherwise, this loop
+ 			 * is an empty loop and optimized out.
+ 			 */
+-			ata_for_each_sg(sg, qc) {
++			for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 				invalidate_dcache_range(
+ 					sg_dma_address(sg),
+ 					sg_dma_address(sg)
+@@ -1144,15 +1147,15 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 	unsigned short int_status = ATAPI_GET_INT_STATUS(base);
+ 
+-	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) {
++	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON))
+ 		host_stat |= ATA_DMA_ACTIVE;
+-	}
+-	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) {
++	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT|
++		ATAPI_DEV_INT))
+ 		host_stat |= ATA_DMA_INTR;
+-	}
+-	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) {
+-		host_stat |= ATA_DMA_ERR;
+-	}
++	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT))
++		host_stat |= ATA_DMA_ERR|ATA_DMA_INTR;
 +
-+static struct crypto_template eseqiv_tmpl = {
-+	.name = "eseqiv",
-+	.alloc = eseqiv_alloc,
-+	.free = skcipher_geniv_free,
-+	.module = THIS_MODULE,
-+};
++	dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat);
+ 
+ 	return host_stat;
+ }
+@@ -1167,34 +1170,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
+  *	Note: Original code is ata_data_xfer().
+  */
+ 
+-static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
+-			   unsigned int buflen, int write_data)
++static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
++				   unsigned int buflen, int rw)
+ {
+-	struct ata_port *ap = adev->link->ap;
+-	unsigned int words = buflen >> 1;
+-	unsigned short *buf16 = (u16 *) buf;
++	struct ata_port *ap = dev->link->ap;
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
++	unsigned int words = buflen >> 1;
++	unsigned short *buf16 = (u16 *)buf;
+ 
+ 	/* Transfer multiple of 2 bytes */
+-	if (write_data) {
+-		write_atapi_data(base, words, buf16);
+-	} else {
++	if (rw == READ)
+ 		read_atapi_data(base, words, buf16);
+-	}
++	else
++		write_atapi_data(base, words, buf16);
+ 
+ 	/* Transfer trailing 1 byte, if any. */
+ 	if (unlikely(buflen & 0x01)) {
+ 		unsigned short align_buf[1] = { 0 };
+ 		unsigned char *trailing_buf = buf + buflen - 1;
+ 
+-		if (write_data) {
+-			memcpy(align_buf, trailing_buf, 1);
+-			write_atapi_data(base, 1, align_buf);
+-		} else {
++		if (rw == READ) {
+ 			read_atapi_data(base, 1, align_buf);
+ 			memcpy(trailing_buf, align_buf, 1);
++		} else {
++			memcpy(align_buf, trailing_buf, 1);
++			write_atapi_data(base, 1, align_buf);
+ 		}
++		words++;
+ 	}
 +
-+static int __init eseqiv_module_init(void)
-+{
-+	return crypto_register_template(&eseqiv_tmpl);
-+}
++	return words << 1;
+ }
+ 
+ /**
+@@ -1208,8 +1213,7 @@ static void bfin_irq_clear(struct ata_port *ap)
+ {
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 
+-	pr_debug("in atapi irq clear\n");
+-
++	dev_dbg(ap->dev, "in atapi irq clear\n");
+ 	ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
+ 		| MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
+ 		| MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
+@@ -1227,7 +1231,7 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 	u8 tmp;
+ 
+-	pr_debug("in atapi irq on\n");
++	dev_dbg(ap->dev, "in atapi irq on\n");
+ 	ap->ctl &= ~ATA_NIEN;
+ 	ap->last_ctl = ap->ctl;
+ 
+@@ -1250,7 +1254,7 @@ static void bfin_bmdma_freeze(struct ata_port *ap)
+ {
+ 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 
+-	pr_debug("in atapi dma freeze\n");
++	dev_dbg(ap->dev, "in atapi dma freeze\n");
+ 	ap->ctl |= ATA_NIEN;
+ 	ap->last_ctl = ap->ctl;
+ 
+@@ -1323,7 +1327,7 @@ static void bfin_error_handler(struct ata_port *ap)
+ 
+ static void bfin_port_stop(struct ata_port *ap)
+ {
+-	pr_debug("in atapi port stop\n");
++	dev_dbg(ap->dev, "in atapi port stop\n");
+ 	if (ap->udma_mask != 0 || ap->mwdma_mask != 0) {
+ 		free_dma(CH_ATAPI_RX);
+ 		free_dma(CH_ATAPI_TX);
+@@ -1332,7 +1336,7 @@ static void bfin_port_stop(struct ata_port *ap)
+ 
+ static int bfin_port_start(struct ata_port *ap)
+ {
+-	pr_debug("in atapi port start\n");
++	dev_dbg(ap->dev, "in atapi port start\n");
+ 	if (!(ap->udma_mask || ap->mwdma_mask))
+ 		return 0;
+ 
+@@ -1368,10 +1372,6 @@ static struct scsi_host_template bfin_sht = {
+ 	.slave_configure	= ata_scsi_slave_config,
+ 	.slave_destroy		= ata_scsi_slave_destroy,
+ 	.bios_param		= ata_std_bios_param,
+-#ifdef CONFIG_PM
+-	.resume			= ata_scsi_device_resume,
+-	.suspend		= ata_scsi_device_suspend,
+-#endif
+ };
+ 
+ static const struct ata_port_operations bfin_pata_ops = {
+diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
+index 33f7f08..7ed279b 100644
+--- a/drivers/ata/pata_cs5520.c
++++ b/drivers/ata/pata_cs5520.c
+@@ -198,7 +198,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 	};
+ 	const struct ata_port_info *ppi[2];
+ 	u8 pcicfg;
+-	void *iomap[5];
++	void __iomem *iomap[5];
+ 	struct ata_host *host;
+ 	struct ata_ioports *ioaddr;
+ 	int i, rc;
+@@ -229,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
+ 		return -ENOMEM;
+ 
+ 	/* Perform set up for DMA */
+-	if (pci_enable_device_bars(pdev, 1<<2)) {
++	if (pci_enable_device_io(pdev)) {
+ 		printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
+ 		return -ENODEV;
+ 	}
+diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c
+index 043dcd3..dc33220 100644
+--- a/drivers/ata/pata_efar.c
++++ b/drivers/ata/pata_efar.c
+@@ -135,7 +135,7 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev)
+ 		idetm_data &= 0xCC0F;
+ 		idetm_data |= (control << 4);
+ 
+-		/* Slave timing in seperate register */
++		/* Slave timing in separate register */
+ 		pci_read_config_byte(dev, 0x44, &slave_data);
+ 		slave_data &= 0x0F << shift;
+ 		slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << shift;
+diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
+index c79f066..68eb349 100644
+--- a/drivers/ata/pata_hpt37x.c
++++ b/drivers/ata/pata_hpt37x.c
+@@ -847,15 +847,16 @@ static u32 hpt374_read_freq(struct pci_dev *pdev)
+ 	u32 freq;
+ 	unsigned long io_base = pci_resource_start(pdev, 4);
+ 	if (PCI_FUNC(pdev->devfn) & 1) {
+-		struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
++		struct pci_dev *pdev_0;
 +
-+static void __exit eseqiv_module_exit(void)
-+{
-+	crypto_unregister_template(&eseqiv_tmpl);
++		pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
+ 		/* Someone hot plugged the controller on us ? */
+ 		if (pdev_0 == NULL)
+ 			return 0;
+ 		io_base = pci_resource_start(pdev_0, 4);
+ 		freq = inl(io_base + 0x90);
+ 		pci_dev_put(pdev_0);
+-	}
+-	else
++	} else
+ 		freq = inl(io_base + 0x90);
+ 	return freq;
+ }
+diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
+index 842fe08..5b8586d 100644
+--- a/drivers/ata/pata_icside.c
++++ b/drivers/ata/pata_icside.c
+@@ -224,6 +224,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+ 	struct pata_icside_state *state = ap->host->private_data;
+ 	struct scatterlist *sg, *rsg = state->sg;
+ 	unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
++	unsigned int si;
+ 
+ 	/*
+ 	 * We are simplex; BUG if we try to fiddle with DMA
+@@ -234,7 +235,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
+ 	/*
+ 	 * Copy ATAs scattered sg list into a contiguous array of sg
+ 	 */
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		memcpy(rsg, sg, sizeof(*sg));
+ 		rsg++;
+ 	}
+diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c
+index 1eda821..e0c2cc2 100644
+--- a/drivers/ata/pata_it8213.c
++++ b/drivers/ata/pata_it8213.c
+@@ -128,7 +128,7 @@ static void it8213_set_piomode (struct ata_port *ap, struct ata_device *adev)
+ 		idetm_data &= 0xCC0F;
+ 		idetm_data |= (control << 4);
+ 
+-		/* Slave timing in seperate register */
++		/* Slave timing in separate register */
+ 		pci_read_config_byte(dev, 0x44, &slave_data);
+ 		slave_data &= 0xF0;
+ 		slave_data |= ((timings[pio][0] << 2) | timings[pio][1]) << 4;
+diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
+index ca9aae0..109ddd4 100644
+--- a/drivers/ata/pata_it821x.c
++++ b/drivers/ata/pata_it821x.c
+@@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
+ 			return ata_qc_issue_prot(qc);
+ 	}
+ 	printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
+-	return AC_ERR_INVALID;
++	return AC_ERR_DEV;
+ }
+ 
+ /**
+@@ -516,6 +516,37 @@ static void it821x_dev_config(struct ata_device *adev)
+ 			printk("(%dK stripe)", adev->id[146]);
+ 		printk(".\n");
+ 	}
++	/* This is a controller firmware triggered funny, don't
++	   report the drive faulty! */
++	adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
 +}
 +
-+module_init(eseqiv_module_init);
-+module_exit(eseqiv_module_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
-diff --git a/crypto/gcm.c b/crypto/gcm.c
-new file mode 100644
-index 0000000..e70afd0
---- /dev/null
-+++ b/crypto/gcm.c
-@@ -0,0 +1,823 @@
-+/*
-+ * GCM: Galois/Counter Mode.
++/**
++ *	it821x_ident_hack	-	Hack identify data up
++ *	@ap: Port
 + *
-+ * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1 at iki.fi>
++ *	Walk the devices on this firmware driven port and slightly
++ *	mash the identify data to stop us and common tools trying to
++ *	use features not firmware supported. The firmware itself does
++ *	some masking (eg SMART) but not enough.
 + *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
++ *	This is a bit of an abuse of the cable method, but it is the
++ *	only method called at the right time. We could modify the libata
++ *	core specifically for ident hacking but while we have one offender
++ *	it seems better to keep the fallout localised.
 + */
 +
-+#include <crypto/gf128mul.h>
-+#include <crypto/internal/aead.h>
-+#include <crypto/internal/skcipher.h>
-+#include <crypto/scatterwalk.h>
-+#include <linux/completion.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/slab.h>
-+
-+struct gcm_instance_ctx {
-+	struct crypto_skcipher_spawn ctr;
-+};
++static int it821x_ident_hack(struct ata_port *ap)
++{
++	struct ata_device *adev;
++	ata_link_for_each_dev(adev, &ap->link) {
++		if (ata_dev_enabled(adev)) {
++			adev->id[84] &= ~(1 << 6);	/* No FUA */
++			adev->id[85] &= ~(1 << 10);	/* No HPA */
++			adev->id[76] = 0;		/* No NCQ/AN etc */
++		}
++	}
++	return ata_cable_unknown(ap);
+ }
+ 
+ 
+@@ -634,7 +665,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
+ 	.thaw		= ata_bmdma_thaw,
+ 	.error_handler	= ata_bmdma_error_handler,
+ 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
+-	.cable_detect	= ata_cable_unknown,
++	.cable_detect	= it821x_ident_hack,
+ 
+ 	.bmdma_setup 	= ata_bmdma_setup,
+ 	.bmdma_start 	= ata_bmdma_start,
+diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
+index 120b5bf..030878f 100644
+--- a/drivers/ata/pata_ixp4xx_cf.c
++++ b/drivers/ata/pata_ixp4xx_cf.c
+@@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
+ 	return 0;
+ }
+ 
+-static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
+-				unsigned int buflen, int write_data)
++static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
++				unsigned char *buf, unsigned int buflen, int rw)
+ {
+ 	unsigned int i;
+ 	unsigned int words = buflen >> 1;
+ 	u16 *buf16 = (u16 *) buf;
+-	struct ata_port *ap = adev->link->ap;
++	struct ata_port *ap = dev->link->ap;
+ 	void __iomem *mmio = ap->ioaddr.data_addr;
+ 	struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
+ 
+@@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
+ 	udelay(100);
+ 
+ 	/* Transfer multiple of 2 bytes */
+-	if (write_data) {
+-		for (i = 0; i < words; i++)
+-			writew(buf16[i], mmio);
+-	} else {
++	if (rw == READ)
+ 		for (i = 0; i < words; i++)
+ 			buf16[i] = readw(mmio);
+-	}
++	else
++		for (i = 0; i < words; i++)
++			writew(buf16[i], mmio);
+ 
+ 	/* Transfer trailing 1 byte, if any. */
+ 	if (unlikely(buflen & 0x01)) {
+ 		u16 align_buf[1] = { 0 };
+ 		unsigned char *trailing_buf = buf + buflen - 1;
+ 
+-		if (write_data) {
+-			memcpy(align_buf, trailing_buf, 1);
+-			writew(align_buf[0], mmio);
+-		} else {
++		if (rw == READ) {
+ 			align_buf[0] = readw(mmio);
+ 			memcpy(trailing_buf, align_buf, 1);
++		} else {
++			memcpy(align_buf, trailing_buf, 1);
++			writew(align_buf[0], mmio);
+ 		}
++		words++;
+ 	}
+ 
+ 	udelay(100);
+ 	*data->cs0_cfg |= 0x01;
 +
-+struct crypto_gcm_ctx {
-+	struct crypto_ablkcipher *ctr;
-+	struct gf128mul_4k *gf128;
-+};
++	return words << 1;
+ }
+ 
+ static struct scsi_host_template ixp4xx_sht = {
+diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
+index 17159b5..333dc15 100644
+--- a/drivers/ata/pata_legacy.c
++++ b/drivers/ata/pata_legacy.c
+@@ -28,7 +28,6 @@
+  *
+  *  Unsupported but docs exist:
+  *	Appian/Adaptec AIC25VL01/Cirrus Logic PD7220
+- *	Winbond W83759A
+  *
+  *  This driver handles legacy (that is "ISA/VLB side") IDE ports found
+  *  on PC class systems. There are three hybrid devices that are exceptions
+@@ -36,7 +35,7 @@
+  *  the MPIIX where the tuning is PCI side but the IDE is "ISA side".
+  *
+  *  Specific support is included for the ht6560a/ht6560b/opti82c611a/
+- *  opti82c465mv/promise 20230c/20630
++ *  opti82c465mv/promise 20230c/20630/winbond83759A
+  *
+  *  Use the autospeed and pio_mask options with:
+  *	Appian ADI/2 aka CLPD7220 or AIC25VL01.
+@@ -47,9 +46,6 @@
+  *  For now use autospeed and pio_mask as above with the W83759A. This may
+  *  change.
+  *
+- *  TODO
+- *	Merge existing pata_qdi driver
+- *
+  */
+ 
+ #include <linux/kernel.h>
+@@ -64,12 +60,13 @@
+ #include <linux/platform_device.h>
+ 
+ #define DRV_NAME "pata_legacy"
+-#define DRV_VERSION "0.5.5"
++#define DRV_VERSION "0.6.5"
+ 
+ #define NR_HOST 6
+ 
+-static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
+-static int legacy_irq[NR_HOST] = { 14, 15, 11, 10, 8, 12 };
++static int all;
++module_param(all, int, 0444);
++MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
+ 
+ struct legacy_data {
+ 	unsigned long timing;
+@@ -80,21 +77,107 @@ struct legacy_data {
+ 
+ };
+ 
++enum controller {
++	BIOS = 0,
++	SNOOP = 1,
++	PDC20230 = 2,
++	HT6560A = 3,
++	HT6560B = 4,
++	OPTI611A = 5,
++	OPTI46X = 6,
++	QDI6500 = 7,
++	QDI6580 = 8,
++	QDI6580DP = 9,		/* Dual channel mode is different */
++	W83759A = 10,
 +
-+struct crypto_rfc4106_ctx {
-+	struct crypto_aead *child;
-+	u8 nonce[4];
++	UNKNOWN = -1
 +};
 +
-+struct crypto_gcm_ghash_ctx {
-+	u32 bytes;
-+	u32 flags;
-+	struct gf128mul_4k *gf128;
-+	u8 buffer[16];
-+};
 +
-+struct crypto_gcm_req_priv_ctx {
-+	u8 auth_tag[16];
-+	u8 iauth_tag[16];
-+	struct scatterlist src[2];
-+	struct scatterlist dst[2];
-+	struct crypto_gcm_ghash_ctx ghash;
-+	struct ablkcipher_request abreq;
++struct legacy_probe {
++	unsigned char *name;
++	unsigned long port;
++	unsigned int irq;
++	unsigned int slot;
++	enum controller type;
++	unsigned long private;
 +};
 +
-+struct crypto_gcm_setkey_result {
-+	int err;
-+	struct completion completion;
++struct legacy_controller {
++	const char *name;
++	struct ata_port_operations *ops;
++	unsigned int pio_mask;
++	unsigned int flags;
++	int (*setup)(struct platform_device *, struct legacy_probe *probe,
++		struct legacy_data *data);
 +};
 +
-+static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_reqctx(
-+	struct aead_request *req)
-+{
-+	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
-+
-+	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
-+}
-+
-+static void crypto_gcm_ghash_init(struct crypto_gcm_ghash_ctx *ctx, u32 flags,
-+				  struct gf128mul_4k *gf128)
-+{
-+	ctx->bytes = 0;
-+	ctx->flags = flags;
-+	ctx->gf128 = gf128;
-+	memset(ctx->buffer, 0, 16);
-+}
-+
-+static void crypto_gcm_ghash_update(struct crypto_gcm_ghash_ctx *ctx,
-+				    const u8 *src, unsigned int srclen)
-+{
-+	u8 *dst = ctx->buffer;
-+
-+	if (ctx->bytes) {
-+		int n = min(srclen, ctx->bytes);
-+		u8 *pos = dst + (16 - ctx->bytes);
-+
-+		ctx->bytes -= n;
-+		srclen -= n;
-+
-+		while (n--)
-+			*pos++ ^= *src++;
-+
-+		if (!ctx->bytes)
-+			gf128mul_4k_lle((be128 *)dst, ctx->gf128);
-+	}
-+
-+	while (srclen >= 16) {
-+		crypto_xor(dst, src, 16);
-+		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
-+		src += 16;
-+		srclen -= 16;
-+	}
++static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
 +
-+	if (srclen) {
-+		ctx->bytes = 16 - srclen;
-+		while (srclen--)
-+			*dst++ ^= *src++;
-+	}
-+}
++static struct legacy_probe probe_list[NR_HOST];
+ static struct legacy_data legacy_data[NR_HOST];
+ static struct ata_host *legacy_host[NR_HOST];
+ static int nr_legacy_host;
+ 
+ 
+-static int probe_all;			/* Set to check all ISA port ranges */
+-static int ht6560a;			/* HT 6560A on primary 1, secondary 2, both 3 */
+-static int ht6560b;			/* HT 6560A on primary 1, secondary 2, both 3 */
+-static int opti82c611a;			/* Opti82c611A on primary 1, secondary 2, both 3 */
+-static int opti82c46x;			/* Opti 82c465MV present (pri/sec autodetect) */
+-static int autospeed;			/* Chip present which snoops speed changes */
+-static int pio_mask = 0x1F;		/* PIO range for autospeed devices */
++static int probe_all;		/* Set to check all ISA port ranges */
++static int ht6560a;		/* HT 6560A on primary 1, second 2, both 3 */
++static int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */
++static int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */
++static int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */
++static int qdi;			/* Set to probe QDI controllers */
++static int winbond;		/* Set to probe Winbond controllers,
++					give I/O port if non stdanard */
++static int autospeed;		/* Chip present which snoops speed changes */
++static int pio_mask = 0x1F;	/* PIO range for autospeed devices */
+ static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
+ 
+ /**
++ *	legacy_probe_add	-	Add interface to probe list
++ *	@port: Controller port
++ *	@irq: IRQ number
++ *	@type: Controller type
++ *	@private: Controller specific info
++ *
++ *	Add an entry into the probe list for ATA controllers. This is used
++ *	to add the default ISA slots and then to build up the table
++ *	further according to other ISA/VLB/Weird device scans
++ *
++ *	An I/O port list is used to keep ordering stable and sane, as we
++ *	don't have any good way to talk about ordering otherwise
++ */
 +
-+static void crypto_gcm_ghash_update_sg(struct crypto_gcm_ghash_ctx *ctx,
-+				       struct scatterlist *sg, int len)
++static int legacy_probe_add(unsigned long port, unsigned int irq,
++				enum controller type, unsigned long private)
 +{
-+	struct scatter_walk walk;
-+	u8 *src;
-+	int n;
-+
-+	if (!len)
-+		return;
-+
-+	scatterwalk_start(&walk, sg);
-+
-+	while (len) {
-+		n = scatterwalk_clamp(&walk, len);
++	struct legacy_probe *lp = &probe_list[0];
++	int i;
++	struct legacy_probe *free = NULL;
 +
-+		if (!n) {
-+			scatterwalk_start(&walk, scatterwalk_sg_next(walk.sg));
-+			n = scatterwalk_clamp(&walk, len);
++	for (i = 0; i < NR_HOST; i++) {
++		if (lp->port == 0 && free == NULL)
++			free = lp;
++		/* Matching port, or the correct slot for ordering */
++		if (lp->port == port || legacy_port[i] == port) {
++			free = lp;
++			break;
 +		}
-+
-+		src = scatterwalk_map(&walk, 0);
-+
-+		crypto_gcm_ghash_update(ctx, src, n);
-+		len -= n;
-+
-+		scatterwalk_unmap(src, 0);
-+		scatterwalk_advance(&walk, n);
-+		scatterwalk_done(&walk, 0, len);
-+		if (len)
-+			crypto_yield(ctx->flags);
++		lp++;
 +	}
-+}
-+
-+static void crypto_gcm_ghash_flush(struct crypto_gcm_ghash_ctx *ctx)
-+{
-+	u8 *dst = ctx->buffer;
-+
-+	if (ctx->bytes) {
-+		u8 *tmp = dst + (16 - ctx->bytes);
-+
-+		while (ctx->bytes--)
-+			*tmp++ ^= 0;
-+
-+		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
++	if (free == NULL) {
++		printk(KERN_ERR "pata_legacy: Too many interfaces.\n");
++		return -1;
 +	}
-+
-+	ctx->bytes = 0;
-+}
-+
-+static void crypto_gcm_ghash_final_xor(struct crypto_gcm_ghash_ctx *ctx,
-+				       unsigned int authlen,
-+				       unsigned int cryptlen, u8 *dst)
-+{
-+	u8 *buf = ctx->buffer;
-+	u128 lengths;
-+
-+	lengths.a = cpu_to_be64(authlen * 8);
-+	lengths.b = cpu_to_be64(cryptlen * 8);
-+
-+	crypto_gcm_ghash_flush(ctx);
-+	crypto_xor(buf, (u8 *)&lengths, 16);
-+	gf128mul_4k_lle((be128 *)buf, ctx->gf128);
-+	crypto_xor(dst, buf, 16);
++	/* Fill in the entry for later probing */
++	free->port = port;
++	free->irq = irq;
++	free->type = type;
++	free->private = private;
++	return 0;
 +}
 +
-+static void crypto_gcm_setkey_done(struct crypto_async_request *req, int err)
-+{
-+	struct crypto_gcm_setkey_result *result = req->data;
-+
-+	if (err == -EINPROGRESS)
-+		return;
 +
-+	result->err = err;
-+	complete(&result->completion);
-+}
++/**
+  *	legacy_set_mode		-	mode setting
+  *	@link: IDE link
+  *	@unused: Device that failed when error is returned
+@@ -113,7 +196,8 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
+ 
+ 	ata_link_for_each_dev(dev, link) {
+ 		if (ata_dev_enabled(dev)) {
+-			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
++			ata_dev_printk(dev, KERN_INFO,
++						"configured for PIO\n");
+ 			dev->pio_mode = XFER_PIO_0;
+ 			dev->xfer_mode = XFER_PIO_0;
+ 			dev->xfer_shift = ATA_SHIFT_PIO;
+@@ -171,7 +255,7 @@ static struct ata_port_operations simple_port_ops = {
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
+ static struct ata_port_operations legacy_port_ops = {
+@@ -198,15 +282,16 @@ static struct ata_port_operations legacy_port_ops = {
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+  *	Promise 20230C and 20620 support
+  *
+- *	This controller supports PIO0 to PIO2. We set PIO timings conservatively to
+- *	allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to
+- *	controller and PIO'd to the host and not supported.
++ *	This controller supports PIO0 to PIO2. We set PIO timings
++ *	conservatively to allow for 50MHz Vesa Local Bus. The 20620 DMA
++ *	support is weird being DMA to controller and PIO'd to the host
++ *	and not supported.
+  */
+ 
+ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -221,8 +306,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 	local_irq_save(flags);
+ 
+ 	/* Unlock the control interface */
+-	do
+-	{
++	do {
+ 		inb(0x1F5);
+ 		outb(inb(0x1F2) | 0x80, 0x1F2);
+ 		inb(0x1F2);
+@@ -231,7 +315,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 		inb(0x1F2);
+ 		inb(0x1F2);
+ 	}
+-	while((inb(0x1F2) & 0x80) && --tries);
++	while ((inb(0x1F2) & 0x80) && --tries);
+ 
+ 	local_irq_restore(flags);
+ 
+@@ -249,13 +333,14 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 
+ }
+ 
+-static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
++static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
++			unsigned char *buf, unsigned int buflen, int rw)
+ {
+-	struct ata_port *ap = adev->link->ap;
+-	int slop = buflen & 3;
+-	unsigned long flags;
++	if (ata_id_has_dword_io(dev->id)) {
++		struct ata_port *ap = dev->link->ap;
++		int slop = buflen & 3;
++		unsigned long flags;
+ 
+-	if (ata_id_has_dword_io(adev->id)) {
+ 		local_irq_save(flags);
+ 
+ 		/* Perform the 32bit I/O synchronization sequence */
+@@ -264,26 +349,27 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig
+ 		ioread8(ap->ioaddr.nsect_addr);
+ 
+ 		/* Now the data */
+-
+-		if (write_data)
+-			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+-		else
++		if (rw == READ)
+ 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
++		else
++			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ 
+ 		if (unlikely(slop)) {
+-			__le32 pad = 0;
+-			if (write_data) {
+-				memcpy(&pad, buf + buflen - slop, slop);
+-				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+-			} else {
++			u32 pad;
++			if (rw == READ) {
+ 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ 				memcpy(buf + buflen - slop, &pad, slop);
++			} else {
++				memcpy(&pad, buf + buflen - slop, slop);
++				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ 			}
++			buflen += 4 - slop;
+ 		}
+ 		local_irq_restore(flags);
+-	}
+-	else
+-		ata_data_xfer_noirq(adev, buf, buflen, write_data);
++	} else
++		buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
 +
-+static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
-+			     unsigned int keylen)
++	return buflen;
+ }
+ 
+ static struct ata_port_operations pdc20230_port_ops = {
+@@ -310,14 +396,14 @@ static struct ata_port_operations pdc20230_port_ops = {
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+  *	Holtek 6560A support
+  *
+- *	This controller supports PIO0 to PIO2 (no IORDY even though higher timings
+- *	can be loaded).
++ *	This controller supports PIO0 to PIO2 (no IORDY even though higher
++ *	timings can be loaded).
+  */
+ 
+ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
+@@ -364,14 +450,14 @@ static struct ata_port_operations ht6560a_port_ops = {
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+  *	Holtek 6560B support
+  *
+- *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting
+- *	unless we see an ATAPI device in which case we force it off.
++ *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO
++ *	setting unless we see an ATAPI device in which case we force it off.
+  *
+  *	FIXME: need to implement 2nd channel support.
+  */
+@@ -398,7 +484,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ 	if (adev->class != ATA_DEV_ATA) {
+ 		u8 rconf = inb(0x3E6);
+ 		if (rconf & 0x24) {
+-			rconf &= ~ 0x24;
++			rconf &= ~0x24;
+ 			outb(rconf, 0x3E6);
+ 		}
+ 	}
+@@ -423,13 +509,13 @@ static struct ata_port_operations ht6560b_port_ops = {
+ 	.qc_prep 	= ata_qc_prep,
+ 	.qc_issue	= ata_qc_issue_prot,
+ 
+-	.data_xfer	= ata_data_xfer,	/* FIXME: Check 32bit and noirq */
++	.data_xfer	= ata_data_xfer,    /* FIXME: Check 32bit and noirq */
+ 
+ 	.irq_handler	= ata_interrupt,
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -462,7 +548,8 @@ static u8 opti_syscfg(u8 reg)
+  *	This controller supports PIO0 to PIO3.
+  */
+ 
+-static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev)
++static void opti82c611a_set_piomode(struct ata_port *ap,
++						struct ata_device *adev)
+ {
+ 	u8 active, recover, setup;
+ 	struct ata_timing t;
+@@ -549,7 +636,7 @@ static struct ata_port_operations opti82c611a_port_ops = {
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
+ /*
+@@ -681,77 +768,398 @@ static struct ata_port_operations opti82c46x_port_ops = {
+ 	.irq_clear	= ata_bmdma_irq_clear,
+ 	.irq_on		= ata_irq_on,
+ 
+-	.port_start	= ata_port_start,
++	.port_start	= ata_sff_port_start,
+ };
+ 
++static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
 +{
-+	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_ablkcipher *ctr = ctx->ctr;
-+	struct {
-+		be128 hash;
-+		u8 iv[8];
-+
-+		struct crypto_gcm_setkey_result result;
-+
-+		struct scatterlist sg[1];
-+		struct ablkcipher_request req;
-+	} *data;
-+	int err;
-+
-+	crypto_ablkcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
-+	crypto_ablkcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
-+				   CRYPTO_TFM_REQ_MASK);
-+
-+	err = crypto_ablkcipher_setkey(ctr, key, keylen);
-+	if (err)
-+		return err;
-+
-+	crypto_aead_set_flags(aead, crypto_ablkcipher_get_flags(ctr) &
-+				       CRYPTO_TFM_RES_MASK);
-+
-+	data = kzalloc(sizeof(*data) + crypto_ablkcipher_reqsize(ctr),
-+		       GFP_KERNEL);
-+	if (!data)
-+		return -ENOMEM;
++	struct ata_timing t;
++	struct legacy_data *qdi = ap->host->private_data;
++	int active, recovery;
++	u8 timing;
 +
-+	init_completion(&data->result.completion);
-+	sg_init_one(data->sg, &data->hash, sizeof(data->hash));
-+	ablkcipher_request_set_tfm(&data->req, ctr);
-+	ablkcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
-+						    CRYPTO_TFM_REQ_MAY_BACKLOG,
-+					crypto_gcm_setkey_done,
-+					&data->result);
-+	ablkcipher_request_set_crypt(&data->req, data->sg, data->sg,
-+				     sizeof(data->hash), data->iv);
++	/* Get the timing data in cycles */
++	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 +
-+	err = crypto_ablkcipher_encrypt(&data->req);
-+	if (err == -EINPROGRESS || err == -EBUSY) {
-+		err = wait_for_completion_interruptible(
-+			&data->result.completion);
-+		if (!err)
-+			err = data->result.err;
++	if (qdi->fast) {
++		active = 8 - FIT(t.active, 1, 8);
++		recovery = 18 - FIT(t.recover, 3, 18);
++	} else {
++		active = 9 - FIT(t.active, 2, 9);
++		recovery = 15 - FIT(t.recover, 0, 15);
 +	}
++	timing = (recovery << 4) | active | 0x08;
 +
-+	if (err)
-+		goto out;
-+
-+	if (ctx->gf128 != NULL)
-+		gf128mul_free_4k(ctx->gf128);
-+
-+	ctx->gf128 = gf128mul_init_4k_lle(&data->hash);
-+
-+	if (ctx->gf128 == NULL)
-+		err = -ENOMEM;
-+
-+out:
-+	kfree(data);
-+	return err;
-+}
-+
-+static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
-+				  unsigned int authsize)
-+{
-+	switch (authsize) {
-+	case 4:
-+	case 8:
-+	case 12:
-+	case 13:
-+	case 14:
-+	case 15:
-+	case 16:
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
++	qdi->clock[adev->devno] = timing;
 +
-+	return 0;
++	outb(timing, qdi->timing);
 +}
+ 
+ /**
+- *	legacy_init_one		-	attach a legacy interface
+- *	@port: port number
+- *	@io: I/O port start
+- *	@ctrl: control port
++ *	qdi6580dp_set_piomode		-	PIO setup for dual channel
++ *	@ap: Port
++ *	@adev: Device
+  *	@irq: interrupt line
+  *
+- *	Register an ISA bus IDE interface. Such interfaces are PIO and we
+- *	assume do not support IRQ sharing.
++ *	In dual channel mode the 6580 has one clock per channel and we have
++ *	to software clockswitch in qc_issue_prot.
+  */
+ 
+-static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq)
++static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ {
+-	struct legacy_data *ld = &legacy_data[nr_legacy_host];
+-	struct ata_host *host;
+-	struct ata_port *ap;
+-	struct platform_device *pdev;
+-	struct ata_port_operations *ops = &legacy_port_ops;
+-	void __iomem *io_addr, *ctrl_addr;
+-	int pio_modes = pio_mask;
+-	u32 mask = (1 << port);
+-	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
+-	int ret;
++	struct ata_timing t;
++	struct legacy_data *qdi = ap->host->private_data;
++	int active, recovery;
++	u8 timing;
+ 
+-	pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
+-	if (IS_ERR(pdev))
+-		return PTR_ERR(pdev);
++	/* Get the timing data in cycles */
++	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 +
-+static void crypto_gcm_init_crypt(struct ablkcipher_request *ablk_req,
-+				  struct aead_request *req,
-+				  unsigned int cryptlen)
-+{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
-+	u32 flags = req->base.tfm->crt_flags;
-+	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
-+	struct scatterlist *dst;
-+	__be32 counter = cpu_to_be32(1);
-+
-+	memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag));
-+	memcpy(req->iv + 12, &counter, 4);
-+
-+	sg_init_table(pctx->src, 2);
-+	sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
-+	scatterwalk_sg_chain(pctx->src, 2, req->src);
-+
-+	dst = pctx->src;
-+	if (req->src != req->dst) {
-+		sg_init_table(pctx->dst, 2);
-+		sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
-+		scatterwalk_sg_chain(pctx->dst, 2, req->dst);
-+		dst = pctx->dst;
++	if (qdi->fast) {
++		active = 8 - FIT(t.active, 1, 8);
++		recovery = 18 - FIT(t.recover, 3, 18);
++	} else {
++		active = 9 - FIT(t.active, 2, 9);
++		recovery = 15 - FIT(t.recover, 0, 15);
 +	}
-+
-+	ablkcipher_request_set_tfm(ablk_req, ctx->ctr);
-+	ablkcipher_request_set_crypt(ablk_req, pctx->src, dst,
-+				     cryptlen + sizeof(pctx->auth_tag),
-+				     req->iv);
-+
-+	crypto_gcm_ghash_init(ghash, flags, ctx->gf128);
-+
-+	crypto_gcm_ghash_update_sg(ghash, req->assoc, req->assoclen);
-+	crypto_gcm_ghash_flush(ghash);
-+}
-+
-+static int crypto_gcm_hash(struct aead_request *req)
-+{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
-+	u8 *auth_tag = pctx->auth_tag;
-+	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
-+
-+	crypto_gcm_ghash_update_sg(ghash, req->dst, req->cryptlen);
-+	crypto_gcm_ghash_final_xor(ghash, req->assoclen, req->cryptlen,
-+				   auth_tag);
-+
-+	scatterwalk_map_and_copy(auth_tag, req->dst, req->cryptlen,
-+				 crypto_aead_authsize(aead), 1);
-+	return 0;
-+}
-+
-+static void crypto_gcm_encrypt_done(struct crypto_async_request *areq, int err)
-+{
-+	struct aead_request *req = areq->data;
-+
-+	if (!err)
-+		err = crypto_gcm_hash(req);
-+
-+	aead_request_complete(req, err);
++	timing = (recovery << 4) | active | 0x08;
+ 
+-	ret = -EBUSY;
+-	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
+-	    devm_request_region(&pdev->dev, ctrl, 1, "pata_legacy") == NULL)
+-		goto fail;
++	qdi->clock[adev->devno] = timing;
+ 
+-	ret = -ENOMEM;
+-	io_addr = devm_ioport_map(&pdev->dev, io, 8);
+-	ctrl_addr = devm_ioport_map(&pdev->dev, ctrl, 1);
+-	if (!io_addr || !ctrl_addr)
+-		goto fail;
++	outb(timing, qdi->timing + 2 * ap->port_no);
++	/* Clear the FIFO */
++	if (adev->class != ATA_DEV_ATA)
++		outb(0x5F, qdi->timing + 3);
 +}
+ 
+-	if (ht6560a & mask) {
+-		ops = &ht6560a_port_ops;
+-		pio_modes = 0x07;
+-		iordy = ATA_FLAG_NO_IORDY;
+-	}
+-	if (ht6560b & mask) {
+-		ops = &ht6560b_port_ops;
+-		pio_modes = 0x1F;
+-	}
+-	if (opti82c611a & mask) {
+-		ops = &opti82c611a_port_ops;
+-		pio_modes = 0x0F;
++/**
++ *	qdi6580_set_piomode		-	PIO setup for single channel
++ *	@ap: Port
++ *	@adev: Device
++ *
++ *	In single channel mode the 6580 has one clock per device and we can
++ *	avoid the requirement to clock switch. We also have to load the timing
++ *	into the right clock according to whether we are master or slave.
++ */
 +
-+static int crypto_gcm_encrypt(struct aead_request *req)
++static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
 +{
-+	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
-+	struct ablkcipher_request *abreq = &pctx->abreq;
-+	int err;
-+
-+	crypto_gcm_init_crypt(abreq, req, req->cryptlen);
-+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-+					crypto_gcm_encrypt_done, req);
++	struct ata_timing t;
++	struct legacy_data *qdi = ap->host->private_data;
++	int active, recovery;
++	u8 timing;
 +
-+	err = crypto_ablkcipher_encrypt(abreq);
-+	if (err)
-+		return err;
++	/* Get the timing data in cycles */
++	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 +
-+	return crypto_gcm_hash(req);
++	if (qdi->fast) {
++		active = 8 - FIT(t.active, 1, 8);
++		recovery = 18 - FIT(t.recover, 3, 18);
++	} else {
++		active = 9 - FIT(t.active, 2, 9);
++		recovery = 15 - FIT(t.recover, 0, 15);
+ 	}
+-	if (opti82c46x & mask) {
+-		ops = &opti82c46x_port_ops;
+-		pio_modes = 0x0F;
++	timing = (recovery << 4) | active | 0x08;
++	qdi->clock[adev->devno] = timing;
++	outb(timing, qdi->timing + 2 * adev->devno);
++	/* Clear the FIFO */
++	if (adev->class != ATA_DEV_ATA)
++		outb(0x5F, qdi->timing + 3);
 +}
 +
-+static int crypto_gcm_verify(struct aead_request *req)
-+{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
-+	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
-+	u8 *auth_tag = pctx->auth_tag;
-+	u8 *iauth_tag = pctx->iauth_tag;
-+	unsigned int authsize = crypto_aead_authsize(aead);
-+	unsigned int cryptlen = req->cryptlen - authsize;
-+
-+	crypto_gcm_ghash_final_xor(ghash, req->assoclen, cryptlen, auth_tag);
-+
-+	authsize = crypto_aead_authsize(aead);
-+	scatterwalk_map_and_copy(iauth_tag, req->src, cryptlen, authsize, 0);
-+	return memcmp(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
-+}
++/**
++ *	qdi_qc_issue_prot	-	command issue
++ *	@qc: command pending
++ *
++ *	Called when the libata layer is about to issue a command. We wrap
++ *	this interface so that we can load the correct ATA timings.
++ */
 +
-+static void crypto_gcm_decrypt_done(struct crypto_async_request *areq, int err)
++static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
 +{
-+	struct aead_request *req = areq->data;
-+
-+	if (!err)
-+		err = crypto_gcm_verify(req);
++	struct ata_port *ap = qc->ap;
++	struct ata_device *adev = qc->dev;
++	struct legacy_data *qdi = ap->host->private_data;
 +
-+	aead_request_complete(req, err);
++	if (qdi->clock[adev->devno] != qdi->last) {
++		if (adev->pio_mode) {
++			qdi->last = qdi->clock[adev->devno];
++			outb(qdi->clock[adev->devno], qdi->timing +
++							2 * ap->port_no);
++		}
+ 	}
++	return ata_qc_issue_prot(qc);
 +}
-+
-+static int crypto_gcm_decrypt(struct aead_request *req)
+ 
+-	/* Probe for automatically detectable controllers */
++static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
++					unsigned int buflen, int rw)
 +{
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
-+	struct ablkcipher_request *abreq = &pctx->abreq;
-+	struct crypto_gcm_ghash_ctx *ghash = &pctx->ghash;
-+	unsigned int cryptlen = req->cryptlen;
-+	unsigned int authsize = crypto_aead_authsize(aead);
-+	int err;
-+
-+	if (cryptlen < authsize)
-+		return -EINVAL;
-+	cryptlen -= authsize;
-+
-+	crypto_gcm_init_crypt(abreq, req, cryptlen);
-+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
-+					crypto_gcm_decrypt_done, req);
-+
-+	crypto_gcm_ghash_update_sg(ghash, req->src, cryptlen);
-+
-+	err = crypto_ablkcipher_decrypt(abreq);
-+	if (err)
-+		return err;
-+
-+	return crypto_gcm_verify(req);
++	struct ata_port *ap = adev->link->ap;
++	int slop = buflen & 3;
+ 
+-	if (io == 0x1F0 && ops == &legacy_port_ops) {
+-		unsigned long flags;
++	if (ata_id_has_dword_io(adev->id)) {
++		if (rw == WRITE)
++			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
++		else
++			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ 
+-		local_irq_save(flags);
++		if (unlikely(slop)) {
++			u32 pad;
++			if (rw == WRITE) {
++				memcpy(&pad, buf + buflen - slop, slop);
++				pad = le32_to_cpu(pad);
++				iowrite32(pad, ap->ioaddr.data_addr);
++			} else {
++				pad = ioread32(ap->ioaddr.data_addr);
++				pad = cpu_to_le32(pad);
++				memcpy(buf + buflen - slop, &pad, slop);
++			}
++		}
++		return (buflen + 3) & ~3;
++	} else
++		return ata_data_xfer(adev, buf, buflen, rw);
 +}
 +
-+static int crypto_gcm_init_tfm(struct crypto_tfm *tfm)
++static int qdi_port(struct platform_device *dev,
++			struct legacy_probe *lp, struct legacy_data *ld)
 +{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct gcm_instance_ctx *ictx = crypto_instance_ctx(inst);
-+	struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_ablkcipher *ctr;
-+	unsigned long align;
-+	int err;
-+
-+	ctr = crypto_spawn_skcipher(&ictx->ctr);
-+	err = PTR_ERR(ctr);
-+	if (IS_ERR(ctr))
-+		return err;
-+
-+	ctx->ctr = ctr;
-+	ctx->gf128 = NULL;
-+
-+	align = crypto_tfm_alg_alignmask(tfm);
-+	align &= ~(crypto_tfm_ctx_alignment() - 1);
-+	tfm->crt_aead.reqsize = align +
-+				sizeof(struct crypto_gcm_req_priv_ctx) +
-+				crypto_ablkcipher_reqsize(ctr);
-+
++	if (devm_request_region(&dev->dev, lp->private, 4, "qdi") == NULL)
++		return -EBUSY;
++	ld->timing = lp->private;
 +	return 0;
 +}
 +
-+static void crypto_gcm_exit_tfm(struct crypto_tfm *tfm)
-+{
-+	struct crypto_gcm_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	if (ctx->gf128 != NULL)
-+		gf128mul_free_4k(ctx->gf128);
-+
-+	crypto_free_ablkcipher(ctx->ctr);
-+}
-+
-+static struct crypto_instance *crypto_gcm_alloc_common(struct rtattr **tb,
-+						       const char *full_name,
-+						       const char *ctr_name)
-+{
-+	struct crypto_attr_type *algt;
-+	struct crypto_instance *inst;
-+	struct crypto_alg *ctr;
-+	struct gcm_instance_ctx *ctx;
-+	int err;
++static struct ata_port_operations qdi6500_port_ops = {
++	.set_piomode	= qdi6500_set_piomode,
 +
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
-+		return ERR_PTR(err);
++	.tf_load	= ata_tf_load,
++	.tf_read	= ata_tf_read,
++	.check_status 	= ata_check_status,
++	.exec_command	= ata_exec_command,
++	.dev_select 	= ata_std_dev_select,
 +
-+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-+		return ERR_PTR(-EINVAL);
++	.freeze		= ata_bmdma_freeze,
++	.thaw		= ata_bmdma_thaw,
++	.error_handler	= ata_bmdma_error_handler,
++	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.cable_detect	= ata_cable_40wire,
 +
-+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
-+	if (!inst)
-+		return ERR_PTR(-ENOMEM);
++	.qc_prep 	= ata_qc_prep,
++	.qc_issue	= qdi_qc_issue_prot,
 +
-+	ctx = crypto_instance_ctx(inst);
-+	crypto_set_skcipher_spawn(&ctx->ctr, inst);
-+	err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0,
-+				   crypto_requires_sync(algt->type,
-+							algt->mask));
-+	if (err)
-+		goto err_free_inst;
++	.data_xfer	= vlb32_data_xfer,
 +
-+	ctr = crypto_skcipher_spawn_alg(&ctx->ctr);
++	.irq_handler	= ata_interrupt,
++	.irq_clear	= ata_bmdma_irq_clear,
++	.irq_on		= ata_irq_on,
 +
-+	/* We only support 16-byte blocks. */
-+	if (ctr->cra_ablkcipher.ivsize != 16)
-+		goto out_put_ctr;
++	.port_start	= ata_sff_port_start,
++};
 +
-+	/* Not a stream cipher? */
-+	err = -EINVAL;
-+	if (ctr->cra_blocksize != 1)
-+		goto out_put_ctr;
++static struct ata_port_operations qdi6580_port_ops = {
++	.set_piomode	= qdi6580_set_piomode,
 +
-+	err = -ENAMETOOLONG;
-+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+		     "gcm_base(%s)", ctr->cra_driver_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		goto out_put_ctr;
++	.tf_load	= ata_tf_load,
++	.tf_read	= ata_tf_read,
++	.check_status 	= ata_check_status,
++	.exec_command	= ata_exec_command,
++	.dev_select 	= ata_std_dev_select,
 +
-+	memcpy(inst->alg.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
++	.freeze		= ata_bmdma_freeze,
++	.thaw		= ata_bmdma_thaw,
++	.error_handler	= ata_bmdma_error_handler,
++	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.cable_detect	= ata_cable_40wire,
 +
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-+	inst->alg.cra_flags |= ctr->cra_flags & CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_priority = ctr->cra_priority;
-+	inst->alg.cra_blocksize = 1;
-+	inst->alg.cra_alignmask = ctr->cra_alignmask | (__alignof__(u64) - 1);
-+	inst->alg.cra_type = &crypto_aead_type;
-+	inst->alg.cra_aead.ivsize = 16;
-+	inst->alg.cra_aead.maxauthsize = 16;
-+	inst->alg.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
-+	inst->alg.cra_init = crypto_gcm_init_tfm;
-+	inst->alg.cra_exit = crypto_gcm_exit_tfm;
-+	inst->alg.cra_aead.setkey = crypto_gcm_setkey;
-+	inst->alg.cra_aead.setauthsize = crypto_gcm_setauthsize;
-+	inst->alg.cra_aead.encrypt = crypto_gcm_encrypt;
-+	inst->alg.cra_aead.decrypt = crypto_gcm_decrypt;
++	.qc_prep 	= ata_qc_prep,
++	.qc_issue	= ata_qc_issue_prot,
 +
-+out:
-+	return inst;
++	.data_xfer	= vlb32_data_xfer,
 +
-+out_put_ctr:
-+	crypto_drop_skcipher(&ctx->ctr);
-+err_free_inst:
-+	kfree(inst);
-+	inst = ERR_PTR(err);
-+	goto out;
-+}
++	.irq_handler	= ata_interrupt,
++	.irq_clear	= ata_bmdma_irq_clear,
++	.irq_on		= ata_irq_on,
 +
-+static struct crypto_instance *crypto_gcm_alloc(struct rtattr **tb)
-+{
-+	int err;
-+	const char *cipher_name;
-+	char ctr_name[CRYPTO_MAX_ALG_NAME];
-+	char full_name[CRYPTO_MAX_ALG_NAME];
++	.port_start	= ata_sff_port_start,
++};
 +
-+	cipher_name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(cipher_name);
-+	if (IS_ERR(cipher_name))
-+		return ERR_PTR(err);
++static struct ata_port_operations qdi6580dp_port_ops = {
++	.set_piomode	= qdi6580dp_set_piomode,
 +
-+	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		return ERR_PTR(-ENAMETOOLONG);
++	.tf_load	= ata_tf_load,
++	.tf_read	= ata_tf_read,
++	.check_status 	= ata_check_status,
++	.exec_command	= ata_exec_command,
++	.dev_select 	= ata_std_dev_select,
 +
-+	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm(%s)", cipher_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		return ERR_PTR(-ENAMETOOLONG);
++	.freeze		= ata_bmdma_freeze,
++	.thaw		= ata_bmdma_thaw,
++	.error_handler	= ata_bmdma_error_handler,
++	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.cable_detect	= ata_cable_40wire,
 +
-+	return crypto_gcm_alloc_common(tb, full_name, ctr_name);
-+}
++	.qc_prep 	= ata_qc_prep,
++	.qc_issue	= qdi_qc_issue_prot,
 +
-+static void crypto_gcm_free(struct crypto_instance *inst)
-+{
-+	struct gcm_instance_ctx *ctx = crypto_instance_ctx(inst);
++	.data_xfer	= vlb32_data_xfer,
 +
-+	crypto_drop_skcipher(&ctx->ctr);
-+	kfree(inst);
-+}
++	.irq_handler	= ata_interrupt,
++	.irq_clear	= ata_bmdma_irq_clear,
++	.irq_on		= ata_irq_on,
 +
-+static struct crypto_template crypto_gcm_tmpl = {
-+	.name = "gcm",
-+	.alloc = crypto_gcm_alloc,
-+	.free = crypto_gcm_free,
-+	.module = THIS_MODULE,
++	.port_start	= ata_sff_port_start,
 +};
 +
-+static struct crypto_instance *crypto_gcm_base_alloc(struct rtattr **tb)
-+{
-+	int err;
-+	const char *ctr_name;
-+	char full_name[CRYPTO_MAX_ALG_NAME];
-+
-+	ctr_name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(ctr_name);
-+	if (IS_ERR(ctr_name))
-+		return ERR_PTR(err);
-+
-+	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s)",
-+		     ctr_name) >= CRYPTO_MAX_ALG_NAME)
-+		return ERR_PTR(-ENAMETOOLONG);
-+
-+	return crypto_gcm_alloc_common(tb, full_name, ctr_name);
-+}
-+
-+static struct crypto_template crypto_gcm_base_tmpl = {
-+	.name = "gcm_base",
-+	.alloc = crypto_gcm_base_alloc,
-+	.free = crypto_gcm_free,
-+	.module = THIS_MODULE,
-+};
++static DEFINE_SPINLOCK(winbond_lock);
 +
-+static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key,
-+				 unsigned int keylen)
++static void winbond_writecfg(unsigned long port, u8 reg, u8 val)
 +{
-+	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
-+	struct crypto_aead *child = ctx->child;
-+	int err;
-+
-+	if (keylen < 4)
-+		return -EINVAL;
-+
-+	keylen -= 4;
-+	memcpy(ctx->nonce, key + keylen, 4);
-+
-+	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
-+	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
-+				     CRYPTO_TFM_REQ_MASK);
-+	err = crypto_aead_setkey(child, key, keylen);
-+	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
-+				      CRYPTO_TFM_RES_MASK);
-+
-+	return err;
++	unsigned long flags;
++	spin_lock_irqsave(&winbond_lock, flags);
++	outb(reg, port + 0x01);
++	outb(val, port + 0x02);
++	spin_unlock_irqrestore(&winbond_lock, flags);
 +}
 +
-+static int crypto_rfc4106_setauthsize(struct crypto_aead *parent,
-+				      unsigned int authsize)
++static u8 winbond_readcfg(unsigned long port, u8 reg)
 +{
-+	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
++	u8 val;
 +
-+	switch (authsize) {
-+	case 8:
-+	case 12:
-+	case 16:
-+		break;
-+	default:
-+		return -EINVAL;
-+	}
++	unsigned long flags;
++	spin_lock_irqsave(&winbond_lock, flags);
++	outb(reg, port + 0x01);
++	val = inb(port + 0x02);
++	spin_unlock_irqrestore(&winbond_lock, flags);
 +
-+	return crypto_aead_setauthsize(ctx->child, authsize);
++	return val;
 +}
 +
-+static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
++static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
 +{
-+	struct aead_request *subreq = aead_request_ctx(req);
-+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
-+	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
-+	struct crypto_aead *child = ctx->child;
-+	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
-+			   crypto_aead_alignmask(child) + 1);
-+
-+	memcpy(iv, ctx->nonce, 4);
-+	memcpy(iv + 4, req->iv, 8);
-+
-+	aead_request_set_tfm(subreq, child);
-+	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
-+				  req->base.data);
-+	aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen, iv);
-+	aead_request_set_assoc(subreq, req->assoc, req->assoclen);
++	struct ata_timing t;
++	struct legacy_data *winbond = ap->host->private_data;
++	int active, recovery;
++	u8 reg;
++	int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
 +
-+	return subreq;
-+}
++	reg = winbond_readcfg(winbond->timing, 0x81);
 +
-+static int crypto_rfc4106_encrypt(struct aead_request *req)
-+{
-+	req = crypto_rfc4106_crypt(req);
++	/* Get the timing data in cycles */
++	if (reg & 0x40)		/* Fast VLB bus, assume 50MHz */
++		ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
++	else
++		ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
 +
-+	return crypto_aead_encrypt(req);
-+}
++	active = (FIT(t.active, 3, 17) - 1) & 0x0F;
++	recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
++	timing = (active << 4) | recovery;
++	winbond_writecfg(winbond->timing, timing, reg);
 +
-+static int crypto_rfc4106_decrypt(struct aead_request *req)
-+{
-+	req = crypto_rfc4106_crypt(req);
++	/* Load the setup timing */
 +
-+	return crypto_aead_decrypt(req);
++	reg = 0x35;
++	if (adev->class != ATA_DEV_ATA)
++		reg |= 0x08;	/* FIFO off */
++	if (!ata_pio_need_iordy(adev))
++		reg |= 0x02;	/* IORDY off */
++	reg |= (FIT(t.setup, 0, 3) << 6);
++	winbond_writecfg(winbond->timing, timing + 1, reg);
 +}
 +
-+static int crypto_rfc4106_init_tfm(struct crypto_tfm *tfm)
++static int winbond_port(struct platform_device *dev,
++			struct legacy_probe *lp, struct legacy_data *ld)
 +{
-+	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-+	struct crypto_aead_spawn *spawn = crypto_instance_ctx(inst);
-+	struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
-+	struct crypto_aead *aead;
-+	unsigned long align;
-+
-+	aead = crypto_spawn_aead(spawn);
-+	if (IS_ERR(aead))
-+		return PTR_ERR(aead);
-+
-+	ctx->child = aead;
-+
-+	align = crypto_aead_alignmask(aead);
-+	align &= ~(crypto_tfm_ctx_alignment() - 1);
-+	tfm->crt_aead.reqsize = sizeof(struct aead_request) +
-+				ALIGN(crypto_aead_reqsize(aead),
-+				      crypto_tfm_ctx_alignment()) +
-+				align + 16;
-+
++	if (devm_request_region(&dev->dev, lp->private, 4, "winbond") == NULL)
++		return -EBUSY;
++	ld->timing = lp->private;
 +	return 0;
 +}
 +
-+static void crypto_rfc4106_exit_tfm(struct crypto_tfm *tfm)
-+{
-+	struct crypto_rfc4106_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	crypto_free_aead(ctx->child);
-+}
-+
-+static struct crypto_instance *crypto_rfc4106_alloc(struct rtattr **tb)
-+{
-+	struct crypto_attr_type *algt;
-+	struct crypto_instance *inst;
-+	struct crypto_aead_spawn *spawn;
-+	struct crypto_alg *alg;
-+	const char *ccm_name;
-+	int err;
-+
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
-+		return ERR_PTR(err);
-+
-+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
-+		return ERR_PTR(-EINVAL);
-+
-+	ccm_name = crypto_attr_alg_name(tb[1]);
-+	err = PTR_ERR(ccm_name);
-+	if (IS_ERR(ccm_name))
-+		return ERR_PTR(err);
-+
-+	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
-+	if (!inst)
-+		return ERR_PTR(-ENOMEM);
-+
-+	spawn = crypto_instance_ctx(inst);
-+	crypto_set_aead_spawn(spawn, inst);
-+	err = crypto_grab_aead(spawn, ccm_name, 0,
-+			       crypto_requires_sync(algt->type, algt->mask));
-+	if (err)
-+		goto out_free_inst;
-+
-+	alg = crypto_aead_spawn_alg(spawn);
-+
-+	err = -EINVAL;
-+
-+	/* We only support 16-byte blocks. */
-+	if (alg->cra_aead.ivsize != 16)
-+		goto out_drop_alg;
-+
-+	/* Not a stream cipher? */
-+	if (alg->cra_blocksize != 1)
-+		goto out_drop_alg;
-+
-+	err = -ENAMETOOLONG;
-+	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
-+		     "rfc4106(%s)", alg->cra_name) >= CRYPTO_MAX_ALG_NAME ||
-+	    snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
-+		     "rfc4106(%s)", alg->cra_driver_name) >=
-+	    CRYPTO_MAX_ALG_NAME)
-+		goto out_drop_alg;
-+
-+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
-+	inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
-+	inst->alg.cra_priority = alg->cra_priority;
-+	inst->alg.cra_blocksize = 1;
-+	inst->alg.cra_alignmask = alg->cra_alignmask;
-+	inst->alg.cra_type = &crypto_nivaead_type;
-+
-+	inst->alg.cra_aead.ivsize = 8;
-+	inst->alg.cra_aead.maxauthsize = 16;
-+
-+	inst->alg.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx);
-+
-+	inst->alg.cra_init = crypto_rfc4106_init_tfm;
-+	inst->alg.cra_exit = crypto_rfc4106_exit_tfm;
-+
-+	inst->alg.cra_aead.setkey = crypto_rfc4106_setkey;
-+	inst->alg.cra_aead.setauthsize = crypto_rfc4106_setauthsize;
-+	inst->alg.cra_aead.encrypt = crypto_rfc4106_encrypt;
-+	inst->alg.cra_aead.decrypt = crypto_rfc4106_decrypt;
++static struct ata_port_operations winbond_port_ops = {
++	.set_piomode	= winbond_set_piomode,
 +
-+	inst->alg.cra_aead.geniv = "seqiv";
++	.tf_load	= ata_tf_load,
++	.tf_read	= ata_tf_read,
++	.check_status 	= ata_check_status,
++	.exec_command	= ata_exec_command,
++	.dev_select 	= ata_std_dev_select,
 +
-+out:
-+	return inst;
++	.freeze		= ata_bmdma_freeze,
++	.thaw		= ata_bmdma_thaw,
++	.error_handler	= ata_bmdma_error_handler,
++	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.cable_detect	= ata_cable_40wire,
 +
-+out_drop_alg:
-+	crypto_drop_aead(spawn);
-+out_free_inst:
-+	kfree(inst);
-+	inst = ERR_PTR(err);
-+	goto out;
-+}
++	.qc_prep 	= ata_qc_prep,
++	.qc_issue	= ata_qc_issue_prot,
 +
-+static void crypto_rfc4106_free(struct crypto_instance *inst)
-+{
-+	crypto_drop_spawn(crypto_instance_ctx(inst));
-+	kfree(inst);
-+}
++	.data_xfer	= vlb32_data_xfer,
 +
-+static struct crypto_template crypto_rfc4106_tmpl = {
-+	.name = "rfc4106",
-+	.alloc = crypto_rfc4106_alloc,
-+	.free = crypto_rfc4106_free,
-+	.module = THIS_MODULE,
++	.irq_clear	= ata_bmdma_irq_clear,
++	.irq_on		= ata_irq_on,
+ 
++	.port_start	= ata_sff_port_start,
 +};
 +
-+static int __init crypto_gcm_module_init(void)
-+{
-+	int err;
-+
-+	err = crypto_register_template(&crypto_gcm_base_tmpl);
-+	if (err)
-+		goto out;
-+
-+	err = crypto_register_template(&crypto_gcm_tmpl);
-+	if (err)
-+		goto out_undo_base;
-+
-+	err = crypto_register_template(&crypto_rfc4106_tmpl);
-+	if (err)
-+		goto out_undo_gcm;
-+
-+out:
-+	return err;
-+
-+out_undo_gcm:
-+	crypto_unregister_template(&crypto_gcm_tmpl);
-+out_undo_base:
-+	crypto_unregister_template(&crypto_gcm_base_tmpl);
-+	goto out;
-+}
-+
-+static void __exit crypto_gcm_module_exit(void)
-+{
-+	crypto_unregister_template(&crypto_rfc4106_tmpl);
-+	crypto_unregister_template(&crypto_gcm_tmpl);
-+	crypto_unregister_template(&crypto_gcm_base_tmpl);
-+}
-+
-+module_init(crypto_gcm_module_init);
-+module_exit(crypto_gcm_module_exit);
++static struct legacy_controller controllers[] = {
++	{"BIOS",	&legacy_port_ops, 	0x1F,
++						ATA_FLAG_NO_IORDY,	NULL },
++	{"Snooping", 	&simple_port_ops, 	0x1F,
++						0	       ,	NULL },
++	{"PDC20230",	&pdc20230_port_ops,	0x7,
++						ATA_FLAG_NO_IORDY,	NULL },
++	{"HT6560A",	&ht6560a_port_ops,	0x07,
++						ATA_FLAG_NO_IORDY,	NULL },
++	{"HT6560B",	&ht6560b_port_ops,	0x1F,
++						ATA_FLAG_NO_IORDY,	NULL },
++	{"OPTI82C611A",	&opti82c611a_port_ops,	0x0F,
++						0	       ,	NULL },
++	{"OPTI82C46X",	&opti82c46x_port_ops,	0x0F,
++						0	       ,	NULL },
++	{"QDI6500",	&qdi6500_port_ops,	0x07,
++					ATA_FLAG_NO_IORDY,	qdi_port },
++	{"QDI6580",	&qdi6580_port_ops,	0x1F,
++					0	       ,	qdi_port },
++	{"QDI6580DP",	&qdi6580dp_port_ops,	0x1F,
++					0	       ,	qdi_port },
++	{"W83759A",	&winbond_port_ops,	0x1F,
++					0	       ,	winbond_port }
++};
 +
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Galois/Counter Mode");
-+MODULE_AUTHOR("Mikko Herranen <mh1 at iki.fi>");
-+MODULE_ALIAS("gcm_base");
-+MODULE_ALIAS("rfc4106");
-diff --git a/crypto/hmac.c b/crypto/hmac.c
-index 0f05be7..a1d016a 100644
---- a/crypto/hmac.c
-+++ b/crypto/hmac.c
-@@ -17,6 +17,7 @@
-  */
- 
- #include <crypto/algapi.h>
-+#include <crypto/scatterwalk.h>
- #include <linux/err.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
-@@ -160,7 +161,7 @@ static int hmac_digest(struct hash_desc *pdesc, struct scatterlist *sg,
- 
- 	sg_init_table(sg1, 2);
- 	sg_set_buf(sg1, ipad, bs);
--	sg_set_page(&sg1[1], (void *) sg, 0, 0);
-+	scatterwalk_sg_chain(sg1, 2, sg);
- 
- 	sg_init_table(sg2, 1);
- 	sg_set_buf(sg2, opad, bs + ds);
-diff --git a/crypto/internal.h b/crypto/internal.h
-index abb01f7..32f4c21 100644
---- a/crypto/internal.h
-+++ b/crypto/internal.h
-@@ -25,7 +25,6 @@
- #include <linux/notifier.h>
- #include <linux/rwsem.h>
- #include <linux/slab.h>
--#include <asm/kmap_types.h>
- 
- /* Crypto notification events. */
- enum {
-@@ -50,34 +49,6 @@ extern struct list_head crypto_alg_list;
- extern struct rw_semaphore crypto_alg_sem;
- extern struct blocking_notifier_head crypto_chain;
- 
--static inline enum km_type crypto_kmap_type(int out)
--{
--	enum km_type type;
--
--	if (in_softirq())
--		type = out * (KM_SOFTIRQ1 - KM_SOFTIRQ0) + KM_SOFTIRQ0;
--	else
--		type = out * (KM_USER1 - KM_USER0) + KM_USER0;
--
--	return type;
--}
--
--static inline void *crypto_kmap(struct page *page, int out)
--{
--	return kmap_atomic(page, crypto_kmap_type(out));
--}
--
--static inline void crypto_kunmap(void *vaddr, int out)
--{
--	kunmap_atomic(vaddr, crypto_kmap_type(out));
--}
--
--static inline void crypto_yield(u32 flags)
--{
--	if (flags & CRYPTO_TFM_REQ_MAY_SLEEP)
--		cond_resched();
--}
--
- #ifdef CONFIG_PROC_FS
- void __init crypto_init_proc(void);
- void __exit crypto_exit_proc(void);
-@@ -122,6 +93,8 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm);
- void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
- void crypto_exit_compress_ops(struct crypto_tfm *tfm);
- 
-+void crypto_larval_kill(struct crypto_alg *alg);
-+struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
- void crypto_larval_error(const char *name, u32 type, u32 mask);
- 
- void crypto_shoot_alg(struct crypto_alg *alg);
-diff --git a/crypto/lzo.c b/crypto/lzo.c
-new file mode 100644
-index 0000000..48c3288
---- /dev/null
-+++ b/crypto/lzo.c
-@@ -0,0 +1,106 @@
-+/*
-+ * Cryptographic API.
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published by
-+ * the Free Software Foundation.
-+ *
-+ * This program is distributed in the hope that it will be useful, but WITHOUT
-+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-+ * more details.
-+ *
-+ * You should have received a copy of the GNU General Public License along with
-+ * this program; if not, write to the Free Software Foundation, Inc., 51
-+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++/**
++ *	probe_chip_type		-	Discover controller
++ *	@probe: Probe entry to check
 + *
++ *	Probe an ATA port and identify the type of controller. We don't
++ *	check if the controller appears to be driveless at this point.
 + */
 +
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/crypto.h>
-+#include <linux/vmalloc.h>
-+#include <linux/lzo.h>
-+
-+struct lzo_ctx {
-+	void *lzo_comp_mem;
-+};
-+
-+static int lzo_init(struct crypto_tfm *tfm)
-+{
-+	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS);
-+	if (!ctx->lzo_comp_mem)
-+		return -ENOMEM;
-+
-+	return 0;
-+}
-+
-+static void lzo_exit(struct crypto_tfm *tfm)
-+{
-+	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+	vfree(ctx->lzo_comp_mem);
-+}
-+
-+static int lzo_compress(struct crypto_tfm *tfm, const u8 *src,
-+			    unsigned int slen, u8 *dst, unsigned int *dlen)
-+{
-+	struct lzo_ctx *ctx = crypto_tfm_ctx(tfm);
-+	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
-+	int err;
-+
-+	err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem);
-+
-+	if (err != LZO_E_OK)
-+		return -EINVAL;
-+
-+	*dlen = tmp_len;
-+	return 0;
-+}
-+
-+static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src,
-+			      unsigned int slen, u8 *dst, unsigned int *dlen)
++static __init int probe_chip_type(struct legacy_probe *probe)
 +{
-+	int err;
-+	size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */
-+
-+	err = lzo1x_decompress_safe(src, slen, dst, &tmp_len);
++	int mask = 1 << probe->slot;
 +
-+	if (err != LZO_E_OK)
-+		return -EINVAL;
++	if (winbond && (probe->port == 0x1F0 || probe->port == 0x170)) {
++		u8 reg = winbond_readcfg(winbond, 0x81);
++		reg |= 0x80;	/* jumpered mode off */
++		winbond_writecfg(winbond, 0x81, reg);
++		reg = winbond_readcfg(winbond, 0x83);
++		reg |= 0xF0;	/* local control */
++		winbond_writecfg(winbond, 0x83, reg);
++		reg = winbond_readcfg(winbond, 0x85);
++		reg |= 0xF0;	/* programmable timing */
++		winbond_writecfg(winbond, 0x85, reg);
 +
-+	*dlen = tmp_len;
-+	return 0;
++		reg = winbond_readcfg(winbond, 0x81);
 +
++		if (reg & mask)
++			return W83759A;
++	}
++	if (probe->port == 0x1F0) {
++		unsigned long flags;
++		local_irq_save(flags);
+ 		/* Probes */
+-		inb(0x1F5);
+ 		outb(inb(0x1F2) | 0x80, 0x1F2);
++		inb(0x1F5);
+ 		inb(0x1F2);
+ 		inb(0x3F6);
+ 		inb(0x3F6);
+@@ -760,29 +1168,83 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
+ 
+ 		if ((inb(0x1F2) & 0x80) == 0) {
+ 			/* PDC20230c or 20630 ? */
+-			printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
+-				pio_modes = 0x07;
+-			ops = &pdc20230_port_ops;
+-			iordy = ATA_FLAG_NO_IORDY;
++			printk(KERN_INFO  "PDC20230-C/20630 VLB ATA controller"
++							" detected.\n");
+ 			udelay(100);
+ 			inb(0x1F5);
++			local_irq_restore(flags);
++			return PDC20230;
+ 		} else {
+ 			outb(0x55, 0x1F2);
+ 			inb(0x1F2);
+ 			inb(0x1F2);
+-			if (inb(0x1F2) == 0x00) {
+-				printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n");
+-			}
++			if (inb(0x1F2) == 0x00)
++				printk(KERN_INFO "PDC20230-B VLB ATA "
++						     "controller detected.\n");
++			local_irq_restore(flags);
++			return BIOS;
+ 		}
+ 		local_irq_restore(flags);
+ 	}
+ 
++	if (ht6560a & mask)
++		return HT6560A;
++	if (ht6560b & mask)
++		return HT6560B;
++	if (opti82c611a & mask)
++		return OPTI611A;
++	if (opti82c46x & mask)
++		return OPTI46X;
++	if (autospeed & mask)
++		return SNOOP;
++	return BIOS;
 +}
 +
-+static struct crypto_alg alg = {
-+	.cra_name		= "lzo",
-+	.cra_flags		= CRYPTO_ALG_TYPE_COMPRESS,
-+	.cra_ctxsize		= sizeof(struct lzo_ctx),
-+	.cra_module		= THIS_MODULE,
-+	.cra_list		= LIST_HEAD_INIT(alg.cra_list),
-+	.cra_init		= lzo_init,
-+	.cra_exit		= lzo_exit,
-+	.cra_u			= { .compress = {
-+	.coa_compress 		= lzo_compress,
-+	.coa_decompress  	= lzo_decompress } }
-+};
 +
-+static int __init init(void)
-+{
-+	return crypto_register_alg(&alg);
-+}
++/**
++ *	legacy_init_one		-	attach a legacy interface
++ *	@pl: probe record
++ *
++ *	Register an ISA bus IDE interface. Such interfaces are PIO and we
++ *	assume do not support IRQ sharing.
++ */
 +
-+static void __exit fini(void)
++static __init int legacy_init_one(struct legacy_probe *probe)
 +{
-+	crypto_unregister_alg(&alg);
-+}
++	struct legacy_controller *controller = &controllers[probe->type];
++	int pio_modes = controller->pio_mask;
++	unsigned long io = probe->port;
++	u32 mask = (1 << probe->slot);
++	struct ata_port_operations *ops = controller->ops;
++	struct legacy_data *ld = &legacy_data[probe->slot];
++	struct ata_host *host = NULL;
++	struct ata_port *ap;
++	struct platform_device *pdev;
++	struct ata_device *dev;
++	void __iomem *io_addr, *ctrl_addr;
++	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
++	int ret;
+ 
+-	/* Chip does mode setting by command snooping */
+-	if (ops == &legacy_port_ops && (autospeed & mask))
+-		ops = &simple_port_ops;
++	iordy |= controller->flags;
 +
-+module_init(init);
-+module_exit(fini);
++	pdev = platform_device_register_simple(DRV_NAME, probe->slot, NULL, 0);
++	if (IS_ERR(pdev))
++		return PTR_ERR(pdev);
 +
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("LZO Compression Algorithm");
-diff --git a/crypto/pcbc.c b/crypto/pcbc.c
-index c3ed8a1..fe70477 100644
---- a/crypto/pcbc.c
-+++ b/crypto/pcbc.c
-@@ -24,7 +24,6 @@
- 
- struct crypto_pcbc_ctx {
- 	struct crypto_cipher *child;
--	void (*xor)(u8 *dst, const u8 *src, unsigned int bs);
- };
- 
- static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
-@@ -45,9 +44,7 @@ static int crypto_pcbc_setkey(struct crypto_tfm *parent, const u8 *key,
- 
- static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
- 				       struct blkcipher_walk *walk,
--				       struct crypto_cipher *tfm,
--				       void (*xor)(u8 *, const u8 *,
--						   unsigned int))
-+				       struct crypto_cipher *tfm)
- {
- 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
- 		crypto_cipher_alg(tfm)->cia_encrypt;
-@@ -58,10 +55,10 @@ static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
- 	u8 *iv = walk->iv;
- 
- 	do {
--		xor(iv, src, bsize);
-+		crypto_xor(iv, src, bsize);
- 		fn(crypto_cipher_tfm(tfm), dst, iv);
- 		memcpy(iv, dst, bsize);
--		xor(iv, src, bsize);
-+		crypto_xor(iv, src, bsize);
- 
- 		src += bsize;
- 		dst += bsize;
-@@ -72,9 +69,7 @@ static int crypto_pcbc_encrypt_segment(struct blkcipher_desc *desc,
- 
- static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
- 				       struct blkcipher_walk *walk,
--				       struct crypto_cipher *tfm,
--				       void (*xor)(u8 *, const u8 *,
--						   unsigned int))
-+				       struct crypto_cipher *tfm)
- {
- 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
- 		crypto_cipher_alg(tfm)->cia_encrypt;
-@@ -86,10 +81,10 @@ static int crypto_pcbc_encrypt_inplace(struct blkcipher_desc *desc,
- 
- 	do {
- 		memcpy(tmpbuf, src, bsize);
--		xor(iv, tmpbuf, bsize);
-+		crypto_xor(iv, src, bsize);
- 		fn(crypto_cipher_tfm(tfm), src, iv);
--		memcpy(iv, src, bsize);
--		xor(iv, tmpbuf, bsize);
-+		memcpy(iv, tmpbuf, bsize);
-+		crypto_xor(iv, src, bsize);
- 
- 		src += bsize;
- 	} while ((nbytes -= bsize) >= bsize);
-@@ -107,7 +102,6 @@ static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
- 	struct crypto_blkcipher *tfm = desc->tfm;
- 	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
- 	struct crypto_cipher *child = ctx->child;
--	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
- 	int err;
- 
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
-@@ -115,11 +109,11 @@ static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
- 
- 	while ((nbytes = walk.nbytes)) {
- 		if (walk.src.virt.addr == walk.dst.virt.addr)
--			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk, child,
--							     xor);
-+			nbytes = crypto_pcbc_encrypt_inplace(desc, &walk,
-+							     child);
- 		else
--			nbytes = crypto_pcbc_encrypt_segment(desc, &walk, child,
--							     xor);
-+			nbytes = crypto_pcbc_encrypt_segment(desc, &walk,
-+							     child);
- 		err = blkcipher_walk_done(desc, &walk, nbytes);
- 	}
- 
-@@ -128,9 +122,7 @@ static int crypto_pcbc_encrypt(struct blkcipher_desc *desc,
- 
- static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
- 				       struct blkcipher_walk *walk,
--				       struct crypto_cipher *tfm,
--				       void (*xor)(u8 *, const u8 *,
--						   unsigned int))
-+				       struct crypto_cipher *tfm)
- {
- 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
- 		crypto_cipher_alg(tfm)->cia_decrypt;
-@@ -142,9 +134,9 @@ static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
- 
- 	do {
- 		fn(crypto_cipher_tfm(tfm), dst, src);
--		xor(dst, iv, bsize);
-+		crypto_xor(dst, iv, bsize);
- 		memcpy(iv, src, bsize);
--		xor(iv, dst, bsize);
-+		crypto_xor(iv, dst, bsize);
- 
- 		src += bsize;
- 		dst += bsize;
-@@ -157,9 +149,7 @@ static int crypto_pcbc_decrypt_segment(struct blkcipher_desc *desc,
- 
- static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
- 				       struct blkcipher_walk *walk,
--				       struct crypto_cipher *tfm,
--				       void (*xor)(u8 *, const u8 *,
--						   unsigned int))
-+				       struct crypto_cipher *tfm)
- {
- 	void (*fn)(struct crypto_tfm *, u8 *, const u8 *) =
- 		crypto_cipher_alg(tfm)->cia_decrypt;
-@@ -172,9 +162,9 @@ static int crypto_pcbc_decrypt_inplace(struct blkcipher_desc *desc,
- 	do {
- 		memcpy(tmpbuf, src, bsize);
- 		fn(crypto_cipher_tfm(tfm), src, src);
--		xor(src, iv, bsize);
-+		crypto_xor(src, iv, bsize);
- 		memcpy(iv, tmpbuf, bsize);
--		xor(iv, src, bsize);
-+		crypto_xor(iv, src, bsize);
- 
- 		src += bsize;
- 	} while ((nbytes -= bsize) >= bsize);
-@@ -192,7 +182,6 @@ static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
- 	struct crypto_blkcipher *tfm = desc->tfm;
- 	struct crypto_pcbc_ctx *ctx = crypto_blkcipher_ctx(tfm);
- 	struct crypto_cipher *child = ctx->child;
--	void (*xor)(u8 *, const u8 *, unsigned int bs) = ctx->xor;
- 	int err;
- 
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
-@@ -200,48 +189,17 @@ static int crypto_pcbc_decrypt(struct blkcipher_desc *desc,
- 
- 	while ((nbytes = walk.nbytes)) {
- 		if (walk.src.virt.addr == walk.dst.virt.addr)
--			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk, child,
--							     xor);
-+			nbytes = crypto_pcbc_decrypt_inplace(desc, &walk,
-+							     child);
- 		else
--			nbytes = crypto_pcbc_decrypt_segment(desc, &walk, child,
--							     xor);
-+			nbytes = crypto_pcbc_decrypt_segment(desc, &walk,
-+							     child);
- 		err = blkcipher_walk_done(desc, &walk, nbytes);
- 	}
++	ret = -EBUSY;
++	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
++	    devm_request_region(&pdev->dev, io + 0x0206, 1,
++							"pata_legacy") == NULL)
++		goto fail;
  
- 	return err;
- }
+ 	ret = -ENOMEM;
++	io_addr = devm_ioport_map(&pdev->dev, io, 8);
++	ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
++	if (!io_addr || !ctrl_addr)
++		goto fail;
++	if (controller->setup)
++		if (controller->setup(pdev, probe, ld) < 0)
++			goto fail;
+ 	host = ata_host_alloc(&pdev->dev, 1);
+ 	if (!host)
+ 		goto fail;
+@@ -795,19 +1257,29 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
+ 	ap->ioaddr.altstatus_addr = ctrl_addr;
+ 	ap->ioaddr.ctl_addr = ctrl_addr;
+ 	ata_std_ports(&ap->ioaddr);
+-	ap->private_data = ld;
++	ap->host->private_data = ld;
  
--static void xor_byte(u8 *a, const u8 *b, unsigned int bs)
--{
--	do {
--		*a++ ^= *b++;
--	} while (--bs);
--}
--
--static void xor_quad(u8 *dst, const u8 *src, unsigned int bs)
--{
--	u32 *a = (u32 *)dst;
--	u32 *b = (u32 *)src;
--
--	do {
--		*a++ ^= *b++;
--	} while ((bs -= 4));
--}
--
--static void xor_64(u8 *a, const u8 *b, unsigned int bs)
--{
--	((u32 *)a)[0] ^= ((u32 *)b)[0];
--	((u32 *)a)[1] ^= ((u32 *)b)[1];
--}
--
--static void xor_128(u8 *a, const u8 *b, unsigned int bs)
--{
--	((u32 *)a)[0] ^= ((u32 *)b)[0];
--	((u32 *)a)[1] ^= ((u32 *)b)[1];
--	((u32 *)a)[2] ^= ((u32 *)b)[2];
--	((u32 *)a)[3] ^= ((u32 *)b)[3];
--}
--
- static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
- {
- 	struct crypto_instance *inst = (void *)tfm->__crt_alg;
-@@ -249,22 +207,6 @@ static int crypto_pcbc_init_tfm(struct crypto_tfm *tfm)
- 	struct crypto_pcbc_ctx *ctx = crypto_tfm_ctx(tfm);
- 	struct crypto_cipher *cipher;
+-	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, ctrl);
++	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
  
--	switch (crypto_tfm_alg_blocksize(tfm)) {
--	case 8:
--		ctx->xor = xor_64;
--		break;
--
--	case 16:
--		ctx->xor = xor_128;
--		break;
--
--	default:
--		if (crypto_tfm_alg_blocksize(tfm) % 4)
--			ctx->xor = xor_byte;
--		else
--			ctx->xor = xor_quad;
--	}
+-	ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht);
++	ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
++								&legacy_sht);
+ 	if (ret)
+ 		goto fail;
 -
- 	cipher = crypto_spawn_cipher(spawn);
- 	if (IS_ERR(cipher))
- 		return PTR_ERR(cipher);
-@@ -304,8 +246,9 @@ static struct crypto_instance *crypto_pcbc_alloc(struct rtattr **tb)
- 	inst->alg.cra_alignmask = alg->cra_alignmask;
- 	inst->alg.cra_type = &crypto_blkcipher_type;
+-	legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
+ 	ld->platform_dev = pdev;
+-	return 0;
  
--	if (!(alg->cra_blocksize % 4))
--		inst->alg.cra_alignmask |= 3;
-+	/* We access the data as u32s when xoring. */
-+	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
-+
- 	inst->alg.cra_blkcipher.ivsize = alg->cra_blocksize;
- 	inst->alg.cra_blkcipher.min_keysize = alg->cra_cipher.cia_min_keysize;
- 	inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize;
-diff --git a/crypto/salsa20_generic.c b/crypto/salsa20_generic.c
-new file mode 100644
-index 0000000..1fa4e4d
---- /dev/null
-+++ b/crypto/salsa20_generic.c
-@@ -0,0 +1,255 @@
-+/*
-+ * Salsa20: Salsa20 stream cipher algorithm
-+ *
-+ * Copyright (c) 2007 Tan Swee Heng <thesweeheng at gmail.com>
-+ *
-+ * Derived from:
-+ * - salsa20.c: Public domain C code by Daniel J. Bernstein <djb at cr.yp.to>
-+ *
-+ * Salsa20 is a stream cipher candidate in eSTREAM, the ECRYPT Stream
-+ * Cipher Project. It is designed by Daniel J. Bernstein <djb at cr.yp.to>.
-+ * More information about eSTREAM and Salsa20 can be found here:
-+ *   http://www.ecrypt.eu.org/stream/
-+ *   http://cr.yp.to/snuffle.html
-+ *
-+ * 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/init.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/crypto.h>
-+#include <linux/types.h>
-+#include <crypto/algapi.h>
-+#include <asm/byteorder.h>
-+
-+#define SALSA20_IV_SIZE        8U
-+#define SALSA20_MIN_KEY_SIZE  16U
-+#define SALSA20_MAX_KEY_SIZE  32U
-+
-+/*
-+ * Start of code taken from D. J. Bernstein's reference implementation.
-+ * With some modifications and optimizations made to suit our needs.
-+ */
-+
-+/*
-+salsa20-ref.c version 20051118
-+D. J. Bernstein
-+Public domain.
-+*/
-+
-+#define ROTATE(v,n) (((v) << (n)) | ((v) >> (32 - (n))))
-+#define XOR(v,w) ((v) ^ (w))
-+#define PLUS(v,w) (((v) + (w)))
-+#define PLUSONE(v) (PLUS((v),1))
-+#define U32TO8_LITTLE(p, v) \
-+	{ (p)[0] = (v >>  0) & 0xff; (p)[1] = (v >>  8) & 0xff; \
-+	  (p)[2] = (v >> 16) & 0xff; (p)[3] = (v >> 24) & 0xff; }
-+#define U8TO32_LITTLE(p)   \
-+	(((u32)((p)[0])      ) | ((u32)((p)[1]) <<  8) | \
-+	 ((u32)((p)[2]) << 16) | ((u32)((p)[3]) << 24)   )
-+
-+struct salsa20_ctx
-+{
-+	u32 input[16];
-+};
-+
-+static void salsa20_wordtobyte(u8 output[64], const u32 input[16])
-+{
-+	u32 x[16];
-+	int i;
-+
-+	memcpy(x, input, sizeof(x));
-+	for (i = 20; i > 0; i -= 2) {
-+		x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 0],x[12]), 7));
-+		x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[ 4],x[ 0]), 9));
-+		x[12] = XOR(x[12],ROTATE(PLUS(x[ 8],x[ 4]),13));
-+		x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[12],x[ 8]),18));
-+		x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 5],x[ 1]), 7));
-+		x[13] = XOR(x[13],ROTATE(PLUS(x[ 9],x[ 5]), 9));
-+		x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[13],x[ 9]),13));
-+		x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 1],x[13]),18));
-+		x[14] = XOR(x[14],ROTATE(PLUS(x[10],x[ 6]), 7));
-+		x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[14],x[10]), 9));
-+		x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 2],x[14]),13));
-+		x[10] = XOR(x[10],ROTATE(PLUS(x[ 6],x[ 2]),18));
-+		x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[15],x[11]), 7));
-+		x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 3],x[15]), 9));
-+		x[11] = XOR(x[11],ROTATE(PLUS(x[ 7],x[ 3]),13));
-+		x[15] = XOR(x[15],ROTATE(PLUS(x[11],x[ 7]),18));
-+		x[ 1] = XOR(x[ 1],ROTATE(PLUS(x[ 0],x[ 3]), 7));
-+		x[ 2] = XOR(x[ 2],ROTATE(PLUS(x[ 1],x[ 0]), 9));
-+		x[ 3] = XOR(x[ 3],ROTATE(PLUS(x[ 2],x[ 1]),13));
-+		x[ 0] = XOR(x[ 0],ROTATE(PLUS(x[ 3],x[ 2]),18));
-+		x[ 6] = XOR(x[ 6],ROTATE(PLUS(x[ 5],x[ 4]), 7));
-+		x[ 7] = XOR(x[ 7],ROTATE(PLUS(x[ 6],x[ 5]), 9));
-+		x[ 4] = XOR(x[ 4],ROTATE(PLUS(x[ 7],x[ 6]),13));
-+		x[ 5] = XOR(x[ 5],ROTATE(PLUS(x[ 4],x[ 7]),18));
-+		x[11] = XOR(x[11],ROTATE(PLUS(x[10],x[ 9]), 7));
-+		x[ 8] = XOR(x[ 8],ROTATE(PLUS(x[11],x[10]), 9));
-+		x[ 9] = XOR(x[ 9],ROTATE(PLUS(x[ 8],x[11]),13));
-+		x[10] = XOR(x[10],ROTATE(PLUS(x[ 9],x[ 8]),18));
-+		x[12] = XOR(x[12],ROTATE(PLUS(x[15],x[14]), 7));
-+		x[13] = XOR(x[13],ROTATE(PLUS(x[12],x[15]), 9));
-+		x[14] = XOR(x[14],ROTATE(PLUS(x[13],x[12]),13));
-+		x[15] = XOR(x[15],ROTATE(PLUS(x[14],x[13]),18));
-+	}
-+	for (i = 0; i < 16; ++i)
-+		x[i] = PLUS(x[i],input[i]);
-+	for (i = 0; i < 16; ++i)
-+		U32TO8_LITTLE(output + 4 * i,x[i]);
-+}
-+
-+static const char sigma[16] = "expand 32-byte k";
-+static const char tau[16] = "expand 16-byte k";
-+
-+static void salsa20_keysetup(struct salsa20_ctx *ctx, const u8 *k, u32 kbytes)
-+{
-+	const char *constants;
++	/* Nothing found means we drop the port as its probably not there */
 +
-+	ctx->input[1] = U8TO32_LITTLE(k + 0);
-+	ctx->input[2] = U8TO32_LITTLE(k + 4);
-+	ctx->input[3] = U8TO32_LITTLE(k + 8);
-+	ctx->input[4] = U8TO32_LITTLE(k + 12);
-+	if (kbytes == 32) { /* recommended */
-+		k += 16;
-+		constants = sigma;
-+	} else { /* kbytes == 16 */
-+		constants = tau;
++	ret = -ENODEV;
++	ata_link_for_each_dev(dev, &ap->link) {
++		if (!ata_dev_absent(dev)) {
++			legacy_host[probe->slot] = host;
++			ld->platform_dev = pdev;
++			return 0;
++		}
 +	}
-+	ctx->input[11] = U8TO32_LITTLE(k + 0);
-+	ctx->input[12] = U8TO32_LITTLE(k + 4);
-+	ctx->input[13] = U8TO32_LITTLE(k + 8);
-+	ctx->input[14] = U8TO32_LITTLE(k + 12);
-+	ctx->input[0] = U8TO32_LITTLE(constants + 0);
-+	ctx->input[5] = U8TO32_LITTLE(constants + 4);
-+	ctx->input[10] = U8TO32_LITTLE(constants + 8);
-+	ctx->input[15] = U8TO32_LITTLE(constants + 12);
-+}
-+
-+static void salsa20_ivsetup(struct salsa20_ctx *ctx, const u8 *iv)
+ fail:
++	if (host)
++		ata_host_detach(host);
+ 	platform_device_unregister(pdev);
+ 	return ret;
+ }
+@@ -818,13 +1290,15 @@ fail:
+  *	@master: set this if we find an ATA master
+  *	@master: set this if we find an ATA secondary
+  *
+- *	A small number of vendors implemented early PCI ATA interfaces on bridge logic
+- *	without the ATA interface being PCI visible. Where we have a matching PCI driver
+- *	we must skip the relevant device here. If we don't know about it then the legacy
+- *	driver is the right driver anyway.
++ *	A small number of vendors implemented early PCI ATA interfaces
++ *	on bridge logic without the ATA interface being PCI visible.
++ *	Where we have a matching PCI driver we must skip the relevant
++ *	device here. If we don't know about it then the legacy driver
++ *	is the right driver anyway.
+  */
+ 
+-static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary)
++static void __init legacy_check_special_cases(struct pci_dev *p, int *primary,
++								int *secondary)
+ {
+ 	/* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
+ 	if (p->vendor == 0x1078 && p->device == 0x0000) {
+@@ -840,7 +1314,8 @@ static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *sec
+ 	if (p->vendor == 0x8086 && p->device == 0x1234) {
+ 		u16 r;
+ 		pci_read_config_word(p, 0x6C, &r);
+-		if (r & 0x8000) {	/* ATA port enabled */
++		if (r & 0x8000) {
++			/* ATA port enabled */
+ 			if (r & 0x4000)
+ 				*secondary = 1;
+ 			else
+@@ -850,6 +1325,114 @@ static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *sec
+ 	}
+ }
+ 
++static __init void probe_opti_vlb(void)
 +{
-+	ctx->input[6] = U8TO32_LITTLE(iv + 0);
-+	ctx->input[7] = U8TO32_LITTLE(iv + 4);
-+	ctx->input[8] = 0;
-+	ctx->input[9] = 0;
++	/* If an OPTI 82C46X is present find out where the channels are */
++	static const char *optis[4] = {
++		"3/463MV", "5MV",
++		"5MVA", "5MVB"
++	};
++	u8 chans = 1;
++	u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
++
++	opti82c46x = 3;	/* Assume master and slave first */
++	printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n",
++								optis[ctrl]);
++	if (ctrl == 3)
++		chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
++	ctrl = opti_syscfg(0xAC);
++	/* Check enabled and this port is the 465MV port. On the
++	   MVB we may have two channels */
++	if (ctrl & 8) {
++		if (chans == 2) {
++			legacy_probe_add(0x1F0, 14, OPTI46X, 0);
++			legacy_probe_add(0x170, 15, OPTI46X, 0);
++		}
++		if (ctrl & 4)
++			legacy_probe_add(0x170, 15, OPTI46X, 0);
++		else
++			legacy_probe_add(0x1F0, 14, OPTI46X, 0);
++	} else
++		legacy_probe_add(0x1F0, 14, OPTI46X, 0);
 +}
 +
-+static void salsa20_encrypt_bytes(struct salsa20_ctx *ctx, u8 *dst,
-+				  const u8 *src, unsigned int bytes)
++static __init void qdi65_identify_port(u8 r, u8 res, unsigned long port)
 +{
-+	u8 buf[64];
-+
-+	if (dst != src)
-+		memcpy(dst, src, bytes);
-+
-+	while (bytes) {
-+		salsa20_wordtobyte(buf, ctx->input);
-+
-+		ctx->input[8] = PLUSONE(ctx->input[8]);
-+		if (!ctx->input[8])
-+			ctx->input[9] = PLUSONE(ctx->input[9]);
-+
-+		if (bytes <= 64) {
-+			crypto_xor(dst, buf, bytes);
++	static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
++	/* Check card type */
++	if ((r & 0xF0) == 0xC0) {
++		/* QD6500: single channel */
++		if (r & 8)
++			/* Disabled ? */
++			return;
++		legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
++								QDI6500, port);
++	}
++	if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
++		/* QD6580: dual channel */
++		if (!request_region(port + 2 , 2, "pata_qdi")) {
++			release_region(port, 2);
 +			return;
 +		}
-+
-+		crypto_xor(dst, buf, 64);
-+		bytes -= 64;
-+		dst += 64;
++		res = inb(port + 3);
++		/* Single channel mode ? */
++		if (res & 1)
++			legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
++								QDI6580, port);
++		else { /* Dual channel mode */
++			legacy_probe_add(0x1F0, 14, QDI6580DP, port);
++			/* port + 0x02, r & 0x04 */
++			legacy_probe_add(0x170, 15, QDI6580DP, port + 2);
++		}
++		release_region(port + 2, 2);
 +	}
 +}
 +
-+/*
-+ * End of code taken from D. J. Bernstein's reference implementation.
-+ */
-+
-+static int setkey(struct crypto_tfm *tfm, const u8 *key,
-+		  unsigned int keysize)
-+{
-+	struct salsa20_ctx *ctx = crypto_tfm_ctx(tfm);
-+	salsa20_keysetup(ctx, key, keysize);
-+	return 0;
-+}
-+
-+static int encrypt(struct blkcipher_desc *desc,
-+		   struct scatterlist *dst, struct scatterlist *src,
-+		   unsigned int nbytes)
++static __init void probe_qdi_vlb(void)
 +{
-+	struct blkcipher_walk walk;
-+	struct crypto_blkcipher *tfm = desc->tfm;
-+	struct salsa20_ctx *ctx = crypto_blkcipher_ctx(tfm);
-+	int err;
-+
-+	blkcipher_walk_init(&walk, dst, src, nbytes);
-+	err = blkcipher_walk_virt_block(desc, &walk, 64);
-+
-+	salsa20_ivsetup(ctx, walk.iv);
++	unsigned long flags;
++	static const unsigned long qd_port[2] = { 0x30, 0xB0 };
++	int i;
 +
-+	if (likely(walk.nbytes == nbytes))
-+	{
-+		salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
-+				      walk.src.virt.addr, nbytes);
-+		return blkcipher_walk_done(desc, &walk, 0);
-+	}
++	/*
++	 *	Check each possible QD65xx base address
++	 */
 +
-+	while (walk.nbytes >= 64) {
-+		salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
-+				      walk.src.virt.addr,
-+				      walk.nbytes - (walk.nbytes % 64));
-+		err = blkcipher_walk_done(desc, &walk, walk.nbytes % 64);
-+	}
++	for (i = 0; i < 2; i++) {
++		unsigned long port = qd_port[i];
++		u8 r, res;
 +
-+	if (walk.nbytes) {
-+		salsa20_encrypt_bytes(ctx, walk.dst.virt.addr,
-+				      walk.src.virt.addr, walk.nbytes);
-+		err = blkcipher_walk_done(desc, &walk, 0);
-+	}
 +
-+	return err;
-+}
++		if (request_region(port, 2, "pata_qdi")) {
++			/* Check for a card */
++			local_irq_save(flags);
++			/* I have no h/w that needs this delay but it
++			   is present in the historic code */
++			r = inb(port);
++			udelay(1);
++			outb(0x19, port);
++			udelay(1);
++			res = inb(port);
++			udelay(1);
++			outb(r, port);
++			udelay(1);
++			local_irq_restore(flags);
 +
-+static struct crypto_alg alg = {
-+	.cra_name           =   "salsa20",
-+	.cra_driver_name    =   "salsa20-generic",
-+	.cra_priority       =   100,
-+	.cra_flags          =   CRYPTO_ALG_TYPE_BLKCIPHER,
-+	.cra_type           =   &crypto_blkcipher_type,
-+	.cra_blocksize      =   1,
-+	.cra_ctxsize        =   sizeof(struct salsa20_ctx),
-+	.cra_alignmask      =	3,
-+	.cra_module         =   THIS_MODULE,
-+	.cra_list           =   LIST_HEAD_INIT(alg.cra_list),
-+	.cra_u              =   {
-+		.blkcipher = {
-+			.setkey         =   setkey,
-+			.encrypt        =   encrypt,
-+			.decrypt        =   encrypt,
-+			.min_keysize    =   SALSA20_MIN_KEY_SIZE,
-+			.max_keysize    =   SALSA20_MAX_KEY_SIZE,
-+			.ivsize         =   SALSA20_IV_SIZE,
++			/* Fail */
++			if (res == 0x19) {
++				release_region(port, 2);
++				continue;
++			}
++			/* Passes the presence test */
++			r = inb(port + 1);
++			udelay(1);
++			/* Check port agrees with port set */
++			if ((r & 2) >> 1 == i)
++				qdi65_identify_port(r, res, port);
++			release_region(port, 2);
 +		}
 +	}
-+};
-+
-+static int __init init(void)
-+{
-+	return crypto_register_alg(&alg);
-+}
-+
-+static void __exit fini(void)
-+{
-+	crypto_unregister_alg(&alg);
 +}
-+
-+module_init(init);
-+module_exit(fini);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION ("Salsa20 stream cipher algorithm");
-+MODULE_ALIAS("salsa20");
-diff --git a/crypto/scatterwalk.c b/crypto/scatterwalk.c
-index b9bbda0..9aeeb52 100644
---- a/crypto/scatterwalk.c
-+++ b/crypto/scatterwalk.c
-@@ -13,6 +13,8 @@
-  * any later version.
-  *
-  */
-+
-+#include <crypto/scatterwalk.h>
- #include <linux/kernel.h>
- #include <linux/mm.h>
- #include <linux/module.h>
-@@ -20,9 +22,6 @@
- #include <linux/highmem.h>
- #include <linux/scatterlist.h>
  
--#include "internal.h"
--#include "scatterwalk.h"
--
- static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
- {
- 	void *src = out ? buf : sgdata;
-@@ -106,6 +105,9 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
- 	struct scatter_walk walk;
- 	unsigned int offset = 0;
+ /**
+  *	legacy_init		-	attach legacy interfaces
+@@ -867,15 +1450,17 @@ static __init int legacy_init(void)
+ 	int ct = 0;
+ 	int primary = 0;
+ 	int secondary = 0;
+-	int last_port = NR_HOST;
++	int pci_present = 0;
++	struct legacy_probe *pl = &probe_list[0];
++	int slot = 0;
  
-+	if (!nbytes)
-+		return;
-+
- 	for (;;) {
- 		scatterwalk_start(&walk, sg);
+ 	struct pci_dev *p = NULL;
  
-@@ -113,7 +115,7 @@ void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
- 			break;
+ 	for_each_pci_dev(p) {
+ 		int r;
+-		/* Check for any overlap of the system ATA mappings. Native mode controllers
+-		   stuck on these addresses or some devices in 'raid' mode won't be found by
+-		   the storage class test */
++		/* Check for any overlap of the system ATA mappings. Native
++		   mode controllers stuck on these addresses or some devices
++		   in 'raid' mode won't be found by the storage class test */
+ 		for (r = 0; r < 6; r++) {
+ 			if (pci_resource_start(p, r) == 0x1f0)
+ 				primary = 1;
+@@ -885,49 +1470,39 @@ static __init int legacy_init(void)
+ 		/* Check for special cases */
+ 		legacy_check_special_cases(p, &primary, &secondary);
  
- 		offset += sg->length;
--		sg = sg_next(sg);
-+		sg = scatterwalk_sg_next(sg);
+-		/* If PCI bus is present then don't probe for tertiary legacy ports */
+-		if (probe_all == 0)
+-			last_port = 2;
++		/* If PCI bus is present then don't probe for tertiary
++		   legacy ports */
++		pci_present = 1;
  	}
  
- 	scatterwalk_advance(&walk, start - offset);
-diff --git a/crypto/scatterwalk.h b/crypto/scatterwalk.h
-deleted file mode 100644
-index 87ed681..0000000
---- a/crypto/scatterwalk.h
-+++ /dev/null
-@@ -1,80 +0,0 @@
--/*
-- * Cryptographic API.
-- *
-- * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
-- * Copyright (c) 2002 Adam J. Richter <adam at yggdrasil.com>
-- * Copyright (c) 2004 Jean-Luc Cooke <jlcooke at certainkey.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.
-- *
-- */
--
--#ifndef _CRYPTO_SCATTERWALK_H
--#define _CRYPTO_SCATTERWALK_H
--
--#include <linux/mm.h>
--#include <linux/scatterlist.h>
--
--#include "internal.h"
--
--static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg)
--{
--	return (++sg)->length ? sg : (void *) sg_page(sg);
--}
--
--static inline unsigned long scatterwalk_samebuf(struct scatter_walk *walk_in,
--						struct scatter_walk *walk_out)
--{
--	return !(((sg_page(walk_in->sg) - sg_page(walk_out->sg)) << PAGE_SHIFT) +
--		 (int)(walk_in->offset - walk_out->offset));
--}
--
--static inline unsigned int scatterwalk_pagelen(struct scatter_walk *walk)
--{
--	unsigned int len = walk->sg->offset + walk->sg->length - walk->offset;
--	unsigned int len_this_page = offset_in_page(~walk->offset) + 1;
--	return len_this_page > len ? len : len_this_page;
--}
--
--static inline unsigned int scatterwalk_clamp(struct scatter_walk *walk,
--					     unsigned int nbytes)
--{
--	unsigned int len_this_page = scatterwalk_pagelen(walk);
--	return nbytes > len_this_page ? len_this_page : nbytes;
--}
--
--static inline void scatterwalk_advance(struct scatter_walk *walk,
--				       unsigned int nbytes)
--{
--	walk->offset += nbytes;
--}
--
--static inline unsigned int scatterwalk_aligned(struct scatter_walk *walk,
--					       unsigned int alignmask)
--{
--	return !(walk->offset & alignmask);
--}
--
--static inline struct page *scatterwalk_page(struct scatter_walk *walk)
--{
--	return sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
--}
--
--static inline void scatterwalk_unmap(void *vaddr, int out)
--{
--	crypto_kunmap(vaddr, out);
--}
+-	/* If an OPTI 82C46X is present find out where the channels are */
+-	if (opti82c46x) {
+-		static const char *optis[4] = {
+-			"3/463MV", "5MV",
+-			"5MVA", "5MVB"
+-		};
+-		u8 chans = 1;
+-		u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
 -
--void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg);
--void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
--			    size_t nbytes, int out);
--void *scatterwalk_map(struct scatter_walk *walk, int out);
--void scatterwalk_done(struct scatter_walk *walk, int out, int more);
+-		opti82c46x = 3;	/* Assume master and slave first */
+-		printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", optis[ctrl]);
+-		if (ctrl == 3)
+-			chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
+-		ctrl = opti_syscfg(0xAC);
+-		/* Check enabled and this port is the 465MV port. On the
+-		   MVB we may have two channels */
+-		if (ctrl & 8) {
+-			if (ctrl & 4)
+-				opti82c46x = 2;	/* Slave */
+-			else
+-				opti82c46x = 1;	/* Master */
+-			if (chans == 2)
+-				opti82c46x = 3; /* Master and Slave */
+-		}	/* Slave only */
+-		else if (chans == 1)
+-			opti82c46x = 1;
++	if (winbond == 1)
++		winbond = 0x130;	/* Default port, alt is 1B0 */
++
++	if (primary == 0 || all)
++		legacy_probe_add(0x1F0, 14, UNKNOWN, 0);
++	if (secondary == 0 || all)
++		legacy_probe_add(0x170, 15, UNKNOWN, 0);
++
++	if (probe_all || !pci_present) {
++		/* ISA/VLB extra ports */
++		legacy_probe_add(0x1E8, 11, UNKNOWN, 0);
++		legacy_probe_add(0x168, 10, UNKNOWN, 0);
++		legacy_probe_add(0x1E0, 8, UNKNOWN, 0);
++		legacy_probe_add(0x160, 12, UNKNOWN, 0);
+ 	}
+ 
+-	for (i = 0; i < last_port; i++) {
+-		/* Skip primary if we have seen a PCI one */
+-		if (i == 0 && primary == 1)
+-			continue;
+-		/* Skip secondary if we have seen a PCI one */
+-		if (i == 1 && secondary == 1)
++	if (opti82c46x)
++		probe_opti_vlb();
++	if (qdi)
++		probe_qdi_vlb();
++
++	for (i = 0; i < NR_HOST; i++, pl++) {
++		if (pl->port == 0)
+ 			continue;
+-		if (legacy_init_one(i, legacy_port[i],
+-				   legacy_port[i] + 0x0206,
+-				   legacy_irq[i]) == 0)
++		if (pl->type == UNKNOWN)
++			pl->type = probe_chip_type(pl);
++		pl->slot = slot++;
++		if (legacy_init_one(pl) == 0)
+ 			ct++;
+ 	}
+ 	if (ct != 0)
+@@ -941,11 +1516,8 @@ static __exit void legacy_exit(void)
+ 
+ 	for (i = 0; i < nr_legacy_host; i++) {
+ 		struct legacy_data *ld = &legacy_data[i];
 -
--void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
--			      unsigned int start, unsigned int nbytes, int out);
+ 		ata_host_detach(legacy_host[i]);
+ 		platform_device_unregister(ld->platform_dev);
+-		if (ld->timing)
+-			release_region(ld->timing, 2);
+ 	}
+ }
+ 
+@@ -960,9 +1532,9 @@ module_param(ht6560a, int, 0);
+ module_param(ht6560b, int, 0);
+ module_param(opti82c611a, int, 0);
+ module_param(opti82c46x, int, 0);
++module_param(qdi, int, 0);
+ module_param(pio_mask, int, 0);
+ module_param(iordy_mask, int, 0);
+ 
+ module_init(legacy_init);
+ module_exit(legacy_exit);
 -
--#endif  /* _CRYPTO_SCATTERWALK_H */
-diff --git a/crypto/seqiv.c b/crypto/seqiv.c
+diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
+index 50c56e2..5413ebf 100644
+--- a/drivers/ata/pata_mpc52xx.c
++++ b/drivers/ata/pata_mpc52xx.c
+@@ -364,7 +364,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
+ {
+ 	unsigned int ipb_freq;
+ 	struct resource res_mem;
+-	int ata_irq = NO_IRQ;
++	int ata_irq;
+ 	struct mpc52xx_ata __iomem *ata_regs;
+ 	struct mpc52xx_ata_priv *priv;
+ 	int rv;
+@@ -494,10 +494,8 @@ mpc52xx_ata_resume(struct of_device *op)
+ 
+ 
+ static struct of_device_id mpc52xx_ata_of_match[] = {
+-	{
+-		.type		= "ata",
+-		.compatible	= "mpc5200-ata",
+-	},
++	{ .compatible = "fsl,mpc5200-ata", },
++	{ .compatible = "mpc5200-ata", },
+ 	{},
+ };
+ 
+diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
 new file mode 100644
-index 0000000..b903aab
+index 0000000..1c1b835
 --- /dev/null
-+++ b/crypto/seqiv.c
-@@ -0,0 +1,345 @@
++++ b/drivers/ata/pata_ninja32.c
+@@ -0,0 +1,214 @@
 +/*
-+ * seqiv: Sequence Number IV Generator
-+ *
-+ * This generator generates an IV based on a sequence number by xoring it
-+ * with a salt.  This algorithm is mainly useful for CTR and similar modes.
++ * pata_ninja32.c 	- Ninja32 PATA for new ATA layer
++ *			  (C) 2007 Red Hat Inc
++ *			  Alan Cox <alan at redhat.com>
 + *
-+ * Copyright (c) 2007 Herbert Xu <herbert at gondor.apana.org.au>
++ * Note: The controller like many controllers has shared timings for
++ * PIO and DMA. We thus flip to the DMA timings in dma_start and flip back
++ * in the dma_stop function. Thus we actually don't need a set_dmamode
++ * method as the PIO method is always called and will set the right PIO
++ * timing parameters.
 + *
-+ * 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.
++ * The Ninja32 Cardbus is not a generic SFF controller. Instead it is
++ * laid out as follows off BAR 0. This is based upon Mark Lord's delkin
++ * driver and the extensive analysis done by the BSD developers, notably
++ * ITOH Yasufumi.
 + *
++ *	Base + 0x00 IRQ Status
++ *	Base + 0x01 IRQ control
++ *	Base + 0x02 Chipset control
++ *	Base + 0x04 VDMA and reset control + wait bits
++ *	Base + 0x08 BMIMBA
++ *	Base + 0x0C DMA Length
++ *	Base + 0x10 Taskfile
++ *	Base + 0x18 BMDMA Status ?
++ *	Base + 0x1C
++ *	Base + 0x1D Bus master control
++ *		bit 0 = enable
++ *		bit 1 = 0 write/1 read
++ *		bit 2 = 1 sgtable
++ *		bit 3 = go
++ *		bit 4-6 wait bits
++ *		bit 7 = done
++ *	Base + 0x1E AltStatus
++ *	Base + 0x1F timing register
 + */
 +
-+#include <crypto/internal/aead.h>
-+#include <crypto/internal/skcipher.h>
-+#include <linux/err.h>
-+#include <linux/init.h>
 +#include <linux/kernel.h>
 +#include <linux/module.h>
-+#include <linux/random.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+
-+struct seqiv_ctx {
-+	spinlock_t lock;
-+	u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
-+};
-+
-+static void seqiv_complete2(struct skcipher_givcrypt_request *req, int err)
-+{
-+	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
-+	struct crypto_ablkcipher *geniv;
-+
-+	if (err == -EINPROGRESS)
-+		return;
-+
-+	if (err)
-+		goto out;
-+
-+	geniv = skcipher_givcrypt_reqtfm(req);
-+	memcpy(req->creq.info, subreq->info, crypto_ablkcipher_ivsize(geniv));
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/blkdev.h>
++#include <linux/delay.h>
++#include <scsi/scsi_host.h>
++#include <linux/libata.h>
 +
-+out:
-+	kfree(subreq->info);
-+}
++#define DRV_NAME "pata_ninja32"
++#define DRV_VERSION "0.0.1"
 +
-+static void seqiv_complete(struct crypto_async_request *base, int err)
-+{
-+	struct skcipher_givcrypt_request *req = base->data;
 +
-+	seqiv_complete2(req, err);
-+	skcipher_givcrypt_complete(req, err);
-+}
++/**
++ *	ninja32_set_piomode	-	set initial PIO mode data
++ *	@ap: ATA interface
++ *	@adev: ATA device
++ *
++ *	Called to do the PIO mode setup. Our timing registers are shared
++ *	but we want to set the PIO timing by default.
++ */
 +
-+static void seqiv_aead_complete2(struct aead_givcrypt_request *req, int err)
++static void ninja32_set_piomode(struct ata_port *ap, struct ata_device *adev)
 +{
-+	struct aead_request *subreq = aead_givcrypt_reqctx(req);
-+	struct crypto_aead *geniv;
-+
-+	if (err == -EINPROGRESS)
-+		return;
-+
-+	if (err)
-+		goto out;
-+
-+	geniv = aead_givcrypt_reqtfm(req);
-+	memcpy(req->areq.iv, subreq->iv, crypto_aead_ivsize(geniv));
-+
-+out:
-+	kfree(subreq->iv);
++	static u16 pio_timing[5] = {
++		0xd6, 0x85, 0x44, 0x33, 0x13
++	};
++	iowrite8(pio_timing[adev->pio_mode - XFER_PIO_0],
++		 ap->ioaddr.bmdma_addr + 0x1f);
++	ap->private_data = adev;
 +}
 +
-+static void seqiv_aead_complete(struct crypto_async_request *base, int err)
-+{
-+	struct aead_givcrypt_request *req = base->data;
-+
-+	seqiv_aead_complete2(req, err);
-+	aead_givcrypt_complete(req, err);
-+}
 +
-+static void seqiv_geniv(struct seqiv_ctx *ctx, u8 *info, u64 seq,
-+			unsigned int ivsize)
++static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
 +{
-+	unsigned int len = ivsize;
-+
-+	if (ivsize > sizeof(u64)) {
-+		memset(info, 0, ivsize - sizeof(u64));
-+		len = sizeof(u64);
++	struct ata_device *adev = &ap->link.device[device];
++	if (ap->private_data != adev) {
++		iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
++		ata_std_dev_select(ap, device);
++		ninja32_set_piomode(ap, adev);
 +	}
-+	seq = cpu_to_be64(seq);
-+	memcpy(info + ivsize - len, &seq, len);
-+	crypto_xor(info, ctx->salt, ivsize);
 +}
 +
-+static int seqiv_givencrypt(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+	struct ablkcipher_request *subreq = skcipher_givcrypt_reqctx(req);
-+	crypto_completion_t complete;
-+	void *data;
-+	u8 *info;
-+	unsigned int ivsize;
-+	int err;
++static struct scsi_host_template ninja32_sht = {
++	.module			= THIS_MODULE,
++	.name			= DRV_NAME,
++	.ioctl			= ata_scsi_ioctl,
++	.queuecommand		= ata_scsi_queuecmd,
++	.can_queue		= ATA_DEF_QUEUE,
++	.this_id		= ATA_SHT_THIS_ID,
++	.sg_tablesize		= LIBATA_MAX_PRD,
++	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
++	.emulated		= ATA_SHT_EMULATED,
++	.use_clustering		= ATA_SHT_USE_CLUSTERING,
++	.proc_name		= DRV_NAME,
++	.dma_boundary		= ATA_DMA_BOUNDARY,
++	.slave_configure	= ata_scsi_slave_config,
++	.slave_destroy		= ata_scsi_slave_destroy,
++	.bios_param		= ata_std_bios_param,
++};
 +
-+	ablkcipher_request_set_tfm(subreq, skcipher_geniv_cipher(geniv));
++static struct ata_port_operations ninja32_port_ops = {
++	.set_piomode	= ninja32_set_piomode,
++	.mode_filter	= ata_pci_default_filter,
 +
-+	complete = req->creq.base.complete;
-+	data = req->creq.base.data;
-+	info = req->creq.info;
++	.tf_load	= ata_tf_load,
++	.tf_read	= ata_tf_read,
++	.check_status 	= ata_check_status,
++	.exec_command	= ata_exec_command,
++	.dev_select 	= ninja32_dev_select,
 +
-+	ivsize = crypto_ablkcipher_ivsize(geniv);
++	.freeze		= ata_bmdma_freeze,
++	.thaw		= ata_bmdma_thaw,
++	.error_handler	= ata_bmdma_error_handler,
++	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.cable_detect	= ata_cable_40wire,
 +
-+	if (unlikely(!IS_ALIGNED((unsigned long)info,
-+				 crypto_ablkcipher_alignmask(geniv) + 1))) {
-+		info = kmalloc(ivsize, req->creq.base.flags &
-+				       CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
-+								  GFP_ATOMIC);
-+		if (!info)
-+			return -ENOMEM;
++	.bmdma_setup 	= ata_bmdma_setup,
++	.bmdma_start 	= ata_bmdma_start,
++	.bmdma_stop	= ata_bmdma_stop,
++	.bmdma_status 	= ata_bmdma_status,
 +
-+		complete = seqiv_complete;
-+		data = req;
-+	}
++	.qc_prep 	= ata_qc_prep,
++	.qc_issue	= ata_qc_issue_prot,
 +
-+	ablkcipher_request_set_callback(subreq, req->creq.base.flags, complete,
-+					data);
-+	ablkcipher_request_set_crypt(subreq, req->creq.src, req->creq.dst,
-+				     req->creq.nbytes, info);
++	.data_xfer	= ata_data_xfer,
 +
-+	seqiv_geniv(ctx, info, req->seq, ivsize);
-+	memcpy(req->giv, info, ivsize);
++	.irq_handler	= ata_interrupt,
++	.irq_clear	= ata_bmdma_irq_clear,
++	.irq_on		= ata_irq_on,
 +
-+	err = crypto_ablkcipher_encrypt(subreq);
-+	if (unlikely(info != req->creq.info))
-+		seqiv_complete2(req, err);
-+	return err;
-+}
++	.port_start	= ata_sff_port_start,
++};
 +
-+static int seqiv_aead_givencrypt(struct aead_givcrypt_request *req)
++static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
 +{
-+	struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
-+	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
-+	struct aead_request *areq = &req->areq;
-+	struct aead_request *subreq = aead_givcrypt_reqctx(req);
-+	crypto_completion_t complete;
-+	void *data;
-+	u8 *info;
-+	unsigned int ivsize;
-+	int err;
-+
-+	aead_request_set_tfm(subreq, aead_geniv_base(geniv));
-+
-+	complete = areq->base.complete;
-+	data = areq->base.data;
-+	info = areq->iv;
++	struct ata_host *host;
++	struct ata_port *ap;
++	void __iomem *base;
++	int rc;
 +
-+	ivsize = crypto_aead_ivsize(geniv);
++	host = ata_host_alloc(&dev->dev, 1);
++	if (!host)
++		return -ENOMEM;
++	ap = host->ports[0];
 +
-+	if (unlikely(!IS_ALIGNED((unsigned long)info,
-+				 crypto_aead_alignmask(geniv) + 1))) {
-+		info = kmalloc(ivsize, areq->base.flags &
-+				       CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
-+								  GFP_ATOMIC);
-+		if (!info)
-+			return -ENOMEM;
++	/* Set up the PCI device */
++	rc = pcim_enable_device(dev);
++	if (rc)
++		return rc;
++	rc = pcim_iomap_regions(dev, 1 << 0, DRV_NAME);
++	if (rc == -EBUSY)
++		pcim_pin_device(dev);
++	if (rc)
++		return rc;
 +
-+		complete = seqiv_aead_complete;
-+		data = req;
-+	}
++	host->iomap = pcim_iomap_table(dev);
++	rc = pci_set_dma_mask(dev, ATA_DMA_MASK);
++	if (rc)
++		return rc;
++	rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK);
++	if (rc)
++		return rc;
++	pci_set_master(dev);
 +
-+	aead_request_set_callback(subreq, areq->base.flags, complete, data);
-+	aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen,
-+			       info);
-+	aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);
++	/* Set up the register mappings */
++	base = host->iomap[0];
++	if (!base)
++		return -ENOMEM;
++	ap->ops = &ninja32_port_ops;
++	ap->pio_mask = 0x1F;
++	ap->flags |= ATA_FLAG_SLAVE_POSS;
 +
-+	seqiv_geniv(ctx, info, req->seq, ivsize);
-+	memcpy(req->giv, info, ivsize);
++	ap->ioaddr.cmd_addr = base + 0x10;
++	ap->ioaddr.ctl_addr = base + 0x1E;
++	ap->ioaddr.altstatus_addr = base + 0x1E;
++	ap->ioaddr.bmdma_addr = base;
++	ata_std_ports(&ap->ioaddr);
 +
-+	err = crypto_aead_encrypt(subreq);
-+	if (unlikely(info != areq->iv))
-+		seqiv_aead_complete2(req, err);
-+	return err;
++	iowrite8(0x05, base + 0x01);	/* Enable interrupt lines */
++	iowrite8(0xB3, base + 0x02);	/* Burst, ?? setup */
++	iowrite8(0x00, base + 0x04);	/* WAIT0 ? */
++	/* FIXME: Should we disable them at remove ? */
++	return ata_host_activate(host, dev->irq, ata_interrupt,
++				 IRQF_SHARED, &ninja32_sht);
 +}
 +
-+static int seqiv_givencrypt_first(struct skcipher_givcrypt_request *req)
-+{
-+	struct crypto_ablkcipher *geniv = skcipher_givcrypt_reqtfm(req);
-+	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+
-+	spin_lock_bh(&ctx->lock);
-+	if (crypto_ablkcipher_crt(geniv)->givencrypt != seqiv_givencrypt_first)
-+		goto unlock;
-+
-+	crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt;
-+	get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
-+
-+unlock:
-+	spin_unlock_bh(&ctx->lock);
++static const struct pci_device_id ninja32[] = {
++	{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	{ },
++};
 +
-+	return seqiv_givencrypt(req);
-+}
++static struct pci_driver ninja32_pci_driver = {
++	.name 		= DRV_NAME,
++	.id_table	= ninja32,
++	.probe 		= ninja32_init_one,
++	.remove		= ata_pci_remove_one
++};
 +
-+static int seqiv_aead_givencrypt_first(struct aead_givcrypt_request *req)
++static int __init ninja32_init(void)
 +{
-+	struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
-+	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
-+
-+	spin_lock_bh(&ctx->lock);
-+	if (crypto_aead_crt(geniv)->givencrypt != seqiv_aead_givencrypt_first)
-+		goto unlock;
-+
-+	crypto_aead_crt(geniv)->givencrypt = seqiv_aead_givencrypt;
-+	get_random_bytes(ctx->salt, crypto_aead_ivsize(geniv));
-+
-+unlock:
-+	spin_unlock_bh(&ctx->lock);
-+
-+	return seqiv_aead_givencrypt(req);
++	return pci_register_driver(&ninja32_pci_driver);
 +}
 +
-+static int seqiv_init(struct crypto_tfm *tfm)
++static void __exit ninja32_exit(void)
 +{
-+	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
-+	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
-+
-+	spin_lock_init(&ctx->lock);
-+
-+	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
-+
-+	return skcipher_geniv_init(tfm);
++	pci_unregister_driver(&ninja32_pci_driver);
 +}
 +
-+static int seqiv_aead_init(struct crypto_tfm *tfm)
-+{
-+	struct crypto_aead *geniv = __crypto_aead_cast(tfm);
-+	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
-+
-+	spin_lock_init(&ctx->lock);
-+
-+	tfm->crt_aead.reqsize = sizeof(struct aead_request);
++MODULE_AUTHOR("Alan Cox");
++MODULE_DESCRIPTION("low-level driver for Ninja32 ATA");
++MODULE_LICENSE("GPL");
++MODULE_DEVICE_TABLE(pci, ninja32);
++MODULE_VERSION(DRV_VERSION);
 +
-+	return aead_geniv_init(tfm);
-+}
++module_init(ninja32_init);
++module_exit(ninja32_exit);
+diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
+new file mode 100644
+index 0000000..938f48a
+--- /dev/null
++++ b/drivers/ata/pata_of_platform.c
+@@ -0,0 +1,114 @@
++/*
++ * OF-platform PATA driver
++ *
++ * Copyright (c) 2007  MontaVista Software, Inc.
++ *                     Anton Vorontsov <avorontsov at ru.mvista.com>
++ *
++ * 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.
++ */
 +
-+static struct crypto_template seqiv_tmpl;
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/of_platform.h>
++#include <linux/pata_platform.h>
 +
-+static struct crypto_instance *seqiv_ablkcipher_alloc(struct rtattr **tb)
++static int __devinit pata_of_platform_probe(struct of_device *ofdev,
++					    const struct of_device_id *match)
 +{
-+	struct crypto_instance *inst;
-+
-+	inst = skcipher_geniv_alloc(&seqiv_tmpl, tb, 0, 0);
-+
-+	if (IS_ERR(inst))
-+		goto out;
-+
-+	inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt_first;
-+
-+	inst->alg.cra_init = seqiv_init;
-+	inst->alg.cra_exit = skcipher_geniv_exit;
-+
-+	inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
-+
-+out:
-+	return inst;
-+}
++	int ret;
++	struct device_node *dn = ofdev->node;
++	struct resource io_res;
++	struct resource ctl_res;
++	struct resource irq_res;
++	unsigned int reg_shift = 0;
++	int pio_mode = 0;
++	int pio_mask;
++	const u32 *prop;
 +
-+static struct crypto_instance *seqiv_aead_alloc(struct rtattr **tb)
-+{
-+	struct crypto_instance *inst;
++	ret = of_address_to_resource(dn, 0, &io_res);
++	if (ret) {
++		dev_err(&ofdev->dev, "can't get IO address from "
++			"device tree\n");
++		return -EINVAL;
++	}
 +
-+	inst = aead_geniv_alloc(&seqiv_tmpl, tb, 0, 0);
++	if (of_device_is_compatible(dn, "electra-ide")) {
++		/* Altstatus is really at offset 0x3f6 from the primary window
++		 * on electra-ide. Adjust ctl_res and io_res accordingly.
++		 */
++		ctl_res = io_res;
++		ctl_res.start = ctl_res.start+0x3f6;
++		io_res.end = ctl_res.start-1;
++	} else {
++		ret = of_address_to_resource(dn, 1, &ctl_res);
++		if (ret) {
++			dev_err(&ofdev->dev, "can't get CTL address from "
++				"device tree\n");
++			return -EINVAL;
++		}
++	}
 +
-+	if (IS_ERR(inst))
-+		goto out;
++	ret = of_irq_to_resource(dn, 0, &irq_res);
++	if (ret == NO_IRQ)
++		irq_res.start = irq_res.end = -1;
++	else
++		irq_res.flags = 0;
 +
-+	inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt_first;
++	prop = of_get_property(dn, "reg-shift", NULL);
++	if (prop)
++		reg_shift = *prop;
 +
-+	inst->alg.cra_init = seqiv_aead_init;
-+	inst->alg.cra_exit = aead_geniv_exit;
++	prop = of_get_property(dn, "pio-mode", NULL);
++	if (prop) {
++		pio_mode = *prop;
++		if (pio_mode > 6) {
++			dev_err(&ofdev->dev, "invalid pio-mode\n");
++			return -EINVAL;
++		}
++	} else {
++		dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n");
++	}
 +
-+	inst->alg.cra_ctxsize = inst->alg.cra_aead.ivsize;
++	pio_mask = 1 << pio_mode;
++	pio_mask |= (1 << pio_mode) - 1;
 +
-+out:
-+	return inst;
++	return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res,
++				     reg_shift, pio_mask);
 +}
 +
-+static struct crypto_instance *seqiv_alloc(struct rtattr **tb)
++static int __devexit pata_of_platform_remove(struct of_device *ofdev)
 +{
-+	struct crypto_attr_type *algt;
-+	struct crypto_instance *inst;
-+	int err;
-+
-+	algt = crypto_get_attr_type(tb);
-+	err = PTR_ERR(algt);
-+	if (IS_ERR(algt))
-+		return ERR_PTR(err);
-+
-+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
-+		inst = seqiv_ablkcipher_alloc(tb);
-+	else
-+		inst = seqiv_aead_alloc(tb);
-+
-+	if (IS_ERR(inst))
-+		goto out;
-+
-+	inst->alg.cra_alignmask |= __alignof__(u32) - 1;
-+	inst->alg.cra_ctxsize += sizeof(struct seqiv_ctx);
-+
-+out:
-+	return inst;
++	return __pata_platform_remove(&ofdev->dev);
 +}
 +
-+static void seqiv_free(struct crypto_instance *inst)
-+{
-+	if ((inst->alg.cra_flags ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
-+		skcipher_geniv_free(inst);
-+	else
-+		aead_geniv_free(inst);
-+}
++static struct of_device_id pata_of_platform_match[] = {
++	{ .compatible = "ata-generic", },
++	{ .compatible = "electra-ide", },
++	{},
++};
++MODULE_DEVICE_TABLE(of, pata_of_platform_match);
 +
-+static struct crypto_template seqiv_tmpl = {
-+	.name = "seqiv",
-+	.alloc = seqiv_alloc,
-+	.free = seqiv_free,
-+	.module = THIS_MODULE,
++static struct of_platform_driver pata_of_platform_driver = {
++	.name		= "pata_of_platform",
++	.match_table	= pata_of_platform_match,
++	.probe		= pata_of_platform_probe,
++	.remove		= __devexit_p(pata_of_platform_remove),
 +};
 +
-+static int __init seqiv_module_init(void)
++static int __init pata_of_platform_init(void)
 +{
-+	return crypto_register_template(&seqiv_tmpl);
++	return of_register_platform_driver(&pata_of_platform_driver);
 +}
++module_init(pata_of_platform_init);
 +
-+static void __exit seqiv_module_exit(void)
++static void __exit pata_of_platform_exit(void)
 +{
-+	crypto_unregister_template(&seqiv_tmpl);
++	of_unregister_platform_driver(&pata_of_platform_driver);
 +}
++module_exit(pata_of_platform_exit);
 +
-+module_init(seqiv_module_init);
-+module_exit(seqiv_module_exit);
-+
++MODULE_DESCRIPTION("OF-platform PATA driver");
++MODULE_AUTHOR("Anton Vorontsov <avorontsov at ru.mvista.com>");
 +MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("Sequence Number IV Generator");
-diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
-index fd3918b..3cc93fd 100644
---- a/crypto/sha256_generic.c
-+++ b/crypto/sha256_generic.c
-@@ -9,6 +9,7 @@
-  * Copyright (c) Jean-Luc Cooke <jlcooke at certainkey.com>
-  * Copyright (c) Andrew McDonald <andrew at mcdonald.org.uk>
-  * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
-+ * SHA224 Support Copyright 2007 Intel Corporation <jonathan.lynch at intel.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
-@@ -218,6 +219,22 @@ static void sha256_transform(u32 *state, const u8 *input)
- 	memset(W, 0, 64 * sizeof(u32));
+diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
+index fd36099..3e7f6a9 100644
+--- a/drivers/ata/pata_pcmcia.c
++++ b/drivers/ata/pata_pcmcia.c
+@@ -42,7 +42,7 @@
+ 
+ 
+ #define DRV_NAME "pata_pcmcia"
+-#define DRV_VERSION "0.3.2"
++#define DRV_VERSION "0.3.3"
+ 
+ /*
+  *	Private data structure to glue stuff together
+@@ -86,6 +86,47 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
+ 	return ata_do_set_mode(link, r_failed_dev);
  }
  
++/**
++ *	pcmcia_set_mode_8bit	-	PCMCIA specific mode setup
++ *	@link: link
++ *	@r_failed_dev: Return pointer for failed device
++ *
++ *	For the simple emulated 8bit stuff the less we do the better.
++ */
 +
-+static void sha224_init(struct crypto_tfm *tfm)
++static int pcmcia_set_mode_8bit(struct ata_link *link,
++				struct ata_device **r_failed_dev)
 +{
-+	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
-+	sctx->state[0] = SHA224_H0;
-+	sctx->state[1] = SHA224_H1;
-+	sctx->state[2] = SHA224_H2;
-+	sctx->state[3] = SHA224_H3;
-+	sctx->state[4] = SHA224_H4;
-+	sctx->state[5] = SHA224_H5;
-+	sctx->state[6] = SHA224_H6;
-+	sctx->state[7] = SHA224_H7;
-+	sctx->count[0] = 0;
-+	sctx->count[1] = 0;
++	return 0;
 +}
 +
- static void sha256_init(struct crypto_tfm *tfm)
- {
- 	struct sha256_ctx *sctx = crypto_tfm_ctx(tfm);
-@@ -294,8 +311,17 @@ static void sha256_final(struct crypto_tfm *tfm, u8 *out)
- 	memset(sctx, 0, sizeof(*sctx));
- }
- 
-+static void sha224_final(struct crypto_tfm *tfm, u8 *hash)
++/**
++ *	ata_data_xfer_8bit	 -	Transfer data by 8bit PIO
++ *	@dev: device to target
++ *	@buf: data buffer
++ *	@buflen: buffer length
++ *	@rw: read/write
++ *
++ *	Transfer data from/to the device data register by 8 bit PIO.
++ *
++ *	LOCKING:
++ *	Inherited from caller.
++ */
++
++static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
++				unsigned char *buf, unsigned int buflen, int rw)
 +{
-+	u8 D[SHA256_DIGEST_SIZE];
++	struct ata_port *ap = dev->link->ap;
 +
-+	sha256_final(tfm, D);
++	if (rw == READ)
++		ioread8_rep(ap->ioaddr.data_addr, buf, buflen);
++	else
++		iowrite8_rep(ap->ioaddr.data_addr, buf, buflen);
 +
-+	memcpy(hash, D, SHA224_DIGEST_SIZE);
-+	memset(D, 0, SHA256_DIGEST_SIZE);
++	return buflen;
 +}
- 
--static struct crypto_alg alg = {
-+static struct crypto_alg sha256 = {
- 	.cra_name	=	"sha256",
- 	.cra_driver_name=	"sha256-generic",
- 	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
-@@ -303,28 +329,58 @@ static struct crypto_alg alg = {
- 	.cra_ctxsize	=	sizeof(struct sha256_ctx),
- 	.cra_module	=	THIS_MODULE,
- 	.cra_alignmask	=	3,
--	.cra_list       =       LIST_HEAD_INIT(alg.cra_list),
-+	.cra_list	=	LIST_HEAD_INIT(sha256.cra_list),
- 	.cra_u		=	{ .digest = {
- 	.dia_digestsize	=	SHA256_DIGEST_SIZE,
--	.dia_init   	= 	sha256_init,
--	.dia_update 	=	sha256_update,
--	.dia_final  	=	sha256_final } }
-+	.dia_init	=	sha256_init,
-+	.dia_update	=	sha256_update,
-+	.dia_final	=	sha256_final } }
-+};
 +
-+static struct crypto_alg sha224 = {
-+	.cra_name	= "sha224",
-+	.cra_driver_name = "sha224-generic",
-+	.cra_flags	= CRYPTO_ALG_TYPE_DIGEST,
-+	.cra_blocksize	= SHA224_BLOCK_SIZE,
-+	.cra_ctxsize	= sizeof(struct sha256_ctx),
-+	.cra_module	= THIS_MODULE,
-+	.cra_alignmask	= 3,
-+	.cra_list	= LIST_HEAD_INIT(sha224.cra_list),
-+	.cra_u		= { .digest = {
-+	.dia_digestsize = SHA224_DIGEST_SIZE,
-+	.dia_init	= sha224_init,
-+	.dia_update	= sha256_update,
-+	.dia_final	= sha224_final } }
++
+ static struct scsi_host_template pcmcia_sht = {
+ 	.module			= THIS_MODULE,
+ 	.name			= DRV_NAME,
+@@ -129,6 +170,31 @@ static struct ata_port_operations pcmcia_port_ops = {
+ 	.port_start	= ata_sff_port_start,
  };
  
- static int __init init(void)
- {
--	return crypto_register_alg(&alg);
-+	int ret = 0;
++static struct ata_port_operations pcmcia_8bit_port_ops = {
++	.set_mode	= pcmcia_set_mode_8bit,
++	.tf_load	= ata_tf_load,
++	.tf_read	= ata_tf_read,
++	.check_status 	= ata_check_status,
++	.exec_command	= ata_exec_command,
++	.dev_select 	= ata_std_dev_select,
 +
-+	ret = crypto_register_alg(&sha224);
++	.freeze		= ata_bmdma_freeze,
++	.thaw		= ata_bmdma_thaw,
++	.error_handler	= ata_bmdma_error_handler,
++	.post_internal_cmd = ata_bmdma_post_internal_cmd,
++	.cable_detect	= ata_cable_40wire,
 +
-+	if (ret < 0)
-+		return ret;
++	.qc_prep 	= ata_qc_prep,
++	.qc_issue	= ata_qc_issue_prot,
 +
-+	ret = crypto_register_alg(&sha256);
++	.data_xfer	= ata_data_xfer_8bit,
 +
-+	if (ret < 0)
-+		crypto_unregister_alg(&sha224);
++	.irq_clear	= ata_bmdma_irq_clear,
++	.irq_on		= ata_irq_on,
 +
-+	return ret;
- }
++	.port_start	= ata_sff_port_start,
++};
++
+ #define CS_CHECK(fn, ret) \
+ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
  
- static void __exit fini(void)
- {
--	crypto_unregister_alg(&alg);
-+	crypto_unregister_alg(&sha224);
-+	crypto_unregister_alg(&sha256);
- }
+@@ -153,9 +219,12 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
+ 		cistpl_cftable_entry_t dflt;
+ 	} *stk = NULL;
+ 	cistpl_cftable_entry_t *cfg;
+-	int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM;
++	int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
+ 	unsigned long io_base, ctl_base;
+ 	void __iomem *io_addr, *ctl_addr;
++	int n_ports = 1;
++
++	struct ata_port_operations *ops = &pcmcia_port_ops;
  
- module_init(init);
- module_exit(fini);
+ 	info = kzalloc(sizeof(*info), GFP_KERNEL);
+ 	if (info == NULL)
+@@ -282,27 +351,32 @@ next_entry:
+ 	/* FIXME: Could be more ports at base + 0x10 but we only deal with
+ 	   one right now */
+ 	if (pdev->io.NumPorts1 >= 0x20)
+-		printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n");
++		n_ports = 2;
  
- MODULE_LICENSE("GPL");
--MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm");
-+MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm");
++	if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
++		ops = &pcmcia_8bit_port_ops;
+ 	/*
+ 	 *	Having done the PCMCIA plumbing the ATA side is relatively
+ 	 *	sane.
+ 	 */
+ 	ret = -ENOMEM;
+-	host = ata_host_alloc(&pdev->dev, 1);
++	host = ata_host_alloc(&pdev->dev, n_ports);
+ 	if (!host)
+ 		goto failed;
+-	ap = host->ports[0];
  
-+MODULE_ALIAS("sha224");
- MODULE_ALIAS("sha256");
-diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
-index 24141fb..1ab8c01 100644
---- a/crypto/tcrypt.c
-+++ b/crypto/tcrypt.c
-@@ -6,12 +6,16 @@
-  *
-  * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
-  * Copyright (c) 2002 Jean-Francois Dive <jef at linuxbe.org>
-+ * Copyright (c) 2007 Nokia Siemens Networks
-  *
-  * 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.
-  *
-+ * 2007-11-13 Added GCM tests
-+ * 2007-11-13 Added AEAD support
-+ * 2007-11-06 Added SHA-224 and SHA-224-HMAC tests
-  * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
-  * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk at vantronix.net>)
-  * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
-@@ -71,22 +75,23 @@ static unsigned int sec;
+-	ap->ops = &pcmcia_port_ops;
+-	ap->pio_mask = 1;		/* ISA so PIO 0 cycles */
+-	ap->flags |= ATA_FLAG_SLAVE_POSS;
+-	ap->ioaddr.cmd_addr = io_addr;
+-	ap->ioaddr.altstatus_addr = ctl_addr;
+-	ap->ioaddr.ctl_addr = ctl_addr;
+-	ata_std_ports(&ap->ioaddr);
++	for (p = 0; p < n_ports; p++) {
++		ap = host->ports[p];
  
- static int mode;
- static char *xbuf;
-+static char *axbuf;
- static char *tvmem;
+-	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
++		ap->ops = ops;
++		ap->pio_mask = 1;		/* ISA so PIO 0 cycles */
++		ap->flags |= ATA_FLAG_SLAVE_POSS;
++		ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
++		ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
++		ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
++		ata_std_ports(&ap->ioaddr);
++
++		ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
++	}
  
- static char *check[] = {
--	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
--	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
-+	"des", "md5", "des3_ede", "rot13", "sha1", "sha224", "sha256",
-+	"blowfish", "twofish", "serpent", "sha384", "sha512", "md4", "aes",
-+	"cast6", "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
- 	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
- 	"khazad", "wp512", "wp384", "wp256", "tnepres", "xeta",  "fcrypt",
--	"camellia", "seed", NULL
-+	"camellia", "seed", "salsa20", "lzo", NULL
+ 	/* activate */
+ 	ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
+@@ -360,6 +434,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
+ 	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
+ 	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
+ 	PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),	/* SanDisk CFA */
++	PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), 	/* TI emulated */
+ 	PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),	/* Toshiba */
+ 	PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
+ 	PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),	/* Samsung */
+diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
+index 2622577..028af5d 100644
+--- a/drivers/ata/pata_pdc2027x.c
++++ b/drivers/ata/pata_pdc2027x.c
+@@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
+ 	ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
+ 			  ATA_ID_PROD_LEN + 1);
+ 	/* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */
+-	if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6)
++	if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
+ 		mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
+ 
+ 	return ata_pci_default_filter(adev, mask);
+diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
+index 6c9689b..3ed8667 100644
+--- a/drivers/ata/pata_pdc202xx_old.c
++++ b/drivers/ata/pata_pdc202xx_old.c
+@@ -168,8 +168,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
+ 	pdc202xx_set_dmamode(ap, qc->dev);
+ 
+ 	/* Cases the state machine will not complete correctly without help */
+-	if ((tf->flags & ATA_TFLAG_LBA48) ||  tf->protocol == ATA_PROT_ATAPI_DMA)
+-	{
++	if ((tf->flags & ATA_TFLAG_LBA48) ||  tf->protocol == ATAPI_PROT_DMA) {
+ 		len = qc->nbytes / 2;
+ 
+ 		if (tf->flags & ATA_TFLAG_WRITE)
+@@ -208,7 +207,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
+ 	void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
+ 
+ 	/* Cases the state machine will not complete correctly */
+-	if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) {
++	if (tf->protocol == ATAPI_PROT_DMA || (tf->flags & ATA_TFLAG_LBA48)) {
+ 		iowrite32(0, atapi_reg);
+ 		iowrite8(ioread8(clock) & ~sel66, clock);
+ 	}
+diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
+index ac03a90..224bb6c 100644
+--- a/drivers/ata/pata_platform.c
++++ b/drivers/ata/pata_platform.c
+@@ -93,14 +93,9 @@ static struct ata_port_operations pata_platform_port_ops = {
  };
  
- static void hexdump(unsigned char *buf, unsigned int len)
+ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
+-				     struct pata_platform_info *info)
++				     unsigned int shift)
  {
--	while (len--)
--		printk("%02x", *buf++);
+-	unsigned int shift = 0;
 -
--	printk("\n");
-+	print_hex_dump(KERN_CONT, "", DUMP_PREFIX_OFFSET,
-+			16, 1,
-+			buf, len, false);
+ 	/* Fixup the port shift for platforms that need it */
+-	if (info && info->ioport_shift)
+-		shift = info->ioport_shift;
+-
+ 	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << shift);
+ 	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << shift);
+ 	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
+@@ -114,8 +109,13 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
  }
  
- static void tcrypt_complete(struct crypto_async_request *req, int err)
-@@ -215,6 +220,238 @@ out:
- 	crypto_free_hash(tfm);
- }
+ /**
+- *	pata_platform_probe		-	attach a platform interface
+- *	@pdev: platform device
++ *	__pata_platform_probe		-	attach a platform interface
++ *	@dev: device
++ *	@io_res: Resource representing I/O base
++ *	@ctl_res: Resource representing CTL base
++ *	@irq_res: Resource representing IRQ and its flags
++ *	@ioport_shift: I/O port shift
++ *	@__pio_mask: PIO mask
+  *
+  *	Register a platform bus IDE interface. Such interfaces are PIO and we
+  *	assume do not support IRQ sharing.
+@@ -135,42 +135,18 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
+  *
+  *	If no IRQ resource is present, PIO polling mode is used instead.
+  */
+-static int __devinit pata_platform_probe(struct platform_device *pdev)
++int __devinit __pata_platform_probe(struct device *dev,
++				    struct resource *io_res,
++				    struct resource *ctl_res,
++				    struct resource *irq_res,
++				    unsigned int ioport_shift,
++				    int __pio_mask)
+ {
+-	struct resource *io_res, *ctl_res;
+ 	struct ata_host *host;
+ 	struct ata_port *ap;
+-	struct pata_platform_info *pp_info;
+ 	unsigned int mmio;
+-	int irq;
+-
+-	/*
+-	 * Simple resource validation ..
+-	 */
+-	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
+-		dev_err(&pdev->dev, "invalid number of resources\n");
+-		return -EINVAL;
+-	}
+-
+-	/*
+-	 * Get the I/O base first
+-	 */
+-	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+-	if (io_res == NULL) {
+-		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+-		if (unlikely(io_res == NULL))
+-			return -EINVAL;
+-	}
+-
+-	/*
+-	 * Then the CTL base
+-	 */
+-	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
+-	if (ctl_res == NULL) {
+-		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+-		if (unlikely(ctl_res == NULL))
+-			return -EINVAL;
+-	}
++	int irq = 0;
++	int irq_flags = 0;
  
-+static void test_aead(char *algo, int enc, struct aead_testvec *template,
-+		      unsigned int tcount)
-+{
-+	unsigned int ret, i, j, k, temp;
-+	unsigned int tsize;
-+	char *q;
-+	struct crypto_aead *tfm;
-+	char *key;
-+	struct aead_testvec *aead_tv;
-+	struct aead_request *req;
-+	struct scatterlist sg[8];
-+	struct scatterlist asg[8];
-+	const char *e;
-+	struct tcrypt_result result;
-+	unsigned int authsize;
-+
-+	if (enc == ENCRYPT)
-+		e = "encryption";
-+	else
-+		e = "decryption";
-+
-+	printk(KERN_INFO "\ntesting %s %s\n", algo, e);
-+
-+	tsize = sizeof(struct aead_testvec);
-+	tsize *= tcount;
-+
-+	if (tsize > TVMEMSIZE) {
-+		printk(KERN_INFO "template (%u) too big for tvmem (%u)\n",
-+		       tsize, TVMEMSIZE);
-+		return;
+ 	/*
+ 	 * Check for MMIO
+@@ -181,20 +157,21 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
+ 	/*
+ 	 * And the IRQ
+ 	 */
+-	irq = platform_get_irq(pdev, 0);
+-	if (irq < 0)
+-		irq = 0;	/* no irq */
++	if (irq_res && irq_res->start > 0) {
++		irq = irq_res->start;
++		irq_flags = irq_res->flags;
 +	}
+ 
+ 	/*
+ 	 * Now that that's out of the way, wire up the port..
+ 	 */
+-	host = ata_host_alloc(&pdev->dev, 1);
++	host = ata_host_alloc(dev, 1);
+ 	if (!host)
+ 		return -ENOMEM;
+ 	ap = host->ports[0];
+ 
+ 	ap->ops = &pata_platform_port_ops;
+-	ap->pio_mask = pio_mask;
++	ap->pio_mask = __pio_mask;
+ 	ap->flags |= ATA_FLAG_SLAVE_POSS;
+ 
+ 	/*
+@@ -209,25 +186,24 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
+ 	 * Handle the MMIO case
+ 	 */
+ 	if (mmio) {
+-		ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
++		ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start,
+ 				io_res->end - io_res->start + 1);
+-		ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
++		ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start,
+ 				ctl_res->end - ctl_res->start + 1);
+ 	} else {
+-		ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
++		ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start,
+ 				io_res->end - io_res->start + 1);
+-		ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
++		ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start,
+ 				ctl_res->end - ctl_res->start + 1);
+ 	}
+ 	if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
+-		dev_err(&pdev->dev, "failed to map IO/CTL base\n");
++		dev_err(dev, "failed to map IO/CTL base\n");
+ 		return -ENOMEM;
+ 	}
+ 
+ 	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
+ 
+-	pp_info = pdev->dev.platform_data;
+-	pata_platform_setup_port(&ap->ioaddr, pp_info);
++	pata_platform_setup_port(&ap->ioaddr, ioport_shift);
+ 
+ 	ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
+ 		      (unsigned long long)io_res->start,
+@@ -235,26 +211,78 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
+ 
+ 	/* activate */
+ 	return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
+-				 pp_info ? pp_info->irq_flags : 0,
+-				 &pata_platform_sht);
++				 irq_flags, &pata_platform_sht);
+ }
++EXPORT_SYMBOL_GPL(__pata_platform_probe);
+ 
+ /**
+- *	pata_platform_remove	-	unplug a platform interface
+- *	@pdev: platform device
++ *	__pata_platform_remove		-	unplug a platform interface
++ *	@dev: device
+  *
+  *	A platform bus ATA device has been unplugged. Perform the needed
+  *	cleanup. Also called on module unload for any active devices.
+  */
+-static int __devexit pata_platform_remove(struct platform_device *pdev)
++int __devexit __pata_platform_remove(struct device *dev)
+ {
+-	struct device *dev = &pdev->dev;
+ 	struct ata_host *host = dev_get_drvdata(dev);
+ 
+ 	ata_host_detach(host);
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL_GPL(__pata_platform_remove);
 +
-+	memcpy(tvmem, template, tsize);
-+	aead_tv = (void *)tvmem;
-+
-+	init_completion(&result.completion);
-+
-+	tfm = crypto_alloc_aead(algo, 0, 0);
++static int __devinit pata_platform_probe(struct platform_device *pdev)
++{
++	struct resource *io_res;
++	struct resource *ctl_res;
++	struct resource *irq_res;
++	struct pata_platform_info *pp_info = pdev->dev.platform_data;
 +
-+	if (IS_ERR(tfm)) {
-+		printk(KERN_INFO "failed to load transform for %s: %ld\n",
-+		       algo, PTR_ERR(tfm));
-+		return;
++	/*
++	 * Simple resource validation ..
++	 */
++	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
++		dev_err(&pdev->dev, "invalid number of resources\n");
++		return -EINVAL;
 +	}
 +
-+	req = aead_request_alloc(tfm, GFP_KERNEL);
-+	if (!req) {
-+		printk(KERN_INFO "failed to allocate request for %s\n", algo);
-+		goto out;
++	/*
++	 * Get the I/O base first
++	 */
++	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
++	if (io_res == NULL) {
++		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++		if (unlikely(io_res == NULL))
++			return -EINVAL;
 +	}
 +
-+	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-+				  tcrypt_complete, &result);
-+
-+	for (i = 0, j = 0; i < tcount; i++) {
-+		if (!aead_tv[i].np) {
-+			printk(KERN_INFO "test %u (%d bit key):\n",
-+			       ++j, aead_tv[i].klen * 8);
-+
-+			crypto_aead_clear_flags(tfm, ~0);
-+			if (aead_tv[i].wk)
-+				crypto_aead_set_flags(
-+					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-+			key = aead_tv[i].key;
-+
-+			ret = crypto_aead_setkey(tfm, key,
-+						 aead_tv[i].klen);
-+			if (ret) {
-+				printk(KERN_INFO "setkey() failed flags=%x\n",
-+				       crypto_aead_get_flags(tfm));
-+
-+				if (!aead_tv[i].fail)
-+					goto out;
-+			}
-+
-+			authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
-+			ret = crypto_aead_setauthsize(tfm, authsize);
-+			if (ret) {
-+				printk(KERN_INFO
-+				       "failed to set authsize = %u\n",
-+				       authsize);
-+				goto out;
-+			}
-+
-+			sg_init_one(&sg[0], aead_tv[i].input,
-+				    aead_tv[i].ilen + (enc ? authsize : 0));
-+
-+			sg_init_one(&asg[0], aead_tv[i].assoc,
-+				    aead_tv[i].alen);
-+
-+			aead_request_set_crypt(req, sg, sg,
-+					       aead_tv[i].ilen,
-+					       aead_tv[i].iv);
-+
-+			aead_request_set_assoc(req, asg, aead_tv[i].alen);
-+
-+			ret = enc ?
-+				crypto_aead_encrypt(req) :
-+				crypto_aead_decrypt(req);
-+
-+			switch (ret) {
-+			case 0:
-+				break;
-+			case -EINPROGRESS:
-+			case -EBUSY:
-+				ret = wait_for_completion_interruptible(
-+					&result.completion);
-+				if (!ret && !(ret = result.err)) {
-+					INIT_COMPLETION(result.completion);
-+					break;
-+				}
-+				/* fall through */
-+			default:
-+				printk(KERN_INFO "%s () failed err=%d\n",
-+				       e, -ret);
-+				goto out;
-+			}
-+
-+			q = kmap(sg_page(&sg[0])) + sg[0].offset;
-+			hexdump(q, aead_tv[i].rlen);
-+
-+			printk(KERN_INFO "enc/dec: %s\n",
-+			       memcmp(q, aead_tv[i].result,
-+				      aead_tv[i].rlen) ? "fail" : "pass");
-+		}
++	/*
++	 * Then the CTL base
++	 */
++	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
++	if (ctl_res == NULL) {
++		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
++		if (unlikely(ctl_res == NULL))
++			return -EINVAL;
 +	}
 +
-+	printk(KERN_INFO "\ntesting %s %s across pages (chunking)\n", algo, e);
-+	memset(xbuf, 0, XBUFSIZE);
-+	memset(axbuf, 0, XBUFSIZE);
-+
-+	for (i = 0, j = 0; i < tcount; i++) {
-+		if (aead_tv[i].np) {
-+			printk(KERN_INFO "test %u (%d bit key):\n",
-+			       ++j, aead_tv[i].klen * 8);
-+
-+			crypto_aead_clear_flags(tfm, ~0);
-+			if (aead_tv[i].wk)
-+				crypto_aead_set_flags(
-+					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
-+			key = aead_tv[i].key;
-+
-+			ret = crypto_aead_setkey(tfm, key, aead_tv[i].klen);
-+			if (ret) {
-+				printk(KERN_INFO "setkey() failed flags=%x\n",
-+				       crypto_aead_get_flags(tfm));
-+
-+				if (!aead_tv[i].fail)
-+					goto out;
-+			}
-+
-+			sg_init_table(sg, aead_tv[i].np);
-+			for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
-+				memcpy(&xbuf[IDX[k]],
-+				       aead_tv[i].input + temp,
-+				       aead_tv[i].tap[k]);
-+				temp += aead_tv[i].tap[k];
-+				sg_set_buf(&sg[k], &xbuf[IDX[k]],
-+					   aead_tv[i].tap[k]);
-+			}
-+
-+			authsize = abs(aead_tv[i].rlen - aead_tv[i].ilen);
-+			ret = crypto_aead_setauthsize(tfm, authsize);
-+			if (ret) {
-+				printk(KERN_INFO
-+				       "failed to set authsize = %u\n",
-+				       authsize);
-+				goto out;
-+			}
-+
-+			if (enc)
-+				sg[k - 1].length += authsize;
-+
-+			sg_init_table(asg, aead_tv[i].anp);
-+			for (k = 0, temp = 0; k < aead_tv[i].anp; k++) {
-+				memcpy(&axbuf[IDX[k]],
-+				       aead_tv[i].assoc + temp,
-+				       aead_tv[i].atap[k]);
-+				temp += aead_tv[i].atap[k];
-+				sg_set_buf(&asg[k], &axbuf[IDX[k]],
-+					   aead_tv[i].atap[k]);
-+			}
-+
-+			aead_request_set_crypt(req, sg, sg,
-+					       aead_tv[i].ilen,
-+					       aead_tv[i].iv);
-+
-+			aead_request_set_assoc(req, asg, aead_tv[i].alen);
-+
-+			ret = enc ?
-+				crypto_aead_encrypt(req) :
-+				crypto_aead_decrypt(req);
-+
-+			switch (ret) {
-+			case 0:
-+				break;
-+			case -EINPROGRESS:
-+			case -EBUSY:
-+				ret = wait_for_completion_interruptible(
-+					&result.completion);
-+				if (!ret && !(ret = result.err)) {
-+					INIT_COMPLETION(result.completion);
-+					break;
-+				}
-+				/* fall through */
-+			default:
-+				printk(KERN_INFO "%s () failed err=%d\n",
-+				       e, -ret);
-+				goto out;
-+			}
-+
-+			for (k = 0, temp = 0; k < aead_tv[i].np; k++) {
-+				printk(KERN_INFO "page %u\n", k);
-+				q = kmap(sg_page(&sg[k])) + sg[k].offset;
-+				hexdump(q, aead_tv[i].tap[k]);
-+				printk(KERN_INFO "%s\n",
-+				       memcmp(q, aead_tv[i].result + temp,
-+					      aead_tv[i].tap[k] -
-+					      (k < aead_tv[i].np - 1 || enc ?
-+					       0 : authsize)) ?
-+				       "fail" : "pass");
++	/*
++	 * And the IRQ
++	 */
++	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++	if (irq_res)
++		irq_res->flags = pp_info ? pp_info->irq_flags : 0;
 +
-+				temp += aead_tv[i].tap[k];
-+			}
-+		}
-+	}
++	return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res,
++				     pp_info ? pp_info->ioport_shift : 0,
++				     pio_mask);
++}
 +
-+out:
-+	crypto_free_aead(tfm);
-+	aead_request_free(req);
++static int __devexit pata_platform_remove(struct platform_device *pdev)
++{
++	return __pata_platform_remove(&pdev->dev);
 +}
+ 
+ static struct platform_driver pata_platform_driver = {
+ 	.probe		= pata_platform_probe,
+diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
+index a4c0e50..9f308ed 100644
+--- a/drivers/ata/pata_qdi.c
++++ b/drivers/ata/pata_qdi.c
+@@ -124,29 +124,33 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
+ 	return ata_qc_issue_prot(qc);
+ }
+ 
+-static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
++static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
++				  unsigned int buflen, int rw)
+ {
+-	struct ata_port *ap = adev->link->ap;
+-	int slop = buflen & 3;
++	if (ata_id_has_dword_io(dev->id)) {
++		struct ata_port *ap = dev->link->ap;
++		int slop = buflen & 3;
+ 
+-	if (ata_id_has_dword_io(adev->id)) {
+-		if (write_data)
+-			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+-		else
++		if (rw == READ)
+ 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
++		else
++			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ 
+ 		if (unlikely(slop)) {
+-			__le32 pad = 0;
+-			if (write_data) {
+-				memcpy(&pad, buf + buflen - slop, slop);
+-				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+-			} else {
++			u32 pad;
++			if (rw == READ) {
+ 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ 				memcpy(buf + buflen - slop, &pad, slop);
++			} else {
++				memcpy(&pad, buf + buflen - slop, slop);
++				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ 			}
++			buflen += 4 - slop;
+ 		}
+ 	} else
+-		ata_data_xfer(adev, buf, buflen, write_data);
++		buflen = ata_data_xfer(dev, buf, buflen, rw);
 +
- static void test_cipher(char *algo, int enc,
- 			struct cipher_testvec *template, unsigned int tcount)
++	return buflen;
+ }
+ 
+ static struct scsi_host_template qdi_sht = {
+diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
+index ea2ef9f..55055b2 100644
+--- a/drivers/ata/pata_scc.c
++++ b/drivers/ata/pata_scc.c
+@@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap)
+ 
+ /**
+  *	scc_data_xfer - Transfer data by PIO
+- *	@adev: device for this I/O
++ *	@dev: device for this I/O
+  *	@buf: data buffer
+  *	@buflen: buffer length
+- *	@write_data: read/write
++ *	@rw: read/write
+  *
+  *	Note: Original code is ata_data_xfer().
+  */
+ 
+-static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
+-			   unsigned int buflen, int write_data)
++static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
++				   unsigned int buflen, int rw)
  {
-@@ -237,15 +474,11 @@ static void test_cipher(char *algo, int enc,
- 	printk("\ntesting %s %s\n", algo, e);
+-	struct ata_port *ap = adev->link->ap;
++	struct ata_port *ap = dev->link->ap;
+ 	unsigned int words = buflen >> 1;
+ 	unsigned int i;
+ 	u16 *buf16 = (u16 *) buf;
+ 	void __iomem *mmio = ap->ioaddr.data_addr;
  
- 	tsize = sizeof (struct cipher_testvec);
--	tsize *= tcount;
--
- 	if (tsize > TVMEMSIZE) {
- 		printk("template (%u) too big for tvmem (%u)\n", tsize,
- 		       TVMEMSIZE);
- 		return;
- 	}
--
--	memcpy(tvmem, template, tsize);
- 	cipher_tv = (void *)tvmem;
+ 	/* Transfer multiple of 2 bytes */
+-	if (write_data) {
+-		for (i = 0; i < words; i++)
+-			out_be32(mmio, cpu_to_le16(buf16[i]));
+-	} else {
++	if (rw == READ)
+ 		for (i = 0; i < words; i++)
+ 			buf16[i] = le16_to_cpu(in_be32(mmio));
+-	}
++	else
++		for (i = 0; i < words; i++)
++			out_be32(mmio, cpu_to_le16(buf16[i]));
  
- 	init_completion(&result.completion);
-@@ -269,33 +502,34 @@ static void test_cipher(char *algo, int enc,
+ 	/* Transfer trailing 1 byte, if any. */
+ 	if (unlikely(buflen & 0x01)) {
+ 		u16 align_buf[1] = { 0 };
+ 		unsigned char *trailing_buf = buf + buflen - 1;
  
- 	j = 0;
- 	for (i = 0; i < tcount; i++) {
--		if (!(cipher_tv[i].np)) {
-+		memcpy(cipher_tv, &template[i], tsize);
-+		if (!(cipher_tv->np)) {
- 			j++;
- 			printk("test %u (%d bit key):\n",
--			j, cipher_tv[i].klen * 8);
-+			j, cipher_tv->klen * 8);
+-		if (write_data) {
+-			memcpy(align_buf, trailing_buf, 1);
+-			out_be32(mmio, cpu_to_le16(align_buf[0]));
+-		} else {
++		if (rw == READ) {
+ 			align_buf[0] = le16_to_cpu(in_be32(mmio));
+ 			memcpy(trailing_buf, align_buf, 1);
++		} else {
++			memcpy(align_buf, trailing_buf, 1);
++			out_be32(mmio, cpu_to_le16(align_buf[0]));
+ 		}
++		words++;
+ 	}
++
++	return words << 1;
+ }
  
- 			crypto_ablkcipher_clear_flags(tfm, ~0);
--			if (cipher_tv[i].wk)
-+			if (cipher_tv->wk)
- 				crypto_ablkcipher_set_flags(
- 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
--			key = cipher_tv[i].key;
-+			key = cipher_tv->key;
+ /**
+diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
+index 8bed888..9c523fb 100644
+--- a/drivers/ata/pata_serverworks.c
++++ b/drivers/ata/pata_serverworks.c
+@@ -41,7 +41,7 @@
+ #include <linux/libata.h>
  
- 			ret = crypto_ablkcipher_setkey(tfm, key,
--						       cipher_tv[i].klen);
-+						       cipher_tv->klen);
- 			if (ret) {
- 				printk("setkey() failed flags=%x\n",
- 				       crypto_ablkcipher_get_flags(tfm));
+ #define DRV_NAME "pata_serverworks"
+-#define DRV_VERSION "0.4.2"
++#define DRV_VERSION "0.4.3"
  
--				if (!cipher_tv[i].fail)
-+				if (!cipher_tv->fail)
- 					goto out;
- 			}
+ #define SVWKS_CSB5_REVISION_NEW	0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
+ #define SVWKS_CSB6_REVISION	0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
+@@ -102,7 +102,7 @@ static int osb4_cable(struct ata_port *ap) {
+ }
  
--			sg_init_one(&sg[0], cipher_tv[i].input,
--				    cipher_tv[i].ilen);
-+			sg_init_one(&sg[0], cipher_tv->input,
-+				    cipher_tv->ilen);
+ /**
+- *	csb4_cable	-	CSB5/6 cable detect
++ *	csb_cable	-	CSB5/6 cable detect
+  *	@ap: ATA port to check
+  *
+  *	Serverworks default arrangement is to use the drive side detection
+@@ -110,7 +110,7 @@ static int osb4_cable(struct ata_port *ap) {
+  */
  
- 			ablkcipher_request_set_crypt(req, sg, sg,
--						     cipher_tv[i].ilen,
--						     cipher_tv[i].iv);
-+						     cipher_tv->ilen,
-+						     cipher_tv->iv);
+ static int csb_cable(struct ata_port *ap) {
+-	return ATA_CBL_PATA80;
++	return ATA_CBL_PATA_UNK;
+ }
  
- 			ret = enc ?
- 				crypto_ablkcipher_encrypt(req) :
-@@ -319,11 +553,11 @@ static void test_cipher(char *algo, int enc,
- 			}
+ struct sv_cable_table {
+@@ -231,7 +231,6 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+ 	return ata_pci_default_filter(adev, mask);
+ }
  
- 			q = kmap(sg_page(&sg[0])) + sg[0].offset;
--			hexdump(q, cipher_tv[i].rlen);
-+			hexdump(q, cipher_tv->rlen);
+-
+ /**
+  *	serverworks_set_piomode	-	set initial PIO mode data
+  *	@ap: ATA interface
+@@ -243,7 +242,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
+ static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ {
+ 	static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+-	int offset = 1 + (2 * ap->port_no) - adev->devno;
++	int offset = 1 + 2 * ap->port_no - adev->devno;
+ 	int devbits = (2 * ap->port_no + adev->devno) * 4;
+ 	u16 csb5_pio;
+ 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
+index 87546d9..dc7e915 100644
+--- a/drivers/ata/pata_sis.c
++++ b/drivers/ata/pata_sis.c
+@@ -345,7 +345,7 @@ static void sis_old_set_dmamode (struct ata_port *ap, struct ata_device *adev)
+ 
+ 	if (adev->dma_mode < XFER_UDMA_0) {
+ 		/* bits 3-0 hold recovery timing bits 8-10 active timing and
+-		   the higer bits are dependant on the device */
++		   the higher bits are dependant on the device */
+ 		timing &= ~0x870F;
+ 		timing |= mwdma_bits[speed];
+ 	} else {
+@@ -385,7 +385,7 @@ static void sis_66_set_dmamode (struct ata_port *ap, struct ata_device *adev)
  
- 			printk("%s\n",
--			       memcmp(q, cipher_tv[i].result,
--				      cipher_tv[i].rlen) ? "fail" : "pass");
-+			       memcmp(q, cipher_tv->result,
-+				      cipher_tv->rlen) ? "fail" : "pass");
- 		}
- 	}
+ 	if (adev->dma_mode < XFER_UDMA_0) {
+ 		/* bits 3-0 hold recovery timing bits 8-10 active timing and
+-		   the higer bits are dependant on the device, bit 15 udma */
++		   the higher bits are dependant on the device, bit 15 udma */
+ 		timing &= ~0x870F;
+ 		timing |= mwdma_bits[speed];
+ 	} else {
+diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
+index 1388cef..81ef207 100644
+--- a/drivers/ata/pata_sl82c105.c
++++ b/drivers/ata/pata_sl82c105.c
+@@ -26,7 +26,7 @@
+ #include <linux/libata.h>
  
-@@ -332,41 +566,42 @@ static void test_cipher(char *algo, int enc,
+ #define DRV_NAME "pata_sl82c105"
+-#define DRV_VERSION "0.3.2"
++#define DRV_VERSION "0.3.3"
  
- 	j = 0;
- 	for (i = 0; i < tcount; i++) {
--		if (cipher_tv[i].np) {
-+		memcpy(cipher_tv, &template[i], tsize);
-+		if (cipher_tv->np) {
- 			j++;
- 			printk("test %u (%d bit key):\n",
--			j, cipher_tv[i].klen * 8);
-+			j, cipher_tv->klen * 8);
+ enum {
+ 	/*
+@@ -206,6 +206,34 @@ static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc)
+ 	sl82c105_set_piomode(ap, qc->dev);
+ }
  
- 			crypto_ablkcipher_clear_flags(tfm, ~0);
--			if (cipher_tv[i].wk)
-+			if (cipher_tv->wk)
- 				crypto_ablkcipher_set_flags(
- 					tfm, CRYPTO_TFM_REQ_WEAK_KEY);
--			key = cipher_tv[i].key;
-+			key = cipher_tv->key;
++/**
++ *	sl82c105_qc_defer	-	implement serialization
++ *	@qc: command
++ *
++ *	We must issue one command per host not per channel because
++ *	of the reset bug.
++ *
++ *	Q: is the scsi host lock sufficient ?
++ */
++
++static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
++{
++	struct ata_host *host = qc->ap->host;
++	struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
++	int rc;
++
++	/* First apply the usual rules */	
++	rc = ata_std_qc_defer(qc);
++	if (rc != 0)
++		return rc;
++
++	/* Now apply serialization rules. Only allow a command if the
++	   other channel state machine is idle */
++	if (alt && alt->qc_active)
++		return	ATA_DEFER_PORT;
++	return 0;
++}
++
+ static struct scsi_host_template sl82c105_sht = {
+ 	.module			= THIS_MODULE,
+ 	.name			= DRV_NAME,
+@@ -245,6 +273,7 @@ static struct ata_port_operations sl82c105_port_ops = {
+ 	.bmdma_stop	= sl82c105_bmdma_stop,
+ 	.bmdma_status 	= ata_bmdma_status,
  
- 			ret = crypto_ablkcipher_setkey(tfm, key,
--						       cipher_tv[i].klen);
-+						       cipher_tv->klen);
- 			if (ret) {
- 				printk("setkey() failed flags=%x\n",
- 				       crypto_ablkcipher_get_flags(tfm));
++	.qc_defer	= sl82c105_qc_defer,
+ 	.qc_prep 	= ata_qc_prep,
+ 	.qc_issue	= ata_qc_issue_prot,
  
--				if (!cipher_tv[i].fail)
-+				if (!cipher_tv->fail)
- 					goto out;
- 			}
+@@ -312,7 +341,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
+ 	};
+ 	/* for now use only the first port */
+ 	const struct ata_port_info *ppi[] = { &info_early,
+-					       &ata_dummy_port_info };
++					       NULL };
+ 	u32 val;
+ 	int rev;
  
- 			temp = 0;
--			sg_init_table(sg, cipher_tv[i].np);
--			for (k = 0; k < cipher_tv[i].np; k++) {
-+			sg_init_table(sg, cipher_tv->np);
-+			for (k = 0; k < cipher_tv->np; k++) {
- 				memcpy(&xbuf[IDX[k]],
--				       cipher_tv[i].input + temp,
--				       cipher_tv[i].tap[k]);
--				temp += cipher_tv[i].tap[k];
-+				       cipher_tv->input + temp,
-+				       cipher_tv->tap[k]);
-+				temp += cipher_tv->tap[k];
- 				sg_set_buf(&sg[k], &xbuf[IDX[k]],
--					   cipher_tv[i].tap[k]);
-+					   cipher_tv->tap[k]);
- 			}
+diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
+index 453d72b..39627ab 100644
+--- a/drivers/ata/pata_via.c
++++ b/drivers/ata/pata_via.c
+@@ -185,7 +185,8 @@ static int via_cable_detect(struct ata_port *ap) {
+ 	if (ata66 & (0x10100000 >> (16 * ap->port_no)))
+ 		return ATA_CBL_PATA80;
+ 	/* Check with ACPI so we can spot BIOS reported SATA bridges */
+-	if (ata_acpi_cbl_80wire(ap))
++	if (ata_acpi_init_gtm(ap) &&
++	    ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap)))
+ 		return ATA_CBL_PATA80;
+ 	return ATA_CBL_PATA40;
+ }
+diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
+index 7116a9e..99c92ed 100644
+--- a/drivers/ata/pata_winbond.c
++++ b/drivers/ata/pata_winbond.c
+@@ -92,29 +92,33 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
+ }
  
- 			ablkcipher_request_set_crypt(req, sg, sg,
--						     cipher_tv[i].ilen,
--						     cipher_tv[i].iv);
-+						     cipher_tv->ilen,
-+						     cipher_tv->iv);
  
- 			ret = enc ?
- 				crypto_ablkcipher_encrypt(req) :
-@@ -390,15 +625,15 @@ static void test_cipher(char *algo, int enc,
- 			}
+-static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
++static unsigned int winbond_data_xfer(struct ata_device *dev,
++			unsigned char *buf, unsigned int buflen, int rw)
+ {
+-	struct ata_port *ap = adev->link->ap;
++	struct ata_port *ap = dev->link->ap;
+ 	int slop = buflen & 3;
  
- 			temp = 0;
--			for (k = 0; k < cipher_tv[i].np; k++) {
-+			for (k = 0; k < cipher_tv->np; k++) {
- 				printk("page %u\n", k);
- 				q = kmap(sg_page(&sg[k])) + sg[k].offset;
--				hexdump(q, cipher_tv[i].tap[k]);
-+				hexdump(q, cipher_tv->tap[k]);
- 				printk("%s\n",
--					memcmp(q, cipher_tv[i].result + temp,
--						cipher_tv[i].tap[k]) ? "fail" :
-+					memcmp(q, cipher_tv->result + temp,
-+						cipher_tv->tap[k]) ? "fail" :
- 					"pass");
--				temp += cipher_tv[i].tap[k];
-+				temp += cipher_tv->tap[k];
+-	if (ata_id_has_dword_io(adev->id)) {
+-		if (write_data)
+-			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+-		else
++	if (ata_id_has_dword_io(dev->id)) {
++		if (rw == READ)
+ 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
++		else
++			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+ 
+ 		if (unlikely(slop)) {
+-			__le32 pad = 0;
+-			if (write_data) {
+-				memcpy(&pad, buf + buflen - slop, slop);
+-				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+-			} else {
++			u32 pad;
++			if (rw == READ) {
+ 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
+ 				memcpy(buf + buflen - slop, &pad, slop);
++			} else {
++				memcpy(&pad, buf + buflen - slop, slop);
++				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
  			}
++			buflen += 4 - slop;
  		}
- 	}
-@@ -800,7 +1035,8 @@ out:
- 	crypto_free_hash(tfm);
+ 	} else
+-		ata_data_xfer(adev, buf, buflen, write_data);
++		buflen = ata_data_xfer(dev, buf, buflen, rw);
++
++	return buflen;
  }
  
--static void test_deflate(void)
-+static void test_comp(char *algo, struct comp_testvec *ctemplate,
-+		       struct comp_testvec *dtemplate, int ctcount, int dtcount)
- {
- 	unsigned int i;
- 	char result[COMP_BUF_SIZE];
-@@ -808,25 +1044,26 @@ static void test_deflate(void)
- 	struct comp_testvec *tv;
- 	unsigned int tsize;
- 
--	printk("\ntesting deflate compression\n");
-+	printk("\ntesting %s compression\n", algo);
- 
--	tsize = sizeof (deflate_comp_tv_template);
-+	tsize = sizeof(struct comp_testvec);
-+	tsize *= ctcount;
- 	if (tsize > TVMEMSIZE) {
- 		printk("template (%u) too big for tvmem (%u)\n", tsize,
- 		       TVMEMSIZE);
- 		return;
- 	}
- 
--	memcpy(tvmem, deflate_comp_tv_template, tsize);
-+	memcpy(tvmem, ctemplate, tsize);
- 	tv = (void *)tvmem;
- 
--	tfm = crypto_alloc_comp("deflate", 0, CRYPTO_ALG_ASYNC);
-+	tfm = crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC);
- 	if (IS_ERR(tfm)) {
--		printk("failed to load transform for deflate\n");
-+		printk("failed to load transform for %s\n", algo);
- 		return;
- 	}
+ static struct scsi_host_template winbond_sht = {
+@@ -191,7 +195,7 @@ static __init int winbond_init_one(unsigned long port)
+ 	reg = winbond_readcfg(port, 0x81);
  
--	for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) {
-+	for (i = 0; i < ctcount; i++) {
- 		int ilen, ret, dlen = COMP_BUF_SIZE;
+ 	if (!(reg & 0x03))		/* Disabled */
+-		return 0;
++		return -ENODEV;
  
- 		printk("test %u:\n", i + 1);
-@@ -845,19 +1082,20 @@ static void test_deflate(void)
- 		       ilen, dlen);
- 	}
+ 	for (i = 0; i < 2 ; i ++) {
+ 		unsigned long cmd_port = 0x1F0 - (0x80 * i);
+diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
+index bd4c2a3..8e1b7e9 100644
+--- a/drivers/ata/pdc_adma.c
++++ b/drivers/ata/pdc_adma.c
+@@ -321,8 +321,9 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)
+ 	u8  *buf = pp->pkt, *last_buf = NULL;
+ 	int i = (2 + buf[3]) * 8;
+ 	u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
++	unsigned int si;
  
--	printk("\ntesting deflate decompression\n");
-+	printk("\ntesting %s decompression\n", algo);
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		u32 addr;
+ 		u32 len;
  
--	tsize = sizeof (deflate_decomp_tv_template);
-+	tsize = sizeof(struct comp_testvec);
-+	tsize *= dtcount;
- 	if (tsize > TVMEMSIZE) {
- 		printk("template (%u) too big for tvmem (%u)\n", tsize,
- 		       TVMEMSIZE);
- 		goto out;
- 	}
+@@ -455,7 +456,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
+ 		adma_packet_start(qc);
+ 		return 0;
  
--	memcpy(tvmem, deflate_decomp_tv_template, tsize);
-+	memcpy(tvmem, dtemplate, tsize);
- 	tv = (void *)tvmem;
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		BUG();
+ 		break;
  
--	for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
-+	for (i = 0; i < dtcount; i++) {
- 		int ilen, ret, dlen = COMP_BUF_SIZE;
+diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
+index d015b4a..922d7b2 100644
+--- a/drivers/ata/sata_fsl.c
++++ b/drivers/ata/sata_fsl.c
+@@ -333,13 +333,14 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
+ 	struct prde *prd_ptr_to_indirect_ext = NULL;
+ 	unsigned indirect_ext_segment_sz = 0;
+ 	dma_addr_t indirect_ext_segment_paddr;
++	unsigned int si;
  
- 		printk("test %u:\n", i + 1);
-@@ -918,6 +1156,8 @@ static void do_test(void)
+ 	VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
  
- 		test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
+ 	indirect_ext_segment_paddr = cmd_desc_paddr +
+ 	    SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
  
-+		test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
-+
- 		test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		dma_addr_t sg_addr = sg_dma_address(sg);
+ 		u32 sg_len = sg_dma_len(sg);
  
- 		//BLOWFISH
-@@ -969,6 +1209,18 @@ static void do_test(void)
- 			    AES_XTS_ENC_TEST_VECTORS);
- 		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
- 			    AES_XTS_DEC_TEST_VECTORS);
-+		test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template,
-+			    AES_CTR_ENC_TEST_VECTORS);
-+		test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template,
-+			    AES_CTR_DEC_TEST_VECTORS);
-+		test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template,
-+			  AES_GCM_ENC_TEST_VECTORS);
-+		test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template,
-+			  AES_GCM_DEC_TEST_VECTORS);
-+		test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template,
-+			  AES_CCM_ENC_TEST_VECTORS);
-+		test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template,
-+			  AES_CCM_DEC_TEST_VECTORS);
+@@ -417,7 +418,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
+ 	}
  
- 		//CAST5
- 		test_cipher("ecb(cast5)", ENCRYPT, cast5_enc_tv_template,
-@@ -1057,12 +1309,18 @@ static void do_test(void)
- 		test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
- 		test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
- 		test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
--		test_deflate();
-+		test_comp("deflate", deflate_comp_tv_template,
-+			  deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS,
-+			  DEFLATE_DECOMP_TEST_VECTORS);
-+		test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template,
-+			  LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS);
- 		test_hash("crc32c", crc32c_tv_template, CRC32C_TEST_VECTORS);
- 		test_hash("hmac(md5)", hmac_md5_tv_template,
- 			  HMAC_MD5_TEST_VECTORS);
- 		test_hash("hmac(sha1)", hmac_sha1_tv_template,
- 			  HMAC_SHA1_TEST_VECTORS);
-+		test_hash("hmac(sha224)", hmac_sha224_tv_template,
-+			  HMAC_SHA224_TEST_VECTORS);
- 		test_hash("hmac(sha256)", hmac_sha256_tv_template,
- 			  HMAC_SHA256_TEST_VECTORS);
- 		test_hash("hmac(sha384)", hmac_sha384_tv_template,
-@@ -1156,6 +1414,10 @@ static void do_test(void)
- 			    AES_XTS_ENC_TEST_VECTORS);
- 		test_cipher("xts(aes)", DECRYPT, aes_xts_dec_tv_template,
- 			    AES_XTS_DEC_TEST_VECTORS);
-+		test_cipher("rfc3686(ctr(aes))", ENCRYPT, aes_ctr_enc_tv_template,
-+			    AES_CTR_ENC_TEST_VECTORS);
-+		test_cipher("rfc3686(ctr(aes))", DECRYPT, aes_ctr_dec_tv_template,
-+			    AES_CTR_DEC_TEST_VECTORS);
- 		break;
+ 	/* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
+-	if (is_atapi_taskfile(&qc->tf)) {
++	if (ata_is_atapi(qc->tf.protocol)) {
+ 		desc_info |= ATAPI_CMD;
+ 		memset((void *)&cd->acmd, 0, 32);
+ 		memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
+diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
+index 323c087..59e65ed 100644
+--- a/drivers/ata/sata_inic162x.c
++++ b/drivers/ata/sata_inic162x.c
+@@ -108,17 +108,6 @@ struct inic_port_priv {
+ 	u8	cached_pirq_mask;
+ };
  
- 	case 11:
-@@ -1167,7 +1429,9 @@ static void do_test(void)
- 		break;
+-static int inic_slave_config(struct scsi_device *sdev)
+-{
+-	/* This controller is braindamaged.  dma_boundary is 0xffff
+-	 * like others but it will lock up the whole machine HARD if
+-	 * 65536 byte PRD entry is fed.  Reduce maximum segment size.
+-	 */
+-	blk_queue_max_segment_size(sdev->request_queue, 65536 - 512);
+-
+-	return ata_scsi_slave_config(sdev);
+-}
+-
+ static struct scsi_host_template inic_sht = {
+ 	.module			= THIS_MODULE,
+ 	.name			= DRV_NAME,
+@@ -132,7 +121,7 @@ static struct scsi_host_template inic_sht = {
+ 	.use_clustering		= ATA_SHT_USE_CLUSTERING,
+ 	.proc_name		= DRV_NAME,
+ 	.dma_boundary		= ATA_DMA_BOUNDARY,
+-	.slave_configure	= inic_slave_config,
++	.slave_configure	= ata_scsi_slave_config,
+ 	.slave_destroy		= ata_scsi_slave_destroy,
+ 	.bios_param		= ata_std_bios_param,
+ };
+@@ -585,7 +574,7 @@ static struct ata_port_operations inic_port_ops = {
+ };
  
- 	case 13:
--		test_deflate();
-+		test_comp("deflate", deflate_comp_tv_template,
-+			  deflate_decomp_tv_template, DEFLATE_COMP_TEST_VECTORS,
-+			  DEFLATE_DECOMP_TEST_VECTORS);
- 		break;
+ static struct ata_port_info inic_port_info = {
+-	/* For some reason, ATA_PROT_ATAPI is broken on this
++	/* For some reason, ATAPI_PROT_PIO is broken on this
+ 	 * controller, and no, PIO_POLLING does't fix it.  It somehow
+ 	 * manages to report the wrong ireason and ignoring ireason
+ 	 * results in machine lock up.  Tell libata to always prefer
+@@ -730,6 +719,18 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		return rc;
+ 	}
  
- 	case 14:
-@@ -1291,6 +1555,34 @@ static void do_test(void)
- 			    camellia_cbc_dec_tv_template,
- 			    CAMELLIA_CBC_DEC_TEST_VECTORS);
- 		break;
-+	case 33:
-+		test_hash("sha224", sha224_tv_template, SHA224_TEST_VECTORS);
-+		break;
-+
-+	case 34:
-+		test_cipher("salsa20", ENCRYPT,
-+			    salsa20_stream_enc_tv_template,
-+			    SALSA20_STREAM_ENC_TEST_VECTORS);
-+		break;
-+
-+	case 35:
-+		test_aead("gcm(aes)", ENCRYPT, aes_gcm_enc_tv_template,
-+			  AES_GCM_ENC_TEST_VECTORS);
-+		test_aead("gcm(aes)", DECRYPT, aes_gcm_dec_tv_template,
-+			  AES_GCM_DEC_TEST_VECTORS);
-+		break;
-+
-+	case 36:
-+		test_comp("lzo", lzo_comp_tv_template, lzo_decomp_tv_template,
-+			  LZO_COMP_TEST_VECTORS, LZO_DECOMP_TEST_VECTORS);
-+		break;
++	/*
++	 * This controller is braindamaged.  dma_boundary is 0xffff
++	 * like others but it will lock up the whole machine HARD if
++	 * 65536 byte PRD entry is fed. Reduce maximum segment size.
++	 */
++	rc = pci_set_dma_max_seg_size(pdev, 65536 - 512);
++	if (rc) {
++		dev_printk(KERN_ERR, &pdev->dev,
++			   "failed to set the maximum segment size.\n");
++		return rc;
++	}
 +
-+	case 37:
-+		test_aead("ccm(aes)", ENCRYPT, aes_ccm_enc_tv_template,
-+			  AES_CCM_ENC_TEST_VECTORS);
-+		test_aead("ccm(aes)", DECRYPT, aes_ccm_dec_tv_template,
-+			  AES_CCM_DEC_TEST_VECTORS);
-+		break;
- 
- 	case 100:
- 		test_hash("hmac(md5)", hmac_md5_tv_template,
-@@ -1317,6 +1609,15 @@ static void do_test(void)
- 			  HMAC_SHA512_TEST_VECTORS);
- 		break;
+ 	rc = init_controller(iomap[MMIO_BAR], hpriv->cached_hctl);
+ 	if (rc) {
+ 		dev_printk(KERN_ERR, &pdev->dev,
+diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
+index 37b850a..3c1b5c9 100644
+--- a/drivers/ata/sata_mv.c
++++ b/drivers/ata/sata_mv.c
+@@ -29,7 +29,13 @@
+   I distinctly remember a couple workarounds (one related to PCI-X)
+   are still needed.
  
-+	case 105:
-+		test_hash("hmac(sha224)", hmac_sha224_tv_template,
-+			  HMAC_SHA224_TEST_VECTORS);
-+		break;
+-  4) Add NCQ support (easy to intermediate, once new-EH support appears)
++  2) Improve/fix IRQ and error handling sequences.
 +
-+	case 106:
-+		test_hash("xcbc(aes)", aes_xcbc128_tv_template,
-+			  XCBC_AES_TEST_VECTORS);
-+		break;
- 
- 	case 200:
- 		test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0,
-@@ -1400,6 +1701,11 @@ static void do_test(void)
- 				camellia_speed_template);
- 		break;
- 
-+	case 206:
-+		test_cipher_speed("salsa20", ENCRYPT, sec, NULL, 0,
-+				  salsa20_speed_template);
-+		break;
++  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
 +
- 	case 300:
- 		/* fall through */
++  4) Think about TCQ support here, and for libata in general
++  with controllers that suppport it via host-queuing hardware
++  (a software-only implementation could be a nightmare).
  
-@@ -1451,6 +1757,10 @@ static void do_test(void)
- 		test_hash_speed("tgr192", sec, generic_hash_speed_template);
- 		if (mode > 300 && mode < 400) break;
+   5) Investigate problems with PCI Message Signalled Interrupts (MSI).
  
-+	case 313:
-+		test_hash_speed("sha224", sec, generic_hash_speed_template);
-+		if (mode > 300 && mode < 400) break;
-+
- 	case 399:
- 		break;
+@@ -53,8 +59,6 @@
+   Target mode, for those without docs, is the ability to directly
+   connect two SATA controllers.
  
-@@ -1467,20 +1777,21 @@ static void do_test(void)
+-  13) Verify that 7042 is fully supported.  I only have a 6042.
+-
+ */
  
- static int __init init(void)
- {
-+	int err = -ENOMEM;
-+
- 	tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
- 	if (tvmem == NULL)
--		return -ENOMEM;
-+		return err;
  
- 	xbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
--	if (xbuf == NULL) {
--		kfree(tvmem);
--		return -ENOMEM;
--	}
-+	if (xbuf == NULL)
-+		goto err_free_tv;
+@@ -73,7 +77,7 @@
+ #include <linux/libata.h>
  
--	do_test();
-+	axbuf = kmalloc(XBUFSIZE, GFP_KERNEL);
-+	if (axbuf == NULL)
-+		goto err_free_xbuf;
+ #define DRV_NAME	"sata_mv"
+-#define DRV_VERSION	"1.01"
++#define DRV_VERSION	"1.20"
  
--	kfree(xbuf);
--	kfree(tvmem);
-+	do_test();
+ enum {
+ 	/* BAR's are enumerated in terms of pci_resource_start() terms */
+@@ -107,14 +111,12 @@ enum {
  
- 	/* We intentionaly return -EAGAIN to prevent keeping
- 	 * the module. It does all its work from init()
-@@ -1488,7 +1799,15 @@ static int __init init(void)
- 	 * => we don't need it in the memory, do we?
- 	 *                                        -- mludvig
+ 	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
+ 	 * CRPB needs alignment on a 256B boundary. Size == 256B
+-	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
+ 	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
  	 */
--	return -EAGAIN;
-+	err = -EAGAIN;
-+
-+	kfree(axbuf);
-+ err_free_xbuf:
-+	kfree(xbuf);
-+ err_free_tv:
-+	kfree(tvmem);
-+
-+	return err;
- }
+ 	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
+ 	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
+-	MV_MAX_SG_CT		= 176,
++	MV_MAX_SG_CT		= 256,
+ 	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
+-	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
  
- /*
-diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
-index ec86138..f785e56 100644
---- a/crypto/tcrypt.h
-+++ b/crypto/tcrypt.h
-@@ -6,12 +6,15 @@
-  *
-  * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
-  * Copyright (c) 2002 Jean-Francois Dive <jef at linuxbe.org>
-+ * Copyright (c) 2007 Nokia Siemens Networks
-  *
-  * 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.
-  *
-+ * 2007-11-13 Added GCM tests
-+ * 2007-11-13 Added AEAD support
-  * 2006-12-07 Added SHA384 HMAC and SHA512 HMAC tests
-  * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk at vantronix.net>
-  * 2003-09-14 Changes by Kartikey Mahendra Bhatt
-@@ -40,14 +43,32 @@ struct hash_testvec {
- struct cipher_testvec {
- 	char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
- 	char iv[MAX_IVLEN];
-+	char input[4100];
-+	char result[4100];
-+	unsigned char tap[MAX_TAP];
-+	int np;
-+	unsigned char fail;
-+	unsigned char wk; /* weak key flag */
-+	unsigned char klen;
-+	unsigned short ilen;
-+	unsigned short rlen;
-+};
+ 	MV_PORTS_PER_HC		= 4,
+ 	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
+@@ -125,6 +127,9 @@ enum {
+ 	/* Host Flags */
+ 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
+ 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
++	/* SoC integrated controllers, no PCI interface */
++	MV_FLAG_SOC = (1 << 28),
 +
-+struct aead_testvec {
-+	char key[MAX_KEYLEN] __attribute__ ((__aligned__(4)));
-+	char iv[MAX_IVLEN];
- 	char input[512];
-+	char assoc[512];
- 	char result[512];
- 	unsigned char tap[MAX_TAP];
-+	unsigned char atap[MAX_TAP];
- 	int np;
-+	int anp;
- 	unsigned char fail;
- 	unsigned char wk; /* weak key flag */
- 	unsigned char klen;
- 	unsigned short ilen;
-+	unsigned short alen;
- 	unsigned short rlen;
- };
+ 	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
+ 				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
+ 				  ATA_FLAG_PIO_POLLING,
+@@ -170,7 +175,7 @@ enum {
  
-@@ -173,6 +194,33 @@ static struct hash_testvec sha1_tv_template[] = {
- 	}
- };
+ 	PCIE_IRQ_CAUSE_OFS	= 0x1900,
+ 	PCIE_IRQ_MASK_OFS	= 0x1910,
+-	PCIE_UNMASK_ALL_IRQS	= 0x70a,	/* assorted bits */
++	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
+ 
+ 	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
+ 	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
+@@ -210,6 +215,7 @@ enum {
+ 	/* SATA registers */
+ 	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
+ 	SATA_ACTIVE_OFS		= 0x350,
++	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
+ 	PHY_MODE3		= 0x310,
+ 	PHY_MODE4		= 0x314,
+ 	PHY_MODE2		= 0x330,
+@@ -222,11 +228,11 @@ enum {
+ 
+ 	/* Port registers */
+ 	EDMA_CFG_OFS		= 0,
+-	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
+-	EDMA_CFG_NCQ		= (1 << 5),
+-	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
+-	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
+-	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
++	EDMA_CFG_Q_DEPTH	= 0x1f,		/* max device queue depth */
++	EDMA_CFG_NCQ		= (1 << 5),	/* for R/W FPDMA queued */
++	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
++	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
++	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
  
+ 	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
+ 	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
+@@ -244,14 +250,33 @@ enum {
+ 	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
+ 	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
+ 	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
 +
-+/*
-+ * SHA224 test vectors from from FIPS PUB 180-2
-+ */
-+#define SHA224_TEST_VECTORS     2
+ 	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
+-	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
++	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
++	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
++	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
++	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
 +
-+static struct hash_testvec sha224_tv_template[] = {
-+	{
-+		.plaintext = "abc",
-+		.psize  = 3,
-+		.digest = { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
-+			0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
-+			0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
-+			0xE3, 0x6C, 0x9D, 0xA7},
-+	}, {
-+		.plaintext =
-+		"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
-+		.psize  = 56,
-+		.digest = { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
-+			0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
-+			0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
-+			0x52, 0x52, 0x25, 0x25 },
-+		.np     = 2,
-+		.tap    = { 28, 28 }
-+	}
-+};
+ 	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
 +
- /*
-  * SHA256 test vectors from from NIST
-  */
-@@ -817,6 +865,121 @@ static struct hash_testvec hmac_sha1_tv_template[] = {
- 	},
- };
- 
+ 	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
++	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
++	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
++	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
++	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
++	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
 +
-+/*
-+ * SHA224 HMAC test vectors from RFC4231
-+ */
-+#define HMAC_SHA224_TEST_VECTORS    4
+ 	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
 +
-+static struct hash_testvec hmac_sha224_tv_template[] = {
-+	{
-+		.key    = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-+			0x0b, 0x0b, 0x0b, 0x0b },
-+		.ksize  = 20,
-+		/*  ("Hi There") */
-+		.plaintext = { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65 },
-+		.psize  = 8,
-+		.digest = { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19,
-+			0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f,
-+			0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f,
-+			0x53, 0x68, 0x4b, 0x22},
-+	}, {
-+		.key    = { 0x4a, 0x65, 0x66, 0x65 }, /* ("Jefe") */
-+		.ksize  = 4,
-+		/* ("what do ya want for nothing?") */
-+		.plaintext = { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
-+			0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
-+			0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
-+			0x69, 0x6e, 0x67, 0x3f },
-+		.psize  = 28,
-+		.digest = { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf,
-+			0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f,
-+			0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00,
-+			0x8f, 0xd0, 0x5e, 0x44 },
-+		.np = 4,
-+		.tap    = { 7, 7, 7, 7 }
-+	}, {
-+		.key    = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa },
-+		.ksize  = 131,
-+		/* ("Test Using Larger Than Block-Size Key - Hash Key First") */
-+		.plaintext = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x55, 0x73, 0x69,
-+			0x6e, 0x67, 0x20, 0x4c, 0x61, 0x72, 0x67, 0x65,
-+			0x72, 0x20, 0x54, 0x68, 0x61, 0x6e, 0x20, 0x42,
-+			0x6c, 0x6f, 0x63, 0x6b, 0x2d, 0x53, 0x69, 0x7a,
-+			0x65, 0x20, 0x4b, 0x65, 0x79, 0x20, 0x2d, 0x20,
-+			0x48, 0x61, 0x73, 0x68, 0x20, 0x4b, 0x65, 0x79,
-+			0x20, 0x46, 0x69, 0x72, 0x73, 0x74 },
-+		.psize  = 54,
-+		.digest = { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad,
-+			0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2,
-+			0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27,
-+			0x3f, 0xa6, 0x87, 0x0e },
-+	}, {
-+		.key    = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
-+			0xaa, 0xaa, 0xaa },
-+		.ksize  = 131,
-+		/* ("This is a test using a larger than block-size key and a")
-+		(" larger than block-size data. The key needs to be")
-+			(" hashed before being used by the HMAC algorithm.") */
-+		.plaintext = { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
-+			0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75,
-+			0x73, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6c,
-+			0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74, 0x68,
-+			0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
-+			0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x6b, 0x65,
-+			0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x20,
-+			0x6c, 0x61, 0x72, 0x67, 0x65, 0x72, 0x20, 0x74,
-+			0x68, 0x61, 0x6e, 0x20, 0x62, 0x6c, 0x6f, 0x63,
-+			0x6b, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x64,
-+			0x61, 0x74, 0x61, 0x2e, 0x20, 0x54, 0x68, 0x65,
-+			0x20, 0x6b, 0x65, 0x79, 0x20, 0x6e, 0x65, 0x65,
-+			0x64, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65,
-+			0x20, 0x68, 0x61, 0x73, 0x68, 0x65, 0x64, 0x20,
-+			0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x62,
-+			0x65, 0x69, 0x6e, 0x67, 0x20, 0x75, 0x73, 0x65,
-+			0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65,
-+			0x20, 0x48, 0x4d, 0x41, 0x43, 0x20, 0x61, 0x6c,
-+			0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x2e },
-+		.psize  = 152,
-+		.digest = { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02,
-+			0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd,
-+			0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9,
-+			0xf6, 0xf5, 0x65, 0xd1 },
-+	},
-+};
+ 	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
+ 	EDMA_ERR_OVERRUN_5	= (1 << 5),
+ 	EDMA_ERR_UNDERRUN_5	= (1 << 6),
 +
- /*
-  * HMAC-SHA256 test vectors from
-  * draft-ietf-ipsec-ciph-sha-256-01.txt
-@@ -2140,12 +2303,18 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
-  */
- #define AES_ENC_TEST_VECTORS 3
- #define AES_DEC_TEST_VECTORS 3
--#define AES_CBC_ENC_TEST_VECTORS 2
--#define AES_CBC_DEC_TEST_VECTORS 2
-+#define AES_CBC_ENC_TEST_VECTORS 4
-+#define AES_CBC_DEC_TEST_VECTORS 4
- #define AES_LRW_ENC_TEST_VECTORS 8
- #define AES_LRW_DEC_TEST_VECTORS 8
- #define AES_XTS_ENC_TEST_VECTORS 4
- #define AES_XTS_DEC_TEST_VECTORS 4
-+#define AES_CTR_ENC_TEST_VECTORS 7
-+#define AES_CTR_DEC_TEST_VECTORS 6
-+#define AES_GCM_ENC_TEST_VECTORS 9
-+#define AES_GCM_DEC_TEST_VECTORS 8
-+#define AES_CCM_ENC_TEST_VECTORS 7
-+#define AES_CCM_DEC_TEST_VECTORS 7
++	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
++				  EDMA_ERR_LNK_CTRL_RX_1 |
++				  EDMA_ERR_LNK_CTRL_RX_3 |
++				  EDMA_ERR_LNK_CTRL_TX,
++
+ 	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
+ 				  EDMA_ERR_PRD_PAR |
+ 				  EDMA_ERR_DEV_DCON |
+@@ -311,12 +336,14 @@ enum {
  
- static struct cipher_testvec aes_enc_tv_template[] = {
- 	{ /* From FIPS-197 */
-@@ -2249,6 +2418,57 @@ static struct cipher_testvec aes_cbc_enc_tv_template[] = {
- 			    0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9,
- 			    0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 },
- 		.rlen   = 32,
-+	}, { /* From NIST SP800-38A */
-+		.key	= { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
-+			    0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
-+			    0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
-+		.klen	= 24,
-+		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-+		.input	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-+			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-+			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
-+			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-+			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-+			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-+			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
-+			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
-+		.ilen	= 64,
-+		.result	= { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
-+			    0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
-+			    0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
-+			    0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
-+			    0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
-+			    0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
-+			    0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
-+			    0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
-+		.rlen	= 64,
-+	}, {
-+		.key	= { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
-+			    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
-+			    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
-+			    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
-+		.klen	= 32,
-+		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-+		.input	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-+			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-+			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
-+			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-+			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-+			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-+			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
-+			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
-+		.ilen	= 64,
-+		.result	= { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
-+			    0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
-+			    0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
-+			    0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
-+			    0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
-+			    0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
-+			    0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
-+			    0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
-+		.rlen	= 64,
- 	},
+ 	/* Port private flags (pp_flags) */
+ 	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
++	MV_PP_FLAG_NCQ_EN	= (1 << 1),	/* is EDMA set up for NCQ? */
+ 	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
  };
  
-@@ -2280,6 +2500,57 @@ static struct cipher_testvec aes_cbc_dec_tv_template[] = {
- 			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
- 		.rlen   = 32,
-+	}, { /* From NIST SP800-38A */
-+		.key	= { 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52,
-+			    0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5,
-+			    0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b },
-+		.klen	= 24,
-+		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-+		.input	= { 0x4f, 0x02, 0x1d, 0xb2, 0x43, 0xbc, 0x63, 0x3d,
-+			    0x71, 0x78, 0x18, 0x3a, 0x9f, 0xa0, 0x71, 0xe8,
-+			    0xb4, 0xd9, 0xad, 0xa9, 0xad, 0x7d, 0xed, 0xf4,
-+			    0xe5, 0xe7, 0x38, 0x76, 0x3f, 0x69, 0x14, 0x5a,
-+			    0x57, 0x1b, 0x24, 0x20, 0x12, 0xfb, 0x7a, 0xe0,
-+			    0x7f, 0xa9, 0xba, 0xac, 0x3d, 0xf1, 0x02, 0xe0,
-+			    0x08, 0xb0, 0xe2, 0x79, 0x88, 0x59, 0x88, 0x81,
-+			    0xd9, 0x20, 0xa9, 0xe6, 0x4f, 0x56, 0x15, 0xcd },
-+		.ilen	= 64,
-+		.result	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-+			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-+			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
-+			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-+			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-+			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-+			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
-+			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
-+		.rlen	= 64,
-+	}, {
-+		.key	= { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe,
-+			    0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
-+			    0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7,
-+			    0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 },
-+		.klen	= 32,
-+		.iv	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
-+		.input	= { 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba,
-+			    0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
-+			    0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d,
-+			    0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
-+			    0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf,
-+			    0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
-+			    0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc,
-+			    0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b },
-+		.ilen	= 64,
-+		.result	= { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
-+			    0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
-+			    0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
-+			    0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
-+			    0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
-+			    0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
-+			    0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17,
-+			    0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 },
-+		.rlen	= 64,
- 	},
- };
+ #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
+ #define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
+ #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
++#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
  
-@@ -3180,6 +3451,1843 @@ static struct cipher_testvec aes_xts_dec_tv_template[] = {
- 	}
- };
+ enum {
+ 	/* DMA boundary 0xffff is required by the s/g splitting
+@@ -379,8 +406,8 @@ struct mv_port_priv {
+ 	dma_addr_t		crqb_dma;
+ 	struct mv_crpb		*crpb;
+ 	dma_addr_t		crpb_dma;
+-	struct mv_sg		*sg_tbl;
+-	dma_addr_t		sg_tbl_dma;
++	struct mv_sg		*sg_tbl[MV_MAX_Q_DEPTH];
++	dma_addr_t		sg_tbl_dma[MV_MAX_Q_DEPTH];
  
+ 	unsigned int		req_idx;
+ 	unsigned int		resp_idx;
+@@ -400,6 +427,14 @@ struct mv_host_priv {
+ 	u32			irq_cause_ofs;
+ 	u32			irq_mask_ofs;
+ 	u32			unmask_all_irqs;
++	/*
++	 * These consistent DMA memory pools give us guaranteed
++	 * alignment for hardware-accessed data structures,
++	 * and less memory waste in accomplishing the alignment.
++	 */
++	struct dma_pool		*crqb_pool;
++	struct dma_pool		*crpb_pool;
++	struct dma_pool		*sg_tbl_pool;
+ };
+ 
+ struct mv_hw_ops {
+@@ -411,7 +446,7 @@ struct mv_hw_ops {
+ 	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			unsigned int n_hc);
+ 	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
+-	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
++	void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
+ };
+ 
+ static void mv_irq_clear(struct ata_port *ap);
+@@ -425,10 +460,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc);
+ static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
+ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
+ static void mv_error_handler(struct ata_port *ap);
+-static void mv_post_int_cmd(struct ata_queued_cmd *qc);
+ static void mv_eh_freeze(struct ata_port *ap);
+ static void mv_eh_thaw(struct ata_port *ap);
+-static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
++static void mv6_dev_config(struct ata_device *dev);
+ 
+ static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			   unsigned int port);
+@@ -438,7 +472,7 @@ static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
+ static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			unsigned int n_hc);
+ static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
+-static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
++static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio);
+ 
+ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			   unsigned int port);
+@@ -448,10 +482,17 @@ static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
+ static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			unsigned int n_hc);
+ static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
+-static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
++static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
+ static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 			     unsigned int port_no);
++static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
++			void __iomem *port_mmio, int want_ncq);
++static int __mv_stop_dma(struct ata_port *ap);
+ 
++/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
++ * because we have to allow room for worst case splitting of
++ * PRDs for 64K boundaries in mv_fill_sg().
++ */
+ static struct scsi_host_template mv5_sht = {
+ 	.module			= THIS_MODULE,
+ 	.name			= DRV_NAME,
+@@ -475,7 +516,8 @@ static struct scsi_host_template mv6_sht = {
+ 	.name			= DRV_NAME,
+ 	.ioctl			= ata_scsi_ioctl,
+ 	.queuecommand		= ata_scsi_queuecmd,
+-	.can_queue		= ATA_DEF_QUEUE,
++	.change_queue_depth	= ata_scsi_change_queue_depth,
++	.can_queue		= MV_MAX_Q_DEPTH - 1,
+ 	.this_id		= ATA_SHT_THIS_ID,
+ 	.sg_tablesize		= MV_MAX_SG_CT / 2,
+ 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
+@@ -505,7 +547,6 @@ static const struct ata_port_operations mv5_ops = {
+ 	.irq_on			= ata_irq_on,
+ 
+ 	.error_handler		= mv_error_handler,
+-	.post_internal_cmd	= mv_post_int_cmd,
+ 	.freeze			= mv_eh_freeze,
+ 	.thaw			= mv_eh_thaw,
+ 
+@@ -517,6 +558,7 @@ static const struct ata_port_operations mv5_ops = {
+ };
+ 
+ static const struct ata_port_operations mv6_ops = {
++	.dev_config             = mv6_dev_config,
+ 	.tf_load		= ata_tf_load,
+ 	.tf_read		= ata_tf_read,
+ 	.check_status		= ata_check_status,
+@@ -533,9 +575,9 @@ static const struct ata_port_operations mv6_ops = {
+ 	.irq_on			= ata_irq_on,
+ 
+ 	.error_handler		= mv_error_handler,
+-	.post_internal_cmd	= mv_post_int_cmd,
+ 	.freeze			= mv_eh_freeze,
+ 	.thaw			= mv_eh_thaw,
++	.qc_defer		= ata_std_qc_defer,
+ 
+ 	.scr_read		= mv_scr_read,
+ 	.scr_write		= mv_scr_write,
+@@ -561,9 +603,9 @@ static const struct ata_port_operations mv_iie_ops = {
+ 	.irq_on			= ata_irq_on,
+ 
+ 	.error_handler		= mv_error_handler,
+-	.post_internal_cmd	= mv_post_int_cmd,
+ 	.freeze			= mv_eh_freeze,
+ 	.thaw			= mv_eh_thaw,
++	.qc_defer		= ata_std_qc_defer,
+ 
+ 	.scr_read		= mv_scr_read,
+ 	.scr_write		= mv_scr_write,
+@@ -592,26 +634,29 @@ static const struct ata_port_info mv_port_info[] = {
+ 		.port_ops	= &mv5_ops,
+ 	},
+ 	{  /* chip_604x */
+-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
++		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &mv6_ops,
+ 	},
+ 	{  /* chip_608x */
+ 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
+-				  MV_FLAG_DUAL_HC,
++				  ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &mv6_ops,
+ 	},
+ 	{  /* chip_6042 */
+-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
++		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &mv_iie_ops,
+ 	},
+ 	{  /* chip_7042 */
+-		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
++		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
++				  ATA_FLAG_NCQ,
+ 		.pio_mask	= 0x1f,	/* pio0-4 */
+ 		.udma_mask	= ATA_UDMA6,
+ 		.port_ops	= &mv_iie_ops,
+@@ -648,13 +693,6 @@ static const struct pci_device_id mv_pci_tbl[] = {
+ 	{ }			/* terminate list */
+ };
+ 
+-static struct pci_driver mv_pci_driver = {
+-	.name			= DRV_NAME,
+-	.id_table		= mv_pci_tbl,
+-	.probe			= mv_init_one,
+-	.remove			= ata_pci_remove_one,
+-};
+-
+ static const struct mv_hw_ops mv5xxx_ops = {
+ 	.phy_errata		= mv5_phy_errata,
+ 	.enable_leds		= mv5_enable_leds,
+@@ -674,45 +712,6 @@ static const struct mv_hw_ops mv6xxx_ops = {
+ };
+ 
+ /*
+- * module options
+- */
+-static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
+-
+-
+-/* move to PCI layer or libata core? */
+-static int pci_go_64(struct pci_dev *pdev)
+-{
+-	int rc;
+-
+-	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+-		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+-		if (rc) {
+-			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+-			if (rc) {
+-				dev_printk(KERN_ERR, &pdev->dev,
+-					   "64-bit DMA enable failed\n");
+-				return rc;
+-			}
+-		}
+-	} else {
+-		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+-		if (rc) {
+-			dev_printk(KERN_ERR, &pdev->dev,
+-				   "32-bit DMA enable failed\n");
+-			return rc;
+-		}
+-		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+-		if (rc) {
+-			dev_printk(KERN_ERR, &pdev->dev,
+-				   "32-bit consistent DMA enable failed\n");
+-			return rc;
+-		}
+-	}
+-
+-	return rc;
+-}
+-
+-/*
+  * Functions
+  */
+ 
+@@ -815,19 +814,46 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
+  *      LOCKING:
+  *      Inherited from caller.
+  */
+-static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
+-			 struct mv_port_priv *pp)
++static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
++			 struct mv_port_priv *pp, u8 protocol)
+ {
++	int want_ncq = (protocol == ATA_PROT_NCQ);
 +
-+static struct cipher_testvec aes_ctr_enc_tv_template[] = {
-+	{ /* From RFC 3686 */
-+		.key	= { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
-+			    0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
-+			    0x00, 0x00, 0x00, 0x30 },
-+		.klen	= 20,
-+		.iv 	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-+		.input 	= { "Single block msg" },
-+		.ilen	= 16,
-+		.result = { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
-+			    0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
-+		.rlen	= 16,
-+	}, {
-+		.key	= { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
-+			    0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
-+			    0x00, 0x6c, 0xb6, 0xdb },
-+		.klen	= 20,
-+		.iv 	= { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
-+		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-+		.ilen 	= 32,
-+		.result = { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
-+			    0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
-+			    0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
-+			    0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
-+		.rlen	= 32,
-+	}, {
-+		.key 	= { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
-+			    0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
-+			    0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
-+			    0x00, 0x00, 0x00, 0x48 },
-+		.klen 	= 28,
-+		.iv	= { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
-+		.input	= { "Single block msg" },
-+		.ilen 	= 16,
-+		.result	= { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
-+			    0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
-+		.rlen	= 16,
-+	}, {
-+		.key	= { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
-+			    0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
-+			    0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
-+			    0x00, 0x96, 0xb0, 0x3b },
-+		.klen	= 28,
-+		.iv 	= { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
-+		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-+		.ilen	= 32,
-+		.result	= { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
-+			    0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
-+			    0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
-+			    0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
-+		.rlen 	= 32,
-+	}, {
-+		.key 	= { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
-+			    0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
-+			    0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
-+			    0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
-+			    0x00, 0x00, 0x00, 0x60 },
-+		.klen	= 36,
-+		.iv 	= { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
-+		.input	= { "Single block msg" },
-+		.ilen	= 16,
-+		.result = { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
-+			    0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
-+		.rlen 	= 16,
-+	}, {
-+		.key	= { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
-+			    0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
-+			    0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
-+			    0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
-+			    0x00, 0xfa, 0xac, 0x24 },
-+		.klen 	= 36,
-+		.iv	= { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
-+		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-+		.ilen	= 32,
-+		.result = { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
-+			    0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
-+			    0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
-+			    0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
-+		.rlen	= 32,
-+	}, {
-+	// generated using Crypto++
-+		.key = {
-+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+			0x00, 0x00, 0x00, 0x00,
-+		},
-+		.klen = 32 + 4,
-+		.iv = {
-+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+		},
-+		.input = {
-+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
-+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
-+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
-+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-+			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-+			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-+			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-+			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-+			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-+			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-+			0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
-+			0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
-+			0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
-+			0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
-+			0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
-+			0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
-+			0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
-+			0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
-+			0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
-+			0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
-+			0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
-+			0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
-+			0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
-+			0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
-+			0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
-+			0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
-+			0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
-+			0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
-+			0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
-+			0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
-+			0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
-+			0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
-+			0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
-+			0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
-+			0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
-+			0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
-+			0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
-+			0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
-+			0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
-+			0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
-+			0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
-+			0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
-+			0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
-+			0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
-+			0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
-+			0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
-+			0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
-+			0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
-+			0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
-+			0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
-+			0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
-+			0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
-+			0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
-+			0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
-+			0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
-+			0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
-+			0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
-+			0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
-+			0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
-+			0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
-+			0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
-+			0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
-+			0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
-+			0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
-+			0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
-+			0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
-+			0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
-+			0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
-+			0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
-+			0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
-+			0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
-+			0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
-+			0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
-+			0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
-+			0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
-+			0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
-+			0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
-+			0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
-+			0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
-+			0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
-+			0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
-+			0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
-+			0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
-+			0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
-+			0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
-+			0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
-+			0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
-+			0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
-+			0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
-+			0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
-+			0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
-+			0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
-+			0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
-+			0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
-+			0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
-+			0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
-+			0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
-+			0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
-+			0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
-+			0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
-+			0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
-+			0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
-+			0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
-+			0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
-+			0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
-+			0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
-+			0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
-+			0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
-+			0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
-+			0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
-+			0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
-+			0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
-+			0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
-+			0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
-+			0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
-+			0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
-+			0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
-+			0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
-+			0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
-+			0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
-+			0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
-+			0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
-+			0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
-+			0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
-+			0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
-+			0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
-+			0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
-+			0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
-+			0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
-+			0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
-+			0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
-+			0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
-+			0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
-+			0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
-+			0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
-+			0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
-+			0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
-+			0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
-+			0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
-+			0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
-+			0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
-+			0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
-+			0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
-+			0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
-+			0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
-+			0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
-+			0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
-+			0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
-+			0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
-+			0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
-+			0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
-+			0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
-+			0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
-+			0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
-+			0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
-+			0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
-+			0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
-+			0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
-+			0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
-+			0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
-+			0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
-+			0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
-+			0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
-+			0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
-+			0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
-+			0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
-+			0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
-+			0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
-+			0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
-+			0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
-+			0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
-+			0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
-+			0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
-+			0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
-+			0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
-+			0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
-+			0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
-+			0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
-+			0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
-+			0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
-+			0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
-+			0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
-+			0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
-+			0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
-+			0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
-+			0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
-+			0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
-+			0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
-+			0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
-+			0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
-+			0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
-+			0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
-+			0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
-+			0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
-+			0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
-+			0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
-+			0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
-+			0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
-+			0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
-+			0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
-+			0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
-+			0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
-+			0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
-+			0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
-+			0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
-+			0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
-+			0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
-+			0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
-+			0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
-+			0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
-+			0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
-+			0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
-+			0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
-+			0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
-+			0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
-+			0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
-+			0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
-+			0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
-+			0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
-+			0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
-+			0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
-+			0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
-+			0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
-+			0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
-+			0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
-+			0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
-+			0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
-+			0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
-+			0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
-+			0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
-+			0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
-+			0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
-+			0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
-+			0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
-+			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-+			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
-+			0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
-+			0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
-+			0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
-+			0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
-+			0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
-+			0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
-+			0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
-+			0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
-+			0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
-+			0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
-+			0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
-+			0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
-+			0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
-+			0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
-+			0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
-+			0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
-+			0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
-+			0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
-+			0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
-+			0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
-+			0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
-+			0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
-+			0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
-+			0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
-+			0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
-+			0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
-+			0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
-+			0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
-+			0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
-+			0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
-+			0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
-+			0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
-+			0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
-+			0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
-+			0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
-+			0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
-+			0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
-+			0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
-+			0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
-+			0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
-+			0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
-+			0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
-+			0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
-+			0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
-+			0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
-+			0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
-+			0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
-+			0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
-+			0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
-+			0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
-+			0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
-+			0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
-+			0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
-+			0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
-+			0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
-+			0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
-+			0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
-+			0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
-+			0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
-+			0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
-+			0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
-+			0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
-+			0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
-+			0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
-+			0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
-+			0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
-+			0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
-+			0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
-+			0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
-+			0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
-+			0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
-+			0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
-+			0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
-+			0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
-+			0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
-+			0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
-+			0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
-+			0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
-+			0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
-+			0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
-+			0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
-+			0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
-+			0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
-+			0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
-+			0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
-+			0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
-+			0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
-+			0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
-+			0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
-+			0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
-+			0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
-+			0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
-+			0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
-+			0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
-+			0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
-+			0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
-+			0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
-+			0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
-+			0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
-+			0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
-+			0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
-+			0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
-+			0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
-+			0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
-+			0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
-+			0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
-+			0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
-+			0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
-+			0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
-+			0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
-+			0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
-+			0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
-+			0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
-+			0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
-+			0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
-+			0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
-+			0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
-+			0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
-+			0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
-+			0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
-+			0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
-+			0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
-+			0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
-+			0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
-+			0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
-+			0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
-+			0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
-+			0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
-+			0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
-+			0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
-+			0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
-+			0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
-+			0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
-+			0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
-+			0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
-+			0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
-+			0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
-+			0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
-+			0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
-+			0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
-+			0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
-+			0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
-+			0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
-+			0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
-+			0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
-+			0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
-+			0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
-+			0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
-+			0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
-+			0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
-+			0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
-+			0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
-+			0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
-+			0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
-+			0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
-+			0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
-+			0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
-+			0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
-+			0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
-+			0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
-+			0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
-+			0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
-+			0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
-+			0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
-+			0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
-+			0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
-+			0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
-+			0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
-+			0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
-+			0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
-+			0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
-+			0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
-+			0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
-+			0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
-+			0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
-+			0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
-+			0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
-+			0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
-+			0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
-+			0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
-+			0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
-+			0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
-+			0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
-+			0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
-+			0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
-+			0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
-+			0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
-+			0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
-+			0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
-+			0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
-+			0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
-+			0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
-+			0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
-+			0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
-+			0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
-+			0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
-+			0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
-+			0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
-+			0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
-+			0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
-+			0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
-+			0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
-+			0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
-+			0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
-+			0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
-+			0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
-+			0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
-+			0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
-+			0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
-+			0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
-+			0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
-+			0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
-+			0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
-+			0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
-+			0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
-+			0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
-+			0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
-+			0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
-+			0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
-+			0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
-+			0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
-+			0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
-+			0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
-+			0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
-+			0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
-+			0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
-+			0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
-+			0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
-+			0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
-+			0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
-+			0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
-+			0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
-+			0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
-+			0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
-+			0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
-+			0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
-+			0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
-+			0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
-+			0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
-+			0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
-+			0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
-+			0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
-+			0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
-+			0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
-+			0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
-+			0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
-+			0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
-+			0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
-+			0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
-+			0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
-+			0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
-+			0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
-+			0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
-+			0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
-+			0x00, 0x21, 0x42, 0x63,
-+		},
-+		.ilen = 4100,
-+		.result = {
-+			0xf0, 0x5c, 0x74, 0xad, 0x4e, 0xbc, 0x99, 0xe2,
-+			0xae, 0xff, 0x91, 0x3a, 0x44, 0xcf, 0x38, 0x32,
-+			0x1e, 0xad, 0xa7, 0xcd, 0xa1, 0x39, 0x95, 0xaa,
-+			0x10, 0xb1, 0xb3, 0x2e, 0x04, 0x31, 0x8f, 0x86,
-+			0xf2, 0x62, 0x74, 0x70, 0x0c, 0xa4, 0x46, 0x08,
-+			0xa8, 0xb7, 0x99, 0xa8, 0xe9, 0xd2, 0x73, 0x79,
-+			0x7e, 0x6e, 0xd4, 0x8f, 0x1e, 0xc7, 0x8e, 0x31,
-+			0x0b, 0xfa, 0x4b, 0xce, 0xfd, 0xf3, 0x57, 0x71,
-+			0xe9, 0x46, 0x03, 0xa5, 0x3d, 0x34, 0x00, 0xe2,
-+			0x18, 0xff, 0x75, 0x6d, 0x06, 0x2d, 0x00, 0xab,
-+			0xb9, 0x3e, 0x6c, 0x59, 0xc5, 0x84, 0x06, 0xb5,
-+			0x8b, 0xd0, 0x89, 0x9c, 0x4a, 0x79, 0x16, 0xc6,
-+			0x3d, 0x74, 0x54, 0xfa, 0x44, 0xcd, 0x23, 0x26,
-+			0x5c, 0xcf, 0x7e, 0x28, 0x92, 0x32, 0xbf, 0xdf,
-+			0xa7, 0x20, 0x3c, 0x74, 0x58, 0x2a, 0x9a, 0xde,
-+			0x61, 0x00, 0x1c, 0x4f, 0xff, 0x59, 0xc4, 0x22,
-+			0xac, 0x3c, 0xd0, 0xe8, 0x6c, 0xf9, 0x97, 0x1b,
-+			0x58, 0x9b, 0xad, 0x71, 0xe8, 0xa9, 0xb5, 0x0d,
-+			0xee, 0x2f, 0x04, 0x1f, 0x7f, 0xbc, 0x99, 0xee,
-+			0x84, 0xff, 0x42, 0x60, 0xdc, 0x3a, 0x18, 0xa5,
-+			0x81, 0xf9, 0xef, 0xdc, 0x7a, 0x0f, 0x65, 0x41,
-+			0x2f, 0xa3, 0xd3, 0xf9, 0xc2, 0xcb, 0xc0, 0x4d,
-+			0x8f, 0xd3, 0x76, 0x96, 0xad, 0x49, 0x6d, 0x38,
-+			0x3d, 0x39, 0x0b, 0x6c, 0x80, 0xb7, 0x54, 0x69,
-+			0xf0, 0x2c, 0x90, 0x02, 0x29, 0x0d, 0x1c, 0x12,
-+			0xad, 0x55, 0xc3, 0x8b, 0x68, 0xd9, 0xcc, 0xb3,
-+			0xb2, 0x64, 0x33, 0x90, 0x5e, 0xca, 0x4b, 0xe2,
-+			0xfb, 0x75, 0xdc, 0x63, 0xf7, 0x9f, 0x82, 0x74,
-+			0xf0, 0xc9, 0xaa, 0x7f, 0xe9, 0x2a, 0x9b, 0x33,
-+			0xbc, 0x88, 0x00, 0x7f, 0xca, 0xb2, 0x1f, 0x14,
-+			0xdb, 0xc5, 0x8e, 0x7b, 0x11, 0x3c, 0x3e, 0x08,
-+			0xf3, 0x83, 0xe8, 0xe0, 0x94, 0x86, 0x2e, 0x92,
-+			0x78, 0x6b, 0x01, 0xc9, 0xc7, 0x83, 0xba, 0x21,
-+			0x6a, 0x25, 0x15, 0x33, 0x4e, 0x45, 0x08, 0xec,
-+			0x35, 0xdb, 0xe0, 0x6e, 0x31, 0x51, 0x79, 0xa9,
-+			0x42, 0x44, 0x65, 0xc1, 0xa0, 0xf1, 0xf9, 0x2a,
-+			0x70, 0xd5, 0xb6, 0xc6, 0xc1, 0x8c, 0x39, 0xfc,
-+			0x25, 0xa6, 0x55, 0xd9, 0xdd, 0x2d, 0x4c, 0xec,
-+			0x49, 0xc6, 0xeb, 0x0e, 0xa8, 0x25, 0x2a, 0x16,
-+			0x1b, 0x66, 0x84, 0xda, 0xe2, 0x92, 0xe5, 0xc0,
-+			0xc8, 0x53, 0x07, 0xaf, 0x80, 0x84, 0xec, 0xfd,
-+			0xcd, 0xd1, 0x6e, 0xcd, 0x6f, 0x6a, 0xf5, 0x36,
-+			0xc5, 0x15, 0xe5, 0x25, 0x7d, 0x77, 0xd1, 0x1a,
-+			0x93, 0x36, 0xa9, 0xcf, 0x7c, 0xa4, 0x54, 0x4a,
-+			0x06, 0x51, 0x48, 0x4e, 0xf6, 0x59, 0x87, 0xd2,
-+			0x04, 0x02, 0xef, 0xd3, 0x44, 0xde, 0x76, 0x31,
-+			0xb3, 0x34, 0x17, 0x1b, 0x9d, 0x66, 0x11, 0x9f,
-+			0x1e, 0xcc, 0x17, 0xe9, 0xc7, 0x3c, 0x1b, 0xe7,
-+			0xcb, 0x50, 0x08, 0xfc, 0xdc, 0x2b, 0x24, 0xdb,
-+			0x65, 0x83, 0xd0, 0x3b, 0xe3, 0x30, 0xea, 0x94,
-+			0x6c, 0xe7, 0xe8, 0x35, 0x32, 0xc7, 0xdb, 0x64,
-+			0xb4, 0x01, 0xab, 0x36, 0x2c, 0x77, 0x13, 0xaf,
-+			0xf8, 0x2b, 0x88, 0x3f, 0x54, 0x39, 0xc4, 0x44,
-+			0xfe, 0xef, 0x6f, 0x68, 0x34, 0xbe, 0x0f, 0x05,
-+			0x16, 0x6d, 0xf6, 0x0a, 0x30, 0xe7, 0xe3, 0xed,
-+			0xc4, 0xde, 0x3c, 0x1b, 0x13, 0xd8, 0xdb, 0xfe,
-+			0x41, 0x62, 0xe5, 0x28, 0xd4, 0x8d, 0xa3, 0xc7,
-+			0x93, 0x97, 0xc6, 0x48, 0x45, 0x1d, 0x9f, 0x83,
-+			0xdf, 0x4b, 0x40, 0x3e, 0x42, 0x25, 0x87, 0x80,
-+			0x4c, 0x7d, 0xa8, 0xd4, 0x98, 0x23, 0x95, 0x75,
-+			0x41, 0x8c, 0xda, 0x41, 0x9b, 0xd4, 0xa7, 0x06,
-+			0xb5, 0xf1, 0x71, 0x09, 0x53, 0xbe, 0xca, 0xbf,
-+			0x32, 0x03, 0xed, 0xf0, 0x50, 0x1c, 0x56, 0x39,
-+			0x5b, 0xa4, 0x75, 0x18, 0xf7, 0x9b, 0x58, 0xef,
-+			0x53, 0xfc, 0x2a, 0x38, 0x23, 0x15, 0x75, 0xcd,
-+			0x45, 0xe5, 0x5a, 0x82, 0x55, 0xba, 0x21, 0xfa,
-+			0xd4, 0xbd, 0xc6, 0x94, 0x7c, 0xc5, 0x80, 0x12,
-+			0xf7, 0x4b, 0x32, 0xc4, 0x9a, 0x82, 0xd8, 0x28,
-+			0x8f, 0xd9, 0xc2, 0x0f, 0x60, 0x03, 0xbe, 0x5e,
-+			0x21, 0xd6, 0x5f, 0x58, 0xbf, 0x5c, 0xb1, 0x32,
-+			0x82, 0x8d, 0xa9, 0xe5, 0xf2, 0x66, 0x1a, 0xc0,
-+			0xa0, 0xbc, 0x58, 0x2f, 0x71, 0xf5, 0x2f, 0xed,
-+			0xd1, 0x26, 0xb9, 0xd8, 0x49, 0x5a, 0x07, 0x19,
-+			0x01, 0x7c, 0x59, 0xb0, 0xf8, 0xa4, 0xb7, 0xd3,
-+			0x7b, 0x1a, 0x8c, 0x38, 0xf4, 0x50, 0xa4, 0x59,
-+			0xb0, 0xcc, 0x41, 0x0b, 0x88, 0x7f, 0xe5, 0x31,
-+			0xb3, 0x42, 0xba, 0xa2, 0x7e, 0xd4, 0x32, 0x71,
-+			0x45, 0x87, 0x48, 0xa9, 0xc2, 0xf2, 0x89, 0xb3,
-+			0xe4, 0xa7, 0x7e, 0x52, 0x15, 0x61, 0xfa, 0xfe,
-+			0xc9, 0xdd, 0x81, 0xeb, 0x13, 0xab, 0xab, 0xc3,
-+			0x98, 0x59, 0xd8, 0x16, 0x3d, 0x14, 0x7a, 0x1c,
-+			0x3c, 0x41, 0x9a, 0x16, 0x16, 0x9b, 0xd2, 0xd2,
-+			0x69, 0x3a, 0x29, 0x23, 0xac, 0x86, 0x32, 0xa5,
-+			0x48, 0x9c, 0x9e, 0xf3, 0x47, 0x77, 0x81, 0x70,
-+			0x24, 0xe8, 0x85, 0xd2, 0xf5, 0xb5, 0xfa, 0xff,
-+			0x59, 0x6a, 0xd3, 0x50, 0x59, 0x43, 0x59, 0xde,
-+			0xd9, 0xf1, 0x55, 0xa5, 0x0c, 0xc3, 0x1a, 0x1a,
-+			0x18, 0x34, 0x0d, 0x1a, 0x63, 0x33, 0xed, 0x10,
-+			0xe0, 0x1d, 0x2a, 0x18, 0xd2, 0xc0, 0x54, 0xa8,
-+			0xca, 0xb5, 0x9a, 0xd3, 0xdd, 0xca, 0x45, 0x84,
-+			0x50, 0xe7, 0x0f, 0xfe, 0xa4, 0x99, 0x5a, 0xbe,
-+			0x43, 0x2d, 0x9a, 0xcb, 0x92, 0x3f, 0x5a, 0x1d,
-+			0x85, 0xd8, 0xc9, 0xdf, 0x68, 0xc9, 0x12, 0x80,
-+			0x56, 0x0c, 0xdc, 0x00, 0xdc, 0x3a, 0x7d, 0x9d,
-+			0xa3, 0xa2, 0xe8, 0x4d, 0xbf, 0xf9, 0x70, 0xa0,
-+			0xa4, 0x13, 0x4f, 0x6b, 0xaf, 0x0a, 0x89, 0x7f,
-+			0xda, 0xf0, 0xbf, 0x9b, 0xc8, 0x1d, 0xe5, 0xf8,
-+			0x2e, 0x8b, 0x07, 0xb5, 0x73, 0x1b, 0xcc, 0xa2,
-+			0xa6, 0xad, 0x30, 0xbc, 0x78, 0x3c, 0x5b, 0x10,
-+			0xfa, 0x5e, 0x62, 0x2d, 0x9e, 0x64, 0xb3, 0x33,
-+			0xce, 0xf9, 0x1f, 0x86, 0xe7, 0x8b, 0xa2, 0xb8,
-+			0xe8, 0x99, 0x57, 0x8c, 0x11, 0xed, 0x66, 0xd9,
-+			0x3c, 0x72, 0xb9, 0xc3, 0xe6, 0x4e, 0x17, 0x3a,
-+			0x6a, 0xcb, 0x42, 0x24, 0x06, 0xed, 0x3e, 0x4e,
-+			0xa3, 0xe8, 0x6a, 0x94, 0xda, 0x0d, 0x4e, 0xd5,
-+			0x14, 0x19, 0xcf, 0xb6, 0x26, 0xd8, 0x2e, 0xcc,
-+			0x64, 0x76, 0x38, 0x49, 0x4d, 0xfe, 0x30, 0x6d,
-+			0xe4, 0xc8, 0x8c, 0x7b, 0xc4, 0xe0, 0x35, 0xba,
-+			0x22, 0x6e, 0x76, 0xe1, 0x1a, 0xf2, 0x53, 0xc3,
-+			0x28, 0xa2, 0x82, 0x1f, 0x61, 0x69, 0xad, 0xc1,
-+			0x7b, 0x28, 0x4b, 0x1e, 0x6c, 0x85, 0x95, 0x9b,
-+			0x51, 0xb5, 0x17, 0x7f, 0x12, 0x69, 0x8c, 0x24,
-+			0xd5, 0xc7, 0x5a, 0x5a, 0x11, 0x54, 0xff, 0x5a,
-+			0xf7, 0x16, 0xc3, 0x91, 0xa6, 0xf0, 0xdc, 0x0a,
-+			0xb6, 0xa7, 0x4a, 0x0d, 0x7a, 0x58, 0xfe, 0xa5,
-+			0xf5, 0xcb, 0x8f, 0x7b, 0x0e, 0xea, 0x57, 0xe7,
-+			0xbd, 0x79, 0xd6, 0x1c, 0x88, 0x23, 0x6c, 0xf2,
-+			0x4d, 0x29, 0x77, 0x53, 0x35, 0x6a, 0x00, 0x8d,
-+			0xcd, 0xa3, 0x58, 0xbe, 0x77, 0x99, 0x18, 0xf8,
-+			0xe6, 0xe1, 0x8f, 0xe9, 0x37, 0x8f, 0xe3, 0xe2,
-+			0x5a, 0x8a, 0x93, 0x25, 0xaf, 0xf3, 0x78, 0x80,
-+			0xbe, 0xa6, 0x1b, 0xc6, 0xac, 0x8b, 0x1c, 0x91,
-+			0x58, 0xe1, 0x9f, 0x89, 0x35, 0x9d, 0x1d, 0x21,
-+			0x29, 0x9f, 0xf4, 0x99, 0x02, 0x27, 0x0f, 0xa8,
-+			0x4f, 0x79, 0x94, 0x2b, 0x33, 0x2c, 0xda, 0xa2,
-+			0x26, 0x39, 0x83, 0x94, 0xef, 0x27, 0xd8, 0x53,
-+			0x8f, 0x66, 0x0d, 0xe4, 0x41, 0x7d, 0x34, 0xcd,
-+			0x43, 0x7c, 0x95, 0x0a, 0x53, 0xef, 0x66, 0xda,
-+			0x7e, 0x9b, 0xf3, 0x93, 0xaf, 0xd0, 0x73, 0x71,
-+			0xba, 0x40, 0x9b, 0x74, 0xf8, 0xd7, 0xd7, 0x41,
-+			0x6d, 0xaf, 0x72, 0x9c, 0x8d, 0x21, 0x87, 0x3c,
-+			0xfd, 0x0a, 0x90, 0xa9, 0x47, 0x96, 0x9e, 0xd3,
-+			0x88, 0xee, 0x73, 0xcf, 0x66, 0x2f, 0x52, 0x56,
-+			0x6d, 0xa9, 0x80, 0x4c, 0xe2, 0x6f, 0x62, 0x88,
-+			0x3f, 0x0e, 0x54, 0x17, 0x48, 0x80, 0x5d, 0xd3,
-+			0xc3, 0xda, 0x25, 0x3d, 0xa1, 0xc8, 0xcb, 0x9f,
-+			0x9b, 0x70, 0xb3, 0xa1, 0xeb, 0x04, 0x52, 0xa1,
-+			0xf2, 0x22, 0x0f, 0xfc, 0xc8, 0x18, 0xfa, 0xf9,
-+			0x85, 0x9c, 0xf1, 0xac, 0xeb, 0x0c, 0x02, 0x46,
-+			0x75, 0xd2, 0xf5, 0x2c, 0xe3, 0xd2, 0x59, 0x94,
-+			0x12, 0xf3, 0x3c, 0xfc, 0xd7, 0x92, 0xfa, 0x36,
-+			0xba, 0x61, 0x34, 0x38, 0x7c, 0xda, 0x48, 0x3e,
-+			0x08, 0xc9, 0x39, 0x23, 0x5e, 0x02, 0x2c, 0x1a,
-+			0x18, 0x7e, 0xb4, 0xd9, 0xfd, 0x9e, 0x40, 0x02,
-+			0xb1, 0x33, 0x37, 0x32, 0xe7, 0xde, 0xd6, 0xd0,
-+			0x7c, 0x58, 0x65, 0x4b, 0xf8, 0x34, 0x27, 0x9c,
-+			0x44, 0xb4, 0xbd, 0xe9, 0xe9, 0x4c, 0x78, 0x7d,
-+			0x4b, 0x9f, 0xce, 0xb1, 0xcd, 0x47, 0xa5, 0x37,
-+			0xe5, 0x6d, 0xbd, 0xb9, 0x43, 0x94, 0x0a, 0xd4,
-+			0xd6, 0xf9, 0x04, 0x5f, 0xb5, 0x66, 0x6c, 0x1a,
-+			0x35, 0x12, 0xe3, 0x36, 0x28, 0x27, 0x36, 0x58,
-+			0x01, 0x2b, 0x79, 0xe4, 0xba, 0x6d, 0x10, 0x7d,
-+			0x65, 0xdf, 0x84, 0x95, 0xf4, 0xd5, 0xb6, 0x8f,
-+			0x2b, 0x9f, 0x96, 0x00, 0x86, 0x60, 0xf0, 0x21,
-+			0x76, 0xa8, 0x6a, 0x8c, 0x28, 0x1c, 0xb3, 0x6b,
-+			0x97, 0xd7, 0xb6, 0x53, 0x2a, 0xcc, 0xab, 0x40,
-+			0x9d, 0x62, 0x79, 0x58, 0x52, 0xe6, 0x65, 0xb7,
-+			0xab, 0x55, 0x67, 0x9c, 0x89, 0x7c, 0x03, 0xb0,
-+			0x73, 0x59, 0xc5, 0x81, 0xf5, 0x18, 0x17, 0x5c,
-+			0x89, 0xf3, 0x78, 0x35, 0x44, 0x62, 0x78, 0x72,
-+			0xd0, 0x96, 0xeb, 0x31, 0xe7, 0x87, 0x77, 0x14,
-+			0x99, 0x51, 0xf2, 0x59, 0x26, 0x9e, 0xb5, 0xa6,
-+			0x45, 0xfe, 0x6e, 0xbd, 0x07, 0x4c, 0x94, 0x5a,
-+			0xa5, 0x7d, 0xfc, 0xf1, 0x2b, 0x77, 0xe2, 0xfe,
-+			0x17, 0xd4, 0x84, 0xa0, 0xac, 0xb5, 0xc7, 0xda,
-+			0xa9, 0x1a, 0xb6, 0xf3, 0x74, 0x11, 0xb4, 0x9d,
-+			0xfb, 0x79, 0x2e, 0x04, 0x2d, 0x50, 0x28, 0x83,
-+			0xbf, 0xc6, 0x52, 0xd3, 0x34, 0xd6, 0xe8, 0x7a,
-+			0xb6, 0xea, 0xe7, 0xa8, 0x6c, 0x15, 0x1e, 0x2c,
-+			0x57, 0xbc, 0x48, 0x4e, 0x5f, 0x5c, 0xb6, 0x92,
-+			0xd2, 0x49, 0x77, 0x81, 0x6d, 0x90, 0x70, 0xae,
-+			0x98, 0xa1, 0x03, 0x0d, 0x6b, 0xb9, 0x77, 0x14,
-+			0xf1, 0x4e, 0x23, 0xd3, 0xf8, 0x68, 0xbd, 0xc2,
-+			0xfe, 0x04, 0xb7, 0x5c, 0xc5, 0x17, 0x60, 0x8f,
-+			0x65, 0x54, 0xa4, 0x7a, 0x42, 0xdc, 0x18, 0x0d,
-+			0xb5, 0xcf, 0x0f, 0xd3, 0xc7, 0x91, 0x66, 0x1b,
-+			0x45, 0x42, 0x27, 0x75, 0x50, 0xe5, 0xee, 0xb8,
-+			0x7f, 0x33, 0x2c, 0xba, 0x4a, 0x92, 0x4d, 0x2c,
-+			0x3c, 0xe3, 0x0d, 0x80, 0x01, 0xba, 0x0d, 0x29,
-+			0xd8, 0x3c, 0xe9, 0x13, 0x16, 0x57, 0xe6, 0xea,
-+			0x94, 0x52, 0xe7, 0x00, 0x4d, 0x30, 0xb0, 0x0f,
-+			0x35, 0xb8, 0xb8, 0xa7, 0xb1, 0xb5, 0x3b, 0x44,
-+			0xe1, 0x2f, 0xfd, 0x88, 0xed, 0x43, 0xe7, 0x52,
-+			0x10, 0x93, 0xb3, 0x8a, 0x30, 0x6b, 0x0a, 0xf7,
-+			0x23, 0xc6, 0x50, 0x9d, 0x4a, 0xb0, 0xde, 0xc3,
-+			0xdc, 0x9b, 0x2f, 0x01, 0x56, 0x36, 0x09, 0xc5,
-+			0x2f, 0x6b, 0xfe, 0xf1, 0xd8, 0x27, 0x45, 0x03,
-+			0x30, 0x5e, 0x5c, 0x5b, 0xb4, 0x62, 0x0e, 0x1a,
-+			0xa9, 0x21, 0x2b, 0x92, 0x94, 0x87, 0x62, 0x57,
-+			0x4c, 0x10, 0x74, 0x1a, 0xf1, 0x0a, 0xc5, 0x84,
-+			0x3b, 0x9e, 0x72, 0x02, 0xd7, 0xcc, 0x09, 0x56,
-+			0xbd, 0x54, 0xc1, 0xf0, 0xc3, 0xe3, 0xb3, 0xf8,
-+			0xd2, 0x0d, 0x61, 0xcb, 0xef, 0xce, 0x0d, 0x05,
-+			0xb0, 0x98, 0xd9, 0x8e, 0x4f, 0xf9, 0xbc, 0x93,
-+			0xa6, 0xea, 0xc8, 0xcf, 0x10, 0x53, 0x4b, 0xf1,
-+			0xec, 0xfc, 0x89, 0xf9, 0x64, 0xb0, 0x22, 0xbf,
-+			0x9e, 0x55, 0x46, 0x9f, 0x7c, 0x50, 0x8e, 0x84,
-+			0x54, 0x20, 0x98, 0xd7, 0x6c, 0x40, 0x1e, 0xdb,
-+			0x69, 0x34, 0x78, 0x61, 0x24, 0x21, 0x9c, 0x8a,
-+			0xb3, 0x62, 0x31, 0x8b, 0x6e, 0xf5, 0x2a, 0x35,
-+			0x86, 0x13, 0xb1, 0x6c, 0x64, 0x2e, 0x41, 0xa5,
-+			0x05, 0xf2, 0x42, 0xba, 0xd2, 0x3a, 0x0d, 0x8e,
-+			0x8a, 0x59, 0x94, 0x3c, 0xcf, 0x36, 0x27, 0x82,
-+			0xc2, 0x45, 0xee, 0x58, 0xcd, 0x88, 0xb4, 0xec,
-+			0xde, 0xb2, 0x96, 0x0a, 0xaf, 0x38, 0x6f, 0x88,
-+			0xd7, 0xd8, 0xe1, 0xdf, 0xb9, 0x96, 0xa9, 0x0a,
-+			0xb1, 0x95, 0x28, 0x86, 0x20, 0xe9, 0x17, 0x49,
-+			0xa2, 0x29, 0x38, 0xaa, 0xa5, 0xe9, 0x6e, 0xf1,
-+			0x19, 0x27, 0xc0, 0xd5, 0x2a, 0x22, 0xc3, 0x0b,
-+			0xdb, 0x7c, 0x73, 0x10, 0xb9, 0xba, 0x89, 0x76,
-+			0x54, 0xae, 0x7d, 0x71, 0xb3, 0x93, 0xf6, 0x32,
-+			0xe6, 0x47, 0x43, 0x55, 0xac, 0xa0, 0x0d, 0xc2,
-+			0x93, 0x27, 0x4a, 0x8e, 0x0e, 0x74, 0x15, 0xc7,
-+			0x0b, 0x85, 0xd9, 0x0c, 0xa9, 0x30, 0x7a, 0x3e,
-+			0xea, 0x8f, 0x85, 0x6d, 0x3a, 0x12, 0x4f, 0x72,
-+			0x69, 0x58, 0x7a, 0x80, 0xbb, 0xb5, 0x97, 0xf3,
-+			0xcf, 0x70, 0xd2, 0x5d, 0xdd, 0x4d, 0x21, 0x79,
-+			0x54, 0x4d, 0xe4, 0x05, 0xe8, 0xbd, 0xc2, 0x62,
-+			0xb1, 0x3b, 0x77, 0x1c, 0xd6, 0x5c, 0xf3, 0xa0,
-+			0x79, 0x00, 0xa8, 0x6c, 0x29, 0xd9, 0x18, 0x24,
-+			0x36, 0xa2, 0x46, 0xc0, 0x96, 0x65, 0x7f, 0xbd,
-+			0x2a, 0xed, 0x36, 0x16, 0x0c, 0xaa, 0x9f, 0xf4,
-+			0xc5, 0xb4, 0xe2, 0x12, 0xed, 0x69, 0xed, 0x4f,
-+			0x26, 0x2c, 0x39, 0x52, 0x89, 0x98, 0xe7, 0x2c,
-+			0x99, 0xa4, 0x9e, 0xa3, 0x9b, 0x99, 0x46, 0x7a,
-+			0x3a, 0xdc, 0xa8, 0x59, 0xa3, 0xdb, 0xc3, 0x3b,
-+			0x95, 0x0d, 0x3b, 0x09, 0x6e, 0xee, 0x83, 0x5d,
-+			0x32, 0x4d, 0xed, 0xab, 0xfa, 0x98, 0x14, 0x4e,
-+			0xc3, 0x15, 0x45, 0x53, 0x61, 0xc4, 0x93, 0xbd,
-+			0x90, 0xf4, 0x99, 0x95, 0x4c, 0xe6, 0x76, 0x92,
-+			0x29, 0x90, 0x46, 0x30, 0x92, 0x69, 0x7d, 0x13,
-+			0xf2, 0xa5, 0xcd, 0x69, 0x49, 0x44, 0xb2, 0x0f,
-+			0x63, 0x40, 0x36, 0x5f, 0x09, 0xe2, 0x78, 0xf8,
-+			0x91, 0xe3, 0xe2, 0xfa, 0x10, 0xf7, 0xc8, 0x24,
-+			0xa8, 0x89, 0x32, 0x5c, 0x37, 0x25, 0x1d, 0xb2,
-+			0xea, 0x17, 0x8a, 0x0a, 0xa9, 0x64, 0xc3, 0x7c,
-+			0x3c, 0x7c, 0xbd, 0xc6, 0x79, 0x34, 0xe7, 0xe2,
-+			0x85, 0x8e, 0xbf, 0xf8, 0xde, 0x92, 0xa0, 0xae,
-+			0x20, 0xc4, 0xf6, 0xbb, 0x1f, 0x38, 0x19, 0x0e,
-+			0xe8, 0x79, 0x9c, 0xa1, 0x23, 0xe9, 0x54, 0x7e,
-+			0x37, 0x2f, 0xe2, 0x94, 0x32, 0xaf, 0xa0, 0x23,
-+			0x49, 0xe4, 0xc0, 0xb3, 0xac, 0x00, 0x8f, 0x36,
-+			0x05, 0xc4, 0xa6, 0x96, 0xec, 0x05, 0x98, 0x4f,
-+			0x96, 0x67, 0x57, 0x1f, 0x20, 0x86, 0x1b, 0x2d,
-+			0x69, 0xe4, 0x29, 0x93, 0x66, 0x5f, 0xaf, 0x6b,
-+			0x88, 0x26, 0x2c, 0x67, 0x02, 0x4b, 0x52, 0xd0,
-+			0x83, 0x7a, 0x43, 0x1f, 0xc0, 0x71, 0x15, 0x25,
-+			0x77, 0x65, 0x08, 0x60, 0x11, 0x76, 0x4c, 0x8d,
-+			0xed, 0xa9, 0x27, 0xc6, 0xb1, 0x2a, 0x2c, 0x6a,
-+			0x4a, 0x97, 0xf5, 0xc6, 0xb7, 0x70, 0x42, 0xd3,
-+			0x03, 0xd1, 0x24, 0x95, 0xec, 0x6d, 0xab, 0x38,
-+			0x72, 0xce, 0xe2, 0x8b, 0x33, 0xd7, 0x51, 0x09,
-+			0xdc, 0x45, 0xe0, 0x09, 0x96, 0x32, 0xf3, 0xc4,
-+			0x84, 0xdc, 0x73, 0x73, 0x2d, 0x1b, 0x11, 0x98,
-+			0xc5, 0x0e, 0x69, 0x28, 0x94, 0xc7, 0xb5, 0x4d,
-+			0xc8, 0x8a, 0xd0, 0xaa, 0x13, 0x2e, 0x18, 0x74,
-+			0xdd, 0xd1, 0x1e, 0xf3, 0x90, 0xe8, 0xfc, 0x9a,
-+			0x72, 0x4a, 0x0e, 0xd1, 0xe4, 0xfb, 0x0d, 0x96,
-+			0xd1, 0x0c, 0x79, 0x85, 0x1b, 0x1c, 0xfe, 0xe1,
-+			0x62, 0x8f, 0x7a, 0x73, 0x32, 0xab, 0xc8, 0x18,
-+			0x69, 0xe3, 0x34, 0x30, 0xdf, 0x13, 0xa6, 0xe5,
-+			0xe8, 0x0e, 0x67, 0x7f, 0x81, 0x11, 0xb4, 0x60,
-+			0xc7, 0xbd, 0x79, 0x65, 0x50, 0xdc, 0xc4, 0x5b,
-+			0xde, 0x39, 0xa4, 0x01, 0x72, 0x63, 0xf3, 0xd1,
-+			0x64, 0x4e, 0xdf, 0xfc, 0x27, 0x92, 0x37, 0x0d,
-+			0x57, 0xcd, 0x11, 0x4f, 0x11, 0x04, 0x8e, 0x1d,
-+			0x16, 0xf7, 0xcd, 0x92, 0x9a, 0x99, 0x30, 0x14,
-+			0xf1, 0x7c, 0x67, 0x1b, 0x1f, 0x41, 0x0b, 0xe8,
-+			0x32, 0xe8, 0xb8, 0xc1, 0x4f, 0x54, 0x86, 0x4f,
-+			0xe5, 0x79, 0x81, 0x73, 0xcd, 0x43, 0x59, 0x68,
-+			0x73, 0x02, 0x3b, 0x78, 0x21, 0x72, 0x43, 0x00,
-+			0x49, 0x17, 0xf7, 0x00, 0xaf, 0x68, 0x24, 0x53,
-+			0x05, 0x0a, 0xc3, 0x33, 0xe0, 0x33, 0x3f, 0x69,
-+			0xd2, 0x84, 0x2f, 0x0b, 0xed, 0xde, 0x04, 0xf4,
-+			0x11, 0x94, 0x13, 0x69, 0x51, 0x09, 0x28, 0xde,
-+			0x57, 0x5c, 0xef, 0xdc, 0x9a, 0x49, 0x1c, 0x17,
-+			0x97, 0xf3, 0x96, 0xc1, 0x7f, 0x5d, 0x2e, 0x7d,
-+			0x55, 0xb8, 0xb3, 0x02, 0x09, 0xb3, 0x1f, 0xe7,
-+			0xc9, 0x8d, 0xa3, 0x36, 0x34, 0x8a, 0x77, 0x13,
-+			0x30, 0x63, 0x4c, 0xa5, 0xcd, 0xc3, 0xe0, 0x7e,
-+			0x05, 0xa1, 0x7b, 0x0c, 0xcb, 0x74, 0x47, 0x31,
-+			0x62, 0x03, 0x43, 0xf1, 0x87, 0xb4, 0xb0, 0x85,
-+			0x87, 0x8e, 0x4b, 0x25, 0xc7, 0xcf, 0xae, 0x4b,
-+			0x36, 0x46, 0x3e, 0x62, 0xbc, 0x6f, 0xeb, 0x5f,
-+			0x73, 0xac, 0xe6, 0x07, 0xee, 0xc1, 0xa1, 0xd6,
-+			0xc4, 0xab, 0xc9, 0xd6, 0x89, 0x45, 0xe1, 0xf1,
-+			0x04, 0x4e, 0x1a, 0x6f, 0xbb, 0x4f, 0x3a, 0xa3,
-+			0xa0, 0xcb, 0xa3, 0x0a, 0xd8, 0x71, 0x35, 0x55,
-+			0xe4, 0xbc, 0x2e, 0x04, 0x06, 0xe6, 0xff, 0x5b,
-+			0x1c, 0xc0, 0x11, 0x7c, 0xc5, 0x17, 0xf3, 0x38,
-+			0xcf, 0xe9, 0xba, 0x0f, 0x0e, 0xef, 0x02, 0xc2,
-+			0x8d, 0xc6, 0xbc, 0x4b, 0x67, 0x20, 0x95, 0xd7,
-+			0x2c, 0x45, 0x5b, 0x86, 0x44, 0x8c, 0x6f, 0x2e,
-+			0x7e, 0x9f, 0x1c, 0x77, 0xba, 0x6b, 0x0e, 0xa3,
-+			0x69, 0xdc, 0xab, 0x24, 0x57, 0x60, 0x47, 0xc1,
-+			0xd1, 0xa5, 0x9d, 0x23, 0xe6, 0xb1, 0x37, 0xfe,
-+			0x93, 0xd2, 0x4c, 0x46, 0xf9, 0x0c, 0xc6, 0xfb,
-+			0xd6, 0x9d, 0x99, 0x69, 0xab, 0x7a, 0x07, 0x0c,
-+			0x65, 0xe7, 0xc4, 0x08, 0x96, 0xe2, 0xa5, 0x01,
-+			0x3f, 0x46, 0x07, 0x05, 0x7e, 0xe8, 0x9a, 0x90,
-+			0x50, 0xdc, 0xe9, 0x7a, 0xea, 0xa1, 0x39, 0x6e,
-+			0x66, 0xe4, 0x6f, 0xa5, 0x5f, 0xb2, 0xd9, 0x5b,
-+			0xf5, 0xdb, 0x2a, 0x32, 0xf0, 0x11, 0x6f, 0x7c,
-+			0x26, 0x10, 0x8f, 0x3d, 0x80, 0xe9, 0x58, 0xf7,
-+			0xe0, 0xa8, 0x57, 0xf8, 0xdb, 0x0e, 0xce, 0x99,
-+			0x63, 0x19, 0x3d, 0xd5, 0xec, 0x1b, 0x77, 0x69,
-+			0x98, 0xf6, 0xe4, 0x5f, 0x67, 0x17, 0x4b, 0x09,
-+			0x85, 0x62, 0x82, 0x70, 0x18, 0xe2, 0x9a, 0x78,
-+			0xe2, 0x62, 0xbd, 0xb4, 0xf1, 0x42, 0xc6, 0xfb,
-+			0x08, 0xd0, 0xbd, 0xeb, 0x4e, 0x09, 0xf2, 0xc8,
-+			0x1e, 0xdc, 0x3d, 0x32, 0x21, 0x56, 0x9c, 0x4f,
-+			0x35, 0xf3, 0x61, 0x06, 0x72, 0x84, 0xc4, 0x32,
-+			0xf2, 0xf1, 0xfa, 0x0b, 0x2f, 0xc3, 0xdb, 0x02,
-+			0x04, 0xc2, 0xde, 0x57, 0x64, 0x60, 0x8d, 0xcf,
-+			0xcb, 0x86, 0x5d, 0x97, 0x3e, 0xb1, 0x9c, 0x01,
-+			0xd6, 0x28, 0x8f, 0x99, 0xbc, 0x46, 0xeb, 0x05,
-+			0xaf, 0x7e, 0xb8, 0x21, 0x2a, 0x56, 0x85, 0x1c,
-+			0xb3, 0x71, 0xa0, 0xde, 0xca, 0x96, 0xf1, 0x78,
-+			0x49, 0xa2, 0x99, 0x81, 0x80, 0x5c, 0x01, 0xf5,
-+			0xa0, 0xa2, 0x56, 0x63, 0xe2, 0x70, 0x07, 0xa5,
-+			0x95, 0xd6, 0x85, 0xeb, 0x36, 0x9e, 0xa9, 0x51,
-+			0x66, 0x56, 0x5f, 0x1d, 0x02, 0x19, 0xe2, 0xf6,
-+			0x4f, 0x73, 0x38, 0x09, 0x75, 0x64, 0x48, 0xe0,
-+			0xf1, 0x7e, 0x0e, 0xe8, 0x9d, 0xf9, 0xed, 0x94,
-+			0xfe, 0x16, 0x26, 0x62, 0x49, 0x74, 0xf4, 0xb0,
-+			0xd4, 0xa9, 0x6c, 0xb0, 0xfd, 0x53, 0xe9, 0x81,
-+			0xe0, 0x7a, 0xbf, 0xcf, 0xb5, 0xc4, 0x01, 0x81,
-+			0x79, 0x99, 0x77, 0x01, 0x3b, 0xe9, 0xa2, 0xb6,
-+			0xe6, 0x6a, 0x8a, 0x9e, 0x56, 0x1c, 0x8d, 0x1e,
-+			0x8f, 0x06, 0x55, 0x2c, 0x6c, 0xdc, 0x92, 0x87,
-+			0x64, 0x3b, 0x4b, 0x19, 0xa1, 0x13, 0x64, 0x1d,
-+			0x4a, 0xe9, 0xc0, 0x00, 0xb8, 0x95, 0xef, 0x6b,
-+			0x1a, 0x86, 0x6d, 0x37, 0x52, 0x02, 0xc2, 0xe0,
-+			0xc8, 0xbb, 0x42, 0x0c, 0x02, 0x21, 0x4a, 0xc9,
-+			0xef, 0xa0, 0x54, 0xe4, 0x5e, 0x16, 0x53, 0x81,
-+			0x70, 0x62, 0x10, 0xaf, 0xde, 0xb8, 0xb5, 0xd3,
-+			0xe8, 0x5e, 0x6c, 0xc3, 0x8a, 0x3e, 0x18, 0x07,
-+			0xf2, 0x2f, 0x7d, 0xa7, 0xe1, 0x3d, 0x4e, 0xb4,
-+			0x26, 0xa7, 0xa3, 0x93, 0x86, 0xb2, 0x04, 0x1e,
-+			0x53, 0x5d, 0x86, 0xd6, 0xde, 0x65, 0xca, 0xe3,
-+			0x4e, 0xc1, 0xcf, 0xef, 0xc8, 0x70, 0x1b, 0x83,
-+			0x13, 0xdd, 0x18, 0x8b, 0x0d, 0x76, 0xd2, 0xf6,
-+			0x37, 0x7a, 0x93, 0x7a, 0x50, 0x11, 0x9f, 0x96,
-+			0x86, 0x25, 0xfd, 0xac, 0xdc, 0xbe, 0x18, 0x93,
-+			0x19, 0x6b, 0xec, 0x58, 0x4f, 0xb9, 0x75, 0xa7,
-+			0xdd, 0x3f, 0x2f, 0xec, 0xc8, 0x5a, 0x84, 0xab,
-+			0xd5, 0xe4, 0x8a, 0x07, 0xf6, 0x4d, 0x23, 0xd6,
-+			0x03, 0xfb, 0x03, 0x6a, 0xea, 0x66, 0xbf, 0xd4,
-+			0xb1, 0x34, 0xfb, 0x78, 0xe9, 0x55, 0xdc, 0x7c,
-+			0x3d, 0x9c, 0xe5, 0x9a, 0xac, 0xc3, 0x7a, 0x80,
-+			0x24, 0x6d, 0xa0, 0xef, 0x25, 0x7c, 0xb7, 0xea,
-+			0xce, 0x4d, 0x5f, 0x18, 0x60, 0xce, 0x87, 0x22,
-+			0x66, 0x2f, 0xd5, 0xdd, 0xdd, 0x02, 0x21, 0x75,
-+			0x82, 0xa0, 0x1f, 0x58, 0xc6, 0xd3, 0x62, 0xf7,
-+			0x32, 0xd8, 0xaf, 0x1e, 0x07, 0x77, 0x51, 0x96,
-+			0xd5, 0x6b, 0x1e, 0x7e, 0x80, 0x02, 0xe8, 0x67,
-+			0xea, 0x17, 0x0b, 0x10, 0xd2, 0x3f, 0x28, 0x25,
-+			0x4f, 0x05, 0x77, 0x02, 0x14, 0x69, 0xf0, 0x2c,
-+			0xbe, 0x0c, 0xf1, 0x74, 0x30, 0xd1, 0xb9, 0x9b,
-+			0xfc, 0x8c, 0xbb, 0x04, 0x16, 0xd9, 0xba, 0xc3,
-+			0xbc, 0x91, 0x8a, 0xc4, 0x30, 0xa4, 0xb0, 0x12,
-+			0x4c, 0x21, 0x87, 0xcb, 0xc9, 0x1d, 0x16, 0x96,
-+			0x07, 0x6f, 0x23, 0x54, 0xb9, 0x6f, 0x79, 0xe5,
-+			0x64, 0xc0, 0x64, 0xda, 0xb1, 0xae, 0xdd, 0x60,
-+			0x6c, 0x1a, 0x9d, 0xd3, 0x04, 0x8e, 0x45, 0xb0,
-+			0x92, 0x61, 0xd0, 0x48, 0x81, 0xed, 0x5e, 0x1d,
-+			0xa0, 0xc9, 0xa4, 0x33, 0xc7, 0x13, 0x51, 0x5d,
-+			0x7f, 0x83, 0x73, 0xb6, 0x70, 0x18, 0x65, 0x3e,
-+			0x2f, 0x0e, 0x7a, 0x12, 0x39, 0x98, 0xab, 0xd8,
-+			0x7e, 0x6f, 0xa3, 0xd1, 0xba, 0x56, 0xad, 0xbd,
-+			0xf0, 0x03, 0x01, 0x1c, 0x85, 0x35, 0x9f, 0xeb,
-+			0x19, 0x63, 0xa1, 0xaf, 0xfe, 0x2d, 0x35, 0x50,
-+			0x39, 0xa0, 0x65, 0x7c, 0x95, 0x7e, 0x6b, 0xfe,
-+			0xc1, 0xac, 0x07, 0x7c, 0x98, 0x4f, 0xbe, 0x57,
-+			0xa7, 0x22, 0xec, 0xe2, 0x7e, 0x29, 0x09, 0x53,
-+			0xe8, 0xbf, 0xb4, 0x7e, 0x3f, 0x8f, 0xfc, 0x14,
-+			0xce, 0x54, 0xf9, 0x18, 0x58, 0xb5, 0xff, 0x44,
-+			0x05, 0x9d, 0xce, 0x1b, 0xb6, 0x82, 0x23, 0xc8,
-+			0x2e, 0xbc, 0x69, 0xbb, 0x4a, 0x29, 0x0f, 0x65,
-+			0x94, 0xf0, 0x63, 0x06, 0x0e, 0xef, 0x8c, 0xbd,
-+			0xff, 0xfd, 0xb0, 0x21, 0x6e, 0x57, 0x05, 0x75,
-+			0xda, 0xd5, 0xc4, 0xeb, 0x8d, 0x32, 0xf7, 0x50,
-+			0xd3, 0x6f, 0x22, 0xed, 0x5f, 0x8e, 0xa2, 0x5b,
-+			0x80, 0x8c, 0xc8, 0x78, 0x40, 0x24, 0x4b, 0x89,
-+			0x30, 0xce, 0x7a, 0x97, 0x0e, 0xc4, 0xaf, 0xef,
-+			0x9b, 0xb4, 0xcd, 0x66, 0x74, 0x14, 0x04, 0x2b,
-+			0xf7, 0xce, 0x0b, 0x1c, 0x6e, 0xc2, 0x78, 0x8c,
-+			0xca, 0xc5, 0xd0, 0x1c, 0x95, 0x4a, 0x91, 0x2d,
-+			0xa7, 0x20, 0xeb, 0x86, 0x52, 0xb7, 0x67, 0xd8,
-+			0x0c, 0xd6, 0x04, 0x14, 0xde, 0x51, 0x74, 0x75,
-+			0xe7, 0x11, 0xb4, 0x87, 0xa3, 0x3d, 0x2d, 0xad,
-+			0x4f, 0xef, 0xa0, 0x0f, 0x70, 0x00, 0x6d, 0x13,
-+			0x19, 0x1d, 0x41, 0x50, 0xe9, 0xd8, 0xf0, 0x32,
-+			0x71, 0xbc, 0xd3, 0x11, 0xf2, 0xac, 0xbe, 0xaf,
-+			0x75, 0x46, 0x65, 0x4e, 0x07, 0x34, 0x37, 0xa3,
-+			0x89, 0xfe, 0x75, 0xd4, 0x70, 0x4c, 0xc6, 0x3f,
-+			0x69, 0x24, 0x0e, 0x38, 0x67, 0x43, 0x8c, 0xde,
-+			0x06, 0xb5, 0xb8, 0xe7, 0xc4, 0xf0, 0x41, 0x8f,
-+			0xf0, 0xbd, 0x2f, 0x0b, 0xb9, 0x18, 0xf8, 0xde,
-+			0x64, 0xb1, 0xdb, 0xee, 0x00, 0x50, 0x77, 0xe1,
-+			0xc7, 0xff, 0xa6, 0xfa, 0xdd, 0x70, 0xf4, 0xe3,
-+			0x93, 0xe9, 0x77, 0x35, 0x3d, 0x4b, 0x2f, 0x2b,
-+			0x6d, 0x55, 0xf0, 0xfc, 0x88, 0x54, 0x4e, 0x89,
-+			0xc1, 0x8a, 0x23, 0x31, 0x2d, 0x14, 0x2a, 0xb8,
-+			0x1b, 0x15, 0xdd, 0x9e, 0x6e, 0x7b, 0xda, 0x05,
-+			0x91, 0x7d, 0x62, 0x64, 0x96, 0x72, 0xde, 0xfc,
-+			0xc1, 0xec, 0xf0, 0x23, 0x51, 0x6f, 0xdb, 0x5b,
-+			0x1d, 0x08, 0x57, 0xce, 0x09, 0xb8, 0xf6, 0xcd,
-+			0x8d, 0x95, 0xf2, 0x20, 0xbf, 0x0f, 0x20, 0x57,
-+			0x98, 0x81, 0x84, 0x4f, 0x15, 0x5c, 0x76, 0xe7,
-+			0x3e, 0x0a, 0x3a, 0x6c, 0xc4, 0x8a, 0xbe, 0x78,
-+			0x74, 0x77, 0xc3, 0x09, 0x4b, 0x5d, 0x48, 0xe4,
-+			0xc8, 0xcb, 0x0b, 0xea, 0x17, 0x28, 0xcf, 0xcf,
-+			0x31, 0x32, 0x44, 0xa4, 0xe5, 0x0e, 0x1a, 0x98,
-+			0x94, 0xc4, 0xf0, 0xff, 0xae, 0x3e, 0x44, 0xe8,
-+			0xa5, 0xb3, 0xb5, 0x37, 0x2f, 0xe8, 0xaf, 0x6f,
-+			0x28, 0xc1, 0x37, 0x5f, 0x31, 0xd2, 0xb9, 0x33,
-+			0xb1, 0xb2, 0x52, 0x94, 0x75, 0x2c, 0x29, 0x59,
-+			0x06, 0xc2, 0x25, 0xe8, 0x71, 0x65, 0x4e, 0xed,
-+			0xc0, 0x9c, 0xb1, 0xbb, 0x25, 0xdc, 0x6c, 0xe7,
-+			0x4b, 0xa5, 0x7a, 0x54, 0x7a, 0x60, 0xff, 0x7a,
-+			0xe0, 0x50, 0x40, 0x96, 0x35, 0x63, 0xe4, 0x0b,
-+			0x76, 0xbd, 0xa4, 0x65, 0x00, 0x1b, 0x57, 0x88,
-+			0xae, 0xed, 0x39, 0x88, 0x42, 0x11, 0x3c, 0xed,
-+			0x85, 0x67, 0x7d, 0xb9, 0x68, 0x82, 0xe9, 0x43,
-+			0x3c, 0x47, 0x53, 0xfa, 0xe8, 0xf8, 0x9f, 0x1f,
-+			0x9f, 0xef, 0x0f, 0xf7, 0x30, 0xd9, 0x30, 0x0e,
-+			0xb9, 0x9f, 0x69, 0x18, 0x2f, 0x7e, 0xf8, 0xf8,
-+			0xf8, 0x8c, 0x0f, 0xd4, 0x02, 0x4d, 0xea, 0xcd,
-+			0x0a, 0x9c, 0x6f, 0x71, 0x6d, 0x5a, 0x4c, 0x60,
-+			0xce, 0x20, 0x56, 0x32, 0xc6, 0xc5, 0x99, 0x1f,
-+			0x09, 0xe6, 0x4e, 0x18, 0x1a, 0x15, 0x13, 0xa8,
-+			0x7d, 0xb1, 0x6b, 0xc0, 0xb2, 0x6d, 0xf8, 0x26,
-+			0x66, 0xf8, 0x3d, 0x18, 0x74, 0x70, 0x66, 0x7a,
-+			0x34, 0x17, 0xde, 0xba, 0x47, 0xf1, 0x06, 0x18,
-+			0xcb, 0xaf, 0xeb, 0x4a, 0x1e, 0x8f, 0xa7, 0x77,
-+			0xe0, 0x3b, 0x78, 0x62, 0x66, 0xc9, 0x10, 0xea,
-+			0x1f, 0xb7, 0x29, 0x0a, 0x45, 0xa1, 0x1d, 0x1e,
-+			0x1d, 0xe2, 0x65, 0x61, 0x50, 0x9c, 0xd7, 0x05,
-+			0xf2, 0x0b, 0x5b, 0x12, 0x61, 0x02, 0xc8, 0xe5,
-+			0x63, 0x4f, 0x20, 0x0c, 0x07, 0x17, 0x33, 0x5e,
-+			0x03, 0x9a, 0x53, 0x0f, 0x2e, 0x55, 0xfe, 0x50,
-+			0x43, 0x7d, 0xd0, 0xb6, 0x7e, 0x5a, 0xda, 0xae,
-+			0x58, 0xef, 0x15, 0xa9, 0x83, 0xd9, 0x46, 0xb1,
-+			0x42, 0xaa, 0xf5, 0x02, 0x6c, 0xce, 0x92, 0x06,
-+			0x1b, 0xdb, 0x66, 0x45, 0x91, 0x79, 0xc2, 0x2d,
-+			0xe6, 0x53, 0xd3, 0x14, 0xfd, 0xbb, 0x44, 0x63,
-+			0xc6, 0xd7, 0x3d, 0x7a, 0x0c, 0x75, 0x78, 0x9d,
-+			0x5c, 0xa6, 0x39, 0xb3, 0xe5, 0x63, 0xca, 0x8b,
-+			0xfe, 0xd3, 0xef, 0x60, 0x83, 0xf6, 0x8e, 0x70,
-+			0xb6, 0x67, 0xc7, 0x77, 0xed, 0x23, 0xef, 0x4c,
-+			0xf0, 0xed, 0x2d, 0x07, 0x59, 0x6f, 0xc1, 0x01,
-+			0x34, 0x37, 0x08, 0xab, 0xd9, 0x1f, 0x09, 0xb1,
-+			0xce, 0x5b, 0x17, 0xff, 0x74, 0xf8, 0x9c, 0xd5,
-+			0x2c, 0x56, 0x39, 0x79, 0x0f, 0x69, 0x44, 0x75,
-+			0x58, 0x27, 0x01, 0xc4, 0xbf, 0xa7, 0xa1, 0x1d,
-+			0x90, 0x17, 0x77, 0x86, 0x5a, 0x3f, 0xd9, 0xd1,
-+			0x0e, 0xa0, 0x10, 0xf8, 0xec, 0x1e, 0xa5, 0x7f,
-+			0x5e, 0x36, 0xd1, 0xe3, 0x04, 0x2c, 0x70, 0xf7,
-+			0x8e, 0xc0, 0x98, 0x2f, 0x6c, 0x94, 0x2b, 0x41,
-+			0xb7, 0x60, 0x00, 0xb7, 0x2e, 0xb8, 0x02, 0x8d,
-+			0xb8, 0xb0, 0xd3, 0x86, 0xba, 0x1d, 0xd7, 0x90,
-+			0xd6, 0xb6, 0xe1, 0xfc, 0xd7, 0xd8, 0x28, 0x06,
-+			0x63, 0x9b, 0xce, 0x61, 0x24, 0x79, 0xc0, 0x70,
-+			0x52, 0xd0, 0xb6, 0xd4, 0x28, 0x95, 0x24, 0x87,
-+			0x03, 0x1f, 0xb7, 0x9a, 0xda, 0xa3, 0xfb, 0x52,
-+			0x5b, 0x68, 0xe7, 0x4c, 0x8c, 0x24, 0xe1, 0x42,
-+			0xf7, 0xd5, 0xfd, 0xad, 0x06, 0x32, 0x9f, 0xba,
-+			0xc1, 0xfc, 0xdd, 0xc6, 0xfc, 0xfc, 0xb3, 0x38,
-+			0x74, 0x56, 0x58, 0x40, 0x02, 0x37, 0x52, 0x2c,
-+			0x55, 0xcc, 0xb3, 0x9e, 0x7a, 0xe9, 0xd4, 0x38,
-+			0x41, 0x5e, 0x0c, 0x35, 0xe2, 0x11, 0xd1, 0x13,
-+			0xf8, 0xb7, 0x8d, 0x72, 0x6b, 0x22, 0x2a, 0xb0,
-+			0xdb, 0x08, 0xba, 0x35, 0xb9, 0x3f, 0xc8, 0xd3,
-+			0x24, 0x90, 0xec, 0x58, 0xd2, 0x09, 0xc7, 0x2d,
-+			0xed, 0x38, 0x80, 0x36, 0x72, 0x43, 0x27, 0x49,
-+			0x4a, 0x80, 0x8a, 0xa2, 0xe8, 0xd3, 0xda, 0x30,
-+			0x7d, 0xb6, 0x82, 0x37, 0x86, 0x92, 0x86, 0x3e,
-+			0x08, 0xb2, 0x28, 0x5a, 0x55, 0x44, 0x24, 0x7d,
-+			0x40, 0x48, 0x8a, 0xb6, 0x89, 0x58, 0x08, 0xa0,
-+			0xd6, 0x6d, 0x3a, 0x17, 0xbf, 0xf6, 0x54, 0xa2,
-+			0xf5, 0xd3, 0x8c, 0x0f, 0x78, 0x12, 0x57, 0x8b,
-+			0xd5, 0xc2, 0xfd, 0x58, 0x5b, 0x7f, 0x38, 0xe3,
-+			0xcc, 0xb7, 0x7c, 0x48, 0xb3, 0x20, 0xe8, 0x81,
-+			0x14, 0x32, 0x45, 0x05, 0xe0, 0xdb, 0x9f, 0x75,
-+			0x85, 0xb4, 0x6a, 0xfc, 0x95, 0xe3, 0x54, 0x22,
-+			0x12, 0xee, 0x30, 0xfe, 0xd8, 0x30, 0xef, 0x34,
-+			0x50, 0xab, 0x46, 0x30, 0x98, 0x2f, 0xb7, 0xc0,
-+			0x15, 0xa2, 0x83, 0xb6, 0xf2, 0x06, 0x21, 0xa2,
-+			0xc3, 0x26, 0x37, 0x14, 0xd1, 0x4d, 0xb5, 0x10,
-+			0x52, 0x76, 0x4d, 0x6a, 0xee, 0xb5, 0x2b, 0x15,
-+			0xb7, 0xf9, 0x51, 0xe8, 0x2a, 0xaf, 0xc7, 0xfa,
-+			0x77, 0xaf, 0xb0, 0x05, 0x4d, 0xd1, 0x68, 0x8e,
-+			0x74, 0x05, 0x9f, 0x9d, 0x93, 0xa5, 0x3e, 0x7f,
-+			0x4e, 0x5f, 0x9d, 0xcb, 0x09, 0xc7, 0x83, 0xe3,
-+			0x02, 0x9d, 0x27, 0x1f, 0xef, 0x85, 0x05, 0x8d,
-+			0xec, 0x55, 0x88, 0x0f, 0x0d, 0x7c, 0x4c, 0xe8,
-+			0xa1, 0x75, 0xa0, 0xd8, 0x06, 0x47, 0x14, 0xef,
-+			0xaa, 0x61, 0xcf, 0x26, 0x15, 0xad, 0xd8, 0xa3,
-+			0xaa, 0x75, 0xf2, 0x78, 0x4a, 0x5a, 0x61, 0xdf,
-+			0x8b, 0xc7, 0x04, 0xbc, 0xb2, 0x32, 0xd2, 0x7e,
-+			0x42, 0xee, 0xb4, 0x2f, 0x51, 0xff, 0x7b, 0x2e,
-+			0xd3, 0x02, 0xe8, 0xdc, 0x5d, 0x0d, 0x50, 0xdc,
-+			0xae, 0xb7, 0x46, 0xf9, 0xa8, 0xe6, 0xd0, 0x16,
-+			0xcc, 0xe6, 0x2c, 0x81, 0xc7, 0xad, 0xe9, 0xf0,
-+			0x05, 0x72, 0x6d, 0x3d, 0x0a, 0x7a, 0xa9, 0x02,
-+			0xac, 0x82, 0x93, 0x6e, 0xb6, 0x1c, 0x28, 0xfc,
-+			0x44, 0x12, 0xfb, 0x73, 0x77, 0xd4, 0x13, 0x39,
-+			0x29, 0x88, 0x8a, 0xf3, 0x5c, 0xa6, 0x36, 0xa0,
-+			0x2a, 0xed, 0x7e, 0xb1, 0x1d, 0xd6, 0x4c, 0x6b,
-+			0x41, 0x01, 0x18, 0x5d, 0x5d, 0x07, 0x97, 0xa6,
-+			0x4b, 0xef, 0x31, 0x18, 0xea, 0xac, 0xb1, 0x84,
-+			0x21, 0xed, 0xda, 0x86,
-+		},
-+		.rlen = 4100,
-+	},
-+};
-+
-+static struct cipher_testvec aes_ctr_dec_tv_template[] = {
-+	{ /* From RFC 3686 */
-+		.key	= { 0xae, 0x68, 0x52, 0xf8, 0x12, 0x10, 0x67, 0xcc,
-+			    0x4b, 0xf7, 0xa5, 0x76, 0x55, 0x77, 0xf3, 0x9e,
-+			    0x00, 0x00, 0x00, 0x30 },
-+		.klen	= 20,
-+		.iv 	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-+		.input	= { 0xe4, 0x09, 0x5d, 0x4f, 0xb7, 0xa7, 0xb3, 0x79,
-+			    0x2d, 0x61, 0x75, 0xa3, 0x26, 0x13, 0x11, 0xb8 },
-+		.ilen	= 16,
-+		.result	= { "Single block msg" },
-+		.rlen	= 16,
-+	}, {
-+		.key	= { 0x7e, 0x24, 0x06, 0x78, 0x17, 0xfa, 0xe0, 0xd7,
-+			    0x43, 0xd6, 0xce, 0x1f, 0x32, 0x53, 0x91, 0x63,
-+			    0x00, 0x6c, 0xb6, 0xdb },
-+		.klen	= 20,
-+		.iv 	= { 0xc0, 0x54, 0x3b, 0x59, 0xda, 0x48, 0xd9, 0x0b },
-+		.input	= { 0x51, 0x04, 0xa1, 0x06, 0x16, 0x8a, 0x72, 0xd9,
-+			    0x79, 0x0d, 0x41, 0xee, 0x8e, 0xda, 0xd3, 0x88,
-+			    0xeb, 0x2e, 0x1e, 0xfc, 0x46, 0xda, 0x57, 0xc8,
-+			    0xfc, 0xe6, 0x30, 0xdf, 0x91, 0x41, 0xbe, 0x28 },
-+		.ilen 	= 32,
-+		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-+		.rlen	= 32,
-+	}, {
-+		.key 	= { 0x16, 0xaf, 0x5b, 0x14, 0x5f, 0xc9, 0xf5, 0x79,
-+			    0xc1, 0x75, 0xf9, 0x3e, 0x3b, 0xfb, 0x0e, 0xed,
-+			    0x86, 0x3d, 0x06, 0xcc, 0xfd, 0xb7, 0x85, 0x15,
-+			    0x00, 0x00, 0x00, 0x48 },
-+		.klen 	= 28,
-+		.iv	= { 0x36, 0x73, 0x3c, 0x14, 0x7d, 0x6d, 0x93, 0xcb },
-+		.input	= { 0x4b, 0x55, 0x38, 0x4f, 0xe2, 0x59, 0xc9, 0xc8,
-+			    0x4e, 0x79, 0x35, 0xa0, 0x03, 0xcb, 0xe9, 0x28 },
-+		.ilen 	= 16,
-+		.result	= { "Single block msg" },
-+		.rlen	= 16,
-+	}, {
-+		.key	= { 0x7c, 0x5c, 0xb2, 0x40, 0x1b, 0x3d, 0xc3, 0x3c,
-+			    0x19, 0xe7, 0x34, 0x08, 0x19, 0xe0, 0xf6, 0x9c,
-+			    0x67, 0x8c, 0x3d, 0xb8, 0xe6, 0xf6, 0xa9, 0x1a,
-+			    0x00, 0x96, 0xb0, 0x3b },
-+		.klen	= 28,
-+		.iv 	= { 0x02, 0x0c, 0x6e, 0xad, 0xc2, 0xcb, 0x50, 0x0d },
-+		.input	= { 0x45, 0x32, 0x43, 0xfc, 0x60, 0x9b, 0x23, 0x32,
-+			    0x7e, 0xdf, 0xaa, 0xfa, 0x71, 0x31, 0xcd, 0x9f,
-+			    0x84, 0x90, 0x70, 0x1c, 0x5a, 0xd4, 0xa7, 0x9c,
-+			    0xfc, 0x1f, 0xe0, 0xff, 0x42, 0xf4, 0xfb, 0x00 },
-+		.ilen	= 32,
-+		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-+		.rlen 	= 32,
-+	}, { 
-+		.key 	= { 0x77, 0x6b, 0xef, 0xf2, 0x85, 0x1d, 0xb0, 0x6f,
-+			    0x4c, 0x8a, 0x05, 0x42, 0xc8, 0x69, 0x6f, 0x6c,
-+			    0x6a, 0x81, 0xaf, 0x1e, 0xec, 0x96, 0xb4, 0xd3,
-+			    0x7f, 0xc1, 0xd6, 0x89, 0xe6, 0xc1, 0xc1, 0x04,
-+			    0x00, 0x00, 0x00, 0x60 },
-+		.klen	= 36,
-+		.iv 	= { 0xdb, 0x56, 0x72, 0xc9, 0x7a, 0xa8, 0xf0, 0xb2 },
-+		.input	= { 0x14, 0x5a, 0xd0, 0x1d, 0xbf, 0x82, 0x4e, 0xc7,
-+			    0x56, 0x08, 0x63, 0xdc, 0x71, 0xe3, 0xe0, 0xc0 },
-+		.ilen	= 16,
-+		.result	= { "Single block msg" },
-+		.rlen 	= 16,
-+	}, {
-+		.key	= { 0xf6, 0xd6, 0x6d, 0x6b, 0xd5, 0x2d, 0x59, 0xbb,
-+			    0x07, 0x96, 0x36, 0x58, 0x79, 0xef, 0xf8, 0x86,
-+			    0xc6, 0x6d, 0xd5, 0x1a, 0x5b, 0x6a, 0x99, 0x74,
-+			    0x4b, 0x50, 0x59, 0x0c, 0x87, 0xa2, 0x38, 0x84,
-+			    0x00, 0xfa, 0xac, 0x24 },
-+		.klen 	= 36,
-+		.iv	= { 0xc1, 0x58, 0x5e, 0xf1, 0x5a, 0x43, 0xd8, 0x75 },
-+		.input	= { 0xf0, 0x5e, 0x23, 0x1b, 0x38, 0x94, 0x61, 0x2c,
-+			    0x49, 0xee, 0x00, 0x0b, 0x80, 0x4e, 0xb2, 0xa9,
-+			    0xb8, 0x30, 0x6b, 0x50, 0x8f, 0x83, 0x9d, 0x6a,
-+			    0x55, 0x30, 0x83, 0x1d, 0x93, 0x44, 0xaf, 0x1c },
-+		.ilen	= 32,
-+		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
-+		.rlen	= 32,
-+	},
-+};
++	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
++		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
++		if (want_ncq != using_ncq)
++			__mv_stop_dma(ap);
++	}
+ 	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
++		struct mv_host_priv *hpriv = ap->host->private_data;
++		int hard_port = mv_hardport_from_port(ap->port_no);
++		void __iomem *hc_mmio = mv_hc_base_from_port(
++				ap->host->iomap[MV_PRIMARY_BAR], hard_port);
++		u32 hc_irq_cause, ipending;
 +
-+static struct aead_testvec aes_gcm_enc_tv_template[] = {
-+	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
-+		.klen	= 16,
-+		.result	= { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
-+			    0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
-+		.rlen	= 16,
-+	}, {
-+		.klen	= 16,
-+		.ilen	= 16,
-+		.result = { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
-+			    0xf3, 0x28, 0xc2, 0xb9, 0x71, 0xb2, 0xfe, 0x78,
-+			    0xab, 0x6e, 0x47, 0xd4, 0x2c, 0xec, 0x13, 0xbd,
-+			    0xf5, 0x3a, 0x67, 0xb2, 0x12, 0x57, 0xbd, 0xdf },
-+		.rlen	= 32,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-+		.klen	= 16,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
-+		.ilen	= 64,
-+		.result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
-+			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
-+			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
-+			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
-+			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
-+			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
-+			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
-+			    0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
-+			    0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
-+			    0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
-+		.rlen	= 80,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-+		.klen	= 16,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39 },
-+		.ilen	= 60,
-+		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xab, 0xad, 0xda, 0xd2 },
-+		.alen	= 20,
-+		.result = { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
-+			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
-+			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
-+			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
-+			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
-+			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
-+			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
-+			    0x3d, 0x58, 0xe0, 0x91,
-+			    0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
-+			    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
-+		.rlen	= 76,
-+	}, {
-+		.klen	= 24,
-+		.result	= { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
-+			    0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
-+		.rlen	= 16,
-+	}, {
-+		.klen	= 24,
-+		.ilen	= 16,
-+		.result = { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
-+			    0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
-+			    0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
-+			    0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
-+		.rlen	= 32,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
-+			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
-+		.klen	= 24,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
-+		.ilen	= 64,
-+		.result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
-+			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
-+			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
-+			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
-+			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
-+			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
-+			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
-+			    0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
-+			    0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
-+			    0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
-+		.rlen	= 80,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
-+			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
-+		.klen	= 24,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39 },
-+		.ilen	= 60,
-+		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xab, 0xad, 0xda, 0xd2 },
-+		.alen	= 20,
-+		.result = { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
-+			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
-+			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
-+			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
-+			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
-+			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
-+			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
-+			    0xcc, 0xda, 0x27, 0x10,
-+			    0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
-+			    0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
-+		.rlen	= 76,
-+		.np	= 2,
-+		.tap	= { 32, 28 },
-+		.anp	= 2,
-+		.atap	= { 8, 12 }
-+	}, {
-+		.klen	= 32,
-+		.result	= { 0x53, 0x0f, 0x8a, 0xfb, 0xc7, 0x45, 0x36, 0xb9,
-+			    0xa9, 0x63, 0xb4, 0xf1, 0xc4, 0xcb, 0x73, 0x8b },
-+		.rlen	= 16,
+ 		/* clear EDMA event indicators, if any */
+-		writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
++		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
++
++		/* clear EDMA interrupt indicator, if any */
++		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
++		ipending = (DEV_IRQ << hard_port) |
++				(CRPB_DMA_DONE << hard_port);
++		if (hc_irq_cause & ipending) {
++			writelfl(hc_irq_cause & ~ipending,
++				 hc_mmio + HC_IRQ_CAUSE_OFS);
++		}
++
++		mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
++
++		/* clear FIS IRQ Cause */
++		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
+ 
+-		mv_set_edma_ptrs(base, hpriv, pp);
++		mv_set_edma_ptrs(port_mmio, hpriv, pp);
+ 
+-		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
++		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
+ 		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
+ 	}
+-	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
++	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
+ }
+ 
+ /**
+@@ -1003,38 +1029,76 @@ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+ 		return -EINVAL;
+ }
+ 
+-static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
+-			void __iomem *port_mmio)
++static void mv6_dev_config(struct ata_device *adev)
+ {
+-	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
++	/*
++	 * We don't have hob_nsect when doing NCQ commands on Gen-II.
++	 * See mv_qc_prep() for more info.
++	 */
++	if (adev->flags & ATA_DFLAG_NCQ)
++		if (adev->max_sectors > ATA_MAX_SECTORS)
++			adev->max_sectors = ATA_MAX_SECTORS;
++}
++
++static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
++			void __iomem *port_mmio, int want_ncq)
++{
++	u32 cfg;
+ 
+ 	/* set up non-NCQ EDMA configuration */
+-	cfg &= ~(1 << 9);	/* disable eQue */
++	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
+ 
+-	if (IS_GEN_I(hpriv)) {
+-		cfg &= ~0x1f;		/* clear queue depth */
++	if (IS_GEN_I(hpriv))
+ 		cfg |= (1 << 8);	/* enab config burst size mask */
+-	}
+ 
+-	else if (IS_GEN_II(hpriv)) {
+-		cfg &= ~0x1f;		/* clear queue depth */
++	else if (IS_GEN_II(hpriv))
+ 		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
+-		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
+-	}
+ 
+ 	else if (IS_GEN_IIE(hpriv)) {
+ 		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
+ 		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
+-		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
+ 		cfg |= (1 << 18);	/* enab early completion */
+ 		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
+-		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
+-		cfg &= ~(EDMA_CFG_NCQ);	/* clear NCQ */
+ 	}
+ 
++	if (want_ncq) {
++		cfg |= EDMA_CFG_NCQ;
++		pp->pp_flags |=  MV_PP_FLAG_NCQ_EN;
++	} else
++		pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
++
+ 	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
+ }
+ 
++static void mv_port_free_dma_mem(struct ata_port *ap)
++{
++	struct mv_host_priv *hpriv = ap->host->private_data;
++	struct mv_port_priv *pp = ap->private_data;
++	int tag;
++
++	if (pp->crqb) {
++		dma_pool_free(hpriv->crqb_pool, pp->crqb, pp->crqb_dma);
++		pp->crqb = NULL;
 +	}
-+};
++	if (pp->crpb) {
++		dma_pool_free(hpriv->crpb_pool, pp->crpb, pp->crpb_dma);
++		pp->crpb = NULL;
++	}
++	/*
++	 * For GEN_I, there's no NCQ, so we have only a single sg_tbl.
++	 * For later hardware, we have one unique sg_tbl per NCQ tag.
++	 */
++	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
++		if (pp->sg_tbl[tag]) {
++			if (tag == 0 || !IS_GEN_I(hpriv))
++				dma_pool_free(hpriv->sg_tbl_pool,
++					      pp->sg_tbl[tag],
++					      pp->sg_tbl_dma[tag]);
++			pp->sg_tbl[tag] = NULL;
++		}
++	}
++}
 +
-+static struct aead_testvec aes_gcm_dec_tv_template[] = {
-+	{ /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
-+		.klen	= 32,
-+		.input	= { 0xce, 0xa7, 0x40, 0x3d, 0x4d, 0x60, 0x6b, 0x6e,
-+			    0x07, 0x4e, 0xc5, 0xd3, 0xba, 0xf3, 0x9d, 0x18,
-+			    0xd0, 0xd1, 0xc8, 0xa7, 0x99, 0x99, 0x6b, 0xf0,
-+			    0x26, 0x5b, 0x98, 0xb5, 0xd4, 0x8a, 0xb9, 0x19 },
-+		.ilen	= 32,
-+		.rlen	= 16,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
-+			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-+		.klen	= 32,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
-+			    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
-+			    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
-+			    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
-+			    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
-+			    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
-+			    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
-+			    0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad,
-+			    0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd,
-+			    0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c },
-+		.ilen	= 80,
-+		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
-+		.rlen	= 64,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
-+			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-+		.klen	= 32,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07,
-+			    0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d,
-+			    0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9,
-+			    0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa,
-+			    0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d,
-+			    0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38,
-+			    0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a,
-+			    0xbc, 0xc9, 0xf6, 0x62,
-+			    0x76, 0xfc, 0x6e, 0xce, 0x0f, 0x4e, 0x17, 0x68,
-+			    0xcd, 0xdf, 0x88, 0x53, 0xbb, 0x2d, 0x55, 0x1b },
-+		.ilen	= 76,
-+		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xab, 0xad, 0xda, 0xd2 },
-+		.alen	= 20,
-+		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39 },
-+		.rlen	= 60,
-+		.np     = 2,
-+		.tap    = { 48, 28 },
-+		.anp	= 3,
-+		.atap	= { 8, 8, 4 }
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-+		.klen	= 16,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
-+			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
-+			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
-+			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
-+			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
-+			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
-+			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
-+			    0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85,
-+			    0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6,
-+			    0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 },
-+		.ilen	= 80,
-+		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
-+		.rlen	= 64,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 },
-+		.klen	= 16,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24,
-+			    0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c,
-+			    0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0,
-+			    0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e,
-+			    0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c,
-+			    0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05,
-+			    0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97,
-+			    0x3d, 0x58, 0xe0, 0x91,
-+			    0x5b, 0xc9, 0x4f, 0xbc, 0x32, 0x21, 0xa5, 0xdb,
-+			    0x94, 0xfa, 0xe9, 0x5a, 0xe7, 0x12, 0x1a, 0x47 },
-+		.ilen	= 76,
-+		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xab, 0xad, 0xda, 0xd2 },
-+		.alen	= 20,
-+		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39 },
-+		.rlen	= 60,
-+	}, {
-+		.klen	= 24,
-+		.input	= { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
-+			    0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00,
-+			    0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
-+			    0x8e, 0xf4, 0xd4, 0x58, 0x75, 0x14, 0xf0, 0xfb },
-+		.ilen	= 32,
-+		.rlen	= 16,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
-+			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
-+		.klen	= 24,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
-+			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
-+			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
-+			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
-+			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
-+			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
-+			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
-+			    0xcc, 0xda, 0x27, 0x10, 0xac, 0xad, 0xe2, 0x56,
-+			    0x99, 0x24, 0xa7, 0xc8, 0x58, 0x73, 0x36, 0xbf,
-+			    0xb1, 0x18, 0x02, 0x4d, 0xb8, 0x67, 0x4a, 0x14 },
-+		.ilen	= 80,
-+		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
-+		.rlen	= 64,
-+	}, {
-+		.key	= { 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c,
-+			    0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08,
-+			    0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c },
-+		.klen	= 24,
-+		.iv	= { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,
-+			    0xde, 0xca, 0xf8, 0x88 },
-+		.input	= { 0x39, 0x80, 0xca, 0x0b, 0x3c, 0x00, 0xe8, 0x41,
-+			    0xeb, 0x06, 0xfa, 0xc4, 0x87, 0x2a, 0x27, 0x57,
-+			    0x85, 0x9e, 0x1c, 0xea, 0xa6, 0xef, 0xd9, 0x84,
-+			    0x62, 0x85, 0x93, 0xb4, 0x0c, 0xa1, 0xe1, 0x9c,
-+			    0x7d, 0x77, 0x3d, 0x00, 0xc1, 0x44, 0xc5, 0x25,
-+			    0xac, 0x61, 0x9d, 0x18, 0xc8, 0x4a, 0x3f, 0x47,
-+			    0x18, 0xe2, 0x44, 0x8b, 0x2f, 0xe3, 0x24, 0xd9,
-+			    0xcc, 0xda, 0x27, 0x10,
-+			    0x25, 0x19, 0x49, 0x8e, 0x80, 0xf1, 0x47, 0x8f,
-+			    0x37, 0xba, 0x55, 0xbd, 0x6d, 0x27, 0x61, 0x8c },
-+		.ilen	= 76,
-+		.assoc	= { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
-+			    0xab, 0xad, 0xda, 0xd2 },
-+		.alen	= 20,
-+		.result = { 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,
-+			    0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,
-+			    0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,
-+			    0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,
-+			    0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,
-+			    0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,
-+			    0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,
-+			    0xba, 0x63, 0x7b, 0x39 },
-+		.rlen	= 60,
+ /**
+  *      mv_port_start - Port specific init/start routine.
+  *      @ap: ATA channel to manipulate
+@@ -1051,51 +1115,47 @@ static int mv_port_start(struct ata_port *ap)
+ 	struct mv_host_priv *hpriv = ap->host->private_data;
+ 	struct mv_port_priv *pp;
+ 	void __iomem *port_mmio = mv_ap_base(ap);
+-	void *mem;
+-	dma_addr_t mem_dma;
+ 	unsigned long flags;
+-	int rc;
++	int tag, rc;
+ 
+ 	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
+ 	if (!pp)
+ 		return -ENOMEM;
+-
+-	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
+-				  GFP_KERNEL);
+-	if (!mem)
+-		return -ENOMEM;
+-	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
++	ap->private_data = pp;
+ 
+ 	rc = ata_pad_alloc(ap, dev);
+ 	if (rc)
+ 		return rc;
+ 
+-	/* First item in chunk of DMA memory:
+-	 * 32-slot command request table (CRQB), 32 bytes each in size
+-	 */
+-	pp->crqb = mem;
+-	pp->crqb_dma = mem_dma;
+-	mem += MV_CRQB_Q_SZ;
+-	mem_dma += MV_CRQB_Q_SZ;
++	pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma);
++	if (!pp->crqb)
++		return -ENOMEM;
++	memset(pp->crqb, 0, MV_CRQB_Q_SZ);
+ 
+-	/* Second item:
+-	 * 32-slot command response table (CRPB), 8 bytes each in size
+-	 */
+-	pp->crpb = mem;
+-	pp->crpb_dma = mem_dma;
+-	mem += MV_CRPB_Q_SZ;
+-	mem_dma += MV_CRPB_Q_SZ;
++	pp->crpb = dma_pool_alloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma);
++	if (!pp->crpb)
++		goto out_port_free_dma_mem;
++	memset(pp->crpb, 0, MV_CRPB_Q_SZ);
+ 
+-	/* Third item:
+-	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
++	/*
++	 * For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
++	 * For later hardware, we need one unique sg_tbl per NCQ tag.
+ 	 */
+-	pp->sg_tbl = mem;
+-	pp->sg_tbl_dma = mem_dma;
++	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
++		if (tag == 0 || !IS_GEN_I(hpriv)) {
++			pp->sg_tbl[tag] = dma_pool_alloc(hpriv->sg_tbl_pool,
++					      GFP_KERNEL, &pp->sg_tbl_dma[tag]);
++			if (!pp->sg_tbl[tag])
++				goto out_port_free_dma_mem;
++		} else {
++			pp->sg_tbl[tag]     = pp->sg_tbl[0];
++			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
++		}
 +	}
-+};
+ 
+ 	spin_lock_irqsave(&ap->host->lock, flags);
+ 
+-	mv_edma_cfg(ap, hpriv, port_mmio);
+-
++	mv_edma_cfg(pp, hpriv, port_mmio, 0);
+ 	mv_set_edma_ptrs(port_mmio, hpriv, pp);
+ 
+ 	spin_unlock_irqrestore(&ap->host->lock, flags);
+@@ -1104,8 +1164,11 @@ static int mv_port_start(struct ata_port *ap)
+ 	 * we'll be unable to send non-data, PIO, etc due to restricted access
+ 	 * to shadow regs.
+ 	 */
+-	ap->private_data = pp;
+ 	return 0;
 +
-+static struct aead_testvec aes_ccm_enc_tv_template[] = {
-+	{ /* From RFC 3610 */
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
-+		.alen	= 8,
-+		.input	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
-+		.ilen	= 23,
-+		.result	= { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
-+			    0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
-+			    0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
-+			    0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
-+		.rlen	= 31,
-+	}, {
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b },
-+		.alen	= 12,
-+		.input	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-+			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
-+			    0x1c, 0x1d, 0x1e, 0x1f },
-+		.ilen	= 20,
-+		.result	= { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
-+			    0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
-+			    0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
-+			    0x7d, 0x9c, 0x2d, 0x93 },
-+		.rlen	= 28,
-+	}, {
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
-+		.alen	= 8,
-+		.input	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+			    0x20 },
-+		.ilen	= 25,
-+		.result	= { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
-+			    0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
-+			    0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
-+			    0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
-+			    0x7e, 0x5f, 0x4e },
-+		.rlen	= 35,
-+	}, {
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b },
-+		.alen	= 12,
-+		.input	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-+			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
-+			    0x1c, 0x1d, 0x1e },
-+		.ilen	= 19,
-+		.result	= { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
-+			    0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
-+			    0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
-+			    0x4d, 0x99, 0x99, 0x88, 0xdd },
-+		.rlen	= 29,
-+	}, {
-+		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
-+			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
-+			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
-+		.assoc	= { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
-+		.alen	= 8,
-+		.input	= { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
-+			    0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
-+			    0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
-+		.ilen	= 24,
-+		.result	= { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
-+			    0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
-+			    0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
-+			    0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
-+		.rlen	= 32,
-+	}, {
-+		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
-+			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
-+			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
-+		.assoc	= { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
-+			    0x20, 0xea, 0x60, 0xc0 },
-+		.alen	= 12,
-+		.input	= { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
-+			    0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
-+			    0x3a, 0x80, 0x3b, 0xa8, 0x7f },
-+		.ilen	= 21,
-+		.result	= { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
-+			    0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
-+			    0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
-+			    0x5a, 0xe0, 0x70, 0x45, 0x51 },
-+		.rlen	= 29,
-+	}, {
-+		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
-+			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
-+			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
-+		.assoc	= { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
-+		.alen	= 8,
-+		.input	= { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
-+			    0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
-+			    0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
-+		.ilen	= 23,
-+		.result	= { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
-+			    0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
-+			    0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
-+			    0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
-+			    0xba },
-+		.rlen	= 33,
-+	},
-+};
++out_port_free_dma_mem:
++	mv_port_free_dma_mem(ap);
++	return -ENOMEM;
+ }
+ 
+ /**
+@@ -1120,6 +1183,7 @@ static int mv_port_start(struct ata_port *ap)
+ static void mv_port_stop(struct ata_port *ap)
+ {
+ 	mv_stop_dma(ap);
++	mv_port_free_dma_mem(ap);
+ }
+ 
+ /**
+@@ -1136,9 +1200,10 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
+ 	struct mv_port_priv *pp = qc->ap->private_data;
+ 	struct scatterlist *sg;
+ 	struct mv_sg *mv_sg, *last_sg = NULL;
++	unsigned int si;
+ 
+-	mv_sg = pp->sg_tbl;
+-	ata_for_each_sg(sg, qc) {
++	mv_sg = pp->sg_tbl[qc->tag];
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		dma_addr_t addr = sg_dma_address(sg);
+ 		u32 sg_len = sg_dma_len(sg);
+ 
+@@ -1193,7 +1258,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
+ 	u16 flags = 0;
+ 	unsigned in_index;
+ 
+-	if (qc->tf.protocol != ATA_PROT_DMA)
++	if ((qc->tf.protocol != ATA_PROT_DMA) &&
++	    (qc->tf.protocol != ATA_PROT_NCQ))
+ 		return;
+ 
+ 	/* Fill in command request block
+@@ -1202,15 +1268,14 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
+ 		flags |= CRQB_FLAG_READ;
+ 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+ 	flags |= qc->tag << CRQB_TAG_SHIFT;
+-	flags |= qc->tag << CRQB_IOID_SHIFT;	/* 50xx appears to ignore this*/
+ 
+ 	/* get current queue index from software */
+ 	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
+ 
+ 	pp->crqb[in_index].sg_addr =
+-		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
++		cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
+ 	pp->crqb[in_index].sg_addr_hi =
+-		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
++		cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
+ 	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
+ 
+ 	cw = &pp->crqb[in_index].ata_cmd[0];
+@@ -1230,13 +1295,11 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
+ 	case ATA_CMD_WRITE_FUA_EXT:
+ 		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
+ 		break;
+-#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
+ 	case ATA_CMD_FPDMA_READ:
+ 	case ATA_CMD_FPDMA_WRITE:
+ 		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
+ 		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
+ 		break;
+-#endif				/* FIXME: remove this line when NCQ added */
+ 	default:
+ 		/* The only other commands EDMA supports in non-queued and
+ 		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
+@@ -1285,7 +1348,8 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
+ 	unsigned in_index;
+ 	u32 flags = 0;
+ 
+-	if (qc->tf.protocol != ATA_PROT_DMA)
++	if ((qc->tf.protocol != ATA_PROT_DMA) &&
++	    (qc->tf.protocol != ATA_PROT_NCQ))
+ 		return;
+ 
+ 	/* Fill in Gen IIE command request block
+@@ -1295,15 +1359,14 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
+ 
+ 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
+ 	flags |= qc->tag << CRQB_TAG_SHIFT;
+-	flags |= qc->tag << CRQB_IOID_SHIFT;	/* "I/O Id" is -really-
+-						   what we use as our tag */
++	flags |= qc->tag << CRQB_HOSTQ_SHIFT;
+ 
+ 	/* get current queue index from software */
+ 	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
+ 
+ 	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
+-	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
+-	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
++	crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
++	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
+ 	crqb->flags = cpu_to_le32(flags);
+ 
+ 	tf = &qc->tf;
+@@ -1350,10 +1413,10 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
+ 	struct ata_port *ap = qc->ap;
+ 	void __iomem *port_mmio = mv_ap_base(ap);
+ 	struct mv_port_priv *pp = ap->private_data;
+-	struct mv_host_priv *hpriv = ap->host->private_data;
+ 	u32 in_index;
+ 
+-	if (qc->tf.protocol != ATA_PROT_DMA) {
++	if ((qc->tf.protocol != ATA_PROT_DMA) &&
++	    (qc->tf.protocol != ATA_PROT_NCQ)) {
+ 		/* We're about to send a non-EDMA capable command to the
+ 		 * port.  Turn off EDMA so there won't be problems accessing
+ 		 * shadow block, etc registers.
+@@ -1362,13 +1425,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
+ 		return ata_qc_issue_prot(qc);
+ 	}
+ 
+-	mv_start_dma(port_mmio, hpriv, pp);
+-
+-	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
+-
+-	/* until we do queuing, the queue should be empty at this point */
+-	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
+-		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
++	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
+ 
+ 	pp->req_idx++;
+ 
+@@ -1436,6 +1493,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+ 		ata_ehi_hotplugged(ehi);
+ 		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
+ 			"dev disconnect" : "dev connect");
++		action |= ATA_EH_HARDRESET;
+ 	}
+ 
+ 	if (IS_GEN_I(hpriv)) {
+@@ -1464,7 +1522,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
+ 	}
+ 
+ 	/* Clear EDMA now that SERR cleanup done */
+-	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
++	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+ 
+ 	if (!err_mask) {
+ 		err_mask = AC_ERR_OTHER;
+@@ -1537,23 +1595,17 @@ static void mv_intr_edma(struct ata_port *ap)
+ 		 * support for queueing.  this works transparently for
+ 		 * queued and non-queued modes.
+ 		 */
+-		else if (IS_GEN_II(hpriv))
+-			tag = (le16_to_cpu(pp->crpb[out_index].id)
+-				>> CRPB_IOID_SHIFT_6) & 0x3f;
+-
+-		else /* IS_GEN_IIE */
+-			tag = (le16_to_cpu(pp->crpb[out_index].id)
+-				>> CRPB_IOID_SHIFT_7) & 0x3f;
++		else
++			tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
+ 
+ 		qc = ata_qc_from_tag(ap, tag);
+ 
+-		/* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
+-		 * bits (WARNING: might not necessarily be associated
+-		 * with this command), which -should- be clear
+-		 * if all is well
++		/* For non-NCQ mode, the lower 8 bits of status
++		 * are from EDMA_ERR_IRQ_CAUSE_OFS,
++		 * which should be zero if all went well.
+ 		 */
+ 		status = le16_to_cpu(pp->crpb[out_index].flags);
+-		if (unlikely(status & 0xff)) {
++		if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
+ 			mv_err_intr(ap, qc);
+ 			return;
+ 		}
+@@ -1714,20 +1766,21 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
+ 	struct ata_host *host = dev_instance;
+ 	unsigned int hc, handled = 0, n_hcs;
+ 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
+-	u32 irq_stat;
++	u32 irq_stat, irq_mask;
+ 
++	spin_lock(&host->lock);
+ 	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
++	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
+ 
+ 	/* check the cases where we either have nothing pending or have read
+ 	 * a bogus register value which can indicate HW removal or PCI fault
+ 	 */
+-	if (!irq_stat || (0xffffffffU == irq_stat))
+-		return IRQ_NONE;
++	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
++		goto out_unlock;
+ 
+ 	n_hcs = mv_get_hc_count(host->ports[0]->flags);
+-	spin_lock(&host->lock);
+ 
+-	if (unlikely(irq_stat & PCI_ERR)) {
++	if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
+ 		mv_pci_error(host, mmio);
+ 		handled = 1;
+ 		goto out_unlock;	/* skip all other HC irq handling */
+@@ -1798,8 +1851,9 @@ static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
+ 		return -EINVAL;
+ }
+ 
+-static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
++static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio)
+ {
++	struct pci_dev *pdev = to_pci_dev(host->dev);
+ 	int early_5080;
+ 
+ 	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
+@@ -1810,7 +1864,7 @@ static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
+ 		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
+ 	}
+ 
+-	mv_reset_pci_bus(pdev, mmio);
++	mv_reset_pci_bus(host, mmio);
+ }
+ 
+ static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
+@@ -1934,9 +1988,8 @@ static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
+ 
+ #undef ZERO
+ #define ZERO(reg) writel(0, mmio + (reg))
+-static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
++static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
+ {
+-	struct ata_host     *host = dev_get_drvdata(&pdev->dev);
+ 	struct mv_host_priv *hpriv = host->private_data;
+ 	u32 tmp;
+ 
+@@ -2328,11 +2381,6 @@ static void mv_error_handler(struct ata_port *ap)
+ 		  mv_hardreset, mv_postreset);
+ }
+ 
+-static void mv_post_int_cmd(struct ata_queued_cmd *qc)
+-{
+-	mv_stop_dma(qc->ap);
+-}
+-
+ static void mv_eh_freeze(struct ata_port *ap)
+ {
+ 	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
+@@ -2426,8 +2474,8 @@ static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
+ 	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
+ 	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
+ 
+-	/* unmask all EDMA error interrupts */
+-	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
++	/* unmask all non-transient EDMA error interrupts */
++	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
+ 
+ 	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
+ 		readl(port_mmio + EDMA_CFG_OFS),
+@@ -2585,7 +2633,6 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
+ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ {
+ 	int rc = 0, n_hc, port, hc;
+-	struct pci_dev *pdev = to_pci_dev(host->dev);
+ 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
+ 	struct mv_host_priv *hpriv = host->private_data;
+ 
+@@ -2606,7 +2653,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ 		goto done;
+ 
+ 	hpriv->ops->reset_flash(hpriv, mmio);
+-	hpriv->ops->reset_bus(pdev, mmio);
++	hpriv->ops->reset_bus(host, mmio);
+ 	hpriv->ops->enable_leds(hpriv, mmio);
+ 
+ 	for (port = 0; port < host->n_ports; port++) {
+@@ -2629,8 +2676,10 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
+ 
+ 		mv_port_init(&ap->ioaddr, port_mmio);
+ 
++#ifdef CONFIG_PCI
+ 		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
+ 		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
++#endif
+ 	}
+ 
+ 	for (hc = 0; hc < n_hc; hc++) {
+@@ -2667,6 +2716,55 @@ done:
+ 	return rc;
+ }
+ 
++#ifdef CONFIG_PCI
++static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
 +
-+static struct aead_testvec aes_ccm_dec_tv_template[] = {
-+	{ /* From RFC 3610 */
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
-+		.alen	= 8,
-+		.input	= { 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2,
-+			    0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
-+			    0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17,
-+			    0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 },
-+		.ilen	= 31,
-+		.result	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e },
-+		.rlen	= 23,
-+	}, {
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x07, 0x06, 0x05, 0x04,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b },
-+		.alen	= 12,
-+		.input	= { 0xdc, 0xf1, 0xfb, 0x7b, 0x5d, 0x9e, 0x23, 0xfb,
-+			    0x9d, 0x4e, 0x13, 0x12, 0x53, 0x65, 0x8a, 0xd8,
-+			    0x6e, 0xbd, 0xca, 0x3e, 0x51, 0xe8, 0x3f, 0x07,
-+			    0x7d, 0x9c, 0x2d, 0x93 },
-+		.ilen	= 28,
-+		.result	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-+			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
-+			    0x1c, 0x1d, 0x1e, 0x1f },
-+		.rlen	= 20,
-+	}, {
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0b, 0x0a, 0x09, 0x08,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 },
-+		.alen	= 8,
-+		.input	= { 0x82, 0x53, 0x1a, 0x60, 0xcc, 0x24, 0x94, 0x5a,
-+			    0x4b, 0x82, 0x79, 0x18, 0x1a, 0xb5, 0xc8, 0x4d,
-+			    0xf2, 0x1c, 0xe7, 0xf9, 0xb7, 0x3f, 0x42, 0xe1,
-+			    0x97, 0xea, 0x9c, 0x07, 0xe5, 0x6b, 0x5e, 0xb1,
-+			    0x7e, 0x5f, 0x4e },
-+		.ilen	= 35,
-+		.result	= { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+			    0x20 },
-+		.rlen	= 25,
-+	}, {
-+		.key	= { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			    0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x00, 0x00, 0x0c, 0x0b, 0x0a, 0x09,
-+			    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x00, 0x00 },
-+		.assoc	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0a, 0x0b },
-+		.alen	= 12,
-+		.input	= { 0x07, 0x34, 0x25, 0x94, 0x15, 0x77, 0x85, 0x15,
-+			    0x2b, 0x07, 0x40, 0x98, 0x33, 0x0a, 0xbb, 0x14,
-+			    0x1b, 0x94, 0x7b, 0x56, 0x6a, 0xa9, 0x40, 0x6b,
-+			    0x4d, 0x99, 0x99, 0x88, 0xdd },
-+		.ilen	= 29,
-+		.result	= { 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
-+			    0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
-+			    0x1c, 0x1d, 0x1e },
-+		.rlen	= 19,
-+	}, {
-+		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
-+			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x33, 0x56, 0x8e, 0xf7, 0xb2, 0x63,
-+			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
-+		.assoc	= { 0x63, 0x01, 0x8f, 0x76, 0xdc, 0x8a, 0x1b, 0xcb },
-+		.alen	= 8,
-+		.input	= { 0x4c, 0xcb, 0x1e, 0x7c, 0xa9, 0x81, 0xbe, 0xfa,
-+			    0xa0, 0x72, 0x6c, 0x55, 0xd3, 0x78, 0x06, 0x12,
-+			    0x98, 0xc8, 0x5c, 0x92, 0x81, 0x4a, 0xbc, 0x33,
-+			    0xc5, 0x2e, 0xe8, 0x1d, 0x7d, 0x77, 0xc0, 0x8a },
-+		.ilen	= 32,
-+		.result	= { 0x90, 0x20, 0xea, 0x6f, 0x91, 0xbd, 0xd8, 0x5a,
-+			    0xfa, 0x00, 0x39, 0xba, 0x4b, 0xaf, 0xf9, 0xbf,
-+			    0xb7, 0x9c, 0x70, 0x28, 0x94, 0x9c, 0xd0, 0xec },
-+		.rlen	= 24,
-+	}, {
-+		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
-+			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0xd5, 0x60, 0x91, 0x2d, 0x3f, 0x70,
-+			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
-+		.assoc	= { 0xcd, 0x90, 0x44, 0xd2, 0xb7, 0x1f, 0xdb, 0x81,
-+			    0x20, 0xea, 0x60, 0xc0 },
-+		.alen	= 12,
-+		.input	= { 0x00, 0x97, 0x69, 0xec, 0xab, 0xdf, 0x48, 0x62,
-+			    0x55, 0x94, 0xc5, 0x92, 0x51, 0xe6, 0x03, 0x57,
-+			    0x22, 0x67, 0x5e, 0x04, 0xc8, 0x47, 0x09, 0x9e,
-+			    0x5a, 0xe0, 0x70, 0x45, 0x51 },
-+		.ilen	= 29,
-+		.result	= { 0x64, 0x35, 0xac, 0xba, 0xfb, 0x11, 0xa8, 0x2e,
-+			    0x2f, 0x07, 0x1d, 0x7c, 0xa4, 0xa5, 0xeb, 0xd9,
-+			    0x3a, 0x80, 0x3b, 0xa8, 0x7f },
-+		.rlen	= 21,
-+	}, {
-+		.key	= { 0xd7, 0x82, 0x8d, 0x13, 0xb2, 0xb0, 0xbd, 0xc3,
-+			    0x25, 0xa7, 0x62, 0x36, 0xdf, 0x93, 0xcc, 0x6b },
-+		.klen	= 16,
-+		.iv	= { 0x01, 0x00, 0x42, 0xff, 0xf8, 0xf1, 0x95, 0x1c,
-+			    0x3c, 0x96, 0x96, 0x76, 0x6c, 0xfa, 0x00, 0x00 },
-+		.assoc	= { 0xd8, 0x5b, 0xc7, 0xe6, 0x9f, 0x94, 0x4f, 0xb8 },
-+		.alen	= 8,
-+		.input	= { 0xbc, 0x21, 0x8d, 0xaa, 0x94, 0x74, 0x27, 0xb6,
-+			    0xdb, 0x38, 0x6a, 0x99, 0xac, 0x1a, 0xef, 0x23,
-+			    0xad, 0xe0, 0xb5, 0x29, 0x39, 0xcb, 0x6a, 0x63,
-+			    0x7c, 0xf9, 0xbe, 0xc2, 0x40, 0x88, 0x97, 0xc6,
-+			    0xba },
-+		.ilen	= 33,
-+		.result	= { 0x8a, 0x19, 0xb9, 0x50, 0xbc, 0xf7, 0x1a, 0x01,
-+			    0x8e, 0x5e, 0x67, 0x01, 0xc9, 0x17, 0x87, 0x65,
-+			    0x98, 0x09, 0xd6, 0x7d, 0xbe, 0xdd, 0x18 },
-+		.rlen	= 23,
-+	},
++static struct pci_driver mv_pci_driver = {
++	.name			= DRV_NAME,
++	.id_table		= mv_pci_tbl,
++	.probe			= mv_init_one,
++	.remove			= ata_pci_remove_one,
 +};
 +
- /* Cast5 test vectors from RFC 2144 */
- #define CAST5_ENC_TEST_VECTORS	3
- #define CAST5_DEC_TEST_VECTORS	3
-@@ -4317,6 +6425,1211 @@ static struct cipher_testvec seed_dec_tv_template[] = {
++/*
++ * module options
++ */
++static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
++
++
++/* move to PCI layer or libata core? */
++static int pci_go_64(struct pci_dev *pdev)
++{
++	int rc;
++
++	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
++		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
++		if (rc) {
++			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
++			if (rc) {
++				dev_printk(KERN_ERR, &pdev->dev,
++					   "64-bit DMA enable failed\n");
++				return rc;
++			}
++		}
++	} else {
++		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
++		if (rc) {
++			dev_printk(KERN_ERR, &pdev->dev,
++				   "32-bit DMA enable failed\n");
++			return rc;
++		}
++		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
++		if (rc) {
++			dev_printk(KERN_ERR, &pdev->dev,
++				   "32-bit consistent DMA enable failed\n");
++			return rc;
++		}
++	}
++
++	return rc;
++}
++
+ /**
+  *      mv_print_info - Dump key info to kernel log for perusal.
+  *      @host: ATA host to print info about
+@@ -2709,6 +2807,26 @@ static void mv_print_info(struct ata_host *host)
+ 	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
+ }
+ 
++static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
++{
++	hpriv->crqb_pool   = dmam_pool_create("crqb_q", dev, MV_CRQB_Q_SZ,
++							     MV_CRQB_Q_SZ, 0);
++	if (!hpriv->crqb_pool)
++		return -ENOMEM;
++
++	hpriv->crpb_pool   = dmam_pool_create("crpb_q", dev, MV_CRPB_Q_SZ,
++							     MV_CRPB_Q_SZ, 0);
++	if (!hpriv->crpb_pool)
++		return -ENOMEM;
++
++	hpriv->sg_tbl_pool = dmam_pool_create("sg_tbl", dev, MV_SG_TBL_SZ,
++							     MV_SG_TBL_SZ, 0);
++	if (!hpriv->sg_tbl_pool)
++		return -ENOMEM;
++
++	return 0;
++}
++
+ /**
+  *      mv_init_one - handle a positive probe of a Marvell host
+  *      @pdev: PCI device found
+@@ -2754,6 +2872,10 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	if (rc)
+ 		return rc;
+ 
++	rc = mv_create_dma_pools(hpriv, &pdev->dev);
++	if (rc)
++		return rc;
++
+ 	/* initialize adapter */
+ 	rc = mv_init_host(host, board_idx);
+ 	if (rc)
+@@ -2771,15 +2893,22 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
+ 				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
+ }
++#endif
+ 
+ static int __init mv_init(void)
+ {
+-	return pci_register_driver(&mv_pci_driver);
++	int rc = -ENODEV;
++#ifdef CONFIG_PCI
++	rc = pci_register_driver(&mv_pci_driver);
++#endif
++	return rc;
+ }
+ 
+ static void __exit mv_exit(void)
+ {
++#ifdef CONFIG_PCI
+ 	pci_unregister_driver(&mv_pci_driver);
++#endif
+ }
+ 
+ MODULE_AUTHOR("Brett Russ");
+@@ -2788,8 +2917,10 @@ MODULE_LICENSE("GPL");
+ MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
+ MODULE_VERSION(DRV_VERSION);
+ 
++#ifdef CONFIG_PCI
+ module_param(msi, int, 0444);
+ MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
++#endif
+ 
+ module_init(mv_init);
+ module_exit(mv_exit);
+diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
+index ed5dc7c..bfe92a4 100644
+--- a/drivers/ata/sata_nv.c
++++ b/drivers/ata/sata_nv.c
+@@ -1011,14 +1011,20 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
+ 			}
+ 
+ 			if (status & (NV_ADMA_STAT_DONE |
+-				      NV_ADMA_STAT_CPBERR)) {
+-				u32 check_commands;
++				      NV_ADMA_STAT_CPBERR |
++				      NV_ADMA_STAT_CMD_COMPLETE)) {
++				u32 check_commands = notifier_clears[i];
+ 				int pos, error = 0;
+ 
+-				if (ata_tag_valid(ap->link.active_tag))
+-					check_commands = 1 << ap->link.active_tag;
+-				else
+-					check_commands = ap->link.sactive;
++				if (status & NV_ADMA_STAT_CPBERR) {
++					/* Check all active commands */
++					if (ata_tag_valid(ap->link.active_tag))
++						check_commands = 1 <<
++							ap->link.active_tag;
++					else
++						check_commands = ap->
++							link.sactive;
++				}
+ 
+ 				/** Check CPBs for completed commands */
+ 				while ((pos = ffs(check_commands)) && !error) {
+@@ -1336,21 +1342,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
+ static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
+ {
+ 	struct nv_adma_port_priv *pp = qc->ap->private_data;
+-	unsigned int idx;
+ 	struct nv_adma_prd *aprd;
+ 	struct scatterlist *sg;
++	unsigned int si;
+ 
+ 	VPRINTK("ENTER\n");
+ 
+-	idx = 0;
+-
+-	ata_for_each_sg(sg, qc) {
+-		aprd = (idx < 5) ? &cpb->aprd[idx] :
+-			       &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
+-		nv_adma_fill_aprd(qc, sg, idx, aprd);
+-		idx++;
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
++		aprd = (si < 5) ? &cpb->aprd[si] :
++			       &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
++		nv_adma_fill_aprd(qc, sg, si, aprd);
+ 	}
+-	if (idx > 5)
++	if (si > 5)
+ 		cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
+ 	else
+ 		cpb->next_aprd = cpu_to_le64(0);
+@@ -1995,17 +1998,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct scatterlist *sg;
+-	unsigned int idx;
+ 	struct nv_swncq_port_priv *pp = ap->private_data;
+ 	struct ata_prd *prd;
+-
+-	WARN_ON(qc->__sg == NULL);
+-	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
++	unsigned int si, idx;
+ 
+ 	prd = pp->prd + ATA_MAX_PRD * qc->tag;
+ 
+ 	idx = 0;
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		u32 addr, offset;
+ 		u32 sg_len, len;
+ 
+@@ -2027,8 +2027,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
+ 		}
+ 	}
+ 
+-	if (idx)
+-		prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++	prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ }
+ 
+ static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
+diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
+index 7914def..a07d319 100644
+--- a/drivers/ata/sata_promise.c
++++ b/drivers/ata/sata_promise.c
+@@ -450,19 +450,19 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
+ 	struct pdc_port_priv *pp = ap->private_data;
+ 	u8 *buf = pp->pkt;
+ 	u32 *buf32 = (u32 *) buf;
+-	unsigned int dev_sel, feature, nbytes;
++	unsigned int dev_sel, feature;
+ 
+ 	/* set control bits (byte 0), zero delay seq id (byte 3),
+ 	 * and seq id (byte 2)
+ 	 */
+ 	switch (qc->tf.protocol) {
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		if (!(qc->tf.flags & ATA_TFLAG_WRITE))
+ 			buf32[0] = cpu_to_le32(PDC_PKT_READ);
+ 		else
+ 			buf32[0] = 0;
+ 		break;
+-	case ATA_PROT_ATAPI_NODATA:
++	case ATAPI_PROT_NODATA:
+ 		buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
+ 		break;
+ 	default:
+@@ -473,45 +473,37 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
+ 	buf32[2] = 0;				/* no next-packet */
+ 
+ 	/* select drive */
+-	if (sata_scr_valid(&ap->link)) {
++	if (sata_scr_valid(&ap->link))
+ 		dev_sel = PDC_DEVICE_SATA;
+-	} else {
+-		dev_sel = ATA_DEVICE_OBS;
+-		if (qc->dev->devno != 0)
+-			dev_sel |= ATA_DEV1;
+-	}
++	else
++		dev_sel = qc->tf.device;
++
+ 	buf[12] = (1 << 5) | ATA_REG_DEVICE;
+ 	buf[13] = dev_sel;
+ 	buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
+ 	buf[15] = dev_sel; /* once more, waiting for BSY to clear */
+ 
+ 	buf[16] = (1 << 5) | ATA_REG_NSECT;
+-	buf[17] = 0x00;
++	buf[17] = qc->tf.nsect;
+ 	buf[18] = (1 << 5) | ATA_REG_LBAL;
+-	buf[19] = 0x00;
++	buf[19] = qc->tf.lbal;
+ 
+ 	/* set feature and byte counter registers */
+-	if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {
++	if (qc->tf.protocol != ATAPI_PROT_DMA)
+ 		feature = PDC_FEATURE_ATAPI_PIO;
+-		/* set byte counter register to real transfer byte count */
+-		nbytes = qc->nbytes;
+-		if (nbytes > 0xffff)
+-			nbytes = 0xffff;
+-	} else {
++	else
+ 		feature = PDC_FEATURE_ATAPI_DMA;
+-		/* set byte counter register to 0 */
+-		nbytes = 0;
+-	}
++
+ 	buf[20] = (1 << 5) | ATA_REG_FEATURE;
+ 	buf[21] = feature;
+ 	buf[22] = (1 << 5) | ATA_REG_BYTEL;
+-	buf[23] = nbytes & 0xFF;
++	buf[23] = qc->tf.lbam;
+ 	buf[24] = (1 << 5) | ATA_REG_BYTEH;
+-	buf[25] = (nbytes >> 8) & 0xFF;
++	buf[25] = qc->tf.lbah;
+ 
+ 	/* send ATAPI packet command 0xA0 */
+ 	buf[26] = (1 << 5) | ATA_REG_CMD;
+-	buf[27] = ATA_CMD_PACKET;
++	buf[27] = qc->tf.command;
+ 
+ 	/* select drive and check DRQ */
+ 	buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
+@@ -541,17 +533,15 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
+ {
+ 	struct ata_port *ap = qc->ap;
+ 	struct scatterlist *sg;
+-	unsigned int idx;
+ 	const u32 SG_COUNT_ASIC_BUG = 41*4;
++	unsigned int si, idx;
++	u32 len;
+ 
+ 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+ 		return;
+ 
+-	WARN_ON(qc->__sg == NULL);
+-	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+-
+ 	idx = 0;
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		u32 addr, offset;
+ 		u32 sg_len, len;
+ 
+@@ -578,29 +568,27 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
+ 		}
+ 	}
+ 
+-	if (idx) {
+-		u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
++	len = le32_to_cpu(ap->prd[idx - 1].flags_len);
+ 
+-		if (len > SG_COUNT_ASIC_BUG) {
+-			u32 addr;
++	if (len > SG_COUNT_ASIC_BUG) {
++		u32 addr;
+ 
+-			VPRINTK("Splitting last PRD.\n");
++		VPRINTK("Splitting last PRD.\n");
+ 
+-			addr = le32_to_cpu(ap->prd[idx - 1].addr);
+-			ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
+-			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
++		addr = le32_to_cpu(ap->prd[idx - 1].addr);
++		ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
++		VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
+ 
+-			addr = addr + len - SG_COUNT_ASIC_BUG;
+-			len = SG_COUNT_ASIC_BUG;
+-			ap->prd[idx].addr = cpu_to_le32(addr);
+-			ap->prd[idx].flags_len = cpu_to_le32(len);
+-			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
++		addr = addr + len - SG_COUNT_ASIC_BUG;
++		len = SG_COUNT_ASIC_BUG;
++		ap->prd[idx].addr = cpu_to_le32(addr);
++		ap->prd[idx].flags_len = cpu_to_le32(len);
++		VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
+ 
+-			idx++;
+-		}
+-
+-		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
++		idx++;
+ 	}
++
++	ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ }
+ 
+ static void pdc_qc_prep(struct ata_queued_cmd *qc)
+@@ -627,14 +615,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
+ 		pdc_pkt_footer(&qc->tf, pp->pkt, i);
+ 		break;
+ 
+-	case ATA_PROT_ATAPI:
++	case ATAPI_PROT_PIO:
+ 		pdc_fill_sg(qc);
+ 		break;
+ 
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		pdc_fill_sg(qc);
+ 		/*FALLTHROUGH*/
+-	case ATA_PROT_ATAPI_NODATA:
++	case ATAPI_PROT_NODATA:
+ 		pdc_atapi_pkt(qc);
+ 		break;
+ 
+@@ -754,8 +742,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
+ 	switch (qc->tf.protocol) {
+ 	case ATA_PROT_DMA:
+ 	case ATA_PROT_NODATA:
+-	case ATA_PROT_ATAPI_DMA:
+-	case ATA_PROT_ATAPI_NODATA:
++	case ATAPI_PROT_DMA:
++	case ATAPI_PROT_NODATA:
+ 		qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
+ 		ata_qc_complete(qc);
+ 		handled = 1;
+@@ -900,7 +888,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
+ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+ {
+ 	switch (qc->tf.protocol) {
+-	case ATA_PROT_ATAPI_NODATA:
++	case ATAPI_PROT_NODATA:
+ 		if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
+ 			break;
+ 		/*FALLTHROUGH*/
+@@ -908,7 +896,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		if (qc->tf.flags & ATA_TFLAG_POLLING)
+ 			break;
+ 		/*FALLTHROUGH*/
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 	case ATA_PROT_DMA:
+ 		pdc_packet_start(qc);
+ 		return 0;
+@@ -922,16 +910,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
+ 
+ static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
+ {
+-	WARN_ON(tf->protocol == ATA_PROT_DMA ||
+-		tf->protocol == ATA_PROT_ATAPI_DMA);
++	WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+ 	ata_tf_load(ap, tf);
+ }
+ 
+ static void pdc_exec_command_mmio(struct ata_port *ap,
+ 				  const struct ata_taskfile *tf)
+ {
+-	WARN_ON(tf->protocol == ATA_PROT_DMA ||
+-		tf->protocol == ATA_PROT_ATAPI_DMA);
++	WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
+ 	ata_exec_command(ap, tf);
+ }
+ 
+diff --git a/drivers/ata/sata_promise.h b/drivers/ata/sata_promise.h
+index 6ee5e19..00d6000 100644
+--- a/drivers/ata/sata_promise.h
++++ b/drivers/ata/sata_promise.h
+@@ -46,7 +46,7 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
+ 					  unsigned int devno, u8 *buf)
+ {
+ 	u8 dev_reg;
+-	u32 *buf32 = (u32 *) buf;
++	__le32 *buf32 = (__le32 *) buf;
+ 
+ 	/* set control bits (byte 0), zero delay seq id (byte 3),
+ 	 * and seq id (byte 2)
+diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
+index c68b241..91cc12c 100644
+--- a/drivers/ata/sata_qstor.c
++++ b/drivers/ata/sata_qstor.c
+@@ -287,14 +287,10 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
+ 	struct scatterlist *sg;
+ 	struct ata_port *ap = qc->ap;
+ 	struct qs_port_priv *pp = ap->private_data;
+-	unsigned int nelem;
+ 	u8 *prd = pp->pkt + QS_CPB_BYTES;
++	unsigned int si;
+ 
+-	WARN_ON(qc->__sg == NULL);
+-	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
+-
+-	nelem = 0;
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		u64 addr;
+ 		u32 len;
+ 
+@@ -306,12 +302,11 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
+ 		*(__le32 *)prd = cpu_to_le32(len);
+ 		prd += sizeof(u64);
+ 
+-		VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
++		VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", si,
+ 					(unsigned long long)addr, len);
+-		nelem++;
+ 	}
+ 
+-	return nelem;
++	return si;
+ }
+ 
+ static void qs_qc_prep(struct ata_queued_cmd *qc)
+@@ -376,7 +371,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
+ 		qs_packet_start(qc);
+ 		return 0;
+ 
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		BUG();
+ 		break;
+ 
+diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
+index f5119bf..0b8191b 100644
+--- a/drivers/ata/sata_sil.c
++++ b/drivers/ata/sata_sil.c
+@@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+ 		 */
+ 
+ 		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
+-		 * The flag was turned on only for atapi devices.
+-		 * No need to check is_atapi_taskfile(&qc->tf) again.
++		 * The flag was turned on only for atapi devices.  No
++		 * need to check ata_is_atapi(qc->tf.protocol) again.
+ 		 */
+ 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
+ 			goto err_hsm;
+ 		break;
+ 	case HSM_ST_LAST:
+-		if (qc->tf.protocol == ATA_PROT_DMA ||
+-		    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
++		if (ata_is_dma(qc->tf.protocol)) {
+ 			/* clear DMA-Start bit */
+ 			ap->ops->bmdma_stop(qc);
+ 
+@@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
+ 	/* kick HSM in the ass */
+ 	ata_hsm_move(ap, qc, status, 0);
+ 
+-	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
+-				       qc->tf.protocol == ATA_PROT_ATAPI_DMA))
++	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+ 		ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
+ 
+ 	return;
+diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
+index 864c1c1..b4b1f91 100644
+--- a/drivers/ata/sata_sil24.c
++++ b/drivers/ata/sata_sil24.c
+@@ -813,8 +813,9 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+ {
+ 	struct scatterlist *sg;
+ 	struct sil24_sge *last_sge = NULL;
++	unsigned int si;
+ 
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		sge->addr = cpu_to_le64(sg_dma_address(sg));
+ 		sge->cnt = cpu_to_le32(sg_dma_len(sg));
+ 		sge->flags = 0;
+@@ -823,8 +824,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
+ 		sge++;
+ 	}
+ 
+-	if (likely(last_sge))
+-		last_sge->flags = cpu_to_le32(SGE_TRM);
++	last_sge->flags = cpu_to_le32(SGE_TRM);
+ }
+ 
+ static int sil24_qc_defer(struct ata_queued_cmd *qc)
+@@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
+ 	 *   set.
+ 	 *
+  	 */
+-	int is_excl = (prot == ATA_PROT_ATAPI ||
+-		       prot == ATA_PROT_ATAPI_NODATA ||
+-		       prot == ATA_PROT_ATAPI_DMA ||
++	int is_excl = (ata_is_atapi(prot) ||
+ 		       (qc->flags & ATA_QCFLAG_RESULT_TF));
+ 
+ 	if (unlikely(ap->excl_link)) {
+@@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
+ 
+ 	cb = &pp->cmd_block[sil24_tag(qc->tag)];
+ 
+-	switch (qc->tf.protocol) {
+-	case ATA_PROT_PIO:
+-	case ATA_PROT_DMA:
+-	case ATA_PROT_NCQ:
+-	case ATA_PROT_NODATA:
++	if (!ata_is_atapi(qc->tf.protocol)) {
+ 		prb = &cb->ata.prb;
+ 		sge = cb->ata.sge;
+-		break;
+-
+-	case ATA_PROT_ATAPI:
+-	case ATA_PROT_ATAPI_DMA:
+-	case ATA_PROT_ATAPI_NODATA:
++	} else {
+ 		prb = &cb->atapi.prb;
+ 		sge = cb->atapi.sge;
+ 		memset(cb->atapi.cdb, 0, 32);
+ 		memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
+ 
+-		if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
++		if (ata_is_data(qc->tf.protocol)) {
+ 			if (qc->tf.flags & ATA_TFLAG_WRITE)
+ 				ctrl = PRB_CTRL_PACKET_WRITE;
+ 			else
+ 				ctrl = PRB_CTRL_PACKET_READ;
+ 		}
+-		break;
+-
+-	default:
+-		prb = NULL;	/* shut up, gcc */
+-		sge = NULL;
+-		BUG();
+ 	}
+ 
+ 	prb->ctrl = cpu_to_le16(ctrl);
+diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
+index 4d85718..e3d56bc 100644
+--- a/drivers/ata/sata_sx4.c
++++ b/drivers/ata/sata_sx4.c
+@@ -334,7 +334,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
+ {
+ 	u32 addr;
+ 	unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
+-	u32 *buf32 = (u32 *) buf;
++	__le32 *buf32 = (__le32 *) buf;
+ 
+ 	/* output ATA packet S/G table */
+ 	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
+@@ -356,7 +356,7 @@ static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
+ {
+ 	u32 addr;
+ 	unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
+-	u32 *buf32 = (u32 *) buf;
++	__le32 *buf32 = (__le32 *) buf;
+ 
+ 	/* output Host DMA packet S/G table */
+ 	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
+@@ -377,7 +377,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
+ 					    unsigned int portno)
+ {
+ 	unsigned int i, dw;
+-	u32 *buf32 = (u32 *) buf;
++	__le32 *buf32 = (__le32 *) buf;
+ 	u8 dev_reg;
+ 
+ 	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
+@@ -429,7 +429,8 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
+ 				     unsigned int portno)
+ {
+ 	unsigned int dw;
+-	u32 tmp, *buf32 = (u32 *) buf;
++	u32 tmp;
++	__le32 *buf32 = (__le32 *) buf;
+ 
+ 	unsigned int host_sg = PDC_20621_DIMM_BASE +
+ 			       (PDC_DIMM_WINDOW_STEP * portno) +
+@@ -473,7 +474,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
+ 	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
+ 	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
+ 	unsigned int portno = ap->port_no;
+-	unsigned int i, idx, total_len = 0, sgt_len;
++	unsigned int i, si, idx, total_len = 0, sgt_len;
+ 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
+ 
+ 	WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
+@@ -487,7 +488,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
+ 	 * Build S/G table
+ 	 */
+ 	idx = 0;
+-	ata_for_each_sg(sg, qc) {
++	for_each_sg(qc->sg, sg, qc->n_elem, si) {
+ 		buf[idx++] = cpu_to_le32(sg_dma_address(sg));
+ 		buf[idx++] = cpu_to_le32(sg_dma_len(sg));
+ 		total_len += sg_dma_len(sg);
+@@ -700,7 +701,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
+ 		pdc20621_packet_start(qc);
+ 		return 0;
+ 
+-	case ATA_PROT_ATAPI_DMA:
++	case ATAPI_PROT_DMA:
+ 		BUG();
+ 		break;
+ 
+diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
+index b34b382..7b44a59 100644
+--- a/drivers/atm/ambassador.c
++++ b/drivers/atm/ambassador.c
+@@ -2163,7 +2163,6 @@ static int __devinit amb_init (amb_dev * dev)
+ static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev) 
+ {
+       unsigned char pool;
+-      memset (dev, 0, sizeof(amb_dev));
+       
+       // set up known dev items straight away
+       dev->pci_dev = pci_dev; 
+@@ -2253,7 +2252,7 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
+ 		goto out_disable;
  	}
- };
  
-+#define SALSA20_STREAM_ENC_TEST_VECTORS 5
-+static struct cipher_testvec salsa20_stream_enc_tv_template[] = {
-+	/*
-+	* Testvectors from verified.test-vectors submitted to ECRYPT.
-+	* They are truncated to size 39, 64, 111, 129 to test a variety
-+	* of input length.
-+	*/
-+	{ /* Set 3, vector 0 */
-+		.key	= {
-+			    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			    0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
-+			  },
-+		.klen	= 16,
-+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-+		.input	= {
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			  },
-+		.ilen	= 39,
-+		.result	= {
-+			    0x2D, 0xD5, 0xC3, 0xF7, 0xBA, 0x2B, 0x20, 0xF7,
-+                            0x68, 0x02, 0x41, 0x0C, 0x68, 0x86, 0x88, 0x89,
-+                            0x5A, 0xD8, 0xC1, 0xBD, 0x4E, 0xA6, 0xC9, 0xB1,
-+                            0x40, 0xFB, 0x9B, 0x90, 0xE2, 0x10, 0x49, 0xBF,
-+                            0x58, 0x3F, 0x52, 0x79, 0x70, 0xEB, 0xC1,
-+			},
-+		.rlen	= 39,
-+	}, { /* Set 5, vector 0 */
-+		.key	= {
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+			  },
-+		.klen	= 16,
-+		.iv     = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-+		.input	= {
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			  },
-+		.ilen	= 64,
-+		.result	= {
-+			    0xB6, 0x6C, 0x1E, 0x44, 0x46, 0xDD, 0x95, 0x57,
-+                            0xE5, 0x78, 0xE2, 0x23, 0xB0, 0xB7, 0x68, 0x01,
-+                            0x7B, 0x23, 0xB2, 0x67, 0xBB, 0x02, 0x34, 0xAE,
-+                            0x46, 0x26, 0xBF, 0x44, 0x3F, 0x21, 0x97, 0x76,
-+                            0x43, 0x6F, 0xB1, 0x9F, 0xD0, 0xE8, 0x86, 0x6F,
-+                            0xCD, 0x0D, 0xE9, 0xA9, 0x53, 0x8F, 0x4A, 0x09,
-+                            0xCA, 0x9A, 0xC0, 0x73, 0x2E, 0x30, 0xBC, 0xF9,
-+                            0x8E, 0x4F, 0x13, 0xE4, 0xB9, 0xE2, 0x01, 0xD9,
-+			  },
-+		.rlen	= 64,
-+	}, { /* Set 3, vector 27 */
-+		.key	= {
-+			    0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22,
-+			    0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A,
-+                            0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32,
-+			    0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
-+			  },
-+		.klen	= 32,
-+		.iv     = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-+		.input	= {
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			  },
-+		.ilen	= 111,
-+		.result	= {
-+			    0xAE, 0x39, 0x50, 0x8E, 0xAC, 0x9A, 0xEC, 0xE7,
-+                            0xBF, 0x97, 0xBB, 0x20, 0xB9, 0xDE, 0xE4, 0x1F,
-+                            0x87, 0xD9, 0x47, 0xF8, 0x28, 0x91, 0x35, 0x98,
-+                            0xDB, 0x72, 0xCC, 0x23, 0x29, 0x48, 0x56, 0x5E,
-+                            0x83, 0x7E, 0x0B, 0xF3, 0x7D, 0x5D, 0x38, 0x7B,
-+                            0x2D, 0x71, 0x02, 0xB4, 0x3B, 0xB5, 0xD8, 0x23,
-+                            0xB0, 0x4A, 0xDF, 0x3C, 0xEC, 0xB6, 0xD9, 0x3B,
-+                            0x9B, 0xA7, 0x52, 0xBE, 0xC5, 0xD4, 0x50, 0x59,
+-	dev = kmalloc (sizeof(amb_dev), GFP_KERNEL);
++	dev = kzalloc(sizeof(amb_dev), GFP_KERNEL);
+ 	if (!dev) {
+ 		PRINTK (KERN_ERR, "out of memory!");
+ 		err = -ENOMEM;
+diff --git a/drivers/atm/he.c b/drivers/atm/he.c
+index 3b64a99..2e3395b 100644
+--- a/drivers/atm/he.c
++++ b/drivers/atm/he.c
+@@ -1,5 +1,3 @@
+-/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */
+-
+ /*
+ 
+   he.c
+@@ -99,10 +97,6 @@
+ #define HPRINTK(fmt,args...)	do { } while (0)
+ #endif /* HE_DEBUG */
+ 
+-/* version definition */
+-
+-static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $";
+-
+ /* declarations */
+ 
+ static int he_open(struct atm_vcc *vcc);
+@@ -366,7 +360,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+ 	struct he_dev *he_dev = NULL;
+ 	int err = 0;
+ 
+-	printk(KERN_INFO "he: %s\n", version);
++	printk(KERN_INFO "ATM he driver\n");
+ 
+ 	if (pci_enable_device(pci_dev))
+ 		return -EIO;
+@@ -1643,6 +1637,8 @@ he_stop(struct he_dev *he_dev)
+ 
+ 	if (he_dev->rbpl_base) {
+ #ifdef USE_RBPL_POOL
++		int i;
 +
-+                            0x15, 0x14, 0xB4, 0x0E, 0x40, 0xE6, 0x53, 0xD1,
-+                            0x83, 0x9C, 0x5B, 0xA0, 0x92, 0x29, 0x6B, 0x5E,
-+                            0x96, 0x5B, 0x1E, 0x2F, 0xD3, 0xAC, 0xC1, 0x92,
-+                            0xB1, 0x41, 0x3F, 0x19, 0x2F, 0xC4, 0x3B, 0xC6,
-+                            0x95, 0x46, 0x45, 0x54, 0xE9, 0x75, 0x03, 0x08,
-+                            0x44, 0xAF, 0xE5, 0x8A, 0x81, 0x12, 0x09,
-+			  },
-+		.rlen	= 111,
+ 		for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
+ 			void *cpuaddr = he_dev->rbpl_virt[i].virt;
+ 			dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
+@@ -1665,6 +1661,8 @@ he_stop(struct he_dev *he_dev)
+ #ifdef USE_RBPS
+ 	if (he_dev->rbps_base) {
+ #ifdef USE_RBPS_POOL
++		int i;
 +
-+	}, { /* Set 5, vector 27 */
-+		.key	= {
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-+			  },
-+		.klen	= 32,
-+		.iv     = { 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00 },
-+		.input	= {
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 		for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
+ 			void *cpuaddr = he_dev->rbps_virt[i].virt;
+ 			dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
+@@ -2933,7 +2931,7 @@ he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
+ 
+ 	left = *pos;
+ 	if (!left--)
+-		return sprintf(page, "%s\n", version);
++		return sprintf(page, "ATM he driver\n");
+ 
+ 	if (!left--)
+ 		return sprintf(page, "%s%s\n\n",
+diff --git a/drivers/base/Makefile b/drivers/base/Makefile
+index b39ea3f..c666373 100644
+--- a/drivers/base/Makefile
++++ b/drivers/base/Makefile
+@@ -5,12 +5,15 @@ obj-y			:= core.o sys.o bus.o dd.o \
+ 			   cpu.o firmware.o init.o map.o devres.o \
+ 			   attribute_container.o transport_class.o
+ obj-y			+= power/
+-obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o dmapool.o
++obj-$(CONFIG_HAS_DMA)	+= dma-mapping.o
+ obj-$(CONFIG_ISA)	+= isa.o
+ obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
+ obj-$(CONFIG_NUMA)	+= node.o
+ obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
+ obj-$(CONFIG_SMP)	+= topology.o
++ifeq ($(CONFIG_SYSFS),y)
++obj-$(CONFIG_MODULES)	+= module.o
++endif
+ obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
+ 
+ ifeq ($(CONFIG_DEBUG_DRIVER),y)
+diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
+index 7370d7c..3b43e8a 100644
+--- a/drivers/base/attribute_container.c
++++ b/drivers/base/attribute_container.c
+@@ -61,7 +61,7 @@ attribute_container_classdev_to_container(struct class_device *classdev)
+ }
+ EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+ 
+-static struct list_head attribute_container_list;
++static LIST_HEAD(attribute_container_list);
+ 
+ static DEFINE_MUTEX(attribute_container_mutex);
+ 
+@@ -320,9 +320,14 @@ attribute_container_add_attrs(struct class_device *classdev)
+ 	struct class_device_attribute **attrs =	cont->attrs;
+ 	int i, error;
+ 
+-	if (!attrs)
++	BUG_ON(attrs && cont->grp);
 +
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++	if (!attrs && !cont->grp)
+ 		return 0;
+ 
++	if (cont->grp)
++		return sysfs_create_group(&classdev->kobj, cont->grp);
 +
-+			    0x00,
-+			  },
-+		.ilen	= 129,
-+		.result	= {
-+			    0xD2, 0xDB, 0x1A, 0x5C, 0xF1, 0xC1, 0xAC, 0xDB,
-+                            0xE8, 0x1A, 0x7A, 0x43, 0x40, 0xEF, 0x53, 0x43,
-+                            0x5E, 0x7F, 0x4B, 0x1A, 0x50, 0x52, 0x3F, 0x8D,
-+                            0x28, 0x3D, 0xCF, 0x85, 0x1D, 0x69, 0x6E, 0x60,
-+                            0xF2, 0xDE, 0x74, 0x56, 0x18, 0x1B, 0x84, 0x10,
-+                            0xD4, 0x62, 0xBA, 0x60, 0x50, 0xF0, 0x61, 0xF2,
-+                            0x1C, 0x78, 0x7F, 0xC1, 0x24, 0x34, 0xAF, 0x58,
-+                            0xBF, 0x2C, 0x59, 0xCA, 0x90, 0x77, 0xF3, 0xB0,
+ 	for (i = 0; attrs[i]; i++) {
+ 		error = class_device_create_file(classdev, attrs[i]);
+ 		if (error)
+@@ -378,9 +383,14 @@ attribute_container_remove_attrs(struct class_device *classdev)
+ 	struct class_device_attribute **attrs =	cont->attrs;
+ 	int i;
+ 
+-	if (!attrs)
++	if (!attrs && !cont->grp)
+ 		return;
+ 
++	if (cont->grp) {
++		sysfs_remove_group(&classdev->kobj, cont->grp);
++		return ;
++	}
 +
-+                            0x5B, 0x4A, 0xDF, 0x89, 0xCE, 0x2C, 0x2F, 0xFC,
-+                            0x67, 0xF0, 0xE3, 0x45, 0xE8, 0xB3, 0xB3, 0x75,
-+                            0xA0, 0x95, 0x71, 0xA1, 0x29, 0x39, 0x94, 0xCA,
-+                            0x45, 0x2F, 0xBD, 0xCB, 0x10, 0xB6, 0xBE, 0x9F,
-+                            0x8E, 0xF9, 0xB2, 0x01, 0x0A, 0x5A, 0x0A, 0xB7,
-+                            0x6B, 0x9D, 0x70, 0x8E, 0x4B, 0xD6, 0x2F, 0xCD,
-+                            0x2E, 0x40, 0x48, 0x75, 0xE9, 0xE2, 0x21, 0x45,
-+                            0x0B, 0xC9, 0xB6, 0xB5, 0x66, 0xBC, 0x9A, 0x59,
+ 	for (i = 0; attrs[i]; i++)
+ 		class_device_remove_file(classdev, attrs[i]);
+ }
+@@ -429,10 +439,3 @@ attribute_container_find_class_device(struct attribute_container *cont,
+ 	return cdev;
+ }
+ EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+-
+-int __init
+-attribute_container_init(void)
+-{
+-	INIT_LIST_HEAD(&attribute_container_list);
+-	return 0;
+-}
+diff --git a/drivers/base/base.h b/drivers/base/base.h
+index 10b2fb6..c044414 100644
+--- a/drivers/base/base.h
++++ b/drivers/base/base.h
+@@ -1,6 +1,42 @@
+ 
+-/* initialisation functions */
++/**
++ * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
++ *
++ * @subsys - the struct kset that defines this bus.  This is the main kobject
++ * @drivers_kset - the list of drivers associated with this bus
++ * @devices_kset - the list of devices associated with this bus
++ * @klist_devices - the klist to iterate over the @devices_kset
++ * @klist_drivers - the klist to iterate over the @drivers_kset
++ * @bus_notifier - the bus notifier list for anything that cares about things
++ * on this bus.
++ * @bus - pointer back to the struct bus_type that this structure is associated
++ * with.
++ *
++ * This structure is the one that is the actual kobject allowing struct
++ * bus_type to be statically allocated safely.  Nothing outside of the driver
++ * core should ever touch these fields.
++ */
++struct bus_type_private {
++	struct kset subsys;
++	struct kset *drivers_kset;
++	struct kset *devices_kset;
++	struct klist klist_devices;
++	struct klist klist_drivers;
++	struct blocking_notifier_head bus_notifier;
++	unsigned int drivers_autoprobe:1;
++	struct bus_type *bus;
++};
 +
-+                            0x5A,
-+			  },
-+		.rlen	= 129,
-+	}, { /* large test vector generated using Crypto++ */
-+		.key = {
-+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+		},
-+		.klen = 32,
-+		.iv = {
-+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+		},
-+		.input = {
-+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-+			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-+			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-+			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-+			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-+			0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-+			0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-+			0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
-+			0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-+			0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
-+			0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-+			0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-+			0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-+			0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
-+			0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
-+			0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-+			0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-+			0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
-+			0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-+			0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-+			0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-+			0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
-+			0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-+			0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
-+			0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-+			0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-+			0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-+			0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
-+			0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-+			0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
-+			0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
-+			0x00, 0x03, 0x06, 0x09, 0x0c, 0x0f, 0x12, 0x15,
-+			0x18, 0x1b, 0x1e, 0x21, 0x24, 0x27, 0x2a, 0x2d,
-+			0x30, 0x33, 0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45,
-+			0x48, 0x4b, 0x4e, 0x51, 0x54, 0x57, 0x5a, 0x5d,
-+			0x60, 0x63, 0x66, 0x69, 0x6c, 0x6f, 0x72, 0x75,
-+			0x78, 0x7b, 0x7e, 0x81, 0x84, 0x87, 0x8a, 0x8d,
-+			0x90, 0x93, 0x96, 0x99, 0x9c, 0x9f, 0xa2, 0xa5,
-+			0xa8, 0xab, 0xae, 0xb1, 0xb4, 0xb7, 0xba, 0xbd,
-+			0xc0, 0xc3, 0xc6, 0xc9, 0xcc, 0xcf, 0xd2, 0xd5,
-+			0xd8, 0xdb, 0xde, 0xe1, 0xe4, 0xe7, 0xea, 0xed,
-+			0xf0, 0xf3, 0xf6, 0xf9, 0xfc, 0xff, 0x02, 0x05,
-+			0x08, 0x0b, 0x0e, 0x11, 0x14, 0x17, 0x1a, 0x1d,
-+			0x20, 0x23, 0x26, 0x29, 0x2c, 0x2f, 0x32, 0x35,
-+			0x38, 0x3b, 0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d,
-+			0x50, 0x53, 0x56, 0x59, 0x5c, 0x5f, 0x62, 0x65,
-+			0x68, 0x6b, 0x6e, 0x71, 0x74, 0x77, 0x7a, 0x7d,
-+			0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x95,
-+			0x98, 0x9b, 0x9e, 0xa1, 0xa4, 0xa7, 0xaa, 0xad,
-+			0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbf, 0xc2, 0xc5,
-+			0xc8, 0xcb, 0xce, 0xd1, 0xd4, 0xd7, 0xda, 0xdd,
-+			0xe0, 0xe3, 0xe6, 0xe9, 0xec, 0xef, 0xf2, 0xf5,
-+			0xf8, 0xfb, 0xfe, 0x01, 0x04, 0x07, 0x0a, 0x0d,
-+			0x10, 0x13, 0x16, 0x19, 0x1c, 0x1f, 0x22, 0x25,
-+			0x28, 0x2b, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3d,
-+			0x40, 0x43, 0x46, 0x49, 0x4c, 0x4f, 0x52, 0x55,
-+			0x58, 0x5b, 0x5e, 0x61, 0x64, 0x67, 0x6a, 0x6d,
-+			0x70, 0x73, 0x76, 0x79, 0x7c, 0x7f, 0x82, 0x85,
-+			0x88, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9d,
-+			0xa0, 0xa3, 0xa6, 0xa9, 0xac, 0xaf, 0xb2, 0xb5,
-+			0xb8, 0xbb, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
-+			0xd0, 0xd3, 0xd6, 0xd9, 0xdc, 0xdf, 0xe2, 0xe5,
-+			0xe8, 0xeb, 0xee, 0xf1, 0xf4, 0xf7, 0xfa, 0xfd,
-+			0x00, 0x05, 0x0a, 0x0f, 0x14, 0x19, 0x1e, 0x23,
-+			0x28, 0x2d, 0x32, 0x37, 0x3c, 0x41, 0x46, 0x4b,
-+			0x50, 0x55, 0x5a, 0x5f, 0x64, 0x69, 0x6e, 0x73,
-+			0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91, 0x96, 0x9b,
-+			0xa0, 0xa5, 0xaa, 0xaf, 0xb4, 0xb9, 0xbe, 0xc3,
-+			0xc8, 0xcd, 0xd2, 0xd7, 0xdc, 0xe1, 0xe6, 0xeb,
-+			0xf0, 0xf5, 0xfa, 0xff, 0x04, 0x09, 0x0e, 0x13,
-+			0x18, 0x1d, 0x22, 0x27, 0x2c, 0x31, 0x36, 0x3b,
-+			0x40, 0x45, 0x4a, 0x4f, 0x54, 0x59, 0x5e, 0x63,
-+			0x68, 0x6d, 0x72, 0x77, 0x7c, 0x81, 0x86, 0x8b,
-+			0x90, 0x95, 0x9a, 0x9f, 0xa4, 0xa9, 0xae, 0xb3,
-+			0xb8, 0xbd, 0xc2, 0xc7, 0xcc, 0xd1, 0xd6, 0xdb,
-+			0xe0, 0xe5, 0xea, 0xef, 0xf4, 0xf9, 0xfe, 0x03,
-+			0x08, 0x0d, 0x12, 0x17, 0x1c, 0x21, 0x26, 0x2b,
-+			0x30, 0x35, 0x3a, 0x3f, 0x44, 0x49, 0x4e, 0x53,
-+			0x58, 0x5d, 0x62, 0x67, 0x6c, 0x71, 0x76, 0x7b,
-+			0x80, 0x85, 0x8a, 0x8f, 0x94, 0x99, 0x9e, 0xa3,
-+			0xa8, 0xad, 0xb2, 0xb7, 0xbc, 0xc1, 0xc6, 0xcb,
-+			0xd0, 0xd5, 0xda, 0xdf, 0xe4, 0xe9, 0xee, 0xf3,
-+			0xf8, 0xfd, 0x02, 0x07, 0x0c, 0x11, 0x16, 0x1b,
-+			0x20, 0x25, 0x2a, 0x2f, 0x34, 0x39, 0x3e, 0x43,
-+			0x48, 0x4d, 0x52, 0x57, 0x5c, 0x61, 0x66, 0x6b,
-+			0x70, 0x75, 0x7a, 0x7f, 0x84, 0x89, 0x8e, 0x93,
-+			0x98, 0x9d, 0xa2, 0xa7, 0xac, 0xb1, 0xb6, 0xbb,
-+			0xc0, 0xc5, 0xca, 0xcf, 0xd4, 0xd9, 0xde, 0xe3,
-+			0xe8, 0xed, 0xf2, 0xf7, 0xfc, 0x01, 0x06, 0x0b,
-+			0x10, 0x15, 0x1a, 0x1f, 0x24, 0x29, 0x2e, 0x33,
-+			0x38, 0x3d, 0x42, 0x47, 0x4c, 0x51, 0x56, 0x5b,
-+			0x60, 0x65, 0x6a, 0x6f, 0x74, 0x79, 0x7e, 0x83,
-+			0x88, 0x8d, 0x92, 0x97, 0x9c, 0xa1, 0xa6, 0xab,
-+			0xb0, 0xb5, 0xba, 0xbf, 0xc4, 0xc9, 0xce, 0xd3,
-+			0xd8, 0xdd, 0xe2, 0xe7, 0xec, 0xf1, 0xf6, 0xfb,
-+			0x00, 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31,
-+			0x38, 0x3f, 0x46, 0x4d, 0x54, 0x5b, 0x62, 0x69,
-+			0x70, 0x77, 0x7e, 0x85, 0x8c, 0x93, 0x9a, 0xa1,
-+			0xa8, 0xaf, 0xb6, 0xbd, 0xc4, 0xcb, 0xd2, 0xd9,
-+			0xe0, 0xe7, 0xee, 0xf5, 0xfc, 0x03, 0x0a, 0x11,
-+			0x18, 0x1f, 0x26, 0x2d, 0x34, 0x3b, 0x42, 0x49,
-+			0x50, 0x57, 0x5e, 0x65, 0x6c, 0x73, 0x7a, 0x81,
-+			0x88, 0x8f, 0x96, 0x9d, 0xa4, 0xab, 0xb2, 0xb9,
-+			0xc0, 0xc7, 0xce, 0xd5, 0xdc, 0xe3, 0xea, 0xf1,
-+			0xf8, 0xff, 0x06, 0x0d, 0x14, 0x1b, 0x22, 0x29,
-+			0x30, 0x37, 0x3e, 0x45, 0x4c, 0x53, 0x5a, 0x61,
-+			0x68, 0x6f, 0x76, 0x7d, 0x84, 0x8b, 0x92, 0x99,
-+			0xa0, 0xa7, 0xae, 0xb5, 0xbc, 0xc3, 0xca, 0xd1,
-+			0xd8, 0xdf, 0xe6, 0xed, 0xf4, 0xfb, 0x02, 0x09,
-+			0x10, 0x17, 0x1e, 0x25, 0x2c, 0x33, 0x3a, 0x41,
-+			0x48, 0x4f, 0x56, 0x5d, 0x64, 0x6b, 0x72, 0x79,
-+			0x80, 0x87, 0x8e, 0x95, 0x9c, 0xa3, 0xaa, 0xb1,
-+			0xb8, 0xbf, 0xc6, 0xcd, 0xd4, 0xdb, 0xe2, 0xe9,
-+			0xf0, 0xf7, 0xfe, 0x05, 0x0c, 0x13, 0x1a, 0x21,
-+			0x28, 0x2f, 0x36, 0x3d, 0x44, 0x4b, 0x52, 0x59,
-+			0x60, 0x67, 0x6e, 0x75, 0x7c, 0x83, 0x8a, 0x91,
-+			0x98, 0x9f, 0xa6, 0xad, 0xb4, 0xbb, 0xc2, 0xc9,
-+			0xd0, 0xd7, 0xde, 0xe5, 0xec, 0xf3, 0xfa, 0x01,
-+			0x08, 0x0f, 0x16, 0x1d, 0x24, 0x2b, 0x32, 0x39,
-+			0x40, 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71,
-+			0x78, 0x7f, 0x86, 0x8d, 0x94, 0x9b, 0xa2, 0xa9,
-+			0xb0, 0xb7, 0xbe, 0xc5, 0xcc, 0xd3, 0xda, 0xe1,
-+			0xe8, 0xef, 0xf6, 0xfd, 0x04, 0x0b, 0x12, 0x19,
-+			0x20, 0x27, 0x2e, 0x35, 0x3c, 0x43, 0x4a, 0x51,
-+			0x58, 0x5f, 0x66, 0x6d, 0x74, 0x7b, 0x82, 0x89,
-+			0x90, 0x97, 0x9e, 0xa5, 0xac, 0xb3, 0xba, 0xc1,
-+			0xc8, 0xcf, 0xd6, 0xdd, 0xe4, 0xeb, 0xf2, 0xf9,
-+			0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
-+			0x48, 0x51, 0x5a, 0x63, 0x6c, 0x75, 0x7e, 0x87,
-+			0x90, 0x99, 0xa2, 0xab, 0xb4, 0xbd, 0xc6, 0xcf,
-+			0xd8, 0xe1, 0xea, 0xf3, 0xfc, 0x05, 0x0e, 0x17,
-+			0x20, 0x29, 0x32, 0x3b, 0x44, 0x4d, 0x56, 0x5f,
-+			0x68, 0x71, 0x7a, 0x83, 0x8c, 0x95, 0x9e, 0xa7,
-+			0xb0, 0xb9, 0xc2, 0xcb, 0xd4, 0xdd, 0xe6, 0xef,
-+			0xf8, 0x01, 0x0a, 0x13, 0x1c, 0x25, 0x2e, 0x37,
-+			0x40, 0x49, 0x52, 0x5b, 0x64, 0x6d, 0x76, 0x7f,
-+			0x88, 0x91, 0x9a, 0xa3, 0xac, 0xb5, 0xbe, 0xc7,
-+			0xd0, 0xd9, 0xe2, 0xeb, 0xf4, 0xfd, 0x06, 0x0f,
-+			0x18, 0x21, 0x2a, 0x33, 0x3c, 0x45, 0x4e, 0x57,
-+			0x60, 0x69, 0x72, 0x7b, 0x84, 0x8d, 0x96, 0x9f,
-+			0xa8, 0xb1, 0xba, 0xc3, 0xcc, 0xd5, 0xde, 0xe7,
-+			0xf0, 0xf9, 0x02, 0x0b, 0x14, 0x1d, 0x26, 0x2f,
-+			0x38, 0x41, 0x4a, 0x53, 0x5c, 0x65, 0x6e, 0x77,
-+			0x80, 0x89, 0x92, 0x9b, 0xa4, 0xad, 0xb6, 0xbf,
-+			0xc8, 0xd1, 0xda, 0xe3, 0xec, 0xf5, 0xfe, 0x07,
-+			0x10, 0x19, 0x22, 0x2b, 0x34, 0x3d, 0x46, 0x4f,
-+			0x58, 0x61, 0x6a, 0x73, 0x7c, 0x85, 0x8e, 0x97,
-+			0xa0, 0xa9, 0xb2, 0xbb, 0xc4, 0xcd, 0xd6, 0xdf,
-+			0xe8, 0xf1, 0xfa, 0x03, 0x0c, 0x15, 0x1e, 0x27,
-+			0x30, 0x39, 0x42, 0x4b, 0x54, 0x5d, 0x66, 0x6f,
-+			0x78, 0x81, 0x8a, 0x93, 0x9c, 0xa5, 0xae, 0xb7,
-+			0xc0, 0xc9, 0xd2, 0xdb, 0xe4, 0xed, 0xf6, 0xff,
-+			0x08, 0x11, 0x1a, 0x23, 0x2c, 0x35, 0x3e, 0x47,
-+			0x50, 0x59, 0x62, 0x6b, 0x74, 0x7d, 0x86, 0x8f,
-+			0x98, 0xa1, 0xaa, 0xb3, 0xbc, 0xc5, 0xce, 0xd7,
-+			0xe0, 0xe9, 0xf2, 0xfb, 0x04, 0x0d, 0x16, 0x1f,
-+			0x28, 0x31, 0x3a, 0x43, 0x4c, 0x55, 0x5e, 0x67,
-+			0x70, 0x79, 0x82, 0x8b, 0x94, 0x9d, 0xa6, 0xaf,
-+			0xb8, 0xc1, 0xca, 0xd3, 0xdc, 0xe5, 0xee, 0xf7,
-+			0x00, 0x0b, 0x16, 0x21, 0x2c, 0x37, 0x42, 0x4d,
-+			0x58, 0x63, 0x6e, 0x79, 0x84, 0x8f, 0x9a, 0xa5,
-+			0xb0, 0xbb, 0xc6, 0xd1, 0xdc, 0xe7, 0xf2, 0xfd,
-+			0x08, 0x13, 0x1e, 0x29, 0x34, 0x3f, 0x4a, 0x55,
-+			0x60, 0x6b, 0x76, 0x81, 0x8c, 0x97, 0xa2, 0xad,
-+			0xb8, 0xc3, 0xce, 0xd9, 0xe4, 0xef, 0xfa, 0x05,
-+			0x10, 0x1b, 0x26, 0x31, 0x3c, 0x47, 0x52, 0x5d,
-+			0x68, 0x73, 0x7e, 0x89, 0x94, 0x9f, 0xaa, 0xb5,
-+			0xc0, 0xcb, 0xd6, 0xe1, 0xec, 0xf7, 0x02, 0x0d,
-+			0x18, 0x23, 0x2e, 0x39, 0x44, 0x4f, 0x5a, 0x65,
-+			0x70, 0x7b, 0x86, 0x91, 0x9c, 0xa7, 0xb2, 0xbd,
-+			0xc8, 0xd3, 0xde, 0xe9, 0xf4, 0xff, 0x0a, 0x15,
-+			0x20, 0x2b, 0x36, 0x41, 0x4c, 0x57, 0x62, 0x6d,
-+			0x78, 0x83, 0x8e, 0x99, 0xa4, 0xaf, 0xba, 0xc5,
-+			0xd0, 0xdb, 0xe6, 0xf1, 0xfc, 0x07, 0x12, 0x1d,
-+			0x28, 0x33, 0x3e, 0x49, 0x54, 0x5f, 0x6a, 0x75,
-+			0x80, 0x8b, 0x96, 0xa1, 0xac, 0xb7, 0xc2, 0xcd,
-+			0xd8, 0xe3, 0xee, 0xf9, 0x04, 0x0f, 0x1a, 0x25,
-+			0x30, 0x3b, 0x46, 0x51, 0x5c, 0x67, 0x72, 0x7d,
-+			0x88, 0x93, 0x9e, 0xa9, 0xb4, 0xbf, 0xca, 0xd5,
-+			0xe0, 0xeb, 0xf6, 0x01, 0x0c, 0x17, 0x22, 0x2d,
-+			0x38, 0x43, 0x4e, 0x59, 0x64, 0x6f, 0x7a, 0x85,
-+			0x90, 0x9b, 0xa6, 0xb1, 0xbc, 0xc7, 0xd2, 0xdd,
-+			0xe8, 0xf3, 0xfe, 0x09, 0x14, 0x1f, 0x2a, 0x35,
-+			0x40, 0x4b, 0x56, 0x61, 0x6c, 0x77, 0x82, 0x8d,
-+			0x98, 0xa3, 0xae, 0xb9, 0xc4, 0xcf, 0xda, 0xe5,
-+			0xf0, 0xfb, 0x06, 0x11, 0x1c, 0x27, 0x32, 0x3d,
-+			0x48, 0x53, 0x5e, 0x69, 0x74, 0x7f, 0x8a, 0x95,
-+			0xa0, 0xab, 0xb6, 0xc1, 0xcc, 0xd7, 0xe2, 0xed,
-+			0xf8, 0x03, 0x0e, 0x19, 0x24, 0x2f, 0x3a, 0x45,
-+			0x50, 0x5b, 0x66, 0x71, 0x7c, 0x87, 0x92, 0x9d,
-+			0xa8, 0xb3, 0xbe, 0xc9, 0xd4, 0xdf, 0xea, 0xf5,
-+			0x00, 0x0d, 0x1a, 0x27, 0x34, 0x41, 0x4e, 0x5b,
-+			0x68, 0x75, 0x82, 0x8f, 0x9c, 0xa9, 0xb6, 0xc3,
-+			0xd0, 0xdd, 0xea, 0xf7, 0x04, 0x11, 0x1e, 0x2b,
-+			0x38, 0x45, 0x52, 0x5f, 0x6c, 0x79, 0x86, 0x93,
-+			0xa0, 0xad, 0xba, 0xc7, 0xd4, 0xe1, 0xee, 0xfb,
-+			0x08, 0x15, 0x22, 0x2f, 0x3c, 0x49, 0x56, 0x63,
-+			0x70, 0x7d, 0x8a, 0x97, 0xa4, 0xb1, 0xbe, 0xcb,
-+			0xd8, 0xe5, 0xf2, 0xff, 0x0c, 0x19, 0x26, 0x33,
-+			0x40, 0x4d, 0x5a, 0x67, 0x74, 0x81, 0x8e, 0x9b,
-+			0xa8, 0xb5, 0xc2, 0xcf, 0xdc, 0xe9, 0xf6, 0x03,
-+			0x10, 0x1d, 0x2a, 0x37, 0x44, 0x51, 0x5e, 0x6b,
-+			0x78, 0x85, 0x92, 0x9f, 0xac, 0xb9, 0xc6, 0xd3,
-+			0xe0, 0xed, 0xfa, 0x07, 0x14, 0x21, 0x2e, 0x3b,
-+			0x48, 0x55, 0x62, 0x6f, 0x7c, 0x89, 0x96, 0xa3,
-+			0xb0, 0xbd, 0xca, 0xd7, 0xe4, 0xf1, 0xfe, 0x0b,
-+			0x18, 0x25, 0x32, 0x3f, 0x4c, 0x59, 0x66, 0x73,
-+			0x80, 0x8d, 0x9a, 0xa7, 0xb4, 0xc1, 0xce, 0xdb,
-+			0xe8, 0xf5, 0x02, 0x0f, 0x1c, 0x29, 0x36, 0x43,
-+			0x50, 0x5d, 0x6a, 0x77, 0x84, 0x91, 0x9e, 0xab,
-+			0xb8, 0xc5, 0xd2, 0xdf, 0xec, 0xf9, 0x06, 0x13,
-+			0x20, 0x2d, 0x3a, 0x47, 0x54, 0x61, 0x6e, 0x7b,
-+			0x88, 0x95, 0xa2, 0xaf, 0xbc, 0xc9, 0xd6, 0xe3,
-+			0xf0, 0xfd, 0x0a, 0x17, 0x24, 0x31, 0x3e, 0x4b,
-+			0x58, 0x65, 0x72, 0x7f, 0x8c, 0x99, 0xa6, 0xb3,
-+			0xc0, 0xcd, 0xda, 0xe7, 0xf4, 0x01, 0x0e, 0x1b,
-+			0x28, 0x35, 0x42, 0x4f, 0x5c, 0x69, 0x76, 0x83,
-+			0x90, 0x9d, 0xaa, 0xb7, 0xc4, 0xd1, 0xde, 0xeb,
-+			0xf8, 0x05, 0x12, 0x1f, 0x2c, 0x39, 0x46, 0x53,
-+			0x60, 0x6d, 0x7a, 0x87, 0x94, 0xa1, 0xae, 0xbb,
-+			0xc8, 0xd5, 0xe2, 0xef, 0xfc, 0x09, 0x16, 0x23,
-+			0x30, 0x3d, 0x4a, 0x57, 0x64, 0x71, 0x7e, 0x8b,
-+			0x98, 0xa5, 0xb2, 0xbf, 0xcc, 0xd9, 0xe6, 0xf3,
-+			0x00, 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69,
-+			0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1,
-+			0xf0, 0xff, 0x0e, 0x1d, 0x2c, 0x3b, 0x4a, 0x59,
-+			0x68, 0x77, 0x86, 0x95, 0xa4, 0xb3, 0xc2, 0xd1,
-+			0xe0, 0xef, 0xfe, 0x0d, 0x1c, 0x2b, 0x3a, 0x49,
-+			0x58, 0x67, 0x76, 0x85, 0x94, 0xa3, 0xb2, 0xc1,
-+			0xd0, 0xdf, 0xee, 0xfd, 0x0c, 0x1b, 0x2a, 0x39,
-+			0x48, 0x57, 0x66, 0x75, 0x84, 0x93, 0xa2, 0xb1,
-+			0xc0, 0xcf, 0xde, 0xed, 0xfc, 0x0b, 0x1a, 0x29,
-+			0x38, 0x47, 0x56, 0x65, 0x74, 0x83, 0x92, 0xa1,
-+			0xb0, 0xbf, 0xce, 0xdd, 0xec, 0xfb, 0x0a, 0x19,
-+			0x28, 0x37, 0x46, 0x55, 0x64, 0x73, 0x82, 0x91,
-+			0xa0, 0xaf, 0xbe, 0xcd, 0xdc, 0xeb, 0xfa, 0x09,
-+			0x18, 0x27, 0x36, 0x45, 0x54, 0x63, 0x72, 0x81,
-+			0x90, 0x9f, 0xae, 0xbd, 0xcc, 0xdb, 0xea, 0xf9,
-+			0x08, 0x17, 0x26, 0x35, 0x44, 0x53, 0x62, 0x71,
-+			0x80, 0x8f, 0x9e, 0xad, 0xbc, 0xcb, 0xda, 0xe9,
-+			0xf8, 0x07, 0x16, 0x25, 0x34, 0x43, 0x52, 0x61,
-+			0x70, 0x7f, 0x8e, 0x9d, 0xac, 0xbb, 0xca, 0xd9,
-+			0xe8, 0xf7, 0x06, 0x15, 0x24, 0x33, 0x42, 0x51,
-+			0x60, 0x6f, 0x7e, 0x8d, 0x9c, 0xab, 0xba, 0xc9,
-+			0xd8, 0xe7, 0xf6, 0x05, 0x14, 0x23, 0x32, 0x41,
-+			0x50, 0x5f, 0x6e, 0x7d, 0x8c, 0x9b, 0xaa, 0xb9,
-+			0xc8, 0xd7, 0xe6, 0xf5, 0x04, 0x13, 0x22, 0x31,
-+			0x40, 0x4f, 0x5e, 0x6d, 0x7c, 0x8b, 0x9a, 0xa9,
-+			0xb8, 0xc7, 0xd6, 0xe5, 0xf4, 0x03, 0x12, 0x21,
-+			0x30, 0x3f, 0x4e, 0x5d, 0x6c, 0x7b, 0x8a, 0x99,
-+			0xa8, 0xb7, 0xc6, 0xd5, 0xe4, 0xf3, 0x02, 0x11,
-+			0x20, 0x2f, 0x3e, 0x4d, 0x5c, 0x6b, 0x7a, 0x89,
-+			0x98, 0xa7, 0xb6, 0xc5, 0xd4, 0xe3, 0xf2, 0x01,
-+			0x10, 0x1f, 0x2e, 0x3d, 0x4c, 0x5b, 0x6a, 0x79,
-+			0x88, 0x97, 0xa6, 0xb5, 0xc4, 0xd3, 0xe2, 0xf1,
-+			0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-+			0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
-+			0x10, 0x21, 0x32, 0x43, 0x54, 0x65, 0x76, 0x87,
-+			0x98, 0xa9, 0xba, 0xcb, 0xdc, 0xed, 0xfe, 0x0f,
-+			0x20, 0x31, 0x42, 0x53, 0x64, 0x75, 0x86, 0x97,
-+			0xa8, 0xb9, 0xca, 0xdb, 0xec, 0xfd, 0x0e, 0x1f,
-+			0x30, 0x41, 0x52, 0x63, 0x74, 0x85, 0x96, 0xa7,
-+			0xb8, 0xc9, 0xda, 0xeb, 0xfc, 0x0d, 0x1e, 0x2f,
-+			0x40, 0x51, 0x62, 0x73, 0x84, 0x95, 0xa6, 0xb7,
-+			0xc8, 0xd9, 0xea, 0xfb, 0x0c, 0x1d, 0x2e, 0x3f,
-+			0x50, 0x61, 0x72, 0x83, 0x94, 0xa5, 0xb6, 0xc7,
-+			0xd8, 0xe9, 0xfa, 0x0b, 0x1c, 0x2d, 0x3e, 0x4f,
-+			0x60, 0x71, 0x82, 0x93, 0xa4, 0xb5, 0xc6, 0xd7,
-+			0xe8, 0xf9, 0x0a, 0x1b, 0x2c, 0x3d, 0x4e, 0x5f,
-+			0x70, 0x81, 0x92, 0xa3, 0xb4, 0xc5, 0xd6, 0xe7,
-+			0xf8, 0x09, 0x1a, 0x2b, 0x3c, 0x4d, 0x5e, 0x6f,
-+			0x80, 0x91, 0xa2, 0xb3, 0xc4, 0xd5, 0xe6, 0xf7,
-+			0x08, 0x19, 0x2a, 0x3b, 0x4c, 0x5d, 0x6e, 0x7f,
-+			0x90, 0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6, 0x07,
-+			0x18, 0x29, 0x3a, 0x4b, 0x5c, 0x6d, 0x7e, 0x8f,
-+			0xa0, 0xb1, 0xc2, 0xd3, 0xe4, 0xf5, 0x06, 0x17,
-+			0x28, 0x39, 0x4a, 0x5b, 0x6c, 0x7d, 0x8e, 0x9f,
-+			0xb0, 0xc1, 0xd2, 0xe3, 0xf4, 0x05, 0x16, 0x27,
-+			0x38, 0x49, 0x5a, 0x6b, 0x7c, 0x8d, 0x9e, 0xaf,
-+			0xc0, 0xd1, 0xe2, 0xf3, 0x04, 0x15, 0x26, 0x37,
-+			0x48, 0x59, 0x6a, 0x7b, 0x8c, 0x9d, 0xae, 0xbf,
-+			0xd0, 0xe1, 0xf2, 0x03, 0x14, 0x25, 0x36, 0x47,
-+			0x58, 0x69, 0x7a, 0x8b, 0x9c, 0xad, 0xbe, 0xcf,
-+			0xe0, 0xf1, 0x02, 0x13, 0x24, 0x35, 0x46, 0x57,
-+			0x68, 0x79, 0x8a, 0x9b, 0xac, 0xbd, 0xce, 0xdf,
-+			0xf0, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67,
-+			0x78, 0x89, 0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef,
-+			0x00, 0x13, 0x26, 0x39, 0x4c, 0x5f, 0x72, 0x85,
-+			0x98, 0xab, 0xbe, 0xd1, 0xe4, 0xf7, 0x0a, 0x1d,
-+			0x30, 0x43, 0x56, 0x69, 0x7c, 0x8f, 0xa2, 0xb5,
-+			0xc8, 0xdb, 0xee, 0x01, 0x14, 0x27, 0x3a, 0x4d,
-+			0x60, 0x73, 0x86, 0x99, 0xac, 0xbf, 0xd2, 0xe5,
-+			0xf8, 0x0b, 0x1e, 0x31, 0x44, 0x57, 0x6a, 0x7d,
-+			0x90, 0xa3, 0xb6, 0xc9, 0xdc, 0xef, 0x02, 0x15,
-+			0x28, 0x3b, 0x4e, 0x61, 0x74, 0x87, 0x9a, 0xad,
-+			0xc0, 0xd3, 0xe6, 0xf9, 0x0c, 0x1f, 0x32, 0x45,
-+			0x58, 0x6b, 0x7e, 0x91, 0xa4, 0xb7, 0xca, 0xdd,
-+			0xf0, 0x03, 0x16, 0x29, 0x3c, 0x4f, 0x62, 0x75,
-+			0x88, 0x9b, 0xae, 0xc1, 0xd4, 0xe7, 0xfa, 0x0d,
-+			0x20, 0x33, 0x46, 0x59, 0x6c, 0x7f, 0x92, 0xa5,
-+			0xb8, 0xcb, 0xde, 0xf1, 0x04, 0x17, 0x2a, 0x3d,
-+			0x50, 0x63, 0x76, 0x89, 0x9c, 0xaf, 0xc2, 0xd5,
-+			0xe8, 0xfb, 0x0e, 0x21, 0x34, 0x47, 0x5a, 0x6d,
-+			0x80, 0x93, 0xa6, 0xb9, 0xcc, 0xdf, 0xf2, 0x05,
-+			0x18, 0x2b, 0x3e, 0x51, 0x64, 0x77, 0x8a, 0x9d,
-+			0xb0, 0xc3, 0xd6, 0xe9, 0xfc, 0x0f, 0x22, 0x35,
-+			0x48, 0x5b, 0x6e, 0x81, 0x94, 0xa7, 0xba, 0xcd,
-+			0xe0, 0xf3, 0x06, 0x19, 0x2c, 0x3f, 0x52, 0x65,
-+			0x78, 0x8b, 0x9e, 0xb1, 0xc4, 0xd7, 0xea, 0xfd,
-+			0x10, 0x23, 0x36, 0x49, 0x5c, 0x6f, 0x82, 0x95,
-+			0xa8, 0xbb, 0xce, 0xe1, 0xf4, 0x07, 0x1a, 0x2d,
-+			0x40, 0x53, 0x66, 0x79, 0x8c, 0x9f, 0xb2, 0xc5,
-+			0xd8, 0xeb, 0xfe, 0x11, 0x24, 0x37, 0x4a, 0x5d,
-+			0x70, 0x83, 0x96, 0xa9, 0xbc, 0xcf, 0xe2, 0xf5,
-+			0x08, 0x1b, 0x2e, 0x41, 0x54, 0x67, 0x7a, 0x8d,
-+			0xa0, 0xb3, 0xc6, 0xd9, 0xec, 0xff, 0x12, 0x25,
-+			0x38, 0x4b, 0x5e, 0x71, 0x84, 0x97, 0xaa, 0xbd,
-+			0xd0, 0xe3, 0xf6, 0x09, 0x1c, 0x2f, 0x42, 0x55,
-+			0x68, 0x7b, 0x8e, 0xa1, 0xb4, 0xc7, 0xda, 0xed,
-+			0x00, 0x15, 0x2a, 0x3f, 0x54, 0x69, 0x7e, 0x93,
-+			0xa8, 0xbd, 0xd2, 0xe7, 0xfc, 0x11, 0x26, 0x3b,
-+			0x50, 0x65, 0x7a, 0x8f, 0xa4, 0xb9, 0xce, 0xe3,
-+			0xf8, 0x0d, 0x22, 0x37, 0x4c, 0x61, 0x76, 0x8b,
-+			0xa0, 0xb5, 0xca, 0xdf, 0xf4, 0x09, 0x1e, 0x33,
-+			0x48, 0x5d, 0x72, 0x87, 0x9c, 0xb1, 0xc6, 0xdb,
-+			0xf0, 0x05, 0x1a, 0x2f, 0x44, 0x59, 0x6e, 0x83,
-+			0x98, 0xad, 0xc2, 0xd7, 0xec, 0x01, 0x16, 0x2b,
-+			0x40, 0x55, 0x6a, 0x7f, 0x94, 0xa9, 0xbe, 0xd3,
-+			0xe8, 0xfd, 0x12, 0x27, 0x3c, 0x51, 0x66, 0x7b,
-+			0x90, 0xa5, 0xba, 0xcf, 0xe4, 0xf9, 0x0e, 0x23,
-+			0x38, 0x4d, 0x62, 0x77, 0x8c, 0xa1, 0xb6, 0xcb,
-+			0xe0, 0xf5, 0x0a, 0x1f, 0x34, 0x49, 0x5e, 0x73,
-+			0x88, 0x9d, 0xb2, 0xc7, 0xdc, 0xf1, 0x06, 0x1b,
-+			0x30, 0x45, 0x5a, 0x6f, 0x84, 0x99, 0xae, 0xc3,
-+			0xd8, 0xed, 0x02, 0x17, 0x2c, 0x41, 0x56, 0x6b,
-+			0x80, 0x95, 0xaa, 0xbf, 0xd4, 0xe9, 0xfe, 0x13,
-+			0x28, 0x3d, 0x52, 0x67, 0x7c, 0x91, 0xa6, 0xbb,
-+			0xd0, 0xe5, 0xfa, 0x0f, 0x24, 0x39, 0x4e, 0x63,
-+			0x78, 0x8d, 0xa2, 0xb7, 0xcc, 0xe1, 0xf6, 0x0b,
-+			0x20, 0x35, 0x4a, 0x5f, 0x74, 0x89, 0x9e, 0xb3,
-+			0xc8, 0xdd, 0xf2, 0x07, 0x1c, 0x31, 0x46, 0x5b,
-+			0x70, 0x85, 0x9a, 0xaf, 0xc4, 0xd9, 0xee, 0x03,
-+			0x18, 0x2d, 0x42, 0x57, 0x6c, 0x81, 0x96, 0xab,
-+			0xc0, 0xd5, 0xea, 0xff, 0x14, 0x29, 0x3e, 0x53,
-+			0x68, 0x7d, 0x92, 0xa7, 0xbc, 0xd1, 0xe6, 0xfb,
-+			0x10, 0x25, 0x3a, 0x4f, 0x64, 0x79, 0x8e, 0xa3,
-+			0xb8, 0xcd, 0xe2, 0xf7, 0x0c, 0x21, 0x36, 0x4b,
-+			0x60, 0x75, 0x8a, 0x9f, 0xb4, 0xc9, 0xde, 0xf3,
-+			0x08, 0x1d, 0x32, 0x47, 0x5c, 0x71, 0x86, 0x9b,
-+			0xb0, 0xc5, 0xda, 0xef, 0x04, 0x19, 0x2e, 0x43,
-+			0x58, 0x6d, 0x82, 0x97, 0xac, 0xc1, 0xd6, 0xeb,
-+			0x00, 0x17, 0x2e, 0x45, 0x5c, 0x73, 0x8a, 0xa1,
-+			0xb8, 0xcf, 0xe6, 0xfd, 0x14, 0x2b, 0x42, 0x59,
-+			0x70, 0x87, 0x9e, 0xb5, 0xcc, 0xe3, 0xfa, 0x11,
-+			0x28, 0x3f, 0x56, 0x6d, 0x84, 0x9b, 0xb2, 0xc9,
-+			0xe0, 0xf7, 0x0e, 0x25, 0x3c, 0x53, 0x6a, 0x81,
-+			0x98, 0xaf, 0xc6, 0xdd, 0xf4, 0x0b, 0x22, 0x39,
-+			0x50, 0x67, 0x7e, 0x95, 0xac, 0xc3, 0xda, 0xf1,
-+			0x08, 0x1f, 0x36, 0x4d, 0x64, 0x7b, 0x92, 0xa9,
-+			0xc0, 0xd7, 0xee, 0x05, 0x1c, 0x33, 0x4a, 0x61,
-+			0x78, 0x8f, 0xa6, 0xbd, 0xd4, 0xeb, 0x02, 0x19,
-+			0x30, 0x47, 0x5e, 0x75, 0x8c, 0xa3, 0xba, 0xd1,
-+			0xe8, 0xff, 0x16, 0x2d, 0x44, 0x5b, 0x72, 0x89,
-+			0xa0, 0xb7, 0xce, 0xe5, 0xfc, 0x13, 0x2a, 0x41,
-+			0x58, 0x6f, 0x86, 0x9d, 0xb4, 0xcb, 0xe2, 0xf9,
-+			0x10, 0x27, 0x3e, 0x55, 0x6c, 0x83, 0x9a, 0xb1,
-+			0xc8, 0xdf, 0xf6, 0x0d, 0x24, 0x3b, 0x52, 0x69,
-+			0x80, 0x97, 0xae, 0xc5, 0xdc, 0xf3, 0x0a, 0x21,
-+			0x38, 0x4f, 0x66, 0x7d, 0x94, 0xab, 0xc2, 0xd9,
-+			0xf0, 0x07, 0x1e, 0x35, 0x4c, 0x63, 0x7a, 0x91,
-+			0xa8, 0xbf, 0xd6, 0xed, 0x04, 0x1b, 0x32, 0x49,
-+			0x60, 0x77, 0x8e, 0xa5, 0xbc, 0xd3, 0xea, 0x01,
-+			0x18, 0x2f, 0x46, 0x5d, 0x74, 0x8b, 0xa2, 0xb9,
-+			0xd0, 0xe7, 0xfe, 0x15, 0x2c, 0x43, 0x5a, 0x71,
-+			0x88, 0x9f, 0xb6, 0xcd, 0xe4, 0xfb, 0x12, 0x29,
-+			0x40, 0x57, 0x6e, 0x85, 0x9c, 0xb3, 0xca, 0xe1,
-+			0xf8, 0x0f, 0x26, 0x3d, 0x54, 0x6b, 0x82, 0x99,
-+			0xb0, 0xc7, 0xde, 0xf5, 0x0c, 0x23, 0x3a, 0x51,
-+			0x68, 0x7f, 0x96, 0xad, 0xc4, 0xdb, 0xf2, 0x09,
-+			0x20, 0x37, 0x4e, 0x65, 0x7c, 0x93, 0xaa, 0xc1,
-+			0xd8, 0xef, 0x06, 0x1d, 0x34, 0x4b, 0x62, 0x79,
-+			0x90, 0xa7, 0xbe, 0xd5, 0xec, 0x03, 0x1a, 0x31,
-+			0x48, 0x5f, 0x76, 0x8d, 0xa4, 0xbb, 0xd2, 0xe9,
-+			0x00, 0x19, 0x32, 0x4b, 0x64, 0x7d, 0x96, 0xaf,
-+			0xc8, 0xe1, 0xfa, 0x13, 0x2c, 0x45, 0x5e, 0x77,
-+			0x90, 0xa9, 0xc2, 0xdb, 0xf4, 0x0d, 0x26, 0x3f,
-+			0x58, 0x71, 0x8a, 0xa3, 0xbc, 0xd5, 0xee, 0x07,
-+			0x20, 0x39, 0x52, 0x6b, 0x84, 0x9d, 0xb6, 0xcf,
-+			0xe8, 0x01, 0x1a, 0x33, 0x4c, 0x65, 0x7e, 0x97,
-+			0xb0, 0xc9, 0xe2, 0xfb, 0x14, 0x2d, 0x46, 0x5f,
-+			0x78, 0x91, 0xaa, 0xc3, 0xdc, 0xf5, 0x0e, 0x27,
-+			0x40, 0x59, 0x72, 0x8b, 0xa4, 0xbd, 0xd6, 0xef,
-+			0x08, 0x21, 0x3a, 0x53, 0x6c, 0x85, 0x9e, 0xb7,
-+			0xd0, 0xe9, 0x02, 0x1b, 0x34, 0x4d, 0x66, 0x7f,
-+			0x98, 0xb1, 0xca, 0xe3, 0xfc, 0x15, 0x2e, 0x47,
-+			0x60, 0x79, 0x92, 0xab, 0xc4, 0xdd, 0xf6, 0x0f,
-+			0x28, 0x41, 0x5a, 0x73, 0x8c, 0xa5, 0xbe, 0xd7,
-+			0xf0, 0x09, 0x22, 0x3b, 0x54, 0x6d, 0x86, 0x9f,
-+			0xb8, 0xd1, 0xea, 0x03, 0x1c, 0x35, 0x4e, 0x67,
-+			0x80, 0x99, 0xb2, 0xcb, 0xe4, 0xfd, 0x16, 0x2f,
-+			0x48, 0x61, 0x7a, 0x93, 0xac, 0xc5, 0xde, 0xf7,
-+			0x10, 0x29, 0x42, 0x5b, 0x74, 0x8d, 0xa6, 0xbf,
-+			0xd8, 0xf1, 0x0a, 0x23, 0x3c, 0x55, 0x6e, 0x87,
-+			0xa0, 0xb9, 0xd2, 0xeb, 0x04, 0x1d, 0x36, 0x4f,
-+			0x68, 0x81, 0x9a, 0xb3, 0xcc, 0xe5, 0xfe, 0x17,
-+			0x30, 0x49, 0x62, 0x7b, 0x94, 0xad, 0xc6, 0xdf,
-+			0xf8, 0x11, 0x2a, 0x43, 0x5c, 0x75, 0x8e, 0xa7,
-+			0xc0, 0xd9, 0xf2, 0x0b, 0x24, 0x3d, 0x56, 0x6f,
-+			0x88, 0xa1, 0xba, 0xd3, 0xec, 0x05, 0x1e, 0x37,
-+			0x50, 0x69, 0x82, 0x9b, 0xb4, 0xcd, 0xe6, 0xff,
-+			0x18, 0x31, 0x4a, 0x63, 0x7c, 0x95, 0xae, 0xc7,
-+			0xe0, 0xf9, 0x12, 0x2b, 0x44, 0x5d, 0x76, 0x8f,
-+			0xa8, 0xc1, 0xda, 0xf3, 0x0c, 0x25, 0x3e, 0x57,
-+			0x70, 0x89, 0xa2, 0xbb, 0xd4, 0xed, 0x06, 0x1f,
-+			0x38, 0x51, 0x6a, 0x83, 0x9c, 0xb5, 0xce, 0xe7,
-+			0x00, 0x1b, 0x36, 0x51, 0x6c, 0x87, 0xa2, 0xbd,
-+			0xd8, 0xf3, 0x0e, 0x29, 0x44, 0x5f, 0x7a, 0x95,
-+			0xb0, 0xcb, 0xe6, 0x01, 0x1c, 0x37, 0x52, 0x6d,
-+			0x88, 0xa3, 0xbe, 0xd9, 0xf4, 0x0f, 0x2a, 0x45,
-+			0x60, 0x7b, 0x96, 0xb1, 0xcc, 0xe7, 0x02, 0x1d,
-+			0x38, 0x53, 0x6e, 0x89, 0xa4, 0xbf, 0xda, 0xf5,
-+			0x10, 0x2b, 0x46, 0x61, 0x7c, 0x97, 0xb2, 0xcd,
-+			0xe8, 0x03, 0x1e, 0x39, 0x54, 0x6f, 0x8a, 0xa5,
-+			0xc0, 0xdb, 0xf6, 0x11, 0x2c, 0x47, 0x62, 0x7d,
-+			0x98, 0xb3, 0xce, 0xe9, 0x04, 0x1f, 0x3a, 0x55,
-+			0x70, 0x8b, 0xa6, 0xc1, 0xdc, 0xf7, 0x12, 0x2d,
-+			0x48, 0x63, 0x7e, 0x99, 0xb4, 0xcf, 0xea, 0x05,
-+			0x20, 0x3b, 0x56, 0x71, 0x8c, 0xa7, 0xc2, 0xdd,
-+			0xf8, 0x13, 0x2e, 0x49, 0x64, 0x7f, 0x9a, 0xb5,
-+			0xd0, 0xeb, 0x06, 0x21, 0x3c, 0x57, 0x72, 0x8d,
-+			0xa8, 0xc3, 0xde, 0xf9, 0x14, 0x2f, 0x4a, 0x65,
-+			0x80, 0x9b, 0xb6, 0xd1, 0xec, 0x07, 0x22, 0x3d,
-+			0x58, 0x73, 0x8e, 0xa9, 0xc4, 0xdf, 0xfa, 0x15,
-+			0x30, 0x4b, 0x66, 0x81, 0x9c, 0xb7, 0xd2, 0xed,
-+			0x08, 0x23, 0x3e, 0x59, 0x74, 0x8f, 0xaa, 0xc5,
-+			0xe0, 0xfb, 0x16, 0x31, 0x4c, 0x67, 0x82, 0x9d,
-+			0xb8, 0xd3, 0xee, 0x09, 0x24, 0x3f, 0x5a, 0x75,
-+			0x90, 0xab, 0xc6, 0xe1, 0xfc, 0x17, 0x32, 0x4d,
-+			0x68, 0x83, 0x9e, 0xb9, 0xd4, 0xef, 0x0a, 0x25,
-+			0x40, 0x5b, 0x76, 0x91, 0xac, 0xc7, 0xe2, 0xfd,
-+			0x18, 0x33, 0x4e, 0x69, 0x84, 0x9f, 0xba, 0xd5,
-+			0xf0, 0x0b, 0x26, 0x41, 0x5c, 0x77, 0x92, 0xad,
-+			0xc8, 0xe3, 0xfe, 0x19, 0x34, 0x4f, 0x6a, 0x85,
-+			0xa0, 0xbb, 0xd6, 0xf1, 0x0c, 0x27, 0x42, 0x5d,
-+			0x78, 0x93, 0xae, 0xc9, 0xe4, 0xff, 0x1a, 0x35,
-+			0x50, 0x6b, 0x86, 0xa1, 0xbc, 0xd7, 0xf2, 0x0d,
-+			0x28, 0x43, 0x5e, 0x79, 0x94, 0xaf, 0xca, 0xe5,
-+			0x00, 0x1d, 0x3a, 0x57, 0x74, 0x91, 0xae, 0xcb,
-+			0xe8, 0x05, 0x22, 0x3f, 0x5c, 0x79, 0x96, 0xb3,
-+			0xd0, 0xed, 0x0a, 0x27, 0x44, 0x61, 0x7e, 0x9b,
-+			0xb8, 0xd5, 0xf2, 0x0f, 0x2c, 0x49, 0x66, 0x83,
-+			0xa0, 0xbd, 0xda, 0xf7, 0x14, 0x31, 0x4e, 0x6b,
-+			0x88, 0xa5, 0xc2, 0xdf, 0xfc, 0x19, 0x36, 0x53,
-+			0x70, 0x8d, 0xaa, 0xc7, 0xe4, 0x01, 0x1e, 0x3b,
-+			0x58, 0x75, 0x92, 0xaf, 0xcc, 0xe9, 0x06, 0x23,
-+			0x40, 0x5d, 0x7a, 0x97, 0xb4, 0xd1, 0xee, 0x0b,
-+			0x28, 0x45, 0x62, 0x7f, 0x9c, 0xb9, 0xd6, 0xf3,
-+			0x10, 0x2d, 0x4a, 0x67, 0x84, 0xa1, 0xbe, 0xdb,
-+			0xf8, 0x15, 0x32, 0x4f, 0x6c, 0x89, 0xa6, 0xc3,
-+			0xe0, 0xfd, 0x1a, 0x37, 0x54, 0x71, 0x8e, 0xab,
-+			0xc8, 0xe5, 0x02, 0x1f, 0x3c, 0x59, 0x76, 0x93,
-+			0xb0, 0xcd, 0xea, 0x07, 0x24, 0x41, 0x5e, 0x7b,
-+			0x98, 0xb5, 0xd2, 0xef, 0x0c, 0x29, 0x46, 0x63,
-+			0x80, 0x9d, 0xba, 0xd7, 0xf4, 0x11, 0x2e, 0x4b,
-+			0x68, 0x85, 0xa2, 0xbf, 0xdc, 0xf9, 0x16, 0x33,
-+			0x50, 0x6d, 0x8a, 0xa7, 0xc4, 0xe1, 0xfe, 0x1b,
-+			0x38, 0x55, 0x72, 0x8f, 0xac, 0xc9, 0xe6, 0x03,
-+			0x20, 0x3d, 0x5a, 0x77, 0x94, 0xb1, 0xce, 0xeb,
-+			0x08, 0x25, 0x42, 0x5f, 0x7c, 0x99, 0xb6, 0xd3,
-+			0xf0, 0x0d, 0x2a, 0x47, 0x64, 0x81, 0x9e, 0xbb,
-+			0xd8, 0xf5, 0x12, 0x2f, 0x4c, 0x69, 0x86, 0xa3,
-+			0xc0, 0xdd, 0xfa, 0x17, 0x34, 0x51, 0x6e, 0x8b,
-+			0xa8, 0xc5, 0xe2, 0xff, 0x1c, 0x39, 0x56, 0x73,
-+			0x90, 0xad, 0xca, 0xe7, 0x04, 0x21, 0x3e, 0x5b,
-+			0x78, 0x95, 0xb2, 0xcf, 0xec, 0x09, 0x26, 0x43,
-+			0x60, 0x7d, 0x9a, 0xb7, 0xd4, 0xf1, 0x0e, 0x2b,
-+			0x48, 0x65, 0x82, 0x9f, 0xbc, 0xd9, 0xf6, 0x13,
-+			0x30, 0x4d, 0x6a, 0x87, 0xa4, 0xc1, 0xde, 0xfb,
-+			0x18, 0x35, 0x52, 0x6f, 0x8c, 0xa9, 0xc6, 0xe3,
-+			0x00, 0x1f, 0x3e, 0x5d, 0x7c, 0x9b, 0xba, 0xd9,
-+			0xf8, 0x17, 0x36, 0x55, 0x74, 0x93, 0xb2, 0xd1,
-+			0xf0, 0x0f, 0x2e, 0x4d, 0x6c, 0x8b, 0xaa, 0xc9,
-+			0xe8, 0x07, 0x26, 0x45, 0x64, 0x83, 0xa2, 0xc1,
-+			0xe0, 0xff, 0x1e, 0x3d, 0x5c, 0x7b, 0x9a, 0xb9,
-+			0xd8, 0xf7, 0x16, 0x35, 0x54, 0x73, 0x92, 0xb1,
-+			0xd0, 0xef, 0x0e, 0x2d, 0x4c, 0x6b, 0x8a, 0xa9,
-+			0xc8, 0xe7, 0x06, 0x25, 0x44, 0x63, 0x82, 0xa1,
-+			0xc0, 0xdf, 0xfe, 0x1d, 0x3c, 0x5b, 0x7a, 0x99,
-+			0xb8, 0xd7, 0xf6, 0x15, 0x34, 0x53, 0x72, 0x91,
-+			0xb0, 0xcf, 0xee, 0x0d, 0x2c, 0x4b, 0x6a, 0x89,
-+			0xa8, 0xc7, 0xe6, 0x05, 0x24, 0x43, 0x62, 0x81,
-+			0xa0, 0xbf, 0xde, 0xfd, 0x1c, 0x3b, 0x5a, 0x79,
-+			0x98, 0xb7, 0xd6, 0xf5, 0x14, 0x33, 0x52, 0x71,
-+			0x90, 0xaf, 0xce, 0xed, 0x0c, 0x2b, 0x4a, 0x69,
-+			0x88, 0xa7, 0xc6, 0xe5, 0x04, 0x23, 0x42, 0x61,
-+			0x80, 0x9f, 0xbe, 0xdd, 0xfc, 0x1b, 0x3a, 0x59,
-+			0x78, 0x97, 0xb6, 0xd5, 0xf4, 0x13, 0x32, 0x51,
-+			0x70, 0x8f, 0xae, 0xcd, 0xec, 0x0b, 0x2a, 0x49,
-+			0x68, 0x87, 0xa6, 0xc5, 0xe4, 0x03, 0x22, 0x41,
-+			0x60, 0x7f, 0x9e, 0xbd, 0xdc, 0xfb, 0x1a, 0x39,
-+			0x58, 0x77, 0x96, 0xb5, 0xd4, 0xf3, 0x12, 0x31,
-+			0x50, 0x6f, 0x8e, 0xad, 0xcc, 0xeb, 0x0a, 0x29,
-+			0x48, 0x67, 0x86, 0xa5, 0xc4, 0xe3, 0x02, 0x21,
-+			0x40, 0x5f, 0x7e, 0x9d, 0xbc, 0xdb, 0xfa, 0x19,
-+			0x38, 0x57, 0x76, 0x95, 0xb4, 0xd3, 0xf2, 0x11,
-+			0x30, 0x4f, 0x6e, 0x8d, 0xac, 0xcb, 0xea, 0x09,
-+			0x28, 0x47, 0x66, 0x85, 0xa4, 0xc3, 0xe2, 0x01,
-+			0x20, 0x3f, 0x5e, 0x7d, 0x9c, 0xbb, 0xda, 0xf9,
-+			0x18, 0x37, 0x56, 0x75, 0x94, 0xb3, 0xd2, 0xf1,
-+			0x10, 0x2f, 0x4e, 0x6d, 0x8c, 0xab, 0xca, 0xe9,
-+			0x08, 0x27, 0x46, 0x65, 0x84, 0xa3, 0xc2, 0xe1,
-+			0x00, 0x21, 0x42, 0x63,
-+		},
-+		.ilen = 4100,
-+		.result = {
-+			0xb5, 0x81, 0xf5, 0x64, 0x18, 0x73, 0xe3, 0xf0,
-+			0x4c, 0x13, 0xf2, 0x77, 0x18, 0x60, 0x65, 0x5e,
-+			0x29, 0x01, 0xce, 0x98, 0x55, 0x53, 0xf9, 0x0c,
-+			0x2a, 0x08, 0xd5, 0x09, 0xb3, 0x57, 0x55, 0x56,
-+			0xc5, 0xe9, 0x56, 0x90, 0xcb, 0x6a, 0xa3, 0xc0,
-+			0xff, 0xc4, 0x79, 0xb4, 0xd2, 0x97, 0x5d, 0xc4,
-+			0x43, 0xd1, 0xfe, 0x94, 0x7b, 0x88, 0x06, 0x5a,
-+			0xb2, 0x9e, 0x2c, 0xfc, 0x44, 0x03, 0xb7, 0x90,
-+			0xa0, 0xc1, 0xba, 0x6a, 0x33, 0xb8, 0xc7, 0xb2,
-+			0x9d, 0xe1, 0x12, 0x4f, 0xc0, 0x64, 0xd4, 0x01,
-+			0xfe, 0x8c, 0x7a, 0x66, 0xf7, 0xe6, 0x5a, 0x91,
-+			0xbb, 0xde, 0x56, 0x86, 0xab, 0x65, 0x21, 0x30,
-+			0x00, 0x84, 0x65, 0x24, 0xa5, 0x7d, 0x85, 0xb4,
-+			0xe3, 0x17, 0xed, 0x3a, 0xb7, 0x6f, 0xb4, 0x0b,
-+			0x0b, 0xaf, 0x15, 0xae, 0x5a, 0x8f, 0xf2, 0x0c,
-+			0x2f, 0x27, 0xf4, 0x09, 0xd8, 0xd2, 0x96, 0xb7,
-+			0x71, 0xf2, 0xc5, 0x99, 0x4d, 0x7e, 0x7f, 0x75,
-+			0x77, 0x89, 0x30, 0x8b, 0x59, 0xdb, 0xa2, 0xb2,
-+			0xa0, 0xf3, 0x19, 0x39, 0x2b, 0xc5, 0x7e, 0x3f,
-+			0x4f, 0xd9, 0xd3, 0x56, 0x28, 0x97, 0x44, 0xdc,
-+			0xc0, 0x8b, 0x77, 0x24, 0xd9, 0x52, 0xe7, 0xc5,
-+			0xaf, 0xf6, 0x7d, 0x59, 0xb2, 0x44, 0x05, 0x1d,
-+			0xb1, 0xb0, 0x11, 0xa5, 0x0f, 0xec, 0x33, 0xe1,
-+			0x6d, 0x1b, 0x4e, 0x1f, 0xff, 0x57, 0x91, 0xb4,
-+			0x5b, 0x9a, 0x96, 0xc5, 0x53, 0xbc, 0xae, 0x20,
-+			0x3c, 0xbb, 0x14, 0xe2, 0xe8, 0x22, 0x33, 0xc1,
-+			0x5e, 0x76, 0x9e, 0x46, 0x99, 0xf6, 0x2a, 0x15,
-+			0xc6, 0x97, 0x02, 0xa0, 0x66, 0x43, 0xd1, 0xa6,
-+			0x31, 0xa6, 0x9f, 0xfb, 0xf4, 0xd3, 0x69, 0xe5,
-+			0xcd, 0x76, 0x95, 0xb8, 0x7a, 0x82, 0x7f, 0x21,
-+			0x45, 0xff, 0x3f, 0xce, 0x55, 0xf6, 0x95, 0x10,
-+			0x08, 0x77, 0x10, 0x43, 0xc6, 0xf3, 0x09, 0xe5,
-+			0x68, 0xe7, 0x3c, 0xad, 0x00, 0x52, 0x45, 0x0d,
-+			0xfe, 0x2d, 0xc6, 0xc2, 0x94, 0x8c, 0x12, 0x1d,
-+			0xe6, 0x25, 0xae, 0x98, 0x12, 0x8e, 0x19, 0x9c,
-+			0x81, 0x68, 0xb1, 0x11, 0xf6, 0x69, 0xda, 0xe3,
-+			0x62, 0x08, 0x18, 0x7a, 0x25, 0x49, 0x28, 0xac,
-+			0xba, 0x71, 0x12, 0x0b, 0xe4, 0xa2, 0xe5, 0xc7,
-+			0x5d, 0x8e, 0xec, 0x49, 0x40, 0x21, 0xbf, 0x5a,
-+			0x98, 0xf3, 0x02, 0x68, 0x55, 0x03, 0x7f, 0x8a,
-+			0xe5, 0x94, 0x0c, 0x32, 0x5c, 0x07, 0x82, 0x63,
-+			0xaf, 0x6f, 0x91, 0x40, 0x84, 0x8e, 0x52, 0x25,
-+			0xd0, 0xb0, 0x29, 0x53, 0x05, 0xe2, 0x50, 0x7a,
-+			0x34, 0xeb, 0xc9, 0x46, 0x20, 0xa8, 0x3d, 0xde,
-+			0x7f, 0x16, 0x5f, 0x36, 0xc5, 0x2e, 0xdc, 0xd1,
-+			0x15, 0x47, 0xc7, 0x50, 0x40, 0x6d, 0x91, 0xc5,
-+			0xe7, 0x93, 0x95, 0x1a, 0xd3, 0x57, 0xbc, 0x52,
-+			0x33, 0xee, 0x14, 0x19, 0x22, 0x52, 0x89, 0xa7,
-+			0x4a, 0x25, 0x56, 0x77, 0x4b, 0xca, 0xcf, 0x0a,
-+			0xe1, 0xf5, 0x35, 0x85, 0x30, 0x7e, 0x59, 0x4a,
-+			0xbd, 0x14, 0x5b, 0xdf, 0xe3, 0x46, 0xcb, 0xac,
-+			0x1f, 0x6c, 0x96, 0x0e, 0xf4, 0x81, 0xd1, 0x99,
-+			0xca, 0x88, 0x63, 0x3d, 0x02, 0x58, 0x6b, 0xa9,
-+			0xe5, 0x9f, 0xb3, 0x00, 0xb2, 0x54, 0xc6, 0x74,
-+			0x1c, 0xbf, 0x46, 0xab, 0x97, 0xcc, 0xf8, 0x54,
-+			0x04, 0x07, 0x08, 0x52, 0xe6, 0xc0, 0xda, 0x93,
-+			0x74, 0x7d, 0x93, 0x99, 0x5d, 0x78, 0x68, 0xa6,
-+			0x2e, 0x6b, 0xd3, 0x6a, 0x69, 0xcc, 0x12, 0x6b,
-+			0xd4, 0xc7, 0xa5, 0xc6, 0xe7, 0xf6, 0x03, 0x04,
-+			0x5d, 0xcd, 0x61, 0x5e, 0x17, 0x40, 0xdc, 0xd1,
-+			0x5c, 0xf5, 0x08, 0xdf, 0x5c, 0x90, 0x85, 0xa4,
-+			0xaf, 0xf6, 0x78, 0xbb, 0x0d, 0xf1, 0xf4, 0xa4,
-+			0x54, 0x26, 0x72, 0x9e, 0x61, 0xfa, 0x86, 0xcf,
-+			0xe8, 0x9e, 0xa1, 0xe0, 0xc7, 0x48, 0x23, 0xae,
-+			0x5a, 0x90, 0xae, 0x75, 0x0a, 0x74, 0x18, 0x89,
-+			0x05, 0xb1, 0x92, 0xb2, 0x7f, 0xd0, 0x1b, 0xa6,
-+			0x62, 0x07, 0x25, 0x01, 0xc7, 0xc2, 0x4f, 0xf9,
-+			0xe8, 0xfe, 0x63, 0x95, 0x80, 0x07, 0xb4, 0x26,
-+			0xcc, 0xd1, 0x26, 0xb6, 0xc4, 0x3f, 0x9e, 0xcb,
-+			0x8e, 0x3b, 0x2e, 0x44, 0x16, 0xd3, 0x10, 0x9a,
-+			0x95, 0x08, 0xeb, 0xc8, 0xcb, 0xeb, 0xbf, 0x6f,
-+			0x0b, 0xcd, 0x1f, 0xc8, 0xca, 0x86, 0xaa, 0xec,
-+			0x33, 0xe6, 0x69, 0xf4, 0x45, 0x25, 0x86, 0x3a,
-+			0x22, 0x94, 0x4f, 0x00, 0x23, 0x6a, 0x44, 0xc2,
-+			0x49, 0x97, 0x33, 0xab, 0x36, 0x14, 0x0a, 0x70,
-+			0x24, 0xc3, 0xbe, 0x04, 0x3b, 0x79, 0xa0, 0xf9,
-+			0xb8, 0xe7, 0x76, 0x29, 0x22, 0x83, 0xd7, 0xf2,
-+			0x94, 0xf4, 0x41, 0x49, 0xba, 0x5f, 0x7b, 0x07,
-+			0xb5, 0xfb, 0xdb, 0x03, 0x1a, 0x9f, 0xb6, 0x4c,
-+			0xc2, 0x2e, 0x37, 0x40, 0x49, 0xc3, 0x38, 0x16,
-+			0xe2, 0x4f, 0x77, 0x82, 0xb0, 0x68, 0x4c, 0x71,
-+			0x1d, 0x57, 0x61, 0x9c, 0xd9, 0x4e, 0x54, 0x99,
-+			0x47, 0x13, 0x28, 0x73, 0x3c, 0xbb, 0x00, 0x90,
-+			0xf3, 0x4d, 0xc9, 0x0e, 0xfd, 0xe7, 0xb1, 0x71,
-+			0xd3, 0x15, 0x79, 0xbf, 0xcc, 0x26, 0x2f, 0xbd,
-+			0xad, 0x6c, 0x50, 0x69, 0x6c, 0x3e, 0x6d, 0x80,
-+			0x9a, 0xea, 0x78, 0xaf, 0x19, 0xb2, 0x0d, 0x4d,
-+			0xad, 0x04, 0x07, 0xae, 0x22, 0x90, 0x4a, 0x93,
-+			0x32, 0x0e, 0x36, 0x9b, 0x1b, 0x46, 0xba, 0x3b,
-+			0xb4, 0xac, 0xc6, 0xd1, 0xa2, 0x31, 0x53, 0x3b,
-+			0x2a, 0x3d, 0x45, 0xfe, 0x03, 0x61, 0x10, 0x85,
-+			0x17, 0x69, 0xa6, 0x78, 0xcc, 0x6c, 0x87, 0x49,
-+			0x53, 0xf9, 0x80, 0x10, 0xde, 0x80, 0xa2, 0x41,
-+			0x6a, 0xc3, 0x32, 0x02, 0xad, 0x6d, 0x3c, 0x56,
-+			0x00, 0x71, 0x51, 0x06, 0xa7, 0xbd, 0xfb, 0xef,
-+			0x3c, 0xb5, 0x9f, 0xfc, 0x48, 0x7d, 0x53, 0x7c,
-+			0x66, 0xb0, 0x49, 0x23, 0xc4, 0x47, 0x10, 0x0e,
-+			0xe5, 0x6c, 0x74, 0x13, 0xe6, 0xc5, 0x3f, 0xaa,
-+			0xde, 0xff, 0x07, 0x44, 0xdd, 0x56, 0x1b, 0xad,
-+			0x09, 0x77, 0xfb, 0x5b, 0x12, 0xb8, 0x0d, 0x38,
-+			0x17, 0x37, 0x35, 0x7b, 0x9b, 0xbc, 0xfe, 0xd4,
-+			0x7e, 0x8b, 0xda, 0x7e, 0x5b, 0x04, 0xa7, 0x22,
-+			0xa7, 0x31, 0xa1, 0x20, 0x86, 0xc7, 0x1b, 0x99,
-+			0xdb, 0xd1, 0x89, 0xf4, 0x94, 0xa3, 0x53, 0x69,
-+			0x8d, 0xe7, 0xe8, 0x74, 0x11, 0x8d, 0x74, 0xd6,
-+			0x07, 0x37, 0x91, 0x9f, 0xfd, 0x67, 0x50, 0x3a,
-+			0xc9, 0xe1, 0xf4, 0x36, 0xd5, 0xa0, 0x47, 0xd1,
-+			0xf9, 0xe5, 0x39, 0xa3, 0x31, 0xac, 0x07, 0x36,
-+			0x23, 0xf8, 0x66, 0x18, 0x14, 0x28, 0x34, 0x0f,
-+			0xb8, 0xd0, 0xe7, 0x29, 0xb3, 0x04, 0x4b, 0x55,
-+			0x01, 0x41, 0xb2, 0x75, 0x8d, 0xcb, 0x96, 0x85,
-+			0x3a, 0xfb, 0xab, 0x2b, 0x9e, 0xfa, 0x58, 0x20,
-+			0x44, 0x1f, 0xc0, 0x14, 0x22, 0x75, 0x61, 0xe8,
-+			0xaa, 0x19, 0xcf, 0xf1, 0x82, 0x56, 0xf4, 0xd7,
-+			0x78, 0x7b, 0x3d, 0x5f, 0xb3, 0x9e, 0x0b, 0x8a,
-+			0x57, 0x50, 0xdb, 0x17, 0x41, 0x65, 0x4d, 0xa3,
-+			0x02, 0xc9, 0x9c, 0x9c, 0x53, 0xfb, 0x39, 0x39,
-+			0x9b, 0x1d, 0x72, 0x24, 0xda, 0xb7, 0x39, 0xbe,
-+			0x13, 0x3b, 0xfa, 0x29, 0xda, 0x9e, 0x54, 0x64,
-+			0x6e, 0xba, 0xd8, 0xa1, 0xcb, 0xb3, 0x36, 0xfa,
-+			0xcb, 0x47, 0x85, 0xe9, 0x61, 0x38, 0xbc, 0xbe,
-+			0xc5, 0x00, 0x38, 0x2a, 0x54, 0xf7, 0xc4, 0xb9,
-+			0xb3, 0xd3, 0x7b, 0xa0, 0xa0, 0xf8, 0x72, 0x7f,
-+			0x8c, 0x8e, 0x82, 0x0e, 0xc6, 0x1c, 0x75, 0x9d,
-+			0xca, 0x8e, 0x61, 0x87, 0xde, 0xad, 0x80, 0xd2,
-+			0xf5, 0xf9, 0x80, 0xef, 0x15, 0x75, 0xaf, 0xf5,
-+			0x80, 0xfb, 0xff, 0x6d, 0x1e, 0x25, 0xb7, 0x40,
-+			0x61, 0x6a, 0x39, 0x5a, 0x6a, 0xb5, 0x31, 0xab,
-+			0x97, 0x8a, 0x19, 0x89, 0x44, 0x40, 0xc0, 0xa6,
-+			0xb4, 0x4e, 0x30, 0x32, 0x7b, 0x13, 0xe7, 0x67,
-+			0xa9, 0x8b, 0x57, 0x04, 0xc2, 0x01, 0xa6, 0xf4,
-+			0x28, 0x99, 0xad, 0x2c, 0x76, 0xa3, 0x78, 0xc2,
-+			0x4a, 0xe6, 0xca, 0x5c, 0x50, 0x6a, 0xc1, 0xb0,
-+			0x62, 0x4b, 0x10, 0x8e, 0x7c, 0x17, 0x43, 0xb3,
-+			0x17, 0x66, 0x1c, 0x3e, 0x8d, 0x69, 0xf0, 0x5a,
-+			0x71, 0xf5, 0x97, 0xdc, 0xd1, 0x45, 0xdd, 0x28,
-+			0xf3, 0x5d, 0xdf, 0x53, 0x7b, 0x11, 0xe5, 0xbc,
-+			0x4c, 0xdb, 0x1b, 0x51, 0x6b, 0xe9, 0xfb, 0x3d,
-+			0xc1, 0xc3, 0x2c, 0xb9, 0x71, 0xf5, 0xb6, 0xb2,
-+			0x13, 0x36, 0x79, 0x80, 0x53, 0xe8, 0xd3, 0xa6,
-+			0x0a, 0xaf, 0xfd, 0x56, 0x97, 0xf7, 0x40, 0x8e,
-+			0x45, 0xce, 0xf8, 0xb0, 0x9e, 0x5c, 0x33, 0x82,
-+			0xb0, 0x44, 0x56, 0xfc, 0x05, 0x09, 0xe9, 0x2a,
-+			0xac, 0x26, 0x80, 0x14, 0x1d, 0xc8, 0x3a, 0x35,
-+			0x4c, 0x82, 0x97, 0xfd, 0x76, 0xb7, 0xa9, 0x0a,
-+			0x35, 0x58, 0x79, 0x8e, 0x0f, 0x66, 0xea, 0xaf,
-+			0x51, 0x6c, 0x09, 0xa9, 0x6e, 0x9b, 0xcb, 0x9a,
-+			0x31, 0x47, 0xa0, 0x2f, 0x7c, 0x71, 0xb4, 0x4a,
-+			0x11, 0xaa, 0x8c, 0x66, 0xc5, 0x64, 0xe6, 0x3a,
-+			0x54, 0xda, 0x24, 0x6a, 0xc4, 0x41, 0x65, 0x46,
-+			0x82, 0xa0, 0x0a, 0x0f, 0x5f, 0xfb, 0x25, 0xd0,
-+			0x2c, 0x91, 0xa7, 0xee, 0xc4, 0x81, 0x07, 0x86,
-+			0x75, 0x5e, 0x33, 0x69, 0x97, 0xe4, 0x2c, 0xa8,
-+			0x9d, 0x9f, 0x0b, 0x6a, 0xbe, 0xad, 0x98, 0xda,
-+			0x6d, 0x94, 0x41, 0xda, 0x2c, 0x1e, 0x89, 0xc4,
-+			0xc2, 0xaf, 0x1e, 0x00, 0x05, 0x0b, 0x83, 0x60,
-+			0xbd, 0x43, 0xea, 0x15, 0x23, 0x7f, 0xb9, 0xac,
-+			0xee, 0x4f, 0x2c, 0xaf, 0x2a, 0xf3, 0xdf, 0xd0,
-+			0xf3, 0x19, 0x31, 0xbb, 0x4a, 0x74, 0x84, 0x17,
-+			0x52, 0x32, 0x2c, 0x7d, 0x61, 0xe4, 0xcb, 0xeb,
-+			0x80, 0x38, 0x15, 0x52, 0xcb, 0x6f, 0xea, 0xe5,
-+			0x73, 0x9c, 0xd9, 0x24, 0x69, 0xc6, 0x95, 0x32,
-+			0x21, 0xc8, 0x11, 0xe4, 0xdc, 0x36, 0xd7, 0x93,
-+			0x38, 0x66, 0xfb, 0xb2, 0x7f, 0x3a, 0xb9, 0xaf,
-+			0x31, 0xdd, 0x93, 0x75, 0x78, 0x8a, 0x2c, 0x94,
-+			0x87, 0x1a, 0x58, 0xec, 0x9e, 0x7d, 0x4d, 0xba,
-+			0xe1, 0xe5, 0x4d, 0xfc, 0xbc, 0xa4, 0x2a, 0x14,
-+			0xef, 0xcc, 0xa7, 0xec, 0xab, 0x43, 0x09, 0x18,
-+			0xd3, 0xab, 0x68, 0xd1, 0x07, 0x99, 0x44, 0x47,
-+			0xd6, 0x83, 0x85, 0x3b, 0x30, 0xea, 0xa9, 0x6b,
-+			0x63, 0xea, 0xc4, 0x07, 0xfb, 0x43, 0x2f, 0xa4,
-+			0xaa, 0xb0, 0xab, 0x03, 0x89, 0xce, 0x3f, 0x8c,
-+			0x02, 0x7c, 0x86, 0x54, 0xbc, 0x88, 0xaf, 0x75,
-+			0xd2, 0xdc, 0x63, 0x17, 0xd3, 0x26, 0xf6, 0x96,
-+			0xa9, 0x3c, 0xf1, 0x61, 0x8c, 0x11, 0x18, 0xcc,
-+			0xd6, 0xea, 0x5b, 0xe2, 0xcd, 0xf0, 0xf1, 0xb2,
-+			0xe5, 0x35, 0x90, 0x1f, 0x85, 0x4c, 0x76, 0x5b,
-+			0x66, 0xce, 0x44, 0xa4, 0x32, 0x9f, 0xe6, 0x7b,
-+			0x71, 0x6e, 0x9f, 0x58, 0x15, 0x67, 0x72, 0x87,
-+			0x64, 0x8e, 0x3a, 0x44, 0x45, 0xd4, 0x76, 0xfa,
-+			0xc2, 0xf6, 0xef, 0x85, 0x05, 0x18, 0x7a, 0x9b,
-+			0xba, 0x41, 0x54, 0xac, 0xf0, 0xfc, 0x59, 0x12,
-+			0x3f, 0xdf, 0xa0, 0xe5, 0x8a, 0x65, 0xfd, 0x3a,
-+			0x62, 0x8d, 0x83, 0x2c, 0x03, 0xbe, 0x05, 0x76,
-+			0x2e, 0x53, 0x49, 0x97, 0x94, 0x33, 0xae, 0x40,
-+			0x81, 0x15, 0xdb, 0x6e, 0xad, 0xaa, 0xf5, 0x4b,
-+			0xe3, 0x98, 0x70, 0xdf, 0xe0, 0x7c, 0xcd, 0xdb,
-+			0x02, 0xd4, 0x7d, 0x2f, 0xc1, 0xe6, 0xb4, 0xf3,
-+			0xd7, 0x0d, 0x7a, 0xd9, 0x23, 0x9e, 0x87, 0x2d,
-+			0xce, 0x87, 0xad, 0xcc, 0x72, 0x05, 0x00, 0x29,
-+			0xdc, 0x73, 0x7f, 0x64, 0xc1, 0x15, 0x0e, 0xc2,
-+			0xdf, 0xa7, 0x5f, 0xeb, 0x41, 0xa1, 0xcd, 0xef,
-+			0x5c, 0x50, 0x79, 0x2a, 0x56, 0x56, 0x71, 0x8c,
-+			0xac, 0xc0, 0x79, 0x50, 0x69, 0xca, 0x59, 0x32,
-+			0x65, 0xf2, 0x54, 0xe4, 0x52, 0x38, 0x76, 0xd1,
-+			0x5e, 0xde, 0x26, 0x9e, 0xfb, 0x75, 0x2e, 0x11,
-+			0xb5, 0x10, 0xf4, 0x17, 0x73, 0xf5, 0x89, 0xc7,
-+			0x4f, 0x43, 0x5c, 0x8e, 0x7c, 0xb9, 0x05, 0x52,
-+			0x24, 0x40, 0x99, 0xfe, 0x9b, 0x85, 0x0b, 0x6c,
-+			0x22, 0x3e, 0x8b, 0xae, 0x86, 0xa1, 0xd2, 0x79,
-+			0x05, 0x68, 0x6b, 0xab, 0xe3, 0x41, 0x49, 0xed,
-+			0x15, 0xa1, 0x8d, 0x40, 0x2d, 0x61, 0xdf, 0x1a,
-+			0x59, 0xc9, 0x26, 0x8b, 0xef, 0x30, 0x4c, 0x88,
-+			0x4b, 0x10, 0xf8, 0x8d, 0xa6, 0x92, 0x9f, 0x4b,
-+			0xf3, 0xc4, 0x53, 0x0b, 0x89, 0x5d, 0x28, 0x92,
-+			0xcf, 0x78, 0xb2, 0xc0, 0x5d, 0xed, 0x7e, 0xfc,
-+			0xc0, 0x12, 0x23, 0x5f, 0x5a, 0x78, 0x86, 0x43,
-+			0x6e, 0x27, 0xf7, 0x5a, 0xa7, 0x6a, 0xed, 0x19,
-+			0x04, 0xf0, 0xb3, 0x12, 0xd1, 0xbd, 0x0e, 0x89,
-+			0x6e, 0xbc, 0x96, 0xa8, 0xd8, 0x49, 0x39, 0x9f,
-+			0x7e, 0x67, 0xf0, 0x2e, 0x3e, 0x01, 0xa9, 0xba,
-+			0xec, 0x8b, 0x62, 0x8e, 0xcb, 0x4a, 0x70, 0x43,
-+			0xc7, 0xc2, 0xc4, 0xca, 0x82, 0x03, 0x73, 0xe9,
-+			0x11, 0xdf, 0xcf, 0x54, 0xea, 0xc9, 0xb0, 0x95,
-+			0x51, 0xc0, 0x13, 0x3d, 0x92, 0x05, 0xfa, 0xf4,
-+			0xa9, 0x34, 0xc8, 0xce, 0x6c, 0x3d, 0x54, 0xcc,
-+			0xc4, 0xaf, 0xf1, 0xdc, 0x11, 0x44, 0x26, 0xa2,
-+			0xaf, 0xf1, 0x85, 0x75, 0x7d, 0x03, 0x61, 0x68,
-+			0x4e, 0x78, 0xc6, 0x92, 0x7d, 0x86, 0x7d, 0x77,
-+			0xdc, 0x71, 0x72, 0xdb, 0xc6, 0xae, 0xa1, 0xcb,
-+			0x70, 0x9a, 0x0b, 0x19, 0xbe, 0x4a, 0x6c, 0x2a,
-+			0xe2, 0xba, 0x6c, 0x64, 0x9a, 0x13, 0x28, 0xdf,
-+			0x85, 0x75, 0xe6, 0x43, 0xf6, 0x87, 0x08, 0x68,
-+			0x6e, 0xba, 0x6e, 0x79, 0x9f, 0x04, 0xbc, 0x23,
-+			0x50, 0xf6, 0x33, 0x5c, 0x1f, 0x24, 0x25, 0xbe,
-+			0x33, 0x47, 0x80, 0x45, 0x56, 0xa3, 0xa7, 0xd7,
-+			0x7a, 0xb1, 0x34, 0x0b, 0x90, 0x3c, 0x9c, 0xad,
-+			0x44, 0x5f, 0x9e, 0x0e, 0x9d, 0xd4, 0xbd, 0x93,
-+			0x5e, 0xfa, 0x3c, 0xe0, 0xb0, 0xd9, 0xed, 0xf3,
-+			0xd6, 0x2e, 0xff, 0x24, 0xd8, 0x71, 0x6c, 0xed,
-+			0xaf, 0x55, 0xeb, 0x22, 0xac, 0x93, 0x68, 0x32,
-+			0x05, 0x5b, 0x47, 0xdd, 0xc6, 0x4a, 0xcb, 0xc7,
-+			0x10, 0xe1, 0x3c, 0x92, 0x1a, 0xf3, 0x23, 0x78,
-+			0x2b, 0xa1, 0xd2, 0x80, 0xf4, 0x12, 0xb1, 0x20,
-+			0x8f, 0xff, 0x26, 0x35, 0xdd, 0xfb, 0xc7, 0x4e,
-+			0x78, 0xf1, 0x2d, 0x50, 0x12, 0x77, 0xa8, 0x60,
-+			0x7c, 0x0f, 0xf5, 0x16, 0x2f, 0x63, 0x70, 0x2a,
-+			0xc0, 0x96, 0x80, 0x4e, 0x0a, 0xb4, 0x93, 0x35,
-+			0x5d, 0x1d, 0x3f, 0x56, 0xf7, 0x2f, 0xbb, 0x90,
-+			0x11, 0x16, 0x8f, 0xa2, 0xec, 0x47, 0xbe, 0xac,
-+			0x56, 0x01, 0x26, 0x56, 0xb1, 0x8c, 0xb2, 0x10,
-+			0xf9, 0x1a, 0xca, 0xf5, 0xd1, 0xb7, 0x39, 0x20,
-+			0x63, 0xf1, 0x69, 0x20, 0x4f, 0x13, 0x12, 0x1f,
-+			0x5b, 0x65, 0xfc, 0x98, 0xf7, 0xc4, 0x7a, 0xbe,
-+			0xf7, 0x26, 0x4d, 0x2b, 0x84, 0x7b, 0x42, 0xad,
-+			0xd8, 0x7a, 0x0a, 0xb4, 0xd8, 0x74, 0xbf, 0xc1,
-+			0xf0, 0x6e, 0xb4, 0x29, 0xa3, 0xbb, 0xca, 0x46,
-+			0x67, 0x70, 0x6a, 0x2d, 0xce, 0x0e, 0xa2, 0x8a,
-+			0xa9, 0x87, 0xbf, 0x05, 0xc4, 0xc1, 0x04, 0xa3,
-+			0xab, 0xd4, 0x45, 0x43, 0x8c, 0xb6, 0x02, 0xb0,
-+			0x41, 0xc8, 0xfc, 0x44, 0x3d, 0x59, 0xaa, 0x2e,
-+			0x44, 0x21, 0x2a, 0x8d, 0x88, 0x9d, 0x57, 0xf4,
-+			0xa0, 0x02, 0x77, 0xb8, 0xa6, 0xa0, 0xe6, 0x75,
-+			0x5c, 0x82, 0x65, 0x3e, 0x03, 0x5c, 0x29, 0x8f,
-+			0x38, 0x55, 0xab, 0x33, 0x26, 0xef, 0x9f, 0x43,
-+			0x52, 0xfd, 0x68, 0xaf, 0x36, 0xb4, 0xbb, 0x9a,
-+			0x58, 0x09, 0x09, 0x1b, 0xc3, 0x65, 0x46, 0x46,
-+			0x1d, 0xa7, 0x94, 0x18, 0x23, 0x50, 0x2c, 0xca,
-+			0x2c, 0x55, 0x19, 0x97, 0x01, 0x9d, 0x93, 0x3b,
-+			0x63, 0x86, 0xf2, 0x03, 0x67, 0x45, 0xd2, 0x72,
-+			0x28, 0x52, 0x6c, 0xf4, 0xe3, 0x1c, 0xb5, 0x11,
-+			0x13, 0xf1, 0xeb, 0x21, 0xc7, 0xd9, 0x56, 0x82,
-+			0x2b, 0x82, 0x39, 0xbd, 0x69, 0x54, 0xed, 0x62,
-+			0xc3, 0xe2, 0xde, 0x73, 0xd4, 0x6a, 0x12, 0xae,
-+			0x13, 0x21, 0x7f, 0x4b, 0x5b, 0xfc, 0xbf, 0xe8,
-+			0x2b, 0xbe, 0x56, 0xba, 0x68, 0x8b, 0x9a, 0xb1,
-+			0x6e, 0xfa, 0xbf, 0x7e, 0x5a, 0x4b, 0xf1, 0xac,
-+			0x98, 0x65, 0x85, 0xd1, 0x93, 0x53, 0xd3, 0x7b,
-+			0x09, 0xdd, 0x4b, 0x10, 0x6d, 0x84, 0xb0, 0x13,
-+			0x65, 0xbd, 0xcf, 0x52, 0x09, 0xc4, 0x85, 0xe2,
-+			0x84, 0x74, 0x15, 0x65, 0xb7, 0xf7, 0x51, 0xaf,
-+			0x55, 0xad, 0xa4, 0xd1, 0x22, 0x54, 0x70, 0x94,
-+			0xa0, 0x1c, 0x90, 0x41, 0xfd, 0x99, 0xd7, 0x5a,
-+			0x31, 0xef, 0xaa, 0x25, 0xd0, 0x7f, 0x4f, 0xea,
-+			0x1d, 0x55, 0x42, 0xe5, 0x49, 0xb0, 0xd0, 0x46,
-+			0x62, 0x36, 0x43, 0xb2, 0x82, 0x15, 0x75, 0x50,
-+			0xa4, 0x72, 0xeb, 0x54, 0x27, 0x1f, 0x8a, 0xe4,
-+			0x7d, 0xe9, 0x66, 0xc5, 0xf1, 0x53, 0xa4, 0xd1,
-+			0x0c, 0xeb, 0xb8, 0xf8, 0xbc, 0xd4, 0xe2, 0xe7,
-+			0xe1, 0xf8, 0x4b, 0xcb, 0xa9, 0xa1, 0xaf, 0x15,
-+			0x83, 0xcb, 0x72, 0xd0, 0x33, 0x79, 0x00, 0x2d,
-+			0x9f, 0xd7, 0xf1, 0x2e, 0x1e, 0x10, 0xe4, 0x45,
-+			0xc0, 0x75, 0x3a, 0x39, 0xea, 0x68, 0xf7, 0x5d,
-+			0x1b, 0x73, 0x8f, 0xe9, 0x8e, 0x0f, 0x72, 0x47,
-+			0xae, 0x35, 0x0a, 0x31, 0x7a, 0x14, 0x4d, 0x4a,
-+			0x6f, 0x47, 0xf7, 0x7e, 0x91, 0x6e, 0x74, 0x8b,
-+			0x26, 0x47, 0xf9, 0xc3, 0xf9, 0xde, 0x70, 0xf5,
-+			0x61, 0xab, 0xa9, 0x27, 0x9f, 0x82, 0xe4, 0x9c,
-+			0x89, 0x91, 0x3f, 0x2e, 0x6a, 0xfd, 0xb5, 0x49,
-+			0xe9, 0xfd, 0x59, 0x14, 0x36, 0x49, 0x40, 0x6d,
-+			0x32, 0xd8, 0x85, 0x42, 0xf3, 0xa5, 0xdf, 0x0c,
-+			0xa8, 0x27, 0xd7, 0x54, 0xe2, 0x63, 0x2f, 0xf2,
-+			0x7e, 0x8b, 0x8b, 0xe7, 0xf1, 0x9a, 0x95, 0x35,
-+			0x43, 0xdc, 0x3a, 0xe4, 0xb6, 0xf4, 0xd0, 0xdf,
-+			0x9c, 0xcb, 0x94, 0xf3, 0x21, 0xa0, 0x77, 0x50,
-+			0xe2, 0xc6, 0xc4, 0xc6, 0x5f, 0x09, 0x64, 0x5b,
-+			0x92, 0x90, 0xd8, 0xe1, 0xd1, 0xed, 0x4b, 0x42,
-+			0xd7, 0x37, 0xaf, 0x65, 0x3d, 0x11, 0x39, 0xb6,
-+			0x24, 0x8a, 0x60, 0xae, 0xd6, 0x1e, 0xbf, 0x0e,
-+			0x0d, 0xd7, 0xdc, 0x96, 0x0e, 0x65, 0x75, 0x4e,
-+			0x29, 0x06, 0x9d, 0xa4, 0x51, 0x3a, 0x10, 0x63,
-+			0x8f, 0x17, 0x07, 0xd5, 0x8e, 0x3c, 0xf4, 0x28,
-+			0x00, 0x5a, 0x5b, 0x05, 0x19, 0xd8, 0xc0, 0x6c,
-+			0xe5, 0x15, 0xe4, 0x9c, 0x9d, 0x71, 0x9d, 0x5e,
-+			0x94, 0x29, 0x1a, 0xa7, 0x80, 0xfa, 0x0e, 0x33,
-+			0x03, 0xdd, 0xb7, 0x3e, 0x9a, 0xa9, 0x26, 0x18,
-+			0x37, 0xa9, 0x64, 0x08, 0x4d, 0x94, 0x5a, 0x88,
-+			0xca, 0x35, 0xce, 0x81, 0x02, 0xe3, 0x1f, 0x1b,
-+			0x89, 0x1a, 0x77, 0x85, 0xe3, 0x41, 0x6d, 0x32,
-+			0x42, 0x19, 0x23, 0x7d, 0xc8, 0x73, 0xee, 0x25,
-+			0x85, 0x0d, 0xf8, 0x31, 0x25, 0x79, 0x1b, 0x6f,
-+			0x79, 0x25, 0xd2, 0xd8, 0xd4, 0x23, 0xfd, 0xf7,
-+			0x82, 0x36, 0x6a, 0x0c, 0x46, 0x22, 0x15, 0xe9,
-+			0xff, 0x72, 0x41, 0x91, 0x91, 0x7d, 0x3a, 0xb7,
-+			0xdd, 0x65, 0x99, 0x70, 0xf6, 0x8d, 0x84, 0xf8,
-+			0x67, 0x15, 0x20, 0x11, 0xd6, 0xb2, 0x55, 0x7b,
-+			0xdb, 0x87, 0xee, 0xef, 0x55, 0x89, 0x2a, 0x59,
-+			0x2b, 0x07, 0x8f, 0x43, 0x8a, 0x59, 0x3c, 0x01,
-+			0x8b, 0x65, 0x54, 0xa1, 0x66, 0xd5, 0x38, 0xbd,
-+			0xc6, 0x30, 0xa9, 0xcc, 0x49, 0xb6, 0xa8, 0x1b,
-+			0xb8, 0xc0, 0x0e, 0xe3, 0x45, 0x28, 0xe2, 0xff,
-+			0x41, 0x9f, 0x7e, 0x7c, 0xd1, 0xae, 0x9e, 0x25,
-+			0x3f, 0x4c, 0x7c, 0x7c, 0xf4, 0xa8, 0x26, 0x4d,
-+			0x5c, 0xfd, 0x4b, 0x27, 0x18, 0xf9, 0x61, 0x76,
-+			0x48, 0xba, 0x0c, 0x6b, 0xa9, 0x4d, 0xfc, 0xf5,
-+			0x3b, 0x35, 0x7e, 0x2f, 0x4a, 0xa9, 0xc2, 0x9a,
-+			0xae, 0xab, 0x86, 0x09, 0x89, 0xc9, 0xc2, 0x40,
-+			0x39, 0x2c, 0x81, 0xb3, 0xb8, 0x17, 0x67, 0xc2,
-+			0x0d, 0x32, 0x4a, 0x3a, 0x67, 0x81, 0xd7, 0x1a,
-+			0x34, 0x52, 0xc5, 0xdb, 0x0a, 0xf5, 0x63, 0x39,
-+			0xea, 0x1f, 0xe1, 0x7c, 0xa1, 0x9e, 0xc1, 0x35,
-+			0xe3, 0xb1, 0x18, 0x45, 0x67, 0xf9, 0x22, 0x38,
-+			0x95, 0xd9, 0x34, 0x34, 0x86, 0xc6, 0x41, 0x94,
-+			0x15, 0xf9, 0x5b, 0x41, 0xa6, 0x87, 0x8b, 0xf8,
-+			0xd5, 0xe1, 0x1b, 0xe2, 0x5b, 0xf3, 0x86, 0x10,
-+			0xff, 0xe6, 0xae, 0x69, 0x76, 0xbc, 0x0d, 0xb4,
-+			0x09, 0x90, 0x0c, 0xa2, 0x65, 0x0c, 0xad, 0x74,
-+			0xf5, 0xd7, 0xff, 0xda, 0xc1, 0xce, 0x85, 0xbe,
-+			0x00, 0xa7, 0xff, 0x4d, 0x2f, 0x65, 0xd3, 0x8c,
-+			0x86, 0x2d, 0x05, 0xe8, 0xed, 0x3e, 0x6b, 0x8b,
-+			0x0f, 0x3d, 0x83, 0x8c, 0xf1, 0x1d, 0x5b, 0x96,
-+			0x2e, 0xb1, 0x9c, 0xc2, 0x98, 0xe1, 0x70, 0xb9,
-+			0xba, 0x5c, 0x8a, 0x43, 0xd6, 0x34, 0xa7, 0x2d,
-+			0xc9, 0x92, 0xae, 0xf2, 0xa5, 0x7b, 0x05, 0x49,
-+			0xa7, 0x33, 0x34, 0x86, 0xca, 0xe4, 0x96, 0x23,
-+			0x76, 0x5b, 0xf2, 0xc6, 0xf1, 0x51, 0x28, 0x42,
-+			0x7b, 0xcc, 0x76, 0x8f, 0xfa, 0xa2, 0xad, 0x31,
-+			0xd4, 0xd6, 0x7a, 0x6d, 0x25, 0x25, 0x54, 0xe4,
-+			0x3f, 0x50, 0x59, 0xe1, 0x5c, 0x05, 0xb7, 0x27,
-+			0x48, 0xbf, 0x07, 0xec, 0x1b, 0x13, 0xbe, 0x2b,
-+			0xa1, 0x57, 0x2b, 0xd5, 0xab, 0xd7, 0xd0, 0x4c,
-+			0x1e, 0xcb, 0x71, 0x9b, 0xc5, 0x90, 0x85, 0xd3,
-+			0xde, 0x59, 0xec, 0x71, 0xeb, 0x89, 0xbb, 0xd0,
-+			0x09, 0x50, 0xe1, 0x16, 0x3f, 0xfd, 0x1c, 0x34,
-+			0xc3, 0x1c, 0xa1, 0x10, 0x77, 0x53, 0x98, 0xef,
-+			0xf2, 0xfd, 0xa5, 0x01, 0x59, 0xc2, 0x9b, 0x26,
-+			0xc7, 0x42, 0xd9, 0x49, 0xda, 0x58, 0x2b, 0x6e,
-+			0x9f, 0x53, 0x19, 0x76, 0x7e, 0xd9, 0xc9, 0x0e,
-+			0x68, 0xc8, 0x7f, 0x51, 0x22, 0x42, 0xef, 0x49,
-+			0xa4, 0x55, 0xb6, 0x36, 0xac, 0x09, 0xc7, 0x31,
-+			0x88, 0x15, 0x4b, 0x2e, 0x8f, 0x3a, 0x08, 0xf7,
-+			0xd8, 0xf7, 0xa8, 0xc5, 0xa9, 0x33, 0xa6, 0x45,
-+			0xe4, 0xc4, 0x94, 0x76, 0xf3, 0x0d, 0x8f, 0x7e,
-+			0xc8, 0xf6, 0xbc, 0x23, 0x0a, 0xb6, 0x4c, 0xd3,
-+			0x6a, 0xcd, 0x36, 0xc2, 0x90, 0x5c, 0x5c, 0x3c,
-+			0x65, 0x7b, 0xc2, 0xd6, 0xcc, 0xe6, 0x0d, 0x87,
-+			0x73, 0x2e, 0x71, 0x79, 0x16, 0x06, 0x63, 0x28,
-+			0x09, 0x15, 0xd8, 0x89, 0x38, 0x38, 0x3d, 0xb5,
-+			0x42, 0x1c, 0x08, 0x24, 0xf7, 0x2a, 0xd2, 0x9d,
-+			0xc8, 0xca, 0xef, 0xf9, 0x27, 0xd8, 0x07, 0x86,
-+			0xf7, 0x43, 0x0b, 0x55, 0x15, 0x3f, 0x9f, 0x83,
-+			0xef, 0xdc, 0x49, 0x9d, 0x2a, 0xc1, 0x54, 0x62,
-+			0xbd, 0x9b, 0x66, 0x55, 0x9f, 0xb7, 0x12, 0xf3,
-+			0x1b, 0x4d, 0x9d, 0x2a, 0x5c, 0xed, 0x87, 0x75,
-+			0x87, 0x26, 0xec, 0x61, 0x2c, 0xb4, 0x0f, 0x89,
-+			0xb0, 0xfb, 0x2e, 0x68, 0x5d, 0x15, 0xc7, 0x8d,
-+			0x2e, 0xc0, 0xd9, 0xec, 0xaf, 0x4f, 0xd2, 0x25,
-+			0x29, 0xe8, 0xd2, 0x26, 0x2b, 0x67, 0xe9, 0xfc,
-+			0x2b, 0xa8, 0x67, 0x96, 0x12, 0x1f, 0x5b, 0x96,
-+			0xc6, 0x14, 0x53, 0xaf, 0x44, 0xea, 0xd6, 0xe2,
-+			0x94, 0x98, 0xe4, 0x12, 0x93, 0x4c, 0x92, 0xe0,
-+			0x18, 0xa5, 0x8d, 0x2d, 0xe4, 0x71, 0x3c, 0x47,
-+			0x4c, 0xf7, 0xe6, 0x47, 0x9e, 0xc0, 0x68, 0xdf,
-+			0xd4, 0xf5, 0x5a, 0x74, 0xb1, 0x2b, 0x29, 0x03,
-+			0x19, 0x07, 0xaf, 0x90, 0x62, 0x5c, 0x68, 0x98,
-+			0x48, 0x16, 0x11, 0x02, 0x9d, 0xee, 0xb4, 0x9b,
-+			0xe5, 0x42, 0x7f, 0x08, 0xfd, 0x16, 0x32, 0x0b,
-+			0xd0, 0xb3, 0xfa, 0x2b, 0xb7, 0x99, 0xf9, 0x29,
-+			0xcd, 0x20, 0x45, 0x9f, 0xb3, 0x1a, 0x5d, 0xa2,
-+			0xaf, 0x4d, 0xe0, 0xbd, 0x42, 0x0d, 0xbc, 0x74,
-+			0x99, 0x9c, 0x8e, 0x53, 0x1a, 0xb4, 0x3e, 0xbd,
-+			0xa2, 0x9a, 0x2d, 0xf7, 0xf8, 0x39, 0x0f, 0x67,
-+			0x63, 0xfc, 0x6b, 0xc0, 0xaf, 0xb3, 0x4b, 0x4f,
-+			0x55, 0xc4, 0xcf, 0xa7, 0xc8, 0x04, 0x11, 0x3e,
-+			0x14, 0x32, 0xbb, 0x1b, 0x38, 0x77, 0xd6, 0x7f,
-+			0x54, 0x4c, 0xdf, 0x75, 0xf3, 0x07, 0x2d, 0x33,
-+			0x9b, 0xa8, 0x20, 0xe1, 0x7b, 0x12, 0xb5, 0xf3,
-+			0xef, 0x2f, 0xce, 0x72, 0xe5, 0x24, 0x60, 0xc1,
-+			0x30, 0xe2, 0xab, 0xa1, 0x8e, 0x11, 0x09, 0xa8,
-+			0x21, 0x33, 0x44, 0xfe, 0x7f, 0x35, 0x32, 0x93,
-+			0x39, 0xa7, 0xad, 0x8b, 0x79, 0x06, 0xb2, 0xcb,
-+			0x4e, 0xa9, 0x5f, 0xc7, 0xba, 0x74, 0x29, 0xec,
-+			0x93, 0xa0, 0x4e, 0x54, 0x93, 0xc0, 0xbc, 0x55,
-+			0x64, 0xf0, 0x48, 0xe5, 0x57, 0x99, 0xee, 0x75,
-+			0xd6, 0x79, 0x0f, 0x66, 0xb7, 0xc6, 0x57, 0x76,
-+			0xf7, 0xb7, 0xf3, 0x9c, 0xc5, 0x60, 0xe8, 0x7f,
-+			0x83, 0x76, 0xd6, 0x0e, 0xaa, 0xe6, 0x90, 0x39,
-+			0x1d, 0xa6, 0x32, 0x6a, 0x34, 0xe3, 0x55, 0xf8,
-+			0x58, 0xa0, 0x58, 0x7d, 0x33, 0xe0, 0x22, 0x39,
-+			0x44, 0x64, 0x87, 0x86, 0x5a, 0x2f, 0xa7, 0x7e,
-+			0x0f, 0x38, 0xea, 0xb0, 0x30, 0xcc, 0x61, 0xa5,
-+			0x6a, 0x32, 0xae, 0x1e, 0xf7, 0xe9, 0xd0, 0xa9,
-+			0x0c, 0x32, 0x4b, 0xb5, 0x49, 0x28, 0xab, 0x85,
-+			0x2f, 0x8e, 0x01, 0x36, 0x38, 0x52, 0xd0, 0xba,
-+			0xd6, 0x02, 0x78, 0xf8, 0x0e, 0x3e, 0x9c, 0x8b,
-+			0x6b, 0x45, 0x99, 0x3f, 0x5c, 0xfe, 0x58, 0xf1,
-+			0x5c, 0x94, 0x04, 0xe1, 0xf5, 0x18, 0x6d, 0x51,
-+			0xb2, 0x5d, 0x18, 0x20, 0xb6, 0xc2, 0x9a, 0x42,
-+			0x1d, 0xb3, 0xab, 0x3c, 0xb6, 0x3a, 0x13, 0x03,
-+			0xb2, 0x46, 0x82, 0x4f, 0xfc, 0x64, 0xbc, 0x4f,
-+			0xca, 0xfa, 0x9c, 0xc0, 0xd5, 0xa7, 0xbd, 0x11,
-+			0xb7, 0xe4, 0x5a, 0xf6, 0x6f, 0x4d, 0x4d, 0x54,
-+			0xea, 0xa4, 0x98, 0x66, 0xd4, 0x22, 0x3b, 0xd3,
-+			0x8f, 0x34, 0x47, 0xd9, 0x7c, 0xf4, 0x72, 0x3b,
-+			0x4d, 0x02, 0x77, 0xf6, 0xd6, 0xdd, 0x08, 0x0a,
-+			0x81, 0xe1, 0x86, 0x89, 0x3e, 0x56, 0x10, 0x3c,
-+			0xba, 0xd7, 0x81, 0x8c, 0x08, 0xbc, 0x8b, 0xe2,
-+			0x53, 0xec, 0xa7, 0x89, 0xee, 0xc8, 0x56, 0xb5,
-+			0x36, 0x2c, 0xb2, 0x03, 0xba, 0x99, 0xdd, 0x7c,
-+			0x48, 0xa0, 0xb0, 0xbc, 0x91, 0x33, 0xe9, 0xa8,
-+			0xcb, 0xcd, 0xcf, 0x59, 0x5f, 0x1f, 0x15, 0xe2,
-+			0x56, 0xf5, 0x4e, 0x01, 0x35, 0x27, 0x45, 0x77,
-+			0x47, 0xc8, 0xbc, 0xcb, 0x7e, 0x39, 0xc1, 0x97,
-+			0x28, 0xd3, 0x84, 0xfc, 0x2c, 0x3e, 0xc8, 0xad,
-+			0x9c, 0xf8, 0x8a, 0x61, 0x9c, 0x28, 0xaa, 0xc5,
-+			0x99, 0x20, 0x43, 0x85, 0x9d, 0xa5, 0xe2, 0x8b,
-+			0xb8, 0xae, 0xeb, 0xd0, 0x32, 0x0d, 0x52, 0x78,
-+			0x09, 0x56, 0x3f, 0xc7, 0xd8, 0x7e, 0x26, 0xfc,
-+			0x37, 0xfb, 0x6f, 0x04, 0xfc, 0xfa, 0x92, 0x10,
-+			0xac, 0xf8, 0x3e, 0x21, 0xdc, 0x8c, 0x21, 0x16,
-+			0x7d, 0x67, 0x6e, 0xf6, 0xcd, 0xda, 0xb6, 0x98,
-+			0x23, 0xab, 0x23, 0x3c, 0xb2, 0x10, 0xa0, 0x53,
-+			0x5a, 0x56, 0x9f, 0xc5, 0xd0, 0xff, 0xbb, 0xe4,
-+			0x98, 0x3c, 0x69, 0x1e, 0xdb, 0x38, 0x8f, 0x7e,
-+			0x0f, 0xd2, 0x98, 0x88, 0x81, 0x8b, 0x45, 0x67,
-+			0xea, 0x33, 0xf1, 0xeb, 0xe9, 0x97, 0x55, 0x2e,
-+			0xd9, 0xaa, 0xeb, 0x5a, 0xec, 0xda, 0xe1, 0x68,
-+			0xa8, 0x9d, 0x3c, 0x84, 0x7c, 0x05, 0x3d, 0x62,
-+			0x87, 0x8f, 0x03, 0x21, 0x28, 0x95, 0x0c, 0x89,
-+			0x25, 0x22, 0x4a, 0xb0, 0x93, 0xa9, 0x50, 0xa2,
-+			0x2f, 0x57, 0x6e, 0x18, 0x42, 0x19, 0x54, 0x0c,
-+			0x55, 0x67, 0xc6, 0x11, 0x49, 0xf4, 0x5c, 0xd2,
-+			0xe9, 0x3d, 0xdd, 0x8b, 0x48, 0x71, 0x21, 0x00,
-+			0xc3, 0x9a, 0x6c, 0x85, 0x74, 0x28, 0x83, 0x4a,
-+			0x1b, 0x31, 0x05, 0xe1, 0x06, 0x92, 0xe7, 0xda,
-+			0x85, 0x73, 0x78, 0x45, 0x20, 0x7f, 0xae, 0x13,
-+			0x7c, 0x33, 0x06, 0x22, 0xf4, 0x83, 0xf9, 0x35,
-+			0x3f, 0x6c, 0x71, 0xa8, 0x4e, 0x48, 0xbe, 0x9b,
-+			0xce, 0x8a, 0xba, 0xda, 0xbe, 0x28, 0x08, 0xf7,
-+			0xe2, 0x14, 0x8c, 0x71, 0xea, 0x72, 0xf9, 0x33,
-+			0xf2, 0x88, 0x3f, 0xd7, 0xbb, 0x69, 0x6c, 0x29,
-+			0x19, 0xdc, 0x84, 0xce, 0x1f, 0x12, 0x4f, 0xc8,
-+			0xaf, 0xa5, 0x04, 0xba, 0x5a, 0xab, 0xb0, 0xd9,
-+			0x14, 0x1f, 0x6c, 0x68, 0x98, 0x39, 0x89, 0x7a,
-+			0xd9, 0xd8, 0x2f, 0xdf, 0xa8, 0x47, 0x4a, 0x25,
-+			0xe2, 0xfb, 0x33, 0xf4, 0x59, 0x78, 0xe1, 0x68,
-+			0x85, 0xcf, 0xfe, 0x59, 0x20, 0xd4, 0x05, 0x1d,
-+			0x80, 0x99, 0xae, 0xbc, 0xca, 0xae, 0x0f, 0x2f,
-+			0x65, 0x43, 0x34, 0x8e, 0x7e, 0xac, 0xd3, 0x93,
-+			0x2f, 0xac, 0x6d, 0x14, 0x3d, 0x02, 0x07, 0x70,
-+			0x9d, 0xa4, 0xf3, 0x1b, 0x5c, 0x36, 0xfc, 0x01,
-+			0x73, 0x34, 0x85, 0x0c, 0x6c, 0xd6, 0xf1, 0xbd,
-+			0x3f, 0xdf, 0xee, 0xf5, 0xd9, 0xba, 0x56, 0xef,
-+			0xf4, 0x9b, 0x6b, 0xee, 0x9f, 0x5a, 0x78, 0x6d,
-+			0x32, 0x19, 0xf4, 0xf7, 0xf8, 0x4c, 0x69, 0x0b,
-+			0x4b, 0xbc, 0xbb, 0xb7, 0xf2, 0x85, 0xaf, 0x70,
-+			0x75, 0x24, 0x6c, 0x54, 0xa7, 0x0e, 0x4d, 0x1d,
-+			0x01, 0xbf, 0x08, 0xac, 0xcf, 0x7f, 0x2c, 0xe3,
-+			0x14, 0x89, 0x5e, 0x70, 0x5a, 0x99, 0x92, 0xcd,
-+			0x01, 0x84, 0xc8, 0xd2, 0xab, 0xe5, 0x4f, 0x58,
-+			0xe7, 0x0f, 0x2f, 0x0e, 0xff, 0x68, 0xea, 0xfd,
-+			0x15, 0xb3, 0x17, 0xe6, 0xb0, 0xe7, 0x85, 0xd8,
-+			0x23, 0x2e, 0x05, 0xc7, 0xc9, 0xc4, 0x46, 0x1f,
-+			0xe1, 0x9e, 0x49, 0x20, 0x23, 0x24, 0x4d, 0x7e,
-+			0x29, 0x65, 0xff, 0xf4, 0xb6, 0xfd, 0x1a, 0x85,
-+			0xc4, 0x16, 0xec, 0xfc, 0xea, 0x7b, 0xd6, 0x2c,
-+			0x43, 0xf8, 0xb7, 0xbf, 0x79, 0xc0, 0x85, 0xcd,
-+			0xef, 0xe1, 0x98, 0xd3, 0xa5, 0xf7, 0x90, 0x8c,
-+			0xe9, 0x7f, 0x80, 0x6b, 0xd2, 0xac, 0x4c, 0x30,
-+			0xa7, 0xc6, 0x61, 0x6c, 0xd2, 0xf9, 0x2c, 0xff,
-+			0x30, 0xbc, 0x22, 0x81, 0x7d, 0x93, 0x12, 0xe4,
-+			0x0a, 0xcd, 0xaf, 0xdd, 0xe8, 0xab, 0x0a, 0x1e,
-+			0x13, 0xa4, 0x27, 0xc3, 0x5f, 0xf7, 0x4b, 0xbb,
-+			0x37, 0x09, 0x4b, 0x91, 0x6f, 0x92, 0x4f, 0xaf,
-+			0x52, 0xee, 0xdf, 0xef, 0x09, 0x6f, 0xf7, 0x5c,
-+			0x6e, 0x12, 0x17, 0x72, 0x63, 0x57, 0xc7, 0xba,
-+			0x3b, 0x6b, 0x38, 0x32, 0x73, 0x1b, 0x9c, 0x80,
-+			0xc1, 0x7a, 0xc6, 0xcf, 0xcd, 0x35, 0xc0, 0x6b,
-+			0x31, 0x1a, 0x6b, 0xe9, 0xd8, 0x2c, 0x29, 0x3f,
-+			0x96, 0xfb, 0xb6, 0xcd, 0x13, 0x91, 0x3b, 0xc2,
-+			0xd2, 0xa3, 0x31, 0x8d, 0xa4, 0xcd, 0x57, 0xcd,
-+			0x13, 0x3d, 0x64, 0xfd, 0x06, 0xce, 0xe6, 0xdc,
-+			0x0c, 0x24, 0x43, 0x31, 0x40, 0x57, 0xf1, 0x72,
-+			0x17, 0xe3, 0x3a, 0x63, 0x6d, 0x35, 0xcf, 0x5d,
-+			0x97, 0x40, 0x59, 0xdd, 0xf7, 0x3c, 0x02, 0xf7,
-+			0x1c, 0x7e, 0x05, 0xbb, 0xa9, 0x0d, 0x01, 0xb1,
-+			0x8e, 0xc0, 0x30, 0xa9, 0x53, 0x24, 0xc9, 0x89,
-+			0x84, 0x6d, 0xaa, 0xd0, 0xcd, 0x91, 0xc2, 0x4d,
-+			0x91, 0xb0, 0x89, 0xe2, 0xbf, 0x83, 0x44, 0xaa,
-+			0x28, 0x72, 0x23, 0xa0, 0xc2, 0xad, 0xad, 0x1c,
-+			0xfc, 0x3f, 0x09, 0x7a, 0x0b, 0xdc, 0xc5, 0x1b,
-+			0x87, 0x13, 0xc6, 0x5b, 0x59, 0x8d, 0xf2, 0xc8,
-+			0xaf, 0xdf, 0x11, 0x95,
-+		},
-+		.rlen = 4100,
-+	},
++struct driver_private {
++	struct kobject kobj;
++	struct klist klist_devices;
++	struct klist_node knode_bus;
++	struct module_kobject *mkobj;
++	struct device_driver *driver;
 +};
++#define to_driver(obj) container_of(obj, struct driver_private, kobj)
+ 
++/* initialisation functions */
+ extern int devices_init(void);
+ extern int buses_init(void);
+ extern int classes_init(void);
+@@ -13,17 +49,16 @@ static inline int hypervisor_init(void) { return 0; }
+ extern int platform_bus_init(void);
+ extern int system_bus_init(void);
+ extern int cpu_dev_init(void);
+-extern int attribute_container_init(void);
+ 
+-extern int bus_add_device(struct device * dev);
+-extern void bus_attach_device(struct device * dev);
+-extern void bus_remove_device(struct device * dev);
++extern int bus_add_device(struct device *dev);
++extern void bus_attach_device(struct device *dev);
++extern void bus_remove_device(struct device *dev);
+ 
+-extern int bus_add_driver(struct device_driver *);
+-extern void bus_remove_driver(struct device_driver *);
++extern int bus_add_driver(struct device_driver *drv);
++extern void bus_remove_driver(struct device_driver *drv);
+ 
+-extern void driver_detach(struct device_driver * drv);
+-extern int driver_probe_device(struct device_driver *, struct device *);
++extern void driver_detach(struct device_driver *drv);
++extern int driver_probe_device(struct device_driver *drv, struct device *dev);
+ 
+ extern void sysdev_shutdown(void);
+ extern int sysdev_suspend(pm_message_t state);
+@@ -44,4 +79,13 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
+ 
+ extern int devres_release_all(struct device *dev);
+ 
+-extern struct kset devices_subsys;
++extern struct kset *devices_kset;
 +
++#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
++extern void module_add_driver(struct module *mod, struct device_driver *drv);
++extern void module_remove_driver(struct device_driver *drv);
++#else
++static inline void module_add_driver(struct module *mod,
++				     struct device_driver *drv) { }
++static inline void module_remove_driver(struct device_driver *drv) { }
++#endif
+diff --git a/drivers/base/bus.c b/drivers/base/bus.c
+index 9a19b07..055989e 100644
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -3,6 +3,8 @@
+  *
+  * Copyright (c) 2002-3 Patrick Mochel
+  * Copyright (c) 2002-3 Open Source Development Labs
++ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
++ * Copyright (c) 2007 Novell Inc.
+  *
+  * This file is released under the GPLv2
+  *
+@@ -17,14 +19,13 @@
+ #include "power/power.h"
+ 
+ #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
+-#define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj)
++#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj)
+ 
  /*
-  * Compression stuff.
+  * sysfs bindings for drivers
+  */
+ 
+ #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
+-#define to_driver(obj) container_of(obj, struct device_driver, kobj)
+ 
+ 
+ static int __must_check bus_rescan_devices_helper(struct device *dev,
+@@ -32,37 +33,40 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
+ 
+ static struct bus_type *bus_get(struct bus_type *bus)
+ {
+-	return bus ? container_of(kset_get(&bus->subsys),
+-				struct bus_type, subsys) : NULL;
++	if (bus) {
++		kset_get(&bus->p->subsys);
++		return bus;
++	}
++	return NULL;
+ }
+ 
+ static void bus_put(struct bus_type *bus)
+ {
+-	kset_put(&bus->subsys);
++	if (bus)
++		kset_put(&bus->p->subsys);
+ }
+ 
+-static ssize_t
+-drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
++static ssize_t drv_attr_show(struct kobject *kobj, struct attribute *attr,
++			     char *buf)
+ {
+-	struct driver_attribute * drv_attr = to_drv_attr(attr);
+-	struct device_driver * drv = to_driver(kobj);
++	struct driver_attribute *drv_attr = to_drv_attr(attr);
++	struct driver_private *drv_priv = to_driver(kobj);
+ 	ssize_t ret = -EIO;
+ 
+ 	if (drv_attr->show)
+-		ret = drv_attr->show(drv, buf);
++		ret = drv_attr->show(drv_priv->driver, buf);
+ 	return ret;
+ }
+ 
+-static ssize_t
+-drv_attr_store(struct kobject * kobj, struct attribute * attr,
+-	       const char * buf, size_t count)
++static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr,
++			      const char *buf, size_t count)
+ {
+-	struct driver_attribute * drv_attr = to_drv_attr(attr);
+-	struct device_driver * drv = to_driver(kobj);
++	struct driver_attribute *drv_attr = to_drv_attr(attr);
++	struct driver_private *drv_priv = to_driver(kobj);
+ 	ssize_t ret = -EIO;
+ 
+ 	if (drv_attr->store)
+-		ret = drv_attr->store(drv, buf, count);
++		ret = drv_attr->store(drv_priv->driver, buf, count);
+ 	return ret;
+ }
+ 
+@@ -71,22 +75,12 @@ static struct sysfs_ops driver_sysfs_ops = {
+ 	.store	= drv_attr_store,
+ };
+ 
+-
+-static void driver_release(struct kobject * kobj)
++static void driver_release(struct kobject *kobj)
+ {
+-	/*
+-	 * Yes this is an empty release function, it is this way because struct
+-	 * device is always a static object, not a dynamic one.  Yes, this is
+-	 * not nice and bad, but remember, drivers are code, reference counted
+-	 * by the module count, not a device, which is really data.  And yes,
+-	 * in the future I do want to have all drivers be created dynamically,
+-	 * and am working toward that goal, but it will take a bit longer...
+-	 *
+-	 * But do not let this example give _anyone_ the idea that they can
+-	 * create a release function without any code in it at all, to do that
+-	 * is almost always wrong.  If you have any questions about this,
+-	 * please send an email to <greg at kroah.com>
+-	 */
++	struct driver_private *drv_priv = to_driver(kobj);
++
++	pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__);
++	kfree(drv_priv);
+ }
+ 
+ static struct kobj_type driver_ktype = {
+@@ -94,34 +88,30 @@ static struct kobj_type driver_ktype = {
+ 	.release	= driver_release,
+ };
+ 
+-
+ /*
+  * sysfs bindings for buses
+  */
+-
+-
+-static ssize_t
+-bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
++static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
++			     char *buf)
+ {
+-	struct bus_attribute * bus_attr = to_bus_attr(attr);
+-	struct bus_type * bus = to_bus(kobj);
++	struct bus_attribute *bus_attr = to_bus_attr(attr);
++	struct bus_type_private *bus_priv = to_bus(kobj);
+ 	ssize_t ret = 0;
+ 
+ 	if (bus_attr->show)
+-		ret = bus_attr->show(bus, buf);
++		ret = bus_attr->show(bus_priv->bus, buf);
+ 	return ret;
+ }
+ 
+-static ssize_t
+-bus_attr_store(struct kobject * kobj, struct attribute * attr,
+-	       const char * buf, size_t count)
++static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
++			      const char *buf, size_t count)
+ {
+-	struct bus_attribute * bus_attr = to_bus_attr(attr);
+-	struct bus_type * bus = to_bus(kobj);
++	struct bus_attribute *bus_attr = to_bus_attr(attr);
++	struct bus_type_private *bus_priv = to_bus(kobj);
+ 	ssize_t ret = 0;
+ 
+ 	if (bus_attr->store)
+-		ret = bus_attr->store(bus, buf, count);
++		ret = bus_attr->store(bus_priv->bus, buf, count);
+ 	return ret;
+ }
+ 
+@@ -130,24 +120,26 @@ static struct sysfs_ops bus_sysfs_ops = {
+ 	.store	= bus_attr_store,
+ };
+ 
+-int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
++int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
+ {
+ 	int error;
+ 	if (bus_get(bus)) {
+-		error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
++		error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
+ 		bus_put(bus);
+ 	} else
+ 		error = -EINVAL;
+ 	return error;
+ }
++EXPORT_SYMBOL_GPL(bus_create_file);
+ 
+-void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
++void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
+ {
+ 	if (bus_get(bus)) {
+-		sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
++		sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr);
+ 		bus_put(bus);
+ 	}
+ }
++EXPORT_SYMBOL_GPL(bus_remove_file);
+ 
+ static struct kobj_type bus_ktype = {
+ 	.sysfs_ops	= &bus_sysfs_ops,
+@@ -166,20 +158,11 @@ static struct kset_uevent_ops bus_uevent_ops = {
+ 	.filter = bus_uevent_filter,
+ };
+ 
+-static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
++static struct kset *bus_kset;
+ 
+ 
+ #ifdef CONFIG_HOTPLUG
+ /* Manually detach a device from its associated driver. */
+-static int driver_helper(struct device *dev, void *data)
+-{
+-	const char *name = data;
+-
+-	if (strcmp(name, dev->bus_id) == 0)
+-		return 1;
+-	return 0;
+-}
+-
+ static ssize_t driver_unbind(struct device_driver *drv,
+ 			     const char *buf, size_t count)
+ {
+@@ -187,7 +170,7 @@ static ssize_t driver_unbind(struct device_driver *drv,
+ 	struct device *dev;
+ 	int err = -ENODEV;
+ 
+-	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
++	dev = bus_find_device_by_name(bus, NULL, buf);
+ 	if (dev && dev->driver == drv) {
+ 		if (dev->parent)	/* Needed for USB */
+ 			down(&dev->parent->sem);
+@@ -214,7 +197,7 @@ static ssize_t driver_bind(struct device_driver *drv,
+ 	struct device *dev;
+ 	int err = -ENODEV;
+ 
+-	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
++	dev = bus_find_device_by_name(bus, NULL, buf);
+ 	if (dev && dev->driver == NULL) {
+ 		if (dev->parent)	/* Needed for USB */
+ 			down(&dev->parent->sem);
+@@ -224,10 +207,13 @@ static ssize_t driver_bind(struct device_driver *drv,
+ 		if (dev->parent)
+ 			up(&dev->parent->sem);
+ 
+-		if (err > 0) 		/* success */
++		if (err > 0) {
++			/* success */
+ 			err = count;
+-		else if (err == 0)	/* driver didn't accept device */
++		} else if (err == 0) {
++			/* driver didn't accept device */
+ 			err = -ENODEV;
++		}
+ 	}
+ 	put_device(dev);
+ 	bus_put(bus);
+@@ -237,16 +223,16 @@ static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+ 
+ static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
+ {
+-	return sprintf(buf, "%d\n", bus->drivers_autoprobe);
++	return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
+ }
+ 
+ static ssize_t store_drivers_autoprobe(struct bus_type *bus,
+ 				       const char *buf, size_t count)
+ {
+ 	if (buf[0] == '0')
+-		bus->drivers_autoprobe = 0;
++		bus->p->drivers_autoprobe = 0;
+ 	else
+-		bus->drivers_autoprobe = 1;
++		bus->p->drivers_autoprobe = 1;
+ 	return count;
+ }
+ 
+@@ -255,7 +241,7 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
+ {
+ 	struct device *dev;
+ 
+-	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
++	dev = bus_find_device_by_name(bus, NULL, buf);
+ 	if (!dev)
+ 		return -ENODEV;
+ 	if (bus_rescan_devices_helper(dev, NULL) != 0)
+@@ -264,49 +250,49 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
+ }
+ #endif
+ 
+-static struct device * next_device(struct klist_iter * i)
++static struct device *next_device(struct klist_iter *i)
+ {
+-	struct klist_node * n = klist_next(i);
++	struct klist_node *n = klist_next(i);
+ 	return n ? container_of(n, struct device, knode_bus) : NULL;
+ }
+ 
+ /**
+- *	bus_for_each_dev - device iterator.
+- *	@bus:	bus type.
+- *	@start:	device to start iterating from.
+- *	@data:	data for the callback.
+- *	@fn:	function to be called for each device.
++ * bus_for_each_dev - device iterator.
++ * @bus: bus type.
++ * @start: device to start iterating from.
++ * @data: data for the callback.
++ * @fn: function to be called for each device.
+  *
+- *	Iterate over @bus's list of devices, and call @fn for each,
+- *	passing it @data. If @start is not NULL, we use that device to
+- *	begin iterating from.
++ * Iterate over @bus's list of devices, and call @fn for each,
++ * passing it @data. If @start is not NULL, we use that device to
++ * begin iterating from.
+  *
+- *	We check the return of @fn each time. If it returns anything
+- *	other than 0, we break out and return that value.
++ * We check the return of @fn each time. If it returns anything
++ * other than 0, we break out and return that value.
+  *
+- *	NOTE: The device that returns a non-zero value is not retained
+- *	in any way, nor is its refcount incremented. If the caller needs
+- *	to retain this data, it should do, and increment the reference
+- *	count in the supplied callback.
++ * NOTE: The device that returns a non-zero value is not retained
++ * in any way, nor is its refcount incremented. If the caller needs
++ * to retain this data, it should do, and increment the reference
++ * count in the supplied callback.
+  */
+-
+-int bus_for_each_dev(struct bus_type * bus, struct device * start,
+-		     void * data, int (*fn)(struct device *, void *))
++int bus_for_each_dev(struct bus_type *bus, struct device *start,
++		     void *data, int (*fn)(struct device *, void *))
+ {
+ 	struct klist_iter i;
+-	struct device * dev;
++	struct device *dev;
+ 	int error = 0;
+ 
+ 	if (!bus)
+ 		return -EINVAL;
+ 
+-	klist_iter_init_node(&bus->klist_devices, &i,
++	klist_iter_init_node(&bus->p->klist_devices, &i,
+ 			     (start ? &start->knode_bus : NULL));
+ 	while ((dev = next_device(&i)) && !error)
+ 		error = fn(dev, data);
+ 	klist_iter_exit(&i);
+ 	return error;
+ }
++EXPORT_SYMBOL_GPL(bus_for_each_dev);
+ 
+ /**
+  * bus_find_device - device iterator for locating a particular device.
+@@ -323,9 +309,9 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
+  * if it does.  If the callback returns non-zero, this function will
+  * return to the caller and not iterate over any more devices.
+  */
+-struct device * bus_find_device(struct bus_type *bus,
+-				struct device *start, void *data,
+-				int (*match)(struct device *, void *))
++struct device *bus_find_device(struct bus_type *bus,
++			       struct device *start, void *data,
++			       int (*match)(struct device *dev, void *data))
+ {
+ 	struct klist_iter i;
+ 	struct device *dev;
+@@ -333,7 +319,7 @@ struct device * bus_find_device(struct bus_type *bus,
+ 	if (!bus)
+ 		return NULL;
+ 
+-	klist_iter_init_node(&bus->klist_devices, &i,
++	klist_iter_init_node(&bus->p->klist_devices, &i,
+ 			     (start ? &start->knode_bus : NULL));
+ 	while ((dev = next_device(&i)))
+ 		if (match(dev, data) && get_device(dev))
+@@ -341,51 +327,83 @@ struct device * bus_find_device(struct bus_type *bus,
+ 	klist_iter_exit(&i);
+ 	return dev;
+ }
++EXPORT_SYMBOL_GPL(bus_find_device);
++
++static int match_name(struct device *dev, void *data)
++{
++	const char *name = data;
+ 
++	if (strcmp(name, dev->bus_id) == 0)
++		return 1;
++	return 0;
++}
+ 
+-static struct device_driver * next_driver(struct klist_iter * i)
++/**
++ * bus_find_device_by_name - device iterator for locating a particular device of a specific name
++ * @bus: bus type
++ * @start: Device to begin with
++ * @name: name of the device to match
++ *
++ * This is similar to the bus_find_device() function above, but it handles
++ * searching by a name automatically, no need to write another strcmp matching
++ * function.
++ */
++struct device *bus_find_device_by_name(struct bus_type *bus,
++				       struct device *start, const char *name)
+ {
+-	struct klist_node * n = klist_next(i);
+-	return n ? container_of(n, struct device_driver, knode_bus) : NULL;
++	return bus_find_device(bus, start, (void *)name, match_name);
++}
++EXPORT_SYMBOL_GPL(bus_find_device_by_name);
++
++static struct device_driver *next_driver(struct klist_iter *i)
++{
++	struct klist_node *n = klist_next(i);
++	struct driver_private *drv_priv;
++
++	if (n) {
++		drv_priv = container_of(n, struct driver_private, knode_bus);
++		return drv_priv->driver;
++	}
++	return NULL;
+ }
+ 
+ /**
+- *	bus_for_each_drv - driver iterator
+- *	@bus:	bus we're dealing with.
+- *	@start:	driver to start iterating on.
+- *	@data:	data to pass to the callback.
+- *	@fn:	function to call for each driver.
++ * bus_for_each_drv - driver iterator
++ * @bus: bus we're dealing with.
++ * @start: driver to start iterating on.
++ * @data: data to pass to the callback.
++ * @fn: function to call for each driver.
+  *
+- *	This is nearly identical to the device iterator above.
+- *	We iterate over each driver that belongs to @bus, and call
+- *	@fn for each. If @fn returns anything but 0, we break out
+- *	and return it. If @start is not NULL, we use it as the head
+- *	of the list.
++ * This is nearly identical to the device iterator above.
++ * We iterate over each driver that belongs to @bus, and call
++ * @fn for each. If @fn returns anything but 0, we break out
++ * and return it. If @start is not NULL, we use it as the head
++ * of the list.
+  *
+- *	NOTE: we don't return the driver that returns a non-zero
+- *	value, nor do we leave the reference count incremented for that
+- *	driver. If the caller needs to know that info, it must set it
+- *	in the callback. It must also be sure to increment the refcount
+- *	so it doesn't disappear before returning to the caller.
++ * NOTE: we don't return the driver that returns a non-zero
++ * value, nor do we leave the reference count incremented for that
++ * driver. If the caller needs to know that info, it must set it
++ * in the callback. It must also be sure to increment the refcount
++ * so it doesn't disappear before returning to the caller.
+  */
+-
+-int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
+-		     void * data, int (*fn)(struct device_driver *, void *))
++int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
++		     void *data, int (*fn)(struct device_driver *, void *))
+ {
+ 	struct klist_iter i;
+-	struct device_driver * drv;
++	struct device_driver *drv;
+ 	int error = 0;
+ 
+ 	if (!bus)
+ 		return -EINVAL;
+ 
+-	klist_iter_init_node(&bus->klist_drivers, &i,
+-			     start ? &start->knode_bus : NULL);
++	klist_iter_init_node(&bus->p->klist_drivers, &i,
++			     start ? &start->p->knode_bus : NULL);
+ 	while ((drv = next_driver(&i)) && !error)
+ 		error = fn(drv, data);
+ 	klist_iter_exit(&i);
+ 	return error;
+ }
++EXPORT_SYMBOL_GPL(bus_for_each_drv);
+ 
+ static int device_add_attrs(struct bus_type *bus, struct device *dev)
+ {
+@@ -396,7 +414,7 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
+ 		return 0;
+ 
+ 	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
+-		error = device_create_file(dev,&bus->dev_attrs[i]);
++		error = device_create_file(dev, &bus->dev_attrs[i]);
+ 		if (error) {
+ 			while (--i >= 0)
+ 				device_remove_file(dev, &bus->dev_attrs[i]);
+@@ -406,13 +424,13 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
+ 	return error;
+ }
+ 
+-static void device_remove_attrs(struct bus_type * bus, struct device * dev)
++static void device_remove_attrs(struct bus_type *bus, struct device *dev)
+ {
+ 	int i;
+ 
+ 	if (bus->dev_attrs) {
+ 		for (i = 0; attr_name(bus->dev_attrs[i]); i++)
+-			device_remove_file(dev,&bus->dev_attrs[i]);
++			device_remove_file(dev, &bus->dev_attrs[i]);
+ 	}
+ }
+ 
+@@ -420,7 +438,7 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev)
+ static int make_deprecated_bus_links(struct device *dev)
+ {
+ 	return sysfs_create_link(&dev->kobj,
+-				 &dev->bus->subsys.kobj, "bus");
++				 &dev->bus->p->subsys.kobj, "bus");
+ }
+ 
+ static void remove_deprecated_bus_links(struct device *dev)
+@@ -433,28 +451,28 @@ static inline void remove_deprecated_bus_links(struct device *dev) { }
+ #endif
+ 
+ /**
+- *	bus_add_device - add device to bus
+- *	@dev:	device being added
++ * bus_add_device - add device to bus
++ * @dev: device being added
+  *
+- *	- Add the device to its bus's list of devices.
+- *	- Create link to device's bus.
++ * - Add the device to its bus's list of devices.
++ * - Create link to device's bus.
+  */
+-int bus_add_device(struct device * dev)
++int bus_add_device(struct device *dev)
+ {
+-	struct bus_type * bus = bus_get(dev->bus);
++	struct bus_type *bus = bus_get(dev->bus);
+ 	int error = 0;
+ 
+ 	if (bus) {
+-		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
++		pr_debug("bus: '%s': add device %s\n", bus->name, dev->bus_id);
+ 		error = device_add_attrs(bus, dev);
+ 		if (error)
+ 			goto out_put;
+-		error = sysfs_create_link(&bus->devices.kobj,
++		error = sysfs_create_link(&bus->p->devices_kset->kobj,
+ 						&dev->kobj, dev->bus_id);
+ 		if (error)
+ 			goto out_id;
+ 		error = sysfs_create_link(&dev->kobj,
+-				&dev->bus->subsys.kobj, "subsystem");
++				&dev->bus->p->subsys.kobj, "subsystem");
+ 		if (error)
+ 			goto out_subsys;
+ 		error = make_deprecated_bus_links(dev);
+@@ -466,7 +484,7 @@ int bus_add_device(struct device * dev)
+ out_deprecated:
+ 	sysfs_remove_link(&dev->kobj, "subsystem");
+ out_subsys:
+-	sysfs_remove_link(&bus->devices.kobj, dev->bus_id);
++	sysfs_remove_link(&bus->p->devices_kset->kobj, dev->bus_id);
+ out_id:
+ 	device_remove_attrs(bus, dev);
+ out_put:
+@@ -475,56 +493,58 @@ out_put:
+ }
+ 
+ /**
+- *	bus_attach_device - add device to bus
+- *	@dev:	device tried to attach to a driver
++ * bus_attach_device - add device to bus
++ * @dev: device tried to attach to a driver
+  *
+- *	- Add device to bus's list of devices.
+- *	- Try to attach to driver.
++ * - Add device to bus's list of devices.
++ * - Try to attach to driver.
+  */
+-void bus_attach_device(struct device * dev)
++void bus_attach_device(struct device *dev)
+ {
+ 	struct bus_type *bus = dev->bus;
+ 	int ret = 0;
+ 
+ 	if (bus) {
+ 		dev->is_registered = 1;
+-		if (bus->drivers_autoprobe)
++		if (bus->p->drivers_autoprobe)
+ 			ret = device_attach(dev);
+ 		WARN_ON(ret < 0);
+ 		if (ret >= 0)
+-			klist_add_tail(&dev->knode_bus, &bus->klist_devices);
++			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
+ 		else
+ 			dev->is_registered = 0;
+ 	}
+ }
+ 
+ /**
+- *	bus_remove_device - remove device from bus
+- *	@dev:	device to be removed
++ * bus_remove_device - remove device from bus
++ * @dev: device to be removed
+  *
+- *	- Remove symlink from bus's directory.
+- *	- Delete device from bus's list.
+- *	- Detach from its driver.
+- *	- Drop reference taken in bus_add_device().
++ * - Remove symlink from bus's directory.
++ * - Delete device from bus's list.
++ * - Detach from its driver.
++ * - Drop reference taken in bus_add_device().
+  */
+-void bus_remove_device(struct device * dev)
++void bus_remove_device(struct device *dev)
+ {
+ 	if (dev->bus) {
+ 		sysfs_remove_link(&dev->kobj, "subsystem");
+ 		remove_deprecated_bus_links(dev);
+-		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
++		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
++				  dev->bus_id);
+ 		device_remove_attrs(dev->bus, dev);
+ 		if (dev->is_registered) {
+ 			dev->is_registered = 0;
+ 			klist_del(&dev->knode_bus);
+ 		}
+-		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
++		pr_debug("bus: '%s': remove device %s\n",
++			 dev->bus->name, dev->bus_id);
+ 		device_release_driver(dev);
+ 		bus_put(dev->bus);
+ 	}
+ }
+ 
+-static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
++static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
+ {
+ 	int error = 0;
+ 	int i;
+@@ -533,19 +553,19 @@ static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
+ 		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
+ 			error = driver_create_file(drv, &bus->drv_attrs[i]);
+ 			if (error)
+-				goto Err;
++				goto err;
+ 		}
+ 	}
+- Done:
++done:
+ 	return error;
+- Err:
++err:
+ 	while (--i >= 0)
+ 		driver_remove_file(drv, &bus->drv_attrs[i]);
+-	goto Done;
++	goto done;
+ }
+ 
+-
+-static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv)
++static void driver_remove_attrs(struct bus_type *bus,
++				struct device_driver *drv)
+ {
+ 	int i;
+ 
+@@ -616,39 +636,46 @@ static ssize_t driver_uevent_store(struct device_driver *drv,
+ 	enum kobject_action action;
+ 
+ 	if (kobject_action_type(buf, count, &action) == 0)
+-		kobject_uevent(&drv->kobj, action);
++		kobject_uevent(&drv->p->kobj, action);
+ 	return count;
+ }
+ static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
+ 
+ /**
+- *	bus_add_driver - Add a driver to the bus.
+- *	@drv:	driver.
+- *
++ * bus_add_driver - Add a driver to the bus.
++ * @drv: driver.
   */
-@@ -4408,6 +7721,88 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
- };
+ int bus_add_driver(struct device_driver *drv)
+ {
+-	struct bus_type * bus = bus_get(drv->bus);
++	struct bus_type *bus;
++	struct driver_private *priv;
+ 	int error = 0;
  
- /*
-+ * LZO test vectors (null-terminated strings).
-+ */
-+#define LZO_COMP_TEST_VECTORS 2
-+#define LZO_DECOMP_TEST_VECTORS 2
-+
-+static struct comp_testvec lzo_comp_tv_template[] = {
-+	{
-+		.inlen	= 70,
-+		.outlen	= 46,
-+		.input	= "Join us now and share the software "
-+			  "Join us now and share the software ",
-+		.output	= {  0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
-+			     0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
-+			     0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
-+			     0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
-+			     0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
-+			     0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
-+	}, {
-+		.inlen	= 159,
-+		.outlen	= 133,
-+		.input	= "This document describes a compression method based on the LZO "
-+			  "compression algorithm.  This document defines the application of "
-+			  "the LZO algorithm used in UBIFS.",
-+		.output	= { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
-+			    0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
-+			    0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
-+			    0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
-+			    0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
-+			    0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
-+			    0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
-+			    0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
-+			    0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
-+			    0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
-+			    0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
-+			    0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
-+			    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
-+			    0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
-+			    0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
-+			    0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
-+			    0x53, 0x2e, 0x11, 0x00, 0x00 },
-+	},
-+};
++	bus = bus_get(drv->bus);
+ 	if (!bus)
+ 		return -EINVAL;
+ 
+-	pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
+-	error = kobject_set_name(&drv->kobj, "%s", drv->name);
+-	if (error)
+-		goto out_put_bus;
+-	drv->kobj.kset = &bus->drivers;
+-	error = kobject_register(&drv->kobj);
++	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
 +
-+static struct comp_testvec lzo_decomp_tv_template[] = {
-+	{
-+		.inlen	= 133,
-+		.outlen	= 159,
-+		.input	= { 0x00, 0x2b, 0x54, 0x68, 0x69, 0x73, 0x20, 0x64,
-+			    0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20,
-+			    0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
-+			    0x73, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70,
-+			    0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20,
-+			    0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x20, 0x62,
-+			    0x61, 0x73, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x20,
-+			    0x74, 0x68, 0x65, 0x20, 0x4c, 0x5a, 0x4f, 0x2b,
-+			    0x8c, 0x00, 0x0d, 0x61, 0x6c, 0x67, 0x6f, 0x72,
-+			    0x69, 0x74, 0x68, 0x6d, 0x2e, 0x20, 0x20, 0x54,
-+			    0x68, 0x69, 0x73, 0x2a, 0x54, 0x01, 0x02, 0x66,
-+			    0x69, 0x6e, 0x65, 0x73, 0x94, 0x06, 0x05, 0x61,
-+			    0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x76,
-+			    0x0a, 0x6f, 0x66, 0x88, 0x02, 0x60, 0x09, 0x27,
-+			    0xf0, 0x00, 0x0c, 0x20, 0x75, 0x73, 0x65, 0x64,
-+			    0x20, 0x69, 0x6e, 0x20, 0x55, 0x42, 0x49, 0x46,
-+			    0x53, 0x2e, 0x11, 0x00, 0x00 },
-+		.output	= "This document describes a compression method based on the LZO "
-+			  "compression algorithm.  This document defines the application of "
-+			  "the LZO algorithm used in UBIFS.",
-+	}, {
-+		.inlen	= 46,
-+		.outlen	= 70,
-+		.input	= { 0x00, 0x0d, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x75,
-+			    0x73, 0x20, 0x6e, 0x6f, 0x77, 0x20, 0x61, 0x6e,
-+			    0x64, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x20,
-+			    0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x66, 0x74,
-+			    0x77, 0x70, 0x01, 0x01, 0x4a, 0x6f, 0x69, 0x6e,
-+			    0x3d, 0x88, 0x00, 0x11, 0x00, 0x00 },
-+		.output	= "Join us now and share the software "
-+			  "Join us now and share the software ",
-+	},
-+};
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
 +
-+/*
-  * Michael MIC test vectors from IEEE 802.11i
++	klist_init(&priv->klist_devices, NULL, NULL);
++	priv->driver = drv;
++	drv->p = priv;
++	priv->kobj.kset = bus->p->drivers_kset;
++	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
++				     "%s", drv->name);
+ 	if (error)
+ 		goto out_put_bus;
+ 
+-	if (drv->bus->drivers_autoprobe) {
++	if (drv->bus->p->drivers_autoprobe) {
+ 		error = driver_attach(drv);
+ 		if (error)
+ 			goto out_unregister;
+ 	}
+-	klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
++	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
+ 	module_add_driver(drv->owner, drv);
+ 
+ 	error = driver_create_file(drv, &driver_attr_uevent);
+@@ -669,24 +696,24 @@ int bus_add_driver(struct device_driver *drv)
+ 			__FUNCTION__, drv->name);
+ 	}
+ 
++	kobject_uevent(&priv->kobj, KOBJ_ADD);
+ 	return error;
+ out_unregister:
+-	kobject_unregister(&drv->kobj);
++	kobject_put(&priv->kobj);
+ out_put_bus:
+ 	bus_put(bus);
+ 	return error;
+ }
+ 
+ /**
+- *	bus_remove_driver - delete driver from bus's knowledge.
+- *	@drv:	driver.
++ * bus_remove_driver - delete driver from bus's knowledge.
++ * @drv: driver.
+  *
+- *	Detach the driver from the devices it controls, and remove
+- *	it from its bus's list of drivers. Finally, we drop the reference
+- *	to the bus we took in bus_add_driver().
++ * Detach the driver from the devices it controls, and remove
++ * it from its bus's list of drivers. Finally, we drop the reference
++ * to the bus we took in bus_add_driver().
   */
- #define MICHAEL_MIC_TEST_VECTORS 6
-@@ -4812,4 +8207,20 @@ static struct cipher_speed camellia_speed_template[] = {
-       {  .klen = 0, .blen = 0, }
- };
+-
+-void bus_remove_driver(struct device_driver * drv)
++void bus_remove_driver(struct device_driver *drv)
+ {
+ 	if (!drv->bus)
+ 		return;
+@@ -694,18 +721,17 @@ void bus_remove_driver(struct device_driver * drv)
+ 	remove_bind_files(drv);
+ 	driver_remove_attrs(drv->bus, drv);
+ 	driver_remove_file(drv, &driver_attr_uevent);
+-	klist_remove(&drv->knode_bus);
+-	pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
++	klist_remove(&drv->p->knode_bus);
++	pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
+ 	driver_detach(drv);
+ 	module_remove_driver(drv);
+-	kobject_unregister(&drv->kobj);
++	kobject_put(&drv->p->kobj);
+ 	bus_put(drv->bus);
+ }
  
-+static struct cipher_speed salsa20_speed_template[] = {
-+      { .klen = 16, .blen = 16, },
-+      { .klen = 16, .blen = 64, },
-+      { .klen = 16, .blen = 256, },
-+      { .klen = 16, .blen = 1024, },
-+      { .klen = 16, .blen = 8192, },
-+      { .klen = 32, .blen = 16, },
-+      { .klen = 32, .blen = 64, },
-+      { .klen = 32, .blen = 256, },
-+      { .klen = 32, .blen = 1024, },
-+      { .klen = 32, .blen = 8192, },
-+
-+      /* End marker */
-+      {  .klen = 0, .blen = 0, }
-+};
-+
- #endif	/* _CRYPTO_TCRYPT_H */
-diff --git a/crypto/twofish_common.c b/crypto/twofish_common.c
-index b4b9c0c..0af216c 100644
---- a/crypto/twofish_common.c
-+++ b/crypto/twofish_common.c
-@@ -655,84 +655,48 @@ int twofish_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int key_len)
- 			CALC_SB256_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
- 		}
+-
+ /* Helper for bus_rescan_devices's iter */
+ static int __must_check bus_rescan_devices_helper(struct device *dev,
+-						void *data)
++						  void *data)
+ {
+ 	int ret = 0;
  
--		/* Calculate whitening and round subkeys.  The constants are
--		 * indices of subkeys, preprocessed through q0 and q1. */
--		CALC_K256 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
--		CALC_K256 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
--		CALC_K256 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
--		CALC_K256 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
--		CALC_K256 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
--		CALC_K256 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
--		CALC_K256 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
--		CALC_K256 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
--		CALC_K256 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
--		CALC_K256 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
--		CALC_K256 (k, 12, 0x18, 0x37, 0xF7, 0x71);
--		CALC_K256 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
--		CALC_K256 (k, 16, 0x43, 0x30, 0x75, 0x0F);
--		CALC_K256 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
--		CALC_K256 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
--		CALC_K256 (k, 22, 0x94, 0x06, 0x48, 0x3F);
--		CALC_K256 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
--		CALC_K256 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
--		CALC_K256 (k, 28, 0x84, 0x8A, 0x54, 0x00);
--		CALC_K256 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
-+		/* CALC_K256/CALC_K192/CALC_K loops were unrolled.
-+		 * Unrolling produced x2.5 more code (+18k on i386),
-+		 * and speeded up key setup by 7%:
-+		 * unrolled: twofish_setkey/sec: 41128
-+		 *     loop: twofish_setkey/sec: 38148
-+		 * CALC_K256: ~100 insns each
-+		 * CALC_K192: ~90 insns
-+		 *    CALC_K: ~70 insns
-+		 */
-+		/* Calculate whitening and round subkeys */
-+		for ( i = 0; i < 8; i += 2 ) {
-+			CALC_K256 (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
-+		}
-+		for ( i = 0; i < 32; i += 2 ) {
-+			CALC_K256 (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
-+		}
- 	} else if (key_len == 24) { /* 192-bit key */
- 		/* Compute the S-boxes. */
- 		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
- 		        CALC_SB192_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
- 		}
+@@ -727,10 +753,11 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
+  * attached and rescan it against existing drivers to see if it matches
+  * any by calling device_attach() for the unbound devices.
+  */
+-int bus_rescan_devices(struct bus_type * bus)
++int bus_rescan_devices(struct bus_type *bus)
+ {
+ 	return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
+ }
++EXPORT_SYMBOL_GPL(bus_rescan_devices);
  
--		/* Calculate whitening and round subkeys.  The constants are
--		 * indices of subkeys, preprocessed through q0 and q1. */
--		CALC_K192 (w, 0, 0xA9, 0x75, 0x67, 0xF3);
--		CALC_K192 (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
--		CALC_K192 (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
--		CALC_K192 (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
--		CALC_K192 (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
--		CALC_K192 (k, 2, 0x80, 0xE6, 0x78, 0x6B);
--		CALC_K192 (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
--		CALC_K192 (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
--		CALC_K192 (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
--		CALC_K192 (k, 10, 0x35, 0xD8, 0x98, 0xFD);
--		CALC_K192 (k, 12, 0x18, 0x37, 0xF7, 0x71);
--		CALC_K192 (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
--		CALC_K192 (k, 16, 0x43, 0x30, 0x75, 0x0F);
--		CALC_K192 (k, 18, 0x37, 0xF8, 0x26, 0x1B);
--		CALC_K192 (k, 20, 0xFA, 0x87, 0x13, 0xFA);
--		CALC_K192 (k, 22, 0x94, 0x06, 0x48, 0x3F);
--		CALC_K192 (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
--		CALC_K192 (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
--		CALC_K192 (k, 28, 0x84, 0x8A, 0x54, 0x00);
--		CALC_K192 (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
-+		/* Calculate whitening and round subkeys */
-+		for ( i = 0; i < 8; i += 2 ) {
-+			CALC_K192 (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
-+		}
-+		for ( i = 0; i < 32; i += 2 ) {
-+			CALC_K192 (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
-+		}
- 	} else { /* 128-bit key */
- 		/* Compute the S-boxes. */
- 		for ( i = j = 0, k = 1; i < 256; i++, j += 2, k += 2 ) {
- 			CALC_SB_2( i, calc_sb_tbl[j], calc_sb_tbl[k] );
+ /**
+  * device_reprobe - remove driver for a device and probe for a new driver
+@@ -755,55 +782,55 @@ int device_reprobe(struct device *dev)
+ EXPORT_SYMBOL_GPL(device_reprobe);
+ 
+ /**
+- *	find_bus - locate bus by name.
+- *	@name:	name of bus.
++ * find_bus - locate bus by name.
++ * @name: name of bus.
+  *
+- *	Call kset_find_obj() to iterate over list of buses to
+- *	find a bus by name. Return bus if found.
++ * Call kset_find_obj() to iterate over list of buses to
++ * find a bus by name. Return bus if found.
+  *
+- *	Note that kset_find_obj increments bus' reference count.
++ * Note that kset_find_obj increments bus' reference count.
+  */
+ #if 0
+-struct bus_type * find_bus(char * name)
++struct bus_type *find_bus(char *name)
+ {
+-	struct kobject * k = kset_find_obj(&bus_subsys.kset, name);
++	struct kobject *k = kset_find_obj(bus_kset, name);
+ 	return k ? to_bus(k) : NULL;
+ }
+ #endif  /*  0  */
+ 
+ 
+ /**
+- *	bus_add_attrs - Add default attributes for this bus.
+- *	@bus:	Bus that has just been registered.
++ * bus_add_attrs - Add default attributes for this bus.
++ * @bus: Bus that has just been registered.
+  */
+ 
+-static int bus_add_attrs(struct bus_type * bus)
++static int bus_add_attrs(struct bus_type *bus)
+ {
+ 	int error = 0;
+ 	int i;
+ 
+ 	if (bus->bus_attrs) {
+ 		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
+-			error = bus_create_file(bus,&bus->bus_attrs[i]);
++			error = bus_create_file(bus, &bus->bus_attrs[i]);
+ 			if (error)
+-				goto Err;
++				goto err;
  		}
+ 	}
+- Done:
++done:
+ 	return error;
+- Err:
++err:
+ 	while (--i >= 0)
+-		bus_remove_file(bus,&bus->bus_attrs[i]);
+-	goto Done;
++		bus_remove_file(bus, &bus->bus_attrs[i]);
++	goto done;
+ }
  
--		/* Calculate whitening and round subkeys.  The constants are
--		 * indices of subkeys, preprocessed through q0 and q1. */
--		CALC_K (w, 0, 0xA9, 0x75, 0x67, 0xF3);
--		CALC_K (w, 2, 0xB3, 0xC6, 0xE8, 0xF4);
--		CALC_K (w, 4, 0x04, 0xDB, 0xFD, 0x7B);
--		CALC_K (w, 6, 0xA3, 0xFB, 0x76, 0xC8);
--		CALC_K (k, 0, 0x9A, 0x4A, 0x92, 0xD3);
--		CALC_K (k, 2, 0x80, 0xE6, 0x78, 0x6B);
--		CALC_K (k, 4, 0xE4, 0x45, 0xDD, 0x7D);
--		CALC_K (k, 6, 0xD1, 0xE8, 0x38, 0x4B);
--		CALC_K (k, 8, 0x0D, 0xD6, 0xC6, 0x32);
--		CALC_K (k, 10, 0x35, 0xD8, 0x98, 0xFD);
--		CALC_K (k, 12, 0x18, 0x37, 0xF7, 0x71);
--		CALC_K (k, 14, 0xEC, 0xF1, 0x6C, 0xE1);
--		CALC_K (k, 16, 0x43, 0x30, 0x75, 0x0F);
--		CALC_K (k, 18, 0x37, 0xF8, 0x26, 0x1B);
--		CALC_K (k, 20, 0xFA, 0x87, 0x13, 0xFA);
--		CALC_K (k, 22, 0x94, 0x06, 0x48, 0x3F);
--		CALC_K (k, 24, 0xF2, 0x5E, 0xD0, 0xBA);
--		CALC_K (k, 26, 0x8B, 0xAE, 0x30, 0x5B);
--		CALC_K (k, 28, 0x84, 0x8A, 0x54, 0x00);
--		CALC_K (k, 30, 0xDF, 0xBC, 0x23, 0x9D);
-+		/* Calculate whitening and round subkeys */
-+		for ( i = 0; i < 8; i += 2 ) {
-+			CALC_K (w, i, q0[i], q1[i], q0[i+1], q1[i+1]);
-+		}
-+		for ( i = 0; i < 32; i += 2 ) {
-+			CALC_K (k, i, q0[i+8], q1[i+8], q0[i+9], q1[i+9]);
-+		}
+-static void bus_remove_attrs(struct bus_type * bus)
++static void bus_remove_attrs(struct bus_type *bus)
+ {
+ 	int i;
+ 
+ 	if (bus->bus_attrs) {
+ 		for (i = 0; attr_name(bus->bus_attrs[i]); i++)
+-			bus_remove_file(bus,&bus->bus_attrs[i]);
++			bus_remove_file(bus, &bus->bus_attrs[i]);
  	}
+ }
+ 
+@@ -827,32 +854,42 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
+ 	enum kobject_action action;
+ 
+ 	if (kobject_action_type(buf, count, &action) == 0)
+-		kobject_uevent(&bus->subsys.kobj, action);
++		kobject_uevent(&bus->p->subsys.kobj, action);
+ 	return count;
+ }
+ static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
+ 
+ /**
+- *	bus_register - register a bus with the system.
+- *	@bus:	bus.
++ * bus_register - register a bus with the system.
++ * @bus: bus.
+  *
+- *	Once we have that, we registered the bus with the kobject
+- *	infrastructure, then register the children subsystems it has:
+- *	the devices and drivers that belong to the bus.
++ * Once we have that, we registered the bus with the kobject
++ * infrastructure, then register the children subsystems it has:
++ * the devices and drivers that belong to the bus.
+  */
+-int bus_register(struct bus_type * bus)
++int bus_register(struct bus_type *bus)
+ {
+ 	int retval;
++	struct bus_type_private *priv;
++
++	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
++	if (!priv)
++		return -ENOMEM;
+ 
+-	BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
++	priv->bus = bus;
++	bus->p = priv;
+ 
+-	retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
++	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
++
++	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
+ 	if (retval)
+ 		goto out;
+ 
+-	bus->subsys.kobj.kset = &bus_subsys;
++	priv->subsys.kobj.kset = bus_kset;
++	priv->subsys.kobj.ktype = &bus_ktype;
++	priv->drivers_autoprobe = 1;
+ 
+-	retval = subsystem_register(&bus->subsys);
++	retval = kset_register(&priv->subsys);
+ 	if (retval)
+ 		goto out;
+ 
+@@ -860,23 +897,23 @@ int bus_register(struct bus_type * bus)
+ 	if (retval)
+ 		goto bus_uevent_fail;
+ 
+-	kobject_set_name(&bus->devices.kobj, "devices");
+-	bus->devices.kobj.parent = &bus->subsys.kobj;
+-	retval = kset_register(&bus->devices);
+-	if (retval)
++	priv->devices_kset = kset_create_and_add("devices", NULL,
++						 &priv->subsys.kobj);
++	if (!priv->devices_kset) {
++		retval = -ENOMEM;
+ 		goto bus_devices_fail;
++	}
+ 
+-	kobject_set_name(&bus->drivers.kobj, "drivers");
+-	bus->drivers.kobj.parent = &bus->subsys.kobj;
+-	bus->drivers.ktype = &driver_ktype;
+-	retval = kset_register(&bus->drivers);
+-	if (retval)
++	priv->drivers_kset = kset_create_and_add("drivers", NULL,
++						 &priv->subsys.kobj);
++	if (!priv->drivers_kset) {
++		retval = -ENOMEM;
+ 		goto bus_drivers_fail;
++	}
+ 
+-	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
+-	klist_init(&bus->klist_drivers, NULL, NULL);
++	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
++	klist_init(&priv->klist_drivers, NULL, NULL);
+ 
+-	bus->drivers_autoprobe = 1;
+ 	retval = add_probe_files(bus);
+ 	if (retval)
+ 		goto bus_probe_files_fail;
+@@ -885,66 +922,73 @@ int bus_register(struct bus_type * bus)
+ 	if (retval)
+ 		goto bus_attrs_fail;
  
+-	pr_debug("bus type '%s' registered\n", bus->name);
++	pr_debug("bus: '%s': registered\n", bus->name);
  	return 0;
-diff --git a/crypto/xcbc.c b/crypto/xcbc.c
-index ac68f3b..a82959d 100644
---- a/crypto/xcbc.c
-+++ b/crypto/xcbc.c
-@@ -19,6 +19,7 @@
-  * 	Kazunori Miyazawa <miyazawa at linux-ipv6.org>
+ 
+ bus_attrs_fail:
+ 	remove_probe_files(bus);
+ bus_probe_files_fail:
+-	kset_unregister(&bus->drivers);
++	kset_unregister(bus->p->drivers_kset);
+ bus_drivers_fail:
+-	kset_unregister(&bus->devices);
++	kset_unregister(bus->p->devices_kset);
+ bus_devices_fail:
+ 	bus_remove_file(bus, &bus_attr_uevent);
+ bus_uevent_fail:
+-	subsystem_unregister(&bus->subsys);
++	kset_unregister(&bus->p->subsys);
++	kfree(bus->p);
+ out:
+ 	return retval;
+ }
++EXPORT_SYMBOL_GPL(bus_register);
+ 
+ /**
+- *	bus_unregister - remove a bus from the system
+- *	@bus:	bus.
++ * bus_unregister - remove a bus from the system
++ * @bus: bus.
+  *
+- *	Unregister the child subsystems and the bus itself.
+- *	Finally, we call bus_put() to release the refcount
++ * Unregister the child subsystems and the bus itself.
++ * Finally, we call bus_put() to release the refcount
   */
+-void bus_unregister(struct bus_type * bus)
++void bus_unregister(struct bus_type *bus)
+ {
+-	pr_debug("bus %s: unregistering\n", bus->name);
++	pr_debug("bus: '%s': unregistering\n", bus->name);
+ 	bus_remove_attrs(bus);
+ 	remove_probe_files(bus);
+-	kset_unregister(&bus->drivers);
+-	kset_unregister(&bus->devices);
++	kset_unregister(bus->p->drivers_kset);
++	kset_unregister(bus->p->devices_kset);
+ 	bus_remove_file(bus, &bus_attr_uevent);
+-	subsystem_unregister(&bus->subsys);
++	kset_unregister(&bus->p->subsys);
++	kfree(bus->p);
+ }
++EXPORT_SYMBOL_GPL(bus_unregister);
  
-+#include <crypto/scatterwalk.h>
- #include <linux/crypto.h>
+ int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
+ {
+-	return blocking_notifier_chain_register(&bus->bus_notifier, nb);
++	return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
+ }
+ EXPORT_SYMBOL_GPL(bus_register_notifier);
+ 
+ int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
+ {
+-	return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
++	return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb);
+ }
+ EXPORT_SYMBOL_GPL(bus_unregister_notifier);
+ 
+-int __init buses_init(void)
++struct kset *bus_get_kset(struct bus_type *bus)
+ {
+-	return subsystem_register(&bus_subsys);
++	return &bus->p->subsys;
+ }
++EXPORT_SYMBOL_GPL(bus_get_kset);
+ 
++struct klist *bus_get_device_klist(struct bus_type *bus)
++{
++	return &bus->p->klist_devices;
++}
++EXPORT_SYMBOL_GPL(bus_get_device_klist);
+ 
+-EXPORT_SYMBOL_GPL(bus_for_each_dev);
+-EXPORT_SYMBOL_GPL(bus_find_device);
+-EXPORT_SYMBOL_GPL(bus_for_each_drv);
+-
+-EXPORT_SYMBOL_GPL(bus_register);
+-EXPORT_SYMBOL_GPL(bus_unregister);
+-EXPORT_SYMBOL_GPL(bus_rescan_devices);
+-
+-EXPORT_SYMBOL_GPL(bus_create_file);
+-EXPORT_SYMBOL_GPL(bus_remove_file);
++int __init buses_init(void)
++{
++	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
++	if (!bus_kset)
++		return -ENOMEM;
++	return 0;
++}
+diff --git a/drivers/base/class.c b/drivers/base/class.c
+index a863bb0..9d91537 100644
+--- a/drivers/base/class.c
++++ b/drivers/base/class.c
+@@ -17,16 +17,17 @@
+ #include <linux/kdev_t.h>
  #include <linux/err.h>
- #include <linux/hardirq.h>
-@@ -27,7 +28,6 @@
- #include <linux/rtnetlink.h>
  #include <linux/slab.h>
- #include <linux/scatterlist.h>
--#include "internal.h"
++#include <linux/genhd.h>
+ #include "base.h"
  
- static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
- 			   0x02020202, 0x02020202, 0x02020202, 0x02020202,
-@@ -307,7 +307,8 @@ static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
- 	case 16:
- 		break;
- 	default:
--		return ERR_PTR(PTR_ERR(alg));
-+		inst = ERR_PTR(-EINVAL);
-+		goto out_put_alg;
- 	}
+ #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
+ #define to_class(obj) container_of(obj, struct class, subsys.kobj)
  
- 	inst = crypto_alloc_instance("xcbc", alg);
-@@ -320,10 +321,7 @@ static struct crypto_instance *xcbc_alloc(struct rtattr **tb)
- 	inst->alg.cra_alignmask = alg->cra_alignmask;
- 	inst->alg.cra_type = &crypto_hash_type;
+-static ssize_t
+-class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
++static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
++			       char *buf)
+ {
+-	struct class_attribute * class_attr = to_class_attr(attr);
+-	struct class * dc = to_class(kobj);
++	struct class_attribute *class_attr = to_class_attr(attr);
++	struct class *dc = to_class(kobj);
+ 	ssize_t ret = -EIO;
  
--	inst->alg.cra_hash.digestsize =
--		(alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
--		CRYPTO_ALG_TYPE_HASH ? alg->cra_hash.digestsize :
--				       alg->cra_blocksize;
-+	inst->alg.cra_hash.digestsize = alg->cra_blocksize;
- 	inst->alg.cra_ctxsize = sizeof(struct crypto_xcbc_ctx) +
- 				ALIGN(inst->alg.cra_blocksize * 3, sizeof(void *));
- 	inst->alg.cra_init = xcbc_init_tfm;
-diff --git a/drivers/Kconfig b/drivers/Kconfig
-index f4076d9..08d4ae2 100644
---- a/drivers/Kconfig
-+++ b/drivers/Kconfig
-@@ -90,8 +90,6 @@ source "drivers/dca/Kconfig"
+ 	if (class_attr->show)
+@@ -34,12 +35,11 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
+ 	return ret;
+ }
  
- source "drivers/auxdisplay/Kconfig"
+-static ssize_t
+-class_attr_store(struct kobject * kobj, struct attribute * attr,
+-		 const char * buf, size_t count)
++static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
++				const char *buf, size_t count)
+ {
+-	struct class_attribute * class_attr = to_class_attr(attr);
+-	struct class * dc = to_class(kobj);
++	struct class_attribute *class_attr = to_class_attr(attr);
++	struct class *dc = to_class(kobj);
+ 	ssize_t ret = -EIO;
  
--source "drivers/kvm/Kconfig"
--
- source "drivers/uio/Kconfig"
+ 	if (class_attr->store)
+@@ -47,7 +47,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr,
+ 	return ret;
+ }
  
- source "drivers/virtio/Kconfig"
-diff --git a/drivers/Makefile b/drivers/Makefile
-index 8cb37e3..0ee9a8a 100644
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -38,7 +38,7 @@ obj-$(CONFIG_SCSI)		+= scsi/
- obj-$(CONFIG_ATA)		+= ata/
- obj-$(CONFIG_FUSION)		+= message/
- obj-$(CONFIG_FIREWIRE)		+= firewire/
--obj-$(CONFIG_IEEE1394)		+= ieee1394/
-+obj-y				+= ieee1394/
- obj-$(CONFIG_UIO)		+= uio/
- obj-y				+= cdrom/
- obj-y				+= auxdisplay/
-@@ -47,7 +47,6 @@ obj-$(CONFIG_SPI)		+= spi/
- obj-$(CONFIG_PCCARD)		+= pcmcia/
- obj-$(CONFIG_DIO)		+= dio/
- obj-$(CONFIG_SBUS)		+= sbus/
--obj-$(CONFIG_KVM)		+= kvm/
- obj-$(CONFIG_ZORRO)		+= zorro/
- obj-$(CONFIG_MAC)		+= macintosh/
- obj-$(CONFIG_ATA_OVER_ETH)	+= block/aoe/
-@@ -73,7 +72,7 @@ obj-$(CONFIG_ISDN)		+= isdn/
- obj-$(CONFIG_EDAC)		+= edac/
- obj-$(CONFIG_MCA)		+= mca/
- obj-$(CONFIG_EISA)		+= eisa/
--obj-$(CONFIG_LGUEST_GUEST)	+= lguest/
-+obj-y				+= lguest/
- obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
- obj-$(CONFIG_CPU_IDLE)		+= cpuidle/
- obj-$(CONFIG_MMC)		+= mmc/
-diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
-index f4487c3..1b4cf98 100644
---- a/drivers/acpi/bus.c
-+++ b/drivers/acpi/bus.c
-@@ -743,7 +743,7 @@ static int __init acpi_bus_init(void)
- 	return -ENODEV;
+-static void class_release(struct kobject * kobj)
++static void class_release(struct kobject *kobj)
+ {
+ 	struct class *class = to_class(kobj);
+ 
+@@ -71,20 +71,20 @@ static struct kobj_type class_ktype = {
+ };
+ 
+ /* Hotplug events for classes go to the class_obj subsys */
+-static decl_subsys(class, &class_ktype, NULL);
++static struct kset *class_kset;
+ 
+ 
+-int class_create_file(struct class * cls, const struct class_attribute * attr)
++int class_create_file(struct class *cls, const struct class_attribute *attr)
+ {
+ 	int error;
+-	if (cls) {
++	if (cls)
+ 		error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
+-	} else
++	else
+ 		error = -EINVAL;
+ 	return error;
  }
  
--decl_subsys(acpi, NULL, NULL);
-+struct kobject *acpi_kobj;
+-void class_remove_file(struct class * cls, const struct class_attribute * attr)
++void class_remove_file(struct class *cls, const struct class_attribute *attr)
+ {
+ 	if (cls)
+ 		sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
+@@ -93,48 +93,48 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr)
+ static struct class *class_get(struct class *cls)
+ {
+ 	if (cls)
+-		return container_of(kset_get(&cls->subsys), struct class, subsys);
++		return container_of(kset_get(&cls->subsys),
++				    struct class, subsys);
+ 	return NULL;
+ }
  
- static int __init acpi_init(void)
+-static void class_put(struct class * cls)
++static void class_put(struct class *cls)
  {
-@@ -755,10 +755,11 @@ static int __init acpi_init(void)
- 		return -ENODEV;
+ 	if (cls)
+ 		kset_put(&cls->subsys);
+ }
+ 
+-
+-static int add_class_attrs(struct class * cls)
++static int add_class_attrs(struct class *cls)
+ {
+ 	int i;
+ 	int error = 0;
+ 
+ 	if (cls->class_attrs) {
+ 		for (i = 0; attr_name(cls->class_attrs[i]); i++) {
+-			error = class_create_file(cls,&cls->class_attrs[i]);
++			error = class_create_file(cls, &cls->class_attrs[i]);
+ 			if (error)
+-				goto Err;
++				goto error;
+ 		}
  	}
+- Done:
++done:
+ 	return error;
+- Err:
++error:
+ 	while (--i >= 0)
+-		class_remove_file(cls,&cls->class_attrs[i]);
+-	goto Done;
++		class_remove_file(cls, &cls->class_attrs[i]);
++	goto done;
+ }
  
--	result = firmware_register(&acpi_subsys);
--	if (result < 0)
--		printk(KERN_WARNING "%s: firmware_register error: %d\n",
--			__FUNCTION__, result);
-+	acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
-+	if (!acpi_kobj) {
-+		printk(KERN_WARNING "%s: kset create error\n", __FUNCTION__);
-+		acpi_kobj = NULL;
-+	}
+-static void remove_class_attrs(struct class * cls)
++static void remove_class_attrs(struct class *cls)
+ {
+ 	int i;
  
- 	result = acpi_bus_init();
+ 	if (cls->class_attrs) {
+ 		for (i = 0; attr_name(cls->class_attrs[i]); i++)
+-			class_remove_file(cls,&cls->class_attrs[i]);
++			class_remove_file(cls, &cls->class_attrs[i]);
+ 	}
+ }
  
-diff --git a/drivers/acpi/hardware/hwsleep.c b/drivers/acpi/hardware/hwsleep.c
-index 81b2484..fd1c4ba 100644
---- a/drivers/acpi/hardware/hwsleep.c
-+++ b/drivers/acpi/hardware/hwsleep.c
-@@ -192,18 +192,13 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
- 	arg.type = ACPI_TYPE_INTEGER;
- 	arg.integer.value = sleep_state;
+-int class_register(struct class * cls)
++int class_register(struct class *cls)
+ {
+ 	int error;
  
--	/* Run the _PTS and _GTS methods */
-+	/* Run the _PTS method */
+@@ -149,9 +149,16 @@ int class_register(struct class * cls)
+ 	if (error)
+ 		return error;
  
- 	status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
- 	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- 		return_ACPI_STATUS(status);
- 	}
+-	cls->subsys.kobj.kset = &class_subsys;
++#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
++	/* let the block class directory show up in the root of sysfs */
++	if (cls != &block_class)
++		cls->subsys.kobj.kset = class_kset;
++#else
++	cls->subsys.kobj.kset = class_kset;
++#endif
++	cls->subsys.kobj.ktype = &class_ktype;
  
--	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
--	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
--		return_ACPI_STATUS(status);
--	}
--
- 	/* Setup the argument to _SST */
+-	error = subsystem_register(&cls->subsys);
++	error = kset_register(&cls->subsys);
+ 	if (!error) {
+ 		error = add_class_attrs(class_get(cls));
+ 		class_put(cls);
+@@ -159,11 +166,11 @@ int class_register(struct class * cls)
+ 	return error;
+ }
  
- 	switch (sleep_state) {
-@@ -234,10 +229,6 @@ acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
- 				"While executing method _SST"));
+-void class_unregister(struct class * cls)
++void class_unregister(struct class *cls)
+ {
+ 	pr_debug("device class '%s': unregistering\n", cls->name);
+ 	remove_class_attrs(cls);
+-	subsystem_unregister(&cls->subsys);
++	kset_unregister(&cls->subsys);
+ }
+ 
+ static void class_create_release(struct class *cls)
+@@ -241,8 +248,8 @@ void class_destroy(struct class *cls)
+ 
+ /* Class Device Stuff */
+ 
+-int class_device_create_file(struct class_device * class_dev,
+-			     const struct class_device_attribute * attr)
++int class_device_create_file(struct class_device *class_dev,
++			     const struct class_device_attribute *attr)
+ {
+ 	int error = -EINVAL;
+ 	if (class_dev)
+@@ -250,8 +257,8 @@ int class_device_create_file(struct class_device * class_dev,
+ 	return error;
+ }
+ 
+-void class_device_remove_file(struct class_device * class_dev,
+-			      const struct class_device_attribute * attr)
++void class_device_remove_file(struct class_device *class_dev,
++			      const struct class_device_attribute *attr)
+ {
+ 	if (class_dev)
+ 		sysfs_remove_file(&class_dev->kobj, &attr->attr);
+@@ -273,12 +280,11 @@ void class_device_remove_bin_file(struct class_device *class_dev,
+ 		sysfs_remove_bin_file(&class_dev->kobj, attr);
+ }
+ 
+-static ssize_t
+-class_device_attr_show(struct kobject * kobj, struct attribute * attr,
+-		       char * buf)
++static ssize_t class_device_attr_show(struct kobject *kobj,
++				      struct attribute *attr, char *buf)
+ {
+-	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
+-	struct class_device * cd = to_class_dev(kobj);
++	struct class_device_attribute *class_dev_attr = to_class_dev_attr(attr);
++	struct class_device *cd = to_class_dev(kobj);
+ 	ssize_t ret = 0;
+ 
+ 	if (class_dev_attr->show)
+@@ -286,12 +292,12 @@ class_device_attr_show(struct kobject * kobj, struct attribute * attr,
+ 	return ret;
+ }
+ 
+-static ssize_t
+-class_device_attr_store(struct kobject * kobj, struct attribute * attr,
+-			const char * buf, size_t count)
++static ssize_t class_device_attr_store(struct kobject *kobj,
++				       struct attribute *attr,
++				       const char *buf, size_t count)
+ {
+-	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
+-	struct class_device * cd = to_class_dev(kobj);
++	struct class_device_attribute *class_dev_attr = to_class_dev_attr(attr);
++	struct class_device *cd = to_class_dev(kobj);
+ 	ssize_t ret = 0;
+ 
+ 	if (class_dev_attr->store)
+@@ -304,10 +310,10 @@ static struct sysfs_ops class_dev_sysfs_ops = {
+ 	.store	= class_device_attr_store,
+ };
+ 
+-static void class_dev_release(struct kobject * kobj)
++static void class_dev_release(struct kobject *kobj)
+ {
+ 	struct class_device *cd = to_class_dev(kobj);
+-	struct class * cls = cd->class;
++	struct class *cls = cd->class;
+ 
+ 	pr_debug("device class '%s': release.\n", cd->class_id);
+ 
+@@ -316,8 +322,8 @@ static void class_dev_release(struct kobject * kobj)
+ 	else if (cls->release)
+ 		cls->release(cd);
+ 	else {
+-		printk(KERN_ERR "Class Device '%s' does not have a release() function, "
+-			"it is broken and must be fixed.\n",
++		printk(KERN_ERR "Class Device '%s' does not have a release() "
++			"function, it is broken and must be fixed.\n",
+ 			cd->class_id);
+ 		WARN_ON(1);
  	}
+@@ -428,7 +434,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj,
+ 			add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
  
--	/* Disable/Clear all GPEs */
--
--	status = acpi_hw_disable_all_gpes();
+ 		if (dev->driver)
+-			add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
++			add_uevent_var(env, "PHYSDEVDRIVER=%s",
++				       dev->driver->name);
+ 	}
+ 
+ 	if (class_dev->uevent) {
+@@ -452,43 +459,49 @@ static struct kset_uevent_ops class_uevent_ops = {
+ 	.uevent =	class_uevent,
+ };
+ 
+-static decl_subsys(class_obj, &class_device_ktype, &class_uevent_ops);
 -
- 	return_ACPI_STATUS(status);
++/*
++ * DO NOT copy how this is created, kset_create_and_add() should be
++ * called, but this is a hold-over from the old-way and will be deleted
++ * entirely soon.
++ */
++static struct kset class_obj_subsys = {
++	.uevent_ops = &class_uevent_ops,
++};
+ 
+-static int class_device_add_attrs(struct class_device * cd)
++static int class_device_add_attrs(struct class_device *cd)
+ {
+ 	int i;
+ 	int error = 0;
+-	struct class * cls = cd->class;
++	struct class *cls = cd->class;
+ 
+ 	if (cls->class_dev_attrs) {
+ 		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
+ 			error = class_device_create_file(cd,
+-							 &cls->class_dev_attrs[i]);
++						&cls->class_dev_attrs[i]);
+ 			if (error)
+-				goto Err;
++				goto err;
+ 		}
+ 	}
+- Done:
++done:
+ 	return error;
+- Err:
++err:
+ 	while (--i >= 0)
+-		class_device_remove_file(cd,&cls->class_dev_attrs[i]);
+-	goto Done;
++		class_device_remove_file(cd, &cls->class_dev_attrs[i]);
++	goto done;
  }
  
-@@ -262,6 +253,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
- 	struct acpi_bit_register_info *sleep_type_reg_info;
- 	struct acpi_bit_register_info *sleep_enable_reg_info;
- 	u32 in_value;
-+	struct acpi_object_list arg_list;
-+	union acpi_object arg;
- 	acpi_status status;
+-static void class_device_remove_attrs(struct class_device * cd)
++static void class_device_remove_attrs(struct class_device *cd)
+ {
+ 	int i;
+-	struct class * cls = cd->class;
++	struct class *cls = cd->class;
  
- 	ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
-@@ -307,6 +300,18 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
- 		return_ACPI_STATUS(status);
+ 	if (cls->class_dev_attrs) {
+ 		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
+-			class_device_remove_file(cd,&cls->class_dev_attrs[i]);
++			class_device_remove_file(cd, &cls->class_dev_attrs[i]);
  	}
+ }
  
-+	/* Execute the _GTS method */
-+
-+	arg_list.count = 1;
-+	arg_list.pointer = &arg;
-+	arg.type = ACPI_TYPE_INTEGER;
-+	arg.integer.value = sleep_state;
-+
-+	status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
-+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-+		return_ACPI_STATUS(status);
-+	}
-+
- 	/* Get current value of PM1A control */
+-static int class_device_add_groups(struct class_device * cd)
++static int class_device_add_groups(struct class_device *cd)
+ {
+ 	int i;
+ 	int error = 0;
+@@ -498,7 +511,8 @@ static int class_device_add_groups(struct class_device * cd)
+ 			error = sysfs_create_group(&cd->kobj, cd->groups[i]);
+ 			if (error) {
+ 				while (--i >= 0)
+-					sysfs_remove_group(&cd->kobj, cd->groups[i]);
++					sysfs_remove_group(&cd->kobj,
++							   cd->groups[i]);
+ 				goto out;
+ 			}
+ 		}
+@@ -507,14 +521,12 @@ out:
+ 	return error;
+ }
  
- 	status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
-@@ -473,17 +478,18 @@ ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
+-static void class_device_remove_groups(struct class_device * cd)
++static void class_device_remove_groups(struct class_device *cd)
+ {
+ 	int i;
+-	if (cd->groups) {
+-		for (i = 0; cd->groups[i]; i++) {
++	if (cd->groups)
++		for (i = 0; cd->groups[i]; i++)
+ 			sysfs_remove_group(&cd->kobj, cd->groups[i]);
+-		}
+-	}
+ }
  
- /*******************************************************************************
-  *
-- * FUNCTION:    acpi_leave_sleep_state
-+ * FUNCTION:    acpi_leave_sleep_state_prep
-  *
-- * PARAMETERS:  sleep_state         - Which sleep state we just exited
-+ * PARAMETERS:  sleep_state         - Which sleep state we are exiting
-  *
-  * RETURN:      Status
-  *
-- * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
-- *              Called with interrupts ENABLED.
-+ * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
-+ *              sleep.
-+ *              Called with interrupts DISABLED.
-  *
-  ******************************************************************************/
--acpi_status acpi_leave_sleep_state(u8 sleep_state)
-+acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
+ static ssize_t show_dev(struct class_device *class_dev, char *buf)
+@@ -537,8 +549,8 @@ static struct class_device_attribute class_uevent_attr =
+ 
+ void class_device_initialize(struct class_device *class_dev)
  {
- 	struct acpi_object_list arg_list;
- 	union acpi_object arg;
-@@ -493,7 +499,7 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
- 	u32 PM1Acontrol;
- 	u32 PM1Bcontrol;
+-	kobj_set_kset_s(class_dev, class_obj_subsys);
+-	kobject_init(&class_dev->kobj);
++	class_dev->kobj.kset = &class_obj_subsys;
++	kobject_init(&class_dev->kobj, &class_device_ktype);
+ 	INIT_LIST_HEAD(&class_dev->node);
+ }
  
--	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
-+	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
+@@ -566,16 +578,13 @@ int class_device_add(struct class_device *class_dev)
+ 		 class_dev->class_id);
  
- 	/*
- 	 * Set SLP_TYPE and SLP_EN to state S0.
-@@ -540,6 +546,41 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
- 		}
- 	}
+ 	/* first, register with generic layer. */
+-	error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
+-	if (error)
+-		goto out2;
+-
+ 	if (parent_class_dev)
+ 		class_dev->kobj.parent = &parent_class_dev->kobj;
+ 	else
+ 		class_dev->kobj.parent = &parent_class->subsys.kobj;
  
-+	/* Execute the _BFS method */
-+
-+	arg_list.count = 1;
-+	arg_list.pointer = &arg;
-+	arg.type = ACPI_TYPE_INTEGER;
-+	arg.integer.value = sleep_state;
+-	error = kobject_add(&class_dev->kobj);
++	error = kobject_add(&class_dev->kobj, class_dev->kobj.parent,
++			    "%s", class_dev->class_id);
+ 	if (error)
+ 		goto out2;
+ 
+@@ -642,7 +651,7 @@ int class_device_add(struct class_device *class_dev)
+  out3:
+ 	kobject_del(&class_dev->kobj);
+  out2:
+-	if(parent_class_dev)
++	if (parent_class_dev)
+ 		class_device_put(parent_class_dev);
+ 	class_put(parent_class);
+  out1:
+@@ -659,9 +668,11 @@ int class_device_register(struct class_device *class_dev)
+ /**
+  * class_device_create - creates a class device and registers it with sysfs
+  * @cls: pointer to the struct class that this device should be registered to.
+- * @parent: pointer to the parent struct class_device of this new device, if any.
++ * @parent: pointer to the parent struct class_device of this new device, if
++ * any.
+  * @devt: the dev_t for the char device to be added.
+- * @device: a pointer to a struct device that is assiociated with this class device.
++ * @device: a pointer to a struct device that is assiociated with this class
++ * device.
+  * @fmt: string for the class device's name
+  *
+  * This function can be used by char device classes.  A struct
+@@ -785,7 +796,7 @@ void class_device_destroy(struct class *cls, dev_t devt)
+ 		class_device_unregister(class_dev);
+ }
+ 
+-struct class_device * class_device_get(struct class_device *class_dev)
++struct class_device *class_device_get(struct class_device *class_dev)
+ {
+ 	if (class_dev)
+ 		return to_class_dev(kobject_get(&class_dev->kobj));
+@@ -798,6 +809,139 @@ void class_device_put(struct class_device *class_dev)
+ 		kobject_put(&class_dev->kobj);
+ }
+ 
++/**
++ * class_for_each_device - device iterator
++ * @class: the class we're iterating
++ * @data: data for the callback
++ * @fn: function to be called for each device
++ *
++ * Iterate over @class's list of devices, and call @fn for each,
++ * passing it @data.
++ *
++ * We check the return of @fn each time. If it returns anything
++ * other than 0, we break out and return that value.
++ *
++ * Note, we hold class->sem in this function, so it can not be
++ * re-acquired in @fn, otherwise it will self-deadlocking. For
++ * example, calls to add or remove class members would be verboten.
++ */
++int class_for_each_device(struct class *class, void *data,
++			   int (*fn)(struct device *, void *))
++{
++	struct device *dev;
++	int error = 0;
 +
-+	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
-+	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
-+		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
++	if (!class)
++		return -EINVAL;
++	down(&class->sem);
++	list_for_each_entry(dev, &class->devices, node) {
++		dev = get_device(dev);
++		if (dev) {
++			error = fn(dev, data);
++			put_device(dev);
++		} else
++			error = -ENODEV;
++		if (error)
++			break;
 +	}
++	up(&class->sem);
 +
-+	return_ACPI_STATUS(status);
++	return error;
 +}
++EXPORT_SYMBOL_GPL(class_for_each_device);
 +
-+/*******************************************************************************
++/**
++ * class_find_device - device iterator for locating a particular device
++ * @class: the class we're iterating
++ * @data: data for the match function
++ * @match: function to check device
 + *
-+ * FUNCTION:    acpi_leave_sleep_state
++ * This is similar to the class_for_each_dev() function above, but it
++ * returns a reference to a device that is 'found' for later use, as
++ * determined by the @match callback.
 + *
-+ * PARAMETERS:  sleep_state         - Which sleep state we just exited
++ * The callback should return 0 if the device doesn't match and non-zero
++ * if it does.  If the callback returns non-zero, this function will
++ * return to the caller and not iterate over any more devices.
 + *
-+ * RETURN:      Status
++ * Note, you will need to drop the reference with put_device() after use.
 + *
-+ * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
-+ *              Called with interrupts ENABLED.
++ * We hold class->sem in this function, so it can not be
++ * re-acquired in @match, otherwise it will self-deadlocking. For
++ * example, calls to add or remove class members would be verboten.
++ */
++struct device *class_find_device(struct class *class, void *data,
++				   int (*match)(struct device *, void *))
++{
++	struct device *dev;
++	int found = 0;
++
++	if (!class)
++		return NULL;
++
++	down(&class->sem);
++	list_for_each_entry(dev, &class->devices, node) {
++		dev = get_device(dev);
++		if (dev) {
++			if (match(dev, data)) {
++				found = 1;
++				break;
++			} else
++				put_device(dev);
++		} else
++			break;
++	}
++	up(&class->sem);
++
++	return found ? dev : NULL;
++}
++EXPORT_SYMBOL_GPL(class_find_device);
++
++/**
++ * class_find_child - device iterator for locating a particular class_device
++ * @class: the class we're iterating
++ * @data: data for the match function
++ * @match: function to check class_device
 + *
-+ ******************************************************************************/
-+acpi_status acpi_leave_sleep_state(u8 sleep_state)
++ * This function returns a reference to a class_device that is 'found' for
++ * later use, as determined by the @match callback.
++ *
++ * The callback should return 0 if the class_device doesn't match and non-zero
++ * if it does.  If the callback returns non-zero, this function will
++ * return to the caller and not iterate over any more class_devices.
++ *
++ * Note, you will need to drop the reference with class_device_put() after use.
++ *
++ * We hold class->sem in this function, so it can not be
++ * re-acquired in @match, otherwise it will self-deadlocking. For
++ * example, calls to add or remove class members would be verboten.
++ */
++struct class_device *class_find_child(struct class *class, void *data,
++				   int (*match)(struct class_device *, void *))
 +{
-+	struct acpi_object_list arg_list;
-+	union acpi_object arg;
-+	acpi_status status;
++	struct class_device *dev;
++	int found = 0;
 +
-+	ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
++	if (!class)
++		return NULL;
 +
- 	/* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
++	down(&class->sem);
++	list_for_each_entry(dev, &class->children, node) {
++		dev = class_device_get(dev);
++		if (dev) {
++			if (match(dev, data)) {
++				found = 1;
++				break;
++			} else
++				class_device_put(dev);
++		} else
++			break;
++	}
++	up(&class->sem);
++
++	return found ? dev : NULL;
++}
++EXPORT_SYMBOL_GPL(class_find_child);
  
- 	acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
-@@ -558,12 +599,6 @@ acpi_status acpi_leave_sleep_state(u8 sleep_state)
- 		ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
+ int class_interface_register(struct class_interface *class_intf)
+ {
+@@ -829,7 +973,7 @@ int class_interface_register(struct class_interface *class_intf)
+ 
+ void class_interface_unregister(struct class_interface *class_intf)
+ {
+-	struct class * parent = class_intf->class;
++	struct class *parent = class_intf->class;
+ 	struct class_device *class_dev;
+ 	struct device *dev;
+ 
+@@ -853,15 +997,14 @@ void class_interface_unregister(struct class_interface *class_intf)
+ 
+ int __init classes_init(void)
+ {
+-	int retval;
+-
+-	retval = subsystem_register(&class_subsys);
+-	if (retval)
+-		return retval;
++	class_kset = kset_create_and_add("class", NULL, NULL);
++	if (!class_kset)
++		return -ENOMEM;
+ 
+ 	/* ick, this is ugly, the things we go through to keep from showing up
+ 	 * in sysfs... */
+ 	kset_init(&class_obj_subsys);
++	kobject_set_name(&class_obj_subsys.kobj, "class_obj");
+ 	if (!class_obj_subsys.kobj.parent)
+ 		class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
+ 	return 0;
+diff --git a/drivers/base/core.c b/drivers/base/core.c
+index 2683eac..9c0070b 100644
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -18,18 +18,26 @@
+ #include <linux/string.h>
+ #include <linux/kdev_t.h>
+ #include <linux/notifier.h>
+-
++#include <linux/genhd.h>
+ #include <asm/semaphore.h>
+ 
+ #include "base.h"
+ #include "power/power.h"
+ 
+-int (*platform_notify)(struct device * dev) = NULL;
+-int (*platform_notify_remove)(struct device * dev) = NULL;
++int (*platform_notify)(struct device *dev) = NULL;
++int (*platform_notify_remove)(struct device *dev) = NULL;
+ 
+-/*
+- * sysfs bindings for devices.
+- */
++#ifdef CONFIG_BLOCK
++static inline int device_is_not_partition(struct device *dev)
++{
++	return !(dev->type == &part_type);
++}
++#else
++static inline int device_is_not_partition(struct device *dev)
++{
++	return 1;
++}
++#endif
+ 
+ /**
+  * dev_driver_string - Return a device's driver name, if at all possible
+@@ -51,11 +59,11 @@ EXPORT_SYMBOL(dev_driver_string);
+ #define to_dev(obj) container_of(obj, struct device, kobj)
+ #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
+ 
+-static ssize_t
+-dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
++static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
++			     char *buf)
+ {
+-	struct device_attribute * dev_attr = to_dev_attr(attr);
+-	struct device * dev = to_dev(kobj);
++	struct device_attribute *dev_attr = to_dev_attr(attr);
++	struct device *dev = to_dev(kobj);
+ 	ssize_t ret = -EIO;
+ 
+ 	if (dev_attr->show)
+@@ -63,12 +71,11 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
+ 	return ret;
+ }
+ 
+-static ssize_t
+-dev_attr_store(struct kobject * kobj, struct attribute * attr,
+-	       const char * buf, size_t count)
++static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
++			      const char *buf, size_t count)
+ {
+-	struct device_attribute * dev_attr = to_dev_attr(attr);
+-	struct device * dev = to_dev(kobj);
++	struct device_attribute *dev_attr = to_dev_attr(attr);
++	struct device *dev = to_dev(kobj);
+ 	ssize_t ret = -EIO;
+ 
+ 	if (dev_attr->store)
+@@ -90,9 +97,9 @@ static struct sysfs_ops dev_sysfs_ops = {
+  *	reaches 0. We forward the call to the device's release
+  *	method, which should handle actually freeing the structure.
+  */
+-static void device_release(struct kobject * kobj)
++static void device_release(struct kobject *kobj)
+ {
+-	struct device * dev = to_dev(kobj);
++	struct device *dev = to_dev(kobj);
+ 
+ 	if (dev->release)
+ 		dev->release(dev);
+@@ -101,8 +108,8 @@ static void device_release(struct kobject * kobj)
+ 	else if (dev->class && dev->class->dev_release)
+ 		dev->class->dev_release(dev);
+ 	else {
+-		printk(KERN_ERR "Device '%s' does not have a release() function, "
+-			"it is broken and must be fixed.\n",
++		printk(KERN_ERR "Device '%s' does not have a release() "
++			"function, it is broken and must be fixed.\n",
+ 			dev->bus_id);
+ 		WARN_ON(1);
  	}
+@@ -185,7 +192,8 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ 		add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
  
--	arg.integer.value = sleep_state;
--	status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
--	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
--		ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
+ 		if (dev->driver)
+-			add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
++			add_uevent_var(env, "PHYSDEVDRIVER=%s",
++				       dev->driver->name);
+ 	}
+ #endif
+ 
+@@ -193,15 +201,16 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ 	if (dev->bus && dev->bus->uevent) {
+ 		retval = dev->bus->uevent(dev, env);
+ 		if (retval)
+-			pr_debug ("%s: bus uevent() returned %d\n",
+-				  __FUNCTION__, retval);
++			pr_debug("device: '%s': %s: bus uevent() returned %d\n",
++				 dev->bus_id, __FUNCTION__, retval);
+ 	}
+ 
+ 	/* have the class specific function add its stuff */
+ 	if (dev->class && dev->class->dev_uevent) {
+ 		retval = dev->class->dev_uevent(dev, env);
+ 		if (retval)
+-			pr_debug("%s: class uevent() returned %d\n",
++			pr_debug("device: '%s': %s: class uevent() "
++				 "returned %d\n", dev->bus_id,
+ 				 __FUNCTION__, retval);
+ 	}
+ 
+@@ -209,7 +218,8 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
+ 	if (dev->type && dev->type->uevent) {
+ 		retval = dev->type->uevent(dev, env);
+ 		if (retval)
+-			pr_debug("%s: dev_type uevent() returned %d\n",
++			pr_debug("device: '%s': %s: dev_type uevent() "
++				 "returned %d\n", dev->bus_id,
+ 				 __FUNCTION__, retval);
+ 	}
+ 
+@@ -325,7 +335,8 @@ static int device_add_groups(struct device *dev,
+ 			error = sysfs_create_group(&dev->kobj, groups[i]);
+ 			if (error) {
+ 				while (--i >= 0)
+-					sysfs_remove_group(&dev->kobj, groups[i]);
++					sysfs_remove_group(&dev->kobj,
++							   groups[i]);
+ 				break;
+ 			}
+ 		}
+@@ -401,41 +412,31 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
+ static struct device_attribute devt_attr =
+ 	__ATTR(dev, S_IRUGO, show_dev, NULL);
+ 
+-/*
+- *	devices_subsys - structure to be registered with kobject core.
+- */
+-
+-decl_subsys(devices, &device_ktype, &device_uevent_ops);
+-
++/* kset to create /sys/devices/  */
++struct kset *devices_kset;
+ 
+ /**
+- *	device_create_file - create sysfs attribute file for device.
+- *	@dev:	device.
+- *	@attr:	device attribute descriptor.
++ * device_create_file - create sysfs attribute file for device.
++ * @dev: device.
++ * @attr: device attribute descriptor.
+  */
+-
+-int device_create_file(struct device * dev, struct device_attribute * attr)
++int device_create_file(struct device *dev, struct device_attribute *attr)
+ {
+ 	int error = 0;
+-	if (get_device(dev)) {
++	if (dev)
+ 		error = sysfs_create_file(&dev->kobj, &attr->attr);
+-		put_device(dev);
 -	}
+ 	return error;
+ }
+ 
+ /**
+- *	device_remove_file - remove sysfs attribute file.
+- *	@dev:	device.
+- *	@attr:	device attribute descriptor.
++ * device_remove_file - remove sysfs attribute file.
++ * @dev: device.
++ * @attr: device attribute descriptor.
+  */
 -
- 	/*
- 	 * GPEs must be enabled before _WAK is called as GPEs
- 	 * might get fired there
-diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
-index c9f526e..5400ea1 100644
---- a/drivers/acpi/pci_link.c
-+++ b/drivers/acpi/pci_link.c
-@@ -911,7 +911,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set);
+-void device_remove_file(struct device * dev, struct device_attribute * attr)
++void device_remove_file(struct device *dev, struct device_attribute *attr)
+ {
+-	if (get_device(dev)) {
++	if (dev)
+ 		sysfs_remove_file(&dev->kobj, &attr->attr);
+-		put_device(dev);
+-	}
+ }
  
- /* FIXME: we will remove this interface after all drivers call pci_disable_device */
- static struct sysdev_class irqrouter_sysdev_class = {
--	set_kset_name("irqrouter"),
-+	.name = "irqrouter",
- 	.resume = irqrouter_resume,
- };
+ /**
+@@ -511,22 +512,20 @@ static void klist_children_put(struct klist_node *n)
+ 	put_device(dev);
+ }
  
-diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
-index 2235f4e..eb1f82f 100644
---- a/drivers/acpi/processor_idle.c
-+++ b/drivers/acpi/processor_idle.c
-@@ -357,6 +357,26 @@ int acpi_processor_resume(struct acpi_device * device)
- 	return 0;
+-
+ /**
+- *	device_initialize - init device structure.
+- *	@dev:	device.
++ * device_initialize - init device structure.
++ * @dev: device.
+  *
+- *	This prepares the device for use by other layers,
+- *	including adding it to the device hierarchy.
+- *	It is the first half of device_register(), if called by
+- *	that, though it can also be called separately, so one
+- *	may use @dev's fields (e.g. the refcount).
++ * This prepares the device for use by other layers,
++ * including adding it to the device hierarchy.
++ * It is the first half of device_register(), if called by
++ * that, though it can also be called separately, so one
++ * may use @dev's fields (e.g. the refcount).
+  */
+-
+ void device_initialize(struct device *dev)
+ {
+-	kobj_set_kset_s(dev, devices_subsys);
+-	kobject_init(&dev->kobj);
++	dev->kobj.kset = devices_kset;
++	kobject_init(&dev->kobj, &device_ktype);
+ 	klist_init(&dev->klist_children, klist_children_get,
+ 		   klist_children_put);
+ 	INIT_LIST_HEAD(&dev->dma_pools);
+@@ -539,36 +538,39 @@ void device_initialize(struct device *dev)
  }
  
-+#if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
-+static int tsc_halts_in_c(int state)
+ #ifdef CONFIG_SYSFS_DEPRECATED
+-static struct kobject * get_device_parent(struct device *dev,
+-					  struct device *parent)
++static struct kobject *get_device_parent(struct device *dev,
++					 struct device *parent)
+ {
+-	/*
+-	 * Set the parent to the class, not the parent device
+-	 * for topmost devices in class hierarchy.
+-	 * This keeps sysfs from having a symlink to make old
+-	 * udevs happy
+-	 */
++	/* class devices without a parent live in /sys/class/<classname>/ */
+ 	if (dev->class && (!parent || parent->class != dev->class))
+ 		return &dev->class->subsys.kobj;
++	/* all other devices keep their parent */
+ 	else if (parent)
+ 		return &parent->kobj;
+ 
+ 	return NULL;
+ }
++
++static inline void cleanup_device_parent(struct device *dev) {}
++static inline void cleanup_glue_dir(struct device *dev,
++				    struct kobject *glue_dir) {}
+ #else
+ static struct kobject *virtual_device_parent(struct device *dev)
+ {
+ 	static struct kobject *virtual_dir = NULL;
+ 
+ 	if (!virtual_dir)
+-		virtual_dir = kobject_add_dir(&devices_subsys.kobj, "virtual");
++		virtual_dir = kobject_create_and_add("virtual",
++						     &devices_kset->kobj);
+ 
+ 	return virtual_dir;
+ }
+ 
+-static struct kobject * get_device_parent(struct device *dev,
+-					  struct device *parent)
++static struct kobject *get_device_parent(struct device *dev,
++					 struct device *parent)
+ {
++	int retval;
++
+ 	if (dev->class) {
+ 		struct kobject *kobj = NULL;
+ 		struct kobject *parent_kobj;
+@@ -576,8 +578,8 @@ static struct kobject * get_device_parent(struct device *dev,
+ 
+ 		/*
+ 		 * If we have no parent, we live in "virtual".
+-		 * Class-devices with a bus-device as parent, live
+-		 * in a class-directory to prevent namespace collisions.
++		 * Class-devices with a non class-device as parent, live
++		 * in a "glue" directory to prevent namespace collisions.
+ 		 */
+ 		if (parent == NULL)
+ 			parent_kobj = virtual_device_parent(dev);
+@@ -598,25 +600,45 @@ static struct kobject * get_device_parent(struct device *dev,
+ 			return kobj;
+ 
+ 		/* or create a new class-directory at the parent device */
+-		return kobject_kset_add_dir(&dev->class->class_dirs,
+-					    parent_kobj, dev->class->name);
++		k = kobject_create();
++		if (!k)
++			return NULL;
++		k->kset = &dev->class->class_dirs;
++		retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
++		if (retval < 0) {
++			kobject_put(k);
++			return NULL;
++		}
++		/* do not emit an uevent for this simple "glue" directory */
++		return k;
+ 	}
+ 
+ 	if (parent)
+ 		return &parent->kobj;
+ 	return NULL;
+ }
++
++static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
 +{
-+	switch (boot_cpu_data.x86_vendor) {
-+	case X86_VENDOR_AMD:
++	/* see if we live in a "glue" directory */
++	if (!dev->class || glue_dir->kset != &dev->class->class_dirs)
++		return;
++
++	kobject_put(glue_dir);
++}
++
++static void cleanup_device_parent(struct device *dev)
++{
++	cleanup_glue_dir(dev, dev->kobj.parent);
++}
+ #endif
+ 
+-static int setup_parent(struct device *dev, struct device *parent)
++static void setup_parent(struct device *dev, struct device *parent)
+ {
+ 	struct kobject *kobj;
+ 	kobj = get_device_parent(dev, parent);
+-	if (IS_ERR(kobj))
+-		return PTR_ERR(kobj);
+ 	if (kobj)
+ 		dev->kobj.parent = kobj;
+-	return 0;
+ }
+ 
+ static int device_add_class_symlinks(struct device *dev)
+@@ -625,65 +647,76 @@ static int device_add_class_symlinks(struct device *dev)
+ 
+ 	if (!dev->class)
+ 		return 0;
++
+ 	error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
+ 				  "subsystem");
+ 	if (error)
+ 		goto out;
+-	/*
+-	 * If this is not a "fake" compatible device, then create the
+-	 * symlink from the class to the device.
+-	 */
+-	if (dev->kobj.parent != &dev->class->subsys.kobj) {
++
++#ifdef CONFIG_SYSFS_DEPRECATED
++	/* stacked class devices need a symlink in the class directory */
++	if (dev->kobj.parent != &dev->class->subsys.kobj &&
++	    device_is_not_partition(dev)) {
+ 		error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
+ 					  dev->bus_id);
+ 		if (error)
+ 			goto out_subsys;
+ 	}
+-	if (dev->parent) {
+-#ifdef CONFIG_SYSFS_DEPRECATED
+-		{
+-			struct device *parent = dev->parent;
+-			char *class_name;
+-
+-			/*
+-			 * In old sysfs stacked class devices had 'device'
+-			 * link pointing to real device instead of parent
+-			 */
+-			while (parent->class && !parent->bus && parent->parent)
+-				parent = parent->parent;
+-
+-			error = sysfs_create_link(&dev->kobj,
+-						  &parent->kobj,
+-						  "device");
+-			if (error)
+-				goto out_busid;
+ 
+-			class_name = make_class_name(dev->class->name,
+-							&dev->kobj);
+-			if (class_name)
+-				error = sysfs_create_link(&dev->parent->kobj,
+-							&dev->kobj, class_name);
+-			kfree(class_name);
+-			if (error)
+-				goto out_device;
+-		}
+-#else
+-		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
++	if (dev->parent && device_is_not_partition(dev)) {
++		struct device *parent = dev->parent;
++		char *class_name;
++
 +		/*
-+		 * AMD Fam10h TSC will tick in all
-+		 * C/P/S0/S1 states when this bit is set.
++		 * stacked class devices have the 'device' link
++		 * pointing to the bus device instead of the parent
 +		 */
-+		if (boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
-+			return 0;
-+		/*FALL THROUGH*/
-+	case X86_VENDOR_INTEL:
-+		/* Several cases known where TSC halts in C2 too */
-+	default:
-+		return state > ACPI_STATE_C1;
++		while (parent->class && !parent->bus && parent->parent)
++			parent = parent->parent;
++
++		error = sysfs_create_link(&dev->kobj,
++					  &parent->kobj,
+ 					  "device");
+ 		if (error)
+ 			goto out_busid;
+-#endif
++
++		class_name = make_class_name(dev->class->name,
++						&dev->kobj);
++		if (class_name)
++			error = sysfs_create_link(&dev->parent->kobj,
++						&dev->kobj, class_name);
++		kfree(class_name);
++		if (error)
++			goto out_device;
+ 	}
+ 	return 0;
+ 
+-#ifdef CONFIG_SYSFS_DEPRECATED
+ out_device:
+-	if (dev->parent)
++	if (dev->parent && device_is_not_partition(dev))
+ 		sysfs_remove_link(&dev->kobj, "device");
+-#endif
+ out_busid:
+-	if (dev->kobj.parent != &dev->class->subsys.kobj)
++	if (dev->kobj.parent != &dev->class->subsys.kobj &&
++	    device_is_not_partition(dev))
+ 		sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
++#else
++	/* link in the class directory pointing to the device */
++	error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
++				  dev->bus_id);
++	if (error)
++		goto out_subsys;
++
++	if (dev->parent && device_is_not_partition(dev)) {
++		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
++					  "device");
++		if (error)
++			goto out_busid;
 +	}
-+}
++	return 0;
++
++out_busid:
++	sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
 +#endif
 +
- #ifndef CONFIG_CPU_IDLE
- static void acpi_processor_idle(void)
+ out_subsys:
+ 	sysfs_remove_link(&dev->kobj, "subsystem");
+ out:
+@@ -694,8 +727,9 @@ static void device_remove_class_symlinks(struct device *dev)
+ {
+ 	if (!dev->class)
+ 		return;
+-	if (dev->parent) {
++
+ #ifdef CONFIG_SYSFS_DEPRECATED
++	if (dev->parent && device_is_not_partition(dev)) {
+ 		char *class_name;
+ 
+ 		class_name = make_class_name(dev->class->name, &dev->kobj);
+@@ -703,45 +737,59 @@ static void device_remove_class_symlinks(struct device *dev)
+ 			sysfs_remove_link(&dev->parent->kobj, class_name);
+ 			kfree(class_name);
+ 		}
+-#endif
+ 		sysfs_remove_link(&dev->kobj, "device");
+ 	}
+-	if (dev->kobj.parent != &dev->class->subsys.kobj)
++
++	if (dev->kobj.parent != &dev->class->subsys.kobj &&
++	    device_is_not_partition(dev))
+ 		sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
++#else
++	if (dev->parent && device_is_not_partition(dev))
++		sysfs_remove_link(&dev->kobj, "device");
++
++	sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
++#endif
++
+ 	sysfs_remove_link(&dev->kobj, "subsystem");
+ }
+ 
+ /**
+- *	device_add - add device to device hierarchy.
+- *	@dev:	device.
++ * device_add - add device to device hierarchy.
++ * @dev: device.
+  *
+- *	This is part 2 of device_register(), though may be called
+- *	separately _iff_ device_initialize() has been called separately.
++ * This is part 2 of device_register(), though may be called
++ * separately _iff_ device_initialize() has been called separately.
+  *
+- *	This adds it to the kobject hierarchy via kobject_add(), adds it
+- *	to the global and sibling lists for the device, then
+- *	adds it to the other relevant subsystems of the driver model.
++ * This adds it to the kobject hierarchy via kobject_add(), adds it
++ * to the global and sibling lists for the device, then
++ * adds it to the other relevant subsystems of the driver model.
+  */
+ int device_add(struct device *dev)
+ {
+ 	struct device *parent = NULL;
+ 	struct class_interface *class_intf;
+-	int error = -EINVAL;
++	int error;
++
++	error = pm_sleep_lock();
++	if (error) {
++		dev_warn(dev, "Suspicious %s during suspend\n", __FUNCTION__);
++		dump_stack();
++		return error;
++	}
+ 
+ 	dev = get_device(dev);
+-	if (!dev || !strlen(dev->bus_id))
++	if (!dev || !strlen(dev->bus_id)) {
++		error = -EINVAL;
+ 		goto Error;
++	}
+ 
+-	pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
++	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+ 
+ 	parent = get_device(dev->parent);
+-	error = setup_parent(dev, parent);
+-	if (error)
+-		goto Error;
++	setup_parent(dev, parent);
+ 
+ 	/* first, register with generic layer. */
+-	kobject_set_name(&dev->kobj, "%s", dev->bus_id);
+-	error = kobject_add(&dev->kobj);
++	error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
+ 	if (error)
+ 		goto Error;
+ 
+@@ -751,7 +799,7 @@ int device_add(struct device *dev)
+ 
+ 	/* notify clients of device entry (new way) */
+ 	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
++		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ 					     BUS_NOTIFY_ADD_DEVICE, dev);
+ 
+ 	error = device_create_file(dev, &uevent_attr);
+@@ -795,13 +843,14 @@ int device_add(struct device *dev)
+ 	}
+  Done:
+ 	put_device(dev);
++	pm_sleep_unlock();
+ 	return error;
+  BusError:
+ 	device_pm_remove(dev);
+ 	dpm_sysfs_remove(dev);
+  PMError:
+ 	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
++		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ 					     BUS_NOTIFY_DEL_DEVICE, dev);
+ 	device_remove_attrs(dev);
+  AttrsError:
+@@ -809,124 +858,84 @@ int device_add(struct device *dev)
+  SymlinkError:
+ 	if (MAJOR(dev->devt))
+ 		device_remove_file(dev, &devt_attr);
+-
+-	if (dev->class) {
+-		sysfs_remove_link(&dev->kobj, "subsystem");
+-		/* If this is not a "fake" compatible device, remove the
+-		 * symlink from the class to the device. */
+-		if (dev->kobj.parent != &dev->class->subsys.kobj)
+-			sysfs_remove_link(&dev->class->subsys.kobj,
+-					  dev->bus_id);
+-		if (parent) {
+-#ifdef CONFIG_SYSFS_DEPRECATED
+-			char *class_name = make_class_name(dev->class->name,
+-							   &dev->kobj);
+-			if (class_name)
+-				sysfs_remove_link(&dev->parent->kobj,
+-						  class_name);
+-			kfree(class_name);
+-#endif
+-			sysfs_remove_link(&dev->kobj, "device");
+-		}
+-	}
+  ueventattrError:
+ 	device_remove_file(dev, &uevent_attr);
+  attrError:
+ 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
+ 	kobject_del(&dev->kobj);
+  Error:
++	cleanup_device_parent(dev);
+ 	if (parent)
+ 		put_device(parent);
+ 	goto Done;
+ }
+ 
+-
+ /**
+- *	device_register - register a device with the system.
+- *	@dev:	pointer to the device structure
++ * device_register - register a device with the system.
++ * @dev: pointer to the device structure
+  *
+- *	This happens in two clean steps - initialize the device
+- *	and add it to the system. The two steps can be called
+- *	separately, but this is the easiest and most common.
+- *	I.e. you should only call the two helpers separately if
+- *	have a clearly defined need to use and refcount the device
+- *	before it is added to the hierarchy.
++ * This happens in two clean steps - initialize the device
++ * and add it to the system. The two steps can be called
++ * separately, but this is the easiest and most common.
++ * I.e. you should only call the two helpers separately if
++ * have a clearly defined need to use and refcount the device
++ * before it is added to the hierarchy.
+  */
+-
+ int device_register(struct device *dev)
+ {
+ 	device_initialize(dev);
+ 	return device_add(dev);
+ }
+ 
+-
+ /**
+- *	get_device - increment reference count for device.
+- *	@dev:	device.
++ * get_device - increment reference count for device.
++ * @dev: device.
+  *
+- *	This simply forwards the call to kobject_get(), though
+- *	we do take care to provide for the case that we get a NULL
+- *	pointer passed in.
++ * This simply forwards the call to kobject_get(), though
++ * we do take care to provide for the case that we get a NULL
++ * pointer passed in.
+  */
+-
+-struct device * get_device(struct device * dev)
++struct device *get_device(struct device *dev)
+ {
+ 	return dev ? to_dev(kobject_get(&dev->kobj)) : NULL;
+ }
+ 
+-
+ /**
+- *	put_device - decrement reference count.
+- *	@dev:	device in question.
++ * put_device - decrement reference count.
++ * @dev: device in question.
+  */
+-void put_device(struct device * dev)
++void put_device(struct device *dev)
  {
-@@ -516,7 +536,8 @@ static void acpi_processor_idle(void)
++	/* might_sleep(); */
+ 	if (dev)
+ 		kobject_put(&dev->kobj);
+ }
  
- #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
- 		/* TSC halts in C2, so notify users */
--		mark_tsc_unstable("possible TSC halt in C2");
-+		if (tsc_halts_in_c(ACPI_STATE_C2))
-+			mark_tsc_unstable("possible TSC halt in C2");
- #endif
- 		/* Compute time (ticks) that we were actually asleep */
- 		sleep_ticks = ticks_elapsed(t1, t2);
-@@ -534,6 +555,7 @@ static void acpi_processor_idle(void)
- 		break;
+-
+ /**
+- *	device_del - delete device from system.
+- *	@dev:	device.
++ * device_del - delete device from system.
++ * @dev: device.
+  *
+- *	This is the first part of the device unregistration
+- *	sequence. This removes the device from the lists we control
+- *	from here, has it removed from the other driver model
+- *	subsystems it was added to in device_add(), and removes it
+- *	from the kobject hierarchy.
++ * This is the first part of the device unregistration
++ * sequence. This removes the device from the lists we control
++ * from here, has it removed from the other driver model
++ * subsystems it was added to in device_add(), and removes it
++ * from the kobject hierarchy.
+  *
+- *	NOTE: this should be called manually _iff_ device_add() was
+- *	also called manually.
++ * NOTE: this should be called manually _iff_ device_add() was
++ * also called manually.
+  */
+-
+-void device_del(struct device * dev)
++void device_del(struct device *dev)
+ {
+-	struct device * parent = dev->parent;
++	struct device *parent = dev->parent;
+ 	struct class_interface *class_intf;
  
- 	case ACPI_STATE_C3:
-+		acpi_unlazy_tlb(smp_processor_id());
- 		/*
- 		 * Must be done before busmaster disable as we might
- 		 * need to access HPET !
-@@ -579,7 +601,8 @@ static void acpi_processor_idle(void)
++	device_pm_remove(dev);
+ 	if (parent)
+ 		klist_del(&dev->knode_parent);
+ 	if (MAJOR(dev->devt))
+ 		device_remove_file(dev, &devt_attr);
+ 	if (dev->class) {
+-		sysfs_remove_link(&dev->kobj, "subsystem");
+-		/* If this is not a "fake" compatible device, remove the
+-		 * symlink from the class to the device. */
+-		if (dev->kobj.parent != &dev->class->subsys.kobj)
+-			sysfs_remove_link(&dev->class->subsys.kobj,
+-					  dev->bus_id);
+-		if (parent) {
+-#ifdef CONFIG_SYSFS_DEPRECATED
+-			char *class_name = make_class_name(dev->class->name,
+-							   &dev->kobj);
+-			if (class_name)
+-				sysfs_remove_link(&dev->parent->kobj,
+-						  class_name);
+-			kfree(class_name);
+-#endif
+-			sysfs_remove_link(&dev->kobj, "device");
+-		}
++		device_remove_class_symlinks(dev);
  
- #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
- 		/* TSC halts in C3, so notify users */
--		mark_tsc_unstable("TSC halts in C3");
-+		if (tsc_halts_in_c(ACPI_STATE_C3))
-+			mark_tsc_unstable("TSC halts in C3");
- #endif
- 		/* Compute time (ticks) that we were actually asleep */
- 		sleep_ticks = ticks_elapsed(t1, t2);
-@@ -1423,6 +1446,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
- 		return 0;
+ 		down(&dev->class->sem);
+ 		/* notify any interfaces that the device is now gone */
+@@ -936,31 +945,6 @@ void device_del(struct device * dev)
+ 		/* remove the device from the class list */
+ 		list_del_init(&dev->node);
+ 		up(&dev->class->sem);
+-
+-		/* If we live in a parent class-directory, unreference it */
+-		if (dev->kobj.parent->kset == &dev->class->class_dirs) {
+-			struct device *d;
+-			int other = 0;
+-
+-			/*
+-			 * if we are the last child of our class, delete
+-			 * our class-directory at this parent
+-			 */
+-			down(&dev->class->sem);
+-			list_for_each_entry(d, &dev->class->devices, node) {
+-				if (d == dev)
+-					continue;
+-				if (d->kobj.parent == dev->kobj.parent) {
+-					other = 1;
+-					break;
+-				}
+-			}
+-			if (!other)
+-				kobject_del(dev->kobj.parent);
+-
+-			kobject_put(dev->kobj.parent);
+-			up(&dev->class->sem);
+-		}
  	}
+ 	device_remove_file(dev, &uevent_attr);
+ 	device_remove_attrs(dev);
+@@ -979,57 +963,55 @@ void device_del(struct device * dev)
+ 	if (platform_notify_remove)
+ 		platform_notify_remove(dev);
+ 	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
++		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ 					     BUS_NOTIFY_DEL_DEVICE, dev);
+-	device_pm_remove(dev);
+ 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
++	cleanup_device_parent(dev);
+ 	kobject_del(&dev->kobj);
+-	if (parent)
+-		put_device(parent);
++	put_device(parent);
+ }
  
-+	acpi_unlazy_tlb(smp_processor_id());
- 	/*
- 	 * Must be done before busmaster disable as we might need to
- 	 * access HPET !
-@@ -1443,7 +1467,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
- 
- #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
- 	/* TSC could halt in idle, so notify users */
--	mark_tsc_unstable("TSC halts in idle");;
-+	if (tsc_halts_in_c(cx->type))
-+		mark_tsc_unstable("TSC halts in idle");;
- #endif
- 	sleep_ticks = ticks_elapsed(t1, t2);
- 
-@@ -1554,7 +1579,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
- 
- #if defined (CONFIG_GENERIC_TIME) && defined (CONFIG_X86_TSC)
- 	/* TSC could halt in idle, so notify users */
--	mark_tsc_unstable("TSC halts in idle");
-+	if (tsc_halts_in_c(ACPI_STATE_C3))
-+		mark_tsc_unstable("TSC halts in idle");
- #endif
- 	sleep_ticks = ticks_elapsed(t1, t2);
- 	/* Tell the scheduler how much we idled: */
-diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c
-index 2c0b663..485de13 100644
---- a/drivers/acpi/sleep/main.c
-+++ b/drivers/acpi/sleep/main.c
-@@ -26,9 +26,24 @@ u8 sleep_states[ACPI_S_STATE_COUNT];
- 
- #ifdef CONFIG_PM_SLEEP
- static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-+static bool acpi_sleep_finish_wake_up;
-+
-+/*
-+ * ACPI 2.0 and later want us to execute _PTS after suspending devices, so we
-+ * allow the user to request that behavior by using the 'acpi_new_pts_ordering'
-+ * kernel command line option that causes the following variable to be set.
-+ */
-+static bool new_pts_ordering;
-+
-+static int __init acpi_new_pts_ordering(char *str)
-+{
-+	new_pts_ordering = true;
-+	return 1;
-+}
-+__setup("acpi_new_pts_ordering", acpi_new_pts_ordering);
- #endif
+ /**
+- *	device_unregister - unregister device from system.
+- *	@dev:	device going away.
++ * device_unregister - unregister device from system.
++ * @dev: device going away.
+  *
+- *	We do this in two parts, like we do device_register(). First,
+- *	we remove it from all the subsystems with device_del(), then
+- *	we decrement the reference count via put_device(). If that
+- *	is the final reference count, the device will be cleaned up
+- *	via device_release() above. Otherwise, the structure will
+- *	stick around until the final reference to the device is dropped.
++ * We do this in two parts, like we do device_register(). First,
++ * we remove it from all the subsystems with device_del(), then
++ * we decrement the reference count via put_device(). If that
++ * is the final reference count, the device will be cleaned up
++ * via device_release() above. Otherwise, the structure will
++ * stick around until the final reference to the device is dropped.
+  */
+-void device_unregister(struct device * dev)
++void device_unregister(struct device *dev)
+ {
+-	pr_debug("DEV: Unregistering device. ID = '%s'\n", dev->bus_id);
++	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+ 	device_del(dev);
+ 	put_device(dev);
+ }
  
--int acpi_sleep_prepare(u32 acpi_state)
-+static int acpi_sleep_prepare(u32 acpi_state)
+-
+-static struct device * next_device(struct klist_iter * i)
++static struct device *next_device(struct klist_iter *i)
  {
- #ifdef CONFIG_ACPI_SLEEP
- 	/* do we have a wakeup address for S2 and S3? */
-@@ -44,6 +59,8 @@ int acpi_sleep_prepare(u32 acpi_state)
- 	ACPI_FLUSH_CPU_CACHE();
- 	acpi_enable_wakeup_device_prep(acpi_state);
- #endif
-+	printk(KERN_INFO PREFIX "Preparing to enter system sleep state S%d\n",
-+		acpi_state);
- 	acpi_enter_sleep_state_prep(acpi_state);
- 	return 0;
+-	struct klist_node * n = klist_next(i);
++	struct klist_node *n = klist_next(i);
+ 	return n ? container_of(n, struct device, knode_parent) : NULL;
  }
-@@ -63,17 +80,25 @@ static u32 acpi_suspend_states[] = {
- static int init_8259A_after_S1;
  
  /**
-- *	acpi_pm_set_target - Set the target system sleep state to the state
-+ *	acpi_pm_begin - Set the target system sleep state to the state
-  *		associated with given @pm_state, if supported.
+- *	device_for_each_child - device child iterator.
+- *	@parent: parent struct device.
+- *	@data:	data for the callback.
+- *	@fn:	function to be called for each device.
++ * device_for_each_child - device child iterator.
++ * @parent: parent struct device.
++ * @data: data for the callback.
++ * @fn: function to be called for each device.
+  *
+- *	Iterate over @parent's child devices, and call @fn for each,
+- *	passing it @data.
++ * Iterate over @parent's child devices, and call @fn for each,
++ * passing it @data.
+  *
+- *	We check the return of @fn each time. If it returns anything
+- *	other than 0, we break out and return that value.
++ * We check the return of @fn each time. If it returns anything
++ * other than 0, we break out and return that value.
   */
- 
--static int acpi_pm_set_target(suspend_state_t pm_state)
-+static int acpi_pm_begin(suspend_state_t pm_state)
+-int device_for_each_child(struct device * parent, void * data,
+-		     int (*fn)(struct device *, void *))
++int device_for_each_child(struct device *parent, void *data,
++			  int (*fn)(struct device *dev, void *data))
  {
- 	u32 acpi_state = acpi_suspend_states[pm_state];
+ 	struct klist_iter i;
+-	struct device * child;
++	struct device *child;
  	int error = 0;
  
- 	if (sleep_states[acpi_state]) {
- 		acpi_target_sleep_state = acpi_state;
-+		if (new_pts_ordering)
-+			return 0;
-+
-+		error = acpi_sleep_prepare(acpi_state);
-+		if (error)
-+			acpi_target_sleep_state = ACPI_STATE_S0;
-+		else
-+			acpi_sleep_finish_wake_up = true;
- 	} else {
- 		printk(KERN_ERR "ACPI does not support this state: %d\n",
- 			pm_state);
-@@ -91,12 +116,17 @@ static int acpi_pm_set_target(suspend_state_t pm_state)
- 
- static int acpi_pm_prepare(void)
+ 	klist_iter_init(&parent->klist_children, &i);
+@@ -1054,8 +1036,8 @@ int device_for_each_child(struct device * parent, void * data,
+  * current device can be obtained, this function will return to the caller
+  * and not iterate over any more devices.
+  */
+-struct device * device_find_child(struct device *parent, void *data,
+-				  int (*match)(struct device *, void *))
++struct device *device_find_child(struct device *parent, void *data,
++				 int (*match)(struct device *dev, void *data))
  {
--	int error = acpi_sleep_prepare(acpi_target_sleep_state);
-+	if (new_pts_ordering) {
-+		int error = acpi_sleep_prepare(acpi_target_sleep_state);
- 
--	if (error)
--		acpi_target_sleep_state = ACPI_STATE_S0;
-+		if (error) {
-+			acpi_target_sleep_state = ACPI_STATE_S0;
-+			return error;
-+		}
-+		acpi_sleep_finish_wake_up = true;
-+	}
+ 	struct klist_iter i;
+ 	struct device *child;
+@@ -1073,7 +1055,10 @@ struct device * device_find_child(struct device *parent, void *data,
  
--	return error;
-+	return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
+ int __init devices_init(void)
+ {
+-	return subsystem_register(&devices_subsys);
++	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
++	if (!devices_kset)
++		return -ENOMEM;
++	return 0;
  }
  
- /**
-@@ -120,10 +150,8 @@ static int acpi_pm_enter(suspend_state_t pm_state)
- 	if (acpi_state == ACPI_STATE_S3) {
- 		int error = acpi_save_state_mem();
+ EXPORT_SYMBOL_GPL(device_for_each_child);
+@@ -1094,7 +1079,7 @@ EXPORT_SYMBOL_GPL(device_remove_file);
  
--		if (error) {
--			acpi_target_sleep_state = ACPI_STATE_S0;
-+		if (error)
- 			return error;
--		}
- 	}
+ static void device_create_release(struct device *dev)
+ {
+-	pr_debug("%s called for %s\n", __FUNCTION__, dev->bus_id);
++	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+ 	kfree(dev);
+ }
  
- 	local_irq_save(flags);
-@@ -139,6 +167,9 @@ static int acpi_pm_enter(suspend_state_t pm_state)
- 		break;
- 	}
+@@ -1155,6 +1140,13 @@ error:
+ }
+ EXPORT_SYMBOL_GPL(device_create);
  
-+	/* Reprogram control registers and execute _BFS */
-+	acpi_leave_sleep_state_prep(acpi_state);
++static int __match_devt(struct device *dev, void *data)
++{
++	dev_t *devt = data;
 +
- 	/* ACPI 3.0 specs (P62) says that it's the responsabilty
- 	 * of the OSPM to clear the status bit [ implying that the
- 	 * POWER_BUTTON event should not reach userspace ]
-@@ -146,6 +177,13 @@ static int acpi_pm_enter(suspend_state_t pm_state)
- 	if (ACPI_SUCCESS(status) && (acpi_state == ACPI_STATE_S3))
- 		acpi_clear_event(ACPI_EVENT_POWER_BUTTON);
- 
-+	/*
-+	 * Disable and clear GPE status before interrupt is enabled. Some GPEs
-+	 * (like wakeup GPE) haven't handler, this can avoid such GPE misfire.
-+	 * acpi_leave_sleep_state will reenable specific GPEs later
-+	 */
-+	acpi_hw_disable_all_gpes();
++	return dev->devt == *devt;
++}
 +
- 	local_irq_restore(flags);
- 	printk(KERN_DEBUG "Back to C!\n");
- 
-@@ -157,7 +195,7 @@ static int acpi_pm_enter(suspend_state_t pm_state)
- }
- 
  /**
-- *	acpi_pm_finish - Finish up suspend sequence.
-+ *	acpi_pm_finish - Instruct the platform to leave a sleep state.
-  *
-  *	This is called after we wake back up (or if entering the sleep state
-  *	failed). 
-@@ -174,6 +212,7 @@ static void acpi_pm_finish(void)
- 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
- 
- 	acpi_target_sleep_state = ACPI_STATE_S0;
-+	acpi_sleep_finish_wake_up = false;
+  * device_destroy - removes a device that was created with device_create()
+  * @class: pointer to the struct class that this device was registered with
+@@ -1165,23 +1157,45 @@ EXPORT_SYMBOL_GPL(device_create);
+  */
+ void device_destroy(struct class *class, dev_t devt)
+ {
+-	struct device *dev = NULL;
+-	struct device *dev_tmp;
++	struct device *dev;
  
- #ifdef CONFIG_X86
- 	if (init_8259A_after_S1) {
-@@ -183,6 +222,20 @@ static void acpi_pm_finish(void)
- #endif
+-	down(&class->sem);
+-	list_for_each_entry(dev_tmp, &class->devices, node) {
+-		if (dev_tmp->devt == devt) {
+-			dev = dev_tmp;
+-			break;
+-		}
+-	}
+-	up(&class->sem);
+-
+-	if (dev)
++	dev = class_find_device(class, &devt, __match_devt);
++	if (dev) {
++		put_device(dev);
+ 		device_unregister(dev);
++	}
  }
+ EXPORT_SYMBOL_GPL(device_destroy);
  
++#ifdef CONFIG_PM_SLEEP
 +/**
-+ *	acpi_pm_end - Finish up suspend sequence.
++ * destroy_suspended_device - asks the PM core to remove a suspended device
++ * @class: pointer to the struct class that this device was registered with
++ * @devt: the dev_t of the device that was previously registered
++ *
++ * This call notifies the PM core of the necessity to unregister a suspended
++ * device created with a call to device_create() (devices cannot be
++ * unregistered directly while suspended, since the PM core holds their
++ * semaphores at that time).
++ *
++ * It can only be called within the scope of a system sleep transition.  In
++ * practice this means it has to be directly or indirectly invoked either by
++ * a suspend or resume method, or by the PM core (e.g. via
++ * disable_nonboot_cpus() or enable_nonboot_cpus()).
 + */
-+
-+static void acpi_pm_end(void)
++void destroy_suspended_device(struct class *class, dev_t devt)
 +{
-+	/*
-+	 * This is necessary in case acpi_pm_finish() is not called directly
-+	 * during a failing transition to a sleep state.
-+	 */
-+	if (acpi_sleep_finish_wake_up)
-+		acpi_pm_finish();
++	struct device *dev;
++
++	dev = class_find_device(class, &devt, __match_devt);
++	if (dev) {
++		device_pm_schedule_removal(dev);
++		put_device(dev);
++	}
 +}
++EXPORT_SYMBOL_GPL(destroy_suspended_device);
++#endif /* CONFIG_PM_SLEEP */
 +
- static int acpi_pm_state_valid(suspend_state_t pm_state)
- {
- 	u32 acpi_state;
-@@ -201,10 +254,11 @@ static int acpi_pm_state_valid(suspend_state_t pm_state)
+ /**
+  * device_rename - renames a device
+  * @dev: the pointer to the struct device to be renamed
+@@ -1198,7 +1212,8 @@ int device_rename(struct device *dev, char *new_name)
+ 	if (!dev)
+ 		return -EINVAL;
  
- static struct platform_suspend_ops acpi_pm_ops = {
- 	.valid = acpi_pm_state_valid,
--	.set_target = acpi_pm_set_target,
-+	.begin = acpi_pm_begin,
- 	.prepare = acpi_pm_prepare,
- 	.enter = acpi_pm_enter,
- 	.finish = acpi_pm_finish,
-+	.end = acpi_pm_end,
- };
+-	pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
++	pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
++		 __FUNCTION__, new_name);
  
- /*
-@@ -229,15 +283,36 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
- #endif /* CONFIG_SUSPEND */
+ #ifdef CONFIG_SYSFS_DEPRECATED
+ 	if ((dev->class) && (dev->parent))
+@@ -1279,8 +1294,7 @@ static int device_move_class_links(struct device *dev,
+ 					  class_name);
+ 		if (error)
+ 			sysfs_remove_link(&dev->kobj, "device");
+-	}
+-	else
++	} else
+ 		error = 0;
+ out:
+ 	kfree(class_name);
+@@ -1311,16 +1325,13 @@ int device_move(struct device *dev, struct device *new_parent)
+ 		return -EINVAL;
  
- #ifdef CONFIG_HIBERNATION
--static int acpi_hibernation_start(void)
-+static int acpi_hibernation_begin(void)
- {
-+	int error;
-+
- 	acpi_target_sleep_state = ACPI_STATE_S4;
--	return 0;
-+	if (new_pts_ordering)
-+		return 0;
-+
-+	error = acpi_sleep_prepare(ACPI_STATE_S4);
-+	if (error)
-+		acpi_target_sleep_state = ACPI_STATE_S0;
-+	else
-+		acpi_sleep_finish_wake_up = true;
+ 	new_parent = get_device(new_parent);
+-	new_parent_kobj = get_device_parent (dev, new_parent);
+-	if (IS_ERR(new_parent_kobj)) {
+-		error = PTR_ERR(new_parent_kobj);
+-		put_device(new_parent);
+-		goto out;
+-	}
+-	pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
+-		 new_parent ? new_parent->bus_id : "<NULL>");
++	new_parent_kobj = get_device_parent(dev, new_parent);
 +
-+	return error;
++	pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
++		 __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
+ 	error = kobject_move(&dev->kobj, new_parent_kobj);
+ 	if (error) {
++		cleanup_glue_dir(dev, new_parent_kobj);
+ 		put_device(new_parent);
+ 		goto out;
+ 	}
+@@ -1343,6 +1354,7 @@ int device_move(struct device *dev, struct device *new_parent)
+ 				klist_add_tail(&dev->knode_parent,
+ 					       &old_parent->klist_children);
+ 		}
++		cleanup_glue_dir(dev, new_parent_kobj);
+ 		put_device(new_parent);
+ 		goto out;
+ 	}
+@@ -1352,5 +1364,23 @@ out:
+ 	put_device(dev);
+ 	return error;
  }
- 
- static int acpi_hibernation_prepare(void)
- {
--	return acpi_sleep_prepare(ACPI_STATE_S4);
-+	if (new_pts_ordering) {
-+		int error = acpi_sleep_prepare(ACPI_STATE_S4);
+-
+ EXPORT_SYMBOL_GPL(device_move);
 +
-+		if (error) {
-+			acpi_target_sleep_state = ACPI_STATE_S0;
-+			return error;
++/**
++ * device_shutdown - call ->shutdown() on each device to shutdown.
++ */
++void device_shutdown(void)
++{
++	struct device *dev, *devn;
++
++	list_for_each_entry_safe_reverse(dev, devn, &devices_kset->list,
++				kobj.entry) {
++		if (dev->bus && dev->bus->shutdown) {
++			dev_dbg(dev, "shutdown\n");
++			dev->bus->shutdown(dev);
++		} else if (dev->driver && dev->driver->shutdown) {
++			dev_dbg(dev, "shutdown\n");
++			dev->driver->shutdown(dev);
 +		}
-+		acpi_sleep_finish_wake_up = true;
 +	}
-+
-+	return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT;
- }
- 
- static int acpi_hibernation_enter(void)
-@@ -251,6 +326,8 @@ static int acpi_hibernation_enter(void)
- 	acpi_enable_wakeup_device(ACPI_STATE_S4);
- 	/* This shouldn't return.  If it returns, we have a problem */
- 	status = acpi_enter_sleep_state(ACPI_STATE_S4);
-+	/* Reprogram control registers and execute _BFS */
-+	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
- 	local_irq_restore(flags);
- 
- 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
-@@ -263,15 +340,12 @@ static void acpi_hibernation_leave(void)
- 	 * enable it here.
- 	 */
- 	acpi_enable();
-+	/* Reprogram control registers and execute _BFS */
-+	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
- }
++}
+diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
+index 4054507..c5885f5 100644
+--- a/drivers/base/cpu.c
++++ b/drivers/base/cpu.c
+@@ -14,7 +14,7 @@
+ #include "base.h"
  
- static void acpi_hibernation_finish(void)
- {
--	/*
--	 * If ACPI is not enabled by the BIOS and the boot kernel, we need to
--	 * enable it here.
--	 */
--	acpi_enable();
- 	acpi_disable_wakeup_device(ACPI_STATE_S4);
- 	acpi_leave_sleep_state(ACPI_STATE_S4);
+ struct sysdev_class cpu_sysdev_class = {
+-	set_kset_name("cpu"),
++	.name = "cpu",
+ };
+ EXPORT_SYMBOL(cpu_sysdev_class);
  
-@@ -279,6 +353,17 @@ static void acpi_hibernation_finish(void)
- 	acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+diff --git a/drivers/base/dd.c b/drivers/base/dd.c
+index 7ac474d..a5cde94 100644
+--- a/drivers/base/dd.c
++++ b/drivers/base/dd.c
+@@ -1,18 +1,20 @@
+ /*
+- *	drivers/base/dd.c - The core device/driver interactions.
++ * drivers/base/dd.c - The core device/driver interactions.
+  *
+- * 	This file contains the (sometimes tricky) code that controls the
+- *	interactions between devices and drivers, which primarily includes
+- *	driver binding and unbinding.
++ * This file contains the (sometimes tricky) code that controls the
++ * interactions between devices and drivers, which primarily includes
++ * driver binding and unbinding.
+  *
+- *	All of this code used to exist in drivers/base/bus.c, but was
+- *	relocated to here in the name of compartmentalization (since it wasn't
+- *	strictly code just for the 'struct bus_type'.
++ * All of this code used to exist in drivers/base/bus.c, but was
++ * relocated to here in the name of compartmentalization (since it wasn't
++ * strictly code just for the 'struct bus_type'.
+  *
+- *	Copyright (c) 2002-5 Patrick Mochel
+- *	Copyright (c) 2002-3 Open Source Development Labs
++ * Copyright (c) 2002-5 Patrick Mochel
++ * Copyright (c) 2002-3 Open Source Development Labs
++ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
++ * Copyright (c) 2007 Novell Inc.
+  *
+- *	This file is released under the GPLv2
++ * This file is released under the GPLv2
+  */
  
- 	acpi_target_sleep_state = ACPI_STATE_S0;
-+	acpi_sleep_finish_wake_up = false;
-+}
-+
-+static void acpi_hibernation_end(void)
-+{
-+	/*
-+	 * This is necessary in case acpi_hibernation_finish() is not called
-+	 * directly during a failing transition to the sleep state.
-+	 */
-+	if (acpi_sleep_finish_wake_up)
-+		acpi_hibernation_finish();
- }
+ #include <linux/device.h>
+@@ -23,8 +25,6 @@
+ #include "base.h"
+ #include "power/power.h"
  
- static int acpi_hibernation_pre_restore(void)
-@@ -296,7 +381,8 @@ static void acpi_hibernation_restore_cleanup(void)
- }
+-#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
+-
  
- static struct platform_hibernation_ops acpi_hibernation_ops = {
--	.start = acpi_hibernation_start,
-+	.begin = acpi_hibernation_begin,
-+	.end = acpi_hibernation_end,
- 	.pre_snapshot = acpi_hibernation_prepare,
- 	.finish = acpi_hibernation_finish,
- 	.prepare = acpi_hibernation_prepare,
-@@ -403,6 +489,7 @@ static void acpi_power_off_prepare(void)
+ static void driver_bound(struct device *dev)
  {
- 	/* Prepare to power off the system */
- 	acpi_sleep_prepare(ACPI_STATE_S5);
-+	acpi_hw_disable_all_gpes();
- }
+@@ -34,27 +34,27 @@ static void driver_bound(struct device *dev)
+ 		return;
+ 	}
  
- static void acpi_power_off(void)
-diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h
-index a2ea125..cfaf8f5 100644
---- a/drivers/acpi/sleep/sleep.h
-+++ b/drivers/acpi/sleep/sleep.h
-@@ -5,5 +5,3 @@ extern int acpi_suspend (u32 state);
- extern void acpi_enable_wakeup_device_prep(u8 sleep_state);
- extern void acpi_enable_wakeup_device(u8 sleep_state);
- extern void acpi_disable_wakeup_device(u8 sleep_state);
--
--extern int acpi_sleep_prepare(u32 acpi_state);
-diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
-index edee280..5ffe0ea 100644
---- a/drivers/acpi/system.c
-+++ b/drivers/acpi/system.c
-@@ -58,7 +58,7 @@ module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444);
-                               FS Interface (/sys)
-    -------------------------------------------------------------------------- */
- static LIST_HEAD(acpi_table_attr_list);
--static struct kobject tables_kobj;
-+static struct kobject *tables_kobj;
+-	pr_debug("bound device '%s' to driver '%s'\n",
+-		 dev->bus_id, dev->driver->name);
++	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->bus_id,
++		 __FUNCTION__, dev->driver->name);
  
- struct acpi_table_attr {
- 	struct bin_attribute attr;
-@@ -135,11 +135,9 @@ static int acpi_system_sysfs_init(void)
- 	int table_index = 0;
- 	int result;
+ 	if (dev->bus)
+-		blocking_notifier_call_chain(&dev->bus->bus_notifier,
++		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ 					     BUS_NOTIFY_BOUND_DRIVER, dev);
  
--	tables_kobj.parent = &acpi_subsys.kobj;
--	kobject_set_name(&tables_kobj, "tables");
--	result = kobject_register(&tables_kobj);
--	if (result)
--		return result;
-+	tables_kobj = kobject_create_and_add("tables", acpi_kobj);
-+	if (!tables_kobj)
-+		return -ENOMEM;
+-	klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
++	klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices);
+ }
  
- 	do {
- 		result = acpi_get_table_by_index(table_index, &table_header);
-@@ -153,7 +151,7 @@ static int acpi_system_sysfs_init(void)
+ static int driver_sysfs_add(struct device *dev)
+ {
+ 	int ret;
  
- 			acpi_table_attr_init(table_attr, table_header);
- 			result =
--			    sysfs_create_bin_file(&tables_kobj,
-+			    sysfs_create_bin_file(tables_kobj,
- 						  &table_attr->attr);
- 			if (result) {
- 				kfree(table_attr);
-@@ -163,6 +161,7 @@ static int acpi_system_sysfs_init(void)
- 					      &acpi_table_attr_list);
- 		}
- 	} while (!result);
-+	kobject_uevent(tables_kobj, KOBJ_ADD);
+-	ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
++	ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
+ 			  kobject_name(&dev->kobj));
+ 	if (ret == 0) {
+-		ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
++		ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
+ 					"driver");
+ 		if (ret)
+-			sysfs_remove_link(&dev->driver->kobj,
++			sysfs_remove_link(&dev->driver->p->kobj,
+ 					kobject_name(&dev->kobj));
+ 	}
+ 	return ret;
+@@ -65,24 +65,24 @@ static void driver_sysfs_remove(struct device *dev)
+ 	struct device_driver *drv = dev->driver;
  
- 	return 0;
+ 	if (drv) {
+-		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
++		sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
+ 		sysfs_remove_link(&dev->kobj, "driver");
+ 	}
  }
-diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
-index ba63619..ba8f7f4 100644
---- a/drivers/ata/Kconfig
-+++ b/drivers/ata/Kconfig
-@@ -69,7 +69,7 @@ config ATA_PIIX
  
- config SATA_MV
- 	tristate "Marvell SATA support (HIGHLY EXPERIMENTAL)"
--	depends on PCI && EXPERIMENTAL
-+	depends on EXPERIMENTAL
- 	help
- 	  This option enables support for the Marvell Serial ATA family.
- 	  Currently supports 88SX[56]0[48][01] chips.
-@@ -184,7 +184,7 @@ config PATA_ACPI
+ /**
+- *	device_bind_driver - bind a driver to one device.
+- *	@dev:	device.
++ * device_bind_driver - bind a driver to one device.
++ * @dev: device.
+  *
+- *	Allow manual attachment of a driver to a device.
+- *	Caller must have already set @dev->driver.
++ * Allow manual attachment of a driver to a device.
++ * Caller must have already set @dev->driver.
+  *
+- *	Note that this does not modify the bus reference count
+- *	nor take the bus's rwsem. Please verify those are accounted
+- *	for before calling this. (It is ok to call with no other effort
+- *	from a driver's probe() method.)
++ * Note that this does not modify the bus reference count
++ * nor take the bus's rwsem. Please verify those are accounted
++ * for before calling this. (It is ok to call with no other effort
++ * from a driver's probe() method.)
+  *
+- *	This function must be called with @dev->sem held.
++ * This function must be called with @dev->sem held.
+  */
+ int device_bind_driver(struct device *dev)
+ {
+@@ -93,6 +93,7 @@ int device_bind_driver(struct device *dev)
+ 		driver_bound(dev);
+ 	return ret;
+ }
++EXPORT_SYMBOL_GPL(device_bind_driver);
  
- config SATA_FSL
- 	tristate "Freescale 3.0Gbps SATA support"
--	depends on PPC_MPC837x
-+	depends on FSL_SOC
- 	help
- 	  This option enables support for Freescale 3.0Gbps SATA controller.
- 	  It can be found on MPC837x and MPC8315.
-@@ -459,6 +459,15 @@ config PATA_NETCELL
+ static atomic_t probe_count = ATOMIC_INIT(0);
+ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
+@@ -102,8 +103,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
+ 	int ret = 0;
  
- 	  If unsure, say N.
+ 	atomic_inc(&probe_count);
+-	pr_debug("%s: Probing driver %s with device %s\n",
+-		 drv->bus->name, drv->name, dev->bus_id);
++	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
++		 drv->bus->name, __FUNCTION__, drv->name, dev->bus_id);
+ 	WARN_ON(!list_empty(&dev->devres_head));
  
-+config PATA_NINJA32
-+	tristate "Ninja32/Delkin Cardbus ATA support (Experimental)"
-+	depends on PCI && EXPERIMENTAL
-+	help
-+	  This option enables support for the Ninja32, Delkin and
-+	  possibly other brands of Cardbus ATA adapter
-+
-+	  If unsure, say N.
-+
- config PATA_NS87410
- 	tristate "Nat Semi NS87410 PATA support (Experimental)"
- 	depends on PCI && EXPERIMENTAL
-@@ -607,13 +616,23 @@ config PATA_WINBOND_VLB
+ 	dev->driver = drv;
+@@ -125,8 +126,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
  
- config PATA_PLATFORM
- 	tristate "Generic platform device PATA support"
--	depends on EMBEDDED || ARCH_RPC
-+	depends on EMBEDDED || ARCH_RPC || PPC
- 	help
- 	  This option enables support for generic directly connected ATA
- 	  devices commonly found on embedded systems.
+ 	driver_bound(dev);
+ 	ret = 1;
+-	pr_debug("%s: Bound Device %s to Driver %s\n",
+-		 drv->bus->name, dev->bus_id, drv->name);
++	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
++		 drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
+ 	goto done;
  
- 	  If unsure, say N.
+ probe_failed:
+@@ -183,7 +184,7 @@ int driver_probe_done(void)
+  * This function must be called with @dev->sem held.  When called for a
+  * USB interface, @dev->parent->sem must be held as well.
+  */
+-int driver_probe_device(struct device_driver * drv, struct device * dev)
++int driver_probe_device(struct device_driver *drv, struct device *dev)
+ {
+ 	int ret = 0;
  
-+config PATA_OF_PLATFORM
-+	tristate "OpenFirmware platform device PATA support"
-+	depends on PATA_PLATFORM && PPC_OF
-+	help
-+	  This option enables support for generic directly connected ATA
-+	  devices commonly found on embedded systems with OpenFirmware
-+	  bindings.
-+
-+	  If unsure, say N.
-+
- config PATA_ICSIDE
- 	tristate "Acorn ICS PATA support"
- 	depends on ARM && ARCH_ACORN
-diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
-index b13feb2..701651e 100644
---- a/drivers/ata/Makefile
-+++ b/drivers/ata/Makefile
-@@ -41,6 +41,7 @@ obj-$(CONFIG_PATA_IT821X)	+= pata_it821x.o
- obj-$(CONFIG_PATA_IT8213)	+= pata_it8213.o
- obj-$(CONFIG_PATA_JMICRON)	+= pata_jmicron.o
- obj-$(CONFIG_PATA_NETCELL)	+= pata_netcell.o
-+obj-$(CONFIG_PATA_NINJA32)	+= pata_ninja32.o
- obj-$(CONFIG_PATA_NS87410)	+= pata_ns87410.o
- obj-$(CONFIG_PATA_NS87415)	+= pata_ns87415.o
- obj-$(CONFIG_PATA_OPTI)		+= pata_opti.o
-@@ -67,6 +68,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF)	+= pata_ixp4xx_cf.o
- obj-$(CONFIG_PATA_SCC)		+= pata_scc.o
- obj-$(CONFIG_PATA_BF54X)	+= pata_bf54x.o
- obj-$(CONFIG_PATA_PLATFORM)	+= pata_platform.o
-+obj-$(CONFIG_PATA_OF_PLATFORM)	+= pata_of_platform.o
- obj-$(CONFIG_PATA_ICSIDE)	+= pata_icside.o
- # Should be last but two libata driver
- obj-$(CONFIG_PATA_ACPI)		+= pata_acpi.o
-diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
-index 54f38c2..27c8d56 100644
---- a/drivers/ata/ahci.c
-+++ b/drivers/ata/ahci.c
-@@ -198,18 +198,18 @@ enum {
- };
+@@ -192,8 +193,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
+ 	if (drv->bus->match && !drv->bus->match(dev, drv))
+ 		goto done;
  
- struct ahci_cmd_hdr {
--	u32			opts;
--	u32			status;
--	u32			tbl_addr;
--	u32			tbl_addr_hi;
--	u32			reserved[4];
-+	__le32			opts;
-+	__le32			status;
-+	__le32			tbl_addr;
-+	__le32			tbl_addr_hi;
-+	__le32			reserved[4];
- };
+-	pr_debug("%s: Matched Device %s with Driver %s\n",
+-		 drv->bus->name, dev->bus_id, drv->name);
++	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
++		 drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
  
- struct ahci_sg {
--	u32			addr;
--	u32			addr_hi;
--	u32			reserved;
--	u32			flags_size;
-+	__le32			addr;
-+	__le32			addr_hi;
-+	__le32			reserved;
-+	__le32			flags_size;
- };
+ 	ret = really_probe(dev, drv);
  
- struct ahci_host_priv {
-@@ -475,6 +475,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
- 	{ PCI_VDEVICE(INTEL, 0x294e), board_ahci }, /* ICH9M */
- 	{ PCI_VDEVICE(INTEL, 0x502a), board_ahci }, /* Tolapai */
- 	{ PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */
-+	{ PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */
-+	{ PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */
+@@ -201,27 +202,27 @@ done:
+ 	return ret;
+ }
  
- 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
- 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-@@ -597,6 +599,20 @@ static inline void __iomem *ahci_port_base(struct ata_port *ap)
- 	return __ahci_port_base(ap->host, ap->port_no);
+-static int __device_attach(struct device_driver * drv, void * data)
++static int __device_attach(struct device_driver *drv, void *data)
+ {
+-	struct device * dev = data;
++	struct device *dev = data;
+ 	return driver_probe_device(drv, dev);
  }
  
-+static void ahci_enable_ahci(void __iomem *mmio)
-+{
-+	u32 tmp;
-+
-+	/* turn on AHCI_EN */
-+	tmp = readl(mmio + HOST_CTL);
-+	if (!(tmp & HOST_AHCI_EN)) {
-+		tmp |= HOST_AHCI_EN;
-+		writel(tmp, mmio + HOST_CTL);
-+		tmp = readl(mmio + HOST_CTL);	/* flush && sanity check */
-+		WARN_ON(!(tmp & HOST_AHCI_EN));
-+	}
-+}
-+
  /**
-  *	ahci_save_initial_config - Save and fixup initial config values
-  *	@pdev: target PCI device
-@@ -619,6 +635,9 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
- 	u32 cap, port_map;
- 	int i;
- 
-+	/* make sure AHCI mode is enabled before accessing CAP */
-+	ahci_enable_ahci(mmio);
-+
- 	/* Values prefixed with saved_ are written back to host after
- 	 * reset.  Values without are used for driver operation.
- 	 */
-@@ -1036,19 +1055,17 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
- static int ahci_reset_controller(struct ata_host *host)
+- *	device_attach - try to attach device to a driver.
+- *	@dev:	device.
++ * device_attach - try to attach device to a driver.
++ * @dev: device.
+  *
+- *	Walk the list of drivers that the bus has and call
+- *	driver_probe_device() for each pair. If a compatible
+- *	pair is found, break out and return.
++ * Walk the list of drivers that the bus has and call
++ * driver_probe_device() for each pair. If a compatible
++ * pair is found, break out and return.
+  *
+- *	Returns 1 if the device was bound to a driver;
+- *	0 if no matching device was found;
+- *	-ENODEV if the device is not registered.
++ * Returns 1 if the device was bound to a driver;
++ * 0 if no matching device was found;
++ * -ENODEV if the device is not registered.
+  *
+- *	When called for a USB interface, @dev->parent->sem must be held.
++ * When called for a USB interface, @dev->parent->sem must be held.
+  */
+-int device_attach(struct device * dev)
++int device_attach(struct device *dev)
  {
- 	struct pci_dev *pdev = to_pci_dev(host->dev);
-+	struct ahci_host_priv *hpriv = host->private_data;
- 	void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
- 	u32 tmp;
- 
- 	/* we must be in AHCI mode, before using anything
- 	 * AHCI-specific, such as HOST_RESET.
- 	 */
--	tmp = readl(mmio + HOST_CTL);
--	if (!(tmp & HOST_AHCI_EN)) {
--		tmp |= HOST_AHCI_EN;
--		writel(tmp, mmio + HOST_CTL);
--	}
-+	ahci_enable_ahci(mmio);
+ 	int ret = 0;
  
- 	/* global controller reset */
-+	tmp = readl(mmio + HOST_CTL);
- 	if ((tmp & HOST_RESET) == 0) {
- 		writel(tmp | HOST_RESET, mmio + HOST_CTL);
- 		readl(mmio + HOST_CTL); /* flush */
-@@ -1067,8 +1084,7 @@ static int ahci_reset_controller(struct ata_host *host)
- 	}
+@@ -240,10 +241,11 @@ int device_attach(struct device * dev)
+ 	up(&dev->sem);
+ 	return ret;
+ }
++EXPORT_SYMBOL_GPL(device_attach);
  
- 	/* turn on AHCI mode */
--	writel(HOST_AHCI_EN, mmio + HOST_CTL);
--	(void) readl(mmio + HOST_CTL);	/* flush */
-+	ahci_enable_ahci(mmio);
+-static int __driver_attach(struct device * dev, void * data)
++static int __driver_attach(struct device *dev, void *data)
+ {
+-	struct device_driver * drv = data;
++	struct device_driver *drv = data;
  
- 	/* some registers might be cleared on reset.  restore initial values */
- 	ahci_restore_initial_config(host);
-@@ -1078,8 +1094,10 @@ static int ahci_reset_controller(struct ata_host *host)
+ 	/*
+ 	 * Lock device and try to bind to it. We drop the error
+@@ -268,35 +270,35 @@ static int __driver_attach(struct device * dev, void * data)
+ }
  
- 		/* configure PCS */
- 		pci_read_config_word(pdev, 0x92, &tmp16);
--		tmp16 |= 0xf;
--		pci_write_config_word(pdev, 0x92, tmp16);
-+		if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
-+			tmp16 |= hpriv->port_map;
-+			pci_write_config_word(pdev, 0x92, tmp16);
-+		}
- 	}
+ /**
+- *	driver_attach - try to bind driver to devices.
+- *	@drv:	driver.
++ * driver_attach - try to bind driver to devices.
++ * @drv: driver.
+  *
+- *	Walk the list of devices that the bus has on it and try to
+- *	match the driver with each one.  If driver_probe_device()
+- *	returns 0 and the @dev->driver is set, we've found a
+- *	compatible pair.
++ * Walk the list of devices that the bus has on it and try to
++ * match the driver with each one.  If driver_probe_device()
++ * returns 0 and the @dev->driver is set, we've found a
++ * compatible pair.
+  */
+-int driver_attach(struct device_driver * drv)
++int driver_attach(struct device_driver *drv)
+ {
+ 	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+ }
++EXPORT_SYMBOL_GPL(driver_attach);
  
- 	return 0;
-@@ -1480,35 +1498,31 @@ static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
- static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl)
+ /*
+- *	__device_release_driver() must be called with @dev->sem held.
+- *	When called for a USB interface, @dev->parent->sem must be held as well.
++ * __device_release_driver() must be called with @dev->sem held.
++ * When called for a USB interface, @dev->parent->sem must be held as well.
+  */
+-static void __device_release_driver(struct device * dev)
++static void __device_release_driver(struct device *dev)
  {
- 	struct scatterlist *sg;
--	struct ahci_sg *ahci_sg;
--	unsigned int n_sg = 0;
-+	struct ahci_sg *ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
-+	unsigned int si;
+-	struct device_driver * drv;
++	struct device_driver *drv;
  
- 	VPRINTK("ENTER\n");
+-	drv = get_driver(dev->driver);
++	drv = dev->driver;
+ 	if (drv) {
+ 		driver_sysfs_remove(dev);
+ 		sysfs_remove_link(&dev->kobj, "driver");
+-		klist_remove(&dev->knode_driver);
  
- 	/*
- 	 * Next, the S/G list.
- 	 */
--	ahci_sg = cmd_tbl + AHCI_CMD_TBL_HDR_SZ;
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		dma_addr_t addr = sg_dma_address(sg);
- 		u32 sg_len = sg_dma_len(sg);
+ 		if (dev->bus)
+-			blocking_notifier_call_chain(&dev->bus->bus_notifier,
++			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ 						     BUS_NOTIFY_UNBIND_DRIVER,
+ 						     dev);
  
--		ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
--		ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
--		ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
--
--		ahci_sg++;
--		n_sg++;
-+		ahci_sg[si].addr = cpu_to_le32(addr & 0xffffffff);
-+		ahci_sg[si].addr_hi = cpu_to_le32((addr >> 16) >> 16);
-+		ahci_sg[si].flags_size = cpu_to_le32(sg_len - 1);
+@@ -306,18 +308,18 @@ static void __device_release_driver(struct device * dev)
+ 			drv->remove(dev);
+ 		devres_release_all(dev);
+ 		dev->driver = NULL;
+-		put_driver(drv);
++		klist_remove(&dev->knode_driver);
  	}
- 
--	return n_sg;
-+	return si;
  }
  
- static void ahci_qc_prep(struct ata_queued_cmd *qc)
+ /**
+- *	device_release_driver - manually detach device from driver.
+- *	@dev:	device.
++ * device_release_driver - manually detach device from driver.
++ * @dev: device.
+  *
+- *	Manually detach device from driver.
+- *	When called for a USB interface, @dev->parent->sem must be held.
++ * Manually detach device from driver.
++ * When called for a USB interface, @dev->parent->sem must be held.
+  */
+-void device_release_driver(struct device * dev)
++void device_release_driver(struct device *dev)
  {
- 	struct ata_port *ap = qc->ap;
- 	struct ahci_port_priv *pp = ap->private_data;
--	int is_atapi = is_atapi_taskfile(&qc->tf);
-+	int is_atapi = ata_is_atapi(qc->tf.protocol);
- 	void *cmd_tbl;
- 	u32 opts;
- 	const u32 cmd_fis_len = 5; /* five dwords */
-diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
-index 9032998..2053420 100644
---- a/drivers/ata/ata_generic.c
-+++ b/drivers/ata/ata_generic.c
-@@ -26,7 +26,7 @@
- #include <linux/libata.h>
- 
- #define DRV_NAME "ata_generic"
--#define DRV_VERSION "0.2.13"
-+#define DRV_VERSION "0.2.15"
- 
- /*
-  *	A generic parallel ATA driver using libata
-@@ -48,27 +48,47 @@ static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
- 	struct ata_port *ap = link->ap;
- 	int dma_enabled = 0;
- 	struct ata_device *dev;
-+	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
+ 	/*
+ 	 * If anyone calls device_release_driver() recursively from
+@@ -328,26 +330,26 @@ void device_release_driver(struct device * dev)
+ 	__device_release_driver(dev);
+ 	up(&dev->sem);
+ }
+-
++EXPORT_SYMBOL_GPL(device_release_driver);
  
- 	/* Bits 5 and 6 indicate if DMA is active on master/slave */
- 	if (ap->ioaddr.bmdma_addr)
- 		dma_enabled = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
+ /**
+  * driver_detach - detach driver from all devices it controls.
+  * @drv: driver.
+  */
+-void driver_detach(struct device_driver * drv)
++void driver_detach(struct device_driver *drv)
+ {
+-	struct device * dev;
++	struct device *dev;
  
-+	if (pdev->vendor == PCI_VENDOR_ID_CENATEK)
-+		dma_enabled = 0xFF;
-+
- 	ata_link_for_each_dev(dev, link) {
--		if (ata_dev_enabled(dev)) {
--			/* We don't really care */
--			dev->pio_mode = XFER_PIO_0;
--			dev->dma_mode = XFER_MW_DMA_0;
--			/* We do need the right mode information for DMA or PIO
--			   and this comes from the current configuration flags */
--			if (dma_enabled & (1 << (5 + dev->devno))) {
--				ata_id_to_dma_mode(dev, XFER_MW_DMA_0);
--				dev->flags &= ~ATA_DFLAG_PIO;
--			} else {
--				ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
--				dev->xfer_mode = XFER_PIO_0;
--				dev->xfer_shift = ATA_SHIFT_PIO;
--				dev->flags |= ATA_DFLAG_PIO;
-+		if (!ata_dev_enabled(dev))
-+			continue;
-+
-+		/* We don't really care */
-+		dev->pio_mode = XFER_PIO_0;
-+		dev->dma_mode = XFER_MW_DMA_0;
-+		/* We do need the right mode information for DMA or PIO
-+		   and this comes from the current configuration flags */
-+		if (dma_enabled & (1 << (5 + dev->devno))) {
-+			unsigned int xfer_mask = ata_id_xfermask(dev->id);
-+			const char *name;
-+
-+			if (xfer_mask & (ATA_MASK_MWDMA | ATA_MASK_UDMA))
-+				name = ata_mode_string(xfer_mask);
-+			else {
-+				/* SWDMA perhaps? */
-+				name = "DMA";
-+				xfer_mask |= ata_xfer_mode2mask(XFER_MW_DMA_0);
- 			}
-+
-+			ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
-+				       name);
-+
-+			dev->xfer_mode = ata_xfer_mask2mode(xfer_mask);
-+			dev->xfer_shift = ata_xfer_mode2shift(dev->xfer_mode);
-+			dev->flags &= ~ATA_DFLAG_PIO;
-+		} else {
-+			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
-+			dev->xfer_mode = XFER_PIO_0;
-+			dev->xfer_shift = ATA_SHIFT_PIO;
-+			dev->flags |= ATA_DFLAG_PIO;
+ 	for (;;) {
+-		spin_lock(&drv->klist_devices.k_lock);
+-		if (list_empty(&drv->klist_devices.k_list)) {
+-			spin_unlock(&drv->klist_devices.k_lock);
++		spin_lock(&drv->p->klist_devices.k_lock);
++		if (list_empty(&drv->p->klist_devices.k_list)) {
++			spin_unlock(&drv->p->klist_devices.k_lock);
+ 			break;
  		}
- 	}
- 	return 0;
-@@ -185,6 +205,7 @@ static struct pci_device_id ata_generic[] = {
- 	{ PCI_DEVICE(PCI_VENDOR_ID_HINT,   PCI_DEVICE_ID_HINT_VXPROII_IDE), },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C561), },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_OPTI,   PCI_DEVICE_ID_OPTI_82C558), },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_CENATEK,PCI_DEVICE_ID_CENATEK_IDE), },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO), },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_1), },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA,PCI_DEVICE_ID_TOSHIBA_PICCOLO_2),  },
-diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
-index b406b39..47892e6 100644
---- a/drivers/ata/ata_piix.c
-+++ b/drivers/ata/ata_piix.c
-@@ -101,39 +101,21 @@ enum {
- 	ICH5_PMR		= 0x90, /* port mapping register */
- 	ICH5_PCS		= 0x92,	/* port control and status */
- 	PIIX_SCC		= 0x0A, /* sub-class code register */
-+	PIIX_SIDPR_BAR		= 5,
-+	PIIX_SIDPR_LEN		= 16,
-+	PIIX_SIDPR_IDX		= 0,
-+	PIIX_SIDPR_DATA		= 4,
- 
--	PIIX_FLAG_SCR		= (1 << 26), /* SCR available */
- 	PIIX_FLAG_AHCI		= (1 << 27), /* AHCI possible */
- 	PIIX_FLAG_CHECKINTR	= (1 << 28), /* make sure PCI INTx enabled */
-+	PIIX_FLAG_SIDPR		= (1 << 29), /* SATA idx/data pair regs */
- 
- 	PIIX_PATA_FLAGS		= ATA_FLAG_SLAVE_POSS,
- 	PIIX_SATA_FLAGS		= ATA_FLAG_SATA | PIIX_FLAG_CHECKINTR,
+-		dev = list_entry(drv->klist_devices.k_list.prev,
++		dev = list_entry(drv->p->klist_devices.k_list.prev,
+ 				struct device, knode_driver.n_node);
+ 		get_device(dev);
+-		spin_unlock(&drv->klist_devices.k_lock);
++		spin_unlock(&drv->p->klist_devices.k_lock);
  
--	/* combined mode.  if set, PATA is channel 0.
--	 * if clear, PATA is channel 1.
+ 		if (dev->parent)	/* Needed for USB */
+ 			down(&dev->parent->sem);
+@@ -360,9 +362,3 @@ void driver_detach(struct device_driver * drv)
+ 		put_device(dev);
+ 	}
+ }
+-
+-EXPORT_SYMBOL_GPL(device_bind_driver);
+-EXPORT_SYMBOL_GPL(device_release_driver);
+-EXPORT_SYMBOL_GPL(device_attach);
+-EXPORT_SYMBOL_GPL(driver_attach);
+-
+diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
+deleted file mode 100644
+index b5034dc..0000000
+--- a/drivers/base/dmapool.c
++++ /dev/null
+@@ -1,481 +0,0 @@
+-
+-#include <linux/device.h>
+-#include <linux/mm.h>
+-#include <asm/io.h>		/* Needed for i386 to build */
+-#include <linux/dma-mapping.h>
+-#include <linux/dmapool.h>
+-#include <linux/slab.h>
+-#include <linux/module.h>
+-#include <linux/poison.h>
+-#include <linux/sched.h>
+-
+-/*
+- * Pool allocator ... wraps the dma_alloc_coherent page allocator, so
+- * small blocks are easily used by drivers for bus mastering controllers.
+- * This should probably be sharing the guts of the slab allocator.
+- */
+-
+-struct dma_pool {	/* the pool */
+-	struct list_head	page_list;
+-	spinlock_t		lock;
+-	size_t			blocks_per_page;
+-	size_t			size;
+-	struct device		*dev;
+-	size_t			allocation;
+-	char			name [32];
+-	wait_queue_head_t	waitq;
+-	struct list_head	pools;
+-};
+-
+-struct dma_page {	/* cacheable header for 'allocation' bytes */
+-	struct list_head	page_list;
+-	void			*vaddr;
+-	dma_addr_t		dma;
+-	unsigned		in_use;
+-	unsigned long		bitmap [0];
+-};
+-
+-#define	POOL_TIMEOUT_JIFFIES	((100 /* msec */ * HZ) / 1000)
+-
+-static DEFINE_MUTEX (pools_lock);
+-
+-static ssize_t
+-show_pools (struct device *dev, struct device_attribute *attr, char *buf)
+-{
+-	unsigned temp;
+-	unsigned size;
+-	char *next;
+-	struct dma_page *page;
+-	struct dma_pool *pool;
+-
+-	next = buf;
+-	size = PAGE_SIZE;
+-
+-	temp = scnprintf(next, size, "poolinfo - 0.1\n");
+-	size -= temp;
+-	next += temp;
+-
+-	mutex_lock(&pools_lock);
+-	list_for_each_entry(pool, &dev->dma_pools, pools) {
+-		unsigned pages = 0;
+-		unsigned blocks = 0;
+-
+-		list_for_each_entry(page, &pool->page_list, page_list) {
+-			pages++;
+-			blocks += page->in_use;
+-		}
+-
+-		/* per-pool info, no real statistics yet */
+-		temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n",
+-				pool->name,
+-				blocks, pages * pool->blocks_per_page,
+-				pool->size, pages);
+-		size -= temp;
+-		next += temp;
+-	}
+-	mutex_unlock(&pools_lock);
+-
+-	return PAGE_SIZE - size;
+-}
+-static DEVICE_ATTR (pools, S_IRUGO, show_pools, NULL);
+-
+-/**
+- * dma_pool_create - Creates a pool of consistent memory blocks, for dma.
+- * @name: name of pool, for diagnostics
+- * @dev: device that will be doing the DMA
+- * @size: size of the blocks in this pool.
+- * @align: alignment requirement for blocks; must be a power of two
+- * @allocation: returned blocks won't cross this boundary (or zero)
+- * Context: !in_interrupt()
+- *
+- * Returns a dma allocation pool with the requested characteristics, or
+- * null if one can't be created.  Given one of these pools, dma_pool_alloc()
+- * may be used to allocate memory.  Such memory will all have "consistent"
+- * DMA mappings, accessible by the device and its driver without using
+- * cache flushing primitives.  The actual size of blocks allocated may be
+- * larger than requested because of alignment.
+- *
+- * If allocation is nonzero, objects returned from dma_pool_alloc() won't
+- * cross that size boundary.  This is useful for devices which have
+- * addressing restrictions on individual DMA transfers, such as not crossing
+- * boundaries of 4KBytes.
+- */
+-struct dma_pool *
+-dma_pool_create (const char *name, struct device *dev,
+-	size_t size, size_t align, size_t allocation)
+-{
+-	struct dma_pool		*retval;
+-
+-	if (align == 0)
+-		align = 1;
+-	if (size == 0)
+-		return NULL;
+-	else if (size < align)
+-		size = align;
+-	else if ((size % align) != 0) {
+-		size += align + 1;
+-		size &= ~(align - 1);
+-	}
+-
+-	if (allocation == 0) {
+-		if (PAGE_SIZE < size)
+-			allocation = size;
+-		else
+-			allocation = PAGE_SIZE;
+-		// FIXME: round up for less fragmentation
+-	} else if (allocation < size)
+-		return NULL;
+-
+-	if (!(retval = kmalloc_node (sizeof *retval, GFP_KERNEL, dev_to_node(dev))))
+-		return retval;
+-
+-	strlcpy (retval->name, name, sizeof retval->name);
+-
+-	retval->dev = dev;
+-
+-	INIT_LIST_HEAD (&retval->page_list);
+-	spin_lock_init (&retval->lock);
+-	retval->size = size;
+-	retval->allocation = allocation;
+-	retval->blocks_per_page = allocation / size;
+-	init_waitqueue_head (&retval->waitq);
+-
+-	if (dev) {
+-		int ret;
+-
+-		mutex_lock(&pools_lock);
+-		if (list_empty (&dev->dma_pools))
+-			ret = device_create_file (dev, &dev_attr_pools);
+-		else
+-			ret = 0;
+-		/* note:  not currently insisting "name" be unique */
+-		if (!ret)
+-			list_add (&retval->pools, &dev->dma_pools);
+-		else {
+-			kfree(retval);
+-			retval = NULL;
+-		}
+-		mutex_unlock(&pools_lock);
+-	} else
+-		INIT_LIST_HEAD (&retval->pools);
+-
+-	return retval;
+-}
+-
+-
+-static struct dma_page *
+-pool_alloc_page (struct dma_pool *pool, gfp_t mem_flags)
+-{
+-	struct dma_page	*page;
+-	int		mapsize;
+-
+-	mapsize = pool->blocks_per_page;
+-	mapsize = (mapsize + BITS_PER_LONG - 1) / BITS_PER_LONG;
+-	mapsize *= sizeof (long);
+-
+-	page = kmalloc(mapsize + sizeof *page, mem_flags);
+-	if (!page)
+-		return NULL;
+-	page->vaddr = dma_alloc_coherent (pool->dev,
+-					    pool->allocation,
+-					    &page->dma,
+-					    mem_flags);
+-	if (page->vaddr) {
+-		memset (page->bitmap, 0xff, mapsize);	// bit set == free
+-#ifdef	CONFIG_DEBUG_SLAB
+-		memset (page->vaddr, POOL_POISON_FREED, pool->allocation);
+-#endif
+-		list_add (&page->page_list, &pool->page_list);
+-		page->in_use = 0;
+-	} else {
+-		kfree (page);
+-		page = NULL;
+-	}
+-	return page;
+-}
+-
+-
+-static inline int
+-is_page_busy (int blocks, unsigned long *bitmap)
+-{
+-	while (blocks > 0) {
+-		if (*bitmap++ != ~0UL)
+-			return 1;
+-		blocks -= BITS_PER_LONG;
+-	}
+-	return 0;
+-}
+-
+-static void
+-pool_free_page (struct dma_pool *pool, struct dma_page *page)
+-{
+-	dma_addr_t	dma = page->dma;
+-
+-#ifdef	CONFIG_DEBUG_SLAB
+-	memset (page->vaddr, POOL_POISON_FREED, pool->allocation);
+-#endif
+-	dma_free_coherent (pool->dev, pool->allocation, page->vaddr, dma);
+-	list_del (&page->page_list);
+-	kfree (page);
+-}
+-
+-
+-/**
+- * dma_pool_destroy - destroys a pool of dma memory blocks.
+- * @pool: dma pool that will be destroyed
+- * Context: !in_interrupt()
+- *
+- * Caller guarantees that no more memory from the pool is in use,
+- * and that nothing will try to use the pool after this call.
+- */
+-void
+-dma_pool_destroy (struct dma_pool *pool)
+-{
+-	mutex_lock(&pools_lock);
+-	list_del (&pool->pools);
+-	if (pool->dev && list_empty (&pool->dev->dma_pools))
+-		device_remove_file (pool->dev, &dev_attr_pools);
+-	mutex_unlock(&pools_lock);
+-
+-	while (!list_empty (&pool->page_list)) {
+-		struct dma_page		*page;
+-		page = list_entry (pool->page_list.next,
+-				struct dma_page, page_list);
+-		if (is_page_busy (pool->blocks_per_page, page->bitmap)) {
+-			if (pool->dev)
+-				dev_err(pool->dev, "dma_pool_destroy %s, %p busy\n",
+-					pool->name, page->vaddr);
+-			else
+-				printk (KERN_ERR "dma_pool_destroy %s, %p busy\n",
+-					pool->name, page->vaddr);
+-			/* leak the still-in-use consistent memory */
+-			list_del (&page->page_list);
+-			kfree (page);
+-		} else
+-			pool_free_page (pool, page);
+-	}
+-
+-	kfree (pool);
+-}
+-
+-
+-/**
+- * dma_pool_alloc - get a block of consistent memory
+- * @pool: dma pool that will produce the block
+- * @mem_flags: GFP_* bitmask
+- * @handle: pointer to dma address of block
+- *
+- * This returns the kernel virtual address of a currently unused block,
+- * and reports its dma address through the handle.
+- * If such a memory block can't be allocated, null is returned.
+- */
+-void *
+-dma_pool_alloc (struct dma_pool *pool, gfp_t mem_flags, dma_addr_t *handle)
+-{
+-	unsigned long		flags;
+-	struct dma_page		*page;
+-	int			map, block;
+-	size_t			offset;
+-	void			*retval;
+-
+-restart:
+-	spin_lock_irqsave (&pool->lock, flags);
+-	list_for_each_entry(page, &pool->page_list, page_list) {
+-		int		i;
+-		/* only cachable accesses here ... */
+-		for (map = 0, i = 0;
+-				i < pool->blocks_per_page;
+-				i += BITS_PER_LONG, map++) {
+-			if (page->bitmap [map] == 0)
+-				continue;
+-			block = ffz (~ page->bitmap [map]);
+-			if ((i + block) < pool->blocks_per_page) {
+-				clear_bit (block, &page->bitmap [map]);
+-				offset = (BITS_PER_LONG * map) + block;
+-				offset *= pool->size;
+-				goto ready;
+-			}
+-		}
+-	}
+-	if (!(page = pool_alloc_page (pool, GFP_ATOMIC))) {
+-		if (mem_flags & __GFP_WAIT) {
+-			DECLARE_WAITQUEUE (wait, current);
+-
+-			__set_current_state(TASK_INTERRUPTIBLE);
+-			add_wait_queue (&pool->waitq, &wait);
+-			spin_unlock_irqrestore (&pool->lock, flags);
+-
+-			schedule_timeout (POOL_TIMEOUT_JIFFIES);
+-
+-			remove_wait_queue (&pool->waitq, &wait);
+-			goto restart;
+-		}
+-		retval = NULL;
+-		goto done;
+-	}
+-
+-	clear_bit (0, &page->bitmap [0]);
+-	offset = 0;
+-ready:
+-	page->in_use++;
+-	retval = offset + page->vaddr;
+-	*handle = offset + page->dma;
+-#ifdef	CONFIG_DEBUG_SLAB
+-	memset (retval, POOL_POISON_ALLOCATED, pool->size);
+-#endif
+-done:
+-	spin_unlock_irqrestore (&pool->lock, flags);
+-	return retval;
+-}
+-
+-
+-static struct dma_page *
+-pool_find_page (struct dma_pool *pool, dma_addr_t dma)
+-{
+-	unsigned long		flags;
+-	struct dma_page		*page;
+-
+-	spin_lock_irqsave (&pool->lock, flags);
+-	list_for_each_entry(page, &pool->page_list, page_list) {
+-		if (dma < page->dma)
+-			continue;
+-		if (dma < (page->dma + pool->allocation))
+-			goto done;
+-	}
+-	page = NULL;
+-done:
+-	spin_unlock_irqrestore (&pool->lock, flags);
+-	return page;
+-}
+-
+-
+-/**
+- * dma_pool_free - put block back into dma pool
+- * @pool: the dma pool holding the block
+- * @vaddr: virtual address of block
+- * @dma: dma address of block
+- *
+- * Caller promises neither device nor driver will again touch this block
+- * unless it is first re-allocated.
+- */
+-void
+-dma_pool_free (struct dma_pool *pool, void *vaddr, dma_addr_t dma)
+-{
+-	struct dma_page		*page;
+-	unsigned long		flags;
+-	int			map, block;
+-
+-	if ((page = pool_find_page(pool, dma)) == NULL) {
+-		if (pool->dev)
+-			dev_err(pool->dev, "dma_pool_free %s, %p/%lx (bad dma)\n",
+-				pool->name, vaddr, (unsigned long) dma);
+-		else
+-			printk (KERN_ERR "dma_pool_free %s, %p/%lx (bad dma)\n",
+-				pool->name, vaddr, (unsigned long) dma);
+-		return;
+-	}
+-
+-	block = dma - page->dma;
+-	block /= pool->size;
+-	map = block / BITS_PER_LONG;
+-	block %= BITS_PER_LONG;
+-
+-#ifdef	CONFIG_DEBUG_SLAB
+-	if (((dma - page->dma) + (void *)page->vaddr) != vaddr) {
+-		if (pool->dev)
+-			dev_err(pool->dev, "dma_pool_free %s, %p (bad vaddr)/%Lx\n",
+-				pool->name, vaddr, (unsigned long long) dma);
+-		else
+-			printk (KERN_ERR "dma_pool_free %s, %p (bad vaddr)/%Lx\n",
+-				pool->name, vaddr, (unsigned long long) dma);
+-		return;
+-	}
+-	if (page->bitmap [map] & (1UL << block)) {
+-		if (pool->dev)
+-			dev_err(pool->dev, "dma_pool_free %s, dma %Lx already free\n",
+-				pool->name, (unsigned long long)dma);
+-		else
+-			printk (KERN_ERR "dma_pool_free %s, dma %Lx already free\n",
+-				pool->name, (unsigned long long)dma);
+-		return;
+-	}
+-	memset (vaddr, POOL_POISON_FREED, pool->size);
+-#endif
+-
+-	spin_lock_irqsave (&pool->lock, flags);
+-	page->in_use--;
+-	set_bit (block, &page->bitmap [map]);
+-	if (waitqueue_active (&pool->waitq))
+-		wake_up (&pool->waitq);
+-	/*
+-	 * Resist a temptation to do
+-	 *    if (!is_page_busy(bpp, page->bitmap)) pool_free_page(pool, page);
+-	 * Better have a few empty pages hang around.
 -	 */
--	PIIX_PORT_ENABLED	= (1 << 0),
--	PIIX_PORT_PRESENT	= (1 << 4),
+-	spin_unlock_irqrestore (&pool->lock, flags);
+-}
 -
- 	PIIX_80C_PRI		= (1 << 5) | (1 << 4),
- 	PIIX_80C_SEC		= (1 << 7) | (1 << 6),
- 
--	/* controller IDs */
--	piix_pata_mwdma		= 0,	/* PIIX3 MWDMA only */
--	piix_pata_33,			/* PIIX4 at 33Mhz */
--	ich_pata_33,			/* ICH up to UDMA 33 only */
--	ich_pata_66,			/* ICH up to 66 Mhz */
--	ich_pata_100,			/* ICH up to UDMA 100 */
--	ich5_sata,
--	ich6_sata,
--	ich6_sata_ahci,
--	ich6m_sata_ahci,
--	ich8_sata_ahci,
--	ich8_2port_sata,
--	ich8m_apple_sata_ahci,		/* locks up on second port enable */
--	tolapai_sata_ahci,
--	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
+-/*
+- * Managed DMA pool
+- */
+-static void dmam_pool_release(struct device *dev, void *res)
+-{
+-	struct dma_pool *pool = *(struct dma_pool **)res;
 -
- 	/* constants for mapping table */
- 	P0			= 0,  /* port 0 */
- 	P1			= 1,  /* port 1 */
-@@ -149,6 +131,24 @@ enum {
- 	PIIX_HOST_BROKEN_SUSPEND = (1 << 24),
- };
+-	dma_pool_destroy(pool);
+-}
+-
+-static int dmam_pool_match(struct device *dev, void *res, void *match_data)
+-{
+-	return *(struct dma_pool **)res == match_data;
+-}
+-
+-/**
+- * dmam_pool_create - Managed dma_pool_create()
+- * @name: name of pool, for diagnostics
+- * @dev: device that will be doing the DMA
+- * @size: size of the blocks in this pool.
+- * @align: alignment requirement for blocks; must be a power of two
+- * @allocation: returned blocks won't cross this boundary (or zero)
+- *
+- * Managed dma_pool_create().  DMA pool created with this function is
+- * automatically destroyed on driver detach.
+- */
+-struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
+-				  size_t size, size_t align, size_t allocation)
+-{
+-	struct dma_pool **ptr, *pool;
+-
+-	ptr = devres_alloc(dmam_pool_release, sizeof(*ptr), GFP_KERNEL);
+-	if (!ptr)
+-		return NULL;
+-
+-	pool = *ptr = dma_pool_create(name, dev, size, align, allocation);
+-	if (pool)
+-		devres_add(dev, ptr);
+-	else
+-		devres_free(ptr);
+-
+-	return pool;
+-}
+-
+-/**
+- * dmam_pool_destroy - Managed dma_pool_destroy()
+- * @pool: dma pool that will be destroyed
+- *
+- * Managed dma_pool_destroy().
+- */
+-void dmam_pool_destroy(struct dma_pool *pool)
+-{
+-	struct device *dev = pool->dev;
+-
+-	dma_pool_destroy(pool);
+-	WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool));
+-}
+-
+-EXPORT_SYMBOL (dma_pool_create);
+-EXPORT_SYMBOL (dma_pool_destroy);
+-EXPORT_SYMBOL (dma_pool_alloc);
+-EXPORT_SYMBOL (dma_pool_free);
+-EXPORT_SYMBOL (dmam_pool_create);
+-EXPORT_SYMBOL (dmam_pool_destroy);
+diff --git a/drivers/base/driver.c b/drivers/base/driver.c
+index eb11475..ba75184 100644
+--- a/drivers/base/driver.c
++++ b/drivers/base/driver.c
+@@ -3,6 +3,8 @@
+  *
+  * Copyright (c) 2002-3 Patrick Mochel
+  * Copyright (c) 2002-3 Open Source Development Labs
++ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
++ * Copyright (c) 2007 Novell Inc.
+  *
+  * This file is released under the GPLv2
+  *
+@@ -15,46 +17,42 @@
+ #include "base.h"
  
-+enum piix_controller_ids {
-+	/* controller IDs */
-+	piix_pata_mwdma,	/* PIIX3 MWDMA only */
-+	piix_pata_33,		/* PIIX4 at 33Mhz */
-+	ich_pata_33,		/* ICH up to UDMA 33 only */
-+	ich_pata_66,		/* ICH up to 66 Mhz */
-+	ich_pata_100,		/* ICH up to UDMA 100 */
-+	ich5_sata,
-+	ich6_sata,
-+	ich6_sata_ahci,
-+	ich6m_sata_ahci,
-+	ich8_sata_ahci,
-+	ich8_2port_sata,
-+	ich8m_apple_sata_ahci,	/* locks up on second port enable */
-+	tolapai_sata_ahci,
-+	piix_pata_vmw,			/* PIIX4 for VMware, spurious DMA_ERR */
-+};
-+
- struct piix_map_db {
- 	const u32 mask;
- 	const u16 port_enable;
-@@ -157,6 +157,7 @@ struct piix_map_db {
+ #define to_dev(node) container_of(node, struct device, driver_list)
+-#define to_drv(obj) container_of(obj, struct device_driver, kobj)
  
- struct piix_host_priv {
- 	const int *map;
-+	void __iomem *sidpr;
- };
  
- static int piix_init_one(struct pci_dev *pdev,
-@@ -167,6 +168,9 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
- static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
- static int ich_pata_cable_detect(struct ata_port *ap);
- static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-+static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
-+static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
-+static void piix_sidpr_error_handler(struct ata_port *ap);
- #ifdef CONFIG_PM
- static int piix_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg);
- static int piix_pci_device_resume(struct pci_dev *pdev);
-@@ -263,6 +267,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
- 	{ 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
- 	/* SATA Controller IDE (Tolapai) */
- 	{ 0x8086, 0x5028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, tolapai_sata_ahci },
-+	/* SATA Controller IDE (ICH10) */
-+	{ 0x8086, 0x3a00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
-+	/* SATA Controller IDE (ICH10) */
-+	{ 0x8086, 0x3a06, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
-+	/* SATA Controller IDE (ICH10) */
-+	{ 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci },
-+	/* SATA Controller IDE (ICH10) */
-+	{ 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+-static struct device * next_device(struct klist_iter * i)
++static struct device *next_device(struct klist_iter *i)
+ {
+-	struct klist_node * n = klist_next(i);
++	struct klist_node *n = klist_next(i);
+ 	return n ? container_of(n, struct device, knode_driver) : NULL;
+ }
  
- 	{ }	/* terminate list */
- };
-@@ -321,7 +333,6 @@ static const struct ata_port_operations piix_pata_ops = {
- 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
- 	.cable_detect		= ata_cable_40wire,
+ /**
+- *	driver_for_each_device - Iterator for devices bound to a driver.
+- *	@drv:	Driver we're iterating.
+- *	@start: Device to begin with
+- *	@data:	Data to pass to the callback.
+- *	@fn:	Function to call for each device.
++ * driver_for_each_device - Iterator for devices bound to a driver.
++ * @drv: Driver we're iterating.
++ * @start: Device to begin with
++ * @data: Data to pass to the callback.
++ * @fn: Function to call for each device.
+  *
+- *	Iterate over the @drv's list of devices calling @fn for each one.
++ * Iterate over the @drv's list of devices calling @fn for each one.
+  */
+-
+-int driver_for_each_device(struct device_driver * drv, struct device * start, 
+-			   void * data, int (*fn)(struct device *, void *))
++int driver_for_each_device(struct device_driver *drv, struct device *start,
++			   void *data, int (*fn)(struct device *, void *))
+ {
+ 	struct klist_iter i;
+-	struct device * dev;
++	struct device *dev;
+ 	int error = 0;
  
--	.irq_handler		= ata_interrupt,
- 	.irq_clear		= ata_bmdma_irq_clear,
- 	.irq_on			= ata_irq_on,
+ 	if (!drv)
+ 		return -EINVAL;
  
-@@ -353,7 +364,6 @@ static const struct ata_port_operations ich_pata_ops = {
- 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
- 	.cable_detect		= ich_pata_cable_detect,
+-	klist_iter_init_node(&drv->klist_devices, &i,
++	klist_iter_init_node(&drv->p->klist_devices, &i,
+ 			     start ? &start->knode_driver : NULL);
+ 	while ((dev = next_device(&i)) && !error)
+ 		error = fn(dev, data);
+ 	klist_iter_exit(&i);
+ 	return error;
+ }
+-
+ EXPORT_SYMBOL_GPL(driver_for_each_device);
  
--	.irq_handler		= ata_interrupt,
- 	.irq_clear		= ata_bmdma_irq_clear,
- 	.irq_on			= ata_irq_on,
+-
+ /**
+  * driver_find_device - device iterator for locating a particular device.
+  * @drv: The device's driver
+@@ -70,9 +68,9 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
+  * if it does.  If the callback returns non-zero, this function will
+  * return to the caller and not iterate over any more devices.
+  */
+-struct device * driver_find_device(struct device_driver *drv,
+-				   struct device * start, void * data,
+-				   int (*match)(struct device *, void *))
++struct device *driver_find_device(struct device_driver *drv,
++				  struct device *start, void *data,
++				  int (*match)(struct device *dev, void *data))
+ {
+ 	struct klist_iter i;
+ 	struct device *dev;
+@@ -80,7 +78,7 @@ struct device * driver_find_device(struct device_driver *drv,
+ 	if (!drv)
+ 		return NULL;
  
-@@ -380,7 +390,6 @@ static const struct ata_port_operations piix_sata_ops = {
- 	.error_handler		= ata_bmdma_error_handler,
- 	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
+-	klist_iter_init_node(&drv->klist_devices, &i,
++	klist_iter_init_node(&drv->p->klist_devices, &i,
+ 			     (start ? &start->knode_driver : NULL));
+ 	while ((dev = next_device(&i)))
+ 		if (match(dev, data) && get_device(dev))
+@@ -91,111 +89,176 @@ struct device * driver_find_device(struct device_driver *drv,
+ EXPORT_SYMBOL_GPL(driver_find_device);
  
--	.irq_handler		= ata_interrupt,
- 	.irq_clear		= ata_bmdma_irq_clear,
- 	.irq_on			= ata_irq_on,
+ /**
+- *	driver_create_file - create sysfs file for driver.
+- *	@drv:	driver.
+- *	@attr:	driver attribute descriptor.
++ * driver_create_file - create sysfs file for driver.
++ * @drv: driver.
++ * @attr: driver attribute descriptor.
+  */
+-
+-int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
++int driver_create_file(struct device_driver *drv,
++		       struct driver_attribute *attr)
+ {
+ 	int error;
+-	if (get_driver(drv)) {
+-		error = sysfs_create_file(&drv->kobj, &attr->attr);
+-		put_driver(drv);
+-	} else
++	if (drv)
++		error = sysfs_create_file(&drv->p->kobj, &attr->attr);
++	else
+ 		error = -EINVAL;
+ 	return error;
+ }
++EXPORT_SYMBOL_GPL(driver_create_file);
  
-@@ -419,6 +428,35 @@ static const struct ata_port_operations piix_vmw_ops = {
- 	.port_start		= ata_port_start,
- };
++/**
++ * driver_remove_file - remove sysfs file for driver.
++ * @drv: driver.
++ * @attr: driver attribute descriptor.
++ */
++void driver_remove_file(struct device_driver *drv,
++			struct driver_attribute *attr)
++{
++	if (drv)
++		sysfs_remove_file(&drv->p->kobj, &attr->attr);
++}
++EXPORT_SYMBOL_GPL(driver_remove_file);
  
-+static const struct ata_port_operations piix_sidpr_sata_ops = {
-+	.tf_load		= ata_tf_load,
-+	.tf_read		= ata_tf_read,
-+	.check_status		= ata_check_status,
-+	.exec_command		= ata_exec_command,
-+	.dev_select		= ata_std_dev_select,
-+
-+	.bmdma_setup		= ata_bmdma_setup,
-+	.bmdma_start		= ata_bmdma_start,
-+	.bmdma_stop		= ata_bmdma_stop,
-+	.bmdma_status		= ata_bmdma_status,
-+	.qc_prep		= ata_qc_prep,
-+	.qc_issue		= ata_qc_issue_prot,
-+	.data_xfer		= ata_data_xfer,
-+
-+	.scr_read		= piix_sidpr_scr_read,
-+	.scr_write		= piix_sidpr_scr_write,
+ /**
+- *	driver_remove_file - remove sysfs file for driver.
+- *	@drv:	driver.
+- *	@attr:	driver attribute descriptor.
++ * driver_add_kobj - add a kobject below the specified driver
++ *
++ * You really don't want to do this, this is only here due to one looney
++ * iseries driver, go poke those developers if you are annoyed about
++ * this...
+  */
++int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
++		    const char *fmt, ...)
++{
++	va_list args;
++	char *name;
 +
-+	.freeze			= ata_bmdma_freeze,
-+	.thaw			= ata_bmdma_thaw,
-+	.error_handler		= piix_sidpr_error_handler,
-+	.post_internal_cmd	= ata_bmdma_post_internal_cmd,
++	va_start(args, fmt);
++	name = kvasprintf(GFP_KERNEL, fmt, args);
++	va_end(args);
 +
-+	.irq_clear		= ata_bmdma_irq_clear,
-+	.irq_on			= ata_irq_on,
++	if (!name)
++		return -ENOMEM;
+ 
+-void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
++	return kobject_add(kobj, &drv->p->kobj, "%s", name);
++}
++EXPORT_SYMBOL_GPL(driver_add_kobj);
 +
-+	.port_start		= ata_port_start,
-+};
++/**
++ * get_driver - increment driver reference count.
++ * @drv: driver.
++ */
++struct device_driver *get_driver(struct device_driver *drv)
+ {
+-	if (get_driver(drv)) {
+-		sysfs_remove_file(&drv->kobj, &attr->attr);
+-		put_driver(drv);
++	if (drv) {
++		struct driver_private *priv;
++		struct kobject *kobj;
 +
- static const struct piix_map_db ich5_map_db = {
- 	.mask = 0x7,
- 	.port_enable = 0x3,
-@@ -526,7 +564,6 @@ static const struct piix_map_db *piix_map_db_table[] = {
- static struct ata_port_info piix_port_info[] = {
- 	[piix_pata_mwdma] = 	/* PIIX3 MWDMA only */
- 	{
--		.sht		= &piix_sht,
- 		.flags		= PIIX_PATA_FLAGS,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-@@ -535,7 +572,6 @@ static struct ata_port_info piix_port_info[] = {
++		kobj = kobject_get(&drv->p->kobj);
++		priv = to_driver(kobj);
++		return priv->driver;
+ 	}
++	return NULL;
+ }
+-
++EXPORT_SYMBOL_GPL(get_driver);
  
- 	[piix_pata_33] =	/* PIIX4 at 33MHz */
- 	{
--		.sht		= &piix_sht,
- 		.flags		= PIIX_PATA_FLAGS,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */
-@@ -545,7 +581,6 @@ static struct ata_port_info piix_port_info[] = {
+ /**
+- *	get_driver - increment driver reference count.
+- *	@drv:	driver.
++ * put_driver - decrement driver's refcount.
++ * @drv: driver.
+  */
+-struct device_driver * get_driver(struct device_driver * drv)
++void put_driver(struct device_driver *drv)
+ {
+-	return drv ? to_drv(kobject_get(&drv->kobj)) : NULL;
++	kobject_put(&drv->p->kobj);
+ }
++EXPORT_SYMBOL_GPL(put_driver);
  
- 	[ich_pata_33] = 	/* ICH0 - ICH at 33Mhz*/
- 	{
--		.sht		= &piix_sht,
- 		.flags		= PIIX_PATA_FLAGS,
- 		.pio_mask 	= 0x1f,	/* pio 0-4 */
- 		.mwdma_mask	= 0x06, /* Check: maybe 0x07  */
-@@ -555,7 +590,6 @@ static struct ata_port_info piix_port_info[] = {
++static int driver_add_groups(struct device_driver *drv,
++			     struct attribute_group **groups)
++{
++	int error = 0;
++	int i;
  
- 	[ich_pata_66] = 	/* ICH controllers up to 66MHz */
- 	{
--		.sht		= &piix_sht,
- 		.flags		= PIIX_PATA_FLAGS,
- 		.pio_mask 	= 0x1f,	/* pio 0-4 */
- 		.mwdma_mask	= 0x06, /* MWDMA0 is broken on chip */
-@@ -565,7 +599,6 @@ static struct ata_port_info piix_port_info[] = {
+-/**
+- *	put_driver - decrement driver's refcount.
+- *	@drv:	driver.
+- */
+-void put_driver(struct device_driver * drv)
++	if (groups) {
++		for (i = 0; groups[i]; i++) {
++			error = sysfs_create_group(&drv->p->kobj, groups[i]);
++			if (error) {
++				while (--i >= 0)
++					sysfs_remove_group(&drv->p->kobj,
++							   groups[i]);
++				break;
++			}
++		}
++	}
++	return error;
++}
++
++static void driver_remove_groups(struct device_driver *drv,
++				 struct attribute_group **groups)
+ {
+-	kobject_put(&drv->kobj);
++	int i;
++
++	if (groups)
++		for (i = 0; groups[i]; i++)
++			sysfs_remove_group(&drv->p->kobj, groups[i]);
+ }
  
- 	[ich_pata_100] =
- 	{
--		.sht		= &piix_sht,
- 		.flags		= PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x06, /* mwdma1-2 */
-@@ -575,7 +608,6 @@ static struct ata_port_info piix_port_info[] = {
+ /**
+- *	driver_register - register driver with bus
+- *	@drv:	driver to register
++ * driver_register - register driver with bus
++ * @drv: driver to register
+  *
+- *	We pass off most of the work to the bus_add_driver() call,
+- *	since most of the things we have to do deal with the bus
+- *	structures.
++ * We pass off most of the work to the bus_add_driver() call,
++ * since most of the things we have to do deal with the bus
++ * structures.
+  */
+-int driver_register(struct device_driver * drv)
++int driver_register(struct device_driver *drv)
+ {
++	int ret;
++
+ 	if ((drv->bus->probe && drv->probe) ||
+ 	    (drv->bus->remove && drv->remove) ||
+-	    (drv->bus->shutdown && drv->shutdown)) {
+-		printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
+-	}
+-	klist_init(&drv->klist_devices, NULL, NULL);
+-	return bus_add_driver(drv);
++	    (drv->bus->shutdown && drv->shutdown))
++		printk(KERN_WARNING "Driver '%s' needs updating - please use "
++			"bus_type methods\n", drv->name);
++	ret = bus_add_driver(drv);
++	if (ret)
++		return ret;
++	ret = driver_add_groups(drv, drv->groups);
++	if (ret)
++		bus_remove_driver(drv);
++	return ret;
+ }
++EXPORT_SYMBOL_GPL(driver_register);
  
- 	[ich5_sata] =
- 	{
--		.sht		= &piix_sht,
- 		.flags		= PIIX_SATA_FLAGS,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
-@@ -585,8 +617,7 @@ static struct ata_port_info piix_port_info[] = {
+ /**
+- *	driver_unregister - remove driver from system.
+- *	@drv:	driver.
++ * driver_unregister - remove driver from system.
++ * @drv: driver.
+  *
+- *	Again, we pass off most of the work to the bus-level call.
++ * Again, we pass off most of the work to the bus-level call.
+  */
+-
+-void driver_unregister(struct device_driver * drv)
++void driver_unregister(struct device_driver *drv)
+ {
++	driver_remove_groups(drv, drv->groups);
+ 	bus_remove_driver(drv);
+ }
++EXPORT_SYMBOL_GPL(driver_unregister);
  
- 	[ich6_sata] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR,
-+		.flags		= PIIX_SATA_FLAGS,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -595,9 +626,7 @@ static struct ata_port_info piix_port_info[] = {
+ /**
+- *	driver_find - locate driver on a bus by its name.
+- *	@name:	name of the driver.
+- *	@bus:	bus to scan for the driver.
++ * driver_find - locate driver on a bus by its name.
++ * @name: name of the driver.
++ * @bus: bus to scan for the driver.
+  *
+- *	Call kset_find_obj() to iterate over list of drivers on
+- *	a bus to find driver by name. Return driver if found.
++ * Call kset_find_obj() to iterate over list of drivers on
++ * a bus to find driver by name. Return driver if found.
+  *
+- *	Note that kset_find_obj increments driver's reference count.
++ * Note that kset_find_obj increments driver's reference count.
+  */
+ struct device_driver *driver_find(const char *name, struct bus_type *bus)
+ {
+-	struct kobject *k = kset_find_obj(&bus->drivers, name);
+-	if (k)
+-		return to_drv(k);
++	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
++	struct driver_private *priv;
++
++	if (k) {
++		priv = to_driver(k);
++		return priv->driver;
++	}
+ 	return NULL;
+ }
+-
+-EXPORT_SYMBOL_GPL(driver_register);
+-EXPORT_SYMBOL_GPL(driver_unregister);
+-EXPORT_SYMBOL_GPL(get_driver);
+-EXPORT_SYMBOL_GPL(put_driver);
+ EXPORT_SYMBOL_GPL(driver_find);
+-
+-EXPORT_SYMBOL_GPL(driver_create_file);
+-EXPORT_SYMBOL_GPL(driver_remove_file);
+diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
+index 90c8629..1138155 100644
+--- a/drivers/base/firmware.c
++++ b/drivers/base/firmware.c
+@@ -3,11 +3,11 @@
+  *
+  * Copyright (c) 2002-3 Patrick Mochel
+  * Copyright (c) 2002-3 Open Source Development Labs
++ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
++ * Copyright (c) 2007 Novell Inc.
+  *
+  * This file is released under the GPLv2
+- *
+  */
+-
+ #include <linux/kobject.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -15,23 +15,13 @@
  
- 	[ich6_sata_ahci] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
--				  PIIX_FLAG_AHCI,
-+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -606,9 +635,7 @@ static struct ata_port_info piix_port_info[] = {
+ #include "base.h"
  
- 	[ich6m_sata_ahci] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
--				  PIIX_FLAG_AHCI,
-+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -617,9 +644,8 @@ static struct ata_port_info piix_port_info[] = {
+-static decl_subsys(firmware, NULL, NULL);
+-
+-int firmware_register(struct kset *s)
+-{
+-	kobj_set_kset_s(s, firmware_subsys);
+-	return subsystem_register(s);
+-}
+-
+-void firmware_unregister(struct kset *s)
+-{
+-	subsystem_unregister(s);
+-}
++struct kobject *firmware_kobj;
++EXPORT_SYMBOL_GPL(firmware_kobj);
  
- 	[ich8_sata_ahci] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
--				  PIIX_FLAG_AHCI,
-+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
-+				  PIIX_FLAG_SIDPR,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -628,9 +654,8 @@ static struct ata_port_info piix_port_info[] = {
+ int __init firmware_init(void)
+ {
+-	return subsystem_register(&firmware_subsys);
++	firmware_kobj = kobject_create_and_add("firmware", NULL);
++	if (!firmware_kobj)
++		return -ENOMEM;
++	return 0;
+ }
+-
+-EXPORT_SYMBOL_GPL(firmware_register);
+-EXPORT_SYMBOL_GPL(firmware_unregister);
+diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c
+index 7080b41..6428cba 100644
+--- a/drivers/base/hypervisor.c
++++ b/drivers/base/hypervisor.c
+@@ -2,19 +2,23 @@
+  * hypervisor.c - /sys/hypervisor subsystem.
+  *
+  * Copyright (C) IBM Corp. 2006
++ * Copyright (C) 2007 Greg Kroah-Hartman <gregkh at suse.de>
++ * Copyright (C) 2007 Novell Inc.
+  *
+  * This file is released under the GPLv2
+  */
  
- 	[ich8_2port_sata] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
--				  PIIX_FLAG_AHCI,
-+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
-+				  PIIX_FLAG_SIDPR,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -639,9 +664,7 @@ static struct ata_port_info piix_port_info[] = {
+ #include <linux/kobject.h>
+ #include <linux/device.h>
+-
+ #include "base.h"
  
- 	[tolapai_sata_ahci] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
--				  PIIX_FLAG_AHCI,
-+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -650,9 +673,8 @@ static struct ata_port_info piix_port_info[] = {
+-decl_subsys(hypervisor, NULL, NULL);
+-EXPORT_SYMBOL_GPL(hypervisor_subsys);
++struct kobject *hypervisor_kobj;
++EXPORT_SYMBOL_GPL(hypervisor_kobj);
+ 
+ int __init hypervisor_init(void)
+ {
+-	return subsystem_register(&hypervisor_subsys);
++	hypervisor_kobj = kobject_create_and_add("hypervisor", NULL);
++	if (!hypervisor_kobj)
++		return -ENOMEM;
++	return 0;
+ }
+diff --git a/drivers/base/init.c b/drivers/base/init.c
+index 3713815..7bd9b6a 100644
+--- a/drivers/base/init.c
++++ b/drivers/base/init.c
+@@ -1,10 +1,8 @@
+ /*
+- *
+  * Copyright (c) 2002-3 Patrick Mochel
+  * Copyright (c) 2002-3 Open Source Development Labs
+  *
+  * This file is released under the GPLv2
+- *
+  */
  
- 	[ich8m_apple_sata_ahci] =
- 	{
--		.sht		= &piix_sht,
--		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_SCR |
--				  PIIX_FLAG_AHCI,
-+		.flags		= PIIX_SATA_FLAGS | PIIX_FLAG_AHCI |
-+				  PIIX_FLAG_SIDPR,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.mwdma_mask	= 0x07, /* mwdma0-2 */
- 		.udma_mask	= ATA_UDMA6,
-@@ -1001,6 +1023,180 @@ static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev)
- 	do_pata_set_dmamode(ap, adev, 1);
+ #include <linux/device.h>
+@@ -14,12 +12,11 @@
+ #include "base.h"
+ 
+ /**
+- *	driver_init - initialize driver model.
++ * driver_init - initialize driver model.
+  *
+- *	Call the driver model init functions to initialize their
+- *	subsystems. Called early from init/main.c.
++ * Call the driver model init functions to initialize their
++ * subsystems. Called early from init/main.c.
+  */
+-
+ void __init driver_init(void)
+ {
+ 	/* These are the core pieces */
+@@ -36,5 +33,4 @@ void __init driver_init(void)
+ 	system_bus_init();
+ 	cpu_dev_init();
+ 	memory_dev_init();
+-	attribute_container_init();
  }
+diff --git a/drivers/base/memory.c b/drivers/base/memory.c
+index 7868707..7ae413f 100644
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -26,7 +26,7 @@
+ #define MEMORY_CLASS_NAME	"memory"
+ 
+ static struct sysdev_class memory_sysdev_class = {
+-	set_kset_name(MEMORY_CLASS_NAME),
++	.name = MEMORY_CLASS_NAME,
+ };
  
+ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
+diff --git a/drivers/base/module.c b/drivers/base/module.c
+new file mode 100644
+index 0000000..103be9c
+--- /dev/null
++++ b/drivers/base/module.c
+@@ -0,0 +1,94 @@
 +/*
-+ * Serial ATA Index/Data Pair Superset Registers access
-+ *
-+ * Beginning from ICH8, there's a sane way to access SCRs using index
-+ * and data register pair located at BAR5.  This creates an
-+ * interesting problem of mapping two SCRs to one port.
++ * module.c - module sysfs fun for drivers
 + *
-+ * Although they have separate SCRs, the master and slave aren't
-+ * independent enough to be treated as separate links - e.g. softreset
-+ * resets both.  Also, there's no protocol defined for hard resetting
-+ * singled device sharing the virtual port (no defined way to acquire
-+ * device signature).  This is worked around by merging the SCR values
-+ * into one sensible value and requesting follow-up SRST after
-+ * hardreset.
++ * This file is released under the GPLv2
 + *
-+ * SCR merging is perfomed in nibbles which is the unit contents in
-+ * SCRs are organized.  If two values are equal, the value is used.
-+ * When they differ, merge table which lists precedence of possible
-+ * values is consulted and the first match or the last entry when
-+ * nothing matches is used.  When there's no merge table for the
-+ * specific nibble, value from the first port is used.
 + */
-+static const int piix_sidx_map[] = {
-+	[SCR_STATUS]	= 0,
-+	[SCR_ERROR]	= 2,
-+	[SCR_CONTROL]	= 1,
-+};
++#include <linux/device.h>
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/string.h>
++#include "base.h"
 +
-+static void piix_sidpr_sel(struct ata_device *dev, unsigned int reg)
++static char *make_driver_name(struct device_driver *drv)
 +{
-+	struct ata_port *ap = dev->link->ap;
-+	struct piix_host_priv *hpriv = ap->host->private_data;
-+
-+	iowrite32(((ap->port_no * 2 + dev->devno) << 8) | piix_sidx_map[reg],
-+		  hpriv->sidpr + PIIX_SIDPR_IDX);
-+}
++	char *driver_name;
 +
-+static int piix_sidpr_read(struct ata_device *dev, unsigned int reg)
-+{
-+	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
++	driver_name = kmalloc(strlen(drv->name) + strlen(drv->bus->name) + 2,
++			      GFP_KERNEL);
++	if (!driver_name)
++		return NULL;
 +
-+	piix_sidpr_sel(dev, reg);
-+	return ioread32(hpriv->sidpr + PIIX_SIDPR_DATA);
++	sprintf(driver_name, "%s:%s", drv->bus->name, drv->name);
++	return driver_name;
 +}
 +
-+static void piix_sidpr_write(struct ata_device *dev, unsigned int reg, u32 val)
++static void module_create_drivers_dir(struct module_kobject *mk)
 +{
-+	struct piix_host_priv *hpriv = dev->link->ap->host->private_data;
++	if (!mk || mk->drivers_dir)
++		return;
 +
-+	piix_sidpr_sel(dev, reg);
-+	iowrite32(val, hpriv->sidpr + PIIX_SIDPR_DATA);
++	mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
 +}
 +
-+static u32 piix_merge_scr(u32 val0, u32 val1, const int * const *merge_tbl)
++void module_add_driver(struct module *mod, struct device_driver *drv)
 +{
-+	u32 val = 0;
-+	int i, mi;
-+
-+	for (i = 0, mi = 0; i < 32 / 4; i++) {
-+		u8 c0 = (val0 >> (i * 4)) & 0xf;
-+		u8 c1 = (val1 >> (i * 4)) & 0xf;
-+		u8 merged = c0;
-+		const int *cur;
++	char *driver_name;
++	int no_warn;
++	struct module_kobject *mk = NULL;
 +
-+		/* if no merge preference, assume the first value */
-+		cur = merge_tbl[mi];
-+		if (!cur)
-+			goto done;
-+		mi++;
++	if (!drv)
++		return;
 +
-+		/* if two values equal, use it */
-+		if (c0 == c1)
-+			goto done;
++	if (mod)
++		mk = &mod->mkobj;
++	else if (drv->mod_name) {
++		struct kobject *mkobj;
 +
-+		/* choose the first match or the last from the merge table */
-+		while (*cur != -1) {
-+			if (c0 == *cur || c1 == *cur)
-+				break;
-+			cur++;
++		/* Lookup built-in module entry in /sys/modules */
++		mkobj = kset_find_obj(module_kset, drv->mod_name);
++		if (mkobj) {
++			mk = container_of(mkobj, struct module_kobject, kobj);
++			/* remember our module structure */
++			drv->p->mkobj = mk;
++			/* kset_find_obj took a reference */
++			kobject_put(mkobj);
 +		}
-+		if (*cur == -1)
-+			cur--;
-+		merged = *cur;
-+	done:
-+		val |= merged << (i * 4);
-+	}
-+
-+	return val;
-+}
-+
-+static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val)
-+{
-+	const int * const sstatus_merge_tbl[] = {
-+		/* DET */ (const int []){ 1, 3, 0, 4, 3, -1 },
-+		/* SPD */ (const int []){ 2, 1, 0, -1 },
-+		/* IPM */ (const int []){ 6, 2, 1, 0, -1 },
-+		NULL,
-+	};
-+	const int * const scontrol_merge_tbl[] = {
-+		/* DET */ (const int []){ 1, 0, 4, 0, -1 },
-+		/* SPD */ (const int []){ 0, 2, 1, 0, -1 },
-+		/* IPM */ (const int []){ 0, 1, 2, 3, 0, -1 },
-+		NULL,
-+	};
-+	u32 v0, v1;
-+
-+	if (reg >= ARRAY_SIZE(piix_sidx_map))
-+		return -EINVAL;
-+
-+	if (!(ap->flags & ATA_FLAG_SLAVE_POSS)) {
-+		*val = piix_sidpr_read(&ap->link.device[0], reg);
-+		return 0;
 +	}
 +
-+	v0 = piix_sidpr_read(&ap->link.device[0], reg);
-+	v1 = piix_sidpr_read(&ap->link.device[1], reg);
++	if (!mk)
++		return;
 +
-+	switch (reg) {
-+	case SCR_STATUS:
-+		*val = piix_merge_scr(v0, v1, sstatus_merge_tbl);
-+		break;
-+	case SCR_ERROR:
-+		*val = v0 | v1;
-+		break;
-+	case SCR_CONTROL:
-+		*val = piix_merge_scr(v0, v1, scontrol_merge_tbl);
-+		break;
++	/* Don't check return codes; these calls are idempotent */
++	no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
++	driver_name = make_driver_name(drv);
++	if (driver_name) {
++		module_create_drivers_dir(mk);
++		no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
++					    driver_name);
++		kfree(driver_name);
 +	}
-+
-+	return 0;
 +}
 +
-+static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
++void module_remove_driver(struct device_driver *drv)
 +{
-+	if (reg >= ARRAY_SIZE(piix_sidx_map))
-+		return -EINVAL;
-+
-+	piix_sidpr_write(&ap->link.device[0], reg, val);
-+
-+	if (ap->flags & ATA_FLAG_SLAVE_POSS)
-+		piix_sidpr_write(&ap->link.device[1], reg, val);
-+
-+	return 0;
-+}
++	struct module_kobject *mk = NULL;
++	char *driver_name;
 +
-+static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
-+				unsigned long deadline)
-+{
-+	const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
-+	int rc;
++	if (!drv)
++		return;
 +
-+	/* do hardreset */
-+	rc = sata_link_hardreset(link, timing, deadline);
-+	if (rc) {
-+		ata_link_printk(link, KERN_ERR,
-+				"COMRESET failed (errno=%d)\n", rc);
-+		return rc;
-+	}
++	sysfs_remove_link(&drv->p->kobj, "module");
 +
-+	/* TODO: phy layer with polling, timeouts, etc. */
-+	if (ata_link_offline(link)) {
-+		*class = ATA_DEV_NONE;
-+		return 0;
++	if (drv->owner)
++		mk = &drv->owner->mkobj;
++	else if (drv->p->mkobj)
++		mk = drv->p->mkobj;
++	if (mk && mk->drivers_dir) {
++		driver_name = make_driver_name(drv);
++		if (driver_name) {
++			sysfs_remove_link(mk->drivers_dir, driver_name);
++			kfree(driver_name);
++		}
 +	}
-+
-+	return -EAGAIN;
-+}
-+
-+static void piix_sidpr_error_handler(struct ata_port *ap)
-+{
-+	ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
-+			   piix_sidpr_hardreset, ata_std_postreset);
 +}
-+
- #ifdef CONFIG_PM
- static int piix_broken_suspend(void)
- {
-@@ -1034,6 +1230,13 @@ static int piix_broken_suspend(void)
- 			},
- 		},
- 		{
-+			.ident = "TECRA M6",
-+			.matches = {
-+				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-+				DMI_MATCH(DMI_PRODUCT_NAME, "TECRA M6"),
-+			},
-+		},
-+		{
- 			.ident = "TECRA M7",
- 			.matches = {
- 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-@@ -1048,6 +1251,13 @@ static int piix_broken_suspend(void)
- 			},
- 		},
- 		{
-+			.ident = "Satellite R20",
-+			.matches = {
-+				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-+				DMI_MATCH(DMI_PRODUCT_NAME, "Satellite R20"),
-+			},
-+		},
-+		{
- 			.ident = "Satellite R25",
- 			.matches = {
- 				DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
-@@ -1253,10 +1463,10 @@ static int __devinit piix_check_450nx_errata(struct pci_dev *ata_dev)
- 	return no_piix_dma;
- }
- 
--static void __devinit piix_init_pcs(struct pci_dev *pdev,
--				    struct ata_port_info *pinfo,
-+static void __devinit piix_init_pcs(struct ata_host *host,
- 				    const struct piix_map_db *map_db)
- {
-+	struct pci_dev *pdev = to_pci_dev(host->dev);
- 	u16 pcs, new_pcs;
+diff --git a/drivers/base/node.c b/drivers/base/node.c
+index 88eeed7..e59861f 100644
+--- a/drivers/base/node.c
++++ b/drivers/base/node.c
+@@ -15,7 +15,7 @@
+ #include <linux/device.h>
  
- 	pci_read_config_word(pdev, ICH5_PCS, &pcs);
-@@ -1270,11 +1480,10 @@ static void __devinit piix_init_pcs(struct pci_dev *pdev,
- 	}
- }
+ static struct sysdev_class node_class = {
+-	set_kset_name("node"),
++	.name = "node",
+ };
  
--static void __devinit piix_init_sata_map(struct pci_dev *pdev,
--					 struct ata_port_info *pinfo,
--					 const struct piix_map_db *map_db)
-+static const int *__devinit piix_init_sata_map(struct pci_dev *pdev,
-+					       struct ata_port_info *pinfo,
-+					       const struct piix_map_db *map_db)
- {
--	struct piix_host_priv *hpriv = pinfo[0].private_data;
- 	const int *map;
- 	int i, invalid_map = 0;
- 	u8 map_value;
-@@ -1298,7 +1507,6 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
- 		case IDE:
- 			WARN_ON((i & 1) || map[i + 1] != IDE);
- 			pinfo[i / 2] = piix_port_info[ich_pata_100];
--			pinfo[i / 2].private_data = hpriv;
- 			i++;
- 			printk(" IDE IDE");
- 			break;
-@@ -1316,7 +1524,33 @@ static void __devinit piix_init_sata_map(struct pci_dev *pdev,
- 		dev_printk(KERN_ERR, &pdev->dev,
- 			   "invalid MAP value %u\n", map_value);
  
--	hpriv->map = map;
-+	return map;
-+}
-+
-+static void __devinit piix_init_sidpr(struct ata_host *host)
-+{
-+	struct pci_dev *pdev = to_pci_dev(host->dev);
-+	struct piix_host_priv *hpriv = host->private_data;
-+	int i;
-+
-+	/* check for availability */
-+	for (i = 0; i < 4; i++)
-+		if (hpriv->map[i] == IDE)
-+			return;
-+
-+	if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR))
-+		return;
-+
-+	if (pci_resource_start(pdev, PIIX_SIDPR_BAR) == 0 ||
-+	    pci_resource_len(pdev, PIIX_SIDPR_BAR) != PIIX_SIDPR_LEN)
-+		return;
-+
-+	if (pcim_iomap_regions(pdev, 1 << PIIX_SIDPR_BAR, DRV_NAME))
-+		return;
-+
-+	hpriv->sidpr = pcim_iomap_table(pdev)[PIIX_SIDPR_BAR];
-+	host->ports[0]->ops = &piix_sidpr_sata_ops;
-+	host->ports[1]->ops = &piix_sidpr_sata_ops;
- }
+diff --git a/drivers/base/platform.c b/drivers/base/platform.c
+index fb56092..efaf282 100644
+--- a/drivers/base/platform.c
++++ b/drivers/base/platform.c
+@@ -20,7 +20,8 @@
  
- static void piix_iocfg_bit18_quirk(struct pci_dev *pdev)
-@@ -1375,8 +1609,10 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- 	struct device *dev = &pdev->dev;
- 	struct ata_port_info port_info[2];
- 	const struct ata_port_info *ppi[] = { &port_info[0], &port_info[1] };
--	struct piix_host_priv *hpriv;
- 	unsigned long port_flags;
-+	struct ata_host *host;
-+	struct piix_host_priv *hpriv;
-+	int rc;
+ #include "base.h"
  
- 	if (!printed_version++)
- 		dev_printk(KERN_DEBUG, &pdev->dev,
-@@ -1386,17 +1622,31 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- 	if (!in_module_init)
- 		return -ENODEV;
+-#define to_platform_driver(drv)	(container_of((drv), struct platform_driver, driver))
++#define to_platform_driver(drv)	(container_of((drv), struct platform_driver, \
++				 driver))
  
-+	port_info[0] = piix_port_info[ent->driver_data];
-+	port_info[1] = piix_port_info[ent->driver_data];
-+
-+	port_flags = port_info[0].flags;
-+
-+	/* enable device and prepare host */
-+	rc = pcim_enable_device(pdev);
-+	if (rc)
-+		return rc;
-+
-+	/* SATA map init can change port_info, do it before prepping host */
- 	hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL);
- 	if (!hpriv)
- 		return -ENOMEM;
+ struct device platform_bus = {
+ 	.bus_id		= "platform",
+@@ -28,14 +29,13 @@ struct device platform_bus = {
+ EXPORT_SYMBOL_GPL(platform_bus);
  
--	port_info[0] = piix_port_info[ent->driver_data];
--	port_info[1] = piix_port_info[ent->driver_data];
--	port_info[0].private_data = hpriv;
--	port_info[1].private_data = hpriv;
-+	if (port_flags & ATA_FLAG_SATA)
-+		hpriv->map = piix_init_sata_map(pdev, port_info,
-+					piix_map_db_table[ent->driver_data]);
+ /**
+- *	platform_get_resource - get a resource for a device
+- *	@dev: platform device
+- *	@type: resource type
+- *	@num: resource index
++ * platform_get_resource - get a resource for a device
++ * @dev: platform device
++ * @type: resource type
++ * @num: resource index
+  */
+-struct resource *
+-platform_get_resource(struct platform_device *dev, unsigned int type,
+-		      unsigned int num)
++struct resource *platform_get_resource(struct platform_device *dev,
++				       unsigned int type, unsigned int num)
+ {
+ 	int i;
  
--	port_flags = port_info[0].flags;
-+	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
-+	if (rc)
-+		return rc;
-+	host->private_data = hpriv;
+@@ -43,8 +43,7 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
+ 		struct resource *r = &dev->resource[i];
  
-+	/* initialize controller */
- 	if (port_flags & PIIX_FLAG_AHCI) {
- 		u8 tmp;
- 		pci_read_config_byte(pdev, PIIX_SCC, &tmp);
-@@ -1407,12 +1657,9 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- 		}
+ 		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
+-				 IORESOURCE_IRQ|IORESOURCE_DMA))
+-		    == type)
++				 IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
+ 			if (num-- == 0)
+ 				return r;
  	}
+@@ -53,9 +52,9 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
+ EXPORT_SYMBOL_GPL(platform_get_resource);
  
--	/* Initialize SATA map */
- 	if (port_flags & ATA_FLAG_SATA) {
--		piix_init_sata_map(pdev, port_info,
--				   piix_map_db_table[ent->driver_data]);
--		piix_init_pcs(pdev, port_info,
--			      piix_map_db_table[ent->driver_data]);
-+		piix_init_pcs(host, piix_map_db_table[ent->driver_data]);
-+		piix_init_sidpr(host);
- 	}
+ /**
+- *	platform_get_irq - get an IRQ for a device
+- *	@dev: platform device
+- *	@num: IRQ number index
++ * platform_get_irq - get an IRQ for a device
++ * @dev: platform device
++ * @num: IRQ number index
+  */
+ int platform_get_irq(struct platform_device *dev, unsigned int num)
+ {
+@@ -66,14 +65,13 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
+ EXPORT_SYMBOL_GPL(platform_get_irq);
  
- 	/* apply IOCFG bit18 quirk */
-@@ -1431,12 +1678,14 @@ static int piix_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- 		/* This writes into the master table but it does not
- 		   really matter for this errata as we will apply it to
- 		   all the PIIX devices on the board */
--		port_info[0].mwdma_mask = 0;
--		port_info[0].udma_mask = 0;
--		port_info[1].mwdma_mask = 0;
--		port_info[1].udma_mask = 0;
-+		host->ports[0]->mwdma_mask = 0;
-+		host->ports[0]->udma_mask = 0;
-+		host->ports[1]->mwdma_mask = 0;
-+		host->ports[1]->udma_mask = 0;
- 	}
--	return ata_pci_init_one(pdev, ppi);
-+
-+	pci_set_master(pdev);
-+	return ata_pci_activate_sff_host(host, ata_interrupt, &piix_sht);
- }
+ /**
+- *	platform_get_resource_byname - get a resource for a device by name
+- *	@dev: platform device
+- *	@type: resource type
+- *	@name: resource name
++ * platform_get_resource_byname - get a resource for a device by name
++ * @dev: platform device
++ * @type: resource type
++ * @name: resource name
+  */
+-struct resource *
+-platform_get_resource_byname(struct platform_device *dev, unsigned int type,
+-		      char *name)
++struct resource *platform_get_resource_byname(struct platform_device *dev,
++					      unsigned int type, char *name)
+ {
+ 	int i;
  
- static int __init piix_init(void)
-diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
-index 7bf4bef..9e8ec19 100644
---- a/drivers/ata/libata-acpi.c
-+++ b/drivers/ata/libata-acpi.c
-@@ -442,40 +442,77 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
+@@ -90,22 +88,23 @@ platform_get_resource_byname(struct platform_device *dev, unsigned int type,
+ EXPORT_SYMBOL_GPL(platform_get_resource_byname);
+ 
+ /**
+- *	platform_get_irq - get an IRQ for a device
+- *	@dev: platform device
+- *	@name: IRQ name
++ * platform_get_irq - get an IRQ for a device
++ * @dev: platform device
++ * @name: IRQ name
+  */
+ int platform_get_irq_byname(struct platform_device *dev, char *name)
+ {
+-	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
++	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
++							  name);
+ 
+ 	return r ? r->start : -ENXIO;
  }
+ EXPORT_SYMBOL_GPL(platform_get_irq_byname);
  
  /**
-+ * ata_acpi_gtm_xfermode - determine xfermode from GTM parameter
-+ * @dev: target device
-+ * @gtm: GTM parameter to use
-+ *
-+ * Determine xfermask for @dev from @gtm.
-+ *
-+ * LOCKING:
-+ * None.
-+ *
-+ * RETURNS:
-+ * Determined xfermask.
-+ */
-+unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
-+				    const struct ata_acpi_gtm *gtm)
-+{
-+	unsigned long xfer_mask = 0;
-+	unsigned int type;
-+	int unit;
-+	u8 mode;
-+
-+	/* we always use the 0 slot for crap hardware */
-+	unit = dev->devno;
-+	if (!(gtm->flags & 0x10))
-+		unit = 0;
-+
-+	/* PIO */
-+	mode = ata_timing_cycle2mode(ATA_SHIFT_PIO, gtm->drive[unit].pio);
-+	xfer_mask |= ata_xfer_mode2mask(mode);
-+
-+	/* See if we have MWDMA or UDMA data. We don't bother with
-+	 * MWDMA if UDMA is available as this means the BIOS set UDMA
-+	 * and our error changedown if it works is UDMA to PIO anyway.
-+	 */
-+	if (!(gtm->flags & (1 << (2 * unit))))
-+		type = ATA_SHIFT_MWDMA;
-+	else
-+		type = ATA_SHIFT_UDMA;
-+
-+	mode = ata_timing_cycle2mode(type, gtm->drive[unit].dma);
-+	xfer_mask |= ata_xfer_mode2mask(mode);
-+
-+	return xfer_mask;
-+}
-+EXPORT_SYMBOL_GPL(ata_acpi_gtm_xfermask);
-+
-+/**
-  * ata_acpi_cbl_80wire		-	Check for 80 wire cable
-  * @ap: Port to check
-+ * @gtm: GTM data to use
-  *
-- * Return 1 if the ACPI mode data for this port indicates the BIOS selected
-- * an 80wire mode.
-+ * Return 1 if the @gtm indicates the BIOS selected an 80wire mode.
+- *	platform_add_devices - add a numbers of platform devices
+- *	@devs: array of platform devices to add
+- *	@num: number of platform devices in array
++ * platform_add_devices - add a numbers of platform devices
++ * @devs: array of platform devices to add
++ * @num: number of platform devices in array
   */
--
--int ata_acpi_cbl_80wire(struct ata_port *ap)
-+int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm)
+ int platform_add_devices(struct platform_device **devs, int num)
  {
--	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
--	int valid = 0;
-+	struct ata_device *dev;
+@@ -130,12 +129,11 @@ struct platform_object {
+ };
  
--	if (!gtm)
--		return 0;
-+	ata_link_for_each_dev(dev, &ap->link) {
-+		unsigned long xfer_mask, udma_mask;
-+
-+		if (!ata_dev_enabled(dev))
-+			continue;
-+
-+		xfer_mask = ata_acpi_gtm_xfermask(dev, gtm);
-+		ata_unpack_xfermask(xfer_mask, NULL, NULL, &udma_mask);
-+
-+		if (udma_mask & ~ATA_UDMA_MASK_40C)
-+			return 1;
-+	}
+ /**
+- *	platform_device_put
+- *	@pdev:	platform device to free
++ * platform_device_put
++ * @pdev: platform device to free
+  *
+- *	Free all memory associated with a platform device.  This function
+- *	must _only_ be externally called in error cases.  All other usage
+- *	is a bug.
++ * Free all memory associated with a platform device.  This function must
++ * _only_ be externally called in error cases.  All other usage is a bug.
+  */
+ void platform_device_put(struct platform_device *pdev)
+ {
+@@ -146,7 +144,8 @@ EXPORT_SYMBOL_GPL(platform_device_put);
  
--	/* Split timing, DMA enabled */
--	if ((gtm->flags & 0x11) == 0x11 && gtm->drive[0].dma < 55)
--		valid |= 1;
--	if ((gtm->flags & 0x14) == 0x14 && gtm->drive[1].dma < 55)
--		valid |= 2;
--	/* Shared timing, DMA enabled */
--	if ((gtm->flags & 0x11) == 0x01 && gtm->drive[0].dma < 55)
--		valid |= 1;
--	if ((gtm->flags & 0x14) == 0x04 && gtm->drive[0].dma < 55)
--		valid |= 2;
--
--	/* Drive check */
--	if ((valid & 1) && ata_dev_enabled(&ap->link.device[0]))
--		return 1;
--	if ((valid & 2) && ata_dev_enabled(&ap->link.device[1]))
--		return 1;
- 	return 0;
- }
--
- EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
+ static void platform_device_release(struct device *dev)
+ {
+-	struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev);
++	struct platform_object *pa = container_of(dev, struct platform_object,
++						  pdev.dev);
  
- static void ata_acpi_gtf_to_tf(struct ata_device *dev,
-@@ -776,6 +813,36 @@ void ata_acpi_on_resume(struct ata_port *ap)
+ 	kfree(pa->pdev.dev.platform_data);
+ 	kfree(pa->pdev.resource);
+@@ -154,12 +153,12 @@ static void platform_device_release(struct device *dev)
  }
  
  /**
-+ * ata_acpi_set_state - set the port power state
-+ * @ap: target ATA port
-+ * @state: state, on/off
-+ *
-+ * This function executes the _PS0/_PS3 ACPI method to set the power state.
-+ * ACPI spec requires _PS0 when IDE power on and _PS3 when power off
-+ */
-+void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
-+{
-+	struct ata_device *dev;
-+
-+	if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA))
-+		return;
-+
-+	/* channel first and then drives for power on and vica versa
-+	   for power off */
-+	if (state.event == PM_EVENT_ON)
-+		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0);
-+
-+	ata_link_for_each_dev(dev, &ap->link) {
-+		if (dev->acpi_handle && ata_dev_enabled(dev))
-+			acpi_bus_set_power(dev->acpi_handle,
-+				state.event == PM_EVENT_ON ?
-+					ACPI_STATE_D0 : ACPI_STATE_D3);
-+	}
-+	if (state.event != PM_EVENT_ON)
-+		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3);
-+}
-+
-+/**
-  * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration
-  * @dev: target ATA device
+- *	platform_device_alloc
+- *	@name:	base name of the device we're adding
+- *	@id:    instance id
++ * platform_device_alloc
++ * @name: base name of the device we're adding
++ * @id: instance id
   *
-diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
-index 6380726..bdbd55a 100644
---- a/drivers/ata/libata-core.c
-+++ b/drivers/ata/libata-core.c
-@@ -119,6 +119,10 @@ int libata_noacpi = 0;
- module_param_named(noacpi, libata_noacpi, int, 0444);
- MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in probe/suspend/resume when set");
- 
-+int libata_allow_tpm = 0;
-+module_param_named(allow_tpm, libata_allow_tpm, int, 0444);
-+MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands");
-+
- MODULE_AUTHOR("Jeff Garzik");
- MODULE_DESCRIPTION("Library module for ATA devices");
- MODULE_LICENSE("GPL");
-@@ -450,9 +454,9 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
-  *	RETURNS:
-  *	Packed xfer_mask.
+- *	Create a platform device object which can have other objects attached
+- *	to it, and which will have attached objects freed when it is released.
++ * Create a platform device object which can have other objects attached
++ * to it, and which will have attached objects freed when it is released.
   */
--static unsigned int ata_pack_xfermask(unsigned int pio_mask,
--				      unsigned int mwdma_mask,
--				      unsigned int udma_mask)
-+unsigned long ata_pack_xfermask(unsigned long pio_mask,
-+				unsigned long mwdma_mask,
-+				unsigned long udma_mask)
+ struct platform_device *platform_device_alloc(const char *name, int id)
  {
- 	return ((pio_mask << ATA_SHIFT_PIO) & ATA_MASK_PIO) |
- 		((mwdma_mask << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA) |
-@@ -469,10 +473,8 @@ static unsigned int ata_pack_xfermask(unsigned int pio_mask,
-  *	Unpack @xfer_mask into @pio_mask, @mwdma_mask and @udma_mask.
-  *	Any NULL distination masks will be ignored.
+@@ -179,16 +178,17 @@ struct platform_device *platform_device_alloc(const char *name, int id)
+ EXPORT_SYMBOL_GPL(platform_device_alloc);
+ 
+ /**
+- *	platform_device_add_resources
+- *	@pdev:	platform device allocated by platform_device_alloc to add resources to
+- *	@res:   set of resources that needs to be allocated for the device
+- *	@num:	number of resources
++ * platform_device_add_resources
++ * @pdev: platform device allocated by platform_device_alloc to add resources to
++ * @res: set of resources that needs to be allocated for the device
++ * @num: number of resources
+  *
+- *	Add a copy of the resources to the platform device.  The memory
+- *	associated with the resources will be freed when the platform
+- *	device is released.
++ * Add a copy of the resources to the platform device.  The memory
++ * associated with the resources will be freed when the platform device is
++ * released.
   */
--static void ata_unpack_xfermask(unsigned int xfer_mask,
--				unsigned int *pio_mask,
--				unsigned int *mwdma_mask,
--				unsigned int *udma_mask)
-+void ata_unpack_xfermask(unsigned long xfer_mask, unsigned long *pio_mask,
-+			 unsigned long *mwdma_mask, unsigned long *udma_mask)
+-int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num)
++int platform_device_add_resources(struct platform_device *pdev,
++				  struct resource *res, unsigned int num)
  {
- 	if (pio_mask)
- 		*pio_mask = (xfer_mask & ATA_MASK_PIO) >> ATA_SHIFT_PIO;
-@@ -486,9 +488,9 @@ static const struct ata_xfer_ent {
- 	int shift, bits;
- 	u8 base;
- } ata_xfer_tbl[] = {
--	{ ATA_SHIFT_PIO, ATA_BITS_PIO, XFER_PIO_0 },
--	{ ATA_SHIFT_MWDMA, ATA_BITS_MWDMA, XFER_MW_DMA_0 },
--	{ ATA_SHIFT_UDMA, ATA_BITS_UDMA, XFER_UDMA_0 },
-+	{ ATA_SHIFT_PIO, ATA_NR_PIO_MODES, XFER_PIO_0 },
-+	{ ATA_SHIFT_MWDMA, ATA_NR_MWDMA_MODES, XFER_MW_DMA_0 },
-+	{ ATA_SHIFT_UDMA, ATA_NR_UDMA_MODES, XFER_UDMA_0 },
- 	{ -1, },
- };
+ 	struct resource *r;
  
-@@ -503,9 +505,9 @@ static const struct ata_xfer_ent {
-  *	None.
+@@ -203,16 +203,17 @@ int platform_device_add_resources(struct platform_device *pdev, struct resource
+ EXPORT_SYMBOL_GPL(platform_device_add_resources);
+ 
+ /**
+- *	platform_device_add_data
+- *	@pdev:	platform device allocated by platform_device_alloc to add resources to
+- *	@data:	platform specific data for this platform device
+- *	@size:	size of platform specific data
++ * platform_device_add_data
++ * @pdev: platform device allocated by platform_device_alloc to add resources to
++ * @data: platform specific data for this platform device
++ * @size: size of platform specific data
   *
-  *	RETURNS:
-- *	Matching XFER_* value, 0 if no match found.
-+ *	Matching XFER_* value, 0xff if no match found.
+- *	Add a copy of platform specific data to the platform device's platform_data
+- *	pointer.  The memory associated with the platform data will be freed
+- *	when the platform device is released.
++ * Add a copy of platform specific data to the platform device's
++ * platform_data pointer.  The memory associated with the platform data
++ * will be freed when the platform device is released.
   */
--static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
-+u8 ata_xfer_mask2mode(unsigned long xfer_mask)
+-int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)
++int platform_device_add_data(struct platform_device *pdev, const void *data,
++			     size_t size)
  {
- 	int highbit = fls(xfer_mask) - 1;
- 	const struct ata_xfer_ent *ent;
-@@ -513,7 +515,7 @@ static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
- 	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
- 		if (highbit >= ent->shift && highbit < ent->shift + ent->bits)
- 			return ent->base + highbit - ent->shift;
--	return 0;
-+	return 0xff;
- }
+ 	void *d;
+ 
+@@ -226,11 +227,11 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, siz
+ EXPORT_SYMBOL_GPL(platform_device_add_data);
  
  /**
-@@ -528,13 +530,14 @@ static u8 ata_xfer_mask2mode(unsigned int xfer_mask)
-  *	RETURNS:
-  *	Matching xfer_mask, 0 if no match found.
+- *	platform_device_add - add a platform device to device hierarchy
+- *	@pdev:	platform device we're adding
++ * platform_device_add - add a platform device to device hierarchy
++ * @pdev: platform device we're adding
+  *
+- *	This is part 2 of platform_device_register(), though may be called
+- *	separately _iff_ pdev was allocated by platform_device_alloc().
++ * This is part 2 of platform_device_register(), though may be called
++ * separately _iff_ pdev was allocated by platform_device_alloc().
   */
--static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
-+unsigned long ata_xfer_mode2mask(u8 xfer_mode)
+ int platform_device_add(struct platform_device *pdev)
  {
- 	const struct ata_xfer_ent *ent;
+@@ -289,13 +290,12 @@ int platform_device_add(struct platform_device *pdev)
+ EXPORT_SYMBOL_GPL(platform_device_add);
  
- 	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
- 		if (xfer_mode >= ent->base && xfer_mode < ent->base + ent->bits)
--			return 1 << (ent->shift + xfer_mode - ent->base);
-+			return ((2 << (ent->shift + xfer_mode - ent->base)) - 1)
-+				& ~((1 << ent->shift) - 1);
- 	return 0;
- }
+ /**
+- *	platform_device_del - remove a platform-level device
+- *	@pdev:	platform device we're removing
++ * platform_device_del - remove a platform-level device
++ * @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).  This function
+- *	must _only_ be externally called in error cases.  All other usage
+- *	is a bug.
++ * Note that this function will also release all memory- and port-based
++ * resources owned by the device (@dev->resource).  This function must
++ * _only_ be externally called in error cases.  All other usage is a bug.
+  */
+ void platform_device_del(struct platform_device *pdev)
+ {
+@@ -314,11 +314,10 @@ void platform_device_del(struct platform_device *pdev)
+ EXPORT_SYMBOL_GPL(platform_device_del);
  
-@@ -550,7 +553,7 @@ static unsigned int ata_xfer_mode2mask(u8 xfer_mode)
-  *	RETURNS:
-  *	Matching xfer_shift, -1 if no match found.
+ /**
+- *	platform_device_register - add a platform-level device
+- *	@pdev:	platform device we're adding
+- *
++ * platform_device_register - add a platform-level device
++ * @pdev: platform device we're adding
   */
--static int ata_xfer_mode2shift(unsigned int xfer_mode)
-+int ata_xfer_mode2shift(unsigned long xfer_mode)
+-int platform_device_register(struct platform_device * pdev)
++int platform_device_register(struct platform_device *pdev)
  {
- 	const struct ata_xfer_ent *ent;
+ 	device_initialize(&pdev->dev);
+ 	return platform_device_add(pdev);
+@@ -326,14 +325,14 @@ int platform_device_register(struct platform_device * pdev)
+ EXPORT_SYMBOL_GPL(platform_device_register);
  
-@@ -574,7 +577,7 @@ static int ata_xfer_mode2shift(unsigned int xfer_mode)
-  *	Constant C string representing highest speed listed in
-  *	@mode_mask, or the constant C string "<n/a>".
+ /**
+- *	platform_device_unregister - unregister a platform-level device
+- *	@pdev:	platform device we're unregistering
++ * platform_device_unregister - unregister a platform-level device
++ * @pdev: platform device we're unregistering
+  *
+- *	Unregistration is done in 2 steps. First we release all resources
+- *	and remove it from the subsystem, then we drop reference count by
+- *	calling platform_device_put().
++ * Unregistration is done in 2 steps. First we release all resources
++ * and remove it from the subsystem, then we drop reference count by
++ * calling platform_device_put().
   */
--static const char *ata_mode_string(unsigned int xfer_mask)
-+const char *ata_mode_string(unsigned long xfer_mask)
+-void platform_device_unregister(struct platform_device * pdev)
++void platform_device_unregister(struct platform_device *pdev)
  {
- 	static const char * const xfer_mode_str[] = {
- 		"PIO0",
-@@ -947,8 +950,8 @@ unsigned int ata_dev_try_classify(struct ata_device *dev, int present,
- 	if (r_err)
- 		*r_err = err;
+ 	platform_device_del(pdev);
+ 	platform_device_put(pdev);
+@@ -341,27 +340,29 @@ void platform_device_unregister(struct platform_device * pdev)
+ EXPORT_SYMBOL_GPL(platform_device_unregister);
  
--	/* see if device passed diags: if master then continue and warn later */
--	if (err == 0 && dev->devno == 0)
-+	/* see if device passed diags: continue and warn later */
-+	if (err == 0)
- 		/* diagnostic fail : do nothing _YET_ */
- 		dev->horkage |= ATA_HORKAGE_DIAGNOSTIC;
- 	else if (err == 1)
-@@ -1286,48 +1289,6 @@ static int ata_hpa_resize(struct ata_device *dev)
+ /**
+- *	platform_device_register_simple
+- *	@name:  base name of the device we're adding
+- *	@id:    instance id
+- *	@res:   set of resources that needs to be allocated for the device
+- *	@num:	number of resources
++ * platform_device_register_simple
++ * @name: base name of the device we're adding
++ * @id: instance id
++ * @res: set of resources that needs to be allocated for the device
++ * @num: number of resources
+  *
+- *	This function creates a simple platform device that requires minimal
+- *	resource and memory management. Canned release function freeing
+- *	memory allocated for the device allows drivers using such devices
+- *	to be unloaded without waiting for the last reference to the device
+- *	to be dropped.
++ * This function creates a simple platform device that requires minimal
++ * resource and memory management. Canned release function freeing memory
++ * allocated for the device allows drivers using such devices to be
++ * unloaded without waiting for the last reference to the device to be
++ * dropped.
+  *
+- *	This interface is primarily intended for use with legacy drivers
+- *	which probe hardware directly.  Because such drivers create sysfs
+- *	device nodes themselves, rather than letting system infrastructure
+- *	handle such device enumeration tasks, they don't fully conform to
+- *	the Linux driver model.  In particular, when such drivers are built
+- *	as modules, they can't be "hotplugged".
++ * This interface is primarily intended for use with legacy drivers which
++ * probe hardware directly.  Because such drivers create sysfs device nodes
++ * themselves, rather than letting system infrastructure handle such device
++ * enumeration tasks, they don't fully conform to the Linux driver model.
++ * In particular, when such drivers are built as modules, they can't be
++ * "hotplugged".
+  */
+-struct platform_device *platform_device_register_simple(char *name, int id,
+-							struct resource *res, unsigned int num)
++struct platform_device *platform_device_register_simple(const char *name,
++							int id,
++							struct resource *res,
++							unsigned int num)
+ {
+ 	struct platform_device *pdev;
+ 	int retval;
+@@ -436,8 +437,8 @@ static int platform_drv_resume(struct device *_dev)
  }
  
  /**
-- *	ata_id_to_dma_mode	-	Identify DMA mode from id block
-- *	@dev: device to identify
-- *	@unknown: mode to assume if we cannot tell
-- *
-- *	Set up the timing values for the device based upon the identify
-- *	reported values for the DMA mode. This function is used by drivers
-- *	which rely upon firmware configured modes, but wish to report the
-- *	mode correctly when possible.
-- *
-- *	In addition we emit similarly formatted messages to the default
-- *	ata_dev_set_mode handler, in order to provide consistency of
-- *	presentation.
-- */
--
--void ata_id_to_dma_mode(struct ata_device *dev, u8 unknown)
--{
--	unsigned int mask;
--	u8 mode;
--
--	/* Pack the DMA modes */
--	mask = ((dev->id[63] >> 8) << ATA_SHIFT_MWDMA) & ATA_MASK_MWDMA;
--	if (dev->id[53] & 0x04)
--		mask |= ((dev->id[88] >> 8) << ATA_SHIFT_UDMA) & ATA_MASK_UDMA;
--
--	/* Select the mode in use */
--	mode = ata_xfer_mask2mode(mask);
--
--	if (mode != 0) {
--		ata_dev_printk(dev, KERN_INFO, "configured for %s\n",
--		       ata_mode_string(mask));
--	} else {
--		/* SWDMA perhaps ? */
--		mode = unknown;
--		ata_dev_printk(dev, KERN_INFO, "configured for DMA\n");
--	}
--
--	/* Configure the device reporting */
--	dev->xfer_mode = mode;
--	dev->xfer_shift = ata_xfer_mode2shift(mode);
--}
--
--/**
-  *	ata_noop_dev_select - Select device 0/1 on ATA bus
-  *	@ap: ATA channel to manipulate
-  *	@device: ATA device (numbered from zero) to select
-@@ -1464,9 +1425,9 @@ static inline void ata_dump_id(const u16 *id)
-  *	RETURNS:
-  *	Computed xfermask
+- *	platform_driver_register
+- *	@drv: platform driver structure
++ * platform_driver_register
++ * @drv: platform driver structure
   */
--static unsigned int ata_id_xfermask(const u16 *id)
-+unsigned long ata_id_xfermask(const u16 *id)
+ int platform_driver_register(struct platform_driver *drv)
  {
--	unsigned int pio_mask, mwdma_mask, udma_mask;
-+	unsigned long pio_mask, mwdma_mask, udma_mask;
+@@ -457,8 +458,8 @@ int platform_driver_register(struct platform_driver *drv)
+ EXPORT_SYMBOL_GPL(platform_driver_register);
  
- 	/* Usual case. Word 53 indicates word 64 is valid */
- 	if (id[ATA_ID_FIELD_VALID] & (1 << 1)) {
-@@ -1519,7 +1480,7 @@ static unsigned int ata_id_xfermask(const u16 *id)
+ /**
+- *	platform_driver_unregister
+- *	@drv: platform driver structure
++ * platform_driver_unregister
++ * @drv: platform driver structure
+  */
+ void platform_driver_unregister(struct platform_driver *drv)
+ {
+@@ -497,12 +498,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
+ 	 * if the probe was successful, and make sure any forced probes of
+ 	 * new devices fail.
+ 	 */
+-	spin_lock(&platform_bus_type.klist_drivers.k_lock);
++	spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
+ 	drv->probe = NULL;
+-	if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
++	if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
+ 		retval = -ENODEV;
+ 	drv->driver.probe = platform_drv_probe_fail;
+-	spin_unlock(&platform_bus_type.klist_drivers.k_lock);
++	spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
+ 
+ 	if (code != retval)
+ 		platform_driver_unregister(drv);
+@@ -516,8 +517,8 @@ EXPORT_SYMBOL_GPL(platform_driver_probe);
+  * (b) sysfs attribute lets new-style coldplug recover from hotplug events
+  *     mishandled before system is fully running:  "modprobe $(cat modalias)"
+  */
+-static ssize_t
+-modalias_show(struct device *dev, struct device_attribute *a, char *buf)
++static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
++			     char *buf)
+ {
+ 	struct platform_device	*pdev = to_platform_device(dev);
+ 	int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
+@@ -538,26 +539,24 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
+ 	return 0;
  }
  
+-
  /**
-- *	ata_port_queue_task - Queue port_task
-+ *	ata_pio_queue_task - Queue port_task
-  *	@ap: The ata_port to queue port_task for
-  *	@fn: workqueue function to be scheduled
-  *	@data: data for @fn to use
-@@ -1531,16 +1492,15 @@ static unsigned int ata_id_xfermask(const u16 *id)
-  *	one task is active at any given time.
-  *
-  *	libata core layer takes care of synchronization between
-- *	port_task and EH.  ata_port_queue_task() may be ignored for EH
-+ *	port_task and EH.  ata_pio_queue_task() may be ignored for EH
-  *	synchronization.
+- *	platform_match - bind platform device to platform driver.
+- *	@dev:	device.
+- *	@drv:	driver.
++ * platform_match - bind platform device to platform driver.
++ * @dev: device.
++ * @drv: driver.
   *
-  *	LOCKING:
-  *	Inherited from caller.
+- *	Platform device IDs are assumed to be encoded like this:
+- *	"<name><instance>", where <name> is a short description of the
+- *	type of device, like "pci" or "floppy", and <instance> is the
+- *	enumerated instance of the device, like '0' or '42'.
+- *	Driver IDs are simply "<name>".
+- *	So, extract the <name> from the platform_device structure,
+- *	and compare it against the name of the driver. Return whether
+- *	they match or not.
++ * Platform device IDs are assumed to be encoded like this:
++ * "<name><instance>", where <name> is a short description of the type of
++ * device, like "pci" or "floppy", and <instance> is the enumerated
++ * instance of the device, like '0' or '42'.  Driver IDs are simply
++ * "<name>".  So, extract the <name> from the platform_device structure,
++ * and compare it against the name of the driver. Return whether they match
++ * or not.
   */
--void ata_port_queue_task(struct ata_port *ap, work_func_t fn, void *data,
--			 unsigned long delay)
-+static void ata_pio_queue_task(struct ata_port *ap, void *data,
-+			       unsigned long delay)
+-
+-static int platform_match(struct device * dev, struct device_driver * drv)
++static int platform_match(struct device *dev, struct device_driver *drv)
  {
--	PREPARE_DELAYED_WORK(&ap->port_task, fn);
- 	ap->port_task_data = data;
+-	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
++	struct platform_device *pdev;
  
- 	/* may fail if ata_port_flush_task() in progress */
-@@ -2090,7 +2050,7 @@ int ata_dev_configure(struct ata_device *dev)
- 	struct ata_eh_context *ehc = &dev->link->eh_context;
- 	int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
- 	const u16 *id = dev->id;
--	unsigned int xfer_mask;
-+	unsigned long xfer_mask;
- 	char revbuf[7];		/* XYZ-99\0 */
- 	char fwrevbuf[ATA_ID_FW_REV_LEN+1];
- 	char modelbuf[ATA_ID_PROD_LEN+1];
-@@ -2161,8 +2121,14 @@ int ata_dev_configure(struct ata_device *dev)
- 					       "supports DRM functions and may "
- 					       "not be fully accessable.\n");
- 			snprintf(revbuf, 7, "CFA");
--		} else
-+		} else {
- 			snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
-+			/* Warn the user if the device has TPM extensions */
-+			if (ata_id_has_tpm(id))
-+				ata_dev_printk(dev, KERN_WARNING,
-+					       "supports DRM functions and may "
-+					       "not be fully accessable.\n");
-+		}
++	pdev = container_of(dev, struct platform_device, dev);
+ 	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
+ }
  
- 		dev->n_sectors = ata_id_n_sectors(id);
+@@ -574,9 +573,10 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
+ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
+ {
+ 	struct platform_driver *drv = to_platform_driver(dev->driver);
+-	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
++	struct platform_device *pdev;
+ 	int ret = 0;
  
-@@ -2295,19 +2261,8 @@ int ata_dev_configure(struct ata_device *dev)
- 			dev->flags |= ATA_DFLAG_DIPM;
- 	}
++	pdev = container_of(dev, struct platform_device, dev);
+ 	if (dev->driver && drv->suspend_late)
+ 		ret = drv->suspend_late(pdev, mesg);
  
--	if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
--		/* Let the user know. We don't want to disallow opens for
--		   rescue purposes, or in case the vendor is just a blithering
--		   idiot */
--		if (print_info) {
--			ata_dev_printk(dev, KERN_WARNING,
--"Drive reports diagnostics failure. This may indicate a drive\n");
--			ata_dev_printk(dev, KERN_WARNING,
--"fault or invalid emulation. Contact drive vendor for information.\n");
--		}
--	}
--
--	/* limit bridge transfers to udma5, 200 sectors */
-+	/* Limit PATA drive on SATA cable bridge transfers to udma5,
-+	   200 sectors */
- 	if (ata_dev_knobble(dev)) {
- 		if (ata_msg_drv(ap) && print_info)
- 			ata_dev_printk(dev, KERN_INFO,
-@@ -2336,6 +2291,21 @@ int ata_dev_configure(struct ata_device *dev)
- 	if (ap->ops->dev_config)
- 		ap->ops->dev_config(dev);
+@@ -586,16 +586,17 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
+ static int platform_resume_early(struct device *dev)
+ {
+ 	struct platform_driver *drv = to_platform_driver(dev->driver);
+-	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
++	struct platform_device *pdev;
+ 	int ret = 0;
  
-+	if (dev->horkage & ATA_HORKAGE_DIAGNOSTIC) {
-+		/* Let the user know. We don't want to disallow opens for
-+		   rescue purposes, or in case the vendor is just a blithering
-+		   idiot. Do this after the dev_config call as some controllers
-+		   with buggy firmware may want to avoid reporting false device
-+		   bugs */
++	pdev = container_of(dev, struct platform_device, dev);
+ 	if (dev->driver && drv->resume_early)
+ 		ret = drv->resume_early(pdev);
+ 
+ 	return ret;
+ }
+ 
+-static int platform_resume(struct device * dev)
++static int platform_resume(struct device *dev)
+ {
+ 	int ret = 0;
+ 
+diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
+index 44504e6..911208b 100644
+--- a/drivers/base/power/Makefile
++++ b/drivers/base/power/Makefile
+@@ -1,11 +1,6 @@
+-obj-y			:= shutdown.o
+ obj-$(CONFIG_PM)	+= sysfs.o
+ obj-$(CONFIG_PM_SLEEP)	+= main.o
+-obj-$(CONFIG_PM_TRACE)	+= trace.o
++obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
+ 
+-ifeq ($(CONFIG_DEBUG_DRIVER),y)
+-EXTRA_CFLAGS += -DDEBUG
+-endif
+-ifeq ($(CONFIG_PM_VERBOSE),y)
+-EXTRA_CFLAGS += -DDEBUG
+-endif
++ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
++ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index 691ffb6..bdc03f7 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -24,20 +24,45 @@
+ #include <linux/mutex.h>
+ #include <linux/pm.h>
+ #include <linux/resume-trace.h>
++#include <linux/rwsem.h>
+ 
+ #include "../base.h"
+ #include "power.h"
+ 
++/*
++ * The entries in the dpm_active list are in a depth first order, simply
++ * because children are guaranteed to be discovered after parents, and
++ * are inserted at the back of the list on discovery.
++ *
++ * All the other lists are kept in the same order, for consistency.
++ * However the lists aren't always traversed in the same order.
++ * Semaphores must be acquired from the top (i.e., front) down
++ * and released in the opposite order.  Devices must be suspended
++ * from the bottom (i.e., end) up and resumed in the opposite order.
++ * That way no parent will be suspended while it still has an active
++ * child.
++ *
++ * Since device_pm_add() may be called with a device semaphore held,
++ * we must never try to acquire a device semaphore while holding
++ * dpm_list_mutex.
++ */
 +
-+		if (print_info) {
-+			ata_dev_printk(dev, KERN_WARNING,
-+"Drive reports diagnostics failure. This may indicate a drive\n");
-+			ata_dev_printk(dev, KERN_WARNING,
-+"fault or invalid emulation. Contact drive vendor for information.\n");
+ LIST_HEAD(dpm_active);
++static LIST_HEAD(dpm_locked);
+ static LIST_HEAD(dpm_off);
+ static LIST_HEAD(dpm_off_irq);
++static LIST_HEAD(dpm_destroy);
+ 
+-static DEFINE_MUTEX(dpm_mtx);
+ static DEFINE_MUTEX(dpm_list_mtx);
+ 
+-int (*platform_enable_wakeup)(struct device *dev, int is_on);
++static DECLARE_RWSEM(pm_sleep_rwsem);
+ 
++int (*platform_enable_wakeup)(struct device *dev, int is_on);
+ 
++/**
++ *	device_pm_add - add a device to the list of active devices
++ *	@dev:	Device to be added to the list
++ */
+ void device_pm_add(struct device *dev)
+ {
+ 	pr_debug("PM: Adding info for %s:%s\n",
+@@ -48,8 +73,36 @@ void device_pm_add(struct device *dev)
+ 	mutex_unlock(&dpm_list_mtx);
+ }
+ 
++/**
++ *	device_pm_remove - remove a device from the list of active devices
++ *	@dev:	Device to be removed from the list
++ *
++ *	This function also removes the device's PM-related sysfs attributes.
++ */
+ void device_pm_remove(struct device *dev)
+ {
++	/*
++	 * If this function is called during a suspend, it will be blocked,
++	 * because we're holding the device's semaphore at that time, which may
++	 * lead to a deadlock.  In that case we want to print a warning.
++	 * However, it may also be called by unregister_dropped_devices() with
++	 * the device's semaphore released, in which case the warning should
++	 * not be printed.
++	 */
++	if (down_trylock(&dev->sem)) {
++		if (down_read_trylock(&pm_sleep_rwsem)) {
++			/* No suspend in progress, wait on dev->sem */
++			down(&dev->sem);
++			up_read(&pm_sleep_rwsem);
++		} else {
++			/* Suspend in progress, we may deadlock */
++			dev_warn(dev, "Suspicious %s during suspend\n",
++				__FUNCTION__);
++			dump_stack();
++			/* The user has been warned ... */
++			down(&dev->sem);
 +		}
 +	}
+ 	pr_debug("PM: Removing info for %s:%s\n",
+ 		 dev->bus ? dev->bus->name : "No Bus",
+ 		 kobject_name(&dev->kobj));
+@@ -57,25 +110,125 @@ void device_pm_remove(struct device *dev)
+ 	dpm_sysfs_remove(dev);
+ 	list_del_init(&dev->power.entry);
+ 	mutex_unlock(&dpm_list_mtx);
++	up(&dev->sem);
++}
 +
- 	if (ata_msg_probe(ap))
- 		ata_dev_printk(dev, KERN_DEBUG, "%s: EXIT, drv_stat = 0x%x\n",
- 			__FUNCTION__, ata_chk_status(ap));
-@@ -2387,6 +2357,18 @@ int ata_cable_unknown(struct ata_port *ap)
- }
- 
- /**
-+ *	ata_cable_ignore	-	return ignored PATA cable.
-+ *	@ap: port
++/**
++ *	device_pm_schedule_removal - schedule the removal of a suspended device
++ *	@dev:	Device to destroy
 + *
-+ *	Helper method for drivers which don't use cable type to limit
-+ *	transfer mode.
++ *	Moves the device to the dpm_destroy list for further processing by
++ *	unregister_dropped_devices().
 + */
-+int ata_cable_ignore(struct ata_port *ap)
++void device_pm_schedule_removal(struct device *dev)
 +{
-+	return ATA_CBL_PATA_IGN;
++	pr_debug("PM: Preparing for removal: %s:%s\n",
++		dev->bus ? dev->bus->name : "No Bus",
++		kobject_name(&dev->kobj));
++	mutex_lock(&dpm_list_mtx);
++	list_move_tail(&dev->power.entry, &dpm_destroy);
++	mutex_unlock(&dpm_list_mtx);
 +}
++EXPORT_SYMBOL_GPL(device_pm_schedule_removal);
 +
 +/**
-  *	ata_cable_sata	-	return SATA cable type
-  *	@ap: port
++ *	pm_sleep_lock - mutual exclusion for registration and suspend
++ *
++ *	Returns 0 if no suspend is underway and device registration
++ *	may proceed, otherwise -EBUSY.
++ */
++int pm_sleep_lock(void)
++{
++	if (down_read_trylock(&pm_sleep_rwsem))
++		return 0;
++
++	return -EBUSY;
++}
++
++/**
++ *	pm_sleep_unlock - mutual exclusion for registration and suspend
++ *
++ *	This routine undoes the effect of device_pm_add_lock
++ *	when a device's registration is complete.
++ */
++void pm_sleep_unlock(void)
++{
++	up_read(&pm_sleep_rwsem);
+ }
+ 
+ 
+ /*------------------------- Resume routines -------------------------*/
+ 
+ /**
+- *	resume_device - Restore state for one device.
++ *	resume_device_early - Power on one device (early resume).
+  *	@dev:	Device.
   *
-@@ -2781,38 +2763,33 @@ int sata_set_spd(struct ata_link *link)
++ *	Must be called with interrupts disabled.
   */
+-
+-static int resume_device(struct device * dev)
++static int resume_device_early(struct device *dev)
+ {
+ 	int error = 0;
  
- static const struct ata_timing ata_timing[] = {
-+/*	{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 }, */
-+	{ XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
-+	{ XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
-+	{ XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
-+	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
-+	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
-+	{ XFER_PIO_5,     15,  65,  25, 100,  65,  25, 100,   0 },
-+	{ XFER_PIO_6,     10,  55,  20,  80,  55,  20,  80,   0 },
+ 	TRACE_DEVICE(dev);
+ 	TRACE_RESUME(0);
  
--	{ XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
--	{ XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
--	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
--	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
-+	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
-+	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
-+	{ XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
+-	down(&dev->sem);
++	if (dev->bus && dev->bus->resume_early) {
++		dev_dbg(dev, "EARLY resume\n");
++		error = dev->bus->resume_early(dev);
++	}
++
++	TRACE_RESUME(error);
++	return error;
++}
++
++/**
++ *	dpm_power_up - Power on all regular (non-sysdev) devices.
++ *
++ *	Walk the dpm_off_irq list and power each device up. This
++ *	is used for devices that required they be powered down with
++ *	interrupts disabled. As devices are powered on, they are moved
++ *	to the dpm_off list.
++ *
++ *	Must be called with interrupts disabled and only one CPU running.
++ */
++static void dpm_power_up(void)
++{
++
++	while (!list_empty(&dpm_off_irq)) {
++		struct list_head *entry = dpm_off_irq.next;
++		struct device *dev = to_device(entry);
++
++		list_move_tail(entry, &dpm_off);
++		resume_device_early(dev);
++	}
++}
++
++/**
++ *	device_power_up - Turn on all devices that need special attention.
++ *
++ *	Power on system devices, then devices that required we shut them down
++ *	with interrupts disabled.
++ *
++ *	Must be called with interrupts disabled.
++ */
++void device_power_up(void)
++{
++	sysdev_resume();
++	dpm_power_up();
++}
++EXPORT_SYMBOL_GPL(device_power_up);
++
++/**
++ *	resume_device - Restore state for one device.
++ *	@dev:	Device.
++ *
++ */
++static int resume_device(struct device *dev)
++{
++	int error = 0;
++
++	TRACE_DEVICE(dev);
++	TRACE_RESUME(0);
  
--	{ XFER_MW_DMA_4,  25,   0,   0,   0,  55,  20,  80,   0 },
-+	{ XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
-+	{ XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
-+	{ XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
- 	{ XFER_MW_DMA_3,  25,   0,   0,   0,  65,  25, 100,   0 },
--	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
--	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
--	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
-+	{ XFER_MW_DMA_4,  25,   0,   0,   0,  55,  20,  80,   0 },
+ 	if (dev->bus && dev->bus->resume) {
+ 		dev_dbg(dev,"resuming\n");
+@@ -92,126 +245,94 @@ static int resume_device(struct device * dev)
+ 		error = dev->class->resume(dev);
+ 	}
  
- /*	{ XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 }, */
+-	up(&dev->sem);
 -
--	{ XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
--	{ XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
--	{ XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
+ 	TRACE_RESUME(error);
+ 	return error;
+ }
+ 
 -
--	{ XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
--	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
--	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
+-static int resume_device_early(struct device * dev)
+-{
+-	int error = 0;
 -
--	{ XFER_PIO_6,     10,  55,  20,  80,  55,  20,  80,   0 },
--	{ XFER_PIO_5,     15,  65,  25, 100,  65,  25, 100,   0 },
--	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
--	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
+-	TRACE_DEVICE(dev);
+-	TRACE_RESUME(0);
+-	if (dev->bus && dev->bus->resume_early) {
+-		dev_dbg(dev,"EARLY resume\n");
+-		error = dev->bus->resume_early(dev);
+-	}
+-	TRACE_RESUME(error);
+-	return error;
+-}
 -
--	{ XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
--	{ XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
--	{ XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
+-/*
+- * Resume the devices that have either not gone through
+- * the late suspend, or that did go through it but also
+- * went through the early resume
++/**
++ *	dpm_resume - Resume every device.
++ *
++ *	Resume the devices that have either not gone through
++ *	the late suspend, or that did go through it but also
++ *	went through the early resume.
++ *
++ *	Take devices from the dpm_off_list, resume them,
++ *	and put them on the dpm_locked list.
+  */
+ static void dpm_resume(void)
+ {
+ 	mutex_lock(&dpm_list_mtx);
+ 	while(!list_empty(&dpm_off)) {
+-		struct list_head * entry = dpm_off.next;
+-		struct device * dev = to_device(entry);
 -
--/*	{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 }, */
-+	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
-+	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
-+	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
-+	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
-+	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
-+	{ XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
-+	{ XFER_UDMA_6,     0,   0,   0,   0,   0,   0,   0,  15 },
+-		get_device(dev);
+-		list_move_tail(entry, &dpm_active);
++		struct list_head *entry = dpm_off.next;
++		struct device *dev = to_device(entry);
  
- 	{ 0xFF }
- };
-@@ -2845,14 +2822,16 @@ void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b,
- 	if (what & ATA_TIMING_UDMA   ) m->udma    = max(a->udma,    b->udma);
++		list_move_tail(entry, &dpm_locked);
+ 		mutex_unlock(&dpm_list_mtx);
+ 		resume_device(dev);
+ 		mutex_lock(&dpm_list_mtx);
+-		put_device(dev);
+ 	}
+ 	mutex_unlock(&dpm_list_mtx);
  }
  
--static const struct ata_timing *ata_timing_find_mode(unsigned short speed)
-+const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
+-
+ /**
+- *	device_resume - Restore state of each device in system.
++ *	unlock_all_devices - Release each device's semaphore
+  *
+- *	Walk the dpm_off list, remove each entry, resume the device,
+- *	then add it to the dpm_active list.
++ *	Go through the dpm_off list.  Put each device on the dpm_active
++ *	list and unlock it.
+  */
+-
+-void device_resume(void)
++static void unlock_all_devices(void)
  {
--	const struct ata_timing *t;
-+	const struct ata_timing *t = ata_timing;
-+
-+	while (xfer_mode > t->mode)
-+		t++;
+-	might_sleep();
+-	mutex_lock(&dpm_mtx);
+-	dpm_resume();
+-	mutex_unlock(&dpm_mtx);
+-}
+-
+-EXPORT_SYMBOL_GPL(device_resume);
++	mutex_lock(&dpm_list_mtx);
++	while (!list_empty(&dpm_locked)) {
++		struct list_head *entry = dpm_locked.prev;
++		struct device *dev = to_device(entry);
  
--	for (t = ata_timing; t->mode != speed; t++)
--		if (t->mode == 0xFF)
--			return NULL;
--	return t;
-+	if (xfer_mode == t->mode)
-+		return t;
-+	return NULL;
++		list_move(entry, &dpm_active);
++		up(&dev->sem);
++	}
++	mutex_unlock(&dpm_list_mtx);
++}
+ 
+ /**
+- *	dpm_power_up - Power on some devices.
+- *
+- *	Walk the dpm_off_irq list and power each device up. This
+- *	is used for devices that required they be powered down with
+- *	interrupts disabled. As devices are powered on, they are moved
+- *	to the dpm_active list.
++ *	unregister_dropped_devices - Unregister devices scheduled for removal
+  *
+- *	Interrupts must be disabled when calling this.
++ *	Unregister all devices on the dpm_destroy list.
+  */
+-
+-static void dpm_power_up(void)
++static void unregister_dropped_devices(void)
+ {
+-	while(!list_empty(&dpm_off_irq)) {
+-		struct list_head * entry = dpm_off_irq.next;
+-		struct device * dev = to_device(entry);
++	mutex_lock(&dpm_list_mtx);
++	while (!list_empty(&dpm_destroy)) {
++		struct list_head *entry = dpm_destroy.next;
++		struct device *dev = to_device(entry);
+ 
+-		list_move_tail(entry, &dpm_off);
+-		resume_device_early(dev);
++		up(&dev->sem);
++		mutex_unlock(&dpm_list_mtx);
++		/* This also removes the device from the list */
++		device_unregister(dev);
++		mutex_lock(&dpm_list_mtx);
+ 	}
++	mutex_unlock(&dpm_list_mtx);
  }
  
- int ata_timing_compute(struct ata_device *adev, unsigned short speed,
-@@ -2927,6 +2906,57 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
+-
+ /**
+- *	device_power_up - Turn on all devices that need special attention.
++ *	device_resume - Restore state of each device in system.
+  *
+- *	Power on system devices then devices that required we shut them down
+- *	with interrupts disabled.
+- *	Called with interrupts disabled.
++ *	Resume all the devices, unlock them all, and allow new
++ *	devices to be registered once again.
+  */
+-
+-void device_power_up(void)
++void device_resume(void)
+ {
+-	sysdev_resume();
+-	dpm_power_up();
++	might_sleep();
++	dpm_resume();
++	unlock_all_devices();
++	unregister_dropped_devices();
++	up_write(&pm_sleep_rwsem);
+ }
+-
+-EXPORT_SYMBOL_GPL(device_power_up);
++EXPORT_SYMBOL_GPL(device_resume);
+ 
+ 
+ /*------------------------- Suspend routines -------------------------*/
+ 
+-/*
+- * The entries in the dpm_active list are in a depth first order, simply
+- * because children are guaranteed to be discovered after parents, and
+- * are inserted at the back of the list on discovery.
+- *
+- * All list on the suspend path are done in reverse order, so we operate
+- * on the leaves of the device tree (or forests, depending on how you want
+- * to look at it ;) first. As nodes are removed from the back of the list,
+- * they are inserted into the front of their destintation lists.
+- *
+- * Things are the reverse on the resume path - iterations are done in
+- * forward order, and nodes are inserted at the back of their destination
+- * lists. This way, the ancestors will be accessed before their descendents.
+- */
+-
+ static inline char *suspend_verb(u32 event)
+ {
+ 	switch (event) {
+@@ -222,7 +343,6 @@ static inline char *suspend_verb(u32 event)
+ 	}
+ }
+ 
+-
+ static void
+ suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
+ {
+@@ -232,16 +352,73 @@ suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
  }
  
  /**
-+ *	ata_timing_cycle2mode - find xfer mode for the specified cycle duration
-+ *	@xfer_shift: ATA_SHIFT_* value for transfer type to examine.
-+ *	@cycle: cycle duration in ns
+- *	suspend_device - Save state of one device.
++ *	suspend_device_late - Shut down one device (late suspend).
+  *	@dev:	Device.
+  *	@state:	Power state device is entering.
 + *
-+ *	Return matching xfer mode for @cycle.  The returned mode is of
-+ *	the transfer type specified by @xfer_shift.  If @cycle is too
-+ *	slow for @xfer_shift, 0xff is returned.  If @cycle is faster
-+ *	than the fastest known mode, the fasted mode is returned.
++ *	This is called with interrupts off and only a single CPU running.
+  */
++static int suspend_device_late(struct device *dev, pm_message_t state)
++{
++	int error = 0;
+ 
+-static int suspend_device(struct device * dev, pm_message_t state)
++	if (dev->bus && dev->bus->suspend_late) {
++		suspend_device_dbg(dev, state, "LATE ");
++		error = dev->bus->suspend_late(dev, state);
++		suspend_report_result(dev->bus->suspend_late, error);
++	}
++	return error;
++}
++
++/**
++ *	device_power_down - Shut down special devices.
++ *	@state:		Power state to enter.
 + *
-+ *	LOCKING:
-+ *	None.
++ *	Power down devices that require interrupts to be disabled
++ *	and move them from the dpm_off list to the dpm_off_irq list.
++ *	Then power down system devices.
 + *
-+ *	RETURNS:
-+ *	Matching xfer_mode, 0xff if no match found.
++ *	Must be called with interrupts disabled and only one CPU running.
 + */
-+u8 ata_timing_cycle2mode(unsigned int xfer_shift, int cycle)
++int device_power_down(pm_message_t state)
 +{
-+	u8 base_mode = 0xff, last_mode = 0xff;
-+	const struct ata_xfer_ent *ent;
-+	const struct ata_timing *t;
-+
-+	for (ent = ata_xfer_tbl; ent->shift >= 0; ent++)
-+		if (ent->shift == xfer_shift)
-+			base_mode = ent->base;
++	int error = 0;
 +
-+	for (t = ata_timing_find_mode(base_mode);
-+	     t && ata_xfer_mode2shift(t->mode) == xfer_shift; t++) {
-+		unsigned short this_cycle;
++	while (!list_empty(&dpm_off)) {
++		struct list_head *entry = dpm_off.prev;
++		struct device *dev = to_device(entry);
 +
-+		switch (xfer_shift) {
-+		case ATA_SHIFT_PIO:
-+		case ATA_SHIFT_MWDMA:
-+			this_cycle = t->cycle;
-+			break;
-+		case ATA_SHIFT_UDMA:
-+			this_cycle = t->udma;
++		list_del_init(&dev->power.entry);
++		error = suspend_device_late(dev, state);
++		if (error) {
++			printk(KERN_ERR "Could not power down device %s: "
++					"error %d\n",
++					kobject_name(&dev->kobj), error);
++			if (list_empty(&dev->power.entry))
++				list_add(&dev->power.entry, &dpm_off);
 +			break;
-+		default:
-+			return 0xff;
 +		}
-+
-+		if (cycle > this_cycle)
-+			break;
-+
-+		last_mode = t->mode;
++		if (list_empty(&dev->power.entry))
++			list_add(&dev->power.entry, &dpm_off_irq);
 +	}
 +
-+	return last_mode;
++	if (!error)
++		error = sysdev_suspend(state);
++	if (error)
++		dpm_power_up();
++	return error;
 +}
++EXPORT_SYMBOL_GPL(device_power_down);
 +
 +/**
-  *	ata_down_xfermask_limit - adjust dev xfer masks downward
-  *	@dev: Device to adjust xfer masks
-  *	@sel: ATA_DNXFER_* selector
-@@ -2944,8 +2974,8 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
- int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel)
++ *	suspend_device - Save state of one device.
++ *	@dev:	Device.
++ *	@state:	Power state device is entering.
++ */
++int suspend_device(struct device *dev, pm_message_t state)
  {
- 	char buf[32];
--	unsigned int orig_mask, xfer_mask;
--	unsigned int pio_mask, mwdma_mask, udma_mask;
-+	unsigned long orig_mask, xfer_mask;
-+	unsigned long pio_mask, mwdma_mask, udma_mask;
- 	int quiet, highbit;
+ 	int error = 0;
  
- 	quiet = !!(sel & ATA_DNXFER_QUIET);
-@@ -3039,7 +3069,7 @@ static int ata_dev_set_mode(struct ata_device *dev)
+-	down(&dev->sem);
+ 	if (dev->power.power_state.event) {
+ 		dev_dbg(dev, "PM: suspend %d-->%d\n",
+ 			dev->power.power_state.event, state.event);
+@@ -264,123 +441,105 @@ static int suspend_device(struct device * dev, pm_message_t state)
+ 		error = dev->bus->suspend(dev, state);
+ 		suspend_report_result(dev->bus->suspend, error);
+ 	}
+-	up(&dev->sem);
+-	return error;
+-}
+-
+-
+-/*
+- * This is called with interrupts off, only a single CPU
+- * running. We can't acquire a mutex or semaphore (and we don't
+- * need the protection)
+- */
+-static int suspend_device_late(struct device *dev, pm_message_t state)
+-{
+-	int error = 0;
+-
+-	if (dev->bus && dev->bus->suspend_late) {
+-		suspend_device_dbg(dev, state, "LATE ");
+-		error = dev->bus->suspend_late(dev, state);
+-		suspend_report_result(dev->bus->suspend_late, error);
+-	}
+ 	return error;
+ }
  
- 	/* Early MWDMA devices do DMA but don't allow DMA mode setting.
- 	   Don't fail an MWDMA0 set IFF the device indicates it is in MWDMA0 */
--	if (dev->xfer_shift == ATA_SHIFT_MWDMA && 
-+	if (dev->xfer_shift == ATA_SHIFT_MWDMA &&
- 	    dev->dma_mode == XFER_MW_DMA_0 &&
- 	    (dev->id[63] >> 8) & 1)
- 		err_mask &= ~AC_ERR_DEV;
-@@ -3089,7 +3119,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ /**
+- *	device_suspend - Save state and stop all devices in system.
+- *	@state:		Power state to put each device in.
++ *	dpm_suspend - Suspend every device.
++ *	@state:	Power state to put each device in.
+  *
+- *	Walk the dpm_active list, call ->suspend() for each device, and move
+- *	it to the dpm_off list.
++ *	Walk the dpm_locked list.  Suspend each device and move it
++ *	to the dpm_off list.
+  *
+  *	(For historical reasons, if it returns -EAGAIN, that used to mean
+  *	that the device would be called again with interrupts disabled.
+  *	These days, we use the "suspend_late()" callback for that, so we
+  *	print a warning and consider it an error).
+- *
+- *	If we get a different error, try and back out.
+- *
+- *	If we hit a failure with any of the devices, call device_resume()
+- *	above to bring the suspended devices back to life.
+- *
+  */
+-
+-int device_suspend(pm_message_t state)
++static int dpm_suspend(pm_message_t state)
+ {
+ 	int error = 0;
  
- 	/* step 1: calculate xfer_mask */
- 	ata_link_for_each_dev(dev, link) {
--		unsigned int pio_mask, dma_mask;
-+		unsigned long pio_mask, dma_mask;
- 		unsigned int mode_mask;
+-	might_sleep();
+-	mutex_lock(&dpm_mtx);
+ 	mutex_lock(&dpm_list_mtx);
+-	while (!list_empty(&dpm_active) && error == 0) {
+-		struct list_head * entry = dpm_active.prev;
+-		struct device * dev = to_device(entry);
++	while (!list_empty(&dpm_locked)) {
++		struct list_head *entry = dpm_locked.prev;
++		struct device *dev = to_device(entry);
  
- 		if (!ata_dev_enabled(dev))
-@@ -3115,7 +3145,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
- 		dev->dma_mode = ata_xfer_mask2mode(dma_mask);
+-		get_device(dev);
++		list_del_init(&dev->power.entry);
+ 		mutex_unlock(&dpm_list_mtx);
+-
+ 		error = suspend_device(dev, state);
+-
+-		mutex_lock(&dpm_list_mtx);
+-
+-		/* Check if the device got removed */
+-		if (!list_empty(&dev->power.entry)) {
+-			/* Move it to the dpm_off list */
+-			if (!error)
+-				list_move(&dev->power.entry, &dpm_off);
+-		}
+-		if (error)
++		if (error) {
+ 			printk(KERN_ERR "Could not suspend device %s: "
+-				"error %d%s\n",
+-				kobject_name(&dev->kobj), error,
+-				error == -EAGAIN ? " (please convert to suspend_late)" : "");
+-		put_device(dev);
++					"error %d%s\n",
++					kobject_name(&dev->kobj),
++					error,
++					(error == -EAGAIN ?
++					" (please convert to suspend_late)" :
++					""));
++			mutex_lock(&dpm_list_mtx);
++			if (list_empty(&dev->power.entry))
++				list_add(&dev->power.entry, &dpm_locked);
++			mutex_unlock(&dpm_list_mtx);
++			break;
++		}
++		mutex_lock(&dpm_list_mtx);
++		if (list_empty(&dev->power.entry))
++			list_add(&dev->power.entry, &dpm_off);
+ 	}
+ 	mutex_unlock(&dpm_list_mtx);
+-	if (error)
+-		dpm_resume();
  
- 		found = 1;
--		if (dev->dma_mode)
-+		if (dev->dma_mode != 0xff)
- 			used_dma = 1;
+-	mutex_unlock(&dpm_mtx);
+ 	return error;
+ }
+ 
+-EXPORT_SYMBOL_GPL(device_suspend);
+-
+ /**
+- *	device_power_down - Shut down special devices.
+- *	@state:		Power state to enter.
++ *	lock_all_devices - Acquire every device's semaphore
+  *
+- *	Walk the dpm_off_irq list, calling ->power_down() for each device that
+- *	couldn't power down the device with interrupts enabled. When we're
+- *	done, power down system devices.
++ *	Go through the dpm_active list. Carefully lock each device's
++ *	semaphore and put it in on the dpm_locked list.
+  */
+-
+-int device_power_down(pm_message_t state)
++static void lock_all_devices(void)
+ {
+-	int error = 0;
+-	struct device * dev;
++	mutex_lock(&dpm_list_mtx);
++	while (!list_empty(&dpm_active)) {
++		struct list_head *entry = dpm_active.next;
++		struct device *dev = to_device(entry);
+ 
+-	while (!list_empty(&dpm_off)) {
+-		struct list_head * entry = dpm_off.prev;
++		/* Required locking order is dev->sem first,
++		 * then dpm_list_mutex.  Hence this awkward code.
++		 */
++		get_device(dev);
++		mutex_unlock(&dpm_list_mtx);
++		down(&dev->sem);
++		mutex_lock(&dpm_list_mtx);
+ 
+-		dev = to_device(entry);
+-		error = suspend_device_late(dev, state);
+-		if (error)
+-			goto Error;
+-		list_move(&dev->power.entry, &dpm_off_irq);
++		if (list_empty(entry))
++			up(&dev->sem);		/* Device was removed */
++		else
++			list_move_tail(entry, &dpm_locked);
++		put_device(dev);
  	}
- 	if (!found)
-@@ -3126,7 +3156,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
- 		if (!ata_dev_enabled(dev))
- 			continue;
++	mutex_unlock(&dpm_list_mtx);
++}
++
++/**
++ *	device_suspend - Save state and stop all devices in system.
++ *
++ *	Prevent new devices from being registered, then lock all devices
++ *	and suspend them.
++ */
++int device_suspend(pm_message_t state)
++{
++	int error;
  
--		if (!dev->pio_mode) {
-+		if (dev->pio_mode == 0xff) {
- 			ata_dev_printk(dev, KERN_WARNING, "no PIO support\n");
- 			rc = -EINVAL;
- 			goto out;
-@@ -3140,7 +3170,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+-	error = sysdev_suspend(state);
+- Done:
++	might_sleep();
++	down_write(&pm_sleep_rwsem);
++	lock_all_devices();
++	error = dpm_suspend(state);
++	if (error)
++		device_resume();
+ 	return error;
+- Error:
+-	printk(KERN_ERR "Could not power down device %s: "
+-		"error %d\n", kobject_name(&dev->kobj), error);
+-	dpm_power_up();
+-	goto Done;
+ }
+-
+-EXPORT_SYMBOL_GPL(device_power_down);
++EXPORT_SYMBOL_GPL(device_suspend);
  
- 	/* step 3: set host DMA timings */
- 	ata_link_for_each_dev(dev, link) {
--		if (!ata_dev_enabled(dev) || !dev->dma_mode)
-+		if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff)
- 			continue;
+ void __suspend_report_result(const char *function, void *fn, int ret)
+ {
+diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
+index 379da4e..e32d3bd 100644
+--- a/drivers/base/power/power.h
++++ b/drivers/base/power/power.h
+@@ -1,10 +1,3 @@
+-/*
+- * shutdown.c
+- */
+-
+-extern void device_shutdown(void);
+-
+-
+ #ifdef CONFIG_PM_SLEEP
  
- 		dev->xfer_mode = dev->dma_mode;
-@@ -3173,31 +3203,6 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+ /*
+@@ -20,6 +13,8 @@ static inline struct device *to_device(struct list_head *entry)
+ 
+ extern void device_pm_add(struct device *);
+ extern void device_pm_remove(struct device *);
++extern int pm_sleep_lock(void);
++extern void pm_sleep_unlock(void);
+ 
+ #else /* CONFIG_PM_SLEEP */
+ 
+@@ -32,6 +27,15 @@ static inline void device_pm_remove(struct device *dev)
+ {
  }
  
- /**
-- *	ata_set_mode - Program timings and issue SET FEATURES - XFER
-- *	@link: link on which timings will be programmed
-- *	@r_failed_dev: out paramter for failed device
++static inline int pm_sleep_lock(void)
++{
++	return 0;
++}
++
++static inline void pm_sleep_unlock(void)
++{
++}
++
+ #endif
+ 
+ #ifdef CONFIG_PM
+diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
+deleted file mode 100644
+index 56e8eaa..0000000
+--- a/drivers/base/power/shutdown.c
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * shutdown.c - power management functions for the device tree.
 - *
-- *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
-- *	ata_set_mode() fails, pointer to the failing device is
-- *	returned in @r_failed_dev.
+- * Copyright (c) 2002-3 Patrick Mochel
+- *		 2002-3 Open Source Development Lab
 - *
-- *	LOCKING:
-- *	PCI/etc. bus probe sem.
+- * This file is released under the GPLv2
 - *
-- *	RETURNS:
-- *	0 on success, negative errno otherwise
 - */
--int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
+-
+-#include <linux/device.h>
+-#include <asm/semaphore.h>
+-
+-#include "../base.h"
+-#include "power.h"
+-
+-#define to_dev(node) container_of(node, struct device, kobj.entry)
+-
+-
+-/**
+- * We handle system devices differently - we suspend and shut them
+- * down last and resume them first. That way, we don't do anything stupid like
+- * shutting down the interrupt controller before any devices..
+- *
+- * Note that there are not different stages for power management calls -
+- * they only get one called once when interrupts are disabled.
+- */
+-
+-
+-/**
+- * device_shutdown - call ->shutdown() on each device to shutdown.
+- */
+-void device_shutdown(void)
 -{
--	struct ata_port *ap = link->ap;
+-	struct device * dev, *devn;
 -
--	/* has private set_mode? */
--	if (ap->ops->set_mode)
--		return ap->ops->set_mode(link, r_failed_dev);
--	return ata_do_set_mode(link, r_failed_dev);
+-	list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.list,
+-				kobj.entry) {
+-		if (dev->bus && dev->bus->shutdown) {
+-			dev_dbg(dev, "shutdown\n");
+-			dev->bus->shutdown(dev);
+-		} else if (dev->driver && dev->driver->shutdown) {
+-			dev_dbg(dev, "shutdown\n");
+-			dev->driver->shutdown(dev);
+-		}
+-	}
 -}
 -
--/**
-  *	ata_tf_to_host - issue ATA taskfile to host controller
-  *	@ap: port to which command is being issued
-  *	@tf: ATA taskfile register set
-@@ -4363,7 +4368,14 @@ static unsigned int ata_dev_set_xfermode(struct ata_device *dev)
- 	tf.feature = SETFEATURES_XFER;
- 	tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_POLLING;
- 	tf.protocol = ATA_PROT_NODATA;
--	tf.nsect = dev->xfer_mode;
-+	/* If we are using IORDY we must send the mode setting command */
-+	if (ata_pio_need_iordy(dev))
-+		tf.nsect = dev->xfer_mode;
-+	/* If the device has IORDY and the controller does not - turn it off */
-+ 	else if (ata_id_has_iordy(dev->id))
-+		tf.nsect = 0x01;
-+	else /* In the ancient relic department - skip all of this */
-+		return 0;
+diff --git a/drivers/base/sys.c b/drivers/base/sys.c
+index ac7ff6d..2f79c55 100644
+--- a/drivers/base/sys.c
++++ b/drivers/base/sys.c
+@@ -25,8 +25,6 @@
  
- 	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ #include "base.h"
  
-@@ -4462,17 +4474,13 @@ static unsigned int ata_dev_init_params(struct ata_device *dev,
- void ata_sg_clean(struct ata_queued_cmd *qc)
+-extern struct kset devices_subsys;
+-
+ #define to_sysdev(k) container_of(k, struct sys_device, kobj)
+ #define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
+ 
+@@ -128,18 +126,17 @@ void sysdev_class_remove_file(struct sysdev_class *c,
+ }
+ EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
+ 
+-/*
+- * declare system_subsys
+- */
+-static decl_subsys(system, &ktype_sysdev_class, NULL);
++static struct kset *system_kset;
+ 
+ int sysdev_class_register(struct sysdev_class * cls)
  {
- 	struct ata_port *ap = qc->ap;
--	struct scatterlist *sg = qc->__sg;
-+	struct scatterlist *sg = qc->sg;
- 	int dir = qc->dma_dir;
- 	void *pad_buf = NULL;
+ 	pr_debug("Registering sysdev class '%s'\n",
+ 		 kobject_name(&cls->kset.kobj));
+ 	INIT_LIST_HEAD(&cls->drivers);
+-	cls->kset.kobj.parent = &system_subsys.kobj;
+-	cls->kset.kobj.kset = &system_subsys;
++	cls->kset.kobj.parent = &system_kset->kobj;
++	cls->kset.kobj.ktype = &ktype_sysdev_class;
++	cls->kset.kobj.kset = system_kset;
++	kobject_set_name(&cls->kset.kobj, cls->name);
+ 	return kset_register(&cls->kset);
+ }
  
--	WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
- 	WARN_ON(sg == NULL);
+@@ -228,20 +225,15 @@ int sysdev_register(struct sys_device * sysdev)
+ 	if (!cls)
+ 		return -EINVAL;
  
--	if (qc->flags & ATA_QCFLAG_SINGLE)
--		WARN_ON(qc->n_elem > 1);
++	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
++
+ 	/* Make sure the kset is set */
+ 	sysdev->kobj.kset = &cls->kset;
+ 
+-	/* But make sure we point to the right type for sysfs translation */
+-	sysdev->kobj.ktype = &ktype_sysdev;
+-	error = kobject_set_name(&sysdev->kobj, "%s%d",
+-			 kobject_name(&cls->kset.kobj), sysdev->id);
+-	if (error)
+-		return error;
 -
--	VPRINTK("unmapping %u sg elements\n", qc->n_elem);
-+	VPRINTK("unmapping %u sg elements\n", qc->mapped_n_elem);
+-	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
+-
+ 	/* Register the object */
+-	error = kobject_register(&sysdev->kobj);
++	error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL,
++				     "%s%d", kobject_name(&cls->kset.kobj),
++				     sysdev->id);
  
- 	/* if we padded the buffer out to 32-bit bound, and data
- 	 * xfer direction is from-device, we must copy from the
-@@ -4481,31 +4489,20 @@ void ata_sg_clean(struct ata_queued_cmd *qc)
- 	if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
- 		pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+ 	if (!error) {
+ 		struct sysdev_driver * drv;
+@@ -258,6 +250,7 @@ int sysdev_register(struct sys_device * sysdev)
+ 		}
+ 		mutex_unlock(&sysdev_drivers_lock);
+ 	}
++	kobject_uevent(&sysdev->kobj, KOBJ_ADD);
+ 	return error;
+ }
  
--	if (qc->flags & ATA_QCFLAG_SG) {
--		if (qc->n_elem)
--			dma_unmap_sg(ap->dev, sg, qc->n_elem, dir);
--		/* restore last sg */
--		sg_last(sg, qc->orig_n_elem)->length += qc->pad_len;
--		if (pad_buf) {
--			struct scatterlist *psg = &qc->pad_sgent;
--			void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
--			memcpy(addr + psg->offset, pad_buf, qc->pad_len);
--			kunmap_atomic(addr, KM_IRQ0);
--		}
--	} else {
--		if (qc->n_elem)
--			dma_unmap_single(ap->dev,
--				sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
--				dir);
--		/* restore sg */
--		sg->length += qc->pad_len;
--		if (pad_buf)
--			memcpy(qc->buf_virt + sg->length - qc->pad_len,
--			       pad_buf, qc->pad_len);
-+	if (qc->mapped_n_elem)
-+		dma_unmap_sg(ap->dev, sg, qc->mapped_n_elem, dir);
-+	/* restore last sg */
-+	if (qc->last_sg)
-+		*qc->last_sg = qc->saved_last_sg;
-+	if (pad_buf) {
-+		struct scatterlist *psg = &qc->extra_sg[1];
-+		void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
-+		memcpy(addr + psg->offset, pad_buf, qc->pad_len);
-+		kunmap_atomic(addr, KM_IRQ0);
+@@ -272,7 +265,7 @@ void sysdev_unregister(struct sys_device * sysdev)
  	}
+ 	mutex_unlock(&sysdev_drivers_lock);
  
- 	qc->flags &= ~ATA_QCFLAG_DMAMAP;
--	qc->__sg = NULL;
-+	qc->sg = NULL;
+-	kobject_unregister(&sysdev->kobj);
++	kobject_put(&sysdev->kobj);
  }
  
- /**
-@@ -4523,13 +4520,10 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
- {
- 	struct ata_port *ap = qc->ap;
- 	struct scatterlist *sg;
--	unsigned int idx;
-+	unsigned int si, pi;
- 
--	WARN_ON(qc->__sg == NULL);
--	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
--
--	idx = 0;
--	ata_for_each_sg(sg, qc) {
-+	pi = 0;
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		u32 addr, offset;
- 		u32 sg_len, len;
  
-@@ -4546,18 +4540,17 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
- 			if ((offset + sg_len) > 0x10000)
- 				len = 0x10000 - offset;
+@@ -298,8 +291,7 @@ void sysdev_shutdown(void)
+ 	pr_debug("Shutting Down System Devices\n");
  
--			ap->prd[idx].addr = cpu_to_le32(addr);
--			ap->prd[idx].flags_len = cpu_to_le32(len & 0xffff);
--			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
-+			ap->prd[pi].addr = cpu_to_le32(addr);
-+			ap->prd[pi].flags_len = cpu_to_le32(len & 0xffff);
-+			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+ 	mutex_lock(&sysdev_drivers_lock);
+-	list_for_each_entry_reverse(cls, &system_subsys.list,
+-				    kset.kobj.entry) {
++	list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
+ 		struct sys_device * sysdev;
  
--			idx++;
-+			pi++;
- 			sg_len -= len;
- 			addr += len;
- 		}
- 	}
+ 		pr_debug("Shutting down type '%s':\n",
+@@ -361,9 +353,7 @@ int sysdev_suspend(pm_message_t state)
  
--	if (idx)
--		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-+	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
- }
+ 	pr_debug("Suspending System Devices\n");
  
- /**
-@@ -4577,13 +4570,10 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
- {
- 	struct ata_port *ap = qc->ap;
- 	struct scatterlist *sg;
--	unsigned int idx;
+-	list_for_each_entry_reverse(cls, &system_subsys.list,
+-				    kset.kobj.entry) {
 -
--	WARN_ON(qc->__sg == NULL);
--	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
-+	unsigned int si, pi;
++	list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
+ 		pr_debug("Suspending type '%s':\n",
+ 			 kobject_name(&cls->kset.kobj));
  
--	idx = 0;
--	ata_for_each_sg(sg, qc) {
-+	pi = 0;
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		u32 addr, offset;
- 		u32 sg_len, len, blen;
+@@ -414,8 +404,7 @@ aux_driver:
+ 	}
  
-@@ -4601,25 +4591,24 @@ static void ata_fill_sg_dumb(struct ata_queued_cmd *qc)
- 				len = 0x10000 - offset;
+ 	/* resume other classes */
+-	list_for_each_entry_continue(cls, &system_subsys.list,
+-					kset.kobj.entry) {
++	list_for_each_entry_continue(cls, &system_kset->list, kset.kobj.entry) {
+ 		list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
+ 			pr_debug(" %s\n", kobject_name(&err_dev->kobj));
+ 			__sysdev_resume(err_dev);
+@@ -440,7 +429,7 @@ int sysdev_resume(void)
  
- 			blen = len & 0xffff;
--			ap->prd[idx].addr = cpu_to_le32(addr);
-+			ap->prd[pi].addr = cpu_to_le32(addr);
- 			if (blen == 0) {
- 			   /* Some PATA chipsets like the CS5530 can't
- 			      cope with 0x0000 meaning 64K as the spec says */
--				ap->prd[idx].flags_len = cpu_to_le32(0x8000);
-+				ap->prd[pi].flags_len = cpu_to_le32(0x8000);
- 				blen = 0x8000;
--				ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000);
-+				ap->prd[++pi].addr = cpu_to_le32(addr + 0x8000);
- 			}
--			ap->prd[idx].flags_len = cpu_to_le32(blen);
--			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
-+			ap->prd[pi].flags_len = cpu_to_le32(blen);
-+			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", pi, addr, len);
+ 	pr_debug("Resuming System Devices\n");
  
--			idx++;
-+			pi++;
- 			sg_len -= len;
- 			addr += len;
- 		}
- 	}
+-	list_for_each_entry(cls, &system_subsys.list, kset.kobj.entry) {
++	list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
+ 		struct sys_device * sysdev;
  
--	if (idx)
--		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-+	ap->prd[pi - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
+ 		pr_debug("Resuming type '%s':\n",
+@@ -458,8 +447,10 @@ int sysdev_resume(void)
+ 
+ int __init system_bus_init(void)
+ {
+-	system_subsys.kobj.parent = &devices_subsys.kobj;
+-	return subsystem_register(&system_subsys);
++	system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
++	if (!system_kset)
++		return -ENOMEM;
++	return 0;
  }
  
- /**
-@@ -4669,8 +4658,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
-  */
- static int atapi_qc_may_overflow(struct ata_queued_cmd *qc)
+ EXPORT_SYMBOL_GPL(sysdev_register);
+diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
+index 9030c37..cd03473 100644
+--- a/drivers/block/DAC960.c
++++ b/drivers/block/DAC960.c
+@@ -3455,19 +3455,12 @@ static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
+ 						 bool SuccessfulIO)
  {
--	if (qc->tf.protocol != ATA_PROT_ATAPI &&
--	    qc->tf.protocol != ATA_PROT_ATAPI_DMA)
-+	if (qc->tf.protocol != ATAPI_PROT_PIO &&
-+	    qc->tf.protocol != ATAPI_PROT_DMA)
- 		return 0;
+ 	struct request *Request = Command->Request;
+-	int UpToDate;
+-
+-	UpToDate = 0;
+-	if (SuccessfulIO)
+-		UpToDate = 1;
++	int Error = SuccessfulIO ? 0 : -EIO;
  
- 	if (qc->tf.flags & ATA_TFLAG_WRITE)
-@@ -4756,33 +4745,6 @@ void ata_dumb_qc_prep(struct ata_queued_cmd *qc)
- void ata_noop_qc_prep(struct ata_queued_cmd *qc) { }
+ 	pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
+ 		Command->SegmentCount, Command->DmaDirection);
  
- /**
-- *	ata_sg_init_one - Associate command with memory buffer
-- *	@qc: Command to be associated
-- *	@buf: Memory buffer
-- *	@buflen: Length of memory buffer, in bytes.
-- *
-- *	Initialize the data-related elements of queued_cmd @qc
-- *	to point to a single memory buffer, @buf of byte length @buflen.
-- *
-- *	LOCKING:
-- *	spin_lock_irqsave(host lock)
-- */
--
--void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
--{
--	qc->flags |= ATA_QCFLAG_SINGLE;
--
--	qc->__sg = &qc->sgent;
--	qc->n_elem = 1;
--	qc->orig_n_elem = 1;
--	qc->buf_virt = buf;
--	qc->nbytes = buflen;
--	qc->cursg = qc->__sg;
--
--	sg_init_one(&qc->sgent, buf, buflen);
--}
--
--/**
-  *	ata_sg_init - Associate command with scatter-gather table.
-  *	@qc: Command to be associated
-  *	@sg: Scatter-gather table.
-@@ -4795,84 +4757,103 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
-  *	LOCKING:
-  *	spin_lock_irqsave(host lock)
-  */
+-	 if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
+-		add_disk_randomness(Request->rq_disk);
+- 	 	end_that_request_last(Request, UpToDate);
 -
- void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
- 		 unsigned int n_elem)
++	 if (!__blk_end_request(Request, Error, Command->BlockCount << 9)) {
+ 		if (Command->Completion) {
+ 			complete(Command->Completion);
+ 			Command->Completion = NULL;
+diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
+index 4d0119e..64e5148 100644
+--- a/drivers/block/Kconfig
++++ b/drivers/block/Kconfig
+@@ -105,6 +105,17 @@ config PARIDE
+ 	  "MicroSolutions backpack protocol", "DataStor Commuter protocol"
+ 	  etc.).
+ 
++config GDROM
++	tristate "SEGA Dreamcast GD-ROM drive"
++	depends on SH_DREAMCAST
++	help
++	  A standard SEGA Dreamcast comes with a modified CD ROM drive called a
++	  "GD-ROM" by SEGA to signify it is capable of reading special disks
++	  with up to 1 GB of data. This drive will also read standard CD ROM
++	  disks. Select this option to access any disks in your GD ROM drive.
++	  Most users will want to say "Y" here.
++	  You can also build this as a module which will be called gdrom.ko
++
+ source "drivers/block/paride/Kconfig"
+ 
+ config BLK_CPQ_DA
+@@ -429,6 +440,7 @@ config VIRTIO_BLK
+ 	tristate "Virtio block driver (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL && VIRTIO
+ 	---help---
+-	  This is the virtual block driver for lguest.  Say Y or M.
++	  This is the virtual block driver for virtio.  It can be used with
++          lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
+ 
+ endif # BLK_DEV
+diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
+index ad00b3d..826d123 100644
+--- a/drivers/block/aoe/aoeblk.c
++++ b/drivers/block/aoe/aoeblk.c
+@@ -15,8 +15,10 @@
+ 
+ static struct kmem_cache *buf_pool_cache;
+ 
+-static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
++static ssize_t aoedisk_show_state(struct device *dev,
++				  struct device_attribute *attr, char *page)
  {
--	qc->flags |= ATA_QCFLAG_SG;
--	qc->__sg = sg;
-+	qc->sg = sg;
- 	qc->n_elem = n_elem;
--	qc->orig_n_elem = n_elem;
--	qc->cursg = qc->__sg;
-+	qc->cursg = qc->sg;
++	struct gendisk *disk = dev_to_disk(dev);
+ 	struct aoedev *d = disk->private_data;
+ 
+ 	return snprintf(page, PAGE_SIZE,
+@@ -26,50 +28,47 @@ static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
+ 			(d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
+ 	/* I'd rather see nopen exported so we can ditch closewait */
  }
+-static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page)
++static ssize_t aoedisk_show_mac(struct device *dev,
++				struct device_attribute *attr, char *page)
+ {
++	struct gendisk *disk = dev_to_disk(dev);
+ 	struct aoedev *d = disk->private_data;
  
--/**
-- *	ata_sg_setup_one - DMA-map the memory buffer associated with a command.
-- *	@qc: Command with memory buffer to be mapped.
-- *
-- *	DMA-map the memory buffer associated with queued_cmd @qc.
-- *
-- *	LOCKING:
-- *	spin_lock_irqsave(host lock)
-- *
-- *	RETURNS:
-- *	Zero on success, negative on error.
-- */
--
--static int ata_sg_setup_one(struct ata_queued_cmd *qc)
-+static unsigned int ata_sg_setup_extra(struct ata_queued_cmd *qc,
-+				       unsigned int *n_elem_extra,
-+				       unsigned int *nbytes_extra)
+ 	return snprintf(page, PAGE_SIZE, "%012llx\n",
+ 			(unsigned long long)mac_addr(d->addr));
+ }
+-static ssize_t aoedisk_show_netif(struct gendisk * disk, char *page)
++static ssize_t aoedisk_show_netif(struct device *dev,
++				  struct device_attribute *attr, char *page)
  {
- 	struct ata_port *ap = qc->ap;
--	int dir = qc->dma_dir;
--	struct scatterlist *sg = qc->__sg;
--	dma_addr_t dma_address;
--	int trim_sg = 0;
-+	unsigned int n_elem = qc->n_elem;
-+	struct scatterlist *lsg, *copy_lsg = NULL, *tsg = NULL, *esg = NULL;
-+
-+	*n_elem_extra = 0;
-+	*nbytes_extra = 0;
-+
-+	/* needs padding? */
-+	qc->pad_len = qc->nbytes & 3;
-+
-+	if (likely(!qc->pad_len))
-+		return n_elem;
-+
-+	/* locate last sg and save it */
-+	lsg = sg_last(qc->sg, n_elem);
-+	qc->last_sg = lsg;
-+	qc->saved_last_sg = *lsg;
-+
-+	sg_init_table(qc->extra_sg, ARRAY_SIZE(qc->extra_sg));
++	struct gendisk *disk = dev_to_disk(dev);
+ 	struct aoedev *d = disk->private_data;
  
--	/* we must lengthen transfers to end on a 32-bit boundary */
--	qc->pad_len = sg->length & 3;
- 	if (qc->pad_len) {
-+		struct scatterlist *psg = &qc->extra_sg[1];
- 		void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
--		struct scatterlist *psg = &qc->pad_sgent;
-+		unsigned int offset;
+ 	return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name);
+ }
+ /* firmware version */
+-static ssize_t aoedisk_show_fwver(struct gendisk * disk, char *page)
++static ssize_t aoedisk_show_fwver(struct device *dev,
++				  struct device_attribute *attr, char *page)
+ {
++	struct gendisk *disk = dev_to_disk(dev);
+ 	struct aoedev *d = disk->private_data;
  
- 		WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
+ 	return snprintf(page, PAGE_SIZE, "0x%04x\n", (unsigned int) d->fw_ver);
+ }
  
- 		memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+-static struct disk_attribute disk_attr_state = {
+-	.attr = {.name = "state", .mode = S_IRUGO },
+-	.show = aoedisk_show_state
+-};
+-static struct disk_attribute disk_attr_mac = {
+-	.attr = {.name = "mac", .mode = S_IRUGO },
+-	.show = aoedisk_show_mac
+-};
+-static struct disk_attribute disk_attr_netif = {
+-	.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 DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
++static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
++static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
++static struct device_attribute dev_attr_firmware_version = {
++	.attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE },
++	.show = aoedisk_show_fwver,
+ };
  
--		if (qc->tf.flags & ATA_TFLAG_WRITE)
--			memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
--			       qc->pad_len);
-+		/* psg->page/offset are used to copy to-be-written
-+		 * data in this function or read data in ata_sg_clean.
-+		 */
-+		offset = lsg->offset + lsg->length - qc->pad_len;
-+		sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
-+			    qc->pad_len, offset_in_page(offset));
-+
-+		if (qc->tf.flags & ATA_TFLAG_WRITE) {
-+			void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
-+			memcpy(pad_buf, addr + psg->offset, qc->pad_len);
-+			kunmap_atomic(addr, KM_IRQ0);
-+		}
+ static struct attribute *aoe_attrs[] = {
+-	&disk_attr_state.attr,
+-	&disk_attr_mac.attr,
+-	&disk_attr_netif.attr,
+-	&disk_attr_fwver.attr,
+-	NULL
++	&dev_attr_state.attr,
++	&dev_attr_mac.attr,
++	&dev_attr_netif.attr,
++	&dev_attr_firmware_version.attr,
++	NULL,
+ };
  
- 		sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
- 		sg_dma_len(psg) = ATA_DMA_PAD_SZ;
--		/* trim sg */
--		sg->length -= qc->pad_len;
--		if (sg->length == 0)
--			trim_sg = 1;
+ static const struct attribute_group attr_group = {
+@@ -79,12 +78,12 @@ static const struct attribute_group attr_group = {
+ static int
+ aoedisk_add_sysfs(struct aoedev *d)
+ {
+-	return sysfs_create_group(&d->gd->kobj, &attr_group);
++	return sysfs_create_group(&d->gd->dev.kobj, &attr_group);
+ }
+ void
+ aoedisk_rm_sysfs(struct aoedev *d)
+ {
+-	sysfs_remove_group(&d->gd->kobj, &attr_group);
++	sysfs_remove_group(&d->gd->dev.kobj, &attr_group);
+ }
  
--		DPRINTK("padding done, sg->length=%u pad_len=%u\n",
--			sg->length, qc->pad_len);
--	}
-+		/* Trim the last sg entry and chain the original and
-+		 * padding sg lists.
-+		 *
-+		 * Because chaining consumes one sg entry, one extra
-+		 * sg entry is allocated and the last sg entry is
-+		 * copied to it if the length isn't zero after padded
-+		 * amount is removed.
-+		 *
-+		 * If the last sg entry is completely replaced by
-+		 * padding sg entry, the first sg entry is skipped
-+		 * while chaining.
-+		 */
-+		lsg->length -= qc->pad_len;
-+		if (lsg->length) {
-+			copy_lsg = &qc->extra_sg[0];
-+			tsg = &qc->extra_sg[0];
-+		} else {
-+			n_elem--;
-+			tsg = &qc->extra_sg[1];
-+		}
+ static int
+diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
+index 39e563e..d5480e3 100644
+--- a/drivers/block/aoe/aoechr.c
++++ b/drivers/block/aoe/aoechr.c
+@@ -259,9 +259,8 @@ aoechr_init(void)
+ 		return PTR_ERR(aoe_class);
+ 	}
+ 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
+-		class_device_create(aoe_class, NULL,
+-					MKDEV(AOE_MAJOR, chardevs[i].minor),
+-					NULL, chardevs[i].name);
++		device_create(aoe_class, NULL,
++			      MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name);
  
--	if (trim_sg) {
--		qc->n_elem--;
--		goto skip_map;
--	}
-+		esg = &qc->extra_sg[1];
+ 	return 0;
+ }
+@@ -272,7 +271,7 @@ aoechr_exit(void)
+ 	int i;
  
--	dma_address = dma_map_single(ap->dev, qc->buf_virt,
--				     sg->length, dir);
--	if (dma_mapping_error(dma_address)) {
--		/* restore sg */
--		sg->length += qc->pad_len;
--		return -1;
-+		(*n_elem_extra)++;
-+		(*nbytes_extra) += 4 - qc->pad_len;
+ 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
+-		class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
++		device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
+ 	class_destroy(aoe_class);
+ 	unregister_chrdev(AOE_MAJOR, "aoechr");
+ }
+diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
+index 509b649..855ce8e 100644
+--- a/drivers/block/cciss.c
++++ b/drivers/block/cciss.c
+@@ -1187,17 +1187,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
  	}
+ }
  
--	sg_dma_address(sg) = dma_address;
--	sg_dma_len(sg) = sg->length;
-+	if (copy_lsg)
-+		sg_set_page(copy_lsg, sg_page(lsg), lsg->length, lsg->offset);
+-static inline void complete_buffers(struct bio *bio, int status)
+-{
+-	while (bio) {
+-		struct bio *xbh = bio->bi_next;
+-
+-		bio->bi_next = NULL;
+-		bio_endio(bio, status ? 0 : -EIO);
+-		bio = xbh;
+-	}
+-}
+-
+ static void cciss_check_queues(ctlr_info_t *h)
+ {
+ 	int start_queue = h->next_to_run;
+@@ -1263,21 +1252,14 @@ static void cciss_softirq_done(struct request *rq)
+ 		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
+ 	}
  
--skip_map:
--	DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
--		qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
-+	sg_chain(lsg, 1, tsg);
-+	sg_mark_end(esg);
+-	complete_buffers(rq->bio, (rq->errors == 0));
+-
+-	if (blk_fs_request(rq)) {
+-		const int rw = rq_data_dir(rq);
+-
+-		disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
+-	}
+-
+ #ifdef CCISS_DEBUG
+ 	printk("Done with %p\n", rq);
+ #endif				/* CCISS_DEBUG */
  
--	return 0;
-+	/* sglist can't start with chaining sg entry, fast forward */
-+	if (qc->sg == lsg) {
-+		qc->sg = tsg;
-+		qc->cursg = tsg;
-+	}
+-	add_disk_randomness(rq->rq_disk);
++	if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, blk_rq_bytes(rq)))
++		BUG();
 +
-+	return n_elem;
+ 	spin_lock_irqsave(&h->lock, flags);
+-	end_that_request_last(rq, (rq->errors == 0));
+ 	cmd_free(h, cmd, 1);
+ 	cciss_check_queues(h);
+ 	spin_unlock_irqrestore(&h->lock, flags);
+@@ -2542,9 +2524,7 @@ after_error_processing:
+ 		resend_cciss_cmd(h, cmd);
+ 		return;
+ 	}
+-	cmd->rq->data_len = 0;
+ 	cmd->rq->completion_data = cmd;
+-	blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE);
+ 	blk_complete_request(cmd->rq);
  }
  
- /**
-@@ -4888,75 +4869,30 @@ skip_map:
-  *	Zero on success, negative on error.
-  *
-  */
--
- static int ata_sg_setup(struct ata_queued_cmd *qc)
- {
- 	struct ata_port *ap = qc->ap;
--	struct scatterlist *sg = qc->__sg;
--	struct scatterlist *lsg = sg_last(qc->__sg, qc->n_elem);
--	int n_elem, pre_n_elem, dir, trim_sg = 0;
-+	unsigned int n_elem, n_elem_extra, nbytes_extra;
+diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
+index 63ee6c0..55178e9 100644
+--- a/drivers/block/cciss_scsi.c
++++ b/drivers/block/cciss_scsi.c
+@@ -1453,7 +1453,7 @@ static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
+ 	rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 2, 0, 0, 
+ 		(unsigned char *) &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 
+ 		TYPE_MSG);
+-	/* sendcmd turned off interrputs on the board, turn 'em back on. */
++	/* sendcmd turned off interrupts on the board, turn 'em back on. */
+ 	(*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
+ 	if (rc == 0)
+ 		return SUCCESS;
+@@ -1483,7 +1483,7 @@ static int  cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
+ 		0, 2, 0, 0, 
+ 		(unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0], 
+ 		TYPE_MSG);
+-	/* sendcmd turned off interrputs on the board, turn 'em back on. */
++	/* sendcmd turned off interrupts on the board, turn 'em back on. */
+ 	(*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
+ 	if (rc == 0)
+ 		return SUCCESS;
+diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
+index c8132d9..6919918 100644
+--- a/drivers/block/cpqarray.c
++++ b/drivers/block/cpqarray.c
+@@ -167,7 +167,6 @@ static void start_io(ctlr_info_t *h);
  
- 	VPRINTK("ENTER, ata%u\n", ap->print_id);
--	WARN_ON(!(qc->flags & ATA_QCFLAG_SG));
+ static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
+ static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
+-static inline void complete_buffers(struct bio *bio, int ok);
+ static inline void complete_command(cmdlist_t *cmd, int timeout);
  
--	/* we must lengthen transfers to end on a 32-bit boundary */
--	qc->pad_len = lsg->length & 3;
--	if (qc->pad_len) {
--		void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
--		struct scatterlist *psg = &qc->pad_sgent;
--		unsigned int offset;
--
--		WARN_ON(qc->dev->class != ATA_DEV_ATAPI);
-+	n_elem = ata_sg_setup_extra(qc, &n_elem_extra, &nbytes_extra);
+ static irqreturn_t do_ida_intr(int irq, void *dev_id);
+@@ -980,26 +979,13 @@ static void start_io(ctlr_info_t *h)
+ 	}
+ }
  
--		memset(pad_buf, 0, ATA_DMA_PAD_SZ);
--
--		/*
--		 * psg->page/offset are used to copy to-be-written
--		 * data in this function or read data in ata_sg_clean.
--		 */
--		offset = lsg->offset + lsg->length - qc->pad_len;
--		sg_init_table(psg, 1);
--		sg_set_page(psg, nth_page(sg_page(lsg), offset >> PAGE_SHIFT),
--				qc->pad_len, offset_in_page(offset));
--
--		if (qc->tf.flags & ATA_TFLAG_WRITE) {
--			void *addr = kmap_atomic(sg_page(psg), KM_IRQ0);
--			memcpy(pad_buf, addr + psg->offset, qc->pad_len);
--			kunmap_atomic(addr, KM_IRQ0);
-+	if (n_elem) {
-+		n_elem = dma_map_sg(ap->dev, qc->sg, n_elem, qc->dma_dir);
-+		if (n_elem < 1) {
-+			/* restore last sg */
-+			if (qc->last_sg)
-+				*qc->last_sg = qc->saved_last_sg;
-+			return -1;
- 		}
+-static inline void complete_buffers(struct bio *bio, int ok)
+-{
+-	struct bio *xbh;
 -
--		sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
--		sg_dma_len(psg) = ATA_DMA_PAD_SZ;
--		/* trim last sg */
--		lsg->length -= qc->pad_len;
--		if (lsg->length == 0)
--			trim_sg = 1;
+-	while (bio) {
+-		xbh = bio->bi_next;
+-		bio->bi_next = NULL;
+-		
+-		bio_endio(bio, ok ? 0 : -EIO);
 -
--		DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
--			qc->n_elem - 1, lsg->length, qc->pad_len);
+-		bio = xbh;
 -	}
+-}
+ /*
+  * Mark all buffers that cmd was responsible for
+  */
+ static inline void complete_command(cmdlist_t *cmd, int timeout)
+ {
+ 	struct request *rq = cmd->rq;
+-	int ok=1;
++	int error = 0;
+ 	int i, ddir;
+ 
+ 	if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
+@@ -1011,16 +997,17 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
+ 	if (cmd->req.hdr.rcode & RCODE_FATAL) {
+ 		printk(KERN_WARNING "Fatal error on ida/c%dd%d\n",
+ 				cmd->ctlr, cmd->hdr.unit);
+-		ok = 0;
++		error = -EIO;
+ 	}
+ 	if (cmd->req.hdr.rcode & RCODE_INVREQ) {
+ 				printk(KERN_WARNING "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
+ 				cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
+ 				cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
+ 				cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
+-		ok = 0;	
++		error = -EIO;
+ 	}
+-	if (timeout) ok = 0;
++	if (timeout)
++		error = -EIO;
+ 	/* unmap the DMA mapping for all the scatter gather elements */
+ 	if (cmd->req.hdr.cmd == IDA_READ)
+ 		ddir = PCI_DMA_FROMDEVICE;
+@@ -1030,18 +1017,9 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
+                 pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr,
+ 				cmd->req.sg[i].size, ddir);
+ 
+-	complete_buffers(rq->bio, ok);
 -
--	pre_n_elem = qc->n_elem;
--	if (trim_sg && pre_n_elem)
--		pre_n_elem--;
+-	if (blk_fs_request(rq)) {
+-		const int rw = rq_data_dir(rq);
 -
--	if (!pre_n_elem) {
--		n_elem = 0;
--		goto skip_map;
+-		disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
 -	}
 -
--	dir = qc->dma_dir;
--	n_elem = dma_map_sg(ap->dev, sg, pre_n_elem, dir);
--	if (n_elem < 1) {
--		/* restore last sg */
--		lsg->length += qc->pad_len;
--		return -1;
-+		DPRINTK("%d sg elements mapped\n", n_elem);
- 	}
- 
--	DPRINTK("%d sg elements mapped\n", n_elem);
+-	add_disk_randomness(rq->rq_disk);
 -
--skip_map:
--	qc->n_elem = n_elem;
-+	qc->n_elem = qc->mapped_n_elem = n_elem;
-+	qc->n_elem += n_elem_extra;
-+	qc->nbytes += nbytes_extra;
-+	qc->flags |= ATA_QCFLAG_DMAMAP;
- 
- 	return 0;
+ 	DBGPX(printk("Done with %p\n", rq););
+-	end_that_request_last(rq, ok ? 1 : -EIO);
++	if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
++		BUG();
  }
-@@ -4985,63 +4921,77 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
  
- /**
-  *	ata_data_xfer - Transfer data by PIO
-- *	@adev: device to target
-+ *	@dev: device to target
-  *	@buf: data buffer
-  *	@buflen: buffer length
-- *	@write_data: read/write
-+ *	@rw: read/write
-  *
-  *	Transfer data from/to the device data register by PIO.
-  *
-  *	LOCKING:
-  *	Inherited from caller.
-+ *
-+ *	RETURNS:
-+ *	Bytes consumed.
+ /*
+diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
+index 639ed14..32c79a5 100644
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -2287,21 +2287,19 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
+  * =============================
   */
--void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
--		   unsigned int buflen, int write_data)
-+unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
-+			   unsigned int buflen, int rw)
+ 
+-static void floppy_end_request(struct request *req, int uptodate)
++static void floppy_end_request(struct request *req, int error)
  {
--	struct ata_port *ap = adev->link->ap;
-+	struct ata_port *ap = dev->link->ap;
-+	void __iomem *data_addr = ap->ioaddr.data_addr;
- 	unsigned int words = buflen >> 1;
+ 	unsigned int nr_sectors = current_count_sectors;
++	unsigned int drive = (unsigned long)req->rq_disk->private_data;
  
- 	/* Transfer multiple of 2 bytes */
--	if (write_data)
--		iowrite16_rep(ap->ioaddr.data_addr, buf, words);
-+	if (rw == READ)
-+		ioread16_rep(data_addr, buf, words);
- 	else
--		ioread16_rep(ap->ioaddr.data_addr, buf, words);
-+		iowrite16_rep(data_addr, buf, words);
+ 	/* current_count_sectors can be zero if transfer failed */
+-	if (!uptodate)
++	if (error)
+ 		nr_sectors = req->current_nr_sectors;
+-	if (end_that_request_first(req, uptodate, nr_sectors))
++	if (__blk_end_request(req, error, nr_sectors << 9))
+ 		return;
+-	add_disk_randomness(req->rq_disk);
+-	floppy_off((long)req->rq_disk->private_data);
+-	blkdev_dequeue_request(req);
+-	end_that_request_last(req, uptodate);
  
- 	/* Transfer trailing 1 byte, if any. */
- 	if (unlikely(buflen & 0x01)) {
--		u16 align_buf[1] = { 0 };
-+		__le16 align_buf[1] = { 0 };
- 		unsigned char *trailing_buf = buf + buflen - 1;
+ 	/* We're done with the request */
++	floppy_off(drive);
+ 	current_req = NULL;
+ }
  
--		if (write_data) {
--			memcpy(align_buf, trailing_buf, 1);
--			iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
--		} else {
--			align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
-+		if (rw == READ) {
-+			align_buf[0] = cpu_to_le16(ioread16(data_addr));
- 			memcpy(trailing_buf, align_buf, 1);
-+		} else {
-+			memcpy(align_buf, trailing_buf, 1);
-+			iowrite16(le16_to_cpu(align_buf[0]), data_addr);
+@@ -2332,7 +2330,7 @@ static void request_done(int uptodate)
+ 
+ 		/* unlock chained buffers */
+ 		spin_lock_irqsave(q->queue_lock, flags);
+-		floppy_end_request(req, 1);
++		floppy_end_request(req, 0);
+ 		spin_unlock_irqrestore(q->queue_lock, flags);
+ 	} else {
+ 		if (rq_data_dir(req) == WRITE) {
+@@ -2346,7 +2344,7 @@ static void request_done(int uptodate)
+ 			DRWE->last_error_generation = DRS->generation;
  		}
-+		words++;
+ 		spin_lock_irqsave(q->queue_lock, flags);
+-		floppy_end_request(req, 0);
++		floppy_end_request(req, -EIO);
+ 		spin_unlock_irqrestore(q->queue_lock, flags);
  	}
-+
-+	return words << 1;
  }
+diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
+index b4c0888..ae31060 100644
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -100,17 +100,15 @@ static const char *nbdcmd_to_ascii(int cmd)
  
- /**
-  *	ata_data_xfer_noirq - Transfer data by PIO
-- *	@adev: device to target
-+ *	@dev: device to target
-  *	@buf: data buffer
-  *	@buflen: buffer length
-- *	@write_data: read/write
-+ *	@rw: read/write
-  *
-  *	Transfer data from/to the device data register by PIO. Do the
-  *	transfer with interrupts disabled.
-  *
-  *	LOCKING:
-  *	Inherited from caller.
-+ *
-+ *	RETURNS:
-+ *	Bytes consumed.
-  */
--void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
--			 unsigned int buflen, int write_data)
-+unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
-+				 unsigned int buflen, int rw)
+ static void nbd_end_request(struct request *req)
  {
+-	int uptodate = (req->errors == 0) ? 1 : 0;
++	int error = req->errors ? -EIO : 0;
+ 	struct request_queue *q = req->q;
  	unsigned long flags;
-+	unsigned int consumed;
-+
- 	local_irq_save(flags);
--	ata_data_xfer(adev, buf, buflen, write_data);
-+	consumed = ata_data_xfer(dev, buf, buflen, rw);
- 	local_irq_restore(flags);
-+
-+	return consumed;
+ 
+ 	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
+-			req, uptodate? "done": "failed");
++			req, error ? "failed" : "done");
+ 
+ 	spin_lock_irqsave(q->queue_lock, flags);
+-	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
+-		end_that_request_last(req, uptodate);
+-	}
++	__blk_end_request(req, error, req->nr_sectors << 9);
+ 	spin_unlock_irqrestore(q->queue_lock, flags);
  }
  
+@@ -375,14 +373,17 @@ harderror:
+ 	return NULL;
+ }
  
-@@ -5152,13 +5102,13 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc)
- 	ata_altstatus(ap); /* flush */
+-static ssize_t pid_show(struct gendisk *disk, char *page)
++static ssize_t pid_show(struct device *dev,
++			struct device_attribute *attr, char *buf)
+ {
+-	return sprintf(page, "%ld\n",
++	struct gendisk *disk = dev_to_disk(dev);
++
++	return sprintf(buf, "%ld\n",
+ 		(long) ((struct nbd_device *)disk->private_data)->pid);
+ }
  
- 	switch (qc->tf.protocol) {
--	case ATA_PROT_ATAPI:
-+	case ATAPI_PROT_PIO:
- 		ap->hsm_task_state = HSM_ST;
- 		break;
--	case ATA_PROT_ATAPI_NODATA:
-+	case ATAPI_PROT_NODATA:
- 		ap->hsm_task_state = HSM_ST_LAST;
- 		break;
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		ap->hsm_task_state = HSM_ST_LAST;
- 		/* initiate bmdma */
- 		ap->ops->bmdma_start(qc);
-@@ -5300,12 +5250,15 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
- 	bytes = (bc_hi << 8) | bc_lo;
+-static struct disk_attribute pid_attr = {
+-	.attr = { .name = "pid", .mode = S_IRUGO },
++static struct device_attribute pid_attr = {
++	.attr = { .name = "pid", .mode = S_IRUGO, .owner = THIS_MODULE },
+ 	.show = pid_show,
+ };
  
- 	/* shall be cleared to zero, indicating xfer of data */
--	if (ireason & (1 << 0))
-+	if (unlikely(ireason & (1 << 0)))
- 		goto err_out;
+@@ -394,7 +395,7 @@ static int nbd_do_it(struct nbd_device *lo)
+ 	BUG_ON(lo->magic != LO_MAGIC);
  
- 	/* make sure transfer direction matches expected */
- 	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
--	if (do_write != i_write)
-+	if (unlikely(do_write != i_write))
-+		goto err_out;
-+
-+	if (unlikely(!bytes))
- 		goto err_out;
+ 	lo->pid = current->pid;
+-	ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
++	ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr);
+ 	if (ret) {
+ 		printk(KERN_ERR "nbd: sysfs_create_file failed!");
+ 		return ret;
+@@ -403,7 +404,7 @@ static int nbd_do_it(struct nbd_device *lo)
+ 	while ((req = nbd_read_stat(lo)) != NULL)
+ 		nbd_end_request(req);
  
- 	VPRINTK("ata%u: xfering %d bytes\n", ap->print_id, bytes);
-@@ -5341,7 +5294,7 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap, struct ata_queued_cmd *q
- 		    (qc->tf.flags & ATA_TFLAG_WRITE))
- 		    return 1;
+-	sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
++	sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr);
+ 	return 0;
+ }
  
--		if (is_atapi_taskfile(&qc->tf) &&
-+		if (ata_is_atapi(qc->tf.protocol) &&
- 		    !(qc->dev->flags & ATA_DFLAG_CDB_INTR))
- 			return 1;
+diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
+index d89e7d3..ab86e23 100644
+--- a/drivers/block/paride/pg.c
++++ b/drivers/block/paride/pg.c
+@@ -676,8 +676,8 @@ static int __init pg_init(void)
+ 	for (unit = 0; unit < PG_UNITS; unit++) {
+ 		struct pg *dev = &devices[unit];
+ 		if (dev->present)
+-			class_device_create(pg_class, NULL, MKDEV(major, unit),
+-					NULL, "pg%u", unit);
++			device_create(pg_class, NULL, MKDEV(major, unit),
++				      "pg%u", unit);
  	}
-@@ -5506,7 +5459,7 @@ fsm_start:
+ 	err = 0;
+ 	goto out;
+@@ -695,7 +695,7 @@ static void __exit pg_exit(void)
+ 	for (unit = 0; unit < PG_UNITS; unit++) {
+ 		struct pg *dev = &devices[unit];
+ 		if (dev->present)
+-			class_device_destroy(pg_class, MKDEV(major, unit));
++			device_destroy(pg_class, MKDEV(major, unit));
+ 	}
+ 	class_destroy(pg_class);
+ 	unregister_chrdev(major, name);
+diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
+index b91accf..76096ca 100644
+--- a/drivers/block/paride/pt.c
++++ b/drivers/block/paride/pt.c
+@@ -972,10 +972,10 @@ static int __init pt_init(void)
  
- 	case HSM_ST:
- 		/* complete command or read/write the data register */
--		if (qc->tf.protocol == ATA_PROT_ATAPI) {
-+		if (qc->tf.protocol == ATAPI_PROT_PIO) {
- 			/* ATAPI PIO protocol */
- 			if ((status & ATA_DRQ) == 0) {
- 				/* No more data to transfer or device error.
-@@ -5664,7 +5617,7 @@ fsm_start:
- 		msleep(2);
- 		status = ata_busy_wait(ap, ATA_BUSY, 10);
- 		if (status & ATA_BUSY) {
--			ata_port_queue_task(ap, ata_pio_task, qc, ATA_SHORT_PAUSE);
-+			ata_pio_queue_task(ap, qc, ATA_SHORT_PAUSE);
- 			return;
+ 	for (unit = 0; unit < PT_UNITS; unit++)
+ 		if (pt[unit].present) {
+-			class_device_create(pt_class, NULL, MKDEV(major, unit),
+-					NULL, "pt%d", unit);
+-			class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
+-					NULL, "pt%dn", unit);
++			device_create(pt_class, NULL, MKDEV(major, unit),
++				      "pt%d", unit);
++			device_create(pt_class, NULL, MKDEV(major, unit + 128),
++				      "pt%dn", unit);
+ 		}
+ 	goto out;
+ 
+@@ -990,8 +990,8 @@ static void __exit pt_exit(void)
+ 	int unit;
+ 	for (unit = 0; unit < PT_UNITS; unit++)
+ 		if (pt[unit].present) {
+-			class_device_destroy(pt_class, MKDEV(major, unit));
+-			class_device_destroy(pt_class, MKDEV(major, unit + 128));
++			device_destroy(pt_class, MKDEV(major, unit));
++			device_destroy(pt_class, MKDEV(major, unit + 128));
  		}
+ 	class_destroy(pt_class);
+ 	unregister_chrdev(major, name);
+diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
+index 3535ef8..e9de171 100644
+--- a/drivers/block/pktcdvd.c
++++ b/drivers/block/pktcdvd.c
+@@ -110,17 +110,18 @@ static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
+ 					struct kobj_type* ktype)
+ {
+ 	struct pktcdvd_kobj *p;
++	int error;
++
+ 	p = kzalloc(sizeof(*p), GFP_KERNEL);
+ 	if (!p)
+ 		return NULL;
+-	kobject_set_name(&p->kobj, "%s", name);
+-	p->kobj.parent = parent;
+-	p->kobj.ktype = ktype;
+ 	p->pd = pd;
+-	if (kobject_register(&p->kobj) != 0) {
++	error = kobject_init_and_add(&p->kobj, ktype, parent, "%s", name);
++	if (error) {
+ 		kobject_put(&p->kobj);
+ 		return NULL;
  	}
-@@ -5805,6 +5758,22 @@ static void fill_result_tf(struct ata_queued_cmd *qc)
- 	ap->ops->tf_read(ap, &qc->result_tf);
++	kobject_uevent(&p->kobj, KOBJ_ADD);
+ 	return p;
+ }
+ /*
+@@ -129,7 +130,7 @@ static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
+ static void pkt_kobj_remove(struct pktcdvd_kobj *p)
+ {
+ 	if (p)
+-		kobject_unregister(&p->kobj);
++		kobject_put(&p->kobj);
+ }
+ /*
+  * default release function for pktcdvd kernel objects.
+@@ -301,18 +302,16 @@ static struct kobj_type kobj_pkt_type_wqueue = {
+ static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
+ {
+ 	if (class_pktcdvd) {
+-		pd->clsdev = class_device_create(class_pktcdvd,
+-					NULL, pd->pkt_dev,
+-					NULL, "%s", pd->name);
+-		if (IS_ERR(pd->clsdev))
+-			pd->clsdev = NULL;
++		pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name);
++		if (IS_ERR(pd->dev))
++			pd->dev = NULL;
+ 	}
+-	if (pd->clsdev) {
++	if (pd->dev) {
+ 		pd->kobj_stat = pkt_kobj_create(pd, "stat",
+-					&pd->clsdev->kobj,
++					&pd->dev->kobj,
+ 					&kobj_pkt_type_stat);
+ 		pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue",
+-					&pd->clsdev->kobj,
++					&pd->dev->kobj,
+ 					&kobj_pkt_type_wqueue);
+ 	}
+ }
+@@ -322,7 +321,7 @@ static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
+ 	pkt_kobj_remove(pd->kobj_stat);
+ 	pkt_kobj_remove(pd->kobj_wqueue);
+ 	if (class_pktcdvd)
+-		class_device_destroy(class_pktcdvd, pd->pkt_dev);
++		device_destroy(class_pktcdvd, pd->pkt_dev);
  }
  
-+static void ata_verify_xfer(struct ata_queued_cmd *qc)
-+{
-+	struct ata_device *dev = qc->dev;
-+
-+	if (ata_tag_internal(qc->tag))
-+		return;
-+
-+	if (ata_is_nodata(qc->tf.protocol))
-+		return;
-+
-+	if ((dev->mwdma_mask || dev->udma_mask) && ata_is_pio(qc->tf.protocol))
-+		return;
-+
-+	dev->flags &= ~ATA_DFLAG_DUBIOUS_XFER;
-+}
-+
- /**
-  *	ata_qc_complete - Complete an active ATA command
-  *	@qc: Command to complete
-@@ -5876,6 +5845,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
- 			break;
- 		}
  
-+		if (unlikely(dev->flags & ATA_DFLAG_DUBIOUS_XFER))
-+			ata_verify_xfer(qc);
-+
- 		__ata_qc_complete(qc);
+diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
+index e354bfc..7483f94 100644
+--- a/drivers/block/ps3disk.c
++++ b/drivers/block/ps3disk.c
+@@ -229,7 +229,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
+ 	struct ps3_storage_device *dev = data;
+ 	struct ps3disk_private *priv;
+ 	struct request *req;
+-	int res, read, uptodate;
++	int res, read, error;
+ 	u64 tag, status;
+ 	unsigned long num_sectors;
+ 	const char *op;
+@@ -270,21 +270,17 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
+ 	if (status) {
+ 		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+ 			__LINE__, op, status);
+-		uptodate = 0;
++		error = -EIO;
  	} else {
- 		if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)
-@@ -5938,30 +5910,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active,
- 	return nr_done;
- }
+ 		dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
+ 			__LINE__, op);
+-		uptodate = 1;
++		error = 0;
+ 		if (read)
+ 			ps3disk_scatter_gather(dev, req, 0);
+ 	}
  
--static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
--{
--	struct ata_port *ap = qc->ap;
--
--	switch (qc->tf.protocol) {
--	case ATA_PROT_NCQ:
--	case ATA_PROT_DMA:
--	case ATA_PROT_ATAPI_DMA:
--		return 1;
--
--	case ATA_PROT_ATAPI:
--	case ATA_PROT_PIO:
--		if (ap->flags & ATA_FLAG_PIO_DMA)
--			return 1;
--
--		/* fall through */
--
--	default:
--		return 0;
+ 	spin_lock(&priv->lock);
+-	if (!end_that_request_first(req, uptodate, num_sectors)) {
+-		add_disk_randomness(req->rq_disk);
+-		blkdev_dequeue_request(req);
+-		end_that_request_last(req, uptodate);
 -	}
--
--	/* never reached */
--}
--
- /**
-  *	ata_qc_issue - issue taskfile to device
-  *	@qc: command to issue to device
-@@ -5978,6 +5926,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
++	__blk_end_request(req, error, num_sectors << 9);
+ 	priv->req = NULL;
+ 	ps3disk_do_request(dev, priv->queue);
+ 	spin_unlock(&priv->lock);
+diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
+index fac4c6c..a8de037 100644
+--- a/drivers/block/sunvdc.c
++++ b/drivers/block/sunvdc.c
+@@ -212,12 +212,9 @@ static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
+ 	vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
+ }
+ 
+-static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
++static void vdc_end_request(struct request *req, int error, int num_sectors)
  {
- 	struct ata_port *ap = qc->ap;
- 	struct ata_link *link = qc->dev->link;
-+	u8 prot = qc->tf.protocol;
+-	if (end_that_request_first(req, uptodate, num_sectors))
+-		return;
+-	add_disk_randomness(req->rq_disk);
+-	end_that_request_last(req, uptodate);
++	__blk_end_request(req, error, num_sectors << 9);
+ }
  
- 	/* Make sure only one non-NCQ command is outstanding.  The
- 	 * check is skipped for old EH because it reuses active qc to
-@@ -5985,7 +5934,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
- 	 */
- 	WARN_ON(ap->ops->error_handler && ata_tag_valid(link->active_tag));
+ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
+@@ -242,7 +239,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
  
--	if (qc->tf.protocol == ATA_PROT_NCQ) {
-+	if (ata_is_ncq(prot)) {
- 		WARN_ON(link->sactive & (1 << qc->tag));
+ 	rqe->req = NULL;
  
- 		if (!link->sactive)
-@@ -6001,17 +5950,18 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
- 	qc->flags |= ATA_QCFLAG_ACTIVE;
- 	ap->qc_active |= 1 << qc->tag;
+-	vdc_end_request(req, !desc->status, desc->size >> 9);
++	vdc_end_request(req, (desc->status ? -EIO : 0), desc->size >> 9);
  
--	if (ata_should_dma_map(qc)) {
--		if (qc->flags & ATA_QCFLAG_SG) {
--			if (ata_sg_setup(qc))
--				goto sg_err;
--		} else if (qc->flags & ATA_QCFLAG_SINGLE) {
--			if (ata_sg_setup_one(qc))
--				goto sg_err;
--		}
--	} else {
--		qc->flags &= ~ATA_QCFLAG_DMAMAP;
--	}
-+	/* We guarantee to LLDs that they will have at least one
-+	 * non-zero sg if the command is a data command.
-+	 */
-+	BUG_ON(ata_is_data(prot) && (!qc->sg || !qc->n_elem || !qc->nbytes));
-+
-+	/* ata_sg_setup() may update nbytes */
-+	qc->raw_nbytes = qc->nbytes;
-+
-+	if (ata_is_dma(prot) || (ata_is_pio(prot) &&
-+				 (ap->flags & ATA_FLAG_PIO_DMA)))
-+		if (ata_sg_setup(qc))
-+			goto sg_err;
+ 	if (blk_queue_stopped(port->disk->queue))
+ 		blk_start_queue(port->disk->queue);
+@@ -456,7 +453,7 @@ static void do_vdc_request(struct request_queue *q)
  
- 	/* if device is sleeping, schedule softreset and abort the link */
- 	if (unlikely(qc->dev->flags & ATA_DFLAG_SLEEPING)) {
-@@ -6029,7 +5979,6 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
- 	return;
+ 		blkdev_dequeue_request(req);
+ 		if (__send_request(req) < 0)
+-			vdc_end_request(req, 0, req->hard_nr_sectors);
++			vdc_end_request(req, -EIO, req->hard_nr_sectors);
+ 	}
+ }
  
- sg_err:
--	qc->flags &= ~ATA_QCFLAG_DMAMAP;
- 	qc->err_mask |= AC_ERR_SYSTEM;
- err:
- 	ata_qc_complete(qc);
-@@ -6064,11 +6013,11 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
- 		switch (qc->tf.protocol) {
- 		case ATA_PROT_PIO:
- 		case ATA_PROT_NODATA:
--		case ATA_PROT_ATAPI:
--		case ATA_PROT_ATAPI_NODATA:
-+		case ATAPI_PROT_PIO:
-+		case ATAPI_PROT_NODATA:
- 			qc->tf.flags |= ATA_TFLAG_POLLING;
- 			break;
--		case ATA_PROT_ATAPI_DMA:
-+		case ATAPI_PROT_DMA:
- 			if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
- 				/* see ata_dma_blacklisted() */
- 				BUG();
-@@ -6091,7 +6040,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
- 		ap->hsm_task_state = HSM_ST_LAST;
+@@ -735,7 +732,7 @@ static struct vio_driver_ops vdc_vio_ops = {
+ 	.handshake_complete	= vdc_handshake_complete,
+ };
  
- 		if (qc->tf.flags & ATA_TFLAG_POLLING)
--			ata_port_queue_task(ap, ata_pio_task, qc, 0);
-+			ata_pio_queue_task(ap, qc, 0);
+-static void print_version(void)
++static void __devinit print_version(void)
+ {
+ 	static int version_printed;
  
- 		break;
+diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
+index 52dc5e1..cd5674b 100644
+--- a/drivers/block/sx8.c
++++ b/drivers/block/sx8.c
+@@ -744,16 +744,14 @@ static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
  
-@@ -6113,7 +6062,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
- 		if (qc->tf.flags & ATA_TFLAG_WRITE) {
- 			/* PIO data out protocol */
- 			ap->hsm_task_state = HSM_ST_FIRST;
--			ata_port_queue_task(ap, ata_pio_task, qc, 0);
-+			ata_pio_queue_task(ap, qc, 0);
+ static inline void carm_end_request_queued(struct carm_host *host,
+ 					   struct carm_request *crq,
+-					   int uptodate)
++					   int error)
+ {
+ 	struct request *req = crq->rq;
+ 	int rc;
  
- 			/* always send first data block using
- 			 * the ata_pio_task() codepath.
-@@ -6123,7 +6072,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
- 			ap->hsm_task_state = HSM_ST;
+-	rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
++	rc = __blk_end_request(req, error, blk_rq_bytes(req));
+ 	assert(rc == 0);
  
- 			if (qc->tf.flags & ATA_TFLAG_POLLING)
--				ata_port_queue_task(ap, ata_pio_task, qc, 0);
-+				ata_pio_queue_task(ap, qc, 0);
+-	end_that_request_last(req, uptodate);
+-
+ 	rc = carm_put_request(host, crq);
+ 	assert(rc == 0);
+ }
+@@ -793,9 +791,9 @@ static inline void carm_round_robin(struct carm_host *host)
+ }
  
- 			/* if polling, ata_pio_task() handles the rest.
- 			 * otherwise, interrupt handler takes over from here.
-@@ -6132,8 +6081,8 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
+-			int is_ok)
++			       int error)
+ {
+-	carm_end_request_queued(host, crq, is_ok);
++	carm_end_request_queued(host, crq, error);
+ 	if (max_queue == 1)
+ 		carm_round_robin(host);
+ 	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
+@@ -873,14 +871,14 @@ queue_one_request:
+ 	sg = &crq->sg[0];
+ 	n_elem = blk_rq_map_sg(q, rq, sg);
+ 	if (n_elem <= 0) {
+-		carm_end_rq(host, crq, 0);
++		carm_end_rq(host, crq, -EIO);
+ 		return;		/* request with no s/g entries? */
+ 	}
  
- 		break;
+ 	/* map scatterlist to PCI bus addresses */
+ 	n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
+ 	if (n_elem <= 0) {
+-		carm_end_rq(host, crq, 0);
++		carm_end_rq(host, crq, -EIO);
+ 		return;		/* request with no s/g entries? */
+ 	}
+ 	crq->n_elem = n_elem;
+@@ -941,7 +939,7 @@ queue_one_request:
  
--	case ATA_PROT_ATAPI:
--	case ATA_PROT_ATAPI_NODATA:
-+	case ATAPI_PROT_PIO:
-+	case ATAPI_PROT_NODATA:
- 		if (qc->tf.flags & ATA_TFLAG_POLLING)
- 			ata_qc_set_polling(qc);
+ static void carm_handle_array_info(struct carm_host *host,
+ 				   struct carm_request *crq, u8 *mem,
+-				   int is_ok)
++				   int error)
+ {
+ 	struct carm_port *port;
+ 	u8 *msg_data = mem + sizeof(struct carm_array_info);
+@@ -952,9 +950,9 @@ static void carm_handle_array_info(struct carm_host *host,
  
-@@ -6144,10 +6093,10 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
- 		/* send cdb by polling if no cdb interrupt */
- 		if ((!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) ||
- 		    (qc->tf.flags & ATA_TFLAG_POLLING))
--			ata_port_queue_task(ap, ata_pio_task, qc, 0);
-+			ata_pio_queue_task(ap, qc, 0);
- 		break;
+ 	DPRINTK("ENTER\n");
  
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		WARN_ON(qc->tf.flags & ATA_TFLAG_POLLING);
+-	carm_end_rq(host, crq, is_ok);
++	carm_end_rq(host, crq, error);
  
- 		ap->ops->tf_load(ap, &qc->tf);	 /* load tf registers */
-@@ -6156,7 +6105,7 @@ unsigned int ata_qc_issue_prot(struct ata_queued_cmd *qc)
+-	if (!is_ok)
++	if (error)
+ 		goto out;
+ 	if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
+ 		goto out;
+@@ -1001,7 +999,7 @@ out:
  
- 		/* send cdb by polling if no cdb interrupt */
- 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
--			ata_port_queue_task(ap, ata_pio_task, qc, 0);
-+			ata_pio_queue_task(ap, qc, 0);
- 		break;
+ static void carm_handle_scan_chan(struct carm_host *host,
+ 				  struct carm_request *crq, u8 *mem,
+-				  int is_ok)
++				  int error)
+ {
+ 	u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
+ 	unsigned int i, dev_count = 0;
+@@ -1009,9 +1007,9 @@ static void carm_handle_scan_chan(struct carm_host *host,
  
- 	default:
-@@ -6200,15 +6149,15 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
- 		 */
+ 	DPRINTK("ENTER\n");
  
- 		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
--		 * The flag was turned on only for atapi devices.
--		 * No need to check is_atapi_taskfile(&qc->tf) again.
-+		 * The flag was turned on only for atapi devices.  No
-+		 * need to check ata_is_atapi(qc->tf.protocol) again.
- 		 */
- 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
- 			goto idle_irq;
- 		break;
- 	case HSM_ST_LAST:
- 		if (qc->tf.protocol == ATA_PROT_DMA ||
--		    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
-+		    qc->tf.protocol == ATAPI_PROT_DMA) {
- 			/* check status of DMA engine */
- 			host_stat = ap->ops->bmdma_status(ap);
- 			VPRINTK("ata%u: host_stat 0x%X\n",
-@@ -6250,7 +6199,7 @@ inline unsigned int ata_host_intr(struct ata_port *ap,
- 	ata_hsm_move(ap, qc, status, 0);
+-	carm_end_rq(host, crq, is_ok);
++	carm_end_rq(host, crq, error);
  
- 	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
--				       qc->tf.protocol == ATA_PROT_ATAPI_DMA))
-+				       qc->tf.protocol == ATAPI_PROT_DMA))
- 		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
+-	if (!is_ok) {
++	if (error) {
+ 		new_state = HST_ERROR;
+ 		goto out;
+ 	}
+@@ -1033,23 +1031,23 @@ out:
+ }
  
- 	return 1;	/* irq handled */
-@@ -6772,7 +6721,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
- 	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
- #endif
+ static void carm_handle_generic(struct carm_host *host,
+-				struct carm_request *crq, int is_ok,
++				struct carm_request *crq, int error,
+ 				int cur_state, int next_state)
+ {
+ 	DPRINTK("ENTER\n");
  
--	INIT_DELAYED_WORK(&ap->port_task, NULL);
-+	INIT_DELAYED_WORK(&ap->port_task, ata_pio_task);
- 	INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
- 	INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
- 	INIT_LIST_HEAD(&ap->eh_done_q);
-@@ -7589,7 +7538,6 @@ EXPORT_SYMBOL_GPL(ata_host_register);
- EXPORT_SYMBOL_GPL(ata_host_activate);
- EXPORT_SYMBOL_GPL(ata_host_detach);
- EXPORT_SYMBOL_GPL(ata_sg_init);
--EXPORT_SYMBOL_GPL(ata_sg_init_one);
- EXPORT_SYMBOL_GPL(ata_hsm_move);
- EXPORT_SYMBOL_GPL(ata_qc_complete);
- EXPORT_SYMBOL_GPL(ata_qc_complete_multiple);
-@@ -7601,6 +7549,13 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select);
- EXPORT_SYMBOL_GPL(sata_print_link_status);
- EXPORT_SYMBOL_GPL(ata_tf_to_fis);
- EXPORT_SYMBOL_GPL(ata_tf_from_fis);
-+EXPORT_SYMBOL_GPL(ata_pack_xfermask);
-+EXPORT_SYMBOL_GPL(ata_unpack_xfermask);
-+EXPORT_SYMBOL_GPL(ata_xfer_mask2mode);
-+EXPORT_SYMBOL_GPL(ata_xfer_mode2mask);
-+EXPORT_SYMBOL_GPL(ata_xfer_mode2shift);
-+EXPORT_SYMBOL_GPL(ata_mode_string);
-+EXPORT_SYMBOL_GPL(ata_id_xfermask);
- EXPORT_SYMBOL_GPL(ata_check_status);
- EXPORT_SYMBOL_GPL(ata_altstatus);
- EXPORT_SYMBOL_GPL(ata_exec_command);
-@@ -7643,7 +7598,6 @@ EXPORT_SYMBOL_GPL(ata_wait_register);
- EXPORT_SYMBOL_GPL(ata_busy_sleep);
- EXPORT_SYMBOL_GPL(ata_wait_after_reset);
- EXPORT_SYMBOL_GPL(ata_wait_ready);
--EXPORT_SYMBOL_GPL(ata_port_queue_task);
- EXPORT_SYMBOL_GPL(ata_scsi_ioctl);
- EXPORT_SYMBOL_GPL(ata_scsi_queuecmd);
- EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
-@@ -7662,18 +7616,20 @@ EXPORT_SYMBOL_GPL(ata_host_resume);
- #endif /* CONFIG_PM */
- EXPORT_SYMBOL_GPL(ata_id_string);
- EXPORT_SYMBOL_GPL(ata_id_c_string);
--EXPORT_SYMBOL_GPL(ata_id_to_dma_mode);
- EXPORT_SYMBOL_GPL(ata_scsi_simulate);
+-	carm_end_rq(host, crq, is_ok);
++	carm_end_rq(host, crq, error);
  
- EXPORT_SYMBOL_GPL(ata_pio_need_iordy);
-+EXPORT_SYMBOL_GPL(ata_timing_find_mode);
- EXPORT_SYMBOL_GPL(ata_timing_compute);
- EXPORT_SYMBOL_GPL(ata_timing_merge);
-+EXPORT_SYMBOL_GPL(ata_timing_cycle2mode);
+ 	assert(host->state == cur_state);
+-	if (is_ok)
+-		host->state = next_state;
+-	else
++	if (error)
+ 		host->state = HST_ERROR;
++	else
++		host->state = next_state;
+ 	schedule_work(&host->fsm_task);
+ }
  
- #ifdef CONFIG_PCI
- EXPORT_SYMBOL_GPL(pci_test_config_bits);
- EXPORT_SYMBOL_GPL(ata_pci_init_sff_host);
- EXPORT_SYMBOL_GPL(ata_pci_init_bmdma);
- EXPORT_SYMBOL_GPL(ata_pci_prepare_sff_host);
-+EXPORT_SYMBOL_GPL(ata_pci_activate_sff_host);
- EXPORT_SYMBOL_GPL(ata_pci_init_one);
- EXPORT_SYMBOL_GPL(ata_pci_remove_one);
- #ifdef CONFIG_PM
-@@ -7715,4 +7671,5 @@ EXPORT_SYMBOL_GPL(ata_dev_try_classify);
- EXPORT_SYMBOL_GPL(ata_cable_40wire);
- EXPORT_SYMBOL_GPL(ata_cable_80wire);
- EXPORT_SYMBOL_GPL(ata_cable_unknown);
-+EXPORT_SYMBOL_GPL(ata_cable_ignore);
- EXPORT_SYMBOL_GPL(ata_cable_sata);
-diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
-index 21a81cd..4e31071 100644
---- a/drivers/ata/libata-eh.c
-+++ b/drivers/ata/libata-eh.c
-@@ -46,9 +46,26 @@
- #include "libata.h"
+ static inline void carm_handle_rw(struct carm_host *host,
+-				  struct carm_request *crq, int is_ok)
++				  struct carm_request *crq, int error)
+ {
+ 	int pci_dir;
  
- enum {
-+	/* speed down verdicts */
- 	ATA_EH_SPDN_NCQ_OFF		= (1 << 0),
- 	ATA_EH_SPDN_SPEED_DOWN		= (1 << 1),
- 	ATA_EH_SPDN_FALLBACK_TO_PIO	= (1 << 2),
-+	ATA_EH_SPDN_KEEP_ERRORS		= (1 << 3),
-+
-+	/* error flags */
-+	ATA_EFLAG_IS_IO			= (1 << 0),
-+	ATA_EFLAG_DUBIOUS_XFER		= (1 << 1),
-+
-+	/* error categories */
-+	ATA_ECAT_NONE			= 0,
-+	ATA_ECAT_ATA_BUS		= 1,
-+	ATA_ECAT_TOUT_HSM		= 2,
-+	ATA_ECAT_UNK_DEV		= 3,
-+	ATA_ECAT_DUBIOUS_NONE		= 4,
-+	ATA_ECAT_DUBIOUS_ATA_BUS	= 5,
-+	ATA_ECAT_DUBIOUS_TOUT_HSM	= 6,
-+	ATA_ECAT_DUBIOUS_UNK_DEV	= 7,
-+	ATA_ECAT_NR			= 8,
- };
+@@ -1062,7 +1060,7 @@ static inline void carm_handle_rw(struct carm_host *host,
  
- /* Waiting in ->prereset can never be reliable.  It's sometimes nice
-@@ -213,12 +230,13 @@ void ata_port_pbar_desc(struct ata_port *ap, int bar, ssize_t offset,
- 	if (offset < 0)
- 		ata_port_desc(ap, "%s %s%llu at 0x%llx", name, type, len, start);
- 	else
--		ata_port_desc(ap, "%s 0x%llx", name, start + offset);
-+		ata_port_desc(ap, "%s 0x%llx", name,
-+				start + (unsigned long long)offset);
+ 	pci_unmap_sg(host->pdev, &crq->sg[0], crq->n_elem, pci_dir);
+ 
+-	carm_end_rq(host, crq, is_ok);
++	carm_end_rq(host, crq, error);
  }
  
- #endif /* CONFIG_PCI */
+ static inline void carm_handle_resp(struct carm_host *host,
+@@ -1071,7 +1069,7 @@ static inline void carm_handle_resp(struct carm_host *host,
+ 	u32 handle = le32_to_cpu(ret_handle_le);
+ 	unsigned int msg_idx;
+ 	struct carm_request *crq;
+-	int is_ok = (status == RMSG_OK);
++	int error = (status == RMSG_OK) ? 0 : -EIO;
+ 	u8 *mem;
  
--static void ata_ering_record(struct ata_ering *ering, int is_io,
-+static void ata_ering_record(struct ata_ering *ering, unsigned int eflags,
- 			     unsigned int err_mask)
- {
- 	struct ata_ering_entry *ent;
-@@ -229,11 +247,20 @@ static void ata_ering_record(struct ata_ering *ering, int is_io,
- 	ering->cursor %= ATA_ERING_SIZE;
+ 	VPRINTK("ENTER, handle == 0x%x\n", handle);
+@@ -1090,7 +1088,7 @@ static inline void carm_handle_resp(struct carm_host *host,
+ 	/* fast path */
+ 	if (likely(crq->msg_type == CARM_MSG_READ ||
+ 		   crq->msg_type == CARM_MSG_WRITE)) {
+-		carm_handle_rw(host, crq, is_ok);
++		carm_handle_rw(host, crq, error);
+ 		return;
+ 	}
  
- 	ent = &ering->ring[ering->cursor];
--	ent->is_io = is_io;
-+	ent->eflags = eflags;
- 	ent->err_mask = err_mask;
- 	ent->timestamp = get_jiffies_64();
+@@ -1100,7 +1098,7 @@ static inline void carm_handle_resp(struct carm_host *host,
+ 	case CARM_MSG_IOCTL: {
+ 		switch (crq->msg_subtype) {
+ 		case CARM_IOC_SCAN_CHAN:
+-			carm_handle_scan_chan(host, crq, mem, is_ok);
++			carm_handle_scan_chan(host, crq, mem, error);
+ 			break;
+ 		default:
+ 			/* unknown / invalid response */
+@@ -1112,21 +1110,21 @@ static inline void carm_handle_resp(struct carm_host *host,
+ 	case CARM_MSG_MISC: {
+ 		switch (crq->msg_subtype) {
+ 		case MISC_ALLOC_MEM:
+-			carm_handle_generic(host, crq, is_ok,
++			carm_handle_generic(host, crq, error,
+ 					    HST_ALLOC_BUF, HST_SYNC_TIME);
+ 			break;
+ 		case MISC_SET_TIME:
+-			carm_handle_generic(host, crq, is_ok,
++			carm_handle_generic(host, crq, error,
+ 					    HST_SYNC_TIME, HST_GET_FW_VER);
+ 			break;
+ 		case MISC_GET_FW_VER: {
+ 			struct carm_fw_ver *ver = (struct carm_fw_ver *)
+ 				mem + sizeof(struct carm_msg_get_fw_ver);
+-			if (is_ok) {
++			if (!error) {
+ 				host->fw_ver = le32_to_cpu(ver->version);
+ 				host->flags |= (ver->features & FL_FW_VER_MASK);
+ 			}
+-			carm_handle_generic(host, crq, is_ok,
++			carm_handle_generic(host, crq, error,
+ 					    HST_GET_FW_VER, HST_PORT_SCAN);
+ 			break;
+ 		}
+@@ -1140,7 +1138,7 @@ static inline void carm_handle_resp(struct carm_host *host,
+ 	case CARM_MSG_ARRAY: {
+ 		switch (crq->msg_subtype) {
+ 		case CARM_ARRAY_INFO:
+-			carm_handle_array_info(host, crq, mem, is_ok);
++			carm_handle_array_info(host, crq, mem, error);
+ 			break;
+ 		default:
+ 			/* unknown / invalid response */
+@@ -1159,7 +1157,7 @@ static inline void carm_handle_resp(struct carm_host *host,
+ err_out:
+ 	printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
+ 	       pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
+-	carm_end_rq(host, crq, 0);
++	carm_end_rq(host, crq, -EIO);
  }
  
-+static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
-+{
-+	struct ata_ering_entry *ent = &ering->ring[ering->cursor];
-+
-+	if (ent->err_mask)
-+		return ent;
-+	return NULL;
-+}
-+
- static void ata_ering_clear(struct ata_ering *ering)
- {
- 	memset(ering, 0, sizeof(*ering));
-@@ -445,9 +472,20 @@ void ata_scsi_error(struct Scsi_Host *host)
- 		spin_lock_irqsave(ap->lock, flags);
- 
- 		__ata_port_for_each_link(link, ap) {
-+			struct ata_eh_context *ehc = &link->eh_context;
-+			struct ata_device *dev;
-+
- 			memset(&link->eh_context, 0, sizeof(link->eh_context));
- 			link->eh_context.i = link->eh_info;
- 			memset(&link->eh_info, 0, sizeof(link->eh_info));
-+
-+			ata_link_for_each_dev(dev, link) {
-+				int devno = dev->devno;
-+
-+				ehc->saved_xfer_mode[devno] = dev->xfer_mode;
-+				if (ata_ncq_enabled(dev))
-+					ehc->saved_ncq_enabled |= 1 << devno;
-+			}
- 		}
+ static inline void carm_handle_responses(struct carm_host *host)
+diff --git a/drivers/block/ub.c b/drivers/block/ub.c
+index 08e909d..a70c1c2 100644
+--- a/drivers/block/ub.c
++++ b/drivers/block/ub.c
+@@ -808,16 +808,16 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
  
- 		ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
-@@ -1260,10 +1298,10 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
+ static void ub_end_rq(struct request *rq, unsigned int scsi_status)
+ {
+-	int uptodate;
++	int error;
  
- 	/* is it pointless to prefer PIO for "safety reasons"? */
- 	if (ap->flags & ATA_FLAG_PIO_DMA) {
--		tf.protocol = ATA_PROT_ATAPI_DMA;
-+		tf.protocol = ATAPI_PROT_DMA;
- 		tf.feature |= ATAPI_PKT_DMA;
+ 	if (scsi_status == 0) {
+-		uptodate = 1;
++		error = 0;
  	} else {
--		tf.protocol = ATA_PROT_ATAPI;
-+		tf.protocol = ATAPI_PROT_PIO;
- 		tf.lbam = SCSI_SENSE_BUFFERSIZE;
- 		tf.lbah = 0;
+-		uptodate = 0;
++		error = -EIO;
+ 		rq->errors = scsi_status;
  	}
-@@ -1451,20 +1489,29 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc,
- 	return action;
+-	end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
+-	end_that_request_last(rq, uptodate);
++	if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
++		BUG();
  }
  
--static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
-+static int ata_eh_categorize_error(unsigned int eflags, unsigned int err_mask,
-+				   int *xfer_ok)
- {
-+	int base = 0;
-+
-+	if (!(eflags & ATA_EFLAG_DUBIOUS_XFER))
-+		*xfer_ok = 1;
-+
-+	if (!*xfer_ok)
-+		base = ATA_ECAT_DUBIOUS_NONE;
-+
- 	if (err_mask & AC_ERR_ATA_BUS)
--		return 1;
-+		return base + ATA_ECAT_ATA_BUS;
+ static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
+@@ -922,11 +922,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+ 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
+ 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
  
- 	if (err_mask & AC_ERR_TIMEOUT)
--		return 2;
-+		return base + ATA_ECAT_TOUT_HSM;
+-	/* Fill what we shouldn't be filling, because usb-storage did so. */
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
+-
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ 		/* XXX Clear stalls */
+ 		ub_complete(&sc->work_done);
+@@ -1313,9 +1308,6 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+ 	sc->last_pipe = pipe;
+ 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
+ 	    sg->length, ub_urb_complete, sc);
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
  
--	if (is_io) {
-+	if (eflags & ATA_EFLAG_IS_IO) {
- 		if (err_mask & AC_ERR_HSM)
--			return 2;
-+			return base + ATA_ECAT_TOUT_HSM;
- 		if ((err_mask &
- 		     (AC_ERR_DEV|AC_ERR_MEDIA|AC_ERR_INVALID)) == AC_ERR_DEV)
--			return 3;
-+			return base + ATA_ECAT_UNK_DEV;
- 	}
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ 		/* XXX Clear stalls */
+@@ -1356,9 +1348,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+ 	sc->last_pipe = sc->recv_bulk_pipe;
+ 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
+ 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
  
- 	return 0;
-@@ -1472,18 +1519,22 @@ static int ata_eh_categorize_error(int is_io, unsigned int err_mask)
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ 		/* XXX Clear stalls */
+@@ -1473,9 +1462,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
  
- struct speed_down_verdict_arg {
- 	u64 since;
--	int nr_errors[4];
-+	int xfer_ok;
-+	int nr_errors[ATA_ECAT_NR];
- };
+ 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ 	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
  
- static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
- {
- 	struct speed_down_verdict_arg *arg = void_arg;
--	int cat = ata_eh_categorize_error(ent->is_io, ent->err_mask);
-+	int cat;
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
+ 		ub_complete(&sc->work_done);
+@@ -1953,9 +1939,6 @@ static int ub_sync_reset(struct ub_dev *sc)
  
- 	if (ent->timestamp < arg->since)
- 		return -1;
+ 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
  
-+	cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
-+				      &arg->xfer_ok);
- 	arg->nr_errors[cat]++;
-+
- 	return 0;
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ 		printk(KERN_WARNING
+@@ -2007,9 +1990,6 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
+ 
+ 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
+ 	    (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
+ 
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
+ 		goto err_submit;
+@@ -2077,9 +2057,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
+ 
+ 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
+ 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
+-	sc->work_urb.actual_length = 0;
+-	sc->work_urb.error_count = 0;
+-	sc->work_urb.status = 0;
+ 
+ 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ 		printk(KERN_WARNING
+diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
+index ab5d404..9e61fca 100644
+--- a/drivers/block/viodasd.c
++++ b/drivers/block/viodasd.c
+@@ -229,13 +229,10 @@ static struct block_device_operations viodasd_fops = {
+ /*
+  * End a request
+  */
+-static void viodasd_end_request(struct request *req, int uptodate,
++static void viodasd_end_request(struct request *req, int error,
+ 		int num_sectors)
+ {
+-	if (end_that_request_first(req, uptodate, num_sectors))
+-		return;
+-	add_disk_randomness(req->rq_disk);
+-	end_that_request_last(req, uptodate);
++	__blk_end_request(req, error, num_sectors << 9);
  }
  
-@@ -1495,22 +1546,48 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
-  *	whether NCQ needs to be turned off, transfer speed should be
-  *	stepped down, or falling back to PIO is necessary.
-  *
-- *	Cat-1 is ATA_BUS error for any command.
-+ *	ECAT_ATA_BUS	: ATA_BUS error for any command
-+ *
-+ *	ECAT_TOUT_HSM	: TIMEOUT for any command or HSM violation for
-+ *			  IO commands
-+ *
-+ *	ECAT_UNK_DEV	: Unknown DEV error for IO commands
-+ *
-+ *	ECAT_DUBIOUS_*	: Identical to above three but occurred while
-+ *			  data transfer hasn't been verified.
-+ *
-+ *	Verdicts are
-+ *
-+ *	NCQ_OFF		: Turn off NCQ.
-+ *
-+ *	SPEED_DOWN	: Speed down transfer speed but don't fall back
-+ *			  to PIO.
-+ *
-+ *	FALLBACK_TO_PIO	: Fall back to PIO.
-+ *
-+ *	Even if multiple verdicts are returned, only one action is
-+ *	taken per error.  An action triggered by non-DUBIOUS errors
-+ *	clears ering, while one triggered by DUBIOUS_* errors doesn't.
-+ *	This is to expedite speed down decisions right after device is
-+ *	initially configured.
-  *
-- *	Cat-2 is TIMEOUT for any command or HSM violation for known
-- *	supported commands.
-+ *	The followings are speed down rules.  #1 and #2 deal with
-+ *	DUBIOUS errors.
-  *
-- *	Cat-3 is is unclassified DEV error for known supported
-- *	command.
-+ *	1. If more than one DUBIOUS_ATA_BUS or DUBIOUS_TOUT_HSM errors
-+ *	   occurred during last 5 mins, SPEED_DOWN and FALLBACK_TO_PIO.
-  *
-- *	NCQ needs to be turned off if there have been more than 3
-- *	Cat-2 + Cat-3 errors during last 10 minutes.
-+ *	2. If more than one DUBIOUS_TOUT_HSM or DUBIOUS_UNK_DEV errors
-+ *	   occurred during last 5 mins, NCQ_OFF.
-  *
-- *	Speed down is necessary if there have been more than 3 Cat-1 +
-- *	Cat-2 errors or 10 Cat-3 errors during last 10 minutes.
-+ *	3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors
-+ *	   ocurred during last 5 mins, FALLBACK_TO_PIO
-  *
-- *	Falling back to PIO mode is necessary if there have been more
-- *	than 10 Cat-1 + Cat-2 + Cat-3 errors during last 5 minutes.
-+ *	4. If more than 3 TOUT_HSM or UNK_DEV errors occurred
-+ *	   during last 10 mins, NCQ_OFF.
-+ *
-+ *	5. If more than 3 ATA_BUS or TOUT_HSM errors, or more than 6
-+ *	   UNK_DEV errors occurred during last 10 mins, SPEED_DOWN.
-  *
-  *	LOCKING:
-  *	Inherited from caller.
-@@ -1525,23 +1602,38 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
- 	struct speed_down_verdict_arg arg;
- 	unsigned int verdict = 0;
+ /*
+@@ -374,12 +371,12 @@ static void do_viodasd_request(struct request_queue *q)
+ 		blkdev_dequeue_request(req);
+ 		/* check that request contains a valid command */
+ 		if (!blk_fs_request(req)) {
+-			viodasd_end_request(req, 0, req->hard_nr_sectors);
++			viodasd_end_request(req, -EIO, req->hard_nr_sectors);
+ 			continue;
+ 		}
+ 		/* Try sending the request */
+ 		if (send_request(req) != 0)
+-			viodasd_end_request(req, 0, req->hard_nr_sectors);
++			viodasd_end_request(req, -EIO, req->hard_nr_sectors);
+ 	}
+ }
  
--	/* scan past 10 mins of error history */
-+	/* scan past 5 mins of error history */
- 	memset(&arg, 0, sizeof(arg));
--	arg.since = j64 - min(j64, j10mins);
-+	arg.since = j64 - min(j64, j5mins);
- 	ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
+@@ -591,7 +588,7 @@ static int viodasd_handle_read_write(struct vioblocklpevent *bevent)
+ 	num_req_outstanding--;
+ 	spin_unlock_irqrestore(&viodasd_spinlock, irq_flags);
+ 
+-	error = event->xRc != HvLpEvent_Rc_Good;
++	error = (event->xRc == HvLpEvent_Rc_Good) ? 0 : -EIO;
+ 	if (error) {
+ 		const struct vio_error_entry *err;
+ 		err = vio_lookup_rc(viodasd_err_table, bevent->sub_result);
+@@ -601,7 +598,7 @@ static int viodasd_handle_read_write(struct vioblocklpevent *bevent)
+ 	}
+ 	qlock = req->q->queue_lock;
+ 	spin_lock_irqsave(qlock, irq_flags);
+-	viodasd_end_request(req, !error, num_sect);
++	viodasd_end_request(req, error, num_sect);
+ 	spin_unlock_irqrestore(qlock, irq_flags);
+ 
+ 	/* Finally, try to get more requests off of this device's queue */
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index 924ddd8..3b1a68d 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -7,8 +7,10 @@
+ #include <linux/scatterlist.h>
+ 
+ #define VIRTIO_MAX_SG	(3+MAX_PHYS_SEGMENTS)
++#define PART_BITS 4
++
++static int major, index;
+ 
+-static unsigned char virtblk_index = 'a';
+ struct virtio_blk
+ {
+ 	spinlock_t lock;
+@@ -36,7 +38,7 @@ struct virtblk_req
+ 	struct virtio_blk_inhdr in_hdr;
+ };
  
--	if (arg.nr_errors[2] + arg.nr_errors[3] > 3)
--		verdict |= ATA_EH_SPDN_NCQ_OFF;
--	if (arg.nr_errors[1] + arg.nr_errors[2] > 3 || arg.nr_errors[3] > 10)
--		verdict |= ATA_EH_SPDN_SPEED_DOWN;
-+	if (arg.nr_errors[ATA_ECAT_DUBIOUS_ATA_BUS] +
-+	    arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] > 1)
-+		verdict |= ATA_EH_SPDN_SPEED_DOWN |
-+			ATA_EH_SPDN_FALLBACK_TO_PIO | ATA_EH_SPDN_KEEP_ERRORS;
+-static bool blk_done(struct virtqueue *vq)
++static void blk_done(struct virtqueue *vq)
+ {
+ 	struct virtio_blk *vblk = vq->vdev->priv;
+ 	struct virtblk_req *vbr;
+@@ -65,7 +67,6 @@ static bool blk_done(struct virtqueue *vq)
+ 	/* In case queue is stopped waiting for more buffers. */
+ 	blk_start_queue(vblk->disk->queue);
+ 	spin_unlock_irqrestore(&vblk->lock, flags);
+-	return true;
+ }
  
--	/* scan past 3 mins of error history */
-+	if (arg.nr_errors[ATA_ECAT_DUBIOUS_TOUT_HSM] +
-+	    arg.nr_errors[ATA_ECAT_DUBIOUS_UNK_DEV] > 1)
-+		verdict |= ATA_EH_SPDN_NCQ_OFF | ATA_EH_SPDN_KEEP_ERRORS;
+ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
+@@ -153,20 +154,37 @@ static int virtblk_ioctl(struct inode *inode, struct file *filp,
+ 			      (void __user *)data);
+ }
+ 
++/* We provide getgeo only to please some old bootloader/partitioning tools */
++static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
++{
++	/* some standard values, similar to sd */
++	geo->heads = 1 << 6;
++	geo->sectors = 1 << 5;
++	geo->cylinders = get_capacity(bd->bd_disk) >> 11;
++	return 0;
++}
 +
-+	if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
-+	    arg.nr_errors[ATA_ECAT_TOUT_HSM] +
-+	    arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
-+		verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
+ static struct block_device_operations virtblk_fops = {
+-	.ioctl = virtblk_ioctl,
+-	.owner = THIS_MODULE,
++	.ioctl  = virtblk_ioctl,
++	.owner  = THIS_MODULE,
++	.getgeo = virtblk_getgeo,
+ };
+ 
++static int index_to_minor(int index)
++{
++	return index << PART_BITS;
++}
 +
-+	/* scan past 10 mins of error history */
- 	memset(&arg, 0, sizeof(arg));
--	arg.since = j64 - min(j64, j5mins);
-+	arg.since = j64 - min(j64, j10mins);
- 	ata_ering_map(&dev->ering, speed_down_verdict_cb, &arg);
+ static int virtblk_probe(struct virtio_device *vdev)
+ {
+ 	struct virtio_blk *vblk;
+-	int err, major;
+-	void *token;
+-	unsigned int len;
++	int err;
+ 	u64 cap;
+ 	u32 v;
  
--	if (arg.nr_errors[1] + arg.nr_errors[2] + arg.nr_errors[3] > 10)
--		verdict |= ATA_EH_SPDN_FALLBACK_TO_PIO;
-+	if (arg.nr_errors[ATA_ECAT_TOUT_HSM] +
-+	    arg.nr_errors[ATA_ECAT_UNK_DEV] > 3)
-+		verdict |= ATA_EH_SPDN_NCQ_OFF;
++	if (index_to_minor(index) >= 1 << MINORBITS)
++		return -ENOSPC;
 +
-+	if (arg.nr_errors[ATA_ECAT_ATA_BUS] +
-+	    arg.nr_errors[ATA_ECAT_TOUT_HSM] > 3 ||
-+	    arg.nr_errors[ATA_ECAT_UNK_DEV] > 6)
-+		verdict |= ATA_EH_SPDN_SPEED_DOWN;
+ 	vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL);
+ 	if (!vblk) {
+ 		err = -ENOMEM;
+@@ -178,7 +196,7 @@ static int virtblk_probe(struct virtio_device *vdev)
+ 	vblk->vdev = vdev;
  
- 	return verdict;
+ 	/* We expect one virtqueue, for output. */
+-	vblk->vq = vdev->config->find_vq(vdev, blk_done);
++	vblk->vq = vdev->config->find_vq(vdev, 0, blk_done);
+ 	if (IS_ERR(vblk->vq)) {
+ 		err = PTR_ERR(vblk->vq);
+ 		goto out_free_vblk;
+@@ -190,17 +208,11 @@ static int virtblk_probe(struct virtio_device *vdev)
+ 		goto out_free_vq;
+ 	}
+ 
+-	major = register_blkdev(0, "virtblk");
+-	if (major < 0) {
+-		err = major;
+-		goto out_mempool;
+-	}
+-
+ 	/* FIXME: How many partitions?  How long is a piece of string? */
+-	vblk->disk = alloc_disk(1 << 4);
++	vblk->disk = alloc_disk(1 << PART_BITS);
+ 	if (!vblk->disk) {
+ 		err = -ENOMEM;
+-		goto out_unregister_blkdev;
++		goto out_mempool;
+ 	}
+ 
+ 	vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock);
+@@ -209,22 +221,32 @@ static int virtblk_probe(struct virtio_device *vdev)
+ 		goto out_put_disk;
+ 	}
+ 
+-	sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++);
++	if (index < 26) {
++		sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
++	} else if (index < (26 + 1) * 26) {
++		sprintf(vblk->disk->disk_name, "vd%c%c",
++			'a' + index / 26 - 1, 'a' + index % 26);
++	} else {
++		const unsigned int m1 = (index / 26 - 1) / 26 - 1;
++		const unsigned int m2 = (index / 26 - 1) % 26;
++		const unsigned int m3 =  index % 26;
++		sprintf(vblk->disk->disk_name, "vd%c%c%c",
++			'a' + m1, 'a' + m2, 'a' + m3);
++	}
++
+ 	vblk->disk->major = major;
+-	vblk->disk->first_minor = 0;
++	vblk->disk->first_minor = index_to_minor(index);
+ 	vblk->disk->private_data = vblk;
+ 	vblk->disk->fops = &virtblk_fops;
++	index++;
+ 
+ 	/* If barriers are supported, tell block layer that queue is ordered */
+-	token = vdev->config->find(vdev, VIRTIO_CONFIG_BLK_F, &len);
+-	if (virtio_use_bit(vdev, token, len, VIRTIO_BLK_F_BARRIER))
++	if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER))
+ 		blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
+ 
+-	err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap);
+-	if (err) {
+-		dev_err(&vdev->dev, "Bad/missing capacity in config\n");
+-		goto out_cleanup_queue;
+-	}
++	/* Host must always specify the capacity. */
++	__virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity),
++			    &cap);
+ 
+ 	/* If capacity is too big, truncate with warning. */
+ 	if ((sector_t)cap != cap) {
+@@ -234,31 +256,25 @@ static int virtblk_probe(struct virtio_device *vdev)
+ 	}
+ 	set_capacity(vblk->disk, cap);
+ 
+-	err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SIZE_MAX, &v);
++	/* Host can optionally specify maximum segment size and number of
++	 * segments. */
++	err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX,
++				offsetof(struct virtio_blk_config, size_max),
++				&v);
+ 	if (!err)
+ 		blk_queue_max_segment_size(vblk->disk->queue, v);
+-	else if (err != -ENOENT) {
+-		dev_err(&vdev->dev, "Bad SIZE_MAX in config\n");
+-		goto out_cleanup_queue;
+-	}
+ 
+-	err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v);
++	err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
++				offsetof(struct virtio_blk_config, seg_max),
++				&v);
+ 	if (!err)
+ 		blk_queue_max_hw_segments(vblk->disk->queue, v);
+-	else if (err != -ENOENT) {
+-		dev_err(&vdev->dev, "Bad SEG_MAX in config\n");
+-		goto out_cleanup_queue;
+-	}
+ 
+ 	add_disk(vblk->disk);
+ 	return 0;
+ 
+-out_cleanup_queue:
+-	blk_cleanup_queue(vblk->disk->queue);
+ out_put_disk:
+ 	put_disk(vblk->disk);
+-out_unregister_blkdev:
+-	unregister_blkdev(major, "virtblk");
+ out_mempool:
+ 	mempool_destroy(vblk->pool);
+ out_free_vq:
+@@ -274,12 +290,16 @@ static void virtblk_remove(struct virtio_device *vdev)
+ 	struct virtio_blk *vblk = vdev->priv;
+ 	int major = vblk->disk->major;
+ 
++	/* Nothing should be pending. */
+ 	BUG_ON(!list_empty(&vblk->reqs));
++
++	/* Stop all the virtqueues. */
++	vdev->config->reset(vdev);
++
+ 	blk_cleanup_queue(vblk->disk->queue);
+ 	put_disk(vblk->disk);
+ 	unregister_blkdev(major, "virtblk");
+ 	mempool_destroy(vblk->pool);
+-	/* There should be nothing in the queue now, so no need to shutdown */
+ 	vdev->config->del_vq(vblk->vq);
+ 	kfree(vblk);
  }
-@@ -1549,7 +1641,7 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
- /**
-  *	ata_eh_speed_down - record error and speed down if necessary
-  *	@dev: Failed device
-- *	@is_io: Did the device fail during normal IO?
-+ *	@eflags: mask of ATA_EFLAG_* flags
-  *	@err_mask: err_mask of the error
-  *
-  *	Record error and examine error history to determine whether
-@@ -1563,18 +1655,20 @@ static unsigned int ata_eh_speed_down_verdict(struct ata_device *dev)
-  *	RETURNS:
-  *	Determined recovery action.
-  */
--static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
--				      unsigned int err_mask)
-+static unsigned int ata_eh_speed_down(struct ata_device *dev,
-+				unsigned int eflags, unsigned int err_mask)
+@@ -299,11 +319,15 @@ static struct virtio_driver virtio_blk = {
+ 
+ static int __init init(void)
  {
-+	struct ata_link *link = dev->link;
-+	int xfer_ok = 0;
- 	unsigned int verdict;
- 	unsigned int action = 0;
++	major = register_blkdev(0, "virtblk");
++	if (major < 0)
++		return major;
+ 	return register_virtio_driver(&virtio_blk);
+ }
  
- 	/* don't bother if Cat-0 error */
--	if (ata_eh_categorize_error(is_io, err_mask) == 0)
-+	if (ata_eh_categorize_error(eflags, err_mask, &xfer_ok) == 0)
- 		return 0;
+ static void __exit fini(void)
+ {
++	unregister_blkdev(major, "virtblk");
+ 	unregister_virtio_driver(&virtio_blk);
+ }
+ module_init(init);
+diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
+index 2bdebcb..8afce67 100644
+--- a/drivers/block/xen-blkfront.c
++++ b/drivers/block/xen-blkfront.c
+@@ -452,7 +452,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+ 	RING_IDX i, rp;
+ 	unsigned long flags;
+ 	struct blkfront_info *info = (struct blkfront_info *)dev_id;
+-	int uptodate;
++	int error;
  
- 	/* record error and determine whether speed down is necessary */
--	ata_ering_record(&dev->ering, is_io, err_mask);
-+	ata_ering_record(&dev->ering, eflags, err_mask);
- 	verdict = ata_eh_speed_down_verdict(dev);
+ 	spin_lock_irqsave(&blkif_io_lock, flags);
  
- 	/* turn off NCQ? */
-@@ -1590,7 +1684,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
- 	/* speed down? */
- 	if (verdict & ATA_EH_SPDN_SPEED_DOWN) {
- 		/* speed down SATA link speed if possible */
--		if (sata_down_spd_limit(dev->link) == 0) {
-+		if (sata_down_spd_limit(link) == 0) {
- 			action |= ATA_EH_HARDRESET;
- 			goto done;
+@@ -477,13 +477,13 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+ 
+ 		add_id_to_freelist(info, id);
+ 
+-		uptodate = (bret->status == BLKIF_RSP_OKAY);
++		error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
+ 		switch (bret->operation) {
+ 		case BLKIF_OP_WRITE_BARRIER:
+ 			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
+ 				printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
+ 				       info->gd->disk_name);
+-				uptodate = -EOPNOTSUPP;
++				error = -EOPNOTSUPP;
+ 				info->feature_barrier = 0;
+ 				xlvbd_barrier(info);
+ 			}
+@@ -494,10 +494,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
+ 				dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
+ 					"request: %x\n", bret->status);
+ 
+-			ret = end_that_request_first(req, uptodate,
+-				req->hard_nr_sectors);
++			ret = __blk_end_request(req, error, blk_rq_bytes(req));
+ 			BUG_ON(ret);
+-			end_that_request_last(req, uptodate);
+ 			break;
+ 		default:
+ 			BUG();
+diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
+index 82effce..78ebfff 100644
+--- a/drivers/block/xsysace.c
++++ b/drivers/block/xsysace.c
+@@ -483,7 +483,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
+ 	u32 status;
+ 	u16 val;
+ 	int count;
+-	int i;
+ 
+ #if defined(DEBUG)
+ 	dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
+@@ -688,7 +687,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
  		}
-@@ -1618,10 +1712,10 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
- 	}
  
- 	/* Fall back to PIO?  Slowing down to PIO is meaningless for
--	 * SATA.  Consider it only for PATA.
-+	 * SATA ATA devices.  Consider it only for PATA and SATAPI.
- 	 */
- 	if ((verdict & ATA_EH_SPDN_FALLBACK_TO_PIO) && (dev->spdn_cnt >= 2) &&
--	    (dev->link->ap->cbl != ATA_CBL_SATA) &&
-+	    (link->ap->cbl != ATA_CBL_SATA || dev->class == ATA_DEV_ATAPI) &&
- 	    (dev->xfer_shift != ATA_SHIFT_PIO)) {
- 		if (ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO) == 0) {
- 			dev->spdn_cnt = 0;
-@@ -1633,7 +1727,8 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, int is_io,
- 	return 0;
-  done:
- 	/* device has been slowed down, blow error history */
--	ata_ering_clear(&dev->ering);
-+	if (!(verdict & ATA_EH_SPDN_KEEP_ERRORS))
-+		ata_ering_clear(&dev->ering);
- 	return action;
- }
+ 		/* Transfer the next buffer */
+-		i = 16;
+ 		if (ace->fsm_task == ACE_TASK_WRITE)
+ 			ace->reg_ops->dataout(ace);
+ 		else
+@@ -702,8 +700,8 @@ static void ace_fsm_dostate(struct ace_device *ace)
+ 		}
  
-@@ -1653,8 +1748,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
- 	struct ata_port *ap = link->ap;
- 	struct ata_eh_context *ehc = &link->eh_context;
- 	struct ata_device *dev;
--	unsigned int all_err_mask = 0;
--	int tag, is_io = 0;
-+	unsigned int all_err_mask = 0, eflags = 0;
-+	int tag;
- 	u32 serror;
- 	int rc;
+ 		/* bio finished; is there another one? */
+-		i = ace->req->current_nr_sectors;
+-		if (end_that_request_first(ace->req, 1, i)) {
++		if (__blk_end_request(ace->req, 0,
++					blk_rq_cur_bytes(ace->req))) {
+ 			/* dev_dbg(ace->dev, "next block; h=%li c=%i\n",
+ 			 *      ace->req->hard_nr_sectors,
+ 			 *      ace->req->current_nr_sectors);
+@@ -718,9 +716,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
+ 		break;
  
-@@ -1713,15 +1808,15 @@ static void ata_eh_link_autopsy(struct ata_link *link)
- 		ehc->i.dev = qc->dev;
- 		all_err_mask |= qc->err_mask;
- 		if (qc->flags & ATA_QCFLAG_IO)
--			is_io = 1;
-+			eflags |= ATA_EFLAG_IS_IO;
+ 	case ACE_FSM_STATE_REQ_COMPLETE:
+-		/* Complete the block request */
+-		blkdev_dequeue_request(ace->req);
+-		end_that_request_last(ace->req, 1);
+ 		ace->req = NULL;
+ 
+ 		/* Finished request; go to idle state */
+diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
+index 1375b53..3b28658 100644
+--- a/drivers/bluetooth/bpa10x.c
++++ b/drivers/bluetooth/bpa10x.c
+@@ -423,6 +423,7 @@ static int bpa10x_send_frame(struct sk_buff *skb)
+ 		break;
+ 
+ 	default:
++		usb_free_urb(urb);
+ 		return -EILSEQ;
  	}
  
- 	/* enforce default EH actions */
- 	if (ap->pflags & ATA_PFLAG_FROZEN ||
- 	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
- 		ehc->i.action |= ATA_EH_SOFTRESET;
--	else if ((is_io && all_err_mask) ||
--		 (!is_io && (all_err_mask & ~AC_ERR_DEV)))
-+	else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
-+		 (!(eflags & ATA_EFLAG_IS_IO) && (all_err_mask & ~AC_ERR_DEV)))
- 		ehc->i.action |= ATA_EH_REVALIDATE;
+diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c
+index a18f9b8..7703d6e 100644
+--- a/drivers/bluetooth/bt3c_cs.c
++++ b/drivers/bluetooth/bt3c_cs.c
+@@ -704,7 +704,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *
  
- 	/* If we have offending qcs and the associated failed device,
-@@ -1743,8 +1838,11 @@ static void ata_eh_link_autopsy(struct ata_link *link)
- 		      ata_dev_enabled(link->device))))
- 	    dev = link->device;
+ static int bt3c_config(struct pcmcia_device *link)
+ {
+-	static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
++	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ 	bt3c_info_t *info = link->priv;
+ 	tuple_t tuple;
+ 	u_short buf[256];
+diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
+index b786f61..58630cc 100644
+--- a/drivers/bluetooth/btsdio.c
++++ b/drivers/bluetooth/btsdio.c
+@@ -162,10 +162,8 @@ static int btsdio_rx_packet(struct btsdio_data *data)
+ 	bt_cb(skb)->pkt_type = hdr[3];
  
--	if (dev)
--		ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);
-+	if (dev) {
-+		if (dev->flags & ATA_DFLAG_DUBIOUS_XFER)
-+			eflags |= ATA_EFLAG_DUBIOUS_XFER;
-+		ehc->i.action |= ata_eh_speed_down(dev, eflags, all_err_mask);
-+	}
+ 	err = hci_recv_frame(skb);
+-	if (err < 0) {
+-		kfree(skb);
++	if (err < 0)
+ 		return err;
+-	}
  
- 	DPRINTK("EXIT\n");
- }
-@@ -1880,8 +1978,8 @@ static void ata_eh_link_report(struct ata_link *link)
- 				[ATA_PROT_PIO]		= "pio",
- 				[ATA_PROT_DMA]		= "dma",
- 				[ATA_PROT_NCQ]		= "ncq",
--				[ATA_PROT_ATAPI]	= "pio",
--				[ATA_PROT_ATAPI_DMA]	= "dma",
-+				[ATAPI_PROT_PIO]	= "pio",
-+				[ATAPI_PROT_DMA]	= "dma",
- 			};
+ 	sdio_writeb(data->func, 0x00, REG_PC_RRT, NULL);
  
- 			snprintf(data_buf, sizeof(data_buf), " %s %u %s",
-@@ -1889,7 +1987,7 @@ static void ata_eh_link_report(struct ata_link *link)
- 				 dma_str[qc->dma_dir]);
- 		}
+diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c
+index 08f48d5..68d1d25 100644
+--- a/drivers/bluetooth/btuart_cs.c
++++ b/drivers/bluetooth/btuart_cs.c
+@@ -383,7 +383,7 @@ static void btuart_change_speed(btuart_info_t *info, unsigned int speed)
+ 	outb(lcr, iobase + UART_LCR);	/* Set 8N1  */
+ 	outb(fcr, iobase + UART_FCR);	/* Enable FIFO's */
  
--		if (is_atapi_taskfile(&qc->tf))
-+		if (ata_is_atapi(qc->tf.protocol))
- 			snprintf(cdb_buf, sizeof(cdb_buf),
- 				 "cdb %02x %02x %02x %02x %02x %02x %02x %02x  "
- 				 "%02x %02x %02x %02x %02x %02x %02x %02x\n         ",
-@@ -2329,6 +2427,58 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
- 	return rc;
+-	/* Turn on interrups */
++	/* Turn on interrupts */
+ 	outb(UART_IER_RLSI | UART_IER_RDI | UART_IER_THRI, iobase + UART_IER);
+ 
+ 	spin_unlock_irqrestore(&(info->lock), flags);
+@@ -634,7 +634,7 @@ static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *
+ 
+ static int btuart_config(struct pcmcia_device *link)
+ {
+-	static kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
++	static unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ 	btuart_info_t *info = link->priv;
+ 	tuple_t tuple;
+ 	u_short buf[256];
+diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
+index 98a9cde..372c7ef 100644
+--- a/drivers/bluetooth/hci_usb.c
++++ b/drivers/bluetooth/hci_usb.c
+@@ -111,6 +111,7 @@ static struct usb_device_id blacklist_ids[] = {
+ 	{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = HCI_IGNORE },
+ 
+ 	/* Broadcom BCM2035 */
++	{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
+ 	{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = HCI_RESET | HCI_WRONG_SCO_MTU },
+ 	{ USB_DEVICE(0x0a5c, 0x2009), .driver_info = HCI_BCM92035 },
+ 
+diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
+index 774c180..ecf85fd 100644
+--- a/drivers/cdrom/Makefile
++++ b/drivers/cdrom/Makefile
+@@ -11,3 +11,4 @@ obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
+ obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
+ 
+ obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
++obj-$(CONFIG_GDROM)		+= gdrom.o      cdrom.o
+diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
+index af05610..47e5b40 100644
+--- a/drivers/cdrom/cdrom.c
++++ b/drivers/cdrom/cdrom.c
+@@ -2787,12 +2787,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
+ 	return -ENOSYS;
  }
  
-+/**
-+ *	ata_set_mode - Program timings and issue SET FEATURES - XFER
-+ *	@link: link on which timings will be programmed
-+ *	@r_failed_dev: out paramter for failed device
+-static inline
+-int msf_to_lba(char m, char s, char f)
+-{
+-	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
+-}
+-
+ /*
+  * Required when we need to use READ_10 to issue other than 2048 block
+  * reads
+diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
+new file mode 100644
+index 0000000..4e2bbcc
+--- /dev/null
++++ b/drivers/cdrom/gdrom.c
+@@ -0,0 +1,867 @@
++/* GD ROM driver for the SEGA Dreamcast
++ * copyright Adrian McMenamin, 2007
++ * With thanks to Marcus Comstedt and Nathan Keynes
++ * for work in reversing PIO and DMA
 + *
-+ *	Set ATA device disk transfer mode (PIO3, UDMA6, etc.).  If
-+ *	ata_set_mode() fails, pointer to the failing device is
-+ *	returned in @r_failed_dev.
++ * 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.
 + *
-+ *	LOCKING:
-+ *	PCI/etc. bus probe sem.
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along
++ * with this program; if not, write to the Free Software Foundation, Inc.,
++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + *
-+ *	RETURNS:
-+ *	0 on success, negative errno otherwise
 + */
-+int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev)
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/slab.h>
++#include <linux/dma-mapping.h>
++#include <linux/cdrom.h>
++#include <linux/genhd.h>
++#include <linux/bio.h>
++#include <linux/blkdev.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++#include <linux/wait.h>
++#include <linux/workqueue.h>
++#include <linux/platform_device.h>
++#include <scsi/scsi.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/delay.h>
++#include <asm/mach/dma.h>
++#include <asm/mach/sysasic.h>
++
++#define GDROM_DEV_NAME "gdrom"
++#define GD_SESSION_OFFSET 150
++
++/* GD Rom commands */
++#define GDROM_COM_SOFTRESET 0x08
++#define GDROM_COM_EXECDIAG 0x90
++#define GDROM_COM_PACKET 0xA0
++#define GDROM_COM_IDDEV 0xA1
++
++/* GD Rom registers */
++#define GDROM_BASE_REG			0xA05F7000
++#define GDROM_ALTSTATUS_REG		(GDROM_BASE_REG + 0x18)
++#define GDROM_DATA_REG			(GDROM_BASE_REG + 0x80)
++#define GDROM_ERROR_REG		(GDROM_BASE_REG + 0x84)
++#define GDROM_INTSEC_REG		(GDROM_BASE_REG + 0x88)
++#define GDROM_SECNUM_REG		(GDROM_BASE_REG + 0x8C)
++#define GDROM_BCL_REG			(GDROM_BASE_REG + 0x90)
++#define GDROM_BCH_REG			(GDROM_BASE_REG + 0x94)
++#define GDROM_DSEL_REG			(GDROM_BASE_REG + 0x98)
++#define GDROM_STATUSCOMMAND_REG	(GDROM_BASE_REG + 0x9C)
++#define GDROM_RESET_REG		(GDROM_BASE_REG + 0x4E4)
++
++#define GDROM_DMA_STARTADDR_REG	(GDROM_BASE_REG + 0x404)
++#define GDROM_DMA_LENGTH_REG		(GDROM_BASE_REG + 0x408)
++#define GDROM_DMA_DIRECTION_REG	(GDROM_BASE_REG + 0x40C)
++#define GDROM_DMA_ENABLE_REG		(GDROM_BASE_REG + 0x414)
++#define GDROM_DMA_STATUS_REG		(GDROM_BASE_REG + 0x418)
++#define GDROM_DMA_WAIT_REG		(GDROM_BASE_REG + 0x4A0)
++#define GDROM_DMA_ACCESS_CTRL_REG	(GDROM_BASE_REG + 0x4B8)
++
++#define GDROM_HARD_SECTOR	2048
++#define BLOCK_LAYER_SECTOR	512
++#define GD_TO_BLK		4
++
++#define GDROM_DEFAULT_TIMEOUT	(HZ * 7)
++
++static const struct {
++	int sense_key;
++	const char * const text;
++} sense_texts[] = {
++	{NO_SENSE, "OK"},
++	{RECOVERED_ERROR, "Recovered from error"},
++	{NOT_READY, "Device not ready"},
++	{MEDIUM_ERROR, "Disk not ready"},
++	{HARDWARE_ERROR, "Hardware error"},
++	{ILLEGAL_REQUEST, "Command has failed"},
++	{UNIT_ATTENTION, "Device needs attention - disk may have been changed"},
++	{DATA_PROTECT, "Data protection error"},
++	{ABORTED_COMMAND, "Command aborted"},
++};
++
++static struct platform_device *pd;
++static int gdrom_major;
++static DECLARE_WAIT_QUEUE_HEAD(command_queue);
++static DECLARE_WAIT_QUEUE_HEAD(request_queue);
++
++static DEFINE_SPINLOCK(gdrom_lock);
++static void gdrom_readdisk_dma(struct work_struct *work);
++static DECLARE_WORK(work, gdrom_readdisk_dma);
++static LIST_HEAD(gdrom_deferred);
++
++struct gdromtoc {
++	unsigned int entry[99];
++	unsigned int first, last;
++	unsigned int leadout;
++};
++
++static struct gdrom_unit {
++	struct gendisk *disk;
++	struct cdrom_device_info *cd_info;
++	int status;
++	int pending;
++	int transfer;
++	char disk_type;
++	struct gdromtoc *toc;
++	struct request_queue *gdrom_rq;
++} gd;
++
++struct gdrom_id {
++	char mid;
++	char modid;
++	char verid;
++	char padA[13];
++	char mname[16];
++	char modname[16];
++	char firmver[16];
++	char padB[16];
++};
++
++static int gdrom_getsense(short *bufstring);
++static int gdrom_packetcommand(struct cdrom_device_info *cd_info,
++	struct packet_command *command);
++static int gdrom_hardreset(struct cdrom_device_info *cd_info);
++
++static bool gdrom_is_busy(void)
 +{
-+	struct ata_port *ap = link->ap;
-+	struct ata_device *dev;
-+	int rc;
++	return (ctrl_inb(GDROM_ALTSTATUS_REG) & 0x80) != 0;
++}
 +
-+	/* if data transfer is verified, clear DUBIOUS_XFER on ering top */
-+	ata_link_for_each_dev(dev, link) {
-+		if (!(dev->flags & ATA_DFLAG_DUBIOUS_XFER)) {
-+			struct ata_ering_entry *ent;
++static bool gdrom_data_request(void)
++{
++	return (ctrl_inb(GDROM_ALTSTATUS_REG) & 0x88) == 8;
++}
 +
-+			ent = ata_ering_top(&dev->ering);
-+			if (ent)
-+				ent->eflags &= ~ATA_EFLAG_DUBIOUS_XFER;
++static bool gdrom_wait_clrbusy(void)
++{
++	unsigned long timeout = jiffies + GDROM_DEFAULT_TIMEOUT;
++	while ((ctrl_inb(GDROM_ALTSTATUS_REG) & 0x80) &&
++		(time_before(jiffies, timeout)))
++		cpu_relax();
++	return time_before(jiffies, timeout + 1);
++}
++
++static bool gdrom_wait_busy_sleeps(void)
++{
++	unsigned long timeout;
++	/* Wait to get busy first */
++	timeout = jiffies + GDROM_DEFAULT_TIMEOUT;
++	while (!gdrom_is_busy() && time_before(jiffies, timeout))
++		cpu_relax();
++	/* Now wait for busy to clear */
++	return gdrom_wait_clrbusy();
++}
++
++static void gdrom_identifydevice(void *buf)
++{
++	int c;
++	short *data = buf;
++	/* If the device won't clear it has probably
++	* been hit by a serious failure - but we'll
++	* try to return a sense key even so */
++	if (!gdrom_wait_clrbusy()) {
++		gdrom_getsense(NULL);
++		return;
++	}
++	ctrl_outb(GDROM_COM_IDDEV, GDROM_STATUSCOMMAND_REG);
++	if (!gdrom_wait_busy_sleeps()) {
++		gdrom_getsense(NULL);
++		return;
++	}
++	/* now read in the data */
++	for (c = 0; c < 40; c++)
++		data[c] = ctrl_inw(GDROM_DATA_REG);
++}
++
++static void gdrom_spicommand(void *spi_string, int buflen)
++{
++	short *cmd = spi_string;
++	unsigned long timeout;
++
++	/* ensure IRQ_WAIT is set */
++	ctrl_outb(0x08, GDROM_ALTSTATUS_REG);
++	/* specify how many bytes we expect back */
++	ctrl_outb(buflen & 0xFF, GDROM_BCL_REG);
++	ctrl_outb((buflen >> 8) & 0xFF, GDROM_BCH_REG);
++	/* other parameters */
++	ctrl_outb(0, GDROM_INTSEC_REG);
++	ctrl_outb(0, GDROM_SECNUM_REG);
++	ctrl_outb(0, GDROM_ERROR_REG);
++	/* Wait until we can go */
++	if (!gdrom_wait_clrbusy()) {
++		gdrom_getsense(NULL);
++		return;
++	}
++	timeout = jiffies + GDROM_DEFAULT_TIMEOUT;
++	ctrl_outb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG);
++	while (!gdrom_data_request() && time_before(jiffies, timeout))
++		cpu_relax();
++	if (!time_before(jiffies, timeout + 1)) {
++		gdrom_getsense(NULL);
++		return;
++	}
++	outsw(PHYSADDR(GDROM_DATA_REG), cmd, 6);
++}
++
++
++/* gdrom_command_executediagnostic:
++ * Used to probe for presence of working GDROM
++ * Restarts GDROM device and then applies standard ATA 3
++ * Execute Diagnostic Command: a return of '1' indicates device 0
++ * present and device 1 absent
++ */
++static char gdrom_execute_diagnostic(void)
++{
++	gdrom_hardreset(gd.cd_info);
++	if (!gdrom_wait_clrbusy())
++		return 0;
++	ctrl_outb(GDROM_COM_EXECDIAG, GDROM_STATUSCOMMAND_REG);
++	if (!gdrom_wait_busy_sleeps())
++		return 0;
++	return ctrl_inb(GDROM_ERROR_REG);
++}
++
++/*
++ * Prepare disk command
++ * byte 0 = 0x70
++ * byte 1 = 0x1f
++ */
++static int gdrom_preparedisk_cmd(void)
++{
++	struct packet_command *spin_command;
++	spin_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
++	if (!spin_command)
++		return -ENOMEM;
++	spin_command->cmd[0] = 0x70;
++	spin_command->cmd[2] = 0x1f;
++	spin_command->buflen = 0;
++	gd.pending = 1;
++	gdrom_packetcommand(gd.cd_info, spin_command);
++	/* 60 second timeout */
++	wait_event_interruptible_timeout(command_queue, gd.pending == 0,
++		GDROM_DEFAULT_TIMEOUT);
++	gd.pending = 0;
++	kfree(spin_command);
++	if (gd.status & 0x01) {
++		/* log an error */
++		gdrom_getsense(NULL);
++		return -EIO;
++	}
++	return 0;
++}
++
++/*
++ * Read TOC command
++ * byte 0 = 0x14
++ * byte 1 = session
++ * byte 3 = sizeof TOC >> 8  ie upper byte
++ * byte 4 = sizeof TOC & 0xff ie lower byte
++ */
++static int gdrom_readtoc_cmd(struct gdromtoc *toc, int session)
++{
++	int tocsize;
++	struct packet_command *toc_command;
++	int err = 0;
++
++	toc_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
++	if (!toc_command)
++		return -ENOMEM;
++	tocsize = sizeof(struct gdromtoc);
++	toc_command->cmd[0] = 0x14;
++	toc_command->cmd[1] = session;
++	toc_command->cmd[3] = tocsize >> 8;
++	toc_command->cmd[4] = tocsize & 0xff;
++	toc_command->buflen = tocsize;
++	if (gd.pending) {
++		err = -EBUSY;
++		goto cleanup_readtoc_final;
++	}
++	gd.pending = 1;
++	gdrom_packetcommand(gd.cd_info, toc_command);
++	wait_event_interruptible_timeout(command_queue, gd.pending == 0,
++		GDROM_DEFAULT_TIMEOUT);
++	if (gd.pending) {
++		err = -EINVAL;
++		goto cleanup_readtoc;
++	}
++	insw(PHYSADDR(GDROM_DATA_REG), toc, tocsize/2);
++	if (gd.status & 0x01)
++		err = -EINVAL;
++
++cleanup_readtoc:
++	gd.pending = 0;
++cleanup_readtoc_final:
++	kfree(toc_command);
++	return err;
++}
++
++/* TOC helpers */
++static int get_entry_lba(int track)
++{
++	return (cpu_to_be32(track & 0xffffff00) - GD_SESSION_OFFSET);
++}
++
++static int get_entry_q_ctrl(int track)
++{
++	return (track & 0x000000f0) >> 4;
++}
++
++static int get_entry_track(int track)
++{
++	return (track & 0x0000ff00) >> 8;
++}
++
++static int gdrom_get_last_session(struct cdrom_device_info *cd_info,
++	struct cdrom_multisession *ms_info)
++{
++	int fentry, lentry, track, data, tocuse, err;
++	if (!gd.toc)
++		return -ENOMEM;
++	tocuse = 1;
++	/* Check if GD-ROM */
++	err = gdrom_readtoc_cmd(gd.toc, 1);
++	/* Not a GD-ROM so check if standard CD-ROM */
++	if (err) {
++		tocuse = 0;
++		err = gdrom_readtoc_cmd(gd.toc, 0);
++		if (err) {
++			printk(KERN_INFO "GDROM: Could not get CD "
++				"table of contents\n");
++			return -ENXIO;
 +		}
 +	}
 +
-+	/* has private set_mode? */
-+	if (ap->ops->set_mode)
-+		rc = ap->ops->set_mode(link, r_failed_dev);
++	fentry = get_entry_track(gd.toc->first);
++	lentry = get_entry_track(gd.toc->last);
++	/* Find the first data track */
++	track = get_entry_track(gd.toc->last);
++	do {
++		data = gd.toc->entry[track - 1];
++		if (get_entry_q_ctrl(data))
++			break;	/* ie a real data track */
++		track--;
++	} while (track >= fentry);
++
++	if ((track > 100) || (track < get_entry_track(gd.toc->first))) {
++		printk(KERN_INFO "GDROM: No data on the last "
++			"session of the CD\n");
++		gdrom_getsense(NULL);
++		return -ENXIO;
++	}
++
++	ms_info->addr_format = CDROM_LBA;
++	ms_info->addr.lba = get_entry_lba(data);
++	ms_info->xa_flag = 1;
++	return 0;
++}
++
++static int gdrom_open(struct cdrom_device_info *cd_info, int purpose)
++{
++	/* spin up the disk */
++	return gdrom_preparedisk_cmd();
++}
++
++/* this function is required even if empty */
++static void gdrom_release(struct cdrom_device_info *cd_info)
++{
++}
++
++static int gdrom_drivestatus(struct cdrom_device_info *cd_info, int ignore)
++{
++	/* read the sense key */
++	char sense = ctrl_inb(GDROM_ERROR_REG);
++	sense &= 0xF0;
++	if (sense == 0)
++		return CDS_DISC_OK;
++	if (sense == 0x20)
++		return CDS_DRIVE_NOT_READY;
++	/* default */
++	return CDS_NO_INFO;
++}
++
++static int gdrom_mediachanged(struct cdrom_device_info *cd_info, int ignore)
++{
++	/* check the sense key */
++	return (ctrl_inb(GDROM_ERROR_REG) & 0xF0) == 0x60;
++}
++
++/* reset the G1 bus */
++static int gdrom_hardreset(struct cdrom_device_info *cd_info)
++{
++	int count;
++	ctrl_outl(0x1fffff, GDROM_RESET_REG);
++	for (count = 0xa0000000; count < 0xa0200000; count += 4)
++		ctrl_inl(count);
++	return 0;
++}
++
++/* keep the function looking like the universal
++ * CD Rom specification  - returning int */
++static int gdrom_packetcommand(struct cdrom_device_info *cd_info,
++	struct packet_command *command)
++{
++	gdrom_spicommand(&command->cmd, command->buflen);
++	return 0;
++}
++
++/* Get Sense SPI command
++ * From Marcus Comstedt
++ * cmd = 0x13
++ * cmd + 4 = length of returned buffer
++ * Returns 5 16 bit words
++ */
++static int gdrom_getsense(short *bufstring)
++{
++	struct packet_command *sense_command;
++	short sense[5];
++	int sense_key;
++	int err = -EIO;
++
++	sense_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
++	if (!sense_command)
++		return -ENOMEM;
++	sense_command->cmd[0] = 0x13;
++	sense_command->cmd[4] = 10;
++	sense_command->buflen = 10;
++	/* even if something is pending try to get
++	* the sense key if possible */
++	if (gd.pending && !gdrom_wait_clrbusy()) {
++		err = -EBUSY;
++		goto cleanup_sense_final;
++	}
++	gd.pending = 1;
++	gdrom_packetcommand(gd.cd_info, sense_command);
++	wait_event_interruptible_timeout(command_queue, gd.pending == 0,
++		GDROM_DEFAULT_TIMEOUT);
++	if (gd.pending)
++		goto cleanup_sense;
++	insw(PHYSADDR(GDROM_DATA_REG), &sense, sense_command->buflen/2);
++	if (sense[1] & 40) {
++		printk(KERN_INFO "GDROM: Drive not ready - command aborted\n");
++		goto cleanup_sense;
++	}
++	sense_key = sense[1] & 0x0F;
++	if (sense_key < ARRAY_SIZE(sense_texts))
++		printk(KERN_INFO "GDROM: %s\n", sense_texts[sense_key].text);
 +	else
-+		rc = ata_do_set_mode(link, r_failed_dev);
++		printk(KERN_ERR "GDROM: Unknown sense key: %d\n", sense_key);
++	if (bufstring) /* return addional sense data */
++		memcpy(bufstring, &sense[4], 2);
++	if (sense_key < 2)
++		err = 0;
 +
-+	/* if transfer mode has changed, set DUBIOUS_XFER on device */
-+	ata_link_for_each_dev(dev, link) {
-+		struct ata_eh_context *ehc = &link->eh_context;
-+		u8 saved_xfer_mode = ehc->saved_xfer_mode[dev->devno];
-+		u8 saved_ncq = !!(ehc->saved_ncq_enabled & (1 << dev->devno));
++cleanup_sense:
++	gd.pending = 0;
++cleanup_sense_final:
++	kfree(sense_command);
++	return err;
++}
 +
-+		if (dev->xfer_mode != saved_xfer_mode ||
-+		    ata_ncq_enabled(dev) != saved_ncq)
-+			dev->flags |= ATA_DFLAG_DUBIOUS_XFER;
++static struct cdrom_device_ops gdrom_ops = {
++	.open			= gdrom_open,
++	.release		= gdrom_release,
++	.drive_status		= gdrom_drivestatus,
++	.media_changed		= gdrom_mediachanged,
++	.get_last_session	= gdrom_get_last_session,
++	.reset			= gdrom_hardreset,
++	.capability		= CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
++				  CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R,
++	.n_minors		= 1,
++};
++
++static int gdrom_bdops_open(struct inode *inode, struct file *file)
++{
++	return cdrom_open(gd.cd_info, inode, file);
++}
++
++static int gdrom_bdops_release(struct inode *inode, struct file *file)
++{
++	return cdrom_release(gd.cd_info, file);
++}
++
++static int gdrom_bdops_mediachanged(struct gendisk *disk)
++{
++	return cdrom_media_changed(gd.cd_info);
++}
++
++static int gdrom_bdops_ioctl(struct inode *inode, struct file *file,
++	unsigned cmd, unsigned long arg)
++{
++	return cdrom_ioctl(file, gd.cd_info, inode, cmd, arg);
++}
++
++static struct block_device_operations gdrom_bdops = {
++	.owner			= THIS_MODULE,
++	.open			= gdrom_bdops_open,
++	.release		= gdrom_bdops_release,
++	.media_changed		= gdrom_bdops_mediachanged,
++	.ioctl			= gdrom_bdops_ioctl,
++};
++
++static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id)
++{
++	gd.status = ctrl_inb(GDROM_STATUSCOMMAND_REG);
++	if (gd.pending != 1)
++		return IRQ_HANDLED;
++	gd.pending = 0;
++	wake_up_interruptible(&command_queue);
++	return IRQ_HANDLED;
++}
++
++static irqreturn_t gdrom_dma_interrupt(int irq, void *dev_id)
++{
++	gd.status = ctrl_inb(GDROM_STATUSCOMMAND_REG);
++	if (gd.transfer != 1)
++		return IRQ_HANDLED;
++	gd.transfer = 0;
++	wake_up_interruptible(&request_queue);
++	return IRQ_HANDLED;
++}
++
++static int __devinit gdrom_set_interrupt_handlers(void)
++{
++	int err;
++
++	err = request_irq(HW_EVENT_GDROM_CMD, gdrom_command_interrupt,
++		IRQF_DISABLED, "gdrom_command", &gd);
++	if (err)
++		return err;
++	err = request_irq(HW_EVENT_GDROM_DMA, gdrom_dma_interrupt,
++		IRQF_DISABLED, "gdrom_dma", &gd);
++	if (err)
++		free_irq(HW_EVENT_GDROM_CMD, &gd);
++	return err;
++}
++
++/* Implement DMA read using SPI command
++ * 0 -> 0x30
++ * 1 -> mode
++ * 2 -> block >> 16
++ * 3 -> block >> 8
++ * 4 -> block
++ * 8 -> sectors >> 16
++ * 9 -> sectors >> 8
++ * 10 -> sectors
++ */
++static void gdrom_readdisk_dma(struct work_struct *work)
++{
++	int err, block, block_cnt;
++	struct packet_command *read_command;
++	struct list_head *elem, *next;
++	struct request *req;
++	unsigned long timeout;
++
++	if (list_empty(&gdrom_deferred))
++		return;
++	read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
++	if (!read_command)
++		return; /* get more memory later? */
++	read_command->cmd[0] = 0x30;
++	read_command->cmd[1] = 0x20;
++	spin_lock(&gdrom_lock);
++	list_for_each_safe(elem, next, &gdrom_deferred) {
++		req = list_entry(elem, struct request, queuelist);
++		spin_unlock(&gdrom_lock);
++		block = req->sector/GD_TO_BLK + GD_SESSION_OFFSET;
++		block_cnt = req->nr_sectors/GD_TO_BLK;
++		ctrl_outl(PHYSADDR(req->buffer), GDROM_DMA_STARTADDR_REG);
++		ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
++		ctrl_outl(1, GDROM_DMA_DIRECTION_REG);
++		ctrl_outl(1, GDROM_DMA_ENABLE_REG);
++		read_command->cmd[2] = (block >> 16) & 0xFF;
++		read_command->cmd[3] = (block >> 8) & 0xFF;
++		read_command->cmd[4] = block & 0xFF;
++		read_command->cmd[8] = (block_cnt >> 16) & 0xFF;
++		read_command->cmd[9] = (block_cnt >> 8) & 0xFF;
++		read_command->cmd[10] = block_cnt & 0xFF;
++		/* set for DMA */
++		ctrl_outb(1, GDROM_ERROR_REG);
++		/* other registers */
++		ctrl_outb(0, GDROM_SECNUM_REG);
++		ctrl_outb(0, GDROM_BCL_REG);
++		ctrl_outb(0, GDROM_BCH_REG);
++		ctrl_outb(0, GDROM_DSEL_REG);
++		ctrl_outb(0, GDROM_INTSEC_REG);
++		/* Wait for registers to reset after any previous activity */
++		timeout = jiffies + HZ / 2;
++		while (gdrom_is_busy() && time_before(jiffies, timeout))
++			cpu_relax();
++		ctrl_outb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG);
++		timeout = jiffies + HZ / 2;
++		/* Wait for packet command to finish */
++		while (gdrom_is_busy() && time_before(jiffies, timeout))
++			cpu_relax();
++		gd.pending = 1;
++		gd.transfer = 1;
++		outsw(PHYSADDR(GDROM_DATA_REG), &read_command->cmd, 6);
++		timeout = jiffies + HZ / 2;
++		/* Wait for any pending DMA to finish */
++		while (ctrl_inb(GDROM_DMA_STATUS_REG) &&
++			time_before(jiffies, timeout))
++			cpu_relax();
++		/* start transfer */
++		ctrl_outb(1, GDROM_DMA_STATUS_REG);
++		wait_event_interruptible_timeout(request_queue,
++			gd.transfer == 0, GDROM_DEFAULT_TIMEOUT);
++		err = gd.transfer;
++		gd.transfer = 0;
++		gd.pending = 0;
++		/* now seek to take the request spinlock
++		* before handling ending the request */
++		spin_lock(&gdrom_lock);
++		list_del_init(&req->queuelist);
++		end_dequeued_request(req, 1 - err);
 +	}
++	spin_unlock(&gdrom_lock);
++	kfree(read_command);
++}
 +
-+	return rc;
++static void gdrom_request_handler_dma(struct request *req)
++{
++	/* dequeue, add to list of deferred work
++	* and then schedule workqueue */
++	blkdev_dequeue_request(req);
++	list_add_tail(&req->queuelist, &gdrom_deferred);
++	schedule_work(&work);
 +}
 +
- static int ata_link_nr_enabled(struct ata_link *link)
- {
- 	struct ata_device *dev;
-@@ -2375,6 +2525,24 @@ static int ata_eh_skip_recovery(struct ata_link *link)
- 	return 1;
- }
- 
-+static int ata_eh_schedule_probe(struct ata_device *dev)
++static void gdrom_request(struct request_queue *rq)
 +{
-+	struct ata_eh_context *ehc = &dev->link->eh_context;
++	struct request *req;
 +
-+	if (!(ehc->i.probe_mask & (1 << dev->devno)) ||
-+	    (ehc->did_probe_mask & (1 << dev->devno)))
-+		return 0;
++	while ((req = elv_next_request(rq)) != NULL) {
++		if (!blk_fs_request(req)) {
++			printk(KERN_DEBUG "GDROM: Non-fs request ignored\n");
++			end_request(req, 0);
++		}
++		if (rq_data_dir(req) != READ) {
++			printk(KERN_NOTICE "GDROM: Read only device -");
++			printk(" write request ignored\n");
++			end_request(req, 0);
++		}
++		if (req->nr_sectors)
++			gdrom_request_handler_dma(req);
++		else
++			end_request(req, 0);
++	}
++}
 +
-+	ata_eh_detach_dev(dev);
-+	ata_dev_init(dev);
-+	ehc->did_probe_mask |= (1 << dev->devno);
-+	ehc->i.action |= ATA_EH_SOFTRESET;
-+	ehc->saved_xfer_mode[dev->devno] = 0;
-+	ehc->saved_ncq_enabled &= ~(1 << dev->devno);
++/* Print string identifying GD ROM device */
++static int __devinit gdrom_outputversion(void)
++{
++	struct gdrom_id *id;
++	char *model_name, *manuf_name, *firmw_ver;
++	int err = -ENOMEM;
 +
-+	return 1;
++	/* query device ID */
++	id = kzalloc(sizeof(struct gdrom_id), GFP_KERNEL);
++	if (!id)
++		return err;
++	gdrom_identifydevice(id);
++	model_name = kstrndup(id->modname, 16, GFP_KERNEL);
++	if (!model_name)
++		goto free_id;
++	manuf_name = kstrndup(id->mname, 16, GFP_KERNEL);
++	if (!manuf_name)
++		goto free_model_name;
++	firmw_ver = kstrndup(id->firmver, 16, GFP_KERNEL);
++	if (!firmw_ver)
++		goto free_manuf_name;
++	printk(KERN_INFO "GDROM: %s from %s with firmware %s\n",
++		model_name, manuf_name, firmw_ver);
++	err = 0;
++	kfree(firmw_ver);
++free_manuf_name:
++	kfree(manuf_name);
++free_model_name:
++	kfree(model_name);
++free_id:
++	kfree(id);
++	return err;
 +}
 +
- static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
- {
- 	struct ata_eh_context *ehc = &dev->link->eh_context;
-@@ -2406,16 +2574,9 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
- 		if (ata_link_offline(dev->link))
- 			ata_eh_detach_dev(dev);
++/* set the default mode for DMA transfer */
++static int __devinit gdrom_init_dma_mode(void)
++{
++	ctrl_outb(0x13, GDROM_ERROR_REG);
++	ctrl_outb(0x22, GDROM_INTSEC_REG);
++	if (!gdrom_wait_clrbusy())
++		return -EBUSY;
++	ctrl_outb(0xEF, GDROM_STATUSCOMMAND_REG);
++	if (!gdrom_wait_busy_sleeps())
++		return -EBUSY;
++	/* Memory protection setting for GDROM DMA
++	* Bits 31 - 16 security: 0x8843
++	* Bits 15 and 7 reserved (0)
++	* Bits 14 - 8 start of transfer range in 1 MB blocks OR'ed with 0x80
++	* Bits 6 - 0 end of transfer range in 1 MB blocks OR'ed with 0x80
++	* (0x40 | 0x80) = start range at 0x0C000000
++	* (0x7F | 0x80) = end range at 0x0FFFFFFF */
++	ctrl_outl(0x8843407F, GDROM_DMA_ACCESS_CTRL_REG);
++	ctrl_outl(9, GDROM_DMA_WAIT_REG); /* DMA word setting */
++	return 0;
++}
++
++static void __devinit probe_gdrom_setupcd(void)
++{
++	gd.cd_info->ops = &gdrom_ops;
++	gd.cd_info->capacity = 1;
++	strcpy(gd.cd_info->name, GDROM_DEV_NAME);
++	gd.cd_info->mask = CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|
++		CDC_SELECT_DISC;
++}
++
++static void __devinit probe_gdrom_setupdisk(void)
++{
++	gd.disk->major = gdrom_major;
++	gd.disk->first_minor = 1;
++	gd.disk->minors = 1;
++	strcpy(gd.disk->disk_name, GDROM_DEV_NAME);
++}
++
++static int __devinit probe_gdrom_setupqueue(void)
++{
++	blk_queue_hardsect_size(gd.gdrom_rq, GDROM_HARD_SECTOR);
++	/* using DMA so memory will need to be contiguous */
++	blk_queue_max_hw_segments(gd.gdrom_rq, 1);
++	/* set a large max size to get most from DMA */
++	blk_queue_max_segment_size(gd.gdrom_rq, 0x40000);
++	gd.disk->queue = gd.gdrom_rq;
++	return gdrom_init_dma_mode();
++}
++
++/*
++ * register this as a block device and as compliant with the
++ * universal CD Rom driver interface
++ */
++static int __devinit probe_gdrom(struct platform_device *devptr)
++{
++	int err;
++	/* Start the device */
++	if (gdrom_execute_diagnostic() != 1) {
++		printk(KERN_WARNING "GDROM: ATA Probe for GDROM failed.\n");
++		return -ENODEV;
++	}
++	/* Print out firmware ID */
++	if (gdrom_outputversion())
++		return -ENOMEM;
++	/* Register GDROM */
++	gdrom_major = register_blkdev(0, GDROM_DEV_NAME);
++	if (gdrom_major <= 0)
++		return gdrom_major;
++	printk(KERN_INFO "GDROM: Registered with major number %d\n",
++		gdrom_major);
++	/* Specify basic properties of drive */
++	gd.cd_info = kzalloc(sizeof(struct cdrom_device_info), GFP_KERNEL);
++	if (!gd.cd_info) {
++		err = -ENOMEM;
++		goto probe_fail_no_mem;
++	}
++	probe_gdrom_setupcd();
++	gd.disk = alloc_disk(1);
++	if (!gd.disk) {
++		err = -ENODEV;
++		goto probe_fail_no_disk;
++	}
++	probe_gdrom_setupdisk();
++	if (register_cdrom(gd.cd_info)) {
++		err = -ENODEV;
++		goto probe_fail_cdrom_register;
++	}
++	gd.disk->fops = &gdrom_bdops;
++	/* latch on to the interrupt */
++	err = gdrom_set_interrupt_handlers();
++	if (err)
++		goto probe_fail_cmdirq_register;
++	gd.gdrom_rq = blk_init_queue(gdrom_request, &gdrom_lock);
++	if (!gd.gdrom_rq)
++		goto probe_fail_requestq;
++
++	err = probe_gdrom_setupqueue();
++	if (err)
++		goto probe_fail_toc;
++
++	gd.toc = kzalloc(sizeof(struct gdromtoc), GFP_KERNEL);
++	if (!gd.toc)
++		goto probe_fail_toc;
++	add_disk(gd.disk);
++	return 0;
++
++probe_fail_toc:
++	blk_cleanup_queue(gd.gdrom_rq);
++probe_fail_requestq:
++	free_irq(HW_EVENT_GDROM_DMA, &gd);
++	free_irq(HW_EVENT_GDROM_CMD, &gd);
++probe_fail_cmdirq_register:
++probe_fail_cdrom_register:
++	del_gendisk(gd.disk);
++probe_fail_no_disk:
++	kfree(gd.cd_info);
++	unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
++	gdrom_major = 0;
++probe_fail_no_mem:
++	printk(KERN_WARNING "GDROM: Probe failed - error is 0x%X\n", err);
++	return err;
++}
++
++static int __devexit remove_gdrom(struct platform_device *devptr)
++{
++	flush_scheduled_work();
++	blk_cleanup_queue(gd.gdrom_rq);
++	free_irq(HW_EVENT_GDROM_CMD, &gd);
++	free_irq(HW_EVENT_GDROM_DMA, &gd);
++	del_gendisk(gd.disk);
++	if (gdrom_major)
++		unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
++	return unregister_cdrom(gd.cd_info);
++}
++
++static struct platform_driver gdrom_driver = {
++	.probe = probe_gdrom,
++	.remove = __devexit_p(remove_gdrom),
++	.driver = {
++			.name = GDROM_DEV_NAME,
++	},
++};
++
++static int __init init_gdrom(void)
++{
++	int rc;
++	gd.toc = NULL;
++	rc = platform_driver_register(&gdrom_driver);
++	if (rc)
++		return rc;
++	pd = platform_device_register_simple(GDROM_DEV_NAME, -1, NULL, 0);
++	if (IS_ERR(pd)) {
++		platform_driver_unregister(&gdrom_driver);
++		return PTR_ERR(pd);
++	}
++	return 0;
++}
++
++static void __exit exit_gdrom(void)
++{
++	platform_device_unregister(pd);
++	platform_driver_unregister(&gdrom_driver);
++	kfree(gd.toc);
++}
++
++module_init(init_gdrom);
++module_exit(exit_gdrom);
++MODULE_AUTHOR("Adrian McMenamin <adrian at mcmen.demon.co.uk>");
++MODULE_DESCRIPTION("SEGA Dreamcast GD-ROM Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
+index d8bb44b..8473b9f 100644
+--- a/drivers/cdrom/viocd.c
++++ b/drivers/cdrom/viocd.c
+@@ -289,7 +289,7 @@ static int send_request(struct request *req)
+ 	return 0;
+ }
  
--		/* probe if requested */
--		if ((ehc->i.probe_mask & (1 << dev->devno)) &&
--		    !(ehc->did_probe_mask & (1 << dev->devno))) {
--			ata_eh_detach_dev(dev);
--			ata_dev_init(dev);
--
-+		/* schedule probe if necessary */
-+		if (ata_eh_schedule_probe(dev))
- 			ehc->tries[dev->devno] = ATA_EH_DEV_TRIES;
--			ehc->did_probe_mask |= (1 << dev->devno);
--			ehc->i.action |= ATA_EH_SOFTRESET;
--		}
+-static void viocd_end_request(struct request *req, int uptodate)
++static void viocd_end_request(struct request *req, int error)
+ {
+ 	int nsectors = req->hard_nr_sectors;
  
- 		return 1;
- 	} else {
-@@ -2492,14 +2653,9 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
- 			if (dev->flags & ATA_DFLAG_DETACH)
- 				ata_eh_detach_dev(dev);
+@@ -302,11 +302,8 @@ static void viocd_end_request(struct request *req, int uptodate)
+ 	if (!nsectors)
+ 		nsectors = 1;
  
--			if (!ata_dev_enabled(dev) &&
--			    ((ehc->i.probe_mask & (1 << dev->devno)) &&
--			     !(ehc->did_probe_mask & (1 << dev->devno)))) {
--				ata_eh_detach_dev(dev);
--				ata_dev_init(dev);
--				ehc->did_probe_mask |= (1 << dev->devno);
--				ehc->i.action |= ATA_EH_SOFTRESET;
--			}
-+			/* schedule probe if necessary */
-+			if (!ata_dev_enabled(dev))
-+				ata_eh_schedule_probe(dev);
- 		}
- 	}
+-	if (end_that_request_first(req, uptodate, nsectors))
++	if (__blk_end_request(req, error, nsectors << 9))
+ 		BUG();
+-	add_disk_randomness(req->rq_disk);
+-	blkdev_dequeue_request(req);
+-	end_that_request_last(req, uptodate);
+ }
  
-@@ -2747,6 +2903,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
- 	if (ap->ops->port_suspend)
- 		rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+ static int rwreq;
+@@ -317,11 +314,11 @@ static void do_viocd_request(struct request_queue *q)
  
-+	ata_acpi_set_state(ap, PMSG_SUSPEND);
-  out:
- 	/* report result */
- 	spin_lock_irqsave(ap->lock, flags);
-@@ -2792,6 +2949,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap)
+ 	while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) {
+ 		if (!blk_fs_request(req))
+-			viocd_end_request(req, 0);
++			viocd_end_request(req, -EIO);
+ 		else if (send_request(req) < 0) {
+ 			printk(VIOCD_KERN_WARNING
+ 					"unable to send message to OS/400!");
+-			viocd_end_request(req, 0);
++			viocd_end_request(req, -EIO);
+ 		} else
+ 			rwreq++;
+ 	}
+@@ -532,9 +529,9 @@ return_complete:
+ 					"with rc %d:0x%04X: %s\n",
+ 					req, event->xRc,
+ 					bevent->sub_result, err->msg);
+-			viocd_end_request(req, 0);
++			viocd_end_request(req, -EIO);
+ 		} else
+-			viocd_end_request(req, 1);
++			viocd_end_request(req, 0);
  
- 	WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED));
+ 		/* restart handling of incoming requests */
+ 		spin_unlock_irqrestore(&viocd_reqlock, flags);
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 2e3a0d4..4666295 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -373,6 +373,16 @@ config ISTALLION
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called istallion.
  
-+	ata_acpi_set_state(ap, PMSG_ON);
++config NOZOMI
++	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter"
++	depends on PCI && EXPERIMENTAL
++	help
++	  If you have a HSDPA driver Broadband Wireless Data Card -
++	  Globe Trotter PCMCIA card, say Y here.
 +
- 	if (ap->ops->port_resume)
- 		rc = ap->ops->port_resume(ap);
++	  To compile this driver as a module, choose M here, the module
++	  will be called nozomi.
++
+ config A2232
+ 	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index 07304d5..96fc01e 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_SERIAL167)		+= serial167.o
+ obj-$(CONFIG_CYCLADES)		+= cyclades.o
+ obj-$(CONFIG_STALLION)		+= stallion.o
+ obj-$(CONFIG_ISTALLION)		+= istallion.o
++obj-$(CONFIG_NOZOMI)		+= nozomi.o
+ obj-$(CONFIG_DIGIEPCA)		+= epca.o
+ obj-$(CONFIG_SPECIALIX)		+= specialix.o
+ obj-$(CONFIG_MOXA_INTELLIO)	+= moxa.o
+diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
+index b83824c..c69f795 100644
+--- a/drivers/char/agp/agp.h
++++ b/drivers/char/agp/agp.h
+@@ -117,7 +117,8 @@ struct agp_bridge_driver {
+ 	void (*free_by_type)(struct agp_memory *);
+ 	void *(*agp_alloc_page)(struct agp_bridge_data *);
+ 	void (*agp_destroy_page)(void *, int flags);
+-        int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
++	int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
++	void (*chipset_flush)(struct agp_bridge_data *);
+ };
+ 
+ struct agp_bridge_data {
+@@ -235,6 +236,9 @@ struct agp_bridge_data {
+ #define I965_PGETBL_SIZE_512KB	(0 << 1)
+ #define I965_PGETBL_SIZE_256KB	(1 << 1)
+ #define I965_PGETBL_SIZE_128KB	(2 << 1)
++#define I965_PGETBL_SIZE_1MB	(3 << 1)
++#define I965_PGETBL_SIZE_2MB	(4 << 1)
++#define I965_PGETBL_SIZE_1_5MB	(5 << 1)
+ #define G33_PGETBL_SIZE_MASK    (3 << 8)
+ #define G33_PGETBL_SIZE_1M      (1 << 8)
+ #define G33_PGETBL_SIZE_2M      (2 << 8)
+diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
+index aa5ddb7..1ffb381 100644
+--- a/drivers/char/agp/ali-agp.c
++++ b/drivers/char/agp/ali-agp.c
+@@ -145,7 +145,6 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
+ 	void *addr = agp_generic_alloc_page(agp_bridge);
+ 	u32 temp;
  
-diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
-index 14daf48..c02c490 100644
---- a/drivers/ata/libata-scsi.c
-+++ b/drivers/ata/libata-scsi.c
-@@ -517,7 +517,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
- 		qc->scsicmd = cmd;
- 		qc->scsidone = done;
+-	global_flush_tlb();
+ 	if (!addr)
+ 		return NULL;
  
--		qc->__sg = scsi_sglist(cmd);
-+		qc->sg = scsi_sglist(cmd);
- 		qc->n_elem = scsi_sg_count(cmd);
- 	} else {
- 		cmd->result = (DID_OK << 16) | (QUEUE_FULL << 1);
-@@ -839,7 +839,14 @@ static void ata_scsi_dev_config(struct scsi_device *sdev,
- 	if (dev->class == ATA_DEV_ATAPI) {
- 		struct request_queue *q = sdev->request_queue;
- 		blk_queue_max_hw_segments(q, q->max_hw_segments - 1);
--	}
-+
-+		/* set the min alignment */
-+		blk_queue_update_dma_alignment(sdev->request_queue,
-+					       ATA_DMA_PAD_SZ - 1);
-+	} else
-+		/* ATA devices must be sector aligned */
-+		blk_queue_update_dma_alignment(sdev->request_queue,
-+					       ATA_SECT_SIZE - 1);
+@@ -162,7 +161,6 @@ static void ali_destroy_page(void * addr, int flags)
+ 		if (flags & AGP_PAGE_DESTROY_UNMAP) {
+ 			global_cache_flush();	/* is this really needed?  --hch */
+ 			agp_generic_destroy_page(addr, flags);
+-			global_flush_tlb();
+ 		} else
+ 			agp_generic_destroy_page(addr, flags);
+ 	}
+diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
+index aa8f3a3..e77c178 100644
+--- a/drivers/char/agp/alpha-agp.c
++++ b/drivers/char/agp/alpha-agp.c
+@@ -11,29 +11,28 @@
+ 
+ #include "agp.h"
+ 
+-static struct page *alpha_core_agp_vm_nopage(struct vm_area_struct *vma,
+-					     unsigned long address,
+-					     int *type)
++static int alpha_core_agp_vm_fault(struct vm_area_struct *vma,
++					struct vm_fault *vmf)
+ {
+ 	alpha_agp_info *agp = agp_bridge->dev_private_data;
+ 	dma_addr_t dma_addr;
+ 	unsigned long pa;
+ 	struct page *page;
  
- 	if (dev->class == ATA_DEV_ATA)
- 		sdev->manage_start_stop = 1;
-@@ -878,7 +885,7 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
- 	if (dev)
- 		ata_scsi_dev_config(sdev, dev);
+-	dma_addr = address - vma->vm_start + agp->aperture.bus_base;
++	dma_addr = (unsigned long)vmf->virtual_address - vma->vm_start
++						+ agp->aperture.bus_base;
+ 	pa = agp->ops->translate(agp, dma_addr);
+ 
+ 	if (pa == (unsigned long)-EINVAL)
+-		return NULL;	/* no translation */
++		return VM_FAULT_SIGBUS;	/* no translation */
  
--	return 0;	/* scsi layer doesn't check return value, sigh */
+ 	/*
+ 	 * Get the page, inc the use count, and return it
+ 	 */
+ 	page = virt_to_page(__va(pa));
+ 	get_page(page);
+-	if (type)
+-		*type = VM_FAULT_MINOR;
+-	return page;
++	vmf->page = page;
 +	return 0;
  }
  
- /**
-@@ -2210,7 +2217,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+ static struct aper_size_info_fixed alpha_core_agp_sizes[] =
+@@ -42,7 +41,7 @@ static struct aper_size_info_fixed alpha_core_agp_sizes[] =
+ };
  
- 		/* sector size */
- 		ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8);
--		ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE);
-+		ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE & 0xff);
- 	} else {
- 		/* sector count, 64-bit */
- 		ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7));
-@@ -2224,7 +2231,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
+ struct vm_operations_struct alpha_core_agp_vm_ops = {
+-	.nopage = alpha_core_agp_vm_nopage,
++	.fault = alpha_core_agp_vm_fault,
+ };
  
- 		/* sector size */
- 		ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8);
--		ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE);
-+		ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE & 0xff);
- 	}
  
- 	return 0;
-@@ -2331,7 +2338,7 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
- 	DPRINTK("ATAPI request sense\n");
+diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
+index 1405a42..87be464 100644
+--- a/drivers/char/agp/amd-k7-agp.c
++++ b/drivers/char/agp/amd-k7-agp.c
+@@ -436,10 +436,6 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev,
+ 				return -ENODEV;
+ 			}
+ 			cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP);
+-			if (!cap_ptr) {
+-				pci_dev_put(gfxcard);
+-				continue;
+-			}
+ 		}
  
- 	/* FIXME: is this needed? */
--	memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
-+	memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+ 		/* With so many variants of NVidia cards, it's simpler just
+diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
+index 832ded2..b1bdd01 100644
+--- a/drivers/char/agp/backend.c
++++ b/drivers/char/agp/backend.c
+@@ -43,7 +43,7 @@
+  * fix some real stupidity. It's only by chance we can bump
+  * past 0.99 at all due to some boolean logic error. */
+ #define AGPGART_VERSION_MAJOR 0
+-#define AGPGART_VERSION_MINOR 102
++#define AGPGART_VERSION_MINOR 103
+ static const struct agp_version agp_current_version =
+ {
+ 	.major = AGPGART_VERSION_MAJOR,
+@@ -147,7 +147,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
+ 			printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
+ 			return -ENOMEM;
+ 		}
+-		flush_agp_mappings();
  
- 	ap->ops->tf_read(ap, &qc->tf);
+ 		bridge->scratch_page_real = virt_to_gart(addr);
+ 		bridge->scratch_page =
+@@ -191,7 +190,6 @@ err_out:
+ 	if (bridge->driver->needs_scratch_page) {
+ 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+ 						 AGP_PAGE_DESTROY_UNMAP);
+-		flush_agp_mappings();
+ 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+ 						 AGP_PAGE_DESTROY_FREE);
+ 	}
+@@ -219,7 +217,6 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
+ 	    bridge->driver->needs_scratch_page) {
+ 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+ 						 AGP_PAGE_DESTROY_UNMAP);
+-		flush_agp_mappings();
+ 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
+ 						 AGP_PAGE_DESTROY_FREE);
+ 	}
+diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c
+index ecd4248..3927579 100644
+--- a/drivers/char/agp/compat_ioctl.c
++++ b/drivers/char/agp/compat_ioctl.c
+@@ -273,6 +273,10 @@ long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ 	case AGPIOC_UNBIND32:
+ 		ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg);
+ 		break;
++
++	case AGPIOC_CHIPSET_FLUSH32:
++		ret_val = agpioc_chipset_flush_wrap(curr_priv);
++		break;
+ 	}
  
-@@ -2341,7 +2348,9 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
+ ioctl_out:
+diff --git a/drivers/char/agp/compat_ioctl.h b/drivers/char/agp/compat_ioctl.h
+index 71939d6..0c9678a 100644
+--- a/drivers/char/agp/compat_ioctl.h
++++ b/drivers/char/agp/compat_ioctl.h
+@@ -39,6 +39,7 @@
+ #define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t)
+ #define AGPIOC_BIND32       _IOW (AGPIOC_BASE, 8, compat_uptr_t)
+ #define AGPIOC_UNBIND32     _IOW (AGPIOC_BASE, 9, compat_uptr_t)
++#define AGPIOC_CHIPSET_FLUSH32 _IO (AGPIOC_BASE, 10)
  
- 	ata_qc_reinit(qc);
+ struct agp_info32 {
+ 	struct agp_version version;	/* version of the driver        */
+@@ -101,5 +102,6 @@ void agp_free_memory_wrap(struct agp_memory *memory);
+ struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type);
+ struct agp_memory *agp_find_mem_by_key(int key);
+ struct agp_client *agp_find_client_by_pid(pid_t id);
++int agpioc_chipset_flush_wrap(struct agp_file_private *priv);
  
--	ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
-+	/* setup sg table and init transfer direction */
-+	sg_init_one(&qc->sgent, cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
-+	ata_sg_init(qc, &qc->sgent, 1);
- 	qc->dma_dir = DMA_FROM_DEVICE;
+ #endif /* _AGP_COMPAT_H */
+diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
+index 7791e98..55d7a82 100644
+--- a/drivers/char/agp/frontend.c
++++ b/drivers/char/agp/frontend.c
+@@ -689,7 +689,7 @@ static int agp_open(struct inode *inode, struct file *file)
+ 	set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags);
+ 	priv->my_pid = current->pid;
  
- 	memset(&qc->cdb, 0, qc->dev->cdb_len);
-@@ -2352,10 +2361,10 @@ static void atapi_request_sense(struct ata_queued_cmd *qc)
- 	qc->tf.command = ATA_CMD_PACKET;
+-	if ((current->uid == 0) || (current->suid == 0)) {
++	if (capable(CAP_SYS_RAWIO)) {
+ 		/* Root priv, can be controller */
+ 		set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags);
+ 	}
+@@ -960,6 +960,13 @@ static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg)
+ 	return agp_unbind_memory(memory);
+ }
  
- 	if (ata_pio_use_silly(ap)) {
--		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
-+		qc->tf.protocol = ATAPI_PROT_DMA;
- 		qc->tf.feature |= ATAPI_PKT_DMA;
- 	} else {
--		qc->tf.protocol = ATA_PROT_ATAPI;
-+		qc->tf.protocol = ATAPI_PROT_PIO;
- 		qc->tf.lbam = SCSI_SENSE_BUFFERSIZE;
- 		qc->tf.lbah = 0;
++int agpioc_chipset_flush_wrap(struct agp_file_private *priv)
++{
++	DBG("");
++	agp_flush_chipset(agp_bridge);
++	return 0;
++}
++
+ static int agp_ioctl(struct inode *inode, struct file *file,
+ 		     unsigned int cmd, unsigned long arg)
+ {
+@@ -1033,6 +1040,10 @@ static int agp_ioctl(struct inode *inode, struct file *file,
+ 	case AGPIOC_UNBIND:
+ 		ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
+ 		break;
++	       
++	case AGPIOC_CHIPSET_FLUSH:
++		ret_val = agpioc_chipset_flush_wrap(curr_priv);
++		break;
  	}
-@@ -2526,12 +2535,12 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc)
- 	if (using_pio || nodata) {
- 		/* no data, or PIO data xfer */
- 		if (nodata)
--			qc->tf.protocol = ATA_PROT_ATAPI_NODATA;
-+			qc->tf.protocol = ATAPI_PROT_NODATA;
- 		else
--			qc->tf.protocol = ATA_PROT_ATAPI;
-+			qc->tf.protocol = ATAPI_PROT_PIO;
- 	} else {
- 		/* DMA data xfer */
--		qc->tf.protocol = ATA_PROT_ATAPI_DMA;
-+		qc->tf.protocol = ATAPI_PROT_DMA;
- 		qc->tf.feature |= ATAPI_PKT_DMA;
  
- 		if (atapi_dmadir && (scmd->sc_data_direction != DMA_TO_DEVICE))
-@@ -2690,6 +2699,24 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
- 	if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN)
- 		goto invalid_fld;
+ ioctl_out:
+diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
+index 64b2f6d..7484bc7 100644
+--- a/drivers/char/agp/generic.c
++++ b/drivers/char/agp/generic.c
+@@ -80,6 +80,13 @@ static int agp_get_key(void)
+ 	return -1;
+ }
  
-+	/*
-+	 * Filter TPM commands by default. These provide an
-+	 * essentially uncontrolled encrypted "back door" between
-+	 * applications and the disk. Set libata.allow_tpm=1 if you
-+	 * have a real reason for wanting to use them. This ensures
-+	 * that installed software cannot easily mess stuff up without
-+	 * user intent. DVR type users will probably ship with this enabled
-+	 * for movie content management.
-+	 *
-+	 * Note that for ATA8 we can issue a DCS change and DCS freeze lock
-+	 * for this and should do in future but that it is not sufficient as
-+	 * DCS is an optional feature set. Thus we also do the software filter
-+	 * so that we comply with the TC consortium stated goal that the user
-+	 * can turn off TC features of their system.
-+	 */
-+	if (tf->command >= 0x5C && tf->command <= 0x5F && !libata_allow_tpm)
-+		goto invalid_fld;
++void agp_flush_chipset(struct agp_bridge_data *bridge)
++{
++	if (bridge->driver->chipset_flush)
++		bridge->driver->chipset_flush(bridge);
++}
++EXPORT_SYMBOL(agp_flush_chipset);
 +
- 	/* We may not issue DMA commands if no DMA mode is set */
- 	if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
- 		goto invalid_fld;
-diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
-index b7ac80b..60cd4b1 100644
---- a/drivers/ata/libata-sff.c
-+++ b/drivers/ata/libata-sff.c
-@@ -147,7 +147,9 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
-  *	@tf: ATA taskfile register set for storing input
-  *
-  *	Reads ATA taskfile registers for currently-selected device
-- *	into @tf.
-+ *	into @tf. Assumes the device has a fully SFF compliant task file
-+ *	layout and behaviour. If you device does not (eg has a different
-+ *	status method) then you will need to provide a replacement tf_read
-  *
-  *	LOCKING:
-  *	Inherited from caller.
-@@ -156,7 +158,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+ /*
+  * Use kmalloc if possible for the page list. Otherwise fall back to
+  * vmalloc. This speeds things up and also saves memory for small AGP
+@@ -197,7 +204,6 @@ void agp_free_memory(struct agp_memory *curr)
+ 		for (i = 0; i < curr->page_count; i++) {
+ 			curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_UNMAP);
+ 		}
+-		flush_agp_mappings();
+ 		for (i = 0; i < curr->page_count; i++) {
+ 			curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_FREE);
+ 		}
+@@ -267,8 +273,6 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
+ 	}
+ 	new->bridge = bridge;
+ 
+-	flush_agp_mappings();
+-
+ 	return new;
+ }
+ EXPORT_SYMBOL(agp_allocate_memory);
+diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
+index e72a83e..76f581c 100644
+--- a/drivers/char/agp/i460-agp.c
++++ b/drivers/char/agp/i460-agp.c
+@@ -527,7 +527,6 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge)
+ 
+ 	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
+ 		page = agp_generic_alloc_page(agp_bridge);
+-		global_flush_tlb();
+ 	} else
+ 		/* Returning NULL would cause problems */
+ 		/* AK: really dubious code. */
+@@ -539,7 +538,6 @@ static void i460_destroy_page (void *page, int flags)
  {
- 	struct ata_ioports *ioaddr = &ap->ioaddr;
+ 	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
+ 		agp_generic_destroy_page(page, flags);
+-		global_flush_tlb();
+ 	}
+ }
  
--	tf->command = ata_chk_status(ap);
-+	tf->command = ata_check_status(ap);
- 	tf->feature = ioread8(ioaddr->error_addr);
- 	tf->nsect = ioread8(ioaddr->nsect_addr);
- 	tf->lbal = ioread8(ioaddr->lbal_addr);
-@@ -415,7 +417,7 @@ void ata_bmdma_drive_eh(struct ata_port *ap, ata_prereset_fn_t prereset,
- 	ap->hsm_task_state = HSM_ST_IDLE;
+diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
+index 03eac1e..eeea50a 100644
+--- a/drivers/char/agp/intel-agp.c
++++ b/drivers/char/agp/intel-agp.c
+@@ -14,8 +14,8 @@
+ #define PCI_DEVICE_ID_INTEL_E7221_IG	0x258a
+ #define PCI_DEVICE_ID_INTEL_82946GZ_HB      0x2970
+ #define PCI_DEVICE_ID_INTEL_82946GZ_IG      0x2972
+-#define PCI_DEVICE_ID_INTEL_82965G_1_HB     0x2980
+-#define PCI_DEVICE_ID_INTEL_82965G_1_IG     0x2982
++#define PCI_DEVICE_ID_INTEL_82G35_HB     0x2980
++#define PCI_DEVICE_ID_INTEL_82G35_IG     0x2982
+ #define PCI_DEVICE_ID_INTEL_82965Q_HB       0x2990
+ #define PCI_DEVICE_ID_INTEL_82965Q_IG       0x2992
+ #define PCI_DEVICE_ID_INTEL_82965G_HB       0x29A0
+@@ -32,13 +32,24 @@
+ #define PCI_DEVICE_ID_INTEL_Q35_IG          0x29B2
+ #define PCI_DEVICE_ID_INTEL_Q33_HB          0x29D0
+ #define PCI_DEVICE_ID_INTEL_Q33_IG          0x29D2
++#define PCI_DEVICE_ID_INTEL_IGD_HB          0x2A40
++#define PCI_DEVICE_ID_INTEL_IGD_IG          0x2A42
++
++/* cover 915 and 945 variants */
++#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB)
+ 
+ #define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
+-                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
+-                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
+-                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
+-                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
+-                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB)
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82G35_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \
++		 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_HB)
+ 
+ #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \
+ 		agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \
+@@ -71,9 +82,11 @@ extern int agp_memory_reserved;
+ #define I915_GMCH_GMS_STOLEN_64M	(0x7 << 4)
+ #define G33_GMCH_GMS_STOLEN_128M       (0x8 << 4)
+ #define G33_GMCH_GMS_STOLEN_256M       (0x9 << 4)
++#define I915_IFPADDR    0x60
+ 
+ /* Intel 965G registers */
+ #define I965_MSAC 0x62
++#define I965_IFPADDR    0x70
+ 
+ /* Intel 7505 registers */
+ #define INTEL_I7505_APSIZE	0x74
+@@ -115,6 +128,13 @@ static struct _intel_private {
+ 	 * popup and for the GTT.
+ 	 */
+ 	int gtt_entries;			/* i830+ */
++	union {
++		void __iomem *i9xx_flush_page;
++		void *i8xx_flush_page;
++	};
++	struct page *i8xx_page;
++	struct resource ifp_resource;
++	int resource_valid;
+ } intel_private;
+ 
+ static int intel_i810_fetch_size(void)
+@@ -204,19 +224,17 @@ static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+ /* Exists to support ARGB cursors */
+ static void *i8xx_alloc_pages(void)
+ {
+-	struct page * page;
++	struct page *page;
  
- 	if (qc && (qc->tf.protocol == ATA_PROT_DMA ||
--		   qc->tf.protocol == ATA_PROT_ATAPI_DMA)) {
-+		   qc->tf.protocol == ATAPI_PROT_DMA)) {
- 		u8 host_stat;
+ 	page = alloc_pages(GFP_KERNEL | GFP_DMA32, 2);
+ 	if (page == NULL)
+ 		return NULL;
  
- 		host_stat = ap->ops->bmdma_status(ap);
-@@ -549,7 +551,7 @@ int ata_pci_init_bmdma(struct ata_host *host)
- 		return rc;
+-	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
+-		change_page_attr(page, 4, PAGE_KERNEL);
+-		global_flush_tlb();
++	if (set_pages_uc(page, 4) < 0) {
++		set_pages_wb(page, 4);
+ 		__free_pages(page, 2);
+ 		return NULL;
+ 	}
+-	global_flush_tlb();
+ 	get_page(page);
+ 	atomic_inc(&agp_bridge->current_memory_agp);
+ 	return page_address(page);
+@@ -230,8 +248,7 @@ static void i8xx_destroy_pages(void *addr)
+ 		return;
  
- 	/* request and iomap DMA region */
--	rc = pcim_iomap_regions(pdev, 1 << 4, DRV_NAME);
-+	rc = pcim_iomap_regions(pdev, 1 << 4, dev_driver_string(gdev));
- 	if (rc) {
- 		dev_printk(KERN_ERR, gdev, "failed to request/iomap BAR4\n");
- 		return -ENOMEM;
-@@ -619,7 +621,8 @@ int ata_pci_init_sff_host(struct ata_host *host)
- 			continue;
- 		}
+ 	page = virt_to_page(addr);
+-	change_page_attr(page, 4, PAGE_KERNEL);
+-	global_flush_tlb();
++	set_pages_wb(page, 4);
+ 	put_page(page);
+ 	__free_pages(page, 2);
+ 	atomic_dec(&agp_bridge->current_memory_agp);
+@@ -341,7 +358,6 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
  
--		rc = pcim_iomap_regions(pdev, 0x3 << base, DRV_NAME);
-+		rc = pcim_iomap_regions(pdev, 0x3 << base,
-+					dev_driver_string(gdev));
- 		if (rc) {
- 			dev_printk(KERN_WARNING, gdev,
- 				   "failed to request/iomap BARs for port %d "
-@@ -711,6 +714,99 @@ int ata_pci_prepare_sff_host(struct pci_dev *pdev,
+ 	switch (pg_count) {
+ 	case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
+-		global_flush_tlb();
+ 		break;
+ 	case 4:
+ 		/* kludge to get 4 physical pages for ARGB cursor */
+@@ -404,7 +420,6 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
+ 		else {
+ 			agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
+ 							     AGP_PAGE_DESTROY_UNMAP);
+-			global_flush_tlb();
+ 			agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
+ 							     AGP_PAGE_DESTROY_FREE);
+ 		}
+@@ -438,7 +453,7 @@ static void intel_i830_init_gtt_entries(void)
+ 	static const int ddt[4] = { 0, 16, 32, 64 };
+ 	int size; /* reserved space (in kb) at the top of stolen memory */
+ 
+-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
++	pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+ 
+ 	if (IS_I965) {
+ 		u32 pgetbl_ctl;
+@@ -458,6 +473,15 @@ static void intel_i830_init_gtt_entries(void)
+ 		case I965_PGETBL_SIZE_512KB:
+ 			size = 512;
+ 			break;
++		case I965_PGETBL_SIZE_1MB:
++			size = 1024;
++			break;
++		case I965_PGETBL_SIZE_2MB:
++			size = 2048;
++			break;
++		case I965_PGETBL_SIZE_1_5MB:
++			size = 1024 + 512;
++			break;
+ 		default:
+ 			printk(KERN_INFO PFX "Unknown page table size, "
+ 			       "assuming 512KB\n");
+@@ -528,26 +552,14 @@ static void intel_i830_init_gtt_entries(void)
+ 			break;
+ 		case I915_GMCH_GMS_STOLEN_48M:
+ 			/* Check it's really I915G */
+-			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB ||
+-			    IS_I965 || IS_G33)
++			if (IS_I915 || IS_I965 || IS_G33)
+ 				gtt_entries = MB(48) - KB(size);
+ 			else
+ 				gtt_entries = 0;
+ 			break;
+ 		case I915_GMCH_GMS_STOLEN_64M:
+ 			/* Check it's really I915G */
+-			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB ||
+-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GME_HB ||
+-			    IS_I965 || IS_G33)
++			if (IS_I915 || IS_I965 || IS_G33)
+ 				gtt_entries = MB(64) - KB(size);
+ 			else
+ 				gtt_entries = 0;
+@@ -580,6 +592,45 @@ static void intel_i830_init_gtt_entries(void)
+ 	intel_private.gtt_entries = gtt_entries;
  }
  
- /**
-+ *	ata_pci_activate_sff_host - start SFF host, request IRQ and register it
-+ *	@host: target SFF ATA host
-+ *	@irq_handler: irq_handler used when requesting IRQ(s)
-+ *	@sht: scsi_host_template to use when registering the host
-+ *
-+ *	This is the counterpart of ata_host_activate() for SFF ATA
-+ *	hosts.  This separate helper is necessary because SFF hosts
-+ *	use two separate interrupts in legacy mode.
-+ *
-+ *	LOCKING:
-+ *	Inherited from calling layer (may sleep).
-+ *
-+ *	RETURNS:
-+ *	0 on success, -errno otherwise.
-+ */
-+int ata_pci_activate_sff_host(struct ata_host *host,
-+			      irq_handler_t irq_handler,
-+			      struct scsi_host_template *sht)
++static void intel_i830_fini_flush(void)
 +{
-+	struct device *dev = host->dev;
-+	struct pci_dev *pdev = to_pci_dev(dev);
-+	const char *drv_name = dev_driver_string(host->dev);
-+	int legacy_mode = 0, rc;
-+
-+	rc = ata_host_start(host);
-+	if (rc)
-+		return rc;
-+
-+	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
-+		u8 tmp8, mask;
-+
-+		/* TODO: What if one channel is in native mode ... */
-+		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
-+		mask = (1 << 2) | (1 << 0);
-+		if ((tmp8 & mask) != mask)
-+			legacy_mode = 1;
-+#if defined(CONFIG_NO_ATA_LEGACY)
-+		/* Some platforms with PCI limits cannot address compat
-+		   port space. In that case we punt if their firmware has
-+		   left a device in compatibility mode */
-+		if (legacy_mode) {
-+			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
-+			return -EOPNOTSUPP;
-+		}
-+#endif
-+	}
++	kunmap(intel_private.i8xx_page);
++	intel_private.i8xx_flush_page = NULL;
++	unmap_page_from_agp(intel_private.i8xx_page);
 +
-+	if (!devres_open_group(dev, NULL, GFP_KERNEL))
-+		return -ENOMEM;
++	__free_page(intel_private.i8xx_page);
++	intel_private.i8xx_page = NULL;
++}
 +
-+	if (!legacy_mode && pdev->irq) {
-+		rc = devm_request_irq(dev, pdev->irq, irq_handler,
-+				      IRQF_SHARED, drv_name, host);
-+		if (rc)
-+			goto out;
++static void intel_i830_setup_flush(void)
++{
++	/* return if we've already set the flush mechanism up */
++	if (intel_private.i8xx_page)
++		return;
 +
-+		ata_port_desc(host->ports[0], "irq %d", pdev->irq);
-+		ata_port_desc(host->ports[1], "irq %d", pdev->irq);
-+	} else if (legacy_mode) {
-+		if (!ata_port_is_dummy(host->ports[0])) {
-+			rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
-+					      irq_handler, IRQF_SHARED,
-+					      drv_name, host);
-+			if (rc)
-+				goto out;
++	intel_private.i8xx_page = alloc_page(GFP_KERNEL | __GFP_ZERO | GFP_DMA32);
++	if (!intel_private.i8xx_page)
++		return;
 +
-+			ata_port_desc(host->ports[0], "irq %d",
-+				      ATA_PRIMARY_IRQ(pdev));
-+		}
++	/* make page uncached */
++	map_page_into_agp(intel_private.i8xx_page);
 +
-+		if (!ata_port_is_dummy(host->ports[1])) {
-+			rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
-+					      irq_handler, IRQF_SHARED,
-+					      drv_name, host);
-+			if (rc)
-+				goto out;
++	intel_private.i8xx_flush_page = kmap(intel_private.i8xx_page);
++	if (!intel_private.i8xx_flush_page)
++		intel_i830_fini_flush();
++}
 +
-+			ata_port_desc(host->ports[1], "irq %d",
-+				      ATA_SECONDARY_IRQ(pdev));
-+		}
-+	}
++static void intel_i830_chipset_flush(struct agp_bridge_data *bridge)
++{
++	unsigned int *pg = intel_private.i8xx_flush_page;
++	int i;
 +
-+	rc = ata_host_register(host, sht);
-+ out:
-+	if (rc == 0)
-+		devres_remove_group(dev, NULL);
-+	else
-+		devres_release_group(dev, NULL);
++	for (i = 0; i < 256; i += 2)
++		*(pg + i) = i;
 +
-+	return rc;
++	wmb();
 +}
 +
-+/**
-  *	ata_pci_init_one - Initialize/register PCI IDE host controller
-  *	@pdev: Controller to be initialized
-  *	@ppi: array of port_info, must be enough for two ports
-@@ -739,8 +835,6 @@ int ata_pci_init_one(struct pci_dev *pdev,
- 	struct device *dev = &pdev->dev;
- 	const struct ata_port_info *pi = NULL;
- 	struct ata_host *host = NULL;
--	u8 mask;
--	int legacy_mode = 0;
- 	int i, rc;
- 
- 	DPRINTK("ENTER\n");
-@@ -762,95 +856,24 @@ int ata_pci_init_one(struct pci_dev *pdev,
- 	if (!devres_open_group(dev, NULL, GFP_KERNEL))
+ /* The intel i830 automatically initializes the agp aperture during POST.
+  * Use the memory already set aside for in the GTT.
+  */
+@@ -595,10 +646,10 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
+ 	num_entries = size->num_entries;
+ 	agp_bridge->gatt_table_real = NULL;
+ 
+-	pci_read_config_dword(intel_private.pcidev,I810_MMADDR,&temp);
++	pci_read_config_dword(intel_private.pcidev, I810_MMADDR, &temp);
+ 	temp &= 0xfff80000;
+ 
+-	intel_private.registers = ioremap(temp,128 * 4096);
++	intel_private.registers = ioremap(temp, 128 * 4096);
+ 	if (!intel_private.registers)
  		return -ENOMEM;
  
--	/* FIXME: Really for ATA it isn't safe because the device may be
--	   multi-purpose and we want to leave it alone if it was already
--	   enabled. Secondly for shared use as Arjan says we want refcounting
--
--	   Checking dev->is_enabled is insufficient as this is not set at
--	   boot for the primary video which is BIOS enabled
--	  */
--
- 	rc = pcim_enable_device(pdev);
- 	if (rc)
--		goto err_out;
-+		goto out;
- 
--	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
--		u8 tmp8;
--
--		/* TODO: What if one channel is in native mode ... */
--		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
--		mask = (1 << 2) | (1 << 0);
--		if ((tmp8 & mask) != mask)
--			legacy_mode = 1;
--#if defined(CONFIG_NO_ATA_LEGACY)
--		/* Some platforms with PCI limits cannot address compat
--		   port space. In that case we punt if their firmware has
--		   left a device in compatibility mode */
--		if (legacy_mode) {
--			printk(KERN_ERR "ata: Compatibility mode ATA is not supported on this platform, skipping.\n");
--			rc = -EOPNOTSUPP;
--			goto err_out;
--		}
--#endif
--	}
--
--	/* prepare host */
-+	/* prepare and activate SFF host */
- 	rc = ata_pci_prepare_sff_host(pdev, ppi, &host);
- 	if (rc)
--		goto err_out;
-+		goto out;
- 
- 	pci_set_master(pdev);
-+	rc = ata_pci_activate_sff_host(host, pi->port_ops->irq_handler,
-+				       pi->sht);
-+ out:
-+	if (rc == 0)
-+		devres_remove_group(&pdev->dev, NULL);
-+	else
-+		devres_release_group(&pdev->dev, NULL);
- 
--	/* start host and request IRQ */
--	rc = ata_host_start(host);
--	if (rc)
--		goto err_out;
--
--	if (!legacy_mode && pdev->irq) {
--		/* We may have no IRQ assigned in which case we can poll. This
--		   shouldn't happen on a sane system but robustness is cheap
--		   in this case */
--		rc = devm_request_irq(dev, pdev->irq, pi->port_ops->irq_handler,
--				      IRQF_SHARED, DRV_NAME, host);
--		if (rc)
--			goto err_out;
--
--		ata_port_desc(host->ports[0], "irq %d", pdev->irq);
--		ata_port_desc(host->ports[1], "irq %d", pdev->irq);
--	} else if (legacy_mode) {
--		if (!ata_port_is_dummy(host->ports[0])) {
--			rc = devm_request_irq(dev, ATA_PRIMARY_IRQ(pdev),
--					      pi->port_ops->irq_handler,
--					      IRQF_SHARED, DRV_NAME, host);
--			if (rc)
--				goto err_out;
--
--			ata_port_desc(host->ports[0], "irq %d",
--				      ATA_PRIMARY_IRQ(pdev));
--		}
--
--		if (!ata_port_is_dummy(host->ports[1])) {
--			rc = devm_request_irq(dev, ATA_SECONDARY_IRQ(pdev),
--					      pi->port_ops->irq_handler,
--					      IRQF_SHARED, DRV_NAME, host);
--			if (rc)
--				goto err_out;
--
--			ata_port_desc(host->ports[1], "irq %d",
--				      ATA_SECONDARY_IRQ(pdev));
--		}
--	}
--
--	/* register */
--	rc = ata_host_register(host, pi->sht);
--	if (rc)
--		goto err_out;
--
--	devres_remove_group(dev, NULL);
--	return 0;
--
--err_out:
--	devres_release_group(dev, NULL);
- 	return rc;
- }
- 
-diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
-index bbe59c2..409ffb9 100644
---- a/drivers/ata/libata.h
-+++ b/drivers/ata/libata.h
-@@ -60,6 +60,7 @@ extern int atapi_dmadir;
- extern int atapi_passthru16;
- extern int libata_fua;
- extern int libata_noacpi;
-+extern int libata_allow_tpm;
- extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
- extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
- 			   u64 block, u32 n_block, unsigned int tf_flags,
-@@ -85,7 +86,6 @@ extern int ata_dev_configure(struct ata_device *dev);
- extern int sata_down_spd_limit(struct ata_link *link);
- extern int sata_set_spd_needed(struct ata_link *link);
- extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
--extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
- extern void ata_sg_clean(struct ata_queued_cmd *qc);
- extern void ata_qc_free(struct ata_queued_cmd *qc);
- extern void ata_qc_issue(struct ata_queued_cmd *qc);
-@@ -113,6 +113,7 @@ extern int ata_acpi_on_suspend(struct ata_port *ap);
- extern void ata_acpi_on_resume(struct ata_port *ap);
- extern int ata_acpi_on_devcfg(struct ata_device *dev);
- extern void ata_acpi_on_disable(struct ata_device *dev);
-+extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
- #else
- static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
- static inline void ata_acpi_associate(struct ata_host *host) { }
-@@ -121,6 +122,8 @@ static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
- static inline void ata_acpi_on_resume(struct ata_port *ap) { }
- static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
- static inline void ata_acpi_on_disable(struct ata_device *dev) { }
-+static inline void ata_acpi_set_state(struct ata_port *ap,
-+				      pm_message_t state) { }
- #endif
+@@ -638,7 +689,7 @@ static int intel_i830_fetch_size(void)
+ 		return values[0].size;
+ 	}
  
- /* libata-scsi.c */
-@@ -183,6 +186,7 @@ extern void ata_eh_report(struct ata_port *ap);
- extern int ata_eh_reset(struct ata_link *link, int classify,
- 			ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
- 			ata_reset_fn_t hardreset, ata_postreset_fn_t postreset);
-+extern int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
- extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
- 			  ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
- 			  ata_postreset_fn_t postreset,
-diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
-index e4542ab..244098a 100644
---- a/drivers/ata/pata_acpi.c
-+++ b/drivers/ata/pata_acpi.c
-@@ -81,17 +81,6 @@ static void pacpi_error_handler(struct ata_port *ap)
- 				  NULL, ata_std_postreset);
- }
+-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
++	pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
  
--/* Welcome to ACPI, bring a bucket */
--static const unsigned int pio_cycle[7] = {
--	600, 383, 240, 180, 120, 100, 80
--};
--static const unsigned int mwdma_cycle[5] = {
--	480, 150, 120, 100, 80
--};
--static const unsigned int udma_cycle[7] = {
--	120, 80, 60, 45, 30, 20, 15
--};
--
- /**
-  *	pacpi_discover_modes	-	filter non ACPI modes
-  *	@adev: ATA device
-@@ -103,56 +92,20 @@ static const unsigned int udma_cycle[7] = {
+ 	if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
+ 		agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
+@@ -662,12 +713,12 @@ static int intel_i830_configure(void)
  
- static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
- {
--	int unit = adev->devno;
- 	struct pata_acpi *acpi = ap->private_data;
--	int i;
--	u32 t;
--	unsigned long mask = (0x7f << ATA_SHIFT_UDMA) | (0x7 << ATA_SHIFT_MWDMA) | (0x1F << ATA_SHIFT_PIO);
--
- 	struct ata_acpi_gtm probe;
-+	unsigned int xfer_mask;
+ 	current_size = A_SIZE_FIX(agp_bridge->current_size);
  
- 	probe = acpi->gtm;
+-	pci_read_config_dword(intel_private.pcidev,I810_GMADDR,&temp);
++	pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp);
+ 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
  
--	/* We always use the 0 slot for crap hardware */
--	if (!(probe.flags & 0x10))
--		unit = 0;
--
- 	ata_acpi_gtm(ap, &probe);
+-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
++	pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+ 	gmch_ctrl |= I830_GMCH_ENABLED;
+-	pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
++	pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
  
--	/* Start by scanning for PIO modes */
--	for (i = 0; i < 7; i++) {
--		t = probe.drive[unit].pio;
--		if (t <= pio_cycle[i]) {
--			mask |= (2 << (ATA_SHIFT_PIO + i)) - 1;
--			break;
--		}
--	}
-+	xfer_mask = ata_acpi_gtm_xfermask(adev, &probe);
+ 	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ 	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+@@ -680,6 +731,8 @@ static int intel_i830_configure(void)
+ 	}
  
--	/* See if we have MWDMA or UDMA data. We don't bother with MWDMA
--	   if UDMA is availabe as this means the BIOS set UDMA and our
--	   error changedown if it works is UDMA to PIO anyway */
--	if (probe.flags & (1 << (2 * unit))) {
--		/* MWDMA */
--		for (i = 0; i < 5; i++) {
--			t = probe.drive[unit].dma;
--			if (t <= mwdma_cycle[i]) {
--				mask |= (2 << (ATA_SHIFT_MWDMA + i)) - 1;
--				break;
--			}
--		}
--	} else {
--		/* UDMA */
--		for (i = 0; i < 7; i++) {
--			t = probe.drive[unit].dma;
--			if (t <= udma_cycle[i]) {
--				mask |= (2 << (ATA_SHIFT_UDMA + i)) - 1;
--				break;
--			}
--		}
--	}
--	if (mask & (0xF8 << ATA_SHIFT_UDMA))
-+	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
- 		ap->cbl = ATA_CBL_PATA80;
--	return mask;
+ 	global_cache_flush();
 +
-+	return xfer_mask;
++	intel_i830_setup_flush();
+ 	return 0;
  }
  
- /**
-@@ -180,12 +133,14 @@ static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
- {
- 	int unit = adev->devno;
- 	struct pata_acpi *acpi = ap->private_data;
-+	const struct ata_timing *t;
- 
- 	if (!(acpi->gtm.flags & 0x10))
- 		unit = 0;
+@@ -688,9 +741,10 @@ static void intel_i830_cleanup(void)
+ 	iounmap(intel_private.registers);
+ }
  
- 	/* Now stuff the nS values into the structure */
--	acpi->gtm.drive[unit].pio = pio_cycle[adev->pio_mode - XFER_PIO_0];
-+	t = ata_timing_find_mode(adev->pio_mode);
-+	acpi->gtm.drive[unit].pio = t->cycle;
- 	ata_acpi_stm(ap, &acpi->gtm);
- 	/* See what mode we actually got */
- 	ata_acpi_gtm(ap, &acpi->gtm);
-@@ -201,16 +156,18 @@ static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+-static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int type)
++static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start,
++				     int type)
  {
- 	int unit = adev->devno;
- 	struct pata_acpi *acpi = ap->private_data;
-+	const struct ata_timing *t;
- 
- 	if (!(acpi->gtm.flags & 0x10))
- 		unit = 0;
- 
- 	/* Now stuff the nS values into the structure */
-+	t = ata_timing_find_mode(adev->dma_mode);
- 	if (adev->dma_mode >= XFER_UDMA_0) {
--		acpi->gtm.drive[unit].dma = udma_cycle[adev->dma_mode - XFER_UDMA_0];
-+		acpi->gtm.drive[unit].dma = t->udma;
- 		acpi->gtm.flags |= (1 << (2 * unit));
- 	} else {
--		acpi->gtm.drive[unit].dma = mwdma_cycle[adev->dma_mode - XFER_MW_DMA_0];
-+		acpi->gtm.drive[unit].dma = t->cycle;
- 		acpi->gtm.flags &= ~(1 << (2 * unit));
- 	}
- 	ata_acpi_stm(ap, &acpi->gtm);
-diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c
-index 8caf9af..7e68edf 100644
---- a/drivers/ata/pata_ali.c
-+++ b/drivers/ata/pata_ali.c
-@@ -64,7 +64,7 @@ static int ali_cable_override(struct pci_dev *pdev)
- 	if (pdev->subsystem_vendor == 0x10CF && pdev->subsystem_device == 0x10AF)
- 	   	return 1;
- 	/* Mitac 8317 (Winbook-A) and relatives */
--	if (pdev->subsystem_vendor == 0x1071  && pdev->subsystem_device == 0x8317)
-+	if (pdev->subsystem_vendor == 0x1071 && pdev->subsystem_device == 0x8317)
- 		return 1;
- 	/* Systems by DMI */
- 	if (dmi_check_system(cable_dmi_table))
-diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
-index 3cc27b5..761a666 100644
---- a/drivers/ata/pata_amd.c
-+++ b/drivers/ata/pata_amd.c
-@@ -220,6 +220,62 @@ static void amd133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
- 	timing_setup(ap, adev, 0x40, adev->dma_mode, 4);
+-	int i,j,num_entries;
++	int i, j, num_entries;
+ 	void *temp;
+ 	int ret = -EINVAL;
+ 	int mask_type;
+@@ -702,10 +756,10 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int
+ 	num_entries = A_SIZE_FIX(temp)->num_entries;
+ 
+ 	if (pg_start < intel_private.gtt_entries) {
+-		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+-				pg_start,intel_private.gtt_entries);
++		printk(KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
++				pg_start, intel_private.gtt_entries);
+ 
+-		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
++		printk(KERN_INFO PFX "Trying to insert into local/stolen memory\n");
+ 		goto out_err;
+ 	}
+ 
+@@ -743,8 +797,8 @@ out_err:
+ 	return ret;
  }
  
-+/* Both host-side and drive-side detection results are worthless on NV
-+ * PATAs.  Ignore them and just follow what BIOS configured.  Both the
-+ * current configuration in PCI config reg and ACPI GTM result are
-+ * cached during driver attach and are consulted to select transfer
-+ * mode.
-+ */
-+static unsigned long nv_mode_filter(struct ata_device *dev,
-+				    unsigned long xfer_mask)
+-static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
+-				int type)
++static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start,
++				     int type)
+ {
+ 	int i;
+ 
+@@ -752,7 +806,7 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
+ 		return 0;
+ 
+ 	if (pg_start < intel_private.gtt_entries) {
+-		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
++		printk(KERN_INFO PFX "Trying to disable local/stolen memory\n");
+ 		return -EINVAL;
+ 	}
+ 
+@@ -765,7 +819,7 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
+ 	return 0;
+ }
+ 
+-static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
++static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count, int type)
+ {
+ 	if (type == AGP_PHYS_MEMORY)
+ 		return alloc_agpphysmem_i8xx(pg_count, type);
+@@ -773,6 +827,95 @@ static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
+ 	return NULL;
+ }
+ 
++static int intel_alloc_chipset_flush_resource(void)
 +{
-+	static const unsigned int udma_mask_map[] =
-+		{ ATA_UDMA2, ATA_UDMA1, ATA_UDMA0, 0,
-+		  ATA_UDMA3, ATA_UDMA4, ATA_UDMA5, ATA_UDMA6 };
-+	struct ata_port *ap = dev->link->ap;
-+	char acpi_str[32] = "";
-+	u32 saved_udma, udma;
-+	const struct ata_acpi_gtm *gtm;
-+	unsigned long bios_limit = 0, acpi_limit = 0, limit;
++	int ret;
++	ret = pci_bus_alloc_resource(agp_bridge->dev->bus, &intel_private.ifp_resource, PAGE_SIZE,
++				     PAGE_SIZE, PCIBIOS_MIN_MEM, 0,
++				     pcibios_align_resource, agp_bridge->dev);
 +
-+	/* find out what BIOS configured */
-+	udma = saved_udma = (unsigned long)ap->host->private_data;
++	return ret;
++}
 +
-+	if (ap->port_no == 0)
-+		udma >>= 16;
-+	if (dev->devno == 0)
-+		udma >>= 8;
++static void intel_i915_setup_chipset_flush(void)
++{
++	int ret;
++	u32 temp;
 +
-+	if ((udma & 0xc0) == 0xc0)
-+		bios_limit = ata_pack_xfermask(0, 0, udma_mask_map[udma & 0x7]);
++	pci_read_config_dword(agp_bridge->dev, I915_IFPADDR, &temp);
++	if (!(temp & 0x1)) {
++		intel_alloc_chipset_flush_resource();
++		intel_private.resource_valid = 1;
++		pci_write_config_dword(agp_bridge->dev, I915_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
++	} else {
++		temp &= ~1;
 +
-+	/* consult ACPI GTM too */
-+	gtm = ata_acpi_init_gtm(ap);
-+	if (gtm) {
-+		acpi_limit = ata_acpi_gtm_xfermask(dev, gtm);
++		intel_private.resource_valid = 1;
++		intel_private.ifp_resource.start = temp;
++		intel_private.ifp_resource.end = temp + PAGE_SIZE;
++		ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
++		/* some BIOSes reserve this area in a pnp some don't */
++		if (ret)
++			intel_private.resource_valid = 0;
++	}
++}
 +
-+		snprintf(acpi_str, sizeof(acpi_str), " (%u:%u:0x%x)",
-+			 gtm->drive[0].dma, gtm->drive[1].dma, gtm->flags);
++static void intel_i965_g33_setup_chipset_flush(void)
++{
++	u32 temp_hi, temp_lo;
++	int ret;
++
++	pci_read_config_dword(agp_bridge->dev, I965_IFPADDR + 4, &temp_hi);
++	pci_read_config_dword(agp_bridge->dev, I965_IFPADDR, &temp_lo);
++
++	if (!(temp_lo & 0x1)) {
++
++		intel_alloc_chipset_flush_resource();
++
++		intel_private.resource_valid = 1;
++		pci_write_config_dword(agp_bridge->dev, I965_IFPADDR + 4,
++			upper_32_bits(intel_private.ifp_resource.start));
++		pci_write_config_dword(agp_bridge->dev, I965_IFPADDR, (intel_private.ifp_resource.start & 0xffffffff) | 0x1);
++	} else {
++		u64 l64;
++
++		temp_lo &= ~0x1;
++		l64 = ((u64)temp_hi << 32) | temp_lo;
++
++		intel_private.resource_valid = 1;
++		intel_private.ifp_resource.start = l64;
++		intel_private.ifp_resource.end = l64 + PAGE_SIZE;
++		ret = request_resource(&iomem_resource, &intel_private.ifp_resource);
++		/* some BIOSes reserve this area in a pnp some don't */
++		if (ret)
++			intel_private.resource_valid = 0;
 +	}
++}
 +
-+	/* be optimistic, EH can take care of things if something goes wrong */
-+	limit = bios_limit | acpi_limit;
++static void intel_i9xx_setup_flush(void)
++{
++	/* return if already configured */
++	if (intel_private.ifp_resource.start)
++		return;
 +
-+	/* If PIO or DMA isn't configured at all, don't limit.  Let EH
-+	 * handle it.
-+	 */
-+	if (!(limit & ATA_MASK_PIO))
-+		limit |= ATA_MASK_PIO;
-+	if (!(limit & (ATA_MASK_MWDMA | ATA_MASK_UDMA)))
-+		limit |= ATA_MASK_MWDMA | ATA_MASK_UDMA;
++	/* setup a resource for this object */
++	intel_private.ifp_resource.name = "Intel Flush Page";
++	intel_private.ifp_resource.flags = IORESOURCE_MEM;
 +
-+	ata_port_printk(ap, KERN_DEBUG, "nv_mode_filter: 0x%lx&0x%lx->0x%lx, "
-+			"BIOS=0x%lx (0x%x) ACPI=0x%lx%s\n",
-+			xfer_mask, limit, xfer_mask & limit, bios_limit,
-+			saved_udma, acpi_limit, acpi_str);
++	/* Setup chipset flush for 915 */
++	if (IS_I965 || IS_G33) {
++		intel_i965_g33_setup_chipset_flush();
++	} else {
++		intel_i915_setup_chipset_flush();
++	}
 +
-+	return xfer_mask & limit;
++	if (intel_private.ifp_resource.start) {
++		intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE);
++		if (!intel_private.i9xx_flush_page)
++			printk(KERN_INFO "unable to ioremap flush  page - no chipset flushing");
++	}
 +}
++
+ static int intel_i915_configure(void)
+ {
+ 	struct aper_size_info_fixed *current_size;
+@@ -786,9 +929,9 @@ static int intel_i915_configure(void)
  
- /**
-  *	nv_probe_init	-	cable detection
-@@ -252,31 +308,6 @@ static void nv_error_handler(struct ata_port *ap)
- 			       ata_std_postreset);
+ 	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+ 
+-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
++	pci_read_config_word(agp_bridge->dev, I830_GMCH_CTRL, &gmch_ctrl);
+ 	gmch_ctrl |= I830_GMCH_ENABLED;
+-	pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
++	pci_write_config_word(agp_bridge->dev, I830_GMCH_CTRL, gmch_ctrl);
+ 
+ 	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_private.registers+I810_PGETBL_CTL);
+ 	readl(intel_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
+@@ -801,19 +944,34 @@ static int intel_i915_configure(void)
+ 	}
+ 
+ 	global_cache_flush();
++
++	intel_i9xx_setup_flush();
++
+ 	return 0;
  }
  
--static int nv_cable_detect(struct ata_port *ap)
--{
--	static const u8 bitmask[2] = {0x03, 0x0C};
--	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
--	u8 ata66;
--	u16 udma;
--	int cbl;
--
--	pci_read_config_byte(pdev, 0x52, &ata66);
--	if (ata66 & bitmask[ap->port_no])
--		cbl = ATA_CBL_PATA80;
--	else
--		cbl = ATA_CBL_PATA40;
--
-- 	/* We now have to double check because the Nvidia boxes BIOS
-- 	   doesn't always set the cable bits but does set mode bits */
-- 	pci_read_config_word(pdev, 0x62 - 2 * ap->port_no, &udma);
-- 	if ((udma & 0xC4) == 0xC4 || (udma & 0xC400) == 0xC400)
--		cbl = ATA_CBL_PATA80;
--	/* And a triple check across suspend/resume with ACPI around */
--	if (ata_acpi_cbl_80wire(ap))
--		cbl = ATA_CBL_PATA80;
--	return cbl;
--}
--
- /**
-  *	nv100_set_piomode	-	set initial PIO mode data
-  *	@ap: ATA interface
-@@ -314,6 +345,14 @@ static void nv133_set_dmamode(struct ata_port *ap, struct ata_device *adev)
- 	timing_setup(ap, adev, 0x50, adev->dma_mode, 4);
+ static void intel_i915_cleanup(void)
+ {
++	if (intel_private.i9xx_flush_page)
++		iounmap(intel_private.i9xx_flush_page);
++	if (intel_private.resource_valid)
++		release_resource(&intel_private.ifp_resource);
++	intel_private.ifp_resource.start = 0;
++	intel_private.resource_valid = 0;
+ 	iounmap(intel_private.gtt);
+ 	iounmap(intel_private.registers);
  }
  
-+static void nv_host_stop(struct ata_host *host)
-+{
-+	u32 udma = (unsigned long)host->private_data;
-+
-+	/* restore PCI config register 0x60 */
-+	pci_write_config_dword(to_pci_dev(host->dev), 0x60, udma);
+-static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
+-				int type)
++static void intel_i915_chipset_flush(struct agp_bridge_data *bridge)
+ {
+-	int i,j,num_entries;
++	if (intel_private.i9xx_flush_page)
++		writel(1, intel_private.i9xx_flush_page);
 +}
 +
- static struct scsi_host_template amd_sht = {
- 	.module			= THIS_MODULE,
- 	.name			= DRV_NAME,
-@@ -478,7 +517,8 @@ static struct ata_port_operations nv100_port_ops = {
- 	.thaw		= ata_bmdma_thaw,
- 	.error_handler	= nv_error_handler,
- 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
--	.cable_detect	= nv_cable_detect,
-+	.cable_detect	= ata_cable_ignore,
-+	.mode_filter	= nv_mode_filter,
- 
- 	.bmdma_setup 	= ata_bmdma_setup,
- 	.bmdma_start 	= ata_bmdma_start,
-@@ -495,6 +535,7 @@ static struct ata_port_operations nv100_port_ops = {
- 	.irq_on		= ata_irq_on,
++static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
++				     int type)
++{
++	int i, j, num_entries;
+ 	void *temp;
+ 	int ret = -EINVAL;
+ 	int mask_type;
+@@ -825,10 +983,10 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
+ 	num_entries = A_SIZE_FIX(temp)->num_entries;
+ 
+ 	if (pg_start < intel_private.gtt_entries) {
+-		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
+-				pg_start,intel_private.gtt_entries);
++		printk(KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n",
++				pg_start, intel_private.gtt_entries);
  
- 	.port_start	= ata_sff_port_start,
-+	.host_stop	= nv_host_stop,
- };
+-		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
++		printk(KERN_INFO PFX "Trying to insert into local/stolen memory\n");
+ 		goto out_err;
+ 	}
  
- static struct ata_port_operations nv133_port_ops = {
-@@ -511,7 +552,8 @@ static struct ata_port_operations nv133_port_ops = {
- 	.thaw		= ata_bmdma_thaw,
- 	.error_handler	= nv_error_handler,
- 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
--	.cable_detect	= nv_cable_detect,
-+	.cable_detect	= ata_cable_ignore,
-+	.mode_filter	= nv_mode_filter,
+@@ -866,8 +1024,8 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start,
+ 	return ret;
+ }
  
- 	.bmdma_setup 	= ata_bmdma_setup,
- 	.bmdma_start 	= ata_bmdma_start,
-@@ -528,6 +570,7 @@ static struct ata_port_operations nv133_port_ops = {
- 	.irq_on		= ata_irq_on,
+-static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
+-				int type)
++static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start,
++				     int type)
+ {
+ 	int i;
  
- 	.port_start	= ata_sff_port_start,
-+	.host_stop	= nv_host_stop,
- };
+@@ -875,13 +1033,13 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start,
+ 		return 0;
  
- static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
-@@ -614,7 +657,8 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
- 			.port_ops = &amd100_port_ops
- 		}
- 	};
--	const struct ata_port_info *ppi[] = { NULL, NULL };
-+	struct ata_port_info pi;
-+	const struct ata_port_info *ppi[] = { &pi, NULL };
- 	static int printed_version;
- 	int type = id->driver_data;
- 	u8 fifo;
-@@ -628,6 +672,19 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
- 	if (type == 1 && pdev->revision > 0x7)
- 		type = 2;
+ 	if (pg_start < intel_private.gtt_entries) {
+-		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
++		printk(KERN_INFO PFX "Trying to disable local/stolen memory\n");
+ 		return -EINVAL;
+ 	}
  
-+	/* Serenade ? */
-+	if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
-+			 pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
-+		type = 6;	/* UDMA 100 only */
-+
-+	/*
-+	 * Okay, type is determined now.  Apply type-specific workarounds.
-+	 */
-+	pi = info[type];
+-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
++	for (i = pg_start; i < (mem->page_count + pg_start); i++)
+ 		writel(agp_bridge->scratch_page, intel_private.gtt+i);
+-	}
 +
-+	if (type < 3)
-+		ata_pci_clear_simplex(pdev);
+ 	readl(intel_private.gtt+i-1);
+ 
+ 	agp_bridge->driver->tlb_flush(mem);
+@@ -928,7 +1086,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
+ 	agp_bridge->gatt_table_real = NULL;
+ 
+ 	pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
+-	pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2);
++	pci_read_config_dword(intel_private.pcidev, I915_PTEADDR, &temp2);
+ 
+ 	if (IS_G33)
+ 	    gtt_map_size = 1024 * 1024; /* 1M on G33 */
+@@ -938,7 +1096,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
+ 
+ 	temp &= 0xfff80000;
+ 
+-	intel_private.registers = ioremap(temp,128 * 4096);
++	intel_private.registers = ioremap(temp, 128 * 4096);
+ 	if (!intel_private.registers) {
+ 		iounmap(intel_private.gtt);
+ 		return -ENOMEM;
+@@ -985,6 +1143,7 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
+        struct aper_size_info_fixed *size;
+        int num_entries;
+        u32 temp;
++       int gtt_offset, gtt_size;
+ 
+        size = agp_bridge->current_size;
+        page_order = size->page_order;
+@@ -994,13 +1153,18 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
+        pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
+ 
+        temp &= 0xfff00000;
+-       intel_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);
+ 
+-	if (!intel_private.gtt)
+-		return -ENOMEM;
++       if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_HB)
++	       gtt_offset = gtt_size = MB(2);
++       else
++	       gtt_offset = gtt_size = KB(512);
 +
- 	/* Check for AMD7411 */
- 	if (type == 3)
- 		/* FIFO is broken */
-@@ -635,16 +692,17 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
- 	else
- 		pci_write_config_byte(pdev, 0x41, fifo | 0xF0);
++       intel_private.gtt = ioremap((temp + gtt_offset) , gtt_size);
  
--	/* Serenade ? */
--	if (type == 5 && pdev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
--			 pdev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
--		type = 6;	/* UDMA 100 only */
-+	/* Cable detection on Nvidia chips doesn't work too well,
-+	 * cache BIOS programmed UDMA mode.
-+	 */
-+	if (type == 7 || type == 8) {
-+		u32 udma;
++       if (!intel_private.gtt)
++	       return -ENOMEM;
  
--	if (type < 3)
--		ata_pci_clear_simplex(pdev);
-+		pci_read_config_dword(pdev, 0x60, &udma);
-+		pi.private_data = (void *)(unsigned long)udma;
-+	}
+-       intel_private.registers = ioremap(temp,128 * 4096);
++       intel_private.registers = ioremap(temp, 128 * 4096);
+        if (!intel_private.registers) {
+ 		iounmap(intel_private.gtt);
+ 		return -ENOMEM;
+@@ -1159,7 +1323,7 @@ static int intel_815_configure(void)
+ 	/* the Intel 815 chipset spec. says that bits 29-31 in the
+ 	* ATTBASE register are reserved -> try not to write them */
+ 	if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) {
+-		printk (KERN_EMERG PFX "gatt bus addr too high");
++		printk(KERN_EMERG PFX "gatt bus addr too high");
+ 		return -EINVAL;
+ 	}
  
- 	/* And fire it up */
--	ppi[0] = &info[type];
- 	return ata_pci_init_one(pdev, ppi);
- }
+@@ -1301,6 +1465,8 @@ static int intel_845_configure(void)
+ 	pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
+ 	/* clear any possible error conditions */
+ 	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c);
++
++	intel_i830_setup_flush();
+ 	return 0;
+ }
+ 
+@@ -1557,6 +1723,7 @@ static const struct agp_bridge_driver intel_830_driver = {
+ 	.agp_alloc_page		= agp_generic_alloc_page,
+ 	.agp_destroy_page	= agp_generic_destroy_page,
+ 	.agp_type_to_mask_type  = intel_i830_type_to_mask_type,
++	.chipset_flush		= intel_i830_chipset_flush,
+ };
+ 
+ static const struct agp_bridge_driver intel_820_driver = {
+@@ -1653,6 +1820,7 @@ static const struct agp_bridge_driver intel_845_driver = {
+ 	.agp_alloc_page		= agp_generic_alloc_page,
+ 	.agp_destroy_page	= agp_generic_destroy_page,
+ 	.agp_type_to_mask_type  = agp_generic_type_to_mask_type,
++	.chipset_flush		= intel_i830_chipset_flush,
+ };
+ 
+ static const struct agp_bridge_driver intel_850_driver = {
+@@ -1726,6 +1894,7 @@ static const struct agp_bridge_driver intel_915_driver = {
+ 	.agp_alloc_page		= agp_generic_alloc_page,
+ 	.agp_destroy_page	= agp_generic_destroy_page,
+ 	.agp_type_to_mask_type  = intel_i830_type_to_mask_type,
++	.chipset_flush		= intel_i915_chipset_flush,
+ };
+ 
+ static const struct agp_bridge_driver intel_i965_driver = {
+@@ -1751,6 +1920,7 @@ static const struct agp_bridge_driver intel_i965_driver = {
+        .agp_alloc_page         = agp_generic_alloc_page,
+        .agp_destroy_page       = agp_generic_destroy_page,
+        .agp_type_to_mask_type  = intel_i830_type_to_mask_type,
++	.chipset_flush		= intel_i915_chipset_flush,
+ };
+ 
+ static const struct agp_bridge_driver intel_7505_driver = {
+@@ -1800,6 +1970,7 @@ static const struct agp_bridge_driver intel_g33_driver = {
+ 	.agp_alloc_page         = agp_generic_alloc_page,
+ 	.agp_destroy_page       = agp_generic_destroy_page,
+ 	.agp_type_to_mask_type  = intel_i830_type_to_mask_type,
++	.chipset_flush		= intel_i915_chipset_flush,
+ };
+ 
+ static int find_gmch(u16 device)
+@@ -1809,7 +1980,7 @@ static int find_gmch(u16 device)
+ 	gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
+ 	if (gmch_device && PCI_FUNC(gmch_device->devfn) != 0) {
+ 		gmch_device = pci_get_device(PCI_VENDOR_ID_INTEL,
+-                                device, gmch_device);
++					     device, gmch_device);
+ 	}
+ 
+ 	if (!gmch_device)
+@@ -1872,7 +2043,7 @@ static const struct intel_driver_description {
+ 		NULL, &intel_915_driver },
+ 	{ PCI_DEVICE_ID_INTEL_82946GZ_HB, PCI_DEVICE_ID_INTEL_82946GZ_IG, 0, "946GZ",
+ 		NULL, &intel_i965_driver },
+-	{ PCI_DEVICE_ID_INTEL_82965G_1_HB, PCI_DEVICE_ID_INTEL_82965G_1_IG, 0, "965G",
++	{ PCI_DEVICE_ID_INTEL_82G35_HB, PCI_DEVICE_ID_INTEL_82G35_IG, 0, "G35",
+ 		NULL, &intel_i965_driver },
+ 	{ PCI_DEVICE_ID_INTEL_82965Q_HB, PCI_DEVICE_ID_INTEL_82965Q_IG, 0, "965Q",
+ 		NULL, &intel_i965_driver },
+@@ -1890,6 +2061,8 @@ static const struct intel_driver_description {
+ 		NULL, &intel_g33_driver },
+ 	{ PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33",
+ 		NULL, &intel_g33_driver },
++	{ PCI_DEVICE_ID_INTEL_IGD_HB, PCI_DEVICE_ID_INTEL_IGD_IG, 0,
++	    "Intel Integrated Graphics Device", NULL, &intel_i965_driver },
+ 	{ 0, 0, 0, NULL, NULL, NULL }
+ };
+ 
+@@ -1929,7 +2102,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
+ 	if (intel_agp_chipsets[i].name == NULL) {
+ 		if (cap_ptr)
+ 			printk(KERN_WARNING PFX "Unsupported Intel chipset"
+-                               "(device id: %04x)\n", pdev->device);
++			       "(device id: %04x)\n", pdev->device);
+ 		agp_put_bridge(bridge);
+ 		return -ENODEV;
+ 	}
+@@ -1942,7 +2115,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
+ 				intel_agp_chipsets[i].gmch_chip_id);
+ 		agp_put_bridge(bridge);
+ 		return -ENODEV;
+-        }
++	}
  
-diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c
-index 7842cc4..7f87f10 100644
---- a/drivers/ata/pata_bf54x.c
-+++ b/drivers/ata/pata_bf54x.c
-@@ -299,7 +299,7 @@ static void bfin_set_piomode(struct ata_port *ap, struct ata_device *adev)
- 	*/
- 	n6 = num_clocks_min(t6min, fsclk);
- 	if (mode >= 0 && mode <= 4 && n6 >= 1) {
--		pr_debug("set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
-+		dev_dbg(adev->link->ap->dev, "set piomode: mode=%d, fsclk=%ud\n", mode, fsclk);
- 		/* calculate the timing values for register transfers. */
- 		while (mode > 0 && pio_fsclk[mode] > fsclk)
- 			mode--;
-@@ -376,7 +376,7 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+ 	bridge->dev = pdev;
+ 	bridge->capndx = cap_ptr;
+@@ -2072,7 +2245,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
+ 	ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_82945GME_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
+-	ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
++	ID(PCI_DEVICE_ID_INTEL_82G35_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_82965G_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_82965GM_HB),
+@@ -2080,6 +2253,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
+ 	ID(PCI_DEVICE_ID_INTEL_G33_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_Q35_HB),
+ 	ID(PCI_DEVICE_ID_INTEL_Q33_HB),
++	ID(PCI_DEVICE_ID_INTEL_IGD_HB),
+ 	{ }
+ };
  
- 	mode = adev->dma_mode - XFER_UDMA_0;
- 	if (mode >= 0 && mode <= 5) {
--		pr_debug("set udmamode: mode=%d\n", mode);
-+		dev_dbg(adev->link->ap->dev, "set udmamode: mode=%d\n", mode);
- 		/* the most restrictive timing value is t6 and tc,
- 		 * the DIOW - data hold. If one SCLK pulse is longer
- 		 * than this minimum value then register
-@@ -433,7 +433,7 @@ static void bfin_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
+index e8d50af..ef5e6b1 100644
+--- a/drivers/char/drm/drm_vm.c
++++ b/drivers/char/drm/drm_vm.c
+@@ -506,6 +506,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
+ 	vma->vm_ops = &drm_vm_dma_ops;
  
- 	mode = adev->dma_mode - XFER_MW_DMA_0;
- 	if (mode >= 0 && mode <= 2) {
--		pr_debug("set mdmamode: mode=%d\n", mode);
-+		dev_dbg(adev->link->ap->dev, "set mdmamode: mode=%d\n", mode);
- 		/* the most restrictive timing value is tf, the DMACK to
- 		 * read data released. If one SCLK pulse is longer than
- 		 * this maximum value then the MDMA mode
-@@ -697,7 +697,7 @@ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
- 			write_atapi_register(base, ATA_REG_LBAL, tf->hob_lbal);
- 			write_atapi_register(base, ATA_REG_LBAM, tf->hob_lbam);
- 			write_atapi_register(base, ATA_REG_LBAH, tf->hob_lbah);
--			pr_debug("hob: feat 0x%X nsect 0x%X, lba 0x%X "
-+			dev_dbg(ap->dev, "hob: feat 0x%X nsect 0x%X, lba 0x%X "
- 				 "0x%X 0x%X\n",
- 				tf->hob_feature,
- 				tf->hob_nsect,
-@@ -711,7 +711,7 @@ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
- 		write_atapi_register(base, ATA_REG_LBAL, tf->lbal);
- 		write_atapi_register(base, ATA_REG_LBAM, tf->lbam);
- 		write_atapi_register(base, ATA_REG_LBAH, tf->lbah);
--		pr_debug("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
-+		dev_dbg(ap->dev, "feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
- 			tf->feature,
- 			tf->nsect,
- 			tf->lbal,
-@@ -721,7 +721,7 @@ static void bfin_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
+ 	vma->vm_flags |= VM_RESERVED;	/* Don't swap */
++	vma->vm_flags |= VM_DONTEXPAND;
  
- 	if (tf->flags & ATA_TFLAG_DEVICE) {
- 		write_atapi_register(base, ATA_REG_DEVICE, tf->device);
--		pr_debug("device 0x%X\n", tf->device);
-+		dev_dbg(ap->dev, "device 0x%X\n", tf->device);
+ 	vma->vm_file = filp;	/* Needed for drm_vm_open() */
+ 	drm_vm_open_locked(vma);
+@@ -655,6 +656,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
+ 		return -EINVAL;	/* This should never happen. */
  	}
+ 	vma->vm_flags |= VM_RESERVED;	/* Don't swap */
++	vma->vm_flags |= VM_DONTEXPAND;
  
- 	ata_wait_idle(ap);
-@@ -782,7 +782,7 @@ static void bfin_exec_command(struct ata_port *ap,
- 			      const struct ata_taskfile *tf)
+ 	vma->vm_file = filp;	/* Needed for drm_vm_open() */
+ 	drm_vm_open_locked(vma);
+diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h
+index 3ae57ec..fa194a4 100644
+--- a/drivers/char/drm/r300_reg.h
++++ b/drivers/char/drm/r300_reg.h
+@@ -584,7 +584,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
+ #define R300_RE_FOG_START                     0x4298
+ 
+ /* Not sure why there are duplicate of factor and constant values.
+- * My best guess so far is that there are seperate zbiases for test and write.
++ * My best guess so far is that there are separate zbiases for test and write.
+  * Ordering might be wrong.
+  * Some of the tests indicate that fgl has a fallback implementation of zbias
+  * via pixel shaders.
+diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
+index 75d6b74..7009dbd 100644
+--- a/drivers/char/drm/via_dma.c
++++ b/drivers/char/drm/via_dma.c
+@@ -400,7 +400,7 @@ static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
+ }
+ 
+ /*
+- * This function is used internally by ring buffer mangement code.
++ * This function is used internally by ring buffer management code.
+  *
+  * Returns virtual pointer to ring buffer.
+  */
+diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c
+index 004141d..49233f5 100644
+--- a/drivers/char/efirtc.c
++++ b/drivers/char/efirtc.c
+@@ -18,7 +18,7 @@
+  *
+  * NOTES:
+  *	- Locking is required for safe execution of EFI calls with regards
+- *	  to interrrupts and SMP.
++ *	  to interrupts and SMP.
+  *
+  * TODO (December 1999):
+  * 	- provide the API to set/get the WakeUp Alarm (different from the
+diff --git a/drivers/char/epca.c b/drivers/char/epca.c
+index ffcecde..ffd747c 100644
+--- a/drivers/char/epca.c
++++ b/drivers/char/epca.c
+@@ -1797,7 +1797,7 @@ static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
+ 	res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
+ 	/*
+ 	 * This gets a little confusing. The Digi cards have their own
+-	 * representation of c_cflags controling baud rate. For the most part
++	 * representation of c_cflags controlling baud rate. For the most part
+ 	 * this is identical to the Linux implementation. However; Digi
+ 	 * supports one rate (76800) that Linux doesn't. This means that the
+ 	 * c_cflag entry that would normally mean 76800 for Digi actually means
+@@ -2068,7 +2068,7 @@ static int info_ioctl(struct tty_struct *tty, struct file *file,
+ 		{
+ 			/*
+ 			 * This call is made by the apps to complete the
+-			 * initilization of the board(s). This routine is
++			 * initialization of the board(s). This routine is
+ 			 * responsible for setting the card to its initial
+ 			 * state and setting the drivers control fields to the
+ 			 * sutianle settings for the card in question.
+diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
+index 0e8ceea..712d9f2 100644
+--- a/drivers/char/hangcheck-timer.c
++++ b/drivers/char/hangcheck-timer.c
+@@ -26,7 +26,7 @@
+  * The hangcheck-timer driver uses the TSC to catch delays that
+  * jiffies does not notice.  A timer is set.  When the timer fires, it
+  * checks whether it was delayed and if that delay exceeds a given
+- * margin of error.  The hangcheck_tick module paramter takes the timer
++ * margin of error.  The hangcheck_tick module parameter takes the timer
+  * duration in seconds.  The hangcheck_margin parameter defines the
+  * margin of error, in seconds.  The defaults are 60 seconds for the
+  * timer and 180 seconds for the margin of error.  IOW, a timer is set
+diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
+index 4c16778..465ad35 100644
+--- a/drivers/char/hpet.c
++++ b/drivers/char/hpet.c
+@@ -600,63 +600,6 @@ static int hpet_is_known(struct hpet_data *hdp)
+ 	return 0;
+ }
+ 
+-EXPORT_SYMBOL(hpet_alloc);
+-EXPORT_SYMBOL(hpet_register);
+-EXPORT_SYMBOL(hpet_unregister);
+-EXPORT_SYMBOL(hpet_control);
+-
+-int hpet_register(struct hpet_task *tp, int periodic)
+-{
+-	unsigned int i;
+-	u64 mask;
+-	struct hpet_timer __iomem *timer;
+-	struct hpet_dev *devp;
+-	struct hpets *hpetp;
+-
+-	switch (periodic) {
+-	case 1:
+-		mask = Tn_PER_INT_CAP_MASK;
+-		break;
+-	case 0:
+-		mask = 0;
+-		break;
+-	default:
+-		return -EINVAL;
+-	}
+-
+-	tp->ht_opaque = NULL;
+-
+-	spin_lock_irq(&hpet_task_lock);
+-	spin_lock(&hpet_lock);
+-
+-	for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
+-		for (timer = hpetp->hp_hpet->hpet_timers, i = 0;
+-		     i < hpetp->hp_ntimer; i++, timer++) {
+-			if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK)
+-			    != mask)
+-				continue;
+-
+-			devp = &hpetp->hp_dev[i];
+-
+-			if (devp->hd_flags & HPET_OPEN || devp->hd_task) {
+-				devp = NULL;
+-				continue;
+-			}
+-
+-			tp->ht_opaque = devp;
+-			devp->hd_task = tp;
+-			break;
+-		}
+-
+-	spin_unlock(&hpet_lock);
+-	spin_unlock_irq(&hpet_task_lock);
+-
+-	if (tp->ht_opaque)
+-		return 0;
+-	else
+-		return -EBUSY;
+-}
+-
+ static inline int hpet_tpcheck(struct hpet_task *tp)
  {
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
--	pr_debug("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
-+	dev_dbg(ap->dev, "ata%u: cmd 0x%X\n", ap->print_id, tf->command);
+ 	struct hpet_dev *devp;
+@@ -706,24 +649,6 @@ int hpet_unregister(struct hpet_task *tp)
+ 	return 0;
+ }
  
- 	write_atapi_register(base, ATA_REG_CMD, tf->command);
- 	ata_pause(ap);
-@@ -832,14 +832,15 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
+-int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
+-{
+-	struct hpet_dev *devp;
+-	int err;
+-
+-	if ((err = hpet_tpcheck(tp)))
+-		return err;
+-
+-	spin_lock_irq(&hpet_lock);
+-	devp = tp->ht_opaque;
+-	if (devp->hd_task != tp) {
+-		spin_unlock_irq(&hpet_lock);
+-		return -ENXIO;
+-	}
+-	spin_unlock_irq(&hpet_lock);
+-	return hpet_ioctl_common(devp, cmd, arg, 1);
+-}
+-
+ static ctl_table hpet_table[] = {
+ 	{
+ 	 .ctl_name = CTL_UNNUMBERED,
+@@ -806,14 +731,14 @@ static unsigned long hpet_calibrate(struct hpets *hpetp)
+ 
+ int hpet_alloc(struct hpet_data *hdp)
  {
- 	unsigned short config = WDSIZE_16;
- 	struct scatterlist *sg;
-+	unsigned int si;
+-	u64 cap, mcfg;
++	u64 cap, mcfg, hpet_config;
+ 	struct hpet_dev *devp;
+-	u32 i, ntimer;
++	u32 i, ntimer, irq;
+ 	struct hpets *hpetp;
+ 	size_t siz;
+ 	struct hpet __iomem *hpet;
+ 	static struct hpets *last = NULL;
+-	unsigned long period;
++	unsigned long period, irq_bitmap;
+ 	unsigned long long temp;
  
--	pr_debug("in atapi dma setup\n");
-+	dev_dbg(qc->ap->dev, "in atapi dma setup\n");
- 	/* Program the ATA_CTRL register with dir */
- 	if (qc->tf.flags & ATA_TFLAG_WRITE) {
- 		/* fill the ATAPI DMA controller */
- 		set_dma_config(CH_ATAPI_TX, config);
- 		set_dma_x_modify(CH_ATAPI_TX, 2);
--		ata_for_each_sg(sg, qc) {
-+		for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 			set_dma_start_addr(CH_ATAPI_TX, sg_dma_address(sg));
- 			set_dma_x_count(CH_ATAPI_TX, sg_dma_len(sg) >> 1);
- 		}
-@@ -848,7 +849,7 @@ static void bfin_bmdma_setup(struct ata_queued_cmd *qc)
- 		/* fill the ATAPI DMA controller */
- 		set_dma_config(CH_ATAPI_RX, config);
- 		set_dma_x_modify(CH_ATAPI_RX, 2);
--		ata_for_each_sg(sg, qc) {
-+		for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 			set_dma_start_addr(CH_ATAPI_RX, sg_dma_address(sg));
- 			set_dma_x_count(CH_ATAPI_RX, sg_dma_len(sg) >> 1);
- 		}
-@@ -867,8 +868,9 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
- 	struct ata_port *ap = qc->ap;
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- 	struct scatterlist *sg;
-+	unsigned int si;
+ 	/*
+@@ -840,11 +765,47 @@ int hpet_alloc(struct hpet_data *hdp)
+ 	hpetp->hp_hpet_phys = hdp->hd_phys_address;
  
--	pr_debug("in atapi dma start\n");
-+	dev_dbg(qc->ap->dev, "in atapi dma start\n");
- 	if (!(ap->udma_mask || ap->mwdma_mask))
- 		return;
+ 	hpetp->hp_ntimer = hdp->hd_nirqs;
++	hpet = hpetp->hp_hpet;
  
-@@ -881,12 +883,12 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
- 		 * data cache is enabled. Otherwise, this loop
- 		 * is an empty loop and optimized out.
- 		 */
--		ata_for_each_sg(sg, qc) {
-+		for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 			flush_dcache_range(sg_dma_address(sg),
- 				sg_dma_address(sg) + sg_dma_len(sg));
- 		}
- 		enable_dma(CH_ATAPI_TX);
--		pr_debug("enable udma write\n");
-+		dev_dbg(qc->ap->dev, "enable udma write\n");
+-	for (i = 0; i < hdp->hd_nirqs; i++)
+-		hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
++	/* Assign IRQs statically for legacy devices */
++	hpetp->hp_dev[0].hd_hdwirq = hdp->hd_irq[0];
++	hpetp->hp_dev[1].hd_hdwirq = hdp->hd_irq[1];
  
- 		/* Send ATA DMA write command */
- 		bfin_exec_command(ap, &qc->tf);
-@@ -896,7 +898,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
- 			| XFER_DIR));
- 	} else {
- 		enable_dma(CH_ATAPI_RX);
--		pr_debug("enable udma read\n");
-+		dev_dbg(qc->ap->dev, "enable udma read\n");
+-	hpet = hpetp->hp_hpet;
++	/* Assign IRQs dynamically for the others */
++	for (i = 2, devp = &hpetp->hp_dev[2]; i < hdp->hd_nirqs; i++, devp++) {
++		struct hpet_timer __iomem *timer;
++
++		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
++
++		/* Check if there's already an IRQ assigned to the timer */
++		if (hdp->hd_irq[i]) {
++			hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
++			continue;
++		}
++
++		hpet_config = readq(&timer->hpet_config);
++		irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK)
++			>> Tn_INT_ROUTE_CAP_SHIFT;
++		if (!irq_bitmap)
++			irq = 0;        /* No valid IRQ Assignable */
++		else {
++			irq = find_first_bit(&irq_bitmap, 32);
++			do {
++				hpet_config |= irq << Tn_INT_ROUTE_CNF_SHIFT;
++				writeq(hpet_config, &timer->hpet_config);
++
++				/*
++				 * Verify whether we have written a valid
++				 * IRQ number by reading it back again
++				 */
++				hpet_config = readq(&timer->hpet_config);
++				if (irq == (hpet_config & Tn_INT_ROUTE_CNF_MASK)
++						>> Tn_INT_ROUTE_CNF_SHIFT)
++					break;  /* Success */
++			} while ((irq = (find_next_bit(&irq_bitmap, 32, irq))));
++		}
++		hpetp->hp_dev[i].hd_hdwirq = irq;
++	}
  
- 		/* Send ATA DMA read command */
- 		bfin_exec_command(ap, &qc->tf);
-@@ -910,7 +912,7 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
- 	ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
+ 	cap = readq(&hpet->hpet_cap);
  
- 		/* Set transfer length to buffer len */
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
- 	}
+@@ -875,7 +836,8 @@ int hpet_alloc(struct hpet_data *hdp)
+ 		hpetp->hp_which, hdp->hd_phys_address,
+ 		hpetp->hp_ntimer > 1 ? "s" : "");
+ 	for (i = 0; i < hpetp->hp_ntimer; i++)
+-		printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
++		printk("%s %d", i > 0 ? "," : "",
++				hpetp->hp_dev[i].hd_hdwirq);
+ 	printk("\n");
  
-@@ -932,8 +934,9 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
- {
- 	struct ata_port *ap = qc->ap;
- 	struct scatterlist *sg;
-+	unsigned int si;
+ 	printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
+diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
+index 8252f86..480fae2 100644
+--- a/drivers/char/hvc_console.c
++++ b/drivers/char/hvc_console.c
+@@ -27,7 +27,7 @@
+ #include <linux/init.h>
+ #include <linux/kbd_kern.h>
+ #include <linux/kernel.h>
+-#include <linux/kobject.h>
++#include <linux/kref.h>
+ #include <linux/kthread.h>
+ #include <linux/list.h>
+ #include <linux/module.h>
+@@ -89,7 +89,7 @@ struct hvc_struct {
+ 	int irq_requested;
+ 	int irq;
+ 	struct list_head next;
+-	struct kobject kobj; /* ref count & hvc_struct lifetime */
++	struct kref kref; /* ref count & hvc_struct lifetime */
+ };
  
--	pr_debug("in atapi dma stop\n");
-+	dev_dbg(qc->ap->dev, "in atapi dma stop\n");
- 	if (!(ap->udma_mask || ap->mwdma_mask))
- 		return;
+ /* dynamic list of hvc_struct instances */
+@@ -110,7 +110,7 @@ static int last_hvc = -1;
  
-@@ -950,7 +953,7 @@ static void bfin_bmdma_stop(struct ata_queued_cmd *qc)
- 			 * data cache is enabled. Otherwise, this loop
- 			 * is an empty loop and optimized out.
- 			 */
--			ata_for_each_sg(sg, qc) {
-+			for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 				invalidate_dcache_range(
- 					sg_dma_address(sg),
- 					sg_dma_address(sg)
-@@ -1144,15 +1147,15 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- 	unsigned short int_status = ATAPI_GET_INT_STATUS(base);
+ /*
+  * Do not call this function with either the hvc_structs_lock or the hvc_struct
+- * lock held.  If successful, this function increments the kobject reference
++ * lock held.  If successful, this function increments the kref reference
+  * count against the target hvc_struct so it should be released when finished.
+  */
+ static struct hvc_struct *hvc_get_by_index(int index)
+@@ -123,7 +123,7 @@ static struct hvc_struct *hvc_get_by_index(int index)
+ 	list_for_each_entry(hp, &hvc_structs, next) {
+ 		spin_lock_irqsave(&hp->lock, flags);
+ 		if (hp->index == index) {
+-			kobject_get(&hp->kobj);
++			kref_get(&hp->kref);
+ 			spin_unlock_irqrestore(&hp->lock, flags);
+ 			spin_unlock(&hvc_structs_lock);
+ 			return hp;
+@@ -242,6 +242,23 @@ static int __init hvc_console_init(void)
+ }
+ console_initcall(hvc_console_init);
  
--	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON)) {
-+	if (ATAPI_GET_STATUS(base) & (MULTI_XFER_ON|ULTRA_XFER_ON))
- 		host_stat |= ATA_DMA_ACTIVE;
--	}
--	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT)) {
-+	if (int_status & (MULTI_DONE_INT|UDMAIN_DONE_INT|UDMAOUT_DONE_INT|
-+		ATAPI_DEV_INT))
- 		host_stat |= ATA_DMA_INTR;
--	}
--	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT)) {
--		host_stat |= ATA_DMA_ERR;
--	}
-+	if (int_status & (MULTI_TERM_INT|UDMAIN_TERM_INT|UDMAOUT_TERM_INT))
-+		host_stat |= ATA_DMA_ERR|ATA_DMA_INTR;
++/* callback when the kboject ref count reaches zero. */
++static void destroy_hvc_struct(struct kref *kref)
++{
++	struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
++	unsigned long flags;
 +
-+	dev_dbg(ap->dev, "ATAPI: host_stat=0x%x\n", host_stat);
++	spin_lock(&hvc_structs_lock);
++
++	spin_lock_irqsave(&hp->lock, flags);
++	list_del(&(hp->next));
++	spin_unlock_irqrestore(&hp->lock, flags);
++
++	spin_unlock(&hvc_structs_lock);
++
++	kfree(hp);
++}
++
+ /*
+  * hvc_instantiate() is an early console discovery method which locates
+  * consoles * prior to the vio subsystem discovering them.  Hotplugged
+@@ -261,7 +278,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
+ 	/* make sure no no tty has been registered in this index */
+ 	hp = hvc_get_by_index(index);
+ 	if (hp) {
+-		kobject_put(&hp->kobj);
++		kref_put(&hp->kref, destroy_hvc_struct);
+ 		return -1;
+ 	}
  
- 	return host_stat;
- }
-@@ -1167,34 +1170,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
-  *	Note: Original code is ata_data_xfer().
-  */
+@@ -318,9 +335,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
+ 	unsigned long flags;
+ 	int irq = 0;
+ 	int rc = 0;
+-	struct kobject *kobjp;
  
--static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
--			   unsigned int buflen, int write_data)
-+static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
-+				   unsigned int buflen, int rw)
+-	/* Auto increments kobject reference if found. */
++	/* Auto increments kref reference if found. */
+ 	if (!(hp = hvc_get_by_index(tty->index)))
+ 		return -ENODEV;
+ 
+@@ -341,8 +357,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
+ 	if (irq)
+ 		hp->irq_requested = 1;
+ 
+-	kobjp = &hp->kobj;
+-
+ 	spin_unlock_irqrestore(&hp->lock, flags);
+ 	/* check error, fallback to non-irq */
+ 	if (irq)
+@@ -352,7 +366,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
+ 	 * If the request_irq() fails and we return an error.  The tty layer
+ 	 * will call hvc_close() after a failed open but we don't want to clean
+ 	 * up there so we'll clean up here and clear out the previously set
+-	 * tty fields and return the kobject reference.
++	 * tty fields and return the kref reference.
+ 	 */
+ 	if (rc) {
+ 		spin_lock_irqsave(&hp->lock, flags);
+@@ -360,7 +374,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
+ 		hp->irq_requested = 0;
+ 		spin_unlock_irqrestore(&hp->lock, flags);
+ 		tty->driver_data = NULL;
+-		kobject_put(kobjp);
++		kref_put(&hp->kref, destroy_hvc_struct);
+ 		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
+ 	}
+ 	/* Force wakeup of the polling thread */
+@@ -372,7 +386,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
+ static void hvc_close(struct tty_struct *tty, struct file * filp)
  {
--	struct ata_port *ap = adev->link->ap;
--	unsigned int words = buflen >> 1;
--	unsigned short *buf16 = (u16 *) buf;
-+	struct ata_port *ap = dev->link->ap;
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
-+	unsigned int words = buflen >> 1;
-+	unsigned short *buf16 = (u16 *)buf;
+ 	struct hvc_struct *hp;
+-	struct kobject *kobjp;
+ 	int irq = 0;
+ 	unsigned long flags;
  
- 	/* Transfer multiple of 2 bytes */
--	if (write_data) {
--		write_atapi_data(base, words, buf16);
--	} else {
-+	if (rw == READ)
- 		read_atapi_data(base, words, buf16);
--	}
-+	else
-+		write_atapi_data(base, words, buf16);
+@@ -382,7 +395,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
+ 	/*
+ 	 * No driver_data means that this close was issued after a failed
+ 	 * hvc_open by the tty layer's release_dev() function and we can just
+-	 * exit cleanly because the kobject reference wasn't made.
++	 * exit cleanly because the kref reference wasn't made.
+ 	 */
+ 	if (!tty->driver_data)
+ 		return;
+@@ -390,7 +403,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
+ 	hp = tty->driver_data;
+ 	spin_lock_irqsave(&hp->lock, flags);
  
- 	/* Transfer trailing 1 byte, if any. */
- 	if (unlikely(buflen & 0x01)) {
- 		unsigned short align_buf[1] = { 0 };
- 		unsigned char *trailing_buf = buf + buflen - 1;
+-	kobjp = &hp->kobj;
+ 	if (--hp->count == 0) {
+ 		if (hp->irq_requested)
+ 			irq = hp->irq;
+@@ -417,7 +429,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
+ 		spin_unlock_irqrestore(&hp->lock, flags);
+ 	}
  
--		if (write_data) {
--			memcpy(align_buf, trailing_buf, 1);
--			write_atapi_data(base, 1, align_buf);
--		} else {
-+		if (rw == READ) {
- 			read_atapi_data(base, 1, align_buf);
- 			memcpy(trailing_buf, align_buf, 1);
-+		} else {
-+			memcpy(align_buf, trailing_buf, 1);
-+			write_atapi_data(base, 1, align_buf);
- 		}
-+		words++;
+-	kobject_put(kobjp);
++	kref_put(&hp->kref, destroy_hvc_struct);
+ }
+ 
+ static void hvc_hangup(struct tty_struct *tty)
+@@ -426,7 +438,6 @@ static void hvc_hangup(struct tty_struct *tty)
+ 	unsigned long flags;
+ 	int irq = 0;
+ 	int temp_open_count;
+-	struct kobject *kobjp;
+ 
+ 	if (!hp)
+ 		return;
+@@ -443,7 +454,6 @@ static void hvc_hangup(struct tty_struct *tty)
+ 		return;
+ 	}
+ 
+-	kobjp = &hp->kobj;
+ 	temp_open_count = hp->count;
+ 	hp->count = 0;
+ 	hp->n_outbuf = 0;
+@@ -457,7 +467,7 @@ static void hvc_hangup(struct tty_struct *tty)
+ 		free_irq(irq, hp);
+ 	while(temp_open_count) {
+ 		--temp_open_count;
+-		kobject_put(kobjp);
++		kref_put(&hp->kref, destroy_hvc_struct);
  	}
-+
-+	return words << 1;
  }
  
- /**
-@@ -1208,8 +1213,7 @@ static void bfin_irq_clear(struct ata_port *ap)
- {
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+@@ -729,27 +739,6 @@ static const struct tty_operations hvc_ops = {
+ 	.chars_in_buffer = hvc_chars_in_buffer,
+ };
  
--	pr_debug("in atapi irq clear\n");
+-/* callback when the kboject ref count reaches zero. */
+-static void destroy_hvc_struct(struct kobject *kobj)
+-{
+-	struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
+-	unsigned long flags;
 -
-+	dev_dbg(ap->dev, "in atapi irq clear\n");
- 	ATAPI_SET_INT_STATUS(base, ATAPI_GET_INT_STATUS(base)|ATAPI_DEV_INT
- 		| MULTI_DONE_INT | UDMAIN_DONE_INT | UDMAOUT_DONE_INT
- 		| MULTI_TERM_INT | UDMAIN_TERM_INT | UDMAOUT_TERM_INT);
-@@ -1227,7 +1231,7 @@ static unsigned char bfin_irq_on(struct ata_port *ap)
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
- 	u8 tmp;
+-	spin_lock(&hvc_structs_lock);
+-
+-	spin_lock_irqsave(&hp->lock, flags);
+-	list_del(&(hp->next));
+-	spin_unlock_irqrestore(&hp->lock, flags);
+-
+-	spin_unlock(&hvc_structs_lock);
+-
+-	kfree(hp);
+-}
+-
+-static struct kobj_type hvc_kobj_type = {
+-	.release = destroy_hvc_struct,
+-};
+-
+ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+ 					struct hv_ops *ops, int outbuf_size)
+ {
+@@ -776,8 +765,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+ 	hp->outbuf_size = outbuf_size;
+ 	hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
  
--	pr_debug("in atapi irq on\n");
-+	dev_dbg(ap->dev, "in atapi irq on\n");
- 	ap->ctl &= ~ATA_NIEN;
- 	ap->last_ctl = ap->ctl;
+-	kobject_init(&hp->kobj);
+-	hp->kobj.ktype = &hvc_kobj_type;
++	kref_init(&hp->kref);
  
-@@ -1250,7 +1254,7 @@ static void bfin_bmdma_freeze(struct ata_port *ap)
+ 	spin_lock_init(&hp->lock);
+ 	spin_lock(&hvc_structs_lock);
+@@ -806,12 +794,10 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
+ int __devexit hvc_remove(struct hvc_struct *hp)
  {
- 	void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+ 	unsigned long flags;
+-	struct kobject *kobjp;
+ 	struct tty_struct *tty;
  
--	pr_debug("in atapi dma freeze\n");
-+	dev_dbg(ap->dev, "in atapi dma freeze\n");
- 	ap->ctl |= ATA_NIEN;
- 	ap->last_ctl = ap->ctl;
+ 	spin_lock_irqsave(&hp->lock, flags);
+ 	tty = hp->tty;
+-	kobjp = &hp->kobj;
  
-@@ -1323,7 +1327,7 @@ static void bfin_error_handler(struct ata_port *ap)
+ 	if (hp->index < MAX_NR_HVC_CONSOLES)
+ 		vtermnos[hp->index] = -1;
+@@ -821,12 +807,12 @@ int __devexit hvc_remove(struct hvc_struct *hp)
+ 	spin_unlock_irqrestore(&hp->lock, flags);
  
- static void bfin_port_stop(struct ata_port *ap)
+ 	/*
+-	 * We 'put' the instance that was grabbed when the kobject instance
+-	 * was initialized using kobject_init().  Let the last holder of this
+-	 * kobject cause it to be removed, which will probably be the tty_hangup
++	 * We 'put' the instance that was grabbed when the kref instance
++	 * was initialized using kref_init().  Let the last holder of this
++	 * kref cause it to be removed, which will probably be the tty_hangup
+ 	 * below.
+ 	 */
+-	kobject_put(kobjp);
++	kref_put(&hp->kref, destroy_hvc_struct);
+ 
+ 	/*
+ 	 * This function call will auto chain call hvc_hangup.  The tty should
+diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
+index 69d8866..3402def 100644
+--- a/drivers/char/hvcs.c
++++ b/drivers/char/hvcs.c
+@@ -57,11 +57,7 @@
+  * rescanning partner information upon a user's request.
+  *
+  * Each vty-server, prior to being exposed to this driver is reference counted
+- * using the 2.6 Linux kernel kobject construct.  This kobject is also used by
+- * the vio bus to provide a vio device sysfs entry that this driver attaches
+- * device specific attributes to, including partner information.  The vio bus
+- * framework also provides a sysfs entry for each vio driver.  The hvcs driver
+- * provides driver attributes in this entry.
++ * using the 2.6 Linux kernel kref construct.
+  *
+  * For direction on installation and usage of this driver please reference
+  * Documentation/powerpc/hvcs.txt.
+@@ -71,7 +67,7 @@
+ #include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/kernel.h>
+-#include <linux/kobject.h>
++#include <linux/kref.h>
+ #include <linux/kthread.h>
+ #include <linux/list.h>
+ #include <linux/major.h>
+@@ -293,12 +289,12 @@ struct hvcs_struct {
+ 	int chars_in_buffer;
+ 
+ 	/*
+-	 * Any variable below the kobject is valid before a tty is connected and
++	 * Any variable below the kref is valid before a tty is connected and
+ 	 * stays valid after the tty is disconnected.  These shouldn't be
+ 	 * whacked until the koject refcount reaches zero though some entries
+ 	 * may be changed via sysfs initiatives.
+ 	 */
+-	struct kobject kobj; /* ref count & hvcs_struct lifetime */
++	struct kref kref; /* ref count & hvcs_struct lifetime */
+ 	int connected; /* is the vty-server currently connected to a vty? */
+ 	uint32_t p_unit_address; /* partner unit address */
+ 	uint32_t p_partition_ID; /* partner partition ID */
+@@ -307,8 +303,8 @@ struct hvcs_struct {
+ 	struct vio_dev *vdev;
+ };
+ 
+-/* Required to back map a kobject to its containing object */
+-#define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
++/* Required to back map a kref to its containing object */
++#define from_kref(k) container_of(k, struct hvcs_struct, kref)
+ 
+ static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
+ static DEFINE_SPINLOCK(hvcs_structs_lock);
+@@ -334,7 +330,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd);
+ static int hvcs_enable_device(struct hvcs_struct *hvcsd,
+ 		uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
+ 
+-static void destroy_hvcs_struct(struct kobject *kobj);
+ static int hvcs_open(struct tty_struct *tty, struct file *filp);
+ static void hvcs_close(struct tty_struct *tty, struct file *filp);
+ static void hvcs_hangup(struct tty_struct * tty);
+@@ -703,10 +698,10 @@ static void hvcs_return_index(int index)
+ 		hvcs_index_list[index] = -1;
+ }
+ 
+-/* callback when the kboject ref count reaches zero */
+-static void destroy_hvcs_struct(struct kobject *kobj)
++/* callback when the kref ref count reaches zero */
++static void destroy_hvcs_struct(struct kref *kref)
  {
--	pr_debug("in atapi port stop\n");
-+	dev_dbg(ap->dev, "in atapi port stop\n");
- 	if (ap->udma_mask != 0 || ap->mwdma_mask != 0) {
- 		free_dma(CH_ATAPI_RX);
- 		free_dma(CH_ATAPI_TX);
-@@ -1332,7 +1336,7 @@ static void bfin_port_stop(struct ata_port *ap)
+-	struct hvcs_struct *hvcsd = from_kobj(kobj);
++	struct hvcs_struct *hvcsd = from_kref(kref);
+ 	struct vio_dev *vdev;
+ 	unsigned long flags;
  
- static int bfin_port_start(struct ata_port *ap)
+@@ -743,10 +738,6 @@ static void destroy_hvcs_struct(struct kobject *kobj)
+ 	kfree(hvcsd);
+ }
+ 
+-static struct kobj_type hvcs_kobj_type = {
+-	.release = destroy_hvcs_struct,
+-};
+-
+ static int hvcs_get_index(void)
  {
--	pr_debug("in atapi port start\n");
-+	dev_dbg(ap->dev, "in atapi port start\n");
- 	if (!(ap->udma_mask || ap->mwdma_mask))
- 		return 0;
+ 	int i;
+@@ -791,9 +782,7 @@ static int __devinit hvcs_probe(
  
-@@ -1368,10 +1372,6 @@ static struct scsi_host_template bfin_sht = {
- 	.slave_configure	= ata_scsi_slave_config,
- 	.slave_destroy		= ata_scsi_slave_destroy,
- 	.bios_param		= ata_std_bios_param,
--#ifdef CONFIG_PM
--	.resume			= ata_scsi_device_resume,
--	.suspend		= ata_scsi_device_suspend,
--#endif
- };
+ 	spin_lock_init(&hvcsd->lock);
+ 	/* Automatically incs the refcount the first time */
+-	kobject_init(&hvcsd->kobj);
+-	/* Set up the callback for terminating the hvcs_struct's life */
+-	hvcsd->kobj.ktype = &hvcs_kobj_type;
++	kref_init(&hvcsd->kref);
  
- static const struct ata_port_operations bfin_pata_ops = {
-diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c
-index 33f7f08..7ed279b 100644
---- a/drivers/ata/pata_cs5520.c
-+++ b/drivers/ata/pata_cs5520.c
-@@ -198,7 +198,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
- 	};
- 	const struct ata_port_info *ppi[2];
- 	u8 pcicfg;
--	void *iomap[5];
-+	void __iomem *iomap[5];
- 	struct ata_host *host;
- 	struct ata_ioports *ioaddr;
- 	int i, rc;
-@@ -229,7 +229,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi
- 		return -ENOMEM;
+ 	hvcsd->vdev = dev;
+ 	dev->dev.driver_data = hvcsd;
+@@ -844,27 +833,24 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
+ {
+ 	struct hvcs_struct *hvcsd = dev->dev.driver_data;
+ 	unsigned long flags;
+-	struct kobject *kobjp;
+ 	struct tty_struct *tty;
  
- 	/* Perform set up for DMA */
--	if (pci_enable_device_bars(pdev, 1<<2)) {
-+	if (pci_enable_device_io(pdev)) {
- 		printk(KERN_ERR DRV_NAME ": unable to configure BAR2.\n");
+ 	if (!hvcsd)
  		return -ENODEV;
- 	}
-diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c
-index c79f066..68eb349 100644
---- a/drivers/ata/pata_hpt37x.c
-+++ b/drivers/ata/pata_hpt37x.c
-@@ -847,15 +847,16 @@ static u32 hpt374_read_freq(struct pci_dev *pdev)
- 	u32 freq;
- 	unsigned long io_base = pci_resource_start(pdev, 4);
- 	if (PCI_FUNC(pdev->devfn) & 1) {
--		struct pci_dev *pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
-+		struct pci_dev *pdev_0;
-+
-+		pdev_0 = pci_get_slot(pdev->bus, pdev->devfn - 1);
- 		/* Someone hot plugged the controller on us ? */
- 		if (pdev_0 == NULL)
- 			return 0;
- 		io_base = pci_resource_start(pdev_0, 4);
- 		freq = inl(io_base + 0x90);
- 		pci_dev_put(pdev_0);
--	}
--	else
-+	} else
- 		freq = inl(io_base + 0x90);
- 	return freq;
- }
-diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c
-index 842fe08..5b8586d 100644
---- a/drivers/ata/pata_icside.c
-+++ b/drivers/ata/pata_icside.c
-@@ -224,6 +224,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
- 	struct pata_icside_state *state = ap->host->private_data;
- 	struct scatterlist *sg, *rsg = state->sg;
- 	unsigned int write = qc->tf.flags & ATA_TFLAG_WRITE;
-+	unsigned int si;
+ 
+-	/* By this time the vty-server won't be getting any more interrups */
++	/* By this time the vty-server won't be getting any more interrupts */
+ 
+ 	spin_lock_irqsave(&hvcsd->lock, flags);
+ 
+ 	tty = hvcsd->tty;
+ 
+-	kobjp = &hvcsd->kobj;
+-
+ 	spin_unlock_irqrestore(&hvcsd->lock, flags);
  
  	/*
- 	 * We are simplex; BUG if we try to fiddle with DMA
-@@ -234,7 +235,7 @@ static void pata_icside_bmdma_setup(struct ata_queued_cmd *qc)
- 	/*
- 	 * Copy ATAs scattered sg list into a contiguous array of sg
+ 	 * Let the last holder of this object cause it to be removed, which
+ 	 * would probably be tty_hangup below.
  	 */
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		memcpy(rsg, sg, sizeof(*sg));
- 		rsg++;
- 	}
-diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c
-index ca9aae0..109ddd4 100644
---- a/drivers/ata/pata_it821x.c
-+++ b/drivers/ata/pata_it821x.c
-@@ -430,7 +430,7 @@ static unsigned int it821x_smart_qc_issue_prot(struct ata_queued_cmd *qc)
- 			return ata_qc_issue_prot(qc);
- 	}
- 	printk(KERN_DEBUG "it821x: can't process command 0x%02X\n", qc->tf.command);
--	return AC_ERR_INVALID;
-+	return AC_ERR_DEV;
- }
+-	kobject_put (kobjp);
++	kref_put(&hvcsd->kref, destroy_hvcs_struct);
  
- /**
-@@ -516,6 +516,37 @@ static void it821x_dev_config(struct ata_device *adev)
- 			printk("(%dK stripe)", adev->id[146]);
- 		printk(".\n");
- 	}
-+	/* This is a controller firmware triggered funny, don't
-+	   report the drive faulty! */
-+	adev->horkage &= ~ATA_HORKAGE_DIAGNOSTIC;
-+}
-+
-+/**
-+ *	it821x_ident_hack	-	Hack identify data up
-+ *	@ap: Port
-+ *
-+ *	Walk the devices on this firmware driven port and slightly
-+ *	mash the identify data to stop us and common tools trying to
-+ *	use features not firmware supported. The firmware itself does
-+ *	some masking (eg SMART) but not enough.
-+ *
-+ *	This is a bit of an abuse of the cable method, but it is the
-+ *	only method called at the right time. We could modify the libata
-+ *	core specifically for ident hacking but while we have one offender
-+ *	it seems better to keep the fallout localised.
-+ */
-+
-+static int it821x_ident_hack(struct ata_port *ap)
-+{
-+	struct ata_device *adev;
-+	ata_link_for_each_dev(adev, &ap->link) {
-+		if (ata_dev_enabled(adev)) {
-+			adev->id[84] &= ~(1 << 6);	/* No FUA */
-+			adev->id[85] &= ~(1 << 10);	/* No HPA */
-+			adev->id[76] = 0;		/* No NCQ/AN etc */
-+		}
-+	}
-+	return ata_cable_unknown(ap);
+ 	/*
+ 	 * The hangup is a scheduled function which will auto chain call
+@@ -1086,7 +1072,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
  }
  
+ /*
+- * This always increments the kobject ref count if the call is successful.
++ * This always increments the kref ref count if the call is successful.
+  * Please remember to dec when you are done with the instance.
+  *
+  * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when
+@@ -1103,7 +1089,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
+ 		list_for_each_entry(hvcsd, &hvcs_structs, next) {
+ 			spin_lock_irqsave(&hvcsd->lock, flags);
+ 			if (hvcsd->index == index) {
+-				kobject_get(&hvcsd->kobj);
++				kref_get(&hvcsd->kref);
+ 				spin_unlock_irqrestore(&hvcsd->lock, flags);
+ 				spin_unlock(&hvcs_structs_lock);
+ 				return hvcsd;
+@@ -1129,14 +1115,13 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
+ 	unsigned int irq;
+ 	struct vio_dev *vdev;
+ 	unsigned long unit_address;
+-	struct kobject *kobjp;
  
-@@ -634,7 +665,7 @@ static struct ata_port_operations it821x_smart_port_ops = {
- 	.thaw		= ata_bmdma_thaw,
- 	.error_handler	= ata_bmdma_error_handler,
- 	.post_internal_cmd = ata_bmdma_post_internal_cmd,
--	.cable_detect	= ata_cable_unknown,
-+	.cable_detect	= it821x_ident_hack,
+ 	if (tty->driver_data)
+ 		goto fast_open;
  
- 	.bmdma_setup 	= ata_bmdma_setup,
- 	.bmdma_start 	= ata_bmdma_start,
-diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c
-index 120b5bf..030878f 100644
---- a/drivers/ata/pata_ixp4xx_cf.c
-+++ b/drivers/ata/pata_ixp4xx_cf.c
-@@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
+ 	/*
+ 	 * Is there a vty-server that shares the same index?
+-	 * This function increments the kobject index.
++	 * This function increments the kref index.
+ 	 */
+ 	if (!(hvcsd = hvcs_get_by_index(tty->index))) {
+ 		printk(KERN_WARNING "HVCS: open failed, no device associated"
+@@ -1181,7 +1166,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
+ 	 * and will grab the spinlock and free the connection if it fails.
+ 	 */
+ 	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
+-		kobject_put(&hvcsd->kobj);
++		kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ 		printk(KERN_WARNING "HVCS: enable device failed.\n");
+ 		return rc;
+ 	}
+@@ -1192,17 +1177,11 @@ fast_open:
+ 	hvcsd = tty->driver_data;
+ 
+ 	spin_lock_irqsave(&hvcsd->lock, flags);
+-	if (!kobject_get(&hvcsd->kobj)) {
+-		spin_unlock_irqrestore(&hvcsd->lock, flags);
+-		printk(KERN_ERR "HVCS: Kobject of open"
+-			" hvcs doesn't exist.\n");
+-		return -EFAULT; /* Is this the right return value? */
+-	}
+-
++	kref_get(&hvcsd->kref);
+ 	hvcsd->open_count++;
+-
+ 	hvcsd->todo_mask |= HVCS_SCHED_READ;
+ 	spin_unlock_irqrestore(&hvcsd->lock, flags);
++
+ open_success:
+ 	hvcs_kick();
+ 
+@@ -1212,9 +1191,8 @@ open_success:
  	return 0;
- }
  
--static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
--				unsigned int buflen, int write_data)
-+static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
-+				unsigned char *buf, unsigned int buflen, int rw)
+ error_release:
+-	kobjp = &hvcsd->kobj;
+ 	spin_unlock_irqrestore(&hvcsd->lock, flags);
+-	kobject_put(&hvcsd->kobj);
++	kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ 
+ 	printk(KERN_WARNING "HVCS: partner connect failed.\n");
+ 	return retval;
+@@ -1224,7 +1202,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
  {
- 	unsigned int i;
- 	unsigned int words = buflen >> 1;
- 	u16 *buf16 = (u16 *) buf;
--	struct ata_port *ap = adev->link->ap;
-+	struct ata_port *ap = dev->link->ap;
- 	void __iomem *mmio = ap->ioaddr.data_addr;
- 	struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
+ 	struct hvcs_struct *hvcsd;
+ 	unsigned long flags;
+-	struct kobject *kobjp;
+ 	int irq = NO_IRQ;
  
-@@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
- 	udelay(100);
+ 	/*
+@@ -1245,7 +1222,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
+ 	hvcsd = tty->driver_data;
  
- 	/* Transfer multiple of 2 bytes */
--	if (write_data) {
--		for (i = 0; i < words; i++)
--			writew(buf16[i], mmio);
--	} else {
-+	if (rw == READ)
- 		for (i = 0; i < words; i++)
- 			buf16[i] = readw(mmio);
--	}
-+	else
-+		for (i = 0; i < words; i++)
-+			writew(buf16[i], mmio);
+ 	spin_lock_irqsave(&hvcsd->lock, flags);
+-	kobjp = &hvcsd->kobj;
+ 	if (--hvcsd->open_count == 0) {
  
- 	/* Transfer trailing 1 byte, if any. */
- 	if (unlikely(buflen & 0x01)) {
- 		u16 align_buf[1] = { 0 };
- 		unsigned char *trailing_buf = buf + buflen - 1;
+ 		vio_disable_interrupts(hvcsd->vdev);
+@@ -1270,7 +1246,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
+ 		tty->driver_data = NULL;
  
--		if (write_data) {
--			memcpy(align_buf, trailing_buf, 1);
--			writew(align_buf[0], mmio);
--		} else {
-+		if (rw == READ) {
- 			align_buf[0] = readw(mmio);
- 			memcpy(trailing_buf, align_buf, 1);
-+		} else {
-+			memcpy(align_buf, trailing_buf, 1);
-+			writew(align_buf[0], mmio);
- 		}
-+		words++;
+ 		free_irq(irq, hvcsd);
+-		kobject_put(kobjp);
++		kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ 		return;
+ 	} else if (hvcsd->open_count < 0) {
+ 		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
+@@ -1279,7 +1255,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
  	}
  
- 	udelay(100);
- 	*data->cs0_cfg |= 0x01;
-+
-+	return words << 1;
+ 	spin_unlock_irqrestore(&hvcsd->lock, flags);
+-	kobject_put(kobjp);
++	kref_put(&hvcsd->kref, destroy_hvcs_struct);
  }
  
- static struct scsi_host_template ixp4xx_sht = {
-diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
-index 17159b5..333dc15 100644
---- a/drivers/ata/pata_legacy.c
-+++ b/drivers/ata/pata_legacy.c
-@@ -28,7 +28,6 @@
-  *
-  *  Unsupported but docs exist:
-  *	Appian/Adaptec AIC25VL01/Cirrus Logic PD7220
-- *	Winbond W83759A
-  *
-  *  This driver handles legacy (that is "ISA/VLB side") IDE ports found
-  *  on PC class systems. There are three hybrid devices that are exceptions
-@@ -36,7 +35,7 @@
-  *  the MPIIX where the tuning is PCI side but the IDE is "ISA side".
-  *
-  *  Specific support is included for the ht6560a/ht6560b/opti82c611a/
-- *  opti82c465mv/promise 20230c/20630
-+ *  opti82c465mv/promise 20230c/20630/winbond83759A
-  *
-  *  Use the autospeed and pio_mask options with:
-  *	Appian ADI/2 aka CLPD7220 or AIC25VL01.
-@@ -47,9 +46,6 @@
-  *  For now use autospeed and pio_mask as above with the W83759A. This may
-  *  change.
-  *
-- *  TODO
-- *	Merge existing pata_qdi driver
-- *
-  */
+ static void hvcs_hangup(struct tty_struct * tty)
+@@ -1287,21 +1263,17 @@ static void hvcs_hangup(struct tty_struct * tty)
+ 	struct hvcs_struct *hvcsd = tty->driver_data;
+ 	unsigned long flags;
+ 	int temp_open_count;
+-	struct kobject *kobjp;
+ 	int irq = NO_IRQ;
  
- #include <linux/kernel.h>
-@@ -64,12 +60,13 @@
- #include <linux/platform_device.h>
+ 	spin_lock_irqsave(&hvcsd->lock, flags);
+-	/* Preserve this so that we know how many kobject refs to put */
++	/* Preserve this so that we know how many kref refs to put */
+ 	temp_open_count = hvcsd->open_count;
  
- #define DRV_NAME "pata_legacy"
--#define DRV_VERSION "0.5.5"
-+#define DRV_VERSION "0.6.5"
+ 	/*
+-	 * Don't kobject put inside the spinlock because the destruction
++	 * Don't kref put inside the spinlock because the destruction
+ 	 * callback may use the spinlock and it may get called before the
+-	 * spinlock has been released.  Get a pointer to the kobject and
+-	 * kobject_put on that after releasing the spinlock.
++	 * spinlock has been released.
+ 	 */
+-	kobjp = &hvcsd->kobj;
+-
+ 	vio_disable_interrupts(hvcsd->vdev);
  
- #define NR_HOST 6
+ 	hvcsd->todo_mask = 0;
+@@ -1324,7 +1296,7 @@ static void hvcs_hangup(struct tty_struct * tty)
+ 	free_irq(irq, hvcsd);
  
--static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
--static int legacy_irq[NR_HOST] = { 14, 15, 11, 10, 8, 12 };
-+static int all;
-+module_param(all, int, 0444);
-+MODULE_PARM_DESC(all, "Grab all legacy port devices, even if PCI(0=off, 1=on)");
+ 	/*
+-	 * We need to kobject_put() for every open_count we have since the
++	 * We need to kref_put() for every open_count we have since the
+ 	 * tty_hangup() function doesn't invoke a close per open connection on a
+ 	 * non-console device.
+ 	 */
+@@ -1335,7 +1307,7 @@ static void hvcs_hangup(struct tty_struct * tty)
+ 		 * NOTE:  If this hangup was signaled from user space then the
+ 		 * final put will never happen.
+ 		 */
+-		kobject_put(kobjp);
++		kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ 	}
+ }
  
- struct legacy_data {
- 	unsigned long timing;
-@@ -80,21 +77,107 @@ struct legacy_data {
+diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
+index 2d7cd48..6bbd4fa 100644
+--- a/drivers/char/hw_random/Kconfig
++++ b/drivers/char/hw_random/Kconfig
+@@ -98,7 +98,7 @@ config HW_RANDOM_PASEMI
+ 	default HW_RANDOM
+ 	---help---
+ 	  This driver provides kernel-side support for the Random Number
+-	  Generator hardware found on PA6T-1682M processor.
++	  Generator hardware found on PA Semi PWRficient SoCs.
  
- };
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called pasemi-rng.
+diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
+index 556fd81..c422e87 100644
+--- a/drivers/char/hw_random/amd-rng.c
++++ b/drivers/char/hw_random/amd-rng.c
+@@ -28,6 +28,7 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/hw_random.h>
++#include <linux/delay.h>
+ #include <asm/io.h>
  
-+enum controller {
-+	BIOS = 0,
-+	SNOOP = 1,
-+	PDC20230 = 2,
-+	HT6560A = 3,
-+	HT6560B = 4,
-+	OPTI611A = 5,
-+	OPTI46X = 6,
-+	QDI6500 = 7,
-+	QDI6580 = 8,
-+	QDI6580DP = 9,		/* Dual channel mode is different */
-+	W83759A = 10,
-+
-+	UNKNOWN = -1
-+};
-+
-+
-+struct legacy_probe {
-+	unsigned char *name;
-+	unsigned long port;
-+	unsigned int irq;
-+	unsigned int slot;
-+	enum controller type;
-+	unsigned long private;
-+};
-+
-+struct legacy_controller {
-+	const char *name;
-+	struct ata_port_operations *ops;
-+	unsigned int pio_mask;
-+	unsigned int flags;
-+	int (*setup)(struct platform_device *, struct legacy_probe *probe,
-+		struct legacy_data *data);
-+};
-+
-+static int legacy_port[NR_HOST] = { 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 };
-+
-+static struct legacy_probe probe_list[NR_HOST];
- static struct legacy_data legacy_data[NR_HOST];
- static struct ata_host *legacy_host[NR_HOST];
- static int nr_legacy_host;
  
+@@ -52,11 +53,18 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
+ static struct pci_dev *amd_pdev;
  
--static int probe_all;			/* Set to check all ISA port ranges */
--static int ht6560a;			/* HT 6560A on primary 1, secondary 2, both 3 */
--static int ht6560b;			/* HT 6560A on primary 1, secondary 2, both 3 */
--static int opti82c611a;			/* Opti82c611A on primary 1, secondary 2, both 3 */
--static int opti82c46x;			/* Opti 82c465MV present (pri/sec autodetect) */
--static int autospeed;			/* Chip present which snoops speed changes */
--static int pio_mask = 0x1F;		/* PIO range for autospeed devices */
-+static int probe_all;		/* Set to check all ISA port ranges */
-+static int ht6560a;		/* HT 6560A on primary 1, second 2, both 3 */
-+static int ht6560b;		/* HT 6560A on primary 1, second 2, both 3 */
-+static int opti82c611a;		/* Opti82c611A on primary 1, sec 2, both 3 */
-+static int opti82c46x;		/* Opti 82c465MV present(pri/sec autodetect) */
-+static int qdi;			/* Set to probe QDI controllers */
-+static int winbond;		/* Set to probe Winbond controllers,
-+					give I/O port if non stdanard */
-+static int autospeed;		/* Chip present which snoops speed changes */
-+static int pio_mask = 0x1F;	/* PIO range for autospeed devices */
- static int iordy_mask = 0xFFFFFFFF;	/* Use iordy if available */
  
- /**
-+ *	legacy_probe_add	-	Add interface to probe list
-+ *	@port: Controller port
-+ *	@irq: IRQ number
-+ *	@type: Controller type
-+ *	@private: Controller specific info
-+ *
-+ *	Add an entry into the probe list for ATA controllers. This is used
-+ *	to add the default ISA slots and then to build up the table
-+ *	further according to other ISA/VLB/Weird device scans
-+ *
-+ *	An I/O port list is used to keep ordering stable and sane, as we
-+ *	don't have any good way to talk about ordering otherwise
-+ */
-+
-+static int legacy_probe_add(unsigned long port, unsigned int irq,
-+				enum controller type, unsigned long private)
-+{
-+	struct legacy_probe *lp = &probe_list[0];
-+	int i;
-+	struct legacy_probe *free = NULL;
-+
-+	for (i = 0; i < NR_HOST; i++) {
-+		if (lp->port == 0 && free == NULL)
-+			free = lp;
-+		/* Matching port, or the correct slot for ordering */
-+		if (lp->port == port || legacy_port[i] == port) {
-+			free = lp;
+-static int amd_rng_data_present(struct hwrng *rng)
++static int amd_rng_data_present(struct hwrng *rng, int wait)
+ {
+ 	u32 pmbase = (u32)rng->priv;
++	int data, i;
+ 
+-      	return !!(inl(pmbase + 0xF4) & 1);
++	for (i = 0; i < 20; i++) {
++		data = !!(inl(pmbase + 0xF4) & 1);
++		if (data || !wait)
 +			break;
-+		}
-+		lp++;
-+	}
-+	if (free == NULL) {
-+		printk(KERN_ERR "pata_legacy: Too many interfaces.\n");
-+		return -1;
++		udelay(10);
 +	}
-+	/* Fill in the entry for later probing */
-+	free->port = port;
-+	free->irq = irq;
-+	free->type = type;
-+	free->private = private;
-+	return 0;
-+}
-+
-+
-+/**
-  *	legacy_set_mode		-	mode setting
-  *	@link: IDE link
-  *	@unused: Device that failed when error is returned
-@@ -113,7 +196,8 @@ static int legacy_set_mode(struct ata_link *link, struct ata_device **unused)
++	return data;
+ }
  
- 	ata_link_for_each_dev(dev, link) {
- 		if (ata_dev_enabled(dev)) {
--			ata_dev_printk(dev, KERN_INFO, "configured for PIO\n");
-+			ata_dev_printk(dev, KERN_INFO,
-+						"configured for PIO\n");
- 			dev->pio_mode = XFER_PIO_0;
- 			dev->xfer_mode = XFER_PIO_0;
- 			dev->xfer_shift = ATA_SHIFT_PIO;
-@@ -171,7 +255,7 @@ static struct ata_port_operations simple_port_ops = {
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+ static int amd_rng_data_read(struct hwrng *rng, u32 *data)
+diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
+index 26a860a..84cdf90 100644
+--- a/drivers/char/hw_random/core.c
++++ b/drivers/char/hw_random/core.c
+@@ -66,11 +66,11 @@ static inline void hwrng_cleanup(struct hwrng *rng)
+ 		rng->cleanup(rng);
+ }
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
- };
+-static inline int hwrng_data_present(struct hwrng *rng)
++static inline int hwrng_data_present(struct hwrng *rng, int wait)
+ {
+ 	if (!rng->data_present)
+ 		return 1;
+-	return rng->data_present(rng);
++	return rng->data_present(rng, wait);
+ }
  
- static struct ata_port_operations legacy_port_ops = {
-@@ -198,15 +282,16 @@ static struct ata_port_operations legacy_port_ops = {
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+ static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
+@@ -94,8 +94,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+ {
+ 	u32 data;
+ 	ssize_t ret = 0;
+-	int i, err = 0;
+-	int data_present;
++	int err = 0;
+ 	int bytes_read;
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
- };
+ 	while (size) {
+@@ -107,21 +106,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
+ 			err = -ENODEV;
+ 			goto out;
+ 		}
+-		if (filp->f_flags & O_NONBLOCK) {
+-			data_present = hwrng_data_present(current_rng);
+-		} else {
+-			/* Some RNG require some time between data_reads to gather
+-			 * new entropy. Poll it.
+-			 */
+-			for (i = 0; i < 20; i++) {
+-				data_present = hwrng_data_present(current_rng);
+-				if (data_present)
+-					break;
+-				udelay(10);
+-			}
+-		}
++
+ 		bytes_read = 0;
+-		if (data_present)
++		if (hwrng_data_present(current_rng,
++				       !(filp->f_flags & O_NONBLOCK)))
+ 			bytes_read = hwrng_data_read(current_rng, &data);
+ 		mutex_unlock(&rng_mutex);
  
- /*
-  *	Promise 20230C and 20620 support
-  *
-- *	This controller supports PIO0 to PIO2. We set PIO timings conservatively to
-- *	allow for 50MHz Vesa Local Bus. The 20620 DMA support is weird being DMA to
-- *	controller and PIO'd to the host and not supported.
-+ *	This controller supports PIO0 to PIO2. We set PIO timings
-+ *	conservatively to allow for 50MHz Vesa Local Bus. The 20620 DMA
-+ *	support is weird being DMA to controller and PIO'd to the host
-+ *	and not supported.
-  */
+@@ -246,11 +234,11 @@ static DEVICE_ATTR(rng_available, S_IRUGO,
+ 		   NULL);
  
- static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
-@@ -221,8 +306,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
- 	local_irq_save(flags);
  
- 	/* Unlock the control interface */
--	do
--	{
-+	do {
- 		inb(0x1F5);
- 		outb(inb(0x1F2) | 0x80, 0x1F2);
- 		inb(0x1F2);
-@@ -231,7 +315,7 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
- 		inb(0x1F2);
- 		inb(0x1F2);
+-static void unregister_miscdev(void)
++static void unregister_miscdev(bool suspended)
+ {
+ 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
+ 	device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
+-	misc_deregister(&rng_miscdev);
++	__misc_deregister(&rng_miscdev, suspended);
+ }
+ 
+ static int register_miscdev(void)
+@@ -325,7 +313,7 @@ out:
+ }
+ EXPORT_SYMBOL_GPL(hwrng_register);
+ 
+-void hwrng_unregister(struct hwrng *rng)
++void __hwrng_unregister(struct hwrng *rng, bool suspended)
+ {
+ 	int err;
+ 
+@@ -344,11 +332,11 @@ void hwrng_unregister(struct hwrng *rng)
+ 		}
  	}
--	while((inb(0x1F2) & 0x80) && --tries);
-+	while ((inb(0x1F2) & 0x80) && --tries);
+ 	if (list_empty(&rng_list))
+-		unregister_miscdev();
++		unregister_miscdev(suspended);
  
- 	local_irq_restore(flags);
+ 	mutex_unlock(&rng_mutex);
+ }
+-EXPORT_SYMBOL_GPL(hwrng_unregister);
++EXPORT_SYMBOL_GPL(__hwrng_unregister);
  
-@@ -249,13 +333,14 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
  
+ MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
+diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
+index 8e8658d..fed4ef5 100644
+--- a/drivers/char/hw_random/geode-rng.c
++++ b/drivers/char/hw_random/geode-rng.c
+@@ -28,6 +28,7 @@
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+ #include <linux/hw_random.h>
++#include <linux/delay.h>
+ #include <asm/io.h>
+ 
+ 
+@@ -61,11 +62,18 @@ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
+ 	return 4;
  }
  
--static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
-+static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
-+			unsigned char *buf, unsigned int buflen, int rw)
+-static int geode_rng_data_present(struct hwrng *rng)
++static int geode_rng_data_present(struct hwrng *rng, int wait)
  {
--	struct ata_port *ap = adev->link->ap;
--	int slop = buflen & 3;
--	unsigned long flags;
-+	if (ata_id_has_dword_io(dev->id)) {
-+		struct ata_port *ap = dev->link->ap;
-+		int slop = buflen & 3;
-+		unsigned long flags;
+ 	void __iomem *mem = (void __iomem *)rng->priv;
++	int data, i;
  
--	if (ata_id_has_dword_io(adev->id)) {
- 		local_irq_save(flags);
+-	return !!(readl(mem + GEODE_RNG_STATUS_REG));
++	for (i = 0; i < 20; i++) {
++		data = !!(readl(mem + GEODE_RNG_STATUS_REG));
++		if (data || !wait)
++			break;
++		udelay(10);
++	}
++	return data;
+ }
  
- 		/* Perform the 32bit I/O synchronization sequence */
-@@ -264,26 +349,27 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig
- 		ioread8(ap->ioaddr.nsect_addr);
  
- 		/* Now the data */
--
--		if (write_data)
--			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
--		else
-+		if (rw == READ)
- 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-+		else
-+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
+index 753f460..5cc651e 100644
+--- a/drivers/char/hw_random/intel-rng.c
++++ b/drivers/char/hw_random/intel-rng.c
+@@ -29,6 +29,7 @@
+ #include <linux/module.h>
+ #include <linux/pci.h>
+ #include <linux/stop_machine.h>
++#include <linux/delay.h>
+ #include <asm/io.h>
  
- 		if (unlikely(slop)) {
--			__le32 pad = 0;
--			if (write_data) {
--				memcpy(&pad, buf + buflen - slop, slop);
--				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
--			} else {
-+			u32 pad;
-+			if (rw == READ) {
- 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- 				memcpy(buf + buflen - slop, &pad, slop);
-+			} else {
-+				memcpy(&pad, buf + buflen - slop, slop);
-+				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
- 			}
-+			buflen += 4 - slop;
- 		}
- 		local_irq_restore(flags);
--	}
--	else
--		ata_data_xfer_noirq(adev, buf, buflen, write_data);
-+	} else
-+		buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
+ 
+@@ -162,11 +163,19 @@ static inline u8 hwstatus_set(void __iomem *mem,
+ 	return hwstatus_get(mem);
+ }
+ 
+-static int intel_rng_data_present(struct hwrng *rng)
++static int intel_rng_data_present(struct hwrng *rng, int wait)
+ {
+ 	void __iomem *mem = (void __iomem *)rng->priv;
+-
+-	return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
++	int data, i;
 +
-+	return buflen;
++	for (i = 0; i < 20; i++) {
++		data = !!(readb(mem + INTEL_RNG_STATUS) &
++			  INTEL_RNG_DATA_PRESENT);
++		if (data || !wait)
++			break;
++		udelay(10);
++	}
++	return data;
  }
  
- static struct ata_port_operations pdc20230_port_ops = {
-@@ -310,14 +396,14 @@ static struct ata_port_operations pdc20230_port_ops = {
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+ static int intel_rng_data_read(struct hwrng *rng, u32 *data)
+diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
+index 3f35a1c..7e31995 100644
+--- a/drivers/char/hw_random/omap-rng.c
++++ b/drivers/char/hw_random/omap-rng.c
+@@ -29,6 +29,7 @@
+ #include <linux/err.h>
+ #include <linux/platform_device.h>
+ #include <linux/hw_random.h>
++#include <linux/delay.h>
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
- };
+ #include <asm/io.h>
  
- /*
-  *	Holtek 6560A support
-  *
-- *	This controller supports PIO0 to PIO2 (no IORDY even though higher timings
-- *	can be loaded).
-+ *	This controller supports PIO0 to PIO2 (no IORDY even though higher
-+ *	timings can be loaded).
-  */
+@@ -65,9 +66,17 @@ static void omap_rng_write_reg(int reg, u32 val)
+ }
  
- static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
-@@ -364,14 +450,14 @@ static struct ata_port_operations ht6560a_port_ops = {
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+ /* REVISIT: Does the status bit really work on 16xx? */
+-static int omap_rng_data_present(struct hwrng *rng)
++static int omap_rng_data_present(struct hwrng *rng, int wait)
+ {
+-	return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
++	int data, i;
++
++	for (i = 0; i < 20; i++) {
++		data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
++		if (data || !wait)
++			break;
++		udelay(10);
++	}
++	return data;
+ }
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
- };
+ static int omap_rng_data_read(struct hwrng *rng, u32 *data)
+diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
+index fa6040b..6d50e9b 100644
+--- a/drivers/char/hw_random/pasemi-rng.c
++++ b/drivers/char/hw_random/pasemi-rng.c
+@@ -23,6 +23,7 @@
+ #include <linux/kernel.h>
+ #include <linux/platform_device.h>
+ #include <linux/hw_random.h>
++#include <linux/delay.h>
+ #include <asm/of_platform.h>
+ #include <asm/io.h>
  
- /*
-  *	Holtek 6560B support
-  *
-- *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO setting
-- *	unless we see an ATAPI device in which case we force it off.
-+ *	This controller supports PIO0 to PIO4. We honour the BIOS/jumper FIFO
-+ *	setting unless we see an ATAPI device in which case we force it off.
-  *
-  *	FIXME: need to implement 2nd channel support.
-  */
-@@ -398,7 +484,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
- 	if (adev->class != ATA_DEV_ATA) {
- 		u8 rconf = inb(0x3E6);
- 		if (rconf & 0x24) {
--			rconf &= ~ 0x24;
-+			rconf &= ~0x24;
- 			outb(rconf, 0x3E6);
- 		}
- 	}
-@@ -423,13 +509,13 @@ static struct ata_port_operations ht6560b_port_ops = {
- 	.qc_prep 	= ata_qc_prep,
- 	.qc_issue	= ata_qc_issue_prot,
+@@ -41,12 +42,19 @@
  
--	.data_xfer	= ata_data_xfer,	/* FIXME: Check 32bit and noirq */
-+	.data_xfer	= ata_data_xfer,    /* FIXME: Check 32bit and noirq */
+ #define MODULE_NAME "pasemi_rng"
  
- 	.irq_handler	= ata_interrupt,
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+-static int pasemi_rng_data_present(struct hwrng *rng)
++static int pasemi_rng_data_present(struct hwrng *rng, int wait)
+ {
+ 	void __iomem *rng_regs = (void __iomem *)rng->priv;
+-
+-	return (in_le32(rng_regs + SDCRNG_CTL_REG)
+-		& SDCRNG_CTL_FVLD_M) ? 1 : 0;
++	int data, i;
++
++	for (i = 0; i < 20; i++) {
++		data = (in_le32(rng_regs + SDCRNG_CTL_REG)
++			& SDCRNG_CTL_FVLD_M) ? 1 : 0;
++		if (data || !wait)
++			break;
++		udelay(10);
++	}
++	return data;
+ }
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
+ static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
+@@ -126,10 +134,9 @@ static int __devexit rng_remove(struct of_device *dev)
+ }
+ 
+ static struct of_device_id rng_match[] = {
+-	{
+-		.compatible      = "1682m-rng",
+-	},
+-	{},
++	{ .compatible      = "1682m-rng", },
++	{ .compatible      = "pasemi,pwrficient-rng", },
++	{ },
  };
  
- /*
-@@ -462,7 +548,8 @@ static u8 opti_syscfg(u8 reg)
-  *	This controller supports PIO0 to PIO3.
-  */
+ static struct of_platform_driver rng_driver = {
+diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
+index ec435cb..868e39f 100644
+--- a/drivers/char/hw_random/via-rng.c
++++ b/drivers/char/hw_random/via-rng.c
+@@ -27,6 +27,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/hw_random.h>
++#include <linux/delay.h>
+ #include <asm/io.h>
+ #include <asm/msr.h>
+ #include <asm/cpufeature.h>
+@@ -77,10 +78,11 @@ static inline u32 xstore(u32 *addr, u32 edx_in)
+ 	return eax_out;
+ }
  
--static void opti82c611a_set_piomode(struct ata_port *ap, struct ata_device *adev)
-+static void opti82c611a_set_piomode(struct ata_port *ap,
-+						struct ata_device *adev)
+-static int via_rng_data_present(struct hwrng *rng)
++static int via_rng_data_present(struct hwrng *rng, int wait)
  {
- 	u8 active, recover, setup;
- 	struct ata_timing t;
-@@ -549,7 +636,7 @@ static struct ata_port_operations opti82c611a_port_ops = {
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+ 	u32 bytes_out;
+ 	u32 *via_rng_datum = (u32 *)(&rng->priv);
++	int i;
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
- };
+ 	/* We choose the recommended 1-byte-per-instruction RNG rate,
+ 	 * for greater randomness at the expense of speed.  Larger
+@@ -95,12 +97,15 @@ static int via_rng_data_present(struct hwrng *rng)
+ 	 * completes.
+ 	 */
  
- /*
-@@ -681,77 +768,398 @@ static struct ata_port_operations opti82c46x_port_ops = {
- 	.irq_clear	= ata_bmdma_irq_clear,
- 	.irq_on		= ata_irq_on,
+-	*via_rng_datum = 0; /* paranoia, not really necessary */
+-	bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
+-	bytes_out &= VIA_XSTORE_CNT_MASK;
+-	if (bytes_out == 0)
+-		return 0;
+-	return 1;
++	for (i = 0; i < 20; i++) {
++		*via_rng_datum = 0; /* paranoia, not really necessary */
++		bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
++		bytes_out &= VIA_XSTORE_CNT_MASK;
++		if (bytes_out || !wait)
++			break;
++		udelay(10);
++	}
++	return bytes_out ? 1 : 0;
+ }
  
--	.port_start	= ata_port_start,
-+	.port_start	= ata_sff_port_start,
- };
+ static int via_rng_data_read(struct hwrng *rng, u32 *data)
+diff --git a/drivers/char/misc.c b/drivers/char/misc.c
+index 71c8cd7..a39101f 100644
+--- a/drivers/char/misc.c
++++ b/drivers/char/misc.c
+@@ -232,8 +232,9 @@ int misc_register(struct miscdevice * misc)
+ }
  
-+static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
-+{
-+	struct ata_timing t;
-+	struct legacy_data *qdi = ap->host->private_data;
-+	int active, recovery;
-+	u8 timing;
+ /**
+- *	misc_deregister - unregister a miscellaneous device
++ *	__misc_deregister - unregister a miscellaneous device
+  *	@misc: device to unregister
++ *	@suspended: to be set if the function is used during suspend/resume
+  *
+  *	Unregister a miscellaneous device that was previously
+  *	successfully registered with misc_register(). Success
+@@ -241,7 +242,7 @@ int misc_register(struct miscdevice * misc)
+  *	indicates an error.
+  */
+ 
+-int misc_deregister(struct miscdevice * misc)
++int __misc_deregister(struct miscdevice *misc, bool suspended)
+ {
+ 	int i = misc->minor;
+ 
+@@ -250,7 +251,11 @@ int misc_deregister(struct miscdevice * misc)
+ 
+ 	mutex_lock(&misc_mtx);
+ 	list_del(&misc->list);
+-	device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
++	if (suspended)
++		destroy_suspended_device(misc_class,
++					MKDEV(MISC_MAJOR, misc->minor));
++	else
++		device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
+ 	if (i < DYNAMIC_MINORS && i>0) {
+ 		misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
+ 	}
+@@ -259,7 +264,7 @@ int misc_deregister(struct miscdevice * misc)
+ }
+ 
+ EXPORT_SYMBOL(misc_register);
+-EXPORT_SYMBOL(misc_deregister);
++EXPORT_SYMBOL(__misc_deregister);
+ 
+ static int __init misc_init(void)
+ {
+diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
+index 82f2e27..ff146c2 100644
+--- a/drivers/char/mspec.c
++++ b/drivers/char/mspec.c
+@@ -283,7 +283,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma,
+ 	vdata->refcnt = ATOMIC_INIT(1);
+ 	vma->vm_private_data = vdata;
+ 
+-	vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP);
++	vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND);
+ 	if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED)
+ 		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ 	vma->vm_ops = &mspec_vm_ops;
+diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
+new file mode 100644
+index 0000000..dfaab23
+--- /dev/null
++++ b/drivers/char/nozomi.c
+@@ -0,0 +1,1941 @@
++/*
++ * nozomi.c  -- HSDPA driver Broadband Wireless Data Card - Globe Trotter
++ *
++ * Written by: Ulf Jakobsson,
++ *             Jan Åkerfeldt,
++ *             Stefan Thomasson,
++ *
++ * Maintained by: Paul Hardwick (p.hardwick at option.com)
++ *
++ * Patches:
++ *          Locking code changes for Vodafone by Sphere Systems Ltd,
++ *                              Andrew Bird (ajb at spheresystems.co.uk )
++ *                              & Phil Sanderson
++ *
++ * Source has been ported from an implementation made by Filip Aben @ Option
++ *
++ * --------------------------------------------------------------------------
++ *
++ * Copyright (c) 2005,2006 Option Wireless Sweden AB
++ * Copyright (c) 2006 Sphere Systems Ltd
++ * Copyright (c) 2006 Option Wireless n/v
++ * All rights Reserved.
++ *
++ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ *
++ * --------------------------------------------------------------------------
++ */
++
++/* Enable this to have a lot of debug printouts */
++#define DEBUG
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/ioport.h>
++#include <linux/tty.h>
++#include <linux/tty_driver.h>
++#include <linux/tty_flip.h>
++#include <linux/serial.h>
++#include <linux/interrupt.h>
++#include <linux/kmod.h>
++#include <linux/init.h>
++#include <linux/kfifo.h>
++#include <linux/uaccess.h>
++#include <asm/byteorder.h>
++
++#include <linux/delay.h>
++
++
++#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \
++					__DATE__ " " __TIME__ ")"
++
++/*    Macros definitions */
++
++/* Default debug printout level */
++#define NOZOMI_DEBUG_LEVEL 0x00
++
++#define P_BUF_SIZE 128
++#define NFO(_err_flag_, args...)				\
++do {								\
++	char tmp[P_BUF_SIZE];					\
++	snprintf(tmp, sizeof(tmp), ##args);			\
++	printk(_err_flag_ "[%d] %s(): %s\n", __LINE__,		\
++		__FUNCTION__, tmp);				\
++} while (0)
++
++#define DBG1(args...) D_(0x01, ##args)
++#define DBG2(args...) D_(0x02, ##args)
++#define DBG3(args...) D_(0x04, ##args)
++#define DBG4(args...) D_(0x08, ##args)
++#define DBG5(args...) D_(0x10, ##args)
++#define DBG6(args...) D_(0x20, ##args)
++#define DBG7(args...) D_(0x40, ##args)
++#define DBG8(args...) D_(0x80, ##args)
++
++#ifdef DEBUG
++/* Do we need this settable at runtime? */
++static int debug = NOZOMI_DEBUG_LEVEL;
++
++#define D(lvl, args...)  do \
++			{if (lvl & debug) NFO(KERN_DEBUG, ##args); } \
++			while (0)
++#define D_(lvl, args...) D(lvl, ##args)
++
++/* These printouts are always printed */
++
++#else
++static int debug;
++#define D_(lvl, args...)
++#endif
++
++/* TODO: rewrite to optimize macros... */
++
++#define TMP_BUF_MAX 256
++
++#define DUMP(buf__,len__) \
++  do {  \
++    char tbuf[TMP_BUF_MAX] = {0};\
++    if (len__ > 1) {\
++	snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\
++	if (tbuf[len__-2] == '\r') {\
++		tbuf[len__-2] = 'r';\
++	} \
++	DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\
++    } else {\
++	DBG1("SENDING: '%s' (%d)", tbuf, len__);\
++    } \
++} while (0)
++
++/*    Defines */
++#define NOZOMI_NAME		"nozomi"
++#define NOZOMI_NAME_TTY		"nozomi_tty"
++#define DRIVER_DESC		"Nozomi driver"
++
++#define NTTY_TTY_MAXMINORS	256
++#define NTTY_FIFO_BUFFER_SIZE	8192
++
++/* Must be power of 2 */
++#define FIFO_BUFFER_SIZE_UL	8192
++
++/* Size of tmp send buffer to card */
++#define SEND_BUF_MAX		1024
++#define RECEIVE_BUF_MAX		4
++
++
++/* Define all types of vendors and devices to support */
++#define VENDOR1		0x1931	/* Vendor Option */
++#define DEVICE1		0x000c	/* HSDPA card */
 +
-+	/* Get the timing data in cycles */
-+	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
++#define R_IIR		0x0000	/* Interrupt Identity Register */
++#define R_FCR		0x0000	/* Flow Control Register */
++#define R_IER		0x0004	/* Interrupt Enable Register */
 +
-+	if (qdi->fast) {
-+		active = 8 - FIT(t.active, 1, 8);
-+		recovery = 18 - FIT(t.recover, 3, 18);
-+	} else {
-+		active = 9 - FIT(t.active, 2, 9);
-+		recovery = 15 - FIT(t.recover, 0, 15);
-+	}
-+	timing = (recovery << 4) | active | 0x08;
++#define CONFIG_MAGIC	0xEFEFFEFE
++#define TOGGLE_VALID	0x0000
 +
-+	qdi->clock[adev->devno] = timing;
++/* Definition of interrupt tokens */
++#define MDM_DL1		0x0001
++#define MDM_UL1		0x0002
++#define MDM_DL2		0x0004
++#define MDM_UL2		0x0008
++#define DIAG_DL1	0x0010
++#define DIAG_DL2	0x0020
++#define DIAG_UL		0x0040
++#define APP1_DL		0x0080
++#define APP1_UL		0x0100
++#define APP2_DL		0x0200
++#define APP2_UL		0x0400
++#define CTRL_DL		0x0800
++#define CTRL_UL		0x1000
++#define RESET		0x8000
 +
-+	outb(timing, qdi->timing);
-+}
- 
- /**
-- *	legacy_init_one		-	attach a legacy interface
-- *	@port: port number
-- *	@io: I/O port start
-- *	@ctrl: control port
-+ *	qdi6580dp_set_piomode		-	PIO setup for dual channel
-+ *	@ap: Port
-+ *	@adev: Device
-  *	@irq: interrupt line
-  *
-- *	Register an ISA bus IDE interface. Such interfaces are PIO and we
-- *	assume do not support IRQ sharing.
-+ *	In dual channel mode the 6580 has one clock per channel and we have
-+ *	to software clockswitch in qc_issue_prot.
-  */
- 
--static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl, int irq)
-+static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
- {
--	struct legacy_data *ld = &legacy_data[nr_legacy_host];
--	struct ata_host *host;
--	struct ata_port *ap;
--	struct platform_device *pdev;
--	struct ata_port_operations *ops = &legacy_port_ops;
--	void __iomem *io_addr, *ctrl_addr;
--	int pio_modes = pio_mask;
--	u32 mask = (1 << port);
--	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
--	int ret;
-+	struct ata_timing t;
-+	struct legacy_data *qdi = ap->host->private_data;
-+	int active, recovery;
-+	u8 timing;
- 
--	pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0);
--	if (IS_ERR(pdev))
--		return PTR_ERR(pdev);
-+	/* Get the timing data in cycles */
-+	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
++#define MDM_DL		(MDM_DL1  | MDM_DL2)
++#define MDM_UL		(MDM_UL1  | MDM_UL2)
++#define DIAG_DL		(DIAG_DL1 | DIAG_DL2)
 +
-+	if (qdi->fast) {
-+		active = 8 - FIT(t.active, 1, 8);
-+		recovery = 18 - FIT(t.recover, 3, 18);
-+	} else {
-+		active = 9 - FIT(t.active, 2, 9);
-+		recovery = 15 - FIT(t.recover, 0, 15);
-+	}
-+	timing = (recovery << 4) | active | 0x08;
- 
--	ret = -EBUSY;
--	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
--	    devm_request_region(&pdev->dev, ctrl, 1, "pata_legacy") == NULL)
--		goto fail;
-+	qdi->clock[adev->devno] = timing;
- 
--	ret = -ENOMEM;
--	io_addr = devm_ioport_map(&pdev->dev, io, 8);
--	ctrl_addr = devm_ioport_map(&pdev->dev, ctrl, 1);
--	if (!io_addr || !ctrl_addr)
--		goto fail;
-+	outb(timing, qdi->timing + 2 * ap->port_no);
-+	/* Clear the FIFO */
-+	if (adev->class != ATA_DEV_ATA)
-+		outb(0x5F, qdi->timing + 3);
-+}
- 
--	if (ht6560a & mask) {
--		ops = &ht6560a_port_ops;
--		pio_modes = 0x07;
--		iordy = ATA_FLAG_NO_IORDY;
--	}
--	if (ht6560b & mask) {
--		ops = &ht6560b_port_ops;
--		pio_modes = 0x1F;
--	}
--	if (opti82c611a & mask) {
--		ops = &opti82c611a_port_ops;
--		pio_modes = 0x0F;
-+/**
-+ *	qdi6580_set_piomode		-	PIO setup for single channel
-+ *	@ap: Port
-+ *	@adev: Device
-+ *
-+ *	In single channel mode the 6580 has one clock per device and we can
-+ *	avoid the requirement to clock switch. We also have to load the timing
-+ *	into the right clock according to whether we are master or slave.
-+ */
++/* modem signal definition */
++#define CTRL_DSR	0x0001
++#define CTRL_DCD	0x0002
++#define CTRL_RI		0x0004
++#define CTRL_CTS	0x0008
 +
-+static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
-+{
-+	struct ata_timing t;
-+	struct legacy_data *qdi = ap->host->private_data;
-+	int active, recovery;
-+	u8 timing;
++#define CTRL_DTR	0x0001
++#define CTRL_RTS	0x0002
 +
-+	/* Get the timing data in cycles */
-+	ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
++#define MAX_PORT		4
++#define NOZOMI_MAX_PORTS	5
++#define NOZOMI_MAX_CARDS	(NTTY_TTY_MAXMINORS / MAX_PORT)
 +
-+	if (qdi->fast) {
-+		active = 8 - FIT(t.active, 1, 8);
-+		recovery = 18 - FIT(t.recover, 3, 18);
-+	} else {
-+		active = 9 - FIT(t.active, 2, 9);
-+		recovery = 15 - FIT(t.recover, 0, 15);
- 	}
--	if (opti82c46x & mask) {
--		ops = &opti82c46x_port_ops;
--		pio_modes = 0x0F;
-+	timing = (recovery << 4) | active | 0x08;
-+	qdi->clock[adev->devno] = timing;
-+	outb(timing, qdi->timing + 2 * adev->devno);
-+	/* Clear the FIFO */
-+	if (adev->class != ATA_DEV_ATA)
-+		outb(0x5F, qdi->timing + 3);
-+}
++/*    Type definitions */
 +
-+/**
-+ *	qdi_qc_issue_prot	-	command issue
-+ *	@qc: command pending
-+ *
-+ *	Called when the libata layer is about to issue a command. We wrap
-+ *	this interface so that we can load the correct ATA timings.
++/*
++ * There are two types of nozomi cards,
++ * one with 2048 memory and with 8192 memory
 + */
++enum card_type {
++	F32_2 = 2048,	/* 512 bytes downlink + uplink * 2 -> 2048 */
++	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
++};
 +
-+static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
-+{
-+	struct ata_port *ap = qc->ap;
-+	struct ata_device *adev = qc->dev;
-+	struct legacy_data *qdi = ap->host->private_data;
++/* Two different toggle channels exist */
++enum channel_type {
++	CH_A = 0,
++	CH_B = 1,
++};
 +
-+	if (qdi->clock[adev->devno] != qdi->last) {
-+		if (adev->pio_mode) {
-+			qdi->last = qdi->clock[adev->devno];
-+			outb(qdi->clock[adev->devno], qdi->timing +
-+							2 * ap->port_no);
-+		}
- 	}
-+	return ata_qc_issue_prot(qc);
-+}
- 
--	/* Probe for automatically detectable controllers */
-+static unsigned int vlb32_data_xfer(struct ata_device *adev, unsigned char *buf,
-+					unsigned int buflen, int rw)
-+{
-+	struct ata_port *ap = adev->link->ap;
-+	int slop = buflen & 3;
- 
--	if (io == 0x1F0 && ops == &legacy_port_ops) {
--		unsigned long flags;
-+	if (ata_id_has_dword_io(adev->id)) {
-+		if (rw == WRITE)
-+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-+		else
-+			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- 
--		local_irq_save(flags);
-+		if (unlikely(slop)) {
-+			u32 pad;
-+			if (rw == WRITE) {
-+				memcpy(&pad, buf + buflen - slop, slop);
-+				pad = le32_to_cpu(pad);
-+				iowrite32(pad, ap->ioaddr.data_addr);
-+			} else {
-+				pad = ioread32(ap->ioaddr.data_addr);
-+				pad = cpu_to_le32(pad);
-+				memcpy(buf + buflen - slop, &pad, slop);
-+			}
-+		}
-+		return (buflen + 3) & ~3;
-+	} else
-+		return ata_data_xfer(adev, buf, buflen, rw);
-+}
++/* Port definition for the card regarding flow control */
++enum ctrl_port_type {
++	CTRL_CMD	= 0,
++	CTRL_MDM	= 1,
++	CTRL_DIAG	= 2,
++	CTRL_APP1	= 3,
++	CTRL_APP2	= 4,
++	CTRL_ERROR	= -1,
++};
 +
-+static int qdi_port(struct platform_device *dev,
-+			struct legacy_probe *lp, struct legacy_data *ld)
-+{
-+	if (devm_request_region(&dev->dev, lp->private, 4, "qdi") == NULL)
-+		return -EBUSY;
-+	ld->timing = lp->private;
-+	return 0;
-+}
++/* Ports that the nozomi has */
++enum port_type {
++	PORT_MDM	= 0,
++	PORT_DIAG	= 1,
++	PORT_APP1	= 2,
++	PORT_APP2	= 3,
++	PORT_CTRL	= 4,
++	PORT_ERROR	= -1,
++};
 +
-+static struct ata_port_operations qdi6500_port_ops = {
-+	.set_piomode	= qdi6500_set_piomode,
++#ifdef __BIG_ENDIAN
++/* Big endian */
 +
-+	.tf_load	= ata_tf_load,
-+	.tf_read	= ata_tf_read,
-+	.check_status 	= ata_check_status,
-+	.exec_command	= ata_exec_command,
-+	.dev_select 	= ata_std_dev_select,
++struct toggles {
++	unsigned int enabled:5;	/*
++				 * Toggle fields are valid if enabled is 0,
++				 * else A-channels must always be used.
++				 */
++	unsigned int diag_dl:1;
++	unsigned int mdm_dl:1;
++	unsigned int mdm_ul:1;
++} __attribute__ ((packed));
 +
-+	.freeze		= ata_bmdma_freeze,
-+	.thaw		= ata_bmdma_thaw,
-+	.error_handler	= ata_bmdma_error_handler,
-+	.post_internal_cmd = ata_bmdma_post_internal_cmd,
-+	.cable_detect	= ata_cable_40wire,
++/* Configuration table to read at startup of card */
++/* Is for now only needed during initialization phase */
++struct config_table {
++	u32 signature;
++	u16 product_information;
++	u16 version;
++	u8 pad3[3];
++	struct toggles toggle;
++	u8 pad1[4];
++	u16 dl_mdm_len1;	/*
++				 * If this is 64, it can hold
++				 * 60 bytes + 4 that is length field
++				 */
++	u16 dl_start;
 +
-+	.qc_prep 	= ata_qc_prep,
-+	.qc_issue	= qdi_qc_issue_prot,
++	u16 dl_diag_len1;
++	u16 dl_mdm_len2;	/*
++				 * If this is 64, it can hold
++				 * 60 bytes + 4 that is length field
++				 */
++	u16 dl_app1_len;
 +
-+	.data_xfer	= vlb32_data_xfer,
++	u16 dl_diag_len2;
++	u16 dl_ctrl_len;
++	u16 dl_app2_len;
++	u8 pad2[16];
++	u16 ul_mdm_len1;
++	u16 ul_start;
++	u16 ul_diag_len;
++	u16 ul_mdm_len2;
++	u16 ul_app1_len;
++	u16 ul_app2_len;
++	u16 ul_ctrl_len;
++} __attribute__ ((packed));
 +
-+	.irq_handler	= ata_interrupt,
-+	.irq_clear	= ata_bmdma_irq_clear,
-+	.irq_on		= ata_irq_on,
++/* This stores all control downlink flags */
++struct ctrl_dl {
++	u8 port;
++	unsigned int reserved:4;
++	unsigned int CTS:1;
++	unsigned int RI:1;
++	unsigned int DCD:1;
++	unsigned int DSR:1;
++} __attribute__ ((packed));
 +
-+	.port_start	= ata_sff_port_start,
-+};
++/* This stores all control uplink flags */
++struct ctrl_ul {
++	u8 port;
++	unsigned int reserved:6;
++	unsigned int RTS:1;
++	unsigned int DTR:1;
++} __attribute__ ((packed));
 +
-+static struct ata_port_operations qdi6580_port_ops = {
-+	.set_piomode	= qdi6580_set_piomode,
++#else
++/* Little endian */
 +
-+	.tf_load	= ata_tf_load,
-+	.tf_read	= ata_tf_read,
-+	.check_status 	= ata_check_status,
-+	.exec_command	= ata_exec_command,
-+	.dev_select 	= ata_std_dev_select,
++/* This represents the toggle information */
++struct toggles {
++	unsigned int mdm_ul:1;
++	unsigned int mdm_dl:1;
++	unsigned int diag_dl:1;
++	unsigned int enabled:5;	/*
++				 * Toggle fields are valid if enabled is 0,
++				 * else A-channels must always be used.
++				 */
++} __attribute__ ((packed));
 +
-+	.freeze		= ata_bmdma_freeze,
-+	.thaw		= ata_bmdma_thaw,
-+	.error_handler	= ata_bmdma_error_handler,
-+	.post_internal_cmd = ata_bmdma_post_internal_cmd,
-+	.cable_detect	= ata_cable_40wire,
++/* Configuration table to read at startup of card */
++struct config_table {
++	u32 signature;
++	u16 version;
++	u16 product_information;
++	struct toggles toggle;
++	u8 pad1[7];
++	u16 dl_start;
++	u16 dl_mdm_len1;	/*
++				 * If this is 64, it can hold
++				 * 60 bytes + 4 that is length field
++				 */
++	u16 dl_mdm_len2;
++	u16 dl_diag_len1;
++	u16 dl_diag_len2;
++	u16 dl_app1_len;
++	u16 dl_app2_len;
++	u16 dl_ctrl_len;
++	u8 pad2[16];
++	u16 ul_start;
++	u16 ul_mdm_len2;
++	u16 ul_mdm_len1;
++	u16 ul_diag_len;
++	u16 ul_app1_len;
++	u16 ul_app2_len;
++	u16 ul_ctrl_len;
++} __attribute__ ((packed));
 +
-+	.qc_prep 	= ata_qc_prep,
-+	.qc_issue	= ata_qc_issue_prot,
++/* This stores all control downlink flags */
++struct ctrl_dl {
++	unsigned int DSR:1;
++	unsigned int DCD:1;
++	unsigned int RI:1;
++	unsigned int CTS:1;
++	unsigned int reserverd:4;
++	u8 port;
++} __attribute__ ((packed));
 +
-+	.data_xfer	= vlb32_data_xfer,
++/* This stores all control uplink flags */
++struct ctrl_ul {
++	unsigned int DTR:1;
++	unsigned int RTS:1;
++	unsigned int reserved:6;
++	u8 port;
++} __attribute__ ((packed));
++#endif
 +
-+	.irq_handler	= ata_interrupt,
-+	.irq_clear	= ata_bmdma_irq_clear,
-+	.irq_on		= ata_irq_on,
++/* This holds all information that is needed regarding a port */
++struct port {
++	u8 update_flow_control;
++	struct ctrl_ul ctrl_ul;
++	struct ctrl_dl ctrl_dl;
++	struct kfifo *fifo_ul;
++	void __iomem *dl_addr[2];
++	u32 dl_size[2];
++	u8 toggle_dl;
++	void __iomem *ul_addr[2];
++	u32 ul_size[2];
++	u8 toggle_ul;
++	u16 token_dl;
 +
-+	.port_start	= ata_sff_port_start,
++	struct tty_struct *tty;
++	int tty_open_count;
++	/* mutex to ensure one access patch to this port */
++	struct mutex tty_sem;
++	wait_queue_head_t tty_wait;
++	struct async_icount tty_icount;
 +};
 +
-+static struct ata_port_operations qdi6580dp_port_ops = {
-+	.set_piomode	= qdi6580dp_set_piomode,
++/* Private data one for each card in the system */
++struct nozomi {
++	void __iomem *base_addr;
++	unsigned long flip;
 +
-+	.tf_load	= ata_tf_load,
-+	.tf_read	= ata_tf_read,
-+	.check_status 	= ata_check_status,
-+	.exec_command	= ata_exec_command,
-+	.dev_select 	= ata_std_dev_select,
++	/* Pointers to registers */
++	void __iomem *reg_iir;
++	void __iomem *reg_fcr;
++	void __iomem *reg_ier;
 +
-+	.freeze		= ata_bmdma_freeze,
-+	.thaw		= ata_bmdma_thaw,
-+	.error_handler	= ata_bmdma_error_handler,
-+	.post_internal_cmd = ata_bmdma_post_internal_cmd,
-+	.cable_detect	= ata_cable_40wire,
++	u16 last_ier;
++	enum card_type card_type;
++	struct config_table config_table;	/* Configuration table */
++	struct pci_dev *pdev;
++	struct port port[NOZOMI_MAX_PORTS];
++	u8 *send_buf;
 +
-+	.qc_prep 	= ata_qc_prep,
-+	.qc_issue	= qdi_qc_issue_prot,
++	spinlock_t spin_mutex;	/* secures access to registers and tty */
 +
-+	.data_xfer	= vlb32_data_xfer,
++	unsigned int index_start;
++	u32 open_ttys;
++};
 +
-+	.irq_handler	= ata_interrupt,
-+	.irq_clear	= ata_bmdma_irq_clear,
-+	.irq_on		= ata_irq_on,
++/* This is a data packet that is read or written to/from card */
++struct buffer {
++	u32 size;		/* size is the length of the data buffer */
++	u8 *data;
++} __attribute__ ((packed));
 +
-+	.port_start	= ata_sff_port_start,
++/*    Global variables */
++static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
++	{PCI_DEVICE(VENDOR1, DEVICE1)},
++	{},
 +};
 +
-+static DEFINE_SPINLOCK(winbond_lock);
++MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
 +
-+static void winbond_writecfg(unsigned long port, u8 reg, u8 val)
-+{
-+	unsigned long flags;
-+	spin_lock_irqsave(&winbond_lock, flags);
-+	outb(reg, port + 0x01);
-+	outb(val, port + 0x02);
-+	spin_unlock_irqrestore(&winbond_lock, flags);
-+}
++static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
++static struct tty_driver *ntty_driver;
 +
-+static u8 winbond_readcfg(unsigned long port, u8 reg)
++/*
++ * find card by tty_index
++ */
++static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
 +{
-+	u8 val;
-+
-+	unsigned long flags;
-+	spin_lock_irqsave(&winbond_lock, flags);
-+	outb(reg, port + 0x01);
-+	val = inb(port + 0x02);
-+	spin_unlock_irqrestore(&winbond_lock, flags);
-+
-+	return val;
++	return tty ? ndevs[tty->index / MAX_PORT] : NULL;
 +}
 +
-+static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
++static inline struct port *get_port_by_tty(const struct tty_struct *tty)
 +{
-+	struct ata_timing t;
-+	struct legacy_data *winbond = ap->host->private_data;
-+	int active, recovery;
-+	u8 reg;
-+	int timing = 0x88 + (ap->port_no * 4) + (adev->devno * 2);
++	struct nozomi *ndev = get_dc_by_tty(tty);
++	return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL;
++}
 +
-+	reg = winbond_readcfg(winbond->timing, 0x81);
++/*
++ * TODO:
++ * -Optimize
++ * -Rewrite cleaner
++ */
 +
-+	/* Get the timing data in cycles */
-+	if (reg & 0x40)		/* Fast VLB bus, assume 50MHz */
-+		ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
-+	else
-+		ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
++static void read_mem32(u32 *buf, const void __iomem *mem_addr_start,
++			u32 size_bytes)
++{
++	u32 i = 0;
++	const u32 *ptr = (__force u32 *) mem_addr_start;
++	u16 *buf16;
 +
-+	active = (FIT(t.active, 3, 17) - 1) & 0x0F;
-+	recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
-+	timing = (active << 4) | recovery;
-+	winbond_writecfg(winbond->timing, timing, reg);
++	if (unlikely(!ptr || !buf))
++		goto out;
 +
-+	/* Load the setup timing */
++	/* shortcut for extremely often used cases */
++	switch (size_bytes) {
++	case 2:	/* 2 bytes */
++		buf16 = (u16 *) buf;
++		*buf16 = __le16_to_cpu(readw((void __iomem *)ptr));
++		goto out;
++		break;
++	case 4:	/* 4 bytes */
++		*(buf) = __le32_to_cpu(readl((void __iomem *)ptr));
++		goto out;
++		break;
++	}
 +
-+	reg = 0x35;
-+	if (adev->class != ATA_DEV_ATA)
-+		reg |= 0x08;	/* FIFO off */
-+	if (!ata_pio_need_iordy(adev))
-+		reg |= 0x02;	/* IORDY off */
-+	reg |= (FIT(t.setup, 0, 3) << 6);
-+	winbond_writecfg(winbond->timing, timing + 1, reg);
++	while (i < size_bytes) {
++		if (size_bytes - i == 2) {
++			/* Handle 2 bytes in the end */
++			buf16 = (u16 *) buf;
++			*(buf16) = __le16_to_cpu(readw((void __iomem *)ptr));
++			i += 2;
++		} else {
++			/* Read 4 bytes */
++			*(buf) = __le32_to_cpu(readl((void __iomem *)ptr));
++			i += 4;
++		}
++		buf++;
++		ptr++;
++	}
++out:
++	return;
 +}
 +
-+static int winbond_port(struct platform_device *dev,
-+			struct legacy_probe *lp, struct legacy_data *ld)
++/*
++ * TODO:
++ * -Optimize
++ * -Rewrite cleaner
++ */
++static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf,
++			u32 size_bytes)
 +{
-+	if (devm_request_region(&dev->dev, lp->private, 4, "winbond") == NULL)
-+		return -EBUSY;
-+	ld->timing = lp->private;
-+	return 0;
++	u32 i = 0;
++	u32 *ptr = (__force u32 *) mem_addr_start;
++	const u16 *buf16;
++
++	if (unlikely(!ptr || !buf))
++		return 0;
++
++	/* shortcut for extremely often used cases */
++	switch (size_bytes) {
++	case 2:	/* 2 bytes */
++		buf16 = (const u16 *)buf;
++		writew(__cpu_to_le16(*buf16), (void __iomem *)ptr);
++		return 2;
++		break;
++	case 1: /*
++		 * also needs to write 4 bytes in this case
++		 * so falling through..
++		 */
++	case 4: /* 4 bytes */
++		writel(__cpu_to_le32(*buf), (void __iomem *)ptr);
++		return 4;
++		break;
++	}
++
++	while (i < size_bytes) {
++		if (size_bytes - i == 2) {
++			/* 2 bytes */
++			buf16 = (const u16 *)buf;
++			writew(__cpu_to_le16(*buf16), (void __iomem *)ptr);
++			i += 2;
++		} else {
++			/* 4 bytes */
++			writel(__cpu_to_le32(*buf), (void __iomem *)ptr);
++			i += 4;
++		}
++		buf++;
++		ptr++;
++	}
++	return i;
 +}
 +
-+static struct ata_port_operations winbond_port_ops = {
-+	.set_piomode	= winbond_set_piomode,
++/* Setup pointers to different channels and also setup buffer sizes. */
++static void setup_memory(struct nozomi *dc)
++{
++	void __iomem *offset = dc->base_addr + dc->config_table.dl_start;
++	/* The length reported is including the length field of 4 bytes,
++	 * hence subtract with 4.
++	 */
++	const u16 buff_offset = 4;
 +
-+	.tf_load	= ata_tf_load,
-+	.tf_read	= ata_tf_read,
-+	.check_status 	= ata_check_status,
-+	.exec_command	= ata_exec_command,
-+	.dev_select 	= ata_std_dev_select,
++	/* Modem port dl configuration */
++	dc->port[PORT_MDM].dl_addr[CH_A] = offset;
++	dc->port[PORT_MDM].dl_addr[CH_B] =
++				(offset += dc->config_table.dl_mdm_len1);
++	dc->port[PORT_MDM].dl_size[CH_A] =
++				dc->config_table.dl_mdm_len1 - buff_offset;
++	dc->port[PORT_MDM].dl_size[CH_B] =
++				dc->config_table.dl_mdm_len2 - buff_offset;
 +
-+	.freeze		= ata_bmdma_freeze,
-+	.thaw		= ata_bmdma_thaw,
-+	.error_handler	= ata_bmdma_error_handler,
-+	.post_internal_cmd = ata_bmdma_post_internal_cmd,
-+	.cable_detect	= ata_cable_40wire,
++	/* Diag port dl configuration */
++	dc->port[PORT_DIAG].dl_addr[CH_A] =
++				(offset += dc->config_table.dl_mdm_len2);
++	dc->port[PORT_DIAG].dl_size[CH_A] =
++				dc->config_table.dl_diag_len1 - buff_offset;
++	dc->port[PORT_DIAG].dl_addr[CH_B] =
++				(offset += dc->config_table.dl_diag_len1);
++	dc->port[PORT_DIAG].dl_size[CH_B] =
++				dc->config_table.dl_diag_len2 - buff_offset;
 +
-+	.qc_prep 	= ata_qc_prep,
-+	.qc_issue	= ata_qc_issue_prot,
++	/* App1 port dl configuration */
++	dc->port[PORT_APP1].dl_addr[CH_A] =
++				(offset += dc->config_table.dl_diag_len2);
++	dc->port[PORT_APP1].dl_size[CH_A] =
++				dc->config_table.dl_app1_len - buff_offset;
 +
-+	.data_xfer	= vlb32_data_xfer,
++	/* App2 port dl configuration */
++	dc->port[PORT_APP2].dl_addr[CH_A] =
++				(offset += dc->config_table.dl_app1_len);
++	dc->port[PORT_APP2].dl_size[CH_A] =
++				dc->config_table.dl_app2_len - buff_offset;
 +
-+	.irq_clear	= ata_bmdma_irq_clear,
-+	.irq_on		= ata_irq_on,
- 
-+	.port_start	= ata_sff_port_start,
-+};
++	/* Ctrl dl configuration */
++	dc->port[PORT_CTRL].dl_addr[CH_A] =
++				(offset += dc->config_table.dl_app2_len);
++	dc->port[PORT_CTRL].dl_size[CH_A] =
++				dc->config_table.dl_ctrl_len - buff_offset;
 +
-+static struct legacy_controller controllers[] = {
-+	{"BIOS",	&legacy_port_ops, 	0x1F,
-+						ATA_FLAG_NO_IORDY,	NULL },
-+	{"Snooping", 	&simple_port_ops, 	0x1F,
-+						0	       ,	NULL },
-+	{"PDC20230",	&pdc20230_port_ops,	0x7,
-+						ATA_FLAG_NO_IORDY,	NULL },
-+	{"HT6560A",	&ht6560a_port_ops,	0x07,
-+						ATA_FLAG_NO_IORDY,	NULL },
-+	{"HT6560B",	&ht6560b_port_ops,	0x1F,
-+						ATA_FLAG_NO_IORDY,	NULL },
-+	{"OPTI82C611A",	&opti82c611a_port_ops,	0x0F,
-+						0	       ,	NULL },
-+	{"OPTI82C46X",	&opti82c46x_port_ops,	0x0F,
-+						0	       ,	NULL },
-+	{"QDI6500",	&qdi6500_port_ops,	0x07,
-+					ATA_FLAG_NO_IORDY,	qdi_port },
-+	{"QDI6580",	&qdi6580_port_ops,	0x1F,
-+					0	       ,	qdi_port },
-+	{"QDI6580DP",	&qdi6580dp_port_ops,	0x1F,
-+					0	       ,	qdi_port },
-+	{"W83759A",	&winbond_port_ops,	0x1F,
-+					0	       ,	winbond_port }
-+};
++	offset = dc->base_addr + dc->config_table.ul_start;
 +
-+/**
-+ *	probe_chip_type		-	Discover controller
-+ *	@probe: Probe entry to check
-+ *
-+ *	Probe an ATA port and identify the type of controller. We don't
-+ *	check if the controller appears to be driveless at this point.
-+ */
++	/* Modem Port ul configuration */
++	dc->port[PORT_MDM].ul_addr[CH_A] = offset;
++	dc->port[PORT_MDM].ul_size[CH_A] =
++				dc->config_table.ul_mdm_len1 - buff_offset;
++	dc->port[PORT_MDM].ul_addr[CH_B] =
++				(offset += dc->config_table.ul_mdm_len1);
++	dc->port[PORT_MDM].ul_size[CH_B] =
++				dc->config_table.ul_mdm_len2 - buff_offset;
 +
-+static __init int probe_chip_type(struct legacy_probe *probe)
-+{
-+	int mask = 1 << probe->slot;
++	/* Diag port ul configuration */
++	dc->port[PORT_DIAG].ul_addr[CH_A] =
++				(offset += dc->config_table.ul_mdm_len2);
++	dc->port[PORT_DIAG].ul_size[CH_A] =
++				dc->config_table.ul_diag_len - buff_offset;
 +
-+	if (winbond && (probe->port == 0x1F0 || probe->port == 0x170)) {
-+		u8 reg = winbond_readcfg(winbond, 0x81);
-+		reg |= 0x80;	/* jumpered mode off */
-+		winbond_writecfg(winbond, 0x81, reg);
-+		reg = winbond_readcfg(winbond, 0x83);
-+		reg |= 0xF0;	/* local control */
-+		winbond_writecfg(winbond, 0x83, reg);
-+		reg = winbond_readcfg(winbond, 0x85);
-+		reg |= 0xF0;	/* programmable timing */
-+		winbond_writecfg(winbond, 0x85, reg);
++	/* App1 port ul configuration */
++	dc->port[PORT_APP1].ul_addr[CH_A] =
++				(offset += dc->config_table.ul_diag_len);
++	dc->port[PORT_APP1].ul_size[CH_A] =
++				dc->config_table.ul_app1_len - buff_offset;
 +
-+		reg = winbond_readcfg(winbond, 0x81);
++	/* App2 port ul configuration */
++	dc->port[PORT_APP2].ul_addr[CH_A] =
++				(offset += dc->config_table.ul_app1_len);
++	dc->port[PORT_APP2].ul_size[CH_A] =
++				dc->config_table.ul_app2_len - buff_offset;
 +
-+		if (reg & mask)
-+			return W83759A;
-+	}
-+	if (probe->port == 0x1F0) {
-+		unsigned long flags;
-+		local_irq_save(flags);
- 		/* Probes */
--		inb(0x1F5);
- 		outb(inb(0x1F2) | 0x80, 0x1F2);
-+		inb(0x1F5);
- 		inb(0x1F2);
- 		inb(0x3F6);
- 		inb(0x3F6);
-@@ -760,29 +1168,83 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
- 
- 		if ((inb(0x1F2) & 0x80) == 0) {
- 			/* PDC20230c or 20630 ? */
--			printk(KERN_INFO "PDC20230-C/20630 VLB ATA controller detected.\n");
--				pio_modes = 0x07;
--			ops = &pdc20230_port_ops;
--			iordy = ATA_FLAG_NO_IORDY;
-+			printk(KERN_INFO  "PDC20230-C/20630 VLB ATA controller"
-+							" detected.\n");
- 			udelay(100);
- 			inb(0x1F5);
-+			local_irq_restore(flags);
-+			return PDC20230;
- 		} else {
- 			outb(0x55, 0x1F2);
- 			inb(0x1F2);
- 			inb(0x1F2);
--			if (inb(0x1F2) == 0x00) {
--				printk(KERN_INFO "PDC20230-B VLB ATA controller detected.\n");
--			}
-+			if (inb(0x1F2) == 0x00)
-+				printk(KERN_INFO "PDC20230-B VLB ATA "
-+						     "controller detected.\n");
-+			local_irq_restore(flags);
-+			return BIOS;
- 		}
- 		local_irq_restore(flags);
- 	}
- 
-+	if (ht6560a & mask)
-+		return HT6560A;
-+	if (ht6560b & mask)
-+		return HT6560B;
-+	if (opti82c611a & mask)
-+		return OPTI611A;
-+	if (opti82c46x & mask)
-+		return OPTI46X;
-+	if (autospeed & mask)
-+		return SNOOP;
-+	return BIOS;
++	/* Ctrl ul configuration */
++	dc->port[PORT_CTRL].ul_addr[CH_A] =
++				(offset += dc->config_table.ul_app2_len);
++	dc->port[PORT_CTRL].ul_size[CH_A] =
++				dc->config_table.ul_ctrl_len - buff_offset;
 +}
 +
++/* Dump config table under initalization phase */
++#ifdef DEBUG
++static void dump_table(const struct nozomi *dc)
++{
++	DBG3("signature: 0x%08X", dc->config_table.signature);
++	DBG3("version: 0x%04X", dc->config_table.version);
++	DBG3("product_information: 0x%04X", \
++				dc->config_table.product_information);
++	DBG3("toggle enabled: %d", dc->config_table.toggle.enabled);
++	DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul);
++	DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl);
++	DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl);
 +
-+/**
-+ *	legacy_init_one		-	attach a legacy interface
-+ *	@pl: probe record
-+ *
-+ *	Register an ISA bus IDE interface. Such interfaces are PIO and we
-+ *	assume do not support IRQ sharing.
-+ */
++	DBG3("dl_start: 0x%04X", dc->config_table.dl_start);
++	DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1,
++	   dc->config_table.dl_mdm_len1);
++	DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2,
++	   dc->config_table.dl_mdm_len2);
++	DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1,
++	   dc->config_table.dl_diag_len1);
++	DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2,
++	   dc->config_table.dl_diag_len2);
++	DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len,
++	   dc->config_table.dl_app1_len);
++	DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len,
++	   dc->config_table.dl_app2_len);
++	DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len,
++	   dc->config_table.dl_ctrl_len);
++	DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start,
++	   dc->config_table.ul_start);
++	DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1,
++	   dc->config_table.ul_mdm_len1);
++	DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2,
++	   dc->config_table.ul_mdm_len2);
++	DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len,
++	   dc->config_table.ul_diag_len);
++	DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len,
++	   dc->config_table.ul_app1_len);
++	DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len,
++	   dc->config_table.ul_app2_len);
++	DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len,
++	   dc->config_table.ul_ctrl_len);
++}
++#else
++static inline void dump_table(const struct nozomi *dc) { }
++#endif
 +
-+static __init int legacy_init_one(struct legacy_probe *probe)
++/*
++ * Read configuration table from card under intalization phase
++ * Returns 1 if ok, else 0
++ */
++static int nozomi_read_config_table(struct nozomi *dc)
 +{
-+	struct legacy_controller *controller = &controllers[probe->type];
-+	int pio_modes = controller->pio_mask;
-+	unsigned long io = probe->port;
-+	u32 mask = (1 << probe->slot);
-+	struct ata_port_operations *ops = controller->ops;
-+	struct legacy_data *ld = &legacy_data[probe->slot];
-+	struct ata_host *host = NULL;
-+	struct ata_port *ap;
-+	struct platform_device *pdev;
-+	struct ata_device *dev;
-+	void __iomem *io_addr, *ctrl_addr;
-+	u32 iordy = (iordy_mask & mask) ? 0: ATA_FLAG_NO_IORDY;
-+	int ret;
- 
--	/* Chip does mode setting by command snooping */
--	if (ops == &legacy_port_ops && (autospeed & mask))
--		ops = &simple_port_ops;
-+	iordy |= controller->flags;
++	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
++						sizeof(struct config_table));
 +
-+	pdev = platform_device_register_simple(DRV_NAME, probe->slot, NULL, 0);
-+	if (IS_ERR(pdev))
-+		return PTR_ERR(pdev);
++	if (dc->config_table.signature != CONFIG_MAGIC) {
++		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
++			dc->config_table.signature, CONFIG_MAGIC);
++		return 0;
++	}
 +
-+	ret = -EBUSY;
-+	if (devm_request_region(&pdev->dev, io, 8, "pata_legacy") == NULL ||
-+	    devm_request_region(&pdev->dev, io + 0x0206, 1,
-+							"pata_legacy") == NULL)
-+		goto fail;
- 
- 	ret = -ENOMEM;
-+	io_addr = devm_ioport_map(&pdev->dev, io, 8);
-+	ctrl_addr = devm_ioport_map(&pdev->dev, io + 0x0206, 1);
-+	if (!io_addr || !ctrl_addr)
-+		goto fail;
-+	if (controller->setup)
-+		if (controller->setup(pdev, probe, ld) < 0)
-+			goto fail;
- 	host = ata_host_alloc(&pdev->dev, 1);
- 	if (!host)
- 		goto fail;
-@@ -795,19 +1257,29 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl
- 	ap->ioaddr.altstatus_addr = ctrl_addr;
- 	ap->ioaddr.ctl_addr = ctrl_addr;
- 	ata_std_ports(&ap->ioaddr);
--	ap->private_data = ld;
-+	ap->host->private_data = ld;
- 
--	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, ctrl);
-+	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io, io + 0x0206);
- 
--	ret = ata_host_activate(host, irq, ata_interrupt, 0, &legacy_sht);
-+	ret = ata_host_activate(host, probe->irq, ata_interrupt, 0,
-+								&legacy_sht);
- 	if (ret)
- 		goto fail;
--
--	legacy_host[nr_legacy_host++] = dev_get_drvdata(&pdev->dev);
- 	ld->platform_dev = pdev;
--	return 0;
- 
-+	/* Nothing found means we drop the port as its probably not there */
++	if ((dc->config_table.version == 0)
++	    || (dc->config_table.toggle.enabled == TOGGLE_VALID)) {
++		int i;
++		DBG1("Second phase, configuring card");
 +
-+	ret = -ENODEV;
-+	ata_link_for_each_dev(dev, &ap->link) {
-+		if (!ata_dev_absent(dev)) {
-+			legacy_host[probe->slot] = host;
-+			ld->platform_dev = pdev;
-+			return 0;
-+		}
-+	}
- fail:
-+	if (host)
-+		ata_host_detach(host);
- 	platform_device_unregister(pdev);
- 	return ret;
- }
-@@ -818,13 +1290,15 @@ fail:
-  *	@master: set this if we find an ATA master
-  *	@master: set this if we find an ATA secondary
-  *
-- *	A small number of vendors implemented early PCI ATA interfaces on bridge logic
-- *	without the ATA interface being PCI visible. Where we have a matching PCI driver
-- *	we must skip the relevant device here. If we don't know about it then the legacy
-- *	driver is the right driver anyway.
-+ *	A small number of vendors implemented early PCI ATA interfaces
-+ *	on bridge logic without the ATA interface being PCI visible.
-+ *	Where we have a matching PCI driver we must skip the relevant
-+ *	device here. If we don't know about it then the legacy driver
-+ *	is the right driver anyway.
-  */
- 
--static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *secondary)
-+static void __init legacy_check_special_cases(struct pci_dev *p, int *primary,
-+								int *secondary)
- {
- 	/* Cyrix CS5510 pre SFF MWDMA ATA on the bridge */
- 	if (p->vendor == 0x1078 && p->device == 0x0000) {
-@@ -840,7 +1314,8 @@ static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *sec
- 	if (p->vendor == 0x8086 && p->device == 0x1234) {
- 		u16 r;
- 		pci_read_config_word(p, 0x6C, &r);
--		if (r & 0x8000) {	/* ATA port enabled */
-+		if (r & 0x8000) {
-+			/* ATA port enabled */
- 			if (r & 0x4000)
- 				*secondary = 1;
- 			else
-@@ -850,6 +1325,114 @@ static void legacy_check_special_cases(struct pci_dev *p, int *primary, int *sec
- 	}
- }
- 
-+static __init void probe_opti_vlb(void)
-+{
-+	/* If an OPTI 82C46X is present find out where the channels are */
-+	static const char *optis[4] = {
-+		"3/463MV", "5MV",
-+		"5MVA", "5MVB"
-+	};
-+	u8 chans = 1;
-+	u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
++		setup_memory(dc);
 +
-+	opti82c46x = 3;	/* Assume master and slave first */
-+	printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n",
-+								optis[ctrl]);
-+	if (ctrl == 3)
-+		chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
-+	ctrl = opti_syscfg(0xAC);
-+	/* Check enabled and this port is the 465MV port. On the
-+	   MVB we may have two channels */
-+	if (ctrl & 8) {
-+		if (chans == 2) {
-+			legacy_probe_add(0x1F0, 14, OPTI46X, 0);
-+			legacy_probe_add(0x170, 15, OPTI46X, 0);
++		dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
++		dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
++		dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl;
++		DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d",
++		   dc->port[PORT_MDM].toggle_ul,
++		   dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl);
++
++		dump_table(dc);
++
++		for (i = PORT_MDM; i < MAX_PORT; i++) {
++			dc->port[i].fifo_ul =
++			    kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL);
++			memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
++			memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
 +		}
-+		if (ctrl & 4)
-+			legacy_probe_add(0x170, 15, OPTI46X, 0);
-+		else
-+			legacy_probe_add(0x1F0, 14, OPTI46X, 0);
-+	} else
-+		legacy_probe_add(0x1F0, 14, OPTI46X, 0);
-+}
 +
-+static __init void qdi65_identify_port(u8 r, u8 res, unsigned long port)
-+{
-+	static const unsigned long ide_port[2] = { 0x170, 0x1F0 };
-+	/* Check card type */
-+	if ((r & 0xF0) == 0xC0) {
-+		/* QD6500: single channel */
-+		if (r & 8)
-+			/* Disabled ? */
-+			return;
-+		legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
-+								QDI6500, port);
++		/* Enable control channel */
++		dc->last_ier = dc->last_ier | CTRL_DL;
++		writew(dc->last_ier, dc->reg_ier);
++
++		dev_info(&dc->pdev->dev, "Initialization OK!\n");
++		return 1;
 +	}
-+	if (((r & 0xF0) == 0xA0) || (r & 0xF0) == 0x50) {
-+		/* QD6580: dual channel */
-+		if (!request_region(port + 2 , 2, "pata_qdi")) {
-+			release_region(port, 2);
-+			return;
-+		}
-+		res = inb(port + 3);
-+		/* Single channel mode ? */
-+		if (res & 1)
-+			legacy_probe_add(ide_port[r & 0x01], 14 + (r & 0x01),
-+								QDI6580, port);
-+		else { /* Dual channel mode */
-+			legacy_probe_add(0x1F0, 14, QDI6580DP, port);
-+			/* port + 0x02, r & 0x04 */
-+			legacy_probe_add(0x170, 15, QDI6580DP, port + 2);
-+		}
-+		release_region(port + 2, 2);
++
++	if ((dc->config_table.version > 0)
++	    && (dc->config_table.toggle.enabled != TOGGLE_VALID)) {
++		u32 offset = 0;
++		DBG1("First phase: pushing upload buffers, clearing download");
++
++		dev_info(&dc->pdev->dev, "Version of card: %d\n",
++			 dc->config_table.version);
++
++		/* Here we should disable all I/O over F32. */
++		setup_memory(dc);
++
++		/*
++		 * We should send ALL channel pair tokens back along
++		 * with reset token
++		 */
++
++		/* push upload modem buffers */
++		write_mem32(dc->port[PORT_MDM].ul_addr[CH_A],
++			(u32 *) &offset, 4);
++		write_mem32(dc->port[PORT_MDM].ul_addr[CH_B],
++			(u32 *) &offset, 4);
++
++		writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr);
++
++		DBG1("First phase done");
 +	}
++
++	return 1;
 +}
 +
-+static __init void probe_qdi_vlb(void)
++/* Enable uplink interrupts  */
++static void enable_transmit_ul(enum port_type port, struct nozomi *dc)
 +{
-+	unsigned long flags;
-+	static const unsigned long qd_port[2] = { 0x30, 0xB0 };
-+	int i;
++	static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL};
 +
-+	/*
-+	 *	Check each possible QD65xx base address
-+	 */
++	if (port < NOZOMI_MAX_PORTS) {
++		dc->last_ier |= mask[port];
++		writew(dc->last_ier, dc->reg_ier);
++	} else {
++		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
++	}
++}
 +
-+	for (i = 0; i < 2; i++) {
-+		unsigned long port = qd_port[i];
-+		u8 r, res;
++/* Disable uplink interrupts  */
++static void disable_transmit_ul(enum port_type port, struct nozomi *dc)
++{
++	static const u16 mask[] =
++		{~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL};
 +
++	if (port < NOZOMI_MAX_PORTS) {
++		dc->last_ier &= mask[port];
++		writew(dc->last_ier, dc->reg_ier);
++	} else {
++		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
++	}
++}
 +
-+		if (request_region(port, 2, "pata_qdi")) {
-+			/* Check for a card */
-+			local_irq_save(flags);
-+			/* I have no h/w that needs this delay but it
-+			   is present in the historic code */
-+			r = inb(port);
-+			udelay(1);
-+			outb(0x19, port);
-+			udelay(1);
-+			res = inb(port);
-+			udelay(1);
-+			outb(r, port);
-+			udelay(1);
-+			local_irq_restore(flags);
++/* Enable downlink interrupts */
++static void enable_transmit_dl(enum port_type port, struct nozomi *dc)
++{
++	static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL};
 +
-+			/* Fail */
-+			if (res == 0x19) {
-+				release_region(port, 2);
-+				continue;
-+			}
-+			/* Passes the presence test */
-+			r = inb(port + 1);
-+			udelay(1);
-+			/* Check port agrees with port set */
-+			if ((r & 2) >> 1 == i)
-+				qdi65_identify_port(r, res, port);
-+			release_region(port, 2);
-+		}
++	if (port < NOZOMI_MAX_PORTS) {
++		dc->last_ier |= mask[port];
++		writew(dc->last_ier, dc->reg_ier);
++	} else {
++		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
 +	}
 +}
- 
- /**
-  *	legacy_init		-	attach legacy interfaces
-@@ -867,15 +1450,17 @@ static __init int legacy_init(void)
- 	int ct = 0;
- 	int primary = 0;
- 	int secondary = 0;
--	int last_port = NR_HOST;
-+	int pci_present = 0;
-+	struct legacy_probe *pl = &probe_list[0];
-+	int slot = 0;
- 
- 	struct pci_dev *p = NULL;
- 
- 	for_each_pci_dev(p) {
- 		int r;
--		/* Check for any overlap of the system ATA mappings. Native mode controllers
--		   stuck on these addresses or some devices in 'raid' mode won't be found by
--		   the storage class test */
-+		/* Check for any overlap of the system ATA mappings. Native
-+		   mode controllers stuck on these addresses or some devices
-+		   in 'raid' mode won't be found by the storage class test */
- 		for (r = 0; r < 6; r++) {
- 			if (pci_resource_start(p, r) == 0x1f0)
- 				primary = 1;
-@@ -885,49 +1470,39 @@ static __init int legacy_init(void)
- 		/* Check for special cases */
- 		legacy_check_special_cases(p, &primary, &secondary);
- 
--		/* If PCI bus is present then don't probe for tertiary legacy ports */
--		if (probe_all == 0)
--			last_port = 2;
-+		/* If PCI bus is present then don't probe for tertiary
-+		   legacy ports */
-+		pci_present = 1;
- 	}
- 
--	/* If an OPTI 82C46X is present find out where the channels are */
--	if (opti82c46x) {
--		static const char *optis[4] = {
--			"3/463MV", "5MV",
--			"5MVA", "5MVB"
--		};
--		u8 chans = 1;
--		u8 ctrl = (opti_syscfg(0x30) & 0xC0) >> 6;
--
--		opti82c46x = 3;	/* Assume master and slave first */
--		printk(KERN_INFO DRV_NAME ": Opti 82C46%s chipset support.\n", optis[ctrl]);
--		if (ctrl == 3)
--			chans = (opti_syscfg(0x3F) & 0x20) ? 2 : 1;
--		ctrl = opti_syscfg(0xAC);
--		/* Check enabled and this port is the 465MV port. On the
--		   MVB we may have two channels */
--		if (ctrl & 8) {
--			if (ctrl & 4)
--				opti82c46x = 2;	/* Slave */
--			else
--				opti82c46x = 1;	/* Master */
--			if (chans == 2)
--				opti82c46x = 3; /* Master and Slave */
--		}	/* Slave only */
--		else if (chans == 1)
--			opti82c46x = 1;
-+	if (winbond == 1)
-+		winbond = 0x130;	/* Default port, alt is 1B0 */
 +
-+	if (primary == 0 || all)
-+		legacy_probe_add(0x1F0, 14, UNKNOWN, 0);
-+	if (secondary == 0 || all)
-+		legacy_probe_add(0x170, 15, UNKNOWN, 0);
++/* Disable downlink interrupts */
++static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
++{
++	static const u16 mask[] =
++		{~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL};
 +
-+	if (probe_all || !pci_present) {
-+		/* ISA/VLB extra ports */
-+		legacy_probe_add(0x1E8, 11, UNKNOWN, 0);
-+		legacy_probe_add(0x168, 10, UNKNOWN, 0);
-+		legacy_probe_add(0x1E0, 8, UNKNOWN, 0);
-+		legacy_probe_add(0x160, 12, UNKNOWN, 0);
- 	}
- 
--	for (i = 0; i < last_port; i++) {
--		/* Skip primary if we have seen a PCI one */
--		if (i == 0 && primary == 1)
--			continue;
--		/* Skip secondary if we have seen a PCI one */
--		if (i == 1 && secondary == 1)
-+	if (opti82c46x)
-+		probe_opti_vlb();
-+	if (qdi)
-+		probe_qdi_vlb();
++	if (port < NOZOMI_MAX_PORTS) {
++		dc->last_ier &= mask[port];
++		writew(dc->last_ier, dc->reg_ier);
++	} else {
++		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
++	}
++}
 +
-+	for (i = 0; i < NR_HOST; i++, pl++) {
-+		if (pl->port == 0)
- 			continue;
--		if (legacy_init_one(i, legacy_port[i],
--				   legacy_port[i] + 0x0206,
--				   legacy_irq[i]) == 0)
-+		if (pl->type == UNKNOWN)
-+			pl->type = probe_chip_type(pl);
-+		pl->slot = slot++;
-+		if (legacy_init_one(pl) == 0)
- 			ct++;
- 	}
- 	if (ct != 0)
-@@ -941,11 +1516,8 @@ static __exit void legacy_exit(void)
- 
- 	for (i = 0; i < nr_legacy_host; i++) {
- 		struct legacy_data *ld = &legacy_data[i];
--
- 		ata_host_detach(legacy_host[i]);
- 		platform_device_unregister(ld->platform_dev);
--		if (ld->timing)
--			release_region(ld->timing, 2);
- 	}
- }
- 
-@@ -960,9 +1532,9 @@ module_param(ht6560a, int, 0);
- module_param(ht6560b, int, 0);
- module_param(opti82c611a, int, 0);
- module_param(opti82c46x, int, 0);
-+module_param(qdi, int, 0);
- module_param(pio_mask, int, 0);
- module_param(iordy_mask, int, 0);
- 
- module_init(legacy_init);
- module_exit(legacy_exit);
--
-diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
-index 50c56e2..5413ebf 100644
---- a/drivers/ata/pata_mpc52xx.c
-+++ b/drivers/ata/pata_mpc52xx.c
-@@ -364,7 +364,7 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match)
- {
- 	unsigned int ipb_freq;
- 	struct resource res_mem;
--	int ata_irq = NO_IRQ;
-+	int ata_irq;
- 	struct mpc52xx_ata __iomem *ata_regs;
- 	struct mpc52xx_ata_priv *priv;
- 	int rv;
-@@ -494,10 +494,8 @@ mpc52xx_ata_resume(struct of_device *op)
- 
- 
- static struct of_device_id mpc52xx_ata_of_match[] = {
--	{
--		.type		= "ata",
--		.compatible	= "mpc5200-ata",
--	},
-+	{ .compatible = "fsl,mpc5200-ata", },
-+	{ .compatible = "mpc5200-ata", },
- 	{},
- };
- 
-diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c
-new file mode 100644
-index 0000000..1c1b835
---- /dev/null
-+++ b/drivers/ata/pata_ninja32.c
-@@ -0,0 +1,214 @@
 +/*
-+ * pata_ninja32.c 	- Ninja32 PATA for new ATA layer
-+ *			  (C) 2007 Red Hat Inc
-+ *			  Alan Cox <alan at redhat.com>
-+ *
-+ * Note: The controller like many controllers has shared timings for
-+ * PIO and DMA. We thus flip to the DMA timings in dma_start and flip back
-+ * in the dma_stop function. Thus we actually don't need a set_dmamode
-+ * method as the PIO method is always called and will set the right PIO
-+ * timing parameters.
-+ *
-+ * The Ninja32 Cardbus is not a generic SFF controller. Instead it is
-+ * laid out as follows off BAR 0. This is based upon Mark Lord's delkin
-+ * driver and the extensive analysis done by the BSD developers, notably
-+ * ITOH Yasufumi.
-+ *
-+ *	Base + 0x00 IRQ Status
-+ *	Base + 0x01 IRQ control
-+ *	Base + 0x02 Chipset control
-+ *	Base + 0x04 VDMA and reset control + wait bits
-+ *	Base + 0x08 BMIMBA
-+ *	Base + 0x0C DMA Length
-+ *	Base + 0x10 Taskfile
-+ *	Base + 0x18 BMDMA Status ?
-+ *	Base + 0x1C
-+ *	Base + 0x1D Bus master control
-+ *		bit 0 = enable
-+ *		bit 1 = 0 write/1 read
-+ *		bit 2 = 1 sgtable
-+ *		bit 3 = go
-+ *		bit 4-6 wait bits
-+ *		bit 7 = done
-+ *	Base + 0x1E AltStatus
-+ *	Base + 0x1F timing register
++ * Return 1 - send buffer to card and ack.
++ * Return 0 - don't ack, don't send buffer to card.
 + */
++static int send_data(enum port_type index, const struct nozomi *dc)
++{
++	u32 size = 0;
++	const struct port *port = &dc->port[index];
++	const u8 toggle = port->toggle_ul;
++	void __iomem *addr = port->ul_addr[toggle];
++	const u32 ul_size = port->ul_size[toggle];
++	struct tty_struct *tty = port->tty;
 +
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/init.h>
-+#include <linux/blkdev.h>
-+#include <linux/delay.h>
-+#include <scsi/scsi_host.h>
-+#include <linux/libata.h>
++	/* Get data from tty and place in buf for now */
++	size = __kfifo_get(port->fifo_ul, dc->send_buf,
++			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
 +
-+#define DRV_NAME "pata_ninja32"
-+#define DRV_VERSION "0.0.1"
++	if (size == 0) {
++		DBG4("No more data to send, disable link:");
++		return 0;
++	}
 +
++	/* DUMP(buf, size); */
 +
-+/**
-+ *	ninja32_set_piomode	-	set initial PIO mode data
-+ *	@ap: ATA interface
-+ *	@adev: ATA device
-+ *
-+ *	Called to do the PIO mode setup. Our timing registers are shared
-+ *	but we want to set the PIO timing by default.
-+ */
++	/* Write length + data */
++	write_mem32(addr, (u32 *) &size, 4);
++	write_mem32(addr + 4, (u32 *) dc->send_buf, size);
 +
-+static void ninja32_set_piomode(struct ata_port *ap, struct ata_device *adev)
-+{
-+	static u16 pio_timing[5] = {
-+		0xd6, 0x85, 0x44, 0x33, 0x13
-+	};
-+	iowrite8(pio_timing[adev->pio_mode - XFER_PIO_0],
-+		 ap->ioaddr.bmdma_addr + 0x1f);
-+	ap->private_data = adev;
-+}
++	if (tty)
++		tty_wakeup(tty);
 +
++	return 1;
++}
 +
-+static void ninja32_dev_select(struct ata_port *ap, unsigned int device)
++/* If all data has been read, return 1, else 0 */
++static int receive_data(enum port_type index, struct nozomi *dc)
 +{
-+	struct ata_device *adev = &ap->link.device[device];
-+	if (ap->private_data != adev) {
-+		iowrite8(0xd6, ap->ioaddr.bmdma_addr + 0x1f);
-+		ata_std_dev_select(ap, device);
-+		ninja32_set_piomode(ap, adev);
++	u8 buf[RECEIVE_BUF_MAX] = { 0 };
++	int size;
++	u32 offset = 4;
++	struct port *port = &dc->port[index];
++	void __iomem *addr = port->dl_addr[port->toggle_dl];
++	struct tty_struct *tty = port->tty;
++	int i;
++
++	if (unlikely(!tty)) {
++		DBG1("tty not open for port: %d?", index);
++		return 1;
 +	}
-+}
 +
-+static struct scsi_host_template ninja32_sht = {
-+	.module			= THIS_MODULE,
-+	.name			= DRV_NAME,
-+	.ioctl			= ata_scsi_ioctl,
-+	.queuecommand		= ata_scsi_queuecmd,
-+	.can_queue		= ATA_DEF_QUEUE,
-+	.this_id		= ATA_SHT_THIS_ID,
-+	.sg_tablesize		= LIBATA_MAX_PRD,
-+	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
-+	.emulated		= ATA_SHT_EMULATED,
-+	.use_clustering		= ATA_SHT_USE_CLUSTERING,
-+	.proc_name		= DRV_NAME,
-+	.dma_boundary		= ATA_DMA_BOUNDARY,
-+	.slave_configure	= ata_scsi_slave_config,
-+	.slave_destroy		= ata_scsi_slave_destroy,
-+	.bios_param		= ata_std_bios_param,
-+};
++	read_mem32((u32 *) &size, addr, 4);
++	/*  DBG1( "%d bytes port: %d", size, index); */
 +
-+static struct ata_port_operations ninja32_port_ops = {
-+	.set_piomode	= ninja32_set_piomode,
-+	.mode_filter	= ata_pci_default_filter,
++	if (test_bit(TTY_THROTTLED, &tty->flags)) {
++		DBG1("No room in tty, don't read data, don't ack interrupt, "
++			"disable interrupt");
 +
-+	.tf_load	= ata_tf_load,
-+	.tf_read	= ata_tf_read,
-+	.check_status 	= ata_check_status,
-+	.exec_command	= ata_exec_command,
-+	.dev_select 	= ninja32_dev_select,
++		/* disable interrupt in downlink... */
++		disable_transmit_dl(index, dc);
++		return 0;
++	}
 +
-+	.freeze		= ata_bmdma_freeze,
-+	.thaw		= ata_bmdma_thaw,
-+	.error_handler	= ata_bmdma_error_handler,
-+	.post_internal_cmd = ata_bmdma_post_internal_cmd,
-+	.cable_detect	= ata_cable_40wire,
++	if (unlikely(size == 0)) {
++		dev_err(&dc->pdev->dev, "size == 0?\n");
++		return 1;
++	}
 +
-+	.bmdma_setup 	= ata_bmdma_setup,
-+	.bmdma_start 	= ata_bmdma_start,
-+	.bmdma_stop	= ata_bmdma_stop,
-+	.bmdma_status 	= ata_bmdma_status,
++	tty_buffer_request_room(tty, size);
 +
-+	.qc_prep 	= ata_qc_prep,
-+	.qc_issue	= ata_qc_issue_prot,
++	while (size > 0) {
++		read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
 +
-+	.data_xfer	= ata_data_xfer,
++		if (size == 1) {
++			tty_insert_flip_char(tty, buf[0], TTY_NORMAL);
++			size = 0;
++		} else if (size < RECEIVE_BUF_MAX) {
++			size -= tty_insert_flip_string(tty, (char *) buf, size);
++		} else {
++			i = tty_insert_flip_string(tty, \
++						(char *) buf, RECEIVE_BUF_MAX);
++			size -= i;
++			offset += i;
++		}
++	}
 +
-+	.irq_handler	= ata_interrupt,
-+	.irq_clear	= ata_bmdma_irq_clear,
-+	.irq_on		= ata_irq_on,
++	set_bit(index, &dc->flip);
 +
-+	.port_start	= ata_sff_port_start,
-+};
++	return 1;
++}
 +
-+static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
++/* Debug for interrupts */
++#ifdef DEBUG
++static char *interrupt2str(u16 interrupt)
 +{
-+	struct ata_host *host;
-+	struct ata_port *ap;
-+	void __iomem *base;
-+	int rc;
++	static char buf[TMP_BUF_MAX];
++	char *p = buf;
 +
-+	host = ata_host_alloc(&dev->dev, 1);
-+	if (!host)
-+		return -ENOMEM;
-+	ap = host->ports[0];
++	interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL;
++	interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"MDM_DL2 ") : NULL;
 +
-+	/* Set up the PCI device */
-+	rc = pcim_enable_device(dev);
-+	if (rc)
-+		return rc;
-+	rc = pcim_iomap_regions(dev, 1 << 0, DRV_NAME);
-+	if (rc == -EBUSY)
-+		pcim_pin_device(dev);
-+	if (rc)
-+		return rc;
++	interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"MDM_UL1 ") : NULL;
++	interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"MDM_UL2 ") : NULL;
 +
-+	host->iomap = pcim_iomap_table(dev);
-+	rc = pci_set_dma_mask(dev, ATA_DMA_MASK);
-+	if (rc)
-+		return rc;
-+	rc = pci_set_consistent_dma_mask(dev, ATA_DMA_MASK);
-+	if (rc)
-+		return rc;
-+	pci_set_master(dev);
++	interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"DIAG_DL1 ") : NULL;
++	interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"DIAG_DL2 ") : NULL;
 +
-+	/* Set up the register mappings */
-+	base = host->iomap[0];
-+	if (!base)
-+		return -ENOMEM;
-+	ap->ops = &ninja32_port_ops;
-+	ap->pio_mask = 0x1F;
-+	ap->flags |= ATA_FLAG_SLAVE_POSS;
++	interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"DIAG_UL ") : NULL;
 +
-+	ap->ioaddr.cmd_addr = base + 0x10;
-+	ap->ioaddr.ctl_addr = base + 0x1E;
-+	ap->ioaddr.altstatus_addr = base + 0x1E;
-+	ap->ioaddr.bmdma_addr = base;
-+	ata_std_ports(&ap->ioaddr);
++	interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"APP1_DL ") : NULL;
++	interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"APP2_DL ") : NULL;
 +
-+	iowrite8(0x05, base + 0x01);	/* Enable interrupt lines */
-+	iowrite8(0xB3, base + 0x02);	/* Burst, ?? setup */
-+	iowrite8(0x00, base + 0x04);	/* WAIT0 ? */
-+	/* FIXME: Should we disable them at remove ? */
-+	return ata_host_activate(host, dev->irq, ata_interrupt,
-+				 IRQF_SHARED, &ninja32_sht);
-+}
++	interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"APP1_UL ") : NULL;
++	interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"APP2_UL ") : NULL;
 +
-+static const struct pci_device_id ninja32[] = {
-+	{ 0x1145, 0xf021, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+	{ 0x1145, 0xf024, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-+	{ },
-+};
++	interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"CTRL_DL ") : NULL;
++	interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"CTRL_UL ") : NULL;
 +
-+static struct pci_driver ninja32_pci_driver = {
-+	.name 		= DRV_NAME,
-+	.id_table	= ninja32,
-+	.probe 		= ninja32_init_one,
-+	.remove		= ata_pci_remove_one
-+};
++	interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
++					"RESET ") : NULL;
 +
-+static int __init ninja32_init(void)
-+{
-+	return pci_register_driver(&ninja32_pci_driver);
++	return buf;
 +}
++#endif
 +
-+static void __exit ninja32_exit(void)
++/*
++ * Receive flow control
++ * Return 1 - If ok, else 0
++ */
++static int receive_flow_control(struct nozomi *dc)
 +{
-+	pci_unregister_driver(&ninja32_pci_driver);
++	enum port_type port = PORT_MDM;
++	struct ctrl_dl ctrl_dl;
++	struct ctrl_dl old_ctrl;
++	u16 enable_ier = 0;
++
++	read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2);
++
++	switch (ctrl_dl.port) {
++	case CTRL_CMD:
++		DBG1("The Base Band sends this value as a response to a "
++			"request for IMSI detach sent over the control "
++			"channel uplink (see section 7.6.1).");
++		break;
++	case CTRL_MDM:
++		port = PORT_MDM;
++		enable_ier = MDM_DL;
++		break;
++	case CTRL_DIAG:
++		port = PORT_DIAG;
++		enable_ier = DIAG_DL;
++		break;
++	case CTRL_APP1:
++		port = PORT_APP1;
++		enable_ier = APP1_DL;
++		break;
++	case CTRL_APP2:
++		port = PORT_APP2;
++		enable_ier = APP2_DL;
++		break;
++	default:
++		dev_err(&dc->pdev->dev,
++			"ERROR: flow control received for non-existing port\n");
++		return 0;
++	};
++
++	DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
++	   *((u16 *)&ctrl_dl));
++
++	old_ctrl = dc->port[port].ctrl_dl;
++	dc->port[port].ctrl_dl = ctrl_dl;
++
++	if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) {
++		DBG1("Disable interrupt (0x%04X) on port: %d",
++			enable_ier, port);
++		disable_transmit_ul(port, dc);
++
++	} else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
++
++		if (__kfifo_len(dc->port[port].fifo_ul)) {
++			DBG1("Enable interrupt (0x%04X) on port: %d",
++				enable_ier, port);
++			DBG1("Data in buffer [%d], enable transmit! ",
++				__kfifo_len(dc->port[port].fifo_ul));
++			enable_transmit_ul(port, dc);
++		} else {
++			DBG1("No data in buffer...");
++		}
++	}
++
++	if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) {
++		DBG1(" No change in mctrl");
++		return 1;
++	}
++	/* Update statistics */
++	if (old_ctrl.CTS != ctrl_dl.CTS)
++		dc->port[port].tty_icount.cts++;
++	if (old_ctrl.DSR != ctrl_dl.DSR)
++		dc->port[port].tty_icount.dsr++;
++	if (old_ctrl.RI != ctrl_dl.RI)
++		dc->port[port].tty_icount.rng++;
++	if (old_ctrl.DCD != ctrl_dl.DCD)
++		dc->port[port].tty_icount.dcd++;
++
++	wake_up_interruptible(&dc->port[port].tty_wait);
++
++	DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)",
++	   port,
++	   dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts,
++	   dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr);
++
++	return 1;
 +}
 +
-+MODULE_AUTHOR("Alan Cox");
-+MODULE_DESCRIPTION("low-level driver for Ninja32 ATA");
-+MODULE_LICENSE("GPL");
-+MODULE_DEVICE_TABLE(pci, ninja32);
-+MODULE_VERSION(DRV_VERSION);
++static enum ctrl_port_type port2ctrl(enum port_type port,
++					const struct nozomi *dc)
++{
++	switch (port) {
++	case PORT_MDM:
++		return CTRL_MDM;
++	case PORT_DIAG:
++		return CTRL_DIAG;
++	case PORT_APP1:
++		return CTRL_APP1;
++	case PORT_APP2:
++		return CTRL_APP2;
++	default:
++		dev_err(&dc->pdev->dev,
++			"ERROR: send flow control " \
++			"received for non-existing port\n");
++	};
++	return CTRL_ERROR;
++}
 +
-+module_init(ninja32_init);
-+module_exit(ninja32_exit);
-diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
-new file mode 100644
-index 0000000..938f48a
---- /dev/null
-+++ b/drivers/ata/pata_of_platform.c
-@@ -0,0 +1,114 @@
 +/*
-+ * OF-platform PATA driver
-+ *
-+ * Copyright (c) 2007  MontaVista Software, Inc.
-+ *                     Anton Vorontsov <avorontsov at ru.mvista.com>
-+ *
-+ * 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.
++ * Send flow control, can only update one channel at a time
++ * Return 0 - If we have updated all flow control
++ * Return 1 - If we need to update more flow control, ack current enable more
 + */
++static int send_flow_control(struct nozomi *dc)
++{
++	u32 i, more_flow_control_to_be_updated = 0;
++	u16 *ctrl;
 +
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of_platform.h>
-+#include <linux/pata_platform.h>
++	for (i = PORT_MDM; i < MAX_PORT; i++) {
++		if (dc->port[i].update_flow_control) {
++			if (more_flow_control_to_be_updated) {
++				/* We have more flow control to be updated */
++				return 1;
++			}
++			dc->port[i].ctrl_ul.port = port2ctrl(i, dc);
++			ctrl = (u16 *)&dc->port[i].ctrl_ul;
++			write_mem32(dc->port[PORT_CTRL].ul_addr[0], \
++				(u32 *) ctrl, 2);
++			dc->port[i].update_flow_control = 0;
++			more_flow_control_to_be_updated = 1;
++		}
++	}
++	return 0;
++}
 +
-+static int __devinit pata_of_platform_probe(struct of_device *ofdev,
-+					    const struct of_device_id *match)
++/*
++ * Handle downlink data, ports that are handled are modem and diagnostics
++ * Return 1 - ok
++ * Return 0 - toggle fields are out of sync
++ */
++static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle,
++			u16 read_iir, u16 mask1, u16 mask2)
 +{
-+	int ret;
-+	struct device_node *dn = ofdev->node;
-+	struct resource io_res;
-+	struct resource ctl_res;
-+	struct resource irq_res;
-+	unsigned int reg_shift = 0;
-+	int pio_mode = 0;
-+	int pio_mask;
-+	const u32 *prop;
++	if (*toggle == 0 && read_iir & mask1) {
++		if (receive_data(port, dc)) {
++			writew(mask1, dc->reg_fcr);
++			*toggle = !(*toggle);
++		}
 +
-+	ret = of_address_to_resource(dn, 0, &io_res);
-+	if (ret) {
-+		dev_err(&ofdev->dev, "can't get IO address from "
-+			"device tree\n");
-+		return -EINVAL;
-+	}
++		if (read_iir & mask2) {
++			if (receive_data(port, dc)) {
++				writew(mask2, dc->reg_fcr);
++				*toggle = !(*toggle);
++			}
++		}
++	} else if (*toggle == 1 && read_iir & mask2) {
++		if (receive_data(port, dc)) {
++			writew(mask2, dc->reg_fcr);
++			*toggle = !(*toggle);
++		}
 +
-+	if (of_device_is_compatible(dn, "electra-ide")) {
-+		/* Altstatus is really at offset 0x3f6 from the primary window
-+		 * on electra-ide. Adjust ctl_res and io_res accordingly.
-+		 */
-+		ctl_res = io_res;
-+		ctl_res.start = ctl_res.start+0x3f6;
-+		io_res.end = ctl_res.start-1;
-+	} else {
-+		ret = of_address_to_resource(dn, 1, &ctl_res);
-+		if (ret) {
-+			dev_err(&ofdev->dev, "can't get CTL address from "
-+				"device tree\n");
-+			return -EINVAL;
++		if (read_iir & mask1) {
++			if (receive_data(port, dc)) {
++				writew(mask1, dc->reg_fcr);
++				*toggle = !(*toggle);
++			}
 +		}
++	} else {
++		dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n",
++			*toggle);
++		return 0;
 +	}
++	return 1;
++}
 +
-+	ret = of_irq_to_resource(dn, 0, &irq_res);
-+	if (ret == NO_IRQ)
-+		irq_res.start = irq_res.end = -1;
-+	else
-+		irq_res.flags = 0;
++/*
++ * Handle uplink data, this is currently for the modem port
++ * Return 1 - ok
++ * Return 0 - toggle field are out of sync
++ */
++static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir)
++{
++	u8 *toggle = &(dc->port[port].toggle_ul);
 +
-+	prop = of_get_property(dn, "reg-shift", NULL);
-+	if (prop)
-+		reg_shift = *prop;
++	if (*toggle == 0 && read_iir & MDM_UL1) {
++		dc->last_ier &= ~MDM_UL;
++		writew(dc->last_ier, dc->reg_ier);
++		if (send_data(port, dc)) {
++			writew(MDM_UL1, dc->reg_fcr);
++			dc->last_ier = dc->last_ier | MDM_UL;
++			writew(dc->last_ier, dc->reg_ier);
++			*toggle = !*toggle;
++		}
 +
-+	prop = of_get_property(dn, "pio-mode", NULL);
-+	if (prop) {
-+		pio_mode = *prop;
-+		if (pio_mode > 6) {
-+			dev_err(&ofdev->dev, "invalid pio-mode\n");
-+			return -EINVAL;
++		if (read_iir & MDM_UL2) {
++			dc->last_ier &= ~MDM_UL;
++			writew(dc->last_ier, dc->reg_ier);
++			if (send_data(port, dc)) {
++				writew(MDM_UL2, dc->reg_fcr);
++				dc->last_ier = dc->last_ier | MDM_UL;
++				writew(dc->last_ier, dc->reg_ier);
++				*toggle = !*toggle;
++			}
 +		}
-+	} else {
-+		dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n");
-+	}
 +
-+	pio_mask = 1 << pio_mode;
-+	pio_mask |= (1 << pio_mode) - 1;
++	} else if (*toggle == 1 && read_iir & MDM_UL2) {
++		dc->last_ier &= ~MDM_UL;
++		writew(dc->last_ier, dc->reg_ier);
++		if (send_data(port, dc)) {
++			writew(MDM_UL2, dc->reg_fcr);
++			dc->last_ier = dc->last_ier | MDM_UL;
++			writew(dc->last_ier, dc->reg_ier);
++			*toggle = !*toggle;
++		}
 +
-+	return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res,
-+				     reg_shift, pio_mask);
++		if (read_iir & MDM_UL1) {
++			dc->last_ier &= ~MDM_UL;
++			writew(dc->last_ier, dc->reg_ier);
++			if (send_data(port, dc)) {
++				writew(MDM_UL1, dc->reg_fcr);
++				dc->last_ier = dc->last_ier | MDM_UL;
++				writew(dc->last_ier, dc->reg_ier);
++				*toggle = !*toggle;
++			}
++		}
++	} else {
++		writew(read_iir & MDM_UL, dc->reg_fcr);
++		dev_err(&dc->pdev->dev, "port out of sync!\n");
++		return 0;
++	}
++	return 1;
 +}
 +
-+static int __devexit pata_of_platform_remove(struct of_device *ofdev)
++static irqreturn_t interrupt_handler(int irq, void *dev_id)
 +{
-+	return __pata_platform_remove(&ofdev->dev);
-+}
++	struct nozomi *dc = dev_id;
++	unsigned int a;
++	u16 read_iir;
 +
-+static struct of_device_id pata_of_platform_match[] = {
-+	{ .compatible = "ata-generic", },
-+	{ .compatible = "electra-ide", },
-+	{},
-+};
-+MODULE_DEVICE_TABLE(of, pata_of_platform_match);
++	if (!dc)
++		return IRQ_NONE;
 +
-+static struct of_platform_driver pata_of_platform_driver = {
-+	.name		= "pata_of_platform",
-+	.match_table	= pata_of_platform_match,
-+	.probe		= pata_of_platform_probe,
-+	.remove		= __devexit_p(pata_of_platform_remove),
-+};
++	spin_lock(&dc->spin_mutex);
++	read_iir = readw(dc->reg_iir);
 +
-+static int __init pata_of_platform_init(void)
-+{
-+	return of_register_platform_driver(&pata_of_platform_driver);
++	/* Card removed */
++	if (read_iir == (u16)-1)
++		goto none;
++	/*
++	 * Just handle interrupt enabled in IER
++	 * (by masking with dc->last_ier)
++	 */
++	read_iir &= dc->last_ier;
++
++	if (read_iir == 0)
++		goto none;
++
++
++	DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir,
++		dc->last_ier);
++
++	if (read_iir & RESET) {
++		if (unlikely(!nozomi_read_config_table(dc))) {
++			dc->last_ier = 0x0;
++			writew(dc->last_ier, dc->reg_ier);
++			dev_err(&dc->pdev->dev, "Could not read status from "
++				"card, we should disable interface\n");
++		} else {
++			writew(RESET, dc->reg_fcr);
++		}
++		/* No more useful info if this was the reset interrupt. */
++		goto exit_handler;
++	}
++	if (read_iir & CTRL_UL) {
++		DBG1("CTRL_UL");
++		dc->last_ier &= ~CTRL_UL;
++		writew(dc->last_ier, dc->reg_ier);
++		if (send_flow_control(dc)) {
++			writew(CTRL_UL, dc->reg_fcr);
++			dc->last_ier = dc->last_ier | CTRL_UL;
++			writew(dc->last_ier, dc->reg_ier);
++		}
++	}
++	if (read_iir & CTRL_DL) {
++		receive_flow_control(dc);
++		writew(CTRL_DL, dc->reg_fcr);
++	}
++	if (read_iir & MDM_DL) {
++		if (!handle_data_dl(dc, PORT_MDM,
++				&(dc->port[PORT_MDM].toggle_dl), read_iir,
++				MDM_DL1, MDM_DL2)) {
++			dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n");
++			goto exit_handler;
++		}
++	}
++	if (read_iir & MDM_UL) {
++		if (!handle_data_ul(dc, PORT_MDM, read_iir)) {
++			dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n");
++			goto exit_handler;
++		}
++	}
++	if (read_iir & DIAG_DL) {
++		if (!handle_data_dl(dc, PORT_DIAG,
++				&(dc->port[PORT_DIAG].toggle_dl), read_iir,
++				DIAG_DL1, DIAG_DL2)) {
++			dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n");
++			goto exit_handler;
++		}
++	}
++	if (read_iir & DIAG_UL) {
++		dc->last_ier &= ~DIAG_UL;
++		writew(dc->last_ier, dc->reg_ier);
++		if (send_data(PORT_DIAG, dc)) {
++			writew(DIAG_UL, dc->reg_fcr);
++			dc->last_ier = dc->last_ier | DIAG_UL;
++			writew(dc->last_ier, dc->reg_ier);
++		}
++	}
++	if (read_iir & APP1_DL) {
++		if (receive_data(PORT_APP1, dc))
++			writew(APP1_DL, dc->reg_fcr);
++	}
++	if (read_iir & APP1_UL) {
++		dc->last_ier &= ~APP1_UL;
++		writew(dc->last_ier, dc->reg_ier);
++		if (send_data(PORT_APP1, dc)) {
++			writew(APP1_UL, dc->reg_fcr);
++			dc->last_ier = dc->last_ier | APP1_UL;
++			writew(dc->last_ier, dc->reg_ier);
++		}
++	}
++	if (read_iir & APP2_DL) {
++		if (receive_data(PORT_APP2, dc))
++			writew(APP2_DL, dc->reg_fcr);
++	}
++	if (read_iir & APP2_UL) {
++		dc->last_ier &= ~APP2_UL;
++		writew(dc->last_ier, dc->reg_ier);
++		if (send_data(PORT_APP2, dc)) {
++			writew(APP2_UL, dc->reg_fcr);
++			dc->last_ier = dc->last_ier | APP2_UL;
++			writew(dc->last_ier, dc->reg_ier);
++		}
++	}
++
++exit_handler:
++	spin_unlock(&dc->spin_mutex);
++	for (a = 0; a < NOZOMI_MAX_PORTS; a++)
++		if (test_and_clear_bit(a, &dc->flip))
++			tty_flip_buffer_push(dc->port[a].tty);
++	return IRQ_HANDLED;
++none:
++	spin_unlock(&dc->spin_mutex);
++	return IRQ_NONE;
 +}
-+module_init(pata_of_platform_init);
 +
-+static void __exit pata_of_platform_exit(void)
++static void nozomi_get_card_type(struct nozomi *dc)
 +{
-+	of_unregister_platform_driver(&pata_of_platform_driver);
-+}
-+module_exit(pata_of_platform_exit);
++	int i;
++	u32 size = 0;
 +
-+MODULE_DESCRIPTION("OF-platform PATA driver");
-+MODULE_AUTHOR("Anton Vorontsov <avorontsov at ru.mvista.com>");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c
-index fd36099..3e7f6a9 100644
---- a/drivers/ata/pata_pcmcia.c
-+++ b/drivers/ata/pata_pcmcia.c
-@@ -42,7 +42,7 @@
- 
- 
- #define DRV_NAME "pata_pcmcia"
--#define DRV_VERSION "0.3.2"
-+#define DRV_VERSION "0.3.3"
- 
- /*
-  *	Private data structure to glue stuff together
-@@ -86,6 +86,47 @@ static int pcmcia_set_mode(struct ata_link *link, struct ata_device **r_failed_d
- 	return ata_do_set_mode(link, r_failed_dev);
- }
- 
-+/**
-+ *	pcmcia_set_mode_8bit	-	PCMCIA specific mode setup
-+ *	@link: link
-+ *	@r_failed_dev: Return pointer for failed device
-+ *
-+ *	For the simple emulated 8bit stuff the less we do the better.
-+ */
++	for (i = 0; i < 6; i++)
++		size += pci_resource_len(dc->pdev, i);
 +
-+static int pcmcia_set_mode_8bit(struct ata_link *link,
-+				struct ata_device **r_failed_dev)
-+{
-+	return 0;
-+}
++	/* Assume card type F32_8 if no match */
++	dc->card_type = size == 2048 ? F32_2 : F32_8;
 +
-+/**
-+ *	ata_data_xfer_8bit	 -	Transfer data by 8bit PIO
-+ *	@dev: device to target
-+ *	@buf: data buffer
-+ *	@buflen: buffer length
-+ *	@rw: read/write
-+ *
-+ *	Transfer data from/to the device data register by 8 bit PIO.
-+ *
-+ *	LOCKING:
-+ *	Inherited from caller.
-+ */
++	dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type);
++}
 +
-+static unsigned int ata_data_xfer_8bit(struct ata_device *dev,
-+				unsigned char *buf, unsigned int buflen, int rw)
++static void nozomi_setup_private_data(struct nozomi *dc)
 +{
-+	struct ata_port *ap = dev->link->ap;
++	void __iomem *offset = dc->base_addr + dc->card_type / 2;
++	unsigned int i;
++
++	dc->reg_fcr = (void __iomem *)(offset + R_FCR);
++	dc->reg_iir = (void __iomem *)(offset + R_IIR);
++	dc->reg_ier = (void __iomem *)(offset + R_IER);
++	dc->last_ier = 0;
++	dc->flip = 0;
 +
-+	if (rw == READ)
-+		ioread8_rep(ap->ioaddr.data_addr, buf, buflen);
-+	else
-+		iowrite8_rep(ap->ioaddr.data_addr, buf, buflen);
++	dc->port[PORT_MDM].token_dl = MDM_DL;
++	dc->port[PORT_DIAG].token_dl = DIAG_DL;
++	dc->port[PORT_APP1].token_dl = APP1_DL;
++	dc->port[PORT_APP2].token_dl = APP2_DL;
 +
-+	return buflen;
++	for (i = 0; i < MAX_PORT; i++)
++		init_waitqueue_head(&dc->port[i].tty_wait);
 +}
 +
++static ssize_t card_type_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
 +
- static struct scsi_host_template pcmcia_sht = {
- 	.module			= THIS_MODULE,
- 	.name			= DRV_NAME,
-@@ -129,6 +170,31 @@ static struct ata_port_operations pcmcia_port_ops = {
- 	.port_start	= ata_sff_port_start,
- };
- 
-+static struct ata_port_operations pcmcia_8bit_port_ops = {
-+	.set_mode	= pcmcia_set_mode_8bit,
-+	.tf_load	= ata_tf_load,
-+	.tf_read	= ata_tf_read,
-+	.check_status 	= ata_check_status,
-+	.exec_command	= ata_exec_command,
-+	.dev_select 	= ata_std_dev_select,
++	return sprintf(buf, "%d\n", dc->card_type);
++}
++static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL);
 +
-+	.freeze		= ata_bmdma_freeze,
-+	.thaw		= ata_bmdma_thaw,
-+	.error_handler	= ata_bmdma_error_handler,
-+	.post_internal_cmd = ata_bmdma_post_internal_cmd,
-+	.cable_detect	= ata_cable_40wire,
++static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
 +
-+	.qc_prep 	= ata_qc_prep,
-+	.qc_issue	= ata_qc_issue_prot,
++	return sprintf(buf, "%u\n", dc->open_ttys);
++}
++static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL);
 +
-+	.data_xfer	= ata_data_xfer_8bit,
++static void make_sysfs_files(struct nozomi *dc)
++{
++	if (device_create_file(&dc->pdev->dev, &dev_attr_card_type))
++		dev_err(&dc->pdev->dev,
++			"Could not create sysfs file for card_type\n");
++	if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys))
++		dev_err(&dc->pdev->dev,
++			"Could not create sysfs file for open_ttys\n");
++}
 +
-+	.irq_clear	= ata_bmdma_irq_clear,
-+	.irq_on		= ata_irq_on,
++static void remove_sysfs_files(struct nozomi *dc)
++{
++	device_remove_file(&dc->pdev->dev, &dev_attr_card_type);
++	device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys);
++}
 +
-+	.port_start	= ata_sff_port_start,
-+};
++/* Allocate memory for one device */
++static int __devinit nozomi_card_init(struct pci_dev *pdev,
++				      const struct pci_device_id *ent)
++{
++	resource_size_t start;
++	int ret;
++	struct nozomi *dc = NULL;
++	int ndev_idx;
++	int i;
 +
- #define CS_CHECK(fn, ret) \
- do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
- 
-@@ -153,9 +219,12 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
- 		cistpl_cftable_entry_t dflt;
- 	} *stk = NULL;
- 	cistpl_cftable_entry_t *cfg;
--	int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM;
-+	int pass, last_ret = 0, last_fn = 0, is_kme = 0, ret = -ENOMEM, p;
- 	unsigned long io_base, ctl_base;
- 	void __iomem *io_addr, *ctl_addr;
-+	int n_ports = 1;
++	dev_dbg(&pdev->dev, "Init, new card found\n");
 +
-+	struct ata_port_operations *ops = &pcmcia_port_ops;
- 
- 	info = kzalloc(sizeof(*info), GFP_KERNEL);
- 	if (info == NULL)
-@@ -282,27 +351,32 @@ next_entry:
- 	/* FIXME: Could be more ports at base + 0x10 but we only deal with
- 	   one right now */
- 	if (pdev->io.NumPorts1 >= 0x20)
--		printk(KERN_WARNING DRV_NAME ": second channel not yet supported.\n");
-+		n_ports = 2;
- 
-+	if (pdev->manf_id == 0x0097 && pdev->card_id == 0x1620)
-+		ops = &pcmcia_8bit_port_ops;
- 	/*
- 	 *	Having done the PCMCIA plumbing the ATA side is relatively
- 	 *	sane.
- 	 */
- 	ret = -ENOMEM;
--	host = ata_host_alloc(&pdev->dev, 1);
-+	host = ata_host_alloc(&pdev->dev, n_ports);
- 	if (!host)
- 		goto failed;
--	ap = host->ports[0];
- 
--	ap->ops = &pcmcia_port_ops;
--	ap->pio_mask = 1;		/* ISA so PIO 0 cycles */
--	ap->flags |= ATA_FLAG_SLAVE_POSS;
--	ap->ioaddr.cmd_addr = io_addr;
--	ap->ioaddr.altstatus_addr = ctl_addr;
--	ap->ioaddr.ctl_addr = ctl_addr;
--	ata_std_ports(&ap->ioaddr);
-+	for (p = 0; p < n_ports; p++) {
-+		ap = host->ports[p];
- 
--	ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
-+		ap->ops = ops;
-+		ap->pio_mask = 1;		/* ISA so PIO 0 cycles */
-+		ap->flags |= ATA_FLAG_SLAVE_POSS;
-+		ap->ioaddr.cmd_addr = io_addr + 0x10 * p;
-+		ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p;
-+		ap->ioaddr.ctl_addr = ctl_addr + 0x10 * p;
-+		ata_std_ports(&ap->ioaddr);
++	for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
++		if (!ndevs[ndev_idx])
++			break;
 +
-+		ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", io_base, ctl_base);
++	if (ndev_idx >= ARRAY_SIZE(ndevs)) {
++		dev_err(&pdev->dev, "no free tty range for this card left\n");
++		ret = -EIO;
++		goto err;
 +	}
- 
- 	/* activate */
- 	ret = ata_host_activate(host, pdev->irq.AssignedIRQ, ata_interrupt,
-@@ -360,6 +434,7 @@ static struct pcmcia_device_id pcmcia_devices[] = {
- 	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x0704),
- 	PCMCIA_DEVICE_MANF_CARD(0x0032, 0x2904),
- 	PCMCIA_DEVICE_MANF_CARD(0x0045, 0x0401),	/* SanDisk CFA */
-+	PCMCIA_DEVICE_MANF_CARD(0x0097, 0x1620), 	/* TI emulated */
- 	PCMCIA_DEVICE_MANF_CARD(0x0098, 0x0000),	/* Toshiba */
- 	PCMCIA_DEVICE_MANF_CARD(0x00a4, 0x002d),
- 	PCMCIA_DEVICE_MANF_CARD(0x00ce, 0x0000),	/* Samsung */
-diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c
-index 2622577..028af5d 100644
---- a/drivers/ata/pata_pdc2027x.c
-+++ b/drivers/ata/pata_pdc2027x.c
-@@ -348,7 +348,7 @@ static unsigned long pdc2027x_mode_filter(struct ata_device *adev, unsigned long
- 	ata_id_c_string(pair->id, model_num, ATA_ID_PROD,
- 			  ATA_ID_PROD_LEN + 1);
- 	/* If the master is a maxtor in UDMA6 then the slave should not use UDMA 6 */
--	if (strstr(model_num, "Maxtor") == 0 && pair->dma_mode == XFER_UDMA_6)
-+	if (strstr(model_num, "Maxtor") == NULL && pair->dma_mode == XFER_UDMA_6)
- 		mask &= ~ (1 << (6 + ATA_SHIFT_UDMA));
- 
- 	return ata_pci_default_filter(adev, mask);
-diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c
-index 6c9689b..3ed8667 100644
---- a/drivers/ata/pata_pdc202xx_old.c
-+++ b/drivers/ata/pata_pdc202xx_old.c
-@@ -168,8 +168,7 @@ static void pdc2026x_bmdma_start(struct ata_queued_cmd *qc)
- 	pdc202xx_set_dmamode(ap, qc->dev);
- 
- 	/* Cases the state machine will not complete correctly without help */
--	if ((tf->flags & ATA_TFLAG_LBA48) ||  tf->protocol == ATA_PROT_ATAPI_DMA)
--	{
-+	if ((tf->flags & ATA_TFLAG_LBA48) ||  tf->protocol == ATAPI_PROT_DMA) {
- 		len = qc->nbytes / 2;
- 
- 		if (tf->flags & ATA_TFLAG_WRITE)
-@@ -208,7 +207,7 @@ static void pdc2026x_bmdma_stop(struct ata_queued_cmd *qc)
- 	void __iomem *atapi_reg = master + 0x20 + (4 * ap->port_no);
- 
- 	/* Cases the state machine will not complete correctly */
--	if (tf->protocol == ATA_PROT_ATAPI_DMA || ( tf->flags & ATA_TFLAG_LBA48)) {
-+	if (tf->protocol == ATAPI_PROT_DMA || (tf->flags & ATA_TFLAG_LBA48)) {
- 		iowrite32(0, atapi_reg);
- 		iowrite8(ioread8(clock) & ~sel66, clock);
- 	}
-diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
-index ac03a90..224bb6c 100644
---- a/drivers/ata/pata_platform.c
-+++ b/drivers/ata/pata_platform.c
-@@ -93,14 +93,9 @@ static struct ata_port_operations pata_platform_port_ops = {
- };
- 
- static void pata_platform_setup_port(struct ata_ioports *ioaddr,
--				     struct pata_platform_info *info)
-+				     unsigned int shift)
- {
--	unsigned int shift = 0;
--
- 	/* Fixup the port shift for platforms that need it */
--	if (info && info->ioport_shift)
--		shift = info->ioport_shift;
--
- 	ioaddr->data_addr	= ioaddr->cmd_addr + (ATA_REG_DATA    << shift);
- 	ioaddr->error_addr	= ioaddr->cmd_addr + (ATA_REG_ERR     << shift);
- 	ioaddr->feature_addr	= ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
-@@ -114,8 +109,13 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
- }
- 
- /**
-- *	pata_platform_probe		-	attach a platform interface
-- *	@pdev: platform device
-+ *	__pata_platform_probe		-	attach a platform interface
-+ *	@dev: device
-+ *	@io_res: Resource representing I/O base
-+ *	@ctl_res: Resource representing CTL base
-+ *	@irq_res: Resource representing IRQ and its flags
-+ *	@ioport_shift: I/O port shift
-+ *	@__pio_mask: PIO mask
-  *
-  *	Register a platform bus IDE interface. Such interfaces are PIO and we
-  *	assume do not support IRQ sharing.
-@@ -135,42 +135,18 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
-  *
-  *	If no IRQ resource is present, PIO polling mode is used instead.
-  */
--static int __devinit pata_platform_probe(struct platform_device *pdev)
-+int __devinit __pata_platform_probe(struct device *dev,
-+				    struct resource *io_res,
-+				    struct resource *ctl_res,
-+				    struct resource *irq_res,
-+				    unsigned int ioport_shift,
-+				    int __pio_mask)
- {
--	struct resource *io_res, *ctl_res;
- 	struct ata_host *host;
- 	struct ata_port *ap;
--	struct pata_platform_info *pp_info;
- 	unsigned int mmio;
--	int irq;
--
--	/*
--	 * Simple resource validation ..
--	 */
--	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
--		dev_err(&pdev->dev, "invalid number of resources\n");
--		return -EINVAL;
--	}
--
--	/*
--	 * Get the I/O base first
--	 */
--	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
--	if (io_res == NULL) {
--		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--		if (unlikely(io_res == NULL))
--			return -EINVAL;
--	}
--
--	/*
--	 * Then the CTL base
--	 */
--	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
--	if (ctl_res == NULL) {
--		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
--		if (unlikely(ctl_res == NULL))
--			return -EINVAL;
--	}
-+	int irq = 0;
-+	int irq_flags = 0;
- 
- 	/*
- 	 * Check for MMIO
-@@ -181,20 +157,21 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
- 	/*
- 	 * And the IRQ
- 	 */
--	irq = platform_get_irq(pdev, 0);
--	if (irq < 0)
--		irq = 0;	/* no irq */
-+	if (irq_res && irq_res->start > 0) {
-+		irq = irq_res->start;
-+		irq_flags = irq_res->flags;
++
++	dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
++	if (unlikely(!dc)) {
++		dev_err(&pdev->dev, "Could not allocate memory\n");
++		ret = -ENOMEM;
++		goto err_free;
 +	}
- 
- 	/*
- 	 * Now that that's out of the way, wire up the port..
- 	 */
--	host = ata_host_alloc(&pdev->dev, 1);
-+	host = ata_host_alloc(dev, 1);
- 	if (!host)
- 		return -ENOMEM;
- 	ap = host->ports[0];
- 
- 	ap->ops = &pata_platform_port_ops;
--	ap->pio_mask = pio_mask;
-+	ap->pio_mask = __pio_mask;
- 	ap->flags |= ATA_FLAG_SLAVE_POSS;
- 
- 	/*
-@@ -209,25 +186,24 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
- 	 * Handle the MMIO case
- 	 */
- 	if (mmio) {
--		ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
-+		ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start,
- 				io_res->end - io_res->start + 1);
--		ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
-+		ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start,
- 				ctl_res->end - ctl_res->start + 1);
- 	} else {
--		ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
-+		ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start,
- 				io_res->end - io_res->start + 1);
--		ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
-+		ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start,
- 				ctl_res->end - ctl_res->start + 1);
- 	}
- 	if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
--		dev_err(&pdev->dev, "failed to map IO/CTL base\n");
-+		dev_err(dev, "failed to map IO/CTL base\n");
- 		return -ENOMEM;
- 	}
- 
- 	ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
- 
--	pp_info = pdev->dev.platform_data;
--	pata_platform_setup_port(&ap->ioaddr, pp_info);
-+	pata_platform_setup_port(&ap->ioaddr, ioport_shift);
- 
- 	ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
- 		      (unsigned long long)io_res->start,
-@@ -235,26 +211,78 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
- 
- 	/* activate */
- 	return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
--				 pp_info ? pp_info->irq_flags : 0,
--				 &pata_platform_sht);
-+				 irq_flags, &pata_platform_sht);
- }
-+EXPORT_SYMBOL_GPL(__pata_platform_probe);
- 
- /**
-- *	pata_platform_remove	-	unplug a platform interface
-- *	@pdev: platform device
-+ *	__pata_platform_remove		-	unplug a platform interface
-+ *	@dev: device
-  *
-  *	A platform bus ATA device has been unplugged. Perform the needed
-  *	cleanup. Also called on module unload for any active devices.
-  */
--static int __devexit pata_platform_remove(struct platform_device *pdev)
-+int __devexit __pata_platform_remove(struct device *dev)
- {
--	struct device *dev = &pdev->dev;
- 	struct ata_host *host = dev_get_drvdata(dev);
- 
- 	ata_host_detach(host);
- 
- 	return 0;
- }
-+EXPORT_SYMBOL_GPL(__pata_platform_remove);
 +
-+static int __devinit pata_platform_probe(struct platform_device *pdev)
-+{
-+	struct resource *io_res;
-+	struct resource *ctl_res;
-+	struct resource *irq_res;
-+	struct pata_platform_info *pp_info = pdev->dev.platform_data;
++	dc->pdev = pdev;
 +
-+	/*
-+	 * Simple resource validation ..
-+	 */
-+	if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
-+		dev_err(&pdev->dev, "invalid number of resources\n");
-+		return -EINVAL;
++	/* Find out what card type it is */
++	nozomi_get_card_type(dc);
++
++	ret = pci_enable_device(dc->pdev);
++	if (ret) {
++		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
++		goto err_free;
 +	}
 +
-+	/*
-+	 * Get the I/O base first
-+	 */
-+	io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-+	if (io_res == NULL) {
-+		io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+		if (unlikely(io_res == NULL))
-+			return -EINVAL;
++	start = pci_resource_start(dc->pdev, 0);
++	if (start == 0) {
++		dev_err(&pdev->dev, "No I/O address for card detected\n");
++		ret = -ENODEV;
++		goto err_disable_device;
 +	}
 +
-+	/*
-+	 * Then the CTL base
-+	 */
-+	ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
-+	if (ctl_res == NULL) {
-+		ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+		if (unlikely(ctl_res == NULL))
-+			return -EINVAL;
++	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
++	if (ret) {
++		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
++			(int) /* nozomi_private.io_addr */ 0);
++		goto err_disable_device;
 +	}
 +
-+	/*
-+	 * And the IRQ
-+	 */
-+	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-+	if (irq_res)
-+		irq_res->flags = pp_info ? pp_info->irq_flags : 0;
++	dc->base_addr = ioremap(start, dc->card_type);
++	if (!dc->base_addr) {
++		dev_err(&pdev->dev, "Unable to map card MMIO\n");
++		ret = -ENODEV;
++		goto err_rel_regs;
++	}
 +
-+	return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res,
-+				     pp_info ? pp_info->ioport_shift : 0,
-+				     pio_mask);
-+}
++	dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL);
++	if (!dc->send_buf) {
++		dev_err(&pdev->dev, "Could not allocate send buffer?\n");
++		ret = -ENOMEM;
++		goto err_free_sbuf;
++	}
 +
-+static int __devexit pata_platform_remove(struct platform_device *pdev)
-+{
-+	return __pata_platform_remove(&pdev->dev);
-+}
- 
- static struct platform_driver pata_platform_driver = {
- 	.probe		= pata_platform_probe,
-diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c
-index a4c0e50..9f308ed 100644
---- a/drivers/ata/pata_qdi.c
-+++ b/drivers/ata/pata_qdi.c
-@@ -124,29 +124,33 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
- 	return ata_qc_issue_prot(qc);
- }
- 
--static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
-+static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
-+				  unsigned int buflen, int rw)
- {
--	struct ata_port *ap = adev->link->ap;
--	int slop = buflen & 3;
-+	if (ata_id_has_dword_io(dev->id)) {
-+		struct ata_port *ap = dev->link->ap;
-+		int slop = buflen & 3;
- 
--	if (ata_id_has_dword_io(adev->id)) {
--		if (write_data)
--			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
--		else
-+		if (rw == READ)
- 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-+		else
-+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- 
- 		if (unlikely(slop)) {
--			__le32 pad = 0;
--			if (write_data) {
--				memcpy(&pad, buf + buflen - slop, slop);
--				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
--			} else {
-+			u32 pad;
-+			if (rw == READ) {
- 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- 				memcpy(buf + buflen - slop, &pad, slop);
-+			} else {
-+				memcpy(&pad, buf + buflen - slop, slop);
-+				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
- 			}
-+			buflen += 4 - slop;
- 		}
- 	} else
--		ata_data_xfer(adev, buf, buflen, write_data);
-+		buflen = ata_data_xfer(dev, buf, buflen, rw);
++	spin_lock_init(&dc->spin_mutex);
 +
-+	return buflen;
- }
- 
- static struct scsi_host_template qdi_sht = {
-diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c
-index ea2ef9f..55055b2 100644
---- a/drivers/ata/pata_scc.c
-+++ b/drivers/ata/pata_scc.c
-@@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap)
- 
- /**
-  *	scc_data_xfer - Transfer data by PIO
-- *	@adev: device for this I/O
-+ *	@dev: device for this I/O
-  *	@buf: data buffer
-  *	@buflen: buffer length
-- *	@write_data: read/write
-+ *	@rw: read/write
-  *
-  *	Note: Original code is ata_data_xfer().
-  */
- 
--static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
--			   unsigned int buflen, int write_data)
-+static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
-+				   unsigned int buflen, int rw)
- {
--	struct ata_port *ap = adev->link->ap;
-+	struct ata_port *ap = dev->link->ap;
- 	unsigned int words = buflen >> 1;
- 	unsigned int i;
- 	u16 *buf16 = (u16 *) buf;
- 	void __iomem *mmio = ap->ioaddr.data_addr;
- 
- 	/* Transfer multiple of 2 bytes */
--	if (write_data) {
--		for (i = 0; i < words; i++)
--			out_be32(mmio, cpu_to_le16(buf16[i]));
--	} else {
-+	if (rw == READ)
- 		for (i = 0; i < words; i++)
- 			buf16[i] = le16_to_cpu(in_be32(mmio));
--	}
-+	else
-+		for (i = 0; i < words; i++)
-+			out_be32(mmio, cpu_to_le16(buf16[i]));
- 
- 	/* Transfer trailing 1 byte, if any. */
- 	if (unlikely(buflen & 0x01)) {
- 		u16 align_buf[1] = { 0 };
- 		unsigned char *trailing_buf = buf + buflen - 1;
- 
--		if (write_data) {
--			memcpy(align_buf, trailing_buf, 1);
--			out_be32(mmio, cpu_to_le16(align_buf[0]));
--		} else {
-+		if (rw == READ) {
- 			align_buf[0] = le16_to_cpu(in_be32(mmio));
- 			memcpy(trailing_buf, align_buf, 1);
-+		} else {
-+			memcpy(align_buf, trailing_buf, 1);
-+			out_be32(mmio, cpu_to_le16(align_buf[0]));
- 		}
-+		words++;
- 	}
++	nozomi_setup_private_data(dc);
 +
-+	return words << 1;
- }
- 
- /**
-diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c
-index 8bed888..9c523fb 100644
---- a/drivers/ata/pata_serverworks.c
-+++ b/drivers/ata/pata_serverworks.c
-@@ -41,7 +41,7 @@
- #include <linux/libata.h>
- 
- #define DRV_NAME "pata_serverworks"
--#define DRV_VERSION "0.4.2"
-+#define DRV_VERSION "0.4.3"
- 
- #define SVWKS_CSB5_REVISION_NEW	0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */
- #define SVWKS_CSB6_REVISION	0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */
-@@ -102,7 +102,7 @@ static int osb4_cable(struct ata_port *ap) {
- }
- 
- /**
-- *	csb4_cable	-	CSB5/6 cable detect
-+ *	csb_cable	-	CSB5/6 cable detect
-  *	@ap: ATA port to check
-  *
-  *	Serverworks default arrangement is to use the drive side detection
-@@ -110,7 +110,7 @@ static int osb4_cable(struct ata_port *ap) {
-  */
- 
- static int csb_cable(struct ata_port *ap) {
--	return ATA_CBL_PATA80;
-+	return ATA_CBL_PATA_UNK;
- }
- 
- struct sv_cable_table {
-@@ -231,7 +231,6 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
- 	return ata_pci_default_filter(adev, mask);
- }
- 
--
- /**
-  *	serverworks_set_piomode	-	set initial PIO mode data
-  *	@ap: ATA interface
-@@ -243,7 +242,7 @@ static unsigned long serverworks_csb_filter(struct ata_device *adev, unsigned lo
- static void serverworks_set_piomode(struct ata_port *ap, struct ata_device *adev)
- {
- 	static const u8 pio_mode[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
--	int offset = 1 + (2 * ap->port_no) - adev->devno;
-+	int offset = 1 + 2 * ap->port_no - adev->devno;
- 	int devbits = (2 * ap->port_no + adev->devno) * 4;
- 	u16 csb5_pio;
- 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
-diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c
-index 1388cef..81ef207 100644
---- a/drivers/ata/pata_sl82c105.c
-+++ b/drivers/ata/pata_sl82c105.c
-@@ -26,7 +26,7 @@
- #include <linux/libata.h>
- 
- #define DRV_NAME "pata_sl82c105"
--#define DRV_VERSION "0.3.2"
-+#define DRV_VERSION "0.3.3"
- 
- enum {
- 	/*
-@@ -206,6 +206,34 @@ static void sl82c105_bmdma_stop(struct ata_queued_cmd *qc)
- 	sl82c105_set_piomode(ap, qc->dev);
- }
- 
-+/**
-+ *	sl82c105_qc_defer	-	implement serialization
-+ *	@qc: command
-+ *
-+ *	We must issue one command per host not per channel because
-+ *	of the reset bug.
-+ *
-+ *	Q: is the scsi host lock sufficient ?
-+ */
++	/* Disable all interrupts */
++	dc->last_ier = 0;
++	writew(dc->last_ier, dc->reg_ier);
 +
-+static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
-+{
-+	struct ata_host *host = qc->ap->host;
-+	struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
-+	int rc;
++	ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
++			NOZOMI_NAME, dc);
++	if (unlikely(ret)) {
++		dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
++		goto err_free_sbuf;
++	}
 +
-+	/* First apply the usual rules */	
-+	rc = ata_std_qc_defer(qc);
-+	if (rc != 0)
-+		return rc;
++	DBG1("base_addr: %p", dc->base_addr);
 +
-+	/* Now apply serialization rules. Only allow a command if the
-+	   other channel state machine is idle */
-+	if (alt && alt->qc_active)
-+		return	ATA_DEFER_PORT;
-+	return 0;
-+}
++	make_sysfs_files(dc);
 +
- static struct scsi_host_template sl82c105_sht = {
- 	.module			= THIS_MODULE,
- 	.name			= DRV_NAME,
-@@ -245,6 +273,7 @@ static struct ata_port_operations sl82c105_port_ops = {
- 	.bmdma_stop	= sl82c105_bmdma_stop,
- 	.bmdma_status 	= ata_bmdma_status,
- 
-+	.qc_defer	= sl82c105_qc_defer,
- 	.qc_prep 	= ata_qc_prep,
- 	.qc_issue	= ata_qc_issue_prot,
- 
-@@ -312,7 +341,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id
- 	};
- 	/* for now use only the first port */
- 	const struct ata_port_info *ppi[] = { &info_early,
--					       &ata_dummy_port_info };
-+					       NULL };
- 	u32 val;
- 	int rev;
- 
-diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
-index 453d72b..39627ab 100644
---- a/drivers/ata/pata_via.c
-+++ b/drivers/ata/pata_via.c
-@@ -185,7 +185,8 @@ static int via_cable_detect(struct ata_port *ap) {
- 	if (ata66 & (0x10100000 >> (16 * ap->port_no)))
- 		return ATA_CBL_PATA80;
- 	/* Check with ACPI so we can spot BIOS reported SATA bridges */
--	if (ata_acpi_cbl_80wire(ap))
-+	if (ata_acpi_init_gtm(ap) &&
-+	    ata_acpi_cbl_80wire(ap, ata_acpi_init_gtm(ap)))
- 		return ATA_CBL_PATA80;
- 	return ATA_CBL_PATA40;
- }
-diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c
-index 7116a9e..99c92ed 100644
---- a/drivers/ata/pata_winbond.c
-+++ b/drivers/ata/pata_winbond.c
-@@ -92,29 +92,33 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
- }
- 
- 
--static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
-+static unsigned int winbond_data_xfer(struct ata_device *dev,
-+			unsigned char *buf, unsigned int buflen, int rw)
- {
--	struct ata_port *ap = adev->link->ap;
-+	struct ata_port *ap = dev->link->ap;
- 	int slop = buflen & 3;
- 
--	if (ata_id_has_dword_io(adev->id)) {
--		if (write_data)
--			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
--		else
-+	if (ata_id_has_dword_io(dev->id)) {
-+		if (rw == READ)
- 			ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-+		else
-+			iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
- 
- 		if (unlikely(slop)) {
--			__le32 pad = 0;
--			if (write_data) {
--				memcpy(&pad, buf + buflen - slop, slop);
--				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
--			} else {
-+			u32 pad;
-+			if (rw == READ) {
- 				pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- 				memcpy(buf + buflen - slop, &pad, slop);
-+			} else {
-+				memcpy(&pad, buf + buflen - slop, slop);
-+				iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
- 			}
-+			buflen += 4 - slop;
- 		}
- 	} else
--		ata_data_xfer(adev, buf, buflen, write_data);
-+		buflen = ata_data_xfer(dev, buf, buflen, rw);
++	dc->index_start = ndev_idx * MAX_PORT;
++	ndevs[ndev_idx] = dc;
 +
-+	return buflen;
- }
- 
- static struct scsi_host_template winbond_sht = {
-@@ -191,7 +195,7 @@ static __init int winbond_init_one(unsigned long port)
- 	reg = winbond_readcfg(port, 0x81);
- 
- 	if (!(reg & 0x03))		/* Disabled */
--		return 0;
-+		return -ENODEV;
- 
- 	for (i = 0; i < 2 ; i ++) {
- 		unsigned long cmd_port = 0x1F0 - (0x80 * i);
-diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c
-index bd4c2a3..8e1b7e9 100644
---- a/drivers/ata/pdc_adma.c
-+++ b/drivers/ata/pdc_adma.c
-@@ -321,8 +321,9 @@ static int adma_fill_sg(struct ata_queued_cmd *qc)
- 	u8  *buf = pp->pkt, *last_buf = NULL;
- 	int i = (2 + buf[3]) * 8;
- 	u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0);
-+	unsigned int si;
- 
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		u32 addr;
- 		u32 len;
- 
-@@ -455,7 +456,7 @@ static unsigned int adma_qc_issue(struct ata_queued_cmd *qc)
- 		adma_packet_start(qc);
- 		return 0;
- 
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		BUG();
- 		break;
- 
-diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
-index d015b4a..922d7b2 100644
---- a/drivers/ata/sata_fsl.c
-+++ b/drivers/ata/sata_fsl.c
-@@ -333,13 +333,14 @@ static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
- 	struct prde *prd_ptr_to_indirect_ext = NULL;
- 	unsigned indirect_ext_segment_sz = 0;
- 	dma_addr_t indirect_ext_segment_paddr;
-+	unsigned int si;
- 
- 	VPRINTK("SATA FSL : cd = 0x%x, prd = 0x%x\n", cmd_desc, prd);
- 
- 	indirect_ext_segment_paddr = cmd_desc_paddr +
- 	    SATA_FSL_CMD_DESC_OFFSET_TO_PRDT + SATA_FSL_MAX_PRD_DIRECT * 16;
- 
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		dma_addr_t sg_addr = sg_dma_address(sg);
- 		u32 sg_len = sg_dma_len(sg);
- 
-@@ -417,7 +418,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
- 	}
- 
- 	/* setup "ACMD - atapi command" in cmd. desc. if this is ATAPI cmd */
--	if (is_atapi_taskfile(&qc->tf)) {
-+	if (ata_is_atapi(qc->tf.protocol)) {
- 		desc_info |= ATAPI_CMD;
- 		memset((void *)&cd->acmd, 0, 32);
- 		memcpy((void *)&cd->acmd, qc->cdb, qc->dev->cdb_len);
-diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
-index 323c087..96e614a 100644
---- a/drivers/ata/sata_inic162x.c
-+++ b/drivers/ata/sata_inic162x.c
-@@ -585,7 +585,7 @@ static struct ata_port_operations inic_port_ops = {
- };
- 
- static struct ata_port_info inic_port_info = {
--	/* For some reason, ATA_PROT_ATAPI is broken on this
-+	/* For some reason, ATAPI_PROT_PIO is broken on this
- 	 * controller, and no, PIO_POLLING does't fix it.  It somehow
- 	 * manages to report the wrong ireason and ignoring ireason
- 	 * results in machine lock up.  Tell libata to always prefer
-diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
-index 37b850a..3c1b5c9 100644
---- a/drivers/ata/sata_mv.c
-+++ b/drivers/ata/sata_mv.c
-@@ -29,7 +29,13 @@
-   I distinctly remember a couple workarounds (one related to PCI-X)
-   are still needed.
- 
--  4) Add NCQ support (easy to intermediate, once new-EH support appears)
-+  2) Improve/fix IRQ and error handling sequences.
++	for (i = 0; i < MAX_PORT; i++) {
++		mutex_init(&dc->port[i].tty_sem);
++		dc->port[i].tty_open_count = 0;
++		dc->port[i].tty = NULL;
++		tty_register_device(ntty_driver, dc->index_start + i,
++							&pdev->dev);
++	}
 +
-+  3) ATAPI support (Marvell claims the 60xx/70xx chips can do it).
++	/* Enable  RESET interrupt. */
++	dc->last_ier = RESET;
++	writew(dc->last_ier, dc->reg_ier);
 +
-+  4) Think about TCQ support here, and for libata in general
-+  with controllers that suppport it via host-queuing hardware
-+  (a software-only implementation could be a nightmare).
- 
-   5) Investigate problems with PCI Message Signalled Interrupts (MSI).
- 
-@@ -53,8 +59,6 @@
-   Target mode, for those without docs, is the ability to directly
-   connect two SATA controllers.
- 
--  13) Verify that 7042 is fully supported.  I only have a 6042.
--
- */
- 
- 
-@@ -73,7 +77,7 @@
- #include <linux/libata.h>
- 
- #define DRV_NAME	"sata_mv"
--#define DRV_VERSION	"1.01"
-+#define DRV_VERSION	"1.20"
- 
- enum {
- 	/* BAR's are enumerated in terms of pci_resource_start() terms */
-@@ -107,14 +111,12 @@ enum {
- 
- 	/* CRQB needs alignment on a 1KB boundary. Size == 1KB
- 	 * CRPB needs alignment on a 256B boundary. Size == 256B
--	 * SG count of 176 leads to MV_PORT_PRIV_DMA_SZ == 4KB
- 	 * ePRD (SG) entries need alignment on a 16B boundary. Size == 16B
- 	 */
- 	MV_CRQB_Q_SZ		= (32 * MV_MAX_Q_DEPTH),
- 	MV_CRPB_Q_SZ		= (8 * MV_MAX_Q_DEPTH),
--	MV_MAX_SG_CT		= 176,
-+	MV_MAX_SG_CT		= 256,
- 	MV_SG_TBL_SZ		= (16 * MV_MAX_SG_CT),
--	MV_PORT_PRIV_DMA_SZ	= (MV_CRQB_Q_SZ + MV_CRPB_Q_SZ + MV_SG_TBL_SZ),
- 
- 	MV_PORTS_PER_HC		= 4,
- 	/* == (port / MV_PORTS_PER_HC) to determine HC from 0-7 port */
-@@ -125,6 +127,9 @@ enum {
- 	/* Host Flags */
- 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
- 	MV_FLAG_IRQ_COALESCE	= (1 << 29),  /* IRQ coalescing capability */
-+	/* SoC integrated controllers, no PCI interface */
-+	MV_FLAG_SOC = (1 << 28),
++	pci_set_drvdata(pdev, dc);
 +
- 	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- 				  ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
- 				  ATA_FLAG_PIO_POLLING,
-@@ -170,7 +175,7 @@ enum {
- 
- 	PCIE_IRQ_CAUSE_OFS	= 0x1900,
- 	PCIE_IRQ_MASK_OFS	= 0x1910,
--	PCIE_UNMASK_ALL_IRQS	= 0x70a,	/* assorted bits */
-+	PCIE_UNMASK_ALL_IRQS	= 0x40a,	/* assorted bits */
- 
- 	HC_MAIN_IRQ_CAUSE_OFS	= 0x1d60,
- 	HC_MAIN_IRQ_MASK_OFS	= 0x1d64,
-@@ -210,6 +215,7 @@ enum {
- 	/* SATA registers */
- 	SATA_STATUS_OFS		= 0x300,  /* ctrl, err regs follow status */
- 	SATA_ACTIVE_OFS		= 0x350,
-+	SATA_FIS_IRQ_CAUSE_OFS	= 0x364,
- 	PHY_MODE3		= 0x310,
- 	PHY_MODE4		= 0x314,
- 	PHY_MODE2		= 0x330,
-@@ -222,11 +228,11 @@ enum {
- 
- 	/* Port registers */
- 	EDMA_CFG_OFS		= 0,
--	EDMA_CFG_Q_DEPTH	= 0,			/* queueing disabled */
--	EDMA_CFG_NCQ		= (1 << 5),
--	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),		/* continue on error */
--	EDMA_CFG_RD_BRST_EXT	= (1 << 11),		/* read burst 512B */
--	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),		/* write buffer 512B */
-+	EDMA_CFG_Q_DEPTH	= 0x1f,		/* max device queue depth */
-+	EDMA_CFG_NCQ		= (1 << 5),	/* for R/W FPDMA queued */
-+	EDMA_CFG_NCQ_GO_ON_ERR	= (1 << 14),	/* continue on error */
-+	EDMA_CFG_RD_BRST_EXT	= (1 << 11),	/* read burst 512B */
-+	EDMA_CFG_WR_BUFF_LEN	= (1 << 13),	/* write buffer 512B */
- 
- 	EDMA_ERR_IRQ_CAUSE_OFS	= 0x8,
- 	EDMA_ERR_IRQ_MASK_OFS	= 0xc,
-@@ -244,14 +250,33 @@ enum {
- 	EDMA_ERR_CRPB_PAR	= (1 << 10),	/* CRPB parity error */
- 	EDMA_ERR_INTRL_PAR	= (1 << 11),	/* internal parity error */
- 	EDMA_ERR_IORDY		= (1 << 12),	/* IORdy timeout */
++	return 0;
 +
- 	EDMA_ERR_LNK_CTRL_RX	= (0xf << 13),	/* link ctrl rx error */
--	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),
-+	EDMA_ERR_LNK_CTRL_RX_0	= (1 << 13),	/* transient: CRC err */
-+	EDMA_ERR_LNK_CTRL_RX_1	= (1 << 14),	/* transient: FIFO err */
-+	EDMA_ERR_LNK_CTRL_RX_2	= (1 << 15),	/* fatal: caught SYNC */
-+	EDMA_ERR_LNK_CTRL_RX_3	= (1 << 16),	/* transient: FIS rx err */
++err_free_sbuf:
++	kfree(dc->send_buf);
++	iounmap(dc->base_addr);
++err_rel_regs:
++	pci_release_regions(pdev);
++err_disable_device:
++	pci_disable_device(pdev);
++err_free:
++	kfree(dc);
++err:
++	return ret;
++}
 +
- 	EDMA_ERR_LNK_DATA_RX	= (0xf << 17),	/* link data rx error */
++static void __devexit tty_exit(struct nozomi *dc)
++{
++	unsigned int i;
 +
- 	EDMA_ERR_LNK_CTRL_TX	= (0x1f << 21),	/* link ctrl tx error */
-+	EDMA_ERR_LNK_CTRL_TX_0	= (1 << 21),	/* transient: CRC err */
-+	EDMA_ERR_LNK_CTRL_TX_1	= (1 << 22),	/* transient: FIFO err */
-+	EDMA_ERR_LNK_CTRL_TX_2	= (1 << 23),	/* transient: caught SYNC */
-+	EDMA_ERR_LNK_CTRL_TX_3	= (1 << 24),	/* transient: caught DMAT */
-+	EDMA_ERR_LNK_CTRL_TX_4	= (1 << 25),	/* transient: FIS collision */
++	DBG1(" ");
 +
- 	EDMA_ERR_LNK_DATA_TX	= (0x1f << 26),	/* link data tx error */
++	flush_scheduled_work();
 +
- 	EDMA_ERR_TRANS_PROTO	= (1 << 31),	/* transport protocol error */
- 	EDMA_ERR_OVERRUN_5	= (1 << 5),
- 	EDMA_ERR_UNDERRUN_5	= (1 << 6),
++	for (i = 0; i < MAX_PORT; ++i)
++		if (dc->port[i].tty && \
++				list_empty(&dc->port[i].tty->hangup_work.entry))
++			tty_hangup(dc->port[i].tty);
 +
-+	EDMA_ERR_IRQ_TRANSIENT  = EDMA_ERR_LNK_CTRL_RX_0 |
-+				  EDMA_ERR_LNK_CTRL_RX_1 |
-+				  EDMA_ERR_LNK_CTRL_RX_3 |
-+				  EDMA_ERR_LNK_CTRL_TX,
++	while (dc->open_ttys)
++		msleep(1);
 +
- 	EDMA_EH_FREEZE		= EDMA_ERR_D_PAR |
- 				  EDMA_ERR_PRD_PAR |
- 				  EDMA_ERR_DEV_DCON |
-@@ -311,12 +336,14 @@ enum {
- 
- 	/* Port private flags (pp_flags) */
- 	MV_PP_FLAG_EDMA_EN	= (1 << 0),	/* is EDMA engine enabled? */
-+	MV_PP_FLAG_NCQ_EN	= (1 << 1),	/* is EDMA set up for NCQ? */
- 	MV_PP_FLAG_HAD_A_RESET	= (1 << 2),	/* 1st hard reset complete? */
- };
- 
- #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I)
- #define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
- #define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
-+#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
- 
- enum {
- 	/* DMA boundary 0xffff is required by the s/g splitting
-@@ -379,8 +406,8 @@ struct mv_port_priv {
- 	dma_addr_t		crqb_dma;
- 	struct mv_crpb		*crpb;
- 	dma_addr_t		crpb_dma;
--	struct mv_sg		*sg_tbl;
--	dma_addr_t		sg_tbl_dma;
-+	struct mv_sg		*sg_tbl[MV_MAX_Q_DEPTH];
-+	dma_addr_t		sg_tbl_dma[MV_MAX_Q_DEPTH];
- 
- 	unsigned int		req_idx;
- 	unsigned int		resp_idx;
-@@ -400,6 +427,14 @@ struct mv_host_priv {
- 	u32			irq_cause_ofs;
- 	u32			irq_mask_ofs;
- 	u32			unmask_all_irqs;
-+	/*
-+	 * These consistent DMA memory pools give us guaranteed
-+	 * alignment for hardware-accessed data structures,
-+	 * and less memory waste in accomplishing the alignment.
-+	 */
-+	struct dma_pool		*crqb_pool;
-+	struct dma_pool		*crpb_pool;
-+	struct dma_pool		*sg_tbl_pool;
- };
- 
- struct mv_hw_ops {
-@@ -411,7 +446,7 @@ struct mv_hw_ops {
- 	int (*reset_hc)(struct mv_host_priv *hpriv, void __iomem *mmio,
- 			unsigned int n_hc);
- 	void (*reset_flash)(struct mv_host_priv *hpriv, void __iomem *mmio);
--	void (*reset_bus)(struct pci_dev *pdev, void __iomem *mmio);
-+	void (*reset_bus)(struct ata_host *host, void __iomem *mmio);
- };
- 
- static void mv_irq_clear(struct ata_port *ap);
-@@ -425,10 +460,9 @@ static void mv_qc_prep(struct ata_queued_cmd *qc);
- static void mv_qc_prep_iie(struct ata_queued_cmd *qc);
- static unsigned int mv_qc_issue(struct ata_queued_cmd *qc);
- static void mv_error_handler(struct ata_port *ap);
--static void mv_post_int_cmd(struct ata_queued_cmd *qc);
- static void mv_eh_freeze(struct ata_port *ap);
- static void mv_eh_thaw(struct ata_port *ap);
--static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-+static void mv6_dev_config(struct ata_device *dev);
- 
- static void mv5_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
- 			   unsigned int port);
-@@ -438,7 +472,7 @@ static void mv5_read_preamp(struct mv_host_priv *hpriv, int idx,
- static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
- 			unsigned int n_hc);
- static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
--static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio);
-+static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio);
- 
- static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
- 			   unsigned int port);
-@@ -448,10 +482,17 @@ static void mv6_read_preamp(struct mv_host_priv *hpriv, int idx,
- static int mv6_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
- 			unsigned int n_hc);
- static void mv6_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio);
--static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio);
-+static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio);
- static void mv_channel_reset(struct mv_host_priv *hpriv, void __iomem *mmio,
- 			     unsigned int port_no);
-+static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
-+			void __iomem *port_mmio, int want_ncq);
-+static int __mv_stop_dma(struct ata_port *ap);
- 
-+/* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below
-+ * because we have to allow room for worst case splitting of
-+ * PRDs for 64K boundaries in mv_fill_sg().
-+ */
- static struct scsi_host_template mv5_sht = {
- 	.module			= THIS_MODULE,
- 	.name			= DRV_NAME,
-@@ -475,7 +516,8 @@ static struct scsi_host_template mv6_sht = {
- 	.name			= DRV_NAME,
- 	.ioctl			= ata_scsi_ioctl,
- 	.queuecommand		= ata_scsi_queuecmd,
--	.can_queue		= ATA_DEF_QUEUE,
-+	.change_queue_depth	= ata_scsi_change_queue_depth,
-+	.can_queue		= MV_MAX_Q_DEPTH - 1,
- 	.this_id		= ATA_SHT_THIS_ID,
- 	.sg_tablesize		= MV_MAX_SG_CT / 2,
- 	.cmd_per_lun		= ATA_SHT_CMD_PER_LUN,
-@@ -505,7 +547,6 @@ static const struct ata_port_operations mv5_ops = {
- 	.irq_on			= ata_irq_on,
- 
- 	.error_handler		= mv_error_handler,
--	.post_internal_cmd	= mv_post_int_cmd,
- 	.freeze			= mv_eh_freeze,
- 	.thaw			= mv_eh_thaw,
- 
-@@ -517,6 +558,7 @@ static const struct ata_port_operations mv5_ops = {
- };
- 
- static const struct ata_port_operations mv6_ops = {
-+	.dev_config             = mv6_dev_config,
- 	.tf_load		= ata_tf_load,
- 	.tf_read		= ata_tf_read,
- 	.check_status		= ata_check_status,
-@@ -533,9 +575,9 @@ static const struct ata_port_operations mv6_ops = {
- 	.irq_on			= ata_irq_on,
- 
- 	.error_handler		= mv_error_handler,
--	.post_internal_cmd	= mv_post_int_cmd,
- 	.freeze			= mv_eh_freeze,
- 	.thaw			= mv_eh_thaw,
-+	.qc_defer		= ata_std_qc_defer,
- 
- 	.scr_read		= mv_scr_read,
- 	.scr_write		= mv_scr_write,
-@@ -561,9 +603,9 @@ static const struct ata_port_operations mv_iie_ops = {
- 	.irq_on			= ata_irq_on,
- 
- 	.error_handler		= mv_error_handler,
--	.post_internal_cmd	= mv_post_int_cmd,
- 	.freeze			= mv_eh_freeze,
- 	.thaw			= mv_eh_thaw,
-+	.qc_defer		= ata_std_qc_defer,
- 
- 	.scr_read		= mv_scr_read,
- 	.scr_write		= mv_scr_write,
-@@ -592,26 +634,29 @@ static const struct ata_port_info mv_port_info[] = {
- 		.port_ops	= &mv5_ops,
- 	},
- 	{  /* chip_604x */
--		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
-+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-+				  ATA_FLAG_NCQ,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.udma_mask	= ATA_UDMA6,
- 		.port_ops	= &mv6_ops,
- 	},
- 	{  /* chip_608x */
- 		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
--				  MV_FLAG_DUAL_HC,
-+				  ATA_FLAG_NCQ | MV_FLAG_DUAL_HC,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.udma_mask	= ATA_UDMA6,
- 		.port_ops	= &mv6_ops,
- 	},
- 	{  /* chip_6042 */
--		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
-+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-+				  ATA_FLAG_NCQ,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.udma_mask	= ATA_UDMA6,
- 		.port_ops	= &mv_iie_ops,
- 	},
- 	{  /* chip_7042 */
--		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS,
-+		.flags		= MV_COMMON_FLAGS | MV_6XXX_FLAGS |
-+				  ATA_FLAG_NCQ,
- 		.pio_mask	= 0x1f,	/* pio0-4 */
- 		.udma_mask	= ATA_UDMA6,
- 		.port_ops	= &mv_iie_ops,
-@@ -648,13 +693,6 @@ static const struct pci_device_id mv_pci_tbl[] = {
- 	{ }			/* terminate list */
- };
- 
--static struct pci_driver mv_pci_driver = {
--	.name			= DRV_NAME,
--	.id_table		= mv_pci_tbl,
--	.probe			= mv_init_one,
--	.remove			= ata_pci_remove_one,
--};
--
- static const struct mv_hw_ops mv5xxx_ops = {
- 	.phy_errata		= mv5_phy_errata,
- 	.enable_leds		= mv5_enable_leds,
-@@ -674,45 +712,6 @@ static const struct mv_hw_ops mv6xxx_ops = {
- };
- 
- /*
-- * module options
-- */
--static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
--
--
--/* move to PCI layer or libata core? */
--static int pci_go_64(struct pci_dev *pdev)
--{
--	int rc;
--
--	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
--		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
--		if (rc) {
--			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
--			if (rc) {
--				dev_printk(KERN_ERR, &pdev->dev,
--					   "64-bit DMA enable failed\n");
--				return rc;
--			}
--		}
--	} else {
--		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
--		if (rc) {
--			dev_printk(KERN_ERR, &pdev->dev,
--				   "32-bit DMA enable failed\n");
--			return rc;
--		}
--		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
--		if (rc) {
--			dev_printk(KERN_ERR, &pdev->dev,
--				   "32-bit consistent DMA enable failed\n");
--			return rc;
--		}
--	}
--
--	return rc;
--}
--
--/*
-  * Functions
-  */
- 
-@@ -815,19 +814,46 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
-  *      LOCKING:
-  *      Inherited from caller.
-  */
--static void mv_start_dma(void __iomem *base, struct mv_host_priv *hpriv,
--			 struct mv_port_priv *pp)
-+static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
-+			 struct mv_port_priv *pp, u8 protocol)
- {
-+	int want_ncq = (protocol == ATA_PROT_NCQ);
++	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
++		tty_unregister_device(ntty_driver, i);
++}
 +
-+	if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) {
-+		int using_ncq = ((pp->pp_flags & MV_PP_FLAG_NCQ_EN) != 0);
-+		if (want_ncq != using_ncq)
-+			__mv_stop_dma(ap);
-+	}
- 	if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) {
-+		struct mv_host_priv *hpriv = ap->host->private_data;
-+		int hard_port = mv_hardport_from_port(ap->port_no);
-+		void __iomem *hc_mmio = mv_hc_base_from_port(
-+				ap->host->iomap[MV_PRIMARY_BAR], hard_port);
-+		u32 hc_irq_cause, ipending;
++/* Deallocate memory for one device */
++static void __devexit nozomi_card_exit(struct pci_dev *pdev)
++{
++	int i;
++	struct ctrl_ul ctrl;
++	struct nozomi *dc = pci_get_drvdata(pdev);
 +
- 		/* clear EDMA event indicators, if any */
--		writelfl(0, base + EDMA_ERR_IRQ_CAUSE_OFS);
-+		writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
++	/* Disable all interrupts */
++	dc->last_ier = 0;
++	writew(dc->last_ier, dc->reg_ier);
 +
-+		/* clear EDMA interrupt indicator, if any */
-+		hc_irq_cause = readl(hc_mmio + HC_IRQ_CAUSE_OFS);
-+		ipending = (DEV_IRQ << hard_port) |
-+				(CRPB_DMA_DONE << hard_port);
-+		if (hc_irq_cause & ipending) {
-+			writelfl(hc_irq_cause & ~ipending,
-+				 hc_mmio + HC_IRQ_CAUSE_OFS);
-+		}
++	tty_exit(dc);
 +
-+		mv_edma_cfg(pp, hpriv, port_mmio, want_ncq);
++	/* Send 0x0001, command card to resend the reset token.  */
++	/* This is to get the reset when the module is reloaded. */
++	ctrl.port = 0x00;
++	ctrl.reserved = 0;
++	ctrl.RTS = 0;
++	ctrl.DTR = 1;
++	DBG1("sending flow control 0x%04X", *((u16 *)&ctrl));
 +
-+		/* clear FIS IRQ Cause */
-+		writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
- 
--		mv_set_edma_ptrs(base, hpriv, pp);
-+		mv_set_edma_ptrs(port_mmio, hpriv, pp);
- 
--		writelfl(EDMA_EN, base + EDMA_CMD_OFS);
-+		writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
- 		pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
- 	}
--	WARN_ON(!(EDMA_EN & readl(base + EDMA_CMD_OFS)));
-+	WARN_ON(!(EDMA_EN & readl(port_mmio + EDMA_CMD_OFS)));
- }
- 
- /**
-@@ -1003,38 +1029,76 @@ static int mv_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
- 		return -EINVAL;
- }
- 
--static void mv_edma_cfg(struct ata_port *ap, struct mv_host_priv *hpriv,
--			void __iomem *port_mmio)
-+static void mv6_dev_config(struct ata_device *adev)
- {
--	u32 cfg = readl(port_mmio + EDMA_CFG_OFS);
-+	/*
-+	 * We don't have hob_nsect when doing NCQ commands on Gen-II.
-+	 * See mv_qc_prep() for more info.
-+	 */
-+	if (adev->flags & ATA_DFLAG_NCQ)
-+		if (adev->max_sectors > ATA_MAX_SECTORS)
-+			adev->max_sectors = ATA_MAX_SECTORS;
-+}
++	/* Setup dc->reg addresses to we can use defines here */
++	write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2);
++	writew(CTRL_UL, dc->reg_fcr);	/* push the token to the card. */
 +
-+static void mv_edma_cfg(struct mv_port_priv *pp, struct mv_host_priv *hpriv,
-+			void __iomem *port_mmio, int want_ncq)
-+{
-+	u32 cfg;
- 
- 	/* set up non-NCQ EDMA configuration */
--	cfg &= ~(1 << 9);	/* disable eQue */
-+	cfg = EDMA_CFG_Q_DEPTH;		/* always 0x1f for *all* chips */
- 
--	if (IS_GEN_I(hpriv)) {
--		cfg &= ~0x1f;		/* clear queue depth */
-+	if (IS_GEN_I(hpriv))
- 		cfg |= (1 << 8);	/* enab config burst size mask */
--	}
- 
--	else if (IS_GEN_II(hpriv)) {
--		cfg &= ~0x1f;		/* clear queue depth */
-+	else if (IS_GEN_II(hpriv))
- 		cfg |= EDMA_CFG_RD_BRST_EXT | EDMA_CFG_WR_BUFF_LEN;
--		cfg &= ~(EDMA_CFG_NCQ | EDMA_CFG_NCQ_GO_ON_ERR); /* clear NCQ */
--	}
- 
- 	else if (IS_GEN_IIE(hpriv)) {
- 		cfg |= (1 << 23);	/* do not mask PM field in rx'd FIS */
- 		cfg |= (1 << 22);	/* enab 4-entry host queue cache */
--		cfg &= ~(1 << 19);	/* dis 128-entry queue (for now?) */
- 		cfg |= (1 << 18);	/* enab early completion */
- 		cfg |= (1 << 17);	/* enab cut-through (dis stor&forwrd) */
--		cfg &= ~(1 << 16);	/* dis FIS-based switching (for now) */
--		cfg &= ~(EDMA_CFG_NCQ);	/* clear NCQ */
- 	}
- 
-+	if (want_ncq) {
-+		cfg |= EDMA_CFG_NCQ;
-+		pp->pp_flags |=  MV_PP_FLAG_NCQ_EN;
-+	} else
-+		pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN;
++	remove_sysfs_files(dc);
 +
- 	writelfl(cfg, port_mmio + EDMA_CFG_OFS);
- }
- 
-+static void mv_port_free_dma_mem(struct ata_port *ap)
-+{
-+	struct mv_host_priv *hpriv = ap->host->private_data;
-+	struct mv_port_priv *pp = ap->private_data;
-+	int tag;
++	free_irq(pdev->irq, dc);
 +
-+	if (pp->crqb) {
-+		dma_pool_free(hpriv->crqb_pool, pp->crqb, pp->crqb_dma);
-+		pp->crqb = NULL;
-+	}
-+	if (pp->crpb) {
-+		dma_pool_free(hpriv->crpb_pool, pp->crpb, pp->crpb_dma);
-+		pp->crpb = NULL;
-+	}
-+	/*
-+	 * For GEN_I, there's no NCQ, so we have only a single sg_tbl.
-+	 * For later hardware, we have one unique sg_tbl per NCQ tag.
-+	 */
-+	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
-+		if (pp->sg_tbl[tag]) {
-+			if (tag == 0 || !IS_GEN_I(hpriv))
-+				dma_pool_free(hpriv->sg_tbl_pool,
-+					      pp->sg_tbl[tag],
-+					      pp->sg_tbl_dma[tag]);
-+			pp->sg_tbl[tag] = NULL;
-+		}
-+	}
-+}
++	for (i = 0; i < MAX_PORT; i++)
++		if (dc->port[i].fifo_ul)
++			kfifo_free(dc->port[i].fifo_ul);
 +
- /**
-  *      mv_port_start - Port specific init/start routine.
-  *      @ap: ATA channel to manipulate
-@@ -1051,51 +1115,47 @@ static int mv_port_start(struct ata_port *ap)
- 	struct mv_host_priv *hpriv = ap->host->private_data;
- 	struct mv_port_priv *pp;
- 	void __iomem *port_mmio = mv_ap_base(ap);
--	void *mem;
--	dma_addr_t mem_dma;
- 	unsigned long flags;
--	int rc;
-+	int tag, rc;
- 
- 	pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
- 	if (!pp)
- 		return -ENOMEM;
--
--	mem = dmam_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma,
--				  GFP_KERNEL);
--	if (!mem)
--		return -ENOMEM;
--	memset(mem, 0, MV_PORT_PRIV_DMA_SZ);
-+	ap->private_data = pp;
- 
- 	rc = ata_pad_alloc(ap, dev);
- 	if (rc)
- 		return rc;
- 
--	/* First item in chunk of DMA memory:
--	 * 32-slot command request table (CRQB), 32 bytes each in size
--	 */
--	pp->crqb = mem;
--	pp->crqb_dma = mem_dma;
--	mem += MV_CRQB_Q_SZ;
--	mem_dma += MV_CRQB_Q_SZ;
-+	pp->crqb = dma_pool_alloc(hpriv->crqb_pool, GFP_KERNEL, &pp->crqb_dma);
-+	if (!pp->crqb)
-+		return -ENOMEM;
-+	memset(pp->crqb, 0, MV_CRQB_Q_SZ);
- 
--	/* Second item:
--	 * 32-slot command response table (CRPB), 8 bytes each in size
--	 */
--	pp->crpb = mem;
--	pp->crpb_dma = mem_dma;
--	mem += MV_CRPB_Q_SZ;
--	mem_dma += MV_CRPB_Q_SZ;
-+	pp->crpb = dma_pool_alloc(hpriv->crpb_pool, GFP_KERNEL, &pp->crpb_dma);
-+	if (!pp->crpb)
-+		goto out_port_free_dma_mem;
-+	memset(pp->crpb, 0, MV_CRPB_Q_SZ);
- 
--	/* Third item:
--	 * Table of scatter-gather descriptors (ePRD), 16 bytes each
-+	/*
-+	 * For GEN_I, there's no NCQ, so we only allocate a single sg_tbl.
-+	 * For later hardware, we need one unique sg_tbl per NCQ tag.
- 	 */
--	pp->sg_tbl = mem;
--	pp->sg_tbl_dma = mem_dma;
-+	for (tag = 0; tag < MV_MAX_Q_DEPTH; ++tag) {
-+		if (tag == 0 || !IS_GEN_I(hpriv)) {
-+			pp->sg_tbl[tag] = dma_pool_alloc(hpriv->sg_tbl_pool,
-+					      GFP_KERNEL, &pp->sg_tbl_dma[tag]);
-+			if (!pp->sg_tbl[tag])
-+				goto out_port_free_dma_mem;
-+		} else {
-+			pp->sg_tbl[tag]     = pp->sg_tbl[0];
-+			pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0];
-+		}
-+	}
- 
- 	spin_lock_irqsave(&ap->host->lock, flags);
- 
--	mv_edma_cfg(ap, hpriv, port_mmio);
--
-+	mv_edma_cfg(pp, hpriv, port_mmio, 0);
- 	mv_set_edma_ptrs(port_mmio, hpriv, pp);
- 
- 	spin_unlock_irqrestore(&ap->host->lock, flags);
-@@ -1104,8 +1164,11 @@ static int mv_port_start(struct ata_port *ap)
- 	 * we'll be unable to send non-data, PIO, etc due to restricted access
- 	 * to shadow regs.
- 	 */
--	ap->private_data = pp;
- 	return 0;
++	kfree(dc->send_buf);
 +
-+out_port_free_dma_mem:
-+	mv_port_free_dma_mem(ap);
-+	return -ENOMEM;
- }
- 
- /**
-@@ -1120,6 +1183,7 @@ static int mv_port_start(struct ata_port *ap)
- static void mv_port_stop(struct ata_port *ap)
- {
- 	mv_stop_dma(ap);
-+	mv_port_free_dma_mem(ap);
- }
- 
- /**
-@@ -1136,9 +1200,10 @@ static void mv_fill_sg(struct ata_queued_cmd *qc)
- 	struct mv_port_priv *pp = qc->ap->private_data;
- 	struct scatterlist *sg;
- 	struct mv_sg *mv_sg, *last_sg = NULL;
-+	unsigned int si;
- 
--	mv_sg = pp->sg_tbl;
--	ata_for_each_sg(sg, qc) {
-+	mv_sg = pp->sg_tbl[qc->tag];
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		dma_addr_t addr = sg_dma_address(sg);
- 		u32 sg_len = sg_dma_len(sg);
- 
-@@ -1193,7 +1258,8 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
- 	u16 flags = 0;
- 	unsigned in_index;
- 
--	if (qc->tf.protocol != ATA_PROT_DMA)
-+	if ((qc->tf.protocol != ATA_PROT_DMA) &&
-+	    (qc->tf.protocol != ATA_PROT_NCQ))
- 		return;
- 
- 	/* Fill in command request block
-@@ -1202,15 +1268,14 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
- 		flags |= CRQB_FLAG_READ;
- 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
- 	flags |= qc->tag << CRQB_TAG_SHIFT;
--	flags |= qc->tag << CRQB_IOID_SHIFT;	/* 50xx appears to ignore this*/
- 
- 	/* get current queue index from software */
- 	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
- 
- 	pp->crqb[in_index].sg_addr =
--		cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
-+		cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
- 	pp->crqb[in_index].sg_addr_hi =
--		cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
-+		cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
- 	pp->crqb[in_index].ctrl_flags = cpu_to_le16(flags);
- 
- 	cw = &pp->crqb[in_index].ata_cmd[0];
-@@ -1230,13 +1295,11 @@ static void mv_qc_prep(struct ata_queued_cmd *qc)
- 	case ATA_CMD_WRITE_FUA_EXT:
- 		mv_crqb_pack_cmd(cw++, tf->hob_nsect, ATA_REG_NSECT, 0);
- 		break;
--#ifdef LIBATA_NCQ		/* FIXME: remove this line when NCQ added */
- 	case ATA_CMD_FPDMA_READ:
- 	case ATA_CMD_FPDMA_WRITE:
- 		mv_crqb_pack_cmd(cw++, tf->hob_feature, ATA_REG_FEATURE, 0);
- 		mv_crqb_pack_cmd(cw++, tf->feature, ATA_REG_FEATURE, 0);
- 		break;
--#endif				/* FIXME: remove this line when NCQ added */
- 	default:
- 		/* The only other commands EDMA supports in non-queued and
- 		 * non-NCQ mode are: [RW] STREAM DMA and W DMA FUA EXT, none
-@@ -1285,7 +1348,8 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
- 	unsigned in_index;
- 	u32 flags = 0;
- 
--	if (qc->tf.protocol != ATA_PROT_DMA)
-+	if ((qc->tf.protocol != ATA_PROT_DMA) &&
-+	    (qc->tf.protocol != ATA_PROT_NCQ))
- 		return;
- 
- 	/* Fill in Gen IIE command request block
-@@ -1295,15 +1359,14 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc)
- 
- 	WARN_ON(MV_MAX_Q_DEPTH <= qc->tag);
- 	flags |= qc->tag << CRQB_TAG_SHIFT;
--	flags |= qc->tag << CRQB_IOID_SHIFT;	/* "I/O Id" is -really-
--						   what we use as our tag */
-+	flags |= qc->tag << CRQB_HOSTQ_SHIFT;
- 
- 	/* get current queue index from software */
- 	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
- 
- 	crqb = (struct mv_crqb_iie *) &pp->crqb[in_index];
--	crqb->addr = cpu_to_le32(pp->sg_tbl_dma & 0xffffffff);
--	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma >> 16) >> 16);
-+	crqb->addr = cpu_to_le32(pp->sg_tbl_dma[qc->tag] & 0xffffffff);
-+	crqb->addr_hi = cpu_to_le32((pp->sg_tbl_dma[qc->tag] >> 16) >> 16);
- 	crqb->flags = cpu_to_le32(flags);
- 
- 	tf = &qc->tf;
-@@ -1350,10 +1413,10 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
- 	struct ata_port *ap = qc->ap;
- 	void __iomem *port_mmio = mv_ap_base(ap);
- 	struct mv_port_priv *pp = ap->private_data;
--	struct mv_host_priv *hpriv = ap->host->private_data;
- 	u32 in_index;
- 
--	if (qc->tf.protocol != ATA_PROT_DMA) {
-+	if ((qc->tf.protocol != ATA_PROT_DMA) &&
-+	    (qc->tf.protocol != ATA_PROT_NCQ)) {
- 		/* We're about to send a non-EDMA capable command to the
- 		 * port.  Turn off EDMA so there won't be problems accessing
- 		 * shadow block, etc registers.
-@@ -1362,13 +1425,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
- 		return ata_qc_issue_prot(qc);
- 	}
- 
--	mv_start_dma(port_mmio, hpriv, pp);
--
--	in_index = pp->req_idx & MV_MAX_Q_DEPTH_MASK;
--
--	/* until we do queuing, the queue should be empty at this point */
--	WARN_ON(in_index != ((readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
--		>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK));
-+	mv_start_dma(ap, port_mmio, pp, qc->tf.protocol);
- 
- 	pp->req_idx++;
- 
-@@ -1436,6 +1493,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
- 		ata_ehi_hotplugged(ehi);
- 		ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
- 			"dev disconnect" : "dev connect");
-+		action |= ATA_EH_HARDRESET;
- 	}
- 
- 	if (IS_GEN_I(hpriv)) {
-@@ -1464,7 +1522,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
- 	}
- 
- 	/* Clear EDMA now that SERR cleanup done */
--	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
-+	writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
- 
- 	if (!err_mask) {
- 		err_mask = AC_ERR_OTHER;
-@@ -1537,23 +1595,17 @@ static void mv_intr_edma(struct ata_port *ap)
- 		 * support for queueing.  this works transparently for
- 		 * queued and non-queued modes.
- 		 */
--		else if (IS_GEN_II(hpriv))
--			tag = (le16_to_cpu(pp->crpb[out_index].id)
--				>> CRPB_IOID_SHIFT_6) & 0x3f;
--
--		else /* IS_GEN_IIE */
--			tag = (le16_to_cpu(pp->crpb[out_index].id)
--				>> CRPB_IOID_SHIFT_7) & 0x3f;
-+		else
-+			tag = le16_to_cpu(pp->crpb[out_index].id) & 0x1f;
- 
- 		qc = ata_qc_from_tag(ap, tag);
- 
--		/* lower 8 bits of status are EDMA_ERR_IRQ_CAUSE_OFS
--		 * bits (WARNING: might not necessarily be associated
--		 * with this command), which -should- be clear
--		 * if all is well
-+		/* For non-NCQ mode, the lower 8 bits of status
-+		 * are from EDMA_ERR_IRQ_CAUSE_OFS,
-+		 * which should be zero if all went well.
- 		 */
- 		status = le16_to_cpu(pp->crpb[out_index].flags);
--		if (unlikely(status & 0xff)) {
-+		if ((status & 0xff) && !(pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
- 			mv_err_intr(ap, qc);
- 			return;
- 		}
-@@ -1714,20 +1766,21 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
- 	struct ata_host *host = dev_instance;
- 	unsigned int hc, handled = 0, n_hcs;
- 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
--	u32 irq_stat;
-+	u32 irq_stat, irq_mask;
- 
-+	spin_lock(&host->lock);
- 	irq_stat = readl(mmio + HC_MAIN_IRQ_CAUSE_OFS);
-+	irq_mask = readl(mmio + HC_MAIN_IRQ_MASK_OFS);
- 
- 	/* check the cases where we either have nothing pending or have read
- 	 * a bogus register value which can indicate HW removal or PCI fault
- 	 */
--	if (!irq_stat || (0xffffffffU == irq_stat))
--		return IRQ_NONE;
-+	if (!(irq_stat & irq_mask) || (0xffffffffU == irq_stat))
-+		goto out_unlock;
- 
- 	n_hcs = mv_get_hc_count(host->ports[0]->flags);
--	spin_lock(&host->lock);
- 
--	if (unlikely(irq_stat & PCI_ERR)) {
-+	if (unlikely((irq_stat & PCI_ERR) && HAS_PCI(host))) {
- 		mv_pci_error(host, mmio);
- 		handled = 1;
- 		goto out_unlock;	/* skip all other HC irq handling */
-@@ -1798,8 +1851,9 @@ static int mv5_scr_write(struct ata_port *ap, unsigned int sc_reg_in, u32 val)
- 		return -EINVAL;
- }
- 
--static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
-+static void mv5_reset_bus(struct ata_host *host, void __iomem *mmio)
- {
-+	struct pci_dev *pdev = to_pci_dev(host->dev);
- 	int early_5080;
- 
- 	early_5080 = (pdev->device == 0x5080) && (pdev->revision == 0);
-@@ -1810,7 +1864,7 @@ static void mv5_reset_bus(struct pci_dev *pdev, void __iomem *mmio)
- 		writel(tmp, mmio + MV_PCI_EXP_ROM_BAR_CTL);
- 	}
- 
--	mv_reset_pci_bus(pdev, mmio);
-+	mv_reset_pci_bus(host, mmio);
- }
- 
- static void mv5_reset_flash(struct mv_host_priv *hpriv, void __iomem *mmio)
-@@ -1934,9 +1988,8 @@ static int mv5_reset_hc(struct mv_host_priv *hpriv, void __iomem *mmio,
- 
- #undef ZERO
- #define ZERO(reg) writel(0, mmio + (reg))
--static void mv_reset_pci_bus(struct pci_dev *pdev, void __iomem *mmio)
-+static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
- {
--	struct ata_host     *host = dev_get_drvdata(&pdev->dev);
- 	struct mv_host_priv *hpriv = host->private_data;
- 	u32 tmp;
- 
-@@ -2328,11 +2381,6 @@ static void mv_error_handler(struct ata_port *ap)
- 		  mv_hardreset, mv_postreset);
- }
- 
--static void mv_post_int_cmd(struct ata_queued_cmd *qc)
--{
--	mv_stop_dma(qc->ap);
--}
--
- static void mv_eh_freeze(struct ata_port *ap)
- {
- 	void __iomem *mmio = ap->host->iomap[MV_PRIMARY_BAR];
-@@ -2426,8 +2474,8 @@ static void mv_port_init(struct ata_ioports *port,  void __iomem *port_mmio)
- 	writelfl(readl(port_mmio + serr_ofs), port_mmio + serr_ofs);
- 	writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
- 
--	/* unmask all EDMA error interrupts */
--	writelfl(~0, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
-+	/* unmask all non-transient EDMA error interrupts */
-+	writelfl(~EDMA_ERR_IRQ_TRANSIENT, port_mmio + EDMA_ERR_IRQ_MASK_OFS);
- 
- 	VPRINTK("EDMA cfg=0x%08x EDMA IRQ err cause/mask=0x%08x/0x%08x\n",
- 		readl(port_mmio + EDMA_CFG_OFS),
-@@ -2585,7 +2633,6 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
- static int mv_init_host(struct ata_host *host, unsigned int board_idx)
- {
- 	int rc = 0, n_hc, port, hc;
--	struct pci_dev *pdev = to_pci_dev(host->dev);
- 	void __iomem *mmio = host->iomap[MV_PRIMARY_BAR];
- 	struct mv_host_priv *hpriv = host->private_data;
- 
-@@ -2606,7 +2653,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
- 		goto done;
- 
- 	hpriv->ops->reset_flash(hpriv, mmio);
--	hpriv->ops->reset_bus(pdev, mmio);
-+	hpriv->ops->reset_bus(host, mmio);
- 	hpriv->ops->enable_leds(hpriv, mmio);
- 
- 	for (port = 0; port < host->n_ports; port++) {
-@@ -2629,8 +2676,10 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
- 
- 		mv_port_init(&ap->ioaddr, port_mmio);
- 
-+#ifdef CONFIG_PCI
- 		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
- 		ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
-+#endif
- 	}
- 
- 	for (hc = 0; hc < n_hc; hc++) {
-@@ -2667,6 +2716,55 @@ done:
- 	return rc;
- }
- 
-+#ifdef CONFIG_PCI
-+static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
++	iounmap(dc->base_addr);
 +
-+static struct pci_driver mv_pci_driver = {
-+	.name			= DRV_NAME,
-+	.id_table		= mv_pci_tbl,
-+	.probe			= mv_init_one,
-+	.remove			= ata_pci_remove_one,
-+};
++	pci_release_regions(pdev);
 +
-+/*
-+ * module options
-+ */
-+static int msi;	      /* Use PCI msi; either zero (off, default) or non-zero */
++	pci_disable_device(pdev);
 +
++	ndevs[dc->index_start / MAX_PORT] = NULL;
 +
-+/* move to PCI layer or libata core? */
-+static int pci_go_64(struct pci_dev *pdev)
-+{
-+	int rc;
++	kfree(dc);
++}
 +
-+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
-+		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
-+		if (rc) {
-+			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-+			if (rc) {
-+				dev_printk(KERN_ERR, &pdev->dev,
-+					   "64-bit DMA enable failed\n");
-+				return rc;
-+			}
-+		}
-+	} else {
-+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-+		if (rc) {
-+			dev_printk(KERN_ERR, &pdev->dev,
-+				   "32-bit DMA enable failed\n");
-+			return rc;
-+		}
-+		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
-+		if (rc) {
-+			dev_printk(KERN_ERR, &pdev->dev,
-+				   "32-bit consistent DMA enable failed\n");
-+			return rc;
-+		}
-+	}
++static void set_rts(const struct tty_struct *tty, int rts)
++{
++	struct port *port = get_port_by_tty(tty);
 +
-+	return rc;
++	port->ctrl_ul.RTS = rts;
++	port->update_flow_control = 1;
++	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
 +}
 +
- /**
-  *      mv_print_info - Dump key info to kernel log for perusal.
-  *      @host: ATA host to print info about
-@@ -2709,6 +2807,26 @@ static void mv_print_info(struct ata_host *host)
- 	       scc_s, (MV_HP_FLAG_MSI & hpriv->hp_flags) ? "MSI" : "INTx");
- }
- 
-+static int mv_create_dma_pools(struct mv_host_priv *hpriv, struct device *dev)
++static void set_dtr(const struct tty_struct *tty, int dtr)
 +{
-+	hpriv->crqb_pool   = dmam_pool_create("crqb_q", dev, MV_CRQB_Q_SZ,
-+							     MV_CRQB_Q_SZ, 0);
-+	if (!hpriv->crqb_pool)
-+		return -ENOMEM;
-+
-+	hpriv->crpb_pool   = dmam_pool_create("crpb_q", dev, MV_CRPB_Q_SZ,
-+							     MV_CRPB_Q_SZ, 0);
-+	if (!hpriv->crpb_pool)
-+		return -ENOMEM;
++	struct port *port = get_port_by_tty(tty);
 +
-+	hpriv->sg_tbl_pool = dmam_pool_create("sg_tbl", dev, MV_SG_TBL_SZ,
-+							     MV_SG_TBL_SZ, 0);
-+	if (!hpriv->sg_tbl_pool)
-+		return -ENOMEM;
++	DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr);
 +
-+	return 0;
++	port->ctrl_ul.DTR = dtr;
++	port->update_flow_control = 1;
++	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
 +}
 +
- /**
-  *      mv_init_one - handle a positive probe of a Marvell host
-  *      @pdev: PCI device found
-@@ -2754,6 +2872,10 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- 	if (rc)
- 		return rc;
- 
-+	rc = mv_create_dma_pools(hpriv, &pdev->dev);
-+	if (rc)
-+		return rc;
++/*
++ * ----------------------------------------------------------------------------
++ * TTY code
++ * ----------------------------------------------------------------------------
++ */
 +
- 	/* initialize adapter */
- 	rc = mv_init_host(host, board_idx);
- 	if (rc)
-@@ -2771,15 +2893,22 @@ static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
- 	return ata_host_activate(host, pdev->irq, mv_interrupt, IRQF_SHARED,
- 				 IS_GEN_I(hpriv) ? &mv5_sht : &mv6_sht);
- }
-+#endif
- 
- static int __init mv_init(void)
- {
--	return pci_register_driver(&mv_pci_driver);
-+	int rc = -ENODEV;
-+#ifdef CONFIG_PCI
-+	rc = pci_register_driver(&mv_pci_driver);
-+#endif
-+	return rc;
- }
- 
- static void __exit mv_exit(void)
- {
-+#ifdef CONFIG_PCI
- 	pci_unregister_driver(&mv_pci_driver);
-+#endif
- }
- 
- MODULE_AUTHOR("Brett Russ");
-@@ -2788,8 +2917,10 @@ MODULE_LICENSE("GPL");
- MODULE_DEVICE_TABLE(pci, mv_pci_tbl);
- MODULE_VERSION(DRV_VERSION);
- 
-+#ifdef CONFIG_PCI
- module_param(msi, int, 0444);
- MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)");
-+#endif
- 
- module_init(mv_init);
- module_exit(mv_exit);
-diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
-index ed5dc7c..bfe92a4 100644
---- a/drivers/ata/sata_nv.c
-+++ b/drivers/ata/sata_nv.c
-@@ -1011,14 +1011,20 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
- 			}
- 
- 			if (status & (NV_ADMA_STAT_DONE |
--				      NV_ADMA_STAT_CPBERR)) {
--				u32 check_commands;
-+				      NV_ADMA_STAT_CPBERR |
-+				      NV_ADMA_STAT_CMD_COMPLETE)) {
-+				u32 check_commands = notifier_clears[i];
- 				int pos, error = 0;
- 
--				if (ata_tag_valid(ap->link.active_tag))
--					check_commands = 1 << ap->link.active_tag;
--				else
--					check_commands = ap->link.sactive;
-+				if (status & NV_ADMA_STAT_CPBERR) {
-+					/* Check all active commands */
-+					if (ata_tag_valid(ap->link.active_tag))
-+						check_commands = 1 <<
-+							ap->link.active_tag;
-+					else
-+						check_commands = ap->
-+							link.sactive;
-+				}
- 
- 				/** Check CPBs for completed commands */
- 				while ((pos = ffs(check_commands)) && !error) {
-@@ -1336,21 +1342,18 @@ static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
- static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
- {
- 	struct nv_adma_port_priv *pp = qc->ap->private_data;
--	unsigned int idx;
- 	struct nv_adma_prd *aprd;
- 	struct scatterlist *sg;
-+	unsigned int si;
- 
- 	VPRINTK("ENTER\n");
- 
--	idx = 0;
--
--	ata_for_each_sg(sg, qc) {
--		aprd = (idx < 5) ? &cpb->aprd[idx] :
--			       &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
--		nv_adma_fill_aprd(qc, sg, idx, aprd);
--		idx++;
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
-+		aprd = (si < 5) ? &cpb->aprd[si] :
-+			       &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (si-5)];
-+		nv_adma_fill_aprd(qc, sg, si, aprd);
- 	}
--	if (idx > 5)
-+	if (si > 5)
- 		cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
- 	else
- 		cpb->next_aprd = cpu_to_le64(0);
-@@ -1995,17 +1998,14 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
- {
- 	struct ata_port *ap = qc->ap;
- 	struct scatterlist *sg;
--	unsigned int idx;
- 	struct nv_swncq_port_priv *pp = ap->private_data;
- 	struct ata_prd *prd;
--
--	WARN_ON(qc->__sg == NULL);
--	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
-+	unsigned int si, idx;
- 
- 	prd = pp->prd + ATA_MAX_PRD * qc->tag;
- 
- 	idx = 0;
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		u32 addr, offset;
- 		u32 sg_len, len;
- 
-@@ -2027,8 +2027,7 @@ static void nv_swncq_fill_sg(struct ata_queued_cmd *qc)
- 		}
- 	}
- 
--	if (idx)
--		prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-+	prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
- }
- 
- static unsigned int nv_swncq_issue_atacmd(struct ata_port *ap,
-diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
-index 7914def..a07d319 100644
---- a/drivers/ata/sata_promise.c
-+++ b/drivers/ata/sata_promise.c
-@@ -450,19 +450,19 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
- 	struct pdc_port_priv *pp = ap->private_data;
- 	u8 *buf = pp->pkt;
- 	u32 *buf32 = (u32 *) buf;
--	unsigned int dev_sel, feature, nbytes;
-+	unsigned int dev_sel, feature;
- 
- 	/* set control bits (byte 0), zero delay seq id (byte 3),
- 	 * and seq id (byte 2)
- 	 */
- 	switch (qc->tf.protocol) {
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		if (!(qc->tf.flags & ATA_TFLAG_WRITE))
- 			buf32[0] = cpu_to_le32(PDC_PKT_READ);
- 		else
- 			buf32[0] = 0;
- 		break;
--	case ATA_PROT_ATAPI_NODATA:
-+	case ATAPI_PROT_NODATA:
- 		buf32[0] = cpu_to_le32(PDC_PKT_NODATA);
- 		break;
- 	default:
-@@ -473,45 +473,37 @@ static void pdc_atapi_pkt(struct ata_queued_cmd *qc)
- 	buf32[2] = 0;				/* no next-packet */
- 
- 	/* select drive */
--	if (sata_scr_valid(&ap->link)) {
-+	if (sata_scr_valid(&ap->link))
- 		dev_sel = PDC_DEVICE_SATA;
--	} else {
--		dev_sel = ATA_DEVICE_OBS;
--		if (qc->dev->devno != 0)
--			dev_sel |= ATA_DEV1;
--	}
-+	else
-+		dev_sel = qc->tf.device;
++/* Called when the userspace process opens the tty, /dev/noz*.  */
++static int ntty_open(struct tty_struct *tty, struct file *file)
++{
++	struct port *port = get_port_by_tty(tty);
++	struct nozomi *dc = get_dc_by_tty(tty);
++	unsigned long flags;
 +
- 	buf[12] = (1 << 5) | ATA_REG_DEVICE;
- 	buf[13] = dev_sel;
- 	buf[14] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_CLEAR_BSY;
- 	buf[15] = dev_sel; /* once more, waiting for BSY to clear */
- 
- 	buf[16] = (1 << 5) | ATA_REG_NSECT;
--	buf[17] = 0x00;
-+	buf[17] = qc->tf.nsect;
- 	buf[18] = (1 << 5) | ATA_REG_LBAL;
--	buf[19] = 0x00;
-+	buf[19] = qc->tf.lbal;
- 
- 	/* set feature and byte counter registers */
--	if (qc->tf.protocol != ATA_PROT_ATAPI_DMA) {
-+	if (qc->tf.protocol != ATAPI_PROT_DMA)
- 		feature = PDC_FEATURE_ATAPI_PIO;
--		/* set byte counter register to real transfer byte count */
--		nbytes = qc->nbytes;
--		if (nbytes > 0xffff)
--			nbytes = 0xffff;
--	} else {
-+	else
- 		feature = PDC_FEATURE_ATAPI_DMA;
--		/* set byte counter register to 0 */
--		nbytes = 0;
--	}
++	if (!port || !dc)
++		return -ENODEV;
++
++	if (mutex_lock_interruptible(&port->tty_sem))
++		return -ERESTARTSYS;
++
++	port->tty_open_count++;
++	dc->open_ttys++;
++
++	/* Enable interrupt downlink for channel */
++	if (port->tty_open_count == 1) {
++		tty->low_latency = 1;
++		tty->driver_data = port;
++		port->tty = tty;
++		DBG1("open: %d", port->token_dl);
++		spin_lock_irqsave(&dc->spin_mutex, flags);
++		dc->last_ier = dc->last_ier | port->token_dl;
++		writew(dc->last_ier, dc->reg_ier);
++		spin_unlock_irqrestore(&dc->spin_mutex, flags);
++	}
 +
- 	buf[20] = (1 << 5) | ATA_REG_FEATURE;
- 	buf[21] = feature;
- 	buf[22] = (1 << 5) | ATA_REG_BYTEL;
--	buf[23] = nbytes & 0xFF;
-+	buf[23] = qc->tf.lbam;
- 	buf[24] = (1 << 5) | ATA_REG_BYTEH;
--	buf[25] = (nbytes >> 8) & 0xFF;
-+	buf[25] = qc->tf.lbah;
- 
- 	/* send ATAPI packet command 0xA0 */
- 	buf[26] = (1 << 5) | ATA_REG_CMD;
--	buf[27] = ATA_CMD_PACKET;
-+	buf[27] = qc->tf.command;
- 
- 	/* select drive and check DRQ */
- 	buf[28] = (1 << 5) | ATA_REG_DEVICE | PDC_PKT_WAIT_DRDY;
-@@ -541,17 +533,15 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
- {
- 	struct ata_port *ap = qc->ap;
- 	struct scatterlist *sg;
--	unsigned int idx;
- 	const u32 SG_COUNT_ASIC_BUG = 41*4;
-+	unsigned int si, idx;
-+	u32 len;
- 
- 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
- 		return;
- 
--	WARN_ON(qc->__sg == NULL);
--	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
--
- 	idx = 0;
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		u32 addr, offset;
- 		u32 sg_len, len;
- 
-@@ -578,29 +568,27 @@ static void pdc_fill_sg(struct ata_queued_cmd *qc)
- 		}
- 	}
- 
--	if (idx) {
--		u32 len = le32_to_cpu(ap->prd[idx - 1].flags_len);
-+	len = le32_to_cpu(ap->prd[idx - 1].flags_len);
- 
--		if (len > SG_COUNT_ASIC_BUG) {
--			u32 addr;
-+	if (len > SG_COUNT_ASIC_BUG) {
-+		u32 addr;
- 
--			VPRINTK("Splitting last PRD.\n");
-+		VPRINTK("Splitting last PRD.\n");
- 
--			addr = le32_to_cpu(ap->prd[idx - 1].addr);
--			ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
--			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
-+		addr = le32_to_cpu(ap->prd[idx - 1].addr);
-+		ap->prd[idx - 1].flags_len = cpu_to_le32(len - SG_COUNT_ASIC_BUG);
-+		VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx - 1, addr, SG_COUNT_ASIC_BUG);
- 
--			addr = addr + len - SG_COUNT_ASIC_BUG;
--			len = SG_COUNT_ASIC_BUG;
--			ap->prd[idx].addr = cpu_to_le32(addr);
--			ap->prd[idx].flags_len = cpu_to_le32(len);
--			VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
-+		addr = addr + len - SG_COUNT_ASIC_BUG;
-+		len = SG_COUNT_ASIC_BUG;
-+		ap->prd[idx].addr = cpu_to_le32(addr);
-+		ap->prd[idx].flags_len = cpu_to_le32(len);
-+		VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len);
- 
--			idx++;
--		}
--
--		ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
-+		idx++;
- 	}
++	mutex_unlock(&port->tty_sem);
 +
-+	ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT);
- }
- 
- static void pdc_qc_prep(struct ata_queued_cmd *qc)
-@@ -627,14 +615,14 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
- 		pdc_pkt_footer(&qc->tf, pp->pkt, i);
- 		break;
- 
--	case ATA_PROT_ATAPI:
-+	case ATAPI_PROT_PIO:
- 		pdc_fill_sg(qc);
- 		break;
- 
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		pdc_fill_sg(qc);
- 		/*FALLTHROUGH*/
--	case ATA_PROT_ATAPI_NODATA:
-+	case ATAPI_PROT_NODATA:
- 		pdc_atapi_pkt(qc);
- 		break;
- 
-@@ -754,8 +742,8 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
- 	switch (qc->tf.protocol) {
- 	case ATA_PROT_DMA:
- 	case ATA_PROT_NODATA:
--	case ATA_PROT_ATAPI_DMA:
--	case ATA_PROT_ATAPI_NODATA:
-+	case ATAPI_PROT_DMA:
-+	case ATAPI_PROT_NODATA:
- 		qc->err_mask |= ac_err_mask(ata_wait_idle(ap));
- 		ata_qc_complete(qc);
- 		handled = 1;
-@@ -900,7 +888,7 @@ static inline void pdc_packet_start(struct ata_queued_cmd *qc)
- static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
- {
- 	switch (qc->tf.protocol) {
--	case ATA_PROT_ATAPI_NODATA:
-+	case ATAPI_PROT_NODATA:
- 		if (qc->dev->flags & ATA_DFLAG_CDB_INTR)
- 			break;
- 		/*FALLTHROUGH*/
-@@ -908,7 +896,7 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
- 		if (qc->tf.flags & ATA_TFLAG_POLLING)
- 			break;
- 		/*FALLTHROUGH*/
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 	case ATA_PROT_DMA:
- 		pdc_packet_start(qc);
- 		return 0;
-@@ -922,16 +910,14 @@ static unsigned int pdc_qc_issue_prot(struct ata_queued_cmd *qc)
- 
- static void pdc_tf_load_mmio(struct ata_port *ap, const struct ata_taskfile *tf)
- {
--	WARN_ON(tf->protocol == ATA_PROT_DMA ||
--		tf->protocol == ATA_PROT_ATAPI_DMA);
-+	WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
- 	ata_tf_load(ap, tf);
- }
- 
- static void pdc_exec_command_mmio(struct ata_port *ap,
- 				  const struct ata_taskfile *tf)
- {
--	WARN_ON(tf->protocol == ATA_PROT_DMA ||
--		tf->protocol == ATA_PROT_ATAPI_DMA);
-+	WARN_ON(tf->protocol == ATA_PROT_DMA || tf->protocol == ATAPI_PROT_DMA);
- 	ata_exec_command(ap, tf);
- }
- 
-diff --git a/drivers/ata/sata_promise.h b/drivers/ata/sata_promise.h
-index 6ee5e19..00d6000 100644
---- a/drivers/ata/sata_promise.h
-+++ b/drivers/ata/sata_promise.h
-@@ -46,7 +46,7 @@ static inline unsigned int pdc_pkt_header(struct ata_taskfile *tf,
- 					  unsigned int devno, u8 *buf)
- {
- 	u8 dev_reg;
--	u32 *buf32 = (u32 *) buf;
-+	__le32 *buf32 = (__le32 *) buf;
- 
- 	/* set control bits (byte 0), zero delay seq id (byte 3),
- 	 * and seq id (byte 2)
-diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c
-index c68b241..91cc12c 100644
---- a/drivers/ata/sata_qstor.c
-+++ b/drivers/ata/sata_qstor.c
-@@ -287,14 +287,10 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
- 	struct scatterlist *sg;
- 	struct ata_port *ap = qc->ap;
- 	struct qs_port_priv *pp = ap->private_data;
--	unsigned int nelem;
- 	u8 *prd = pp->pkt + QS_CPB_BYTES;
-+	unsigned int si;
- 
--	WARN_ON(qc->__sg == NULL);
--	WARN_ON(qc->n_elem == 0 && qc->pad_len == 0);
--
--	nelem = 0;
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		u64 addr;
- 		u32 len;
- 
-@@ -306,12 +302,11 @@ static unsigned int qs_fill_sg(struct ata_queued_cmd *qc)
- 		*(__le32 *)prd = cpu_to_le32(len);
- 		prd += sizeof(u64);
- 
--		VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
-+		VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", si,
- 					(unsigned long long)addr, len);
--		nelem++;
- 	}
- 
--	return nelem;
-+	return si;
- }
- 
- static void qs_qc_prep(struct ata_queued_cmd *qc)
-@@ -376,7 +371,7 @@ static unsigned int qs_qc_issue(struct ata_queued_cmd *qc)
- 		qs_packet_start(qc);
- 		return 0;
- 
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		BUG();
- 		break;
- 
-diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
-index f5119bf..0b8191b 100644
---- a/drivers/ata/sata_sil.c
-+++ b/drivers/ata/sata_sil.c
-@@ -416,15 +416,14 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
- 		 */
- 
- 		/* Check the ATA_DFLAG_CDB_INTR flag is enough here.
--		 * The flag was turned on only for atapi devices.
--		 * No need to check is_atapi_taskfile(&qc->tf) again.
-+		 * The flag was turned on only for atapi devices.  No
-+		 * need to check ata_is_atapi(qc->tf.protocol) again.
- 		 */
- 		if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
- 			goto err_hsm;
- 		break;
- 	case HSM_ST_LAST:
--		if (qc->tf.protocol == ATA_PROT_DMA ||
--		    qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
-+		if (ata_is_dma(qc->tf.protocol)) {
- 			/* clear DMA-Start bit */
- 			ap->ops->bmdma_stop(qc);
- 
-@@ -451,8 +450,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2)
- 	/* kick HSM in the ass */
- 	ata_hsm_move(ap, qc, status, 0);
- 
--	if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA ||
--				       qc->tf.protocol == ATA_PROT_ATAPI_DMA))
-+	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
- 		ata_ehi_push_desc(ehi, "BMDMA2 stat 0x%x", bmdma2);
- 
- 	return;
-diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
-index 864c1c1..b4b1f91 100644
---- a/drivers/ata/sata_sil24.c
-+++ b/drivers/ata/sata_sil24.c
-@@ -813,8 +813,9 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
- {
- 	struct scatterlist *sg;
- 	struct sil24_sge *last_sge = NULL;
-+	unsigned int si;
- 
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		sge->addr = cpu_to_le64(sg_dma_address(sg));
- 		sge->cnt = cpu_to_le32(sg_dma_len(sg));
- 		sge->flags = 0;
-@@ -823,8 +824,7 @@ static inline void sil24_fill_sg(struct ata_queued_cmd *qc,
- 		sge++;
- 	}
- 
--	if (likely(last_sge))
--		last_sge->flags = cpu_to_le32(SGE_TRM);
-+	last_sge->flags = cpu_to_le32(SGE_TRM);
- }
- 
- static int sil24_qc_defer(struct ata_queued_cmd *qc)
-@@ -852,9 +852,7 @@ static int sil24_qc_defer(struct ata_queued_cmd *qc)
- 	 *   set.
- 	 *
-  	 */
--	int is_excl = (prot == ATA_PROT_ATAPI ||
--		       prot == ATA_PROT_ATAPI_NODATA ||
--		       prot == ATA_PROT_ATAPI_DMA ||
-+	int is_excl = (ata_is_atapi(prot) ||
- 		       (qc->flags & ATA_QCFLAG_RESULT_TF));
- 
- 	if (unlikely(ap->excl_link)) {
-@@ -885,35 +883,21 @@ static void sil24_qc_prep(struct ata_queued_cmd *qc)
- 
- 	cb = &pp->cmd_block[sil24_tag(qc->tag)];
- 
--	switch (qc->tf.protocol) {
--	case ATA_PROT_PIO:
--	case ATA_PROT_DMA:
--	case ATA_PROT_NCQ:
--	case ATA_PROT_NODATA:
-+	if (!ata_is_atapi(qc->tf.protocol)) {
- 		prb = &cb->ata.prb;
- 		sge = cb->ata.sge;
--		break;
--
--	case ATA_PROT_ATAPI:
--	case ATA_PROT_ATAPI_DMA:
--	case ATA_PROT_ATAPI_NODATA:
-+	} else {
- 		prb = &cb->atapi.prb;
- 		sge = cb->atapi.sge;
- 		memset(cb->atapi.cdb, 0, 32);
- 		memcpy(cb->atapi.cdb, qc->cdb, qc->dev->cdb_len);
- 
--		if (qc->tf.protocol != ATA_PROT_ATAPI_NODATA) {
-+		if (ata_is_data(qc->tf.protocol)) {
- 			if (qc->tf.flags & ATA_TFLAG_WRITE)
- 				ctrl = PRB_CTRL_PACKET_WRITE;
- 			else
- 				ctrl = PRB_CTRL_PACKET_READ;
- 		}
--		break;
--
--	default:
--		prb = NULL;	/* shut up, gcc */
--		sge = NULL;
--		BUG();
- 	}
- 
- 	prb->ctrl = cpu_to_le16(ctrl);
-diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
-index 4d85718..e3d56bc 100644
---- a/drivers/ata/sata_sx4.c
-+++ b/drivers/ata/sata_sx4.c
-@@ -334,7 +334,7 @@ static inline void pdc20621_ata_sg(struct ata_taskfile *tf, u8 *buf,
- {
- 	u32 addr;
- 	unsigned int dw = PDC_DIMM_APKT_PRD >> 2;
--	u32 *buf32 = (u32 *) buf;
-+	__le32 *buf32 = (__le32 *) buf;
- 
- 	/* output ATA packet S/G table */
- 	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
-@@ -356,7 +356,7 @@ static inline void pdc20621_host_sg(struct ata_taskfile *tf, u8 *buf,
- {
- 	u32 addr;
- 	unsigned int dw = PDC_DIMM_HPKT_PRD >> 2;
--	u32 *buf32 = (u32 *) buf;
-+	__le32 *buf32 = (__le32 *) buf;
- 
- 	/* output Host DMA packet S/G table */
- 	addr = PDC_20621_DIMM_BASE + PDC_20621_DIMM_DATA +
-@@ -377,7 +377,7 @@ static inline unsigned int pdc20621_ata_pkt(struct ata_taskfile *tf,
- 					    unsigned int portno)
- {
- 	unsigned int i, dw;
--	u32 *buf32 = (u32 *) buf;
-+	__le32 *buf32 = (__le32 *) buf;
- 	u8 dev_reg;
- 
- 	unsigned int dimm_sg = PDC_20621_DIMM_BASE +
-@@ -429,7 +429,8 @@ static inline void pdc20621_host_pkt(struct ata_taskfile *tf, u8 *buf,
- 				     unsigned int portno)
- {
- 	unsigned int dw;
--	u32 tmp, *buf32 = (u32 *) buf;
-+	u32 tmp;
-+	__le32 *buf32 = (__le32 *) buf;
- 
- 	unsigned int host_sg = PDC_20621_DIMM_BASE +
- 			       (PDC_DIMM_WINDOW_STEP * portno) +
-@@ -473,7 +474,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
- 	void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
- 	void __iomem *dimm_mmio = ap->host->iomap[PDC_DIMM_BAR];
- 	unsigned int portno = ap->port_no;
--	unsigned int i, idx, total_len = 0, sgt_len;
-+	unsigned int i, si, idx, total_len = 0, sgt_len;
- 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
- 
- 	WARN_ON(!(qc->flags & ATA_QCFLAG_DMAMAP));
-@@ -487,7 +488,7 @@ static void pdc20621_dma_prep(struct ata_queued_cmd *qc)
- 	 * Build S/G table
- 	 */
- 	idx = 0;
--	ata_for_each_sg(sg, qc) {
-+	for_each_sg(qc->sg, sg, qc->n_elem, si) {
- 		buf[idx++] = cpu_to_le32(sg_dma_address(sg));
- 		buf[idx++] = cpu_to_le32(sg_dma_len(sg));
- 		total_len += sg_dma_len(sg);
-@@ -700,7 +701,7 @@ static unsigned int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc)
- 		pdc20621_packet_start(qc);
- 		return 0;
- 
--	case ATA_PROT_ATAPI_DMA:
-+	case ATAPI_PROT_DMA:
- 		BUG();
- 		break;
- 
-diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
-index b34b382..7b44a59 100644
---- a/drivers/atm/ambassador.c
-+++ b/drivers/atm/ambassador.c
-@@ -2163,7 +2163,6 @@ static int __devinit amb_init (amb_dev * dev)
- static void setup_dev(amb_dev *dev, struct pci_dev *pci_dev) 
- {
-       unsigned char pool;
--      memset (dev, 0, sizeof(amb_dev));
-       
-       // set up known dev items straight away
-       dev->pci_dev = pci_dev; 
-@@ -2253,7 +2252,7 @@ static int __devinit amb_probe(struct pci_dev *pci_dev, const struct pci_device_
- 		goto out_disable;
- 	}
- 
--	dev = kmalloc (sizeof(amb_dev), GFP_KERNEL);
-+	dev = kzalloc(sizeof(amb_dev), GFP_KERNEL);
- 	if (!dev) {
- 		PRINTK (KERN_ERR, "out of memory!");
- 		err = -ENOMEM;
-diff --git a/drivers/atm/he.c b/drivers/atm/he.c
-index 3b64a99..2e3395b 100644
---- a/drivers/atm/he.c
-+++ b/drivers/atm/he.c
-@@ -1,5 +1,3 @@
--/* $Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $ */
--
- /*
- 
-   he.c
-@@ -99,10 +97,6 @@
- #define HPRINTK(fmt,args...)	do { } while (0)
- #endif /* HE_DEBUG */
- 
--/* version definition */
--
--static char *version = "$Id: he.c,v 1.18 2003/05/06 22:57:15 chas Exp $";
--
- /* declarations */
- 
- static int he_open(struct atm_vcc *vcc);
-@@ -366,7 +360,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
- 	struct he_dev *he_dev = NULL;
- 	int err = 0;
- 
--	printk(KERN_INFO "he: %s\n", version);
-+	printk(KERN_INFO "ATM he driver\n");
- 
- 	if (pci_enable_device(pci_dev))
- 		return -EIO;
-@@ -1643,6 +1637,8 @@ he_stop(struct he_dev *he_dev)
- 
- 	if (he_dev->rbpl_base) {
- #ifdef USE_RBPL_POOL
-+		int i;
++	return 0;
++}
 +
- 		for (i = 0; i < CONFIG_RBPL_SIZE; ++i) {
- 			void *cpuaddr = he_dev->rbpl_virt[i].virt;
- 			dma_addr_t dma_handle = he_dev->rbpl_base[i].phys;
-@@ -1665,6 +1661,8 @@ he_stop(struct he_dev *he_dev)
- #ifdef USE_RBPS
- 	if (he_dev->rbps_base) {
- #ifdef USE_RBPS_POOL
-+		int i;
++/* Called when the userspace process close the tty, /dev/noz*. */
++static void ntty_close(struct tty_struct *tty, struct file *file)
++{
++	struct nozomi *dc = get_dc_by_tty(tty);
++	struct port *port = tty->driver_data;
++	unsigned long flags;
 +
- 		for (i = 0; i < CONFIG_RBPS_SIZE; ++i) {
- 			void *cpuaddr = he_dev->rbps_virt[i].virt;
- 			dma_addr_t dma_handle = he_dev->rbps_base[i].phys;
-@@ -2933,7 +2931,7 @@ he_proc_read(struct atm_dev *dev, loff_t *pos, char *page)
- 
- 	left = *pos;
- 	if (!left--)
--		return sprintf(page, "%s\n", version);
-+		return sprintf(page, "ATM he driver\n");
- 
- 	if (!left--)
- 		return sprintf(page, "%s%s\n\n",
-diff --git a/drivers/base/Makefile b/drivers/base/Makefile
-index b39ea3f..63e09c0 100644
---- a/drivers/base/Makefile
-+++ b/drivers/base/Makefile
-@@ -11,6 +11,9 @@ obj-$(CONFIG_FW_LOADER)	+= firmware_class.o
- obj-$(CONFIG_NUMA)	+= node.o
- obj-$(CONFIG_MEMORY_HOTPLUG_SPARSE) += memory.o
- obj-$(CONFIG_SMP)	+= topology.o
-+ifeq ($(CONFIG_SYSFS),y)
-+obj-$(CONFIG_MODULES)	+= module.o
-+endif
- obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
- 
- ifeq ($(CONFIG_DEBUG_DRIVER),y)
-diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
-index 7370d7c..3b43e8a 100644
---- a/drivers/base/attribute_container.c
-+++ b/drivers/base/attribute_container.c
-@@ -61,7 +61,7 @@ attribute_container_classdev_to_container(struct class_device *classdev)
- }
- EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
- 
--static struct list_head attribute_container_list;
-+static LIST_HEAD(attribute_container_list);
- 
- static DEFINE_MUTEX(attribute_container_mutex);
- 
-@@ -320,9 +320,14 @@ attribute_container_add_attrs(struct class_device *classdev)
- 	struct class_device_attribute **attrs =	cont->attrs;
- 	int i, error;
- 
--	if (!attrs)
-+	BUG_ON(attrs && cont->grp);
++	if (!dc || !port)
++		return;
 +
-+	if (!attrs && !cont->grp)
- 		return 0;
- 
-+	if (cont->grp)
-+		return sysfs_create_group(&classdev->kobj, cont->grp);
++	if (mutex_lock_interruptible(&port->tty_sem))
++		return;
 +
- 	for (i = 0; attrs[i]; i++) {
- 		error = class_device_create_file(classdev, attrs[i]);
- 		if (error)
-@@ -378,9 +383,14 @@ attribute_container_remove_attrs(struct class_device *classdev)
- 	struct class_device_attribute **attrs =	cont->attrs;
- 	int i;
- 
--	if (!attrs)
-+	if (!attrs && !cont->grp)
- 		return;
- 
-+	if (cont->grp) {
-+		sysfs_remove_group(&classdev->kobj, cont->grp);
-+		return ;
++	if (!port->tty_open_count)
++		goto exit;
++
++	dc->open_ttys--;
++	port->tty_open_count--;
++
++	if (port->tty_open_count == 0) {
++		DBG1("close: %d", port->token_dl);
++		spin_lock_irqsave(&dc->spin_mutex, flags);
++		dc->last_ier &= ~(port->token_dl);
++		writew(dc->last_ier, dc->reg_ier);
++		spin_unlock_irqrestore(&dc->spin_mutex, flags);
 +	}
 +
- 	for (i = 0; attrs[i]; i++)
- 		class_device_remove_file(classdev, attrs[i]);
- }
-@@ -429,10 +439,3 @@ attribute_container_find_class_device(struct attribute_container *cont,
- 	return cdev;
- }
- EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
--
--int __init
--attribute_container_init(void)
--{
--	INIT_LIST_HEAD(&attribute_container_list);
--	return 0;
--}
-diff --git a/drivers/base/base.h b/drivers/base/base.h
-index 10b2fb6..c044414 100644
---- a/drivers/base/base.h
-+++ b/drivers/base/base.h
-@@ -1,6 +1,42 @@
- 
--/* initialisation functions */
-+/**
-+ * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
-+ *
-+ * @subsys - the struct kset that defines this bus.  This is the main kobject
-+ * @drivers_kset - the list of drivers associated with this bus
-+ * @devices_kset - the list of devices associated with this bus
-+ * @klist_devices - the klist to iterate over the @devices_kset
-+ * @klist_drivers - the klist to iterate over the @drivers_kset
-+ * @bus_notifier - the bus notifier list for anything that cares about things
-+ * on this bus.
-+ * @bus - pointer back to the struct bus_type that this structure is associated
-+ * with.
-+ *
-+ * This structure is the one that is the actual kobject allowing struct
-+ * bus_type to be statically allocated safely.  Nothing outside of the driver
-+ * core should ever touch these fields.
++exit:
++	mutex_unlock(&port->tty_sem);
++}
++
++/*
++ * called when the userspace process writes to the tty (/dev/noz*).
++ * Data is inserted into a fifo, which is then read and transfered to the modem.
 + */
-+struct bus_type_private {
-+	struct kset subsys;
-+	struct kset *drivers_kset;
-+	struct kset *devices_kset;
-+	struct klist klist_devices;
-+	struct klist klist_drivers;
-+	struct blocking_notifier_head bus_notifier;
-+	unsigned int drivers_autoprobe:1;
-+	struct bus_type *bus;
-+};
++static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
++		      int count)
++{
++	int rval = -EINVAL;
++	struct nozomi *dc = get_dc_by_tty(tty);
++	struct port *port = tty->driver_data;
++	unsigned long flags;
 +
-+struct driver_private {
-+	struct kobject kobj;
-+	struct klist klist_devices;
-+	struct klist_node knode_bus;
-+	struct module_kobject *mkobj;
-+	struct device_driver *driver;
-+};
-+#define to_driver(obj) container_of(obj, struct driver_private, kobj)
- 
-+/* initialisation functions */
- extern int devices_init(void);
- extern int buses_init(void);
- extern int classes_init(void);
-@@ -13,17 +49,16 @@ static inline int hypervisor_init(void) { return 0; }
- extern int platform_bus_init(void);
- extern int system_bus_init(void);
- extern int cpu_dev_init(void);
--extern int attribute_container_init(void);
- 
--extern int bus_add_device(struct device * dev);
--extern void bus_attach_device(struct device * dev);
--extern void bus_remove_device(struct device * dev);
-+extern int bus_add_device(struct device *dev);
-+extern void bus_attach_device(struct device *dev);
-+extern void bus_remove_device(struct device *dev);
- 
--extern int bus_add_driver(struct device_driver *);
--extern void bus_remove_driver(struct device_driver *);
-+extern int bus_add_driver(struct device_driver *drv);
-+extern void bus_remove_driver(struct device_driver *drv);
- 
--extern void driver_detach(struct device_driver * drv);
--extern int driver_probe_device(struct device_driver *, struct device *);
-+extern void driver_detach(struct device_driver *drv);
-+extern int driver_probe_device(struct device_driver *drv, struct device *dev);
- 
- extern void sysdev_shutdown(void);
- extern int sysdev_suspend(pm_message_t state);
-@@ -44,4 +79,13 @@ extern char *make_class_name(const char *name, struct kobject *kobj);
- 
- extern int devres_release_all(struct device *dev);
- 
--extern struct kset devices_subsys;
-+extern struct kset *devices_kset;
++	/* DBG1( "WRITEx: %d, index = %d", count, index); */
 +
-+#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
-+extern void module_add_driver(struct module *mod, struct device_driver *drv);
-+extern void module_remove_driver(struct device_driver *drv);
-+#else
-+static inline void module_add_driver(struct module *mod,
-+				     struct device_driver *drv) { }
-+static inline void module_remove_driver(struct device_driver *drv) { }
-+#endif
-diff --git a/drivers/base/bus.c b/drivers/base/bus.c
-index 9a19b07..055989e 100644
---- a/drivers/base/bus.c
-+++ b/drivers/base/bus.c
-@@ -3,6 +3,8 @@
-  *
-  * Copyright (c) 2002-3 Patrick Mochel
-  * Copyright (c) 2002-3 Open Source Development Labs
-+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
-+ * Copyright (c) 2007 Novell Inc.
-  *
-  * This file is released under the GPLv2
-  *
-@@ -17,14 +19,13 @@
- #include "power/power.h"
- 
- #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
--#define to_bus(obj) container_of(obj, struct bus_type, subsys.kobj)
-+#define to_bus(obj) container_of(obj, struct bus_type_private, subsys.kobj)
- 
- /*
-  * sysfs bindings for drivers
-  */
- 
- #define to_drv_attr(_attr) container_of(_attr, struct driver_attribute, attr)
--#define to_driver(obj) container_of(obj, struct device_driver, kobj)
- 
- 
- static int __must_check bus_rescan_devices_helper(struct device *dev,
-@@ -32,37 +33,40 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
- 
- static struct bus_type *bus_get(struct bus_type *bus)
- {
--	return bus ? container_of(kset_get(&bus->subsys),
--				struct bus_type, subsys) : NULL;
-+	if (bus) {
-+		kset_get(&bus->p->subsys);
-+		return bus;
++	if (!dc || !port)
++		return -ENODEV;
++
++	if (unlikely(!mutex_trylock(&port->tty_sem))) {
++		/*
++		 * must test lock as tty layer wraps calls
++		 * to this function with BKL
++		 */
++		dev_err(&dc->pdev->dev, "Would have deadlocked - "
++			"return EAGAIN\n");
++		return -EAGAIN;
 +	}
-+	return NULL;
- }
- 
- static void bus_put(struct bus_type *bus)
- {
--	kset_put(&bus->subsys);
-+	if (bus)
-+		kset_put(&bus->p->subsys);
- }
- 
--static ssize_t
--drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
-+static ssize_t drv_attr_show(struct kobject *kobj, struct attribute *attr,
-+			     char *buf)
- {
--	struct driver_attribute * drv_attr = to_drv_attr(attr);
--	struct device_driver * drv = to_driver(kobj);
-+	struct driver_attribute *drv_attr = to_drv_attr(attr);
-+	struct driver_private *drv_priv = to_driver(kobj);
- 	ssize_t ret = -EIO;
- 
- 	if (drv_attr->show)
--		ret = drv_attr->show(drv, buf);
-+		ret = drv_attr->show(drv_priv->driver, buf);
- 	return ret;
- }
- 
--static ssize_t
--drv_attr_store(struct kobject * kobj, struct attribute * attr,
--	       const char * buf, size_t count)
-+static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr,
-+			      const char *buf, size_t count)
- {
--	struct driver_attribute * drv_attr = to_drv_attr(attr);
--	struct device_driver * drv = to_driver(kobj);
-+	struct driver_attribute *drv_attr = to_drv_attr(attr);
-+	struct driver_private *drv_priv = to_driver(kobj);
- 	ssize_t ret = -EIO;
- 
- 	if (drv_attr->store)
--		ret = drv_attr->store(drv, buf, count);
-+		ret = drv_attr->store(drv_priv->driver, buf, count);
- 	return ret;
- }
- 
-@@ -71,22 +75,12 @@ static struct sysfs_ops driver_sysfs_ops = {
- 	.store	= drv_attr_store,
- };
- 
--
--static void driver_release(struct kobject * kobj)
-+static void driver_release(struct kobject *kobj)
- {
--	/*
--	 * Yes this is an empty release function, it is this way because struct
--	 * device is always a static object, not a dynamic one.  Yes, this is
--	 * not nice and bad, but remember, drivers are code, reference counted
--	 * by the module count, not a device, which is really data.  And yes,
--	 * in the future I do want to have all drivers be created dynamically,
--	 * and am working toward that goal, but it will take a bit longer...
--	 *
--	 * But do not let this example give _anyone_ the idea that they can
--	 * create a release function without any code in it at all, to do that
--	 * is almost always wrong.  If you have any questions about this,
--	 * please send an email to <greg at kroah.com>
--	 */
-+	struct driver_private *drv_priv = to_driver(kobj);
 +
-+	pr_debug("driver: '%s': %s\n", kobject_name(kobj), __FUNCTION__);
-+	kfree(drv_priv);
- }
- 
- static struct kobj_type driver_ktype = {
-@@ -94,34 +88,30 @@ static struct kobj_type driver_ktype = {
- 	.release	= driver_release,
- };
- 
--
- /*
-  * sysfs bindings for buses
-  */
--
--
--static ssize_t
--bus_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
-+static ssize_t bus_attr_show(struct kobject *kobj, struct attribute *attr,
-+			     char *buf)
- {
--	struct bus_attribute * bus_attr = to_bus_attr(attr);
--	struct bus_type * bus = to_bus(kobj);
-+	struct bus_attribute *bus_attr = to_bus_attr(attr);
-+	struct bus_type_private *bus_priv = to_bus(kobj);
- 	ssize_t ret = 0;
- 
- 	if (bus_attr->show)
--		ret = bus_attr->show(bus, buf);
-+		ret = bus_attr->show(bus_priv->bus, buf);
- 	return ret;
- }
- 
--static ssize_t
--bus_attr_store(struct kobject * kobj, struct attribute * attr,
--	       const char * buf, size_t count)
-+static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
-+			      const char *buf, size_t count)
- {
--	struct bus_attribute * bus_attr = to_bus_attr(attr);
--	struct bus_type * bus = to_bus(kobj);
-+	struct bus_attribute *bus_attr = to_bus_attr(attr);
-+	struct bus_type_private *bus_priv = to_bus(kobj);
- 	ssize_t ret = 0;
- 
- 	if (bus_attr->store)
--		ret = bus_attr->store(bus, buf, count);
-+		ret = bus_attr->store(bus_priv->bus, buf, count);
- 	return ret;
- }
- 
-@@ -130,24 +120,26 @@ static struct sysfs_ops bus_sysfs_ops = {
- 	.store	= bus_attr_store,
- };
- 
--int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
-+int bus_create_file(struct bus_type *bus, struct bus_attribute *attr)
- {
- 	int error;
- 	if (bus_get(bus)) {
--		error = sysfs_create_file(&bus->subsys.kobj, &attr->attr);
-+		error = sysfs_create_file(&bus->p->subsys.kobj, &attr->attr);
- 		bus_put(bus);
- 	} else
- 		error = -EINVAL;
- 	return error;
- }
-+EXPORT_SYMBOL_GPL(bus_create_file);
- 
--void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
-+void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr)
- {
- 	if (bus_get(bus)) {
--		sysfs_remove_file(&bus->subsys.kobj, &attr->attr);
-+		sysfs_remove_file(&bus->p->subsys.kobj, &attr->attr);
- 		bus_put(bus);
- 	}
- }
-+EXPORT_SYMBOL_GPL(bus_remove_file);
- 
- static struct kobj_type bus_ktype = {
- 	.sysfs_ops	= &bus_sysfs_ops,
-@@ -166,20 +158,11 @@ static struct kset_uevent_ops bus_uevent_ops = {
- 	.filter = bus_uevent_filter,
- };
- 
--static decl_subsys(bus, &bus_ktype, &bus_uevent_ops);
-+static struct kset *bus_kset;
- 
- 
- #ifdef CONFIG_HOTPLUG
- /* Manually detach a device from its associated driver. */
--static int driver_helper(struct device *dev, void *data)
--{
--	const char *name = data;
--
--	if (strcmp(name, dev->bus_id) == 0)
--		return 1;
--	return 0;
--}
--
- static ssize_t driver_unbind(struct device_driver *drv,
- 			     const char *buf, size_t count)
- {
-@@ -187,7 +170,7 @@ static ssize_t driver_unbind(struct device_driver *drv,
- 	struct device *dev;
- 	int err = -ENODEV;
- 
--	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
-+	dev = bus_find_device_by_name(bus, NULL, buf);
- 	if (dev && dev->driver == drv) {
- 		if (dev->parent)	/* Needed for USB */
- 			down(&dev->parent->sem);
-@@ -214,7 +197,7 @@ static ssize_t driver_bind(struct device_driver *drv,
- 	struct device *dev;
- 	int err = -ENODEV;
- 
--	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
-+	dev = bus_find_device_by_name(bus, NULL, buf);
- 	if (dev && dev->driver == NULL) {
- 		if (dev->parent)	/* Needed for USB */
- 			down(&dev->parent->sem);
-@@ -224,10 +207,13 @@ static ssize_t driver_bind(struct device_driver *drv,
- 		if (dev->parent)
- 			up(&dev->parent->sem);
- 
--		if (err > 0) 		/* success */
-+		if (err > 0) {
-+			/* success */
- 			err = count;
--		else if (err == 0)	/* driver didn't accept device */
-+		} else if (err == 0) {
-+			/* driver didn't accept device */
- 			err = -ENODEV;
++	if (unlikely(!port->tty_open_count)) {
++		DBG1(" ");
++		goto exit;
++	}
++
++	rval = __kfifo_put(port->fifo_ul, (unsigned char *)buffer, count);
++
++	/* notify card */
++	if (unlikely(dc == NULL)) {
++		DBG1("No device context?");
++		goto exit;
++	}
++
++	spin_lock_irqsave(&dc->spin_mutex, flags);
++	/* CTS is only valid on the modem channel */
++	if (port == &(dc->port[PORT_MDM])) {
++		if (port->ctrl_dl.CTS) {
++			DBG4("Enable interrupt");
++			enable_transmit_ul(tty->index % MAX_PORT, dc);
++		} else {
++			dev_err(&dc->pdev->dev,
++				"CTS not active on modem port?\n");
 +		}
- 	}
- 	put_device(dev);
- 	bus_put(bus);
-@@ -237,16 +223,16 @@ static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
- 
- static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
- {
--	return sprintf(buf, "%d\n", bus->drivers_autoprobe);
-+	return sprintf(buf, "%d\n", bus->p->drivers_autoprobe);
- }
- 
- static ssize_t store_drivers_autoprobe(struct bus_type *bus,
- 				       const char *buf, size_t count)
- {
- 	if (buf[0] == '0')
--		bus->drivers_autoprobe = 0;
-+		bus->p->drivers_autoprobe = 0;
- 	else
--		bus->drivers_autoprobe = 1;
-+		bus->p->drivers_autoprobe = 1;
- 	return count;
- }
- 
-@@ -255,7 +241,7 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
- {
- 	struct device *dev;
- 
--	dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
-+	dev = bus_find_device_by_name(bus, NULL, buf);
- 	if (!dev)
- 		return -ENODEV;
- 	if (bus_rescan_devices_helper(dev, NULL) != 0)
-@@ -264,49 +250,49 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
- }
- #endif
- 
--static struct device * next_device(struct klist_iter * i)
-+static struct device *next_device(struct klist_iter *i)
- {
--	struct klist_node * n = klist_next(i);
-+	struct klist_node *n = klist_next(i);
- 	return n ? container_of(n, struct device, knode_bus) : NULL;
- }
- 
- /**
-- *	bus_for_each_dev - device iterator.
-- *	@bus:	bus type.
-- *	@start:	device to start iterating from.
-- *	@data:	data for the callback.
-- *	@fn:	function to be called for each device.
-+ * bus_for_each_dev - device iterator.
-+ * @bus: bus type.
-+ * @start: device to start iterating from.
-+ * @data: data for the callback.
-+ * @fn: function to be called for each device.
-  *
-- *	Iterate over @bus's list of devices, and call @fn for each,
-- *	passing it @data. If @start is not NULL, we use that device to
-- *	begin iterating from.
-+ * Iterate over @bus's list of devices, and call @fn for each,
-+ * passing it @data. If @start is not NULL, we use that device to
-+ * begin iterating from.
-  *
-- *	We check the return of @fn each time. If it returns anything
-- *	other than 0, we break out and return that value.
-+ * We check the return of @fn each time. If it returns anything
-+ * other than 0, we break out and return that value.
-  *
-- *	NOTE: The device that returns a non-zero value is not retained
-- *	in any way, nor is its refcount incremented. If the caller needs
-- *	to retain this data, it should do, and increment the reference
-- *	count in the supplied callback.
-+ * NOTE: The device that returns a non-zero value is not retained
-+ * in any way, nor is its refcount incremented. If the caller needs
-+ * to retain this data, it should do, and increment the reference
-+ * count in the supplied callback.
-  */
--
--int bus_for_each_dev(struct bus_type * bus, struct device * start,
--		     void * data, int (*fn)(struct device *, void *))
-+int bus_for_each_dev(struct bus_type *bus, struct device *start,
-+		     void *data, int (*fn)(struct device *, void *))
- {
- 	struct klist_iter i;
--	struct device * dev;
-+	struct device *dev;
- 	int error = 0;
- 
- 	if (!bus)
- 		return -EINVAL;
- 
--	klist_iter_init_node(&bus->klist_devices, &i,
-+	klist_iter_init_node(&bus->p->klist_devices, &i,
- 			     (start ? &start->knode_bus : NULL));
- 	while ((dev = next_device(&i)) && !error)
- 		error = fn(dev, data);
- 	klist_iter_exit(&i);
- 	return error;
- }
-+EXPORT_SYMBOL_GPL(bus_for_each_dev);
- 
- /**
-  * bus_find_device - device iterator for locating a particular device.
-@@ -323,9 +309,9 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
-  * if it does.  If the callback returns non-zero, this function will
-  * return to the caller and not iterate over any more devices.
-  */
--struct device * bus_find_device(struct bus_type *bus,
--				struct device *start, void *data,
--				int (*match)(struct device *, void *))
-+struct device *bus_find_device(struct bus_type *bus,
-+			       struct device *start, void *data,
-+			       int (*match)(struct device *dev, void *data))
- {
- 	struct klist_iter i;
- 	struct device *dev;
-@@ -333,7 +319,7 @@ struct device * bus_find_device(struct bus_type *bus,
- 	if (!bus)
- 		return NULL;
- 
--	klist_iter_init_node(&bus->klist_devices, &i,
-+	klist_iter_init_node(&bus->p->klist_devices, &i,
- 			     (start ? &start->knode_bus : NULL));
- 	while ((dev = next_device(&i)))
- 		if (match(dev, data) && get_device(dev))
-@@ -341,51 +327,83 @@ struct device * bus_find_device(struct bus_type *bus,
- 	klist_iter_exit(&i);
- 	return dev;
- }
-+EXPORT_SYMBOL_GPL(bus_find_device);
++	} else {
++		enable_transmit_ul(tty->index % MAX_PORT, dc);
++	}
++	spin_unlock_irqrestore(&dc->spin_mutex, flags);
 +
-+static int match_name(struct device *dev, void *data)
++exit:
++	mutex_unlock(&port->tty_sem);
++	return rval;
++}
++
++/*
++ * Calculate how much is left in device
++ * This method is called by the upper tty layer.
++ *   #according to sources N_TTY.c it expects a value >= 0 and
++ *    does not check for negative values.
++ */
++static int ntty_write_room(struct tty_struct *tty)
 +{
-+	const char *name = data;
- 
-+	if (strcmp(name, dev->bus_id) == 0)
-+		return 1;
++	struct port *port = tty->driver_data;
++	int room = 0;
++	const struct nozomi *dc = get_dc_by_tty(tty);
++
++	if (!dc || !port)
++		return 0;
++	if (!mutex_trylock(&port->tty_sem))
++		return 0;
++
++	if (!port->tty_open_count)
++		goto exit;
++
++	room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
++
++exit:
++	mutex_unlock(&port->tty_sem);
++	return room;
++}
++
++/* Gets io control parameters */
++static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
++{
++	const struct port *port = tty->driver_data;
++	const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
++	const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
++
++	return	(ctrl_ul->RTS ? TIOCM_RTS : 0) |
++		(ctrl_ul->DTR ? TIOCM_DTR : 0) |
++		(ctrl_dl->DCD ? TIOCM_CAR : 0) |
++		(ctrl_dl->RI  ? TIOCM_RNG : 0) |
++		(ctrl_dl->DSR ? TIOCM_DSR : 0) |
++		(ctrl_dl->CTS ? TIOCM_CTS : 0);
++}
++
++/* Sets io controls parameters */
++static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
++	unsigned int set, unsigned int clear)
++{
++	if (set & TIOCM_RTS)
++		set_rts(tty, 1);
++	else if (clear & TIOCM_RTS)
++		set_rts(tty, 0);
++
++	if (set & TIOCM_DTR)
++		set_dtr(tty, 1);
++	else if (clear & TIOCM_DTR)
++		set_dtr(tty, 0);
++
 +	return 0;
 +}
- 
--static struct device_driver * next_driver(struct klist_iter * i)
-+/**
-+ * bus_find_device_by_name - device iterator for locating a particular device of a specific name
-+ * @bus: bus type
-+ * @start: Device to begin with
-+ * @name: name of the device to match
-+ *
-+ * This is similar to the bus_find_device() function above, but it handles
-+ * searching by a name automatically, no need to write another strcmp matching
-+ * function.
++
++static int ntty_cflags_changed(struct port *port, unsigned long flags,
++		struct async_icount *cprev)
++{
++	const struct async_icount cnow = port->tty_icount;
++	int ret;
++
++	ret =	((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
++		((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
++		((flags & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
++		((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
++
++	*cprev = cnow;
++
++	return ret;
++}
++
++static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
++{
++	const struct async_icount cnow = port->tty_icount;
++	struct serial_icounter_struct icount;
++
++	icount.cts = cnow.cts;
++	icount.dsr = cnow.dsr;
++	icount.rng = cnow.rng;
++	icount.dcd = cnow.dcd;
++	icount.rx = cnow.rx;
++	icount.tx = cnow.tx;
++	icount.frame = cnow.frame;
++	icount.overrun = cnow.overrun;
++	icount.parity = cnow.parity;
++	icount.brk = cnow.brk;
++	icount.buf_overrun = cnow.buf_overrun;
++
++	return copy_to_user(argp, &icount, sizeof(icount));
++}
++
++static int ntty_ioctl(struct tty_struct *tty, struct file *file,
++		      unsigned int cmd, unsigned long arg)
++{
++	struct port *port = tty->driver_data;
++	void __user *argp = (void __user *)arg;
++	int rval = -ENOIOCTLCMD;
++
++	DBG1("******** IOCTL, cmd: %d", cmd);
++
++	switch (cmd) {
++	case TIOCMIWAIT: {
++		struct async_icount cprev = port->tty_icount;
++
++		rval = wait_event_interruptible(port->tty_wait,
++				ntty_cflags_changed(port, arg, &cprev));
++		break;
++	} case TIOCGICOUNT:
++		rval = ntty_ioctl_tiocgicount(port, argp);
++		break;
++	default:
++		DBG1("ERR: 0x%08X, %d", cmd, cmd);
++		break;
++	};
++
++	return rval;
++}
++
++/*
++ * Called by the upper tty layer when tty buffers are ready
++ * to receive data again after a call to throttle.
 + */
-+struct device *bus_find_device_by_name(struct bus_type *bus,
-+				       struct device *start, const char *name)
- {
--	struct klist_node * n = klist_next(i);
--	return n ? container_of(n, struct device_driver, knode_bus) : NULL;
-+	return bus_find_device(bus, start, (void *)name, match_name);
++static void ntty_unthrottle(struct tty_struct *tty)
++{
++	struct nozomi *dc = get_dc_by_tty(tty);
++	unsigned long flags;
++
++	DBG1("UNTHROTTLE");
++	spin_lock_irqsave(&dc->spin_mutex, flags);
++	enable_transmit_dl(tty->index % MAX_PORT, dc);
++	set_rts(tty, 1);
++
++	spin_unlock_irqrestore(&dc->spin_mutex, flags);
 +}
-+EXPORT_SYMBOL_GPL(bus_find_device_by_name);
 +
-+static struct device_driver *next_driver(struct klist_iter *i)
++/*
++ * Called by the upper tty layer when the tty buffers are almost full.
++ * The driver should stop send more data.
++ */
++static void ntty_throttle(struct tty_struct *tty)
 +{
-+	struct klist_node *n = klist_next(i);
-+	struct driver_private *drv_priv;
++	struct nozomi *dc = get_dc_by_tty(tty);
++	unsigned long flags;
 +
-+	if (n) {
-+		drv_priv = container_of(n, struct driver_private, knode_bus);
-+		return drv_priv->driver;
++	DBG1("THROTTLE");
++	spin_lock_irqsave(&dc->spin_mutex, flags);
++	set_rts(tty, 0);
++	spin_unlock_irqrestore(&dc->spin_mutex, flags);
++}
++
++/* just to discard single character writes */
++static void ntty_put_char(struct tty_struct *tty, unsigned char c)
++{
++	/*
++	 * card does not react correct when we write single chars
++	 * to the card, so we discard them
++	 */
++	DBG2("PUT CHAR Function: %c", c);
++}
++
++/* Returns number of chars in buffer, called by tty layer */
++static s32 ntty_chars_in_buffer(struct tty_struct *tty)
++{
++	struct port *port = tty->driver_data;
++	struct nozomi *dc = get_dc_by_tty(tty);
++	s32 rval;
++
++	if (unlikely(!dc || !port)) {
++		rval = -ENODEV;
++		goto exit_in_buffer;
 +	}
-+	return NULL;
- }
- 
- /**
-- *	bus_for_each_drv - driver iterator
-- *	@bus:	bus we're dealing with.
-- *	@start:	driver to start iterating on.
-- *	@data:	data to pass to the callback.
-- *	@fn:	function to call for each driver.
-+ * bus_for_each_drv - driver iterator
-+ * @bus: bus we're dealing with.
-+ * @start: driver to start iterating on.
-+ * @data: data to pass to the callback.
-+ * @fn: function to call for each driver.
-  *
-- *	This is nearly identical to the device iterator above.
-- *	We iterate over each driver that belongs to @bus, and call
-- *	@fn for each. If @fn returns anything but 0, we break out
-- *	and return it. If @start is not NULL, we use it as the head
-- *	of the list.
-+ * This is nearly identical to the device iterator above.
-+ * We iterate over each driver that belongs to @bus, and call
-+ * @fn for each. If @fn returns anything but 0, we break out
-+ * and return it. If @start is not NULL, we use it as the head
-+ * of the list.
-  *
-- *	NOTE: we don't return the driver that returns a non-zero
-- *	value, nor do we leave the reference count incremented for that
-- *	driver. If the caller needs to know that info, it must set it
-- *	in the callback. It must also be sure to increment the refcount
-- *	so it doesn't disappear before returning to the caller.
-+ * NOTE: we don't return the driver that returns a non-zero
-+ * value, nor do we leave the reference count incremented for that
-+ * driver. If the caller needs to know that info, it must set it
-+ * in the callback. It must also be sure to increment the refcount
-+ * so it doesn't disappear before returning to the caller.
-  */
--
--int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
--		     void * data, int (*fn)(struct device_driver *, void *))
-+int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
-+		     void *data, int (*fn)(struct device_driver *, void *))
- {
- 	struct klist_iter i;
--	struct device_driver * drv;
-+	struct device_driver *drv;
- 	int error = 0;
- 
- 	if (!bus)
- 		return -EINVAL;
- 
--	klist_iter_init_node(&bus->klist_drivers, &i,
--			     start ? &start->knode_bus : NULL);
-+	klist_iter_init_node(&bus->p->klist_drivers, &i,
-+			     start ? &start->p->knode_bus : NULL);
- 	while ((drv = next_driver(&i)) && !error)
- 		error = fn(drv, data);
- 	klist_iter_exit(&i);
- 	return error;
- }
-+EXPORT_SYMBOL_GPL(bus_for_each_drv);
- 
- static int device_add_attrs(struct bus_type *bus, struct device *dev)
- {
-@@ -396,7 +414,7 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
- 		return 0;
- 
- 	for (i = 0; attr_name(bus->dev_attrs[i]); i++) {
--		error = device_create_file(dev,&bus->dev_attrs[i]);
-+		error = device_create_file(dev, &bus->dev_attrs[i]);
- 		if (error) {
- 			while (--i >= 0)
- 				device_remove_file(dev, &bus->dev_attrs[i]);
-@@ -406,13 +424,13 @@ static int device_add_attrs(struct bus_type *bus, struct device *dev)
- 	return error;
- }
- 
--static void device_remove_attrs(struct bus_type * bus, struct device * dev)
-+static void device_remove_attrs(struct bus_type *bus, struct device *dev)
- {
- 	int i;
- 
- 	if (bus->dev_attrs) {
- 		for (i = 0; attr_name(bus->dev_attrs[i]); i++)
--			device_remove_file(dev,&bus->dev_attrs[i]);
-+			device_remove_file(dev, &bus->dev_attrs[i]);
- 	}
- }
- 
-@@ -420,7 +438,7 @@ static void device_remove_attrs(struct bus_type * bus, struct device * dev)
- static int make_deprecated_bus_links(struct device *dev)
- {
- 	return sysfs_create_link(&dev->kobj,
--				 &dev->bus->subsys.kobj, "bus");
-+				 &dev->bus->p->subsys.kobj, "bus");
- }
- 
- static void remove_deprecated_bus_links(struct device *dev)
-@@ -433,28 +451,28 @@ static inline void remove_deprecated_bus_links(struct device *dev) { }
- #endif
- 
- /**
-- *	bus_add_device - add device to bus
-- *	@dev:	device being added
-+ * bus_add_device - add device to bus
-+ * @dev: device being added
-  *
-- *	- Add the device to its bus's list of devices.
-- *	- Create link to device's bus.
-+ * - Add the device to its bus's list of devices.
-+ * - Create link to device's bus.
-  */
--int bus_add_device(struct device * dev)
-+int bus_add_device(struct device *dev)
- {
--	struct bus_type * bus = bus_get(dev->bus);
-+	struct bus_type *bus = bus_get(dev->bus);
- 	int error = 0;
- 
- 	if (bus) {
--		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
-+		pr_debug("bus: '%s': add device %s\n", bus->name, dev->bus_id);
- 		error = device_add_attrs(bus, dev);
- 		if (error)
- 			goto out_put;
--		error = sysfs_create_link(&bus->devices.kobj,
-+		error = sysfs_create_link(&bus->p->devices_kset->kobj,
- 						&dev->kobj, dev->bus_id);
- 		if (error)
- 			goto out_id;
- 		error = sysfs_create_link(&dev->kobj,
--				&dev->bus->subsys.kobj, "subsystem");
-+				&dev->bus->p->subsys.kobj, "subsystem");
- 		if (error)
- 			goto out_subsys;
- 		error = make_deprecated_bus_links(dev);
-@@ -466,7 +484,7 @@ int bus_add_device(struct device * dev)
- out_deprecated:
- 	sysfs_remove_link(&dev->kobj, "subsystem");
- out_subsys:
--	sysfs_remove_link(&bus->devices.kobj, dev->bus_id);
-+	sysfs_remove_link(&bus->p->devices_kset->kobj, dev->bus_id);
- out_id:
- 	device_remove_attrs(bus, dev);
- out_put:
-@@ -475,56 +493,58 @@ out_put:
- }
- 
- /**
-- *	bus_attach_device - add device to bus
-- *	@dev:	device tried to attach to a driver
-+ * bus_attach_device - add device to bus
-+ * @dev: device tried to attach to a driver
-  *
-- *	- Add device to bus's list of devices.
-- *	- Try to attach to driver.
-+ * - Add device to bus's list of devices.
-+ * - Try to attach to driver.
-  */
--void bus_attach_device(struct device * dev)
-+void bus_attach_device(struct device *dev)
- {
- 	struct bus_type *bus = dev->bus;
- 	int ret = 0;
- 
- 	if (bus) {
- 		dev->is_registered = 1;
--		if (bus->drivers_autoprobe)
-+		if (bus->p->drivers_autoprobe)
- 			ret = device_attach(dev);
- 		WARN_ON(ret < 0);
- 		if (ret >= 0)
--			klist_add_tail(&dev->knode_bus, &bus->klist_devices);
-+			klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
- 		else
- 			dev->is_registered = 0;
- 	}
- }
- 
- /**
-- *	bus_remove_device - remove device from bus
-- *	@dev:	device to be removed
-+ * bus_remove_device - remove device from bus
-+ * @dev: device to be removed
-  *
-- *	- Remove symlink from bus's directory.
-- *	- Delete device from bus's list.
-- *	- Detach from its driver.
-- *	- Drop reference taken in bus_add_device().
-+ * - Remove symlink from bus's directory.
-+ * - Delete device from bus's list.
-+ * - Detach from its driver.
-+ * - Drop reference taken in bus_add_device().
-  */
--void bus_remove_device(struct device * dev)
-+void bus_remove_device(struct device *dev)
- {
- 	if (dev->bus) {
- 		sysfs_remove_link(&dev->kobj, "subsystem");
- 		remove_deprecated_bus_links(dev);
--		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
-+		sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
-+				  dev->bus_id);
- 		device_remove_attrs(dev->bus, dev);
- 		if (dev->is_registered) {
- 			dev->is_registered = 0;
- 			klist_del(&dev->knode_bus);
- 		}
--		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
-+		pr_debug("bus: '%s': remove device %s\n",
-+			 dev->bus->name, dev->bus_id);
- 		device_release_driver(dev);
- 		bus_put(dev->bus);
- 	}
- }
- 
--static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
-+static int driver_add_attrs(struct bus_type *bus, struct device_driver *drv)
- {
- 	int error = 0;
- 	int i;
-@@ -533,19 +553,19 @@ static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
- 		for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
- 			error = driver_create_file(drv, &bus->drv_attrs[i]);
- 			if (error)
--				goto Err;
-+				goto err;
- 		}
- 	}
-- Done:
-+done:
- 	return error;
-- Err:
-+err:
- 	while (--i >= 0)
- 		driver_remove_file(drv, &bus->drv_attrs[i]);
--	goto Done;
-+	goto done;
- }
- 
--
--static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv)
-+static void driver_remove_attrs(struct bus_type *bus,
-+				struct device_driver *drv)
- {
- 	int i;
- 
-@@ -616,39 +636,46 @@ static ssize_t driver_uevent_store(struct device_driver *drv,
- 	enum kobject_action action;
- 
- 	if (kobject_action_type(buf, count, &action) == 0)
--		kobject_uevent(&drv->kobj, action);
-+		kobject_uevent(&drv->p->kobj, action);
- 	return count;
- }
- static DRIVER_ATTR(uevent, S_IWUSR, NULL, driver_uevent_store);
- 
- /**
-- *	bus_add_driver - Add a driver to the bus.
-- *	@drv:	driver.
-- *
-+ * bus_add_driver - Add a driver to the bus.
-+ * @drv: driver.
-  */
- int bus_add_driver(struct device_driver *drv)
- {
--	struct bus_type * bus = bus_get(drv->bus);
-+	struct bus_type *bus;
-+	struct driver_private *priv;
- 	int error = 0;
- 
-+	bus = bus_get(drv->bus);
- 	if (!bus)
- 		return -EINVAL;
- 
--	pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
--	error = kobject_set_name(&drv->kobj, "%s", drv->name);
--	if (error)
--		goto out_put_bus;
--	drv->kobj.kset = &bus->drivers;
--	error = kobject_register(&drv->kobj);
-+	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);
 +
-+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-+	if (!priv)
-+		return -ENOMEM;
++	if (unlikely(!port->tty_open_count)) {
++		dev_err(&dc->pdev->dev, "No tty open?\n");
++		rval = -ENODEV;
++		goto exit_in_buffer;
++	}
 +
-+	klist_init(&priv->klist_devices, NULL, NULL);
-+	priv->driver = drv;
-+	drv->p = priv;
-+	priv->kobj.kset = bus->p->drivers_kset;
-+	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
-+				     "%s", drv->name);
- 	if (error)
- 		goto out_put_bus;
- 
--	if (drv->bus->drivers_autoprobe) {
-+	if (drv->bus->p->drivers_autoprobe) {
- 		error = driver_attach(drv);
- 		if (error)
- 			goto out_unregister;
- 	}
--	klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
-+	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
- 	module_add_driver(drv->owner, drv);
- 
- 	error = driver_create_file(drv, &driver_attr_uevent);
-@@ -669,24 +696,24 @@ int bus_add_driver(struct device_driver *drv)
- 			__FUNCTION__, drv->name);
- 	}
- 
-+	kobject_uevent(&priv->kobj, KOBJ_ADD);
- 	return error;
- out_unregister:
--	kobject_unregister(&drv->kobj);
-+	kobject_put(&priv->kobj);
- out_put_bus:
- 	bus_put(bus);
- 	return error;
- }
- 
- /**
-- *	bus_remove_driver - delete driver from bus's knowledge.
-- *	@drv:	driver.
-+ * bus_remove_driver - delete driver from bus's knowledge.
-+ * @drv: driver.
-  *
-- *	Detach the driver from the devices it controls, and remove
-- *	it from its bus's list of drivers. Finally, we drop the reference
-- *	to the bus we took in bus_add_driver().
-+ * Detach the driver from the devices it controls, and remove
-+ * it from its bus's list of drivers. Finally, we drop the reference
-+ * to the bus we took in bus_add_driver().
-  */
--
--void bus_remove_driver(struct device_driver * drv)
-+void bus_remove_driver(struct device_driver *drv)
- {
- 	if (!drv->bus)
- 		return;
-@@ -694,18 +721,17 @@ void bus_remove_driver(struct device_driver * drv)
- 	remove_bind_files(drv);
- 	driver_remove_attrs(drv->bus, drv);
- 	driver_remove_file(drv, &driver_attr_uevent);
--	klist_remove(&drv->knode_bus);
--	pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
-+	klist_remove(&drv->p->knode_bus);
-+	pr_debug("bus: '%s': remove driver %s\n", drv->bus->name, drv->name);
- 	driver_detach(drv);
- 	module_remove_driver(drv);
--	kobject_unregister(&drv->kobj);
-+	kobject_put(&drv->p->kobj);
- 	bus_put(drv->bus);
- }
- 
--
- /* Helper for bus_rescan_devices's iter */
- static int __must_check bus_rescan_devices_helper(struct device *dev,
--						void *data)
-+						  void *data)
- {
- 	int ret = 0;
- 
-@@ -727,10 +753,11 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
-  * attached and rescan it against existing drivers to see if it matches
-  * any by calling device_attach() for the unbound devices.
-  */
--int bus_rescan_devices(struct bus_type * bus)
-+int bus_rescan_devices(struct bus_type *bus)
- {
- 	return bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
- }
-+EXPORT_SYMBOL_GPL(bus_rescan_devices);
- 
- /**
-  * device_reprobe - remove driver for a device and probe for a new driver
-@@ -755,55 +782,55 @@ int device_reprobe(struct device *dev)
- EXPORT_SYMBOL_GPL(device_reprobe);
- 
- /**
-- *	find_bus - locate bus by name.
-- *	@name:	name of bus.
-+ * find_bus - locate bus by name.
-+ * @name: name of bus.
-  *
-- *	Call kset_find_obj() to iterate over list of buses to
-- *	find a bus by name. Return bus if found.
-+ * Call kset_find_obj() to iterate over list of buses to
-+ * find a bus by name. Return bus if found.
-  *
-- *	Note that kset_find_obj increments bus' reference count.
-+ * Note that kset_find_obj increments bus' reference count.
-  */
- #if 0
--struct bus_type * find_bus(char * name)
-+struct bus_type *find_bus(char *name)
- {
--	struct kobject * k = kset_find_obj(&bus_subsys.kset, name);
-+	struct kobject *k = kset_find_obj(bus_kset, name);
- 	return k ? to_bus(k) : NULL;
- }
- #endif  /*  0  */
- 
- 
- /**
-- *	bus_add_attrs - Add default attributes for this bus.
-- *	@bus:	Bus that has just been registered.
-+ * bus_add_attrs - Add default attributes for this bus.
-+ * @bus: Bus that has just been registered.
-  */
- 
--static int bus_add_attrs(struct bus_type * bus)
-+static int bus_add_attrs(struct bus_type *bus)
- {
- 	int error = 0;
- 	int i;
- 
- 	if (bus->bus_attrs) {
- 		for (i = 0; attr_name(bus->bus_attrs[i]); i++) {
--			error = bus_create_file(bus,&bus->bus_attrs[i]);
-+			error = bus_create_file(bus, &bus->bus_attrs[i]);
- 			if (error)
--				goto Err;
-+				goto err;
- 		}
- 	}
-- Done:
-+done:
- 	return error;
-- Err:
-+err:
- 	while (--i >= 0)
--		bus_remove_file(bus,&bus->bus_attrs[i]);
--	goto Done;
-+		bus_remove_file(bus, &bus->bus_attrs[i]);
-+	goto done;
- }
- 
--static void bus_remove_attrs(struct bus_type * bus)
-+static void bus_remove_attrs(struct bus_type *bus)
- {
- 	int i;
- 
- 	if (bus->bus_attrs) {
- 		for (i = 0; attr_name(bus->bus_attrs[i]); i++)
--			bus_remove_file(bus,&bus->bus_attrs[i]);
-+			bus_remove_file(bus, &bus->bus_attrs[i]);
- 	}
- }
- 
-@@ -827,32 +854,42 @@ static ssize_t bus_uevent_store(struct bus_type *bus,
- 	enum kobject_action action;
- 
- 	if (kobject_action_type(buf, count, &action) == 0)
--		kobject_uevent(&bus->subsys.kobj, action);
-+		kobject_uevent(&bus->p->subsys.kobj, action);
- 	return count;
- }
- static BUS_ATTR(uevent, S_IWUSR, NULL, bus_uevent_store);
- 
- /**
-- *	bus_register - register a bus with the system.
-- *	@bus:	bus.
-+ * bus_register - register a bus with the system.
-+ * @bus: bus.
-  *
-- *	Once we have that, we registered the bus with the kobject
-- *	infrastructure, then register the children subsystems it has:
-- *	the devices and drivers that belong to the bus.
-+ * Once we have that, we registered the bus with the kobject
-+ * infrastructure, then register the children subsystems it has:
-+ * the devices and drivers that belong to the bus.
-  */
--int bus_register(struct bus_type * bus)
-+int bus_register(struct bus_type *bus)
- {
- 	int retval;
-+	struct bus_type_private *priv;
++	rval = __kfifo_len(port->fifo_ul);
 +
-+	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
-+	if (!priv)
++exit_in_buffer:
++	return rval;
++}
++
++static const struct tty_operations tty_ops = {
++	.ioctl = ntty_ioctl,
++	.open = ntty_open,
++	.close = ntty_close,
++	.write = ntty_write,
++	.write_room = ntty_write_room,
++	.unthrottle = ntty_unthrottle,
++	.throttle = ntty_throttle,
++	.chars_in_buffer = ntty_chars_in_buffer,
++	.put_char = ntty_put_char,
++	.tiocmget = ntty_tiocmget,
++	.tiocmset = ntty_tiocmset,
++};
++
++/* Module initialization */
++static struct pci_driver nozomi_driver = {
++	.name = NOZOMI_NAME,
++	.id_table = nozomi_pci_tbl,
++	.probe = nozomi_card_init,
++	.remove = __devexit_p(nozomi_card_exit),
++};
++
++static __init int nozomi_init(void)
++{
++	int ret;
++
++	printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
++
++	ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
++	if (!ntty_driver)
 +		return -ENOMEM;
- 
--	BLOCKING_INIT_NOTIFIER_HEAD(&bus->bus_notifier);
-+	priv->bus = bus;
-+	bus->p = priv;
- 
--	retval = kobject_set_name(&bus->subsys.kobj, "%s", bus->name);
-+	BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
 +
-+	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
- 	if (retval)
- 		goto out;
- 
--	bus->subsys.kobj.kset = &bus_subsys;
-+	priv->subsys.kobj.kset = bus_kset;
-+	priv->subsys.kobj.ktype = &bus_ktype;
-+	priv->drivers_autoprobe = 1;
- 
--	retval = subsystem_register(&bus->subsys);
-+	retval = kset_register(&priv->subsys);
- 	if (retval)
- 		goto out;
- 
-@@ -860,23 +897,23 @@ int bus_register(struct bus_type * bus)
- 	if (retval)
- 		goto bus_uevent_fail;
- 
--	kobject_set_name(&bus->devices.kobj, "devices");
--	bus->devices.kobj.parent = &bus->subsys.kobj;
--	retval = kset_register(&bus->devices);
--	if (retval)
-+	priv->devices_kset = kset_create_and_add("devices", NULL,
-+						 &priv->subsys.kobj);
-+	if (!priv->devices_kset) {
-+		retval = -ENOMEM;
- 		goto bus_devices_fail;
++	ntty_driver->owner = THIS_MODULE;
++	ntty_driver->driver_name = NOZOMI_NAME_TTY;
++	ntty_driver->name = "noz";
++	ntty_driver->major = 0;
++	ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
++	ntty_driver->subtype = SERIAL_TYPE_NORMAL;
++	ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
++	ntty_driver->init_termios = tty_std_termios;
++	ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
++						HUPCL | CLOCAL;
++	ntty_driver->init_termios.c_ispeed = 115200;
++	ntty_driver->init_termios.c_ospeed = 115200;
++	tty_set_operations(ntty_driver, &tty_ops);
++
++	ret = tty_register_driver(ntty_driver);
++	if (ret) {
++		printk(KERN_ERR "Nozomi: failed to register ntty driver\n");
++		goto free_tty;
 +	}
- 
--	kobject_set_name(&bus->drivers.kobj, "drivers");
--	bus->drivers.kobj.parent = &bus->subsys.kobj;
--	bus->drivers.ktype = &driver_ktype;
--	retval = kset_register(&bus->drivers);
--	if (retval)
-+	priv->drivers_kset = kset_create_and_add("drivers", NULL,
-+						 &priv->subsys.kobj);
-+	if (!priv->drivers_kset) {
-+		retval = -ENOMEM;
- 		goto bus_drivers_fail;
++
++	ret = pci_register_driver(&nozomi_driver);
++	if (ret) {
++		printk(KERN_ERR "Nozomi: can't register pci driver\n");
++		goto unr_tty;
 +	}
- 
--	klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
--	klist_init(&bus->klist_drivers, NULL, NULL);
-+	klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
-+	klist_init(&priv->klist_drivers, NULL, NULL);
- 
--	bus->drivers_autoprobe = 1;
- 	retval = add_probe_files(bus);
- 	if (retval)
- 		goto bus_probe_files_fail;
-@@ -885,66 +922,73 @@ int bus_register(struct bus_type * bus)
- 	if (retval)
- 		goto bus_attrs_fail;
- 
--	pr_debug("bus type '%s' registered\n", bus->name);
-+	pr_debug("bus: '%s': registered\n", bus->name);
- 	return 0;
- 
- bus_attrs_fail:
- 	remove_probe_files(bus);
- bus_probe_files_fail:
--	kset_unregister(&bus->drivers);
-+	kset_unregister(bus->p->drivers_kset);
- bus_drivers_fail:
--	kset_unregister(&bus->devices);
-+	kset_unregister(bus->p->devices_kset);
- bus_devices_fail:
- 	bus_remove_file(bus, &bus_attr_uevent);
- bus_uevent_fail:
--	subsystem_unregister(&bus->subsys);
-+	kset_unregister(&bus->p->subsys);
-+	kfree(bus->p);
- out:
- 	return retval;
- }
-+EXPORT_SYMBOL_GPL(bus_register);
- 
- /**
-- *	bus_unregister - remove a bus from the system
-- *	@bus:	bus.
-+ * bus_unregister - remove a bus from the system
-+ * @bus: bus.
-  *
-- *	Unregister the child subsystems and the bus itself.
-- *	Finally, we call bus_put() to release the refcount
-+ * Unregister the child subsystems and the bus itself.
-+ * Finally, we call bus_put() to release the refcount
-  */
--void bus_unregister(struct bus_type * bus)
-+void bus_unregister(struct bus_type *bus)
- {
--	pr_debug("bus %s: unregistering\n", bus->name);
-+	pr_debug("bus: '%s': unregistering\n", bus->name);
- 	bus_remove_attrs(bus);
- 	remove_probe_files(bus);
--	kset_unregister(&bus->drivers);
--	kset_unregister(&bus->devices);
-+	kset_unregister(bus->p->drivers_kset);
-+	kset_unregister(bus->p->devices_kset);
- 	bus_remove_file(bus, &bus_attr_uevent);
--	subsystem_unregister(&bus->subsys);
-+	kset_unregister(&bus->p->subsys);
-+	kfree(bus->p);
- }
-+EXPORT_SYMBOL_GPL(bus_unregister);
- 
- int bus_register_notifier(struct bus_type *bus, struct notifier_block *nb)
- {
--	return blocking_notifier_chain_register(&bus->bus_notifier, nb);
-+	return blocking_notifier_chain_register(&bus->p->bus_notifier, nb);
- }
- EXPORT_SYMBOL_GPL(bus_register_notifier);
- 
- int bus_unregister_notifier(struct bus_type *bus, struct notifier_block *nb)
- {
--	return blocking_notifier_chain_unregister(&bus->bus_notifier, nb);
-+	return blocking_notifier_chain_unregister(&bus->p->bus_notifier, nb);
- }
- EXPORT_SYMBOL_GPL(bus_unregister_notifier);
- 
--int __init buses_init(void)
-+struct kset *bus_get_kset(struct bus_type *bus)
- {
--	return subsystem_register(&bus_subsys);
-+	return &bus->p->subsys;
- }
-+EXPORT_SYMBOL_GPL(bus_get_kset);
- 
-+struct klist *bus_get_device_klist(struct bus_type *bus)
-+{
-+	return &bus->p->klist_devices;
++
++	return 0;
++unr_tty:
++	tty_unregister_driver(ntty_driver);
++free_tty:
++	put_tty_driver(ntty_driver);
++	return ret;
 +}
-+EXPORT_SYMBOL_GPL(bus_get_device_klist);
- 
--EXPORT_SYMBOL_GPL(bus_for_each_dev);
--EXPORT_SYMBOL_GPL(bus_find_device);
--EXPORT_SYMBOL_GPL(bus_for_each_drv);
--
--EXPORT_SYMBOL_GPL(bus_register);
--EXPORT_SYMBOL_GPL(bus_unregister);
--EXPORT_SYMBOL_GPL(bus_rescan_devices);
--
--EXPORT_SYMBOL_GPL(bus_create_file);
--EXPORT_SYMBOL_GPL(bus_remove_file);
-+int __init buses_init(void)
++
++static __exit void nozomi_exit(void)
 +{
-+	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
-+	if (!bus_kset)
-+		return -ENOMEM;
-+	return 0;
++	printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
++	pci_unregister_driver(&nozomi_driver);
++	tty_unregister_driver(ntty_driver);
++	put_tty_driver(ntty_driver);
 +}
-diff --git a/drivers/base/class.c b/drivers/base/class.c
-index a863bb0..9d91537 100644
---- a/drivers/base/class.c
-+++ b/drivers/base/class.c
-@@ -17,16 +17,17 @@
- #include <linux/kdev_t.h>
- #include <linux/err.h>
- #include <linux/slab.h>
-+#include <linux/genhd.h>
- #include "base.h"
- 
- #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
- #define to_class(obj) container_of(obj, struct class, subsys.kobj)
- 
--static ssize_t
--class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
-+static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
-+			       char *buf)
- {
--	struct class_attribute * class_attr = to_class_attr(attr);
--	struct class * dc = to_class(kobj);
-+	struct class_attribute *class_attr = to_class_attr(attr);
-+	struct class *dc = to_class(kobj);
- 	ssize_t ret = -EIO;
- 
- 	if (class_attr->show)
-@@ -34,12 +35,11 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
- 	return ret;
- }
- 
--static ssize_t
--class_attr_store(struct kobject * kobj, struct attribute * attr,
--		 const char * buf, size_t count)
-+static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
-+				const char *buf, size_t count)
- {
--	struct class_attribute * class_attr = to_class_attr(attr);
--	struct class * dc = to_class(kobj);
-+	struct class_attribute *class_attr = to_class_attr(attr);
-+	struct class *dc = to_class(kobj);
- 	ssize_t ret = -EIO;
- 
- 	if (class_attr->store)
-@@ -47,7 +47,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr,
- 	return ret;
- }
- 
--static void class_release(struct kobject * kobj)
-+static void class_release(struct kobject *kobj)
- {
- 	struct class *class = to_class(kobj);
- 
-@@ -71,20 +71,20 @@ static struct kobj_type class_ktype = {
- };
- 
- /* Hotplug events for classes go to the class_obj subsys */
--static decl_subsys(class, &class_ktype, NULL);
-+static struct kset *class_kset;
- 
- 
--int class_create_file(struct class * cls, const struct class_attribute * attr)
-+int class_create_file(struct class *cls, const struct class_attribute *attr)
- {
- 	int error;
--	if (cls) {
-+	if (cls)
- 		error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
--	} else
-+	else
- 		error = -EINVAL;
- 	return error;
- }
- 
--void class_remove_file(struct class * cls, const struct class_attribute * attr)
-+void class_remove_file(struct class *cls, const struct class_attribute *attr)
- {
- 	if (cls)
- 		sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
-@@ -93,48 +93,48 @@ void class_remove_file(struct class * cls, const struct class_attribute * attr)
- static struct class *class_get(struct class *cls)
- {
- 	if (cls)
--		return container_of(kset_get(&cls->subsys), struct class, subsys);
-+		return container_of(kset_get(&cls->subsys),
-+				    struct class, subsys);
- 	return NULL;
- }
- 
--static void class_put(struct class * cls)
-+static void class_put(struct class *cls)
- {
- 	if (cls)
- 		kset_put(&cls->subsys);
- }
- 
--
--static int add_class_attrs(struct class * cls)
-+static int add_class_attrs(struct class *cls)
++
++module_init(nozomi_init);
++module_exit(nozomi_exit);
++
++module_param(debug, int, S_IRUGO | S_IWUSR);
++
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_DESCRIPTION(DRIVER_DESC);
+diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
+index 02518da..454d732 100644
+--- a/drivers/char/pcmcia/cm4000_cs.c
++++ b/drivers/char/pcmcia/cm4000_cs.c
+@@ -308,7 +308,8 @@ static unsigned int calc_baudv(unsigned char fidi)
+ 	return (wcrcf / wbrcf);
+ }
+ 
+-static unsigned short io_read_num_rec_bytes(ioaddr_t iobase, unsigned short *s)
++static unsigned short io_read_num_rec_bytes(unsigned int iobase,
++					    unsigned short *s)
  {
- 	int i;
- 	int error = 0;
- 
- 	if (cls->class_attrs) {
- 		for (i = 0; attr_name(cls->class_attrs[i]); i++) {
--			error = class_create_file(cls,&cls->class_attrs[i]);
-+			error = class_create_file(cls, &cls->class_attrs[i]);
- 			if (error)
--				goto Err;
-+				goto error;
- 		}
- 	}
-- Done:
-+done:
- 	return error;
-- Err:
-+error:
- 	while (--i >= 0)
--		class_remove_file(cls,&cls->class_attrs[i]);
--	goto Done;
-+		class_remove_file(cls, &cls->class_attrs[i]);
-+	goto done;
- }
+ 	unsigned short tmp;
  
--static void remove_class_attrs(struct class * cls)
-+static void remove_class_attrs(struct class *cls)
+@@ -426,7 +427,7 @@ static struct card_fixup card_fixups[] = {
+ static void set_cardparameter(struct cm4000_dev *dev)
  {
  	int i;
+-	ioaddr_t iobase = dev->p_dev->io.BasePort1;
++	unsigned int iobase = dev->p_dev->io.BasePort1;
+ 	u_int8_t stopbits = 0x02; /* ISO default */
+ 
+ 	DEBUGP(3, dev, "-> set_cardparameter\n");
+@@ -459,7 +460,7 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq)
+ 	unsigned short num_bytes_read;
+ 	unsigned char pts_reply[4];
+ 	ssize_t rc;
+-	ioaddr_t iobase = dev->p_dev->io.BasePort1;
++	unsigned int iobase = dev->p_dev->io.BasePort1;
  
- 	if (cls->class_attrs) {
- 		for (i = 0; attr_name(cls->class_attrs[i]); i++)
--			class_remove_file(cls,&cls->class_attrs[i]);
-+			class_remove_file(cls, &cls->class_attrs[i]);
- 	}
- }
- 
--int class_register(struct class * cls)
-+int class_register(struct class *cls)
- {
- 	int error;
- 
-@@ -149,9 +149,16 @@ int class_register(struct class * cls)
- 	if (error)
- 		return error;
- 
--	cls->subsys.kobj.kset = &class_subsys;
-+#if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK)
-+	/* let the block class directory show up in the root of sysfs */
-+	if (cls != &block_class)
-+		cls->subsys.kobj.kset = class_kset;
-+#else
-+	cls->subsys.kobj.kset = class_kset;
-+#endif
-+	cls->subsys.kobj.ktype = &class_ktype;
- 
--	error = subsystem_register(&cls->subsys);
-+	error = kset_register(&cls->subsys);
- 	if (!error) {
- 		error = add_class_attrs(class_get(cls));
- 		class_put(cls);
-@@ -159,11 +166,11 @@ int class_register(struct class * cls)
- 	return error;
- }
- 
--void class_unregister(struct class * cls)
-+void class_unregister(struct class *cls)
- {
- 	pr_debug("device class '%s': unregistering\n", cls->name);
- 	remove_class_attrs(cls);
--	subsystem_unregister(&cls->subsys);
-+	kset_unregister(&cls->subsys);
- }
- 
- static void class_create_release(struct class *cls)
-@@ -241,8 +248,8 @@ void class_destroy(struct class *cls)
- 
- /* Class Device Stuff */
- 
--int class_device_create_file(struct class_device * class_dev,
--			     const struct class_device_attribute * attr)
-+int class_device_create_file(struct class_device *class_dev,
-+			     const struct class_device_attribute *attr)
- {
- 	int error = -EINVAL;
- 	if (class_dev)
-@@ -250,8 +257,8 @@ int class_device_create_file(struct class_device * class_dev,
- 	return error;
- }
+ 	rc = 0;
  
--void class_device_remove_file(struct class_device * class_dev,
--			      const struct class_device_attribute * attr)
-+void class_device_remove_file(struct class_device *class_dev,
-+			      const struct class_device_attribute *attr)
- {
- 	if (class_dev)
- 		sysfs_remove_file(&class_dev->kobj, &attr->attr);
-@@ -273,12 +280,11 @@ void class_device_remove_bin_file(struct class_device *class_dev,
- 		sysfs_remove_bin_file(&class_dev->kobj, attr);
+@@ -610,7 +611,7 @@ exit_setprotocol:
+ 	return rc;
  }
  
--static ssize_t
--class_device_attr_show(struct kobject * kobj, struct attribute * attr,
--		       char * buf)
-+static ssize_t class_device_attr_show(struct kobject *kobj,
-+				      struct attribute *attr, char *buf)
+-static int io_detect_cm4000(ioaddr_t iobase, struct cm4000_dev *dev)
++static int io_detect_cm4000(unsigned int iobase, struct cm4000_dev *dev)
  {
--	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
--	struct class_device * cd = to_class_dev(kobj);
-+	struct class_device_attribute *class_dev_attr = to_class_dev_attr(attr);
-+	struct class_device *cd = to_class_dev(kobj);
- 	ssize_t ret = 0;
  
- 	if (class_dev_attr->show)
-@@ -286,12 +292,12 @@ class_device_attr_show(struct kobject * kobj, struct attribute * attr,
- 	return ret;
+ 	/* note: statemachine is assumed to be reset */
+@@ -671,7 +672,7 @@ static void terminate_monitor(struct cm4000_dev *dev)
+ static void monitor_card(unsigned long p)
+ {
+ 	struct cm4000_dev *dev = (struct cm4000_dev *) p;
+-	ioaddr_t iobase = dev->p_dev->io.BasePort1;
++	unsigned int iobase = dev->p_dev->io.BasePort1;
+ 	unsigned short s;
+ 	struct ptsreq ptsreq;
+ 	int i, atrc;
+@@ -933,7 +934,7 @@ static ssize_t cmm_read(struct file *filp, __user char *buf, size_t count,
+ 			loff_t *ppos)
+ {
+ 	struct cm4000_dev *dev = filp->private_data;
+-	ioaddr_t iobase = dev->p_dev->io.BasePort1;
++	unsigned int iobase = dev->p_dev->io.BasePort1;
+ 	ssize_t rc;
+ 	int i, j, k;
+ 
+@@ -1054,7 +1055,7 @@ static ssize_t cmm_write(struct file *filp, const char __user *buf,
+ 			 size_t count, loff_t *ppos)
+ {
+ 	struct cm4000_dev *dev = (struct cm4000_dev *) filp->private_data;
+-	ioaddr_t iobase = dev->p_dev->io.BasePort1;
++	unsigned int iobase = dev->p_dev->io.BasePort1;
+ 	unsigned short s;
+ 	unsigned char tmp;
+ 	unsigned char infolen;
+@@ -1408,7 +1409,7 @@ static int cmm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
+ 		     unsigned long arg)
+ {
+ 	struct cm4000_dev *dev = filp->private_data;
+-	ioaddr_t iobase = dev->p_dev->io.BasePort1;
++	unsigned int iobase = dev->p_dev->io.BasePort1;
+ 	struct pcmcia_device *link;
+ 	int size;
+ 	int rc;
+diff --git a/drivers/char/random.c b/drivers/char/random.c
+index 5fee056..c511a83 100644
+--- a/drivers/char/random.c
++++ b/drivers/char/random.c
+@@ -667,8 +667,6 @@ void add_disk_randomness(struct gendisk *disk)
+ 	add_timer_randomness(disk->random,
+ 			     0x100 + MKDEV(disk->major, disk->first_minor));
  }
+-
+-EXPORT_SYMBOL(add_disk_randomness);
+ #endif
  
--static ssize_t
--class_device_attr_store(struct kobject * kobj, struct attribute * attr,
--			const char * buf, size_t count)
-+static ssize_t class_device_attr_store(struct kobject *kobj,
-+				       struct attribute *attr,
-+				       const char *buf, size_t count)
- {
--	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
--	struct class_device * cd = to_class_dev(kobj);
-+	struct class_device_attribute *class_dev_attr = to_class_dev_attr(attr);
-+	struct class_device *cd = to_class_dev(kobj);
- 	ssize_t ret = 0;
- 
- 	if (class_dev_attr->store)
-@@ -304,10 +310,10 @@ static struct sysfs_ops class_dev_sysfs_ops = {
- 	.store	= class_device_attr_store,
- };
+ #define EXTRACT_SIZE 10
+diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
+index 0c66b80..78b151c 100644
+--- a/drivers/char/rtc.c
++++ b/drivers/char/rtc.c
+@@ -1,5 +1,5 @@
+ /*
+- *	Real Time Clock interface for Linux	
++ *	Real Time Clock interface for Linux
+  *
+  *	Copyright (C) 1996 Paul Gortmaker
+  *
+@@ -17,7 +17,7 @@
+  *	has been received. If a RTC interrupt has already happened,
+  *	it will output an unsigned long and then block. The output value
+  *	contains the interrupt status in the low byte and the number of
+- *	interrupts since the last read in the remaining high bytes. The 
++ *	interrupts since the last read in the remaining high bytes. The
+  *	/dev/rtc interface can also be used with the select(2) call.
+  *
+  *	This program is free software; you can redistribute it and/or
+@@ -104,12 +104,14 @@ static int rtc_has_irq = 1;
  
--static void class_dev_release(struct kobject * kobj)
-+static void class_dev_release(struct kobject *kobj)
+ #ifndef CONFIG_HPET_EMULATE_RTC
+ #define is_hpet_enabled()			0
+-#define hpet_set_alarm_time(hrs, min, sec) 	0
+-#define hpet_set_periodic_freq(arg) 		0
+-#define hpet_mask_rtc_irq_bit(arg) 		0
+-#define hpet_set_rtc_irq_bit(arg) 		0
+-#define hpet_rtc_timer_init() 			do { } while (0)
+-#define hpet_rtc_dropped_irq() 			0
++#define hpet_set_alarm_time(hrs, min, sec)	0
++#define hpet_set_periodic_freq(arg)		0
++#define hpet_mask_rtc_irq_bit(arg)		0
++#define hpet_set_rtc_irq_bit(arg)		0
++#define hpet_rtc_timer_init()			do { } while (0)
++#define hpet_rtc_dropped_irq()			0
++#define hpet_register_irq_handler(h)		0
++#define hpet_unregister_irq_handler(h)		0
+ #ifdef RTC_IRQ
+ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
  {
- 	struct class_device *cd = to_class_dev(kobj);
--	struct class * cls = cd->class;
-+	struct class *cls = cd->class;
- 
- 	pr_debug("device class '%s': release.\n", cd->class_id);
- 
-@@ -316,8 +322,8 @@ static void class_dev_release(struct kobject * kobj)
- 	else if (cls->release)
- 		cls->release(cd);
- 	else {
--		printk(KERN_ERR "Class Device '%s' does not have a release() function, "
--			"it is broken and must be fixed.\n",
-+		printk(KERN_ERR "Class Device '%s' does not have a release() "
-+			"function, it is broken and must be fixed.\n",
- 			cd->class_id);
- 		WARN_ON(1);
- 	}
-@@ -428,7 +434,8 @@ static int class_uevent(struct kset *kset, struct kobject *kobj,
- 			add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
+@@ -147,7 +149,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file,
+ static unsigned int rtc_poll(struct file *file, poll_table *wait);
+ #endif
  
- 		if (dev->driver)
--			add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
-+			add_uevent_var(env, "PHYSDEVDRIVER=%s",
-+				       dev->driver->name);
- 	}
+-static void get_rtc_alm_time (struct rtc_time *alm_tm);
++static void get_rtc_alm_time(struct rtc_time *alm_tm);
+ #ifdef RTC_IRQ
+ static void set_rtc_irq_bit_locked(unsigned char bit);
+ static void mask_rtc_irq_bit_locked(unsigned char bit);
+@@ -185,9 +187,9 @@ static int rtc_proc_open(struct inode *inode, struct file *file);
+  * rtc_status but before mod_timer is called, which would then reenable the
+  * timer (but you would need to have an awful timing before you'd trip on it)
+  */
+-static unsigned long rtc_status = 0;	/* bitmapped status byte.	*/
+-static unsigned long rtc_freq = 0;	/* Current periodic IRQ rate	*/
+-static unsigned long rtc_irq_data = 0;	/* our output to the world	*/
++static unsigned long rtc_status;	/* bitmapped status byte.	*/
++static unsigned long rtc_freq;		/* Current periodic IRQ rate	*/
++static unsigned long rtc_irq_data;	/* our output to the world	*/
+ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
  
- 	if (class_dev->uevent) {
-@@ -452,43 +459,49 @@ static struct kset_uevent_ops class_uevent_ops = {
- 	.uevent =	class_uevent,
- };
+ #ifdef RTC_IRQ
+@@ -195,7 +197,7 @@ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
+  * rtc_task_lock nests inside rtc_lock.
+  */
+ static DEFINE_SPINLOCK(rtc_task_lock);
+-static rtc_task_t *rtc_callback = NULL;
++static rtc_task_t *rtc_callback;
+ #endif
  
--static decl_subsys(class_obj, &class_device_ktype, &class_uevent_ops);
--
-+/*
-+ * DO NOT copy how this is created, kset_create_and_add() should be
-+ * called, but this is a hold-over from the old-way and will be deleted
-+ * entirely soon.
-+ */
-+static struct kset class_obj_subsys = {
-+	.uevent_ops = &class_uevent_ops,
-+};
+ /*
+@@ -205,7 +207,7 @@ static rtc_task_t *rtc_callback = NULL;
  
--static int class_device_add_attrs(struct class_device * cd)
-+static int class_device_add_attrs(struct class_device *cd)
- {
- 	int i;
- 	int error = 0;
--	struct class * cls = cd->class;
-+	struct class *cls = cd->class;
+ static unsigned long epoch = 1900;	/* year corresponding to 0x00	*/
  
- 	if (cls->class_dev_attrs) {
- 		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
- 			error = class_device_create_file(cd,
--							 &cls->class_dev_attrs[i]);
-+						&cls->class_dev_attrs[i]);
- 			if (error)
--				goto Err;
-+				goto err;
- 		}
- 	}
-- Done:
-+done:
- 	return error;
-- Err:
-+err:
- 	while (--i >= 0)
--		class_device_remove_file(cd,&cls->class_dev_attrs[i]);
--	goto Done;
-+		class_device_remove_file(cd, &cls->class_dev_attrs[i]);
-+	goto done;
- }
+-static const unsigned char days_in_mo[] = 
++static const unsigned char days_in_mo[] =
+ {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  
--static void class_device_remove_attrs(struct class_device * cd)
-+static void class_device_remove_attrs(struct class_device *cd)
- {
- 	int i;
--	struct class * cls = cd->class;
-+	struct class *cls = cd->class;
+ /*
+@@ -242,7 +244,7 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id)
+ 	 *	the last read in the remainder of rtc_irq_data.
+ 	 */
  
- 	if (cls->class_dev_attrs) {
- 		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
--			class_device_remove_file(cd,&cls->class_dev_attrs[i]);
-+			class_device_remove_file(cd, &cls->class_dev_attrs[i]);
- 	}
- }
+-	spin_lock (&rtc_lock);
++	spin_lock(&rtc_lock);
+ 	rtc_irq_data += 0x100;
+ 	rtc_irq_data &= ~0xff;
+ 	if (is_hpet_enabled()) {
+@@ -259,16 +261,16 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id)
+ 	if (rtc_status & RTC_TIMER_ON)
+ 		mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
  
--static int class_device_add_groups(struct class_device * cd)
-+static int class_device_add_groups(struct class_device *cd)
- {
- 	int i;
- 	int error = 0;
-@@ -498,7 +511,8 @@ static int class_device_add_groups(struct class_device * cd)
- 			error = sysfs_create_group(&cd->kobj, cd->groups[i]);
- 			if (error) {
- 				while (--i >= 0)
--					sysfs_remove_group(&cd->kobj, cd->groups[i]);
-+					sysfs_remove_group(&cd->kobj,
-+							   cd->groups[i]);
- 				goto out;
- 			}
- 		}
-@@ -507,14 +521,12 @@ out:
- 	return error;
- }
+-	spin_unlock (&rtc_lock);
++	spin_unlock(&rtc_lock);
  
--static void class_device_remove_groups(struct class_device * cd)
-+static void class_device_remove_groups(struct class_device *cd)
- {
- 	int i;
--	if (cd->groups) {
--		for (i = 0; cd->groups[i]; i++) {
-+	if (cd->groups)
-+		for (i = 0; cd->groups[i]; i++)
- 			sysfs_remove_group(&cd->kobj, cd->groups[i]);
--		}
--	}
- }
+ 	/* Now do the rest of the actions */
+ 	spin_lock(&rtc_task_lock);
+ 	if (rtc_callback)
+ 		rtc_callback->func(rtc_callback->private_data);
+ 	spin_unlock(&rtc_task_lock);
+-	wake_up_interruptible(&rtc_wait);	
++	wake_up_interruptible(&rtc_wait);
  
- static ssize_t show_dev(struct class_device *class_dev, char *buf)
-@@ -537,8 +549,8 @@ static struct class_device_attribute class_uevent_attr =
+-	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
++	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
  
- void class_device_initialize(struct class_device *class_dev)
- {
--	kobj_set_kset_s(class_dev, class_obj_subsys);
--	kobject_init(&class_dev->kobj);
-+	class_dev->kobj.kset = &class_obj_subsys;
-+	kobject_init(&class_dev->kobj, &class_device_ktype);
- 	INIT_LIST_HEAD(&class_dev->node);
+ 	return IRQ_HANDLED;
  }
+@@ -335,7 +337,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
+ 	DECLARE_WAITQUEUE(wait, current);
+ 	unsigned long data;
+ 	ssize_t retval;
+-	
++
+ 	if (rtc_has_irq == 0)
+ 		return -EIO;
  
-@@ -566,16 +578,13 @@ int class_device_add(struct class_device *class_dev)
- 		 class_dev->class_id);
+@@ -358,11 +360,11 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
+ 		 * confusing. And no, xchg() is not the answer. */
  
- 	/* first, register with generic layer. */
--	error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
--	if (error)
--		goto out2;
--
- 	if (parent_class_dev)
- 		class_dev->kobj.parent = &parent_class_dev->kobj;
- 	else
- 		class_dev->kobj.parent = &parent_class->subsys.kobj;
+ 		__set_current_state(TASK_INTERRUPTIBLE);
+-		
+-		spin_lock_irq (&rtc_lock);
++
++		spin_lock_irq(&rtc_lock);
+ 		data = rtc_irq_data;
+ 		rtc_irq_data = 0;
+-		spin_unlock_irq (&rtc_lock);
++		spin_unlock_irq(&rtc_lock);
  
--	error = kobject_add(&class_dev->kobj);
-+	error = kobject_add(&class_dev->kobj, class_dev->kobj.parent,
-+			    "%s", class_dev->class_id);
- 	if (error)
- 		goto out2;
+ 		if (data != 0)
+ 			break;
+@@ -378,10 +380,13 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
+ 		schedule();
+ 	} while (1);
  
-@@ -642,7 +651,7 @@ int class_device_add(struct class_device *class_dev)
-  out3:
- 	kobject_del(&class_dev->kobj);
-  out2:
--	if(parent_class_dev)
-+	if (parent_class_dev)
- 		class_device_put(parent_class_dev);
- 	class_put(parent_class);
-  out1:
-@@ -659,9 +668,11 @@ int class_device_register(struct class_device *class_dev)
- /**
-  * class_device_create - creates a class device and registers it with sysfs
-  * @cls: pointer to the struct class that this device should be registered to.
-- * @parent: pointer to the parent struct class_device of this new device, if any.
-+ * @parent: pointer to the parent struct class_device of this new device, if
-+ * any.
-  * @devt: the dev_t for the char device to be added.
-- * @device: a pointer to a struct device that is assiociated with this class device.
-+ * @device: a pointer to a struct device that is assiociated with this class
-+ * device.
-  * @fmt: string for the class device's name
-  *
-  * This function can be used by char device classes.  A struct
-@@ -785,7 +796,7 @@ void class_device_destroy(struct class *cls, dev_t devt)
- 		class_device_unregister(class_dev);
- }
+-	if (count == sizeof(unsigned int))
+-		retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int);
+-	else
+-		retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long);
++	if (count == sizeof(unsigned int)) {
++		retval = put_user(data,
++				  (unsigned int __user *)buf) ?: sizeof(int);
++	} else {
++		retval = put_user(data,
++				  (unsigned long __user *)buf) ?: sizeof(long);
++	}
+ 	if (!retval)
+ 		retval = count;
+  out:
+@@ -394,7 +399,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
  
--struct class_device * class_device_get(struct class_device *class_dev)
-+struct class_device *class_device_get(struct class_device *class_dev)
+ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
  {
- 	if (class_dev)
- 		return to_class_dev(kobject_get(&class_dev->kobj));
-@@ -798,6 +809,139 @@ void class_device_put(struct class_device *class_dev)
- 		kobject_put(&class_dev->kobj);
- }
+-	struct rtc_time wtime; 
++	struct rtc_time wtime;
  
-+/**
-+ * class_for_each_device - device iterator
-+ * @class: the class we're iterating
-+ * @data: data for the callback
-+ * @fn: function to be called for each device
-+ *
-+ * Iterate over @class's list of devices, and call @fn for each,
-+ * passing it @data.
-+ *
-+ * We check the return of @fn each time. If it returns anything
-+ * other than 0, we break out and return that value.
-+ *
-+ * Note, we hold class->sem in this function, so it can not be
-+ * re-acquired in @fn, otherwise it will self-deadlocking. For
-+ * example, calls to add or remove class members would be verboten.
-+ */
-+int class_for_each_device(struct class *class, void *data,
-+			   int (*fn)(struct device *, void *))
-+{
-+	struct device *dev;
-+	int error = 0;
-+
-+	if (!class)
-+		return -EINVAL;
-+	down(&class->sem);
-+	list_for_each_entry(dev, &class->devices, node) {
-+		dev = get_device(dev);
-+		if (dev) {
-+			error = fn(dev, data);
-+			put_device(dev);
-+		} else
-+			error = -ENODEV;
-+		if (error)
-+			break;
-+	}
-+	up(&class->sem);
-+
-+	return error;
-+}
-+EXPORT_SYMBOL_GPL(class_for_each_device);
-+
-+/**
-+ * class_find_device - device iterator for locating a particular device
-+ * @class: the class we're iterating
-+ * @data: data for the match function
-+ * @match: function to check device
-+ *
-+ * This is similar to the class_for_each_dev() function above, but it
-+ * returns a reference to a device that is 'found' for later use, as
-+ * determined by the @match callback.
-+ *
-+ * The callback should return 0 if the device doesn't match and non-zero
-+ * if it does.  If the callback returns non-zero, this function will
-+ * return to the caller and not iterate over any more devices.
-+ *
-+ * Note, you will need to drop the reference with put_device() after use.
-+ *
-+ * We hold class->sem in this function, so it can not be
-+ * re-acquired in @match, otherwise it will self-deadlocking. For
-+ * example, calls to add or remove class members would be verboten.
-+ */
-+struct device *class_find_device(struct class *class, void *data,
-+				   int (*match)(struct device *, void *))
-+{
-+	struct device *dev;
-+	int found = 0;
-+
-+	if (!class)
-+		return NULL;
+ #ifdef RTC_IRQ
+ 	if (rtc_has_irq == 0) {
+@@ -426,35 +431,41 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ 	}
+ 	case RTC_PIE_OFF:	/* Mask periodic int. enab. bit	*/
+ 	{
+-		unsigned long flags; /* can be called from isr via rtc_control() */
+-		spin_lock_irqsave (&rtc_lock, flags);
++		/* can be called from isr via rtc_control() */
++		unsigned long flags;
 +
-+	down(&class->sem);
-+	list_for_each_entry(dev, &class->devices, node) {
-+		dev = get_device(dev);
-+		if (dev) {
-+			if (match(dev, data)) {
-+				found = 1;
-+				break;
-+			} else
-+				put_device(dev);
-+		} else
-+			break;
-+	}
-+	up(&class->sem);
++		spin_lock_irqsave(&rtc_lock, flags);
+ 		mask_rtc_irq_bit_locked(RTC_PIE);
+ 		if (rtc_status & RTC_TIMER_ON) {
+ 			rtc_status &= ~RTC_TIMER_ON;
+ 			del_timer(&rtc_irq_timer);
+ 		}
+-		spin_unlock_irqrestore (&rtc_lock, flags);
++		spin_unlock_irqrestore(&rtc_lock, flags);
 +
-+	return found ? dev : NULL;
-+}
-+EXPORT_SYMBOL_GPL(class_find_device);
+ 		return 0;
+ 	}
+ 	case RTC_PIE_ON:	/* Allow periodic ints		*/
+ 	{
+-		unsigned long flags; /* can be called from isr via rtc_control() */
++		/* can be called from isr via rtc_control() */
++		unsigned long flags;
 +
-+/**
-+ * class_find_child - device iterator for locating a particular class_device
-+ * @class: the class we're iterating
-+ * @data: data for the match function
-+ * @match: function to check class_device
-+ *
-+ * This function returns a reference to a class_device that is 'found' for
-+ * later use, as determined by the @match callback.
-+ *
-+ * The callback should return 0 if the class_device doesn't match and non-zero
-+ * if it does.  If the callback returns non-zero, this function will
-+ * return to the caller and not iterate over any more class_devices.
-+ *
-+ * Note, you will need to drop the reference with class_device_put() after use.
-+ *
-+ * We hold class->sem in this function, so it can not be
-+ * re-acquired in @match, otherwise it will self-deadlocking. For
-+ * example, calls to add or remove class members would be verboten.
-+ */
-+struct class_device *class_find_child(struct class *class, void *data,
-+				   int (*match)(struct class_device *, void *))
-+{
-+	struct class_device *dev;
-+	int found = 0;
+ 		/*
+ 		 * We don't really want Joe User enabling more
+ 		 * than 64Hz of interrupts on a multi-user machine.
+ 		 */
+ 		if (!kernel && (rtc_freq > rtc_max_user_freq) &&
+-			(!capable(CAP_SYS_RESOURCE)))
++						(!capable(CAP_SYS_RESOURCE)))
+ 			return -EACCES;
+ 
+-		spin_lock_irqsave (&rtc_lock, flags);
++		spin_lock_irqsave(&rtc_lock, flags);
+ 		if (!(rtc_status & RTC_TIMER_ON)) {
+ 			mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq +
+ 					2*HZ/100);
+ 			rtc_status |= RTC_TIMER_ON;
+ 		}
+ 		set_rtc_irq_bit_locked(RTC_PIE);
+-		spin_unlock_irqrestore (&rtc_lock, flags);
++		spin_unlock_irqrestore(&rtc_lock, flags);
 +
-+	if (!class)
-+		return NULL;
+ 		return 0;
+ 	}
+ 	case RTC_UIE_OFF:	/* Mask ints from RTC updates.	*/
+@@ -477,7 +488,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ 		 */
+ 		memset(&wtime, 0, sizeof(struct rtc_time));
+ 		get_rtc_alm_time(&wtime);
+-		break; 
++		break;
+ 	}
+ 	case RTC_ALM_SET:	/* Store a time into the alarm */
+ 	{
+@@ -505,16 +516,21 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ 			 */
+ 		}
+ 		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
+-		    RTC_ALWAYS_BCD)
+-		{
+-			if (sec < 60) BIN_TO_BCD(sec);
+-			else sec = 0xff;
+-
+-			if (min < 60) BIN_TO_BCD(min);
+-			else min = 0xff;
+-
+-			if (hrs < 24) BIN_TO_BCD(hrs);
+-			else hrs = 0xff;
++							RTC_ALWAYS_BCD) {
++			if (sec < 60)
++				BIN_TO_BCD(sec);
++			else
++				sec = 0xff;
 +
-+	down(&class->sem);
-+	list_for_each_entry(dev, &class->children, node) {
-+		dev = class_device_get(dev);
-+		if (dev) {
-+			if (match(dev, data)) {
-+				found = 1;
-+				break;
-+			} else
-+				class_device_put(dev);
-+		} else
-+			break;
-+	}
-+	up(&class->sem);
++			if (min < 60)
++				BIN_TO_BCD(min);
++			else
++				min = 0xff;
 +
-+	return found ? dev : NULL;
-+}
-+EXPORT_SYMBOL_GPL(class_find_child);
- 
- int class_interface_register(struct class_interface *class_intf)
- {
-@@ -829,7 +973,7 @@ int class_interface_register(struct class_interface *class_intf)
++			if (hrs < 24)
++				BIN_TO_BCD(hrs);
++			else
++				hrs = 0xff;
+ 		}
+ 		CMOS_WRITE(hrs, RTC_HOURS_ALARM);
+ 		CMOS_WRITE(min, RTC_MINUTES_ALARM);
+@@ -563,11 +579,12 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
  
- void class_interface_unregister(struct class_interface *class_intf)
- {
--	struct class * parent = class_intf->class;
-+	struct class *parent = class_intf->class;
- 	struct class_device *class_dev;
- 	struct device *dev;
+ 		if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
+ 			return -EINVAL;
+-			
++
+ 		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+ 			return -EINVAL;
  
-@@ -853,15 +997,14 @@ void class_interface_unregister(struct class_interface *class_intf)
+-		if ((yrs -= epoch) > 255)    /* They are unsigned */
++		yrs -= epoch;
++		if (yrs > 255)		/* They are unsigned */
+ 			return -EINVAL;
  
- int __init classes_init(void)
- {
--	int retval;
--
--	retval = subsystem_register(&class_subsys);
--	if (retval)
--		return retval;
-+	class_kset = kset_create_and_add("class", NULL, NULL);
-+	if (!class_kset)
-+		return -ENOMEM;
+ 		spin_lock_irq(&rtc_lock);
+@@ -635,9 +652,10 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ 	{
+ 		int tmp = 0;
+ 		unsigned char val;
+-		unsigned long flags; /* can be called from isr via rtc_control() */
++		/* can be called from isr via rtc_control() */
++		unsigned long flags;
  
- 	/* ick, this is ugly, the things we go through to keep from showing up
- 	 * in sysfs... */
- 	kset_init(&class_obj_subsys);
-+	kobject_set_name(&class_obj_subsys.kobj, "class_obj");
- 	if (!class_obj_subsys.kobj.parent)
- 		class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
- 	return 0;
-diff --git a/drivers/base/core.c b/drivers/base/core.c
-index 2683eac..b172787 100644
---- a/drivers/base/core.c
-+++ b/drivers/base/core.c
-@@ -18,18 +18,26 @@
- #include <linux/string.h>
- #include <linux/kdev_t.h>
- #include <linux/notifier.h>
--
-+#include <linux/genhd.h>
- #include <asm/semaphore.h>
+-		/* 
++		/*
+ 		 * The max we can do is 8192Hz.
+ 		 */
+ 		if ((arg < 2) || (arg > 8192))
+@@ -646,7 +664,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ 		 * We don't really want Joe User generating more
+ 		 * than 64Hz of interrupts on a multi-user machine.
+ 		 */
+-		if (!kernel && (arg > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
++		if (!kernel && (arg > rtc_max_user_freq) &&
++					!capable(CAP_SYS_RESOURCE))
+ 			return -EACCES;
  
- #include "base.h"
- #include "power/power.h"
+ 		while (arg > (1<<tmp))
+@@ -674,11 +693,11 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ #endif
+ 	case RTC_EPOCH_READ:	/* Read the epoch.	*/
+ 	{
+-		return put_user (epoch, (unsigned long __user *)arg);
++		return put_user(epoch, (unsigned long __user *)arg);
+ 	}
+ 	case RTC_EPOCH_SET:	/* Set the epoch.	*/
+ 	{
+-		/* 
++		/*
+ 		 * There were no RTC clocks before 1900.
+ 		 */
+ 		if (arg < 1900)
+@@ -693,7 +712,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ 	default:
+ 		return -ENOTTY;
+ 	}
+-	return copy_to_user((void __user *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
++	return copy_to_user((void __user *)arg,
++			    &wtime, sizeof wtime) ? -EFAULT : 0;
+ }
  
--int (*platform_notify)(struct device * dev) = NULL;
--int (*platform_notify_remove)(struct device * dev) = NULL;
-+int (*platform_notify)(struct device *dev) = NULL;
-+int (*platform_notify_remove)(struct device *dev) = NULL;
+ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+@@ -712,26 +732,25 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+  * needed here. Or anywhere else in this driver. */
+ static int rtc_open(struct inode *inode, struct file *file)
+ {
+-	spin_lock_irq (&rtc_lock);
++	spin_lock_irq(&rtc_lock);
  
--/*
-- * sysfs bindings for devices.
-- */
-+#ifdef CONFIG_BLOCK
-+static inline int device_is_not_partition(struct device *dev)
-+{
-+	return !(dev->type == &part_type);
-+}
-+#else
-+static inline int device_is_not_partition(struct device *dev)
-+{
-+	return 1;
-+}
-+#endif
+-	if(rtc_status & RTC_IS_OPEN)
++	if (rtc_status & RTC_IS_OPEN)
+ 		goto out_busy;
  
- /**
-  * dev_driver_string - Return a device's driver name, if at all possible
-@@ -51,11 +59,11 @@ EXPORT_SYMBOL(dev_driver_string);
- #define to_dev(obj) container_of(obj, struct device, kobj)
- #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
+ 	rtc_status |= RTC_IS_OPEN;
  
--static ssize_t
--dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
-+static ssize_t dev_attr_show(struct kobject *kobj, struct attribute *attr,
-+			     char *buf)
- {
--	struct device_attribute * dev_attr = to_dev_attr(attr);
--	struct device * dev = to_dev(kobj);
-+	struct device_attribute *dev_attr = to_dev_attr(attr);
-+	struct device *dev = to_dev(kobj);
- 	ssize_t ret = -EIO;
+ 	rtc_irq_data = 0;
+-	spin_unlock_irq (&rtc_lock);
++	spin_unlock_irq(&rtc_lock);
+ 	return 0;
  
- 	if (dev_attr->show)
-@@ -63,12 +71,11 @@ dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
- 	return ret;
+ out_busy:
+-	spin_unlock_irq (&rtc_lock);
++	spin_unlock_irq(&rtc_lock);
+ 	return -EBUSY;
  }
  
--static ssize_t
--dev_attr_store(struct kobject * kobj, struct attribute * attr,
--	       const char * buf, size_t count)
-+static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
-+			      const char *buf, size_t count)
- {
--	struct device_attribute * dev_attr = to_dev_attr(attr);
--	struct device * dev = to_dev(kobj);
-+	struct device_attribute *dev_attr = to_dev_attr(attr);
-+	struct device *dev = to_dev(kobj);
- 	ssize_t ret = -EIO;
- 
- 	if (dev_attr->store)
-@@ -90,9 +97,9 @@ static struct sysfs_ops dev_sysfs_ops = {
-  *	reaches 0. We forward the call to the device's release
-  *	method, which should handle actually freeing the structure.
-  */
--static void device_release(struct kobject * kobj)
-+static void device_release(struct kobject *kobj)
+-static int rtc_fasync (int fd, struct file *filp, int on)
+-
++static int rtc_fasync(int fd, struct file *filp, int on)
  {
--	struct device * dev = to_dev(kobj);
-+	struct device *dev = to_dev(kobj);
+-	return fasync_helper (fd, filp, on, &rtc_async_queue);
++	return fasync_helper(fd, filp, on, &rtc_async_queue);
+ }
  
- 	if (dev->release)
- 		dev->release(dev);
-@@ -101,8 +108,8 @@ static void device_release(struct kobject * kobj)
- 	else if (dev->class && dev->class->dev_release)
- 		dev->class->dev_release(dev);
- 	else {
--		printk(KERN_ERR "Device '%s' does not have a release() function, "
--			"it is broken and must be fixed.\n",
-+		printk(KERN_ERR "Device '%s' does not have a release() "
-+			"function, it is broken and must be fixed.\n",
- 			dev->bus_id);
- 		WARN_ON(1);
+ static int rtc_release(struct inode *inode, struct file *file)
+@@ -762,16 +781,16 @@ static int rtc_release(struct inode *inode, struct file *file)
  	}
-@@ -185,7 +192,8 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
- 		add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
+ 	spin_unlock_irq(&rtc_lock);
  
- 		if (dev->driver)
--			add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
-+			add_uevent_var(env, "PHYSDEVDRIVER=%s",
-+				       dev->driver->name);
- 	}
+-	if (file->f_flags & FASYNC) {
+-		rtc_fasync (-1, file, 0);
+-	}
++	if (file->f_flags & FASYNC)
++		rtc_fasync(-1, file, 0);
+ no_irq:
  #endif
  
-@@ -193,15 +201,16 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
- 	if (dev->bus && dev->bus->uevent) {
- 		retval = dev->bus->uevent(dev, env);
- 		if (retval)
--			pr_debug ("%s: bus uevent() returned %d\n",
--				  __FUNCTION__, retval);
-+			pr_debug("device: '%s': %s: bus uevent() returned %d\n",
-+				 dev->bus_id, __FUNCTION__, retval);
- 	}
+-	spin_lock_irq (&rtc_lock);
++	spin_lock_irq(&rtc_lock);
+ 	rtc_irq_data = 0;
+ 	rtc_status &= ~RTC_IS_OPEN;
+-	spin_unlock_irq (&rtc_lock);
++	spin_unlock_irq(&rtc_lock);
++
+ 	return 0;
+ }
  
- 	/* have the class specific function add its stuff */
- 	if (dev->class && dev->class->dev_uevent) {
- 		retval = dev->class->dev_uevent(dev, env);
- 		if (retval)
--			pr_debug("%s: class uevent() returned %d\n",
-+			pr_debug("device: '%s': %s: class uevent() "
-+				 "returned %d\n", dev->bus_id,
- 				 __FUNCTION__, retval);
- 	}
+@@ -786,9 +805,9 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait)
  
-@@ -209,7 +218,8 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
- 	if (dev->type && dev->type->uevent) {
- 		retval = dev->type->uevent(dev, env);
- 		if (retval)
--			pr_debug("%s: dev_type uevent() returned %d\n",
-+			pr_debug("device: '%s': %s: dev_type uevent() "
-+				 "returned %d\n", dev->bus_id,
- 				 __FUNCTION__, retval);
- 	}
+ 	poll_wait(file, &rtc_wait, wait);
  
-@@ -325,7 +335,8 @@ static int device_add_groups(struct device *dev,
- 			error = sysfs_create_group(&dev->kobj, groups[i]);
- 			if (error) {
- 				while (--i >= 0)
--					sysfs_remove_group(&dev->kobj, groups[i]);
-+					sysfs_remove_group(&dev->kobj,
-+							   groups[i]);
- 				break;
- 			}
- 		}
-@@ -401,20 +412,15 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
- static struct device_attribute devt_attr =
- 	__ATTR(dev, S_IRUGO, show_dev, NULL);
+-	spin_lock_irq (&rtc_lock);
++	spin_lock_irq(&rtc_lock);
+ 	l = rtc_irq_data;
+-	spin_unlock_irq (&rtc_lock);
++	spin_unlock_irq(&rtc_lock);
+ 
+ 	if (l != 0)
+ 		return POLLIN | POLLRDNORM;
+@@ -796,14 +815,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait)
+ }
+ #endif
  
 -/*
-- *	devices_subsys - structure to be registered with kobject core.
+- * exported stuffs
 - */
 -
--decl_subsys(devices, &device_ktype, &device_uevent_ops);
--
-+/* kset to create /sys/devices/  */
-+struct kset *devices_kset;
- 
- /**
-- *	device_create_file - create sysfs attribute file for device.
-- *	@dev:	device.
-- *	@attr:	device attribute descriptor.
-+ * device_create_file - create sysfs attribute file for device.
-+ * @dev: device.
-+ * @attr: device attribute descriptor.
-  */
+-EXPORT_SYMBOL(rtc_register);
+-EXPORT_SYMBOL(rtc_unregister);
+-EXPORT_SYMBOL(rtc_control);
 -
--int device_create_file(struct device * dev, struct device_attribute * attr)
-+int device_create_file(struct device *dev, struct device_attribute *attr)
+ int rtc_register(rtc_task_t *task)
  {
- 	int error = 0;
- 	if (get_device(dev)) {
-@@ -425,12 +431,11 @@ int device_create_file(struct device * dev, struct device_attribute * attr)
+ #ifndef RTC_IRQ
+@@ -829,6 +840,7 @@ int rtc_register(rtc_task_t *task)
+ 	return 0;
+ #endif
  }
++EXPORT_SYMBOL(rtc_register);
  
- /**
-- *	device_remove_file - remove sysfs attribute file.
-- *	@dev:	device.
-- *	@attr:	device attribute descriptor.
-+ * device_remove_file - remove sysfs attribute file.
-+ * @dev: device.
-+ * @attr: device attribute descriptor.
-  */
--
--void device_remove_file(struct device * dev, struct device_attribute * attr)
-+void device_remove_file(struct device *dev, struct device_attribute *attr)
+ int rtc_unregister(rtc_task_t *task)
  {
- 	if (get_device(dev)) {
- 		sysfs_remove_file(&dev->kobj, &attr->attr);
-@@ -511,22 +516,20 @@ static void klist_children_put(struct klist_node *n)
- 	put_device(dev);
+@@ -845,7 +857,7 @@ int rtc_unregister(rtc_task_t *task)
+ 		return -ENXIO;
+ 	}
+ 	rtc_callback = NULL;
+-	
++
+ 	/* disable controls */
+ 	if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) {
+ 		tmp = CMOS_READ(RTC_CONTROL);
+@@ -865,6 +877,7 @@ int rtc_unregister(rtc_task_t *task)
+ 	return 0;
+ #endif
  }
++EXPORT_SYMBOL(rtc_unregister);
  
--
- /**
-- *	device_initialize - init device structure.
-- *	@dev:	device.
-+ * device_initialize - init device structure.
-+ * @dev: device.
-  *
-- *	This prepares the device for use by other layers,
-- *	including adding it to the device hierarchy.
-- *	It is the first half of device_register(), if called by
-- *	that, though it can also be called separately, so one
-- *	may use @dev's fields (e.g. the refcount).
-+ * This prepares the device for use by other layers,
-+ * including adding it to the device hierarchy.
-+ * It is the first half of device_register(), if called by
-+ * that, though it can also be called separately, so one
-+ * may use @dev's fields (e.g. the refcount).
-  */
--
- void device_initialize(struct device *dev)
+ int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
  {
--	kobj_set_kset_s(dev, devices_subsys);
--	kobject_init(&dev->kobj);
-+	dev->kobj.kset = devices_kset;
-+	kobject_init(&dev->kobj, &device_ktype);
- 	klist_init(&dev->klist_children, klist_children_get,
- 		   klist_children_put);
- 	INIT_LIST_HEAD(&dev->dma_pools);
-@@ -539,36 +542,39 @@ void device_initialize(struct device *dev)
+@@ -883,7 +896,7 @@ int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
+ 	return rtc_do_ioctl(cmd, arg, 1);
+ #endif
  }
+-
++EXPORT_SYMBOL(rtc_control);
  
- #ifdef CONFIG_SYSFS_DEPRECATED
--static struct kobject * get_device_parent(struct device *dev,
--					  struct device *parent)
-+static struct kobject *get_device_parent(struct device *dev,
-+					 struct device *parent)
- {
--	/*
--	 * Set the parent to the class, not the parent device
--	 * for topmost devices in class hierarchy.
--	 * This keeps sysfs from having a symlink to make old
--	 * udevs happy
--	 */
-+	/* class devices without a parent live in /sys/class/<classname>/ */
- 	if (dev->class && (!parent || parent->class != dev->class))
- 		return &dev->class->subsys.kobj;
-+	/* all other devices keep their parent */
- 	else if (parent)
- 		return &parent->kobj;
- 
- 	return NULL;
- }
-+
-+static inline void cleanup_device_parent(struct device *dev) {}
-+static inline void cleanup_glue_dir(struct device *dev,
-+				    struct kobject *glue_dir) {}
- #else
- static struct kobject *virtual_device_parent(struct device *dev)
- {
- 	static struct kobject *virtual_dir = NULL;
+ /*
+  *	The various file operations we support.
+@@ -910,11 +923,11 @@ static struct miscdevice rtc_dev = {
  
- 	if (!virtual_dir)
--		virtual_dir = kobject_add_dir(&devices_subsys.kobj, "virtual");
-+		virtual_dir = kobject_create_and_add("virtual",
-+						     &devices_kset->kobj);
+ #ifdef CONFIG_PROC_FS
+ static const struct file_operations rtc_proc_fops = {
+-	.owner = THIS_MODULE,
+-	.open = rtc_proc_open,
+-	.read  = seq_read,
+-	.llseek = seq_lseek,
+-	.release = single_release,
++	.owner		= THIS_MODULE,
++	.open		= rtc_proc_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
+ };
+ #endif
  
- 	return virtual_dir;
- }
+@@ -965,7 +978,7 @@ static int __init rtc_init(void)
+ #ifdef CONFIG_SPARC32
+ 	for_each_ebus(ebus) {
+ 		for_each_ebusdev(edev, ebus) {
+-			if(strcmp(edev->prom_node->name, "rtc") == 0) {
++			if (strcmp(edev->prom_node->name, "rtc") == 0) {
+ 				rtc_port = edev->resource[0].start;
+ 				rtc_irq = edev->irqs[0];
+ 				goto found;
+@@ -986,7 +999,8 @@ found:
+ 	 * XXX Interrupt pin #7 in Espresso is shared between RTC and
+ 	 * PCI Slot 2 INTA# (and some INTx# in Slot 1).
+ 	 */
+-	if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
++	if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc",
++			(void *)&rtc_port)) {
+ 		rtc_has_irq = 0;
+ 		printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
+ 		return -EIO;
+@@ -1015,16 +1029,26 @@ no_irq:
  
--static struct kobject * get_device_parent(struct device *dev,
--					  struct device *parent)
-+static struct kobject *get_device_parent(struct device *dev,
-+					 struct device *parent)
- {
-+	int retval;
+ #ifdef RTC_IRQ
+ 	if (is_hpet_enabled()) {
++		int err;
 +
- 	if (dev->class) {
- 		struct kobject *kobj = NULL;
- 		struct kobject *parent_kobj;
-@@ -576,8 +582,8 @@ static struct kobject * get_device_parent(struct device *dev,
- 
- 		/*
- 		 * If we have no parent, we live in "virtual".
--		 * Class-devices with a bus-device as parent, live
--		 * in a class-directory to prevent namespace collisions.
-+		 * Class-devices with a non class-device as parent, live
-+		 * in a "glue" directory to prevent namespace collisions.
- 		 */
- 		if (parent == NULL)
- 			parent_kobj = virtual_device_parent(dev);
-@@ -598,25 +604,45 @@ static struct kobject * get_device_parent(struct device *dev,
- 			return kobj;
- 
- 		/* or create a new class-directory at the parent device */
--		return kobject_kset_add_dir(&dev->class->class_dirs,
--					    parent_kobj, dev->class->name);
-+		k = kobject_create();
-+		if (!k)
-+			return NULL;
-+		k->kset = &dev->class->class_dirs;
-+		retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
-+		if (retval < 0) {
-+			kobject_put(k);
-+			return NULL;
+ 		rtc_int_handler_ptr = hpet_rtc_interrupt;
++		err = hpet_register_irq_handler(rtc_interrupt);
++		if (err != 0) {
++			printk(KERN_WARNING "hpet_register_irq_handler failed "
++					"in rtc_init().");
++			return err;
 +		}
-+		/* do not emit an uevent for this simple "glue" directory */
-+		return k;
+ 	} else {
+ 		rtc_int_handler_ptr = rtc_interrupt;
  	}
  
- 	if (parent)
- 		return &parent->kobj;
- 	return NULL;
- }
-+
-+static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir)
-+{
-+	/* see if we live in a "glue" directory */
-+	if (!dev->class || glue_dir->kset != &dev->class->class_dirs)
-+		return;
-+
-+	kobject_put(glue_dir);
-+}
+-	if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
++	if (request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED,
++			"rtc", NULL)) {
+ 		/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
+ 		rtc_has_irq = 0;
+ 		printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
+ 		rtc_release_region();
 +
-+static void cleanup_device_parent(struct device *dev)
-+{
-+	cleanup_glue_dir(dev, dev->kobj.parent);
-+}
+ 		return -EIO;
+ 	}
+ 	hpet_rtc_timer_init();
+@@ -1036,6 +1060,7 @@ no_irq:
+ 	if (misc_register(&rtc_dev)) {
+ #ifdef RTC_IRQ
+ 		free_irq(RTC_IRQ, NULL);
++		hpet_unregister_irq_handler(rtc_interrupt);
+ 		rtc_has_irq = 0;
  #endif
+ 		rtc_release_region();
+@@ -1052,21 +1077,21 @@ no_irq:
  
--static int setup_parent(struct device *dev, struct device *parent)
-+static void setup_parent(struct device *dev, struct device *parent)
- {
- 	struct kobject *kobj;
- 	kobj = get_device_parent(dev, parent);
--	if (IS_ERR(kobj))
--		return PTR_ERR(kobj);
- 	if (kobj)
- 		dev->kobj.parent = kobj;
--	return 0;
- }
- 
- static int device_add_class_symlinks(struct device *dev)
-@@ -625,65 +651,76 @@ static int device_add_class_symlinks(struct device *dev)
- 
- 	if (!dev->class)
- 		return 0;
+ #if defined(__alpha__) || defined(__mips__)
+ 	rtc_freq = HZ;
+-	
 +
- 	error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj,
- 				  "subsystem");
- 	if (error)
- 		goto out;
--	/*
--	 * If this is not a "fake" compatible device, then create the
--	 * symlink from the class to the device.
--	 */
--	if (dev->kobj.parent != &dev->class->subsys.kobj) {
+ 	/* Each operating system on an Alpha uses its own epoch.
+ 	   Let's try to guess which one we are using now. */
+-	
 +
-+#ifdef CONFIG_SYSFS_DEPRECATED
-+	/* stacked class devices need a symlink in the class directory */
-+	if (dev->kobj.parent != &dev->class->subsys.kobj &&
-+	    device_is_not_partition(dev)) {
- 		error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
- 					  dev->bus_id);
- 		if (error)
- 			goto out_subsys;
- 	}
--	if (dev->parent) {
--#ifdef CONFIG_SYSFS_DEPRECATED
--		{
--			struct device *parent = dev->parent;
--			char *class_name;
--
--			/*
--			 * In old sysfs stacked class devices had 'device'
--			 * link pointing to real device instead of parent
--			 */
--			while (parent->class && !parent->bus && parent->parent)
--				parent = parent->parent;
--
--			error = sysfs_create_link(&dev->kobj,
--						  &parent->kobj,
--						  "device");
--			if (error)
--				goto out_busid;
- 
--			class_name = make_class_name(dev->class->name,
--							&dev->kobj);
--			if (class_name)
--				error = sysfs_create_link(&dev->parent->kobj,
--							&dev->kobj, class_name);
--			kfree(class_name);
--			if (error)
--				goto out_device;
--		}
--#else
--		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
-+	if (dev->parent && device_is_not_partition(dev)) {
-+		struct device *parent = dev->parent;
-+		char *class_name;
+ 	if (rtc_is_updating() != 0)
+ 		msleep(20);
+-	
 +
-+		/*
-+		 * stacked class devices have the 'device' link
-+		 * pointing to the bus device instead of the parent
-+		 */
-+		while (parent->class && !parent->bus && parent->parent)
-+			parent = parent->parent;
+ 	spin_lock_irq(&rtc_lock);
+ 	year = CMOS_READ(RTC_YEAR);
+ 	ctrl = CMOS_READ(RTC_CONTROL);
+ 	spin_unlock_irq(&rtc_lock);
+-	
 +
-+		error = sysfs_create_link(&dev->kobj,
-+					  &parent->kobj,
- 					  "device");
- 		if (error)
- 			goto out_busid;
--#endif
+ 	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ 		BCD_TO_BIN(year);       /* This should never happen... */
+-	
 +
-+		class_name = make_class_name(dev->class->name,
-+						&dev->kobj);
-+		if (class_name)
-+			error = sysfs_create_link(&dev->parent->kobj,
-+						&dev->kobj, class_name);
-+		kfree(class_name);
-+		if (error)
-+			goto out_device;
+ 	if (year < 20) {
+ 		epoch = 2000;
+ 		guess = "SRM (post-2000)";
+@@ -1087,7 +1112,8 @@ no_irq:
+ #endif
+ 	}
+ 	if (guess)
+-		printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", guess, epoch);
++		printk(KERN_INFO "rtc: %s epoch (%lu) detected\n",
++			guess, epoch);
+ #endif
+ #ifdef RTC_IRQ
+ 	if (rtc_has_irq == 0)
+@@ -1096,8 +1122,12 @@ no_irq:
+ 	spin_lock_irq(&rtc_lock);
+ 	rtc_freq = 1024;
+ 	if (!hpet_set_periodic_freq(rtc_freq)) {
+-		/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
+-		CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
++		/*
++		 * Initialize periodic frequency to CMOS reset default,
++		 * which is 1024Hz
++		 */
++		CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06),
++			   RTC_FREQ_SELECT);
  	}
+ 	spin_unlock_irq(&rtc_lock);
+ no_irq2:
+@@ -1110,20 +1140,22 @@ no_irq2:
  	return 0;
+ }
  
--#ifdef CONFIG_SYSFS_DEPRECATED
- out_device:
--	if (dev->parent)
-+	if (dev->parent && device_is_not_partition(dev))
- 		sysfs_remove_link(&dev->kobj, "device");
--#endif
- out_busid:
--	if (dev->kobj.parent != &dev->class->subsys.kobj)
-+	if (dev->kobj.parent != &dev->class->subsys.kobj &&
-+	    device_is_not_partition(dev))
- 		sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
-+#else
-+	/* link in the class directory pointing to the device */
-+	error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj,
-+				  dev->bus_id);
-+	if (error)
-+		goto out_subsys;
-+
-+	if (dev->parent && device_is_not_partition(dev)) {
-+		error = sysfs_create_link(&dev->kobj, &dev->parent->kobj,
-+					  "device");
-+		if (error)
-+			goto out_busid;
-+	}
-+	return 0;
-+
-+out_busid:
-+	sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
-+#endif
-+
- out_subsys:
- 	sysfs_remove_link(&dev->kobj, "subsystem");
- out:
-@@ -694,8 +731,9 @@ static void device_remove_class_symlinks(struct device *dev)
+-static void __exit rtc_exit (void)
++static void __exit rtc_exit(void)
  {
- 	if (!dev->class)
- 		return;
--	if (dev->parent) {
-+
- #ifdef CONFIG_SYSFS_DEPRECATED
-+	if (dev->parent && device_is_not_partition(dev)) {
- 		char *class_name;
+ 	cleanup_sysctl();
+-	remove_proc_entry ("driver/rtc", NULL);
++	remove_proc_entry("driver/rtc", NULL);
+ 	misc_deregister(&rtc_dev);
  
- 		class_name = make_class_name(dev->class->name, &dev->kobj);
-@@ -703,45 +741,59 @@ static void device_remove_class_symlinks(struct device *dev)
- 			sysfs_remove_link(&dev->parent->kobj, class_name);
- 			kfree(class_name);
- 		}
--#endif
- 		sysfs_remove_link(&dev->kobj, "device");
- 	}
--	if (dev->kobj.parent != &dev->class->subsys.kobj)
-+
-+	if (dev->kobj.parent != &dev->class->subsys.kobj &&
-+	    device_is_not_partition(dev))
- 		sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
-+#else
-+	if (dev->parent && device_is_not_partition(dev))
-+		sysfs_remove_link(&dev->kobj, "device");
-+
-+	sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id);
-+#endif
-+
- 	sysfs_remove_link(&dev->kobj, "subsystem");
+ #ifdef CONFIG_SPARC32
+ 	if (rtc_has_irq)
+-		free_irq (rtc_irq, &rtc_port);
++		free_irq(rtc_irq, &rtc_port);
+ #else
+ 	rtc_release_region();
+ #ifdef RTC_IRQ
+-	if (rtc_has_irq)
+-		free_irq (RTC_IRQ, NULL);
++	if (rtc_has_irq) {
++		free_irq(RTC_IRQ, NULL);
++		hpet_unregister_irq_handler(hpet_rtc_interrupt);
++	}
+ #endif
+ #endif /* CONFIG_SPARC32 */
  }
+@@ -1133,14 +1165,14 @@ module_exit(rtc_exit);
  
- /**
-- *	device_add - add device to device hierarchy.
-- *	@dev:	device.
-+ * device_add - add device to device hierarchy.
-+ * @dev: device.
-  *
-- *	This is part 2 of device_register(), though may be called
-- *	separately _iff_ device_initialize() has been called separately.
-+ * This is part 2 of device_register(), though may be called
-+ * separately _iff_ device_initialize() has been called separately.
-  *
-- *	This adds it to the kobject hierarchy via kobject_add(), adds it
-- *	to the global and sibling lists for the device, then
-- *	adds it to the other relevant subsystems of the driver model.
-+ * This adds it to the kobject hierarchy via kobject_add(), adds it
-+ * to the global and sibling lists for the device, then
-+ * adds it to the other relevant subsystems of the driver model.
+ #ifdef RTC_IRQ
+ /*
+- * 	At IRQ rates >= 4096Hz, an interrupt may get lost altogether.
++ *	At IRQ rates >= 4096Hz, an interrupt may get lost altogether.
+  *	(usually during an IDE disk interrupt, with IRQ unmasking off)
+  *	Since the interrupt handler doesn't get called, the IRQ status
+  *	byte doesn't get read, and the RTC stops generating interrupts.
+  *	A timer is set, and will call this function if/when that happens.
+  *	To get it out of this stalled state, we just read the status.
+  *	At least a jiffy of interrupts (rtc_freq/HZ) will have been lost.
+- *	(You *really* shouldn't be trying to use a non-realtime system 
++ *	(You *really* shouldn't be trying to use a non-realtime system
+  *	for something that requires a steady > 1KHz signal anyways.)
   */
- int device_add(struct device *dev)
+ 
+@@ -1148,7 +1180,7 @@ static void rtc_dropped_irq(unsigned long data)
  {
- 	struct device *parent = NULL;
- 	struct class_interface *class_intf;
--	int error = -EINVAL;
-+	int error;
-+
-+	error = pm_sleep_lock();
-+	if (error) {
-+		dev_warn(dev, "Suspicious %s during suspend\n", __FUNCTION__);
-+		dump_stack();
-+		return error;
-+	}
+ 	unsigned long freq;
  
- 	dev = get_device(dev);
--	if (!dev || !strlen(dev->bus_id))
-+	if (!dev || !strlen(dev->bus_id)) {
-+		error = -EINVAL;
- 		goto Error;
+-	spin_lock_irq (&rtc_lock);
++	spin_lock_irq(&rtc_lock);
+ 
+ 	if (hpet_rtc_dropped_irq()) {
+ 		spin_unlock_irq(&rtc_lock);
+@@ -1167,13 +1199,15 @@ static void rtc_dropped_irq(unsigned long data)
+ 
+ 	spin_unlock_irq(&rtc_lock);
+ 
+-	if (printk_ratelimit())
+-		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
++	if (printk_ratelimit()) {
++		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
++			freq);
 +	}
  
--	pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
-+	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
+ 	/* Now we have new data */
+ 	wake_up_interruptible(&rtc_wait);
  
- 	parent = get_device(dev->parent);
--	error = setup_parent(dev, parent);
--	if (error)
--		goto Error;
-+	setup_parent(dev, parent);
+-	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
++	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+ }
+ #endif
  
- 	/* first, register with generic layer. */
--	kobject_set_name(&dev->kobj, "%s", dev->bus_id);
--	error = kobject_add(&dev->kobj);
-+	error = kobject_add(&dev->kobj, dev->kobj.parent, "%s", dev->bus_id);
- 	if (error)
- 		goto Error;
+@@ -1277,7 +1311,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
+ 	 * can take just over 2ms. We wait 20ms. There is no need to
+ 	 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
+ 	 * If you need to know *exactly* when a second has started, enable
+-	 * periodic update complete interrupts, (via ioctl) and then 
++	 * periodic update complete interrupts, (via ioctl) and then
+ 	 * immediately read /dev/rtc which will block until you get the IRQ.
+ 	 * Once the read clears, read the RTC time (again via ioctl). Easy.
+ 	 */
+@@ -1307,8 +1341,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
+ 	ctrl = CMOS_READ(RTC_CONTROL);
+ 	spin_unlock_irqrestore(&rtc_lock, flags);
  
-@@ -751,7 +803,7 @@ int device_add(struct device *dev)
+-	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+-	{
++	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ 		BCD_TO_BIN(rtc_tm->tm_sec);
+ 		BCD_TO_BIN(rtc_tm->tm_min);
+ 		BCD_TO_BIN(rtc_tm->tm_hour);
+@@ -1326,7 +1359,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
+ 	 * Account for differences between how the RTC uses the values
+ 	 * and how they are defined in a struct rtc_time;
+ 	 */
+-	if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
++	rtc_tm->tm_year += epoch - 1900;
++	if (rtc_tm->tm_year <= 69)
+ 		rtc_tm->tm_year += 100;
  
- 	/* notify clients of device entry (new way) */
- 	if (dev->bus)
--		blocking_notifier_call_chain(&dev->bus->bus_notifier,
-+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- 					     BUS_NOTIFY_ADD_DEVICE, dev);
+ 	rtc_tm->tm_mon--;
+@@ -1347,8 +1381,7 @@ static void get_rtc_alm_time(struct rtc_time *alm_tm)
+ 	ctrl = CMOS_READ(RTC_CONTROL);
+ 	spin_unlock_irq(&rtc_lock);
  
- 	error = device_create_file(dev, &uevent_attr);
-@@ -795,13 +847,14 @@ int device_add(struct device *dev)
- 	}
-  Done:
- 	put_device(dev);
-+	pm_sleep_unlock();
- 	return error;
-  BusError:
- 	device_pm_remove(dev);
- 	dpm_sysfs_remove(dev);
-  PMError:
- 	if (dev->bus)
--		blocking_notifier_call_chain(&dev->bus->bus_notifier,
-+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- 					     BUS_NOTIFY_DEL_DEVICE, dev);
- 	device_remove_attrs(dev);
-  AttrsError:
-@@ -809,124 +862,84 @@ int device_add(struct device *dev)
-  SymlinkError:
- 	if (MAJOR(dev->devt))
- 		device_remove_file(dev, &devt_attr);
--
--	if (dev->class) {
--		sysfs_remove_link(&dev->kobj, "subsystem");
--		/* If this is not a "fake" compatible device, remove the
--		 * symlink from the class to the device. */
--		if (dev->kobj.parent != &dev->class->subsys.kobj)
--			sysfs_remove_link(&dev->class->subsys.kobj,
--					  dev->bus_id);
--		if (parent) {
--#ifdef CONFIG_SYSFS_DEPRECATED
--			char *class_name = make_class_name(dev->class->name,
--							   &dev->kobj);
--			if (class_name)
--				sysfs_remove_link(&dev->parent->kobj,
--						  class_name);
--			kfree(class_name);
--#endif
--			sysfs_remove_link(&dev->kobj, "device");
--		}
--	}
-  ueventattrError:
- 	device_remove_file(dev, &uevent_attr);
-  attrError:
- 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
- 	kobject_del(&dev->kobj);
-  Error:
-+	cleanup_device_parent(dev);
- 	if (parent)
- 		put_device(parent);
- 	goto Done;
- }
+-	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+-	{
++	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+ 		BCD_TO_BIN(alm_tm->tm_sec);
+ 		BCD_TO_BIN(alm_tm->tm_min);
+ 		BCD_TO_BIN(alm_tm->tm_hour);
+diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
+index 905d1f5..d010ed9 100644
+--- a/drivers/char/synclink.c
++++ b/drivers/char/synclink.c
+@@ -1544,7 +1544,7 @@ static void mgsl_isr_receive_data( struct mgsl_struct *info )
  
--
- /**
-- *	device_register - register a device with the system.
-- *	@dev:	pointer to the device structure
-+ * device_register - register a device with the system.
-+ * @dev: pointer to the device structure
-  *
-- *	This happens in two clean steps - initialize the device
-- *	and add it to the system. The two steps can be called
-- *	separately, but this is the easiest and most common.
-- *	I.e. you should only call the two helpers separately if
-- *	have a clearly defined need to use and refcount the device
-- *	before it is added to the hierarchy.
-+ * This happens in two clean steps - initialize the device
-+ * and add it to the system. The two steps can be called
-+ * separately, but this is the easiest and most common.
-+ * I.e. you should only call the two helpers separately if
-+ * have a clearly defined need to use and refcount the device
-+ * before it is added to the hierarchy.
+ /* mgsl_isr_misc()
+  * 
+- * 	Service a miscellaneos interrupt source.
++ * 	Service a miscellaneous interrupt source.
+  * 	
+  * Arguments:		info		pointer to device extension (instance data)
+  * Return Value:	None
+diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
+index 5422f99..ce5ebe3 100644
+--- a/drivers/char/toshiba.c
++++ b/drivers/char/toshiba.c
+@@ -505,7 +505,7 @@ static int __init toshiba_init(void)
+ 	if (tosh_probe())
+ 		return -ENODEV;
+ 
+-	printk(KERN_INFO "Toshiba System Managment Mode driver v" TOSH_VERSION "\n");
++	printk(KERN_INFO "Toshiba System Management Mode driver v" TOSH_VERSION "\n");
+ 
+ 	/* set the port to use for Fn status if not specified as a parameter */
+ 	if (tosh_fn==0x00)
+diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
+index d222012..bacded0 100644
+--- a/drivers/char/tty_audit.c
++++ b/drivers/char/tty_audit.c
+@@ -73,6 +73,7 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf)
+  *	@tsk with @loginuid.  @buf->mutex must be locked.
   */
--
- int device_register(struct device *dev)
+ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
++			       unsigned int sessionid,
+ 			       struct tty_audit_buf *buf)
  {
- 	device_initialize(dev);
- 	return device_add(dev);
- }
+ 	struct audit_buffer *ab;
+@@ -85,9 +86,9 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
+ 	if (ab) {
+ 		char name[sizeof(tsk->comm)];
  
--
- /**
-- *	get_device - increment reference count for device.
-- *	@dev:	device.
-+ * get_device - increment reference count for device.
-+ * @dev: device.
-  *
-- *	This simply forwards the call to kobject_get(), though
-- *	we do take care to provide for the case that we get a NULL
-- *	pointer passed in.
-+ * This simply forwards the call to kobject_get(), though
-+ * we do take care to provide for the case that we get a NULL
-+ * pointer passed in.
+-		audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
+-				 "minor=%d comm=", tsk->pid, tsk->uid,
+-				 loginuid, buf->major, buf->minor);
++		audit_log_format(ab, "tty pid=%u uid=%u auid=%u ses=%u "
++				 "major=%d minor=%d comm=", tsk->pid, tsk->uid,
++				 loginuid, sessionid, buf->major, buf->minor);
+ 		get_task_comm(name, tsk);
+ 		audit_log_untrustedstring(ab, name);
+ 		audit_log_format(ab, " data=");
+@@ -105,8 +106,9 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
   */
--
--struct device * get_device(struct device * dev)
-+struct device *get_device(struct device *dev)
+ static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
  {
- 	return dev ? to_dev(kobject_get(&dev->kobj)) : NULL;
+-	tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
+-			   buf);
++	uid_t auid = audit_get_loginuid(current);
++	unsigned int sessionid = audit_get_sessionid(current);
++	tty_audit_buf_push(current, auid, sessionid, buf);
  }
  
--
  /**
-- *	put_device - decrement reference count.
-- *	@dev:	device in question.
-+ * put_device - decrement reference count.
-+ * @dev: device in question.
-  */
--void put_device(struct device * dev)
-+void put_device(struct device *dev)
+@@ -152,6 +154,11 @@ void tty_audit_fork(struct signal_struct *sig)
+ void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
  {
-+	/* might_sleep(); */
- 	if (dev)
- 		kobject_put(&dev->kobj);
+ 	struct tty_audit_buf *buf;
++	/* FIXME I think this is correct.  Check against netlink once that is
++	 * I really need to read this code more closely.  But that's for
++	 * another patch.
++	 */
++	unsigned int sessionid = audit_get_sessionid(tsk);
+ 
+ 	spin_lock_irq(&tsk->sighand->siglock);
+ 	buf = tsk->signal->tty_audit_buf;
+@@ -162,7 +169,7 @@ void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+ 		return;
+ 
+ 	mutex_lock(&buf->mutex);
+-	tty_audit_buf_push(tsk, loginuid, buf);
++	tty_audit_buf_push(tsk, loginuid, sessionid, buf);
+ 	mutex_unlock(&buf->mutex);
+ 
+ 	tty_audit_buf_put(buf);
+diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
+index e34da5c..dc17fe3 100644
+--- a/drivers/char/virtio_console.c
++++ b/drivers/char/virtio_console.c
+@@ -158,13 +158,13 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
+ 	/* Find the input queue. */
+ 	/* FIXME: This is why we want to wean off hvc: we do nothing
+ 	 * when input comes in. */
+-	in_vq = vdev->config->find_vq(vdev, NULL);
++	in_vq = vdev->config->find_vq(vdev, 0, NULL);
+ 	if (IS_ERR(in_vq)) {
+ 		err = PTR_ERR(in_vq);
+ 		goto free;
+ 	}
+ 
+-	out_vq = vdev->config->find_vq(vdev, NULL);
++	out_vq = vdev->config->find_vq(vdev, 1, NULL);
+ 	if (IS_ERR(out_vq)) {
+ 		err = PTR_ERR(out_vq);
+ 		goto free_in_vq;
+diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
+index 12ceed5..5732ca3 100644
+--- a/drivers/connector/cn_queue.c
++++ b/drivers/connector/cn_queue.c
+@@ -104,7 +104,6 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id
+ 		return -EINVAL;
+ 	}
+ 
+-	cbq->nls = dev->nls;
+ 	cbq->seq = 0;
+ 	cbq->group = cbq->id.id.idx;
+ 
+@@ -146,7 +145,6 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
+ 	spin_lock_init(&dev->queue_lock);
+ 
+ 	dev->nls = nls;
+-	dev->netlink_groups = 0;
+ 
+ 	dev->cn_queue = create_workqueue(dev->name);
+ 	if (!dev->cn_queue) {
+diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
+index bf9716b..fea2d3e 100644
+--- a/drivers/connector/connector.c
++++ b/drivers/connector/connector.c
+@@ -88,6 +88,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
+ 			if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
+ 				found = 1;
+ 				group = __cbq->group;
++				break;
+ 			}
+ 		}
+ 		spin_unlock_bh(&dev->cbdev->queue_lock);
+@@ -181,33 +182,14 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
  }
  
+ /*
+- * Skb receive helper - checks skb and msg size and calls callback
+- * helper.
+- */
+-static int __cn_rx_skb(struct sk_buff *skb, struct nlmsghdr *nlh)
+-{
+-	u32 pid, uid, seq, group;
+-	struct cn_msg *msg;
 -
- /**
-- *	device_del - delete device from system.
-- *	@dev:	device.
-+ * device_del - delete device from system.
-+ * @dev: device.
-  *
-- *	This is the first part of the device unregistration
-- *	sequence. This removes the device from the lists we control
-- *	from here, has it removed from the other driver model
-- *	subsystems it was added to in device_add(), and removes it
-- *	from the kobject hierarchy.
-+ * This is the first part of the device unregistration
-+ * sequence. This removes the device from the lists we control
-+ * from here, has it removed from the other driver model
-+ * subsystems it was added to in device_add(), and removes it
-+ * from the kobject hierarchy.
+-	pid = NETLINK_CREDS(skb)->pid;
+-	uid = NETLINK_CREDS(skb)->uid;
+-	seq = nlh->nlmsg_seq;
+-	group = NETLINK_CB((skb)).dst_group;
+-	msg = NLMSG_DATA(nlh);
+-
+-	return cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+-}
+-
+-/*
+  * Main netlink receiving function.
   *
-- *	NOTE: this should be called manually _iff_ device_add() was
-- *	also called manually.
-+ * NOTE: this should be called manually _iff_ device_add() was
-+ * also called manually.
+- * It checks skb and netlink header sizes and calls the skb receive
+- * helper with a shared skb.
++ * It checks skb, netlink header and msg sizes, and calls callback helper.
   */
--
--void device_del(struct device * dev)
-+void device_del(struct device *dev)
+ static void cn_rx_skb(struct sk_buff *__skb)
  {
--	struct device * parent = dev->parent;
-+	struct device *parent = dev->parent;
- 	struct class_interface *class_intf;
++	struct cn_msg *msg;
+ 	struct nlmsghdr *nlh;
+-	u32 len;
+ 	int err;
+ 	struct sk_buff *skb;
  
-+	device_pm_remove(dev);
- 	if (parent)
- 		klist_del(&dev->knode_parent);
- 	if (MAJOR(dev->devt))
- 		device_remove_file(dev, &devt_attr);
- 	if (dev->class) {
--		sysfs_remove_link(&dev->kobj, "subsystem");
--		/* If this is not a "fake" compatible device, remove the
--		 * symlink from the class to the device. */
--		if (dev->kobj.parent != &dev->class->subsys.kobj)
--			sysfs_remove_link(&dev->class->subsys.kobj,
--					  dev->bus_id);
--		if (parent) {
--#ifdef CONFIG_SYSFS_DEPRECATED
--			char *class_name = make_class_name(dev->class->name,
--							   &dev->kobj);
--			if (class_name)
--				sysfs_remove_link(&dev->parent->kobj,
--						  class_name);
--			kfree(class_name);
--#endif
--			sysfs_remove_link(&dev->kobj, "device");
--		}
-+		device_remove_class_symlinks(dev);
+@@ -223,11 +205,8 @@ static void cn_rx_skb(struct sk_buff *__skb)
+ 			return;
+ 		}
  
- 		down(&dev->class->sem);
- 		/* notify any interfaces that the device is now gone */
-@@ -936,31 +949,6 @@ void device_del(struct device * dev)
- 		/* remove the device from the class list */
- 		list_del_init(&dev->node);
- 		up(&dev->class->sem);
--
--		/* If we live in a parent class-directory, unreference it */
--		if (dev->kobj.parent->kset == &dev->class->class_dirs) {
--			struct device *d;
--			int other = 0;
--
--			/*
--			 * if we are the last child of our class, delete
--			 * our class-directory at this parent
--			 */
--			down(&dev->class->sem);
--			list_for_each_entry(d, &dev->class->devices, node) {
--				if (d == dev)
--					continue;
--				if (d->kobj.parent == dev->kobj.parent) {
--					other = 1;
--					break;
--				}
--			}
--			if (!other)
--				kobject_del(dev->kobj.parent);
+-		len = NLMSG_ALIGN(nlh->nlmsg_len);
+-		if (len > skb->len)
+-			len = skb->len;
 -
--			kobject_put(dev->kobj.parent);
--			up(&dev->class->sem);
--		}
+-		err = __cn_rx_skb(skb, nlh);
++		msg = NLMSG_DATA(nlh);
++		err = cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
+ 		if (err < 0)
+ 			kfree_skb(skb);
  	}
- 	device_remove_file(dev, &uevent_attr);
- 	device_remove_attrs(dev);
-@@ -979,57 +967,55 @@ void device_del(struct device * dev)
- 	if (platform_notify_remove)
- 		platform_notify_remove(dev);
- 	if (dev->bus)
--		blocking_notifier_call_chain(&dev->bus->bus_notifier,
-+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- 					     BUS_NOTIFY_DEL_DEVICE, dev);
--	device_pm_remove(dev);
- 	kobject_uevent(&dev->kobj, KOBJ_REMOVE);
-+	cleanup_device_parent(dev);
- 	kobject_del(&dev->kobj);
--	if (parent)
--		put_device(parent);
-+	put_device(parent);
- }
+@@ -441,8 +420,7 @@ static int __devinit cn_init(void)
  
- /**
-- *	device_unregister - unregister device from system.
-- *	@dev:	device going away.
-+ * device_unregister - unregister device from system.
-+ * @dev: device going away.
-  *
-- *	We do this in two parts, like we do device_register(). First,
-- *	we remove it from all the subsystems with device_del(), then
-- *	we decrement the reference count via put_device(). If that
-- *	is the final reference count, the device will be cleaned up
-- *	via device_release() above. Otherwise, the structure will
-- *	stick around until the final reference to the device is dropped.
-+ * We do this in two parts, like we do device_register(). First,
-+ * we remove it from all the subsystems with device_del(), then
-+ * we decrement the reference count via put_device(). If that
-+ * is the final reference count, the device will be cleaned up
-+ * via device_release() above. Otherwise, the structure will
-+ * stick around until the final reference to the device is dropped.
-  */
--void device_unregister(struct device * dev)
-+void device_unregister(struct device *dev)
- {
--	pr_debug("DEV: Unregistering device. ID = '%s'\n", dev->bus_id);
-+	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
- 	device_del(dev);
- 	put_device(dev);
+ 	dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
+ 	if (!dev->cbdev) {
+-		if (dev->nls->sk_socket)
+-			sock_release(dev->nls->sk_socket);
++		netlink_kernel_release(dev->nls);
+ 		return -EINVAL;
+ 	}
+ 	
+@@ -452,8 +430,7 @@ static int __devinit cn_init(void)
+ 	if (err) {
+ 		cn_already_initialized = 0;
+ 		cn_queue_free_dev(dev->cbdev);
+-		if (dev->nls->sk_socket)
+-			sock_release(dev->nls->sk_socket);
++		netlink_kernel_release(dev->nls);
+ 		return -EINVAL;
+ 	}
+ 
+@@ -468,8 +445,7 @@ static void __devexit cn_fini(void)
+ 
+ 	cn_del_callback(&dev->id);
+ 	cn_queue_free_dev(dev->cbdev);
+-	if (dev->nls->sk_socket)
+-		sock_release(dev->nls->sk_socket);
++	netlink_kernel_release(dev->nls);
  }
  
+ subsys_initcall(cn_init);
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 79581fa..b730d67 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -828,11 +828,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ 	memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+ 
+ 	/* prepare interface data */
+-	policy->kobj.parent = &sys_dev->kobj;
+-	policy->kobj.ktype = &ktype_cpufreq;
+-	kobject_set_name(&policy->kobj, "cpufreq");
 -
--static struct device * next_device(struct klist_iter * i)
-+static struct device *next_device(struct klist_iter *i)
- {
--	struct klist_node * n = klist_next(i);
-+	struct klist_node *n = klist_next(i);
- 	return n ? container_of(n, struct device, knode_parent) : NULL;
- }
+-	ret = kobject_register(&policy->kobj);
++	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
++				   "cpufreq");
+ 	if (ret) {
+ 		unlock_policy_rwsem_write(cpu);
+ 		goto err_out_driver_exit;
+@@ -902,6 +899,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
+ 		goto err_out_unregister;
+ 	}
  
- /**
-- *	device_for_each_child - device child iterator.
-- *	@parent: parent struct device.
-- *	@data:	data for the callback.
-- *	@fn:	function to be called for each device.
-+ * device_for_each_child - device child iterator.
-+ * @parent: parent struct device.
-+ * @data: data for the callback.
-+ * @fn: function to be called for each device.
-  *
-- *	Iterate over @parent's child devices, and call @fn for each,
-- *	passing it @data.
-+ * Iterate over @parent's child devices, and call @fn for each,
-+ * passing it @data.
-  *
-- *	We check the return of @fn each time. If it returns anything
-- *	other than 0, we break out and return that value.
-+ * We check the return of @fn each time. If it returns anything
-+ * other than 0, we break out and return that value.
-  */
--int device_for_each_child(struct device * parent, void * data,
--		     int (*fn)(struct device *, void *))
-+int device_for_each_child(struct device *parent, void *data,
-+			  int (*fn)(struct device *dev, void *data))
- {
- 	struct klist_iter i;
--	struct device * child;
-+	struct device *child;
- 	int error = 0;
++	kobject_uevent(&policy->kobj, KOBJ_ADD);
+ 	module_put(cpufreq_driver->owner);
+ 	dprintk("initialization complete\n");
+ 	cpufreq_debug_enable_ratelimit();
+@@ -915,7 +913,7 @@ err_out_unregister:
+ 		cpufreq_cpu_data[j] = NULL;
+ 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
  
- 	klist_iter_init(&parent->klist_children, &i);
-@@ -1054,8 +1040,8 @@ int device_for_each_child(struct device * parent, void * data,
-  * current device can be obtained, this function will return to the caller
-  * and not iterate over any more devices.
-  */
--struct device * device_find_child(struct device *parent, void *data,
--				  int (*match)(struct device *, void *))
-+struct device *device_find_child(struct device *parent, void *data,
-+				 int (*match)(struct device *dev, void *data))
- {
- 	struct klist_iter i;
- 	struct device *child;
-@@ -1073,7 +1059,10 @@ struct device * device_find_child(struct device *parent, void *data,
+-	kobject_unregister(&policy->kobj);
++	kobject_put(&policy->kobj);
+ 	wait_for_completion(&policy->kobj_unregister);
  
- int __init devices_init(void)
+ err_out_driver_exit:
+@@ -1032,8 +1030,6 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
+ 
+ 	unlock_policy_rwsem_write(cpu);
+ 
+-	kobject_unregister(&data->kobj);
+-
+ 	kobject_put(&data->kobj);
+ 
+ 	/* we need to make sure that the underlying kobj is actually
+@@ -1608,7 +1604,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
+ 	memcpy(&policy->cpuinfo, &data->cpuinfo,
+ 				sizeof(struct cpufreq_cpuinfo));
+ 
+-	if (policy->min > data->min && policy->min > policy->max) {
++	if (policy->min > data->max || policy->max < data->min) {
+ 		ret = -EINVAL;
+ 		goto error_out;
+ 	}
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index d2fabe7..2a98d99 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -12,7 +12,7 @@
+ #include <linux/mutex.h>
+ #include <linux/sched.h>
+ #include <linux/notifier.h>
+-#include <linux/latency.h>
++#include <linux/pm_qos_params.h>
+ #include <linux/cpu.h>
+ #include <linux/cpuidle.h>
+ 
+@@ -265,7 +265,10 @@ static struct notifier_block cpuidle_latency_notifier = {
+ 	.notifier_call = cpuidle_latency_notify,
+ };
+ 
+-#define latency_notifier_init(x) do { register_latency_notifier(x); } while (0)
++static inline void latency_notifier_init(struct notifier_block *n)
++{
++	pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, n);
++}
+ 
+ #else /* CONFIG_SMP */
+ 
+diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
+index eb666ec..ba7b9a6 100644
+--- a/drivers/cpuidle/governors/ladder.c
++++ b/drivers/cpuidle/governors/ladder.c
+@@ -14,7 +14,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/cpuidle.h>
+-#include <linux/latency.h>
++#include <linux/pm_qos_params.h>
+ #include <linux/moduleparam.h>
+ #include <linux/jiffies.h>
+ 
+@@ -81,7 +81,8 @@ static int ladder_select_state(struct cpuidle_device *dev)
+ 	/* consider promotion */
+ 	if (last_idx < dev->state_count - 1 &&
+ 	    last_residency > last_state->threshold.promotion_time &&
+-	    dev->states[last_idx + 1].exit_latency <= system_latency_constraint()) {
++	    dev->states[last_idx + 1].exit_latency <=
++			pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY)) {
+ 		last_state->stats.promotion_count++;
+ 		last_state->stats.demotion_count = 0;
+ 		if (last_state->stats.promotion_count >= last_state->threshold.promotion_count) {
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index 299d45c..78d77c5 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -8,7 +8,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/cpuidle.h>
+-#include <linux/latency.h>
++#include <linux/pm_qos_params.h>
+ #include <linux/time.h>
+ #include <linux/ktime.h>
+ #include <linux/hrtimer.h>
+@@ -48,7 +48,7 @@ static int menu_select(struct cpuidle_device *dev)
+ 			break;
+ 		if (s->target_residency > data->predicted_us)
+ 			break;
+-		if (s->exit_latency > system_latency_constraint())
++		if (s->exit_latency > pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY))
+ 			break;
+ 	}
+ 
+diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
+index 0f3515e..088ea74 100644
+--- a/drivers/cpuidle/sysfs.c
++++ b/drivers/cpuidle/sysfs.c
+@@ -277,7 +277,7 @@ static struct kobj_type ktype_state_cpuidle = {
+ 
+ static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
  {
--	return subsystem_register(&devices_subsys);
-+	devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
-+	if (!devices_kset)
-+		return -ENOMEM;
-+	return 0;
- }
+-	kobject_unregister(&device->kobjs[i]->kobj);
++	kobject_put(&device->kobjs[i]->kobj);
+ 	wait_for_completion(&device->kobjs[i]->kobj_unregister);
+ 	kfree(device->kobjs[i]);
+ 	device->kobjs[i] = NULL;
+@@ -300,14 +300,13 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
+ 		kobj->state = &device->states[i];
+ 		init_completion(&kobj->kobj_unregister);
  
- EXPORT_SYMBOL_GPL(device_for_each_child);
-@@ -1094,7 +1083,7 @@ EXPORT_SYMBOL_GPL(device_remove_file);
+-		kobj->kobj.parent = &device->kobj;
+-		kobj->kobj.ktype = &ktype_state_cpuidle;
+-		kobject_set_name(&kobj->kobj, "state%d", i);
+-		ret = kobject_register(&kobj->kobj);
++		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
++					   "state%d", i);
+ 		if (ret) {
+ 			kfree(kobj);
+ 			goto error_state;
+ 		}
++		kobject_uevent(&kobj->kobj, KOBJ_ADD);
+ 		device->kobjs[i] = kobj;
+ 	}
  
- static void device_create_release(struct device *dev)
+@@ -339,12 +338,14 @@ int cpuidle_add_sysfs(struct sys_device *sysdev)
  {
--	pr_debug("%s called for %s\n", __FUNCTION__, dev->bus_id);
-+	pr_debug("device: '%s': %s\n", dev->bus_id, __FUNCTION__);
- 	kfree(dev);
- }
+ 	int cpu = sysdev->id;
+ 	struct cpuidle_device *dev;
++	int error;
  
-@@ -1156,14 +1145,11 @@ error:
- EXPORT_SYMBOL_GPL(device_create);
+ 	dev = per_cpu(cpuidle_devices, cpu);
+-	dev->kobj.parent = &sysdev->kobj;
+-	dev->kobj.ktype = &ktype_cpuidle;
+-	kobject_set_name(&dev->kobj, "%s", "cpuidle");
+-	return kobject_register(&dev->kobj);
++	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj,
++				     "cpuidle");
++	if (!error)
++		kobject_uevent(&dev->kobj, KOBJ_ADD);
++	return error;
+ }
  
  /**
-- * device_destroy - removes a device that was created with device_create()
-+ * find_device - finds a device that was created with device_create()
-  * @class: pointer to the struct class that this device was registered with
-  * @devt: the dev_t of the device that was previously registered
-- *
-- * This call unregisters and cleans up a device that was created with a
-- * call to device_create().
-  */
--void device_destroy(struct class *class, dev_t devt)
-+static struct device *find_device(struct class *class, dev_t devt)
- {
- 	struct device *dev = NULL;
- 	struct device *dev_tmp;
-@@ -1176,12 +1162,54 @@ void device_destroy(struct class *class, dev_t devt)
- 		}
- 	}
- 	up(&class->sem);
-+	return dev;
-+}
+@@ -357,5 +358,5 @@ void cpuidle_remove_sysfs(struct sys_device *sysdev)
+ 	struct cpuidle_device *dev;
  
-+/**
-+ * device_destroy - removes a device that was created with device_create()
-+ * @class: pointer to the struct class that this device was registered with
-+ * @devt: the dev_t of the device that was previously registered
-+ *
-+ * This call unregisters and cleans up a device that was created with a
-+ * call to device_create().
-+ */
-+void device_destroy(struct class *class, dev_t devt)
-+{
-+	struct device *dev;
-+
-+	dev = find_device(class, devt);
- 	if (dev)
- 		device_unregister(dev);
+ 	dev = per_cpu(cpuidle_devices, cpu);
+-	kobject_unregister(&dev->kobj);
++	kobject_put(&dev->kobj);
  }
- EXPORT_SYMBOL_GPL(device_destroy);
+diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
+index ddd3a25..6b658d8 100644
+--- a/drivers/crypto/Kconfig
++++ b/drivers/crypto/Kconfig
+@@ -48,8 +48,6 @@ config CRYPTO_DEV_PADLOCK_SHA
+ 	  If unsure say M. The compiled module will be
+ 	  called padlock-sha.ko
  
-+#ifdef CONFIG_PM_SLEEP
-+/**
-+ * destroy_suspended_device - asks the PM core to remove a suspended device
-+ * @class: pointer to the struct class that this device was registered with
-+ * @devt: the dev_t of the device that was previously registered
-+ *
-+ * This call notifies the PM core of the necessity to unregister a suspended
-+ * device created with a call to device_create() (devices cannot be
-+ * unregistered directly while suspended, since the PM core holds their
-+ * semaphores at that time).
-+ *
-+ * It can only be called within the scope of a system sleep transition.  In
-+ * practice this means it has to be directly or indirectly invoked either by
-+ * a suspend or resume method, or by the PM core (e.g. via
-+ * disable_nonboot_cpus() or enable_nonboot_cpus()).
-+ */
-+void destroy_suspended_device(struct class *class, dev_t devt)
-+{
-+	struct device *dev;
+-source "arch/s390/crypto/Kconfig"
+-
+ config CRYPTO_DEV_GEODE
+ 	tristate "Support for the Geode LX AES engine"
+ 	depends on X86_32 && PCI
+@@ -83,4 +81,82 @@ config ZCRYPT_MONOLITHIC
+ 	  that contains all parts of the crypto device driver (ap bus,
+ 	  request router and all the card drivers).
+ 
++config CRYPTO_SHA1_S390
++	tristate "SHA1 digest algorithm"
++	depends on S390
++	select CRYPTO_ALGAPI
++	help
++	  This is the s390 hardware accelerated implementation of the
++	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
 +
-+	dev = find_device(class, devt);
-+	if (dev)
-+		device_pm_schedule_removal(dev);
-+}
-+EXPORT_SYMBOL_GPL(destroy_suspended_device);
-+#endif /* CONFIG_PM_SLEEP */
++config CRYPTO_SHA256_S390
++	tristate "SHA256 digest algorithm"
++	depends on S390
++	select CRYPTO_ALGAPI
++	help
++	  This is the s390 hardware accelerated implementation of the
++	  SHA256 secure hash standard (DFIPS 180-2).
 +
- /**
-  * device_rename - renames a device
-  * @dev: the pointer to the struct device to be renamed
-@@ -1198,7 +1226,8 @@ int device_rename(struct device *dev, char *new_name)
- 	if (!dev)
- 		return -EINVAL;
- 
--	pr_debug("DEVICE: renaming '%s' to '%s'\n", dev->bus_id, new_name);
-+	pr_debug("device: '%s': %s: renaming to '%s'\n", dev->bus_id,
-+		 __FUNCTION__, new_name);
- 
- #ifdef CONFIG_SYSFS_DEPRECATED
- 	if ((dev->class) && (dev->parent))
-@@ -1279,8 +1308,7 @@ static int device_move_class_links(struct device *dev,
- 					  class_name);
- 		if (error)
- 			sysfs_remove_link(&dev->kobj, "device");
--	}
--	else
-+	} else
- 		error = 0;
- out:
- 	kfree(class_name);
-@@ -1311,16 +1339,13 @@ int device_move(struct device *dev, struct device *new_parent)
- 		return -EINVAL;
- 
- 	new_parent = get_device(new_parent);
--	new_parent_kobj = get_device_parent (dev, new_parent);
--	if (IS_ERR(new_parent_kobj)) {
--		error = PTR_ERR(new_parent_kobj);
--		put_device(new_parent);
--		goto out;
--	}
--	pr_debug("DEVICE: moving '%s' to '%s'\n", dev->bus_id,
--		 new_parent ? new_parent->bus_id : "<NULL>");
-+	new_parent_kobj = get_device_parent(dev, new_parent);
++	  This version of SHA implements a 256 bit hash with 128 bits of
++	  security against collision attacks.
 +
-+	pr_debug("device: '%s': %s: moving to '%s'\n", dev->bus_id,
-+		 __FUNCTION__, new_parent ? new_parent->bus_id : "<NULL>");
- 	error = kobject_move(&dev->kobj, new_parent_kobj);
- 	if (error) {
-+		cleanup_glue_dir(dev, new_parent_kobj);
- 		put_device(new_parent);
- 		goto out;
- 	}
-@@ -1343,6 +1368,7 @@ int device_move(struct device *dev, struct device *new_parent)
- 				klist_add_tail(&dev->knode_parent,
- 					       &old_parent->klist_children);
- 		}
-+		cleanup_glue_dir(dev, new_parent_kobj);
- 		put_device(new_parent);
- 		goto out;
- 	}
-@@ -1352,5 +1378,23 @@ out:
- 	put_device(dev);
- 	return error;
- }
--
- EXPORT_SYMBOL_GPL(device_move);
++config CRYPTO_DES_S390
++	tristate "DES and Triple DES cipher algorithms"
++	depends on S390
++	select CRYPTO_ALGAPI
++	select CRYPTO_BLKCIPHER
++	help
++	  This us the s390 hardware accelerated implementation of the
++	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
 +
-+/**
-+ * device_shutdown - call ->shutdown() on each device to shutdown.
-+ */
-+void device_shutdown(void)
-+{
-+	struct device *dev, *devn;
++config CRYPTO_AES_S390
++	tristate "AES cipher algorithms"
++	depends on S390
++	select CRYPTO_ALGAPI
++	select CRYPTO_BLKCIPHER
++	help
++	  This is the s390 hardware accelerated implementation of the
++	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
++	  algorithm.
 +
-+	list_for_each_entry_safe_reverse(dev, devn, &devices_kset->list,
-+				kobj.entry) {
-+		if (dev->bus && dev->bus->shutdown) {
-+			dev_dbg(dev, "shutdown\n");
-+			dev->bus->shutdown(dev);
-+		} else if (dev->driver && dev->driver->shutdown) {
-+			dev_dbg(dev, "shutdown\n");
-+			dev->driver->shutdown(dev);
-+		}
-+	}
-+}
-diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
-index 4054507..c5885f5 100644
---- a/drivers/base/cpu.c
-+++ b/drivers/base/cpu.c
-@@ -14,7 +14,7 @@
- #include "base.h"
- 
- struct sysdev_class cpu_sysdev_class = {
--	set_kset_name("cpu"),
-+	.name = "cpu",
- };
- EXPORT_SYMBOL(cpu_sysdev_class);
++	  Rijndael appears to be consistently a very good performer in
++	  both hardware and software across a wide range of computing
++	  environments regardless of its use in feedback or non-feedback
++	  modes. Its key setup time is excellent, and its key agility is
++	  good. Rijndael's very low memory requirements make it very well
++	  suited for restricted-space environments, in which it also
++	  demonstrates excellent performance. Rijndael's operations are
++	  among the easiest to defend against power and timing attacks.
++
++	  On s390 the System z9-109 currently only supports the key size
++	  of 128 bit.
++
++config S390_PRNG
++	tristate "Pseudo random number generator device driver"
++	depends on S390
++	default "m"
++	help
++	  Select this option if you want to use the s390 pseudo random number
++	  generator. The PRNG is part of the cryptographic processor functions
++	  and uses triple-DES to generate secure random numbers like the
++	  ANSI X9.17 standard. The PRNG is usable via the char device
++	  /dev/prandom.
++
++config CRYPTO_DEV_HIFN_795X
++	tristate "Driver HIFN 795x crypto accelerator chips"
++	select CRYPTO_DES
++	select CRYPTO_ALGAPI
++	select CRYPTO_BLKCIPHER
++	select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
++	depends on PCI
++	help
++	  This option allows you to have support for HIFN 795x crypto adapters.
++
++config CRYPTO_DEV_HIFN_795X_RNG
++	bool "HIFN 795x random number generator"
++	depends on CRYPTO_DEV_HIFN_795X
++	help
++	  Select this option if you want to enable the random number generator
++	  on the HIFN 795x crypto adapters.
++
+ endif # CRYPTO_HW
+diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
+index d070030..c0327f0 100644
+--- a/drivers/crypto/Makefile
++++ b/drivers/crypto/Makefile
+@@ -1,3 +1,4 @@
+ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
+ obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
+ obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
++obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
+diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
+index 711e246..4801162 100644
+--- a/drivers/crypto/geode-aes.c
++++ b/drivers/crypto/geode-aes.c
+@@ -13,44 +13,13 @@
+ #include <linux/crypto.h>
+ #include <linux/spinlock.h>
+ #include <crypto/algapi.h>
++#include <crypto/aes.h>
  
-diff --git a/drivers/base/dd.c b/drivers/base/dd.c
-index 7ac474d..a5cde94 100644
---- a/drivers/base/dd.c
-+++ b/drivers/base/dd.c
-@@ -1,18 +1,20 @@
- /*
-- *	drivers/base/dd.c - The core device/driver interactions.
-+ * drivers/base/dd.c - The core device/driver interactions.
-  *
-- * 	This file contains the (sometimes tricky) code that controls the
-- *	interactions between devices and drivers, which primarily includes
-- *	driver binding and unbinding.
-+ * This file contains the (sometimes tricky) code that controls the
-+ * interactions between devices and drivers, which primarily includes
-+ * driver binding and unbinding.
-  *
-- *	All of this code used to exist in drivers/base/bus.c, but was
-- *	relocated to here in the name of compartmentalization (since it wasn't
-- *	strictly code just for the 'struct bus_type'.
-+ * All of this code used to exist in drivers/base/bus.c, but was
-+ * relocated to here in the name of compartmentalization (since it wasn't
-+ * strictly code just for the 'struct bus_type'.
-  *
-- *	Copyright (c) 2002-5 Patrick Mochel
-- *	Copyright (c) 2002-3 Open Source Development Labs
-+ * Copyright (c) 2002-5 Patrick Mochel
-+ * Copyright (c) 2002-3 Open Source Development Labs
-+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
-+ * Copyright (c) 2007 Novell Inc.
-  *
-- *	This file is released under the GPLv2
-+ * This file is released under the GPLv2
-  */
+ #include <asm/io.h>
+ #include <asm/delay.h>
  
- #include <linux/device.h>
-@@ -23,8 +25,6 @@
- #include "base.h"
- #include "power/power.h"
+ #include "geode-aes.h"
  
--#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
+-/* Register definitions */
+-
+-#define AES_CTRLA_REG  0x0000
+-
+-#define AES_CTRL_START     0x01
+-#define AES_CTRL_DECRYPT   0x00
+-#define AES_CTRL_ENCRYPT   0x02
+-#define AES_CTRL_WRKEY     0x04
+-#define AES_CTRL_DCA       0x08
+-#define AES_CTRL_SCA       0x10
+-#define AES_CTRL_CBC       0x20
+-
+-#define AES_INTR_REG  0x0008
+-
+-#define AES_INTRA_PENDING (1 << 16)
+-#define AES_INTRB_PENDING (1 << 17)
+-
+-#define AES_INTR_PENDING  (AES_INTRA_PENDING | AES_INTRB_PENDING)
+-#define AES_INTR_MASK     0x07
 -
+-#define AES_SOURCEA_REG   0x0010
+-#define AES_DSTA_REG      0x0014
+-#define AES_LENA_REG      0x0018
+-#define AES_WRITEKEY0_REG 0x0030
+-#define AES_WRITEIV0_REG  0x0040
+-
+-/*  A very large counter that is used to gracefully bail out of an
+- *  operation in case of trouble
+- */
+-
+-#define AES_OP_TIMEOUT    0x50000
+-
+ /* Static structures */
  
- static void driver_bound(struct device *dev)
+ static void __iomem * _iobase;
+@@ -87,9 +56,10 @@ do_crypt(void *src, void *dst, int len, u32 flags)
+ 	/* Start the operation */
+ 	iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
+ 
+-	do
++	do {
+ 		status = ioread32(_iobase + AES_INTR_REG);
+-	while(!(status & AES_INTRA_PENDING) && --counter);
++		cpu_relax();
++	} while(!(status & AES_INTRA_PENDING) && --counter);
+ 
+ 	/* Clear the event */
+ 	iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
+@@ -101,6 +71,7 @@ geode_aes_crypt(struct geode_aes_op *op)
  {
-@@ -34,27 +34,27 @@ static void driver_bound(struct device *dev)
- 		return;
+ 	u32 flags = 0;
+ 	unsigned long iflags;
++	int ret;
+ 
+ 	if (op->len == 0)
+ 		return 0;
+@@ -129,7 +100,8 @@ geode_aes_crypt(struct geode_aes_op *op)
+ 		_writefield(AES_WRITEKEY0_REG, op->key);
  	}
  
--	pr_debug("bound device '%s' to driver '%s'\n",
--		 dev->bus_id, dev->driver->name);
-+	pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->bus_id,
-+		 __FUNCTION__, dev->driver->name);
+-	do_crypt(op->src, op->dst, op->len, flags);
++	ret = do_crypt(op->src, op->dst, op->len, flags);
++	BUG_ON(ret);
  
- 	if (dev->bus)
--		blocking_notifier_call_chain(&dev->bus->bus_notifier,
-+		blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- 					     BUS_NOTIFY_BOUND_DRIVER, dev);
+ 	if (op->mode == AES_MODE_CBC)
+ 		_readfield(AES_WRITEIV0_REG, op->iv);
+@@ -141,18 +113,103 @@ geode_aes_crypt(struct geode_aes_op *op)
  
--	klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
-+	klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices);
- }
+ /* CRYPTO-API Functions */
  
- static int driver_sysfs_add(struct device *dev)
+-static int
+-geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len)
++static int geode_setkey_cip(struct crypto_tfm *tfm, const u8 *key,
++		unsigned int len)
  {
- 	int ret;
+ 	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++	unsigned int ret;
  
--	ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj,
-+	ret = sysfs_create_link(&dev->driver->p->kobj, &dev->kobj,
- 			  kobject_name(&dev->kobj));
- 	if (ret == 0) {
--		ret = sysfs_create_link(&dev->kobj, &dev->driver->kobj,
-+		ret = sysfs_create_link(&dev->kobj, &dev->driver->p->kobj,
- 					"driver");
- 		if (ret)
--			sysfs_remove_link(&dev->driver->kobj,
-+			sysfs_remove_link(&dev->driver->p->kobj,
- 					kobject_name(&dev->kobj));
+-	if (len != AES_KEY_LENGTH) {
++	op->keylen = len;
++
++	if (len == AES_KEYSIZE_128) {
++		memcpy(op->key, key, len);
++		return 0;
++	}
++
++	if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
++		/* not supported at all */
+ 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ 		return -EINVAL;
  	}
- 	return ret;
-@@ -65,24 +65,24 @@ static void driver_sysfs_remove(struct device *dev)
- 	struct device_driver *drv = dev->driver;
  
- 	if (drv) {
--		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
-+		sysfs_remove_link(&drv->p->kobj, kobject_name(&dev->kobj));
- 		sysfs_remove_link(&dev->kobj, "driver");
- 	}
+-	memcpy(op->key, key, len);
+-	return 0;
++	/*
++	 * The requested key size is not supported by HW, do a fallback
++	 */
++	op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
++	op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
++
++	ret = crypto_cipher_setkey(op->fallback.cip, key, len);
++	if (ret) {
++		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
++		tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
++	}
++	return ret;
++}
++
++static int geode_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
++		unsigned int len)
++{
++	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++	unsigned int ret;
++
++	op->keylen = len;
++
++	if (len == AES_KEYSIZE_128) {
++		memcpy(op->key, key, len);
++		return 0;
++	}
++
++	if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
++		/* not supported at all */
++		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
++		return -EINVAL;
++	}
++
++	/*
++	 * The requested key size is not supported by HW, do a fallback
++	 */
++	op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
++	op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
++
++	ret = crypto_blkcipher_setkey(op->fallback.blk, key, len);
++	if (ret) {
++		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
++		tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
++	}
++	return ret;
++}
++
++static int fallback_blk_dec(struct blkcipher_desc *desc,
++		struct scatterlist *dst, struct scatterlist *src,
++		unsigned int nbytes)
++{
++	unsigned int ret;
++	struct crypto_blkcipher *tfm;
++	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
++
++	tfm = desc->tfm;
++	desc->tfm = op->fallback.blk;
++
++	ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
++
++	desc->tfm = tfm;
++	return ret;
++}
++static int fallback_blk_enc(struct blkcipher_desc *desc,
++		struct scatterlist *dst, struct scatterlist *src,
++		unsigned int nbytes)
++{
++	unsigned int ret;
++	struct crypto_blkcipher *tfm;
++	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
++
++	tfm = desc->tfm;
++	desc->tfm = op->fallback.blk;
++
++	ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
++
++	desc->tfm = tfm;
++	return ret;
  }
  
- /**
-- *	device_bind_driver - bind a driver to one device.
-- *	@dev:	device.
-+ * device_bind_driver - bind a driver to one device.
-+ * @dev: device.
-  *
-- *	Allow manual attachment of a driver to a device.
-- *	Caller must have already set @dev->driver.
-+ * Allow manual attachment of a driver to a device.
-+ * Caller must have already set @dev->driver.
-  *
-- *	Note that this does not modify the bus reference count
-- *	nor take the bus's rwsem. Please verify those are accounted
-- *	for before calling this. (It is ok to call with no other effort
-- *	from a driver's probe() method.)
-+ * Note that this does not modify the bus reference count
-+ * nor take the bus's rwsem. Please verify those are accounted
-+ * for before calling this. (It is ok to call with no other effort
-+ * from a driver's probe() method.)
-  *
-- *	This function must be called with @dev->sem held.
-+ * This function must be called with @dev->sem held.
-  */
- int device_bind_driver(struct device *dev)
+ static void
+@@ -160,8 +217,10 @@ geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
  {
-@@ -93,6 +93,7 @@ int device_bind_driver(struct device *dev)
- 		driver_bound(dev);
- 	return ret;
- }
-+EXPORT_SYMBOL_GPL(device_bind_driver);
- 
- static atomic_t probe_count = ATOMIC_INIT(0);
- static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
-@@ -102,8 +103,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
- 	int ret = 0;
+ 	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
  
- 	atomic_inc(&probe_count);
--	pr_debug("%s: Probing driver %s with device %s\n",
--		 drv->bus->name, drv->name, dev->bus_id);
-+	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
-+		 drv->bus->name, __FUNCTION__, drv->name, dev->bus_id);
- 	WARN_ON(!list_empty(&dev->devres_head));
+-	if ((out == NULL) || (in == NULL))
++	if (unlikely(op->keylen != AES_KEYSIZE_128)) {
++		crypto_cipher_encrypt_one(op->fallback.cip, out, in);
+ 		return;
++	}
  
- 	dev->driver = drv;
-@@ -125,8 +126,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
+ 	op->src = (void *) in;
+ 	op->dst = (void *) out;
+@@ -179,8 +238,10 @@ geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+ 	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
  
- 	driver_bound(dev);
- 	ret = 1;
--	pr_debug("%s: Bound Device %s to Driver %s\n",
--		 drv->bus->name, dev->bus_id, drv->name);
-+	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
-+		 drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
- 	goto done;
+-	if ((out == NULL) || (in == NULL))
++	if (unlikely(op->keylen != AES_KEYSIZE_128)) {
++		crypto_cipher_decrypt_one(op->fallback.cip, out, in);
+ 		return;
++	}
  
- probe_failed:
-@@ -183,7 +184,7 @@ int driver_probe_done(void)
-  * This function must be called with @dev->sem held.  When called for a
-  * USB interface, @dev->parent->sem must be held as well.
-  */
--int driver_probe_device(struct device_driver * drv, struct device * dev)
-+int driver_probe_device(struct device_driver *drv, struct device *dev)
- {
- 	int ret = 0;
+ 	op->src = (void *) in;
+ 	op->dst = (void *) out;
+@@ -192,24 +253,50 @@ geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ 	geode_aes_crypt(op);
+ }
  
-@@ -192,8 +193,8 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
- 	if (drv->bus->match && !drv->bus->match(dev, drv))
- 		goto done;
++static int fallback_init_cip(struct crypto_tfm *tfm)
++{
++	const char *name = tfm->__crt_alg->cra_name;
++	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++
++	op->fallback.cip = crypto_alloc_cipher(name, 0,
++				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
++
++	if (IS_ERR(op->fallback.cip)) {
++		printk(KERN_ERR "Error allocating fallback algo %s\n", name);
++		return PTR_ERR(op->fallback.blk);
++	}
++
++	return 0;
++}
++
++static void fallback_exit_cip(struct crypto_tfm *tfm)
++{
++	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++
++	crypto_free_cipher(op->fallback.cip);
++	op->fallback.cip = NULL;
++}
  
--	pr_debug("%s: Matched Device %s with Driver %s\n",
--		 drv->bus->name, dev->bus_id, drv->name);
-+	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
-+		 drv->bus->name, __FUNCTION__, dev->bus_id, drv->name);
+ static struct crypto_alg geode_alg = {
+-	.cra_name               =       "aes",
+-	.cra_driver_name	=       "geode-aes-128",
+-	.cra_priority           =       300,
+-	.cra_alignmask          =       15,
+-	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
++	.cra_name			=	"aes",
++	.cra_driver_name	=	"geode-aes",
++	.cra_priority		=	300,
++	.cra_alignmask		=	15,
++	.cra_flags			=	CRYPTO_ALG_TYPE_CIPHER |
++							CRYPTO_ALG_NEED_FALLBACK,
++	.cra_init			=	fallback_init_cip,
++	.cra_exit			=	fallback_exit_cip,
+ 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
+ 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
+-	.cra_module		=	THIS_MODULE,
+-	.cra_list		=	LIST_HEAD_INIT(geode_alg.cra_list),
+-	.cra_u			=	{
+-		.cipher = {
+-			.cia_min_keysize	=  AES_KEY_LENGTH,
+-			.cia_max_keysize	=  AES_KEY_LENGTH,
+-			.cia_setkey		=  geode_setkey,
+-			.cia_encrypt		=  geode_encrypt,
+-			.cia_decrypt		=  geode_decrypt
++	.cra_module			=	THIS_MODULE,
++	.cra_list			=	LIST_HEAD_INIT(geode_alg.cra_list),
++	.cra_u				=	{
++		.cipher	=	{
++			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
++			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
++			.cia_setkey			=	geode_setkey_cip,
++			.cia_encrypt		=	geode_encrypt,
++			.cia_decrypt		=	geode_decrypt
+ 		}
+ 	}
+ };
+@@ -223,8 +310,12 @@ geode_cbc_decrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err, ret;
  
- 	ret = really_probe(dev, drv);
++	if (unlikely(op->keylen != AES_KEYSIZE_128))
++		return fallback_blk_dec(desc, dst, src, nbytes);
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
++	op->iv = walk.iv;
  
-@@ -201,27 +202,27 @@ done:
- 	return ret;
- }
+ 	while((nbytes = walk.nbytes)) {
+ 		op->src = walk.src.virt.addr,
+@@ -233,13 +324,9 @@ geode_cbc_decrypt(struct blkcipher_desc *desc,
+ 		op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+ 		op->dir = AES_DIR_DECRYPT;
  
--static int __device_attach(struct device_driver * drv, void * data)
-+static int __device_attach(struct device_driver *drv, void *data)
- {
--	struct device * dev = data;
-+	struct device *dev = data;
- 	return driver_probe_device(drv, dev);
- }
+-		memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+-
+ 		ret = geode_aes_crypt(op);
  
- /**
-- *	device_attach - try to attach device to a driver.
-- *	@dev:	device.
-+ * device_attach - try to attach device to a driver.
-+ * @dev: device.
-  *
-- *	Walk the list of drivers that the bus has and call
-- *	driver_probe_device() for each pair. If a compatible
-- *	pair is found, break out and return.
-+ * Walk the list of drivers that the bus has and call
-+ * driver_probe_device() for each pair. If a compatible
-+ * pair is found, break out and return.
-  *
-- *	Returns 1 if the device was bound to a driver;
-- *	0 if no matching device was found;
-- *	-ENODEV if the device is not registered.
-+ * Returns 1 if the device was bound to a driver;
-+ * 0 if no matching device was found;
-+ * -ENODEV if the device is not registered.
-  *
-- *	When called for a USB interface, @dev->parent->sem must be held.
-+ * When called for a USB interface, @dev->parent->sem must be held.
-  */
--int device_attach(struct device * dev)
-+int device_attach(struct device *dev)
- {
- 	int ret = 0;
+-		memcpy(walk.iv, op->iv, AES_IV_LENGTH);
+ 		nbytes -= ret;
+-
+ 		err = blkcipher_walk_done(desc, &walk, nbytes);
+ 	}
  
-@@ -240,10 +241,11 @@ int device_attach(struct device * dev)
- 	up(&dev->sem);
- 	return ret;
- }
-+EXPORT_SYMBOL_GPL(device_attach);
+@@ -255,8 +342,12 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err, ret;
  
--static int __driver_attach(struct device * dev, void * data)
-+static int __driver_attach(struct device *dev, void *data)
- {
--	struct device_driver * drv = data;
-+	struct device_driver *drv = data;
++	if (unlikely(op->keylen != AES_KEYSIZE_128))
++		return fallback_blk_enc(desc, dst, src, nbytes);
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
++	op->iv = walk.iv;
  
- 	/*
- 	 * Lock device and try to bind to it. We drop the error
-@@ -268,35 +270,35 @@ static int __driver_attach(struct device * dev, void * data)
- }
+ 	while((nbytes = walk.nbytes)) {
+ 		op->src = walk.src.virt.addr,
+@@ -265,8 +356,6 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
+ 		op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
+ 		op->dir = AES_DIR_ENCRYPT;
  
- /**
-- *	driver_attach - try to bind driver to devices.
-- *	@drv:	driver.
-+ * driver_attach - try to bind driver to devices.
-+ * @drv: driver.
-  *
-- *	Walk the list of devices that the bus has on it and try to
-- *	match the driver with each one.  If driver_probe_device()
-- *	returns 0 and the @dev->driver is set, we've found a
-- *	compatible pair.
-+ * Walk the list of devices that the bus has on it and try to
-+ * match the driver with each one.  If driver_probe_device()
-+ * returns 0 and the @dev->driver is set, we've found a
-+ * compatible pair.
-  */
--int driver_attach(struct device_driver * drv)
-+int driver_attach(struct device_driver *drv)
- {
- 	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+-		memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+-
+ 		ret = geode_aes_crypt(op);
+ 		nbytes -= ret;
+ 		err = blkcipher_walk_done(desc, &walk, nbytes);
+@@ -275,22 +364,49 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
+ 	return err;
  }
-+EXPORT_SYMBOL_GPL(driver_attach);
  
- /*
-- *	__device_release_driver() must be called with @dev->sem held.
-- *	When called for a USB interface, @dev->parent->sem must be held as well.
-+ * __device_release_driver() must be called with @dev->sem held.
-+ * When called for a USB interface, @dev->parent->sem must be held as well.
-  */
--static void __device_release_driver(struct device * dev)
-+static void __device_release_driver(struct device *dev)
- {
--	struct device_driver * drv;
-+	struct device_driver *drv;
++static int fallback_init_blk(struct crypto_tfm *tfm)
++{
++	const char *name = tfm->__crt_alg->cra_name;
++	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++
++	op->fallback.blk = crypto_alloc_blkcipher(name, 0,
++			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
++
++	if (IS_ERR(op->fallback.blk)) {
++		printk(KERN_ERR "Error allocating fallback algo %s\n", name);
++		return PTR_ERR(op->fallback.blk);
++	}
++
++	return 0;
++}
++
++static void fallback_exit_blk(struct crypto_tfm *tfm)
++{
++	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++
++	crypto_free_blkcipher(op->fallback.blk);
++	op->fallback.blk = NULL;
++}
++
+ static struct crypto_alg geode_cbc_alg = {
+ 	.cra_name		=	"cbc(aes)",
+-	.cra_driver_name	=	"cbc-aes-geode-128",
++	.cra_driver_name	=	"cbc-aes-geode",
+ 	.cra_priority		=	400,
+-	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
++	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
++							CRYPTO_ALG_NEED_FALLBACK,
++	.cra_init			=	fallback_init_blk,
++	.cra_exit			=	fallback_exit_blk,
+ 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
+ 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
+ 	.cra_alignmask		=	15,
+-	.cra_type		=	&crypto_blkcipher_type,
+-	.cra_module		=	THIS_MODULE,
+-	.cra_list		=	LIST_HEAD_INIT(geode_cbc_alg.cra_list),
+-	.cra_u			=	{
+-		.blkcipher = {
+-			.min_keysize		=	AES_KEY_LENGTH,
+-			.max_keysize		=	AES_KEY_LENGTH,
+-			.setkey			=	geode_setkey,
++	.cra_type			=	&crypto_blkcipher_type,
++	.cra_module			=	THIS_MODULE,
++	.cra_list			=	LIST_HEAD_INIT(geode_cbc_alg.cra_list),
++	.cra_u				=	{
++		.blkcipher	=	{
++			.min_keysize	=	AES_MIN_KEY_SIZE,
++			.max_keysize	=	AES_MAX_KEY_SIZE,
++			.setkey			=	geode_setkey_blk,
+ 			.encrypt		=	geode_cbc_encrypt,
+ 			.decrypt		=	geode_cbc_decrypt,
+ 			.ivsize			=	AES_IV_LENGTH,
+@@ -307,6 +423,9 @@ geode_ecb_decrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err, ret;
  
--	drv = get_driver(dev->driver);
-+	drv = dev->driver;
- 	if (drv) {
- 		driver_sysfs_remove(dev);
- 		sysfs_remove_link(&dev->kobj, "driver");
--		klist_remove(&dev->knode_driver);
++	if (unlikely(op->keylen != AES_KEYSIZE_128))
++		return fallback_blk_dec(desc, dst, src, nbytes);
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
  
- 		if (dev->bus)
--			blocking_notifier_call_chain(&dev->bus->bus_notifier,
-+			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
- 						     BUS_NOTIFY_UNBIND_DRIVER,
- 						     dev);
+@@ -334,6 +453,9 @@ geode_ecb_encrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err, ret;
  
-@@ -306,18 +308,18 @@ static void __device_release_driver(struct device * dev)
- 			drv->remove(dev);
- 		devres_release_all(dev);
- 		dev->driver = NULL;
--		put_driver(drv);
-+		klist_remove(&dev->knode_driver);
- 	}
- }
++	if (unlikely(op->keylen != AES_KEYSIZE_128))
++		return fallback_blk_enc(desc, dst, src, nbytes);
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
  
- /**
-- *	device_release_driver - manually detach device from driver.
-- *	@dev:	device.
-+ * device_release_driver - manually detach device from driver.
-+ * @dev: device.
-  *
-- *	Manually detach device from driver.
-- *	When called for a USB interface, @dev->parent->sem must be held.
-+ * Manually detach device from driver.
-+ * When called for a USB interface, @dev->parent->sem must be held.
-  */
--void device_release_driver(struct device * dev)
-+void device_release_driver(struct device *dev)
- {
- 	/*
- 	 * If anyone calls device_release_driver() recursively from
-@@ -328,26 +330,26 @@ void device_release_driver(struct device * dev)
- 	__device_release_driver(dev);
- 	up(&dev->sem);
+@@ -353,28 +475,31 @@ geode_ecb_encrypt(struct blkcipher_desc *desc,
  }
--
-+EXPORT_SYMBOL_GPL(device_release_driver);
- 
- /**
-  * driver_detach - detach driver from all devices it controls.
-  * @drv: driver.
-  */
--void driver_detach(struct device_driver * drv)
-+void driver_detach(struct device_driver *drv)
- {
--	struct device * dev;
-+	struct device *dev;
  
- 	for (;;) {
--		spin_lock(&drv->klist_devices.k_lock);
--		if (list_empty(&drv->klist_devices.k_list)) {
--			spin_unlock(&drv->klist_devices.k_lock);
-+		spin_lock(&drv->p->klist_devices.k_lock);
-+		if (list_empty(&drv->p->klist_devices.k_list)) {
-+			spin_unlock(&drv->p->klist_devices.k_lock);
- 			break;
+ static struct crypto_alg geode_ecb_alg = {
+-	.cra_name		=	"ecb(aes)",
+-	.cra_driver_name	=	"ecb-aes-geode-128",
++	.cra_name			=	"ecb(aes)",
++	.cra_driver_name	=	"ecb-aes-geode",
+ 	.cra_priority		=	400,
+-	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
++	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
++							CRYPTO_ALG_NEED_FALLBACK,
++	.cra_init			=	fallback_init_blk,
++	.cra_exit			=	fallback_exit_blk,
+ 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
+ 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
+ 	.cra_alignmask		=	15,
+-	.cra_type		=	&crypto_blkcipher_type,
+-	.cra_module		=	THIS_MODULE,
+-	.cra_list		=	LIST_HEAD_INIT(geode_ecb_alg.cra_list),
+-	.cra_u			=	{
+-		.blkcipher = {
+-			.min_keysize		=	AES_KEY_LENGTH,
+-			.max_keysize		=	AES_KEY_LENGTH,
+-			.setkey			=	geode_setkey,
++	.cra_type			=	&crypto_blkcipher_type,
++	.cra_module			=	THIS_MODULE,
++	.cra_list			=	LIST_HEAD_INIT(geode_ecb_alg.cra_list),
++	.cra_u				=	{
++		.blkcipher	=	{
++			.min_keysize	=	AES_MIN_KEY_SIZE,
++			.max_keysize	=	AES_MAX_KEY_SIZE,
++			.setkey			=	geode_setkey_blk,
+ 			.encrypt		=	geode_ecb_encrypt,
+ 			.decrypt		=	geode_ecb_decrypt,
  		}
--		dev = list_entry(drv->klist_devices.k_list.prev,
-+		dev = list_entry(drv->p->klist_devices.k_list.prev,
- 				struct device, knode_driver.n_node);
- 		get_device(dev);
--		spin_unlock(&drv->klist_devices.k_lock);
-+		spin_unlock(&drv->p->klist_devices.k_lock);
- 
- 		if (dev->parent)	/* Needed for USB */
- 			down(&dev->parent->sem);
-@@ -360,9 +362,3 @@ void driver_detach(struct device_driver * drv)
- 		put_device(dev);
  	}
- }
--
--EXPORT_SYMBOL_GPL(device_bind_driver);
--EXPORT_SYMBOL_GPL(device_release_driver);
--EXPORT_SYMBOL_GPL(device_attach);
--EXPORT_SYMBOL_GPL(driver_attach);
--
-diff --git a/drivers/base/driver.c b/drivers/base/driver.c
-index eb11475..a35f041 100644
---- a/drivers/base/driver.c
-+++ b/drivers/base/driver.c
-@@ -3,6 +3,8 @@
-  *
-  * Copyright (c) 2002-3 Patrick Mochel
-  * Copyright (c) 2002-3 Open Source Development Labs
-+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
-+ * Copyright (c) 2007 Novell Inc.
-  *
-  * This file is released under the GPLv2
-  *
-@@ -15,46 +17,42 @@
- #include "base.h"
- 
- #define to_dev(node) container_of(node, struct device, driver_list)
--#define to_drv(obj) container_of(obj, struct device_driver, kobj)
- 
+ };
  
--static struct device * next_device(struct klist_iter * i)
-+static struct device *next_device(struct klist_iter *i)
+-static void
++static void __devexit
+ geode_aes_remove(struct pci_dev *dev)
  {
--	struct klist_node * n = klist_next(i);
-+	struct klist_node *n = klist_next(i);
- 	return n ? container_of(n, struct device, knode_driver) : NULL;
+ 	crypto_unregister_alg(&geode_alg);
+@@ -389,7 +514,7 @@ geode_aes_remove(struct pci_dev *dev)
  }
  
- /**
-- *	driver_for_each_device - Iterator for devices bound to a driver.
-- *	@drv:	Driver we're iterating.
-- *	@start: Device to begin with
-- *	@data:	Data to pass to the callback.
-- *	@fn:	Function to call for each device.
-+ * driver_for_each_device - Iterator for devices bound to a driver.
-+ * @drv: Driver we're iterating.
-+ * @start: Device to begin with
-+ * @data: Data to pass to the callback.
-+ * @fn: Function to call for each device.
-  *
-- *	Iterate over the @drv's list of devices calling @fn for each one.
-+ * Iterate over the @drv's list of devices calling @fn for each one.
-  */
--
--int driver_for_each_device(struct device_driver * drv, struct device * start, 
--			   void * data, int (*fn)(struct device *, void *))
-+int driver_for_each_device(struct device_driver *drv, struct device *start,
-+			   void *data, int (*fn)(struct device *, void *))
+ 
+-static int
++static int __devinit
+ geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
  {
- 	struct klist_iter i;
--	struct device * dev;
-+	struct device *dev;
- 	int error = 0;
+ 	int ret;
+@@ -397,7 +522,7 @@ geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ 	if ((ret = pci_enable_device(dev)))
+ 		return ret;
  
- 	if (!drv)
- 		return -EINVAL;
+-	if ((ret = pci_request_regions(dev, "geode-aes-128")))
++	if ((ret = pci_request_regions(dev, "geode-aes")))
+ 		goto eenable;
  
--	klist_iter_init_node(&drv->klist_devices, &i,
-+	klist_iter_init_node(&drv->p->klist_devices, &i,
- 			     start ? &start->knode_driver : NULL);
- 	while ((dev = next_device(&i)) && !error)
- 		error = fn(dev, data);
- 	klist_iter_exit(&i);
- 	return error;
- }
--
- EXPORT_SYMBOL_GPL(driver_for_each_device);
+ 	_iobase = pci_iomap(dev, 0, 0);
+@@ -472,7 +597,6 @@ geode_aes_exit(void)
+ MODULE_AUTHOR("Advanced Micro Devices, Inc.");
+ MODULE_DESCRIPTION("Geode LX Hardware AES driver");
+ MODULE_LICENSE("GPL");
+-MODULE_ALIAS("aes");
+ 
+ module_init(geode_aes_init);
+ module_exit(geode_aes_exit);
+diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h
+index f479686..f1855b5 100644
+--- a/drivers/crypto/geode-aes.h
++++ b/drivers/crypto/geode-aes.h
+@@ -9,9 +9,9 @@
+ #ifndef _GEODE_AES_H_
+ #define _GEODE_AES_H_
  
+-#define AES_KEY_LENGTH 16
++/* driver logic flags */
+ #define AES_IV_LENGTH  16
 -
- /**
-  * driver_find_device - device iterator for locating a particular device.
-  * @drv: The device's driver
-@@ -70,9 +68,9 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
-  * if it does.  If the callback returns non-zero, this function will
-  * return to the caller and not iterate over any more devices.
-  */
--struct device * driver_find_device(struct device_driver *drv,
--				   struct device * start, void * data,
--				   int (*match)(struct device *, void *))
-+struct device *driver_find_device(struct device_driver *drv,
-+				  struct device *start, void *data,
-+				  int (*match)(struct device *dev, void *data))
- {
- 	struct klist_iter i;
- 	struct device *dev;
-@@ -80,7 +78,7 @@ struct device * driver_find_device(struct device_driver *drv,
- 	if (!drv)
- 		return NULL;
++#define AES_KEY_LENGTH 16
+ #define AES_MIN_BLOCK_SIZE 16
  
--	klist_iter_init_node(&drv->klist_devices, &i,
-+	klist_iter_init_node(&drv->p->klist_devices, &i,
- 			     (start ? &start->knode_driver : NULL));
- 	while ((dev = next_device(&i)))
- 		if (match(dev, data) && get_device(dev))
-@@ -91,111 +89,179 @@ struct device * driver_find_device(struct device_driver *drv,
- EXPORT_SYMBOL_GPL(driver_find_device);
+ #define AES_MODE_ECB 0
+@@ -22,6 +22,38 @@
  
- /**
-- *	driver_create_file - create sysfs file for driver.
-- *	@drv:	driver.
-- *	@attr:	driver attribute descriptor.
-+ * driver_create_file - create sysfs file for driver.
-+ * @drv: driver.
-+ * @attr: driver attribute descriptor.
-  */
--
--int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
-+int driver_create_file(struct device_driver *drv,
-+		       struct driver_attribute *attr)
- {
- 	int error;
- 	if (get_driver(drv)) {
--		error = sysfs_create_file(&drv->kobj, &attr->attr);
-+		error = sysfs_create_file(&drv->p->kobj, &attr->attr);
- 		put_driver(drv);
- 	} else
- 		error = -EINVAL;
- 	return error;
- }
--
-+EXPORT_SYMBOL_GPL(driver_create_file);
+ #define AES_FLAGS_HIDDENKEY (1 << 0)
  
- /**
-- *	driver_remove_file - remove sysfs file for driver.
-- *	@drv:	driver.
-- *	@attr:	driver attribute descriptor.
-+ * driver_remove_file - remove sysfs file for driver.
-+ * @drv: driver.
-+ * @attr: driver attribute descriptor.
-  */
--
--void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
-+void driver_remove_file(struct device_driver *drv,
-+			struct driver_attribute *attr)
- {
- 	if (get_driver(drv)) {
--		sysfs_remove_file(&drv->kobj, &attr->attr);
-+		sysfs_remove_file(&drv->p->kobj, &attr->attr);
- 		put_driver(drv);
- 	}
- }
--
-+EXPORT_SYMBOL_GPL(driver_remove_file);
++/* Register definitions */
++
++#define AES_CTRLA_REG  0x0000
++
++#define AES_CTRL_START     0x01
++#define AES_CTRL_DECRYPT   0x00
++#define AES_CTRL_ENCRYPT   0x02
++#define AES_CTRL_WRKEY     0x04
++#define AES_CTRL_DCA       0x08
++#define AES_CTRL_SCA       0x10
++#define AES_CTRL_CBC       0x20
++
++#define AES_INTR_REG  0x0008
++
++#define AES_INTRA_PENDING (1 << 16)
++#define AES_INTRB_PENDING (1 << 17)
++
++#define AES_INTR_PENDING  (AES_INTRA_PENDING | AES_INTRB_PENDING)
++#define AES_INTR_MASK     0x07
++
++#define AES_SOURCEA_REG   0x0010
++#define AES_DSTA_REG      0x0014
++#define AES_LENA_REG      0x0018
++#define AES_WRITEKEY0_REG 0x0030
++#define AES_WRITEIV0_REG  0x0040
++
++/*  A very large counter that is used to gracefully bail out of an
++ *  operation in case of trouble
++ */
++
++#define AES_OP_TIMEOUT    0x50000
++
+ struct geode_aes_op {
  
- /**
-- *	get_driver - increment driver reference count.
-- *	@drv:	driver.
-+ * driver_add_kobj - add a kobject below the specified driver
+ 	void *src;
+@@ -33,7 +65,13 @@ struct geode_aes_op {
+ 	int len;
+ 
+ 	u8 key[AES_KEY_LENGTH];
+-	u8 iv[AES_IV_LENGTH];
++	u8 *iv;
++
++	union {
++		struct crypto_blkcipher *blk;
++		struct crypto_cipher *cip;
++	} fallback;
++	u32 keylen;
+ };
+ 
+ #endif
+diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
+new file mode 100644
+index 0000000..dfbf24c
+--- /dev/null
++++ b/drivers/crypto/hifn_795x.c
+@@ -0,0 +1,2838 @@
++/*
++ * 2007+ Copyright (c) Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
++ * All rights reserved.
 + *
-+ * You really don't want to do this, this is only here due to one looney
-+ * iseries driver, go poke those developers if you are annoyed about
-+ * this...
-  */
--struct device_driver * get_driver(struct device_driver * drv)
-+int driver_add_kobj(struct device_driver *drv, struct kobject *kobj,
-+		    const char *fmt, ...)
- {
--	return drv ? to_drv(kobject_get(&drv->kobj)) : NULL;
-+	va_list args;
-+	char *name;
++ * 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 <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/mod_devicetable.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/delay.h>
++#include <linux/mm.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/highmem.h>
++#include <linux/interrupt.h>
++#include <linux/crypto.h>
++#include <linux/hw_random.h>
++#include <linux/ktime.h>
++
++#include <crypto/algapi.h>
++#include <crypto/des.h>
++
++#include <asm/kmap_types.h>
++
++#undef dprintk
++
++#define HIFN_TEST
++//#define HIFN_DEBUG
++
++#ifdef HIFN_DEBUG
++#define dprintk(f, a...) 	printk(f, ##a)
++#else
++#define dprintk(f, a...)	do {} while (0)
++#endif
++
++static char hifn_pll_ref[sizeof("extNNN")] = "ext";
++module_param_string(hifn_pll_ref, hifn_pll_ref, sizeof(hifn_pll_ref), 0444);
++MODULE_PARM_DESC(hifn_pll_ref,
++		 "PLL reference clock (pci[freq] or ext[freq], default ext)");
++
++static atomic_t hifn_dev_number;
++
++#define ACRYPTO_OP_DECRYPT	0
++#define ACRYPTO_OP_ENCRYPT	1
++#define ACRYPTO_OP_HMAC		2
++#define ACRYPTO_OP_RNG		3
++
++#define ACRYPTO_MODE_ECB		0
++#define ACRYPTO_MODE_CBC		1
++#define ACRYPTO_MODE_CFB		2
++#define ACRYPTO_MODE_OFB		3
++
++#define ACRYPTO_TYPE_AES_128	0
++#define ACRYPTO_TYPE_AES_192	1
++#define ACRYPTO_TYPE_AES_256	2
++#define ACRYPTO_TYPE_3DES	3
++#define ACRYPTO_TYPE_DES	4
++
++#define PCI_VENDOR_ID_HIFN		0x13A3
++#define PCI_DEVICE_ID_HIFN_7955		0x0020
++#define	PCI_DEVICE_ID_HIFN_7956		0x001d
++
++/* I/O region sizes */
++
++#define HIFN_BAR0_SIZE			0x1000
++#define HIFN_BAR1_SIZE			0x2000
++#define HIFN_BAR2_SIZE			0x8000
++
++/* DMA registres */
++
++#define HIFN_DMA_CRA 			0x0C	/* DMA Command Ring Address */
++#define HIFN_DMA_SDRA 			0x1C	/* DMA Source Data Ring Address */
++#define HIFN_DMA_RRA			0x2C	/* DMA Result Ring Address */
++#define HIFN_DMA_DDRA			0x3C	/* DMA Destination Data Ring Address */
++#define HIFN_DMA_STCTL			0x40	/* DMA Status and Control */
++#define HIFN_DMA_INTREN 		0x44	/* DMA Interrupt Enable */
++#define HIFN_DMA_CFG1			0x48	/* DMA Configuration #1 */
++#define HIFN_DMA_CFG2			0x6C	/* DMA Configuration #2 */
++#define HIFN_CHIP_ID			0x98	/* Chip ID */
++
++/*
++ * Processing Unit Registers (offset from BASEREG0)
++ */
++#define	HIFN_0_PUDATA		0x00	/* Processing Unit Data */
++#define	HIFN_0_PUCTRL		0x04	/* Processing Unit Control */
++#define	HIFN_0_PUISR		0x08	/* Processing Unit Interrupt Status */
++#define	HIFN_0_PUCNFG		0x0c	/* Processing Unit Configuration */
++#define	HIFN_0_PUIER		0x10	/* Processing Unit Interrupt Enable */
++#define	HIFN_0_PUSTAT		0x14	/* Processing Unit Status/Chip ID */
++#define	HIFN_0_FIFOSTAT		0x18	/* FIFO Status */
++#define	HIFN_0_FIFOCNFG		0x1c	/* FIFO Configuration */
++#define	HIFN_0_SPACESIZE	0x20	/* Register space size */
++
++/* Processing Unit Control Register (HIFN_0_PUCTRL) */
++#define	HIFN_PUCTRL_CLRSRCFIFO	0x0010	/* clear source fifo */
++#define	HIFN_PUCTRL_STOP	0x0008	/* stop pu */
++#define	HIFN_PUCTRL_LOCKRAM	0x0004	/* lock ram */
++#define	HIFN_PUCTRL_DMAENA	0x0002	/* enable dma */
++#define	HIFN_PUCTRL_RESET	0x0001	/* Reset processing unit */
++
++/* Processing Unit Interrupt Status Register (HIFN_0_PUISR) */
++#define	HIFN_PUISR_CMDINVAL	0x8000	/* Invalid command interrupt */
++#define	HIFN_PUISR_DATAERR	0x4000	/* Data error interrupt */
++#define	HIFN_PUISR_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
++#define	HIFN_PUISR_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
++#define	HIFN_PUISR_DSTOVER	0x0200	/* Destination overrun interrupt */
++#define	HIFN_PUISR_SRCCMD	0x0080	/* Source command interrupt */
++#define	HIFN_PUISR_SRCCTX	0x0040	/* Source context interrupt */
++#define	HIFN_PUISR_SRCDATA	0x0020	/* Source data interrupt */
++#define	HIFN_PUISR_DSTDATA	0x0010	/* Destination data interrupt */
++#define	HIFN_PUISR_DSTRESULT	0x0004	/* Destination result interrupt */
++
++/* Processing Unit Configuration Register (HIFN_0_PUCNFG) */
++#define	HIFN_PUCNFG_DRAMMASK	0xe000	/* DRAM size mask */
++#define	HIFN_PUCNFG_DSZ_256K	0x0000	/* 256k dram */
++#define	HIFN_PUCNFG_DSZ_512K	0x2000	/* 512k dram */
++#define	HIFN_PUCNFG_DSZ_1M	0x4000	/* 1m dram */
++#define	HIFN_PUCNFG_DSZ_2M	0x6000	/* 2m dram */
++#define	HIFN_PUCNFG_DSZ_4M	0x8000	/* 4m dram */
++#define	HIFN_PUCNFG_DSZ_8M	0xa000	/* 8m dram */
++#define	HIFN_PUNCFG_DSZ_16M	0xc000	/* 16m dram */
++#define	HIFN_PUCNFG_DSZ_32M	0xe000	/* 32m dram */
++#define	HIFN_PUCNFG_DRAMREFRESH	0x1800	/* DRAM refresh rate mask */
++#define	HIFN_PUCNFG_DRFR_512	0x0000	/* 512 divisor of ECLK */
++#define	HIFN_PUCNFG_DRFR_256	0x0800	/* 256 divisor of ECLK */
++#define	HIFN_PUCNFG_DRFR_128	0x1000	/* 128 divisor of ECLK */
++#define	HIFN_PUCNFG_TCALLPHASES	0x0200	/* your guess is as good as mine... */
++#define	HIFN_PUCNFG_TCDRVTOTEM	0x0100	/* your guess is as good as mine... */
++#define	HIFN_PUCNFG_BIGENDIAN	0x0080	/* DMA big endian mode */
++#define	HIFN_PUCNFG_BUS32	0x0040	/* Bus width 32bits */
++#define	HIFN_PUCNFG_BUS16	0x0000	/* Bus width 16 bits */
++#define	HIFN_PUCNFG_CHIPID	0x0020	/* Allow chipid from PUSTAT */
++#define	HIFN_PUCNFG_DRAM	0x0010	/* Context RAM is DRAM */
++#define	HIFN_PUCNFG_SRAM	0x0000	/* Context RAM is SRAM */
++#define	HIFN_PUCNFG_COMPSING	0x0004	/* Enable single compression context */
++#define	HIFN_PUCNFG_ENCCNFG	0x0002	/* Encryption configuration */
++
++/* Processing Unit Interrupt Enable Register (HIFN_0_PUIER) */
++#define	HIFN_PUIER_CMDINVAL	0x8000	/* Invalid command interrupt */
++#define	HIFN_PUIER_DATAERR	0x4000	/* Data error interrupt */
++#define	HIFN_PUIER_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
++#define	HIFN_PUIER_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
++#define	HIFN_PUIER_DSTOVER	0x0200	/* Destination overrun interrupt */
++#define	HIFN_PUIER_SRCCMD	0x0080	/* Source command interrupt */
++#define	HIFN_PUIER_SRCCTX	0x0040	/* Source context interrupt */
++#define	HIFN_PUIER_SRCDATA	0x0020	/* Source data interrupt */
++#define	HIFN_PUIER_DSTDATA	0x0010	/* Destination data interrupt */
++#define	HIFN_PUIER_DSTRESULT	0x0004	/* Destination result interrupt */
++
++/* Processing Unit Status Register/Chip ID (HIFN_0_PUSTAT) */
++#define	HIFN_PUSTAT_CMDINVAL	0x8000	/* Invalid command interrupt */
++#define	HIFN_PUSTAT_DATAERR	0x4000	/* Data error interrupt */
++#define	HIFN_PUSTAT_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
++#define	HIFN_PUSTAT_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
++#define	HIFN_PUSTAT_DSTOVER	0x0200	/* Destination overrun interrupt */
++#define	HIFN_PUSTAT_SRCCMD	0x0080	/* Source command interrupt */
++#define	HIFN_PUSTAT_SRCCTX	0x0040	/* Source context interrupt */
++#define	HIFN_PUSTAT_SRCDATA	0x0020	/* Source data interrupt */
++#define	HIFN_PUSTAT_DSTDATA	0x0010	/* Destination data interrupt */
++#define	HIFN_PUSTAT_DSTRESULT	0x0004	/* Destination result interrupt */
++#define	HIFN_PUSTAT_CHIPREV	0x00ff	/* Chip revision mask */
++#define	HIFN_PUSTAT_CHIPENA	0xff00	/* Chip enabled mask */
++#define	HIFN_PUSTAT_ENA_2	0x1100	/* Level 2 enabled */
++#define	HIFN_PUSTAT_ENA_1	0x1000	/* Level 1 enabled */
++#define	HIFN_PUSTAT_ENA_0	0x3000	/* Level 0 enabled */
++#define	HIFN_PUSTAT_REV_2	0x0020	/* 7751 PT6/2 */
++#define	HIFN_PUSTAT_REV_3	0x0030	/* 7751 PT6/3 */
++
++/* FIFO Status Register (HIFN_0_FIFOSTAT) */
++#define	HIFN_FIFOSTAT_SRC	0x7f00	/* Source FIFO available */
++#define	HIFN_FIFOSTAT_DST	0x007f	/* Destination FIFO available */
++
++/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
++#define	HIFN_FIFOCNFG_THRESHOLD	0x0400	/* must be written as 1 */
++
++/*
++ * DMA Interface Registers (offset from BASEREG1)
++ */
++#define	HIFN_1_DMA_CRAR		0x0c	/* DMA Command Ring Address */
++#define	HIFN_1_DMA_SRAR		0x1c	/* DMA Source Ring Address */
++#define	HIFN_1_DMA_RRAR		0x2c	/* DMA Result Ring Address */
++#define	HIFN_1_DMA_DRAR		0x3c	/* DMA Destination Ring Address */
++#define	HIFN_1_DMA_CSR		0x40	/* DMA Status and Control */
++#define	HIFN_1_DMA_IER		0x44	/* DMA Interrupt Enable */
++#define	HIFN_1_DMA_CNFG		0x48	/* DMA Configuration */
++#define	HIFN_1_PLL		0x4c	/* 795x: PLL config */
++#define	HIFN_1_7811_RNGENA	0x60	/* 7811: rng enable */
++#define	HIFN_1_7811_RNGCFG	0x64	/* 7811: rng config */
++#define	HIFN_1_7811_RNGDAT	0x68	/* 7811: rng data */
++#define	HIFN_1_7811_RNGSTS	0x6c	/* 7811: rng status */
++#define	HIFN_1_7811_MIPSRST	0x94	/* 7811: MIPS reset */
++#define	HIFN_1_REVID		0x98	/* Revision ID */
++#define	HIFN_1_UNLOCK_SECRET1	0xf4
++#define	HIFN_1_UNLOCK_SECRET2	0xfc
++#define	HIFN_1_PUB_RESET	0x204	/* Public/RNG Reset */
++#define	HIFN_1_PUB_BASE		0x300	/* Public Base Address */
++#define	HIFN_1_PUB_OPLEN	0x304	/* Public Operand Length */
++#define	HIFN_1_PUB_OP		0x308	/* Public Operand */
++#define	HIFN_1_PUB_STATUS	0x30c	/* Public Status */
++#define	HIFN_1_PUB_IEN		0x310	/* Public Interrupt enable */
++#define	HIFN_1_RNG_CONFIG	0x314	/* RNG config */
++#define	HIFN_1_RNG_DATA		0x318	/* RNG data */
++#define	HIFN_1_PUB_MEM		0x400	/* start of Public key memory */
++#define	HIFN_1_PUB_MEMEND	0xbff	/* end of Public key memory */
++
++/* DMA Status and Control Register (HIFN_1_DMA_CSR) */
++#define	HIFN_DMACSR_D_CTRLMASK	0xc0000000	/* Destinition Ring Control */
++#define	HIFN_DMACSR_D_CTRL_NOP	0x00000000	/* Dest. Control: no-op */
++#define	HIFN_DMACSR_D_CTRL_DIS	0x40000000	/* Dest. Control: disable */
++#define	HIFN_DMACSR_D_CTRL_ENA	0x80000000	/* Dest. Control: enable */
++#define	HIFN_DMACSR_D_ABORT	0x20000000	/* Destinition Ring PCIAbort */
++#define	HIFN_DMACSR_D_DONE	0x10000000	/* Destinition Ring Done */
++#define	HIFN_DMACSR_D_LAST	0x08000000	/* Destinition Ring Last */
++#define	HIFN_DMACSR_D_WAIT	0x04000000	/* Destinition Ring Waiting */
++#define	HIFN_DMACSR_D_OVER	0x02000000	/* Destinition Ring Overflow */
++#define	HIFN_DMACSR_R_CTRL	0x00c00000	/* Result Ring Control */
++#define	HIFN_DMACSR_R_CTRL_NOP	0x00000000	/* Result Control: no-op */
++#define	HIFN_DMACSR_R_CTRL_DIS	0x00400000	/* Result Control: disable */
++#define	HIFN_DMACSR_R_CTRL_ENA	0x00800000	/* Result Control: enable */
++#define	HIFN_DMACSR_R_ABORT	0x00200000	/* Result Ring PCI Abort */
++#define	HIFN_DMACSR_R_DONE	0x00100000	/* Result Ring Done */
++#define	HIFN_DMACSR_R_LAST	0x00080000	/* Result Ring Last */
++#define	HIFN_DMACSR_R_WAIT	0x00040000	/* Result Ring Waiting */
++#define	HIFN_DMACSR_R_OVER	0x00020000	/* Result Ring Overflow */
++#define	HIFN_DMACSR_S_CTRL	0x0000c000	/* Source Ring Control */
++#define	HIFN_DMACSR_S_CTRL_NOP	0x00000000	/* Source Control: no-op */
++#define	HIFN_DMACSR_S_CTRL_DIS	0x00004000	/* Source Control: disable */
++#define	HIFN_DMACSR_S_CTRL_ENA	0x00008000	/* Source Control: enable */
++#define	HIFN_DMACSR_S_ABORT	0x00002000	/* Source Ring PCI Abort */
++#define	HIFN_DMACSR_S_DONE	0x00001000	/* Source Ring Done */
++#define	HIFN_DMACSR_S_LAST	0x00000800	/* Source Ring Last */
++#define	HIFN_DMACSR_S_WAIT	0x00000400	/* Source Ring Waiting */
++#define	HIFN_DMACSR_ILLW	0x00000200	/* Illegal write (7811 only) */
++#define	HIFN_DMACSR_ILLR	0x00000100	/* Illegal read (7811 only) */
++#define	HIFN_DMACSR_C_CTRL	0x000000c0	/* Command Ring Control */
++#define	HIFN_DMACSR_C_CTRL_NOP	0x00000000	/* Command Control: no-op */
++#define	HIFN_DMACSR_C_CTRL_DIS	0x00000040	/* Command Control: disable */
++#define	HIFN_DMACSR_C_CTRL_ENA	0x00000080	/* Command Control: enable */
++#define	HIFN_DMACSR_C_ABORT	0x00000020	/* Command Ring PCI Abort */
++#define	HIFN_DMACSR_C_DONE	0x00000010	/* Command Ring Done */
++#define	HIFN_DMACSR_C_LAST	0x00000008	/* Command Ring Last */
++#define	HIFN_DMACSR_C_WAIT	0x00000004	/* Command Ring Waiting */
++#define	HIFN_DMACSR_PUBDONE	0x00000002	/* Public op done (7951 only) */
++#define	HIFN_DMACSR_ENGINE	0x00000001	/* Command Ring Engine IRQ */
++
++/* DMA Interrupt Enable Register (HIFN_1_DMA_IER) */
++#define	HIFN_DMAIER_D_ABORT	0x20000000	/* Destination Ring PCIAbort */
++#define	HIFN_DMAIER_D_DONE	0x10000000	/* Destination Ring Done */
++#define	HIFN_DMAIER_D_LAST	0x08000000	/* Destination Ring Last */
++#define	HIFN_DMAIER_D_WAIT	0x04000000	/* Destination Ring Waiting */
++#define	HIFN_DMAIER_D_OVER	0x02000000	/* Destination Ring Overflow */
++#define	HIFN_DMAIER_R_ABORT	0x00200000	/* Result Ring PCI Abort */
++#define	HIFN_DMAIER_R_DONE	0x00100000	/* Result Ring Done */
++#define	HIFN_DMAIER_R_LAST	0x00080000	/* Result Ring Last */
++#define	HIFN_DMAIER_R_WAIT	0x00040000	/* Result Ring Waiting */
++#define	HIFN_DMAIER_R_OVER	0x00020000	/* Result Ring Overflow */
++#define	HIFN_DMAIER_S_ABORT	0x00002000	/* Source Ring PCI Abort */
++#define	HIFN_DMAIER_S_DONE	0x00001000	/* Source Ring Done */
++#define	HIFN_DMAIER_S_LAST	0x00000800	/* Source Ring Last */
++#define	HIFN_DMAIER_S_WAIT	0x00000400	/* Source Ring Waiting */
++#define	HIFN_DMAIER_ILLW	0x00000200	/* Illegal write (7811 only) */
++#define	HIFN_DMAIER_ILLR	0x00000100	/* Illegal read (7811 only) */
++#define	HIFN_DMAIER_C_ABORT	0x00000020	/* Command Ring PCI Abort */
++#define	HIFN_DMAIER_C_DONE	0x00000010	/* Command Ring Done */
++#define	HIFN_DMAIER_C_LAST	0x00000008	/* Command Ring Last */
++#define	HIFN_DMAIER_C_WAIT	0x00000004	/* Command Ring Waiting */
++#define	HIFN_DMAIER_PUBDONE	0x00000002	/* public op done (7951 only) */
++#define	HIFN_DMAIER_ENGINE	0x00000001	/* Engine IRQ */
++
++/* DMA Configuration Register (HIFN_1_DMA_CNFG) */
++#define	HIFN_DMACNFG_BIGENDIAN	0x10000000	/* big endian mode */
++#define	HIFN_DMACNFG_POLLFREQ	0x00ff0000	/* Poll frequency mask */
++#define	HIFN_DMACNFG_UNLOCK	0x00000800
++#define	HIFN_DMACNFG_POLLINVAL	0x00000700	/* Invalid Poll Scalar */
++#define	HIFN_DMACNFG_LAST	0x00000010	/* Host control LAST bit */
++#define	HIFN_DMACNFG_MODE	0x00000004	/* DMA mode */
++#define	HIFN_DMACNFG_DMARESET	0x00000002	/* DMA Reset # */
++#define	HIFN_DMACNFG_MSTRESET	0x00000001	/* Master Reset # */
++
++/* PLL configuration register */
++#define HIFN_PLL_REF_CLK_HBI	0x00000000	/* HBI reference clock */
++#define HIFN_PLL_REF_CLK_PLL	0x00000001	/* PLL reference clock */
++#define HIFN_PLL_BP		0x00000002	/* Reference clock bypass */
++#define HIFN_PLL_PK_CLK_HBI	0x00000000	/* PK engine HBI clock */
++#define HIFN_PLL_PK_CLK_PLL	0x00000008	/* PK engine PLL clock */
++#define HIFN_PLL_PE_CLK_HBI	0x00000000	/* PE engine HBI clock */
++#define HIFN_PLL_PE_CLK_PLL	0x00000010	/* PE engine PLL clock */
++#define HIFN_PLL_RESERVED_1	0x00000400	/* Reserved bit, must be 1 */
++#define HIFN_PLL_ND_SHIFT	11		/* Clock multiplier shift */
++#define HIFN_PLL_ND_MULT_2	0x00000000	/* PLL clock multiplier 2 */
++#define HIFN_PLL_ND_MULT_4	0x00000800	/* PLL clock multiplier 4 */
++#define HIFN_PLL_ND_MULT_6	0x00001000	/* PLL clock multiplier 6 */
++#define HIFN_PLL_ND_MULT_8	0x00001800	/* PLL clock multiplier 8 */
++#define HIFN_PLL_ND_MULT_10	0x00002000	/* PLL clock multiplier 10 */
++#define HIFN_PLL_ND_MULT_12	0x00002800	/* PLL clock multiplier 12 */
++#define HIFN_PLL_IS_1_8		0x00000000	/* charge pump (mult. 1-8) */
++#define HIFN_PLL_IS_9_12	0x00010000	/* charge pump (mult. 9-12) */
++
++#define HIFN_PLL_FCK_MAX	266		/* Maximum PLL frequency */
++
++/* Public key reset register (HIFN_1_PUB_RESET) */
++#define	HIFN_PUBRST_RESET	0x00000001	/* reset public/rng unit */
++
++/* Public base address register (HIFN_1_PUB_BASE) */
++#define	HIFN_PUBBASE_ADDR	0x00003fff	/* base address */
++
++/* Public operand length register (HIFN_1_PUB_OPLEN) */
++#define	HIFN_PUBOPLEN_MOD_M	0x0000007f	/* modulus length mask */
++#define	HIFN_PUBOPLEN_MOD_S	0		/* modulus length shift */
++#define	HIFN_PUBOPLEN_EXP_M	0x0003ff80	/* exponent length mask */
++#define	HIFN_PUBOPLEN_EXP_S	7		/* exponent lenght shift */
++#define	HIFN_PUBOPLEN_RED_M	0x003c0000	/* reducend length mask */
++#define	HIFN_PUBOPLEN_RED_S	18		/* reducend length shift */
++
++/* Public operation register (HIFN_1_PUB_OP) */
++#define	HIFN_PUBOP_AOFFSET_M	0x0000007f	/* A offset mask */
++#define	HIFN_PUBOP_AOFFSET_S	0		/* A offset shift */
++#define	HIFN_PUBOP_BOFFSET_M	0x00000f80	/* B offset mask */
++#define	HIFN_PUBOP_BOFFSET_S	7		/* B offset shift */
++#define	HIFN_PUBOP_MOFFSET_M	0x0003f000	/* M offset mask */
++#define	HIFN_PUBOP_MOFFSET_S	12		/* M offset shift */
++#define	HIFN_PUBOP_OP_MASK	0x003c0000	/* Opcode: */
++#define	HIFN_PUBOP_OP_NOP	0x00000000	/*  NOP */
++#define	HIFN_PUBOP_OP_ADD	0x00040000	/*  ADD */
++#define	HIFN_PUBOP_OP_ADDC	0x00080000	/*  ADD w/carry */
++#define	HIFN_PUBOP_OP_SUB	0x000c0000	/*  SUB */
++#define	HIFN_PUBOP_OP_SUBC	0x00100000	/*  SUB w/carry */
++#define	HIFN_PUBOP_OP_MODADD	0x00140000	/*  Modular ADD */
++#define	HIFN_PUBOP_OP_MODSUB	0x00180000	/*  Modular SUB */
++#define	HIFN_PUBOP_OP_INCA	0x001c0000	/*  INC A */
++#define	HIFN_PUBOP_OP_DECA	0x00200000	/*  DEC A */
++#define	HIFN_PUBOP_OP_MULT	0x00240000	/*  MULT */
++#define	HIFN_PUBOP_OP_MODMULT	0x00280000	/*  Modular MULT */
++#define	HIFN_PUBOP_OP_MODRED	0x002c0000	/*  Modular RED */
++#define	HIFN_PUBOP_OP_MODEXP	0x00300000	/*  Modular EXP */
++
++/* Public status register (HIFN_1_PUB_STATUS) */
++#define	HIFN_PUBSTS_DONE	0x00000001	/* operation done */
++#define	HIFN_PUBSTS_CARRY	0x00000002	/* carry */
++
++/* Public interrupt enable register (HIFN_1_PUB_IEN) */
++#define	HIFN_PUBIEN_DONE	0x00000001	/* operation done interrupt */
++
++/* Random number generator config register (HIFN_1_RNG_CONFIG) */
++#define	HIFN_RNGCFG_ENA		0x00000001	/* enable rng */
++
++#define HIFN_NAMESIZE			32
++#define HIFN_MAX_RESULT_ORDER		5
++
++#define	HIFN_D_CMD_RSIZE		24*4
++#define	HIFN_D_SRC_RSIZE		80*4
++#define	HIFN_D_DST_RSIZE		80*4
++#define	HIFN_D_RES_RSIZE		24*4
++
++#define HIFN_QUEUE_LENGTH		HIFN_D_CMD_RSIZE-5
++
++#define AES_MIN_KEY_SIZE		16
++#define AES_MAX_KEY_SIZE		32
++
++#define HIFN_DES_KEY_LENGTH		8
++#define HIFN_3DES_KEY_LENGTH		24
++#define HIFN_MAX_CRYPT_KEY_LENGTH	AES_MAX_KEY_SIZE
++#define HIFN_IV_LENGTH			8
++#define HIFN_AES_IV_LENGTH		16
++#define	HIFN_MAX_IV_LENGTH		HIFN_AES_IV_LENGTH
++
++#define HIFN_MAC_KEY_LENGTH		64
++#define HIFN_MD5_LENGTH			16
++#define HIFN_SHA1_LENGTH		20
++#define HIFN_MAC_TRUNC_LENGTH		12
++
++#define	HIFN_MAX_COMMAND		(8 + 8 + 8 + 64 + 260)
++#define	HIFN_MAX_RESULT			(8 + 4 + 4 + 20 + 4)
++#define HIFN_USED_RESULT		12
++
++struct hifn_desc
++{
++	volatile u32		l;
++	volatile u32		p;
++};
++
++struct hifn_dma {
++	struct hifn_desc	cmdr[HIFN_D_CMD_RSIZE+1];
++	struct hifn_desc	srcr[HIFN_D_SRC_RSIZE+1];
++	struct hifn_desc	dstr[HIFN_D_DST_RSIZE+1];
++	struct hifn_desc	resr[HIFN_D_RES_RSIZE+1];
++
++	u8			command_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_COMMAND];
++	u8			result_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_RESULT];
++
++	u64			test_src, test_dst;
++
++	/*
++	 *  Our current positions for insertion and removal from the descriptor
++	 *  rings.
++	 */
++	volatile int		cmdi, srci, dsti, resi;
++	volatile int		cmdu, srcu, dstu, resu;
++	int			cmdk, srck, dstk, resk;
++};
++
++#define HIFN_FLAG_CMD_BUSY	(1<<0)
++#define HIFN_FLAG_SRC_BUSY	(1<<1)
++#define HIFN_FLAG_DST_BUSY	(1<<2)
++#define HIFN_FLAG_RES_BUSY	(1<<3)
++#define HIFN_FLAG_OLD_KEY	(1<<4)
++
++#define HIFN_DEFAULT_ACTIVE_NUM	5
++
++struct hifn_device
++{
++	char			name[HIFN_NAMESIZE];
++
++	int			irq;
++
++	struct pci_dev		*pdev;
++	void __iomem		*bar[3];
++
++	unsigned long		result_mem;
++	dma_addr_t		dst;
++
++	void			*desc_virt;
++	dma_addr_t		desc_dma;
++
++	u32			dmareg;
++
++	void 			*sa[HIFN_D_RES_RSIZE];
++
++	spinlock_t		lock;
++
++	void 			*priv;
++
++	u32			flags;
++	int			active, started;
++	struct delayed_work	work;
++	unsigned long		reset;
++	unsigned long		success;
++	unsigned long		prev_success;
++
++	u8			snum;
++
++	struct tasklet_struct	tasklet;
++
++	struct crypto_queue 	queue;
++	struct list_head	alg_list;
++
++	unsigned int		pk_clk_freq;
++
++#ifdef CRYPTO_DEV_HIFN_795X_RNG
++	unsigned int		rng_wait_time;
++	ktime_t			rngtime;
++	struct hwrng		rng;
++#endif
++};
++
++#define	HIFN_D_LENGTH			0x0000ffff
++#define	HIFN_D_NOINVALID		0x01000000
++#define	HIFN_D_MASKDONEIRQ		0x02000000
++#define	HIFN_D_DESTOVER			0x04000000
++#define	HIFN_D_OVER			0x08000000
++#define	HIFN_D_LAST			0x20000000
++#define	HIFN_D_JUMP			0x40000000
++#define	HIFN_D_VALID			0x80000000
++
++struct hifn_base_command
++{
++	volatile u16		masks;
++	volatile u16		session_num;
++	volatile u16		total_source_count;
++	volatile u16		total_dest_count;
++};
++
++#define	HIFN_BASE_CMD_COMP		0x0100	/* enable compression engine */
++#define	HIFN_BASE_CMD_PAD		0x0200	/* enable padding engine */
++#define	HIFN_BASE_CMD_MAC		0x0400	/* enable MAC engine */
++#define	HIFN_BASE_CMD_CRYPT		0x0800	/* enable crypt engine */
++#define	HIFN_BASE_CMD_DECODE		0x2000
++#define	HIFN_BASE_CMD_SRCLEN_M		0xc000
++#define	HIFN_BASE_CMD_SRCLEN_S		14
++#define	HIFN_BASE_CMD_DSTLEN_M		0x3000
++#define	HIFN_BASE_CMD_DSTLEN_S		12
++#define	HIFN_BASE_CMD_LENMASK_HI	0x30000
++#define	HIFN_BASE_CMD_LENMASK_LO	0x0ffff
++
++/*
++ * Structure to help build up the command data structure.
++ */
++struct hifn_crypt_command
++{
++	volatile u16 		masks;
++	volatile u16 		header_skip;
++	volatile u16 		source_count;
++	volatile u16 		reserved;
++};
++
++#define	HIFN_CRYPT_CMD_ALG_MASK		0x0003		/* algorithm: */
++#define	HIFN_CRYPT_CMD_ALG_DES		0x0000		/*   DES */
++#define	HIFN_CRYPT_CMD_ALG_3DES		0x0001		/*   3DES */
++#define	HIFN_CRYPT_CMD_ALG_RC4		0x0002		/*   RC4 */
++#define	HIFN_CRYPT_CMD_ALG_AES		0x0003		/*   AES */
++#define	HIFN_CRYPT_CMD_MODE_MASK	0x0018		/* Encrypt mode: */
++#define	HIFN_CRYPT_CMD_MODE_ECB		0x0000		/*   ECB */
++#define	HIFN_CRYPT_CMD_MODE_CBC		0x0008		/*   CBC */
++#define	HIFN_CRYPT_CMD_MODE_CFB		0x0010		/*   CFB */
++#define	HIFN_CRYPT_CMD_MODE_OFB		0x0018		/*   OFB */
++#define	HIFN_CRYPT_CMD_CLR_CTX		0x0040		/* clear context */
++#define	HIFN_CRYPT_CMD_KSZ_MASK		0x0600		/* AES key size: */
++#define	HIFN_CRYPT_CMD_KSZ_128		0x0000		/*  128 bit */
++#define	HIFN_CRYPT_CMD_KSZ_192		0x0200		/*  192 bit */
++#define	HIFN_CRYPT_CMD_KSZ_256		0x0400		/*  256 bit */
++#define	HIFN_CRYPT_CMD_NEW_KEY		0x0800		/* expect new key */
++#define	HIFN_CRYPT_CMD_NEW_IV		0x1000		/* expect new iv */
++#define	HIFN_CRYPT_CMD_SRCLEN_M		0xc000
++#define	HIFN_CRYPT_CMD_SRCLEN_S		14
++
++/*
++ * Structure to help build up the command data structure.
++ */
++struct hifn_mac_command
++{
++	volatile u16 		masks;
++	volatile u16 		header_skip;
++	volatile u16 		source_count;
++	volatile u16 		reserved;
++};
++
++#define	HIFN_MAC_CMD_ALG_MASK		0x0001
++#define	HIFN_MAC_CMD_ALG_SHA1		0x0000
++#define	HIFN_MAC_CMD_ALG_MD5		0x0001
++#define	HIFN_MAC_CMD_MODE_MASK		0x000c
++#define	HIFN_MAC_CMD_MODE_HMAC		0x0000
++#define	HIFN_MAC_CMD_MODE_SSL_MAC	0x0004
++#define	HIFN_MAC_CMD_MODE_HASH		0x0008
++#define	HIFN_MAC_CMD_MODE_FULL		0x0004
++#define	HIFN_MAC_CMD_TRUNC		0x0010
++#define	HIFN_MAC_CMD_RESULT		0x0020
++#define	HIFN_MAC_CMD_APPEND		0x0040
++#define	HIFN_MAC_CMD_SRCLEN_M		0xc000
++#define	HIFN_MAC_CMD_SRCLEN_S		14
++
++/*
++ * MAC POS IPsec initiates authentication after encryption on encodes
++ * and before decryption on decodes.
++ */
++#define	HIFN_MAC_CMD_POS_IPSEC		0x0200
++#define	HIFN_MAC_CMD_NEW_KEY		0x0800
++
++struct hifn_comp_command
++{
++	volatile u16 		masks;
++	volatile u16 		header_skip;
++	volatile u16 		source_count;
++	volatile u16 		reserved;
++};
++
++#define	HIFN_COMP_CMD_SRCLEN_M		0xc000
++#define	HIFN_COMP_CMD_SRCLEN_S		14
++#define	HIFN_COMP_CMD_ONE		0x0100	/* must be one */
++#define	HIFN_COMP_CMD_CLEARHIST		0x0010	/* clear history */
++#define	HIFN_COMP_CMD_UPDATEHIST	0x0008	/* update history */
++#define	HIFN_COMP_CMD_LZS_STRIP0	0x0004	/* LZS: strip zero */
++#define	HIFN_COMP_CMD_MPPC_RESTART	0x0004	/* MPPC: restart */
++#define	HIFN_COMP_CMD_ALG_MASK		0x0001	/* compression mode: */
++#define	HIFN_COMP_CMD_ALG_MPPC		0x0001	/*   MPPC */
++#define	HIFN_COMP_CMD_ALG_LZS		0x0000	/*   LZS */
++
++struct hifn_base_result
++{
++	volatile u16 		flags;
++	volatile u16 		session;
++	volatile u16 		src_cnt;		/* 15:0 of source count */
++	volatile u16 		dst_cnt;		/* 15:0 of dest count */
++};
++
++#define	HIFN_BASE_RES_DSTOVERRUN	0x0200	/* destination overrun */
++#define	HIFN_BASE_RES_SRCLEN_M		0xc000	/* 17:16 of source count */
++#define	HIFN_BASE_RES_SRCLEN_S		14
++#define	HIFN_BASE_RES_DSTLEN_M		0x3000	/* 17:16 of dest count */
++#define	HIFN_BASE_RES_DSTLEN_S		12
++
++struct hifn_comp_result
++{
++	volatile u16 		flags;
++	volatile u16 		crc;
++};
++
++#define	HIFN_COMP_RES_LCB_M		0xff00	/* longitudinal check byte */
++#define	HIFN_COMP_RES_LCB_S		8
++#define	HIFN_COMP_RES_RESTART		0x0004	/* MPPC: restart */
++#define	HIFN_COMP_RES_ENDMARKER		0x0002	/* LZS: end marker seen */
++#define	HIFN_COMP_RES_SRC_NOTZERO	0x0001	/* source expired */
++
++struct hifn_mac_result
++{
++	volatile u16 		flags;
++	volatile u16 		reserved;
++	/* followed by 0, 6, 8, or 10 u16's of the MAC, then crypt */
++};
++
++#define	HIFN_MAC_RES_MISCOMPARE		0x0002	/* compare failed */
++#define	HIFN_MAC_RES_SRC_NOTZERO	0x0001	/* source expired */
++
++struct hifn_crypt_result
++{
++	volatile u16 		flags;
++	volatile u16 		reserved;
++};
++
++#define	HIFN_CRYPT_RES_SRC_NOTZERO	0x0001	/* source expired */
++
++#ifndef HIFN_POLL_FREQUENCY
++#define	HIFN_POLL_FREQUENCY	0x1
++#endif
++
++#ifndef HIFN_POLL_SCALAR
++#define	HIFN_POLL_SCALAR	0x0
++#endif
++
++#define	HIFN_MAX_SEGLEN 	0xffff		/* maximum dma segment len */
++#define	HIFN_MAX_DMALEN		0x3ffff		/* maximum dma length */
++
++struct hifn_crypto_alg
++{
++	struct list_head	entry;
++	struct crypto_alg	alg;
++	struct hifn_device	*dev;
++};
++
++#define ASYNC_SCATTERLIST_CACHE	16
++
++#define ASYNC_FLAGS_MISALIGNED	(1<<0)
++
++struct ablkcipher_walk
++{
++	struct scatterlist	cache[ASYNC_SCATTERLIST_CACHE];
++	u32			flags;
++	int			num;
++};
++
++struct hifn_context
++{
++	u8			key[HIFN_MAX_CRYPT_KEY_LENGTH], *iv;
++	struct hifn_device	*dev;
++	unsigned int		keysize, ivsize;
++	u8			op, type, mode, unused;
++	struct ablkcipher_walk	walk;
++	atomic_t		sg_num;
++};
++
++#define crypto_alg_to_hifn(a)	container_of(a, struct hifn_crypto_alg, alg)
++
++static inline u32 hifn_read_0(struct hifn_device *dev, u32 reg)
++{
++	u32 ret;
++
++	ret = readl((char *)(dev->bar[0]) + reg);
++
++	return ret;
++}
++
++static inline u32 hifn_read_1(struct hifn_device *dev, u32 reg)
++{
++	u32 ret;
++
++	ret = readl((char *)(dev->bar[1]) + reg);
++
++	return ret;
++}
++
++static inline void hifn_write_0(struct hifn_device *dev, u32 reg, u32 val)
++{
++	writel(val, (char *)(dev->bar[0]) + reg);
++}
++
++static inline void hifn_write_1(struct hifn_device *dev, u32 reg, u32 val)
++{
++	writel(val, (char *)(dev->bar[1]) + reg);
++}
++
++static void hifn_wait_puc(struct hifn_device *dev)
++{
++	int i;
++	u32 ret;
++
++	for (i=10000; i > 0; --i) {
++		ret = hifn_read_0(dev, HIFN_0_PUCTRL);
++		if (!(ret & HIFN_PUCTRL_RESET))
++			break;
++
++		udelay(1);
++	}
++
++	if (!i)
++		dprintk("%s: Failed to reset PUC unit.\n", dev->name);
++}
++
++static void hifn_reset_puc(struct hifn_device *dev)
++{
++	hifn_write_0(dev, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
++	hifn_wait_puc(dev);
++}
++
++static void hifn_stop_device(struct hifn_device *dev)
++{
++	hifn_write_1(dev, HIFN_1_DMA_CSR,
++		HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
++		HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS);
++	hifn_write_0(dev, HIFN_0_PUIER, 0);
++	hifn_write_1(dev, HIFN_1_DMA_IER, 0);
++}
++
++static void hifn_reset_dma(struct hifn_device *dev, int full)
++{
++	hifn_stop_device(dev);
++
++	/*
++	 * Setting poll frequency and others to 0.
++	 */
++	hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++	mdelay(1);
++
++	/*
++	 * Reset DMA.
++	 */
++	if (full) {
++		hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
++		mdelay(1);
++	} else {
++		hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE |
++				HIFN_DMACNFG_MSTRESET);
++		hifn_reset_puc(dev);
++	}
++
++	hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++
++	hifn_reset_puc(dev);
++}
++
++static u32 hifn_next_signature(u_int32_t a, u_int cnt)
++{
++	int i;
++	u32 v;
++
++	for (i = 0; i < cnt; i++) {
++
++		/* get the parity */
++		v = a & 0x80080125;
++		v ^= v >> 16;
++		v ^= v >> 8;
++		v ^= v >> 4;
++		v ^= v >> 2;
++		v ^= v >> 1;
++
++		a = (v & 1) ^ (a << 1);
++	}
++
++	return a;
++}
++
++static struct pci2id {
++	u_short		pci_vendor;
++	u_short		pci_prod;
++	char		card_id[13];
++} pci2id[] = {
++	{
++		PCI_VENDOR_ID_HIFN,
++		PCI_DEVICE_ID_HIFN_7955,
++		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++		  0x00, 0x00, 0x00, 0x00, 0x00 }
++	},
++	{
++		PCI_VENDOR_ID_HIFN,
++		PCI_DEVICE_ID_HIFN_7956,
++		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++		  0x00, 0x00, 0x00, 0x00, 0x00 }
++	}
++};
++
++#ifdef CRYPTO_DEV_HIFN_795X_RNG
++static int hifn_rng_data_present(struct hwrng *rng, int wait)
++{
++	struct hifn_device *dev = (struct hifn_device *)rng->priv;
++	s64 nsec;
++
++	nsec = ktime_to_ns(ktime_sub(ktime_get(), dev->rngtime));
++	nsec -= dev->rng_wait_time;
++	if (nsec <= 0)
++		return 1;
++	if (!wait)
++		return 0;
++	ndelay(nsec);
++	return 1;
++}
++
++static int hifn_rng_data_read(struct hwrng *rng, u32 *data)
++{
++	struct hifn_device *dev = (struct hifn_device *)rng->priv;
++
++	*data = hifn_read_1(dev, HIFN_1_RNG_DATA);
++	dev->rngtime = ktime_get();
++	return 4;
++}
++
++static int hifn_register_rng(struct hifn_device *dev)
++{
++	/*
++	 * We must wait at least 256 Pk_clk cycles between two reads of the rng.
++	 */
++	dev->rng_wait_time	= DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) *
++				  256;
++
++	dev->rng.name		= dev->name;
++	dev->rng.data_present	= hifn_rng_data_present,
++	dev->rng.data_read	= hifn_rng_data_read,
++	dev->rng.priv		= (unsigned long)dev;
++
++	return hwrng_register(&dev->rng);
++}
++
++static void hifn_unregister_rng(struct hifn_device *dev)
++{
++	hwrng_unregister(&dev->rng);
++}
++#else
++#define hifn_register_rng(dev)		0
++#define hifn_unregister_rng(dev)
++#endif
++
++static int hifn_init_pubrng(struct hifn_device *dev)
++{
++	int i;
++
++	hifn_write_1(dev, HIFN_1_PUB_RESET, hifn_read_1(dev, HIFN_1_PUB_RESET) |
++			HIFN_PUBRST_RESET);
++
++	for (i=100; i > 0; --i) {
++		mdelay(1);
++
++		if ((hifn_read_1(dev, HIFN_1_PUB_RESET) & HIFN_PUBRST_RESET) == 0)
++			break;
++	}
++
++	if (!i)
++		dprintk("Chip %s: Failed to initialise public key engine.\n",
++				dev->name);
++	else {
++		hifn_write_1(dev, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
++		dev->dmareg |= HIFN_DMAIER_PUBDONE;
++		hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
 +
-+	va_start(args, fmt);
-+	name = kvasprintf(GFP_KERNEL, fmt, args);
-+	va_end(args);
++		dprintk("Chip %s: Public key engine has been sucessfully "
++				"initialised.\n", dev->name);
++	}
 +
-+	if (!name)
-+		return -ENOMEM;
++	/*
++	 * Enable RNG engine.
++	 */
 +
-+	return kobject_add(kobj, &drv->p->kobj, "%s", name);
- }
-+EXPORT_SYMBOL_GPL(driver_add_kobj);
++	hifn_write_1(dev, HIFN_1_RNG_CONFIG,
++			hifn_read_1(dev, HIFN_1_RNG_CONFIG) | HIFN_RNGCFG_ENA);
++	dprintk("Chip %s: RNG engine has been successfully initialised.\n",
++			dev->name);
 +
-+/**
-+ * get_driver - increment driver reference count.
-+ * @drv: driver.
++#ifdef CRYPTO_DEV_HIFN_795X_RNG
++	/* First value must be discarded */
++	hifn_read_1(dev, HIFN_1_RNG_DATA);
++	dev->rngtime = ktime_get();
++#endif
++	return 0;
++}
++
++static int hifn_enable_crypto(struct hifn_device *dev)
++{
++	u32 dmacfg, addr;
++	char *offtbl = NULL;
++	int i;
++
++	for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
++		if (pci2id[i].pci_vendor == dev->pdev->vendor &&
++				pci2id[i].pci_prod == dev->pdev->device) {
++			offtbl = pci2id[i].card_id;
++			break;
++		}
++	}
++
++	if (offtbl == NULL) {
++		dprintk("Chip %s: Unknown card!\n", dev->name);
++		return -ENODEV;
++	}
++
++	dmacfg = hifn_read_1(dev, HIFN_1_DMA_CNFG);
++
++	hifn_write_1(dev, HIFN_1_DMA_CNFG,
++			HIFN_DMACNFG_UNLOCK | HIFN_DMACNFG_MSTRESET |
++			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
++	mdelay(1);
++	addr = hifn_read_1(dev, HIFN_1_UNLOCK_SECRET1);
++	mdelay(1);
++	hifn_write_1(dev, HIFN_1_UNLOCK_SECRET2, 0);
++	mdelay(1);
++
++	for (i=0; i<12; ++i) {
++		addr = hifn_next_signature(addr, offtbl[i] + 0x101);
++		hifn_write_1(dev, HIFN_1_UNLOCK_SECRET2, addr);
++
++		mdelay(1);
++	}
++	hifn_write_1(dev, HIFN_1_DMA_CNFG, dmacfg);
++
++	dprintk("Chip %s: %s.\n", dev->name, pci_name(dev->pdev));
++
++	return 0;
++}
++
++static void hifn_init_dma(struct hifn_device *dev)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	u32 dptr = dev->desc_dma;
++	int i;
++
++	for (i=0; i<HIFN_D_CMD_RSIZE; ++i)
++		dma->cmdr[i].p = __cpu_to_le32(dptr +
++				offsetof(struct hifn_dma, command_bufs[i][0]));
++	for (i=0; i<HIFN_D_RES_RSIZE; ++i)
++		dma->resr[i].p = __cpu_to_le32(dptr +
++				offsetof(struct hifn_dma, result_bufs[i][0]));
++
++	/*
++	 * Setup LAST descriptors.
++	 */
++	dma->cmdr[HIFN_D_CMD_RSIZE].p = __cpu_to_le32(dptr +
++			offsetof(struct hifn_dma, cmdr[0]));
++	dma->srcr[HIFN_D_SRC_RSIZE].p = __cpu_to_le32(dptr +
++			offsetof(struct hifn_dma, srcr[0]));
++	dma->dstr[HIFN_D_DST_RSIZE].p = __cpu_to_le32(dptr +
++			offsetof(struct hifn_dma, dstr[0]));
++	dma->resr[HIFN_D_RES_RSIZE].p = __cpu_to_le32(dptr +
++			offsetof(struct hifn_dma, resr[0]));
++
++	dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
++	dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
++	dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
++}
++
++/*
++ * Initialize the PLL. We need to know the frequency of the reference clock
++ * to calculate the optimal multiplier. For PCI we assume 66MHz, since that
++ * allows us to operate without the risk of overclocking the chip. If it
++ * actually uses 33MHz, the chip will operate at half the speed, this can be
++ * overriden by specifying the frequency as module parameter (pci33).
++ *
++ * Unfortunately the PCI clock is not very suitable since the HIFN needs a
++ * stable clock and the PCI clock frequency may vary, so the default is the
++ * external clock. There is no way to find out its frequency, we default to
++ * 66MHz since according to Mike Ham of HiFn, almost every board in existence
++ * has an external crystal populated at 66MHz.
 + */
-+struct device_driver *get_driver(struct device_driver *drv)
++static void hifn_init_pll(struct hifn_device *dev)
 +{
-+	if (drv) {
-+		struct driver_private *priv;
-+		struct kobject *kobj;
- 
-+		kobj = kobject_get(&drv->p->kobj);
-+		priv = to_driver(kobj);
-+		return priv->driver;
++	unsigned int freq, m;
++	u32 pllcfg;
++
++	pllcfg = HIFN_1_PLL | HIFN_PLL_RESERVED_1;
++
++	if (strncmp(hifn_pll_ref, "ext", 3) == 0)
++		pllcfg |= HIFN_PLL_REF_CLK_PLL;
++	else
++		pllcfg |= HIFN_PLL_REF_CLK_HBI;
++
++	if (hifn_pll_ref[3] != '\0')
++		freq = simple_strtoul(hifn_pll_ref + 3, NULL, 10);
++	else {
++		freq = 66;
++		printk(KERN_INFO "hifn795x: assuming %uMHz clock speed, "
++				 "override with hifn_pll_ref=%.3s<frequency>\n",
++		       freq, hifn_pll_ref);
 +	}
-+	return NULL;
++
++	m = HIFN_PLL_FCK_MAX / freq;
++
++	pllcfg |= (m / 2 - 1) << HIFN_PLL_ND_SHIFT;
++	if (m <= 8)
++		pllcfg |= HIFN_PLL_IS_1_8;
++	else
++		pllcfg |= HIFN_PLL_IS_9_12;
++
++	/* Select clock source and enable clock bypass */
++	hifn_write_1(dev, HIFN_1_PLL, pllcfg |
++		     HIFN_PLL_PK_CLK_HBI | HIFN_PLL_PE_CLK_HBI | HIFN_PLL_BP);
++
++	/* Let the chip lock to the input clock */
++	mdelay(10);
++
++	/* Disable clock bypass */
++	hifn_write_1(dev, HIFN_1_PLL, pllcfg |
++		     HIFN_PLL_PK_CLK_HBI | HIFN_PLL_PE_CLK_HBI);
++
++	/* Switch the engines to the PLL */
++	hifn_write_1(dev, HIFN_1_PLL, pllcfg |
++		     HIFN_PLL_PK_CLK_PLL | HIFN_PLL_PE_CLK_PLL);
++
++	/*
++	 * The Fpk_clk runs at half the total speed. Its frequency is needed to
++	 * calculate the minimum time between two reads of the rng. Since 33MHz
++	 * is actually 33.333... we overestimate the frequency here, resulting
++	 * in slightly larger intervals.
++	 */
++	dev->pk_clk_freq = 1000000 * (freq + 1) * m / 2;
 +}
-+EXPORT_SYMBOL_GPL(get_driver);
- 
- /**
-- *	put_driver - decrement driver's refcount.
-- *	@drv:	driver.
-+ * put_driver - decrement driver's refcount.
-+ * @drv: driver.
-  */
--void put_driver(struct device_driver * drv)
-+void put_driver(struct device_driver *drv)
++
++static void hifn_init_registers(struct hifn_device *dev)
 +{
-+	kobject_put(&drv->p->kobj);
++	u32 dptr = dev->desc_dma;
++
++	/* Initialization magic... */
++	hifn_write_0(dev, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
++	hifn_write_0(dev, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
++	hifn_write_0(dev, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
++
++	/* write all 4 ring address registers */
++	hifn_write_1(dev, HIFN_1_DMA_CRAR, __cpu_to_le32(dptr +
++				offsetof(struct hifn_dma, cmdr[0])));
++	hifn_write_1(dev, HIFN_1_DMA_SRAR, __cpu_to_le32(dptr +
++				offsetof(struct hifn_dma, srcr[0])));
++	hifn_write_1(dev, HIFN_1_DMA_DRAR, __cpu_to_le32(dptr +
++				offsetof(struct hifn_dma, dstr[0])));
++	hifn_write_1(dev, HIFN_1_DMA_RRAR, __cpu_to_le32(dptr +
++				offsetof(struct hifn_dma, resr[0])));
++
++	mdelay(2);
++#if 0
++	hifn_write_1(dev, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
++	    HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
++	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
++	    HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
++	    HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
++	    HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
++	    HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
++	    HIFN_DMACSR_S_WAIT |
++	    HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
++	    HIFN_DMACSR_C_WAIT |
++	    HIFN_DMACSR_ENGINE |
++	    HIFN_DMACSR_PUBDONE);
++#else
++	hifn_write_1(dev, HIFN_1_DMA_CSR,
++	    HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
++	    HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA |
++	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
++	    HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
++	    HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
++	    HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
++	    HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
++	    HIFN_DMACSR_S_WAIT |
++	    HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
++	    HIFN_DMACSR_C_WAIT |
++	    HIFN_DMACSR_ENGINE |
++	    HIFN_DMACSR_PUBDONE);
++#endif
++	hifn_read_1(dev, HIFN_1_DMA_CSR);
++
++	dev->dmareg |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
++	    HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
++	    HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
++	    HIFN_DMAIER_ENGINE;
++	dev->dmareg &= ~HIFN_DMAIER_C_WAIT;
++
++	hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
++	hifn_read_1(dev, HIFN_1_DMA_IER);
++#if 0
++	hifn_write_0(dev, HIFN_0_PUCNFG, HIFN_PUCNFG_ENCCNFG |
++		    HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
++		    HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
++		    HIFN_PUCNFG_DRAM);
++#else
++	hifn_write_0(dev, HIFN_0_PUCNFG, 0x10342);
++#endif
++	hifn_init_pll(dev);
++
++	hifn_write_0(dev, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
++	hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
++	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
++	    ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
++	    ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
 +}
-+EXPORT_SYMBOL_GPL(put_driver);
 +
-+static int driver_add_groups(struct device_driver *drv,
-+			     struct attribute_group **groups)
- {
--	kobject_put(&drv->kobj);
-+	int error = 0;
-+	int i;
++static int hifn_setup_base_command(struct hifn_device *dev, u8 *buf,
++		unsigned dlen, unsigned slen, u16 mask, u8 snum)
++{
++	struct hifn_base_command *base_cmd;
++	u8 *buf_pos = buf;
 +
-+	if (groups) {
-+		for (i = 0; groups[i]; i++) {
-+			error = sysfs_create_group(&drv->p->kobj, groups[i]);
-+			if (error) {
-+				while (--i >= 0)
-+					sysfs_remove_group(&drv->p->kobj,
-+							   groups[i]);
++	base_cmd = (struct hifn_base_command *)buf_pos;
++	base_cmd->masks = __cpu_to_le16(mask);
++	base_cmd->total_source_count =
++		__cpu_to_le16(slen & HIFN_BASE_CMD_LENMASK_LO);
++	base_cmd->total_dest_count =
++		__cpu_to_le16(dlen & HIFN_BASE_CMD_LENMASK_LO);
++
++	dlen >>= 16;
++	slen >>= 16;
++	base_cmd->session_num = __cpu_to_le16(snum |
++	    ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
++	    ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
++
++	return sizeof(struct hifn_base_command);
++}
++
++static int hifn_setup_crypto_command(struct hifn_device *dev,
++		u8 *buf, unsigned dlen, unsigned slen,
++		u8 *key, int keylen, u8 *iv, int ivsize, u16 mode)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	struct hifn_crypt_command *cry_cmd;
++	u8 *buf_pos = buf;
++	u16 cmd_len;
++
++	cry_cmd = (struct hifn_crypt_command *)buf_pos;
++
++	cry_cmd->source_count = __cpu_to_le16(dlen & 0xffff);
++	dlen >>= 16;
++	cry_cmd->masks = __cpu_to_le16(mode |
++			((dlen << HIFN_CRYPT_CMD_SRCLEN_S) &
++			 HIFN_CRYPT_CMD_SRCLEN_M));
++	cry_cmd->header_skip = 0;
++	cry_cmd->reserved = 0;
++
++	buf_pos += sizeof(struct hifn_crypt_command);
++
++	dma->cmdu++;
++	if (dma->cmdu > 1) {
++		dev->dmareg |= HIFN_DMAIER_C_WAIT;
++		hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
++	}
++
++	if (keylen) {
++		memcpy(buf_pos, key, keylen);
++		buf_pos += keylen;
++	}
++	if (ivsize) {
++		memcpy(buf_pos, iv, ivsize);
++		buf_pos += ivsize;
++	}
++
++	cmd_len = buf_pos - buf;
++
++	return cmd_len;
++}
++
++static int hifn_setup_src_desc(struct hifn_device *dev, struct page *page,
++		unsigned int offset, unsigned int size)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	int idx;
++	dma_addr_t addr;
++
++	addr = pci_map_page(dev->pdev, page, offset, size, PCI_DMA_TODEVICE);
++
++	idx = dma->srci;
++
++	dma->srcr[idx].p = __cpu_to_le32(addr);
++	dma->srcr[idx].l = __cpu_to_le32(size) | HIFN_D_VALID |
++			HIFN_D_MASKDONEIRQ | HIFN_D_NOINVALID | HIFN_D_LAST;
++
++	if (++idx == HIFN_D_SRC_RSIZE) {
++		dma->srcr[idx].l = __cpu_to_le32(HIFN_D_VALID |
++				HIFN_D_JUMP |
++				HIFN_D_MASKDONEIRQ | HIFN_D_LAST);
++		idx = 0;
++	}
++
++	dma->srci = idx;
++	dma->srcu++;
++
++	if (!(dev->flags & HIFN_FLAG_SRC_BUSY)) {
++		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA);
++		dev->flags |= HIFN_FLAG_SRC_BUSY;
++	}
++
++	return size;
++}
++
++static void hifn_setup_res_desc(struct hifn_device *dev)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++
++	dma->resr[dma->resi].l = __cpu_to_le32(HIFN_USED_RESULT |
++			HIFN_D_VALID | HIFN_D_LAST);
++	/*
++	 * dma->resr[dma->resi].l = __cpu_to_le32(HIFN_MAX_RESULT | HIFN_D_VALID |
++	 *					HIFN_D_LAST | HIFN_D_NOINVALID);
++	 */
++
++	if (++dma->resi == HIFN_D_RES_RSIZE) {
++		dma->resr[HIFN_D_RES_RSIZE].l = __cpu_to_le32(HIFN_D_VALID |
++				HIFN_D_JUMP | HIFN_D_MASKDONEIRQ | HIFN_D_LAST);
++		dma->resi = 0;
++	}
++
++	dma->resu++;
++
++	if (!(dev->flags & HIFN_FLAG_RES_BUSY)) {
++		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA);
++		dev->flags |= HIFN_FLAG_RES_BUSY;
++	}
++}
++
++static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page,
++		unsigned offset, unsigned size)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	int idx;
++	dma_addr_t addr;
++
++	addr = pci_map_page(dev->pdev, page, offset, size, PCI_DMA_FROMDEVICE);
++
++	idx = dma->dsti;
++	dma->dstr[idx].p = __cpu_to_le32(addr);
++	dma->dstr[idx].l = __cpu_to_le32(size |	HIFN_D_VALID |
++			HIFN_D_MASKDONEIRQ | HIFN_D_NOINVALID | HIFN_D_LAST);
++
++	if (++idx == HIFN_D_DST_RSIZE) {
++		dma->dstr[idx].l = __cpu_to_le32(HIFN_D_VALID |
++				HIFN_D_JUMP | HIFN_D_MASKDONEIRQ |
++				HIFN_D_LAST | HIFN_D_NOINVALID);
++		idx = 0;
++	}
++	dma->dsti = idx;
++	dma->dstu++;
++
++	if (!(dev->flags & HIFN_FLAG_DST_BUSY)) {
++		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA);
++		dev->flags |= HIFN_FLAG_DST_BUSY;
++	}
++}
++
++static int hifn_setup_dma(struct hifn_device *dev, struct page *spage, unsigned int soff,
++		struct page *dpage, unsigned int doff, unsigned int nbytes, void *priv,
++		struct hifn_context *ctx)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	int cmd_len, sa_idx;
++	u8 *buf, *buf_pos;
++	u16 mask;
++
++	dprintk("%s: spage: %p, soffset: %u, dpage: %p, doffset: %u, nbytes: %u, priv: %p, ctx: %p.\n",
++			dev->name, spage, soff, dpage, doff, nbytes, priv, ctx);
++
++	sa_idx = dma->resi;
++
++	hifn_setup_src_desc(dev, spage, soff, nbytes);
++
++	buf_pos = buf = dma->command_bufs[dma->cmdi];
++
++	mask = 0;
++	switch (ctx->op) {
++		case ACRYPTO_OP_DECRYPT:
++			mask = HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE;
++			break;
++		case ACRYPTO_OP_ENCRYPT:
++			mask = HIFN_BASE_CMD_CRYPT;
++			break;
++		case ACRYPTO_OP_HMAC:
++			mask = HIFN_BASE_CMD_MAC;
++			break;
++		default:
++			goto err_out;
++	}
++
++	buf_pos += hifn_setup_base_command(dev, buf_pos, nbytes,
++			nbytes, mask, dev->snum);
++
++	if (ctx->op == ACRYPTO_OP_ENCRYPT || ctx->op == ACRYPTO_OP_DECRYPT) {
++		u16 md = 0;
++
++		if (ctx->keysize)
++			md |= HIFN_CRYPT_CMD_NEW_KEY;
++		if (ctx->iv && ctx->mode != ACRYPTO_MODE_ECB)
++			md |= HIFN_CRYPT_CMD_NEW_IV;
++
++		switch (ctx->mode) {
++			case ACRYPTO_MODE_ECB:
++				md |= HIFN_CRYPT_CMD_MODE_ECB;
 +				break;
-+			}
++			case ACRYPTO_MODE_CBC:
++				md |= HIFN_CRYPT_CMD_MODE_CBC;
++				break;
++			case ACRYPTO_MODE_CFB:
++				md |= HIFN_CRYPT_CMD_MODE_CFB;
++				break;
++			case ACRYPTO_MODE_OFB:
++				md |= HIFN_CRYPT_CMD_MODE_OFB;
++				break;
++			default:
++				goto err_out;
++		}
++
++		switch (ctx->type) {
++			case ACRYPTO_TYPE_AES_128:
++				if (ctx->keysize != 16)
++					goto err_out;
++				md |= HIFN_CRYPT_CMD_KSZ_128 |
++					HIFN_CRYPT_CMD_ALG_AES;
++				break;
++			case ACRYPTO_TYPE_AES_192:
++				if (ctx->keysize != 24)
++					goto err_out;
++				md |= HIFN_CRYPT_CMD_KSZ_192 |
++					HIFN_CRYPT_CMD_ALG_AES;
++				break;
++			case ACRYPTO_TYPE_AES_256:
++				if (ctx->keysize != 32)
++					goto err_out;
++				md |= HIFN_CRYPT_CMD_KSZ_256 |
++					HIFN_CRYPT_CMD_ALG_AES;
++				break;
++			case ACRYPTO_TYPE_3DES:
++				if (ctx->keysize != 24)
++					goto err_out;
++				md |= HIFN_CRYPT_CMD_ALG_3DES;
++				break;
++			case ACRYPTO_TYPE_DES:
++				if (ctx->keysize != 8)
++					goto err_out;
++				md |= HIFN_CRYPT_CMD_ALG_DES;
++				break;
++			default:
++				goto err_out;
 +		}
++
++		buf_pos += hifn_setup_crypto_command(dev, buf_pos,
++				nbytes, nbytes, ctx->key, ctx->keysize,
++				ctx->iv, ctx->ivsize, md);
 +	}
-+	return error;
++
++	dev->sa[sa_idx] = priv;
++
++	cmd_len = buf_pos - buf;
++	dma->cmdr[dma->cmdi].l = __cpu_to_le32(cmd_len | HIFN_D_VALID |
++			HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
++
++	if (++dma->cmdi == HIFN_D_CMD_RSIZE) {
++		dma->cmdr[dma->cmdi].l = __cpu_to_le32(HIFN_MAX_COMMAND |
++			HIFN_D_VALID | HIFN_D_LAST |
++			HIFN_D_MASKDONEIRQ | HIFN_D_JUMP);
++		dma->cmdi = 0;
++	} else
++		dma->cmdr[dma->cmdi-1].l |= __cpu_to_le32(HIFN_D_VALID);
++
++	if (!(dev->flags & HIFN_FLAG_CMD_BUSY)) {
++		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA);
++		dev->flags |= HIFN_FLAG_CMD_BUSY;
++	}
++
++	hifn_setup_dst_desc(dev, dpage, doff, nbytes);
++	hifn_setup_res_desc(dev);
++
++	return 0;
++
++err_out:
++	return -EINVAL;
 +}
 +
-+static void driver_remove_groups(struct device_driver *drv,
-+				 struct attribute_group **groups)
++static int ablkcipher_walk_init(struct ablkcipher_walk *w,
++		int num, gfp_t gfp_flags)
 +{
 +	int i;
 +
-+	if (groups)
-+		for (i = 0; groups[i]; i++)
-+			sysfs_remove_group(&drv->p->kobj, groups[i]);
- }
- 
- /**
-- *	driver_register - register driver with bus
-- *	@drv:	driver to register
-+ * driver_register - register driver with bus
-+ * @drv: driver to register
-  *
-- *	We pass off most of the work to the bus_add_driver() call,
-- *	since most of the things we have to do deal with the bus
-- *	structures.
-+ * We pass off most of the work to the bus_add_driver() call,
-+ * since most of the things we have to do deal with the bus
-+ * structures.
-  */
--int driver_register(struct device_driver * drv)
-+int driver_register(struct device_driver *drv)
- {
-+	int ret;
++	num = min(ASYNC_SCATTERLIST_CACHE, num);
++	sg_init_table(w->cache, num);
 +
- 	if ((drv->bus->probe && drv->probe) ||
- 	    (drv->bus->remove && drv->remove) ||
--	    (drv->bus->shutdown && drv->shutdown)) {
--		printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
--	}
--	klist_init(&drv->klist_devices, NULL, NULL);
--	return bus_add_driver(drv);
-+	    (drv->bus->shutdown && drv->shutdown))
-+		printk(KERN_WARNING "Driver '%s' needs updating - please use "
-+			"bus_type methods\n", drv->name);
-+	ret = bus_add_driver(drv);
-+	if (ret)
-+		return ret;
-+	ret = driver_add_groups(drv, drv->groups);
-+	if (ret)
-+		bus_remove_driver(drv);
-+	return ret;
- }
-+EXPORT_SYMBOL_GPL(driver_register);
- 
- /**
-- *	driver_unregister - remove driver from system.
-- *	@drv:	driver.
-+ * driver_unregister - remove driver from system.
-+ * @drv: driver.
-  *
-- *	Again, we pass off most of the work to the bus-level call.
-+ * Again, we pass off most of the work to the bus-level call.
-  */
--
--void driver_unregister(struct device_driver * drv)
-+void driver_unregister(struct device_driver *drv)
- {
-+	driver_remove_groups(drv, drv->groups);
- 	bus_remove_driver(drv);
- }
-+EXPORT_SYMBOL_GPL(driver_unregister);
- 
- /**
-- *	driver_find - locate driver on a bus by its name.
-- *	@name:	name of the driver.
-- *	@bus:	bus to scan for the driver.
-+ * driver_find - locate driver on a bus by its name.
-+ * @name: name of the driver.
-+ * @bus: bus to scan for the driver.
-  *
-- *	Call kset_find_obj() to iterate over list of drivers on
-- *	a bus to find driver by name. Return driver if found.
-+ * Call kset_find_obj() to iterate over list of drivers on
-+ * a bus to find driver by name. Return driver if found.
-  *
-- *	Note that kset_find_obj increments driver's reference count.
-+ * Note that kset_find_obj increments driver's reference count.
-  */
- struct device_driver *driver_find(const char *name, struct bus_type *bus)
- {
--	struct kobject *k = kset_find_obj(&bus->drivers, name);
--	if (k)
--		return to_drv(k);
-+	struct kobject *k = kset_find_obj(bus->p->drivers_kset, name);
-+	struct driver_private *priv;
++	w->num = 0;
++	for (i=0; i<num; ++i) {
++		struct page *page = alloc_page(gfp_flags);
++		struct scatterlist *s;
 +
-+	if (k) {
-+		priv = to_driver(k);
-+		return priv->driver;
++		if (!page)
++			break;
++
++		s = &w->cache[i];
++
++		sg_set_page(s, page, PAGE_SIZE, 0);
++		w->num++;
 +	}
- 	return NULL;
- }
--
--EXPORT_SYMBOL_GPL(driver_register);
--EXPORT_SYMBOL_GPL(driver_unregister);
--EXPORT_SYMBOL_GPL(get_driver);
--EXPORT_SYMBOL_GPL(put_driver);
- EXPORT_SYMBOL_GPL(driver_find);
--
--EXPORT_SYMBOL_GPL(driver_create_file);
--EXPORT_SYMBOL_GPL(driver_remove_file);
-diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
-index 90c8629..1138155 100644
---- a/drivers/base/firmware.c
-+++ b/drivers/base/firmware.c
-@@ -3,11 +3,11 @@
-  *
-  * Copyright (c) 2002-3 Patrick Mochel
-  * Copyright (c) 2002-3 Open Source Development Labs
-+ * Copyright (c) 2007 Greg Kroah-Hartman <gregkh at suse.de>
-+ * Copyright (c) 2007 Novell Inc.
-  *
-  * This file is released under the GPLv2
-- *
-  */
--
- #include <linux/kobject.h>
- #include <linux/module.h>
- #include <linux/init.h>
-@@ -15,23 +15,13 @@
- 
- #include "base.h"
- 
--static decl_subsys(firmware, NULL, NULL);
--
--int firmware_register(struct kset *s)
--{
--	kobj_set_kset_s(s, firmware_subsys);
--	return subsystem_register(s);
--}
--
--void firmware_unregister(struct kset *s)
--{
--	subsystem_unregister(s);
--}
-+struct kobject *firmware_kobj;
-+EXPORT_SYMBOL_GPL(firmware_kobj);
- 
- int __init firmware_init(void)
- {
--	return subsystem_register(&firmware_subsys);
-+	firmware_kobj = kobject_create_and_add("firmware", NULL);
-+	if (!firmware_kobj)
-+		return -ENOMEM;
-+	return 0;
- }
--
--EXPORT_SYMBOL_GPL(firmware_register);
--EXPORT_SYMBOL_GPL(firmware_unregister);
-diff --git a/drivers/base/hypervisor.c b/drivers/base/hypervisor.c
-index 7080b41..6428cba 100644
---- a/drivers/base/hypervisor.c
-+++ b/drivers/base/hypervisor.c
-@@ -2,19 +2,23 @@
-  * hypervisor.c - /sys/hypervisor subsystem.
-  *
-  * Copyright (C) IBM Corp. 2006
-+ * Copyright (C) 2007 Greg Kroah-Hartman <gregkh at suse.de>
-+ * Copyright (C) 2007 Novell Inc.
-  *
-  * This file is released under the GPLv2
-  */
- 
- #include <linux/kobject.h>
- #include <linux/device.h>
--
- #include "base.h"
- 
--decl_subsys(hypervisor, NULL, NULL);
--EXPORT_SYMBOL_GPL(hypervisor_subsys);
-+struct kobject *hypervisor_kobj;
-+EXPORT_SYMBOL_GPL(hypervisor_kobj);
- 
- int __init hypervisor_init(void)
- {
--	return subsystem_register(&hypervisor_subsys);
-+	hypervisor_kobj = kobject_create_and_add("hypervisor", NULL);
-+	if (!hypervisor_kobj)
-+		return -ENOMEM;
-+	return 0;
- }
-diff --git a/drivers/base/init.c b/drivers/base/init.c
-index 3713815..7bd9b6a 100644
---- a/drivers/base/init.c
-+++ b/drivers/base/init.c
-@@ -1,10 +1,8 @@
- /*
-- *
-  * Copyright (c) 2002-3 Patrick Mochel
-  * Copyright (c) 2002-3 Open Source Development Labs
-  *
-  * This file is released under the GPLv2
-- *
-  */
- 
- #include <linux/device.h>
-@@ -14,12 +12,11 @@
- #include "base.h"
- 
- /**
-- *	driver_init - initialize driver model.
-+ * driver_init - initialize driver model.
-  *
-- *	Call the driver model init functions to initialize their
-- *	subsystems. Called early from init/main.c.
-+ * Call the driver model init functions to initialize their
-+ * subsystems. Called early from init/main.c.
-  */
--
- void __init driver_init(void)
- {
- 	/* These are the core pieces */
-@@ -36,5 +33,4 @@ void __init driver_init(void)
- 	system_bus_init();
- 	cpu_dev_init();
- 	memory_dev_init();
--	attribute_container_init();
- }
-diff --git a/drivers/base/memory.c b/drivers/base/memory.c
-index 7868707..7ae413f 100644
---- a/drivers/base/memory.c
-+++ b/drivers/base/memory.c
-@@ -26,7 +26,7 @@
- #define MEMORY_CLASS_NAME	"memory"
- 
- static struct sysdev_class memory_sysdev_class = {
--	set_kset_name(MEMORY_CLASS_NAME),
-+	.name = MEMORY_CLASS_NAME,
- };
- 
- static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj)
-diff --git a/drivers/base/module.c b/drivers/base/module.c
-new file mode 100644
-index 0000000..103be9c
---- /dev/null
-+++ b/drivers/base/module.c
-@@ -0,0 +1,94 @@
-+/*
-+ * module.c - module sysfs fun for drivers
-+ *
-+ * This file is released under the GPLv2
-+ *
-+ */
-+#include <linux/device.h>
-+#include <linux/module.h>
-+#include <linux/errno.h>
-+#include <linux/string.h>
-+#include "base.h"
 +
-+static char *make_driver_name(struct device_driver *drv)
++	return i;
++}
++
++static void ablkcipher_walk_exit(struct ablkcipher_walk *w)
 +{
-+	char *driver_name;
++	int i;
 +
-+	driver_name = kmalloc(strlen(drv->name) + strlen(drv->bus->name) + 2,
-+			      GFP_KERNEL);
-+	if (!driver_name)
-+		return NULL;
++	for (i=0; i<w->num; ++i) {
++		struct scatterlist *s = &w->cache[i];
 +
-+	sprintf(driver_name, "%s:%s", drv->bus->name, drv->name);
-+	return driver_name;
++		__free_page(sg_page(s));
++
++		s->length = 0;
++	}
++
++	w->num = 0;
 +}
 +
-+static void module_create_drivers_dir(struct module_kobject *mk)
++static int ablkcipher_add(void *daddr, unsigned int *drestp, struct scatterlist *src,
++		unsigned int size, unsigned int *nbytesp)
 +{
-+	if (!mk || mk->drivers_dir)
-+		return;
++	unsigned int copy, drest = *drestp, nbytes = *nbytesp;
++	int idx = 0;
++	void *saddr;
 +
-+	mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
++	if (drest < size || size > nbytes)
++		return -EINVAL;
++
++	while (size) {
++		copy = min(drest, src->length);
++
++		saddr = kmap_atomic(sg_page(src), KM_SOFTIRQ1);
++		memcpy(daddr, saddr + src->offset, copy);
++		kunmap_atomic(saddr, KM_SOFTIRQ1);
++
++		size -= copy;
++		drest -= copy;
++		nbytes -= copy;
++		daddr += copy;
++
++		dprintk("%s: copy: %u, size: %u, drest: %u, nbytes: %u.\n",
++				__func__, copy, size, drest, nbytes);
++
++		src++;
++		idx++;
++	}
++
++	*nbytesp = nbytes;
++	*drestp = drest;
++
++	return idx;
 +}
 +
-+void module_add_driver(struct module *mod, struct device_driver *drv)
++static int ablkcipher_walk(struct ablkcipher_request *req,
++		struct ablkcipher_walk *w)
 +{
-+	char *driver_name;
-+	int no_warn;
-+	struct module_kobject *mk = NULL;
++	unsigned blocksize =
++		crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(req));
++	unsigned alignmask =
++		crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
++	struct scatterlist *src, *dst, *t;
++	void *daddr;
++	unsigned int nbytes = req->nbytes, offset, copy, diff;
++	int idx, tidx, err;
 +
-+	if (!drv)
-+		return;
++	tidx = idx = 0;
++	offset = 0;
++	while (nbytes) {
++		if (idx >= w->num && (w->flags & ASYNC_FLAGS_MISALIGNED))
++			return -EINVAL;
 +
-+	if (mod)
-+		mk = &mod->mkobj;
-+	else if (drv->mod_name) {
-+		struct kobject *mkobj;
++		src = &req->src[idx];
++		dst = &req->dst[idx];
 +
-+		/* Lookup built-in module entry in /sys/modules */
-+		mkobj = kset_find_obj(module_kset, drv->mod_name);
-+		if (mkobj) {
-+			mk = container_of(mkobj, struct module_kobject, kobj);
-+			/* remember our module structure */
-+			drv->p->mkobj = mk;
-+			/* kset_find_obj took a reference */
-+			kobject_put(mkobj);
++		dprintk("\n%s: slen: %u, dlen: %u, soff: %u, doff: %u, offset: %u, "
++				"blocksize: %u, nbytes: %u.\n",
++				__func__, src->length, dst->length, src->offset,
++				dst->offset, offset, blocksize, nbytes);
++
++		if (src->length & (blocksize - 1) ||
++				src->offset & (alignmask - 1) ||
++				dst->length & (blocksize - 1) ||
++				dst->offset & (alignmask - 1) ||
++				offset) {
++			unsigned slen = src->length - offset;
++			unsigned dlen = PAGE_SIZE;
++
++			t = &w->cache[idx];
++
++			daddr = kmap_atomic(sg_page(t), KM_SOFTIRQ0);
++			err = ablkcipher_add(daddr, &dlen, src, slen, &nbytes);
++			if (err < 0)
++				goto err_out_unmap;
++
++			idx += err;
++
++			copy = slen & ~(blocksize - 1);
++			diff = slen & (blocksize - 1);
++
++			if (dlen < nbytes) {
++				/*
++				 * Destination page does not have enough space
++				 * to put there additional blocksized chunk,
++				 * so we mark that page as containing only
++				 * blocksize aligned chunks:
++				 * 	t->length = (slen & ~(blocksize - 1));
++				 * and increase number of bytes to be processed
++				 * in next chunk:
++				 * 	nbytes += diff;
++				 */
++				nbytes += diff;
++
++				/*
++				 * Temporary of course...
++				 * Kick author if you will catch this one.
++				 */
++				printk(KERN_ERR "%s: dlen: %u, nbytes: %u,"
++					"slen: %u, offset: %u.\n",
++					__func__, dlen, nbytes, slen, offset);
++				printk(KERN_ERR "%s: please contact author to fix this "
++					"issue, generally you should not catch "
++					"this path under any condition but who "
++					"knows how did you use crypto code.\n"
++					"Thank you.\n",	__func__);
++				BUG();
++			} else {
++				copy += diff + nbytes;
++
++				src = &req->src[idx];
++
++				err = ablkcipher_add(daddr + slen, &dlen, src, nbytes, &nbytes);
++				if (err < 0)
++					goto err_out_unmap;
++
++				idx += err;
++			}
++
++			t->length = copy;
++			t->offset = offset;
++
++			kunmap_atomic(daddr, KM_SOFTIRQ0);
++		} else {
++			nbytes -= src->length;
++			idx++;
 +		}
++
++		tidx++;
 +	}
 +
-+	if (!mk)
-+		return;
++	return tidx;
 +
-+	/* Don't check return codes; these calls are idempotent */
-+	no_warn = sysfs_create_link(&drv->p->kobj, &mk->kobj, "module");
-+	driver_name = make_driver_name(drv);
-+	if (driver_name) {
-+		module_create_drivers_dir(mk);
-+		no_warn = sysfs_create_link(mk->drivers_dir, &drv->p->kobj,
-+					    driver_name);
-+		kfree(driver_name);
-+	}
++err_out_unmap:
++	kunmap_atomic(daddr, KM_SOFTIRQ0);
++	return err;
 +}
 +
-+void module_remove_driver(struct device_driver *drv)
++static int hifn_setup_session(struct ablkcipher_request *req)
 +{
-+	struct module_kobject *mk = NULL;
-+	char *driver_name;
++	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
++	struct hifn_device *dev = ctx->dev;
++	struct page *spage, *dpage;
++	unsigned long soff, doff, flags;
++	unsigned int nbytes = req->nbytes, idx = 0, len;
++	int err = -EINVAL, sg_num;
++	struct scatterlist *src, *dst, *t;
++	unsigned blocksize =
++		crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(req));
++	unsigned alignmask =
++		crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
 +
-+	if (!drv)
-+		return;
++	if (ctx->iv && !ctx->ivsize && ctx->mode != ACRYPTO_MODE_ECB)
++		goto err_out_exit;
 +
-+	sysfs_remove_link(&drv->p->kobj, "module");
++	ctx->walk.flags = 0;
 +
-+	if (drv->owner)
-+		mk = &drv->owner->mkobj;
-+	else if (drv->p->mkobj)
-+		mk = drv->p->mkobj;
-+	if (mk && mk->drivers_dir) {
-+		driver_name = make_driver_name(drv);
-+		if (driver_name) {
-+			sysfs_remove_link(mk->drivers_dir, driver_name);
-+			kfree(driver_name);
++	while (nbytes) {
++		src = &req->src[idx];
++		dst = &req->dst[idx];
++
++		if (src->length & (blocksize - 1) ||
++				src->offset & (alignmask - 1) ||
++				dst->length & (blocksize - 1) ||
++				dst->offset & (alignmask - 1)) {
++			ctx->walk.flags |= ASYNC_FLAGS_MISALIGNED;
 +		}
++
++		nbytes -= src->length;
++		idx++;
 +	}
-+}
-diff --git a/drivers/base/node.c b/drivers/base/node.c
-index 88eeed7..e59861f 100644
---- a/drivers/base/node.c
-+++ b/drivers/base/node.c
-@@ -15,7 +15,7 @@
- #include <linux/device.h>
- 
- static struct sysdev_class node_class = {
--	set_kset_name("node"),
-+	.name = "node",
- };
- 
- 
-diff --git a/drivers/base/platform.c b/drivers/base/platform.c
-index fb56092..efaf282 100644
---- a/drivers/base/platform.c
-+++ b/drivers/base/platform.c
-@@ -20,7 +20,8 @@
- 
- #include "base.h"
- 
--#define to_platform_driver(drv)	(container_of((drv), struct platform_driver, driver))
-+#define to_platform_driver(drv)	(container_of((drv), struct platform_driver, \
-+				 driver))
- 
- struct device platform_bus = {
- 	.bus_id		= "platform",
-@@ -28,14 +29,13 @@ struct device platform_bus = {
- EXPORT_SYMBOL_GPL(platform_bus);
- 
- /**
-- *	platform_get_resource - get a resource for a device
-- *	@dev: platform device
-- *	@type: resource type
-- *	@num: resource index
-+ * platform_get_resource - get a resource for a device
-+ * @dev: platform device
-+ * @type: resource type
-+ * @num: resource index
-  */
--struct resource *
--platform_get_resource(struct platform_device *dev, unsigned int type,
--		      unsigned int num)
-+struct resource *platform_get_resource(struct platform_device *dev,
-+				       unsigned int type, unsigned int num)
- {
- 	int i;
- 
-@@ -43,8 +43,7 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
- 		struct resource *r = &dev->resource[i];
- 
- 		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
--				 IORESOURCE_IRQ|IORESOURCE_DMA))
--		    == type)
-+				 IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
- 			if (num-- == 0)
- 				return r;
- 	}
-@@ -53,9 +52,9 @@ platform_get_resource(struct platform_device *dev, unsigned int type,
- EXPORT_SYMBOL_GPL(platform_get_resource);
- 
- /**
-- *	platform_get_irq - get an IRQ for a device
-- *	@dev: platform device
-- *	@num: IRQ number index
-+ * platform_get_irq - get an IRQ for a device
-+ * @dev: platform device
-+ * @num: IRQ number index
-  */
- int platform_get_irq(struct platform_device *dev, unsigned int num)
- {
-@@ -66,14 +65,13 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
- EXPORT_SYMBOL_GPL(platform_get_irq);
- 
- /**
-- *	platform_get_resource_byname - get a resource for a device by name
-- *	@dev: platform device
-- *	@type: resource type
-- *	@name: resource name
-+ * platform_get_resource_byname - get a resource for a device by name
-+ * @dev: platform device
-+ * @type: resource type
-+ * @name: resource name
-  */
--struct resource *
--platform_get_resource_byname(struct platform_device *dev, unsigned int type,
--		      char *name)
-+struct resource *platform_get_resource_byname(struct platform_device *dev,
-+					      unsigned int type, char *name)
- {
- 	int i;
- 
-@@ -90,22 +88,23 @@ platform_get_resource_byname(struct platform_device *dev, unsigned int type,
- EXPORT_SYMBOL_GPL(platform_get_resource_byname);
- 
- /**
-- *	platform_get_irq - get an IRQ for a device
-- *	@dev: platform device
-- *	@name: IRQ name
-+ * platform_get_irq - get an IRQ for a device
-+ * @dev: platform device
-+ * @name: IRQ name
-  */
- int platform_get_irq_byname(struct platform_device *dev, char *name)
- {
--	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
-+	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
-+							  name);
- 
- 	return r ? r->start : -ENXIO;
- }
- EXPORT_SYMBOL_GPL(platform_get_irq_byname);
- 
- /**
-- *	platform_add_devices - add a numbers of platform devices
-- *	@devs: array of platform devices to add
-- *	@num: number of platform devices in array
-+ * platform_add_devices - add a numbers of platform devices
-+ * @devs: array of platform devices to add
-+ * @num: number of platform devices in array
-  */
- int platform_add_devices(struct platform_device **devs, int num)
- {
-@@ -130,12 +129,11 @@ struct platform_object {
- };
- 
- /**
-- *	platform_device_put
-- *	@pdev:	platform device to free
-+ * platform_device_put
-+ * @pdev: platform device to free
-  *
-- *	Free all memory associated with a platform device.  This function
-- *	must _only_ be externally called in error cases.  All other usage
-- *	is a bug.
-+ * Free all memory associated with a platform device.  This function must
-+ * _only_ be externally called in error cases.  All other usage is a bug.
-  */
- void platform_device_put(struct platform_device *pdev)
- {
-@@ -146,7 +144,8 @@ EXPORT_SYMBOL_GPL(platform_device_put);
- 
- static void platform_device_release(struct device *dev)
- {
--	struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev);
-+	struct platform_object *pa = container_of(dev, struct platform_object,
-+						  pdev.dev);
- 
- 	kfree(pa->pdev.dev.platform_data);
- 	kfree(pa->pdev.resource);
-@@ -154,12 +153,12 @@ static void platform_device_release(struct device *dev)
- }
- 
- /**
-- *	platform_device_alloc
-- *	@name:	base name of the device we're adding
-- *	@id:    instance id
-+ * platform_device_alloc
-+ * @name: base name of the device we're adding
-+ * @id: instance id
-  *
-- *	Create a platform device object which can have other objects attached
-- *	to it, and which will have attached objects freed when it is released.
-+ * Create a platform device object which can have other objects attached
-+ * to it, and which will have attached objects freed when it is released.
-  */
- struct platform_device *platform_device_alloc(const char *name, int id)
- {
-@@ -179,16 +178,17 @@ struct platform_device *platform_device_alloc(const char *name, int id)
- EXPORT_SYMBOL_GPL(platform_device_alloc);
- 
- /**
-- *	platform_device_add_resources
-- *	@pdev:	platform device allocated by platform_device_alloc to add resources to
-- *	@res:   set of resources that needs to be allocated for the device
-- *	@num:	number of resources
-+ * platform_device_add_resources
-+ * @pdev: platform device allocated by platform_device_alloc to add resources to
-+ * @res: set of resources that needs to be allocated for the device
-+ * @num: number of resources
-  *
-- *	Add a copy of the resources to the platform device.  The memory
-- *	associated with the resources will be freed when the platform
-- *	device is released.
-+ * Add a copy of the resources to the platform device.  The memory
-+ * associated with the resources will be freed when the platform device is
-+ * released.
-  */
--int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num)
-+int platform_device_add_resources(struct platform_device *pdev,
-+				  struct resource *res, unsigned int num)
- {
- 	struct resource *r;
- 
-@@ -203,16 +203,17 @@ int platform_device_add_resources(struct platform_device *pdev, struct resource
- EXPORT_SYMBOL_GPL(platform_device_add_resources);
- 
- /**
-- *	platform_device_add_data
-- *	@pdev:	platform device allocated by platform_device_alloc to add resources to
-- *	@data:	platform specific data for this platform device
-- *	@size:	size of platform specific data
-+ * platform_device_add_data
-+ * @pdev: platform device allocated by platform_device_alloc to add resources to
-+ * @data: platform specific data for this platform device
-+ * @size: size of platform specific data
-  *
-- *	Add a copy of platform specific data to the platform device's platform_data
-- *	pointer.  The memory associated with the platform data will be freed
-- *	when the platform device is released.
-+ * Add a copy of platform specific data to the platform device's
-+ * platform_data pointer.  The memory associated with the platform data
-+ * will be freed when the platform device is released.
-  */
--int platform_device_add_data(struct platform_device *pdev, const void *data, size_t size)
-+int platform_device_add_data(struct platform_device *pdev, const void *data,
-+			     size_t size)
- {
- 	void *d;
- 
-@@ -226,11 +227,11 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, siz
- EXPORT_SYMBOL_GPL(platform_device_add_data);
- 
- /**
-- *	platform_device_add - add a platform device to device hierarchy
-- *	@pdev:	platform device we're adding
-+ * platform_device_add - add a platform device to device hierarchy
-+ * @pdev: platform device we're adding
-  *
-- *	This is part 2 of platform_device_register(), though may be called
-- *	separately _iff_ pdev was allocated by platform_device_alloc().
-+ * This is part 2 of platform_device_register(), though may be called
-+ * separately _iff_ pdev was allocated by platform_device_alloc().
-  */
- int platform_device_add(struct platform_device *pdev)
- {
-@@ -289,13 +290,12 @@ int platform_device_add(struct platform_device *pdev)
- EXPORT_SYMBOL_GPL(platform_device_add);
- 
- /**
-- *	platform_device_del - remove a platform-level device
-- *	@pdev:	platform device we're removing
-+ * platform_device_del - remove a platform-level device
-+ * @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).  This function
-- *	must _only_ be externally called in error cases.  All other usage
-- *	is a bug.
-+ * Note that this function will also release all memory- and port-based
-+ * resources owned by the device (@dev->resource).  This function must
-+ * _only_ be externally called in error cases.  All other usage is a bug.
-  */
- void platform_device_del(struct platform_device *pdev)
- {
-@@ -314,11 +314,10 @@ void platform_device_del(struct platform_device *pdev)
- EXPORT_SYMBOL_GPL(platform_device_del);
- 
- /**
-- *	platform_device_register - add a platform-level device
-- *	@pdev:	platform device we're adding
-- *
-+ * platform_device_register - add a platform-level device
-+ * @pdev: platform device we're adding
-  */
--int platform_device_register(struct platform_device * pdev)
-+int platform_device_register(struct platform_device *pdev)
- {
- 	device_initialize(&pdev->dev);
- 	return platform_device_add(pdev);
-@@ -326,14 +325,14 @@ int platform_device_register(struct platform_device * pdev)
- EXPORT_SYMBOL_GPL(platform_device_register);
- 
- /**
-- *	platform_device_unregister - unregister a platform-level device
-- *	@pdev:	platform device we're unregistering
-+ * platform_device_unregister - unregister a platform-level device
-+ * @pdev: platform device we're unregistering
-  *
-- *	Unregistration is done in 2 steps. First we release all resources
-- *	and remove it from the subsystem, then we drop reference count by
-- *	calling platform_device_put().
-+ * Unregistration is done in 2 steps. First we release all resources
-+ * and remove it from the subsystem, then we drop reference count by
-+ * calling platform_device_put().
-  */
--void platform_device_unregister(struct platform_device * pdev)
-+void platform_device_unregister(struct platform_device *pdev)
- {
- 	platform_device_del(pdev);
- 	platform_device_put(pdev);
-@@ -341,27 +340,29 @@ void platform_device_unregister(struct platform_device * pdev)
- EXPORT_SYMBOL_GPL(platform_device_unregister);
- 
- /**
-- *	platform_device_register_simple
-- *	@name:  base name of the device we're adding
-- *	@id:    instance id
-- *	@res:   set of resources that needs to be allocated for the device
-- *	@num:	number of resources
-+ * platform_device_register_simple
-+ * @name: base name of the device we're adding
-+ * @id: instance id
-+ * @res: set of resources that needs to be allocated for the device
-+ * @num: number of resources
-  *
-- *	This function creates a simple platform device that requires minimal
-- *	resource and memory management. Canned release function freeing
-- *	memory allocated for the device allows drivers using such devices
-- *	to be unloaded without waiting for the last reference to the device
-- *	to be dropped.
-+ * This function creates a simple platform device that requires minimal
-+ * resource and memory management. Canned release function freeing memory
-+ * allocated for the device allows drivers using such devices to be
-+ * unloaded without waiting for the last reference to the device to be
-+ * dropped.
-  *
-- *	This interface is primarily intended for use with legacy drivers
-- *	which probe hardware directly.  Because such drivers create sysfs
-- *	device nodes themselves, rather than letting system infrastructure
-- *	handle such device enumeration tasks, they don't fully conform to
-- *	the Linux driver model.  In particular, when such drivers are built
-- *	as modules, they can't be "hotplugged".
-+ * This interface is primarily intended for use with legacy drivers which
-+ * probe hardware directly.  Because such drivers create sysfs device nodes
-+ * themselves, rather than letting system infrastructure handle such device
-+ * enumeration tasks, they don't fully conform to the Linux driver model.
-+ * In particular, when such drivers are built as modules, they can't be
-+ * "hotplugged".
-  */
--struct platform_device *platform_device_register_simple(char *name, int id,
--							struct resource *res, unsigned int num)
-+struct platform_device *platform_device_register_simple(const char *name,
-+							int id,
-+							struct resource *res,
-+							unsigned int num)
- {
- 	struct platform_device *pdev;
- 	int retval;
-@@ -436,8 +437,8 @@ static int platform_drv_resume(struct device *_dev)
- }
- 
- /**
-- *	platform_driver_register
-- *	@drv: platform driver structure
-+ * platform_driver_register
-+ * @drv: platform driver structure
-  */
- int platform_driver_register(struct platform_driver *drv)
- {
-@@ -457,8 +458,8 @@ int platform_driver_register(struct platform_driver *drv)
- EXPORT_SYMBOL_GPL(platform_driver_register);
- 
- /**
-- *	platform_driver_unregister
-- *	@drv: platform driver structure
-+ * platform_driver_unregister
-+ * @drv: platform driver structure
-  */
- void platform_driver_unregister(struct platform_driver *drv)
- {
-@@ -497,12 +498,12 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
- 	 * if the probe was successful, and make sure any forced probes of
- 	 * new devices fail.
- 	 */
--	spin_lock(&platform_bus_type.klist_drivers.k_lock);
-+	spin_lock(&platform_bus_type.p->klist_drivers.k_lock);
- 	drv->probe = NULL;
--	if (code == 0 && list_empty(&drv->driver.klist_devices.k_list))
-+	if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
- 		retval = -ENODEV;
- 	drv->driver.probe = platform_drv_probe_fail;
--	spin_unlock(&platform_bus_type.klist_drivers.k_lock);
-+	spin_unlock(&platform_bus_type.p->klist_drivers.k_lock);
- 
- 	if (code != retval)
- 		platform_driver_unregister(drv);
-@@ -516,8 +517,8 @@ EXPORT_SYMBOL_GPL(platform_driver_probe);
-  * (b) sysfs attribute lets new-style coldplug recover from hotplug events
-  *     mishandled before system is fully running:  "modprobe $(cat modalias)"
-  */
--static ssize_t
--modalias_show(struct device *dev, struct device_attribute *a, char *buf)
-+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
-+			     char *buf)
- {
- 	struct platform_device	*pdev = to_platform_device(dev);
- 	int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
-@@ -538,26 +539,24 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
- 	return 0;
- }
- 
--
- /**
-- *	platform_match - bind platform device to platform driver.
-- *	@dev:	device.
-- *	@drv:	driver.
-+ * platform_match - bind platform device to platform driver.
-+ * @dev: device.
-+ * @drv: driver.
-  *
-- *	Platform device IDs are assumed to be encoded like this:
-- *	"<name><instance>", where <name> is a short description of the
-- *	type of device, like "pci" or "floppy", and <instance> is the
-- *	enumerated instance of the device, like '0' or '42'.
-- *	Driver IDs are simply "<name>".
-- *	So, extract the <name> from the platform_device structure,
-- *	and compare it against the name of the driver. Return whether
-- *	they match or not.
-+ * Platform device IDs are assumed to be encoded like this:
-+ * "<name><instance>", where <name> is a short description of the type of
-+ * device, like "pci" or "floppy", and <instance> is the enumerated
-+ * instance of the device, like '0' or '42'.  Driver IDs are simply
-+ * "<name>".  So, extract the <name> from the platform_device structure,
-+ * and compare it against the name of the driver. Return whether they match
-+ * or not.
-  */
--
--static int platform_match(struct device * dev, struct device_driver * drv)
-+static int platform_match(struct device *dev, struct device_driver *drv)
- {
--	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
-+	struct platform_device *pdev;
- 
-+	pdev = container_of(dev, struct platform_device, dev);
- 	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
- }
- 
-@@ -574,9 +573,10 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
- static int platform_suspend_late(struct device *dev, pm_message_t mesg)
- {
- 	struct platform_driver *drv = to_platform_driver(dev->driver);
--	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
-+	struct platform_device *pdev;
- 	int ret = 0;
- 
-+	pdev = container_of(dev, struct platform_device, dev);
- 	if (dev->driver && drv->suspend_late)
- 		ret = drv->suspend_late(pdev, mesg);
- 
-@@ -586,16 +586,17 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
- static int platform_resume_early(struct device *dev)
- {
- 	struct platform_driver *drv = to_platform_driver(dev->driver);
--	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
-+	struct platform_device *pdev;
- 	int ret = 0;
- 
-+	pdev = container_of(dev, struct platform_device, dev);
- 	if (dev->driver && drv->resume_early)
- 		ret = drv->resume_early(pdev);
- 
- 	return ret;
- }
- 
--static int platform_resume(struct device * dev)
-+static int platform_resume(struct device *dev)
- {
- 	int ret = 0;
- 
-diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
-index 44504e6..911208b 100644
---- a/drivers/base/power/Makefile
-+++ b/drivers/base/power/Makefile
-@@ -1,11 +1,6 @@
--obj-y			:= shutdown.o
- obj-$(CONFIG_PM)	+= sysfs.o
- obj-$(CONFIG_PM_SLEEP)	+= main.o
--obj-$(CONFIG_PM_TRACE)	+= trace.o
-+obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
- 
--ifeq ($(CONFIG_DEBUG_DRIVER),y)
--EXTRA_CFLAGS += -DDEBUG
--endif
--ifeq ($(CONFIG_PM_VERBOSE),y)
--EXTRA_CFLAGS += -DDEBUG
--endif
-+ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
-+ccflags-$(CONFIG_PM_VERBOSE)   += -DDEBUG
-diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
-index 691ffb6..200ed5f 100644
---- a/drivers/base/power/main.c
-+++ b/drivers/base/power/main.c
-@@ -24,20 +24,45 @@
- #include <linux/mutex.h>
- #include <linux/pm.h>
- #include <linux/resume-trace.h>
-+#include <linux/rwsem.h>
- 
- #include "../base.h"
- #include "power.h"
- 
-+/*
-+ * The entries in the dpm_active list are in a depth first order, simply
-+ * because children are guaranteed to be discovered after parents, and
-+ * are inserted at the back of the list on discovery.
-+ *
-+ * All the other lists are kept in the same order, for consistency.
-+ * However the lists aren't always traversed in the same order.
-+ * Semaphores must be acquired from the top (i.e., front) down
-+ * and released in the opposite order.  Devices must be suspended
-+ * from the bottom (i.e., end) up and resumed in the opposite order.
-+ * That way no parent will be suspended while it still has an active
-+ * child.
-+ *
-+ * Since device_pm_add() may be called with a device semaphore held,
-+ * we must never try to acquire a device semaphore while holding
-+ * dpm_list_mutex.
-+ */
 +
- LIST_HEAD(dpm_active);
-+static LIST_HEAD(dpm_locked);
- static LIST_HEAD(dpm_off);
- static LIST_HEAD(dpm_off_irq);
-+static LIST_HEAD(dpm_destroy);
- 
--static DEFINE_MUTEX(dpm_mtx);
- static DEFINE_MUTEX(dpm_list_mtx);
- 
--int (*platform_enable_wakeup)(struct device *dev, int is_on);
-+static DECLARE_RWSEM(pm_sleep_rwsem);
- 
-+int (*platform_enable_wakeup)(struct device *dev, int is_on);
- 
-+/**
-+ *	device_pm_add - add a device to the list of active devices
-+ *	@dev:	Device to be added to the list
-+ */
- void device_pm_add(struct device *dev)
- {
- 	pr_debug("PM: Adding info for %s:%s\n",
-@@ -48,8 +73,36 @@ void device_pm_add(struct device *dev)
- 	mutex_unlock(&dpm_list_mtx);
- }
- 
-+/**
-+ *	device_pm_remove - remove a device from the list of active devices
-+ *	@dev:	Device to be removed from the list
-+ *
-+ *	This function also removes the device's PM-related sysfs attributes.
-+ */
- void device_pm_remove(struct device *dev)
- {
-+	/*
-+	 * If this function is called during a suspend, it will be blocked,
-+	 * because we're holding the device's semaphore at that time, which may
-+	 * lead to a deadlock.  In that case we want to print a warning.
-+	 * However, it may also be called by unregister_dropped_devices() with
-+	 * the device's semaphore released, in which case the warning should
-+	 * not be printed.
-+	 */
-+	if (down_trylock(&dev->sem)) {
-+		if (down_read_trylock(&pm_sleep_rwsem)) {
-+			/* No suspend in progress, wait on dev->sem */
-+			down(&dev->sem);
-+			up_read(&pm_sleep_rwsem);
++	if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) {
++		err = ablkcipher_walk_init(&ctx->walk, idx, GFP_ATOMIC);
++		if (err < 0)
++			return err;
++	}
++
++	nbytes = req->nbytes;
++	idx = 0;
++
++	sg_num = ablkcipher_walk(req, &ctx->walk);
++
++	atomic_set(&ctx->sg_num, sg_num);
++
++	spin_lock_irqsave(&dev->lock, flags);
++	if (dev->started + sg_num > HIFN_QUEUE_LENGTH) {
++		err = -EAGAIN;
++		goto err_out;
++	}
++
++	dev->snum++;
++	dev->started += sg_num;
++
++	while (nbytes) {
++		src = &req->src[idx];
++		dst = &req->dst[idx];
++		t = &ctx->walk.cache[idx];
++
++		if (t->length) {
++			spage = dpage = sg_page(t);
++			soff = doff = 0;
++			len = t->length;
 +		} else {
-+			/* Suspend in progress, we may deadlock */
-+			dev_warn(dev, "Suspicious %s during suspend\n",
-+				__FUNCTION__);
-+			dump_stack();
-+			/* The user has been warned ... */
-+			down(&dev->sem);
++			spage = sg_page(src);
++			soff = src->offset;
++
++			dpage = sg_page(dst);
++			doff = dst->offset;
++
++			len = dst->length;
 +		}
++
++		idx++;
++
++		err = hifn_setup_dma(dev, spage, soff, dpage, doff, nbytes,
++				req, ctx);
++		if (err)
++			goto err_out;
++
++		nbytes -= len;
 +	}
- 	pr_debug("PM: Removing info for %s:%s\n",
- 		 dev->bus ? dev->bus->name : "No Bus",
- 		 kobject_name(&dev->kobj));
-@@ -57,25 +110,124 @@ void device_pm_remove(struct device *dev)
- 	dpm_sysfs_remove(dev);
- 	list_del_init(&dev->power.entry);
- 	mutex_unlock(&dpm_list_mtx);
-+	up(&dev->sem);
++
++	dev->active = HIFN_DEFAULT_ACTIVE_NUM;
++	spin_unlock_irqrestore(&dev->lock, flags);
++
++	return 0;
++
++err_out:
++	spin_unlock_irqrestore(&dev->lock, flags);
++err_out_exit:
++	if (err && printk_ratelimit())
++		dprintk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
++				"type: %u, err: %d.\n",
++			dev->name, ctx->iv, ctx->ivsize,
++			ctx->key, ctx->keysize,
++			ctx->mode, ctx->op, ctx->type, err);
++
++	return err;
 +}
 +
-+/**
-+ *	device_pm_schedule_removal - schedule the removal of a suspended device
-+ *	@dev:	Device to destroy
-+ *
-+ *	Moves the device to the dpm_destroy list for further processing by
-+ *	unregister_dropped_devices().
-+ */
-+void device_pm_schedule_removal(struct device *dev)
++static int hifn_test(struct hifn_device *dev, int encdec, u8 snum)
 +{
-+	pr_debug("PM: Preparing for removal: %s:%s\n",
-+		dev->bus ? dev->bus->name : "No Bus",
-+		kobject_name(&dev->kobj));
-+	mutex_lock(&dpm_list_mtx);
-+	list_move_tail(&dev->power.entry, &dpm_destroy);
-+	mutex_unlock(&dpm_list_mtx);
++	int n, err;
++	u8 src[16];
++	struct hifn_context ctx;
++	u8 fips_aes_ecb_from_zero[16] = {
++		0x66, 0xE9, 0x4B, 0xD4,
++		0xEF, 0x8A, 0x2C, 0x3B,
++		0x88, 0x4C, 0xFA, 0x59,
++		0xCA, 0x34, 0x2B, 0x2E};
++
++	memset(src, 0, sizeof(src));
++	memset(ctx.key, 0, sizeof(ctx.key));
++
++	ctx.dev = dev;
++	ctx.keysize = 16;
++	ctx.ivsize = 0;
++	ctx.iv = NULL;
++	ctx.op = (encdec)?ACRYPTO_OP_ENCRYPT:ACRYPTO_OP_DECRYPT;
++	ctx.mode = ACRYPTO_MODE_ECB;
++	ctx.type = ACRYPTO_TYPE_AES_128;
++	atomic_set(&ctx.sg_num, 1);
++
++	err = hifn_setup_dma(dev,
++			virt_to_page(src), offset_in_page(src),
++			virt_to_page(src), offset_in_page(src),
++			sizeof(src), NULL, &ctx);
++	if (err)
++		goto err_out;
++
++	msleep(200);
++
++	dprintk("%s: decoded: ", dev->name);
++	for (n=0; n<sizeof(src); ++n)
++		dprintk("%02x ", src[n]);
++	dprintk("\n");
++	dprintk("%s: FIPS   : ", dev->name);
++	for (n=0; n<sizeof(fips_aes_ecb_from_zero); ++n)
++		dprintk("%02x ", fips_aes_ecb_from_zero[n]);
++	dprintk("\n");
++
++	if (!memcmp(src, fips_aes_ecb_from_zero, sizeof(fips_aes_ecb_from_zero))) {
++		printk(KERN_INFO "%s: AES 128 ECB test has been successfully "
++				"passed.\n", dev->name);
++		return 0;
++	}
++
++err_out:
++	printk(KERN_INFO "%s: AES 128 ECB test has been failed.\n", dev->name);
++	return -1;
 +}
 +
-+/**
-+ *	pm_sleep_lock - mutual exclusion for registration and suspend
-+ *
-+ *	Returns 0 if no suspend is underway and device registration
-+ *	may proceed, otherwise -EBUSY.
-+ */
-+int pm_sleep_lock(void)
++static int hifn_start_device(struct hifn_device *dev)
 +{
-+	if (down_read_trylock(&pm_sleep_rwsem))
-+		return 0;
++	int err;
 +
-+	return -EBUSY;
++	hifn_reset_dma(dev, 1);
++
++	err = hifn_enable_crypto(dev);
++	if (err)
++		return err;
++
++	hifn_reset_puc(dev);
++
++	hifn_init_dma(dev);
++
++	hifn_init_registers(dev);
++
++	hifn_init_pubrng(dev);
++
++	return 0;
 +}
 +
-+/**
-+ *	pm_sleep_unlock - mutual exclusion for registration and suspend
-+ *
-+ *	This routine undoes the effect of device_pm_add_lock
-+ *	when a device's registration is complete.
-+ */
-+void pm_sleep_unlock(void)
++static int ablkcipher_get(void *saddr, unsigned int *srestp, unsigned int offset,
++		struct scatterlist *dst, unsigned int size, unsigned int *nbytesp)
 +{
-+	up_read(&pm_sleep_rwsem);
- }
- 
- 
- /*------------------------- Resume routines -------------------------*/
- 
- /**
-- *	resume_device - Restore state for one device.
-+ *	resume_device_early - Power on one device (early resume).
-  *	@dev:	Device.
-  *
-+ *	Must be called with interrupts disabled.
-  */
--
--static int resume_device(struct device * dev)
-+static int resume_device_early(struct device *dev)
- {
- 	int error = 0;
- 
- 	TRACE_DEVICE(dev);
- 	TRACE_RESUME(0);
- 
--	down(&dev->sem);
-+	if (dev->bus && dev->bus->resume_early) {
-+		dev_dbg(dev, "EARLY resume\n");
-+		error = dev->bus->resume_early(dev);
++	unsigned int srest = *srestp, nbytes = *nbytesp, copy;
++	void *daddr;
++	int idx = 0;
++
++	if (srest < size || size > nbytes)
++		return -EINVAL;
++
++	while (size) {
++
++		copy = min(dst->length, srest);
++
++		daddr = kmap_atomic(sg_page(dst), KM_IRQ0);
++		memcpy(daddr + dst->offset + offset, saddr, copy);
++		kunmap_atomic(daddr, KM_IRQ0);
++
++		nbytes -= copy;
++		size -= copy;
++		srest -= copy;
++		saddr += copy;
++		offset = 0;
++
++		dprintk("%s: copy: %u, size: %u, srest: %u, nbytes: %u.\n",
++				__func__, copy, size, srest, nbytes);
++
++		dst++;
++		idx++;
++	}
++
++	*nbytesp = nbytes;
++	*srestp = srest;
++
++	return idx;
++}
++
++static void hifn_process_ready(struct ablkcipher_request *req, int error)
++{
++	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
++	struct hifn_device *dev;
++
++	dprintk("%s: req: %p, ctx: %p.\n", __func__, req, ctx);
++
++	dev = ctx->dev;
++	dprintk("%s: req: %p, started: %d, sg_num: %d.\n",
++		__func__, req, dev->started, atomic_read(&ctx->sg_num));
++
++	if (--dev->started < 0)
++		BUG();
++
++	if (atomic_dec_and_test(&ctx->sg_num)) {
++		unsigned int nbytes = req->nbytes;
++		int idx = 0, err;
++		struct scatterlist *dst, *t;
++		void *saddr;
++
++		if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) {
++			while (nbytes) {
++				t = &ctx->walk.cache[idx];
++				dst = &req->dst[idx];
++
++				dprintk("\n%s: sg_page(t): %p, t->length: %u, "
++					"sg_page(dst): %p, dst->length: %u, "
++					"nbytes: %u.\n",
++					__func__, sg_page(t), t->length,
++					sg_page(dst), dst->length, nbytes);
++
++				if (!t->length) {
++					nbytes -= dst->length;
++					idx++;
++					continue;
++				}
++
++				saddr = kmap_atomic(sg_page(t), KM_IRQ1);
++
++				err = ablkcipher_get(saddr, &t->length, t->offset,
++						dst, nbytes, &nbytes);
++				if (err < 0) {
++					kunmap_atomic(saddr, KM_IRQ1);
++					break;
++				}
++
++				idx += err;
++				kunmap_atomic(saddr, KM_IRQ1);
++			}
++
++			ablkcipher_walk_exit(&ctx->walk);
++		}
++
++		req->base.complete(&req->base, error);
++	}
++}
++
++static void hifn_check_for_completion(struct hifn_device *dev, int error)
++{
++	int i;
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++
++	for (i=0; i<HIFN_D_RES_RSIZE; ++i) {
++		struct hifn_desc *d = &dma->resr[i];
++
++		if (!(d->l & __cpu_to_le32(HIFN_D_VALID)) && dev->sa[i]) {
++			dev->success++;
++			dev->reset = 0;
++			hifn_process_ready(dev->sa[i], error);
++			dev->sa[i] = NULL;
++		}
++
++		if (d->l & __cpu_to_le32(HIFN_D_DESTOVER | HIFN_D_OVER))
++			if (printk_ratelimit())
++				printk("%s: overflow detected [d: %u, o: %u] "
++						"at %d resr: l: %08x, p: %08x.\n",
++					dev->name,
++					!!(d->l & __cpu_to_le32(HIFN_D_DESTOVER)),
++					!!(d->l & __cpu_to_le32(HIFN_D_OVER)),
++					i, d->l, d->p);
++	}
++}
++
++static void hifn_clear_rings(struct hifn_device *dev)
++{
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	int i, u;
++
++	dprintk("%s: ring cleanup 1: i: %d.%d.%d.%d, u: %d.%d.%d.%d, "
++			"k: %d.%d.%d.%d.\n",
++			dev->name,
++			dma->cmdi, dma->srci, dma->dsti, dma->resi,
++			dma->cmdu, dma->srcu, dma->dstu, dma->resu,
++			dma->cmdk, dma->srck, dma->dstk, dma->resk);
++
++	i = dma->resk; u = dma->resu;
++	while (u != 0) {
++		if (dma->resr[i].l & __cpu_to_le32(HIFN_D_VALID))
++			break;
++
++		if (i != HIFN_D_RES_RSIZE)
++			u--;
++
++		if (++i == (HIFN_D_RES_RSIZE + 1))
++			i = 0;
++	}
++	dma->resk = i; dma->resu = u;
++
++	i = dma->srck; u = dma->srcu;
++	while (u != 0) {
++		if (i == HIFN_D_SRC_RSIZE)
++			i = 0;
++		if (dma->srcr[i].l & __cpu_to_le32(HIFN_D_VALID))
++			break;
++		i++, u--;
++	}
++	dma->srck = i; dma->srcu = u;
++
++	i = dma->cmdk; u = dma->cmdu;
++	while (u != 0) {
++		if (dma->cmdr[i].l & __cpu_to_le32(HIFN_D_VALID))
++			break;
++		if (i != HIFN_D_CMD_RSIZE)
++			u--;
++		if (++i == (HIFN_D_CMD_RSIZE + 1))
++			i = 0;
++	}
++	dma->cmdk = i; dma->cmdu = u;
++
++	i = dma->dstk; u = dma->dstu;
++	while (u != 0) {
++		if (i == HIFN_D_DST_RSIZE)
++			i = 0;
++		if (dma->dstr[i].l & __cpu_to_le32(HIFN_D_VALID))
++			break;
++		i++, u--;
++	}
++	dma->dstk = i; dma->dstu = u;
++
++	dprintk("%s: ring cleanup 2: i: %d.%d.%d.%d, u: %d.%d.%d.%d, "
++			"k: %d.%d.%d.%d.\n",
++			dev->name,
++			dma->cmdi, dma->srci, dma->dsti, dma->resi,
++			dma->cmdu, dma->srcu, dma->dstu, dma->resu,
++			dma->cmdk, dma->srck, dma->dstk, dma->resk);
++}
++
++static void hifn_work(struct work_struct *work)
++{
++	struct delayed_work *dw = container_of(work, struct delayed_work, work);
++	struct hifn_device *dev = container_of(dw, struct hifn_device, work);
++	unsigned long flags;
++	int reset = 0;
++	u32 r = 0;
++
++	spin_lock_irqsave(&dev->lock, flags);
++	if (dev->active == 0) {
++		struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++
++		if (dma->cmdu == 0 && (dev->flags & HIFN_FLAG_CMD_BUSY)) {
++			dev->flags &= ~HIFN_FLAG_CMD_BUSY;
++			r |= HIFN_DMACSR_C_CTRL_DIS;
++		}
++		if (dma->srcu == 0 && (dev->flags & HIFN_FLAG_SRC_BUSY)) {
++			dev->flags &= ~HIFN_FLAG_SRC_BUSY;
++			r |= HIFN_DMACSR_S_CTRL_DIS;
++		}
++		if (dma->dstu == 0 && (dev->flags & HIFN_FLAG_DST_BUSY)) {
++			dev->flags &= ~HIFN_FLAG_DST_BUSY;
++			r |= HIFN_DMACSR_D_CTRL_DIS;
++		}
++		if (dma->resu == 0 && (dev->flags & HIFN_FLAG_RES_BUSY)) {
++			dev->flags &= ~HIFN_FLAG_RES_BUSY;
++			r |= HIFN_DMACSR_R_CTRL_DIS;
++		}
++		if (r)
++			hifn_write_1(dev, HIFN_1_DMA_CSR, r);
++	} else
++		dev->active--;
++
++	if (dev->prev_success == dev->success && dev->started)
++		reset = 1;
++	dev->prev_success = dev->success;
++	spin_unlock_irqrestore(&dev->lock, flags);
++
++	if (reset) {
++		dprintk("%s: r: %08x, active: %d, started: %d, "
++				"success: %lu: reset: %d.\n",
++			dev->name, r, dev->active, dev->started,
++			dev->success, reset);
++
++		if (++dev->reset >= 5) {
++			dprintk("%s: really hard reset.\n", dev->name);
++			hifn_reset_dma(dev, 1);
++			hifn_stop_device(dev);
++			hifn_start_device(dev);
++			dev->reset = 0;
++		}
++
++		spin_lock_irqsave(&dev->lock, flags);
++		hifn_check_for_completion(dev, -EBUSY);
++		hifn_clear_rings(dev);
++		dev->started = 0;
++		spin_unlock_irqrestore(&dev->lock, flags);
 +	}
 +
-+	TRACE_RESUME(error);
-+	return error;
-+}
++	schedule_delayed_work(&dev->work, HZ);
++}
++
++static irqreturn_t hifn_interrupt(int irq, void *data)
++{
++	struct hifn_device *dev = (struct hifn_device *)data;
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	u32 dmacsr, restart;
++
++	dmacsr = hifn_read_1(dev, HIFN_1_DMA_CSR);
++
++	dprintk("%s: 1 dmacsr: %08x, dmareg: %08x, res: %08x [%d], "
++			"i: %d.%d.%d.%d, u: %d.%d.%d.%d.\n",
++		dev->name, dmacsr, dev->dmareg, dmacsr & dev->dmareg, dma->cmdi,
++		dma->cmdu, dma->srcu, dma->dstu, dma->resu,
++		dma->cmdi, dma->srci, dma->dsti, dma->resi);
++
++	if ((dmacsr & dev->dmareg) == 0)
++		return IRQ_NONE;
++
++	hifn_write_1(dev, HIFN_1_DMA_CSR, dmacsr & dev->dmareg);
++
++	if (dmacsr & HIFN_DMACSR_ENGINE)
++		hifn_write_0(dev, HIFN_0_PUISR, hifn_read_0(dev, HIFN_0_PUISR));
++	if (dmacsr & HIFN_DMACSR_PUBDONE)
++		hifn_write_1(dev, HIFN_1_PUB_STATUS,
++			hifn_read_1(dev, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
 +
-+/**
-+ *	dpm_power_up - Power on all regular (non-sysdev) devices.
-+ *
-+ *	Walk the dpm_off_irq list and power each device up. This
-+ *	is used for devices that required they be powered down with
-+ *	interrupts disabled. As devices are powered on, they are moved
-+ *	to the dpm_off list.
-+ *
-+ *	Must be called with interrupts disabled and only one CPU running.
-+ */
-+static void dpm_power_up(void)
-+{
++	restart = dmacsr & (HIFN_DMACSR_R_OVER | HIFN_DMACSR_D_OVER);
++	if (restart) {
++		u32 puisr = hifn_read_0(dev, HIFN_0_PUISR);
 +
-+	while (!list_empty(&dpm_off_irq)) {
-+		struct list_head *entry = dpm_off_irq.next;
-+		struct device *dev = to_device(entry);
++		if (printk_ratelimit())
++			printk("%s: overflow: r: %d, d: %d, puisr: %08x, d: %u.\n",
++				dev->name, !!(dmacsr & HIFN_DMACSR_R_OVER),
++				!!(dmacsr & HIFN_DMACSR_D_OVER),
++				puisr, !!(puisr & HIFN_PUISR_DSTOVER));
++		if (!!(puisr & HIFN_PUISR_DSTOVER))
++			hifn_write_0(dev, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
++		hifn_write_1(dev, HIFN_1_DMA_CSR, dmacsr & (HIFN_DMACSR_R_OVER |
++					HIFN_DMACSR_D_OVER));
++	}
 +
-+		list_move_tail(entry, &dpm_off);
-+		resume_device_early(dev);
++	restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
++			HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
++	if (restart) {
++		if (printk_ratelimit())
++			printk("%s: abort: c: %d, s: %d, d: %d, r: %d.\n",
++				dev->name, !!(dmacsr & HIFN_DMACSR_C_ABORT),
++				!!(dmacsr & HIFN_DMACSR_S_ABORT),
++				!!(dmacsr & HIFN_DMACSR_D_ABORT),
++				!!(dmacsr & HIFN_DMACSR_R_ABORT));
++		hifn_reset_dma(dev, 1);
++		hifn_init_dma(dev);
++		hifn_init_registers(dev);
 +	}
-+}
 +
-+/**
-+ *	device_power_up - Turn on all devices that need special attention.
-+ *
-+ *	Power on system devices, then devices that required we shut them down
-+ *	with interrupts disabled.
-+ *
-+ *	Must be called with interrupts disabled.
-+ */
-+void device_power_up(void)
-+{
-+	sysdev_resume();
-+	dpm_power_up();
++	if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
++		dprintk("%s: wait on command.\n", dev->name);
++		dev->dmareg &= ~(HIFN_DMAIER_C_WAIT);
++		hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
++	}
++
++	tasklet_schedule(&dev->tasklet);
++	hifn_clear_rings(dev);
++
++	return IRQ_HANDLED;
 +}
-+EXPORT_SYMBOL_GPL(device_power_up);
 +
-+/**
-+ *	resume_device - Restore state for one device.
-+ *	@dev:	Device.
-+ *
-+ */
-+static int resume_device(struct device *dev)
++static void hifn_flush(struct hifn_device *dev)
 +{
-+	int error = 0;
++	unsigned long flags;
++	struct crypto_async_request *async_req;
++	struct hifn_context *ctx;
++	struct ablkcipher_request *req;
++	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	int i;
 +
-+	TRACE_DEVICE(dev);
-+	TRACE_RESUME(0);
- 
- 	if (dev->bus && dev->bus->resume) {
- 		dev_dbg(dev,"resuming\n");
-@@ -92,126 +244,94 @@ static int resume_device(struct device * dev)
- 		error = dev->class->resume(dev);
- 	}
- 
--	up(&dev->sem);
--
- 	TRACE_RESUME(error);
- 	return error;
- }
- 
--
--static int resume_device_early(struct device * dev)
--{
--	int error = 0;
--
--	TRACE_DEVICE(dev);
--	TRACE_RESUME(0);
--	if (dev->bus && dev->bus->resume_early) {
--		dev_dbg(dev,"EARLY resume\n");
--		error = dev->bus->resume_early(dev);
--	}
--	TRACE_RESUME(error);
--	return error;
--}
--
--/*
-- * Resume the devices that have either not gone through
-- * the late suspend, or that did go through it but also
-- * went through the early resume
-+/**
-+ *	dpm_resume - Resume every device.
-+ *
-+ *	Resume the devices that have either not gone through
-+ *	the late suspend, or that did go through it but also
-+ *	went through the early resume.
-+ *
-+ *	Take devices from the dpm_off_list, resume them,
-+ *	and put them on the dpm_locked list.
-  */
- static void dpm_resume(void)
- {
- 	mutex_lock(&dpm_list_mtx);
- 	while(!list_empty(&dpm_off)) {
--		struct list_head * entry = dpm_off.next;
--		struct device * dev = to_device(entry);
--
--		get_device(dev);
--		list_move_tail(entry, &dpm_active);
-+		struct list_head *entry = dpm_off.next;
-+		struct device *dev = to_device(entry);
- 
-+		list_move_tail(entry, &dpm_locked);
- 		mutex_unlock(&dpm_list_mtx);
- 		resume_device(dev);
- 		mutex_lock(&dpm_list_mtx);
--		put_device(dev);
- 	}
- 	mutex_unlock(&dpm_list_mtx);
- }
- 
--
- /**
-- *	device_resume - Restore state of each device in system.
-+ *	unlock_all_devices - Release each device's semaphore
-  *
-- *	Walk the dpm_off list, remove each entry, resume the device,
-- *	then add it to the dpm_active list.
-+ *	Go through the dpm_off list.  Put each device on the dpm_active
-+ *	list and unlock it.
-  */
--
--void device_resume(void)
-+static void unlock_all_devices(void)
- {
--	might_sleep();
--	mutex_lock(&dpm_mtx);
--	dpm_resume();
--	mutex_unlock(&dpm_mtx);
--}
--
--EXPORT_SYMBOL_GPL(device_resume);
-+	mutex_lock(&dpm_list_mtx);
-+	while (!list_empty(&dpm_locked)) {
-+		struct list_head *entry = dpm_locked.prev;
-+		struct device *dev = to_device(entry);
- 
-+		list_move(entry, &dpm_active);
-+		up(&dev->sem);
++	spin_lock_irqsave(&dev->lock, flags);
++	for (i=0; i<HIFN_D_RES_RSIZE; ++i) {
++		struct hifn_desc *d = &dma->resr[i];
++
++		if (dev->sa[i]) {
++			hifn_process_ready(dev->sa[i],
++				(d->l & __cpu_to_le32(HIFN_D_VALID))?-ENODEV:0);
++		}
 +	}
-+	mutex_unlock(&dpm_list_mtx);
-+}
- 
- /**
-- *	dpm_power_up - Power on some devices.
-- *
-- *	Walk the dpm_off_irq list and power each device up. This
-- *	is used for devices that required they be powered down with
-- *	interrupts disabled. As devices are powered on, they are moved
-- *	to the dpm_active list.
-+ *	unregister_dropped_devices - Unregister devices scheduled for removal
-  *
-- *	Interrupts must be disabled when calling this.
-+ *	Unregister all devices on the dpm_destroy list.
-  */
--
--static void dpm_power_up(void)
-+static void unregister_dropped_devices(void)
- {
--	while(!list_empty(&dpm_off_irq)) {
--		struct list_head * entry = dpm_off_irq.next;
--		struct device * dev = to_device(entry);
-+	mutex_lock(&dpm_list_mtx);
-+	while (!list_empty(&dpm_destroy)) {
-+		struct list_head *entry = dpm_destroy.next;
-+		struct device *dev = to_device(entry);
- 
--		list_move_tail(entry, &dpm_off);
--		resume_device_early(dev);
-+		up(&dev->sem);
-+		mutex_unlock(&dpm_list_mtx);
-+		/* This also removes the device from the list */
-+		device_unregister(dev);
-+		mutex_lock(&dpm_list_mtx);
- 	}
-+	mutex_unlock(&dpm_list_mtx);
- }
- 
--
- /**
-- *	device_power_up - Turn on all devices that need special attention.
-+ *	device_resume - Restore state of each device in system.
-  *
-- *	Power on system devices then devices that required we shut them down
-- *	with interrupts disabled.
-- *	Called with interrupts disabled.
-+ *	Resume all the devices, unlock them all, and allow new
-+ *	devices to be registered once again.
-  */
--
--void device_power_up(void)
-+void device_resume(void)
- {
--	sysdev_resume();
--	dpm_power_up();
-+	might_sleep();
-+	dpm_resume();
-+	unlock_all_devices();
-+	unregister_dropped_devices();
-+	up_write(&pm_sleep_rwsem);
- }
--
--EXPORT_SYMBOL_GPL(device_power_up);
-+EXPORT_SYMBOL_GPL(device_resume);
- 
- 
- /*------------------------- Suspend routines -------------------------*/
- 
--/*
-- * The entries in the dpm_active list are in a depth first order, simply
-- * because children are guaranteed to be discovered after parents, and
-- * are inserted at the back of the list on discovery.
-- *
-- * All list on the suspend path are done in reverse order, so we operate
-- * on the leaves of the device tree (or forests, depending on how you want
-- * to look at it ;) first. As nodes are removed from the back of the list,
-- * they are inserted into the front of their destintation lists.
-- *
-- * Things are the reverse on the resume path - iterations are done in
-- * forward order, and nodes are inserted at the back of their destination
-- * lists. This way, the ancestors will be accessed before their descendents.
-- */
--
- static inline char *suspend_verb(u32 event)
- {
- 	switch (event) {
-@@ -222,7 +342,6 @@ static inline char *suspend_verb(u32 event)
- 	}
- }
- 
--
- static void
- suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
- {
-@@ -232,16 +351,73 @@ suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
- }
- 
- /**
-- *	suspend_device - Save state of one device.
-+ *	suspend_device_late - Shut down one device (late suspend).
-  *	@dev:	Device.
-  *	@state:	Power state device is entering.
-+ *
-+ *	This is called with interrupts off and only a single CPU running.
-  */
-+static int suspend_device_late(struct device *dev, pm_message_t state)
-+{
-+	int error = 0;
- 
--static int suspend_device(struct device * dev, pm_message_t state)
-+	if (dev->bus && dev->bus->suspend_late) {
-+		suspend_device_dbg(dev, state, "LATE ");
-+		error = dev->bus->suspend_late(dev, state);
-+		suspend_report_result(dev->bus->suspend_late, error);
++
++	while ((async_req = crypto_dequeue_request(&dev->queue))) {
++		ctx = crypto_tfm_ctx(async_req->tfm);
++		req = container_of(async_req, struct ablkcipher_request, base);
++
++		hifn_process_ready(req, -ENODEV);
 +	}
-+	return error;
++	spin_unlock_irqrestore(&dev->lock, flags);
 +}
 +
-+/**
-+ *	device_power_down - Shut down special devices.
-+ *	@state:		Power state to enter.
-+ *
-+ *	Power down devices that require interrupts to be disabled
-+ *	and move them from the dpm_off list to the dpm_off_irq list.
-+ *	Then power down system devices.
-+ *
-+ *	Must be called with interrupts disabled and only one CPU running.
-+ */
-+int device_power_down(pm_message_t state)
++static int hifn_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
++		unsigned int len)
 +{
-+	int error = 0;
++	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
++	struct hifn_context *ctx = crypto_tfm_ctx(tfm);
++	struct hifn_device *dev = ctx->dev;
 +
-+	while (!list_empty(&dpm_off)) {
-+		struct list_head *entry = dpm_off.prev;
-+		struct device *dev = to_device(entry);
++	if (len > HIFN_MAX_CRYPT_KEY_LENGTH) {
++		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
++		return -1;
++	}
 +
-+		list_del_init(&dev->power.entry);
-+		error = suspend_device_late(dev, state);
-+		if (error) {
-+			printk(KERN_ERR "Could not power down device %s: "
-+					"error %d\n",
-+					kobject_name(&dev->kobj), error);
-+			if (list_empty(&dev->power.entry))
-+				list_add(&dev->power.entry, &dpm_off);
-+			break;
++	if (len == HIFN_DES_KEY_LENGTH) {
++		u32 tmp[DES_EXPKEY_WORDS];
++		int ret = des_ekey(tmp, key);
++		
++		if (unlikely(ret == 0) && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
++			tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
++			return -EINVAL;
 +		}
-+		if (list_empty(&dev->power.entry))
-+			list_add(&dev->power.entry, &dpm_off_irq);
 +	}
 +
-+	if (!error)
-+		error = sysdev_suspend(state);
-+	if (error)
-+		dpm_power_up();
-+	return error;
-+}
-+EXPORT_SYMBOL_GPL(device_power_down);
++	dev->flags &= ~HIFN_FLAG_OLD_KEY;
 +
-+/**
-+ *	suspend_device - Save state of one device.
-+ *	@dev:	Device.
-+ *	@state:	Power state device is entering.
-+ */
-+int suspend_device(struct device *dev, pm_message_t state)
- {
- 	int error = 0;
- 
--	down(&dev->sem);
- 	if (dev->power.power_state.event) {
- 		dev_dbg(dev, "PM: suspend %d-->%d\n",
- 			dev->power.power_state.event, state.event);
-@@ -264,123 +440,105 @@ static int suspend_device(struct device * dev, pm_message_t state)
- 		error = dev->bus->suspend(dev, state);
- 		suspend_report_result(dev->bus->suspend, error);
- 	}
--	up(&dev->sem);
--	return error;
--}
--
--
--/*
-- * This is called with interrupts off, only a single CPU
-- * running. We can't acquire a mutex or semaphore (and we don't
-- * need the protection)
-- */
--static int suspend_device_late(struct device *dev, pm_message_t state)
--{
--	int error = 0;
--
--	if (dev->bus && dev->bus->suspend_late) {
--		suspend_device_dbg(dev, state, "LATE ");
--		error = dev->bus->suspend_late(dev, state);
--		suspend_report_result(dev->bus->suspend_late, error);
--	}
- 	return error;
- }
- 
- /**
-- *	device_suspend - Save state and stop all devices in system.
-- *	@state:		Power state to put each device in.
-+ *	dpm_suspend - Suspend every device.
-+ *	@state:	Power state to put each device in.
-  *
-- *	Walk the dpm_active list, call ->suspend() for each device, and move
-- *	it to the dpm_off list.
-+ *	Walk the dpm_locked list.  Suspend each device and move it
-+ *	to the dpm_off list.
-  *
-  *	(For historical reasons, if it returns -EAGAIN, that used to mean
-  *	that the device would be called again with interrupts disabled.
-  *	These days, we use the "suspend_late()" callback for that, so we
-  *	print a warning and consider it an error).
-- *
-- *	If we get a different error, try and back out.
-- *
-- *	If we hit a failure with any of the devices, call device_resume()
-- *	above to bring the suspended devices back to life.
-- *
-  */
--
--int device_suspend(pm_message_t state)
-+static int dpm_suspend(pm_message_t state)
- {
- 	int error = 0;
- 
--	might_sleep();
--	mutex_lock(&dpm_mtx);
- 	mutex_lock(&dpm_list_mtx);
--	while (!list_empty(&dpm_active) && error == 0) {
--		struct list_head * entry = dpm_active.prev;
--		struct device * dev = to_device(entry);
-+	while (!list_empty(&dpm_locked)) {
-+		struct list_head *entry = dpm_locked.prev;
-+		struct device *dev = to_device(entry);
- 
--		get_device(dev);
-+		list_del_init(&dev->power.entry);
- 		mutex_unlock(&dpm_list_mtx);
--
- 		error = suspend_device(dev, state);
--
--		mutex_lock(&dpm_list_mtx);
--
--		/* Check if the device got removed */
--		if (!list_empty(&dev->power.entry)) {
--			/* Move it to the dpm_off list */
--			if (!error)
--				list_move(&dev->power.entry, &dpm_off);
--		}
--		if (error)
-+		if (error) {
- 			printk(KERN_ERR "Could not suspend device %s: "
--				"error %d%s\n",
--				kobject_name(&dev->kobj), error,
--				error == -EAGAIN ? " (please convert to suspend_late)" : "");
--		put_device(dev);
-+					"error %d%s\n",
-+					kobject_name(&dev->kobj),
-+					error,
-+					(error == -EAGAIN ?
-+					" (please convert to suspend_late)" :
-+					""));
-+			mutex_lock(&dpm_list_mtx);
-+			if (list_empty(&dev->power.entry))
-+				list_add(&dev->power.entry, &dpm_locked);
-+			mutex_unlock(&dpm_list_mtx);
-+			break;
-+		}
-+		mutex_lock(&dpm_list_mtx);
-+		if (list_empty(&dev->power.entry))
-+			list_add(&dev->power.entry, &dpm_off);
- 	}
- 	mutex_unlock(&dpm_list_mtx);
--	if (error)
--		dpm_resume();
- 
--	mutex_unlock(&dpm_mtx);
- 	return error;
- }
- 
--EXPORT_SYMBOL_GPL(device_suspend);
--
- /**
-- *	device_power_down - Shut down special devices.
-- *	@state:		Power state to enter.
-+ *	lock_all_devices - Acquire every device's semaphore
-  *
-- *	Walk the dpm_off_irq list, calling ->power_down() for each device that
-- *	couldn't power down the device with interrupts enabled. When we're
-- *	done, power down system devices.
-+ *	Go through the dpm_active list. Carefully lock each device's
-+ *	semaphore and put it in on the dpm_locked list.
-  */
--
--int device_power_down(pm_message_t state)
-+static void lock_all_devices(void)
- {
--	int error = 0;
--	struct device * dev;
-+	mutex_lock(&dpm_list_mtx);
-+	while (!list_empty(&dpm_active)) {
-+		struct list_head *entry = dpm_active.next;
-+		struct device *dev = to_device(entry);
- 
--	while (!list_empty(&dpm_off)) {
--		struct list_head * entry = dpm_off.prev;
-+		/* Required locking order is dev->sem first,
-+		 * then dpm_list_mutex.  Hence this awkward code.
-+		 */
-+		get_device(dev);
-+		mutex_unlock(&dpm_list_mtx);
-+		down(&dev->sem);
-+		mutex_lock(&dpm_list_mtx);
- 
--		dev = to_device(entry);
--		error = suspend_device_late(dev, state);
--		if (error)
--			goto Error;
--		list_move(&dev->power.entry, &dpm_off_irq);
-+		if (list_empty(entry))
-+			up(&dev->sem);		/* Device was removed */
-+		else
-+			list_move_tail(entry, &dpm_locked);
-+		put_device(dev);
- 	}
-+	mutex_unlock(&dpm_list_mtx);
-+}
++	memcpy(ctx->key, key, len);
++	ctx->keysize = len;
 +
-+/**
-+ *	device_suspend - Save state and stop all devices in system.
-+ *
-+ *	Prevent new devices from being registered, then lock all devices
-+ *	and suspend them.
-+ */
-+int device_suspend(pm_message_t state)
-+{
-+	int error;
- 
--	error = sysdev_suspend(state);
-- Done:
-+	might_sleep();
-+	down_write(&pm_sleep_rwsem);
-+	lock_all_devices();
-+	error = dpm_suspend(state);
-+	if (error)
-+		device_resume();
- 	return error;
-- Error:
--	printk(KERN_ERR "Could not power down device %s: "
--		"error %d\n", kobject_name(&dev->kobj), error);
--	dpm_power_up();
--	goto Done;
- }
--
--EXPORT_SYMBOL_GPL(device_power_down);
-+EXPORT_SYMBOL_GPL(device_suspend);
- 
- void __suspend_report_result(const char *function, void *fn, int ret)
- {
-diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
-index 379da4e..6f0dfca 100644
---- a/drivers/base/power/power.h
-+++ b/drivers/base/power/power.h
-@@ -1,10 +1,3 @@
--/*
-- * shutdown.c
-- */
--
--extern void device_shutdown(void);
--
--
- #ifdef CONFIG_PM_SLEEP
- 
- /*
-@@ -20,6 +13,9 @@ static inline struct device *to_device(struct list_head *entry)
- 
- extern void device_pm_add(struct device *);
- extern void device_pm_remove(struct device *);
-+extern void device_pm_schedule_removal(struct device *);
-+extern int pm_sleep_lock(void);
-+extern void pm_sleep_unlock(void);
- 
- #else /* CONFIG_PM_SLEEP */
- 
-@@ -32,6 +28,15 @@ static inline void device_pm_remove(struct device *dev)
- {
- }
- 
-+static inline int pm_sleep_lock(void)
-+{
 +	return 0;
 +}
 +
-+static inline void pm_sleep_unlock(void)
++static int hifn_handle_req(struct ablkcipher_request *req)
 +{
-+}
-+
- #endif
- 
- #ifdef CONFIG_PM
-diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
-deleted file mode 100644
-index 56e8eaa..0000000
---- a/drivers/base/power/shutdown.c
-+++ /dev/null
-@@ -1,48 +0,0 @@
--/*
-- * shutdown.c - power management functions for the device tree.
-- *
-- * Copyright (c) 2002-3 Patrick Mochel
-- *		 2002-3 Open Source Development Lab
-- *
-- * This file is released under the GPLv2
-- *
-- */
--
--#include <linux/device.h>
--#include <asm/semaphore.h>
--
--#include "../base.h"
--#include "power.h"
--
--#define to_dev(node) container_of(node, struct device, kobj.entry)
--
--
--/**
-- * We handle system devices differently - we suspend and shut them
-- * down last and resume them first. That way, we don't do anything stupid like
-- * shutting down the interrupt controller before any devices..
-- *
-- * Note that there are not different stages for power management calls -
-- * they only get one called once when interrupts are disabled.
-- */
--
--
--/**
-- * device_shutdown - call ->shutdown() on each device to shutdown.
-- */
--void device_shutdown(void)
--{
--	struct device * dev, *devn;
--
--	list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.list,
--				kobj.entry) {
--		if (dev->bus && dev->bus->shutdown) {
--			dev_dbg(dev, "shutdown\n");
--			dev->bus->shutdown(dev);
--		} else if (dev->driver && dev->driver->shutdown) {
--			dev_dbg(dev, "shutdown\n");
--			dev->driver->shutdown(dev);
--		}
--	}
--}
--
-diff --git a/drivers/base/sys.c b/drivers/base/sys.c
-index ac7ff6d..2f79c55 100644
---- a/drivers/base/sys.c
-+++ b/drivers/base/sys.c
-@@ -25,8 +25,6 @@
- 
- #include "base.h"
- 
--extern struct kset devices_subsys;
--
- #define to_sysdev(k) container_of(k, struct sys_device, kobj)
- #define to_sysdev_attr(a) container_of(a, struct sysdev_attribute, attr)
- 
-@@ -128,18 +126,17 @@ void sysdev_class_remove_file(struct sysdev_class *c,
- }
- EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
- 
--/*
-- * declare system_subsys
-- */
--static decl_subsys(system, &ktype_sysdev_class, NULL);
-+static struct kset *system_kset;
- 
- int sysdev_class_register(struct sysdev_class * cls)
- {
- 	pr_debug("Registering sysdev class '%s'\n",
- 		 kobject_name(&cls->kset.kobj));
- 	INIT_LIST_HEAD(&cls->drivers);
--	cls->kset.kobj.parent = &system_subsys.kobj;
--	cls->kset.kobj.kset = &system_subsys;
-+	cls->kset.kobj.parent = &system_kset->kobj;
-+	cls->kset.kobj.ktype = &ktype_sysdev_class;
-+	cls->kset.kobj.kset = system_kset;
-+	kobject_set_name(&cls->kset.kobj, cls->name);
- 	return kset_register(&cls->kset);
- }
- 
-@@ -228,20 +225,15 @@ int sysdev_register(struct sys_device * sysdev)
- 	if (!cls)
- 		return -EINVAL;
- 
-+	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
-+
- 	/* Make sure the kset is set */
- 	sysdev->kobj.kset = &cls->kset;
- 
--	/* But make sure we point to the right type for sysfs translation */
--	sysdev->kobj.ktype = &ktype_sysdev;
--	error = kobject_set_name(&sysdev->kobj, "%s%d",
--			 kobject_name(&cls->kset.kobj), sysdev->id);
--	if (error)
--		return error;
--
--	pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj));
--
- 	/* Register the object */
--	error = kobject_register(&sysdev->kobj);
-+	error = kobject_init_and_add(&sysdev->kobj, &ktype_sysdev, NULL,
-+				     "%s%d", kobject_name(&cls->kset.kobj),
-+				     sysdev->id);
- 
- 	if (!error) {
- 		struct sysdev_driver * drv;
-@@ -258,6 +250,7 @@ int sysdev_register(struct sys_device * sysdev)
- 		}
- 		mutex_unlock(&sysdev_drivers_lock);
- 	}
-+	kobject_uevent(&sysdev->kobj, KOBJ_ADD);
- 	return error;
- }
- 
-@@ -272,7 +265,7 @@ void sysdev_unregister(struct sys_device * sysdev)
- 	}
- 	mutex_unlock(&sysdev_drivers_lock);
- 
--	kobject_unregister(&sysdev->kobj);
-+	kobject_put(&sysdev->kobj);
- }
- 
- 
-@@ -298,8 +291,7 @@ void sysdev_shutdown(void)
- 	pr_debug("Shutting Down System Devices\n");
- 
- 	mutex_lock(&sysdev_drivers_lock);
--	list_for_each_entry_reverse(cls, &system_subsys.list,
--				    kset.kobj.entry) {
-+	list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
- 		struct sys_device * sysdev;
- 
- 		pr_debug("Shutting down type '%s':\n",
-@@ -361,9 +353,7 @@ int sysdev_suspend(pm_message_t state)
- 
- 	pr_debug("Suspending System Devices\n");
- 
--	list_for_each_entry_reverse(cls, &system_subsys.list,
--				    kset.kobj.entry) {
--
-+	list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
- 		pr_debug("Suspending type '%s':\n",
- 			 kobject_name(&cls->kset.kobj));
- 
-@@ -414,8 +404,7 @@ aux_driver:
- 	}
- 
- 	/* resume other classes */
--	list_for_each_entry_continue(cls, &system_subsys.list,
--					kset.kobj.entry) {
-+	list_for_each_entry_continue(cls, &system_kset->list, kset.kobj.entry) {
- 		list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
- 			pr_debug(" %s\n", kobject_name(&err_dev->kobj));
- 			__sysdev_resume(err_dev);
-@@ -440,7 +429,7 @@ int sysdev_resume(void)
- 
- 	pr_debug("Resuming System Devices\n");
- 
--	list_for_each_entry(cls, &system_subsys.list, kset.kobj.entry) {
-+	list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
- 		struct sys_device * sysdev;
- 
- 		pr_debug("Resuming type '%s':\n",
-@@ -458,8 +447,10 @@ int sysdev_resume(void)
- 
- int __init system_bus_init(void)
- {
--	system_subsys.kobj.parent = &devices_subsys.kobj;
--	return subsystem_register(&system_subsys);
-+	system_kset = kset_create_and_add("system", NULL, &devices_kset->kobj);
-+	if (!system_kset)
-+		return -ENOMEM;
-+	return 0;
- }
- 
- EXPORT_SYMBOL_GPL(sysdev_register);
-diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
-index 9030c37..cd03473 100644
---- a/drivers/block/DAC960.c
-+++ b/drivers/block/DAC960.c
-@@ -3455,19 +3455,12 @@ static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
- 						 bool SuccessfulIO)
- {
- 	struct request *Request = Command->Request;
--	int UpToDate;
--
--	UpToDate = 0;
--	if (SuccessfulIO)
--		UpToDate = 1;
-+	int Error = SuccessfulIO ? 0 : -EIO;
- 
- 	pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
- 		Command->SegmentCount, Command->DmaDirection);
- 
--	 if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
--		add_disk_randomness(Request->rq_disk);
-- 	 	end_that_request_last(Request, UpToDate);
--
-+	 if (!__blk_end_request(Request, Error, Command->BlockCount << 9)) {
- 		if (Command->Completion) {
- 			complete(Command->Completion);
- 			Command->Completion = NULL;
-diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
-index 4d0119e..f212285 100644
---- a/drivers/block/Kconfig
-+++ b/drivers/block/Kconfig
-@@ -105,6 +105,17 @@ config PARIDE
- 	  "MicroSolutions backpack protocol", "DataStor Commuter protocol"
- 	  etc.).
- 
-+config GDROM
-+	tristate "SEGA Dreamcast GD-ROM drive"
-+	depends on SH_DREAMCAST
-+	help
-+	  A standard SEGA Dreamcast comes with a modified CD ROM drive called a
-+	  "GD-ROM" by SEGA to signify it is capable of reading special disks
-+	  with up to 1 GB of data. This drive will also read standard CD ROM
-+	  disks. Select this option to access any disks in your GD ROM drive.
-+	  Most users will want to say "Y" here.
-+	  You can also build this as a module which will be called gdrom.ko
-+
- source "drivers/block/paride/Kconfig"
- 
- config BLK_CPQ_DA
-diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
-index ad00b3d..826d123 100644
---- a/drivers/block/aoe/aoeblk.c
-+++ b/drivers/block/aoe/aoeblk.c
-@@ -15,8 +15,10 @@
- 
- static struct kmem_cache *buf_pool_cache;
- 
--static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
-+static ssize_t aoedisk_show_state(struct device *dev,
-+				  struct device_attribute *attr, char *page)
- {
-+	struct gendisk *disk = dev_to_disk(dev);
- 	struct aoedev *d = disk->private_data;
- 
- 	return snprintf(page, PAGE_SIZE,
-@@ -26,50 +28,47 @@ static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
- 			(d->nopen && !(d->flags & DEVFL_UP)) ? ",closewait" : "");
- 	/* I'd rather see nopen exported so we can ditch closewait */
- }
--static ssize_t aoedisk_show_mac(struct gendisk * disk, char *page)
-+static ssize_t aoedisk_show_mac(struct device *dev,
-+				struct device_attribute *attr, char *page)
- {
-+	struct gendisk *disk = dev_to_disk(dev);
- 	struct aoedev *d = disk->private_data;
- 
- 	return snprintf(page, PAGE_SIZE, "%012llx\n",
- 			(unsigned long long)mac_addr(d->addr));
- }
--static ssize_t aoedisk_show_netif(struct gendisk * disk, char *page)
-+static ssize_t aoedisk_show_netif(struct device *dev,
-+				  struct device_attribute *attr, char *page)
- {
-+	struct gendisk *disk = dev_to_disk(dev);
- 	struct aoedev *d = disk->private_data;
- 
- 	return snprintf(page, PAGE_SIZE, "%s\n", d->ifp->name);
- }
- /* firmware version */
--static ssize_t aoedisk_show_fwver(struct gendisk * disk, char *page)
-+static ssize_t aoedisk_show_fwver(struct device *dev,
-+				  struct device_attribute *attr, char *page)
- {
-+	struct gendisk *disk = dev_to_disk(dev);
- 	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 },
--	.show = aoedisk_show_state
--};
--static struct disk_attribute disk_attr_mac = {
--	.attr = {.name = "mac", .mode = S_IRUGO },
--	.show = aoedisk_show_mac
--};
--static struct disk_attribute disk_attr_netif = {
--	.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 DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
-+static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
-+static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
-+static struct device_attribute dev_attr_firmware_version = {
-+	.attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE },
-+	.show = aoedisk_show_fwver,
- };
- 
- static struct attribute *aoe_attrs[] = {
--	&disk_attr_state.attr,
--	&disk_attr_mac.attr,
--	&disk_attr_netif.attr,
--	&disk_attr_fwver.attr,
--	NULL
-+	&dev_attr_state.attr,
-+	&dev_attr_mac.attr,
-+	&dev_attr_netif.attr,
-+	&dev_attr_firmware_version.attr,
-+	NULL,
- };
- 
- static const struct attribute_group attr_group = {
-@@ -79,12 +78,12 @@ static const struct attribute_group attr_group = {
- static int
- aoedisk_add_sysfs(struct aoedev *d)
- {
--	return sysfs_create_group(&d->gd->kobj, &attr_group);
-+	return sysfs_create_group(&d->gd->dev.kobj, &attr_group);
- }
- void
- aoedisk_rm_sysfs(struct aoedev *d)
- {
--	sysfs_remove_group(&d->gd->kobj, &attr_group);
-+	sysfs_remove_group(&d->gd->dev.kobj, &attr_group);
- }
- 
- static int
-diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
-index 39e563e..d5480e3 100644
---- a/drivers/block/aoe/aoechr.c
-+++ b/drivers/block/aoe/aoechr.c
-@@ -259,9 +259,8 @@ aoechr_init(void)
- 		return PTR_ERR(aoe_class);
- 	}
- 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
--		class_device_create(aoe_class, NULL,
--					MKDEV(AOE_MAJOR, chardevs[i].minor),
--					NULL, chardevs[i].name);
-+		device_create(aoe_class, NULL,
-+			      MKDEV(AOE_MAJOR, chardevs[i].minor), chardevs[i].name);
- 
- 	return 0;
- }
-@@ -272,7 +271,7 @@ aoechr_exit(void)
- 	int i;
- 
- 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
--		class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
-+		device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
- 	class_destroy(aoe_class);
- 	unregister_chrdev(AOE_MAJOR, "aoechr");
- }
-diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
-index 509b649..855ce8e 100644
---- a/drivers/block/cciss.c
-+++ b/drivers/block/cciss.c
-@@ -1187,17 +1187,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
- 	}
- }
- 
--static inline void complete_buffers(struct bio *bio, int status)
--{
--	while (bio) {
--		struct bio *xbh = bio->bi_next;
--
--		bio->bi_next = NULL;
--		bio_endio(bio, status ? 0 : -EIO);
--		bio = xbh;
--	}
--}
--
- static void cciss_check_queues(ctlr_info_t *h)
- {
- 	int start_queue = h->next_to_run;
-@@ -1263,21 +1252,14 @@ static void cciss_softirq_done(struct request *rq)
- 		pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir);
- 	}
- 
--	complete_buffers(rq->bio, (rq->errors == 0));
--
--	if (blk_fs_request(rq)) {
--		const int rw = rq_data_dir(rq);
--
--		disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
--	}
--
- #ifdef CCISS_DEBUG
- 	printk("Done with %p\n", rq);
- #endif				/* CCISS_DEBUG */
- 
--	add_disk_randomness(rq->rq_disk);
-+	if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, blk_rq_bytes(rq)))
-+		BUG();
-+
- 	spin_lock_irqsave(&h->lock, flags);
--	end_that_request_last(rq, (rq->errors == 0));
- 	cmd_free(h, cmd, 1);
- 	cciss_check_queues(h);
- 	spin_unlock_irqrestore(&h->lock, flags);
-@@ -2542,9 +2524,7 @@ after_error_processing:
- 		resend_cciss_cmd(h, cmd);
- 		return;
- 	}
--	cmd->rq->data_len = 0;
- 	cmd->rq->completion_data = cmd;
--	blk_add_trace_rq(cmd->rq->q, cmd->rq, BLK_TA_COMPLETE);
- 	blk_complete_request(cmd->rq);
- }
- 
-diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
-index c8132d9..6919918 100644
---- a/drivers/block/cpqarray.c
-+++ b/drivers/block/cpqarray.c
-@@ -167,7 +167,6 @@ static void start_io(ctlr_info_t *h);
- 
- static inline void addQ(cmdlist_t **Qptr, cmdlist_t *c);
- static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
--static inline void complete_buffers(struct bio *bio, int ok);
- static inline void complete_command(cmdlist_t *cmd, int timeout);
- 
- static irqreturn_t do_ida_intr(int irq, void *dev_id);
-@@ -980,26 +979,13 @@ static void start_io(ctlr_info_t *h)
- 	}
- }
- 
--static inline void complete_buffers(struct bio *bio, int ok)
--{
--	struct bio *xbh;
--
--	while (bio) {
--		xbh = bio->bi_next;
--		bio->bi_next = NULL;
--		
--		bio_endio(bio, ok ? 0 : -EIO);
--
--		bio = xbh;
--	}
--}
- /*
-  * Mark all buffers that cmd was responsible for
-  */
- static inline void complete_command(cmdlist_t *cmd, int timeout)
- {
- 	struct request *rq = cmd->rq;
--	int ok=1;
-+	int error = 0;
- 	int i, ddir;
- 
- 	if (cmd->req.hdr.rcode & RCODE_NONFATAL &&
-@@ -1011,16 +997,17 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
- 	if (cmd->req.hdr.rcode & RCODE_FATAL) {
- 		printk(KERN_WARNING "Fatal error on ida/c%dd%d\n",
- 				cmd->ctlr, cmd->hdr.unit);
--		ok = 0;
-+		error = -EIO;
- 	}
- 	if (cmd->req.hdr.rcode & RCODE_INVREQ) {
- 				printk(KERN_WARNING "Invalid request on ida/c%dd%d = (cmd=%x sect=%d cnt=%d sg=%d ret=%x)\n",
- 				cmd->ctlr, cmd->hdr.unit, cmd->req.hdr.cmd,
- 				cmd->req.hdr.blk, cmd->req.hdr.blk_cnt,
- 				cmd->req.hdr.sg_cnt, cmd->req.hdr.rcode);
--		ok = 0;	
-+		error = -EIO;
- 	}
--	if (timeout) ok = 0;
-+	if (timeout)
-+		error = -EIO;
- 	/* unmap the DMA mapping for all the scatter gather elements */
- 	if (cmd->req.hdr.cmd == IDA_READ)
- 		ddir = PCI_DMA_FROMDEVICE;
-@@ -1030,18 +1017,9 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
-                 pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr,
- 				cmd->req.sg[i].size, ddir);
- 
--	complete_buffers(rq->bio, ok);
--
--	if (blk_fs_request(rq)) {
--		const int rw = rq_data_dir(rq);
--
--		disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
--	}
--
--	add_disk_randomness(rq->rq_disk);
--
- 	DBGPX(printk("Done with %p\n", rq););
--	end_that_request_last(rq, ok ? 1 : -EIO);
-+	if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
-+		BUG();
- }
- 
- /*
-diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
-index 639ed14..32c79a5 100644
---- a/drivers/block/floppy.c
-+++ b/drivers/block/floppy.c
-@@ -2287,21 +2287,19 @@ static int do_format(int drive, struct format_descr *tmp_format_req)
-  * =============================
-  */
- 
--static void floppy_end_request(struct request *req, int uptodate)
-+static void floppy_end_request(struct request *req, int error)
- {
- 	unsigned int nr_sectors = current_count_sectors;
-+	unsigned int drive = (unsigned long)req->rq_disk->private_data;
- 
- 	/* current_count_sectors can be zero if transfer failed */
--	if (!uptodate)
-+	if (error)
- 		nr_sectors = req->current_nr_sectors;
--	if (end_that_request_first(req, uptodate, nr_sectors))
-+	if (__blk_end_request(req, error, nr_sectors << 9))
- 		return;
--	add_disk_randomness(req->rq_disk);
--	floppy_off((long)req->rq_disk->private_data);
--	blkdev_dequeue_request(req);
--	end_that_request_last(req, uptodate);
- 
- 	/* We're done with the request */
-+	floppy_off(drive);
- 	current_req = NULL;
- }
- 
-@@ -2332,7 +2330,7 @@ static void request_done(int uptodate)
- 
- 		/* unlock chained buffers */
- 		spin_lock_irqsave(q->queue_lock, flags);
--		floppy_end_request(req, 1);
-+		floppy_end_request(req, 0);
- 		spin_unlock_irqrestore(q->queue_lock, flags);
- 	} else {
- 		if (rq_data_dir(req) == WRITE) {
-@@ -2346,7 +2344,7 @@ static void request_done(int uptodate)
- 			DRWE->last_error_generation = DRS->generation;
- 		}
- 		spin_lock_irqsave(q->queue_lock, flags);
--		floppy_end_request(req, 0);
-+		floppy_end_request(req, -EIO);
- 		spin_unlock_irqrestore(q->queue_lock, flags);
- 	}
- }
-diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
-index b4c0888..ae31060 100644
---- a/drivers/block/nbd.c
-+++ b/drivers/block/nbd.c
-@@ -100,17 +100,15 @@ static const char *nbdcmd_to_ascii(int cmd)
- 
- static void nbd_end_request(struct request *req)
- {
--	int uptodate = (req->errors == 0) ? 1 : 0;
-+	int error = req->errors ? -EIO : 0;
- 	struct request_queue *q = req->q;
- 	unsigned long flags;
- 
- 	dprintk(DBG_BLKDEV, "%s: request %p: %s\n", req->rq_disk->disk_name,
--			req, uptodate? "done": "failed");
-+			req, error ? "failed" : "done");
- 
- 	spin_lock_irqsave(q->queue_lock, flags);
--	if (!end_that_request_first(req, uptodate, req->nr_sectors)) {
--		end_that_request_last(req, uptodate);
--	}
-+	__blk_end_request(req, error, req->nr_sectors << 9);
- 	spin_unlock_irqrestore(q->queue_lock, flags);
- }
- 
-@@ -375,14 +373,17 @@ harderror:
- 	return NULL;
- }
- 
--static ssize_t pid_show(struct gendisk *disk, char *page)
-+static ssize_t pid_show(struct device *dev,
-+			struct device_attribute *attr, char *buf)
- {
--	return sprintf(page, "%ld\n",
-+	struct gendisk *disk = dev_to_disk(dev);
++	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
++	struct hifn_device *dev = ctx->dev;
++	int err = -EAGAIN;
 +
-+	return sprintf(buf, "%ld\n",
- 		(long) ((struct nbd_device *)disk->private_data)->pid);
- }
- 
--static struct disk_attribute pid_attr = {
--	.attr = { .name = "pid", .mode = S_IRUGO },
-+static struct device_attribute pid_attr = {
-+	.attr = { .name = "pid", .mode = S_IRUGO, .owner = THIS_MODULE },
- 	.show = pid_show,
- };
- 
-@@ -394,7 +395,7 @@ static int nbd_do_it(struct nbd_device *lo)
- 	BUG_ON(lo->magic != LO_MAGIC);
- 
- 	lo->pid = current->pid;
--	ret = sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
-+	ret = sysfs_create_file(&lo->disk->dev.kobj, &pid_attr.attr);
- 	if (ret) {
- 		printk(KERN_ERR "nbd: sysfs_create_file failed!");
- 		return ret;
-@@ -403,7 +404,7 @@ static int nbd_do_it(struct nbd_device *lo)
- 	while ((req = nbd_read_stat(lo)) != NULL)
- 		nbd_end_request(req);
- 
--	sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
-+	sysfs_remove_file(&lo->disk->dev.kobj, &pid_attr.attr);
- 	return 0;
- }
- 
-diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
-index d89e7d3..ab86e23 100644
---- a/drivers/block/paride/pg.c
-+++ b/drivers/block/paride/pg.c
-@@ -676,8 +676,8 @@ static int __init pg_init(void)
- 	for (unit = 0; unit < PG_UNITS; unit++) {
- 		struct pg *dev = &devices[unit];
- 		if (dev->present)
--			class_device_create(pg_class, NULL, MKDEV(major, unit),
--					NULL, "pg%u", unit);
-+			device_create(pg_class, NULL, MKDEV(major, unit),
-+				      "pg%u", unit);
- 	}
- 	err = 0;
- 	goto out;
-@@ -695,7 +695,7 @@ static void __exit pg_exit(void)
- 	for (unit = 0; unit < PG_UNITS; unit++) {
- 		struct pg *dev = &devices[unit];
- 		if (dev->present)
--			class_device_destroy(pg_class, MKDEV(major, unit));
-+			device_destroy(pg_class, MKDEV(major, unit));
- 	}
- 	class_destroy(pg_class);
- 	unregister_chrdev(major, name);
-diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
-index b91accf..76096ca 100644
---- a/drivers/block/paride/pt.c
-+++ b/drivers/block/paride/pt.c
-@@ -972,10 +972,10 @@ static int __init pt_init(void)
- 
- 	for (unit = 0; unit < PT_UNITS; unit++)
- 		if (pt[unit].present) {
--			class_device_create(pt_class, NULL, MKDEV(major, unit),
--					NULL, "pt%d", unit);
--			class_device_create(pt_class, NULL, MKDEV(major, unit + 128),
--					NULL, "pt%dn", unit);
-+			device_create(pt_class, NULL, MKDEV(major, unit),
-+				      "pt%d", unit);
-+			device_create(pt_class, NULL, MKDEV(major, unit + 128),
-+				      "pt%dn", unit);
- 		}
- 	goto out;
- 
-@@ -990,8 +990,8 @@ static void __exit pt_exit(void)
- 	int unit;
- 	for (unit = 0; unit < PT_UNITS; unit++)
- 		if (pt[unit].present) {
--			class_device_destroy(pt_class, MKDEV(major, unit));
--			class_device_destroy(pt_class, MKDEV(major, unit + 128));
-+			device_destroy(pt_class, MKDEV(major, unit));
-+			device_destroy(pt_class, MKDEV(major, unit + 128));
- 		}
- 	class_destroy(pt_class);
- 	unregister_chrdev(major, name);
-diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
-index 3535ef8..e9de171 100644
---- a/drivers/block/pktcdvd.c
-+++ b/drivers/block/pktcdvd.c
-@@ -110,17 +110,18 @@ static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
- 					struct kobj_type* ktype)
- {
- 	struct pktcdvd_kobj *p;
-+	int error;
++	if (dev->started + DIV_ROUND_UP(req->nbytes, PAGE_SIZE) <= HIFN_QUEUE_LENGTH)
++		err = hifn_setup_session(req);
 +
- 	p = kzalloc(sizeof(*p), GFP_KERNEL);
- 	if (!p)
- 		return NULL;
--	kobject_set_name(&p->kobj, "%s", name);
--	p->kobj.parent = parent;
--	p->kobj.ktype = ktype;
- 	p->pd = pd;
--	if (kobject_register(&p->kobj) != 0) {
-+	error = kobject_init_and_add(&p->kobj, ktype, parent, "%s", name);
-+	if (error) {
- 		kobject_put(&p->kobj);
- 		return NULL;
- 	}
-+	kobject_uevent(&p->kobj, KOBJ_ADD);
- 	return p;
- }
- /*
-@@ -129,7 +130,7 @@ static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
- static void pkt_kobj_remove(struct pktcdvd_kobj *p)
- {
- 	if (p)
--		kobject_unregister(&p->kobj);
-+		kobject_put(&p->kobj);
- }
- /*
-  * default release function for pktcdvd kernel objects.
-@@ -301,18 +302,16 @@ static struct kobj_type kobj_pkt_type_wqueue = {
- static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
- {
- 	if (class_pktcdvd) {
--		pd->clsdev = class_device_create(class_pktcdvd,
--					NULL, pd->pkt_dev,
--					NULL, "%s", pd->name);
--		if (IS_ERR(pd->clsdev))
--			pd->clsdev = NULL;
-+		pd->dev = device_create(class_pktcdvd, NULL, pd->pkt_dev, "%s", pd->name);
-+		if (IS_ERR(pd->dev))
-+			pd->dev = NULL;
- 	}
--	if (pd->clsdev) {
-+	if (pd->dev) {
- 		pd->kobj_stat = pkt_kobj_create(pd, "stat",
--					&pd->clsdev->kobj,
-+					&pd->dev->kobj,
- 					&kobj_pkt_type_stat);
- 		pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue",
--					&pd->clsdev->kobj,
-+					&pd->dev->kobj,
- 					&kobj_pkt_type_wqueue);
- 	}
- }
-@@ -322,7 +321,7 @@ static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
- 	pkt_kobj_remove(pd->kobj_stat);
- 	pkt_kobj_remove(pd->kobj_wqueue);
- 	if (class_pktcdvd)
--		class_device_destroy(class_pktcdvd, pd->pkt_dev);
-+		device_destroy(class_pktcdvd, pd->pkt_dev);
- }
- 
- 
-diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
-index e354bfc..7483f94 100644
---- a/drivers/block/ps3disk.c
-+++ b/drivers/block/ps3disk.c
-@@ -229,7 +229,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
- 	struct ps3_storage_device *dev = data;
- 	struct ps3disk_private *priv;
- 	struct request *req;
--	int res, read, uptodate;
-+	int res, read, error;
- 	u64 tag, status;
- 	unsigned long num_sectors;
- 	const char *op;
-@@ -270,21 +270,17 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data)
- 	if (status) {
- 		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
- 			__LINE__, op, status);
--		uptodate = 0;
-+		error = -EIO;
- 	} else {
- 		dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
- 			__LINE__, op);
--		uptodate = 1;
-+		error = 0;
- 		if (read)
- 			ps3disk_scatter_gather(dev, req, 0);
- 	}
- 
- 	spin_lock(&priv->lock);
--	if (!end_that_request_first(req, uptodate, num_sectors)) {
--		add_disk_randomness(req->rq_disk);
--		blkdev_dequeue_request(req);
--		end_that_request_last(req, uptodate);
--	}
-+	__blk_end_request(req, error, num_sectors << 9);
- 	priv->req = NULL;
- 	ps3disk_do_request(dev, priv->queue);
- 	spin_unlock(&priv->lock);
-diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c
-index fac4c6c..a8de037 100644
---- a/drivers/block/sunvdc.c
-+++ b/drivers/block/sunvdc.c
-@@ -212,12 +212,9 @@ static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc)
- 	vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD);
- }
- 
--static void vdc_end_request(struct request *req, int uptodate, int num_sectors)
-+static void vdc_end_request(struct request *req, int error, int num_sectors)
- {
--	if (end_that_request_first(req, uptodate, num_sectors))
--		return;
--	add_disk_randomness(req->rq_disk);
--	end_that_request_last(req, uptodate);
-+	__blk_end_request(req, error, num_sectors << 9);
- }
- 
- static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
-@@ -242,7 +239,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
- 
- 	rqe->req = NULL;
- 
--	vdc_end_request(req, !desc->status, desc->size >> 9);
-+	vdc_end_request(req, (desc->status ? -EIO : 0), desc->size >> 9);
- 
- 	if (blk_queue_stopped(port->disk->queue))
- 		blk_start_queue(port->disk->queue);
-@@ -456,7 +453,7 @@ static void do_vdc_request(struct request_queue *q)
- 
- 		blkdev_dequeue_request(req);
- 		if (__send_request(req) < 0)
--			vdc_end_request(req, 0, req->hard_nr_sectors);
-+			vdc_end_request(req, -EIO, req->hard_nr_sectors);
- 	}
- }
- 
-@@ -735,7 +732,7 @@ static struct vio_driver_ops vdc_vio_ops = {
- 	.handshake_complete	= vdc_handshake_complete,
- };
- 
--static void print_version(void)
-+static void __devinit print_version(void)
- {
- 	static int version_printed;
- 
-diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
-index 52dc5e1..cd5674b 100644
---- a/drivers/block/sx8.c
-+++ b/drivers/block/sx8.c
-@@ -744,16 +744,14 @@ static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
- 
- static inline void carm_end_request_queued(struct carm_host *host,
- 					   struct carm_request *crq,
--					   int uptodate)
-+					   int error)
- {
- 	struct request *req = crq->rq;
- 	int rc;
- 
--	rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
-+	rc = __blk_end_request(req, error, blk_rq_bytes(req));
- 	assert(rc == 0);
- 
--	end_that_request_last(req, uptodate);
--
- 	rc = carm_put_request(host, crq);
- 	assert(rc == 0);
- }
-@@ -793,9 +791,9 @@ static inline void carm_round_robin(struct carm_host *host)
- }
- 
- static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
--			int is_ok)
-+			       int error)
- {
--	carm_end_request_queued(host, crq, is_ok);
-+	carm_end_request_queued(host, crq, error);
- 	if (max_queue == 1)
- 		carm_round_robin(host);
- 	else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
-@@ -873,14 +871,14 @@ queue_one_request:
- 	sg = &crq->sg[0];
- 	n_elem = blk_rq_map_sg(q, rq, sg);
- 	if (n_elem <= 0) {
--		carm_end_rq(host, crq, 0);
-+		carm_end_rq(host, crq, -EIO);
- 		return;		/* request with no s/g entries? */
- 	}
- 
- 	/* map scatterlist to PCI bus addresses */
- 	n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
- 	if (n_elem <= 0) {
--		carm_end_rq(host, crq, 0);
-+		carm_end_rq(host, crq, -EIO);
- 		return;		/* request with no s/g entries? */
- 	}
- 	crq->n_elem = n_elem;
-@@ -941,7 +939,7 @@ queue_one_request:
- 
- static void carm_handle_array_info(struct carm_host *host,
- 				   struct carm_request *crq, u8 *mem,
--				   int is_ok)
-+				   int error)
- {
- 	struct carm_port *port;
- 	u8 *msg_data = mem + sizeof(struct carm_array_info);
-@@ -952,9 +950,9 @@ static void carm_handle_array_info(struct carm_host *host,
- 
- 	DPRINTK("ENTER\n");
- 
--	carm_end_rq(host, crq, is_ok);
-+	carm_end_rq(host, crq, error);
- 
--	if (!is_ok)
-+	if (error)
- 		goto out;
- 	if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
- 		goto out;
-@@ -1001,7 +999,7 @@ out:
- 
- static void carm_handle_scan_chan(struct carm_host *host,
- 				  struct carm_request *crq, u8 *mem,
--				  int is_ok)
-+				  int error)
- {
- 	u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
- 	unsigned int i, dev_count = 0;
-@@ -1009,9 +1007,9 @@ static void carm_handle_scan_chan(struct carm_host *host,
- 
- 	DPRINTK("ENTER\n");
- 
--	carm_end_rq(host, crq, is_ok);
-+	carm_end_rq(host, crq, error);
- 
--	if (!is_ok) {
-+	if (error) {
- 		new_state = HST_ERROR;
- 		goto out;
- 	}
-@@ -1033,23 +1031,23 @@ out:
- }
- 
- static void carm_handle_generic(struct carm_host *host,
--				struct carm_request *crq, int is_ok,
-+				struct carm_request *crq, int error,
- 				int cur_state, int next_state)
- {
- 	DPRINTK("ENTER\n");
- 
--	carm_end_rq(host, crq, is_ok);
-+	carm_end_rq(host, crq, error);
- 
- 	assert(host->state == cur_state);
--	if (is_ok)
--		host->state = next_state;
--	else
-+	if (error)
- 		host->state = HST_ERROR;
-+	else
-+		host->state = next_state;
- 	schedule_work(&host->fsm_task);
- }
- 
- static inline void carm_handle_rw(struct carm_host *host,
--				  struct carm_request *crq, int is_ok)
-+				  struct carm_request *crq, int error)
- {
- 	int pci_dir;
- 
-@@ -1062,7 +1060,7 @@ static inline void carm_handle_rw(struct carm_host *host,
- 
- 	pci_unmap_sg(host->pdev, &crq->sg[0], crq->n_elem, pci_dir);
- 
--	carm_end_rq(host, crq, is_ok);
-+	carm_end_rq(host, crq, error);
- }
- 
- static inline void carm_handle_resp(struct carm_host *host,
-@@ -1071,7 +1069,7 @@ static inline void carm_handle_resp(struct carm_host *host,
- 	u32 handle = le32_to_cpu(ret_handle_le);
- 	unsigned int msg_idx;
- 	struct carm_request *crq;
--	int is_ok = (status == RMSG_OK);
-+	int error = (status == RMSG_OK) ? 0 : -EIO;
- 	u8 *mem;
- 
- 	VPRINTK("ENTER, handle == 0x%x\n", handle);
-@@ -1090,7 +1088,7 @@ static inline void carm_handle_resp(struct carm_host *host,
- 	/* fast path */
- 	if (likely(crq->msg_type == CARM_MSG_READ ||
- 		   crq->msg_type == CARM_MSG_WRITE)) {
--		carm_handle_rw(host, crq, is_ok);
-+		carm_handle_rw(host, crq, error);
- 		return;
- 	}
- 
-@@ -1100,7 +1098,7 @@ static inline void carm_handle_resp(struct carm_host *host,
- 	case CARM_MSG_IOCTL: {
- 		switch (crq->msg_subtype) {
- 		case CARM_IOC_SCAN_CHAN:
--			carm_handle_scan_chan(host, crq, mem, is_ok);
-+			carm_handle_scan_chan(host, crq, mem, error);
- 			break;
- 		default:
- 			/* unknown / invalid response */
-@@ -1112,21 +1110,21 @@ static inline void carm_handle_resp(struct carm_host *host,
- 	case CARM_MSG_MISC: {
- 		switch (crq->msg_subtype) {
- 		case MISC_ALLOC_MEM:
--			carm_handle_generic(host, crq, is_ok,
-+			carm_handle_generic(host, crq, error,
- 					    HST_ALLOC_BUF, HST_SYNC_TIME);
- 			break;
- 		case MISC_SET_TIME:
--			carm_handle_generic(host, crq, is_ok,
-+			carm_handle_generic(host, crq, error,
- 					    HST_SYNC_TIME, HST_GET_FW_VER);
- 			break;
- 		case MISC_GET_FW_VER: {
- 			struct carm_fw_ver *ver = (struct carm_fw_ver *)
- 				mem + sizeof(struct carm_msg_get_fw_ver);
--			if (is_ok) {
-+			if (!error) {
- 				host->fw_ver = le32_to_cpu(ver->version);
- 				host->flags |= (ver->features & FL_FW_VER_MASK);
- 			}
--			carm_handle_generic(host, crq, is_ok,
-+			carm_handle_generic(host, crq, error,
- 					    HST_GET_FW_VER, HST_PORT_SCAN);
- 			break;
- 		}
-@@ -1140,7 +1138,7 @@ static inline void carm_handle_resp(struct carm_host *host,
- 	case CARM_MSG_ARRAY: {
- 		switch (crq->msg_subtype) {
- 		case CARM_ARRAY_INFO:
--			carm_handle_array_info(host, crq, mem, is_ok);
-+			carm_handle_array_info(host, crq, mem, error);
- 			break;
- 		default:
- 			/* unknown / invalid response */
-@@ -1159,7 +1157,7 @@ static inline void carm_handle_resp(struct carm_host *host,
- err_out:
- 	printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
- 	       pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
--	carm_end_rq(host, crq, 0);
-+	carm_end_rq(host, crq, -EIO);
- }
- 
- static inline void carm_handle_responses(struct carm_host *host)
-diff --git a/drivers/block/ub.c b/drivers/block/ub.c
-index 08e909d..a70c1c2 100644
---- a/drivers/block/ub.c
-+++ b/drivers/block/ub.c
-@@ -808,16 +808,16 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
- 
- static void ub_end_rq(struct request *rq, unsigned int scsi_status)
- {
--	int uptodate;
-+	int error;
- 
- 	if (scsi_status == 0) {
--		uptodate = 1;
-+		error = 0;
- 	} else {
--		uptodate = 0;
-+		error = -EIO;
- 		rq->errors = scsi_status;
- 	}
--	end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
--	end_that_request_last(rq, uptodate);
-+	if (__blk_end_request(rq, error, blk_rq_bytes(rq)))
-+		BUG();
- }
- 
- static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
-@@ -922,11 +922,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
- 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
- 	    bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
- 
--	/* Fill what we shouldn't be filling, because usb-storage did so. */
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
--
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
- 		/* XXX Clear stalls */
- 		ub_complete(&sc->work_done);
-@@ -1313,9 +1308,6 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
- 	sc->last_pipe = pipe;
- 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg),
- 	    sg->length, ub_urb_complete, sc);
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
- 
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
- 		/* XXX Clear stalls */
-@@ -1356,9 +1348,6 @@ static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
- 	sc->last_pipe = sc->recv_bulk_pipe;
- 	usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
- 	    &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
- 
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
- 		/* XXX Clear stalls */
-@@ -1473,9 +1462,6 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- 
- 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
- 	    (unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
- 
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
- 		ub_complete(&sc->work_done);
-@@ -1953,9 +1939,6 @@ static int ub_sync_reset(struct ub_dev *sc)
- 
- 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
- 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
- 
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
- 		printk(KERN_WARNING
-@@ -2007,9 +1990,6 @@ static int ub_sync_getmaxlun(struct ub_dev *sc)
- 
- 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
- 	    (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
- 
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0)
- 		goto err_submit;
-@@ -2077,9 +2057,6 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
- 
- 	usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
- 	    (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
--	sc->work_urb.actual_length = 0;
--	sc->work_urb.error_count = 0;
--	sc->work_urb.status = 0;
- 
- 	if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
- 		printk(KERN_WARNING
-diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
-index ab5d404..9e61fca 100644
---- a/drivers/block/viodasd.c
-+++ b/drivers/block/viodasd.c
-@@ -229,13 +229,10 @@ static struct block_device_operations viodasd_fops = {
- /*
-  * End a request
-  */
--static void viodasd_end_request(struct request *req, int uptodate,
-+static void viodasd_end_request(struct request *req, int error,
- 		int num_sectors)
- {
--	if (end_that_request_first(req, uptodate, num_sectors))
--		return;
--	add_disk_randomness(req->rq_disk);
--	end_that_request_last(req, uptodate);
-+	__blk_end_request(req, error, num_sectors << 9);
- }
- 
- /*
-@@ -374,12 +371,12 @@ static void do_viodasd_request(struct request_queue *q)
- 		blkdev_dequeue_request(req);
- 		/* check that request contains a valid command */
- 		if (!blk_fs_request(req)) {
--			viodasd_end_request(req, 0, req->hard_nr_sectors);
-+			viodasd_end_request(req, -EIO, req->hard_nr_sectors);
- 			continue;
- 		}
- 		/* Try sending the request */
- 		if (send_request(req) != 0)
--			viodasd_end_request(req, 0, req->hard_nr_sectors);
-+			viodasd_end_request(req, -EIO, req->hard_nr_sectors);
- 	}
- }
- 
-@@ -591,7 +588,7 @@ static int viodasd_handle_read_write(struct vioblocklpevent *bevent)
- 	num_req_outstanding--;
- 	spin_unlock_irqrestore(&viodasd_spinlock, irq_flags);
- 
--	error = event->xRc != HvLpEvent_Rc_Good;
-+	error = (event->xRc == HvLpEvent_Rc_Good) ? 0 : -EIO;
- 	if (error) {
- 		const struct vio_error_entry *err;
- 		err = vio_lookup_rc(viodasd_err_table, bevent->sub_result);
-@@ -601,7 +598,7 @@ static int viodasd_handle_read_write(struct vioblocklpevent *bevent)
- 	}
- 	qlock = req->q->queue_lock;
- 	spin_lock_irqsave(qlock, irq_flags);
--	viodasd_end_request(req, !error, num_sect);
-+	viodasd_end_request(req, error, num_sect);
- 	spin_unlock_irqrestore(qlock, irq_flags);
- 
- 	/* Finally, try to get more requests off of this device's queue */
-diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
-index 2bdebcb..8afce67 100644
---- a/drivers/block/xen-blkfront.c
-+++ b/drivers/block/xen-blkfront.c
-@@ -452,7 +452,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
- 	RING_IDX i, rp;
- 	unsigned long flags;
- 	struct blkfront_info *info = (struct blkfront_info *)dev_id;
--	int uptodate;
-+	int error;
- 
- 	spin_lock_irqsave(&blkif_io_lock, flags);
- 
-@@ -477,13 +477,13 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
- 
- 		add_id_to_freelist(info, id);
- 
--		uptodate = (bret->status == BLKIF_RSP_OKAY);
-+		error = (bret->status == BLKIF_RSP_OKAY) ? 0 : -EIO;
- 		switch (bret->operation) {
- 		case BLKIF_OP_WRITE_BARRIER:
- 			if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
- 				printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
- 				       info->gd->disk_name);
--				uptodate = -EOPNOTSUPP;
-+				error = -EOPNOTSUPP;
- 				info->feature_barrier = 0;
- 				xlvbd_barrier(info);
- 			}
-@@ -494,10 +494,8 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
- 				dev_dbg(&info->xbdev->dev, "Bad return from blkdev data "
- 					"request: %x\n", bret->status);
- 
--			ret = end_that_request_first(req, uptodate,
--				req->hard_nr_sectors);
-+			ret = __blk_end_request(req, error, blk_rq_bytes(req));
- 			BUG_ON(ret);
--			end_that_request_last(req, uptodate);
- 			break;
- 		default:
- 			BUG();
-diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c
-index 82effce..78ebfff 100644
---- a/drivers/block/xsysace.c
-+++ b/drivers/block/xsysace.c
-@@ -483,7 +483,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
- 	u32 status;
- 	u16 val;
- 	int count;
--	int i;
- 
- #if defined(DEBUG)
- 	dev_dbg(ace->dev, "fsm_state=%i, id_req_count=%i\n",
-@@ -688,7 +687,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
- 		}
- 
- 		/* Transfer the next buffer */
--		i = 16;
- 		if (ace->fsm_task == ACE_TASK_WRITE)
- 			ace->reg_ops->dataout(ace);
- 		else
-@@ -702,8 +700,8 @@ static void ace_fsm_dostate(struct ace_device *ace)
- 		}
- 
- 		/* bio finished; is there another one? */
--		i = ace->req->current_nr_sectors;
--		if (end_that_request_first(ace->req, 1, i)) {
-+		if (__blk_end_request(ace->req, 0,
-+					blk_rq_cur_bytes(ace->req))) {
- 			/* dev_dbg(ace->dev, "next block; h=%li c=%i\n",
- 			 *      ace->req->hard_nr_sectors,
- 			 *      ace->req->current_nr_sectors);
-@@ -718,9 +716,6 @@ static void ace_fsm_dostate(struct ace_device *ace)
- 		break;
- 
- 	case ACE_FSM_STATE_REQ_COMPLETE:
--		/* Complete the block request */
--		blkdev_dequeue_request(ace->req);
--		end_that_request_last(ace->req, 1);
- 		ace->req = NULL;
- 
- 		/* Finished request; go to idle state */
-diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile
-index 774c180..ecf85fd 100644
---- a/drivers/cdrom/Makefile
-+++ b/drivers/cdrom/Makefile
-@@ -11,3 +11,4 @@ obj-$(CONFIG_PARIDE_PCD)	+=		cdrom.o
- obj-$(CONFIG_CDROM_PKTCDVD)	+=		cdrom.o
- 
- obj-$(CONFIG_VIOCD)		+= viocd.o      cdrom.o
-+obj-$(CONFIG_GDROM)		+= gdrom.o      cdrom.o
-diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
-index af05610..47e5b40 100644
---- a/drivers/cdrom/cdrom.c
-+++ b/drivers/cdrom/cdrom.c
-@@ -2787,12 +2787,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
- 	return -ENOSYS;
- }
- 
--static inline
--int msf_to_lba(char m, char s, char f)
--{
--	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
--}
--
- /*
-  * Required when we need to use READ_10 to issue other than 2048 block
-  * reads
-diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
-new file mode 100644
-index 0000000..4e2bbcc
---- /dev/null
-+++ b/drivers/cdrom/gdrom.c
-@@ -0,0 +1,867 @@
-+/* GD ROM driver for the SEGA Dreamcast
-+ * copyright Adrian McMenamin, 2007
-+ * With thanks to Marcus Comstedt and Nathan Keynes
-+ * for work in reversing PIO and DMA
-+ *
-+ * 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.,
-+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-+ *
-+ */
++	if (err == -EAGAIN) {
++		unsigned long flags;
 +
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/fs.h>
-+#include <linux/kernel.h>
-+#include <linux/list.h>
-+#include <linux/slab.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/cdrom.h>
-+#include <linux/genhd.h>
-+#include <linux/bio.h>
-+#include <linux/blkdev.h>
-+#include <linux/interrupt.h>
-+#include <linux/device.h>
-+#include <linux/wait.h>
-+#include <linux/workqueue.h>
-+#include <linux/platform_device.h>
-+#include <scsi/scsi.h>
-+#include <asm/io.h>
-+#include <asm/dma.h>
-+#include <asm/delay.h>
-+#include <asm/mach/dma.h>
-+#include <asm/mach/sysasic.h>
++		spin_lock_irqsave(&dev->lock, flags);
++		err = ablkcipher_enqueue_request(&dev->queue, req);
++		spin_unlock_irqrestore(&dev->lock, flags);
++	}
 +
-+#define GDROM_DEV_NAME "gdrom"
-+#define GD_SESSION_OFFSET 150
++	return err;
++}
 +
-+/* GD Rom commands */
-+#define GDROM_COM_SOFTRESET 0x08
-+#define GDROM_COM_EXECDIAG 0x90
-+#define GDROM_COM_PACKET 0xA0
-+#define GDROM_COM_IDDEV 0xA1
++static int hifn_setup_crypto_req(struct ablkcipher_request *req, u8 op,
++		u8 type, u8 mode)
++{
++	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
++	unsigned ivsize;
 +
-+/* GD Rom registers */
-+#define GDROM_BASE_REG			0xA05F7000
-+#define GDROM_ALTSTATUS_REG		(GDROM_BASE_REG + 0x18)
-+#define GDROM_DATA_REG			(GDROM_BASE_REG + 0x80)
-+#define GDROM_ERROR_REG		(GDROM_BASE_REG + 0x84)
-+#define GDROM_INTSEC_REG		(GDROM_BASE_REG + 0x88)
-+#define GDROM_SECNUM_REG		(GDROM_BASE_REG + 0x8C)
-+#define GDROM_BCL_REG			(GDROM_BASE_REG + 0x90)
-+#define GDROM_BCH_REG			(GDROM_BASE_REG + 0x94)
-+#define GDROM_DSEL_REG			(GDROM_BASE_REG + 0x98)
-+#define GDROM_STATUSCOMMAND_REG	(GDROM_BASE_REG + 0x9C)
-+#define GDROM_RESET_REG		(GDROM_BASE_REG + 0x4E4)
++	ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
 +
-+#define GDROM_DMA_STARTADDR_REG	(GDROM_BASE_REG + 0x404)
-+#define GDROM_DMA_LENGTH_REG		(GDROM_BASE_REG + 0x408)
-+#define GDROM_DMA_DIRECTION_REG	(GDROM_BASE_REG + 0x40C)
-+#define GDROM_DMA_ENABLE_REG		(GDROM_BASE_REG + 0x414)
-+#define GDROM_DMA_STATUS_REG		(GDROM_BASE_REG + 0x418)
-+#define GDROM_DMA_WAIT_REG		(GDROM_BASE_REG + 0x4A0)
-+#define GDROM_DMA_ACCESS_CTRL_REG	(GDROM_BASE_REG + 0x4B8)
++	if (req->info && mode != ACRYPTO_MODE_ECB) {
++		if (type == ACRYPTO_TYPE_AES_128)
++			ivsize = HIFN_AES_IV_LENGTH;
++		else if (type == ACRYPTO_TYPE_DES)
++			ivsize = HIFN_DES_KEY_LENGTH;
++		else if (type == ACRYPTO_TYPE_3DES)
++			ivsize = HIFN_3DES_KEY_LENGTH;
++	}
 +
-+#define GDROM_HARD_SECTOR	2048
-+#define BLOCK_LAYER_SECTOR	512
-+#define GD_TO_BLK		4
++	if (ctx->keysize != 16 && type == ACRYPTO_TYPE_AES_128) {
++		if (ctx->keysize == 24)
++			type = ACRYPTO_TYPE_AES_192;
++		else if (ctx->keysize == 32)
++			type = ACRYPTO_TYPE_AES_256;
++	}
 +
-+#define GDROM_DEFAULT_TIMEOUT	(HZ * 7)
++	ctx->op = op;
++	ctx->mode = mode;
++	ctx->type = type;
++	ctx->iv = req->info;
++	ctx->ivsize = ivsize;
 +
-+static const struct {
-+	int sense_key;
-+	const char * const text;
-+} sense_texts[] = {
-+	{NO_SENSE, "OK"},
-+	{RECOVERED_ERROR, "Recovered from error"},
-+	{NOT_READY, "Device not ready"},
-+	{MEDIUM_ERROR, "Disk not ready"},
-+	{HARDWARE_ERROR, "Hardware error"},
-+	{ILLEGAL_REQUEST, "Command has failed"},
-+	{UNIT_ATTENTION, "Device needs attention - disk may have been changed"},
-+	{DATA_PROTECT, "Data protection error"},
-+	{ABORTED_COMMAND, "Command aborted"},
-+};
++	/*
++	 * HEAVY TODO: needs to kick Herbert XU to write documentation.
++	 * HEAVY TODO: needs to kick Herbert XU to write documentation.
++	 * HEAVY TODO: needs to kick Herbert XU to write documentation.
++	 */
 +
-+static struct platform_device *pd;
-+static int gdrom_major;
-+static DECLARE_WAIT_QUEUE_HEAD(command_queue);
-+static DECLARE_WAIT_QUEUE_HEAD(request_queue);
++	return hifn_handle_req(req);
++}
 +
-+static DEFINE_SPINLOCK(gdrom_lock);
-+static void gdrom_readdisk_dma(struct work_struct *work);
-+static DECLARE_WORK(work, gdrom_readdisk_dma);
-+static LIST_HEAD(gdrom_deferred);
++static int hifn_process_queue(struct hifn_device *dev)
++{
++	struct crypto_async_request *async_req;
++	struct hifn_context *ctx;
++	struct ablkcipher_request *req;
++	unsigned long flags;
++	int err = 0;
 +
-+struct gdromtoc {
-+	unsigned int entry[99];
-+	unsigned int first, last;
-+	unsigned int leadout;
-+};
++	while (dev->started < HIFN_QUEUE_LENGTH) {
++		spin_lock_irqsave(&dev->lock, flags);
++		async_req = crypto_dequeue_request(&dev->queue);
++		spin_unlock_irqrestore(&dev->lock, flags);
 +
-+static struct gdrom_unit {
-+	struct gendisk *disk;
-+	struct cdrom_device_info *cd_info;
-+	int status;
-+	int pending;
-+	int transfer;
-+	char disk_type;
-+	struct gdromtoc *toc;
-+	struct request_queue *gdrom_rq;
-+} gd;
++		if (!async_req)
++			break;
 +
-+struct gdrom_id {
-+	char mid;
-+	char modid;
-+	char verid;
-+	char padA[13];
-+	char mname[16];
-+	char modname[16];
-+	char firmver[16];
-+	char padB[16];
-+};
++		ctx = crypto_tfm_ctx(async_req->tfm);
++		req = container_of(async_req, struct ablkcipher_request, base);
 +
-+static int gdrom_getsense(short *bufstring);
-+static int gdrom_packetcommand(struct cdrom_device_info *cd_info,
-+	struct packet_command *command);
-+static int gdrom_hardreset(struct cdrom_device_info *cd_info);
++		err = hifn_handle_req(req);
++		if (err)
++			break;
++	}
 +
-+static bool gdrom_is_busy(void)
-+{
-+	return (ctrl_inb(GDROM_ALTSTATUS_REG) & 0x80) != 0;
++	return err;
 +}
 +
-+static bool gdrom_data_request(void)
++static int hifn_setup_crypto(struct ablkcipher_request *req, u8 op,
++		u8 type, u8 mode)
 +{
-+	return (ctrl_inb(GDROM_ALTSTATUS_REG) & 0x88) == 8;
++	int err;
++	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
++	struct hifn_device *dev = ctx->dev;
++
++	err = hifn_setup_crypto_req(req, op, type, mode);
++	if (err)
++		return err;
++
++	if (dev->started < HIFN_QUEUE_LENGTH &&	dev->queue.qlen)
++		err = hifn_process_queue(dev);
++
++	return err;
 +}
 +
-+static bool gdrom_wait_clrbusy(void)
++/*
++ * AES ecryption functions.
++ */
++static inline int hifn_encrypt_aes_ecb(struct ablkcipher_request *req)
 +{
-+	unsigned long timeout = jiffies + GDROM_DEFAULT_TIMEOUT;
-+	while ((ctrl_inb(GDROM_ALTSTATUS_REG) & 0x80) &&
-+		(time_before(jiffies, timeout)))
-+		cpu_relax();
-+	return time_before(jiffies, timeout + 1);
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_ECB);
 +}
-+
-+static bool gdrom_wait_busy_sleeps(void)
++static inline int hifn_encrypt_aes_cbc(struct ablkcipher_request *req)
 +{
-+	unsigned long timeout;
-+	/* Wait to get busy first */
-+	timeout = jiffies + GDROM_DEFAULT_TIMEOUT;
-+	while (!gdrom_is_busy() && time_before(jiffies, timeout))
-+		cpu_relax();
-+	/* Now wait for busy to clear */
-+	return gdrom_wait_clrbusy();
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CBC);
 +}
-+
-+static void gdrom_identifydevice(void *buf)
++static inline int hifn_encrypt_aes_cfb(struct ablkcipher_request *req)
 +{
-+	int c;
-+	short *data = buf;
-+	/* If the device won't clear it has probably
-+	* been hit by a serious failure - but we'll
-+	* try to return a sense key even so */
-+	if (!gdrom_wait_clrbusy()) {
-+		gdrom_getsense(NULL);
-+		return;
-+	}
-+	ctrl_outb(GDROM_COM_IDDEV, GDROM_STATUSCOMMAND_REG);
-+	if (!gdrom_wait_busy_sleeps()) {
-+		gdrom_getsense(NULL);
-+		return;
-+	}
-+	/* now read in the data */
-+	for (c = 0; c < 40; c++)
-+		data[c] = ctrl_inw(GDROM_DATA_REG);
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CFB);
 +}
-+
-+static void gdrom_spicommand(void *spi_string, int buflen)
++static inline int hifn_encrypt_aes_ofb(struct ablkcipher_request *req)
 +{
-+	short *cmd = spi_string;
-+	unsigned long timeout;
-+
-+	/* ensure IRQ_WAIT is set */
-+	ctrl_outb(0x08, GDROM_ALTSTATUS_REG);
-+	/* specify how many bytes we expect back */
-+	ctrl_outb(buflen & 0xFF, GDROM_BCL_REG);
-+	ctrl_outb((buflen >> 8) & 0xFF, GDROM_BCH_REG);
-+	/* other parameters */
-+	ctrl_outb(0, GDROM_INTSEC_REG);
-+	ctrl_outb(0, GDROM_SECNUM_REG);
-+	ctrl_outb(0, GDROM_ERROR_REG);
-+	/* Wait until we can go */
-+	if (!gdrom_wait_clrbusy()) {
-+		gdrom_getsense(NULL);
-+		return;
-+	}
-+	timeout = jiffies + GDROM_DEFAULT_TIMEOUT;
-+	ctrl_outb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG);
-+	while (!gdrom_data_request() && time_before(jiffies, timeout))
-+		cpu_relax();
-+	if (!time_before(jiffies, timeout + 1)) {
-+		gdrom_getsense(NULL);
-+		return;
-+	}
-+	outsw(PHYSADDR(GDROM_DATA_REG), cmd, 6);
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_OFB);
 +}
 +
-+
-+/* gdrom_command_executediagnostic:
-+ * Used to probe for presence of working GDROM
-+ * Restarts GDROM device and then applies standard ATA 3
-+ * Execute Diagnostic Command: a return of '1' indicates device 0
-+ * present and device 1 absent
++/*
++ * AES decryption functions.
 + */
-+static char gdrom_execute_diagnostic(void)
++static inline int hifn_decrypt_aes_ecb(struct ablkcipher_request *req)
 +{
-+	gdrom_hardreset(gd.cd_info);
-+	if (!gdrom_wait_clrbusy())
-+		return 0;
-+	ctrl_outb(GDROM_COM_EXECDIAG, GDROM_STATUSCOMMAND_REG);
-+	if (!gdrom_wait_busy_sleeps())
-+		return 0;
-+	return ctrl_inb(GDROM_ERROR_REG);
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_ECB);
++}
++static inline int hifn_decrypt_aes_cbc(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CBC);
++}
++static inline int hifn_decrypt_aes_cfb(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CFB);
++}
++static inline int hifn_decrypt_aes_ofb(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_OFB);
 +}
 +
 +/*
-+ * Prepare disk command
-+ * byte 0 = 0x70
-+ * byte 1 = 0x1f
++ * DES ecryption functions.
 + */
-+static int gdrom_preparedisk_cmd(void)
++static inline int hifn_encrypt_des_ecb(struct ablkcipher_request *req)
 +{
-+	struct packet_command *spin_command;
-+	spin_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
-+	if (!spin_command)
-+		return -ENOMEM;
-+	spin_command->cmd[0] = 0x70;
-+	spin_command->cmd[2] = 0x1f;
-+	spin_command->buflen = 0;
-+	gd.pending = 1;
-+	gdrom_packetcommand(gd.cd_info, spin_command);
-+	/* 60 second timeout */
-+	wait_event_interruptible_timeout(command_queue, gd.pending == 0,
-+		GDROM_DEFAULT_TIMEOUT);
-+	gd.pending = 0;
-+	kfree(spin_command);
-+	if (gd.status & 0x01) {
-+		/* log an error */
-+		gdrom_getsense(NULL);
-+		return -EIO;
-+	}
-+	return 0;
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_ECB);
++}
++static inline int hifn_encrypt_des_cbc(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CBC);
++}
++static inline int hifn_encrypt_des_cfb(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CFB);
++}
++static inline int hifn_encrypt_des_ofb(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_OFB);
 +}
 +
 +/*
-+ * Read TOC command
-+ * byte 0 = 0x14
-+ * byte 1 = session
-+ * byte 3 = sizeof TOC >> 8  ie upper byte
-+ * byte 4 = sizeof TOC & 0xff ie lower byte
++ * DES decryption functions.
 + */
-+static int gdrom_readtoc_cmd(struct gdromtoc *toc, int session)
++static inline int hifn_decrypt_des_ecb(struct ablkcipher_request *req)
 +{
-+	int tocsize;
-+	struct packet_command *toc_command;
-+	int err = 0;
-+
-+	toc_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
-+	if (!toc_command)
-+		return -ENOMEM;
-+	tocsize = sizeof(struct gdromtoc);
-+	toc_command->cmd[0] = 0x14;
-+	toc_command->cmd[1] = session;
-+	toc_command->cmd[3] = tocsize >> 8;
-+	toc_command->cmd[4] = tocsize & 0xff;
-+	toc_command->buflen = tocsize;
-+	if (gd.pending) {
-+		err = -EBUSY;
-+		goto cleanup_readtoc_final;
-+	}
-+	gd.pending = 1;
-+	gdrom_packetcommand(gd.cd_info, toc_command);
-+	wait_event_interruptible_timeout(command_queue, gd.pending == 0,
-+		GDROM_DEFAULT_TIMEOUT);
-+	if (gd.pending) {
-+		err = -EINVAL;
-+		goto cleanup_readtoc;
-+	}
-+	insw(PHYSADDR(GDROM_DATA_REG), toc, tocsize/2);
-+	if (gd.status & 0x01)
-+		err = -EINVAL;
-+
-+cleanup_readtoc:
-+	gd.pending = 0;
-+cleanup_readtoc_final:
-+	kfree(toc_command);
-+	return err;
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_ECB);
 +}
-+
-+/* TOC helpers */
-+static int get_entry_lba(int track)
++static inline int hifn_decrypt_des_cbc(struct ablkcipher_request *req)
 +{
-+	return (cpu_to_be32(track & 0xffffff00) - GD_SESSION_OFFSET);
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CBC);
 +}
-+
-+static int get_entry_q_ctrl(int track)
++static inline int hifn_decrypt_des_cfb(struct ablkcipher_request *req)
 +{
-+	return (track & 0x000000f0) >> 4;
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CFB);
 +}
-+
-+static int get_entry_track(int track)
++static inline int hifn_decrypt_des_ofb(struct ablkcipher_request *req)
 +{
-+	return (track & 0x0000ff00) >> 8;
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_DES, ACRYPTO_MODE_OFB);
 +}
 +
-+static int gdrom_get_last_session(struct cdrom_device_info *cd_info,
-+	struct cdrom_multisession *ms_info)
++/*
++ * 3DES ecryption functions.
++ */
++static inline int hifn_encrypt_3des_ecb(struct ablkcipher_request *req)
 +{
-+	int fentry, lentry, track, data, tocuse, err;
-+	if (!gd.toc)
-+		return -ENOMEM;
-+	tocuse = 1;
-+	/* Check if GD-ROM */
-+	err = gdrom_readtoc_cmd(gd.toc, 1);
-+	/* Not a GD-ROM so check if standard CD-ROM */
-+	if (err) {
-+		tocuse = 0;
-+		err = gdrom_readtoc_cmd(gd.toc, 0);
-+		if (err) {
-+			printk(KERN_INFO "GDROM: Could not get CD "
-+				"table of contents\n");
-+			return -ENXIO;
-+		}
-+	}
-+
-+	fentry = get_entry_track(gd.toc->first);
-+	lentry = get_entry_track(gd.toc->last);
-+	/* Find the first data track */
-+	track = get_entry_track(gd.toc->last);
-+	do {
-+		data = gd.toc->entry[track - 1];
-+		if (get_entry_q_ctrl(data))
-+			break;	/* ie a real data track */
-+		track--;
-+	} while (track >= fentry);
-+
-+	if ((track > 100) || (track < get_entry_track(gd.toc->first))) {
-+		printk(KERN_INFO "GDROM: No data on the last "
-+			"session of the CD\n");
-+		gdrom_getsense(NULL);
-+		return -ENXIO;
-+	}
-+
-+	ms_info->addr_format = CDROM_LBA;
-+	ms_info->addr.lba = get_entry_lba(data);
-+	ms_info->xa_flag = 1;
-+	return 0;
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_ECB);
 +}
-+
-+static int gdrom_open(struct cdrom_device_info *cd_info, int purpose)
++static inline int hifn_encrypt_3des_cbc(struct ablkcipher_request *req)
 +{
-+	/* spin up the disk */
-+	return gdrom_preparedisk_cmd();
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CBC);
 +}
-+
-+/* this function is required even if empty */
-+static void gdrom_release(struct cdrom_device_info *cd_info)
++static inline int hifn_encrypt_3des_cfb(struct ablkcipher_request *req)
 +{
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CFB);
 +}
-+
-+static int gdrom_drivestatus(struct cdrom_device_info *cd_info, int ignore)
++static inline int hifn_encrypt_3des_ofb(struct ablkcipher_request *req)
 +{
-+	/* read the sense key */
-+	char sense = ctrl_inb(GDROM_ERROR_REG);
-+	sense &= 0xF0;
-+	if (sense == 0)
-+		return CDS_DISC_OK;
-+	if (sense == 0x20)
-+		return CDS_DRIVE_NOT_READY;
-+	/* default */
-+	return CDS_NO_INFO;
++	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_OFB);
 +}
 +
-+static int gdrom_mediachanged(struct cdrom_device_info *cd_info, int ignore)
++/*
++ * 3DES decryption functions.
++ */
++static inline int hifn_decrypt_3des_ecb(struct ablkcipher_request *req)
 +{
-+	/* check the sense key */
-+	return (ctrl_inb(GDROM_ERROR_REG) & 0xF0) == 0x60;
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_ECB);
 +}
-+
-+/* reset the G1 bus */
-+static int gdrom_hardreset(struct cdrom_device_info *cd_info)
++static inline int hifn_decrypt_3des_cbc(struct ablkcipher_request *req)
 +{
-+	int count;
-+	ctrl_outl(0x1fffff, GDROM_RESET_REG);
-+	for (count = 0xa0000000; count < 0xa0200000; count += 4)
-+		ctrl_inl(count);
-+	return 0;
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CBC);
 +}
-+
-+/* keep the function looking like the universal
-+ * CD Rom specification  - returning int */
-+static int gdrom_packetcommand(struct cdrom_device_info *cd_info,
-+	struct packet_command *command)
++static inline int hifn_decrypt_3des_cfb(struct ablkcipher_request *req)
 +{
-+	gdrom_spicommand(&command->cmd, command->buflen);
-+	return 0;
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CFB);
++}
++static inline int hifn_decrypt_3des_ofb(struct ablkcipher_request *req)
++{
++	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
++			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_OFB);
 +}
 +
-+/* Get Sense SPI command
-+ * From Marcus Comstedt
-+ * cmd = 0x13
-+ * cmd + 4 = length of returned buffer
-+ * Returns 5 16 bit words
-+ */
-+static int gdrom_getsense(short *bufstring)
++struct hifn_alg_template
 +{
-+	struct packet_command *sense_command;
-+	short sense[5];
-+	int sense_key;
-+	int err = -EIO;
++	char name[CRYPTO_MAX_ALG_NAME];
++	char drv_name[CRYPTO_MAX_ALG_NAME];
++	unsigned int bsize;
++	struct ablkcipher_alg ablkcipher;
++};
 +
-+	sense_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
-+	if (!sense_command)
-+		return -ENOMEM;
-+	sense_command->cmd[0] = 0x13;
-+	sense_command->cmd[4] = 10;
-+	sense_command->buflen = 10;
-+	/* even if something is pending try to get
-+	* the sense key if possible */
-+	if (gd.pending && !gdrom_wait_clrbusy()) {
-+		err = -EBUSY;
-+		goto cleanup_sense_final;
-+	}
-+	gd.pending = 1;
-+	gdrom_packetcommand(gd.cd_info, sense_command);
-+	wait_event_interruptible_timeout(command_queue, gd.pending == 0,
-+		GDROM_DEFAULT_TIMEOUT);
-+	if (gd.pending)
-+		goto cleanup_sense;
-+	insw(PHYSADDR(GDROM_DATA_REG), &sense, sense_command->buflen/2);
-+	if (sense[1] & 40) {
-+		printk(KERN_INFO "GDROM: Drive not ready - command aborted\n");
-+		goto cleanup_sense;
-+	}
-+	sense_key = sense[1] & 0x0F;
-+	if (sense_key < ARRAY_SIZE(sense_texts))
-+		printk(KERN_INFO "GDROM: %s\n", sense_texts[sense_key].text);
-+	else
-+		printk(KERN_ERR "GDROM: Unknown sense key: %d\n", sense_key);
-+	if (bufstring) /* return addional sense data */
-+		memcpy(bufstring, &sense[4], 2);
-+	if (sense_key < 2)
-+		err = 0;
++static struct hifn_alg_template hifn_alg_templates[] = {
++	/*
++	 * 3DES ECB, CBC, CFB and OFB modes.
++	 */
++	{
++		.name = "cfb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_3des_cfb,
++			.decrypt	=	hifn_decrypt_3des_cfb,
++		},
++	},
++	{
++		.name = "ofb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_3des_ofb,
++			.decrypt	=	hifn_decrypt_3des_ofb,
++		},
++	},
++	{
++		.name = "cbc(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_3des_cbc,
++			.decrypt	=	hifn_decrypt_3des_cbc,
++		},
++	},
++	{
++		.name = "ecb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_3des_ecb,
++			.decrypt	=	hifn_decrypt_3des_ecb,
++		},
++	},
 +
-+cleanup_sense:
-+	gd.pending = 0;
-+cleanup_sense_final:
-+	kfree(sense_command);
-+	return err;
-+}
++	/*
++	 * DES ECB, CBC, CFB and OFB modes.
++	 */
++	{
++		.name = "cfb(des)", .drv_name = "hifn-des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_des_cfb,
++			.decrypt	=	hifn_decrypt_des_cfb,
++		},
++	},
++	{
++		.name = "ofb(des)", .drv_name = "hifn-des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_des_ofb,
++			.decrypt	=	hifn_decrypt_des_ofb,
++		},
++	},
++	{
++		.name = "cbc(des)", .drv_name = "hifn-des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_des_cbc,
++			.decrypt	=	hifn_decrypt_des_cbc,
++		},
++	},
++	{
++		.name = "ecb(des)", .drv_name = "hifn-des", .bsize = 8,
++		.ablkcipher = {
++			.min_keysize	=	HIFN_DES_KEY_LENGTH,
++			.max_keysize	=	HIFN_DES_KEY_LENGTH,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_des_ecb,
++			.decrypt	=	hifn_decrypt_des_ecb,
++		},
++	},
 +
-+static struct cdrom_device_ops gdrom_ops = {
-+	.open			= gdrom_open,
-+	.release		= gdrom_release,
-+	.drive_status		= gdrom_drivestatus,
-+	.media_changed		= gdrom_mediachanged,
-+	.get_last_session	= gdrom_get_last_session,
-+	.reset			= gdrom_hardreset,
-+	.capability		= CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
-+				  CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R,
-+	.n_minors		= 1,
++	/*
++	 * AES ECB, CBC, CFB and OFB modes.
++	 */
++	{
++		.name = "ecb(aes)", .drv_name = "hifn-aes", .bsize = 16,
++		.ablkcipher = {
++			.min_keysize	=	AES_MIN_KEY_SIZE,
++			.max_keysize	=	AES_MAX_KEY_SIZE,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_aes_ecb,
++			.decrypt	=	hifn_decrypt_aes_ecb,
++		},
++	},
++	{
++		.name = "cbc(aes)", .drv_name = "hifn-aes", .bsize = 16,
++		.ablkcipher = {
++			.min_keysize	=	AES_MIN_KEY_SIZE,
++			.max_keysize	=	AES_MAX_KEY_SIZE,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_aes_cbc,
++			.decrypt	=	hifn_decrypt_aes_cbc,
++		},
++	},
++	{
++		.name = "cfb(aes)", .drv_name = "hifn-aes", .bsize = 16,
++		.ablkcipher = {
++			.min_keysize	=	AES_MIN_KEY_SIZE,
++			.max_keysize	=	AES_MAX_KEY_SIZE,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_aes_cfb,
++			.decrypt	=	hifn_decrypt_aes_cfb,
++		},
++	},
++	{
++		.name = "ofb(aes)", .drv_name = "hifn-aes", .bsize = 16,
++		.ablkcipher = {
++			.min_keysize	=	AES_MIN_KEY_SIZE,
++			.max_keysize	=	AES_MAX_KEY_SIZE,
++			.setkey		=	hifn_setkey,
++			.encrypt	=	hifn_encrypt_aes_ofb,
++			.decrypt	=	hifn_decrypt_aes_ofb,
++		},
++	},
 +};
 +
-+static int gdrom_bdops_open(struct inode *inode, struct file *file)
++static int hifn_cra_init(struct crypto_tfm *tfm)
 +{
-+	return cdrom_open(gd.cd_info, inode, file);
++	struct crypto_alg *alg = tfm->__crt_alg;
++	struct hifn_crypto_alg *ha = crypto_alg_to_hifn(alg);
++	struct hifn_context *ctx = crypto_tfm_ctx(tfm);
++
++	ctx->dev = ha->dev;
++
++	return 0;
 +}
 +
-+static int gdrom_bdops_release(struct inode *inode, struct file *file)
++static int hifn_alg_alloc(struct hifn_device *dev, struct hifn_alg_template *t)
 +{
-+	return cdrom_release(gd.cd_info, file);
++	struct hifn_crypto_alg *alg;
++	int err;
++
++	alg = kzalloc(sizeof(struct hifn_crypto_alg), GFP_KERNEL);
++	if (!alg)
++		return -ENOMEM;
++
++	snprintf(alg->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s", t->name);
++	snprintf(alg->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", t->drv_name);
++
++	alg->alg.cra_priority = 300;
++	alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
++	alg->alg.cra_blocksize = t->bsize;
++	alg->alg.cra_ctxsize = sizeof(struct hifn_context);
++	alg->alg.cra_alignmask = 15;
++	if (t->bsize == 8)
++		alg->alg.cra_alignmask = 3;
++	alg->alg.cra_type = &crypto_ablkcipher_type;
++	alg->alg.cra_module = THIS_MODULE;
++	alg->alg.cra_u.ablkcipher = t->ablkcipher;
++	alg->alg.cra_init = hifn_cra_init;
++
++	alg->dev = dev;
++
++	list_add_tail(&alg->entry, &dev->alg_list);
++
++	err = crypto_register_alg(&alg->alg);
++	if (err) {
++		list_del(&alg->entry);
++		kfree(alg);
++	}
++
++	return err;
 +}
 +
-+static int gdrom_bdops_mediachanged(struct gendisk *disk)
++static void hifn_unregister_alg(struct hifn_device *dev)
 +{
-+	return cdrom_media_changed(gd.cd_info);
++	struct hifn_crypto_alg *a, *n;
++
++	list_for_each_entry_safe(a, n, &dev->alg_list, entry) {
++		list_del(&a->entry);
++		crypto_unregister_alg(&a->alg);
++		kfree(a);
++	}
 +}
 +
-+static int gdrom_bdops_ioctl(struct inode *inode, struct file *file,
-+	unsigned cmd, unsigned long arg)
++static int hifn_register_alg(struct hifn_device *dev)
 +{
-+	return cdrom_ioctl(file, gd.cd_info, inode, cmd, arg);
-+}
++	int i, err;
 +
-+static struct block_device_operations gdrom_bdops = {
-+	.owner			= THIS_MODULE,
-+	.open			= gdrom_bdops_open,
-+	.release		= gdrom_bdops_release,
-+	.media_changed		= gdrom_bdops_mediachanged,
-+	.ioctl			= gdrom_bdops_ioctl,
-+};
++	for (i=0; i<ARRAY_SIZE(hifn_alg_templates); ++i) {
++		err = hifn_alg_alloc(dev, &hifn_alg_templates[i]);
++		if (err)
++			goto err_out_exit;
++	}
 +
-+static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id)
-+{
-+	gd.status = ctrl_inb(GDROM_STATUSCOMMAND_REG);
-+	if (gd.pending != 1)
-+		return IRQ_HANDLED;
-+	gd.pending = 0;
-+	wake_up_interruptible(&command_queue);
-+	return IRQ_HANDLED;
++	return 0;
++
++err_out_exit:
++	hifn_unregister_alg(dev);
++	return err;
 +}
 +
-+static irqreturn_t gdrom_dma_interrupt(int irq, void *dev_id)
++static void hifn_tasklet_callback(unsigned long data)
 +{
-+	gd.status = ctrl_inb(GDROM_STATUSCOMMAND_REG);
-+	if (gd.transfer != 1)
-+		return IRQ_HANDLED;
-+	gd.transfer = 0;
-+	wake_up_interruptible(&request_queue);
-+	return IRQ_HANDLED;
++	struct hifn_device *dev = (struct hifn_device *)data;
++
++	/*
++	 * This is ok to call this without lock being held,
++	 * althogh it modifies some parameters used in parallel,
++	 * (like dev->success), but they are used in process
++	 * context or update is atomic (like setting dev->sa[i] to NULL).
++	 */
++	hifn_check_for_completion(dev, 0);
 +}
 +
-+static int __devinit gdrom_set_interrupt_handlers(void)
++static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 +{
-+	int err;
++	int err, i;
++	struct hifn_device *dev;
++	char name[8];
 +
-+	err = request_irq(HW_EVENT_GDROM_CMD, gdrom_command_interrupt,
-+		IRQF_DISABLED, "gdrom_command", &gd);
++	err = pci_enable_device(pdev);
 +	if (err)
 +		return err;
-+	err = request_irq(HW_EVENT_GDROM_DMA, gdrom_dma_interrupt,
-+		IRQF_DISABLED, "gdrom_dma", &gd);
++	pci_set_master(pdev);
++
++	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 +	if (err)
-+		free_irq(HW_EVENT_GDROM_CMD, &gd);
++		goto err_out_disable_pci_device;
++
++	snprintf(name, sizeof(name), "hifn%d",
++			atomic_inc_return(&hifn_dev_number)-1);
++
++	err = pci_request_regions(pdev, name);
++	if (err)
++		goto err_out_disable_pci_device;
++
++	if (pci_resource_len(pdev, 0) < HIFN_BAR0_SIZE ||
++	    pci_resource_len(pdev, 1) < HIFN_BAR1_SIZE ||
++	    pci_resource_len(pdev, 2) < HIFN_BAR2_SIZE) {
++		dprintk("%s: Broken hardware - I/O regions are too small.\n",
++				pci_name(pdev));
++		err = -ENODEV;
++		goto err_out_free_regions;
++	}
++
++	dev = kzalloc(sizeof(struct hifn_device) + sizeof(struct crypto_alg),
++			GFP_KERNEL);
++	if (!dev) {
++		err = -ENOMEM;
++		goto err_out_free_regions;
++	}
++
++	INIT_LIST_HEAD(&dev->alg_list);
++
++	snprintf(dev->name, sizeof(dev->name), "%s", name);
++	spin_lock_init(&dev->lock);
++
++	for (i=0; i<3; ++i) {
++		unsigned long addr, size;
++
++		addr = pci_resource_start(pdev, i);
++		size = pci_resource_len(pdev, i);
++
++		dev->bar[i] = ioremap_nocache(addr, size);
++		if (!dev->bar[i])
++			goto err_out_unmap_bars;
++	}
++
++	dev->result_mem = __get_free_pages(GFP_KERNEL, HIFN_MAX_RESULT_ORDER);
++	if (!dev->result_mem) {
++		dprintk("Failed to allocate %d pages for result_mem.\n",
++				HIFN_MAX_RESULT_ORDER);
++		goto err_out_unmap_bars;
++	}
++	memset((void *)dev->result_mem, 0, PAGE_SIZE*(1<<HIFN_MAX_RESULT_ORDER));
++
++	dev->dst = pci_map_single(pdev, (void *)dev->result_mem,
++			PAGE_SIZE << HIFN_MAX_RESULT_ORDER, PCI_DMA_FROMDEVICE);
++
++	dev->desc_virt = pci_alloc_consistent(pdev, sizeof(struct hifn_dma),
++			&dev->desc_dma);
++	if (!dev->desc_virt) {
++		dprintk("Failed to allocate descriptor rings.\n");
++		goto err_out_free_result_pages;
++	}
++	memset(dev->desc_virt, 0, sizeof(struct hifn_dma));
++
++	dev->pdev = pdev;
++	dev->irq = pdev->irq;
++
++	for (i=0; i<HIFN_D_RES_RSIZE; ++i)
++		dev->sa[i] = NULL;
++
++	pci_set_drvdata(pdev, dev);
++
++	tasklet_init(&dev->tasklet, hifn_tasklet_callback, (unsigned long)dev);
++
++	crypto_init_queue(&dev->queue, 1);
++
++	err = request_irq(dev->irq, hifn_interrupt, IRQF_SHARED, dev->name, dev);
++	if (err) {
++		dprintk("Failed to request IRQ%d: err: %d.\n", dev->irq, err);
++		dev->irq = 0;
++		goto err_out_free_desc;
++	}
++
++	err = hifn_start_device(dev);
++	if (err)
++		goto err_out_free_irq;
++
++	err = hifn_test(dev, 1, 0);
++	if (err)
++		goto err_out_stop_device;
++
++	err = hifn_register_rng(dev);
++	if (err)
++		goto err_out_stop_device;
++
++	err = hifn_register_alg(dev);
++	if (err)
++		goto err_out_unregister_rng;
++
++	INIT_DELAYED_WORK(&dev->work, hifn_work);
++	schedule_delayed_work(&dev->work, HZ);
++
++	dprintk("HIFN crypto accelerator card at %s has been "
++			"successfully registered as %s.\n",
++			pci_name(pdev), dev->name);
++
++	return 0;
++
++err_out_unregister_rng:
++	hifn_unregister_rng(dev);
++err_out_stop_device:
++	hifn_reset_dma(dev, 1);
++	hifn_stop_device(dev);
++err_out_free_irq:
++	free_irq(dev->irq, dev->name);
++	tasklet_kill(&dev->tasklet);
++err_out_free_desc:
++	pci_free_consistent(pdev, sizeof(struct hifn_dma),
++			dev->desc_virt, dev->desc_dma);
++
++err_out_free_result_pages:
++	pci_unmap_single(pdev, dev->dst, PAGE_SIZE << HIFN_MAX_RESULT_ORDER,
++			PCI_DMA_FROMDEVICE);
++	free_pages(dev->result_mem, HIFN_MAX_RESULT_ORDER);
++
++err_out_unmap_bars:
++	for (i=0; i<3; ++i)
++		if (dev->bar[i])
++			iounmap(dev->bar[i]);
++
++err_out_free_regions:
++	pci_release_regions(pdev);
++
++err_out_disable_pci_device:
++	pci_disable_device(pdev);
++
 +	return err;
 +}
 +
-+/* Implement DMA read using SPI command
-+ * 0 -> 0x30
-+ * 1 -> mode
-+ * 2 -> block >> 16
-+ * 3 -> block >> 8
-+ * 4 -> block
-+ * 8 -> sectors >> 16
-+ * 9 -> sectors >> 8
-+ * 10 -> sectors
-+ */
-+static void gdrom_readdisk_dma(struct work_struct *work)
++static void hifn_remove(struct pci_dev *pdev)
 +{
-+	int err, block, block_cnt;
-+	struct packet_command *read_command;
-+	struct list_head *elem, *next;
-+	struct request *req;
-+	unsigned long timeout;
++	int i;
++	struct hifn_device *dev;
 +
-+	if (list_empty(&gdrom_deferred))
-+		return;
-+	read_command = kzalloc(sizeof(struct packet_command), GFP_KERNEL);
-+	if (!read_command)
-+		return; /* get more memory later? */
-+	read_command->cmd[0] = 0x30;
-+	read_command->cmd[1] = 0x20;
-+	spin_lock(&gdrom_lock);
-+	list_for_each_safe(elem, next, &gdrom_deferred) {
-+		req = list_entry(elem, struct request, queuelist);
-+		spin_unlock(&gdrom_lock);
-+		block = req->sector/GD_TO_BLK + GD_SESSION_OFFSET;
-+		block_cnt = req->nr_sectors/GD_TO_BLK;
-+		ctrl_outl(PHYSADDR(req->buffer), GDROM_DMA_STARTADDR_REG);
-+		ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG);
-+		ctrl_outl(1, GDROM_DMA_DIRECTION_REG);
-+		ctrl_outl(1, GDROM_DMA_ENABLE_REG);
-+		read_command->cmd[2] = (block >> 16) & 0xFF;
-+		read_command->cmd[3] = (block >> 8) & 0xFF;
-+		read_command->cmd[4] = block & 0xFF;
-+		read_command->cmd[8] = (block_cnt >> 16) & 0xFF;
-+		read_command->cmd[9] = (block_cnt >> 8) & 0xFF;
-+		read_command->cmd[10] = block_cnt & 0xFF;
-+		/* set for DMA */
-+		ctrl_outb(1, GDROM_ERROR_REG);
-+		/* other registers */
-+		ctrl_outb(0, GDROM_SECNUM_REG);
-+		ctrl_outb(0, GDROM_BCL_REG);
-+		ctrl_outb(0, GDROM_BCH_REG);
-+		ctrl_outb(0, GDROM_DSEL_REG);
-+		ctrl_outb(0, GDROM_INTSEC_REG);
-+		/* Wait for registers to reset after any previous activity */
-+		timeout = jiffies + HZ / 2;
-+		while (gdrom_is_busy() && time_before(jiffies, timeout))
-+			cpu_relax();
-+		ctrl_outb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG);
-+		timeout = jiffies + HZ / 2;
-+		/* Wait for packet command to finish */
-+		while (gdrom_is_busy() && time_before(jiffies, timeout))
-+			cpu_relax();
-+		gd.pending = 1;
-+		gd.transfer = 1;
-+		outsw(PHYSADDR(GDROM_DATA_REG), &read_command->cmd, 6);
-+		timeout = jiffies + HZ / 2;
-+		/* Wait for any pending DMA to finish */
-+		while (ctrl_inb(GDROM_DMA_STATUS_REG) &&
-+			time_before(jiffies, timeout))
-+			cpu_relax();
-+		/* start transfer */
-+		ctrl_outb(1, GDROM_DMA_STATUS_REG);
-+		wait_event_interruptible_timeout(request_queue,
-+			gd.transfer == 0, GDROM_DEFAULT_TIMEOUT);
-+		err = gd.transfer;
-+		gd.transfer = 0;
-+		gd.pending = 0;
-+		/* now seek to take the request spinlock
-+		* before handling ending the request */
-+		spin_lock(&gdrom_lock);
-+		list_del_init(&req->queuelist);
-+		end_dequeued_request(req, 1 - err);
++	dev = pci_get_drvdata(pdev);
++
++	if (dev) {
++		cancel_delayed_work(&dev->work);
++		flush_scheduled_work();
++
++		hifn_unregister_rng(dev);
++		hifn_unregister_alg(dev);
++		hifn_reset_dma(dev, 1);
++		hifn_stop_device(dev);
++
++		free_irq(dev->irq, dev->name);
++		tasklet_kill(&dev->tasklet);
++
++		hifn_flush(dev);
++
++		pci_free_consistent(pdev, sizeof(struct hifn_dma),
++				dev->desc_virt, dev->desc_dma);
++		pci_unmap_single(pdev, dev->dst,
++				PAGE_SIZE << HIFN_MAX_RESULT_ORDER,
++				PCI_DMA_FROMDEVICE);
++		free_pages(dev->result_mem, HIFN_MAX_RESULT_ORDER);
++		for (i=0; i<3; ++i)
++			if (dev->bar[i])
++				iounmap(dev->bar[i]);
++
++		kfree(dev);
 +	}
-+	spin_unlock(&gdrom_lock);
-+	kfree(read_command);
-+}
 +
-+static void gdrom_request_handler_dma(struct request *req)
-+{
-+	/* dequeue, add to list of deferred work
-+	* and then schedule workqueue */
-+	blkdev_dequeue_request(req);
-+	list_add_tail(&req->queuelist, &gdrom_deferred);
-+	schedule_work(&work);
++	pci_release_regions(pdev);
++	pci_disable_device(pdev);
 +}
 +
-+static void gdrom_request(struct request_queue *rq)
++static struct pci_device_id hifn_pci_tbl[] = {
++	{ PCI_DEVICE(PCI_VENDOR_ID_HIFN, PCI_DEVICE_ID_HIFN_7955) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_HIFN, PCI_DEVICE_ID_HIFN_7956) },
++	{ 0 }
++};
++MODULE_DEVICE_TABLE(pci, hifn_pci_tbl);
++
++static struct pci_driver hifn_pci_driver = {
++	.name     = "hifn795x",
++	.id_table = hifn_pci_tbl,
++	.probe    = hifn_probe,
++	.remove   = __devexit_p(hifn_remove),
++};
++
++static int __devinit hifn_init(void)
 +{
-+	struct request *req;
++	unsigned int freq;
++	int err;
 +
-+	while ((req = elv_next_request(rq)) != NULL) {
-+		if (!blk_fs_request(req)) {
-+			printk(KERN_DEBUG "GDROM: Non-fs request ignored\n");
-+			end_request(req, 0);
-+		}
-+		if (rq_data_dir(req) != READ) {
-+			printk(KERN_NOTICE "GDROM: Read only device -");
-+			printk(" write request ignored\n");
-+			end_request(req, 0);
++	if (strncmp(hifn_pll_ref, "ext", 3) &&
++	    strncmp(hifn_pll_ref, "pci", 3)) {
++		printk(KERN_ERR "hifn795x: invalid hifn_pll_ref clock, "
++				"must be pci or ext");
++		return -EINVAL;
++	}
++
++	/*
++	 * For the 7955/7956 the reference clock frequency must be in the
++	 * range of 20MHz-100MHz. For the 7954 the upper bound is 66.67MHz,
++	 * but this chip is currently not supported.
++	 */
++	if (hifn_pll_ref[3] != '\0') {
++		freq = simple_strtoul(hifn_pll_ref + 3, NULL, 10);
++		if (freq < 20 || freq > 100) {
++			printk(KERN_ERR "hifn795x: invalid hifn_pll_ref "
++					"frequency, must be in the range "
++					"of 20-100");
++			return -EINVAL;
 +		}
-+		if (req->nr_sectors)
-+			gdrom_request_handler_dma(req);
-+		else
-+			end_request(req, 0);
 +	}
-+}
 +
-+/* Print string identifying GD ROM device */
-+static int __devinit gdrom_outputversion(void)
-+{
-+	struct gdrom_id *id;
-+	char *model_name, *manuf_name, *firmw_ver;
-+	int err = -ENOMEM;
++	err = pci_register_driver(&hifn_pci_driver);
++	if (err < 0) {
++		dprintk("Failed to register PCI driver for %s device.\n",
++				hifn_pci_driver.name);
++		return -ENODEV;
++	}
 +
-+	/* query device ID */
-+	id = kzalloc(sizeof(struct gdrom_id), GFP_KERNEL);
-+	if (!id)
-+		return err;
-+	gdrom_identifydevice(id);
-+	model_name = kstrndup(id->modname, 16, GFP_KERNEL);
-+	if (!model_name)
-+		goto free_id;
-+	manuf_name = kstrndup(id->mname, 16, GFP_KERNEL);
-+	if (!manuf_name)
-+		goto free_model_name;
-+	firmw_ver = kstrndup(id->firmver, 16, GFP_KERNEL);
-+	if (!firmw_ver)
-+		goto free_manuf_name;
-+	printk(KERN_INFO "GDROM: %s from %s with firmware %s\n",
-+		model_name, manuf_name, firmw_ver);
-+	err = 0;
-+	kfree(firmw_ver);
-+free_manuf_name:
-+	kfree(manuf_name);
-+free_model_name:
-+	kfree(model_name);
-+free_id:
-+	kfree(id);
-+	return err;
-+}
++	printk(KERN_INFO "Driver for HIFN 795x crypto accelerator chip "
++			"has been successfully registered.\n");
 +
-+/* set the default mode for DMA transfer */
-+static int __devinit gdrom_init_dma_mode(void)
-+{
-+	ctrl_outb(0x13, GDROM_ERROR_REG);
-+	ctrl_outb(0x22, GDROM_INTSEC_REG);
-+	if (!gdrom_wait_clrbusy())
-+		return -EBUSY;
-+	ctrl_outb(0xEF, GDROM_STATUSCOMMAND_REG);
-+	if (!gdrom_wait_busy_sleeps())
-+		return -EBUSY;
-+	/* Memory protection setting for GDROM DMA
-+	* Bits 31 - 16 security: 0x8843
-+	* Bits 15 and 7 reserved (0)
-+	* Bits 14 - 8 start of transfer range in 1 MB blocks OR'ed with 0x80
-+	* Bits 6 - 0 end of transfer range in 1 MB blocks OR'ed with 0x80
-+	* (0x40 | 0x80) = start range at 0x0C000000
-+	* (0x7F | 0x80) = end range at 0x0FFFFFFF */
-+	ctrl_outl(0x8843407F, GDROM_DMA_ACCESS_CTRL_REG);
-+	ctrl_outl(9, GDROM_DMA_WAIT_REG); /* DMA word setting */
 +	return 0;
 +}
 +
-+static void __devinit probe_gdrom_setupcd(void)
++static void __devexit hifn_fini(void)
 +{
-+	gd.cd_info->ops = &gdrom_ops;
-+	gd.cd_info->capacity = 1;
-+	strcpy(gd.cd_info->name, GDROM_DEV_NAME);
-+	gd.cd_info->mask = CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|
-+		CDC_SELECT_DISC;
-+}
++	pci_unregister_driver(&hifn_pci_driver);
 +
-+static void __devinit probe_gdrom_setupdisk(void)
-+{
-+	gd.disk->major = gdrom_major;
-+	gd.disk->first_minor = 1;
-+	gd.disk->minors = 1;
-+	strcpy(gd.disk->disk_name, GDROM_DEV_NAME);
++	printk(KERN_INFO "Driver for HIFN 795x crypto accelerator chip "
++			"has been successfully unregistered.\n");
 +}
 +
-+static int __devinit probe_gdrom_setupqueue(void)
++module_init(hifn_init);
++module_exit(hifn_fini);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Evgeniy Polyakov <johnpol at 2ka.mipt.ru>");
++MODULE_DESCRIPTION("Driver for HIFN 795x crypto accelerator chip.");
+diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
+index 5f7e718..2f3ad3f 100644
+--- a/drivers/crypto/padlock-aes.c
++++ b/drivers/crypto/padlock-aes.c
+@@ -44,6 +44,7 @@
+  */
+ 
+ #include <crypto/algapi.h>
++#include <crypto/aes.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/types.h>
+@@ -53,9 +54,6 @@
+ #include <asm/byteorder.h>
+ #include "padlock.h"
+ 
+-#define AES_MIN_KEY_SIZE	16	/* in uint8_t units */
+-#define AES_MAX_KEY_SIZE	32	/* ditto */
+-#define AES_BLOCK_SIZE		16	/* ditto */
+ #define AES_EXTENDED_KEY_SIZE	64	/* in uint32_t units */
+ #define AES_EXTENDED_KEY_SIZE_B	(AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
+ 
+@@ -419,6 +417,11 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
+ /* ====== Encryption/decryption routines ====== */
+ 
+ /* These are the real call to PadLock. */
++static inline void padlock_reset_key(void)
 +{
-+	blk_queue_hardsect_size(gd.gdrom_rq, GDROM_HARD_SECTOR);
-+	/* using DMA so memory will need to be contiguous */
-+	blk_queue_max_hw_segments(gd.gdrom_rq, 1);
-+	/* set a large max size to get most from DMA */
-+	blk_queue_max_segment_size(gd.gdrom_rq, 0x40000);
-+	gd.disk->queue = gd.gdrom_rq;
-+	return gdrom_init_dma_mode();
++	asm volatile ("pushfl; popfl");
 +}
 +
+ static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
+ 				  void *control_word)
+ {
+@@ -439,8 +442,6 @@ static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword)
+ static inline void aes_crypt(const u8 *in, u8 *out, u32 *key,
+ 			     struct cword *cword)
+ {
+-	asm volatile ("pushfl; popfl");
+-
+ 	/* padlock_xcrypt requires at least two blocks of data. */
+ 	if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) &
+ 		       (PAGE_SIZE - 1)))) {
+@@ -459,7 +460,6 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
+ 		return;
+ 	}
+ 
+-	asm volatile ("pushfl; popfl");		/* enforce key reload. */
+ 	asm volatile ("test $1, %%cl;"
+ 		      "je 1f;"
+ 		      "lea -1(%%ecx), %%eax;"
+@@ -476,8 +476,6 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
+ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
+ 				     u8 *iv, void *control_word, u32 count)
+ {
+-	/* Enforce key reload. */
+-	asm volatile ("pushfl; popfl");
+ 	/* rep xcryptcbc */
+ 	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"
+ 		      : "+S" (input), "+D" (output), "+a" (iv)
+@@ -488,12 +486,14 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
+ static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+ 	struct aes_ctx *ctx = aes_ctx(tfm);
++	padlock_reset_key();
+ 	aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
+ }
+ 
+ static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ {
+ 	struct aes_ctx *ctx = aes_ctx(tfm);
++	padlock_reset_key();
+ 	aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
+ }
+ 
+@@ -526,6 +526,8 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err;
+ 
++	padlock_reset_key();
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
+ 
+@@ -548,6 +550,8 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err;
+ 
++	padlock_reset_key();
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
+ 
+@@ -592,6 +596,8 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err;
+ 
++	padlock_reset_key();
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
+ 
+@@ -616,6 +622,8 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
+ 	struct blkcipher_walk walk;
+ 	int err;
+ 
++	padlock_reset_key();
++
+ 	blkcipher_walk_init(&walk, dst, src, nbytes);
+ 	err = blkcipher_walk_virt(desc, &walk);
+ 
+diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c
+index e4c48e3..8cd8507 100644
+--- a/drivers/dio/dio-driver.c
++++ b/drivers/dio/dio-driver.c
+@@ -15,16 +15,15 @@
+ #include <linux/dio.h>
+ 
+ 
+-	/**
+-	 *  dio_match_device - Tell if a DIO device structure has a matching
+-	 *                     DIO device id structure
+-	 *  @ids: array of DIO device id structures to search in
+-	 *  @dev: the DIO device structure to match against
+-	 *
+-	 *  Used by a driver to check whether a DIO device present in the
+-	 *  system is in its list of supported devices. Returns the matching
+-	 *  dio_device_id structure or %NULL if there is no match.
+-	 */
++/**
++ *  dio_match_device - Tell if a DIO device structure has a matching DIO device id structure
++ *  @ids: array of DIO device id structures to search in
++ *  @d: the DIO device structure to match against
++ *
++ *  Used by a driver to check whether a DIO device present in the
++ *  system is in its list of supported devices. Returns the matching
++ *  dio_device_id structure or %NULL if there is no match.
++ */
+ 
+ const struct dio_device_id *
+ dio_match_device(const struct dio_device_id *ids,
+@@ -66,13 +65,13 @@ static int dio_device_probe(struct device *dev)
+ }
+ 
+ 
+-	/**
+-	 *  dio_register_driver - register a new DIO driver
+-	 *  @drv: the driver structure to register
+-	 *
+-	 *  Adds the driver structure to the list of registered drivers
+-	 *  Returns zero or a negative error value.
+-	 */
++/**
++ *  dio_register_driver - register a new DIO driver
++ *  @drv: the driver structure to register
++ *
++ *  Adds the driver structure to the list of registered drivers
++ *  Returns zero or a negative error value.
++ */
+ 
+ int dio_register_driver(struct dio_driver *drv)
+ {
+@@ -85,15 +84,15 @@ int dio_register_driver(struct dio_driver *drv)
+ }
+ 
+ 
+-	/**
+-	 *  dio_unregister_driver - unregister a DIO driver
+-	 *  @drv: the driver structure to unregister
+-	 *
+-	 *  Deletes the driver structure from the list of registered DIO drivers,
+-	 *  gives it a chance to clean up by calling its remove() function for
+-	 *  each device it was responsible for, and marks those devices as
+-	 *  driverless.
+-	 */
++/**
++ *  dio_unregister_driver - unregister a DIO driver
++ *  @drv: the driver structure to unregister
++ *
++ *  Deletes the driver structure from the list of registered DIO drivers,
++ *  gives it a chance to clean up by calling its remove() function for
++ *  each device it was responsible for, and marks those devices as
++ *  driverless.
++ */
+ 
+ void dio_unregister_driver(struct dio_driver *drv)
+ {
+@@ -101,16 +100,15 @@ void dio_unregister_driver(struct dio_driver *drv)
+ }
+ 
+ 
+-	/**
+-	 *  dio_bus_match - Tell if a DIO device structure has a matching DIO
+-	 *                  device id structure
+-	 *  @ids: array of DIO device id structures to search in
+-	 *  @dev: the DIO device structure to match against
+-	 *
+-	 *  Used by a driver to check whether a DIO device present in the
+-	 *  system is in its list of supported devices. Returns the matching
+-	 *  dio_device_id structure or %NULL if there is no match.
+-	 */
++/**
++ *  dio_bus_match - Tell if a DIO device structure has a matching DIO device id structure
++ *  @dev: the DIO device structure to match against
++ *  @drv: the &device_driver that points to the array of DIO device id structures to search
++ *
++ *  Used by a driver to check whether a DIO device present in the
++ *  system is in its list of supported devices. Returns the matching
++ *  dio_device_id structure or %NULL if there is no match.
++ */
+ 
+ static int dio_bus_match(struct device *dev, struct device_driver *drv)
+ {
+diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c
+index 17502d6..07f274f 100644
+--- a/drivers/dio/dio.c
++++ b/drivers/dio/dio.c
+@@ -88,8 +88,6 @@ static struct dioname names[] =
+ #undef DIONAME
+ #undef DIOFBNAME
+ 
+-#define NUMNAMES (sizeof(names) / sizeof(struct dioname))
+-
+ static const char *unknowndioname 
+         = "unknown DIO board -- please email <linux-m68k at lists.linux-m68k.org>!";
+ 
+@@ -97,7 +95,7 @@ static const char *dio_getname(int id)
+ {
+         /* return pointer to a constant string describing the board with given ID */
+ 	unsigned int i;
+-        for (i = 0; i < NUMNAMES; i++)
++	for (i = 0; i < ARRAY_SIZE(names); i++)
+                 if (names[i].id == id) 
+                         return names[i].name;
+ 
+diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
+index d59b2f4..bcf52df 100644
+--- a/drivers/dma/dmaengine.c
++++ b/drivers/dma/dmaengine.c
+@@ -41,12 +41,12 @@
+  * the definition of dma_event_callback in dmaengine.h.
+  *
+  * Each device has a kref, which is initialized to 1 when the device is
+- * registered. A kref_get is done for each class_device registered.  When the
+- * class_device is released, the coresponding kref_put is done in the release
++ * registered. A kref_get is done for each device registered.  When the
++ * device is released, the coresponding kref_put is done in the release
+  * method. Every time one of the device's channels is allocated to a client,
+  * a kref_get occurs.  When the channel is freed, the coresponding kref_put
+  * happens. The device's release function does a completion, so
+- * unregister_device does a remove event, class_device_unregister, a kref_put
++ * unregister_device does a remove event, device_unregister, a kref_put
+  * for the first reference, then waits on the completion for all other
+  * references to finish.
+  *
+@@ -77,9 +77,9 @@ static LIST_HEAD(dma_client_list);
+ 
+ /* --- sysfs implementation --- */
+ 
+-static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
++static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
++	struct dma_chan *chan = to_dma_chan(dev);
+ 	unsigned long count = 0;
+ 	int i;
+ 
+@@ -89,9 +89,10 @@ static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
+ 	return sprintf(buf, "%lu\n", count);
+ }
+ 
+-static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
++static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr,
++				      char *buf)
+ {
+-	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
++	struct dma_chan *chan = to_dma_chan(dev);
+ 	unsigned long count = 0;
+ 	int i;
+ 
+@@ -101,9 +102,9 @@ static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
+ 	return sprintf(buf, "%lu\n", count);
+ }
+ 
+-static ssize_t show_in_use(struct class_device *cd, char *buf)
++static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+-	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
++	struct dma_chan *chan = to_dma_chan(dev);
+ 	int in_use = 0;
+ 
+ 	if (unlikely(chan->slow_ref) &&
+@@ -119,7 +120,7 @@ static ssize_t show_in_use(struct class_device *cd, char *buf)
+ 	return sprintf(buf, "%d\n", in_use);
+ }
+ 
+-static struct class_device_attribute dma_class_attrs[] = {
++static struct device_attribute dma_attrs[] = {
+ 	__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
+ 	__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
+ 	__ATTR(in_use, S_IRUGO, show_in_use, NULL),
+@@ -128,16 +129,16 @@ static struct class_device_attribute dma_class_attrs[] = {
+ 
+ static void dma_async_device_cleanup(struct kref *kref);
+ 
+-static void dma_class_dev_release(struct class_device *cd)
++static void dma_dev_release(struct device *dev)
+ {
+-	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
++	struct dma_chan *chan = to_dma_chan(dev);
+ 	kref_put(&chan->device->refcount, dma_async_device_cleanup);
+ }
+ 
+ static struct class dma_devclass = {
+-	.name            = "dma",
+-	.class_dev_attrs = dma_class_attrs,
+-	.release = dma_class_dev_release,
++	.name		= "dma",
++	.dev_attrs	= dma_attrs,
++	.dev_release	= dma_dev_release,
+ };
+ 
+ /* --- client and device registration --- */
+@@ -377,12 +378,12 @@ int dma_async_device_register(struct dma_device *device)
+ 			continue;
+ 
+ 		chan->chan_id = chancnt++;
+-		chan->class_dev.class = &dma_devclass;
+-		chan->class_dev.dev = NULL;
+-		snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
++		chan->dev.class = &dma_devclass;
++		chan->dev.parent = NULL;
++		snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d",
+ 		         device->dev_id, chan->chan_id);
+ 
+-		rc = class_device_register(&chan->class_dev);
++		rc = device_register(&chan->dev);
+ 		if (rc) {
+ 			chancnt--;
+ 			free_percpu(chan->local);
+@@ -411,7 +412,7 @@ err_out:
+ 		if (chan->local == NULL)
+ 			continue;
+ 		kref_put(&device->refcount, dma_async_device_cleanup);
+-		class_device_unregister(&chan->class_dev);
++		device_unregister(&chan->dev);
+ 		chancnt--;
+ 		free_percpu(chan->local);
+ 	}
+@@ -445,7 +446,7 @@ void dma_async_device_unregister(struct dma_device *device)
+ 
+ 	list_for_each_entry(chan, &device->channels, device_node) {
+ 		dma_clients_notify_removed(chan);
+-		class_device_unregister(&chan->class_dev);
++		device_unregister(&chan->dev);
+ 		dma_chan_release(chan);
+ 	}
+ 
+diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
+index 70b837f..5376457 100644
+--- a/drivers/edac/edac_device_sysfs.c
++++ b/drivers/edac/edac_device_sysfs.c
+@@ -246,16 +246,6 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
+ 
+ 	/* Init the devices's kobject */
+ 	memset(&edac_dev->kobj, 0, sizeof(struct kobject));
+-	edac_dev->kobj.ktype = &ktype_device_ctrl;
+-
+-	/* set this new device under the edac_class kobject */
+-	edac_dev->kobj.parent = &edac_class->kset.kobj;
+-
+-	/* generate sysfs "..../edac/<name>"   */
+-	debugf4("%s() set name of kobject to: %s\n", __func__, edac_dev->name);
+-	err = kobject_set_name(&edac_dev->kobj, "%s", edac_dev->name);
+-	if (err)
+-		goto err_out;
+ 
+ 	/* Record which module 'owns' this control structure
+ 	 * and bump the ref count of the module
+@@ -268,12 +258,15 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
+ 	}
+ 
+ 	/* register */
+-	err = kobject_register(&edac_dev->kobj);
++	err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
++				   &edac_class->kset.kobj,
++				   "%s", edac_dev->name);
+ 	if (err) {
+ 		debugf1("%s()Failed to register '.../edac/%s'\n",
+ 			__func__, edac_dev->name);
+ 		goto err_kobj_reg;
+ 	}
++	kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
+ 
+ 	/* At this point, to 'free' the control struct,
+ 	 * edac_device_unregister_sysfs_main_kobj() must be used
+@@ -310,7 +303,7 @@ void edac_device_unregister_sysfs_main_kobj(
+ 	 *   a) module_put() this module
+ 	 *   b) 'kfree' the memory
+ 	 */
+-	kobject_unregister(&edac_dev->kobj);
++	kobject_put(&edac_dev->kobj);
+ }
+ 
+ /* edac_dev -> instance information */
+@@ -533,12 +526,6 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
+ 
+ 	/* init this block's kobject */
+ 	memset(&block->kobj, 0, sizeof(struct kobject));
+-	block->kobj.parent = &instance->kobj;
+-	block->kobj.ktype = &ktype_block_ctrl;
+-
+-	err = kobject_set_name(&block->kobj, "%s", block->name);
+-	if (err)
+-		return err;
+ 
+ 	/* bump the main kobject's reference count for this controller
+ 	 * and this instance is dependant on the main
+@@ -550,7 +537,9 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
+ 	}
+ 
+ 	/* Add this block's kobject */
+-	err = kobject_register(&block->kobj);
++	err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
++				   &instance->kobj,
++				   "%s", block->name);
+ 	if (err) {
+ 		debugf1("%s() Failed to register instance '%s'\n",
+ 			__func__, block->name);
+@@ -579,12 +568,13 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
+ 				goto err_on_attrib;
+ 		}
+ 	}
++	kobject_uevent(&block->kobj, KOBJ_ADD);
+ 
+ 	return 0;
+ 
+ 	/* Error unwind stack */
+ err_on_attrib:
+-	kobject_unregister(&block->kobj);
++	kobject_put(&block->kobj);
+ 
+ err_out:
+ 	return err;
+@@ -615,7 +605,7 @@ static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
+ 	/* unregister this block's kobject, SEE:
+ 	 *	edac_device_ctrl_block_release() callback operation
+ 	 */
+-	kobject_unregister(&block->kobj);
++	kobject_put(&block->kobj);
+ }
+ 
+ /* instance ctor/dtor code */
+@@ -637,15 +627,8 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
+ 	/* Init the instance's kobject */
+ 	memset(&instance->kobj, 0, sizeof(struct kobject));
+ 
+-	/* set this new device under the edac_device main kobject */
+-	instance->kobj.parent = &edac_dev->kobj;
+-	instance->kobj.ktype = &ktype_instance_ctrl;
+ 	instance->ctl = edac_dev;
+ 
+-	err = kobject_set_name(&instance->kobj, "%s", instance->name);
+-	if (err)
+-		goto err_out;
+-
+ 	/* bump the main kobject's reference count for this controller
+ 	 * and this instance is dependant on the main
+ 	 */
+@@ -655,8 +638,9 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
+ 		goto err_out;
+ 	}
+ 
+-	/* Formally register this instance's kobject */
+-	err = kobject_register(&instance->kobj);
++	/* Formally register this instance's kobject under the edac_device */
++	err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
++				   &edac_dev->kobj, "%s", instance->name);
+ 	if (err != 0) {
+ 		debugf2("%s() Failed to register instance '%s'\n",
+ 			__func__, instance->name);
+@@ -679,6 +663,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
+ 			goto err_release_instance_kobj;
+ 		}
+ 	}
++	kobject_uevent(&instance->kobj, KOBJ_ADD);
+ 
+ 	debugf4("%s() Registered instance %d '%s' kobject\n",
+ 		__func__, idx, instance->name);
+@@ -687,7 +672,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
+ 
+ 	/* error unwind stack */
+ err_release_instance_kobj:
+-	kobject_unregister(&instance->kobj);
++	kobject_put(&instance->kobj);
+ 
+ err_out:
+ 	return err;
+@@ -712,7 +697,7 @@ static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
+ 	/* unregister this instance's kobject, SEE:
+ 	 *	edac_device_ctrl_instance_release() for callback operation
+ 	 */
+-	kobject_unregister(&instance->kobj);
++	kobject_put(&instance->kobj);
+ }
+ 
+ /*
+diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
+index 3706b2b..9aac880 100644
+--- a/drivers/edac/edac_mc_sysfs.c
++++ b/drivers/edac/edac_mc_sysfs.c
+@@ -380,13 +380,6 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
+ 	/* generate ..../edac/mc/mc<id>/csrow<index>   */
+ 	memset(&csrow->kobj, 0, sizeof(csrow->kobj));
+ 	csrow->mci = mci;	/* include container up link */
+-	csrow->kobj.parent = kobj_mci;
+-	csrow->kobj.ktype = &ktype_csrow;
+-
+-	/* name this instance of csrow<id> */
+-	err = kobject_set_name(&csrow->kobj, "csrow%d", index);
+-	if (err)
+-		goto err_out;
+ 
+ 	/* bump the mci instance's kobject's ref count */
+ 	kobj = kobject_get(&mci->edac_mci_kobj);
+@@ -396,12 +389,13 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
+ 	}
+ 
+ 	/* Instanstiate the csrow object */
+-	err = kobject_register(&csrow->kobj);
++	err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci,
++				   "csrow%d", index);
+ 	if (err)
+ 		goto err_release_top_kobj;
+ 
+ 	/* At this point, to release a csrow kobj, one must
+-	 * call the kobject_unregister and allow that tear down
++	 * call the kobject_put and allow that tear down
+ 	 * to work the releasing
+ 	 */
+ 
+@@ -412,11 +406,11 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
+ 		err = edac_create_channel_files(&csrow->kobj, chan);
+ 		if (err) {
+ 			/* special case the unregister here */
+-			kobject_unregister(&csrow->kobj);
++			kobject_put(&csrow->kobj);
+ 			goto err_out;
+ 		}
+ 	}
+-
++	kobject_uevent(&csrow->kobj, KOBJ_ADD);
+ 	return 0;
+ 
+ 	/* error unwind stack */
+@@ -744,7 +738,6 @@ static struct kobj_type ktype_mc_set_attribs = {
+  */
+ static struct kset mc_kset = {
+ 	.kobj = {.ktype = &ktype_mc_set_attribs },
+-	.ktype = &ktype_mci,
+ };
+ 
+ 
+@@ -765,14 +758,6 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
+ 	/* Init the mci's kobject */
+ 	memset(kobj_mci, 0, sizeof(*kobj_mci));
+ 
+-	/* this instance become part of the mc_kset */
+-	kobj_mci->kset = &mc_kset;
+-
+-	/* set the name of the mc<id> object */
+-	err = kobject_set_name(kobj_mci, "mc%d", mci->mc_idx);
+-	if (err)
+-		goto fail_out;
+-
+ 	/* Record which module 'owns' this control structure
+ 	 * and bump the ref count of the module
+ 	 */
+@@ -784,13 +769,18 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
+ 		goto fail_out;
+ 	}
+ 
++	/* this instance become part of the mc_kset */
++	kobj_mci->kset = &mc_kset;
++
+ 	/* register the mc<id> kobject to the mc_kset */
+-	err = kobject_register(kobj_mci);
++	err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
++				   "mc%d", mci->mc_idx);
+ 	if (err) {
+ 		debugf1("%s()Failed to register '.../edac/mc%d'\n",
+ 			__func__, mci->mc_idx);
+ 		goto kobj_reg_fail;
+ 	}
++	kobject_uevent(kobj_mci, KOBJ_ADD);
+ 
+ 	/* At this point, to 'free' the control struct,
+ 	 * edac_mc_unregister_sysfs_main_kobj() must be used
+@@ -818,7 +808,7 @@ fail_out:
+ void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
+ {
+ 	/* delete the kobj from the mc_kset */
+-	kobject_unregister(&mci->edac_mci_kobj);
++	kobject_put(&mci->edac_mci_kobj);
+ }
+ 
+ #define EDAC_DEVICE_SYMLINK	"device"
+@@ -933,7 +923,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+ fail1:
+ 	for (i--; i >= 0; i--) {
+ 		if (csrow->nr_pages > 0) {
+-			kobject_unregister(&mci->csrows[i].kobj);
++			kobject_put(&mci->csrows[i].kobj);
+ 		}
+ 	}
+ 
+@@ -960,7 +950,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
+ 	for (i = 0; i < mci->nr_csrows; i++) {
+ 		if (mci->csrows[i].nr_pages > 0) {
+ 			debugf0("%s()  unreg csrow-%d\n", __func__, i);
+-			kobject_unregister(&mci->csrows[i].kobj);
++			kobject_put(&mci->csrows[i].kobj);
+ 		}
+ 	}
+ 
+@@ -977,7 +967,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
+ 	debugf0("%s()  unregister this mci kobj\n", __func__);
+ 
+ 	/* unregister this instance's kobject */
+-	kobject_unregister(&mci->edac_mci_kobj);
++	kobject_put(&mci->edac_mci_kobj);
+ }
+ 
+ 
+diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
+index e0c4a40..7e1374a 100644
+--- a/drivers/edac/edac_module.c
++++ b/drivers/edac/edac_module.c
+@@ -31,7 +31,7 @@ struct workqueue_struct *edac_workqueue;
+  *	need to export to other files in this modules
+  */
+ static struct sysdev_class edac_class = {
+-	set_kset_name("edac"),
++	.name = "edac",
+ };
+ static int edac_class_valid;
+ 
+diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
+index 5dee9f5..e0b47b7 100644
+--- a/drivers/edac/edac_pci.c
++++ b/drivers/edac/edac_pci.c
+@@ -73,7 +73,7 @@ EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
+  *
+  *	Last action on the pci control structure.
+  *
+- *	call the remove sysfs informaton, which will unregister
++ *	call the remove sysfs information, which will unregister
+  *	this control struct's kobj. When that kobj's ref count
+  *	goes to zero, its release function will be call and then
+  *	kfree() the memory.
+diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
+index 69f5ddd..5b075da 100644
+--- a/drivers/edac/edac_pci_sysfs.c
++++ b/drivers/edac/edac_pci_sysfs.c
+@@ -162,14 +162,6 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
+ 
+ 	debugf0("%s()\n", __func__);
+ 
+-	/* Set the parent and the instance's ktype */
+-	pci->kobj.parent = &edac_pci_top_main_kobj;
+-	pci->kobj.ktype = &ktype_pci_instance;
+-
+-	err = kobject_set_name(&pci->kobj, "pci%d", idx);
+-	if (err)
+-		return err;
+-
+ 	/* First bump the ref count on the top main kobj, which will
+ 	 * track the number of PCI instances we have, and thus nest
+ 	 * properly on keeping the module loaded
+@@ -181,7 +173,8 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
+ 	}
+ 
+ 	/* And now register this new kobject under the main kobj */
+-	err = kobject_register(&pci->kobj);
++	err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
++				   &edac_pci_top_main_kobj, "pci%d", idx);
+ 	if (err != 0) {
+ 		debugf2("%s() failed to register instance pci%d\n",
+ 			__func__, idx);
+@@ -189,6 +182,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
+ 		goto error_out;
+ 	}
+ 
++	kobject_uevent(&pci->kobj, KOBJ_ADD);
+ 	debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx);
+ 
+ 	return 0;
+@@ -211,7 +205,7 @@ void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci)
+ 	 * function release the main reference count and then
+ 	 * kfree the memory
+ 	 */
+-	kobject_unregister(&pci->kobj);
++	kobject_put(&pci->kobj);
+ }
+ 
+ /***************************** EDAC PCI sysfs root **********************/
+@@ -364,14 +358,6 @@ int edac_pci_main_kobj_setup(void)
+ 		goto decrement_count_fail;
+ 	}
+ 
+-	/* Need the kobject hook ups, and name setting */
+-	edac_pci_top_main_kobj.ktype = &ktype_edac_pci_main_kobj;
+-	edac_pci_top_main_kobj.parent = &edac_class->kset.kobj;
+-
+-	err = kobject_set_name(&edac_pci_top_main_kobj, "pci");
+-	if (err)
+-		goto decrement_count_fail;
+-
+ 	/* Bump the reference count on this module to ensure the
+ 	 * modules isn't unloaded until we deconstruct the top
+ 	 * level main kobj for EDAC PCI
+@@ -383,23 +369,24 @@ int edac_pci_main_kobj_setup(void)
+ 	}
+ 
+ 	/* Instanstiate the pci object */
+-	/* FIXME: maybe new sysdev_create_subdir() */
+-	err = kobject_register(&edac_pci_top_main_kobj);
++	err = kobject_init_and_add(&edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj,
++				   &edac_class->kset.kobj, "pci");
+ 	if (err) {
+ 		debugf1("Failed to register '.../edac/pci'\n");
+-		goto kobject_register_fail;
++		goto kobject_init_and_add_fail;
+ 	}
+ 
+ 	/* At this point, to 'release' the top level kobject
+ 	 * for EDAC PCI, then edac_pci_main_kobj_teardown()
+ 	 * must be used, for resources to be cleaned up properly
+ 	 */
++	kobject_uevent(&edac_pci_top_main_kobj, KOBJ_ADD);
+ 	debugf1("Registered '.../edac/pci' kobject\n");
+ 
+ 	return 0;
+ 
+ 	/* Error unwind statck */
+-kobject_register_fail:
++kobject_init_and_add_fail:
+ 	module_put(THIS_MODULE);
+ 
+ decrement_count_fail:
+@@ -424,9 +411,9 @@ static void edac_pci_main_kobj_teardown(void)
+ 	 * main kobj
+ 	 */
+ 	if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
+-		debugf0("%s() called kobject_unregister on main kobj\n",
++		debugf0("%s() called kobject_put on main kobj\n",
+ 			__func__);
+-		kobject_unregister(&edac_pci_top_main_kobj);
++		kobject_put(&edac_pci_top_main_kobj);
+ 	}
+ }
+ 
+diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
+index a1f24c4..5a85201 100644
+--- a/drivers/edac/i5000_edac.c
++++ b/drivers/edac/i5000_edac.c
+@@ -351,7 +351,7 @@ struct i5000_pvt {
+ 	u16 b1_ambpresent0;	/* Branch 1, Channel 8 */
+ 	u16 b1_ambpresent1;	/* Branch 1, Channel 1 */
+ 
+-	/* DIMM infomation matrix, allocating architecture maximums */
++	/* DIMM information matrix, allocating architecture maximums */
+ 	struct i5000_dimm_info dimm_info[MAX_CSROWS][MAX_CHANNELS];
+ 
+ 	/* Actual values for this controller */
+diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c
+index 9007d06..9032091 100644
+--- a/drivers/edac/pasemi_edac.c
++++ b/drivers/edac/pasemi_edac.c
+@@ -225,7 +225,7 @@ static int __devinit pasemi_edac_probe(struct pci_dev *pdev,
+ 		EDAC_FLAG_NONE;
+ 	mci->mod_name = MODULE_NAME;
+ 	mci->dev_name = pci_name(pdev);
+-	mci->ctl_name = "pasemi,1682m-mc";
++	mci->ctl_name = "pasemi,pwrficient-mc";
+ 	mci->edac_check = pasemi_edac_check;
+ 	mci->ctl_page_to_phys = NULL;
+ 	pci_read_config_dword(pdev, MCCFG_SCRUB, &scrub);
+@@ -297,4 +297,4 @@ module_exit(pasemi_edac_exit);
+ 
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("Egor Martovetsky <egor at pasemi.com>");
+-MODULE_DESCRIPTION("MC support for PA Semi PA6T-1682M memory controller");
++MODULE_DESCRIPTION("MC support for PA Semi PWRficient memory controller");
+diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
+index 60f1a89..7e73cba 100644
+--- a/drivers/firewire/fw-cdev.c
++++ b/drivers/firewire/fw-cdev.c
+@@ -206,12 +206,13 @@ fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
+ 
+ 	event->closure	     = client->bus_reset_closure;
+ 	event->type          = FW_CDEV_EVENT_BUS_RESET;
++	event->generation    = client->device->generation;
++	smp_rmb();           /* node_id must not be older than generation */
+ 	event->node_id       = client->device->node_id;
+ 	event->local_node_id = card->local_node->node_id;
+ 	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
+ 	event->irm_node_id   = card->irm_node->node_id;
+ 	event->root_node_id  = card->root_node->node_id;
+-	event->generation    = card->generation;
+ }
+ 
+ static void
+diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
+index 56681b3..de9066e 100644
+--- a/drivers/firewire/fw-device.c
++++ b/drivers/firewire/fw-device.c
+@@ -27,6 +27,7 @@
+ #include <linux/idr.h>
+ #include <linux/rwsem.h>
+ #include <asm/semaphore.h>
++#include <asm/system.h>
+ #include <linux/ctype.h>
+ #include "fw-transaction.h"
+ #include "fw-topology.h"
+@@ -182,9 +183,14 @@ static void fw_device_release(struct device *dev)
+ 
+ int fw_device_enable_phys_dma(struct fw_device *device)
+ {
++	int generation = device->generation;
++
++	/* device->node_id, accessed below, must not be older than generation */
++	smp_rmb();
++
+ 	return device->card->driver->enable_phys_dma(device->card,
+ 						     device->node_id,
+-						     device->generation);
++						     generation);
+ }
+ EXPORT_SYMBOL(fw_device_enable_phys_dma);
+ 
+@@ -384,17 +390,21 @@ complete_transaction(struct fw_card *card, int rcode,
+ 	complete(&callback_data->done);
+ }
+ 
+-static int read_rom(struct fw_device *device, int index, u32 * data)
++static int
++read_rom(struct fw_device *device, int generation, int index, u32 *data)
+ {
+ 	struct read_quadlet_callback_data callback_data;
+ 	struct fw_transaction t;
+ 	u64 offset;
+ 
++	/* device->node_id, accessed below, must not be older than generation */
++	smp_rmb();
++
+ 	init_completion(&callback_data.done);
+ 
+ 	offset = 0xfffff0000400ULL + index * 4;
+ 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
+-			device->node_id, device->generation, device->max_speed,
++			device->node_id, generation, device->max_speed,
+ 			offset, NULL, 4, complete_transaction, &callback_data);
+ 
+ 	wait_for_completion(&callback_data.done);
+@@ -404,7 +414,14 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
+ 	return callback_data.rcode;
+ }
+ 
+-static int read_bus_info_block(struct fw_device *device)
++/*
++ * Read the bus info block, perform a speed probe, and read all of the rest of
++ * the config ROM.  We do all this with a cached bus generation.  If the bus
++ * generation changes under us, read_bus_info_block will fail and get retried.
++ * It's better to start all over in this case because the node from which we
++ * are reading the ROM may have changed the ROM during the reset.
++ */
++static int read_bus_info_block(struct fw_device *device, int generation)
+ {
+ 	static u32 rom[256];
+ 	u32 stack[16], sp, key;
+@@ -414,7 +431,7 @@ static int read_bus_info_block(struct fw_device *device)
+ 
+ 	/* First read the bus info block. */
+ 	for (i = 0; i < 5; i++) {
+-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+ 			return -1;
+ 		/*
+ 		 * As per IEEE1212 7.2, during power-up, devices can
+@@ -449,7 +466,8 @@ static int read_bus_info_block(struct fw_device *device)
+ 			device->max_speed = device->card->link_speed;
+ 
+ 		while (device->max_speed > SCODE_100) {
+-			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
++			if (read_rom(device, generation, 0, &dummy) ==
++			    RCODE_COMPLETE)
+ 				break;
+ 			device->max_speed--;
+ 		}
+@@ -482,7 +500,7 @@ static int read_bus_info_block(struct fw_device *device)
+ 			return -1;
+ 
+ 		/* Read header quadlet for the block to get the length. */
+-		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
+ 			return -1;
+ 		end = i + (rom[i] >> 16) + 1;
+ 		i++;
+@@ -501,7 +519,8 @@ static int read_bus_info_block(struct fw_device *device)
+ 		 * it references another block, and push it in that case.
+ 		 */
+ 		while (i < end) {
+-			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
++			if (read_rom(device, generation, i, &rom[i]) !=
++			    RCODE_COMPLETE)
+ 				return -1;
+ 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
+ 			    sp < ARRAY_SIZE(stack))
+@@ -648,7 +667,7 @@ static void fw_device_init(struct work_struct *work)
+ 	 * device.
+ 	 */
+ 
+-	if (read_bus_info_block(device) < 0) {
++	if (read_bus_info_block(device, device->generation) < 0) {
+ 		if (device->config_rom_retries < MAX_RETRIES) {
+ 			device->config_rom_retries++;
+ 			schedule_delayed_work(&device->work, RETRY_DELAY);
+@@ -801,6 +820,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+ 
+ 		device = node->data;
+ 		device->node_id = node->node_id;
++		smp_wmb();  /* update node_id before generation */
+ 		device->generation = card->generation;
+ 		if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
+ 			PREPARE_DELAYED_WORK(&device->work, fw_device_update);
+diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
+index 894d4a9..0854fe2 100644
+--- a/drivers/firewire/fw-device.h
++++ b/drivers/firewire/fw-device.h
+@@ -35,6 +35,18 @@ struct fw_attribute_group {
+ 	struct attribute *attrs[11];
+ };
+ 
++/*
++ * Note, fw_device.generation always has to be read before fw_device.node_id.
++ * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
++ * to an outdated node_id if the generation was updated in the meantime due
++ * to a bus reset.
++ *
++ * Likewise, fw-core will take care to update .node_id before .generation so
++ * that whenever fw_device.generation is current WRT the actual bus generation,
++ * fw_device.node_id is guaranteed to be current too.
++ *
++ * The same applies to fw_device.card->node_id vs. fw_device.generation.
++ */
+ struct fw_device {
+ 	atomic_t state;
+ 	struct fw_node *node;
+diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
+index 436a855..7ebad3c 100644
+--- a/drivers/firewire/fw-ohci.c
++++ b/drivers/firewire/fw-ohci.c
+@@ -98,17 +98,48 @@ struct context;
+ typedef int (*descriptor_callback_t)(struct context *ctx,
+ 				     struct descriptor *d,
+ 				     struct descriptor *last);
++
++/*
++ * A buffer that contains a block of DMA-able coherent memory used for
++ * storing a portion of a DMA descriptor program.
++ */
++struct descriptor_buffer {
++	struct list_head list;
++	dma_addr_t buffer_bus;
++	size_t buffer_size;
++	size_t used;
++	struct descriptor buffer[0];
++};
++
+ struct context {
+ 	struct fw_ohci *ohci;
+ 	u32 regs;
++	int total_allocation;
+ 
+-	struct descriptor *buffer;
+-	dma_addr_t buffer_bus;
+-	size_t buffer_size;
+-	struct descriptor *head_descriptor;
+-	struct descriptor *tail_descriptor;
+-	struct descriptor *tail_descriptor_last;
+-	struct descriptor *prev_descriptor;
++	/*
++	 * List of page-sized buffers for storing DMA descriptors.
++	 * Head of list contains buffers in use and tail of list contains
++	 * free buffers.
++	 */
++	struct list_head buffer_list;
++
++	/*
++	 * Pointer to a buffer inside buffer_list that contains the tail
++	 * end of the current DMA program.
++	 */
++	struct descriptor_buffer *buffer_tail;
++
++	/*
++	 * The descriptor containing the branch address of the first
++	 * descriptor that has not yet been filled by the device.
++	 */
++	struct descriptor *last;
++
++	/*
++	 * The last descriptor in the DMA program.  It contains the branch
++	 * address that must be updated upon appending a new descriptor.
++	 */
++	struct descriptor *prev;
+ 
+ 	descriptor_callback_t callback;
+ 
+@@ -125,6 +156,7 @@ struct context {
+ struct iso_context {
+ 	struct fw_iso_context base;
+ 	struct context context;
++	int excess_bytes;
+ 	void *header;
+ 	size_t header_length;
+ };
+@@ -197,8 +229,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
+ #define SELF_ID_BUF_SIZE		0x800
+ #define OHCI_TCODE_PHY_PACKET		0x0e
+ #define OHCI_VERSION_1_1		0x010010
+-#define ISO_BUFFER_SIZE			(64 * 1024)
+-#define AT_BUFFER_SIZE			4096
+ 
+ static char ohci_driver_name[] = KBUILD_MODNAME;
+ 
+@@ -455,71 +485,108 @@ find_branch_descriptor(struct descriptor *d, int z)
+ static void context_tasklet(unsigned long data)
+ {
+ 	struct context *ctx = (struct context *) data;
+-	struct fw_ohci *ohci = ctx->ohci;
+ 	struct descriptor *d, *last;
+ 	u32 address;
+ 	int z;
++	struct descriptor_buffer *desc;
+ 
+-	dma_sync_single_for_cpu(ohci->card.device, ctx->buffer_bus,
+-				ctx->buffer_size, DMA_TO_DEVICE);
+-
+-	d    = ctx->tail_descriptor;
+-	last = ctx->tail_descriptor_last;
+-
++	desc = list_entry(ctx->buffer_list.next,
++			struct descriptor_buffer, list);
++	last = ctx->last;
+ 	while (last->branch_address != 0) {
++		struct descriptor_buffer *old_desc = desc;
+ 		address = le32_to_cpu(last->branch_address);
+ 		z = address & 0xf;
+-		d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d);
++		address &= ~0xf;
++
++		/* If the branch address points to a buffer outside of the
++		 * current buffer, advance to the next buffer. */
++		if (address < desc->buffer_bus ||
++				address >= desc->buffer_bus + desc->used)
++			desc = list_entry(desc->list.next,
++					struct descriptor_buffer, list);
++		d = desc->buffer + (address - desc->buffer_bus) / sizeof(*d);
+ 		last = find_branch_descriptor(d, z);
+ 
+ 		if (!ctx->callback(ctx, d, last))
+ 			break;
+ 
+-		ctx->tail_descriptor      = d;
+-		ctx->tail_descriptor_last = last;
++		if (old_desc != desc) {
++			/* If we've advanced to the next buffer, move the
++			 * previous buffer to the free list. */
++			unsigned long flags;
++			old_desc->used = 0;
++			spin_lock_irqsave(&ctx->ohci->lock, flags);
++			list_move_tail(&old_desc->list, &ctx->buffer_list);
++			spin_unlock_irqrestore(&ctx->ohci->lock, flags);
++		}
++		ctx->last = last;
+ 	}
+ }
+ 
 +/*
-+ * register this as a block device and as compliant with the
-+ * universal CD Rom driver interface
++ * Allocate a new buffer and add it to the list of free buffers for this
++ * context.  Must be called with ohci->lock held.
 + */
-+static int __devinit probe_gdrom(struct platform_device *devptr)
++static int
++context_add_buffer(struct context *ctx)
 +{
-+	int err;
-+	/* Start the device */
-+	if (gdrom_execute_diagnostic() != 1) {
-+		printk(KERN_WARNING "GDROM: ATA Probe for GDROM failed.\n");
-+		return -ENODEV;
-+	}
-+	/* Print out firmware ID */
-+	if (gdrom_outputversion())
-+		return -ENOMEM;
-+	/* Register GDROM */
-+	gdrom_major = register_blkdev(0, GDROM_DEV_NAME);
-+	if (gdrom_major <= 0)
-+		return gdrom_major;
-+	printk(KERN_INFO "GDROM: Registered with major number %d\n",
-+		gdrom_major);
-+	/* Specify basic properties of drive */
-+	gd.cd_info = kzalloc(sizeof(struct cdrom_device_info), GFP_KERNEL);
-+	if (!gd.cd_info) {
-+		err = -ENOMEM;
-+		goto probe_fail_no_mem;
-+	}
-+	probe_gdrom_setupcd();
-+	gd.disk = alloc_disk(1);
-+	if (!gd.disk) {
-+		err = -ENODEV;
-+		goto probe_fail_no_disk;
-+	}
-+	probe_gdrom_setupdisk();
-+	if (register_cdrom(gd.cd_info)) {
-+		err = -ENODEV;
-+		goto probe_fail_cdrom_register;
-+	}
-+	gd.disk->fops = &gdrom_bdops;
-+	/* latch on to the interrupt */
-+	err = gdrom_set_interrupt_handlers();
-+	if (err)
-+		goto probe_fail_cmdirq_register;
-+	gd.gdrom_rq = blk_init_queue(gdrom_request, &gdrom_lock);
-+	if (!gd.gdrom_rq)
-+		goto probe_fail_requestq;
-+
-+	err = probe_gdrom_setupqueue();
-+	if (err)
-+		goto probe_fail_toc;
++	struct descriptor_buffer *desc;
++	dma_addr_t bus_addr;
++	int offset;
 +
-+	gd.toc = kzalloc(sizeof(struct gdromtoc), GFP_KERNEL);
-+	if (!gd.toc)
-+		goto probe_fail_toc;
-+	add_disk(gd.disk);
-+	return 0;
++	/*
++	 * 16MB of descriptors should be far more than enough for any DMA
++	 * program.  This will catch run-away userspace or DoS attacks.
++	 */
++	if (ctx->total_allocation >= 16*1024*1024)
++		return -ENOMEM;
 +
-+probe_fail_toc:
-+	blk_cleanup_queue(gd.gdrom_rq);
-+probe_fail_requestq:
-+	free_irq(HW_EVENT_GDROM_DMA, &gd);
-+	free_irq(HW_EVENT_GDROM_CMD, &gd);
-+probe_fail_cmdirq_register:
-+probe_fail_cdrom_register:
-+	del_gendisk(gd.disk);
-+probe_fail_no_disk:
-+	kfree(gd.cd_info);
-+	unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
-+	gdrom_major = 0;
-+probe_fail_no_mem:
-+	printk(KERN_WARNING "GDROM: Probe failed - error is 0x%X\n", err);
-+	return err;
-+}
++	desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE,
++			&bus_addr, GFP_ATOMIC);
++	if (!desc)
++		return -ENOMEM;
 +
-+static int __devexit remove_gdrom(struct platform_device *devptr)
-+{
-+	flush_scheduled_work();
-+	blk_cleanup_queue(gd.gdrom_rq);
-+	free_irq(HW_EVENT_GDROM_CMD, &gd);
-+	free_irq(HW_EVENT_GDROM_DMA, &gd);
-+	del_gendisk(gd.disk);
-+	if (gdrom_major)
-+		unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
-+	return unregister_cdrom(gd.cd_info);
-+}
++	offset = (void *)&desc->buffer - (void *)desc;
++	desc->buffer_size = PAGE_SIZE - offset;
++	desc->buffer_bus = bus_addr + offset;
++	desc->used = 0;
 +
-+static struct platform_driver gdrom_driver = {
-+	.probe = probe_gdrom,
-+	.remove = __devexit_p(remove_gdrom),
-+	.driver = {
-+			.name = GDROM_DEV_NAME,
-+	},
-+};
++	list_add_tail(&desc->list, &ctx->buffer_list);
++	ctx->total_allocation += PAGE_SIZE;
 +
-+static int __init init_gdrom(void)
-+{
-+	int rc;
-+	gd.toc = NULL;
-+	rc = platform_driver_register(&gdrom_driver);
-+	if (rc)
-+		return rc;
-+	pd = platform_device_register_simple(GDROM_DEV_NAME, -1, NULL, 0);
-+	if (IS_ERR(pd)) {
-+		platform_driver_unregister(&gdrom_driver);
-+		return PTR_ERR(pd);
-+	}
 +	return 0;
 +}
 +
-+static void __exit exit_gdrom(void)
-+{
-+	platform_device_unregister(pd);
-+	platform_driver_unregister(&gdrom_driver);
-+	kfree(gd.toc);
-+}
+ static int
+ context_init(struct context *ctx, struct fw_ohci *ohci,
+-	     size_t buffer_size, u32 regs,
+-	     descriptor_callback_t callback)
++	     u32 regs, descriptor_callback_t callback)
+ {
+ 	ctx->ohci = ohci;
+ 	ctx->regs = regs;
+-	ctx->buffer_size = buffer_size;
+-	ctx->buffer = kmalloc(buffer_size, GFP_KERNEL);
+-	if (ctx->buffer == NULL)
++	ctx->total_allocation = 0;
 +
-+module_init(init_gdrom);
-+module_exit(exit_gdrom);
-+MODULE_AUTHOR("Adrian McMenamin <adrian at mcmen.demon.co.uk>");
-+MODULE_DESCRIPTION("SEGA Dreamcast GD-ROM Driver");
-+MODULE_LICENSE("GPL");
-diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
-index d8bb44b..8473b9f 100644
---- a/drivers/cdrom/viocd.c
-+++ b/drivers/cdrom/viocd.c
-@@ -289,7 +289,7 @@ static int send_request(struct request *req)
++	INIT_LIST_HEAD(&ctx->buffer_list);
++	if (context_add_buffer(ctx) < 0)
+ 		return -ENOMEM;
+ 
++	ctx->buffer_tail = list_entry(ctx->buffer_list.next,
++			struct descriptor_buffer, list);
++
+ 	tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx);
+ 	ctx->callback = callback;
+ 
+-	ctx->buffer_bus =
+-		dma_map_single(ohci->card.device, ctx->buffer,
+-			       buffer_size, DMA_TO_DEVICE);
+-	if (dma_mapping_error(ctx->buffer_bus)) {
+-		kfree(ctx->buffer);
+-		return -ENOMEM;
+-	}
+-
+-	ctx->head_descriptor      = ctx->buffer;
+-	ctx->prev_descriptor      = ctx->buffer;
+-	ctx->tail_descriptor      = ctx->buffer;
+-	ctx->tail_descriptor_last = ctx->buffer;
+-
+ 	/*
+ 	 * We put a dummy descriptor in the buffer that has a NULL
+ 	 * branch address and looks like it's been sent.  That way we
+-	 * have a descriptor to append DMA programs to.  Also, the
+-	 * ring buffer invariant is that it always has at least one
+-	 * element so that head == tail means buffer full.
++	 * have a descriptor to append DMA programs to.
+ 	 */
+-
+-	memset(ctx->head_descriptor, 0, sizeof(*ctx->head_descriptor));
+-	ctx->head_descriptor->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
+-	ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011);
+-	ctx->head_descriptor++;
++	memset(ctx->buffer_tail->buffer, 0, sizeof(*ctx->buffer_tail->buffer));
++	ctx->buffer_tail->buffer->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
++	ctx->buffer_tail->buffer->transfer_status = cpu_to_le16(0x8011);
++	ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer);
++	ctx->last = ctx->buffer_tail->buffer;
++	ctx->prev = ctx->buffer_tail->buffer;
+ 
  	return 0;
  }
+@@ -528,35 +595,42 @@ static void
+ context_release(struct context *ctx)
+ {
+ 	struct fw_card *card = &ctx->ohci->card;
++	struct descriptor_buffer *desc, *tmp;
+ 
+-	dma_unmap_single(card->device, ctx->buffer_bus,
+-			 ctx->buffer_size, DMA_TO_DEVICE);
+-	kfree(ctx->buffer);
++	list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list)
++		dma_free_coherent(card->device, PAGE_SIZE, desc,
++			desc->buffer_bus -
++			((void *)&desc->buffer - (void *)desc));
+ }
  
--static void viocd_end_request(struct request *req, int uptodate)
-+static void viocd_end_request(struct request *req, int error)
++/* Must be called with ohci->lock held */
+ static struct descriptor *
+ context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus)
  {
- 	int nsectors = req->hard_nr_sectors;
+-	struct descriptor *d, *tail, *end;
+-
+-	d = ctx->head_descriptor;
+-	tail = ctx->tail_descriptor;
+-	end = ctx->buffer + ctx->buffer_size / sizeof(*d);
+-
+-	if (d + z <= tail) {
+-		goto has_space;
+-	} else if (d > tail && d + z <= end) {
+-		goto has_space;
+-	} else if (d > tail && ctx->buffer + z <= tail) {
+-		d = ctx->buffer;
+-		goto has_space;
+-	}
++	struct descriptor *d = NULL;
++	struct descriptor_buffer *desc = ctx->buffer_tail;
++
++	if (z * sizeof(*d) > desc->buffer_size)
++		return NULL;
  
-@@ -302,11 +302,8 @@ static void viocd_end_request(struct request *req, int uptodate)
- 	if (!nsectors)
- 		nsectors = 1;
+-	return NULL;
++	if (z * sizeof(*d) > desc->buffer_size - desc->used) {
++		/* No room for the descriptor in this buffer, so advance to the
++		 * next one. */
++
++		if (desc->list.next == &ctx->buffer_list) {
++			/* If there is no free buffer next in the list,
++			 * allocate one. */
++			if (context_add_buffer(ctx) < 0)
++				return NULL;
++		}
++		desc = list_entry(desc->list.next,
++				struct descriptor_buffer, list);
++		ctx->buffer_tail = desc;
++	}
  
--	if (end_that_request_first(req, uptodate, nsectors))
-+	if (__blk_end_request(req, error, nsectors << 9))
- 		BUG();
--	add_disk_randomness(req->rq_disk);
--	blkdev_dequeue_request(req);
--	end_that_request_last(req, uptodate);
+- has_space:
++	d = desc->buffer + desc->used / sizeof(*d);
+ 	memset(d, 0, z * sizeof(*d));
+-	*d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d);
++	*d_bus = desc->buffer_bus + desc->used;
+ 
+ 	return d;
  }
+@@ -566,7 +640,7 @@ static void context_run(struct context *ctx, u32 extra)
+ 	struct fw_ohci *ohci = ctx->ohci;
  
- static int rwreq;
-@@ -317,11 +314,11 @@ static void do_viocd_request(struct request_queue *q)
+ 	reg_write(ohci, COMMAND_PTR(ctx->regs),
+-		  le32_to_cpu(ctx->tail_descriptor_last->branch_address));
++		  le32_to_cpu(ctx->last->branch_address));
+ 	reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0);
+ 	reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra);
+ 	flush_writes(ohci);
+@@ -576,15 +650,13 @@ static void context_append(struct context *ctx,
+ 			   struct descriptor *d, int z, int extra)
+ {
+ 	dma_addr_t d_bus;
++	struct descriptor_buffer *desc = ctx->buffer_tail;
  
- 	while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) {
- 		if (!blk_fs_request(req))
--			viocd_end_request(req, 0);
-+			viocd_end_request(req, -EIO);
- 		else if (send_request(req) < 0) {
- 			printk(VIOCD_KERN_WARNING
- 					"unable to send message to OS/400!");
--			viocd_end_request(req, 0);
-+			viocd_end_request(req, -EIO);
- 		} else
- 			rwreq++;
- 	}
-@@ -532,9 +529,9 @@ return_complete:
- 					"with rc %d:0x%04X: %s\n",
- 					req, event->xRc,
- 					bevent->sub_result, err->msg);
--			viocd_end_request(req, 0);
-+			viocd_end_request(req, -EIO);
- 		} else
--			viocd_end_request(req, 1);
-+			viocd_end_request(req, 0);
+-	d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d);
++	d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d);
  
- 		/* restart handling of incoming requests */
- 		spin_unlock_irqrestore(&viocd_reqlock, flags);
-diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
-index 2e3a0d4..4666295 100644
---- a/drivers/char/Kconfig
-+++ b/drivers/char/Kconfig
-@@ -373,6 +373,16 @@ config ISTALLION
- 	  To compile this driver as a module, choose M here: the
- 	  module will be called istallion.
+-	ctx->head_descriptor = d + z + extra;
+-	ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z);
+-	ctx->prev_descriptor = find_branch_descriptor(d, z);
+-
+-	dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus,
+-				   ctx->buffer_size, DMA_TO_DEVICE);
++	desc->used += (z + extra) * sizeof(*d);
++	ctx->prev->branch_address = cpu_to_le32(d_bus | z);
++	ctx->prev = find_branch_descriptor(d, z);
  
-+config NOZOMI
-+	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter"
-+	depends on PCI && EXPERIMENTAL
-+	help
-+	  If you have a HSDPA driver Broadband Wireless Data Card -
-+	  Globe Trotter PCMCIA card, say Y here.
-+
-+	  To compile this driver as a module, choose M here, the module
-+	  will be called nozomi.
+ 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
+ 	flush_writes(ctx->ohci);
+@@ -1078,6 +1150,13 @@ static irqreturn_t irq_handler(int irq, void *data)
+ 	if (unlikely(event & OHCI1394_postedWriteErr))
+ 		fw_error("PCI posted write error\n");
+ 
++	if (unlikely(event & OHCI1394_cycleTooLong)) {
++		if (printk_ratelimit())
++			fw_notify("isochronous cycle too long\n");
++		reg_write(ohci, OHCI1394_LinkControlSet,
++			  OHCI1394_LinkControl_cycleMaster);
++	}
 +
- config A2232
- 	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
- 	depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
-diff --git a/drivers/char/Makefile b/drivers/char/Makefile
-index 07304d5..96fc01e 100644
---- a/drivers/char/Makefile
-+++ b/drivers/char/Makefile
-@@ -26,6 +26,7 @@ obj-$(CONFIG_SERIAL167)		+= serial167.o
- obj-$(CONFIG_CYCLADES)		+= cyclades.o
- obj-$(CONFIG_STALLION)		+= stallion.o
- obj-$(CONFIG_ISTALLION)		+= istallion.o
-+obj-$(CONFIG_NOZOMI)		+= nozomi.o
- obj-$(CONFIG_DIGIEPCA)		+= epca.o
- obj-$(CONFIG_SPECIALIX)		+= specialix.o
- obj-$(CONFIG_MOXA_INTELLIO)	+= moxa.o
-diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
-index aa5ddb7..1ffb381 100644
---- a/drivers/char/agp/ali-agp.c
-+++ b/drivers/char/agp/ali-agp.c
-@@ -145,7 +145,6 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
- 	void *addr = agp_generic_alloc_page(agp_bridge);
- 	u32 temp;
+ 	if (event & OHCI1394_cycle64Seconds) {
+ 		cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
+ 		if ((cycle_time & 0x80000000) == 0)
+@@ -1151,8 +1230,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
+ 		  OHCI1394_RQPkt | OHCI1394_RSPkt |
+ 		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
+ 		  OHCI1394_isochRx | OHCI1394_isochTx |
+-		  OHCI1394_postedWriteErr | OHCI1394_cycle64Seconds |
+-		  OHCI1394_masterIntEnable);
++		  OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
++		  OHCI1394_cycle64Seconds | OHCI1394_masterIntEnable);
  
--	global_flush_tlb();
- 	if (!addr)
- 		return NULL;
+ 	/* Activate link_on bit and contender bit in our self ID packets.*/
+ 	if (ohci_update_phy_reg(card, 4, 0,
+@@ -1408,9 +1487,13 @@ static int handle_ir_dualbuffer_packet(struct context *context,
+ 	void *p, *end;
+ 	int i;
  
-@@ -162,7 +161,6 @@ static void ali_destroy_page(void * addr, int flags)
- 		if (flags & AGP_PAGE_DESTROY_UNMAP) {
- 			global_cache_flush();	/* is this really needed?  --hch */
- 			agp_generic_destroy_page(addr, flags);
--			global_flush_tlb();
- 		} else
- 			agp_generic_destroy_page(addr, flags);
- 	}
-diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
-index 832ded2..2720882 100644
---- a/drivers/char/agp/backend.c
-+++ b/drivers/char/agp/backend.c
-@@ -147,7 +147,6 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
- 			printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
- 			return -ENOMEM;
- 		}
--		flush_agp_mappings();
+-	if (db->first_res_count > 0 && db->second_res_count > 0)
+-		/* This descriptor isn't done yet, stop iteration. */
+-		return 0;
++	if (db->first_res_count > 0 && db->second_res_count > 0) {
++		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
++			/* This descriptor isn't done yet, stop iteration. */
++			return 0;
++		}
++		ctx->excess_bytes -= le16_to_cpu(db->second_req_count);
++	}
  
- 		bridge->scratch_page_real = virt_to_gart(addr);
- 		bridge->scratch_page =
-@@ -191,7 +190,6 @@ err_out:
- 	if (bridge->driver->needs_scratch_page) {
- 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
- 						 AGP_PAGE_DESTROY_UNMAP);
--		flush_agp_mappings();
- 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
- 						 AGP_PAGE_DESTROY_FREE);
- 	}
-@@ -219,7 +217,6 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
- 	    bridge->driver->needs_scratch_page) {
- 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
- 						 AGP_PAGE_DESTROY_UNMAP);
--		flush_agp_mappings();
- 		bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real),
- 						 AGP_PAGE_DESTROY_FREE);
- 	}
-diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
-index 64b2f6d..1a4674c 100644
---- a/drivers/char/agp/generic.c
-+++ b/drivers/char/agp/generic.c
-@@ -197,7 +197,6 @@ void agp_free_memory(struct agp_memory *curr)
- 		for (i = 0; i < curr->page_count; i++) {
- 			curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_UNMAP);
- 		}
--		flush_agp_mappings();
- 		for (i = 0; i < curr->page_count; i++) {
- 			curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_FREE);
- 		}
-@@ -267,8 +266,6 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
+ 	header_length = le16_to_cpu(db->first_req_count) -
+ 		le16_to_cpu(db->first_res_count);
+@@ -1429,11 +1512,15 @@ static int handle_ir_dualbuffer_packet(struct context *context,
+ 		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
+ 		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
+ 		i += ctx->base.header_size;
++		ctx->excess_bytes +=
++			(le32_to_cpu(*(u32 *)(p + 4)) >> 16) & 0xffff;
+ 		p += ctx->base.header_size + 4;
  	}
- 	new->bridge = bridge;
- 
--	flush_agp_mappings();
 -
- 	return new;
- }
- EXPORT_SYMBOL(agp_allocate_memory);
-diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
-index e72a83e..76f581c 100644
---- a/drivers/char/agp/i460-agp.c
-+++ b/drivers/char/agp/i460-agp.c
-@@ -527,7 +527,6 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge)
+ 	ctx->header_length = i;
  
- 	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
- 		page = agp_generic_alloc_page(agp_bridge);
--		global_flush_tlb();
- 	} else
- 		/* Returning NULL would cause problems */
- 		/* AK: really dubious code. */
-@@ -539,7 +538,6 @@ static void i460_destroy_page (void *page, int flags)
++	ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
++		le16_to_cpu(db->second_res_count);
++
+ 	if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) {
+ 		ir_header = (__le32 *) (db + 1);
+ 		ctx->base.callback(&ctx->base,
+@@ -1452,24 +1539,24 @@ static int handle_ir_packet_per_buffer(struct context *context,
  {
- 	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) {
- 		agp_generic_destroy_page(page, flags);
--		global_flush_tlb();
- 	}
- }
+ 	struct iso_context *ctx =
+ 		container_of(context, struct iso_context, context);
+-	struct descriptor *pd = d + 1;
++	struct descriptor *pd;
+ 	__le32 *ir_header;
+-	size_t header_length;
+-	void *p, *end;
+-	int i, z;
++	void *p;
++	int i;
  
-diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
-index 03eac1e..189efb6 100644
---- a/drivers/char/agp/intel-agp.c
-+++ b/drivers/char/agp/intel-agp.c
-@@ -210,13 +210,11 @@ static void *i8xx_alloc_pages(void)
- 	if (page == NULL)
- 		return NULL;
+-	if (pd->res_count == pd->req_count)
++	for (pd = d; pd <= last; pd++) {
++		if (pd->transfer_status)
++			break;
++	}
++	if (pd > last)
+ 		/* Descriptor(s) not done yet, stop iteration */
+ 		return 0;
  
--	if (change_page_attr(page, 4, PAGE_KERNEL_NOCACHE) < 0) {
--		change_page_attr(page, 4, PAGE_KERNEL);
--		global_flush_tlb();
-+	if (set_pages_uc(page, 4) < 0) {
-+		set_pages_wb(page, 4);
- 		__free_pages(page, 2);
- 		return NULL;
+-	header_length = le16_to_cpu(d->req_count);
+-
+ 	i   = ctx->header_length;
+-	z   = le32_to_cpu(pd->branch_address) & 0xf;
+-	p   = d + z;
+-	end = p + header_length;
++	p   = last + 1;
+ 
+-	while (p < end && i + ctx->base.header_size <= PAGE_SIZE) {
++	if (ctx->base.header_size > 0 &&
++			i + ctx->base.header_size <= PAGE_SIZE) {
+ 		/*
+ 		 * The iso header is byteswapped to little endian by
+ 		 * the controller, but the remaining header quadlets
+@@ -1478,14 +1565,11 @@ static int handle_ir_packet_per_buffer(struct context *context,
+ 		 */
+ 		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
+ 		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
+-		i += ctx->base.header_size;
+-		p += ctx->base.header_size + 4;
++		ctx->header_length += ctx->base.header_size;
  	}
--	global_flush_tlb();
- 	get_page(page);
- 	atomic_inc(&agp_bridge->current_memory_agp);
- 	return page_address(page);
-@@ -230,8 +228,7 @@ static void i8xx_destroy_pages(void *addr)
- 		return;
  
- 	page = virt_to_page(addr);
--	change_page_attr(page, 4, PAGE_KERNEL);
--	global_flush_tlb();
-+	set_pages_wb(page, 4);
- 	put_page(page);
- 	__free_pages(page, 2);
- 	atomic_dec(&agp_bridge->current_memory_agp);
-@@ -341,7 +338,6 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
+-	ctx->header_length = i;
+-
+-	if (le16_to_cpu(pd->control) & DESCRIPTOR_IRQ_ALWAYS) {
+-		ir_header = (__le32 *) (d + z);
++	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
++		ir_header = (__le32 *) p;
+ 		ctx->base.callback(&ctx->base,
+ 				   le32_to_cpu(ir_header[0]) & 0xffff,
+ 				   ctx->header_length, ctx->header,
+@@ -1493,7 +1577,6 @@ static int handle_ir_packet_per_buffer(struct context *context,
+ 		ctx->header_length = 0;
+ 	}
  
- 	switch (pg_count) {
- 	case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
--		global_flush_tlb();
- 		break;
- 	case 4:
- 		/* kludge to get 4 physical pages for ARGB cursor */
-@@ -404,7 +400,6 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
- 		else {
- 			agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
- 							     AGP_PAGE_DESTROY_UNMAP);
--			global_flush_tlb();
- 			agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]),
- 							     AGP_PAGE_DESTROY_FREE);
- 		}
-diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
-index 4c16778..465ad35 100644
---- a/drivers/char/hpet.c
-+++ b/drivers/char/hpet.c
-@@ -600,63 +600,6 @@ static int hpet_is_known(struct hpet_data *hdp)
- 	return 0;
+-
+ 	return 1;
  }
  
--EXPORT_SYMBOL(hpet_alloc);
--EXPORT_SYMBOL(hpet_register);
--EXPORT_SYMBOL(hpet_unregister);
--EXPORT_SYMBOL(hpet_control);
--
--int hpet_register(struct hpet_task *tp, int periodic)
--{
--	unsigned int i;
--	u64 mask;
--	struct hpet_timer __iomem *timer;
--	struct hpet_dev *devp;
--	struct hpets *hpetp;
+@@ -1559,8 +1642,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
+ 	if (ctx->header == NULL)
+ 		goto out;
+ 
+-	retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE,
+-			      regs, callback);
++	retval = context_init(&ctx->context, ohci, regs, callback);
+ 	if (retval < 0)
+ 		goto out_with_header;
+ 
+@@ -1775,19 +1857,6 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
+ 	 * packet, retransmit or terminate..
+ 	 */
+ 
+-	if (packet->skip) {
+-		d = context_get_descriptors(&ctx->context, 2, &d_bus);
+-		if (d == NULL)
+-			return -ENOMEM;
 -
--	switch (periodic) {
--	case 1:
--		mask = Tn_PER_INT_CAP_MASK;
--		break;
--	case 0:
--		mask = 0;
--		break;
--	default:
--		return -EINVAL;
+-		db = (struct db_descriptor *) d;
+-		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
+-					  DESCRIPTOR_BRANCH_ALWAYS |
+-					  DESCRIPTOR_WAIT);
+-		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
+-		context_append(&ctx->context, d, 2, 0);
 -	}
 -
--	tp->ht_opaque = NULL;
--
--	spin_lock_irq(&hpet_task_lock);
--	spin_lock(&hpet_lock);
--
--	for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
--		for (timer = hpetp->hp_hpet->hpet_timers, i = 0;
--		     i < hpetp->hp_ntimer; i++, timer++) {
--			if ((readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK)
--			    != mask)
--				continue;
--
--			devp = &hpetp->hp_dev[i];
--
--			if (devp->hd_flags & HPET_OPEN || devp->hd_task) {
--				devp = NULL;
--				continue;
--			}
--
--			tp->ht_opaque = devp;
--			devp->hd_task = tp;
--			break;
--		}
--
--	spin_unlock(&hpet_lock);
--	spin_unlock_irq(&hpet_task_lock);
--
--	if (tp->ht_opaque)
--		return 0;
--	else
--		return -EBUSY;
--}
--
- static inline int hpet_tpcheck(struct hpet_task *tp)
- {
- 	struct hpet_dev *devp;
-@@ -706,24 +649,6 @@ int hpet_unregister(struct hpet_task *tp)
- 	return 0;
- }
+ 	p = packet;
+ 	z = 2;
  
--int hpet_control(struct hpet_task *tp, unsigned int cmd, unsigned long arg)
--{
--	struct hpet_dev *devp;
--	int err;
+@@ -1815,11 +1884,18 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
+ 		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
+ 					  DESCRIPTOR_BRANCH_ALWAYS);
+ 		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
+-		db->first_req_count = cpu_to_le16(header_size);
++		if (p->skip && rest == p->payload_length) {
++			db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
++			db->first_req_count = db->first_size;
++		} else {
++			db->first_req_count = cpu_to_le16(header_size);
++		}
+ 		db->first_res_count = db->first_req_count;
+ 		db->first_buffer = cpu_to_le32(d_bus + sizeof(*db));
+ 
+-		if (offset + rest < PAGE_SIZE)
++		if (p->skip && rest == p->payload_length)
++			length = 4;
++		else if (offset + rest < PAGE_SIZE)
+ 			length = rest;
+ 		else
+ 			length = PAGE_SIZE - offset;
+@@ -1835,7 +1911,8 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
+ 		context_append(&ctx->context, d, z, header_z);
+ 		offset = (offset + length) & ~PAGE_MASK;
+ 		rest -= length;
+-		page++;
++		if (offset == 0)
++			page++;
+ 	}
+ 
+ 	return 0;
+@@ -1849,67 +1926,70 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
+ {
+ 	struct iso_context *ctx = container_of(base, struct iso_context, base);
+ 	struct descriptor *d = NULL, *pd = NULL;
+-	struct fw_iso_packet *p;
++	struct fw_iso_packet *p = packet;
+ 	dma_addr_t d_bus, page_bus;
+ 	u32 z, header_z, rest;
+-	int i, page, offset, packet_count, header_size;
 -
--	if ((err = hpet_tpcheck(tp)))
--		return err;
+-	if (packet->skip) {
+-		d = context_get_descriptors(&ctx->context, 1, &d_bus);
+-		if (d == NULL)
+-			return -ENOMEM;
 -
--	spin_lock_irq(&hpet_lock);
--	devp = tp->ht_opaque;
--	if (devp->hd_task != tp) {
--		spin_unlock_irq(&hpet_lock);
--		return -ENXIO;
+-		d->control = cpu_to_le16(DESCRIPTOR_STATUS |
+-					 DESCRIPTOR_INPUT_LAST |
+-					 DESCRIPTOR_BRANCH_ALWAYS |
+-					 DESCRIPTOR_WAIT);
+-		context_append(&ctx->context, d, 1, 0);
 -	}
--	spin_unlock_irq(&hpet_lock);
--	return hpet_ioctl_common(devp, cmd, arg, 1);
--}
 -
- static ctl_table hpet_table[] = {
- 	{
- 	 .ctl_name = CTL_UNNUMBERED,
-@@ -806,14 +731,14 @@ static unsigned long hpet_calibrate(struct hpets *hpetp)
- 
- int hpet_alloc(struct hpet_data *hdp)
- {
--	u64 cap, mcfg;
-+	u64 cap, mcfg, hpet_config;
- 	struct hpet_dev *devp;
--	u32 i, ntimer;
-+	u32 i, ntimer, irq;
- 	struct hpets *hpetp;
- 	size_t siz;
- 	struct hpet __iomem *hpet;
- 	static struct hpets *last = NULL;
--	unsigned long period;
-+	unsigned long period, irq_bitmap;
- 	unsigned long long temp;
+-	/* one descriptor for header, one for payload */
+-	/* FIXME: handle cases where we need multiple desc. for payload */
+-	z = 2;
+-	p = packet;
++	int i, j, length;
++	int page, offset, packet_count, header_size, payload_per_buffer;
  
  	/*
-@@ -840,11 +765,47 @@ int hpet_alloc(struct hpet_data *hdp)
- 	hpetp->hp_hpet_phys = hdp->hd_phys_address;
+ 	 * The OHCI controller puts the status word in the
+ 	 * buffer too, so we need 4 extra bytes per packet.
+ 	 */
+ 	packet_count = p->header_length / ctx->base.header_size;
+-	header_size  = packet_count * (ctx->base.header_size + 4);
++	header_size  = ctx->base.header_size + 4;
  
- 	hpetp->hp_ntimer = hdp->hd_nirqs;
-+	hpet = hpetp->hp_hpet;
+ 	/* Get header size in number of descriptors. */
+ 	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
+ 	page     = payload >> PAGE_SHIFT;
+ 	offset   = payload & ~PAGE_MASK;
+-	rest     = p->payload_length;
++	payload_per_buffer = p->payload_length / packet_count;
  
--	for (i = 0; i < hdp->hd_nirqs; i++)
--		hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
-+	/* Assign IRQs statically for legacy devices */
-+	hpetp->hp_dev[0].hd_hdwirq = hdp->hd_irq[0];
-+	hpetp->hp_dev[1].hd_hdwirq = hdp->hd_irq[1];
+ 	for (i = 0; i < packet_count; i++) {
+ 		/* d points to the header descriptor */
++		z = DIV_ROUND_UP(payload_per_buffer + offset, PAGE_SIZE) + 1;
+ 		d = context_get_descriptors(&ctx->context,
+-					    z + header_z, &d_bus);
++				z + header_z, &d_bus);
+ 		if (d == NULL)
+ 			return -ENOMEM;
  
--	hpet = hpetp->hp_hpet;
-+	/* Assign IRQs dynamically for the others */
-+	for (i = 2, devp = &hpetp->hp_dev[2]; i < hdp->hd_nirqs; i++, devp++) {
-+		struct hpet_timer __iomem *timer;
-+
-+		timer = &hpet->hpet_timers[devp - hpetp->hp_dev];
+-		d->control      = cpu_to_le16(DESCRIPTOR_INPUT_MORE);
++		d->control      = cpu_to_le16(DESCRIPTOR_STATUS |
++					      DESCRIPTOR_INPUT_MORE);
++		if (p->skip && i == 0)
++			d->control |= cpu_to_le16(DESCRIPTOR_WAIT);
+ 		d->req_count    = cpu_to_le16(header_size);
+ 		d->res_count    = d->req_count;
++		d->transfer_status = 0;
+ 		d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
+ 
+-		/* pd points to the payload descriptor */
+-		pd = d + 1;
++		rest = payload_per_buffer;
++		for (j = 1; j < z; j++) {
++			pd = d + j;
++			pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
++						  DESCRIPTOR_INPUT_MORE);
 +
-+		/* Check if there's already an IRQ assigned to the timer */
-+		if (hdp->hd_irq[i]) {
-+			hpetp->hp_dev[i].hd_hdwirq = hdp->hd_irq[i];
-+			continue;
-+		}
++			if (offset + rest < PAGE_SIZE)
++				length = rest;
++			else
++				length = PAGE_SIZE - offset;
++			pd->req_count = cpu_to_le16(length);
++			pd->res_count = pd->req_count;
++			pd->transfer_status = 0;
 +
-+		hpet_config = readq(&timer->hpet_config);
-+		irq_bitmap = (hpet_config & Tn_INT_ROUTE_CAP_MASK)
-+			>> Tn_INT_ROUTE_CAP_SHIFT;
-+		if (!irq_bitmap)
-+			irq = 0;        /* No valid IRQ Assignable */
-+		else {
-+			irq = find_first_bit(&irq_bitmap, 32);
-+			do {
-+				hpet_config |= irq << Tn_INT_ROUTE_CNF_SHIFT;
-+				writeq(hpet_config, &timer->hpet_config);
++			page_bus = page_private(buffer->pages[page]);
++			pd->data_address = cpu_to_le32(page_bus + offset);
 +
-+				/*
-+				 * Verify whether we have written a valid
-+				 * IRQ number by reading it back again
-+				 */
-+				hpet_config = readq(&timer->hpet_config);
-+				if (irq == (hpet_config & Tn_INT_ROUTE_CNF_MASK)
-+						>> Tn_INT_ROUTE_CNF_SHIFT)
-+					break;  /* Success */
-+			} while ((irq = (find_next_bit(&irq_bitmap, 32, irq))));
++			offset = (offset + length) & ~PAGE_MASK;
++			rest -= length;
++			if (offset == 0)
++				page++;
 +		}
-+		hpetp->hp_dev[i].hd_hdwirq = irq;
-+	}
+ 		pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
+ 					  DESCRIPTOR_INPUT_LAST |
+ 					  DESCRIPTOR_BRANCH_ALWAYS);
+-		if (p->interrupt)
++		if (p->interrupt && i == packet_count - 1)
+ 			pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
  
- 	cap = readq(&hpet->hpet_cap);
+-		pd->req_count = cpu_to_le16(rest);
+-		pd->res_count = pd->req_count;
+-
+-		page_bus = page_private(buffer->pages[page]);
+-		pd->data_address = cpu_to_le32(page_bus + offset);
+-
+ 		context_append(&ctx->context, d, z, header_z);
+ 	}
  
-@@ -875,7 +836,8 @@ int hpet_alloc(struct hpet_data *hdp)
- 		hpetp->hp_which, hdp->hd_phys_address,
- 		hpetp->hp_ntimer > 1 ? "s" : "");
- 	for (i = 0; i < hpetp->hp_ntimer; i++)
--		printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
-+		printk("%s %d", i > 0 ? "," : "",
-+				hpetp->hp_dev[i].hd_hdwirq);
- 	printk("\n");
+@@ -1923,16 +2003,22 @@ ohci_queue_iso(struct fw_iso_context *base,
+ 	       unsigned long payload)
+ {
+ 	struct iso_context *ctx = container_of(base, struct iso_context, base);
++	unsigned long flags;
++	int retval;
  
- 	printk(KERN_INFO "hpet%u: %u %d-bit timers, %Lu Hz\n",
-diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
-index 8252f86..480fae2 100644
---- a/drivers/char/hvc_console.c
-+++ b/drivers/char/hvc_console.c
-@@ -27,7 +27,7 @@
- #include <linux/init.h>
- #include <linux/kbd_kern.h>
- #include <linux/kernel.h>
--#include <linux/kobject.h>
-+#include <linux/kref.h>
- #include <linux/kthread.h>
- #include <linux/list.h>
- #include <linux/module.h>
-@@ -89,7 +89,7 @@ struct hvc_struct {
- 	int irq_requested;
- 	int irq;
- 	struct list_head next;
--	struct kobject kobj; /* ref count & hvc_struct lifetime */
-+	struct kref kref; /* ref count & hvc_struct lifetime */
- };
++	spin_lock_irqsave(&ctx->context.ohci->lock, flags);
+ 	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
+-		return ohci_queue_iso_transmit(base, packet, buffer, payload);
++		retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
+ 	else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
+-		return ohci_queue_iso_receive_dualbuffer(base, packet,
++		retval = ohci_queue_iso_receive_dualbuffer(base, packet,
+ 							 buffer, payload);
+ 	else
+-		return ohci_queue_iso_receive_packet_per_buffer(base, packet,
++		retval = ohci_queue_iso_receive_packet_per_buffer(base, packet,
+ 								buffer,
+ 								payload);
++	spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
++
++	return retval;
+ }
  
- /* dynamic list of hvc_struct instances */
-@@ -110,7 +110,7 @@ static int last_hvc = -1;
+ static const struct fw_card_driver ohci_driver = {
+@@ -2004,10 +2090,10 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+ 	ar_context_init(&ohci->ar_response_ctx, ohci,
+ 			OHCI1394_AsRspRcvContextControlSet);
  
- /*
-  * Do not call this function with either the hvc_structs_lock or the hvc_struct
-- * lock held.  If successful, this function increments the kobject reference
-+ * lock held.  If successful, this function increments the kref reference
-  * count against the target hvc_struct so it should be released when finished.
-  */
- static struct hvc_struct *hvc_get_by_index(int index)
-@@ -123,7 +123,7 @@ static struct hvc_struct *hvc_get_by_index(int index)
- 	list_for_each_entry(hp, &hvc_structs, next) {
- 		spin_lock_irqsave(&hp->lock, flags);
- 		if (hp->index == index) {
--			kobject_get(&hp->kobj);
-+			kref_get(&hp->kref);
- 			spin_unlock_irqrestore(&hp->lock, flags);
- 			spin_unlock(&hvc_structs_lock);
- 			return hp;
-@@ -242,6 +242,23 @@ static int __init hvc_console_init(void)
- }
- console_initcall(hvc_console_init);
+-	context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE,
++	context_init(&ohci->at_request_ctx, ohci,
+ 		     OHCI1394_AsReqTrContextControlSet, handle_at_packet);
  
-+/* callback when the kboject ref count reaches zero. */
-+static void destroy_hvc_struct(struct kref *kref)
-+{
-+	struct hvc_struct *hp = container_of(kref, struct hvc_struct, kref);
-+	unsigned long flags;
-+
-+	spin_lock(&hvc_structs_lock);
-+
-+	spin_lock_irqsave(&hp->lock, flags);
-+	list_del(&(hp->next));
-+	spin_unlock_irqrestore(&hp->lock, flags);
-+
-+	spin_unlock(&hvc_structs_lock);
-+
-+	kfree(hp);
-+}
-+
- /*
-  * hvc_instantiate() is an early console discovery method which locates
-  * consoles * prior to the vio subsystem discovering them.  Hotplugged
-@@ -261,7 +278,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
- 	/* make sure no no tty has been registered in this index */
- 	hp = hvc_get_by_index(index);
- 	if (hp) {
--		kobject_put(&hp->kobj);
-+		kref_put(&hp->kref, destroy_hvc_struct);
- 		return -1;
- 	}
+-	context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
++	context_init(&ohci->at_response_ctx, ohci,
+ 		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
  
-@@ -318,9 +335,8 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
- 	unsigned long flags;
- 	int irq = 0;
- 	int rc = 0;
--	struct kobject *kobjp;
+ 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
+diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
+index 624ff3e..19ece9b 100644
+--- a/drivers/firewire/fw-sbp2.c
++++ b/drivers/firewire/fw-sbp2.c
+@@ -40,6 +40,7 @@
+ #include <linux/stringify.h>
+ #include <linux/timer.h>
+ #include <linux/workqueue.h>
++#include <asm/system.h>
  
--	/* Auto increments kobject reference if found. */
-+	/* Auto increments kref reference if found. */
- 	if (!(hp = hvc_get_by_index(tty->index)))
- 		return -ENODEV;
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+@@ -148,18 +149,26 @@ struct sbp2_target {
  
-@@ -341,8 +357,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
- 	if (irq)
- 		hp->irq_requested = 1;
+ 	unsigned workarounds;
+ 	struct list_head lu_list;
++
++	unsigned int mgt_orb_timeout;
+ };
  
--	kobjp = &hp->kobj;
+-#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
+-#define SBP2_MAX_SECTORS		255	/* Max sectors supported */
++/*
++ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
++ * provided in the config rom. Most devices do provide a value, which
++ * we'll use for login management orbs, but with some sane limits.
++ */
++#define SBP2_MIN_LOGIN_ORB_TIMEOUT	5000U	/* Timeout in ms */
++#define SBP2_MAX_LOGIN_ORB_TIMEOUT	40000U	/* Timeout in ms */
+ #define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
 -
- 	spin_unlock_irqrestore(&hp->lock, flags);
- 	/* check error, fallback to non-irq */
- 	if (irq)
-@@ -352,7 +366,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
- 	 * If the request_irq() fails and we return an error.  The tty layer
- 	 * will call hvc_close() after a failed open but we don't want to clean
- 	 * up there so we'll clean up here and clear out the previously set
--	 * tty fields and return the kobject reference.
-+	 * tty fields and return the kref reference.
- 	 */
- 	if (rc) {
- 		spin_lock_irqsave(&hp->lock, flags);
-@@ -360,7 +374,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
- 		hp->irq_requested = 0;
- 		spin_unlock_irqrestore(&hp->lock, flags);
- 		tty->driver_data = NULL;
--		kobject_put(kobjp);
-+		kref_put(&hp->kref, destroy_hvc_struct);
- 		printk(KERN_ERR "hvc_open: request_irq failed with rc %d.\n", rc);
- 	}
- 	/* Force wakeup of the polling thread */
-@@ -372,7 +386,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
- static void hvc_close(struct tty_struct *tty, struct file * filp)
+ #define SBP2_ORB_NULL			0x80000000
++#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
+ 
+ #define SBP2_DIRECTION_TO_MEDIA		0x0
+ #define SBP2_DIRECTION_FROM_MEDIA	0x1
+ 
+ /* Unit directory keys */
++#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
+ #define SBP2_CSR_FIRMWARE_REVISION	0x3c
+ #define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
+ #define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
+@@ -489,6 +498,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
  {
- 	struct hvc_struct *hp;
--	struct kobject *kobjp;
- 	int irq = 0;
- 	unsigned long flags;
+ 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+ 	struct sbp2_management_orb *orb;
++	unsigned int timeout;
+ 	int retval = -ENOMEM;
  
-@@ -382,7 +395,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
- 	/*
- 	 * No driver_data means that this close was issued after a failed
- 	 * hvc_open by the tty layer's release_dev() function and we can just
--	 * exit cleanly because the kobject reference wasn't made.
-+	 * exit cleanly because the kref reference wasn't made.
- 	 */
- 	if (!tty->driver_data)
- 		return;
-@@ -390,7 +403,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
- 	hp = tty->driver_data;
- 	spin_lock_irqsave(&hp->lock, flags);
+ 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
+@@ -516,9 +526,13 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ 	orb->request.status_fifo.low  = lu->address_handler.offset;
  
--	kobjp = &hp->kobj;
- 	if (--hp->count == 0) {
- 		if (hp->irq_requested)
- 			irq = hp->irq;
-@@ -417,7 +429,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
- 		spin_unlock_irqrestore(&hp->lock, flags);
+ 	if (function == SBP2_LOGIN_REQUEST) {
++		/* Ask for 2^2 == 4 seconds reconnect grace period */
+ 		orb->request.misc |=
+-			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
+-			MANAGEMENT_ORB_RECONNECT(0);
++			MANAGEMENT_ORB_RECONNECT(2) |
++			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
++		timeout = lu->tgt->mgt_orb_timeout;
++	} else {
++		timeout = SBP2_ORB_TIMEOUT;
  	}
  
--	kobject_put(kobjp);
-+	kref_put(&hp->kref, destroy_hvc_struct);
- }
+ 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
+@@ -535,8 +549,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
+ 	sbp2_send_orb(&orb->base, lu, node_id, generation,
+ 		      lu->tgt->management_agent_address);
  
- static void hvc_hangup(struct tty_struct *tty)
-@@ -426,7 +438,6 @@ static void hvc_hangup(struct tty_struct *tty)
- 	unsigned long flags;
- 	int irq = 0;
- 	int temp_open_count;
--	struct kobject *kobjp;
+-	wait_for_completion_timeout(&orb->done,
+-				    msecs_to_jiffies(SBP2_ORB_TIMEOUT));
++	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
  
- 	if (!hp)
- 		return;
-@@ -443,7 +454,6 @@ static void hvc_hangup(struct tty_struct *tty)
- 		return;
- 	}
+ 	retval = -EIO;
+ 	if (sbp2_cancel_orbs(lu) == 0) {
+@@ -608,13 +621,17 @@ static void sbp2_release_target(struct kref *kref)
+ 	struct sbp2_logical_unit *lu, *next;
+ 	struct Scsi_Host *shost =
+ 		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
++	struct fw_device *device = fw_device(tgt->unit->device.parent);
  
--	kobjp = &hp->kobj;
- 	temp_open_count = hp->count;
- 	hp->count = 0;
- 	hp->n_outbuf = 0;
-@@ -457,7 +467,7 @@ static void hvc_hangup(struct tty_struct *tty)
- 		free_irq(irq, hp);
- 	while(temp_open_count) {
- 		--temp_open_count;
--		kobject_put(kobjp);
-+		kref_put(&hp->kref, destroy_hvc_struct);
- 	}
- }
+ 	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
+ 		if (lu->sdev)
+ 			scsi_remove_device(lu->sdev);
  
-@@ -729,27 +739,6 @@ static const struct tty_operations hvc_ops = {
- 	.chars_in_buffer = hvc_chars_in_buffer,
- };
+-		sbp2_send_management_orb(lu, tgt->node_id, lu->generation,
+-				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
++		if (!fw_device_is_shutdown(device))
++			sbp2_send_management_orb(lu, tgt->node_id,
++					lu->generation, SBP2_LOGOUT_REQUEST,
++					lu->login_id, NULL);
++
+ 		fw_core_remove_address_handler(&lu->address_handler);
+ 		list_del(&lu->link);
+ 		kfree(lu);
+@@ -628,6 +645,21 @@ static void sbp2_release_target(struct kref *kref)
  
--/* callback when the kboject ref count reaches zero. */
--static void destroy_hvc_struct(struct kobject *kobj)
--{
--	struct hvc_struct *hp = container_of(kobj, struct hvc_struct, kobj);
--	unsigned long flags;
--
--	spin_lock(&hvc_structs_lock);
--
--	spin_lock_irqsave(&hp->lock, flags);
--	list_del(&(hp->next));
--	spin_unlock_irqrestore(&hp->lock, flags);
--
--	spin_unlock(&hvc_structs_lock);
--
--	kfree(hp);
--}
--
--static struct kobj_type hvc_kobj_type = {
--	.release = destroy_hvc_struct,
--};
--
- struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
- 					struct hv_ops *ops, int outbuf_size)
- {
-@@ -776,8 +765,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
- 	hp->outbuf_size = outbuf_size;
- 	hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
+ static struct workqueue_struct *sbp2_wq;
  
--	kobject_init(&hp->kobj);
--	hp->kobj.ktype = &hvc_kobj_type;
-+	kref_init(&hp->kref);
++/*
++ * Always get the target's kref when scheduling work on one its units.
++ * Each workqueue job is responsible to call sbp2_target_put() upon return.
++ */
++static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
++{
++	if (queue_delayed_work(sbp2_wq, &lu->work, delay))
++		kref_get(&lu->tgt->kref);
++}
++
++static void sbp2_target_put(struct sbp2_target *tgt)
++{
++	kref_put(&tgt->kref, sbp2_release_target);
++}
++
+ static void sbp2_reconnect(struct work_struct *work);
  
- 	spin_lock_init(&hp->lock);
- 	spin_lock(&hvc_structs_lock);
-@@ -806,12 +794,10 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
- int __devexit hvc_remove(struct hvc_struct *hp)
- {
- 	unsigned long flags;
--	struct kobject *kobjp;
- 	struct tty_struct *tty;
+ static void sbp2_login(struct work_struct *work)
+@@ -643,22 +675,19 @@ static void sbp2_login(struct work_struct *work)
+ 	struct sbp2_login_response response;
+ 	int generation, node_id, local_node_id;
  
- 	spin_lock_irqsave(&hp->lock, flags);
- 	tty = hp->tty;
--	kobjp = &hp->kobj;
+-	generation    = device->card->generation;
+-	node_id       = device->node->node_id;
+-	local_node_id = device->card->local_node->node_id;
++	generation    = device->generation;
++	smp_rmb();    /* node_id must not be older than generation */
++	node_id       = device->node_id;
++	local_node_id = device->card->node_id;
  
- 	if (hp->index < MAX_NR_HVC_CONSOLES)
- 		vtermnos[hp->index] = -1;
-@@ -821,12 +807,12 @@ int __devexit hvc_remove(struct hvc_struct *hp)
- 	spin_unlock_irqrestore(&hp->lock, flags);
+ 	if (sbp2_send_management_orb(lu, node_id, generation,
+ 				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
+-		if (lu->retries++ < 5) {
+-			if (queue_delayed_work(sbp2_wq, &lu->work,
+-					       DIV_ROUND_UP(HZ, 5)))
+-				kref_get(&lu->tgt->kref);
+-		} else {
++		if (lu->retries++ < 5)
++			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
++		else
+ 			fw_error("failed to login to %s LUN %04x\n",
+ 				 unit->device.bus_id, lu->lun);
+-		}
+-		kref_put(&lu->tgt->kref, sbp2_release_target);
+-		return;
++		goto out;
+ 	}
  
- 	/*
--	 * We 'put' the instance that was grabbed when the kobject instance
--	 * was initialized using kobject_init().  Let the last holder of this
--	 * kobject cause it to be removed, which will probably be the tty_hangup
-+	 * We 'put' the instance that was grabbed when the kref instance
-+	 * was initialized using kref_init().  Let the last holder of this
-+	 * kref cause it to be removed, which will probably be the tty_hangup
- 	 * below.
- 	 */
--	kobject_put(kobjp);
-+	kref_put(&hp->kref, destroy_hvc_struct);
+ 	lu->generation        = generation;
+@@ -700,7 +729,8 @@ static void sbp2_login(struct work_struct *work)
+ 		lu->sdev = sdev;
+ 		scsi_device_put(sdev);
+ 	}
+-	kref_put(&lu->tgt->kref, sbp2_release_target);
++ out:
++	sbp2_target_put(lu->tgt);
+ }
  
- 	/*
- 	 * This function call will auto chain call hvc_hangup.  The tty should
-diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
-index 69d8866..fd75590 100644
---- a/drivers/char/hvcs.c
-+++ b/drivers/char/hvcs.c
-@@ -57,11 +57,7 @@
-  * rescanning partner information upon a user's request.
-  *
-  * Each vty-server, prior to being exposed to this driver is reference counted
-- * using the 2.6 Linux kernel kobject construct.  This kobject is also used by
-- * the vio bus to provide a vio device sysfs entry that this driver attaches
-- * device specific attributes to, including partner information.  The vio bus
-- * framework also provides a sysfs entry for each vio driver.  The hvcs driver
-- * provides driver attributes in this entry.
-+ * using the 2.6 Linux kernel kref construct.
-  *
-  * For direction on installation and usage of this driver please reference
-  * Documentation/powerpc/hvcs.txt.
-@@ -71,7 +67,7 @@
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/kernel.h>
--#include <linux/kobject.h>
-+#include <linux/kref.h>
- #include <linux/kthread.h>
- #include <linux/list.h>
- #include <linux/major.h>
-@@ -293,12 +289,12 @@ struct hvcs_struct {
- 	int chars_in_buffer;
+ static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
+@@ -750,6 +780,7 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
+ {
+ 	struct fw_csr_iterator ci;
+ 	int key, value;
++	unsigned int timeout;
  
- 	/*
--	 * Any variable below the kobject is valid before a tty is connected and
-+	 * Any variable below the kref is valid before a tty is connected and
- 	 * stays valid after the tty is disconnected.  These shouldn't be
- 	 * whacked until the koject refcount reaches zero though some entries
- 	 * may be changed via sysfs initiatives.
- 	 */
--	struct kobject kobj; /* ref count & hvcs_struct lifetime */
-+	struct kref kref; /* ref count & hvcs_struct lifetime */
- 	int connected; /* is the vty-server currently connected to a vty? */
- 	uint32_t p_unit_address; /* partner unit address */
- 	uint32_t p_partition_ID; /* partner partition ID */
-@@ -307,8 +303,8 @@ struct hvcs_struct {
- 	struct vio_dev *vdev;
- };
+ 	fw_csr_iterator_init(&ci, directory);
+ 	while (fw_csr_iterator_next(&ci, &key, &value)) {
+@@ -772,6 +803,21 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
+ 			*firmware_revision = value;
+ 			break;
  
--/* Required to back map a kobject to its containing object */
--#define from_kobj(kobj) container_of(kobj, struct hvcs_struct, kobj)
-+/* Required to back map a kref to its containing object */
-+#define from_kref(k) container_of(k, struct hvcs_struct, kref)
++		case SBP2_CSR_UNIT_CHARACTERISTICS:
++			/* the timeout value is stored in 500ms units */
++			timeout = ((unsigned int) value >> 8 & 0xff) * 500;
++			timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
++			tgt->mgt_orb_timeout =
++				  min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);
++
++			if (timeout > tgt->mgt_orb_timeout)
++				fw_notify("%s: config rom contains %ds "
++					  "management ORB timeout, limiting "
++					  "to %ds\n", tgt->unit->device.bus_id,
++					  timeout / 1000,
++					  tgt->mgt_orb_timeout / 1000);
++			break;
++
+ 		case SBP2_CSR_LOGICAL_UNIT_NUMBER:
+ 			if (sbp2_add_logical_unit(tgt, value) < 0)
+ 				return -ENOMEM;
+@@ -865,18 +911,13 @@ static int sbp2_probe(struct device *dev)
  
- static struct list_head hvcs_structs = LIST_HEAD_INIT(hvcs_structs);
- static DEFINE_SPINLOCK(hvcs_structs_lock);
-@@ -334,7 +330,6 @@ static void hvcs_partner_free(struct hvcs_struct *hvcsd);
- static int hvcs_enable_device(struct hvcs_struct *hvcsd,
- 		uint32_t unit_address, unsigned int irq, struct vio_dev *dev);
+ 	get_device(&unit->device);
  
--static void destroy_hvcs_struct(struct kobject *kobj);
- static int hvcs_open(struct tty_struct *tty, struct file *filp);
- static void hvcs_close(struct tty_struct *tty, struct file *filp);
- static void hvcs_hangup(struct tty_struct * tty);
-@@ -703,10 +698,10 @@ static void hvcs_return_index(int index)
- 		hvcs_index_list[index] = -1;
- }
+-	/*
+-	 * We schedule work to do the login so we can easily
+-	 * reschedule retries. Always get the ref before scheduling
+-	 * work.
+-	 */
++	/* Do the login in a workqueue so we can easily reschedule retries. */
+ 	list_for_each_entry(lu, &tgt->lu_list, link)
+-		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
+-			kref_get(&tgt->kref);
++		sbp2_queue_work(lu, 0);
+ 	return 0;
  
--/* callback when the kboject ref count reaches zero */
--static void destroy_hvcs_struct(struct kobject *kobj)
-+/* callback when the kref ref count reaches zero */
-+static void destroy_hvcs_struct(struct kref *kref)
- {
--	struct hvcs_struct *hvcsd = from_kobj(kobj);
-+	struct hvcs_struct *hvcsd = from_kref(kref);
- 	struct vio_dev *vdev;
- 	unsigned long flags;
+  fail_tgt_put:
+-	kref_put(&tgt->kref, sbp2_release_target);
++	sbp2_target_put(tgt);
+ 	return -ENOMEM;
  
-@@ -743,10 +738,6 @@ static void destroy_hvcs_struct(struct kobject *kobj)
- 	kfree(hvcsd);
- }
+  fail_shost_put:
+@@ -889,7 +930,7 @@ static int sbp2_remove(struct device *dev)
+ 	struct fw_unit *unit = fw_unit(dev);
+ 	struct sbp2_target *tgt = unit->device.driver_data;
  
--static struct kobj_type hvcs_kobj_type = {
--	.release = destroy_hvcs_struct,
--};
--
- static int hvcs_get_index(void)
- {
- 	int i;
-@@ -791,9 +782,7 @@ static int __devinit hvcs_probe(
+-	kref_put(&tgt->kref, sbp2_release_target);
++	sbp2_target_put(tgt);
+ 	return 0;
+ }
  
- 	spin_lock_init(&hvcsd->lock);
- 	/* Automatically incs the refcount the first time */
--	kobject_init(&hvcsd->kobj);
--	/* Set up the callback for terminating the hvcs_struct's life */
--	hvcsd->kobj.ktype = &hvcs_kobj_type;
-+	kref_init(&hvcsd->kref);
+@@ -901,9 +942,10 @@ static void sbp2_reconnect(struct work_struct *work)
+ 	struct fw_device *device = fw_device(unit->device.parent);
+ 	int generation, node_id, local_node_id;
  
- 	hvcsd->vdev = dev;
- 	dev->dev.driver_data = hvcsd;
-@@ -844,7 +833,6 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
- {
- 	struct hvcs_struct *hvcsd = dev->dev.driver_data;
- 	unsigned long flags;
--	struct kobject *kobjp;
- 	struct tty_struct *tty;
+-	generation    = device->card->generation;
+-	node_id       = device->node->node_id;
+-	local_node_id = device->card->local_node->node_id;
++	generation    = device->generation;
++	smp_rmb();    /* node_id must not be older than generation */
++	node_id       = device->node_id;
++	local_node_id = device->card->node_id;
  
- 	if (!hvcsd)
-@@ -856,15 +844,13 @@ static int __devexit hvcs_remove(struct vio_dev *dev)
+ 	if (sbp2_send_management_orb(lu, node_id, generation,
+ 				     SBP2_RECONNECT_REQUEST,
+@@ -915,10 +957,8 @@ static void sbp2_reconnect(struct work_struct *work)
+ 			lu->retries = 0;
+ 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
+ 		}
+-		if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
+-			kref_get(&lu->tgt->kref);
+-		kref_put(&lu->tgt->kref, sbp2_release_target);
+-		return;
++		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
++		goto out;
+ 	}
  
- 	tty = hvcsd->tty;
+ 	lu->generation        = generation;
+@@ -930,8 +970,8 @@ static void sbp2_reconnect(struct work_struct *work)
  
--	kobjp = &hvcsd->kobj;
+ 	sbp2_agent_reset(lu);
+ 	sbp2_cancel_orbs(lu);
 -
- 	spin_unlock_irqrestore(&hvcsd->lock, flags);
+-	kref_put(&lu->tgt->kref, sbp2_release_target);
++ out:
++	sbp2_target_put(lu->tgt);
+ }
  
- 	/*
- 	 * Let the last holder of this object cause it to be removed, which
- 	 * would probably be tty_hangup below.
+ static void sbp2_update(struct fw_unit *unit)
+@@ -947,8 +987,7 @@ static void sbp2_update(struct fw_unit *unit)
  	 */
--	kobject_put (kobjp);
-+	kref_put(&hvcsd->kref, destroy_hvcs_struct);
- 
- 	/*
- 	 * The hangup is a scheduled function which will auto chain call
-@@ -1086,7 +1072,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address,
+ 	list_for_each_entry(lu, &tgt->lu_list, link) {
+ 		lu->retries = 0;
+-		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
+-			kref_get(&tgt->kref);
++		sbp2_queue_work(lu, 0);
+ 	}
  }
  
- /*
-- * This always increments the kobject ref count if the call is successful.
-+ * This always increments the kref ref count if the call is successful.
-  * Please remember to dec when you are done with the instance.
-  *
-  * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when
-@@ -1103,7 +1089,7 @@ static struct hvcs_struct *hvcs_get_by_index(int index)
- 		list_for_each_entry(hvcsd, &hvcs_structs, next) {
- 			spin_lock_irqsave(&hvcsd->lock, flags);
- 			if (hvcsd->index == index) {
--				kobject_get(&hvcsd->kobj);
-+				kref_get(&hvcsd->kref);
- 				spin_unlock_irqrestore(&hvcsd->lock, flags);
- 				spin_unlock(&hvcs_structs_lock);
- 				return hvcsd;
-@@ -1129,14 +1115,13 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
- 	unsigned int irq;
- 	struct vio_dev *vdev;
- 	unsigned long unit_address;
--	struct kobject *kobjp;
- 
- 	if (tty->driver_data)
- 		goto fast_open;
- 
- 	/*
- 	 * Is there a vty-server that shares the same index?
--	 * This function increments the kobject index.
-+	 * This function increments the kref index.
- 	 */
- 	if (!(hvcsd = hvcs_get_by_index(tty->index))) {
- 		printk(KERN_WARNING "HVCS: open failed, no device associated"
-@@ -1181,7 +1166,7 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp)
- 	 * and will grab the spinlock and free the connection if it fails.
+@@ -1103,9 +1142,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
+ 	 * elements larger than 65535 bytes, some IOMMUs may merge sg elements
+ 	 * during DMA mapping, and Linux currently doesn't prevent this.
  	 */
- 	if (((rc = hvcs_enable_device(hvcsd, unit_address, irq, vdev)))) {
--		kobject_put(&hvcsd->kobj);
-+		kref_put(&hvcsd->kref, destroy_hvcs_struct);
- 		printk(KERN_WARNING "HVCS: enable device failed.\n");
- 		return rc;
- 	}
-@@ -1192,17 +1177,11 @@ fast_open:
- 	hvcsd = tty->driver_data;
+-	for (i = 0, j = 0; i < count; i++) {
+-		sg_len = sg_dma_len(sg + i);
+-		sg_addr = sg_dma_address(sg + i);
++	for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
++		sg_len = sg_dma_len(sg);
++		sg_addr = sg_dma_address(sg);
+ 		while (sg_len) {
+ 			/* FIXME: This won't get us out of the pinch. */
+ 			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
+@@ -1238,6 +1277,12 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
  
- 	spin_lock_irqsave(&hvcsd->lock, flags);
--	if (!kobject_get(&hvcsd->kobj)) {
--		spin_unlock_irqrestore(&hvcsd->lock, flags);
--		printk(KERN_ERR "HVCS: Kobject of open"
--			" hvcs doesn't exist.\n");
--		return -EFAULT; /* Is this the right return value? */
--	}
--
-+	kref_get(&hvcsd->kref);
- 	hvcsd->open_count++;
--
- 	hvcsd->todo_mask |= HVCS_SCHED_READ;
- 	spin_unlock_irqrestore(&hvcsd->lock, flags);
+ 	sdev->allow_restart = 1;
+ 
++	/*
++	 * Update the dma alignment (minimum alignment requirements for
++	 * start and end of DMA transfers) to be a sector
++	 */
++	blk_queue_update_dma_alignment(sdev->request_queue, 511);
 +
- open_success:
- 	hvcs_kick();
+ 	if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ 		sdev->inquiry_len = 36;
  
-@@ -1212,9 +1191,8 @@ open_success:
- 	return 0;
+diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
+index 0fc9b00..172c186 100644
+--- a/drivers/firewire/fw-topology.c
++++ b/drivers/firewire/fw-topology.c
+@@ -21,6 +21,7 @@
+ #include <linux/module.h>
+ #include <linux/wait.h>
+ #include <linux/errno.h>
++#include <asm/system.h>
+ #include "fw-transaction.h"
+ #include "fw-topology.h"
  
- error_release:
--	kobjp = &hvcsd->kobj;
- 	spin_unlock_irqrestore(&hvcsd->lock, flags);
--	kobject_put(&hvcsd->kobj);
-+	kref_put(&hvcsd->kref, destroy_hvcs_struct);
+@@ -518,6 +519,11 @@ fw_core_handle_bus_reset(struct fw_card *card,
+ 		card->bm_retries = 0;
  
- 	printk(KERN_WARNING "HVCS: partner connect failed.\n");
- 	return retval;
-@@ -1224,7 +1202,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
- {
- 	struct hvcs_struct *hvcsd;
- 	unsigned long flags;
--	struct kobject *kobjp;
- 	int irq = NO_IRQ;
+ 	card->node_id = node_id;
++	/*
++	 * Update node_id before generation to prevent anybody from using
++	 * a stale node_id together with a current generation.
++	 */
++	smp_wmb();
+ 	card->generation = generation;
+ 	card->reset_jiffies = jiffies;
+ 	schedule_delayed_work(&card->work, 0);
+diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
+index c00d4a9..7fcc59d 100644
+--- a/drivers/firewire/fw-transaction.c
++++ b/drivers/firewire/fw-transaction.c
+@@ -153,7 +153,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
+ 	int ext_tcode;
  
- 	/*
-@@ -1245,7 +1222,6 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
- 	hvcsd = tty->driver_data;
+ 	if (tcode > 0x10) {
+-		ext_tcode = tcode - 0x10;
++		ext_tcode = tcode & ~0x10;
+ 		tcode = TCODE_LOCK_REQUEST;
+ 	} else
+ 		ext_tcode = 0;
+@@ -650,7 +650,7 @@ fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
+ 		 HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2];
+ 	tcode       = HEADER_GET_TCODE(p->header[0]);
+ 	destination = HEADER_GET_DESTINATION(p->header[0]);
+-	source      = HEADER_GET_SOURCE(p->header[0]);
++	source      = HEADER_GET_SOURCE(p->header[1]);
  
- 	spin_lock_irqsave(&hvcsd->lock, flags);
--	kobjp = &hvcsd->kobj;
- 	if (--hvcsd->open_count == 0) {
+ 	spin_lock_irqsave(&address_handler_lock, flags);
+ 	handler = lookup_enclosing_address_handler(&address_handler_list,
+diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
+index 5e596a7..9008ed5 100644
+--- a/drivers/firmware/dmi_scan.c
++++ b/drivers/firmware/dmi_scan.c
+@@ -8,6 +8,8 @@
+ #include <linux/slab.h>
+ #include <asm/dmi.h>
  
- 		vio_disable_interrupts(hvcsd->vdev);
-@@ -1270,7 +1246,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
- 		tty->driver_data = NULL;
++static char dmi_empty_string[] = "        ";
++
+ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
+ {
+ 	const u8 *bp = ((u8 *) dm) + dm->length;
+@@ -21,11 +23,16 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
+ 		}
  
- 		free_irq(irq, hvcsd);
--		kobject_put(kobjp);
-+		kref_put(&hvcsd->kref, destroy_hvcs_struct);
- 		return;
- 	} else if (hvcsd->open_count < 0) {
- 		printk(KERN_ERR "HVCS: vty-server@%X open_count: %d"
-@@ -1279,7 +1255,7 @@ static void hvcs_close(struct tty_struct *tty, struct file *filp)
+ 		if (*bp != 0) {
+-			str = dmi_alloc(strlen(bp) + 1);
++			size_t len = strlen(bp)+1;
++			size_t cmp_len = len > 8 ? 8 : len;
++
++			if (!memcmp(bp, dmi_empty_string, cmp_len))
++				return dmi_empty_string;
++			str = dmi_alloc(len);
+ 			if (str != NULL)
+ 				strcpy(str, bp);
+ 			else
+-				printk(KERN_ERR "dmi_string: out of memory.\n");
++				printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len);
+ 		}
  	}
  
- 	spin_unlock_irqrestore(&hvcsd->lock, flags);
--	kobject_put(kobjp);
-+	kref_put(&hvcsd->kref, destroy_hvcs_struct);
+@@ -175,12 +182,23 @@ static void __init dmi_save_devices(const struct dmi_header *dm)
+ 	}
  }
  
- static void hvcs_hangup(struct tty_struct * tty)
-@@ -1287,21 +1263,17 @@ static void hvcs_hangup(struct tty_struct * tty)
- 	struct hvcs_struct *hvcsd = tty->driver_data;
- 	unsigned long flags;
- 	int temp_open_count;
--	struct kobject *kobjp;
- 	int irq = NO_IRQ;
- 
- 	spin_lock_irqsave(&hvcsd->lock, flags);
--	/* Preserve this so that we know how many kobject refs to put */
-+	/* Preserve this so that we know how many kref refs to put */
- 	temp_open_count = hvcsd->open_count;
++static struct dmi_device empty_oem_string_dev = {
++	.name = dmi_empty_string,
++};
++
+ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
+ {
+ 	int i, count = *(u8 *)(dm + 1);
+ 	struct dmi_device *dev;
  
- 	/*
--	 * Don't kobject put inside the spinlock because the destruction
-+	 * Don't kref put inside the spinlock because the destruction
- 	 * callback may use the spinlock and it may get called before the
--	 * spinlock has been released.  Get a pointer to the kobject and
--	 * kobject_put on that after releasing the spinlock.
-+	 * spinlock has been released.
- 	 */
--	kobjp = &hvcsd->kobj;
--
- 	vio_disable_interrupts(hvcsd->vdev);
+ 	for (i = 1; i <= count; i++) {
++		char *devname = dmi_string(dm, i);
++
++		if (!strcmp(devname, dmi_empty_string)) {
++			list_add(&empty_oem_string_dev.list, &dmi_devices);
++			continue;
++		}
++
+ 		dev = dmi_alloc(sizeof(*dev));
+ 		if (!dev) {
+ 			printk(KERN_ERR
+@@ -189,7 +207,7 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
+ 		}
  
- 	hvcsd->todo_mask = 0;
-@@ -1324,7 +1296,7 @@ static void hvcs_hangup(struct tty_struct * tty)
- 	free_irq(irq, hvcsd);
+ 		dev->type = DMI_DEV_TYPE_OEM_STRING;
+-		dev->name = dmi_string(dm, i);
++		dev->name = devname;
+ 		dev->device_data = NULL;
  
- 	/*
--	 * We need to kobject_put() for every open_count we have since the
-+	 * We need to kref_put() for every open_count we have since the
- 	 * tty_hangup() function doesn't invoke a close per open connection on a
- 	 * non-console device.
- 	 */
-@@ -1335,7 +1307,7 @@ static void hvcs_hangup(struct tty_struct * tty)
- 		 * NOTE:  If this hangup was signaled from user space then the
- 		 * final put will never happen.
- 		 */
--		kobject_put(kobjp);
-+		kref_put(&hvcsd->kref, destroy_hvcs_struct);
+ 		list_add(&dev->list, &dmi_devices);
+@@ -331,9 +349,11 @@ void __init dmi_scan_machine(void)
+ 			rc = dmi_present(q);
+ 			if (!rc) {
+ 				dmi_available = 1;
++				dmi_iounmap(p, 0x10000);
+ 				return;
+ 			}
+ 		}
++		dmi_iounmap(p, 0x10000);
  	}
+  out:	printk(KERN_INFO "DMI not present or invalid.\n");
  }
+diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
+index 6942e06..7440119 100644
+--- a/drivers/firmware/edd.c
++++ b/drivers/firmware/edd.c
+@@ -11,7 +11,7 @@
+  *
+  * This code takes information provided by BIOS EDD calls
+  * fn41 - Check Extensions Present and
+- * fn48 - Get Device Parametes with EDD extensions
++ * fn48 - Get Device Parameters with EDD extensions
+  * made in setup.S, copied to safe structures in setup.c,
+  * and presents it in sysfs.
+  *
+@@ -631,7 +631,7 @@ static struct kobj_type edd_ktype = {
+ 	.default_attrs	= def_attrs,
+ };
  
-diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
-index 2d7cd48..6bbd4fa 100644
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -98,7 +98,7 @@ config HW_RANDOM_PASEMI
- 	default HW_RANDOM
- 	---help---
- 	  This driver provides kernel-side support for the Random Number
--	  Generator hardware found on PA6T-1682M processor.
-+	  Generator hardware found on PA Semi PWRficient SoCs.
- 
- 	  To compile this driver as a module, choose M here: the
- 	  module will be called pasemi-rng.
-diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
-index 556fd81..c422e87 100644
---- a/drivers/char/hw_random/amd-rng.c
-+++ b/drivers/char/hw_random/amd-rng.c
-@@ -28,6 +28,7 @@
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/hw_random.h>
-+#include <linux/delay.h>
- #include <asm/io.h>
- 
- 
-@@ -52,11 +53,18 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
- static struct pci_dev *amd_pdev;
+-static decl_subsys(edd, &edd_ktype, NULL);
++static struct kset *edd_kset;
  
  
--static int amd_rng_data_present(struct hwrng *rng)
-+static int amd_rng_data_present(struct hwrng *rng, int wait)
+ /**
+@@ -693,7 +693,7 @@ edd_create_symlink_to_pcidev(struct edd_device *edev)
+ static inline void
+ edd_device_unregister(struct edd_device *edev)
  {
- 	u32 pmbase = (u32)rng->priv;
-+	int data, i;
+-	kobject_unregister(&edev->kobj);
++	kobject_put(&edev->kobj);
+ }
  
--      	return !!(inl(pmbase + 0xF4) & 1);
-+	for (i = 0; i < 20; i++) {
-+		data = !!(inl(pmbase + 0xF4) & 1);
-+		if (data || !wait)
-+			break;
-+		udelay(10);
+ static void edd_populate_dir(struct edd_device * edev)
+@@ -721,12 +721,13 @@ edd_device_register(struct edd_device *edev, int i)
+ 	if (!edev)
+ 		return 1;
+ 	edd_dev_set_info(edev, i);
+-	kobject_set_name(&edev->kobj, "int13_dev%02x",
+-			 0x80 + i);
+-	kobj_set_kset_s(edev,edd_subsys);
+-	error = kobject_register(&edev->kobj);
+-	if (!error)
++	edev->kobj.kset = edd_kset;
++	error = kobject_init_and_add(&edev->kobj, &edd_ktype, NULL,
++				     "int13_dev%02x", 0x80 + i);
++	if (!error) {
+ 		edd_populate_dir(edev);
++		kobject_uevent(&edev->kobj, KOBJ_ADD);
 +	}
-+	return data;
+ 	return error;
  }
  
- static int amd_rng_data_read(struct hwrng *rng, u32 *data)
-diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
-index 26a860a..0118b98 100644
---- a/drivers/char/hw_random/core.c
-+++ b/drivers/char/hw_random/core.c
-@@ -66,11 +66,11 @@ static inline void hwrng_cleanup(struct hwrng *rng)
- 		rng->cleanup(rng);
+@@ -755,9 +756,9 @@ edd_init(void)
+ 		return 1;
+ 	}
+ 
+-	rc = firmware_register(&edd_subsys);
+-	if (rc)
+-		return rc;
++	edd_kset = kset_create_and_add("edd", NULL, firmware_kobj);
++	if (!edd_kset)
++		return -ENOMEM;
+ 
+ 	for (i = 0; i < edd_num_devices() && !rc; i++) {
+ 		edev = kzalloc(sizeof (*edev), GFP_KERNEL);
+@@ -773,7 +774,7 @@ edd_init(void)
+ 	}
+ 
+ 	if (rc)
+-		firmware_unregister(&edd_subsys);
++		kset_unregister(edd_kset);
+ 	return rc;
  }
  
--static inline int hwrng_data_present(struct hwrng *rng)
-+static inline int hwrng_data_present(struct hwrng *rng, int wait)
- {
- 	if (!rng->data_present)
- 		return 1;
--	return rng->data_present(rng);
-+	return rng->data_present(rng, wait);
+@@ -787,7 +788,7 @@ edd_exit(void)
+ 		if ((edev = edd_devices[i]))
+ 			edd_device_unregister(edev);
+ 	}
+-	firmware_unregister(&edd_subsys);
++	kset_unregister(edd_kset);
  }
  
- static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
-@@ -94,8 +94,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
- {
- 	u32 data;
- 	ssize_t ret = 0;
--	int i, err = 0;
--	int data_present;
-+	int err = 0;
- 	int bytes_read;
+ late_initcall(edd_init);
+diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
+index 858a7b9..f4f709d 100644
+--- a/drivers/firmware/efivars.c
++++ b/drivers/firmware/efivars.c
+@@ -129,13 +129,6 @@ struct efivar_attribute {
+ };
  
- 	while (size) {
-@@ -107,21 +106,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
- 			err = -ENODEV;
- 			goto out;
- 		}
--		if (filp->f_flags & O_NONBLOCK) {
--			data_present = hwrng_data_present(current_rng);
--		} else {
--			/* Some RNG require some time between data_reads to gather
--			 * new entropy. Poll it.
--			 */
--			for (i = 0; i < 20; i++) {
--				data_present = hwrng_data_present(current_rng);
--				if (data_present)
--					break;
--				udelay(10);
--			}
--		}
-+
- 		bytes_read = 0;
--		if (data_present)
-+		if (hwrng_data_present(current_rng,
-+				       !(filp->f_flags & O_NONBLOCK)))
- 			bytes_read = hwrng_data_read(current_rng, &data);
- 		mutex_unlock(&rng_mutex);
  
-diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
-index 8e8658d..fed4ef5 100644
---- a/drivers/char/hw_random/geode-rng.c
-+++ b/drivers/char/hw_random/geode-rng.c
-@@ -28,6 +28,7 @@
- #include <linux/kernel.h>
- #include <linux/pci.h>
- #include <linux/hw_random.h>
-+#include <linux/delay.h>
- #include <asm/io.h>
+-#define EFI_ATTR(_name, _mode, _show, _store) \
+-struct subsys_attribute efi_attr_##_name = { \
+-	.attr = {.name = __stringify(_name), .mode = _mode}, \
+-	.show = _show, \
+-	.store = _store, \
+-};
+-
+ #define EFIVAR_ATTR(_name, _mode, _show, _store) \
+ struct efivar_attribute efivar_attr_##_name = { \
+ 	.attr = {.name = __stringify(_name), .mode = _mode}, \
+@@ -143,13 +136,6 @@ struct efivar_attribute efivar_attr_##_name = { \
+ 	.store = _store, \
+ };
+ 
+-#define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
+-struct subsys_attribute var_subsys_attr_##_name = { \
+-	.attr = {.name = __stringify(_name), .mode = _mode}, \
+-	.show = _show, \
+-	.store = _store, \
+-};
+-
+ #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
+ #define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
  
+@@ -408,21 +394,16 @@ static struct kobj_type efivar_ktype = {
+ 	.default_attrs = def_attrs,
+ };
  
-@@ -61,11 +62,18 @@ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
- 	return 4;
+-static ssize_t
+-dummy(struct kset *kset, char *buf)
+-{
+-	return -ENODEV;
+-}
+-
+ static inline void
+ efivar_unregister(struct efivar_entry *var)
+ {
+-	kobject_unregister(&var->kobj);
++	kobject_put(&var->kobj);
  }
  
--static int geode_rng_data_present(struct hwrng *rng)
-+static int geode_rng_data_present(struct hwrng *rng, int wait)
+ 
+-static ssize_t
+-efivar_create(struct kset *kset, const char *buf, size_t count)
++static ssize_t efivar_create(struct kobject *kobj,
++			     struct bin_attribute *bin_attr,
++			     char *buf, loff_t pos, size_t count)
  {
- 	void __iomem *mem = (void __iomem *)rng->priv;
-+	int data, i;
+ 	struct efi_variable *new_var = (struct efi_variable *)buf;
+ 	struct efivar_entry *search_efivar, *n;
+@@ -479,8 +460,9 @@ efivar_create(struct kset *kset, const char *buf, size_t count)
+ 	return count;
+ }
  
--	return !!(readl(mem + GEODE_RNG_STATUS_REG));
-+	for (i = 0; i < 20; i++) {
-+		data = !!(readl(mem + GEODE_RNG_STATUS_REG));
-+		if (data || !wait)
-+			break;
-+		udelay(10);
-+	}
-+	return data;
+-static ssize_t
+-efivar_delete(struct kset *kset, const char *buf, size_t count)
++static ssize_t efivar_delete(struct kobject *kobj,
++			     struct bin_attribute *bin_attr,
++			     char *buf, loff_t pos, size_t count)
+ {
+ 	struct efi_variable *del_var = (struct efi_variable *)buf;
+ 	struct efivar_entry *search_efivar, *n;
+@@ -537,25 +519,26 @@ efivar_delete(struct kset *kset, const char *buf, size_t count)
+ 	return count;
  }
  
+-static VAR_SUBSYS_ATTR(new_var, 0200, dummy, efivar_create);
+-static VAR_SUBSYS_ATTR(del_var, 0200, dummy, efivar_delete);
++static struct bin_attribute var_subsys_attr_new_var = {
++	.attr = {.name = "new_var", .mode = 0200},
++	.write = efivar_create,
++};
  
-diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
-index 753f460..5cc651e 100644
---- a/drivers/char/hw_random/intel-rng.c
-+++ b/drivers/char/hw_random/intel-rng.c
-@@ -29,6 +29,7 @@
- #include <linux/module.h>
- #include <linux/pci.h>
- #include <linux/stop_machine.h>
-+#include <linux/delay.h>
- #include <asm/io.h>
+-static struct subsys_attribute *var_subsys_attrs[] = {
+-	&var_subsys_attr_new_var,
+-	&var_subsys_attr_del_var,
+-	NULL,
++static struct bin_attribute var_subsys_attr_del_var = {
++	.attr = {.name = "del_var", .mode = 0200},
++	.write = efivar_delete,
+ };
  
+ /*
+  * Let's not leave out systab information that snuck into
+  * the efivars driver
+  */
+-static ssize_t
+-systab_read(struct kset *kset, char *buf)
++static ssize_t systab_show(struct kobject *kobj,
++			   struct kobj_attribute *attr, char *buf)
+ {
+ 	char *str = buf;
  
-@@ -162,11 +163,19 @@ static inline u8 hwstatus_set(void __iomem *mem,
- 	return hwstatus_get(mem);
- }
+-	if (!kset || !buf)
++	if (!kobj || !buf)
+ 		return -EINVAL;
  
--static int intel_rng_data_present(struct hwrng *rng)
-+static int intel_rng_data_present(struct hwrng *rng, int wait)
- {
- 	void __iomem *mem = (void __iomem *)rng->priv;
--
--	return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
-+	int data, i;
-+
-+	for (i = 0; i < 20; i++) {
-+		data = !!(readb(mem + INTEL_RNG_STATUS) &
-+			  INTEL_RNG_DATA_PRESENT);
-+		if (data || !wait)
-+			break;
-+		udelay(10);
-+	}
-+	return data;
+ 	if (efi.mps != EFI_INVALID_TABLE_ADDR)
+@@ -576,15 +559,21 @@ systab_read(struct kset *kset, char *buf)
+ 	return str - buf;
  }
  
- static int intel_rng_data_read(struct hwrng *rng, u32 *data)
-diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
-index 3f35a1c..7e31995 100644
---- a/drivers/char/hw_random/omap-rng.c
-+++ b/drivers/char/hw_random/omap-rng.c
-@@ -29,6 +29,7 @@
- #include <linux/err.h>
- #include <linux/platform_device.h>
- #include <linux/hw_random.h>
-+#include <linux/delay.h>
+-static EFI_ATTR(systab, 0400, systab_read, NULL);
++static struct kobj_attribute efi_attr_systab =
++			__ATTR(systab, 0400, systab_show, NULL);
  
- #include <asm/io.h>
+-static struct subsys_attribute *efi_subsys_attrs[] = {
+-	&efi_attr_systab,
++static struct attribute *efi_subsys_attrs[] = {
++	&efi_attr_systab.attr,
+ 	NULL,	/* maybe more in the future? */
+ };
  
-@@ -65,9 +66,17 @@ static void omap_rng_write_reg(int reg, u32 val)
- }
+-static decl_subsys(vars, &efivar_ktype, NULL);
+-static decl_subsys(efi, NULL, NULL);
++static struct attribute_group efi_subsys_attr_group = {
++	.attrs = efi_subsys_attrs,
++};
++
++
++static struct kset *vars_kset;
++static struct kobject *efi_kobj;
+ 
+ /*
+  * efivar_create_sysfs_entry()
+@@ -628,15 +617,16 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
+ 	*(short_name + strlen(short_name)) = '-';
+ 	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
+ 
+-	kobject_set_name(&new_efivar->kobj, "%s", short_name);
+-	kobj_set_kset_s(new_efivar, vars_subsys);
+-	i = kobject_register(&new_efivar->kobj);
++	new_efivar->kobj.kset = vars_kset;
++	i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL,
++				 "%s", short_name);
+ 	if (i) {
+ 		kfree(short_name);
+ 		kfree(new_efivar);
+ 		return 1;
+ 	}
  
- /* REVISIT: Does the status bit really work on 16xx? */
--static int omap_rng_data_present(struct hwrng *rng)
-+static int omap_rng_data_present(struct hwrng *rng, int wait)
- {
--	return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
-+	int data, i;
-+
-+	for (i = 0; i < 20; i++) {
-+		data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
-+		if (data || !wait)
-+			break;
-+		udelay(10);
-+	}
-+	return data;
- }
++	kobject_uevent(&new_efivar->kobj, KOBJ_ADD);
+ 	kfree(short_name);
+ 	short_name = NULL;
  
- static int omap_rng_data_read(struct hwrng *rng, u32 *data)
-diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
-index fa6040b..6d50e9b 100644
---- a/drivers/char/hw_random/pasemi-rng.c
-+++ b/drivers/char/hw_random/pasemi-rng.c
-@@ -23,6 +23,7 @@
- #include <linux/kernel.h>
- #include <linux/platform_device.h>
- #include <linux/hw_random.h>
-+#include <linux/delay.h>
- #include <asm/of_platform.h>
- #include <asm/io.h>
+@@ -660,9 +650,8 @@ efivars_init(void)
+ 	efi_status_t status = EFI_NOT_FOUND;
+ 	efi_guid_t vendor_guid;
+ 	efi_char16_t *variable_name;
+-	struct subsys_attribute *attr;
+ 	unsigned long variable_name_size = 1024;
+-	int i, error = 0;
++	int error = 0;
  
-@@ -41,12 +42,19 @@
+ 	if (!efi_enabled)
+ 		return -ENODEV;
+@@ -676,23 +665,18 @@ efivars_init(void)
+ 	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
+ 	       EFIVARS_DATE);
  
- #define MODULE_NAME "pasemi_rng"
+-	/*
+-	 * For now we'll register the efi subsys within this driver
+-	 */
+-
+-	error = firmware_register(&efi_subsys);
+-
+-	if (error) {
+-		printk(KERN_ERR "efivars: Firmware registration failed with error %d.\n", error);
++	/* For now we'll register the efi directory at /sys/firmware/efi */
++	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
++	if (!efi_kobj) {
++		printk(KERN_ERR "efivars: Firmware registration failed.\n");
++		error = -ENOMEM;
+ 		goto out_free;
+ 	}
  
--static int pasemi_rng_data_present(struct hwrng *rng)
-+static int pasemi_rng_data_present(struct hwrng *rng, int wait)
- {
- 	void __iomem *rng_regs = (void __iomem *)rng->priv;
+-	kobj_set_kset_s(&vars_subsys, efi_subsys);
 -
--	return (in_le32(rng_regs + SDCRNG_CTL_REG)
--		& SDCRNG_CTL_FVLD_M) ? 1 : 0;
-+	int data, i;
-+
-+	for (i = 0; i < 20; i++) {
-+		data = (in_le32(rng_regs + SDCRNG_CTL_REG)
-+			& SDCRNG_CTL_FVLD_M) ? 1 : 0;
-+		if (data || !wait)
-+			break;
-+		udelay(10);
-+	}
-+	return data;
- }
+-	error = subsystem_register(&vars_subsys);
+-
+-	if (error) {
+-		printk(KERN_ERR "efivars: Subsystem registration failed with error %d.\n", error);
++	vars_kset = kset_create_and_add("vars", NULL, efi_kobj);
++	if (!vars_kset) {
++		printk(KERN_ERR "efivars: Subsystem registration failed.\n");
++		error = -ENOMEM;
+ 		goto out_firmware_unregister;
+ 	}
  
- static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
-@@ -126,10 +134,9 @@ static int __devexit rng_remove(struct of_device *dev)
- }
+@@ -727,28 +711,28 @@ efivars_init(void)
+ 	 * Now add attributes to allow creation of new vars
+ 	 * and deletion of existing ones...
+ 	 */
+-
+-	for (i = 0; (attr = var_subsys_attrs[i]) && !error; i++) {
+-		if (attr->show && attr->store)
+-			error = subsys_create_file(&vars_subsys, attr);
+-	}
++	error = sysfs_create_bin_file(&vars_kset->kobj,
++				      &var_subsys_attr_new_var);
++	if (error)
++		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
++			" due to error %d\n", error);
++	error = sysfs_create_bin_file(&vars_kset->kobj,
++				      &var_subsys_attr_del_var);
++	if (error)
++		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
++			" due to error %d\n", error);
  
- static struct of_device_id rng_match[] = {
--	{
--		.compatible      = "1682m-rng",
--	},
--	{},
-+	{ .compatible      = "1682m-rng", },
-+	{ .compatible      = "pasemi,pwrficient-rng", },
-+	{ },
- };
+ 	/* Don't forget the systab entry */
+-
+-	for (i = 0; (attr = efi_subsys_attrs[i]) && !error; i++) {
+-		if (attr->show)
+-			error = subsys_create_file(&efi_subsys, attr);
+-	}
+-
++	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
+ 	if (error)
+ 		printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
+ 	else
+ 		goto out_free;
  
- static struct of_platform_driver rng_driver = {
-diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
-index ec435cb..868e39f 100644
---- a/drivers/char/hw_random/via-rng.c
-+++ b/drivers/char/hw_random/via-rng.c
-@@ -27,6 +27,7 @@
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/hw_random.h>
-+#include <linux/delay.h>
- #include <asm/io.h>
- #include <asm/msr.h>
- #include <asm/cpufeature.h>
-@@ -77,10 +78,11 @@ static inline u32 xstore(u32 *addr, u32 edx_in)
- 	return eax_out;
- }
+-	subsystem_unregister(&vars_subsys);
++	kset_unregister(vars_kset);
  
--static int via_rng_data_present(struct hwrng *rng)
-+static int via_rng_data_present(struct hwrng *rng, int wait)
- {
- 	u32 bytes_out;
- 	u32 *via_rng_datum = (u32 *)(&rng->priv);
-+	int i;
+ out_firmware_unregister:
+-	firmware_unregister(&efi_subsys);
++	kobject_put(efi_kobj);
  
- 	/* We choose the recommended 1-byte-per-instruction RNG rate,
- 	 * for greater randomness at the expense of speed.  Larger
-@@ -95,12 +97,15 @@ static int via_rng_data_present(struct hwrng *rng)
- 	 * completes.
- 	 */
+ out_free:
+ 	kfree(variable_name);
+@@ -768,8 +752,8 @@ efivars_exit(void)
+ 		efivar_unregister(entry);
+ 	}
  
--	*via_rng_datum = 0; /* paranoia, not really necessary */
--	bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
--	bytes_out &= VIA_XSTORE_CNT_MASK;
--	if (bytes_out == 0)
--		return 0;
--	return 1;
-+	for (i = 0; i < 20; i++) {
-+		*via_rng_datum = 0; /* paranoia, not really necessary */
-+		bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
-+		bytes_out &= VIA_XSTORE_CNT_MASK;
-+		if (bytes_out || !wait)
-+			break;
-+		udelay(10);
-+	}
-+	return bytes_out ? 1 : 0;
+-	subsystem_unregister(&vars_subsys);
+-	firmware_unregister(&efi_subsys);
++	kset_unregister(vars_kset);
++	kobject_put(efi_kobj);
  }
  
- static int via_rng_data_read(struct hwrng *rng, u32 *data)
-diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
+ module_init(efivars_init);
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
 new file mode 100644
-index 0000000..6076e66
+index 0000000..74fac0f
 --- /dev/null
-+++ b/drivers/char/nozomi.c
-@@ -0,0 +1,1993 @@
-+/*
-+ * nozomi.c  -- HSDPA driver Broadband Wireless Data Card - Globe Trotter
-+ *
-+ * Written by: Ulf Jakobsson,
-+ *             Jan �erfeldt,
-+ *             Stefan Thomasson,
-+ *
-+ * Maintained by: Paul Hardwick (p.hardwick at option.com)
-+ *
-+ * Patches:
-+ *          Locking code changes for Vodafone by Sphere Systems Ltd,
-+ *                              Andrew Bird (ajb at spheresystems.co.uk )
-+ *                              & Phil Sanderson
-+ *
-+ * Source has been ported from an implementation made by Filip Aben @ Option
-+ *
-+ * --------------------------------------------------------------------------
-+ *
-+ * Copyright (c) 2005,2006 Option Wireless Sweden AB
-+ * Copyright (c) 2006 Sphere Systems Ltd
-+ * Copyright (c) 2006 Option Wireless n/v
-+ * All rights Reserved.
-+ *
-+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-+ *
-+ * --------------------------------------------------------------------------
-+ */
++++ b/drivers/gpio/Kconfig
+@@ -0,0 +1,72 @@
++#
++# GPIO infrastructure and expanders
++#
 +
-+/*
-+ * CHANGELOG
-+ * Version 2.1d
-+ * 11-November-2007 Jiri Slaby, Frank Seidel
-+ * - Big rework of multicard support by Jiri
-+ * - Major cleanups (semaphore to mutex, endianess, no major reservation)
-+ * - Optimizations
-+ *
-+ * Version 2.1c
-+ * 30-October-2007 Frank Seidel
-+ * - Completed multicard support
-+ * - Minor cleanups
-+ *
-+ * Version 2.1b
-+ * 07-August-2007 Frank Seidel
-+ * - Minor cleanups
-+ * - theoretical multicard support
-+ *
-+ * Version 2.1
-+ * 03-July-2006 Paul Hardwick
-+ *
-+ * - Stability Improvements. Incorporated spinlock wraps patch.
-+ * - Updated for newer 2.6.14+ kernels (tty_buffer_request_room)
-+ * - using __devexit macro for tty
-+ *
-+ *
-+ * Version 2.0
-+ * 08-feb-2006 15:34:10:Ulf
-+ *
-+ * -Fixed issue when not waking up line disipine layer, could probably result
-+ *  in better uplink performance for 2.4.
-+ *
-+ * -Fixed issue with big endian during initalization, now proper toggle flags
-+ *  are handled between preloader and maincode.
-+ *
-+ * -Fixed flow control issue.
-+ *
-+ * -Added support for setting DTR.
-+ *
-+ * -For 2.4 kernels, removing temporary buffer that's not needed.
-+ *
-+ * -Reading CTS only for modem port (only port that supports it).
-+ *
-+ * -Return 0 in write_room instead of netative value, it's not handled in
-+ *  upper layer.
-+ *
-+ * --------------------------------------------------------------------------
-+ * Version 1.0
-+ *
-+ * First version of driver, only tested with card of type F32_2.
-+ * Works fine with 2.4 and 2.6 kernels.
-+ * Driver also support big endian architecture.
-+ */
++config HAVE_GPIO_LIB
++	bool
++	help
++	  Platforms select gpiolib if they use this infrastructure
++	  for all their GPIOs, usually starting with ones integrated
++	  into SOC processors.
 +
-+/* Enable this to have a lot of debug printouts */
-+#define DEBUG
++menu "GPIO Support"
++	depends on HAVE_GPIO_LIB
 +
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/pci.h>
-+#include <linux/ioport.h>
-+#include <linux/tty.h>
-+#include <linux/tty_driver.h>
-+#include <linux/tty_flip.h>
-+#include <linux/serial.h>
-+#include <linux/interrupt.h>
-+#include <linux/kmod.h>
-+#include <linux/init.h>
-+#include <linux/kfifo.h>
-+#include <linux/uaccess.h>
-+#include <asm/byteorder.h>
++config DEBUG_GPIO
++	bool "Debug GPIO calls"
++	depends on DEBUG_KERNEL
++	help
++	  Say Y here to add some extra checks and diagnostics to GPIO calls.
++	  The checks help ensure that GPIOs have been properly initialized
++	  before they are used and that sleeping calls aren not made from
++	  nonsleeping contexts.  They can make bitbanged serial protocols
++	  slower.  The diagnostics help catch the type of setup errors
++	  that are most common when setting up new platforms or boards.
 +
-+#include <linux/delay.h>
++# put expanders in the right section, in alphabetical order
 +
++comment "I2C GPIO expanders:"
 +
-+#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \
-+					__DATE__ " " __TIME__ ")"
++config GPIO_PCA9539
++	tristate "PCA9539 16-bit I/O port"
++	depends on I2C
++	help
++	  Say yes here to support the PCA9539 16-bit I/O port. These
++	  parts are made by NXP and TI.
 +
-+/*    Macros definitions */
++	  This driver can also be built as a module.  If so, the module
++	  will be called pca9539.
 +
-+/* Default debug printout level */
-+#define NOZOMI_DEBUG_LEVEL 0x00
++config GPIO_PCF857X
++	tristate "PCF857x, PCA857x, and PCA967x I2C GPIO expanders"
++	depends on I2C
++	help
++	  Say yes here to provide access to most "quasi-bidirectional" I2C
++	  GPIO expanders used for additional digital outputs or inputs.
++	  Most of these parts are from NXP, though TI is a second source for
++	  some of them.  Compatible models include:
++
++	  8 bits:   pcf8574, pcf8574a, pca8574, pca8574a,
++	            pca9670, pca9672, pca9674, pca9674a
++
++	  16 bits:  pcf8575, pcf8575c, pca8575,
++	            pca9671, pca9673, pca9675
++
++	  Your board setup code will need to declare the expanders in
++	  use, and assign numbers to the GPIOs they expose.  Those GPIOs
++	  can then be used from drivers and other kernel code, just like
++	  other GPIOs, but only accessible from task contexts.
++
++	  This driver provides an in-kernel interface to those GPIOs using
++	  platform-neutral GPIO calls.
++
++comment "SPI GPIO expanders:"
++
++config GPIO_MCP23S08
++	tristate "Microchip MCP23S08 I/O expander"
++	depends on SPI_MASTER
++	help
++	  SPI driver for Microchip MCP23S08 I/O expander.  This provides
++	  a GPIO interface supporting inputs and outputs.
 +
-+#define P_BUF_SIZE 128
-+#define NFO(_err_flag_, args...)				\
-+do {								\
-+	char tmp[P_BUF_SIZE];					\
-+	snprintf(tmp, sizeof(tmp), ##args);			\
-+	printk(_err_flag_ "[%d] %s(): %s\n", __LINE__,		\
-+		__FUNCTION__, tmp);				\
-+} while (0)
++endmenu
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+new file mode 100644
+index 0000000..470ecd6
+--- /dev/null
++++ b/drivers/gpio/Makefile
+@@ -0,0 +1,9 @@
++# gpio support: dedicated expander chips, etc
 +
-+#define DBG1(args...) D_(0x01, ##args)
-+#define DBG2(args...) D_(0x02, ##args)
-+#define DBG3(args...) D_(0x04, ##args)
-+#define DBG4(args...) D_(0x08, ##args)
-+#define DBG5(args...) D_(0x10, ##args)
-+#define DBG6(args...) D_(0x20, ##args)
-+#define DBG7(args...) D_(0x40, ##args)
-+#define DBG8(args...) D_(0x80, ##args)
++ccflags-$(CONFIG_DEBUG_GPIO)	+= -DDEBUG
 +
-+#ifdef DEBUG
-+/* Do we need this settable at runtime? */
-+static int debug = NOZOMI_DEBUG_LEVEL;
++obj-$(CONFIG_HAVE_GPIO_LIB)	+= gpiolib.o
 +
-+#define D(lvl, args...)  do {if (lvl & debug) NFO(KERN_DEBUG, ##args); } \
-+				while (0)
-+#define D_(lvl, args...) D(lvl, ##args)
++obj-$(CONFIG_GPIO_MCP23S08)	+= mcp23s08.o
++obj-$(CONFIG_GPIO_PCA9539)	+= pca9539.o
++obj-$(CONFIG_GPIO_PCF857X)	+= pcf857x.o
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+new file mode 100644
+index 0000000..d8db2f8
+--- /dev/null
++++ b/drivers/gpio/gpiolib.c
+@@ -0,0 +1,567 @@
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/irq.h>
++#include <linux/spinlock.h>
 +
-+/* These printouts are always printed */
++#include <asm/gpio.h>
 +
++
++/* Optional implementation infrastructure for GPIO interfaces.
++ *
++ * Platforms may want to use this if they tend to use very many GPIOs
++ * that aren't part of a System-On-Chip core; or across I2C/SPI/etc.
++ *
++ * When kernel footprint or instruction count is an issue, simpler
++ * implementations may be preferred.  The GPIO programming interface
++ * allows for inlining speed-critical get/set operations for common
++ * cases, so that access to SOC-integrated GPIOs can sometimes cost
++ * only an instruction or two per bit.
++ */
++
++
++/* When debugging, extend minimal trust to callers and platform code.
++ * Also emit diagnostic messages that may help initial bringup, when
++ * board setup or driver bugs are most common.
++ *
++ * Otherwise, minimize overhead in what may be bitbanging codepaths.
++ */
++#ifdef	DEBUG
++#define	extra_checks	1
 +#else
-+static int debug;
-+#define D_(lvl, args...)
++#define	extra_checks	0
 +#endif
 +
-+/* TODO: rewrite to optimize macros... */
++/* gpio_lock prevents conflicts during gpio_desc[] table updates.
++ * While any GPIO is requested, its gpio_chip is not removable;
++ * each GPIO's "requested" flag serves as a lock and refcount.
++ */
++static DEFINE_SPINLOCK(gpio_lock);
 +
-+#define TMP_BUF_MAX 256
++struct gpio_desc {
++	struct gpio_chip	*chip;
++	unsigned long		flags;
++/* flag symbols are bit numbers */
++#define FLAG_REQUESTED	0
++#define FLAG_IS_OUT	1
 +
-+#define DUMP(buf__,len__) \
-+  do {  \
-+    char tbuf[TMP_BUF_MAX] = {0};\
-+    if (len__ > 1) {\
-+	snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\
-+	if (tbuf[len__-2] == '\r') {\
-+		tbuf[len__-2] = 'r';\
-+	} \
-+	DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\
-+    } else {\
-+	DBG1("SENDING: '%s' (%d)", tbuf, len__);\
-+    } \
-+} while (0)
++#ifdef CONFIG_DEBUG_FS
++	const char		*label;
++#endif
++};
++static struct gpio_desc gpio_desc[ARCH_NR_GPIOS];
 +
-+/*    Defines */
-+#define NOZOMI_NAME		"nozomi"
-+#define NOZOMI_NAME_TTY		"nozomi_tty"
-+#define DRIVER_DESC		"Nozomi driver"
++static inline void desc_set_label(struct gpio_desc *d, const char *label)
++{
++#ifdef CONFIG_DEBUG_FS
++	d->label = label;
++#endif
++}
 +
-+#define NTTY_TTY_MAXMINORS	256
-+#define NTTY_FIFO_BUFFER_SIZE	8192
++/* Warn when drivers omit gpio_request() calls -- legal but ill-advised
++ * when setting direction, and otherwise illegal.  Until board setup code
++ * and drivers use explicit requests everywhere (which won't happen when
++ * those calls have no teeth) we can't avoid autorequesting.  This nag
++ * message should motivate switching to explicit requests...
++ */
++static void gpio_ensure_requested(struct gpio_desc *desc)
++{
++	if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
++		pr_warning("GPIO-%d autorequested\n", (int)(desc - gpio_desc));
++		desc_set_label(desc, "[auto]");
++	}
++}
 +
-+/* Must be power of 2 */
-+#define FIFO_BUFFER_SIZE_UL	8192
++/* caller holds gpio_lock *OR* gpio is marked as requested */
++static inline struct gpio_chip *gpio_to_chip(unsigned gpio)
++{
++	return gpio_desc[gpio].chip;
++}
 +
-+/* Size of tmp send buffer to card */
-+#define SEND_BUF_MAX		1024
-+#define RECEIVE_BUF_MAX		4
++/**
++ * gpiochip_add() - register a gpio_chip
++ * @chip: the chip to register, with chip->base initialized
++ * Context: potentially before irqs or kmalloc will work
++ *
++ * Returns a negative errno if the chip can't be registered, such as
++ * because the chip->base is invalid or already associated with a
++ * different chip.  Otherwise it returns zero as a success code.
++ */
++int gpiochip_add(struct gpio_chip *chip)
++{
++	unsigned long	flags;
++	int		status = 0;
++	unsigned	id;
 +
++	/* NOTE chip->base negative is reserved to mean a request for
++	 * dynamic allocation.  We don't currently support that.
++	 */
 +
-+/* Define all types of vendors and devices to support */
-+#define VENDOR1		0x1931	/* Vendor Option */
-+#define DEVICE1		0x000c	/* HSDPA card */
++	if (chip->base < 0 || (chip->base  + chip->ngpio) >= ARCH_NR_GPIOS) {
++		status = -EINVAL;
++		goto fail;
++	}
 +
-+#define R_IIR		0x0000	/* Interrupt Identity Register */
-+#define R_FCR		0x0000	/* Flow Control Register */
-+#define R_IER		0x0004	/* Interrupt Enable Register */
++	spin_lock_irqsave(&gpio_lock, flags);
 +
-+#define CONFIG_MAGIC	0xEFEFFEFE
-+#define TOGGLE_VALID	0x0000
++	/* these GPIO numbers must not be managed by another gpio_chip */
++	for (id = chip->base; id < chip->base + chip->ngpio; id++) {
++		if (gpio_desc[id].chip != NULL) {
++			status = -EBUSY;
++			break;
++		}
++	}
++	if (status == 0) {
++		for (id = chip->base; id < chip->base + chip->ngpio; id++) {
++			gpio_desc[id].chip = chip;
++			gpio_desc[id].flags = 0;
++		}
++	}
 +
-+/* Definition of interrupt tokens */
-+#define MDM_DL1		0x0001
-+#define MDM_UL1		0x0002
-+#define MDM_DL2		0x0004
-+#define MDM_UL2		0x0008
-+#define DIAG_DL1	0x0010
-+#define DIAG_DL2	0x0020
-+#define DIAG_UL		0x0040
-+#define APP1_DL		0x0080
-+#define APP1_UL		0x0100
-+#define APP2_DL		0x0200
-+#define APP2_UL		0x0400
-+#define CTRL_DL		0x0800
-+#define CTRL_UL		0x1000
-+#define RESET		0x8000
++	spin_unlock_irqrestore(&gpio_lock, flags);
++fail:
++	/* failures here can mean systems won't boot... */
++	if (status)
++		pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n",
++			chip->base, chip->base + chip->ngpio,
++			chip->label ? : "generic");
++	return status;
++}
++EXPORT_SYMBOL_GPL(gpiochip_add);
 +
-+#define MDM_DL		(MDM_DL1  | MDM_DL2)
-+#define MDM_UL		(MDM_UL1  | MDM_UL2)
-+#define DIAG_DL		(DIAG_DL1 | DIAG_DL2)
++/**
++ * gpiochip_remove() - unregister a gpio_chip
++ * @chip: the chip to unregister
++ *
++ * A gpio_chip with any GPIOs still requested may not be removed.
++ */
++int gpiochip_remove(struct gpio_chip *chip)
++{
++	unsigned long	flags;
++	int		status = 0;
++	unsigned	id;
 +
-+/* modem signal definition */
-+#define CTRL_DSR	0x0001
-+#define CTRL_DCD	0x0002
-+#define CTRL_RI		0x0004
-+#define CTRL_CTS	0x0008
++	spin_lock_irqsave(&gpio_lock, flags);
 +
-+#define CTRL_DTR	0x0001
-+#define CTRL_RTS	0x0002
++	for (id = chip->base; id < chip->base + chip->ngpio; id++) {
++		if (test_bit(FLAG_REQUESTED, &gpio_desc[id].flags)) {
++			status = -EBUSY;
++			break;
++		}
++	}
++	if (status == 0) {
++		for (id = chip->base; id < chip->base + chip->ngpio; id++)
++			gpio_desc[id].chip = NULL;
++	}
 +
-+#define MAX_PORT		4
-+#define NOZOMI_MAX_PORTS	5
-+#define NOZOMI_MAX_CARDS	(NTTY_TTY_MAXMINORS / MAX_PORT)
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	return status;
++}
++EXPORT_SYMBOL_GPL(gpiochip_remove);
 +
-+/*    Type definitions */
 +
-+/*
-+ * There are two types of nozomi cards,
-+ * one with 2048 memory and with 8192 memory
++/* These "optional" allocation calls help prevent drivers from stomping
++ * on each other, and help provide better diagnostics in debugfs.
++ * They're called even less than the "set direction" calls.
 + */
-+enum card_type {
-+	F32_2 = 2048,	/* 512 bytes downlink + uplink * 2 -> 2048 */
-+	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
-+};
++int gpio_request(unsigned gpio, const char *label)
++{
++	struct gpio_desc	*desc;
++	int			status = -EINVAL;
++	unsigned long		flags;
 +
-+/* Two different toggle channels exist */
-+enum channel_type {
-+	CH_A = 0,
-+	CH_B = 1,
-+};
++	spin_lock_irqsave(&gpio_lock, flags);
 +
-+/* Port definition for the card regarding flow control */
-+enum ctrl_port_type {
-+	CTRL_CMD	= 0,
-+	CTRL_MDM	= 1,
-+	CTRL_DIAG	= 2,
-+	CTRL_APP1	= 3,
-+	CTRL_APP2	= 4,
-+	CTRL_ERROR	= -1,
-+};
++	if (gpio >= ARCH_NR_GPIOS)
++		goto done;
++	desc = &gpio_desc[gpio];
++	if (desc->chip == NULL)
++		goto done;
 +
-+/* Ports that the nozomi has */
-+enum port_type {
-+	PORT_MDM	= 0,
-+	PORT_DIAG	= 1,
-+	PORT_APP1	= 2,
-+	PORT_APP2	= 3,
-+	PORT_CTRL	= 4,
-+	PORT_ERROR	= -1,
-+};
++	/* NOTE:  gpio_request() can be called in early boot,
++	 * before IRQs are enabled.
++	 */
 +
-+#ifdef __BIG_ENDIAN
-+/* Big endian */
++	if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
++		desc_set_label(desc, label ? : "?");
++		status = 0;
++	} else
++		status = -EBUSY;
 +
-+struct toggles {
-+	unsigned enabled:5;	/*
-+				 * Toggle fields are valid if enabled is 0,
-+				 * else A-channels must always be used.
-+				 */
-+	unsigned diag_dl:1;
-+	unsigned mdm_dl:1;
-+	unsigned mdm_ul:1;
-+} __attribute__ ((packed));
++done:
++	if (status)
++		pr_debug("gpio_request: gpio-%d (%s) status %d\n",
++			gpio, label ? : "?", status);
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	return status;
++}
++EXPORT_SYMBOL_GPL(gpio_request);
 +
-+/* Configuration table to read at startup of card */
-+/* Is for now only needed during initialization phase */
-+struct config_table {
-+	u32 signature;
-+	u16 product_information;
-+	u16 version;
-+	u8 pad3[3];
-+	struct toggles toggle;
-+	u8 pad1[4];
-+	u16 dl_mdm_len1;	/*
-+				 * If this is 64, it can hold
-+				 * 60 bytes + 4 that is length field
-+				 */
-+	u16 dl_start;
++void gpio_free(unsigned gpio)
++{
++	unsigned long		flags;
++	struct gpio_desc	*desc;
 +
-+	u16 dl_diag_len1;
-+	u16 dl_mdm_len2;	/*
-+				 * If this is 64, it can hold
-+				 * 60 bytes + 4 that is length field
-+				 */
-+	u16 dl_app1_len;
++	if (gpio >= ARCH_NR_GPIOS) {
++		WARN_ON(extra_checks);
++		return;
++	}
 +
-+	u16 dl_diag_len2;
-+	u16 dl_ctrl_len;
-+	u16 dl_app2_len;
-+	u8 pad2[16];
-+	u16 ul_mdm_len1;
-+	u16 ul_start;
-+	u16 ul_diag_len;
-+	u16 ul_mdm_len2;
-+	u16 ul_app1_len;
-+	u16 ul_app2_len;
-+	u16 ul_ctrl_len;
-+} __attribute__ ((packed));
++	spin_lock_irqsave(&gpio_lock, flags);
 +
-+/* This stores all control downlink flags */
-+struct ctrl_dl {
-+	u8 port;
-+	unsigned reserved:4;
-+	unsigned CTS:1;
-+	unsigned RI:1;
-+	unsigned DCD:1;
-+	unsigned DSR:1;
-+} __attribute__ ((packed));
++	desc = &gpio_desc[gpio];
++	if (desc->chip && test_and_clear_bit(FLAG_REQUESTED, &desc->flags))
++		desc_set_label(desc, NULL);
++	else
++		WARN_ON(extra_checks);
 +
-+/* This stores all control uplink flags */
-+struct ctrl_ul {
-+	u8 port;
-+	unsigned reserved:6;
-+	unsigned RTS:1;
-+	unsigned DTR:1;
-+} __attribute__ ((packed));
++	spin_unlock_irqrestore(&gpio_lock, flags);
++}
++EXPORT_SYMBOL_GPL(gpio_free);
++
++
++/**
++ * gpiochip_is_requested - return string iff signal was requested
++ * @chip: controller managing the signal
++ * @offset: of signal within controller's 0..(ngpio - 1) range
++ *
++ * Returns NULL if the GPIO is not currently requested, else a string.
++ * If debugfs support is enabled, the string returned is the label passed
++ * to gpio_request(); otherwise it is a meaningless constant.
++ *
++ * This function is for use by GPIO controller drivers.  The label can
++ * help with diagnostics, and knowing that the signal is used as a GPIO
++ * can help avoid accidentally multiplexing it to another controller.
++ */
++const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset)
++{
++	unsigned gpio = chip->base + offset;
 +
++	if (gpio >= ARCH_NR_GPIOS || gpio_desc[gpio].chip != chip)
++		return NULL;
++	if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0)
++		return NULL;
++#ifdef CONFIG_DEBUG_FS
++	return gpio_desc[gpio].label;
 +#else
-+/* Little endian */
++	return "?";
++#endif
++}
++EXPORT_SYMBOL_GPL(gpiochip_is_requested);
 +
-+/* This represents the toggle information */
-+struct toggles {
-+	unsigned mdm_ul:1;
-+	unsigned mdm_dl:1;
-+	unsigned diag_dl:1;
-+	unsigned enabled:5;	/*
-+				 * Toggle fields are valid if enabled is 0,
-+				 * else A-channels must always be used.
-+				 */
-+} __attribute__ ((packed));
 +
-+/* Configuration table to read at startup of card */
-+struct config_table {
-+	u32 signature;
-+	u16 version;
-+	u16 product_information;
-+	struct toggles toggle;
-+	u8 pad1[7];
-+	u16 dl_start;
-+	u16 dl_mdm_len1;	/*
-+				 * If this is 64, it can hold
-+				 * 60 bytes + 4 that is length field
-+				 */
-+	u16 dl_mdm_len2;
-+	u16 dl_diag_len1;
-+	u16 dl_diag_len2;
-+	u16 dl_app1_len;
-+	u16 dl_app2_len;
-+	u16 dl_ctrl_len;
-+	u8 pad2[16];
-+	u16 ul_start;
-+	u16 ul_mdm_len2;
-+	u16 ul_mdm_len1;
-+	u16 ul_diag_len;
-+	u16 ul_app1_len;
-+	u16 ul_app2_len;
-+	u16 ul_ctrl_len;
-+} __attribute__ ((packed));
++/* Drivers MUST set GPIO direction before making get/set calls.  In
++ * some cases this is done in early boot, before IRQs are enabled.
++ *
++ * As a rule these aren't called more than once (except for drivers
++ * using the open-drain emulation idiom) so these are natural places
++ * to accumulate extra debugging checks.  Note that we can't (yet)
++ * rely on gpio_request() having been called beforehand.
++ */
 +
-+/* This stores all control downlink flags */
-+struct ctrl_dl {
-+	unsigned DSR:1;
-+	unsigned DCD:1;
-+	unsigned RI:1;
-+	unsigned CTS:1;
-+	unsigned reserverd:4;
-+	u8 port;
-+} __attribute__ ((packed));
++int gpio_direction_input(unsigned gpio)
++{
++	unsigned long		flags;
++	struct gpio_chip	*chip;
++	struct gpio_desc	*desc = &gpio_desc[gpio];
++	int			status = -EINVAL;
 +
-+/* This stores all control uplink flags */
-+struct ctrl_ul {
-+	unsigned DTR:1;
-+	unsigned RTS:1;
-+	unsigned reserved:6;
-+	u8 port;
-+} __attribute__ ((packed));
-+#endif
++	spin_lock_irqsave(&gpio_lock, flags);
 +
-+/* This holds all information that is needed regarding a port */
-+struct port {
-+	u8 update_flow_control;
-+	struct ctrl_ul ctrl_ul;
-+	struct ctrl_dl ctrl_dl;
-+	struct kfifo *fifo_ul;
-+	void __iomem *dl_addr[2];
-+	u32 dl_size[2];
-+	u8 toggle_dl;
-+	void __iomem *ul_addr[2];
-+	u32 ul_size[2];
-+	u8 toggle_ul;
-+	u16 token_dl;
++	if (gpio >= ARCH_NR_GPIOS)
++		goto fail;
++	chip = desc->chip;
++	if (!chip || !chip->get || !chip->direction_input)
++		goto fail;
++	gpio -= chip->base;
++	if (gpio >= chip->ngpio)
++		goto fail;
++	gpio_ensure_requested(desc);
 +
-+	struct tty_struct *tty;
-+	int tty_open_count;
-+	/* mutex to ensure one access patch to this port */
-+	struct mutex tty_sem;
-+	wait_queue_head_t tty_wait;
-+	struct async_icount tty_icount;
-+};
++	/* now we know the gpio is valid and chip won't vanish */
 +
-+/* Private data one for each card in the system */
-+struct nozomi {
-+	void __iomem *base_addr;
-+	unsigned long flip;
++	spin_unlock_irqrestore(&gpio_lock, flags);
 +
-+	/* Pointers to registers */
-+	void __iomem *reg_iir;
-+	void __iomem *reg_fcr;
-+	void __iomem *reg_ier;
++	might_sleep_if(extra_checks && chip->can_sleep);
 +
-+	u16 last_ier;
-+	enum card_type card_type;
-+	struct config_table config_table;	/* Configuration table */
-+	struct pci_dev *pdev;
-+	struct port port[NOZOMI_MAX_PORTS];
-+	u8 *send_buf;
++	status = chip->direction_input(chip, gpio);
++	if (status == 0)
++		clear_bit(FLAG_IS_OUT, &desc->flags);
++	return status;
++fail:
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	if (status)
++		pr_debug("%s: gpio-%d status %d\n",
++			__FUNCTION__, gpio, status);
++	return status;
++}
++EXPORT_SYMBOL_GPL(gpio_direction_input);
 +
-+	spinlock_t spin_mutex;	/* secures access to registers and tty */
++int gpio_direction_output(unsigned gpio, int value)
++{
++	unsigned long		flags;
++	struct gpio_chip	*chip;
++	struct gpio_desc	*desc = &gpio_desc[gpio];
++	int			status = -EINVAL;
 +
-+	unsigned int index_start;
-+	u32 open_ttys;
-+};
++	spin_lock_irqsave(&gpio_lock, flags);
 +
-+/* This is a data packet that is read or written to/from card */
-+struct buffer {
-+	u32 size;		/* size is the length of the data buffer */
-+	u8 *data;
-+} __attribute__ ((packed));
++	if (gpio >= ARCH_NR_GPIOS)
++		goto fail;
++	chip = desc->chip;
++	if (!chip || !chip->set || !chip->direction_output)
++		goto fail;
++	gpio -= chip->base;
++	if (gpio >= chip->ngpio)
++		goto fail;
++	gpio_ensure_requested(desc);
 +
-+/*    Global variables */
-+static struct pci_device_id nozomi_pci_tbl[] = {
-+	{PCI_DEVICE(VENDOR1, DEVICE1)},
-+	{},
-+};
++	/* now we know the gpio is valid and chip won't vanish */
 +
-+MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
++	spin_unlock_irqrestore(&gpio_lock, flags);
 +
-+static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
-+static struct tty_driver *ntty_driver;
++	might_sleep_if(extra_checks && chip->can_sleep);
 +
-+/*
-+ * find card by tty_index
++	status = chip->direction_output(chip, gpio, value);
++	if (status == 0)
++		set_bit(FLAG_IS_OUT, &desc->flags);
++	return status;
++fail:
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	if (status)
++		pr_debug("%s: gpio-%d status %d\n",
++			__FUNCTION__, gpio, status);
++	return status;
++}
++EXPORT_SYMBOL_GPL(gpio_direction_output);
++
++
++/* I/O calls are only valid after configuration completed; the relevant
++ * "is this a valid GPIO" error checks should already have been done.
++ *
++ * "Get" operations are often inlinable as reading a pin value register,
++ * and masking the relevant bit in that register.
++ *
++ * When "set" operations are inlinable, they involve writing that mask to
++ * one register to set a low value, or a different register to set it high.
++ * Otherwise locking is needed, so there may be little value to inlining.
++ *
++ *------------------------------------------------------------------------
++ *
++ * IMPORTANT!!!  The hot paths -- get/set value -- assume that callers
++ * have requested the GPIO.  That can include implicit requesting by
++ * a direction setting call.  Marking a gpio as requested locks its chip
++ * in memory, guaranteeing that these table lookups need no more locking
++ * and that gpiochip_remove() will fail.
++ *
++ * REVISIT when debugging, consider adding some instrumentation to ensure
++ * that the GPIO was actually requested.
 + */
-+static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
++
++/**
++ * __gpio_get_value() - return a gpio's value
++ * @gpio: gpio whose value will be returned
++ * Context: any
++ *
++ * This is used directly or indirectly to implement gpio_get_value().
++ * It returns the zero or nonzero value provided by the associated
++ * gpio_chip.get() method; or zero if no such method is provided.
++ */
++int __gpio_get_value(unsigned gpio)
 +{
-+	return tty ? ndevs[tty->index / MAX_PORT] : NULL;
++	struct gpio_chip	*chip;
++
++	chip = gpio_to_chip(gpio);
++	WARN_ON(extra_checks && chip->can_sleep);
++	return chip->get ? chip->get(chip, gpio - chip->base) : 0;
 +}
++EXPORT_SYMBOL_GPL(__gpio_get_value);
 +
-+static inline struct port *get_port_by_tty(const struct tty_struct *tty)
++/**
++ * __gpio_set_value() - assign a gpio's value
++ * @gpio: gpio whose value will be assigned
++ * @value: value to assign
++ * Context: any
++ *
++ * This is used directly or indirectly to implement gpio_set_value().
++ * It invokes the associated gpio_chip.set() method.
++ */
++void __gpio_set_value(unsigned gpio, int value)
 +{
-+	struct nozomi *ndev = get_dc_by_tty(tty);
-+	return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL;
++	struct gpio_chip	*chip;
++
++	chip = gpio_to_chip(gpio);
++	WARN_ON(extra_checks && chip->can_sleep);
++	chip->set(chip, gpio - chip->base, value);
 +}
++EXPORT_SYMBOL_GPL(__gpio_set_value);
 +
-+/*
-+ * TODO:
-+ * -Optimize
-+ * -Rewrite cleaner
++/**
++ * __gpio_cansleep() - report whether gpio value access will sleep
++ * @gpio: gpio in question
++ * Context: any
++ *
++ * This is used directly or indirectly to implement gpio_cansleep().  It
++ * returns nonzero if access reading or writing the GPIO value can sleep.
 + */
-+
-+static void read_mem32(u32 *buf, const void __iomem *mem_addr_start,
-+			u32 size_bytes)
++int __gpio_cansleep(unsigned gpio)
 +{
-+	u32 i = 0;
-+	const u32 *ptr = (__force u32 *) mem_addr_start;
-+	u16 *buf16;
-+
-+	if (unlikely(!ptr || !buf))
-+		goto out;
++	struct gpio_chip	*chip;
 +
-+	/* shortcut for extremely often used cases */
-+	switch (size_bytes) {
-+	case 2:	/* 2 bytes */
-+		buf16 = (u16 *) buf;
-+		*buf16 = __le16_to_cpu(readw((void __iomem *)ptr));
-+		goto out;
-+		break;
-+	case 4:	/* 4 bytes */
-+		*(buf) = __le32_to_cpu(readl((void __iomem *)ptr));
-+		goto out;
-+		break;
-+	}
++	/* only call this on GPIOs that are valid! */
++	chip = gpio_to_chip(gpio);
 +
-+	while (i < size_bytes) {
-+		if (size_bytes - i == 2) {
-+			/* Handle 2 bytes in the end */
-+			buf16 = (u16 *) buf;
-+			*(buf16) = __le16_to_cpu(readw((void __iomem *)ptr));
-+			i += 2;
-+		} else {
-+			/* Read 4 bytes */
-+			*(buf) = __le32_to_cpu(readl((void __iomem *)ptr));
-+			i += 4;
-+		}
-+		buf++;
-+		ptr++;
-+	}
-+out:
-+	return;
++	return chip->can_sleep;
 +}
++EXPORT_SYMBOL_GPL(__gpio_cansleep);
 +
-+/*
-+ * TODO:
-+ * -Optimize
-+ * -Rewrite cleaner
++
++
++/* There's no value in making it easy to inline GPIO calls that may sleep.
++ * Common examples include ones connected to I2C or SPI chips.
 + */
-+static u32 write_mem32(void __iomem *mem_addr_start, u32 *buf,
-+			u32 size_bytes)
++
++int gpio_get_value_cansleep(unsigned gpio)
 +{
-+	u32 i = 0;
-+	u32 *ptr = (__force u32 *) mem_addr_start;
-+	u16 *buf16;
++	struct gpio_chip	*chip;
 +
-+	if (unlikely(!ptr || !buf))
-+		return 0;
++	might_sleep_if(extra_checks);
++	chip = gpio_to_chip(gpio);
++	return chip->get(chip, gpio - chip->base);
++}
++EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
 +
-+	/* shortcut for extremely often used cases */
-+	switch (size_bytes) {
-+	case 2:	/* 2 bytes */
-+		buf16 = (u16 *) buf;
-+		writew(__cpu_to_le16(*buf16), (void __iomem *)ptr);
-+		return 2;
-+		break;
-+	case 1: /*
-+		 * also needs to write 4 bytes in this case
-+		 * so falling through..
-+		 */
-+	case 4: /* 4 bytes */
-+		writel(__cpu_to_le32(*buf), (void __iomem *)ptr);
-+		return 4;
-+		break;
-+	}
++void gpio_set_value_cansleep(unsigned gpio, int value)
++{
++	struct gpio_chip	*chip;
 +
-+	while (i < size_bytes) {
-+		if (size_bytes - i == 2) {
-+			/* 2 bytes */
-+			buf16 = (u16 *) buf;
-+			writew(__cpu_to_le16(*buf16), (void __iomem *)ptr);
-+			i += 2;
-+		} else {
-+			/* 4 bytes */
-+			writel(__cpu_to_le32(*buf), (void __iomem *)ptr);
-+			i += 4;
-+		}
-+		buf++;
-+		ptr++;
-+	}
-+	return i;
++	might_sleep_if(extra_checks);
++	chip = gpio_to_chip(gpio);
++	chip->set(chip, gpio - chip->base, value);
 +}
++EXPORT_SYMBOL_GPL(gpio_set_value_cansleep);
 +
-+/* Setup pointers to different channels and also setup buffer sizes. */
-+static void setup_memory(struct nozomi *dc)
-+{
-+	void __iomem *offset = dc->base_addr + dc->config_table.dl_start;
-+	/* The length reported is including the length field of 4 bytes,
-+	 * hence subtract with 4.
-+	 */
-+	const u16 buff_offset = 4;
 +
-+	/* Modem port dl configuration */
-+	dc->port[PORT_MDM].dl_addr[CH_A] = offset;
-+	dc->port[PORT_MDM].dl_addr[CH_B] =
-+				(offset += dc->config_table.dl_mdm_len1);
-+	dc->port[PORT_MDM].dl_size[CH_A] =
-+				dc->config_table.dl_mdm_len1 - buff_offset;
-+	dc->port[PORT_MDM].dl_size[CH_B] =
-+				dc->config_table.dl_mdm_len2 - buff_offset;
++#ifdef CONFIG_DEBUG_FS
 +
-+	/* Diag port dl configuration */
-+	dc->port[PORT_DIAG].dl_addr[CH_A] =
-+				(offset += dc->config_table.dl_mdm_len2);
-+	dc->port[PORT_DIAG].dl_size[CH_A] =
-+				dc->config_table.dl_diag_len1 - buff_offset;
-+	dc->port[PORT_DIAG].dl_addr[CH_B] =
-+				(offset += dc->config_table.dl_diag_len1);
-+	dc->port[PORT_DIAG].dl_size[CH_B] =
-+				dc->config_table.dl_diag_len2 - buff_offset;
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
 +
-+	/* App1 port dl configuration */
-+	dc->port[PORT_APP1].dl_addr[CH_A] =
-+				(offset += dc->config_table.dl_diag_len2);
-+	dc->port[PORT_APP1].dl_size[CH_A] =
-+				dc->config_table.dl_app1_len - buff_offset;
 +
-+	/* App2 port dl configuration */
-+	dc->port[PORT_APP2].dl_addr[CH_A] =
-+				(offset += dc->config_table.dl_app1_len);
-+	dc->port[PORT_APP2].dl_size[CH_A] =
-+				dc->config_table.dl_app2_len - buff_offset;
++static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
++{
++	unsigned		i;
++	unsigned		gpio = chip->base;
++	struct gpio_desc	*gdesc = &gpio_desc[gpio];
++	int			is_out;
 +
-+	/* Ctrl dl configuration */
-+	dc->port[PORT_CTRL].dl_addr[CH_A] =
-+				(offset += dc->config_table.dl_app2_len);
-+	dc->port[PORT_CTRL].dl_size[CH_A] =
-+				dc->config_table.dl_ctrl_len - buff_offset;
++	for (i = 0; i < chip->ngpio; i++, gpio++, gdesc++) {
++		if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
++			continue;
 +
-+	offset = dc->base_addr + dc->config_table.ul_start;
++		is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
++		seq_printf(s, " gpio-%-3d (%-12s) %s %s",
++			gpio, gdesc->label,
++			is_out ? "out" : "in ",
++			chip->get
++				? (chip->get(chip, i) ? "hi" : "lo")
++				: "?  ");
++
++		if (!is_out) {
++			int		irq = gpio_to_irq(gpio);
++			struct irq_desc	*desc = irq_desc + irq;
 +
-+	/* Modem Port ul configuration */
-+	dc->port[PORT_MDM].ul_addr[CH_A] = offset;
-+	dc->port[PORT_MDM].ul_size[CH_A] =
-+				dc->config_table.ul_mdm_len1 - buff_offset;
-+	dc->port[PORT_MDM].ul_addr[CH_B] =
-+				(offset += dc->config_table.ul_mdm_len1);
-+	dc->port[PORT_MDM].ul_size[CH_B] =
-+				dc->config_table.ul_mdm_len2 - buff_offset;
++			/* This races with request_irq(), set_irq_type(),
++			 * and set_irq_wake() ... but those are "rare".
++			 *
++			 * More significantly, trigger type flags aren't
++			 * currently maintained by genirq.
++			 */
++			if (irq >= 0 && desc->action) {
++				char *trigger;
 +
-+	/* Diag port ul configuration */
-+	dc->port[PORT_DIAG].ul_addr[CH_A] =
-+				(offset += dc->config_table.ul_mdm_len2);
-+	dc->port[PORT_DIAG].ul_size[CH_A] =
-+				dc->config_table.ul_diag_len - buff_offset;
++				switch (desc->status & IRQ_TYPE_SENSE_MASK) {
++				case IRQ_TYPE_NONE:
++					trigger = "(default)";
++					break;
++				case IRQ_TYPE_EDGE_FALLING:
++					trigger = "edge-falling";
++					break;
++				case IRQ_TYPE_EDGE_RISING:
++					trigger = "edge-rising";
++					break;
++				case IRQ_TYPE_EDGE_BOTH:
++					trigger = "edge-both";
++					break;
++				case IRQ_TYPE_LEVEL_HIGH:
++					trigger = "level-high";
++					break;
++				case IRQ_TYPE_LEVEL_LOW:
++					trigger = "level-low";
++					break;
++				default:
++					trigger = "?trigger?";
++					break;
++				}
 +
-+	/* App1 port ul configuration */
-+	dc->port[PORT_APP1].ul_addr[CH_A] =
-+				(offset += dc->config_table.ul_diag_len);
-+	dc->port[PORT_APP1].ul_size[CH_A] =
-+				dc->config_table.ul_app1_len - buff_offset;
++				seq_printf(s, " irq-%d %s%s",
++					irq, trigger,
++					(desc->status & IRQ_WAKEUP)
++						? " wakeup" : "");
++			}
++		}
 +
-+	/* App2 port ul configuration */
-+	dc->port[PORT_APP2].ul_addr[CH_A] =
-+				(offset += dc->config_table.ul_app1_len);
-+	dc->port[PORT_APP2].ul_size[CH_A] =
-+				dc->config_table.ul_app2_len - buff_offset;
++		seq_printf(s, "\n");
++	}
++}
 +
-+	/* Ctrl ul configuration */
-+	dc->port[PORT_CTRL].ul_addr[CH_A] =
-+				(offset += dc->config_table.ul_app2_len);
-+	dc->port[PORT_CTRL].ul_size[CH_A] =
-+				dc->config_table.ul_ctrl_len - buff_offset;
++static int gpiolib_show(struct seq_file *s, void *unused)
++{
++	struct gpio_chip	*chip = NULL;
++	unsigned		gpio;
++	int			started = 0;
++
++	/* REVISIT this isn't locked against gpio_chip removal ... */
++
++	for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) {
++		if (chip == gpio_desc[gpio].chip)
++			continue;
++		chip = gpio_desc[gpio].chip;
++		if (!chip)
++			continue;
++
++		seq_printf(s, "%sGPIOs %d-%d, %s%s:\n",
++				started ? "\n" : "",
++				chip->base, chip->base + chip->ngpio - 1,
++				chip->label ? : "generic",
++				chip->can_sleep ? ", can sleep" : "");
++		started = 1;
++		if (chip->dbg_show)
++			chip->dbg_show(s, chip);
++		else
++			gpiolib_dbg_show(s, chip);
++	}
++	return 0;
 +}
 +
-+/* Dump config table under initalization phase */
-+#ifdef DEBUG
-+static void dump_table(const struct nozomi *dc)
++static int gpiolib_open(struct inode *inode, struct file *file)
 +{
-+	DBG3("signature: 0x%08X", dc->config_table.signature);
-+	DBG3("version: 0x%04X", dc->config_table.version);
-+	DBG3("product_information: 0x%04X", \
-+				dc->config_table.product_information);
-+	DBG3("toggle enabled: %d", dc->config_table.toggle.enabled);
-+	DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul);
-+	DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl);
-+	DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl);
++	return single_open(file, gpiolib_show, NULL);
++}
 +
-+	DBG3("dl_start: 0x%04X", dc->config_table.dl_start);
-+	DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1,
-+	   dc->config_table.dl_mdm_len1);
-+	DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2,
-+	   dc->config_table.dl_mdm_len2);
-+	DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1,
-+	   dc->config_table.dl_diag_len1);
-+	DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2,
-+	   dc->config_table.dl_diag_len2);
-+	DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len,
-+	   dc->config_table.dl_app1_len);
-+	DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len,
-+	   dc->config_table.dl_app2_len);
-+	DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len,
-+	   dc->config_table.dl_ctrl_len);
-+	DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start,
-+	   dc->config_table.ul_start);
-+	DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1,
-+	   dc->config_table.ul_mdm_len1);
-+	DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2,
-+	   dc->config_table.ul_mdm_len2);
-+	DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len,
-+	   dc->config_table.ul_diag_len);
-+	DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len,
-+	   dc->config_table.ul_app1_len);
-+	DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len,
-+	   dc->config_table.ul_app2_len);
-+	DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len,
-+	   dc->config_table.ul_ctrl_len);
++static struct file_operations gpiolib_operations = {
++	.open		= gpiolib_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++};
++
++static int __init gpiolib_debugfs_init(void)
++{
++	/* /sys/kernel/debug/gpio */
++	(void) debugfs_create_file("gpio", S_IFREG | S_IRUGO,
++				NULL, NULL, &gpiolib_operations);
++	return 0;
 +}
-+#else
-+static __inline__ void dump_table(const struct nozomi *dc) { }
-+#endif
++subsys_initcall(gpiolib_debugfs_init);
 +
++#endif	/* DEBUG_FS */
+diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
+new file mode 100644
+index 0000000..bb60e8c
+--- /dev/null
++++ b/drivers/gpio/mcp23s08.c
+@@ -0,0 +1,357 @@
 +/*
-+ * Read configuration table from card under intalization phase
-+ * Returns 1 if ok, else 0
++ * mcp23s08.c - SPI gpio expander driver
 + */
-+static int nozomi_read_config_table(struct nozomi *dc)
-+{
-+	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
-+						sizeof(struct config_table));
 +
-+	if (dc->config_table.signature != CONFIG_MAGIC) {
-+		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
-+			dc->config_table.signature, CONFIG_MAGIC);
-+		return 0;
-+	}
++#include <linux/kernel.h>
++#include <linux/device.h>
++#include <linux/workqueue.h>
++#include <linux/mutex.h>
 +
-+	if ((dc->config_table.version == 0)
-+	    || (dc->config_table.toggle.enabled == TOGGLE_VALID)) {
-+		int i;
-+		DBG1("Second phase, configuring card");
++#include <linux/spi/spi.h>
++#include <linux/spi/mcp23s08.h>
 +
-+		setup_memory(dc);
++#include <asm/gpio.h>
 +
-+		dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
-+		dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
-+		dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl;
-+		DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d",
-+		   dc->port[PORT_MDM].toggle_ul,
-+		   dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl);
 +
-+		dump_table(dc);
++/* Registers are all 8 bits wide.
++ *
++ * The mcp23s17 has twice as many bits, and can be configured to work
++ * with either 16 bit registers or with two adjacent 8 bit banks.
++ *
++ * Also, there are I2C versions of both chips.
++ */
++#define MCP_IODIR	0x00		/* init/reset:  all ones */
++#define MCP_IPOL	0x01
++#define MCP_GPINTEN	0x02
++#define MCP_DEFVAL	0x03
++#define MCP_INTCON	0x04
++#define MCP_IOCON	0x05
++#	define IOCON_SEQOP	(1 << 5)
++#	define IOCON_HAEN	(1 << 3)
++#	define IOCON_ODR	(1 << 2)
++#	define IOCON_INTPOL	(1 << 1)
++#define MCP_GPPU	0x06
++#define MCP_INTF	0x07
++#define MCP_INTCAP	0x08
++#define MCP_GPIO	0x09
++#define MCP_OLAT	0x0a
++
++struct mcp23s08 {
++	struct spi_device	*spi;
++	u8			addr;
 +
-+		for (i = PORT_MDM; i < MAX_PORT; i++) {
-+			dc->port[i].fifo_ul =
-+			    kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL);
-+			memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
-+			memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
-+		}
++	/* lock protects the cached values */
++	struct mutex		lock;
++	u8			cache[11];
 +
-+		/* Enable control channel */
-+		dc->last_ier = dc->last_ier | CTRL_DL;
-+		writew(dc->last_ier, dc->reg_ier);
++	struct gpio_chip	chip;
 +
-+		dev_info(&dc->pdev->dev, "Initialization OK!\n");
-+		return 1;
-+	}
++	struct work_struct	work;
++};
 +
-+	if ((dc->config_table.version > 0)
-+	    && (dc->config_table.toggle.enabled != TOGGLE_VALID)) {
-+		u32 offset = 0;
-+		DBG1("First phase: pushing upload buffers, clearing download");
++static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
++{
++	u8	tx[2], rx[1];
++	int	status;
 +
-+		dev_info(&dc->pdev->dev, "Version of card: %d\n",
-+			 dc->config_table.version);
++	tx[0] = mcp->addr | 0x01;
++	tx[1] = reg;
++	status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
++	return (status < 0) ? status : rx[0];
++}
 +
-+		/* Here we should disable all I/O over F32. */
-+		setup_memory(dc);
++static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
++{
++	u8	tx[3];
 +
-+		/*
-+		 * We should send ALL channel pair tokens back along
-+		 * with reset token
-+		 */
++	tx[0] = mcp->addr;
++	tx[1] = reg;
++	tx[2] = val;
++	return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
++}
 +
-+		/* push upload modem buffers */
-+		write_mem32(dc->port[PORT_MDM].ul_addr[CH_A],
-+			(u32 *) &offset, 4);
-+		write_mem32(dc->port[PORT_MDM].ul_addr[CH_B],
-+			(u32 *) &offset, 4);
++static int
++mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u8 *vals, unsigned n)
++{
++	u8	tx[2];
 +
-+		writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr);
++	if ((n + reg) > sizeof mcp->cache)
++		return -EINVAL;
++	tx[0] = mcp->addr | 0x01;
++	tx[1] = reg;
++	return spi_write_then_read(mcp->spi, tx, sizeof tx, vals, n);
++}
 +
-+		DBG1("First phase done");
-+	}
++/*----------------------------------------------------------------------*/
 +
-+	return 1;
++static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
++{
++	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
++	int status;
++
++	mutex_lock(&mcp->lock);
++	mcp->cache[MCP_IODIR] |= (1 << offset);
++	status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
++	mutex_unlock(&mcp->lock);
++	return status;
 +}
 +
-+/* Enable uplink interrupts  */
-+static void enable_transmit_ul(enum port_type port, struct nozomi *dc)
++static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
 +{
-+	u16 mask[NOZOMI_MAX_PORTS] = \
-+			{MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL};
++	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
++	int status;
 +
-+	if (port < NOZOMI_MAX_PORTS) {
-+		dc->last_ier |= mask[port];
-+		writew(dc->last_ier, dc->reg_ier);
-+	} else {
-+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
++	mutex_lock(&mcp->lock);
++
++	/* REVISIT reading this clears any IRQ ... */
++	status = mcp23s08_read(mcp, MCP_GPIO);
++	if (status < 0)
++		status = 0;
++	else {
++		mcp->cache[MCP_GPIO] = status;
++		status = !!(status & (1 << offset));
 +	}
++	mutex_unlock(&mcp->lock);
++	return status;
 +}
 +
-+/* Disable uplink interrupts  */
-+static void disable_transmit_ul(enum port_type port, struct nozomi *dc)
++static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
 +{
-+	u16 mask[NOZOMI_MAX_PORTS] = \
-+			{~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL};
++	u8 olat = mcp->cache[MCP_OLAT];
 +
-+	if (port < NOZOMI_MAX_PORTS) {
-+		dc->last_ier &= mask[port];
-+		writew(dc->last_ier, dc->reg_ier);
-+	} else {
-+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-+	}
++	if (value)
++		olat |= mask;
++	else
++		olat &= ~mask;
++	mcp->cache[MCP_OLAT] = olat;
++	return mcp23s08_write(mcp, MCP_OLAT, olat);
 +}
 +
-+/* Enable downlink interrupts */
-+static void enable_transmit_dl(enum port_type port, struct nozomi *dc)
++static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
 +{
-+	u16 mask[NOZOMI_MAX_PORTS] = \
-+			{MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL};
++	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
++	u8 mask = 1 << offset;
 +
-+	if (port < NOZOMI_MAX_PORTS) {
-+		dc->last_ier |= mask[port];
-+		writew(dc->last_ier, dc->reg_ier);
-+	} else {
-+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-+	}
++	mutex_lock(&mcp->lock);
++	__mcp23s08_set(mcp, mask, value);
++	mutex_unlock(&mcp->lock);
 +}
 +
-+/* Disable downlink interrupts */
-+static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
++static int
++mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 +{
-+	u16 mask[NOZOMI_MAX_PORTS] = \
-+			{~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL};
++	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
++	u8 mask = 1 << offset;
++	int status;
 +
-+	if (port < NOZOMI_MAX_PORTS) {
-+		dc->last_ier &= mask[port];
-+		writew(dc->last_ier, dc->reg_ier);
-+	} else {
-+		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
++	mutex_lock(&mcp->lock);
++	status = __mcp23s08_set(mcp, mask, value);
++	if (status == 0) {
++		mcp->cache[MCP_IODIR] &= ~mask;
++		status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 +	}
++	mutex_unlock(&mcp->lock);
++	return status;
 +}
 +
++/*----------------------------------------------------------------------*/
++
++#ifdef CONFIG_DEBUG_FS
++
++#include <linux/seq_file.h>
++
 +/*
-+ * Return 1 - send buffer to card and ack.
-+ * Return 0 - don't ack, don't send buffer to card.
++ * This shows more info than the generic gpio dump code:
++ * pullups, deglitching, open drain drive.
 + */
-+static int send_data(enum port_type index, struct nozomi *dc)
++static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 +{
-+	u32 size = 0;
-+	struct port *port = &dc->port[index];
-+	u8 toggle = port->toggle_ul;
-+	void __iomem *addr = port->ul_addr[toggle];
-+	u32 ul_size = port->ul_size[toggle];
-+	struct tty_struct *tty = port->tty;
++	struct mcp23s08	*mcp;
++	char		bank;
++	unsigned	t;
++	unsigned	mask;
 +
-+	/* Get data from tty and place in buf for now */
-+	size = __kfifo_get(port->fifo_ul, dc->send_buf,
-+			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
++	mcp = container_of(chip, struct mcp23s08, chip);
 +
-+	if (size == 0) {
-+		DBG4("No more data to send, disable link:");
-+		return 0;
-+	}
++	/* NOTE: we only handle one bank for now ... */
++	bank = '0' + ((mcp->addr >> 1) & 0x3);
 +
-+	/* DUMP(buf, size); */
++	mutex_lock(&mcp->lock);
++	t = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
++	if (t < 0) {
++		seq_printf(s, " I/O ERROR %d\n", t);
++		goto done;
++	}
 +
-+	/* Write length + data */
-+	write_mem32(addr, (u32 *) &size, 4);
-+	write_mem32(addr + 4, (u32 *) dc->send_buf, size);
++	for (t = 0, mask = 1; t < 8; t++, mask <<= 1) {
++		const char	*label;
 +
-+	if (tty)
-+		tty_wakeup(tty);
++		label = gpiochip_is_requested(chip, t);
++		if (!label)
++			continue;
 +
-+	return 1;
++		seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
++			chip->base + t, bank, t, label,
++			(mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
++			(mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
++			(mcp->cache[MCP_GPPU] & mask) ? "  " : "up");
++		/* NOTE:  ignoring the irq-related registers */
++		seq_printf(s, "\n");
++	}
++done:
++	mutex_unlock(&mcp->lock);
 +}
 +
-+/* If all data has been read, return 1, else 0 */
-+static int receive_data(enum port_type index, struct nozomi *dc)
++#else
++#define mcp23s08_dbg_show	NULL
++#endif
++
++/*----------------------------------------------------------------------*/
++
++static int mcp23s08_probe(struct spi_device *spi)
 +{
-+	u8 buf[RECEIVE_BUF_MAX] = { 0 };
-+	int size;
-+	u32 offset = 4;
-+	struct port *port = &dc->port[index];
-+	void __iomem *addr = port->dl_addr[port->toggle_dl];
-+	struct tty_struct *tty = port->tty;
-+	int i;
++	struct mcp23s08			*mcp;
++	struct mcp23s08_platform_data	*pdata;
++	int				status;
++	int				do_update = 0;
 +
-+	if (unlikely(!tty)) {
-+		DBG1("tty not open for port: %d?", index);
-+		return 1;
-+	}
++	pdata = spi->dev.platform_data;
++	if (!pdata || pdata->slave > 3 || !pdata->base)
++		return -ENODEV;
 +
-+	read_mem32((u32 *) &size, addr, 4);
-+	/*  DBG1( "%d bytes port: %d", size, index); */
++	mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
++	if (!mcp)
++		return -ENOMEM;
 +
-+	if (test_bit(TTY_THROTTLED, &tty->flags)) {
-+		DBG1("No room in tty, don't read data, don't ack interrupt, "
-+			"disable interrupt");
++	mutex_init(&mcp->lock);
 +
-+		/* disable interrupt in downlink... */
-+		disable_transmit_dl(index, dc);
-+		return 0;
-+	}
++	mcp->spi = spi;
++	mcp->addr = 0x40 | (pdata->slave << 1);
 +
-+	if (unlikely(size == 0)) {
-+		dev_err(&dc->pdev->dev, "size == 0?\n");
-+		return 1;
-+	}
++	mcp->chip.label = "mcp23s08",
 +
-+	tty_buffer_request_room(tty, size);
++	mcp->chip.direction_input = mcp23s08_direction_input;
++	mcp->chip.get = mcp23s08_get;
++	mcp->chip.direction_output = mcp23s08_direction_output;
++	mcp->chip.set = mcp23s08_set;
++	mcp->chip.dbg_show = mcp23s08_dbg_show;
 +
-+	while (size > 0) {
-+		read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
++	mcp->chip.base = pdata->base;
++	mcp->chip.ngpio = 8;
++	mcp->chip.can_sleep = 1;
 +
-+		if (size == 1) {
-+			tty_insert_flip_char(tty, buf[0], TTY_NORMAL);
-+			size = 0;
-+		} else if (size < RECEIVE_BUF_MAX) {
-+			size -= tty_insert_flip_string(tty, (char *) buf, size);
-+		} else {
-+			i = tty_insert_flip_string(tty, \
-+						(char *) buf, RECEIVE_BUF_MAX);
-+			size -= i;
-+			offset += i;
-+		}
++	spi_set_drvdata(spi, mcp);
++
++	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work */
++	status = mcp23s08_read(mcp, MCP_IOCON);
++	if (status < 0)
++		goto fail;
++	if (status & IOCON_SEQOP) {
++		status &= ~IOCON_SEQOP;
++		status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
++		if (status < 0)
++			goto fail;
 +	}
 +
-+	set_bit(index, &dc->flip);
++	/* configure ~100K pullups */
++	status = mcp23s08_write(mcp, MCP_GPPU, pdata->pullups);
++	if (status < 0)
++		goto fail;
 +
-+	return 1;
-+}
++	status = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
++	if (status < 0)
++		goto fail;
 +
-+/* Debug for interrupts */
-+#ifdef DEBUG
-+static char *interrupt2str(u16 interrupt)
-+{
-+	static char buf[TMP_BUF_MAX];
-+	char *p = buf;
++	/* disable inverter on input */
++	if (mcp->cache[MCP_IPOL] != 0) {
++		mcp->cache[MCP_IPOL] = 0;
++		do_update = 1;
++	}
 +
-+	interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL;
-+	interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"MDM_DL2 ") : NULL;
++	/* disable irqs */
++	if (mcp->cache[MCP_GPINTEN] != 0) {
++		mcp->cache[MCP_GPINTEN] = 0;
++		do_update = 1;
++	}
 +
-+	interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"MDM_UL1 ") : NULL;
-+	interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"MDM_UL2 ") : NULL;
++	if (do_update) {
++		u8 tx[4];
 +
-+	interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"DIAG_DL1 ") : NULL;
-+	interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"DIAG_DL2 ") : NULL;
++		tx[0] = mcp->addr;
++		tx[1] = MCP_IPOL;
++		memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
++		status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
 +
-+	interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"DIAG_UL ") : NULL;
++		/* FIXME check status... */
++	}
 +
-+	interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"APP1_DL ") : NULL;
-+	interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"APP2_DL ") : NULL;
++	status = gpiochip_add(&mcp->chip);
 +
-+	interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"APP1_UL ") : NULL;
-+	interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"APP2_UL ") : NULL;
++	/* NOTE:  these chips have a relatively sane IRQ framework, with
++	 * per-signal masking and level/edge triggering.  It's not yet
++	 * handled here...
++	 */
 +
-+	interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"CTRL_DL ") : NULL;
-+	interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"CTRL_UL ") : NULL;
++	if (pdata->setup) {
++		status = pdata->setup(spi, mcp->chip.base,
++				mcp->chip.ngpio, pdata->context);
++		if (status < 0)
++			dev_dbg(&spi->dev, "setup --> %d\n", status);
++	}
 +
-+	interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-+					"RESET ") : NULL;
++	return 0;
 +
-+	return buf;
++fail:
++	kfree(mcp);
++	return status;
 +}
-+#endif
 +
-+/*
-+ * Receive flow control
-+ * Return 1 - If ok, else 0
-+ */
-+static int receive_flow_control(struct nozomi *dc)
++static int mcp23s08_remove(struct spi_device *spi)
 +{
-+	enum port_type port = PORT_MDM;
-+	struct ctrl_dl ctrl_dl;
-+	struct ctrl_dl old_ctrl;
-+	u16 enable_ier = 0;
-+
-+	read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2);
-+
-+	switch (ctrl_dl.port) {
-+	case CTRL_CMD:
-+		DBG1("The Base Band sends this value as a response to a "
-+			"request for IMSI detach sent over the control "
-+			"channel uplink (see section 7.6.1).");
-+		break;
-+	case CTRL_MDM:
-+		port = PORT_MDM;
-+		enable_ier = MDM_DL;
-+		break;
-+	case CTRL_DIAG:
-+		port = PORT_DIAG;
-+		enable_ier = DIAG_DL;
-+		break;
-+	case CTRL_APP1:
-+		port = PORT_APP1;
-+		enable_ier = APP1_DL;
-+		break;
-+	case CTRL_APP2:
-+		port = PORT_APP2;
-+		enable_ier = APP2_DL;
-+		break;
-+	default:
-+		dev_err(&dc->pdev->dev,
-+			"ERROR: flow control received for non-existing port\n");
-+		return 0;
-+	};
-+
-+	DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
-+	   *((u16 *)&ctrl_dl));
-+
-+	old_ctrl = dc->port[port].ctrl_dl;
-+	dc->port[port].ctrl_dl = ctrl_dl;
-+
-+	if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) {
-+		DBG1("Disable interrupt (0x%04X) on port: %d",
-+			enable_ier, port);
-+		disable_transmit_ul(port, dc);
-+
-+	} else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
-+
-+		if (__kfifo_len(dc->port[port].fifo_ul)) {
-+			DBG1("Enable interrupt (0x%04X) on port: %d",
-+				enable_ier, port);
-+			DBG1("Data in buffer [%d], enable transmit! ",
-+				__kfifo_len(dc->port[port].fifo_ul));
-+			enable_transmit_ul(port, dc);
-+		} else {
-+			DBG1("No data in buffer...");
++	struct mcp23s08			*mcp = spi_get_drvdata(spi);
++	struct mcp23s08_platform_data	*pdata = spi->dev.platform_data;
++	int				status = 0;
++
++	if (pdata->teardown) {
++		status = pdata->teardown(spi,
++				mcp->chip.base, mcp->chip.ngpio,
++				pdata->context);
++		if (status < 0) {
++			dev_err(&spi->dev, "%s --> %d\n", "teardown", status);
++			return status;
 +		}
 +	}
 +
-+	if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) {
-+		DBG1(" No change in mctrl");
-+		return 1;
-+	}
-+	/* Update statistics */
-+	if (old_ctrl.CTS != ctrl_dl.CTS)
-+		dc->port[port].tty_icount.cts++;
-+	if (old_ctrl.DSR != ctrl_dl.DSR)
-+		dc->port[port].tty_icount.dsr++;
-+	if (old_ctrl.RI != ctrl_dl.RI)
-+		dc->port[port].tty_icount.rng++;
-+	if (old_ctrl.DCD != ctrl_dl.DCD)
-+		dc->port[port].tty_icount.dcd++;
++	status = gpiochip_remove(&mcp->chip);
++	if (status == 0)
++		kfree(mcp);
++	else
++		dev_err(&spi->dev, "%s --> %d\n", "remove", status);
++	return status;
++}
 +
-+	wake_up_interruptible(&dc->port[port].tty_wait);
++static struct spi_driver mcp23s08_driver = {
++	.probe		= mcp23s08_probe,
++	.remove		= mcp23s08_remove,
++	.driver = {
++		.name	= "mcp23s08",
++		.owner	= THIS_MODULE,
++	},
++};
 +
-+	DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)",
-+	   port,
-+	   dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts,
-+	   dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr);
++/*----------------------------------------------------------------------*/
 +
-+	return 1;
++static int __init mcp23s08_init(void)
++{
++	return spi_register_driver(&mcp23s08_driver);
 +}
++module_init(mcp23s08_init);
 +
-+static enum ctrl_port_type port2ctrl(enum port_type port,
-+					const struct nozomi *dc)
++static void __exit mcp23s08_exit(void)
 +{
-+	switch (port) {
-+	case PORT_MDM:
-+		return CTRL_MDM;
-+	case PORT_DIAG:
-+		return CTRL_DIAG;
-+	case PORT_APP1:
-+		return CTRL_APP1;
-+	case PORT_APP2:
-+		return CTRL_APP2;
-+	default:
-+		dev_err(&dc->pdev->dev,
-+			"ERROR: send flow control " \
-+			"received for non-existing port\n");
-+	};
-+	return CTRL_ERROR;
++	spi_unregister_driver(&mcp23s08_driver);
 +}
++module_exit(mcp23s08_exit);
++
++MODULE_LICENSE("GPL");
 +
+diff --git a/drivers/gpio/pca9539.c b/drivers/gpio/pca9539.c
+new file mode 100644
+index 0000000..3e85c92
+--- /dev/null
++++ b/drivers/gpio/pca9539.c
+@@ -0,0 +1,271 @@
 +/*
-+ * Send flow control, can only update one channel at a time
-+ * Return 0 - If we have updated all flow control
-+ * Return 1 - If we need to update more flow control, ack current enable more
++ *  pca9539.c - 16-bit I/O port with interrupt and reset
++ *
++ *  Copyright (C) 2005 Ben Gardner <bgardner at wabtec.com>
++ *  Copyright (C) 2007 Marvell International Ltd.
++ *
++ *  Derived from drivers/i2c/chips/pca9539.c
++ *
++ *  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; version 2 of the License.
 + */
-+static int send_flow_control(struct nozomi *dc)
-+{
-+	u32 i, more_flow_control_to_be_updated = 0;
-+	u16 *ctrl;
 +
-+	for (i = PORT_MDM; i < MAX_PORT; i++) {
-+		if (dc->port[i].update_flow_control) {
-+			if (more_flow_control_to_be_updated) {
-+				/* We have more flow control to be updated */
-+				return 1;
-+			}
-+			dc->port[i].ctrl_ul.port = port2ctrl(i, dc);
-+			ctrl = (u16 *)&dc->port[i].ctrl_ul;
-+			write_mem32(dc->port[PORT_CTRL].ul_addr[0], \
-+				(u32 *) ctrl, 2);
-+			dc->port[i].update_flow_control = 0;
-+			more_flow_control_to_be_updated = 1;
-+		}
-+	}
-+	return 0;
-+}
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/i2c/pca9539.h>
 +
-+/*
-+ * Handle donlink data, ports that are handled are modem and diagnostics
-+ * Return 1 - ok
-+ * Return 0 - toggle fields are out of sync
++#include <asm/gpio.h>
++
++
++#define NR_PCA9539_GPIOS	16
++
++#define PCA9539_INPUT		0
++#define PCA9539_OUTPUT		2
++#define PCA9539_INVERT		4
++#define PCA9539_DIRECTION	6
++
++struct pca9539_chip {
++	unsigned gpio_start;
++	uint16_t reg_output;
++	uint16_t reg_direction;
++
++	struct i2c_client *client;
++	struct gpio_chip gpio_chip;
++};
++
++/* NOTE:  we can't currently rely on fault codes to come from SMBus
++ * calls, so we map all errors to EIO here and return zero otherwise.
 + */
-+static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle,
-+			u16 read_iir, u16 mask1, u16 mask2)
++static int pca9539_write_reg(struct pca9539_chip *chip, int reg, uint16_t val)
 +{
-+	if (*toggle == 0 && read_iir & mask1) {
-+		if (receive_data(port, dc)) {
-+			writew(mask1, dc->reg_fcr);
-+			*toggle = !(*toggle);
-+		}
++	if (i2c_smbus_write_word_data(chip->client, reg, val) < 0)
++		return -EIO;
++	else
++		return 0;
++}
 +
-+		if (read_iir & mask2) {
-+			if (receive_data(port, dc)) {
-+				writew(mask2, dc->reg_fcr);
-+				*toggle = !(*toggle);
-+			}
-+		}
-+	} else if (*toggle == 1 && read_iir & mask2) {
-+		if (receive_data(port, dc)) {
-+			writew(mask2, dc->reg_fcr);
-+			*toggle = !(*toggle);
-+		}
++static int pca9539_read_reg(struct pca9539_chip *chip, int reg, uint16_t *val)
++{
++	int ret;
 +
-+		if (read_iir & mask1) {
-+			if (receive_data(port, dc)) {
-+				writew(mask1, dc->reg_fcr);
-+				*toggle = !(*toggle);
-+			}
-+		}
-+	} else {
-+		dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n",
-+			*toggle);
-+		return 0;
++	ret = i2c_smbus_read_word_data(chip->client, reg);
++	if (ret < 0) {
++		dev_err(&chip->client->dev, "failed reading register\n");
++		return -EIO;
 +	}
-+	return 1;
++
++	*val = (uint16_t)ret;
++	return 0;
 +}
 +
-+/*
-+ * Handle uplink data, this is currently for the modem port
-+ * Return 1 - ok
-+ * Return 0 - toggle field are out of sync
-+ */
-+static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir)
++static int pca9539_gpio_direction_input(struct gpio_chip *gc, unsigned off)
 +{
-+	u8 *toggle = &(dc->port[port].toggle_ul);
-+
-+	if (*toggle == 0 && read_iir & MDM_UL1) {
-+		dc->last_ier &= ~MDM_UL;
-+		writew(dc->last_ier, dc->reg_ier);
-+		if (send_data(port, dc)) {
-+			writew(MDM_UL1, dc->reg_fcr);
-+			dc->last_ier = dc->last_ier | MDM_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+			*toggle = !*toggle;
-+		}
++	struct pca9539_chip *chip;
++	uint16_t reg_val;
++	int ret;
 +
-+		if (read_iir & MDM_UL2) {
-+			dc->last_ier &= ~MDM_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+			if (send_data(port, dc)) {
-+				writew(MDM_UL2, dc->reg_fcr);
-+				dc->last_ier = dc->last_ier | MDM_UL;
-+				writew(dc->last_ier, dc->reg_ier);
-+				*toggle = !*toggle;
-+			}
-+		}
++	chip = container_of(gc, struct pca9539_chip, gpio_chip);
 +
-+	} else if (*toggle == 1 && read_iir & MDM_UL2) {
-+		dc->last_ier &= ~MDM_UL;
-+		writew(dc->last_ier, dc->reg_ier);
-+		if (send_data(port, dc)) {
-+			writew(MDM_UL2, dc->reg_fcr);
-+			dc->last_ier = dc->last_ier | MDM_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+			*toggle = !*toggle;
-+		}
++	reg_val = chip->reg_direction | (1u << off);
++	ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
++	if (ret)
++		return ret;
 +
-+		if (read_iir & MDM_UL1) {
-+			dc->last_ier &= ~MDM_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+			if (send_data(port, dc)) {
-+				writew(MDM_UL1, dc->reg_fcr);
-+				dc->last_ier = dc->last_ier | MDM_UL;
-+				writew(dc->last_ier, dc->reg_ier);
-+				*toggle = !*toggle;
-+			}
-+		}
-+	} else {
-+		writew(read_iir & MDM_UL, dc->reg_fcr);
-+		dev_err(&dc->pdev->dev, "port out of sync!\n");
-+		return 0;
-+	}
-+	return 1;
++	chip->reg_direction = reg_val;
++	return 0;
 +}
 +
-+static irqreturn_t interrupt_handler(int irq, void *dev_id)
++static int pca9539_gpio_direction_output(struct gpio_chip *gc,
++		unsigned off, int val)
 +{
-+	struct nozomi *dc = dev_id;
-+	unsigned int a;
-+	u16 read_iir;
-+
-+	if (!dc)
-+		return IRQ_NONE;
-+
-+	spin_lock(&dc->spin_mutex);
-+	read_iir = readw(dc->reg_iir);
++	struct pca9539_chip *chip;
++	uint16_t reg_val;
++	int ret;
 +
-+	/* Card removed */
-+	if (read_iir == (u16)-1)
-+		goto none;
-+	/*
-+	 * Just handle interrupt enabled in IER
-+	 * (by masking with dc->last_ier)
-+	 */
-+	read_iir &= dc->last_ier;
++	chip = container_of(gc, struct pca9539_chip, gpio_chip);
 +
-+	if (read_iir == 0)
-+		goto none;
++	/* set output level */
++	if (val)
++		reg_val = chip->reg_output | (1u << off);
++	else
++		reg_val = chip->reg_output & ~(1u << off);
 +
++	ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
++	if (ret)
++		return ret;
 +
-+	DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir,
-+		dc->last_ier);
++	chip->reg_output = reg_val;
 +
-+	if (read_iir & RESET) {
-+		if (unlikely(!nozomi_read_config_table(dc))) {
-+			dc->last_ier = 0x0;
-+			writew(dc->last_ier, dc->reg_ier);
-+			dev_err(&dc->pdev->dev, "Could not read status from "
-+				"card, we should disable interface\n");
-+		} else {
-+			writew(RESET, dc->reg_fcr);
-+		}
-+		/* No more useful info if this was the reset interrupt. */
-+		goto exit_handler;
-+	}
-+	if (read_iir & CTRL_UL) {
-+		DBG1("CTRL_UL");
-+		dc->last_ier &= ~CTRL_UL;
-+		writew(dc->last_ier, dc->reg_ier);
-+		if (send_flow_control(dc)) {
-+			writew(CTRL_UL, dc->reg_fcr);
-+			dc->last_ier = dc->last_ier | CTRL_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+		}
-+	}
-+	if (read_iir & CTRL_DL) {
-+		receive_flow_control(dc);
-+		writew(CTRL_DL, dc->reg_fcr);
-+	}
-+	if (read_iir & MDM_DL) {
-+		if (!handle_data_dl(dc, PORT_MDM,
-+				&(dc->port[PORT_MDM].toggle_dl), read_iir,
-+				MDM_DL1, MDM_DL2)) {
-+			dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n");
-+			goto exit_handler;
-+		}
-+	}
-+	if (read_iir & MDM_UL) {
-+		if (!handle_data_ul(dc, PORT_MDM, read_iir)) {
-+			dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n");
-+			goto exit_handler;
-+		}
-+	}
-+	if (read_iir & DIAG_DL) {
-+		if (!handle_data_dl(dc, PORT_DIAG,
-+				&(dc->port[PORT_DIAG].toggle_dl), read_iir,
-+				DIAG_DL1, DIAG_DL2)) {
-+			dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n");
-+			goto exit_handler;
-+		}
-+	}
-+	if (read_iir & DIAG_UL) {
-+		dc->last_ier &= ~DIAG_UL;
-+		writew(dc->last_ier, dc->reg_ier);
-+		if (send_data(PORT_DIAG, dc)) {
-+			writew(DIAG_UL, dc->reg_fcr);
-+			dc->last_ier = dc->last_ier | DIAG_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+		}
-+	}
-+	if (read_iir & APP1_DL) {
-+		if (receive_data(PORT_APP1, dc))
-+			writew(APP1_DL, dc->reg_fcr);
-+	}
-+	if (read_iir & APP1_UL) {
-+		dc->last_ier &= ~APP1_UL;
-+		writew(dc->last_ier, dc->reg_ier);
-+		if (send_data(PORT_APP1, dc)) {
-+			writew(APP1_UL, dc->reg_fcr);
-+			dc->last_ier = dc->last_ier | APP1_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+		}
-+	}
-+	if (read_iir & APP2_DL) {
-+		if (receive_data(PORT_APP2, dc))
-+			writew(APP2_DL, dc->reg_fcr);
-+	}
-+	if (read_iir & APP2_UL) {
-+		dc->last_ier &= ~APP2_UL;
-+		writew(dc->last_ier, dc->reg_ier);
-+		if (send_data(PORT_APP2, dc)) {
-+			writew(APP2_UL, dc->reg_fcr);
-+			dc->last_ier = dc->last_ier | APP2_UL;
-+			writew(dc->last_ier, dc->reg_ier);
-+		}
-+	}
++	/* then direction */
++	reg_val = chip->reg_direction & ~(1u << off);
++	ret = pca9539_write_reg(chip, PCA9539_DIRECTION, reg_val);
++	if (ret)
++		return ret;
 +
-+exit_handler:
-+	spin_unlock(&dc->spin_mutex);
-+	for (a = 0; a < NOZOMI_MAX_PORTS; a++)
-+		if (test_and_clear_bit(a, &dc->flip))
-+			tty_flip_buffer_push(dc->port[a].tty);
-+	return IRQ_HANDLED;
-+none:
-+	spin_unlock(&dc->spin_mutex);
-+	return IRQ_NONE;
++	chip->reg_direction = reg_val;
++	return 0;
 +}
 +
-+static void nozomi_get_card_type(struct nozomi *dc)
++static int pca9539_gpio_get_value(struct gpio_chip *gc, unsigned off)
 +{
-+	int i;
-+	u32 size = 0;
++	struct pca9539_chip *chip;
++	uint16_t reg_val;
++	int ret;
 +
-+	for (i = 0; i < 6; i++)
-+		size += pci_resource_len(dc->pdev, i);
++	chip = container_of(gc, struct pca9539_chip, gpio_chip);
 +
-+	/* Assume card type F32_8 if no match */
-+	dc->card_type = size == 2048 ? F32_2 : F32_8;
++	ret = pca9539_read_reg(chip, PCA9539_INPUT, &reg_val);
++	if (ret < 0) {
++		/* NOTE:  diagnostic already emitted; that's all we should
++		 * do unless gpio_*_value_cansleep() calls become different
++		 * from their nonsleeping siblings (and report faults).
++		 */
++		return 0;
++	}
 +
-+	dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type);
++	return (reg_val & (1u << off)) ? 1 : 0;
 +}
 +
-+static void nozomi_setup_private_data(struct nozomi *dc)
++static void pca9539_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
 +{
-+	void __iomem *offset = dc->base_addr + dc->card_type / 2;
-+	unsigned int i;
-+
-+	dc->reg_fcr = (void __iomem *)(offset + R_FCR);
-+	dc->reg_iir = (void __iomem *)(offset + R_IIR);
-+	dc->reg_ier = (void __iomem *)(offset + R_IER);
-+	dc->last_ier = 0;
-+	dc->flip = 0;
++	struct pca9539_chip *chip;
++	uint16_t reg_val;
++	int ret;
 +
-+	dc->port[PORT_MDM].token_dl = MDM_DL;
-+	dc->port[PORT_DIAG].token_dl = DIAG_DL;
-+	dc->port[PORT_APP1].token_dl = APP1_DL;
-+	dc->port[PORT_APP2].token_dl = APP2_DL;
++	chip = container_of(gc, struct pca9539_chip, gpio_chip);
 +
-+	for (i = 0; i < MAX_PORT; i++)
-+		init_waitqueue_head(&dc->port[i].tty_wait);
-+}
++	if (val)
++		reg_val = chip->reg_output | (1u << off);
++	else
++		reg_val = chip->reg_output & ~(1u << off);
 +
-+static ssize_t card_type_show(struct device *dev, struct device_attribute *attr,
-+			  char *buf)
-+{
-+	struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
++	ret = pca9539_write_reg(chip, PCA9539_OUTPUT, reg_val);
++	if (ret)
++		return;
 +
-+	return sprintf(buf, "%d\n", dc->card_type);
++	chip->reg_output = reg_val;
 +}
-+static DEVICE_ATTR(card_type, 0444, card_type_show, NULL);
 +
-+static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr,
-+			  char *buf)
++static int pca9539_init_gpio(struct pca9539_chip *chip)
 +{
-+	struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
++	struct gpio_chip *gc;
 +
-+	return sprintf(buf, "%u\n", dc->open_ttys);
-+}
-+static DEVICE_ATTR(open_ttys, 0444, open_ttys_show, NULL);
++	gc = &chip->gpio_chip;
 +
-+static void make_sysfs_files(struct nozomi *dc)
-+{
-+	if (device_create_file(&dc->pdev->dev, &dev_attr_card_type))
-+		dev_err(&dc->pdev->dev,
-+			"Could not create sysfs file for card_type\n");
-+	if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys))
-+		dev_err(&dc->pdev->dev,
-+			"Could not create sysfs file for open_ttys\n");
-+}
++	gc->direction_input  = pca9539_gpio_direction_input;
++	gc->direction_output = pca9539_gpio_direction_output;
++	gc->get = pca9539_gpio_get_value;
++	gc->set = pca9539_gpio_set_value;
 +
-+static void remove_sysfs_files(struct nozomi *dc)
-+{
-+	device_remove_file(&dc->pdev->dev, &dev_attr_card_type);
-+	device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys);
++	gc->base = chip->gpio_start;
++	gc->ngpio = NR_PCA9539_GPIOS;
++	gc->label = "pca9539";
++
++	return gpiochip_add(gc);
 +}
 +
-+/* Allocate memory for one device */
-+static int __devinit nozomi_card_init(struct pci_dev *pdev,
-+				      const struct pci_device_id *ent)
++static int __devinit pca9539_probe(struct i2c_client *client)
 +{
-+	resource_size_t start;
++	struct pca9539_platform_data *pdata;
++	struct pca9539_chip *chip;
 +	int ret;
-+	struct nozomi *dc = NULL;
-+	int ndev_idx;
-+	int i;
-+
-+	dev_dbg(&pdev->dev, "Init, new card found\n");
-+
-+	for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
-+		if (!ndevs[ndev_idx])
-+			break;
 +
-+	if (ndev_idx >= ARRAY_SIZE(ndevs)) {
-+		dev_err(&pdev->dev, "no free tty range for this card left\n");
-+		ret = -EIO;
-+		goto err;
-+	}
++	pdata = client->dev.platform_data;
++	if (pdata == NULL)
++		return -ENODEV;
 +
-+	dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
-+	if (unlikely(!dc)) {
-+		dev_err(&pdev->dev, "Could not allocate memory\n");
-+		ret = -ENOMEM;
-+		goto err_free;
-+	}
++	chip = kzalloc(sizeof(struct pca9539_chip), GFP_KERNEL);
++	if (chip == NULL)
++		return -ENOMEM;
 +
-+	dc->pdev = pdev;
++	chip->client = client;
 +
-+	/* Find out what card type it is */
-+	nozomi_get_card_type(dc);
++	chip->gpio_start = pdata->gpio_base;
 +
-+	ret = pci_enable_device(dc->pdev);
-+	if (ret) {
-+		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
-+		goto err_free;
-+	}
++	/* initialize cached registers from their original values.
++	 * we can't share this chip with another i2c master.
++	 */
++	ret = pca9539_read_reg(chip, PCA9539_OUTPUT, &chip->reg_output);
++	if (ret)
++		goto out_failed;
 +
-+	start = pci_resource_start(dc->pdev, 0);
-+	if (start == 0) {
-+		dev_err(&pdev->dev, "No I/O address for card detected\n");
-+		ret = -ENODEV;
-+		goto err_disable_device;
-+	}
++	ret = pca9539_read_reg(chip, PCA9539_DIRECTION, &chip->reg_direction);
++	if (ret)
++		goto out_failed;
 +
-+	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
-+	if (ret) {
-+		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
-+			(int) /* nozomi_private.io_addr */ 0);
-+		goto err_disable_device;
-+	}
++	/* set platform specific polarity inversion */
++	ret = pca9539_write_reg(chip, PCA9539_INVERT, pdata->invert);
++	if (ret)
++		goto out_failed;
 +
-+	dc->base_addr = ioremap(start, dc->card_type);
-+	if (!dc->base_addr) {
-+		dev_err(&pdev->dev, "Unable to map card MMIO\n");
-+		ret = -ENODEV;
-+		goto err_rel_regs;
-+	}
++	ret = pca9539_init_gpio(chip);
++	if (ret)
++		goto out_failed;
 +
-+	dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL);
-+	if (!dc->send_buf) {
-+		dev_err(&pdev->dev, "Could not allocate send buffer?\n");
-+		ret = -ENOMEM;
-+		goto err_free_sbuf;
++	if (pdata->setup) {
++		ret = pdata->setup(client, chip->gpio_chip.base,
++				chip->gpio_chip.ngpio, pdata->context);
++		if (ret < 0)
++			dev_warn(&client->dev, "setup failed, %d\n", ret);
 +	}
 +
-+	spin_lock_init(&dc->spin_mutex);
++	i2c_set_clientdata(client, chip);
++	return 0;
 +
-+	nozomi_setup_private_data(dc);
++out_failed:
++	kfree(chip);
++	return ret;
++}
 +
-+	/* Disable all interrupts */
-+	dc->last_ier = 0;
-+	writew(dc->last_ier, dc->reg_ier);
++static int pca9539_remove(struct i2c_client *client)
++{
++	struct pca9539_platform_data *pdata = client->dev.platform_data;
++	struct pca9539_chip *chip = i2c_get_clientdata(client);
++	int ret = 0;
 +
-+	ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
-+			NOZOMI_NAME, dc);
-+	if (unlikely(ret)) {
-+		dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
-+		goto err_free_sbuf;
++	if (pdata->teardown) {
++		ret = pdata->teardown(client, chip->gpio_chip.base,
++				chip->gpio_chip.ngpio, pdata->context);
++		if (ret < 0) {
++			dev_err(&client->dev, "%s failed, %d\n",
++					"teardown", ret);
++			return ret;
++		}
 +	}
 +
-+	DBG1("base_addr: %p", dc->base_addr);
++	ret = gpiochip_remove(&chip->gpio_chip);
++	if (ret) {
++		dev_err(&client->dev, "%s failed, %d\n",
++				"gpiochip_remove()", ret);
++		return ret;
++	}
 +
-+	make_sysfs_files(dc);
++	kfree(chip);
++	return 0;
++}
 +
-+	dc->index_start = ndev_idx * MAX_PORT;
-+	ndevs[ndev_idx] = dc;
++static struct i2c_driver pca9539_driver = {
++	.driver = {
++		.name	= "pca9539",
++	},
++	.probe		= pca9539_probe,
++	.remove		= pca9539_remove,
++};
 +
-+	for (i = 0; i < MAX_PORT; i++) {
-+		mutex_init(&dc->port[i].tty_sem);
-+		dc->port[i].tty_open_count = 0;
-+		dc->port[i].tty = NULL;
-+		tty_register_device(ntty_driver, dc->index_start + i,
-+							&pdev->dev);
-+	}
++static int __init pca9539_init(void)
++{
++	return i2c_add_driver(&pca9539_driver);
++}
++module_init(pca9539_init);
 +
-+	/* Enable  RESET interrupt. */
-+	dc->last_ier = RESET;
-+	writew(dc->last_ier, dc->reg_ier);
++static void __exit pca9539_exit(void)
++{
++	i2c_del_driver(&pca9539_driver);
++}
++module_exit(pca9539_exit);
 +
-+	pci_set_drvdata(pdev, dc);
++MODULE_AUTHOR("eric miao <eric.miao at marvell.com>");
++MODULE_DESCRIPTION("GPIO expander driver for PCA9539");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/gpio/pcf857x.c b/drivers/gpio/pcf857x.c
+new file mode 100644
+index 0000000..c6b3b53
+--- /dev/null
++++ b/drivers/gpio/pcf857x.c
+@@ -0,0 +1,330 @@
++/*
++ * pcf857x - driver for pcf857x, pca857x, and pca967x I2C GPIO expanders
++ *
++ * Copyright (C) 2007 David Brownell
++ *
++ * 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.
++ */
 +
-+	return 0;
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <linux/i2c/pcf857x.h>
 +
-+err_free_sbuf:
-+	kfree(dc->send_buf);
-+	iounmap(dc->base_addr);
-+err_rel_regs:
-+	pci_release_regions(pdev);
-+err_disable_device:
-+	pci_disable_device(pdev);
-+err_free:
-+	kfree(dc);
-+err:
-+	return ret;
-+}
++#include <asm/gpio.h>
 +
-+static void __devexit tty_exit(struct nozomi *dc)
-+{
-+	unsigned int i;
 +
-+	DBG1(" ");
++/*
++ * The pcf857x, pca857x, and pca967x chips only expose one read and one
++ * write register.  Writing a "one" bit (to match the reset state) lets
++ * that pin be used as an input; it's not an open-drain model, but acts
++ * a bit like one.  This is described as "quasi-bidirectional"; read the
++ * chip documentation for details.
++ *
++ * Many other I2C GPIO expander chips (like the pca953x models) have
++ * more complex register models and more conventional circuitry using
++ * push/pull drivers.  They often use the same 0x20..0x27 addresses as
++ * pcf857x parts, making the "legacy" I2C driver model problematic.
++ */
++struct pcf857x {
++	struct gpio_chip	chip;
++	struct i2c_client	*client;
++	unsigned		out;		/* software latch */
++};
 +
-+	flush_scheduled_work();
++/*-------------------------------------------------------------------------*/
 +
-+	for (i = 0; i < MAX_PORT; ++i)
-+		if (dc->port[i].tty && \
-+				list_empty(&dc->port[i].tty->hangup_work.entry))
-+			tty_hangup(dc->port[i].tty);
++/* Talk to 8-bit I/O expander */
 +
-+	while (dc->open_ttys)
-+		msleep(1);
++static int pcf857x_input8(struct gpio_chip *chip, unsigned offset)
++{
++	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
 +
-+	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-+		tty_unregister_device(ntty_driver, i);
++	gpio->out |= (1 << offset);
++	return i2c_smbus_write_byte(gpio->client, gpio->out);
 +}
 +
-+/* Deallocate memory for one device */
-+static void __devexit nozomi_card_exit(struct pci_dev *pdev)
++static int pcf857x_get8(struct gpio_chip *chip, unsigned offset)
 +{
-+	int i;
-+	struct ctrl_ul ctrl;
-+	struct nozomi *dc = pci_get_drvdata(pdev);
-+
-+	/* Disable all interrupts */
-+	dc->last_ier = 0;
-+	writew(dc->last_ier, dc->reg_ier);
++	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
++	s32		value;
 +
-+	tty_exit(dc);
++	value = i2c_smbus_read_byte(gpio->client);
++	return (value < 0) ? 0 : (value & (1 << offset));
++}
 +
-+	/* Send 0x0001, command card to resend the reset token.  */
-+	/* This is to get the reset when the module is reloaded. */
-+	ctrl.port = 0x00;
-+	ctrl.reserved = 0;
-+	ctrl.RTS = 0;
-+	ctrl.DTR = 1;
-+	DBG1("sending flow control 0x%04X", *((u16 *)&ctrl));
++static int pcf857x_output8(struct gpio_chip *chip, unsigned offset, int value)
++{
++	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
++	unsigned	bit = 1 << offset;
 +
-+	/* Setup dc->reg addresses to we can use defines here */
-+	write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2);
-+	writew(CTRL_UL, dc->reg_fcr);	/* push the token to the card. */
++	if (value)
++		gpio->out |= bit;
++	else
++		gpio->out &= ~bit;
++	return i2c_smbus_write_byte(gpio->client, gpio->out);
++}
 +
-+	remove_sysfs_files(dc);
++static void pcf857x_set8(struct gpio_chip *chip, unsigned offset, int value)
++{
++	pcf857x_output8(chip, offset, value);
++}
 +
-+	free_irq(pdev->irq, dc);
++/*-------------------------------------------------------------------------*/
 +
-+	for (i = 0; i < MAX_PORT; i++)
-+		if (dc->port[i].fifo_ul)
-+			kfifo_free(dc->port[i].fifo_ul);
++/* Talk to 16-bit I/O expander */
 +
-+	kfree(dc->send_buf);
++static int i2c_write_le16(struct i2c_client *client, u16 word)
++{
++	u8 buf[2] = { word & 0xff, word >> 8, };
++	int status;
 +
-+	iounmap(dc->base_addr);
++	status = i2c_master_send(client, buf, 2);
++	return (status < 0) ? status : 0;
++}
 +
-+	pci_release_regions(pdev);
++static int i2c_read_le16(struct i2c_client *client)
++{
++	u8 buf[2];
++	int status;
 +
-+	pci_disable_device(pdev);
++	status = i2c_master_recv(client, buf, 2);
++	if (status < 0)
++		return status;
++	return (buf[1] << 8) | buf[0];
++}
 +
-+	ndevs[dc->index_start / MAX_PORT] = NULL;
++static int pcf857x_input16(struct gpio_chip *chip, unsigned offset)
++{
++	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
 +
-+	kfree(dc);
++	gpio->out |= (1 << offset);
++	return i2c_write_le16(gpio->client, gpio->out);
 +}
 +
-+static void set_rts(const struct tty_struct *tty, int rts)
++static int pcf857x_get16(struct gpio_chip *chip, unsigned offset)
 +{
-+	struct port *port = get_port_by_tty(tty);
++	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
++	int		value;
 +
-+	port->ctrl_ul.RTS = rts;
-+	port->update_flow_control = 1;
-+	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
++	value = i2c_read_le16(gpio->client);
++	return (value < 0) ? 0 : (value & (1 << offset));
 +}
 +
-+static void set_dtr(const struct tty_struct *tty, int dtr)
++static int pcf857x_output16(struct gpio_chip *chip, unsigned offset, int value)
 +{
-+	struct port *port = get_port_by_tty(tty);
++	struct pcf857x	*gpio = container_of(chip, struct pcf857x, chip);
++	unsigned	bit = 1 << offset;
 +
-+	DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr);
++	if (value)
++		gpio->out |= bit;
++	else
++		gpio->out &= ~bit;
++	return i2c_write_le16(gpio->client, gpio->out);
++}
 +
-+	port->ctrl_ul.DTR = dtr;
-+	port->update_flow_control = 1;
-+	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
++static void pcf857x_set16(struct gpio_chip *chip, unsigned offset, int value)
++{
++	pcf857x_output16(chip, offset, value);
 +}
 +
-+/*
-+ * ----------------------------------------------------------------------------
-+ * TTY code
-+ * ----------------------------------------------------------------------------
-+ */
++/*-------------------------------------------------------------------------*/
 +
-+/* Called when the userspace process opens the tty, /dev/noz*.  */
-+static int ntty_open(struct tty_struct *tty, struct file *file)
++static int pcf857x_probe(struct i2c_client *client)
 +{
-+	struct port *port = get_port_by_tty(tty);
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+	unsigned long flags;
++	struct pcf857x_platform_data	*pdata;
++	struct pcf857x			*gpio;
++	int				status;
 +
-+	if (!port || !dc)
++	pdata = client->dev.platform_data;
++	if (!pdata)
 +		return -ENODEV;
 +
-+	if (mutex_lock_interruptible(&port->tty_sem))
-+		return -ERESTARTSYS;
++	/* Allocate, initialize, and register this gpio_chip. */
++	gpio = kzalloc(sizeof *gpio, GFP_KERNEL);
++	if (!gpio)
++		return -ENOMEM;
 +
-+	port->tty_open_count++;
-+	dc->open_ttys++;
++	gpio->chip.base = pdata->gpio_base;
++	gpio->chip.can_sleep = 1;
 +
-+	/* Enable interrupt downlink for channel */
-+	if (port->tty_open_count == 1) {
-+		tty->low_latency = 1;
-+		tty->driver_data = port;
-+		port->tty = tty;
-+		DBG1("open: %d", port->token_dl);
-+		spin_lock_irqsave(&dc->spin_mutex, flags);
-+		dc->last_ier = dc->last_ier | port->token_dl;
-+		writew(dc->last_ier, dc->reg_ier);
-+		spin_unlock_irqrestore(&dc->spin_mutex, flags);
-+	}
++	/* NOTE:  the OnSemi jlc1562b is also largely compatible with
++	 * these parts, notably for output.  It has a low-resolution
++	 * DAC instead of pin change IRQs; and its inputs can be the
++	 * result of comparators.
++	 */
 +
-+	mutex_unlock(&port->tty_sem);
++	/* 8574 addresses are 0x20..0x27; 8574a uses 0x38..0x3f;
++	 * 9670, 9672, 9764, and 9764a use quite a variety.
++	 *
++	 * NOTE: we don't distinguish here between *4 and *4a parts.
++	 */
++	if (strcmp(client->name, "pcf8574") == 0
++			|| strcmp(client->name, "pca8574") == 0
++			|| strcmp(client->name, "pca9670") == 0
++			|| strcmp(client->name, "pca9672") == 0
++			|| strcmp(client->name, "pca9674") == 0
++			) {
++		gpio->chip.ngpio = 8;
++		gpio->chip.direction_input = pcf857x_input8;
++		gpio->chip.get = pcf857x_get8;
++		gpio->chip.direction_output = pcf857x_output8;
++		gpio->chip.set = pcf857x_set8;
++
++		if (!i2c_check_functionality(client->adapter,
++				I2C_FUNC_SMBUS_BYTE))
++			status = -EIO;
 +
-+	return 0;
-+}
++		/* fail if there's no chip present */
++		else
++			status = i2c_smbus_read_byte(client);
 +
-+/* Called when the userspace process close the tty, /dev/noz*. */
-+static void ntty_close(struct tty_struct *tty, struct file *file)
-+{
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+	struct port *port = tty->driver_data;
-+	unsigned long flags;
++	/* '75/'75c addresses are 0x20..0x27, just like the '74;
++	 * the '75c doesn't have a current source pulling high.
++	 * 9671, 9673, and 9765 use quite a variety of addresses.
++	 *
++	 * NOTE: we don't distinguish here between '75 and '75c parts.
++	 */
++	} else if (strcmp(client->name, "pcf8575") == 0
++			|| strcmp(client->name, "pca8575") == 0
++			|| strcmp(client->name, "pca9671") == 0
++			|| strcmp(client->name, "pca9673") == 0
++			|| strcmp(client->name, "pca9675") == 0
++			) {
++		gpio->chip.ngpio = 16;
++		gpio->chip.direction_input = pcf857x_input16;
++		gpio->chip.get = pcf857x_get16;
++		gpio->chip.direction_output = pcf857x_output16;
++		gpio->chip.set = pcf857x_set16;
 +
-+	if (!dc || !port)
-+		return;
++		if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
++			status = -EIO;
 +
-+	if (mutex_lock_interruptible(&port->tty_sem))
-+		return;
++		/* fail if there's no chip present */
++		else
++			status = i2c_read_le16(client);
 +
-+	if (!port->tty_open_count)
-+		goto exit;
++	} else
++		status = -ENODEV;
 +
-+	dc->open_ttys--;
-+	port->tty_open_count--;
++	if (status < 0)
++		goto fail;
 +
-+	if (port->tty_open_count == 0) {
-+		DBG1("close: %d", port->token_dl);
-+		spin_lock_irqsave(&dc->spin_mutex, flags);
-+		dc->last_ier &= ~(port->token_dl);
-+		writew(dc->last_ier, dc->reg_ier);
-+		spin_unlock_irqrestore(&dc->spin_mutex, flags);
++	gpio->chip.label = client->name;
++
++	gpio->client = client;
++	i2c_set_clientdata(client, gpio);
++
++	/* NOTE:  these chips have strange "quasi-bidirectional" I/O pins.
++	 * We can't actually know whether a pin is configured (a) as output
++	 * and driving the signal low, or (b) as input and reporting a low
++	 * value ... without knowing the last value written since the chip
++	 * came out of reset (if any).  We can't read the latched output.
++	 *
++	 * In short, the only reliable solution for setting up pin direction
++	 * is to do it explicitly.  The setup() method can do that, but it
++	 * may cause transient glitching since it can't know the last value
++	 * written (some pins may need to be driven low).
++	 *
++	 * Using pdata->n_latch avoids that trouble.  When left initialized
++	 * to zero, our software copy of the "latch" then matches the chip's
++	 * all-ones reset state.  Otherwise it flags pins to be driven low.
++	 */
++	gpio->out = ~pdata->n_latch;
++
++	status = gpiochip_add(&gpio->chip);
++	if (status < 0)
++		goto fail;
++
++	/* NOTE: these chips can issue "some pin-changed" IRQs, which we
++	 * don't yet even try to use.  Among other issues, the relevant
++	 * genirq state isn't available to modular drivers; and most irq
++	 * methods can't be called from sleeping contexts.
++	 */
++
++	dev_info(&client->dev, "gpios %d..%d on a %s%s\n",
++			gpio->chip.base,
++			gpio->chip.base + gpio->chip.ngpio - 1,
++			client->name,
++			client->irq ? " (irq ignored)" : "");
++
++	/* Let platform code set up the GPIOs and their users.
++	 * Now is the first time anyone could use them.
++	 */
++	if (pdata->setup) {
++		status = pdata->setup(client,
++				gpio->chip.base, gpio->chip.ngpio,
++				pdata->context);
++		if (status < 0)
++			dev_warn(&client->dev, "setup --> %d\n", status);
 +	}
 +
-+exit:
-+	mutex_unlock(&port->tty_sem);
++	return 0;
++
++fail:
++	dev_dbg(&client->dev, "probe error %d for '%s'\n",
++			status, client->name);
++	kfree(gpio);
++	return status;
++}
++
++static int pcf857x_remove(struct i2c_client *client)
++{
++	struct pcf857x_platform_data	*pdata = client->dev.platform_data;
++	struct pcf857x			*gpio = i2c_get_clientdata(client);
++	int				status = 0;
++
++	if (pdata->teardown) {
++		status = pdata->teardown(client,
++				gpio->chip.base, gpio->chip.ngpio,
++				pdata->context);
++		if (status < 0) {
++			dev_err(&client->dev, "%s --> %d\n",
++					"teardown", status);
++			return status;
++		}
++	}
++
++	status = gpiochip_remove(&gpio->chip);
++	if (status == 0)
++		kfree(gpio);
++	else
++		dev_err(&client->dev, "%s --> %d\n", "remove", status);
++	return status;
++}
++
++static struct i2c_driver pcf857x_driver = {
++	.driver = {
++		.name	= "pcf857x",
++		.owner	= THIS_MODULE,
++	},
++	.probe	= pcf857x_probe,
++	.remove	= pcf857x_remove,
++};
++
++static int __init pcf857x_init(void)
++{
++	return i2c_add_driver(&pcf857x_driver);
++}
++module_init(pcf857x_init);
++
++static void __exit pcf857x_exit(void)
++{
++	i2c_del_driver(&pcf857x_driver);
 +}
++module_exit(pcf857x_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("David Brownell");
+diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
+index 1ac5103..275dc52 100644
+--- a/drivers/hid/Makefile
++++ b/drivers/hid/Makefile
+@@ -1,7 +1,7 @@
+ #
+ # Makefile for the HID driver
+ #
+-hid-objs			:= hid-core.o hid-input.o
++hid-objs			:= hid-core.o hid-input.o hid-input-quirks.o
+ 
+ obj-$(CONFIG_HID)		+= hid.o
+ 
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index 2884b03..d73a768 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -26,6 +26,7 @@
+ #include <linux/input.h>
+ #include <linux/wait.h>
+ #include <linux/vmalloc.h>
++#include <linux/sched.h>
+ 
+ #include <linux/hid.h>
+ #include <linux/hiddev.h>
+@@ -758,7 +759,9 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
+ {
+ 	u64 x;
+ 
+-	WARN_ON(n > 32);
++	if (n > 32)
++		printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n",
++				n, current->comm);
+ 
+ 	report += offset >> 3;  /* adjust byte index */
+ 	offset &= 7;            /* now only need bit offset into one byte */
+@@ -780,8 +783,13 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
+ 	__le64 x;
+ 	u64 m = (1ULL << n) - 1;
+ 
+-	WARN_ON(n > 32);
++	if (n > 32)
++		printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n",
++				n, current->comm);
+ 
++	if (value > m)
++		printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n",
++				value, current->comm);
+ 	WARN_ON(value > m);
+ 	value &= m;
+ 
+diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
+new file mode 100644
+index 0000000..a870ba5
+--- /dev/null
++++ b/drivers/hid/hid-input-quirks.c
+@@ -0,0 +1,423 @@
++/*
++ *  HID-input usage mapping quirks
++ *
++ *  This is used to handle HID-input mappings for devices violating
++ *  HUT 1.12 specification.
++ *
++ * Copyright (c) 2007-2008 Jiri Kosina
++ */
 +
 +/*
-+ * called when the userspace process writes to the tty (/dev/noz*).
-+ * Data is inserted into a fifo, which is then read and transfered to the modem.
++ * 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
 + */
-+static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
-+		      int count)
-+{
-+	int rval = -EINVAL;
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+	struct port *port = tty->driver_data;
-+	unsigned long flags;
 +
-+	/* DBG1( "WRITEx: %d, index = %d", count, index); */
++#include <linux/input.h>
++#include <linux/hid.h>
 +
-+	if (!dc || !port)
-+		return -ENODEV;
++#define map_abs(c)      do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
++#define map_rel(c)      do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
++#define map_key(c)      do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
++#define map_led(c)      do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
 +
-+	if (unlikely(!mutex_trylock(&port->tty_sem))) {
-+		/*
-+		 * must test lock as tty layer wraps calls
-+		 * to this function with BKL
-+		 */
-+		dev_err(&dc->pdev->dev, "Would have deadlocked - "
-+			"return EAGAIN\n");
-+		return -EAGAIN;
-+	}
++#define map_abs_clear(c)        do { map_abs(c); clear_bit(c, *bit); } while (0)
++#define map_key_clear(c)        do { map_key(c); clear_bit(c, *bit); } while (0)
++
++static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
++{
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++		return 0;
 +
-+	if (unlikely(!port->tty_open_count)) {
-+		DBG1(" ");
-+		goto exit;
++	switch (usage->hid & HID_USAGE) {
++		case 0x03a: map_key_clear(KEY_SOUND);		break;
++		case 0x03b: map_key_clear(KEY_CAMERA);		break;
++		case 0x03c: map_key_clear(KEY_DOCUMENTS);	break;
++		default:
++			return 0;
 +	}
++	return 1;
++}
 +
-+	rval = __kfifo_put(port->fifo_ul, (unsigned char *)buffer, count);
++static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
++{
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++		return 0;
 +
-+	/* notify card */
-+	if (unlikely(dc == NULL)) {
-+		DBG1("No device context?");
-+		goto exit;
++	switch (usage->hid & HID_USAGE) {
++		case 0x301: map_key_clear(KEY_PROG1);		break;
++		case 0x302: map_key_clear(KEY_PROG2);		break;
++		case 0x303: map_key_clear(KEY_PROG3);		break;
++		default:
++			return 0;
 +	}
++	return 1;
++}
 +
-+	spin_lock_irqsave(&dc->spin_mutex, flags);
-+	/* CTS is only valid on the modem channel */
-+	if (port == &(dc->port[PORT_MDM])) {
-+		if (port->ctrl_dl.CTS) {
-+			DBG4("Enable interrupt");
-+			enable_transmit_ul(tty->index % MAX_PORT, dc);
-+		} else {
-+			dev_err(&dc->pdev->dev,
-+				"CTS not active on modem port?\n");
-+		}
-+	} else {
-+		enable_transmit_ul(tty->index % MAX_PORT, dc);
-+	}
-+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
++static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
++{
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
++		return 0;
 +
-+exit:
-+	mutex_unlock(&port->tty_sem);
-+	return rval;
++	set_bit(EV_REP, input->evbit);
++	switch(usage->hid & HID_USAGE) {
++		/* Reported on Logitech Ultra X Media Remote */
++		case 0x004: map_key_clear(KEY_AGAIN);		break;
++		case 0x00d: map_key_clear(KEY_HOME);		break;
++		case 0x024: map_key_clear(KEY_SHUFFLE);		break;
++		case 0x025: map_key_clear(KEY_TV);		break;
++		case 0x026: map_key_clear(KEY_MENU);		break;
++		case 0x031: map_key_clear(KEY_AUDIO);		break;
++		case 0x032: map_key_clear(KEY_TEXT);		break;
++		case 0x033: map_key_clear(KEY_LAST);		break;
++		case 0x047: map_key_clear(KEY_MP3);		break;
++		case 0x048: map_key_clear(KEY_DVD);		break;
++		case 0x049: map_key_clear(KEY_MEDIA);		break;
++		case 0x04a: map_key_clear(KEY_VIDEO);		break;
++		case 0x04b: map_key_clear(KEY_ANGLE);		break;
++		case 0x04c: map_key_clear(KEY_LANGUAGE);	break;
++		case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
++		case 0x051: map_key_clear(KEY_RED);		break;
++		case 0x052: map_key_clear(KEY_CLOSE);		break;
++
++		default:
++			return 0;
++	}
++	return 1;
 +}
 +
-+/*
-+ * Calculate how much is left in device
-+ * This method is called by the upper tty layer.
-+ *   #according to sources N_TTY.c it expects a value >= 0 and
-+ *    does not check for negative values.
-+ */
-+static int ntty_write_room(struct tty_struct *tty)
++static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
 +{
-+	struct port *port = tty->driver_data;
-+	int room = 0;
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+
-+	if (!dc || !port)
-+		return 0;
-+	if (!mutex_trylock(&port->tty_sem))
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
 +		return 0;
 +
-+	if (!port->tty_open_count)
-+		goto exit;
++	set_bit(EV_REP, input->evbit);
++	switch (usage->hid & HID_USAGE) {
++		case 0xff01: map_key_clear(BTN_1);		break;
++		case 0xff02: map_key_clear(BTN_2);		break;
++		case 0xff03: map_key_clear(BTN_3);		break;
++		case 0xff04: map_key_clear(BTN_4);		break;
++		case 0xff05: map_key_clear(BTN_5);		break;
++		case 0xff06: map_key_clear(BTN_6);		break;
++		case 0xff07: map_key_clear(BTN_7);		break;
++		case 0xff08: map_key_clear(BTN_8);		break;
++		case 0xff09: map_key_clear(BTN_9);		break;
++		case 0xff0a: map_key_clear(BTN_A);		break;
++		case 0xff0b: map_key_clear(BTN_B);		break;
++		default:
++			return 0;
++	}
++	return 1;
++}
 +
-+	room = port->fifo_ul->size - __kfifo_len(port->fifo_ul);
++static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
++{
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
++		return 0;
 +
-+exit:
-+	mutex_unlock(&port->tty_sem);
-+	return room;
++	switch(usage->hid & HID_USAGE) {
++		case 0xfd06: map_key_clear(KEY_CHAT);		break;
++		case 0xfd07: map_key_clear(KEY_PHONE);		break;
++		case 0xff05:
++			set_bit(EV_REP, input->evbit);
++			map_key_clear(KEY_F13);
++			set_bit(KEY_F14, input->keybit);
++			set_bit(KEY_F15, input->keybit);
++			set_bit(KEY_F16, input->keybit);
++			set_bit(KEY_F17, input->keybit);
++			set_bit(KEY_F18, input->keybit);
++		default:
++			return 0;
++	}
++	return 1;
 +}
 +
-+/* Gets io control parameters */
-+static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
++static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
 +{
-+	struct port *port = tty->driver_data;
-+	struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
-+	struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
++		return 0;
 +
-+	return	(ctrl_ul->RTS ? TIOCM_RTS : 0) |
-+		(ctrl_ul->DTR ? TIOCM_DTR : 0) |
-+		(ctrl_dl->DCD ? TIOCM_CAR : 0) |
-+		(ctrl_dl->RI  ? TIOCM_RNG : 0) |
-+		(ctrl_dl->DSR ? TIOCM_DSR : 0) |
-+		(ctrl_dl->CTS ? TIOCM_CTS : 0);
++	set_bit(EV_REP, input->evbit);
++	switch(usage->hid & HID_USAGE) {
++		case 0xfd08: map_key_clear(KEY_FORWARD);	break;
++		case 0xfd09: map_key_clear(KEY_BACK);		break;
++		case 0xfd0b: map_key_clear(KEY_PLAYPAUSE);	break;
++		case 0xfd0e: map_key_clear(KEY_CLOSE);		break;
++		case 0xfd0f: map_key_clear(KEY_PLAY);		break;
++		default:
++			return 0;
++	}
++	return 1;
 +}
 +
-+/* Sets io controls parameters */
-+static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
-+	unsigned int set, unsigned int clear)
++static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
 +{
-+	if (set & TIOCM_RTS)
-+		set_rts(tty, 1);
-+	else if (clear & TIOCM_RTS)
-+		set_rts(tty, 0);
++	if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
++			((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
++		return 0;
 +
-+	if (set & TIOCM_DTR)
-+		set_dtr(tty, 1);
-+	else if (clear & TIOCM_DTR)
-+		set_dtr(tty, 0);
++	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR)
++		switch(usage->hid & HID_USAGE) {
++			case 0x05a: map_key_clear(KEY_TEXT);		break;
++			case 0x05b: map_key_clear(KEY_RED);		break;
++			case 0x05c: map_key_clear(KEY_GREEN);		break;
++			case 0x05d: map_key_clear(KEY_YELLOW);		break;
++			case 0x05e: map_key_clear(KEY_BLUE);		break;
++			default:
++				return 0;
++		}
 +
-+	return 0;
++	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
++		switch(usage->hid & HID_USAGE) {
++			case 0x0f6: map_key_clear(KEY_NEXT);            break;
++			case 0x0fa: map_key_clear(KEY_BACK);            break;
++			default:
++				return 0;
++		}
++	return 1;
 +}
 +
-+static int ntty_cflags_changed(struct port *port, unsigned long flags,
-+		struct async_icount *cprev)
++static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
 +{
-+	struct async_icount cnow = port->tty_icount;
-+	int ret;
-+
-+	ret =	((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
-+		((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
-+		((flags & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
-+		((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++		return 0;
 +
-+	*cprev = cnow;
++	switch (usage->hid & HID_USAGE) {
++		case 0x1001: map_key_clear(KEY_MESSENGER);	break;
++		case 0x1003: map_key_clear(KEY_SOUND);		break;
++		case 0x1004: map_key_clear(KEY_VIDEO);		break;
++		case 0x1005: map_key_clear(KEY_AUDIO);		break;
++		case 0x100a: map_key_clear(KEY_DOCUMENTS);	break;
++		case 0x1011: map_key_clear(KEY_PREVIOUSSONG);	break;
++		case 0x1012: map_key_clear(KEY_NEXTSONG);	break;
++		case 0x1013: map_key_clear(KEY_CAMERA);		break;
++		case 0x1014: map_key_clear(KEY_MESSENGER);	break;
++		case 0x1015: map_key_clear(KEY_RECORD);		break;
++		case 0x1016: map_key_clear(KEY_PLAYER);		break;
++		case 0x1017: map_key_clear(KEY_EJECTCD);	break;
++		case 0x1018: map_key_clear(KEY_MEDIA);		break;
++		case 0x1019: map_key_clear(KEY_PROG1);		break;
++		case 0x101a: map_key_clear(KEY_PROG2);		break;
++		case 0x101b: map_key_clear(KEY_PROG3);		break;
++		case 0x101f: map_key_clear(KEY_ZOOMIN);		break;
++		case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
++		case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
++		case 0x1023: map_key_clear(KEY_CLOSE);		break;
++		case 0x1027: map_key_clear(KEY_MENU);		break;
++		/* this one is marked as 'Rotate' */
++		case 0x1028: map_key_clear(KEY_ANGLE);		break;
++		case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
++		case 0x102a: map_key_clear(KEY_BACK);		break;
++		case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);	break;
++		case 0x1041: map_key_clear(KEY_BATTERY);	break;
++		case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
++		case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
++		case 0x1044: map_key_clear(KEY_PRESENTATION);	break;
++		case 0x1045: map_key_clear(KEY_UNDO);		break;
++		case 0x1046: map_key_clear(KEY_REDO);		break;
++		case 0x1047: map_key_clear(KEY_PRINT);		break;
++		case 0x1048: map_key_clear(KEY_SAVE);		break;
++		case 0x1049: map_key_clear(KEY_PROG1);		break;
++		case 0x104a: map_key_clear(KEY_PROG2);		break;
++		case 0x104b: map_key_clear(KEY_PROG3);		break;
++		case 0x104c: map_key_clear(KEY_PROG4);		break;
 +
-+	return ret;
++		default:
++			return 0;
++	}
++	return 1;
 +}
 +
-+static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
++static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
 +{
-+	struct async_icount cnow = port->tty_icount;
-+	struct serial_icounter_struct icount;
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++		return 0;
 +
-+	icount.cts = cnow.cts;
-+	icount.dsr = cnow.dsr;
-+	icount.rng = cnow.rng;
-+	icount.dcd = cnow.dcd;
-+	icount.rx = cnow.rx;
-+	icount.tx = cnow.tx;
-+	icount.frame = cnow.frame;
-+	icount.overrun = cnow.overrun;
-+	icount.parity = cnow.parity;
-+	icount.brk = cnow.brk;
-+	icount.buf_overrun = cnow.buf_overrun;
++	switch (usage->hid & HID_USAGE) {
++		case 0x156: map_key_clear(KEY_WORDPROCESSOR);	break;
++		case 0x157: map_key_clear(KEY_SPREADSHEET);	break;
++		case 0x158: map_key_clear(KEY_PRESENTATION);	break;
++		case 0x15c: map_key_clear(KEY_STOP);		break;
 +
-+	return copy_to_user(argp, &icount, sizeof(icount));
++		default:
++			return 0;
++	}
++	return 1;
 +}
 +
-+static int ntty_ioctl(struct tty_struct *tty, struct file *file,
-+		      unsigned int cmd, unsigned long arg)
++static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
++			      unsigned long **bit, int *max)
 +{
-+	struct port *port = tty->driver_data;
-+	void __user *argp = (void __user *)arg;
-+	int rval = -ENOIOCTLCMD;
++	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
++		return 0;
 +
-+	DBG1("******** IOCTL, cmd: %d", cmd);
++	switch (usage->hid & HID_USAGE) {
++		case 0x230: map_key(BTN_MOUSE);			break;
++		case 0x231: map_rel(REL_WHEEL);			break;
++		/* 
++		 * this keyboard has a scrollwheel implemented in
++		 * totally broken way. We map this usage temporarily
++		 * to HWHEEL and handle it in the event quirk handler
++		 */
++		case 0x232: map_rel(REL_HWHEEL);		break;
 +
-+	switch (cmd) {
-+	case TIOCMIWAIT: {
-+		struct async_icount cprev = port->tty_icount;
++		default:
++			return 0;
++	}
++	return 1;
++}
 +
-+		rval = wait_event_interruptible(port->tty_wait,
-+				ntty_cflags_changed(port, arg, &cprev));
-+		break;
-+	} case TIOCGICOUNT:
-+		rval = ntty_ioctl_tiocgicount(port, argp);
-+		break;
-+	default:
-+		DBG1("ERR: 0x%08X, %d", cmd, cmd);
-+		break;
-+	};
++#define VENDOR_ID_BELKIN			0x1020
++#define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD	0x0006
 +
-+	return rval;
-+}
++#define VENDOR_ID_CHERRY			0x046a
++#define DEVICE_ID_CHERRY_CYMOTION		0x0023
 +
-+/*
-+ * Called by the upper tty layer when tty buffers are ready
-+ * to receive data again after a call to throttle.
-+ */
-+static void ntty_unthrottle(struct tty_struct *tty)
-+{
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+	unsigned long flags;
++#define VENDOR_ID_CHICONY			0x04f2
++#define DEVICE_ID_CHICONY_TACTICAL_PAD		0x0418
 +
-+	DBG1("UNTHROTTLE");
-+	spin_lock_irqsave(&dc->spin_mutex, flags);
-+	enable_transmit_dl(tty->index % MAX_PORT, dc);
-+	set_rts(tty, 1);
++#define VENDOR_ID_EZKEY				0x0518
++#define DEVICE_ID_BTC_8193			0x0002
 +
-+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-+}
++#define VENDOR_ID_LOGITECH			0x046d
++#define DEVICE_ID_LOGITECH_RECEIVER		0xc101
++#define DEVICE_ID_S510_RECEIVER			0xc50c
++#define DEVICE_ID_S510_RECEIVER_2		0xc517
++#define DEVICE_ID_MX3000_RECEIVER		0xc513
 +
-+/*
-+ * Called by the upper tty layer when the tty buffers are almost full.
-+ * The driver should stop send more data.
-+ */
-+static void ntty_throttle(struct tty_struct *tty)
-+{
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+	unsigned long flags;
++#define VENDOR_ID_MICROSOFT			0x045e
++#define DEVICE_ID_MS4K				0x00db
++#define DEVICE_ID_MS6K				0x00f9
++#define DEVICE_IS_MS_PRESENTER_8K_BT		0x0701
++#define DEVICE_ID_MS_PRESENTER_8K_USB		0x0713
 +
-+	DBG1("THROTTLE");
-+	spin_lock_irqsave(&dc->spin_mutex, flags);
-+	set_rts(tty, 0);
-+	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-+}
++#define VENDOR_ID_MONTEREY			0x0566
++#define DEVICE_ID_GENIUS_KB29E			0x3004
 +
-+/* just to discard single character writes */
-+static void ntty_put_char(struct tty_struct *tty, unsigned char c)
-+{
-+	/* FIXME !!! */
-+	DBG2("PUT CHAR Function: %c", c);
-+}
++#define VENDOR_ID_PETALYNX			0x18b1
++#define DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
 +
-+/* Returns number of chars in buffer, called by tty layer */
-+static s32 ntty_chars_in_buffer(struct tty_struct *tty)
-+{
-+	struct port *port = tty->driver_data;
-+	struct nozomi *dc = get_dc_by_tty(tty);
-+	s32 rval;
++static const struct hid_input_blacklist {
++	__u16 idVendor;
++	__u16 idProduct;
++	int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
++} hid_input_blacklist[] = {
++	{ VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
 +
-+	if (unlikely(!dc || !port)) {
-+		rval = -ENODEV;
-+		goto exit_in_buffer;
-+	}
++	{ VENDOR_ID_CHERRY, DEVICE_ID_CHERRY_CYMOTION, quirk_cherry_cymotion },
 +
-+	if (unlikely(!port->tty_open_count)) {
-+		dev_err(&dc->pdev->dev, "No tty open?\n");
-+		rval = -ENODEV;
-+		goto exit_in_buffer;
-+	}
++	{ VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad },
 +
-+	rval = __kfifo_len(port->fifo_ul);
++	{ VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
 +
-+exit_in_buffer:
-+	return rval;
-+}
++	{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
++	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
++	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
++	{ VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless },
 +
-+static struct tty_operations tty_ops = {
-+	.ioctl = ntty_ioctl,
-+	.open = ntty_open,
-+	.close = ntty_close,
-+	.write = ntty_write,
-+	.write_room = ntty_write_room,
-+	.unthrottle = ntty_unthrottle,
-+	.throttle = ntty_throttle,
-+	.chars_in_buffer = ntty_chars_in_buffer,
-+	.put_char = ntty_put_char,
-+	.tiocmget = ntty_tiocmget,
-+	.tiocmset = ntty_tiocmset,
-+};
++	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb },
++	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb },
++	{ VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k },
++	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K_USB, quirk_microsoft_presenter_8k },
 +
-+/* Module initialization */
-+static struct pci_driver nozomi_driver = {
-+	.name = NOZOMI_NAME,
-+	.id_table = nozomi_pci_tbl,
-+	.probe = nozomi_card_init,
-+	.remove = __devexit_p(nozomi_card_exit),
++	{ VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
++
++	{ VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
++	
++	{ 0, 0, 0 }
 +};
 +
-+static __init int nozomi_init(void)
++int hidinput_mapping_quirks(struct hid_usage *usage, 
++				   struct input_dev *input, 
++				   unsigned long **bit, int *max)
 +{
-+	int ret;
++	struct hid_device *device = input_get_drvdata(input);
++	int i = 0;
++	
++	while (hid_input_blacklist[i].quirk) {
++		if (hid_input_blacklist[i].idVendor == device->vendor &&
++				hid_input_blacklist[i].idProduct == device->product)
++			return hid_input_blacklist[i].quirk(usage, input, bit, max);
++		i++;
++	}
++	return 0;
++}
 +
-+	printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
++void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
++{
++	struct input_dev *input;
 +
-+	ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
-+	if (!ntty_driver)
-+		return -ENOMEM;
++	input = field->hidinput->input;
 +
-+	ntty_driver->owner = THIS_MODULE;
-+	ntty_driver->driver_name = NOZOMI_NAME_TTY;
-+	ntty_driver->name = "noz";
-+	ntty_driver->major = 0;
-+	ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-+	ntty_driver->subtype = SERIAL_TYPE_NORMAL;
-+	ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-+	ntty_driver->init_termios = tty_std_termios;
-+	ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
-+						HUPCL | CLOCAL;
-+	ntty_driver->init_termios.c_ispeed = 115200;
-+	ntty_driver->init_termios.c_ospeed = 115200;
-+	tty_set_operations(ntty_driver, &tty_ops);
++	if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
++		|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
++		if (value) hid->quirks |=  HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
++		else       hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
++		return;
++	}
 +
-+	ret = tty_register_driver(ntty_driver);
-+	if (ret) {
-+		printk(KERN_ERR "Nozomi: failed to register ntty driver\n");
-+		goto free_tty;
++	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
++			(usage->type == EV_REL) &&
++			(usage->code == REL_WHEEL)) {
++		hid->delayed_value = value;
++		return;
 +	}
 +
-+	ret = pci_register_driver(&nozomi_driver);
-+	if (ret) {
-+		printk(KERN_ERR "Nozomi: can't register pci driver\n");
-+		goto unr_tty;
++	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
++			(usage->hid == 0x000100b8)) {
++		input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value);
++		return;
 +	}
 +
-+	return 0;
-+unr_tty:
-+	tty_unregister_driver(ntty_driver);
-+free_tty:
-+	put_tty_driver(ntty_driver);
-+	return ret;
-+}
++	if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
++		input_event(input, usage->type, usage->code, -value);
++		return;
++	}
 +
-+static __exit void nozomi_exit(void)
-+{
-+	printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
-+	pci_unregister_driver(&nozomi_driver);
-+	tty_unregister_driver(ntty_driver);
-+	put_tty_driver(ntty_driver);
-+}
++	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
++		input_event(input, usage->type, REL_HWHEEL, value);
++		return;
++	}
 +
-+module_init(nozomi_init);
-+module_exit(nozomi_exit);
++	if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
++		return;
 +
-+module_param(debug, int, S_IRUGO | S_IWUSR);
++	/* Handling MS keyboards special buttons */
++	if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && 
++			usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
++		int key = 0;
++		static int last_key = 0;
++		switch (value) {
++			case 0x01: key = KEY_F14; break;
++			case 0x02: key = KEY_F15; break;
++			case 0x04: key = KEY_F16; break;
++			case 0x08: key = KEY_F17; break;
++			case 0x10: key = KEY_F18; break;
++			default: break;
++		}
++		if (key) {
++			input_event(input, usage->type, key, 1);
++			last_key = key;
++		} else {
++			input_event(input, usage->type, last_key, 0);
++		}
++	}
 +
-+MODULE_LICENSE("Dual BSD/GPL");
-+MODULE_DESCRIPTION(DRIVER_DESC);
-diff --git a/drivers/char/random.c b/drivers/char/random.c
-index 5fee056..c511a83 100644
---- a/drivers/char/random.c
-+++ b/drivers/char/random.c
-@@ -667,8 +667,6 @@ void add_disk_randomness(struct gendisk *disk)
- 	add_timer_randomness(disk->random,
- 			     0x100 + MKDEV(disk->major, disk->first_minor));
- }
++	/* handle the temporary quirky mapping to HWHEEL */
++	if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT &&
++			usage->type == EV_REL && usage->code == REL_HWHEEL) {
++		input_event(input, usage->type, REL_WHEEL, -value);
++		return;
++	}
++}
++
++
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index 0b27da7..5325d98 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -34,10 +34,10 @@
+ #include <linux/hid.h>
+ #include <linux/hid-debug.h>
+ 
+-static int hid_pb_fnmode = 1;
+-module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
++static int hid_apple_fnmode = 1;
++module_param_named(pb_fnmode, hid_apple_fnmode, int, 0644);
+ MODULE_PARM_DESC(pb_fnmode,
+-		"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
++		"Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
+ 
+ #define unk	KEY_UNKNOWN
+ 
+@@ -86,10 +86,6 @@ static const struct {
+ #define map_abs_clear(c)	do { map_abs(c); clear_bit(c, bit); } while (0)
+ #define map_key_clear(c)	do { map_key(c); clear_bit(c, bit); } while (0)
+ 
+-/* hardware needing special handling due to colliding MSVENDOR page usages */
+-#define IS_CHICONY_TACTICAL_PAD(x) (x->vendor == 0x04f2 && device->product == 0x0418)
+-#define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9))
 -
--EXPORT_SYMBOL(add_disk_randomness);
- #endif
+ #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
  
- #define EXTRACT_SIZE 10
-diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
-index 0c66b80..78b151c 100644
---- a/drivers/char/rtc.c
-+++ b/drivers/char/rtc.c
-@@ -1,5 +1,5 @@
- /*
-- *	Real Time Clock interface for Linux	
-+ *	Real Time Clock interface for Linux
-  *
-  *	Copyright (C) 1996 Paul Gortmaker
-  *
-@@ -17,7 +17,7 @@
-  *	has been received. If a RTC interrupt has already happened,
-  *	it will output an unsigned long and then block. The output value
-  *	contains the interrupt status in the low byte and the number of
-- *	interrupts since the last read in the remaining high bytes. The 
-+ *	interrupts since the last read in the remaining high bytes. The
-  *	/dev/rtc interface can also be used with the select(2) call.
-  *
-  *	This program is free software; you can redistribute it and/or
-@@ -104,12 +104,14 @@ static int rtc_has_irq = 1;
+ struct hidinput_key_translation {
+@@ -98,20 +94,36 @@ struct hidinput_key_translation {
+ 	u8 flags;
+ };
  
- #ifndef CONFIG_HPET_EMULATE_RTC
- #define is_hpet_enabled()			0
--#define hpet_set_alarm_time(hrs, min, sec) 	0
--#define hpet_set_periodic_freq(arg) 		0
--#define hpet_mask_rtc_irq_bit(arg) 		0
--#define hpet_set_rtc_irq_bit(arg) 		0
--#define hpet_rtc_timer_init() 			do { } while (0)
--#define hpet_rtc_dropped_irq() 			0
-+#define hpet_set_alarm_time(hrs, min, sec)	0
-+#define hpet_set_periodic_freq(arg)		0
-+#define hpet_mask_rtc_irq_bit(arg)		0
-+#define hpet_set_rtc_irq_bit(arg)		0
-+#define hpet_rtc_timer_init()			do { } while (0)
-+#define hpet_rtc_dropped_irq()			0
-+#define hpet_register_irq_handler(h)		0
-+#define hpet_unregister_irq_handler(h)		0
- #ifdef RTC_IRQ
- static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id)
- {
-@@ -147,7 +149,7 @@ static int rtc_ioctl(struct inode *inode, struct file *file,
- static unsigned int rtc_poll(struct file *file, poll_table *wait);
- #endif
+-#define POWERBOOK_FLAG_FKEY 0x01
++#define APPLE_FLAG_FKEY 0x01
++
++static struct hidinput_key_translation apple_fn_keys[] = {
++	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
++	{ KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
++	{ KEY_F3,       KEY_CYCLEWINDOWS,       APPLE_FLAG_FKEY }, /* Exposé */
++	{ KEY_F4,       KEY_FN_F4,              APPLE_FLAG_FKEY }, /* Dashboard */
++	{ KEY_F5,       KEY_FN_F5 },
++	{ KEY_F6,       KEY_FN_F6 },
++	{ KEY_F7,       KEY_BACK,               APPLE_FLAG_FKEY },
++	{ KEY_F8,       KEY_PLAYPAUSE,          APPLE_FLAG_FKEY },
++	{ KEY_F9,       KEY_FORWARD,            APPLE_FLAG_FKEY },
++	{ KEY_F10,      KEY_MUTE,               APPLE_FLAG_FKEY },
++	{ KEY_F11,      KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
++	{ KEY_F12,      KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
++	{ }
++};
  
--static void get_rtc_alm_time (struct rtc_time *alm_tm);
-+static void get_rtc_alm_time(struct rtc_time *alm_tm);
- #ifdef RTC_IRQ
- static void set_rtc_irq_bit_locked(unsigned char bit);
- static void mask_rtc_irq_bit_locked(unsigned char bit);
-@@ -185,9 +187,9 @@ static int rtc_proc_open(struct inode *inode, struct file *file);
-  * rtc_status but before mod_timer is called, which would then reenable the
-  * timer (but you would need to have an awful timing before you'd trip on it)
-  */
--static unsigned long rtc_status = 0;	/* bitmapped status byte.	*/
--static unsigned long rtc_freq = 0;	/* Current periodic IRQ rate	*/
--static unsigned long rtc_irq_data = 0;	/* our output to the world	*/
-+static unsigned long rtc_status;	/* bitmapped status byte.	*/
-+static unsigned long rtc_freq;		/* Current periodic IRQ rate	*/
-+static unsigned long rtc_irq_data;	/* our output to the world	*/
- static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
+ static struct hidinput_key_translation powerbook_fn_keys[] = {
+ 	{ KEY_BACKSPACE, KEY_DELETE },
+-	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     POWERBOOK_FLAG_FKEY },
+-	{ KEY_F2,       KEY_BRIGHTNESSUP,       POWERBOOK_FLAG_FKEY },
+-	{ KEY_F3,       KEY_MUTE,               POWERBOOK_FLAG_FKEY },
+-	{ KEY_F4,       KEY_VOLUMEDOWN,         POWERBOOK_FLAG_FKEY },
+-	{ KEY_F5,       KEY_VOLUMEUP,           POWERBOOK_FLAG_FKEY },
+-	{ KEY_F6,       KEY_NUMLOCK,            POWERBOOK_FLAG_FKEY },
+-	{ KEY_F7,       KEY_SWITCHVIDEOMODE,    POWERBOOK_FLAG_FKEY },
+-	{ KEY_F8,       KEY_KBDILLUMTOGGLE,     POWERBOOK_FLAG_FKEY },
+-	{ KEY_F9,       KEY_KBDILLUMDOWN,       POWERBOOK_FLAG_FKEY },
+-	{ KEY_F10,      KEY_KBDILLUMUP,         POWERBOOK_FLAG_FKEY },
++	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
++	{ KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
++	{ KEY_F3,       KEY_MUTE,               APPLE_FLAG_FKEY },
++	{ KEY_F4,       KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
++	{ KEY_F5,       KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
++	{ KEY_F6,       KEY_NUMLOCK,            APPLE_FLAG_FKEY },
++	{ KEY_F7,       KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
++	{ KEY_F8,       KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
++	{ KEY_F9,       KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
++	{ KEY_F10,      KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
+ 	{ KEY_UP,       KEY_PAGEUP },
+ 	{ KEY_DOWN,     KEY_PAGEDOWN },
+ 	{ KEY_LEFT,     KEY_HOME },
+@@ -142,7 +154,7 @@ static struct hidinput_key_translation powerbook_numlock_keys[] = {
+ 	{ }
+ };
  
- #ifdef RTC_IRQ
-@@ -195,7 +197,7 @@ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */
-  * rtc_task_lock nests inside rtc_lock.
-  */
- static DEFINE_SPINLOCK(rtc_task_lock);
--static rtc_task_t *rtc_callback = NULL;
-+static rtc_task_t *rtc_callback;
- #endif
+-static struct hidinput_key_translation powerbook_iso_keyboard[] = {
++static struct hidinput_key_translation apple_iso_keyboard[] = {
+ 	{ KEY_GRAVE,    KEY_102ND },
+ 	{ KEY_102ND,    KEY_GRAVE },
+ 	{ }
+@@ -160,39 +172,42 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra
+ 	return NULL;
+ }
  
- /*
-@@ -205,7 +207,7 @@ static rtc_task_t *rtc_callback = NULL;
+-static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
++int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
+ 		struct hid_usage *usage, __s32 value)
+ {
+ 	struct hidinput_key_translation *trans;
  
- static unsigned long epoch = 1900;	/* year corresponding to 0x00	*/
+ 	if (usage->code == KEY_FN) {
+-		if (value) hid->quirks |=  HID_QUIRK_POWERBOOK_FN_ON;
+-		else       hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
++		if (value) hid->quirks |=  HID_QUIRK_APPLE_FN_ON;
++		else       hid->quirks &= ~HID_QUIRK_APPLE_FN_ON;
  
--static const unsigned char days_in_mo[] = 
-+static const unsigned char days_in_mo[] =
- {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+ 		input_event(input, usage->type, usage->code, value);
  
- /*
-@@ -242,7 +244,7 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id)
- 	 *	the last read in the remainder of rtc_irq_data.
- 	 */
+ 		return 1;
+ 	}
  
--	spin_lock (&rtc_lock);
-+	spin_lock(&rtc_lock);
- 	rtc_irq_data += 0x100;
- 	rtc_irq_data &= ~0xff;
- 	if (is_hpet_enabled()) {
-@@ -259,16 +261,16 @@ irqreturn_t rtc_interrupt(int irq, void *dev_id)
- 	if (rtc_status & RTC_TIMER_ON)
- 		mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq + 2*HZ/100);
+-	if (hid_pb_fnmode) {
++	if (hid_apple_fnmode) {
+ 		int do_translate;
  
--	spin_unlock (&rtc_lock);
-+	spin_unlock(&rtc_lock);
+-		trans = find_translation(powerbook_fn_keys, usage->code);
++		trans = find_translation((hid->product < 0x220 ||
++					  hid->product >= 0x300) ?
++					 powerbook_fn_keys : apple_fn_keys,
++					 usage->code);
+ 		if (trans) {
+-			if (test_bit(usage->code, hid->pb_pressed_fn))
++			if (test_bit(usage->code, hid->apple_pressed_fn))
+ 				do_translate = 1;
+-			else if (trans->flags & POWERBOOK_FLAG_FKEY)
++			else if (trans->flags & APPLE_FLAG_FKEY)
+ 				do_translate =
+-					(hid_pb_fnmode == 2 &&  (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
+-					(hid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
++					(hid_apple_fnmode == 2 &&  (hid->quirks & HID_QUIRK_APPLE_FN_ON)) ||
++					(hid_apple_fnmode == 1 && !(hid->quirks & HID_QUIRK_APPLE_FN_ON));
+ 			else
+-				do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
++				do_translate = (hid->quirks & HID_QUIRK_APPLE_FN_ON);
  
- 	/* Now do the rest of the actions */
- 	spin_lock(&rtc_task_lock);
- 	if (rtc_callback)
- 		rtc_callback->func(rtc_callback->private_data);
- 	spin_unlock(&rtc_task_lock);
--	wake_up_interruptible(&rtc_wait);	
-+	wake_up_interruptible(&rtc_wait);
+ 			if (do_translate) {
+ 				if (value)
+-					set_bit(usage->code, hid->pb_pressed_fn);
++					set_bit(usage->code, hid->apple_pressed_fn);
+ 				else
+-					clear_bit(usage->code, hid->pb_pressed_fn);
++					clear_bit(usage->code, hid->apple_pressed_fn);
  
--	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
+ 				input_event(input, usage->type, trans->to, value);
  
- 	return IRQ_HANDLED;
+@@ -217,8 +232,8 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+ 		}
+ 	}
+ 
+-	if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) {
+-		trans = find_translation(powerbook_iso_keyboard, usage->code);
++	if (hid->quirks & HID_QUIRK_APPLE_ISO_KEYBOARD) {
++		trans = find_translation(apple_iso_keyboard, usage->code);
+ 		if (trans) {
+ 			input_event(input, usage->type, trans->to, value);
+ 			return 1;
+@@ -228,31 +243,35 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+ 	return 0;
  }
-@@ -335,7 +337,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
- 	DECLARE_WAITQUEUE(wait, current);
- 	unsigned long data;
- 	ssize_t retval;
--	
-+
- 	if (rtc_has_irq == 0)
- 		return -EIO;
  
-@@ -358,11 +360,11 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
- 		 * confusing. And no, xchg() is not the answer. */
+-static void hidinput_pb_setup(struct input_dev *input)
++static void hidinput_apple_setup(struct input_dev *input)
+ {
+ 	struct hidinput_key_translation *trans;
  
- 		__set_current_state(TASK_INTERRUPTIBLE);
--		
--		spin_lock_irq (&rtc_lock);
+ 	set_bit(KEY_NUMLOCK, input->keybit);
+ 
+ 	/* Enable all needed keys */
++	for (trans = apple_fn_keys; trans->from; trans++)
++		set_bit(trans->to, input->keybit);
 +
-+		spin_lock_irq(&rtc_lock);
- 		data = rtc_irq_data;
- 		rtc_irq_data = 0;
--		spin_unlock_irq (&rtc_lock);
-+		spin_unlock_irq(&rtc_lock);
+ 	for (trans = powerbook_fn_keys; trans->from; trans++)
+ 		set_bit(trans->to, input->keybit);
  
- 		if (data != 0)
- 			break;
-@@ -378,10 +380,13 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
- 		schedule();
- 	} while (1);
+ 	for (trans = powerbook_numlock_keys; trans->from; trans++)
+ 		set_bit(trans->to, input->keybit);
  
--	if (count == sizeof(unsigned int))
--		retval = put_user(data, (unsigned int __user *)buf) ?: sizeof(int);
--	else
--		retval = put_user(data, (unsigned long __user *)buf) ?: sizeof(long);
-+	if (count == sizeof(unsigned int)) {
-+		retval = put_user(data,
-+				  (unsigned int __user *)buf) ?: sizeof(int);
-+	} else {
-+		retval = put_user(data,
-+				  (unsigned long __user *)buf) ?: sizeof(long);
-+	}
- 	if (!retval)
- 		retval = count;
-  out:
-@@ -394,7 +399,7 @@ static ssize_t rtc_read(struct file *file, char __user *buf,
+-	for (trans = powerbook_iso_keyboard; trans->from; trans++)
++	for (trans = apple_iso_keyboard; trans->from; trans++)
+ 		set_bit(trans->to, input->keybit);
  
- static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
+ }
+ #else
+-static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
+-		struct hid_usage *usage, __s32 value)
++inline int hidinput_apple_event(struct hid_device *hid,
++				       struct input_dev *input,
++				       struct hid_usage *usage, __s32 value)
  {
--	struct rtc_time wtime; 
-+	struct rtc_time wtime;
+ 	return 0;
+ }
  
- #ifdef RTC_IRQ
- 	if (rtc_has_irq == 0) {
-@@ -426,35 +431,41 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- 	}
- 	case RTC_PIE_OFF:	/* Mask periodic int. enab. bit	*/
- 	{
--		unsigned long flags; /* can be called from isr via rtc_control() */
--		spin_lock_irqsave (&rtc_lock, flags);
-+		/* can be called from isr via rtc_control() */
-+		unsigned long flags;
-+
-+		spin_lock_irqsave(&rtc_lock, flags);
- 		mask_rtc_irq_bit_locked(RTC_PIE);
- 		if (rtc_status & RTC_TIMER_ON) {
- 			rtc_status &= ~RTC_TIMER_ON;
- 			del_timer(&rtc_irq_timer);
- 		}
--		spin_unlock_irqrestore (&rtc_lock, flags);
-+		spin_unlock_irqrestore(&rtc_lock, flags);
-+
- 		return 0;
- 	}
- 	case RTC_PIE_ON:	/* Allow periodic ints		*/
- 	{
--		unsigned long flags; /* can be called from isr via rtc_control() */
-+		/* can be called from isr via rtc_control() */
-+		unsigned long flags;
-+
- 		/*
- 		 * We don't really want Joe User enabling more
- 		 * than 64Hz of interrupts on a multi-user machine.
- 		 */
- 		if (!kernel && (rtc_freq > rtc_max_user_freq) &&
--			(!capable(CAP_SYS_RESOURCE)))
-+						(!capable(CAP_SYS_RESOURCE)))
- 			return -EACCES;
+-static inline void hidinput_pb_setup(struct input_dev *input)
++static inline void hidinput_apple_setup(struct input_dev *input)
+ {
+ }
+ #endif
+@@ -343,7 +362,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ {
+ 	struct input_dev *input = hidinput->input;
+ 	struct hid_device *device = input_get_drvdata(input);
+-	int max = 0, code;
++	int max = 0, code, ret;
+ 	unsigned long *bit = NULL;
  
--		spin_lock_irqsave (&rtc_lock, flags);
-+		spin_lock_irqsave(&rtc_lock, flags);
- 		if (!(rtc_status & RTC_TIMER_ON)) {
- 			mod_timer(&rtc_irq_timer, jiffies + HZ/rtc_freq +
- 					2*HZ/100);
- 			rtc_status |= RTC_TIMER_ON;
- 		}
- 		set_rtc_irq_bit_locked(RTC_PIE);
--		spin_unlock_irqrestore (&rtc_lock, flags);
-+		spin_unlock_irqrestore(&rtc_lock, flags);
-+
- 		return 0;
- 	}
- 	case RTC_UIE_OFF:	/* Mask ints from RTC updates.	*/
-@@ -477,7 +488,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- 		 */
- 		memset(&wtime, 0, sizeof(struct rtc_time));
- 		get_rtc_alm_time(&wtime);
--		break; 
-+		break;
+ 	field->hidinput = hidinput;
+@@ -362,6 +381,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 		goto ignore;
  	}
- 	case RTC_ALM_SET:	/* Store a time into the alarm */
- 	{
-@@ -505,16 +516,21 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- 			 */
- 		}
- 		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
--		    RTC_ALWAYS_BCD)
--		{
--			if (sec < 60) BIN_TO_BCD(sec);
--			else sec = 0xff;
--
--			if (min < 60) BIN_TO_BCD(min);
--			else min = 0xff;
--
--			if (hrs < 24) BIN_TO_BCD(hrs);
--			else hrs = 0xff;
-+							RTC_ALWAYS_BCD) {
-+			if (sec < 60)
-+				BIN_TO_BCD(sec);
-+			else
-+				sec = 0xff;
-+
-+			if (min < 60)
-+				BIN_TO_BCD(min);
-+			else
-+				min = 0xff;
-+
-+			if (hrs < 24)
-+				BIN_TO_BCD(hrs);
-+			else
-+				hrs = 0xff;
- 		}
- 		CMOS_WRITE(hrs, RTC_HOURS_ALARM);
- 		CMOS_WRITE(min, RTC_MINUTES_ALARM);
-@@ -563,11 +579,12 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
  
- 		if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
- 			return -EINVAL;
--			
++	/* handle input mappings for quirky devices */
++	ret = hidinput_mapping_quirks(usage, input, &bit, &max);
++	if (ret)
++		goto mapped;
 +
- 		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
- 			return -EINVAL;
+ 	switch (usage->hid & HID_USAGE_PAGE) {
  
--		if ((yrs -= epoch) > 255)    /* They are unsigned */
-+		yrs -= epoch;
-+		if (yrs > 255)		/* They are unsigned */
- 			return -EINVAL;
+ 		case HID_UP_UNDEFINED:
+@@ -549,14 +573,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 				case 0x000: goto ignore;
+ 				case 0x034: map_key_clear(KEY_SLEEP);		break;
+ 				case 0x036: map_key_clear(BTN_MISC);		break;
+-				/*
+-				 * The next three are reported by Belkin wireless
+-				 * keyboard (1020:0006). These values are "reserved"
+-				 * in HUT 1.12.
+-				 */
+-				case 0x03a: map_key_clear(KEY_SOUND);           break;
+-				case 0x03b: map_key_clear(KEY_CAMERA);          break;
+-				case 0x03c: map_key_clear(KEY_DOCUMENTS);       break;
  
- 		spin_lock_irq(&rtc_lock);
-@@ -635,9 +652,10 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- 	{
- 		int tmp = 0;
- 		unsigned char val;
--		unsigned long flags; /* can be called from isr via rtc_control() */
-+		/* can be called from isr via rtc_control() */
-+		unsigned long flags;
+ 				case 0x040: map_key_clear(KEY_MENU);		break;
+ 				case 0x045: map_key_clear(KEY_RADIO);		break;
+@@ -602,10 +618,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 				case 0x0e9: map_key_clear(KEY_VOLUMEUP);	break;
+ 				case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);	break;
  
--		/* 
-+		/*
- 		 * The max we can do is 8192Hz.
- 		 */
- 		if ((arg < 2) || (arg > 8192))
-@@ -646,7 +664,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- 		 * We don't really want Joe User generating more
- 		 * than 64Hz of interrupts on a multi-user machine.
- 		 */
--		if (!kernel && (arg > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
-+		if (!kernel && (arg > rtc_max_user_freq) &&
-+					!capable(CAP_SYS_RESOURCE))
- 			return -EACCES;
+-				/* reserved in HUT 1.12. Reported on Petalynx remote */
+-				case 0x0f6: map_key_clear(KEY_NEXT);		break;
+-				case 0x0fa: map_key_clear(KEY_BACK);		break;
+-
+ 				case 0x182: map_key_clear(KEY_BOOKMARKS);	break;
+ 				case 0x183: map_key_clear(KEY_CONFIG);		break;
+ 				case 0x184: map_key_clear(KEY_WORDPROCESSOR);	break;
+@@ -665,51 +677,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 				case 0x28b: map_key_clear(KEY_FORWARDMAIL);	break;
+ 				case 0x28c: map_key_clear(KEY_SEND);		break;
  
- 		while (arg > (1<<tmp))
-@@ -674,11 +693,11 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- #endif
- 	case RTC_EPOCH_READ:	/* Read the epoch.	*/
- 	{
--		return put_user (epoch, (unsigned long __user *)arg);
-+		return put_user(epoch, (unsigned long __user *)arg);
- 	}
- 	case RTC_EPOCH_SET:	/* Set the epoch.	*/
- 	{
--		/* 
-+		/*
- 		 * There were no RTC clocks before 1900.
- 		 */
- 		if (arg < 1900)
-@@ -693,7 +712,8 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
- 	default:
- 		return -ENOTTY;
- 	}
--	return copy_to_user((void __user *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
-+	return copy_to_user((void __user *)arg,
-+			    &wtime, sizeof wtime) ? -EFAULT : 0;
- }
+-				/* Reported on a Cherry Cymotion keyboard */
+-				case 0x301: map_key_clear(KEY_PROG1);		break;
+-				case 0x302: map_key_clear(KEY_PROG2);		break;
+-				case 0x303: map_key_clear(KEY_PROG3);		break;
+-
+-				/* Reported on certain Logitech wireless keyboards */
+-				case 0x1001: map_key_clear(KEY_MESSENGER);	break;
+-				case 0x1003: map_key_clear(KEY_SOUND);		break;
+-				case 0x1004: map_key_clear(KEY_VIDEO);		break;
+-				case 0x1005: map_key_clear(KEY_AUDIO);		break;
+-				case 0x100a: map_key_clear(KEY_DOCUMENTS);	break;
+-				case 0x1011: map_key_clear(KEY_PREVIOUSSONG);	break;
+-				case 0x1012: map_key_clear(KEY_NEXTSONG);	break;
+-				case 0x1013: map_key_clear(KEY_CAMERA);		break;
+-				case 0x1014: map_key_clear(KEY_MESSENGER);	break;
+-				case 0x1015: map_key_clear(KEY_RECORD);		break;
+-				case 0x1016: map_key_clear(KEY_PLAYER);		break;
+-				case 0x1017: map_key_clear(KEY_EJECTCD);	break;
+-				case 0x1018: map_key_clear(KEY_MEDIA);          break;
+-				case 0x1019: map_key_clear(KEY_PROG1);		break;
+-				case 0x101a: map_key_clear(KEY_PROG2);		break;
+-				case 0x101b: map_key_clear(KEY_PROG3);		break;
+-				case 0x101f: map_key_clear(KEY_ZOOMIN);		break;
+-				case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
+-				case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
+-				case 0x1023: map_key_clear(KEY_CLOSE);		break;
+-				case 0x1027: map_key_clear(KEY_MENU);           break;
+-				/* this one is marked as 'Rotate' */
+-				case 0x1028: map_key_clear(KEY_ANGLE);		break;
+-				case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
+-				case 0x102a: map_key_clear(KEY_BACK);           break;
+-				case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);   break;
+-				case 0x1041: map_key_clear(KEY_BATTERY);	break;
+-				case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
+-				case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
+-				case 0x1044: map_key_clear(KEY_PRESENTATION);	break;
+-				case 0x1045: map_key_clear(KEY_UNDO);		break;
+-				case 0x1046: map_key_clear(KEY_REDO);		break;
+-				case 0x1047: map_key_clear(KEY_PRINT);		break;
+-				case 0x1048: map_key_clear(KEY_SAVE);		break;
+-				case 0x1049: map_key_clear(KEY_PROG1);		break;
+-				case 0x104a: map_key_clear(KEY_PROG2);		break;
+-				case 0x104b: map_key_clear(KEY_PROG3);		break;
+-				case 0x104c: map_key_clear(KEY_PROG4);		break;
+-
+ 				default:    goto ignore;
+ 			}
+ 			break;
+@@ -736,63 +703,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
  
- static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-@@ -712,26 +732,25 @@ static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-  * needed here. Or anywhere else in this driver. */
- static int rtc_open(struct inode *inode, struct file *file)
- {
--	spin_lock_irq (&rtc_lock);
-+	spin_lock_irq(&rtc_lock);
+ 		case HID_UP_MSVENDOR:
  
--	if(rtc_status & RTC_IS_OPEN)
-+	if (rtc_status & RTC_IS_OPEN)
- 		goto out_busy;
+-			/* Unfortunately, there are multiple devices which
+-			 * emit usages from MSVENDOR page that require different
+-			 * handling. If this list grows too much in the future,
+-			 * more general handling will have to be introduced here
+-			 * (i.e. another blacklist).
+-			 */
+-
+-			/* Chicony Chicony KU-0418 tactical pad */
+-			if (IS_CHICONY_TACTICAL_PAD(device)) {
+-				set_bit(EV_REP, input->evbit);
+-				switch(usage->hid & HID_USAGE) {
+-					case 0xff01: map_key_clear(BTN_1);		break;
+-					case 0xff02: map_key_clear(BTN_2);		break;
+-					case 0xff03: map_key_clear(BTN_3);		break;
+-					case 0xff04: map_key_clear(BTN_4);		break;
+-					case 0xff05: map_key_clear(BTN_5);		break;
+-					case 0xff06: map_key_clear(BTN_6);		break;
+-					case 0xff07: map_key_clear(BTN_7);		break;
+-					case 0xff08: map_key_clear(BTN_8);		break;
+-					case 0xff09: map_key_clear(BTN_9);		break;
+-					case 0xff0a: map_key_clear(BTN_A);		break;
+-					case 0xff0b: map_key_clear(BTN_B);		break;
+-					default:    goto ignore;
+-				}
+-
+-			/* Microsoft Natural Ergonomic Keyboard 4000 */
+-			} else if (IS_MS_KB(device)) {
+-				switch(usage->hid & HID_USAGE) {
+-					case 0xfd06:
+-						map_key_clear(KEY_CHAT);
+-						break;
+-					case 0xfd07:
+-						map_key_clear(KEY_PHONE);
+-						break;
+-					case 0xff05:
+-						set_bit(EV_REP, input->evbit);
+-						map_key_clear(KEY_F13);
+-						set_bit(KEY_F14, input->keybit);
+-						set_bit(KEY_F15, input->keybit);
+-						set_bit(KEY_F16, input->keybit);
+-						set_bit(KEY_F17, input->keybit);
+-						set_bit(KEY_F18, input->keybit);
+-					default:	goto ignore;
+-				}
+-			} else {
+-				goto ignore;
+-			}
+-			break;
++			goto ignore;
  
- 	rtc_status |= RTC_IS_OPEN;
+-		case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
++		case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
  
- 	rtc_irq_data = 0;
--	spin_unlock_irq (&rtc_lock);
-+	spin_unlock_irq(&rtc_lock);
- 	return 0;
+ 			set_bit(EV_REP, input->evbit);
+ 			switch(usage->hid & HID_USAGE) {
+ 				case 0x003:
+-					/* The fn key on Apple PowerBooks */
++					/* The fn key on Apple USB keyboards */
+ 					map_key_clear(KEY_FN);
+-					hidinput_pb_setup(input);
++					hidinput_apple_setup(input);
+ 					break;
  
- out_busy:
--	spin_unlock_irq (&rtc_lock);
-+	spin_unlock_irq(&rtc_lock);
- 	return -EBUSY;
- }
+ 				default:    goto ignore;
+@@ -800,38 +720,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 			break;
  
--static int rtc_fasync (int fd, struct file *filp, int on)
+ 		case HID_UP_LOGIVENDOR:
+-			set_bit(EV_REP, input->evbit);
+-			switch(usage->hid & HID_USAGE) {
+-				/* Reported on Logitech Ultra X Media Remote */
+-				case 0x004: map_key_clear(KEY_AGAIN);		break;
+-				case 0x00d: map_key_clear(KEY_HOME);		break;
+-				case 0x024: map_key_clear(KEY_SHUFFLE);		break;
+-				case 0x025: map_key_clear(KEY_TV);		break;
+-				case 0x026: map_key_clear(KEY_MENU);		break;
+-				case 0x031: map_key_clear(KEY_AUDIO);		break;
+-				case 0x032: map_key_clear(KEY_TEXT);		break;
+-				case 0x033: map_key_clear(KEY_LAST);		break;
+-				case 0x047: map_key_clear(KEY_MP3);		break;
+-				case 0x048: map_key_clear(KEY_DVD);		break;
+-				case 0x049: map_key_clear(KEY_MEDIA);		break;
+-				case 0x04a: map_key_clear(KEY_VIDEO);		break;
+-				case 0x04b: map_key_clear(KEY_ANGLE);		break;
+-				case 0x04c: map_key_clear(KEY_LANGUAGE);	break;
+-				case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
+-				case 0x051: map_key_clear(KEY_RED);		break;
+-				case 0x052: map_key_clear(KEY_CLOSE);		break;
 -
-+static int rtc_fasync(int fd, struct file *filp, int on)
- {
--	return fasync_helper (fd, filp, on, &rtc_async_queue);
-+	return fasync_helper(fd, filp, on, &rtc_async_queue);
- }
- 
- static int rtc_release(struct inode *inode, struct file *file)
-@@ -762,16 +781,16 @@ static int rtc_release(struct inode *inode, struct file *file)
- 	}
- 	spin_unlock_irq(&rtc_lock);
- 
--	if (file->f_flags & FASYNC) {
--		rtc_fasync (-1, file, 0);
--	}
-+	if (file->f_flags & FASYNC)
-+		rtc_fasync(-1, file, 0);
- no_irq:
- #endif
+-				/* Reported on Petalynx Maxter remote */
+-				case 0x05a: map_key_clear(KEY_TEXT);		break;
+-				case 0x05b: map_key_clear(KEY_RED);		break;
+-				case 0x05c: map_key_clear(KEY_GREEN);		break;
+-				case 0x05d: map_key_clear(KEY_YELLOW);		break;
+-				case 0x05e: map_key_clear(KEY_BLUE);		break;
+-
+-				default:    goto ignore;
+-			}
+-			break;
  
--	spin_lock_irq (&rtc_lock);
-+	spin_lock_irq(&rtc_lock);
- 	rtc_irq_data = 0;
- 	rtc_status &= ~RTC_IS_OPEN;
--	spin_unlock_irq (&rtc_lock);
-+	spin_unlock_irq(&rtc_lock);
-+
- 	return 0;
- }
++			goto ignore;
++		
+ 		case HID_UP_PID:
  
-@@ -786,9 +805,9 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait)
+ 			switch(usage->hid & HID_USAGE) {
+@@ -858,6 +749,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 			break;
+ 	}
  
- 	poll_wait(file, &rtc_wait, wait);
++mapped:
+ 	if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
+ 		if (usage->hid == HID_GD_Z)
+ 			map_rel(REL_HWHEEL);
+@@ -867,9 +759,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+ 			map_key(BTN_1);
+ 	}
  
--	spin_lock_irq (&rtc_lock);
-+	spin_lock_irq(&rtc_lock);
- 	l = rtc_irq_data;
--	spin_unlock_irq (&rtc_lock);
-+	spin_unlock_irq(&rtc_lock);
+-	if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
+-		 (usage->type == EV_REL) && (usage->code == REL_WHEEL))
+-			set_bit(REL_HWHEEL, bit);
++	if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 |
++			HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
++			(usage->code == REL_WHEEL))
++		set_bit(REL_HWHEEL, bit);
  
- 	if (l != 0)
- 		return POLLIN | POLLRDNORM;
-@@ -796,14 +815,6 @@ static unsigned int rtc_poll(struct file *file, poll_table *wait)
- }
- #endif
+ 	if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
+ 		|| ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
+@@ -960,25 +853,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
+ 	if (!usage->type)
+ 		return;
  
--/*
-- * exported stuffs
-- */
+-	if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
+-		|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
+-		if (value) hid->quirks |=  HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
+-		else       hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
+-		return;
+-	}
 -
--EXPORT_SYMBOL(rtc_register);
--EXPORT_SYMBOL(rtc_unregister);
--EXPORT_SYMBOL(rtc_control);
+-	if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
+-		input_event(input, usage->type, usage->code, -value);
+-		return;
+-	}
 -
- int rtc_register(rtc_task_t *task)
- {
- #ifndef RTC_IRQ
-@@ -829,6 +840,7 @@ int rtc_register(rtc_task_t *task)
- 	return 0;
- #endif
- }
-+EXPORT_SYMBOL(rtc_register);
+-	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
+-		input_event(input, usage->type, REL_HWHEEL, value);
+-		return;
+-	}
+-
+-	if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
+-		return;
++	/* handle input events for quirky devices */
++	hidinput_event_quirks(hid, field, usage, value);
  
- int rtc_unregister(rtc_task_t *task)
- {
-@@ -845,7 +857,7 @@ int rtc_unregister(rtc_task_t *task)
- 		return -ENXIO;
+ 	if (usage->hat_min < usage->hat_max || usage->hat_dir) {
+ 		int hat_dir = usage->hat_dir;
+@@ -1039,25 +915,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
+ 		return;
  	}
- 	rtc_callback = NULL;
--	
-+
- 	/* disable controls */
- 	if (!hpet_mask_rtc_irq_bit(RTC_PIE | RTC_AIE | RTC_UIE)) {
- 		tmp = CMOS_READ(RTC_CONTROL);
-@@ -865,6 +877,7 @@ int rtc_unregister(rtc_task_t *task)
- 	return 0;
- #endif
- }
-+EXPORT_SYMBOL(rtc_unregister);
  
- int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
- {
-@@ -883,7 +896,7 @@ int rtc_control(rtc_task_t *task, unsigned int cmd, unsigned long arg)
- 	return rtc_do_ioctl(cmd, arg, 1);
- #endif
- }
--
-+EXPORT_SYMBOL(rtc_control);
+-	/* Handling MS keyboards special buttons */
+-	if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
+-		int key = 0;
+-		static int last_key = 0;
+-		switch (value) {
+-			case 0x01: key = KEY_F14; break;
+-			case 0x02: key = KEY_F15; break;
+-			case 0x04: key = KEY_F16; break;
+-			case 0x08: key = KEY_F17; break;
+-			case 0x10: key = KEY_F18; break;
+-			default: break;
+-		}
+-		if (key) {
+-			input_event(input, usage->type, key, 1);
+-			last_key = key;
+-		} else {
+-			input_event(input, usage->type, last_key, 0);
+-		}
+-	}
+ 	/* report the usage code as scancode if the key status has changed */
+ 	if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
+ 		input_event(input, EV_MSC, MSC_SCAN, usage->hid);
+diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
+index c557d70..7160fa6 100644
+--- a/drivers/hid/usbhid/Kconfig
++++ b/drivers/hid/usbhid/Kconfig
+@@ -25,12 +25,13 @@ comment "Input core support is needed for USB HID input layer or HIDBP support"
+ 	depends on USB_HID && INPUT=n
  
- /*
-  *	The various file operations we support.
-@@ -910,11 +923,11 @@ static struct miscdevice rtc_dev = {
+ config USB_HIDINPUT_POWERBOOK
+-	bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
++	bool "Enable support for Apple laptop/aluminum USB special keys"
+ 	default n
+ 	depends on USB_HID
+ 	help
+ 	  Say Y here if you want support for the special keys (Fn, Numlock) on
+-	  Apple iBooks, PowerBooks, MacBooks and MacBook Pros.
++	  Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB
++	  keyboards.
  
- #ifdef CONFIG_PROC_FS
- static const struct file_operations rtc_proc_fops = {
--	.owner = THIS_MODULE,
--	.open = rtc_proc_open,
--	.read  = seq_read,
--	.llseek = seq_lseek,
--	.release = single_release,
-+	.owner		= THIS_MODULE,
-+	.open		= rtc_proc_open,
-+	.read		= seq_read,
-+	.llseek		= seq_lseek,
-+	.release	= single_release,
- };
- #endif
+ 	  If unsure, say N.
  
-@@ -965,7 +978,7 @@ static int __init rtc_init(void)
- #ifdef CONFIG_SPARC32
- 	for_each_ebus(ebus) {
- 		for_each_ebusdev(edev, ebus) {
--			if(strcmp(edev->prom_node->name, "rtc") == 0) {
-+			if (strcmp(edev->prom_node->name, "rtc") == 0) {
- 				rtc_port = edev->resource[0].start;
- 				rtc_irq = edev->irqs[0];
- 				goto found;
-@@ -986,7 +999,8 @@ found:
- 	 * XXX Interrupt pin #7 in Espresso is shared between RTC and
- 	 * PCI Slot 2 INTA# (and some INTx# in Slot 1).
- 	 */
--	if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc", (void *)&rtc_port)) {
-+	if (request_irq(rtc_irq, rtc_interrupt, IRQF_SHARED, "rtc",
-+			(void *)&rtc_port)) {
- 		rtc_has_irq = 0;
- 		printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq);
- 		return -EIO;
-@@ -1015,16 +1029,26 @@ no_irq:
+diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
+index a255285..b77b61e 100644
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -19,6 +19,7 @@
  
- #ifdef RTC_IRQ
- 	if (is_hpet_enabled()) {
-+		int err;
-+
- 		rtc_int_handler_ptr = hpet_rtc_interrupt;
-+		err = hpet_register_irq_handler(rtc_interrupt);
-+		if (err != 0) {
-+			printk(KERN_WARNING "hpet_register_irq_handler failed "
-+					"in rtc_init().");
-+			return err;
-+		}
- 	} else {
- 		rtc_int_handler_ptr = rtc_interrupt;
- 	}
+ #define USB_VENDOR_ID_A4TECH		0x09da
+ #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
++#define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
  
--	if(request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED, "rtc", NULL)) {
-+	if (request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED,
-+			"rtc", NULL)) {
- 		/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
- 		rtc_has_irq = 0;
- 		printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
- 		rtc_release_region();
-+
- 		return -EIO;
- 	}
- 	hpet_rtc_timer_init();
-@@ -1036,6 +1060,7 @@ no_irq:
- 	if (misc_register(&rtc_dev)) {
- #ifdef RTC_IRQ
- 		free_irq(RTC_IRQ, NULL);
-+		hpet_unregister_irq_handler(rtc_interrupt);
- 		rtc_has_irq = 0;
- #endif
- 		rtc_release_region();
-@@ -1052,21 +1077,21 @@ no_irq:
+ #define USB_VENDOR_ID_AASHIMA		0x06d6
+ #define USB_DEVICE_ID_AASHIMA_GAMEPAD	0x0025
+@@ -28,6 +29,9 @@
+ #define USB_DEVICE_ID_ACECAD_FLAIR	0x0004
+ #define USB_DEVICE_ID_ACECAD_302	0x0008
  
- #if defined(__alpha__) || defined(__mips__)
- 	rtc_freq = HZ;
--	
-+
- 	/* Each operating system on an Alpha uses its own epoch.
- 	   Let's try to guess which one we are using now. */
--	
-+
- 	if (rtc_is_updating() != 0)
- 		msleep(20);
--	
-+
- 	spin_lock_irq(&rtc_lock);
- 	year = CMOS_READ(RTC_YEAR);
- 	ctrl = CMOS_READ(RTC_CONTROL);
- 	spin_unlock_irq(&rtc_lock);
--	
-+
- 	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
- 		BCD_TO_BIN(year);       /* This should never happen... */
--	
++#define USB_VENDOR_ID_ADS_TECH 		0x06e1
++#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X	0xa155
 +
- 	if (year < 20) {
- 		epoch = 2000;
- 		guess = "SRM (post-2000)";
-@@ -1087,7 +1112,8 @@ no_irq:
- #endif
- 	}
- 	if (guess)
--		printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", guess, epoch);
-+		printk(KERN_INFO "rtc: %s epoch (%lu) detected\n",
-+			guess, epoch);
- #endif
- #ifdef RTC_IRQ
- 	if (rtc_has_irq == 0)
-@@ -1096,8 +1122,12 @@ no_irq:
- 	spin_lock_irq(&rtc_lock);
- 	rtc_freq = 1024;
- 	if (!hpet_set_periodic_freq(rtc_freq)) {
--		/* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
--		CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
-+		/*
-+		 * Initialize periodic frequency to CMOS reset default,
-+		 * which is 1024Hz
-+		 */
-+		CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06),
-+			   RTC_FREQ_SELECT);
- 	}
- 	spin_unlock_irq(&rtc_lock);
- no_irq2:
-@@ -1110,20 +1140,22 @@ no_irq2:
- 	return 0;
- }
+ #define USB_VENDOR_ID_AIPTEK		0x08ca
+ #define USB_DEVICE_ID_AIPTEK_01		0x0001
+ #define USB_DEVICE_ID_AIPTEK_10		0x0010
+@@ -59,6 +63,9 @@
+ #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI	0x021a
+ #define USB_DEVICE_ID_APPLE_GEYSER4_ISO	0x021b
+ #define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
++#define USB_DEVICE_ID_APPLE_ALU_ANSI	0x0220
++#define USB_DEVICE_ID_APPLE_ALU_ISO	0x0221
++#define USB_DEVICE_ID_APPLE_ALU_JIS	0x0222
+ #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
+ #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
+ #define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
+@@ -94,6 +101,9 @@
+ #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST	0x1500
+ #define USB_DEVICE_ID_CODEMERCS_IOW_LAST	0x15ff
  
--static void __exit rtc_exit (void)
-+static void __exit rtc_exit(void)
- {
- 	cleanup_sysctl();
--	remove_proc_entry ("driver/rtc", NULL);
-+	remove_proc_entry("driver/rtc", NULL);
- 	misc_deregister(&rtc_dev);
++#define USB_VENDOR_ID_CYGNAL		0x10c4
++#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X	0x818a
++
+ #define USB_VENDOR_ID_CYPRESS		0x04b4
+ #define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
+ #define USB_DEVICE_ID_CYPRESS_HIDCOM	0x5500
+@@ -114,6 +124,9 @@
+ #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
+ #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
  
- #ifdef CONFIG_SPARC32
- 	if (rtc_has_irq)
--		free_irq (rtc_irq, &rtc_port);
-+		free_irq(rtc_irq, &rtc_port);
- #else
- 	rtc_release_region();
- #ifdef RTC_IRQ
--	if (rtc_has_irq)
--		free_irq (RTC_IRQ, NULL);
-+	if (rtc_has_irq) {
-+		free_irq(RTC_IRQ, NULL);
-+		hpet_unregister_irq_handler(hpet_rtc_interrupt);
-+	}
- #endif
- #endif /* CONFIG_SPARC32 */
- }
-@@ -1133,14 +1165,14 @@ module_exit(rtc_exit);
++#define USB_VENDOR_ID_EZKEY 		0x0518
++#define USB_DEVICE_ID_BTC_8193		0x0002
++
+ #define USB_VENDOR_ID_GAMERON		0x0810
+ #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
  
- #ifdef RTC_IRQ
- /*
-- * 	At IRQ rates >= 4096Hz, an interrupt may get lost altogether.
-+ *	At IRQ rates >= 4096Hz, an interrupt may get lost altogether.
-  *	(usually during an IDE disk interrupt, with IRQ unmasking off)
-  *	Since the interrupt handler doesn't get called, the IRQ status
-  *	byte doesn't get read, and the RTC stops generating interrupts.
-  *	A timer is set, and will call this function if/when that happens.
-  *	To get it out of this stalled state, we just read the status.
-  *	At least a jiffy of interrupts (rtc_freq/HZ) will have been lost.
-- *	(You *really* shouldn't be trying to use a non-realtime system 
-+ *	(You *really* shouldn't be trying to use a non-realtime system
-  *	for something that requires a steady > 1KHz signal anyways.)
-  */
+@@ -134,6 +147,9 @@
+ #define USB_DEVICE_ID_GOGOPEN		0x00ce
+ #define USB_DEVICE_ID_PENPOWER		0x00f4
  
-@@ -1148,7 +1180,7 @@ static void rtc_dropped_irq(unsigned long data)
- {
- 	unsigned long freq;
++#define USB_VENDOR_ID_GRETAGMACBETH	0x0971
++#define USB_DEVICE_ID_GRETAGMACBETH_HUEY	0x2005
++
+ #define USB_VENDOR_ID_GRIFFIN		0x077d
+ #define USB_DEVICE_ID_POWERMATE		0x0410
+ #define USB_DEVICE_ID_SOUNDKNOB		0x04AA
+@@ -278,7 +294,9 @@
+ #define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
+ #define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
+ #define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
++#define USB_DEVICE_ID_LOGITECH_EXTREME_3D	0xc215
+ #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
++#define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
+ #define USB_DEVICE_ID_LOGITECH_KBD	0xc311
+ #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
+ #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
+@@ -296,6 +314,12 @@
  
--	spin_lock_irq (&rtc_lock);
-+	spin_lock_irq(&rtc_lock);
+ #define USB_VENDOR_ID_MICROSOFT		0x045e
+ #define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
++#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
++#define USB_DEVICE_ID_MS_NE4K		0x00db
++#define USB_DEVICE_ID_MS_LK6K		0x00f9
++
++#define USB_VENDOR_ID_MONTEREY		0x0566
++#define USB_DEVICE_ID_GENIUS_KB29E	0x3004
  
- 	if (hpet_rtc_dropped_irq()) {
- 		spin_unlock_irq(&rtc_lock);
-@@ -1167,13 +1199,15 @@ static void rtc_dropped_irq(unsigned long data)
+ #define USB_VENDOR_ID_NCR		0x0404
+ #define USB_DEVICE_ID_NCR_FIRST		0x0300
+@@ -324,6 +348,9 @@
+ #define USB_VENDOR_ID_SAITEK		0x06a3
+ #define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
  
- 	spin_unlock_irq(&rtc_lock);
++#define USB_VENDOR_ID_SAMSUNG		0x0419
++#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
++
+ #define USB_VENDOR_ID_SONY			0x054c
+ #define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
  
--	if (printk_ratelimit())
--		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq);
-+	if (printk_ratelimit()) {
-+		printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
-+			freq);
-+	}
+@@ -368,6 +395,7 @@ static const struct hid_blacklist {
+ } hid_blacklist[] = {
  
- 	/* Now we have new data */
- 	wake_up_interruptible(&rtc_wait);
+ 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
++	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 },
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
  
--	kill_fasync (&rtc_async_queue, SIGIO, POLL_IN);
-+	kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
- }
- #endif
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
+@@ -390,6 +418,9 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
+ 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
  
-@@ -1277,7 +1311,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
- 	 * can take just over 2ms. We wait 20ms. There is no need to
- 	 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
- 	 * If you need to know *exactly* when a second has started, enable
--	 * periodic update complete interrupts, (via ioctl) and then 
-+	 * periodic update complete interrupts, (via ioctl) and then
- 	 * immediately read /dev/rtc which will block until you get the IRQ.
- 	 * Once the read clears, read the RTC time (again via ioctl). Easy.
- 	 */
-@@ -1307,8 +1341,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
- 	ctrl = CMOS_READ(RTC_CONTROL);
- 	spin_unlock_irqrestore(&rtc_lock, flags);
++	{ USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
++
++	{ USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
+@@ -402,6 +433,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
+ 	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
++	{ USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
+@@ -423,6 +455,7 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
++	{ USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
+@@ -516,14 +549,18 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
+ 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
  
--	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
--	{
-+	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- 		BCD_TO_BIN(rtc_tm->tm_sec);
- 		BCD_TO_BIN(rtc_tm->tm_min);
- 		BCD_TO_BIN(rtc_tm->tm_hour);
-@@ -1326,7 +1359,8 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
- 	 * Account for differences between how the RTC uses the values
- 	 * and how they are defined in a struct rtc_time;
- 	 */
--	if ((rtc_tm->tm_year += (epoch - 1900)) <= 69)
-+	rtc_tm->tm_year += epoch - 1900;
-+	if (rtc_tm->tm_year <= 69)
- 		rtc_tm->tm_year += 100;
++	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
  
- 	rtc_tm->tm_mon--;
-@@ -1347,8 +1381,7 @@ static void get_rtc_alm_time(struct rtc_time *alm_tm)
- 	ctrl = CMOS_READ(RTC_CONTROL);
- 	spin_unlock_irq(&rtc_lock);
++	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
++	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
++
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
  
--	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
--	{
-+	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
- 		BCD_TO_BIN(alm_tm->tm_sec);
- 		BCD_TO_BIN(alm_tm->tm_min);
- 		BCD_TO_BIN(alm_tm->tm_hour);
-diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
-index d222012..bacded0 100644
---- a/drivers/char/tty_audit.c
-+++ b/drivers/char/tty_audit.c
-@@ -73,6 +73,7 @@ static void tty_audit_buf_put(struct tty_audit_buf *buf)
-  *	@tsk with @loginuid.  @buf->mutex must be locked.
-  */
- static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
-+			       unsigned int sessionid,
- 			       struct tty_audit_buf *buf)
- {
- 	struct audit_buffer *ab;
-@@ -85,9 +86,9 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
- 	if (ab) {
- 		char name[sizeof(tsk->comm)];
+ 	{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
+ 	{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
  
--		audit_log_format(ab, "tty pid=%u uid=%u auid=%u major=%d "
--				 "minor=%d comm=", tsk->pid, tsk->uid,
--				 loginuid, buf->major, buf->minor);
-+		audit_log_format(ab, "tty pid=%u uid=%u auid=%u ses=%u "
-+				 "major=%d minor=%d comm=", tsk->pid, tsk->uid,
-+				 loginuid, sessionid, buf->major, buf->minor);
- 		get_task_comm(name, tsk);
- 		audit_log_untrustedstring(ab, name);
- 		audit_log_format(ab, " data=");
-@@ -105,8 +106,9 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid,
-  */
- static void tty_audit_buf_push_current(struct tty_audit_buf *buf)
- {
--	tty_audit_buf_push(current, audit_get_loginuid(current->audit_context),
--			   buf);
-+	uid_t auid = audit_get_loginuid(current);
-+	unsigned int sessionid = audit_get_sessionid(current);
-+	tty_audit_buf_push(current, auid, sessionid, buf);
- }
+-	{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
++	{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER | HID_QUIRK_HIDDEV },
  
- /**
-@@ -152,6 +154,11 @@ void tty_audit_fork(struct signal_struct *sig)
- void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
- {
- 	struct tty_audit_buf *buf;
-+	/* FIXME I think this is correct.  Check against netlink once that is
-+	 * I really need to read this code more closely.  But that's for
-+	 * another patch.
-+	 */
-+	unsigned int sessionid = audit_get_sessionid(tsk);
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
+@@ -531,7 +568,9 @@ static const struct hid_blacklist {
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
++	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
++	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
+ 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
+@@ -540,19 +579,22 @@ static const struct hid_blacklist {
  
- 	spin_lock_irq(&tsk->sighand->siglock);
- 	buf = tsk->signal->tty_audit_buf;
-@@ -162,7 +169,7 @@ void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
- 		return;
+ 	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
  
- 	mutex_lock(&buf->mutex);
--	tty_audit_buf_push(tsk, loginuid, buf);
-+	tty_audit_buf_push(tsk, loginuid, sessionid, buf);
- 	mutex_unlock(&buf->mutex);
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+-	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
++	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
  
- 	tty_audit_buf_put(buf);
-diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c
-index 12ceed5..5732ca3 100644
---- a/drivers/connector/cn_queue.c
-+++ b/drivers/connector/cn_queue.c
-@@ -104,7 +104,6 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id
- 		return -EINVAL;
- 	}
+ 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
+@@ -638,10 +680,14 @@ static const struct hid_rdesc_blacklist {
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
+ 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
  
--	cbq->nls = dev->nls;
- 	cbq->seq = 0;
- 	cbq->group = cbq->id.id.idx;
++	{ USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
++
+ 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
  
-@@ -146,7 +145,6 @@ struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
- 	spin_lock_init(&dev->queue_lock);
+ 	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
  
- 	dev->nls = nls;
--	dev->netlink_groups = 0;
++	{ USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
++
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+ 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
  
- 	dev->cn_queue = create_workqueue(dev->name);
- 	if (!dev->cn_queue) {
-diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
-index bf9716b..fea2d3e 100644
---- a/drivers/connector/connector.c
-+++ b/drivers/connector/connector.c
-@@ -88,6 +88,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, gfp_t gfp_mask)
- 			if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
- 				found = 1;
- 				group = __cbq->group;
-+				break;
- 			}
- 		}
- 		spin_unlock_bh(&dev->cbdev->queue_lock);
-@@ -181,33 +182,14 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v
+@@ -884,6 +930,8 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
+ 	return quirks;
  }
  
++EXPORT_SYMBOL_GPL(usbhid_lookup_quirk);
++
  /*
-- * Skb receive helper - checks skb and msg size and calls callback
-- * helper.
-- */
--static int __cn_rx_skb(struct sk_buff *skb, struct nlmsghdr *nlh)
--{
--	u32 pid, uid, seq, group;
--	struct cn_msg *msg;
--
--	pid = NETLINK_CREDS(skb)->pid;
--	uid = NETLINK_CREDS(skb)->uid;
--	seq = nlh->nlmsg_seq;
--	group = NETLINK_CB((skb)).dst_group;
--	msg = NLMSG_DATA(nlh);
--
--	return cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
--}
--
--/*
-  * Main netlink receiving function.
-  *
-- * It checks skb and netlink header sizes and calls the skb receive
-- * helper with a shared skb.
-+ * It checks skb, netlink header and msg sizes, and calls callback helper.
-  */
- static void cn_rx_skb(struct sk_buff *__skb)
- {
-+	struct cn_msg *msg;
- 	struct nlmsghdr *nlh;
--	u32 len;
- 	int err;
- 	struct sk_buff *skb;
- 
-@@ -223,11 +205,8 @@ static void cn_rx_skb(struct sk_buff *__skb)
- 			return;
- 		}
- 
--		len = NLMSG_ALIGN(nlh->nlmsg_len);
--		if (len > skb->len)
--			len = skb->len;
--
--		err = __cn_rx_skb(skb, nlh);
-+		msg = NLMSG_DATA(nlh);
-+		err = cn_call_callback(msg, (void (*)(void *))kfree_skb, skb);
- 		if (err < 0)
- 			kfree_skb(skb);
+  * Cherry Cymotion keyboard have an invalid HID report descriptor,
+  * that needs fixing before we can parse it.
+@@ -914,6 +962,33 @@ static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
  	}
-@@ -441,8 +420,7 @@ static int __devinit cn_init(void)
+ }
  
- 	dev->cbdev = cn_queue_alloc_dev("cqueue", dev->nls);
- 	if (!dev->cbdev) {
--		if (dev->nls->sk_socket)
--			sock_release(dev->nls->sk_socket);
-+		netlink_kernel_release(dev->nls);
- 		return -EINVAL;
- 	}
- 	
-@@ -452,8 +430,7 @@ static int __devinit cn_init(void)
- 	if (err) {
- 		cn_already_initialized = 0;
- 		cn_queue_free_dev(dev->cbdev);
--		if (dev->nls->sk_socket)
--			sock_release(dev->nls->sk_socket);
-+		netlink_kernel_release(dev->nls);
- 		return -EINVAL;
++/*
++ * Samsung IrDA remote controller (reports as Cypress USB Mouse).
++ *
++ * Vendor specific report #4 has a size of 48 bit,
++ * and therefore is not accepted when inspecting the descriptors.
++ * As a workaround we reinterpret the report as:
++ *   Variable type, count 6, size 8 bit, log. maximum 255
++ * The burden to reconstruct the data is moved into user space.
++ */
++static void usbhid_fixup_samsung_irda_descriptor(unsigned char *rdesc,
++						  int rsize)
++{
++	if (rsize >= 182 && rdesc[175] == 0x25
++			 && rdesc[176] == 0x40
++			 && rdesc[177] == 0x75
++			 && rdesc[178] == 0x30
++			 && rdesc[179] == 0x95
++			 && rdesc[180] == 0x01
++			 && rdesc[182] == 0x40) {
++		printk(KERN_INFO "Fixing up Samsung IrDA report descriptor\n");
++		rdesc[176] = 0xff;
++		rdesc[178] = 0x08;
++		rdesc[180] = 0x06;
++		rdesc[182] = 0x42;
++	}
++}
++
+ /* Petalynx Maxter Remote has maximum for consumer page set too low */
+ static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+ {
+@@ -965,6 +1040,14 @@ static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
  	}
+ }
  
-@@ -468,8 +445,7 @@ static void __devexit cn_fini(void)
++static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize)
++{
++	if (rsize >= 30 && rdesc[29] == 0x05
++			&& rdesc[30] == 0x09) {
++		printk(KERN_INFO "Fixing up button/consumer in HID report descriptor\n");
++		rdesc[30] = 0x0c;
++	}
++}
  
- 	cn_del_callback(&dev->id);
- 	cn_queue_free_dev(dev->cbdev);
--	if (dev->nls->sk_socket)
--		sock_release(dev->nls->sk_socket);
-+	netlink_kernel_release(dev->nls);
+ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+ {
+@@ -982,6 +1065,13 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
+ 
+ 	if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
+ 		usbhid_fixup_macbook_descriptor(rdesc, rsize);
++
++	if (quirks & HID_QUIRK_RDESC_BUTTON_CONSUMER)
++		usbhid_fixup_button_consumer_descriptor(rdesc, rsize);
++
++	if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
++		usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
++
  }
  
- subsys_initcall(cn_init);
-diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
-index 79581fa..b730d67 100644
---- a/drivers/cpufreq/cpufreq.c
-+++ b/drivers/cpufreq/cpufreq.c
-@@ -828,11 +828,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
- 	memcpy(&new_policy, policy, sizeof(struct cpufreq_policy));
+ /**
+diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
+index 69882a7..144578b 100644
+--- a/drivers/hid/usbhid/hid-tmff.c
++++ b/drivers/hid/usbhid/hid-tmff.c
+@@ -137,7 +137,8 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
+ int hid_tmff_init(struct hid_device *hid)
+ {
+ 	struct tmff_device *tmff;
+-	struct list_head *pos;
++	struct hid_report *report;
++	struct list_head *report_list;
+ 	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
+ 	struct input_dev *input_dev = hidinput->input;
+ 	const signed short *ff_bits = ff_joystick;
+@@ -149,8 +150,8 @@ int hid_tmff_init(struct hid_device *hid)
+ 		return -ENOMEM;
  
- 	/* prepare interface data */
--	policy->kobj.parent = &sys_dev->kobj;
--	policy->kobj.ktype = &ktype_cpufreq;
--	kobject_set_name(&policy->kobj, "cpufreq");
--
--	ret = kobject_register(&policy->kobj);
-+	ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj,
-+				   "cpufreq");
- 	if (ret) {
- 		unlock_policy_rwsem_write(cpu);
- 		goto err_out_driver_exit;
-@@ -902,6 +899,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev)
- 		goto err_out_unregister;
- 	}
+ 	/* Find the report to use */
+-	list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
+-		struct hid_report *report = (struct hid_report *)pos;
++	report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
++	list_for_each_entry(report, report_list, list) {
+ 		int fieldnum;
+ 
+ 		for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
+diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
+index 775a1ef..5d9dbb4 100644
+--- a/drivers/hid/usbhid/usbkbd.c
++++ b/drivers/hid/usbhid/usbkbd.c
+@@ -235,6 +235,14 @@ static int usb_kbd_probe(struct usb_interface *iface,
+ 	if (!usb_endpoint_is_int_in(endpoint))
+ 		return -ENODEV;
  
-+	kobject_uevent(&policy->kobj, KOBJ_ADD);
- 	module_put(cpufreq_driver->owner);
- 	dprintk("initialization complete\n");
- 	cpufreq_debug_enable_ratelimit();
-@@ -915,7 +913,7 @@ err_out_unregister:
- 		cpufreq_cpu_data[j] = NULL;
- 	spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
++#ifdef CONFIG_USB_HID
++	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
++				le16_to_cpu(dev->descriptor.idProduct))
++			& HID_QUIRK_IGNORE) {
++		return -ENODEV;
++	}
++#endif
++
+ 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+ 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
  
--	kobject_unregister(&policy->kobj);
-+	kobject_put(&policy->kobj);
- 	wait_for_completion(&policy->kobj_unregister);
+diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
+index f8ad691..df0d96d 100644
+--- a/drivers/hid/usbhid/usbmouse.c
++++ b/drivers/hid/usbhid/usbmouse.c
+@@ -131,6 +131,14 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
+ 	if (!usb_endpoint_is_int_in(endpoint))
+ 		return -ENODEV;
  
- err_out_driver_exit:
-@@ -1032,8 +1030,6 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev)
++#ifdef CONFIG_USB_HID
++	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
++				le16_to_cpu(dev->descriptor.idProduct))
++			& (HID_QUIRK_IGNORE|HID_QUIRK_IGNORE_MOUSE)) {
++		return -ENODEV;
++	}
++#endif
++
+ 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
+ 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
  
- 	unlock_policy_rwsem_write(cpu);
+diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
+index a37cb6b..3581282 100644
+--- a/drivers/i2c/algos/i2c-algo-bit.c
++++ b/drivers/i2c/algos/i2c-algo-bit.c
+@@ -1,7 +1,7 @@
+-/* ------------------------------------------------------------------------- */
+-/* i2c-algo-bit.c i2c driver algorithms for bit-shift adapters		     */
+-/* ------------------------------------------------------------------------- */
+-/*   Copyright (C) 1995-2000 Simon G. Vogl
++/* -------------------------------------------------------------------------
++ * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters
++ * -------------------------------------------------------------------------
++ *   Copyright (C) 1995-2000 Simon G. Vogl
  
--	kobject_unregister(&data->kobj);
--
- 	kobject_put(&data->kobj);
+     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
+@@ -15,8 +15,8 @@
  
- 	/* we need to make sure that the underlying kobj is actually
-@@ -1608,7 +1604,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data,
- 	memcpy(&policy->cpuinfo, &data->cpuinfo,
- 				sizeof(struct cpufreq_cpuinfo));
+     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.		     */
+-/* ------------------------------------------------------------------------- */
++    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ * ------------------------------------------------------------------------- */
  
--	if (policy->min > data->min && policy->min > policy->max) {
-+	if (policy->min > data->max || policy->max < data->min) {
- 		ret = -EINVAL;
- 		goto error_out;
- 	}
-diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
-index 0f3515e..088ea74 100644
---- a/drivers/cpuidle/sysfs.c
-+++ b/drivers/cpuidle/sysfs.c
-@@ -277,7 +277,7 @@ static struct kobj_type ktype_state_cpuidle = {
+ /* With some changes from Frodo Looijaard <frodol at dds.nl>, Kyösti Mälkki
+    <kmalkki at cc.hut.fi> and Jean Delvare <khali at linux-fr.org> */
+@@ -60,26 +60,26 @@ MODULE_PARM_DESC(i2c_debug,
  
- static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
- {
--	kobject_unregister(&device->kobjs[i]->kobj);
-+	kobject_put(&device->kobjs[i]->kobj);
- 	wait_for_completion(&device->kobjs[i]->kobj_unregister);
- 	kfree(device->kobjs[i]);
- 	device->kobjs[i] = NULL;
-@@ -300,14 +300,13 @@ int cpuidle_add_state_sysfs(struct cpuidle_device *device)
- 		kobj->state = &device->states[i];
- 		init_completion(&kobj->kobj_unregister);
+ /* --- setting states on the bus with the right timing: ---------------	*/
  
--		kobj->kobj.parent = &device->kobj;
--		kobj->kobj.ktype = &ktype_state_cpuidle;
--		kobject_set_name(&kobj->kobj, "state%d", i);
--		ret = kobject_register(&kobj->kobj);
-+		ret = kobject_init_and_add(&kobj->kobj, &ktype_state_cpuidle, &device->kobj,
-+					   "state%d", i);
- 		if (ret) {
- 			kfree(kobj);
- 			goto error_state;
- 		}
-+		kobject_uevent(&kobj->kobj, KOBJ_ADD);
- 		device->kobjs[i] = kobj;
- 	}
+-#define setsda(adap,val) adap->setsda(adap->data, val)
+-#define setscl(adap,val) adap->setscl(adap->data, val)
+-#define getsda(adap) adap->getsda(adap->data)
+-#define getscl(adap) adap->getscl(adap->data)
++#define setsda(adap, val)	adap->setsda(adap->data, val)
++#define setscl(adap, val)	adap->setscl(adap->data, val)
++#define getsda(adap)		adap->getsda(adap->data)
++#define getscl(adap)		adap->getscl(adap->data)
  
-@@ -339,12 +338,14 @@ int cpuidle_add_sysfs(struct sys_device *sysdev)
+ static inline void sdalo(struct i2c_algo_bit_data *adap)
  {
- 	int cpu = sysdev->id;
- 	struct cpuidle_device *dev;
-+	int error;
- 
- 	dev = per_cpu(cpuidle_devices, cpu);
--	dev->kobj.parent = &sysdev->kobj;
--	dev->kobj.ktype = &ktype_cpuidle;
--	kobject_set_name(&dev->kobj, "%s", "cpuidle");
--	return kobject_register(&dev->kobj);
-+	error = kobject_init_and_add(&dev->kobj, &ktype_cpuidle, &sysdev->kobj,
-+				     "cpuidle");
-+	if (!error)
-+		kobject_uevent(&dev->kobj, KOBJ_ADD);
-+	return error;
+-	setsda(adap,0);
++	setsda(adap, 0);
+ 	udelay((adap->udelay + 1) / 2);
  }
  
- /**
-@@ -357,5 +358,5 @@ void cpuidle_remove_sysfs(struct sys_device *sysdev)
- 	struct cpuidle_device *dev;
- 
- 	dev = per_cpu(cpuidle_devices, cpu);
--	kobject_unregister(&dev->kobj);
-+	kobject_put(&dev->kobj);
+ static inline void sdahi(struct i2c_algo_bit_data *adap)
+ {
+-	setsda(adap,1);
++	setsda(adap, 1);
+ 	udelay((adap->udelay + 1) / 2);
  }
-diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
-index ddd3a25..6b658d8 100644
---- a/drivers/crypto/Kconfig
-+++ b/drivers/crypto/Kconfig
-@@ -48,8 +48,6 @@ config CRYPTO_DEV_PADLOCK_SHA
- 	  If unsure say M. The compiled module will be
- 	  called padlock-sha.ko
  
--source "arch/s390/crypto/Kconfig"
--
- config CRYPTO_DEV_GEODE
- 	tristate "Support for the Geode LX AES engine"
- 	depends on X86_32 && PCI
-@@ -83,4 +81,82 @@ config ZCRYPT_MONOLITHIC
- 	  that contains all parts of the crypto device driver (ap bus,
- 	  request router and all the card drivers).
+ static inline void scllo(struct i2c_algo_bit_data *adap)
+ {
+-	setscl(adap,0);
++	setscl(adap, 0);
+ 	udelay(adap->udelay / 2);
+ }
  
-+config CRYPTO_SHA1_S390
-+	tristate "SHA1 digest algorithm"
-+	depends on S390
-+	select CRYPTO_ALGAPI
-+	help
-+	  This is the s390 hardware accelerated implementation of the
-+	  SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2).
-+
-+config CRYPTO_SHA256_S390
-+	tristate "SHA256 digest algorithm"
-+	depends on S390
-+	select CRYPTO_ALGAPI
-+	help
-+	  This is the s390 hardware accelerated implementation of the
-+	  SHA256 secure hash standard (DFIPS 180-2).
-+
-+	  This version of SHA implements a 256 bit hash with 128 bits of
-+	  security against collision attacks.
-+
-+config CRYPTO_DES_S390
-+	tristate "DES and Triple DES cipher algorithms"
-+	depends on S390
-+	select CRYPTO_ALGAPI
-+	select CRYPTO_BLKCIPHER
-+	help
-+	  This us the s390 hardware accelerated implementation of the
-+	  DES cipher algorithm (FIPS 46-2), and Triple DES EDE (FIPS 46-3).
-+
-+config CRYPTO_AES_S390
-+	tristate "AES cipher algorithms"
-+	depends on S390
-+	select CRYPTO_ALGAPI
-+	select CRYPTO_BLKCIPHER
-+	help
-+	  This is the s390 hardware accelerated implementation of the
-+	  AES cipher algorithms (FIPS-197). AES uses the Rijndael
-+	  algorithm.
-+
-+	  Rijndael appears to be consistently a very good performer in
-+	  both hardware and software across a wide range of computing
-+	  environments regardless of its use in feedback or non-feedback
-+	  modes. Its key setup time is excellent, and its key agility is
-+	  good. Rijndael's very low memory requirements make it very well
-+	  suited for restricted-space environments, in which it also
-+	  demonstrates excellent performance. Rijndael's operations are
-+	  among the easiest to defend against power and timing attacks.
-+
-+	  On s390 the System z9-109 currently only supports the key size
-+	  of 128 bit.
-+
-+config S390_PRNG
-+	tristate "Pseudo random number generator device driver"
-+	depends on S390
-+	default "m"
-+	help
-+	  Select this option if you want to use the s390 pseudo random number
-+	  generator. The PRNG is part of the cryptographic processor functions
-+	  and uses triple-DES to generate secure random numbers like the
-+	  ANSI X9.17 standard. The PRNG is usable via the char device
-+	  /dev/prandom.
-+
-+config CRYPTO_DEV_HIFN_795X
-+	tristate "Driver HIFN 795x crypto accelerator chips"
-+	select CRYPTO_DES
-+	select CRYPTO_ALGAPI
-+	select CRYPTO_BLKCIPHER
-+	select HW_RANDOM if CRYPTO_DEV_HIFN_795X_RNG
-+	depends on PCI
-+	help
-+	  This option allows you to have support for HIFN 795x crypto adapters.
-+
-+config CRYPTO_DEV_HIFN_795X_RNG
-+	bool "HIFN 795x random number generator"
-+	depends on CRYPTO_DEV_HIFN_795X
-+	help
-+	  Select this option if you want to enable the random number generator
-+	  on the HIFN 795x crypto adapters.
-+
- endif # CRYPTO_HW
-diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
-index d070030..c0327f0 100644
---- a/drivers/crypto/Makefile
-+++ b/drivers/crypto/Makefile
-@@ -1,3 +1,4 @@
- obj-$(CONFIG_CRYPTO_DEV_PADLOCK_AES) += padlock-aes.o
- obj-$(CONFIG_CRYPTO_DEV_PADLOCK_SHA) += padlock-sha.o
- obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
-+obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
-diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
-index 711e246..4801162 100644
---- a/drivers/crypto/geode-aes.c
-+++ b/drivers/crypto/geode-aes.c
-@@ -13,44 +13,13 @@
- #include <linux/crypto.h>
- #include <linux/spinlock.h>
- #include <crypto/algapi.h>
-+#include <crypto/aes.h>
+@@ -91,22 +91,21 @@ static int sclhi(struct i2c_algo_bit_data *adap)
+ {
+ 	unsigned long start;
  
- #include <asm/io.h>
- #include <asm/delay.h>
+-	setscl(adap,1);
++	setscl(adap, 1);
  
- #include "geode-aes.h"
+ 	/* Not all adapters have scl sense line... */
+ 	if (!adap->getscl)
+ 		goto done;
  
--/* Register definitions */
--
--#define AES_CTRLA_REG  0x0000
--
--#define AES_CTRL_START     0x01
--#define AES_CTRL_DECRYPT   0x00
--#define AES_CTRL_ENCRYPT   0x02
--#define AES_CTRL_WRKEY     0x04
--#define AES_CTRL_DCA       0x08
--#define AES_CTRL_SCA       0x10
--#define AES_CTRL_CBC       0x20
--
--#define AES_INTR_REG  0x0008
--
--#define AES_INTRA_PENDING (1 << 16)
--#define AES_INTRB_PENDING (1 << 17)
--
--#define AES_INTR_PENDING  (AES_INTRA_PENDING | AES_INTRB_PENDING)
--#define AES_INTR_MASK     0x07
--
--#define AES_SOURCEA_REG   0x0010
--#define AES_DSTA_REG      0x0014
--#define AES_LENA_REG      0x0018
--#define AES_WRITEKEY0_REG 0x0030
--#define AES_WRITEIV0_REG  0x0040
--
--/*  A very large counter that is used to gracefully bail out of an
-- *  operation in case of trouble
-- */
--
--#define AES_OP_TIMEOUT    0x50000
--
- /* Static structures */
+-	start=jiffies;
+-	while (! getscl(adap) ) {	
+- 		/* the hw knows how to read the clock line,
+- 		 * so we wait until it actually gets high.
+- 		 * This is safer as some chips may hold it low
+- 		 * while they are processing data internally. 
+- 		 */
+-		if (time_after_eq(jiffies, start+adap->timeout)) {
++	start = jiffies;
++	while (!getscl(adap)) {
++		/* This hw knows how to read the clock line, so we wait
++		 * until it actually gets high.  This is safer as some
++		 * chips may hold it low ("clock stretching") while they
++		 * are processing data internally.
++		 */
++		if (time_after_eq(jiffies, start + adap->timeout))
+ 			return -ETIMEDOUT;
+-		}
+ 		cond_resched();
+ 	}
+ #ifdef DEBUG
+@@ -118,11 +117,11 @@ static int sclhi(struct i2c_algo_bit_data *adap)
+ done:
+ 	udelay(adap->udelay);
+ 	return 0;
+-} 
++}
  
- static void __iomem * _iobase;
-@@ -87,9 +56,10 @@ do_crypt(void *src, void *dst, int len, u32 flags)
- 	/* Start the operation */
- 	iowrite32(AES_CTRL_START | flags, _iobase + AES_CTRLA_REG);
  
--	do
-+	do {
- 		status = ioread32(_iobase + AES_INTR_REG);
--	while(!(status & AES_INTRA_PENDING) && --counter);
-+		cpu_relax();
-+	} while(!(status & AES_INTRA_PENDING) && --counter);
+ /* --- other auxiliary functions --------------------------------------	*/
+-static void i2c_start(struct i2c_algo_bit_data *adap) 
++static void i2c_start(struct i2c_algo_bit_data *adap)
+ {
+ 	/* assert: scl, sda are high */
+ 	setsda(adap, 0);
+@@ -130,7 +129,7 @@ static void i2c_start(struct i2c_algo_bit_data *adap)
+ 	scllo(adap);
+ }
  
- 	/* Clear the event */
- 	iowrite32((status & 0xFF) | AES_INTRA_PENDING, _iobase + AES_INTR_REG);
-@@ -101,6 +71,7 @@ geode_aes_crypt(struct geode_aes_op *op)
+-static void i2c_repstart(struct i2c_algo_bit_data *adap) 
++static void i2c_repstart(struct i2c_algo_bit_data *adap)
  {
- 	u32 flags = 0;
- 	unsigned long iflags;
-+	int ret;
+ 	/* assert: scl is low */
+ 	sdahi(adap);
+@@ -141,18 +140,18 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
+ }
  
- 	if (op->len == 0)
- 		return 0;
-@@ -129,7 +100,8 @@ geode_aes_crypt(struct geode_aes_op *op)
- 		_writefield(AES_WRITEKEY0_REG, op->key);
- 	}
  
--	do_crypt(op->src, op->dst, op->len, flags);
-+	ret = do_crypt(op->src, op->dst, op->len, flags);
-+	BUG_ON(ret);
+-static void i2c_stop(struct i2c_algo_bit_data *adap) 
++static void i2c_stop(struct i2c_algo_bit_data *adap)
+ {
+ 	/* assert: scl is low */
+ 	sdalo(adap);
+-	sclhi(adap); 
++	sclhi(adap);
+ 	setsda(adap, 1);
+ 	udelay(adap->udelay);
+ }
  
- 	if (op->mode == AES_MODE_CBC)
- 		_readfield(AES_WRITEIV0_REG, op->iv);
-@@ -141,18 +113,103 @@ geode_aes_crypt(struct geode_aes_op *op)
  
- /* CRYPTO-API Functions */
  
--static int
--geode_setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int len)
-+static int geode_setkey_cip(struct crypto_tfm *tfm, const u8 *key,
-+		unsigned int len)
- {
- 	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
-+	unsigned int ret;
+-/* send a byte without start cond., look for arbitration, 
++/* send a byte without start cond., look for arbitration,
+    check ackn. from slave */
+ /* returns:
+  * 1 if the device acknowledged
+@@ -167,27 +166,33 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
+ 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
  
--	if (len != AES_KEY_LENGTH) {
-+	op->keylen = len;
-+
-+	if (len == AES_KEYSIZE_128) {
-+		memcpy(op->key, key, len);
-+		return 0;
-+	}
-+
-+	if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
-+		/* not supported at all */
- 		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
- 		return -EINVAL;
+ 	/* assert: scl is low */
+-	for ( i=7 ; i>=0 ; i-- ) {
++	for (i = 7; i >= 0; i--) {
+ 		sb = (c >> i) & 1;
+-		setsda(adap,sb);
++		setsda(adap, sb);
+ 		udelay((adap->udelay + 1) / 2);
+-		if (sclhi(adap)<0) { /* timed out */
++		if (sclhi(adap) < 0) { /* timed out */
+ 			bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+ 				"timeout at bit #%d\n", (int)c, i);
+ 			return -ETIMEDOUT;
+-		};
+-		/* do arbitration here: 
+-		 * if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
++		}
++		/* FIXME do arbitration here:
++		 * if (sb && !getsda(adap)) -> ouch! Get out of here.
++		 *
++		 * Report a unique code, so higher level code can retry
++		 * the whole (combined) message and *NOT* issue STOP.
+ 		 */
+ 		scllo(adap);
  	}
- 
--	memcpy(op->key, key, len);
--	return 0;
-+	/*
-+	 * The requested key size is not supported by HW, do a fallback
-+	 */
-+	op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
-+	op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
-+
-+	ret = crypto_cipher_setkey(op->fallback.cip, key, len);
-+	if (ret) {
-+		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
-+		tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
-+	}
-+	return ret;
-+}
-+
-+static int geode_setkey_blk(struct crypto_tfm *tfm, const u8 *key,
-+		unsigned int len)
-+{
-+	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
-+	unsigned int ret;
-+
-+	op->keylen = len;
-+
-+	if (len == AES_KEYSIZE_128) {
-+		memcpy(op->key, key, len);
-+		return 0;
-+	}
-+
-+	if (len != AES_KEYSIZE_192 && len != AES_KEYSIZE_256) {
-+		/* not supported at all */
-+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
-+		return -EINVAL;
+ 	sdahi(adap);
+-	if (sclhi(adap)<0){ /* timeout */
++	if (sclhi(adap) < 0) { /* timeout */
+ 		bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
+ 			"timeout at ack\n", (int)c);
+ 		return -ETIMEDOUT;
+-	};
+-	/* read ack: SDA should be pulled down by slave */
 +	}
 +
-+	/*
-+	 * The requested key size is not supported by HW, do a fallback
++	/* read ack: SDA should be pulled down by slave, or it may
++	 * NAK (usually to report problems with the data we wrote).
 +	 */
-+	op->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
-+	op->fallback.blk->base.crt_flags |= (tfm->crt_flags & CRYPTO_TFM_REQ_MASK);
-+
-+	ret = crypto_blkcipher_setkey(op->fallback.blk, key, len);
-+	if (ret) {
-+		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
-+		tfm->crt_flags |= (op->fallback.blk->base.crt_flags & CRYPTO_TFM_RES_MASK);
-+	}
-+	return ret;
-+}
-+
-+static int fallback_blk_dec(struct blkcipher_desc *desc,
-+		struct scatterlist *dst, struct scatterlist *src,
-+		unsigned int nbytes)
-+{
-+	unsigned int ret;
-+	struct crypto_blkcipher *tfm;
-+	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-+
-+	tfm = desc->tfm;
-+	desc->tfm = op->fallback.blk;
-+
-+	ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
-+
-+	desc->tfm = tfm;
-+	return ret;
-+}
-+static int fallback_blk_enc(struct blkcipher_desc *desc,
-+		struct scatterlist *dst, struct scatterlist *src,
-+		unsigned int nbytes)
-+{
-+	unsigned int ret;
-+	struct crypto_blkcipher *tfm;
-+	struct geode_aes_op *op = crypto_blkcipher_ctx(desc->tfm);
-+
-+	tfm = desc->tfm;
-+	desc->tfm = op->fallback.blk;
-+
-+	ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
-+
-+	desc->tfm = tfm;
-+	return ret;
+ 	ack = !getsda(adap);    /* ack: sda is pulled low -> success */
+ 	bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
+ 		ack ? "A" : "NA");
+@@ -198,24 +203,24 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
  }
  
- static void
-@@ -160,8 +217,10 @@ geode_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ 
+-static int i2c_inb(struct i2c_adapter *i2c_adap) 
++static int i2c_inb(struct i2c_adapter *i2c_adap)
  {
- 	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+ 	/* read byte via i2c port, without start/stop sequence	*/
+ 	/* acknowledge is sent in i2c_read.			*/
+ 	int i;
+-	unsigned char indata=0;
++	unsigned char indata = 0;
+ 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
  
--	if ((out == NULL) || (in == NULL))
-+	if (unlikely(op->keylen != AES_KEYSIZE_128)) {
-+		crypto_cipher_encrypt_one(op->fallback.cip, out, in);
- 		return;
-+	}
+ 	/* assert: scl is low */
+ 	sdahi(adap);
+-	for (i=0;i<8;i++) {
+-		if (sclhi(adap)<0) { /* timeout */
++	for (i = 0; i < 8; i++) {
++		if (sclhi(adap) < 0) { /* timeout */
+ 			bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
+ 				"#%d\n", 7 - i);
+ 			return -ETIMEDOUT;
+-		};
++		}
+ 		indata *= 2;
+-		if ( getsda(adap) ) 
++		if (getsda(adap))
+ 			indata |= 0x01;
+ 		setscl(adap, 0);
+ 		udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
+@@ -228,66 +233,67 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
+  * Sanity check for the adapter hardware - check the reaction of
+  * the bus lines only if it seems to be idle.
+  */
+-static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
+-	int scl,sda;
++static int test_bus(struct i2c_algo_bit_data *adap, char *name)
++{
++	int scl, sda;
  
- 	op->src = (void *) in;
- 	op->dst = (void *) out;
-@@ -179,8 +238,10 @@ geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- {
- 	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+-	if (adap->getscl==NULL)
++	if (adap->getscl == NULL)
+ 		pr_info("%s: Testing SDA only, SCL is not readable\n", name);
  
--	if ((out == NULL) || (in == NULL))
-+	if (unlikely(op->keylen != AES_KEYSIZE_128)) {
-+		crypto_cipher_decrypt_one(op->fallback.cip, out, in);
- 		return;
+-	sda=getsda(adap);
+-	scl=(adap->getscl==NULL?1:getscl(adap));
+-	if (!scl || !sda ) {
++	sda = getsda(adap);
++	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
++	if (!scl || !sda) {
+ 		printk(KERN_WARNING "%s: bus seems to be busy\n", name);
+ 		goto bailout;
+ 	}
+ 
+ 	sdalo(adap);
+-	sda=getsda(adap);
+-	scl=(adap->getscl==NULL?1:getscl(adap));
+-	if ( 0 != sda ) {
++	sda = getsda(adap);
++	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
++	if (sda) {
+ 		printk(KERN_WARNING "%s: SDA stuck high!\n", name);
+ 		goto bailout;
+ 	}
+-	if ( 0 == scl ) {
++	if (!scl) {
+ 		printk(KERN_WARNING "%s: SCL unexpected low "
+ 		       "while pulling SDA low!\n", name);
+ 		goto bailout;
+-	}		
 +	}
  
- 	op->src = (void *) in;
- 	op->dst = (void *) out;
-@@ -192,24 +253,50 @@ geode_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- 	geode_aes_crypt(op);
- }
+ 	sdahi(adap);
+-	sda=getsda(adap);
+-	scl=(adap->getscl==NULL?1:getscl(adap));
+-	if ( 0 == sda ) {
++	sda = getsda(adap);
++	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
++	if (!sda) {
+ 		printk(KERN_WARNING "%s: SDA stuck low!\n", name);
+ 		goto bailout;
+ 	}
+-	if ( 0 == scl ) {
++	if (!scl) {
+ 		printk(KERN_WARNING "%s: SCL unexpected low "
+ 		       "while pulling SDA high!\n", name);
+ 		goto bailout;
+ 	}
  
-+static int fallback_init_cip(struct crypto_tfm *tfm)
-+{
-+	const char *name = tfm->__crt_alg->cra_name;
-+	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
+ 	scllo(adap);
+-	sda=getsda(adap);
+-	scl=(adap->getscl==NULL?0:getscl(adap));
+-	if ( 0 != scl ) {
++	sda = getsda(adap);
++	scl = (adap->getscl == NULL) ? 0 : getscl(adap);
++	if (scl) {
+ 		printk(KERN_WARNING "%s: SCL stuck high!\n", name);
+ 		goto bailout;
+ 	}
+-	if ( 0 == sda ) {
++	if (!sda) {
+ 		printk(KERN_WARNING "%s: SDA unexpected low "
+ 		       "while pulling SCL low!\n", name);
+ 		goto bailout;
+ 	}
+-	
 +
-+	op->fallback.cip = crypto_alloc_cipher(name, 0,
-+				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+ 	sclhi(adap);
+-	sda=getsda(adap);
+-	scl=(adap->getscl==NULL?1:getscl(adap));
+-	if ( 0 == scl ) {
++	sda = getsda(adap);
++	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
++	if (!scl) {
+ 		printk(KERN_WARNING "%s: SCL stuck low!\n", name);
+ 		goto bailout;
+ 	}
+-	if ( 0 == sda ) {
++	if (!sda) {
+ 		printk(KERN_WARNING "%s: SDA unexpected low "
+ 		       "while pulling SCL high!\n", name);
+ 		goto bailout;
+@@ -314,9 +320,10 @@ static int try_address(struct i2c_adapter *i2c_adap,
+ 		       unsigned char addr, int retries)
+ {
+ 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+-	int i,ret = -1;
+-	for (i=0;i<=retries;i++) {
+-		ret = i2c_outb(i2c_adap,addr);
++	int i, ret = -1;
 +
-+	if (IS_ERR(op->fallback.cip)) {
-+		printk(KERN_ERR "Error allocating fallback algo %s\n", name);
-+		return PTR_ERR(op->fallback.blk);
-+	}
++	for (i = 0; i <= retries; i++) {
++		ret = i2c_outb(i2c_adap, addr);
+ 		if (ret == 1 || i == retries)
+ 			break;
+ 		bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
+@@ -338,20 +345,38 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+ {
+ 	const unsigned char *temp = msg->buf;
+ 	int count = msg->len;
+-	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
++	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
+ 	int retval;
+-	int wrcount=0;
++	int wrcount = 0;
+ 
+ 	while (count > 0) {
+ 		retval = i2c_outb(i2c_adap, *temp);
+-		if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */
+-			count--; 
 +
-+	return 0;
-+}
++		/* OK/ACK; or ignored NAK */
++		if ((retval > 0) || (nak_ok && (retval == 0))) {
++			count--;
+ 			temp++;
+ 			wrcount++;
+-		} else { /* arbitration or no acknowledge */
+-			dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
+-			return (retval<0)? retval : -EFAULT;
+-			        /* got a better one ?? */
 +
-+static void fallback_exit_cip(struct crypto_tfm *tfm)
-+{
-+	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
++		/* A slave NAKing the master means the slave didn't like
++		 * something about the data it saw.  For example, maybe
++		 * the SMBus PEC was wrong.
++		 */
++		} else if (retval == 0) {
++			dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n");
++			return -EIO;
 +
-+	crypto_free_cipher(op->fallback.cip);
-+	op->fallback.cip = NULL;
-+}
- 
- static struct crypto_alg geode_alg = {
--	.cra_name               =       "aes",
--	.cra_driver_name	=       "geode-aes-128",
--	.cra_priority           =       300,
--	.cra_alignmask          =       15,
--	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
-+	.cra_name			=	"aes",
-+	.cra_driver_name	=	"geode-aes",
-+	.cra_priority		=	300,
-+	.cra_alignmask		=	15,
-+	.cra_flags			=	CRYPTO_ALG_TYPE_CIPHER |
-+							CRYPTO_ALG_NEED_FALLBACK,
-+	.cra_init			=	fallback_init_cip,
-+	.cra_exit			=	fallback_exit_cip,
- 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
- 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
--	.cra_module		=	THIS_MODULE,
--	.cra_list		=	LIST_HEAD_INIT(geode_alg.cra_list),
--	.cra_u			=	{
--		.cipher = {
--			.cia_min_keysize	=  AES_KEY_LENGTH,
--			.cia_max_keysize	=  AES_KEY_LENGTH,
--			.cia_setkey		=  geode_setkey,
--			.cia_encrypt		=  geode_encrypt,
--			.cia_decrypt		=  geode_decrypt
-+	.cra_module			=	THIS_MODULE,
-+	.cra_list			=	LIST_HEAD_INIT(geode_alg.cra_list),
-+	.cra_u				=	{
-+		.cipher	=	{
-+			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
-+			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
-+			.cia_setkey			=	geode_setkey_cip,
-+			.cia_encrypt		=	geode_encrypt,
-+			.cia_decrypt		=	geode_decrypt
++		/* Timeout; or (someday) lost arbitration
++		 *
++		 * FIXME Lost ARB implies retrying the transaction from
++		 * the first message, after the "winning" master issues
++		 * its STOP.  As a rule, upper layer code has no reason
++		 * to know or care about this ... it is *NOT* an error.
++		 */
++		} else {
++			dev_err(&i2c_adap->dev, "sendbytes: error %d\n",
++					retval);
++			return retval;
  		}
  	}
- };
-@@ -223,8 +310,12 @@ geode_cbc_decrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err, ret;
+ 	return wrcount;
+@@ -376,14 +401,14 @@ static int acknak(struct i2c_adapter *i2c_adap, int is_ack)
+ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+ {
+ 	int inval;
+-	int rdcount=0;   	/* counts bytes read */
++	int rdcount = 0;	/* counts bytes read */
+ 	unsigned char *temp = msg->buf;
+ 	int count = msg->len;
+ 	const unsigned flags = msg->flags;
  
-+	if (unlikely(op->keylen != AES_KEYSIZE_128))
-+		return fallback_blk_dec(desc, dst, src, nbytes);
+ 	while (count > 0) {
+ 		inval = i2c_inb(i2c_adap);
+-		if (inval>=0) {
++		if (inval >= 0) {
+ 			*temp = inval;
+ 			rdcount++;
+ 		} else {   /* read timed out */
+@@ -431,7 +456,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+  * returns:
+  *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
+  * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
+- *	-ETIMEDOUT, for example if the lines are stuck...) 
++ *	-ETIMEDOUT, for example if the lines are stuck...)
+  */
+ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+ {
+@@ -443,10 +468,10 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+ 	int ret, retries;
+ 
+ 	retries = nak_ok ? 0 : i2c_adap->retries;
+-	
+-	if ( (flags & I2C_M_TEN)  ) { 
 +
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
-+	op->iv = walk.iv;
++	if (flags & I2C_M_TEN) {
+ 		/* a ten bit address */
+-		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
++		addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+ 		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
+ 		/* try extended address code...*/
+ 		ret = try_address(i2c_adap, addr, retries);
+@@ -456,33 +481,33 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+ 			return -EREMOTEIO;
+ 		}
+ 		/* the remaining 8 bit address */
+-		ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
++		ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
+ 		if ((ret != 1) && !nak_ok) {
+ 			/* the chip did not ack / xmission error occurred */
+ 			dev_err(&i2c_adap->dev, "died at 2nd address code\n");
+ 			return -EREMOTEIO;
+ 		}
+-		if ( flags & I2C_M_RD ) {
++		if (flags & I2C_M_RD) {
+ 			bit_dbg(3, &i2c_adap->dev, "emitting repeated "
+ 				"start condition\n");
+ 			i2c_repstart(adap);
+ 			/* okay, now switch into reading mode */
+ 			addr |= 0x01;
+ 			ret = try_address(i2c_adap, addr, retries);
+-			if ((ret!=1) && !nak_ok) {
++			if ((ret != 1) && !nak_ok) {
+ 				dev_err(&i2c_adap->dev,
+ 					"died at repeated address code\n");
+ 				return -EREMOTEIO;
+ 			}
+ 		}
+ 	} else {		/* normal 7bit address	*/
+-		addr = ( msg->addr << 1 );
+-		if (flags & I2C_M_RD )
++		addr = msg->addr << 1;
++		if (flags & I2C_M_RD)
+ 			addr |= 1;
+-		if (flags & I2C_M_REV_DIR_ADDR )
++		if (flags & I2C_M_REV_DIR_ADDR)
+ 			addr ^= 1;
+ 		ret = try_address(i2c_adap, addr, retries);
+-		if ((ret!=1) && !nak_ok)
++		if ((ret != 1) && !nak_ok)
+ 			return -EREMOTEIO;
+ 	}
  
- 	while((nbytes = walk.nbytes)) {
- 		op->src = walk.src.virt.addr,
-@@ -233,13 +324,9 @@ geode_cbc_decrypt(struct blkcipher_desc *desc,
- 		op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
- 		op->dir = AES_DIR_DECRYPT;
+@@ -494,15 +519,14 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
+ {
+ 	struct i2c_msg *pmsg;
+ 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+-	
+-	int i,ret;
++	int i, ret;
+ 	unsigned short nak_ok;
  
--		memcpy(op->iv, walk.iv, AES_IV_LENGTH);
--
- 		ret = geode_aes_crypt(op);
+ 	bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
+ 	i2c_start(adap);
+-	for (i=0;i<num;i++) {
++	for (i = 0; i < num; i++) {
+ 		pmsg = &msgs[i];
+-		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
++		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
+ 		if (!(pmsg->flags & I2C_M_NOSTART)) {
+ 			if (i) {
+ 				bit_dbg(3, &i2c_adap->dev, "emitting "
+@@ -517,7 +541,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
+ 				goto bailout;
+ 			}
+ 		}
+-		if (pmsg->flags & I2C_M_RD ) {
++		if (pmsg->flags & I2C_M_RD) {
+ 			/* read bytes into buffer*/
+ 			ret = readbytes(i2c_adap, pmsg);
+ 			if (ret >= 1)
+@@ -551,7 +575,7 @@ bailout:
  
--		memcpy(walk.iv, op->iv, AES_IV_LENGTH);
- 		nbytes -= ret;
--
- 		err = blkcipher_walk_done(desc, &walk, nbytes);
- 	}
+ static u32 bit_func(struct i2c_adapter *adap)
+ {
+-	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
++	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ 	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
+ 	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ 	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
+@@ -565,8 +589,8 @@ static const struct i2c_algorithm i2c_bit_algo = {
+ 	.functionality	= bit_func,
+ };
  
-@@ -255,8 +342,12 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err, ret;
+-/* 
+- * registering functions to load algorithms at runtime 
++/*
++ * registering functions to load algorithms at runtime
+  */
+ static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
+ {
+@@ -574,7 +598,7 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
  
-+	if (unlikely(op->keylen != AES_KEYSIZE_128))
-+		return fallback_blk_enc(desc, dst, src, nbytes);
-+
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
-+	op->iv = walk.iv;
+ 	if (bit_test) {
+ 		int ret = test_bus(bit_adap, adap->name);
+-		if (ret<0)
++		if (ret < 0)
+ 			return -ENODEV;
+ 	}
  
- 	while((nbytes = walk.nbytes)) {
- 		op->src = walk.src.virt.addr,
-@@ -265,8 +356,6 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
- 		op->len = nbytes - (nbytes % AES_MIN_BLOCK_SIZE);
- 		op->dir = AES_DIR_ENCRYPT;
+diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
+index ab2e6f3..8907b01 100644
+--- a/drivers/i2c/algos/i2c-algo-pcf.c
++++ b/drivers/i2c/algos/i2c-algo-pcf.c
+@@ -203,35 +203,6 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
+ /* ----- Utility functions
+  */
  
--		memcpy(op->iv, walk.iv, AES_IV_LENGTH);
+-static inline int try_address(struct i2c_algo_pcf_data *adap,
+-		       unsigned char addr, int retries)
+-{
+-	int i, status, ret = -1;
+-	int wfp;
+-	for (i=0;i<retries;i++) {
+-		i2c_outb(adap, addr);
+-		i2c_start(adap);
+-		status = get_pcf(adap, 1);
+-		if ((wfp = wait_for_pin(adap, &status)) >= 0) {
+-			if ((status & I2C_PCF_LRB) == 0) { 
+-				i2c_stop(adap);
+-				break;	/* success! */
+-			}
+-		}
+-		if (wfp == -EINTR) {
+-			/* arbitration lost */
+-			udelay(adap->udelay);
+-			return -EINTR;
+-		}
+-		i2c_stop(adap);
+-		udelay(adap->udelay);
+-	}
+-	DEB2(if (i) printk(KERN_DEBUG "i2c-algo-pcf.o: needed %d retries for %d\n",i,
+-	                   addr));
+-	return ret;
+-}
 -
- 		ret = geode_aes_crypt(op);
- 		nbytes -= ret;
- 		err = blkcipher_walk_done(desc, &walk, nbytes);
-@@ -275,22 +364,49 @@ geode_cbc_encrypt(struct blkcipher_desc *desc,
- 	return err;
+-
+ static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
+                          int count, int last)
+ {
+@@ -321,47 +292,19 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
  }
  
-+static int fallback_init_blk(struct crypto_tfm *tfm)
-+{
-+	const char *name = tfm->__crt_alg->cra_name;
-+	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
-+
-+	op->fallback.blk = crypto_alloc_blkcipher(name, 0,
-+			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
-+
-+	if (IS_ERR(op->fallback.blk)) {
-+		printk(KERN_ERR "Error allocating fallback algo %s\n", name);
-+		return PTR_ERR(op->fallback.blk);
-+	}
-+
-+	return 0;
-+}
-+
-+static void fallback_exit_blk(struct crypto_tfm *tfm)
-+{
-+	struct geode_aes_op *op = crypto_tfm_ctx(tfm);
-+
-+	crypto_free_blkcipher(op->fallback.blk);
-+	op->fallback.blk = NULL;
-+}
-+
- static struct crypto_alg geode_cbc_alg = {
- 	.cra_name		=	"cbc(aes)",
--	.cra_driver_name	=	"cbc-aes-geode-128",
-+	.cra_driver_name	=	"cbc-aes-geode",
- 	.cra_priority		=	400,
--	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
-+	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
-+							CRYPTO_ALG_NEED_FALLBACK,
-+	.cra_init			=	fallback_init_blk,
-+	.cra_exit			=	fallback_exit_blk,
- 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
- 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
- 	.cra_alignmask		=	15,
--	.cra_type		=	&crypto_blkcipher_type,
--	.cra_module		=	THIS_MODULE,
--	.cra_list		=	LIST_HEAD_INIT(geode_cbc_alg.cra_list),
--	.cra_u			=	{
--		.blkcipher = {
--			.min_keysize		=	AES_KEY_LENGTH,
--			.max_keysize		=	AES_KEY_LENGTH,
--			.setkey			=	geode_setkey,
-+	.cra_type			=	&crypto_blkcipher_type,
-+	.cra_module			=	THIS_MODULE,
-+	.cra_list			=	LIST_HEAD_INIT(geode_cbc_alg.cra_list),
-+	.cra_u				=	{
-+		.blkcipher	=	{
-+			.min_keysize	=	AES_MIN_KEY_SIZE,
-+			.max_keysize	=	AES_MAX_KEY_SIZE,
-+			.setkey			=	geode_setkey_blk,
- 			.encrypt		=	geode_cbc_encrypt,
- 			.decrypt		=	geode_cbc_decrypt,
- 			.ivsize			=	AES_IV_LENGTH,
-@@ -307,6 +423,9 @@ geode_ecb_decrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err, ret;
  
-+	if (unlikely(op->keylen != AES_KEYSIZE_128))
-+		return fallback_blk_dec(desc, dst, src, nbytes);
+-static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap,
+-                                struct i2c_msg *msg, int retries) 
++static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
++			 struct i2c_msg *msg)
+ {
+ 	unsigned short flags = msg->flags;
+ 	unsigned char addr;
+-	int ret;
+-	if ( (flags & I2C_M_TEN)  ) { 
+-		/* a ten bit address */
+-		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
+-		DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
+-		/* try extended address code...*/
+-		ret = try_address(adap, addr, retries);
+-		if (ret!=1) {
+-			printk(KERN_ERR "died at extended address code.\n");
+-			return -EREMOTEIO;
+-		}
+-		/* the remaining 8 bit address */
+-		i2c_outb(adap,msg->addr & 0x7f);
+-/* Status check comes here */
+-		if (ret != 1) {
+-			printk(KERN_ERR "died at 2nd address code.\n");
+-			return -EREMOTEIO;
+-		}
+-		if ( flags & I2C_M_RD ) {
+-			i2c_repstart(adap);
+-			/* okay, now switch into reading mode */
+-			addr |= 0x01;
+-			ret = try_address(adap, addr, retries);
+-			if (ret!=1) {
+-				printk(KERN_ERR "died at extended address code.\n");
+-				return -EREMOTEIO;
+-			}
+-		}
+-	} else {		/* normal 7bit address	*/
+-		addr = ( msg->addr << 1 );
+-		if (flags & I2C_M_RD )
+-			addr |= 1;
+-		if (flags & I2C_M_REV_DIR_ADDR )
+-			addr ^= 1;
+-		i2c_outb(adap, addr);
+-	}
 +
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
- 
-@@ -334,6 +453,9 @@ geode_ecb_encrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err, ret;
- 
-+	if (unlikely(op->keylen != AES_KEYSIZE_128))
-+		return fallback_blk_enc(desc, dst, src, nbytes);
++	addr = msg->addr << 1;
++	if (flags & I2C_M_RD)
++		addr |= 1;
++	if (flags & I2C_M_REV_DIR_ADDR)
++		addr ^= 1;
++	i2c_outb(adap, addr);
 +
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
- 
-@@ -353,28 +475,31 @@ geode_ecb_encrypt(struct blkcipher_desc *desc,
+ 	return 0;
  }
  
- static struct crypto_alg geode_ecb_alg = {
--	.cra_name		=	"ecb(aes)",
--	.cra_driver_name	=	"ecb-aes-geode-128",
-+	.cra_name			=	"ecb(aes)",
-+	.cra_driver_name	=	"ecb-aes-geode",
- 	.cra_priority		=	400,
--	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
-+	.cra_flags			=	CRYPTO_ALG_TYPE_BLKCIPHER |
-+							CRYPTO_ALG_NEED_FALLBACK,
-+	.cra_init			=	fallback_init_blk,
-+	.cra_exit			=	fallback_exit_blk,
- 	.cra_blocksize		=	AES_MIN_BLOCK_SIZE,
- 	.cra_ctxsize		=	sizeof(struct geode_aes_op),
- 	.cra_alignmask		=	15,
--	.cra_type		=	&crypto_blkcipher_type,
--	.cra_module		=	THIS_MODULE,
--	.cra_list		=	LIST_HEAD_INIT(geode_ecb_alg.cra_list),
--	.cra_u			=	{
--		.blkcipher = {
--			.min_keysize		=	AES_KEY_LENGTH,
--			.max_keysize		=	AES_KEY_LENGTH,
--			.setkey			=	geode_setkey,
-+	.cra_type			=	&crypto_blkcipher_type,
-+	.cra_module			=	THIS_MODULE,
-+	.cra_list			=	LIST_HEAD_INIT(geode_ecb_alg.cra_list),
-+	.cra_u				=	{
-+		.blkcipher	=	{
-+			.min_keysize	=	AES_MIN_KEY_SIZE,
-+			.max_keysize	=	AES_MAX_KEY_SIZE,
-+			.setkey			=	geode_setkey_blk,
- 			.encrypt		=	geode_ecb_encrypt,
- 			.decrypt		=	geode_ecb_decrypt,
- 		}
- 	}
- };
+@@ -390,7 +333,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
+ 		     pmsg->flags & I2C_M_RD ? "read" : "write",
+                      pmsg->len, pmsg->addr, i + 1, num);)
+     
+-		ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
++		ret = pcf_doAddress(adap, pmsg);
  
--static void
-+static void __devexit
- geode_aes_remove(struct pci_dev *dev)
+ 		/* Send START */
+ 		if (i == 0) {
+@@ -453,7 +396,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
+ static u32 pcf_func(struct i2c_adapter *adap)
  {
- 	crypto_unregister_alg(&geode_alg);
-@@ -389,7 +514,7 @@ geode_aes_remove(struct pci_dev *dev)
+ 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
+-	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; 
++	       I2C_FUNC_PROTOCOL_MANGLING;
  }
  
+ /* -----exported algorithm data: -------------------------------------	*/
+@@ -475,9 +418,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
  
--static int
-+static int __devinit
- geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
- {
- 	int ret;
-@@ -397,7 +522,7 @@ geode_aes_probe(struct pci_dev *dev, const struct pci_device_id *id)
- 	if ((ret = pci_enable_device(dev)))
- 		return ret;
+ 	/* register new adapter to i2c module... */
+ 	adap->algo = &pcf_algo;
+-
+-	adap->timeout = 100;		/* default values, should	*/
+-	adap->retries = 3;		/* be replaced by defines	*/
++	adap->timeout = 100;
  
--	if ((ret = pci_request_regions(dev, "geode-aes-128")))
-+	if ((ret = pci_request_regions(dev, "geode-aes")))
- 		goto eenable;
+ 	if ((rval = pcf_init_8584(pcf_adap)))
+ 		return rval;
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index c466c6c..b61f56b 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -182,7 +182,8 @@ config I2C_I801
+ 	  will be called i2c-i801.
  
- 	_iobase = pci_iomap(dev, 0, 0);
-@@ -472,7 +597,6 @@ geode_aes_exit(void)
- MODULE_AUTHOR("Advanced Micro Devices, Inc.");
- MODULE_DESCRIPTION("Geode LX Hardware AES driver");
- MODULE_LICENSE("GPL");
--MODULE_ALIAS("aes");
+ config I2C_I810
+-	tristate "Intel 810/815"
++	tristate "Intel 810/815 (DEPRECATED)"
++	default n
+ 	depends on PCI
+ 	select I2C_ALGOBIT
+ 	help
+@@ -195,6 +196,8 @@ config I2C_I810
+ 	    i815
+ 	    i845G
  
- module_init(geode_aes_init);
- module_exit(geode_aes_exit);
-diff --git a/drivers/crypto/geode-aes.h b/drivers/crypto/geode-aes.h
-index f479686..f1855b5 100644
---- a/drivers/crypto/geode-aes.h
-+++ b/drivers/crypto/geode-aes.h
-@@ -9,9 +9,9 @@
- #ifndef _GEODE_AES_H_
- #define _GEODE_AES_H_
++	  This driver is deprecated in favor of the i810fb and intelfb drivers.
++
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-i810.
  
--#define AES_KEY_LENGTH 16
-+/* driver logic flags */
- #define AES_IV_LENGTH  16
--
-+#define AES_KEY_LENGTH 16
- #define AES_MIN_BLOCK_SIZE 16
+@@ -259,20 +262,6 @@ config I2C_IOP3XX
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-iop3xx.
  
- #define AES_MODE_ECB 0
-@@ -22,6 +22,38 @@
+-config I2C_IXP4XX
+-	tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
+-	depends on ARCH_IXP4XX
+-	select I2C_ALGOBIT
+-	help
+-	  Say Y here if you have an Intel IXP4xx(420,421,422,425) based 
+-	  system and are using GPIO lines for an I2C bus.
+-
+-	  This support is also available as a module. If so, the module
+-	  will be called i2c-ixp4xx.
+-
+-	  This driver is deprecated and will be dropped soon. Use i2c-gpio
+-	  instead.
+-
+ config I2C_IXP2000
+ 	tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
+ 	depends on ARCH_IXP2000
+@@ -396,7 +385,8 @@ config I2C_PASEMI
+ 	  Supports the PA Semi PWRficient on-chip SMBus interfaces.
  
- #define AES_FLAGS_HIDDENKEY (1 << 0)
+ config I2C_PROSAVAGE
+-	tristate "S3/VIA (Pro)Savage"
++	tristate "S3/VIA (Pro)Savage (DEPRECATED)"
++	default n
+ 	depends on PCI
+ 	select I2C_ALGOBIT
+ 	help
+@@ -407,6 +397,8 @@ config I2C_PROSAVAGE
+ 	    S3/VIA KM266/VT8375 aka ProSavage8
+ 	    S3/VIA KM133/VT8365 aka Savage4
  
-+/* Register definitions */
-+
-+#define AES_CTRLA_REG  0x0000
-+
-+#define AES_CTRL_START     0x01
-+#define AES_CTRL_DECRYPT   0x00
-+#define AES_CTRL_ENCRYPT   0x02
-+#define AES_CTRL_WRKEY     0x04
-+#define AES_CTRL_DCA       0x08
-+#define AES_CTRL_SCA       0x10
-+#define AES_CTRL_CBC       0x20
-+
-+#define AES_INTR_REG  0x0008
-+
-+#define AES_INTRA_PENDING (1 << 16)
-+#define AES_INTRB_PENDING (1 << 17)
-+
-+#define AES_INTR_PENDING  (AES_INTRA_PENDING | AES_INTRB_PENDING)
-+#define AES_INTR_MASK     0x07
-+
-+#define AES_SOURCEA_REG   0x0010
-+#define AES_DSTA_REG      0x0014
-+#define AES_LENA_REG      0x0018
-+#define AES_WRITEKEY0_REG 0x0030
-+#define AES_WRITEIV0_REG  0x0040
-+
-+/*  A very large counter that is used to gracefully bail out of an
-+ *  operation in case of trouble
-+ */
++	  This driver is deprecated in favor of the savagefb driver.
 +
-+#define AES_OP_TIMEOUT    0x50000
+ 	  This support is also available as a module.  If so, the module 
+ 	  will be called i2c-prosavage.
+ 
+@@ -418,13 +410,16 @@ config I2C_S3C2410
+ 	  Samsung S3C2410 based System-on-Chip devices.
+ 
+ config I2C_SAVAGE4
+-	tristate "S3 Savage 4"
+-	depends on PCI && EXPERIMENTAL
++	tristate "S3 Savage 4 (DEPRECATED)"
++	default n
++	depends on PCI
+ 	select I2C_ALGOBIT
+ 	help
+ 	  If you say yes to this option, support will be included for the 
+ 	  S3 Savage 4 I2C interface.
+ 
++	  This driver is deprecated in favor of the savagefb driver.
 +
- struct geode_aes_op {
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called i2c-savage4.
  
- 	void *src;
-@@ -33,7 +65,13 @@ struct geode_aes_op {
- 	int len;
+@@ -611,7 +606,7 @@ config I2C_VIAPRO
+ 	    VT8231
+ 	    VT8233/A
+ 	    VT8235
+-	    VT8237R/A
++	    VT8237R/A/S
+ 	    VT8251
+ 	    CX700
  
- 	u8 key[AES_KEY_LENGTH];
--	u8 iv[AES_IV_LENGTH];
-+	u8 *iv;
+@@ -648,7 +643,7 @@ config I2C_PCA_ISA
+ 
+ config I2C_MV64XXX
+ 	tristate "Marvell mv64xxx I2C Controller"
+-	depends on MV64X60 && EXPERIMENTAL
++	depends on (MV64X60 || ARCH_ORION) && EXPERIMENTAL
+ 	help
+ 	  If you say yes to this option, support will be included for the
+ 	  built-in I2C interface on the Marvell 64xxx line of host bridges.
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index 81d43c2..ea7068f 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -20,7 +20,6 @@ obj-$(CONFIG_I2C_I810)		+= i2c-i810.o
+ obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
+ obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
+ obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
+-obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
+ obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
+ obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+ obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
+diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
+index 7490dc1..573abe4 100644
+--- a/drivers/i2c/busses/i2c-amd756.c
++++ b/drivers/i2c/busses/i2c-amd756.c
+@@ -334,6 +334,10 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
+ 	int error;
+ 	u8 temp;
+ 	
++	/* driver_data might come from user-space, so check it */
++	if (id->driver_data > ARRAY_SIZE(chipname))
++		return -EINVAL;
 +
-+	union {
-+		struct crypto_blkcipher *blk;
-+		struct crypto_cipher *cip;
-+	} fallback;
-+	u32 keylen;
+ 	if (amd756_ioport) {
+ 		dev_err(&pdev->dev, "Only one device supported "
+ 		       "(you have a strange motherboard, btw)\n");
+@@ -405,6 +409,7 @@ static struct pci_driver amd756_driver = {
+ 	.id_table	= amd756_ids,
+ 	.probe		= amd756_probe,
+ 	.remove		= __devexit_p(amd756_remove),
++	.dynids.use_driver_data = 1,
  };
  
- #endif
-diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
-new file mode 100644
-index 0000000..dfbf24c
---- /dev/null
-+++ b/drivers/crypto/hifn_795x.c
-@@ -0,0 +1,2838 @@
-+/*
-+ * 2007+ Copyright (c) Evgeniy Polyakov <johnpol at 2ka.mipt.ru>
-+ * All rights reserved.
-+ *
-+ * 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 <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/interrupt.h>
-+#include <linux/pci.h>
+ static int __init amd756_init(void)
+diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
+index 2f68416..1953b26 100644
+--- a/drivers/i2c/busses/i2c-au1550.c
++++ b/drivers/i2c/busses/i2c-au1550.c
+@@ -30,14 +30,22 @@
+ #include <linux/delay.h>
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/platform_device.h>
+ #include <linux/init.h>
+ #include <linux/errno.h>
+ #include <linux/i2c.h>
 +#include <linux/slab.h>
-+#include <linux/delay.h>
-+#include <linux/mm.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/scatterlist.h>
-+#include <linux/highmem.h>
-+#include <linux/interrupt.h>
-+#include <linux/crypto.h>
-+#include <linux/hw_random.h>
-+#include <linux/ktime.h>
-+
-+#include <crypto/algapi.h>
-+#include <crypto/des.h>
-+
-+#include <asm/kmap_types.h>
-+
-+#undef dprintk
-+
-+#define HIFN_TEST
-+//#define HIFN_DEBUG
-+
-+#ifdef HIFN_DEBUG
-+#define dprintk(f, a...) 	printk(f, ##a)
-+#else
-+#define dprintk(f, a...)	do {} while (0)
-+#endif
-+
-+static char hifn_pll_ref[sizeof("extNNN")] = "ext";
-+module_param_string(hifn_pll_ref, hifn_pll_ref, sizeof(hifn_pll_ref), 0444);
-+MODULE_PARM_DESC(hifn_pll_ref,
-+		 "PLL reference clock (pci[freq] or ext[freq], default ext)");
-+
-+static atomic_t hifn_dev_number;
-+
-+#define ACRYPTO_OP_DECRYPT	0
-+#define ACRYPTO_OP_ENCRYPT	1
-+#define ACRYPTO_OP_HMAC		2
-+#define ACRYPTO_OP_RNG		3
-+
-+#define ACRYPTO_MODE_ECB		0
-+#define ACRYPTO_MODE_CBC		1
-+#define ACRYPTO_MODE_CFB		2
-+#define ACRYPTO_MODE_OFB		3
-+
-+#define ACRYPTO_TYPE_AES_128	0
-+#define ACRYPTO_TYPE_AES_192	1
-+#define ACRYPTO_TYPE_AES_256	2
-+#define ACRYPTO_TYPE_3DES	3
-+#define ACRYPTO_TYPE_DES	4
-+
-+#define PCI_VENDOR_ID_HIFN		0x13A3
-+#define PCI_DEVICE_ID_HIFN_7955		0x0020
-+#define	PCI_DEVICE_ID_HIFN_7956		0x001d
-+
-+/* I/O region sizes */
-+
-+#define HIFN_BAR0_SIZE			0x1000
-+#define HIFN_BAR1_SIZE			0x2000
-+#define HIFN_BAR2_SIZE			0x8000
-+
-+/* DMA registres */
-+
-+#define HIFN_DMA_CRA 			0x0C	/* DMA Command Ring Address */
-+#define HIFN_DMA_SDRA 			0x1C	/* DMA Source Data Ring Address */
-+#define HIFN_DMA_RRA			0x2C	/* DMA Result Ring Address */
-+#define HIFN_DMA_DDRA			0x3C	/* DMA Destination Data Ring Address */
-+#define HIFN_DMA_STCTL			0x40	/* DMA Status and Control */
-+#define HIFN_DMA_INTREN 		0x44	/* DMA Interrupt Enable */
-+#define HIFN_DMA_CFG1			0x48	/* DMA Configuration #1 */
-+#define HIFN_DMA_CFG2			0x6C	/* DMA Configuration #2 */
-+#define HIFN_CHIP_ID			0x98	/* Chip ID */
-+
-+/*
-+ * Processing Unit Registers (offset from BASEREG0)
-+ */
-+#define	HIFN_0_PUDATA		0x00	/* Processing Unit Data */
-+#define	HIFN_0_PUCTRL		0x04	/* Processing Unit Control */
-+#define	HIFN_0_PUISR		0x08	/* Processing Unit Interrupt Status */
-+#define	HIFN_0_PUCNFG		0x0c	/* Processing Unit Configuration */
-+#define	HIFN_0_PUIER		0x10	/* Processing Unit Interrupt Enable */
-+#define	HIFN_0_PUSTAT		0x14	/* Processing Unit Status/Chip ID */
-+#define	HIFN_0_FIFOSTAT		0x18	/* FIFO Status */
-+#define	HIFN_0_FIFOCNFG		0x1c	/* FIFO Configuration */
-+#define	HIFN_0_SPACESIZE	0x20	/* Register space size */
-+
-+/* Processing Unit Control Register (HIFN_0_PUCTRL) */
-+#define	HIFN_PUCTRL_CLRSRCFIFO	0x0010	/* clear source fifo */
-+#define	HIFN_PUCTRL_STOP	0x0008	/* stop pu */
-+#define	HIFN_PUCTRL_LOCKRAM	0x0004	/* lock ram */
-+#define	HIFN_PUCTRL_DMAENA	0x0002	/* enable dma */
-+#define	HIFN_PUCTRL_RESET	0x0001	/* Reset processing unit */
-+
-+/* Processing Unit Interrupt Status Register (HIFN_0_PUISR) */
-+#define	HIFN_PUISR_CMDINVAL	0x8000	/* Invalid command interrupt */
-+#define	HIFN_PUISR_DATAERR	0x4000	/* Data error interrupt */
-+#define	HIFN_PUISR_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
-+#define	HIFN_PUISR_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
-+#define	HIFN_PUISR_DSTOVER	0x0200	/* Destination overrun interrupt */
-+#define	HIFN_PUISR_SRCCMD	0x0080	/* Source command interrupt */
-+#define	HIFN_PUISR_SRCCTX	0x0040	/* Source context interrupt */
-+#define	HIFN_PUISR_SRCDATA	0x0020	/* Source data interrupt */
-+#define	HIFN_PUISR_DSTDATA	0x0010	/* Destination data interrupt */
-+#define	HIFN_PUISR_DSTRESULT	0x0004	/* Destination result interrupt */
-+
-+/* Processing Unit Configuration Register (HIFN_0_PUCNFG) */
-+#define	HIFN_PUCNFG_DRAMMASK	0xe000	/* DRAM size mask */
-+#define	HIFN_PUCNFG_DSZ_256K	0x0000	/* 256k dram */
-+#define	HIFN_PUCNFG_DSZ_512K	0x2000	/* 512k dram */
-+#define	HIFN_PUCNFG_DSZ_1M	0x4000	/* 1m dram */
-+#define	HIFN_PUCNFG_DSZ_2M	0x6000	/* 2m dram */
-+#define	HIFN_PUCNFG_DSZ_4M	0x8000	/* 4m dram */
-+#define	HIFN_PUCNFG_DSZ_8M	0xa000	/* 8m dram */
-+#define	HIFN_PUNCFG_DSZ_16M	0xc000	/* 16m dram */
-+#define	HIFN_PUCNFG_DSZ_32M	0xe000	/* 32m dram */
-+#define	HIFN_PUCNFG_DRAMREFRESH	0x1800	/* DRAM refresh rate mask */
-+#define	HIFN_PUCNFG_DRFR_512	0x0000	/* 512 divisor of ECLK */
-+#define	HIFN_PUCNFG_DRFR_256	0x0800	/* 256 divisor of ECLK */
-+#define	HIFN_PUCNFG_DRFR_128	0x1000	/* 128 divisor of ECLK */
-+#define	HIFN_PUCNFG_TCALLPHASES	0x0200	/* your guess is as good as mine... */
-+#define	HIFN_PUCNFG_TCDRVTOTEM	0x0100	/* your guess is as good as mine... */
-+#define	HIFN_PUCNFG_BIGENDIAN	0x0080	/* DMA big endian mode */
-+#define	HIFN_PUCNFG_BUS32	0x0040	/* Bus width 32bits */
-+#define	HIFN_PUCNFG_BUS16	0x0000	/* Bus width 16 bits */
-+#define	HIFN_PUCNFG_CHIPID	0x0020	/* Allow chipid from PUSTAT */
-+#define	HIFN_PUCNFG_DRAM	0x0010	/* Context RAM is DRAM */
-+#define	HIFN_PUCNFG_SRAM	0x0000	/* Context RAM is SRAM */
-+#define	HIFN_PUCNFG_COMPSING	0x0004	/* Enable single compression context */
-+#define	HIFN_PUCNFG_ENCCNFG	0x0002	/* Encryption configuration */
-+
-+/* Processing Unit Interrupt Enable Register (HIFN_0_PUIER) */
-+#define	HIFN_PUIER_CMDINVAL	0x8000	/* Invalid command interrupt */
-+#define	HIFN_PUIER_DATAERR	0x4000	/* Data error interrupt */
-+#define	HIFN_PUIER_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
-+#define	HIFN_PUIER_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
-+#define	HIFN_PUIER_DSTOVER	0x0200	/* Destination overrun interrupt */
-+#define	HIFN_PUIER_SRCCMD	0x0080	/* Source command interrupt */
-+#define	HIFN_PUIER_SRCCTX	0x0040	/* Source context interrupt */
-+#define	HIFN_PUIER_SRCDATA	0x0020	/* Source data interrupt */
-+#define	HIFN_PUIER_DSTDATA	0x0010	/* Destination data interrupt */
-+#define	HIFN_PUIER_DSTRESULT	0x0004	/* Destination result interrupt */
-+
-+/* Processing Unit Status Register/Chip ID (HIFN_0_PUSTAT) */
-+#define	HIFN_PUSTAT_CMDINVAL	0x8000	/* Invalid command interrupt */
-+#define	HIFN_PUSTAT_DATAERR	0x4000	/* Data error interrupt */
-+#define	HIFN_PUSTAT_SRCFIFO	0x2000	/* Source FIFO ready interrupt */
-+#define	HIFN_PUSTAT_DSTFIFO	0x1000	/* Destination FIFO ready interrupt */
-+#define	HIFN_PUSTAT_DSTOVER	0x0200	/* Destination overrun interrupt */
-+#define	HIFN_PUSTAT_SRCCMD	0x0080	/* Source command interrupt */
-+#define	HIFN_PUSTAT_SRCCTX	0x0040	/* Source context interrupt */
-+#define	HIFN_PUSTAT_SRCDATA	0x0020	/* Source data interrupt */
-+#define	HIFN_PUSTAT_DSTDATA	0x0010	/* Destination data interrupt */
-+#define	HIFN_PUSTAT_DSTRESULT	0x0004	/* Destination result interrupt */
-+#define	HIFN_PUSTAT_CHIPREV	0x00ff	/* Chip revision mask */
-+#define	HIFN_PUSTAT_CHIPENA	0xff00	/* Chip enabled mask */
-+#define	HIFN_PUSTAT_ENA_2	0x1100	/* Level 2 enabled */
-+#define	HIFN_PUSTAT_ENA_1	0x1000	/* Level 1 enabled */
-+#define	HIFN_PUSTAT_ENA_0	0x3000	/* Level 0 enabled */
-+#define	HIFN_PUSTAT_REV_2	0x0020	/* 7751 PT6/2 */
-+#define	HIFN_PUSTAT_REV_3	0x0030	/* 7751 PT6/3 */
-+
-+/* FIFO Status Register (HIFN_0_FIFOSTAT) */
-+#define	HIFN_FIFOSTAT_SRC	0x7f00	/* Source FIFO available */
-+#define	HIFN_FIFOSTAT_DST	0x007f	/* Destination FIFO available */
-+
-+/* FIFO Configuration Register (HIFN_0_FIFOCNFG) */
-+#define	HIFN_FIFOCNFG_THRESHOLD	0x0400	/* must be written as 1 */
-+
-+/*
-+ * DMA Interface Registers (offset from BASEREG1)
-+ */
-+#define	HIFN_1_DMA_CRAR		0x0c	/* DMA Command Ring Address */
-+#define	HIFN_1_DMA_SRAR		0x1c	/* DMA Source Ring Address */
-+#define	HIFN_1_DMA_RRAR		0x2c	/* DMA Result Ring Address */
-+#define	HIFN_1_DMA_DRAR		0x3c	/* DMA Destination Ring Address */
-+#define	HIFN_1_DMA_CSR		0x40	/* DMA Status and Control */
-+#define	HIFN_1_DMA_IER		0x44	/* DMA Interrupt Enable */
-+#define	HIFN_1_DMA_CNFG		0x48	/* DMA Configuration */
-+#define	HIFN_1_PLL		0x4c	/* 795x: PLL config */
-+#define	HIFN_1_7811_RNGENA	0x60	/* 7811: rng enable */
-+#define	HIFN_1_7811_RNGCFG	0x64	/* 7811: rng config */
-+#define	HIFN_1_7811_RNGDAT	0x68	/* 7811: rng data */
-+#define	HIFN_1_7811_RNGSTS	0x6c	/* 7811: rng status */
-+#define	HIFN_1_7811_MIPSRST	0x94	/* 7811: MIPS reset */
-+#define	HIFN_1_REVID		0x98	/* Revision ID */
-+#define	HIFN_1_UNLOCK_SECRET1	0xf4
-+#define	HIFN_1_UNLOCK_SECRET2	0xfc
-+#define	HIFN_1_PUB_RESET	0x204	/* Public/RNG Reset */
-+#define	HIFN_1_PUB_BASE		0x300	/* Public Base Address */
-+#define	HIFN_1_PUB_OPLEN	0x304	/* Public Operand Length */
-+#define	HIFN_1_PUB_OP		0x308	/* Public Operand */
-+#define	HIFN_1_PUB_STATUS	0x30c	/* Public Status */
-+#define	HIFN_1_PUB_IEN		0x310	/* Public Interrupt enable */
-+#define	HIFN_1_RNG_CONFIG	0x314	/* RNG config */
-+#define	HIFN_1_RNG_DATA		0x318	/* RNG data */
-+#define	HIFN_1_PUB_MEM		0x400	/* start of Public key memory */
-+#define	HIFN_1_PUB_MEMEND	0xbff	/* end of Public key memory */
-+
-+/* DMA Status and Control Register (HIFN_1_DMA_CSR) */
-+#define	HIFN_DMACSR_D_CTRLMASK	0xc0000000	/* Destinition Ring Control */
-+#define	HIFN_DMACSR_D_CTRL_NOP	0x00000000	/* Dest. Control: no-op */
-+#define	HIFN_DMACSR_D_CTRL_DIS	0x40000000	/* Dest. Control: disable */
-+#define	HIFN_DMACSR_D_CTRL_ENA	0x80000000	/* Dest. Control: enable */
-+#define	HIFN_DMACSR_D_ABORT	0x20000000	/* Destinition Ring PCIAbort */
-+#define	HIFN_DMACSR_D_DONE	0x10000000	/* Destinition Ring Done */
-+#define	HIFN_DMACSR_D_LAST	0x08000000	/* Destinition Ring Last */
-+#define	HIFN_DMACSR_D_WAIT	0x04000000	/* Destinition Ring Waiting */
-+#define	HIFN_DMACSR_D_OVER	0x02000000	/* Destinition Ring Overflow */
-+#define	HIFN_DMACSR_R_CTRL	0x00c00000	/* Result Ring Control */
-+#define	HIFN_DMACSR_R_CTRL_NOP	0x00000000	/* Result Control: no-op */
-+#define	HIFN_DMACSR_R_CTRL_DIS	0x00400000	/* Result Control: disable */
-+#define	HIFN_DMACSR_R_CTRL_ENA	0x00800000	/* Result Control: enable */
-+#define	HIFN_DMACSR_R_ABORT	0x00200000	/* Result Ring PCI Abort */
-+#define	HIFN_DMACSR_R_DONE	0x00100000	/* Result Ring Done */
-+#define	HIFN_DMACSR_R_LAST	0x00080000	/* Result Ring Last */
-+#define	HIFN_DMACSR_R_WAIT	0x00040000	/* Result Ring Waiting */
-+#define	HIFN_DMACSR_R_OVER	0x00020000	/* Result Ring Overflow */
-+#define	HIFN_DMACSR_S_CTRL	0x0000c000	/* Source Ring Control */
-+#define	HIFN_DMACSR_S_CTRL_NOP	0x00000000	/* Source Control: no-op */
-+#define	HIFN_DMACSR_S_CTRL_DIS	0x00004000	/* Source Control: disable */
-+#define	HIFN_DMACSR_S_CTRL_ENA	0x00008000	/* Source Control: enable */
-+#define	HIFN_DMACSR_S_ABORT	0x00002000	/* Source Ring PCI Abort */
-+#define	HIFN_DMACSR_S_DONE	0x00001000	/* Source Ring Done */
-+#define	HIFN_DMACSR_S_LAST	0x00000800	/* Source Ring Last */
-+#define	HIFN_DMACSR_S_WAIT	0x00000400	/* Source Ring Waiting */
-+#define	HIFN_DMACSR_ILLW	0x00000200	/* Illegal write (7811 only) */
-+#define	HIFN_DMACSR_ILLR	0x00000100	/* Illegal read (7811 only) */
-+#define	HIFN_DMACSR_C_CTRL	0x000000c0	/* Command Ring Control */
-+#define	HIFN_DMACSR_C_CTRL_NOP	0x00000000	/* Command Control: no-op */
-+#define	HIFN_DMACSR_C_CTRL_DIS	0x00000040	/* Command Control: disable */
-+#define	HIFN_DMACSR_C_CTRL_ENA	0x00000080	/* Command Control: enable */
-+#define	HIFN_DMACSR_C_ABORT	0x00000020	/* Command Ring PCI Abort */
-+#define	HIFN_DMACSR_C_DONE	0x00000010	/* Command Ring Done */
-+#define	HIFN_DMACSR_C_LAST	0x00000008	/* Command Ring Last */
-+#define	HIFN_DMACSR_C_WAIT	0x00000004	/* Command Ring Waiting */
-+#define	HIFN_DMACSR_PUBDONE	0x00000002	/* Public op done (7951 only) */
-+#define	HIFN_DMACSR_ENGINE	0x00000001	/* Command Ring Engine IRQ */
-+
-+/* DMA Interrupt Enable Register (HIFN_1_DMA_IER) */
-+#define	HIFN_DMAIER_D_ABORT	0x20000000	/* Destination Ring PCIAbort */
-+#define	HIFN_DMAIER_D_DONE	0x10000000	/* Destination Ring Done */
-+#define	HIFN_DMAIER_D_LAST	0x08000000	/* Destination Ring Last */
-+#define	HIFN_DMAIER_D_WAIT	0x04000000	/* Destination Ring Waiting */
-+#define	HIFN_DMAIER_D_OVER	0x02000000	/* Destination Ring Overflow */
-+#define	HIFN_DMAIER_R_ABORT	0x00200000	/* Result Ring PCI Abort */
-+#define	HIFN_DMAIER_R_DONE	0x00100000	/* Result Ring Done */
-+#define	HIFN_DMAIER_R_LAST	0x00080000	/* Result Ring Last */
-+#define	HIFN_DMAIER_R_WAIT	0x00040000	/* Result Ring Waiting */
-+#define	HIFN_DMAIER_R_OVER	0x00020000	/* Result Ring Overflow */
-+#define	HIFN_DMAIER_S_ABORT	0x00002000	/* Source Ring PCI Abort */
-+#define	HIFN_DMAIER_S_DONE	0x00001000	/* Source Ring Done */
-+#define	HIFN_DMAIER_S_LAST	0x00000800	/* Source Ring Last */
-+#define	HIFN_DMAIER_S_WAIT	0x00000400	/* Source Ring Waiting */
-+#define	HIFN_DMAIER_ILLW	0x00000200	/* Illegal write (7811 only) */
-+#define	HIFN_DMAIER_ILLR	0x00000100	/* Illegal read (7811 only) */
-+#define	HIFN_DMAIER_C_ABORT	0x00000020	/* Command Ring PCI Abort */
-+#define	HIFN_DMAIER_C_DONE	0x00000010	/* Command Ring Done */
-+#define	HIFN_DMAIER_C_LAST	0x00000008	/* Command Ring Last */
-+#define	HIFN_DMAIER_C_WAIT	0x00000004	/* Command Ring Waiting */
-+#define	HIFN_DMAIER_PUBDONE	0x00000002	/* public op done (7951 only) */
-+#define	HIFN_DMAIER_ENGINE	0x00000001	/* Engine IRQ */
-+
-+/* DMA Configuration Register (HIFN_1_DMA_CNFG) */
-+#define	HIFN_DMACNFG_BIGENDIAN	0x10000000	/* big endian mode */
-+#define	HIFN_DMACNFG_POLLFREQ	0x00ff0000	/* Poll frequency mask */
-+#define	HIFN_DMACNFG_UNLOCK	0x00000800
-+#define	HIFN_DMACNFG_POLLINVAL	0x00000700	/* Invalid Poll Scalar */
-+#define	HIFN_DMACNFG_LAST	0x00000010	/* Host control LAST bit */
-+#define	HIFN_DMACNFG_MODE	0x00000004	/* DMA mode */
-+#define	HIFN_DMACNFG_DMARESET	0x00000002	/* DMA Reset # */
-+#define	HIFN_DMACNFG_MSTRESET	0x00000001	/* Master Reset # */
-+
-+/* PLL configuration register */
-+#define HIFN_PLL_REF_CLK_HBI	0x00000000	/* HBI reference clock */
-+#define HIFN_PLL_REF_CLK_PLL	0x00000001	/* PLL reference clock */
-+#define HIFN_PLL_BP		0x00000002	/* Reference clock bypass */
-+#define HIFN_PLL_PK_CLK_HBI	0x00000000	/* PK engine HBI clock */
-+#define HIFN_PLL_PK_CLK_PLL	0x00000008	/* PK engine PLL clock */
-+#define HIFN_PLL_PE_CLK_HBI	0x00000000	/* PE engine HBI clock */
-+#define HIFN_PLL_PE_CLK_PLL	0x00000010	/* PE engine PLL clock */
-+#define HIFN_PLL_RESERVED_1	0x00000400	/* Reserved bit, must be 1 */
-+#define HIFN_PLL_ND_SHIFT	11		/* Clock multiplier shift */
-+#define HIFN_PLL_ND_MULT_2	0x00000000	/* PLL clock multiplier 2 */
-+#define HIFN_PLL_ND_MULT_4	0x00000800	/* PLL clock multiplier 4 */
-+#define HIFN_PLL_ND_MULT_6	0x00001000	/* PLL clock multiplier 6 */
-+#define HIFN_PLL_ND_MULT_8	0x00001800	/* PLL clock multiplier 8 */
-+#define HIFN_PLL_ND_MULT_10	0x00002000	/* PLL clock multiplier 10 */
-+#define HIFN_PLL_ND_MULT_12	0x00002800	/* PLL clock multiplier 12 */
-+#define HIFN_PLL_IS_1_8		0x00000000	/* charge pump (mult. 1-8) */
-+#define HIFN_PLL_IS_9_12	0x00010000	/* charge pump (mult. 9-12) */
-+
-+#define HIFN_PLL_FCK_MAX	266		/* Maximum PLL frequency */
-+
-+/* Public key reset register (HIFN_1_PUB_RESET) */
-+#define	HIFN_PUBRST_RESET	0x00000001	/* reset public/rng unit */
-+
-+/* Public base address register (HIFN_1_PUB_BASE) */
-+#define	HIFN_PUBBASE_ADDR	0x00003fff	/* base address */
-+
-+/* Public operand length register (HIFN_1_PUB_OPLEN) */
-+#define	HIFN_PUBOPLEN_MOD_M	0x0000007f	/* modulus length mask */
-+#define	HIFN_PUBOPLEN_MOD_S	0		/* modulus length shift */
-+#define	HIFN_PUBOPLEN_EXP_M	0x0003ff80	/* exponent length mask */
-+#define	HIFN_PUBOPLEN_EXP_S	7		/* exponent lenght shift */
-+#define	HIFN_PUBOPLEN_RED_M	0x003c0000	/* reducend length mask */
-+#define	HIFN_PUBOPLEN_RED_S	18		/* reducend length shift */
-+
-+/* Public operation register (HIFN_1_PUB_OP) */
-+#define	HIFN_PUBOP_AOFFSET_M	0x0000007f	/* A offset mask */
-+#define	HIFN_PUBOP_AOFFSET_S	0		/* A offset shift */
-+#define	HIFN_PUBOP_BOFFSET_M	0x00000f80	/* B offset mask */
-+#define	HIFN_PUBOP_BOFFSET_S	7		/* B offset shift */
-+#define	HIFN_PUBOP_MOFFSET_M	0x0003f000	/* M offset mask */
-+#define	HIFN_PUBOP_MOFFSET_S	12		/* M offset shift */
-+#define	HIFN_PUBOP_OP_MASK	0x003c0000	/* Opcode: */
-+#define	HIFN_PUBOP_OP_NOP	0x00000000	/*  NOP */
-+#define	HIFN_PUBOP_OP_ADD	0x00040000	/*  ADD */
-+#define	HIFN_PUBOP_OP_ADDC	0x00080000	/*  ADD w/carry */
-+#define	HIFN_PUBOP_OP_SUB	0x000c0000	/*  SUB */
-+#define	HIFN_PUBOP_OP_SUBC	0x00100000	/*  SUB w/carry */
-+#define	HIFN_PUBOP_OP_MODADD	0x00140000	/*  Modular ADD */
-+#define	HIFN_PUBOP_OP_MODSUB	0x00180000	/*  Modular SUB */
-+#define	HIFN_PUBOP_OP_INCA	0x001c0000	/*  INC A */
-+#define	HIFN_PUBOP_OP_DECA	0x00200000	/*  DEC A */
-+#define	HIFN_PUBOP_OP_MULT	0x00240000	/*  MULT */
-+#define	HIFN_PUBOP_OP_MODMULT	0x00280000	/*  Modular MULT */
-+#define	HIFN_PUBOP_OP_MODRED	0x002c0000	/*  Modular RED */
-+#define	HIFN_PUBOP_OP_MODEXP	0x00300000	/*  Modular EXP */
-+
-+/* Public status register (HIFN_1_PUB_STATUS) */
-+#define	HIFN_PUBSTS_DONE	0x00000001	/* operation done */
-+#define	HIFN_PUBSTS_CARRY	0x00000002	/* carry */
-+
-+/* Public interrupt enable register (HIFN_1_PUB_IEN) */
-+#define	HIFN_PUBIEN_DONE	0x00000001	/* operation done interrupt */
-+
-+/* Random number generator config register (HIFN_1_RNG_CONFIG) */
-+#define	HIFN_RNGCFG_ENA		0x00000001	/* enable rng */
-+
-+#define HIFN_NAMESIZE			32
-+#define HIFN_MAX_RESULT_ORDER		5
-+
-+#define	HIFN_D_CMD_RSIZE		24*4
-+#define	HIFN_D_SRC_RSIZE		80*4
-+#define	HIFN_D_DST_RSIZE		80*4
-+#define	HIFN_D_RES_RSIZE		24*4
-+
-+#define HIFN_QUEUE_LENGTH		HIFN_D_CMD_RSIZE-5
-+
-+#define AES_MIN_KEY_SIZE		16
-+#define AES_MAX_KEY_SIZE		32
-+
-+#define HIFN_DES_KEY_LENGTH		8
-+#define HIFN_3DES_KEY_LENGTH		24
-+#define HIFN_MAX_CRYPT_KEY_LENGTH	AES_MAX_KEY_SIZE
-+#define HIFN_IV_LENGTH			8
-+#define HIFN_AES_IV_LENGTH		16
-+#define	HIFN_MAX_IV_LENGTH		HIFN_AES_IV_LENGTH
-+
-+#define HIFN_MAC_KEY_LENGTH		64
-+#define HIFN_MD5_LENGTH			16
-+#define HIFN_SHA1_LENGTH		20
-+#define HIFN_MAC_TRUNC_LENGTH		12
-+
-+#define	HIFN_MAX_COMMAND		(8 + 8 + 8 + 64 + 260)
-+#define	HIFN_MAX_RESULT			(8 + 4 + 4 + 20 + 4)
-+#define HIFN_USED_RESULT		12
-+
-+struct hifn_desc
-+{
-+	volatile u32		l;
-+	volatile u32		p;
-+};
-+
-+struct hifn_dma {
-+	struct hifn_desc	cmdr[HIFN_D_CMD_RSIZE+1];
-+	struct hifn_desc	srcr[HIFN_D_SRC_RSIZE+1];
-+	struct hifn_desc	dstr[HIFN_D_DST_RSIZE+1];
-+	struct hifn_desc	resr[HIFN_D_RES_RSIZE+1];
-+
-+	u8			command_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_COMMAND];
-+	u8			result_bufs[HIFN_D_CMD_RSIZE][HIFN_MAX_RESULT];
-+
-+	u64			test_src, test_dst;
-+
-+	/*
-+	 *  Our current positions for insertion and removal from the descriptor
-+	 *  rings.
-+	 */
-+	volatile int		cmdi, srci, dsti, resi;
-+	volatile int		cmdu, srcu, dstu, resu;
-+	int			cmdk, srck, dstk, resk;
-+};
-+
-+#define HIFN_FLAG_CMD_BUSY	(1<<0)
-+#define HIFN_FLAG_SRC_BUSY	(1<<1)
-+#define HIFN_FLAG_DST_BUSY	(1<<2)
-+#define HIFN_FLAG_RES_BUSY	(1<<3)
-+#define HIFN_FLAG_OLD_KEY	(1<<4)
-+
-+#define HIFN_DEFAULT_ACTIVE_NUM	5
-+
-+struct hifn_device
-+{
-+	char			name[HIFN_NAMESIZE];
-+
-+	int			irq;
-+
-+	struct pci_dev		*pdev;
-+	void __iomem		*bar[3];
-+
-+	unsigned long		result_mem;
-+	dma_addr_t		dst;
-+
-+	void			*desc_virt;
-+	dma_addr_t		desc_dma;
-+
-+	u32			dmareg;
-+
-+	void 			*sa[HIFN_D_RES_RSIZE];
-+
-+	spinlock_t		lock;
-+
-+	void 			*priv;
-+
-+	u32			flags;
-+	int			active, started;
-+	struct delayed_work	work;
-+	unsigned long		reset;
-+	unsigned long		success;
-+	unsigned long		prev_success;
-+
-+	u8			snum;
-+
-+	struct tasklet_struct	tasklet;
-+
-+	struct crypto_queue 	queue;
-+	struct list_head	alg_list;
-+
-+	unsigned int		pk_clk_freq;
-+
-+#ifdef CRYPTO_DEV_HIFN_795X_RNG
-+	unsigned int		rng_wait_time;
-+	ktime_t			rngtime;
-+	struct hwrng		rng;
-+#endif
-+};
-+
-+#define	HIFN_D_LENGTH			0x0000ffff
-+#define	HIFN_D_NOINVALID		0x01000000
-+#define	HIFN_D_MASKDONEIRQ		0x02000000
-+#define	HIFN_D_DESTOVER			0x04000000
-+#define	HIFN_D_OVER			0x08000000
-+#define	HIFN_D_LAST			0x20000000
-+#define	HIFN_D_JUMP			0x40000000
-+#define	HIFN_D_VALID			0x80000000
-+
-+struct hifn_base_command
-+{
-+	volatile u16		masks;
-+	volatile u16		session_num;
-+	volatile u16		total_source_count;
-+	volatile u16		total_dest_count;
-+};
-+
-+#define	HIFN_BASE_CMD_COMP		0x0100	/* enable compression engine */
-+#define	HIFN_BASE_CMD_PAD		0x0200	/* enable padding engine */
-+#define	HIFN_BASE_CMD_MAC		0x0400	/* enable MAC engine */
-+#define	HIFN_BASE_CMD_CRYPT		0x0800	/* enable crypt engine */
-+#define	HIFN_BASE_CMD_DECODE		0x2000
-+#define	HIFN_BASE_CMD_SRCLEN_M		0xc000
-+#define	HIFN_BASE_CMD_SRCLEN_S		14
-+#define	HIFN_BASE_CMD_DSTLEN_M		0x3000
-+#define	HIFN_BASE_CMD_DSTLEN_S		12
-+#define	HIFN_BASE_CMD_LENMASK_HI	0x30000
-+#define	HIFN_BASE_CMD_LENMASK_LO	0x0ffff
-+
-+/*
-+ * Structure to help build up the command data structure.
-+ */
-+struct hifn_crypt_command
-+{
-+	volatile u16 		masks;
-+	volatile u16 		header_skip;
-+	volatile u16 		source_count;
-+	volatile u16 		reserved;
-+};
-+
-+#define	HIFN_CRYPT_CMD_ALG_MASK		0x0003		/* algorithm: */
-+#define	HIFN_CRYPT_CMD_ALG_DES		0x0000		/*   DES */
-+#define	HIFN_CRYPT_CMD_ALG_3DES		0x0001		/*   3DES */
-+#define	HIFN_CRYPT_CMD_ALG_RC4		0x0002		/*   RC4 */
-+#define	HIFN_CRYPT_CMD_ALG_AES		0x0003		/*   AES */
-+#define	HIFN_CRYPT_CMD_MODE_MASK	0x0018		/* Encrypt mode: */
-+#define	HIFN_CRYPT_CMD_MODE_ECB		0x0000		/*   ECB */
-+#define	HIFN_CRYPT_CMD_MODE_CBC		0x0008		/*   CBC */
-+#define	HIFN_CRYPT_CMD_MODE_CFB		0x0010		/*   CFB */
-+#define	HIFN_CRYPT_CMD_MODE_OFB		0x0018		/*   OFB */
-+#define	HIFN_CRYPT_CMD_CLR_CTX		0x0040		/* clear context */
-+#define	HIFN_CRYPT_CMD_KSZ_MASK		0x0600		/* AES key size: */
-+#define	HIFN_CRYPT_CMD_KSZ_128		0x0000		/*  128 bit */
-+#define	HIFN_CRYPT_CMD_KSZ_192		0x0200		/*  192 bit */
-+#define	HIFN_CRYPT_CMD_KSZ_256		0x0400		/*  256 bit */
-+#define	HIFN_CRYPT_CMD_NEW_KEY		0x0800		/* expect new key */
-+#define	HIFN_CRYPT_CMD_NEW_IV		0x1000		/* expect new iv */
-+#define	HIFN_CRYPT_CMD_SRCLEN_M		0xc000
-+#define	HIFN_CRYPT_CMD_SRCLEN_S		14
-+
-+/*
-+ * Structure to help build up the command data structure.
-+ */
-+struct hifn_mac_command
-+{
-+	volatile u16 		masks;
-+	volatile u16 		header_skip;
-+	volatile u16 		source_count;
-+	volatile u16 		reserved;
-+};
-+
-+#define	HIFN_MAC_CMD_ALG_MASK		0x0001
-+#define	HIFN_MAC_CMD_ALG_SHA1		0x0000
-+#define	HIFN_MAC_CMD_ALG_MD5		0x0001
-+#define	HIFN_MAC_CMD_MODE_MASK		0x000c
-+#define	HIFN_MAC_CMD_MODE_HMAC		0x0000
-+#define	HIFN_MAC_CMD_MODE_SSL_MAC	0x0004
-+#define	HIFN_MAC_CMD_MODE_HASH		0x0008
-+#define	HIFN_MAC_CMD_MODE_FULL		0x0004
-+#define	HIFN_MAC_CMD_TRUNC		0x0010
-+#define	HIFN_MAC_CMD_RESULT		0x0020
-+#define	HIFN_MAC_CMD_APPEND		0x0040
-+#define	HIFN_MAC_CMD_SRCLEN_M		0xc000
-+#define	HIFN_MAC_CMD_SRCLEN_S		14
-+
-+/*
-+ * MAC POS IPsec initiates authentication after encryption on encodes
-+ * and before decryption on decodes.
-+ */
-+#define	HIFN_MAC_CMD_POS_IPSEC		0x0200
-+#define	HIFN_MAC_CMD_NEW_KEY		0x0800
-+
-+struct hifn_comp_command
-+{
-+	volatile u16 		masks;
-+	volatile u16 		header_skip;
-+	volatile u16 		source_count;
-+	volatile u16 		reserved;
-+};
-+
-+#define	HIFN_COMP_CMD_SRCLEN_M		0xc000
-+#define	HIFN_COMP_CMD_SRCLEN_S		14
-+#define	HIFN_COMP_CMD_ONE		0x0100	/* must be one */
-+#define	HIFN_COMP_CMD_CLEARHIST		0x0010	/* clear history */
-+#define	HIFN_COMP_CMD_UPDATEHIST	0x0008	/* update history */
-+#define	HIFN_COMP_CMD_LZS_STRIP0	0x0004	/* LZS: strip zero */
-+#define	HIFN_COMP_CMD_MPPC_RESTART	0x0004	/* MPPC: restart */
-+#define	HIFN_COMP_CMD_ALG_MASK		0x0001	/* compression mode: */
-+#define	HIFN_COMP_CMD_ALG_MPPC		0x0001	/*   MPPC */
-+#define	HIFN_COMP_CMD_ALG_LZS		0x0000	/*   LZS */
-+
-+struct hifn_base_result
-+{
-+	volatile u16 		flags;
-+	volatile u16 		session;
-+	volatile u16 		src_cnt;		/* 15:0 of source count */
-+	volatile u16 		dst_cnt;		/* 15:0 of dest count */
-+};
-+
-+#define	HIFN_BASE_RES_DSTOVERRUN	0x0200	/* destination overrun */
-+#define	HIFN_BASE_RES_SRCLEN_M		0xc000	/* 17:16 of source count */
-+#define	HIFN_BASE_RES_SRCLEN_S		14
-+#define	HIFN_BASE_RES_DSTLEN_M		0x3000	/* 17:16 of dest count */
-+#define	HIFN_BASE_RES_DSTLEN_S		12
-+
-+struct hifn_comp_result
-+{
-+	volatile u16 		flags;
-+	volatile u16 		crc;
-+};
-+
-+#define	HIFN_COMP_RES_LCB_M		0xff00	/* longitudinal check byte */
-+#define	HIFN_COMP_RES_LCB_S		8
-+#define	HIFN_COMP_RES_RESTART		0x0004	/* MPPC: restart */
-+#define	HIFN_COMP_RES_ENDMARKER		0x0002	/* LZS: end marker seen */
-+#define	HIFN_COMP_RES_SRC_NOTZERO	0x0001	/* source expired */
-+
-+struct hifn_mac_result
-+{
-+	volatile u16 		flags;
-+	volatile u16 		reserved;
-+	/* followed by 0, 6, 8, or 10 u16's of the MAC, then crypt */
-+};
-+
-+#define	HIFN_MAC_RES_MISCOMPARE		0x0002	/* compare failed */
-+#define	HIFN_MAC_RES_SRC_NOTZERO	0x0001	/* source expired */
-+
-+struct hifn_crypt_result
-+{
-+	volatile u16 		flags;
-+	volatile u16 		reserved;
-+};
-+
-+#define	HIFN_CRYPT_RES_SRC_NOTZERO	0x0001	/* source expired */
-+
-+#ifndef HIFN_POLL_FREQUENCY
-+#define	HIFN_POLL_FREQUENCY	0x1
-+#endif
-+
-+#ifndef HIFN_POLL_SCALAR
-+#define	HIFN_POLL_SCALAR	0x0
-+#endif
-+
-+#define	HIFN_MAX_SEGLEN 	0xffff		/* maximum dma segment len */
-+#define	HIFN_MAX_DMALEN		0x3ffff		/* maximum dma length */
-+
-+struct hifn_crypto_alg
-+{
-+	struct list_head	entry;
-+	struct crypto_alg	alg;
-+	struct hifn_device	*dev;
-+};
-+
-+#define ASYNC_SCATTERLIST_CACHE	16
-+
-+#define ASYNC_FLAGS_MISALIGNED	(1<<0)
-+
-+struct ablkcipher_walk
-+{
-+	struct scatterlist	cache[ASYNC_SCATTERLIST_CACHE];
-+	u32			flags;
-+	int			num;
+ 
+ #include <asm/mach-au1x00/au1xxx.h>
+ #include <asm/mach-au1x00/au1xxx_psc.h>
+ 
+-#include "i2c-au1550.h"
++struct i2c_au1550_data {
++	u32	psc_base;
++	int	xfer_timeout;
++	int	ack_timeout;
++	struct i2c_adapter adap;
++	struct resource *ioarea;
 +};
+ 
+ static int
+ wait_xfer_done(struct i2c_au1550_data *adap)
+@@ -105,7 +113,7 @@ wait_master_done(struct i2c_au1550_data *adap)
+ }
+ 
+ static int
+-do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
++do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
+ {
+ 	volatile psc_smb_t	*sp;
+ 	u32			stat;
+@@ -134,6 +142,10 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
+ 	if (rd)
+ 		addr |= 1;
+ 
++	/* zero-byte xfers stop immediately */
++	if (q)
++		addr |= PSC_SMBTXRX_STP;
 +
-+struct hifn_context
-+{
-+	u8			key[HIFN_MAX_CRYPT_KEY_LENGTH], *iv;
-+	struct hifn_device	*dev;
-+	unsigned int		keysize, ivsize;
-+	u8			op, type, mode, unused;
-+	struct ablkcipher_walk	walk;
-+	atomic_t		sg_num;
-+};
+ 	/* Put byte into fifo, start up master.
+ 	*/
+ 	sp->psc_smbtxrx = addr;
+@@ -142,7 +154,7 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
+ 	au_sync();
+ 	if (wait_ack(adap))
+ 		return -EIO;
+-	return 0;
++	return (q) ? wait_master_done(adap) : 0;
+ }
+ 
+ static u32
+@@ -262,7 +274,8 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+ 
+ 	for (i = 0; !err && i < num; i++) {
+ 		p = &msgs[i];
+-		err = do_address(adap, p->addr, p->flags & I2C_M_RD);
++		err = do_address(adap, p->addr, p->flags & I2C_M_RD,
++				 (p->len == 0));
+ 		if (err || !p->len)
+ 			continue;
+ 		if (p->flags & I2C_M_RD)
+@@ -294,18 +307,48 @@ static const struct i2c_algorithm au1550_algo = {
+  * Prior to calling us, the 50MHz clock frequency and routing
+  * must have been set up for the PSC indicated by the adapter.
+  */
+-int
+-i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
++static int __devinit
++i2c_au1550_probe(struct platform_device *pdev)
+ {
+-	struct i2c_au1550_data *adap = i2c_adap->algo_data;
+-	volatile psc_smb_t	*sp;
+-	u32	stat;
++	struct i2c_au1550_data *priv;
++	volatile psc_smb_t *sp;
++	struct resource *r;
++	u32 stat;
++	int ret;
 +
-+#define crypto_alg_to_hifn(a)	container_of(a, struct hifn_crypto_alg, alg)
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!r) {
++		ret = -ENODEV;
++		goto out;
++	}
 +
-+static inline u32 hifn_read_0(struct hifn_device *dev, u32 reg)
-+{
-+	u32 ret;
++	priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
++	if (!priv) {
++		ret = -ENOMEM;
++		goto out;
++	}
 +
-+	ret = readl((char *)(dev->bar[0]) + reg);
++	priv->ioarea = request_mem_region(r->start, r->end - r->start + 1,
++					  pdev->name);
++	if (!priv->ioarea) {
++		ret = -EBUSY;
++		goto out_mem;
++	}
+ 
+-	i2c_adap->algo = &au1550_algo;
++	priv->psc_base = r->start;
++	priv->xfer_timeout = 200;
++	priv->ack_timeout = 200;
 +
++	priv->adap.id = I2C_HW_AU1550_PSC;
++	priv->adap.nr = pdev->id;
++	priv->adap.algo = &au1550_algo;
++	priv->adap.algo_data = priv;
++	priv->adap.dev.parent = &pdev->dev;
++	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
+ 
+ 	/* Now, set up the PSC for SMBus PIO mode.
+ 	*/
+-	sp = (volatile psc_smb_t *)(adap->psc_base);
++	sp = (volatile psc_smb_t *)priv->psc_base;
+ 	sp->psc_ctrl = PSC_CTRL_DISABLE;
+ 	au_sync();
+ 	sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
+@@ -343,87 +386,87 @@ i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
+ 		au_sync();
+ 	} while ((stat & PSC_SMBSTAT_DR) == 0);
+ 
+-	return i2c_add_adapter(i2c_adap);
+-}
++	ret = i2c_add_numbered_adapter(&priv->adap);
++	if (ret == 0) {
++		platform_set_drvdata(pdev, priv);
++		return 0;
++	}
+ 
++	/* disable the PSC */
++	sp->psc_smbcfg = 0;
++	sp->psc_ctrl = PSC_CTRL_DISABLE;
++	au_sync();
+ 
+-int
+-i2c_au1550_del_bus(struct i2c_adapter *adap)
++	release_resource(priv->ioarea);
++	kfree(priv->ioarea);
++out_mem:
++	kfree(priv);
++out:
 +	return ret;
 +}
 +
-+static inline u32 hifn_read_1(struct hifn_device *dev, u32 reg)
-+{
-+	u32 ret;
-+
-+	ret = readl((char *)(dev->bar[1]) + reg);
-+
-+	return ret;
-+}
++static int __devexit
++i2c_au1550_remove(struct platform_device *pdev)
+ {
+-	return i2c_del_adapter(adap);
++	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
++	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
 +
-+static inline void hifn_write_0(struct hifn_device *dev, u32 reg, u32 val)
-+{
-+	writel(val, (char *)(dev->bar[0]) + reg);
-+}
++	platform_set_drvdata(pdev, NULL);
++	i2c_del_adapter(&priv->adap);
++	sp->psc_smbcfg = 0;
++	sp->psc_ctrl = PSC_CTRL_DISABLE;
++	au_sync();
++	release_resource(priv->ioarea);
++	kfree(priv->ioarea);
++	kfree(priv);
++	return 0;
+ }
+ 
+ static int
+-pb1550_reg(struct i2c_client *client)
++i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+ {
++	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
++	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
 +
-+static inline void hifn_write_1(struct hifn_device *dev, u32 reg, u32 val)
-+{
-+	writel(val, (char *)(dev->bar[1]) + reg);
-+}
++	sp->psc_ctrl = PSC_CTRL_SUSPEND;
++	au_sync();
+ 	return 0;
+ }
+ 
+ static int
+-pb1550_unreg(struct i2c_client *client)
++i2c_au1550_resume(struct platform_device *pdev)
+ {
++	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
++	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
 +
-+static void hifn_wait_puc(struct hifn_device *dev)
-+{
-+	int i;
-+	u32 ret;
++	sp->psc_ctrl = PSC_CTRL_ENABLE;
++	au_sync();
++	while (!(sp->psc_smbstat & PSC_SMBSTAT_SR))
++		au_sync();
+ 	return 0;
+ }
+ 
+-static struct i2c_au1550_data pb1550_i2c_info = {
+-	SMBUS_PSC_BASE, 200, 200
+-};
+-
+-static struct i2c_adapter pb1550_board_adapter = {
+-	name:              "pb1550 adapter",
+-	id:                I2C_HW_AU1550_PSC,
+-	algo:              NULL,
+-	algo_data:         &pb1550_i2c_info,
+-	client_register:   pb1550_reg,
+-	client_unregister: pb1550_unreg,
++static struct platform_driver au1xpsc_smbus_driver = {
++	.driver = {
++		.name	= "au1xpsc_smbus",
++		.owner	= THIS_MODULE,
++	},
++	.probe		= i2c_au1550_probe,
++	.remove		= __devexit_p(i2c_au1550_remove),
++	.suspend	= i2c_au1550_suspend,
++	.resume		= i2c_au1550_resume,
+ };
+ 
+-/* BIG hack to support the control interface on the Wolfson WM8731
+- * audio codec on the Pb1550 board.  We get an address and two data
+- * bytes to write, create an i2c message, and send it across the
+- * i2c transfer function.  We do this here because we have access to
+- * the i2c adapter structure.
+- */
+-static struct i2c_msg wm_i2c_msg;  /* We don't want this stuff on the stack */
+-static	u8 i2cbuf[2];
+-
+-int
+-pb1550_wm_codec_write(u8 addr, u8 reg, u8 val)
+-{
+-	wm_i2c_msg.addr = addr;
+-	wm_i2c_msg.flags = 0;
+-	wm_i2c_msg.buf = i2cbuf;
+-	wm_i2c_msg.len = 2;
+-	i2cbuf[0] = reg;
+-	i2cbuf[1] = val;
+-
+-	return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, &wm_i2c_msg, 1);
+-}
+-
+ static int __init
+ i2c_au1550_init(void)
+ {
+-	printk(KERN_INFO "Au1550 I2C: ");
+-
+-	/* This is where we would set up a 50MHz clock source
+-	 * and routing.  On the Pb1550, the SMBus is PSC2, which
+-	 * uses a shared clock with USB.  This has been already
+-	 * configured by Yamon as a 48MHz clock, close enough
+-	 * for our work.
+-	 */
+-        if (i2c_au1550_add_bus(&pb1550_board_adapter) < 0) {
+-		printk("failed to initialize.\n");
+-                return -ENODEV;
+-	}
+-
+-	printk("initialized.\n");
+-	return 0;
++	return platform_driver_register(&au1xpsc_smbus_driver);
+ }
+ 
+ static void __exit
+ i2c_au1550_exit(void)
+ {
+-	i2c_au1550_del_bus(&pb1550_board_adapter);
++	platform_driver_unregister(&au1xpsc_smbus_driver);
+ }
+ 
+ MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
+diff --git a/drivers/i2c/busses/i2c-au1550.h b/drivers/i2c/busses/i2c-au1550.h
+deleted file mode 100644
+index fce15d1..0000000
+--- a/drivers/i2c/busses/i2c-au1550.h
++++ /dev/null
+@@ -1,32 +0,0 @@
+-/*
+- * Copyright (C) 2004 Embedded Edge, LLC <dan at embeddededge.com>
+- * 2.6 port by Matt Porter <mporter at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef I2C_AU1550_H
+-#define I2C_AU1550_H
+-
+-struct i2c_au1550_data {
+-	u32	psc_base;
+-	int	xfer_timeout;
+-	int	ack_timeout;
+-};
+-
+-int i2c_au1550_add_bus(struct i2c_adapter *);
+-int i2c_au1550_del_bus(struct i2c_adapter *);
+-
+-#endif /* I2C_AU1550_H */
+diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
+index 67224a4..7dbdaeb 100644
+--- a/drivers/i2c/busses/i2c-bfin-twi.c
++++ b/drivers/i2c/busses/i2c-bfin-twi.c
+@@ -550,6 +550,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
+ 
+ 	p_adap = &iface->adap;
+ 	p_adap->id = I2C_HW_BLACKFIN;
++	p_adap->nr = dev->id;
+ 	strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
+ 	p_adap->algo = &bfin_twi_algorithm;
+ 	p_adap->algo_data = iface;
+@@ -576,7 +577,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
+ 	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
+ 	SSYNC();
+ 
+-	rc = i2c_add_adapter(p_adap);
++	rc = i2c_add_numbered_adapter(p_adap);
+ 	if (rc < 0)
+ 		free_irq(iface->irq, iface);
+ 	else
+diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
+index 6767988..cce5a61 100644
+--- a/drivers/i2c/busses/i2c-davinci.c
++++ b/drivers/i2c/busses/i2c-davinci.c
+@@ -510,7 +510,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
+ 
+ 	/* FIXME */
+ 	adap->timeout = 1;
+-	adap->retries = 1;
+ 
+ 	adap->nr = pdev->id;
+ 	r = i2c_add_numbered_adapter(adap);
+diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
+index ac27e5f..aa91579 100644
+--- a/drivers/i2c/busses/i2c-i801.c
++++ b/drivers/i2c/busses/i2c-i801.c
+@@ -4,6 +4,7 @@
+     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol at dds.nl>,
+     Philip Edelbrock <phil at netroedge.com>, and Mark D. Studebaker
+     <mdsxyz123 at yahoo.com>
++    Copyright (C) 2007         Jean Delvare <khali at linux-fr.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
+@@ -21,25 +22,34 @@
+ */
+ 
+ /*
+-    SUPPORTED DEVICES	PCI ID
+-    82801AA		2413
+-    82801AB		2423
+-    82801BA		2443
+-    82801CA/CAM		2483
+-    82801DB		24C3   (HW PEC supported)
+-    82801EB		24D3   (HW PEC supported)
+-    6300ESB		25A4
+-    ICH6		266A
+-    ICH7		27DA
+-    ESB2		269B
+-    ICH8		283E
+-    ICH9		2930
+-    Tolapai		5032
+-    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
+-    For SMBus support, they are similar to the PIIX4 and are part
+-    of Intel's '810' and other chipsets.
+-    See the file Documentation/i2c/busses/i2c-i801 for details.
+-    I2C Block Read and Process Call are not supported.
++  Supports the following Intel I/O Controller Hubs (ICH):
 +
-+	for (i=10000; i > 0; --i) {
-+		ret = hifn_read_0(dev, HIFN_0_PUCTRL);
-+		if (!(ret & HIFN_PUCTRL_RESET))
-+			break;
++                                  I/O                     Block   I2C
++                                  region  SMBus   Block   proc.   block
++  Chip name             PCI ID    size    PEC     buffer  call    read
++  ----------------------------------------------------------------------
++  82801AA  (ICH)        0x2413     16      no      no      no      no
++  82801AB  (ICH0)       0x2423     16      no      no      no      no
++  82801BA  (ICH2)       0x2443     16      no      no      no      no
++  82801CA  (ICH3)       0x2483     32     soft     no      no      no
++  82801DB  (ICH4)       0x24c3     32     hard     yes     no      no
++  82801E   (ICH5)       0x24d3     32     hard     yes     yes     yes
++  6300ESB               0x25a4     32     hard     yes     yes     yes
++  82801F   (ICH6)       0x266a     32     hard     yes     yes     yes
++  6310ESB/6320ESB       0x269b     32     hard     yes     yes     yes
++  82801G   (ICH7)       0x27da     32     hard     yes     yes     yes
++  82801H   (ICH8)       0x283e     32     hard     yes     yes     yes
++  82801I   (ICH9)       0x2930     32     hard     yes     yes     yes
++  Tolapai               0x5032     32     hard     yes     ?       ?
 +
-+		udelay(1);
-+	}
++  Features supported by this driver:
++  Software PEC                     no
++  Hardware PEC                     yes
++  Block buffer                     yes
++  Block process call transaction   no
++  I2C block read transaction       yes  (doesn't use the block buffer)
 +
-+	if (!i)
-+		dprintk("%s: Failed to reset PUC unit.\n", dev->name);
-+}
++  See the file Documentation/i2c/busses/i2c-i801 for details.
+ */
+ 
+ /* Note: we assume there can only be one I801, with one SMBus interface */
+@@ -62,9 +72,9 @@
+ #define SMBHSTDAT0	(5 + i801_smba)
+ #define SMBHSTDAT1	(6 + i801_smba)
+ #define SMBBLKDAT	(7 + i801_smba)
+-#define SMBPEC		(8 + i801_smba)	/* ICH4 only */
+-#define SMBAUXSTS	(12 + i801_smba)	/* ICH4 only */
+-#define SMBAUXCTL	(13 + i801_smba)	/* ICH4 only */
++#define SMBPEC		(8 + i801_smba)		/* ICH3 and later */
++#define SMBAUXSTS	(12 + i801_smba)	/* ICH4 and later */
++#define SMBAUXCTL	(13 + i801_smba)	/* ICH4 and later */
+ 
+ /* PCI Address Constants */
+ #define SMBBAR		4
+@@ -91,13 +101,13 @@
+ #define I801_BYTE		0x04
+ #define I801_BYTE_DATA		0x08
+ #define I801_WORD_DATA		0x0C
+-#define I801_PROC_CALL		0x10	/* later chips only, unimplemented */
++#define I801_PROC_CALL		0x10	/* unimplemented */
+ #define I801_BLOCK_DATA		0x14
+-#define I801_I2C_BLOCK_DATA	0x18	/* unimplemented */
++#define I801_I2C_BLOCK_DATA	0x18	/* ICH5 and later */
+ #define I801_BLOCK_LAST		0x34
+-#define I801_I2C_BLOCK_LAST	0x38	/* unimplemented */
++#define I801_I2C_BLOCK_LAST	0x38	/* ICH5 and later */
+ #define I801_START		0x40
+-#define I801_PEC_EN		0x80	/* ICH4 only */
++#define I801_PEC_EN		0x80	/* ICH3 and later */
+ 
+ /* I801 Hosts Status register bits */
+ #define SMBHSTSTS_BYTE_DONE	0x80
+@@ -113,7 +123,12 @@ static unsigned long i801_smba;
+ static unsigned char i801_original_hstcfg;
+ static struct pci_driver i801_driver;
+ static struct pci_dev *I801_dev;
+-static int isich4;
 +
-+static void hifn_reset_puc(struct hifn_device *dev)
-+{
-+	hifn_write_0(dev, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
-+	hifn_wait_puc(dev);
-+}
++#define FEATURE_SMBUS_PEC	(1 << 0)
++#define FEATURE_BLOCK_BUFFER	(1 << 1)
++#define FEATURE_BLOCK_PROC	(1 << 2)
++#define FEATURE_I2C_BLOCK_READ	(1 << 3)
++static unsigned int i801_features;
+ 
+ static int i801_transaction(int xact)
+ {
+@@ -242,7 +257,8 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
+ }
+ 
+ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+-					       char read_write, int hwpec)
++					       char read_write, int command,
++					       int hwpec)
+ {
+ 	int i, len;
+ 	int smbcmd;
+@@ -259,16 +275,24 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+ 	}
+ 
+ 	for (i = 1; i <= len; i++) {
+-		if (i == len && read_write == I2C_SMBUS_READ)
+-			smbcmd = I801_BLOCK_LAST;
+-		else
+-			smbcmd = I801_BLOCK_DATA;
++		if (i == len && read_write == I2C_SMBUS_READ) {
++			if (command == I2C_SMBUS_I2C_BLOCK_DATA)
++				smbcmd = I801_I2C_BLOCK_LAST;
++			else
++				smbcmd = I801_BLOCK_LAST;
++		} else {
++			if (command == I2C_SMBUS_I2C_BLOCK_DATA
++			 && read_write == I2C_SMBUS_READ)
++				smbcmd = I801_I2C_BLOCK_DATA;
++			else
++				smbcmd = I801_BLOCK_DATA;
++		}
+ 		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
+ 
+ 		dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
+-			"ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
++			"ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
+ 			inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
+-			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
++			inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
+ 
+ 		/* Make sure the SMBus host is ready to start transmitting */
+ 		temp = inb_p(SMBHSTSTS);
+@@ -332,7 +356,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+ 			dev_dbg(&I801_dev->dev, "Error: no response!\n");
+ 		}
+ 
+-		if (i == 1 && read_write == I2C_SMBUS_READ) {
++		if (i == 1 && read_write == I2C_SMBUS_READ
++		 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+ 			len = inb_p(SMBHSTDAT0);
+ 			if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
+ 				return -1;
+@@ -353,9 +378,9 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
+ 				temp);
+ 		}
+ 		dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
+-			"ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
++			"ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
+ 			inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
+-			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
++			inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
+ 
+ 		if (result < 0)
+ 			return result;
+@@ -384,33 +409,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
+ 			pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+ 			pci_write_config_byte(I801_dev, SMBHSTCFG,
+ 					      hostc | SMBHSTCFG_I2C_EN);
+-		} else {
++		} else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
+ 			dev_err(&I801_dev->dev,
+-				"I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
++				"I2C block read is unsupported!\n");
+ 			return -1;
+ 		}
+ 	}
+ 
+-	if (read_write == I2C_SMBUS_WRITE) {
++	if (read_write == I2C_SMBUS_WRITE
++	 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
+ 		if (data->block[0] < 1)
+ 			data->block[0] = 1;
+ 		if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
+ 			data->block[0] = I2C_SMBUS_BLOCK_MAX;
+ 	} else {
+-		data->block[0] = 32;	/* max for reads */
++		data->block[0] = 32;	/* max for SMBus block reads */
+ 	}
+ 
+-	if (isich4 && i801_set_block_buffer_mode() == 0 )
++	if ((i801_features & FEATURE_BLOCK_BUFFER)
++	 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
++	      && read_write == I2C_SMBUS_READ)
++	 && i801_set_block_buffer_mode() == 0)
+ 		result = i801_block_transaction_by_block(data, read_write,
+ 							 hwpec);
+ 	else
+ 		result = i801_block_transaction_byte_by_byte(data, read_write,
+-							     hwpec);
++							     command, hwpec);
+ 
+ 	if (result == 0 && hwpec)
+ 		i801_wait_hwpec();
+ 
+-	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
++	if (command == I2C_SMBUS_I2C_BLOCK_DATA
++	 && read_write == I2C_SMBUS_WRITE) {
+ 		/* restore saved configuration register value */
+ 		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
+ 	}
+@@ -426,7 +456,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
+ 	int block = 0;
+ 	int ret, xact = 0;
+ 
+-	hwpec = isich4 && (flags & I2C_CLIENT_PEC)
++	hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
+ 		&& size != I2C_SMBUS_QUICK
+ 		&& size != I2C_SMBUS_I2C_BLOCK_DATA;
+ 
+@@ -462,12 +492,23 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
+ 		xact = I801_WORD_DATA;
+ 		break;
+ 	case I2C_SMBUS_BLOCK_DATA:
+-	case I2C_SMBUS_I2C_BLOCK_DATA:
+ 		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+ 		       SMBHSTADD);
+ 		outb_p(command, SMBHSTCMD);
+ 		block = 1;
+ 		break;
++	case I2C_SMBUS_I2C_BLOCK_DATA:
++		/* NB: page 240 of ICH5 datasheet shows that the R/#W
++		 * bit should be cleared here, even when reading */
++		outb_p((addr & 0x7f) << 1, SMBHSTADD);
++		if (read_write == I2C_SMBUS_READ) {
++			/* NB: page 240 of ICH5 datasheet also shows
++			 * that DATA1 is the cmd field when reading */
++			outb_p(command, SMBHSTDAT1);
++		} else
++			outb_p(command, SMBHSTCMD);
++		block = 1;
++		break;
+ 	case I2C_SMBUS_PROC_CALL:
+ 	default:
+ 		dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
+@@ -487,7 +528,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
+ 	/* Some BIOSes don't like it when PEC is enabled at reboot or resume
+ 	   time, so we forcibly disable it after every transaction. Turn off
+ 	   E32B for the same reason. */
+-	if (hwpec)
++	if (hwpec || block)
+ 		outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
+ 		       SMBAUXCTL);
+ 
+@@ -514,9 +555,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
+ static u32 i801_func(struct i2c_adapter *adapter)
+ {
+ 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+-	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+-	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
+-	     | (isich4 ? I2C_FUNC_SMBUS_PEC : 0);
++	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
++	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
++	       ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
++	       ((i801_features & FEATURE_I2C_BLOCK_READ) ?
++		I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
+ }
+ 
+ static const struct i2c_algorithm smbus_algorithm = {
+@@ -556,8 +599,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
+ 	int err;
+ 
+ 	I801_dev = dev;
++	i801_features = 0;
+ 	switch (dev->device) {
+-	case PCI_DEVICE_ID_INTEL_82801DB_3:
+ 	case PCI_DEVICE_ID_INTEL_82801EB_3:
+ 	case PCI_DEVICE_ID_INTEL_ESB_4:
+ 	case PCI_DEVICE_ID_INTEL_ICH6_16:
+@@ -565,11 +608,13 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
+ 	case PCI_DEVICE_ID_INTEL_ESB2_17:
+ 	case PCI_DEVICE_ID_INTEL_ICH8_5:
+ 	case PCI_DEVICE_ID_INTEL_ICH9_6:
++		i801_features |= FEATURE_I2C_BLOCK_READ;
++		/* fall through */
++	case PCI_DEVICE_ID_INTEL_82801DB_3:
+ 	case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
+-		isich4 = 1;
++		i801_features |= FEATURE_SMBUS_PEC;
++		i801_features |= FEATURE_BLOCK_BUFFER;
+ 		break;
+-	default:
+-		isich4 = 0;
+ 	}
+ 
+ 	err = pci_enable_device(dev);
+@@ -610,6 +655,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
+ 	else
+ 		dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
+ 
++	/* Clear special mode bits */
++	if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
++		outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
++		       SMBAUXCTL);
 +
-+static void hifn_stop_device(struct hifn_device *dev)
-+{
-+	hifn_write_1(dev, HIFN_1_DMA_CSR,
-+		HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
-+		HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS);
-+	hifn_write_0(dev, HIFN_0_PUIER, 0);
-+	hifn_write_1(dev, HIFN_1_DMA_IER, 0);
-+}
+ 	/* set up the sysfs linkage to our parent device */
+ 	i801_adapter.dev.parent = &dev->dev;
+ 
+@@ -678,9 +728,8 @@ static void __exit i2c_i801_exit(void)
+ 	pci_unregister_driver(&i801_driver);
+ }
+ 
+-MODULE_AUTHOR ("Frodo Looijaard <frodol at dds.nl>, "
+-		"Philip Edelbrock <phil at netroedge.com>, "
+-		"and Mark D. Studebaker <mdsxyz123 at yahoo.com>");
++MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123 at yahoo.com>, "
++	      "Jean Delvare <khali at linux-fr.org>");
+ MODULE_DESCRIPTION("I801 SMBus driver");
+ MODULE_LICENSE("GPL");
+ 
+diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
+index 9b43ff7..7c7eb0c 100644
+--- a/drivers/i2c/busses/i2c-ibm_iic.c
++++ b/drivers/i2c/busses/i2c-ibm_iic.c
+@@ -6,7 +6,7 @@
+  * Copyright (c) 2003, 2004 Zultys Technologies.
+  * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+  *
+- * Based on original work by 
++ * Based on original work by
+  * 	Ian DaSilva  <idasilva at mvista.com>
+  *      Armin Kuster <akuster at mvista.com>
+  * 	Matt Porter  <mporter at mvista.com>
+@@ -86,8 +86,8 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
+ 	       KERN_DEBUG "  sts      = 0x%02x, extsts = 0x%02x\n"
+ 	       KERN_DEBUG "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
+ 	       KERN_DEBUG "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
+-		in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), 
+-		in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), 
++		in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
++		in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
+ 		in_8(&iic->xtcntlss), in_8(&iic->directcntl));
+ }
+ #  define DUMP_REGS(h,dev)	dump_iic_regs((h),(dev))
+@@ -125,7 +125,7 @@ static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable)
+ {
+ 	out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0);
+ }
+- 
 +
-+static void hifn_reset_dma(struct hifn_device *dev, int full)
-+{
-+	hifn_stop_device(dev);
+ /*
+  * Initialize IIC interface.
+  */
+@@ -134,7 +134,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 
+ 	DBG("%d: init\n", dev->idx);
+-	
 +
-+	/*
-+	 * Setting poll frequency and others to 0.
-+	 */
-+	hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
-+			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
-+	mdelay(1);
+ 	/* Clear master address */
+ 	out_8(&iic->lmadr, 0);
+ 	out_8(&iic->hmadr, 0);
+@@ -160,7 +160,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
+ 
+ 	/* Clear control register */
+ 	out_8(&iic->cntl, 0);
+-	
 +
-+	/*
-+	 * Reset DMA.
-+	 */
-+	if (full) {
-+		hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE);
-+		mdelay(1);
-+	} else {
-+		hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MODE |
-+				HIFN_DMACNFG_MSTRESET);
-+		hifn_reset_puc(dev);
-+	}
+ 	/* Enable interrupts if possible */
+ 	iic_interrupt_mode(dev, dev->irq >= 0);
+ 
+@@ -171,7 +171,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
+ 	DUMP_REGS("iic_init", dev);
+ }
+ 
+-/* 
++/*
+  * Reset IIC interface
+  */
+ static void iic_dev_reset(struct ibm_iic_private* dev)
+@@ -179,42 +179,42 @@ static void iic_dev_reset(struct ibm_iic_private* dev)
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 	int i;
+ 	u8 dc;
+-	
 +
-+	hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
-+			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
+ 	DBG("%d: soft reset\n", dev->idx);
+ 	DUMP_REGS("reset", dev);
+-	
 +
-+	hifn_reset_puc(dev);
-+}
+     	/* Place chip in the reset state */
+ 	out_8(&iic->xtcntlss, XTCNTLSS_SRST);
+-	
 +
-+static u32 hifn_next_signature(u_int32_t a, u_int cnt)
-+{
-+	int i;
-+	u32 v;
+ 	/* Check if bus is free */
+-	dc = in_8(&iic->directcntl);	
++	dc = in_8(&iic->directcntl);
+ 	if (!DIRCTNL_FREE(dc)){
+ 		DBG("%d: trying to regain bus control\n", dev->idx);
+-	
 +
-+	for (i = 0; i < cnt; i++) {
+ 		/* Try to set bus free state */
+-		out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);	
+-	
++		out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
 +
-+		/* get the parity */
-+		v = a & 0x80080125;
-+		v ^= v >> 16;
-+		v ^= v >> 8;
-+		v ^= v >> 4;
-+		v ^= v >> 2;
-+		v ^= v >> 1;
+ 		/* Wait until we regain bus control */
+ 		for (i = 0; i < 100; ++i){
+ 			dc = in_8(&iic->directcntl);
+ 			if (DIRCTNL_FREE(dc))
+ 				break;
+-			
 +
-+		a = (v & 1) ^ (a << 1);
-+	}
+ 			/* Toggle SCL line */
+ 			dc ^= DIRCNTL_SCC;
+ 			out_8(&iic->directcntl, dc);
+ 			udelay(10);
+ 			dc ^= DIRCNTL_SCC;
+ 			out_8(&iic->directcntl, dc);
+-			
 +
-+	return a;
-+}
+ 			/* be nice */
+ 			cond_resched();
+ 		}
+ 	}
+-	
 +
-+static struct pci2id {
-+	u_short		pci_vendor;
-+	u_short		pci_prod;
-+	char		card_id[13];
-+} pci2id[] = {
-+	{
-+		PCI_VENDOR_ID_HIFN,
-+		PCI_DEVICE_ID_HIFN_7955,
-+		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+		  0x00, 0x00, 0x00, 0x00, 0x00 }
-+	},
-+	{
-+		PCI_VENDOR_ID_HIFN,
-+		PCI_DEVICE_ID_HIFN_7956,
-+		{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-+		  0x00, 0x00, 0x00, 0x00, 0x00 }
-+	}
-+};
+ 	/* Remove reset */
+ 	out_8(&iic->xtcntlss, 0);
+-	
 +
-+#ifdef CRYPTO_DEV_HIFN_795X_RNG
-+static int hifn_rng_data_present(struct hwrng *rng, int wait)
-+{
-+	struct hifn_device *dev = (struct hifn_device *)rng->priv;
-+	s64 nsec;
+ 	/* Reinitialize interface */
+ 	iic_dev_init(dev);
+ }
+@@ -324,14 +324,14 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
+ {
+ 	struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+-	
+-	DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", 
 +
-+	nsec = ktime_to_ns(ktime_sub(ktime_get(), dev->rngtime));
-+	nsec -= dev->rng_wait_time;
-+	if (nsec <= 0)
-+		return 1;
-+	if (!wait)
-+		return 0;
-+	ndelay(nsec);
-+	return 1;
-+}
++	DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n",
+ 	     dev->idx, in_8(&iic->sts), in_8(&iic->extsts));
+-	
 +
-+static int hifn_rng_data_read(struct hwrng *rng, u32 *data)
-+{
-+	struct hifn_device *dev = (struct hifn_device *)rng->priv;
+ 	/* Acknowledge IRQ and wakeup iic_wait_for_tc */
+ 	out_8(&iic->sts, STS_IRQA | STS_SCMP);
+ 	wake_up_interruptible(&dev->wq);
+-	
 +
-+	*data = hifn_read_1(dev, HIFN_1_RNG_DATA);
-+	dev->rngtime = ktime_get();
-+	return 4;
-+}
+ 	return IRQ_HANDLED;
+ }
+ 
+@@ -341,19 +341,19 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
+  */
+ static int iic_xfer_result(struct ibm_iic_private* dev)
+ {
+-	volatile struct iic_regs __iomem *iic = dev->vaddr;	
+-	
++	volatile struct iic_regs __iomem *iic = dev->vaddr;
 +
-+static int hifn_register_rng(struct hifn_device *dev)
-+{
-+	/*
-+	 * We must wait at least 256 Pk_clk cycles between two reads of the rng.
-+	 */
-+	dev->rng_wait_time	= DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) *
-+				  256;
+ 	if (unlikely(in_8(&iic->sts) & STS_ERR)){
+-		DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, 
++		DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx,
+ 			in_8(&iic->extsts));
+-				
 +
-+	dev->rng.name		= dev->name;
-+	dev->rng.data_present	= hifn_rng_data_present,
-+	dev->rng.data_read	= hifn_rng_data_read,
-+	dev->rng.priv		= (unsigned long)dev;
+ 		/* Clear errors and possible pending IRQs */
+-		out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | 
++		out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |
+ 			EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA);
+-			
 +
-+	return hwrng_register(&dev->rng);
-+}
+ 		/* Flush master data buffer */
+ 		out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
+-		
 +
-+static void hifn_unregister_rng(struct hifn_device *dev)
-+{
-+	hwrng_unregister(&dev->rng);
-+}
-+#else
-+#define hifn_register_rng(dev)		0
-+#define hifn_unregister_rng(dev)
-+#endif
+ 		/* Is bus free?
+ 		 * If error happened during combined xfer
+ 		 * IIC interface is usually stuck in some strange
+@@ -376,11 +376,11 @@ static void iic_abort_xfer(struct ibm_iic_private* dev)
+ {
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 	unsigned long x;
+-	
 +
-+static int hifn_init_pubrng(struct hifn_device *dev)
-+{
-+	int i;
+ 	DBG("%d: iic_abort_xfer\n", dev->idx);
+-	
 +
-+	hifn_write_1(dev, HIFN_1_PUB_RESET, hifn_read_1(dev, HIFN_1_PUB_RESET) |
-+			HIFN_PUBRST_RESET);
+ 	out_8(&iic->cntl, CNTL_HMT);
+-	
 +
-+	for (i=100; i > 0; --i) {
-+		mdelay(1);
+ 	/*
+ 	 * Wait for the abort command to complete.
+ 	 * It's not worth to be optimized, just poll (timeout >= 1 tick)
+@@ -405,13 +405,13 @@ static void iic_abort_xfer(struct ibm_iic_private* dev)
+  * Returns the number of transferred bytes or error (<0)
+  */
+ static int iic_wait_for_tc(struct ibm_iic_private* dev){
+-	
 +
-+		if ((hifn_read_1(dev, HIFN_1_PUB_RESET) & HIFN_PUBRST_RESET) == 0)
-+			break;
-+	}
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 	int ret = 0;
+-	
 +
-+	if (!i)
-+		dprintk("Chip %s: Failed to initialise public key engine.\n",
-+				dev->name);
-+	else {
-+		hifn_write_1(dev, HIFN_1_PUB_IEN, HIFN_PUBIEN_DONE);
-+		dev->dmareg |= HIFN_DMAIER_PUBDONE;
-+		hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
+ 	if (dev->irq >= 0){
+ 		/* Interrupt mode */
+-		ret = wait_event_interruptible_timeout(dev->wq, 
++		ret = wait_event_interruptible_timeout(dev->wq,
+ 			!(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ);
+ 
+ 		if (unlikely(ret < 0))
+@@ -424,37 +424,37 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){
+ 	else {
+ 		/* Polling mode */
+ 		unsigned long x = jiffies + dev->adap.timeout * HZ;
+-		
 +
-+		dprintk("Chip %s: Public key engine has been sucessfully "
-+				"initialised.\n", dev->name);
-+	}
+ 		while (in_8(&iic->sts) & STS_PT){
+ 			if (unlikely(time_after(jiffies, x))){
+ 				DBG("%d: poll timeout\n", dev->idx);
+ 				ret = -ETIMEDOUT;
+ 				break;
+ 			}
+-		
 +
-+	/*
-+	 * Enable RNG engine.
-+	 */
+ 			if (unlikely(signal_pending(current))){
+ 				DBG("%d: poll interrupted\n", dev->idx);
+ 				ret = -ERESTARTSYS;
+ 				break;
+ 			}
+ 			schedule();
+-		}	
++		}
+ 	}
+-	
 +
-+	hifn_write_1(dev, HIFN_1_RNG_CONFIG,
-+			hifn_read_1(dev, HIFN_1_RNG_CONFIG) | HIFN_RNGCFG_ENA);
-+	dprintk("Chip %s: RNG engine has been successfully initialised.\n",
-+			dev->name);
+ 	if (unlikely(ret < 0))
+ 		iic_abort_xfer(dev);
+ 	else
+ 		ret = iic_xfer_result(dev);
+-	
 +
-+#ifdef CRYPTO_DEV_HIFN_795X_RNG
-+	/* First value must be discarded */
-+	hifn_read_1(dev, HIFN_1_RNG_DATA);
-+	dev->rngtime = ktime_get();
-+#endif
-+	return 0;
-+}
+ 	DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret);
+-	
 +
-+static int hifn_enable_crypto(struct hifn_device *dev)
-+{
-+	u32 dmacfg, addr;
-+	char *offtbl = NULL;
-+	int i;
+ 	return ret;
+ }
+ 
+ /*
+  * Low level master transfer routine
+  */
+-static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, 
++static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
+ 			  int combined_xfer)
+ {
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+@@ -465,48 +465,48 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
+ 	u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT;
+ 	if (pm->flags & I2C_M_RD)
+ 		cntl |= CNTL_RW;
+-	
 +
-+	for (i = 0; i < sizeof(pci2id)/sizeof(pci2id[0]); i++) {
-+		if (pci2id[i].pci_vendor == dev->pdev->vendor &&
-+				pci2id[i].pci_prod == dev->pdev->device) {
-+			offtbl = pci2id[i].card_id;
-+			break;
-+		}
-+	}
+ 	loops = (len + 3) / 4;
+ 	for (i = 0; i < loops; ++i, len -= 4){
+ 		int count = len > 4 ? 4 : len;
+ 		u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT);
+-		
 +
-+	if (offtbl == NULL) {
-+		dprintk("Chip %s: Unknown card!\n", dev->name);
-+		return -ENODEV;
-+	}
+ 		if (!(cntl & CNTL_RW))
+ 			for (j = 0; j < count; ++j)
+ 				out_8((void __iomem *)&iic->mdbuf, *buf++);
+-		
 +
-+	dmacfg = hifn_read_1(dev, HIFN_1_DMA_CNFG);
+ 		if (i < loops - 1)
+ 			cmd |= CNTL_CHT;
+ 		else if (combined_xfer)
+ 			cmd |= CNTL_RPST;
+-		
 +
-+	hifn_write_1(dev, HIFN_1_DMA_CNFG,
-+			HIFN_DMACNFG_UNLOCK | HIFN_DMACNFG_MSTRESET |
-+			HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE);
-+	mdelay(1);
-+	addr = hifn_read_1(dev, HIFN_1_UNLOCK_SECRET1);
-+	mdelay(1);
-+	hifn_write_1(dev, HIFN_1_UNLOCK_SECRET2, 0);
-+	mdelay(1);
+ 		DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd);
+-		
 +
-+	for (i=0; i<12; ++i) {
-+		addr = hifn_next_signature(addr, offtbl[i] + 0x101);
-+		hifn_write_1(dev, HIFN_1_UNLOCK_SECRET2, addr);
+ 		/* Start transfer */
+ 		out_8(&iic->cntl, cmd);
+-		
 +
-+		mdelay(1);
-+	}
-+	hifn_write_1(dev, HIFN_1_DMA_CNFG, dmacfg);
+ 		/* Wait for completion */
+ 		ret = iic_wait_for_tc(dev);
+ 
+ 		if (unlikely(ret < 0))
+ 			break;
+ 		else if (unlikely(ret != count)){
+-			DBG("%d: xfer_bytes, requested %d, transfered %d\n", 
++			DBG("%d: xfer_bytes, requested %d, transfered %d\n",
+ 				dev->idx, count, ret);
+-			
 +
-+	dprintk("Chip %s: %s.\n", dev->name, pci_name(dev->pdev));
+ 			/* If it's not a last part of xfer, abort it */
+ 			if (combined_xfer || (i < loops - 1))
+     				iic_abort_xfer(dev);
+-				
 +
-+	return 0;
-+}
+ 			ret = -EREMOTEIO;
+-			break;				
++			break;
+ 		}
+-		
 +
-+static void hifn_init_dma(struct hifn_device *dev)
-+{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	u32 dptr = dev->desc_dma;
-+	int i;
+ 		if (cntl & CNTL_RW)
+ 			for (j = 0; j < count; ++j)
+ 				*buf++ = in_8((void __iomem *)&iic->mdbuf);
+ 	}
+-	
 +
-+	for (i=0; i<HIFN_D_CMD_RSIZE; ++i)
-+		dma->cmdr[i].p = __cpu_to_le32(dptr +
-+				offsetof(struct hifn_dma, command_bufs[i][0]));
-+	for (i=0; i<HIFN_D_RES_RSIZE; ++i)
-+		dma->resr[i].p = __cpu_to_le32(dptr +
-+				offsetof(struct hifn_dma, result_bufs[i][0]));
+ 	return ret > 0 ? 0 : ret;
+ }
+ 
+@@ -517,10 +517,10 @@ static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg)
+ {
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 	u16 addr = msg->addr;
+-	
+-	DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, 
 +
-+	/*
-+	 * Setup LAST descriptors.
-+	 */
-+	dma->cmdr[HIFN_D_CMD_RSIZE].p = __cpu_to_le32(dptr +
-+			offsetof(struct hifn_dma, cmdr[0]));
-+	dma->srcr[HIFN_D_SRC_RSIZE].p = __cpu_to_le32(dptr +
-+			offsetof(struct hifn_dma, srcr[0]));
-+	dma->dstr[HIFN_D_DST_RSIZE].p = __cpu_to_le32(dptr +
-+			offsetof(struct hifn_dma, dstr[0]));
-+	dma->resr[HIFN_D_RES_RSIZE].p = __cpu_to_le32(dptr +
-+			offsetof(struct hifn_dma, resr[0]));
++	DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,
+ 		addr, msg->flags & I2C_M_TEN ? 10 : 7);
+-	
 +
-+	dma->cmdu = dma->srcu = dma->dstu = dma->resu = 0;
-+	dma->cmdi = dma->srci = dma->dsti = dma->resi = 0;
-+	dma->cmdk = dma->srck = dma->dstk = dma->resk = 0;
+ 	if (msg->flags & I2C_M_TEN){
+ 	    out_8(&iic->cntl, CNTL_AMD);
+ 	    out_8(&iic->lmadr, addr);
+@@ -537,15 +537,15 @@ static inline int iic_invalid_address(const struct i2c_msg* p)
+ 	return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f));
+ }
+ 
+-static inline int iic_address_neq(const struct i2c_msg* p1, 
++static inline int iic_address_neq(const struct i2c_msg* p1,
+ 				  const struct i2c_msg* p2)
+ {
+-	return (p1->addr != p2->addr) 
++	return (p1->addr != p2->addr)
+ 		|| ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN));
+-} 
 +}
+ 
+ /*
+- * Generic master transfer entrypoint. 
++ * Generic master transfer entrypoint.
+  * Returns the number of processed messages or error (<0)
+  */
+ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+@@ -553,20 +553,20 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+     	struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
+ 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 	int i, ret = 0;
+-	
 +
-+/*
-+ * Initialize the PLL. We need to know the frequency of the reference clock
-+ * to calculate the optimal multiplier. For PCI we assume 66MHz, since that
-+ * allows us to operate without the risk of overclocking the chip. If it
-+ * actually uses 33MHz, the chip will operate at half the speed, this can be
-+ * overriden by specifying the frequency as module parameter (pci33).
-+ *
-+ * Unfortunately the PCI clock is not very suitable since the HIFN needs a
-+ * stable clock and the PCI clock frequency may vary, so the default is the
-+ * external clock. There is no way to find out its frequency, we default to
-+ * 66MHz since according to Mike Ham of HiFn, almost every board in existence
-+ * has an external crystal populated at 66MHz.
-+ */
-+static void hifn_init_pll(struct hifn_device *dev)
-+{
-+	unsigned int freq, m;
-+	u32 pllcfg;
-+
-+	pllcfg = HIFN_1_PLL | HIFN_PLL_RESERVED_1;
+ 	DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
+-	
 +
-+	if (strncmp(hifn_pll_ref, "ext", 3) == 0)
-+		pllcfg |= HIFN_PLL_REF_CLK_PLL;
-+	else
-+		pllcfg |= HIFN_PLL_REF_CLK_HBI;
+ 	if (!num)
+ 		return 0;
+-	
 +
-+	if (hifn_pll_ref[3] != '\0')
-+		freq = simple_strtoul(hifn_pll_ref + 3, NULL, 10);
-+	else {
-+		freq = 66;
-+		printk(KERN_INFO "hifn795x: assuming %uMHz clock speed, "
-+				 "override with hifn_pll_ref=%.3s<frequency>\n",
-+		       freq, hifn_pll_ref);
+ 	/* Check the sanity of the passed messages.
+ 	 * Uhh, generic i2c layer is more suitable place for such code...
+ 	 */
+ 	if (unlikely(iic_invalid_address(&msgs[0]))){
+-		DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx, 
++		DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,
+ 			msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7);
+ 		return -EINVAL;
+-	}		
 +	}
+ 	for (i = 0; i < num; ++i){
+ 		if (unlikely(msgs[i].len <= 0)){
+ 			if (num == 1 && !msgs[0].len){
+@@ -576,7 +576,7 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ 				 */
+ 				return iic_smbus_quick(dev, &msgs[0]);
+ 			}
+-			DBG("%d: invalid len %d in msg[%d]\n", dev->idx, 
++			DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
+ 				msgs[i].len, i);
+ 			return -EINVAL;
+ 		}
+@@ -585,34 +585,34 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+ 			return -EINVAL;
+ 		}
+ 	}
+-	
 +
-+	m = HIFN_PLL_FCK_MAX / freq;
-+
-+	pllcfg |= (m / 2 - 1) << HIFN_PLL_ND_SHIFT;
-+	if (m <= 8)
-+		pllcfg |= HIFN_PLL_IS_1_8;
-+	else
-+		pllcfg |= HIFN_PLL_IS_9_12;
-+
-+	/* Select clock source and enable clock bypass */
-+	hifn_write_1(dev, HIFN_1_PLL, pllcfg |
-+		     HIFN_PLL_PK_CLK_HBI | HIFN_PLL_PE_CLK_HBI | HIFN_PLL_BP);
-+
-+	/* Let the chip lock to the input clock */
-+	mdelay(10);
-+
-+	/* Disable clock bypass */
-+	hifn_write_1(dev, HIFN_1_PLL, pllcfg |
-+		     HIFN_PLL_PK_CLK_HBI | HIFN_PLL_PE_CLK_HBI);
-+
-+	/* Switch the engines to the PLL */
-+	hifn_write_1(dev, HIFN_1_PLL, pllcfg |
-+		     HIFN_PLL_PK_CLK_PLL | HIFN_PLL_PE_CLK_PLL);
+ 	/* Check bus state */
+ 	if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){
+ 		DBG("%d: iic_xfer, bus is not free\n", dev->idx);
+-		
 +
-+	/*
-+	 * The Fpk_clk runs at half the total speed. Its frequency is needed to
-+	 * calculate the minimum time between two reads of the rng. Since 33MHz
-+	 * is actually 33.333... we overestimate the frequency here, resulting
-+	 * in slightly larger intervals.
-+	 */
-+	dev->pk_clk_freq = 1000000 * (freq + 1) * m / 2;
-+}
+ 		/* Usually it means something serious has happend.
+ 		 * We *cannot* have unfinished previous transfer
+ 		 * so it doesn't make any sense to try to stop it.
+-		 * Probably we were not able to recover from the 
++		 * Probably we were not able to recover from the
+ 		 * previous error.
+ 		 * The only *reasonable* thing I can think of here
+ 		 * is soft reset.  --ebs
+ 		 */
+ 		iic_dev_reset(dev);
+-		
 +
-+static void hifn_init_registers(struct hifn_device *dev)
-+{
-+	u32 dptr = dev->desc_dma;
+ 		if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
+ 			DBG("%d: iic_xfer, bus is still not free\n", dev->idx);
+ 			return -EREMOTEIO;
+ 		}
+-	} 
++	}
+ 	else {
+ 		/* Flush master data buffer (just in case) */
+ 		out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
+ 	}
+-	
 +
-+	/* Initialization magic... */
-+	hifn_write_0(dev, HIFN_0_PUCTRL, HIFN_PUCTRL_DMAENA);
-+	hifn_write_0(dev, HIFN_0_FIFOCNFG, HIFN_FIFOCNFG_THRESHOLD);
-+	hifn_write_0(dev, HIFN_0_PUIER, HIFN_PUIER_DSTOVER);
+ 	/* Load slave address */
+ 	iic_address(dev, &msgs[0]);
+-	
 +
-+	/* write all 4 ring address registers */
-+	hifn_write_1(dev, HIFN_1_DMA_CRAR, __cpu_to_le32(dptr +
-+				offsetof(struct hifn_dma, cmdr[0])));
-+	hifn_write_1(dev, HIFN_1_DMA_SRAR, __cpu_to_le32(dptr +
-+				offsetof(struct hifn_dma, srcr[0])));
-+	hifn_write_1(dev, HIFN_1_DMA_DRAR, __cpu_to_le32(dptr +
-+				offsetof(struct hifn_dma, dstr[0])));
-+	hifn_write_1(dev, HIFN_1_DMA_RRAR, __cpu_to_le32(dptr +
-+				offsetof(struct hifn_dma, resr[0])));
+ 	/* Do real transfer */
+     	for (i = 0; i < num && !ret; ++i)
+ 		ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1);
+@@ -648,7 +648,7 @@ static inline u8 iic_clckdiv(unsigned int opb)
+ 
+ 	/* Convert to MHz */
+ 	opb /= 1000000;
+-	
 +
-+	mdelay(2);
-+#if 0
-+	hifn_write_1(dev, HIFN_1_DMA_CSR,
-+	    HIFN_DMACSR_D_CTRL_DIS | HIFN_DMACSR_R_CTRL_DIS |
-+	    HIFN_DMACSR_S_CTRL_DIS | HIFN_DMACSR_C_CTRL_DIS |
-+	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
-+	    HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
-+	    HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
-+	    HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
-+	    HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
-+	    HIFN_DMACSR_S_WAIT |
-+	    HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
-+	    HIFN_DMACSR_C_WAIT |
-+	    HIFN_DMACSR_ENGINE |
-+	    HIFN_DMACSR_PUBDONE);
-+#else
-+	hifn_write_1(dev, HIFN_1_DMA_CSR,
-+	    HIFN_DMACSR_C_CTRL_ENA | HIFN_DMACSR_S_CTRL_ENA |
-+	    HIFN_DMACSR_D_CTRL_ENA | HIFN_DMACSR_R_CTRL_ENA |
-+	    HIFN_DMACSR_D_ABORT | HIFN_DMACSR_D_DONE | HIFN_DMACSR_D_LAST |
-+	    HIFN_DMACSR_D_WAIT | HIFN_DMACSR_D_OVER |
-+	    HIFN_DMACSR_R_ABORT | HIFN_DMACSR_R_DONE | HIFN_DMACSR_R_LAST |
-+	    HIFN_DMACSR_R_WAIT | HIFN_DMACSR_R_OVER |
-+	    HIFN_DMACSR_S_ABORT | HIFN_DMACSR_S_DONE | HIFN_DMACSR_S_LAST |
-+	    HIFN_DMACSR_S_WAIT |
-+	    HIFN_DMACSR_C_ABORT | HIFN_DMACSR_C_DONE | HIFN_DMACSR_C_LAST |
-+	    HIFN_DMACSR_C_WAIT |
-+	    HIFN_DMACSR_ENGINE |
-+	    HIFN_DMACSR_PUBDONE);
-+#endif
-+	hifn_read_1(dev, HIFN_1_DMA_CSR);
+ 	if (opb < 20 || opb > 150){
+ 		printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
+ 			opb);
+@@ -666,7 +666,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 	struct i2c_adapter* adap;
+ 	struct ocp_func_iic_data* iic_data = ocp->def->additions;
+ 	int ret;
+-	
 +
-+	dev->dmareg |= HIFN_DMAIER_R_DONE | HIFN_DMAIER_C_ABORT |
-+	    HIFN_DMAIER_D_OVER | HIFN_DMAIER_R_OVER |
-+	    HIFN_DMAIER_S_ABORT | HIFN_DMAIER_D_ABORT | HIFN_DMAIER_R_ABORT |
-+	    HIFN_DMAIER_ENGINE;
-+	dev->dmareg &= ~HIFN_DMAIER_C_WAIT;
+ 	if (!iic_data)
+ 		printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
+ 			ocp->def->index);
+@@ -679,7 +679,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 
+ 	dev->idx = ocp->def->index;
+ 	ocp_set_drvdata(ocp, dev);
+-	
 +
-+	hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
-+	hifn_read_1(dev, HIFN_1_DMA_IER);
-+#if 0
-+	hifn_write_0(dev, HIFN_0_PUCNFG, HIFN_PUCNFG_ENCCNFG |
-+		    HIFN_PUCNFG_DRFR_128 | HIFN_PUCNFG_TCALLPHASES |
-+		    HIFN_PUCNFG_TCDRVTOTEM | HIFN_PUCNFG_BUS32 |
-+		    HIFN_PUCNFG_DRAM);
-+#else
-+	hifn_write_0(dev, HIFN_0_PUCNFG, 0x10342);
-+#endif
-+	hifn_init_pll(dev);
+ 	if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
+ 				"ibm_iic")) {
+ 		ret = -EBUSY;
+@@ -692,7 +692,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 		ret = -ENXIO;
+ 		goto fail2;
+ 	}
+-	
 +
-+	hifn_write_0(dev, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
-+	hifn_write_1(dev, HIFN_1_DMA_CNFG, HIFN_DMACNFG_MSTRESET |
-+	    HIFN_DMACNFG_DMARESET | HIFN_DMACNFG_MODE | HIFN_DMACNFG_LAST |
-+	    ((HIFN_POLL_FREQUENCY << 16 ) & HIFN_DMACNFG_POLLFREQ) |
-+	    ((HIFN_POLL_SCALAR << 8) & HIFN_DMACNFG_POLLINVAL));
-+}
+ 	init_waitqueue_head(&dev->wq);
+ 
+ 	dev->irq = iic_force_poll ? -1 : ocp->def->irq;
+@@ -702,29 +702,29 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 		 */
+ 		iic_interrupt_mode(dev, 0);
+ 		if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
+-			printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", 
++			printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
+ 				dev->idx, dev->irq);
+-			/* Fallback to the polling mode */	
++			/* Fallback to the polling mode */
+ 			dev->irq = -1;
+ 		}
+ 	}
+-	
 +
-+static int hifn_setup_base_command(struct hifn_device *dev, u8 *buf,
-+		unsigned dlen, unsigned slen, u16 mask, u8 snum)
-+{
-+	struct hifn_base_command *base_cmd;
-+	u8 *buf_pos = buf;
+ 	if (dev->irq < 0)
+-		printk(KERN_WARNING "ibm-iic%d: using polling mode\n", 
++		printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
+ 			dev->idx);
+-		
 +
-+	base_cmd = (struct hifn_base_command *)buf_pos;
-+	base_cmd->masks = __cpu_to_le16(mask);
-+	base_cmd->total_source_count =
-+		__cpu_to_le16(slen & HIFN_BASE_CMD_LENMASK_LO);
-+	base_cmd->total_dest_count =
-+		__cpu_to_le16(dlen & HIFN_BASE_CMD_LENMASK_LO);
+ 	/* Board specific settings */
+ 	dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
+-	
+-	/* clckdiv is the same for *all* IIC interfaces, 
 +
-+	dlen >>= 16;
-+	slen >>= 16;
-+	base_cmd->session_num = __cpu_to_le16(snum |
-+	    ((slen << HIFN_BASE_CMD_SRCLEN_S) & HIFN_BASE_CMD_SRCLEN_M) |
-+	    ((dlen << HIFN_BASE_CMD_DSTLEN_S) & HIFN_BASE_CMD_DSTLEN_M));
++	/* clckdiv is the same for *all* IIC interfaces,
+ 	 * but I'd rather make a copy than introduce another global. --ebs
+ 	 */
+ 	dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
+ 	DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
+-	
 +
-+	return sizeof(struct hifn_base_command);
-+}
+ 	/* Initialize IIC interface */
+ 	iic_dev_init(dev);
+-	
 +
-+static int hifn_setup_crypto_command(struct hifn_device *dev,
-+		u8 *buf, unsigned dlen, unsigned slen,
-+		u8 *key, int keylen, u8 *iv, int ivsize, u16 mode)
-+{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	struct hifn_crypt_command *cry_cmd;
-+	u8 *buf_pos = buf;
-+	u16 cmd_len;
+ 	/* Register it with i2c layer */
+ 	adap = &dev->adap;
+ 	adap->dev.parent = &ocp->dev;
+@@ -736,7 +736,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 	adap->client_register = NULL;
+ 	adap->client_unregister = NULL;
+ 	adap->timeout = 1;
+-	adap->retries = 1;
+ 
+ 	/*
+ 	 * If "dev->idx" is negative we consider it as zero.
+@@ -750,24 +749,24 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+ 			dev->idx);
+ 		goto fail;
+ 	}
+-	
 +
-+	cry_cmd = (struct hifn_crypt_command *)buf_pos;
+ 	printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
+ 		dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
+ 
+ 	return 0;
+ 
+-fail:	
++fail:
+ 	if (dev->irq >= 0){
+ 		iic_interrupt_mode(dev, 0);
+ 		free_irq(dev->irq, dev);
+-	}	
++	}
+ 
+ 	iounmap(dev->vaddr);
+-fail2:	
++fail2:
+ 	release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
+ fail1:
+ 	ocp_set_drvdata(ocp, NULL);
+-	kfree(dev);	
++	kfree(dev);
+ 	return ret;
+ }
+ 
+@@ -783,13 +782,13 @@ static void __devexit iic_remove(struct ocp_device *ocp)
+ 			dev->idx);
+ 		/* That's *very* bad, just shutdown IRQ ... */
+ 		if (dev->irq >= 0){
+-		    iic_interrupt_mode(dev, 0);	
++		    iic_interrupt_mode(dev, 0);
+ 		    free_irq(dev->irq, dev);
+ 		    dev->irq = -1;
+ 		}
+ 	} else {
+ 		if (dev->irq >= 0){
+-		    iic_interrupt_mode(dev, 0);	
++		    iic_interrupt_mode(dev, 0);
+ 		    free_irq(dev->irq, dev);
+ 		}
+ 		iounmap(dev->vaddr);
+@@ -798,7 +797,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
+ 	}
+ }
+ 
+-static struct ocp_device_id ibm_iic_ids[] __devinitdata = 
++static struct ocp_device_id ibm_iic_ids[] __devinitdata =
+ {
+ 	{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
+ 	{ .vendor = OCP_VENDOR_INVALID }
+diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
+index 59d7b43..fdaa482 100644
+--- a/drivers/i2c/busses/i2c-ibm_iic.h
++++ b/drivers/i2c/busses/i2c-ibm_iic.h
+@@ -2,11 +2,11 @@
+  * drivers/i2c/busses/i2c-ibm_iic.h
+  *
+  * Support for the IIC peripheral on IBM PPC 4xx
+- * 
++ *
+  * Copyright (c) 2003 Zultys Technologies.
+  * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
+  *
+- * Based on original work by 
++ * Based on original work by
+  * 	Ian DaSilva  <idasilva at mvista.com>
+  *      Armin Kuster <akuster at mvista.com>
+  * 	Matt Porter  <mporter at mvista.com>
+@@ -22,7 +22,7 @@
+ #ifndef __I2C_IBM_IIC_H_
+ #define __I2C_IBM_IIC_H_
+ 
+-#include <linux/i2c.h> 
++#include <linux/i2c.h>
+ 
+ struct iic_regs {
+ 	u16 mdbuf;
+@@ -58,7 +58,7 @@ struct ibm_iic_private {
+ #define CNTL_TCT_MASK	0x30
+ #define CNTL_TCT_SHIFT	4
+ #define CNTL_RPST	0x08
+-#define CNTL_CHT	0x04 
++#define CNTL_CHT	0x04
+ #define CNTL_RW		0x02
+ #define CNTL_PT		0x01
+ 
+diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
+index c70146e..ab41400 100644
+--- a/drivers/i2c/busses/i2c-iop3xx.c
++++ b/drivers/i2c/busses/i2c-iop3xx.c
+@@ -490,7 +490,6 @@ iop3xx_i2c_probe(struct platform_device *pdev)
+ 	 * Default values...should these come in from board code?
+ 	 */
+ 	new_adapter->timeout = 100;	
+-	new_adapter->retries = 3;
+ 	new_adapter->algo = &iop3xx_i2c_algo;
+ 
+ 	init_waitqueue_head(&adapter_data->waitq);
+diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
+deleted file mode 100644
+index 069ed7f..0000000
+--- a/drivers/i2c/busses/i2c-ixp4xx.c
++++ /dev/null
+@@ -1,178 +0,0 @@
+-/*
+- * drivers/i2c/busses/i2c-ixp4xx.c
+- *
+- * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have
+- * an on board I2C controller but provide 16 GPIO pins that are often
+- * used to create an I2C bus. This driver provides an i2c_adapter 
+- * interface that plugs in under algo_bit and drives the GPIO pins
+- * as instructed by the alogorithm driver.
+- *
+- * Author: Deepak Saxena <dsaxena at plexity.net>
+- *
+- * Copyright (c) 2003-2004 MontaVista Software Inc.
+- *
+- * This file is licensed under the terms of the GNU General Public 
+- * License version 2. This program is licensed "as is" without any 
+- * warranty of any kind, whether express or implied.
+- *
+- * NOTE: Since different platforms will use different GPIO pins for
+- *       I2C, this driver uses an IXP4xx-specific platform_data
+- *       pointer to pass the GPIO numbers to the driver. This 
+- *       allows us to support all the different IXP4xx platforms
+- *       w/o having to put #ifdefs in this driver.
+- *
+- *       See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a 
+- *       device list and filling in the ixp4xx_i2c_pins data structure 
+- *       that is passed as the platform_data to this driver.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/init.h>
+-#include <linux/platform_device.h>
+-#include <linux/module.h>
+-#include <linux/i2c.h>
+-#include <linux/i2c-algo-bit.h>
+-
+-#include <asm/hardware.h>	/* Pick up IXP4xx-specific bits */
+-
+-static inline int ixp4xx_scl_pin(void *data)
+-{
+-	return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
+-}
+-
+-static inline int ixp4xx_sda_pin(void *data)
+-{
+-	return ((struct ixp4xx_i2c_pins*)data)->sda_pin;
+-}
+-
+-static void ixp4xx_bit_setscl(void *data, int val)
+-{
+-	gpio_line_set(ixp4xx_scl_pin(data), 0);
+-	gpio_line_config(ixp4xx_scl_pin(data),
+-		val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
+-}
+-
+-static void ixp4xx_bit_setsda(void *data, int val)
+-{
+-	gpio_line_set(ixp4xx_sda_pin(data), 0);
+-	gpio_line_config(ixp4xx_sda_pin(data),
+-		val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
+-}
+-
+-static int ixp4xx_bit_getscl(void *data)
+-{
+-	int scl;
+-
+-	gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN );
+-	gpio_line_get(ixp4xx_scl_pin(data), &scl);
+-
+-	return scl;
+-}	
+-
+-static int ixp4xx_bit_getsda(void *data)
+-{
+-	int sda;
+-
+-	gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN );
+-	gpio_line_get(ixp4xx_sda_pin(data), &sda);
+-
+-	return sda;
+-}	
+-
+-struct ixp4xx_i2c_data {
+-	struct ixp4xx_i2c_pins *gpio_pins;
+-	struct i2c_adapter adapter;
+-	struct i2c_algo_bit_data algo_data;
+-};
+-
+-static int ixp4xx_i2c_remove(struct platform_device *plat_dev)
+-{
+-	struct ixp4xx_i2c_data *drv_data = platform_get_drvdata(plat_dev);
+-
+-	platform_set_drvdata(plat_dev, NULL);
+-
+-	i2c_del_adapter(&drv_data->adapter);
+-
+-	kfree(drv_data);
+-
+-	return 0;
+-}
+-
+-static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
+-{
+-	int err;
+-	struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
+-	struct ixp4xx_i2c_data *drv_data = 
+-		kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
+-
+-	if(!drv_data)
+-		return -ENOMEM;
+-
+-	drv_data->gpio_pins = gpio;
+-
+-	/*
+-	 * We could make a lot of these structures static, but
+-	 * certain platforms may have multiple GPIO-based I2C
+-	 * buses for various device domains, so we need per-device
+-	 * algo_data->data. 
+-	 */
+-	drv_data->algo_data.data = gpio;
+-	drv_data->algo_data.setsda = ixp4xx_bit_setsda;
+-	drv_data->algo_data.setscl = ixp4xx_bit_setscl;
+-	drv_data->algo_data.getsda = ixp4xx_bit_getsda;
+-	drv_data->algo_data.getscl = ixp4xx_bit_getscl;
+-	drv_data->algo_data.udelay = 10;
+-	drv_data->algo_data.timeout = 100;
+-
+-	drv_data->adapter.id = I2C_HW_B_IXP4XX;
+-	drv_data->adapter.class = I2C_CLASS_HWMON;
+-	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
+-		sizeof(drv_data->adapter.name));
+-	drv_data->adapter.algo_data = &drv_data->algo_data;
+-
+-	drv_data->adapter.dev.parent = &plat_dev->dev;
+-
+-	gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN);
+-	gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN);
+-	gpio_line_set(gpio->scl_pin, 0);
+-	gpio_line_set(gpio->sda_pin, 0);
+-
+-	err = i2c_bit_add_bus(&drv_data->adapter);
+-	if (err) {
+-		printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id);
+-
+-		kfree(drv_data);
+-		return err;
+-	}
+-
+-	platform_set_drvdata(plat_dev, drv_data);
+-
+-	return 0;
+-}
+-
+-static struct platform_driver ixp4xx_i2c_driver = {
+-	.probe		= ixp4xx_i2c_probe,
+-	.remove		= ixp4xx_i2c_remove,
+-	.driver		= {
+-		.name	= "IXP4XX-I2C",
+-		.owner	= THIS_MODULE,
+-	},
+-};
+-
+-static int __init ixp4xx_i2c_init(void)
+-{
+-	return platform_driver_register(&ixp4xx_i2c_driver);
+-}
+-
+-static void __exit ixp4xx_i2c_exit(void)
+-{
+-	platform_driver_unregister(&ixp4xx_i2c_driver);
+-}
+-
+-module_init(ixp4xx_i2c_init);
+-module_exit(ixp4xx_i2c_exit);
+-
+-MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems");
+-MODULE_LICENSE("GPL");
+-MODULE_AUTHOR("Deepak Saxena <dsaxena at plexity.net>");
+-
+diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
+index d8de4ac..bbe787b 100644
+--- a/drivers/i2c/busses/i2c-mpc.c
++++ b/drivers/i2c/busses/i2c-mpc.c
+@@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c)
+ static int mpc_write(struct mpc_i2c *i2c, int target,
+ 		     const u8 * data, int length, int restart)
+ {
+-	int i;
++	int i, result;
+ 	unsigned timeout = i2c->adap.timeout;
+ 	u32 flags = restart ? CCR_RSTA : 0;
+ 
+@@ -192,15 +192,17 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
+ 	/* Write target byte */
+ 	writeb((target << 1), i2c->base + MPC_I2C_DR);
+ 
+-	if (i2c_wait(i2c, timeout, 1) < 0)
+-		return -1;
++	result = i2c_wait(i2c, timeout, 1);
++	if (result < 0)
++		return result;
+ 
+ 	for (i = 0; i < length; i++) {
+ 		/* Write data byte */
+ 		writeb(data[i], i2c->base + MPC_I2C_DR);
+ 
+-		if (i2c_wait(i2c, timeout, 1) < 0)
+-			return -1;
++		result = i2c_wait(i2c, timeout, 1);
++		if (result < 0)
++			return result;
+ 	}
+ 
+ 	return 0;
+@@ -210,7 +212,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
+ 		    u8 * data, int length, int restart)
+ {
+ 	unsigned timeout = i2c->adap.timeout;
+-	int i;
++	int i, result;
+ 	u32 flags = restart ? CCR_RSTA : 0;
+ 
+ 	/* Start with MEN */
+@@ -221,8 +223,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
+ 	/* Write target address byte - this time with the read flag set */
+ 	writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
+ 
+-	if (i2c_wait(i2c, timeout, 1) < 0)
+-		return -1;
++	result = i2c_wait(i2c, timeout, 1);
++	if (result < 0)
++		return result;
+ 
+ 	if (length) {
+ 		if (length == 1)
+@@ -234,8 +237,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
+ 	}
+ 
+ 	for (i = 0; i < length; i++) {
+-		if (i2c_wait(i2c, timeout, 0) < 0)
+-			return -1;
++		result = i2c_wait(i2c, timeout, 0);
++		if (result < 0)
++			return result;
+ 
+ 		/* Generate txack on next to last byte */
+ 		if (i == length - 2)
+@@ -309,7 +313,6 @@ static struct i2c_adapter mpc_ops = {
+ 	.algo = &mpc_algo,
+ 	.class = I2C_CLASS_HWMON,
+ 	.timeout = 1,
+-	.retries = 1
+ };
+ 
+ static int fsl_i2c_probe(struct platform_device *pdev)
+@@ -321,9 +324,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
+ 
+ 	pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
+ 
+-	if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
++	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
++	if (!i2c)
+ 		return -ENOMEM;
+-	}
+ 
+ 	i2c->irq = platform_get_irq(pdev, 0);
+ 	if (i2c->irq < 0) {
+diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
+index bb7bf68..036e6a8 100644
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -1,6 +1,6 @@
+ /*
+- * Driver for the i2c controller on the Marvell line of host bridges for MIPS
+- * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
++ * Driver for the i2c controller on the Marvell line of host bridges
++ * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family).
+  *
+  * Author: Mark A. Greer <mgreer at mvista.com>
+  *
+@@ -14,7 +14,7 @@
+ #include <linux/spinlock.h>
+ #include <linux/i2c.h>
+ #include <linux/interrupt.h>
+-#include <linux/mv643xx.h>
++#include <linux/mv643xx_i2c.h>
+ #include <linux/platform_device.h>
+ 
+ #include <asm/io.h>
+@@ -86,6 +86,7 @@ struct mv64xxx_i2c_data {
+ 	u32			cntl_bits;
+ 	void __iomem		*reg_base;
+ 	u32			reg_base_p;
++	u32			reg_size;
+ 	u32			addr1;
+ 	u32			addr2;
+ 	u32			bytes_left;
+@@ -463,17 +464,20 @@ static int __devinit
+ mv64xxx_i2c_map_regs(struct platform_device *pd,
+ 	struct mv64xxx_i2c_data *drv_data)
+ {
+-	struct resource	*r;
++	int size;
++	struct resource	*r = platform_get_resource(pd, IORESOURCE_MEM, 0);
+ 
+-	if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) &&
+-		request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE,
+-			drv_data->adapter.name)) {
++	if (!r)
++		return -ENODEV;
+ 
+-		drv_data->reg_base = ioremap(r->start,
+-			MV64XXX_I2C_REG_BLOCK_SIZE);
+-		drv_data->reg_base_p = r->start;
+-	} else
+-		return -ENOMEM;
++	size = r->end - r->start + 1;
 +
-+	cry_cmd->source_count = __cpu_to_le16(dlen & 0xffff);
-+	dlen >>= 16;
-+	cry_cmd->masks = __cpu_to_le16(mode |
-+			((dlen << HIFN_CRYPT_CMD_SRCLEN_S) &
-+			 HIFN_CRYPT_CMD_SRCLEN_M));
-+	cry_cmd->header_skip = 0;
-+	cry_cmd->reserved = 0;
++	if (!request_mem_region(r->start, size, drv_data->adapter.name))
++		return -EBUSY;
 +
-+	buf_pos += sizeof(struct hifn_crypt_command);
++	drv_data->reg_base = ioremap(r->start, size);
++	drv_data->reg_base_p = r->start;
++	drv_data->reg_size = size;
+ 
+ 	return 0;
+ }
+@@ -483,8 +487,7 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
+ {
+ 	if (drv_data->reg_base) {
+ 		iounmap(drv_data->reg_base);
+-		release_mem_region(drv_data->reg_base_p,
+-			MV64XXX_I2C_REG_BLOCK_SIZE);
++		release_mem_region(drv_data->reg_base_p, drv_data->reg_size);
+ 	}
+ 
+ 	drv_data->reg_base = NULL;
+@@ -529,7 +532,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
+ 	drv_data->adapter.owner = THIS_MODULE;
+ 	drv_data->adapter.class = I2C_CLASS_HWMON;
+ 	drv_data->adapter.timeout = pdata->timeout;
+-	drv_data->adapter.retries = pdata->retries;
+ 	drv_data->adapter.nr = pd->id;
+ 	platform_set_drvdata(pd, drv_data);
+ 	i2c_set_adapdata(&drv_data->adapter, drv_data);
+diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
+index 1bf590c..3dac920 100644
+--- a/drivers/i2c/busses/i2c-nforce2.c
++++ b/drivers/i2c/busses/i2c-nforce2.c
+@@ -351,6 +351,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
+ 	pci_set_drvdata(dev, smbuses);
+ 
+ 	switch(dev->device) {
++	case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS:
+ 	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
+ 	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
+ 		smbuses[0].blockops = 1;
+diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
+index f2552b1..da66397 100644
+--- a/drivers/i2c/busses/i2c-omap.c
++++ b/drivers/i2c/busses/i2c-omap.c
+@@ -362,8 +362,6 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ 
+ 	omap_i2c_enable_clocks(dev);
+ 
+-	/* REVISIT: initialize and use adap->retries. This is an optional
+-	 * feature */
+ 	if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+ 		goto out;
+ 
+diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
+index ca18e0b..1603c81 100644
+--- a/drivers/i2c/busses/i2c-pasemi.c
++++ b/drivers/i2c/busses/i2c-pasemi.c
+@@ -368,6 +368,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
+ 	smbus->adapter.class = I2C_CLASS_HWMON;
+ 	smbus->adapter.algo = &smbus_algorithm;
+ 	smbus->adapter.algo_data = smbus;
++	smbus->adapter.nr = PCI_FUNC(dev->devfn);
+ 
+ 	/* set up the sysfs linkage to our parent device */
+ 	smbus->adapter.dev.parent = &dev->dev;
+@@ -375,7 +376,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
+ 	reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
+ 		  (CLK_100K_DIV & CTL_CLK_M)));
+ 
+-	error = i2c_add_adapter(&smbus->adapter);
++	error = i2c_add_numbered_adapter(&smbus->adapter);
+ 	if (error)
+ 		goto out_release_region;
+ 
+diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
+index 167e413..9bbe96c 100644
+--- a/drivers/i2c/busses/i2c-piix4.c
++++ b/drivers/i2c/busses/i2c-piix4.c
+@@ -121,10 +121,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
+ {
+ 	unsigned char temp;
+ 
+-	/* match up the function */
+-	if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
+-		return -ENODEV;
+-
+ 	dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
+ 
+ 	/* Don't access SMBus on IBM systems which get corrupted eeproms */
+@@ -389,28 +385,21 @@ static struct i2c_adapter piix4_adapter = {
+ };
+ 
+ static struct pci_device_id piix4_ids[] = {
+-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
+-	  .driver_data = 3 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB),
+-	  .driver_data = 0 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
+-	  .driver_data = 3 },
+-	{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),
+-	  .driver_data = 0 },
++	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
++		     PCI_DEVICE_ID_SERVERWORKS_OSB4) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
++		     PCI_DEVICE_ID_SERVERWORKS_CSB5) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
++		     PCI_DEVICE_ID_SERVERWORKS_CSB6) },
++	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
++		     PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
+ 	{ 0, }
+ };
+ 
+diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
+index 6426a61..2598d29 100644
+--- a/drivers/i2c/busses/i2c-pxa.c
++++ b/drivers/i2c/busses/i2c-pxa.c
+@@ -65,6 +65,7 @@ struct pxa_i2c {
+ 	unsigned long		iosize;
+ 
+ 	int			irq;
++	int			use_pio;
+ };
+ 
+ #define _IBMR(i2c)	((i2c)->reg_base + 0)
+@@ -163,6 +164,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
+ #define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0)
+ 
+ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
++static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
+ 
+ static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
+ {
+@@ -554,6 +556,71 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
+ 	writel(icr, _ICR(i2c));
+ }
+ 
++static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
++{
++	/* make timeout the same as for interrupt based functions */
++	long timeout = 2 * DEF_TIMEOUT;
 +
-+	dma->cmdu++;
-+	if (dma->cmdu > 1) {
-+		dev->dmareg |= HIFN_DMAIER_C_WAIT;
-+		hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
++	/*
++	 * Wait for the bus to become free.
++	 */
++	while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
++		udelay(1000);
++		show_state(i2c);
 +	}
 +
-+	if (keylen) {
-+		memcpy(buf_pos, key, keylen);
-+		buf_pos += keylen;
-+	}
-+	if (ivsize) {
-+		memcpy(buf_pos, iv, ivsize);
-+		buf_pos += ivsize;
++	if (timeout <= 0) {
++		show_state(i2c);
++		dev_err(&i2c->adap.dev,
++			"i2c_pxa: timeout waiting for bus free\n");
++		return I2C_RETRY;
 +	}
 +
-+	cmd_len = buf_pos - buf;
++	/*
++	 * Set master mode.
++	 */
++	writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
 +
-+	return cmd_len;
++	return 0;
 +}
 +
-+static int hifn_setup_src_desc(struct hifn_device *dev, struct page *page,
-+		unsigned int offset, unsigned int size)
++static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
++			       struct i2c_msg *msg, int num)
 +{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	int idx;
-+	dma_addr_t addr;
-+
-+	addr = pci_map_page(dev->pdev, page, offset, size, PCI_DMA_TODEVICE);
-+
-+	idx = dma->srci;
++	unsigned long timeout = 500000; /* 5 seconds */
++	int ret = 0;
 +
-+	dma->srcr[idx].p = __cpu_to_le32(addr);
-+	dma->srcr[idx].l = __cpu_to_le32(size) | HIFN_D_VALID |
-+			HIFN_D_MASKDONEIRQ | HIFN_D_NOINVALID | HIFN_D_LAST;
++	ret = i2c_pxa_pio_set_master(i2c);
++	if (ret)
++		goto out;
 +
-+	if (++idx == HIFN_D_SRC_RSIZE) {
-+		dma->srcr[idx].l = __cpu_to_le32(HIFN_D_VALID |
-+				HIFN_D_JUMP |
-+				HIFN_D_MASKDONEIRQ | HIFN_D_LAST);
-+		idx = 0;
-+	}
++	i2c->msg = msg;
++	i2c->msg_num = num;
++	i2c->msg_idx = 0;
++	i2c->msg_ptr = 0;
++	i2c->irqlogidx = 0;
 +
-+	dma->srci = idx;
-+	dma->srcu++;
++	i2c_pxa_start_message(i2c);
 +
-+	if (!(dev->flags & HIFN_FLAG_SRC_BUSY)) {
-+		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_S_CTRL_ENA);
-+		dev->flags |= HIFN_FLAG_SRC_BUSY;
++	while (timeout-- && i2c->msg_num > 0) {
++		i2c_pxa_handler(0, i2c);
++		udelay(10);
 +	}
 +
-+	return size;
-+}
-+
-+static void hifn_setup_res_desc(struct hifn_device *dev)
-+{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
++	i2c_pxa_stop_message(i2c);
 +
-+	dma->resr[dma->resi].l = __cpu_to_le32(HIFN_USED_RESULT |
-+			HIFN_D_VALID | HIFN_D_LAST);
 +	/*
-+	 * dma->resr[dma->resi].l = __cpu_to_le32(HIFN_MAX_RESULT | HIFN_D_VALID |
-+	 *					HIFN_D_LAST | HIFN_D_NOINVALID);
++	 * We place the return code in i2c->msg_idx.
 +	 */
++	ret = i2c->msg_idx;
 +
-+	if (++dma->resi == HIFN_D_RES_RSIZE) {
-+		dma->resr[HIFN_D_RES_RSIZE].l = __cpu_to_le32(HIFN_D_VALID |
-+				HIFN_D_JUMP | HIFN_D_MASKDONEIRQ | HIFN_D_LAST);
-+		dma->resi = 0;
-+	}
-+
-+	dma->resu++;
++out:
++	if (timeout == 0)
++		i2c_pxa_scream_blue_murder(i2c, "timeout");
 +
-+	if (!(dev->flags & HIFN_FLAG_RES_BUSY)) {
-+		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_R_CTRL_ENA);
-+		dev->flags |= HIFN_FLAG_RES_BUSY;
-+	}
++	return ret;
 +}
 +
-+static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page,
-+		unsigned offset, unsigned size)
+ /*
+  * We are protected by the adapter bus mutex.
+  */
+@@ -610,6 +677,35 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
+ 	return ret;
+ }
+ 
++static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
++			    struct i2c_msg msgs[], int num)
 +{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	int idx;
-+	dma_addr_t addr;
-+
-+	addr = pci_map_page(dev->pdev, page, offset, size, PCI_DMA_FROMDEVICE);
++	struct pxa_i2c *i2c = adap->algo_data;
++	int ret, i;
 +
-+	idx = dma->dsti;
-+	dma->dstr[idx].p = __cpu_to_le32(addr);
-+	dma->dstr[idx].l = __cpu_to_le32(size |	HIFN_D_VALID |
-+			HIFN_D_MASKDONEIRQ | HIFN_D_NOINVALID | HIFN_D_LAST);
++	/* If the I2C controller is disabled we need to reset it
++	  (probably due to a suspend/resume destroying state). We do
++	  this here as we can then avoid worrying about resuming the
++	  controller before its users. */
++	if (!(readl(_ICR(i2c)) & ICR_IUE))
++		i2c_pxa_reset(i2c);
 +
-+	if (++idx == HIFN_D_DST_RSIZE) {
-+		dma->dstr[idx].l = __cpu_to_le32(HIFN_D_VALID |
-+				HIFN_D_JUMP | HIFN_D_MASKDONEIRQ |
-+				HIFN_D_LAST | HIFN_D_NOINVALID);
-+		idx = 0;
-+	}
-+	dma->dsti = idx;
-+	dma->dstu++;
++	for (i = adap->retries; i >= 0; i--) {
++		ret = i2c_pxa_do_pio_xfer(i2c, msgs, num);
++		if (ret != I2C_RETRY)
++			goto out;
 +
-+	if (!(dev->flags & HIFN_FLAG_DST_BUSY)) {
-+		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_D_CTRL_ENA);
-+		dev->flags |= HIFN_FLAG_DST_BUSY;
++		if (i2c_debug)
++			dev_dbg(&adap->dev, "Retrying transmission\n");
++		udelay(100);
 +	}
++	i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
++	ret = -EREMOTEIO;
++ out:
++	i2c_pxa_set_slave(i2c, ret);
++	return ret;
 +}
 +
-+static int hifn_setup_dma(struct hifn_device *dev, struct page *spage, unsigned int soff,
-+		struct page *dpage, unsigned int doff, unsigned int nbytes, void *priv,
-+		struct hifn_context *ctx)
-+{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	int cmd_len, sa_idx;
-+	u8 *buf, *buf_pos;
-+	u16 mask;
-+
-+	dprintk("%s: spage: %p, soffset: %u, dpage: %p, doffset: %u, nbytes: %u, priv: %p, ctx: %p.\n",
-+			dev->name, spage, soff, dpage, doff, nbytes, priv, ctx);
-+
-+	sa_idx = dma->resi;
-+
-+	hifn_setup_src_desc(dev, spage, soff, nbytes);
-+
-+	buf_pos = buf = dma->command_bufs[dma->cmdi];
+ /*
+  * i2c_pxa_master_complete - complete the message and wake up.
+  */
+@@ -621,7 +717,8 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
+ 	i2c->msg_num = 0;
+ 	if (ret)
+ 		i2c->msg_idx = ret;
+-	wake_up(&i2c->wait);
++	if (!i2c->use_pio)
++		wake_up(&i2c->wait);
+ }
+ 
+ static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
+@@ -840,6 +937,37 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
+ 	.functionality	= i2c_pxa_functionality,
+ };
+ 
++static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
++	.master_xfer	= i2c_pxa_pio_xfer,
++	.functionality	= i2c_pxa_functionality,
++};
 +
-+	mask = 0;
-+	switch (ctx->op) {
-+		case ACRYPTO_OP_DECRYPT:
-+			mask = HIFN_BASE_CMD_CRYPT | HIFN_BASE_CMD_DECODE;
-+			break;
-+		case ACRYPTO_OP_ENCRYPT:
-+			mask = HIFN_BASE_CMD_CRYPT;
++static void i2c_pxa_enable(struct platform_device *dev)
++{
++	if (cpu_is_pxa27x()) {
++		switch (dev->id) {
++		case 0:
++			pxa_gpio_mode(GPIO117_I2CSCL_MD);
++			pxa_gpio_mode(GPIO118_I2CSDA_MD);
 +			break;
-+		case ACRYPTO_OP_HMAC:
-+			mask = HIFN_BASE_CMD_MAC;
++		case 1:
++			local_irq_disable();
++			PCFR |= PCFR_PI2CEN;
++			local_irq_enable();
 +			break;
-+		default:
-+			goto err_out;
-+	}
-+
-+	buf_pos += hifn_setup_base_command(dev, buf_pos, nbytes,
-+			nbytes, mask, dev->snum);
-+
-+	if (ctx->op == ACRYPTO_OP_ENCRYPT || ctx->op == ACRYPTO_OP_DECRYPT) {
-+		u16 md = 0;
-+
-+		if (ctx->keysize)
-+			md |= HIFN_CRYPT_CMD_NEW_KEY;
-+		if (ctx->iv && ctx->mode != ACRYPTO_MODE_ECB)
-+			md |= HIFN_CRYPT_CMD_NEW_IV;
-+
-+		switch (ctx->mode) {
-+			case ACRYPTO_MODE_ECB:
-+				md |= HIFN_CRYPT_CMD_MODE_ECB;
-+				break;
-+			case ACRYPTO_MODE_CBC:
-+				md |= HIFN_CRYPT_CMD_MODE_CBC;
-+				break;
-+			case ACRYPTO_MODE_CFB:
-+				md |= HIFN_CRYPT_CMD_MODE_CFB;
-+				break;
-+			case ACRYPTO_MODE_OFB:
-+				md |= HIFN_CRYPT_CMD_MODE_OFB;
-+				break;
-+			default:
-+				goto err_out;
-+		}
-+
-+		switch (ctx->type) {
-+			case ACRYPTO_TYPE_AES_128:
-+				if (ctx->keysize != 16)
-+					goto err_out;
-+				md |= HIFN_CRYPT_CMD_KSZ_128 |
-+					HIFN_CRYPT_CMD_ALG_AES;
-+				break;
-+			case ACRYPTO_TYPE_AES_192:
-+				if (ctx->keysize != 24)
-+					goto err_out;
-+				md |= HIFN_CRYPT_CMD_KSZ_192 |
-+					HIFN_CRYPT_CMD_ALG_AES;
-+				break;
-+			case ACRYPTO_TYPE_AES_256:
-+				if (ctx->keysize != 32)
-+					goto err_out;
-+				md |= HIFN_CRYPT_CMD_KSZ_256 |
-+					HIFN_CRYPT_CMD_ALG_AES;
-+				break;
-+			case ACRYPTO_TYPE_3DES:
-+				if (ctx->keysize != 24)
-+					goto err_out;
-+				md |= HIFN_CRYPT_CMD_ALG_3DES;
-+				break;
-+			case ACRYPTO_TYPE_DES:
-+				if (ctx->keysize != 8)
-+					goto err_out;
-+				md |= HIFN_CRYPT_CMD_ALG_DES;
-+				break;
-+			default:
-+				goto err_out;
 +		}
-+
-+		buf_pos += hifn_setup_crypto_command(dev, buf_pos,
-+				nbytes, nbytes, ctx->key, ctx->keysize,
-+				ctx->iv, ctx->ivsize, md);
-+	}
-+
-+	dev->sa[sa_idx] = priv;
-+
-+	cmd_len = buf_pos - buf;
-+	dma->cmdr[dma->cmdi].l = __cpu_to_le32(cmd_len | HIFN_D_VALID |
-+			HIFN_D_LAST | HIFN_D_MASKDONEIRQ);
-+
-+	if (++dma->cmdi == HIFN_D_CMD_RSIZE) {
-+		dma->cmdr[dma->cmdi].l = __cpu_to_le32(HIFN_MAX_COMMAND |
-+			HIFN_D_VALID | HIFN_D_LAST |
-+			HIFN_D_MASKDONEIRQ | HIFN_D_JUMP);
-+		dma->cmdi = 0;
-+	} else
-+		dma->cmdr[dma->cmdi-1].l |= __cpu_to_le32(HIFN_D_VALID);
-+
-+	if (!(dev->flags & HIFN_FLAG_CMD_BUSY)) {
-+		hifn_write_1(dev, HIFN_1_DMA_CSR, HIFN_DMACSR_C_CTRL_ENA);
-+		dev->flags |= HIFN_FLAG_CMD_BUSY;
-+	}
-+
-+	hifn_setup_dst_desc(dev, dpage, doff, nbytes);
-+	hifn_setup_res_desc(dev);
-+
-+	return 0;
-+
-+err_out:
-+	return -EINVAL;
-+}
-+
-+static int ablkcipher_walk_init(struct ablkcipher_walk *w,
-+		int num, gfp_t gfp_flags)
-+{
-+	int i;
-+
-+	num = min(ASYNC_SCATTERLIST_CACHE, num);
-+	sg_init_table(w->cache, num);
-+
-+	w->num = 0;
-+	for (i=0; i<num; ++i) {
-+		struct page *page = alloc_page(gfp_flags);
-+		struct scatterlist *s;
-+
-+		if (!page)
-+			break;
-+
-+		s = &w->cache[i];
-+
-+		sg_set_page(s, page, PAGE_SIZE, 0);
-+		w->num++;
 +	}
-+
-+	return i;
 +}
 +
-+static void ablkcipher_walk_exit(struct ablkcipher_walk *w)
++static void i2c_pxa_disable(struct platform_device *dev)
 +{
-+	int i;
-+
-+	for (i=0; i<w->num; ++i) {
-+		struct scatterlist *s = &w->cache[i];
-+
-+		__free_page(sg_page(s));
-+
-+		s->length = 0;
++	if (cpu_is_pxa27x() && dev->id == 1) {
++		local_irq_disable();
++		PCFR &= ~PCFR_PI2CEN;
++		local_irq_enable();
 +	}
-+
-+	w->num = 0;
 +}
 +
-+static int ablkcipher_add(void *daddr, unsigned int *drestp, struct scatterlist *src,
-+		unsigned int size, unsigned int *nbytesp)
-+{
-+	unsigned int copy, drest = *drestp, nbytes = *nbytesp;
-+	int idx = 0;
-+	void *saddr;
-+
-+	if (drest < size || size > nbytes)
-+		return -EINVAL;
-+
-+	while (size) {
-+		copy = min(drest, src->length);
-+
-+		saddr = kmap_atomic(sg_page(src), KM_SOFTIRQ1);
-+		memcpy(daddr, saddr + src->offset, copy);
-+		kunmap_atomic(saddr, KM_SOFTIRQ1);
-+
-+		size -= copy;
-+		drest -= copy;
-+		nbytes -= copy;
-+		daddr += copy;
-+
-+		dprintk("%s: copy: %u, size: %u, drest: %u, nbytes: %u.\n",
-+				__func__, copy, size, drest, nbytes);
-+
-+		src++;
-+		idx++;
+ #define res_len(r)		((r)->end - (r)->start + 1)
+ static int i2c_pxa_probe(struct platform_device *dev)
+ {
+@@ -864,7 +992,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
+ 	}
+ 
+ 	i2c->adap.owner   = THIS_MODULE;
+-	i2c->adap.algo    = &i2c_pxa_algorithm;
+ 	i2c->adap.retries = 5;
+ 
+ 	spin_lock_init(&i2c->lock);
+@@ -899,34 +1026,28 @@ static int i2c_pxa_probe(struct platform_device *dev)
+ #endif
+ 
+ 	clk_enable(i2c->clk);
+-#ifdef CONFIG_PXA27x
+-	switch (dev->id) {
+-	case 0:
+-		pxa_gpio_mode(GPIO117_I2CSCL_MD);
+-		pxa_gpio_mode(GPIO118_I2CSDA_MD);
+-		break;
+-	case 1:
+-		local_irq_disable();
+-		PCFR |= PCFR_PI2CEN;
+-		local_irq_enable();
+-	}
+-#endif
++	i2c_pxa_enable(dev);
+ 
+-	ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+-			  i2c->adap.name, i2c);
+-	if (ret)
+-		goto ereqirq;
++	if (plat) {
++		i2c->adap.class = plat->class;
++		i2c->use_pio = plat->use_pio;
 +	}
-+
-+	*nbytesp = nbytes;
-+	*drestp = drest;
-+
-+	return idx;
-+}
-+
-+static int ablkcipher_walk(struct ablkcipher_request *req,
-+		struct ablkcipher_walk *w)
-+{
-+	unsigned blocksize =
-+		crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(req));
-+	unsigned alignmask =
-+		crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
-+	struct scatterlist *src, *dst, *t;
-+	void *daddr;
-+	unsigned int nbytes = req->nbytes, offset, copy, diff;
-+	int idx, tidx, err;
-+
-+	tidx = idx = 0;
-+	offset = 0;
-+	while (nbytes) {
-+		if (idx >= w->num && (w->flags & ASYNC_FLAGS_MISALIGNED))
-+			return -EINVAL;
-+
-+		src = &req->src[idx];
-+		dst = &req->dst[idx];
-+
-+		dprintk("\n%s: slen: %u, dlen: %u, soff: %u, doff: %u, offset: %u, "
-+				"blocksize: %u, nbytes: %u.\n",
-+				__func__, src->length, dst->length, src->offset,
-+				dst->offset, offset, blocksize, nbytes);
-+
-+		if (src->length & (blocksize - 1) ||
-+				src->offset & (alignmask - 1) ||
-+				dst->length & (blocksize - 1) ||
-+				dst->offset & (alignmask - 1) ||
-+				offset) {
-+			unsigned slen = src->length - offset;
-+			unsigned dlen = PAGE_SIZE;
-+
-+			t = &w->cache[idx];
-+
-+			daddr = kmap_atomic(sg_page(t), KM_SOFTIRQ0);
-+			err = ablkcipher_add(daddr, &dlen, src, slen, &nbytes);
-+			if (err < 0)
-+				goto err_out_unmap;
-+
-+			idx += err;
-+
-+			copy = slen & ~(blocksize - 1);
-+			diff = slen & (blocksize - 1);
-+
-+			if (dlen < nbytes) {
-+				/*
-+				 * Destination page does not have enough space
-+				 * to put there additional blocksized chunk,
-+				 * so we mark that page as containing only
-+				 * blocksize aligned chunks:
-+				 * 	t->length = (slen & ~(blocksize - 1));
-+				 * and increase number of bytes to be processed
-+				 * in next chunk:
-+				 * 	nbytes += diff;
-+				 */
-+				nbytes += diff;
-+
-+				/*
-+				 * Temporary of course...
-+				 * Kick author if you will catch this one.
-+				 */
-+				printk(KERN_ERR "%s: dlen: %u, nbytes: %u,"
-+					"slen: %u, offset: %u.\n",
-+					__func__, dlen, nbytes, slen, offset);
-+				printk(KERN_ERR "%s: please contact author to fix this "
-+					"issue, generally you should not catch "
-+					"this path under any condition but who "
-+					"knows how did you use crypto code.\n"
-+					"Thank you.\n",	__func__);
-+				BUG();
-+			} else {
-+				copy += diff + nbytes;
-+
-+				src = &req->src[idx];
-+
-+				err = ablkcipher_add(daddr + slen, &dlen, src, nbytes, &nbytes);
-+				if (err < 0)
-+					goto err_out_unmap;
-+
-+				idx += err;
-+			}
-+
-+			t->length = copy;
-+			t->offset = offset;
-+
-+			kunmap_atomic(daddr, KM_SOFTIRQ0);
-+		} else {
-+			nbytes -= src->length;
-+			idx++;
-+		}
-+
-+		tidx++;
+ 
++	if (i2c->use_pio) {
++		i2c->adap.algo = &i2c_pxa_pio_algorithm;
++	} else {
++		i2c->adap.algo = &i2c_pxa_algorithm;
++		ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
++				  i2c->adap.name, i2c);
++		if (ret)
++			goto ereqirq;
 +	}
+ 
+ 	i2c_pxa_reset(i2c);
+ 
+ 	i2c->adap.algo_data = i2c;
+ 	i2c->adap.dev.parent = &dev->dev;
+ 
+-	if (plat) {
+-		i2c->adap.class = plat->class;
+-	}
+-
+ 	/*
+ 	 * If "dev->id" is negative we consider it as zero.
+ 	 * The reason to do so is to avoid sysfs names that only make
+@@ -952,17 +1073,11 @@ static int i2c_pxa_probe(struct platform_device *dev)
+ 	return 0;
+ 
+ eadapt:
+-	free_irq(irq, i2c);
++	if (!i2c->use_pio)
++		free_irq(irq, i2c);
+ ereqirq:
+ 	clk_disable(i2c->clk);
+-
+-#ifdef CONFIG_PXA27x
+-	if (dev->id == 1) {
+-		local_irq_disable();
+-		PCFR &= ~PCFR_PI2CEN;
+-		local_irq_enable();
+-	}
+-#endif
++	i2c_pxa_disable(dev);
+ eremap:
+ 	clk_put(i2c->clk);
+ eclk:
+@@ -979,18 +1094,12 @@ static int i2c_pxa_remove(struct platform_device *dev)
+ 	platform_set_drvdata(dev, NULL);
+ 
+ 	i2c_del_adapter(&i2c->adap);
+-	free_irq(i2c->irq, i2c);
++	if (!i2c->use_pio)
++		free_irq(i2c->irq, i2c);
+ 
+ 	clk_disable(i2c->clk);
+ 	clk_put(i2c->clk);
+-
+-#ifdef CONFIG_PXA27x
+-	if (dev->id == 1) {
+-		local_irq_disable();
+-		PCFR &= ~PCFR_PI2CEN;
+-		local_irq_enable();
+-	}
+-#endif
++	i2c_pxa_disable(dev);
+ 
+ 	release_mem_region(i2c->iobase, i2c->iosize);
+ 	kfree(i2c);
+diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
+index 503a134..8fbbdb4 100644
+--- a/drivers/i2c/busses/i2c-sibyte.c
++++ b/drivers/i2c/busses/i2c-sibyte.c
+@@ -36,14 +36,6 @@ struct i2c_algo_sibyte_data {
+ /* ----- global defines ----------------------------------------------- */
+ #define SMB_CSR(a,r) ((long)(a->reg_base + r))
+ 
+-/* ----- global variables --------------------------------------------- */
+-
+-/* module parameters:
+- */
+-static int bit_scan;	/* have a look at what's hanging 'round */
+-module_param(bit_scan, int, 0);
+-MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+-
+ 
+ static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
+ 		      unsigned short flags, char read_write,
+@@ -140,9 +132,8 @@ static const struct i2c_algorithm i2c_sibyte_algo = {
+ /*
+  * registering functions to load algorithms at runtime
+  */
+-int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
++int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+ {
+-	int i;
+ 	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+ 
+ 	/* register new adapter to i2c module... */
+@@ -152,24 +143,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+ 	csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
+ 	csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+ 
+-	/* scan bus */
+-	if (bit_scan) {
+-		union i2c_smbus_data data;
+-		int rc;
+-		printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
+-		       i2c_adap->name);
+-		for (i = 0x00; i < 0x7f; i++) {
+-			/* XXXKW is this a realistic probe? */
+-			rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
+-					I2C_SMBUS_BYTE_DATA, &data);
+-			if (!rc) {
+-				printk("(%02x)",i);
+-			} else
+-				printk(".");
+-		}
+-		printk("\n");
+-	}
+-
+ 	return i2c_add_adapter(i2c_adap);
+ }
+ 
+diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
+index 84df29d..c2a9f8c 100644
+--- a/drivers/i2c/busses/i2c-stub.c
++++ b/drivers/i2c/busses/i2c-stub.c
+@@ -1,8 +1,8 @@
+ /*
+-    i2c-stub.c - Part of lm_sensors, Linux kernel modules for hardware
+-              monitoring
++    i2c-stub.c - I2C/SMBus chip emulator
+ 
+     Copyright (c) 2004 Mark M. Hoffman <mhoffman at lightlink.com>
++    Copyright (C) 2007 Jean Delvare <khali at linux-fr.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
+@@ -37,8 +37,8 @@ MODULE_PARM_DESC(chip_addr,
+ 
+ struct stub_chip {
+ 	u8 pointer;
+-	u8 bytes[256];
+-	u16 words[256];
++	u16 words[256];		/* Byte operations use the LSB as per SMBus
++				   specification */
+ };
+ 
+ static struct stub_chip *stub_chips;
+@@ -75,7 +75,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+ 					"wrote 0x%02x.\n",
+ 					addr, command);
+ 		} else {
+-			data->byte = chip->bytes[chip->pointer++];
++			data->byte = chip->words[chip->pointer++] & 0xff;
+ 			dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
+ 					"read  0x%02x.\n",
+ 					addr, data->byte);
+@@ -86,12 +86,13 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+ 
+ 	case I2C_SMBUS_BYTE_DATA:
+ 		if (read_write == I2C_SMBUS_WRITE) {
+-			chip->bytes[command] = data->byte;
++			chip->words[command] &= 0xff00;
++			chip->words[command] |= data->byte;
+ 			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
+ 					"wrote 0x%02x at 0x%02x.\n",
+ 					addr, data->byte, command);
+ 		} else {
+-			data->byte = chip->bytes[command];
++			data->byte = chip->words[command] & 0xff;
+ 			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
+ 					"read  0x%02x at 0x%02x.\n",
+ 					addr, data->byte, command);
+diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
+index c9ce77f..77b13d0 100644
+--- a/drivers/i2c/busses/i2c-viapro.c
++++ b/drivers/i2c/busses/i2c-viapro.c
+@@ -4,7 +4,7 @@
+     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol at dds.nl>,
+     Philip Edelbrock <phil at netroedge.com>, Kyösti Mälkki <kmalkki at cc.hut.fi>,
+     Mark D. Studebaker <mdsxyz123 at yahoo.com>
+-    Copyright (C) 2005 - 2007  Jean Delvare <khali at linux-fr.org>
++    Copyright (C) 2005 - 2008  Jean Delvare <khali at linux-fr.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
+@@ -35,6 +35,7 @@
+    VT8235             0x3177             yes
+    VT8237R            0x3227             yes
+    VT8237A            0x3337             yes
++   VT8237S            0x3372             yes
+    VT8251             0x3287             yes
+    CX700              0x8324             yes
+ 
+@@ -318,6 +319,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
+ 	unsigned char temp;
+ 	int error = -ENODEV;
+ 
++	/* driver_data might come from user-space, so check it */
++	if (id->driver_data & 1 || id->driver_data > 0xff)
++		return -EINVAL;
 +
-+	return tidx;
-+
-+err_out_unmap:
-+	kunmap_atomic(daddr, KM_SOFTIRQ0);
-+	return err;
-+}
-+
-+static int hifn_setup_session(struct ablkcipher_request *req)
-+{
-+	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
-+	struct hifn_device *dev = ctx->dev;
-+	struct page *spage, *dpage;
-+	unsigned long soff, doff, flags;
-+	unsigned int nbytes = req->nbytes, idx = 0, len;
-+	int err = -EINVAL, sg_num;
-+	struct scatterlist *src, *dst, *t;
-+	unsigned blocksize =
-+		crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(req));
-+	unsigned alignmask =
-+		crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
-+
-+	if (ctx->iv && !ctx->ivsize && ctx->mode != ACRYPTO_MODE_ECB)
-+		goto err_out_exit;
-+
-+	ctx->walk.flags = 0;
-+
-+	while (nbytes) {
-+		src = &req->src[idx];
-+		dst = &req->dst[idx];
-+
-+		if (src->length & (blocksize - 1) ||
-+				src->offset & (alignmask - 1) ||
-+				dst->length & (blocksize - 1) ||
-+				dst->offset & (alignmask - 1)) {
-+			ctx->walk.flags |= ASYNC_FLAGS_MISALIGNED;
-+		}
-+
-+		nbytes -= src->length;
-+		idx++;
-+	}
+ 	/* Determine the address of the SMBus areas */
+ 	if (force_addr) {
+ 		vt596_smba = force_addr & 0xfff0;
+@@ -389,6 +394,7 @@ found:
+ 	case PCI_DEVICE_ID_VIA_8251:
+ 	case PCI_DEVICE_ID_VIA_8237:
+ 	case PCI_DEVICE_ID_VIA_8237A:
++	case PCI_DEVICE_ID_VIA_8237S:
+ 	case PCI_DEVICE_ID_VIA_8235:
+ 	case PCI_DEVICE_ID_VIA_8233A:
+ 	case PCI_DEVICE_ID_VIA_8233_0:
+@@ -440,6 +446,8 @@ static struct pci_device_id vt596_ids[] = {
+ 	  .driver_data = SMBBA3 },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
+ 	  .driver_data = SMBBA3 },
++	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237S),
++	  .driver_data = SMBBA3 },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
+ 	  .driver_data = SMBBA1 },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
+@@ -455,6 +463,7 @@ static struct pci_driver vt596_driver = {
+ 	.name		= "vt596_smbus",
+ 	.id_table	= vt596_ids,
+ 	.probe		= vt596_probe,
++	.dynids.use_driver_data = 1,
+ };
+ 
+ static int __init i2c_vt596_init(void)
+diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
+index e6c4a2b..f5e7a70 100644
+--- a/drivers/i2c/busses/scx200_acb.c
++++ b/drivers/i2c/busses/scx200_acb.c
+@@ -492,7 +492,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
+ 	iface->pdev = pdev;
+ 	iface->bar = bar;
+ 
+-	rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
++	rc = pci_enable_device_io(iface->pdev);
+ 	if (rc)
+ 		goto errout_free;
+ 
+diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
+index 2e1c24f..b21593f 100644
+--- a/drivers/i2c/chips/Kconfig
++++ b/drivers/i2c/chips/Kconfig
+@@ -4,32 +4,6 @@
+ 
+ menu "Miscellaneous I2C Chip support"
+ 
+-config SENSORS_DS1337
+-	tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)"
+-	depends on EXPERIMENTAL
+-	help
+-	  If you say yes here you get support for Dallas Semiconductor
+-	  DS1337 and DS1339 real-time clock chips.
+-
+-	  This driver can also be built as a module.  If so, the module
+-	  will be called ds1337.
+-
+-	  This driver is deprecated and will be dropped soon. Use
+-	  rtc-ds1307 instead.
+-
+-config SENSORS_DS1374
+-	tristate "Dallas DS1374 Real Time Clock (DEPRECATED)"
+-	depends on EXPERIMENTAL
+-	help
+-	  If you say yes here you get support for Dallas Semiconductor
+-	  DS1374 real-time clock chips.
+-
+-	  This driver can also be built as a module.  If so, the module
+-	  will be called ds1374.
+-
+-	  This driver is deprecated and will be dropped soon. Use
+-	  rtc-ds1374 instead.
+-
+ config DS1682
+ 	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
+ 	depends on EXPERIMENTAL
+@@ -57,7 +31,7 @@ config SENSORS_PCF8574
+ 	default n
+ 	help
+ 	  If you say yes here you get support for Philips PCF8574 and 
+-	  PCF8574A chips.
++	  PCF8574A chips. These chips are 8-bit I/O expanders for the I2C bus.
+ 
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called pcf8574.
+@@ -65,9 +39,23 @@ config SENSORS_PCF8574
+ 	  These devices are hard to detect and rarely found on mainstream
+ 	  hardware.  If unsure, say N.
+ 
++config PCF8575
++	tristate "Philips PCF8575"
++	default n
++	help
++	  If you say yes here you get support for Philips PCF8575 chip.
++	  This chip is a 16-bit I/O expander for the I2C bus.  Several other
++	  chip manufacturers sell equivalent chips, e.g. Texas Instruments.
 +
-+	if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) {
-+		err = ablkcipher_walk_init(&ctx->walk, idx, GFP_ATOMIC);
-+		if (err < 0)
-+			return err;
-+	}
++	  This driver can also be built as a module.  If so, the module
++	  will be called pcf8575.
 +
-+	nbytes = req->nbytes;
-+	idx = 0;
++	  This device is hard to detect and is rarely found on mainstream
++	  hardware.  If unsure, say N.
 +
-+	sg_num = ablkcipher_walk(req, &ctx->walk);
+ config SENSORS_PCA9539
+-	tristate "Philips PCA9539 16-bit I/O port"
+-	depends on EXPERIMENTAL
++	tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)"
++	depends on EXPERIMENTAL && GPIO_PCA9539 = "n"
+ 	help
+ 	  If you say yes here you get support for the Philips PCA9539
+ 	  16-bit I/O port.
+@@ -75,6 +63,9 @@ config SENSORS_PCA9539
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called pca9539.
+ 
++	  This driver is deprecated and will be dropped soon. Use
++	  drivers/gpio/pca9539.c instead.
 +
-+	atomic_set(&ctx->sg_num, sg_num);
+ config SENSORS_PCF8591
+ 	tristate "Philips PCF8591"
+ 	depends on EXPERIMENTAL
+@@ -100,12 +91,8 @@ config ISP1301_OMAP
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called isp1301_omap.
+ 
+-# NOTE:  This isn't really OMAP-specific, except for the current
+-# interface location in  <include/asm-arm/arch-omap/tps65010.h>
+-# and having mostly OMAP-specific board support
+ config TPS65010
+ 	tristate "TPS6501x Power Management chips"
+-	depends on ARCH_OMAP
+ 	default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+ 	help
+ 	  If you say yes here you get support for the TPS6501x series of
+@@ -116,18 +103,6 @@ config TPS65010
+ 	  This driver can also be built as a module.  If so, the module
+ 	  will be called tps65010.
+ 
+-config SENSORS_M41T00
+-	tristate "ST M41T00 RTC chip (DEPRECATED)"
+-	depends on PPC32
+-	help
+-	  If you say yes here you get support for the ST M41T00 RTC chip.
+-
+-	  This driver can also be built as a module.  If so, the module
+-	  will be called m41t00.
+-
+-	  This driver is deprecated and will be dropped soon. Use
+-	  rtc-ds1307 or rtc-m41t80 instead.
+-
+ config SENSORS_MAX6875
+ 	tristate "Maxim MAX6875 Power supply supervisor"
+ 	depends on EXPERIMENTAL
+diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
+index ca924e1..501f00c 100644
+--- a/drivers/i2c/chips/Makefile
++++ b/drivers/i2c/chips/Makefile
+@@ -2,14 +2,12 @@
+ # Makefile for miscellaneous I2C chip drivers.
+ #
+ 
+-obj-$(CONFIG_SENSORS_DS1337)	+= ds1337.o
+-obj-$(CONFIG_SENSORS_DS1374)	+= ds1374.o
+ obj-$(CONFIG_DS1682)		+= ds1682.o
+ obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
+ obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
+-obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
+ obj-$(CONFIG_SENSORS_PCA9539)	+= pca9539.o
+ obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
++obj-$(CONFIG_PCF8575)		+= pcf8575.o
+ obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
+ obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
+ obj-$(CONFIG_TPS65010)		+= tps65010.o
+diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
+deleted file mode 100644
+index ec17d6b..0000000
+--- a/drivers/i2c/chips/ds1337.c
++++ /dev/null
+@@ -1,410 +0,0 @@
+-/*
+- *  linux/drivers/i2c/chips/ds1337.c
+- *
+- *  Copyright (C) 2005 James Chapman <jchapman at katalix.com>
+- *
+- *	based on linux/drivers/acorn/char/pcf8583.c
+- *  Copyright (C) 2000 Russell King
+- *
+- * 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.
+- *
+- * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip
+- */
+-
+-#include <linux/module.h>
+-#include <linux/init.h>
+-#include <linux/slab.h>
+-#include <linux/i2c.h>
+-#include <linux/string.h>
+-#include <linux/rtc.h>		/* get the user-level API */
+-#include <linux/bcd.h>
+-#include <linux/list.h>
+-
+-/* Device registers */
+-#define DS1337_REG_HOUR		2
+-#define DS1337_REG_DAY		3
+-#define DS1337_REG_DATE		4
+-#define DS1337_REG_MONTH	5
+-#define DS1337_REG_CONTROL	14
+-#define DS1337_REG_STATUS	15
+-
+-/* FIXME - how do we export these interface constants? */
+-#define DS1337_GET_DATE		0
+-#define DS1337_SET_DATE		1
+-
+-/*
+- * Functions declaration
+- */
+-static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
+-
+-I2C_CLIENT_INSMOD_1(ds1337);
+-
+-static int ds1337_attach_adapter(struct i2c_adapter *adapter);
+-static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
+-static void ds1337_init_client(struct i2c_client *client);
+-static int ds1337_detach_client(struct i2c_client *client);
+-static int ds1337_command(struct i2c_client *client, unsigned int cmd,
+-			  void *arg);
+-
+-/*
+- * Driver data (common to all clients)
+- */
+-static struct i2c_driver ds1337_driver = {
+-	.driver = {
+-		.name	= "ds1337",
+-	},
+-	.attach_adapter	= ds1337_attach_adapter,
+-	.detach_client	= ds1337_detach_client,
+-	.command	= ds1337_command,
+-};
+-
+-/*
+- * Client data (each client gets its own)
+- */
+-struct ds1337_data {
+-	struct i2c_client client;
+-	struct list_head list;
+-};
+-
+-/*
+- * Internal variables
+- */
+-static LIST_HEAD(ds1337_clients);
+-
+-static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
+-{
+-	s32 tmp = i2c_smbus_read_byte_data(client, reg);
+-
+-	if (tmp < 0)
+-		return -EIO;
+-
+-	*value = tmp;
+-
+-	return 0;
+-}
+-
+-/*
+- * Chip access functions
+- */
+-static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
+-{
+-	int result;
+-	u8 buf[7];
+-	u8 val;
+-	struct i2c_msg msg[2];
+-	u8 offs = 0;
+-
+-	if (!dt) {
+-		dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
+-		return -EINVAL;
+-	}
+-
+-	msg[0].addr = client->addr;
+-	msg[0].flags = 0;
+-	msg[0].len = 1;
+-	msg[0].buf = &offs;
+-
+-	msg[1].addr = client->addr;
+-	msg[1].flags = I2C_M_RD;
+-	msg[1].len = sizeof(buf);
+-	msg[1].buf = &buf[0];
+-
+-	result = i2c_transfer(client->adapter, msg, 2);
+-
+-	dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
+-		__FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
+-		buf[4], buf[5], buf[6]);
+-
+-	if (result == 2) {
+-		dt->tm_sec = BCD2BIN(buf[0]);
+-		dt->tm_min = BCD2BIN(buf[1]);
+-		val = buf[2] & 0x3f;
+-		dt->tm_hour = BCD2BIN(val);
+-		dt->tm_wday = BCD2BIN(buf[3]) - 1;
+-		dt->tm_mday = BCD2BIN(buf[4]);
+-		val = buf[5] & 0x7f;
+-		dt->tm_mon = BCD2BIN(val) - 1;
+-		dt->tm_year = BCD2BIN(buf[6]);
+-		if (buf[5] & 0x80)
+-			dt->tm_year += 100;
+-
+-		dev_dbg(&client->dev, "%s: secs=%d, mins=%d, "
+-			"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
+-			__FUNCTION__, dt->tm_sec, dt->tm_min,
+-			dt->tm_hour, dt->tm_mday,
+-			dt->tm_mon, dt->tm_year, dt->tm_wday);
+-
+-		return 0;
+-	}
+-
+-	dev_err(&client->dev, "error reading data! %d\n", result);
+-	return -EIO;
+-}
+-
+-static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
+-{
+-	int result;
+-	u8 buf[8];
+-	u8 val;
+-	struct i2c_msg msg[1];
+-
+-	if (!dt) {
+-		dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
+-		return -EINVAL;
+-	}
+-
+-	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+-		"mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
+-		dt->tm_sec, dt->tm_min, dt->tm_hour,
+-		dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
+-
+-	buf[0] = 0;		/* reg offset */
+-	buf[1] = BIN2BCD(dt->tm_sec);
+-	buf[2] = BIN2BCD(dt->tm_min);
+-	buf[3] = BIN2BCD(dt->tm_hour);
+-	buf[4] = BIN2BCD(dt->tm_wday + 1);
+-	buf[5] = BIN2BCD(dt->tm_mday);
+-	buf[6] = BIN2BCD(dt->tm_mon + 1);
+-	val = dt->tm_year;
+-	if (val >= 100) {
+-		val -= 100;
+-		buf[6] |= (1 << 7);
+-	}
+-	buf[7] = BIN2BCD(val);
+-
+-	msg[0].addr = client->addr;
+-	msg[0].flags = 0;
+-	msg[0].len = sizeof(buf);
+-	msg[0].buf = &buf[0];
+-
+-	result = i2c_transfer(client->adapter, msg, 1);
+-	if (result == 1)
+-		return 0;
+-
+-	dev_err(&client->dev, "error writing data! %d\n", result);
+-	return -EIO;
+-}
+-
+-static int ds1337_command(struct i2c_client *client, unsigned int cmd,
+-			  void *arg)
+-{
+-	dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+-
+-	switch (cmd) {
+-	case DS1337_GET_DATE:
+-		return ds1337_get_datetime(client, arg);
+-
+-	case DS1337_SET_DATE:
+-		return ds1337_set_datetime(client, arg);
+-
+-	default:
+-		return -EINVAL;
+-	}
+-}
+-
+-/*
+- * Public API for access to specific device. Useful for low-level
+- * RTC access from kernel code.
+- */
+-int ds1337_do_command(int bus, int cmd, void *arg)
+-{
+-	struct list_head *walk;
+-	struct list_head *tmp;
+-	struct ds1337_data *data;
+-
+-	list_for_each_safe(walk, tmp, &ds1337_clients) {
+-		data = list_entry(walk, struct ds1337_data, list);
+-		if (data->client.adapter->nr == bus)
+-			return ds1337_command(&data->client, cmd, arg);
+-	}
+-
+-	return -ENODEV;
+-}
+-
+-static int ds1337_attach_adapter(struct i2c_adapter *adapter)
+-{
+-	return i2c_probe(adapter, &addr_data, ds1337_detect);
+-}
+-
+-/*
+- * The following function does more than just detection. If detection
+- * succeeds, it also registers the new chip.
+- */
+-static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
+-{
+-	struct i2c_client *new_client;
+-	struct ds1337_data *data;
+-	int err = 0;
+-	const char *name = "";
+-
+-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+-				     I2C_FUNC_I2C))
+-		goto exit;
+-
+-	if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
+-		err = -ENOMEM;
+-		goto exit;
+-	}
+-	INIT_LIST_HEAD(&data->list);
+-
+-	/* The common I2C client data is placed right before the
+-	 * DS1337-specific data. 
+-	 */
+-	new_client = &data->client;
+-	i2c_set_clientdata(new_client, data);
+-	new_client->addr = address;
+-	new_client->adapter = adapter;
+-	new_client->driver = &ds1337_driver;
+-	new_client->flags = 0;
+-
+-	/*
+-	 * Now we do the remaining detection. A negative kind means that
+-	 * the driver was loaded with no force parameter (default), so we
+-	 * must both detect and identify the chip. A zero kind means that
+-	 * the driver was loaded with the force parameter, the detection
+-	 * step shall be skipped. A positive kind means that the driver
+-	 * was loaded with the force parameter and a given kind of chip is
+-	 * requested, so both the detection and the identification steps
+-	 * are skipped.
+-	 *
+-	 * For detection, we read registers that are most likely to cause
+-	 * detection failure, i.e. those that have more bits with fixed
+-	 * or reserved values.
+-	 */
+-
+-	/* Default to an DS1337 if forced */
+-	if (kind == 0)
+-		kind = ds1337;
+-
+-	if (kind < 0) {		/* detection and identification */
+-		u8 data;
+-
+-		/* Check that status register bits 6-2 are zero */
+-		if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) ||
+-		    (data & 0x7c))
+-			goto exit_free;
+-
+-		/* Check for a valid day register value */
+-		if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) ||
+-		    (data == 0) || (data & 0xf8))
+-			goto exit_free;
+-
+-		/* Check for a valid date register value */
+-		if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) ||
+-		    (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) ||
+-		    (data >= 0x32))
+-			goto exit_free;
+-
+-		/* Check for a valid month register value */
+-		if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) ||
+-		    (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) ||
+-		    ((data >= 0x13) && (data <= 0x19)))
+-			goto exit_free;
+-
+-		/* Check that control register bits 6-5 are zero */
+-		if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) ||
+-		    (data & 0x60))
+-			goto exit_free;
+-
+-		kind = ds1337;
+-	}
+-
+-	if (kind == ds1337)
+-		name = "ds1337";
+-
+-	/* We can fill in the remaining client fields */
+-	strlcpy(new_client->name, name, I2C_NAME_SIZE);
+-
+-	/* Tell the I2C layer a new client has arrived */
+-	if ((err = i2c_attach_client(new_client)))
+-		goto exit_free;
+-
+-	/* Initialize the DS1337 chip */
+-	ds1337_init_client(new_client);
+-
+-	/* Add client to local list */
+-	list_add(&data->list, &ds1337_clients);
+-
+-	return 0;
+-
+-exit_free:
+-	kfree(data);
+-exit:
+-	return err;
+-}
+-
+-static void ds1337_init_client(struct i2c_client *client)
+-{
+-	u8 status, control;
+-
+-	/* On some boards, the RTC isn't configured by boot firmware.
+-	 * Handle that case by starting/configuring the RTC now.
+-	 */
+-	status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
+-	control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
+-
+-	if ((status & 0x80) || (control & 0x80)) {
+-		/* RTC not running */
+-		u8 buf[1+16];	/* First byte is interpreted as address */
+-		struct i2c_msg msg[1];
+-
+-		dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
+-
+-		/* Initialize all, including STATUS and CONTROL to zero */
+-		memset(buf, 0, sizeof(buf));
+-
+-		/* Write valid values in the date/time registers */
+-		buf[1+DS1337_REG_DAY] = 1;
+-		buf[1+DS1337_REG_DATE] = 1;
+-		buf[1+DS1337_REG_MONTH] = 1;
+-
+-		msg[0].addr = client->addr;
+-		msg[0].flags = 0;
+-		msg[0].len = sizeof(buf);
+-		msg[0].buf = &buf[0];
+-
+-		i2c_transfer(client->adapter, msg, 1);
+-	} else {
+-		/* Running: ensure that device is set in 24-hour mode */
+-		s32 val;
+-
+-		val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+-		if ((val >= 0) && (val & (1 << 6)))
+-			i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+-						  val & 0x3f);
+-	}
+-}
+-
+-static int ds1337_detach_client(struct i2c_client *client)
+-{
+-	int err;
+-	struct ds1337_data *data = i2c_get_clientdata(client);
+-
+-	if ((err = i2c_detach_client(client)))
+-		return err;
+-
+-	list_del(&data->list);
+-	kfree(data);
+-	return 0;
+-}
+-
+-static int __init ds1337_init(void)
+-{
+-	return i2c_add_driver(&ds1337_driver);
+-}
+-
+-static void __exit ds1337_exit(void)
+-{
+-	i2c_del_driver(&ds1337_driver);
+-}
+-
+-MODULE_AUTHOR("James Chapman <jchapman at katalix.com>");
+-MODULE_DESCRIPTION("DS1337 RTC driver");
+-MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL_GPL(ds1337_do_command);
+-
+-module_init(ds1337_init);
+-module_exit(ds1337_exit);
+diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
+deleted file mode 100644
+index 8a2ff0c..0000000
+--- a/drivers/i2c/chips/ds1374.c
++++ /dev/null
+@@ -1,267 +0,0 @@
+-/*
+- * drivers/i2c/chips/ds1374.c
+- *
+- * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock
+- *
+- * Author: Randy Vinson <rvinson at mvista.com>
+- *
+- * Based on the m41t00.c by Mark Greer <mgreer at mvista.com>
+- *
+- * 2005 (c) MontaVista Software, Inc. This file is licensed under
+- * the terms of the GNU General Public License version 2. This program
+- * is licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
+-/*
+- * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
+- * interface and the SMBus interface of the i2c subsystem.
+- * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
+- * recommened in .../Documentation/i2c/writing-clients section
+- * "Sending and receiving", using SMBus level communication is preferred.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/i2c.h>
+-#include <linux/rtc.h>
+-#include <linux/bcd.h>
+-#include <linux/mutex.h>
+-#include <linux/workqueue.h>
+-
+-#define DS1374_REG_TOD0		0x00
+-#define DS1374_REG_TOD1		0x01
+-#define DS1374_REG_TOD2		0x02
+-#define DS1374_REG_TOD3		0x03
+-#define DS1374_REG_WDALM0	0x04
+-#define DS1374_REG_WDALM1	0x05
+-#define DS1374_REG_WDALM2	0x06
+-#define DS1374_REG_CR		0x07
+-#define DS1374_REG_SR		0x08
+-#define DS1374_REG_SR_OSF	0x80
+-#define DS1374_REG_TCR		0x09
+-
+-#define	DS1374_DRV_NAME		"ds1374"
+-
+-static DEFINE_MUTEX(ds1374_mutex);
+-
+-static struct i2c_driver ds1374_driver;
+-static struct i2c_client *save_client;
+-
+-static unsigned short ignore[] = { I2C_CLIENT_END };
+-static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+-
+-static struct i2c_client_address_data addr_data = {
+-	.normal_i2c = normal_addr,
+-	.probe = ignore,
+-	.ignore = ignore,
+-};
+-
+-static ulong ds1374_read_rtc(void)
+-{
+-	ulong time = 0;
+-	int reg = DS1374_REG_WDALM0;
+-
+-	while (reg--) {
+-		s32 tmp;
+-		if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) {
+-			dev_warn(&save_client->dev,
+-				 "can't read from rtc chip\n");
+-			return 0;
+-		}
+-		time = (time << 8) | (tmp & 0xff);
+-	}
+-	return time;
+-}
+-
+-static void ds1374_write_rtc(ulong time)
+-{
+-	int reg;
+-
+-	for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) {
+-		if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff)
+-		    < 0) {
+-			dev_warn(&save_client->dev,
+-				 "can't write to rtc chip\n");
+-			break;
+-		}
+-		time = time >> 8;
+-	}
+-}
+-
+-static void ds1374_check_rtc_status(void)
+-{
+-	s32 tmp;
+-
+-	tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR);
+-	if (tmp < 0) {
+-		dev_warn(&save_client->dev,
+-			 "can't read status from rtc chip\n");
+-		return;
+-	}
+-	if (tmp & DS1374_REG_SR_OSF) {
+-		dev_warn(&save_client->dev,
+-			 "oscillator discontinuity flagged, time unreliable\n");
+-		tmp &= ~DS1374_REG_SR_OSF;
+-		tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR,
+-						tmp & 0xff);
+-		if (tmp < 0)
+-			dev_warn(&save_client->dev,
+-				 "can't clear discontinuity notification\n");
+-	}
+-}
+-
+-ulong ds1374_get_rtc_time(void)
+-{
+-	ulong t1, t2;
+-	int limit = 10;		/* arbitrary retry limit */
+-
+-	mutex_lock(&ds1374_mutex);
+-
+-	/*
+-	 * Since the reads are being performed one byte at a time using
+-	 * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+-	 * carry will occur during the read. To detect this, 2 reads are
+-	 * performed and compared.
+-	 */
+-	do {
+-		t1 = ds1374_read_rtc();
+-		t2 = ds1374_read_rtc();
+-	} while (t1 != t2 && limit--);
+-
+-	mutex_unlock(&ds1374_mutex);
+-
+-	if (t1 != t2) {
+-		dev_warn(&save_client->dev,
+-			 "can't get consistent time from rtc chip\n");
+-		t1 = 0;
+-	}
+-
+-	return t1;
+-}
+-
+-static ulong new_time;
+-
+-static void ds1374_set_work(struct work_struct *work)
+-{
+-	ulong t1, t2;
+-	int limit = 10;		/* arbitrary retry limit */
+-
+-	t1 = new_time;
+-
+-	mutex_lock(&ds1374_mutex);
+-
+-	/*
+-	 * Since the writes are being performed one byte at a time using
+-	 * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+-	 * carry will occur during the write. To detect this, the write
+-	 * value is read back and compared.
+-	 */
+-	do {
+-		ds1374_write_rtc(t1);
+-		t2 = ds1374_read_rtc();
+-	} while (t1 != t2 && limit--);
+-
+-	mutex_unlock(&ds1374_mutex);
+-
+-	if (t1 != t2)
+-		dev_warn(&save_client->dev,
+-			 "can't confirm time set from rtc chip\n");
+-}
+-
+-static struct workqueue_struct *ds1374_workqueue;
+-
+-static DECLARE_WORK(ds1374_work, ds1374_set_work);
+-
+-int ds1374_set_rtc_time(ulong nowtime)
+-{
+-	new_time = nowtime;
+-
+-	if (in_interrupt())
+-		queue_work(ds1374_workqueue, &ds1374_work);
+-	else
+-		ds1374_set_work(NULL);
+-
+-	return 0;
+-}
+-
+-/*
+- *****************************************************************************
+- *
+- *	Driver Interface
+- *
+- *****************************************************************************
+- */
+-static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
+-{
+-	struct i2c_client *client;
+-	int rc;
+-
+-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+-	if (!client)
+-		return -ENOMEM;
+-
+-	strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
+-	client->addr = addr;
+-	client->adapter = adap;
+-	client->driver = &ds1374_driver;
+-
+-	ds1374_workqueue = create_singlethread_workqueue("ds1374");
+-	if (!ds1374_workqueue) {
+-		kfree(client);
+-		return -ENOMEM;	/* most expected reason */
+-	}
+-
+-	if ((rc = i2c_attach_client(client)) != 0) {
+-		kfree(client);
+-		return rc;
+-	}
+-
+-	save_client = client;
+-
+-	ds1374_check_rtc_status();
+-
+-	return 0;
+-}
+-
+-static int ds1374_attach(struct i2c_adapter *adap)
+-{
+-	return i2c_probe(adap, &addr_data, ds1374_probe);
+-}
+-
+-static int ds1374_detach(struct i2c_client *client)
+-{
+-	int rc;
+-
+-	if ((rc = i2c_detach_client(client)) == 0) {
+-		kfree(i2c_get_clientdata(client));
+-		destroy_workqueue(ds1374_workqueue);
+-	}
+-	return rc;
+-}
+-
+-static struct i2c_driver ds1374_driver = {
+-	.driver = {
+-		.name	= DS1374_DRV_NAME,
+-	},
+-	.id = I2C_DRIVERID_DS1374,
+-	.attach_adapter = ds1374_attach,
+-	.detach_client = ds1374_detach,
+-};
+-
+-static int __init ds1374_init(void)
+-{
+-	return i2c_add_driver(&ds1374_driver);
+-}
+-
+-static void __exit ds1374_exit(void)
+-{
+-	i2c_del_driver(&ds1374_driver);
+-}
+-
+-module_init(ds1374_init);
+-module_exit(ds1374_exit);
+-
+-MODULE_AUTHOR("Randy Vinson <rvinson at mvista.com>");
+-MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
+index 1a7eeeb..fde297b 100644
+--- a/drivers/i2c/chips/eeprom.c
++++ b/drivers/i2c/chips/eeprom.c
+@@ -35,7 +35,7 @@
+ #include <linux/mutex.h>
+ 
+ /* Addresses to scan */
+-static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
++static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
+ 					0x55, 0x56, 0x57, I2C_CLIENT_END };
+ 
+ /* Insmod parameters */
+diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
+index b767603..2a31601 100644
+--- a/drivers/i2c/chips/isp1301_omap.c
++++ b/drivers/i2c/chips/isp1301_omap.c
+@@ -100,7 +100,7 @@ struct isp1301 {
+ 
+ #if	defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
+ 
+-#include <asm/arch/tps65010.h>
++#include <linux/i2c/tps65010.h>
+ 
+ #else
+ 
+@@ -259,12 +259,6 @@ static inline const char *state_name(struct isp1301 *isp)
+ 	return state_string(isp->otg.state);
+ }
+ 
+-#ifdef	VERBOSE
+-#define	dev_vdbg			dev_dbg
+-#else
+-#define	dev_vdbg(dev, fmt, arg...)	do{}while(0)
+-#endif
+-
+ /*-------------------------------------------------------------------------*/
+ 
+ /* NOTE:  some of this ISP1301 setup is specific to H2 boards;
+diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
+deleted file mode 100644
+index 3fcb646..0000000
+--- a/drivers/i2c/chips/m41t00.c
++++ /dev/null
+@@ -1,413 +0,0 @@
+-/*
+- * I2C client/driver for the ST M41T00 family of i2c rtc chips.
+- *
+- * Author: Mark A. Greer <mgreer at mvista.com>
+- *
+- * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under
+- * the terms of the GNU General Public License version 2. This program
+- * is licensed "as is" without any warranty of any kind, whether express
+- * or implied.
+- */
+-/*
+- * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
+- * interface and the SMBus interface of the i2c subsystem.
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/interrupt.h>
+-#include <linux/i2c.h>
+-#include <linux/rtc.h>
+-#include <linux/bcd.h>
+-#include <linux/workqueue.h>
+-#include <linux/platform_device.h>
+-#include <linux/m41t00.h>
+-#include <asm/time.h>
+-#include <asm/rtc.h>
+-
+-static struct i2c_driver m41t00_driver;
+-static struct i2c_client *save_client;
+-
+-static unsigned short ignore[] = { I2C_CLIENT_END };
+-static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END };
+-
+-static struct i2c_client_address_data addr_data = {
+-	.normal_i2c	= normal_addr,
+-	.probe		= ignore,
+-	.ignore		= ignore,
+-};
+-
+-struct m41t00_chip_info {
+-	u8	type;
+-	char	*name;
+-	u8	read_limit;
+-	u8	sec;		/* Offsets for chip regs */
+-	u8	min;
+-	u8	hour;
+-	u8	day;
+-	u8	mon;
+-	u8	year;
+-	u8	alarm_mon;
+-	u8	alarm_hour;
+-	u8	sqw;
+-	u8	sqw_freq;
+-};
+-
+-static struct m41t00_chip_info m41t00_chip_info_tbl[] = {
+-	{
+-		.type		= M41T00_TYPE_M41T00,
+-		.name		= "m41t00",
+-		.read_limit	= 5,
+-		.sec		= 0,
+-		.min		= 1,
+-		.hour		= 2,
+-		.day		= 4,
+-		.mon		= 5,
+-		.year		= 6,
+-	},
+-	{
+-		.type		= M41T00_TYPE_M41T81,
+-		.name		= "m41t81",
+-		.read_limit	= 1,
+-		.sec		= 1,
+-		.min		= 2,
+-		.hour		= 3,
+-		.day		= 5,
+-		.mon		= 6,
+-		.year		= 7,
+-		.alarm_mon	= 0xa,
+-		.alarm_hour	= 0xc,
+-		.sqw		= 0x13,
+-	},
+-	{
+-		.type		= M41T00_TYPE_M41T85,
+-		.name		= "m41t85",
+-		.read_limit	= 1,
+-		.sec		= 1,
+-		.min		= 2,
+-		.hour		= 3,
+-		.day		= 5,
+-		.mon		= 6,
+-		.year		= 7,
+-		.alarm_mon	= 0xa,
+-		.alarm_hour	= 0xc,
+-		.sqw		= 0x13,
+-	},
+-};
+-static struct m41t00_chip_info *m41t00_chip;
+-
+-ulong
+-m41t00_get_rtc_time(void)
+-{
+-	s32 sec, min, hour, day, mon, year;
+-	s32 sec1, min1, hour1, day1, mon1, year1;
+-	u8 reads = 0;
+-	u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */
+-	struct i2c_msg msgs[] = {
+-		{
+-			.addr	= save_client->addr,
+-			.flags	= 0,
+-			.len	= 1,
+-			.buf	= msgbuf,
+-		},
+-		{
+-			.addr	= save_client->addr,
+-			.flags	= I2C_M_RD,
+-			.len	= 8,
+-			.buf	= buf,
+-		},
+-	};
+-
+-	sec = min = hour = day = mon = year = 0;
+-
+-	do {
+-		if (i2c_transfer(save_client->adapter, msgs, 2) < 0)
+-			goto read_err;
+-
+-		sec1 = sec;
+-		min1 = min;
+-		hour1 = hour;
+-		day1 = day;
+-		mon1 = mon;
+-		year1 = year;
+-
+-		sec = buf[m41t00_chip->sec] & 0x7f;
+-		min = buf[m41t00_chip->min] & 0x7f;
+-		hour = buf[m41t00_chip->hour] & 0x3f;
+-		day = buf[m41t00_chip->day] & 0x3f;
+-		mon = buf[m41t00_chip->mon] & 0x1f;
+-		year = buf[m41t00_chip->year];
+-	} while ((++reads < m41t00_chip->read_limit) && ((sec != sec1)
+-			|| (min != min1) || (hour != hour1) || (day != day1)
+-			|| (mon != mon1) || (year != year1)));
+-
+-	if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1)
+-			|| (hour != hour1) || (day != day1) || (mon != mon1)
+-			|| (year != year1)))
+-		goto read_err;
+-
+-	sec = BCD2BIN(sec);
+-	min = BCD2BIN(min);
+-	hour = BCD2BIN(hour);
+-	day = BCD2BIN(day);
+-	mon = BCD2BIN(mon);
+-	year = BCD2BIN(year);
+-
+-	year += 1900;
+-	if (year < 1970)
+-		year += 100;
+-
+-	return mktime(year, mon, day, hour, min, sec);
+-
+-read_err:
+-	dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n");
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(m41t00_get_rtc_time);
+-
+-static void
+-m41t00_set(void *arg)
+-{
+-	struct rtc_time	tm;
+-	int nowtime = *(int *)arg;
+-	s32 sec, min, hour, day, mon, year;
+-	u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 };
+-	struct i2c_msg msgs[] = {
+-		{
+-			.addr	= save_client->addr,
+-			.flags	= 0,
+-			.len	= 1,
+-			.buf	= msgbuf,
+-		},
+-		{
+-			.addr	= save_client->addr,
+-			.flags	= I2C_M_RD,
+-			.len	= 8,
+-			.buf	= buf,
+-		},
+-	};
+-
+-	to_tm(nowtime, &tm);
+-	tm.tm_year = (tm.tm_year - 1900) % 100;
+-
+-	sec = BIN2BCD(tm.tm_sec);
+-	min = BIN2BCD(tm.tm_min);
+-	hour = BIN2BCD(tm.tm_hour);
+-	day = BIN2BCD(tm.tm_mday);
+-	mon = BIN2BCD(tm.tm_mon);
+-	year = BIN2BCD(tm.tm_year);
+-
+-	/* Read reg values into buf[0..7]/wbuf[1..8] */
+-	if (i2c_transfer(save_client->adapter, msgs, 2) < 0) {
+-		dev_err(&save_client->dev, "m41t00_set: Read error\n");
+-		return;
+-	}
+-
+-	wbuf[0] = 0; /* offset into rtc's regs */
+-	buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f);
+-	buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f);
+-	buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f);
+-	buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f);
+-	buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f);
+-	buf[m41t00_chip->year] = year;
+-
+-	if (i2c_master_send(save_client, wbuf, 9) < 0)
+-		dev_err(&save_client->dev, "m41t00_set: Write error\n");
+-}
+-
+-static ulong new_time;
+-/* well, isn't this API just _lovely_? */
+-static void
+-m41t00_barf(struct work_struct *unusable)
+-{
+-	m41t00_set(&new_time);
+-}
+-
+-static struct workqueue_struct *m41t00_wq;
+-static DECLARE_WORK(m41t00_work, m41t00_barf);
+-
+-int
+-m41t00_set_rtc_time(ulong nowtime)
+-{
+-	new_time = nowtime;
+-
+-	if (in_interrupt())
+-		queue_work(m41t00_wq, &m41t00_work);
+-	else
+-		m41t00_set(&new_time);
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(m41t00_set_rtc_time);
+-
+-/*
+- *****************************************************************************
+- *
+- *	platform_data Driver Interface
+- *
+- *****************************************************************************
+- */
+-static int __init
+-m41t00_platform_probe(struct platform_device *pdev)
+-{
+-	struct m41t00_platform_data *pdata;
+-	int i;
+-
+-	if (pdev && (pdata = pdev->dev.platform_data)) {
+-		normal_addr[0] = pdata->i2c_addr;
+-
+-		for (i=0; i<ARRAY_SIZE(m41t00_chip_info_tbl); i++)
+-			if (m41t00_chip_info_tbl[i].type == pdata->type) {
+-				m41t00_chip = &m41t00_chip_info_tbl[i];
+-				m41t00_chip->sqw_freq = pdata->sqw_freq;
+-				return 0;
+-			}
+-	}
+-	return -ENODEV;
+-}
+-
+-static int __exit
+-m41t00_platform_remove(struct platform_device *pdev)
+-{
+-	return 0;
+-}
+-
+-static struct platform_driver m41t00_platform_driver = {
+-	.probe  = m41t00_platform_probe,
+-	.remove = m41t00_platform_remove,
+-	.driver = {
+-		.owner = THIS_MODULE,
+-		.name  = M41T00_DRV_NAME,
+-	},
+-};
+-
+-/*
+- *****************************************************************************
+- *
+- *	Driver Interface
+- *
+- *****************************************************************************
+- */
+-static int
+-m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
+-{
+-	struct i2c_client *client;
+-	int rc;
+-
+-	if (!i2c_check_functionality(adap, I2C_FUNC_I2C
+-			| I2C_FUNC_SMBUS_BYTE_DATA))
+-		return 0;
+-
+-	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+-	if (!client)
+-		return -ENOMEM;
+-
+-	strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE);
+-	client->addr = addr;
+-	client->adapter = adap;
+-	client->driver = &m41t00_driver;
+-
+-	if ((rc = i2c_attach_client(client)))
+-		goto attach_err;
+-
+-	if (m41t00_chip->type != M41T00_TYPE_M41T00) {
+-		/* If asked, disable SQW, set SQW frequency & re-enable */
+-		if (m41t00_chip->sqw_freq)
+-			if (((rc = i2c_smbus_read_byte_data(client,
+-					m41t00_chip->alarm_mon)) < 0)
+-			 || ((rc = i2c_smbus_write_byte_data(client,
+-					m41t00_chip->alarm_mon, rc & ~0x40)) <0)
+-			 || ((rc = i2c_smbus_write_byte_data(client,
+-					m41t00_chip->sqw,
+-					m41t00_chip->sqw_freq)) < 0)
+-			 || ((rc = i2c_smbus_write_byte_data(client,
+-					m41t00_chip->alarm_mon, rc | 0x40)) <0))
+-				goto sqw_err;
+-
+-		/* Make sure HT (Halt Update) bit is cleared */
+-		if ((rc = i2c_smbus_read_byte_data(client,
+-				m41t00_chip->alarm_hour)) < 0)
+-			goto ht_err;
+-
+-		if (rc & 0x40)
+-			if ((rc = i2c_smbus_write_byte_data(client,
+-					m41t00_chip->alarm_hour, rc & ~0x40))<0)
+-				goto ht_err;
+-	}
+-
+-	/* Make sure ST (stop) bit is cleared */
+-	if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0)
+-		goto st_err;
+-
+-	if (rc & 0x80)
+-		if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec,
+-				rc & ~0x80)) < 0)
+-			goto st_err;
+-
+-	m41t00_wq = create_singlethread_workqueue(m41t00_chip->name);
+-	save_client = client;
+-	return 0;
+-
+-st_err:
+-	dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n");
+-	goto attach_err;
+-ht_err:
+-	dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n");
+-	goto attach_err;
+-sqw_err:
+-	dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n");
+-attach_err:
+-	kfree(client);
+-	return rc;
+-}
+-
+-static int
+-m41t00_attach(struct i2c_adapter *adap)
+-{
+-	return i2c_probe(adap, &addr_data, m41t00_probe);
+-}
+-
+-static int
+-m41t00_detach(struct i2c_client *client)
+-{
+-	int rc;
+-
+-	if ((rc = i2c_detach_client(client)) == 0) {
+-		kfree(client);
+-		destroy_workqueue(m41t00_wq);
+-	}
+-	return rc;
+-}
+-
+-static struct i2c_driver m41t00_driver = {
+-	.driver = {
+-		.name	= M41T00_DRV_NAME,
+-	},
+-	.id		= I2C_DRIVERID_STM41T00,
+-	.attach_adapter	= m41t00_attach,
+-	.detach_client	= m41t00_detach,
+-};
+-
+-static int __init
+-m41t00_init(void)
+-{
+-	int rc;
+-
+-	if (!(rc = platform_driver_register(&m41t00_platform_driver)))
+-		rc = i2c_add_driver(&m41t00_driver);
+-	return rc;
+-}
+-
+-static void __exit
+-m41t00_exit(void)
+-{
+-	i2c_del_driver(&m41t00_driver);
+-	platform_driver_unregister(&m41t00_platform_driver);
+-}
+-
+-module_init(m41t00_init);
+-module_exit(m41t00_exit);
+-
+-MODULE_AUTHOR("Mark A. Greer <mgreer at mvista.com>");
+-MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver");
+-MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
+index 64692f6..fb7ea56 100644
+--- a/drivers/i2c/chips/max6875.c
++++ b/drivers/i2c/chips/max6875.c
+@@ -34,7 +34,7 @@
+ #include <linux/mutex.h>
+ 
+ /* Do not scan - the MAX6875 access method will write to some EEPROM chips */
+-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
++static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+ 
+ /* Insmod parameters */
+ I2C_CLIENT_INSMOD_1(max6875);
+diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
+index 21c6dd6..b3b830c 100644
+--- a/drivers/i2c/chips/pcf8574.c
++++ b/drivers/i2c/chips/pcf8574.c
+@@ -41,9 +41,11 @@
+ #include <linux/i2c.h>
+ 
+ /* Addresses to scan */
+-static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+-					0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+-					I2C_CLIENT_END };
++static const unsigned short normal_i2c[] = {
++	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++	I2C_CLIENT_END
++};
+ 
+ /* Insmod parameters */
+ I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
+diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c
+new file mode 100644
+index 0000000..3ea08ac
+--- /dev/null
++++ b/drivers/i2c/chips/pcf8575.c
+@@ -0,0 +1,214 @@
++/*
++  pcf8575.c
 +
-+	spin_lock_irqsave(&dev->lock, flags);
-+	if (dev->started + sg_num > HIFN_QUEUE_LENGTH) {
-+		err = -EAGAIN;
-+		goto err_out;
-+	}
++  About the PCF8575 chip: the PCF8575 is a 16-bit I/O expander for the I2C bus
++  produced by a.o. Philips Semiconductors.
 +
-+	dev->snum++;
-+	dev->started += sg_num;
++  Copyright (C) 2006 Michael Hennerich, Analog Devices Inc.
++  <hennerich at blackfin.uclinux.org>
++  Based on pcf8574.c.
 +
-+	while (nbytes) {
-+		src = &req->src[idx];
-+		dst = &req->dst[idx];
-+		t = &ctx->walk.cache[idx];
++  Copyright (c) 2007 Bart Van Assche <bart.vanassche at gmail.com>.
++  Ported this driver from ucLinux to the mainstream Linux kernel.
 +
-+		if (t->length) {
-+			spage = dpage = sg_page(t);
-+			soff = doff = 0;
-+			len = t->length;
-+		} else {
-+			spage = sg_page(src);
-+			soff = src->offset;
++  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.
 +
-+			dpage = sg_page(dst);
-+			doff = dst->offset;
++  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.
 +
-+			len = dst->length;
-+		}
++  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.
++*/
 +
-+		idx++;
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/i2c.h>
++#include <linux/slab.h>  /* kzalloc() */
++#include <linux/sysfs.h> /* sysfs_create_group() */
 +
-+		err = hifn_setup_dma(dev, spage, soff, dpage, doff, nbytes,
-+				req, ctx);
-+		if (err)
-+			goto err_out;
++/* Addresses to scan */
++static const unsigned short normal_i2c[] = {
++	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
++	I2C_CLIENT_END
++};
 +
-+		nbytes -= len;
-+	}
++/* Insmod parameters */
++I2C_CLIENT_INSMOD;
 +
-+	dev->active = HIFN_DEFAULT_ACTIVE_NUM;
-+	spin_unlock_irqrestore(&dev->lock, flags);
 +
-+	return 0;
++/* Each client has this additional data */
++struct pcf8575_data {
++	struct i2c_client client;
++	int write;		/* last written value, or error code */
++};
 +
-+err_out:
-+	spin_unlock_irqrestore(&dev->lock, flags);
-+err_out_exit:
-+	if (err && printk_ratelimit())
-+		dprintk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
-+				"type: %u, err: %d.\n",
-+			dev->name, ctx->iv, ctx->ivsize,
-+			ctx->key, ctx->keysize,
-+			ctx->mode, ctx->op, ctx->type, err);
++static int pcf8575_attach_adapter(struct i2c_adapter *adapter);
++static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind);
++static int pcf8575_detach_client(struct i2c_client *client);
 +
-+	return err;
-+}
++/* This is the driver that will be inserted */
++static struct i2c_driver pcf8575_driver = {
++	.driver = {
++		.owner	= THIS_MODULE,
++		.name	= "pcf8575",
++	},
++	.attach_adapter	= pcf8575_attach_adapter,
++	.detach_client	= pcf8575_detach_client,
++};
 +
-+static int hifn_test(struct hifn_device *dev, int encdec, u8 snum)
++/* following are the sysfs callback functions */
++static ssize_t show_read(struct device *dev, struct device_attribute *attr,
++			 char *buf)
 +{
-+	int n, err;
-+	u8 src[16];
-+	struct hifn_context ctx;
-+	u8 fips_aes_ecb_from_zero[16] = {
-+		0x66, 0xE9, 0x4B, 0xD4,
-+		0xEF, 0x8A, 0x2C, 0x3B,
-+		0x88, 0x4C, 0xFA, 0x59,
-+		0xCA, 0x34, 0x2B, 0x2E};
-+
-+	memset(src, 0, sizeof(src));
-+	memset(ctx.key, 0, sizeof(ctx.key));
-+
-+	ctx.dev = dev;
-+	ctx.keysize = 16;
-+	ctx.ivsize = 0;
-+	ctx.iv = NULL;
-+	ctx.op = (encdec)?ACRYPTO_OP_ENCRYPT:ACRYPTO_OP_DECRYPT;
-+	ctx.mode = ACRYPTO_MODE_ECB;
-+	ctx.type = ACRYPTO_TYPE_AES_128;
-+	atomic_set(&ctx.sg_num, 1);
-+
-+	err = hifn_setup_dma(dev,
-+			virt_to_page(src), offset_in_page(src),
-+			virt_to_page(src), offset_in_page(src),
-+			sizeof(src), NULL, &ctx);
-+	if (err)
-+		goto err_out;
-+
-+	msleep(200);
++	struct i2c_client *client = to_i2c_client(dev);
++	u16 val;
++	u8 iopin_state[2];
 +
-+	dprintk("%s: decoded: ", dev->name);
-+	for (n=0; n<sizeof(src); ++n)
-+		dprintk("%02x ", src[n]);
-+	dprintk("\n");
-+	dprintk("%s: FIPS   : ", dev->name);
-+	for (n=0; n<sizeof(fips_aes_ecb_from_zero); ++n)
-+		dprintk("%02x ", fips_aes_ecb_from_zero[n]);
-+	dprintk("\n");
++	i2c_master_recv(client, iopin_state, 2);
 +
-+	if (!memcmp(src, fips_aes_ecb_from_zero, sizeof(fips_aes_ecb_from_zero))) {
-+		printk(KERN_INFO "%s: AES 128 ECB test has been successfully "
-+				"passed.\n", dev->name);
-+		return 0;
-+	}
++	val = iopin_state[0];
++	val |= iopin_state[1] << 8;
 +
-+err_out:
-+	printk(KERN_INFO "%s: AES 128 ECB test has been failed.\n", dev->name);
-+	return -1;
++	return sprintf(buf, "%u\n", val);
 +}
 +
-+static int hifn_start_device(struct hifn_device *dev)
-+{
-+	int err;
-+
-+	hifn_reset_dma(dev, 1);
-+
-+	err = hifn_enable_crypto(dev);
-+	if (err)
-+		return err;
-+
-+	hifn_reset_puc(dev);
-+
-+	hifn_init_dma(dev);
-+
-+	hifn_init_registers(dev);
-+
-+	hifn_init_pubrng(dev);
++static DEVICE_ATTR(read, S_IRUGO, show_read, NULL);
 +
-+	return 0;
++static ssize_t show_write(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	struct pcf8575_data *data = dev_get_drvdata(dev);
++	if (data->write < 0)
++		return data->write;
++	return sprintf(buf, "%d\n", data->write);
 +}
 +
-+static int ablkcipher_get(void *saddr, unsigned int *srestp, unsigned int offset,
-+		struct scatterlist *dst, unsigned int size, unsigned int *nbytesp)
++static ssize_t set_write(struct device *dev, struct device_attribute *attr,
++			 const char *buf, size_t count)
 +{
-+	unsigned int srest = *srestp, nbytes = *nbytesp, copy;
-+	void *daddr;
-+	int idx = 0;
++	struct i2c_client *client = to_i2c_client(dev);
++	struct pcf8575_data *data = i2c_get_clientdata(client);
++	unsigned long val = simple_strtoul(buf, NULL, 10);
++	u8 iopin_state[2];
 +
-+	if (srest < size || size > nbytes)
++	if (val > 0xffff)
 +		return -EINVAL;
 +
-+	while (size) {
-+
-+		copy = min(dst->length, srest);
-+
-+		daddr = kmap_atomic(sg_page(dst), KM_IRQ0);
-+		memcpy(daddr + dst->offset + offset, saddr, copy);
-+		kunmap_atomic(daddr, KM_IRQ0);
-+
-+		nbytes -= copy;
-+		size -= copy;
-+		srest -= copy;
-+		saddr += copy;
-+		offset = 0;
-+
-+		dprintk("%s: copy: %u, size: %u, srest: %u, nbytes: %u.\n",
-+				__func__, copy, size, srest, nbytes);
++	data->write = val;
 +
-+		dst++;
-+		idx++;
-+	}
++	iopin_state[0] = val & 0xFF;
++	iopin_state[1] = val >> 8;
 +
-+	*nbytesp = nbytes;
-+	*srestp = srest;
++	i2c_master_send(client, iopin_state, 2);
 +
-+	return idx;
++	return count;
 +}
 +
-+static void hifn_process_ready(struct ablkcipher_request *req, int error)
-+{
-+	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
-+	struct hifn_device *dev;
-+
-+	dprintk("%s: req: %p, ctx: %p.\n", __func__, req, ctx);
-+
-+	dev = ctx->dev;
-+	dprintk("%s: req: %p, started: %d, sg_num: %d.\n",
-+		__func__, req, dev->started, atomic_read(&ctx->sg_num));
-+
-+	if (--dev->started < 0)
-+		BUG();
-+
-+	if (atomic_dec_and_test(&ctx->sg_num)) {
-+		unsigned int nbytes = req->nbytes;
-+		int idx = 0, err;
-+		struct scatterlist *dst, *t;
-+		void *saddr;
-+
-+		if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) {
-+			while (nbytes) {
-+				t = &ctx->walk.cache[idx];
-+				dst = &req->dst[idx];
-+
-+				dprintk("\n%s: sg_page(t): %p, t->length: %u, "
-+					"sg_page(dst): %p, dst->length: %u, "
-+					"nbytes: %u.\n",
-+					__func__, sg_page(t), t->length,
-+					sg_page(dst), dst->length, nbytes);
-+
-+				if (!t->length) {
-+					nbytes -= dst->length;
-+					idx++;
-+					continue;
-+				}
-+
-+				saddr = kmap_atomic(sg_page(t), KM_IRQ1);
-+
-+				err = ablkcipher_get(saddr, &t->length, t->offset,
-+						dst, nbytes, &nbytes);
-+				if (err < 0) {
-+					kunmap_atomic(saddr, KM_IRQ1);
-+					break;
-+				}
++static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
 +
-+				idx += err;
-+				kunmap_atomic(saddr, KM_IRQ1);
-+			}
++static struct attribute *pcf8575_attributes[] = {
++	&dev_attr_read.attr,
++	&dev_attr_write.attr,
++	NULL
++};
 +
-+			ablkcipher_walk_exit(&ctx->walk);
-+		}
++static const struct attribute_group pcf8575_attr_group = {
++	.attrs = pcf8575_attributes,
++};
 +
-+		req->base.complete(&req->base, error);
-+	}
-+}
++/*
++ * Real code
++ */
 +
-+static void hifn_check_for_completion(struct hifn_device *dev, int error)
++static int pcf8575_attach_adapter(struct i2c_adapter *adapter)
 +{
-+	int i;
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+
-+	for (i=0; i<HIFN_D_RES_RSIZE; ++i) {
-+		struct hifn_desc *d = &dma->resr[i];
-+
-+		if (!(d->l & __cpu_to_le32(HIFN_D_VALID)) && dev->sa[i]) {
-+			dev->success++;
-+			dev->reset = 0;
-+			hifn_process_ready(dev->sa[i], error);
-+			dev->sa[i] = NULL;
-+		}
-+
-+		if (d->l & __cpu_to_le32(HIFN_D_DESTOVER | HIFN_D_OVER))
-+			if (printk_ratelimit())
-+				printk("%s: overflow detected [d: %u, o: %u] "
-+						"at %d resr: l: %08x, p: %08x.\n",
-+					dev->name,
-+					!!(d->l & __cpu_to_le32(HIFN_D_DESTOVER)),
-+					!!(d->l & __cpu_to_le32(HIFN_D_OVER)),
-+					i, d->l, d->p);
-+	}
++	return i2c_probe(adapter, &addr_data, pcf8575_detect);
 +}
 +
-+static void hifn_clear_rings(struct hifn_device *dev)
++/* This function is called by i2c_probe */
++static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind)
 +{
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	int i, u;
++	struct i2c_client *client;
++	struct pcf8575_data *data;
++	int err = 0;
 +
-+	dprintk("%s: ring cleanup 1: i: %d.%d.%d.%d, u: %d.%d.%d.%d, "
-+			"k: %d.%d.%d.%d.\n",
-+			dev->name,
-+			dma->cmdi, dma->srci, dma->dsti, dma->resi,
-+			dma->cmdu, dma->srcu, dma->dstu, dma->resu,
-+			dma->cmdk, dma->srck, dma->dstk, dma->resk);
++	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
++		goto exit;
 +
-+	i = dma->resk; u = dma->resu;
-+	while (u != 0) {
-+		if (dma->resr[i].l & __cpu_to_le32(HIFN_D_VALID))
-+			break;
++	/* OK. For now, we presume we have a valid client. We now create the
++	   client structure, even though we cannot fill it completely yet. */
++	data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL);
++	if (!data) {
++		err = -ENOMEM;
++		goto exit;
++	}
 +
-+		if (i != HIFN_D_RES_RSIZE)
-+			u--;
++	client = &data->client;
++	i2c_set_clientdata(client, data);
++	client->addr = address;
++	client->adapter = adapter;
++	client->driver = &pcf8575_driver;
++	strlcpy(client->name, "pcf8575", I2C_NAME_SIZE);
++	data->write = -EAGAIN;
 +
-+		if (++i == (HIFN_D_RES_RSIZE + 1))
-+			i = 0;
-+	}
-+	dma->resk = i; dma->resu = u;
++	/* This is the place to detect whether the chip at the specified
++	   address really is a PCF8575 chip. However, there is no method known
++	   to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
 +
-+	i = dma->srck; u = dma->srcu;
-+	while (u != 0) {
-+		if (i == HIFN_D_SRC_RSIZE)
-+			i = 0;
-+		if (dma->srcr[i].l & __cpu_to_le32(HIFN_D_VALID))
-+			break;
-+		i++, u--;
-+	}
-+	dma->srck = i; dma->srcu = u;
++	/* Tell the I2C layer a new client has arrived */
++	err = i2c_attach_client(client);
++	if (err)
++		goto exit_free;
 +
-+	i = dma->cmdk; u = dma->cmdu;
-+	while (u != 0) {
-+		if (dma->cmdr[i].l & __cpu_to_le32(HIFN_D_VALID))
-+			break;
-+		if (i != HIFN_D_CMD_RSIZE)
-+			u--;
-+		if (++i == (HIFN_D_CMD_RSIZE + 1))
-+			i = 0;
-+	}
-+	dma->cmdk = i; dma->cmdu = u;
++	/* Register sysfs hooks */
++	err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group);
++	if (err)
++		goto exit_detach;
 +
-+	i = dma->dstk; u = dma->dstu;
-+	while (u != 0) {
-+		if (i == HIFN_D_DST_RSIZE)
-+			i = 0;
-+		if (dma->dstr[i].l & __cpu_to_le32(HIFN_D_VALID))
-+			break;
-+		i++, u--;
-+	}
-+	dma->dstk = i; dma->dstu = u;
++	return 0;
 +
-+	dprintk("%s: ring cleanup 2: i: %d.%d.%d.%d, u: %d.%d.%d.%d, "
-+			"k: %d.%d.%d.%d.\n",
-+			dev->name,
-+			dma->cmdi, dma->srci, dma->dsti, dma->resi,
-+			dma->cmdu, dma->srcu, dma->dstu, dma->resu,
-+			dma->cmdk, dma->srck, dma->dstk, dma->resk);
++exit_detach:
++	i2c_detach_client(client);
++exit_free:
++	kfree(data);
++exit:
++	return err;
 +}
 +
-+static void hifn_work(struct work_struct *work)
++static int pcf8575_detach_client(struct i2c_client *client)
 +{
-+	struct delayed_work *dw = container_of(work, struct delayed_work, work);
-+	struct hifn_device *dev = container_of(dw, struct hifn_device, work);
-+	unsigned long flags;
-+	int reset = 0;
-+	u32 r = 0;
-+
-+	spin_lock_irqsave(&dev->lock, flags);
-+	if (dev->active == 0) {
-+		struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+
-+		if (dma->cmdu == 0 && (dev->flags & HIFN_FLAG_CMD_BUSY)) {
-+			dev->flags &= ~HIFN_FLAG_CMD_BUSY;
-+			r |= HIFN_DMACSR_C_CTRL_DIS;
-+		}
-+		if (dma->srcu == 0 && (dev->flags & HIFN_FLAG_SRC_BUSY)) {
-+			dev->flags &= ~HIFN_FLAG_SRC_BUSY;
-+			r |= HIFN_DMACSR_S_CTRL_DIS;
-+		}
-+		if (dma->dstu == 0 && (dev->flags & HIFN_FLAG_DST_BUSY)) {
-+			dev->flags &= ~HIFN_FLAG_DST_BUSY;
-+			r |= HIFN_DMACSR_D_CTRL_DIS;
-+		}
-+		if (dma->resu == 0 && (dev->flags & HIFN_FLAG_RES_BUSY)) {
-+			dev->flags &= ~HIFN_FLAG_RES_BUSY;
-+			r |= HIFN_DMACSR_R_CTRL_DIS;
-+		}
-+		if (r)
-+			hifn_write_1(dev, HIFN_1_DMA_CSR, r);
-+	} else
-+		dev->active--;
-+
-+	if (dev->prev_success == dev->success && dev->started)
-+		reset = 1;
-+	dev->prev_success = dev->success;
-+	spin_unlock_irqrestore(&dev->lock, flags);
-+
-+	if (reset) {
-+		dprintk("%s: r: %08x, active: %d, started: %d, "
-+				"success: %lu: reset: %d.\n",
-+			dev->name, r, dev->active, dev->started,
-+			dev->success, reset);
++	int err;
 +
-+		if (++dev->reset >= 5) {
-+			dprintk("%s: really hard reset.\n", dev->name);
-+			hifn_reset_dma(dev, 1);
-+			hifn_stop_device(dev);
-+			hifn_start_device(dev);
-+			dev->reset = 0;
-+		}
++	sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group);
 +
-+		spin_lock_irqsave(&dev->lock, flags);
-+		hifn_check_for_completion(dev, -EBUSY);
-+		hifn_clear_rings(dev);
-+		dev->started = 0;
-+		spin_unlock_irqrestore(&dev->lock, flags);
-+	}
++	err = i2c_detach_client(client);
++	if (err)
++		return err;
 +
-+	schedule_delayed_work(&dev->work, HZ);
++	kfree(i2c_get_clientdata(client));
++	return 0;
 +}
 +
-+static irqreturn_t hifn_interrupt(int irq, void *data)
++static int __init pcf8575_init(void)
 +{
-+	struct hifn_device *dev = (struct hifn_device *)data;
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	u32 dmacsr, restart;
-+
-+	dmacsr = hifn_read_1(dev, HIFN_1_DMA_CSR);
-+
-+	dprintk("%s: 1 dmacsr: %08x, dmareg: %08x, res: %08x [%d], "
-+			"i: %d.%d.%d.%d, u: %d.%d.%d.%d.\n",
-+		dev->name, dmacsr, dev->dmareg, dmacsr & dev->dmareg, dma->cmdi,
-+		dma->cmdu, dma->srcu, dma->dstu, dma->resu,
-+		dma->cmdi, dma->srci, dma->dsti, dma->resi);
-+
-+	if ((dmacsr & dev->dmareg) == 0)
-+		return IRQ_NONE;
-+
-+	hifn_write_1(dev, HIFN_1_DMA_CSR, dmacsr & dev->dmareg);
-+
-+	if (dmacsr & HIFN_DMACSR_ENGINE)
-+		hifn_write_0(dev, HIFN_0_PUISR, hifn_read_0(dev, HIFN_0_PUISR));
-+	if (dmacsr & HIFN_DMACSR_PUBDONE)
-+		hifn_write_1(dev, HIFN_1_PUB_STATUS,
-+			hifn_read_1(dev, HIFN_1_PUB_STATUS) | HIFN_PUBSTS_DONE);
-+
-+	restart = dmacsr & (HIFN_DMACSR_R_OVER | HIFN_DMACSR_D_OVER);
-+	if (restart) {
-+		u32 puisr = hifn_read_0(dev, HIFN_0_PUISR);
-+
-+		if (printk_ratelimit())
-+			printk("%s: overflow: r: %d, d: %d, puisr: %08x, d: %u.\n",
-+				dev->name, !!(dmacsr & HIFN_DMACSR_R_OVER),
-+				!!(dmacsr & HIFN_DMACSR_D_OVER),
-+				puisr, !!(puisr & HIFN_PUISR_DSTOVER));
-+		if (!!(puisr & HIFN_PUISR_DSTOVER))
-+			hifn_write_0(dev, HIFN_0_PUISR, HIFN_PUISR_DSTOVER);
-+		hifn_write_1(dev, HIFN_1_DMA_CSR, dmacsr & (HIFN_DMACSR_R_OVER |
-+					HIFN_DMACSR_D_OVER));
-+	}
-+
-+	restart = dmacsr & (HIFN_DMACSR_C_ABORT | HIFN_DMACSR_S_ABORT |
-+			HIFN_DMACSR_D_ABORT | HIFN_DMACSR_R_ABORT);
-+	if (restart) {
-+		if (printk_ratelimit())
-+			printk("%s: abort: c: %d, s: %d, d: %d, r: %d.\n",
-+				dev->name, !!(dmacsr & HIFN_DMACSR_C_ABORT),
-+				!!(dmacsr & HIFN_DMACSR_S_ABORT),
-+				!!(dmacsr & HIFN_DMACSR_D_ABORT),
-+				!!(dmacsr & HIFN_DMACSR_R_ABORT));
-+		hifn_reset_dma(dev, 1);
-+		hifn_init_dma(dev);
-+		hifn_init_registers(dev);
-+	}
-+
-+	if ((dmacsr & HIFN_DMACSR_C_WAIT) && (dma->cmdu == 0)) {
-+		dprintk("%s: wait on command.\n", dev->name);
-+		dev->dmareg &= ~(HIFN_DMAIER_C_WAIT);
-+		hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg);
-+	}
-+
-+	tasklet_schedule(&dev->tasklet);
-+	hifn_clear_rings(dev);
-+
-+	return IRQ_HANDLED;
++	return i2c_add_driver(&pcf8575_driver);
 +}
 +
-+static void hifn_flush(struct hifn_device *dev)
++static void __exit pcf8575_exit(void)
 +{
-+	unsigned long flags;
-+	struct crypto_async_request *async_req;
-+	struct hifn_context *ctx;
-+	struct ablkcipher_request *req;
-+	struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt;
-+	int i;
-+
-+	spin_lock_irqsave(&dev->lock, flags);
-+	for (i=0; i<HIFN_D_RES_RSIZE; ++i) {
-+		struct hifn_desc *d = &dma->resr[i];
++	i2c_del_driver(&pcf8575_driver);
++}
 +
-+		if (dev->sa[i]) {
-+			hifn_process_ready(dev->sa[i],
-+				(d->l & __cpu_to_le32(HIFN_D_VALID))?-ENODEV:0);
-+		}
-+	}
++MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>, "
++	      "Bart Van Assche <bart.vanassche at gmail.com>");
++MODULE_DESCRIPTION("pcf8575 driver");
++MODULE_LICENSE("GPL");
 +
-+	while ((async_req = crypto_dequeue_request(&dev->queue))) {
-+		ctx = crypto_tfm_ctx(async_req->tfm);
-+		req = container_of(async_req, struct ablkcipher_request, base);
++module_init(pcf8575_init);
++module_exit(pcf8575_exit);
+diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
+index 4dc3637..865f440 100644
+--- a/drivers/i2c/chips/pcf8591.c
++++ b/drivers/i2c/chips/pcf8591.c
+@@ -27,7 +27,7 @@
+ #include <linux/mutex.h>
+ 
+ /* Addresses to scan */
+-static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
++static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+ 					0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
+ 
+ /* Insmod parameters */
+diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
+index e320994..4154a91 100644
+--- a/drivers/i2c/chips/tps65010.c
++++ b/drivers/i2c/chips/tps65010.c
+@@ -31,7 +31,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/mutex.h>
+ 
+-#include <asm/arch/tps65010.h>
++#include <linux/i2c/tps65010.h>
+ 
+ /*-------------------------------------------------------------------------*/
+ 
+diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
+index 3de4b19..a10fd27 100644
+--- a/drivers/i2c/chips/tsl2550.c
++++ b/drivers/i2c/chips/tsl2550.c
+@@ -432,11 +432,32 @@ static int __devexit tsl2550_remove(struct i2c_client *client)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_PM
 +
-+		hifn_process_ready(req, -ENODEV);
-+	}
-+	spin_unlock_irqrestore(&dev->lock, flags);
++static int tsl2550_suspend(struct i2c_client *client, pm_message_t mesg)
++{
++	return tsl2550_set_power_state(client, 0);
 +}
 +
-+static int hifn_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
-+		unsigned int len)
++static int tsl2550_resume(struct i2c_client *client)
 +{
-+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
-+	struct hifn_context *ctx = crypto_tfm_ctx(tfm);
-+	struct hifn_device *dev = ctx->dev;
++	return tsl2550_set_power_state(client, 1);
++}
 +
-+	if (len > HIFN_MAX_CRYPT_KEY_LENGTH) {
-+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
-+		return -1;
-+	}
++#else
 +
-+	if (len == HIFN_DES_KEY_LENGTH) {
-+		u32 tmp[DES_EXPKEY_WORDS];
-+		int ret = des_ekey(tmp, key);
-+		
-+		if (unlikely(ret == 0) && (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
-+			tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
-+			return -EINVAL;
-+		}
-+	}
++#define tsl2550_suspend		NULL
++#define tsl2550_resume		NULL
 +
-+	dev->flags &= ~HIFN_FLAG_OLD_KEY;
++#endif /* CONFIG_PM */
 +
-+	memcpy(ctx->key, key, len);
-+	ctx->keysize = len;
+ static struct i2c_driver tsl2550_driver = {
+ 	.driver = {
+ 		.name	= TSL2550_DRV_NAME,
+ 		.owner	= THIS_MODULE,
+ 	},
++	.suspend = tsl2550_suspend,
++	.resume	= tsl2550_resume,
+ 	.probe	= tsl2550_probe,
+ 	.remove	= __devexit_p(tsl2550_remove),
+ };
+diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
+index b5e13e4..96da22e 100644
+--- a/drivers/i2c/i2c-core.c
++++ b/drivers/i2c/i2c-core.c
+@@ -33,14 +33,15 @@
+ #include <linux/platform_device.h>
+ #include <linux/mutex.h>
+ #include <linux/completion.h>
++#include <linux/hardirq.h>
++#include <linux/irqflags.h>
+ #include <asm/uaccess.h>
++#include <asm/semaphore.h>
+ 
+ #include "i2c-core.h"
+ 
+ 
+-static LIST_HEAD(adapters);
+-static LIST_HEAD(drivers);
+-static DEFINE_MUTEX(core_lists);
++static DEFINE_MUTEX(core_lock);
+ static DEFINE_IDR(i2c_adapter_idr);
+ 
+ #define is_newstyle_driver(d) ((d)->probe || (d)->remove)
+@@ -198,6 +199,25 @@ static struct bus_type i2c_bus_type = {
+ 	.resume		= i2c_device_resume,
+ };
+ 
 +
-+	return 0;
++/**
++ * i2c_verify_client - return parameter as i2c_client, or NULL
++ * @dev: device, probably from some driver model iterator
++ *
++ * When traversing the driver model tree, perhaps using driver model
++ * iterators like @device_for_each_child(), you can't assume very much
++ * about the nodes you find.  Use this function to avoid oopses caused
++ * by wrongly treating some non-I2C device as an i2c_client.
++ */
++struct i2c_client *i2c_verify_client(struct device *dev)
++{
++	return (dev->bus == &i2c_bus_type)
++			? to_i2c_client(dev)
++			: NULL;
 +}
++EXPORT_SYMBOL(i2c_verify_client);
 +
-+static int hifn_handle_req(struct ablkcipher_request *req)
-+{
-+	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
-+	struct hifn_device *dev = ctx->dev;
-+	int err = -EAGAIN;
 +
-+	if (dev->started + DIV_ROUND_UP(req->nbytes, PAGE_SIZE) <= HIFN_QUEUE_LENGTH)
-+		err = hifn_setup_session(req);
+ /**
+  * i2c_new_device - instantiate an i2c device for use with a new style driver
+  * @adap: the adapter managing the device
+@@ -276,6 +296,50 @@ void i2c_unregister_device(struct i2c_client *client)
+ EXPORT_SYMBOL_GPL(i2c_unregister_device);
+ 
+ 
++static int dummy_nop(struct i2c_client *client)
++{
++	return 0;
++}
 +
-+	if (err == -EAGAIN) {
-+		unsigned long flags;
++static struct i2c_driver dummy_driver = {
++	.driver.name	= "dummy",
++	.probe		= dummy_nop,
++	.remove		= dummy_nop,
++};
 +
-+		spin_lock_irqsave(&dev->lock, flags);
-+		err = ablkcipher_enqueue_request(&dev->queue, req);
-+		spin_unlock_irqrestore(&dev->lock, flags);
-+	}
++/**
++ * i2c_new_dummy - return a new i2c device bound to a dummy driver
++ * @adapter: the adapter managing the device
++ * @address: seven bit address to be used
++ * @type: optional label used for i2c_client.name
++ * Context: can sleep
++ *
++ * This returns an I2C client bound to the "dummy" driver, intended for use
++ * with devices that consume multiple addresses.  Examples of such chips
++ * include various EEPROMS (like 24c04 and 24c08 models).
++ *
++ * These dummy devices have two main uses.  First, most I2C and SMBus calls
++ * except i2c_transfer() need a client handle; the dummy will be that handle.
++ * And second, this prevents the specified address from being bound to a
++ * different driver.
++ *
++ * This returns the new i2c client, which should be saved for later use with
++ * i2c_unregister_device(); or NULL to indicate an error.
++ */
++struct i2c_client *
++i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type)
++{
++	struct i2c_board_info info = {
++		.driver_name	= "dummy",
++		.addr		= address,
++	};
 +
-+	return err;
++	if (type)
++		strlcpy(info.type, type, sizeof info.type);
++	return i2c_new_device(adapter, &info);
 +}
++EXPORT_SYMBOL_GPL(i2c_new_dummy);
 +
-+static int hifn_setup_crypto_req(struct ablkcipher_request *req, u8 op,
-+		u8 type, u8 mode)
+ /* ------------------------------------------------------------------------- */
+ 
+ /* I2C bus adapters -- one roots each I2C or SMBUS segment */
+@@ -320,18 +384,27 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
+ 	mutex_unlock(&__i2c_board_lock);
+ }
+ 
++static int i2c_do_add_adapter(struct device_driver *d, void *data)
 +{
-+	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
-+	unsigned ivsize;
-+
-+	ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
-+
-+	if (req->info && mode != ACRYPTO_MODE_ECB) {
-+		if (type == ACRYPTO_TYPE_AES_128)
-+			ivsize = HIFN_AES_IV_LENGTH;
-+		else if (type == ACRYPTO_TYPE_DES)
-+			ivsize = HIFN_DES_KEY_LENGTH;
-+		else if (type == ACRYPTO_TYPE_3DES)
-+			ivsize = HIFN_3DES_KEY_LENGTH;
-+	}
++	struct i2c_driver *driver = to_i2c_driver(d);
++	struct i2c_adapter *adap = data;
 +
-+	if (ctx->keysize != 16 && type == ACRYPTO_TYPE_AES_128) {
-+		if (ctx->keysize == 24)
-+			type = ACRYPTO_TYPE_AES_192;
-+		else if (ctx->keysize == 32)
-+			type = ACRYPTO_TYPE_AES_256;
++	if (driver->attach_adapter) {
++		/* We ignore the return code; if it fails, too bad */
++		driver->attach_adapter(adap);
 +	}
-+
-+	ctx->op = op;
-+	ctx->mode = mode;
-+	ctx->type = type;
-+	ctx->iv = req->info;
-+	ctx->ivsize = ivsize;
-+
-+	/*
-+	 * HEAVY TODO: needs to kick Herbert XU to write documentation.
-+	 * HEAVY TODO: needs to kick Herbert XU to write documentation.
-+	 * HEAVY TODO: needs to kick Herbert XU to write documentation.
-+	 */
-+
-+	return hifn_handle_req(req);
++	return 0;
 +}
 +
-+static int hifn_process_queue(struct hifn_device *dev)
+ static int i2c_register_adapter(struct i2c_adapter *adap)
+ {
+-	int res = 0;
+-	struct list_head   *item;
+-	struct i2c_driver  *driver;
++	int res = 0, dummy;
+ 
+ 	mutex_init(&adap->bus_lock);
+ 	mutex_init(&adap->clist_lock);
+ 	INIT_LIST_HEAD(&adap->clients);
+ 
+-	mutex_lock(&core_lists);
+-	list_add_tail(&adap->list, &adapters);
++	mutex_lock(&core_lock);
+ 
+ 	/* Add the adapter to the driver core.
+ 	 * If the parent pointer is not set up,
+@@ -356,19 +429,14 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
+ 		i2c_scan_static_board_info(adap);
+ 
+ 	/* let legacy drivers scan this bus for matching devices */
+-	list_for_each(item,&drivers) {
+-		driver = list_entry(item, struct i2c_driver, list);
+-		if (driver->attach_adapter)
+-			/* We ignore the return code; if it fails, too bad */
+-			driver->attach_adapter(adap);
+-	}
++	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
++				 i2c_do_add_adapter);
+ 
+ out_unlock:
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ 	return res;
+ 
+ out_list:
+-	list_del(&adap->list);
+ 	idr_remove(&i2c_adapter_idr, adap->nr);
+ 	goto out_unlock;
+ }
+@@ -394,11 +462,11 @@ retry:
+ 	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+ 		return -ENOMEM;
+ 
+-	mutex_lock(&core_lists);
++	mutex_lock(&core_lock);
+ 	/* "above" here means "above or equal to", sigh */
+ 	res = idr_get_new_above(&i2c_adapter_idr, adapter,
+ 				__i2c_first_dynamic_bus_num, &id);
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ 
+ 	if (res < 0) {
+ 		if (res == -EAGAIN)
+@@ -443,7 +511,7 @@ retry:
+ 	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
+ 		return -ENOMEM;
+ 
+-	mutex_lock(&core_lists);
++	mutex_lock(&core_lock);
+ 	/* "above" here means "above or equal to", sigh;
+ 	 * we need the "equal to" result to force the result
+ 	 */
+@@ -452,7 +520,7 @@ retry:
+ 		status = -EBUSY;
+ 		idr_remove(&i2c_adapter_idr, id);
+ 	}
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ 	if (status == -EAGAIN)
+ 		goto retry;
+ 
+@@ -462,6 +530,21 @@ retry:
+ }
+ EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
+ 
++static int i2c_do_del_adapter(struct device_driver *d, void *data)
 +{
-+	struct crypto_async_request *async_req;
-+	struct hifn_context *ctx;
-+	struct ablkcipher_request *req;
-+	unsigned long flags;
-+	int err = 0;
-+
-+	while (dev->started < HIFN_QUEUE_LENGTH) {
-+		spin_lock_irqsave(&dev->lock, flags);
-+		async_req = crypto_dequeue_request(&dev->queue);
-+		spin_unlock_irqrestore(&dev->lock, flags);
-+
-+		if (!async_req)
-+			break;
-+
-+		ctx = crypto_tfm_ctx(async_req->tfm);
-+		req = container_of(async_req, struct ablkcipher_request, base);
-+
-+		err = hifn_handle_req(req);
-+		if (err)
-+			break;
-+	}
++	struct i2c_driver *driver = to_i2c_driver(d);
++	struct i2c_adapter *adapter = data;
++	int res;
 +
-+	return err;
++	if (!driver->detach_adapter)
++		return 0;
++	res = driver->detach_adapter(adapter);
++	if (res)
++		dev_err(&adapter->dev, "detach_adapter failed (%d) "
++			"for driver [%s]\n", res, driver->driver.name);
++	return res;
 +}
 +
-+static int hifn_setup_crypto(struct ablkcipher_request *req, u8 op,
-+		u8 type, u8 mode)
-+{
-+	int err;
-+	struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm);
-+	struct hifn_device *dev = ctx->dev;
-+
-+	err = hifn_setup_crypto_req(req, op, type, mode);
-+	if (err)
-+		return err;
+ /**
+  * i2c_del_adapter - unregister I2C adapter
+  * @adap: the adapter being unregistered
+@@ -473,35 +556,24 @@ EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
+ int i2c_del_adapter(struct i2c_adapter *adap)
+ {
+ 	struct list_head  *item, *_n;
+-	struct i2c_adapter *adap_from_list;
+-	struct i2c_driver *driver;
+ 	struct i2c_client *client;
+ 	int res = 0;
+ 
+-	mutex_lock(&core_lists);
++	mutex_lock(&core_lock);
+ 
+ 	/* First make sure that this adapter was ever added */
+-	list_for_each_entry(adap_from_list, &adapters, list) {
+-		if (adap_from_list == adap)
+-			break;
+-	}
+-	if (adap_from_list != adap) {
++	if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
+ 		pr_debug("i2c-core: attempting to delete unregistered "
+ 			 "adapter [%s]\n", adap->name);
+ 		res = -EINVAL;
+ 		goto out_unlock;
+ 	}
+ 
+-	list_for_each(item,&drivers) {
+-		driver = list_entry(item, struct i2c_driver, list);
+-		if (driver->detach_adapter)
+-			if ((res = driver->detach_adapter(adap))) {
+-				dev_err(&adap->dev, "detach_adapter failed "
+-					"for driver [%s]\n",
+-					driver->driver.name);
+-				goto out_unlock;
+-			}
+-	}
++	/* Tell drivers about this removal */
++	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
++			       i2c_do_del_adapter);
++	if (res)
++		goto out_unlock;
+ 
+ 	/* detach any active clients. This must be done first, because
+ 	 * it can fail; in which case we give up. */
+@@ -529,7 +601,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
+ 	/* clean up the sysfs representation */
+ 	init_completion(&adap->dev_released);
+ 	device_unregister(&adap->dev);
+-	list_del(&adap->list);
+ 
+ 	/* wait for sysfs to drop all references */
+ 	wait_for_completion(&adap->dev_released);
+@@ -540,7 +611,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
+ 	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
+ 
+  out_unlock:
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ 	return res;
+ }
+ EXPORT_SYMBOL(i2c_del_adapter);
+@@ -583,21 +654,23 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
+ 	if (res)
+ 		return res;
+ 
+-	mutex_lock(&core_lists);
++	mutex_lock(&core_lock);
+ 
+-	list_add_tail(&driver->list,&drivers);
+ 	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
+ 
+ 	/* legacy drivers scan i2c busses directly */
+ 	if (driver->attach_adapter) {
+ 		struct i2c_adapter *adapter;
+ 
+-		list_for_each_entry(adapter, &adapters, list) {
++		down(&i2c_adapter_class.sem);
++		list_for_each_entry(adapter, &i2c_adapter_class.devices,
++				    dev.node) {
+ 			driver->attach_adapter(adapter);
+ 		}
++		up(&i2c_adapter_class.sem);
+ 	}
+ 
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ 	return 0;
+ }
+ EXPORT_SYMBOL(i2c_register_driver);
+@@ -609,11 +682,11 @@ EXPORT_SYMBOL(i2c_register_driver);
+  */
+ void i2c_del_driver(struct i2c_driver *driver)
+ {
+-	struct list_head   *item1, *item2, *_n;
++	struct list_head   *item2, *_n;
+ 	struct i2c_client  *client;
+ 	struct i2c_adapter *adap;
+ 
+-	mutex_lock(&core_lists);
++	mutex_lock(&core_lock);
+ 
+ 	/* new-style driver? */
+ 	if (is_newstyle_driver(driver))
+@@ -623,8 +696,8 @@ void i2c_del_driver(struct i2c_driver *driver)
+ 	 * attached. If so, detach them to be able to kill the driver
+ 	 * afterwards.
+ 	 */
+-	list_for_each(item1,&adapters) {
+-		adap = list_entry(item1, struct i2c_adapter, list);
++	down(&i2c_adapter_class.sem);
++	list_for_each_entry(adap, &i2c_adapter_class.devices, dev.node) {
+ 		if (driver->detach_adapter) {
+ 			if (driver->detach_adapter(adap)) {
+ 				dev_err(&adap->dev, "detach_adapter failed "
+@@ -648,40 +721,31 @@ void i2c_del_driver(struct i2c_driver *driver)
+ 			}
+ 		}
+ 	}
++	up(&i2c_adapter_class.sem);
+ 
+  unregister:
+ 	driver_unregister(&driver->driver);
+-	list_del(&driver->list);
+ 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
+ 
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ }
+ EXPORT_SYMBOL(i2c_del_driver);
+ 
+ /* ------------------------------------------------------------------------- */
+ 
+-static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
++static int __i2c_check_addr(struct device *dev, void *addrp)
+ {
+-	struct list_head   *item;
+-	struct i2c_client  *client;
++	struct i2c_client	*client = i2c_verify_client(dev);
++	int			addr = *(int *)addrp;
+ 
+-	list_for_each(item,&adapter->clients) {
+-		client = list_entry(item, struct i2c_client, list);
+-		if (client->addr == addr)
+-			return -EBUSY;
+-	}
++	if (client && client->addr == addr)
++		return -EBUSY;
+ 	return 0;
+ }
+ 
+ static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
+ {
+-	int rval;
+-
+-	mutex_lock(&adapter->clist_lock);
+-	rval = __i2c_check_addr(adapter, addr);
+-	mutex_unlock(&adapter->clist_lock);
+-
+-	return rval;
++	return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
+ }
+ 
+ int i2c_attach_client(struct i2c_client *client)
+@@ -689,15 +753,6 @@ int i2c_attach_client(struct i2c_client *client)
+ 	struct i2c_adapter *adapter = client->adapter;
+ 	int res = 0;
+ 
+-	mutex_lock(&adapter->clist_lock);
+-	if (__i2c_check_addr(client->adapter, client->addr)) {
+-		res = -EBUSY;
+-		goto out_unlock;
+-	}
+-	list_add_tail(&client->list,&adapter->clients);
+-
+-	client->usage_count = 0;
+-
+ 	client->dev.parent = &client->adapter->dev;
+ 	client->dev.bus = &i2c_bus_type;
+ 
+@@ -712,13 +767,17 @@ int i2c_attach_client(struct i2c_client *client)
+ 
+ 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
+ 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
+-	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+-		client->name, client->dev.bus_id);
+ 	res = device_register(&client->dev);
+ 	if (res)
+-		goto out_list;
++		goto out_err;
 +
-+	if (dev->started < HIFN_QUEUE_LENGTH &&	dev->queue.qlen)
-+		err = hifn_process_queue(dev);
++	mutex_lock(&adapter->clist_lock);
++	list_add_tail(&client->list, &adapter->clients);
+ 	mutex_unlock(&adapter->clist_lock);
+ 
++	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
++		client->name, client->dev.bus_id);
 +
-+	return err;
-+}
+ 	if (adapter->client_register)  {
+ 		if (adapter->client_register(client)) {
+ 			dev_dbg(&adapter->dev, "client_register "
+@@ -729,12 +788,9 @@ int i2c_attach_client(struct i2c_client *client)
+ 
+ 	return 0;
+ 
+-out_list:
+-	list_del(&client->list);
++out_err:
+ 	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
+ 		"(%d)\n", client->name, client->addr, res);
+-out_unlock:
+-	mutex_unlock(&adapter->clist_lock);
+ 	return res;
+ }
+ EXPORT_SYMBOL(i2c_attach_client);
+@@ -744,12 +800,6 @@ int i2c_detach_client(struct i2c_client *client)
+ 	struct i2c_adapter *adapter = client->adapter;
+ 	int res = 0;
+ 
+-	if (client->usage_count > 0) {
+-		dev_warn(&client->dev, "Client [%s] still busy, "
+-			 "can't detach\n", client->name);
+-		return -EBUSY;
+-	}
+-
+ 	if (adapter->client_unregister)  {
+ 		res = adapter->client_unregister(client);
+ 		if (res) {
+@@ -762,9 +812,10 @@ int i2c_detach_client(struct i2c_client *client)
+ 
+ 	mutex_lock(&adapter->clist_lock);
+ 	list_del(&client->list);
++	mutex_unlock(&adapter->clist_lock);
 +
-+/*
-+ * AES ecryption functions.
+ 	init_completion(&client->released);
+ 	device_unregister(&client->dev);
+-	mutex_unlock(&adapter->clist_lock);
+ 	wait_for_completion(&client->released);
+ 
+  out:
+@@ -772,72 +823,58 @@ int i2c_detach_client(struct i2c_client *client)
+ }
+ EXPORT_SYMBOL(i2c_detach_client);
+ 
+-static int i2c_inc_use_client(struct i2c_client *client)
++/**
++ * i2c_use_client - increments the reference count of the i2c client structure
++ * @client: the client being referenced
++ *
++ * Each live reference to a client should be refcounted. The driver model does
++ * that automatically as part of driver binding, so that most drivers don't
++ * need to do this explicitly: they hold a reference until they're unbound
++ * from the device.
++ *
++ * A pointer to the client with the incremented reference counter is returned.
 + */
-+static inline int hifn_encrypt_aes_ecb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_ECB);
-+}
-+static inline int hifn_encrypt_aes_cbc(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CBC);
-+}
-+static inline int hifn_encrypt_aes_cfb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CFB);
-+}
-+static inline int hifn_encrypt_aes_ofb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_OFB);
-+}
-+
-+/*
-+ * AES decryption functions.
++struct i2c_client *i2c_use_client(struct i2c_client *client)
+ {
+-
+-	if (!try_module_get(client->driver->driver.owner))
+-		return -ENODEV;
+-	if (!try_module_get(client->adapter->owner)) {
+-		module_put(client->driver->driver.owner);
+-		return -ENODEV;
+-	}
+-
+-	return 0;
++	get_device(&client->dev);
++	return client;
+ }
++EXPORT_SYMBOL(i2c_use_client);
+ 
+-static void i2c_dec_use_client(struct i2c_client *client)
++/**
++ * i2c_release_client - release a use of the i2c client structure
++ * @client: the client being no longer referenced
++ *
++ * Must be called when a user of a client is finished with it.
 + */
-+static inline int hifn_decrypt_aes_ecb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_ECB);
-+}
-+static inline int hifn_decrypt_aes_cbc(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CBC);
-+}
-+static inline int hifn_decrypt_aes_cfb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_CFB);
-+}
-+static inline int hifn_decrypt_aes_ofb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_AES_128, ACRYPTO_MODE_OFB);
-+}
++void i2c_release_client(struct i2c_client *client)
+ {
+-	module_put(client->driver->driver.owner);
+-	module_put(client->adapter->owner);
++	put_device(&client->dev);
+ }
++EXPORT_SYMBOL(i2c_release_client);
+ 
+-int i2c_use_client(struct i2c_client *client)
+-{
+-	int ret;
+-
+-	ret = i2c_inc_use_client(client);
+-	if (ret)
+-		return ret;
+-
+-	client->usage_count++;
+-
+-	return 0;
+-}
+-EXPORT_SYMBOL(i2c_use_client);
++struct i2c_cmd_arg {
++	unsigned	cmd;
++	void		*arg;
++};
+ 
+-int i2c_release_client(struct i2c_client *client)
++static int i2c_cmd(struct device *dev, void *_arg)
+ {
+-	if (!client->usage_count) {
+-		pr_debug("i2c-core: %s used one too many times\n",
+-			 __FUNCTION__);
+-		return -EPERM;
+-	}
+-
+-	client->usage_count--;
+-	i2c_dec_use_client(client);
++	struct i2c_client	*client = i2c_verify_client(dev);
++	struct i2c_cmd_arg	*arg = _arg;
+ 
++	if (client && client->driver && client->driver->command)
++		client->driver->command(client, arg->cmd, arg->arg);
+ 	return 0;
+ }
+-EXPORT_SYMBOL(i2c_release_client);
+ 
+ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
+ {
+-	struct list_head  *item;
+-	struct i2c_client *client;
++	struct i2c_cmd_arg	cmd_arg;
+ 
+-	mutex_lock(&adap->clist_lock);
+-	list_for_each(item,&adap->clients) {
+-		client = list_entry(item, struct i2c_client, list);
+-		if (!try_module_get(client->driver->driver.owner))
+-			continue;
+-		if (NULL != client->driver->command) {
+-			mutex_unlock(&adap->clist_lock);
+-			client->driver->command(client,cmd,arg);
+-			mutex_lock(&adap->clist_lock);
+-		}
+-		module_put(client->driver->driver.owner);
+-       }
+-       mutex_unlock(&adap->clist_lock);
++	cmd_arg.cmd = cmd;
++	cmd_arg.arg = arg;
++	device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd);
+ }
+ EXPORT_SYMBOL(i2c_clients_command);
+ 
+@@ -848,11 +885,24 @@ static int __init i2c_init(void)
+ 	retval = bus_register(&i2c_bus_type);
+ 	if (retval)
+ 		return retval;
+-	return class_register(&i2c_adapter_class);
++	retval = class_register(&i2c_adapter_class);
++	if (retval)
++		goto bus_err;
++	retval = i2c_add_driver(&dummy_driver);
++	if (retval)
++		goto class_err;
++	return 0;
 +
-+/*
-+ * DES ecryption functions.
-+ */
-+static inline int hifn_encrypt_des_ecb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_ECB);
-+}
-+static inline int hifn_encrypt_des_cbc(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CBC);
-+}
-+static inline int hifn_encrypt_des_cfb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CFB);
-+}
-+static inline int hifn_encrypt_des_ofb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_OFB);
-+}
++class_err:
++	class_unregister(&i2c_adapter_class);
++bus_err:
++	bus_unregister(&i2c_bus_type);
++	return retval;
+ }
+ 
+ static void __exit i2c_exit(void)
+ {
++	i2c_del_driver(&dummy_driver);
+ 	class_unregister(&i2c_adapter_class);
+ 	bus_unregister(&i2c_bus_type);
+ }
+@@ -879,7 +929,15 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
+ 		}
+ #endif
+ 
+-		mutex_lock_nested(&adap->bus_lock, adap->level);
++		if (in_atomic() || irqs_disabled()) {
++			ret = mutex_trylock(&adap->bus_lock);
++			if (!ret)
++				/* I2C activity is ongoing. */
++				return -EAGAIN;
++		} else {
++			mutex_lock_nested(&adap->bus_lock, adap->level);
++		}
 +
-+/*
-+ * DES decryption functions.
-+ */
-+static inline int hifn_decrypt_des_ecb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_ECB);
-+}
-+static inline int hifn_decrypt_des_cbc(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CBC);
-+}
-+static inline int hifn_decrypt_des_cfb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_CFB);
-+}
-+static inline int hifn_decrypt_des_ofb(struct ablkcipher_request *req)
+ 		ret = adap->algo->master_xfer(adap,msgs,num);
+ 		mutex_unlock(&adap->bus_lock);
+ 
+@@ -978,7 +1036,7 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
+ }
+ 
+ int i2c_probe(struct i2c_adapter *adapter,
+-	      struct i2c_client_address_data *address_data,
++	      const struct i2c_client_address_data *address_data,
+ 	      int (*found_proc) (struct i2c_adapter *, int, int))
+ {
+ 	int i, err;
+@@ -987,7 +1045,7 @@ int i2c_probe(struct i2c_adapter *adapter,
+ 	/* Force entries are done first, and are not affected by ignore
+ 	   entries */
+ 	if (address_data->forces) {
+-		unsigned short **forces = address_data->forces;
++		const unsigned short * const *forces = address_data->forces;
+ 		int kind;
+ 
+ 		for (kind = 0; forces[kind]; kind++) {
+@@ -1085,7 +1143,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
+ 		return NULL;
+ 	}
+ 
+-	mutex_lock(&adap->clist_lock);
+ 	for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
+ 		/* Check address validity */
+ 		if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
+@@ -1095,7 +1152,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,
+ 		}
+ 
+ 		/* Check address availability */
+-		if (__i2c_check_addr(adap, addr_list[i])) {
++		if (i2c_check_addr(adap, addr_list[i])) {
+ 			dev_dbg(&adap->dev, "Address 0x%02x already in "
+ 				"use, not probing\n", addr_list[i]);
+ 			continue;
+@@ -1123,7 +1180,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
+ 				break;
+ 		}
+ 	}
+-	mutex_unlock(&adap->clist_lock);
+ 
+ 	if (addr_list[i] == I2C_CLIENT_END) {
+ 		dev_dbg(&adap->dev, "Probing failed, no device found\n");
+@@ -1139,12 +1195,12 @@ struct i2c_adapter* i2c_get_adapter(int id)
+ {
+ 	struct i2c_adapter *adapter;
+ 
+-	mutex_lock(&core_lists);
++	mutex_lock(&core_lock);
+ 	adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+ 	if (adapter && !try_module_get(adapter->owner))
+ 		adapter = NULL;
+ 
+-	mutex_unlock(&core_lists);
++	mutex_unlock(&core_lock);
+ 	return adapter;
+ }
+ EXPORT_SYMBOL(i2c_get_adapter);
+diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
+index df540d5..393e679 100644
+--- a/drivers/i2c/i2c-dev.c
++++ b/drivers/i2c/i2c-dev.c
+@@ -182,27 +182,22 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
+ 	return ret;
+ }
+ 
++static int i2cdev_check(struct device *dev, void *addrp)
 +{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_DES, ACRYPTO_MODE_OFB);
-+}
++	struct i2c_client *client = i2c_verify_client(dev);
 +
-+/*
-+ * 3DES ecryption functions.
-+ */
-+static inline int hifn_encrypt_3des_ecb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_ECB);
-+}
-+static inline int hifn_encrypt_3des_cbc(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CBC);
-+}
-+static inline int hifn_encrypt_3des_cfb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CFB);
-+}
-+static inline int hifn_encrypt_3des_ofb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_ENCRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_OFB);
-+}
++	if (!client || client->addr != *(unsigned int *)addrp)
++		return 0;
 +
-+/*
-+ * 3DES decryption functions.
-+ */
-+static inline int hifn_decrypt_3des_ecb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_ECB);
-+}
-+static inline int hifn_decrypt_3des_cbc(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CBC);
-+}
-+static inline int hifn_decrypt_3des_cfb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_CFB);
-+}
-+static inline int hifn_decrypt_3des_ofb(struct ablkcipher_request *req)
-+{
-+	return hifn_setup_crypto(req, ACRYPTO_OP_DECRYPT,
-+			ACRYPTO_TYPE_3DES, ACRYPTO_MODE_OFB);
++	return dev->driver ? -EBUSY : 0;
 +}
 +
-+struct hifn_alg_template
-+{
-+	char name[CRYPTO_MAX_ALG_NAME];
-+	char drv_name[CRYPTO_MAX_ALG_NAME];
-+	unsigned int bsize;
-+	struct ablkcipher_alg ablkcipher;
-+};
+ /* This address checking function differs from the one in i2c-core
+    in that it considers an address with a registered device, but no
+-   bound driver, as NOT busy. */
++   driver bound to it, as NOT busy. */
+ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+ {
+-	struct list_head *item;
+-	struct i2c_client *client;
+-	int res = 0;
+-
+-	mutex_lock(&adapter->clist_lock);
+-	list_for_each(item, &adapter->clients) {
+-		client = list_entry(item, struct i2c_client, list);
+-		if (client->addr == addr) {
+-			if (client->driver)
+-				res = -EBUSY;
+-			break;
+-		}
+-	}
+-	mutex_unlock(&adapter->clist_lock);
+-
+-	return res;
++	return device_for_each_child(&adapter->dev, &addr, i2cdev_check);
+ }
+ 
+ static int i2cdev_ioctl(struct inode *inode, struct file *file,
+diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
+index fb06555..ab8fb25 100644
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -206,9 +206,17 @@ config BLK_DEV_IDECD
+ 	  To compile this driver as a module, choose M here: the
+ 	  module will be called ide-cd.
+ 
++config BLK_DEV_IDECD_VERBOSE_ERRORS
++	bool "Verbose error logging for IDE/ATAPI CDROM driver" if EMBEDDED
++	depends on BLK_DEV_IDECD
++	default y
++	help
++	  Turn this on to have the driver print out the meanings of the
++	  ATAPI error codes.  This will use up additional 8kB of kernel-space
++	  memory, though.
 +
-+static struct hifn_alg_template hifn_alg_templates[] = {
-+	/*
-+	 * 3DES ECB, CBC, CFB and OFB modes.
-+	 */
-+	{
-+		.name = "cfb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_3des_cfb,
-+			.decrypt	=	hifn_decrypt_3des_cfb,
-+		},
-+	},
-+	{
-+		.name = "ofb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_3des_ofb,
-+			.decrypt	=	hifn_decrypt_3des_ofb,
-+		},
-+	},
-+	{
-+		.name = "cbc(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_3des_cbc,
-+			.decrypt	=	hifn_decrypt_3des_cbc,
-+		},
-+	},
-+	{
-+		.name = "ecb(des3_ede)", .drv_name = "hifn-3des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_3DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_3des_ecb,
-+			.decrypt	=	hifn_decrypt_3des_ecb,
-+		},
-+	},
+ config BLK_DEV_IDETAPE
+-	tristate "Include IDE/ATAPI TAPE support (EXPERIMENTAL)"
+-	depends on EXPERIMENTAL
++	tristate "Include IDE/ATAPI TAPE support"
+ 	help
+ 	  If you have an IDE tape drive using the ATAPI protocol, say Y.
+ 	  ATAPI is a newer protocol used by IDE tape and CD-ROM drives,
+@@ -325,7 +333,7 @@ config BLK_DEV_PLATFORM
+ 	  If unsure, say N.
+ 
+ config BLK_DEV_CMD640
+-	bool "CMD640 chipset bugfix/support"
++	tristate "CMD640 chipset bugfix/support"
+ 	depends on X86
+ 	---help---
+ 	  The CMD-Technologies CMD640 IDE chip is used on many common 486 and
+@@ -359,9 +367,8 @@ config BLK_DEV_CMD640_ENHANCED
+ 	  Otherwise say N.
+ 
+ config BLK_DEV_IDEPNP
+-	bool "PNP EIDE support"
++	tristate "PNP EIDE support"
+ 	depends on PNP
+-	select IDE_GENERIC
+ 	help
+ 	  If you have a PnP (Plug and Play) compatible EIDE card and
+ 	  would like the kernel to automatically detect and activate
+@@ -374,19 +381,20 @@ comment "PCI IDE chipsets support"
+ config BLK_DEV_IDEPCI
+ 	bool
+ 
+-config IDEPCI_SHARE_IRQ
+-	bool "Sharing PCI IDE interrupts support"
+-	depends on BLK_DEV_IDEPCI
++config IDEPCI_PCIBUS_ORDER
++	bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)"
++	depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI
++	default y
+ 	help
+-	  Some ATA/IDE chipsets have hardware support which allows for
+-	  sharing a single IRQ with other cards. To enable support for
+-	  this in the ATA/IDE driver, say Y here.
++	  Probe IDE PCI devices in the order in which they appear on the
++	  PCI bus (i.e. 00:1f.1 PCI device before 02:01.0 PCI device)
++	  instead of the order in which IDE PCI host drivers are loaded.
+ 
+-	  It is safe to say Y to this question, in most cases.
+-	  If unsure, say N.
++	  Please note that this method of assuring stable naming of
++	  IDE devices is unreliable and use other means for achieving
++	  it (i.e. udev).
+ 
+-config IDEPCI_PCIBUS_ORDER
+-	def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI
++	  If in doubt, say N.
+ 
+ # TODO: split it on per host driver config options (or module parameters)
+ config BLK_DEV_OFFBOARD
+@@ -617,8 +625,8 @@ config BLK_DEV_SC1200
+ 	tristate "National SCx200 chipset support"
+ 	select BLK_DEV_IDEDMA_PCI
+ 	help
+-	  This driver adds support for the built in IDE on the National
+-	  SCx200 series of embedded x86 "Geode" systems
++	  This driver adds support for the on-board IDE controller on the
++	  National SCx200 series of embedded x86 "Geode" systems.
+ 
+ config BLK_DEV_PIIX
+ 	tristate "Intel PIIXn chipsets support"
+@@ -707,7 +715,6 @@ config BLK_DEV_SVWKS
+ config BLK_DEV_SGIIOC4
+ 	tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
+ 	depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
+-	select IDEPCI_SHARE_IRQ
+ 	select BLK_DEV_IDEDMA_PCI
+ 	help
+ 	  This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
+@@ -794,22 +801,22 @@ config BLK_DEV_CELLEB
+ 	depends on PPC_CELLEB
+ 	select BLK_DEV_IDEDMA_PCI
+ 	help
+-	  This driver provides support for the built-in IDE controller on
++	  This driver provides support for the on-board IDE controller on
+ 	  Toshiba Cell Reference Board.
+ 	  If unsure, say Y.
+ 
+ endif
+ 
+ config BLK_DEV_IDE_PMAC
+-	bool "Builtin PowerMac IDE support"
++	tristate "PowerMac on-board IDE support"
+ 	depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
+ 	help
+-	  This driver provides support for the built-in IDE controller on
++	  This driver provides support for the on-board IDE controller on
+ 	  most of the recent Apple Power Macintoshes and PowerBooks.
+ 	  If unsure, say Y.
+ 
+ config BLK_DEV_IDE_PMAC_ATA100FIRST
+-	bool "Probe internal ATA/100 (Kauai) first"
++	bool "Probe on-board ATA/100 (Kauai) first"
+ 	depends on BLK_DEV_IDE_PMAC
+ 	help
+ 	  This option will cause the ATA/100 controller found in UniNorth2
+@@ -824,7 +831,7 @@ config BLK_DEV_IDEDMA_PMAC
+ 	depends on BLK_DEV_IDE_PMAC
+ 	select BLK_DEV_IDEDMA_PCI
+ 	help
+-	  This option allows the driver for the built-in IDE controller on
++	  This option allows the driver for the on-board IDE controller on
+ 	  Power Macintoshes and PowerBooks to use DMA (direct memory access)
+ 	  to transfer data to and from memory.  Saying Y is safe and improves
+ 	  performance.
+@@ -855,8 +862,9 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+        depends on BLK_DEV_IDE_AU1XXX
+ 
+ config IDE_ARM
+-	def_bool ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
+-	select IDE_GENERIC
++	tristate "ARM IDE support"
++	depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
++	default y
+ 
+ config BLK_DEV_IDE_ICSIDE
+ 	tristate "ICS IDE interface support"
+@@ -888,10 +896,9 @@ config BLK_DEV_IDE_BAST
+ 	  Simtec BAST or the Thorcom VR1000
+ 
+ config ETRAX_IDE
+-	bool "ETRAX IDE support"
++	tristate "ETRAX IDE support"
+ 	depends on CRIS && BROKEN
+ 	select BLK_DEV_IDEDMA
+-	select IDE_GENERIC
+ 	help
+ 	  Enables the ETRAX IDE driver.
+ 
+@@ -923,21 +930,19 @@ config ETRAX_IDE_G27_RESET
+ endchoice
+ 
+ config IDE_H8300
+-	bool "H8300 IDE support"
++	tristate "H8300 IDE support"
+ 	depends on H8300
+-	select IDE_GENERIC
+ 	default y
+ 	help
+ 	  Enables the H8300 IDE driver.
+ 
+ config BLK_DEV_GAYLE
+-	bool "Amiga Gayle IDE interface support"
++	tristate "Amiga Gayle IDE interface support"
+ 	depends on AMIGA
+-	select IDE_GENERIC
+ 	help
+ 	  This is the IDE driver for the Amiga Gayle IDE interface. It supports
+ 	  both the `A1200 style' and `A4000 style' of the Gayle IDE interface,
+-	  This includes builtin IDE interfaces on some Amiga models (A600,
++	  This includes on-board IDE interfaces on some Amiga models (A600,
+ 	  A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion
+ 	  bus (M-Tech E-Matrix 530 expansion card).
+ 	  Say Y if you have an Amiga with a Gayle IDE interface and want to use
+@@ -951,10 +956,10 @@ config BLK_DEV_IDEDOUBLER
+ 	depends on BLK_DEV_GAYLE && EXPERIMENTAL
+ 	---help---
+ 	  This driver provides support for the so-called `IDE doublers' (made
+-	  by various manufacturers, e.g. Eyetech) that can be connected to the
+-	  builtin IDE interface of some Amiga models. Using such an IDE
+-	  doubler, you can connect up to four instead of two IDE devices on
+-	  the Amiga's builtin IDE interface.
++	  by various manufacturers, e.g. Eyetech) that can be connected to
++	  the on-board IDE interface of some Amiga models. Using such an IDE
++	  doubler, you can connect up to four instead of two IDE devices to
++	  the Amiga's on-board IDE interface.
+ 
+ 	  Note that the normal Amiga Gayle IDE driver may not work correctly
+ 	  if you have an IDE doubler and don't enable this driver!
+@@ -963,55 +968,59 @@ config BLK_DEV_IDEDOUBLER
+ 	  runtime using the "ide=doubler" kernel boot parameter.
+ 
+ config BLK_DEV_BUDDHA
+-	bool "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
++	tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
+ 	depends on ZORRO && EXPERIMENTAL
+-	select IDE_GENERIC
+ 	help
+-	  This is the IDE driver for the IDE interfaces on the Buddha, 
+-	  Catweasel and X-Surf expansion boards.  It supports up to two interfaces 
+-	  on the Buddha, three on the Catweasel and two on the X-Surf.
++	  This is the IDE driver for the IDE interfaces on the Buddha, Catweasel
++	  and X-Surf expansion boards.  It supports up to two interfaces on the
++	  Buddha, three on the Catweasel and two on the X-Surf.
+ 
+ 	  Say Y if you have a Buddha or Catweasel expansion board and want to
+ 	  use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
+ 	  to one of its IDE interfaces.
+ 
+ config BLK_DEV_FALCON_IDE
+-	bool "Falcon IDE interface support"
++	tristate "Falcon IDE interface support"
+ 	depends on ATARI
+-	select IDE_GENERIC
+ 	help
+-	  This is the IDE driver for the builtin IDE interface on the Atari
++	  This is the IDE driver for the on-board IDE interface on the Atari
+ 	  Falcon. Say Y if you have a Falcon and want to use IDE devices (hard
+-	  disks, CD-ROM drives, etc.) that are connected to the builtin IDE
++	  disks, CD-ROM drives, etc.) that are connected to the on-board IDE
+ 	  interface.
+ 
+ config BLK_DEV_MAC_IDE
+-	bool "Macintosh Quadra/Powerbook IDE interface support"
++	tristate "Macintosh Quadra/Powerbook IDE interface support"
+ 	depends on MAC
+-	select IDE_GENERIC
+ 	help
+-	  This is the IDE driver for the builtin IDE interface on some m68k
++	  This is the IDE driver for the on-board IDE interface on some m68k
+ 	  Macintosh models. It supports both the `Quadra style' (used in
+ 	  Quadra/ Centris 630 and Performa 588 models) and `Powerbook style'
+ 	  (used in the Powerbook 150 and 190 models) IDE interface.
+ 
+ 	  Say Y if you have such an Macintosh model and want to use IDE
+ 	  devices (hard disks, CD-ROM drives, etc.) that are connected to the
+-	  builtin IDE interface.
++	  on-board IDE interface.
+ 
+ config BLK_DEV_Q40IDE
+-	bool "Q40/Q60 IDE interface support"
++	tristate "Q40/Q60 IDE interface support"
+ 	depends on Q40
+-	select IDE_GENERIC
+ 	help
+ 	  Enable the on-board IDE controller in the Q40/Q60.  This should
+ 	  normally be on; disable it only if you are running a custom hard
+ 	  drive subsystem through an expansion card.
+ 
++config BLK_DEV_PALMCHIP_BK3710
++	tristate "Palmchip bk3710 IDE controller support"
++	depends on ARCH_DAVINCI
++	select BLK_DEV_IDEDMA_PCI
++	help
++	  Say Y here if you want to support the onchip IDE controller on the
++	  TI DaVinci SoC
 +
-+	/*
-+	 * DES ECB, CBC, CFB and OFB modes.
-+	 */
-+	{
-+		.name = "cfb(des)", .drv_name = "hifn-des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_des_cfb,
-+			.decrypt	=	hifn_decrypt_des_cfb,
-+		},
-+	},
-+	{
-+		.name = "ofb(des)", .drv_name = "hifn-des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_des_ofb,
-+			.decrypt	=	hifn_decrypt_des_ofb,
-+		},
-+	},
-+	{
-+		.name = "cbc(des)", .drv_name = "hifn-des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_des_cbc,
-+			.decrypt	=	hifn_decrypt_des_cbc,
-+		},
-+	},
-+	{
-+		.name = "ecb(des)", .drv_name = "hifn-des", .bsize = 8,
-+		.ablkcipher = {
-+			.min_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.max_keysize	=	HIFN_DES_KEY_LENGTH,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_des_ecb,
-+			.decrypt	=	hifn_decrypt_des_ecb,
-+		},
-+	},
 +
-+	/*
-+	 * AES ECB, CBC, CFB and OFB modes.
-+	 */
-+	{
-+		.name = "ecb(aes)", .drv_name = "hifn-aes", .bsize = 16,
-+		.ablkcipher = {
-+			.min_keysize	=	AES_MIN_KEY_SIZE,
-+			.max_keysize	=	AES_MAX_KEY_SIZE,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_aes_ecb,
-+			.decrypt	=	hifn_decrypt_aes_ecb,
-+		},
-+	},
-+	{
-+		.name = "cbc(aes)", .drv_name = "hifn-aes", .bsize = 16,
-+		.ablkcipher = {
-+			.min_keysize	=	AES_MIN_KEY_SIZE,
-+			.max_keysize	=	AES_MAX_KEY_SIZE,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_aes_cbc,
-+			.decrypt	=	hifn_decrypt_aes_cbc,
-+		},
-+	},
-+	{
-+		.name = "cfb(aes)", .drv_name = "hifn-aes", .bsize = 16,
-+		.ablkcipher = {
-+			.min_keysize	=	AES_MIN_KEY_SIZE,
-+			.max_keysize	=	AES_MAX_KEY_SIZE,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_aes_cfb,
-+			.decrypt	=	hifn_decrypt_aes_cfb,
-+		},
-+	},
-+	{
-+		.name = "ofb(aes)", .drv_name = "hifn-aes", .bsize = 16,
-+		.ablkcipher = {
-+			.min_keysize	=	AES_MIN_KEY_SIZE,
-+			.max_keysize	=	AES_MAX_KEY_SIZE,
-+			.setkey		=	hifn_setkey,
-+			.encrypt	=	hifn_encrypt_aes_ofb,
-+			.decrypt	=	hifn_decrypt_aes_ofb,
-+		},
-+	},
-+};
+ config BLK_DEV_MPC8xx_IDE
+-	bool "MPC8xx IDE support"
++	tristate "MPC8xx IDE support"
+ 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
+-	select IDE_GENERIC
+ 	help
+ 	  This option provides support for IDE on Motorola MPC8xx Systems.
+ 	  Please see 'Type of MPC8xx IDE interface' for details.
+@@ -1070,8 +1079,8 @@ config BLK_DEV_ALI14XX
+ 	  boot parameter.  It enables support for the secondary IDE interface
+ 	  of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
+ 	  I/O speeds to be set as well.  See the files
+-	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> for
+-	  more info.
++	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c>
++	  for more info.
+ 
+ config BLK_DEV_DTC2278
+ 	tristate "DTC-2278 support"
+@@ -1096,8 +1105,8 @@ config BLK_DEV_QD65XX
+ 	help
+ 	  This driver is enabled at runtime using the "qd65xx.probe" kernel
+ 	  boot parameter.  It permits faster I/O speeds to be set.  See the
+-	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for
+-	  more info.
++	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c>
++	  for more info.
+ 
+ config BLK_DEV_UMC8672
+ 	tristate "UMC-8672 support"
+diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
+index b181fc6..a4a4323 100644
+--- a/drivers/ide/Makefile
++++ b/drivers/ide/Makefile
+@@ -7,48 +7,60 @@
+ # Note : at this point, these files are compiled on all systems.
+ # In the future, some of these should be built conditionally.
+ #
+-# First come modules that register themselves with the core
++# link order is important here
+ 
+ EXTRA_CFLAGS				+= -Idrivers/ide
+ 
+-obj-$(CONFIG_BLK_DEV_IDE)		+= pci/
+-
+ ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
+ 
+-ide-core-$(CONFIG_BLK_DEV_CMD640)	+= pci/cmd640.o
+-
+-# Core IDE code - must come before legacy
++# core IDE code
+ ide-core-$(CONFIG_BLK_DEV_IDEPCI)	+= setup-pci.o
+ ide-core-$(CONFIG_BLK_DEV_IDEDMA)	+= ide-dma.o
+ ide-core-$(CONFIG_IDE_PROC_FS)		+= ide-proc.o
+-ide-core-$(CONFIG_BLK_DEV_IDEPNP)	+= ide-pnp.o
+ ide-core-$(CONFIG_BLK_DEV_IDEACPI)	+= ide-acpi.o
+ 
+-# built-in only drivers from arm/
+-ide-core-$(CONFIG_IDE_ARM)		+= arm/ide_arm.o
++obj-$(CONFIG_BLK_DEV_IDE)		+= ide-core.o
+ 
+-# built-in only drivers from legacy/
+-ide-core-$(CONFIG_BLK_DEV_BUDDHA)	+= legacy/buddha.o
+-ide-core-$(CONFIG_BLK_DEV_FALCON_IDE)	+= legacy/falconide.o
+-ide-core-$(CONFIG_BLK_DEV_GAYLE)	+= legacy/gayle.o
+-ide-core-$(CONFIG_BLK_DEV_MAC_IDE)	+= legacy/macide.o
+-ide-core-$(CONFIG_BLK_DEV_Q40IDE)	+= legacy/q40ide.o
++ifeq ($(CONFIG_IDE_ARM), y)
++	ide-arm-core-y += arm/ide_arm.o
++	obj-y += ide-arm-core.o
++endif
+ 
+-# built-in only drivers from ppc/
+-ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE)	+= ppc/mpc8xx.o
+-ide-core-$(CONFIG_BLK_DEV_IDE_PMAC)	+= ppc/pmac.o
++obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ pci/
+ 
+-# built-in only drivers from h8300/
+-ide-core-$(CONFIG_IDE_H8300)		+= h8300/ide-h8300.o
++obj-$(CONFIG_IDEPCI_PCIBUS_ORDER)	+= ide-scan-pci.o
+ 
+-obj-$(CONFIG_BLK_DEV_IDE)		+= ide-core.o
++ifeq ($(CONFIG_BLK_DEV_CMD640), y)
++	cmd640-core-y += pci/cmd640.o
++	obj-y += cmd640-core.o
++endif
 +
-+static int hifn_cra_init(struct crypto_tfm *tfm)
-+{
-+	struct crypto_alg *alg = tfm->__crt_alg;
-+	struct hifn_crypto_alg *ha = crypto_alg_to_hifn(alg);
-+	struct hifn_context *ctx = crypto_tfm_ctx(tfm);
++obj-$(CONFIG_BLK_DEV_IDE)		+= cris/ ppc/
++obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
++obj-$(CONFIG_IDE_H8300)			+= h8300/
+ obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
+ 
++ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
 +
-+	ctx->dev = ha->dev;
+ obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk.o
+-obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd.o
++obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd_mod.o
+ obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
+ obj-$(CONFIG_BLK_DEV_IDEFLOPPY)		+= ide-floppy.o
+ 
+-obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ arm/ mips/
+-obj-$(CONFIG_BLK_DEV_HD)		+= legacy/
+-obj-$(CONFIG_ETRAX_IDE)		+= cris/
++ifeq ($(CONFIG_BLK_DEV_IDECS), y)
++	ide-cs-core-y += legacy/ide-cs.o
++	obj-y += ide-cs-core.o
++endif
 +
-+	return 0;
-+}
++ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
++	ide-platform-core-y += legacy/ide_platform.o
++	obj-y += ide-platform-core.o
++endif
 +
-+static int hifn_alg_alloc(struct hifn_device *dev, struct hifn_alg_template *t)
-+{
-+	struct hifn_crypto_alg *alg;
-+	int err;
++obj-$(CONFIG_BLK_DEV_IDE)		+= arm/ mips/
 +
-+	alg = kzalloc(sizeof(struct hifn_crypto_alg), GFP_KERNEL);
-+	if (!alg)
-+		return -ENOMEM;
++# old hd driver must be last
++ifeq ($(CONFIG_BLK_DEV_HD), y)
++	hd-core-y += legacy/hd.o
++	obj-y += hd-core.o
++endif
+diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
+index 6a78f07..936e7b0 100644
+--- a/drivers/ide/arm/Makefile
++++ b/drivers/ide/arm/Makefile
+@@ -2,5 +2,10 @@
+ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
+ obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
+ obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
++obj-$(CONFIG_BLK_DEV_PALMCHIP_BK3710)	+= palm_bk3710.o
 +
-+	snprintf(alg->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s", t->name);
-+	snprintf(alg->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", t->drv_name);
++ifeq ($(CONFIG_IDE_ARM), m)
++	obj-m += ide_arm.o
++endif
+ 
+ EXTRA_CFLAGS	:= -Idrivers/ide
+diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
+index 48db616..0e7574c 100644
+--- a/drivers/ide/arm/bast-ide.c
++++ b/drivers/ide/arm/bast-ide.c
+@@ -1,5 +1,4 @@
+-/* linux/drivers/ide/arm/bast-ide.c
+- *
++/*
+  * Copyright (c) 2003-2004 Simtec Electronics
+  *  Ben Dooks <ben at simtec.co.uk>
+  *
+@@ -29,8 +28,10 @@ static int __init
+ bastide_register(unsigned int base, unsigned int aux, int irq,
+ 		 ide_hwif_t **hwif)
+ {
++	ide_hwif_t *hwif;
+ 	hw_regs_t hw;
+ 	int i;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+ 	memset(&hw, 0, sizeof(hw));
+ 
+@@ -45,8 +46,24 @@ bastide_register(unsigned int base, unsigned int aux, int irq,
+ 	hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
+ 	hw.irq = irq;
+ 
+-	ide_register_hw(&hw, NULL, 0, hwif);
++	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif == NULL)
++		goto out;
 +
-+	alg->alg.cra_priority = 300;
-+	alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
-+	alg->alg.cra_blocksize = t->bsize;
-+	alg->alg.cra_ctxsize = sizeof(struct hifn_context);
-+	alg->alg.cra_alignmask = 15;
-+	if (t->bsize == 8)
-+		alg->alg.cra_alignmask = 3;
-+	alg->alg.cra_type = &crypto_ablkcipher_type;
-+	alg->alg.cra_module = THIS_MODULE;
-+	alg->alg.cra_u.ablkcipher = t->ablkcipher;
-+	alg->alg.cra_init = hifn_cra_init;
++	i = hwif->index;
 +
-+	alg->dev = dev;
++	if (hwif->present)
++		ide_unregister(i, 0, 0);
++	else if (!hwif->hold)
++		ide_init_port_data(hwif, i);
 +
-+	list_add_tail(&alg->entry, &dev->alg_list);
++	ide_init_port_hw(hwif, &hw);
++	hwif->quirkproc = NULL;
 +
-+	err = crypto_register_alg(&alg->alg);
-+	if (err) {
-+		list_del(&alg->entry);
-+		kfree(alg);
-+	}
++	idx[0] = i;
+ 
++	ide_device_add(idx, NULL);
++out:
+ 	return 0;
+ }
+ 
+diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
+index 93f71fc..e816b0f 100644
+--- a/drivers/ide/arm/icside.c
++++ b/drivers/ide/arm/icside.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/arm/icside.c
+- *
+  * Copyright (c) 1996-2004 Russell King.
+  *
+  * Please note that this platform does not support 32-bit IDE IO.
+@@ -71,8 +69,6 @@ struct icside_state {
+ 	void __iomem *irq_port;
+ 	void __iomem *ioc_base;
+ 	unsigned int type;
+-	/* parent device... until the IDE core gets one of its own */
+-	struct device *dev;
+ 	ide_hwif_t *hwif[2];
+ };
+ 
+@@ -206,23 +202,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
+  * interfaces use the same IRQ, which should guarantee this.
+  */
+ 
+-static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
+-{
+-	ide_hwif_t *hwif = drive->hwif;
+-	struct icside_state *state = hwif->hwif_data;
+-	struct scatterlist *sg = hwif->sg_table;
+-
+-	ide_map_sg(drive, rq);
+-
+-	if (rq_data_dir(rq) == READ)
+-		hwif->sg_dma_direction = DMA_FROM_DEVICE;
+-	else
+-		hwif->sg_dma_direction = DMA_TO_DEVICE;
+-
+-	hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents,
+-				    hwif->sg_dma_direction);
+-}
+-
+ /*
+  * Configure the IOMD to give the appropriate timings for the transfer
+  * mode being requested.  We take the advice of the ATA standards, and
+@@ -272,8 +251,6 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
+ 	case XFER_SW_DMA_0:
+ 		cycle_time = 480;
+ 		break;
+-	default:
+-		return;
+ 	}
+ 
+ 	/*
+@@ -289,56 +266,39 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
+ 		ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
+ }
+ 
+-static void icside_dma_host_off(ide_drive_t *drive)
++static void icside_dma_host_set(ide_drive_t *drive, int on)
+ {
+ }
+ 
+-static void icside_dma_off_quietly(ide_drive_t *drive)
+-{
+-	drive->using_dma = 0;
+-}
+-
+-static void icside_dma_host_on(ide_drive_t *drive)
+-{
+-}
+-
+-static int icside_dma_on(ide_drive_t *drive)
+-{
+-	drive->using_dma = 1;
+-
+-	return 0;
+-}
+-
+ static int icside_dma_end(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct icside_state *state = hwif->hwif_data;
++	struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ 
+ 	drive->waiting_for_dma = 0;
+ 
+-	disable_dma(ECARD_DEV(state->dev)->dma);
++	disable_dma(ec->dma);
+ 
+ 	/* Teardown mappings after DMA has completed. */
+-	dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
+-		     hwif->sg_dma_direction);
++	ide_destroy_dmatable(drive);
+ 
+-	return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0;
++	return get_dma_residue(ec->dma) != 0;
+ }
+ 
+ static void icside_dma_start(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct icside_state *state = hwif->hwif_data;
++	struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ 
+ 	/* We can not enable DMA on both channels simultaneously. */
+-	BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
+-	enable_dma(ECARD_DEV(state->dev)->dma);
++	BUG_ON(dma_channel_active(ec->dma));
++	enable_dma(ec->dma);
+ }
+ 
+ static int icside_dma_setup(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct icside_state *state = hwif->hwif_data;
++	struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ 	struct request *rq = hwif->hwgroup->rq;
+ 	unsigned int dma_mode;
+ 
+@@ -350,9 +310,9 @@ static int icside_dma_setup(ide_drive_t *drive)
+ 	/*
+ 	 * We can not enable DMA on both channels.
+ 	 */
+-	BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
++	BUG_ON(dma_channel_active(ec->dma));
+ 
+-	icside_build_sglist(drive, rq);
++	hwif->sg_nents = ide_build_sglist(drive, rq);
+ 
+ 	/*
+ 	 * Ensure that we have the right interrupt routed.
+@@ -367,14 +327,14 @@ static int icside_dma_setup(ide_drive_t *drive)
+ 	/*
+ 	 * Select the correct timing for this drive.
+ 	 */
+-	set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data);
++	set_dma_speed(ec->dma, drive->drive_data);
+ 
+ 	/*
+ 	 * Tell the DMA engine about the SG table and
+ 	 * data direction.
+ 	 */
+-	set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents);
+-	set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode);
++	set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
++	set_dma_mode(ec->dma, dma_mode);
+ 
+ 	drive->waiting_for_dma = 1;
+ 
+@@ -405,7 +365,7 @@ static void icside_dma_timeout(ide_drive_t *drive)
+ 	if (icside_dma_test_irq(drive))
+ 		return;
+ 
+-	ide_dump_status(drive, "DMA timeout", HWIF(drive)->INB(IDE_STATUS_REG));
++	ide_dump_status(drive, "DMA timeout", ide_read_status(drive));
+ 
+ 	icside_dma_end(drive);
+ }
+@@ -417,17 +377,11 @@ static void icside_dma_lost_irq(ide_drive_t *drive)
+ 
+ static void icside_dma_init(ide_hwif_t *hwif)
+ {
+-	hwif->mwdma_mask	= 7; /* MW0..2 */
+-	hwif->swdma_mask	= 7; /* SW0..2 */
+-
+ 	hwif->dmatable_cpu	= NULL;
+ 	hwif->dmatable_dma	= 0;
+ 	hwif->set_dma_mode	= icside_set_dma_mode;
+ 
+-	hwif->dma_host_off	= icside_dma_host_off;
+-	hwif->dma_off_quietly	= icside_dma_off_quietly;
+-	hwif->dma_host_on	= icside_dma_host_on;
+-	hwif->ide_dma_on	= icside_dma_on;
++	hwif->dma_host_set	= icside_dma_host_set;
+ 	hwif->dma_setup		= icside_dma_setup;
+ 	hwif->dma_exec_cmd	= icside_dma_exec_cmd;
+ 	hwif->dma_start		= icside_dma_start;
+@@ -465,6 +419,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
+ 		hwif->noprobe = 0;
+ 		hwif->chipset = ide_acorn;
+ 		hwif->gendev.parent = &ec->dev;
++		hwif->dev = &ec->dev;
+ 	}
+ 
+ 	return hwif;
+@@ -501,11 +456,19 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
+ 
+ 	idx[0] = hwif->index;
+ 
+-	ide_device_add(idx);
++	ide_device_add(idx, NULL);
+ 
+ 	return 0;
+ }
+ 
++static const struct ide_port_info icside_v6_port_info __initdata = {
++	.host_flags		= IDE_HFLAG_SERIALIZE |
++				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
++				  IDE_HFLAG_NO_AUTOTUNE,
++	.mwdma_mask		= ATA_MWDMA2,
++	.swdma_mask		= ATA_SWDMA2,
++};
 +
-+	return err;
-+}
+ static int __init
+ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+ {
+@@ -514,6 +477,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+ 	unsigned int sel = 0;
+ 	int ret;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	struct ide_port_info d = icside_v6_port_info;
+ 
+ 	ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
+ 	if (!ioc_base) {
+@@ -563,30 +527,25 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+ 	state->hwif[1]    = mate;
+ 
+ 	hwif->maskproc    = icside_maskproc;
+-	hwif->channel     = 0;
+ 	hwif->hwif_data   = state;
+-	hwif->mate        = mate;
+-	hwif->serialized  = 1;
+ 	hwif->config_data = (unsigned long)ioc_base;
+ 	hwif->select_data = sel;
+ 
+ 	mate->maskproc    = icside_maskproc;
+-	mate->channel     = 1;
+ 	mate->hwif_data   = state;
+-	mate->mate        = hwif;
+-	mate->serialized  = 1;
+ 	mate->config_data = (unsigned long)ioc_base;
+ 	mate->select_data = sel | 1;
+ 
+ 	if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
+ 		icside_dma_init(hwif);
+ 		icside_dma_init(mate);
+-	}
++	} else
++		d.mwdma_mask = d.swdma_mask = 0;
+ 
+ 	idx[0] = hwif->index;
+ 	idx[1] = mate->index;
+ 
+-	ide_device_add(idx);
++	ide_device_add(idx, &d);
+ 
+ 	return 0;
+ 
+@@ -612,7 +571,6 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 	}
+ 
+ 	state->type	= ICS_TYPE_NOTYPE;
+-	state->dev	= &ec->dev;
+ 
+ 	idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
+ 	if (idmem) {
+diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
+index 8957cba..43a70e9 100644
+--- a/drivers/ide/arm/ide_arm.c
++++ b/drivers/ide/arm/ide_arm.c
+@@ -24,12 +24,25 @@
+ # define IDE_ARM_IRQ	IRQ_HARDDISK
+ #endif
+ 
+-void __init ide_arm_init(void)
++static int __init ide_arm_init(void)
+ {
++	ide_hwif_t *hwif;
+ 	hw_regs_t hw;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+ 	memset(&hw, 0, sizeof(hw));
+ 	ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
+ 	hw.irq = IDE_ARM_IRQ;
+-	ide_register_hw(&hw, NULL, 1, NULL);
 +
-+static void hifn_unregister_alg(struct hifn_device *dev)
-+{
-+	struct hifn_crypto_alg *a, *n;
++	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif) {
++		ide_init_port_hw(hwif, &hw);
++		idx[0] = hwif->index;
 +
-+	list_for_each_entry_safe(a, n, &dev->alg_list, entry) {
-+		list_del(&a->entry);
-+		crypto_unregister_alg(&a->alg);
-+		kfree(a);
++		ide_device_add(idx, NULL);
 +	}
-+}
 +
-+static int hifn_register_alg(struct hifn_device *dev)
-+{
-+	int i, err;
++	return 0;
+ }
 +
-+	for (i=0; i<ARRAY_SIZE(hifn_alg_templates); ++i) {
-+		err = hifn_alg_alloc(dev, &hifn_alg_templates[i]);
-+		if (err)
-+			goto err_out_exit;
-+	}
++module_init(ide_arm_init);
+diff --git a/drivers/ide/arm/palm_bk3710.c b/drivers/ide/arm/palm_bk3710.c
+new file mode 100644
+index 0000000..c306997
+--- /dev/null
++++ b/drivers/ide/arm/palm_bk3710.c
+@@ -0,0 +1,395 @@
++/*
++ * Palmchip bk3710 IDE controller
++ *
++ * Copyright (C) 2006 Texas Instruments.
++ * Copyright (C) 2007 MontaVista Software, Inc., <source at mvista.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.
++ *
++ * 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.
++ * ----------------------------------------------------------------------------
++ *
++ */
 +
-+	return 0;
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/ioport.h>
++#include <linux/hdreg.h>
++#include <linux/ide.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
 +
-+err_out_exit:
-+	hifn_unregister_alg(dev);
-+	return err;
++/* Offset of the primary interface registers */
++#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0
++
++/* Primary Control Offset */
++#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6
++
++/*
++ * PalmChip 3710 IDE Controller UDMA timing structure Definition
++ */
++struct palm_bk3710_udmatiming {
++	unsigned int rptime;	/* Ready to pause time  */
++	unsigned int cycletime;	/* Cycle Time           */
++};
++
++#define BK3710_BMICP		0x00
++#define BK3710_BMISP		0x02
++#define BK3710_BMIDTP		0x04
++#define BK3710_BMICS		0x08
++#define BK3710_BMISS		0x0A
++#define BK3710_BMIDTS		0x0C
++#define BK3710_IDETIMP		0x40
++#define BK3710_IDETIMS		0x42
++#define BK3710_SIDETIM		0x44
++#define BK3710_SLEWCTL		0x45
++#define BK3710_IDESTATUS	0x47
++#define BK3710_UDMACTL		0x48
++#define BK3710_UDMATIM		0x4A
++#define BK3710_MISCCTL		0x50
++#define BK3710_REGSTB		0x54
++#define BK3710_REGRCVR		0x58
++#define BK3710_DATSTB		0x5C
++#define BK3710_DATRCVR		0x60
++#define BK3710_DMASTB		0x64
++#define BK3710_DMARCVR		0x68
++#define BK3710_UDMASTB		0x6C
++#define BK3710_UDMATRP		0x70
++#define BK3710_UDMAENV		0x74
++#define BK3710_IORDYTMP		0x78
++#define BK3710_IORDYTMS		0x7C
++
++#include "../ide-timing.h"
++
++static long ide_palm_clk;
++
++static const struct palm_bk3710_udmatiming palm_bk3710_udmatimings[6] = {
++	{160, 240},		/* UDMA Mode 0 */
++	{125, 160},		/* UDMA Mode 1 */
++	{100, 120},		/* UDMA Mode 2 */
++	{100, 90},		/* UDMA Mode 3 */
++	{85,  60},		/* UDMA Mode 4 */
++};
++
++static struct clk *ideclkp;
++
++static void palm_bk3710_setudmamode(void __iomem *base, unsigned int dev,
++				    unsigned int mode)
++{
++	u8 tenv, trp, t0;
++	u32 val32;
++	u16 val16;
++
++	/* DMA Data Setup */
++	t0 = (palm_bk3710_udmatimings[mode].cycletime + ide_palm_clk - 1)
++			/ ide_palm_clk - 1;
++	tenv = (20 + ide_palm_clk - 1) / ide_palm_clk - 1;
++	trp = (palm_bk3710_udmatimings[mode].rptime + ide_palm_clk - 1)
++			/ ide_palm_clk - 1;
++
++	/* udmatim Register */
++	val16 = readw(base + BK3710_UDMATIM) & (dev ? 0xFF0F : 0xFFF0);
++	val16 |= (mode << (dev ? 4 : 0));
++	writew(val16, base + BK3710_UDMATIM);
++
++	/* udmastb Ultra DMA Access Strobe Width */
++	val32 = readl(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
++	val32 |= (t0 << (dev ? 8 : 0));
++	writel(val32, base + BK3710_UDMASTB);
++
++	/* udmatrp Ultra DMA Ready to Pause Time */
++	val32 = readl(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
++	val32 |= (trp << (dev ? 8 : 0));
++	writel(val32, base + BK3710_UDMATRP);
++
++	/* udmaenv Ultra DMA envelop Time */
++	val32 = readl(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
++	val32 |= (tenv << (dev ? 8 : 0));
++	writel(val32, base + BK3710_UDMAENV);
++
++	/* Enable UDMA for Device */
++	val16 = readw(base + BK3710_UDMACTL) | (1 << dev);
++	writew(val16, base + BK3710_UDMACTL);
++}
++
++static void palm_bk3710_setdmamode(void __iomem *base, unsigned int dev,
++				   unsigned short min_cycle,
++				   unsigned int mode)
++{
++	u8 td, tkw, t0;
++	u32 val32;
++	u16 val16;
++	struct ide_timing *t;
++	int cycletime;
++
++	t = ide_timing_find_mode(mode);
++	cycletime = max_t(int, t->cycle, min_cycle);
++
++	/* DMA Data Setup */
++	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
++	td = (t->active + ide_palm_clk - 1) / ide_palm_clk;
++	tkw = t0 - td - 1;
++	td -= 1;
++
++	val32 = readl(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
++	val32 |= (td << (dev ? 8 : 0));
++	writel(val32, base + BK3710_DMASTB);
++
++	val32 = readl(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
++	val32 |= (tkw << (dev ? 8 : 0));
++	writel(val32, base + BK3710_DMARCVR);
++
++	/* Disable UDMA for Device */
++	val16 = readw(base + BK3710_UDMACTL) & ~(1 << dev);
++	writew(val16, base + BK3710_UDMACTL);
++}
++
++static void palm_bk3710_setpiomode(void __iomem *base, ide_drive_t *mate,
++				   unsigned int dev, unsigned int cycletime,
++				   unsigned int mode)
++{
++	u8 t2, t2i, t0;
++	u32 val32;
++	struct ide_timing *t;
++
++	/* PIO Data Setup */
++	t0 = (cycletime + ide_palm_clk - 1) / ide_palm_clk;
++	t2 = (ide_timing_find_mode(XFER_PIO_0 + mode)->active +
++	      ide_palm_clk - 1)	/ ide_palm_clk;
++
++	t2i = t0 - t2 - 1;
++	t2 -= 1;
++
++	val32 = readl(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
++	val32 |= (t2 << (dev ? 8 : 0));
++	writel(val32, base + BK3710_DATSTB);
++
++	val32 = readl(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
++	val32 |= (t2i << (dev ? 8 : 0));
++	writel(val32, base + BK3710_DATRCVR);
++
++	if (mate && mate->present) {
++		u8 mode2 = ide_get_best_pio_mode(mate, 255, 4);
++
++		if (mode2 < mode)
++			mode = mode2;
++	}
++
++	/* TASKFILE Setup */
++	t = ide_timing_find_mode(XFER_PIO_0 + mode);
++	t0 = (t->cyc8b + ide_palm_clk - 1) / ide_palm_clk;
++	t2 = (t->act8b + ide_palm_clk - 1) / ide_palm_clk;
++
++	t2i = t0 - t2 - 1;
++	t2 -= 1;
++
++	val32 = readl(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
++	val32 |= (t2 << (dev ? 8 : 0));
++	writel(val32, base + BK3710_REGSTB);
++
++	val32 = readl(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
++	val32 |= (t2i << (dev ? 8 : 0));
++	writel(val32, base + BK3710_REGRCVR);
++}
++
++static void palm_bk3710_set_dma_mode(ide_drive_t *drive, u8 xferspeed)
++{
++	int is_slave = drive->dn & 1;
++	void __iomem *base = (void *)drive->hwif->dma_base;
++
++	if (xferspeed >= XFER_UDMA_0) {
++		palm_bk3710_setudmamode(base, is_slave,
++					xferspeed - XFER_UDMA_0);
++	} else {
++		palm_bk3710_setdmamode(base, is_slave, drive->id->eide_dma_min,
++				       xferspeed);
++	}
 +}
 +
-+static void hifn_tasklet_callback(unsigned long data)
++static void palm_bk3710_set_pio_mode(ide_drive_t *drive, u8 pio)
 +{
-+	struct hifn_device *dev = (struct hifn_device *)data;
++	unsigned int cycle_time;
++	int is_slave = drive->dn & 1;
++	ide_drive_t *mate;
++	void __iomem *base = (void *)drive->hwif->dma_base;
 +
 +	/*
-+	 * This is ok to call this without lock being held,
-+	 * althogh it modifies some parameters used in parallel,
-+	 * (like dev->success), but they are used in process
-+	 * context or update is atomic (like setting dev->sa[i] to NULL).
++	 * Obtain the drive PIO data for tuning the Palm Chip registers
 +	 */
-+	hifn_check_for_completion(dev, 0);
++	cycle_time = ide_pio_cycle_time(drive, pio);
++	mate = ide_get_paired_drive(drive);
++	palm_bk3710_setpiomode(base, mate, is_slave, cycle_time, pio);
 +}
 +
-+static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++static void __devinit palm_bk3710_chipinit(void __iomem *base)
 +{
-+	int err, i;
-+	struct hifn_device *dev;
-+	char name[8];
-+
-+	err = pci_enable_device(pdev);
-+	if (err)
-+		return err;
-+	pci_set_master(pdev);
-+
-+	err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
-+	if (err)
-+		goto err_out_disable_pci_device;
++	/*
++	 * enable the reset_en of ATA controller so that when ata signals
++	 * are brought out, by writing into device config. at that
++	 * time por_n signal should not be 'Z' and have a stable value.
++	 */
++	writel(0x0300, base + BK3710_MISCCTL);
 +
-+	snprintf(name, sizeof(name), "hifn%d",
-+			atomic_inc_return(&hifn_dev_number)-1);
++	/* wait for some time and deassert the reset of ATA Device. */
++	mdelay(100);
 +
-+	err = pci_request_regions(pdev, name);
-+	if (err)
-+		goto err_out_disable_pci_device;
++	/* Deassert the Reset */
++	writel(0x0200, base + BK3710_MISCCTL);
 +
-+	if (pci_resource_len(pdev, 0) < HIFN_BAR0_SIZE ||
-+	    pci_resource_len(pdev, 1) < HIFN_BAR1_SIZE ||
-+	    pci_resource_len(pdev, 2) < HIFN_BAR2_SIZE) {
-+		dprintk("%s: Broken hardware - I/O regions are too small.\n",
-+				pci_name(pdev));
-+		err = -ENODEV;
-+		goto err_out_free_regions;
-+	}
++	/*
++	 * Program the IDETIMP Register Value based on the following assumptions
++	 *
++	 * (ATA_IDETIMP_IDEEN		, ENABLE ) |
++	 * (ATA_IDETIMP_SLVTIMEN	, DISABLE) |
++	 * (ATA_IDETIMP_RDYSMPL		, 70NS)    |
++	 * (ATA_IDETIMP_RDYRCVRY	, 50NS)    |
++	 * (ATA_IDETIMP_DMAFTIM1	, PIOCOMP) |
++	 * (ATA_IDETIMP_PREPOST1	, DISABLE) |
++	 * (ATA_IDETIMP_RDYSEN1		, DISABLE) |
++	 * (ATA_IDETIMP_PIOFTIM1	, DISABLE) |
++	 * (ATA_IDETIMP_DMAFTIM0	, PIOCOMP) |
++	 * (ATA_IDETIMP_PREPOST0	, DISABLE) |
++	 * (ATA_IDETIMP_RDYSEN0		, DISABLE) |
++	 * (ATA_IDETIMP_PIOFTIM0	, DISABLE)
++	 */
++	writew(0xB388, base + BK3710_IDETIMP);
++
++	/*
++	 * Configure  SIDETIM  Register
++	 * (ATA_SIDETIM_RDYSMPS1	,120NS ) |
++	 * (ATA_SIDETIM_RDYRCYS1	,120NS )
++	 */
++	writeb(0, base + BK3710_SIDETIM);
++
++	/*
++	 * UDMACTL Ultra-ATA DMA Control
++	 * (ATA_UDMACTL_UDMAP1	, 0 ) |
++	 * (ATA_UDMACTL_UDMAP0	, 0 )
++	 *
++	 */
++	writew(0, base + BK3710_UDMACTL);
 +
-+	dev = kzalloc(sizeof(struct hifn_device) + sizeof(struct crypto_alg),
-+			GFP_KERNEL);
-+	if (!dev) {
-+		err = -ENOMEM;
-+		goto err_out_free_regions;
-+	}
++	/*
++	 * MISCCTL Miscellaneous Conrol Register
++	 * (ATA_MISCCTL_RSTMODEP	, 1) |
++	 * (ATA_MISCCTL_RESETP		, 0) |
++	 * (ATA_MISCCTL_TIMORIDE	, 1)
++	 */
++	writel(0x201, base + BK3710_MISCCTL);
 +
-+	INIT_LIST_HEAD(&dev->alg_list);
++	/*
++	 * IORDYTMP IORDY Timer for Primary Register
++	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
++	 */
++	writel(0xFFFF, base + BK3710_IORDYTMP);
 +
-+	snprintf(dev->name, sizeof(dev->name), "%s", name);
-+	spin_lock_init(&dev->lock);
++	/*
++	 * Configure BMISP Register
++	 * (ATA_BMISP_DMAEN1	, DISABLE )	|
++	 * (ATA_BMISP_DMAEN0	, DISABLE )	|
++	 * (ATA_BMISP_IORDYINT	, CLEAR)	|
++	 * (ATA_BMISP_INTRSTAT	, CLEAR)	|
++	 * (ATA_BMISP_DMAERROR	, CLEAR)
++	 */
++	writew(0, base + BK3710_BMISP);
 +
-+	for (i=0; i<3; ++i) {
-+		unsigned long addr, size;
++	palm_bk3710_setpiomode(base, NULL, 0, 600, 0);
++	palm_bk3710_setpiomode(base, NULL, 1, 600, 0);
++}
++static int __devinit palm_bk3710_probe(struct platform_device *pdev)
++{
++	hw_regs_t ide_ctlr_info;
++	int index = 0;
++	int pribase;
++	struct clk *clkp;
++	struct resource *mem, *irq;
++	ide_hwif_t *hwif;
++	void __iomem *base;
 +
-+		addr = pci_resource_start(pdev, i);
-+		size = pci_resource_len(pdev, i);
++	clkp = clk_get(NULL, "IDECLK");
++	if (IS_ERR(clkp))
++		return -ENODEV;
 +
-+		dev->bar[i] = ioremap_nocache(addr, size);
-+		if (!dev->bar[i])
-+			goto err_out_unmap_bars;
-+	}
++	ideclkp = clkp;
++	clk_enable(ideclkp);
++	ide_palm_clk = clk_get_rate(ideclkp)/100000;
++	ide_palm_clk = (10000/ide_palm_clk) + 1;
++	/* Register the IDE interface with Linux ATA Interface */
++	memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
 +
-+	dev->result_mem = __get_free_pages(GFP_KERNEL, HIFN_MAX_RESULT_ORDER);
-+	if (!dev->result_mem) {
-+		dprintk("Failed to allocate %d pages for result_mem.\n",
-+				HIFN_MAX_RESULT_ORDER);
-+		goto err_out_unmap_bars;
++	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (mem == NULL) {
++		printk(KERN_ERR "failed to get memory region resource\n");
++		return -ENODEV;
 +	}
-+	memset((void *)dev->result_mem, 0, PAGE_SIZE*(1<<HIFN_MAX_RESULT_ORDER));
-+
-+	dev->dst = pci_map_single(pdev, (void *)dev->result_mem,
-+			PAGE_SIZE << HIFN_MAX_RESULT_ORDER, PCI_DMA_FROMDEVICE);
-+
-+	dev->desc_virt = pci_alloc_consistent(pdev, sizeof(struct hifn_dma),
-+			&dev->desc_dma);
-+	if (!dev->desc_virt) {
-+		dprintk("Failed to allocate descriptor rings.\n");
-+		goto err_out_free_result_pages;
++	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
++	if (irq == NULL) {
++		printk(KERN_ERR "failed to get IRQ resource\n");
++		return -ENODEV;
 +	}
-+	memset(dev->desc_virt, 0, sizeof(struct hifn_dma));
-+
-+	dev->pdev = pdev;
-+	dev->irq = pdev->irq;
-+
-+	for (i=0; i<HIFN_D_RES_RSIZE; ++i)
-+		dev->sa[i] = NULL;
 +
-+	pci_set_drvdata(pdev, dev);
++	base = (void *)mem->start;
 +
-+	tasklet_init(&dev->tasklet, hifn_tasklet_callback, (unsigned long)dev);
++	/* Configure the Palm Chip controller */
++	palm_bk3710_chipinit(base);
 +
-+	crypto_init_queue(&dev->queue, 1);
++	pribase = mem->start + IDE_PALM_ATA_PRI_REG_OFFSET;
++	for (index = 0; index < IDE_NR_PORTS - 2; index++)
++		ide_ctlr_info.io_ports[index] = pribase + index;
++	ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] = mem->start +
++			IDE_PALM_ATA_PRI_CTL_OFFSET;
++	ide_ctlr_info.irq = irq->start;
++	ide_ctlr_info.chipset = ide_palm3710;
 +
-+	err = request_irq(dev->irq, hifn_interrupt, IRQF_SHARED, dev->name, dev);
-+	if (err) {
-+		dprintk("Failed to request IRQ%d: err: %d.\n", dev->irq, err);
-+		dev->irq = 0;
-+		goto err_out_free_desc;
++	if (ide_register_hw(&ide_ctlr_info, NULL, &hwif) < 0) {
++		printk(KERN_WARNING "Palm Chip BK3710 IDE Register Fail\n");
++		return -ENODEV;
 +	}
 +
-+	err = hifn_start_device(dev);
-+	if (err)
-+		goto err_out_free_irq;
-+
-+	err = hifn_test(dev, 1, 0);
-+	if (err)
-+		goto err_out_stop_device;
-+
-+	err = hifn_register_rng(dev);
-+	if (err)
-+		goto err_out_stop_device;
-+
-+	err = hifn_register_alg(dev);
-+	if (err)
-+		goto err_out_unregister_rng;
-+
-+	INIT_DELAYED_WORK(&dev->work, hifn_work);
-+	schedule_delayed_work(&dev->work, HZ);
++	hwif->set_pio_mode = &palm_bk3710_set_pio_mode;
++	hwif->set_dma_mode = &palm_bk3710_set_dma_mode;
++	hwif->mmio = 1;
++	default_hwif_mmiops(hwif);
++	hwif->cbl = ATA_CBL_PATA80;
++	hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
++						(input clk 99MHz) */
++	hwif->mwdma_mask = 0x7;
++	hwif->drives[0].autotune = 1;
++	hwif->drives[1].autotune = 1;
 +
-+	dprintk("HIFN crypto accelerator card at %s has been "
-+			"successfully registered as %s.\n",
-+			pci_name(pdev), dev->name);
++	ide_setup_dma(hwif, mem->start);
 +
 +	return 0;
++}
 +
-+err_out_unregister_rng:
-+	hifn_unregister_rng(dev);
-+err_out_stop_device:
-+	hifn_reset_dma(dev, 1);
-+	hifn_stop_device(dev);
-+err_out_free_irq:
-+	free_irq(dev->irq, dev->name);
-+	tasklet_kill(&dev->tasklet);
-+err_out_free_desc:
-+	pci_free_consistent(pdev, sizeof(struct hifn_dma),
-+			dev->desc_virt, dev->desc_dma);
-+
-+err_out_free_result_pages:
-+	pci_unmap_single(pdev, dev->dst, PAGE_SIZE << HIFN_MAX_RESULT_ORDER,
-+			PCI_DMA_FROMDEVICE);
-+	free_pages(dev->result_mem, HIFN_MAX_RESULT_ORDER);
-+
-+err_out_unmap_bars:
-+	for (i=0; i<3; ++i)
-+		if (dev->bar[i])
-+			iounmap(dev->bar[i]);
-+
-+err_out_free_regions:
-+	pci_release_regions(pdev);
-+
-+err_out_disable_pci_device:
-+	pci_disable_device(pdev);
++static struct platform_driver platform_bk_driver = {
++	.driver = {
++		.name = "palm_bk3710",
++	},
++	.probe = palm_bk3710_probe,
++	.remove = NULL,
++};
 +
-+	return err;
++static int __init palm_bk3710_init(void)
++{
++	return platform_driver_register(&platform_bk_driver);
 +}
 +
-+static void hifn_remove(struct pci_dev *pdev)
-+{
-+	int i;
-+	struct hifn_device *dev;
++module_init(palm_bk3710_init);
++MODULE_LICENSE("GPL");
 +
-+	dev = pci_get_drvdata(pdev);
+diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
+index 0775a3a..efba00d 100644
+--- a/drivers/ide/arm/rapide.c
++++ b/drivers/ide/arm/rapide.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/arm/rapide.c
+- *
+  * Copyright (c) 1996-2002 Russell King.
+  */
+ 
+@@ -13,26 +11,18 @@
+ 
+ #include <asm/ecard.h>
+ 
+-static ide_hwif_t *
+-rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq)
++static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
++			       void __iomem *ctrl, unsigned int sz, int irq)
+ {
+ 	unsigned long port = (unsigned long)base;
+-	ide_hwif_t *hwif = ide_find_port(port);
+ 	int i;
+ 
+-	if (hwif == NULL)
+-		goto out;
+-
+ 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+-		hwif->io_ports[i] = port;
++		hw->io_ports[i] = port;
+ 		port += sz;
+ 	}
+-	hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+-	hwif->irq = irq;
+-	hwif->mmio = 1;
+-	default_hwif_mmiops(hwif);
+-out:
+-	return hwif;
++	hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
++	hw->irq = irq;
+ }
+ 
+ static int __devinit
+@@ -42,6 +32,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 	void __iomem *base;
+ 	int ret;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw;
+ 
+ 	ret = ecard_request_resources(ec);
+ 	if (ret)
+@@ -53,15 +44,21 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
+ 		goto release;
+ 	}
+ 
+-	hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq);
++	hwif = ide_find_port((unsigned long)base);
+ 	if (hwif) {
+-		hwif->hwif_data = base;
+-		hwif->gendev.parent = &ec->dev;
+-		hwif->noprobe = 0;
++		memset(&hw, 0, sizeof(hw));
++		rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
++		hw.chipset = ide_generic;
++		hw.dev = &ec->dev;
 +
-+	if (dev) {
-+		cancel_delayed_work(&dev->work);
-+		flush_scheduled_work();
++		ide_init_port_hw(hwif, &hw);
 +
-+		hifn_unregister_rng(dev);
-+		hifn_unregister_alg(dev);
-+		hifn_reset_dma(dev, 1);
-+		hifn_stop_device(dev);
++		hwif->mmio = 1;
++		default_hwif_mmiops(hwif);
+ 
+ 		idx[0] = hwif->index;
+ 
+-		ide_device_add(idx);
++		ide_device_add(idx, NULL);
+ 
+ 		ecard_set_drvdata(ec, hwif);
+ 		goto out;
+@@ -79,8 +76,8 @@ static void __devexit rapide_remove(struct expansion_card *ec)
+ 
+ 	ecard_set_drvdata(ec, NULL);
+ 
+-	/* there must be a better way */
+-	ide_unregister(hwif - ide_hwifs);
++	ide_unregister(hwif->index, 0, 0);
 +
-+		free_irq(dev->irq, dev->name);
-+		tasklet_kill(&dev->tasklet);
+ 	ecard_release_resources(ec);
+ }
+ 
+diff --git a/drivers/ide/cris/Makefile b/drivers/ide/cris/Makefile
+index 6176e8d..20b9596 100644
+--- a/drivers/ide/cris/Makefile
++++ b/drivers/ide/cris/Makefile
+@@ -1,3 +1,3 @@
+ EXTRA_CFLAGS				+= -Idrivers/ide
+ 
+-obj-y					+= ide-cris.o
++obj-$(CONFIG_IDE_ETRAX)			+= ide-cris.o
+diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
+index 476e0d6..e79bf8f 100644
+--- a/drivers/ide/cris/ide-cris.c
++++ b/drivers/ide/cris/ide-cris.c
+@@ -1,5 +1,4 @@
+-/* $Id: cris-ide-driver.patch,v 1.1 2005/06/29 21:39:07 akpm Exp $
+- *
++/*
+  * Etrax specific IDE functions, like init and PIO-mode setting etc.
+  * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
+  * Copyright (c) 2000-2005 Axis Communications AB
+@@ -673,9 +672,8 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
+ static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
+ static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
+ static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
+-static int cris_dma_on (ide_drive_t *drive);
+ 
+-static void cris_dma_off(ide_drive_t *drive)
++static void cris_dma_host_set(ide_drive_t *drive, int on)
+ {
+ }
+ 
+@@ -747,8 +745,6 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 			strobe = ATA_DMA2_STROBE;
+ 			hold = ATA_DMA2_HOLD;
+ 			break;
+-		default:
+-			return;
+ 	}
+ 
+ 	if (speed >= XFER_UDMA_0)
+@@ -757,40 +753,60 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 		cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
+ }
+ 
+-void __init
+-init_e100_ide (void)
++static void __init cris_setup_ports(hw_regs_t *hw, unsigned long base)
+ {
+-	hw_regs_t hw;
+-	int ide_offsets[IDE_NR_PORTS];
+-	int h;
+ 	int i;
+ 
+-	printk("ide: ETRAX FS built-in ATA DMA controller\n");
++	memset(hw, 0, sizeof(*hw));
+ 
+-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+-		ide_offsets[i] = cris_ide_reg_addr(i, 0, 1);
++	for (i = 0; i <= 7; i++)
++		hw->io_ports[i] = base + cris_ide_reg_addr(i, 0, 1);
+ 
+-	/* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
+-	ide_offsets[IDE_CONTROL_OFFSET] = cris_ide_reg_addr(6, 1, 0);
++	/*
++	 * the IDE control register is at ATA address 6,
++	 * with CS1 active instead of CS0
++	 */
++	hw->io_ports[IDE_CONTROL_OFFSET] = base + cris_ide_reg_addr(6, 1, 0);
 +
-+		hifn_flush(dev);
++	hw->irq = ide_default_irq(0);
++	hw->ack_intr = cris_ide_ack_intr;
++}
 +
-+		pci_free_consistent(pdev, sizeof(struct hifn_dma),
-+				dev->desc_virt, dev->desc_dma);
-+		pci_unmap_single(pdev, dev->dst,
-+				PAGE_SIZE << HIFN_MAX_RESULT_ORDER,
-+				PCI_DMA_FROMDEVICE);
-+		free_pages(dev->result_mem, HIFN_MAX_RESULT_ORDER);
-+		for (i=0; i<3; ++i)
-+			if (dev->bar[i])
-+				iounmap(dev->bar[i]);
++static const struct ide_port_info cris_port_info __initdata = {
++	.chipset		= ide_etrax100,
++	.host_flags		= IDE_HFLAG_NO_ATAPI_DMA |
++				  IDE_HFLAG_NO_DMA, /* no SFF-style DMA */
++	.pio_mask		= ATA_PIO4,
++	.udma_mask		= cris_ultra_mask,
++	.mwdma_mask		= ATA_MWDMA2,
++};
 +
-+		kfree(dev);
-+	}
++static int __init init_e100_ide(void)
++{
++	hw_regs_t hw;
++	int h;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 +
-+	pci_release_regions(pdev);
-+	pci_disable_device(pdev);
-+}
++	printk("ide: ETRAX FS built-in ATA DMA controller\n");
+ 
+ 	for (h = 0; h < 4; h++) {
+ 		ide_hwif_t *hwif = NULL;
+ 
+-		ide_setup_ports(&hw, cris_ide_base_address(h),
+-		                ide_offsets,
+-		                0, 0, cris_ide_ack_intr,
+-		                ide_default_irq(0));
+-		ide_register_hw(&hw, NULL, 1, &hwif);
++		cris_setup_ports(&hw, cris_ide_base_address(h));
 +
-+static struct pci_device_id hifn_pci_tbl[] = {
-+	{ PCI_DEVICE(PCI_VENDOR_ID_HIFN, PCI_DEVICE_ID_HIFN_7955) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_HIFN, PCI_DEVICE_ID_HIFN_7956) },
-+	{ 0 }
-+};
-+MODULE_DEVICE_TABLE(pci, hifn_pci_tbl);
++		hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
+ 		if (hwif == NULL)
+ 			continue;
++		ide_init_port_data(hwif, hwif->index);
++		ide_init_port_hw(hwif, &hw);
+ 		hwif->mmio = 1;
+-		hwif->chipset = ide_etrax100;
+ 		hwif->set_pio_mode = &cris_set_pio_mode;
+ 		hwif->set_dma_mode = &cris_set_dma_mode;
+ 		hwif->ata_input_data = &cris_ide_input_data;
+ 		hwif->ata_output_data = &cris_ide_output_data;
+ 		hwif->atapi_input_bytes = &cris_atapi_input_bytes;
+ 		hwif->atapi_output_bytes = &cris_atapi_output_bytes;
++		hwif->dma_host_set = &cris_dma_host_set;
+ 		hwif->ide_dma_end = &cris_dma_end;
+ 		hwif->dma_setup = &cris_dma_setup;
+ 		hwif->dma_exec_cmd = &cris_dma_exec_cmd;
+@@ -801,16 +817,9 @@ init_e100_ide (void)
+ 		hwif->OUTBSYNC = &cris_ide_outbsync;
+ 		hwif->INB = &cris_ide_inb;
+ 		hwif->INW = &cris_ide_inw;
+-		hwif->dma_host_off = &cris_dma_off;
+-		hwif->dma_host_on = &cris_dma_on;
+-		hwif->dma_off_quietly = &cris_dma_off;
+ 		hwif->cbl = ATA_CBL_PATA40;
+-		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+-		hwif->pio_mask = ATA_PIO4,
+-		hwif->drives[0].autotune = 1;
+-		hwif->drives[1].autotune = 1;
+-		hwif->ultra_mask = cris_ultra_mask;
+-		hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
 +
-+static struct pci_driver hifn_pci_driver = {
-+	.name     = "hifn795x",
-+	.id_table = hifn_pci_tbl,
-+	.probe    = hifn_probe,
-+	.remove   = __devexit_p(hifn_remove),
-+};
++		idx[h] = hwif->index;
+ 	}
+ 
+ 	/* Reset pulse */
+@@ -823,14 +832,12 @@ init_e100_ide (void)
+ 	cris_ide_set_speed(TYPE_PIO, ATA_PIO4_SETUP, ATA_PIO4_STROBE, ATA_PIO4_HOLD);
+ 	cris_ide_set_speed(TYPE_DMA, 0, ATA_DMA2_STROBE, ATA_DMA2_HOLD);
+ 	cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
+-}
+ 
+-static int cris_dma_on (ide_drive_t *drive)
+-{
++	ide_device_add(idx, &cris_port_info);
 +
-+static int __devinit hifn_init(void)
-+{
-+	unsigned int freq;
-+	int err;
+ 	return 0;
+ }
+ 
+-
+ static cris_dma_descr_type mydescr __attribute__ ((__aligned__(16)));
+ 
+ /*
+@@ -1038,11 +1045,7 @@ static int cris_dma_setup(ide_drive_t *drive)
+ 
+ static void cris_dma_exec_cmd(ide_drive_t *drive, u8 command)
+ {
+-	/* set the irq handler which will finish the request when DMA is done */
+-	ide_set_handler(drive, &cris_dma_intr, WAIT_CMD, NULL);
+-
+-	/* issue cmd to drive */
+-	cris_ide_outb(command, IDE_COMMAND_REG);
++	ide_execute_command(drive, command, &cris_dma_intr, WAIT_CMD, NULL);
+ }
+ 
+ static void cris_dma_start(ide_drive_t *drive)
+@@ -1062,3 +1065,5 @@ static void cris_dma_start(ide_drive_t *drive)
+ 		LED_DISK_READ(1);
+ 	}
+ }
 +
-+	if (strncmp(hifn_pll_ref, "ext", 3) &&
-+	    strncmp(hifn_pll_ref, "pci", 3)) {
-+		printk(KERN_ERR "hifn795x: invalid hifn_pll_ref clock, "
-+				"must be pci or ext");
-+		return -EINVAL;
-+	}
++module_init(init_e100_ide);
+diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile
+new file mode 100644
+index 0000000..5eba16f
+--- /dev/null
++++ b/drivers/ide/h8300/Makefile
+@@ -0,0 +1,2 @@
 +
-+	/*
-+	 * For the 7955/7956 the reference clock frequency must be in the
-+	 * range of 20MHz-100MHz. For the 7954 the upper bound is 66.67MHz,
-+	 * but this chip is currently not supported.
-+	 */
-+	if (hifn_pll_ref[3] != '\0') {
-+		freq = simple_strtoul(hifn_pll_ref + 3, NULL, 10);
-+		if (freq < 20 || freq > 100) {
-+			printk(KERN_ERR "hifn795x: invalid hifn_pll_ref "
-+					"frequency, must be in the range "
-+					"of 20-100");
-+			return -EINVAL;
-+		}
-+	}
++obj-$(CONFIG_IDE_H8300)			+= ide-h8300.o
+diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
+index 4a49b5c..520aec0 100644
+--- a/drivers/ide/h8300/ide-h8300.c
++++ b/drivers/ide/h8300/ide-h8300.c
+@@ -1,5 +1,4 @@
+ /*
+- * drivers/ide/h8300/ide-h8300.c
+  * H8/300 generic IDE interface
+  */
+ 
+@@ -84,11 +83,12 @@ static inline void hwif_setup(ide_hwif_t *hwif)
+ 	hwif->INSL  = NULL;
+ }
+ 
+-void __init h8300_ide_init(void)
++static int __init h8300_ide_init(void)
+ {
+ 	hw_regs_t hw;
+ 	ide_hwif_t *hwif;
+-	int idx;
++	int index;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+ 	if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
+ 		goto out_busy;
+@@ -100,16 +100,28 @@ void __init h8300_ide_init(void)
+ 	hw_setup(&hw);
+ 
+ 	/* register if */
+-	idx = ide_register_hw(&hw, NULL, 1, &hwif);
+-	if (idx == -1) {
++	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif == NULL) {
+ 		printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
+-		return;
++		return -ENOENT;
+ 	}
+ 
++	index = hwif->index;
++	ide_init_port_data(hwif, index);
++	ide_init_port_hw(hwif, &hw);
+ 	hwif_setup(hwif);
+-	printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", idx);
+-	return;
++	printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index);
 +
-+	err = pci_register_driver(&hifn_pci_driver);
-+	if (err < 0) {
-+		dprintk("Failed to register PCI driver for %s device.\n",
-+				hifn_pci_driver.name);
-+		return -ENODEV;
-+	}
++	idx[0] = index;
 +
-+	printk(KERN_INFO "Driver for HIFN 795x crypto accelerator chip "
-+			"has been successfully registered.\n");
++	ide_device_add(idx, NULL);
 +
 +	return 0;
+ 
+ out_busy:
+ 	printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
++
++	return -EBUSY;
+ }
++
++module_init(h8300_ide_init);
+diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
+index 899d565..e07b189 100644
+--- a/drivers/ide/ide-acpi.c
++++ b/drivers/ide/ide-acpi.c
+@@ -1,5 +1,4 @@
+ /*
+- * ide-acpi.c
+  * Provides ACPI support for IDE drives.
+  *
+  * Copyright (C) 2005 Intel Corp.
+@@ -40,7 +39,6 @@ struct GTM_buffer {
+ };
+ 
+ struct ide_acpi_drive_link {
+-	ide_drive_t	*drive;
+ 	acpi_handle	 obj_handle;
+ 	u8		 idbuff[512];
+ };
+@@ -173,7 +171,7 @@ err:
+ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif)
+ {
+ 	struct device		*dev = hwif->gendev.parent;
+-	acpi_handle		dev_handle;
++	acpi_handle		uninitialized_var(dev_handle);
+ 	acpi_integer		pcidevfn;
+ 	acpi_handle		chan_handle;
+ 	int			err;
+@@ -281,16 +279,6 @@ static int do_drive_get_GTF(ide_drive_t *drive,
+ 
+ 	port = hwif->channel ? drive->dn - 2: drive->dn;
+ 
+-	if (!drive->acpidata) {
+-		if (port == 0) {
+-			drive->acpidata = &hwif->acpidata->master;
+-			hwif->acpidata->master.drive = drive;
+-		} else {
+-			drive->acpidata = &hwif->acpidata->slave;
+-			hwif->acpidata->slave.drive = drive;
+-		}
+-	}
+-
+ 	DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
+ 		 hwif->name, dev->bus_id, port, hwif->channel);
+ 
+@@ -383,27 +371,19 @@ static int taskfile_load_raw(ide_drive_t *drive,
+ 	       gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+ 
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.command_type = IDE_DRIVE_TASK_NO_DATA;
+-	args.data_phase   = TASKFILE_NO_DATA;
+-	args.handler      = &task_no_data_intr;
+ 
+ 	/* convert gtf to IDE Taskfile */
+-	args.tfRegister[1] = gtf->tfa[0];	/* 0x1f1 */
+-	args.tfRegister[2] = gtf->tfa[1];	/* 0x1f2 */
+-	args.tfRegister[3] = gtf->tfa[2];	/* 0x1f3 */
+-	args.tfRegister[4] = gtf->tfa[3];	/* 0x1f4 */
+-	args.tfRegister[5] = gtf->tfa[4];	/* 0x1f5 */
+-	args.tfRegister[6] = gtf->tfa[5];	/* 0x1f6 */
+-	args.tfRegister[7] = gtf->tfa[6];	/* 0x1f7 */
++	memcpy(&args.tf_array[7], &gtf->tfa, 7);
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ 
+ 	if (ide_noacpitfs) {
+ 		DEBPRINT("_GTF execution disabled\n");
+ 		return err;
+ 	}
+ 
+-	err = ide_raw_taskfile(drive, &args, NULL);
++	err = ide_no_data_taskfile(drive, &args);
+ 	if (err)
+-		printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
++		printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
+ 		       __FUNCTION__, err);
+ 
+ 	return err;
+@@ -503,7 +483,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive)
+ 
+ 	return ret;
+ }
+-EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs);
+ 
+ /**
+  * ide_acpi_get_timing - get the channel (controller) timings
+@@ -589,7 +568,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
+ 
+ 	kfree(output.pointer);
+ }
+-EXPORT_SYMBOL_GPL(ide_acpi_get_timing);
+ 
+ /**
+  * ide_acpi_push_timing - set the channel (controller) timings
+@@ -643,7 +621,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
+ 	}
+ 	DEBPRINT("_STM status: %d\n", status);
+ }
+-EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
+ 
+ /**
+  * ide_acpi_set_state - set the channel power state
+@@ -697,11 +674,6 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
+  */
+ void ide_acpi_init(ide_hwif_t *hwif)
+ {
+-	int unit;
+-	int			err;
+-	struct ide_acpi_drive_link	*master;
+-	struct ide_acpi_drive_link	*slave;
+-
+ 	ide_acpi_blacklist();
+ 
+ 	hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
+@@ -713,40 +685,38 @@ void ide_acpi_init(ide_hwif_t *hwif)
+ 		DEBPRINT("no ACPI object for %s found\n", hwif->name);
+ 		kfree(hwif->acpidata);
+ 		hwif->acpidata = NULL;
+-		return;
+ 	}
 +}
 +
-+static void __devexit hifn_fini(void)
++void ide_acpi_port_init_devices(ide_hwif_t *hwif)
 +{
-+	pci_unregister_driver(&hifn_pci_driver);
++	ide_drive_t *drive;
++	int i, err;
 +
-+	printk(KERN_INFO "Driver for HIFN 795x crypto accelerator chip "
-+			"has been successfully unregistered.\n");
-+}
++	if (hwif->acpidata == NULL)
++		return;
+ 
+ 	/*
+ 	 * The ACPI spec mandates that we send information
+ 	 * for both drives, regardless whether they are connected
+ 	 * or not.
+ 	 */
+-	hwif->acpidata->master.drive = &hwif->drives[0];
+ 	hwif->drives[0].acpidata = &hwif->acpidata->master;
+-	master = &hwif->acpidata->master;
+-
+-	hwif->acpidata->slave.drive = &hwif->drives[1];
+ 	hwif->drives[1].acpidata = &hwif->acpidata->slave;
+-	slave = &hwif->acpidata->slave;
+-
+ 
+ 	/*
+ 	 * Send IDENTIFY for each drive
+ 	 */
+-	if (master->drive->present) {
+-		err = taskfile_lib_get_identify(master->drive, master->idbuff);
+-		if (err) {
+-			DEBPRINT("identify device %s failed (%d)\n",
+-				 master->drive->name, err);
+-		}
+-	}
++	for (i = 0; i < MAX_DRIVES; i++) {
++		drive = &hwif->drives[i];
 +
-+module_init(hifn_init);
-+module_exit(hifn_fini);
++		if (!drive->present)
++			continue;
+ 
+-	if (slave->drive->present) {
+-		err = taskfile_lib_get_identify(slave->drive, slave->idbuff);
+-		if (err) {
++		err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
++		if (err)
+ 			DEBPRINT("identify device %s failed (%d)\n",
+-				 slave->drive->name, err);
+-		}
++				 drive->name, err);
+ 	}
+ 
+ 	if (ide_noacpionboot) {
+@@ -762,13 +732,11 @@ void ide_acpi_init(ide_hwif_t *hwif)
+ 	ide_acpi_get_timing(hwif);
+ 	ide_acpi_push_timing(hwif);
+ 
+-	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+-		ide_drive_t *drive = &hwif->drives[unit];
++	for (i = 0; i < MAX_DRIVES; i++) {
++		drive = &hwif->drives[i];
+ 
+-		if (drive->present) {
++		if (drive->present)
+ 			/* Execute ACPI startup code */
+ 			ide_acpi_exec_tfs(drive);
+-		}
+ 	}
+ }
+-EXPORT_SYMBOL_GPL(ide_acpi_init);
+diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
+index c7d77f0..5e42c19 100644
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -1,14 +1,14 @@
+ /*
+- * linux/drivers/ide/ide-cd.c
++ * ATAPI CD-ROM driver.
+  *
+- * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder at fnald0.fnal.gov>
+- * Copyright (C) 1996-1998  Erik Andersen <andersee at debian.org>
+- * Copyright (C) 1998-2000  Jens Axboe <axboe at suse.de>
++ * Copyright (C) 1994-1996   Scott Snyder <snyder at fnald0.fnal.gov>
++ * Copyright (C) 1996-1998   Erik Andersen <andersee at debian.org>
++ * Copyright (C) 1998-2000   Jens Axboe <axboe at suse.de>
++ * Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
+  *
+  * May be copied or modified under the terms of the GNU General Public
+  * License.  See linux/COPYING for more information.
+  *
+- * ATAPI CD-ROM driver.  To be used with ide.c.
+  * See Documentation/cdrom/ide-cd for usage information.
+  *
+  * Suggestions are welcome. Patches that work are more welcome though. ;-)
+@@ -19,287 +19,11 @@
+  * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+  * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
+  *
+- * Drives that deviate from these standards will be accommodated as much
+- * as possible via compile time or command-line options.  Since I only have
+- * a few drives, you generally need to send me patches...
+- *
+- * ----------------------------------
+- * TO DO LIST:
+- * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
+- *   boot
+- *
+- * ----------------------------------
+- * 1.00  Oct 31, 1994 -- Initial version.
+- * 1.01  Nov  2, 1994 -- Fixed problem with starting request in
+- *                       cdrom_check_status.
+- * 1.03  Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
+- * (from mlord)       -- minor changes to cdrom_setup()
+- *                    -- renamed ide_dev_s to ide_drive_t, enable irq on command
+- * 2.00  Nov 27, 1994 -- Generalize packet command interface;
+- *                       add audio ioctls.
+- * 2.01  Dec  3, 1994 -- Rework packet command interface to handle devices
+- *                       which send an interrupt when ready for a command.
+- * 2.02  Dec 11, 1994 -- Cache the TOC in the driver.
+- *                       Don't use SCMD_PLAYAUDIO_TI; it's not included
+- *                       in the current version of ATAPI.
+- *                       Try to use LBA instead of track or MSF addressing
+- *                       when possible.
+- *                       Don't wait for READY_STAT.
+- * 2.03  Jan 10, 1995 -- Rewrite block read routines to handle block sizes
+- *                       other than 2k and to move multiple sectors in a
+- *                       single transaction.
+- * 2.04  Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
+- *                       Thanks to Nick Saw <cwsaw at pts7.pts.mot.com> for
+- *                       help in figuring this out.  Ditto for Acer and
+- *                       Aztech drives, which seem to have the same problem.
+- * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
+- * 2.05  Jun  8, 1995 -- Don't attempt to retry after an illegal request
+- *                        or data protect error.
+- *                       Use HWIF and DEV_HWIF macros as in ide.c.
+- *                       Always try to do a request_sense after
+- *                        a failed command.
+- *                       Include an option to give textual descriptions
+- *                        of ATAPI errors.
+- *                       Fix a bug in handling the sector cache which
+- *                        showed up if the drive returned data in 512 byte
+- *                        blocks (like Pioneer drives).  Thanks to
+- *                        Richard Hirst <srh at gpt.co.uk> for diagnosing this.
+- *                       Properly supply the page number field in the
+- *                        MODE_SELECT command.
+- *                       PLAYAUDIO12 is broken on the Aztech; work around it.
+- * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
+- *                       (my apologies to Scott, but now ide-cd.c is independent)
+- * 3.00  Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
+- *                       Implement CDROMREADAUDIO ioctl (UNTESTED).
+- *                       Use input_ide_data() and output_ide_data().
+- *                       Add door locking.
+- *                       Fix usage count leak in cdrom_open, which happened
+- *                        when a read-write mount was attempted.
+- *                       Try to load the disk on open.
+- *                       Implement CDROMEJECT_SW ioctl (off by default).
+- *                       Read total cdrom capacity during open.
+- *                       Rearrange logic in cdrom_decode_status.  Issue
+- *                        request sense commands for failed packet commands
+- *                        from here instead of from cdrom_queue_packet_command.
+- *                        Fix a race condition in retrieving error information.
+- *                       Suppress printing normal unit attention errors and
+- *                        some drive not ready errors.
+- *                       Implement CDROMVOLREAD ioctl.
+- *                       Implement CDROMREADMODE1/2 ioctls.
+- *                       Fix race condition in setting up interrupt handlers
+- *                        when the `serialize' option is used.
+- * 3.01  Sep  2, 1995 -- Fix ordering of reenabling interrupts in
+- *                        cdrom_queue_request.
+- *                       Another try at using ide_[input,output]_data.
+- * 3.02  Sep 16, 1995 -- Stick total disk capacity in partition table as well.
+- *                       Make VERBOSE_IDE_CD_ERRORS dump failed command again.
+- *                       Dump out more information for ILLEGAL REQUEST errs.
+- *                       Fix handling of errors occurring before the
+- *                        packet command is transferred.
+- *                       Fix transfers with odd bytelengths.
+- * 3.03  Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
+- *                       `DCI-2S10' drives are broken too.
+- * 3.04  Nov 20, 1995 -- So are Vertos drives.
+- * 3.05  Dec  1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
+- * 3.06  Dec 16, 1995 -- Add support needed for partitions.
+- *                       More workarounds for Vertos bugs (based on patches
+- *                        from Holger Dietze <dietze at aix520.informatik.uni-leipzig.de>).
+- *                       Try to eliminate byteorder assumptions.
+- *                       Use atapi_cdrom_subchnl struct definition.
+- *                       Add STANDARD_ATAPI compilation option.
+- * 3.07  Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
+- *                        Vertos 300.
+- *                       Add NO_DOOR_LOCKING configuration option.
+- *                       Handle drive_cmd requests w/NULL args (for hdparm -t).
+- *                       Work around sporadic Sony55e audio play problem.
+- * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
+- *                        problem with "hde=cdrom" with no drive present.  -ml
+- * 3.08  Mar  6, 1996 -- More Vertos workarounds.
+- * 3.09  Apr  5, 1996 -- Add CDROMCLOSETRAY ioctl.
+- *                       Switch to using MSF addressing for audio commands.
+- *                       Reformat to match kernel tabbing style.
+- *                       Add CDROM_GET_UPC ioctl.
+- * 3.10  Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
+- * 3.11  Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko at colossus.escape.de>
+- *                       to remove redundant verify_area calls.
+- * 3.12  May  7, 1996 -- Rudimentary changer support.  Based on patches
+- *                        from Gerhard Zuber <zuber at berlin.snafu.de>.
+- *                       Let open succeed even if there's no loaded disc.
+- * 3.13  May 19, 1996 -- Fixes for changer code.
+- * 3.14  May 29, 1996 -- Add work-around for Vertos 600.
+- *                        (From Hennus Bergman <hennus at sky.ow.nl>.)
+- * 3.15  July 2, 1996 -- Added support for Sanyo 3 CD changers
+- *                        from Ben Galliart <bgallia at luc.edu> with 
+- *                        special help from Jeff Lightfoot 
+- *                        <jeffml at pobox.com>
+- * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
+- * 3.16  Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
+- * 3.17  Sep 17, 1996 -- Tweak audio reads for some drives.
+- *                       Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
+- * 3.18  Oct 31, 1996 -- Added module and DMA support.
+- *                       
+- *                       
+- * 4.00  Nov 5, 1996   -- New ide-cd maintainer,
+- *                                 Erik B. Andersen <andersee at debian.org>
+- *                     -- Newer Creative drives don't always set the error
+- *                          register correctly.  Make sure we see media changes
+- *                          regardless.
+- *                     -- Integrate with generic cdrom driver.
+- *                     -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
+- *                          a patch from Ciro Cattuto <>.
+- *                     -- Call set_device_ro.
+- *                     -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
+- *                          ioctls, based on patch by Erik Andersen
+- *                     -- Add some probes of drive capability during setup.
+- *
+- * 4.01  Nov 11, 1996  -- Split into ide-cd.c and ide-cd.h
+- *                     -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE 
+- *                          ioctls in favor of a generalized approach 
+- *                          using the generic cdrom driver.
+- *                     -- Fully integrated with the 2.1.X kernel.
+- *                     -- Other stuff that I forgot (lots of changes)
+- *
+- * 4.02  Dec 01, 1996  -- Applied patch from Gadi Oxman <gadio at netvision.net.il>
+- *                          to fix the drive door locking problems.
+- *
+- * 4.03  Dec 04, 1996  -- Added DSC overlap support.
+- * 4.04  Dec 29, 1996  -- Added CDROMREADRAW ioclt based on patch 
+- *                          by Ales Makarov (xmakarov at sun.felk.cvut.cz)
+- *
+- * 4.05  Nov 20, 1997  -- Modified to print more drive info on init
+- *                        Minor other changes
+- *                        Fix errors on CDROMSTOP (If you have a "Dolphin",
+- *                          you must define IHAVEADOLPHIN)
+- *                        Added identifier so new Sanyo CD-changer works
+- *                        Better detection if door locking isn't supported
+- *
+- * 4.06  Dec 17, 1997  -- fixed endless "tray open" messages  -ml
+- * 4.07  Dec 17, 1997  -- fallback to set pc->stat on "tray open"
+- * 4.08  Dec 18, 1997  -- spew less noise when tray is empty
+- *                     -- fix speed display for ACER 24X, 18X
+- * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
+- *                         an end of file instead of an I/O error (Gadi)
+- * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
+- *                         slot when there is no disc in the current slot.
+- *                     -- Fixed a memory leak where info->changer_info was
+- *                         malloc'ed but never free'd when closing the device.
+- *                     -- Cleaned up the global namespace a bit by making more
+- *                         functions static that should already have been.
+- * 4.11  Mar 12, 1998  -- Added support for the CDROM_SELECT_SPEED ioctl
+- *                         based on a patch for 2.0.33 by Jelle Foks 
+- *                         <jelle at scintilla.utwente.nl>, a patch for 2.0.33
+- *                         by Toni Giorgino <toni at pcape2.pi.infn.it>, the SCSI
+- *                         version, and my own efforts.  -erik
+- *                     -- Fixed a stupid bug which egcs was kind enough to
+- *                         inform me of where "Illegal mode for this track"
+- *                         was never returned due to a comparison on data
+- *                         types of limited range.
+- * 4.12  Mar 29, 1998  -- Fixed bug in CDROM_SELECT_SPEED so write speed is 
+- *                         now set ionly for CD-R and CD-RW drives.  I had 
+- *                         removed this support because it produced errors.
+- *                         It produced errors _only_ for non-writers. duh.
+- * 4.13  May 05, 1998  -- Suppress useless "in progress of becoming ready"
+- *                         messages, since this is not an error.
+- *                     -- Change error messages to be const
+- *                     -- Remove a "\t" which looks ugly in the syslogs
+- * 4.14  July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
+- *                         since the .pdf version doesn't seem to work...
+- *                     -- Updated the TODO list to something more current.
+- *
+- * 4.15  Aug 25, 1998  -- Updated ide-cd.h to respect mechine endianess, 
+- *                         patch thanks to "Eddie C. Dost" <ecd at skynet.be>
+- *
+- * 4.50  Oct 19, 1998  -- New maintainers!
+- *                         Jens Axboe <axboe at image.dk>
+- *                         Chris Zwilling <chris at cloudnet.com>
+- *
+- * 4.51  Dec 23, 1998  -- Jens Axboe <axboe at image.dk>
+- *                      - ide_cdrom_reset enabled since the ide subsystem
+- *                         handles resets fine now. <axboe at image.dk>
+- *                      - Transfer size fix for Samsung CD-ROMs, thanks to
+- *                        "Ville Hallik" <ville.hallik at mail.ee>.
+- *                      - other minor stuff.
+- *
+- * 4.52  Jan 19, 1999  -- Jens Axboe <axboe at image.dk>
+- *                      - Detect DVD-ROM/RAM drives
+- *
+- * 4.53  Feb 22, 1999   - Include other model Samsung and one Goldstar
+- *                         drive in transfer size limit.
+- *                      - Fix the I/O error when doing eject without a medium
+- *                         loaded on some drives.
+- *                      - CDROMREADMODE2 is now implemented through
+- *                         CDROMREADRAW, since many drives don't support
+- *                         MODE2 (even though ATAPI 2.6 says they must).
+- *                      - Added ignore parameter to ide-cd (as a module), eg
+- *                         	insmod ide-cd ignore='hda hdb'
+- *                         Useful when using ide-cd in conjunction with
+- *                         ide-scsi. TODO: non-modular way of doing the
+- *                         same.
+- *
+- * 4.54  Aug 5, 1999	- Support for MMC2 class commands through the generic
+- *			  packet interface to cdrom.c.
+- *			- Unified audio ioctl support, most of it.
+- *			- cleaned up various deprecated verify_area().
+- *			- Added ide_cdrom_packet() as the interface for
+- *			  the Uniform generic_packet().
+- *			- bunch of other stuff, will fill in logs later.
+- *			- report 1 slot for non-changers, like the other
+- *			  cd-rom drivers. don't report select disc for
+- *			  non-changers as well.
+- *			- mask out audio playing, if the device can't do it.
+- *
+- * 4.55  Sep 1, 1999	- Eliminated the rest of the audio ioctls, except
+- *			  for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
+- *			  use this independently of the actual audio handling.
+- *			  They will disappear later when I get the time to
+- *			  do it cleanly.
+- *			- Minimize the TOC reading - only do it when we
+- *			  know a media change has occurred.
+- *			- Moved all the CDROMREADx ioctls to the Uniform layer.
+- *			- Heiko Eißfeldt <heiko at colossus.escape.de> supplied
+- *			  some fixes for CDI.
+- *			- CD-ROM leaving door locked fix from Andries
+- *			  Brouwer <Andries.Brouwer at cwi.nl>
+- *			- Erik Andersen <andersen at xmission.com> unified
+- *			  commands across the various drivers and how
+- *			  sense errors are handled.
+- *
+- * 4.56  Sep 12, 1999	- Removed changer support - it is now in the
+- *			  Uniform layer.
+- *			- Added partition based multisession handling.
+- *			- Mode sense and mode select moved to the
+- *			  Uniform layer.
+- *			- Fixed a problem with WPI CDS-32X drive - it
+- *			  failed the capabilities 
+- *
+- * 4.57  Apr 7, 2000	- Fixed sense reporting.
+- *			- Fixed possible oops in ide_cdrom_get_last_session()
+- *			- Fix locking mania and make ide_cdrom_reset relock
+- *			- Stop spewing errors to log when magicdev polls with
+- *			  TEST_UNIT_READY on some drives.
+- *			- Various fixes from Tobias Ringstrom:
+- *			  tray if it was locked prior to the reset.
+- *			  - cdrom_read_capacity returns one frame too little.
+- *			  - Fix real capacity reporting.
+- *
+- * 4.58  May 1, 2000	- Clean up ACER50 stuff.
+- *			- Fix small problem with ide_cdrom_capacity
+- *
+- * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
+- *			  correctly sensing a disc change.
+- *			- Rearranged some code
+- *			- Use extended sense on drives that support it for
+- *			  correctly reporting tray status -- from
+- *			  Michael D Johnson <johnsom at orst.edu>
+- * 4.60  Dec 17, 2003	- Add mt rainier support
+- *			- Bump timeout for packet commands, matches sr
+- *			- Odd stuff
+- * 4.61  Jan 22, 2004	- support hardware sector sizes other than 2kB,
+- *			  Pascal Schmidt <der.eremit at email.de>
+- *
+- *************************************************************************/
+- 
+-#define IDECD_VERSION "4.61"
++ * For historical changelog please see:
++ *	Documentation/ide/ChangeLog.ide-cd.1994-2004
++ */
 +
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Evgeniy Polyakov <johnpol at 2ka.mipt.ru>");
-+MODULE_DESCRIPTION("Driver for HIFN 795x crypto accelerator chip.");
-diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
-index 5f7e718..2f3ad3f 100644
---- a/drivers/crypto/padlock-aes.c
-+++ b/drivers/crypto/padlock-aes.c
-@@ -44,6 +44,7 @@
-  */
++#define IDECD_VERSION "5.00"
  
- #include <crypto/algapi.h>
-+#include <crypto/aes.h>
  #include <linux/module.h>
- #include <linux/init.h>
  #include <linux/types.h>
-@@ -53,9 +54,6 @@
- #include <asm/byteorder.h>
- #include "padlock.h"
- 
--#define AES_MIN_KEY_SIZE	16	/* in uint8_t units */
--#define AES_MAX_KEY_SIZE	32	/* ditto */
--#define AES_BLOCK_SIZE		16	/* ditto */
- #define AES_EXTENDED_KEY_SIZE	64	/* in uint32_t units */
- #define AES_EXTENDED_KEY_SIZE_B	(AES_EXTENDED_KEY_SIZE * sizeof(uint32_t))
+@@ -313,6 +37,7 @@
+ #include <linux/ide.h>
+ #include <linux/completion.h>
+ #include <linux/mutex.h>
++#include <linux/bcd.h>
  
-@@ -419,6 +417,11 @@ static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
- /* ====== Encryption/decryption routines ====== */
+ #include <scsi/scsi.h>	/* For SCSI -> ATAPI command conversion */
  
- /* These are the real call to PadLock. */
-+static inline void padlock_reset_key(void)
-+{
-+	asm volatile ("pushfl; popfl");
-+}
-+
- static inline void padlock_xcrypt(const u8 *input, u8 *output, void *key,
- 				  void *control_word)
- {
-@@ -439,8 +442,6 @@ static void aes_crypt_copy(const u8 *in, u8 *out, u32 *key, struct cword *cword)
- static inline void aes_crypt(const u8 *in, u8 *out, u32 *key,
- 			     struct cword *cword)
+@@ -360,11 +85,11 @@ static void ide_cd_put(struct cdrom_info *cd)
+    buffers. */
+ static void cdrom_saw_media_change (ide_drive_t *drive)
  {
--	asm volatile ("pushfl; popfl");
+-	struct cdrom_info *info = drive->driver_data;
+-	
+-	CDROM_STATE_FLAGS (drive)->media_changed = 1;
+-	CDROM_STATE_FLAGS (drive)->toc_valid = 0;
+-	info->nsectors_buffered = 0;
++	struct cdrom_info *cd = drive->driver_data;
++
++	cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
++	cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
++	cd->nsectors_buffered = 0;
+ }
+ 
+ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
+@@ -465,134 +190,14 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
+ 			}
+  		}
+  	}
+-#if VERBOSE_IDE_CD_ERRORS
+-	{
+-		int i;
+-		const char *s = "bad sense key!";
+-		char buf[80];
 -
- 	/* padlock_xcrypt requires at least two blocks of data. */
- 	if (unlikely(!(((unsigned long)in ^ (PAGE_SIZE - AES_BLOCK_SIZE)) &
- 		       (PAGE_SIZE - 1)))) {
-@@ -459,7 +460,6 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
- 		return;
- 	}
+-		printk ("ATAPI device %s:\n", drive->name);
+-		if (sense->error_code==0x70)
+-			printk("  Error: ");
+-		else if (sense->error_code==0x71)
+-			printk("  Deferred Error: ");
+-		else if (sense->error_code == 0x7f)
+-			printk("  Vendor-specific Error: ");
+-		else
+-			printk("  Unknown Error Type: ");
+-
+-		if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
+-			s = sense_key_texts[sense->sense_key];
+-
+-		printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
+-
+-		if (sense->asc == 0x40) {
+-			sprintf(buf, "Diagnostic failure on component 0x%02x",
+-				 sense->ascq);
+-			s = buf;
+-		} else {
+-			int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
+-			unsigned long key = (sense->sense_key << 16);
+-			key |= (sense->asc << 8);
+-			if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
+-				key |= sense->ascq;
+-			s = NULL;
+-
+-			while (hi > lo) {
+-				mid = (lo + hi) / 2;
+-				if (sense_data_texts[mid].asc_ascq == key ||
+-				    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
+-					s = sense_data_texts[mid].text;
+-					break;
+-				}
+-				else if (sense_data_texts[mid].asc_ascq > key)
+-					hi = mid;
+-				else
+-					lo = mid+1;
+-			}
+-		}
+-
+-		if (s == NULL) {
+-			if (sense->asc > 0x80)
+-				s = "(vendor-specific error)";
+-			else
+-				s = "(reserved error code)";
+-		}
+-
+-		printk(KERN_ERR "  %s -- (asc=0x%02x, ascq=0x%02x)\n",
+-			s, sense->asc, sense->ascq);
+-
+-		if (failed_command != NULL) {
+-
+-			int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
+-			s = NULL;
+-
+-			while (hi > lo) {
+-				mid = (lo + hi) / 2;
+-				if (packet_command_texts[mid].packet_command ==
+-				    failed_command->cmd[0]) {
+-					s = packet_command_texts[mid].text;
+-					break;
+-				}
+-				if (packet_command_texts[mid].packet_command >
+-				    failed_command->cmd[0])
+-					hi = mid;
+-				else
+-					lo = mid+1;
+-			}
+-
+-			printk (KERN_ERR "  The failed \"%s\" packet command was: \n  \"", s);
+-			for (i=0; i<sizeof (failed_command->cmd); i++)
+-				printk ("%02x ", failed_command->cmd[i]);
+-			printk ("\"\n");
+-		}
+-
+-		/* The SKSV bit specifies validity of the sense_key_specific
+-		 * in the next two commands. It is bit 7 of the first byte.
+-		 * In the case of NOT_READY, if SKSV is set the drive can
+-		 * give us nice ETA readings.
+-		 */
+-		if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
+-			int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
+-			printk(KERN_ERR "  Command is %02d%% complete\n", progress / 0xffff);
+-
+-		}
+-
+-		if (sense->sense_key == ILLEGAL_REQUEST &&
+-		    (sense->sks[0] & 0x80) != 0) {
+-			printk(KERN_ERR "  Error in %s byte %d",
+-				(sense->sks[0] & 0x40) != 0 ?
+-				"command packet" : "command data",
+-				(sense->sks[1] << 8) + sense->sks[2]);
  
--	asm volatile ("pushfl; popfl");		/* enforce key reload. */
- 	asm volatile ("test $1, %%cl;"
- 		      "je 1f;"
- 		      "lea -1(%%ecx), %%eax;"
-@@ -476,8 +476,6 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key,
- static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
- 				     u8 *iv, void *control_word, u32 count)
- {
--	/* Enforce key reload. */
--	asm volatile ("pushfl; popfl");
- 	/* rep xcryptcbc */
- 	asm volatile (".byte 0xf3,0x0f,0xa7,0xd0"
- 		      : "+S" (input), "+D" (output), "+a" (iv)
-@@ -488,12 +486,14 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key,
- static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
- {
- 	struct aes_ctx *ctx = aes_ctx(tfm);
-+	padlock_reset_key();
- 	aes_crypt(in, out, ctx->E, &ctx->cword.encrypt);
+-			if ((sense->sks[0] & 0x40) != 0)
+-				printk (" bit %d", sense->sks[0] & 0x07);
+-
+-			printk ("\n");
+-		}
+-	}
+-
+-#else /* not VERBOSE_IDE_CD_ERRORS */
+-
+-	/* Suppress printing unit attention and `in progress of becoming ready'
+-	   errors when we're not being verbose. */
+-
+-	if (sense->sense_key == UNIT_ATTENTION ||
+-	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
+-						sense->asc == 0x3a)))
+-		return;
+-
+-	printk(KERN_ERR "%s: error code: 0x%02x  sense_key: 0x%02x  asc: 0x%02x  ascq: 0x%02x\n",
+-		drive->name,
+-		sense->error_code, sense->sense_key,
+-		sense->asc, sense->ascq);
+-#endif /* not VERBOSE_IDE_CD_ERRORS */
++	ide_cd_log_error(drive->name, failed_command, sense);
  }
  
- static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
+ /*
+  * Initialize a ide-cd packet command request
+  */
+-static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
++void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
  {
- 	struct aes_ctx *ctx = aes_ctx(tfm);
-+	padlock_reset_key();
- 	aes_crypt(in, out, ctx->D, &ctx->cword.decrypt);
- }
+ 	struct cdrom_info *cd = drive->driver_data;
  
-@@ -526,6 +526,8 @@ static int ecb_aes_encrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err;
+@@ -611,7 +216,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
+ 		sense = &info->sense_data;
  
-+	padlock_reset_key();
+ 	/* stuff the sense request in front of our current request */
+-	cdrom_prepare_request(drive, rq);
++	ide_cd_init_rq(drive, rq);
+ 
+ 	rq->data = sense;
+ 	rq->cmd[0] = GPCMD_REQUEST_SENSE;
+@@ -655,9 +260,9 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
+ 					BUG();
+ 			} else {
+ 				spin_lock_irqsave(&ide_lock, flags);
+-				end_that_request_chunk(failed, 0,
+-							failed->data_len);
+-				end_that_request_last(failed, 0);
++				if (__blk_end_request(failed, -EIO,
++						      failed->data_len))
++					BUG();
+ 				spin_unlock_irqrestore(&ide_lock, flags);
+ 			}
+ 		} else
+@@ -690,7 +295,8 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 	int stat, err, sense_key;
+ 	
+ 	/* Check for errors. */
+-	stat = HWIF(drive)->INB(IDE_STATUS_REG);
++	stat = ide_read_status(drive);
 +
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
+ 	if (stat_ret)
+ 		*stat_ret = stat;
  
-@@ -548,6 +550,8 @@ static int ecb_aes_decrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err;
+@@ -698,7 +304,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 		return 0;
  
-+	padlock_reset_key();
-+
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
+ 	/* Get the IDE error register. */
+-	err = HWIF(drive)->INB(IDE_ERROR_REG);
++	err = ide_read_error(drive);
+ 	sense_key = err >> 4;
  
-@@ -592,6 +596,8 @@ static int cbc_aes_encrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err;
+ 	if (rq == NULL) {
+@@ -718,7 +324,6 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
  
-+	padlock_reset_key();
+ 	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
+ 		/* All other functions, except for READ. */
+-		unsigned long flags;
+ 
+ 		/*
+ 		 * if we have an error, pass back CHECK_CONDITION as the
+@@ -756,15 +361,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 		 * remove failed request completely and end it when the
+ 		 * request sense has completed
+ 		 */
+-		if (stat & ERR_STAT) {
+-			spin_lock_irqsave(&ide_lock, flags);
+-			blkdev_dequeue_request(rq);
+-			HWGROUP(drive)->rq = NULL;
+-			spin_unlock_irqrestore(&ide_lock, flags);
+-
+-			cdrom_queue_request_sense(drive, rq->sense, rq);
+-		} else
+-			cdrom_end_request(drive, 0);
++		goto end_request;
+ 
+ 	} else if (blk_fs_request(rq)) {
+ 		int do_end_request = 0;
+@@ -844,23 +441,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 		   sense data. We need this in order to perform end of media
+ 		   processing */
+ 
+-		if (do_end_request) {
+-			if (stat & ERR_STAT) {
+-				unsigned long flags;
+-				spin_lock_irqsave(&ide_lock, flags);
+-				blkdev_dequeue_request(rq);
+-				HWGROUP(drive)->rq = NULL;
+-				spin_unlock_irqrestore(&ide_lock, flags);
++		if (do_end_request)
++			goto end_request;
+ 
+-				cdrom_queue_request_sense(drive, rq->sense, rq);
+-			} else
+-				cdrom_end_request(drive, 0);
+-		} else {
+-			/* If we got a CHECK_CONDITION status,
+-			   queue a request sense command. */
+-			if (stat & ERR_STAT)
+-				cdrom_queue_request_sense(drive, NULL, NULL);
+-		}
++		/*
++		 * If we got a CHECK_CONDITION status,
++		 * queue a request sense command.
++		 */
++		if (stat & ERR_STAT)
++			cdrom_queue_request_sense(drive, NULL, NULL);
+ 	} else {
+ 		blk_dump_rq_flags(rq, "ide-cd: bad rq");
+ 		cdrom_end_request(drive, 0);
+@@ -868,6 +457,21 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 
+ 	/* Retry, or handle the next request. */
+ 	return 1;
 +
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
++end_request:
++	if (stat & ERR_STAT) {
++		unsigned long flags;
++
++		spin_lock_irqsave(&ide_lock, flags);
++		blkdev_dequeue_request(rq);
++		HWGROUP(drive)->rq = NULL;
++		spin_unlock_irqrestore(&ide_lock, flags);
++
++		cdrom_queue_request_sense(drive, rq->sense, rq);
++	} else
++		cdrom_end_request(drive, 0);
++
++	return 1;
+ }
  
-@@ -616,6 +622,8 @@ static int cbc_aes_decrypt(struct blkcipher_desc *desc,
- 	struct blkcipher_walk walk;
- 	int err;
+ static int cdrom_timer_expiry(ide_drive_t *drive)
+@@ -917,21 +521,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+ 	if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
+ 		return startstop;
  
-+	padlock_reset_key();
++	/* FIXME: for Virtual DMA we must check harder */
+ 	if (info->dma)
+ 		info->dma = !hwif->dma_setup(drive);
+ 
+ 	/* Set up the controller registers. */
+-	/* FIXME: for Virtual DMA we must check harder */
+-	HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG);
+-	HWIF(drive)->OUTB(0, IDE_IREASON_REG);
+-	HWIF(drive)->OUTB(0, IDE_SECTOR_REG);
+-
+-	HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG);
+-	HWIF(drive)->OUTB(xferlen >> 8  , IDE_BCOUNTH_REG);
+-	if (IDE_CONTROL_REG)
+-		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
+- 
+-	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
++	ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
++			   IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
 +
- 	blkcipher_walk_init(&walk, dst, src, nbytes);
- 	err = blkcipher_walk_virt(desc, &walk);
++	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ 		/* waiting for CDB interrupt, not DMA yet. */
+ 		if (info->dma)
+ 			drive->waiting_for_dma = 0;
+@@ -957,10 +555,6 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
+    by cdrom_start_packet_command.
+    HANDLER is the interrupt handler to call when the command completes
+    or there's data ready. */
+-/*
+- * changed 5 parameters to 3 for dvd-ram
+- * struct packet_command *pc; now packet_command_t *pc;
+- */
+ #define ATAPI_MIN_CDB_BYTES 12
+ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+ 					  struct request *rq,
+@@ -971,7 +565,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+ 	struct cdrom_info *info = drive->driver_data;
+ 	ide_startstop_t startstop;
  
-diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
-index d59b2f4..bcf52df 100644
---- a/drivers/dma/dmaengine.c
-+++ b/drivers/dma/dmaengine.c
-@@ -41,12 +41,12 @@
-  * the definition of dma_event_callback in dmaengine.h.
-  *
-  * Each device has a kref, which is initialized to 1 when the device is
-- * registered. A kref_get is done for each class_device registered.  When the
-- * class_device is released, the coresponding kref_put is done in the release
-+ * registered. A kref_get is done for each device registered.  When the
-+ * device is released, the coresponding kref_put is done in the release
-  * method. Every time one of the device's channels is allocated to a client,
-  * a kref_get occurs.  When the channel is freed, the coresponding kref_put
-  * happens. The device's release function does a completion, so
-- * unregister_device does a remove event, class_device_unregister, a kref_put
-+ * unregister_device does a remove event, device_unregister, a kref_put
-  * for the first reference, then waits on the completion for all other
-  * references to finish.
-  *
-@@ -77,9 +77,9 @@ static LIST_HEAD(dma_client_list);
+-	if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) {
++	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
+ 		/* Here we should have been called after receiving an interrupt
+ 		   from the device.  DRQ should how be set. */
  
- /* --- sysfs implementation --- */
+@@ -1011,6 +605,25 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
+  * Block read functions.
+  */
  
--static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
-+static ssize_t show_memcpy_count(struct device *dev, struct device_attribute *attr, char *buf)
- {
--	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
-+	struct dma_chan *chan = to_dma_chan(dev);
- 	unsigned long count = 0;
- 	int i;
++static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
++{
++	while (len > 0) {
++		int dum = 0;
++		xf(drive, &dum, sizeof(dum));
++		len -= sizeof(dum);
++	}
++}
++
++static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
++{
++	while (nsects > 0) {
++		static char dum[SECTOR_SIZE];
++
++		drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
++		nsects--;
++	}
++}
++
+ /*
+  * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
+  * buffer.  Once the first sector is added, any subsequent sectors are
+@@ -1049,11 +662,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
+ 	}
  
-@@ -89,9 +89,10 @@ static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
- 	return sprintf(buf, "%lu\n", count);
+ 	/* Throw away any remaining data. */
+-	while (sectors_to_transfer > 0) {
+-		static char dum[SECTOR_SIZE];
+-		HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
+-		--sectors_to_transfer;
+-	}
++	ide_cd_drain_data(drive, sectors_to_transfer);
  }
  
--static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
-+static ssize_t show_bytes_transferred(struct device *dev, struct device_attribute *attr,
-+				      char *buf)
+ /*
+@@ -1062,27 +671,29 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
+  * ok; nonzero if the request has been terminated.
+  */
+ static
+-int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
++int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw)
  {
--	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
-+	struct dma_chan *chan = to_dma_chan(dev);
- 	unsigned long count = 0;
- 	int i;
+-	if (ireason == 2)
++	/*
++	 * ireason == 0: the drive wants to receive data from us
++	 * ireason == 2: the drive is expecting to transfer data to us
++	 */
++	if (ireason == (!rw << 1))
+ 		return 0;
+-	else if (ireason == 0) {
+-		/* Whoops... The drive is expecting to receive data from us! */
++	else if (ireason == (rw << 1)) {
++		ide_hwif_t *hwif = drive->hwif;
++		xfer_func_t *xf;
++
++		/* Whoops... */
+ 		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+ 				drive->name, __FUNCTION__);
  
-@@ -101,9 +102,9 @@ static ssize_t show_bytes_transferred(struct class_device *cd, char *buf)
- 	return sprintf(buf, "%lu\n", count);
+-		/* Throw some data at the drive so it doesn't hang
+-		   and quit this request. */
+-		while (len > 0) {
+-			int dum = 0;
+-			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof (dum));
+-			len -= sizeof (dum);
+-		}
+-	} else  if (ireason == 1) {
++		xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
++		ide_cd_pad_transfer(drive, xf, len);
++	} else  if (rw == 0 && ireason == 1) {
+ 		/* Some drives (ASUS) seem to tell us that status
+ 		 * info is available. just get it and ignore.
+ 		 */
+-		(void) HWIF(drive)->INB(IDE_STATUS_REG);
++		(void)ide_read_status(drive);
+ 		return 0;
+ 	} else {
+ 		/* Drive wants a command packet, or invalid ireason... */
+@@ -1095,137 +706,28 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
  }
  
--static ssize_t show_in_use(struct class_device *cd, char *buf)
-+static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, char *buf)
+ /*
+- * Interrupt routine.  Called when a read request has completed.
++ * Assume that the drive will always provide data in multiples of at least
++ * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
+  */
+-static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
++static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
  {
--	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
-+	struct dma_chan *chan = to_dma_chan(dev);
- 	int in_use = 0;
+-	int stat;
+-	int ireason, len, sectors_to_transfer, nskip;
+-	struct cdrom_info *info = drive->driver_data;
+-	u8 lowcyl = 0, highcyl = 0;
+-	int dma = info->dma, dma_error = 0;
+-
+-	struct request *rq = HWGROUP(drive)->rq;
+-
+-	/*
+-	 * handle dma case
+-	 */
+-	if (dma) {
+-		info->dma = 0;
+-		dma_error = HWIF(drive)->ide_dma_end(drive);
+-		if (dma_error) {
+-			printk(KERN_ERR "%s: DMA read error\n", drive->name);
+-			ide_dma_off(drive);
+-		}
+-	}
+-
+-	if (cdrom_decode_status(drive, 0, &stat))
+-		return ide_stopped;
+-
+-	if (dma) {
+-		if (!dma_error) {
+-			ide_end_request(drive, 1, rq->nr_sectors);
+-			return ide_stopped;
+-		} else
+-			return ide_error(drive, "dma error", stat);
+-	}
+-
+-	/* Read the interrupt reason and the transfer length. */
+-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
+-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
+-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
+-
+-	len = lowcyl + (256 * highcyl);
+-
+-	/* If DRQ is clear, the command has completed. */
+-	if ((stat & DRQ_STAT) == 0) {
+-		/* If we're not done filling the current buffer, complain.
+-		   Otherwise, complete the command normally. */
+-		if (rq->current_nr_sectors > 0) {
+-			printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
+-				drive->name, rq->current_nr_sectors);
+-			rq->cmd_flags |= REQ_FAILED;
+-			cdrom_end_request(drive, 0);
+-		} else
+-			cdrom_end_request(drive, 1);
+-		return ide_stopped;
+-	}
+-
+-	/* Check that the drive is expecting to do the same thing we are. */
+-	if (cdrom_read_check_ireason (drive, len, ireason))
+-		return ide_stopped;
+-
+-	/* Assume that the drive will always provide data in multiples
+-	   of at least SECTOR_SIZE, as it gets hairy to keep track
+-	   of the transfers otherwise. */
+-	if ((len % SECTOR_SIZE) != 0) {
+-		printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n",
+-			drive->name, len);
+-		if (CDROM_CONFIG_FLAGS(drive)->limit_nframes)
+-			printk (KERN_ERR "  This drive is not supported by this version of the driver\n");
+-		else {
+-			printk (KERN_ERR "  Trying to limit transfer sizes\n");
+-			CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
+-		}
+-		cdrom_end_request(drive, 0);
+-		return ide_stopped;
+-	}
+-
+-	/* The number of sectors we need to read from the drive. */
+-	sectors_to_transfer = len / SECTOR_SIZE;
+-
+-	/* First, figure out if we need to bit-bucket
+-	   any of the leading sectors. */
+-	nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer);
+-
+-	while (nskip > 0) {
+-		/* We need to throw away a sector. */
+-		static char dum[SECTOR_SIZE];
+-		HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
+-
+-		--rq->current_nr_sectors;
+-		--nskip;
+-		--sectors_to_transfer;
+-	}
++	struct cdrom_info *cd = drive->driver_data;
  
- 	if (unlikely(chan->slow_ref) &&
-@@ -119,7 +120,7 @@ static ssize_t show_in_use(struct class_device *cd, char *buf)
- 	return sprintf(buf, "%d\n", in_use);
- }
+-	/* Now loop while we still have data to read from the drive. */
+-	while (sectors_to_transfer > 0) {
+-		int this_transfer;
++	if ((len % SECTOR_SIZE) == 0)
++		return 0;
  
--static struct class_device_attribute dma_class_attrs[] = {
-+static struct device_attribute dma_attrs[] = {
- 	__ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
- 	__ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
- 	__ATTR(in_use, S_IRUGO, show_in_use, NULL),
-@@ -128,16 +129,16 @@ static struct class_device_attribute dma_class_attrs[] = {
+-		/* If we've filled the present buffer but there's another
+-		   chained buffer after it, move on. */
+-		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+-			cdrom_end_request(drive, 1);
++	printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
++			drive->name, __FUNCTION__, len);
  
- static void dma_async_device_cleanup(struct kref *kref);
+-		/* If the buffers are full, cache the rest of the data in our
+-		   internal buffer. */
+-		if (rq->current_nr_sectors == 0) {
+-			cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
+-			sectors_to_transfer = 0;
+-		} else {
+-			/* Transfer data to the buffers.
+-			   Figure out how many sectors we can transfer
+-			   to the current buffer. */
+-			this_transfer = min_t(int, sectors_to_transfer,
+-					     rq->current_nr_sectors);
+-
+-			/* Read this_transfer sectors
+-			   into the current buffer. */
+-			while (this_transfer > 0) {
+-				HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
+-				rq->buffer += SECTOR_SIZE;
+-				--rq->nr_sectors;
+-				--rq->current_nr_sectors;
+-				++rq->sector;
+-				--this_transfer;
+-				--sectors_to_transfer;
+-			}
+-		}
++	if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
++		printk(KERN_ERR "  This drive is not supported by "
++				"this version of the driver\n");
++	else {
++		printk(KERN_ERR "  Trying to limit transfer sizes\n");
++		cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
+ 	}
  
--static void dma_class_dev_release(struct class_device *cd)
-+static void dma_dev_release(struct device *dev)
- {
--	struct dma_chan *chan = container_of(cd, struct dma_chan, class_dev);
-+	struct dma_chan *chan = to_dma_chan(dev);
- 	kref_put(&chan->device->refcount, dma_async_device_cleanup);
+-	/* Done moving data!  Wait for another interrupt. */
+-	ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
+-	return ide_started;
++	return 1;
  }
  
- static struct class dma_devclass = {
--	.name            = "dma",
--	.class_dev_attrs = dma_class_attrs,
--	.release = dma_class_dev_release,
-+	.name		= "dma",
-+	.dev_attrs	= dma_attrs,
-+	.dev_release	= dma_dev_release,
- };
- 
- /* --- client and device registration --- */
-@@ -377,12 +378,12 @@ int dma_async_device_register(struct dma_device *device)
- 			continue;
+ /*
+@@ -1287,48 +789,58 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
+ 	return 0;
+ }
  
- 		chan->chan_id = chancnt++;
--		chan->class_dev.class = &dma_devclass;
--		chan->class_dev.dev = NULL;
--		snprintf(chan->class_dev.class_id, BUS_ID_SIZE, "dma%dchan%d",
-+		chan->dev.class = &dma_devclass;
-+		chan->dev.parent = NULL;
-+		snprintf(chan->dev.bus_id, BUS_ID_SIZE, "dma%dchan%d",
- 		         device->dev_id, chan->chan_id);
++static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
++
+ /*
+- * Routine to send a read packet command to the drive.
+- * This is usually called directly from cdrom_start_read.
++ * Routine to send a read/write packet command to the drive.
++ * This is usually called directly from cdrom_start_{read,write}().
+  * However, for drq_interrupt devices, it is called from an interrupt
+  * when the drive is ready to accept the command.
+  */
+-static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
++static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
+ {
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	unsigned short sectors_per_frame;
+-	int nskip;
  
--		rc = class_device_register(&chan->class_dev);
-+		rc = device_register(&chan->dev);
- 		if (rc) {
- 			chancnt--;
- 			free_percpu(chan->local);
-@@ -411,7 +412,7 @@ err_out:
- 		if (chan->local == NULL)
- 			continue;
- 		kref_put(&device->refcount, dma_async_device_cleanup);
--		class_device_unregister(&chan->class_dev);
-+		device_unregister(&chan->dev);
- 		chancnt--;
- 		free_percpu(chan->local);
- 	}
-@@ -445,7 +446,7 @@ void dma_async_device_unregister(struct dma_device *device)
+-	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
++	if (rq_data_dir(rq) == READ) {
++		unsigned short sectors_per_frame =
++			queue_hardsect_size(drive->queue) >> SECTOR_BITS;
++		int nskip = rq->sector & (sectors_per_frame - 1);
  
- 	list_for_each_entry(chan, &device->channels, device_node) {
- 		dma_clients_notify_removed(chan);
--		class_device_unregister(&chan->class_dev);
-+		device_unregister(&chan->dev);
- 		dma_chan_release(chan);
+-	/* If the requested sector doesn't start on a cdrom block boundary,
+-	   we must adjust the start of the transfer so that it does,
+-	   and remember to skip the first few sectors.
+-	   If the CURRENT_NR_SECTORS field is larger than the size
+-	   of the buffer, it will mean that we're to skip a number
+-	   of sectors equal to the amount by which CURRENT_NR_SECTORS
+-	   is larger than the buffer size. */
+-	nskip = rq->sector & (sectors_per_frame - 1);
+-	if (nskip > 0) {
+-		/* Sanity check... */
+-		if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) &&
+-			(rq->sector & (sectors_per_frame - 1))) {
+-			printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n",
+-				drive->name, rq->current_nr_sectors);
+-			cdrom_end_request(drive, 0);
+-			return ide_stopped;
++		/*
++		 * If the requested sector doesn't start on a frame boundary,
++		 * we must adjust the start of the transfer so that it does,
++		 * and remember to skip the first few sectors.
++		 *
++		 * If the rq->current_nr_sectors field is larger than the size
++		 * of the buffer, it will mean that we're to skip a number of
++		 * sectors equal to the amount by which rq->current_nr_sectors
++		 * is larger than the buffer size.
++		 */
++		if (nskip > 0) {
++			/* Sanity check... */
++			if (rq->current_nr_sectors !=
++			    bio_cur_sectors(rq->bio)) {
++				printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
++						drive->name, __FUNCTION__,
++						rq->current_nr_sectors);
++				cdrom_end_request(drive, 0);
++				return ide_stopped;
++			}
++			rq->current_nr_sectors += nskip;
+ 		}
+-		rq->current_nr_sectors += nskip;
  	}
+-
++#if 0
++	else
++		/* the immediate bit */
++		rq->cmd[1] = 1 << 3;
++#endif
+ 	/* Set up the command */
+ 	rq->timeout = ATAPI_WAIT_PC;
  
-diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
-index 70b837f..5376457 100644
---- a/drivers/edac/edac_device_sysfs.c
-+++ b/drivers/edac/edac_device_sysfs.c
-@@ -246,16 +246,6 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
+ 	/* Send the command to the drive and return. */
+-	return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
++	return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
+ }
  
- 	/* Init the devices's kobject */
- 	memset(&edac_dev->kobj, 0, sizeof(struct kobject));
--	edac_dev->kobj.ktype = &ktype_device_ctrl;
--
--	/* set this new device under the edac_class kobject */
--	edac_dev->kobj.parent = &edac_class->kset.kobj;
 -
--	/* generate sysfs "..../edac/<name>"   */
--	debugf4("%s() set name of kobject to: %s\n", __func__, edac_dev->name);
--	err = kobject_set_name(&edac_dev->kobj, "%s", edac_dev->name);
--	if (err)
--		goto err_out;
- 
- 	/* Record which module 'owns' this control structure
- 	 * and bump the ref count of the module
-@@ -268,12 +258,15 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
- 	}
+ #define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
+ #define IDECD_SEEK_TIMER	(5 * WAIT_MIN_SLEEP)	/* 100 ms */
+ #define IDECD_SEEK_TIMEOUT	(2 * WAIT_CMD)		/* 20 sec */
+@@ -1341,7 +853,8 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
  
- 	/* register */
--	err = kobject_register(&edac_dev->kobj);
-+	err = kobject_init_and_add(&edac_dev->kobj, &ktype_device_ctrl,
-+				   &edac_class->kset.kobj,
-+				   "%s", edac_dev->name);
- 	if (err) {
- 		debugf1("%s()Failed to register '.../edac/%s'\n",
- 			__func__, edac_dev->name);
- 		goto err_kobj_reg;
- 	}
-+	kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
+ 	if (cdrom_decode_status(drive, 0, &stat))
+ 		return ide_stopped;
+-	CDROM_CONFIG_FLAGS(drive)->seeking = 1;
++
++	info->cd_flags |= IDE_CD_FLAG_SEEKING;
  
- 	/* At this point, to 'free' the control struct,
- 	 * edac_device_unregister_sysfs_main_kobj() must be used
-@@ -310,7 +303,7 @@ void edac_device_unregister_sysfs_main_kobj(
- 	 *   a) module_put() this module
- 	 *   b) 'kfree' the memory
- 	 */
--	kobject_unregister(&edac_dev->kobj);
-+	kobject_put(&edac_dev->kobj);
+ 	if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
+ 		if (--retry == 0) {
+@@ -1397,184 +910,25 @@ static void restore_request (struct request *rq)
+ 	rq->q->prep_rq_fn(rq->q, rq);
  }
  
- /* edac_dev -> instance information */
-@@ -533,12 +526,6 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
- 
- 	/* init this block's kobject */
- 	memset(&block->kobj, 0, sizeof(struct kobject));
--	block->kobj.parent = &instance->kobj;
--	block->kobj.ktype = &ktype_block_ctrl;
+-/*
+- * Start a read request from the CD-ROM.
+- */
+-static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
+-{
+-	struct cdrom_info *info = drive->driver_data;
+-	struct request *rq = HWGROUP(drive)->rq;
+-	unsigned short sectors_per_frame;
 -
--	err = kobject_set_name(&block->kobj, "%s", block->name);
--	if (err)
--		return err;
- 
- 	/* bump the main kobject's reference count for this controller
- 	 * and this instance is dependant on the main
-@@ -550,7 +537,9 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
- 	}
+-	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+-
+-	/* We may be retrying this request after an error.  Fix up
+-	   any weirdness which might be present in the request packet. */
+-	restore_request(rq);
+-
+-	/* Satisfy whatever we can of this request from our cached sector. */
+-	if (cdrom_read_from_buffer(drive))
+-		return ide_stopped;
+-
+-	/* Clear the local sector buffer. */
+-	info->nsectors_buffered = 0;
+-
+-	/* use dma, if possible. */
+-	info->dma = drive->using_dma;
+-	if ((rq->sector & (sectors_per_frame - 1)) ||
+-	    (rq->nr_sectors & (sectors_per_frame - 1)))
+-		info->dma = 0;
+-
+-	/* Start sending the read request to the drive. */
+-	return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
+-}
+-
+ /****************************************************************************
+  * Execute all other packet commands.
+  */
  
- 	/* Add this block's kobject */
--	err = kobject_register(&block->kobj);
-+	err = kobject_init_and_add(&block->kobj, &ktype_block_ctrl,
-+				   &instance->kobj,
-+				   "%s", block->name);
- 	if (err) {
- 		debugf1("%s() Failed to register instance '%s'\n",
- 			__func__, block->name);
-@@ -579,12 +568,13 @@ static int edac_device_create_block(struct edac_device_ctl_info *edac_dev,
- 				goto err_on_attrib;
+-/* Interrupt routine for packet command completion. */
+-static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
++static void ide_cd_request_sense_fixup(struct request *rq)
+ {
+-	int ireason, len, thislen;
+-	struct request *rq = HWGROUP(drive)->rq;
+-	u8 lowcyl = 0, highcyl = 0;
+-	int stat;
+-
+-	/* Check for errors. */
+-	if (cdrom_decode_status(drive, 0, &stat))
+-		return ide_stopped;
+-
+-	/* Read the interrupt reason and the transfer length. */
+-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
+-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
+-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
+-
+-	len = lowcyl + (256 * highcyl);
+-
+-	/* If DRQ is clear, the command has completed.
+-	   Complain if we still have data left to transfer. */
+-	if ((stat & DRQ_STAT) == 0) {
+-		/* Some of the trailing request sense fields are optional, and
+-		   some drives don't send them.  Sigh. */
+-		if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
+-		    rq->data_len > 0 &&
+-		    rq->data_len <= 5) {
+-			while (rq->data_len > 0) {
+-				*(unsigned char *)rq->data++ = 0;
+-				--rq->data_len;
+-			}
+-		}
+-
+-		if (rq->data_len == 0)
+-			cdrom_end_request(drive, 1);
+-		else {
+-			/* Comment this out, because this always happens 
+-			   right after a reset occurs, and it is annoying to 
+-			   always print expected stuff.  */
+-			/*
+-			printk ("%s: cdrom_pc_intr: data underrun %d\n",
+-				drive->name, pc->buflen);
+-			*/
+-			rq->cmd_flags |= REQ_FAILED;
+-			cdrom_end_request(drive, 0);
+-		}
+-		return ide_stopped;
+-	}
+-
+-	/* Figure out how much data to transfer. */
+-	thislen = rq->data_len;
+-	if (thislen > len) thislen = len;
+-
+-	/* The drive wants to be written to. */
+-	if (ireason == 0) {
+-		if (!rq->data) {
+-			blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
+-			goto confused;
+-		}
+-		/* Transfer the data. */
+-		HWIF(drive)->atapi_output_bytes(drive, rq->data, thislen);
+-
+-		/* If we haven't moved enough data to satisfy the drive,
+-		   add some padding. */
+-		while (len > thislen) {
+-			int dum = 0;
+-			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum));
+-			len -= sizeof(dum);
+-		}
+-
+-		/* Keep count of how much data we've moved. */
+-		rq->data += thislen;
+-		rq->data_len -= thislen;
+-	}
+-
+-	/* Same drill for reading. */
+-	else if (ireason == 2) {
+-		if (!rq->data) {
+-			blk_dump_rq_flags(rq, "cdrom_pc_intr, read");
+-			goto confused;
+-		}
+-		/* Transfer the data. */
+-		HWIF(drive)->atapi_input_bytes(drive, rq->data, thislen);
+-
+-		/* If we haven't moved enough data to satisfy the drive,
+-		   add some padding. */
+-		while (len > thislen) {
+-			int dum = 0;
+-			HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
+-			len -= sizeof(dum);
++	/*
++	 * Some of the trailing request sense fields are optional,
++	 * and some drives don't send them.  Sigh.
++	 */
++	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
++	    rq->data_len > 0 && rq->data_len <= 5)
++		while (rq->data_len > 0) {
++			*(u8 *)rq->data++ = 0;
++			--rq->data_len;
  		}
- 	}
-+	kobject_uevent(&block->kobj, KOBJ_ADD);
- 
- 	return 0;
- 
- 	/* Error unwind stack */
- err_on_attrib:
--	kobject_unregister(&block->kobj);
-+	kobject_put(&block->kobj);
- 
- err_out:
- 	return err;
-@@ -615,7 +605,7 @@ static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev,
- 	/* unregister this block's kobject, SEE:
- 	 *	edac_device_ctrl_block_release() callback operation
- 	 */
--	kobject_unregister(&block->kobj);
-+	kobject_put(&block->kobj);
+-
+-		/* Keep count of how much data we've moved. */
+-		rq->data += thislen;
+-		rq->data_len -= thislen;
+-
+-		if (blk_sense_request(rq))
+-			rq->sense_len += thislen;
+-	} else {
+-confused:
+-		printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
+-			"appears confused (ireason = 0x%02x). "
+-			"Trying to recover by ending request.\n",
+-			drive->name, ireason);
+-		rq->cmd_flags |= REQ_FAILED;
+-		cdrom_end_request(drive, 0);
+-		return ide_stopped;
+-	}
+-
+-	/* Now we wait for another interrupt. */
+-	ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry);
+-	return ide_started;
+-}
+-
+-static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
+-{
+-	struct request *rq = HWGROUP(drive)->rq;
+-
+-	if (!rq->timeout)
+-		rq->timeout = ATAPI_WAIT_PC;
+-
+-	/* Send the command to the drive and return. */
+-	return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr);
+-}
+-
+-
+-static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
+-{
+-	int len;
+-	struct request *rq = HWGROUP(drive)->rq;
+-	struct cdrom_info *info = drive->driver_data;
+-
+-	info->dma = 0;
+-	rq->cmd_flags &= ~REQ_FAILED;
+-	len = rq->data_len;
+-
+-	/* Start sending the command to the drive. */
+-	return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
  }
  
- /* instance ctor/dtor code */
-@@ -637,15 +627,8 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
- 	/* Init the instance's kobject */
- 	memset(&instance->kobj, 0, sizeof(struct kobject));
+-
+-static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
++int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+ {
+ 	struct request_sense sense;
+ 	int retries = 10;
+@@ -1623,59 +977,37 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+ }
  
--	/* set this new device under the edac_device main kobject */
--	instance->kobj.parent = &edac_dev->kobj;
--	instance->kobj.ktype = &ktype_instance_ctrl;
- 	instance->ctl = edac_dev;
+ /*
+- * Write handling
++ * Called from blk_end_request_callback() after the data of the request
++ * is completed and before the request is completed.
++ * By returning value '1', blk_end_request_callback() returns immediately
++ * without completing the request.
+  */
+-static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
++static int cdrom_newpc_intr_dummy_cb(struct request *rq)
+ {
+-	/* Two notes about IDE interrupt reason here - 0 means that
+-	 * the drive wants to receive data from us, 2 means that
+-	 * the drive is expecting to transfer data to us.
+-	 */
+-	if (ireason == 0)
+-		return 0;
+-	else if (ireason == 2) {
+-		/* Whoops... The drive wants to send data. */
+-		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
+-				drive->name, __FUNCTION__);
+-
+-		while (len > 0) {
+-			int dum = 0;
+-			HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
+-			len -= sizeof(dum);
+-		}
+-	} else {
+-		/* Drive wants a command packet, or invalid ireason... */
+-		printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
+-				drive->name, __FUNCTION__, ireason);
+-	}
+-
+-	cdrom_end_request(drive, 0);
+ 	return 1;
+ }
  
--	err = kobject_set_name(&instance->kobj, "%s", instance->name);
--	if (err)
--		goto err_out;
+-typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
 -
- 	/* bump the main kobject's reference count for this controller
- 	 * and this instance is dependant on the main
- 	 */
-@@ -655,8 +638,9 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
- 		goto err_out;
+-/*
+- * best way to deal with dma that is not sector aligned right now... note
+- * that in this path we are not using ->data or ->buffer at all. this irs
+- * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the
+- * future.
+- */
+ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ {
+ 	struct cdrom_info *info = drive->driver_data;
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	int dma_error, dma, stat, ireason, len, thislen;
+-	u8 lowcyl, highcyl;
+ 	xfer_func_t *xferfunc;
+-	unsigned long flags;
++	ide_expiry_t *expiry = NULL;
++	int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
++	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
++	unsigned int timeout;
++	u8 lowcyl, highcyl;
+ 
+ 	/* Check for errors. */
+-	dma_error = 0;
+ 	dma = info->dma;
+ 	if (dma) {
+ 		info->dma = 0;
+ 		dma_error = HWIF(drive)->ide_dma_end(drive);
++		if (dma_error) {
++			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
++					write ? "write" : "read");
++			ide_dma_off(drive);
++		}
  	}
  
--	/* Formally register this instance's kobject */
--	err = kobject_register(&instance->kobj);
-+	/* Formally register this instance's kobject under the edac_device */
-+	err = kobject_init_and_add(&instance->kobj, &ktype_instance_ctrl,
-+				   &edac_dev->kobj, "%s", instance->name);
- 	if (err != 0) {
- 		debugf2("%s() Failed to register instance '%s'\n",
- 			__func__, instance->name);
-@@ -679,6 +663,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
- 			goto err_release_instance_kobj;
+ 	if (cdrom_decode_status(drive, 0, &stat))
+@@ -1685,14 +1017,12 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ 	 * using dma, transfer is complete now
+ 	 */
+ 	if (dma) {
+-		if (dma_error) {
+-			printk(KERN_ERR "ide-cd: dma error\n");
+-			ide_dma_off(drive);
++		if (dma_error)
+ 			return ide_error(drive, "dma error", stat);
++		if (blk_fs_request(rq)) {
++			ide_end_request(drive, 1, rq->nr_sectors);
++			return ide_stopped;
  		}
+-
+-		end_that_request_chunk(rq, 1, rq->data_len);
+-		rq->data_len = 0;
+ 		goto end_request;
  	}
-+	kobject_uevent(&instance->kobj, KOBJ_ADD);
  
- 	debugf4("%s() Registered instance %d '%s' kobject\n",
- 		__func__, idx, instance->name);
-@@ -687,7 +672,7 @@ static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev,
+@@ -1704,54 +1034,120 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+ 	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
  
- 	/* error unwind stack */
- err_release_instance_kobj:
--	kobject_unregister(&instance->kobj);
-+	kobject_put(&instance->kobj);
+ 	len = lowcyl + (256 * highcyl);
+-	thislen = rq->data_len;
++
++	thislen = blk_fs_request(rq) ? len : rq->data_len;
+ 	if (thislen > len)
+ 		thislen = len;
  
- err_out:
- 	return err;
-@@ -712,7 +697,7 @@ static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev,
- 	/* unregister this instance's kobject, SEE:
- 	 *	edac_device_ctrl_instance_release() for callback operation
+ 	/*
+ 	 * If DRQ is clear, the command has completed.
  	 */
--	kobject_unregister(&instance->kobj);
-+	kobject_put(&instance->kobj);
- }
+-	if ((stat & DRQ_STAT) == 0)
++	if ((stat & DRQ_STAT) == 0) {
++		if (blk_fs_request(rq)) {
++			/*
++			 * If we're not done reading/writing, complain.
++			 * Otherwise, complete the command normally.
++			 */
++			uptodate = 1;
++			if (rq->current_nr_sectors > 0) {
++				printk(KERN_ERR "%s: %s: data underrun "
++						"(%d blocks)\n",
++						drive->name, __FUNCTION__,
++						rq->current_nr_sectors);
++				if (!write)
++					rq->cmd_flags |= REQ_FAILED;
++				uptodate = 0;
++			}
++			cdrom_end_request(drive, uptodate);
++			return ide_stopped;
++		} else if (!blk_pc_request(rq)) {
++			ide_cd_request_sense_fixup(rq);
++			/* Complain if we still have data left to transfer. */
++			uptodate = rq->data_len ? 0 : 1;
++		}
+ 		goto end_request;
++	}
  
- /*
-diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
-index 3706b2b..9aac880 100644
---- a/drivers/edac/edac_mc_sysfs.c
-+++ b/drivers/edac/edac_mc_sysfs.c
-@@ -380,13 +380,6 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
- 	/* generate ..../edac/mc/mc<id>/csrow<index>   */
- 	memset(&csrow->kobj, 0, sizeof(csrow->kobj));
- 	csrow->mci = mci;	/* include container up link */
--	csrow->kobj.parent = kobj_mci;
--	csrow->kobj.ktype = &ktype_csrow;
--
--	/* name this instance of csrow<id> */
--	err = kobject_set_name(&csrow->kobj, "csrow%d", index);
--	if (err)
--		goto err_out;
+ 	/*
+ 	 * check which way to transfer data
+ 	 */
+-	if (rq_data_dir(rq) == WRITE) {
+-		/*
+-		 * write to drive
+-		 */
+-		if (cdrom_write_check_ireason(drive, len, ireason))
++	if (blk_fs_request(rq) || blk_pc_request(rq)) {
++		if (ide_cd_check_ireason(drive, len, ireason, write))
+ 			return ide_stopped;
  
- 	/* bump the mci instance's kobject's ref count */
- 	kobj = kobject_get(&mci->edac_mci_kobj);
-@@ -396,12 +389,13 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
- 	}
+-		xferfunc = HWIF(drive)->atapi_output_bytes;
+-	} else  {
+-		/*
+-		 * read from drive
+-		 */
+-		if (cdrom_read_check_ireason(drive, len, ireason))
+-			return ide_stopped;
++		if (blk_fs_request(rq) && write == 0) {
++			int nskip;
++
++			if (ide_cd_check_transfer_size(drive, len)) {
++				cdrom_end_request(drive, 0);
++				return ide_stopped;
++			}
  
- 	/* Instanstiate the csrow object */
--	err = kobject_register(&csrow->kobj);
-+	err = kobject_init_and_add(&csrow->kobj, &ktype_csrow, kobj_mci,
-+				   "csrow%d", index);
- 	if (err)
- 		goto err_release_top_kobj;
++			/*
++			 * First, figure out if we need to bit-bucket
++			 * any of the leading sectors.
++			 */
++			nskip = min_t(int, rq->current_nr_sectors
++					   - bio_cur_sectors(rq->bio),
++					   thislen >> 9);
++			if (nskip > 0) {
++				ide_cd_drain_data(drive, nskip);
++				rq->current_nr_sectors -= nskip;
++				thislen -= (nskip << 9);
++			}
++		}
++	}
++
++	if (ireason == 0) {
++		write = 1;
++		xferfunc = HWIF(drive)->atapi_output_bytes;
++	} else if (ireason == 2 || (ireason == 1 &&
++		   (blk_fs_request(rq) || blk_pc_request(rq)))) {
++		write = 0;
+ 		xferfunc = HWIF(drive)->atapi_input_bytes;
++	} else {
++		printk(KERN_ERR "%s: %s: The drive "
++				"appears confused (ireason = 0x%02x). "
++				"Trying to recover by ending request.\n",
++				drive->name, __FUNCTION__, ireason);
++		goto end_request;
+ 	}
  
- 	/* At this point, to release a csrow kobj, one must
--	 * call the kobject_unregister and allow that tear down
-+	 * call the kobject_put and allow that tear down
- 	 * to work the releasing
+ 	/*
+ 	 * transfer data
  	 */
+ 	while (thislen > 0) {
+-		int blen = blen = rq->data_len;
+-		char *ptr = rq->data;
++		u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
++		int blen = rq->data_len;
  
-@@ -412,11 +406,11 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
- 		err = edac_create_channel_files(&csrow->kobj, chan);
- 		if (err) {
- 			/* special case the unregister here */
--			kobject_unregister(&csrow->kobj);
-+			kobject_put(&csrow->kobj);
- 			goto err_out;
+ 		/*
+ 		 * bio backed?
+ 		 */
+ 		if (rq->bio) {
+-			ptr = bio_data(rq->bio);
+-			blen = bio_iovec(rq->bio)->bv_len;
++			if (blk_fs_request(rq)) {
++				ptr = rq->buffer;
++				blen = rq->current_nr_sectors << 9;
++			} else {
++				ptr = bio_data(rq->bio);
++				blen = bio_iovec(rq->bio)->bv_len;
++			}
  		}
- 	}
--
-+	kobject_uevent(&csrow->kobj, KOBJ_ADD);
- 	return 0;
- 
- 	/* error unwind stack */
-@@ -744,7 +738,6 @@ static struct kobj_type ktype_mc_set_attribs = {
-  */
- static struct kset mc_kset = {
- 	.kobj = {.ktype = &ktype_mc_set_attribs },
--	.ktype = &ktype_mci,
- };
  
+ 		if (!ptr) {
+-			printk(KERN_ERR "%s: confused, missing data\n", drive->name);
++			if (blk_fs_request(rq) && !write)
++				/*
++				 * If the buffers are full, cache the rest
++				 * of the data in our internal buffer.
++				 */
++				cdrom_buffer_sectors(drive, rq->sector,
++						     thislen >> 9);
++			else {
++				printk(KERN_ERR "%s: confused, missing data\n",
++						drive->name);
++				blk_dump_rq_flags(rq, rq_data_dir(rq)
++						  ? "cdrom_newpc_intr, write"
++						  : "cdrom_newpc_intr, read");
++			}
+ 			break;
+ 		}
  
-@@ -765,14 +758,6 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
- 	/* Init the mci's kobject */
- 	memset(kobj_mci, 0, sizeof(*kobj_mci));
+@@ -1762,186 +1158,117 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
  
--	/* this instance become part of the mc_kset */
--	kobj_mci->kset = &mc_kset;
+ 		thislen -= blen;
+ 		len -= blen;
+-		rq->data_len -= blen;
 -
--	/* set the name of the mc<id> object */
--	err = kobject_set_name(kobj_mci, "mc%d", mci->mc_idx);
--	if (err)
--		goto fail_out;
+-		if (rq->bio)
+-			end_that_request_chunk(rq, 1, blen);
+-		else
+-			rq->data += blen;
+-	}
 -
- 	/* Record which module 'owns' this control structure
- 	 * and bump the ref count of the module
- 	 */
-@@ -784,13 +769,18 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
- 		goto fail_out;
- 	}
- 
-+	/* this instance become part of the mc_kset */
-+	kobj_mci->kset = &mc_kset;
-+
- 	/* register the mc<id> kobject to the mc_kset */
--	err = kobject_register(kobj_mci);
-+	err = kobject_init_and_add(kobj_mci, &ktype_mci, NULL,
-+				   "mc%d", mci->mc_idx);
- 	if (err) {
- 		debugf1("%s()Failed to register '.../edac/mc%d'\n",
- 			__func__, mci->mc_idx);
- 		goto kobj_reg_fail;
- 	}
-+	kobject_uevent(kobj_mci, KOBJ_ADD);
+-	/*
+-	 * pad, if necessary
+-	 */
+-	if (len > 0) {
+-		while (len > 0) {
+-			int pad = 0;
+-
+-			xferfunc(drive, &pad, sizeof(pad));
+-			len -= sizeof(pad);
+-		}
+-	}
+-
+-	BUG_ON(HWGROUP(drive)->handler != NULL);
  
- 	/* At this point, to 'free' the control struct,
- 	 * edac_mc_unregister_sysfs_main_kobj() must be used
-@@ -818,7 +808,7 @@ fail_out:
- void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
- {
- 	/* delete the kobj from the mc_kset */
--	kobject_unregister(&mci->edac_mci_kobj);
-+	kobject_put(&mci->edac_mci_kobj);
- }
+-	ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
+-	return ide_started;
+-
+-end_request:
+-	spin_lock_irqsave(&ide_lock, flags);
+-	blkdev_dequeue_request(rq);
+-	end_that_request_last(rq, 1);
+-	HWGROUP(drive)->rq = NULL;
+-	spin_unlock_irqrestore(&ide_lock, flags);
+-	return ide_stopped;
+-}
+-
+-static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
+-{
+-	int stat, ireason, len, sectors_to_transfer, uptodate;
+-	struct cdrom_info *info = drive->driver_data;
+-	int dma_error = 0, dma = info->dma;
+-	u8 lowcyl = 0, highcyl = 0;
++		if (blk_fs_request(rq)) {
++			rq->buffer += blen;
++			rq->nr_sectors -= (blen >> 9);
++			rq->current_nr_sectors -= (blen >> 9);
++			rq->sector += (blen >> 9);
  
- #define EDAC_DEVICE_SYMLINK	"device"
-@@ -933,7 +923,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
- fail1:
- 	for (i--; i >= 0; i--) {
- 		if (csrow->nr_pages > 0) {
--			kobject_unregister(&mci->csrows[i].kobj);
-+			kobject_put(&mci->csrows[i].kobj);
- 		}
- 	}
+-	struct request *rq = HWGROUP(drive)->rq;
++			if (rq->current_nr_sectors == 0 && rq->nr_sectors)
++				cdrom_end_request(drive, 1);
++		} else {
++			rq->data_len -= blen;
  
-@@ -960,7 +950,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
- 	for (i = 0; i < mci->nr_csrows; i++) {
- 		if (mci->csrows[i].nr_pages > 0) {
- 			debugf0("%s()  unreg csrow-%d\n", __func__, i);
--			kobject_unregister(&mci->csrows[i].kobj);
-+			kobject_put(&mci->csrows[i].kobj);
+-	/* Check for errors. */
+-	if (dma) {
+-		info->dma = 0;
+-		dma_error = HWIF(drive)->ide_dma_end(drive);
+-		if (dma_error) {
+-			printk(KERN_ERR "%s: DMA write error\n", drive->name);
+-			ide_dma_off(drive);
++			/*
++			 * The request can't be completed until DRQ is cleared.
++			 * So complete the data, but don't complete the request
++			 * using the dummy function for the callback feature
++			 * of blk_end_request_callback().
++			 */
++			if (rq->bio)
++				blk_end_request_callback(rq, 0, blen,
++						 cdrom_newpc_intr_dummy_cb);
++			else
++				rq->data += blen;
  		}
  	}
  
-@@ -977,7 +967,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
- 	debugf0("%s()  unregister this mci kobj\n", __func__);
+-	if (cdrom_decode_status(drive, 0, &stat))
+-		return ide_stopped;
++	if (write && blk_sense_request(rq))
++		rq->sense_len += thislen;
  
- 	/* unregister this instance's kobject */
--	kobject_unregister(&mci->edac_mci_kobj);
-+	kobject_put(&mci->edac_mci_kobj);
- }
+ 	/*
+-	 * using dma, transfer is complete now
++	 * pad, if necessary
+ 	 */
+-	if (dma) {
+-		if (dma_error)
+-			return ide_error(drive, "dma error", stat);
++	if (!blk_fs_request(rq) && len > 0)
++		ide_cd_pad_transfer(drive, xferfunc, len);
  
+-		ide_end_request(drive, 1, rq->nr_sectors);
+-		return ide_stopped;
++	if (blk_pc_request(rq)) {
++		timeout = rq->timeout;
++	} else {
++		timeout = ATAPI_WAIT_PC;
++		if (!blk_fs_request(rq))
++			expiry = cdrom_timer_expiry;
+ 	}
  
-diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
-index e0c4a40..7e1374a 100644
---- a/drivers/edac/edac_module.c
-+++ b/drivers/edac/edac_module.c
-@@ -31,7 +31,7 @@ struct workqueue_struct *edac_workqueue;
-  *	need to export to other files in this modules
-  */
- static struct sysdev_class edac_class = {
--	set_kset_name("edac"),
-+	.name = "edac",
- };
- static int edac_class_valid;
+-	/* Read the interrupt reason and the transfer length. */
+-	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
+-	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
+-	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
++	ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
++	return ide_started;
  
-diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
-index 69f5ddd..5b075da 100644
---- a/drivers/edac/edac_pci_sysfs.c
-+++ b/drivers/edac/edac_pci_sysfs.c
-@@ -162,14 +162,6 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
+-	len = lowcyl + (256 * highcyl);
++end_request:
++	if (blk_pc_request(rq)) {
++		unsigned long flags;
  
- 	debugf0("%s()\n", __func__);
+-	/* If DRQ is clear, the command has completed. */
+-	if ((stat & DRQ_STAT) == 0) {
+-		/* If we're not done writing, complain.
+-		 * Otherwise, complete the command normally.
+-		 */
+-		uptodate = 1;
+-		if (rq->current_nr_sectors > 0) {
+-			printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n",
+-					drive->name, __FUNCTION__,
+-					rq->current_nr_sectors);
+-			uptodate = 0;
+-		}
++		spin_lock_irqsave(&ide_lock, flags);
++		if (__blk_end_request(rq, 0, rq->data_len))
++			BUG();
++		HWGROUP(drive)->rq = NULL;
++		spin_unlock_irqrestore(&ide_lock, flags);
++	} else {
++		if (!uptodate)
++			rq->cmd_flags |= REQ_FAILED;
+ 		cdrom_end_request(drive, uptodate);
+-		return ide_stopped;
+ 	}
++	return ide_stopped;
++}
  
--	/* Set the parent and the instance's ktype */
--	pci->kobj.parent = &edac_pci_top_main_kobj;
--	pci->kobj.ktype = &ktype_pci_instance;
+-	/* Check that the drive is expecting to do the same thing we are. */
+-	if (cdrom_write_check_ireason(drive, len, ireason))
+-		return ide_stopped;
 -
--	err = kobject_set_name(&pci->kobj, "pci%d", idx);
--	if (err)
--		return err;
+-	sectors_to_transfer = len / SECTOR_SIZE;
 -
- 	/* First bump the ref count on the top main kobj, which will
- 	 * track the number of PCI instances we have, and thus nest
- 	 * properly on keeping the module loaded
-@@ -181,7 +173,8 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
- 	}
+-	/*
+-	 * now loop and write out the data
+-	 */
+-	while (sectors_to_transfer > 0) {
+-		int this_transfer;
+-
+-		if (!rq->current_nr_sectors) {
+-			printk(KERN_ERR "%s: %s: confused, missing data\n",
+-					drive->name, __FUNCTION__);
+-			break;
+-		}
++static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
++{
++	struct cdrom_info *cd = drive->driver_data;
++	int write = rq_data_dir(rq) == WRITE;
++	unsigned short sectors_per_frame =
++		queue_hardsect_size(drive->queue) >> SECTOR_BITS;
  
- 	/* And now register this new kobject under the main kobj */
--	err = kobject_register(&pci->kobj);
-+	err = kobject_init_and_add(&pci->kobj, &ktype_pci_instance,
-+				   &edac_pci_top_main_kobj, "pci%d", idx);
- 	if (err != 0) {
- 		debugf2("%s() failed to register instance pci%d\n",
- 			__func__, idx);
-@@ -189,6 +182,7 @@ static int edac_pci_create_instance_kobj(struct edac_pci_ctl_info *pci, int idx)
- 		goto error_out;
- 	}
++	if (write) {
+ 		/*
+-		 * Figure out how many sectors we can transfer
++		 * disk has become write protected
+ 		 */
+-		this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors);
+-
+-		while (this_transfer > 0) {
+-			HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
+-			rq->buffer += SECTOR_SIZE;
+-			--rq->nr_sectors;
+-			--rq->current_nr_sectors;
+-			++rq->sector;
+-			--this_transfer;
+-			--sectors_to_transfer;
++		if (cd->disk->policy) {
++			cdrom_end_request(drive, 0);
++			return ide_stopped;
+ 		}
+-
++	} else {
+ 		/*
+-		 * current buffer complete, move on
++		 * We may be retrying this request after an error.  Fix up any
++		 * weirdness which might be present in the request packet.
+ 		 */
+-		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
+-			cdrom_end_request(drive, 1);
+-	}
+-
+-	/* re-arm handler */
+-	ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);
+-	return ide_started;
+-}
+-
+-static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
+-{
+-	struct request *rq = HWGROUP(drive)->rq;
++		restore_request(rq);
  
-+	kobject_uevent(&pci->kobj, KOBJ_ADD);
- 	debugf1("%s() Register instance 'pci%d' kobject\n", __func__, idx);
+-#if 0	/* the immediate bit */
+-	rq->cmd[1] = 1 << 3;
+-#endif
+-	rq->timeout = ATAPI_WAIT_PC;
+-
+-	return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
+-}
+-
+-static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
+-{
+-	struct cdrom_info *info = drive->driver_data;
+-	struct gendisk *g = info->disk;
+-	unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
++		/* Satisfy whatever we can of this request from our cache. */
++		if (cdrom_read_from_buffer(drive))
++			return ide_stopped;
++	}
  
- 	return 0;
-@@ -211,7 +205,7 @@ void edac_pci_unregister_sysfs_instance_kobj(struct edac_pci_ctl_info *pci)
- 	 * function release the main reference count and then
- 	 * kfree the memory
+ 	/*
+-	 * writes *must* be hardware frame aligned
++	 * use DMA, if possible / writes *must* be hardware frame aligned
  	 */
--	kobject_unregister(&pci->kobj);
-+	kobject_put(&pci->kobj);
- }
- 
- /***************************** EDAC PCI sysfs root **********************/
-@@ -364,14 +358,6 @@ int edac_pci_main_kobj_setup(void)
- 		goto decrement_count_fail;
- 	}
- 
--	/* Need the kobject hook ups, and name setting */
--	edac_pci_top_main_kobj.ktype = &ktype_edac_pci_main_kobj;
--	edac_pci_top_main_kobj.parent = &edac_class->kset.kobj;
+ 	if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
+ 	    (rq->sector & (sectors_per_frame - 1))) {
+-		cdrom_end_request(drive, 0);
+-		return ide_stopped;
+-	}
 -
--	err = kobject_set_name(&edac_pci_top_main_kobj, "pci");
--	if (err)
--		goto decrement_count_fail;
+-	/*
+-	 * disk has become write protected
+-	 */
+-	if (g->policy) {
+-		cdrom_end_request(drive, 0);
+-		return ide_stopped;
+-	}
 -
- 	/* Bump the reference count on this module to ensure the
- 	 * modules isn't unloaded until we deconstruct the top
- 	 * level main kobj for EDAC PCI
-@@ -383,23 +369,24 @@ int edac_pci_main_kobj_setup(void)
- 	}
+-	info->nsectors_buffered = 0;
++		if (write) {
++			cdrom_end_request(drive, 0);
++			return ide_stopped;
++		}
++		cd->dma = 0;
++	} else
++		cd->dma = drive->using_dma;
  
- 	/* Instanstiate the pci object */
--	/* FIXME: maybe new sysdev_create_subdir() */
--	err = kobject_register(&edac_pci_top_main_kobj);
-+	err = kobject_init_and_add(&edac_pci_top_main_kobj, &ktype_edac_pci_main_kobj,
-+				   &edac_class->kset.kobj, "pci");
- 	if (err) {
- 		debugf1("Failed to register '.../edac/pci'\n");
--		goto kobject_register_fail;
-+		goto kobject_init_and_add_fail;
- 	}
+-	/* use dma, if possible. we don't need to check more, since we
+-	 * know that the transfer is always (at least!) frame aligned */
+-	info->dma = drive->using_dma ? 1 : 0;
++	/* Clear the local sector buffer. */
++	cd->nsectors_buffered = 0;
  
- 	/* At this point, to 'release' the top level kobject
- 	 * for EDAC PCI, then edac_pci_main_kobj_teardown()
- 	 * must be used, for resources to be cleaned up properly
- 	 */
-+	kobject_uevent(&edac_pci_top_main_kobj, KOBJ_ADD);
- 	debugf1("Registered '.../edac/pci' kobject\n");
+-	info->devinfo.media_written = 1;
++	if (write)
++		cd->devinfo.media_written = 1;
  
- 	return 0;
+-	/* Start sending the write request to the drive. */
+-	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
++	/* Start sending the read/write request to the drive. */
++	return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
+ }
  
- 	/* Error unwind statck */
--kobject_register_fail:
-+kobject_init_and_add_fail:
- 	module_put(THIS_MODULE);
+ static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
+@@ -1958,7 +1285,10 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+ {
+ 	struct cdrom_info *info = drive->driver_data;
  
- decrement_count_fail:
-@@ -424,9 +411,9 @@ static void edac_pci_main_kobj_teardown(void)
- 	 * main kobj
- 	 */
- 	if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
--		debugf0("%s() called kobject_unregister on main kobj\n",
-+		debugf0("%s() called kobject_put on main kobj\n",
- 			__func__);
--		kobject_unregister(&edac_pci_top_main_kobj);
-+		kobject_put(&edac_pci_top_main_kobj);
- 	}
- }
+-	rq->cmd_flags |= REQ_QUIET;
++	if (blk_pc_request(rq))
++		rq->cmd_flags |= REQ_QUIET;
++	else
++		rq->cmd_flags &= ~REQ_FAILED;
  
-diff --git a/drivers/edac/pasemi_edac.c b/drivers/edac/pasemi_edac.c
-index 9007d06..9032091 100644
---- a/drivers/edac/pasemi_edac.c
-+++ b/drivers/edac/pasemi_edac.c
-@@ -225,7 +225,7 @@ static int __devinit pasemi_edac_probe(struct pci_dev *pdev,
- 		EDAC_FLAG_NONE;
- 	mci->mod_name = MODULE_NAME;
- 	mci->dev_name = pci_name(pdev);
--	mci->ctl_name = "pasemi,1682m-mc";
-+	mci->ctl_name = "pasemi,pwrficient-mc";
- 	mci->edac_check = pasemi_edac_check;
- 	mci->ctl_page_to_phys = NULL;
- 	pci_read_config_dword(pdev, MCCFG_SCRUB, &scrub);
-@@ -297,4 +297,4 @@ module_exit(pasemi_edac_exit);
+ 	info->dma = 0;
  
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Egor Martovetsky <egor at pasemi.com>");
--MODULE_DESCRIPTION("MC support for PA Semi PA6T-1682M memory controller");
-+MODULE_DESCRIPTION("MC support for PA Semi PWRficient memory controller");
-diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
-index 60f1a89..7e73cba 100644
---- a/drivers/firewire/fw-cdev.c
-+++ b/drivers/firewire/fw-cdev.c
-@@ -206,12 +206,13 @@ fill_bus_reset_event(struct fw_cdev_event_bus_reset *event,
+@@ -1995,9 +1325,9 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ 	struct cdrom_info *info = drive->driver_data;
  
- 	event->closure	     = client->bus_reset_closure;
- 	event->type          = FW_CDEV_EVENT_BUS_RESET;
-+	event->generation    = client->device->generation;
-+	smp_rmb();           /* node_id must not be older than generation */
- 	event->node_id       = client->device->node_id;
- 	event->local_node_id = card->local_node->node_id;
- 	event->bm_node_id    = 0; /* FIXME: We don't track the BM. */
- 	event->irm_node_id   = card->irm_node->node_id;
- 	event->root_node_id  = card->root_node->node_id;
--	event->generation    = card->generation;
- }
+ 	if (blk_fs_request(rq)) {
+-		if (CDROM_CONFIG_FLAGS(drive)->seeking) {
++		if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
+ 			unsigned long elapsed = jiffies - info->start_seek;
+-			int stat = HWIF(drive)->INB(IDE_STATUS_REG);
++			int stat = ide_read_status(drive);
  
- static void
-diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c
-index 56681b3..de9066e 100644
---- a/drivers/firewire/fw-device.c
-+++ b/drivers/firewire/fw-device.c
-@@ -27,6 +27,7 @@
- #include <linux/idr.h>
- #include <linux/rwsem.h>
- #include <asm/semaphore.h>
-+#include <asm/system.h>
- #include <linux/ctype.h>
- #include "fw-transaction.h"
- #include "fw-topology.h"
-@@ -182,9 +183,14 @@ static void fw_device_release(struct device *dev)
+ 			if ((stat & SEEK_STAT) != SEEK_STAT) {
+ 				if (elapsed < IDECD_SEEK_TIMEOUT) {
+@@ -2006,22 +1336,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+ 				}
+ 				printk (KERN_ERR "%s: DSC timeout\n", drive->name);
+ 			}
+-			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
++			info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
+ 		}
+ 		if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
+ 			action = cdrom_start_seek(drive, block);
+-		} else {
+-			if (rq_data_dir(rq) == READ)
+-				action = cdrom_start_read(drive, block);
+-			else
+-				action = cdrom_start_write(drive, rq);
+-		}
++		} else
++			action = cdrom_start_rw(drive, rq);
+ 		info->last_block = block;
+ 		return action;
+-	} else if (rq->cmd_type == REQ_TYPE_SENSE ||
++	} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
+ 		   rq->cmd_type == REQ_TYPE_ATA_PC) {
+-		return cdrom_do_packet_command(drive);
+-	} else if (blk_pc_request(rq)) {
+ 		return cdrom_do_block_pc(drive, rq);
+ 	} else if (blk_special_request(rq)) {
+ 		/*
+@@ -2048,141 +1372,33 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
+  * can also be NULL, in which case no sense information is returned.
+  */
  
- int fw_device_enable_phys_dma(struct fw_device *device)
+-#if ! STANDARD_ATAPI
+-static inline
+-int bin2bcd (int x)
+-{
+-	return (x%10) | ((x/10) << 4);
+-}
+-
+-
+-static inline
+-int bcd2bin (int x)
+-{
+-	return (x >> 4) * 10 + (x & 0x0f);
+-}
+-
+ static
+ void msf_from_bcd (struct atapi_msf *msf)
  {
-+	int generation = device->generation;
-+
-+	/* device->node_id, accessed below, must not be older than generation */
-+	smp_rmb();
-+
- 	return device->card->driver->enable_phys_dma(device->card,
- 						     device->node_id,
--						     device->generation);
-+						     generation);
- }
- EXPORT_SYMBOL(fw_device_enable_phys_dma);
- 
-@@ -384,17 +390,21 @@ complete_transaction(struct fw_card *card, int rcode,
- 	complete(&callback_data->done);
+-	msf->minute = bcd2bin (msf->minute);
+-	msf->second = bcd2bin (msf->second);
+-	msf->frame  = bcd2bin (msf->frame);
+-}
+-
+-#endif /* not STANDARD_ATAPI */
+-
+-
+-static inline
+-void lba_to_msf (int lba, byte *m, byte *s, byte *f)
+-{
+-	lba += CD_MSF_OFFSET;
+-	lba &= 0xffffff;  /* negative lbas use only 24 bits */
+-	*m = lba / (CD_SECS * CD_FRAMES);
+-	lba %= (CD_SECS * CD_FRAMES);
+-	*s = lba / CD_FRAMES;
+-	*f = lba % CD_FRAMES;
+-}
+-
+-
+-static inline
+-int msf_to_lba (byte m, byte s, byte f)
+-{
+-	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
++	msf->minute = BCD2BIN(msf->minute);
++	msf->second = BCD2BIN(msf->second);
++	msf->frame  = BCD2BIN(msf->frame);
  }
  
--static int read_rom(struct fw_device *device, int index, u32 * data)
-+static int
-+read_rom(struct fw_device *device, int generation, int index, u32 *data)
+-static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
++int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
  {
- 	struct read_quadlet_callback_data callback_data;
- 	struct fw_transaction t;
- 	u64 offset;
+ 	struct request req;
+ 	struct cdrom_info *info = drive->driver_data;
+ 	struct cdrom_device_info *cdi = &info->devinfo;
  
-+	/* device->node_id, accessed below, must not be older than generation */
-+	smp_rmb();
-+
- 	init_completion(&callback_data.done);
+-	cdrom_prepare_request(drive, &req);
++	ide_cd_init_rq(drive, &req);
  
- 	offset = 0xfffff0000400ULL + index * 4;
- 	fw_send_request(device->card, &t, TCODE_READ_QUADLET_REQUEST,
--			device->node_id, device->generation, device->max_speed,
-+			device->node_id, generation, device->max_speed,
- 			offset, NULL, 4, complete_transaction, &callback_data);
+ 	req.sense = sense;
+ 	req.cmd[0] = GPCMD_TEST_UNIT_READY;
+ 	req.cmd_flags |= REQ_QUIET;
  
- 	wait_for_completion(&callback_data.done);
-@@ -404,7 +414,14 @@ static int read_rom(struct fw_device *device, int index, u32 * data)
- 	return callback_data.rcode;
+-#if ! STANDARD_ATAPI
+-        /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
+-           switch CDs instead of supporting the LOAD_UNLOAD opcode   */
+-
++	/*
++	 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
++	 * switch CDs instead of supporting the LOAD_UNLOAD opcode.
++	 */
+ 	req.cmd[7] = cdi->sanyo_slot % 3;
+-#endif /* not STANDARD_ATAPI */
+-
+-	return cdrom_queue_packet_command(drive, &req);
+-}
+ 
+-
+-/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
+-static int
+-cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
+-{
+-	struct request_sense my_sense;
+-	struct request req;
+-	int stat;
+-
+-	if (sense == NULL)
+-		sense = &my_sense;
+-
+-	/* If the drive cannot lock the door, just pretend. */
+-	if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
+-		stat = 0;
+-	} else {
+-		cdrom_prepare_request(drive, &req);
+-		req.sense = sense;
+-		req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
+-		req.cmd[4] = lockflag ? 1 : 0;
+-		stat = cdrom_queue_packet_command(drive, &req);
+-	}
+-
+-	/* If we got an illegal field error, the drive
+-	   probably cannot lock the door. */
+-	if (stat != 0 &&
+-	    sense->sense_key == ILLEGAL_REQUEST &&
+-	    (sense->asc == 0x24 || sense->asc == 0x20)) {
+-		printk (KERN_ERR "%s: door locking not supported\n",
+-			drive->name);
+-		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
+-		stat = 0;
+-	}
+-	
+-	/* no medium, that's alright. */
+-	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
+-		stat = 0;
+-
+-	if (stat == 0)
+-		CDROM_STATE_FLAGS(drive)->door_locked = lockflag;
+-
+-	return stat;
+-}
+-
+-
+-/* Eject the disk if EJECTFLAG is 0.
+-   If EJECTFLAG is 1, try to reload the disk. */
+-static int cdrom_eject(ide_drive_t *drive, int ejectflag,
+-		       struct request_sense *sense)
+-{
+-	struct request req;
+-	char loej = 0x02;
+-
+-	if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
+-		return -EDRIVE_CANT_DO_THIS;
+-	
+-	/* reload fails on some drives, if the tray is locked */
+-	if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
+-		return 0;
+-
+-	cdrom_prepare_request(drive, &req);
+-
+-	/* only tell drive to close tray if open, if it can do that */
+-	if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray)
+-		loej = 0;
+-
+-	req.sense = sense;
+-	req.cmd[0] = GPCMD_START_STOP_UNIT;
+-	req.cmd[4] = loej | (ejectflag != 0);
+-	return cdrom_queue_packet_command(drive, &req);
++	return ide_cd_queue_pc(drive, &req);
  }
  
--static int read_bus_info_block(struct fw_device *device)
-+/*
-+ * Read the bus info block, perform a speed probe, and read all of the rest of
-+ * the config ROM.  We do all this with a cached bus generation.  If the bus
-+ * generation changes under us, read_bus_info_block will fail and get retried.
-+ * It's better to start all over in this case because the node from which we
-+ * are reading the ROM may have changed the ROM during the reset.
-+ */
-+static int read_bus_info_block(struct fw_device *device, int generation)
+ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
+@@ -2197,7 +1413,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
+ 	int stat;
+ 	struct request req;
+ 
+-	cdrom_prepare_request(drive, &req);
++	ide_cd_init_rq(drive, &req);
+ 
+ 	req.sense = sense;
+ 	req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
+@@ -2205,7 +1421,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
+ 	req.data_len = sizeof(capbuf);
+ 	req.cmd_flags |= REQ_QUIET;
+ 
+-	stat = cdrom_queue_packet_command(drive, &req);
++	stat = ide_cd_queue_pc(drive, &req);
+ 	if (stat == 0) {
+ 		*capacity = 1 + be32_to_cpu(capbuf.lba);
+ 		*sectors_per_frame =
+@@ -2221,7 +1437,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
  {
- 	static u32 rom[256];
- 	u32 stack[16], sp, key;
-@@ -414,7 +431,7 @@ static int read_bus_info_block(struct fw_device *device)
+ 	struct request req;
  
- 	/* First read the bus info block. */
- 	for (i = 0; i < 5; i++) {
--		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
-+		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
- 			return -1;
- 		/*
- 		 * As per IEEE1212 7.2, during power-up, devices can
-@@ -449,7 +466,8 @@ static int read_bus_info_block(struct fw_device *device)
- 			device->max_speed = device->card->link_speed;
+-	cdrom_prepare_request(drive, &req);
++	ide_cd_init_rq(drive, &req);
  
- 		while (device->max_speed > SCODE_100) {
--			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)
-+			if (read_rom(device, generation, 0, &dummy) ==
-+			    RCODE_COMPLETE)
- 				break;
- 			device->max_speed--;
- 		}
-@@ -482,7 +500,7 @@ static int read_bus_info_block(struct fw_device *device)
- 			return -1;
+ 	req.sense = sense;
+ 	req.data =  buf;
+@@ -2236,12 +1452,11 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
+ 	if (msf_flag)
+ 		req.cmd[1] = 2;
  
- 		/* Read header quadlet for the block to get the length. */
--		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
-+		if (read_rom(device, generation, i, &rom[i]) != RCODE_COMPLETE)
- 			return -1;
- 		end = i + (rom[i] >> 16) + 1;
- 		i++;
-@@ -501,7 +519,8 @@ static int read_bus_info_block(struct fw_device *device)
- 		 * it references another block, and push it in that case.
- 		 */
- 		while (i < end) {
--			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)
-+			if (read_rom(device, generation, i, &rom[i]) !=
-+			    RCODE_COMPLETE)
- 				return -1;
- 			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&
- 			    sp < ARRAY_SIZE(stack))
-@@ -648,7 +667,7 @@ static void fw_device_init(struct work_struct *work)
- 	 * device.
- 	 */
+-	return cdrom_queue_packet_command(drive, &req);
++	return ide_cd_queue_pc(drive, &req);
+ }
  
--	if (read_bus_info_block(device) < 0) {
-+	if (read_bus_info_block(device, device->generation) < 0) {
- 		if (device->config_rom_retries < MAX_RETRIES) {
- 			device->config_rom_retries++;
- 			schedule_delayed_work(&device->work, RETRY_DELAY);
-@@ -801,6 +820,7 @@ void fw_node_event(struct fw_card *card, struct fw_node *node, int event)
+-
+ /* Try to read the entire TOC for the disk into our internal buffer. */
+-static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
++int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ {
+ 	int stat, ntracks, i;
+ 	struct cdrom_info *info = drive->driver_data;
+@@ -2268,7 +1483,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 	   If it is, just return. */
+ 	(void) cdrom_check_status(drive, sense);
  
- 		device = node->data;
- 		device->node_id = node->node_id;
-+		smp_wmb();  /* update node_id before generation */
- 		device->generation = card->generation;
- 		if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {
- 			PREPARE_DELAYED_WORK(&device->work, fw_device_update);
-diff --git a/drivers/firewire/fw-device.h b/drivers/firewire/fw-device.h
-index 894d4a9..0854fe2 100644
---- a/drivers/firewire/fw-device.h
-+++ b/drivers/firewire/fw-device.h
-@@ -35,6 +35,18 @@ struct fw_attribute_group {
- 	struct attribute *attrs[11];
- };
+-	if (CDROM_STATE_FLAGS(drive)->toc_valid)
++	if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
+ 		return 0;
  
-+/*
-+ * Note, fw_device.generation always has to be read before fw_device.node_id.
-+ * Use SMP memory barriers to ensure this.  Otherwise requests will be sent
-+ * to an outdated node_id if the generation was updated in the meantime due
-+ * to a bus reset.
-+ *
-+ * Likewise, fw-core will take care to update .node_id before .generation so
-+ * that whenever fw_device.generation is current WRT the actual bus generation,
-+ * fw_device.node_id is guaranteed to be current too.
-+ *
-+ * The same applies to fw_device.card->node_id vs. fw_device.generation.
-+ */
- struct fw_device {
- 	atomic_t state;
- 	struct fw_node *node;
-diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c
-index 436a855..7ebad3c 100644
---- a/drivers/firewire/fw-ohci.c
-+++ b/drivers/firewire/fw-ohci.c
-@@ -98,17 +98,48 @@ struct context;
- typedef int (*descriptor_callback_t)(struct context *ctx,
- 				     struct descriptor *d,
- 				     struct descriptor *last);
-+
-+/*
-+ * A buffer that contains a block of DMA-able coherent memory used for
-+ * storing a portion of a DMA descriptor program.
-+ */
-+struct descriptor_buffer {
-+	struct list_head list;
-+	dma_addr_t buffer_bus;
-+	size_t buffer_size;
-+	size_t used;
-+	struct descriptor buffer[0];
-+};
-+
- struct context {
- 	struct fw_ohci *ohci;
- 	u32 regs;
-+	int total_allocation;
+ 	/* Try to get the total cdrom capacity and sector size. */
+@@ -2290,12 +1505,10 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 	if (stat)
+ 		return stat;
  
--	struct descriptor *buffer;
--	dma_addr_t buffer_bus;
--	size_t buffer_size;
--	struct descriptor *head_descriptor;
--	struct descriptor *tail_descriptor;
--	struct descriptor *tail_descriptor_last;
--	struct descriptor *prev_descriptor;
-+	/*
-+	 * List of page-sized buffers for storing DMA descriptors.
-+	 * Head of list contains buffers in use and tail of list contains
-+	 * free buffers.
-+	 */
-+	struct list_head buffer_list;
-+
-+	/*
-+	 * Pointer to a buffer inside buffer_list that contains the tail
-+	 * end of the current DMA program.
-+	 */
-+	struct descriptor_buffer *buffer_tail;
-+
-+	/*
-+	 * The descriptor containing the branch address of the first
-+	 * descriptor that has not yet been filled by the device.
-+	 */
-+	struct descriptor *last;
-+
-+	/*
-+	 * The last descriptor in the DMA program.  It contains the branch
-+	 * address that must be updated upon appending a new descriptor.
-+	 */
-+	struct descriptor *prev;
+-#if ! STANDARD_ATAPI
+-	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
+-		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
+-		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
++	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
++		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
++		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
+ 	}
+-#endif  /* not STANDARD_ATAPI */
  
- 	descriptor_callback_t callback;
+ 	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+ 	if (ntracks <= 0)
+@@ -2327,16 +1540,13 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 					   (ntracks + 1) *
+ 					   sizeof(struct atapi_toc_entry),
+ 					   sense);
+-		if (stat) {
++		if (stat)
+ 			return stat;
+-		}
+-#if ! STANDARD_ATAPI
+-		if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
+-			toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
+-			toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
+-		} else
+-#endif  /* not STANDARD_ATAPI */
+-		{
++
++		if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
++			toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
++			toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
++		} else {
+ 			toc->hdr.first_track = CDROM_LEADOUT;
+ 			toc->hdr.last_track = CDROM_LEADOUT;
+ 		}
+@@ -2347,21 +1557,17 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
  
-@@ -125,6 +156,7 @@ struct context {
- struct iso_context {
- 	struct fw_iso_context base;
- 	struct context context;
-+	int excess_bytes;
- 	void *header;
- 	size_t header_length;
- };
-@@ -197,8 +229,6 @@ static inline struct fw_ohci *fw_ohci(struct fw_card *card)
- #define SELF_ID_BUF_SIZE		0x800
- #define OHCI_TCODE_PHY_PACKET		0x0e
- #define OHCI_VERSION_1_1		0x010010
--#define ISO_BUFFER_SIZE			(64 * 1024)
--#define AT_BUFFER_SIZE			4096
+ 	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
  
- static char ohci_driver_name[] = KBUILD_MODNAME;
+-#if ! STANDARD_ATAPI
+-	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
+-		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
+-		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
++	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
++		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
++		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
+ 	}
+-#endif  /* not STANDARD_ATAPI */
  
-@@ -455,71 +485,108 @@ find_branch_descriptor(struct descriptor *d, int z)
- static void context_tasklet(unsigned long data)
- {
- 	struct context *ctx = (struct context *) data;
--	struct fw_ohci *ohci = ctx->ohci;
- 	struct descriptor *d, *last;
- 	u32 address;
- 	int z;
-+	struct descriptor_buffer *desc;
+-	for (i=0; i<=ntracks; i++) {
+-#if ! STANDARD_ATAPI
+-		if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
+-			if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd)
+-				toc->ent[i].track = bcd2bin(toc->ent[i].track);
++	for (i = 0; i <= ntracks; i++) {
++		if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
++			if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
++				toc->ent[i].track = BCD2BIN(toc->ent[i].track);
+ 			msf_from_bcd(&toc->ent[i].addr.msf);
+ 		}
+-#endif  /* not STANDARD_ATAPI */
+ 		toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
+ 						   toc->ent[i].addr.msf.second,
+ 						   toc->ent[i].addr.msf.frame);
+@@ -2381,8 +1587,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
+ 	}
  
--	dma_sync_single_for_cpu(ohci->card.device, ctx->buffer_bus,
--				ctx->buffer_size, DMA_TO_DEVICE);
--
--	d    = ctx->tail_descriptor;
--	last = ctx->tail_descriptor_last;
--
-+	desc = list_entry(ctx->buffer_list.next,
-+			struct descriptor_buffer, list);
-+	last = ctx->last;
- 	while (last->branch_address != 0) {
-+		struct descriptor_buffer *old_desc = desc;
- 		address = le32_to_cpu(last->branch_address);
- 		z = address & 0xf;
--		d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d);
-+		address &= ~0xf;
-+
-+		/* If the branch address points to a buffer outside of the
-+		 * current buffer, advance to the next buffer. */
-+		if (address < desc->buffer_bus ||
-+				address >= desc->buffer_bus + desc->used)
-+			desc = list_entry(desc->list.next,
-+					struct descriptor_buffer, list);
-+		d = desc->buffer + (address - desc->buffer_bus) / sizeof(*d);
- 		last = find_branch_descriptor(d, z);
+-#if ! STANDARD_ATAPI
+-	if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
++	if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
+ 		/* Re-read multisession information using MSF format */
+ 		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
+ 					   sizeof(ms_tmp), sense);
+@@ -2394,7 +1599,6 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 					  	   ms_tmp.ent.addr.msf.second,
+ 						   ms_tmp.ent.addr.msf.frame);
+ 	}
+-#endif  /* not STANDARD_ATAPI */
  
- 		if (!ctx->callback(ctx, d, last))
- 			break;
+ 	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
  
--		ctx->tail_descriptor      = d;
--		ctx->tail_descriptor_last = last;
-+		if (old_desc != desc) {
-+			/* If we've advanced to the next buffer, move the
-+			 * previous buffer to the free list. */
-+			unsigned long flags;
-+			old_desc->used = 0;
-+			spin_lock_irqsave(&ctx->ohci->lock, flags);
-+			list_move_tail(&old_desc->list, &ctx->buffer_list);
-+			spin_unlock_irqrestore(&ctx->ohci->lock, flags);
-+		}
-+		ctx->last = last;
+@@ -2407,278 +1611,22 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
  	}
- }
  
-+/*
-+ * Allocate a new buffer and add it to the list of free buffers for this
-+ * context.  Must be called with ohci->lock held.
-+ */
-+static int
-+context_add_buffer(struct context *ctx)
-+{
-+	struct descriptor_buffer *desc;
-+	dma_addr_t bus_addr;
-+	int offset;
-+
-+	/*
-+	 * 16MB of descriptors should be far more than enough for any DMA
-+	 * program.  This will catch run-away userspace or DoS attacks.
-+	 */
-+	if (ctx->total_allocation >= 16*1024*1024)
-+		return -ENOMEM;
-+
-+	desc = dma_alloc_coherent(ctx->ohci->card.device, PAGE_SIZE,
-+			&bus_addr, GFP_ATOMIC);
-+	if (!desc)
-+		return -ENOMEM;
-+
-+	offset = (void *)&desc->buffer - (void *)desc;
-+	desc->buffer_size = PAGE_SIZE - offset;
-+	desc->buffer_bus = bus_addr + offset;
-+	desc->used = 0;
-+
-+	list_add_tail(&desc->list, &ctx->buffer_list);
-+	ctx->total_allocation += PAGE_SIZE;
-+
-+	return 0;
-+}
-+
- static int
- context_init(struct context *ctx, struct fw_ohci *ohci,
--	     size_t buffer_size, u32 regs,
--	     descriptor_callback_t callback)
-+	     u32 regs, descriptor_callback_t callback)
- {
- 	ctx->ohci = ohci;
- 	ctx->regs = regs;
--	ctx->buffer_size = buffer_size;
--	ctx->buffer = kmalloc(buffer_size, GFP_KERNEL);
--	if (ctx->buffer == NULL)
-+	ctx->total_allocation = 0;
-+
-+	INIT_LIST_HEAD(&ctx->buffer_list);
-+	if (context_add_buffer(ctx) < 0)
- 		return -ENOMEM;
+ 	/* Remember that we've read this stuff. */
+-	CDROM_STATE_FLAGS(drive)->toc_valid = 1;
++	info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
  
-+	ctx->buffer_tail = list_entry(ctx->buffer_list.next,
-+			struct descriptor_buffer, list);
-+
- 	tasklet_init(&ctx->tasklet, context_tasklet, (unsigned long)ctx);
- 	ctx->callback = callback;
+ 	return 0;
+ }
  
--	ctx->buffer_bus =
--		dma_map_single(ohci->card.device, ctx->buffer,
--			       buffer_size, DMA_TO_DEVICE);
--	if (dma_mapping_error(ctx->buffer_bus)) {
--		kfree(ctx->buffer);
--		return -ENOMEM;
+-
+-static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
+-				 int buflen, struct request_sense *sense)
+-{
+-	struct request req;
+-
+-	cdrom_prepare_request(drive, &req);
+-
+-	req.sense = sense;
+-	req.data = buf;
+-	req.data_len = buflen;
+-	req.cmd[0] = GPCMD_READ_SUBCHANNEL;
+-	req.cmd[1] = 2;     /* MSF addressing */
+-	req.cmd[2] = 0x40;  /* request subQ data */
+-	req.cmd[3] = format;
+-	req.cmd[7] = (buflen >> 8);
+-	req.cmd[8] = (buflen & 0xff);
+-	return cdrom_queue_packet_command(drive, &req);
+-}
+-
+-/* ATAPI cdrom drives are free to select the speed you request or any slower
+-   rate :-( Requesting too fast a speed will _not_ produce an error. */
+-static int cdrom_select_speed(ide_drive_t *drive, int speed,
+-			      struct request_sense *sense)
+-{
+-	struct request req;
+-	cdrom_prepare_request(drive, &req);
+-
+-	req.sense = sense;
+-	if (speed == 0)
+-		speed = 0xffff; /* set to max */
+-	else
+-		speed *= 177;   /* Nx to kbytes/s */
+-
+-	req.cmd[0] = GPCMD_SET_SPEED;
+-	/* Read Drive speed in kbytes/second MSB */
+-	req.cmd[2] = (speed >> 8) & 0xff;	
+-	/* Read Drive speed in kbytes/second LSB */
+-	req.cmd[3] = speed & 0xff;
+-	if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
+-	    CDROM_CONFIG_FLAGS(drive)->cd_rw ||
+-	    CDROM_CONFIG_FLAGS(drive)->dvd_r) {
+-		/* Write Drive speed in kbytes/second MSB */
+-		req.cmd[4] = (speed >> 8) & 0xff;
+-		/* Write Drive speed in kbytes/second LSB */
+-		req.cmd[5] = speed & 0xff;
+-       }
+-
+-	return cdrom_queue_packet_command(drive, &req);
+-}
+-
+-static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
+-{
+-	struct request_sense sense;
+-	struct request req;
+-
+-	cdrom_prepare_request(drive, &req);
+-
+-	req.sense = &sense;
+-	req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+-	lba_to_msf(lba_start, &req.cmd[3], &req.cmd[4], &req.cmd[5]);
+-	lba_to_msf(lba_end-1, &req.cmd[6], &req.cmd[7], &req.cmd[8]);
+-
+-	return cdrom_queue_packet_command(drive, &req);
+-}
+-
+-static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
+-				struct atapi_toc_entry **ent)
+-{
+-	struct cdrom_info *info = drive->driver_data;
+-	struct atapi_toc *toc = info->toc;
+-	int ntracks;
+-
+-	/*
+-	 * don't serve cached data, if the toc isn't valid
+-	 */
+-	if (!CDROM_STATE_FLAGS(drive)->toc_valid)
+-		return -EINVAL;
+-
+-	/* Check validity of requested track number. */
+-	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
+-	if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
+-	if (track == CDROM_LEADOUT)
+-		*ent = &toc->ent[ntracks];
+-	else if (track < toc->hdr.first_track ||
+-		 track > toc->hdr.last_track)
+-		return -EINVAL;
+-	else
+-		*ent = &toc->ent[track - toc->hdr.first_track];
+-
+-	return 0;
+-}
+-
+-/* the generic packet interface to cdrom.c */
+-static int ide_cdrom_packet(struct cdrom_device_info *cdi,
+-			    struct packet_command *cgc)
+-{
+-	struct request req;
+-	ide_drive_t *drive = cdi->handle;
+-
+-	if (cgc->timeout <= 0)
+-		cgc->timeout = ATAPI_WAIT_PC;
+-
+-	/* here we queue the commands from the uniform CD-ROM
+-	   layer. the packet must be complete, as we do not
+-	   touch it at all. */
+-	cdrom_prepare_request(drive, &req);
+-	memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
+-	if (cgc->sense)
+-		memset(cgc->sense, 0, sizeof(struct request_sense));
+-	req.data = cgc->buffer;
+-	req.data_len = cgc->buflen;
+-	req.timeout = cgc->timeout;
+-
+-	if (cgc->quiet)
+-		req.cmd_flags |= REQ_QUIET;
+-
+-	req.sense = cgc->sense;
+-	cgc->stat = cdrom_queue_packet_command(drive, &req);
+-	if (!cgc->stat)
+-		cgc->buflen -= req.data_len;
+-	return cgc->stat;
+-}
+-
+-static
+-int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
+-			   unsigned int cmd, void *arg)
+-			   
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	struct cdrom_info *info = drive->driver_data;
+-	int stat;
+-
+-	switch (cmd) {
+-	/*
+-	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
+-	 * atapi doesn't support it
+-	 */
+-	case CDROMPLAYTRKIND: {
+-		unsigned long lba_start, lba_end;
+-		struct cdrom_ti *ti = arg;
+-		struct atapi_toc_entry *first_toc, *last_toc;
+-
+-		stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
+-		if (stat)
+-			return stat;
+-
+-		stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
+-		if (stat)
+-			return stat;
+-
+-		if (ti->cdti_trk1 != CDROM_LEADOUT)
+-			++last_toc;
+-		lba_start = first_toc->addr.lba;
+-		lba_end   = last_toc->addr.lba;
+-
+-		if (lba_end <= lba_start)
+-			return -EINVAL;
+-
+-		return cdrom_play_audio(drive, lba_start, lba_end);
+-	}
+-
+-	case CDROMREADTOCHDR: {
+-		struct cdrom_tochdr *tochdr = arg;
+-		struct atapi_toc *toc;
+-
+-		/* Make sure our saved TOC is valid. */
+-		stat = cdrom_read_toc(drive, NULL);
+-		if (stat)
+-			return stat;
+-
+-		toc = info->toc;
+-		tochdr->cdth_trk0 = toc->hdr.first_track;
+-		tochdr->cdth_trk1 = toc->hdr.last_track;
+-
+-		return 0;
+-	}
+-
+-	case CDROMREADTOCENTRY: {
+-		struct cdrom_tocentry *tocentry = arg;
+-		struct atapi_toc_entry *toce;
+-
+-		stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
+-		if (stat)
+-			return stat;
+-
+-		tocentry->cdte_ctrl = toce->control;
+-		tocentry->cdte_adr  = toce->adr;
+-		if (tocentry->cdte_format == CDROM_MSF) {
+-			lba_to_msf (toce->addr.lba,
+-				   &tocentry->cdte_addr.msf.minute,
+-				   &tocentry->cdte_addr.msf.second,
+-				   &tocentry->cdte_addr.msf.frame);
+-		} else
+-			tocentry->cdte_addr.lba = toce->addr.lba;
+-
+-		return 0;
+-	}
+-
+-	default:
+-		return -EINVAL;
+-	}
+-}
+-
+-static
+-int ide_cdrom_reset (struct cdrom_device_info *cdi)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	struct request_sense sense;
+-	struct request req;
+-	int ret;
+-
+-	cdrom_prepare_request(drive, &req);
+-	req.cmd_type = REQ_TYPE_SPECIAL;
+-	req.cmd_flags = REQ_QUIET;
+-	ret = ide_do_drive_cmd(drive, &req, ide_wait);
+-
+-	/*
+-	 * A reset will unlock the door. If it was previously locked,
+-	 * lock it again.
+-	 */
+-	if (CDROM_STATE_FLAGS(drive)->door_locked)
+-		(void) cdrom_lockdoor(drive, 1, &sense);
+-
+-	return ret;
+-}
+-
+-
+-static
+-int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	struct request_sense sense;
+-
+-	if (position) {
+-		int stat = cdrom_lockdoor(drive, 0, &sense);
+-		if (stat)
+-			return stat;
 -	}
 -
--	ctx->head_descriptor      = ctx->buffer;
--	ctx->prev_descriptor      = ctx->buffer;
--	ctx->tail_descriptor      = ctx->buffer;
--	ctx->tail_descriptor_last = ctx->buffer;
+-	return cdrom_eject(drive, !position, &sense);
+-}
 -
- 	/*
- 	 * We put a dummy descriptor in the buffer that has a NULL
- 	 * branch address and looks like it's been sent.  That way we
--	 * have a descriptor to append DMA programs to.  Also, the
--	 * ring buffer invariant is that it always has at least one
--	 * element so that head == tail means buffer full.
-+	 * have a descriptor to append DMA programs to.
- 	 */
+-static
+-int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	return cdrom_lockdoor(drive, lock, NULL);
+-}
 -
--	memset(ctx->head_descriptor, 0, sizeof(*ctx->head_descriptor));
--	ctx->head_descriptor->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
--	ctx->head_descriptor->transfer_status = cpu_to_le16(0x8011);
--	ctx->head_descriptor++;
-+	memset(ctx->buffer_tail->buffer, 0, sizeof(*ctx->buffer_tail->buffer));
-+	ctx->buffer_tail->buffer->control = cpu_to_le16(DESCRIPTOR_OUTPUT_LAST);
-+	ctx->buffer_tail->buffer->transfer_status = cpu_to_le16(0x8011);
-+	ctx->buffer_tail->used += sizeof(*ctx->buffer_tail->buffer);
-+	ctx->last = ctx->buffer_tail->buffer;
-+	ctx->prev = ctx->buffer_tail->buffer;
- 
- 	return 0;
- }
-@@ -528,35 +595,42 @@ static void
- context_release(struct context *ctx)
+-static
+-int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
++int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
  {
- 	struct fw_card *card = &ctx->ohci->card;
-+	struct descriptor_buffer *desc, *tmp;
+ 	struct cdrom_info *info = drive->driver_data;
+ 	struct cdrom_device_info *cdi = &info->devinfo;
+ 	struct packet_command cgc;
+-	int stat, attempts = 3, size = sizeof(*cap);
++	int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
  
--	dma_unmap_single(card->device, ctx->buffer_bus,
--			 ctx->buffer_size, DMA_TO_DEVICE);
--	kfree(ctx->buffer);
-+	list_for_each_entry_safe(desc, tmp, &ctx->buffer_list, list)
-+		dma_free_coherent(card->device, PAGE_SIZE, desc,
-+			desc->buffer_bus -
-+			((void *)&desc->buffer - (void *)desc));
+-	/*
+-	 * ACER50 (and others?) require the full spec length mode sense
+-	 * page capabilities size, but older drives break.
+-	 */
+-	if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
+-	    !strcmp(drive->id->model, "WPI CDS-32X")))
+-		size -= sizeof(cap->pad);
++	if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
++		size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
+ 
+-	init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
++	init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
+ 	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+ 		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
+ 		if (!stat)
+@@ -2687,177 +1635,33 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_pag
+ 	return stat;
  }
  
-+/* Must be called with ohci->lock held */
- static struct descriptor *
- context_get_descriptors(struct context *ctx, int z, dma_addr_t *d_bus)
- {
--	struct descriptor *d, *tail, *end;
+-static
+-void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap)
+-{
+-	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
+-	if (!drive->id->model[0] &&
+-	    !strncmp(drive->id->fw_rev, "241N", 4)) {
+-		CDROM_STATE_FLAGS(drive)->current_speed  =
+-			(le16_to_cpu(cap->curspeed) + (176/2)) / 176;
+-		CDROM_CONFIG_FLAGS(drive)->max_speed =
+-			(le16_to_cpu(cap->maxspeed) + (176/2)) / 176;
+-	} else {
+-		CDROM_STATE_FLAGS(drive)->current_speed  =
+-			(be16_to_cpu(cap->curspeed) + (176/2)) / 176;
+-		CDROM_CONFIG_FLAGS(drive)->max_speed =
+-			(be16_to_cpu(cap->maxspeed) + (176/2)) / 176;
+-	}
+-}
 -
--	d = ctx->head_descriptor;
--	tail = ctx->tail_descriptor;
--	end = ctx->buffer + ctx->buffer_size / sizeof(*d);
+-static
+-int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	struct request_sense sense;
+-	struct atapi_capabilities_page cap;
+-	int stat;
 -
--	if (d + z <= tail) {
--		goto has_space;
--	} else if (d > tail && d + z <= end) {
--		goto has_space;
--	} else if (d > tail && ctx->buffer + z <= tail) {
--		d = ctx->buffer;
--		goto has_space;
+-	if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
+-		return stat;
+-
+-	if (!ide_cdrom_get_capabilities(drive, &cap)) {
+-		ide_cdrom_update_speed(drive, &cap);
+-		cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
 -	}
-+	struct descriptor *d = NULL;
-+	struct descriptor_buffer *desc = ctx->buffer_tail;
-+
-+	if (z * sizeof(*d) > desc->buffer_size)
-+		return NULL;
- 
--	return NULL;
-+	if (z * sizeof(*d) > desc->buffer_size - desc->used) {
-+		/* No room for the descriptor in this buffer, so advance to the
-+		 * next one. */
-+
-+		if (desc->list.next == &ctx->buffer_list) {
-+			/* If there is no free buffer next in the list,
-+			 * allocate one. */
-+			if (context_add_buffer(ctx) < 0)
-+				return NULL;
-+		}
-+		desc = list_entry(desc->list.next,
-+				struct descriptor_buffer, list);
-+		ctx->buffer_tail = desc;
-+	}
- 
-- has_space:
-+	d = desc->buffer + desc->used / sizeof(*d);
- 	memset(d, 0, z * sizeof(*d));
--	*d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d);
-+	*d_bus = desc->buffer_bus + desc->used;
- 
- 	return d;
- }
-@@ -566,7 +640,7 @@ static void context_run(struct context *ctx, u32 extra)
- 	struct fw_ohci *ohci = ctx->ohci;
- 
- 	reg_write(ohci, COMMAND_PTR(ctx->regs),
--		  le32_to_cpu(ctx->tail_descriptor_last->branch_address));
-+		  le32_to_cpu(ctx->last->branch_address));
- 	reg_write(ohci, CONTROL_CLEAR(ctx->regs), ~0);
- 	reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_RUN | extra);
- 	flush_writes(ohci);
-@@ -576,15 +650,13 @@ static void context_append(struct context *ctx,
- 			   struct descriptor *d, int z, int extra)
- {
- 	dma_addr_t d_bus;
-+	struct descriptor_buffer *desc = ctx->buffer_tail;
- 
--	d_bus = ctx->buffer_bus + (d - ctx->buffer) * sizeof(*d);
-+	d_bus = desc->buffer_bus + (d - desc->buffer) * sizeof(*d);
- 
--	ctx->head_descriptor = d + z + extra;
--	ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z);
--	ctx->prev_descriptor = find_branch_descriptor(d, z);
+-        return 0;
+-}
 -
--	dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus,
--				   ctx->buffer_size, DMA_TO_DEVICE);
-+	desc->used += (z + extra) * sizeof(*d);
-+	ctx->prev->branch_address = cpu_to_le32(d_bus | z);
-+	ctx->prev = find_branch_descriptor(d, z);
- 
- 	reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
- 	flush_writes(ctx->ohci);
-@@ -1078,6 +1150,13 @@ static irqreturn_t irq_handler(int irq, void *data)
- 	if (unlikely(event & OHCI1394_postedWriteErr))
- 		fw_error("PCI posted write error\n");
- 
-+	if (unlikely(event & OHCI1394_cycleTooLong)) {
-+		if (printk_ratelimit())
-+			fw_notify("isochronous cycle too long\n");
-+		reg_write(ohci, OHCI1394_LinkControlSet,
-+			  OHCI1394_LinkControl_cycleMaster);
-+	}
-+
- 	if (event & OHCI1394_cycle64Seconds) {
- 		cycle_time = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
- 		if ((cycle_time & 0x80000000) == 0)
-@@ -1151,8 +1230,8 @@ static int ohci_enable(struct fw_card *card, u32 *config_rom, size_t length)
- 		  OHCI1394_RQPkt | OHCI1394_RSPkt |
- 		  OHCI1394_reqTxComplete | OHCI1394_respTxComplete |
- 		  OHCI1394_isochRx | OHCI1394_isochTx |
--		  OHCI1394_postedWriteErr | OHCI1394_cycle64Seconds |
--		  OHCI1394_masterIntEnable);
-+		  OHCI1394_postedWriteErr | OHCI1394_cycleTooLong |
-+		  OHCI1394_cycle64Seconds | OHCI1394_masterIntEnable);
- 
- 	/* Activate link_on bit and contender bit in our self ID packets.*/
- 	if (ohci_update_phy_reg(card, 4, 0,
-@@ -1408,9 +1487,13 @@ static int handle_ir_dualbuffer_packet(struct context *context,
- 	void *p, *end;
- 	int i;
- 
--	if (db->first_res_count > 0 && db->second_res_count > 0)
--		/* This descriptor isn't done yet, stop iteration. */
--		return 0;
-+	if (db->first_res_count > 0 && db->second_res_count > 0) {
-+		if (ctx->excess_bytes <= le16_to_cpu(db->second_req_count)) {
-+			/* This descriptor isn't done yet, stop iteration. */
-+			return 0;
-+		}
-+		ctx->excess_bytes -= le16_to_cpu(db->second_req_count);
-+	}
- 
- 	header_length = le16_to_cpu(db->first_req_count) -
- 		le16_to_cpu(db->first_res_count);
-@@ -1429,11 +1512,15 @@ static int handle_ir_dualbuffer_packet(struct context *context,
- 		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
- 		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
- 		i += ctx->base.header_size;
-+		ctx->excess_bytes +=
-+			(le32_to_cpu(*(u32 *)(p + 4)) >> 16) & 0xffff;
- 		p += ctx->base.header_size + 4;
- 	}
+-/*
+- * add logic to try GET_EVENT command first to check for media and tray
+- * status. this should be supported by newer cd-r/w and all DVD etc
+- * drives
+- */
+-static
+-int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	struct media_event_desc med;
+-	struct request_sense sense;
+-	int stat;
 -
- 	ctx->header_length = i;
- 
-+	ctx->excess_bytes -= le16_to_cpu(db->second_req_count) -
-+		le16_to_cpu(db->second_res_count);
-+
- 	if (le16_to_cpu(db->control) & DESCRIPTOR_IRQ_ALWAYS) {
- 		ir_header = (__le32 *) (db + 1);
- 		ctx->base.callback(&ctx->base,
-@@ -1452,24 +1539,24 @@ static int handle_ir_packet_per_buffer(struct context *context,
- {
- 	struct iso_context *ctx =
- 		container_of(context, struct iso_context, context);
--	struct descriptor *pd = d + 1;
-+	struct descriptor *pd;
- 	__le32 *ir_header;
--	size_t header_length;
--	void *p, *end;
--	int i, z;
-+	void *p;
-+	int i;
- 
--	if (pd->res_count == pd->req_count)
-+	for (pd = d; pd <= last; pd++) {
-+		if (pd->transfer_status)
-+			break;
-+	}
-+	if (pd > last)
- 		/* Descriptor(s) not done yet, stop iteration */
- 		return 0;
- 
--	header_length = le16_to_cpu(d->req_count);
+-	if (slot_nr != CDSL_CURRENT)
+-		return -EINVAL;
 -
- 	i   = ctx->header_length;
--	z   = le32_to_cpu(pd->branch_address) & 0xf;
--	p   = d + z;
--	end = p + header_length;
-+	p   = last + 1;
- 
--	while (p < end && i + ctx->base.header_size <= PAGE_SIZE) {
-+	if (ctx->base.header_size > 0 &&
-+			i + ctx->base.header_size <= PAGE_SIZE) {
- 		/*
- 		 * The iso header is byteswapped to little endian by
- 		 * the controller, but the remaining header quadlets
-@@ -1478,14 +1565,11 @@ static int handle_ir_packet_per_buffer(struct context *context,
- 		 */
- 		*(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4));
- 		memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4);
--		i += ctx->base.header_size;
--		p += ctx->base.header_size + 4;
-+		ctx->header_length += ctx->base.header_size;
- 	}
- 
--	ctx->header_length = i;
+-	stat = cdrom_check_status(drive, &sense);
+-	if (!stat || sense.sense_key == UNIT_ATTENTION)
+-		return CDS_DISC_OK;
 -
--	if (le16_to_cpu(pd->control) & DESCRIPTOR_IRQ_ALWAYS) {
--		ir_header = (__le32 *) (d + z);
-+	if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) {
-+		ir_header = (__le32 *) p;
- 		ctx->base.callback(&ctx->base,
- 				   le32_to_cpu(ir_header[0]) & 0xffff,
- 				   ctx->header_length, ctx->header,
-@@ -1493,7 +1577,6 @@ static int handle_ir_packet_per_buffer(struct context *context,
- 		ctx->header_length = 0;
- 	}
- 
+-	if (!cdrom_get_media_event(cdi, &med)) {
+-		if (med.media_present)
+-			return CDS_DISC_OK;
+-		else if (med.door_open)
+-			return CDS_TRAY_OPEN;
+-		else
+-			return CDS_NO_DISC;
+-	}
 -
- 	return 1;
- }
- 
-@@ -1559,8 +1642,7 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size)
- 	if (ctx->header == NULL)
- 		goto out;
- 
--	retval = context_init(&ctx->context, ohci, ISO_BUFFER_SIZE,
--			      regs, callback);
-+	retval = context_init(&ctx->context, ohci, regs, callback);
- 	if (retval < 0)
- 		goto out_with_header;
- 
-@@ -1775,19 +1857,6 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
- 	 * packet, retransmit or terminate..
- 	 */
- 
--	if (packet->skip) {
--		d = context_get_descriptors(&ctx->context, 2, &d_bus);
--		if (d == NULL)
--			return -ENOMEM;
+-	if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
+-		return CDS_DISC_OK;
 -
--		db = (struct db_descriptor *) d;
--		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
--					  DESCRIPTOR_BRANCH_ALWAYS |
--					  DESCRIPTOR_WAIT);
--		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
--		context_append(&ctx->context, d, 2, 0);
+-	/*
+-	 * If not using Mt Fuji extended media tray reports,
+-	 * just return TRAY_OPEN since ATAPI doesn't provide
+-	 * any other way to detect this...
+-	 */
+-	if (sense.sense_key == NOT_READY) {
+-		if (sense.asc == 0x3a && sense.ascq == 1)
+-			return CDS_NO_DISC;
+-		else
+-			return CDS_TRAY_OPEN;
 -	}
+-	return CDS_DRIVE_NOT_READY;
+-}
 -
- 	p = packet;
- 	z = 2;
- 
-@@ -1815,11 +1884,18 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
- 		db->control = cpu_to_le16(DESCRIPTOR_STATUS |
- 					  DESCRIPTOR_BRANCH_ALWAYS);
- 		db->first_size = cpu_to_le16(ctx->base.header_size + 4);
--		db->first_req_count = cpu_to_le16(header_size);
-+		if (p->skip && rest == p->payload_length) {
-+			db->control |= cpu_to_le16(DESCRIPTOR_WAIT);
-+			db->first_req_count = db->first_size;
-+		} else {
-+			db->first_req_count = cpu_to_le16(header_size);
-+		}
- 		db->first_res_count = db->first_req_count;
- 		db->first_buffer = cpu_to_le32(d_bus + sizeof(*db));
- 
--		if (offset + rest < PAGE_SIZE)
-+		if (p->skip && rest == p->payload_length)
-+			length = 4;
-+		else if (offset + rest < PAGE_SIZE)
- 			length = rest;
- 		else
- 			length = PAGE_SIZE - offset;
-@@ -1835,7 +1911,8 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base,
- 		context_append(&ctx->context, d, z, header_z);
- 		offset = (offset + length) & ~PAGE_MASK;
- 		rest -= length;
--		page++;
-+		if (offset == 0)
-+			page++;
- 	}
- 
- 	return 0;
-@@ -1849,67 +1926,70 @@ ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base,
+-static
+-int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
+-				struct cdrom_multisession *ms_info)
+-{
+-	struct atapi_toc *toc;
+-	ide_drive_t *drive = cdi->handle;
+-	struct cdrom_info *info = drive->driver_data;
+-	struct request_sense sense;
+-	int ret;
+-
+-	if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL)
+-		if ((ret = cdrom_read_toc(drive, &sense)))
+-			return ret;
+-
+-	toc = info->toc;
+-	ms_info->addr.lba = toc->last_session_lba;
+-	ms_info->xa_flag = toc->xa_flag;
+-
+-	return 0;
+-}
+-
+-static
+-int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
+-		       struct cdrom_mcn *mcn_info)
++void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
  {
- 	struct iso_context *ctx = container_of(base, struct iso_context, base);
- 	struct descriptor *d = NULL, *pd = NULL;
--	struct fw_iso_packet *p;
-+	struct fw_iso_packet *p = packet;
- 	dma_addr_t d_bus, page_bus;
- 	u32 z, header_z, rest;
--	int i, page, offset, packet_count, header_size;
+-	int stat;
+-	char mcnbuf[24];
+-	ide_drive_t *drive = cdi->handle;
 -
--	if (packet->skip) {
--		d = context_get_descriptors(&ctx->context, 1, &d_bus);
--		if (d == NULL)
--			return -ENOMEM;
+-/* get MCN */
+-	if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
+-		return stat;
 -
--		d->control = cpu_to_le16(DESCRIPTOR_STATUS |
--					 DESCRIPTOR_INPUT_LAST |
--					 DESCRIPTOR_BRANCH_ALWAYS |
--					 DESCRIPTOR_WAIT);
--		context_append(&ctx->context, d, 1, 0);
--	}
+-	memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
+-		sizeof (mcn_info->medium_catalog_number)-1);
+-	mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
+-		= '\0';
 -
--	/* one descriptor for header, one for payload */
--	/* FIXME: handle cases where we need multiple desc. for payload */
--	z = 2;
--	p = packet;
-+	int i, j, length;
-+	int page, offset, packet_count, header_size, payload_per_buffer;
- 
- 	/*
- 	 * The OHCI controller puts the status word in the
- 	 * buffer too, so we need 4 extra bytes per packet.
- 	 */
- 	packet_count = p->header_length / ctx->base.header_size;
--	header_size  = packet_count * (ctx->base.header_size + 4);
-+	header_size  = ctx->base.header_size + 4;
- 
- 	/* Get header size in number of descriptors. */
- 	header_z = DIV_ROUND_UP(header_size, sizeof(*d));
- 	page     = payload >> PAGE_SHIFT;
- 	offset   = payload & ~PAGE_MASK;
--	rest     = p->payload_length;
-+	payload_per_buffer = p->payload_length / packet_count;
- 
- 	for (i = 0; i < packet_count; i++) {
- 		/* d points to the header descriptor */
-+		z = DIV_ROUND_UP(payload_per_buffer + offset, PAGE_SIZE) + 1;
- 		d = context_get_descriptors(&ctx->context,
--					    z + header_z, &d_bus);
-+				z + header_z, &d_bus);
- 		if (d == NULL)
- 			return -ENOMEM;
- 
--		d->control      = cpu_to_le16(DESCRIPTOR_INPUT_MORE);
-+		d->control      = cpu_to_le16(DESCRIPTOR_STATUS |
-+					      DESCRIPTOR_INPUT_MORE);
-+		if (p->skip && i == 0)
-+			d->control |= cpu_to_le16(DESCRIPTOR_WAIT);
- 		d->req_count    = cpu_to_le16(header_size);
- 		d->res_count    = d->req_count;
-+		d->transfer_status = 0;
- 		d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d)));
+-	return 0;
+-}
+-
++	struct cdrom_info *cd = drive->driver_data;
++	u16 curspeed, maxspeed;
  
--		/* pd points to the payload descriptor */
--		pd = d + 1;
-+		rest = payload_per_buffer;
-+		for (j = 1; j < z; j++) {
-+			pd = d + j;
-+			pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
-+						  DESCRIPTOR_INPUT_MORE);
-+
-+			if (offset + rest < PAGE_SIZE)
-+				length = rest;
-+			else
-+				length = PAGE_SIZE - offset;
-+			pd->req_count = cpu_to_le16(length);
-+			pd->res_count = pd->req_count;
-+			pd->transfer_status = 0;
-+
-+			page_bus = page_private(buffer->pages[page]);
-+			pd->data_address = cpu_to_le32(page_bus + offset);
-+
-+			offset = (offset + length) & ~PAGE_MASK;
-+			rest -= length;
-+			if (offset == 0)
-+				page++;
-+		}
- 		pd->control = cpu_to_le16(DESCRIPTOR_STATUS |
- 					  DESCRIPTOR_INPUT_LAST |
- 					  DESCRIPTOR_BRANCH_ALWAYS);
--		if (p->interrupt)
-+		if (p->interrupt && i == packet_count - 1)
- 			pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS);
++	curspeed = *(u16 *)&buf[8 + 14];
++	maxspeed = *(u16 *)&buf[8 +  8];
  
--		pd->req_count = cpu_to_le16(rest);
--		pd->res_count = pd->req_count;
--
--		page_bus = page_private(buffer->pages[page]);
--		pd->data_address = cpu_to_le32(page_bus + offset);
+-/****************************************************************************
+- * Other driver requests (open, close, check media change).
+- */
 -
- 		context_append(&ctx->context, d, z, header_z);
+-static
+-int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
+-				       int slot_nr)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-	int retval;
+-	
+-	if (slot_nr == CDSL_CURRENT) {
+-		(void) cdrom_check_status(drive, NULL);
+-		retval = CDROM_STATE_FLAGS(drive)->media_changed;
+-		CDROM_STATE_FLAGS(drive)->media_changed = 0;
+-		return retval;
++	if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
++		curspeed = le16_to_cpu(curspeed);
++		maxspeed = le16_to_cpu(maxspeed);
+ 	} else {
+-		return -EINVAL;
++		curspeed = be16_to_cpu(curspeed);
++		maxspeed = be16_to_cpu(maxspeed);
  	}
+-}
+-
+-
+-static
+-int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
+-{
+-	return 0;
+-}
  
-@@ -1923,16 +2003,22 @@ ohci_queue_iso(struct fw_iso_context *base,
- 	       unsigned long payload)
- {
- 	struct iso_context *ctx = container_of(base, struct iso_context, base);
-+	unsigned long flags;
-+	int retval;
- 
-+	spin_lock_irqsave(&ctx->context.ohci->lock, flags);
- 	if (base->type == FW_ISO_CONTEXT_TRANSMIT)
--		return ohci_queue_iso_transmit(base, packet, buffer, payload);
-+		retval = ohci_queue_iso_transmit(base, packet, buffer, payload);
- 	else if (ctx->context.ohci->version >= OHCI_VERSION_1_1)
--		return ohci_queue_iso_receive_dualbuffer(base, packet,
-+		retval = ohci_queue_iso_receive_dualbuffer(base, packet,
- 							 buffer, payload);
- 	else
--		return ohci_queue_iso_receive_packet_per_buffer(base, packet,
-+		retval = ohci_queue_iso_receive_packet_per_buffer(base, packet,
- 								buffer,
- 								payload);
-+	spin_unlock_irqrestore(&ctx->context.ohci->lock, flags);
-+
-+	return retval;
+-/*
+- * Close down the device.  Invalidate all cached blocks.
+- */
+-
+-static
+-void ide_cdrom_release_real (struct cdrom_device_info *cdi)
+-{
+-	ide_drive_t *drive = cdi->handle;
+-
+-	if (!cdi->use_count)
+-		CDROM_STATE_FLAGS(drive)->toc_valid = 0;
++	cd->current_speed = (curspeed + (176/2)) / 176;
++	cd->max_speed = (maxspeed + (176/2)) / 176;
  }
  
- static const struct fw_card_driver ohci_driver = {
-@@ -2004,10 +2090,10 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent)
- 	ar_context_init(&ohci->ar_response_ctx, ohci,
- 			OHCI1394_AsRspRcvContextControlSet);
- 
--	context_init(&ohci->at_request_ctx, ohci, AT_BUFFER_SIZE,
-+	context_init(&ohci->at_request_ctx, ohci,
- 		     OHCI1394_AsReqTrContextControlSet, handle_at_packet);
- 
--	context_init(&ohci->at_response_ctx, ohci, AT_BUFFER_SIZE,
-+	context_init(&ohci->at_response_ctx, ohci,
- 		     OHCI1394_AsRspTrContextControlSet, handle_at_packet);
- 
- 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
-diff --git a/drivers/firewire/fw-sbp2.c b/drivers/firewire/fw-sbp2.c
-index 624ff3e..19ece9b 100644
---- a/drivers/firewire/fw-sbp2.c
-+++ b/drivers/firewire/fw-sbp2.c
-@@ -40,6 +40,7 @@
- #include <linux/stringify.h>
- #include <linux/timer.h>
- #include <linux/workqueue.h>
-+#include <asm/system.h>
- 
- #include <scsi/scsi.h>
- #include <scsi/scsi_cmnd.h>
-@@ -148,18 +149,26 @@ struct sbp2_target {
- 
- 	unsigned workarounds;
- 	struct list_head lu_list;
-+
-+	unsigned int mgt_orb_timeout;
- };
++#define IDE_CD_CAPABILITIES \
++	(CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
++	 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
++	 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
++	 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
++	 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
  
--#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
--#define SBP2_MAX_SECTORS		255	/* Max sectors supported */
-+/*
-+ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
-+ * provided in the config rom. Most devices do provide a value, which
-+ * we'll use for login management orbs, but with some sane limits.
-+ */
-+#define SBP2_MIN_LOGIN_ORB_TIMEOUT	5000U	/* Timeout in ms */
-+#define SBP2_MAX_LOGIN_ORB_TIMEOUT	40000U	/* Timeout in ms */
- #define SBP2_ORB_TIMEOUT		2000	/* Timeout in ms */
 -
- #define SBP2_ORB_NULL			0x80000000
-+#define SBP2_MAX_SG_ELEMENT_LENGTH	0xf000
- 
- #define SBP2_DIRECTION_TO_MEDIA		0x0
- #define SBP2_DIRECTION_FROM_MEDIA	0x1
- 
- /* Unit directory keys */
-+#define SBP2_CSR_UNIT_CHARACTERISTICS	0x3a
- #define SBP2_CSR_FIRMWARE_REVISION	0x3c
- #define SBP2_CSR_LOGICAL_UNIT_NUMBER	0x14
- #define SBP2_CSR_LOGICAL_UNIT_DIRECTORY	0xd4
-@@ -489,6 +498,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
- {
- 	struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
- 	struct sbp2_management_orb *orb;
-+	unsigned int timeout;
- 	int retval = -ENOMEM;
- 
- 	orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
-@@ -516,9 +526,13 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
- 	orb->request.status_fifo.low  = lu->address_handler.offset;
- 
- 	if (function == SBP2_LOGIN_REQUEST) {
-+		/* Ask for 2^2 == 4 seconds reconnect grace period */
- 		orb->request.misc |=
--			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login) |
--			MANAGEMENT_ORB_RECONNECT(0);
-+			MANAGEMENT_ORB_RECONNECT(2) |
-+			MANAGEMENT_ORB_EXCLUSIVE(sbp2_param_exclusive_login);
-+		timeout = lu->tgt->mgt_orb_timeout;
-+	} else {
-+		timeout = SBP2_ORB_TIMEOUT;
- 	}
- 
- 	fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
-@@ -535,8 +549,7 @@ sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
- 	sbp2_send_orb(&orb->base, lu, node_id, generation,
- 		      lu->tgt->management_agent_address);
- 
--	wait_for_completion_timeout(&orb->done,
--				    msecs_to_jiffies(SBP2_ORB_TIMEOUT));
-+	wait_for_completion_timeout(&orb->done, msecs_to_jiffies(timeout));
- 
- 	retval = -EIO;
- 	if (sbp2_cancel_orbs(lu) == 0) {
-@@ -608,13 +621,17 @@ static void sbp2_release_target(struct kref *kref)
- 	struct sbp2_logical_unit *lu, *next;
- 	struct Scsi_Host *shost =
- 		container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
-+	struct fw_device *device = fw_device(tgt->unit->device.parent);
+-/****************************************************************************
+- * Device initialization.
+- */
+ static struct cdrom_device_ops ide_cdrom_dops = {
+ 	.open			= ide_cdrom_open_real,
+ 	.release		= ide_cdrom_release_real,
+@@ -2870,14 +1674,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
+ 	.get_mcn		= ide_cdrom_get_mcn,
+ 	.reset			= ide_cdrom_reset,
+ 	.audio_ioctl		= ide_cdrom_audio_ioctl,
+-	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
+-				CDC_SELECT_SPEED | CDC_SELECT_DISC |
+-				CDC_MULTI_SESSION | CDC_MCN |
+-				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
+-				CDC_DRIVE_STATUS | CDC_CD_R |
+-				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
+-				CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
+-				CDC_MRW_W | CDC_RAM,
++	.capability		= IDE_CD_CAPABILITIES,
+ 	.generic_packet		= ide_cdrom_packet,
+ };
  
- 	list_for_each_entry_safe(lu, next, &tgt->lu_list, link) {
- 		if (lu->sdev)
- 			scsi_remove_device(lu->sdev);
+@@ -2887,35 +1684,12 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+ 	struct cdrom_device_info *devinfo = &info->devinfo;
  
--		sbp2_send_management_orb(lu, tgt->node_id, lu->generation,
--				SBP2_LOGOUT_REQUEST, lu->login_id, NULL);
-+		if (!fw_device_is_shutdown(device))
-+			sbp2_send_management_orb(lu, tgt->node_id,
-+					lu->generation, SBP2_LOGOUT_REQUEST,
-+					lu->login_id, NULL);
+ 	devinfo->ops = &ide_cdrom_dops;
+-	devinfo->mask = 0;
+-	devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
++	devinfo->speed = info->current_speed;
+ 	devinfo->capacity = nslots;
+ 	devinfo->handle = drive;
+ 	strcpy(devinfo->name, drive->name);
+-	
+-	/* set capability mask to match the probe. */
+-	if (!CDROM_CONFIG_FLAGS(drive)->cd_r)
+-		devinfo->mask |= CDC_CD_R;
+-	if (!CDROM_CONFIG_FLAGS(drive)->cd_rw)
+-		devinfo->mask |= CDC_CD_RW;
+-	if (!CDROM_CONFIG_FLAGS(drive)->dvd)
+-		devinfo->mask |= CDC_DVD;
+-	if (!CDROM_CONFIG_FLAGS(drive)->dvd_r)
+-		devinfo->mask |= CDC_DVD_R;
+-	if (!CDROM_CONFIG_FLAGS(drive)->dvd_ram)
+-		devinfo->mask |= CDC_DVD_RAM;
+-	if (!CDROM_CONFIG_FLAGS(drive)->is_changer)
+-		devinfo->mask |= CDC_SELECT_DISC;
+-	if (!CDROM_CONFIG_FLAGS(drive)->audio_play)
+-		devinfo->mask |= CDC_PLAY_AUDIO;
+-	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
+-		devinfo->mask |= CDC_CLOSE_TRAY;
+-	if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
+-		devinfo->mask |= CDC_MO_DRIVE;
+-	if (!CDROM_CONFIG_FLAGS(drive)->ram)
+-		devinfo->mask |= CDC_RAM;
+-
+-	if (CDROM_CONFIG_FLAGS(drive)->no_speed_select)
 +
- 		fw_core_remove_address_handler(&lu->address_handler);
- 		list_del(&lu->link);
- 		kfree(lu);
-@@ -628,6 +645,21 @@ static void sbp2_release_target(struct kref *kref)
++	if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
+ 		devinfo->mask |= CDC_SELECT_SPEED;
  
- static struct workqueue_struct *sbp2_wq;
+ 	devinfo->disk = info->disk;
+@@ -2925,22 +1699,25 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
+ static
+ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+ {
+-	struct cdrom_info *info = drive->driver_data;
+-	struct cdrom_device_info *cdi = &info->devinfo;
+-	struct atapi_capabilities_page cap;
++	struct cdrom_info *cd = drive->driver_data;
++	struct cdrom_device_info *cdi = &cd->devinfo;
++	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
++	mechtype_t mechtype;
+ 	int nslots = 1;
  
-+/*
-+ * Always get the target's kref when scheduling work on one its units.
-+ * Each workqueue job is responsible to call sbp2_target_put() upon return.
-+ */
-+static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
-+{
-+	if (queue_delayed_work(sbp2_wq, &lu->work, delay))
-+		kref_get(&lu->tgt->kref);
-+}
-+
-+static void sbp2_target_put(struct sbp2_target *tgt)
-+{
-+	kref_put(&tgt->kref, sbp2_release_target);
-+}
++	cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
++		     CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
++		     CDC_MO_DRIVE | CDC_RAM);
 +
- static void sbp2_reconnect(struct work_struct *work);
- 
- static void sbp2_login(struct work_struct *work)
-@@ -643,22 +675,19 @@ static void sbp2_login(struct work_struct *work)
- 	struct sbp2_login_response response;
- 	int generation, node_id, local_node_id;
- 
--	generation    = device->card->generation;
--	node_id       = device->node->node_id;
--	local_node_id = device->card->local_node->node_id;
-+	generation    = device->generation;
-+	smp_rmb();    /* node_id must not be older than generation */
-+	node_id       = device->node_id;
-+	local_node_id = device->card->node_id;
- 
- 	if (sbp2_send_management_orb(lu, node_id, generation,
- 				SBP2_LOGIN_REQUEST, lu->lun, &response) < 0) {
--		if (lu->retries++ < 5) {
--			if (queue_delayed_work(sbp2_wq, &lu->work,
--					       DIV_ROUND_UP(HZ, 5)))
--				kref_get(&lu->tgt->kref);
--		} else {
-+		if (lu->retries++ < 5)
-+			sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-+		else
- 			fw_error("failed to login to %s LUN %04x\n",
- 				 unit->device.bus_id, lu->lun);
--		}
--		kref_put(&lu->tgt->kref, sbp2_release_target);
--		return;
-+		goto out;
+ 	if (drive->media == ide_optical) {
+-		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
+-		CDROM_CONFIG_FLAGS(drive)->ram = 1;
++		cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
+ 		printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
+ 		return nslots;
  	}
  
- 	lu->generation        = generation;
-@@ -700,7 +729,8 @@ static void sbp2_login(struct work_struct *work)
- 		lu->sdev = sdev;
- 		scsi_device_put(sdev);
+-	if (CDROM_CONFIG_FLAGS(drive)->nec260 ||
+-	    !strcmp(drive->id->model,"STINGRAY 8422 IDE 8X CD-ROM 7-27-95")) {
+-		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
+-		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
++	if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
++		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
++		cdi->mask &= ~CDC_PLAY_AUDIO;
+ 		return nslots;
  	}
--	kref_put(&lu->tgt->kref, sbp2_release_target);
-+ out:
-+	sbp2_target_put(lu->tgt);
- }
- 
- static int sbp2_add_logical_unit(struct sbp2_target *tgt, int lun_entry)
-@@ -750,6 +780,7 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
- {
- 	struct fw_csr_iterator ci;
- 	int key, value;
-+	unsigned int timeout;
- 
- 	fw_csr_iterator_init(&ci, directory);
- 	while (fw_csr_iterator_next(&ci, &key, &value)) {
-@@ -772,6 +803,21 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
- 			*firmware_revision = value;
- 			break;
  
-+		case SBP2_CSR_UNIT_CHARACTERISTICS:
-+			/* the timeout value is stored in 500ms units */
-+			timeout = ((unsigned int) value >> 8 & 0xff) * 500;
-+			timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
-+			tgt->mgt_orb_timeout =
-+				  min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);
-+
-+			if (timeout > tgt->mgt_orb_timeout)
-+				fw_notify("%s: config rom contains %ds "
-+					  "management ORB timeout, limiting "
-+					  "to %ds\n", tgt->unit->device.bus_id,
-+					  timeout / 1000,
-+					  tgt->mgt_orb_timeout / 1000);
-+			break;
-+
- 		case SBP2_CSR_LOGICAL_UNIT_NUMBER:
- 			if (sbp2_add_logical_unit(tgt, value) < 0)
- 				return -ENOMEM;
-@@ -865,18 +911,13 @@ static int sbp2_probe(struct device *dev)
+@@ -2954,83 +1731,66 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
+ 	cdi->handle = drive;
+ 	cdi->ops = &ide_cdrom_dops;
  
- 	get_device(&unit->device);
+-	if (ide_cdrom_get_capabilities(drive, &cap))
++	if (ide_cdrom_get_capabilities(drive, buf))
+ 		return 0;
  
--	/*
--	 * We schedule work to do the login so we can easily
--	 * reschedule retries. Always get the ref before scheduling
--	 * work.
+-	if (cap.lock == 0)
+-		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
+-	if (cap.eject)
+-		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
+-	if (cap.cd_r_write)
+-		CDROM_CONFIG_FLAGS(drive)->cd_r = 1;
+-	if (cap.cd_rw_write) {
+-		CDROM_CONFIG_FLAGS(drive)->cd_rw = 1;
+-		CDROM_CONFIG_FLAGS(drive)->ram = 1;
+-	}
+-	if (cap.test_write)
+-		CDROM_CONFIG_FLAGS(drive)->test_write = 1;
+-	if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
+-		CDROM_CONFIG_FLAGS(drive)->dvd = 1;
+-	if (cap.dvd_ram_write) {
+-		CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
+-		CDROM_CONFIG_FLAGS(drive)->ram = 1;
+-	}
+-	if (cap.dvd_r_write)
+-		CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
+-	if (cap.audio_play)
+-		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
+-	if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
+-		CDROM_CONFIG_FLAGS(drive)->close_tray = 0;
+-
+-	/* Some drives used by Apple don't advertise audio play
+-	 * but they do support reading TOC & audio datas
 -	 */
-+	/* Do the login in a workqueue so we can easily reschedule retries. */
- 	list_for_each_entry(lu, &tgt->lu_list, link)
--		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
--			kref_get(&tgt->kref);
-+		sbp2_queue_work(lu, 0);
- 	return 0;
+-	if (strcmp(drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 ||
+-	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 ||
+-	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 ||
+-	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8174") == 0)
+-		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
++	if ((buf[8 + 6] & 0x01) == 0)
++		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
++	if (buf[8 + 6] & 0x08)
++		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
++	if (buf[8 + 3] & 0x01)
++		cdi->mask &= ~CDC_CD_R;
++	if (buf[8 + 3] & 0x02)
++		cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
++	if (buf[8 + 2] & 0x38)
++		cdi->mask &= ~CDC_DVD;
++	if (buf[8 + 3] & 0x20)
++		cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
++	if (buf[8 + 3] & 0x10)
++		cdi->mask &= ~CDC_DVD_R;
++	if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
++		cdi->mask &= ~CDC_PLAY_AUDIO;
++
++	mechtype = buf[8 + 6] >> 5;
++	if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
++		cdi->mask |= CDC_CLOSE_TRAY;
  
-  fail_tgt_put:
--	kref_put(&tgt->kref, sbp2_release_target);
-+	sbp2_target_put(tgt);
- 	return -ENOMEM;
+-#if ! STANDARD_ATAPI
+ 	if (cdi->sanyo_slot > 0) {
+-		CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
++		cdi->mask &= ~CDC_SELECT_DISC;
+ 		nslots = 3;
++	} else if (mechtype == mechtype_individual_changer ||
++		   mechtype == mechtype_cartridge_changer) {
++		nslots = cdrom_number_of_slots(cdi);
++		if (nslots > 1)
++			cdi->mask &= ~CDC_SELECT_DISC;
+ 	}
  
-  fail_shost_put:
-@@ -889,7 +930,7 @@ static int sbp2_remove(struct device *dev)
- 	struct fw_unit *unit = fw_unit(dev);
- 	struct sbp2_target *tgt = unit->device.driver_data;
+-	else
+-#endif /* not STANDARD_ATAPI */
+-	if (cap.mechtype == mechtype_individual_changer ||
+-	    cap.mechtype == mechtype_cartridge_changer) {
+-		if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
+-			CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
+-			CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 1;
+-		}
+-	}
++	ide_cdrom_update_speed(drive, buf);
  
--	kref_put(&tgt->kref, sbp2_release_target);
-+	sbp2_target_put(tgt);
- 	return 0;
- }
+-	ide_cdrom_update_speed(drive, &cap);
+-	/* don't print speed if the drive reported 0.
+-	 */
+ 	printk(KERN_INFO "%s: ATAPI", drive->name);
+-	if (CDROM_CONFIG_FLAGS(drive)->max_speed)
+-		printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
+-	printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
  
-@@ -901,9 +942,10 @@ static void sbp2_reconnect(struct work_struct *work)
- 	struct fw_device *device = fw_device(unit->device.parent);
- 	int generation, node_id, local_node_id;
+-	if (CDROM_CONFIG_FLAGS(drive)->dvd_r|CDROM_CONFIG_FLAGS(drive)->dvd_ram)
+-        	printk(" DVD%s%s", 
+-        	(CDROM_CONFIG_FLAGS(drive)->dvd_r)? "-R" : "", 
+-        	(CDROM_CONFIG_FLAGS(drive)->dvd_ram)? "-RAM" : "");
++	/* don't print speed if the drive reported 0 */
++	if (cd->max_speed)
++		printk(KERN_CONT " %dX", cd->max_speed);
  
--	generation    = device->card->generation;
--	node_id       = device->node->node_id;
--	local_node_id = device->card->local_node->node_id;
-+	generation    = device->generation;
-+	smp_rmb();    /* node_id must not be older than generation */
-+	node_id       = device->node_id;
-+	local_node_id = device->card->node_id;
+-        if (CDROM_CONFIG_FLAGS(drive)->cd_r|CDROM_CONFIG_FLAGS(drive)->cd_rw) 
+-        	printk(" CD%s%s", 
+-        	(CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", 
+-        	(CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
++	printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
  
- 	if (sbp2_send_management_orb(lu, node_id, generation,
- 				     SBP2_RECONNECT_REQUEST,
-@@ -915,10 +957,8 @@ static void sbp2_reconnect(struct work_struct *work)
- 			lu->retries = 0;
- 			PREPARE_DELAYED_WORK(&lu->work, sbp2_login);
- 		}
--		if (queue_delayed_work(sbp2_wq, &lu->work, DIV_ROUND_UP(HZ, 5)))
--			kref_get(&lu->tgt->kref);
--		kref_put(&lu->tgt->kref, sbp2_release_target);
--		return;
-+		sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5));
-+		goto out;
- 	}
+-        if (CDROM_CONFIG_FLAGS(drive)->is_changer) 
+-        	printk(" changer w/%d slots", nslots);
+-        else 	
+-        	printk(" drive");
++	if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
++		printk(KERN_CONT " DVD%s%s",
++				 (cdi->mask & CDC_DVD_R) ? "" : "-R",
++				 (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
  
- 	lu->generation        = generation;
-@@ -930,8 +970,8 @@ static void sbp2_reconnect(struct work_struct *work)
+-	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(cap.buffer_size));
++	if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
++		printk(KERN_CONT " CD%s%s",
++				 (cdi->mask & CDC_CD_R) ? "" : "-R",
++				 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
++
++	if ((cdi->mask & CDC_SELECT_DISC) == 0)
++		printk(KERN_CONT " changer w/%d slots", nslots);
++	else
++		printk(KERN_CONT " drive");
++
++	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
  
- 	sbp2_agent_reset(lu);
- 	sbp2_cancel_orbs(lu);
--
--	kref_put(&lu->tgt->kref, sbp2_release_target);
-+ out:
-+	sbp2_target_put(lu->tgt);
+ 	return nslots;
  }
- 
- static void sbp2_update(struct fw_unit *unit)
-@@ -947,8 +987,7 @@ static void sbp2_update(struct fw_unit *unit)
- 	 */
- 	list_for_each_entry(lu, &tgt->lu_list, link) {
- 		lu->retries = 0;
--		if (queue_delayed_work(sbp2_wq, &lu->work, 0))
--			kref_get(&tgt->kref);
-+		sbp2_queue_work(lu, 0);
- 	}
+@@ -3123,11 +1883,74 @@ static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
+ 	return 0;
  }
  
-@@ -1103,9 +1142,9 @@ sbp2_map_scatterlist(struct sbp2_command_orb *orb, struct fw_device *device,
- 	 * elements larger than 65535 bytes, some IOMMUs may merge sg elements
- 	 * during DMA mapping, and Linux currently doesn't prevent this.
- 	 */
--	for (i = 0, j = 0; i < count; i++) {
--		sg_len = sg_dma_len(sg + i);
--		sg_addr = sg_dma_address(sg + i);
-+	for (i = 0, j = 0; i < count; i++, sg = sg_next(sg)) {
-+		sg_len = sg_dma_len(sg);
-+		sg_addr = sg_dma_address(sg);
- 		while (sg_len) {
- 			/* FIXME: This won't get us out of the pinch. */
- 			if (unlikely(j >= ARRAY_SIZE(orb->page_table))) {
-@@ -1238,6 +1277,12 @@ static int sbp2_scsi_slave_alloc(struct scsi_device *sdev)
- 
- 	sdev->allow_restart = 1;
- 
++struct cd_list_entry {
++	const char	*id_model;
++	const char	*id_firmware;
++	unsigned int	cd_flags;
++};
++
++static const struct cd_list_entry ide_cd_quirks_list[] = {
++	/* Limit transfer size per interrupt. */
++	{ "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
++	{ "SAMSUNG CD-ROM SCR-2432", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
++	/* SCR-3231 doesn't support the SET_CD_SPEED command. */
++	{ "SAMSUNG CD-ROM SCR-3231", NULL,   IDE_CD_FLAG_NO_SPEED_SELECT    },
++	/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
++	{ "NEC CD-ROM DRIVE:260",    "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
++					     IDE_CD_FLAG_PRE_ATAPI12,	    },
++	/* Vertos 300, some versions of this drive like to talk BCD. */
++	{ "V003S0DS",		     NULL,   IDE_CD_FLAG_VERTOS_300_SSD,    },
++	/* Vertos 600 ESD. */
++	{ "V006E0DS",		     NULL,   IDE_CD_FLAG_VERTOS_600_ESD,    },
 +	/*
-+	 * Update the dma alignment (minimum alignment requirements for
-+	 * start and end of DMA transfers) to be a sector
++	 * Sanyo 3 CD changer uses a non-standard command for CD changing
++	 * (by default standard ATAPI support for CD changers is used).
 +	 */
-+	blk_queue_update_dma_alignment(sdev->request_queue, 511);
-+
- 	if (lu->tgt->workarounds & SBP2_WORKAROUND_INQUIRY_36)
- 		sdev->inquiry_len = 36;
- 
-diff --git a/drivers/firewire/fw-topology.c b/drivers/firewire/fw-topology.c
-index 0fc9b00..172c186 100644
---- a/drivers/firewire/fw-topology.c
-+++ b/drivers/firewire/fw-topology.c
-@@ -21,6 +21,7 @@
- #include <linux/module.h>
- #include <linux/wait.h>
- #include <linux/errno.h>
-+#include <asm/system.h>
- #include "fw-transaction.h"
- #include "fw-topology.h"
- 
-@@ -518,6 +519,11 @@ fw_core_handle_bus_reset(struct fw_card *card,
- 		card->bm_retries = 0;
- 
- 	card->node_id = node_id;
++	{ "CD-ROM CDR-C3 G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
++	{ "CD-ROM CDR-C3G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
++	{ "CD-ROM CDR_C36",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
++	/* Stingray 8X CD-ROM. */
++	{ "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
 +	/*
-+	 * Update node_id before generation to prevent anybody from using
-+	 * a stale node_id together with a current generation.
++	 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
++	 * mode sense page capabilities size, but older drives break.
 +	 */
-+	smp_wmb();
- 	card->generation = generation;
- 	card->reset_jiffies = jiffies;
- 	schedule_delayed_work(&card->work, 0);
-diff --git a/drivers/firewire/fw-transaction.c b/drivers/firewire/fw-transaction.c
-index c00d4a9..7fcc59d 100644
---- a/drivers/firewire/fw-transaction.c
-+++ b/drivers/firewire/fw-transaction.c
-@@ -153,7 +153,7 @@ fw_fill_request(struct fw_packet *packet, int tcode, int tlabel,
- 	int ext_tcode;
- 
- 	if (tcode > 0x10) {
--		ext_tcode = tcode - 0x10;
-+		ext_tcode = tcode & ~0x10;
- 		tcode = TCODE_LOCK_REQUEST;
- 	} else
- 		ext_tcode = 0;
-@@ -650,7 +650,7 @@ fw_core_handle_request(struct fw_card *card, struct fw_packet *p)
- 		 HEADER_GET_OFFSET_HIGH(p->header[1]) << 32) | p->header[2];
- 	tcode       = HEADER_GET_TCODE(p->header[0]);
- 	destination = HEADER_GET_DESTINATION(p->header[0]);
--	source      = HEADER_GET_SOURCE(p->header[0]);
-+	source      = HEADER_GET_SOURCE(p->header[1]);
- 
- 	spin_lock_irqsave(&address_handler_lock, flags);
- 	handler = lookup_enclosing_address_handler(&address_handler_list,
-diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
-index 5e596a7..9008ed5 100644
---- a/drivers/firmware/dmi_scan.c
-+++ b/drivers/firmware/dmi_scan.c
-@@ -8,6 +8,8 @@
- #include <linux/slab.h>
- #include <asm/dmi.h>
- 
-+static char dmi_empty_string[] = "        ";
++	{ "ATAPI CD ROM DRIVE 50X MAX",	NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
++	{ "WPI CDS-32X",		NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
++	/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
++	{ "",			     "241N", IDE_CD_FLAG_LE_SPEED_FIELDS    },
++	/*
++	 * Some drives used by Apple don't advertise audio play
++	 * but they do support reading TOC & audio datas.
++	 */
++	{ "MATSHITADVD-ROM SR-8187", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
++	{ "MATSHITADVD-ROM SR-8186", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
++	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
++	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
++	{ NULL, NULL, 0 }
++};
 +
- static char * __init dmi_string(const struct dmi_header *dm, u8 s)
- {
- 	const u8 *bp = ((u8 *) dm) + dm->length;
-@@ -21,11 +23,16 @@ static char * __init dmi_string(const struct dmi_header *dm, u8 s)
- 		}
- 
- 		if (*bp != 0) {
--			str = dmi_alloc(strlen(bp) + 1);
-+			size_t len = strlen(bp)+1;
-+			size_t cmp_len = len > 8 ? 8 : len;
++static unsigned int ide_cd_flags(struct hd_driveid *id)
++{
++	const struct cd_list_entry *cle = ide_cd_quirks_list;
 +
-+			if (!memcmp(bp, dmi_empty_string, cmp_len))
-+				return dmi_empty_string;
-+			str = dmi_alloc(len);
- 			if (str != NULL)
- 				strcpy(str, bp);
- 			else
--				printk(KERN_ERR "dmi_string: out of memory.\n");
-+				printk(KERN_ERR "dmi_string: cannot allocate %Zu bytes.\n", len);
- 		}
- 	}
- 
-@@ -175,12 +182,23 @@ static void __init dmi_save_devices(const struct dmi_header *dm)
- 	}
- }
- 
-+static struct dmi_device empty_oem_string_dev = {
-+	.name = dmi_empty_string,
-+};
++	while (cle->id_model) {
++		if (strcmp(cle->id_model, id->model) == 0 &&
++		    (cle->id_firmware == NULL ||
++		     strstr(id->fw_rev, cle->id_firmware)))
++			return cle->cd_flags;
++		cle++;
++	}
 +
- static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
++	return 0;
++}
++
+ static
+ int ide_cdrom_setup (ide_drive_t *drive)
  {
- 	int i, count = *(u8 *)(dm + 1);
- 	struct dmi_device *dev;
+-	struct cdrom_info *info = drive->driver_data;
+-	struct cdrom_device_info *cdi = &info->devinfo;
++	struct cdrom_info *cd = drive->driver_data;
++	struct cdrom_device_info *cdi = &cd->devinfo;
++	struct hd_driveid *id = drive->id;
+ 	int nslots;
  
- 	for (i = 1; i <= count; i++) {
-+		char *devname = dmi_string(dm, i);
-+
-+		if (!strcmp(devname, dmi_empty_string)) {
-+			list_add(&empty_oem_string_dev.list, &dmi_devices);
-+			continue;
-+		}
-+
- 		dev = dmi_alloc(sizeof(*dev));
- 		if (!dev) {
- 			printk(KERN_ERR
-@@ -189,7 +207,7 @@ static void __init dmi_save_oem_strings_devices(const struct dmi_header *dm)
- 		}
+ 	blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
+@@ -3138,101 +1961,21 @@ int ide_cdrom_setup (ide_drive_t *drive)
  
- 		dev->type = DMI_DEV_TYPE_OEM_STRING;
--		dev->name = dmi_string(dm, i);
-+		dev->name = devname;
- 		dev->device_data = NULL;
+ 	drive->special.all	= 0;
  
- 		list_add(&dev->list, &dmi_devices);
-@@ -331,9 +349,11 @@ void __init dmi_scan_machine(void)
- 			rc = dmi_present(q);
- 			if (!rc) {
- 				dmi_available = 1;
-+				dmi_iounmap(p, 0x10000);
- 				return;
- 			}
- 		}
-+		dmi_iounmap(p, 0x10000);
- 	}
-  out:	printk(KERN_INFO "DMI not present or invalid.\n");
- }
-diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
-index 6942e06..d168223 100644
---- a/drivers/firmware/edd.c
-+++ b/drivers/firmware/edd.c
-@@ -631,7 +631,7 @@ static struct kobj_type edd_ktype = {
- 	.default_attrs	= def_attrs,
- };
+-	CDROM_STATE_FLAGS(drive)->media_changed = 1;
+-	CDROM_STATE_FLAGS(drive)->toc_valid     = 0;
+-	CDROM_STATE_FLAGS(drive)->door_locked   = 0;
++	cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
++		       ide_cd_flags(id);
  
--static decl_subsys(edd, &edd_ktype, NULL);
-+static struct kset *edd_kset;
+-#if NO_DOOR_LOCKING
+-	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
+-#else
+-	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0;
+-#endif
++	if ((id->config & 0x0060) == 0x20)
++		cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
  
+-	CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20);
+-	CDROM_CONFIG_FLAGS(drive)->is_changer = 0;
+-	CDROM_CONFIG_FLAGS(drive)->cd_r = 0;
+-	CDROM_CONFIG_FLAGS(drive)->cd_rw = 0;
+-	CDROM_CONFIG_FLAGS(drive)->test_write = 0;
+-	CDROM_CONFIG_FLAGS(drive)->dvd = 0;
+-	CDROM_CONFIG_FLAGS(drive)->dvd_r = 0;
+-	CDROM_CONFIG_FLAGS(drive)->dvd_ram = 0;
+-	CDROM_CONFIG_FLAGS(drive)->no_eject = 1;
+-	CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 0;
+-	CDROM_CONFIG_FLAGS(drive)->audio_play = 0;
+-	CDROM_CONFIG_FLAGS(drive)->close_tray = 1;
+-	
+-	/* limit transfer size per interrupt. */
+-	CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0;
+-	/* a testament to the nice quality of Samsung drives... */
+-	if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
+-		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
+-	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
+-		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
+-	/* the 3231 model does not support the SET_CD_SPEED command */
+-	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
+-		CDROM_CONFIG_FLAGS(drive)->no_speed_select = 1;
+-
+-#if ! STANDARD_ATAPI
+-	/* by default Sanyo 3 CD changer support is turned off and
+-           ATAPI Rev 2.2+ standard support for CD changers is used */
+-	cdi->sanyo_slot = 0;
+-
+-	CDROM_CONFIG_FLAGS(drive)->nec260 = 0;
+-	CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 0;
+-	CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 0;
+-	CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0;
+-	CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0;
+-
+-	if (strcmp (drive->id->model, "V003S0DS") == 0 &&
+-	    drive->id->fw_rev[4] == '1' &&
+-	    drive->id->fw_rev[6] <= '2') {
+-		/* Vertos 300.
+-		   Some versions of this drive like to talk BCD. */
+-		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
+-	}
+-
+-	else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
+-	    drive->id->fw_rev[4] == '1' &&
+-	    drive->id->fw_rev[6] <= '2') {
+-		/* Vertos 600 ESD. */
+-		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
+-	}
+-	else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 &&
+-		 strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
+-		/* Old NEC260 (not R).
+-		   This drive was released before the 1.2 version
+-		   of the spec. */
+-		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->nec260         = 1;
+-	}
+-	else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 &&
+-		 strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
+-		/* Wearnes */
+-		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
+-		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
+-	}
+-        /* Sanyo 3 CD changer uses a non-standard command
+-           for CD changing */
+-        else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
+-                 (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
+-                 (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
+-                 /* uses CD in slot 0 when value is set to 3 */
+-                 cdi->sanyo_slot = 3;
+-        }
+-#endif /* not STANDARD_ATAPI */
+-
+-	info->toc		= NULL;
+-	info->buffer		= NULL;
+-	info->sector_buffered	= 0;
+-	info->nsectors_buffered	= 0;
+-	info->changer_info      = NULL;
+-	info->last_block	= 0;
+-	info->start_seek	= 0;
++	if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
++	    id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
++		cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
++				 IDE_CD_FLAG_TOCADDR_AS_BCD);
++	else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
++		 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
++		cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
++	else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
++		cdi->sanyo_slot = 3;	/* 3 => use CD in slot 0 */
  
- /**
-@@ -693,7 +693,7 @@ edd_create_symlink_to_pcidev(struct edd_device *edev)
- static inline void
- edd_device_unregister(struct edd_device *edev)
- {
--	kobject_unregister(&edev->kobj);
-+	kobject_put(&edev->kobj);
- }
+ 	nslots = ide_cdrom_probe_capabilities (drive);
  
- static void edd_populate_dir(struct edd_device * edev)
-@@ -721,12 +721,13 @@ edd_device_register(struct edd_device *edev, int i)
- 	if (!edev)
- 		return 1;
- 	edd_dev_set_info(edev, i);
--	kobject_set_name(&edev->kobj, "int13_dev%02x",
--			 0x80 + i);
--	kobj_set_kset_s(edev,edd_subsys);
--	error = kobject_register(&edev->kobj);
--	if (!error)
-+	edev->kobj.kset = edd_kset;
-+	error = kobject_init_and_add(&edev->kobj, &edd_ktype, NULL,
-+				     "int13_dev%02x", 0x80 + i);
-+	if (!error) {
- 		edd_populate_dir(edev);
-+		kobject_uevent(&edev->kobj, KOBJ_ADD);
-+	}
- 	return error;
- }
+@@ -3247,7 +1990,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
  
-@@ -755,9 +756,9 @@ edd_init(void)
+ 	if (ide_cdrom_register(drive, nslots)) {
+ 		printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
+-		info->devinfo.handle = NULL;
++		cd->devinfo.handle = NULL;
  		return 1;
  	}
+ 	ide_cdrom_add_settings(drive);
+@@ -3287,7 +2030,6 @@ static void ide_cd_release(struct kref *kref)
  
--	rc = firmware_register(&edd_subsys);
--	if (rc)
--		return rc;
-+	edd_kset = kset_create_and_add("edd", NULL, firmware_kobj);
-+	if (!edd_kset)
-+		return -ENOMEM;
- 
- 	for (i = 0; i < edd_num_devices() && !rc; i++) {
- 		edev = kzalloc(sizeof (*edev), GFP_KERNEL);
-@@ -773,7 +774,7 @@ edd_init(void)
- 	}
- 
- 	if (rc)
--		firmware_unregister(&edd_subsys);
-+		kset_unregister(edd_kset);
- 	return rc;
+ 	kfree(info->buffer);
+ 	kfree(info->toc);
+-	kfree(info->changer_info);
+ 	if (devinfo->handle == drive && unregister_cdrom(devinfo))
+ 		printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
+ 				"driver.\n", __FUNCTION__, drive->name);
+@@ -3443,7 +2185,9 @@ static int idecd_revalidate_disk(struct gendisk *disk)
+ {
+ 	struct cdrom_info *info = ide_cd_g(disk);
+ 	struct request_sense sense;
+-	cdrom_read_toc(info->drive, &sense);
++
++	ide_cd_read_toc(info->drive, &sense);
++
+ 	return  0;
  }
  
-@@ -787,7 +788,7 @@ edd_exit(void)
- 		if ((edev = edd_devices[i]))
- 			edd_device_unregister(edev);
+@@ -3518,7 +2262,7 @@ static int ide_cd_probe(ide_drive_t *drive)
+ 		goto failed;
  	}
--	firmware_unregister(&edd_subsys);
-+	kset_unregister(edd_kset);
- }
  
- late_initcall(edd_init);
-diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
-index 858a7b9..f4f709d 100644
---- a/drivers/firmware/efivars.c
-+++ b/drivers/firmware/efivars.c
-@@ -129,13 +129,6 @@ struct efivar_attribute {
- };
+-	cdrom_read_toc(drive, &sense);
++	ide_cd_read_toc(drive, &sense);
+ 	g->fops = &idecd_ops;
+ 	g->flags |= GENHD_FL_REMOVABLE;
+ 	add_disk(g);
+@@ -3541,6 +2285,7 @@ static int __init ide_cdrom_init(void)
+ }
  
+ MODULE_ALIAS("ide:*m-cdrom*");
++MODULE_ALIAS("ide-cd");
+ module_init(ide_cdrom_init);
+ module_exit(ide_cdrom_exit);
+ MODULE_LICENSE("GPL");
+diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
+index 1b302fe..22e3751 100644
+--- a/drivers/ide/ide-cd.h
++++ b/drivers/ide/ide-cd.h
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/ide_cd.h
+- *
+  *  Copyright (C) 1996-98  Erik Andersen
+  *  Copyright (C) 1998-2000 Jens Axboe
+  */
+@@ -10,31 +8,6 @@
+ #include <linux/cdrom.h>
+ #include <asm/byteorder.h>
  
--#define EFI_ATTR(_name, _mode, _show, _store) \
--struct subsys_attribute efi_attr_##_name = { \
--	.attr = {.name = __stringify(_name), .mode = _mode}, \
--	.show = _show, \
--	.store = _store, \
--};
+-/* Turn this on to have the driver print out the meanings of the
+-   ATAPI error codes.  This will use up additional kernel-space
+-   memory, though. */
 -
- #define EFIVAR_ATTR(_name, _mode, _show, _store) \
- struct efivar_attribute efivar_attr_##_name = { \
- 	.attr = {.name = __stringify(_name), .mode = _mode}, \
-@@ -143,13 +136,6 @@ struct efivar_attribute efivar_attr_##_name = { \
- 	.store = _store, \
- };
- 
--#define VAR_SUBSYS_ATTR(_name, _mode, _show, _store) \
--struct subsys_attribute var_subsys_attr_##_name = { \
--	.attr = {.name = __stringify(_name), .mode = _mode}, \
--	.show = _show, \
--	.store = _store, \
--};
+-#ifndef VERBOSE_IDE_CD_ERRORS
+-#define VERBOSE_IDE_CD_ERRORS 1
+-#endif
 -
- #define to_efivar_attr(_attr) container_of(_attr, struct efivar_attribute, attr)
- #define to_efivar_entry(obj)  container_of(obj, struct efivar_entry, kobj)
- 
-@@ -408,21 +394,16 @@ static struct kobj_type efivar_ktype = {
- 	.default_attrs = def_attrs,
- };
- 
--static ssize_t
--dummy(struct kset *kset, char *buf)
--{
--	return -ENODEV;
--}
 -
- static inline void
- efivar_unregister(struct efivar_entry *var)
- {
--	kobject_unregister(&var->kobj);
-+	kobject_put(&var->kobj);
- }
- 
- 
--static ssize_t
--efivar_create(struct kset *kset, const char *buf, size_t count)
-+static ssize_t efivar_create(struct kobject *kobj,
-+			     struct bin_attribute *bin_attr,
-+			     char *buf, loff_t pos, size_t count)
- {
- 	struct efi_variable *new_var = (struct efi_variable *)buf;
- 	struct efivar_entry *search_efivar, *n;
-@@ -479,8 +460,9 @@ efivar_create(struct kset *kset, const char *buf, size_t count)
- 	return count;
- }
- 
--static ssize_t
--efivar_delete(struct kset *kset, const char *buf, size_t count)
-+static ssize_t efivar_delete(struct kobject *kobj,
-+			     struct bin_attribute *bin_attr,
-+			     char *buf, loff_t pos, size_t count)
- {
- 	struct efi_variable *del_var = (struct efi_variable *)buf;
- 	struct efivar_entry *search_efivar, *n;
-@@ -537,25 +519,26 @@ efivar_delete(struct kset *kset, const char *buf, size_t count)
- 	return count;
- }
- 
--static VAR_SUBSYS_ATTR(new_var, 0200, dummy, efivar_create);
--static VAR_SUBSYS_ATTR(del_var, 0200, dummy, efivar_delete);
-+static struct bin_attribute var_subsys_attr_new_var = {
-+	.attr = {.name = "new_var", .mode = 0200},
-+	.write = efivar_create,
-+};
- 
--static struct subsys_attribute *var_subsys_attrs[] = {
--	&var_subsys_attr_new_var,
--	&var_subsys_attr_del_var,
--	NULL,
-+static struct bin_attribute var_subsys_attr_del_var = {
-+	.attr = {.name = "del_var", .mode = 0200},
-+	.write = efivar_delete,
- };
- 
+-/* Turning this on will remove code to work around various nonstandard
+-   ATAPI implementations.  If you know your drive follows the standard,
+-   this will give you a slightly smaller kernel. */
+-
+-#ifndef STANDARD_ATAPI
+-#define STANDARD_ATAPI 0
+-#endif
+-
+-
+-/* Turning this on will disable the door-locking functionality.
+-   This is apparently needed for supermount. */
+-
+-#ifndef NO_DOOR_LOCKING
+-#define NO_DOOR_LOCKING 0
+-#endif
+-
  /*
-  * Let's not leave out systab information that snuck into
-  * the efivars driver
+  * typical timeout for packet command
   */
--static ssize_t
--systab_read(struct kset *kset, char *buf)
-+static ssize_t systab_show(struct kobject *kobj,
-+			   struct kobj_attribute *attr, char *buf)
- {
- 	char *str = buf;
- 
--	if (!kset || !buf)
-+	if (!kobj || !buf)
- 		return -EINVAL;
- 
- 	if (efi.mps != EFI_INVALID_TABLE_ADDR)
-@@ -576,15 +559,21 @@ systab_read(struct kset *kset, char *buf)
- 	return str - buf;
- }
- 
--static EFI_ATTR(systab, 0400, systab_read, NULL);
-+static struct kobj_attribute efi_attr_systab =
-+			__ATTR(systab, 0400, systab_show, NULL);
- 
--static struct subsys_attribute *efi_subsys_attrs[] = {
--	&efi_attr_systab,
-+static struct attribute *efi_subsys_attrs[] = {
-+	&efi_attr_systab.attr,
- 	NULL,	/* maybe more in the future? */
- };
+@@ -49,68 +22,47 @@
+ #endif
+ #define SECTORS_PER_FRAME	(CD_FRAMESIZE >> SECTOR_BITS)
+ #define SECTOR_BUFFER_SIZE	(CD_FRAMESIZE * 32)
+-#define SECTORS_BUFFER		(SECTOR_BUFFER_SIZE >> SECTOR_BITS)
+-#define SECTORS_MAX		(131072 >> SECTOR_BITS)
+-
+-#define BLOCKS_PER_FRAME	(CD_FRAMESIZE / BLOCK_SIZE)
+-
+-/* special command codes for strategy routine. */
+-#define PACKET_COMMAND        4315
+-#define REQUEST_SENSE_COMMAND 4316
+-#define RESET_DRIVE_COMMAND   4317
+-
+-
+-/* Configuration flags.  These describe the capabilities of the drive.
+-   They generally do not change after initialization, unless we learn
+-   more about the drive from stuff failing. */
+-struct ide_cd_config_flags {
+-	__u8 drq_interrupt	: 1; /* Device sends an interrupt when ready
+-					for a packet command. */
+-	__u8 no_doorlock	: 1; /* Drive cannot lock the door. */
+-	__u8 no_eject		: 1; /* Drive cannot eject the disc. */
+-	__u8 nec260		: 1; /* Drive is a pre-1.2 NEC 260 drive. */
+-	__u8 playmsf_as_bcd	: 1; /* PLAYMSF command takes BCD args. */
+-	__u8 tocaddr_as_bcd	: 1; /* TOC addresses are in BCD. */
+-	__u8 toctracks_as_bcd	: 1; /* TOC track numbers are in BCD. */
+-	__u8 subchan_as_bcd	: 1; /* Subchannel info is in BCD. */
+-	__u8 is_changer		: 1; /* Drive is a changer. */
+-	__u8 cd_r		: 1; /* Drive can write to CD-R media . */
+-	__u8 cd_rw		: 1; /* Drive can write to CD-R/W media . */
+-	__u8 dvd		: 1; /* Drive is a DVD-ROM */
+-	__u8 dvd_r		: 1; /* Drive can write DVD-R */
+-	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
+-	__u8 ram		: 1; /* generic WRITE (dvd-ram/mrw) */
+-	__u8 test_write		: 1; /* Drive can fake writes */
+-	__u8 supp_disc_present	: 1; /* Changer can report exact contents
+-					of slots. */
+-	__u8 limit_nframes	: 1; /* Drive does not provide data in
+-					multiples of SECTOR_SIZE when more
+-					than one interrupt is needed. */
+-	__u8 seeking		: 1; /* Seeking in progress */
+-	__u8 audio_play		: 1; /* can do audio related commands */
+-	__u8 close_tray		: 1; /* can close the tray */
+-	__u8 writing		: 1; /* pseudo write in progress */
+-	__u8 mo_drive		: 1; /* drive is an MO device */
+-	__u8 no_speed_select	: 1; /* SET_CD_SPEED command is unsupported. */
+-	__u8 reserved		: 1;
+-	byte max_speed;		     /* Max speed of the drive */
+-};
+-#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
  
--static decl_subsys(vars, &efivar_ktype, NULL);
--static decl_subsys(efi, NULL, NULL);
-+static struct attribute_group efi_subsys_attr_group = {
-+	.attrs = efi_subsys_attrs,
-+};
-+
+- 
+-/* State flags.  These give information about the current state of the
+-   drive, and will change during normal operation. */
+-struct ide_cd_state_flags {
+-	__u8 media_changed : 1; /* Driver has noticed a media change. */
+-	__u8 toc_valid     : 1; /* Saved TOC information is current. */
+-	__u8 door_locked   : 1; /* We think that the drive door is locked. */
+-	__u8 writing       : 1; /* the drive is currently writing */
+-	__u8 reserved      : 4;
+-	byte current_speed;	/* Current speed of the drive */
++/* Capabilities Page size including 8 bytes of Mode Page Header */
++#define ATAPI_CAPABILITIES_PAGE_SIZE		(8 + 20)
++#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE	4
 +
-+static struct kset *vars_kset;
-+static struct kobject *efi_kobj;
- 
- /*
-  * efivar_create_sysfs_entry()
-@@ -628,15 +617,16 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
- 	*(short_name + strlen(short_name)) = '-';
- 	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
++enum {
++	/* Device sends an interrupt when ready for a packet command. */
++	IDE_CD_FLAG_DRQ_INTERRUPT	= (1 << 0),
++	/* Drive cannot lock the door. */
++	IDE_CD_FLAG_NO_DOORLOCK		= (1 << 1),
++	/* Drive cannot eject the disc. */
++	IDE_CD_FLAG_NO_EJECT		= (1 << 2),
++	/* Drive is a pre ATAPI 1.2 drive. */
++	IDE_CD_FLAG_PRE_ATAPI12		= (1 << 3),
++	/* TOC addresses are in BCD. */
++	IDE_CD_FLAG_TOCADDR_AS_BCD	= (1 << 4),
++	/* TOC track numbers are in BCD. */
++	IDE_CD_FLAG_TOCTRACKS_AS_BCD	= (1 << 5),
++	/*
++	 * Drive does not provide data in multiples of SECTOR_SIZE
++	 * when more than one interrupt is needed.
++	 */
++	IDE_CD_FLAG_LIMIT_NFRAMES	= (1 << 6),
++	/* Seeking in progress. */
++	IDE_CD_FLAG_SEEKING		= (1 << 7),
++	/* Driver has noticed a media change. */
++	IDE_CD_FLAG_MEDIA_CHANGED	= (1 << 8),
++	/* Saved TOC information is current. */
++	IDE_CD_FLAG_TOC_VALID		= (1 << 9),
++	/* We think that the drive door is locked. */
++	IDE_CD_FLAG_DOOR_LOCKED		= (1 << 10),
++	/* SET_CD_SPEED command is unsupported. */
++	IDE_CD_FLAG_NO_SPEED_SELECT	= (1 << 11),
++	IDE_CD_FLAG_VERTOS_300_SSD	= (1 << 12),
++	IDE_CD_FLAG_VERTOS_600_ESD	= (1 << 13),
++	IDE_CD_FLAG_SANYO_3CD		= (1 << 14),
++	IDE_CD_FLAG_FULL_CAPS_PAGE	= (1 << 15),
++	IDE_CD_FLAG_PLAY_AUDIO_OK	= (1 << 16),
++	IDE_CD_FLAG_LE_SPEED_FIELDS	= (1 << 17),
+ };
  
--	kobject_set_name(&new_efivar->kobj, "%s", short_name);
--	kobj_set_kset_s(new_efivar, vars_subsys);
--	i = kobject_register(&new_efivar->kobj);
-+	new_efivar->kobj.kset = vars_kset;
-+	i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL,
-+				 "%s", short_name);
- 	if (i) {
- 		kfree(short_name);
- 		kfree(new_efivar);
- 		return 1;
- 	}
+-#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
+-
+ /* Structure of a MSF cdrom address. */
+ struct atapi_msf {
+ 	byte reserved;
+@@ -155,310 +107,6 @@ struct atapi_toc {
+ 	  /* One extra for the leadout. */
+ };
  
-+	kobject_uevent(&new_efivar->kobj, KOBJ_ADD);
- 	kfree(short_name);
- 	short_name = NULL;
+-
+-/* This structure is annoyingly close to, but not identical with,
+-   the cdrom_subchnl structure from cdrom.h. */
+-struct atapi_cdrom_subchnl {
+- 	u_char  acdsc_reserved;
+- 	u_char  acdsc_audiostatus;
+- 	u_short acdsc_length;
+-	u_char  acdsc_format;
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	u_char  acdsc_ctrl:     4;
+-	u_char  acdsc_adr:      4;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	u_char  acdsc_adr:	4;
+-	u_char  acdsc_ctrl:	4;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-	u_char  acdsc_trk;
+-	u_char  acdsc_ind;
+-	union {
+-		struct atapi_msf msf;
+-		int	lba;
+-	} acdsc_absaddr;
+-	union {
+-		struct atapi_msf msf;
+-		int	lba;
+-	} acdsc_reladdr;
+-};
+-
+-
+-
+-/* This should probably go into cdrom.h along with the other
+- * generic stuff now in the Mt. Fuji spec.
+- */
+-struct atapi_capabilities_page {
+-	struct mode_page_header header;
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 parameters_saveable : 1;
+-	__u8 reserved1           : 1;
+-	__u8 page_code           : 6;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	__u8 page_code           : 6;
+-	__u8 reserved1           : 1;
+-	__u8 parameters_saveable : 1;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-	byte     page_length;
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 reserved2           : 2;
+-	/* Drive supports reading of DVD-RAM discs */
+-	__u8 dvd_ram_read        : 1;
+-	/* Drive supports reading of DVD-R discs */
+-	__u8 dvd_r_read          : 1;
+-	/* Drive supports reading of DVD-ROM discs */
+-	__u8 dvd_rom             : 1;
+-	/* Drive supports reading CD-R discs with addressing method 2 */
+-	__u8 method2             : 1; /* reserved in 1.2 */
+-	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
+-	__u8 cd_rw_read		 : 1; /* reserved in 1.2 */
+-	/* Drive supports read from CD-R discs (orange book, part II) */
+-	__u8 cd_r_read           : 1; /* reserved in 1.2 */
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	/* Drive supports read from CD-R discs (orange book, part II) */
+-	__u8 cd_r_read           : 1; /* reserved in 1.2 */
+-	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
+-	__u8 cd_rw_read          : 1; /* reserved in 1.2 */
+-	/* Drive supports reading CD-R discs with addressing method 2 */
+-	__u8 method2             : 1;
+-	/* Drive supports reading of DVD-ROM discs */
+-	__u8 dvd_rom             : 1;
+-	/* Drive supports reading of DVD-R discs */
+-	__u8 dvd_r_read          : 1;
+-	/* Drive supports reading of DVD-RAM discs */
+-	__u8 dvd_ram_read        : 1;
+-	__u8 reserved2		 : 2;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 reserved3           : 2;
+-	/* Drive can write DVD-RAM discs */
+-	__u8 dvd_ram_write       : 1;
+-	/* Drive can write DVD-R discs */
+-	__u8 dvd_r_write         : 1;
+-	__u8 reserved3a          : 1;
+-	/* Drive can fake writes */
+-	__u8 test_write          : 1;
+-	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
+-	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
+-	/* Drive supports write to CD-R discs (orange book, part II) */
+-	__u8 cd_r_write          : 1; /* reserved in 1.2 */
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	/* Drive can write to CD-R discs (orange book, part II) */
+-	__u8 cd_r_write          : 1; /* reserved in 1.2 */
+-	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
+-	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
+-	/* Drive can fake writes */
+-	__u8 test_write          : 1;
+-	__u8 reserved3a          : 1;
+-	/* Drive can write DVD-R discs */
+-	__u8 dvd_r_write         : 1;
+-	/* Drive can write DVD-RAM discs */
+-	__u8 dvd_ram_write       : 1;
+-	__u8 reserved3           : 2;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 reserved4           : 1;
+-	/* Drive can read multisession discs. */
+-	__u8 multisession        : 1;
+-	/* Drive can read mode 2, form 2 data. */
+-	__u8 mode2_form2         : 1;
+-	/* Drive can read mode 2, form 1 (XA) data. */
+-	__u8 mode2_form1         : 1;
+-	/* Drive supports digital output on port 2. */
+-	__u8 digport2            : 1;
+-	/* Drive supports digital output on port 1. */
+-	__u8 digport1            : 1;
+-	/* Drive can deliver a composite audio/video data stream. */
+-	__u8 composite           : 1;
+-	/* Drive supports audio play operations. */
+-	__u8 audio_play          : 1;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	/* Drive supports audio play operations. */
+-	__u8 audio_play          : 1;
+-	/* Drive can deliver a composite audio/video data stream. */
+-	__u8 composite           : 1;
+-	/* Drive supports digital output on port 1. */
+-	__u8 digport1            : 1;
+-	/* Drive supports digital output on port 2. */
+-	__u8 digport2            : 1;
+-	/* Drive can read mode 2, form 1 (XA) data. */
+-	__u8 mode2_form1         : 1;
+-	/* Drive can read mode 2, form 2 data. */
+-	__u8 mode2_form2         : 1;
+-	/* Drive can read multisession discs. */
+-	__u8 multisession        : 1;
+-	__u8 reserved4           : 1;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 reserved5           : 1;
+-	/* Drive can return Media Catalog Number (UPC) info. */
+-	__u8 upc                 : 1;
+-	/* Drive can return International Standard Recording Code info. */
+-	__u8 isrc                : 1;
+-	/* Drive supports C2 error pointers. */
+-	__u8 c2_pointers         : 1;
+-	/* R-W data will be returned deinterleaved and error corrected. */
+-	__u8 rw_corr             : 1;
+-	/* Subchannel reads can return combined R-W information. */
+-	__u8 rw_supported        : 1;
+-	/* Drive can continue a read cdda operation from a loss of streaming.*/
+-	__u8 cdda_accurate       : 1;
+-	/* Drive can read Red Book audio data. */
+-	__u8 cdda                : 1;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	/* Drive can read Red Book audio data. */
+-	__u8 cdda                : 1;
+-	/* Drive can continue a read cdda operation from a loss of streaming.*/
+-	__u8 cdda_accurate       : 1;
+-	/* Subchannel reads can return combined R-W information. */
+-	__u8 rw_supported        : 1;
+-	/* R-W data will be returned deinterleaved and error corrected. */
+-	__u8 rw_corr             : 1;
+-	/* Drive supports C2 error pointers. */
+-	__u8 c2_pointers         : 1;
+-	/* Drive can return International Standard Recording Code info. */
+-	__u8 isrc                : 1;
+-	/* Drive can return Media Catalog Number (UPC) info. */
+-	__u8 upc                 : 1;
+-	__u8 reserved5           : 1;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	/* Drive mechanism types. */
+-	mechtype_t mechtype	 : 3;
+-	__u8 reserved6           : 1;
+-	/* Drive can eject a disc or changer cartridge. */
+-	__u8 eject               : 1;
+-	/* State of prevent/allow jumper. */
+-	__u8 prevent_jumper      : 1;
+-	/* Present state of door lock. */
+-	__u8 lock_state          : 1;
+-	/* Drive can lock the door. */
+-	__u8 lock                : 1;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-
+-	/* Drive can lock the door. */
+-	__u8 lock                : 1;
+-	/* Present state of door lock. */
+-	__u8 lock_state          : 1;
+-	/* State of prevent/allow jumper. */
+-	__u8 prevent_jumper      : 1;
+-	/* Drive can eject a disc or changer cartridge. */
+-	__u8 eject               : 1;
+-	__u8 reserved6           : 1;
+-	/* Drive mechanism types. */
+-	mechtype_t mechtype	 : 3;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 reserved7           : 4;
+-	/* Drive supports software slot selection. */
+-	__u8 sss                 : 1;  /* reserved in 1.2 */
+-	/* Changer can report exact contents of slots. */
+-	__u8 disc_present        : 1;  /* reserved in 1.2 */
+-	/* Audio for each channel can be muted independently. */
+-	__u8 separate_mute       : 1;
+-	/* Audio level for each channel can be controlled independently. */
+-	__u8 separate_volume     : 1;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-
+-	/* Audio level for each channel can be controlled independently. */
+-	__u8 separate_volume     : 1;
+-	/* Audio for each channel can be muted independently. */
+-	__u8 separate_mute       : 1;
+-	/* Changer can report exact contents of slots. */
+-	__u8 disc_present        : 1;  /* reserved in 1.2 */
+-	/* Drive supports software slot selection. */
+-	__u8 sss                 : 1;  /* reserved in 1.2 */
+-	__u8 reserved7           : 4;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-	/* Note: the following four fields are returned in big-endian form. */
+-	/* Maximum speed (in kB/s). */
+-	unsigned short maxspeed;
+-	/* Number of discrete volume levels. */
+-	unsigned short n_vol_levels;
+-	/* Size of cache in drive, in kB. */
+-	unsigned short buffer_size;
+-	/* Current speed (in kB/s). */
+-	unsigned short curspeed;
+-	char pad[4];
+-};
+-
+-
+-struct atapi_mechstat_header {
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 fault         : 1;
+-	__u8 changer_state : 2;
+-	__u8 curslot       : 5;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	__u8 curslot       : 5;
+-	__u8 changer_state : 2;
+-	__u8 fault         : 1;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 mech_state    : 3;
+-	__u8 door_open     : 1;
+-	__u8 reserved1     : 4;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	__u8 reserved1     : 4;
+-	__u8 door_open     : 1;
+-	__u8 mech_state    : 3;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-	byte     curlba[3];
+-	byte     nslots;
+-	__u16	 slot_tablelen;
+-};
+-
+-
+-struct atapi_slot {
+-#if defined(__BIG_ENDIAN_BITFIELD)
+-	__u8 disc_present : 1;
+-	__u8 reserved1    : 6;
+-	__u8 change       : 1;
+-#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-	__u8 change       : 1;
+-	__u8 reserved1    : 6;
+-	__u8 disc_present : 1;
+-#else
+-#error "Please fix <asm/byteorder.h>"
+-#endif
+-
+-	byte reserved2[3];
+-};
+-
+-struct atapi_changer_info {
+-	struct atapi_mechstat_header hdr;
+-	struct atapi_slot slots[0];
+-};
+-
+ /* Extra per-device info for cdrom drives. */
+ struct cdrom_info {
+ 	ide_drive_t	*drive;
+@@ -483,11 +131,11 @@ struct cdrom_info {
+ 	int dma;
+ 	unsigned long last_block;
+ 	unsigned long start_seek;
+-	/* Buffer to hold mechanism status and changer slot table. */
+-	struct atapi_changer_info *changer_info;
  
-@@ -660,9 +650,8 @@ efivars_init(void)
- 	efi_status_t status = EFI_NOT_FOUND;
- 	efi_guid_t vendor_guid;
- 	efi_char16_t *variable_name;
--	struct subsys_attribute *attr;
- 	unsigned long variable_name_size = 1024;
--	int i, error = 0;
-+	int error = 0;
+-	struct ide_cd_config_flags	config_flags;
+-	struct ide_cd_state_flags	state_flags;
++	unsigned int cd_flags;
++
++	u8 max_speed;		/* Max speed of the drive. */
++	u8 current_speed;	/* Current speed of the drive. */
  
- 	if (!efi_enabled)
- 		return -ENODEV;
-@@ -676,23 +665,18 @@ efivars_init(void)
- 	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
- 	       EFIVARS_DATE);
+         /* Per-device info needed by cdrom.c generic driver. */
+         struct cdrom_device_info devinfo;
+@@ -495,250 +143,30 @@ struct cdrom_info {
+ 	unsigned long write_timeout;
+ };
  
--	/*
--	 * For now we'll register the efi subsys within this driver
--	 */
+-/****************************************************************************
+- * Descriptions of ATAPI error codes.
+- */
 -
--	error = firmware_register(&efi_subsys);
+-/* This stuff should be in cdrom.h, since it is now generic... */
 -
--	if (error) {
--		printk(KERN_ERR "efivars: Firmware registration failed with error %d.\n", error);
-+	/* For now we'll register the efi directory at /sys/firmware/efi */
-+	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
-+	if (!efi_kobj) {
-+		printk(KERN_ERR "efivars: Firmware registration failed.\n");
-+		error = -ENOMEM;
- 		goto out_free;
- 	}
- 
--	kobj_set_kset_s(&vars_subsys, efi_subsys);
+-/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
+-#define NO_SENSE                0x00
+-#define RECOVERED_ERROR         0x01
+-#define NOT_READY               0x02
+-#define MEDIUM_ERROR            0x03
+-#define HARDWARE_ERROR          0x04
+-#define ILLEGAL_REQUEST         0x05
+-#define UNIT_ATTENTION          0x06
+-#define DATA_PROTECT            0x07
+-#define BLANK_CHECK             0x08
+-#define ABORTED_COMMAND         0x0b
+-#define MISCOMPARE              0x0e
 -
--	error = subsystem_register(&vars_subsys);
+- 
 -
--	if (error) {
--		printk(KERN_ERR "efivars: Subsystem registration failed with error %d.\n", error);
-+	vars_kset = kset_create_and_add("vars", NULL, efi_kobj);
-+	if (!vars_kset) {
-+		printk(KERN_ERR "efivars: Subsystem registration failed.\n");
-+		error = -ENOMEM;
- 		goto out_firmware_unregister;
- 	}
- 
-@@ -727,28 +711,28 @@ efivars_init(void)
- 	 * Now add attributes to allow creation of new vars
- 	 * and deletion of existing ones...
- 	 */
+-/* This stuff should be in cdrom.h, since it is now generic... */
+-#if VERBOSE_IDE_CD_ERRORS
 -
--	for (i = 0; (attr = var_subsys_attrs[i]) && !error; i++) {
--		if (attr->show && attr->store)
--			error = subsys_create_file(&vars_subsys, attr);
--	}
-+	error = sysfs_create_bin_file(&vars_kset->kobj,
-+				      &var_subsys_attr_new_var);
-+	if (error)
-+		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
-+			" due to error %d\n", error);
-+	error = sysfs_create_bin_file(&vars_kset->kobj,
-+				      &var_subsys_attr_del_var);
-+	if (error)
-+		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
-+			" due to error %d\n", error);
- 
- 	/* Don't forget the systab entry */
+- /* The generic packet command opcodes for CD/DVD Logical Units,
+- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ 
+-static const struct {
+-	unsigned short packet_command;
+-	const char * const text;
+-} packet_command_texts[] = {
+-	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
+-	{ GPCMD_REQUEST_SENSE, "Request Sense" },
+-	{ GPCMD_FORMAT_UNIT, "Format Unit" },
+-	{ GPCMD_INQUIRY, "Inquiry" },
+-	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
+-	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
+-	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
+-	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
+-	{ GPCMD_READ_10, "Read 10" },
+-	{ GPCMD_WRITE_10, "Write 10" },
+-	{ GPCMD_SEEK, "Seek" },
+-	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
+-	{ GPCMD_VERIFY_10, "Verify 10" },
+-	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
+-	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
+-	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
+-	{ GPCMD_READ_HEADER, "Read Header" },
+-	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
+-	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
+-	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
+-	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
+-	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
+-	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
+-	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
+-	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
+-	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
+-	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
+-	{ GPCMD_SEND_OPC, "Send OPC" },
+-	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
+-	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
+-	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
+-	{ GPCMD_CLOSE_TRACK, "Close Track" },
+-	{ GPCMD_BLANK, "Blank" },
+-	{ GPCMD_SEND_EVENT, "Send Event" },
+-	{ GPCMD_SEND_KEY, "Send Key" },
+-	{ GPCMD_REPORT_KEY, "Report Key" },
+-	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
+-	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
+-	{ GPCMD_READ_12, "Read 12" },
+-	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
+-	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
+-	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
+-	{ GPCMD_SET_STREAMING, "Set Streaming" },
+-	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
+-	{ GPCMD_SCAN, "Scan" },
+-	{ GPCMD_SET_SPEED, "Set Speed" },
+-	{ GPCMD_PLAY_CD, "Play CD" },
+-	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
+-	{ GPCMD_READ_CD, "Read CD" },
+-};
 -
--	for (i = 0; (attr = efi_subsys_attrs[i]) && !error; i++) {
--		if (attr->show)
--			error = subsys_create_file(&efi_subsys, attr);
--	}
 -
-+	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
- 	if (error)
- 		printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
- 	else
- 		goto out_free;
- 
--	subsystem_unregister(&vars_subsys);
-+	kset_unregister(vars_kset);
- 
- out_firmware_unregister:
--	firmware_unregister(&efi_subsys);
-+	kobject_put(efi_kobj);
- 
- out_free:
- 	kfree(variable_name);
-@@ -768,8 +752,8 @@ efivars_exit(void)
- 		efivar_unregister(entry);
- 	}
- 
--	subsystem_unregister(&vars_subsys);
--	firmware_unregister(&efi_subsys);
-+	kset_unregister(vars_kset);
-+	kobject_put(efi_kobj);
- }
- 
- module_init(efivars_init);
-diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
-index 1ac5103..275dc52 100644
---- a/drivers/hid/Makefile
-+++ b/drivers/hid/Makefile
-@@ -1,7 +1,7 @@
- #
- # Makefile for the HID driver
- #
--hid-objs			:= hid-core.o hid-input.o
-+hid-objs			:= hid-core.o hid-input.o hid-input-quirks.o
- 
- obj-$(CONFIG_HID)		+= hid.o
- 
-diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
-index 2884b03..d73a768 100644
---- a/drivers/hid/hid-core.c
-+++ b/drivers/hid/hid-core.c
-@@ -26,6 +26,7 @@
- #include <linux/input.h>
- #include <linux/wait.h>
- #include <linux/vmalloc.h>
-+#include <linux/sched.h>
- 
- #include <linux/hid.h>
- #include <linux/hiddev.h>
-@@ -758,7 +759,9 @@ static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n)
- {
- 	u64 x;
- 
--	WARN_ON(n > 32);
-+	if (n > 32)
-+		printk(KERN_WARNING "HID: extract() called with n (%d) > 32! (%s)\n",
-+				n, current->comm);
- 
- 	report += offset >> 3;  /* adjust byte index */
- 	offset &= 7;            /* now only need bit offset into one byte */
-@@ -780,8 +783,13 @@ static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u3
- 	__le64 x;
- 	u64 m = (1ULL << n) - 1;
- 
--	WARN_ON(n > 32);
-+	if (n > 32)
-+		printk(KERN_WARNING "HID: implement() called with n (%d) > 32! (%s)\n",
-+				n, current->comm);
- 
-+	if (value > m)
-+		printk(KERN_WARNING "HID: implement() called with too large value %d! (%s)\n",
-+				value, current->comm);
- 	WARN_ON(value > m);
- 	value &= m;
+-
+-/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+-static const char * const sense_key_texts[16] = {
+-	"No sense data",
+-	"Recovered error",
+-	"Not ready",
+-	"Medium error",
+-	"Hardware error",
+-	"Illegal request",
+-	"Unit attention",
+-	"Data protect",
+-	"Blank check",
+-	"(reserved)",
+-	"(reserved)",
+-	"Aborted command",
+-	"(reserved)",
+-	"(reserved)",
+-	"Miscompare",
+-	"(reserved)",
+-};
+-
+-/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+-static const struct {
+-	unsigned long asc_ascq;
+-	const char * const text;
+-} sense_data_texts[] = {
+-	{ 0x000000, "No additional sense information" },
+-	{ 0x000011, "Play operation in progress" },
+-	{ 0x000012, "Play operation paused" },
+-	{ 0x000013, "Play operation successfully completed" },
+-	{ 0x000014, "Play operation stopped due to error" },
+-	{ 0x000015, "No current audio status to return" },
+-	{ 0x010c0a, "Write error - padding blocks added" },
+-	{ 0x011700, "Recovered data with no error correction applied" },
+-	{ 0x011701, "Recovered data with retries" },
+-	{ 0x011702, "Recovered data with positive head offset" },
+-	{ 0x011703, "Recovered data with negative head offset" },
+-	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
+-	{ 0x011705, "Recovered data using previous sector ID" },
+-	{ 0x011800, "Recovered data with error correction applied" },
+-	{ 0x011801, "Recovered data with error correction and retries applied"},
+-	{ 0x011802, "Recovered data - the data was auto-reallocated" },
+-	{ 0x011803, "Recovered data with CIRC" },
+-	{ 0x011804, "Recovered data with L-EC" },
+-	{ 0x015d00, 
+-	    "Failure prediction threshold exceeded - Predicted logical unit failure" },
+-	{ 0x015d01, 
+-	    "Failure prediction threshold exceeded - Predicted media failure" },
+-	{ 0x015dff, "Failure prediction threshold exceeded - False" },
+-	{ 0x017301, "Power calibration area almost full" },
+-	{ 0x020400, "Logical unit not ready - cause not reportable" },
+-	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
+-	{ 0x020401,
+-	  "Logical unit not ready - in progress [sic] of becoming ready" },
+-	{ 0x020402, "Logical unit not ready - initializing command required" },
+-	{ 0x020403, "Logical unit not ready - manual intervention required" },
+-	{ 0x020404, "Logical unit not ready - format in progress" },
+-	{ 0x020407, "Logical unit not ready - operation in progress" },
+-	{ 0x020408, "Logical unit not ready - long write in progress" },
+-	{ 0x020600, "No reference position found (media may be upside down)" },
+-	{ 0x023000, "Incompatible medium installed" },
+-	{ 0x023a00, "Medium not present" },
+-	{ 0x025300, "Media load or eject failed" },
+-	{ 0x025700, "Unable to recover table of contents" },
+-	{ 0x030300, "Peripheral device write fault" },
+-	{ 0x030301, "No write current" },
+-	{ 0x030302, "Excessive write errors" },
+-	{ 0x030c00, "Write error" },
+-	{ 0x030c01, "Write error - Recovered with auto reallocation" },
+-	{ 0x030c02, "Write error - auto reallocation failed" },
+-	{ 0x030c03, "Write error - recommend reassignment" },
+-	{ 0x030c04, "Compression check miscompare error" },
+-	{ 0x030c05, "Data expansion occurred during compress" },
+-	{ 0x030c06, "Block not compressible" },
+-	{ 0x030c07, "Write error - recovery needed" },
+-	{ 0x030c08, "Write error - recovery failed" },
+-	{ 0x030c09, "Write error - loss of streaming" },
+-	{ 0x031100, "Unrecovered read error" },
+-	{ 0x031106, "CIRC unrecovered error" },
+-	{ 0x033101, "Format command failed" },
+-	{ 0x033200, "No defect spare location available" },
+-	{ 0x033201, "Defect list update failure" },
+-	{ 0x035100, "Erase failure" },
+-	{ 0x037200, "Session fixation error" },
+-	{ 0x037201, "Session fixation error writin lead-in" },
+-	{ 0x037202, "Session fixation error writin lead-out" },
+-	{ 0x037300, "CD control error" },
+-	{ 0x037302, "Power calibration area is full" },
+-	{ 0x037303, "Power calibration area error" },
+-	{ 0x037304, "Program memory area / RMA update failure" },
+-	{ 0x037305, "Program memory area / RMA is full" },
+-	{ 0x037306, "Program memory area / RMA is (almost) full" },
+-
+-	{ 0x040200, "No seek complete" },
+-	{ 0x040300, "Write fault" },
+-	{ 0x040900, "Track following error" },
+-	{ 0x040901, "Tracking servo failure" },
+-	{ 0x040902, "Focus servo failure" },
+-	{ 0x040903, "Spindle servo failure" },
+-	{ 0x041500, "Random positioning error" },
+-	{ 0x041501, "Mechanical positioning or changer error" },
+-	{ 0x041502, "Positioning error detected by read of medium" },
+-	{ 0x043c00, "Mechanical positioning or changer error" },
+-	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
+-	{ 0x044400, "Internal CD/DVD logical unit failure" },
+-	{ 0x04b600, "Media load mechanism failed" },
+-	{ 0x051a00, "Parameter list length error" },
+-	{ 0x052000, "Invalid command operation code" },
+-	{ 0x052100, "Logical block address out of range" },
+-	{ 0x052102, "Invalid address for write" },
+-	{ 0x052400, "Invalid field in command packet" },
+-	{ 0x052600, "Invalid field in parameter list" },
+-	{ 0x052601, "Parameter not supported" },
+-	{ 0x052602, "Parameter value invalid" },
+-	{ 0x052700, "Write protected media" },
+-	{ 0x052c00, "Command sequence error" },
+-	{ 0x052c03, "Current program area is not empty" },
+-	{ 0x052c04, "Current program area is empty" },
+-	{ 0x053001, "Cannot read medium - unknown format" },
+-	{ 0x053002, "Cannot read medium - incompatible format" },
+-	{ 0x053900, "Saving parameters not supported" },
+-	{ 0x054e00, "Overlapped commands attempted" },
+-	{ 0x055302, "Medium removal prevented" },
+-	{ 0x055500, "System resource failure" },
+-	{ 0x056300, "End of user area encountered on this track" },
+-	{ 0x056400, "Illegal mode for this track or incompatible medium" },
+-	{ 0x056f00, "Copy protection key exchange failure - Authentication failure" },
+-	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
+-	{ 0x056f02, "Copy protection key exchange failure - Key not established" },
+-	{ 0x056f03, "Read of scrambled sector without authentication" },
+-	{ 0x056f04, "Media region code is mismatched to logical unit" },
+-	{ 0x056f05,  "Drive region must be permanent / region reset count error" },
+-	{ 0x057203, "Session fixation error - incomplete track in session" },
+-	{ 0x057204, "Empty or partially written reserved track" },
+-	{ 0x057205, "No more RZONE reservations are allowed" },
+-	{ 0x05bf00, "Loss of streaming" },
+-	{ 0x062800, "Not ready to ready transition, medium may have changed" },
+-	{ 0x062900, "Power on, reset or hardware reset occurred" },
+-	{ 0x062a00, "Parameters changed" },
+-	{ 0x062a01, "Mode parameters changed" },
+-	{ 0x062e00, "Insufficient time for operation" },
+-	{ 0x063f00, "Logical unit operating conditions have changed" },
+-	{ 0x063f01, "Microcode has been changed" },
+-	{ 0x065a00, "Operator request or state change input (unspecified)" },
+-	{ 0x065a01, "Operator medium removal request" },
+-	{ 0x0bb900, "Play operation aborted" },
+-
+-	/* Here we use 0xff for the key (not a valid key) to signify
+-	 * that these can have _any_ key value associated with them... */
+-	{ 0xff0401, "Logical unit is in process of becoming ready" },
+-	{ 0xff0400, "Logical unit not ready, cause not reportable" },
+-	{ 0xff0402, "Logical unit not ready, initializing command required" },
+-	{ 0xff0403, "Logical unit not ready, manual intervention required" },
+-	{ 0xff0500, "Logical unit does not respond to selection" },
+-	{ 0xff0800, "Logical unit communication failure" },
+-	{ 0xff0802, "Logical unit communication parity error" },
+-	{ 0xff0801, "Logical unit communication time-out" },
+-	{ 0xff2500, "Logical unit not supported" },
+-	{ 0xff4c00, "Logical unit failed self-configuration" },
+-	{ 0xff3e00, "Logical unit has not self-configured yet" },
+-};
+-#endif
+-
++/* ide-cd_verbose.c */
++void ide_cd_log_error(const char *, struct request *, struct request_sense *);
++
++/* ide-cd.c functions used by ide-cd_ioctl.c */
++void ide_cd_init_rq(ide_drive_t *, struct request *);
++int ide_cd_queue_pc(ide_drive_t *, struct request *);
++int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
++int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
++void ide_cdrom_update_speed(ide_drive_t *, u8 *);
++int cdrom_check_status(ide_drive_t *, struct request_sense *);
++
++/* ide-cd_ioctl.c */
++int ide_cdrom_open_real(struct cdrom_device_info *, int);
++void ide_cdrom_release_real(struct cdrom_device_info *);
++int ide_cdrom_drive_status(struct cdrom_device_info *, int);
++int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
++int ide_cdrom_tray_move(struct cdrom_device_info *, int);
++int ide_cdrom_lock_door(struct cdrom_device_info *, int);
++int ide_cdrom_select_speed(struct cdrom_device_info *, int);
++int ide_cdrom_get_last_session(struct cdrom_device_info *,
++			       struct cdrom_multisession *);
++int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
++int ide_cdrom_reset(struct cdrom_device_info *cdi);
++int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
++int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *);
  
-diff --git a/drivers/hid/hid-input-quirks.c b/drivers/hid/hid-input-quirks.c
+ #endif /* _IDE_CD_H */
+diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
 new file mode 100644
-index 0000000..a870ba5
+index 0000000..b68284d
 --- /dev/null
-+++ b/drivers/hid/hid-input-quirks.c
-@@ -0,0 +1,423 @@
++++ b/drivers/ide/ide-cd_ioctl.c
+@@ -0,0 +1,475 @@
 +/*
-+ *  HID-input usage mapping quirks
-+ *
-+ *  This is used to handle HID-input mappings for devices violating
-+ *  HUT 1.12 specification.
++ * cdrom.c IOCTLs handling for ide-cd driver.
 + *
-+ * Copyright (c) 2007-2008 Jiri Kosina
++ * Copyright (C) 1994-1996  Scott Snyder <snyder at fnald0.fnal.gov>
++ * Copyright (C) 1996-1998  Erik Andersen <andersee at debian.org>
++ * Copyright (C) 1998-2000  Jens Axboe <axboe at suse.de>
++ */
++
++#include <linux/kernel.h>
++#include <linux/cdrom.h>
++#include <linux/ide.h>
++#include <scsi/scsi.h>
++
++#include "ide-cd.h"
++
++/****************************************************************************
++ * Other driver requests (open, close, check media change).
 + */
++int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
++{
++	return 0;
++}
 +
 +/*
-+ * 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
++ * Close down the device.  Invalidate all cached blocks.
 + */
++void ide_cdrom_release_real(struct cdrom_device_info *cdi)
++{
++	ide_drive_t *drive = cdi->handle;
++	struct cdrom_info *cd = drive->driver_data;
 +
-+#include <linux/input.h>
-+#include <linux/hid.h>
++	if (!cdi->use_count)
++		cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
++}
 +
-+#define map_abs(c)      do { usage->code = c; usage->type = EV_ABS; *bit = input->absbit; *max = ABS_MAX; } while (0)
-+#define map_rel(c)      do { usage->code = c; usage->type = EV_REL; *bit = input->relbit; *max = REL_MAX; } while (0)
-+#define map_key(c)      do { usage->code = c; usage->type = EV_KEY; *bit = input->keybit; *max = KEY_MAX; } while (0)
-+#define map_led(c)      do { usage->code = c; usage->type = EV_LED; *bit = input->ledbit; *max = LED_MAX; } while (0)
++/*
++ * add logic to try GET_EVENT command first to check for media and tray
++ * status. this should be supported by newer cd-r/w and all DVD etc
++ * drives
++ */
++int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
++{
++	ide_drive_t *drive = cdi->handle;
++	struct media_event_desc med;
++	struct request_sense sense;
++	int stat;
 +
-+#define map_abs_clear(c)        do { map_abs(c); clear_bit(c, *bit); } while (0)
-+#define map_key_clear(c)        do { map_key(c); clear_bit(c, *bit); } while (0)
++	if (slot_nr != CDSL_CURRENT)
++		return -EINVAL;
 +
-+static int quirk_belkin_wkbd(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
-+{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-+		return 0;
++	stat = cdrom_check_status(drive, &sense);
++	if (!stat || sense.sense_key == UNIT_ATTENTION)
++		return CDS_DISC_OK;
 +
-+	switch (usage->hid & HID_USAGE) {
-+		case 0x03a: map_key_clear(KEY_SOUND);		break;
-+		case 0x03b: map_key_clear(KEY_CAMERA);		break;
-+		case 0x03c: map_key_clear(KEY_DOCUMENTS);	break;
-+		default:
-+			return 0;
++	if (!cdrom_get_media_event(cdi, &med)) {
++		if (med.media_present)
++			return CDS_DISC_OK;
++		else if (med.door_open)
++			return CDS_TRAY_OPEN;
++		else
++			return CDS_NO_DISC;
 +	}
-+	return 1;
++
++	if (sense.sense_key == NOT_READY && sense.asc == 0x04
++			&& sense.ascq == 0x04)
++		return CDS_DISC_OK;
++
++	/*
++	 * If not using Mt Fuji extended media tray reports,
++	 * just return TRAY_OPEN since ATAPI doesn't provide
++	 * any other way to detect this...
++	 */
++	if (sense.sense_key == NOT_READY) {
++		if (sense.asc == 0x3a && sense.ascq == 1)
++			return CDS_NO_DISC;
++		else
++			return CDS_TRAY_OPEN;
++	}
++	return CDS_DRIVE_NOT_READY;
 +}
 +
-+static int quirk_cherry_cymotion(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
++				       int slot_nr)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-+		return 0;
++	ide_drive_t *drive = cdi->handle;
++	struct cdrom_info *cd = drive->driver_data;
++	int retval;
 +
-+	switch (usage->hid & HID_USAGE) {
-+		case 0x301: map_key_clear(KEY_PROG1);		break;
-+		case 0x302: map_key_clear(KEY_PROG2);		break;
-+		case 0x303: map_key_clear(KEY_PROG3);		break;
-+		default:
-+			return 0;
++	if (slot_nr == CDSL_CURRENT) {
++		(void) cdrom_check_status(drive, NULL);
++		retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
++		cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
++		return retval;
++	} else {
++		return -EINVAL;
 +	}
-+	return 1;
 +}
 +
-+static int quirk_logitech_ultrax_remote(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++/* Eject the disk if EJECTFLAG is 0.
++   If EJECTFLAG is 1, try to reload the disk. */
++static
++int cdrom_eject(ide_drive_t *drive, int ejectflag,
++		struct request_sense *sense)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR)
++	struct cdrom_info *cd = drive->driver_data;
++	struct cdrom_device_info *cdi = &cd->devinfo;
++	struct request req;
++	char loej = 0x02;
++
++	if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
++		return -EDRIVE_CANT_DO_THIS;
++
++	/* reload fails on some drives, if the tray is locked */
++	if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
 +		return 0;
 +
-+	set_bit(EV_REP, input->evbit);
-+	switch(usage->hid & HID_USAGE) {
-+		/* Reported on Logitech Ultra X Media Remote */
-+		case 0x004: map_key_clear(KEY_AGAIN);		break;
-+		case 0x00d: map_key_clear(KEY_HOME);		break;
-+		case 0x024: map_key_clear(KEY_SHUFFLE);		break;
-+		case 0x025: map_key_clear(KEY_TV);		break;
-+		case 0x026: map_key_clear(KEY_MENU);		break;
-+		case 0x031: map_key_clear(KEY_AUDIO);		break;
-+		case 0x032: map_key_clear(KEY_TEXT);		break;
-+		case 0x033: map_key_clear(KEY_LAST);		break;
-+		case 0x047: map_key_clear(KEY_MP3);		break;
-+		case 0x048: map_key_clear(KEY_DVD);		break;
-+		case 0x049: map_key_clear(KEY_MEDIA);		break;
-+		case 0x04a: map_key_clear(KEY_VIDEO);		break;
-+		case 0x04b: map_key_clear(KEY_ANGLE);		break;
-+		case 0x04c: map_key_clear(KEY_LANGUAGE);	break;
-+		case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
-+		case 0x051: map_key_clear(KEY_RED);		break;
-+		case 0x052: map_key_clear(KEY_CLOSE);		break;
++	ide_cd_init_rq(drive, &req);
 +
-+		default:
-+			return 0;
++	/* only tell drive to close tray if open, if it can do that */
++	if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
++		loej = 0;
++
++	req.sense = sense;
++	req.cmd[0] = GPCMD_START_STOP_UNIT;
++	req.cmd[4] = loej | (ejectflag != 0);
++
++	return ide_cd_queue_pc(drive, &req);
++}
++
++/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
++static
++int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
++		    struct request_sense *sense)
++{
++	struct cdrom_info *cd = drive->driver_data;
++	struct request_sense my_sense;
++	struct request req;
++	int stat;
++
++	if (sense == NULL)
++		sense = &my_sense;
++
++	/* If the drive cannot lock the door, just pretend. */
++	if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
++		stat = 0;
++	} else {
++		ide_cd_init_rq(drive, &req);
++		req.sense = sense;
++		req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
++		req.cmd[4] = lockflag ? 1 : 0;
++		stat = ide_cd_queue_pc(drive, &req);
 +	}
-+	return 1;
++
++	/* If we got an illegal field error, the drive
++	   probably cannot lock the door. */
++	if (stat != 0 &&
++	    sense->sense_key == ILLEGAL_REQUEST &&
++	    (sense->asc == 0x24 || sense->asc == 0x20)) {
++		printk(KERN_ERR "%s: door locking not supported\n",
++			drive->name);
++		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
++		stat = 0;
++	}
++
++	/* no medium, that's alright. */
++	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
++		stat = 0;
++
++	if (stat == 0) {
++		if (lockflag)
++			cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
++		else
++			cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
++	}
++
++	return stat;
 +}
 +
-+static int quirk_chicony_tactical_pad(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-+		return 0;
++	ide_drive_t *drive = cdi->handle;
++	struct request_sense sense;
 +
-+	set_bit(EV_REP, input->evbit);
-+	switch (usage->hid & HID_USAGE) {
-+		case 0xff01: map_key_clear(BTN_1);		break;
-+		case 0xff02: map_key_clear(BTN_2);		break;
-+		case 0xff03: map_key_clear(BTN_3);		break;
-+		case 0xff04: map_key_clear(BTN_4);		break;
-+		case 0xff05: map_key_clear(BTN_5);		break;
-+		case 0xff06: map_key_clear(BTN_6);		break;
-+		case 0xff07: map_key_clear(BTN_7);		break;
-+		case 0xff08: map_key_clear(BTN_8);		break;
-+		case 0xff09: map_key_clear(BTN_9);		break;
-+		case 0xff0a: map_key_clear(BTN_A);		break;
-+		case 0xff0b: map_key_clear(BTN_B);		break;
-+		default:
-+			return 0;
++	if (position) {
++		int stat = ide_cd_lockdoor(drive, 0, &sense);
++
++		if (stat)
++			return stat;
 +	}
-+	return 1;
++
++	return cdrom_eject(drive, !position, &sense);
 +}
 +
-+static int quirk_microsoft_ergonomy_kb(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-+		return 0;
++	ide_drive_t *drive = cdi->handle;
 +
-+	switch(usage->hid & HID_USAGE) {
-+		case 0xfd06: map_key_clear(KEY_CHAT);		break;
-+		case 0xfd07: map_key_clear(KEY_PHONE);		break;
-+		case 0xff05:
-+			set_bit(EV_REP, input->evbit);
-+			map_key_clear(KEY_F13);
-+			set_bit(KEY_F14, input->keybit);
-+			set_bit(KEY_F15, input->keybit);
-+			set_bit(KEY_F16, input->keybit);
-+			set_bit(KEY_F17, input->keybit);
-+			set_bit(KEY_F18, input->keybit);
-+		default:
-+			return 0;
++	return ide_cd_lockdoor(drive, lock, NULL);
++}
++
++/*
++ * ATAPI devices are free to select the speed you request or any slower
++ * rate. :-(  Requesting too fast a speed will _not_ produce an error.
++ */
++int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
++{
++	ide_drive_t *drive = cdi->handle;
++	struct cdrom_info *cd = drive->driver_data;
++	struct request rq;
++	struct request_sense sense;
++	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
++	int stat;
++
++	ide_cd_init_rq(drive, &rq);
++
++	rq.sense = &sense;
++
++	if (speed == 0)
++		speed = 0xffff; /* set to max */
++	else
++		speed *= 177;   /* Nx to kbytes/s */
++
++	rq.cmd[0] = GPCMD_SET_SPEED;
++	/* Read Drive speed in kbytes/second MSB/LSB */
++	rq.cmd[2] = (speed >> 8) & 0xff;
++	rq.cmd[3] = speed & 0xff;
++	if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
++	    (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
++		/* Write Drive speed in kbytes/second MSB/LSB */
++		rq.cmd[4] = (speed >> 8) & 0xff;
++		rq.cmd[5] = speed & 0xff;
 +	}
-+	return 1;
++
++	stat = ide_cd_queue_pc(drive, &rq);
++
++	if (!ide_cdrom_get_capabilities(drive, buf)) {
++		ide_cdrom_update_speed(drive, buf);
++		cdi->speed = cd->current_speed;
++	}
++
++	return 0;
 +}
 +
-+static int quirk_microsoft_presenter_8k(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
++			       struct cdrom_multisession *ms_info)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_MSVENDOR)
-+		return 0;
++	struct atapi_toc *toc;
++	ide_drive_t *drive = cdi->handle;
++	struct cdrom_info *info = drive->driver_data;
++	struct request_sense sense;
++	int ret;
 +
-+	set_bit(EV_REP, input->evbit);
-+	switch(usage->hid & HID_USAGE) {
-+		case 0xfd08: map_key_clear(KEY_FORWARD);	break;
-+		case 0xfd09: map_key_clear(KEY_BACK);		break;
-+		case 0xfd0b: map_key_clear(KEY_PLAYPAUSE);	break;
-+		case 0xfd0e: map_key_clear(KEY_CLOSE);		break;
-+		case 0xfd0f: map_key_clear(KEY_PLAY);		break;
-+		default:
-+			return 0;
++	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
++		ret = ide_cd_read_toc(drive, &sense);
++		if (ret)
++			return ret;
 +	}
-+	return 1;
++
++	toc = info->toc;
++	ms_info->addr.lba = toc->last_session_lba;
++	ms_info->xa_flag = toc->xa_flag;
++
++	return 0;
 +}
 +
-+static int quirk_petalynx_remote(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
++		      struct cdrom_mcn *mcn_info)
 +{
-+	if (((usage->hid & HID_USAGE_PAGE) != HID_UP_LOGIVENDOR) &&
-+			((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER))
-+		return 0;
++	ide_drive_t *drive = cdi->handle;
++	int stat, mcnlen;
++	struct request rq;
++	char buf[24];
 +
-+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_LOGIVENDOR)
-+		switch(usage->hid & HID_USAGE) {
-+			case 0x05a: map_key_clear(KEY_TEXT);		break;
-+			case 0x05b: map_key_clear(KEY_RED);		break;
-+			case 0x05c: map_key_clear(KEY_GREEN);		break;
-+			case 0x05d: map_key_clear(KEY_YELLOW);		break;
-+			case 0x05e: map_key_clear(KEY_BLUE);		break;
-+			default:
-+				return 0;
-+		}
++	ide_cd_init_rq(drive, &rq);
 +
-+	if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER)
-+		switch(usage->hid & HID_USAGE) {
-+			case 0x0f6: map_key_clear(KEY_NEXT);            break;
-+			case 0x0fa: map_key_clear(KEY_BACK);            break;
-+			default:
-+				return 0;
-+		}
-+	return 1;
++	rq.data = buf;
++	rq.data_len = sizeof(buf);
++
++	rq.cmd[0] = GPCMD_READ_SUBCHANNEL;
++	rq.cmd[1] = 2;		/* MSF addressing */
++	rq.cmd[2] = 0x40;	/* request subQ data */
++	rq.cmd[3] = 2;		/* format */
++	rq.cmd[8] = sizeof(buf);
++
++	stat = ide_cd_queue_pc(drive, &rq);
++	if (stat)
++		return stat;
++
++	mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
++	memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
++	mcn_info->medium_catalog_number[mcnlen] = '\0';
++
++	return 0;
 +}
 +
-+static int quirk_logitech_wireless(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++int ide_cdrom_reset(struct cdrom_device_info *cdi)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-+		return 0;
++	ide_drive_t *drive = cdi->handle;
++	struct cdrom_info *cd = drive->driver_data;
++	struct request_sense sense;
++	struct request req;
++	int ret;
 +
-+	switch (usage->hid & HID_USAGE) {
-+		case 0x1001: map_key_clear(KEY_MESSENGER);	break;
-+		case 0x1003: map_key_clear(KEY_SOUND);		break;
-+		case 0x1004: map_key_clear(KEY_VIDEO);		break;
-+		case 0x1005: map_key_clear(KEY_AUDIO);		break;
-+		case 0x100a: map_key_clear(KEY_DOCUMENTS);	break;
-+		case 0x1011: map_key_clear(KEY_PREVIOUSSONG);	break;
-+		case 0x1012: map_key_clear(KEY_NEXTSONG);	break;
-+		case 0x1013: map_key_clear(KEY_CAMERA);		break;
-+		case 0x1014: map_key_clear(KEY_MESSENGER);	break;
-+		case 0x1015: map_key_clear(KEY_RECORD);		break;
-+		case 0x1016: map_key_clear(KEY_PLAYER);		break;
-+		case 0x1017: map_key_clear(KEY_EJECTCD);	break;
-+		case 0x1018: map_key_clear(KEY_MEDIA);		break;
-+		case 0x1019: map_key_clear(KEY_PROG1);		break;
-+		case 0x101a: map_key_clear(KEY_PROG2);		break;
-+		case 0x101b: map_key_clear(KEY_PROG3);		break;
-+		case 0x101f: map_key_clear(KEY_ZOOMIN);		break;
-+		case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
-+		case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
-+		case 0x1023: map_key_clear(KEY_CLOSE);		break;
-+		case 0x1027: map_key_clear(KEY_MENU);		break;
-+		/* this one is marked as 'Rotate' */
-+		case 0x1028: map_key_clear(KEY_ANGLE);		break;
-+		case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
-+		case 0x102a: map_key_clear(KEY_BACK);		break;
-+		case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);	break;
-+		case 0x1041: map_key_clear(KEY_BATTERY);	break;
-+		case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
-+		case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
-+		case 0x1044: map_key_clear(KEY_PRESENTATION);	break;
-+		case 0x1045: map_key_clear(KEY_UNDO);		break;
-+		case 0x1046: map_key_clear(KEY_REDO);		break;
-+		case 0x1047: map_key_clear(KEY_PRINT);		break;
-+		case 0x1048: map_key_clear(KEY_SAVE);		break;
-+		case 0x1049: map_key_clear(KEY_PROG1);		break;
-+		case 0x104a: map_key_clear(KEY_PROG2);		break;
-+		case 0x104b: map_key_clear(KEY_PROG3);		break;
-+		case 0x104c: map_key_clear(KEY_PROG4);		break;
++	ide_cd_init_rq(drive, &req);
++	req.cmd_type = REQ_TYPE_SPECIAL;
++	req.cmd_flags = REQ_QUIET;
++	ret = ide_do_drive_cmd(drive, &req, ide_wait);
 +
-+		default:
-+			return 0;
-+	}
-+	return 1;
++	/*
++	 * A reset will unlock the door. If it was previously locked,
++	 * lock it again.
++	 */
++	if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
++		(void)ide_cd_lockdoor(drive, 1, &sense);
++
++	return ret;
 +}
 +
-+static int quirk_cherry_genius_29e(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
++				struct atapi_toc_entry **ent)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-+		return 0;
++	struct cdrom_info *info = drive->driver_data;
++	struct atapi_toc *toc = info->toc;
++	int ntracks;
 +
-+	switch (usage->hid & HID_USAGE) {
-+		case 0x156: map_key_clear(KEY_WORDPROCESSOR);	break;
-+		case 0x157: map_key_clear(KEY_SPREADSHEET);	break;
-+		case 0x158: map_key_clear(KEY_PRESENTATION);	break;
-+		case 0x15c: map_key_clear(KEY_STOP);		break;
++	/*
++	 * don't serve cached data, if the toc isn't valid
++	 */
++	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
++		return -EINVAL;
 +
-+		default:
-+			return 0;
-+	}
-+	return 1;
++	/* Check validity of requested track number. */
++	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
++
++	if (toc->hdr.first_track == CDROM_LEADOUT)
++		ntracks = 0;
++
++	if (track == CDROM_LEADOUT)
++		*ent = &toc->ent[ntracks];
++	else if (track < toc->hdr.first_track || track > toc->hdr.last_track)
++		return -EINVAL;
++	else
++		*ent = &toc->ent[track - toc->hdr.first_track];
++
++	return 0;
 +}
 +
-+static int quirk_btc_8193(struct hid_usage *usage, struct input_dev *input,
-+			      unsigned long **bit, int *max)
++static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
 +{
-+	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_CONSUMER)
-+		return 0;
++	struct cdrom_ti *ti = arg;
++	struct atapi_toc_entry *first_toc, *last_toc;
++	unsigned long lba_start, lba_end;
++	int stat;
++	struct request rq;
++	struct request_sense sense;
 +
-+	switch (usage->hid & HID_USAGE) {
-+		case 0x230: map_key(BTN_MOUSE);			break;
-+		case 0x231: map_rel(REL_WHEEL);			break;
-+		/* 
-+		 * this keyboard has a scrollwheel implemented in
-+		 * totally broken way. We map this usage temporarily
-+		 * to HWHEEL and handle it in the event quirk handler
-+		 */
-+		case 0x232: map_rel(REL_HWHEEL);		break;
++	stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
++	if (stat)
++		return stat;
 +
-+		default:
-+			return 0;
-+	}
-+	return 1;
++	stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
++	if (stat)
++		return stat;
++
++	if (ti->cdti_trk1 != CDROM_LEADOUT)
++		++last_toc;
++	lba_start = first_toc->addr.lba;
++	lba_end   = last_toc->addr.lba;
++
++	if (lba_end <= lba_start)
++		return -EINVAL;
++
++	ide_cd_init_rq(drive, &rq);
++
++	rq.sense = &sense;
++	rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
++	lba_to_msf(lba_start,   &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]);
++	lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]);
++
++	return ide_cd_queue_pc(drive, &rq);
 +}
 +
-+#define VENDOR_ID_BELKIN			0x1020
-+#define DEVICE_ID_BELKIN_WIRELESS_KEYBOARD	0x0006
++static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
++{
++	struct cdrom_info *cd = drive->driver_data;
++	struct cdrom_tochdr *tochdr = arg;
++	struct atapi_toc *toc;
++	int stat;
 +
-+#define VENDOR_ID_CHERRY			0x046a
-+#define DEVICE_ID_CHERRY_CYMOTION		0x0023
++	/* Make sure our saved TOC is valid. */
++	stat = ide_cd_read_toc(drive, NULL);
++	if (stat)
++		return stat;
 +
-+#define VENDOR_ID_CHICONY			0x04f2
-+#define DEVICE_ID_CHICONY_TACTICAL_PAD		0x0418
++	toc = cd->toc;
++	tochdr->cdth_trk0 = toc->hdr.first_track;
++	tochdr->cdth_trk1 = toc->hdr.last_track;
 +
-+#define VENDOR_ID_EZKEY				0x0518
-+#define DEVICE_ID_BTC_8193			0x0002
++	return 0;
++}
 +
-+#define VENDOR_ID_LOGITECH			0x046d
-+#define DEVICE_ID_LOGITECH_RECEIVER		0xc101
-+#define DEVICE_ID_S510_RECEIVER			0xc50c
-+#define DEVICE_ID_S510_RECEIVER_2		0xc517
-+#define DEVICE_ID_MX3000_RECEIVER		0xc513
++static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
++{
++	struct cdrom_tocentry *tocentry = arg;
++	struct atapi_toc_entry *toce;
++	int stat;
 +
-+#define VENDOR_ID_MICROSOFT			0x045e
-+#define DEVICE_ID_MS4K				0x00db
-+#define DEVICE_ID_MS6K				0x00f9
-+#define DEVICE_IS_MS_PRESENTER_8K_BT		0x0701
-+#define DEVICE_ID_MS_PRESENTER_8K_USB		0x0713
++	stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
++	if (stat)
++		return stat;
 +
-+#define VENDOR_ID_MONTEREY			0x0566
-+#define DEVICE_ID_GENIUS_KB29E			0x3004
++	tocentry->cdte_ctrl = toce->control;
++	tocentry->cdte_adr  = toce->adr;
++	if (tocentry->cdte_format == CDROM_MSF) {
++		lba_to_msf(toce->addr.lba,
++			   &tocentry->cdte_addr.msf.minute,
++			   &tocentry->cdte_addr.msf.second,
++			   &tocentry->cdte_addr.msf.frame);
++	} else
++		tocentry->cdte_addr.lba = toce->addr.lba;
 +
-+#define VENDOR_ID_PETALYNX			0x18b1
-+#define DEVICE_ID_PETALYNX_MAXTER_REMOTE	0x0037
++	return 0;
++}
 +
-+static const struct hid_input_blacklist {
-+	__u16 idVendor;
-+	__u16 idProduct;
-+	int (*quirk)(struct hid_usage *, struct input_dev *, unsigned long **, int *);
-+} hid_input_blacklist[] = {
-+	{ VENDOR_ID_BELKIN, DEVICE_ID_BELKIN_WIRELESS_KEYBOARD, quirk_belkin_wkbd },
++int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
++			  unsigned int cmd, void *arg)
++{
++	ide_drive_t *drive = cdi->handle;
 +
-+	{ VENDOR_ID_CHERRY, DEVICE_ID_CHERRY_CYMOTION, quirk_cherry_cymotion },
++	switch (cmd) {
++	/*
++	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
++	 * atapi doesn't support it
++	 */
++	case CDROMPLAYTRKIND:
++		return ide_cd_fake_play_trkind(drive, arg);
++	case CDROMREADTOCHDR:
++		return ide_cd_read_tochdr(drive, arg);
++	case CDROMREADTOCENTRY:
++		return ide_cd_read_tocentry(drive, arg);
++	default:
++		return -EINVAL;
++	}
++}
 +
-+	{ VENDOR_ID_CHICONY, DEVICE_ID_CHICONY_TACTICAL_PAD, quirk_chicony_tactical_pad },
++/* the generic packet interface to cdrom.c */
++int ide_cdrom_packet(struct cdrom_device_info *cdi,
++			    struct packet_command *cgc)
++{
++	struct request req;
++	ide_drive_t *drive = cdi->handle;
 +
-+	{ VENDOR_ID_EZKEY, DEVICE_ID_BTC_8193, quirk_btc_8193 },
++	if (cgc->timeout <= 0)
++		cgc->timeout = ATAPI_WAIT_PC;
 +
-+	{ VENDOR_ID_LOGITECH, DEVICE_ID_LOGITECH_RECEIVER, quirk_logitech_ultrax_remote },
-+	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER, quirk_logitech_wireless },
-+	{ VENDOR_ID_LOGITECH, DEVICE_ID_S510_RECEIVER_2, quirk_logitech_wireless },
-+	{ VENDOR_ID_LOGITECH, DEVICE_ID_MX3000_RECEIVER, quirk_logitech_wireless },
++	/* here we queue the commands from the uniform CD-ROM
++	   layer. the packet must be complete, as we do not
++	   touch it at all. */
++	ide_cd_init_rq(drive, &req);
++	memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
++	if (cgc->sense)
++		memset(cgc->sense, 0, sizeof(struct request_sense));
++	req.data = cgc->buffer;
++	req.data_len = cgc->buflen;
++	req.timeout = cgc->timeout;
 +
-+	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS4K, quirk_microsoft_ergonomy_kb },
-+	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS6K, quirk_microsoft_ergonomy_kb },
-+	{ VENDOR_ID_MICROSOFT, DEVICE_IS_MS_PRESENTER_8K_BT, quirk_microsoft_presenter_8k },
-+	{ VENDOR_ID_MICROSOFT, DEVICE_ID_MS_PRESENTER_8K_USB, quirk_microsoft_presenter_8k },
++	if (cgc->quiet)
++		req.cmd_flags |= REQ_QUIET;
 +
-+	{ VENDOR_ID_MONTEREY, DEVICE_ID_GENIUS_KB29E, quirk_cherry_genius_29e },
++	req.sense = cgc->sense;
++	cgc->stat = ide_cd_queue_pc(drive, &req);
++	if (!cgc->stat)
++		cgc->buflen -= req.data_len;
++	return cgc->stat;
++}
+diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c
+new file mode 100644
+index 0000000..6ed7ca0
+--- /dev/null
++++ b/drivers/ide/ide-cd_verbose.c
+@@ -0,0 +1,359 @@
++/*
++ * Verbose error logging for ATAPI CD/DVD devices.
++ *
++ * Copyright (C) 1994-1996  Scott Snyder <snyder at fnald0.fnal.gov>
++ * Copyright (C) 1996-1998  Erik Andersen <andersee at debian.org>
++ * Copyright (C) 1998-2000  Jens Axboe <axboe at suse.de>
++ */
 +
-+	{ VENDOR_ID_PETALYNX, DEVICE_ID_PETALYNX_MAXTER_REMOTE, quirk_petalynx_remote },
-+	
-+	{ 0, 0, 0 }
++#include <linux/kernel.h>
++#include <linux/blkdev.h>
++#include <linux/cdrom.h>
++#include <scsi/scsi.h>
++
++#ifndef CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS
++void ide_cd_log_error(const char *name, struct request *failed_command,
++		      struct request_sense *sense)
++{
++	/* Suppress printing unit attention and `in progress of becoming ready'
++	   errors when we're not being verbose. */
++	if (sense->sense_key == UNIT_ATTENTION ||
++	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
++						sense->asc == 0x3a)))
++		return;
++
++	printk(KERN_ERR "%s: error code: 0x%02x  sense_key: 0x%02x  "
++			"asc: 0x%02x  ascq: 0x%02x\n",
++			name, sense->error_code, sense->sense_key,
++			sense->asc, sense->ascq);
++}
++#else
++/* The generic packet command opcodes for CD/DVD Logical Units,
++ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
++static const struct {
++	unsigned short packet_command;
++	const char * const text;
++} packet_command_texts[] = {
++	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
++	{ GPCMD_REQUEST_SENSE, "Request Sense" },
++	{ GPCMD_FORMAT_UNIT, "Format Unit" },
++	{ GPCMD_INQUIRY, "Inquiry" },
++	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
++	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
++	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
++	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
++	{ GPCMD_READ_10, "Read 10" },
++	{ GPCMD_WRITE_10, "Write 10" },
++	{ GPCMD_SEEK, "Seek" },
++	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
++	{ GPCMD_VERIFY_10, "Verify 10" },
++	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
++	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
++	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
++	{ GPCMD_READ_HEADER, "Read Header" },
++	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
++	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
++	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
++	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
++	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION,
++		"Get Event Status Notification" },
++	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
++	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
++	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
++	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
++	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
++	{ GPCMD_SEND_OPC, "Send OPC" },
++	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
++	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
++	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
++	{ GPCMD_CLOSE_TRACK, "Close Track" },
++	{ GPCMD_BLANK, "Blank" },
++	{ GPCMD_SEND_EVENT, "Send Event" },
++	{ GPCMD_SEND_KEY, "Send Key" },
++	{ GPCMD_REPORT_KEY, "Report Key" },
++	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
++	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
++	{ GPCMD_READ_12, "Read 12" },
++	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
++	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
++	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
++	{ GPCMD_SET_STREAMING, "Set Streaming" },
++	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
++	{ GPCMD_SCAN, "Scan" },
++	{ GPCMD_SET_SPEED, "Set Speed" },
++	{ GPCMD_PLAY_CD, "Play CD" },
++	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
++	{ GPCMD_READ_CD, "Read CD" },
 +};
 +
-+int hidinput_mapping_quirks(struct hid_usage *usage, 
-+				   struct input_dev *input, 
-+				   unsigned long **bit, int *max)
++/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
++static const char * const sense_key_texts[16] = {
++	"No sense data",
++	"Recovered error",
++	"Not ready",
++	"Medium error",
++	"Hardware error",
++	"Illegal request",
++	"Unit attention",
++	"Data protect",
++	"Blank check",
++	"(reserved)",
++	"(reserved)",
++	"Aborted command",
++	"(reserved)",
++	"(reserved)",
++	"Miscompare",
++	"(reserved)",
++};
++
++/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
++static const struct {
++	unsigned long asc_ascq;
++	const char * const text;
++} sense_data_texts[] = {
++	{ 0x000000, "No additional sense information" },
++	{ 0x000011, "Play operation in progress" },
++	{ 0x000012, "Play operation paused" },
++	{ 0x000013, "Play operation successfully completed" },
++	{ 0x000014, "Play operation stopped due to error" },
++	{ 0x000015, "No current audio status to return" },
++	{ 0x010c0a, "Write error - padding blocks added" },
++	{ 0x011700, "Recovered data with no error correction applied" },
++	{ 0x011701, "Recovered data with retries" },
++	{ 0x011702, "Recovered data with positive head offset" },
++	{ 0x011703, "Recovered data with negative head offset" },
++	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
++	{ 0x011705, "Recovered data using previous sector ID" },
++	{ 0x011800, "Recovered data with error correction applied" },
++	{ 0x011801, "Recovered data with error correction and retries applied"},
++	{ 0x011802, "Recovered data - the data was auto-reallocated" },
++	{ 0x011803, "Recovered data with CIRC" },
++	{ 0x011804, "Recovered data with L-EC" },
++	{ 0x015d00, "Failure prediction threshold exceeded"
++		    " - Predicted logical unit failure" },
++	{ 0x015d01, "Failure prediction threshold exceeded"
++		    " - Predicted media failure" },
++	{ 0x015dff, "Failure prediction threshold exceeded - False" },
++	{ 0x017301, "Power calibration area almost full" },
++	{ 0x020400, "Logical unit not ready - cause not reportable" },
++	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
++	{ 0x020401, "Logical unit not ready"
++		    " - in progress [sic] of becoming ready" },
++	{ 0x020402, "Logical unit not ready - initializing command required" },
++	{ 0x020403, "Logical unit not ready - manual intervention required" },
++	{ 0x020404, "Logical unit not ready - format in progress" },
++	{ 0x020407, "Logical unit not ready - operation in progress" },
++	{ 0x020408, "Logical unit not ready - long write in progress" },
++	{ 0x020600, "No reference position found (media may be upside down)" },
++	{ 0x023000, "Incompatible medium installed" },
++	{ 0x023a00, "Medium not present" },
++	{ 0x025300, "Media load or eject failed" },
++	{ 0x025700, "Unable to recover table of contents" },
++	{ 0x030300, "Peripheral device write fault" },
++	{ 0x030301, "No write current" },
++	{ 0x030302, "Excessive write errors" },
++	{ 0x030c00, "Write error" },
++	{ 0x030c01, "Write error - Recovered with auto reallocation" },
++	{ 0x030c02, "Write error - auto reallocation failed" },
++	{ 0x030c03, "Write error - recommend reassignment" },
++	{ 0x030c04, "Compression check miscompare error" },
++	{ 0x030c05, "Data expansion occurred during compress" },
++	{ 0x030c06, "Block not compressible" },
++	{ 0x030c07, "Write error - recovery needed" },
++	{ 0x030c08, "Write error - recovery failed" },
++	{ 0x030c09, "Write error - loss of streaming" },
++	{ 0x031100, "Unrecovered read error" },
++	{ 0x031106, "CIRC unrecovered error" },
++	{ 0x033101, "Format command failed" },
++	{ 0x033200, "No defect spare location available" },
++	{ 0x033201, "Defect list update failure" },
++	{ 0x035100, "Erase failure" },
++	{ 0x037200, "Session fixation error" },
++	{ 0x037201, "Session fixation error writin lead-in" },
++	{ 0x037202, "Session fixation error writin lead-out" },
++	{ 0x037300, "CD control error" },
++	{ 0x037302, "Power calibration area is full" },
++	{ 0x037303, "Power calibration area error" },
++	{ 0x037304, "Program memory area / RMA update failure" },
++	{ 0x037305, "Program memory area / RMA is full" },
++	{ 0x037306, "Program memory area / RMA is (almost) full" },
++	{ 0x040200, "No seek complete" },
++	{ 0x040300, "Write fault" },
++	{ 0x040900, "Track following error" },
++	{ 0x040901, "Tracking servo failure" },
++	{ 0x040902, "Focus servo failure" },
++	{ 0x040903, "Spindle servo failure" },
++	{ 0x041500, "Random positioning error" },
++	{ 0x041501, "Mechanical positioning or changer error" },
++	{ 0x041502, "Positioning error detected by read of medium" },
++	{ 0x043c00, "Mechanical positioning or changer error" },
++	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
++	{ 0x044400, "Internal CD/DVD logical unit failure" },
++	{ 0x04b600, "Media load mechanism failed" },
++	{ 0x051a00, "Parameter list length error" },
++	{ 0x052000, "Invalid command operation code" },
++	{ 0x052100, "Logical block address out of range" },
++	{ 0x052102, "Invalid address for write" },
++	{ 0x052400, "Invalid field in command packet" },
++	{ 0x052600, "Invalid field in parameter list" },
++	{ 0x052601, "Parameter not supported" },
++	{ 0x052602, "Parameter value invalid" },
++	{ 0x052700, "Write protected media" },
++	{ 0x052c00, "Command sequence error" },
++	{ 0x052c03, "Current program area is not empty" },
++	{ 0x052c04, "Current program area is empty" },
++	{ 0x053001, "Cannot read medium - unknown format" },
++	{ 0x053002, "Cannot read medium - incompatible format" },
++	{ 0x053900, "Saving parameters not supported" },
++	{ 0x054e00, "Overlapped commands attempted" },
++	{ 0x055302, "Medium removal prevented" },
++	{ 0x055500, "System resource failure" },
++	{ 0x056300, "End of user area encountered on this track" },
++	{ 0x056400, "Illegal mode for this track or incompatible medium" },
++	{ 0x056f00, "Copy protection key exchange failure"
++		    " - Authentication failure" },
++	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
++	{ 0x056f02, "Copy protection key exchange failure"
++		     " - Key not established" },
++	{ 0x056f03, "Read of scrambled sector without authentication" },
++	{ 0x056f04, "Media region code is mismatched to logical unit" },
++	{ 0x056f05, "Drive region must be permanent"
++		    " / region reset count error" },
++	{ 0x057203, "Session fixation error - incomplete track in session" },
++	{ 0x057204, "Empty or partially written reserved track" },
++	{ 0x057205, "No more RZONE reservations are allowed" },
++	{ 0x05bf00, "Loss of streaming" },
++	{ 0x062800, "Not ready to ready transition, medium may have changed" },
++	{ 0x062900, "Power on, reset or hardware reset occurred" },
++	{ 0x062a00, "Parameters changed" },
++	{ 0x062a01, "Mode parameters changed" },
++	{ 0x062e00, "Insufficient time for operation" },
++	{ 0x063f00, "Logical unit operating conditions have changed" },
++	{ 0x063f01, "Microcode has been changed" },
++	{ 0x065a00, "Operator request or state change input (unspecified)" },
++	{ 0x065a01, "Operator medium removal request" },
++	{ 0x0bb900, "Play operation aborted" },
++	/* Here we use 0xff for the key (not a valid key) to signify
++	 * that these can have _any_ key value associated with them... */
++	{ 0xff0401, "Logical unit is in process of becoming ready" },
++	{ 0xff0400, "Logical unit not ready, cause not reportable" },
++	{ 0xff0402, "Logical unit not ready, initializing command required" },
++	{ 0xff0403, "Logical unit not ready, manual intervention required" },
++	{ 0xff0500, "Logical unit does not respond to selection" },
++	{ 0xff0800, "Logical unit communication failure" },
++	{ 0xff0802, "Logical unit communication parity error" },
++	{ 0xff0801, "Logical unit communication time-out" },
++	{ 0xff2500, "Logical unit not supported" },
++	{ 0xff4c00, "Logical unit failed self-configuration" },
++	{ 0xff3e00, "Logical unit has not self-configured yet" },
++};
++
++void ide_cd_log_error(const char *name, struct request *failed_command,
++		      struct request_sense *sense)
 +{
-+	struct hid_device *device = input_get_drvdata(input);
-+	int i = 0;
-+	
-+	while (hid_input_blacklist[i].quirk) {
-+		if (hid_input_blacklist[i].idVendor == device->vendor &&
-+				hid_input_blacklist[i].idProduct == device->product)
-+			return hid_input_blacklist[i].quirk(usage, input, bit, max);
-+		i++;
++	int i;
++	const char *s = "bad sense key!";
++	char buf[80];
++
++	printk(KERN_ERR "ATAPI device %s:\n", name);
++	if (sense->error_code == 0x70)
++		printk(KERN_CONT "  Error: ");
++	else if (sense->error_code == 0x71)
++		printk("  Deferred Error: ");
++	else if (sense->error_code == 0x7f)
++		printk(KERN_CONT "  Vendor-specific Error: ");
++	else
++		printk(KERN_CONT "  Unknown Error Type: ");
++
++	if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
++		s = sense_key_texts[sense->sense_key];
++
++	printk(KERN_CONT "%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
++
++	if (sense->asc == 0x40) {
++		sprintf(buf, "Diagnostic failure on component 0x%02x",
++			sense->ascq);
++		s = buf;
++	} else {
++		int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
++		unsigned long key = (sense->sense_key << 16);
++
++		key |= (sense->asc << 8);
++		if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
++			key |= sense->ascq;
++		s = NULL;
++
++		while (hi > lo) {
++			mid = (lo + hi) / 2;
++			if (sense_data_texts[mid].asc_ascq == key ||
++			    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
++				s = sense_data_texts[mid].text;
++				break;
++			} else if (sense_data_texts[mid].asc_ascq > key)
++				hi = mid;
++			else
++				lo = mid + 1;
++		}
 +	}
-+	return 0;
++
++	if (s == NULL) {
++		if (sense->asc > 0x80)
++			s = "(vendor-specific error)";
++		else
++			s = "(reserved error code)";
++	}
++
++	printk(KERN_ERR "  %s -- (asc=0x%02x, ascq=0x%02x)\n",
++			s, sense->asc, sense->ascq);
++
++	if (failed_command != NULL) {
++		int lo = 0, mid, hi = ARRAY_SIZE(packet_command_texts);
++		s = NULL;
++
++		while (hi > lo) {
++			mid = (lo + hi) / 2;
++			if (packet_command_texts[mid].packet_command ==
++			    failed_command->cmd[0]) {
++				s = packet_command_texts[mid].text;
++				break;
++			}
++			if (packet_command_texts[mid].packet_command >
++			    failed_command->cmd[0])
++				hi = mid;
++			else
++				lo = mid + 1;
++		}
++
++		printk(KERN_ERR "  The failed \"%s\" packet command "
++				"was: \n  \"", s);
++		for (i = 0; i < sizeof(failed_command->cmd); i++)
++			printk(KERN_CONT "%02x ", failed_command->cmd[i]);
++		printk(KERN_CONT "\"\n");
++	}
++
++	/* The SKSV bit specifies validity of the sense_key_specific
++	 * in the next two commands. It is bit 7 of the first byte.
++	 * In the case of NOT_READY, if SKSV is set the drive can
++	 * give us nice ETA readings.
++	 */
++	if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
++		int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
++
++		printk(KERN_ERR "  Command is %02d%% complete\n",
++				progress / 0xffff);
++	}
++
++	if (sense->sense_key == ILLEGAL_REQUEST &&
++	    (sense->sks[0] & 0x80) != 0) {
++		printk(KERN_ERR "  Error in %s byte %d",
++				(sense->sks[0] & 0x40) != 0 ?
++				"command packet" : "command data",
++				(sense->sks[1] << 8) + sense->sks[2]);
++
++		if ((sense->sks[0] & 0x40) != 0)
++			printk(KERN_CONT " bit %d", sense->sks[0] & 0x07);
++
++		printk(KERN_CONT "\n");
++	}
++}
++#endif
+diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
+index b178190..3c69822 100644
+--- a/drivers/ide/ide-disk.c
++++ b/drivers/ide/ide-disk.c
+@@ -1,10 +1,9 @@
+ /*
+- *  linux/drivers/ide/ide-disk.c	Version 1.18	Mar 05, 2003
+- *
+- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
+- *  Copyright (C) 1998-2002  Linux ATA Development
+- *				Andre Hedrick <andre at linux-ide.org>
+- *  Copyright (C) 2003	     Red Hat <alan at redhat.com>
++ *  Copyright (C) 1994-1998	   Linus Torvalds & authors (see below)
++ *  Copyright (C) 1998-2002	   Linux ATA Development
++ *				      Andre Hedrick <andre at linux-ide.org>
++ *  Copyright (C) 2003		   Red Hat <alan at redhat.com>
++ *  Copyright (C) 2003-2005, 2007  Bartlomiej Zolnierkiewicz
+  */
+ 
+ /*
+@@ -129,6 +128,50 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
+ 	return 0;	/* lba_capacity value may be bad */
+ }
+ 
++static const u8 ide_rw_cmds[] = {
++	WIN_MULTREAD,
++	WIN_MULTWRITE,
++	WIN_MULTREAD_EXT,
++	WIN_MULTWRITE_EXT,
++	WIN_READ,
++	WIN_WRITE,
++	WIN_READ_EXT,
++	WIN_WRITE_EXT,
++	WIN_READDMA,
++	WIN_WRITEDMA,
++	WIN_READDMA_EXT,
++	WIN_WRITEDMA_EXT,
++};
++
++static const u8 ide_data_phases[] = {
++	TASKFILE_MULTI_IN,
++	TASKFILE_MULTI_OUT,
++	TASKFILE_IN,
++	TASKFILE_OUT,
++	TASKFILE_IN_DMA,
++	TASKFILE_OUT_DMA,
++};
++
++static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
++{
++	u8 index, lba48, write;
++
++	lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
++	write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
++
++	if (dma)
++		index = drive->vdma ? 4 : 8;
++	else
++		index = drive->mult_count ? 0 : 4;
++
++	task->tf.command = ide_rw_cmds[index + lba48 + write];
++
++	if (dma)
++		index = 8; /* fixup index */
++
++	task->data_phase = ide_data_phases[index / 2 + write];
 +}
 +
-+void hidinput_event_quirks(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
+ /*
+  * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
+  * using LBA if supported, or CHS otherwise, to address sectors.
+@@ -137,11 +180,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+ 	unsigned int dma	= drive->using_dma;
++	u16 nsectors		= (u16)rq->nr_sectors;
+ 	u8 lba48		= (drive->addressing == 1) ? 1 : 0;
+-	task_ioreg_t command	= WIN_NOP;
+-	ata_nsector_t		nsectors;
+-
+-	nsectors.all		= (u16) rq->nr_sectors;
++	ide_task_t		task;
++	struct ide_taskfile	*tf = &task.tf;
++	ide_startstop_t		rc;
+ 
+ 	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
+ 		if (block + rq->nr_sectors > 1ULL << 28)
+@@ -155,121 +198,71 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
+ 		ide_map_sg(drive, rq);
+ 	}
+ 
+-	if (IDE_CONTROL_REG)
+-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+-
+-	/* FIXME: SELECT_MASK(drive, 0) ? */
++	memset(&task, 0, sizeof(task));
++	task.tf_flags = IDE_TFLAG_NO_SELECT_MASK;  /* FIXME? */
++	task.tf_flags |= (IDE_TFLAG_TF | IDE_TFLAG_DEVICE);
+ 
+ 	if (drive->select.b.lba) {
+ 		if (lba48) {
+-			task_ioreg_t tasklets[10];
+-
+ 			pr_debug("%s: LBA=0x%012llx\n", drive->name,
+ 					(unsigned long long)block);
+ 
+-			tasklets[0] = 0;
+-			tasklets[1] = 0;
+-			tasklets[2] = nsectors.b.low;
+-			tasklets[3] = nsectors.b.high;
+-			tasklets[4] = (task_ioreg_t) block;
+-			tasklets[5] = (task_ioreg_t) (block>>8);
+-			tasklets[6] = (task_ioreg_t) (block>>16);
+-			tasklets[7] = (task_ioreg_t) (block>>24);
+-			if (sizeof(block) == 4) {
+-				tasklets[8] = (task_ioreg_t) 0;
+-				tasklets[9] = (task_ioreg_t) 0;
+-			} else {
+-				tasklets[8] = (task_ioreg_t)((u64)block >> 32);
+-				tasklets[9] = (task_ioreg_t)((u64)block >> 40);
++			tf->hob_nsect = (nsectors >> 8) & 0xff;
++			tf->hob_lbal  = (u8)(block >> 24);
++			if (sizeof(block) != 4) {
++				tf->hob_lbam = (u8)((u64)block >> 32);
++				tf->hob_lbah = (u8)((u64)block >> 40);
+ 			}
+-#ifdef DEBUG
+-			printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
+-				drive->name, tasklets[3], tasklets[2],
+-				tasklets[9], tasklets[8], tasklets[7],
+-				tasklets[6], tasklets[5], tasklets[4]);
+-#endif
+-			hwif->OUTB(tasklets[1], IDE_FEATURE_REG);
+-			hwif->OUTB(tasklets[3], IDE_NSECTOR_REG);
+-			hwif->OUTB(tasklets[7], IDE_SECTOR_REG);
+-			hwif->OUTB(tasklets[8], IDE_LCYL_REG);
+-			hwif->OUTB(tasklets[9], IDE_HCYL_REG);
+-
+-			hwif->OUTB(tasklets[0], IDE_FEATURE_REG);
+-			hwif->OUTB(tasklets[2], IDE_NSECTOR_REG);
+-			hwif->OUTB(tasklets[4], IDE_SECTOR_REG);
+-			hwif->OUTB(tasklets[5], IDE_LCYL_REG);
+-			hwif->OUTB(tasklets[6], IDE_HCYL_REG);
+-			hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG);
++
++			tf->nsect  = nsectors & 0xff;
++			tf->lbal   = (u8) block;
++			tf->lbam   = (u8)(block >>  8);
++			tf->lbah   = (u8)(block >> 16);
++
++			task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+ 		} else {
+-			hwif->OUTB(0x00, IDE_FEATURE_REG);
+-			hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
+-			hwif->OUTB(block, IDE_SECTOR_REG);
+-			hwif->OUTB(block>>=8, IDE_LCYL_REG);
+-			hwif->OUTB(block>>=8, IDE_HCYL_REG);
+-			hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
++			tf->nsect  = nsectors & 0xff;
++			tf->lbal   = block;
++			tf->lbam   = block >>= 8;
++			tf->lbah   = block >>= 8;
++			tf->device = (block >> 8) & 0xf;
+ 		}
+ 	} else {
+ 		unsigned int sect,head,cyl,track;
+ 		track = (int)block / drive->sect;
+ 		sect  = (int)block % drive->sect + 1;
+-		hwif->OUTB(sect, IDE_SECTOR_REG);
+ 		head  = track % drive->head;
+ 		cyl   = track / drive->head;
+ 
+ 		pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
+ 
+-		hwif->OUTB(0x00, IDE_FEATURE_REG);
+-		hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
+-		hwif->OUTB(cyl, IDE_LCYL_REG);
+-		hwif->OUTB(cyl>>8, IDE_HCYL_REG);
+-		hwif->OUTB(head|drive->select.all,IDE_SELECT_REG);
++		tf->nsect  = nsectors & 0xff;
++		tf->lbal   = sect;
++		tf->lbam   = cyl;
++		tf->lbah   = cyl >> 8;
++		tf->device = head;
+ 	}
+ 
+-	if (dma) {
+-		if (!hwif->dma_setup(drive)) {
+-			if (rq_data_dir(rq)) {
+-				command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
+-				if (drive->vdma)
+-					command = lba48 ? WIN_WRITE_EXT: WIN_WRITE;
+-			} else {
+-				command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
+-				if (drive->vdma)
+-					command = lba48 ? WIN_READ_EXT: WIN_READ;
+-			}
+-			hwif->dma_exec_cmd(drive, command);
+-			hwif->dma_start(drive);
+-			return ide_started;
+-		}
+-		/* fallback to PIO */
+-		ide_init_sg_cmd(drive, rq);
+-	}
+-
+-	if (rq_data_dir(rq) == READ) {
++	if (rq_data_dir(rq))
++		task.tf_flags |= IDE_TFLAG_WRITE;
+ 
+-		if (drive->mult_count) {
+-			hwif->data_phase = TASKFILE_MULTI_IN;
+-			command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
+-		} else {
+-			hwif->data_phase = TASKFILE_IN;
+-			command = lba48 ? WIN_READ_EXT : WIN_READ;
+-		}
+-
+-		ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);
+-		return ide_started;
+-	} else {
+-		if (drive->mult_count) {
+-			hwif->data_phase = TASKFILE_MULTI_OUT;
+-			command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
+-		} else {
+-			hwif->data_phase = TASKFILE_OUT;
+-			command = lba48 ? WIN_WRITE_EXT : WIN_WRITE;
+-		}
++	ide_tf_set_cmd(drive, &task, dma);
++	if (!dma)
++		hwif->data_phase = task.data_phase;
++	task.rq = rq;
+ 
+-		/* FIXME: ->OUTBSYNC ? */
+-		hwif->OUTB(command, IDE_COMMAND_REG);
++	rc = do_rw_taskfile(drive, &task);
+ 
+-		return pre_task_out_intr(drive, rq);
++	if (rc == ide_stopped && dma) {
++		/* fallback to PIO */
++		task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
++		ide_tf_set_cmd(drive, &task, 0);
++		hwif->data_phase = task.data_phase;
++		ide_init_sg_cmd(drive, rq);
++		rc = do_rw_taskfile(drive, &task);
+ 	}
++
++	return rc;
+ }
+ 
+ /*
+@@ -307,57 +300,29 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
+  * Queries for true maximum capacity of the drive.
+  * Returns maximum LBA address (> 0) of the drive, 0 if failed.
+  */
+-static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
++static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
+ {
+ 	ide_task_t args;
+-	unsigned long addr = 0;
++	struct ide_taskfile *tf = &args.tf;
++	u64 addr = 0;
+ 
+ 	/* Create IDE/ATA command request structure */
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;
+-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
+-	args.handler				= &task_no_data_intr;
++	if (lba48)
++		tf->command = WIN_READ_NATIVE_MAX_EXT;
++	else
++		tf->command = WIN_READ_NATIVE_MAX;
++	tf->device  = ATA_LBA;
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	if (lba48)
++		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+ 	/* submit command request */
+-	ide_raw_taskfile(drive, &args, NULL);
++	ide_no_data_taskfile(drive, &args);
+ 
+ 	/* if OK, compute maximum address value */
+-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+-		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
+-		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
+-		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
+-		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
+-		addr++;	/* since the return value is (maxlba - 1), we add 1 */
+-	}
+-	return addr;
+-}
++	if ((tf->status & 0x01) == 0)
++		addr = ide_get_lba_addr(tf, lba48) + 1;
+ 
+-static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
+-{
+-	ide_task_t args;
+-	unsigned long long addr = 0;
+-
+-	/* Create IDE/ATA command request structure */
+-	memset(&args, 0, sizeof(ide_task_t));
+-
+-	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;
+-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
+-	args.handler				= &task_no_data_intr;
+-        /* submit command request */
+-        ide_raw_taskfile(drive, &args, NULL);
+-
+-	/* if OK, compute maximum address value */
+-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+-		u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
+-			   (args.hobRegister[IDE_LCYL_OFFSET] <<  8) |
+-			    args.hobRegister[IDE_SECTOR_OFFSET];
+-		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
+-			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
+-			    (args.tfRegister[IDE_SECTOR_OFFSET]);
+-		addr = ((__u64)high << 24) | low;
+-		addr++;	/* since the return value is (maxlba - 1), we add 1 */
+-	}
+ 	return addr;
+ }
+ 
+@@ -365,67 +330,37 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive
+  * Sets maximum virtual LBA address of the drive.
+  * Returns new maximum virtual LBA address (> 0) or 0 on failure.
+  */
+-static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
++static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
+ {
+ 	ide_task_t args;
+-	unsigned long addr_set = 0;
+-	
+-	addr_req--;
+-	/* Create IDE/ATA command request structure */
+-	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
+-	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);
+-	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);
+-	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;
+-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
+-	args.handler				= &task_no_data_intr;
+-	/* submit command request */
+-	ide_raw_taskfile(drive, &args, NULL);
+-	/* if OK, read new maximum address value */
+-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+-		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
+-			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
+-			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
+-			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
+-		addr_set++;
+-	}
+-	return addr_set;
+-}
+-
+-static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
+-{
+-	ide_task_t args;
+-	unsigned long long addr_set = 0;
++	struct ide_taskfile *tf = &args.tf;
++	u64 addr_set = 0;
+ 
+ 	addr_req--;
+ 	/* Create IDE/ATA command request structure */
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
+-	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
+-	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
+-	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;
+-	args.hobRegister[IDE_SECTOR_OFFSET]	= (addr_req >>= 8) & 0xff;
+-	args.hobRegister[IDE_LCYL_OFFSET]	= (addr_req >>= 8) & 0xff;
+-	args.hobRegister[IDE_HCYL_OFFSET]	= (addr_req >>= 8) & 0xff;
+-	args.hobRegister[IDE_SELECT_OFFSET]	= 0x40;
+-	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
+-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
+-	args.handler				= &task_no_data_intr;
++	tf->lbal     = (addr_req >>  0) & 0xff;
++	tf->lbam     = (addr_req >>= 8) & 0xff;
++	tf->lbah     = (addr_req >>= 8) & 0xff;
++	if (lba48) {
++		tf->hob_lbal = (addr_req >>= 8) & 0xff;
++		tf->hob_lbam = (addr_req >>= 8) & 0xff;
++		tf->hob_lbah = (addr_req >>= 8) & 0xff;
++		tf->command  = WIN_SET_MAX_EXT;
++	} else {
++		tf->device   = (addr_req >>= 8) & 0x0f;
++		tf->command  = WIN_SET_MAX;
++	}
++	tf->device |= ATA_LBA;
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	if (lba48)
++		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
+ 	/* submit command request */
+-	ide_raw_taskfile(drive, &args, NULL);
++	ide_no_data_taskfile(drive, &args);
+ 	/* if OK, compute maximum address value */
+-	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
+-		u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
+-			   (args.hobRegister[IDE_LCYL_OFFSET] <<  8) |
+-			    args.hobRegister[IDE_SECTOR_OFFSET];
+-		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
+-			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
+-			    (args.tfRegister[IDE_SECTOR_OFFSET]);
+-		addr_set = ((__u64)high << 24) | low;
+-		addr_set++;
+-	}
++	if ((tf->status & 0x01) == 0)
++		addr_set = ide_get_lba_addr(tf, lba48) + 1;
++
+ 	return addr_set;
+ }
+ 
+@@ -471,10 +406,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
+ 	int lba48 = idedisk_supports_lba48(drive->id);
+ 
+ 	capacity = drive->capacity64;
+-	if (lba48)
+-		set_max = idedisk_read_native_max_address_ext(drive);
+-	else
+-		set_max = idedisk_read_native_max_address(drive);
++
++	set_max = idedisk_read_native_max_address(drive, lba48);
+ 
+ 	if (ide_in_drive_list(drive->id, hpa_list)) {
+ 		/*
+@@ -495,10 +428,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
+ 			 capacity, sectors_to_MB(capacity),
+ 			 set_max, sectors_to_MB(set_max));
+ 
+-	if (lba48)
+-		set_max = idedisk_set_max_address_ext(drive, set_max);
+-	else
+-		set_max = idedisk_set_max_address(drive, set_max);
++	set_max = idedisk_set_max_address(drive, set_max, lba48);
++
+ 	if (set_max) {
+ 		drive->capacity64 = set_max;
+ 		printk(KERN_INFO "%s: Host Protected Area disabled.\n",
+@@ -556,32 +487,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive)
+ static int smart_enable(ide_drive_t *drive)
+ {
+ 	ide_task_t args;
++	struct ide_taskfile *tf = &args.tf;
+ 
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_FEATURE_OFFSET]	= SMART_ENABLE;
+-	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;
+-	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
+-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
+-	args.handler				= &task_no_data_intr;
+-	return ide_raw_taskfile(drive, &args, NULL);
++	tf->feature = SMART_ENABLE;
++	tf->lbam    = SMART_LCYL_PASS;
++	tf->lbah    = SMART_HCYL_PASS;
++	tf->command = WIN_SMART;
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	return ide_no_data_taskfile(drive, &args);
+ }
+ 
+ static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
+ {
+ 	ide_task_t args;
++	struct ide_taskfile *tf = &args.tf;
+ 
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_FEATURE_OFFSET]	= sub_cmd;
+-	args.tfRegister[IDE_NSECTOR_OFFSET]	= 0x01;
+-	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;
+-	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
+-	args.command_type			= IDE_DRIVE_TASK_IN;
+-	args.data_phase				= TASKFILE_IN;
+-	args.handler				= &task_in_intr;
++	tf->feature = sub_cmd;
++	tf->nsect   = 0x01;
++	tf->lbam    = SMART_LCYL_PASS;
++	tf->lbah    = SMART_HCYL_PASS;
++	tf->command = WIN_SMART;
++	args.tf_flags	= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	args.data_phase	= TASKFILE_IN;
+ 	(void) smart_enable(drive);
+-	return ide_raw_taskfile(drive, &args, buf);
++	return ide_raw_taskfile(drive, &args, buf, 1);
+ }
+ 
+ static int proc_idedisk_read_cache
+@@ -659,19 +590,20 @@ static ide_proc_entry_t idedisk_proc[] = {
+ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
+ {
+ 	ide_drive_t *drive = q->queuedata;
++	ide_task_t task;
+ 
+-	memset(rq->cmd, 0, sizeof(rq->cmd));
+-
++	memset(&task, 0, sizeof(task));
+ 	if (ide_id_has_flush_cache_ext(drive->id) &&
+ 	    (drive->capacity64 >= (1UL << 28)))
+-		rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
++		task.tf.command = WIN_FLUSH_CACHE_EXT;
+ 	else
+-		rq->cmd[0] = WIN_FLUSH_CACHE;
++		task.tf.command = WIN_FLUSH_CACHE;
++	task.tf_flags	= IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
++	task.data_phase	= TASKFILE_NO_DATA;
+ 
+-
+-	rq->cmd_type = REQ_TYPE_ATA_TASK;
++	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ 	rq->cmd_flags |= REQ_SOFTBARRIER;
+-	rq->buffer = rq->cmd;
++	rq->special = &task;
+ }
+ 
+ /*
+@@ -687,8 +619,10 @@ static int set_multcount(ide_drive_t *drive, int arg)
+ 
+ 	if (drive->special.b.set_multmode)
+ 		return -EBUSY;
++
+ 	ide_init_drive_cmd (&rq);
+-	rq.cmd_type = REQ_TYPE_ATA_CMD;
++	rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
++
+ 	drive->mult_req = arg;
+ 	drive->special.b.set_multmode = 1;
+ 	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
+@@ -753,12 +687,11 @@ static int write_cache(ide_drive_t *drive, int arg)
+ 
+ 	if (ide_id_has_flush_cache(drive->id)) {
+ 		memset(&args, 0, sizeof(ide_task_t));
+-		args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ?
++		args.tf.feature = arg ?
+ 			SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
+-		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
+-		args.command_type		= IDE_DRIVE_TASK_NO_DATA;
+-		args.handler			= &task_no_data_intr;
+-		err = ide_raw_taskfile(drive, &args, NULL);
++		args.tf.command = WIN_SETFEATURES;
++		args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++		err = ide_no_data_taskfile(drive, &args);
+ 		if (err == 0)
+ 			drive->wcache = arg;
+ 	}
+@@ -774,12 +707,11 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
+ 
+ 	memset(&args, 0, sizeof(ide_task_t));
+ 	if (ide_id_has_flush_cache_ext(drive->id))
+-		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_FLUSH_CACHE_EXT;
++		args.tf.command = WIN_FLUSH_CACHE_EXT;
+ 	else
+-		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_FLUSH_CACHE;
+-	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
+-	args.handler				= &task_no_data_intr;
+-	return ide_raw_taskfile(drive, &args, NULL);
++		args.tf.command = WIN_FLUSH_CACHE;
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	return ide_no_data_taskfile(drive, &args);
+ }
+ 
+ static int set_acoustic (ide_drive_t *drive, int arg)
+@@ -790,13 +722,11 @@ static int set_acoustic (ide_drive_t *drive, int arg)
+ 		return -EINVAL;
+ 
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ? SETFEATURES_EN_AAM :
+-							  SETFEATURES_DIS_AAM;
+-	args.tfRegister[IDE_NSECTOR_OFFSET]	= arg;
+-	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
+-	args.command_type = IDE_DRIVE_TASK_NO_DATA;
+-	args.handler	  = &task_no_data_intr;
+-	ide_raw_taskfile(drive, &args, NULL);
++	args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
++	args.tf.nsect   = arg;
++	args.tf.command = WIN_SETFEATURES;
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	ide_no_data_taskfile(drive, &args);
+ 	drive->acoustic = arg;
+ 	return 0;
+ }
+@@ -832,7 +762,6 @@ static void idedisk_add_settings(ide_drive_t *drive)
+ 	ide_add_setting(drive,	"bios_head",	SETTING_RW,	TYPE_BYTE,	0,	255,			1,	1,	&drive->bios_head,	NULL);
+ 	ide_add_setting(drive,	"bios_sect",	SETTING_RW,	TYPE_BYTE,	0,	63,			1,	1,	&drive->bios_sect,	NULL);
+ 	ide_add_setting(drive,	"address",	SETTING_RW,	TYPE_BYTE,	0,	2,			1,	1,	&drive->addressing,	set_lba_addressing);
+-	ide_add_setting(drive,	"bswap",	SETTING_READ,	TYPE_BYTE,	0,	1,			1,	1,	&drive->bswap,		NULL);
+ 	ide_add_setting(drive,	"multcount",	SETTING_RW,	TYPE_BYTE,	0,	id->max_multsect,	1,	1,	&drive->mult_count,	set_multcount);
+ 	ide_add_setting(drive,	"nowerr",	SETTING_RW,	TYPE_BYTE,	0,	1,			1,	1,	&drive->nowerr,		set_nowerr);
+ 	ide_add_setting(drive,	"lun",		SETTING_RW,	TYPE_INT,	0,	7,			1,	1,	&drive->lun,		NULL);
+@@ -1041,6 +970,17 @@ static ide_driver_t idedisk_driver = {
+ #endif
+ };
+ 
++static int idedisk_set_doorlock(ide_drive_t *drive, int on)
 +{
-+	struct input_dev *input;
-+
-+	input = field->hidinput->input;
-+
-+	if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
-+		|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
-+		if (value) hid->quirks |=  HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
-+		else       hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
-+		return;
-+	}
-+
-+	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
-+			(usage->type == EV_REL) &&
-+			(usage->code == REL_WHEEL)) {
-+		hid->delayed_value = value;
-+		return;
-+	}
-+
-+	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_B8) &&
-+			(usage->hid == 0x000100b8)) {
-+		input_event(input, EV_REL, value ? REL_HWHEEL : REL_WHEEL, hid->delayed_value);
-+		return;
-+	}
-+
-+	if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
-+		input_event(input, usage->type, usage->code, -value);
-+		return;
-+	}
-+
-+	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
-+		input_event(input, usage->type, REL_HWHEEL, value);
-+		return;
-+	}
-+
-+	if ((hid->quirks & HID_QUIRK_APPLE_HAS_FN) && hidinput_apple_event(hid, input, usage, value))
-+		return;
++	ide_task_t task;
 +
-+	/* Handling MS keyboards special buttons */
-+	if (hid->quirks & HID_QUIRK_MICROSOFT_KEYS && 
-+			usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
-+		int key = 0;
-+		static int last_key = 0;
-+		switch (value) {
-+			case 0x01: key = KEY_F14; break;
-+			case 0x02: key = KEY_F15; break;
-+			case 0x04: key = KEY_F16; break;
-+			case 0x08: key = KEY_F17; break;
-+			case 0x10: key = KEY_F18; break;
-+			default: break;
-+		}
-+		if (key) {
-+			input_event(input, usage->type, key, 1);
-+			last_key = key;
-+		} else {
-+			input_event(input, usage->type, last_key, 0);
-+		}
-+	}
++	memset(&task, 0, sizeof(task));
++	task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
++	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
 +
-+	/* handle the temporary quirky mapping to HWHEEL */
-+	if (hid->quirks & HID_QUIRK_HWHEEL_WHEEL_INVERT &&
-+			usage->type == EV_REL && usage->code == REL_HWHEEL) {
-+		input_event(input, usage->type, REL_WHEEL, -value);
-+		return;
-+	}
++	return ide_no_data_taskfile(drive, &task);
 +}
 +
-+
-diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
-index 0b27da7..5325d98 100644
---- a/drivers/hid/hid-input.c
-+++ b/drivers/hid/hid-input.c
-@@ -34,10 +34,10 @@
- #include <linux/hid.h>
- #include <linux/hid-debug.h>
+ static int idedisk_open(struct inode *inode, struct file *filp)
+ {
+ 	struct gendisk *disk = inode->i_bdev->bd_disk;
+@@ -1055,18 +995,13 @@ static int idedisk_open(struct inode *inode, struct file *filp)
+ 	idkp->openers++;
  
--static int hid_pb_fnmode = 1;
--module_param_named(pb_fnmode, hid_pb_fnmode, int, 0644);
-+static int hid_apple_fnmode = 1;
-+module_param_named(pb_fnmode, hid_apple_fnmode, int, 0644);
- MODULE_PARM_DESC(pb_fnmode,
--		"Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
-+		"Mode of fn key on Apple keyboards (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)");
+ 	if (drive->removable && idkp->openers == 1) {
+-		ide_task_t args;
+-		memset(&args, 0, sizeof(ide_task_t));
+-		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
+-		args.command_type = IDE_DRIVE_TASK_NO_DATA;
+-		args.handler	  = &task_no_data_intr;
+ 		check_disk_change(inode->i_bdev);
+ 		/*
+ 		 * Ignore the return code from door_lock,
+ 		 * since the open() has already succeeded,
+ 		 * and the door_lock is irrelevant at this point.
+ 		 */
+-		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
++		if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
+ 			drive->doorlocking = 0;
+ 	}
+ 	return 0;
+@@ -1082,12 +1017,7 @@ static int idedisk_release(struct inode *inode, struct file *filp)
+ 		ide_cacheflush_p(drive);
  
- #define unk	KEY_UNKNOWN
+ 	if (drive->removable && idkp->openers == 1) {
+-		ide_task_t args;
+-		memset(&args, 0, sizeof(ide_task_t));
+-		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
+-		args.command_type = IDE_DRIVE_TASK_NO_DATA;
+-		args.handler	  = &task_no_data_intr;
+-		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
++		if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
+ 			drive->doorlocking = 0;
+ 	}
  
-@@ -86,10 +86,6 @@ static const struct {
- #define map_abs_clear(c)	do { map_abs(c); clear_bit(c, bit); } while (0)
- #define map_key_clear(c)	do { map_key(c); clear_bit(c, bit); } while (0)
+diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
+index 4703837..a4bb328 100644
+--- a/drivers/ide/ide-dma.c
++++ b/drivers/ide/ide-dma.c
+@@ -1,15 +1,13 @@
+ /*
+- *  linux/drivers/ide/ide-dma.c		Version 4.10	June 9, 2000
++ *  Copyright (C) 1995-1998   Mark Lord
++ *  Copyright (C) 1999-2000   Andre Hedrick <andre at linux-ide.org>
++ *  Copyright (C) 2004, 2007  Bartlomiej Zolnierkiewicz
+  *
+- *  Copyright (c) 1999-2000	Andre Hedrick <andre at linux-ide.org>
+  *  May be copied or modified under the terms of the GNU General Public License
+  */
  
--/* hardware needing special handling due to colliding MSVENDOR page usages */
--#define IS_CHICONY_TACTICAL_PAD(x) (x->vendor == 0x04f2 && device->product == 0x0418)
--#define IS_MS_KB(x) (x->vendor == 0x045e && (x->product == 0x00db || x->product == 0x00f9))
--
- #ifdef CONFIG_USB_HIDINPUT_POWERBOOK
+ /*
+  *  Special Thanks to Mark for his Six years of work.
+- *
+- *  Copyright (c) 1995-1998  Mark Lord
+- *  May be copied or modified under the terms of the GNU General Public License
+  */
  
- struct hidinput_key_translation {
-@@ -98,20 +94,36 @@ struct hidinput_key_translation {
- 	u8 flags;
- };
+ /*
+@@ -85,6 +83,7 @@
+ #include <linux/ide.h>
+ #include <linux/delay.h>
+ #include <linux/scatterlist.h>
++#include <linux/dma-mapping.h>
  
--#define POWERBOOK_FLAG_FKEY 0x01
-+#define APPLE_FLAG_FKEY 0x01
-+
-+static struct hidinput_key_translation apple_fn_keys[] = {
-+	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
-+	{ KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
-+	{ KEY_F3,       KEY_CYCLEWINDOWS,       APPLE_FLAG_FKEY }, /* Exposé */
-+	{ KEY_F4,       KEY_FN_F4,              APPLE_FLAG_FKEY }, /* Dashboard */
-+	{ KEY_F5,       KEY_FN_F5 },
-+	{ KEY_F6,       KEY_FN_F6 },
-+	{ KEY_F7,       KEY_BACK,               APPLE_FLAG_FKEY },
-+	{ KEY_F8,       KEY_PLAYPAUSE,          APPLE_FLAG_FKEY },
-+	{ KEY_F9,       KEY_FORWARD,            APPLE_FLAG_FKEY },
-+	{ KEY_F10,      KEY_MUTE,               APPLE_FLAG_FKEY },
-+	{ KEY_F11,      KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
-+	{ KEY_F12,      KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
-+	{ }
-+};
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -148,18 +147,13 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
+ 	u8 stat = 0, dma_stat = 0;
  
- static struct hidinput_key_translation powerbook_fn_keys[] = {
- 	{ KEY_BACKSPACE, KEY_DELETE },
--	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     POWERBOOK_FLAG_FKEY },
--	{ KEY_F2,       KEY_BRIGHTNESSUP,       POWERBOOK_FLAG_FKEY },
--	{ KEY_F3,       KEY_MUTE,               POWERBOOK_FLAG_FKEY },
--	{ KEY_F4,       KEY_VOLUMEDOWN,         POWERBOOK_FLAG_FKEY },
--	{ KEY_F5,       KEY_VOLUMEUP,           POWERBOOK_FLAG_FKEY },
--	{ KEY_F6,       KEY_NUMLOCK,            POWERBOOK_FLAG_FKEY },
--	{ KEY_F7,       KEY_SWITCHVIDEOMODE,    POWERBOOK_FLAG_FKEY },
--	{ KEY_F8,       KEY_KBDILLUMTOGGLE,     POWERBOOK_FLAG_FKEY },
--	{ KEY_F9,       KEY_KBDILLUMDOWN,       POWERBOOK_FLAG_FKEY },
--	{ KEY_F10,      KEY_KBDILLUMUP,         POWERBOOK_FLAG_FKEY },
-+	{ KEY_F1,       KEY_BRIGHTNESSDOWN,     APPLE_FLAG_FKEY },
-+	{ KEY_F2,       KEY_BRIGHTNESSUP,       APPLE_FLAG_FKEY },
-+	{ KEY_F3,       KEY_MUTE,               APPLE_FLAG_FKEY },
-+	{ KEY_F4,       KEY_VOLUMEDOWN,         APPLE_FLAG_FKEY },
-+	{ KEY_F5,       KEY_VOLUMEUP,           APPLE_FLAG_FKEY },
-+	{ KEY_F6,       KEY_NUMLOCK,            APPLE_FLAG_FKEY },
-+	{ KEY_F7,       KEY_SWITCHVIDEOMODE,    APPLE_FLAG_FKEY },
-+	{ KEY_F8,       KEY_KBDILLUMTOGGLE,     APPLE_FLAG_FKEY },
-+	{ KEY_F9,       KEY_KBDILLUMDOWN,       APPLE_FLAG_FKEY },
-+	{ KEY_F10,      KEY_KBDILLUMUP,         APPLE_FLAG_FKEY },
- 	{ KEY_UP,       KEY_PAGEUP },
- 	{ KEY_DOWN,     KEY_PAGEDOWN },
- 	{ KEY_LEFT,     KEY_HOME },
-@@ -142,7 +154,7 @@ static struct hidinput_key_translation powerbook_numlock_keys[] = {
- 	{ }
- };
+ 	dma_stat = HWIF(drive)->ide_dma_end(drive);
+-	stat = HWIF(drive)->INB(IDE_STATUS_REG);	/* get drive status */
++	stat = ide_read_status(drive);
++
+ 	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+ 		if (!dma_stat) {
+ 			struct request *rq = HWGROUP(drive)->rq;
  
--static struct hidinput_key_translation powerbook_iso_keyboard[] = {
-+static struct hidinput_key_translation apple_iso_keyboard[] = {
- 	{ KEY_GRAVE,    KEY_102ND },
- 	{ KEY_102ND,    KEY_GRAVE },
- 	{ }
-@@ -160,39 +172,42 @@ static struct hidinput_key_translation *find_translation(struct hidinput_key_tra
- 	return NULL;
+-			if (rq->rq_disk) {
+-				ide_driver_t *drv;
+-
+-				drv = *(ide_driver_t **)rq->rq_disk->private_data;
+-				drv->end_request(drive, 1, rq->nr_sectors);
+-			} else
+-				ide_end_request(drive, 1, rq->nr_sectors);
++			task_end_request(drive, rq, stat);
+ 			return ide_stopped;
+ 		}
+ 		printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
+@@ -175,16 +169,15 @@ static int ide_dma_good_drive(ide_drive_t *drive)
+ 	return ide_in_drive_list(drive->id, drive_whitelist);
  }
  
--static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
-+int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
- 		struct hid_usage *usage, __s32 value)
- {
- 	struct hidinput_key_translation *trans;
- 
- 	if (usage->code == KEY_FN) {
--		if (value) hid->quirks |=  HID_QUIRK_POWERBOOK_FN_ON;
--		else       hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON;
-+		if (value) hid->quirks |=  HID_QUIRK_APPLE_FN_ON;
-+		else       hid->quirks &= ~HID_QUIRK_APPLE_FN_ON;
- 
- 		input_event(input, usage->type, usage->code, value);
+-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+ /**
+  *	ide_build_sglist	-	map IDE scatter gather for DMA I/O
+  *	@drive: the drive to build the DMA table for
+  *	@rq: the request holding the sg list
+  *
+- *	Perform the PCI mapping magic necessary to access the source or
+- *	target buffers of a request via PCI DMA. The lower layers of the
++ *	Perform the DMA mapping magic necessary to access the source or
++ *	target buffers of a request via DMA.  The lower layers of the
+  *	kernel provide the necessary cache management so that we can
+- *	operate in a portable fashion
++ *	operate in a portable fashion.
+  */
  
- 		return 1;
- 	}
+ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
+@@ -192,20 +185,20 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
+ 	ide_hwif_t *hwif = HWIF(drive);
+ 	struct scatterlist *sg = hwif->sg_table;
  
--	if (hid_pb_fnmode) {
-+	if (hid_apple_fnmode) {
- 		int do_translate;
+-	BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256);
+-
+ 	ide_map_sg(drive, rq);
  
--		trans = find_translation(powerbook_fn_keys, usage->code);
-+		trans = find_translation((hid->product < 0x220 ||
-+					  hid->product >= 0x300) ?
-+					 powerbook_fn_keys : apple_fn_keys,
-+					 usage->code);
- 		if (trans) {
--			if (test_bit(usage->code, hid->pb_pressed_fn))
-+			if (test_bit(usage->code, hid->apple_pressed_fn))
- 				do_translate = 1;
--			else if (trans->flags & POWERBOOK_FLAG_FKEY)
-+			else if (trans->flags & APPLE_FLAG_FKEY)
- 				do_translate =
--					(hid_pb_fnmode == 2 &&  (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) ||
--					(hid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON));
-+					(hid_apple_fnmode == 2 &&  (hid->quirks & HID_QUIRK_APPLE_FN_ON)) ||
-+					(hid_apple_fnmode == 1 && !(hid->quirks & HID_QUIRK_APPLE_FN_ON));
- 			else
--				do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON);
-+				do_translate = (hid->quirks & HID_QUIRK_APPLE_FN_ON);
+ 	if (rq_data_dir(rq) == READ)
+-		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
++		hwif->sg_dma_direction = DMA_FROM_DEVICE;
+ 	else
+-		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
++		hwif->sg_dma_direction = DMA_TO_DEVICE;
  
- 			if (do_translate) {
- 				if (value)
--					set_bit(usage->code, hid->pb_pressed_fn);
-+					set_bit(usage->code, hid->apple_pressed_fn);
- 				else
--					clear_bit(usage->code, hid->pb_pressed_fn);
-+					clear_bit(usage->code, hid->apple_pressed_fn);
+-	return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
++	return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
++			  hwif->sg_dma_direction);
+ }
  
- 				input_event(input, usage->type, trans->to, value);
+ EXPORT_SYMBOL_GPL(ide_build_sglist);
  
-@@ -217,8 +232,8 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- 		}
++#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+ /**
+  *	ide_build_dmatable	-	build IDE DMA table
+  *
+@@ -290,16 +283,17 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
+ 			*--table |= cpu_to_le32(0x80000000);
+ 		return count;
  	}
- 
--	if (hid->quirks & HID_QUIRK_POWERBOOK_ISO_KEYBOARD) {
--		trans = find_translation(powerbook_iso_keyboard, usage->code);
-+	if (hid->quirks & HID_QUIRK_APPLE_ISO_KEYBOARD) {
-+		trans = find_translation(apple_iso_keyboard, usage->code);
- 		if (trans) {
- 			input_event(input, usage->type, trans->to, value);
- 			return 1;
-@@ -228,31 +243,35 @@ static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
- 	return 0;
++
+ 	printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
++
+ use_pio_instead:
+-	pci_unmap_sg(hwif->pci_dev,
+-		     hwif->sg_table,
+-		     hwif->sg_nents,
+-		     hwif->sg_dma_direction);
++	ide_destroy_dmatable(drive);
++
+ 	return 0; /* revert to PIO for this request */
  }
  
--static void hidinput_pb_setup(struct input_dev *input)
-+static void hidinput_apple_setup(struct input_dev *input)
+ EXPORT_SYMBOL_GPL(ide_build_dmatable);
++#endif
+ 
+ /**
+  *	ide_destroy_dmatable	-	clean up DMA mapping
+@@ -314,15 +308,15 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
+  
+ void ide_destroy_dmatable (ide_drive_t *drive)
  {
- 	struct hidinput_key_translation *trans;
+-	struct pci_dev *dev = HWIF(drive)->pci_dev;
+-	struct scatterlist *sg = HWIF(drive)->sg_table;
+-	int nents = HWIF(drive)->sg_nents;
++	ide_hwif_t *hwif = drive->hwif;
  
- 	set_bit(KEY_NUMLOCK, input->keybit);
+-	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
++	dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
++		     hwif->sg_dma_direction);
+ }
  
- 	/* Enable all needed keys */
-+	for (trans = apple_fn_keys; trans->from; trans++)
-+		set_bit(trans->to, input->keybit);
-+
- 	for (trans = powerbook_fn_keys; trans->from; trans++)
- 		set_bit(trans->to, input->keybit);
+ EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
  
- 	for (trans = powerbook_numlock_keys; trans->from; trans++)
- 		set_bit(trans->to, input->keybit);
++#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+ /**
+  *	config_drive_for_dma	-	attempt to activate IDE DMA
+  *	@drive: the drive to place in DMA mode
+@@ -408,23 +402,29 @@ static int dma_timer_expiry (ide_drive_t *drive)
+ }
  
--	for (trans = powerbook_iso_keyboard; trans->from; trans++)
-+	for (trans = apple_iso_keyboard; trans->from; trans++)
- 		set_bit(trans->to, input->keybit);
+ /**
+- *	ide_dma_host_off	-	Generic DMA kill
++ *	ide_dma_host_set	-	Enable/disable DMA on a host
+  *	@drive: drive to control
+  *
+- *	Perform the generic IDE controller DMA off operation. This
+- *	works for most IDE bus mastering controllers
++ *	Enable/disable DMA on an IDE controller following generic
++ *	bus-mastering IDE controller behaviour.
+  */
  
- }
- #else
--static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input,
--		struct hid_usage *usage, __s32 value)
-+inline int hidinput_apple_event(struct hid_device *hid,
-+				       struct input_dev *input,
-+				       struct hid_usage *usage, __s32 value)
+-void ide_dma_host_off(ide_drive_t *drive)
++void ide_dma_host_set(ide_drive_t *drive, int on)
  {
- 	return 0;
- }
+ 	ide_hwif_t *hwif	= HWIF(drive);
+ 	u8 unit			= (drive->select.b.unit & 0x01);
+ 	u8 dma_stat		= hwif->INB(hwif->dma_status);
  
--static inline void hidinput_pb_setup(struct input_dev *input)
-+static inline void hidinput_apple_setup(struct input_dev *input)
- {
+-	hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status);
++	if (on)
++		dma_stat |= (1 << (5 + unit));
++	else
++		dma_stat &= ~(1 << (5 + unit));
++
++	hwif->OUTB(dma_stat, hwif->dma_status);
  }
- #endif
-@@ -343,7 +362,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- {
- 	struct input_dev *input = hidinput->input;
- 	struct hid_device *device = input_get_drvdata(input);
--	int max = 0, code;
-+	int max = 0, code, ret;
- 	unsigned long *bit = NULL;
  
- 	field->hidinput = hidinput;
-@@ -362,6 +381,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 		goto ignore;
- 	}
+-EXPORT_SYMBOL(ide_dma_host_off);
++EXPORT_SYMBOL_GPL(ide_dma_host_set);
++#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
  
-+	/* handle input mappings for quirky devices */
-+	ret = hidinput_mapping_quirks(usage, input, &bit, &max);
-+	if (ret)
-+		goto mapped;
-+
- 	switch (usage->hid & HID_USAGE_PAGE) {
+ /**
+  *	ide_dma_off_quietly	-	Generic DMA kill
+@@ -438,11 +438,10 @@ void ide_dma_off_quietly(ide_drive_t *drive)
+ 	drive->using_dma = 0;
+ 	ide_toggle_bounce(drive, 0);
  
- 		case HID_UP_UNDEFINED:
-@@ -549,14 +573,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 				case 0x000: goto ignore;
- 				case 0x034: map_key_clear(KEY_SLEEP);		break;
- 				case 0x036: map_key_clear(BTN_MISC);		break;
--				/*
--				 * The next three are reported by Belkin wireless
--				 * keyboard (1020:0006). These values are "reserved"
--				 * in HUT 1.12.
--				 */
--				case 0x03a: map_key_clear(KEY_SOUND);           break;
--				case 0x03b: map_key_clear(KEY_CAMERA);          break;
--				case 0x03c: map_key_clear(KEY_DOCUMENTS);       break;
+-	drive->hwif->dma_host_off(drive);
++	drive->hwif->dma_host_set(drive, 0);
+ }
  
- 				case 0x040: map_key_clear(KEY_MENU);		break;
- 				case 0x045: map_key_clear(KEY_RADIO);		break;
-@@ -602,10 +618,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 				case 0x0e9: map_key_clear(KEY_VOLUMEUP);	break;
- 				case 0x0ea: map_key_clear(KEY_VOLUMEDOWN);	break;
+ EXPORT_SYMBOL(ide_dma_off_quietly);
+-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
  
--				/* reserved in HUT 1.12. Reported on Petalynx remote */
--				case 0x0f6: map_key_clear(KEY_NEXT);		break;
--				case 0x0fa: map_key_clear(KEY_BACK);		break;
--
- 				case 0x182: map_key_clear(KEY_BOOKMARKS);	break;
- 				case 0x183: map_key_clear(KEY_CONFIG);		break;
- 				case 0x184: map_key_clear(KEY_WORDPROCESSOR);	break;
-@@ -665,51 +677,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 				case 0x28b: map_key_clear(KEY_FORWARDMAIL);	break;
- 				case 0x28c: map_key_clear(KEY_SEND);		break;
+ /**
+  *	ide_dma_off	-	disable DMA on a device
+@@ -455,56 +454,27 @@ EXPORT_SYMBOL(ide_dma_off_quietly);
+ void ide_dma_off(ide_drive_t *drive)
+ {
+ 	printk(KERN_INFO "%s: DMA disabled\n", drive->name);
+-	drive->hwif->dma_off_quietly(drive);
++	ide_dma_off_quietly(drive);
+ }
  
--				/* Reported on a Cherry Cymotion keyboard */
--				case 0x301: map_key_clear(KEY_PROG1);		break;
--				case 0x302: map_key_clear(KEY_PROG2);		break;
--				case 0x303: map_key_clear(KEY_PROG3);		break;
+ EXPORT_SYMBOL(ide_dma_off);
+ 
+-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+-/**
+- *	ide_dma_host_on	-	Enable DMA on a host
+- *	@drive: drive to enable for DMA
+- *
+- *	Enable DMA on an IDE controller following generic bus mastering
+- *	IDE controller behaviour
+- */
 -
--				/* Reported on certain Logitech wireless keyboards */
--				case 0x1001: map_key_clear(KEY_MESSENGER);	break;
--				case 0x1003: map_key_clear(KEY_SOUND);		break;
--				case 0x1004: map_key_clear(KEY_VIDEO);		break;
--				case 0x1005: map_key_clear(KEY_AUDIO);		break;
--				case 0x100a: map_key_clear(KEY_DOCUMENTS);	break;
--				case 0x1011: map_key_clear(KEY_PREVIOUSSONG);	break;
--				case 0x1012: map_key_clear(KEY_NEXTSONG);	break;
--				case 0x1013: map_key_clear(KEY_CAMERA);		break;
--				case 0x1014: map_key_clear(KEY_MESSENGER);	break;
--				case 0x1015: map_key_clear(KEY_RECORD);		break;
--				case 0x1016: map_key_clear(KEY_PLAYER);		break;
--				case 0x1017: map_key_clear(KEY_EJECTCD);	break;
--				case 0x1018: map_key_clear(KEY_MEDIA);          break;
--				case 0x1019: map_key_clear(KEY_PROG1);		break;
--				case 0x101a: map_key_clear(KEY_PROG2);		break;
--				case 0x101b: map_key_clear(KEY_PROG3);		break;
--				case 0x101f: map_key_clear(KEY_ZOOMIN);		break;
--				case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;
--				case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;
--				case 0x1023: map_key_clear(KEY_CLOSE);		break;
--				case 0x1027: map_key_clear(KEY_MENU);           break;
--				/* this one is marked as 'Rotate' */
--				case 0x1028: map_key_clear(KEY_ANGLE);		break;
--				case 0x1029: map_key_clear(KEY_SHUFFLE);	break;
--				case 0x102a: map_key_clear(KEY_BACK);           break;
--				case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);   break;
--				case 0x1041: map_key_clear(KEY_BATTERY);	break;
--				case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;
--				case 0x1043: map_key_clear(KEY_SPREADSHEET);	break;
--				case 0x1044: map_key_clear(KEY_PRESENTATION);	break;
--				case 0x1045: map_key_clear(KEY_UNDO);		break;
--				case 0x1046: map_key_clear(KEY_REDO);		break;
--				case 0x1047: map_key_clear(KEY_PRINT);		break;
--				case 0x1048: map_key_clear(KEY_SAVE);		break;
--				case 0x1049: map_key_clear(KEY_PROG1);		break;
--				case 0x104a: map_key_clear(KEY_PROG2);		break;
--				case 0x104b: map_key_clear(KEY_PROG3);		break;
--				case 0x104c: map_key_clear(KEY_PROG4);		break;
+-void ide_dma_host_on(ide_drive_t *drive)
+-{
+-	if (drive->using_dma) {
+-		ide_hwif_t *hwif	= HWIF(drive);
+-		u8 unit			= (drive->select.b.unit & 0x01);
+-		u8 dma_stat		= hwif->INB(hwif->dma_status);
 -
- 				default:    goto ignore;
- 			}
- 			break;
-@@ -736,63 +703,16 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
+-		hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);
+-	}
+-}
+-
+-EXPORT_SYMBOL(ide_dma_host_on);
+-
+ /**
+- *	__ide_dma_on		-	Enable DMA on a device
++ *	ide_dma_on		-	Enable DMA on a device
+  *	@drive: drive to enable DMA on
+  *
+  *	Enable IDE DMA for a device on this IDE controller.
+  */
+- 
+-int __ide_dma_on (ide_drive_t *drive)
+-{
+-	/* consult the list of known "bad" drives */
+-	if (__ide_dma_bad_drive(drive))
+-		return 1;
  
- 		case HID_UP_MSVENDOR:
++void ide_dma_on(ide_drive_t *drive)
++{
+ 	drive->using_dma = 1;
+ 	ide_toggle_bounce(drive, 1);
  
--			/* Unfortunately, there are multiple devices which
--			 * emit usages from MSVENDOR page that require different
--			 * handling. If this list grows too much in the future,
--			 * more general handling will have to be introduced here
--			 * (i.e. another blacklist).
--			 */
+-	drive->hwif->dma_host_on(drive);
 -
--			/* Chicony Chicony KU-0418 tactical pad */
--			if (IS_CHICONY_TACTICAL_PAD(device)) {
--				set_bit(EV_REP, input->evbit);
--				switch(usage->hid & HID_USAGE) {
--					case 0xff01: map_key_clear(BTN_1);		break;
--					case 0xff02: map_key_clear(BTN_2);		break;
--					case 0xff03: map_key_clear(BTN_3);		break;
--					case 0xff04: map_key_clear(BTN_4);		break;
--					case 0xff05: map_key_clear(BTN_5);		break;
--					case 0xff06: map_key_clear(BTN_6);		break;
--					case 0xff07: map_key_clear(BTN_7);		break;
--					case 0xff08: map_key_clear(BTN_8);		break;
--					case 0xff09: map_key_clear(BTN_9);		break;
--					case 0xff0a: map_key_clear(BTN_A);		break;
--					case 0xff0b: map_key_clear(BTN_B);		break;
--					default:    goto ignore;
--				}
+-	return 0;
++	drive->hwif->dma_host_set(drive, 1);
+ }
+ 
+-EXPORT_SYMBOL(__ide_dma_on);
 -
--			/* Microsoft Natural Ergonomic Keyboard 4000 */
--			} else if (IS_MS_KB(device)) {
--				switch(usage->hid & HID_USAGE) {
--					case 0xfd06:
--						map_key_clear(KEY_CHAT);
--						break;
--					case 0xfd07:
--						map_key_clear(KEY_PHONE);
--						break;
--					case 0xff05:
--						set_bit(EV_REP, input->evbit);
--						map_key_clear(KEY_F13);
--						set_bit(KEY_F14, input->keybit);
--						set_bit(KEY_F15, input->keybit);
--						set_bit(KEY_F16, input->keybit);
--						set_bit(KEY_F17, input->keybit);
--						set_bit(KEY_F18, input->keybit);
--					default:	goto ignore;
--				}
--			} else {
--				goto ignore;
--			}
--			break;
-+			goto ignore;
++#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+ /**
+  *	ide_dma_setup	-	begin a DMA phase
+  *	@drive: target device
+@@ -759,6 +729,7 @@ EXPORT_SYMBOL_GPL(ide_find_dma_mode);
  
--		case HID_UP_CUSTOM: /* Reported on Logitech and Powerbook USB keyboards */
-+		case HID_UP_CUSTOM: /* Reported on Logitech and Apple USB keyboards */
+ static int ide_tune_dma(ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
+ 	u8 speed;
  
- 			set_bit(EV_REP, input->evbit);
- 			switch(usage->hid & HID_USAGE) {
- 				case 0x003:
--					/* The fn key on Apple PowerBooks */
-+					/* The fn key on Apple USB keyboards */
- 					map_key_clear(KEY_FN);
--					hidinput_pb_setup(input);
-+					hidinput_apple_setup(input);
- 					break;
+ 	if (noautodma || drive->nodma || (drive->id->capability & 1) == 0)
+@@ -771,15 +742,21 @@ static int ide_tune_dma(ide_drive_t *drive)
+ 	if (ide_id_dma_bug(drive))
+ 		return 0;
  
- 				default:    goto ignore;
-@@ -800,38 +720,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 			break;
+-	if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
++	if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
+ 		return config_drive_for_dma(drive);
  
- 		case HID_UP_LOGIVENDOR:
--			set_bit(EV_REP, input->evbit);
--			switch(usage->hid & HID_USAGE) {
--				/* Reported on Logitech Ultra X Media Remote */
--				case 0x004: map_key_clear(KEY_AGAIN);		break;
--				case 0x00d: map_key_clear(KEY_HOME);		break;
--				case 0x024: map_key_clear(KEY_SHUFFLE);		break;
--				case 0x025: map_key_clear(KEY_TV);		break;
--				case 0x026: map_key_clear(KEY_MENU);		break;
--				case 0x031: map_key_clear(KEY_AUDIO);		break;
--				case 0x032: map_key_clear(KEY_TEXT);		break;
--				case 0x033: map_key_clear(KEY_LAST);		break;
--				case 0x047: map_key_clear(KEY_MP3);		break;
--				case 0x048: map_key_clear(KEY_DVD);		break;
--				case 0x049: map_key_clear(KEY_MEDIA);		break;
--				case 0x04a: map_key_clear(KEY_VIDEO);		break;
--				case 0x04b: map_key_clear(KEY_ANGLE);		break;
--				case 0x04c: map_key_clear(KEY_LANGUAGE);	break;
--				case 0x04d: map_key_clear(KEY_SUBTITLE);	break;
--				case 0x051: map_key_clear(KEY_RED);		break;
--				case 0x052: map_key_clear(KEY_CLOSE);		break;
--
--				/* Reported on Petalynx Maxter remote */
--				case 0x05a: map_key_clear(KEY_TEXT);		break;
--				case 0x05b: map_key_clear(KEY_RED);		break;
--				case 0x05c: map_key_clear(KEY_GREEN);		break;
--				case 0x05d: map_key_clear(KEY_YELLOW);		break;
--				case 0x05e: map_key_clear(KEY_BLUE);		break;
--
--				default:    goto ignore;
--			}
--			break;
+ 	speed = ide_max_dma_mode(drive);
  
-+			goto ignore;
-+		
- 		case HID_UP_PID:
+-	if (!speed)
+-		return 0;
++	if (!speed) {
++		 /* is this really correct/needed? */
++		if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
++		    ide_dma_good_drive(drive))
++			return 1;
++		else
++			return 0;
++	}
  
- 			switch(usage->hid & HID_USAGE) {
-@@ -858,6 +749,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 			break;
+-	if (drive->hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
++	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+ 		return 0;
+ 
+ 	if (ide_set_dma_mode(drive, speed))
+@@ -824,25 +801,43 @@ err_out:
+ 
+ int ide_set_dma(ide_drive_t *drive)
+ {
+-	ide_hwif_t *hwif = drive->hwif;
+ 	int rc;
+ 
++	/*
++	 * Force DMAing for the beginning of the check.
++	 * Some chipsets appear to do interesting
++	 * things, if not checked and cleared.
++	 *   PARANOIA!!!
++	 */
++	ide_dma_off_quietly(drive);
++
+ 	rc = ide_dma_check(drive);
++	if (rc)
++		return rc;
+ 
+-	switch(rc) {
+-	case -1: /* DMA needs to be disabled */
+-		hwif->dma_off_quietly(drive);
+-		return -1;
+-	case  0: /* DMA needs to be enabled */
+-		return hwif->ide_dma_on(drive);
+-	case  1: /* DMA setting cannot be changed */
+-		break;
+-	default:
+-		BUG();
+-		break;
+-	}
++	ide_dma_on(drive);
++
++	return 0;
++}
+ 
+-	return rc;
++void ide_check_dma_crc(ide_drive_t *drive)
++{
++	u8 mode;
++
++	ide_dma_off_quietly(drive);
++	drive->crc_count = 0;
++	mode = drive->current_speed;
++	/*
++	 * Don't try non Ultra-DMA modes without iCRC's.  Force the
++	 * device to PIO and make the user enable SWDMA/MWDMA modes.
++	 */
++	if (mode > XFER_UDMA_0 && mode <= XFER_UDMA_7)
++		mode--;
++	else
++		mode = XFER_PIO_4;
++	ide_set_xfer_rate(drive, mode);
++	if (drive->current_speed >= XFER_SW_DMA_0)
++		ide_dma_on(drive);
+ }
+ 
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+@@ -870,10 +865,10 @@ EXPORT_SYMBOL(ide_dma_timeout);
+ static void ide_release_dma_engine(ide_hwif_t *hwif)
+ {
+ 	if (hwif->dmatable_cpu) {
+-		pci_free_consistent(hwif->pci_dev,
+-				    PRD_ENTRIES * PRD_BYTES,
+-				    hwif->dmatable_cpu,
+-				    hwif->dmatable_dma);
++		struct pci_dev *pdev = to_pci_dev(hwif->dev);
++
++		pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
++				    hwif->dmatable_cpu, hwif->dmatable_dma);
+ 		hwif->dmatable_cpu = NULL;
  	}
+ }
+@@ -901,7 +896,9 @@ int ide_release_dma(ide_hwif_t *hwif)
  
-+mapped:
- 	if (device->quirks & HID_QUIRK_MIGHTYMOUSE) {
- 		if (usage->hid == HID_GD_Z)
- 			map_rel(REL_HWHEEL);
-@@ -867,9 +759,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
- 			map_key(BTN_1);
+ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
+ {
+-	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
++
++	hwif->dmatable_cpu = pci_alloc_consistent(pdev,
+ 						  PRD_ENTRIES * PRD_BYTES,
+ 						  &hwif->dmatable_dma);
+ 
+@@ -914,19 +911,19 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
+ 	return 1;
+ }
+ 
+-static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
++static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
+ {
+ 	printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
+ 
+ 	return 0;
+ }
+ 
+-static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
++static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
+ {
+ 	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
+-	       hwif->name, base, base + ports - 1);
++	       hwif->name, base, base + 7);
+ 
+-	if (!request_region(base, ports, hwif->name)) {
++	if (!request_region(base, 8, hwif->name)) {
+ 		printk(" -- Error, ports in use.\n");
+ 		return 1;
  	}
+@@ -938,7 +935,7 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
+ 			if (!request_region(hwif->extra_base,
+ 					    hwif->cds->extra, hwif->cds->name)) {
+ 				printk(" -- Error, extra ports in use.\n");
+-				release_region(base, ports);
++				release_region(base, 8);
+ 				return 1;
+ 			}
+ 			hwif->extra_ports = hwif->cds->extra;
+@@ -948,17 +945,19 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
+ 	return 0;
+ }
  
--	if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) &&
--		 (usage->type == EV_REL) && (usage->code == REL_WHEEL))
--			set_bit(REL_HWHEEL, bit);
-+	if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5 |
-+			HID_QUIRK_2WHEEL_MOUSE_HACK_B8)) && (usage->type == EV_REL) &&
-+			(usage->code == REL_WHEEL))
-+		set_bit(REL_HWHEEL, bit);
+-static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
++static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
+ {
+ 	if (hwif->mmio)
+-		return ide_mapped_mmio_dma(hwif, base,ports);
++		return ide_mapped_mmio_dma(hwif, base);
  
- 	if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
- 		|| ((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007)))
-@@ -960,25 +853,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
- 	if (!usage->type)
+-	return ide_iomio_dma(hwif, base, ports);
++	return ide_iomio_dma(hwif, base);
+ }
+ 
+-void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
++void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
+ {
+-	if (ide_dma_iobase(hwif, base, num_ports))
++	u8 dma_stat;
++
++	if (ide_dma_iobase(hwif, base))
  		return;
  
--	if (((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005))
--		|| ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_7) && (usage->hid == 0x00090007))) {
--		if (value) hid->quirks |=  HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
--		else       hid->quirks &= ~HID_QUIRK_2WHEEL_MOUSE_HACK_ON;
--		return;
--	}
--
--	if ((hid->quirks & HID_QUIRK_INVERT_HWHEEL) && (usage->code == REL_HWHEEL)) {
--		input_event(input, usage->type, usage->code, -value);
--		return;
--	}
+ 	if (ide_allocate_dma_engine(hwif)) {
+@@ -968,30 +967,19 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
+ 
+ 	hwif->dma_base = base;
+ 
+-	if (hwif->mate)
+-		hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
+-	else
+-		hwif->dma_master = base;
 -
--	if ((hid->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_ON) && (usage->code == REL_WHEEL)) {
--		input_event(input, usage->type, REL_HWHEEL, value);
--		return;
--	}
+-	if (!(hwif->dma_command))
+-		hwif->dma_command	= hwif->dma_base;
+-	if (!(hwif->dma_vendor1))
+-		hwif->dma_vendor1	= (hwif->dma_base + 1);
+-	if (!(hwif->dma_status))
+-		hwif->dma_status	= (hwif->dma_base + 2);
+-	if (!(hwif->dma_vendor3))
+-		hwif->dma_vendor3	= (hwif->dma_base + 3);
+-	if (!(hwif->dma_prdtable))
+-		hwif->dma_prdtable	= (hwif->dma_base + 4);
 -
--	if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value))
--		return;
-+	/* handle input events for quirky devices */
-+	hidinput_event_quirks(hid, field, usage, value);
- 
- 	if (usage->hat_min < usage->hat_max || usage->hat_dir) {
- 		int hat_dir = usage->hat_dir;
-@@ -1039,25 +915,6 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
- 		return;
- 	}
+-	if (!hwif->dma_off_quietly)
+-		hwif->dma_off_quietly = &ide_dma_off_quietly;
+-	if (!hwif->dma_host_off)
+-		hwif->dma_host_off = &ide_dma_host_off;
+-	if (!hwif->ide_dma_on)
+-		hwif->ide_dma_on = &__ide_dma_on;
+-	if (!hwif->dma_host_on)
+-		hwif->dma_host_on = &ide_dma_host_on;
++	if (!hwif->dma_command)
++		hwif->dma_command	= hwif->dma_base + 0;
++	if (!hwif->dma_vendor1)
++		hwif->dma_vendor1	= hwif->dma_base + 1;
++	if (!hwif->dma_status)
++		hwif->dma_status	= hwif->dma_base + 2;
++	if (!hwif->dma_vendor3)
++		hwif->dma_vendor3	= hwif->dma_base + 3;
++	if (!hwif->dma_prdtable)
++		hwif->dma_prdtable	= hwif->dma_base + 4;
++
++	if (!hwif->dma_host_set)
++		hwif->dma_host_set = &ide_dma_host_set;
+ 	if (!hwif->dma_setup)
+ 		hwif->dma_setup = &ide_dma_setup;
+ 	if (!hwif->dma_exec_cmd)
+@@ -1007,15 +995,10 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
+ 	if (!hwif->dma_lost_irq)
+ 		hwif->dma_lost_irq = &ide_dma_lost_irq;
  
--	/* Handling MS keyboards special buttons */
--	if (IS_MS_KB(hid) && usage->hid == (HID_UP_MSVENDOR | 0xff05)) {
--		int key = 0;
--		static int last_key = 0;
--		switch (value) {
--			case 0x01: key = KEY_F14; break;
--			case 0x02: key = KEY_F15; break;
--			case 0x04: key = KEY_F16; break;
--			case 0x08: key = KEY_F17; break;
--			case 0x10: key = KEY_F18; break;
--			default: break;
--		}
--		if (key) {
--			input_event(input, usage->type, key, 1);
--			last_key = key;
--		} else {
--			input_event(input, usage->type, last_key, 0);
--		}
+-	if (hwif->chipset != ide_trm290) {
+-		u8 dma_stat = hwif->INB(hwif->dma_status);
+-		printk(", BIOS settings: %s:%s, %s:%s",
+-		       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
+-		       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
 -	}
- 	/* report the usage code as scancode if the key status has changed */
- 	if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value)
- 		input_event(input, EV_MSC, MSC_SCAN, usage->hid);
-diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
-index c557d70..7160fa6 100644
---- a/drivers/hid/usbhid/Kconfig
-+++ b/drivers/hid/usbhid/Kconfig
-@@ -25,12 +25,13 @@ comment "Input core support is needed for USB HID input layer or HIDBP support"
- 	depends on USB_HID && INPUT=n
+-	printk("\n");
+-
+-	BUG_ON(!hwif->dma_master);
++	dma_stat = hwif->INB(hwif->dma_status);
++	printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
++	       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
++	       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
+ }
  
- config USB_HIDINPUT_POWERBOOK
--	bool "Enable support for iBook/PowerBook/MacBook/MacBookPro special keys"
-+	bool "Enable support for Apple laptop/aluminum USB special keys"
- 	default n
- 	depends on USB_HID
- 	help
- 	  Say Y here if you want support for the special keys (Fn, Numlock) on
--	  Apple iBooks, PowerBooks, MacBooks and MacBook Pros.
-+	  Apple iBooks, PowerBooks, MacBooks, MacBook Pros and aluminum USB
-+	  keyboards.
+ EXPORT_SYMBOL_GPL(ide_setup_dma);
+diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
+index 04a3578..faf22d7 100644
+--- a/drivers/ide/ide-floppy.c
++++ b/drivers/ide/ide-floppy.c
+@@ -1,15 +1,9 @@
+ /*
+- * linux/drivers/ide/ide-floppy.c	Version 0.99	Feb 24 2002
+- *
+- * Copyright (C) 1996 - 1999 Gadi Oxman <gadio at netvision.net.il>
+- * Copyright (C) 2000 - 2002 Paul Bristow <paul at paulbristow.net>
+- */
+-
+-/*
+  * IDE ATAPI floppy driver.
+  *
+- * The driver currently doesn't have any fancy features, just the bare
+- * minimum read/write support.
++ * Copyright (C) 1996-1999  Gadi Oxman <gadio at netvision.net.il>
++ * Copyright (C) 2000-2002  Paul Bristow <paul at paulbristow.net>
++ * Copyright (C) 2005       Bartlomiej Zolnierkiewicz
+  *
+  * This driver supports the following IDE floppy drives:
+  *
+@@ -17,70 +11,11 @@
+  * Iomega Zip 100/250
+  * Iomega PC Card Clik!/PocketZip
+  *
+- * Many thanks to Lode Leroy <Lode.Leroy at www.ibase.be>, who tested so many
+- * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
+- *
+- * Ver 0.1   Oct 17 96   Initial test version, mostly based on ide-tape.c.
+- * Ver 0.2   Oct 31 96   Minor changes.
+- * Ver 0.3   Dec  2 96   Fixed error recovery bug.
+- * Ver 0.4   Jan 26 97   Add support for the HDIO_GETGEO ioctl.
+- * Ver 0.5   Feb 21 97   Add partitions support.
+- *                       Use the minimum of the LBA and CHS capacities.
+- *                       Avoid hwgroup->rq == NULL on the last irq.
+- *                       Fix potential null dereferencing with DEBUG_LOG.
+- * Ver 0.8   Dec  7 97   Increase irq timeout from 10 to 50 seconds.
+- *                       Add media write-protect detection.
+- *                       Issue START command only if TEST UNIT READY fails.
+- *                       Add work-around for IOMEGA ZIP revision 21.D.
+- *                       Remove idefloppy_get_capabilities().
+- * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
+- *                        bytes requested on each interrupt to be zero.
+- *                        Thanks to <shanos at es.co.nz> for pointing this out.
+- * Ver 0.9.sv Jan 6 01   Sam Varshavchik <mrsam at courier-mta.com>
+- *                       Implement low level formatting.  Reimplemented
+- *                       IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
+- *                       bit.  My LS-120 drive barfs on
+- *                       IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
+- *                       Compromise by not reporting a failure to get this
+- *                       mode page.  Implemented four IOCTLs in order to
+- *                       implement formatting.  IOCTls begin with 0x4600,
+- *                       0x46 is 'F' as in Format.
+- *            Jan 9 01   Userland option to select format verify.
+- *                       Added PC_SUPPRESS_ERROR flag - some idefloppy drives
+- *                       do not implement IDEFLOPPY_CAPABILITIES_PAGE, and
+- *                       return a sense error.  Suppress error reporting in
+- *                       this particular case in order to avoid spurious
+- *                       errors in syslog.  The culprit is
+- *                       idefloppy_get_capability_page(), so move it to
+- *                       idefloppy_begin_format() so that it's not used
+- *                       unless absolutely necessary.
+- *                       If drive does not support format progress indication
+- *                       monitor the dsc bit in the status register.
+- *                       Also, O_NDELAY on open will allow the device to be
+- *                       opened without a disk available.  This can be used to
+- *                       open an unformatted disk, or get the device capacity.
+- * Ver 0.91  Dec 11 99   Added IOMEGA Clik! drive support by 
+- *     		   <paul at paulbristow.net>
+- * Ver 0.92  Oct 22 00   Paul Bristow became official maintainer for this 
+- *           		   driver.  Included Powerbook internal zip kludge.
+- * Ver 0.93  Oct 24 00   Fixed bugs for Clik! drive
+- *                        no disk on insert and disk change now works
+- * Ver 0.94  Oct 27 00   Tidied up to remove strstr(Clik) everywhere
+- * Ver 0.95  Nov  7 00   Brought across to kernel 2.4
+- * Ver 0.96  Jan  7 01   Actually in line with release version of 2.4.0
+- *                       including set_bit patch from Rusty Russell
+- * Ver 0.97  Jul 22 01   Merge 0.91-0.96 onto 0.9.sv for ac series
+- * Ver 0.97.sv Aug 3 01  Backported from 2.4.7-ac3
+- * Ver 0.98  Oct 26 01   Split idefloppy_transfer_pc into two pieces to
+- *                        fix a lost interrupt problem. It appears the busy
+- *                        bit was being deasserted by my IOMEGA ATAPI ZIP 100
+- *                        drive before the drive was actually ready.
+- * Ver 0.98a Oct 29 01   Expose delay value so we can play.
+- * Ver 0.99  Feb 24 02   Remove duplicate code, modify clik! detection code 
+- *                        to support new PocketZip drives 
++ * For a historical changelog see
++ * Documentation/ide/ChangeLog.ide-floppy.1996-2002
+  */
  
- 	  If unsure, say N.
+-#define IDEFLOPPY_VERSION "0.99.newide"
++#define IDEFLOPPY_VERSION "1.00"
  
-diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
-index a255285..b77b61e 100644
---- a/drivers/hid/usbhid/hid-quirks.c
-+++ b/drivers/hid/usbhid/hid-quirks.c
-@@ -19,6 +19,7 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -102,179 +37,91 @@
+ #include <scsi/scsi_ioctl.h>
  
- #define USB_VENDOR_ID_A4TECH		0x09da
- #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
-+#define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
+ #include <asm/byteorder.h>
+-#include <asm/irq.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
++#include <linux/irq.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+ #include <asm/unaligned.h>
  
- #define USB_VENDOR_ID_AASHIMA		0x06d6
- #define USB_DEVICE_ID_AASHIMA_GAMEPAD	0x0025
-@@ -28,6 +29,9 @@
- #define USB_DEVICE_ID_ACECAD_FLAIR	0x0004
- #define USB_DEVICE_ID_ACECAD_302	0x0008
+-/*
+- *	The following are used to debug the driver.
+- */
++/* define to see debug info */
+ #define IDEFLOPPY_DEBUG_LOG		0
+-#define IDEFLOPPY_DEBUG_INFO		0
+-#define IDEFLOPPY_DEBUG_BUGS		1
  
-+#define USB_VENDOR_ID_ADS_TECH 		0x06e1
-+#define USB_DEVICE_ID_ADS_TECH_RADIO_SI470X	0xa155
-+
- #define USB_VENDOR_ID_AIPTEK		0x08ca
- #define USB_DEVICE_ID_AIPTEK_01		0x0001
- #define USB_DEVICE_ID_AIPTEK_10		0x0010
-@@ -59,6 +63,9 @@
- #define USB_DEVICE_ID_APPLE_GEYSER4_ANSI	0x021a
- #define USB_DEVICE_ID_APPLE_GEYSER4_ISO	0x021b
- #define USB_DEVICE_ID_APPLE_GEYSER4_JIS	0x021c
-+#define USB_DEVICE_ID_APPLE_ALU_ANSI	0x0220
-+#define USB_DEVICE_ID_APPLE_ALU_ISO	0x0221
-+#define USB_DEVICE_ID_APPLE_ALU_JIS	0x0222
- #define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY	0x030a
- #define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY	0x030b
- #define USB_DEVICE_ID_APPLE_IRCONTROL4	0x8242
-@@ -94,6 +101,9 @@
- #define USB_DEVICE_ID_CODEMERCS_IOW_FIRST	0x1500
- #define USB_DEVICE_ID_CODEMERCS_IOW_LAST	0x15ff
+ /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
+-#define IDEFLOPPY_DEBUG( fmt, args... )
++#define IDEFLOPPY_DEBUG(fmt, args...)
  
-+#define USB_VENDOR_ID_CYGNAL		0x10c4
-+#define USB_DEVICE_ID_CYGNAL_RADIO_SI470X	0x818a
-+
- #define USB_VENDOR_ID_CYPRESS		0x04b4
- #define USB_DEVICE_ID_CYPRESS_MOUSE	0x0001
- #define USB_DEVICE_ID_CYPRESS_HIDCOM	0x5500
-@@ -114,6 +124,9 @@
- #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
- #define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
+ #if IDEFLOPPY_DEBUG_LOG
+-#define debug_log printk
++#define debug_log(fmt, args...) \
++	printk(KERN_INFO "ide-floppy: " fmt, ## args)
+ #else
+-#define debug_log(fmt, args... ) do {} while(0)
++#define debug_log(fmt, args...) do {} while (0)
+ #endif
  
-+#define USB_VENDOR_ID_EZKEY 		0x0518
-+#define USB_DEVICE_ID_BTC_8193		0x0002
-+
- #define USB_VENDOR_ID_GAMERON		0x0810
- #define USB_DEVICE_ID_GAMERON_DUAL_PSX_ADAPTOR	0x0001
  
-@@ -134,6 +147,9 @@
- #define USB_DEVICE_ID_GOGOPEN		0x00ce
- #define USB_DEVICE_ID_PENPOWER		0x00f4
+-/*
+- *	Some drives require a longer irq timeout.
+- */
++/* Some drives require a longer irq timeout. */
+ #define IDEFLOPPY_WAIT_CMD		(5 * WAIT_CMD)
  
-+#define USB_VENDOR_ID_GRETAGMACBETH	0x0971
-+#define USB_DEVICE_ID_GRETAGMACBETH_HUEY	0x2005
-+
- #define USB_VENDOR_ID_GRIFFIN		0x077d
- #define USB_DEVICE_ID_POWERMATE		0x0410
- #define USB_DEVICE_ID_SOUNDKNOB		0x04AA
-@@ -278,7 +294,9 @@
- #define USB_DEVICE_ID_LOGITECH_HARMONY_62 0xc14d
- #define USB_DEVICE_ID_LOGITECH_HARMONY_63 0xc14e
- #define USB_DEVICE_ID_LOGITECH_HARMONY_64 0xc14f
-+#define USB_DEVICE_ID_LOGITECH_EXTREME_3D	0xc215
- #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
-+#define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
- #define USB_DEVICE_ID_LOGITECH_KBD	0xc311
- #define USB_DEVICE_ID_S510_RECEIVER	0xc50c
- #define USB_DEVICE_ID_S510_RECEIVER_2	0xc517
-@@ -296,6 +314,12 @@
+ /*
+- *	After each failed packet command we issue a request sense command
+- *	and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times.
++ * After each failed packet command we issue a request sense command and retry
++ * the packet command IDEFLOPPY_MAX_PC_RETRIES times.
+  */
+ #define IDEFLOPPY_MAX_PC_RETRIES	3
  
- #define USB_VENDOR_ID_MICROSOFT		0x045e
- #define USB_DEVICE_ID_SIDEWINDER_GV	0x003b
-+#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
-+#define USB_DEVICE_ID_MS_NE4K		0x00db
-+#define USB_DEVICE_ID_MS_LK6K		0x00f9
-+
-+#define USB_VENDOR_ID_MONTEREY		0x0566
-+#define USB_DEVICE_ID_GENIUS_KB29E	0x3004
+ /*
+- *	With each packet command, we allocate a buffer of
+- *	IDEFLOPPY_PC_BUFFER_SIZE bytes.
++ * With each packet command, we allocate a buffer of IDEFLOPPY_PC_BUFFER_SIZE
++ * bytes.
+  */
+ #define IDEFLOPPY_PC_BUFFER_SIZE	256
  
- #define USB_VENDOR_ID_NCR		0x0404
- #define USB_DEVICE_ID_NCR_FIRST		0x0300
-@@ -324,6 +348,9 @@
- #define USB_VENDOR_ID_SAITEK		0x06a3
- #define USB_DEVICE_ID_SAITEK_RUMBLEPAD	0xff17
+ /*
+- *	In various places in the driver, we need to allocate storage
+- *	for packet commands and requests, which will remain valid while
+- *	we leave the driver to wait for an interrupt or a timeout event.
++ * In various places in the driver, we need to allocate storage for packet
++ * commands and requests, which will remain valid while	we leave the driver to
++ * wait for an interrupt or a timeout event.
+  */
+ #define IDEFLOPPY_PC_STACK		(10 + IDEFLOPPY_MAX_PC_RETRIES)
  
-+#define USB_VENDOR_ID_SAMSUNG		0x0419
-+#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
-+
- #define USB_VENDOR_ID_SONY			0x054c
- #define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
+-/*
+- *	Our view of a packet command.
+- */
+ typedef struct idefloppy_packet_command_s {
+ 	u8 c[12];				/* Actual packet bytes */
+-	int retries;				/* On each retry, we increment retries */
++	int retries;				/* On each retry, we increment
++						   retries */
+ 	int error;				/* Error code */
+ 	int request_transfer;			/* Bytes to transfer */
+ 	int actually_transferred;		/* Bytes actually transferred */
+ 	int buffer_size;			/* Size of our data buffer */
+-	int b_count;				/* Missing/Available data on the current buffer */
++	int b_count;				/* Missing/Available data on
++						   the current buffer */
+ 	struct request *rq;			/* The corresponding request */
+ 	u8 *buffer;				/* Data buffer */
+-	u8 *current_position;			/* Pointer into the above buffer */
+-	void (*callback) (ide_drive_t *);	/* Called when this packet command is completed */
++	u8 *current_position;			/* Pointer into above buffer */
++	void (*callback) (ide_drive_t *);	/* Called when this packet
++						   command is completed */
+ 	u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE];	/* Temporary buffer */
+-	unsigned long flags;			/* Status/Action bit flags: long for set_bit */
++	unsigned long flags;			/* Status/Action bit flags: long
++						   for set_bit */
+ } idefloppy_pc_t;
  
-@@ -368,6 +395,7 @@ static const struct hid_blacklist {
- } hid_blacklist[] = {
+-/*
+- *	Packet command flag bits.
+- */
+-#define	PC_ABORT			0	/* Set when an error is considered normal - We won't retry */
+-#define PC_DMA_RECOMMENDED		2	/* 1 when we prefer to use DMA if possible */
+-#define	PC_DMA_IN_PROGRESS		3	/* 1 while DMA in progress */
+-#define	PC_DMA_ERROR			4	/* 1 when encountered problem during DMA */
+-#define	PC_WRITING			5	/* Data direction */
+-
+-#define	PC_SUPPRESS_ERROR		6	/* Suppress error reporting */
+-
+-/*
+- *	Removable Block Access Capabilities Page
+- */
+-typedef struct {
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	page_code	:6;	/* Page code - Should be 0x1b */
+-	unsigned	reserved1_6	:1;	/* Reserved */
+-	unsigned	ps		:1;	/* Should be 0 */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	ps		:1;	/* Should be 0 */
+-	unsigned	reserved1_6	:1;	/* Reserved */
+-	unsigned	page_code	:6;	/* Page code - Should be 0x1b */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u8		page_length;		/* Page Length - Should be 0xa */
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	reserved2	:6;
+-	unsigned	srfp		:1;	/* Supports reporting progress of format */
+-	unsigned	sflp		:1;	/* System floppy type device */
+-	unsigned	tlun		:3;	/* Total logical units supported by the device */
+-	unsigned	reserved3	:3;
+-	unsigned	sml		:1;	/* Single / Multiple lun supported */
+-	unsigned	ncd		:1;	/* Non cd optical device */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	sflp		:1;	/* System floppy type device */
+-	unsigned	srfp		:1;	/* Supports reporting progress of format */
+-	unsigned	reserved2	:6;
+-	unsigned	ncd		:1;	/* Non cd optical device */
+-	unsigned	sml		:1;	/* Single / Multiple lun supported */
+-	unsigned	reserved3	:3;
+-	unsigned	tlun		:3;	/* Total logical units supported by the device */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u8		reserved[8];
+-} idefloppy_capabilities_page_t;
+-
+-/*
+- *	Flexible disk page.
+- */
+-typedef struct {
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	page_code	:6;	/* Page code - Should be 0x5 */
+-	unsigned	reserved1_6	:1;	/* Reserved */
+-	unsigned	ps		:1;	/* The device is capable of saving the page */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	ps		:1;	/* The device is capable of saving the page */
+-	unsigned	reserved1_6	:1;	/* Reserved */
+-	unsigned	page_code	:6;	/* Page code - Should be 0x5 */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u8		page_length;		/* Page Length - Should be 0x1e */
+-	u16		transfer_rate;		/* In kilobits per second */
+-	u8		heads, sectors;		/* Number of heads, Number of sectors per track */
+-	u16		sector_size;		/* Byes per sector */
+-	u16		cyls;			/* Number of cylinders */
+-	u8		reserved10[10];
+-	u8		motor_delay;		/* Motor off delay */
+-	u8		reserved21[7];
+-	u16		rpm;			/* Rotations per minute */
+-	u8		reserved30[2];
+-} idefloppy_flexible_disk_page_t;
+- 
+-/*
+- *	Format capacity
+- */
+-typedef struct {
+-	u8		reserved[3];
+-	u8		length;			/* Length of the following descriptors in bytes */
+-} idefloppy_capacity_header_t;
+-
+-typedef struct {
+-	u32		blocks;			/* Number of blocks */
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	dc		:2;	/* Descriptor Code */
+-	unsigned	reserved	:6;
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	reserved	:6;
+-	unsigned	dc		:2;	/* Descriptor Code */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u8		length_msb;		/* Block Length (MSB)*/
+-	u16		length;			/* Block Length */
+-} idefloppy_capacity_descriptor_t;
++/* Packet command flag bits. */
++enum {
++	/* 1 when we prefer to use DMA if possible */
++	PC_FLAG_DMA_RECOMMENDED	= (1 << 0),
++	/* 1 while DMA in progress */
++	PC_FLAG_DMA_IN_PROGRESS	= (1 << 1),
++	/* 1 when encountered problem during DMA */
++	PC_FLAG_DMA_ERROR	= (1 << 2),
++	/* Data direction */
++	PC_FLAG_WRITING		= (1 << 3),
++	/* Suppress error reporting */
++	PC_FLAG_SUPPRESS_ERROR	= (1 << 4),
++};
  
- 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
-+	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D, HID_QUIRK_2WHEEL_MOUSE_HACK_B8 },
- 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
++/* format capacities descriptor codes */
+ #define CAPACITY_INVALID	0x00
+ #define CAPACITY_UNFORMATTED	0x01
+ #define CAPACITY_CURRENT	0x02
+ #define CAPACITY_NO_CARTRIDGE	0x03
  
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RECEIVER, HID_QUIRK_BAD_RELATIVE_KEYS },
-@@ -390,6 +418,9 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4, HID_QUIRK_HIDDEV | HID_QUIRK_IGNORE_HIDINPUT },
- 	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV, HID_QUIRK_HIDINPUT },
+ /*
+- *	Most of our global data which we need to save even as we leave the
+- *	driver due to an interrupt or a timer event is stored in a variable
+- *	of type idefloppy_floppy_t, defined below.
++ * Most of our global data which we need to save even as we leave the driver
++ * due to an interrupt or a timer event is stored in a variable of type
++ * idefloppy_floppy_t, defined below.
+  */
+ typedef struct ide_floppy_obj {
+ 	ide_drive_t	*drive;
+@@ -295,23 +142,19 @@ typedef struct ide_floppy_obj {
+ 	/* We implement a circular array */
+ 	int rq_stack_index;
  
-+	{ USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193, HID_QUIRK_HWHEEL_WHEEL_INVERT },
-+
-+	{ USB_VENDOR_ID_ADS_TECH, USB_DEVICE_ID_ADS_TECH_RADIO_SI470X, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_01, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_10, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_AIPTEK, USB_DEVICE_ID_AIPTEK_20, HID_QUIRK_IGNORE },
-@@ -402,6 +433,7 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, HID_QUIRK_IGNORE},
- 	{ USB_VENDOR_ID_BERKSHIRE, USB_DEVICE_ID_BERKSHIRE_PCWD, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_CIDC, 0x0103, HID_QUIRK_IGNORE },
-+	{ USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_RADIO_SI470X, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_CMEDIA, USB_DEVICE_ID_CM109, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_ULTRAMOUSE, HID_QUIRK_IGNORE },
-@@ -423,6 +455,7 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER, HID_QUIRK_IGNORE },
-+	{ USB_VENDOR_ID_GRETAGMACBETH, USB_DEVICE_ID_GRETAGMACBETH_HUEY, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_90, HID_QUIRK_IGNORE },
-@@ -516,14 +549,18 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
- 	{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
+-	/*
+-	 *	Last error information
+-	 */
++	/* Last error information */
+ 	u8 sense_key, asc, ascq;
+ 	/* delay this long before sending packet command */
+ 	u8 ticks;
+ 	int progress_indication;
  
-+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
+-	/*
+-	 *	Device information
+-	 */
++	/* Device information */
+ 	/* Current format */
+ 	int blocks, block_size, bs_factor;
+-	/* Last format capacity */
+-	idefloppy_capacity_descriptor_t capacity;
++	/* Last format capacity descriptor */
++	u8 cap_desc[8];
+ 	/* Copy of the flexible disk page */
+-	idefloppy_flexible_disk_page_t flexible_disk_page;
++	u8 flexible_disk_page[32];
+ 	/* Write protect */
+ 	int wp;
+ 	/* Supports format progress report */
+@@ -322,85 +165,40 @@ typedef struct ide_floppy_obj {
  
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K, HID_QUIRK_MICROSOFT_KEYS },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K, HID_QUIRK_MICROSOFT_KEYS },
-+
- 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
+ #define IDEFLOPPY_TICKS_DELAY	HZ/20	/* default delay for ZIP 100 (50ms) */
  
- 	{ USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS },
- 	{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
+-/*
+- *	Floppy flag bits values.
+- */
+-#define IDEFLOPPY_DRQ_INTERRUPT		0	/* DRQ interrupt device */
+-#define IDEFLOPPY_MEDIA_CHANGED		1	/* Media may have changed */
+-#define IDEFLOPPY_USE_READ12		2	/* Use READ12/WRITE12 or READ10/WRITE10 */
+-#define	IDEFLOPPY_FORMAT_IN_PROGRESS	3	/* Format in progress */
+-#define IDEFLOPPY_CLIK_DRIVE	        4       /* Avoid commands not supported in Clik drive */
+-#define IDEFLOPPY_ZIP_DRIVE		5	/* Requires BH algorithm for packets */
+-
+-/*
+- *	ATAPI floppy drive packet commands
+- */
+-#define IDEFLOPPY_FORMAT_UNIT_CMD	0x04
+-#define IDEFLOPPY_INQUIRY_CMD		0x12
+-#define IDEFLOPPY_MODE_SELECT_CMD	0x55
+-#define IDEFLOPPY_MODE_SENSE_CMD	0x5a
+-#define IDEFLOPPY_READ10_CMD		0x28
+-#define IDEFLOPPY_READ12_CMD		0xa8
+-#define IDEFLOPPY_READ_CAPACITY_CMD	0x23
+-#define IDEFLOPPY_REQUEST_SENSE_CMD	0x03
+-#define IDEFLOPPY_PREVENT_REMOVAL_CMD	0x1e
+-#define IDEFLOPPY_SEEK_CMD		0x2b
+-#define IDEFLOPPY_START_STOP_CMD	0x1b
+-#define IDEFLOPPY_TEST_UNIT_READY_CMD	0x00
+-#define IDEFLOPPY_VERIFY_CMD		0x2f
+-#define IDEFLOPPY_WRITE10_CMD		0x2a
+-#define IDEFLOPPY_WRITE12_CMD		0xaa
+-#define IDEFLOPPY_WRITE_VERIFY_CMD	0x2e
++/* Floppy flag bits values. */
++enum {
++	/* DRQ interrupt device */
++	IDEFLOPPY_FLAG_DRQ_INTERRUPT		= (1 <<	0),
++	/* Media may have changed */
++	IDEFLOPPY_FLAG_MEDIA_CHANGED		= (1 << 1),
++	/* Format in progress */
++	IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS	= (1 << 2),
++	/* Avoid commands not supported in Clik drive */
++	IDEFLOPPY_FLAG_CLIK_DRIVE		= (1 << 3),
++	/* Requires BH algorithm for packets */
++	IDEFLOPPY_FLAG_ZIP_DRIVE		= (1 << 4),
++};
  
--	{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER },
-+	{ USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER, HID_QUIRK_SONY_PS3_CONTROLLER | HID_QUIRK_HIDDEV },
+-/*
+- *	Defines for the mode sense command
+- */
++/* Defines for the MODE SENSE command */
+ #define MODE_SENSE_CURRENT		0x00
+ #define MODE_SENSE_CHANGEABLE		0x01
+-#define MODE_SENSE_DEFAULT		0x02 
++#define MODE_SENSE_DEFAULT		0x02
+ #define MODE_SENSE_SAVED		0x03
  
- 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
-@@ -531,7 +568,9 @@ static const struct hid_blacklist {
- 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
-+	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_EXTREME_3D, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WHEEL, HID_QUIRK_NOGET },
-+	{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
- 	{ USB_VENDOR_ID_TURBOX, USB_DEVICE_ID_TURBOX_KEYBOARD, HID_QUIRK_NOGET },
-@@ -540,19 +579,22 @@ static const struct hid_blacklist {
+-/*
+- *	IOCTLs used in low-level formatting.
+- */
+-
++/* IOCTLs used in low-level formatting. */
+ #define	IDEFLOPPY_IOCTL_FORMAT_SUPPORTED	0x4600
+ #define	IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY	0x4601
+ #define	IDEFLOPPY_IOCTL_FORMAT_START		0x4602
+ #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS	0x4603
  
- 	{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+-#if 0
+-/*
+- *	Special requests for our block device strategy routine.
+- */
+-#define	IDEFLOPPY_FIRST_RQ	90
+-
+-/*
+- * 	IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue.
+- */
+-#define	IDEFLOPPY_PC_RQ		90
+-
+-#define IDEFLOPPY_LAST_RQ	90
+-
+-/*
+- *	A macro which can be used to check if a given request command
+- *	originated in the driver or in the buffer cache layer.
+- */
+-#define IDEFLOPPY_RQ_CMD(cmd) 	((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ))
+-
+-#endif
+-
+-/*
+- *	Error codes which are returned in rq->errors to the higher part
+- *	of the driver.
+- */
++/* Error code returned in rq->errors to the higher part of the driver. */
+ #define	IDEFLOPPY_ERROR_GENERAL		101
  
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
--	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
-+	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
+ /*
+- *	The following is used to format the general configuration word of
+- *	the ATAPI IDENTIFY DEVICE command.
++ * The following is used to format the general configuration word of the
++ * ATAPI IDENTIFY DEVICE command.
+  */
+-struct idefloppy_id_gcw {	
++struct idefloppy_id_gcw {
+ #if defined(__LITTLE_ENDIAN_BITFIELD)
+ 	unsigned packet_size		:2;	/* Packet Size */
+ 	unsigned reserved234		:3;	/* Reserved */
+@@ -423,103 +221,12 @@ struct idefloppy_id_gcw {
+ };
  
- 	{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
-@@ -638,10 +680,14 @@ static const struct hid_rdesc_blacklist {
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER, HID_QUIRK_RDESC_LOGITECH },
- 	{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2, HID_QUIRK_RDESC_LOGITECH },
+ /*
+- *	INQUIRY packet command - Data Format
+- */
+-typedef struct {
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	device_type	:5;	/* Peripheral Device Type */
+-	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */
+-	unsigned	reserved1_6t0	:7;	/* Reserved */
+-	unsigned	rmb		:1;	/* Removable Medium Bit */
+-	unsigned	ansi_version	:3;	/* ANSI Version */
+-	unsigned	ecma_version	:3;	/* ECMA Version */
+-	unsigned	iso_version	:2;	/* ISO Version */
+-	unsigned	response_format :4;	/* Response Data Format */
+-	unsigned	reserved3_45	:2;	/* Reserved */
+-	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */
+-	unsigned	reserved3_7	:1;	/* AENC - Reserved */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */
+-	unsigned	device_type	:5;	/* Peripheral Device Type */
+-	unsigned	rmb		:1;	/* Removable Medium Bit */
+-	unsigned	reserved1_6t0	:7;	/* Reserved */
+-	unsigned	iso_version	:2;	/* ISO Version */
+-	unsigned	ecma_version	:3;	/* ECMA Version */
+-	unsigned	ansi_version	:3;	/* ANSI Version */
+-	unsigned	reserved3_7	:1;	/* AENC - Reserved */
+-	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */
+-	unsigned	reserved3_45	:2;	/* Reserved */
+-	unsigned	response_format :4;	/* Response Data Format */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u8		additional_length;	/* Additional Length (total_length-4) */
+-	u8		rsv5, rsv6, rsv7;	/* Reserved */
+-	u8		vendor_id[8];		/* Vendor Identification */
+-	u8		product_id[16];		/* Product Identification */
+-	u8		revision_level[4];	/* Revision Level */
+-	u8		vendor_specific[20];	/* Vendor Specific - Optional */
+-	u8		reserved56t95[40];	/* Reserved - Optional */
+-						/* Additional information may be returned */
+-} idefloppy_inquiry_result_t;
+-
+-/*
+- *	REQUEST SENSE packet command result - Data Format.
+- */
+-typedef struct {
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	error_code	:7;	/* Current error (0x70) */
+-	unsigned	valid		:1;	/* The information field conforms to SFF-8070i */
+-	u8		reserved1	:8;	/* Reserved */
+-	unsigned	sense_key	:4;	/* Sense Key */
+-	unsigned	reserved2_4	:1;	/* Reserved */
+-	unsigned	ili		:1;	/* Incorrect Length Indicator */
+-	unsigned	reserved2_67	:2;
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	valid		:1;	/* The information field conforms to SFF-8070i */
+-	unsigned	error_code	:7;	/* Current error (0x70) */
+-	u8		reserved1	:8;	/* Reserved */
+-	unsigned	reserved2_67	:2;
+-	unsigned	ili		:1;	/* Incorrect Length Indicator */
+-	unsigned	reserved2_4	:1;	/* Reserved */
+-	unsigned	sense_key	:4;	/* Sense Key */
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u32		information __attribute__ ((packed));
+-	u8		asl;			/* Additional sense length (n-7) */
+-	u32		command_specific;	/* Additional command specific information */
+-	u8		asc;			/* Additional Sense Code */
+-	u8		ascq;			/* Additional Sense Code Qualifier */
+-	u8		replaceable_unit_code;	/* Field Replaceable Unit Code */
+-	u8		sksv[3];
+-	u8		pad[2];			/* Padding to 20 bytes */
+-} idefloppy_request_sense_result_t;
+-
+-/*
+- *	Pages of the SELECT SENSE / MODE SENSE packet commands.
++ * Pages of the SELECT SENSE / MODE SENSE packet commands.
++ * See SFF-8070i spec.
+  */
+ #define	IDEFLOPPY_CAPABILITIES_PAGE	0x1b
+ #define IDEFLOPPY_FLEXIBLE_DISK_PAGE	0x05
  
-+	{ USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E, HID_QUIRK_RDESC_BUTTON_CONSUMER },
-+
- 	{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_RDESC_MACBOOK_JIS },
+-/*
+- *	Mode Parameter Header for the MODE SENSE packet command
+- */
+-typedef struct {
+-	u16		mode_data_length;	/* Length of the following data transfer */
+-	u8		medium_type;		/* Medium Type */
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-	unsigned	reserved3	:7;
+-	unsigned	wp		:1;	/* Write protect */
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-	unsigned	wp		:1;	/* Write protect */
+-	unsigned	reserved3	:7;
+-#else
+-#error "Bitfield endianness not defined! Check your byteorder.h"
+-#endif
+-	u8		reserved[4];
+-} idefloppy_mode_parameter_header_t;
+-
+ static DEFINE_MUTEX(idefloppy_ref_mutex);
  
- 	{ USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE, HID_QUIRK_RDESC_PETALYNX },
+ #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
+@@ -539,39 +246,35 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
+ 	return floppy;
+ }
  
-+	{ USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE, HID_QUIRK_RDESC_SAMSUNG_REMOTE },
-+
- 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
- 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2, HID_QUIRK_RDESC_SWAPPED_MIN_MAX },
+-static void ide_floppy_release(struct kref *);
++static void idefloppy_cleanup_obj(struct kref *);
  
-@@ -884,6 +930,8 @@ u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct)
- 	return quirks;
+ static void ide_floppy_put(struct ide_floppy_obj *floppy)
+ {
+ 	mutex_lock(&idefloppy_ref_mutex);
+-	kref_put(&floppy->kref, ide_floppy_release);
++	kref_put(&floppy->kref, idefloppy_cleanup_obj);
+ 	mutex_unlock(&idefloppy_ref_mutex);
  }
  
-+EXPORT_SYMBOL_GPL(usbhid_lookup_quirk);
-+
  /*
-  * Cherry Cymotion keyboard have an invalid HID report descriptor,
-  * that needs fixing before we can parse it.
-@@ -914,6 +962,33 @@ static void usbhid_fixup_logitech_descriptor(unsigned char *rdesc, int rsize)
- 	}
+- *	Too bad. The drive wants to send us data which we are not ready to accept.
+- *	Just throw it away.
++ * Too bad. The drive wants to send us data which we are not ready to accept.
++ * Just throw it away.
+  */
+-static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount)
++static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount)
+ {
+ 	while (bcount--)
+ 		(void) HWIF(drive)->INB(IDE_DATA_REG);
  }
  
-+/*
-+ * Samsung IrDA remote controller (reports as Cypress USB Mouse).
-+ *
-+ * Vendor specific report #4 has a size of 48 bit,
-+ * and therefore is not accepted when inspecting the descriptors.
-+ * As a workaround we reinterpret the report as:
-+ *   Variable type, count 6, size 8 bit, log. maximum 255
-+ * The burden to reconstruct the data is moved into user space.
-+ */
-+static void usbhid_fixup_samsung_irda_descriptor(unsigned char *rdesc,
-+						  int rsize)
-+{
-+	if (rsize >= 182 && rdesc[175] == 0x25
-+			 && rdesc[176] == 0x40
-+			 && rdesc[177] == 0x75
-+			 && rdesc[178] == 0x30
-+			 && rdesc[179] == 0x95
-+			 && rdesc[180] == 0x01
-+			 && rdesc[182] == 0x40) {
-+		printk(KERN_INFO "Fixing up Samsung IrDA report descriptor\n");
-+		rdesc[176] = 0xff;
-+		rdesc[178] = 0x08;
-+		rdesc[180] = 0x06;
-+		rdesc[182] = 0x42;
-+	}
-+}
-+
- /* Petalynx Maxter Remote has maximum for consumer page set too low */
- static void usbhid_fixup_petalynx_descriptor(unsigned char *rdesc, int rsize)
+-#if IDEFLOPPY_DEBUG_BUGS
+-static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount)
++static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount)
  {
-@@ -965,6 +1040,14 @@ static void usbhid_fixup_macbook_descriptor(unsigned char *rdesc, int rsize)
- 	}
+ 	while (bcount--)
+ 		HWIF(drive)->OUTB(0, IDE_DATA_REG);
  }
+-#endif /* IDEFLOPPY_DEBUG_BUGS */
  
-+static void usbhid_fixup_button_consumer_descriptor(unsigned char *rdesc, int rsize)
-+{
-+	if (rsize >= 30 && rdesc[29] == 0x05
-+			&& rdesc[30] == 0x09) {
-+		printk(KERN_INFO "Fixing up button/consumer in HID report descriptor\n");
-+		rdesc[30] = 0x0c;
-+	}
-+}
  
- static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned rsize)
+ /*
+- *	idefloppy_do_end_request is used to finish servicing a request.
+- *
+- *	For read/write requests, we will call ide_end_request to pass to the
+- *	next buffer.
++ * Used to finish servicing a request. For read/write requests, we will call
++ * ide_end_request to pass to the next buffer.
+  */
+ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
  {
-@@ -982,6 +1065,13 @@ static void __usbhid_fixup_report_descriptor(__u32 quirks, char *rdesc, unsigned
+@@ -579,12 +282,12 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ 	struct request *rq = HWGROUP(drive)->rq;
+ 	int error;
  
- 	if (quirks & HID_QUIRK_RDESC_MACBOOK_JIS)
- 		usbhid_fixup_macbook_descriptor(rdesc, rsize);
-+
-+	if (quirks & HID_QUIRK_RDESC_BUTTON_CONSUMER)
-+		usbhid_fixup_button_consumer_descriptor(rdesc, rsize);
-+
-+	if (quirks & HID_QUIRK_RDESC_SAMSUNG_REMOTE)
-+		usbhid_fixup_samsung_irda_descriptor(rdesc, rsize);
-+
+-	debug_log(KERN_INFO "Reached idefloppy_end_request\n");
++	debug_log("Reached %s\n", __func__);
+ 
+ 	switch (uptodate) {
+-		case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
+-		case 1: error = 0; break;
+-		default: error = uptodate;
++	case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
++	case 1: error = 0; break;
++	default: error = uptodate;
+ 	}
+ 	if (error)
+ 		floppy->failed_pc = NULL;
+@@ -602,39 +305,8 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
+ 	return 0;
  }
  
- /**
-diff --git a/drivers/hid/usbhid/hid-tmff.c b/drivers/hid/usbhid/hid-tmff.c
-index 69882a7..144578b 100644
---- a/drivers/hid/usbhid/hid-tmff.c
-+++ b/drivers/hid/usbhid/hid-tmff.c
-@@ -137,7 +137,8 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
- int hid_tmff_init(struct hid_device *hid)
+-static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
+-{
+-	struct request *rq = pc->rq;
+-	struct bio_vec *bvec;
+-	struct req_iterator iter;
+-	unsigned long flags;
+-	char *data;
+-	int count, done = 0;
+-
+-	rq_for_each_segment(bvec, rq, iter) {
+-		if (!bcount)
+-			break;
+-
+-		count = min(bvec->bv_len, bcount);
+-
+-		data = bvec_kmap_irq(bvec, &flags);
+-		drive->hwif->atapi_input_bytes(drive, data, count);
+-		bvec_kunmap_irq(data, &flags);
+-
+-		bcount -= count;
+-		pc->b_count += count;
+-		done += count;
+-	}
+-
+-	idefloppy_do_end_request(drive, 1, done >> 9);
+-
+-	if (bcount) {
+-		printk(KERN_ERR "%s: leftover data in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);
+-		idefloppy_discard_data(drive, bcount);
+-	}
+-}
+-
+-static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
++static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
++				  unsigned int bcount, int direction)
  {
- 	struct tmff_device *tmff;
--	struct list_head *pos;
-+	struct hid_report *report;
-+	struct list_head *report_list;
- 	struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list);
- 	struct input_dev *input_dev = hidinput->input;
- 	const signed short *ff_bits = ff_joystick;
-@@ -149,8 +150,8 @@ int hid_tmff_init(struct hid_device *hid)
- 		return -ENOMEM;
- 
- 	/* Find the report to use */
--	list_for_each(pos, &hid->report_enum[HID_OUTPUT_REPORT].report_list) {
--		struct hid_report *report = (struct hid_report *)pos;
-+	report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list;
-+	list_for_each_entry(report, report_list, list) {
- 		int fieldnum;
+ 	struct request *rq = pc->rq;
+ 	struct req_iterator iter;
+@@ -650,7 +322,10 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
+ 		count = min(bvec->bv_len, bcount);
  
- 		for (fieldnum = 0; fieldnum < report->maxfield; ++fieldnum) {
-diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c
-index 775a1ef..5d9dbb4 100644
---- a/drivers/hid/usbhid/usbkbd.c
-+++ b/drivers/hid/usbhid/usbkbd.c
-@@ -235,6 +235,14 @@ static int usb_kbd_probe(struct usb_interface *iface,
- 	if (!usb_endpoint_is_int_in(endpoint))
- 		return -ENODEV;
+ 		data = bvec_kmap_irq(bvec, &flags);
+-		drive->hwif->atapi_output_bytes(drive, data, count);
++		if (direction)
++			drive->hwif->atapi_output_bytes(drive, data, count);
++		else
++			drive->hwif->atapi_input_bytes(drive, data, count);
+ 		bvec_kunmap_irq(data, &flags);
  
-+#ifdef CONFIG_USB_HID
-+	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
-+				le16_to_cpu(dev->descriptor.idProduct))
-+			& HID_QUIRK_IGNORE) {
-+		return -ENODEV;
-+	}
-+#endif
-+
- 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
+ 		bcount -= count;
+@@ -660,15 +335,18 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
  
-diff --git a/drivers/hid/usbhid/usbmouse.c b/drivers/hid/usbhid/usbmouse.c
-index f8ad691..df0d96d 100644
---- a/drivers/hid/usbhid/usbmouse.c
-+++ b/drivers/hid/usbhid/usbmouse.c
-@@ -131,6 +131,14 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
- 	if (!usb_endpoint_is_int_in(endpoint))
- 		return -ENODEV;
+ 	idefloppy_do_end_request(drive, 1, done >> 9);
  
-+#ifdef CONFIG_USB_HID
-+	if (usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
-+				le16_to_cpu(dev->descriptor.idProduct))
-+			& (HID_QUIRK_IGNORE|HID_QUIRK_IGNORE_MOUSE)) {
-+		return -ENODEV;
-+	}
-+#endif
+-#if IDEFLOPPY_DEBUG_BUGS
+ 	if (bcount) {
+-		printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
+-		idefloppy_write_zeros(drive, bcount);
++		printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
++				drive->name, __func__, bcount);
++		if (direction)
++			idefloppy_write_zeros(drive, bcount);
++		else
++			idefloppy_discard_data(drive, bcount);
 +
- 	pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
- 	maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
- 
-diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
-index a37cb6b..3581282 100644
---- a/drivers/i2c/algos/i2c-algo-bit.c
-+++ b/drivers/i2c/algos/i2c-algo-bit.c
-@@ -1,7 +1,7 @@
--/* ------------------------------------------------------------------------- */
--/* i2c-algo-bit.c i2c driver algorithms for bit-shift adapters		     */
--/* ------------------------------------------------------------------------- */
--/*   Copyright (C) 1995-2000 Simon G. Vogl
-+/* -------------------------------------------------------------------------
-+ * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters
-+ * -------------------------------------------------------------------------
-+ *   Copyright (C) 1995-2000 Simon G. Vogl
- 
-     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
-@@ -15,8 +15,8 @@
- 
-     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.		     */
--/* ------------------------------------------------------------------------- */
-+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ * ------------------------------------------------------------------------- */
+ 	}
+-#endif
+ }
  
- /* With some changes from Frodo Looijaard <frodol at dds.nl>, Kyösti Mälkki
-    <kmalkki at cc.hut.fi> and Jean Delvare <khali at linux-fr.org> */
-@@ -60,26 +60,26 @@ MODULE_PARM_DESC(i2c_debug,
+-static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
++static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
+ {
+ 	struct request *rq = pc->rq;
+ 	struct bio *bio = rq->bio;
+@@ -678,11 +356,12 @@ static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
+ }
  
- /* --- setting states on the bus with the right timing: ---------------	*/
+ /*
+- *	idefloppy_queue_pc_head generates a new packet command request in front
+- *	of the request queue, before the current request, so that it will be
+- *	processed immediately, on the next pass through the driver.
++ * Generate a new packet command request in front of the request queue, before
++ * the current request so that it will be processed immediately, on the next
++ * pass through the driver.
+  */
+-static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq)
++static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
++		struct request *rq)
+ {
+ 	struct ide_floppy_obj *floppy = drive->driver_data;
  
--#define setsda(adap,val) adap->setsda(adap->data, val)
--#define setscl(adap,val) adap->setscl(adap->data, val)
--#define getsda(adap) adap->getsda(adap->data)
--#define getscl(adap) adap->getscl(adap->data)
-+#define setsda(adap, val)	adap->setsda(adap->data, val)
-+#define setscl(adap, val)	adap->setscl(adap->data, val)
-+#define getsda(adap)		adap->getsda(adap->data)
-+#define getscl(adap)		adap->getscl(adap->data)
+@@ -693,16 +372,16 @@ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struc
+ 	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
+ }
  
- static inline void sdalo(struct i2c_algo_bit_data *adap)
+-static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive)
++static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive)
  {
--	setsda(adap,0);
-+	setsda(adap, 0);
- 	udelay((adap->udelay + 1) / 2);
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 
+ 	if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK)
+-		floppy->pc_stack_index=0;
++		floppy->pc_stack_index = 0;
+ 	return (&floppy->pc_stack[floppy->pc_stack_index++]);
  }
  
- static inline void sdahi(struct i2c_algo_bit_data *adap)
+-static struct request *idefloppy_next_rq_storage (ide_drive_t *drive)
++static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
  {
--	setsda(adap,1);
-+	setsda(adap, 1);
- 	udelay((adap->udelay + 1) / 2);
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 
+@@ -711,60 +390,53 @@ static struct request *idefloppy_next_rq_storage (ide_drive_t *drive)
+ 	return (&floppy->rq_stack[floppy->rq_stack_index++]);
  }
  
- static inline void scllo(struct i2c_algo_bit_data *adap)
+-/*
+- *	idefloppy_analyze_error is called on each failed packet command retry
+- *	to analyze the request sense.
+- */
+-static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result)
++static void idefloppy_request_sense_callback(ide_drive_t *drive)
  {
--	setscl(adap,0);
-+	setscl(adap, 0);
- 	udelay(adap->udelay / 2);
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
++	u8 *buf = floppy->pc->buffer;
+ 
+-	floppy->sense_key = result->sense_key;
+-	floppy->asc = result->asc;
+-	floppy->ascq = result->ascq;
+-	floppy->progress_indication = result->sksv[0] & 0x80 ?
+-		(u16)get_unaligned((u16 *)(result->sksv+1)):0x10000;
+-	if (floppy->failed_pc)
+-		debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, "
+-			"asc = %x, ascq = %x\n", floppy->failed_pc->c[0],
+-			result->sense_key, result->asc, result->ascq);
+-	else
+-		debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "
+-			"ascq = %x\n", result->sense_key,
+-			result->asc, result->ascq);
+-}
+-
+-static void idefloppy_request_sense_callback (ide_drive_t *drive)
+-{
+-	idefloppy_floppy_t *floppy = drive->driver_data;
++	debug_log("Reached %s\n", __func__);
+ 
+-	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
+-	
+ 	if (!floppy->pc->error) {
+-		idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);
++		floppy->sense_key = buf[2] & 0x0F;
++		floppy->asc = buf[12];
++		floppy->ascq = buf[13];
++		floppy->progress_indication = buf[15] & 0x80 ?
++			(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
++
++		if (floppy->failed_pc)
++			debug_log("pc = %x, sense key = %x, asc = %x,"
++					" ascq = %x\n",
++					floppy->failed_pc->c[0],
++					floppy->sense_key,
++					floppy->asc,
++					floppy->ascq);
++		else
++			debug_log("sense key = %x, asc = %x, ascq = %x\n",
++					floppy->sense_key,
++					floppy->asc,
++					floppy->ascq);
++
++
+ 		idefloppy_do_end_request(drive, 1, 0);
+ 	} else {
+-		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");
++		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
++				" request!\n");
+ 		idefloppy_do_end_request(drive, 0, 0);
+ 	}
  }
  
-@@ -91,22 +91,21 @@ static int sclhi(struct i2c_algo_bit_data *adap)
+-/*
+- *	General packet command callback function.
+- */
+-static void idefloppy_pc_callback (ide_drive_t *drive)
++/* General packet command callback function. */
++static void idefloppy_pc_callback(ide_drive_t *drive)
  {
- 	unsigned long start;
- 
--	setscl(adap,1);
-+	setscl(adap, 1);
- 
- 	/* Not all adapters have scl sense line... */
- 	if (!adap->getscl)
- 		goto done;
- 
--	start=jiffies;
--	while (! getscl(adap) ) {	
-- 		/* the hw knows how to read the clock line,
-- 		 * so we wait until it actually gets high.
-- 		 * This is safer as some chips may hold it low
-- 		 * while they are processing data internally. 
-- 		 */
--		if (time_after_eq(jiffies, start+adap->timeout)) {
-+	start = jiffies;
-+	while (!getscl(adap)) {
-+		/* This hw knows how to read the clock line, so we wait
-+		 * until it actually gets high.  This is safer as some
-+		 * chips may hold it low ("clock stretching") while they
-+		 * are processing data internally.
-+		 */
-+		if (time_after_eq(jiffies, start + adap->timeout))
- 			return -ETIMEDOUT;
--		}
- 		cond_resched();
- 	}
- #ifdef DEBUG
-@@ -118,11 +117,11 @@ static int sclhi(struct i2c_algo_bit_data *adap)
- done:
- 	udelay(adap->udelay);
- 	return 0;
--} 
-+}
- 
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	
+-	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
++
++	debug_log("Reached %s\n", __func__);
  
- /* --- other auxiliary functions --------------------------------------	*/
--static void i2c_start(struct i2c_algo_bit_data *adap) 
-+static void i2c_start(struct i2c_algo_bit_data *adap)
- {
- 	/* assert: scl, sda are high */
- 	setsda(adap, 0);
-@@ -130,7 +129,7 @@ static void i2c_start(struct i2c_algo_bit_data *adap)
- 	scllo(adap);
+ 	idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
  }
  
--static void i2c_repstart(struct i2c_algo_bit_data *adap) 
-+static void i2c_repstart(struct i2c_algo_bit_data *adap)
+-/*
+- *	idefloppy_init_pc initializes a packet command.
+- */
+-static void idefloppy_init_pc (idefloppy_pc_t *pc)
++static void idefloppy_init_pc(idefloppy_pc_t *pc)
  {
- 	/* assert: scl is low */
- 	sdahi(adap);
-@@ -141,18 +140,18 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
+ 	memset(pc->c, 0, 12);
+ 	pc->retries = 0;
+@@ -775,76 +447,75 @@ static void idefloppy_init_pc (idefloppy_pc_t *pc)
+ 	pc->callback = &idefloppy_pc_callback;
  }
  
- 
--static void i2c_stop(struct i2c_algo_bit_data *adap) 
-+static void i2c_stop(struct i2c_algo_bit_data *adap)
+-static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc)
++static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
  {
- 	/* assert: scl is low */
- 	sdalo(adap);
--	sclhi(adap); 
-+	sclhi(adap);
- 	setsda(adap, 1);
- 	udelay(adap->udelay);
+-	idefloppy_init_pc(pc);	
+-	pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD;
++	idefloppy_init_pc(pc);
++	pc->c[0] = GPCMD_REQUEST_SENSE;
+ 	pc->c[4] = 255;
+ 	pc->request_transfer = 18;
+ 	pc->callback = &idefloppy_request_sense_callback;
  }
  
+ /*
+- *	idefloppy_retry_pc is called when an error was detected during the
+- *	last packet command. We queue a request sense packet command in
+- *	the head of the request list.
++ * Called when an error was detected during the last packet command. We queue a
++ * request sense packet command in the head of the request list.
+  */
+-static void idefloppy_retry_pc (ide_drive_t *drive)
++static void idefloppy_retry_pc(ide_drive_t *drive)
+ {
+ 	idefloppy_pc_t *pc;
+ 	struct request *rq;
+-	atapi_error_t error;
  
- 
--/* send a byte without start cond., look for arbitration, 
-+/* send a byte without start cond., look for arbitration,
-    check ackn. from slave */
- /* returns:
-  * 1 if the device acknowledged
-@@ -167,27 +166,33 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
- 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
- 
- 	/* assert: scl is low */
--	for ( i=7 ; i>=0 ; i-- ) {
-+	for (i = 7; i >= 0; i--) {
- 		sb = (c >> i) & 1;
--		setsda(adap,sb);
-+		setsda(adap, sb);
- 		udelay((adap->udelay + 1) / 2);
--		if (sclhi(adap)<0) { /* timed out */
-+		if (sclhi(adap) < 0) { /* timed out */
- 			bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
- 				"timeout at bit #%d\n", (int)c, i);
- 			return -ETIMEDOUT;
--		};
--		/* do arbitration here: 
--		 * if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
-+		}
-+		/* FIXME do arbitration here:
-+		 * if (sb && !getsda(adap)) -> ouch! Get out of here.
-+		 *
-+		 * Report a unique code, so higher level code can retry
-+		 * the whole (combined) message and *NOT* issue STOP.
- 		 */
- 		scllo(adap);
- 	}
- 	sdahi(adap);
--	if (sclhi(adap)<0){ /* timeout */
-+	if (sclhi(adap) < 0) { /* timeout */
- 		bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
- 			"timeout at ack\n", (int)c);
- 		return -ETIMEDOUT;
--	};
--	/* read ack: SDA should be pulled down by slave */
-+	}
-+
-+	/* read ack: SDA should be pulled down by slave, or it may
-+	 * NAK (usually to report problems with the data we wrote).
-+	 */
- 	ack = !getsda(adap);    /* ack: sda is pulled low -> success */
- 	bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
- 		ack ? "A" : "NA");
-@@ -198,24 +203,24 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
+-	error.all = HWIF(drive)->INB(IDE_ERROR_REG);
++	(void)ide_read_error(drive);
+ 	pc = idefloppy_next_pc_storage(drive);
+ 	rq = idefloppy_next_rq_storage(drive);
+ 	idefloppy_create_request_sense_cmd(pc);
+ 	idefloppy_queue_pc_head(drive, pc, rq);
  }
  
- 
--static int i2c_inb(struct i2c_adapter *i2c_adap) 
-+static int i2c_inb(struct i2c_adapter *i2c_adap)
+-/*
+- *	idefloppy_pc_intr is the usual interrupt handler which will be called
+- *	during a packet command.
+- */
++/* The usual interrupt handler called during a packet command. */
+ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
  {
- 	/* read byte via i2c port, without start/stop sequence	*/
- 	/* acknowledge is sent in i2c_read.			*/
- 	int i;
--	unsigned char indata=0;
-+	unsigned char indata = 0;
- 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	atapi_status_t status;
+-	atapi_bcount_t bcount;
+-	atapi_ireason_t ireason;
++	ide_hwif_t *hwif = drive->hwif;
+ 	idefloppy_pc_t *pc = floppy->pc;
+ 	struct request *rq = pc->rq;
++	xfer_func_t *xferfunc;
+ 	unsigned int temp;
+-
+-	debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
+-		__FUNCTION__);
+-
+-	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
+-		if (HWIF(drive)->ide_dma_end(drive)) {
+-			set_bit(PC_DMA_ERROR, &pc->flags);
++	int dma_error = 0;
++	u16 bcount;
++	u8 stat, ireason;
++
++	debug_log("Reached %s interrupt handler\n", __func__);
++
++	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++		dma_error = hwif->ide_dma_end(drive);
++		if (dma_error) {
++			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
++					rq_data_dir(rq) ? "write" : "read");
++			pc->flags |= PC_FLAG_DMA_ERROR;
+ 		} else {
+ 			pc->actually_transferred = pc->request_transfer;
+ 			idefloppy_update_buffers(drive, pc);
+ 		}
+-		debug_log(KERN_INFO "ide-floppy: DMA finished\n");
++		debug_log("DMA finished\n");
+ 	}
  
- 	/* assert: scl is low */
- 	sdahi(adap);
--	for (i=0;i<8;i++) {
--		if (sclhi(adap)<0) { /* timeout */
-+	for (i = 0; i < 8; i++) {
-+		if (sclhi(adap) < 0) { /* timeout */
- 			bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
- 				"#%d\n", 7 - i);
- 			return -ETIMEDOUT;
--		};
-+		}
- 		indata *= 2;
--		if ( getsda(adap) ) 
-+		if (getsda(adap))
- 			indata |= 0x01;
- 		setscl(adap, 0);
- 		udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
-@@ -228,66 +233,67 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
-  * Sanity check for the adapter hardware - check the reaction of
-  * the bus lines only if it seems to be idle.
-  */
--static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
--	int scl,sda;
-+static int test_bus(struct i2c_algo_bit_data *adap, char *name)
-+{
-+	int scl, sda;
+ 	/* Clear the interrupt */
+-	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
++	stat = ide_read_status(drive);
  
--	if (adap->getscl==NULL)
-+	if (adap->getscl == NULL)
- 		pr_info("%s: Testing SDA only, SCL is not readable\n", name);
+-	if (!status.b.drq) {			/* No more interrupts */
+-		debug_log(KERN_INFO "Packet command completed, %d bytes "
+-			"transferred\n", pc->actually_transferred);
+-		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
++	/* No more interrupts */
++	if ((stat & DRQ_STAT) == 0) {
++		debug_log("Packet command completed, %d bytes transferred\n",
++				pc->actually_transferred);
++		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
  
--	sda=getsda(adap);
--	scl=(adap->getscl==NULL?1:getscl(adap));
--	if (!scl || !sda ) {
-+	sda = getsda(adap);
-+	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-+	if (!scl || !sda) {
- 		printk(KERN_WARNING "%s: bus seems to be busy\n", name);
- 		goto bailout;
- 	}
+ 		local_irq_enable_in_hardirq();
  
- 	sdalo(adap);
--	sda=getsda(adap);
--	scl=(adap->getscl==NULL?1:getscl(adap));
--	if ( 0 != sda ) {
-+	sda = getsda(adap);
-+	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-+	if (sda) {
- 		printk(KERN_WARNING "%s: SDA stuck high!\n", name);
- 		goto bailout;
+-		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {
++		if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
+ 			/* Error detected */
+-			debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",
+-				drive->name);
++			debug_log("%s: I/O error\n", drive->name);
+ 			rq->errors++;
+-			if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
++			if (pc->c[0] == GPCMD_REQUEST_SENSE) {
+ 				printk(KERN_ERR "ide-floppy: I/O error in "
+ 					"request sense command\n");
+ 				return ide_do_reset(drive);
+@@ -862,7 +533,8 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+ 		return ide_stopped;
  	}
--	if ( 0 == scl ) {
-+	if (!scl) {
- 		printk(KERN_WARNING "%s: SCL unexpected low "
- 		       "while pulling SDA low!\n", name);
- 		goto bailout;
--	}		
-+	}
  
- 	sdahi(adap);
--	sda=getsda(adap);
--	scl=(adap->getscl==NULL?1:getscl(adap));
--	if ( 0 == sda ) {
-+	sda = getsda(adap);
-+	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-+	if (!sda) {
- 		printk(KERN_WARNING "%s: SDA stuck low!\n", name);
- 		goto bailout;
- 	}
--	if ( 0 == scl ) {
-+	if (!scl) {
- 		printk(KERN_WARNING "%s: SCL unexpected low "
- 		       "while pulling SDA high!\n", name);
- 		goto bailout;
+-	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
++	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
++		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
+ 		printk(KERN_ERR "ide-floppy: The floppy wants to issue "
+ 			"more interrupts in DMA mode\n");
+ 		ide_dma_off(drive);
+@@ -870,67 +542,60 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
  	}
  
- 	scllo(adap);
--	sda=getsda(adap);
--	scl=(adap->getscl==NULL?0:getscl(adap));
--	if ( 0 != scl ) {
-+	sda = getsda(adap);
-+	scl = (adap->getscl == NULL) ? 0 : getscl(adap);
-+	if (scl) {
- 		printk(KERN_WARNING "%s: SCL stuck high!\n", name);
- 		goto bailout;
+ 	/* Get the number of bytes to transfer */
+-	bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
+-	bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
++	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
++		  hwif->INB(IDE_BCOUNTL_REG);
+ 	/* on this interrupt */
+-	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(IDE_IREASON_REG);
+ 
+-	if (ireason.b.cod) {
+-		printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
++	if (ireason & CD) {
++		printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
+ 		return ide_do_reset(drive);
  	}
--	if ( 0 == sda ) {
-+	if (!sda) {
- 		printk(KERN_WARNING "%s: SDA unexpected low "
- 		       "while pulling SCL low!\n", name);
- 		goto bailout;
+-	if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
++	if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
+ 		/* Hopefully, we will never get here */
+ 		printk(KERN_ERR "ide-floppy: We wanted to %s, ",
+-			ireason.b.io ? "Write":"Read");
++				(ireason & IO) ? "Write" : "Read");
+ 		printk(KERN_ERR "but the floppy wants us to %s !\n",
+-			ireason.b.io ? "Read":"Write");
++				(ireason & IO) ? "Read" : "Write");
+ 		return ide_do_reset(drive);
  	}
--	
+-	if (!test_bit(PC_WRITING, &pc->flags)) {
++	if (!(pc->flags & PC_FLAG_WRITING)) {
+ 		/* Reading - Check that we have enough space */
+-		temp = pc->actually_transferred + bcount.all;
++		temp = pc->actually_transferred + bcount;
+ 		if (temp > pc->request_transfer) {
+ 			if (temp > pc->buffer_size) {
+ 				printk(KERN_ERR "ide-floppy: The floppy wants "
+ 					"to send us more data than expected "
+ 					"- discarding data\n");
+-				idefloppy_discard_data(drive,bcount.all);
+-				BUG_ON(HWGROUP(drive)->handler != NULL);
++				idefloppy_discard_data(drive, bcount);
 +
- 	sclhi(adap);
--	sda=getsda(adap);
--	scl=(adap->getscl==NULL?1:getscl(adap));
--	if ( 0 == scl ) {
-+	sda = getsda(adap);
-+	scl = (adap->getscl == NULL) ? 1 : getscl(adap);
-+	if (!scl) {
- 		printk(KERN_WARNING "%s: SCL stuck low!\n", name);
- 		goto bailout;
+ 				ide_set_handler(drive,
+ 						&idefloppy_pc_intr,
+ 						IDEFLOPPY_WAIT_CMD,
+ 						NULL);
+ 				return ide_started;
+ 			}
+-			debug_log(KERN_NOTICE "ide-floppy: The floppy wants to "
+-				"send us more data than expected - "
+-				"allowing transfer\n");
++			debug_log("The floppy wants to send us more data than"
++					" expected - allowing transfer\n");
+ 		}
  	}
--	if ( 0 == sda ) {
-+	if (!sda) {
- 		printk(KERN_WARNING "%s: SDA unexpected low "
- 		       "while pulling SCL high!\n", name);
- 		goto bailout;
-@@ -314,9 +320,10 @@ static int try_address(struct i2c_adapter *i2c_adap,
- 		       unsigned char addr, int retries)
- {
- 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
--	int i,ret = -1;
--	for (i=0;i<=retries;i++) {
--		ret = i2c_outb(i2c_adap,addr);
-+	int i, ret = -1;
-+
-+	for (i = 0; i <= retries; i++) {
-+		ret = i2c_outb(i2c_adap, addr);
- 		if (ret == 1 || i == retries)
- 			break;
- 		bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
-@@ -338,20 +345,38 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
- {
- 	const unsigned char *temp = msg->buf;
- 	int count = msg->len;
--	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; 
-+	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
- 	int retval;
--	int wrcount=0;
-+	int wrcount = 0;
- 
- 	while (count > 0) {
- 		retval = i2c_outb(i2c_adap, *temp);
--		if ((retval>0) || (nak_ok && (retval==0)))  { /* ok or ignored NAK */
--			count--; 
-+
-+		/* OK/ACK; or ignored NAK */
-+		if ((retval > 0) || (nak_ok && (retval == 0))) {
-+			count--;
- 			temp++;
- 			wrcount++;
--		} else { /* arbitration or no acknowledge */
--			dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
--			return (retval<0)? retval : -EFAULT;
--			        /* got a better one ?? */
+-	if (test_bit(PC_WRITING, &pc->flags)) {
+-		if (pc->buffer != NULL)
+-			/* Write the current buffer */
+-			HWIF(drive)->atapi_output_bytes(drive,
+-						pc->current_position,
+-						bcount.all);
+-		else
+-			idefloppy_output_buffers(drive, pc, bcount.all);
+-	} else {
+-		if (pc->buffer != NULL)
+-			/* Read the current buffer */
+-			HWIF(drive)->atapi_input_bytes(drive,
+-						pc->current_position,
+-						bcount.all);
+-		else
+-			idefloppy_input_buffers(drive, pc, bcount.all);
+-	}
++	if (pc->flags & PC_FLAG_WRITING)
++		xferfunc = hwif->atapi_output_bytes;
++	else
++		xferfunc = hwif->atapi_input_bytes;
 +
-+		/* A slave NAKing the master means the slave didn't like
-+		 * something about the data it saw.  For example, maybe
-+		 * the SMBus PEC was wrong.
-+		 */
-+		} else if (retval == 0) {
-+			dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n");
-+			return -EIO;
++	if (pc->buffer)
++		xferfunc(drive, pc->current_position, bcount);
++	else
++		ide_floppy_io_buffers(drive, pc, bcount,
++				      !!(pc->flags & PC_FLAG_WRITING));
 +
-+		/* Timeout; or (someday) lost arbitration
-+		 *
-+		 * FIXME Lost ARB implies retrying the transaction from
-+		 * the first message, after the "winning" master issues
-+		 * its STOP.  As a rule, upper layer code has no reason
-+		 * to know or care about this ... it is *NOT* an error.
-+		 */
-+		} else {
-+			dev_err(&i2c_adap->dev, "sendbytes: error %d\n",
-+					retval);
-+			return retval;
- 		}
- 	}
- 	return wrcount;
-@@ -376,14 +401,14 @@ static int acknak(struct i2c_adapter *i2c_adap, int is_ack)
- static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
- {
- 	int inval;
--	int rdcount=0;   	/* counts bytes read */
-+	int rdcount = 0;	/* counts bytes read */
- 	unsigned char *temp = msg->buf;
- 	int count = msg->len;
- 	const unsigned flags = msg->flags;
+ 	/* Update the current position */
+-	pc->actually_transferred += bcount.all;
+-	pc->current_position += bcount.all;
++	pc->actually_transferred += bcount;
++	pc->current_position += bcount;
  
- 	while (count > 0) {
- 		inval = i2c_inb(i2c_adap);
--		if (inval>=0) {
-+		if (inval >= 0) {
- 			*temp = inval;
- 			rdcount++;
- 		} else {   /* read timed out */
-@@ -431,7 +456,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
-  * returns:
-  *  0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set
-  * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
-- *	-ETIMEDOUT, for example if the lines are stuck...) 
-+ *	-ETIMEDOUT, for example if the lines are stuck...)
+-	BUG_ON(HWGROUP(drive)->handler != NULL);
+-	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
++	/* And set the interrupt handler again */
++	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
+ 	return ide_started;
+ }
+ 
+@@ -939,24 +604,24 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
+  * It fails at high speeds on the Iomega ZIP drive, so there's a slower version
+  * for that drive below. The algorithm is chosen based on drive type
   */
- static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+-static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
++static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
  {
-@@ -443,10 +468,10 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
- 	int ret, retries;
+ 	ide_startstop_t startstop;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	atapi_ireason_t ireason;
++	u8 ireason;
  
- 	retries = nak_ok ? 0 : i2c_adap->retries;
--	
--	if ( (flags & I2C_M_TEN)  ) { 
-+
-+	if (flags & I2C_M_TEN) {
- 		/* a ten bit address */
--		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
-+		addr = 0xf0 | ((msg->addr >> 7) & 0x03);
- 		bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
- 		/* try extended address code...*/
- 		ret = try_address(i2c_adap, addr, retries);
-@@ -456,33 +481,33 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
- 			return -EREMOTEIO;
- 		}
- 		/* the remaining 8 bit address */
--		ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
-+		ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
- 		if ((ret != 1) && !nak_ok) {
- 			/* the chip did not ack / xmission error occurred */
- 			dev_err(&i2c_adap->dev, "died at 2nd address code\n");
- 			return -EREMOTEIO;
- 		}
--		if ( flags & I2C_M_RD ) {
-+		if (flags & I2C_M_RD) {
- 			bit_dbg(3, &i2c_adap->dev, "emitting repeated "
- 				"start condition\n");
- 			i2c_repstart(adap);
- 			/* okay, now switch into reading mode */
- 			addr |= 0x01;
- 			ret = try_address(i2c_adap, addr, retries);
--			if ((ret!=1) && !nak_ok) {
-+			if ((ret != 1) && !nak_ok) {
- 				dev_err(&i2c_adap->dev,
- 					"died at repeated address code\n");
- 				return -EREMOTEIO;
- 			}
- 		}
- 	} else {		/* normal 7bit address	*/
--		addr = ( msg->addr << 1 );
--		if (flags & I2C_M_RD )
-+		addr = msg->addr << 1;
-+		if (flags & I2C_M_RD)
- 			addr |= 1;
--		if (flags & I2C_M_REV_DIR_ADDR )
-+		if (flags & I2C_M_REV_DIR_ADDR)
- 			addr ^= 1;
- 		ret = try_address(i2c_adap, addr, retries);
--		if ((ret!=1) && !nak_ok)
-+		if ((ret != 1) && !nak_ok)
- 			return -EREMOTEIO;
+ 	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
+ 		printk(KERN_ERR "ide-floppy: Strange, packet command "
+ 				"initiated yet DRQ isn't asserted\n");
+ 		return startstop;
  	}
+-	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
+-	if (!ireason.b.cod || ireason.b.io) {
++	ireason = drive->hwif->INB(IDE_IREASON_REG);
++	if ((ireason & CD) == 0 || (ireason & IO)) {
+ 		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
+ 				"issuing a packet command\n");
+ 		return ide_do_reset(drive);
+ 	}
+-	BUG_ON(HWGROUP(drive)->handler != NULL);
++
+ 	/* Set the interrupt routine */
+ 	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
+ 	/* Send the actual packet */
+@@ -966,18 +631,16 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
  
-@@ -494,15 +519,14 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
- {
- 	struct i2c_msg *pmsg;
- 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
--	
--	int i,ret;
-+	int i, ret;
- 	unsigned short nak_ok;
- 
- 	bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
- 	i2c_start(adap);
--	for (i=0;i<num;i++) {
-+	for (i = 0; i < num; i++) {
- 		pmsg = &msgs[i];
--		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; 
-+		nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
- 		if (!(pmsg->flags & I2C_M_NOSTART)) {
- 			if (i) {
- 				bit_dbg(3, &i2c_adap->dev, "emitting "
-@@ -517,7 +541,7 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
- 				goto bailout;
- 			}
- 		}
--		if (pmsg->flags & I2C_M_RD ) {
-+		if (pmsg->flags & I2C_M_RD) {
- 			/* read bytes into buffer*/
- 			ret = readbytes(i2c_adap, pmsg);
- 			if (ret >= 1)
-@@ -551,7 +575,7 @@ bailout:
  
- static u32 bit_func(struct i2c_adapter *adap)
+ /*
+- * What we have here is a classic case of a top half / bottom half
+- * interrupt service routine. In interrupt mode, the device sends
+- * an interrupt to signal it's ready to receive a packet. However,
+- * we need to delay about 2-3 ticks before issuing the packet or we
+- * gets in trouble.
++ * What we have here is a classic case of a top half / bottom half interrupt
++ * service routine. In interrupt mode, the device sends an interrupt to signal
++ * that it is ready to receive a packet. However, we need to delay about 2-3
++ * ticks before issuing the packet or we gets in trouble.
+  *
+- * So, follow carefully. transfer_pc1 is called as an interrupt (or
+- * directly). In either case, when the device says it's ready for a 
+- * packet, we schedule the packet transfer to occur about 2-3 ticks
+- * later in transfer_pc2.
++ * So, follow carefully. transfer_pc1 is called as an interrupt (or directly).
++ * In either case, when the device says it's ready for a packet, we schedule
++ * the packet transfer to occur about 2-3 ticks later in transfer_pc2.
+  */
+-static int idefloppy_transfer_pc2 (ide_drive_t *drive)
++static int idefloppy_transfer_pc2(ide_drive_t *drive)
  {
--	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
-+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
- 	       I2C_FUNC_SMBUS_READ_BLOCK_DATA |
- 	       I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
- 	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
-@@ -565,8 +589,8 @@ static const struct i2c_algorithm i2c_bit_algo = {
- 	.functionality	= bit_func,
- };
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
  
--/* 
-- * registering functions to load algorithms at runtime 
-+/*
-+ * registering functions to load algorithms at runtime
-  */
- static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
+@@ -987,24 +650,24 @@ static int idefloppy_transfer_pc2 (ide_drive_t *drive)
+ 	return IDEFLOPPY_WAIT_CMD;
+ }
+ 
+-static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
++static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
  {
-@@ -574,7 +598,7 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_startstop_t startstop;
+-	atapi_ireason_t ireason;
++	u8 ireason;
  
- 	if (bit_test) {
- 		int ret = test_bus(bit_adap, adap->name);
--		if (ret<0)
-+		if (ret < 0)
- 			return -ENODEV;
+ 	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
+ 		printk(KERN_ERR "ide-floppy: Strange, packet command "
+ 				"initiated yet DRQ isn't asserted\n");
+ 		return startstop;
  	}
+-	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
+-	if (!ireason.b.cod || ireason.b.io) {
++	ireason = drive->hwif->INB(IDE_IREASON_REG);
++	if ((ireason & CD) == 0 || (ireason & IO)) {
+ 		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
+ 				"while issuing a packet command\n");
+ 		return ide_do_reset(drive);
+ 	}
+-	/* 
++	/*
+ 	 * The following delay solves a problem with ATAPI Zip 100 drives
+ 	 * where the Busy flag was apparently being deasserted before the
+ 	 * unit was ready to receive data. This was happening on a
+@@ -1012,112 +675,82 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
+ 	 * 40 and 50msec work well. idefloppy_pc_intr will not be actually
+ 	 * used until after the packet is moved in about 50 msec.
+ 	 */
+-	BUG_ON(HWGROUP(drive)->handler != NULL);
+-	ide_set_handler(drive, 
+-	  &idefloppy_pc_intr, 		/* service routine for packet command */
+-	  floppy->ticks,		/* wait this long before "failing" */
+-	  &idefloppy_transfer_pc2);	/* fail == transfer_pc2 */
++
++	ide_set_handler(drive, &idefloppy_pc_intr, floppy->ticks,
++			&idefloppy_transfer_pc2);
+ 	return ide_started;
+ }
  
-diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
-index ab2e6f3..8907b01 100644
---- a/drivers/i2c/algos/i2c-algo-pcf.c
-+++ b/drivers/i2c/algos/i2c-algo-pcf.c
-@@ -203,35 +203,6 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
- /* ----- Utility functions
-  */
- 
--static inline int try_address(struct i2c_algo_pcf_data *adap,
--		       unsigned char addr, int retries)
--{
--	int i, status, ret = -1;
--	int wfp;
--	for (i=0;i<retries;i++) {
--		i2c_outb(adap, addr);
--		i2c_start(adap);
--		status = get_pcf(adap, 1);
--		if ((wfp = wait_for_pin(adap, &status)) >= 0) {
--			if ((status & I2C_PCF_LRB) == 0) { 
--				i2c_stop(adap);
--				break;	/* success! */
--			}
--		}
--		if (wfp == -EINTR) {
--			/* arbitration lost */
--			udelay(adap->udelay);
--			return -EINTR;
--		}
--		i2c_stop(adap);
--		udelay(adap->udelay);
--	}
--	DEB2(if (i) printk(KERN_DEBUG "i2c-algo-pcf.o: needed %d retries for %d\n",i,
--	                   addr));
--	return ret;
--}
--
--
- static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
-                          int count, int last)
+-/**
+- * idefloppy_should_report_error()
+- *
+- * Supresses error messages resulting from Medium not present
+- */
+-static inline int idefloppy_should_report_error(idefloppy_floppy_t *floppy)
++static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
++				    idefloppy_pc_t *pc)
  {
-@@ -321,47 +292,19 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
++	/* supress error messages resulting from Medium not present */
+ 	if (floppy->sense_key == 0x02 &&
+ 	    floppy->asc       == 0x3a &&
+ 	    floppy->ascq      == 0x00)
+-		return 0;
+-	return 1;
++		return;
++
++	printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
++			"asc = %2x, ascq = %2x\n",
++			floppy->drive->name, pc->c[0], floppy->sense_key,
++			floppy->asc, floppy->ascq);
++
  }
  
- 
--static inline int pcf_doAddress(struct i2c_algo_pcf_data *adap,
--                                struct i2c_msg *msg, int retries) 
-+static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
-+			 struct i2c_msg *msg)
+-/*
+- *	Issue a packet command
+- */
+-static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
++static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
++		idefloppy_pc_t *pc)
  {
- 	unsigned short flags = msg->flags;
- 	unsigned char addr;
--	int ret;
--	if ( (flags & I2C_M_TEN)  ) { 
--		/* a ten bit address */
--		addr = 0xf0 | (( msg->addr >> 7) & 0x03);
--		DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
--		/* try extended address code...*/
--		ret = try_address(adap, addr, retries);
--		if (ret!=1) {
--			printk(KERN_ERR "died at extended address code.\n");
--			return -EREMOTEIO;
--		}
--		/* the remaining 8 bit address */
--		i2c_outb(adap,msg->addr & 0x7f);
--/* Status check comes here */
--		if (ret != 1) {
--			printk(KERN_ERR "died at 2nd address code.\n");
--			return -EREMOTEIO;
--		}
--		if ( flags & I2C_M_RD ) {
--			i2c_repstart(adap);
--			/* okay, now switch into reading mode */
--			addr |= 0x01;
--			ret = try_address(adap, addr, retries);
--			if (ret!=1) {
--				printk(KERN_ERR "died at extended address code.\n");
--				return -EREMOTEIO;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_hwif_t *hwif = drive->hwif;
+-	atapi_feature_t feature;
+-	atapi_bcount_t bcount;
+ 	ide_handler_t *pkt_xfer_routine;
+-
+-#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
+-         and have lived on another thread's stack; that stack may have become
+-         unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
+-#if IDEFLOPPY_DEBUG_BUGS
+-	if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
+-	    pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
+-		printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - "
+-			"Two request sense in serial were issued\n");
+-	}
+-#endif /* IDEFLOPPY_DEBUG_BUGS */
+-#endif
++	u16 bcount;
++	u8 dma;
+ 
+ 	if (floppy->failed_pc == NULL &&
+-	    pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
++	    pc->c[0] != GPCMD_REQUEST_SENSE)
+ 		floppy->failed_pc = pc;
+ 	/* Set the current packet command */
+ 	floppy->pc = pc;
+ 
+-	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES ||
+-	    test_bit(PC_ABORT, &pc->flags)) {
+-		/*
+-		 *	We will "abort" retrying a packet command in case
+-		 *	a legitimate error code was received.
+-		 */
+-		if (!test_bit(PC_ABORT, &pc->flags)) {
+-			if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) {
+-				if (idefloppy_should_report_error(floppy))
+-					printk(KERN_ERR "ide-floppy: %s: I/O error, "
+-					       "pc = %2x, key = %2x, "
+-					       "asc = %2x, ascq = %2x\n",
+-					       drive->name, pc->c[0],
+-					       floppy->sense_key,
+-					       floppy->asc, floppy->ascq);
 -			}
+-			/* Giving up */
+-			pc->error = IDEFLOPPY_ERROR_GENERAL;
 -		}
--	} else {		/* normal 7bit address	*/
--		addr = ( msg->addr << 1 );
--		if (flags & I2C_M_RD )
--			addr |= 1;
--		if (flags & I2C_M_REV_DIR_ADDR )
--			addr ^= 1;
--		i2c_outb(adap, addr);
--	}
-+
-+	addr = msg->addr << 1;
-+	if (flags & I2C_M_RD)
-+		addr |= 1;
-+	if (flags & I2C_M_REV_DIR_ADDR)
-+		addr ^= 1;
-+	i2c_outb(adap, addr);
++	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
++		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
++			ide_floppy_report_error(floppy, pc);
++		/* Giving up */
++		pc->error = IDEFLOPPY_ERROR_GENERAL;
 +
- 	return 0;
- }
+ 		floppy->failed_pc = NULL;
+ 		pc->callback(drive);
+ 		return ide_stopped;
+ 	}
  
-@@ -390,7 +333,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
- 		     pmsg->flags & I2C_M_RD ? "read" : "write",
-                      pmsg->len, pmsg->addr, i + 1, num);)
-     
--		ret = pcf_doAddress(adap, pmsg, i2c_adap->retries);
-+		ret = pcf_doAddress(adap, pmsg);
+-	debug_log(KERN_INFO "Retry number - %d\n",pc->retries);
++	debug_log("Retry number - %d\n", pc->retries);
  
- 		/* Send START */
- 		if (i == 0) {
-@@ -453,7 +396,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
- static u32 pcf_func(struct i2c_adapter *adap)
- {
- 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | 
--	       I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; 
-+	       I2C_FUNC_PROTOCOL_MANGLING;
- }
+ 	pc->retries++;
+ 	/* We haven't transferred any data yet */
+ 	pc->actually_transferred = 0;
+ 	pc->current_position = pc->buffer;
+-	bcount.all = min(pc->request_transfer, 63 * 1024);
++	bcount = min(pc->request_transfer, 63 * 1024);
  
- /* -----exported algorithm data: -------------------------------------	*/
-@@ -475,9 +418,7 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
+-	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
++	if (pc->flags & PC_FLAG_DMA_ERROR) {
++		pc->flags &= ~PC_FLAG_DMA_ERROR;
+ 		ide_dma_off(drive);
++	}
++	dma = 0;
  
- 	/* register new adapter to i2c module... */
- 	adap->algo = &pcf_algo;
+-	feature.all = 0;
 -
--	adap->timeout = 100;		/* default values, should	*/
--	adap->retries = 3;		/* be replaced by defines	*/
-+	adap->timeout = 100;
+-	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
+-		feature.b.dma = !hwif->dma_setup(drive);
++	if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
++		dma = !hwif->dma_setup(drive);
  
- 	if ((rval = pcf_init_8584(pcf_adap)))
- 		return rval;
-diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
-index c466c6c..b61f56b 100644
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -182,7 +182,8 @@ config I2C_I801
- 	  will be called i2c-i801.
+-	if (IDE_CONTROL_REG)
+-		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
+-	/* Use PIO/DMA */
+-	HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
+-	HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
+-	HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
+-	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
++	ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
++			   IDE_TFLAG_OUT_DEVICE, bcount, dma);
  
- config I2C_I810
--	tristate "Intel 810/815"
-+	tristate "Intel 810/815 (DEPRECATED)"
-+	default n
- 	depends on PCI
- 	select I2C_ALGOBIT
- 	help
-@@ -195,6 +196,8 @@ config I2C_I810
- 	    i815
- 	    i845G
+-	if (feature.b.dma) {	/* Begin DMA, if necessary */
+-		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
++	if (dma) {
++		/* Begin DMA, if necessary */
++		pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
+ 		hwif->dma_start(drive);
+ 	}
  
-+	  This driver is deprecated in favor of the i810fb and intelfb drivers.
-+
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called i2c-i810.
+ 	/* Can we transfer the packet when we get the interrupt or wait? */
+-	if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) {
++	if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) {
+ 		/* wait */
+ 		pkt_xfer_routine = &idefloppy_transfer_pc1;
+ 	} else {
+@@ -1125,7 +758,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
+ 		pkt_xfer_routine = &idefloppy_transfer_pc;
+ 	}
+ 	
+-	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
++	if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
+ 		/* Issue the packet command */
+ 		ide_execute_command(drive, WIN_PACKETCMD,
+ 				pkt_xfer_routine,
+@@ -1139,38 +772,37 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
+ 	}
+ }
  
-@@ -259,20 +262,6 @@ config I2C_IOP3XX
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called i2c-iop3xx.
+-static void idefloppy_rw_callback (ide_drive_t *drive)
++static void idefloppy_rw_callback(ide_drive_t *drive)
+ {
+-	debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
++	debug_log("Reached %s\n", __func__);
  
--config I2C_IXP4XX
--	tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
--	depends on ARCH_IXP4XX
--	select I2C_ALGOBIT
--	help
--	  Say Y here if you have an Intel IXP4xx(420,421,422,425) based 
--	  system and are using GPIO lines for an I2C bus.
--
--	  This support is also available as a module. If so, the module
--	  will be called i2c-ixp4xx.
--
--	  This driver is deprecated and will be dropped soon. Use i2c-gpio
--	  instead.
--
- config I2C_IXP2000
- 	tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
- 	depends on ARCH_IXP2000
-@@ -396,7 +385,8 @@ config I2C_PASEMI
- 	  Supports the PA Semi PWRficient on-chip SMBus interfaces.
+ 	idefloppy_do_end_request(drive, 1, 0);
+ 	return;
+ }
  
- config I2C_PROSAVAGE
--	tristate "S3/VIA (Pro)Savage"
-+	tristate "S3/VIA (Pro)Savage (DEPRECATED)"
-+	default n
- 	depends on PCI
- 	select I2C_ALGOBIT
- 	help
-@@ -407,6 +397,8 @@ config I2C_PROSAVAGE
- 	    S3/VIA KM266/VT8375 aka ProSavage8
- 	    S3/VIA KM133/VT8365 aka Savage4
+-static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent)
++static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
+ {
+-	debug_log(KERN_INFO "ide-floppy: creating prevent removal command, "
+-		"prevent = %d\n", prevent);
++	debug_log("creating prevent removal command, prevent = %d\n", prevent);
  
-+	  This driver is deprecated in favor of the savagefb driver.
-+
- 	  This support is also available as a module.  If so, the module 
- 	  will be called i2c-prosavage.
+ 	idefloppy_init_pc(pc);
+-	pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;
++	pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
+ 	pc->c[4] = prevent;
+ }
  
-@@ -418,13 +410,16 @@ config I2C_S3C2410
- 	  Samsung S3C2410 based System-on-Chip devices.
+-static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc)
++static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc)
+ {
+ 	idefloppy_init_pc(pc);
+-	pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD;
++	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
+ 	pc->c[7] = 255;
+ 	pc->c[8] = 255;
+ 	pc->request_transfer = 255;
+ }
  
- config I2C_SAVAGE4
--	tristate "S3 Savage 4"
--	depends on PCI && EXPERIMENTAL
-+	tristate "S3 Savage 4 (DEPRECATED)"
-+	default n
-+	depends on PCI
- 	select I2C_ALGOBIT
- 	help
- 	  If you say yes to this option, support will be included for the 
- 	  S3 Savage 4 I2C interface.
+-static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,
++static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l,
+ 					      int flags)
+ {
+ 	idefloppy_init_pc(pc);
+-	pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD;
++	pc->c[0] = GPCMD_FORMAT_UNIT;
+ 	pc->c[1] = 0x17;
  
-+	  This driver is deprecated in favor of the savagefb driver.
+ 	memset(pc->buffer, 0, 12);
+@@ -1181,83 +813,79 @@ static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,
+ 		pc->buffer[1] ^= 0x20;		/* ... turn off DCRT bit */
+ 	pc->buffer[3] = 8;
+ 
+-	put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4]));
+-	put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8]));
+-	pc->buffer_size=12;
+-	set_bit(PC_WRITING, &pc->flags);
++	put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4]));
++	put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8]));
++	pc->buffer_size = 12;
++	pc->flags |= PC_FLAG_WRITING;
+ }
+ 
+-/*
+- *	A mode sense command is used to "sense" floppy parameters.
+- */
+-static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, u8 page_code, u8 type)
++/* A mode sense command is used to "sense" floppy parameters. */
++static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
++		u8 type)
+ {
+-	u16 length = sizeof(idefloppy_mode_parameter_header_t);
+-	
++	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
 +
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called i2c-savage4.
+ 	idefloppy_init_pc(pc);
+-	pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD;
++	pc->c[0] = GPCMD_MODE_SENSE_10;
+ 	pc->c[1] = 0;
+ 	pc->c[2] = page_code + (type << 6);
  
-@@ -611,7 +606,7 @@ config I2C_VIAPRO
- 	    VT8231
- 	    VT8233/A
- 	    VT8235
--	    VT8237R/A
-+	    VT8237R/A/S
- 	    VT8251
- 	    CX700
+ 	switch (page_code) {
+-		case IDEFLOPPY_CAPABILITIES_PAGE:
+-			length += 12;
+-			break;
+-		case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
+-			length += 32;
+-			break;
+-		default:
+-			printk(KERN_ERR "ide-floppy: unsupported page code "
++	case IDEFLOPPY_CAPABILITIES_PAGE:
++		length += 12;
++		break;
++	case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
++		length += 32;
++		break;
++	default:
++		printk(KERN_ERR "ide-floppy: unsupported page code "
+ 				"in create_mode_sense_cmd\n");
+ 	}
+-	put_unaligned(htons(length), (u16 *) &pc->c[7]);
++	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
+ 	pc->request_transfer = length;
+ }
  
-@@ -648,7 +643,7 @@ config I2C_PCA_ISA
+-static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start)
++static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start)
+ {
+ 	idefloppy_init_pc(pc);
+-	pc->c[0] = IDEFLOPPY_START_STOP_CMD;
++	pc->c[0] = GPCMD_START_STOP_UNIT;
+ 	pc->c[4] = start;
+ }
  
- config I2C_MV64XXX
- 	tristate "Marvell mv64xxx I2C Controller"
--	depends on MV64X60 && EXPERIMENTAL
-+	depends on (MV64X60 || ARCH_ORION) && EXPERIMENTAL
- 	help
- 	  If you say yes to this option, support will be included for the
- 	  built-in I2C interface on the Marvell 64xxx line of host bridges.
-diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
-index 81d43c2..ea7068f 100644
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -20,7 +20,6 @@ obj-$(CONFIG_I2C_I810)		+= i2c-i810.o
- obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
- obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
- obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
--obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
- obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
- obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
- obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
-diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
-index 7490dc1..573abe4 100644
---- a/drivers/i2c/busses/i2c-amd756.c
-+++ b/drivers/i2c/busses/i2c-amd756.c
-@@ -334,6 +334,10 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
- 	int error;
- 	u8 temp;
- 	
-+	/* driver_data might come from user-space, so check it */
-+	if (id->driver_data > ARRAY_SIZE(chipname))
-+		return -EINVAL;
-+
- 	if (amd756_ioport) {
- 		dev_err(&pdev->dev, "Only one device supported "
- 		       "(you have a strange motherboard, btw)\n");
-@@ -405,6 +409,7 @@ static struct pci_driver amd756_driver = {
- 	.id_table	= amd756_ids,
- 	.probe		= amd756_probe,
- 	.remove		= __devexit_p(amd756_remove),
-+	.dynids.use_driver_data = 1,
- };
+ static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc)
+ {
+ 	idefloppy_init_pc(pc);
+-	pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD;
++	pc->c[0] = GPCMD_TEST_UNIT_READY;
+ }
  
- static int __init amd756_init(void)
-diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
-index 2f68416..1953b26 100644
---- a/drivers/i2c/busses/i2c-au1550.c
-+++ b/drivers/i2c/busses/i2c-au1550.c
-@@ -30,14 +30,22 @@
- #include <linux/delay.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
-+#include <linux/platform_device.h>
- #include <linux/init.h>
- #include <linux/errno.h>
- #include <linux/i2c.h>
-+#include <linux/slab.h>
+-static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector)
++static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
++				    idefloppy_pc_t *pc, struct request *rq,
++				    unsigned long sector)
+ {
+ 	int block = sector / floppy->bs_factor;
+ 	int blocks = rq->nr_sectors / floppy->bs_factor;
+ 	int cmd = rq_data_dir(rq);
  
- #include <asm/mach-au1x00/au1xxx.h>
- #include <asm/mach-au1x00/au1xxx_psc.h>
+-	debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n",
+-		2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags),
++	debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
+ 		block, blocks);
  
--#include "i2c-au1550.h"
-+struct i2c_au1550_data {
-+	u32	psc_base;
-+	int	xfer_timeout;
-+	int	ack_timeout;
-+	struct i2c_adapter adap;
-+	struct resource *ioarea;
-+};
+ 	idefloppy_init_pc(pc);
+-	if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) {
+-		pc->c[0] = cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD;
+-		put_unaligned(htonl(blocks), (unsigned int *) &pc->c[6]);
+-	} else {
+-		pc->c[0] = cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD;
+-		put_unaligned(htons(blocks), (unsigned short *) &pc->c[7]);
+-	}
+-	put_unaligned(htonl(block), (unsigned int *) &pc->c[2]);
++	pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
++	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
++	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
++
+ 	pc->callback = &idefloppy_rw_callback;
+ 	pc->rq = rq;
+ 	pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
+ 	if (rq->cmd_flags & REQ_RW)
+-		set_bit(PC_WRITING, &pc->flags);
++		pc->flags |= PC_FLAG_WRITING;
+ 	pc->buffer = NULL;
+ 	pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;
+-	set_bit(PC_DMA_RECOMMENDED, &pc->flags);
++	pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ }
  
- static int
- wait_xfer_done(struct i2c_au1550_data *adap)
-@@ -105,7 +113,7 @@ wait_master_done(struct i2c_au1550_data *adap)
+-static void
+-idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
++static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
++		idefloppy_pc_t *pc, struct request *rq)
+ {
+ 	idefloppy_init_pc(pc);
+ 	pc->callback = &idefloppy_rw_callback;
+@@ -1265,11 +893,10 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req
+ 	pc->rq = rq;
+ 	pc->b_count = rq->data_len;
+ 	if (rq->data_len && rq_data_dir(rq) == WRITE)
+-		set_bit(PC_WRITING, &pc->flags);
++		pc->flags |= PC_FLAG_WRITING;
+ 	pc->buffer = rq->data;
+ 	if (rq->bio)
+-		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+-		
++		pc->flags |= PC_FLAG_DMA_RECOMMENDED;
+ 	/*
+ 	 * possibly problematic, doesn't look like ide-floppy correctly
+ 	 * handled scattered requests if dma fails...
+@@ -1277,30 +904,23 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req
+ 	pc->request_transfer = pc->buffer_size = rq->data_len;
  }
  
- static int
--do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
-+do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q)
+-/*
+- *	idefloppy_do_request is our request handling function.	
+- */
+-static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, sector_t block_s)
++static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
++		struct request *rq, sector_t block_s)
  {
- 	volatile psc_smb_t	*sp;
- 	u32			stat;
-@@ -134,6 +142,10 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
- 	if (rd)
- 		addr |= 1;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	idefloppy_pc_t *pc;
+ 	unsigned long block = (unsigned long)block_s;
  
-+	/* zero-byte xfers stop immediately */
-+	if (q)
-+		addr |= PSC_SMBTXRX_STP;
-+
- 	/* Put byte into fifo, start up master.
- 	*/
- 	sp->psc_smbtxrx = addr;
-@@ -142,7 +154,7 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
- 	au_sync();
- 	if (wait_ack(adap))
- 		return -EIO;
--	return 0;
-+	return (q) ? wait_master_done(adap) : 0;
+-	debug_log(KERN_INFO "dev: %s, flags: %lx, errors: %d\n",
++	debug_log("dev: %s, cmd_type: %x, errors: %d\n",
+ 			rq->rq_disk ? rq->rq_disk->disk_name : "?",
+-			rq->flags, rq->errors);
+-	debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
++			rq->cmd_type, rq->errors);
++	debug_log("sector: %ld, nr_sectors: %ld, "
+ 			"current_nr_sectors: %d\n", (long)rq->sector,
+ 			rq->nr_sectors, rq->current_nr_sectors);
+ 
+ 	if (rq->errors >= ERROR_MAX) {
+-		if (floppy->failed_pc != NULL) {
+-			if (idefloppy_should_report_error(floppy))
+-				printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x,"
+-				       " key = %2x, asc = %2x, ascq = %2x\n",
+-				       drive->name, floppy->failed_pc->c[0],
+-				       floppy->sense_key, floppy->asc, floppy->ascq);
+-		}
++		if (floppy->failed_pc)
++			ide_floppy_report_error(floppy, floppy->failed_pc);
+ 		else
+ 			printk(KERN_ERR "ide-floppy: %s: I/O error\n",
+ 				drive->name);
+@@ -1310,8 +930,8 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
+ 	if (blk_fs_request(rq)) {
+ 		if (((long)rq->sector % floppy->bs_factor) ||
+ 		    (rq->nr_sectors % floppy->bs_factor)) {
+-			printk("%s: unsupported r/w request size\n",
+-				drive->name);
++			printk(KERN_ERR "%s: unsupported r/w request size\n",
++					drive->name);
+ 			idefloppy_do_end_request(drive, 0, 0);
+ 			return ide_stopped;
+ 		}
+@@ -1334,15 +954,15 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
  }
  
- static u32
-@@ -262,7 +274,8 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
+ /*
+- *	idefloppy_queue_pc_tail adds a special packet command request to the
+- *	tail of the request queue, and waits for it to be serviced.
++ * Add a special packet command request to the tail of the request queue,
++ * and wait for it to be serviced.
+  */
+-static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
++static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
+ {
+ 	struct ide_floppy_obj *floppy = drive->driver_data;
+ 	struct request rq;
  
- 	for (i = 0; !err && i < num; i++) {
- 		p = &msgs[i];
--		err = do_address(adap, p->addr, p->flags & I2C_M_RD);
-+		err = do_address(adap, p->addr, p->flags & I2C_M_RD,
-+				 (p->len == 0));
- 		if (err || !p->len)
- 			continue;
- 		if (p->flags & I2C_M_RD)
-@@ -294,18 +307,48 @@ static const struct i2c_algorithm au1550_algo = {
-  * Prior to calling us, the 50MHz clock frequency and routing
-  * must have been set up for the PSC indicated by the adapter.
+-	ide_init_drive_cmd (&rq);
++	ide_init_drive_cmd(&rq);
+ 	rq.buffer = (char *) pc;
+ 	rq.cmd_type = REQ_TYPE_SPECIAL;
+ 	rq.rq_disk = floppy->disk;
+@@ -1351,88 +971,90 @@ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
+ }
+ 
+ /*
+- *	Look at the flexible disk page parameters. We will ignore the CHS
+- *	capacity parameters and use the LBA parameters instead.
++ * Look at the flexible disk page parameters. We ignore the CHS capacity
++ * parameters and use the LBA parameters instead.
   */
--int
--i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
-+static int __devinit
-+i2c_au1550_probe(struct platform_device *pdev)
+-static int idefloppy_get_flexible_disk_page (ide_drive_t *drive)
++static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
  {
--	struct i2c_au1550_data *adap = i2c_adap->algo_data;
--	volatile psc_smb_t	*sp;
--	u32	stat;
-+	struct i2c_au1550_data *priv;
-+	volatile psc_smb_t *sp;
-+	struct resource *r;
-+	u32 stat;
-+	int ret;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	idefloppy_pc_t pc;
+-	idefloppy_mode_parameter_header_t *header;
+-	idefloppy_flexible_disk_page_t *page;
++	u8 *page;
+ 	int capacity, lba_capacity;
++	u16 transfer_rate, sector_size, cyls, rpm;
++	u8 heads, sectors;
 +
-+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	if (!r) {
-+		ret = -ENODEV;
-+		goto out;
-+	}
++	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE,
++					MODE_SENSE_CURRENT);
+ 
+-	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT);
+-	if (idefloppy_queue_pc_tail(drive,&pc)) {
+-		printk(KERN_ERR "ide-floppy: Can't get flexible disk "
+-			"page parameters\n");
++	if (idefloppy_queue_pc_tail(drive, &pc)) {
++		printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
++				" parameters\n");
+ 		return 1;
+ 	}
+-	header = (idefloppy_mode_parameter_header_t *) pc.buffer;
+-	floppy->wp = header->wp;
++	floppy->wp = !!(pc.buffer[3] & 0x80);
+ 	set_disk_ro(floppy->disk, floppy->wp);
+-	page = (idefloppy_flexible_disk_page_t *) (header + 1);
+-
+-	page->transfer_rate = ntohs(page->transfer_rate);
+-	page->sector_size = ntohs(page->sector_size);
+-	page->cyls = ntohs(page->cyls);
+-	page->rpm = ntohs(page->rpm);
+-	capacity = page->cyls * page->heads * page->sectors * page->sector_size;
+-	if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t)))
++	page = &pc.buffer[8];
 +
-+	priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL);
-+	if (!priv) {
-+		ret = -ENOMEM;
-+		goto out;
-+	}
++	transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]);
++	sector_size   = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]);
++	cyls          = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]);
++	rpm           = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]);
++	heads         = pc.buffer[8 + 4];
++	sectors       = pc.buffer[8 + 5];
 +
-+	priv->ioarea = request_mem_region(r->start, r->end - r->start + 1,
-+					  pdev->name);
-+	if (!priv->ioarea) {
-+		ret = -EBUSY;
-+		goto out_mem;
-+	}
- 
--	i2c_adap->algo = &au1550_algo;
-+	priv->psc_base = r->start;
-+	priv->xfer_timeout = 200;
-+	priv->ack_timeout = 200;
++	capacity = cyls * heads * sectors * sector_size;
 +
-+	priv->adap.id = I2C_HW_AU1550_PSC;
-+	priv->adap.nr = pdev->id;
-+	priv->adap.algo = &au1550_algo;
-+	priv->adap.algo_data = priv;
-+	priv->adap.dev.parent = &pdev->dev;
-+	strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name));
++	if (memcmp(page, &floppy->flexible_disk_page, 32))
+ 		printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
+ 				"%d sector size, %d rpm\n",
+-			drive->name, capacity / 1024, page->cyls,
+-			page->heads, page->sectors,
+-			page->transfer_rate / 8, page->sector_size, page->rpm);
+-
+-	floppy->flexible_disk_page = *page;
+-	drive->bios_cyl = page->cyls;
+-	drive->bios_head = page->heads;
+-	drive->bios_sect = page->sectors;
++				drive->name, capacity / 1024, cyls, heads,
++				sectors, transfer_rate / 8, sector_size, rpm);
++
++	memcpy(&floppy->flexible_disk_page, page, 32);
++	drive->bios_cyl = cyls;
++	drive->bios_head = heads;
++	drive->bios_sect = sectors;
+ 	lba_capacity = floppy->blocks * floppy->block_size;
++
+ 	if (capacity < lba_capacity) {
+ 		printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
+ 			"bytes, but the drive only handles %d\n",
+ 			drive->name, lba_capacity, capacity);
+-		floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0;
++		floppy->blocks = floppy->block_size ?
++			capacity / floppy->block_size : 0;
+ 	}
+ 	return 0;
+ }
  
- 	/* Now, set up the PSC for SMBus PIO mode.
- 	*/
--	sp = (volatile psc_smb_t *)(adap->psc_base);
-+	sp = (volatile psc_smb_t *)priv->psc_base;
- 	sp->psc_ctrl = PSC_CTRL_DISABLE;
- 	au_sync();
- 	sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
-@@ -343,87 +386,87 @@ i2c_au1550_add_bus(struct i2c_adapter *i2c_adap)
- 		au_sync();
- 	} while ((stat & PSC_SMBSTAT_DR) == 0);
+-static int idefloppy_get_capability_page(ide_drive_t *drive)
++static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	idefloppy_pc_t pc;
+-	idefloppy_mode_parameter_header_t *header;
+-	idefloppy_capabilities_page_t *page;
  
--	return i2c_add_adapter(i2c_adap);
--}
-+	ret = i2c_add_numbered_adapter(&priv->adap);
-+	if (ret == 0) {
-+		platform_set_drvdata(pdev, priv);
-+		return 0;
-+	}
+ 	floppy->srfp = 0;
+ 	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
+ 						 MODE_SENSE_CURRENT);
  
-+	/* disable the PSC */
-+	sp->psc_smbcfg = 0;
-+	sp->psc_ctrl = PSC_CTRL_DISABLE;
-+	au_sync();
+-	set_bit(PC_SUPPRESS_ERROR, &pc.flags);
+-	if (idefloppy_queue_pc_tail(drive,&pc)) {
++	pc.flags |= PC_FLAG_SUPPRESS_ERROR;
++	if (idefloppy_queue_pc_tail(drive, &pc))
+ 		return 1;
+-	}
  
--int
--i2c_au1550_del_bus(struct i2c_adapter *adap)
-+	release_resource(priv->ioarea);
-+	kfree(priv->ioarea);
-+out_mem:
-+	kfree(priv);
-+out:
-+	return ret;
-+}
-+
-+static int __devexit
-+i2c_au1550_remove(struct platform_device *pdev)
- {
--	return i2c_del_adapter(adap);
-+	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
-+	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
-+
-+	platform_set_drvdata(pdev, NULL);
-+	i2c_del_adapter(&priv->adap);
-+	sp->psc_smbcfg = 0;
-+	sp->psc_ctrl = PSC_CTRL_DISABLE;
-+	au_sync();
-+	release_resource(priv->ioarea);
-+	kfree(priv->ioarea);
-+	kfree(priv);
-+	return 0;
+-	header = (idefloppy_mode_parameter_header_t *) pc.buffer;
+-	page= (idefloppy_capabilities_page_t *)(header+1);
+-	floppy->srfp = page->srfp;
++	floppy->srfp = pc.buffer[8 + 2] & 0x40;
+ 	return (0);
  }
  
- static int
--pb1550_reg(struct i2c_client *client)
-+i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
+ /*
+- *	Determine if a media is present in the floppy drive, and if so,
+- *	its LBA capacity.
++ * Determine if a media is present in the floppy drive, and if so, its LBA
++ * capacity.
+  */
+-static int idefloppy_get_capacity (ide_drive_t *drive)
++static int ide_floppy_get_capacity(ide_drive_t *drive)
  {
-+	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
-+	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	idefloppy_pc_t pc;
+-	idefloppy_capacity_header_t *header;
+-	idefloppy_capacity_descriptor_t *descriptor;
+-	int i, descriptors, rc = 1, blocks, length;
+-	
++	u8 *cap_desc;
++	u8 header_len, desc_cnt;
++	int i, rc = 1, blocks, length;
 +
-+	sp->psc_ctrl = PSC_CTRL_SUSPEND;
-+	au_sync();
- 	return 0;
- }
+ 	drive->bios_cyl = 0;
+ 	drive->bios_head = drive->bios_sect = 0;
+ 	floppy->blocks = 0;
+@@ -1444,44 +1066,55 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
+ 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+ 		return 1;
+ 	}
+-	header = (idefloppy_capacity_header_t *) pc.buffer;
+-	descriptors = header->length / sizeof(idefloppy_capacity_descriptor_t);
+-	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
++	header_len = pc.buffer[3];
++	cap_desc = &pc.buffer[4];
++	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
++
++	for (i = 0; i < desc_cnt; i++) {
++		unsigned int desc_start = 4 + i*8;
++
++		blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
++		length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
  
- static int
--pb1550_unreg(struct i2c_client *client)
-+i2c_au1550_resume(struct platform_device *pdev)
- {
-+	struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
-+	volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+-	for (i = 0; i < descriptors; i++, descriptor++) {
+-		blocks = descriptor->blocks = ntohl(descriptor->blocks);
+-		length = descriptor->length = ntohs(descriptor->length);
++		debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
++				i, blocks * length / 1024, blocks, length);
 +
-+	sp->psc_ctrl = PSC_CTRL_ENABLE;
-+	au_sync();
-+	while (!(sp->psc_smbstat & PSC_SMBSTAT_SR))
-+		au_sync();
- 	return 0;
- }
++		if (i)
++			continue;
++		/*
++		 * the code below is valid only for the 1st descriptor, ie i=0
++		 */
  
--static struct i2c_au1550_data pb1550_i2c_info = {
--	SMBUS_PSC_BASE, 200, 200
--};
--
--static struct i2c_adapter pb1550_board_adapter = {
--	name:              "pb1550 adapter",
--	id:                I2C_HW_AU1550_PSC,
--	algo:              NULL,
--	algo_data:         &pb1550_i2c_info,
--	client_register:   pb1550_reg,
--	client_unregister: pb1550_unreg,
-+static struct platform_driver au1xpsc_smbus_driver = {
-+	.driver = {
-+		.name	= "au1xpsc_smbus",
-+		.owner	= THIS_MODULE,
-+	},
-+	.probe		= i2c_au1550_probe,
-+	.remove		= __devexit_p(i2c_au1550_remove),
-+	.suspend	= i2c_au1550_suspend,
-+	.resume		= i2c_au1550_resume,
- };
+-		if (!i) 
+-		{
+-		switch (descriptor->dc) {
++		switch (pc.buffer[desc_start + 4] & 0x03) {
+ 		/* Clik! drive returns this instead of CAPACITY_CURRENT */
+ 		case CAPACITY_UNFORMATTED:
+-			if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
+-                                /*
++			if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
++				/*
+ 				 * If it is not a clik drive, break out
+ 				 * (maintains previous driver behaviour)
+ 				 */
+ 				break;
+ 		case CAPACITY_CURRENT:
+ 			/* Normal Zip/LS-120 disks */
+-			if (memcmp(descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
++			if (memcmp(cap_desc, &floppy->cap_desc, 8))
+ 				printk(KERN_INFO "%s: %dkB, %d blocks, %d "
+ 					"sector size\n", drive->name,
+ 					blocks * length / 1024, blocks, length);
+-			floppy->capacity = *descriptor;
++			memcpy(&floppy->cap_desc, cap_desc, 8);
++
+ 			if (!length || length % 512) {
+ 				printk(KERN_NOTICE "%s: %d bytes block size "
+ 					"not supported\n", drive->name, length);
+ 			} else {
+-                                floppy->blocks = blocks;
+-                                floppy->block_size = length;
+-                                if ((floppy->bs_factor = length / 512) != 1)
+-                                        printk(KERN_NOTICE "%s: warning: non "
++				floppy->blocks = blocks;
++				floppy->block_size = length;
++				floppy->bs_factor = length / 512;
++				if (floppy->bs_factor != 1)
++					printk(KERN_NOTICE "%s: warning: non "
+ 						"512 bytes block size not "
+ 						"fully supported\n",
+ 						drive->name);
+-                                rc = 0;
++				rc = 0;
+ 			}
+ 			break;
+ 		case CAPACITY_NO_CARTRIDGE:
+@@ -1496,54 +1129,42 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
+ 				"in drive\n", drive->name);
+ 			break;
+ 		}
+-		}
+-		if (!i) {
+-			debug_log( "Descriptor 0 Code: %d\n",
+-				descriptor->dc);
+-		}
+-		debug_log( "Descriptor %d: %dkB, %d blocks, %d "
+-			"sector size\n", i, blocks * length / 1024, blocks,
+-			length);
++		debug_log("Descriptor 0 Code: %d\n",
++			  pc.buffer[desc_start + 4] & 0x03);
+ 	}
  
--/* BIG hack to support the control interface on the Wolfson WM8731
-- * audio codec on the Pb1550 board.  We get an address and two data
-- * bytes to write, create an i2c message, and send it across the
-- * i2c transfer function.  We do this here because we have access to
-- * the i2c adapter structure.
-- */
--static struct i2c_msg wm_i2c_msg;  /* We don't want this stuff on the stack */
--static	u8 i2cbuf[2];
--
--int
--pb1550_wm_codec_write(u8 addr, u8 reg, u8 val)
--{
--	wm_i2c_msg.addr = addr;
--	wm_i2c_msg.flags = 0;
--	wm_i2c_msg.buf = i2cbuf;
--	wm_i2c_msg.len = 2;
--	i2cbuf[0] = reg;
--	i2cbuf[1] = val;
--
--	return pb1550_board_adapter.algo->master_xfer(&pb1550_board_adapter, &wm_i2c_msg, 1);
--}
--
- static int __init
- i2c_au1550_init(void)
- {
--	printk(KERN_INFO "Au1550 I2C: ");
--
--	/* This is where we would set up a 50MHz clock source
--	 * and routing.  On the Pb1550, the SMBus is PSC2, which
--	 * uses a shared clock with USB.  This has been already
--	 * configured by Yamon as a 48MHz clock, close enough
--	 * for our work.
--	 */
--        if (i2c_au1550_add_bus(&pb1550_board_adapter) < 0) {
--		printk("failed to initialize.\n");
--                return -ENODEV;
+ 	/* Clik! disk does not support get_flexible_disk_page */
+-        if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+-		(void) idefloppy_get_flexible_disk_page(drive);
 -	}
--
--	printk("initialized.\n");
--	return 0;
-+	return platform_driver_register(&au1xpsc_smbus_driver);
- }
++	if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
++		(void) ide_floppy_get_flexible_disk_page(drive);
  
- static void __exit
- i2c_au1550_exit(void)
- {
--	i2c_au1550_del_bus(&pb1550_board_adapter);
-+	platform_driver_unregister(&au1xpsc_smbus_driver);
+ 	set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
+ 	return rc;
  }
  
- MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC.");
-diff --git a/drivers/i2c/busses/i2c-au1550.h b/drivers/i2c/busses/i2c-au1550.h
-deleted file mode 100644
-index fce15d1..0000000
---- a/drivers/i2c/busses/i2c-au1550.h
-+++ /dev/null
-@@ -1,32 +0,0 @@
--/*
-- * Copyright (C) 2004 Embedded Edge, LLC <dan at embeddededge.com>
-- * 2.6 port by Matt Porter <mporter at 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-- */
--
--#ifndef I2C_AU1550_H
--#define I2C_AU1550_H
--
--struct i2c_au1550_data {
--	u32	psc_base;
--	int	xfer_timeout;
--	int	ack_timeout;
--};
--
--int i2c_au1550_add_bus(struct i2c_adapter *);
--int i2c_au1550_del_bus(struct i2c_adapter *);
+ /*
+-** Obtain the list of formattable capacities.
+-** Very similar to idefloppy_get_capacity, except that we push the capacity
+-** descriptors to userland, instead of our own structures.
+-**
+-** Userland gives us the following structure:
+-**
+-** struct idefloppy_format_capacities {
+-**        int nformats;
+-**        struct {
+-**                int nblocks;
+-**                int blocksize;
+-**                } formats[];
+-**        } ;
+-**
+-** userland initializes nformats to the number of allocated formats[]
+-** records.  On exit we set nformats to the number of records we've
+-** actually initialized.
+-**
+-*/
 -
--#endif /* I2C_AU1550_H */
-diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
-index 67224a4..7dbdaeb 100644
---- a/drivers/i2c/busses/i2c-bfin-twi.c
-+++ b/drivers/i2c/busses/i2c-bfin-twi.c
-@@ -550,6 +550,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
+-static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
++ * Obtain the list of formattable capacities.
++ * Very similar to ide_floppy_get_capacity, except that we push the capacity
++ * descriptors to userland, instead of our own structures.
++ *
++ * Userland gives us the following structure:
++ *
++ * struct idefloppy_format_capacities {
++ *	int nformats;
++ *	struct {
++ *		int nblocks;
++ *		int blocksize;
++ *	} formats[];
++ * };
++ *
++ * userland initializes nformats to the number of allocated formats[] records.
++ * On exit we set nformats to the number of records we've actually initialized.
++ */
++
++static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ {
+-        idefloppy_pc_t pc;
+-	idefloppy_capacity_header_t *header;
+-        idefloppy_capacity_descriptor_t *descriptor;
+-	int i, descriptors, blocks, length;
+-	int u_array_size;
+-	int u_index;
++	idefloppy_pc_t pc;
++	u8 header_len, desc_cnt;
++	int i, blocks, length, u_array_size, u_index;
+ 	int __user *argp;
  
- 	p_adap = &iface->adap;
- 	p_adap->id = I2C_HW_BLACKFIN;
-+	p_adap->nr = dev->id;
- 	strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
- 	p_adap->algo = &bfin_twi_algorithm;
- 	p_adap->algo_data = iface;
-@@ -576,7 +577,7 @@ static int i2c_bfin_twi_probe(struct platform_device *dev)
- 	bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
- 	SSYNC();
+ 	if (get_user(u_array_size, arg))
+@@ -1555,30 +1176,27 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ 	idefloppy_create_read_capacity_cmd(&pc);
+ 	if (idefloppy_queue_pc_tail(drive, &pc)) {
+ 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
+-                return (-EIO);
+-        }
+-        header = (idefloppy_capacity_header_t *) pc.buffer;
+-        descriptors = header->length /
+-		sizeof(idefloppy_capacity_descriptor_t);
+-	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
++		return (-EIO);
++	}
++	header_len = pc.buffer[3];
++	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
  
--	rc = i2c_add_adapter(p_adap);
-+	rc = i2c_add_numbered_adapter(p_adap);
- 	if (rc < 0)
- 		free_irq(iface->irq, iface);
- 	else
-diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
-index 6767988..cce5a61 100644
---- a/drivers/i2c/busses/i2c-davinci.c
-+++ b/drivers/i2c/busses/i2c-davinci.c
-@@ -510,7 +510,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
+ 	u_index = 0;
+ 	argp = arg + 1;
  
- 	/* FIXME */
- 	adap->timeout = 1;
--	adap->retries = 1;
+ 	/*
+-	** We always skip the first capacity descriptor.  That's the
+-	** current capacity.  We are interested in the remaining descriptors,
+-	** the formattable capacities.
+-	*/
++	 * We always skip the first capacity descriptor.  That's the current
++	 * capacity.  We are interested in the remaining descriptors, the
++	 * formattable capacities.
++	 */
++	for (i = 1; i < desc_cnt; i++) {
++		unsigned int desc_start = 4 + i*8;
  
- 	adap->nr = pdev->id;
- 	r = i2c_add_numbered_adapter(adap);
-diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
-index ac27e5f..aa91579 100644
---- a/drivers/i2c/busses/i2c-i801.c
-+++ b/drivers/i2c/busses/i2c-i801.c
-@@ -4,6 +4,7 @@
-     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol at dds.nl>,
-     Philip Edelbrock <phil at netroedge.com>, and Mark D. Studebaker
-     <mdsxyz123 at yahoo.com>
-+    Copyright (C) 2007         Jean Delvare <khali at linux-fr.org>
+-	for (i=0; i<descriptors; i++, descriptor++) {
+ 		if (u_index >= u_array_size)
+ 			break;	/* User-supplied buffer too small */
+-		if (i == 0)
+-			continue;	/* Skip the first descriptor */
  
-     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
-@@ -21,25 +22,34 @@
- */
+-		blocks = ntohl(descriptor->blocks);
+-		length = ntohs(descriptor->length);
++		blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
++		length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
  
- /*
--    SUPPORTED DEVICES	PCI ID
--    82801AA		2413
--    82801AB		2423
--    82801BA		2443
--    82801CA/CAM		2483
--    82801DB		24C3   (HW PEC supported)
--    82801EB		24D3   (HW PEC supported)
--    6300ESB		25A4
--    ICH6		266A
--    ICH7		27DA
--    ESB2		269B
--    ICH8		283E
--    ICH9		2930
--    Tolapai		5032
--    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
--    For SMBus support, they are similar to the PIIX4 and are part
--    of Intel's '810' and other chipsets.
--    See the file Documentation/i2c/busses/i2c-i801 for details.
--    I2C Block Read and Process Call are not supported.
-+  Supports the following Intel I/O Controller Hubs (ICH):
-+
-+                                  I/O                     Block   I2C
-+                                  region  SMBus   Block   proc.   block
-+  Chip name             PCI ID    size    PEC     buffer  call    read
-+  ----------------------------------------------------------------------
-+  82801AA  (ICH)        0x2413     16      no      no      no      no
-+  82801AB  (ICH0)       0x2423     16      no      no      no      no
-+  82801BA  (ICH2)       0x2443     16      no      no      no      no
-+  82801CA  (ICH3)       0x2483     32     soft     no      no      no
-+  82801DB  (ICH4)       0x24c3     32     hard     yes     no      no
-+  82801E   (ICH5)       0x24d3     32     hard     yes     yes     yes
-+  6300ESB               0x25a4     32     hard     yes     yes     yes
-+  82801F   (ICH6)       0x266a     32     hard     yes     yes     yes
-+  6310ESB/6320ESB       0x269b     32     hard     yes     yes     yes
-+  82801G   (ICH7)       0x27da     32     hard     yes     yes     yes
-+  82801H   (ICH8)       0x283e     32     hard     yes     yes     yes
-+  82801I   (ICH9)       0x2930     32     hard     yes     yes     yes
-+  Tolapai               0x5032     32     hard     yes     ?       ?
-+
-+  Features supported by this driver:
-+  Software PEC                     no
-+  Hardware PEC                     yes
-+  Block buffer                     yes
-+  Block process call transaction   no
-+  I2C block read transaction       yes  (doesn't use the block buffer)
-+
-+  See the file Documentation/i2c/busses/i2c-i801 for details.
- */
+ 		if (put_user(blocks, argp))
+ 			return(-EFAULT);
+@@ -1597,53 +1215,14 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ }
  
- /* Note: we assume there can only be one I801, with one SMBus interface */
-@@ -62,9 +72,9 @@
- #define SMBHSTDAT0	(5 + i801_smba)
- #define SMBHSTDAT1	(6 + i801_smba)
- #define SMBBLKDAT	(7 + i801_smba)
--#define SMBPEC		(8 + i801_smba)	/* ICH4 only */
--#define SMBAUXSTS	(12 + i801_smba)	/* ICH4 only */
--#define SMBAUXCTL	(13 + i801_smba)	/* ICH4 only */
-+#define SMBPEC		(8 + i801_smba)		/* ICH3 and later */
-+#define SMBAUXSTS	(12 + i801_smba)	/* ICH4 and later */
-+#define SMBAUXCTL	(13 + i801_smba)	/* ICH4 and later */
+ /*
+-** Send ATAPI_FORMAT_UNIT to the drive.
+-**
+-** Userland gives us the following structure:
+-**
+-** struct idefloppy_format_command {
+-**        int nblocks;
+-**        int blocksize;
+-**        int flags;
+-**        } ;
+-**
+-** flags is a bitmask, currently, the only defined flag is:
+-**
+-**        0x01 - verify media after format.
+-*/
+-
+-static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg)
+-{
+-	int blocks;
+-	int length;
+-	int flags;
+-	idefloppy_pc_t pc;
+-
+-	if (get_user(blocks, arg) ||
+-	    get_user(length, arg+1) ||
+-	    get_user(flags, arg+2)) {
+-		return (-EFAULT);
+-	}
+-
+-	/* Get the SFRP bit */
+-	(void) idefloppy_get_capability_page(drive);
+-	idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
+-	if (idefloppy_queue_pc_tail(drive, &pc)) {
+-                return (-EIO);
+-	}
+-
+-	return (0);
+-}
+-
+-/*
+-** Get ATAPI_FORMAT_UNIT progress indication.
+-**
+-** Userland gives a pointer to an int.  The int is set to a progress
+-** indicator 0-65536, with 65536=100%.
+-**
+-** If the drive does not support format progress indication, we just check
+-** the dsc bit, and return either 0 or 65536.
+-*/
++ * Get ATAPI_FORMAT_UNIT progress indication.
++ *
++ * Userland gives a pointer to an int.  The int is set to a progress
++ * indicator 0-65536, with 65536=100%.
++ *
++ * If the drive does not support format progress indication, we just check
++ * the dsc bit, and return either 0 or 65536.
++ */
  
- /* PCI Address Constants */
- #define SMBBAR		4
-@@ -91,13 +101,13 @@
- #define I801_BYTE		0x04
- #define I801_BYTE_DATA		0x08
- #define I801_WORD_DATA		0x0C
--#define I801_PROC_CALL		0x10	/* later chips only, unimplemented */
-+#define I801_PROC_CALL		0x10	/* unimplemented */
- #define I801_BLOCK_DATA		0x14
--#define I801_I2C_BLOCK_DATA	0x18	/* unimplemented */
-+#define I801_I2C_BLOCK_DATA	0x18	/* ICH5 and later */
- #define I801_BLOCK_LAST		0x34
--#define I801_I2C_BLOCK_LAST	0x38	/* unimplemented */
-+#define I801_I2C_BLOCK_LAST	0x38	/* ICH5 and later */
- #define I801_START		0x40
--#define I801_PEC_EN		0x80	/* ICH4 only */
-+#define I801_PEC_EN		0x80	/* ICH3 and later */
+ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+ {
+@@ -1653,26 +1232,24 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
  
- /* I801 Hosts Status register bits */
- #define SMBHSTSTS_BYTE_DONE	0x80
-@@ -113,7 +123,12 @@ static unsigned long i801_smba;
- static unsigned char i801_original_hstcfg;
- static struct pci_driver i801_driver;
- static struct pci_dev *I801_dev;
--static int isich4;
+ 	if (floppy->srfp) {
+ 		idefloppy_create_request_sense_cmd(&pc);
+-		if (idefloppy_queue_pc_tail(drive, &pc)) {
++		if (idefloppy_queue_pc_tail(drive, &pc))
+ 			return (-EIO);
+-		}
+ 
+ 		if (floppy->sense_key == 2 &&
+ 		    floppy->asc == 4 &&
+-		    floppy->ascq == 4) {
++		    floppy->ascq == 4)
+ 			progress_indication = floppy->progress_indication;
+-		}
+-		/* Else assume format_unit has finished, and we're
+-		** at 0x10000 */
 +
-+#define FEATURE_SMBUS_PEC	(1 << 0)
-+#define FEATURE_BLOCK_BUFFER	(1 << 1)
-+#define FEATURE_BLOCK_PROC	(1 << 2)
-+#define FEATURE_I2C_BLOCK_READ	(1 << 3)
-+static unsigned int i801_features;
++		/* Else assume format_unit has finished, and we're at 0x10000 */
+ 	} else {
+-		atapi_status_t status;
+ 		unsigned long flags;
++		u8 stat;
  
- static int i801_transaction(int xact)
+ 		local_irq_save(flags);
+-		status.all = HWIF(drive)->INB(IDE_STATUS_REG);
++		stat = ide_read_status(drive);
+ 		local_irq_restore(flags);
+ 
+-		progress_indication = !status.b.dsc ? 0 : 0x10000;
++		progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
+ 	}
+ 	if (put_user(progress_indication, arg))
+ 		return (-EFAULT);
+@@ -1680,10 +1257,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+ 	return (0);
+ }
+ 
+-/*
+- *	Return the current floppy capacity.
+- */
+-static sector_t idefloppy_capacity (ide_drive_t *drive)
++static sector_t idefloppy_capacity(ide_drive_t *drive)
  {
-@@ -242,7 +257,8 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	unsigned long capacity = floppy->blocks * floppy->bs_factor;
+@@ -1692,16 +1266,12 @@ static sector_t idefloppy_capacity (ide_drive_t *drive)
  }
  
- static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
--					       char read_write, int hwpec)
-+					       char read_write, int command,
-+					       int hwpec)
+ /*
+- *	idefloppy_identify_device checks if we can support a drive,
+- *	based on the ATAPI IDENTIFY command results.
++ * Check whether we can support a drive, based on the ATAPI IDENTIFY command
++ * results.
+  */
+-static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
++static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
  {
- 	int i, len;
- 	int smbcmd;
-@@ -259,16 +275,24 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
- 	}
+ 	struct idefloppy_id_gcw gcw;
+-#if IDEFLOPPY_DEBUG_INFO
+-	u16 mask,i;
+-	char buffer[80];
+-#endif /* IDEFLOPPY_DEBUG_INFO */
  
- 	for (i = 1; i <= len; i++) {
--		if (i == len && read_write == I2C_SMBUS_READ)
--			smbcmd = I801_BLOCK_LAST;
--		else
--			smbcmd = I801_BLOCK_DATA;
-+		if (i == len && read_write == I2C_SMBUS_READ) {
-+			if (command == I2C_SMBUS_I2C_BLOCK_DATA)
-+				smbcmd = I801_I2C_BLOCK_LAST;
-+			else
-+				smbcmd = I801_BLOCK_LAST;
-+		} else {
-+			if (command == I2C_SMBUS_I2C_BLOCK_DATA
-+			 && read_write == I2C_SMBUS_READ)
-+				smbcmd = I801_I2C_BLOCK_DATA;
-+			else
-+				smbcmd = I801_BLOCK_DATA;
-+		}
- 		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
+ 	*((u16 *) &gcw) = id->config;
  
- 		dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
--			"ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
-+			"ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
- 			inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
--			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
-+			inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
+@@ -1710,103 +1280,23 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
+ 	if ((gcw.device_type == 5) &&
+ 	    !strstr(id->model, "CD-ROM") &&
+ 	    strstr(id->model, "ZIP"))
+-		gcw.device_type = 0;			
++		gcw.device_type = 0;
+ #endif
  
- 		/* Make sure the SMBus host is ready to start transmitting */
- 		temp = inb_p(SMBHSTSTS);
-@@ -332,7 +356,8 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
- 			dev_dbg(&I801_dev->dev, "Error: no response!\n");
- 		}
+-#if IDEFLOPPY_DEBUG_INFO
+-	printk(KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n");
+-	switch (gcw.protocol) {
+-		case 0: case 1: sprintf(buffer, "ATA");break;
+-		case 2:	sprintf(buffer, "ATAPI");break;
+-		case 3: sprintf(buffer, "Reserved (Unknown to ide-floppy)");break;
+-	}
+-	printk(KERN_INFO "Protocol Type: %s\n", buffer);
+-	switch (gcw.device_type) {
+-		case 0: sprintf(buffer, "Direct-access Device");break;
+-		case 1: sprintf(buffer, "Streaming Tape Device");break;
+-		case 2: case 3: case 4: sprintf (buffer, "Reserved");break;
+-		case 5: sprintf(buffer, "CD-ROM Device");break;
+-		case 6: sprintf(buffer, "Reserved");
+-		case 7: sprintf(buffer, "Optical memory Device");break;
+-		case 0x1f: sprintf(buffer, "Unknown or no Device type");break;
+-		default: sprintf(buffer, "Reserved");
+-	}
+-	printk(KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer);
+-	printk(KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No");	
+-	switch (gcw.drq_type) {
+-		case 0: sprintf(buffer, "Microprocessor DRQ");break;
+-		case 1: sprintf(buffer, "Interrupt DRQ");break;
+-		case 2: sprintf(buffer, "Accelerated DRQ");break;
+-		case 3: sprintf(buffer, "Reserved");break;
+-	}
+-	printk(KERN_INFO "Command Packet DRQ Type: %s\n", buffer);
+-	switch (gcw.packet_size) {
+-		case 0: sprintf(buffer, "12 bytes");break;
+-		case 1: sprintf(buffer, "16 bytes");break;
+-		default: sprintf(buffer, "Reserved");break;
+-	}
+-	printk(KERN_INFO "Command Packet Size: %s\n", buffer);
+-	printk(KERN_INFO "Model: %.40s\n",id->model);
+-	printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev);
+-	printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no);
+-	printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512);
+-	printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
+-	printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO);
+-	printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA);
+-	printk(KERN_INFO "Single Word DMA supported modes:\n");
+-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
+-		if (id->dma_1word & mask)
+-			printk(KERN_INFO "   Mode %d%s\n", i,
+-			(id->dma_1word & (mask << 8)) ? " (active)" : "");
+-	}
+-	printk(KERN_INFO "Multi Word DMA supported modes:\n");
+-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
+-		if (id->dma_mword & mask)
+-			printk(KERN_INFO "   Mode %d%s\n", i,
+-			(id->dma_mword & (mask << 8)) ? " (active)" : "");
+-	}
+-	if (id->field_valid & 0x0002) {
+-		printk(KERN_INFO "Enhanced PIO Modes: %s\n",
+-			id->eide_pio_modes & 1 ? "Mode 3":"None");
+-		if (id->eide_dma_min == 0)
+-			sprintf(buffer, "Not supported");
+-		else
+-			sprintf(buffer, "%d ns",id->eide_dma_min);
+-		printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer);
+-		if (id->eide_dma_time == 0)
+-			sprintf(buffer, "Not supported");
+-		else
+-			sprintf(buffer, "%d ns",id->eide_dma_time);
+-		printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer);
+-		if (id->eide_pio == 0)
+-			sprintf(buffer, "Not supported");
+-		else
+-			sprintf(buffer, "%d ns",id->eide_pio);
+-		printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n",
+-			buffer);
+-		if (id->eide_pio_iordy == 0)
+-			sprintf(buffer, "Not supported");
+-		else
+-			sprintf(buffer, "%d ns",id->eide_pio_iordy);
+-		printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer);
+-	} else
+-		printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n");
+-#endif /* IDEFLOPPY_DEBUG_INFO */
+-
+ 	if (gcw.protocol != 2)
+-		printk(KERN_ERR "ide-floppy: Protocol is not ATAPI\n");
++		printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
++				gcw.protocol);
+ 	else if (gcw.device_type != 0)
+-		printk(KERN_ERR "ide-floppy: Device type is not set to floppy\n");
++		printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
++				"to floppy\n", gcw.device_type);
+ 	else if (!gcw.removable)
+ 		printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
+ 	else if (gcw.drq_type == 3) {
+-		printk(KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type);
++		printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
++				"supported\n", gcw.drq_type);
+ 	} else if (gcw.packet_size != 0) {
+-		printk(KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n");
++		printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
++				"bytes long\n", gcw.packet_size);
+ 	} else
+ 		return 1;
+ 	return 0;
+@@ -1817,59 +1307,53 @@ static void idefloppy_add_settings(ide_drive_t *drive)
+ {
+ 	idefloppy_floppy_t *floppy = drive->driver_data;
  
--		if (i == 1 && read_write == I2C_SMBUS_READ) {
-+		if (i == 1 && read_write == I2C_SMBUS_READ
-+		 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
- 			len = inb_p(SMBHSTDAT0);
- 			if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
- 				return -1;
-@@ -353,9 +378,9 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
- 				temp);
- 		}
- 		dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
--			"ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i,
-+			"ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
- 			inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
--			inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT));
-+			inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
+-/*
+- *			drive	setting name	read/write	data type	min	max	mul_factor	div_factor	data pointer		set function
+- */
+-	ide_add_setting(drive,	"bios_cyl",	SETTING_RW,	TYPE_INT,	0,	1023,		1,		1,	&drive->bios_cyl,	NULL);
+-	ide_add_setting(drive,	"bios_head",	SETTING_RW,	TYPE_BYTE,	0,	255,		1,		1,	&drive->bios_head,	NULL);
+-	ide_add_setting(drive,	"bios_sect",	SETTING_RW,	TYPE_BYTE,	0,	63,		1,		1,	&drive->bios_sect,	NULL);
+-	ide_add_setting(drive,	"ticks",	SETTING_RW,	TYPE_BYTE,	0,	255,		1,		1,	&floppy->ticks,		NULL);
++	ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1,
++			&drive->bios_cyl, NULL);
++	ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
++			&drive->bios_head, NULL);
++	ide_add_setting(drive, "bios_sect", SETTING_RW,	TYPE_BYTE, 0,  63, 1, 1,
++			&drive->bios_sect, NULL);
++	ide_add_setting(drive, "ticks",	   SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
++			&floppy->ticks,	 NULL);
+ }
+ #else
+ static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
+ #endif
  
- 		if (result < 0)
- 			return result;
-@@ -384,33 +409,38 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
- 			pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
- 			pci_write_config_byte(I801_dev, SMBHSTCFG,
- 					      hostc | SMBHSTCFG_I2C_EN);
--		} else {
-+		} else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
- 			dev_err(&I801_dev->dev,
--				"I2C_SMBUS_I2C_BLOCK_READ not DB!\n");
-+				"I2C block read is unsupported!\n");
- 			return -1;
- 		}
- 	}
+-/*
+- *	Driver initialization.
+- */
+-static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
++static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
+ {
+ 	struct idefloppy_id_gcw gcw;
  
--	if (read_write == I2C_SMBUS_WRITE) {
-+	if (read_write == I2C_SMBUS_WRITE
-+	 || command == I2C_SMBUS_I2C_BLOCK_DATA) {
- 		if (data->block[0] < 1)
- 			data->block[0] = 1;
- 		if (data->block[0] > I2C_SMBUS_BLOCK_MAX)
- 			data->block[0] = I2C_SMBUS_BLOCK_MAX;
- 	} else {
--		data->block[0] = 32;	/* max for reads */
-+		data->block[0] = 32;	/* max for SMBus block reads */
+ 	*((u16 *) &gcw) = drive->id->config;
+ 	floppy->pc = floppy->pc_stack;
+ 	if (gcw.drq_type == 1)
+-		set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
++		floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
+ 	/*
+-	 *	We used to check revisions here. At this point however
+-	 *	I'm giving up. Just assume they are all broken, its easier.
++	 * We used to check revisions here. At this point however I'm giving up.
++	 * Just assume they are all broken, its easier.
+ 	 *
+-	 *	The actual reason for the workarounds was likely
+-	 *	a driver bug after all rather than a firmware bug,
+-	 *	and the workaround below used to hide it. It should
+-	 *	be fixed as of version 1.9, but to be on the safe side
+-	 *	we'll leave the limitation below for the 2.2.x tree.
++	 * The actual reason for the workarounds was likely a driver bug after
++	 * all rather than a firmware bug, and the workaround below used to hide
++	 * it. It should be fixed as of version 1.9, but to be on the safe side
++	 * we'll leave the limitation below for the 2.2.x tree.
+ 	 */
+-
+ 	if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
+-		set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags);
++		floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
+ 		/* This value will be visible in the /proc/ide/hdx/settings */
+ 		floppy->ticks = IDEFLOPPY_TICKS_DELAY;
+ 		blk_queue_max_sectors(drive->queue, 64);
  	}
  
--	if (isich4 && i801_set_block_buffer_mode() == 0 )
-+	if ((i801_features & FEATURE_BLOCK_BUFFER)
-+	 && !(command == I2C_SMBUS_I2C_BLOCK_DATA
-+	      && read_write == I2C_SMBUS_READ)
-+	 && i801_set_block_buffer_mode() == 0)
- 		result = i801_block_transaction_by_block(data, read_write,
- 							 hwpec);
- 	else
- 		result = i801_block_transaction_byte_by_byte(data, read_write,
--							     hwpec);
-+							     command, hwpec);
- 
- 	if (result == 0 && hwpec)
- 		i801_wait_hwpec();
- 
--	if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
-+	if (command == I2C_SMBUS_I2C_BLOCK_DATA
-+	 && read_write == I2C_SMBUS_WRITE) {
- 		/* restore saved configuration register value */
- 		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
+ 	/*
+-	*      Guess what?  The IOMEGA Clik! drive also needs the
+-	*      above fix.  It makes nasty clicking noises without
+-	*      it, so please don't remove this.
+-	*/
++	 * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
++	 * nasty clicking noises without it, so please don't remove this.
++	 */
+ 	if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
+ 		blk_queue_max_sectors(drive->queue, 64);
+-		set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
++		floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
  	}
-@@ -426,7 +456,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
- 	int block = 0;
- 	int ret, xact = 0;
  
--	hwpec = isich4 && (flags & I2C_CLIENT_PEC)
-+	hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
- 		&& size != I2C_SMBUS_QUICK
- 		&& size != I2C_SMBUS_I2C_BLOCK_DATA;
+-
+-	(void) idefloppy_get_capacity(drive);
++	(void) ide_floppy_get_capacity(drive);
+ 	idefloppy_add_settings(drive);
+ }
  
-@@ -462,12 +492,23 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
- 		xact = I801_WORD_DATA;
- 		break;
- 	case I2C_SMBUS_BLOCK_DATA:
--	case I2C_SMBUS_I2C_BLOCK_DATA:
- 		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
- 		       SMBHSTADD);
- 		outb_p(command, SMBHSTCMD);
- 		block = 1;
- 		break;
-+	case I2C_SMBUS_I2C_BLOCK_DATA:
-+		/* NB: page 240 of ICH5 datasheet shows that the R/#W
-+		 * bit should be cleared here, even when reading */
-+		outb_p((addr & 0x7f) << 1, SMBHSTADD);
-+		if (read_write == I2C_SMBUS_READ) {
-+			/* NB: page 240 of ICH5 datasheet also shows
-+			 * that DATA1 is the cmd field when reading */
-+			outb_p(command, SMBHSTDAT1);
-+		} else
-+			outb_p(command, SMBHSTCMD);
-+		block = 1;
-+		break;
- 	case I2C_SMBUS_PROC_CALL:
- 	default:
- 		dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
-@@ -487,7 +528,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
- 	/* Some BIOSes don't like it when PEC is enabled at reboot or resume
- 	   time, so we forcibly disable it after every transaction. Turn off
- 	   E32B for the same reason. */
--	if (hwpec)
-+	if (hwpec || block)
- 		outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
- 		       SMBAUXCTL);
+@@ -1885,7 +1369,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
+ 	ide_floppy_put(floppy);
+ }
  
-@@ -514,9 +555,11 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
- static u32 i801_func(struct i2c_adapter *adapter)
+-static void ide_floppy_release(struct kref *kref)
++static void idefloppy_cleanup_obj(struct kref *kref)
  {
- 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
--	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
--	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
--	     | (isich4 ? I2C_FUNC_SMBUS_PEC : 0);
-+	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
-+	       I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
-+	       ((i801_features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) |
-+	       ((i801_features & FEATURE_I2C_BLOCK_READ) ?
-+		I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0);
+ 	struct ide_floppy_obj *floppy = to_ide_floppy(kref);
+ 	ide_drive_t *drive = floppy->drive;
+@@ -1898,19 +1382,19 @@ static void ide_floppy_release(struct kref *kref)
  }
  
- static const struct i2c_algorithm smbus_algorithm = {
-@@ -556,8 +599,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
- 	int err;
+ #ifdef CONFIG_IDE_PROC_FS
+-static int proc_idefloppy_read_capacity
+-	(char *page, char **start, off_t off, int count, int *eof, void *data)
++static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
++		int count, int *eof, void *data)
+ {
+ 	ide_drive_t*drive = (ide_drive_t *)data;
+ 	int len;
  
- 	I801_dev = dev;
-+	i801_features = 0;
- 	switch (dev->device) {
--	case PCI_DEVICE_ID_INTEL_82801DB_3:
- 	case PCI_DEVICE_ID_INTEL_82801EB_3:
- 	case PCI_DEVICE_ID_INTEL_ESB_4:
- 	case PCI_DEVICE_ID_INTEL_ICH6_16:
-@@ -565,11 +608,13 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
- 	case PCI_DEVICE_ID_INTEL_ESB2_17:
- 	case PCI_DEVICE_ID_INTEL_ICH8_5:
- 	case PCI_DEVICE_ID_INTEL_ICH9_6:
-+		i801_features |= FEATURE_I2C_BLOCK_READ;
-+		/* fall through */
-+	case PCI_DEVICE_ID_INTEL_82801DB_3:
- 	case PCI_DEVICE_ID_INTEL_TOLAPAI_1:
--		isich4 = 1;
-+		i801_features |= FEATURE_SMBUS_PEC;
-+		i801_features |= FEATURE_BLOCK_BUFFER;
- 		break;
--	default:
--		isich4 = 0;
- 	}
+-	len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive));
+-	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
++	len = sprintf(page, "%llu\n", (long long)idefloppy_capacity(drive));
++	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
+ }
  
- 	err = pci_enable_device(dev);
-@@ -610,6 +655,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
- 	else
- 		dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n");
+ static ide_proc_entry_t idefloppy_proc[] = {
+-	{ "capacity",	S_IFREG|S_IRUGO,	proc_idefloppy_read_capacity, NULL },
+-	{ "geometry",	S_IFREG|S_IRUGO,	proc_ide_read_geometry,	NULL },
++	{ "capacity",	S_IFREG|S_IRUGO, proc_idefloppy_read_capacity,	NULL },
++	{ "geometry",	S_IFREG|S_IRUGO, proc_ide_read_geometry,	NULL },
+ 	{ NULL, 0, NULL, NULL }
+ };
+ #endif	/* CONFIG_IDE_PROC_FS */
+@@ -1945,9 +1429,10 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
+ 	idefloppy_pc_t pc;
+ 	int ret = 0;
  
-+	/* Clear special mode bits */
-+	if (i801_features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER))
-+		outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B),
-+		       SMBAUXCTL);
-+
- 	/* set up the sysfs linkage to our parent device */
- 	i801_adapter.dev.parent = &dev->dev;
+-	debug_log(KERN_INFO "Reached idefloppy_open\n");
++	debug_log("Reached %s\n", __func__);
  
-@@ -678,9 +728,8 @@ static void __exit i2c_i801_exit(void)
- 	pci_unregister_driver(&i801_driver);
- }
+-	if (!(floppy = ide_floppy_get(disk)))
++	floppy = ide_floppy_get(disk);
++	if (!floppy)
+ 		return -ENXIO;
  
--MODULE_AUTHOR ("Frodo Looijaard <frodol at dds.nl>, "
--		"Philip Edelbrock <phil at netroedge.com>, "
--		"and Mark D. Studebaker <mdsxyz123 at yahoo.com>");
-+MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123 at yahoo.com>, "
-+	      "Jean Delvare <khali at linux-fr.org>");
- MODULE_DESCRIPTION("I801 SMBus driver");
- MODULE_LICENSE("GPL");
+ 	drive = floppy->drive;
+@@ -1955,7 +1440,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
+ 	floppy->openers++;
  
-diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
-index 9b43ff7..7c7eb0c 100644
---- a/drivers/i2c/busses/i2c-ibm_iic.c
-+++ b/drivers/i2c/busses/i2c-ibm_iic.c
-@@ -6,7 +6,7 @@
-  * Copyright (c) 2003, 2004 Zultys Technologies.
-  * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
-  *
-- * Based on original work by 
-+ * Based on original work by
-  * 	Ian DaSilva  <idasilva at mvista.com>
-  *      Armin Kuster <akuster at mvista.com>
-  * 	Matt Porter  <mporter at mvista.com>
-@@ -86,8 +86,8 @@ static void dump_iic_regs(const char* header, struct ibm_iic_private* dev)
- 	       KERN_DEBUG "  sts      = 0x%02x, extsts = 0x%02x\n"
- 	       KERN_DEBUG "  clkdiv   = 0x%02x, xfrcnt = 0x%02x\n"
- 	       KERN_DEBUG "  xtcntlss = 0x%02x, directcntl = 0x%02x\n",
--		in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), 
--		in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), 
-+		in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts),
-+		in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt),
- 		in_8(&iic->xtcntlss), in_8(&iic->directcntl));
- }
- #  define DUMP_REGS(h,dev)	dump_iic_regs((h),(dev))
-@@ -125,7 +125,7 @@ static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable)
- {
- 	out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0);
- }
-- 
-+
- /*
-  * Initialize IIC interface.
-  */
-@@ -134,7 +134,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
+ 	if (floppy->openers == 1) {
+-		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
++		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ 		/* Just in case */
  
- 	DBG("%d: init\n", dev->idx);
--	
-+
- 	/* Clear master address */
- 	out_8(&iic->lmadr, 0);
- 	out_8(&iic->hmadr, 0);
-@@ -160,7 +160,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
+ 		idefloppy_create_test_unit_ready_cmd(&pc);
+@@ -1964,13 +1449,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
+ 			(void) idefloppy_queue_pc_tail(drive, &pc);
+ 		}
  
- 	/* Clear control register */
- 	out_8(&iic->cntl, 0);
+-		if (idefloppy_get_capacity (drive)
++		if (ide_floppy_get_capacity(drive)
+ 		   && (filp->f_flags & O_NDELAY) == 0
+ 		    /*
+-		    ** Allow O_NDELAY to open a drive without a disk, or with
+-		    ** an unreadable disk, so that we can get the format
+-		    ** capacity of the drive or begin the format - Sam
+-		    */
++		     * Allow O_NDELAY to open a drive without a disk, or with an
++		     * unreadable disk, so that we can get the format capacity
++		     * of the drive or begin the format - Sam
++		     */
+ 		    ) {
+ 			ret = -EIO;
+ 			goto out_put_floppy;
+@@ -1980,14 +1465,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
+ 			ret = -EROFS;
+ 			goto out_put_floppy;
+ 		}
+-		set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
++		floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
+ 		/* IOMEGA Clik! drives do not support lock/unlock commands */
+-                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
++		if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ 			idefloppy_create_prevent_cmd(&pc, 1);
+ 			(void) idefloppy_queue_pc_tail(drive, &pc);
+ 		}
+ 		check_disk_change(inode->i_bdev);
+-	} else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
++	} else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
+ 		ret = -EBUSY;
+ 		goto out_put_floppy;
+ 	}
+@@ -2005,17 +1490,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
+ 	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ 	ide_drive_t *drive = floppy->drive;
+ 	idefloppy_pc_t pc;
 -	
+-	debug_log(KERN_INFO "Reached idefloppy_release\n");
 +
- 	/* Enable interrupts if possible */
- 	iic_interrupt_mode(dev, dev->irq >= 0);
- 
-@@ -171,7 +171,7 @@ static void iic_dev_init(struct ibm_iic_private* dev)
- 	DUMP_REGS("iic_init", dev);
- }
++	debug_log("Reached %s\n", __func__);
  
--/* 
-+/*
-  * Reset IIC interface
-  */
- static void iic_dev_reset(struct ibm_iic_private* dev)
-@@ -179,42 +179,42 @@ static void iic_dev_reset(struct ibm_iic_private* dev)
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
- 	int i;
- 	u8 dc;
--	
-+
- 	DBG("%d: soft reset\n", dev->idx);
- 	DUMP_REGS("reset", dev);
--	
-+
-     	/* Place chip in the reset state */
- 	out_8(&iic->xtcntlss, XTCNTLSS_SRST);
--	
-+
- 	/* Check if bus is free */
--	dc = in_8(&iic->directcntl);	
-+	dc = in_8(&iic->directcntl);
- 	if (!DIRCTNL_FREE(dc)){
- 		DBG("%d: trying to regain bus control\n", dev->idx);
--	
-+
- 		/* Try to set bus free state */
--		out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);	
--	
-+		out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC);
-+
- 		/* Wait until we regain bus control */
- 		for (i = 0; i < 100; ++i){
- 			dc = in_8(&iic->directcntl);
- 			if (DIRCTNL_FREE(dc))
- 				break;
--			
-+
- 			/* Toggle SCL line */
- 			dc ^= DIRCNTL_SCC;
- 			out_8(&iic->directcntl, dc);
- 			udelay(10);
- 			dc ^= DIRCNTL_SCC;
- 			out_8(&iic->directcntl, dc);
--			
-+
- 			/* be nice */
- 			cond_resched();
+ 	if (floppy->openers == 1) {
+ 		/* IOMEGA Clik! drives do not support lock/unlock commands */
+-                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
++		if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
+ 			idefloppy_create_prevent_cmd(&pc, 0);
+ 			(void) idefloppy_queue_pc_tail(drive, &pc);
  		}
+ 
+-		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
++		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
  	}
--	
-+
- 	/* Remove reset */
- 	out_8(&iic->xtcntlss, 0);
--	
-+
- 	/* Reinitialize interface */
- 	iic_dev_init(dev);
- }
-@@ -324,14 +324,14 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
- {
- 	struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id;
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
--	
--	DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", 
-+
-+	DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n",
- 	     dev->idx, in_8(&iic->sts), in_8(&iic->extsts));
--	
-+
- 	/* Acknowledge IRQ and wakeup iic_wait_for_tc */
- 	out_8(&iic->sts, STS_IRQA | STS_SCMP);
- 	wake_up_interruptible(&dev->wq);
--	
-+
- 	return IRQ_HANDLED;
+ 
+ 	floppy->openers--;
+@@ -2036,64 +1521,105 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+ 	return 0;
  }
  
-@@ -341,19 +341,19 @@ static irqreturn_t iic_handler(int irq, void *dev_id)
-  */
- static int iic_xfer_result(struct ibm_iic_private* dev)
- {
--	volatile struct iic_regs __iomem *iic = dev->vaddr;	
--	
-+	volatile struct iic_regs __iomem *iic = dev->vaddr;
++static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc,
++			       unsigned long arg, unsigned int cmd)
++{
++	if (floppy->openers > 1)
++		return -EBUSY;
 +
- 	if (unlikely(in_8(&iic->sts) & STS_ERR)){
--		DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, 
-+		DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx,
- 			in_8(&iic->extsts));
--				
++	/* The IOMEGA Clik! Drive doesn't support this command -
++	 * no room for an eject mechanism */
++	if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
++		int prevent = arg ? 1 : 0;
 +
- 		/* Clear errors and possible pending IRQs */
--		out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | 
-+		out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD |
- 			EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA);
--			
++		if (cmd == CDROMEJECT)
++			prevent = 0;
 +
- 		/* Flush master data buffer */
- 		out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
--		
++		idefloppy_create_prevent_cmd(pc, prevent);
++		(void) idefloppy_queue_pc_tail(floppy->drive, pc);
++	}
 +
- 		/* Is bus free?
- 		 * If error happened during combined xfer
- 		 * IIC interface is usually stuck in some strange
-@@ -376,11 +376,11 @@ static void iic_abort_xfer(struct ibm_iic_private* dev)
- {
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
- 	unsigned long x;
--	
++	if (cmd == CDROMEJECT) {
++		idefloppy_create_start_stop_cmd(pc, 2);
++		(void) idefloppy_queue_pc_tail(floppy->drive, pc);
++	}
 +
- 	DBG("%d: iic_abort_xfer\n", dev->idx);
--	
++	return 0;
++}
 +
- 	out_8(&iic->cntl, CNTL_HMT);
--	
++static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
++				  int __user *arg)
++{
++	int blocks, length, flags, err = 0;
++	idefloppy_pc_t pc;
 +
- 	/*
- 	 * Wait for the abort command to complete.
- 	 * It's not worth to be optimized, just poll (timeout >= 1 tick)
-@@ -405,13 +405,13 @@ static void iic_abort_xfer(struct ibm_iic_private* dev)
-  * Returns the number of transferred bytes or error (<0)
-  */
- static int iic_wait_for_tc(struct ibm_iic_private* dev){
--	
++	if (floppy->openers > 1) {
++		/* Don't format if someone is using the disk */
++		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
++		return -EBUSY;
++	}
 +
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
- 	int ret = 0;
--	
++	floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
 +
- 	if (dev->irq >= 0){
- 		/* Interrupt mode */
--		ret = wait_event_interruptible_timeout(dev->wq, 
-+		ret = wait_event_interruptible_timeout(dev->wq,
- 			!(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ);
- 
- 		if (unlikely(ret < 0))
-@@ -424,37 +424,37 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){
- 	else {
- 		/* Polling mode */
- 		unsigned long x = jiffies + dev->adap.timeout * HZ;
--		
++	/*
++	 * Send ATAPI_FORMAT_UNIT to the drive.
++	 *
++	 * Userland gives us the following structure:
++	 *
++	 * struct idefloppy_format_command {
++	 *        int nblocks;
++	 *        int blocksize;
++	 *        int flags;
++	 *        } ;
++	 *
++	 * flags is a bitmask, currently, the only defined flag is:
++	 *
++	 *        0x01 - verify media after format.
++	 */
++	if (get_user(blocks, arg) ||
++			get_user(length, arg+1) ||
++			get_user(flags, arg+2)) {
++		err = -EFAULT;
++		goto out;
++	}
 +
- 		while (in_8(&iic->sts) & STS_PT){
- 			if (unlikely(time_after(jiffies, x))){
- 				DBG("%d: poll timeout\n", dev->idx);
- 				ret = -ETIMEDOUT;
- 				break;
- 			}
--		
++	(void) idefloppy_get_sfrp_bit(floppy->drive);
++	idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
 +
- 			if (unlikely(signal_pending(current))){
- 				DBG("%d: poll interrupted\n", dev->idx);
- 				ret = -ERESTARTSYS;
- 				break;
- 			}
- 			schedule();
--		}	
-+		}
- 	}
--	
++	if (idefloppy_queue_pc_tail(floppy->drive, &pc))
++		err = -EIO;
 +
- 	if (unlikely(ret < 0))
- 		iic_abort_xfer(dev);
- 	else
- 		ret = iic_xfer_result(dev);
--	
++out:
++	if (err)
++		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
++	return err;
++}
 +
- 	DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret);
--	
 +
- 	return ret;
- }
+ static int idefloppy_ioctl(struct inode *inode, struct file *file,
+ 			unsigned int cmd, unsigned long arg)
+ {
+ 	struct block_device *bdev = inode->i_bdev;
+ 	struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
+ 	ide_drive_t *drive = floppy->drive;
++	idefloppy_pc_t pc;
+ 	void __user *argp = (void __user *)arg;
+ 	int err;
+-	int prevent = (arg) ? 1 : 0;
+-	idefloppy_pc_t pc;
  
- /*
-  * Low level master transfer routine
-  */
--static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, 
-+static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
- 			  int combined_xfer)
+ 	switch (cmd) {
+ 	case CDROMEJECT:
+-		prevent = 0;
+ 		/* fall through */
+ 	case CDROM_LOCKDOOR:
+-		if (floppy->openers > 1)
+-			return -EBUSY;
+-
+-		/* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
+-                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
+-			idefloppy_create_prevent_cmd(&pc, prevent);
+-			(void) idefloppy_queue_pc_tail(drive, &pc);
+-		}
+-		if (cmd == CDROMEJECT) {
+-			idefloppy_create_start_stop_cmd(&pc, 2);
+-			(void) idefloppy_queue_pc_tail(drive, &pc);
+-		}
+-		return 0;
++		return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
+ 	case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
+ 		return 0;
+ 	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
+-		return idefloppy_get_format_capacities(drive, argp);
++		return ide_floppy_get_format_capacities(drive, argp);
+ 	case IDEFLOPPY_IOCTL_FORMAT_START:
+-
+ 		if (!(file->f_mode & 2))
+ 			return -EPERM;
+ 
+-		if (floppy->openers > 1) {
+-			/* Don't format if someone is using the disk */
+-
+-			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
+-				  &floppy->flags);
+-			return -EBUSY;
+-		}
+-
+-		set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+-
+-		err = idefloppy_begin_format(drive, argp);
+-		if (err)
+-			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+-		return err;
+-		/*
+-		** Note, the bit will be cleared when the device is
+-		** closed.  This is the cleanest way to handle the
+-		** situation where the drive does not support
+-		** format progress reporting.
+-		*/
++		return ide_floppy_format_unit(floppy, (int __user *)arg);
+ 	case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
+ 		return idefloppy_get_format_progress(drive, argp);
+ 	}
+@@ -2118,13 +1644,16 @@ static int idefloppy_media_changed(struct gendisk *disk)
  {
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
-@@ -465,48 +465,48 @@ static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm,
- 	u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT;
- 	if (pm->flags & I2C_M_RD)
- 		cntl |= CNTL_RW;
--	
-+
- 	loops = (len + 3) / 4;
- 	for (i = 0; i < loops; ++i, len -= 4){
- 		int count = len > 4 ? 4 : len;
- 		u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT);
--		
-+
- 		if (!(cntl & CNTL_RW))
- 			for (j = 0; j < count; ++j)
- 				out_8((void __iomem *)&iic->mdbuf, *buf++);
--		
-+
- 		if (i < loops - 1)
- 			cmd |= CNTL_CHT;
- 		else if (combined_xfer)
- 			cmd |= CNTL_RPST;
--		
-+
- 		DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd);
--		
-+
- 		/* Start transfer */
- 		out_8(&iic->cntl, cmd);
--		
-+
- 		/* Wait for completion */
- 		ret = iic_wait_for_tc(dev);
+ 	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
+ 	ide_drive_t *drive = floppy->drive;
++	int ret;
  
- 		if (unlikely(ret < 0))
- 			break;
- 		else if (unlikely(ret != count)){
--			DBG("%d: xfer_bytes, requested %d, transfered %d\n", 
-+			DBG("%d: xfer_bytes, requested %d, transfered %d\n",
- 				dev->idx, count, ret);
--			
-+
- 			/* If it's not a last part of xfer, abort it */
- 			if (combined_xfer || (i < loops - 1))
-     				iic_abort_xfer(dev);
--				
-+
- 			ret = -EREMOTEIO;
--			break;				
-+			break;
- 		}
--		
-+
- 		if (cntl & CNTL_RW)
- 			for (j = 0; j < count; ++j)
- 				*buf++ = in_8((void __iomem *)&iic->mdbuf);
+ 	/* do not scan partitions twice if this is a removable device */
+ 	if (drive->attach) {
+ 		drive->attach = 0;
+ 		return 0;
  	}
--	
-+
- 	return ret > 0 ? 0 : ret;
+-	return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
++	ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
++	floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
++	return ret;
  }
  
-@@ -517,10 +517,10 @@ static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg)
+ static int idefloppy_revalidate_disk(struct gendisk *disk)
+@@ -2155,16 +1684,20 @@ static int ide_floppy_probe(ide_drive_t *drive)
+ 		goto failed;
+ 	if (drive->media != ide_floppy)
+ 		goto failed;
+-	if (!idefloppy_identify_device (drive, drive->id)) {
+-		printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);
++	if (!idefloppy_identify_device(drive, drive->id)) {
++		printk(KERN_ERR "ide-floppy: %s: not supported by this version"
++				" of ide-floppy\n", drive->name);
+ 		goto failed;
+ 	}
+ 	if (drive->scsi) {
+-		printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
++		printk(KERN_INFO "ide-floppy: passing drive %s to ide-scsi"
++				" emulation.\n", drive->name);
+ 		goto failed;
+ 	}
+-	if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
+-		printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
++	floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
++	if (!floppy) {
++		printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
++				" structure\n", drive->name);
+ 		goto failed;
+ 	}
+ 
+@@ -2186,7 +1719,7 @@ static int ide_floppy_probe(ide_drive_t *drive)
+ 
+ 	drive->driver_data = floppy;
+ 
+-	idefloppy_setup (drive, floppy);
++	idefloppy_setup(drive, floppy);
+ 
+ 	g->minors = 1 << PARTN_BITS;
+ 	g->driverfs_dev = &drive->gendev;
+@@ -2202,9 +1735,7 @@ failed:
+ 	return -ENODEV;
+ }
+ 
+-MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
+-
+-static void __exit idefloppy_exit (void)
++static void __exit idefloppy_exit(void)
  {
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
- 	u16 addr = msg->addr;
--	
--	DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, 
-+
-+	DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx,
- 		addr, msg->flags & I2C_M_TEN ? 10 : 7);
--	
-+
- 	if (msg->flags & I2C_M_TEN){
- 	    out_8(&iic->cntl, CNTL_AMD);
- 	    out_8(&iic->lmadr, addr);
-@@ -537,15 +537,15 @@ static inline int iic_invalid_address(const struct i2c_msg* p)
- 	return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f));
+ 	driver_unregister(&idefloppy_driver.gen_driver);
  }
+@@ -2219,3 +1750,5 @@ MODULE_ALIAS("ide:*m-floppy*");
+ module_init(idefloppy_init);
+ module_exit(idefloppy_exit);
+ MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
++
+diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
+index 0f72b98..709b9e4 100644
+--- a/drivers/ide/ide-generic.c
++++ b/drivers/ide/ide-generic.c
+@@ -14,10 +14,22 @@
  
--static inline int iic_address_neq(const struct i2c_msg* p1, 
-+static inline int iic_address_neq(const struct i2c_msg* p1,
- 				  const struct i2c_msg* p2)
+ static int __init ide_generic_init(void)
  {
--	return (p1->addr != p2->addr) 
-+	return (p1->addr != p2->addr)
- 		|| ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN));
--} 
-+}
++	u8 idx[MAX_HWIFS];
++	int i;
++
+ 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
+ 		ide_get_lock(NULL, NULL); /* for atari only */
  
- /*
-- * Generic master transfer entrypoint. 
-+ * Generic master transfer entrypoint.
-  * Returns the number of processed messages or error (<0)
-  */
- static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-@@ -553,20 +553,20 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
-     	struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
- 	volatile struct iic_regs __iomem *iic = dev->vaddr;
- 	int i, ret = 0;
--	
+-	(void)ideprobe_init();
++	for (i = 0; i < MAX_HWIFS; i++) {
++		ide_hwif_t *hwif = &ide_hwifs[i];
 +
- 	DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
--	
++		if (hwif->io_ports[IDE_DATA_OFFSET] && !hwif->present)
++			idx[i] = i;
++		else
++			idx[i] = 0xff;
++	}
 +
- 	if (!num)
- 		return 0;
--	
++	ide_device_add_all(idx, NULL);
+ 
+ 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
+ 		ide_release_lock();	/* for atari only */
+diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
+index bef781f..3addbe4 100644
+--- a/drivers/ide/ide-io.c
++++ b/drivers/ide/ide-io.c
+@@ -58,15 +58,19 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
+ 			     int uptodate, unsigned int nr_bytes, int dequeue)
+ {
+ 	int ret = 1;
++	int error = 0;
 +
- 	/* Check the sanity of the passed messages.
- 	 * Uhh, generic i2c layer is more suitable place for such code...
++	if (uptodate <= 0)
++		error = uptodate ? uptodate : -EIO;
+ 
+ 	/*
+ 	 * if failfast is set on a request, override number of sectors and
+ 	 * complete the whole request right now
  	 */
- 	if (unlikely(iic_invalid_address(&msgs[0]))){
--		DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx, 
-+		DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx,
- 			msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7);
- 		return -EINVAL;
--	}		
-+	}
- 	for (i = 0; i < num; ++i){
- 		if (unlikely(msgs[i].len <= 0)){
- 			if (num == 1 && !msgs[0].len){
-@@ -576,7 +576,7 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
- 				 */
- 				return iic_smbus_quick(dev, &msgs[0]);
- 			}
--			DBG("%d: invalid len %d in msg[%d]\n", dev->idx, 
-+			DBG("%d: invalid len %d in msg[%d]\n", dev->idx,
- 				msgs[i].len, i);
- 			return -EINVAL;
- 		}
-@@ -585,34 +585,34 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
- 			return -EINVAL;
- 		}
+-	if (blk_noretry_request(rq) && end_io_error(uptodate))
++	if (blk_noretry_request(rq) && error)
+ 		nr_bytes = rq->hard_nr_sectors << 9;
+ 
+-	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
++	if (!blk_fs_request(rq) && error && !rq->errors)
+ 		rq->errors = -EIO;
+ 
+ 	/*
+@@ -75,17 +79,12 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
+ 	 */
+ 	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+ 		drive->state = 0;
+-		HWGROUP(drive)->hwif->ide_dma_on(drive);
++		ide_dma_on(drive);
  	}
--	
-+
- 	/* Check bus state */
- 	if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){
- 		DBG("%d: iic_xfer, bus is not free\n", dev->idx);
--		
-+
- 		/* Usually it means something serious has happend.
- 		 * We *cannot* have unfinished previous transfer
- 		 * so it doesn't make any sense to try to stop it.
--		 * Probably we were not able to recover from the 
-+		 * Probably we were not able to recover from the
- 		 * previous error.
- 		 * The only *reasonable* thing I can think of here
- 		 * is soft reset.  --ebs
- 		 */
- 		iic_dev_reset(dev);
--		
-+
- 		if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){
- 			DBG("%d: iic_xfer, bus is still not free\n", dev->idx);
- 			return -EREMOTEIO;
- 		}
--	} 
-+	}
- 	else {
- 		/* Flush master data buffer (just in case) */
- 		out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB);
+ 
+-	if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
+-		add_disk_randomness(rq->rq_disk);
+-		if (dequeue) {
+-			if (!list_empty(&rq->queuelist))
+-				blkdev_dequeue_request(rq);
++	if (!__blk_end_request(rq, error, nr_bytes)) {
++		if (dequeue)
+ 			HWGROUP(drive)->rq = NULL;
+-		}
+-		end_that_request_last(rq, uptodate);
+ 		ret = 0;
  	}
--	
-+
- 	/* Load slave address */
- 	iic_address(dev, &msgs[0]);
--	
-+
- 	/* Do real transfer */
-     	for (i = 0; i < num && !ret; ++i)
- 		ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1);
-@@ -648,7 +648,7 @@ static inline u8 iic_clckdiv(unsigned int opb)
  
- 	/* Convert to MHz */
- 	opb /= 1000000;
--	
-+
- 	if (opb < 20 || opb > 150){
- 		printk(KERN_CRIT "ibm-iic: invalid OPB clock frequency %u MHz\n",
- 			opb);
-@@ -666,7 +666,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- 	struct i2c_adapter* adap;
- 	struct ocp_func_iic_data* iic_data = ocp->def->additions;
- 	int ret;
--	
-+
- 	if (!iic_data)
- 		printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
- 			ocp->def->index);
-@@ -679,7 +679,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
+@@ -189,18 +188,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
+ 			return ide_stopped;
+ 		}
+ 		if (ide_id_has_flush_cache_ext(drive->id))
+-			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
++			args->tf.command = WIN_FLUSH_CACHE_EXT;
+ 		else
+-			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
+-		args->command_type = IDE_DRIVE_TASK_NO_DATA;
+-		args->handler	   = &task_no_data_intr;
+-		return do_rw_taskfile(drive, args);
++			args->tf.command = WIN_FLUSH_CACHE;
++		goto out_do_tf;
  
- 	dev->idx = ocp->def->index;
- 	ocp_set_drvdata(ocp, dev);
--	
-+
- 	if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
- 				"ibm_iic")) {
- 		ret = -EBUSY;
-@@ -692,7 +692,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- 		ret = -ENXIO;
- 		goto fail2;
+ 	case idedisk_pm_standby:	/* Suspend step 2 (standby) */
+-		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
+-		args->command_type = IDE_DRIVE_TASK_NO_DATA;
+-		args->handler	   = &task_no_data_intr;
+-		return do_rw_taskfile(drive, args);
++		args->tf.command = WIN_STANDBYNOW1;
++		goto out_do_tf;
+ 
+ 	case idedisk_pm_restore_pio:	/* Resume step 1 (restore PIO) */
+ 		ide_set_max_pio(drive);
+@@ -214,10 +209,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
+ 		return ide_stopped;
+ 
+ 	case idedisk_pm_idle:		/* Resume step 2 (idle) */
+-		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
+-		args->command_type = IDE_DRIVE_TASK_NO_DATA;
+-		args->handler = task_no_data_intr;
+-		return do_rw_taskfile(drive, args);
++		args->tf.command = WIN_IDLEIMMEDIATE;
++		goto out_do_tf;
+ 
+ 	case ide_pm_restore_dma:	/* Resume step 3 (restore DMA) */
+ 		/*
+@@ -225,9 +218,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
+ 		 * we could be smarter and check for current xfer_speed
+ 		 * in struct drive etc...
+ 		 */
+-		if (drive->hwif->ide_dma_on == NULL)
++		if (drive->hwif->dma_host_set == NULL)
+ 			break;
+-		drive->hwif->dma_off_quietly(drive);
+ 		/*
+ 		 * TODO: respect ->using_dma setting
+ 		 */
+@@ -236,6 +228,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
  	}
--	
+ 	pm->pm_step = ide_pm_state_completed;
+ 	return ide_stopped;
 +
- 	init_waitqueue_head(&dev->wq);
++out_do_tf:
++	args->tf_flags	 = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	args->data_phase = TASKFILE_NO_DATA;
++	return do_rw_taskfile(drive, args);
+ }
  
- 	dev->irq = iic_force_poll ? -1 : ocp->def->irq;
-@@ -702,29 +702,29 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- 		 */
- 		iic_interrupt_mode(dev, 0);
- 		if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
--			printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n", 
-+			printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
- 				dev->idx, dev->irq);
--			/* Fallback to the polling mode */	
-+			/* Fallback to the polling mode */
- 			dev->irq = -1;
- 		}
+ /**
+@@ -292,12 +289,54 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
+ 		drive->blocked = 0;
+ 		blk_start_queue(drive->queue);
  	}
--	
+-	blkdev_dequeue_request(rq);
+ 	HWGROUP(drive)->rq = NULL;
+-	end_that_request_last(rq, 1);
++	if (__blk_end_request(rq, 0, 0))
++		BUG();
+ 	spin_unlock_irqrestore(&ide_lock, flags);
+ }
+ 
++void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
++{
++	ide_hwif_t *hwif = drive->hwif;
++	struct ide_taskfile *tf = &task->tf;
 +
- 	if (dev->irq < 0)
--		printk(KERN_WARNING "ibm-iic%d: using polling mode\n", 
-+		printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
- 			dev->idx);
--		
++	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
++		u16 data = hwif->INW(IDE_DATA_REG);
 +
- 	/* Board specific settings */
- 	dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
--	
--	/* clckdiv is the same for *all* IIC interfaces, 
++		tf->data = data & 0xff;
++		tf->hob_data = (data >> 8) & 0xff;
++	}
 +
-+	/* clckdiv is the same for *all* IIC interfaces,
- 	 * but I'd rather make a copy than introduce another global. --ebs
- 	 */
- 	dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
- 	DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
--	
++	/* be sure we're looking at the low order bits */
++	hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
 +
- 	/* Initialize IIC interface */
- 	iic_dev_init(dev);
--	
++	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
++		tf->nsect  = hwif->INB(IDE_NSECTOR_REG);
++	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
++		tf->lbal   = hwif->INB(IDE_SECTOR_REG);
++	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
++		tf->lbam   = hwif->INB(IDE_LCYL_REG);
++	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
++		tf->lbah   = hwif->INB(IDE_HCYL_REG);
++	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
++		tf->device = hwif->INB(IDE_SELECT_REG);
 +
- 	/* Register it with i2c layer */
- 	adap = &dev->adap;
- 	adap->dev.parent = &ocp->dev;
-@@ -736,7 +736,6 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- 	adap->client_register = NULL;
- 	adap->client_unregister = NULL;
- 	adap->timeout = 1;
--	adap->retries = 1;
- 
- 	/*
- 	 * If "dev->idx" is negative we consider it as zero.
-@@ -750,24 +749,24 @@ static int __devinit iic_probe(struct ocp_device *ocp){
- 			dev->idx);
- 		goto fail;
- 	}
--	
++	if (task->tf_flags & IDE_TFLAG_LBA48) {
++		hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
 +
- 	printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
- 		dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
- 
- 	return 0;
- 
--fail:	
-+fail:
- 	if (dev->irq >= 0){
- 		iic_interrupt_mode(dev, 0);
- 		free_irq(dev->irq, dev);
--	}	
++		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
++			tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
++		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
++			tf->hob_nsect   = hwif->INB(IDE_NSECTOR_REG);
++		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
++			tf->hob_lbal    = hwif->INB(IDE_SECTOR_REG);
++		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
++			tf->hob_lbam    = hwif->INB(IDE_LCYL_REG);
++		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
++			tf->hob_lbah    = hwif->INB(IDE_HCYL_REG);
 +	}
++}
++
+ /**
+  *	ide_end_drive_cmd	-	end an explicit drive command
+  *	@drive: command 
+@@ -314,7 +353,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
+  
+ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+ 	unsigned long flags;
+ 	struct request *rq;
  
- 	iounmap(dev->vaddr);
--fail2:	
-+fail2:
- 	release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
- fail1:
- 	ocp_set_drvdata(ocp, NULL);
--	kfree(dev);	
-+	kfree(dev);
- 	return ret;
- }
+@@ -322,61 +360,18 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
+ 	rq = HWGROUP(drive)->rq;
+ 	spin_unlock_irqrestore(&ide_lock, flags);
  
-@@ -783,13 +782,13 @@ static void __devexit iic_remove(struct ocp_device *ocp)
- 			dev->idx);
- 		/* That's *very* bad, just shutdown IRQ ... */
- 		if (dev->irq >= 0){
--		    iic_interrupt_mode(dev, 0);	
-+		    iic_interrupt_mode(dev, 0);
- 		    free_irq(dev->irq, dev);
- 		    dev->irq = -1;
- 		}
- 	} else {
- 		if (dev->irq >= 0){
--		    iic_interrupt_mode(dev, 0);	
-+		    iic_interrupt_mode(dev, 0);
- 		    free_irq(dev->irq, dev);
+-	if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
+-		u8 *args = (u8 *) rq->buffer;
+-		if (rq->errors == 0)
+-			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+-
+-		if (args) {
+-			args[0] = stat;
+-			args[1] = err;
+-			args[2] = hwif->INB(IDE_NSECTOR_REG);
+-		}
+-	} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
+-		u8 *args = (u8 *) rq->buffer;
+-		if (rq->errors == 0)
+-			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+-
+-		if (args) {
+-			args[0] = stat;
+-			args[1] = err;
+-			/* be sure we're looking at the low order bits */
+-			hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
+-			args[2] = hwif->INB(IDE_NSECTOR_REG);
+-			args[3] = hwif->INB(IDE_SECTOR_REG);
+-			args[4] = hwif->INB(IDE_LCYL_REG);
+-			args[5] = hwif->INB(IDE_HCYL_REG);
+-			args[6] = hwif->INB(IDE_SELECT_REG);
+-		}
+-	} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
++	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+ 		ide_task_t *args = (ide_task_t *) rq->special;
+ 		if (rq->errors == 0)
+ 			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+ 			
+ 		if (args) {
+-			if (args->tf_in_flags.b.data) {
+-				u16 data				= hwif->INW(IDE_DATA_REG);
+-				args->tfRegister[IDE_DATA_OFFSET]	= (data) & 0xFF;
+-				args->hobRegister[IDE_DATA_OFFSET]	= (data >> 8) & 0xFF;
+-			}
+-			args->tfRegister[IDE_ERROR_OFFSET]   = err;
+-			/* be sure we're looking at the low order bits */
+-			hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
+-			args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
+-			args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
+-			args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
+-			args->tfRegister[IDE_HCYL_OFFSET]    = hwif->INB(IDE_HCYL_REG);
+-			args->tfRegister[IDE_SELECT_OFFSET]  = hwif->INB(IDE_SELECT_REG);
+-			args->tfRegister[IDE_STATUS_OFFSET]  = stat;
+-
+-			if (drive->addressing == 1) {
+-				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
+-				args->hobRegister[IDE_FEATURE_OFFSET]	= hwif->INB(IDE_FEATURE_REG);
+-				args->hobRegister[IDE_NSECTOR_OFFSET]	= hwif->INB(IDE_NSECTOR_REG);
+-				args->hobRegister[IDE_SECTOR_OFFSET]	= hwif->INB(IDE_SECTOR_REG);
+-				args->hobRegister[IDE_LCYL_OFFSET]	= hwif->INB(IDE_LCYL_REG);
+-				args->hobRegister[IDE_HCYL_OFFSET]	= hwif->INB(IDE_HCYL_REG);
+-			}
++			struct ide_taskfile *tf = &args->tf;
++
++			tf->error = err;
++			tf->status = stat;
++
++			ide_tf_read(drive, args);
  		}
- 		iounmap(dev->vaddr);
-@@ -798,7 +797,7 @@ static void __devexit iic_remove(struct ocp_device *ocp)
+ 	} else if (blk_pm_request(rq)) {
+ 		struct request_pm_state *pm = rq->data;
+@@ -391,10 +386,10 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
  	}
+ 
+ 	spin_lock_irqsave(&ide_lock, flags);
+-	blkdev_dequeue_request(rq);
+ 	HWGROUP(drive)->rq = NULL;
+ 	rq->errors = err;
+-	end_that_request_last(rq, !rq->errors);
++	if (__blk_end_request(rq, (rq->errors ? -EIO : 0), 0))
++		BUG();
+ 	spin_unlock_irqrestore(&ide_lock, flags);
  }
  
--static struct ocp_device_id ibm_iic_ids[] __devinitdata = 
-+static struct ocp_device_id ibm_iic_ids[] __devinitdata =
- {
- 	{ .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
- 	{ .vendor = OCP_VENDOR_INVALID }
-diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
-index 59d7b43..fdaa482 100644
---- a/drivers/i2c/busses/i2c-ibm_iic.h
-+++ b/drivers/i2c/busses/i2c-ibm_iic.h
-@@ -2,11 +2,11 @@
-  * drivers/i2c/busses/i2c-ibm_iic.h
-  *
-  * Support for the IIC peripheral on IBM PPC 4xx
-- * 
-+ *
-  * Copyright (c) 2003 Zultys Technologies.
-  * Eugene Surovegin <eugene.surovegin at zultys.com> or <ebs at ebshome.net>
-  *
-- * Based on original work by 
-+ * Based on original work by
-  * 	Ian DaSilva  <idasilva at mvista.com>
-  *      Armin Kuster <akuster at mvista.com>
-  * 	Matt Porter  <mporter at mvista.com>
-@@ -22,7 +22,7 @@
- #ifndef __I2C_IBM_IIC_H_
- #define __I2C_IBM_IIC_H_
+@@ -471,7 +466,7 @@ static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8
+ 		return ide_stopped;
+ 	}
  
--#include <linux/i2c.h> 
-+#include <linux/i2c.h>
+-	if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
++	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ 		rq->errors |= ERROR_RESET;
+ 
+ 	if ((rq->errors & ERROR_RESET) == ERROR_RESET) {
+@@ -498,7 +493,7 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
+ 		/* add decoding error stuff */
+ 	}
  
- struct iic_regs {
- 	u16 mdbuf;
-@@ -58,7 +58,7 @@ struct ibm_iic_private {
- #define CNTL_TCT_MASK	0x30
- #define CNTL_TCT_SHIFT	4
- #define CNTL_RPST	0x08
--#define CNTL_CHT	0x04 
-+#define CNTL_CHT	0x04
- #define CNTL_RW		0x02
- #define CNTL_PT		0x01
+-	if (hwif->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
++	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ 		/* force an abort */
+ 		hwif->OUTB(WIN_IDLEIMMEDIATE, IDE_COMMAND_REG);
  
-diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
-index c70146e..ab41400 100644
---- a/drivers/i2c/busses/i2c-iop3xx.c
-+++ b/drivers/i2c/busses/i2c-iop3xx.c
-@@ -490,7 +490,6 @@ iop3xx_i2c_probe(struct platform_device *pdev)
- 	 * Default values...should these come in from board code?
- 	 */
- 	new_adapter->timeout = 100;	
--	new_adapter->retries = 3;
- 	new_adapter->algo = &iop3xx_i2c_algo;
+@@ -615,90 +610,26 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
+ 		return __ide_abort(drive, rq);
+ }
  
- 	init_waitqueue_head(&adapter_data->waitq);
-diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
-deleted file mode 100644
-index 069ed7f..0000000
---- a/drivers/i2c/busses/i2c-ixp4xx.c
-+++ /dev/null
-@@ -1,178 +0,0 @@
--/*
-- * drivers/i2c/busses/i2c-ixp4xx.c
-- *
-- * Intel's IXP4xx XScale NPU chipsets (IXP420, 421, 422, 425) do not have
-- * an on board I2C controller but provide 16 GPIO pins that are often
-- * used to create an I2C bus. This driver provides an i2c_adapter 
-- * interface that plugs in under algo_bit and drives the GPIO pins
-- * as instructed by the alogorithm driver.
-- *
-- * Author: Deepak Saxena <dsaxena at plexity.net>
-- *
-- * Copyright (c) 2003-2004 MontaVista Software Inc.
-- *
-- * This file is licensed under the terms of the GNU General Public 
-- * License version 2. This program is licensed "as is" without any 
-- * warranty of any kind, whether express or implied.
-- *
-- * NOTE: Since different platforms will use different GPIO pins for
-- *       I2C, this driver uses an IXP4xx-specific platform_data
-- *       pointer to pass the GPIO numbers to the driver. This 
-- *       allows us to support all the different IXP4xx platforms
-- *       w/o having to put #ifdefs in this driver.
+-/**
+- *	ide_cmd		-	issue a simple drive command
+- *	@drive: drive the command is for
+- *	@cmd: command byte
+- *	@nsect: sector byte
+- *	@handler: handler for the command completion
 - *
-- *       See arch/arm/mach-ixp4xx/ixdp425.c for an example of building a 
-- *       device list and filling in the ixp4xx_i2c_pins data structure 
-- *       that is passed as the platform_data to this driver.
+- *	Issue a simple drive command with interrupts.
+- *	The drive must be selected beforehand.
 - */
 -
--#include <linux/kernel.h>
--#include <linux/init.h>
--#include <linux/platform_device.h>
--#include <linux/module.h>
--#include <linux/i2c.h>
--#include <linux/i2c-algo-bit.h>
--
--#include <asm/hardware.h>	/* Pick up IXP4xx-specific bits */
--
--static inline int ixp4xx_scl_pin(void *data)
+-static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
+-		ide_handler_t *handler)
 -{
--	return ((struct ixp4xx_i2c_pins*)data)->scl_pin;
+-	ide_hwif_t *hwif = HWIF(drive);
+-	if (IDE_CONTROL_REG)
+-		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
+-	SELECT_MASK(drive,0);
+-	hwif->OUTB(nsect,IDE_NSECTOR_REG);
+-	ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
 -}
 -
--static inline int ixp4xx_sda_pin(void *data)
+-/**
+- *	drive_cmd_intr		- 	drive command completion interrupt
+- *	@drive: drive the completion interrupt occurred on
+- *
+- *	drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
+- *	We do any necessary data reading and then wait for the drive to
+- *	go non busy. At that point we may read the error data and complete
+- *	the request
+- */
+- 
+-static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
 -{
--	return ((struct ixp4xx_i2c_pins*)data)->sda_pin;
--}
+-	struct request *rq = HWGROUP(drive)->rq;
+-	ide_hwif_t *hwif = HWIF(drive);
+-	u8 *args = (u8 *) rq->buffer;
+-	u8 stat = hwif->INB(IDE_STATUS_REG);
+-	int retries = 10;
 -
--static void ixp4xx_bit_setscl(void *data, int val)
--{
--	gpio_line_set(ixp4xx_scl_pin(data), 0);
--	gpio_line_config(ixp4xx_scl_pin(data),
--		val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
--}
+-	local_irq_enable_in_hardirq();
+-	if (rq->cmd_type == REQ_TYPE_ATA_CMD &&
+-	    (stat & DRQ_STAT) && args && args[3]) {
+-		u8 io_32bit = drive->io_32bit;
+-		drive->io_32bit = 0;
+-		hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
+-		drive->io_32bit = io_32bit;
+-		while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
+-			udelay(100);
+-	}
 -
--static void ixp4xx_bit_setsda(void *data, int val)
--{
--	gpio_line_set(ixp4xx_sda_pin(data), 0);
--	gpio_line_config(ixp4xx_sda_pin(data),
--		val ? IXP4XX_GPIO_IN : IXP4XX_GPIO_OUT );
+-	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+-		return ide_error(drive, "drive_cmd", stat);
+-		/* calls ide_end_drive_cmd */
+-	ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
+-	return ide_stopped;
 -}
 -
--static int ixp4xx_bit_getscl(void *data)
--{
--	int scl;
--
--	gpio_line_config(ixp4xx_scl_pin(data), IXP4XX_GPIO_IN );
--	gpio_line_get(ixp4xx_scl_pin(data), &scl);
--
--	return scl;
--}	
+-static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
++static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+ {
+-	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+-	task->tfRegister[IDE_SECTOR_OFFSET]  = drive->sect;
+-	task->tfRegister[IDE_LCYL_OFFSET]    = drive->cyl;
+-	task->tfRegister[IDE_HCYL_OFFSET]    = drive->cyl>>8;
+-	task->tfRegister[IDE_SELECT_OFFSET]  = ((drive->head-1)|drive->select.all)&0xBF;
+-	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
 -
--static int ixp4xx_bit_getsda(void *data)
--{
--	int sda;
+-	task->handler = &set_geometry_intr;
++	tf->nsect   = drive->sect;
++	tf->lbal    = drive->sect;
++	tf->lbam    = drive->cyl;
++	tf->lbah    = drive->cyl >> 8;
++	tf->device  = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
++	tf->command = WIN_SPECIFY;
+ }
+ 
+-static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
++static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+ {
+-	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+-	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
 -
--	gpio_line_config(ixp4xx_sda_pin(data), IXP4XX_GPIO_IN );
--	gpio_line_get(ixp4xx_sda_pin(data), &sda);
+-	task->handler = &recal_intr;
++	tf->nsect   = drive->sect;
++	tf->command = WIN_RESTORE;
+ }
+ 
+-static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
++static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+ {
+-	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
+-	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
 -
--	return sda;
--}	
+-	task->handler = &set_multmode_intr;
++	tf->nsect   = drive->mult_req;
++	tf->command = WIN_SETMULT;
+ }
+ 
+ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
+@@ -707,19 +638,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
+ 	ide_task_t args;
+ 
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.command_type = IDE_DRIVE_TASK_NO_DATA;
++	args.data_phase = TASKFILE_NO_DATA;
+ 
+ 	if (s->b.set_geometry) {
+ 		s->b.set_geometry = 0;
+-		ide_init_specify_cmd(drive, &args);
++		ide_tf_set_specify_cmd(drive, &args.tf);
+ 	} else if (s->b.recalibrate) {
+ 		s->b.recalibrate = 0;
+-		ide_init_restore_cmd(drive, &args);
++		ide_tf_set_restore_cmd(drive, &args.tf);
+ 	} else if (s->b.set_multmode) {
+ 		s->b.set_multmode = 0;
+ 		if (drive->mult_req > drive->id->max_multsect)
+ 			drive->mult_req = drive->id->max_multsect;
+-		ide_init_setmult_cmd(drive, &args);
++		ide_tf_set_setmult_cmd(drive, &args.tf);
+ 	} else if (s->all) {
+ 		int special = s->all;
+ 		s->all = 0;
+@@ -727,6 +658,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
+ 		return ide_stopped;
+ 	}
+ 
++	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE |
++			IDE_TFLAG_CUSTOM_HANDLER;
++
+ 	do_rw_taskfile(drive, &args);
+ 
+ 	return ide_started;
+@@ -801,7 +735,7 @@ static ide_startstop_t do_special (ide_drive_t *drive)
+ 
+ 			if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
+ 				if (keep_dma)
+-					hwif->ide_dma_on(drive);
++					ide_dma_on(drive);
+ 			}
+ 		}
+ 
+@@ -861,13 +795,10 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
+ 		struct request *rq)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+- 		ide_task_t *args = rq->special;
+- 
+-		if (!args)
+-			goto done;
++	ide_task_t *task = rq->special;
+ 
+-		hwif->data_phase = args->data_phase;
++	if (task) {
++		hwif->data_phase = task->data_phase;
+ 
+ 		switch (hwif->data_phase) {
+ 		case TASKFILE_MULTI_OUT:
+@@ -880,57 +811,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
+ 			break;
+ 		}
+ 
+-		if (args->tf_out_flags.all != 0) 
+-			return flagged_taskfile(drive, args);
+-		return do_rw_taskfile(drive, args);
+-	} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
+-		u8 *args = rq->buffer;
+- 
+-		if (!args)
+-			goto done;
+-#ifdef DEBUG
+- 		printk("%s: DRIVE_TASK_CMD ", drive->name);
+- 		printk("cmd=0x%02x ", args[0]);
+- 		printk("fr=0x%02x ", args[1]);
+- 		printk("ns=0x%02x ", args[2]);
+- 		printk("sc=0x%02x ", args[3]);
+- 		printk("lcyl=0x%02x ", args[4]);
+- 		printk("hcyl=0x%02x ", args[5]);
+- 		printk("sel=0x%02x\n", args[6]);
+-#endif
+- 		hwif->OUTB(args[1], IDE_FEATURE_REG);
+- 		hwif->OUTB(args[3], IDE_SECTOR_REG);
+- 		hwif->OUTB(args[4], IDE_LCYL_REG);
+- 		hwif->OUTB(args[5], IDE_HCYL_REG);
+- 		hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
+- 		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+- 		return ide_started;
+- 	} else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
+- 		u8 *args = rq->buffer;
 -
--struct ixp4xx_i2c_data {
--	struct ixp4xx_i2c_pins *gpio_pins;
--	struct i2c_adapter adapter;
--	struct i2c_algo_bit_data algo_data;
--};
+-		if (!args)
+-			goto done;
+-#ifdef DEBUG
+- 		printk("%s: DRIVE_CMD ", drive->name);
+- 		printk("cmd=0x%02x ", args[0]);
+- 		printk("sc=0x%02x ", args[1]);
+- 		printk("fr=0x%02x ", args[2]);
+- 		printk("xx=0x%02x\n", args[3]);
+-#endif
+- 		if (args[0] == WIN_SMART) {
+- 			hwif->OUTB(0x4f, IDE_LCYL_REG);
+- 			hwif->OUTB(0xc2, IDE_HCYL_REG);
+- 			hwif->OUTB(args[2],IDE_FEATURE_REG);
+- 			hwif->OUTB(args[1],IDE_SECTOR_REG);
+- 			ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
+- 			return ide_started;
+- 		}
+- 		hwif->OUTB(args[2],IDE_FEATURE_REG);
+- 		ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
+- 		return ide_started;
+- 	}
 -
--static int ixp4xx_i2c_remove(struct platform_device *plat_dev)
+-done:
++		return do_rw_taskfile(drive, task);
++	}
++
+  	/*
+  	 * NULL is actually a valid way of waiting for
+  	 * all current requests to be flushed from the queue.
+@@ -938,9 +821,8 @@ done:
+ #ifdef DEBUG
+  	printk("%s: DRIVE_CMD (null)\n", drive->name);
+ #endif
+- 	ide_end_drive_cmd(drive,
+-			hwif->INB(IDE_STATUS_REG),
+-			hwif->INB(IDE_ERROR_REG));
++	ide_end_drive_cmd(drive, ide_read_status(drive), ide_read_error(drive));
++
+  	return ide_stopped;
+ }
+ 
+@@ -970,8 +852,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
+ 		if (rc)
+ 			printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
+ 		SELECT_DRIVE(drive);
+-		if (IDE_CONTROL_REG)
+-			HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
++		ide_set_irq(drive, 1);
+ 		rc = ide_wait_not_busy(HWIF(drive), 100000);
+ 		if (rc)
+ 			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
+@@ -1003,6 +884,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
+ 
+ 	/* bail early if we've exceeded max_failures */
+ 	if (drive->max_failures && (drive->failures > drive->max_failures)) {
++		rq->cmd_flags |= REQ_FAILED;
+ 		goto kill_rq;
+ 	}
+ 
+@@ -1034,9 +916,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
+ 		if (drive->current_speed == 0xff)
+ 			ide_config_drive_speed(drive, drive->desired_speed);
+ 
+-		if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+-		    rq->cmd_type == REQ_TYPE_ATA_TASK ||
+-		    rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
++		if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
+ 			return execute_drive_cmd(drive, rq);
+ 		else if (blk_pm_request(rq)) {
+ 			struct request_pm_state *pm = rq->data;
+@@ -1244,11 +1124,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+ 		}
+ 	again:
+ 		hwif = HWIF(drive);
+-		if (hwgroup->hwif->sharing_irq &&
+-		    hwif != hwgroup->hwif &&
+-		    hwif->io_ports[IDE_CONTROL_OFFSET]) {
+-			/* set nIEN for previous hwif */
+-			SELECT_INTERRUPT(drive);
++		if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) {
++			/*
++			 * set nIEN for previous hwif, drives in the
++			 * quirk_list may not like intr setups/cleanups
++			 */
++			if (drive->quirk_list != 1)
++				ide_set_irq(drive, 0);
+ 		}
+ 		hwgroup->hwif = hwif;
+ 		hwgroup->drive = drive;
+@@ -1348,7 +1230,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
+ 		printk(KERN_WARNING "%s: DMA timeout error\n", drive->name);
+ 		(void)HWIF(drive)->ide_dma_end(drive);
+ 		ret = ide_error(drive, "dma timeout error",
+-						hwif->INB(IDE_STATUS_REG));
++				ide_read_status(drive));
+ 	} else {
+ 		printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name);
+ 		hwif->dma_timeout(drive);
+@@ -1361,7 +1243,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
+ 	 */
+ 	drive->retry_pio++;
+ 	drive->state = DMA_PIO_RETRY;
+-	hwif->dma_off_quietly(drive);
++	ide_dma_off_quietly(drive);
+ 
+ 	/*
+ 	 * un-busy drive etc (hwgroup->busy is cleared on return) and
+@@ -1454,12 +1336,8 @@ void ide_timer_expiry (unsigned long data)
+ 			 */
+ 			spin_unlock(&ide_lock);
+ 			hwif  = HWIF(drive);
+-#if DISABLE_IRQ_NOSYNC
+-			disable_irq_nosync(hwif->irq);
+-#else
+ 			/* disable_irq_nosync ?? */
+ 			disable_irq(hwif->irq);
+-#endif /* DISABLE_IRQ_NOSYNC */
+ 			/* local CPU only,
+ 			 * as if we were handling an interrupt */
+ 			local_irq_disable();
+@@ -1476,7 +1354,8 @@ void ide_timer_expiry (unsigned long data)
+ 					startstop = ide_dma_timeout_retry(drive, wait);
+ 				} else
+ 					startstop =
+-					ide_error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
++					ide_error(drive, "irq timeout",
++						  ide_read_status(drive));
+ 			}
+ 			drive->service_time = jiffies - drive->service_start;
+ 			spin_lock_irq(&ide_lock);
+@@ -1608,7 +1487,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
+ 		 * remove all the ifdef PCI crap
+ 		 */
+ #ifdef CONFIG_BLK_DEV_IDEPCI
+-		if (hwif->pci_dev && !hwif->pci_dev->vendor)
++		if (hwif->chipset != ide_pci)
+ #endif	/* CONFIG_BLK_DEV_IDEPCI */
+ 		{
+ 			/*
+@@ -1710,7 +1589,6 @@ irqreturn_t ide_intr (int irq, void *dev_id)
+ void ide_init_drive_cmd (struct request *rq)
+ {
+ 	memset(rq, 0, sizeof(*rq));
+-	rq->cmd_type = REQ_TYPE_ATA_CMD;
+ 	rq->ref_count = 1;
+ }
+ 
+@@ -1785,3 +1663,19 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
+ }
+ 
+ EXPORT_SYMBOL(ide_do_drive_cmd);
++
++void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
++{
++	ide_task_t task;
++
++	memset(&task, 0, sizeof(task));
++	task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
++			IDE_TFLAG_OUT_FEATURE | tf_flags;
++	task.tf.feature = dma;		/* Use PIO/DMA */
++	task.tf.lbam    = bcount & 0xff;
++	task.tf.lbah    = (bcount >> 8) & 0xff;
++
++	ide_tf_load(drive, &task);
++}
++
++EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
+diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
+index bb9693d..c32e759 100644
+--- a/drivers/ide/ide-iops.c
++++ b/drivers/ide/ide-iops.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/ide-iops.c	Version 0.37	Mar 05, 2003
+- *
+  *  Copyright (C) 2000-2002	Andre Hedrick <andre at linux-ide.org>
+  *  Copyright (C) 2003		Red Hat <alan at redhat.com>
+  *
+@@ -158,14 +156,6 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
+ 
+ EXPORT_SYMBOL(default_hwif_mmiops);
+ 
+-u32 ide_read_24 (ide_drive_t *drive)
 -{
--	struct ixp4xx_i2c_data *drv_data = platform_get_drvdata(plat_dev);
--
--	platform_set_drvdata(plat_dev, NULL);
--
--	i2c_del_adapter(&drv_data->adapter);
+-	u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
+-	u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG);
+-	u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG);
+-	return (hcyl<<16)|(lcyl<<8)|sect;
+-}
 -
--	kfree(drv_data);
+ void SELECT_DRIVE (ide_drive_t *drive)
+ {
+ 	if (HWIF(drive)->selectproc)
+@@ -173,28 +163,12 @@ void SELECT_DRIVE (ide_drive_t *drive)
+ 	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
+ }
+ 
+-EXPORT_SYMBOL(SELECT_DRIVE);
 -
--	return 0;
+-void SELECT_INTERRUPT (ide_drive_t *drive)
+-{
+-	if (HWIF(drive)->intrproc)
+-		HWIF(drive)->intrproc(drive);
+-	else
+-		HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);
 -}
 -
--static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
+ void SELECT_MASK (ide_drive_t *drive, int mask)
+ {
+ 	if (HWIF(drive)->maskproc)
+ 		HWIF(drive)->maskproc(drive, mask);
+ }
+ 
+-void QUIRK_LIST (ide_drive_t *drive)
 -{
--	int err;
--	struct ixp4xx_i2c_pins *gpio = plat_dev->dev.platform_data;
--	struct ixp4xx_i2c_data *drv_data = 
--		kzalloc(sizeof(struct ixp4xx_i2c_data), GFP_KERNEL);
--
--	if(!drv_data)
--		return -ENOMEM;
--
--	drv_data->gpio_pins = gpio;
--
--	/*
--	 * We could make a lot of these structures static, but
--	 * certain platforms may have multiple GPIO-based I2C
--	 * buses for various device domains, so we need per-device
--	 * algo_data->data. 
--	 */
--	drv_data->algo_data.data = gpio;
--	drv_data->algo_data.setsda = ixp4xx_bit_setsda;
--	drv_data->algo_data.setscl = ixp4xx_bit_setscl;
--	drv_data->algo_data.getsda = ixp4xx_bit_getsda;
--	drv_data->algo_data.getscl = ixp4xx_bit_getscl;
--	drv_data->algo_data.udelay = 10;
--	drv_data->algo_data.timeout = 100;
--
--	drv_data->adapter.id = I2C_HW_B_IXP4XX;
--	drv_data->adapter.class = I2C_CLASS_HWMON;
--	strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
--		sizeof(drv_data->adapter.name));
--	drv_data->adapter.algo_data = &drv_data->algo_data;
--
--	drv_data->adapter.dev.parent = &plat_dev->dev;
--
--	gpio_line_config(gpio->scl_pin, IXP4XX_GPIO_IN);
--	gpio_line_config(gpio->sda_pin, IXP4XX_GPIO_IN);
--	gpio_line_set(gpio->scl_pin, 0);
--	gpio_line_set(gpio->sda_pin, 0);
--
--	err = i2c_bit_add_bus(&drv_data->adapter);
--	if (err) {
--		printk(KERN_ERR "ERROR: Could not install %s\n", plat_dev->dev.bus_id);
+-	if (HWIF(drive)->quirkproc)
+-		drive->quirk_list = HWIF(drive)->quirkproc(drive);
+-}
 -
--		kfree(drv_data);
--		return err;
+ /*
+  * Some localbus EIDE interfaces require a special access sequence
+  * when using 32-bit I/O instructions to transfer data.  We call this
+@@ -449,7 +423,6 @@ int drive_is_ready (ide_drive_t *drive)
+ 	udelay(1);
+ #endif
+ 
+-#ifdef CONFIG_IDEPCI_SHARE_IRQ
+ 	/*
+ 	 * We do a passive status test under shared PCI interrupts on
+ 	 * cards that truly share the ATA side interrupt, but may also share
+@@ -457,11 +430,10 @@ int drive_is_ready (ide_drive_t *drive)
+ 	 * about possible isa-pnp and pci-pnp issues yet.
+ 	 */
+ 	if (IDE_CONTROL_REG)
+-		stat = hwif->INB(IDE_ALTSTATUS_REG);
++		stat = ide_read_altstatus(drive);
+ 	else
+-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+ 		/* Note: this may clear a pending IRQ!! */
+-		stat = hwif->INB(IDE_STATUS_REG);
++		stat = ide_read_status(drive);
+ 
+ 	if (stat & BUSY_STAT)
+ 		/* drive busy:  definitely not interrupting */
+@@ -486,23 +458,24 @@ EXPORT_SYMBOL(drive_is_ready);
+  */
+ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
+ {
+-	ide_hwif_t *hwif = drive->hwif;
+ 	unsigned long flags;
+ 	int i;
+ 	u8 stat;
+ 
+ 	udelay(1);	/* spec allows drive 400ns to assert "BUSY" */
+-	if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
++	stat = ide_read_status(drive);
++
++	if (stat & BUSY_STAT) {
+ 		local_irq_set(flags);
+ 		timeout += jiffies;
+-		while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
++		while ((stat = ide_read_status(drive)) & BUSY_STAT) {
+ 			if (time_after(jiffies, timeout)) {
+ 				/*
+ 				 * One last read after the timeout in case
+ 				 * heavy interrupt load made us not make any
+ 				 * progress during the timeout..
+ 				 */
+-				stat = hwif->INB(IDE_STATUS_REG);
++				stat = ide_read_status(drive);
+ 				if (!(stat & BUSY_STAT))
+ 					break;
+ 
+@@ -522,7 +495,9 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti
+ 	 */
+ 	for (i = 0; i < 10; i++) {
+ 		udelay(1);
+-		if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) {
++		stat = ide_read_status(drive);
++
++		if (OK_STAT(stat, good, bad)) {
+ 			*rstat = stat;
+ 			return 0;
+ 		}
+@@ -640,71 +615,12 @@ no_80w:
+ 	return 0;
+ }
+ 
+-int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
+-{
+-	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
+-	    (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
+-	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
+-		if (eighty_ninty_three(drive) == 0) {
+-			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
+-					    "be set\n", drive->name);
+-			return 1;
+-		}
 -	}
 -
--	platform_set_drvdata(plat_dev, drv_data);
--
 -	return 0;
 -}
 -
--static struct platform_driver ixp4xx_i2c_driver = {
--	.probe		= ixp4xx_i2c_probe,
--	.remove		= ixp4xx_i2c_remove,
--	.driver		= {
--		.name	= "IXP4XX-I2C",
--		.owner	= THIS_MODULE,
--	},
--};
--
--static int __init ixp4xx_i2c_init(void)
+-/*
+- * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
+- * 1 : Safe to update drive->id DMA registers.
+- * 0 : OOPs not allowed.
+- */
+-int set_transfer (ide_drive_t *drive, ide_task_t *args)
 -{
--	return platform_driver_register(&ixp4xx_i2c_driver);
--}
+-	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
+-	    (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
+-	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
+-	    (drive->id->dma_ultra ||
+-	     drive->id->dma_mword ||
+-	     drive->id->dma_1word))
+-		return 1;
 -
--static void __exit ixp4xx_i2c_exit(void)
--{
--	platform_driver_unregister(&ixp4xx_i2c_driver);
+-	return 0;
 -}
 -
--module_init(ixp4xx_i2c_init);
--module_exit(ixp4xx_i2c_exit);
+-#ifdef CONFIG_BLK_DEV_IDEDMA
+-static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
+-{
+-	if (!drive->crc_count)
+-		return drive->current_speed;
+-	drive->crc_count = 0;
 -
--MODULE_DESCRIPTION("GPIO-based I2C adapter for IXP4xx systems");
--MODULE_LICENSE("GPL");
--MODULE_AUTHOR("Deepak Saxena <dsaxena at plexity.net>");
+-	switch(drive->current_speed) {
+-		case XFER_UDMA_7:	return XFER_UDMA_6;
+-		case XFER_UDMA_6:	return XFER_UDMA_5;
+-		case XFER_UDMA_5:	return XFER_UDMA_4;
+-		case XFER_UDMA_4:	return XFER_UDMA_3;
+-		case XFER_UDMA_3:	return XFER_UDMA_2;
+-		case XFER_UDMA_2:	return XFER_UDMA_1;
+-		case XFER_UDMA_1:	return XFER_UDMA_0;
+-			/*
+-			 * OOPS we do not goto non Ultra DMA modes
+-			 * without iCRC's available we force
+-			 * the system to PIO and make the user
+-			 * invoke the ATA-1 ATA-2 DMA modes.
+-			 */
+-		case XFER_UDMA_0:
+-		default:		return XFER_PIO_4;
+-	}
+-}
+-#endif /* CONFIG_BLK_DEV_IDEDMA */
 -
-diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
-index d8de4ac..bbe787b 100644
---- a/drivers/i2c/busses/i2c-mpc.c
-+++ b/drivers/i2c/busses/i2c-mpc.c
-@@ -180,7 +180,7 @@ static void mpc_i2c_stop(struct mpc_i2c *i2c)
- static int mpc_write(struct mpc_i2c *i2c, int target,
- 		     const u8 * data, int length, int restart)
- {
--	int i;
-+	int i, result;
- 	unsigned timeout = i2c->adap.timeout;
- 	u32 flags = restart ? CCR_RSTA : 0;
- 
-@@ -192,15 +192,17 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
- 	/* Write target byte */
- 	writeb((target << 1), i2c->base + MPC_I2C_DR);
- 
--	if (i2c_wait(i2c, timeout, 1) < 0)
--		return -1;
-+	result = i2c_wait(i2c, timeout, 1);
-+	if (result < 0)
-+		return result;
- 
- 	for (i = 0; i < length; i++) {
- 		/* Write data byte */
- 		writeb(data[i], i2c->base + MPC_I2C_DR);
- 
--		if (i2c_wait(i2c, timeout, 1) < 0)
--			return -1;
-+		result = i2c_wait(i2c, timeout, 1);
-+		if (result < 0)
-+			return result;
- 	}
- 
- 	return 0;
-@@ -210,7 +212,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
- 		    u8 * data, int length, int restart)
+ int ide_driveid_update(ide_drive_t *drive)
  {
- 	unsigned timeout = i2c->adap.timeout;
--	int i;
-+	int i, result;
- 	u32 flags = restart ? CCR_RSTA : 0;
- 
- 	/* Start with MEN */
-@@ -221,8 +223,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
- 	/* Write target address byte - this time with the read flag set */
- 	writeb((target << 1) | 1, i2c->base + MPC_I2C_DR);
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	struct hd_driveid *id;
+ 	unsigned long timeout, flags;
++	u8 stat;
  
--	if (i2c_wait(i2c, timeout, 1) < 0)
--		return -1;
-+	result = i2c_wait(i2c, timeout, 1);
-+	if (result < 0)
-+		return result;
+ 	/*
+ 	 * Re-read drive->id for possible DMA mode
+@@ -712,8 +628,7 @@ int ide_driveid_update(ide_drive_t *drive)
+ 	 */
  
- 	if (length) {
- 		if (length == 1)
-@@ -234,8 +237,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
+ 	SELECT_MASK(drive, 1);
+-	if (IDE_CONTROL_REG)
+-		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);
++	ide_set_irq(drive, 1);
+ 	msleep(50);
+ 	hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG);
+ 	timeout = jiffies + WAIT_WORSTCASE;
+@@ -722,10 +637,15 @@ int ide_driveid_update(ide_drive_t *drive)
+ 			SELECT_MASK(drive, 0);
+ 			return 0;	/* drive timed-out */
+ 		}
++
+ 		msleep(50);	/* give drive a breather */
+-	} while (hwif->INB(IDE_ALTSTATUS_REG) & BUSY_STAT);
++		stat = ide_read_altstatus(drive);
++	} while (stat & BUSY_STAT);
++
+ 	msleep(50);	/* wait for IRQ and DRQ_STAT */
+-	if (!OK_STAT(hwif->INB(IDE_STATUS_REG),DRQ_STAT,BAD_R_STAT)) {
++	stat = ide_read_status(drive);
++
++	if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
+ 		SELECT_MASK(drive, 0);
+ 		printk("%s: CHECK for good STATUS\n", drive->name);
+ 		return 0;
+@@ -738,7 +658,7 @@ int ide_driveid_update(ide_drive_t *drive)
+ 		return 0;
  	}
+ 	ata_input_data(drive, id, SECTOR_WORDS);
+-	(void) hwif->INB(IDE_STATUS_REG);	/* clear drive IRQ */
++	(void)ide_read_status(drive);	/* clear drive IRQ */
+ 	local_irq_enable();
+ 	local_irq_restore(flags);
+ 	ide_fix_driveid(id);
+@@ -766,8 +686,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ //		msleep(50);
  
- 	for (i = 0; i < length; i++) {
--		if (i2c_wait(i2c, timeout, 0) < 0)
--			return -1;
-+		result = i2c_wait(i2c, timeout, 0);
-+		if (result < 0)
-+			return result;
- 
- 		/* Generate txack on next to last byte */
- 		if (i == length - 2)
-@@ -309,7 +313,6 @@ static struct i2c_adapter mpc_ops = {
- 	.algo = &mpc_algo,
- 	.class = I2C_CLASS_HWMON,
- 	.timeout = 1,
--	.retries = 1
- };
- 
- static int fsl_i2c_probe(struct platform_device *pdev)
-@@ -321,9 +324,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
- 
- 	pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
- 
--	if (!(i2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) {
-+	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
-+	if (!i2c)
- 		return -ENOMEM;
--	}
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-	if (hwif->ide_dma_on)	/* check if host supports DMA */
+-		hwif->dma_host_off(drive);
++	if (hwif->dma_host_set)	/* check if host supports DMA */
++		hwif->dma_host_set(drive, 0);
+ #endif
  
- 	i2c->irq = platform_get_irq(pdev, 0);
- 	if (i2c->irq < 0) {
-diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
-index bb7bf68..036e6a8 100644
---- a/drivers/i2c/busses/i2c-mv64xxx.c
-+++ b/drivers/i2c/busses/i2c-mv64xxx.c
-@@ -1,6 +1,6 @@
- /*
-- * Driver for the i2c controller on the Marvell line of host bridges for MIPS
-- * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
-+ * Driver for the i2c controller on the Marvell line of host bridges
-+ * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family).
-  *
-  * Author: Mark A. Greer <mgreer at mvista.com>
-  *
-@@ -14,7 +14,7 @@
- #include <linux/spinlock.h>
- #include <linux/i2c.h>
- #include <linux/interrupt.h>
--#include <linux/mv643xx.h>
-+#include <linux/mv643xx_i2c.h>
- #include <linux/platform_device.h>
+ 	/* Skip setting PIO flow-control modes on pre-EIDE drives */
+@@ -796,13 +716,12 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+ 	SELECT_DRIVE(drive);
+ 	SELECT_MASK(drive, 0);
+ 	udelay(1);
+-	if (IDE_CONTROL_REG)
+-		hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
++	ide_set_irq(drive, 0);
+ 	hwif->OUTB(speed, IDE_NSECTOR_REG);
+ 	hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);
+ 	hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
+-	if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
+-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
++	if (drive->quirk_list == 2)
++		ide_set_irq(drive, 1);
  
- #include <asm/io.h>
-@@ -86,6 +86,7 @@ struct mv64xxx_i2c_data {
- 	u32			cntl_bits;
- 	void __iomem		*reg_base;
- 	u32			reg_base_p;
-+	u32			reg_size;
- 	u32			addr1;
- 	u32			addr2;
- 	u32			bytes_left;
-@@ -463,17 +464,20 @@ static int __devinit
- mv64xxx_i2c_map_regs(struct platform_device *pd,
- 	struct mv64xxx_i2c_data *drv_data)
- {
--	struct resource	*r;
-+	int size;
-+	struct resource	*r = platform_get_resource(pd, IORESOURCE_MEM, 0);
+ 	error = __ide_wait_stat(drive, drive->ready_stat,
+ 				BUSY_STAT|DRQ_STAT|ERR_STAT,
+@@ -823,10 +742,11 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
  
--	if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) &&
--		request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE,
--			drv_data->adapter.name)) {
-+	if (!r)
-+		return -ENODEV;
+  skip:
+ #ifdef CONFIG_BLK_DEV_IDEDMA
+-	if (speed >= XFER_SW_DMA_0)
+-		hwif->dma_host_on(drive);
+-	else if (hwif->ide_dma_on)	/* check if host supports DMA */
+-		hwif->dma_off_quietly(drive);
++	if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
++	    drive->using_dma)
++		hwif->dma_host_set(drive, 1);
++	else if (hwif->dma_host_set)	/* check if host supports DMA */
++		ide_dma_off_quietly(drive);
+ #endif
  
--		drv_data->reg_base = ioremap(r->start,
--			MV64XXX_I2C_REG_BLOCK_SIZE);
--		drv_data->reg_base_p = r->start;
--	} else
--		return -ENOMEM;
-+	size = r->end - r->start + 1;
+ 	switch(speed) {
+@@ -902,28 +822,24 @@ EXPORT_SYMBOL(ide_set_handler);
+  *	handler and IRQ setup do not race. All IDE command kick off
+  *	should go via this function or do equivalent locking.
+  */
+- 
+-void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry)
 +
-+	if (!request_mem_region(r->start, size, drv_data->adapter.name))
-+		return -EBUSY;
++void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
++			 unsigned timeout, ide_expiry_t *expiry)
+ {
+ 	unsigned long flags;
+ 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	
 +
-+	drv_data->reg_base = ioremap(r->start, size);
-+	drv_data->reg_base_p = r->start;
-+	drv_data->reg_size = size;
- 
- 	return 0;
+ 	spin_lock_irqsave(&ide_lock, flags);
+-	
+ 	BUG_ON(hwgroup->handler);
+-	hwgroup->handler	= handler;
+-	hwgroup->expiry		= expiry;
+-	hwgroup->timer.expires	= jiffies + timeout;
+-	hwgroup->req_gen_timer = hwgroup->req_gen;
+-	add_timer(&hwgroup->timer);
++	__ide_set_handler(drive, handler, timeout, expiry);
+ 	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
+-	/* Drive takes 400nS to respond, we must avoid the IRQ being
+-	   serviced before that. 
+-	   
+-	   FIXME: we could skip this delay with care on non shared
+-	   devices 
+-	*/
++	/*
++	 * Drive takes 400nS to respond, we must avoid the IRQ being
++	 * serviced before that.
++	 *
++	 * FIXME: we could skip this delay with care on non shared devices
++	 */
+ 	ndelay(400);
+ 	spin_unlock_irqrestore(&ide_lock, flags);
  }
-@@ -483,8 +487,7 @@ mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
+@@ -943,17 +859,16 @@ static ide_startstop_t do_reset1 (ide_drive_t *, int);
+ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
  {
- 	if (drv_data->reg_base) {
- 		iounmap(drv_data->reg_base);
--		release_mem_region(drv_data->reg_base_p,
--			MV64XXX_I2C_REG_BLOCK_SIZE);
-+		release_mem_region(drv_data->reg_base_p, drv_data->reg_size);
- 	}
- 
- 	drv_data->reg_base = NULL;
-@@ -529,7 +532,6 @@ mv64xxx_i2c_probe(struct platform_device *pd)
- 	drv_data->adapter.owner = THIS_MODULE;
- 	drv_data->adapter.class = I2C_CLASS_HWMON;
- 	drv_data->adapter.timeout = pdata->timeout;
--	drv_data->adapter.retries = pdata->retries;
- 	drv_data->adapter.nr = pd->id;
- 	platform_set_drvdata(pd, drv_data);
- 	i2c_set_adapdata(&drv_data->adapter, drv_data);
-diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
-index 1bf590c..3dac920 100644
---- a/drivers/i2c/busses/i2c-nforce2.c
-+++ b/drivers/i2c/busses/i2c-nforce2.c
-@@ -351,6 +351,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
- 	pci_set_drvdata(dev, smbuses);
- 
- 	switch(dev->device) {
-+	case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS:
- 	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:
- 	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:
- 		smbuses[0].blockops = 1;
-diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
-index f2552b1..da66397 100644
---- a/drivers/i2c/busses/i2c-omap.c
-+++ b/drivers/i2c/busses/i2c-omap.c
-@@ -362,8 +362,6 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+ 	ide_hwgroup_t *hwgroup	= HWGROUP(drive);
+-	ide_hwif_t *hwif	= HWIF(drive);
+ 	u8 stat;
  
- 	omap_i2c_enable_clocks(dev);
+ 	SELECT_DRIVE(drive);
+ 	udelay (10);
++	stat = ide_read_status(drive);
  
--	/* REVISIT: initialize and use adap->retries. This is an optional
--	 * feature */
- 	if ((r = omap_i2c_wait_for_bb(dev)) < 0)
- 		goto out;
+-	if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
++	if (OK_STAT(stat, 0, BUSY_STAT))
+ 		printk("%s: ATAPI reset complete\n", drive->name);
+-	} else {
++	else {
+ 		if (time_before(jiffies, hwgroup->poll_timeout)) {
+-			BUG_ON(HWGROUP(drive)->handler != NULL);
+ 			ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
+ 			/* continue polling */
+ 			return ide_started;
+@@ -991,9 +906,10 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
+ 		}
+ 	}
  
-diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
-index ca18e0b..1603c81 100644
---- a/drivers/i2c/busses/i2c-pasemi.c
-+++ b/drivers/i2c/busses/i2c-pasemi.c
-@@ -368,6 +368,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
- 	smbus->adapter.class = I2C_CLASS_HWMON;
- 	smbus->adapter.algo = &smbus_algorithm;
- 	smbus->adapter.algo_data = smbus;
-+	smbus->adapter.nr = PCI_FUNC(dev->devfn);
+-	if (!OK_STAT(tmp = hwif->INB(IDE_STATUS_REG), 0, BUSY_STAT)) {
++	tmp = ide_read_status(drive);
++
++	if (!OK_STAT(tmp, 0, BUSY_STAT)) {
+ 		if (time_before(jiffies, hwgroup->poll_timeout)) {
+-			BUG_ON(HWGROUP(drive)->handler != NULL);
+ 			ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL);
+ 			/* continue polling */
+ 			return ide_started;
+@@ -1002,7 +918,9 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
+ 		drive->failures++;
+ 	} else  {
+ 		printk("%s: reset: ", hwif->name);
+-		if ((tmp = hwif->INB(IDE_ERROR_REG)) == 1) {
++		tmp = ide_read_error(drive);
++
++		if (tmp == 1) {
+ 			printk("success\n");
+ 			drive->failures = 0;
+ 		} else {
+@@ -1031,19 +949,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
+ 	return ide_stopped;
+ }
  
- 	/* set up the sysfs linkage to our parent device */
- 	smbus->adapter.dev.parent = &dev->dev;
-@@ -375,7 +376,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
- 	reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
- 		  (CLK_100K_DIV & CTL_CLK_M)));
+-static void check_dma_crc(ide_drive_t *drive)
+-{
+-#ifdef CONFIG_BLK_DEV_IDEDMA
+-	if (drive->crc_count) {
+-		drive->hwif->dma_off_quietly(drive);
+-		ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
+-		if (drive->current_speed >= XFER_SW_DMA_0)
+-			(void) HWIF(drive)->ide_dma_on(drive);
+-	} else
+-		ide_dma_off(drive);
+-#endif
+-}
+-
+ static void ide_disk_pre_reset(ide_drive_t *drive)
+ {
+ 	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
+@@ -1051,8 +956,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
+ 	drive->special.all = 0;
+ 	drive->special.b.set_geometry = legacy;
+ 	drive->special.b.recalibrate  = legacy;
+-	if (OK_TO_RESET_CONTROLLER)
+-		drive->mult_count = 0;
++	drive->mult_count = 0;
+ 	if (!drive->keep_settings && !drive->using_dma)
+ 		drive->mult_req = 0;
+ 	if (drive->mult_req != drive->mult_count)
+@@ -1066,17 +970,20 @@ static void pre_reset(ide_drive_t *drive)
+ 	else
+ 		drive->post_reset = 1;
  
--	error = i2c_add_adapter(&smbus->adapter);
-+	error = i2c_add_numbered_adapter(&smbus->adapter);
- 	if (error)
- 		goto out_release_region;
++	if (drive->using_dma) {
++		if (drive->crc_count)
++			ide_check_dma_crc(drive);
++		else
++			ide_dma_off(drive);
++	}
++
+ 	if (!drive->keep_settings) {
+-		if (drive->using_dma) {
+-			check_dma_crc(drive);
+-		} else {
++		if (!drive->using_dma) {
+ 			drive->unmask = 0;
+ 			drive->io_32bit = 0;
+ 		}
+ 		return;
+ 	}
+-	if (drive->using_dma)
+-		check_dma_crc(drive);
  
-diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
-index 167e413..9bbe96c 100644
---- a/drivers/i2c/busses/i2c-piix4.c
-+++ b/drivers/i2c/busses/i2c-piix4.c
-@@ -121,10 +121,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
- {
- 	unsigned char temp;
+ 	if (HWIF(drive)->pre_reset != NULL)
+ 		HWIF(drive)->pre_reset(drive);
+@@ -1137,7 +1044,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ 	for (unit = 0; unit < MAX_DRIVES; ++unit)
+ 		pre_reset(&hwif->drives[unit]);
  
--	/* match up the function */
--	if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
--		return -ENODEV;
--
- 	dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
+-#if OK_TO_RESET_CONTROLLER
+ 	if (!IDE_CONTROL_REG) {
+ 		spin_unlock_irqrestore(&ide_lock, flags);
+ 		return ide_stopped;
+@@ -1174,11 +1080,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
+ 	 * state when the disks are reset this way. At least, the Winbond
+ 	 * 553 documentation says that
+ 	 */
+-	if (hwif->resetproc != NULL) {
++	if (hwif->resetproc)
+ 		hwif->resetproc(drive);
+-	}
+-	
+-#endif	/* OK_TO_RESET_CONTROLLER */
  
- 	/* Don't access SMBus on IBM systems which get corrupted eeproms */
-@@ -389,28 +385,21 @@ static struct i2c_adapter piix4_adapter = {
- };
+ 	spin_unlock_irqrestore(&ide_lock, flags);
+ 	return ide_started;
+@@ -1197,7 +1100,7 @@ EXPORT_SYMBOL(ide_do_reset);
  
- static struct pci_device_id piix4_ids[] = {
--	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3),
--	  .driver_data = 3 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000SB),
--	  .driver_data = 0 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3),
--	  .driver_data = 3 },
--	{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3),
--	  .driver_data = 0 },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
-+		     PCI_DEVICE_ID_SERVERWORKS_OSB4) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
-+		     PCI_DEVICE_ID_SERVERWORKS_CSB5) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
-+		     PCI_DEVICE_ID_SERVERWORKS_CSB6) },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
-+		     PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
- 	{ 0, }
- };
+ /*
+  * ide_wait_not_busy() waits for the currently selected device on the hwif
+- * to report a non-busy status, see comments in probe_hwif().
++ * to report a non-busy status, see comments in ide_probe_port().
+  */
+ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
+ {
+diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
+index 062d3bc..1ff676c 100644
+--- a/drivers/ide/ide-lib.c
++++ b/drivers/ide/ide-lib.c
+@@ -358,8 +358,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
+ 	if (!PCI_DMA_BUS_IS_PHYS) {
+ 		addr = BLK_BOUNCE_ANY;
+ 	} else if (on && drive->media == ide_disk) {
+-		if (HWIF(drive)->pci_dev)
+-			addr = HWIF(drive)->pci_dev->dma_mask;
++		struct device *dev = drive->hwif->dev;
++
++		if (dev && dev->dma_mask)
++			addr = *dev->dma_mask;
+ 	}
  
-diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c
-index 6426a61..2598d29 100644
---- a/drivers/i2c/busses/i2c-pxa.c
-+++ b/drivers/i2c/busses/i2c-pxa.c
-@@ -65,6 +65,7 @@ struct pxa_i2c {
- 	unsigned long		iosize;
+ 	if (drive->queue)
+@@ -441,6 +443,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+ 	 * case could happen iff the transfer mode has already been set on
+ 	 * the device by ide-proc.c::set_xfer_rate()).
+ 	 */
++	if (rate < XFER_PIO_0) {
++		if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
++			return ide_set_dma_mode(drive, rate);
++		else
++			return ide_config_drive_speed(drive, rate);
++	}
  
- 	int			irq;
-+	int			use_pio;
- };
+ 	return ide_set_dma_mode(drive, rate);
+ }
+@@ -448,8 +456,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
+ static void ide_dump_opcode(ide_drive_t *drive)
+ {
+ 	struct request *rq;
+-	u8 opcode = 0;
+-	int found = 0;
++	ide_task_t *task = NULL;
  
- #define _IBMR(i2c)	((i2c)->reg_base + 0)
-@@ -163,6 +164,7 @@ static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname)
- #define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0)
+ 	spin_lock(&ide_lock);
+ 	rq = NULL;
+@@ -458,164 +465,129 @@ static void ide_dump_opcode(ide_drive_t *drive)
+ 	spin_unlock(&ide_lock);
+ 	if (!rq)
+ 		return;
+-	if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
+-	    rq->cmd_type == REQ_TYPE_ATA_TASK) {
+-		char *args = rq->buffer;
+-		if (args) {
+-			opcode = args[0];
+-			found = 1;
+-		}
+-	} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+-		ide_task_t *args = rq->special;
+-		if (args) {
+-			task_struct_t *tf = (task_struct_t *) args->tfRegister;
+-			opcode = tf->command;
+-			found = 1;
+-		}
+-	}
++
++	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
++		task = rq->special;
  
- static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret);
-+static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
+ 	printk("ide: failed opcode was: ");
+-	if (!found)
+-		printk("unknown\n");
++	if (task == NULL)
++		printk(KERN_CONT "unknown\n");
+ 	else
+-		printk("0x%02x\n", opcode);
++		printk(KERN_CONT "0x%02x\n", task->tf.command);
+ }
  
- static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
+-static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
++u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
  {
-@@ -554,6 +556,71 @@ static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
- 	writel(icr, _ICR(i2c));
- }
+-	ide_hwif_t *hwif = HWIF(drive);
+-	unsigned long flags;
+-	u8 err = 0;
++	u32 high, low;
  
-+static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c)
-+{
-+	/* make timeout the same as for interrupt based functions */
-+	long timeout = 2 * DEF_TIMEOUT;
-+
-+	/*
-+	 * Wait for the bus to become free.
-+	 */
-+	while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) {
-+		udelay(1000);
-+		show_state(i2c);
-+	}
-+
-+	if (timeout <= 0) {
-+		show_state(i2c);
-+		dev_err(&i2c->adap.dev,
-+			"i2c_pxa: timeout waiting for bus free\n");
-+		return I2C_RETRY;
-+	}
-+
-+	/*
-+	 * Set master mode.
-+	 */
-+	writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c));
+-	local_irq_save(flags);
+-	printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
+-	if (stat & BUSY_STAT)
+-		printk("Busy ");
+-	else {
+-		if (stat & READY_STAT)	printk("DriveReady ");
+-		if (stat & WRERR_STAT)	printk("DeviceFault ");
+-		if (stat & SEEK_STAT)	printk("SeekComplete ");
+-		if (stat & DRQ_STAT)	printk("DataRequest ");
+-		if (stat & ECC_STAT)	printk("CorrectedError ");
+-		if (stat & INDEX_STAT)	printk("Index ");
+-		if (stat & ERR_STAT)	printk("Error ");
++	if (lba48)
++		high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
++			tf->hob_lbal;
++	else
++		high = tf->device & 0xf;
++	low  = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
 +
-+	return 0;
++	return ((u64)high << 24) | low;
 +}
++EXPORT_SYMBOL_GPL(ide_get_lba_addr);
 +
-+static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c,
-+			       struct i2c_msg *msg, int num)
++static void ide_dump_sector(ide_drive_t *drive)
 +{
-+	unsigned long timeout = 500000; /* 5 seconds */
-+	int ret = 0;
-+
-+	ret = i2c_pxa_pio_set_master(i2c);
-+	if (ret)
-+		goto out;
-+
-+	i2c->msg = msg;
-+	i2c->msg_num = num;
-+	i2c->msg_idx = 0;
-+	i2c->msg_ptr = 0;
-+	i2c->irqlogidx = 0;
-+
-+	i2c_pxa_start_message(i2c);
-+
-+	while (timeout-- && i2c->msg_num > 0) {
-+		i2c_pxa_handler(0, i2c);
-+		udelay(10);
-+	}
-+
-+	i2c_pxa_stop_message(i2c);
++	ide_task_t task;
++	struct ide_taskfile *tf = &task.tf;
++	int lba48 = (drive->addressing == 1) ? 1 : 0;
 +
-+	/*
-+	 * We place the return code in i2c->msg_idx.
-+	 */
-+	ret = i2c->msg_idx;
++	memset(&task, 0, sizeof(task));
++	if (lba48)
++		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
++				IDE_TFLAG_LBA48;
++	else
++		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
 +
-+out:
-+	if (timeout == 0)
-+		i2c_pxa_scream_blue_murder(i2c, "timeout");
++	ide_tf_read(drive, &task);
 +
-+	return ret;
++	if (lba48 || (tf->device & ATA_LBA))
++		printk(", LBAsect=%llu",
++			(unsigned long long)ide_get_lba_addr(tf, lba48));
++	else
++		printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
++					 tf->device & 0xf, tf->lbal);
 +}
 +
- /*
-  * We are protected by the adapter bus mutex.
-  */
-@@ -610,6 +677,35 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
- 	return ret;
- }
- 
-+static int i2c_pxa_pio_xfer(struct i2c_adapter *adap,
-+			    struct i2c_msg msgs[], int num)
++static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
 +{
-+	struct pxa_i2c *i2c = adap->algo_data;
-+	int ret, i;
-+
-+	/* If the I2C controller is disabled we need to reset it
-+	  (probably due to a suspend/resume destroying state). We do
-+	  this here as we can then avoid worrying about resuming the
-+	  controller before its users. */
-+	if (!(readl(_ICR(i2c)) & ICR_IUE))
-+		i2c_pxa_reset(i2c);
-+
-+	for (i = adap->retries; i >= 0; i--) {
-+		ret = i2c_pxa_do_pio_xfer(i2c, msgs, num);
-+		if (ret != I2C_RETRY)
-+			goto out;
-+
-+		if (i2c_debug)
-+			dev_dbg(&adap->dev, "Retrying transmission\n");
-+		udelay(100);
-+	}
-+	i2c_pxa_scream_blue_murder(i2c, "exhausted retries");
-+	ret = -EREMOTEIO;
-+ out:
-+	i2c_pxa_set_slave(i2c, ret);
-+	return ret;
++	printk("{ ");
++	if (err & ABRT_ERR)	printk("DriveStatusError ");
++	if (err & ICRC_ERR)
++		printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
++	if (err & ECC_ERR)	printk("UncorrectableError ");
++	if (err & ID_ERR)	printk("SectorIdNotFound ");
++	if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
++	if (err & MARK_ERR)	printk("AddrMarkNotFound ");
++	printk("}");
++	if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
++	    (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
++		ide_dump_sector(drive);
++		if (HWGROUP(drive) && HWGROUP(drive)->rq)
++			printk(", sector=%llu",
++			       (unsigned long long)HWGROUP(drive)->rq->sector);
+ 	}
++	printk("\n");
 +}
 +
- /*
-  * i2c_pxa_master_complete - complete the message and wake up.
++static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
++{
++	printk("{ ");
++	if (err & ILI_ERR)	printk("IllegalLengthIndication ");
++	if (err & EOM_ERR)	printk("EndOfMedia ");
++	if (err & ABRT_ERR)	printk("AbortedCommand ");
++	if (err & MCR_ERR)	printk("MediaChangeRequested ");
++	if (err & LFS_ERR)	printk("LastFailedSense=0x%02x ",
++				       (err & LFS_ERR) >> 4);
+ 	printk("}\n");
+-	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
+-		err = hwif->INB(IDE_ERROR_REG);
+-		printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
+-		if (err & ABRT_ERR)	printk("DriveStatusError ");
+-		if (err & ICRC_ERR)
+-			printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
+-		if (err & ECC_ERR)	printk("UncorrectableError ");
+-		if (err & ID_ERR)	printk("SectorIdNotFound ");
+-		if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
+-		if (err & MARK_ERR)	printk("AddrMarkNotFound ");
+-		printk("}");
+-		if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
+-		    (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
+-			if (drive->addressing == 1) {
+-				__u64 sectors = 0;
+-				u32 low = 0, high = 0;
+-				hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
+-				low = ide_read_24(drive);
+-				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
+-				high = ide_read_24(drive);
+-				sectors = ((__u64)high << 24) | low;
+-				printk(", LBAsect=%llu, high=%d, low=%d",
+-				       (unsigned long long) sectors,
+-				       high, low);
+-			} else {
+-				u8 cur = hwif->INB(IDE_SELECT_REG);
+-				if (cur & 0x40) {	/* using LBA? */
+-					printk(", LBAsect=%ld", (unsigned long)
+-					 ((cur&0xf)<<24)
+-					 |(hwif->INB(IDE_HCYL_REG)<<16)
+-					 |(hwif->INB(IDE_LCYL_REG)<<8)
+-					 | hwif->INB(IDE_SECTOR_REG));
+-				} else {
+-					printk(", CHS=%d/%d/%d",
+-					 (hwif->INB(IDE_HCYL_REG)<<8) +
+-					  hwif->INB(IDE_LCYL_REG),
+-					  cur & 0xf,
+-					  hwif->INB(IDE_SECTOR_REG));
+-				}
+-			}
+-			if (HWGROUP(drive) && HWGROUP(drive)->rq)
+-				printk(", sector=%llu",
+-					(unsigned long long)HWGROUP(drive)->rq->sector);
+-		}
+-		printk("\n");
+-	}
+-	ide_dump_opcode(drive);
+-	local_irq_restore(flags);
+-	return err;
+ }
+ 
+ /**
+- *	ide_dump_atapi_status       -       print human readable atapi status
++ *	ide_dump_status		-	translate ATA/ATAPI error
+  *	@drive: drive that status applies to
+  *	@msg: text message to print
+  *	@stat: status byte to decode
+  *
+  *	Error reporting, in human readable form (luxurious, but a memory hog).
++ *	Combines the drive name, message and status byte to provide a
++ *	user understandable explanation of the device error.
   */
-@@ -621,7 +717,8 @@ static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret)
- 	i2c->msg_num = 0;
- 	if (ret)
- 		i2c->msg_idx = ret;
--	wake_up(&i2c->wait);
-+	if (!i2c->use_pio)
-+		wake_up(&i2c->wait);
+ 
+-static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
++u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
+ {
+ 	unsigned long flags;
++	u8 err = 0;
+ 
+-	atapi_status_t status;
+-	atapi_error_t error;
+-
+-	status.all = stat;
+-	error.all = 0;
+ 	local_irq_save(flags);
+ 	printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
+-	if (status.b.bsy)
++	if (stat & BUSY_STAT)
+ 		printk("Busy ");
+ 	else {
+-		if (status.b.drdy)	printk("DriveReady ");
+-		if (status.b.df)	printk("DeviceFault ");
+-		if (status.b.dsc)	printk("SeekComplete ");
+-		if (status.b.drq)	printk("DataRequest ");
+-		if (status.b.corr)	printk("CorrectedError ");
+-		if (status.b.idx)	printk("Index ");
+-		if (status.b.check)	printk("Error ");
++		if (stat & READY_STAT)	printk("DriveReady ");
++		if (stat & WRERR_STAT)	printk("DeviceFault ");
++		if (stat & SEEK_STAT)	printk("SeekComplete ");
++		if (stat & DRQ_STAT)	printk("DataRequest ");
++		if (stat & ECC_STAT)	printk("CorrectedError ");
++		if (stat & INDEX_STAT)	printk("Index ");
++		if (stat & ERR_STAT)	printk("Error ");
+ 	}
+ 	printk("}\n");
+-	if (status.b.check && !status.b.bsy) {
+-		error.all = HWIF(drive)->INB(IDE_ERROR_REG);
+-		printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all);
+-		if (error.b.ili)	printk("IllegalLengthIndication ");
+-		if (error.b.eom)	printk("EndOfMedia ");
+-		if (error.b.abrt)	printk("AbortedCommand ");
+-		if (error.b.mcr)	printk("MediaChangeRequested ");
+-		if (error.b.sense_key)	printk("LastFailedSense=0x%02x ",
+-						error.b.sense_key);
+-		printk("}\n");
++	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
++		err = ide_read_error(drive);
++		printk("%s: %s: error=0x%02x ", drive->name, msg, err);
++		if (drive->media == ide_disk)
++			ide_dump_ata_error(drive, err);
++		else
++			ide_dump_atapi_error(drive, err);
+ 	}
+ 	ide_dump_opcode(drive);
+ 	local_irq_restore(flags);
+-	return error.all;
+-}
+-
+-/**
+- *	ide_dump_status		-	translate ATA/ATAPI error
+- *	@drive: drive the error occured on
+- *	@msg: information string
+- *	@stat: status byte
+- *
+- *	Error reporting, in human readable form (luxurious, but a memory hog).
+- *	Combines the drive name, message and status byte to provide a
+- *	user understandable explanation of the device error.
+- */
+-
+-u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
+-{
+-	if (drive->media == ide_disk)
+-		return ide_dump_ata_status(drive, msg, stat);
+-	return ide_dump_atapi_status(drive, msg, stat);
++	return err;
  }
  
- static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr)
-@@ -840,6 +937,37 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
- 	.functionality	= i2c_pxa_functionality,
- };
+ EXPORT_SYMBOL(ide_dump_status);
+diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
+index e245521..b163b2e 100644
+--- a/drivers/ide/ide-pnp.c
++++ b/drivers/ide/ide-pnp.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/ide-pnp.c
+- *
+  * This file provides autodetection for ISA PnP IDE interfaces.
+  * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
+  *
+@@ -31,7 +29,6 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ {
+ 	hw_regs_t hw;
+ 	ide_hwif_t *hwif;
+-	int index;
  
-+static const struct i2c_algorithm i2c_pxa_pio_algorithm = {
-+	.master_xfer	= i2c_pxa_pio_xfer,
-+	.functionality	= i2c_pxa_functionality,
-+};
+ 	if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
+ 		return -1;
+@@ -41,11 +38,19 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ 				pnp_port_start(dev, 1));
+ 	hw.irq = pnp_irq(dev, 0);
+ 
+-	index = ide_register_hw(&hw, NULL, 1, &hwif);
++	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif) {
++		u8 index = hwif->index;
++		u8 idx[4] = { index, 0xff, 0xff, 0xff };
 +
-+static void i2c_pxa_enable(struct platform_device *dev)
-+{
-+	if (cpu_is_pxa27x()) {
-+		switch (dev->id) {
-+		case 0:
-+			pxa_gpio_mode(GPIO117_I2CSCL_MD);
-+			pxa_gpio_mode(GPIO118_I2CSDA_MD);
-+			break;
-+		case 1:
-+			local_irq_disable();
-+			PCFR |= PCFR_PI2CEN;
-+			local_irq_enable();
-+			break;
-+		}
-+	}
-+}
++		ide_init_port_data(hwif, index);
++		ide_init_port_hw(hwif, &hw);
+ 
+-	if (index != -1) {
+-	    	printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
++		printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
+ 		pnp_set_drvdata(dev,hwif);
 +
-+static void i2c_pxa_disable(struct platform_device *dev)
-+{
-+	if (cpu_is_pxa27x() && dev->id == 1) {
-+		local_irq_disable();
-+		PCFR &= ~PCFR_PI2CEN;
-+		local_irq_enable();
-+	}
-+}
++		ide_device_add(idx, NULL);
 +
- #define res_len(r)		((r)->end - (r)->start + 1)
- static int i2c_pxa_probe(struct platform_device *dev)
- {
-@@ -864,7 +992,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
+ 		return 0;
  	}
  
- 	i2c->adap.owner   = THIS_MODULE;
--	i2c->adap.algo    = &i2c_pxa_algorithm;
- 	i2c->adap.retries = 5;
+@@ -55,9 +60,10 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+ static void idepnp_remove(struct pnp_dev * dev)
+ {
+ 	ide_hwif_t *hwif = pnp_get_drvdata(dev);
+-	if (hwif) {
+-		ide_unregister(hwif->index);
+-	} else
++
++	if (hwif)
++		ide_unregister(hwif->index, 0, 0);
++	else
+ 		printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
+ }
  
- 	spin_lock_init(&i2c->lock);
-@@ -899,34 +1026,28 @@ static int i2c_pxa_probe(struct platform_device *dev)
- #endif
+@@ -68,12 +74,15 @@ static struct pnp_driver idepnp_driver = {
+ 	.remove		= idepnp_remove,
+ };
  
- 	clk_enable(i2c->clk);
--#ifdef CONFIG_PXA27x
--	switch (dev->id) {
--	case 0:
--		pxa_gpio_mode(GPIO117_I2CSCL_MD);
--		pxa_gpio_mode(GPIO118_I2CSDA_MD);
--		break;
--	case 1:
--		local_irq_disable();
--		PCFR |= PCFR_PI2CEN;
--		local_irq_enable();
--	}
--#endif
-+	i2c_pxa_enable(dev);
+-void __init pnpide_init(void)
++static int __init pnpide_init(void)
+ {
+-	pnp_register_driver(&idepnp_driver);
++	return pnp_register_driver(&idepnp_driver);
+ }
  
--	ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
--			  i2c->adap.name, i2c);
--	if (ret)
--		goto ereqirq;
-+	if (plat) {
-+		i2c->adap.class = plat->class;
-+		i2c->use_pio = plat->use_pio;
-+	}
+-void __exit pnpide_exit(void)
++static void __exit pnpide_exit(void)
+ {
+ 	pnp_unregister_driver(&idepnp_driver);
+ }
++
++module_init(pnpide_init);
++module_exit(pnpide_exit);
+diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
+index 2994523..fd0ef82 100644
+--- a/drivers/ide/ide-probe.c
++++ b/drivers/ide/ide-probe.c
+@@ -1,7 +1,6 @@
+ /*
+- *  linux/drivers/ide/ide-probe.c	Version 1.11	Mar 05, 2003
+- *
+- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
++ *  Copyright (C) 1994-1998   Linus Torvalds & authors (see below)
++ *  Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
+  */
  
-+	if (i2c->use_pio) {
-+		i2c->adap.algo = &i2c_pxa_pio_algorithm;
-+	} else {
-+		i2c->adap.algo = &i2c_pxa_algorithm;
-+		ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
-+				  i2c->adap.name, i2c);
-+		if (ret)
-+			goto ereqirq;
-+	}
+ /*
+@@ -95,10 +94,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
+ #ifdef CONFIG_IDEDISK_MULTI_MODE
+ 		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
+ 		id->multsect_valid = id->multsect ? 1 : 0;
+-		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
++		drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
+ 		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
+ #else	/* original, pre IDE-NFG, per request of AC */
+-		drive->mult_req = INITIAL_MULT_COUNT;
++		drive->mult_req = 0;
+ 		if (drive->mult_req > id->max_multsect)
+ 			drive->mult_req = id->max_multsect;
+ 		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
+@@ -129,6 +128,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
  
- 	i2c_pxa_reset(i2c);
+ 	drive->id_read = 1;
+ 	local_irq_enable();
++#ifdef DEBUG
++	printk(KERN_INFO "%s: dumping identify data\n", drive->name);
++	ide_dump_identify((u8 *)id);
++#endif
+ 	ide_fix_driveid(id);
  
- 	i2c->adap.algo_data = i2c;
- 	i2c->adap.dev.parent = &dev->dev;
+ #if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
+@@ -234,7 +237,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
  
--	if (plat) {
--		i2c->adap.class = plat->class;
--	}
--
- 	/*
- 	 * If "dev->id" is negative we consider it as zero.
- 	 * The reason to do so is to avoid sysfs names that only make
-@@ -952,17 +1073,11 @@ static int i2c_pxa_probe(struct platform_device *dev)
- 	return 0;
+ 	drive->media = ide_disk;
+ 	printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
+-	QUIRK_LIST(drive);
++
+ 	return;
  
- eadapt:
--	free_irq(irq, i2c);
-+	if (!i2c->use_pio)
-+		free_irq(irq, i2c);
- ereqirq:
- 	clk_disable(i2c->clk);
--
--#ifdef CONFIG_PXA27x
--	if (dev->id == 1) {
--		local_irq_disable();
--		PCFR &= ~PCFR_PI2CEN;
--		local_irq_enable();
--	}
--#endif
-+	i2c_pxa_disable(dev);
- eremap:
- 	clk_put(i2c->clk);
- eclk:
-@@ -979,18 +1094,12 @@ static int i2c_pxa_remove(struct platform_device *dev)
- 	platform_set_drvdata(dev, NULL);
+ err_misc:
+@@ -261,8 +264,7 @@ err_misc:
+ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	int rc;
+-	unsigned long hd_status;
++	int use_altstatus = 0, rc;
+ 	unsigned long timeout;
+ 	u8 s = 0, a = 0;
  
- 	i2c_del_adapter(&i2c->adap);
--	free_irq(i2c->irq, i2c);
-+	if (!i2c->use_pio)
-+		free_irq(i2c->irq, i2c);
+@@ -270,19 +272,17 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	msleep(50);
  
- 	clk_disable(i2c->clk);
- 	clk_put(i2c->clk);
--
--#ifdef CONFIG_PXA27x
--	if (dev->id == 1) {
--		local_irq_disable();
--		PCFR &= ~PCFR_PI2CEN;
--		local_irq_enable();
--	}
--#endif
-+	i2c_pxa_disable(dev);
+ 	if (IDE_CONTROL_REG) {
+-		a = hwif->INB(IDE_ALTSTATUS_REG);
+-		s = hwif->INB(IDE_STATUS_REG);
+-		if ((a ^ s) & ~INDEX_STAT) {
+-			printk(KERN_INFO "%s: probing with STATUS(0x%02x) instead of "
+-				"ALTSTATUS(0x%02x)\n", drive->name, s, a);
++		a = ide_read_altstatus(drive);
++		s = ide_read_status(drive);
++		if ((a ^ s) & ~INDEX_STAT)
+ 			/* ancient Seagate drives, broken interfaces */
+-			hd_status = IDE_STATUS_REG;
+-		} else {
++			printk(KERN_INFO "%s: probing with STATUS(0x%02x) "
++					 "instead of ALTSTATUS(0x%02x)\n",
++					 drive->name, s, a);
++		else
+ 			/* use non-intrusive polling */
+-			hd_status = IDE_ALTSTATUS_REG;
+-		}
+-	} else
+-		hd_status = IDE_STATUS_REG;
++			use_altstatus = 1;
++	}
  
- 	release_mem_region(i2c->iobase, i2c->iosize);
- 	kfree(i2c);
-diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
-index 503a134..8fbbdb4 100644
---- a/drivers/i2c/busses/i2c-sibyte.c
-+++ b/drivers/i2c/busses/i2c-sibyte.c
-@@ -36,14 +36,6 @@ struct i2c_algo_sibyte_data {
- /* ----- global defines ----------------------------------------------- */
- #define SMB_CSR(a,r) ((long)(a->reg_base + r))
+ 	/* set features register for atapi
+ 	 * identify command to be sure of reply
+@@ -303,11 +303,15 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ 		}
+ 		/* give drive a breather */
+ 		msleep(50);
+-	} while ((hwif->INB(hd_status)) & BUSY_STAT);
++		s = use_altstatus ? ide_read_altstatus(drive)
++				  : ide_read_status(drive);
++	} while (s & BUSY_STAT);
  
--/* ----- global variables --------------------------------------------- */
--
--/* module parameters:
-- */
--static int bit_scan;	/* have a look at what's hanging 'round */
--module_param(bit_scan, int, 0);
--MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
--
+ 	/* wait for IRQ and DRQ_STAT */
+ 	msleep(50);
+-	if (OK_STAT((hwif->INB(IDE_STATUS_REG)), DRQ_STAT, BAD_R_STAT)) {
++	s = ide_read_status(drive);
++
++	if (OK_STAT(s, DRQ_STAT, BAD_R_STAT)) {
+ 		unsigned long flags;
  
- static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
- 		      unsigned short flags, char read_write,
-@@ -140,9 +132,8 @@ static const struct i2c_algorithm i2c_sibyte_algo = {
- /*
-  * registering functions to load algorithms at runtime
-  */
--int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
-+int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
- {
--	int i;
- 	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+ 		/* local CPU only; some systems need this */
+@@ -317,7 +321,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
+ 		/* drive responded with ID */
+ 		rc = 0;
+ 		/* clear drive IRQ */
+-		(void) hwif->INB(IDE_STATUS_REG);
++		(void)ide_read_status(drive);
+ 		local_irq_restore(flags);
+ 	} else {
+ 		/* drive refused ID */
+@@ -350,24 +354,21 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	 * the irq handler isn't expecting.
+ 	 */
+ 	if (IDE_CONTROL_REG) {
+-		u8 ctl = drive->ctl | 2;
+ 		if (!hwif->irq) {
+ 			autoprobe = 1;
+ 			cookie = probe_irq_on();
+-			/* enable device irq */
+-			ctl &= ~2;
+ 		}
+-		hwif->OUTB(ctl, IDE_CONTROL_REG);
++		ide_set_irq(drive, autoprobe);
+ 	}
  
- 	/* register new adapter to i2c module... */
-@@ -152,24 +143,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
- 	csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
- 	csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+ 	retval = actual_try_to_identify(drive, cmd);
  
--	/* scan bus */
--	if (bit_scan) {
--		union i2c_smbus_data data;
--		int rc;
--		printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
--		       i2c_adap->name);
--		for (i = 0x00; i < 0x7f; i++) {
--			/* XXXKW is this a realistic probe? */
--			rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
--					I2C_SMBUS_BYTE_DATA, &data);
--			if (!rc) {
--				printk("(%02x)",i);
--			} else
--				printk(".");
--		}
--		printk("\n");
--	}
--
- 	return i2c_add_adapter(i2c_adap);
+ 	if (autoprobe) {
+ 		int irq;
+-		/* mask device irq */
+-		hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
++
++		ide_set_irq(drive, 0);
+ 		/* clear drive IRQ */
+-		(void) hwif->INB(IDE_STATUS_REG);
++		(void)ide_read_status(drive);
+ 		udelay(5);
+ 		irq = probe_irq_off(cookie);
+ 		if (!hwif->irq) {
+@@ -385,6 +386,20 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	return retval;
  }
  
-diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
-index 84df29d..c2a9f8c 100644
---- a/drivers/i2c/busses/i2c-stub.c
-+++ b/drivers/i2c/busses/i2c-stub.c
-@@ -1,8 +1,8 @@
- /*
--    i2c-stub.c - Part of lm_sensors, Linux kernel modules for hardware
--              monitoring
-+    i2c-stub.c - I2C/SMBus chip emulator
++static int ide_busy_sleep(ide_hwif_t *hwif)
++{
++	unsigned long timeout = jiffies + WAIT_WORSTCASE;
++	u8 stat;
++
++	do {
++		msleep(50);
++		stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++		if ((stat & BUSY_STAT) == 0)
++			return 0;
++	} while (time_before(jiffies, timeout));
++
++	return 1;
++}
  
-     Copyright (c) 2004 Mark M. Hoffman <mhoffman at lightlink.com>
-+    Copyright (C) 2007 Jean Delvare <khali at linux-fr.org>
+ /**
+  *	do_probe		-	probe an IDE device
+@@ -409,8 +424,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
  
-     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
-@@ -37,8 +37,8 @@ MODULE_PARM_DESC(chip_addr,
+ static int do_probe (ide_drive_t *drive, u8 cmd)
+ {
+-	int rc;
+ 	ide_hwif_t *hwif = HWIF(drive);
++	int rc;
++	u8 stat;
  
- struct stub_chip {
- 	u8 pointer;
--	u8 bytes[256];
--	u16 words[256];
-+	u16 words[256];		/* Byte operations use the LSB as per SMBus
-+				   specification */
- };
+ 	if (drive->present) {
+ 		/* avoid waiting for inappropriate probes */
+@@ -440,38 +456,40 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ 		return 3;
+ 	}
  
- static struct stub_chip *stub_chips;
-@@ -75,7 +75,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
- 					"wrote 0x%02x.\n",
- 					addr, command);
- 		} else {
--			data->byte = chip->bytes[chip->pointer++];
-+			data->byte = chip->words[chip->pointer++] & 0xff;
- 			dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
- 					"read  0x%02x.\n",
- 					addr, data->byte);
-@@ -86,12 +86,13 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+-	if (OK_STAT((hwif->INB(IDE_STATUS_REG)), READY_STAT, BUSY_STAT) ||
++	stat = ide_read_status(drive);
++
++	if (OK_STAT(stat, READY_STAT, BUSY_STAT) ||
+ 	    drive->present || cmd == WIN_PIDENTIFY) {
+ 		/* send cmd and wait */
+ 		if ((rc = try_to_identify(drive, cmd))) {
+ 			/* failed: try again */
+ 			rc = try_to_identify(drive,cmd);
+ 		}
+-		if (hwif->INB(IDE_STATUS_REG) == (BUSY_STAT|READY_STAT))
++
++		stat = ide_read_status(drive);
++
++		if (stat == (BUSY_STAT | READY_STAT))
+ 			return 4;
  
- 	case I2C_SMBUS_BYTE_DATA:
- 		if (read_write == I2C_SMBUS_WRITE) {
--			chip->bytes[command] = data->byte;
-+			chip->words[command] &= 0xff00;
-+			chip->words[command] |= data->byte;
- 			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
- 					"wrote 0x%02x at 0x%02x.\n",
- 					addr, data->byte, command);
- 		} else {
--			data->byte = chip->bytes[command];
-+			data->byte = chip->words[command] & 0xff;
- 			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
- 					"read  0x%02x at 0x%02x.\n",
- 					addr, data->byte, command);
-diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
-index c9ce77f..77b13d0 100644
---- a/drivers/i2c/busses/i2c-viapro.c
-+++ b/drivers/i2c/busses/i2c-viapro.c
-@@ -4,7 +4,7 @@
-     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol at dds.nl>,
-     Philip Edelbrock <phil at netroedge.com>, Kyösti Mälkki <kmalkki at cc.hut.fi>,
-     Mark D. Studebaker <mdsxyz123 at yahoo.com>
--    Copyright (C) 2005 - 2007  Jean Delvare <khali at linux-fr.org>
-+    Copyright (C) 2005 - 2008  Jean Delvare <khali at linux-fr.org>
+ 		if ((rc == 1 && cmd == WIN_PIDENTIFY) &&
+ 			((drive->autotune == IDE_TUNE_DEFAULT) ||
+ 			(drive->autotune == IDE_TUNE_AUTO))) {
+-			unsigned long timeout;
+-			printk("%s: no response (status = 0x%02x), "
+-				"resetting drive\n", drive->name,
+-				hwif->INB(IDE_STATUS_REG));
++			printk(KERN_ERR "%s: no response (status = 0x%02x), "
++					"resetting drive\n", drive->name, stat);
+ 			msleep(50);
+ 			hwif->OUTB(drive->select.all, IDE_SELECT_REG);
+ 			msleep(50);
+ 			hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
+-			timeout = jiffies;
+-			while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) &&
+-			       time_before(jiffies, timeout + WAIT_WORSTCASE))
+-				msleep(50);
++			(void)ide_busy_sleep(hwif);
+ 			rc = try_to_identify(drive, cmd);
+ 		}
++
++		/* ensure drive IRQ is clear */
++		stat = ide_read_status(drive);
++
+ 		if (rc == 1)
+-			printk("%s: no response (status = 0x%02x)\n",
+-				drive->name, hwif->INB(IDE_STATUS_REG));
+-		/* ensure drive irq is clear */
+-		(void) hwif->INB(IDE_STATUS_REG);
++			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
++					drive->name, stat);
+ 	} else {
+ 		/* not present or maybe ATAPI */
+ 		rc = 3;
+@@ -481,7 +499,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ 		SELECT_DRIVE(&hwif->drives[0]);
+ 		msleep(50);
+ 		/* ensure drive irq is clear */
+-		(void) hwif->INB(IDE_STATUS_REG);
++		(void)ide_read_status(drive);
+ 	}
+ 	return rc;
+ }
+@@ -492,28 +510,26 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
+ static void enable_nest (ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	unsigned long timeout;
++	u8 stat;
  
-     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
-@@ -35,6 +35,7 @@
-    VT8235             0x3177             yes
-    VT8237R            0x3227             yes
-    VT8237A            0x3337             yes
-+   VT8237S            0x3372             yes
-    VT8251             0x3287             yes
-    CX700              0x8324             yes
+ 	printk("%s: enabling %s -- ", hwif->name, drive->id->model);
+ 	SELECT_DRIVE(drive);
+ 	msleep(50);
+ 	hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
+-	timeout = jiffies + WAIT_WORSTCASE;
+-	do {
+-		if (time_after(jiffies, timeout)) {
+-			printk("failed (timeout)\n");
+-			return;
+-		}
+-		msleep(50);
+-	} while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT);
++
++	if (ide_busy_sleep(hwif)) {
++		printk(KERN_CONT "failed (timeout)\n");
++		return;
++	}
  
-@@ -318,6 +319,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
- 	unsigned char temp;
- 	int error = -ENODEV;
+ 	msleep(50);
  
-+	/* driver_data might come from user-space, so check it */
-+	if (id->driver_data & 1 || id->driver_data > 0xff)
-+		return -EINVAL;
+-	if (!OK_STAT((hwif->INB(IDE_STATUS_REG)), 0, BAD_STAT)) {
+-		printk("failed (status = 0x%02x)\n", hwif->INB(IDE_STATUS_REG));
+-	} else {
+-		printk("success\n");
+-	}
++	stat = ide_read_status(drive);
 +
- 	/* Determine the address of the SMBus areas */
- 	if (force_addr) {
- 		vt596_smba = force_addr & 0xfff0;
-@@ -389,6 +394,7 @@ found:
- 	case PCI_DEVICE_ID_VIA_8251:
- 	case PCI_DEVICE_ID_VIA_8237:
- 	case PCI_DEVICE_ID_VIA_8237A:
-+	case PCI_DEVICE_ID_VIA_8237S:
- 	case PCI_DEVICE_ID_VIA_8235:
- 	case PCI_DEVICE_ID_VIA_8233A:
- 	case PCI_DEVICE_ID_VIA_8233_0:
-@@ -440,6 +446,8 @@ static struct pci_device_id vt596_ids[] = {
- 	  .driver_data = SMBBA3 },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
- 	  .driver_data = SMBBA3 },
-+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237S),
-+	  .driver_data = SMBBA3 },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
- 	  .driver_data = SMBBA1 },
- 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
-@@ -455,6 +463,7 @@ static struct pci_driver vt596_driver = {
- 	.name		= "vt596_smbus",
- 	.id_table	= vt596_ids,
- 	.probe		= vt596_probe,
-+	.dynids.use_driver_data = 1,
- };
++	if (!OK_STAT(stat, 0, BAD_STAT))
++		printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
++	else
++		printk(KERN_CONT "success\n");
  
- static int __init i2c_vt596_init(void)
-diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
-index e6c4a2b..f5e7a70 100644
---- a/drivers/i2c/busses/scx200_acb.c
-+++ b/drivers/i2c/busses/scx200_acb.c
-@@ -492,7 +492,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
- 	iface->pdev = pdev;
- 	iface->bar = bar;
+ 	/* if !(success||timed-out) */
+ 	if (do_probe(drive, WIN_IDENTIFY) >= 2) {
+@@ -607,7 +623,7 @@ static void hwif_release_dev (struct device *dev)
+ 	complete(&hwif->gendev_rel_comp);
+ }
  
--	rc = pci_enable_device_bars(iface->pdev, 1 << iface->bar);
-+	rc = pci_enable_device_io(iface->pdev);
- 	if (rc)
- 		goto errout_free;
+-static void hwif_register (ide_hwif_t *hwif)
++static void ide_register_port(ide_hwif_t *hwif)
+ {
+ 	int ret;
  
-diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
-index 2e1c24f..bd7082c 100644
---- a/drivers/i2c/chips/Kconfig
-+++ b/drivers/i2c/chips/Kconfig
-@@ -4,32 +4,6 @@
+@@ -615,8 +631,8 @@ static void hwif_register (ide_hwif_t *hwif)
+ 	strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
+ 	hwif->gendev.driver_data = hwif;
+ 	if (hwif->gendev.parent == NULL) {
+-		if (hwif->pci_dev)
+-			hwif->gendev.parent = &hwif->pci_dev->dev;
++		if (hwif->dev)
++			hwif->gendev.parent = hwif->dev;
+ 		else
+ 			/* Would like to do = &device_legacy */
+ 			hwif->gendev.parent = NULL;
+@@ -628,7 +644,33 @@ static void hwif_register (ide_hwif_t *hwif)
+ 			__FUNCTION__, ret);
+ }
  
- menu "Miscellaneous I2C Chip support"
+-static int wait_hwif_ready(ide_hwif_t *hwif)
++/**
++ *	ide_port_wait_ready	-	wait for port to become ready
++ *	@hwif: IDE port
++ *
++ *	This is needed on some PPCs and a bunch of BIOS-less embedded
++ *	platforms.  Typical cases are:
++ *
++ *	- The firmware hard reset the disk before booting the kernel,
++ *	  the drive is still doing it's poweron-reset sequence, that
++ *	  can take up to 30 seconds.
++ *
++ *	- The firmware does nothing (or no firmware), the device is
++ *	  still in POST state (same as above actually).
++ *
++ *	- Some CD/DVD/Writer combo drives tend to drive the bus during
++ *	  their reset sequence even when they are non-selected slave
++ *	  devices, thus preventing discovery of the main HD.
++ *
++ *	Doing this wait-for-non-busy should not harm any existing
++ *	configuration and fix some issues like the above.
++ *
++ *	BenH.
++ *
++ *	Returns 0 on success, error code (< 0) otherwise.
++ */
++
++static int ide_port_wait_ready(ide_hwif_t *hwif)
+ {
+ 	int unit, rc;
  
--config SENSORS_DS1337
--	tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)"
--	depends on EXPERIMENTAL
--	help
--	  If you say yes here you get support for Dallas Semiconductor
--	  DS1337 and DS1339 real-time clock chips.
--
--	  This driver can also be built as a module.  If so, the module
--	  will be called ds1337.
--
--	  This driver is deprecated and will be dropped soon. Use
--	  rtc-ds1307 instead.
--
--config SENSORS_DS1374
--	tristate "Dallas DS1374 Real Time Clock (DEPRECATED)"
--	depends on EXPERIMENTAL
--	help
--	  If you say yes here you get support for Dallas Semiconductor
--	  DS1374 real-time clock chips.
--
--	  This driver can also be built as a module.  If so, the module
--	  will be called ds1374.
--
--	  This driver is deprecated and will be dropped soon. Use
--	  rtc-ds1374 instead.
--
- config DS1682
- 	tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
- 	depends on EXPERIMENTAL
-@@ -57,7 +31,7 @@ config SENSORS_PCF8574
- 	default n
- 	help
- 	  If you say yes here you get support for Philips PCF8574 and 
--	  PCF8574A chips.
-+	  PCF8574A chips. These chips are 8-bit I/O expanders for the I2C bus.
+@@ -653,8 +695,7 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
+ 		/* Ignore disks that we will not probe for later. */
+ 		if (!drive->noprobe || drive->present) {
+ 			SELECT_DRIVE(drive);
+-			if (IDE_CONTROL_REG)
+-				hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
++			ide_set_irq(drive, 1);
+ 			mdelay(2);
+ 			rc = ide_wait_not_busy(hwif, 35000);
+ 			if (rc)
+@@ -673,19 +714,18 @@ out:
  
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called pcf8574.
-@@ -65,6 +39,20 @@ config SENSORS_PCF8574
- 	  These devices are hard to detect and rarely found on mainstream
- 	  hardware.  If unsure, say N.
+ /**
+  *	ide_undecoded_slave	-	look for bad CF adapters
+- *	@hwif: interface
++ *	@drive1: drive
+  *
+  *	Analyse the drives on the interface and attempt to decide if we
+  *	have the same drive viewed twice. This occurs with crap CF adapters
+  *	and PCMCIA sometimes.
+  */
  
-+config PCF8575
-+	tristate "Philips PCF8575"
-+	default n
-+	help
-+	  If you say yes here you get support for Philips PCF8575 chip.
-+	  This chip is a 16-bit I/O expander for the I2C bus.  Several other
-+	  chip manufacturers sell equivalent chips, e.g. Texas Instruments.
-+
-+	  This driver can also be built as a module.  If so, the module
-+	  will be called pcf8575.
-+
-+	  This device is hard to detect and is rarely found on mainstream
-+	  hardware.  If unsure, say N.
-+
- config SENSORS_PCA9539
- 	tristate "Philips PCA9539 16-bit I/O port"
- 	depends on EXPERIMENTAL
-@@ -100,12 +88,8 @@ config ISP1301_OMAP
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called isp1301_omap.
+-void ide_undecoded_slave(ide_hwif_t *hwif)
++void ide_undecoded_slave(ide_drive_t *drive1)
+ {
+-	ide_drive_t *drive0 = &hwif->drives[0];
+-	ide_drive_t *drive1 = &hwif->drives[1];
++	ide_drive_t *drive0 = &drive1->hwif->drives[0];
  
--# NOTE:  This isn't really OMAP-specific, except for the current
--# interface location in  <include/asm-arm/arch-omap/tps65010.h>
--# and having mostly OMAP-specific board support
- config TPS65010
- 	tristate "TPS6501x Power Management chips"
--	depends on ARCH_OMAP
- 	default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
- 	help
- 	  If you say yes here you get support for the TPS6501x series of
-@@ -116,18 +100,6 @@ config TPS65010
- 	  This driver can also be built as a module.  If so, the module
- 	  will be called tps65010.
+-	if (drive0->present == 0 || drive1->present == 0)
++	if ((drive1->dn & 1) == 0 || drive0->present == 0)
+ 		return;
  
--config SENSORS_M41T00
--	tristate "ST M41T00 RTC chip (DEPRECATED)"
--	depends on PPC32
--	help
--	  If you say yes here you get support for the ST M41T00 RTC chip.
--
--	  This driver can also be built as a module.  If so, the module
--	  will be called m41t00.
--
--	  This driver is deprecated and will be dropped soon. Use
--	  rtc-ds1307 or rtc-m41t80 instead.
--
- config SENSORS_MAX6875
- 	tristate "Maxim MAX6875 Power supply supervisor"
- 	depends on EXPERIMENTAL
-diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
-index ca924e1..501f00c 100644
---- a/drivers/i2c/chips/Makefile
-+++ b/drivers/i2c/chips/Makefile
-@@ -2,14 +2,12 @@
- # Makefile for miscellaneous I2C chip drivers.
- #
+ 	/* If the models don't match they are not the same product */
+@@ -708,36 +748,16 @@ void ide_undecoded_slave(ide_hwif_t *hwif)
  
--obj-$(CONFIG_SENSORS_DS1337)	+= ds1337.o
--obj-$(CONFIG_SENSORS_DS1374)	+= ds1374.o
- obj-$(CONFIG_DS1682)		+= ds1682.o
- obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
- obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
--obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
- obj-$(CONFIG_SENSORS_PCA9539)	+= pca9539.o
- obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
-+obj-$(CONFIG_PCF8575)		+= pcf8575.o
- obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
- obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
- obj-$(CONFIG_TPS65010)		+= tps65010.o
-diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
-deleted file mode 100644
-index ec17d6b..0000000
---- a/drivers/i2c/chips/ds1337.c
-+++ /dev/null
-@@ -1,410 +0,0 @@
--/*
-- *  linux/drivers/i2c/chips/ds1337.c
-- *
-- *  Copyright (C) 2005 James Chapman <jchapman at katalix.com>
-- *
-- *	based on linux/drivers/acorn/char/pcf8583.c
-- *  Copyright (C) 2000 Russell King
-- *
-- * 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.
-- *
-- * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip
-- */
--
--#include <linux/module.h>
--#include <linux/init.h>
--#include <linux/slab.h>
--#include <linux/i2c.h>
--#include <linux/string.h>
--#include <linux/rtc.h>		/* get the user-level API */
--#include <linux/bcd.h>
--#include <linux/list.h>
--
--/* Device registers */
--#define DS1337_REG_HOUR		2
--#define DS1337_REG_DAY		3
--#define DS1337_REG_DATE		4
--#define DS1337_REG_MONTH	5
--#define DS1337_REG_CONTROL	14
--#define DS1337_REG_STATUS	15
--
--/* FIXME - how do we export these interface constants? */
--#define DS1337_GET_DATE		0
--#define DS1337_SET_DATE		1
--
--/*
-- * Functions declaration
-- */
--static unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END };
--
--I2C_CLIENT_INSMOD_1(ds1337);
--
--static int ds1337_attach_adapter(struct i2c_adapter *adapter);
--static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind);
--static void ds1337_init_client(struct i2c_client *client);
--static int ds1337_detach_client(struct i2c_client *client);
--static int ds1337_command(struct i2c_client *client, unsigned int cmd,
--			  void *arg);
--
--/*
-- * Driver data (common to all clients)
-- */
--static struct i2c_driver ds1337_driver = {
--	.driver = {
--		.name	= "ds1337",
--	},
--	.attach_adapter	= ds1337_attach_adapter,
--	.detach_client	= ds1337_detach_client,
--	.command	= ds1337_command,
--};
--
--/*
-- * Client data (each client gets its own)
-- */
--struct ds1337_data {
--	struct i2c_client client;
--	struct list_head list;
--};
--
--/*
-- * Internal variables
-- */
--static LIST_HEAD(ds1337_clients);
--
--static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
--{
--	s32 tmp = i2c_smbus_read_byte_data(client, reg);
--
--	if (tmp < 0)
--		return -EIO;
--
--	*value = tmp;
--
--	return 0;
--}
--
--/*
-- * Chip access functions
-- */
--static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
--{
--	int result;
--	u8 buf[7];
--	u8 val;
--	struct i2c_msg msg[2];
--	u8 offs = 0;
--
--	if (!dt) {
--		dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
--		return -EINVAL;
--	}
--
--	msg[0].addr = client->addr;
--	msg[0].flags = 0;
--	msg[0].len = 1;
--	msg[0].buf = &offs;
--
--	msg[1].addr = client->addr;
--	msg[1].flags = I2C_M_RD;
--	msg[1].len = sizeof(buf);
--	msg[1].buf = &buf[0];
--
--	result = i2c_transfer(client->adapter, msg, 2);
--
--	dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
--		__FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
--		buf[4], buf[5], buf[6]);
--
--	if (result == 2) {
--		dt->tm_sec = BCD2BIN(buf[0]);
--		dt->tm_min = BCD2BIN(buf[1]);
--		val = buf[2] & 0x3f;
--		dt->tm_hour = BCD2BIN(val);
--		dt->tm_wday = BCD2BIN(buf[3]) - 1;
--		dt->tm_mday = BCD2BIN(buf[4]);
--		val = buf[5] & 0x7f;
--		dt->tm_mon = BCD2BIN(val) - 1;
--		dt->tm_year = BCD2BIN(buf[6]);
--		if (buf[5] & 0x80)
--			dt->tm_year += 100;
--
--		dev_dbg(&client->dev, "%s: secs=%d, mins=%d, "
--			"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
--			__FUNCTION__, dt->tm_sec, dt->tm_min,
--			dt->tm_hour, dt->tm_mday,
--			dt->tm_mon, dt->tm_year, dt->tm_wday);
--
--		return 0;
--	}
--
--	dev_err(&client->dev, "error reading data! %d\n", result);
--	return -EIO;
--}
--
--static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
--{
--	int result;
--	u8 buf[8];
--	u8 val;
--	struct i2c_msg msg[1];
--
--	if (!dt) {
--		dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
--		return -EINVAL;
--	}
--
--	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
--		"mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
--		dt->tm_sec, dt->tm_min, dt->tm_hour,
--		dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
--
--	buf[0] = 0;		/* reg offset */
--	buf[1] = BIN2BCD(dt->tm_sec);
--	buf[2] = BIN2BCD(dt->tm_min);
--	buf[3] = BIN2BCD(dt->tm_hour);
--	buf[4] = BIN2BCD(dt->tm_wday + 1);
--	buf[5] = BIN2BCD(dt->tm_mday);
--	buf[6] = BIN2BCD(dt->tm_mon + 1);
--	val = dt->tm_year;
--	if (val >= 100) {
--		val -= 100;
--		buf[6] |= (1 << 7);
--	}
--	buf[7] = BIN2BCD(val);
--
--	msg[0].addr = client->addr;
--	msg[0].flags = 0;
--	msg[0].len = sizeof(buf);
--	msg[0].buf = &buf[0];
--
--	result = i2c_transfer(client->adapter, msg, 1);
--	if (result == 1)
--		return 0;
--
--	dev_err(&client->dev, "error writing data! %d\n", result);
--	return -EIO;
--}
--
--static int ds1337_command(struct i2c_client *client, unsigned int cmd,
--			  void *arg)
--{
--	dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
--
--	switch (cmd) {
--	case DS1337_GET_DATE:
--		return ds1337_get_datetime(client, arg);
--
--	case DS1337_SET_DATE:
--		return ds1337_set_datetime(client, arg);
--
--	default:
--		return -EINVAL;
--	}
--}
--
--/*
-- * Public API for access to specific device. Useful for low-level
-- * RTC access from kernel code.
-- */
--int ds1337_do_command(int bus, int cmd, void *arg)
--{
--	struct list_head *walk;
--	struct list_head *tmp;
--	struct ds1337_data *data;
--
--	list_for_each_safe(walk, tmp, &ds1337_clients) {
--		data = list_entry(walk, struct ds1337_data, list);
--		if (data->client.adapter->nr == bus)
--			return ds1337_command(&data->client, cmd, arg);
--	}
--
--	return -ENODEV;
--}
--
--static int ds1337_attach_adapter(struct i2c_adapter *adapter)
--{
--	return i2c_probe(adapter, &addr_data, ds1337_detect);
--}
--
--/*
-- * The following function does more than just detection. If detection
-- * succeeds, it also registers the new chip.
-- */
--static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
--{
--	struct i2c_client *new_client;
--	struct ds1337_data *data;
--	int err = 0;
--	const char *name = "";
--
--	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
--				     I2C_FUNC_I2C))
--		goto exit;
--
--	if (!(data = kzalloc(sizeof(struct ds1337_data), GFP_KERNEL))) {
--		err = -ENOMEM;
--		goto exit;
--	}
--	INIT_LIST_HEAD(&data->list);
--
--	/* The common I2C client data is placed right before the
--	 * DS1337-specific data. 
--	 */
--	new_client = &data->client;
--	i2c_set_clientdata(new_client, data);
--	new_client->addr = address;
--	new_client->adapter = adapter;
--	new_client->driver = &ds1337_driver;
--	new_client->flags = 0;
--
--	/*
--	 * Now we do the remaining detection. A negative kind means that
--	 * the driver was loaded with no force parameter (default), so we
--	 * must both detect and identify the chip. A zero kind means that
--	 * the driver was loaded with the force parameter, the detection
--	 * step shall be skipped. A positive kind means that the driver
--	 * was loaded with the force parameter and a given kind of chip is
--	 * requested, so both the detection and the identification steps
--	 * are skipped.
--	 *
--	 * For detection, we read registers that are most likely to cause
--	 * detection failure, i.e. those that have more bits with fixed
--	 * or reserved values.
--	 */
--
--	/* Default to an DS1337 if forced */
--	if (kind == 0)
--		kind = ds1337;
--
--	if (kind < 0) {		/* detection and identification */
--		u8 data;
--
--		/* Check that status register bits 6-2 are zero */
--		if ((ds1337_read(new_client, DS1337_REG_STATUS, &data) < 0) ||
--		    (data & 0x7c))
--			goto exit_free;
--
--		/* Check for a valid day register value */
--		if ((ds1337_read(new_client, DS1337_REG_DAY, &data) < 0) ||
--		    (data == 0) || (data & 0xf8))
--			goto exit_free;
--
--		/* Check for a valid date register value */
--		if ((ds1337_read(new_client, DS1337_REG_DATE, &data) < 0) ||
--		    (data == 0) || (data & 0xc0) || ((data & 0x0f) > 9) ||
--		    (data >= 0x32))
--			goto exit_free;
--
--		/* Check for a valid month register value */
--		if ((ds1337_read(new_client, DS1337_REG_MONTH, &data) < 0) ||
--		    (data == 0) || (data & 0x60) || ((data & 0x0f) > 9) ||
--		    ((data >= 0x13) && (data <= 0x19)))
--			goto exit_free;
--
--		/* Check that control register bits 6-5 are zero */
--		if ((ds1337_read(new_client, DS1337_REG_CONTROL, &data) < 0) ||
--		    (data & 0x60))
--			goto exit_free;
--
--		kind = ds1337;
--	}
--
--	if (kind == ds1337)
--		name = "ds1337";
--
--	/* We can fill in the remaining client fields */
--	strlcpy(new_client->name, name, I2C_NAME_SIZE);
--
--	/* Tell the I2C layer a new client has arrived */
--	if ((err = i2c_attach_client(new_client)))
--		goto exit_free;
--
--	/* Initialize the DS1337 chip */
--	ds1337_init_client(new_client);
--
--	/* Add client to local list */
--	list_add(&data->list, &ds1337_clients);
--
--	return 0;
--
--exit_free:
--	kfree(data);
--exit:
--	return err;
--}
--
--static void ds1337_init_client(struct i2c_client *client)
--{
--	u8 status, control;
--
--	/* On some boards, the RTC isn't configured by boot firmware.
--	 * Handle that case by starting/configuring the RTC now.
--	 */
--	status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
--	control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
--
--	if ((status & 0x80) || (control & 0x80)) {
--		/* RTC not running */
--		u8 buf[1+16];	/* First byte is interpreted as address */
--		struct i2c_msg msg[1];
--
--		dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
--
--		/* Initialize all, including STATUS and CONTROL to zero */
--		memset(buf, 0, sizeof(buf));
--
--		/* Write valid values in the date/time registers */
--		buf[1+DS1337_REG_DAY] = 1;
--		buf[1+DS1337_REG_DATE] = 1;
--		buf[1+DS1337_REG_MONTH] = 1;
--
--		msg[0].addr = client->addr;
--		msg[0].flags = 0;
--		msg[0].len = sizeof(buf);
--		msg[0].buf = &buf[0];
--
--		i2c_transfer(client->adapter, msg, 1);
--	} else {
--		/* Running: ensure that device is set in 24-hour mode */
--		s32 val;
--
--		val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
--		if ((val >= 0) && (val & (1 << 6)))
--			i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
--						  val & 0x3f);
--	}
--}
--
--static int ds1337_detach_client(struct i2c_client *client)
--{
--	int err;
--	struct ds1337_data *data = i2c_get_clientdata(client);
--
--	if ((err = i2c_detach_client(client)))
--		return err;
--
--	list_del(&data->list);
--	kfree(data);
--	return 0;
--}
--
--static int __init ds1337_init(void)
--{
--	return i2c_add_driver(&ds1337_driver);
--}
--
--static void __exit ds1337_exit(void)
--{
--	i2c_del_driver(&ds1337_driver);
--}
--
--MODULE_AUTHOR("James Chapman <jchapman at katalix.com>");
--MODULE_DESCRIPTION("DS1337 RTC driver");
--MODULE_LICENSE("GPL");
--
--EXPORT_SYMBOL_GPL(ds1337_do_command);
--
--module_init(ds1337_init);
--module_exit(ds1337_exit);
-diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
-deleted file mode 100644
-index 8a2ff0c..0000000
---- a/drivers/i2c/chips/ds1374.c
-+++ /dev/null
-@@ -1,267 +0,0 @@
--/*
-- * drivers/i2c/chips/ds1374.c
-- *
-- * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock
-- *
-- * Author: Randy Vinson <rvinson at mvista.com>
-- *
-- * Based on the m41t00.c by Mark Greer <mgreer at mvista.com>
-- *
-- * 2005 (c) MontaVista Software, Inc. This file is licensed under
-- * the terms of the GNU General Public License version 2. This program
-- * is licensed "as is" without any warranty of any kind, whether express
-- * or implied.
-- */
--/*
-- * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
-- * interface and the SMBus interface of the i2c subsystem.
-- * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
-- * recommened in .../Documentation/i2c/writing-clients section
-- * "Sending and receiving", using SMBus level communication is preferred.
+ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
+ 
+-/*
+- * This routine only knows how to look for drive units 0 and 1
+- * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
 - */
--
--#include <linux/kernel.h>
--#include <linux/module.h>
--#include <linux/interrupt.h>
--#include <linux/i2c.h>
--#include <linux/rtc.h>
--#include <linux/bcd.h>
--#include <linux/mutex.h>
--#include <linux/workqueue.h>
--
--#define DS1374_REG_TOD0		0x00
--#define DS1374_REG_TOD1		0x01
--#define DS1374_REG_TOD2		0x02
--#define DS1374_REG_TOD3		0x03
--#define DS1374_REG_WDALM0	0x04
--#define DS1374_REG_WDALM1	0x05
--#define DS1374_REG_WDALM2	0x06
--#define DS1374_REG_CR		0x07
--#define DS1374_REG_SR		0x08
--#define DS1374_REG_SR_OSF	0x80
--#define DS1374_REG_TCR		0x09
--
--#define	DS1374_DRV_NAME		"ds1374"
--
--static DEFINE_MUTEX(ds1374_mutex);
--
--static struct i2c_driver ds1374_driver;
--static struct i2c_client *save_client;
--
--static unsigned short ignore[] = { I2C_CLIENT_END };
--static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
--
--static struct i2c_client_address_data addr_data = {
--	.normal_i2c = normal_addr,
--	.probe = ignore,
--	.ignore = ignore,
--};
--
--static ulong ds1374_read_rtc(void)
--{
--	ulong time = 0;
--	int reg = DS1374_REG_WDALM0;
--
--	while (reg--) {
--		s32 tmp;
--		if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) {
--			dev_warn(&save_client->dev,
--				 "can't read from rtc chip\n");
--			return 0;
+-static void probe_hwif(ide_hwif_t *hwif)
++static int ide_probe_port(ide_hwif_t *hwif)
+ {
+ 	unsigned long flags;
+ 	unsigned int irqd;
+-	int unit;
++	int unit, rc = -ENODEV;
+ 
+-	if (hwif->noprobe)
+-		return;
++	BUG_ON(hwif->present);
+ 
+-	if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
+-	    (ide_hwif_request_regions(hwif))) {
+-		u16 msgout = 0;
+-		for (unit = 0; unit < MAX_DRIVES; ++unit) {
+-			ide_drive_t *drive = &hwif->drives[unit];
+-			if (drive->present) {
+-				drive->present = 0;
+-				printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n",
+-					drive->name);
+-				msgout = 1;
+-			}
 -		}
--		time = (time << 8) | (tmp & 0xff);
+-		if (!msgout)
+-			printk(KERN_ERR "%s: ports already in use, skipping probe\n",
+-				hwif->name);
+-		return;	
 -	}
--	return time;
--}
--
--static void ds1374_write_rtc(ulong time)
--{
--	int reg;
--
--	for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) {
--		if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff)
--		    < 0) {
--			dev_warn(&save_client->dev,
--				 "can't write to rtc chip\n");
--			break;
++	if (hwif->noprobe)
++		return -EACCES;
+ 
+ 	/*
+ 	 * We must always disable IRQ, as probe_for_drive will assert IRQ, but
+@@ -749,26 +769,7 @@ static void probe_hwif(ide_hwif_t *hwif)
+ 
+ 	local_irq_set(flags);
+ 
+-	/* This is needed on some PPCs and a bunch of BIOS-less embedded
+-	 * platforms. Typical cases are:
+-	 * 
+-	 *  - The firmware hard reset the disk before booting the kernel,
+-	 *    the drive is still doing it's poweron-reset sequence, that
+-	 *    can take up to 30 seconds
+-	 *  - The firmware does nothing (or no firmware), the device is
+-	 *    still in POST state (same as above actually).
+-	 *  - Some CD/DVD/Writer combo drives tend to drive the bus during
+-	 *    their reset sequence even when they are non-selected slave
+-	 *    devices, thus preventing discovery of the main HD
+-	 *    
+-	 *  Doing this wait-for-busy should not harm any existing configuration
+-	 *  (at least things won't be worse than what current code does, that
+-	 *  is blindly go & talk to the drive) and fix some issues like the
+-	 *  above.
+-	 *  
+-	 *  BenH.
+-	 */
+-	if (wait_hwif_ready(hwif) == -EBUSY)
++	if (ide_port_wait_ready(hwif) == -EBUSY)
+ 		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
+ 
+ 	/*
+@@ -778,28 +779,15 @@ static void probe_hwif(ide_hwif_t *hwif)
+ 		ide_drive_t *drive = &hwif->drives[unit];
+ 		drive->dn = (hwif->channel ? 2 : 0) + unit;
+ 		(void) probe_for_drive(drive);
+-		if (drive->present && !hwif->present) {
+-			hwif->present = 1;
+-			if (hwif->chipset != ide_4drives ||
+-			    !hwif->mate || 
+-			    !hwif->mate->present) {
+-				hwif_register(hwif);
+-			}
 -		}
--		time = time >> 8;
--	}
--}
++		if (drive->present)
++			rc = 0;
+ 	}
+ 	if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
+-		unsigned long timeout = jiffies + WAIT_WORSTCASE;
+-		u8 stat;
 -
--static void ds1374_check_rtc_status(void)
--{
--	s32 tmp;
+ 		printk(KERN_WARNING "%s: reset\n", hwif->name);
+ 		hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+ 		udelay(10);
+ 		hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
+-		do {
+-			msleep(50);
+-			stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
+-		} while ((stat & BUSY_STAT) && time_after(timeout, jiffies));
 -
--	tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR);
--	if (tmp < 0) {
--		dev_warn(&save_client->dev,
--			 "can't read status from rtc chip\n");
++		(void)ide_busy_sleep(hwif);
+ 	}
+ 	local_irq_restore(flags);
+ 	/*
+@@ -809,13 +797,19 @@ static void probe_hwif(ide_hwif_t *hwif)
+ 	if (irqd)
+ 		enable_irq(irqd);
+ 
+-	if (!hwif->present) {
+-		ide_hwif_release_regions(hwif);
 -		return;
 -	}
--	if (tmp & DS1374_REG_SR_OSF) {
--		dev_warn(&save_client->dev,
--			 "oscillator discontinuity flagged, time unreliable\n");
--		tmp &= ~DS1374_REG_SR_OSF;
--		tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR,
--						tmp & 0xff);
--		if (tmp < 0)
--			dev_warn(&save_client->dev,
--				 "can't clear discontinuity notification\n");
--	}
--}
--
--ulong ds1374_get_rtc_time(void)
--{
--	ulong t1, t2;
--	int limit = 10;		/* arbitrary retry limit */
--
--	mutex_lock(&ds1374_mutex);
--
--	/*
--	 * Since the reads are being performed one byte at a time using
--	 * the SMBus vs a 4-byte i2c transfer, there is a chance that a
--	 * carry will occur during the read. To detect this, 2 reads are
--	 * performed and compared.
--	 */
--	do {
--		t1 = ds1374_read_rtc();
--		t2 = ds1374_read_rtc();
--	} while (t1 != t2 && limit--);
--
--	mutex_unlock(&ds1374_mutex);
--
--	if (t1 != t2) {
--		dev_warn(&save_client->dev,
--			 "can't get consistent time from rtc chip\n");
--		t1 = 0;
--	}
--
--	return t1;
--}
--
--static ulong new_time;
--
--static void ds1374_set_work(struct work_struct *work)
--{
--	ulong t1, t2;
--	int limit = 10;		/* arbitrary retry limit */
--
--	t1 = new_time;
--
--	mutex_lock(&ds1374_mutex);
--
--	/*
--	 * Since the writes are being performed one byte at a time using
--	 * the SMBus vs a 4-byte i2c transfer, there is a chance that a
--	 * carry will occur during the write. To detect this, the write
--	 * value is read back and compared.
--	 */
--	do {
--		ds1374_write_rtc(t1);
--		t2 = ds1374_read_rtc();
--	} while (t1 != t2 && limit--);
--
--	mutex_unlock(&ds1374_mutex);
--
--	if (t1 != t2)
--		dev_warn(&save_client->dev,
--			 "can't confirm time set from rtc chip\n");
--}
--
--static struct workqueue_struct *ds1374_workqueue;
--
--static DECLARE_WORK(ds1374_work, ds1374_set_work);
--
--int ds1374_set_rtc_time(ulong nowtime)
--{
--	new_time = nowtime;
--
--	if (in_interrupt())
--		queue_work(ds1374_workqueue, &ds1374_work);
--	else
--		ds1374_set_work(NULL);
--
--	return 0;
--}
--
--/*
-- *****************************************************************************
-- *
-- *	Driver Interface
-- *
-- *****************************************************************************
-- */
--static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
--{
--	struct i2c_client *client;
--	int rc;
--
--	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
--	if (!client)
--		return -ENOMEM;
--
--	strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
--	client->addr = addr;
--	client->adapter = adap;
--	client->driver = &ds1374_driver;
--
--	ds1374_workqueue = create_singlethread_workqueue("ds1374");
--	if (!ds1374_workqueue) {
--		kfree(client);
--		return -ENOMEM;	/* most expected reason */
--	}
--
--	if ((rc = i2c_attach_client(client)) != 0) {
--		kfree(client);
--		return rc;
--	}
--
--	save_client = client;
--
--	ds1374_check_rtc_status();
--
--	return 0;
--}
--
--static int ds1374_attach(struct i2c_adapter *adap)
--{
--	return i2c_probe(adap, &addr_data, ds1374_probe);
--}
--
--static int ds1374_detach(struct i2c_client *client)
--{
--	int rc;
--
--	if ((rc = i2c_detach_client(client)) == 0) {
--		kfree(i2c_get_clientdata(client));
--		destroy_workqueue(ds1374_workqueue);
--	}
--	return rc;
--}
--
--static struct i2c_driver ds1374_driver = {
--	.driver = {
--		.name	= DS1374_DRV_NAME,
--	},
--	.id = I2C_DRIVERID_DS1374,
--	.attach_adapter = ds1374_attach,
--	.detach_client = ds1374_detach,
--};
--
--static int __init ds1374_init(void)
--{
--	return i2c_add_driver(&ds1374_driver);
--}
--
--static void __exit ds1374_exit(void)
--{
--	i2c_del_driver(&ds1374_driver);
--}
--
--module_init(ds1374_init);
--module_exit(ds1374_exit);
--
--MODULE_AUTHOR("Randy Vinson <rvinson at mvista.com>");
--MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver");
--MODULE_LICENSE("GPL");
-diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
-index 1a7eeeb..fde297b 100644
---- a/drivers/i2c/chips/eeprom.c
-+++ b/drivers/i2c/chips/eeprom.c
-@@ -35,7 +35,7 @@
- #include <linux/mutex.h>
++	return rc;
++}
  
- /* Addresses to scan */
--static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
-+static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
- 					0x55, 0x56, 0x57, I2C_CLIENT_END };
+-	if (hwif->fixup)
+-		hwif->fixup(hwif);
++static void ide_port_tune_devices(ide_hwif_t *hwif)
++{
++	int unit;
++
++	for (unit = 0; unit < MAX_DRIVES; unit++) {
++		ide_drive_t *drive = &hwif->drives[unit];
++
++		if (drive->present && hwif->quirkproc)
++			hwif->quirkproc(drive);
++	}
  
- /* Insmod parameters */
-diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
-index b767603..2a31601 100644
---- a/drivers/i2c/chips/isp1301_omap.c
-+++ b/drivers/i2c/chips/isp1301_omap.c
-@@ -100,7 +100,7 @@ struct isp1301 {
+ 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ 		ide_drive_t *drive = &hwif->drives[unit];
+@@ -830,48 +824,21 @@ static void probe_hwif(ide_hwif_t *hwif)
  
- #if	defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
+ 			drive->nice1 = 1;
  
--#include <asm/arch/tps65010.h>
-+#include <linux/i2c/tps65010.h>
+-			if (hwif->ide_dma_on) {
+-				/*
+-				 * Force DMAing for the beginning of the check.
+-				 * Some chipsets appear to do interesting
+-				 * things, if not checked and cleared.
+-				 *   PARANOIA!!!
+-				 */
+-				hwif->dma_off_quietly(drive);
++			if (hwif->dma_host_set)
+ 				ide_set_dma(drive);
+-			}
+ 		}
+ 	}
  
- #else
+ 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ 		ide_drive_t *drive = &hwif->drives[unit];
  
-@@ -259,12 +259,6 @@ static inline const char *state_name(struct isp1301 *isp)
- 	return state_string(isp->otg.state);
+-		if (hwif->no_io_32bit)
++		if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
+ 			drive->no_io_32bit = 1;
+ 		else
+ 			drive->no_io_32bit = drive->id->dword_io ? 1 : 0;
+ 	}
  }
  
--#ifdef	VERBOSE
--#define	dev_vdbg			dev_dbg
--#else
--#define	dev_vdbg(dev, fmt, arg...)	do{}while(0)
--#endif
--
- /*-------------------------------------------------------------------------*/
- 
- /* NOTE:  some of this ISP1301 setup is specific to H2 boards;
-diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
-deleted file mode 100644
-index 3fcb646..0000000
---- a/drivers/i2c/chips/m41t00.c
-+++ /dev/null
-@@ -1,413 +0,0 @@
--/*
-- * I2C client/driver for the ST M41T00 family of i2c rtc chips.
-- *
-- * Author: Mark A. Greer <mgreer at mvista.com>
-- *
-- * 2005, 2006 (c) MontaVista Software, Inc. This file is licensed under
-- * the terms of the GNU General Public License version 2. This program
-- * is licensed "as is" without any warranty of any kind, whether express
-- * or implied.
-- */
--/*
-- * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
-- * interface and the SMBus interface of the i2c subsystem.
-- */
--
--#include <linux/kernel.h>
--#include <linux/module.h>
--#include <linux/interrupt.h>
--#include <linux/i2c.h>
--#include <linux/rtc.h>
--#include <linux/bcd.h>
--#include <linux/workqueue.h>
--#include <linux/platform_device.h>
--#include <linux/m41t00.h>
--#include <asm/time.h>
--#include <asm/rtc.h>
--
--static struct i2c_driver m41t00_driver;
--static struct i2c_client *save_client;
--
--static unsigned short ignore[] = { I2C_CLIENT_END };
--static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END };
--
--static struct i2c_client_address_data addr_data = {
--	.normal_i2c	= normal_addr,
--	.probe		= ignore,
--	.ignore		= ignore,
--};
--
--struct m41t00_chip_info {
--	u8	type;
--	char	*name;
--	u8	read_limit;
--	u8	sec;		/* Offsets for chip regs */
--	u8	min;
--	u8	hour;
--	u8	day;
--	u8	mon;
--	u8	year;
--	u8	alarm_mon;
--	u8	alarm_hour;
--	u8	sqw;
--	u8	sqw_freq;
--};
--
--static struct m41t00_chip_info m41t00_chip_info_tbl[] = {
--	{
--		.type		= M41T00_TYPE_M41T00,
--		.name		= "m41t00",
--		.read_limit	= 5,
--		.sec		= 0,
--		.min		= 1,
--		.hour		= 2,
--		.day		= 4,
--		.mon		= 5,
--		.year		= 6,
--	},
--	{
--		.type		= M41T00_TYPE_M41T81,
--		.name		= "m41t81",
--		.read_limit	= 1,
--		.sec		= 1,
--		.min		= 2,
--		.hour		= 3,
--		.day		= 5,
--		.mon		= 6,
--		.year		= 7,
--		.alarm_mon	= 0xa,
--		.alarm_hour	= 0xc,
--		.sqw		= 0x13,
--	},
--	{
--		.type		= M41T00_TYPE_M41T85,
--		.name		= "m41t85",
--		.read_limit	= 1,
--		.sec		= 1,
--		.min		= 2,
--		.hour		= 3,
--		.day		= 5,
--		.mon		= 6,
--		.year		= 7,
--		.alarm_mon	= 0xa,
--		.alarm_hour	= 0xc,
--		.sqw		= 0x13,
--	},
--};
--static struct m41t00_chip_info *m41t00_chip;
--
--ulong
--m41t00_get_rtc_time(void)
--{
--	s32 sec, min, hour, day, mon, year;
--	s32 sec1, min1, hour1, day1, mon1, year1;
--	u8 reads = 0;
--	u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */
--	struct i2c_msg msgs[] = {
--		{
--			.addr	= save_client->addr,
--			.flags	= 0,
--			.len	= 1,
--			.buf	= msgbuf,
--		},
--		{
--			.addr	= save_client->addr,
--			.flags	= I2C_M_RD,
--			.len	= 8,
--			.buf	= buf,
--		},
--	};
--
--	sec = min = hour = day = mon = year = 0;
--
--	do {
--		if (i2c_transfer(save_client->adapter, msgs, 2) < 0)
--			goto read_err;
--
--		sec1 = sec;
--		min1 = min;
--		hour1 = hour;
--		day1 = day;
--		mon1 = mon;
--		year1 = year;
--
--		sec = buf[m41t00_chip->sec] & 0x7f;
--		min = buf[m41t00_chip->min] & 0x7f;
--		hour = buf[m41t00_chip->hour] & 0x3f;
--		day = buf[m41t00_chip->day] & 0x3f;
--		mon = buf[m41t00_chip->mon] & 0x1f;
--		year = buf[m41t00_chip->year];
--	} while ((++reads < m41t00_chip->read_limit) && ((sec != sec1)
--			|| (min != min1) || (hour != hour1) || (day != day1)
--			|| (mon != mon1) || (year != year1)));
--
--	if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1)
--			|| (hour != hour1) || (day != day1) || (mon != mon1)
--			|| (year != year1)))
--		goto read_err;
--
--	sec = BCD2BIN(sec);
--	min = BCD2BIN(min);
--	hour = BCD2BIN(hour);
--	day = BCD2BIN(day);
--	mon = BCD2BIN(mon);
--	year = BCD2BIN(year);
--
--	year += 1900;
--	if (year < 1970)
--		year += 100;
--
--	return mktime(year, mon, day, hour, min, sec);
--
--read_err:
--	dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n");
--	return 0;
--}
--EXPORT_SYMBOL_GPL(m41t00_get_rtc_time);
+-static int hwif_init(ide_hwif_t *hwif);
+-static void hwif_register_devices(ide_hwif_t *hwif);
 -
--static void
--m41t00_set(void *arg)
+-static int probe_hwif_init(ide_hwif_t *hwif)
 -{
--	struct rtc_time	tm;
--	int nowtime = *(int *)arg;
--	s32 sec, min, hour, day, mon, year;
--	u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 };
--	struct i2c_msg msgs[] = {
--		{
--			.addr	= save_client->addr,
--			.flags	= 0,
--			.len	= 1,
--			.buf	= msgbuf,
--		},
--		{
--			.addr	= save_client->addr,
--			.flags	= I2C_M_RD,
--			.len	= 8,
--			.buf	= buf,
--		},
--	};
--
--	to_tm(nowtime, &tm);
--	tm.tm_year = (tm.tm_year - 1900) % 100;
--
--	sec = BIN2BCD(tm.tm_sec);
--	min = BIN2BCD(tm.tm_min);
--	hour = BIN2BCD(tm.tm_hour);
--	day = BIN2BCD(tm.tm_mday);
--	mon = BIN2BCD(tm.tm_mon);
--	year = BIN2BCD(tm.tm_year);
+-	probe_hwif(hwif);
 -
--	/* Read reg values into buf[0..7]/wbuf[1..8] */
--	if (i2c_transfer(save_client->adapter, msgs, 2) < 0) {
--		dev_err(&save_client->dev, "m41t00_set: Read error\n");
--		return;
+-	if (!hwif_init(hwif)) {
+-		printk(KERN_INFO "%s: failed to initialize IDE interface\n",
+-				 hwif->name);
+-		return -1;
 -	}
 -
--	wbuf[0] = 0; /* offset into rtc's regs */
--	buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f);
--	buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f);
--	buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f);
--	buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f);
--	buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f);
--	buf[m41t00_chip->year] = year;
--
--	if (i2c_master_send(save_client, wbuf, 9) < 0)
--		dev_err(&save_client->dev, "m41t00_set: Write error\n");
--}
--
--static ulong new_time;
--/* well, isn't this API just _lovely_? */
--static void
--m41t00_barf(struct work_struct *unusable)
--{
--	m41t00_set(&new_time);
--}
--
--static struct workqueue_struct *m41t00_wq;
--static DECLARE_WORK(m41t00_work, m41t00_barf);
--
--int
--m41t00_set_rtc_time(ulong nowtime)
--{
--	new_time = nowtime;
--
--	if (in_interrupt())
--		queue_work(m41t00_wq, &m41t00_work);
--	else
--		m41t00_set(&new_time);
+-	if (hwif->present)
+-		hwif_register_devices(hwif);
 -
 -	return 0;
 -}
--EXPORT_SYMBOL_GPL(m41t00_set_rtc_time);
 -
--/*
-- *****************************************************************************
-- *
-- *	platform_data Driver Interface
+ #if MAX_HWIFS > 1
+ /*
+  * save_match() is used to simplify logic in init_irq() below.
+@@ -924,13 +891,6 @@ static int ide_init_queue(ide_drive_t *drive)
+ 	q->queuedata = drive;
+ 	blk_queue_segment_boundary(q, 0xffff);
+ 
+-	if (!hwif->rqsize) {
+-		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
+-		    (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
+-			hwif->rqsize = 256;
+-		else
+-			hwif->rqsize = 65536;
+-	}
+ 	if (hwif->rqsize < max_sectors)
+ 		max_sectors = hwif->rqsize;
+ 	blk_queue_max_sectors(q, max_sectors);
+@@ -961,6 +921,48 @@ static int ide_init_queue(ide_drive_t *drive)
+ 	return 0;
+ }
+ 
++static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
++{
++	ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
++
++	spin_lock_irq(&ide_lock);
++	if (!hwgroup->drive) {
++		/* first drive for hwgroup. */
++		drive->next = drive;
++		hwgroup->drive = drive;
++		hwgroup->hwif = HWIF(hwgroup->drive);
++	} else {
++		drive->next = hwgroup->drive->next;
++		hwgroup->drive->next = drive;
++	}
++	spin_unlock_irq(&ide_lock);
++}
++
++/*
++ * For any present drive:
++ * - allocate the block device queue
++ * - link drive into the hwgroup
++ */
++static void ide_port_setup_devices(ide_hwif_t *hwif)
++{
++	int i;
++
++	for (i = 0; i < MAX_DRIVES; i++) {
++		ide_drive_t *drive = &hwif->drives[i];
++
++		if (!drive->present)
++			continue;
++
++		if (ide_init_queue(drive)) {
++			printk(KERN_ERR "ide: failed to init %s\n",
++					drive->name);
++			continue;
++		}
++
++		ide_add_drive_to_hwgroup(drive);
++	}
++}
++
+ /*
+  * This routine sets up the irq for an ide interface, and creates a new
+  * hwgroup for the irq/hwif if none was previously assigned.
+@@ -968,11 +970,6 @@ static int ide_init_queue(ide_drive_t *drive)
+  * Much of the code is for correctly detecting/handling irq sharing
+  * and irq serialization situations.  This is somewhat complex because
+  * it handles static as well as dynamic (PCMCIA) IDE interfaces.
 - *
-- *****************************************************************************
-- */
--static int __init
--m41t00_platform_probe(struct platform_device *pdev)
--{
--	struct m41t00_platform_data *pdata;
--	int i;
--
--	if (pdev && (pdata = pdev->dev.platform_data)) {
--		normal_addr[0] = pdata->i2c_addr;
--
--		for (i=0; i<ARRAY_SIZE(m41t00_chip_info_tbl); i++)
--			if (m41t00_chip_info_tbl[i].type == pdata->type) {
--				m41t00_chip = &m41t00_chip_info_tbl[i];
--				m41t00_chip->sqw_freq = pdata->sqw_freq;
--				return 0;
--			}
+- * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with
+- * interrupts completely disabled.  This can be bad for interrupt latency,
+- * but anything else has led to problems on some machines.  We re-enable
+- * interrupts as much as we can safely do in most places.
+  */
+ static int init_irq (ide_hwif_t *hwif)
+ {
+@@ -1031,21 +1028,17 @@ static int init_irq (ide_hwif_t *hwif)
+ 		spin_lock_irq(&ide_lock);
+ 		hwif->next = hwgroup->hwif->next;
+ 		hwgroup->hwif->next = hwif;
++		BUG_ON(hwif->next == hwif);
+ 		spin_unlock_irq(&ide_lock);
+ 	} else {
+-		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
+-					GFP_KERNEL | __GFP_ZERO,
+-					hwif_to_node(hwif->drives[0].hwif));
+-		if (!hwgroup)
+-	       		goto out_up;
++		hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
++				       hwif_to_node(hwif));
++		if (hwgroup == NULL)
++			goto out_up;
+ 
+ 		hwif->hwgroup = hwgroup;
++		hwgroup->hwif = hwif->next = hwif;
+ 
+-		hwgroup->hwif     = hwif->next = hwif;
+-		hwgroup->rq       = NULL;
+-		hwgroup->handler  = NULL;
+-		hwgroup->drive    = NULL;
+-		hwgroup->busy     = 0;
+ 		init_timer(&hwgroup->timer);
+ 		hwgroup->timer.function = &ide_timer_expiry;
+ 		hwgroup->timer.data = (unsigned long) hwgroup;
+@@ -1055,17 +1048,13 @@ static int init_irq (ide_hwif_t *hwif)
+ 	 * Allocate the irq, if not already obtained for another hwif
+ 	 */
+ 	if (!match || match->irq != hwif->irq) {
+-		int sa = IRQF_DISABLED;
++		int sa = 0;
+ #if defined(__mc68000__) || defined(CONFIG_APUS)
+ 		sa = IRQF_SHARED;
+ #endif /* __mc68000__ || CONFIG_APUS */
+ 
+-		if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
++		if (IDE_CHIPSET_IS_PCI(hwif->chipset))
+ 			sa = IRQF_SHARED;
+-#ifndef CONFIG_IDEPCI_SHARE_IRQ
+-			sa |= IRQF_DISABLED;
+-#endif /* CONFIG_IDEPCI_SHARE_IRQ */
+-		}
+ 
+ 		if (hwif->io_ports[IDE_CONTROL_OFFSET])
+ 			/* clear nIEN */
+@@ -1075,30 +1064,12 @@ static int init_irq (ide_hwif_t *hwif)
+ 	       		goto out_unlink;
+ 	}
+ 
+-	/*
+-	 * For any present drive:
+-	 * - allocate the block device queue
+-	 * - link drive into the hwgroup
+-	 */
+-	for (index = 0; index < MAX_DRIVES; ++index) {
+-		ide_drive_t *drive = &hwif->drives[index];
+-		if (!drive->present)
+-			continue;
+-		if (ide_init_queue(drive)) {
+-			printk(KERN_ERR "ide: failed to init %s\n",drive->name);
+-			continue;
+-		}
+-		spin_lock_irq(&ide_lock);
+-		if (!hwgroup->drive) {
+-			/* first drive for hwgroup. */
+-			drive->next = drive;
+-			hwgroup->drive = drive;
+-			hwgroup->hwif = HWIF(hwgroup->drive);
+-		} else {
+-			drive->next = hwgroup->drive->next;
+-			hwgroup->drive->next = drive;
+-		}
+-		spin_unlock_irq(&ide_lock);
++	if (!hwif->rqsize) {
++		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
++		    (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
++			hwif->rqsize = 256;
++		else
++			hwif->rqsize = 65536;
+ 	}
+ 
+ #if !defined(__mc68000__) && !defined(CONFIG_APUS)
+@@ -1114,28 +1085,13 @@ static int init_irq (ide_hwif_t *hwif)
+ 		printk(" (%sed with %s)",
+ 			hwif->sharing_irq ? "shar" : "serializ", match->name);
+ 	printk("\n");
++
++	ide_port_setup_devices(hwif);
++
+ 	mutex_unlock(&ide_cfg_mtx);
+ 	return 0;
+ out_unlink:
+-	spin_lock_irq(&ide_lock);
+-	if (hwif->next == hwif) {
+-		BUG_ON(match);
+-		BUG_ON(hwgroup->hwif != hwif);
+-		kfree(hwgroup);
+-	} else {
+-		ide_hwif_t *g;
+-		g = hwgroup->hwif;
+-		while (g->next != hwif)
+-			g = g->next;
+-		g->next = hwif->next;
+-		if (hwgroup->hwif == hwif) {
+-			/* Impossible. */
+-			printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");
+-			hwgroup->hwif = g;
+-		}
+-		BUG_ON(hwgroup->hwif == hwif);
 -	}
--	return -ENODEV;
--}
--
--static int __exit
--m41t00_platform_remove(struct platform_device *pdev)
--{
--	return 0;
--}
--
--static struct platform_driver m41t00_platform_driver = {
--	.probe  = m41t00_platform_probe,
--	.remove = m41t00_platform_remove,
--	.driver = {
--		.owner = THIS_MODULE,
--		.name  = M41T00_DRV_NAME,
--	},
--};
--
+-	spin_unlock_irq(&ide_lock);
++	ide_remove_port_from_hwgroup(hwif);
+ out_up:
+ 	mutex_unlock(&ide_cfg_mtx);
+ 	return 1;
+@@ -1173,7 +1129,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
+ {
+ 	struct gendisk *p = data;
+ 	*part &= (1 << PARTN_BITS) - 1;
+-	return &p->kobj;
++	return &p->dev.kobj;
+ }
+ 
+ static int exact_lock(dev_t dev, void *data)
+@@ -1256,56 +1212,25 @@ static void drive_release_dev (struct device *dev)
+ 	complete(&drive->gendev_rel_comp);
+ }
+ 
 -/*
-- *****************************************************************************
-- *
-- *	Driver Interface
-- *
-- *****************************************************************************
+- * init_gendisk() (as opposed to ide_geninit) is called for each major device,
+- * after probing for drives, to allocate partition tables and other data
+- * structures needed for the routines in genhd.c.  ide_geninit() gets called
+- * somewhat later, during the partition check.
 - */
--static int
--m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
--{
--	struct i2c_client *client;
--	int rc;
--
--	if (!i2c_check_functionality(adap, I2C_FUNC_I2C
--			| I2C_FUNC_SMBUS_BYTE_DATA))
--		return 0;
--
--	client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
--	if (!client)
--		return -ENOMEM;
--
--	strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE);
--	client->addr = addr;
--	client->adapter = adap;
--	client->driver = &m41t00_driver;
--
--	if ((rc = i2c_attach_client(client)))
--		goto attach_err;
--
--	if (m41t00_chip->type != M41T00_TYPE_M41T00) {
--		/* If asked, disable SQW, set SQW frequency & re-enable */
--		if (m41t00_chip->sqw_freq)
--			if (((rc = i2c_smbus_read_byte_data(client,
--					m41t00_chip->alarm_mon)) < 0)
--			 || ((rc = i2c_smbus_write_byte_data(client,
--					m41t00_chip->alarm_mon, rc & ~0x40)) <0)
--			 || ((rc = i2c_smbus_write_byte_data(client,
--					m41t00_chip->sqw,
--					m41t00_chip->sqw_freq)) < 0)
--			 || ((rc = i2c_smbus_write_byte_data(client,
--					m41t00_chip->alarm_mon, rc | 0x40)) <0))
--				goto sqw_err;
--
--		/* Make sure HT (Halt Update) bit is cleared */
--		if ((rc = i2c_smbus_read_byte_data(client,
--				m41t00_chip->alarm_hour)) < 0)
--			goto ht_err;
--
--		if (rc & 0x40)
--			if ((rc = i2c_smbus_write_byte_data(client,
--					m41t00_chip->alarm_hour, rc & ~0x40))<0)
--				goto ht_err;
--	}
--
--	/* Make sure ST (stop) bit is cleared */
--	if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0)
--		goto st_err;
--
--	if (rc & 0x80)
--		if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec,
--				rc & ~0x80)) < 0)
--			goto st_err;
--
--	m41t00_wq = create_singlethread_workqueue(m41t00_chip->name);
--	save_client = client;
--	return 0;
--
--st_err:
--	dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n");
--	goto attach_err;
--ht_err:
--	dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n");
--	goto attach_err;
--sqw_err:
--	dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n");
--attach_err:
--	kfree(client);
--	return rc;
--}
--
--static int
--m41t00_attach(struct i2c_adapter *adap)
--{
--	return i2c_probe(adap, &addr_data, m41t00_probe);
--}
--
--static int
--m41t00_detach(struct i2c_client *client)
+-static void init_gendisk (ide_hwif_t *hwif)
 -{
--	int rc;
+-	unsigned int unit;
 -
--	if ((rc = i2c_detach_client(client)) == 0) {
--		kfree(client);
--		destroy_workqueue(m41t00_wq);
+-	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+-		ide_drive_t * drive = &hwif->drives[unit];
+-		ide_add_generic_settings(drive);
+-		snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u",
+-			 hwif->index,unit);
+-		drive->gendev.parent = &hwif->gendev;
+-		drive->gendev.bus = &ide_bus_type;
+-		drive->gendev.driver_data = drive;
+-		drive->gendev.release = drive_release_dev;
 -	}
--	return rc;
+-	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
+-			THIS_MODULE, ata_probe, ata_lock, hwif);
 -}
 -
--static struct i2c_driver m41t00_driver = {
--	.driver = {
--		.name	= M41T00_DRV_NAME,
--	},
--	.id		= I2C_DRIVERID_STM41T00,
--	.attach_adapter	= m41t00_attach,
--	.detach_client	= m41t00_detach,
--};
--
--static int __init
--m41t00_init(void)
--{
--	int rc;
+ static int hwif_init(ide_hwif_t *hwif)
+ {
+ 	int old_irq;
+ 
+-	/* Return success if no device is connected */
+-	if (!hwif->present)
+-		return 1;
 -
--	if (!(rc = platform_driver_register(&m41t00_platform_driver)))
--		rc = i2c_add_driver(&m41t00_driver);
--	return rc;
--}
+ 	if (!hwif->irq) {
+ 		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
+ 		{
+ 			printk("%s: DISABLED, NO IRQ\n", hwif->name);
+-			return (hwif->present = 0);
++			return 0;
+ 		}
+ 	}
+ #ifdef CONFIG_BLK_DEV_HD
+ 	if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
+ 		printk("%s: CANNOT SHARE IRQ WITH OLD "
+ 			"HARDDISK DRIVER (hd.c)\n", hwif->name);
+-		return (hwif->present = 0);
++		return 0;
+ 	}
+ #endif /* CONFIG_BLK_DEV_HD */
+ 
+-	/* we set it back to 1 if all is ok below */	
+-	hwif->present = 0;
 -
--static void __exit
--m41t00_exit(void)
--{
--	i2c_del_driver(&m41t00_driver);
--	platform_driver_unregister(&m41t00_platform_driver);
--}
+ 	if (register_blkdev(hwif->major, hwif->name))
+ 		return 0;
+ 
+@@ -1343,11 +1268,8 @@ static int hwif_init(ide_hwif_t *hwif)
+ 		hwif->name, hwif->irq);
+ 
+ done:
+-	init_gendisk(hwif);
 -
--module_init(m41t00_init);
--module_exit(m41t00_exit);
+-	ide_acpi_init(hwif);
 -
--MODULE_AUTHOR("Mark A. Greer <mgreer at mvista.com>");
--MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver");
--MODULE_LICENSE("GPL");
-diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
-index 64692f6..fb7ea56 100644
---- a/drivers/i2c/chips/max6875.c
-+++ b/drivers/i2c/chips/max6875.c
-@@ -34,7 +34,7 @@
- #include <linux/mutex.h>
+-	hwif->present = 1;	/* success */
++	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
++			    THIS_MODULE, ata_probe, ata_lock, hwif);
+ 	return 1;
  
- /* Do not scan - the MAX6875 access method will write to some EEPROM chips */
--static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-+static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
+ out:
+@@ -1361,66 +1283,204 @@ static void hwif_register_devices(ide_hwif_t *hwif)
  
- /* Insmod parameters */
- I2C_CLIENT_INSMOD_1(max6875);
-diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
-index 21c6dd6..b3b830c 100644
---- a/drivers/i2c/chips/pcf8574.c
-+++ b/drivers/i2c/chips/pcf8574.c
-@@ -41,9 +41,11 @@
- #include <linux/i2c.h>
+ 	for (i = 0; i < MAX_DRIVES; i++) {
+ 		ide_drive_t *drive = &hwif->drives[i];
++		struct device *dev = &drive->gendev;
++		int ret;
  
- /* Addresses to scan */
--static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
--					0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
--					I2C_CLIENT_END };
-+static const unsigned short normal_i2c[] = {
-+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-+	I2C_CLIENT_END
-+};
+-		if (drive->present) {
+-			int ret = device_register(&drive->gendev);
++		if (!drive->present)
++			continue;
  
- /* Insmod parameters */
- I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
-diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c
-new file mode 100644
-index 0000000..3ea08ac
---- /dev/null
-+++ b/drivers/i2c/chips/pcf8575.c
-@@ -0,0 +1,214 @@
-+/*
-+  pcf8575.c
-+
-+  About the PCF8575 chip: the PCF8575 is a 16-bit I/O expander for the I2C bus
-+  produced by a.o. Philips Semiconductors.
-+
-+  Copyright (C) 2006 Michael Hennerich, Analog Devices Inc.
-+  <hennerich at blackfin.uclinux.org>
-+  Based on pcf8574.c.
+-			if (ret < 0)
+-				printk(KERN_WARNING "IDE: %s: "
+-					"device_register error: %d\n",
+-					__FUNCTION__, ret);
+-		}
++		ide_add_generic_settings(drive);
 +
-+  Copyright (c) 2007 Bart Van Assche <bart.vanassche at gmail.com>.
-+  Ported this driver from ucLinux to the mainstream Linux kernel.
++		snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
++		dev->parent = &hwif->gendev;
++		dev->bus = &ide_bus_type;
++		dev->driver_data = drive;
++		dev->release = drive_release_dev;
 +
-+  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.
++		ret = device_register(dev);
++		if (ret < 0)
++			printk(KERN_WARNING "IDE: %s: device_register error: "
++					    "%d\n", __func__, ret);
+ 	}
+ }
+ 
+-int ideprobe_init (void)
++static void ide_port_init_devices(ide_hwif_t *hwif)
+ {
+-	unsigned int index;
+-	int probe[MAX_HWIFS];
+-
+-	memset(probe, 0, MAX_HWIFS * sizeof(int));
+-	for (index = 0; index < MAX_HWIFS; ++index)
+-		probe[index] = !ide_hwifs[index].present;
+-
+-	for (index = 0; index < MAX_HWIFS; ++index)
+-		if (probe[index])
+-			probe_hwif(&ide_hwifs[index]);
+-	for (index = 0; index < MAX_HWIFS; ++index)
+-		if (probe[index])
+-			hwif_init(&ide_hwifs[index]);
+-	for (index = 0; index < MAX_HWIFS; ++index) {
+-		if (probe[index]) {
+-			ide_hwif_t *hwif = &ide_hwifs[index];
+-			if (!hwif->present)
+-				continue;
+-			if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced)
+-				hwif->chipset = ide_generic;
+-			hwif_register_devices(hwif);
+-		}
++	int i;
 +
-+  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.
++	for (i = 0; i < MAX_DRIVES; i++) {
++		ide_drive_t *drive = &hwif->drives[i];
 +
-+  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.
-+*/
++		if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
++			drive->io_32bit = 1;
++		if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
++			drive->unmask = 1;
++		if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
++			drive->no_unmask = 1;
++		if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0)
++			drive->autotune = 1;
+ 	}
+-	for (index = 0; index < MAX_HWIFS; ++index)
+-		if (probe[index])
+-			ide_proc_register_port(&ide_hwifs[index]);
+-	return 0;
 +
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/i2c.h>
-+#include <linux/slab.h>  /* kzalloc() */
-+#include <linux/sysfs.h> /* sysfs_create_group() */
++	if (hwif->port_init_devs)
++		hwif->port_init_devs(hwif);
+ }
+ 
+-EXPORT_SYMBOL_GPL(ideprobe_init);
++static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
++			  const struct ide_port_info *d)
++{
++	if (d->chipset != ide_etrax100)
++		hwif->channel = port;
 +
-+/* Addresses to scan */
-+static const unsigned short normal_i2c[] = {
-+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-+	I2C_CLIENT_END
-+};
++	if (d->chipset)
++		hwif->chipset = d->chipset;
 +
-+/* Insmod parameters */
-+I2C_CLIENT_INSMOD;
++	if (d->init_iops)
++		d->init_iops(hwif);
 +
++	if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
++		ide_hwif_setup_dma(hwif, d);
 +
-+/* Each client has this additional data */
-+struct pcf8575_data {
-+	struct i2c_client client;
-+	int write;		/* last written value, or error code */
-+};
++	if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
++	    (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
++		hwif->irq = port ? 15 : 14;
 +
-+static int pcf8575_attach_adapter(struct i2c_adapter *adapter);
-+static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind);
-+static int pcf8575_detach_client(struct i2c_client *client);
++	hwif->host_flags = d->host_flags;
++	hwif->pio_mask = d->pio_mask;
 +
-+/* This is the driver that will be inserted */
-+static struct i2c_driver pcf8575_driver = {
-+	.driver = {
-+		.owner	= THIS_MODULE,
-+		.name	= "pcf8575",
-+	},
-+	.attach_adapter	= pcf8575_attach_adapter,
-+	.detach_client	= pcf8575_detach_client,
-+};
++	if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
++		hwif->mate->serialized = hwif->serialized = 1;
 +
-+/* following are the sysfs callback functions */
-+static ssize_t show_read(struct device *dev, struct device_attribute *attr,
-+			 char *buf)
-+{
-+	struct i2c_client *client = to_i2c_client(dev);
-+	u16 val;
-+	u8 iopin_state[2];
++	hwif->swdma_mask = d->swdma_mask;
++	hwif->mwdma_mask = d->mwdma_mask;
++	hwif->ultra_mask = d->udma_mask;
+ 
+-int ide_device_add(u8 idx[4])
++	/* reset DMA masks only for SFF-style DMA controllers */
++	if ((d->host_flags && IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0)
++		hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0;
 +
-+	i2c_master_recv(client, iopin_state, 2);
++	if (d->host_flags & IDE_HFLAG_RQSIZE_256)
++		hwif->rqsize = 256;
 +
-+	val = iopin_state[0];
-+	val |= iopin_state[1] << 8;
++	/* call chipset specific routine for each enabled port */
++	if (d->init_hwif)
++		d->init_hwif(hwif);
 +
-+	return sprintf(buf, "%u\n", val);
++	if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
++		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
++			hwif->cbl = hwif->cable_detect(hwif);
++	}
 +}
 +
-+static DEVICE_ATTR(read, S_IRUGO, show_read, NULL);
++int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ {
++	ide_hwif_t *hwif, *mate = NULL;
+ 	int i, rc = 0;
+ 
+-	for (i = 0; i < 4; i++) {
+-		if (idx[i] != 0xff)
+-			rc |= probe_hwif_init(&ide_hwifs[idx[i]]);
++	for (i = 0; i < MAX_HWIFS; i++) {
++		if (d == NULL || idx[i] == 0xff) {
++			mate = NULL;
++			continue;
++		}
 +
-+static ssize_t show_write(struct device *dev, struct device_attribute *attr,
-+			  char *buf)
-+{
-+	struct pcf8575_data *data = dev_get_drvdata(dev);
-+	if (data->write < 0)
-+		return data->write;
-+	return sprintf(buf, "%d\n", data->write);
-+}
++		hwif = &ide_hwifs[idx[i]];
 +
-+static ssize_t set_write(struct device *dev, struct device_attribute *attr,
-+			 const char *buf, size_t count)
-+{
-+	struct i2c_client *client = to_i2c_client(dev);
-+	struct pcf8575_data *data = i2c_get_clientdata(client);
-+	unsigned long val = simple_strtoul(buf, NULL, 10);
-+	u8 iopin_state[2];
++		if (d->chipset != ide_etrax100 && (i & 1) && mate) {
++			hwif->mate = mate;
++			mate->mate = hwif;
++		}
 +
-+	if (val > 0xffff)
-+		return -EINVAL;
++		mate = (i & 1) ? NULL : hwif;
 +
-+	data->write = val;
++		ide_init_port(hwif, i & 1, d);
++		ide_port_init_devices(hwif);
++	}
 +
-+	iopin_state[0] = val & 0xFF;
-+	iopin_state[1] = val >> 8;
++	for (i = 0; i < MAX_HWIFS; i++) {
++		if (idx[i] == 0xff)
++			continue;
 +
-+	i2c_master_send(client, iopin_state, 2);
++		hwif = &ide_hwifs[idx[i]];
 +
-+	return count;
-+}
++		if ((hwif->chipset != ide_4drives || !hwif->mate ||
++		     !hwif->mate->present) && ide_hwif_request_regions(hwif)) {
++			printk(KERN_ERR "%s: ports already in use, "
++					"skipping probe\n", hwif->name);
++			continue;
++		}
 +
-+static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
++		if (ide_probe_port(hwif) < 0) {
++			ide_hwif_release_regions(hwif);
++			continue;
++		}
 +
-+static struct attribute *pcf8575_attributes[] = {
-+	&dev_attr_read.attr,
-+	&dev_attr_write.attr,
-+	NULL
-+};
++		hwif->present = 1;
 +
-+static const struct attribute_group pcf8575_attr_group = {
-+	.attrs = pcf8575_attributes,
-+};
++		if (hwif->chipset != ide_4drives || !hwif->mate ||
++		    !hwif->mate->present)
++			ide_register_port(hwif);
 +
-+/*
-+ * Real code
-+ */
++		ide_port_tune_devices(hwif);
++	}
 +
-+static int pcf8575_attach_adapter(struct i2c_adapter *adapter)
-+{
-+	return i2c_probe(adapter, &addr_data, pcf8575_detect);
-+}
++	for (i = 0; i < MAX_HWIFS; i++) {
++		if (idx[i] == 0xff)
++			continue;
 +
-+/* This function is called by i2c_probe */
-+static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind)
-+{
-+	struct i2c_client *client;
-+	struct pcf8575_data *data;
-+	int err = 0;
++		hwif = &ide_hwifs[idx[i]];
 +
-+	if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
-+		goto exit;
++		if (!hwif->present)
++			continue;
 +
-+	/* OK. For now, we presume we have a valid client. We now create the
-+	   client structure, even though we cannot fill it completely yet. */
-+	data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL);
-+	if (!data) {
-+		err = -ENOMEM;
-+		goto exit;
++		if (hwif_init(hwif) == 0) {
++			printk(KERN_INFO "%s: failed to initialize IDE "
++					 "interface\n", hwif->name);
++			hwif->present = 0;
++			rc = -1;
++			continue;
++		}
++
++		ide_acpi_init(hwif);
++		ide_acpi_port_init_devices(hwif);
 +	}
 +
-+	client = &data->client;
-+	i2c_set_clientdata(client, data);
-+	client->addr = address;
-+	client->adapter = adapter;
-+	client->driver = &pcf8575_driver;
-+	strlcpy(client->name, "pcf8575", I2C_NAME_SIZE);
-+	data->write = -EAGAIN;
++	for (i = 0; i < MAX_HWIFS; i++) {
++		if (idx[i] == 0xff)
++			continue;
 +
-+	/* This is the place to detect whether the chip at the specified
-+	   address really is a PCF8575 chip. However, there is no method known
-+	   to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
++		hwif = &ide_hwifs[idx[i]];
 +
-+	/* Tell the I2C layer a new client has arrived */
-+	err = i2c_attach_client(client);
-+	if (err)
-+		goto exit_free;
++		if (hwif->present) {
++			if (hwif->chipset == ide_unknown ||
++			    hwif->chipset == ide_forced)
++				hwif->chipset = ide_generic;
++			hwif_register_devices(hwif);
++		}
+ 	}
+ 
+-	for (i = 0; i < 4; i++) {
+-		if (idx[i] != 0xff)
+-			ide_proc_register_port(&ide_hwifs[idx[i]]);
++	for (i = 0; i < MAX_HWIFS; i++) {
++		if (idx[i] == 0xff)
++			continue;
 +
-+	/* Register sysfs hooks */
-+	err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group);
-+	if (err)
-+		goto exit_detach;
++		hwif = &ide_hwifs[idx[i]];
 +
-+	return 0;
++		if (hwif->present) {
++			ide_proc_register_port(hwif);
++			ide_proc_port_register_devices(hwif);
++		}
+ 	}
+ 
+ 	return rc;
+ }
++EXPORT_SYMBOL_GPL(ide_device_add_all);
+ 
++int ide_device_add(u8 idx[4], const struct ide_port_info *d)
++{
++	u8 idx_all[MAX_HWIFS];
++	int i;
 +
-+exit_detach:
-+	i2c_detach_client(client);
-+exit_free:
-+	kfree(data);
-+exit:
-+	return err;
++	for (i = 0; i < MAX_HWIFS; i++)
++		idx_all[i] = (i < 4) ? idx[i] : 0xff;
++
++	return ide_device_add_all(idx_all, d);
 +}
+ EXPORT_SYMBOL_GPL(ide_device_add);
+diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
+index a4007d3..bab88ca 100644
+--- a/drivers/ide/ide-proc.c
++++ b/drivers/ide/ide-proc.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/ide-proc.c	Version 1.05	Mar 05, 2003
+- *
+  *  Copyright (C) 1997-1998	Mark Lord
+  *  Copyright (C) 2003		Red Hat <alan at redhat.com>
+  *
+@@ -67,6 +65,7 @@ static int proc_ide_read_imodel
+ 		case ide_4drives:	name = "4drives";	break;
+ 		case ide_pmac:		name = "mac-io";	break;
+ 		case ide_au1xxx:	name = "au1xxx";	break;
++		case ide_palm3710:      name = "palm3710";      break;
+ 		case ide_etrax100:	name = "etrax100";	break;
+ 		case ide_acorn:		name = "acorn";		break;
+ 		default:		name = "(unknown)";	break;
+@@ -346,14 +345,20 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
+ 
+ static int set_xfer_rate (ide_drive_t *drive, int arg)
+ {
++	ide_task_t task;
+ 	int err;
+ 
+ 	if (arg < 0 || arg > 70)
+ 		return -EINVAL;
+ 
+-	err = ide_wait_cmd(drive,
+-			WIN_SETFEATURES, (u8) arg,
+-			SETFEATURES_XFER, 0, NULL);
++	memset(&task, 0, sizeof(task));
++	task.tf.command = WIN_SETFEATURES;
++	task.tf.feature = SETFEATURES_XFER;
++	task.tf.nsect   = (u8)arg;
++	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
++			IDE_TFLAG_IN_NSECT;
 +
-+static int pcf8575_detach_client(struct i2c_client *client)
-+{
-+	int err;
++	err = ide_no_data_taskfile(drive, &task);
+ 
+ 	if (!err && arg) {
+ 		ide_set_xfer_rate(drive, (u8) arg);
+@@ -735,7 +740,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
+ 
+ EXPORT_SYMBOL(ide_proc_unregister_driver);
+ 
+-static void create_proc_ide_drives(ide_hwif_t *hwif)
++void ide_proc_port_register_devices(ide_hwif_t *hwif)
+ {
+ 	int	d;
+ 	struct proc_dir_entry *ent;
+@@ -789,9 +794,6 @@ static ide_proc_entry_t hwif_entries[] = {
+ 
+ void ide_proc_register_port(ide_hwif_t *hwif)
+ {
+-	if (!hwif->present)
+-		return;
+-
+ 	if (!hwif->proc) {
+ 		hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
+ 
+@@ -800,8 +802,6 @@ void ide_proc_register_port(ide_hwif_t *hwif)
+ 
+ 		ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
+ 	}
+-
+-	create_proc_ide_drives(hwif);
+ }
+ 
+ #ifdef CONFIG_BLK_DEV_IDEPCI
+diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
+new file mode 100644
+index 0000000..93d2e41
+--- /dev/null
++++ b/drivers/ide/ide-scan-pci.c
+@@ -0,0 +1,116 @@
++/*
++ * support for probing IDE PCI devices in the PCI bus order
++ *
++ * Copyright (c) 1998-2000  Andre Hedrick <andre at linux-ide.org>
++ * Copyright (c) 1995-1998  Mark Lord
++ *
++ * May be copied or modified under the terms of the GNU General Public License
++ */
 +
-+	sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group);
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/ide.h>
 +
-+	err = i2c_detach_client(client);
-+	if (err)
-+		return err;
++/*
++ *	Module interfaces
++ */
 +
-+	kfree(i2c_get_clientdata(client));
++static int pre_init = 1;		/* Before first ordered IDE scan */
++static LIST_HEAD(ide_pci_drivers);
++
++/*
++ *	__ide_pci_register_driver	-	attach IDE driver
++ *	@driver: pci driver
++ *	@module: owner module of the driver
++ *
++ *	Registers a driver with the IDE layer. The IDE layer arranges that
++ *	boot time setup is done in the expected device order and then
++ *	hands the controllers off to the core PCI code to do the rest of
++ *	the work.
++ *
++ *	Returns are the same as for pci_register_driver
++ */
++
++int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
++			      const char *mod_name)
++{
++	if (!pre_init)
++		return __pci_register_driver(driver, module, mod_name);
++	driver->driver.owner = module;
++	list_add_tail(&driver->node, &ide_pci_drivers);
 +	return 0;
 +}
++EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
 +
-+static int __init pcf8575_init(void)
++/**
++ *	ide_scan_pcidev		-	find an IDE driver for a device
++ *	@dev: PCI device to check
++ *
++ *	Look for an IDE driver to handle the device we are considering.
++ *	This is only used during boot up to get the ordering correct. After
++ *	boot up the pci layer takes over the job.
++ */
++
++static int __init ide_scan_pcidev(struct pci_dev *dev)
 +{
-+	return i2c_add_driver(&pcf8575_driver);
++	struct list_head *l;
++	struct pci_driver *d;
++
++	list_for_each(l, &ide_pci_drivers) {
++		d = list_entry(l, struct pci_driver, node);
++		if (d->id_table) {
++			const struct pci_device_id *id =
++				pci_match_id(d->id_table, dev);
++
++			if (id != NULL && d->probe(dev, id) >= 0) {
++				dev->driver = d;
++				pci_dev_get(dev);
++				return 1;
++			}
++		}
++	}
++	return 0;
 +}
 +
-+static void __exit pcf8575_exit(void)
++/**
++ *	ide_scan_pcibus		-	perform the initial IDE driver scan
++ *
++ *	Perform the initial bus rather than driver ordered scan of the
++ *	PCI drivers. After this all IDE pci handling becomes standard
++ *	module ordering not traditionally ordered.
++ */
++
++static int __init ide_scan_pcibus(void)
 +{
-+	i2c_del_driver(&pcf8575_driver);
-+}
++	struct pci_dev *dev = NULL;
++	struct pci_driver *d;
++	struct list_head *l, *n;
 +
-+MODULE_AUTHOR("Michael Hennerich <hennerich at blackfin.uclinux.org>, "
-+	      "Bart Van Assche <bart.vanassche at gmail.com>");
-+MODULE_DESCRIPTION("pcf8575 driver");
-+MODULE_LICENSE("GPL");
++	pre_init = 0;
++	if (!ide_scan_direction)
++		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
++			ide_scan_pcidev(dev);
++	else
++		while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
++						     dev)))
++			ide_scan_pcidev(dev);
 +
-+module_init(pcf8575_init);
-+module_exit(pcf8575_exit);
-diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
-index 4dc3637..865f440 100644
---- a/drivers/i2c/chips/pcf8591.c
-+++ b/drivers/i2c/chips/pcf8591.c
-@@ -27,7 +27,7 @@
- #include <linux/mutex.h>
++	/*
++	 *	Hand the drivers over to the PCI layer now we
++	 *	are post init.
++	 */
++
++	list_for_each_safe(l, n, &ide_pci_drivers) {
++		list_del(l);
++		d = list_entry(l, struct pci_driver, node);
++		if (__pci_register_driver(d, d->driver.owner,
++					  d->driver.mod_name))
++			printk(KERN_ERR "%s: failed to register %s driver\n",
++					__FUNCTION__, d->driver.mod_name);
++	}
++
++	return 0;
++}
++
++module_init(ide_scan_pcibus);
+diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
+index 7b9181b..49dd2e7 100644
+--- a/drivers/ide/ide-tape.c
++++ b/drivers/ide/ide-tape.c
+@@ -1,9 +1,8 @@
+ /*
+- * linux/drivers/ide/ide-tape.c		Version 1.19	Nov, 2003
+- *
+- * Copyright (C) 1995 - 1999 Gadi Oxman <gadio at netvision.net.il>
++ * IDE ATAPI streaming tape driver.
+  *
+- * $Header$
++ * Copyright (C) 1995-1999  Gadi Oxman <gadio at netvision.net.il>
++ * Copyright (C) 2003-2005  Bartlomiej Zolnierkiewicz
+  *
+  * This driver was constructed as a student project in the software laboratory
+  * of the faculty of electrical engineering in the Technion - Israel's
+@@ -11,418 +10,12 @@
+  *
+  * It is hereby placed under the terms of the GNU general public license.
+  * (See linux/COPYING).
+- */
+- 
+-/*
+- * IDE ATAPI streaming tape driver.
+- *
+- * This driver is a part of the Linux ide driver and works in co-operation
+- * with linux/drivers/block/ide.c.
+- *
+- * The driver, in co-operation with ide.c, basically traverses the 
+- * request-list for the block device interface. The character device
+- * interface, on the other hand, creates new requests, adds them
+- * to the request-list of the block device, and waits for their completion.
+- *
+- * Pipelined operation mode is now supported on both reads and writes.
+- *
+- * The block device major and minor numbers are determined from the
+- * tape's relative position in the ide interfaces, as explained in ide.c.
+- *
+- * The character device interface consists of the following devices:
+- *
+- * ht0		major 37, minor 0	first  IDE tape, rewind on close.
+- * ht1		major 37, minor 1	second IDE tape, rewind on close.
+- * ...
+- * nht0		major 37, minor 128	first  IDE tape, no rewind on close.
+- * nht1		major 37, minor 129	second IDE tape, no rewind on close.
+- * ...
+- *
+- * Run linux/scripts/MAKEDEV.ide to create the above entries.
+- *
+- * The general magnetic tape commands compatible interface, as defined by
+- * include/linux/mtio.h, is accessible through the character device.
+- *
+- * General ide driver configuration options, such as the interrupt-unmask
+- * flag, can be configured by issuing an ioctl to the block device interface,
+- * as any other ide device.
+- *
+- * Our own ide-tape ioctl's can be issued to either the block device or
+- * the character device interface.
+- *
+- * Maximal throughput with minimal bus load will usually be achieved in the
+- * following scenario:
+- *
+- *	1.	ide-tape is operating in the pipelined operation mode.
+- *	2.	No buffering is performed by the user backup program.
+- *
+- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
+- * 
+- * Ver 0.1   Nov  1 95   Pre-working code :-)
+- * Ver 0.2   Nov 23 95   A short backup (few megabytes) and restore procedure
+- *                        was successful ! (Using tar cvf ... on the block
+- *                        device interface).
+- *                       A longer backup resulted in major swapping, bad
+- *                        overall Linux performance and eventually failed as
+- *                        we received non serial read-ahead requests from the
+- *                        buffer cache.
+- * Ver 0.3   Nov 28 95   Long backups are now possible, thanks to the
+- *                        character device interface. Linux's responsiveness
+- *                        and performance doesn't seem to be much affected
+- *                        from the background backup procedure.
+- *                       Some general mtio.h magnetic tape operations are
+- *                        now supported by our character device. As a result,
+- *                        popular tape utilities are starting to work with
+- *                        ide tapes :-)
+- *                       The following configurations were tested:
+- *                       	1. An IDE ATAPI TAPE shares the same interface
+- *                       	   and irq with an IDE ATAPI CDROM.
+- *                        	2. An IDE ATAPI TAPE shares the same interface
+- *                          	   and irq with a normal IDE disk.
+- *                        Both configurations seemed to work just fine !
+- *                        However, to be on the safe side, it is meanwhile
+- *                        recommended to give the IDE TAPE its own interface
+- *                        and irq.
+- *                       The one thing which needs to be done here is to
+- *                        add a "request postpone" feature to ide.c,
+- *                        so that we won't have to wait for the tape to finish
+- *                        performing a long media access (DSC) request (such
+- *                        as a rewind) before we can access the other device
+- *                        on the same interface. This effect doesn't disturb
+- *                        normal operation most of the time because read/write
+- *                        requests are relatively fast, and once we are
+- *                        performing one tape r/w request, a lot of requests
+- *                        from the other device can be queued and ide.c will
+- *			  service all of them after this single tape request.
+- * Ver 1.0   Dec 11 95   Integrated into Linux 1.3.46 development tree.
+- *                       On each read / write request, we now ask the drive
+- *                        if we can transfer a constant number of bytes
+- *                        (a parameter of the drive) only to its buffers,
+- *                        without causing actual media access. If we can't,
+- *                        we just wait until we can by polling the DSC bit.
+- *                        This ensures that while we are not transferring
+- *                        more bytes than the constant referred to above, the
+- *                        interrupt latency will not become too high and
+- *                        we won't cause an interrupt timeout, as happened
+- *                        occasionally in the previous version.
+- *                       While polling for DSC, the current request is
+- *                        postponed and ide.c is free to handle requests from
+- *                        the other device. This is handled transparently to
+- *                        ide.c. The hwgroup locking method which was used
+- *                        in the previous version was removed.
+- *                       Use of new general features which are provided by
+- *                        ide.c for use with atapi devices.
+- *                        (Programming done by Mark Lord)
+- *                       Few potential bug fixes (Again, suggested by Mark)
+- *                       Single character device data transfers are now
+- *                        not limited in size, as they were before.
+- *                       We are asking the tape about its recommended
+- *                        transfer unit and send a larger data transfer
+- *                        as several transfers of the above size.
+- *                        For best results, use an integral number of this
+- *                        basic unit (which is shown during driver
+- *                        initialization). I will soon add an ioctl to get
+- *                        this important parameter.
+- *                       Our data transfer buffer is allocated on startup,
+- *                        rather than before each data transfer. This should
+- *                        ensure that we will indeed have a data buffer.
+- * Ver 1.1   Dec 14 95   Fixed random problems which occurred when the tape
+- *                        shared an interface with another device.
+- *                        (poll_for_dsc was a complete mess).
+- *                       Removed some old (non-active) code which had
+- *                        to do with supporting buffer cache originated
+- *                        requests.
+- *                       The block device interface can now be opened, so
+- *                        that general ide driver features like the unmask
+- *                        interrupts flag can be selected with an ioctl.
+- *                        This is the only use of the block device interface.
+- *                       New fast pipelined operation mode (currently only on
+- *                        writes). When using the pipelined mode, the
+- *                        throughput can potentially reach the maximum
+- *                        tape supported throughput, regardless of the
+- *                        user backup program. On my tape drive, it sometimes
+- *                        boosted performance by a factor of 2. Pipelined
+- *                        mode is enabled by default, but since it has a few
+- *                        downfalls as well, you may want to disable it.
+- *                        A short explanation of the pipelined operation mode
+- *                        is available below.
+- * Ver 1.2   Jan  1 96   Eliminated pipelined mode race condition.
+- *                       Added pipeline read mode. As a result, restores
+- *                        are now as fast as backups.
+- *                       Optimized shared interface behavior. The new behavior
+- *                        typically results in better IDE bus efficiency and
+- *                        higher tape throughput.
+- *                       Pre-calculation of the expected read/write request
+- *                        service time, based on the tape's parameters. In
+- *                        the pipelined operation mode, this allows us to
+- *                        adjust our polling frequency to a much lower value,
+- *                        and thus to dramatically reduce our load on Linux,
+- *                        without any decrease in performance.
+- *                       Implemented additional mtio.h operations.
+- *                       The recommended user block size is returned by
+- *                        the MTIOCGET ioctl.
+- *                       Additional minor changes.
+- * Ver 1.3   Feb  9 96   Fixed pipelined read mode bug which prevented the
+- *                        use of some block sizes during a restore procedure.
+- *                       The character device interface will now present a
+- *                        continuous view of the media - any mix of block sizes
+- *                        during a backup/restore procedure is supported. The
+- *                        driver will buffer the requests internally and
+- *                        convert them to the tape's recommended transfer
+- *                        unit, making performance almost independent of the
+- *                        chosen user block size.
+- *                       Some improvements in error recovery.
+- *                       By cooperating with ide-dma.c, bus mastering DMA can
+- *                        now sometimes be used with IDE tape drives as well.
+- *                        Bus mastering DMA has the potential to dramatically
+- *                        reduce the CPU's overhead when accessing the device,
+- *                        and can be enabled by using hdparm -d1 on the tape's
+- *                        block device interface. For more info, read the
+- *                        comments in ide-dma.c.
+- * Ver 1.4   Mar 13 96   Fixed serialize support.
+- * Ver 1.5   Apr 12 96   Fixed shared interface operation, broken in 1.3.85.
+- *                       Fixed pipelined read mode inefficiency.
+- *                       Fixed nasty null dereferencing bug.
+- * Ver 1.6   Aug 16 96   Fixed FPU usage in the driver.
+- *                       Fixed end of media bug.
+- * Ver 1.7   Sep 10 96   Minor changes for the CONNER CTT8000-A model.
+- * Ver 1.8   Sep 26 96   Attempt to find a better balance between good
+- *                        interactive response and high system throughput.
+- * Ver 1.9   Nov  5 96   Automatically cross encountered filemarks rather
+- *                        than requiring an explicit FSF command.
+- *                       Abort pending requests at end of media.
+- *                       MTTELL was sometimes returning incorrect results.
+- *                       Return the real block size in the MTIOCGET ioctl.
+- *                       Some error recovery bug fixes.
+- * Ver 1.10  Nov  5 96   Major reorganization.
+- *                       Reduced CPU overhead a bit by eliminating internal
+- *                        bounce buffers.
+- *                       Added module support.
+- *                       Added multiple tape drives support.
+- *                       Added partition support.
+- *                       Rewrote DSC handling.
+- *                       Some portability fixes.
+- *                       Removed ide-tape.h.
+- *                       Additional minor changes.
+- * Ver 1.11  Dec  2 96   Bug fix in previous DSC timeout handling.
+- *                       Use ide_stall_queue() for DSC overlap.
+- *                       Use the maximum speed rather than the current speed
+- *                        to compute the request service time.
+- * Ver 1.12  Dec  7 97   Fix random memory overwriting and/or last block data
+- *                        corruption, which could occur if the total number
+- *                        of bytes written to the tape was not an integral
+- *                        number of tape blocks.
+- *                       Add support for INTERRUPT DRQ devices.
+- * Ver 1.13  Jan  2 98   Add "speed == 0" work-around for HP COLORADO 5GB
+- * Ver 1.14  Dec 30 98   Partial fixes for the Sony/AIWA tape drives.
+- *                       Replace cli()/sti() with hwgroup spinlocks.
+- * Ver 1.15  Mar 25 99   Fix SMP race condition by replacing hwgroup
+- *                        spinlock with private per-tape spinlock.
+- * Ver 1.16  Sep  1 99   Add OnStream tape support.
+- *                       Abort read pipeline on EOD.
+- *                       Wait for the tape to become ready in case it returns
+- *                        "in the process of becoming ready" on open().
+- *                       Fix zero padding of the last written block in
+- *                        case the tape block size is larger than PAGE_SIZE.
+- *                       Decrease the default disconnection time to tn.
+- * Ver 1.16e Oct  3 99   Minor fixes.
+- * Ver 1.16e1 Oct 13 99  Patches by Arnold Niessen,
+- *                          niessen at iae.nl / arnold.niessen at philips.com
+- *                   GO-1)  Undefined code in idetape_read_position
+- *				according to Gadi's email
+- *                   AJN-1) Minor fix asc == 11 should be asc == 0x11
+- *                               in idetape_issue_packet_command (did effect
+- *                               debugging output only)
+- *                   AJN-2) Added more debugging output, and
+- *                              added ide-tape: where missing. I would also
+- *				like to add tape->name where possible
+- *                   AJN-3) Added different debug_level's 
+- *                              via /proc/ide/hdc/settings
+- * 				"debug_level" determines amount of debugging output;
+- * 				can be changed using /proc/ide/hdx/settings
+- * 				0 : almost no debugging output
+- * 				1 : 0+output errors only
+- * 				2 : 1+output all sensekey/asc
+- * 				3 : 2+follow all chrdev related procedures
+- * 				4 : 3+follow all procedures
+- * 				5 : 4+include pc_stack rq_stack info
+- * 				6 : 5+USE_COUNT updates
+- *                   AJN-4) Fixed timeout for retension in idetape_queue_pc_tail
+- *				from 5 to 10 minutes
+- *                   AJN-5) Changed maximum number of blocks to skip when
+- *                              reading tapes with multiple consecutive write
+- *                              errors from 100 to 1000 in idetape_get_logical_blk
+- *                   Proposed changes to code:
+- *                   1) output "logical_blk_num" via /proc
+- *                   2) output "current_operation" via /proc
+- *                   3) Either solve or document the fact that `mt rewind' is
+- *                      required after reading from /dev/nhtx to be
+- *			able to rmmod the idetape module;
+- *			Also, sometimes an application finishes but the
+- *			device remains `busy' for some time. Same cause ?
+- *                   Proposed changes to release-notes:
+- *		     4) write a simple `quickstart' section in the
+- *                      release notes; I volunteer if you don't want to
+- * 		     5) include a pointer to video4linux in the doc
+- *                      to stimulate video applications
+- *                   6) release notes lines 331 and 362: explain what happens
+- *			if the application data rate is higher than 1100 KB/s; 
+- *			similar approach to lower-than-500 kB/s ?
+- *		     7) 6.6 Comparison; wouldn't it be better to allow different 
+- *			strategies for read and write ?
+- *			Wouldn't it be better to control the tape buffer
+- *			contents instead of the bandwidth ?
+- *		     8) line 536: replace will by would (if I understand
+- *			this section correctly, a hypothetical and unwanted situation
+- *			 is being described)
+- * Ver 1.16f Dec 15 99   Change place of the secondary OnStream header frames.
+- * Ver 1.17  Nov 2000 / Jan 2001  Marcel Mol, marcel at mesa.nl
+- *			- Add idetape_onstream_mode_sense_tape_parameter_page
+- *			  function to get tape capacity in frames: tape->capacity.
+- *			- Add support for DI-50 drives( or any DI- drive).
+- *			- 'workaround' for read error/blank block around block 3000.
+- *			- Implement Early warning for end of media for Onstream.
+- *			- Cosmetic code changes for readability.
+- *			- Idetape_position_tape should not use SKIP bit during
+- *			  Onstream read recovery.
+- *			- Add capacity, logical_blk_num and first/last_frame_position
+- *			  to /proc/ide/hd?/settings.
+- *			- Module use count was gone in the Linux 2.4 driver.
+- * Ver 1.17a Apr 2001 Willem Riede osst at riede.org
+- * 			- Get drive's actual block size from mode sense block descriptor
+- * 			- Limit size of pipeline
+- * Ver 1.17b Oct 2002   Alan Stern <stern at rowland.harvard.edu>
+- *			Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used
+- *			 it in the code!
+- *			Actually removed aborted stages in idetape_abort_pipeline
+- *			 instead of just changing the command code.
+- *			Made the transfer byte count for Request Sense equal to the
+- *			 actual length of the data transfer.
+- *			Changed handling of partial data transfers: they do not
+- *			 cause DMA errors.
+- *			Moved initiation of DMA transfers to the correct place.
+- *			Removed reference to unallocated memory.
+- *			Made __idetape_discard_read_pipeline return the number of
+- *			 sectors skipped, not the number of stages.
+- *			Replaced errant kfree() calls with __idetape_kfree_stage().
+- *			Fixed off-by-one error in testing the pipeline length.
+- *			Fixed handling of filemarks in the read pipeline.
+- *			Small code optimization for MTBSF and MTBSFM ioctls.
+- *			Don't try to unlock the door during device close if is
+- *			 already unlocked!
+- *			Cosmetic fixes to miscellaneous debugging output messages.
+- *			Set the minimum /proc/ide/hd?/settings values for "pipeline",
+- *			 "pipeline_min", and "pipeline_max" to 1.
+- *
+- * Here are some words from the first releases of hd.c, which are quoted
+- * in ide.c and apply here as well:
+- *
+- * | Special care is recommended.  Have Fun!
+  *
++ * For a historical changelog see
++ * Documentation/ide/ChangeLog.ide-tape.1995-2002
+  */
  
- /* Addresses to scan */
--static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
-+static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
- 					0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
+-/*
+- * An overview of the pipelined operation mode.
+- *
+- * In the pipelined write mode, we will usually just add requests to our
+- * pipeline and return immediately, before we even start to service them. The
+- * user program will then have enough time to prepare the next request while
+- * we are still busy servicing previous requests. In the pipelined read mode,
+- * the situation is similar - we add read-ahead requests into the pipeline,
+- * before the user even requested them.
+- *
+- * The pipeline can be viewed as a "safety net" which will be activated when
+- * the system load is high and prevents the user backup program from keeping up
+- * with the current tape speed. At this point, the pipeline will get
+- * shorter and shorter but the tape will still be streaming at the same speed.
+- * Assuming we have enough pipeline stages, the system load will hopefully
+- * decrease before the pipeline is completely empty, and the backup program
+- * will be able to "catch up" and refill the pipeline again.
+- * 
+- * When using the pipelined mode, it would be best to disable any type of
+- * buffering done by the user program, as ide-tape already provides all the
+- * benefits in the kernel, where it can be done in a more efficient way.
+- * As we will usually not block the user program on a request, the most
+- * efficient user code will then be a simple read-write-read-... cycle.
+- * Any additional logic will usually just slow down the backup process.
+- *
+- * Using the pipelined mode, I get a constant over 400 KBps throughput,
+- * which seems to be the maximum throughput supported by my tape.
+- *
+- * However, there are some downfalls:
+- *
+- *	1.	We use memory (for data buffers) in proportional to the number
+- *		of pipeline stages (each stage is about 26 KB with my tape).
+- *	2.	In the pipelined write mode, we cheat and postpone error codes
+- *		to the user task. In read mode, the actual tape position
+- *		will be a bit further than the last requested block.
+- *
+- * Concerning (1):
+- *
+- *	1.	We allocate stages dynamically only when we need them. When
+- *		we don't need them, we don't consume additional memory. In
+- *		case we can't allocate stages, we just manage without them
+- *		(at the expense of decreased throughput) so when Linux is
+- *		tight in memory, we will not pose additional difficulties.
+- *
+- *	2.	The maximum number of stages (which is, in fact, the maximum
+- *		amount of memory) which we allocate is limited by the compile
+- *		time parameter IDETAPE_MAX_PIPELINE_STAGES.
+- *
+- *	3.	The maximum number of stages is a controlled parameter - We
+- *		don't start from the user defined maximum number of stages
+- *		but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
+- *		will not even allocate this amount of stages if the user
+- *		program can't handle the speed). We then implement a feedback
+- *		loop which checks if the pipeline is empty, and if it is, we
+- *		increase the maximum number of stages as necessary until we
+- *		reach the optimum value which just manages to keep the tape
+- *		busy with minimum allocated memory or until we reach
+- *		IDETAPE_MAX_PIPELINE_STAGES.
+- *
+- * Concerning (2):
+- *
+- *	In pipelined write mode, ide-tape can not return accurate error codes
+- *	to the user program since we usually just add the request to the
+- *      pipeline without waiting for it to be serviced. In case an error
+- *      occurs, I will report it on the next user request.
+- *
+- *	In the pipelined read mode, subsequent read requests or forward
+- *	filemark spacing will perform correctly, as we preserve all blocks
+- *	and filemarks which we encountered during our excess read-ahead.
+- * 
+- *	For accurate tape positioning and error reporting, disabling
+- *	pipelined mode might be the best option.
+- *
+- * You can enable/disable/tune the pipelined operation mode by adjusting
+- * the compile time parameters below.
+- */
+-
+-/*
+- *	Possible improvements.
+- *
+- *	1.	Support for the ATAPI overlap protocol.
+- *
+- *		In order to maximize bus throughput, we currently use the DSC
+- *		overlap method which enables ide.c to service requests from the
+- *		other device while the tape is busy executing a command. The
+- *		DSC overlap method involves polling the tape's status register
+- *		for the DSC bit, and servicing the other device while the tape
+- *		isn't ready.
+- *
+- *		In the current QIC development standard (December 1995),
+- *		it is recommended that new tape drives will *in addition* 
+- *		implement the ATAPI overlap protocol, which is used for the
+- *		same purpose - efficient use of the IDE bus, but is interrupt
+- *		driven and thus has much less CPU overhead.
+- *
+- *		ATAPI overlap is likely to be supported in most new ATAPI
+- *		devices, including new ATAPI cdroms, and thus provides us
+- *		a method by which we can achieve higher throughput when
+- *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
+- */
+-
+-#define IDETAPE_VERSION "1.19"
++#define IDETAPE_VERSION "1.20"
  
- /* Insmod parameters */
-diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
-index e320994..4154a91 100644
---- a/drivers/i2c/chips/tps65010.c
-+++ b/drivers/i2c/chips/tps65010.c
-@@ -31,7 +31,7 @@
- #include <linux/seq_file.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -443,107 +36,73 @@
+ #include <linux/completion.h>
+ #include <linux/bitops.h>
  #include <linux/mutex.h>
++#include <scsi/scsi.h>
  
--#include <asm/arch/tps65010.h>
-+#include <linux/i2c/tps65010.h>
+ #include <asm/byteorder.h>
+-#include <asm/irq.h>
+-#include <asm/uaccess.h>
+-#include <asm/io.h>
++#include <linux/irq.h>
++#include <linux/uaccess.h>
++#include <linux/io.h>
+ #include <asm/unaligned.h>
++#include <linux/mtio.h>
  
- /*-------------------------------------------------------------------------*/
+-/*
+- * partition
+- */
+-typedef struct os_partition_s {
+-	__u8	partition_num;
+-	__u8	par_desc_ver;
+-	__u16	wrt_pass_cntr;
+-	__u32	first_frame_addr;
+-	__u32	last_frame_addr;
+-	__u32	eod_frame_addr;
+-} os_partition_t;
+-
+-/*
+- * DAT entry
+- */
+-typedef struct os_dat_entry_s {
+-	__u32	blk_sz;
+-	__u16	blk_cnt;
+-	__u8	flags;
+-	__u8	reserved;
+-} os_dat_entry_t;
+-
+-/*
+- * DAT
+- */
+-#define OS_DAT_FLAGS_DATA	(0xc)
+-#define OS_DAT_FLAGS_MARK	(0x1)
++enum {
++	/* output errors only */
++	DBG_ERR =		(1 << 0),
++	/* output all sense key/asc */
++	DBG_SENSE =		(1 << 1),
++	/* info regarding all chrdev-related procedures */
++	DBG_CHRDEV =		(1 << 2),
++	/* all remaining procedures */
++	DBG_PROCS =		(1 << 3),
++	/* buffer alloc info (pc_stack & rq_stack) */
++	DBG_PCRQ_STACK =	(1 << 4),
++};
  
-diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/i2c/chips/tsl2550.c
-index 3de4b19..a10fd27 100644
---- a/drivers/i2c/chips/tsl2550.c
-+++ b/drivers/i2c/chips/tsl2550.c
-@@ -432,11 +432,32 @@ static int __devexit tsl2550_remove(struct i2c_client *client)
- 	return 0;
- }
+-typedef struct os_dat_s {
+-	__u8		dat_sz;
+-	__u8		reserved1;
+-	__u8		entry_cnt;
+-	__u8		reserved3;
+-	os_dat_entry_t	dat_list[16];
+-} os_dat_t;
++/* define to see debug info */
++#define IDETAPE_DEBUG_LOG		0
  
-+#ifdef CONFIG_PM
-+
-+static int tsl2550_suspend(struct i2c_client *client, pm_message_t mesg)
-+{
-+	return tsl2550_set_power_state(client, 0);
-+}
-+
-+static int tsl2550_resume(struct i2c_client *client)
-+{
-+	return tsl2550_set_power_state(client, 1);
+-#include <linux/mtio.h>
++#if IDETAPE_DEBUG_LOG
++#define debug_log(lvl, fmt, args...)			\
++{							\
++	if (tape->debug_mask & lvl)			\
++	printk(KERN_INFO "ide-tape: " fmt, ## args);	\
 +}
-+
 +#else
-+
-+#define tsl2550_suspend		NULL
-+#define tsl2550_resume		NULL
-+
-+#endif /* CONFIG_PM */
-+
- static struct i2c_driver tsl2550_driver = {
- 	.driver = {
- 		.name	= TSL2550_DRV_NAME,
- 		.owner	= THIS_MODULE,
- 	},
-+	.suspend = tsl2550_suspend,
-+	.resume	= tsl2550_resume,
- 	.probe	= tsl2550_probe,
- 	.remove	= __devexit_p(tsl2550_remove),
- };
-diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
-index b5e13e4..96da22e 100644
---- a/drivers/i2c/i2c-core.c
-+++ b/drivers/i2c/i2c-core.c
-@@ -33,14 +33,15 @@
- #include <linux/platform_device.h>
- #include <linux/mutex.h>
- #include <linux/completion.h>
-+#include <linux/hardirq.h>
-+#include <linux/irqflags.h>
- #include <asm/uaccess.h>
-+#include <asm/semaphore.h>
++#define debug_log(lvl, fmt, args...) do {} while (0)
++#endif
  
- #include "i2c-core.h"
+ /**************************** Tunable parameters *****************************/
  
  
--static LIST_HEAD(adapters);
--static LIST_HEAD(drivers);
--static DEFINE_MUTEX(core_lists);
-+static DEFINE_MUTEX(core_lock);
- static DEFINE_IDR(i2c_adapter_idr);
+ /*
+- *	Pipelined mode parameters.
++ * Pipelined mode parameters.
+  *
+- *	We try to use the minimum number of stages which is enough to
+- *	keep the tape constantly streaming. To accomplish that, we implement
+- *	a feedback loop around the maximum number of stages:
++ * We try to use the minimum number of stages which is enough to keep the tape
++ * constantly streaming. To accomplish that, we implement a feedback loop around
++ * the maximum number of stages:
+  *
+- *	We start from MIN maximum stages (we will not even use MIN stages
+- *      if we don't need them), increment it by RATE*(MAX-MIN)
+- *	whenever we sense that the pipeline is empty, until we reach
+- *	the optimum value or until we reach MAX.
++ * We start from MIN maximum stages (we will not even use MIN stages if we don't
++ * need them), increment it by RATE*(MAX-MIN) whenever we sense that the
++ * pipeline is empty, until we reach the optimum value or until we reach MAX.
+  *
+- *	Setting the following parameter to 0 is illegal: the pipelined mode
+- *	cannot be disabled (calculate_speeds() divides by tape->max_stages.)
++ * Setting the following parameter to 0 is illegal: the pipelined mode cannot be
++ * disabled (idetape_calculate_speeds() divides by tape->max_stages.)
+  */
+ #define IDETAPE_MIN_PIPELINE_STAGES	  1
+ #define IDETAPE_MAX_PIPELINE_STAGES	400
+ #define IDETAPE_INCREASE_STAGES_RATE	 20
  
- #define is_newstyle_driver(d) ((d)->probe || (d)->remove)
-@@ -198,6 +199,25 @@ static struct bus_type i2c_bus_type = {
- 	.resume		= i2c_device_resume,
- };
+ /*
+- *	The following are used to debug the driver:
+- *
+- *	Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities.
+- *	Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
+- *	Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in
+- *	some places.
+- *
+- *	Setting them to 0 will restore normal operation mode:
+- *
+- *		1.	Disable logging normal successful operations.
+- *		2.	Disable self-sanity checks.
+- *		3.	Errors will still be logged, of course.
+- *
+- *	All the #if DEBUG code will be removed some day, when the driver
+- *	is verified to be stable enough. This will make it much more
+- *	esthetic.
+- */
+-#define IDETAPE_DEBUG_INFO		0
+-#define IDETAPE_DEBUG_LOG		0
+-#define IDETAPE_DEBUG_BUGS		1
+-
+-/*
+- *	After each failed packet command we issue a request sense command
+- *	and retry the packet command IDETAPE_MAX_PC_RETRIES times.
++ * After each failed packet command we issue a request sense command and retry
++ * the packet command IDETAPE_MAX_PC_RETRIES times.
+  *
+- *	Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
++ * Setting IDETAPE_MAX_PC_RETRIES to 0 will disable retries.
+  */
+ #define IDETAPE_MAX_PC_RETRIES		3
  
+ /*
+- *	With each packet command, we allocate a buffer of
+- *	IDETAPE_PC_BUFFER_SIZE bytes. This is used for several packet
+- *	commands (Not for READ/WRITE commands).
++ * With each packet command, we allocate a buffer of IDETAPE_PC_BUFFER_SIZE
++ * bytes. This is used for several packet commands (Not for READ/WRITE commands)
+  */
+ #define IDETAPE_PC_BUFFER_SIZE		256
+ 
+@@ -562,48 +121,39 @@ typedef struct os_dat_s {
+ #define IDETAPE_WAIT_CMD		(900*HZ)
+ 
+ /*
+- *	The following parameter is used to select the point in the internal
+- *	tape fifo in which we will start to refill the buffer. Decreasing
+- *	the following parameter will improve the system's latency and
+- *	interactive response, while using a high value might improve system
+- *	throughput.
++ * The following parameter is used to select the point in the internal tape fifo
++ * in which we will start to refill the buffer. Decreasing the following
++ * parameter will improve the system's latency and interactive response, while
++ * using a high value might improve system throughput.
+  */
+-#define IDETAPE_FIFO_THRESHOLD 		2
++#define IDETAPE_FIFO_THRESHOLD		2
+ 
+ /*
+- *	DSC polling parameters.
++ * DSC polling parameters.
+  *
+- *	Polling for DSC (a single bit in the status register) is a very
+- *	important function in ide-tape. There are two cases in which we
+- *	poll for DSC:
++ * Polling for DSC (a single bit in the status register) is a very important
++ * function in ide-tape. There are two cases in which we poll for DSC:
+  *
+- *	1.	Before a read/write packet command, to ensure that we
+- *		can transfer data from/to the tape's data buffers, without
+- *		causing an actual media access. In case the tape is not
+- *		ready yet, we take out our request from the device
+- *		request queue, so that ide.c will service requests from
+- *		the other device on the same interface meanwhile.
++ * 1. Before a read/write packet command, to ensure that we can transfer data
++ * from/to the tape's data buffers, without causing an actual media access.
++ * In case the tape is not ready yet, we take out our request from the device
++ * request queue, so that ide.c could service requests from the other device
++ * on the same interface in the meantime.
+  *
+- *	2.	After the successful initialization of a "media access
+- *		packet command", which is a command which can take a long
+- *		time to complete (it can be several seconds or even an hour).
++ * 2. After the successful initialization of a "media access packet command",
++ * which is a command that can take a long time to complete (the interval can
++ * range from several seconds to even an hour). Again, we postpone our request
++ * in the middle to free the bus for the other device. The polling frequency
++ * here should be lower than the read/write frequency since those media access
++ * commands are slow. We start from a "fast" frequency - IDETAPE_DSC_MA_FAST
++ * (1 second), and if we don't receive DSC after IDETAPE_DSC_MA_THRESHOLD
++ * (5 min), we switch it to a lower frequency - IDETAPE_DSC_MA_SLOW (1 min).
+  *
+- *		Again, we postpone our request in the middle to free the bus
+- *		for the other device. The polling frequency here should be
+- *		lower than the read/write frequency since those media access
+- *		commands are slow. We start from a "fast" frequency -
+- *		IDETAPE_DSC_MA_FAST (one second), and if we don't receive DSC
+- *		after IDETAPE_DSC_MA_THRESHOLD (5 minutes), we switch it to a
+- *		lower frequency - IDETAPE_DSC_MA_SLOW (1 minute).
+- *
+- *	We also set a timeout for the timer, in case something goes wrong.
+- *	The timeout should be longer then the maximum execution time of a
+- *	tape operation.
+- */
+- 
+-/*
+- *	DSC timings.
++ * We also set a timeout for the timer, in case something goes wrong. The
++ * timeout should be longer then the maximum execution time of a tape operation.
+  */
 +
-+/**
-+ * i2c_verify_client - return parameter as i2c_client, or NULL
-+ * @dev: device, probably from some driver model iterator
-+ *
-+ * When traversing the driver model tree, perhaps using driver model
-+ * iterators like @device_for_each_child(), you can't assume very much
-+ * about the nodes you find.  Use this function to avoid oopses caused
-+ * by wrongly treating some non-I2C device as an i2c_client.
-+ */
-+struct i2c_client *i2c_verify_client(struct device *dev)
-+{
-+	return (dev->bus == &i2c_bus_type)
-+			? to_i2c_client(dev)
-+			: NULL;
-+}
-+EXPORT_SYMBOL(i2c_verify_client);
-+
-+
- /**
-  * i2c_new_device - instantiate an i2c device for use with a new style driver
-  * @adap: the adapter managing the device
-@@ -276,6 +296,50 @@ void i2c_unregister_device(struct i2c_client *client)
- EXPORT_SYMBOL_GPL(i2c_unregister_device);
++/* DSC timings. */
+ #define IDETAPE_DSC_RW_MIN		5*HZ/100	/* 50 msec */
+ #define IDETAPE_DSC_RW_MAX		40*HZ/100	/* 400 msec */
+ #define IDETAPE_DSC_RW_TIMEOUT		2*60*HZ		/* 2 minutes */
+@@ -614,29 +164,15 @@ typedef struct os_dat_s {
  
+ /*************************** End of tunable parameters ***********************/
  
-+static int dummy_nop(struct i2c_client *client)
-+{
-+	return 0;
-+}
-+
-+static struct i2c_driver dummy_driver = {
-+	.driver.name	= "dummy",
-+	.probe		= dummy_nop,
-+	.remove		= dummy_nop,
+-/*
+- *	Debugging/Performance analysis
+- *
+- *	I/O trace support
+- */
+-#define USE_IOTRACE	0
+-#if USE_IOTRACE
+-#define IO_IDETAPE_FIFO	500
+-#endif
+-
+-/*
+- *	Read/Write error simulation
+- */
++/* Read/Write error simulation */
+ #define SIMULATE_ERRORS			0
+ 
+-/*
+- *	For general magnetic tape device compatibility.
+- */
+-typedef enum {
+-	idetape_direction_none,
+-	idetape_direction_read,
+-	idetape_direction_write
+-} idetape_chrdev_direction_t;
++/* tape directions */
++enum {
++	IDETAPE_DIR_NONE  = (1 << 0),
++	IDETAPE_DIR_READ  = (1 << 1),
++	IDETAPE_DIR_WRITE = (1 << 2),
 +};
-+
-+/**
-+ * i2c_new_dummy - return a new i2c device bound to a dummy driver
-+ * @adapter: the adapter managing the device
-+ * @address: seven bit address to be used
-+ * @type: optional label used for i2c_client.name
-+ * Context: can sleep
-+ *
-+ * This returns an I2C client bound to the "dummy" driver, intended for use
-+ * with devices that consume multiple addresses.  Examples of such chips
-+ * include various EEPROMS (like 24c04 and 24c08 models).
-+ *
-+ * These dummy devices have two main uses.  First, most I2C and SMBus calls
-+ * except i2c_transfer() need a client handle; the dummy will be that handle.
-+ * And second, this prevents the specified address from being bound to a
-+ * different driver.
-+ *
-+ * This returns the new i2c client, which should be saved for later use with
-+ * i2c_unregister_device(); or NULL to indicate an error.
-+ */
-+struct i2c_client *
-+i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type)
-+{
-+	struct i2c_board_info info = {
-+		.driver_name	= "dummy",
-+		.addr		= address,
-+	};
-+
-+	if (type)
-+		strlcpy(info.type, type, sizeof info.type);
-+	return i2c_new_device(adapter, &info);
-+}
-+EXPORT_SYMBOL_GPL(i2c_new_dummy);
-+
- /* ------------------------------------------------------------------------- */
  
- /* I2C bus adapters -- one roots each I2C or SMBUS segment */
-@@ -320,18 +384,27 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
- 	mutex_unlock(&__i2c_board_lock);
- }
+ struct idetape_bh {
+ 	u32 b_size;
+@@ -645,24 +181,32 @@ struct idetape_bh {
+ 	char *b_data;
+ };
  
-+static int i2c_do_add_adapter(struct device_driver *d, void *data)
-+{
-+	struct i2c_driver *driver = to_i2c_driver(d);
-+	struct i2c_adapter *adap = data;
-+
-+	if (driver->attach_adapter) {
-+		/* We ignore the return code; if it fails, too bad */
-+		driver->attach_adapter(adap);
-+	}
-+	return 0;
-+}
-+
- static int i2c_register_adapter(struct i2c_adapter *adap)
- {
--	int res = 0;
--	struct list_head   *item;
--	struct i2c_driver  *driver;
-+	int res = 0, dummy;
+-/*
+- *	Our view of a packet command.
+- */
+ typedef struct idetape_packet_command_s {
+-	u8 c[12];				/* Actual packet bytes */
+-	int retries;				/* On each retry, we increment retries */
+-	int error;				/* Error code */
+-	int request_transfer;			/* Bytes to transfer */
+-	int actually_transferred;		/* Bytes actually transferred */
+-	int buffer_size;			/* Size of our data buffer */
++	/* Actual packet bytes */
++	u8 c[12];
++	/* On each retry, we increment retries */
++	int retries;
++	/* Error code */
++	int error;
++	/* Bytes to transfer */
++	int request_transfer;
++	/* Bytes actually transferred */
++	int actually_transferred;
++	/* Size of our data buffer */
++	int buffer_size;
+ 	struct idetape_bh *bh;
+ 	char *b_data;
+ 	int b_count;
+-	u8 *buffer;				/* Data buffer */
+-	u8 *current_position;			/* Pointer into the above buffer */
+-	ide_startstop_t (*callback) (ide_drive_t *);	/* Called when this packet command is completed */
+-	u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE];	/* Temporary buffer */
+-	unsigned long flags;			/* Status/Action bit flags: long for set_bit */
++	/* Data buffer */
++	u8 *buffer;
++	/* Pointer into the above buffer */
++	u8 *current_position;
++	/* Called when this packet command is completed */
++	ide_startstop_t (*callback) (ide_drive_t *);
++	/* Temporary buffer */
++	u8 pc_buffer[IDETAPE_PC_BUFFER_SIZE];
++	/* Status/Action bit flags: long for set_bit */
++	unsigned long flags;
+ } idetape_pc_t;
  
- 	mutex_init(&adap->bus_lock);
- 	mutex_init(&adap->clist_lock);
- 	INIT_LIST_HEAD(&adap->clients);
+ /*
+@@ -681,68 +225,7 @@ typedef struct idetape_packet_command_s {
+ /* Data direction */
+ #define	PC_WRITING			5
  
--	mutex_lock(&core_lists);
--	list_add_tail(&adap->list, &adapters);
-+	mutex_lock(&core_lock);
+-/*
+- *	Capabilities and Mechanical Status Page
+- */
+-typedef struct {
+-	unsigned	page_code	:6;	/* Page code - Should be 0x2a */
+-	__u8		reserved0_6	:1;
+-	__u8		ps		:1;	/* parameters saveable */
+-	__u8		page_length;		/* Page Length - Should be 0x12 */
+-	__u8		reserved2, reserved3;
+-	unsigned	ro		:1;	/* Read Only Mode */
+-	unsigned	reserved4_1234	:4;
+-	unsigned	sprev		:1;	/* Supports SPACE in the reverse direction */
+-	unsigned	reserved4_67	:2;
+-	unsigned	reserved5_012	:3;
+-	unsigned	efmt		:1;	/* Supports ERASE command initiated formatting */
+-	unsigned	reserved5_4	:1;
+-	unsigned	qfa		:1;	/* Supports the QFA two partition formats */
+-	unsigned	reserved5_67	:2;
+-	unsigned	lock		:1;	/* Supports locking the volume */
+-	unsigned	locked		:1;	/* The volume is locked */
+-	unsigned	prevent		:1;	/* The device defaults in the prevent state after power up */	
+-	unsigned	eject		:1;	/* The device can eject the volume */
+-	__u8		disconnect	:1;	/* The device can break request > ctl */	
+-	__u8		reserved6_5	:1;
+-	unsigned	ecc		:1;	/* Supports error correction */
+-	unsigned	cmprs		:1;	/* Supports data compression */
+-	unsigned	reserved7_0	:1;
+-	unsigned	blk512		:1;	/* Supports 512 bytes block size */
+-	unsigned	blk1024		:1;	/* Supports 1024 bytes block size */
+-	unsigned	reserved7_3_6	:4;
+-	unsigned	blk32768	:1;	/* slowb - the device restricts the byte count for PIO */
+-						/* transfers for slow buffer memory ??? */
+-						/* Also 32768 block size in some cases */
+-	__u16		max_speed;		/* Maximum speed supported in KBps */
+-	__u8		reserved10, reserved11;
+-	__u16		ctl;			/* Continuous Transfer Limit in blocks */
+-	__u16		speed;			/* Current Speed, in KBps */
+-	__u16		buffer_size;		/* Buffer Size, in 512 bytes */
+-	__u8		reserved18, reserved19;
+-} idetape_capabilities_page_t;
+-
+-/*
+- *	Block Size Page
+- */
+-typedef struct {
+-	unsigned	page_code	:6;	/* Page code - Should be 0x30 */
+-	unsigned	reserved1_6	:1;
+-	unsigned	ps		:1;
+-	__u8		page_length;		/* Page Length - Should be 2 */
+-	__u8		reserved2;
+-	unsigned	play32		:1;
+-	unsigned	play32_5	:1;
+-	unsigned	reserved2_23	:2;
+-	unsigned	record32	:1;
+-	unsigned	record32_5	:1;
+-	unsigned	reserved2_6	:1;
+-	unsigned	one		:1;
+-} idetape_block_size_page_t;
+-
+-/*
+- *	A pipeline stage.
+- */
++/* A pipeline stage. */
+ typedef struct idetape_stage_s {
+ 	struct request rq;			/* The corresponding request */
+ 	struct idetape_bh *bh;			/* The data buffers */
+@@ -750,35 +233,8 @@ typedef struct idetape_stage_s {
+ } idetape_stage_t;
  
- 	/* Add the adapter to the driver core.
- 	 * If the parent pointer is not set up,
-@@ -356,19 +429,14 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
- 		i2c_scan_static_board_info(adap);
+ /*
+- *	REQUEST SENSE packet command result - Data Format.
+- */
+-typedef struct {
+-	unsigned	error_code	:7;	/* Current of deferred errors */
+-	unsigned	valid		:1;	/* The information field conforms to QIC-157C */
+-	__u8		reserved1	:8;	/* Segment Number - Reserved */
+-	unsigned	sense_key	:4;	/* Sense Key */
+-	unsigned	reserved2_4	:1;	/* Reserved */
+-	unsigned	ili		:1;	/* Incorrect Length Indicator */
+-	unsigned	eom		:1;	/* End Of Medium */
+-	unsigned	filemark 	:1;	/* Filemark */
+-	__u32		information __attribute__ ((packed));
+-	__u8		asl;			/* Additional sense length (n-7) */
+-	__u32		command_specific;	/* Additional command specific information */
+-	__u8		asc;			/* Additional Sense Code */
+-	__u8		ascq;			/* Additional Sense Code Qualifier */
+-	__u8		replaceable_unit_code;	/* Field Replaceable Unit Code */
+-	unsigned	sk_specific1 	:7;	/* Sense Key Specific */
+-	unsigned	sksv		:1;	/* Sense Key Specific information is valid */
+-	__u8		sk_specific2;		/* Sense Key Specific */
+-	__u8		sk_specific3;		/* Sense Key Specific */
+-	__u8		pad[2];			/* Padding to 20 bytes */
+-} idetape_request_sense_result_t;
+-
+-
+-/*
+- *	Most of our global data which we need to save even as we leave the
+- *	driver due to an interrupt or a timer event is stored in a variable
+- *	of type idetape_tape_t, defined below.
++ * Most of our global data which we need to save even as we leave the driver due
++ * to an interrupt or a timer event is stored in the struct defined below.
+  */
+ typedef struct ide_tape_obj {
+ 	ide_drive_t	*drive;
+@@ -814,15 +270,14 @@ typedef struct ide_tape_obj {
+ 	int rq_stack_index;
  
- 	/* let legacy drivers scan this bus for matching devices */
--	list_for_each(item,&drivers) {
--		driver = list_entry(item, struct i2c_driver, list);
--		if (driver->attach_adapter)
--			/* We ignore the return code; if it fails, too bad */
--			driver->attach_adapter(adap);
--	}
-+	dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
-+				 i2c_do_add_adapter);
+ 	/*
+-	 *	DSC polling variables.
++	 * DSC polling variables.
+ 	 *
+-	 *	While polling for DSC we use postponed_rq to postpone the
+-	 *	current request so that ide.c will be able to service
+-	 *	pending requests on the other device. Note that at most
+-	 *	we will have only one DSC (usually data transfer) request
+-	 *	in the device request queue. Additional requests can be
+-	 *	queued in our internal pipeline, but they will be visible
+-	 *	to ide.c only one at a time.
++	 * While polling for DSC we use postponed_rq to postpone the current
++	 * request so that ide.c will be able to service pending requests on the
++	 * other device. Note that at most we will have only one DSC (usually
++	 * data transfer) request in the device request queue. Additional
++	 * requests can be queued in our internal pipeline, but they will be
++	 * visible to ide.c only one at a time.
+ 	 */
+ 	struct request *postponed_rq;
+ 	/* The time in which we started polling for DSC */
+@@ -830,72 +285,57 @@ typedef struct ide_tape_obj {
+ 	/* Timer used to poll for dsc */
+ 	struct timer_list dsc_timer;
+ 	/* Read/Write dsc polling frequency */
+-	unsigned long best_dsc_rw_frequency;
+-	/* The current polling frequency */
+-	unsigned long dsc_polling_frequency;
+-	/* Maximum waiting time */
++	unsigned long best_dsc_rw_freq;
++	unsigned long dsc_poll_freq;
+ 	unsigned long dsc_timeout;
  
- out_unlock:
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
- 	return res;
+-	/*
+-	 *	Read position information
+-	 */
++	/* Read position information */
+ 	u8 partition;
+ 	/* Current block */
+-	unsigned int first_frame_position;
+-	unsigned int last_frame_position;
+-	unsigned int blocks_in_buffer;
++	unsigned int first_frame;
  
- out_list:
--	list_del(&adap->list);
- 	idr_remove(&i2c_adapter_idr, adap->nr);
- 	goto out_unlock;
- }
-@@ -394,11 +462,11 @@ retry:
- 	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
- 		return -ENOMEM;
+-	/*
+-	 *	Last error information
+-	 */
++	/* Last error information */
+ 	u8 sense_key, asc, ascq;
  
--	mutex_lock(&core_lists);
-+	mutex_lock(&core_lock);
- 	/* "above" here means "above or equal to", sigh */
- 	res = idr_get_new_above(&i2c_adapter_idr, adapter,
- 				__i2c_first_dynamic_bus_num, &id);
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
+-	/*
+-	 *	Character device operation
+-	 */
++	/* Character device operation */
+ 	unsigned int minor;
+ 	/* device name */
+ 	char name[4];
+ 	/* Current character device data transfer direction */
+-	idetape_chrdev_direction_t chrdev_direction;
++	u8 chrdev_dir;
  
- 	if (res < 0) {
- 		if (res == -EAGAIN)
-@@ -443,7 +511,7 @@ retry:
- 	if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
- 		return -ENOMEM;
+-	/*
+-	 *	Device information
+-	 */
+-	/* Usually 512 or 1024 bytes */
+-	unsigned short tape_block_size;
++	/* tape block size, usually 512 or 1024 bytes */
++	unsigned short blk_size;
+ 	int user_bs_factor;
++
+ 	/* Copy of the tape's Capabilities and Mechanical Page */
+-	idetape_capabilities_page_t capabilities;
++	u8 caps[20];
  
--	mutex_lock(&core_lists);
-+	mutex_lock(&core_lock);
- 	/* "above" here means "above or equal to", sigh;
- 	 * we need the "equal to" result to force the result
- 	 */
-@@ -452,7 +520,7 @@ retry:
- 		status = -EBUSY;
- 		idr_remove(&i2c_adapter_idr, id);
- 	}
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
- 	if (status == -EAGAIN)
- 		goto retry;
+ 	/*
+-	 *	Active data transfer request parameters.
++	 * Active data transfer request parameters.
+ 	 *
+-	 *	At most, there is only one ide-tape originated data transfer
+-	 *	request in the device request queue. This allows ide.c to
+-	 *	easily service requests from the other device when we
+-	 *	postpone our active request. In the pipelined operation
+-	 *	mode, we use our internal pipeline structure to hold
+-	 *	more data requests.
+-	 *
+-	 *	The data buffer size is chosen based on the tape's
+-	 *	recommendation.
++	 * At most, there is only one ide-tape originated data transfer request
++	 * in the device request queue. This allows ide.c to easily service
++	 * requests from the other device when we postpone our active request.
++	 * In the pipelined operation mode, we use our internal pipeline
++	 * structure to hold more data requests. The data buffer size is chosen
++	 * based on the tape's recommendation.
+ 	 */
+-	/* Pointer to the request which is waiting in the device request queue */
+-	struct request *active_data_request;
+-	/* Data buffer size (chosen based on the tape's recommendation */
++	/* ptr to the request which is waiting in the device request queue */
++	struct request *active_data_rq;
++	/* Data buffer size chosen based on the tape's recommendation */
+ 	int stage_size;
+ 	idetape_stage_t *merge_stage;
+ 	int merge_stage_size;
+ 	struct idetape_bh *bh;
+ 	char *b_data;
+ 	int b_count;
+-	
++
+ 	/*
+-	 *	Pipeline parameters.
++	 * Pipeline parameters.
+ 	 *
+-	 *	To accomplish non-pipelined mode, we simply set the following
+-	 *	variables to zero (or NULL, where appropriate).
++	 * To accomplish non-pipelined mode, we simply set the following
++	 * variables to zero (or NULL, where appropriate).
+ 	 */
+ 	/* Number of currently used stages */
+ 	int nr_stages;
+@@ -920,23 +360,13 @@ typedef struct ide_tape_obj {
+ 	/* Status/Action flags: long for set_bit */
+ 	unsigned long flags;
+ 	/* protects the ide-tape queue */
+-	spinlock_t spinlock;
++	spinlock_t lock;
  
-@@ -462,6 +530,21 @@ retry:
- }
- EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
+-	/*
+-	 * Measures average tape speed
+-	 */
++	/* Measures average tape speed */
+ 	unsigned long avg_time;
+ 	int avg_size;
+ 	int avg_speed;
  
-+static int i2c_do_del_adapter(struct device_driver *d, void *data)
-+{
-+	struct i2c_driver *driver = to_i2c_driver(d);
-+	struct i2c_adapter *adapter = data;
-+	int res;
-+
-+	if (!driver->detach_adapter)
-+		return 0;
-+	res = driver->detach_adapter(adapter);
-+	if (res)
-+		dev_err(&adapter->dev, "detach_adapter failed (%d) "
-+			"for driver [%s]\n", res, driver->driver.name);
-+	return res;
-+}
-+
- /**
-  * i2c_del_adapter - unregister I2C adapter
-  * @adap: the adapter being unregistered
-@@ -473,35 +556,24 @@ EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
- int i2c_del_adapter(struct i2c_adapter *adap)
- {
- 	struct list_head  *item, *_n;
--	struct i2c_adapter *adap_from_list;
--	struct i2c_driver *driver;
- 	struct i2c_client *client;
- 	int res = 0;
+-	/* last sense information */
+-	idetape_request_sense_result_t sense;
+-
+-	char vendor_id[10];
+-	char product_id[18];
+-	char firmware_revision[6];
+-	int firmware_revision_num;
+-
+ 	/* the door is currently locked */
+ 	int door_locked;
+ 	/* the tape hardware is write protected */
+@@ -945,11 +375,9 @@ typedef struct ide_tape_obj {
+ 	char write_prot;
  
--	mutex_lock(&core_lists);
-+	mutex_lock(&core_lock);
+ 	/*
+-	 * Limit the number of times a request can
+-	 * be postponed, to avoid an infinite postpone
+-	 * deadlock.
++	 * Limit the number of times a request can be postponed, to avoid an
++	 * infinite postpone deadlock.
+ 	 */
+-	/* request postpone count limit */
+ 	int postpone_cnt;
  
- 	/* First make sure that this adapter was ever added */
--	list_for_each_entry(adap_from_list, &adapters, list) {
--		if (adap_from_list == adap)
--			break;
--	}
--	if (adap_from_list != adap) {
-+	if (idr_find(&i2c_adapter_idr, adap->nr) != adap) {
- 		pr_debug("i2c-core: attempting to delete unregistered "
- 			 "adapter [%s]\n", adap->name);
- 		res = -EINVAL;
- 		goto out_unlock;
- 	}
+ 	/*
+@@ -964,30 +392,19 @@ typedef struct ide_tape_obj {
+ 	int tape_head;
+ 	int last_tape_head;
  
--	list_for_each(item,&drivers) {
--		driver = list_entry(item, struct i2c_driver, list);
--		if (driver->detach_adapter)
--			if ((res = driver->detach_adapter(adap))) {
--				dev_err(&adap->dev, "detach_adapter failed "
--					"for driver [%s]\n",
--					driver->driver.name);
--				goto out_unlock;
--			}
--	}
-+	/* Tell drivers about this removal */
-+	res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
-+			       i2c_do_del_adapter);
-+	if (res)
-+		goto out_unlock;
+-	/*
+-	 * Speed control at the tape buffers input/output
+-	 */
++	/* Speed control at the tape buffers input/output */
+ 	unsigned long insert_time;
+ 	int insert_size;
+ 	int insert_speed;
+ 	int max_insert_speed;
+ 	int measure_insert_time;
  
- 	/* detach any active clients. This must be done first, because
- 	 * it can fail; in which case we give up. */
-@@ -529,7 +601,6 @@ int i2c_del_adapter(struct i2c_adapter *adap)
- 	/* clean up the sysfs representation */
- 	init_completion(&adap->dev_released);
- 	device_unregister(&adap->dev);
--	list_del(&adap->list);
+-	/*
+-	 * Measure tape still time, in milliseconds
+-	 */
+-	unsigned long tape_still_time_begin;
+-	int tape_still_time;
+-
+-	/*
+-	 * Speed regulation negative feedback loop
+-	 */
++	/* Speed regulation negative feedback loop */
+ 	int speed_control;
+ 	int pipeline_head_speed;
+ 	int controlled_pipeline_head_speed;
+ 	int uncontrolled_pipeline_head_speed;
+ 	int controlled_last_pipeline_head;
+-	int uncontrolled_last_pipeline_head;
+ 	unsigned long uncontrolled_pipeline_head_time;
+ 	unsigned long controlled_pipeline_head_time;
+ 	int controlled_previous_pipeline_head;
+@@ -996,18 +413,7 @@ typedef struct ide_tape_obj {
+ 	unsigned long uncontrolled_previous_head_time;
+ 	int restart_speed_control_req;
  
- 	/* wait for sysfs to drop all references */
- 	wait_for_completion(&adap->dev_released);
-@@ -540,7 +611,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
- 	dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
+-        /*
+-         * Debug_level determines amount of debugging output;
+-         * can be changed using /proc/ide/hdx/settings
+-         * 0 : almost no debugging output
+-         * 1 : 0+output errors only
+-         * 2 : 1+output all sensekey/asc
+-         * 3 : 2+follow all chrdev related procedures
+-         * 4 : 3+follow all procedures
+-         * 5 : 4+include pc_stack rq_stack info
+-         * 6 : 5+USE_COUNT updates
+-         */
+-         int debug_level; 
++	u32 debug_mask;
+ } idetape_tape_t;
  
-  out_unlock:
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
- 	return res;
+ static DEFINE_MUTEX(idetape_ref_mutex);
+@@ -1040,9 +446,7 @@ static void ide_tape_put(struct ide_tape_obj *tape)
+ 	mutex_unlock(&idetape_ref_mutex);
  }
- EXPORT_SYMBOL(i2c_del_adapter);
-@@ -583,21 +654,23 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
- 	if (res)
- 		return res;
  
--	mutex_lock(&core_lists);
-+	mutex_lock(&core_lock);
+-/*
+- *	Tape door status
+- */
++/* Tape door status */
+ #define DOOR_UNLOCKED			0
+ #define DOOR_LOCKED			1
+ #define DOOR_EXPLICITLY_LOCKED		2
+@@ -1062,51 +466,23 @@ static void ide_tape_put(struct ide_tape_obj *tape)
+ /* 0 = no tape is loaded, so we don't rewind after ejecting */
+ #define IDETAPE_MEDIUM_PRESENT		9
  
--	list_add_tail(&driver->list,&drivers);
- 	pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
+-/*
+- *	Supported ATAPI tape drives packet commands
+- */
+-#define IDETAPE_TEST_UNIT_READY_CMD	0x00
+-#define IDETAPE_REWIND_CMD		0x01
+-#define IDETAPE_REQUEST_SENSE_CMD	0x03
+-#define IDETAPE_READ_CMD		0x08
+-#define IDETAPE_WRITE_CMD		0x0a
+-#define IDETAPE_WRITE_FILEMARK_CMD	0x10
+-#define IDETAPE_SPACE_CMD		0x11
+-#define IDETAPE_INQUIRY_CMD		0x12
+-#define IDETAPE_ERASE_CMD		0x19
+-#define IDETAPE_MODE_SENSE_CMD		0x1a
+-#define IDETAPE_MODE_SELECT_CMD		0x15
+-#define IDETAPE_LOAD_UNLOAD_CMD		0x1b
+-#define IDETAPE_PREVENT_CMD		0x1e
+-#define IDETAPE_LOCATE_CMD		0x2b
+-#define IDETAPE_READ_POSITION_CMD	0x34
+-#define IDETAPE_READ_BUFFER_CMD		0x3c
+-#define IDETAPE_SET_SPEED_CMD		0xbb
+-
+-/*
+- *	Some defines for the READ BUFFER command
+- */
++/* A define for the READ BUFFER command */
+ #define IDETAPE_RETRIEVE_FAULTY_BLOCK	6
  
- 	/* legacy drivers scan i2c busses directly */
- 	if (driver->attach_adapter) {
- 		struct i2c_adapter *adapter;
+-/*
+- *	Some defines for the SPACE command
+- */
++/* Some defines for the SPACE command */
+ #define IDETAPE_SPACE_OVER_FILEMARK	1
+ #define IDETAPE_SPACE_TO_EOD		3
  
--		list_for_each_entry(adapter, &adapters, list) {
-+		down(&i2c_adapter_class.sem);
-+		list_for_each_entry(adapter, &i2c_adapter_class.devices,
-+				    dev.node) {
- 			driver->attach_adapter(adapter);
- 		}
-+		up(&i2c_adapter_class.sem);
- 	}
+-/*
+- *	Some defines for the LOAD UNLOAD command
+- */
++/* Some defines for the LOAD UNLOAD command */
+ #define IDETAPE_LU_LOAD_MASK		1
+ #define IDETAPE_LU_RETENSION_MASK	2
+ #define IDETAPE_LU_EOT_MASK		4
  
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
- 	return 0;
- }
- EXPORT_SYMBOL(i2c_register_driver);
-@@ -609,11 +682,11 @@ EXPORT_SYMBOL(i2c_register_driver);
+ /*
+- *	Special requests for our block device strategy routine.
++ * Special requests for our block device strategy routine.
+  *
+- *	In order to service a character device command, we add special
+- *	requests to the tail of our block device request queue and wait
+- *	for their completion.
++ * In order to service a character device command, we add special requests to
++ * the tail of our block device request queue and wait for their completion.
   */
- void i2c_del_driver(struct i2c_driver *driver)
- {
--	struct list_head   *item1, *item2, *_n;
-+	struct list_head   *item2, *_n;
- 	struct i2c_client  *client;
- 	struct i2c_adapter *adap;
  
--	mutex_lock(&core_lists);
-+	mutex_lock(&core_lock);
+ enum {
+@@ -1117,171 +493,20 @@ enum {
+ 	REQ_IDETAPE_READ_BUFFER	= (1 << 4),
+ };
  
- 	/* new-style driver? */
- 	if (is_newstyle_driver(driver))
-@@ -623,8 +696,8 @@ void i2c_del_driver(struct i2c_driver *driver)
- 	 * attached. If so, detach them to be able to kill the driver
- 	 * afterwards.
- 	 */
--	list_for_each(item1,&adapters) {
--		adap = list_entry(item1, struct i2c_adapter, list);
-+	down(&i2c_adapter_class.sem);
-+	list_for_each_entry(adap, &i2c_adapter_class.devices, dev.node) {
- 		if (driver->detach_adapter) {
- 			if (driver->detach_adapter(adap)) {
- 				dev_err(&adap->dev, "detach_adapter failed "
-@@ -648,40 +721,31 @@ void i2c_del_driver(struct i2c_driver *driver)
- 			}
- 		}
- 	}
-+	up(&i2c_adapter_class.sem);
+-/*
+- *	Error codes which are returned in rq->errors to the higher part
+- *	of the driver.
+- */
++/* Error codes returned in rq->errors to the higher part of the driver. */
+ #define	IDETAPE_ERROR_GENERAL		101
+ #define	IDETAPE_ERROR_FILEMARK		102
+ #define	IDETAPE_ERROR_EOD		103
  
-  unregister:
- 	driver_unregister(&driver->driver);
--	list_del(&driver->list);
- 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
+-/*
+- *	The following is used to format the general configuration word of
+- *	the ATAPI IDENTIFY DEVICE command.
+- */
+-struct idetape_id_gcw {	
+-	unsigned packet_size		:2;	/* Packet Size */
+-	unsigned reserved234		:3;	/* Reserved */
+-	unsigned drq_type		:2;	/* Command packet DRQ type */
+-	unsigned removable		:1;	/* Removable media */
+-	unsigned device_type		:5;	/* Device type */
+-	unsigned reserved13		:1;	/* Reserved */
+-	unsigned protocol		:2;	/* Protocol type */
+-};
+-
+-/*
+- *	INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C)
+- */
+-typedef struct {
+-	unsigned	device_type	:5;	/* Peripheral Device Type */
+-	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */
+-	unsigned	reserved1_6t0	:7;	/* Reserved */
+-	unsigned	rmb		:1;	/* Removable Medium Bit */
+-	unsigned	ansi_version	:3;	/* ANSI Version */
+-	unsigned	ecma_version	:3;	/* ECMA Version */
+-	unsigned	iso_version	:2;	/* ISO Version */
+-	unsigned	response_format :4;	/* Response Data Format */
+-	unsigned	reserved3_45	:2;	/* Reserved */
+-	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */
+-	unsigned	reserved3_7	:1;	/* AENC - Reserved */
+-	__u8		additional_length;	/* Additional Length (total_length-4) */
+-	__u8		rsv5, rsv6, rsv7;	/* Reserved */
+-	__u8		vendor_id[8];		/* Vendor Identification */
+-	__u8		product_id[16];		/* Product Identification */
+-	__u8		revision_level[4];	/* Revision Level */
+-	__u8		vendor_specific[20];	/* Vendor Specific - Optional */
+-	__u8		reserved56t95[40];	/* Reserved - Optional */
+-						/* Additional information may be returned */
+-} idetape_inquiry_result_t;
+-
+-/*
+- *	READ POSITION packet command - Data Format (From Table 6-57)
+- */
+-typedef struct {
+-	unsigned	reserved0_10	:2;	/* Reserved */
+-	unsigned	bpu		:1;	/* Block Position Unknown */	
+-	unsigned	reserved0_543	:3;	/* Reserved */
+-	unsigned	eop		:1;	/* End Of Partition */
+-	unsigned	bop		:1;	/* Beginning Of Partition */
+-	u8		partition;		/* Partition Number */
+-	u8		reserved2, reserved3;	/* Reserved */
+-	u32		first_block;		/* First Block Location */
+-	u32		last_block;		/* Last Block Location (Optional) */
+-	u8		reserved12;		/* Reserved */
+-	u8		blocks_in_buffer[3];	/* Blocks In Buffer - (Optional) */
+-	u32		bytes_in_buffer;	/* Bytes In Buffer (Optional) */
+-} idetape_read_position_result_t;
+-
+-/*
+- *	Follows structures which are related to the SELECT SENSE / MODE SENSE
+- *	packet commands. Those packet commands are still not supported
+- *	by ide-tape.
+- */
++/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
+ #define IDETAPE_BLOCK_DESCRIPTOR	0
+ #define	IDETAPE_CAPABILITIES_PAGE	0x2a
+-#define IDETAPE_PARAMTR_PAGE		0x2b   /* Onstream DI-x0 only */
+-#define IDETAPE_BLOCK_SIZE_PAGE		0x30
+-#define IDETAPE_BUFFER_FILLING_PAGE	0x33
+-
+-/*
+- *	Mode Parameter Header for the MODE SENSE packet command
+- */
+-typedef struct {
+-	__u8	mode_data_length;	/* Length of the following data transfer */
+-	__u8	medium_type;		/* Medium Type */
+-	__u8	dsp;			/* Device Specific Parameter */
+-	__u8	bdl;			/* Block Descriptor Length */
+-#if 0
+-	/* data transfer page */
+-	__u8	page_code	:6;
+-	__u8	reserved0_6	:1;
+-	__u8	ps		:1;	/* parameters saveable */
+-	__u8	page_length;		/* page Length == 0x02 */
+-	__u8	reserved2;
+-	__u8	read32k		:1;	/* 32k blk size (data only) */
+-	__u8	read32k5	:1;	/* 32.5k blk size (data&AUX) */
+-	__u8	reserved3_23	:2;
+-	__u8	write32k	:1;	/* 32k blk size (data only) */
+-	__u8	write32k5	:1;	/* 32.5k blk size (data&AUX) */
+-	__u8	reserved3_6	:1;
+-	__u8	streaming	:1;	/* streaming mode enable */
+-#endif
+-} idetape_mode_parameter_header_t;
+-
+-/*
+- *	Mode Parameter Block Descriptor the MODE SENSE packet command
+- *
+- *	Support for block descriptors is optional.
+- */
+-typedef struct {
+-	__u8		density_code;		/* Medium density code */
+-	__u8		blocks[3];		/* Number of blocks */
+-	__u8		reserved4;		/* Reserved */
+-	__u8		length[3];		/* Block Length */
+-} idetape_parameter_block_descriptor_t;
+-
+-/*
+- *	The Data Compression Page, as returned by the MODE SENSE packet command.
+- */
+-typedef struct {
+-	unsigned	page_code	:6;	/* Page Code - Should be 0xf */
+-	unsigned	reserved0	:1;	/* Reserved */
+-	unsigned	ps		:1;
+-	__u8		page_length;		/* Page Length - Should be 14 */
+-	unsigned	reserved2	:6;	/* Reserved */
+-	unsigned	dcc		:1;	/* Data Compression Capable */
+-	unsigned	dce		:1;	/* Data Compression Enable */
+-	unsigned	reserved3	:5;	/* Reserved */
+-	unsigned	red		:2;	/* Report Exception on Decompression */
+-	unsigned	dde		:1;	/* Data Decompression Enable */
+-	__u32		ca;			/* Compression Algorithm */
+-	__u32		da;			/* Decompression Algorithm */
+-	__u8		reserved[4];		/* Reserved */
+-} idetape_data_compression_page_t;
+-
+-/*
+- *	The Medium Partition Page, as returned by the MODE SENSE packet command.
+- */
+-typedef struct {
+-	unsigned	page_code	:6;	/* Page Code - Should be 0x11 */
+-	unsigned	reserved1_6	:1;	/* Reserved */
+-	unsigned	ps		:1;
+-	__u8		page_length;		/* Page Length - Should be 6 */
+-	__u8		map;			/* Maximum Additional Partitions - Should be 0 */
+-	__u8		apd;			/* Additional Partitions Defined - Should be 0 */
+-	unsigned	reserved4_012	:3;	/* Reserved */
+-	unsigned	psum		:2;	/* Should be 0 */
+-	unsigned	idp		:1;	/* Should be 0 */
+-	unsigned	sdp		:1;	/* Should be 0 */
+-	unsigned	fdp		:1;	/* Fixed Data Partitions */
+-	__u8		mfr;			/* Medium Format Recognition */
+-	__u8		reserved[2];		/* Reserved */
+-} idetape_medium_partition_page_t;
+-
+-/*
+- *	Run time configurable parameters.
+- */
+-typedef struct {
+-	int	dsc_rw_frequency;
+-	int	dsc_media_access_frequency;
+-	int	nr_stages;
+-} idetape_config_t;
  
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
+ /*
+- *	The variables below are used for the character device interface.
+- *	Additional state variables are defined in our ide_drive_t structure.
++ * The variables below are used for the character device interface. Additional
++ * state variables are defined in our ide_drive_t structure.
+  */
+-static struct ide_tape_obj * idetape_devs[MAX_HWIFS * MAX_DRIVES];
++static struct ide_tape_obj *idetape_devs[MAX_HWIFS * MAX_DRIVES];
+ 
+ #define ide_tape_f(file) ((file)->private_data)
+ 
+@@ -1298,38 +523,33 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i)
  }
- EXPORT_SYMBOL(i2c_del_driver);
  
- /* ------------------------------------------------------------------------- */
+ /*
+- *      Function declarations
+- *
+- */
+-static int idetape_chrdev_release (struct inode *inode, struct file *filp);
+-static void idetape_write_release (ide_drive_t *drive, unsigned int minor);
+-
+-/*
+  * Too bad. The drive wants to send us data which we are not ready to accept.
+  * Just throw it away.
+  */
+-static void idetape_discard_data (ide_drive_t *drive, unsigned int bcount)
++static void idetape_discard_data(ide_drive_t *drive, unsigned int bcount)
+ {
+ 	while (bcount--)
+ 		(void) HWIF(drive)->INB(IDE_DATA_REG);
+ }
  
--static int __i2c_check_addr(struct i2c_adapter *adapter, unsigned int addr)
-+static int __i2c_check_addr(struct device *dev, void *addrp)
+-static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount)
++static void idetape_input_buffers(ide_drive_t *drive, idetape_pc_t *pc,
++				  unsigned int bcount)
  {
--	struct list_head   *item;
--	struct i2c_client  *client;
-+	struct i2c_client	*client = i2c_verify_client(dev);
-+	int			addr = *(int *)addrp;
+ 	struct idetape_bh *bh = pc->bh;
+ 	int count;
  
--	list_for_each(item,&adapter->clients) {
--		client = list_entry(item, struct i2c_client, list);
--		if (client->addr == addr)
--			return -EBUSY;
--	}
-+	if (client && client->addr == addr)
-+		return -EBUSY;
- 	return 0;
+ 	while (bcount) {
+-#if IDETAPE_DEBUG_BUGS
+ 		if (bh == NULL) {
+ 			printk(KERN_ERR "ide-tape: bh == NULL in "
+ 				"idetape_input_buffers\n");
+ 			idetape_discard_data(drive, bcount);
+ 			return;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+-		count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount);
+-		HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count);
++		count = min(
++			(unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
++			bcount);
++		HWIF(drive)->atapi_input_bytes(drive, bh->b_data +
++					atomic_read(&bh->b_count), count);
+ 		bcount -= count;
+ 		atomic_add(count, &bh->b_count);
+ 		if (atomic_read(&bh->b_count) == bh->b_size) {
+@@ -1341,26 +561,26 @@ static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigne
+ 	pc->bh = bh;
  }
  
- static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
+-static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigned int bcount)
++static void idetape_output_buffers(ide_drive_t *drive, idetape_pc_t *pc,
++				   unsigned int bcount)
  {
--	int rval;
--
--	mutex_lock(&adapter->clist_lock);
--	rval = __i2c_check_addr(adapter, addr);
--	mutex_unlock(&adapter->clist_lock);
--
--	return rval;
-+	return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
- }
+ 	struct idetape_bh *bh = pc->bh;
+ 	int count;
  
- int i2c_attach_client(struct i2c_client *client)
-@@ -689,15 +753,6 @@ int i2c_attach_client(struct i2c_client *client)
- 	struct i2c_adapter *adapter = client->adapter;
- 	int res = 0;
+ 	while (bcount) {
+-#if IDETAPE_DEBUG_BUGS
+ 		if (bh == NULL) {
+-			printk(KERN_ERR "ide-tape: bh == NULL in "
+-				"idetape_output_buffers\n");
++			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
++					__func__);
+ 			return;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 		count = min((unsigned int)pc->b_count, (unsigned int)bcount);
+ 		HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);
+ 		bcount -= count;
+ 		pc->b_data += count;
+ 		pc->b_count -= count;
+ 		if (!pc->b_count) {
+-			pc->bh = bh = bh->b_reqnext;
++			bh = bh->b_reqnext;
++			pc->bh = bh;
+ 			if (bh) {
+ 				pc->b_data = bh->b_data;
+ 				pc->b_count = atomic_read(&bh->b_count);
+@@ -1369,7 +589,7 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign
+ 	}
+ }
  
--	mutex_lock(&adapter->clist_lock);
--	if (__i2c_check_addr(client->adapter, client->addr)) {
--		res = -EBUSY;
--		goto out_unlock;
--	}
--	list_add_tail(&client->list,&adapter->clients);
--
--	client->usage_count = 0;
--
- 	client->dev.parent = &client->adapter->dev;
- 	client->dev.bus = &i2c_bus_type;
+-static void idetape_update_buffers (idetape_pc_t *pc)
++static void idetape_update_buffers(idetape_pc_t *pc)
+ {
+ 	struct idetape_bh *bh = pc->bh;
+ 	int count;
+@@ -1378,13 +598,11 @@ static void idetape_update_buffers (idetape_pc_t *pc)
+ 	if (test_bit(PC_WRITING, &pc->flags))
+ 		return;
+ 	while (bcount) {
+-#if IDETAPE_DEBUG_BUGS
+ 		if (bh == NULL) {
+-			printk(KERN_ERR "ide-tape: bh == NULL in "
+-				"idetape_update_buffers\n");
++			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
++					__func__);
+ 			return;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 		count = min((unsigned int)bh->b_size, (unsigned int)bcount);
+ 		atomic_set(&bh->b_count, count);
+ 		if (atomic_read(&bh->b_count) == bh->b_size)
+@@ -1400,17 +618,14 @@ static void idetape_update_buffers (idetape_pc_t *pc)
+  *	driver. A storage space for a maximum of IDETAPE_PC_STACK packet
+  *	commands is allocated at initialization time.
+  */
+-static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive)
++static idetape_pc_t *idetape_next_pc_storage(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
-@@ -712,13 +767,17 @@ int i2c_attach_client(struct i2c_client *client)
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 5)
+-		printk(KERN_INFO "ide-tape: pc_stack_index=%d\n",
+-			tape->pc_stack_index);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PCRQ_STACK, "pc_stack_index=%d\n", tape->pc_stack_index);
++
+ 	if (tape->pc_stack_index == IDETAPE_PC_STACK)
+-		tape->pc_stack_index=0;
++		tape->pc_stack_index = 0;
+ 	return (&tape->pc_stack[tape->pc_stack_index++]);
+ }
  
- 	snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
- 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
--	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
--		client->name, client->dev.bus_id);
- 	res = device_register(&client->dev);
- 	if (res)
--		goto out_list;
-+		goto out_err;
+@@ -1419,32 +634,26 @@ static idetape_pc_t *idetape_next_pc_storage (ide_drive_t *drive)
+  *	Since we queue packet commands in the request queue, we need to
+  *	allocate a request, along with the allocation of a packet command.
+  */
+- 
 +
-+	mutex_lock(&adapter->clist_lock);
-+	list_add_tail(&client->list, &adapter->clients);
- 	mutex_unlock(&adapter->clist_lock);
- 
-+	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
-+		client->name, client->dev.bus_id);
+ /**************************************************************
+  *                                                            *
+  *  This should get fixed to use kmalloc(.., GFP_ATOMIC)      *
+  *  followed later on by kfree().   -ml                       *
+  *                                                            *
+  **************************************************************/
+- 
+-static struct request *idetape_next_rq_storage (ide_drive_t *drive)
 +
- 	if (adapter->client_register)  {
- 		if (adapter->client_register(client)) {
- 			dev_dbg(&adapter->dev, "client_register "
-@@ -729,12 +788,9 @@ int i2c_attach_client(struct i2c_client *client)
++static struct request *idetape_next_rq_storage(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
- 	return 0;
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 5)
+-		printk(KERN_INFO "ide-tape: rq_stack_index=%d\n",
+-			tape->rq_stack_index);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PCRQ_STACK, "rq_stack_index=%d\n", tape->rq_stack_index);
++
+ 	if (tape->rq_stack_index == IDETAPE_PC_STACK)
+-		tape->rq_stack_index=0;
++		tape->rq_stack_index = 0;
+ 	return (&tape->rq_stack[tape->rq_stack_index++]);
+ }
  
--out_list:
--	list_del(&client->list);
-+out_err:
- 	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
- 		"(%d)\n", client->name, client->addr, res);
--out_unlock:
--	mutex_unlock(&adapter->clist_lock);
- 	return res;
+-/*
+- *	idetape_init_pc initializes a packet command.
+- */
+-static void idetape_init_pc (idetape_pc_t *pc)
++static void idetape_init_pc(idetape_pc_t *pc)
+ {
+ 	memset(pc->c, 0, 12);
+ 	pc->retries = 0;
+@@ -1457,36 +666,26 @@ static void idetape_init_pc (idetape_pc_t *pc)
  }
- EXPORT_SYMBOL(i2c_attach_client);
-@@ -744,12 +800,6 @@ int i2c_detach_client(struct i2c_client *client)
- 	struct i2c_adapter *adapter = client->adapter;
- 	int res = 0;
  
--	if (client->usage_count > 0) {
--		dev_warn(&client->dev, "Client [%s] still busy, "
--			 "can't detach\n", client->name);
--		return -EBUSY;
--	}
--
- 	if (adapter->client_unregister)  {
- 		res = adapter->client_unregister(client);
- 		if (res) {
-@@ -762,9 +812,10 @@ int i2c_detach_client(struct i2c_client *client)
+ /*
+- *	idetape_analyze_error is called on each failed packet command retry
+- *	to analyze the request sense. We currently do not utilize this
+- *	information.
++ * called on each failed packet command retry to analyze the request sense. We
++ * currently do not utilize this information.
+  */
+-static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_result_t *result)
++static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t *pc = tape->failed_pc;
  
- 	mutex_lock(&adapter->clist_lock);
- 	list_del(&client->list);
-+	mutex_unlock(&adapter->clist_lock);
+-	tape->sense     = *result;
+-	tape->sense_key = result->sense_key;
+-	tape->asc       = result->asc;
+-	tape->ascq      = result->ascq;
+-#if IDETAPE_DEBUG_LOG
+-	/*
+-	 *	Without debugging, we only log an error if we decided to
+-	 *	give up retrying.
+-	 */
+-	if (tape->debug_level >= 1)
+-		printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, "
+-			"asc = %x, ascq = %x\n",
+-			pc->c[0], result->sense_key,
+-			result->asc, result->ascq);
+-#endif /* IDETAPE_DEBUG_LOG */
++	tape->sense_key = sense[2] & 0xF;
++	tape->asc       = sense[12];
++	tape->ascq      = sense[13];
+ 
+-	/*
+-	 *	Correct pc->actually_transferred by asking the tape.
+-	 */
++	debug_log(DBG_ERR, "pc = %x, sense key = %x, asc = %x, ascq = %x\n",
++		 pc->c[0], tape->sense_key, tape->asc, tape->ascq);
 +
- 	init_completion(&client->released);
- 	device_unregister(&client->dev);
--	mutex_unlock(&adapter->clist_lock);
- 	wait_for_completion(&client->released);
++	/* Correct pc->actually_transferred by asking the tape.	 */
+ 	if (test_bit(PC_DMA_ERROR, &pc->flags)) {
+-		pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information));
++		pc->actually_transferred = pc->request_transfer -
++			tape->blk_size *
++			be32_to_cpu(get_unaligned((u32 *)&sense[3]));
+ 		idetape_update_buffers(pc);
+ 	}
  
-  out:
-@@ -772,72 +823,58 @@ int i2c_detach_client(struct i2c_client *client)
+@@ -1495,29 +694,29 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
+ 	 * with sense key=5, asc=0x22, ascq=0, let it slide.  Some drives
+ 	 * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes.
+ 	 */
+-	if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD)
+-	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { /* length==0 */
+-		if (result->sense_key == 5) {
++	if ((pc->c[0] == READ_6 || pc->c[0] == WRITE_6)
++	    /* length == 0 */
++	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) {
++		if (tape->sense_key == 5) {
+ 			/* don't report an error, everything's ok */
+ 			pc->error = 0;
+ 			/* don't retry read/write */
+ 			set_bit(PC_ABORT, &pc->flags);
+ 		}
+ 	}
+-	if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) {
++	if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
+ 		pc->error = IDETAPE_ERROR_FILEMARK;
+ 		set_bit(PC_ABORT, &pc->flags);
+ 	}
+-	if (pc->c[0] == IDETAPE_WRITE_CMD) {
+-		if (result->eom ||
+-		    (result->sense_key == 0xd && result->asc == 0x0 &&
+-		     result->ascq == 0x2)) {
++	if (pc->c[0] == WRITE_6) {
++		if ((sense[2] & 0x40) || (tape->sense_key == 0xd
++		     && tape->asc == 0x0 && tape->ascq == 0x2)) {
+ 			pc->error = IDETAPE_ERROR_EOD;
+ 			set_bit(PC_ABORT, &pc->flags);
+ 		}
+ 	}
+-	if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) {
+-		if (result->sense_key == 8) {
++	if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
++		if (tape->sense_key == 8) {
+ 			pc->error = IDETAPE_ERROR_EOD;
+ 			set_bit(PC_ABORT, &pc->flags);
+ 		}
+@@ -1527,61 +726,30 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
+ 	}
  }
- EXPORT_SYMBOL(i2c_detach_client);
  
--static int i2c_inc_use_client(struct i2c_client *client)
-+/**
-+ * i2c_use_client - increments the reference count of the i2c client structure
-+ * @client: the client being referenced
-+ *
-+ * Each live reference to a client should be refcounted. The driver model does
-+ * that automatically as part of driver binding, so that most drivers don't
-+ * need to do this explicitly: they hold a reference until they're unbound
-+ * from the device.
-+ *
-+ * A pointer to the client with the incremented reference counter is returned.
-+ */
-+struct i2c_client *i2c_use_client(struct i2c_client *client)
+-/*
+- * idetape_active_next_stage will declare the next stage as "active".
+- */
+-static void idetape_active_next_stage (ide_drive_t *drive)
++static void idetape_activate_next_stage(ide_drive_t *drive)
  {
--
--	if (!try_module_get(client->driver->driver.owner))
--		return -ENODEV;
--	if (!try_module_get(client->adapter->owner)) {
--		module_put(client->driver->driver.owner);
--		return -ENODEV;
--	}
--
--	return 0;
-+	get_device(&client->dev);
-+	return client;
- }
-+EXPORT_SYMBOL(i2c_use_client);
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_stage_t *stage = tape->next_stage;
+ 	struct request *rq = &stage->rq;
  
--static void i2c_dec_use_client(struct i2c_client *client)
-+/**
-+ * i2c_release_client - release a use of the i2c client structure
-+ * @client: the client being no longer referenced
-+ *
-+ * Must be called when a user of a client is finished with it.
-+ */
-+void i2c_release_client(struct i2c_client *client)
- {
--	module_put(client->driver->driver.owner);
--	module_put(client->adapter->owner);
-+	put_device(&client->dev);
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_active_next_stage\n");
+-#endif /* IDETAPE_DEBUG_LOG */
+-#if IDETAPE_DEBUG_BUGS
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
++
+ 	if (stage == NULL) {
+-		printk(KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n");
++		printk(KERN_ERR "ide-tape: bug: Trying to activate a non"
++				" existing stage\n");
+ 		return;
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */	
+ 
+ 	rq->rq_disk = tape->disk;
+ 	rq->buffer = NULL;
+ 	rq->special = (void *)stage->bh;
+-	tape->active_data_request = rq;
++	tape->active_data_rq = rq;
+ 	tape->active_stage = stage;
+ 	tape->next_stage = stage->next;
  }
-+EXPORT_SYMBOL(i2c_release_client);
  
--int i2c_use_client(struct i2c_client *client)
+-/*
+- *	idetape_increase_max_pipeline_stages is a part of the feedback
+- *	loop which tries to find the optimum number of stages. In the
+- *	feedback loop, we are starting from a minimum maximum number of
+- *	stages, and if we sense that the pipeline is empty, we try to
+- *	increase it, until we reach the user compile time memory limit.
+- */
+-static void idetape_increase_max_pipeline_stages (ide_drive_t *drive)
 -{
--	int ret;
--
--	ret = i2c_inc_use_client(client);
--	if (ret)
--		return ret;
--
--	client->usage_count++;
+-	idetape_tape_t *tape = drive->driver_data;
+-	int increase = (tape->max_pipeline - tape->min_pipeline) / 10;
+-	
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk (KERN_INFO "ide-tape: Reached idetape_increase_max_pipeline_stages\n");
+-#endif /* IDETAPE_DEBUG_LOG */
 -
--	return 0;
+-	tape->max_stages += max(increase, 1);
+-	tape->max_stages = max(tape->max_stages, tape->min_pipeline);
+-	tape->max_stages = min(tape->max_stages, tape->max_pipeline);
 -}
--EXPORT_SYMBOL(i2c_use_client);
-+struct i2c_cmd_arg {
-+	unsigned	cmd;
-+	void		*arg;
-+};
- 
--int i2c_release_client(struct i2c_client *client)
-+static int i2c_cmd(struct device *dev, void *_arg)
- {
--	if (!client->usage_count) {
--		pr_debug("i2c-core: %s used one too many times\n",
--			 __FUNCTION__);
--		return -EPERM;
--	}
 -
--	client->usage_count--;
--	i2c_dec_use_client(client);
-+	struct i2c_client	*client = i2c_verify_client(dev);
-+	struct i2c_cmd_arg	*arg = _arg;
- 
-+	if (client && client->driver && client->driver->command)
-+		client->driver->command(client, arg->cmd, arg->arg);
- 	return 0;
+-/*
+- *	idetape_kfree_stage calls kfree to completely free a stage, along with
+- *	its related buffers.
+- */
+-static void __idetape_kfree_stage (idetape_stage_t *stage)
++/* Free a stage along with its related buffers completely. */
++static void __idetape_kfree_stage(idetape_stage_t *stage)
+ {
+ 	struct idetape_bh *prev_bh, *bh = stage->bh;
+ 	int size;
+@@ -1602,46 +770,43 @@ static void __idetape_kfree_stage (idetape_stage_t *stage)
+ 	kfree(stage);
  }
--EXPORT_SYMBOL(i2c_release_client);
  
- void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
+-static void idetape_kfree_stage (idetape_tape_t *tape, idetape_stage_t *stage)
++static void idetape_kfree_stage(idetape_tape_t *tape, idetape_stage_t *stage)
  {
--	struct list_head  *item;
--	struct i2c_client *client;
-+	struct i2c_cmd_arg	cmd_arg;
- 
--	mutex_lock(&adap->clist_lock);
--	list_for_each(item,&adap->clients) {
--		client = list_entry(item, struct i2c_client, list);
--		if (!try_module_get(client->driver->driver.owner))
--			continue;
--		if (NULL != client->driver->command) {
--			mutex_unlock(&adap->clist_lock);
--			client->driver->command(client,cmd,arg);
--			mutex_lock(&adap->clist_lock);
--		}
--		module_put(client->driver->driver.owner);
--       }
--       mutex_unlock(&adap->clist_lock);
-+	cmd_arg.cmd = cmd;
-+	cmd_arg.arg = arg;
-+	device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd);
+ 	__idetape_kfree_stage(stage);
  }
- EXPORT_SYMBOL(i2c_clients_command);
  
-@@ -848,11 +885,24 @@ static int __init i2c_init(void)
- 	retval = bus_register(&i2c_bus_type);
- 	if (retval)
- 		return retval;
--	return class_register(&i2c_adapter_class);
-+	retval = class_register(&i2c_adapter_class);
-+	if (retval)
-+		goto bus_err;
-+	retval = i2c_add_driver(&dummy_driver);
-+	if (retval)
-+		goto class_err;
-+	return 0;
+ /*
+- *	idetape_remove_stage_head removes tape->first_stage from the pipeline.
+- *	The caller should avoid race conditions.
++ * Remove tape->first_stage from the pipeline. The caller should avoid race
++ * conditions.
+  */
+-static void idetape_remove_stage_head (ide_drive_t *drive)
++static void idetape_remove_stage_head(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_stage_t *stage;
+-	
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n");
+-#endif /* IDETAPE_DEBUG_LOG */
+-#if IDETAPE_DEBUG_BUGS
 +
-+class_err:
-+	class_unregister(&i2c_adapter_class);
-+bus_err:
-+	bus_unregister(&i2c_bus_type);
-+	return retval;
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
++
+ 	if (tape->first_stage == NULL) {
+ 		printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
+-		return;		
++		return;
+ 	}
+ 	if (tape->active_stage == tape->first_stage) {
+-		printk(KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n");
++		printk(KERN_ERR "ide-tape: bug: Trying to free our active "
++				"pipeline stage\n");
+ 		return;
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 	stage = tape->first_stage;
+ 	tape->first_stage = stage->next;
+ 	idetape_kfree_stage(tape, stage);
+ 	tape->nr_stages--;
+ 	if (tape->first_stage == NULL) {
+ 		tape->last_stage = NULL;
+-#if IDETAPE_DEBUG_BUGS
+ 		if (tape->next_stage != NULL)
+-			printk(KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n");
++			printk(KERN_ERR "ide-tape: bug: tape->next_stage !="
++					" NULL\n");
+ 		if (tape->nr_stages)
+-			printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n");
+-#endif /* IDETAPE_DEBUG_BUGS */
++			printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 "
++					"now\n");
+ 	}
  }
  
- static void __exit i2c_exit(void)
- {
-+	i2c_del_driver(&dummy_driver);
- 	class_unregister(&i2c_adapter_class);
- 	bus_unregister(&i2c_bus_type);
- }
-@@ -879,7 +929,15 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
- 		}
- #endif
+@@ -1656,10 +821,8 @@ static void idetape_abort_pipeline(ide_drive_t *drive,
+ 	idetape_stage_t *stage = new_last_stage->next;
+ 	idetape_stage_t *nstage;
  
--		mutex_lock_nested(&adap->bus_lock, adap->level);
-+		if (in_atomic() || irqs_disabled()) {
-+			ret = mutex_trylock(&adap->bus_lock);
-+			if (!ret)
-+				/* I2C activity is ongoing. */
-+				return -EAGAIN;
-+		} else {
-+			mutex_lock_nested(&adap->bus_lock, adap->level);
-+		}
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: %s: idetape_abort_pipeline called\n", tape->name);
+-#endif
++	debug_log(DBG_PROCS, "%s: Enter %s\n", tape->name, __func__);
 +
- 		ret = adap->algo->master_xfer(adap,msgs,num);
- 		mutex_unlock(&adap->bus_lock);
- 
-@@ -978,7 +1036,7 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
+ 	while (stage) {
+ 		nstage = stage->next;
+ 		idetape_kfree_stage(tape, stage);
+@@ -1674,8 +837,8 @@ static void idetape_abort_pipeline(ide_drive_t *drive,
  }
  
- int i2c_probe(struct i2c_adapter *adapter,
--	      struct i2c_client_address_data *address_data,
-+	      const struct i2c_client_address_data *address_data,
- 	      int (*found_proc) (struct i2c_adapter *, int, int))
+ /*
+- *	idetape_end_request is used to finish servicing a request, and to
+- *	insert a pending pipeline request into the main device queue.
++ * Finish servicing a request and insert a pending pipeline request into the
++ * main device queue.
+  */
+ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
  {
- 	int i, err;
-@@ -987,7 +1045,7 @@ int i2c_probe(struct i2c_adapter *adapter,
- 	/* Force entries are done first, and are not affected by ignore
- 	   entries */
- 	if (address_data->forces) {
--		unsigned short **forces = address_data->forces;
-+		const unsigned short * const *forces = address_data->forces;
- 		int kind;
+@@ -1686,34 +849,37 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ 	int remove_stage = 0;
+ 	idetape_stage_t *active_stage;
  
- 		for (kind = 0; forces[kind]; kind++) {
-@@ -1085,7 +1143,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
- 		return NULL;
+-#if IDETAPE_DEBUG_LOG
+-        if (tape->debug_level >= 4)
+-	printk(KERN_INFO "ide-tape: Reached idetape_end_request\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ 
+ 	switch (uptodate) {
+-		case 0:	error = IDETAPE_ERROR_GENERAL; break;
+-		case 1: error = 0; break;
+-		default: error = uptodate;
++	case 0:	error = IDETAPE_ERROR_GENERAL; break;
++	case 1: error = 0; break;
++	default: error = uptodate;
  	}
+ 	rq->errors = error;
+ 	if (error)
+ 		tape->failed_pc = NULL;
  
--	mutex_lock(&adap->clist_lock);
- 	for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
- 		/* Check address validity */
- 		if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
-@@ -1095,7 +1152,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,
- 		}
+-	spin_lock_irqsave(&tape->spinlock, flags);
++	if (!blk_special_request(rq)) {
++		ide_end_request(drive, uptodate, nr_sects);
++		return 0;
++	}
++
++	spin_lock_irqsave(&tape->lock, flags);
  
- 		/* Check address availability */
--		if (__i2c_check_addr(adap, addr_list[i])) {
-+		if (i2c_check_addr(adap, addr_list[i])) {
- 			dev_dbg(&adap->dev, "Address 0x%02x already in "
- 				"use, not probing\n", addr_list[i]);
- 			continue;
-@@ -1123,7 +1180,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
- 				break;
+ 	/* The request was a pipelined data transfer request */
+-	if (tape->active_data_request == rq) {
++	if (tape->active_data_rq == rq) {
+ 		active_stage = tape->active_stage;
+ 		tape->active_stage = NULL;
+-		tape->active_data_request = NULL;
++		tape->active_data_rq = NULL;
+ 		tape->nr_pending_stages--;
+ 		if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+ 			remove_stage = 1;
+ 			if (error) {
+ 				set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+ 				if (error == IDETAPE_ERROR_EOD)
+-					idetape_abort_pipeline(drive, active_stage);
++					idetape_abort_pipeline(drive,
++								active_stage);
+ 			}
+ 		} else if (rq->cmd[0] & REQ_IDETAPE_READ) {
+ 			if (error == IDETAPE_ERROR_EOD) {
+@@ -1722,51 +888,60 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
+ 			}
  		}
- 	}
--	mutex_unlock(&adap->clist_lock);
+ 		if (tape->next_stage != NULL) {
+-			idetape_active_next_stage(drive);
++			idetape_activate_next_stage(drive);
  
- 	if (addr_list[i] == I2C_CLIENT_END) {
- 		dev_dbg(&adap->dev, "Probing failed, no device found\n");
-@@ -1139,12 +1195,12 @@ struct i2c_adapter* i2c_get_adapter(int id)
- {
- 	struct i2c_adapter *adapter;
++			/* Insert the next request into the request queue. */
++			(void)ide_do_drive_cmd(drive, tape->active_data_rq,
++						ide_end);
++		} else if (!error) {
+ 			/*
+-			 * Insert the next request into the request queue.
++			 * This is a part of the feedback loop which tries to
++			 * find the optimum number of stages. We are starting
++			 * from a minimum maximum number of stages, and if we
++			 * sense that the pipeline is empty, we try to increase
++			 * it, until we reach the user compile time memory
++			 * limit.
+ 			 */
+-			(void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
+-		} else if (!error) {
+-				idetape_increase_max_pipeline_stages(drive);
++			int i = (tape->max_pipeline - tape->min_pipeline) / 10;
++
++			tape->max_stages += max(i, 1);
++			tape->max_stages = max(tape->max_stages,
++						tape->min_pipeline);
++			tape->max_stages = min(tape->max_stages,
++						tape->max_pipeline);
+ 		}
+ 	}
+ 	ide_end_drive_cmd(drive, 0, 0);
+-//	blkdev_dequeue_request(rq);
+-//	drive->rq = NULL;
+-//	end_that_request_last(rq);
  
--	mutex_lock(&core_lists);
-+	mutex_lock(&core_lock);
- 	adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
- 	if (adapter && !try_module_get(adapter->owner))
- 		adapter = NULL;
+ 	if (remove_stage)
+ 		idetape_remove_stage_head(drive);
+-	if (tape->active_data_request == NULL)
++	if (tape->active_data_rq == NULL)
+ 		clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
+-	spin_unlock_irqrestore(&tape->spinlock, flags);
++	spin_unlock_irqrestore(&tape->lock, flags);
+ 	return 0;
+ }
  
--	mutex_unlock(&core_lists);
-+	mutex_unlock(&core_lock);
- 	return adapter;
+-static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
++static ide_startstop_t idetape_request_sense_callback(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
++
+ 	if (!tape->pc->error) {
+-		idetape_analyze_error(drive, (idetape_request_sense_result_t *) tape->pc->buffer);
++		idetape_analyze_error(drive, tape->pc->buffer);
+ 		idetape_end_request(drive, 1, 0);
+ 	} else {
+-		printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n");
++		printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - "
++				"Aborting request!\n");
+ 		idetape_end_request(drive, 0, 0);
+ 	}
+ 	return ide_stopped;
  }
- EXPORT_SYMBOL(i2c_get_adapter);
-diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
-index df540d5..393e679 100644
---- a/drivers/i2c/i2c-dev.c
-+++ b/drivers/i2c/i2c-dev.c
-@@ -182,27 +182,22 @@ static ssize_t i2cdev_write (struct file *file, const char __user *buf, size_t c
- 	return ret;
+ 
+-static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
++static void idetape_create_request_sense_cmd(idetape_pc_t *pc)
+ {
+-	idetape_init_pc(pc);	
+-	pc->c[0] = IDETAPE_REQUEST_SENSE_CMD;
++	idetape_init_pc(pc);
++	pc->c[0] = REQUEST_SENSE;
+ 	pc->c[4] = 20;
+ 	pc->request_transfer = 20;
+ 	pc->callback = &idetape_request_sense_callback;
+@@ -1780,25 +955,22 @@ static void idetape_init_rq(struct request *rq, u8 cmd)
  }
  
-+static int i2cdev_check(struct device *dev, void *addrp)
-+{
-+	struct i2c_client *client = i2c_verify_client(dev);
-+
-+	if (!client || client->addr != *(unsigned int *)addrp)
-+		return 0;
-+
-+	return dev->driver ? -EBUSY : 0;
-+}
-+
- /* This address checking function differs from the one in i2c-core
-    in that it considers an address with a registered device, but no
--   bound driver, as NOT busy. */
-+   driver bound to it, as NOT busy. */
- static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr)
+ /*
+- *	idetape_queue_pc_head generates a new packet command request in front
+- *	of the request queue, before the current request, so that it will be
+- *	processed immediately, on the next pass through the driver.
++ * Generate a new packet command request in front of the request queue, before
++ * the current request, so that it will be processed immediately, on the next
++ * pass through the driver. The function below is called from the request
++ * handling part of the driver (the "bottom" part). Safe storage for the request
++ * should be allocated with ide_tape_next_{pc,rq}_storage() prior to that.
+  *
+- *	idetape_queue_pc_head is called from the request handling part of
+- *	the driver (the "bottom" part). Safe storage for the request should
+- *	be allocated with idetape_next_pc_storage and idetape_next_rq_storage
+- *	before calling idetape_queue_pc_head.
++ * Memory for those requests is pre-allocated at initialization time, and is
++ * limited to IDETAPE_PC_STACK requests. We assume that we have enough space for
++ * the maximum possible number of inter-dependent packet commands.
+  *
+- *	Memory for those requests is pre-allocated at initialization time, and
+- *	is limited to IDETAPE_PC_STACK requests. We assume that we have enough
+- *	space for the maximum possible number of inter-dependent packet commands.
+- *
+- *	The higher level of the driver - The ioctl handler and the character
+- *	device handling functions should queue request to the lower level part
+- *	and wait for their completion using idetape_queue_pc_tail or
+- *	idetape_queue_rw_tail.
++ * The higher level of the driver - The ioctl handler and the character device
++ * handling functions should queue request to the lower level part and wait for
++ * their completion using idetape_queue_pc_tail or idetape_queue_rw_tail.
+  */
+-static void idetape_queue_pc_head (ide_drive_t *drive, idetape_pc_t *pc,struct request *rq)
++static void idetape_queue_pc_head(ide_drive_t *drive, idetape_pc_t *pc,
++				  struct request *rq)
  {
--	struct list_head *item;
--	struct i2c_client *client;
--	int res = 0;
--
--	mutex_lock(&adapter->clist_lock);
--	list_for_each(item, &adapter->clients) {
--		client = list_entry(item, struct i2c_client, list);
--		if (client->addr == addr) {
--			if (client->driver)
--				res = -EBUSY;
--			break;
--		}
--	}
--	mutex_unlock(&adapter->clist_lock);
--
--	return res;
-+	return device_for_each_child(&adapter->dev, &addr, i2cdev_check);
+ 	struct ide_tape_obj *tape = drive->driver_data;
+ 
+@@ -1818,9 +990,8 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t *pc;
+ 	struct request *rq;
+-	atapi_error_t error;
+ 
+-	error.all = HWIF(drive)->INB(IDE_ERROR_REG);
++	(void)ide_read_error(drive);
+ 	pc = idetape_next_pc_storage(drive);
+ 	rq = idetape_next_rq_storage(drive);
+ 	idetape_create_request_sense_cmd(pc);
+@@ -1830,55 +1001,49 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
  }
  
- static int i2cdev_ioctl(struct inode *inode, struct file *file,
-diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
-index fb06555..45b26ed 100644
---- a/drivers/ide/Kconfig
-+++ b/drivers/ide/Kconfig
-@@ -206,9 +206,17 @@ config BLK_DEV_IDECD
- 	  To compile this driver as a module, choose M here: the
- 	  module will be called ide-cd.
+ /*
+- *	idetape_postpone_request postpones the current request so that
+- *	ide.c will be able to service requests from another device on
+- *	the same hwgroup while we are polling for DSC.
++ * Postpone the current request so that ide.c will be able to service requests
++ * from another device on the same hwgroup while we are polling for DSC.
+  */
+-static void idetape_postpone_request (ide_drive_t *drive)
++static void idetape_postpone_request(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
-+config BLK_DEV_IDECD_VERBOSE_ERRORS
-+	bool "Verbose error logging for IDE/ATAPI CDROM driver" if EMBEDDED
-+	depends on BLK_DEV_IDECD
-+	default y
-+	help
-+	  Turn this on to have the driver print out the meanings of the
-+	  ATAPI error codes.  This will use up additional 8kB of kernel-space
-+	  memory, though.
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: idetape_postpone_request\n");
+-#endif
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
 +
- config BLK_DEV_IDETAPE
--	tristate "Include IDE/ATAPI TAPE support (EXPERIMENTAL)"
--	depends on EXPERIMENTAL
-+	tristate "Include IDE/ATAPI TAPE support"
- 	help
- 	  If you have an IDE tape drive using the ATAPI protocol, say Y.
- 	  ATAPI is a newer protocol used by IDE tape and CD-ROM drives,
-@@ -325,7 +333,7 @@ config BLK_DEV_PLATFORM
- 	  If unsure, say N.
- 
- config BLK_DEV_CMD640
--	bool "CMD640 chipset bugfix/support"
-+	tristate "CMD640 chipset bugfix/support"
- 	depends on X86
- 	---help---
- 	  The CMD-Technologies CMD640 IDE chip is used on many common 486 and
-@@ -359,9 +367,8 @@ config BLK_DEV_CMD640_ENHANCED
- 	  Otherwise say N.
+ 	tape->postponed_rq = HWGROUP(drive)->rq;
+-	ide_stall_queue(drive, tape->dsc_polling_frequency);
++	ide_stall_queue(drive, tape->dsc_poll_freq);
+ }
  
- config BLK_DEV_IDEPNP
--	bool "PNP EIDE support"
-+	tristate "PNP EIDE support"
- 	depends on PNP
--	select IDE_GENERIC
- 	help
- 	  If you have a PnP (Plug and Play) compatible EIDE card and
- 	  would like the kernel to automatically detect and activate
-@@ -374,19 +381,20 @@ comment "PCI IDE chipsets support"
- config BLK_DEV_IDEPCI
- 	bool
++typedef void idetape_io_buf(ide_drive_t *, idetape_pc_t *, unsigned int);
++
+ /*
+- *	idetape_pc_intr is the usual interrupt handler which will be called
+- *	during a packet command. We will transfer some of the data (as
+- *	requested by the drive) and will re-point interrupt handler to us.
+- *	When data transfer is finished, we will act according to the
+- *	algorithm described before idetape_issue_packet_command.
+- *
++ * This is the usual interrupt handler which will be called during a packet
++ * command. We will transfer some of the data (as requested by the drive) and
++ * will re-point interrupt handler to us. When data transfer is finished, we
++ * will act according to the algorithm described before
++ * idetape_issue_pc.
+  */
+-static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
++static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idetape_tape_t *tape = drive->driver_data;
+-	atapi_status_t status;
+-	atapi_bcount_t bcount;
+-	atapi_ireason_t ireason;
+ 	idetape_pc_t *pc = tape->pc;
+-
++	xfer_func_t *xferfunc;
++	idetape_io_buf *iobuf;
+ 	unsigned int temp;
+ #if SIMULATE_ERRORS
+-	static int error_sim_count = 0;
++	static int error_sim_count;
+ #endif
++	u16 bcount;
++	u8 stat, ireason;
  
--config IDEPCI_SHARE_IRQ
--	bool "Sharing PCI IDE interrupts support"
--	depends on BLK_DEV_IDEPCI
-+config IDEPCI_PCIBUS_ORDER
-+	bool "Probe IDE PCI devices in the PCI bus order (DEPRECATED)"
-+	depends on BLK_DEV_IDE=y && BLK_DEV_IDEPCI
-+	default y
- 	help
--	  Some ATA/IDE chipsets have hardware support which allows for
--	  sharing a single IRQ with other cards. To enable support for
--	  this in the ATA/IDE driver, say Y here.
-+	  Probe IDE PCI devices in the order in which they appear on the
-+	  PCI bus (i.e. 00:1f.1 PCI device before 02:01.0 PCI device)
-+	  instead of the order in which IDE PCI host drivers are loaded.
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_pc_intr "
+-				"interrupt handler\n");
+-#endif /* IDETAPE_DEBUG_LOG */	
++	debug_log(DBG_PROCS, "Enter %s - interrupt handler\n", __func__);
  
--	  It is safe to say Y to this question, in most cases.
--	  If unsure, say N.
-+	  Please note that this method of assuring stable naming of
-+	  IDE devices is unreliable and use other means for achieving
-+	  it (i.e. udev).
+ 	/* Clear the interrupt */
+-	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
++	stat = ide_read_status(drive);
  
--config IDEPCI_PCIBUS_ORDER
--	def_bool BLK_DEV_IDE=y && BLK_DEV_IDEPCI
-+	  If in doubt, say N.
+ 	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
+-		if (HWIF(drive)->ide_dma_end(drive) || status.b.check) {
++		if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
+ 			/*
+ 			 * A DMA error is sometimes expected. For example,
+ 			 * if the tape is crossing a filemark during a
+@@ -1905,56 +1070,49 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
+ 			pc->actually_transferred = pc->request_transfer;
+ 			idetape_update_buffers(pc);
+ 		}
+-#if IDETAPE_DEBUG_LOG
+-		if (tape->debug_level >= 4)
+-			printk(KERN_INFO "ide-tape: DMA finished\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++		debug_log(DBG_PROCS, "DMA finished\n");
++
+ 	}
  
- # TODO: split it on per host driver config options (or module parameters)
- config BLK_DEV_OFFBOARD
-@@ -617,8 +625,8 @@ config BLK_DEV_SC1200
- 	tristate "National SCx200 chipset support"
- 	select BLK_DEV_IDEDMA_PCI
- 	help
--	  This driver adds support for the built in IDE on the National
--	  SCx200 series of embedded x86 "Geode" systems
-+	  This driver adds support for the on-board IDE controller on the
-+	  National SCx200 series of embedded x86 "Geode" systems.
+ 	/* No more interrupts */
+-	if (!status.b.drq) {
+-#if IDETAPE_DEBUG_LOG
+-		if (tape->debug_level >= 2)
+-			printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
+-#endif /* IDETAPE_DEBUG_LOG */
+-		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
++	if ((stat & DRQ_STAT) == 0) {
++		debug_log(DBG_SENSE, "Packet command completed, %d bytes"
++				" transferred\n", pc->actually_transferred);
  
- config BLK_DEV_PIIX
- 	tristate "Intel PIIXn chipsets support"
-@@ -707,7 +715,6 @@ config BLK_DEV_SVWKS
- config BLK_DEV_SGIIOC4
- 	tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
- 	depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
--	select IDEPCI_SHARE_IRQ
- 	select BLK_DEV_IDEDMA_PCI
- 	help
- 	  This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
-@@ -794,22 +801,22 @@ config BLK_DEV_CELLEB
- 	depends on PPC_CELLEB
- 	select BLK_DEV_IDEDMA_PCI
- 	help
--	  This driver provides support for the built-in IDE controller on
-+	  This driver provides support for the on-board IDE controller on
- 	  Toshiba Cell Reference Board.
- 	  If unsure, say Y.
++		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+ 		local_irq_enable();
  
- endif
+ #if SIMULATE_ERRORS
+-		if ((pc->c[0] == IDETAPE_WRITE_CMD ||
+-		     pc->c[0] == IDETAPE_READ_CMD) &&
++		if ((pc->c[0] == WRITE_6 || pc->c[0] == READ_6) &&
+ 		    (++error_sim_count % 100) == 0) {
+ 			printk(KERN_INFO "ide-tape: %s: simulating error\n",
+ 				tape->name);
+-			status.b.check = 1;
++			stat |= ERR_STAT;
+ 		}
+ #endif
+-		if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
+-			status.b.check = 0;
+-		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {	/* Error detected */
+-#if IDETAPE_DEBUG_LOG
+-			if (tape->debug_level >= 1)
+-				printk(KERN_INFO "ide-tape: %s: I/O error\n",
+-					tape->name);
+-#endif /* IDETAPE_DEBUG_LOG */
+-			if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
+-				printk(KERN_ERR "ide-tape: I/O error in request sense command\n");
++		if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
++			stat &= ~ERR_STAT;
++		if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
++			/* Error detected */
++			debug_log(DBG_ERR, "%s: I/O error\n", tape->name);
++
++			if (pc->c[0] == REQUEST_SENSE) {
++				printk(KERN_ERR "ide-tape: I/O error in request"
++						" sense command\n");
+ 				return ide_do_reset(drive);
+ 			}
+-#if IDETAPE_DEBUG_LOG
+-			if (tape->debug_level >= 1)
+-				printk(KERN_INFO "ide-tape: [cmd %x]: check condition\n", pc->c[0]);
+-#endif
++			debug_log(DBG_ERR, "[cmd %x]: check condition\n",
++					pc->c[0]);
++
+ 			/* Retry operation */
+ 			return idetape_retry_pc(drive);
+ 		}
+ 		pc->error = 0;
+ 		if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
+-		    !status.b.dsc) {
++		    (stat & SEEK_STAT) == 0) {
+ 			/* Media access command */
+ 			tape->dsc_polling_start = jiffies;
+-			tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
++			tape->dsc_poll_freq = IDETAPE_DSC_MA_FAST;
+ 			tape->dsc_timeout = jiffies + IDETAPE_DSC_MA_TIMEOUT;
+ 			/* Allow ide.c to handle other requests */
+ 			idetape_postpone_request(drive);
+@@ -1973,133 +1131,127 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
+ 		return ide_do_reset(drive);
+ 	}
+ 	/* Get the number of bytes to transfer on this interrupt. */
+-	bcount.b.high = hwif->INB(IDE_BCOUNTH_REG);
+-	bcount.b.low = hwif->INB(IDE_BCOUNTL_REG);
++	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
++		  hwif->INB(IDE_BCOUNTL_REG);
  
- config BLK_DEV_IDE_PMAC
--	bool "Builtin PowerMac IDE support"
-+	tristate "PowerMac on-board IDE support"
- 	depends on PPC_PMAC && IDE=y && BLK_DEV_IDE=y
- 	help
--	  This driver provides support for the built-in IDE controller on
-+	  This driver provides support for the on-board IDE controller on
- 	  most of the recent Apple Power Macintoshes and PowerBooks.
- 	  If unsure, say Y.
+-	ireason.all = hwif->INB(IDE_IREASON_REG);
++	ireason = hwif->INB(IDE_IREASON_REG);
  
- config BLK_DEV_IDE_PMAC_ATA100FIRST
--	bool "Probe internal ATA/100 (Kauai) first"
-+	bool "Probe on-board ATA/100 (Kauai) first"
- 	depends on BLK_DEV_IDE_PMAC
- 	help
- 	  This option will cause the ATA/100 controller found in UniNorth2
-@@ -824,7 +831,7 @@ config BLK_DEV_IDEDMA_PMAC
- 	depends on BLK_DEV_IDE_PMAC
- 	select BLK_DEV_IDEDMA_PCI
- 	help
--	  This option allows the driver for the built-in IDE controller on
-+	  This option allows the driver for the on-board IDE controller on
- 	  Power Macintoshes and PowerBooks to use DMA (direct memory access)
- 	  to transfer data to and from memory.  Saying Y is safe and improves
- 	  performance.
-@@ -855,8 +862,9 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
-        depends on BLK_DEV_IDE_AU1XXX
+-	if (ireason.b.cod) {
+-		printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
++	if (ireason & CD) {
++		printk(KERN_ERR "ide-tape: CoD != 0 in %s\n", __func__);
+ 		return ide_do_reset(drive);
+ 	}
+-	if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
++	if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
+ 		/* Hopefully, we will never get here */
+ 		printk(KERN_ERR "ide-tape: We wanted to %s, ",
+-			ireason.b.io ? "Write":"Read");
++				(ireason & IO) ? "Write" : "Read");
+ 		printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
+-			ireason.b.io ? "Read":"Write");
++				(ireason & IO) ? "Read" : "Write");
+ 		return ide_do_reset(drive);
+ 	}
+ 	if (!test_bit(PC_WRITING, &pc->flags)) {
+ 		/* Reading - Check that we have enough space */
+-		temp = pc->actually_transferred + bcount.all;
++		temp = pc->actually_transferred + bcount;
+ 		if (temp > pc->request_transfer) {
+ 			if (temp > pc->buffer_size) {
+-				printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
+-				idetape_discard_data(drive, bcount.all);
+-				ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
++				printk(KERN_ERR "ide-tape: The tape wants to "
++					"send us more data than expected "
++					"- discarding data\n");
++				idetape_discard_data(drive, bcount);
++				ide_set_handler(drive, &idetape_pc_intr,
++						IDETAPE_WAIT_CMD, NULL);
+ 				return ide_started;
+ 			}
+-#if IDETAPE_DEBUG_LOG
+-			if (tape->debug_level >= 2)
+-				printk(KERN_NOTICE "ide-tape: The tape wants to send us more data than expected - allowing transfer\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++			debug_log(DBG_SENSE, "The tape wants to send us more "
++				"data than expected - allowing transfer\n");
+ 		}
+-	}
+-	if (test_bit(PC_WRITING, &pc->flags)) {
+-		if (pc->bh != NULL)
+-			idetape_output_buffers(drive, pc, bcount.all);
+-		else
+-			/* Write the current buffer */
+-			HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
++		iobuf = &idetape_input_buffers;
++		xferfunc = hwif->atapi_input_bytes;
+ 	} else {
+-		if (pc->bh != NULL)
+-			idetape_input_buffers(drive, pc, bcount.all);
+-		else
+-			/* Read the current buffer */
+-			HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
++		iobuf = &idetape_output_buffers;
++		xferfunc = hwif->atapi_output_bytes;
+ 	}
++
++	if (pc->bh)
++		iobuf(drive, pc, bcount);
++	else
++		xferfunc(drive, pc->current_position, bcount);
++
+ 	/* Update the current position */
+-	pc->actually_transferred += bcount.all;
+-	pc->current_position += bcount.all;
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 2)
+-		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
+-#endif
++	pc->actually_transferred += bcount;
++	pc->current_position += bcount;
++
++	debug_log(DBG_SENSE, "[cmd %x] transferred %d bytes on that intr.\n",
++			pc->c[0], bcount);
++
+ 	/* And set the interrupt handler again */
+ 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
+ 	return ide_started;
+ }
  
- config IDE_ARM
--	def_bool ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
--	select IDE_GENERIC
-+	tristate "ARM IDE support"
-+	depends on ARM && (ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
-+	default y
+ /*
+- *	Packet Command Interface
++ * Packet Command Interface
+  *
+- *	The current Packet Command is available in tape->pc, and will not
+- *	change until we finish handling it. Each packet command is associated
+- *	with a callback function that will be called when the command is
+- *	finished.
++ * The current Packet Command is available in tape->pc, and will not change
++ * until we finish handling it. Each packet command is associated with a
++ * callback function that will be called when the command is finished.
+  *
+- *	The handling will be done in three stages:
++ * The handling will be done in three stages:
+  *
+- *	1.	idetape_issue_packet_command will send the packet command to the
+- *		drive, and will set the interrupt handler to idetape_pc_intr.
++ * 1. idetape_issue_pc will send the packet command to the drive, and will set
++ * the interrupt handler to idetape_pc_intr.
+  *
+- *	2.	On each interrupt, idetape_pc_intr will be called. This step
+- *		will be repeated until the device signals us that no more
+- *		interrupts will be issued.
++ * 2. On each interrupt, idetape_pc_intr will be called. This step will be
++ * repeated until the device signals us that no more interrupts will be issued.
+  *
+- *	3.	ATAPI Tape media access commands have immediate status with a
+- *		delayed process. In case of a successful initiation of a
+- *		media access packet command, the DSC bit will be set when the
+- *		actual execution of the command is finished. 
+- *		Since the tape drive will not issue an interrupt, we have to
+- *		poll for this event. In this case, we define the request as
+- *		"low priority request" by setting rq_status to
+- *		IDETAPE_RQ_POSTPONED, 	set a timer to poll for DSC and exit
+- *		the driver.
++ * 3. ATAPI Tape media access commands have immediate status with a delayed
++ * process. In case of a successful initiation of a media access packet command,
++ * the DSC bit will be set when the actual execution of the command is finished.
++ * Since the tape drive will not issue an interrupt, we have to poll for this
++ * event. In this case, we define the request as "low priority request" by
++ * setting rq_status to IDETAPE_RQ_POSTPONED, set a timer to poll for DSC and
++ * exit the driver.
+  *
+- *		ide.c will then give higher priority to requests which
+- *		originate from the other device, until will change rq_status
+- *		to RQ_ACTIVE.
++ * ide.c will then give higher priority to requests which originate from the
++ * other device, until will change rq_status to RQ_ACTIVE.
+  *
+- *	4.	When the packet command is finished, it will be checked for errors.
++ * 4. When the packet command is finished, it will be checked for errors.
+  *
+- *	5.	In case an error was found, we queue a request sense packet
+- *		command in front of the request queue and retry the operation
+- *		up to IDETAPE_MAX_PC_RETRIES times.
+- *
+- *	6.	In case no error was found, or we decided to give up and not
+- *		to retry again, the callback function will be called and then
+- *		we will handle the next request.
++ * 5. In case an error was found, we queue a request sense packet command in
++ * front of the request queue and retry the operation up to
++ * IDETAPE_MAX_PC_RETRIES times.
+  *
++ * 6. In case no error was found, or we decided to give up and not to retry
++ * again, the callback function will be called and then we will handle the next
++ * request.
+  */
+ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t *pc = tape->pc;
+-	atapi_ireason_t ireason;
+ 	int retries = 100;
+ 	ide_startstop_t startstop;
++	u8 ireason;
  
- config BLK_DEV_IDE_ICSIDE
- 	tristate "ICS IDE interface support"
-@@ -888,10 +896,9 @@ config BLK_DEV_IDE_BAST
- 	  Simtec BAST or the Thorcom VR1000
+-	if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
+-		printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
++	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
++		printk(KERN_ERR "ide-tape: Strange, packet command initiated "
++				"yet DRQ isn't asserted\n");
+ 		return startstop;
+ 	}
+-	ireason.all = hwif->INB(IDE_IREASON_REG);
+-	while (retries-- && (!ireason.b.cod || ireason.b.io)) {
++	ireason = hwif->INB(IDE_IREASON_REG);
++	while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
+ 		printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
+ 				"a packet command, retrying\n");
+ 		udelay(100);
+-		ireason.all = hwif->INB(IDE_IREASON_REG);
++		ireason = hwif->INB(IDE_IREASON_REG);
+ 		if (retries == 0) {
+ 			printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
+ 					"issuing a packet command, ignoring\n");
+-			ireason.b.cod = 1;
+-			ireason.b.io = 0;
++			ireason |= CD;
++			ireason &= ~IO;
+ 		}
+ 	}
+-	if (!ireason.b.cod || ireason.b.io) {
++	if ((ireason & CD) == 0 || (ireason & IO)) {
+ 		printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing "
+ 				"a packet command\n");
+ 		return ide_do_reset(drive);
+@@ -2116,22 +1268,20 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
+ 	return ide_started;
+ }
  
- config ETRAX_IDE
--	bool "ETRAX IDE support"
-+	tristate "ETRAX IDE support"
- 	depends on CRIS && BROKEN
- 	select BLK_DEV_IDEDMA
--	select IDE_GENERIC
- 	help
- 	  Enables the ETRAX IDE driver.
+-static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape_pc_t *pc)
++static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, idetape_pc_t *pc)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	idetape_tape_t *tape = drive->driver_data;
+-	atapi_bcount_t bcount;
+ 	int dma_ok = 0;
++	u16 bcount;
  
-@@ -923,21 +930,19 @@ config ETRAX_IDE_G27_RESET
- endchoice
+-#if IDETAPE_DEBUG_BUGS
+-	if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD &&
+-	    pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
++	if (tape->pc->c[0] == REQUEST_SENSE &&
++	    pc->c[0] == REQUEST_SENSE) {
+ 		printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
+ 			"Two request sense in serial were issued\n");
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */
  
- config IDE_H8300
--	bool "H8300 IDE support"
-+	tristate "H8300 IDE support"
- 	depends on H8300
--	select IDE_GENERIC
- 	default y
- 	help
- 	  Enables the H8300 IDE driver.
+-	if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD)
++	if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
+ 		tape->failed_pc = pc;
+ 	/* Set the current packet command */
+ 	tape->pc = pc;
+@@ -2139,12 +1289,12 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
+ 	if (pc->retries > IDETAPE_MAX_PC_RETRIES ||
+ 	    test_bit(PC_ABORT, &pc->flags)) {
+ 		/*
+-		 *	We will "abort" retrying a packet command in case
+-		 *	a legitimate error code was received (crossing a
+-		 *	filemark, or end of the media, for example).
++		 * We will "abort" retrying a packet command in case legitimate
++		 * error code was received (crossing a filemark, or end of the
++		 * media, for example).
+ 		 */
+ 		if (!test_bit(PC_ABORT, &pc->flags)) {
+-			if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD &&
++			if (!(pc->c[0] == TEST_UNIT_READY &&
+ 			      tape->sense_key == 2 && tape->asc == 4 &&
+ 			     (tape->ascq == 1 || tape->ascq == 8))) {
+ 				printk(KERN_ERR "ide-tape: %s: I/O error, "
+@@ -2160,17 +1310,14 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
+ 		tape->failed_pc = NULL;
+ 		return pc->callback(drive);
+ 	}
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 2)
+-		printk(KERN_INFO "ide-tape: Retry number - %d, cmd = %02X\n", pc->retries, pc->c[0]);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]);
  
- config BLK_DEV_GAYLE
--	bool "Amiga Gayle IDE interface support"
-+	tristate "Amiga Gayle IDE interface support"
- 	depends on AMIGA
--	select IDE_GENERIC
- 	help
- 	  This is the IDE driver for the Amiga Gayle IDE interface. It supports
- 	  both the `A1200 style' and `A4000 style' of the Gayle IDE interface,
--	  This includes builtin IDE interfaces on some Amiga models (A600,
-+	  This includes on-board IDE interfaces on some Amiga models (A600,
- 	  A1200, A4000, and A4000T), and IDE interfaces on the Zorro expansion
- 	  bus (M-Tech E-Matrix 530 expansion card).
- 	  Say Y if you have an Amiga with a Gayle IDE interface and want to use
-@@ -951,10 +956,10 @@ config BLK_DEV_IDEDOUBLER
- 	depends on BLK_DEV_GAYLE && EXPERIMENTAL
- 	---help---
- 	  This driver provides support for the so-called `IDE doublers' (made
--	  by various manufacturers, e.g. Eyetech) that can be connected to the
--	  builtin IDE interface of some Amiga models. Using such an IDE
--	  doubler, you can connect up to four instead of two IDE devices on
--	  the Amiga's builtin IDE interface.
-+	  by various manufacturers, e.g. Eyetech) that can be connected to
-+	  the on-board IDE interface of some Amiga models. Using such an IDE
-+	  doubler, you can connect up to four instead of two IDE devices to
-+	  the Amiga's on-board IDE interface.
+ 	pc->retries++;
+ 	/* We haven't transferred any data yet */
+ 	pc->actually_transferred = 0;
+ 	pc->current_position = pc->buffer;
+ 	/* Request to transfer the entire buffer at once */
+-	bcount.all = pc->request_transfer;
++	bcount = pc->request_transfer;
  
- 	  Note that the normal Amiga Gayle IDE driver may not work correctly
- 	  if you have an IDE doubler and don't enable this driver!
-@@ -963,55 +968,50 @@ config BLK_DEV_IDEDOUBLER
- 	  runtime using the "ide=doubler" kernel boot parameter.
+ 	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
+ 		printk(KERN_WARNING "ide-tape: DMA disabled, "
+@@ -2180,17 +1327,14 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
+ 	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
+ 		dma_ok = !hwif->dma_setup(drive);
  
- config BLK_DEV_BUDDHA
--	bool "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
-+	tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)"
- 	depends on ZORRO && EXPERIMENTAL
--	select IDE_GENERIC
- 	help
--	  This is the IDE driver for the IDE interfaces on the Buddha, 
--	  Catweasel and X-Surf expansion boards.  It supports up to two interfaces 
--	  on the Buddha, three on the Catweasel and two on the X-Surf.
-+	  This is the IDE driver for the IDE interfaces on the Buddha, Catweasel
-+	  and X-Surf expansion boards.  It supports up to two interfaces on the
-+	  Buddha, three on the Catweasel and two on the X-Surf.
+-	if (IDE_CONTROL_REG)
+-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+-	hwif->OUTB(dma_ok ? 1 : 0, IDE_FEATURE_REG);	/* Use PIO/DMA */
+-	hwif->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
+-	hwif->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
+-	hwif->OUTB(drive->select.all, IDE_SELECT_REG);
++	ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
++			   IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
++
+ 	if (dma_ok)			/* Will begin DMA later */
+ 		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
+ 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
+-		ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
+-		hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
++		ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
++				    IDETAPE_WAIT_CMD, NULL);
+ 		return ide_started;
+ 	} else {
+ 		hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
+@@ -2198,31 +1342,24 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
+ 	}
+ }
  
- 	  Say Y if you have a Buddha or Catweasel expansion board and want to
- 	  use IDE devices (hard disks, CD-ROM drives, etc.) that are connected
- 	  to one of its IDE interfaces.
+-/*
+- *	General packet command callback function.
+- */
+-static ide_startstop_t idetape_pc_callback (ide_drive_t *drive)
++static ide_startstop_t idetape_pc_callback(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_pc_callback\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
  
- config BLK_DEV_FALCON_IDE
--	bool "Falcon IDE interface support"
-+	tristate "Falcon IDE interface support"
- 	depends on ATARI
--	select IDE_GENERIC
- 	help
--	  This is the IDE driver for the builtin IDE interface on the Atari
-+	  This is the IDE driver for the on-board IDE interface on the Atari
- 	  Falcon. Say Y if you have a Falcon and want to use IDE devices (hard
--	  disks, CD-ROM drives, etc.) that are connected to the builtin IDE
-+	  disks, CD-ROM drives, etc.) that are connected to the on-board IDE
- 	  interface.
+ 	idetape_end_request(drive, tape->pc->error ? 0 : 1, 0);
+ 	return ide_stopped;
+ }
  
- config BLK_DEV_MAC_IDE
--	bool "Macintosh Quadra/Powerbook IDE interface support"
-+	tristate "Macintosh Quadra/Powerbook IDE interface support"
- 	depends on MAC
--	select IDE_GENERIC
- 	help
--	  This is the IDE driver for the builtin IDE interface on some m68k
-+	  This is the IDE driver for the on-board IDE interface on some m68k
- 	  Macintosh models. It supports both the `Quadra style' (used in
- 	  Quadra/ Centris 630 and Performa 588 models) and `Powerbook style'
- 	  (used in the Powerbook 150 and 190 models) IDE interface.
+-/*
+- *	A mode sense command is used to "sense" tape parameters.
+- */
+-static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code)
++/* A mode sense command is used to "sense" tape parameters. */
++static void idetape_create_mode_sense_cmd(idetape_pc_t *pc, u8 page_code)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_MODE_SENSE_CMD;
++	pc->c[0] = MODE_SENSE;
+ 	if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
+-		pc->c[1] = 8;	/* DBD = 1 - Don't return block descriptors */
++		/* DBD = 1 - Don't return block descriptors */
++		pc->c[1] = 8;
+ 	pc->c[2] = page_code;
+ 	/*
+ 	 * Changed pc->c[3] to 0 (255 will at best return unused info).
+@@ -2232,7 +1369,8 @@ static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code)
+ 	 * and return an error when 255 is used.
+ 	 */
+ 	pc->c[3] = 0;
+-	pc->c[4] = 255;		/* (We will just discard data in that case) */
++	/* We will just discard data in that case */
++	pc->c[4] = 255;
+ 	if (page_code == IDETAPE_BLOCK_DESCRIPTOR)
+ 		pc->request_transfer = 12;
+ 	else if (page_code == IDETAPE_CAPABILITIES_PAGE)
+@@ -2242,66 +1380,81 @@ static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code)
+ 	pc->callback = &idetape_pc_callback;
+ }
  
- 	  Say Y if you have such an Macintosh model and want to use IDE
- 	  devices (hard disks, CD-ROM drives, etc.) that are connected to the
--	  builtin IDE interface.
-+	  on-board IDE interface.
+-static void calculate_speeds(ide_drive_t *drive)
++static void idetape_calculate_speeds(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	int full = 125, empty = 75;
  
- config BLK_DEV_Q40IDE
--	bool "Q40/Q60 IDE interface support"
-+	tristate "Q40/Q60 IDE interface support"
- 	depends on Q40
--	select IDE_GENERIC
- 	help
- 	  Enable the on-board IDE controller in the Q40/Q60.  This should
- 	  normally be on; disable it only if you are running a custom hard
- 	  drive subsystem through an expansion card.
+-	if (time_after(jiffies, tape->controlled_pipeline_head_time + 120 * HZ)) {
+-		tape->controlled_previous_pipeline_head = tape->controlled_last_pipeline_head;
+-		tape->controlled_previous_head_time = tape->controlled_pipeline_head_time;
++	if (time_after(jiffies,
++			tape->controlled_pipeline_head_time + 120 * HZ)) {
++		tape->controlled_previous_pipeline_head =
++			tape->controlled_last_pipeline_head;
++		tape->controlled_previous_head_time =
++			tape->controlled_pipeline_head_time;
+ 		tape->controlled_last_pipeline_head = tape->pipeline_head;
+ 		tape->controlled_pipeline_head_time = jiffies;
+ 	}
+ 	if (time_after(jiffies, tape->controlled_pipeline_head_time + 60 * HZ))
+-		tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_last_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_pipeline_head_time);
++		tape->controlled_pipeline_head_speed = (tape->pipeline_head -
++				tape->controlled_last_pipeline_head) * 32 * HZ /
++				(jiffies - tape->controlled_pipeline_head_time);
+ 	else if (time_after(jiffies, tape->controlled_previous_head_time))
+-		tape->controlled_pipeline_head_speed = (tape->pipeline_head - tape->controlled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->controlled_previous_head_time);
++		tape->controlled_pipeline_head_speed = (tape->pipeline_head -
++				tape->controlled_previous_pipeline_head) * 32 *
++			HZ / (jiffies - tape->controlled_previous_head_time);
+ 
+-	if (tape->nr_pending_stages < tape->max_stages /*- 1 */) {
++	if (tape->nr_pending_stages < tape->max_stages/*- 1 */) {
+ 		/* -1 for read mode error recovery */
+-		if (time_after(jiffies, tape->uncontrolled_previous_head_time + 10 * HZ)) {
++		if (time_after(jiffies, tape->uncontrolled_previous_head_time +
++					10 * HZ)) {
+ 			tape->uncontrolled_pipeline_head_time = jiffies;
+-			tape->uncontrolled_pipeline_head_speed = (tape->pipeline_head - tape->uncontrolled_previous_pipeline_head) * 32 * HZ / (jiffies - tape->uncontrolled_previous_head_time);
++			tape->uncontrolled_pipeline_head_speed =
++				(tape->pipeline_head -
++				 tape->uncontrolled_previous_pipeline_head) *
++				32 * HZ / (jiffies -
++					tape->uncontrolled_previous_head_time);
+ 		}
+ 	} else {
+ 		tape->uncontrolled_previous_head_time = jiffies;
+ 		tape->uncontrolled_previous_pipeline_head = tape->pipeline_head;
+-		if (time_after(jiffies, tape->uncontrolled_pipeline_head_time + 30 * HZ)) {
++		if (time_after(jiffies, tape->uncontrolled_pipeline_head_time +
++					30 * HZ))
+ 			tape->uncontrolled_pipeline_head_time = jiffies;
+-		}
++
+ 	}
+-	tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed, tape->controlled_pipeline_head_speed);
+-	if (tape->speed_control == 0) {
+-		tape->max_insert_speed = 5000;
+-	} else if (tape->speed_control == 1) {
++	tape->pipeline_head_speed = max(tape->uncontrolled_pipeline_head_speed,
++					tape->controlled_pipeline_head_speed);
++
++	if (tape->speed_control == 1) {
+ 		if (tape->nr_pending_stages >= tape->max_stages / 2)
+ 			tape->max_insert_speed = tape->pipeline_head_speed +
+-				(1100 - tape->pipeline_head_speed) * 2 * (tape->nr_pending_stages - tape->max_stages / 2) / tape->max_stages;
++				(1100 - tape->pipeline_head_speed) * 2 *
++				(tape->nr_pending_stages - tape->max_stages / 2)
++				/ tape->max_stages;
+ 		else
+ 			tape->max_insert_speed = 500 +
+-				(tape->pipeline_head_speed - 500) * 2 * tape->nr_pending_stages / tape->max_stages;
++				(tape->pipeline_head_speed - 500) * 2 *
++				tape->nr_pending_stages / tape->max_stages;
++
+ 		if (tape->nr_pending_stages >= tape->max_stages * 99 / 100)
+ 			tape->max_insert_speed = 5000;
+-	} else if (tape->speed_control == 2) {
+-		tape->max_insert_speed = tape->pipeline_head_speed * empty / 100 +
+-			(tape->pipeline_head_speed * full / 100 - tape->pipeline_head_speed * empty / 100) * tape->nr_pending_stages / tape->max_stages;
+ 	} else
+ 		tape->max_insert_speed = tape->speed_control;
++
+ 	tape->max_insert_speed = max(tape->max_insert_speed, 500);
+ }
  
- config BLK_DEV_MPC8xx_IDE
--	bool "MPC8xx IDE support"
-+	tristate "MPC8xx IDE support"
- 	depends on 8xx && (LWMON || IVMS8 || IVML24 || TQM8xxL) && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
--	select IDE_GENERIC
- 	help
- 	  This option provides support for IDE on Motorola MPC8xx Systems.
- 	  Please see 'Type of MPC8xx IDE interface' for details.
-@@ -1070,8 +1070,8 @@ config BLK_DEV_ALI14XX
- 	  boot parameter.  It enables support for the secondary IDE interface
- 	  of the ALI M1439/1443/1445/1487/1489 chipsets, and permits faster
- 	  I/O speeds to be set as well.  See the files
--	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c> for
--	  more info.
-+	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/ali14xx.c>
-+	  for more info.
+-static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
++static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t *pc = tape->pc;
+-	atapi_status_t status;
++	u8 stat;
++
++	stat = ide_read_status(drive);
  
- config BLK_DEV_DTC2278
- 	tristate "DTC-2278 support"
-@@ -1096,8 +1096,8 @@ config BLK_DEV_QD65XX
- 	help
- 	  This driver is enabled at runtime using the "qd65xx.probe" kernel
- 	  boot parameter.  It permits faster I/O speeds to be set.  See the
--	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c> for
--	  more info.
-+	  <file:Documentation/ide.txt> and <file:drivers/ide/legacy/qd65xx.c>
-+	  for more info.
+-	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
+-	if (status.b.dsc) {
+-		if (status.b.check) {
++	if (stat & SEEK_STAT) {
++		if (stat & ERR_STAT) {
+ 			/* Error detected */
+-			if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD)
++			if (pc->c[0] != TEST_UNIT_READY)
+ 				printk(KERN_ERR "ide-tape: %s: I/O error, ",
+ 						tape->name);
+ 			/* Retry operation */
+@@ -2317,14 +1470,14 @@ static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
+ 	return pc->callback(drive);
+ }
  
- config BLK_DEV_UMC8672
- 	tristate "UMC-8672 support"
-diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
-index b181fc6..a4a4323 100644
---- a/drivers/ide/Makefile
-+++ b/drivers/ide/Makefile
-@@ -7,48 +7,60 @@
- # Note : at this point, these files are compiled on all systems.
- # In the future, some of these should be built conditionally.
- #
--# First come modules that register themselves with the core
-+# link order is important here
+-static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
++static ide_startstop_t idetape_rw_callback(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	int blocks = tape->pc->actually_transferred / tape->tape_block_size;
++	int blocks = tape->pc->actually_transferred / tape->blk_size;
  
- EXTRA_CFLAGS				+= -Idrivers/ide
+-	tape->avg_size += blocks * tape->tape_block_size;
+-	tape->insert_size += blocks * tape->tape_block_size;
++	tape->avg_size += blocks * tape->blk_size;
++	tape->insert_size += blocks * tape->blk_size;
+ 	if (tape->insert_size > 1024 * 1024)
+ 		tape->measure_insert_time = 1;
+ 	if (tape->measure_insert_time) {
+@@ -2333,19 +1486,17 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
+ 		tape->insert_size = 0;
+ 	}
+ 	if (time_after(jiffies, tape->insert_time))
+-		tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
++		tape->insert_speed = tape->insert_size / 1024 * HZ /
++					(jiffies - tape->insert_time);
+ 	if (time_after_eq(jiffies, tape->avg_time + HZ)) {
+-		tape->avg_speed = tape->avg_size * HZ / (jiffies - tape->avg_time) / 1024;
++		tape->avg_speed = tape->avg_size * HZ /
++				(jiffies - tape->avg_time) / 1024;
+ 		tape->avg_size = 0;
+ 		tape->avg_time = jiffies;
+ 	}
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ 
+-#if IDETAPE_DEBUG_LOG	
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_rw_callback\n");
+-#endif /* IDETAPE_DEBUG_LOG */
+-
+-	tape->first_frame_position += blocks;
++	tape->first_frame += blocks;
+ 	rq->current_nr_sectors -= blocks;
  
--obj-$(CONFIG_BLK_DEV_IDE)		+= pci/
--
- ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o
+ 	if (!tape->pc->error)
+@@ -2355,28 +1506,31 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
+ 	return ide_stopped;
+ }
  
--ide-core-$(CONFIG_BLK_DEV_CMD640)	+= pci/cmd640.o
--
--# Core IDE code - must come before legacy
-+# core IDE code
- ide-core-$(CONFIG_BLK_DEV_IDEPCI)	+= setup-pci.o
- ide-core-$(CONFIG_BLK_DEV_IDEDMA)	+= ide-dma.o
- ide-core-$(CONFIG_IDE_PROC_FS)		+= ide-proc.o
--ide-core-$(CONFIG_BLK_DEV_IDEPNP)	+= ide-pnp.o
- ide-core-$(CONFIG_BLK_DEV_IDEACPI)	+= ide-acpi.o
+-static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
++static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
++		unsigned int length, struct idetape_bh *bh)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_READ_CMD;
+-	put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
++	pc->c[0] = READ_6;
++	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
+ 	pc->c[1] = 1;
+ 	pc->callback = &idetape_rw_callback;
+ 	pc->bh = bh;
+ 	atomic_set(&bh->b_count, 0);
+ 	pc->buffer = NULL;
+-	pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
++	pc->buffer_size = length * tape->blk_size;
++	pc->request_transfer = pc->buffer_size;
+ 	if (pc->request_transfer == tape->stage_size)
+ 		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+ }
  
--# built-in only drivers from arm/
--ide-core-$(CONFIG_IDE_ARM)		+= arm/ide_arm.o
-+obj-$(CONFIG_BLK_DEV_IDE)		+= ide-core.o
+-static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
++static void idetape_create_read_buffer_cmd(idetape_tape_t *tape,
++		idetape_pc_t *pc, struct idetape_bh *bh)
+ {
+ 	int size = 32768;
+ 	struct idetape_bh *p = bh;
  
--# built-in only drivers from legacy/
--ide-core-$(CONFIG_BLK_DEV_BUDDHA)	+= legacy/buddha.o
--ide-core-$(CONFIG_BLK_DEV_FALCON_IDE)	+= legacy/falconide.o
--ide-core-$(CONFIG_BLK_DEV_GAYLE)	+= legacy/gayle.o
--ide-core-$(CONFIG_BLK_DEV_MAC_IDE)	+= legacy/macide.o
--ide-core-$(CONFIG_BLK_DEV_Q40IDE)	+= legacy/q40ide.o
-+ifeq ($(CONFIG_IDE_ARM), y)
-+	ide-arm-core-y += arm/ide_arm.o
-+	obj-y += ide-arm-core.o
-+endif
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_READ_BUFFER_CMD;
++	pc->c[0] = READ_BUFFER;
+ 	pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK;
+ 	pc->c[7] = size >> 8;
+ 	pc->c[8] = size & 0xff;
+@@ -2388,14 +1542,16 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p
+ 		atomic_set(&p->b_count, 0);
+ 		p = p->b_reqnext;
+ 	}
+-	pc->request_transfer = pc->buffer_size = size;
++	pc->request_transfer = size;
++	pc->buffer_size = size;
+ }
  
--# built-in only drivers from ppc/
--ide-core-$(CONFIG_BLK_DEV_MPC8xx_IDE)	+= ppc/mpc8xx.o
--ide-core-$(CONFIG_BLK_DEV_IDE_PMAC)	+= ppc/pmac.o
-+obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ pci/
+-static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
++static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc,
++		unsigned int length, struct idetape_bh *bh)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_WRITE_CMD;
+-	put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
++	pc->c[0] = WRITE_6;
++	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
+ 	pc->c[1] = 1;
+ 	pc->callback = &idetape_rw_callback;
+ 	set_bit(PC_WRITING, &pc->flags);
+@@ -2403,53 +1559,36 @@ static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, uns
+ 	pc->b_data = bh->b_data;
+ 	pc->b_count = atomic_read(&bh->b_count);
+ 	pc->buffer = NULL;
+-	pc->request_transfer = pc->buffer_size = length * tape->tape_block_size;
++	pc->buffer_size = length * tape->blk_size;
++	pc->request_transfer = pc->buffer_size;
+ 	if (pc->request_transfer == tape->stage_size)
+ 		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
+ }
  
--# built-in only drivers from h8300/
--ide-core-$(CONFIG_IDE_H8300)		+= h8300/ide-h8300.o
-+obj-$(CONFIG_IDEPCI_PCIBUS_ORDER)	+= ide-scan-pci.o
+-/*
+- * idetape_do_request is our request handling function.	
+- */
+ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 					  struct request *rq, sector_t block)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t *pc = NULL;
+ 	struct request *postponed_rq = tape->postponed_rq;
+-	atapi_status_t status;
++	u8 stat;
  
--obj-$(CONFIG_BLK_DEV_IDE)		+= ide-core.o
-+ifeq ($(CONFIG_BLK_DEV_CMD640), y)
-+	cmd640-core-y += pci/cmd640.o
-+	obj-y += cmd640-core.o
-+endif
-+
-+obj-$(CONFIG_BLK_DEV_IDE)		+= cris/ ppc/
-+obj-$(CONFIG_BLK_DEV_IDEPNP)		+= ide-pnp.o
-+obj-$(CONFIG_IDE_H8300)			+= h8300/
- obj-$(CONFIG_IDE_GENERIC)		+= ide-generic.o
+-#if IDETAPE_DEBUG_LOG
+-#if 0
+-	if (tape->debug_level >= 5)
+-		printk(KERN_INFO "ide-tape:  %d, "
+-			"dev: %s, cmd: %ld, errors: %d\n",
+-			 rq->rq_disk->disk_name, rq->cmd[0], rq->errors);
+-#endif
+-	if (tape->debug_level >= 2)
+-		printk(KERN_INFO "ide-tape: sector: %ld, "
+-			"nr_sectors: %ld, current_nr_sectors: %d\n",
++	debug_log(DBG_SENSE, "sector: %ld, nr_sectors: %ld,"
++			" current_nr_sectors: %d\n",
+ 			rq->sector, rq->nr_sectors, rq->current_nr_sectors);
+-#endif /* IDETAPE_DEBUG_LOG */
  
-+ide-cd_mod-y += ide-cd.o ide-cd_ioctl.o ide-cd_verbose.o
-+
- obj-$(CONFIG_BLK_DEV_IDEDISK)		+= ide-disk.o
--obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd.o
-+obj-$(CONFIG_BLK_DEV_IDECD)		+= ide-cd_mod.o
- obj-$(CONFIG_BLK_DEV_IDETAPE)		+= ide-tape.o
- obj-$(CONFIG_BLK_DEV_IDEFLOPPY)		+= ide-floppy.o
+ 	if (!blk_special_request(rq)) {
+-		/*
+-		 * We do not support buffer cache originated requests.
+-		 */
++		/* We do not support buffer cache originated requests. */
+ 		printk(KERN_NOTICE "ide-tape: %s: Unsupported request in "
+ 			"request queue (%d)\n", drive->name, rq->cmd_type);
+ 		ide_end_request(drive, 0, 0);
+ 		return ide_stopped;
+ 	}
  
--obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ arm/ mips/
--obj-$(CONFIG_BLK_DEV_HD)		+= legacy/
--obj-$(CONFIG_ETRAX_IDE)		+= cris/
-+ifeq ($(CONFIG_BLK_DEV_IDECS), y)
-+	ide-cs-core-y += legacy/ide-cs.o
-+	obj-y += ide-cs-core.o
-+endif
-+
-+ifeq ($(CONFIG_BLK_DEV_PLATFORM), y)
-+	ide-platform-core-y += legacy/ide_platform.o
-+	obj-y += ide-platform-core.o
-+endif
-+
-+obj-$(CONFIG_BLK_DEV_IDE)		+= arm/ mips/
+-	/*
+-	 *	Retry a failed packet command
+-	 */
+-	if (tape->failed_pc != NULL &&
+-	    tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
+-		return idetape_issue_packet_command(drive, tape->failed_pc);
+-	}
+-#if IDETAPE_DEBUG_BUGS
++	/* Retry a failed packet command */
++	if (tape->failed_pc && tape->pc->c[0] == REQUEST_SENSE)
++		return idetape_issue_pc(drive, tape->failed_pc);
 +
-+# old hd driver must be last
-+ifeq ($(CONFIG_BLK_DEV_HD), y)
-+	hd-core-y += legacy/hd.o
-+	obj-y += hd-core.o
-+endif
-diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
-index 6a78f07..5f63ad2 100644
---- a/drivers/ide/arm/Makefile
-+++ b/drivers/ide/arm/Makefile
-@@ -3,4 +3,8 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)	+= icside.o
- obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)	+= rapide.o
- obj-$(CONFIG_BLK_DEV_IDE_BAST)		+= bast-ide.o
+ 	if (postponed_rq != NULL)
+ 		if (rq != postponed_rq) {
+ 			printk(KERN_ERR "ide-tape: ide-tape.c bug - "
+@@ -2457,7 +1596,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 			idetape_end_request(drive, 0, 0);
+ 			return ide_stopped;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
  
-+ifeq ($(CONFIG_IDE_ARM), m)
-+	obj-m += ide_arm.o
-+endif
-+
- EXTRA_CFLAGS	:= -Idrivers/ide
-diff --git a/drivers/ide/arm/bast-ide.c b/drivers/ide/arm/bast-ide.c
-index 48db616..0e7574c 100644
---- a/drivers/ide/arm/bast-ide.c
-+++ b/drivers/ide/arm/bast-ide.c
-@@ -1,5 +1,4 @@
--/* linux/drivers/ide/arm/bast-ide.c
-- *
-+/*
-  * Copyright (c) 2003-2004 Simtec Electronics
-  *  Ben Dooks <ben at simtec.co.uk>
-  *
-@@ -29,8 +28,10 @@ static int __init
- bastide_register(unsigned int base, unsigned int aux, int irq,
- 		 ide_hwif_t **hwif)
- {
-+	ide_hwif_t *hwif;
- 	hw_regs_t hw;
- 	int i;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	tape->postponed_rq = NULL;
  
- 	memset(&hw, 0, sizeof(hw));
+@@ -2465,7 +1603,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 	 * If the tape is still busy, postpone our request and service
+ 	 * the other device meanwhile.
+ 	 */
+-	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
++	stat = ide_read_status(drive);
  
-@@ -45,8 +46,24 @@ bastide_register(unsigned int base, unsigned int aux, int irq,
- 	hw.io_ports[IDE_CONTROL_OFFSET] = aux + (6 * 0x20);
- 	hw.irq = irq;
+ 	if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
+ 		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
+@@ -2475,16 +1613,15 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 		drive->post_reset = 0;
+ 	}
  
--	ide_register_hw(&hw, NULL, 0, hwif);
-+	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif == NULL)
-+		goto out;
-+
-+	i = hwif->index;
-+
-+	if (hwif->present)
-+		ide_unregister(i, 0, 0);
-+	else if (!hwif->hold)
-+		ide_init_port_data(hwif, i);
-+
-+	ide_init_port_hw(hwif, &hw);
-+	hwif->quirkproc = NULL;
-+
-+	idx[0] = i;
+-	if (tape->tape_still_time > 100 && tape->tape_still_time < 200)
+-		tape->measure_insert_time = 1;
+ 	if (time_after(jiffies, tape->insert_time))
+-		tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
+-	calculate_speeds(drive);
++		tape->insert_speed = tape->insert_size / 1024 * HZ /
++					(jiffies - tape->insert_time);
++	idetape_calculate_speeds(drive);
+ 	if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
+-	    !status.b.dsc) {
++	    (stat & SEEK_STAT) == 0) {
+ 		if (postponed_rq == NULL) {
+ 			tape->dsc_polling_start = jiffies;
+-			tape->dsc_polling_frequency = tape->best_dsc_rw_frequency;
++			tape->dsc_poll_freq = tape->best_dsc_rw_freq;
+ 			tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
+ 		} else if (time_after(jiffies, tape->dsc_timeout)) {
+ 			printk(KERN_ERR "ide-tape: %s: DSC timeout\n",
+@@ -2495,35 +1632,34 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 			} else {
+ 				return ide_do_reset(drive);
+ 			}
+-		} else if (time_after(jiffies, tape->dsc_polling_start + IDETAPE_DSC_MA_THRESHOLD))
+-			tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
++		} else if (time_after(jiffies,
++					tape->dsc_polling_start +
++					IDETAPE_DSC_MA_THRESHOLD))
++			tape->dsc_poll_freq = IDETAPE_DSC_MA_SLOW;
+ 		idetape_postpone_request(drive);
+ 		return ide_stopped;
+ 	}
+ 	if (rq->cmd[0] & REQ_IDETAPE_READ) {
+ 		tape->buffer_head++;
+-#if USE_IOTRACE
+-		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+-#endif
+ 		tape->postpone_cnt = 0;
+ 		pc = idetape_next_pc_storage(drive);
+-		idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
++		idetape_create_read_cmd(tape, pc, rq->current_nr_sectors,
++					(struct idetape_bh *)rq->special);
+ 		goto out;
+ 	}
+ 	if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
+ 		tape->buffer_head++;
+-#if USE_IOTRACE
+-		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+-#endif
+ 		tape->postpone_cnt = 0;
+ 		pc = idetape_next_pc_storage(drive);
+-		idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
++		idetape_create_write_cmd(tape, pc, rq->current_nr_sectors,
++					 (struct idetape_bh *)rq->special);
+ 		goto out;
+ 	}
+ 	if (rq->cmd[0] & REQ_IDETAPE_READ_BUFFER) {
+ 		tape->postpone_cnt = 0;
+ 		pc = idetape_next_pc_storage(drive);
+-		idetape_create_read_buffer_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
++		idetape_create_read_buffer_cmd(tape, pc,
++				(struct idetape_bh *)rq->special);
+ 		goto out;
+ 	}
+ 	if (rq->cmd[0] & REQ_IDETAPE_PC1) {
+@@ -2538,49 +1674,51 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
+ 	}
+ 	BUG();
+ out:
+-	return idetape_issue_packet_command(drive, pc);
++	return idetape_issue_pc(drive, pc);
+ }
  
-+	ide_device_add(idx, NULL);
-+out:
- 	return 0;
+-/*
+- *	Pipeline related functions
+- */
+-static inline int idetape_pipeline_active (idetape_tape_t *tape)
++/* Pipeline related functions */
++static inline int idetape_pipeline_active(idetape_tape_t *tape)
+ {
+ 	int rc1, rc2;
+ 
+ 	rc1 = test_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
+-	rc2 = (tape->active_data_request != NULL);
++	rc2 = (tape->active_data_rq != NULL);
+ 	return rc1;
  }
  
-diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
-index 93f71fc..fb00f38 100644
---- a/drivers/ide/arm/icside.c
-+++ b/drivers/ide/arm/icside.c
-@@ -1,6 +1,4 @@
  /*
-- * linux/drivers/ide/arm/icside.c
-- *
-  * Copyright (c) 1996-2004 Russell King.
+- *	idetape_kmalloc_stage uses __get_free_page to allocate a pipeline
+- *	stage, along with all the necessary small buffers which together make
+- *	a buffer of size tape->stage_size (or a bit more). We attempt to
+- *	combine sequential pages as much as possible.
++ * The function below uses __get_free_page to allocate a pipeline stage, along
++ * with all the necessary small buffers which together make a buffer of size
++ * tape->stage_size (or a bit more). We attempt to combine sequential pages as
++ * much as possible.
   *
-  * Please note that this platform does not support 32-bit IDE IO.
-@@ -71,8 +69,6 @@ struct icside_state {
- 	void __iomem *irq_port;
- 	void __iomem *ioc_base;
- 	unsigned int type;
--	/* parent device... until the IDE core gets one of its own */
--	struct device *dev;
- 	ide_hwif_t *hwif[2];
- };
- 
-@@ -206,23 +202,6 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
-  * interfaces use the same IRQ, which should guarantee this.
+- *	Returns a pointer to the new allocated stage, or NULL if we
+- *	can't (or don't want to) allocate a stage.
++ * It returns a pointer to the new allocated stage, or NULL if we can't (or
++ * don't want to) allocate a stage.
+  *
+- *	Pipeline stages are optional and are used to increase performance.
+- *	If we can't allocate them, we'll manage without them.
++ * Pipeline stages are optional and are used to increase performance. If we
++ * can't allocate them, we'll manage without them.
   */
+-static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full, int clear)
++static idetape_stage_t *__idetape_kmalloc_stage(idetape_tape_t *tape, int full,
++						int clear)
+ {
+ 	idetape_stage_t *stage;
+ 	struct idetape_bh *prev_bh, *bh;
+ 	int pages = tape->pages_per_stage;
+ 	char *b_data = NULL;
  
--static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
--{
--	ide_hwif_t *hwif = drive->hwif;
--	struct icside_state *state = hwif->hwif_data;
--	struct scatterlist *sg = hwif->sg_table;
--
--	ide_map_sg(drive, rq);
--
--	if (rq_data_dir(rq) == READ)
--		hwif->sg_dma_direction = DMA_FROM_DEVICE;
--	else
--		hwif->sg_dma_direction = DMA_TO_DEVICE;
--
--	hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents,
--				    hwif->sg_dma_direction);
--}
--
- /*
-  * Configure the IOMD to give the appropriate timings for the transfer
-  * mode being requested.  We take the advice of the ATA standards, and
-@@ -272,8 +251,6 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
- 	case XFER_SW_DMA_0:
- 		cycle_time = 480;
- 		break;
--	default:
--		return;
- 	}
+-	if ((stage = kmalloc(sizeof (idetape_stage_t),GFP_KERNEL)) == NULL)
++	stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL);
++	if (!stage)
+ 		return NULL;
+ 	stage->next = NULL;
  
- 	/*
-@@ -289,56 +266,39 @@ static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
- 		ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
+-	bh = stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
++	stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
++	bh = stage->bh;
+ 	if (bh == NULL)
+ 		goto abort;
+ 	bh->b_reqnext = NULL;
+-	if ((bh->b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL)
++	bh->b_data = (char *) __get_free_page(GFP_KERNEL);
++	if (!bh->b_data)
+ 		goto abort;
+ 	if (clear)
+ 		memset(bh->b_data, 0, PAGE_SIZE);
+@@ -2588,7 +1726,8 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
+ 	atomic_set(&bh->b_count, full ? bh->b_size : 0);
+ 
+ 	while (--pages) {
+-		if ((b_data = (char *) __get_free_page (GFP_KERNEL)) == NULL)
++		b_data = (char *) __get_free_page(GFP_KERNEL);
++		if (!b_data)
+ 			goto abort;
+ 		if (clear)
+ 			memset(b_data, 0, PAGE_SIZE);
+@@ -2606,7 +1745,8 @@ static idetape_stage_t *__idetape_kmalloc_stage (idetape_tape_t *tape, int full,
+ 			continue;
+ 		}
+ 		prev_bh = bh;
+-		if ((bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL)) == NULL) {
++		bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL);
++		if (!bh) {
+ 			free_page((unsigned long) b_data);
+ 			goto abort;
+ 		}
+@@ -2625,14 +1765,11 @@ abort:
+ 	return NULL;
  }
  
--static void icside_dma_host_off(ide_drive_t *drive)
-+static void icside_dma_host_set(ide_drive_t *drive, int on)
+-static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape)
++static idetape_stage_t *idetape_kmalloc_stage(idetape_tape_t *tape)
  {
+ 	idetape_stage_t *cache_stage = tape->cache_stage;
+ 
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_kmalloc_stage\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
+ 
+ 	if (tape->nr_stages >= tape->max_stages)
+ 		return NULL;
+@@ -2643,22 +1780,24 @@ static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape)
+ 	return __idetape_kmalloc_stage(tape, 0, 0);
  }
  
--static void icside_dma_off_quietly(ide_drive_t *drive)
--{
--	drive->using_dma = 0;
--}
--
--static void icside_dma_host_on(ide_drive_t *drive)
--{
--}
--
--static int icside_dma_on(ide_drive_t *drive)
--{
--	drive->using_dma = 1;
--
--	return 0;
--}
--
- static int icside_dma_end(ide_drive_t *drive)
+-static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
++static int idetape_copy_stage_from_user(idetape_tape_t *tape,
++		idetape_stage_t *stage, const char __user *buf, int n)
  {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct icside_state *state = hwif->hwif_data;
-+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ 	struct idetape_bh *bh = tape->bh;
+ 	int count;
+ 	int ret = 0;
  
- 	drive->waiting_for_dma = 0;
+ 	while (n) {
+-#if IDETAPE_DEBUG_BUGS
+ 		if (bh == NULL) {
+-			printk(KERN_ERR "ide-tape: bh == NULL in "
+-				"idetape_copy_stage_from_user\n");
++			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
++					__func__);
+ 			return 1;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+-		count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
+-		if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
++		count = min((unsigned int)
++				(bh->b_size - atomic_read(&bh->b_count)),
++				(unsigned int)n);
++		if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf,
++				count))
+ 			ret = 1;
+ 		n -= count;
+ 		atomic_add(count, &bh->b_count);
+@@ -2673,20 +1812,19 @@ static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *
+ 	return ret;
+ }
  
--	disable_dma(ECARD_DEV(state->dev)->dma);
-+	disable_dma(ec->dma);
+-static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
++static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf,
++		idetape_stage_t *stage, int n)
+ {
+ 	struct idetape_bh *bh = tape->bh;
+ 	int count;
+ 	int ret = 0;
  
- 	/* Teardown mappings after DMA has completed. */
--	dma_unmap_sg(state->dev, hwif->sg_table, hwif->sg_nents,
--		     hwif->sg_dma_direction);
-+	ide_destroy_dmatable(drive);
+ 	while (n) {
+-#if IDETAPE_DEBUG_BUGS
+ 		if (bh == NULL) {
+-			printk(KERN_ERR "ide-tape: bh == NULL in "
+-				"idetape_copy_stage_to_user\n");
++			printk(KERN_ERR "ide-tape: bh == NULL in %s\n",
++					__func__);
+ 			return 1;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 		count = min(tape->b_count, n);
+ 		if  (copy_to_user(buf, tape->b_data, count))
+ 			ret = 1;
+@@ -2695,7 +1833,8 @@ static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, i
+ 		tape->b_count -= count;
+ 		buf += count;
+ 		if (!tape->b_count) {
+-			tape->bh = bh = bh->b_reqnext;
++			bh = bh->b_reqnext;
++			tape->bh = bh;
+ 			if (bh) {
+ 				tape->b_data = bh->b_data;
+ 				tape->b_count = atomic_read(&bh->b_count);
+@@ -2705,12 +1844,12 @@ static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, i
+ 	return ret;
+ }
  
--	return get_dma_residue(ECARD_DEV(state->dev)->dma) != 0;
-+	return get_dma_residue(ec->dma) != 0;
+-static void idetape_init_merge_stage (idetape_tape_t *tape)
++static void idetape_init_merge_stage(idetape_tape_t *tape)
+ {
+ 	struct idetape_bh *bh = tape->merge_stage->bh;
+-	
++
+ 	tape->bh = bh;
+-	if (tape->chrdev_direction == idetape_direction_write)
++	if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
+ 		atomic_set(&bh->b_count, 0);
+ 	else {
+ 		tape->b_data = bh->b_data;
+@@ -2718,7 +1857,7 @@ static void idetape_init_merge_stage (idetape_tape_t *tape)
+ 	}
  }
  
- static void icside_dma_start(ide_drive_t *drive)
+-static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage)
++static void idetape_switch_buffers(idetape_tape_t *tape, idetape_stage_t *stage)
  {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct icside_state *state = hwif->hwif_data;
-+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
+ 	struct idetape_bh *tmp;
  
- 	/* We can not enable DMA on both channels simultaneously. */
--	BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
--	enable_dma(ECARD_DEV(state->dev)->dma);
-+	BUG_ON(dma_channel_active(ec->dma));
-+	enable_dma(ec->dma);
+@@ -2728,89 +1867,76 @@ static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage
+ 	idetape_init_merge_stage(tape);
  }
  
- static int icside_dma_setup(ide_drive_t *drive)
+-/*
+- *	idetape_add_stage_tail adds a new stage at the end of the pipeline.
+- */
+-static void idetape_add_stage_tail (ide_drive_t *drive,idetape_stage_t *stage)
++/* Add a new stage at the end of the pipeline. */
++static void idetape_add_stage_tail(ide_drive_t *drive, idetape_stage_t *stage)
  {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct icside_state *state = hwif->hwif_data;
-+	struct expansion_card *ec = ECARD_DEV(hwif->dev);
- 	struct request *rq = hwif->hwgroup->rq;
- 	unsigned int dma_mode;
- 
-@@ -350,9 +310,9 @@ static int icside_dma_setup(ide_drive_t *drive)
- 	/*
- 	 * We can not enable DMA on both channels.
- 	 */
--	BUG_ON(dma_channel_active(ECARD_DEV(state->dev)->dma));
-+	BUG_ON(dma_channel_active(ec->dma));
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	unsigned long flags;
+-	
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk (KERN_INFO "ide-tape: Reached idetape_add_stage_tail\n");
+-#endif /* IDETAPE_DEBUG_LOG */
+-	spin_lock_irqsave(&tape->spinlock, flags);
++
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
++
++	spin_lock_irqsave(&tape->lock, flags);
+ 	stage->next = NULL;
+ 	if (tape->last_stage != NULL)
+-		tape->last_stage->next=stage;
++		tape->last_stage->next = stage;
+ 	else
+-		tape->first_stage = tape->next_stage=stage;
++		tape->first_stage = stage;
++		tape->next_stage  = stage;
+ 	tape->last_stage = stage;
+ 	if (tape->next_stage == NULL)
+ 		tape->next_stage = tape->last_stage;
+ 	tape->nr_stages++;
+ 	tape->nr_pending_stages++;
+-	spin_unlock_irqrestore(&tape->spinlock, flags);
++	spin_unlock_irqrestore(&tape->lock, flags);
+ }
  
--	icside_build_sglist(drive, rq);
-+	hwif->sg_nents = ide_build_sglist(drive, rq);
+-/*
+- *	idetape_wait_for_request installs a completion in a pending request
+- *	and sleeps until it is serviced.
+- *
+- *	The caller should ensure that the request will not be serviced
+- *	before we install the completion (usually by disabling interrupts).
++/* Install a completion in a pending request and sleep until it is serviced. The
++ * caller should ensure that the request will not be serviced before we install
++ * the completion (usually by disabling interrupts).
+  */
+-static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
++static void idetape_wait_for_request(ide_drive_t *drive, struct request *rq)
+ {
+ 	DECLARE_COMPLETION_ONSTACK(wait);
+ 	idetape_tape_t *tape = drive->driver_data;
  
- 	/*
- 	 * Ensure that we have the right interrupt routed.
-@@ -367,14 +327,14 @@ static int icside_dma_setup(ide_drive_t *drive)
- 	/*
- 	 * Select the correct timing for this drive.
- 	 */
--	set_dma_speed(ECARD_DEV(state->dev)->dma, drive->drive_data);
-+	set_dma_speed(ec->dma, drive->drive_data);
+-#if IDETAPE_DEBUG_BUGS
+ 	if (rq == NULL || !blk_special_request(rq)) {
+-		printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
++		printk(KERN_ERR "ide-tape: bug: Trying to sleep on non-valid"
++				 " request\n");
+ 		return;
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 	rq->end_io_data = &wait;
+ 	rq->end_io = blk_end_sync_rq;
+-	spin_unlock_irq(&tape->spinlock);
++	spin_unlock_irq(&tape->lock);
+ 	wait_for_completion(&wait);
+ 	/* The stage and its struct request have been deallocated */
+-	spin_lock_irq(&tape->spinlock);
++	spin_lock_irq(&tape->lock);
+ }
  
- 	/*
- 	 * Tell the DMA engine about the SG table and
- 	 * data direction.
- 	 */
--	set_dma_sg(ECARD_DEV(state->dev)->dma, hwif->sg_table, hwif->sg_nents);
--	set_dma_mode(ECARD_DEV(state->dev)->dma, dma_mode);
-+	set_dma_sg(ec->dma, hwif->sg_table, hwif->sg_nents);
-+	set_dma_mode(ec->dma, dma_mode);
+-static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive)
++static ide_startstop_t idetape_read_position_callback(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_read_position_result_t *result;
+-	
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_read_position_callback\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	u8 *readpos = tape->pc->buffer;
++
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
  
- 	drive->waiting_for_dma = 1;
+ 	if (!tape->pc->error) {
+-		result = (idetape_read_position_result_t *) tape->pc->buffer;
+-#if IDETAPE_DEBUG_LOG
+-		if (tape->debug_level >= 2)
+-			printk(KERN_INFO "ide-tape: BOP - %s\n",result->bop ? "Yes":"No");
+-		if (tape->debug_level >= 2)
+-			printk(KERN_INFO "ide-tape: EOP - %s\n",result->eop ? "Yes":"No");
+-#endif /* IDETAPE_DEBUG_LOG */
+-		if (result->bpu) {
+-			printk(KERN_INFO "ide-tape: Block location is unknown to the tape\n");
++		debug_log(DBG_SENSE, "BOP - %s\n",
++				(readpos[0] & 0x80) ? "Yes" : "No");
++		debug_log(DBG_SENSE, "EOP - %s\n",
++				(readpos[0] & 0x40) ? "Yes" : "No");
++
++		if (readpos[0] & 0x4) {
++			printk(KERN_INFO "ide-tape: Block location is unknown"
++					 "to the tape\n");
+ 			clear_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
+ 			idetape_end_request(drive, 0, 0);
+ 		} else {
+-#if IDETAPE_DEBUG_LOG
+-			if (tape->debug_level >= 2)
+-				printk(KERN_INFO "ide-tape: Block Location - %u\n", ntohl(result->first_block));
+-#endif /* IDETAPE_DEBUG_LOG */
+-			tape->partition = result->partition;
+-			tape->first_frame_position = ntohl(result->first_block);
+-			tape->last_frame_position = ntohl(result->last_block);
+-			tape->blocks_in_buffer = result->blocks_in_buffer[2];
++			debug_log(DBG_SENSE, "Block Location - %u\n",
++					be32_to_cpu(*(u32 *)&readpos[4]));
++
++			tape->partition = readpos[1];
++			tape->first_frame =
++				be32_to_cpu(*(u32 *)&readpos[4]);
+ 			set_bit(IDETAPE_ADDRESS_VALID, &tape->flags);
+ 			idetape_end_request(drive, 1, 0);
+ 		}
+@@ -2821,17 +1947,14 @@ static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive)
+ }
  
-@@ -417,17 +377,11 @@ static void icside_dma_lost_irq(ide_drive_t *drive)
+ /*
+- *	idetape_create_write_filemark_cmd will:
+- *
+- *		1.	Write a filemark if write_filemark=1.
+- *		2.	Flush the device buffers without writing a filemark
+- *			if write_filemark=0.
+- *
++ * Write a filemark if write_filemark=1. Flush the device buffers without
++ * writing a filemark otherwise.
+  */
+-static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark)
++static void idetape_create_write_filemark_cmd(ide_drive_t *drive,
++		idetape_pc_t *pc, int write_filemark)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD;
++	pc->c[0] = WRITE_FILEMARKS;
+ 	pc->c[4] = write_filemark;
+ 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+ 	pc->callback = &idetape_pc_callback;
+@@ -2840,31 +1963,24 @@ static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t
+ static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_TEST_UNIT_READY_CMD;
++	pc->c[0] = TEST_UNIT_READY;
+ 	pc->callback = &idetape_pc_callback;
+ }
  
- static void icside_dma_init(ide_hwif_t *hwif)
+ /*
+- *	idetape_queue_pc_tail is based on the following functions:
++ * We add a special packet command request to the tail of the request queue, and
++ * wait for it to be serviced. This is not to be called from within the request
++ * handling part of the driver! We allocate here data on the stack and it is
++ * valid until the request is finished. This is not the case for the bottom part
++ * of the driver, where we are always leaving the functions to wait for an
++ * interrupt or a timer event.
+  *
+- *	ide_do_drive_cmd from ide.c
+- *	cdrom_queue_request and cdrom_queue_packet_command from ide-cd.c
+- *
+- *	We add a special packet command request to the tail of the request
+- *	queue, and wait for it to be serviced.
+- *
+- *	This is not to be called from within the request handling part
+- *	of the driver ! We allocate here data in the stack, and it is valid
+- *	until the request is finished. This is not the case for the bottom
+- *	part of the driver, where we are always leaving the functions to wait
+- *	for an interrupt or a timer event.
+- *
+- *	From the bottom part of the driver, we should allocate safe memory
+- *	using idetape_next_pc_storage and idetape_next_rq_storage, and add
+- *	the request to the request list without waiting for it to be serviced !
+- *	In that case, we usually use idetape_queue_pc_head.
++ * From the bottom part of the driver, we should allocate safe memory using
++ * idetape_next_pc_storage() and ide_tape_next_rq_storage(), and add the request
++ * to the request list without waiting for it to be serviced! In that case, we
++ * usually use idetape_queue_pc_head().
+  */
+-static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc)
++static int __idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
  {
--	hwif->mwdma_mask	= 7; /* MW0..2 */
--	hwif->swdma_mask	= 7; /* SW0..2 */
--
- 	hwif->dmatable_cpu	= NULL;
- 	hwif->dmatable_dma	= 0;
- 	hwif->set_dma_mode	= icside_set_dma_mode;
+ 	struct ide_tape_obj *tape = drive->driver_data;
+ 	struct request rq;
+@@ -2875,10 +1991,11 @@ static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc)
+ 	return ide_do_drive_cmd(drive, &rq, ide_wait);
+ }
  
--	hwif->dma_host_off	= icside_dma_host_off;
--	hwif->dma_off_quietly	= icside_dma_off_quietly;
--	hwif->dma_host_on	= icside_dma_host_on;
--	hwif->ide_dma_on	= icside_dma_on;
-+	hwif->dma_host_set	= icside_dma_host_set;
- 	hwif->dma_setup		= icside_dma_setup;
- 	hwif->dma_exec_cmd	= icside_dma_exec_cmd;
- 	hwif->dma_start		= icside_dma_start;
-@@ -465,6 +419,7 @@ icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *e
- 		hwif->noprobe = 0;
- 		hwif->chipset = ide_acorn;
- 		hwif->gendev.parent = &ec->dev;
-+		hwif->dev = &ec->dev;
- 	}
+-static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd)
++static void idetape_create_load_unload_cmd(ide_drive_t *drive, idetape_pc_t *pc,
++		int cmd)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD;
++	pc->c[0] = START_STOP;
+ 	pc->c[4] = cmd;
+ 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+ 	pc->callback = &idetape_pc_callback;
+@@ -2890,9 +2007,7 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ 	idetape_pc_t pc;
+ 	int load_attempted = 0;
  
- 	return hwif;
-@@ -501,11 +456,19 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
+-	/*
+-	 * Wait for the tape to become ready
+-	 */
++	/* Wait for the tape to become ready */
+ 	set_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
+ 	timeout += jiffies;
+ 	while (time_before(jiffies, timeout)) {
+@@ -2900,10 +2015,12 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ 		if (!__idetape_queue_pc_tail(drive, &pc))
+ 			return 0;
+ 		if ((tape->sense_key == 2 && tape->asc == 4 && tape->ascq == 2)
+-		    || (tape->asc == 0x3A)) {	/* no media */
++		    || (tape->asc == 0x3A)) {
++			/* no media */
+ 			if (load_attempted)
+ 				return -ENOMEDIUM;
+-			idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK);
++			idetape_create_load_unload_cmd(drive, &pc,
++							IDETAPE_LU_LOAD_MASK);
+ 			__idetape_queue_pc_tail(drive, &pc);
+ 			load_attempted = 1;
+ 		/* not about to be ready */
+@@ -2915,85 +2032,86 @@ static int idetape_wait_ready(ide_drive_t *drive, unsigned long timeout)
+ 	return -EIO;
+ }
  
- 	idx[0] = hwif->index;
+-static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc)
++static int idetape_queue_pc_tail(ide_drive_t *drive, idetape_pc_t *pc)
+ {
+ 	return __idetape_queue_pc_tail(drive, pc);
+ }
  
--	ide_device_add(idx);
-+	ide_device_add(idx, NULL);
+-static int idetape_flush_tape_buffers (ide_drive_t *drive)
++static int idetape_flush_tape_buffers(ide_drive_t *drive)
+ {
+ 	idetape_pc_t pc;
+ 	int rc;
  
+ 	idetape_create_write_filemark_cmd(drive, &pc, 0);
+-	if ((rc = idetape_queue_pc_tail(drive, &pc)))
++	rc = idetape_queue_pc_tail(drive, &pc);
++	if (rc)
+ 		return rc;
+ 	idetape_wait_ready(drive, 60 * 5 * HZ);
  	return 0;
  }
  
-+static const struct ide_port_info icside_v6_port_info __initdata = {
-+	.host_flags		= IDE_HFLAG_SERIALIZE |
-+				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
-+				  IDE_HFLAG_NO_AUTOTUNE,
-+	.mwdma_mask		= ATA_MWDMA2,
-+	.swdma_mask		= ATA_SWDMA2,
-+};
-+
- static int __init
- icside_register_v6(struct icside_state *state, struct expansion_card *ec)
+-static void idetape_create_read_position_cmd (idetape_pc_t *pc)
++static void idetape_create_read_position_cmd(idetape_pc_t *pc)
  {
-@@ -514,6 +477,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
- 	unsigned int sel = 0;
- 	int ret;
- 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+	struct ide_port_info d = icside_v6_port_info;
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_READ_POSITION_CMD;
++	pc->c[0] = READ_POSITION;
+ 	pc->request_transfer = 20;
+ 	pc->callback = &idetape_read_position_callback;
+ }
  
- 	ioc_base = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
- 	if (!ioc_base) {
-@@ -563,30 +527,25 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
- 	state->hwif[1]    = mate;
+-static int idetape_read_position (ide_drive_t *drive)
++static int idetape_read_position(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t pc;
+ 	int position;
  
- 	hwif->maskproc    = icside_maskproc;
--	hwif->channel     = 0;
- 	hwif->hwif_data   = state;
--	hwif->mate        = mate;
--	hwif->serialized  = 1;
- 	hwif->config_data = (unsigned long)ioc_base;
- 	hwif->select_data = sel;
+-#if IDETAPE_DEBUG_LOG
+-        if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_read_position\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
  
- 	mate->maskproc    = icside_maskproc;
--	mate->channel     = 1;
- 	mate->hwif_data   = state;
--	mate->mate        = hwif;
--	mate->serialized  = 1;
- 	mate->config_data = (unsigned long)ioc_base;
- 	mate->select_data = sel | 1;
+ 	idetape_create_read_position_cmd(&pc);
+ 	if (idetape_queue_pc_tail(drive, &pc))
+ 		return -1;
+-	position = tape->first_frame_position;
++	position = tape->first_frame;
+ 	return position;
+ }
  
- 	if (ec->dma != NO_DMA && !request_dma(ec->dma, hwif->name)) {
- 		icside_dma_init(hwif);
- 		icside_dma_init(mate);
--	}
-+	} else
-+		d.mwdma_mask = d.swdma_mask = 0;
+-static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip)
++static void idetape_create_locate_cmd(ide_drive_t *drive, idetape_pc_t *pc,
++		unsigned int block, u8 partition, int skip)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_LOCATE_CMD;
++	pc->c[0] = POSITION_TO_ELEMENT;
+ 	pc->c[1] = 2;
+-	put_unaligned(htonl(block), (unsigned int *) &pc->c[3]);
++	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
+ 	pc->c[8] = partition;
+ 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+ 	pc->callback = &idetape_pc_callback;
+ }
  
- 	idx[0] = hwif->index;
- 	idx[1] = mate->index;
+-static int idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int prevent)
++static int idetape_create_prevent_cmd(ide_drive_t *drive, idetape_pc_t *pc,
++				      int prevent)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
--	ide_device_add(idx);
-+	ide_device_add(idx, &d);
+-	if (!tape->capabilities.lock)
++	/* device supports locking according to capabilities page */
++	if (!(tape->caps[6] & 0x01))
+ 		return 0;
  
- 	return 0;
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_PREVENT_CMD;
++	pc->c[0] = ALLOW_MEDIUM_REMOVAL;
+ 	pc->c[4] = prevent;
+ 	pc->callback = &idetape_pc_callback;
+ 	return 1;
+ }
  
-@@ -612,7 +571,6 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
- 	}
+-static int __idetape_discard_read_pipeline (ide_drive_t *drive)
++static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	unsigned long flags;
+ 	int cnt;
  
- 	state->type	= ICS_TYPE_NOTYPE;
--	state->dev	= &ec->dev;
+-	if (tape->chrdev_direction != idetape_direction_read)
++	if (tape->chrdev_dir != IDETAPE_DIR_READ)
+ 		return 0;
  
- 	idmem = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0);
- 	if (idmem) {
-diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
-index 8957cba..43a70e9 100644
---- a/drivers/ide/arm/ide_arm.c
-+++ b/drivers/ide/arm/ide_arm.c
-@@ -24,12 +24,25 @@
- # define IDE_ARM_IRQ	IRQ_HARDDISK
- #endif
+ 	/* Remove merge stage. */
+-	cnt = tape->merge_stage_size / tape->tape_block_size;
++	cnt = tape->merge_stage_size / tape->blk_size;
+ 	if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+ 		++cnt;		/* Filemarks count as 1 sector */
+ 	tape->merge_stage_size = 0;
+@@ -3004,22 +2122,22 @@ static int __idetape_discard_read_pipeline (ide_drive_t *drive)
+ 
+ 	/* Clear pipeline flags. */
+ 	clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+-	tape->chrdev_direction = idetape_direction_none;
++	tape->chrdev_dir = IDETAPE_DIR_NONE;
  
--void __init ide_arm_init(void)
-+static int __init ide_arm_init(void)
- {
-+	ide_hwif_t *hwif;
- 	hw_regs_t hw;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	/* Remove pipeline stages. */
+ 	if (tape->first_stage == NULL)
+ 		return 0;
  
- 	memset(&hw, 0, sizeof(hw));
- 	ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
- 	hw.irq = IDE_ARM_IRQ;
--	ide_register_hw(&hw, NULL, 1, NULL);
-+
-+	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif) {
-+		ide_init_port_hw(hwif, &hw);
-+		idx[0] = hwif->index;
-+
-+		ide_device_add(idx, NULL);
-+	}
-+
-+	return 0;
+-	spin_lock_irqsave(&tape->spinlock, flags);
++	spin_lock_irqsave(&tape->lock, flags);
+ 	tape->next_stage = NULL;
+ 	if (idetape_pipeline_active(tape))
+-		idetape_wait_for_request(drive, tape->active_data_request);
+-	spin_unlock_irqrestore(&tape->spinlock, flags);
++		idetape_wait_for_request(drive, tape->active_data_rq);
++	spin_unlock_irqrestore(&tape->lock, flags);
+ 
+ 	while (tape->first_stage != NULL) {
+ 		struct request *rq_ptr = &tape->first_stage->rq;
+ 
+-		cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors; 
++		cnt += rq_ptr->nr_sectors - rq_ptr->current_nr_sectors;
+ 		if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+ 			++cnt;
+ 		idetape_remove_stage_head(drive);
+@@ -3030,21 +2148,19 @@ static int __idetape_discard_read_pipeline (ide_drive_t *drive)
  }
-+
-+module_init(ide_arm_init);
-diff --git a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
-index 0775a3a..efba00d 100644
---- a/drivers/ide/arm/rapide.c
-+++ b/drivers/ide/arm/rapide.c
-@@ -1,6 +1,4 @@
+ 
  /*
-- * linux/drivers/ide/arm/rapide.c
+- *	idetape_position_tape positions the tape to the requested block
+- *	using the LOCATE packet command. A READ POSITION command is then
+- *	issued to check where we are positioned.
 - *
-  * Copyright (c) 1996-2002 Russell King.
-  */
- 
-@@ -13,26 +11,18 @@
+- *	Like all higher level operations, we queue the commands at the tail
+- *	of the request queue and wait for their completion.
+- *	
++ * Position the tape to the requested block using the LOCATE packet command.
++ * A READ POSITION command is then issued to check where we are positioned. Like
++ * all higher level operations, we queue the commands at the tail of the request
++ * queue and wait for their completion.
+  */
+-static int idetape_position_tape (ide_drive_t *drive, unsigned int block, u8 partition, int skip)
++static int idetape_position_tape(ide_drive_t *drive, unsigned int block,
++		u8 partition, int skip)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	int retval;
+ 	idetape_pc_t pc;
  
- #include <asm/ecard.h>
+-	if (tape->chrdev_direction == idetape_direction_read)
++	if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ 		__idetape_discard_read_pipeline(drive);
+ 	idetape_wait_ready(drive, 60 * 5 * HZ);
+ 	idetape_create_locate_cmd(drive, &pc, block, partition, skip);
+@@ -3056,7 +2172,8 @@ static int idetape_position_tape (ide_drive_t *drive, unsigned int block, u8 par
+ 	return (idetape_queue_pc_tail(drive, &pc));
+ }
  
--static ide_hwif_t *
--rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq)
-+static void rapide_setup_ports(hw_regs_t *hw, void __iomem *base,
-+			       void __iomem *ctrl, unsigned int sz, int irq)
+-static void idetape_discard_read_pipeline (ide_drive_t *drive, int restore_position)
++static void idetape_discard_read_pipeline(ide_drive_t *drive,
++					  int restore_position)
  {
- 	unsigned long port = (unsigned long)base;
--	ide_hwif_t *hwif = ide_find_port(port);
- 	int i;
- 
--	if (hwif == NULL)
--		goto out;
--
- 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
--		hwif->io_ports[i] = port;
-+		hw->io_ports[i] = port;
- 		port += sz;
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	int cnt;
+@@ -3067,37 +2184,37 @@ static void idetape_discard_read_pipeline (ide_drive_t *drive, int restore_posit
+ 		position = idetape_read_position(drive);
+ 		seek = position > cnt ? position - cnt : 0;
+ 		if (idetape_position_tape(drive, seek, 0, 0)) {
+-			printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name);
++			printk(KERN_INFO "ide-tape: %s: position_tape failed in"
++					 " discard_pipeline()\n", tape->name);
+ 			return;
+ 		}
  	}
--	hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
--	hwif->irq = irq;
--	hwif->mmio = 1;
--	default_hwif_mmiops(hwif);
--out:
--	return hwif;
-+	hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
-+	hw->irq = irq;
  }
  
- static int __devinit
-@@ -42,6 +32,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
- 	void __iomem *base;
- 	int ret;
- 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+	hw_regs_t hw;
- 
- 	ret = ecard_request_resources(ec);
- 	if (ret)
-@@ -53,15 +44,21 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
- 		goto release;
- 	}
+ /*
+- * idetape_queue_rw_tail generates a read/write request for the block
+- * device interface and wait for it to be serviced.
++ * Generate a read/write request for the block device interface and wait for it
++ * to be serviced.
+  */
+-static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct idetape_bh *bh)
++static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks,
++				 struct idetape_bh *bh)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	struct request rq;
  
--	hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq);
-+	hwif = ide_find_port((unsigned long)base);
- 	if (hwif) {
--		hwif->hwif_data = base;
--		hwif->gendev.parent = &ec->dev;
--		hwif->noprobe = 0;
-+		memset(&hw, 0, sizeof(hw));
-+		rapide_setup_ports(&hw, base, base + 0x818, 1 << 6, ec->irq);
-+		hw.chipset = ide_generic;
-+		hw.dev = &ec->dev;
-+
-+		ide_init_port_hw(hwif, &hw);
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 2)
+-		printk(KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd);
+-#endif /* IDETAPE_DEBUG_LOG */
+-#if IDETAPE_DEBUG_BUGS
++	debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd);
 +
-+		hwif->mmio = 1;
-+		default_hwif_mmiops(hwif);
+ 	if (idetape_pipeline_active(tape)) {
+-		printk(KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n");
++		printk(KERN_ERR "ide-tape: bug: the pipeline is active in %s\n",
++				__func__);
+ 		return (0);
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */	
  
- 		idx[0] = hwif->index;
+ 	idetape_init_rq(&rq, cmd);
+ 	rq.rq_disk = tape->disk;
+ 	rq.special = (void *)bh;
+-	rq.sector = tape->first_frame_position;
+-	rq.nr_sectors = rq.current_nr_sectors = blocks;
++	rq.sector = tape->first_frame;
++	rq.nr_sectors		= blocks;
++	rq.current_nr_sectors	= blocks;
+ 	(void) ide_do_drive_cmd(drive, &rq, ide_wait);
  
--		ide_device_add(idx);
-+		ide_device_add(idx, NULL);
+ 	if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0)
+@@ -3107,14 +2224,11 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct
+ 		idetape_init_merge_stage(tape);
+ 	if (rq.errors == IDETAPE_ERROR_GENERAL)
+ 		return -EIO;
+-	return (tape->tape_block_size * (blocks-rq.current_nr_sectors));
++	return (tape->blk_size * (blocks-rq.current_nr_sectors));
+ }
  
- 		ecard_set_drvdata(ec, hwif);
- 		goto out;
-@@ -79,8 +76,8 @@ static void __devexit rapide_remove(struct expansion_card *ec)
+-/*
+- *	idetape_insert_pipeline_into_queue is used to start servicing the
+- *	pipeline stages, starting from tape->next_stage.
+- */
+-static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
++/* start servicing the pipeline stages, starting from tape->next_stage. */
++static void idetape_plug_pipeline(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
- 	ecard_set_drvdata(ec, NULL);
+@@ -3122,145 +2236,128 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
+ 		return;
+ 	if (!idetape_pipeline_active(tape)) {
+ 		set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
+-		idetape_active_next_stage(drive);
+-		(void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
++		idetape_activate_next_stage(drive);
++		(void) ide_do_drive_cmd(drive, tape->active_data_rq, ide_end);
+ 	}
+ }
  
--	/* there must be a better way */
--	ide_unregister(hwif - ide_hwifs);
-+	ide_unregister(hwif->index, 0, 0);
-+
- 	ecard_release_resources(ec);
+-static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
++static void idetape_create_inquiry_cmd(idetape_pc_t *pc)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_INQUIRY_CMD;
+-	pc->c[4] = pc->request_transfer = 254;
++	pc->c[0] = INQUIRY;
++	pc->c[4] = 254;
++	pc->request_transfer = 254;
+ 	pc->callback = &idetape_pc_callback;
  }
  
-diff --git a/drivers/ide/cris/Makefile b/drivers/ide/cris/Makefile
-index 6176e8d..20b9596 100644
---- a/drivers/ide/cris/Makefile
-+++ b/drivers/ide/cris/Makefile
-@@ -1,3 +1,3 @@
- EXTRA_CFLAGS				+= -Idrivers/ide
+-static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc)
++static void idetape_create_rewind_cmd(ide_drive_t *drive, idetape_pc_t *pc)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_REWIND_CMD;
++	pc->c[0] = REZERO_UNIT;
+ 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+ 	pc->callback = &idetape_pc_callback;
+ }
  
--obj-y					+= ide-cris.o
-+obj-$(CONFIG_IDE_ETRAX)			+= ide-cris.o
-diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
-index 476e0d6..00587a8 100644
---- a/drivers/ide/cris/ide-cris.c
-+++ b/drivers/ide/cris/ide-cris.c
-@@ -1,5 +1,4 @@
--/* $Id: cris-ide-driver.patch,v 1.1 2005/06/29 21:39:07 akpm Exp $
-- *
-+/*
-  * Etrax specific IDE functions, like init and PIO-mode setting etc.
-  * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
-  * Copyright (c) 2000-2005 Axis Communications AB
-@@ -673,9 +672,8 @@ static void cris_ide_input_data (ide_drive_t *drive, void *, unsigned int);
- static void cris_ide_output_data (ide_drive_t *drive, void *, unsigned int);
- static void cris_atapi_input_bytes(ide_drive_t *drive, void *, unsigned int);
- static void cris_atapi_output_bytes(ide_drive_t *drive, void *, unsigned int);
--static int cris_dma_on (ide_drive_t *drive);
+-#if 0
+-static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length)
+-{
+-	idetape_init_pc(pc);
+-	set_bit(PC_WRITING, &pc->flags);
+-	pc->c[0] = IDETAPE_MODE_SELECT_CMD;
+-	pc->c[1] = 0x10;
+-	put_unaligned(htons(length), (unsigned short *) &pc->c[3]);
+-	pc->request_transfer = 255;
+-	pc->callback = &idetape_pc_callback;
+-}
+-#endif
+-
+-static void idetape_create_erase_cmd (idetape_pc_t *pc)
++static void idetape_create_erase_cmd(idetape_pc_t *pc)
+ {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_ERASE_CMD;
++	pc->c[0] = ERASE;
+ 	pc->c[1] = 1;
+ 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+ 	pc->callback = &idetape_pc_callback;
+ }
  
--static void cris_dma_off(ide_drive_t *drive)
-+static void cris_dma_host_set(ide_drive_t *drive, int on)
+-static void idetape_create_space_cmd (idetape_pc_t *pc,int count, u8 cmd)
++static void idetape_create_space_cmd(idetape_pc_t *pc, int count, u8 cmd)
  {
+ 	idetape_init_pc(pc);
+-	pc->c[0] = IDETAPE_SPACE_CMD;
+-	put_unaligned(htonl(count), (unsigned int *) &pc->c[1]);
++	pc->c[0] = SPACE;
++	put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
+ 	pc->c[1] = cmd;
+ 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
+ 	pc->callback = &idetape_pc_callback;
  }
  
-@@ -747,8 +745,6 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 			strobe = ATA_DMA2_STROBE;
- 			hold = ATA_DMA2_HOLD;
- 			break;
--		default:
--			return;
- 	}
+-static void idetape_wait_first_stage (ide_drive_t *drive)
++static void idetape_wait_first_stage(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	unsigned long flags;
  
- 	if (speed >= XFER_UDMA_0)
-@@ -757,13 +753,20 @@ static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 		cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
+ 	if (tape->first_stage == NULL)
+ 		return;
+-	spin_lock_irqsave(&tape->spinlock, flags);
++	spin_lock_irqsave(&tape->lock, flags);
+ 	if (tape->active_stage == tape->first_stage)
+-		idetape_wait_for_request(drive, tape->active_data_request);
+-	spin_unlock_irqrestore(&tape->spinlock, flags);
++		idetape_wait_for_request(drive, tape->active_data_rq);
++	spin_unlock_irqrestore(&tape->lock, flags);
  }
  
--void __init
--init_e100_ide (void)
-+static const struct ide_port_info cris_port_info __initdata = {
-+	.chipset		= ide_etrax100,
-+	.host_flags		= IDE_HFLAG_NO_ATAPI_DMA |
-+				  IDE_HFLAG_NO_DMA, /* no SFF-style DMA */
-+	.pio_mask		= ATA_PIO4,
-+	.udma_mask		= cris_ultra_mask,
-+	.mwdma_mask		= ATA_MWDMA2,
-+};
-+
-+static int __init init_e100_ide(void)
+ /*
+- *	idetape_add_chrdev_write_request tries to add a character device
+- *	originated write request to our pipeline. In case we don't succeed,
+- *	we revert to non-pipelined operation mode for this request.
++ * Try to add a character device originated write request to our pipeline. In
++ * case we don't succeed, we revert to non-pipelined operation mode for this
++ * request. In order to accomplish that, we
+  *
+- *	1.	Try to allocate a new pipeline stage.
+- *	2.	If we can't, wait for more and more requests to be serviced
+- *		and try again each time.
+- *	3.	If we still can't allocate a stage, fallback to
+- *		non-pipelined operation mode for this request.
++ * 1. Try to allocate a new pipeline stage.
++ * 2. If we can't, wait for more and more requests to be serviced and try again
++ * each time.
++ * 3. If we still can't allocate a stage, fallback to non-pipelined operation
++ * mode for this request.
+  */
+-static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
++static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks)
  {
- 	hw_regs_t hw;
--	int ide_offsets[IDE_NR_PORTS];
--	int h;
--	int i;
-+	int ide_offsets[IDE_NR_PORTS], h, i;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- 
- 	printk("ide: ETRAX FS built-in ATA DMA controller\n");
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_stage_t *new_stage;
+ 	unsigned long flags;
+ 	struct request *rq;
  
-@@ -780,17 +783,19 @@ init_e100_ide (void)
- 		                ide_offsets,
- 		                0, 0, cris_ide_ack_intr,
- 		                ide_default_irq(0));
--		ide_register_hw(&hw, NULL, 1, &hwif);
-+		hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
- 		if (hwif == NULL)
- 			continue;
-+		ide_init_port_data(hwif, hwif->index);
-+		ide_init_port_hw(hwif, &hw);
- 		hwif->mmio = 1;
--		hwif->chipset = ide_etrax100;
- 		hwif->set_pio_mode = &cris_set_pio_mode;
- 		hwif->set_dma_mode = &cris_set_dma_mode;
- 		hwif->ata_input_data = &cris_ide_input_data;
- 		hwif->ata_output_data = &cris_ide_output_data;
- 		hwif->atapi_input_bytes = &cris_atapi_input_bytes;
- 		hwif->atapi_output_bytes = &cris_atapi_output_bytes;
-+		hwif->dma_host_set = &cris_dma_host_set;
- 		hwif->ide_dma_end = &cris_dma_end;
- 		hwif->dma_setup = &cris_dma_setup;
- 		hwif->dma_exec_cmd = &cris_dma_exec_cmd;
-@@ -801,16 +806,9 @@ init_e100_ide (void)
- 		hwif->OUTBSYNC = &cris_ide_outbsync;
- 		hwif->INB = &cris_ide_inb;
- 		hwif->INW = &cris_ide_inw;
--		hwif->dma_host_off = &cris_dma_off;
--		hwif->dma_host_on = &cris_dma_on;
--		hwif->dma_off_quietly = &cris_dma_off;
- 		hwif->cbl = ATA_CBL_PATA40;
--		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
--		hwif->pio_mask = ATA_PIO4,
--		hwif->drives[0].autotune = 1;
--		hwif->drives[1].autotune = 1;
--		hwif->ultra_mask = cris_ultra_mask;
--		hwif->mwdma_mask = 0x07; /* Multiword DMA 0-2 */
-+
-+		idx[h] = hwif->index;
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 3)
+-		printk(KERN_INFO "ide-tape: Reached idetape_add_chrdev_write_request\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
+ 
+-     	/*
+-     	 *	Attempt to allocate a new stage.
+-	 *	Pay special attention to possible race conditions.
+-	 */
++	/* Attempt to allocate a new stage. Beware possible race conditions. */
+ 	while ((new_stage = idetape_kmalloc_stage(tape)) == NULL) {
+-		spin_lock_irqsave(&tape->spinlock, flags);
++		spin_lock_irqsave(&tape->lock, flags);
+ 		if (idetape_pipeline_active(tape)) {
+-			idetape_wait_for_request(drive, tape->active_data_request);
+-			spin_unlock_irqrestore(&tape->spinlock, flags);
++			idetape_wait_for_request(drive, tape->active_data_rq);
++			spin_unlock_irqrestore(&tape->lock, flags);
+ 		} else {
+-			spin_unlock_irqrestore(&tape->spinlock, flags);
+-			idetape_insert_pipeline_into_queue(drive);
++			spin_unlock_irqrestore(&tape->lock, flags);
++			idetape_plug_pipeline(drive);
+ 			if (idetape_pipeline_active(tape))
+ 				continue;
+ 			/*
+-			 *	Linux is short on memory. Fallback to
+-			 *	non-pipelined operation mode for this request.
++			 * The machine is short on memory. Fallback to non-
++			 * pipelined operation mode for this request.
+ 			 */
+-			return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, tape->merge_stage->bh);
++			return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE,
++						blocks, tape->merge_stage->bh);
+ 		}
  	}
+ 	rq = &new_stage->rq;
+ 	idetape_init_rq(rq, REQ_IDETAPE_WRITE);
+ 	/* Doesn't actually matter - We always assume sequential access */
+-	rq->sector = tape->first_frame_position;
+-	rq->nr_sectors = rq->current_nr_sectors = blocks;
++	rq->sector = tape->first_frame;
++	rq->current_nr_sectors = blocks;
++	rq->nr_sectors = blocks;
  
- 	/* Reset pulse */
-@@ -823,14 +821,12 @@ init_e100_ide (void)
- 	cris_ide_set_speed(TYPE_PIO, ATA_PIO4_SETUP, ATA_PIO4_STROBE, ATA_PIO4_HOLD);
- 	cris_ide_set_speed(TYPE_DMA, 0, ATA_DMA2_STROBE, ATA_DMA2_HOLD);
- 	cris_ide_set_speed(TYPE_UDMA, ATA_UDMA2_CYC, ATA_UDMA2_DVS, 0);
--}
+ 	idetape_switch_buffers(tape, new_stage);
+ 	idetape_add_stage_tail(drive, new_stage);
+ 	tape->pipeline_head++;
+-#if USE_IOTRACE
+-	IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+-#endif
+-	calculate_speeds(drive);
++	idetape_calculate_speeds(drive);
  
--static int cris_dma_on (ide_drive_t *drive)
--{
-+	ide_device_add(idx, &cris_port_info);
-+
- 	return 0;
+ 	/*
+-	 *	Estimate whether the tape has stopped writing by checking
+-	 *	if our write pipeline is currently empty. If we are not
+-	 *	writing anymore, wait for the pipeline to be full enough
+-	 *	(90%) before starting to service requests, so that we will
+-	 *	be able to keep up with the higher speeds of the tape.
++	 * Estimate whether the tape has stopped writing by checking if our
++	 * write pipeline is currently empty. If we are not writing anymore,
++	 * wait for the pipeline to be almost completely full (90%) before
++	 * starting to service requests, so that we will be able to keep up with
++	 * the higher speeds of the tape.
+ 	 */
+ 	if (!idetape_pipeline_active(tape)) {
+ 		if (tape->nr_stages >= tape->max_stages * 9 / 10 ||
+-		    tape->nr_stages >= tape->max_stages - tape->uncontrolled_pipeline_head_speed * 3 * 1024 / tape->tape_block_size) {
++			tape->nr_stages >= tape->max_stages -
++			tape->uncontrolled_pipeline_head_speed * 3 * 1024 /
++			tape->blk_size) {
+ 			tape->measure_insert_time = 1;
+ 			tape->insert_time = jiffies;
+ 			tape->insert_size = 0;
+ 			tape->insert_speed = 0;
+-			idetape_insert_pipeline_into_queue(drive);
++			idetape_plug_pipeline(drive);
+ 		}
+ 	}
+ 	if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
+@@ -3270,46 +2367,46 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
  }
  
--
- static cris_dma_descr_type mydescr __attribute__ ((__aligned__(16)));
- 
  /*
-@@ -1038,11 +1034,7 @@ static int cris_dma_setup(ide_drive_t *drive)
- 
- static void cris_dma_exec_cmd(ide_drive_t *drive, u8 command)
+- *	idetape_wait_for_pipeline will wait until all pending pipeline
+- *	requests are serviced. Typically called on device close.
++ * Wait until all pending pipeline requests are serviced. Typically called on
++ * device close.
+  */
+-static void idetape_wait_for_pipeline (ide_drive_t *drive)
++static void idetape_wait_for_pipeline(ide_drive_t *drive)
  {
--	/* set the irq handler which will finish the request when DMA is done */
--	ide_set_handler(drive, &cris_dma_intr, WAIT_CMD, NULL);
--
--	/* issue cmd to drive */
--	cris_ide_outb(command, IDE_COMMAND_REG);
-+	ide_execute_command(drive, command, &cris_dma_intr, WAIT_CMD, NULL);
- }
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	unsigned long flags;
  
- static void cris_dma_start(ide_drive_t *drive)
-@@ -1062,3 +1054,5 @@ static void cris_dma_start(ide_drive_t *drive)
- 		LED_DISK_READ(1);
+ 	while (tape->next_stage || idetape_pipeline_active(tape)) {
+-		idetape_insert_pipeline_into_queue(drive);
+-		spin_lock_irqsave(&tape->spinlock, flags);
++		idetape_plug_pipeline(drive);
++		spin_lock_irqsave(&tape->lock, flags);
+ 		if (idetape_pipeline_active(tape))
+-			idetape_wait_for_request(drive, tape->active_data_request);
+-		spin_unlock_irqrestore(&tape->spinlock, flags);
++			idetape_wait_for_request(drive, tape->active_data_rq);
++		spin_unlock_irqrestore(&tape->lock, flags);
  	}
  }
+ 
+-static void idetape_empty_write_pipeline (ide_drive_t *drive)
++static void idetape_empty_write_pipeline(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	int blocks, min;
+ 	struct idetape_bh *bh;
+-	
+-#if IDETAPE_DEBUG_BUGS
+-	if (tape->chrdev_direction != idetape_direction_write) {
+-		printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
 +
-+module_init(init_e100_ide);
-diff --git a/drivers/ide/h8300/Makefile b/drivers/ide/h8300/Makefile
-new file mode 100644
-index 0000000..5eba16f
---- /dev/null
-+++ b/drivers/ide/h8300/Makefile
-@@ -0,0 +1,2 @@
-+
-+obj-$(CONFIG_IDE_H8300)			+= ide-h8300.o
-diff --git a/drivers/ide/h8300/ide-h8300.c b/drivers/ide/h8300/ide-h8300.c
-index 4a49b5c..520aec0 100644
---- a/drivers/ide/h8300/ide-h8300.c
-+++ b/drivers/ide/h8300/ide-h8300.c
-@@ -1,5 +1,4 @@
- /*
-- * drivers/ide/h8300/ide-h8300.c
-  * H8/300 generic IDE interface
-  */
++	if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
++		printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline,"
++				" but we are not writing.\n");
+ 		return;
+ 	}
+ 	if (tape->merge_stage_size > tape->stage_size) {
+ 		printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
+ 		tape->merge_stage_size = tape->stage_size;
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 	if (tape->merge_stage_size) {
+-		blocks = tape->merge_stage_size / tape->tape_block_size;
+-		if (tape->merge_stage_size % tape->tape_block_size) {
++		blocks = tape->merge_stage_size / tape->blk_size;
++		if (tape->merge_stage_size % tape->blk_size) {
+ 			unsigned int i;
+ 
+ 			blocks++;
+-			i = tape->tape_block_size - tape->merge_stage_size % tape->tape_block_size;
++			i = tape->blk_size - tape->merge_stage_size %
++				tape->blk_size;
+ 			bh = tape->bh->b_reqnext;
+ 			while (bh) {
+ 				atomic_set(&bh->b_count, 0);
+@@ -3318,12 +2415,14 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
+ 			bh = tape->bh;
+ 			while (i) {
+ 				if (bh == NULL) {
+-
+-					printk(KERN_INFO "ide-tape: bug, bh NULL\n");
++					printk(KERN_INFO "ide-tape: bug,"
++							 " bh NULL\n");
+ 					break;
+ 				}
+-				min = min(i, (unsigned int)(bh->b_size - atomic_read(&bh->b_count)));
+-				memset(bh->b_data + atomic_read(&bh->b_count), 0, min);
++				min = min(i, (unsigned int)(bh->b_size -
++						atomic_read(&bh->b_count)));
++				memset(bh->b_data + atomic_read(&bh->b_count),
++						0, min);
+ 				atomic_add(min, &bh->b_count);
+ 				i -= min;
+ 				bh = bh->b_reqnext;
+@@ -3338,16 +2437,15 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
+ 		tape->merge_stage = NULL;
+ 	}
+ 	clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+-	tape->chrdev_direction = idetape_direction_none;
++	tape->chrdev_dir = IDETAPE_DIR_NONE;
  
-@@ -84,11 +83,12 @@ static inline void hwif_setup(ide_hwif_t *hwif)
- 	hwif->INSL  = NULL;
+ 	/*
+-	 *	On the next backup, perform the feedback loop again.
+-	 *	(I don't want to keep sense information between backups,
+-	 *	 as some systems are constantly on, and the system load
+-	 *	 can be totally different on the next backup).
++	 * On the next backup, perform the feedback loop again. (I don't want to
++	 * keep sense information between backups, as some systems are
++	 * constantly on, and the system load can be totally different on the
++	 * next backup).
+ 	 */
+ 	tape->max_stages = tape->min_pipeline;
+-#if IDETAPE_DEBUG_BUGS
+ 	if (tape->first_stage != NULL ||
+ 	    tape->next_stage != NULL ||
+ 	    tape->last_stage != NULL ||
+@@ -3358,60 +2456,64 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
+ 			tape->first_stage, tape->next_stage,
+ 			tape->last_stage, tape->nr_stages);
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */
  }
  
--void __init h8300_ide_init(void)
-+static int __init h8300_ide_init(void)
+-static void idetape_restart_speed_control (ide_drive_t *drive)
++static void idetape_restart_speed_control(ide_drive_t *drive)
  {
- 	hw_regs_t hw;
- 	ide_hwif_t *hwif;
--	int idx;
-+	int index;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	idetape_tape_t *tape = drive->driver_data;
  
- 	if (!request_region(CONFIG_H8300_IDE_BASE, H8300_IDE_GAP*8, "ide-h8300"))
- 		goto out_busy;
-@@ -100,16 +100,28 @@ void __init h8300_ide_init(void)
- 	hw_setup(&hw);
+ 	tape->restart_speed_control_req = 0;
+ 	tape->pipeline_head = 0;
+-	tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0;
+-	tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0;
+-	tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000;
++	tape->controlled_last_pipeline_head = 0;
++	tape->controlled_previous_pipeline_head = 0;
++	tape->uncontrolled_previous_pipeline_head = 0;
++	tape->controlled_pipeline_head_speed = 5000;
++	tape->pipeline_head_speed = 5000;
+ 	tape->uncontrolled_pipeline_head_speed = 0;
+-	tape->controlled_pipeline_head_time = tape->uncontrolled_pipeline_head_time = jiffies;
+-	tape->controlled_previous_head_time = tape->uncontrolled_previous_head_time = jiffies;
++	tape->controlled_pipeline_head_time =
++		tape->uncontrolled_pipeline_head_time = jiffies;
++	tape->controlled_previous_head_time =
++		tape->uncontrolled_previous_head_time = jiffies;
+ }
  
- 	/* register if */
--	idx = ide_register_hw(&hw, NULL, 1, &hwif);
--	if (idx == -1) {
-+	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif == NULL) {
- 		printk(KERN_ERR "ide-h8300: IDE I/F register failed\n");
--		return;
-+		return -ENOENT;
- 	}
+-static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
++static int idetape_init_read(ide_drive_t *drive, int max_stages)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_stage_t *new_stage;
+ 	struct request rq;
+ 	int bytes_read;
+-	int blocks = tape->capabilities.ctl;
++	u16 blocks = *(u16 *)&tape->caps[12];
  
-+	index = hwif->index;
-+	ide_init_port_data(hwif, index);
-+	ide_init_port_hw(hwif, &hw);
- 	hwif_setup(hwif);
--	printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", idx);
--	return;
-+	printk(KERN_INFO "ide%d: H8/300 generic IDE interface\n", index);
-+
-+	idx[0] = index;
-+
-+	ide_device_add(idx, NULL);
-+
-+	return 0;
+ 	/* Initialize read operation */
+-	if (tape->chrdev_direction != idetape_direction_read) {
+-		if (tape->chrdev_direction == idetape_direction_write) {
++	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
++		if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+ 			idetape_empty_write_pipeline(drive);
+ 			idetape_flush_tape_buffers(drive);
+ 		}
+-#if IDETAPE_DEBUG_BUGS
+ 		if (tape->merge_stage || tape->merge_stage_size) {
+-			printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n");
++			printk(KERN_ERR "ide-tape: merge_stage_size should be"
++					 " 0 now\n");
+ 			tape->merge_stage_size = 0;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+-		if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
++		tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
++		if (!tape->merge_stage)
+ 			return -ENOMEM;
+-		tape->chrdev_direction = idetape_direction_read;
++		tape->chrdev_dir = IDETAPE_DIR_READ;
  
- out_busy:
- 	printk(KERN_ERR "ide-h8300: IDE I/F resource already used.\n");
-+
-+	return -EBUSY;
+ 		/*
+-		 *	Issue a read 0 command to ensure that DSC handshake
+-		 *	is switched from completion mode to buffer available
+-		 *	mode.
+-		 *	No point in issuing this if DSC overlap isn't supported,
+-		 *	some drives (Seagate STT3401A) will return an error.
++		 * Issue a read 0 command to ensure that DSC handshake is
++		 * switched from completion mode to buffer available mode.
++		 * No point in issuing this if DSC overlap isn't supported, some
++		 * drives (Seagate STT3401A) will return an error.
+ 		 */
+ 		if (drive->dsc_overlap) {
+-			bytes_read = idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 0, tape->merge_stage->bh);
++			bytes_read = idetape_queue_rw_tail(drive,
++							REQ_IDETAPE_READ, 0,
++							tape->merge_stage->bh);
+ 			if (bytes_read < 0) {
+ 				__idetape_kfree_stage(tape->merge_stage);
+ 				tape->merge_stage = NULL;
+-				tape->chrdev_direction = idetape_direction_none;
++				tape->chrdev_dir = IDETAPE_DIR_NONE;
+ 				return bytes_read;
+ 			}
+ 		}
+@@ -3419,8 +2521,9 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
+ 	if (tape->restart_speed_control_req)
+ 		idetape_restart_speed_control(drive);
+ 	idetape_init_rq(&rq, REQ_IDETAPE_READ);
+-	rq.sector = tape->first_frame_position;
+-	rq.nr_sectors = rq.current_nr_sectors = blocks;
++	rq.sector = tape->first_frame;
++	rq.nr_sectors = blocks;
++	rq.current_nr_sectors = blocks;
+ 	if (!test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags) &&
+ 	    tape->nr_stages < max_stages) {
+ 		new_stage = idetape_kmalloc_stage(tape);
+@@ -3438,50 +2541,43 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
+ 			tape->insert_time = jiffies;
+ 			tape->insert_size = 0;
+ 			tape->insert_speed = 0;
+-			idetape_insert_pipeline_into_queue(drive);
++			idetape_plug_pipeline(drive);
+ 		}
+ 	}
+ 	return 0;
  }
-+
-+module_init(h8300_ide_init);
-diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c
-index 899d565..25aaeae 100644
---- a/drivers/ide/ide-acpi.c
-+++ b/drivers/ide/ide-acpi.c
-@@ -1,5 +1,4 @@
+ 
  /*
-- * ide-acpi.c
-  * Provides ACPI support for IDE drives.
-  *
-  * Copyright (C) 2005 Intel Corp.
-@@ -40,7 +39,6 @@ struct GTM_buffer {
- };
+- *	idetape_add_chrdev_read_request is called from idetape_chrdev_read
+- *	to service a character device read request and add read-ahead
+- *	requests to our pipeline.
++ * Called from idetape_chrdev_read() to service a character device read request
++ * and add read-ahead requests to our pipeline.
+  */
+-static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
++static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	unsigned long flags;
+ 	struct request *rq_ptr;
+ 	int bytes_read;
  
- struct ide_acpi_drive_link {
--	ide_drive_t	*drive;
- 	acpi_handle	 obj_handle;
- 	u8		 idbuff[512];
- };
-@@ -281,16 +279,6 @@ static int do_drive_get_GTF(ide_drive_t *drive,
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_add_chrdev_read_request, %d blocks\n", blocks);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks);
  
- 	port = hwif->channel ? drive->dn - 2: drive->dn;
+-	/*
+-	 * If we are at a filemark, return a read length of 0
+-	 */
++	/* If we are at a filemark, return a read length of 0 */
+ 	if (test_bit(IDETAPE_FILEMARK, &tape->flags))
+ 		return 0;
  
--	if (!drive->acpidata) {
--		if (port == 0) {
--			drive->acpidata = &hwif->acpidata->master;
--			hwif->acpidata->master.drive = drive;
--		} else {
--			drive->acpidata = &hwif->acpidata->slave;
--			hwif->acpidata->slave.drive = drive;
--		}
--	}
--
- 	DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n",
- 		 hwif->name, dev->bus_id, port, hwif->channel);
+-	/*
+-	 * Wait for the next block to be available at the head
+-	 * of the pipeline
+-	 */
+-	idetape_initiate_read(drive, tape->max_stages);
++	/* Wait for the next block to reach the head of the pipeline. */
++	idetape_init_read(drive, tape->max_stages);
+ 	if (tape->first_stage == NULL) {
+ 		if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags))
+ 			return 0;
+-		return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, tape->merge_stage->bh);
++		return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks,
++					tape->merge_stage->bh);
+ 	}
+ 	idetape_wait_first_stage(drive);
+ 	rq_ptr = &tape->first_stage->rq;
+-	bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
+-	rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0;
+-
++	bytes_read = tape->blk_size * (rq_ptr->nr_sectors -
++					rq_ptr->current_nr_sectors);
++	rq_ptr->nr_sectors = 0;
++	rq_ptr->current_nr_sectors = 0;
  
-@@ -383,27 +371,19 @@ static int taskfile_load_raw(ide_drive_t *drive,
- 	       gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+ 	if (rq_ptr->errors == IDETAPE_ERROR_EOD)
+ 		return 0;
+@@ -3489,48 +2585,46 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
+ 		idetape_switch_buffers(tape, tape->first_stage);
+ 		if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK)
+ 			set_bit(IDETAPE_FILEMARK, &tape->flags);
+-		spin_lock_irqsave(&tape->spinlock, flags);
++		spin_lock_irqsave(&tape->lock, flags);
+ 		idetape_remove_stage_head(drive);
+-		spin_unlock_irqrestore(&tape->spinlock, flags);
++		spin_unlock_irqrestore(&tape->lock, flags);
+ 		tape->pipeline_head++;
+-#if USE_IOTRACE
+-		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
+-#endif
+-		calculate_speeds(drive);
++		idetape_calculate_speeds(drive);
+ 	}
+-#if IDETAPE_DEBUG_BUGS
+-	if (bytes_read > blocks * tape->tape_block_size) {
+-		printk(KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
+-		bytes_read = blocks * tape->tape_block_size;
++	if (bytes_read > blocks * tape->blk_size) {
++		printk(KERN_ERR "ide-tape: bug: trying to return more bytes"
++				" than requested\n");
++		bytes_read = blocks * tape->blk_size;
+ 	}
+-#endif /* IDETAPE_DEBUG_BUGS */
+ 	return (bytes_read);
+ }
  
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.command_type = IDE_DRIVE_TASK_NO_DATA;
--	args.data_phase   = TASKFILE_NO_DATA;
--	args.handler      = &task_no_data_intr;
+-static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
++static void idetape_pad_zeros(ide_drive_t *drive, int bcount)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	struct idetape_bh *bh;
+ 	int blocks;
+-	
++
+ 	while (bcount) {
+ 		unsigned int count;
  
- 	/* convert gtf to IDE Taskfile */
--	args.tfRegister[1] = gtf->tfa[0];	/* 0x1f1 */
--	args.tfRegister[2] = gtf->tfa[1];	/* 0x1f2 */
--	args.tfRegister[3] = gtf->tfa[2];	/* 0x1f3 */
--	args.tfRegister[4] = gtf->tfa[3];	/* 0x1f4 */
--	args.tfRegister[5] = gtf->tfa[4];	/* 0x1f5 */
--	args.tfRegister[6] = gtf->tfa[5];	/* 0x1f6 */
--	args.tfRegister[7] = gtf->tfa[6];	/* 0x1f7 */
-+	memcpy(&args.tf_array[7], &gtf->tfa, 7);
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ 		bh = tape->merge_stage->bh;
+ 		count = min(tape->stage_size, bcount);
+ 		bcount -= count;
+-		blocks = count / tape->tape_block_size;
++		blocks = count / tape->blk_size;
+ 		while (count) {
+-			atomic_set(&bh->b_count, min(count, (unsigned int)bh->b_size));
++			atomic_set(&bh->b_count,
++				   min(count, (unsigned int)bh->b_size));
+ 			memset(bh->b_data, 0, atomic_read(&bh->b_count));
+ 			count -= atomic_read(&bh->b_count);
+ 			bh = bh->b_reqnext;
+ 		}
+-		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, tape->merge_stage->bh);
++		idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks,
++				      tape->merge_stage->bh);
+ 	}
+ }
  
- 	if (ide_noacpitfs) {
- 		DEBPRINT("_GTF execution disabled\n");
- 		return err;
+-static int idetape_pipeline_size (ide_drive_t *drive)
++static int idetape_pipeline_size(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_stage_t *stage;
+@@ -3541,9 +2635,10 @@ static int idetape_pipeline_size (ide_drive_t *drive)
+ 	stage = tape->first_stage;
+ 	while (stage != NULL) {
+ 		rq = &stage->rq;
+-		size += tape->tape_block_size * (rq->nr_sectors-rq->current_nr_sectors);
++		size += tape->blk_size * (rq->nr_sectors -
++				rq->current_nr_sectors);
+ 		if (rq->errors == IDETAPE_ERROR_FILEMARK)
+-			size += tape->tape_block_size;
++			size += tape->blk_size;
+ 		stage = stage->next;
  	}
+ 	size += tape->merge_stage_size;
+@@ -3551,20 +2646,18 @@ static int idetape_pipeline_size (ide_drive_t *drive)
+ }
  
--	err = ide_raw_taskfile(drive, &args, NULL);
-+	err = ide_no_data_taskfile(drive, &args);
- 	if (err)
--		printk(KERN_ERR "%s: ide_raw_taskfile failed: %u\n",
-+		printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n",
- 		       __FUNCTION__, err);
+ /*
+- *	Rewinds the tape to the Beginning Of the current Partition (BOP).
+- *
+- *	We currently support only one partition.
+- */ 
+-static int idetape_rewind_tape (ide_drive_t *drive)
++ * Rewinds the tape to the Beginning Of the current Partition (BOP). We
++ * currently support only one partition.
++ */
++static int idetape_rewind_tape(ide_drive_t *drive)
+ {
+ 	int retval;
+ 	idetape_pc_t pc;
+-#if IDETAPE_DEBUG_LOG
+-	idetape_tape_t *tape = drive->driver_data;
+-	if (tape->debug_level >= 2)
+-		printk(KERN_INFO "ide-tape: Reached idetape_rewind_tape\n");
+-#endif /* IDETAPE_DEBUG_LOG */	
+-	
++	idetape_tape_t *tape;
++	tape = drive->driver_data;
++
++	debug_log(DBG_SENSE, "Enter %s\n", __func__);
++
+ 	idetape_create_rewind_cmd(drive, &pc);
+ 	retval = idetape_queue_pc_tail(drive, &pc);
+ 	if (retval)
+@@ -3577,71 +2670,66 @@ static int idetape_rewind_tape (ide_drive_t *drive)
+ 	return 0;
+ }
  
- 	return err;
-@@ -503,7 +483,6 @@ int ide_acpi_exec_tfs(ide_drive_t *drive)
+-/*
+- *	Our special ide-tape ioctl's.
+- *
+- *	Currently there aren't any ioctl's.
+- *	mtio.h compatible commands should be issued to the character device
+- *	interface.
+- */
+-static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg)
++/* mtio.h compatible commands should be issued to the chrdev interface. */
++static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd,
++				unsigned long arg)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+-	idetape_config_t config;
+ 	void __user *argp = (void __user *)arg;
  
- 	return ret;
+-#if IDETAPE_DEBUG_LOG	
+-	if (tape->debug_level >= 4)
+-		printk(KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n");
+-#endif /* IDETAPE_DEBUG_LOG */
++	struct idetape_config {
++		int dsc_rw_frequency;
++		int dsc_media_access_frequency;
++		int nr_stages;
++	} config;
++
++	debug_log(DBG_PROCS, "Enter %s\n", __func__);
++
+ 	switch (cmd) {
+-		case 0x0340:
+-			if (copy_from_user(&config, argp, sizeof (idetape_config_t)))
+-				return -EFAULT;
+-			tape->best_dsc_rw_frequency = config.dsc_rw_frequency;
+-			tape->max_stages = config.nr_stages;
+-			break;
+-		case 0x0350:
+-			config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency;
+-			config.nr_stages = tape->max_stages; 
+-			if (copy_to_user(argp, &config, sizeof (idetape_config_t)))
+-				return -EFAULT;
+-			break;
+-		default:
+-			return -EIO;
++	case 0x0340:
++		if (copy_from_user(&config, argp, sizeof(config)))
++			return -EFAULT;
++		tape->best_dsc_rw_freq = config.dsc_rw_frequency;
++		tape->max_stages = config.nr_stages;
++		break;
++	case 0x0350:
++		config.dsc_rw_frequency = (int) tape->best_dsc_rw_freq;
++		config.nr_stages = tape->max_stages;
++		if (copy_to_user(argp, &config, sizeof(config)))
++			return -EFAULT;
++		break;
++	default:
++		return -EIO;
+ 	}
+ 	return 0;
  }
--EXPORT_SYMBOL_GPL(ide_acpi_exec_tfs);
  
- /**
-  * ide_acpi_get_timing - get the channel (controller) timings
-@@ -589,7 +568,6 @@ void ide_acpi_get_timing(ide_hwif_t *hwif)
+ /*
+- *	idetape_space_over_filemarks is now a bit more complicated than just
+- *	passing the command to the tape since we may have crossed some
+- *	filemarks during our pipelined read-ahead mode.
+- *
+- *	As a minor side effect, the pipeline enables us to support MTFSFM when
+- *	the filemark is in our internal pipeline even if the tape doesn't
+- *	support spacing over filemarks in the reverse direction.
++ * The function below is now a bit more complicated than just passing the
++ * command to the tape since we may have crossed some filemarks during our
++ * pipelined read-ahead mode. As a minor side effect, the pipeline enables us to
++ * support MTFSFM when the filemark is in our internal pipeline even if the tape
++ * doesn't support spacing over filemarks in the reverse direction.
+  */
+-static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_count)
++static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op,
++					int mt_count)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t pc;
+ 	unsigned long flags;
+-	int retval,count=0;
++	int retval, count = 0;
++	int sprev = !!(tape->caps[4] & 0x20);
  
- 	kfree(output.pointer);
- }
--EXPORT_SYMBOL_GPL(ide_acpi_get_timing);
+ 	if (mt_count == 0)
+ 		return 0;
+ 	if (MTBSF == mt_op || MTBSFM == mt_op) {
+-		if (!tape->capabilities.sprev)
++		if (!sprev)
+ 			return -EIO;
+-		mt_count = - mt_count;
++		mt_count = -mt_count;
+ 	}
  
- /**
-  * ide_acpi_push_timing - set the channel (controller) timings
-@@ -643,7 +621,6 @@ void ide_acpi_push_timing(ide_hwif_t *hwif)
+-	if (tape->chrdev_direction == idetape_direction_read) {
+-		/*
+-		 *	We have a read-ahead buffer. Scan it for crossed
+-		 *	filemarks.
+-		 */
++	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
++		/* its a read-ahead buffer, scan it for crossed filemarks. */
+ 		tape->merge_stage_size = 0;
+ 		if (test_and_clear_bit(IDETAPE_FILEMARK, &tape->flags))
+ 			++count;
+@@ -3651,24 +2739,27 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
+ 					set_bit(IDETAPE_FILEMARK, &tape->flags);
+ 				return 0;
+ 			}
+-			spin_lock_irqsave(&tape->spinlock, flags);
++			spin_lock_irqsave(&tape->lock, flags);
+ 			if (tape->first_stage == tape->active_stage) {
+ 				/*
+-				 *	We have reached the active stage in the read pipeline.
+-				 *	There is no point in allowing the drive to continue
+-				 *	reading any farther, so we stop the pipeline.
++				 * We have reached the active stage in the read
++				 * pipeline. There is no point in allowing the
++				 * drive to continue reading any farther, so we
++				 * stop the pipeline.
+ 				 *
+-				 *	This section should be moved to a separate subroutine,
+-				 *	because a similar function is performed in
+-				 *	__idetape_discard_read_pipeline(), for example.
++				 * This section should be moved to a separate
++				 * subroutine because similar operations are
++				 * done in __idetape_discard_read_pipeline(),
++				 * for example.
+ 				 */
+ 				tape->next_stage = NULL;
+-				spin_unlock_irqrestore(&tape->spinlock, flags);
++				spin_unlock_irqrestore(&tape->lock, flags);
+ 				idetape_wait_first_stage(drive);
+ 				tape->next_stage = tape->first_stage->next;
+ 			} else
+-				spin_unlock_irqrestore(&tape->spinlock, flags);
+-			if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
++				spin_unlock_irqrestore(&tape->lock, flags);
++			if (tape->first_stage->rq.errors ==
++					IDETAPE_ERROR_FILEMARK)
+ 				++count;
+ 			idetape_remove_stage_head(drive);
+ 		}
+@@ -3676,157 +2767,156 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
+ 	}
+ 
+ 	/*
+-	 *	The filemark was not found in our internal pipeline.
+-	 *	Now we can issue the space command.
++	 * The filemark was not found in our internal pipeline;	now we can issue
++	 * the space command.
+ 	 */
+ 	switch (mt_op) {
+-		case MTFSF:
+-		case MTBSF:
+-			idetape_create_space_cmd(&pc,mt_count-count,IDETAPE_SPACE_OVER_FILEMARK);
+-			return (idetape_queue_pc_tail(drive, &pc));
+-		case MTFSFM:
+-		case MTBSFM:
+-			if (!tape->capabilities.sprev)
+-				return (-EIO);
+-			retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
+-			if (retval) return (retval);
+-			count = (MTBSFM == mt_op ? 1 : -1);
+-			return (idetape_space_over_filemarks(drive, MTFSF, count));
+-		default:
+-			printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",mt_op);
+-			return (-EIO);
++	case MTFSF:
++	case MTBSF:
++		idetape_create_space_cmd(&pc, mt_count - count,
++					 IDETAPE_SPACE_OVER_FILEMARK);
++		return idetape_queue_pc_tail(drive, &pc);
++	case MTFSFM:
++	case MTBSFM:
++		if (!sprev)
++			return -EIO;
++		retval = idetape_space_over_filemarks(drive, MTFSF,
++						      mt_count - count);
++		if (retval)
++			return retval;
++		count = (MTBSFM == mt_op ? 1 : -1);
++		return idetape_space_over_filemarks(drive, MTFSF, count);
++	default:
++		printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",
++				mt_op);
++		return -EIO;
  	}
- 	DEBPRINT("_STM status: %d\n", status);
  }
--EXPORT_SYMBOL_GPL(ide_acpi_push_timing);
  
- /**
-  * ide_acpi_set_state - set the channel power state
-@@ -697,11 +674,6 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on)
+-
+ /*
+- *	Our character device read / write functions.
++ * Our character device read / write functions.
+  *
+- *	The tape is optimized to maximize throughput when it is transferring
+- *	an integral number of the "continuous transfer limit", which is
+- *	a parameter of the specific tape (26 KB on my particular tape).
+- *      (32 kB for Onstream)
++ * The tape is optimized to maximize throughput when it is transferring an
++ * integral number of the "continuous transfer limit", which is a parameter of
++ * the specific tape (26kB on my particular tape, 32kB for Onstream).
+  *
+- *	As of version 1.3 of the driver, the character device provides an
+- *	abstract continuous view of the media - any mix of block sizes (even 1
+- *	byte) on the same backup/restore procedure is supported. The driver
+- *	will internally convert the requests to the recommended transfer unit,
+- *	so that an unmatch between the user's block size to the recommended
+- *	size will only result in a (slightly) increased driver overhead, but
+- *	will no longer hit performance.
+- *      This is not applicable to Onstream.
++ * As of version 1.3 of the driver, the character device provides an abstract
++ * continuous view of the media - any mix of block sizes (even 1 byte) on the
++ * same backup/restore procedure is supported. The driver will internally
++ * convert the requests to the recommended transfer unit, so that an unmatch
++ * between the user's block size to the recommended size will only result in a
++ * (slightly) increased driver overhead, but will no longer hit performance.
++ * This is not applicable to Onstream.
   */
- void ide_acpi_init(ide_hwif_t *hwif)
+-static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
+-				    size_t count, loff_t *ppos)
++static ssize_t idetape_chrdev_read(struct file *file, char __user *buf,
++				   size_t count, loff_t *ppos)
  {
--	int unit;
--	int			err;
--	struct ide_acpi_drive_link	*master;
--	struct ide_acpi_drive_link	*slave;
--
- 	ide_acpi_blacklist();
+ 	struct ide_tape_obj *tape = ide_tape_f(file);
+ 	ide_drive_t *drive = tape->drive;
+-	ssize_t bytes_read,temp, actually_read = 0, rc;
++	ssize_t bytes_read, temp, actually_read = 0, rc;
+ 	ssize_t ret = 0;
++	u16 ctl = *(u16 *)&tape->caps[12];
  
- 	hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL);
-@@ -713,40 +685,38 @@ void ide_acpi_init(ide_hwif_t *hwif)
- 		DEBPRINT("no ACPI object for %s found\n", hwif->name);
- 		kfree(hwif->acpidata);
- 		hwif->acpidata = NULL;
--		return;
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 3)
+-		printk(KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
+ 
+-	if (tape->chrdev_direction != idetape_direction_read) {
++	if (tape->chrdev_dir != IDETAPE_DIR_READ) {
+ 		if (test_bit(IDETAPE_DETECT_BS, &tape->flags))
+-			if (count > tape->tape_block_size &&
+-			    (count % tape->tape_block_size) == 0)
+-				tape->user_bs_factor = count / tape->tape_block_size;
++			if (count > tape->blk_size &&
++			    (count % tape->blk_size) == 0)
++				tape->user_bs_factor = count / tape->blk_size;
  	}
-+}
-+
-+void ide_acpi_port_init_devices(ide_hwif_t *hwif)
-+{
-+	ide_drive_t *drive;
-+	int i, err;
+-	if ((rc = idetape_initiate_read(drive, tape->max_stages)) < 0)
++	rc = idetape_init_read(drive, tape->max_stages);
++	if (rc < 0)
+ 		return rc;
+ 	if (count == 0)
+ 		return (0);
+ 	if (tape->merge_stage_size) {
+-		actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count);
+-		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read))
++		actually_read = min((unsigned int)(tape->merge_stage_size),
++				    (unsigned int)count);
++		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
++					       actually_read))
+ 			ret = -EFAULT;
+ 		buf += actually_read;
+ 		tape->merge_stage_size -= actually_read;
+ 		count -= actually_read;
+ 	}
+ 	while (count >= tape->stage_size) {
+-		bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
++		bytes_read = idetape_add_chrdev_read_request(drive, ctl);
+ 		if (bytes_read <= 0)
+ 			goto finish;
+-		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
++		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
++					       bytes_read))
+ 			ret = -EFAULT;
+ 		buf += bytes_read;
+ 		count -= bytes_read;
+ 		actually_read += bytes_read;
+ 	}
+ 	if (count) {
+-		bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
++		bytes_read = idetape_add_chrdev_read_request(drive, ctl);
+ 		if (bytes_read <= 0)
+ 			goto finish;
+ 		temp = min((unsigned long)count, (unsigned long)bytes_read);
+-		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp))
++		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage,
++					       temp))
+ 			ret = -EFAULT;
+ 		actually_read += temp;
+ 		tape->merge_stage_size = bytes_read-temp;
+ 	}
+ finish:
+ 	if (!actually_read && test_bit(IDETAPE_FILEMARK, &tape->flags)) {
+-#if IDETAPE_DEBUG_LOG
+-		if (tape->debug_level >= 2)
+-			printk(KERN_INFO "ide-tape: %s: spacing over filemark\n", tape->name);
+-#endif
++		debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name);
 +
-+	if (hwif->acpidata == NULL)
-+		return;
- 
- 	/*
- 	 * The ACPI spec mandates that we send information
- 	 * for both drives, regardless whether they are connected
- 	 * or not.
- 	 */
--	hwif->acpidata->master.drive = &hwif->drives[0];
- 	hwif->drives[0].acpidata = &hwif->acpidata->master;
--	master = &hwif->acpidata->master;
--
--	hwif->acpidata->slave.drive = &hwif->drives[1];
- 	hwif->drives[1].acpidata = &hwif->acpidata->slave;
--	slave = &hwif->acpidata->slave;
--
+ 		idetape_space_over_filemarks(drive, MTFSF, 1);
+ 		return 0;
+ 	}
  
- 	/*
- 	 * Send IDENTIFY for each drive
- 	 */
--	if (master->drive->present) {
--		err = taskfile_lib_get_identify(master->drive, master->idbuff);
--		if (err) {
--			DEBPRINT("identify device %s failed (%d)\n",
--				 master->drive->name, err);
--		}
--	}
-+	for (i = 0; i < MAX_DRIVES; i++) {
-+		drive = &hwif->drives[i];
-+
-+		if (!drive->present)
-+			continue;
+-	return (ret) ? ret : actually_read;
++	return ret ? ret : actually_read;
+ }
  
--	if (slave->drive->present) {
--		err = taskfile_lib_get_identify(slave->drive, slave->idbuff);
--		if (err) {
-+		err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff);
-+		if (err)
- 			DEBPRINT("identify device %s failed (%d)\n",
--				 slave->drive->name, err);
--		}
-+				 drive->name, err);
- 	}
+-static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
++static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf,
+ 				     size_t count, loff_t *ppos)
+ {
+ 	struct ide_tape_obj *tape = ide_tape_f(file);
+ 	ide_drive_t *drive = tape->drive;
+ 	ssize_t actually_written = 0;
+ 	ssize_t ret = 0;
++	u16 ctl = *(u16 *)&tape->caps[12];
  
- 	if (ide_noacpionboot) {
-@@ -762,13 +732,11 @@ void ide_acpi_init(ide_hwif_t *hwif)
- 	ide_acpi_get_timing(hwif);
- 	ide_acpi_push_timing(hwif);
+ 	/* The drive is write protected. */
+ 	if (tape->write_prot)
+ 		return -EACCES;
  
--	for (unit = 0; unit < MAX_DRIVES; ++unit) {
--		ide_drive_t *drive = &hwif->drives[unit];
-+	for (i = 0; i < MAX_DRIVES; i++) {
-+		drive = &hwif->drives[i];
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 3)
+-		printk(KERN_INFO "ide-tape: Reached idetape_chrdev_write, "
+-			"count %Zd\n", count);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count);
+ 
+ 	/* Initialize write operation */
+-	if (tape->chrdev_direction != idetape_direction_write) {
+-		if (tape->chrdev_direction == idetape_direction_read)
++	if (tape->chrdev_dir != IDETAPE_DIR_WRITE) {
++		if (tape->chrdev_dir == IDETAPE_DIR_READ)
+ 			idetape_discard_read_pipeline(drive, 1);
+-#if IDETAPE_DEBUG_BUGS
+ 		if (tape->merge_stage || tape->merge_stage_size) {
+ 			printk(KERN_ERR "ide-tape: merge_stage_size "
+ 				"should be 0 now\n");
+ 			tape->merge_stage_size = 0;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+-		if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
++		tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0);
++		if (!tape->merge_stage)
+ 			return -ENOMEM;
+-		tape->chrdev_direction = idetape_direction_write;
++		tape->chrdev_dir = IDETAPE_DIR_WRITE;
+ 		idetape_init_merge_stage(tape);
  
--		if (drive->present) {
-+		if (drive->present)
- 			/* Execute ACPI startup code */
- 			ide_acpi_exec_tfs(drive);
--		}
+ 		/*
+-		 *	Issue a write 0 command to ensure that DSC handshake
+-		 *	is switched from completion mode to buffer available
+-		 *	mode.
+-		 *	No point in issuing this if DSC overlap isn't supported,
+-		 *	some drives (Seagate STT3401A) will return an error.
++		 * Issue a write 0 command to ensure that DSC handshake is
++		 * switched from completion mode to buffer available mode. No
++		 * point in issuing this if DSC overlap isn't supported, some
++		 * drives (Seagate STT3401A) will return an error.
+ 		 */
+ 		if (drive->dsc_overlap) {
+-			ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
++			ssize_t retval = idetape_queue_rw_tail(drive,
++							REQ_IDETAPE_WRITE, 0,
++							tape->merge_stage->bh);
+ 			if (retval < 0) {
+ 				__idetape_kfree_stage(tape->merge_stage);
+ 				tape->merge_stage = NULL;
+-				tape->chrdev_direction = idetape_direction_none;
++				tape->chrdev_dir = IDETAPE_DIR_NONE;
+ 				return retval;
+ 			}
+ 		}
+@@ -3836,14 +2926,15 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
+ 	if (tape->restart_speed_control_req)
+ 		idetape_restart_speed_control(drive);
+ 	if (tape->merge_stage_size) {
+-#if IDETAPE_DEBUG_BUGS
+ 		if (tape->merge_stage_size >= tape->stage_size) {
+-			printk(KERN_ERR "ide-tape: bug: merge buffer too big\n");
++			printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
+ 			tape->merge_stage_size = 0;
+ 		}
+-#endif /* IDETAPE_DEBUG_BUGS */
+-		actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
+-		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
++		actually_written = min((unsigned int)
++				(tape->stage_size - tape->merge_stage_size),
++				(unsigned int)count);
++		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
++						 actually_written))
+ 				ret = -EFAULT;
+ 		buf += actually_written;
+ 		tape->merge_stage_size += actually_written;
+@@ -3852,32 +2943,34 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
+ 		if (tape->merge_stage_size == tape->stage_size) {
+ 			ssize_t retval;
+ 			tape->merge_stage_size = 0;
+-			retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
++			retval = idetape_add_chrdev_write_request(drive, ctl);
+ 			if (retval <= 0)
+ 				return (retval);
+ 		}
+ 	}
+ 	while (count >= tape->stage_size) {
+ 		ssize_t retval;
+-		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size))
++		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
++						 tape->stage_size))
+ 			ret = -EFAULT;
+ 		buf += tape->stage_size;
+ 		count -= tape->stage_size;
+-		retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
++		retval = idetape_add_chrdev_write_request(drive, ctl);
+ 		actually_written += tape->stage_size;
+ 		if (retval <= 0)
+ 			return (retval);
  	}
+ 	if (count) {
+ 		actually_written += count;
+-		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count))
++		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf,
++						 count))
+ 			ret = -EFAULT;
+ 		tape->merge_stage_size += count;
+ 	}
+-	return (ret) ? ret : actually_written;
++	return ret ? ret : actually_written;
  }
--EXPORT_SYMBOL_GPL(ide_acpi_init);
-diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
-index c7d77f0..ee4d458 100644
---- a/drivers/ide/ide-cd.c
-+++ b/drivers/ide/ide-cd.c
-@@ -1,14 +1,14 @@
+ 
+-static int idetape_write_filemark (ide_drive_t *drive)
++static int idetape_write_filemark(ide_drive_t *drive)
+ {
+ 	idetape_pc_t pc;
+ 
+@@ -3891,265 +2984,224 @@ static int idetape_write_filemark (ide_drive_t *drive)
+ }
+ 
  /*
-- * linux/drivers/ide/ide-cd.c
-+ * ATAPI CD-ROM driver.
-  *
-- * Copyright (C) 1994, 1995, 1996  scott snyder  <snyder at fnald0.fnal.gov>
-- * Copyright (C) 1996-1998  Erik Andersen <andersee at debian.org>
-- * Copyright (C) 1998-2000  Jens Axboe <axboe at suse.de>
-+ * Copyright (C) 1994-1996   Scott Snyder <snyder at fnald0.fnal.gov>
-+ * Copyright (C) 1996-1998   Erik Andersen <andersee at debian.org>
-+ * Copyright (C) 1998-2000   Jens Axboe <axboe at suse.de>
-+ * Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
-  *
-  * May be copied or modified under the terms of the GNU General Public
-  * License.  See linux/COPYING for more information.
+- *	idetape_mtioctop is called from idetape_chrdev_ioctl when
+- *	the general mtio MTIOCTOP ioctl is requested.
+- *
+- *	We currently support the following mtio.h operations:
+- *
+- *	MTFSF	-	Space over mt_count filemarks in the positive direction.
+- *			The tape is positioned after the last spaced filemark.
++ * Called from idetape_chrdev_ioctl when the general mtio MTIOCTOP ioctl is
++ * requested.
   *
-- * ATAPI CD-ROM driver.  To be used with ide.c.
-  * See Documentation/cdrom/ide-cd for usage information.
+- *	MTFSFM	-	Same as MTFSF, but the tape is positioned before the
+- *			last filemark.
++ * Note: MTBSF and MTBSFM are not supported when the tape doesn't support
++ * spacing over filemarks in the reverse direction. In this case, MTFSFM is also
++ * usually not supported (it is supported in the rare case in which we crossed
++ * the filemark during our read-ahead pipelined operation mode).
   *
-  * Suggestions are welcome. Patches that work are more welcome though. ;-)
-@@ -19,287 +19,11 @@
-  * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
-  * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
+- *	MTBSF	-	Steps background over mt_count filemarks, tape is
+- *			positioned before the last filemark.
++ * The following commands are currently not supported:
   *
-- * Drives that deviate from these standards will be accommodated as much
-- * as possible via compile time or command-line options.  Since I only have
-- * a few drives, you generally need to send me patches...
+- *	MTBSFM	-	Like MTBSF, only tape is positioned after the last filemark.
 - *
-- * ----------------------------------
-- * TO DO LIST:
-- * -Make it so that Pioneer CD DR-A24X and friends don't get screwed up on
-- *   boot
+- *	Note:
 - *
-- * ----------------------------------
-- * 1.00  Oct 31, 1994 -- Initial version.
-- * 1.01  Nov  2, 1994 -- Fixed problem with starting request in
-- *                       cdrom_check_status.
-- * 1.03  Nov 25, 1994 -- leaving unmask_intr[] as a user-setting (as for disks)
-- * (from mlord)       -- minor changes to cdrom_setup()
-- *                    -- renamed ide_dev_s to ide_drive_t, enable irq on command
-- * 2.00  Nov 27, 1994 -- Generalize packet command interface;
-- *                       add audio ioctls.
-- * 2.01  Dec  3, 1994 -- Rework packet command interface to handle devices
-- *                       which send an interrupt when ready for a command.
-- * 2.02  Dec 11, 1994 -- Cache the TOC in the driver.
-- *                       Don't use SCMD_PLAYAUDIO_TI; it's not included
-- *                       in the current version of ATAPI.
-- *                       Try to use LBA instead of track or MSF addressing
-- *                       when possible.
-- *                       Don't wait for READY_STAT.
-- * 2.03  Jan 10, 1995 -- Rewrite block read routines to handle block sizes
-- *                       other than 2k and to move multiple sectors in a
-- *                       single transaction.
-- * 2.04  Apr 21, 1995 -- Add work-around for Creative Labs CD220E drives.
-- *                       Thanks to Nick Saw <cwsaw at pts7.pts.mot.com> for
-- *                       help in figuring this out.  Ditto for Acer and
-- *                       Aztech drives, which seem to have the same problem.
-- * 2.04b May 30, 1995 -- Fix to match changes in ide.c version 3.16 -ml
-- * 2.05  Jun  8, 1995 -- Don't attempt to retry after an illegal request
-- *                        or data protect error.
-- *                       Use HWIF and DEV_HWIF macros as in ide.c.
-- *                       Always try to do a request_sense after
-- *                        a failed command.
-- *                       Include an option to give textual descriptions
-- *                        of ATAPI errors.
-- *                       Fix a bug in handling the sector cache which
-- *                        showed up if the drive returned data in 512 byte
-- *                        blocks (like Pioneer drives).  Thanks to
-- *                        Richard Hirst <srh at gpt.co.uk> for diagnosing this.
-- *                       Properly supply the page number field in the
-- *                        MODE_SELECT command.
-- *                       PLAYAUDIO12 is broken on the Aztech; work around it.
-- * 2.05x Aug 11, 1995 -- lots of data structure renaming/restructuring in ide.c
-- *                       (my apologies to Scott, but now ide-cd.c is independent)
-- * 3.00  Aug 22, 1995 -- Implement CDROMMULTISESSION ioctl.
-- *                       Implement CDROMREADAUDIO ioctl (UNTESTED).
-- *                       Use input_ide_data() and output_ide_data().
-- *                       Add door locking.
-- *                       Fix usage count leak in cdrom_open, which happened
-- *                        when a read-write mount was attempted.
-- *                       Try to load the disk on open.
-- *                       Implement CDROMEJECT_SW ioctl (off by default).
-- *                       Read total cdrom capacity during open.
-- *                       Rearrange logic in cdrom_decode_status.  Issue
-- *                        request sense commands for failed packet commands
-- *                        from here instead of from cdrom_queue_packet_command.
-- *                        Fix a race condition in retrieving error information.
-- *                       Suppress printing normal unit attention errors and
-- *                        some drive not ready errors.
-- *                       Implement CDROMVOLREAD ioctl.
-- *                       Implement CDROMREADMODE1/2 ioctls.
-- *                       Fix race condition in setting up interrupt handlers
-- *                        when the `serialize' option is used.
-- * 3.01  Sep  2, 1995 -- Fix ordering of reenabling interrupts in
-- *                        cdrom_queue_request.
-- *                       Another try at using ide_[input,output]_data.
-- * 3.02  Sep 16, 1995 -- Stick total disk capacity in partition table as well.
-- *                       Make VERBOSE_IDE_CD_ERRORS dump failed command again.
-- *                       Dump out more information for ILLEGAL REQUEST errs.
-- *                       Fix handling of errors occurring before the
-- *                        packet command is transferred.
-- *                       Fix transfers with odd bytelengths.
-- * 3.03  Oct 27, 1995 -- Some Creative drives have an id of just `CD'.
-- *                       `DCI-2S10' drives are broken too.
-- * 3.04  Nov 20, 1995 -- So are Vertos drives.
-- * 3.05  Dec  1, 1995 -- Changes to go with overhaul of ide.c and ide-tape.c
-- * 3.06  Dec 16, 1995 -- Add support needed for partitions.
-- *                       More workarounds for Vertos bugs (based on patches
-- *                        from Holger Dietze <dietze at aix520.informatik.uni-leipzig.de>).
-- *                       Try to eliminate byteorder assumptions.
-- *                       Use atapi_cdrom_subchnl struct definition.
-- *                       Add STANDARD_ATAPI compilation option.
-- * 3.07  Jan 29, 1996 -- More twiddling for broken drives: Sony 55D,
-- *                        Vertos 300.
-- *                       Add NO_DOOR_LOCKING configuration option.
-- *                       Handle drive_cmd requests w/NULL args (for hdparm -t).
-- *                       Work around sporadic Sony55e audio play problem.
-- * 3.07a Feb 11, 1996 -- check drive->id for NULL before dereferencing, to fix
-- *                        problem with "hde=cdrom" with no drive present.  -ml
-- * 3.08  Mar  6, 1996 -- More Vertos workarounds.
-- * 3.09  Apr  5, 1996 -- Add CDROMCLOSETRAY ioctl.
-- *                       Switch to using MSF addressing for audio commands.
-- *                       Reformat to match kernel tabbing style.
-- *                       Add CDROM_GET_UPC ioctl.
-- * 3.10  Apr 10, 1996 -- Fix compilation error with STANDARD_ATAPI.
-- * 3.11  Apr 29, 1996 -- Patch from Heiko Eißfeldt <heiko at colossus.escape.de>
-- *                       to remove redundant verify_area calls.
-- * 3.12  May  7, 1996 -- Rudimentary changer support.  Based on patches
-- *                        from Gerhard Zuber <zuber at berlin.snafu.de>.
-- *                       Let open succeed even if there's no loaded disc.
-- * 3.13  May 19, 1996 -- Fixes for changer code.
-- * 3.14  May 29, 1996 -- Add work-around for Vertos 600.
-- *                        (From Hennus Bergman <hennus at sky.ow.nl>.)
-- * 3.15  July 2, 1996 -- Added support for Sanyo 3 CD changers
-- *                        from Ben Galliart <bgallia at luc.edu> with 
-- *                        special help from Jeff Lightfoot 
-- *                        <jeffml at pobox.com>
-- * 3.15a July 9, 1996 -- Improved Sanyo 3 CD changer identification
-- * 3.16  Jul 28, 1996 -- Fix from Gadi to reduce kernel stack usage for ioctl.
-- * 3.17  Sep 17, 1996 -- Tweak audio reads for some drives.
-- *                       Start changing CDROMLOADFROMSLOT to CDROM_SELECT_DISC.
-- * 3.18  Oct 31, 1996 -- Added module and DMA support.
-- *                       
-- *                       
-- * 4.00  Nov 5, 1996   -- New ide-cd maintainer,
-- *                                 Erik B. Andersen <andersee at debian.org>
-- *                     -- Newer Creative drives don't always set the error
-- *                          register correctly.  Make sure we see media changes
-- *                          regardless.
-- *                     -- Integrate with generic cdrom driver.
-- *                     -- CDROMGETSPINDOWN and CDROMSETSPINDOWN ioctls, based on
-- *                          a patch from Ciro Cattuto <>.
-- *                     -- Call set_device_ro.
-- *                     -- Implement CDROMMECHANISMSTATUS and CDROMSLOTTABLE
-- *                          ioctls, based on patch by Erik Andersen
-- *                     -- Add some probes of drive capability during setup.
+- *		MTBSF and MTBSFM are not supported when the tape doesn't
+- *		support spacing over filemarks in the reverse direction.
+- *		In this case, MTFSFM is also usually not supported (it is
+- *		supported in the rare case in which we crossed the filemark
+- *		during our read-ahead pipelined operation mode).
+- *		
+- *	MTWEOF	-	Writes mt_count filemarks. Tape is positioned after
+- *			the last written filemark.
 - *
-- * 4.01  Nov 11, 1996  -- Split into ide-cd.c and ide-cd.h
-- *                     -- Removed CDROMMECHANISMSTATUS and CDROMSLOTTABLE 
-- *                          ioctls in favor of a generalized approach 
-- *                          using the generic cdrom driver.
-- *                     -- Fully integrated with the 2.1.X kernel.
-- *                     -- Other stuff that I forgot (lots of changes)
+- *	MTREW	-	Rewinds tape.
 - *
-- * 4.02  Dec 01, 1996  -- Applied patch from Gadi Oxman <gadio at netvision.net.il>
-- *                          to fix the drive door locking problems.
+- *	MTLOAD	-	Loads the tape.
 - *
-- * 4.03  Dec 04, 1996  -- Added DSC overlap support.
-- * 4.04  Dec 29, 1996  -- Added CDROMREADRAW ioclt based on patch 
-- *                          by Ales Makarov (xmakarov at sun.felk.cvut.cz)
+- *	MTOFFL	-	Puts the tape drive "Offline": Rewinds the tape and
+- *	MTUNLOAD	prevents further access until the media is replaced.
 - *
-- * 4.05  Nov 20, 1997  -- Modified to print more drive info on init
-- *                        Minor other changes
-- *                        Fix errors on CDROMSTOP (If you have a "Dolphin",
-- *                          you must define IHAVEADOLPHIN)
-- *                        Added identifier so new Sanyo CD-changer works
-- *                        Better detection if door locking isn't supported
+- *	MTNOP	-	Flushes tape buffers.
 - *
-- * 4.06  Dec 17, 1997  -- fixed endless "tray open" messages  -ml
-- * 4.07  Dec 17, 1997  -- fallback to set pc->stat on "tray open"
-- * 4.08  Dec 18, 1997  -- spew less noise when tray is empty
-- *                     -- fix speed display for ACER 24X, 18X
-- * 4.09  Jan 04, 1998  -- fix handling of the last block so we return
-- *                         an end of file instead of an I/O error (Gadi)
-- * 4.10  Jan 24, 1998  -- fixed a bug so now changers can change to a new
-- *                         slot when there is no disc in the current slot.
-- *                     -- Fixed a memory leak where info->changer_info was
-- *                         malloc'ed but never free'd when closing the device.
-- *                     -- Cleaned up the global namespace a bit by making more
-- *                         functions static that should already have been.
-- * 4.11  Mar 12, 1998  -- Added support for the CDROM_SELECT_SPEED ioctl
-- *                         based on a patch for 2.0.33 by Jelle Foks 
-- *                         <jelle at scintilla.utwente.nl>, a patch for 2.0.33
-- *                         by Toni Giorgino <toni at pcape2.pi.infn.it>, the SCSI
-- *                         version, and my own efforts.  -erik
-- *                     -- Fixed a stupid bug which egcs was kind enough to
-- *                         inform me of where "Illegal mode for this track"
-- *                         was never returned due to a comparison on data
-- *                         types of limited range.
-- * 4.12  Mar 29, 1998  -- Fixed bug in CDROM_SELECT_SPEED so write speed is 
-- *                         now set ionly for CD-R and CD-RW drives.  I had 
-- *                         removed this support because it produced errors.
-- *                         It produced errors _only_ for non-writers. duh.
-- * 4.13  May 05, 1998  -- Suppress useless "in progress of becoming ready"
-- *                         messages, since this is not an error.
-- *                     -- Change error messages to be const
-- *                     -- Remove a "\t" which looks ugly in the syslogs
-- * 4.14  July 17, 1998 -- Change to pointing to .ps version of ATAPI spec
-- *                         since the .pdf version doesn't seem to work...
-- *                     -- Updated the TODO list to something more current.
+- *	MTRETEN	-	Retension media. This typically consists of one end
+- *			to end pass on the media.
 - *
-- * 4.15  Aug 25, 1998  -- Updated ide-cd.h to respect mechine endianess, 
-- *                         patch thanks to "Eddie C. Dost" <ecd at skynet.be>
+- *	MTEOM	-	Moves to the end of recorded data.
 - *
-- * 4.50  Oct 19, 1998  -- New maintainers!
-- *                         Jens Axboe <axboe at image.dk>
-- *                         Chris Zwilling <chris at cloudnet.com>
+- *	MTERASE	-	Erases tape.
 - *
-- * 4.51  Dec 23, 1998  -- Jens Axboe <axboe at image.dk>
-- *                      - ide_cdrom_reset enabled since the ide subsystem
-- *                         handles resets fine now. <axboe at image.dk>
-- *                      - Transfer size fix for Samsung CD-ROMs, thanks to
-- *                        "Ville Hallik" <ville.hallik at mail.ee>.
-- *                      - other minor stuff.
+- *	MTSETBLK - 	Sets the user block size to mt_count bytes. If
+- *			mt_count is 0, we will attempt to autodetect
+- *			the block size.
 - *
-- * 4.52  Jan 19, 1999  -- Jens Axboe <axboe at image.dk>
-- *                      - Detect DVD-ROM/RAM drives
+- *	MTSEEK	-	Positions the tape in a specific block number, where
+- *			each block is assumed to contain which user_block_size
+- *			bytes.
 - *
-- * 4.53  Feb 22, 1999   - Include other model Samsung and one Goldstar
-- *                         drive in transfer size limit.
-- *                      - Fix the I/O error when doing eject without a medium
-- *                         loaded on some drives.
-- *                      - CDROMREADMODE2 is now implemented through
-- *                         CDROMREADRAW, since many drives don't support
-- *                         MODE2 (even though ATAPI 2.6 says they must).
-- *                      - Added ignore parameter to ide-cd (as a module), eg
-- *                         	insmod ide-cd ignore='hda hdb'
-- *                         Useful when using ide-cd in conjunction with
-- *                         ide-scsi. TODO: non-modular way of doing the
-- *                         same.
+- *	MTSETPART - 	Switches to another tape partition.
 - *
-- * 4.54  Aug 5, 1999	- Support for MMC2 class commands through the generic
-- *			  packet interface to cdrom.c.
-- *			- Unified audio ioctl support, most of it.
-- *			- cleaned up various deprecated verify_area().
-- *			- Added ide_cdrom_packet() as the interface for
-- *			  the Uniform generic_packet().
-- *			- bunch of other stuff, will fill in logs later.
-- *			- report 1 slot for non-changers, like the other
-- *			  cd-rom drivers. don't report select disc for
-- *			  non-changers as well.
-- *			- mask out audio playing, if the device can't do it.
+- *	MTLOCK - 	Locks the tape door.
 - *
-- * 4.55  Sep 1, 1999	- Eliminated the rest of the audio ioctls, except
-- *			  for CDROMREADTOC[ENTRY|HEADER]. Some of the drivers
-- *			  use this independently of the actual audio handling.
-- *			  They will disappear later when I get the time to
-- *			  do it cleanly.
-- *			- Minimize the TOC reading - only do it when we
-- *			  know a media change has occurred.
-- *			- Moved all the CDROMREADx ioctls to the Uniform layer.
-- *			- Heiko Eißfeldt <heiko at colossus.escape.de> supplied
-- *			  some fixes for CDI.
-- *			- CD-ROM leaving door locked fix from Andries
-- *			  Brouwer <Andries.Brouwer at cwi.nl>
-- *			- Erik Andersen <andersen at xmission.com> unified
-- *			  commands across the various drivers and how
-- *			  sense errors are handled.
+- *	MTUNLOCK - 	Unlocks the tape door.
 - *
-- * 4.56  Sep 12, 1999	- Removed changer support - it is now in the
-- *			  Uniform layer.
-- *			- Added partition based multisession handling.
-- *			- Mode sense and mode select moved to the
-- *			  Uniform layer.
-- *			- Fixed a problem with WPI CDS-32X drive - it
-- *			  failed the capabilities 
+- *	The following commands are currently not supported:
 - *
-- * 4.57  Apr 7, 2000	- Fixed sense reporting.
-- *			- Fixed possible oops in ide_cdrom_get_last_session()
-- *			- Fix locking mania and make ide_cdrom_reset relock
-- *			- Stop spewing errors to log when magicdev polls with
-- *			  TEST_UNIT_READY on some drives.
-- *			- Various fixes from Tobias Ringstrom:
-- *			  tray if it was locked prior to the reset.
-- *			  - cdrom_read_capacity returns one frame too little.
-- *			  - Fix real capacity reporting.
+- *	MTFSS, MTBSS, MTWSM, MTSETDENSITY,
+- *	MTSETDRVBUFFER, MT_ST_BOOLEANS, MT_ST_WRITE_THRESHOLD.
++ * MTFSS, MTBSS, MTWSM, MTSETDENSITY, MTSETDRVBUFFER, MT_ST_BOOLEANS,
++ * MT_ST_WRITE_THRESHOLD.
+  */
+-static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count)
++static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t pc;
+-	int i,retval;
++	int i, retval;
+ 
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 1)
+-		printk(KERN_INFO "ide-tape: Handling MTIOCTOP ioctl: "
+-			"mt_op=%d, mt_count=%d\n", mt_op, mt_count);
+-#endif /* IDETAPE_DEBUG_LOG */
+-	/*
+-	 *	Commands which need our pipelined read-ahead stages.
+-	 */
++	debug_log(DBG_ERR, "Handling MTIOCTOP ioctl: mt_op=%d, mt_count=%d\n",
++			mt_op, mt_count);
++
++	/* Commands which need our pipelined read-ahead stages. */
+ 	switch (mt_op) {
+-		case MTFSF:
+-		case MTFSFM:
+-		case MTBSF:
+-		case MTBSFM:
+-			if (!mt_count)
+-				return (0);
+-			return (idetape_space_over_filemarks(drive,mt_op,mt_count));
+-		default:
+-			break;
++	case MTFSF:
++	case MTFSFM:
++	case MTBSF:
++	case MTBSFM:
++		if (!mt_count)
++			return 0;
++		return idetape_space_over_filemarks(drive, mt_op, mt_count);
++	default:
++		break;
+ 	}
++
+ 	switch (mt_op) {
+-		case MTWEOF:
+-			if (tape->write_prot)
+-				return -EACCES;
+-			idetape_discard_read_pipeline(drive, 1);
+-			for (i = 0; i < mt_count; i++) {
+-				retval = idetape_write_filemark(drive);
+-				if (retval)
+-					return retval;
+-			}
+-			return (0);
+-		case MTREW:
+-			idetape_discard_read_pipeline(drive, 0);
+-			if (idetape_rewind_tape(drive))
++	case MTWEOF:
++		if (tape->write_prot)
++			return -EACCES;
++		idetape_discard_read_pipeline(drive, 1);
++		for (i = 0; i < mt_count; i++) {
++			retval = idetape_write_filemark(drive);
++			if (retval)
++				return retval;
++		}
++		return 0;
++	case MTREW:
++		idetape_discard_read_pipeline(drive, 0);
++		if (idetape_rewind_tape(drive))
++			return -EIO;
++		return 0;
++	case MTLOAD:
++		idetape_discard_read_pipeline(drive, 0);
++		idetape_create_load_unload_cmd(drive, &pc,
++					       IDETAPE_LU_LOAD_MASK);
++		return idetape_queue_pc_tail(drive, &pc);
++	case MTUNLOAD:
++	case MTOFFL:
++		/*
++		 * If door is locked, attempt to unlock before
++		 * attempting to eject.
++		 */
++		if (tape->door_locked) {
++			if (idetape_create_prevent_cmd(drive, &pc, 0))
++				if (!idetape_queue_pc_tail(drive, &pc))
++					tape->door_locked = DOOR_UNLOCKED;
++		}
++		idetape_discard_read_pipeline(drive, 0);
++		idetape_create_load_unload_cmd(drive, &pc,
++					      !IDETAPE_LU_LOAD_MASK);
++		retval = idetape_queue_pc_tail(drive, &pc);
++		if (!retval)
++			clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
++		return retval;
++	case MTNOP:
++		idetape_discard_read_pipeline(drive, 0);
++		return idetape_flush_tape_buffers(drive);
++	case MTRETEN:
++		idetape_discard_read_pipeline(drive, 0);
++		idetape_create_load_unload_cmd(drive, &pc,
++			IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
++		return idetape_queue_pc_tail(drive, &pc);
++	case MTEOM:
++		idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
++		return idetape_queue_pc_tail(drive, &pc);
++	case MTERASE:
++		(void)idetape_rewind_tape(drive);
++		idetape_create_erase_cmd(&pc);
++		return idetape_queue_pc_tail(drive, &pc);
++	case MTSETBLK:
++		if (mt_count) {
++			if (mt_count < tape->blk_size ||
++			    mt_count % tape->blk_size)
+ 				return -EIO;
++			tape->user_bs_factor = mt_count / tape->blk_size;
++			clear_bit(IDETAPE_DETECT_BS, &tape->flags);
++		} else
++			set_bit(IDETAPE_DETECT_BS, &tape->flags);
++		return 0;
++	case MTSEEK:
++		idetape_discard_read_pipeline(drive, 0);
++		return idetape_position_tape(drive,
++			mt_count * tape->user_bs_factor, tape->partition, 0);
++	case MTSETPART:
++		idetape_discard_read_pipeline(drive, 0);
++		return idetape_position_tape(drive, 0, mt_count, 0);
++	case MTFSR:
++	case MTBSR:
++	case MTLOCK:
++		if (!idetape_create_prevent_cmd(drive, &pc, 1))
+ 			return 0;
+-		case MTLOAD:
+-			idetape_discard_read_pipeline(drive, 0);
+-			idetape_create_load_unload_cmd(drive, &pc, IDETAPE_LU_LOAD_MASK);
+-			return (idetape_queue_pc_tail(drive, &pc));
+-		case MTUNLOAD:
+-		case MTOFFL:
+-			/*
+-			 * If door is locked, attempt to unlock before
+-			 * attempting to eject.
+-			 */
+-			if (tape->door_locked) {
+-				if (idetape_create_prevent_cmd(drive, &pc, 0))
+-					if (!idetape_queue_pc_tail(drive, &pc))
+-						tape->door_locked = DOOR_UNLOCKED;
+-			}
+-			idetape_discard_read_pipeline(drive, 0);
+-			idetape_create_load_unload_cmd(drive, &pc,!IDETAPE_LU_LOAD_MASK);
+-			retval = idetape_queue_pc_tail(drive, &pc);
+-			if (!retval)
+-				clear_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags);
++		retval = idetape_queue_pc_tail(drive, &pc);
++		if (retval)
+ 			return retval;
+-		case MTNOP:
+-			idetape_discard_read_pipeline(drive, 0);
+-			return (idetape_flush_tape_buffers(drive));
+-		case MTRETEN:
+-			idetape_discard_read_pipeline(drive, 0);
+-			idetape_create_load_unload_cmd(drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK);
+-			return (idetape_queue_pc_tail(drive, &pc));
+-		case MTEOM:
+-			idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD);
+-			return (idetape_queue_pc_tail(drive, &pc));
+-		case MTERASE:
+-			(void) idetape_rewind_tape(drive);
+-			idetape_create_erase_cmd(&pc);
+-			return (idetape_queue_pc_tail(drive, &pc));
+-		case MTSETBLK:
+-			if (mt_count) {
+-				if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size)
+-					return -EIO;
+-				tape->user_bs_factor = mt_count / tape->tape_block_size;
+-				clear_bit(IDETAPE_DETECT_BS, &tape->flags);
+-			} else
+-				set_bit(IDETAPE_DETECT_BS, &tape->flags);
+-			return 0;
+-		case MTSEEK:
+-			idetape_discard_read_pipeline(drive, 0);
+-			return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0);
+-		case MTSETPART:
+-			idetape_discard_read_pipeline(drive, 0);
+-			return (idetape_position_tape(drive, 0, mt_count, 0));
+-		case MTFSR:
+-		case MTBSR:
+-		case MTLOCK:
+-			if (!idetape_create_prevent_cmd(drive, &pc, 1))
+-				return 0;
+-			retval = idetape_queue_pc_tail(drive, &pc);
+-			if (retval) return retval;
+-			tape->door_locked = DOOR_EXPLICITLY_LOCKED;
+-			return 0;
+-		case MTUNLOCK:
+-			if (!idetape_create_prevent_cmd(drive, &pc, 0))
+-				return 0;
+-			retval = idetape_queue_pc_tail(drive, &pc);
+-			if (retval) return retval;
+-			tape->door_locked = DOOR_UNLOCKED;
++		tape->door_locked = DOOR_EXPLICITLY_LOCKED;
++		return 0;
++	case MTUNLOCK:
++		if (!idetape_create_prevent_cmd(drive, &pc, 0))
+ 			return 0;
+-		default:
+-			printk(KERN_ERR "ide-tape: MTIO operation %d not "
+-				"supported\n", mt_op);
+-			return (-EIO);
++		retval = idetape_queue_pc_tail(drive, &pc);
++		if (retval)
++			return retval;
++		tape->door_locked = DOOR_UNLOCKED;
++		return 0;
++	default:
++		printk(KERN_ERR "ide-tape: MTIO operation %d not supported\n",
++				mt_op);
++		return -EIO;
+ 	}
+ }
+ 
+ /*
+- *	Our character device ioctls.
 - *
-- * 4.58  May 1, 2000	- Clean up ACER50 stuff.
-- *			- Fix small problem with ide_cdrom_capacity
+- *	General mtio.h magnetic io commands are supported here, and not in
+- *	the corresponding block interface.
 - *
-- * 4.59  Aug 11, 2000	- Fix changer problem in cdrom_read_toc, we weren't
-- *			  correctly sensing a disc change.
-- *			- Rearranged some code
-- *			- Use extended sense on drives that support it for
-- *			  correctly reporting tray status -- from
-- *			  Michael D Johnson <johnsom at orst.edu>
-- * 4.60  Dec 17, 2003	- Add mt rainier support
-- *			- Bump timeout for packet commands, matches sr
-- *			- Odd stuff
-- * 4.61  Jan 22, 2004	- support hardware sector sizes other than 2kB,
-- *			  Pascal Schmidt <der.eremit at email.de>
+- *	The following ioctls are supported:
 - *
-- *************************************************************************/
-- 
--#define IDECD_VERSION "4.61"
-+ * For historical changelog please see:
-+ *	Documentation/ide/ChangeLog.ide-cd.1994-2004
-+ */
-+
-+#define IDECD_VERSION "5.00"
- 
- #include <linux/module.h>
- #include <linux/types.h>
-@@ -313,6 +37,7 @@
- #include <linux/ide.h>
- #include <linux/completion.h>
- #include <linux/mutex.h>
-+#include <linux/bcd.h>
- 
- #include <scsi/scsi.h>	/* For SCSI -> ATAPI command conversion */
- 
-@@ -360,11 +85,11 @@ static void ide_cd_put(struct cdrom_info *cd)
-    buffers. */
- static void cdrom_saw_media_change (ide_drive_t *drive)
+- *	MTIOCTOP -	Refer to idetape_mtioctop for detailed description.
+- *
+- *	MTIOCGET - 	The mt_dsreg field in the returned mtget structure
+- *			will be set to (user block size in bytes <<
+- *			MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK.
+- *
+- *			The mt_blkno is set to the current user block number.
+- *			The other mtget fields are not supported.
+- *
+- *	MTIOCPOS -	The current tape "block position" is returned. We
+- *			assume that each block contains user_block_size
+- *			bytes.
+- *
+- *	Our own ide-tape ioctls are supported on both interfaces.
++ * Our character device ioctls. General mtio.h magnetic io commands are
++ * supported here, and not in the corresponding block interface. Our own
++ * ide-tape ioctls are supported on both interfaces.
+  */
+-static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
++				unsigned int cmd, unsigned long arg)
  {
--	struct cdrom_info *info = drive->driver_data;
--	
--	CDROM_STATE_FLAGS (drive)->media_changed = 1;
--	CDROM_STATE_FLAGS (drive)->toc_valid = 0;
--	info->nsectors_buffered = 0;
-+	struct cdrom_info *cd = drive->driver_data;
-+
-+	cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED;
-+	cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
-+	cd->nsectors_buffered = 0;
- }
+ 	struct ide_tape_obj *tape = ide_tape_f(file);
+ 	ide_drive_t *drive = tape->drive;
+ 	struct mtop mtop;
+ 	struct mtget mtget;
+ 	struct mtpos mtpos;
+-	int block_offset = 0, position = tape->first_frame_position;
++	int block_offset = 0, position = tape->first_frame;
+ 	void __user *argp = (void __user *)arg;
  
- static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
-@@ -465,134 +190,14 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
- 			}
-  		}
-  	}
--#if VERBOSE_IDE_CD_ERRORS
--	{
--		int i;
--		const char *s = "bad sense key!";
--		char buf[80];
--
--		printk ("ATAPI device %s:\n", drive->name);
--		if (sense->error_code==0x70)
--			printk("  Error: ");
--		else if (sense->error_code==0x71)
--			printk("  Deferred Error: ");
--		else if (sense->error_code == 0x7f)
--			printk("  Vendor-specific Error: ");
--		else
--			printk("  Unknown Error Type: ");
--
--		if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
--			s = sense_key_texts[sense->sense_key];
--
--		printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
--
--		if (sense->asc == 0x40) {
--			sprintf(buf, "Diagnostic failure on component 0x%02x",
--				 sense->ascq);
--			s = buf;
--		} else {
--			int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
--			unsigned long key = (sense->sense_key << 16);
--			key |= (sense->asc << 8);
--			if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
--				key |= sense->ascq;
--			s = NULL;
--
--			while (hi > lo) {
--				mid = (lo + hi) / 2;
--				if (sense_data_texts[mid].asc_ascq == key ||
--				    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
--					s = sense_data_texts[mid].text;
--					break;
--				}
--				else if (sense_data_texts[mid].asc_ascq > key)
--					hi = mid;
--				else
--					lo = mid+1;
--			}
--		}
--
--		if (s == NULL) {
--			if (sense->asc > 0x80)
--				s = "(vendor-specific error)";
--			else
--				s = "(reserved error code)";
--		}
--
--		printk(KERN_ERR "  %s -- (asc=0x%02x, ascq=0x%02x)\n",
--			s, sense->asc, sense->ascq);
--
--		if (failed_command != NULL) {
--
--			int lo=0, mid, hi= ARRAY_SIZE(packet_command_texts);
--			s = NULL;
--
--			while (hi > lo) {
--				mid = (lo + hi) / 2;
--				if (packet_command_texts[mid].packet_command ==
--				    failed_command->cmd[0]) {
--					s = packet_command_texts[mid].text;
--					break;
--				}
--				if (packet_command_texts[mid].packet_command >
--				    failed_command->cmd[0])
--					hi = mid;
--				else
--					lo = mid+1;
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 3)
+-		printk(KERN_INFO "ide-tape: Reached idetape_chrdev_ioctl, "
+-			"cmd=%u\n", cmd);
+-#endif /* IDETAPE_DEBUG_LOG */
++	debug_log(DBG_CHRDEV, "Enter %s, cmd=%u\n", __func__, cmd);
+ 
+ 	tape->restart_speed_control_req = 1;
+-	if (tape->chrdev_direction == idetape_direction_write) {
++	if (tape->chrdev_dir == IDETAPE_DIR_WRITE) {
+ 		idetape_empty_write_pipeline(drive);
+ 		idetape_flush_tape_buffers(drive);
+ 	}
+ 	if (cmd == MTIOCGET || cmd == MTIOCPOS) {
+-		block_offset = idetape_pipeline_size(drive) / (tape->tape_block_size * tape->user_bs_factor);
+-		if ((position = idetape_read_position(drive)) < 0)
++		block_offset = idetape_pipeline_size(drive) /
++			(tape->blk_size * tape->user_bs_factor);
++		position = idetape_read_position(drive);
++		if (position < 0)
+ 			return -EIO;
+ 	}
+ 	switch (cmd) {
+-		case MTIOCTOP:
+-			if (copy_from_user(&mtop, argp, sizeof (struct mtop)))
+-				return -EFAULT;
+-			return (idetape_mtioctop(drive,mtop.mt_op,mtop.mt_count));
+-		case MTIOCGET:
+-			memset(&mtget, 0, sizeof (struct mtget));
+-			mtget.mt_type = MT_ISSCSI2;
+-			mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
+-			mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
+-			if (tape->drv_write_prot) {
+-				mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
 -			}
--
--			printk (KERN_ERR "  The failed \"%s\" packet command was: \n  \"", s);
--			for (i=0; i<sizeof (failed_command->cmd); i++)
--				printk ("%02x ", failed_command->cmd[i]);
--			printk ("\"\n");
--		}
--
--		/* The SKSV bit specifies validity of the sense_key_specific
--		 * in the next two commands. It is bit 7 of the first byte.
--		 * In the case of NOT_READY, if SKSV is set the drive can
--		 * give us nice ETA readings.
--		 */
--		if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
--			int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
--			printk(KERN_ERR "  Command is %02d%% complete\n", progress / 0xffff);
--
--		}
--
--		if (sense->sense_key == ILLEGAL_REQUEST &&
--		    (sense->sks[0] & 0x80) != 0) {
--			printk(KERN_ERR "  Error in %s byte %d",
--				(sense->sks[0] & 0x40) != 0 ?
--				"command packet" : "command data",
--				(sense->sks[1] << 8) + sense->sks[2]);
- 
--			if ((sense->sks[0] & 0x40) != 0)
--				printk (" bit %d", sense->sks[0] & 0x07);
--
--			printk ("\n");
--		}
--	}
--
--#else /* not VERBOSE_IDE_CD_ERRORS */
--
--	/* Suppress printing unit attention and `in progress of becoming ready'
--	   errors when we're not being verbose. */
--
--	if (sense->sense_key == UNIT_ATTENTION ||
--	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
--						sense->asc == 0x3a)))
--		return;
--
--	printk(KERN_ERR "%s: error code: 0x%02x  sense_key: 0x%02x  asc: 0x%02x  ascq: 0x%02x\n",
--		drive->name,
--		sense->error_code, sense->sense_key,
--		sense->asc, sense->ascq);
--#endif /* not VERBOSE_IDE_CD_ERRORS */
-+	ide_cd_log_error(drive->name, failed_command, sense);
+-			if (copy_to_user(argp, &mtget, sizeof(struct mtget)))
+-				return -EFAULT;
+-			return 0;
+-		case MTIOCPOS:
+-			mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
+-			if (copy_to_user(argp, &mtpos, sizeof(struct mtpos)))
+-				return -EFAULT;
+-			return 0;
+-		default:
+-			if (tape->chrdev_direction == idetape_direction_read)
+-				idetape_discard_read_pipeline(drive, 1);
+-			return idetape_blkdev_ioctl(drive, cmd, arg);
++	case MTIOCTOP:
++		if (copy_from_user(&mtop, argp, sizeof(struct mtop)))
++			return -EFAULT;
++		return idetape_mtioctop(drive, mtop.mt_op, mtop.mt_count);
++	case MTIOCGET:
++		memset(&mtget, 0, sizeof(struct mtget));
++		mtget.mt_type = MT_ISSCSI2;
++		mtget.mt_blkno = position / tape->user_bs_factor - block_offset;
++		mtget.mt_dsreg =
++			((tape->blk_size * tape->user_bs_factor)
++			 << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK;
++
++		if (tape->drv_write_prot)
++			mtget.mt_gstat |= GMT_WR_PROT(0xffffffff);
++
++		if (copy_to_user(argp, &mtget, sizeof(struct mtget)))
++			return -EFAULT;
++		return 0;
++	case MTIOCPOS:
++		mtpos.mt_blkno = position / tape->user_bs_factor - block_offset;
++		if (copy_to_user(argp, &mtpos, sizeof(struct mtpos)))
++			return -EFAULT;
++		return 0;
++	default:
++		if (tape->chrdev_dir == IDETAPE_DIR_READ)
++			idetape_discard_read_pipeline(drive, 1);
++		return idetape_blkdev_ioctl(drive, cmd, arg);
+ 	}
  }
  
+-static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive);
+-
  /*
-  * Initialize a ide-cd packet command request
+- *	Our character device open function.
++ * Do a mode sense page 0 with block descriptor and if it succeeds set the tape
++ * block size with the reported value.
   */
--static void cdrom_prepare_request(ide_drive_t *drive, struct request *rq)
-+void ide_cd_init_rq(ide_drive_t *drive, struct request *rq)
+-static int idetape_chrdev_open (struct inode *inode, struct file *filp)
++static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
++{
++	idetape_tape_t *tape = drive->driver_data;
++	idetape_pc_t pc;
++
++	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
++	if (idetape_queue_pc_tail(drive, &pc)) {
++		printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
++		if (tape->blk_size == 0) {
++			printk(KERN_WARNING "ide-tape: Cannot deal with zero "
++					    "block size, assuming 32k\n");
++			tape->blk_size = 32768;
++		}
++		return;
++	}
++	tape->blk_size = (pc.buffer[4 + 5] << 16) +
++				(pc.buffer[4 + 6] << 8)  +
++				 pc.buffer[4 + 7];
++	tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
++}
++
++static int idetape_chrdev_open(struct inode *inode, struct file *filp)
  {
- 	struct cdrom_info *cd = drive->driver_data;
+ 	unsigned int minor = iminor(inode), i = minor & ~0xc0;
+ 	ide_drive_t *drive;
+@@ -4157,6 +3209,15 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
+ 	idetape_pc_t pc;
+ 	int retval;
  
-@@ -611,7 +216,7 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense,
- 		sense = &info->sense_data;
++	if (i >= MAX_HWIFS * MAX_DRIVES)
++		return -ENXIO;
++
++	tape = ide_tape_chrdev_get(i);
++	if (!tape)
++		return -ENXIO;
++
++	debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
++
+ 	/*
+ 	 * We really want to do nonseekable_open(inode, filp); here, but some
+ 	 * versions of tar incorrectly call lseek on tapes and bail out if that
+@@ -4164,16 +3225,6 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
+ 	 */
+ 	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+ 
+-#if IDETAPE_DEBUG_LOG
+-	printk(KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
+-#endif /* IDETAPE_DEBUG_LOG */
+-	
+-	if (i >= MAX_HWIFS * MAX_DRIVES)
+-		return -ENXIO;
+-
+-	if (!(tape = ide_tape_chrdev_get(i)))
+-		return -ENXIO;
+-
+ 	drive = tape->drive;
  
- 	/* stuff the sense request in front of our current request */
--	cdrom_prepare_request(drive, rq);
-+	ide_cd_init_rq(drive, rq);
+ 	filp->private_data = tape;
+@@ -4194,11 +3245,11 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
+ 	if (!test_bit(IDETAPE_ADDRESS_VALID, &tape->flags))
+ 		(void)idetape_rewind_tape(drive);
  
- 	rq->data = sense;
- 	rq->cmd[0] = GPCMD_REQUEST_SENSE;
-@@ -655,9 +260,9 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
- 					BUG();
- 			} else {
- 				spin_lock_irqsave(&ide_lock, flags);
--				end_that_request_chunk(failed, 0,
--							failed->data_len);
--				end_that_request_last(failed, 0);
-+				if (__blk_end_request(failed, -EIO,
-+						      failed->data_len))
-+					BUG();
- 				spin_unlock_irqrestore(&ide_lock, flags);
- 			}
- 		} else
-@@ -718,7 +323,6 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+-	if (tape->chrdev_direction != idetape_direction_read)
++	if (tape->chrdev_dir != IDETAPE_DIR_READ)
+ 		clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
  
- 	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
- 		/* All other functions, except for READ. */
--		unsigned long flags;
+ 	/* Read block size and write protect status from drive. */
+-	idetape_get_blocksize_from_block_descriptor(drive);
++	ide_tape_get_bsize_from_bdesc(drive);
  
- 		/*
- 		 * if we have an error, pass back CHECK_CONDITION as the
-@@ -756,15 +360,7 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
- 		 * remove failed request completely and end it when the
- 		 * request sense has completed
- 		 */
--		if (stat & ERR_STAT) {
--			spin_lock_irqsave(&ide_lock, flags);
--			blkdev_dequeue_request(rq);
--			HWGROUP(drive)->rq = NULL;
--			spin_unlock_irqrestore(&ide_lock, flags);
--
--			cdrom_queue_request_sense(drive, rq->sense, rq);
--		} else
--			cdrom_end_request(drive, 0);
-+		goto end_request;
+ 	/* Set write protect flag if device is opened as read-only. */
+ 	if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
+@@ -4216,10 +3267,8 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
+ 		}
+ 	}
  
- 	} else if (blk_fs_request(rq)) {
- 		int do_end_request = 0;
-@@ -844,23 +440,15 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
- 		   sense data. We need this in order to perform end of media
- 		   processing */
+-	/*
+-	 * Lock the tape drive door so user can't eject.
+-	 */
+-	if (tape->chrdev_direction == idetape_direction_none) {
++	/* Lock the tape drive door so user can't eject. */
++	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
+ 		if (idetape_create_prevent_cmd(drive, &pc, 1)) {
+ 			if (!idetape_queue_pc_tail(drive, &pc)) {
+ 				if (tape->door_locked != DOOR_EXPLICITLY_LOCKED)
+@@ -4236,14 +3285,15 @@ out_put_tape:
+ 	return retval;
+ }
  
--		if (do_end_request) {
--			if (stat & ERR_STAT) {
--				unsigned long flags;
--				spin_lock_irqsave(&ide_lock, flags);
--				blkdev_dequeue_request(rq);
--				HWGROUP(drive)->rq = NULL;
--				spin_unlock_irqrestore(&ide_lock, flags);
-+		if (do_end_request)
-+			goto end_request;
+-static void idetape_write_release (ide_drive_t *drive, unsigned int minor)
++static void idetape_write_release(ide_drive_t *drive, unsigned int minor)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
--				cdrom_queue_request_sense(drive, rq->sense, rq);
--			} else
--				cdrom_end_request(drive, 0);
--		} else {
--			/* If we got a CHECK_CONDITION status,
--			   queue a request sense command. */
--			if (stat & ERR_STAT)
--				cdrom_queue_request_sense(drive, NULL, NULL);
--		}
-+		/*
-+		 * If we got a CHECK_CONDITION status,
-+		 * queue a request sense command.
-+		 */
-+		if (stat & ERR_STAT)
-+			cdrom_queue_request_sense(drive, NULL, NULL);
- 	} else {
- 		blk_dump_rq_flags(rq, "ide-cd: bad rq");
- 		cdrom_end_request(drive, 0);
-@@ -868,6 +456,21 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
+ 	idetape_empty_write_pipeline(drive);
+ 	tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0);
+ 	if (tape->merge_stage != NULL) {
+-		idetape_pad_zeros(drive, tape->tape_block_size * (tape->user_bs_factor - 1));
++		idetape_pad_zeros(drive, tape->blk_size *
++				(tape->user_bs_factor - 1));
+ 		__idetape_kfree_stage(tape->merge_stage);
+ 		tape->merge_stage = NULL;
+ 	}
+@@ -4252,10 +3302,7 @@ static void idetape_write_release (ide_drive_t *drive, unsigned int minor)
+ 	idetape_flush_tape_buffers(drive);
+ }
  
- 	/* Retry, or handle the next request. */
- 	return 1;
-+
-+end_request:
-+	if (stat & ERR_STAT) {
-+		unsigned long flags;
-+
-+		spin_lock_irqsave(&ide_lock, flags);
-+		blkdev_dequeue_request(rq);
-+		HWGROUP(drive)->rq = NULL;
-+		spin_unlock_irqrestore(&ide_lock, flags);
-+
-+		cdrom_queue_request_sense(drive, rq->sense, rq);
-+	} else
-+		cdrom_end_request(drive, 0);
-+
-+	return 1;
+-/*
+- *	Our character device release function.
+- */
+-static int idetape_chrdev_release (struct inode *inode, struct file *filp)
++static int idetape_chrdev_release(struct inode *inode, struct file *filp)
+ {
+ 	struct ide_tape_obj *tape = ide_tape_f(filp);
+ 	ide_drive_t *drive = tape->drive;
+@@ -4264,14 +3311,12 @@ static int idetape_chrdev_release (struct inode *inode, struct file *filp)
+ 
+ 	lock_kernel();
+ 	tape = drive->driver_data;
+-#if IDETAPE_DEBUG_LOG
+-	if (tape->debug_level >= 3)
+-		printk(KERN_INFO "ide-tape: Reached idetape_chrdev_release\n");
+-#endif /* IDETAPE_DEBUG_LOG */
+ 
+-	if (tape->chrdev_direction == idetape_direction_write)
++	debug_log(DBG_CHRDEV, "Enter %s\n", __func__);
++
++	if (tape->chrdev_dir == IDETAPE_DIR_WRITE)
+ 		idetape_write_release(drive, minor);
+-	if (tape->chrdev_direction == idetape_direction_read) {
++	if (tape->chrdev_dir == IDETAPE_DIR_READ) {
+ 		if (minor < 128)
+ 			idetape_discard_read_pipeline(drive, 1);
+ 		else
+@@ -4283,7 +3328,7 @@ static int idetape_chrdev_release (struct inode *inode, struct file *filp)
+ 	}
+ 	if (minor < 128 && test_bit(IDETAPE_MEDIUM_PRESENT, &tape->flags))
+ 		(void) idetape_rewind_tape(drive);
+-	if (tape->chrdev_direction == idetape_direction_none) {
++	if (tape->chrdev_dir == IDETAPE_DIR_NONE) {
+ 		if (tape->door_locked == DOOR_LOCKED) {
+ 			if (idetape_create_prevent_cmd(drive, &pc, 0)) {
+ 				if (!idetape_queue_pc_tail(drive, &pc))
+@@ -4298,331 +3343,188 @@ static int idetape_chrdev_release (struct inode *inode, struct file *filp)
  }
  
- static int cdrom_timer_expiry(ide_drive_t *drive)
-@@ -917,21 +520,15 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
- 	if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
- 		return startstop;
+ /*
+- *	idetape_identify_device is called to check the contents of the
+- *	ATAPI IDENTIFY command results. We return:
++ * check the contents of the ATAPI IDENTIFY command results. We return:
+  *
+- *	1	If the tape can be supported by us, based on the information
+- *		we have so far.
++ * 1 - If the tape can be supported by us, based on the information we have so
++ * far.
+  *
+- *	0 	If this tape driver is not currently supported by us.
++ * 0 - If this tape driver is not currently supported by us.
+  */
+-static int idetape_identify_device (ide_drive_t *drive)
++static int idetape_identify_device(ide_drive_t *drive)
+ {
+-	struct idetape_id_gcw gcw;
+-	struct hd_driveid *id = drive->id;
+-#if IDETAPE_DEBUG_INFO
+-	unsigned short mask,i;
+-#endif /* IDETAPE_DEBUG_INFO */
++	u8 gcw[2], protocol, device_type, removable, packet_size;
+ 
+ 	if (drive->id_read == 0)
+ 		return 1;
+ 
+-	*((unsigned short *) &gcw) = id->config;
+-
+-#if IDETAPE_DEBUG_INFO
+-	printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
+-	printk(KERN_INFO "ide-tape: Protocol Type: ");
+-	switch (gcw.protocol) {
+-		case 0: case 1: printk("ATA\n");break;
+-		case 2:	printk("ATAPI\n");break;
+-		case 3: printk("Reserved (Unknown to ide-tape)\n");break;
+-	}
+-	printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);	
+-	switch (gcw.device_type) {
+-		case 0: printk("Direct-access Device\n");break;
+-		case 1: printk("Streaming Tape Device\n");break;
+-		case 2: case 3: case 4: printk("Reserved\n");break;
+-		case 5: printk("CD-ROM Device\n");break;
+-		case 6: printk("Reserved\n");
+-		case 7: printk("Optical memory Device\n");break;
+-		case 0x1f: printk("Unknown or no Device type\n");break;
+-		default: printk("Reserved\n");
+-	}
+-	printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");	
+-	printk(KERN_INFO "ide-tape: Command Packet DRQ Type: ");
+-	switch (gcw.drq_type) {
+-		case 0: printk("Microprocessor DRQ\n");break;
+-		case 1: printk("Interrupt DRQ\n");break;
+-		case 2: printk("Accelerated DRQ\n");break;
+-		case 3: printk("Reserved\n");break;
+-	}
+-	printk(KERN_INFO "ide-tape: Command Packet Size: ");
+-	switch (gcw.packet_size) {
+-		case 0: printk("12 bytes\n");break;
+-		case 1: printk("16 bytes\n");break;
+-		default: printk("Reserved\n");break;
+-	}
+-	printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model);
+-	printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
+-	printk(KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no);
+-	printk(KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512);
+-	printk(KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
+-	printk(KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
+-	printk(KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO);
+-	printk(KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA);
+-	printk(KERN_INFO "ide-tape: Single Word DMA supported modes: ");
+-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
+-		if (id->dma_1word & mask)
+-			printk("%d ",i);
+-		if (id->dma_1word & (mask << 8))
+-			printk("(active) ");
+-	}
+-	printk("\n");
+-	printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
+-	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
+-		if (id->dma_mword & mask)
+-			printk("%d ",i);
+-		if (id->dma_mword & (mask << 8))
+-			printk("(active) ");
+-	}
+-	printk("\n");
+-	if (id->field_valid & 0x0002) {
+-		printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",
+-			id->eide_pio_modes & 1 ? "Mode 3":"None");
+-		printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
+-		if (id->eide_dma_min == 0)
+-			printk("Not supported\n");
+-		else
+-			printk("%d ns\n",id->eide_dma_min);
+-
+-		printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
+-		if (id->eide_dma_time == 0)
+-			printk("Not supported\n");
+-		else
+-			printk("%d ns\n",id->eide_dma_time);
+-
+-		printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
+-		if (id->eide_pio == 0)
+-			printk("Not supported\n");
+-		else
+-			printk("%d ns\n",id->eide_pio);
++	*((unsigned short *) &gcw) = drive->id->config;
  
-+	/* FIXME: for Virtual DMA we must check harder */
- 	if (info->dma)
- 		info->dma = !hwif->dma_setup(drive);
+-		printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
+-		if (id->eide_pio_iordy == 0)
+-			printk("Not supported\n");
+-		else
+-			printk("%d ns\n",id->eide_pio_iordy);
+-		
+-	} else
+-		printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
+-#endif /* IDETAPE_DEBUG_INFO */
++	protocol	=   (gcw[1] & 0xC0) >> 6;
++	device_type	=    gcw[1] & 0x1F;
++	removable	= !!(gcw[0] & 0x80);
++	packet_size	=    gcw[0] & 0x3;
  
- 	/* Set up the controller registers. */
--	/* FIXME: for Virtual DMA we must check harder */
--	HWIF(drive)->OUTB(info->dma, IDE_FEATURE_REG);
--	HWIF(drive)->OUTB(0, IDE_IREASON_REG);
--	HWIF(drive)->OUTB(0, IDE_SECTOR_REG);
+ 	/* Check that we can support this device */
 -
--	HWIF(drive)->OUTB(xferlen & 0xff, IDE_BCOUNTL_REG);
--	HWIF(drive)->OUTB(xferlen >> 8  , IDE_BCOUNTH_REG);
--	if (IDE_CONTROL_REG)
--		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
-- 
--	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
-+	ide_pktcmd_tf_load(drive, IDE_TFLAG_OUT_NSECT | IDE_TFLAG_OUT_LBAL |
-+			   IDE_TFLAG_NO_SELECT_MASK, xferlen, info->dma);
-+
-+	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
- 		/* waiting for CDB interrupt, not DMA yet. */
- 		if (info->dma)
- 			drive->waiting_for_dma = 0;
-@@ -957,10 +554,6 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
-    by cdrom_start_packet_command.
-    HANDLER is the interrupt handler to call when the command completes
-    or there's data ready. */
+-	if (gcw.protocol !=2 )
+-		printk(KERN_ERR "ide-tape: Protocol is not ATAPI\n");
+-	else if (gcw.device_type != 1)
+-		printk(KERN_ERR "ide-tape: Device type is not set to tape\n");
+-	else if (!gcw.removable)
++	if (protocol != 2)
++		printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
++				protocol);
++	else if (device_type != 1)
++		printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
++				"to tape\n", device_type);
++	else if (!removable)
+ 		printk(KERN_ERR "ide-tape: The removable flag is not set\n");
+-	else if (gcw.packet_size != 0) {
+-		printk(KERN_ERR "ide-tape: Packet size is not 12 bytes long\n");
+-		if (gcw.packet_size == 1)
+-			printk(KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n");
++	else if (packet_size != 0) {
++		printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12"
++				" bytes\n", packet_size);
+ 	} else
+ 		return 1;
+ 	return 0;
+ }
+ 
 -/*
-- * changed 5 parameters to 3 for dvd-ram
-- * struct packet_command *pc; now packet_command_t *pc;
+- * Use INQUIRY to get the firmware revision
 - */
- #define ATAPI_MIN_CDB_BYTES 12
- static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
- 					  struct request *rq,
-@@ -971,7 +564,7 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
- 	struct cdrom_info *info = drive->driver_data;
- 	ide_startstop_t startstop;
- 
--	if (CDROM_CONFIG_FLAGS(drive)->drq_interrupt) {
-+	if (info->cd_flags & IDE_CD_FLAG_DRQ_INTERRUPT) {
- 		/* Here we should have been called after receiving an interrupt
- 		   from the device.  DRQ should how be set. */
- 
-@@ -1011,6 +604,25 @@ static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive,
-  * Block read functions.
-  */
- 
-+static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
-+{
-+	while (len > 0) {
-+		int dum = 0;
-+		xf(drive, &dum, sizeof(dum));
-+		len -= sizeof(dum);
-+	}
-+}
-+
-+static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
-+{
-+	while (nsects > 0) {
-+		static char dum[SECTOR_SIZE];
-+
-+		drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum));
-+		nsects--;
-+	}
-+}
+-static void idetape_get_inquiry_results (ide_drive_t *drive)
++static void idetape_get_inquiry_results(ide_drive_t *drive)
+ {
+-	char *r;
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t pc;
+-	idetape_inquiry_result_t *inquiry;
+-	
++	char fw_rev[6], vendor_id[10], product_id[18];
 +
- /*
-  * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector
-  * buffer.  Once the first sector is added, any subsequent sectors are
-@@ -1049,11 +661,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
+ 	idetape_create_inquiry_cmd(&pc);
+ 	if (idetape_queue_pc_tail(drive, &pc)) {
+-		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name);
++		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
++				tape->name);
+ 		return;
  	}
- 
- 	/* Throw away any remaining data. */
--	while (sectors_to_transfer > 0) {
--		static char dum[SECTOR_SIZE];
--		HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
--		--sectors_to_transfer;
--	}
-+	ide_cd_drain_data(drive, sectors_to_transfer);
+-	inquiry = (idetape_inquiry_result_t *) pc.buffer;
+-	memcpy(tape->vendor_id, inquiry->vendor_id, 8);
+-	memcpy(tape->product_id, inquiry->product_id, 16);
+-	memcpy(tape->firmware_revision, inquiry->revision_level, 4);
+-	ide_fixstring(tape->vendor_id, 10, 0);
+-	ide_fixstring(tape->product_id, 18, 0);
+-	ide_fixstring(tape->firmware_revision, 6, 0);
+-	r = tape->firmware_revision;
+-	if (*(r + 1) == '.')
+-		tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0';
+-	printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision);
++	memcpy(vendor_id, &pc.buffer[8], 8);
++	memcpy(product_id, &pc.buffer[16], 16);
++	memcpy(fw_rev, &pc.buffer[32], 4);
++
++	ide_fixstring(vendor_id, 10, 0);
++	ide_fixstring(product_id, 18, 0);
++	ide_fixstring(fw_rev, 6, 0);
++
++	printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
++			drive->name, tape->name, vendor_id, product_id, fw_rev);
  }
  
  /*
-@@ -1062,23 +670,25 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector,
-  * ok; nonzero if the request has been terminated.
+- *	idetape_get_mode_sense_results asks the tape about its various
+- *	parameters. In particular, we will adjust our data transfer buffer
+- *	size to the recommended value as returned by the tape.
++ * Ask the tape about its various parameters. In particular, we will adjust our
++ * data transfer buffer	size to the recommended value as returned by the tape.
   */
- static
--int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
-+int ide_cd_check_ireason(ide_drive_t *drive, int len, int ireason, int rw)
+-static void idetape_get_mode_sense_results (ide_drive_t *drive)
++static void idetape_get_mode_sense_results(ide_drive_t *drive)
  {
--	if (ireason == 2)
-+	/*
-+	 * ireason == 0: the drive wants to receive data from us
-+	 * ireason == 2: the drive is expecting to transfer data to us
-+	 */
-+	if (ireason == (!rw << 1))
- 		return 0;
--	else if (ireason == 0) {
--		/* Whoops... The drive is expecting to receive data from us! */
-+	else if (ireason == (rw << 1)) {
-+		ide_hwif_t *hwif = drive->hwif;
-+		xfer_func_t *xf;
+ 	idetape_tape_t *tape = drive->driver_data;
+ 	idetape_pc_t pc;
+-	idetape_mode_parameter_header_t *header;
+-	idetape_capabilities_page_t *capabilities;
+-	
++	u8 *caps;
++	u8 speed, max_speed;
 +
-+		/* Whoops... */
- 		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
- 				drive->name, __FUNCTION__);
+ 	idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
+ 	if (idetape_queue_pc_tail(drive, &pc)) {
+-		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n");
+-		tape->tape_block_size = 512;
+-		tape->capabilities.ctl = 52;
+-		tape->capabilities.speed = 450;
+-		tape->capabilities.buffer_size = 6 * 52;
++		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
++				" some default values\n");
++		tape->blk_size = 512;
++		put_unaligned(52,   (u16 *)&tape->caps[12]);
++		put_unaligned(540,  (u16 *)&tape->caps[14]);
++		put_unaligned(6*52, (u16 *)&tape->caps[16]);
+ 		return;
+ 	}
+-	header = (idetape_mode_parameter_header_t *) pc.buffer;
+-	capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
++	caps = pc.buffer + 4 + pc.buffer[3];
++
++	/* convert to host order and save for later use */
++	speed = be16_to_cpu(*(u16 *)&caps[14]);
++	max_speed = be16_to_cpu(*(u16 *)&caps[8]);
  
--		/* Throw some data at the drive so it doesn't hang
--		   and quit this request. */
--		while (len > 0) {
--			int dum = 0;
--			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof (dum));
--			len -= sizeof (dum);
--		}
--	} else  if (ireason == 1) {
-+		xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes;
-+		ide_cd_pad_transfer(drive, xf, len);
-+	} else  if (rw == 0 && ireason == 1) {
- 		/* Some drives (ASUS) seem to tell us that status
- 		 * info is available. just get it and ignore.
- 		 */
-@@ -1095,137 +705,28 @@ int cdrom_read_check_ireason (ide_drive_t *drive, int len, int ireason)
- }
+-	capabilities->max_speed = ntohs(capabilities->max_speed);
+-	capabilities->ctl = ntohs(capabilities->ctl);
+-	capabilities->speed = ntohs(capabilities->speed);
+-	capabilities->buffer_size = ntohs(capabilities->buffer_size);
++	put_unaligned(max_speed, (u16 *)&caps[8]);
++	put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]);
++	put_unaligned(speed, (u16 *)&caps[14]);
++	put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]);
  
- /*
-- * Interrupt routine.  Called when a read request has completed.
-+ * Assume that the drive will always provide data in multiples of at least
-+ * SECTOR_SIZE, as it gets hairy to keep track of the transfers otherwise.
-  */
--static ide_startstop_t cdrom_read_intr (ide_drive_t *drive)
-+static int ide_cd_check_transfer_size(ide_drive_t *drive, int len)
- {
--	int stat;
--	int ireason, len, sectors_to_transfer, nskip;
--	struct cdrom_info *info = drive->driver_data;
--	u8 lowcyl = 0, highcyl = 0;
--	int dma = info->dma, dma_error = 0;
--
--	struct request *rq = HWGROUP(drive)->rq;
--
--	/*
--	 * handle dma case
--	 */
--	if (dma) {
--		info->dma = 0;
--		dma_error = HWIF(drive)->ide_dma_end(drive);
--		if (dma_error) {
--			printk(KERN_ERR "%s: DMA read error\n", drive->name);
--			ide_dma_off(drive);
--		}
--	}
--
--	if (cdrom_decode_status(drive, 0, &stat))
--		return ide_stopped;
--
--	if (dma) {
--		if (!dma_error) {
--			ide_end_request(drive, 1, rq->nr_sectors);
--			return ide_stopped;
--		} else
--			return ide_error(drive, "dma error", stat);
--	}
--
--	/* Read the interrupt reason and the transfer length. */
--	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
--	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
--	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
--
--	len = lowcyl + (256 * highcyl);
+-	if (!capabilities->speed) {
+-		printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name);
+-		capabilities->speed = 650;
++	if (!speed) {
++		printk(KERN_INFO "ide-tape: %s: invalid tape speed "
++				"(assuming 650KB/sec)\n", drive->name);
++		put_unaligned(650, (u16 *)&caps[14]);
+ 	}
+-	if (!capabilities->max_speed) {
+-		printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name);
+-		capabilities->max_speed = 650;
++	if (!max_speed) {
++		printk(KERN_INFO "ide-tape: %s: invalid max_speed "
++				"(assuming 650KB/sec)\n", drive->name);
++		put_unaligned(650, (u16 *)&caps[8]);
+ 	}
+ 
+-	tape->capabilities = *capabilities;		/* Save us a copy */
+-	if (capabilities->blk512)
+-		tape->tape_block_size = 512;
+-	else if (capabilities->blk1024)
+-		tape->tape_block_size = 1024;
 -
--	/* If DRQ is clear, the command has completed. */
--	if ((stat & DRQ_STAT) == 0) {
--		/* If we're not done filling the current buffer, complain.
--		   Otherwise, complete the command normally. */
--		if (rq->current_nr_sectors > 0) {
--			printk (KERN_ERR "%s: cdrom_read_intr: data underrun (%d blocks)\n",
--				drive->name, rq->current_nr_sectors);
--			rq->cmd_flags |= REQ_FAILED;
--			cdrom_end_request(drive, 0);
--		} else
--			cdrom_end_request(drive, 1);
--		return ide_stopped;
--	}
+-#if IDETAPE_DEBUG_INFO
+-	printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n");
+-	printk(KERN_INFO "ide-tape: Mode Parameter Header:\n");
+-	printk(KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length);
+-	printk(KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type);
+-	printk(KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp);
+-	printk(KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl);
+-	
+-	printk(KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n");
+-	printk(KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code);
+-	printk(KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length);
+-	printk(KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No");
+-	printk(KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed);
+-	printk(KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl);
+-	printk(KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed);	
+-	printk(KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512);
+-#endif /* IDETAPE_DEBUG_INFO */
+-}
 -
--	/* Check that the drive is expecting to do the same thing we are. */
--	if (cdrom_read_check_ireason (drive, len, ireason))
--		return ide_stopped;
+-/*
+- *	ide_get_blocksize_from_block_descriptor does a mode sense page 0 with block descriptor
+- *	and if it succeeds sets the tape block size with the reported value
+- */
+-static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive)
+-{
 -
--	/* Assume that the drive will always provide data in multiples
--	   of at least SECTOR_SIZE, as it gets hairy to keep track
--	   of the transfers otherwise. */
--	if ((len % SECTOR_SIZE) != 0) {
--		printk (KERN_ERR "%s: cdrom_read_intr: Bad transfer size %d\n",
--			drive->name, len);
--		if (CDROM_CONFIG_FLAGS(drive)->limit_nframes)
--			printk (KERN_ERR "  This drive is not supported by this version of the driver\n");
--		else {
--			printk (KERN_ERR "  Trying to limit transfer sizes\n");
--			CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
+-	idetape_tape_t *tape = drive->driver_data;
+-	idetape_pc_t pc;
+-	idetape_mode_parameter_header_t *header;
+-	idetape_parameter_block_descriptor_t *block_descrp;
+-	
+-	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
+-	if (idetape_queue_pc_tail(drive, &pc)) {
+-		printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
+-		if (tape->tape_block_size == 0) {
+-			printk(KERN_WARNING "ide-tape: Cannot deal with zero block size, assume 32k\n");
+-			tape->tape_block_size =  32768;
 -		}
--		cdrom_end_request(drive, 0);
--		return ide_stopped;
+-		return;
 -	}
+-	header = (idetape_mode_parameter_header_t *) pc.buffer;
+-	block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t));
+-	tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2];
+-	tape->drv_write_prot = (header->dsp & 0x80) >> 7;
 -
--	/* The number of sectors we need to read from the drive. */
--	sectors_to_transfer = len / SECTOR_SIZE;
--
--	/* First, figure out if we need to bit-bucket
--	   any of the leading sectors. */
--	nskip = min_t(int, rq->current_nr_sectors - bio_cur_sectors(rq->bio), sectors_to_transfer);
--
--	while (nskip > 0) {
--		/* We need to throw away a sector. */
--		static char dum[SECTOR_SIZE];
--		HWIF(drive)->atapi_input_bytes(drive, dum, sizeof (dum));
--
--		--rq->current_nr_sectors;
--		--nskip;
--		--sectors_to_transfer;
--	}
-+	struct cdrom_info *cd = drive->driver_data;
+-#if IDETAPE_DEBUG_INFO
+-	printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size);
+-#endif /* IDETAPE_DEBUG_INFO */
++	memcpy(&tape->caps, caps, 20);
++	if (caps[7] & 0x02)
++		tape->blk_size = 512;
++	else if (caps[7] & 0x04)
++		tape->blk_size = 1024;
+ }
  
--	/* Now loop while we still have data to read from the drive. */
--	while (sectors_to_transfer > 0) {
--		int this_transfer;
-+	if ((len % SECTOR_SIZE) == 0)
-+		return 0;
+ #ifdef CONFIG_IDE_PROC_FS
+-static void idetape_add_settings (ide_drive_t *drive)
++static void idetape_add_settings(ide_drive_t *drive)
+ {
+ 	idetape_tape_t *tape = drive->driver_data;
  
--		/* If we've filled the present buffer but there's another
--		   chained buffer after it, move on. */
--		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
--			cdrom_end_request(drive, 1);
-+	printk(KERN_ERR "%s: %s: Bad transfer size %d\n",
-+			drive->name, __FUNCTION__, len);
+-/*
+- *			drive	setting name		read/write	data type	min			max			mul_factor			div_factor	data pointer				set function
+- */
+-	ide_add_setting(drive,	"buffer",		SETTING_READ,	TYPE_SHORT,	0,			0xffff,			1,				2,		&tape->capabilities.buffer_size,	NULL);
+-	ide_add_setting(drive,	"pipeline_min",		SETTING_RW,	TYPE_INT,	1,			0xffff,			tape->stage_size / 1024,	1,		&tape->min_pipeline,			NULL);
+-	ide_add_setting(drive,	"pipeline",		SETTING_RW,	TYPE_INT,	1,			0xffff,			tape->stage_size / 1024,	1,		&tape->max_stages,			NULL);
+-	ide_add_setting(drive,	"pipeline_max",		SETTING_RW,	TYPE_INT,	1,			0xffff,			tape->stage_size / 1024,	1,		&tape->max_pipeline,			NULL);
+-	ide_add_setting(drive,	"pipeline_used",	SETTING_READ,	TYPE_INT,	0,			0xffff,			tape->stage_size / 1024,	1,		&tape->nr_stages,			NULL);
+-	ide_add_setting(drive,	"pipeline_pending",	SETTING_READ,	TYPE_INT,	0,			0xffff,			tape->stage_size / 1024,	1,		&tape->nr_pending_stages,		NULL);
+-	ide_add_setting(drive,	"speed",		SETTING_READ,	TYPE_SHORT,	0,			0xffff,			1,				1,		&tape->capabilities.speed,		NULL);
+-	ide_add_setting(drive,	"stage",		SETTING_READ,	TYPE_INT,	0,			0xffff,			1,				1024,		&tape->stage_size,			NULL);
+-	ide_add_setting(drive,	"tdsc",			SETTING_RW,	TYPE_INT,	IDETAPE_DSC_RW_MIN,	IDETAPE_DSC_RW_MAX,	1000,				HZ,		&tape->best_dsc_rw_frequency,		NULL);
+-	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW,	TYPE_BYTE,	0,			1,			1,				1,		&drive->dsc_overlap,			NULL);
+-	ide_add_setting(drive,	"pipeline_head_speed_c",SETTING_READ,	TYPE_INT,	0,			0xffff,			1,				1,		&tape->controlled_pipeline_head_speed,	NULL);
+-	ide_add_setting(drive,	"pipeline_head_speed_u",SETTING_READ,	TYPE_INT,	0,			0xffff,			1,				1,		&tape->uncontrolled_pipeline_head_speed,NULL);
+-	ide_add_setting(drive,	"avg_speed",		SETTING_READ,	TYPE_INT,	0,			0xffff,			1,				1,		&tape->avg_speed,			NULL);
+-	ide_add_setting(drive,	"debug_level",		SETTING_RW,	TYPE_INT,	0,			0xffff,			1,				1,		&tape->debug_level,			NULL);
++	ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
++			1, 2, (u16 *)&tape->caps[16], NULL);
++	ide_add_setting(drive, "pipeline_min", SETTING_RW, TYPE_INT, 1, 0xffff,
++			tape->stage_size / 1024, 1, &tape->min_pipeline, NULL);
++	ide_add_setting(drive, "pipeline", SETTING_RW, TYPE_INT, 1, 0xffff,
++			tape->stage_size / 1024, 1, &tape->max_stages, NULL);
++	ide_add_setting(drive, "pipeline_max", SETTING_RW, TYPE_INT, 1,	0xffff,
++			tape->stage_size / 1024, 1, &tape->max_pipeline, NULL);
++	ide_add_setting(drive, "pipeline_used",	SETTING_READ, TYPE_INT, 0,
++			0xffff,	tape->stage_size / 1024, 1, &tape->nr_stages,
++			NULL);
++	ide_add_setting(drive, "pipeline_pending", SETTING_READ, TYPE_INT, 0,
++			0xffff, tape->stage_size / 1024, 1,
++			&tape->nr_pending_stages, NULL);
++	ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
++			1, 1, (u16 *)&tape->caps[14], NULL);
++	ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT,	0, 0xffff, 1,
++			1024, &tape->stage_size, NULL);
++	ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
++			IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
++			NULL);
++	ide_add_setting(drive, "dsc_overlap", SETTING_RW, TYPE_BYTE, 0, 1, 1,
++			1, &drive->dsc_overlap, NULL);
++	ide_add_setting(drive, "pipeline_head_speed_c", SETTING_READ, TYPE_INT,
++			0, 0xffff, 1, 1, &tape->controlled_pipeline_head_speed,
++			NULL);
++	ide_add_setting(drive, "pipeline_head_speed_u", SETTING_READ, TYPE_INT,
++			0, 0xffff, 1, 1,
++			&tape->uncontrolled_pipeline_head_speed, NULL);
++	ide_add_setting(drive, "avg_speed", SETTING_READ, TYPE_INT, 0, 0xffff,
++			1, 1, &tape->avg_speed, NULL);
++	ide_add_setting(drive, "debug_mask", SETTING_RW, TYPE_INT, 0, 0xffff, 1,
++			1, &tape->debug_mask, NULL);
+ }
+ #else
+ static inline void idetape_add_settings(ide_drive_t *drive) { ; }
+ #endif
  
--		/* If the buffers are full, cache the rest of the data in our
--		   internal buffer. */
--		if (rq->current_nr_sectors == 0) {
--			cdrom_buffer_sectors(drive, rq->sector, sectors_to_transfer);
--			sectors_to_transfer = 0;
--		} else {
--			/* Transfer data to the buffers.
--			   Figure out how many sectors we can transfer
--			   to the current buffer. */
--			this_transfer = min_t(int, sectors_to_transfer,
--					     rq->current_nr_sectors);
--
--			/* Read this_transfer sectors
--			   into the current buffer. */
--			while (this_transfer > 0) {
--				HWIF(drive)->atapi_input_bytes(drive, rq->buffer, SECTOR_SIZE);
--				rq->buffer += SECTOR_SIZE;
--				--rq->nr_sectors;
--				--rq->current_nr_sectors;
--				++rq->sector;
--				--this_transfer;
--				--sectors_to_transfer;
--			}
+ /*
+- *	ide_setup is called to:
++ * The function below is called to:
+  *
+- *		1.	Initialize our various state variables.
+- *		2.	Ask the tape for its capabilities.
+- *		3.	Allocate a buffer which will be used for data
+- *			transfer. The buffer size is chosen based on
+- *			the recommendation which we received in step (2).
++ * 1. Initialize our various state variables.
++ * 2. Ask the tape for its capabilities.
++ * 3. Allocate a buffer which will be used for data transfer. The buffer size
++ * is chosen based on the recommendation which we received in step 2.
+  *
+- *	Note that at this point ide.c already assigned us an irq, so that
+- *	we can queue requests here and wait for their completion.
++ * Note that at this point ide.c already assigned us an irq, so that we can
++ * queue requests here and wait for their completion.
+  */
+-static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
++static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ {
+ 	unsigned long t1, tmid, tn, t;
+ 	int speed;
+-	struct idetape_id_gcw gcw;
+ 	int stage_size;
++	u8 gcw[2];
+ 	struct sysinfo si;
++	u16 *ctl = (u16 *)&tape->caps[12];
+ 
+-	spin_lock_init(&tape->spinlock);
++	spin_lock_init(&tape->lock);
+ 	drive->dsc_overlap = 1;
+-#ifdef CONFIG_BLK_DEV_IDEPCI
+-	if (HWIF(drive)->pci_dev != NULL) {
+-		/*
+-		 * These two ide-pci host adapters appear to need DSC overlap disabled.
+-		 * This probably needs further analysis.
+-		 */
+-		if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
+-		    (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
+-			printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name);
+-		    	drive->dsc_overlap = 0;
 -		}
-+	if (cd->cd_flags & IDE_CD_FLAG_LIMIT_NFRAMES)
-+		printk(KERN_ERR "  This drive is not supported by "
-+				"this version of the driver\n");
-+	else {
-+		printk(KERN_ERR "  Trying to limit transfer sizes\n");
-+		cd->cd_flags |= IDE_CD_FLAG_LIMIT_NFRAMES;
++	if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
++		printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
++				 tape->name);
++		drive->dsc_overlap = 0;
  	}
+-#endif /* CONFIG_BLK_DEV_IDEPCI */
+ 	/* Seagate Travan drives do not support DSC overlap. */
+ 	if (strstr(drive->id->model, "Seagate STT3401"))
+ 		drive->dsc_overlap = 0;
+@@ -4630,25 +3532,29 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ 	tape->name[0] = 'h';
+ 	tape->name[1] = 't';
+ 	tape->name[2] = '0' + minor;
+-	tape->chrdev_direction = idetape_direction_none;
++	tape->chrdev_dir = IDETAPE_DIR_NONE;
+ 	tape->pc = tape->pc_stack;
+ 	tape->max_insert_speed = 10000;
+ 	tape->speed_control = 1;
+ 	*((unsigned short *) &gcw) = drive->id->config;
+-	if (gcw.drq_type == 1)
++
++	/* Command packet DRQ type */
++	if (((gcw[0] & 0x60) >> 5) == 1)
+ 		set_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags);
  
--	/* Done moving data!  Wait for another interrupt. */
--	ide_set_handler(drive, &cdrom_read_intr, ATAPI_WAIT_PC, NULL);
--	return ide_started;
-+	return 1;
- }
+-	tape->min_pipeline = tape->max_pipeline = tape->max_stages = 10;
+-	
++	tape->min_pipeline = 10;
++	tape->max_pipeline = 10;
++	tape->max_stages   = 10;
++
+ 	idetape_get_inquiry_results(drive);
+ 	idetape_get_mode_sense_results(drive);
+-	idetape_get_blocksize_from_block_descriptor(drive);
++	ide_tape_get_bsize_from_bdesc(drive);
+ 	tape->user_bs_factor = 1;
+-	tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
++	tape->stage_size = *ctl * tape->blk_size;
+ 	while (tape->stage_size > 0xffff) {
+ 		printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
+-		tape->capabilities.ctl /= 2;
+-		tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
++		*ctl /= 2;
++		tape->stage_size = *ctl * tape->blk_size;
+ 	}
+ 	stage_size = tape->stage_size;
+ 	tape->pages_per_stage = stage_size / PAGE_SIZE;
+@@ -4657,28 +3563,30 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ 		tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
+ 	}
  
- /*
-@@ -1287,48 +788,58 @@ static int cdrom_read_from_buffer (ide_drive_t *drive)
- 	return 0;
- }
+-	/*
+-	 *	Select the "best" DSC read/write polling frequency
+-	 *	and pipeline size.
+-	 */
+-	speed = max(tape->capabilities.speed, tape->capabilities.max_speed);
++	/* Select the "best" DSC read/write polling freq and pipeline size. */
++	speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
  
-+static ide_startstop_t cdrom_newpc_intr(ide_drive_t *);
-+
- /*
-- * Routine to send a read packet command to the drive.
-- * This is usually called directly from cdrom_start_read.
-+ * Routine to send a read/write packet command to the drive.
-+ * This is usually called directly from cdrom_start_{read,write}().
-  * However, for drq_interrupt devices, it is called from an interrupt
-  * when the drive is ready to accept the command.
-  */
--static ide_startstop_t cdrom_start_read_continuation (ide_drive_t *drive)
-+static ide_startstop_t cdrom_start_rw_cont(ide_drive_t *drive)
- {
- 	struct request *rq = HWGROUP(drive)->rq;
--	unsigned short sectors_per_frame;
--	int nskip;
+ 	tape->max_stages = speed * 1000 * 10 / tape->stage_size;
  
--	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-+	if (rq_data_dir(rq) == READ) {
-+		unsigned short sectors_per_frame =
-+			queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-+		int nskip = rq->sector & (sectors_per_frame - 1);
+-	/*
+-	 * 	Limit memory use for pipeline to 10% of physical memory
+-	 */
++	/* Limit memory use for pipeline to 10% of physical memory */
+ 	si_meminfo(&si);
+-	if (tape->max_stages * tape->stage_size > si.totalram * si.mem_unit / 10)
+-		tape->max_stages = si.totalram * si.mem_unit / (10 * tape->stage_size);
++	if (tape->max_stages * tape->stage_size >
++			si.totalram * si.mem_unit / 10)
++		tape->max_stages =
++			si.totalram * si.mem_unit / (10 * tape->stage_size);
++
+ 	tape->max_stages   = min(tape->max_stages, IDETAPE_MAX_PIPELINE_STAGES);
+ 	tape->min_pipeline = min(tape->max_stages, IDETAPE_MIN_PIPELINE_STAGES);
+-	tape->max_pipeline = min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
+-	if (tape->max_stages == 0)
+-		tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;
++	tape->max_pipeline =
++		min(tape->max_stages * 2, IDETAPE_MAX_PIPELINE_STAGES);
++	if (tape->max_stages == 0) {
++		tape->max_stages   = 1;
++		tape->min_pipeline = 1;
++		tape->max_pipeline = 1;
++	}
  
--	/* If the requested sector doesn't start on a cdrom block boundary,
--	   we must adjust the start of the transfer so that it does,
--	   and remember to skip the first few sectors.
--	   If the CURRENT_NR_SECTORS field is larger than the size
--	   of the buffer, it will mean that we're to skip a number
--	   of sectors equal to the amount by which CURRENT_NR_SECTORS
--	   is larger than the buffer size. */
--	nskip = rq->sector & (sectors_per_frame - 1);
--	if (nskip > 0) {
--		/* Sanity check... */
--		if (rq->current_nr_sectors != bio_cur_sectors(rq->bio) &&
--			(rq->sector & (sectors_per_frame - 1))) {
--			printk(KERN_ERR "%s: cdrom_start_read_continuation: buffer botch (%u)\n",
--				drive->name, rq->current_nr_sectors);
--			cdrom_end_request(drive, 0);
--			return ide_stopped;
-+		/*
-+		 * If the requested sector doesn't start on a frame boundary,
-+		 * we must adjust the start of the transfer so that it does,
-+		 * and remember to skip the first few sectors.
-+		 *
-+		 * If the rq->current_nr_sectors field is larger than the size
-+		 * of the buffer, it will mean that we're to skip a number of
-+		 * sectors equal to the amount by which rq->current_nr_sectors
-+		 * is larger than the buffer size.
-+		 */
-+		if (nskip > 0) {
-+			/* Sanity check... */
-+			if (rq->current_nr_sectors !=
-+			    bio_cur_sectors(rq->bio)) {
-+				printk(KERN_ERR "%s: %s: buffer botch (%u)\n",
-+						drive->name, __FUNCTION__,
-+						rq->current_nr_sectors);
-+				cdrom_end_request(drive, 0);
-+				return ide_stopped;
-+			}
-+			rq->current_nr_sectors += nskip;
- 		}
--		rq->current_nr_sectors += nskip;
- 	}
--
-+#if 0
-+	else
-+		/* the immediate bit */
-+		rq->cmd[1] = 1 << 3;
-+#endif
- 	/* Set up the command */
- 	rq->timeout = ATAPI_WAIT_PC;
+ 	t1 = (tape->stage_size * HZ) / (speed * 1000);
+-	tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);
++	tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
+ 	tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
  
- 	/* Send the command to the drive and return. */
--	return cdrom_transfer_packet_command(drive, rq, &cdrom_read_intr);
-+	return cdrom_transfer_packet_command(drive, rq, cdrom_newpc_intr);
- }
+ 	if (tape->max_stages)
+@@ -4687,17 +3595,19 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
+ 		t = t1;
  
--
- #define IDECD_SEEK_THRESHOLD	(1000)			/* 1000 blocks */
- #define IDECD_SEEK_TIMER	(5 * WAIT_MIN_SLEEP)	/* 100 ms */
- #define IDECD_SEEK_TIMEOUT	(2 * WAIT_CMD)		/* 20 sec */
-@@ -1341,7 +852,8 @@ static ide_startstop_t cdrom_seek_intr (ide_drive_t *drive)
+ 	/*
+-	 *	Ensure that the number we got makes sense; limit
+-	 *	it within IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
++	 * Ensure that the number we got makes sense; limit it within
++	 * IDETAPE_DSC_RW_MIN and IDETAPE_DSC_RW_MAX.
+ 	 */
+-	tape->best_dsc_rw_frequency = max_t(unsigned long, min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
++	tape->best_dsc_rw_freq = max_t(unsigned long,
++				min_t(unsigned long, t, IDETAPE_DSC_RW_MAX),
++				IDETAPE_DSC_RW_MIN);
+ 	printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
+ 		"%dkB pipeline, %lums tDSC%s\n",
+-		drive->name, tape->name, tape->capabilities.speed,
+-		(tape->capabilities.buffer_size * 512) / tape->stage_size,
++		drive->name, tape->name, *(u16 *)&tape->caps[14],
++		(*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
+ 		tape->stage_size / 1024,
+ 		tape->max_stages * tape->stage_size / 1024,
+-		tape->best_dsc_rw_frequency * 1000 / HZ,
++		tape->best_dsc_rw_freq * 1000 / HZ,
+ 		drive->using_dma ? ", DMA":"");
  
- 	if (cdrom_decode_status(drive, 0, &stat))
- 		return ide_stopped;
--	CDROM_CONFIG_FLAGS(drive)->seeking = 1;
-+
-+	info->cd_flags |= IDE_CD_FLAG_SEEKING;
+ 	idetape_add_settings(drive);
+@@ -4724,9 +3634,8 @@ static void ide_tape_release(struct kref *kref)
  
- 	if (retry && time_after(jiffies, info->start_seek + IDECD_SEEK_TIMER)) {
- 		if (--retry == 0) {
-@@ -1397,184 +909,25 @@ static void restore_request (struct request *rq)
- 	rq->q->prep_rq_fn(rq->q, rq);
- }
+ 	drive->dsc_overlap = 0;
+ 	drive->driver_data = NULL;
+-	class_device_destroy(idetape_sysfs_class,
+-			MKDEV(IDETAPE_MAJOR, tape->minor));
+-	class_device_destroy(idetape_sysfs_class,
++	device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
++	device_destroy(idetape_sysfs_class,
+ 			MKDEV(IDETAPE_MAJOR, tape->minor + 128));
+ 	idetape_devs[tape->minor] = NULL;
+ 	g->private_data = NULL;
+@@ -4776,9 +3685,7 @@ static ide_driver_t idetape_driver = {
+ #endif
+ };
  
 -/*
-- * Start a read request from the CD-ROM.
+- *	Our character device supporting functions, passed to register_chrdev.
 - */
--static ide_startstop_t cdrom_start_read (ide_drive_t *drive, unsigned int block)
--{
--	struct cdrom_info *info = drive->driver_data;
--	struct request *rq = HWGROUP(drive)->rq;
--	unsigned short sectors_per_frame;
--
--	sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
--
--	/* We may be retrying this request after an error.  Fix up
--	   any weirdness which might be present in the request packet. */
--	restore_request(rq);
--
--	/* Satisfy whatever we can of this request from our cached sector. */
--	if (cdrom_read_from_buffer(drive))
--		return ide_stopped;
--
--	/* Clear the local sector buffer. */
--	info->nsectors_buffered = 0;
--
--	/* use dma, if possible. */
--	info->dma = drive->using_dma;
--	if ((rq->sector & (sectors_per_frame - 1)) ||
--	    (rq->nr_sectors & (sectors_per_frame - 1)))
--		info->dma = 0;
--
--	/* Start sending the read request to the drive. */
--	return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation);
--}
++/* Our character device supporting functions, passed to register_chrdev. */
+ static const struct file_operations idetape_fops = {
+ 	.owner		= THIS_MODULE,
+ 	.read		= idetape_chrdev_read,
+@@ -4793,7 +3700,8 @@ static int idetape_open(struct inode *inode, struct file *filp)
+ 	struct gendisk *disk = inode->i_bdev->bd_disk;
+ 	struct ide_tape_obj *tape;
+ 
+-	if (!(tape = ide_tape_get(disk)))
++	tape = ide_tape_get(disk);
++	if (!tape)
+ 		return -ENXIO;
+ 
+ 	return 0;
+@@ -4840,21 +3748,20 @@ static int ide_tape_probe(ide_drive_t *drive)
+ 		goto failed;
+ 	if (drive->media != ide_tape)
+ 		goto failed;
+-	if (!idetape_identify_device (drive)) {
+-		printk(KERN_ERR "ide-tape: %s: not supported by this version of ide-tape\n", drive->name);
++	if (!idetape_identify_device(drive)) {
++		printk(KERN_ERR "ide-tape: %s: not supported by this version of"
++				" the driver\n", drive->name);
+ 		goto failed;
+ 	}
+ 	if (drive->scsi) {
+-		printk("ide-tape: passing drive %s to ide-scsi emulation.\n", drive->name);
++		printk(KERN_INFO "ide-tape: passing drive %s to ide-scsi"
++				 " emulation.\n", drive->name);
+ 		goto failed;
+ 	}
+-	if (strstr(drive->id->model, "OnStream DI-")) {
+-		printk(KERN_WARNING "ide-tape: Use drive %s with ide-scsi emulation and osst.\n", drive->name);
+-		printk(KERN_WARNING "ide-tape: OnStream support will be removed soon from ide-tape!\n");
+-	}
+-	tape = kzalloc(sizeof (idetape_tape_t), GFP_KERNEL);
++	tape = kzalloc(sizeof(idetape_tape_t), GFP_KERNEL);
+ 	if (tape == NULL) {
+-		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name);
++		printk(KERN_ERR "ide-tape: %s: Can't allocate a tape struct\n",
++				drive->name);
+ 		goto failed;
+ 	}
+ 
+@@ -4884,10 +3791,10 @@ static int ide_tape_probe(ide_drive_t *drive)
+ 
+ 	idetape_setup(drive, tape, minor);
+ 
+-	class_device_create(idetape_sysfs_class, NULL,
+-			MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
+-	class_device_create(idetape_sysfs_class, NULL,
+-			MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
++	device_create(idetape_sysfs_class, &drive->gendev,
++		      MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
++	device_create(idetape_sysfs_class, &drive->gendev,
++			MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
+ 
+ 	g->fops = &idetape_block_ops;
+ 	ide_register_region(g);
+@@ -4900,10 +3807,7 @@ failed:
+ 	return -ENODEV;
+ }
+ 
+-MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
+-MODULE_LICENSE("GPL");
 -
- /****************************************************************************
-  * Execute all other packet commands.
+-static void __exit idetape_exit (void)
++static void __exit idetape_exit(void)
+ {
+ 	driver_unregister(&idetape_driver.gen_driver);
+ 	class_destroy(idetape_sysfs_class);
+@@ -4922,7 +3826,8 @@ static int __init idetape_init(void)
+ 	}
+ 
+ 	if (register_chrdev(IDETAPE_MAJOR, "ht", &idetape_fops)) {
+-		printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
++		printk(KERN_ERR "ide-tape: Failed to register chrdev"
++				" interface\n");
+ 		error = -EBUSY;
+ 		goto out_free_class;
+ 	}
+@@ -4945,3 +3850,5 @@ MODULE_ALIAS("ide:*m-tape*");
+ module_init(idetape_init);
+ module_exit(idetape_exit);
+ MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR);
++MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
+index 2b60f1b..0518a2e 100644
+--- a/drivers/ide/ide-taskfile.c
++++ b/drivers/ide/ide-taskfile.c
+@@ -1,11 +1,9 @@
+ /*
+- * linux/drivers/ide/ide-taskfile.c	Version 0.38	March 05, 2003
+- *
+- *  Copyright (C) 2000-2002	Michael Cornwell <cornwell at acm.org>
+- *  Copyright (C) 2000-2002	Andre Hedrick <andre at linux-ide.org>
+- *  Copyright (C) 2001-2002	Klaus Smolin
++ *  Copyright (C) 2000-2002	   Michael Cornwell <cornwell at acm.org>
++ *  Copyright (C) 2000-2002	   Andre Hedrick <andre at linux-ide.org>
++ *  Copyright (C) 2001-2002	   Klaus Smolin
+  *					IBM Storage Technology Division
+- *  Copyright (C) 2003-2004	Bartlomiej Zolnierkiewicz
++ *  Copyright (C) 2003-2004, 2007  Bartlomiej Zolnierkiewicz
+  *
+  *  The big the bad and the ugly.
   */
+@@ -35,93 +33,81 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
  
--/* Interrupt routine for packet command completion. */
--static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
-+static void ide_cd_request_sense_fixup(struct request *rq)
+-static void ata_bswap_data (void *buffer, int wcount)
++void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
  {
--	int ireason, len, thislen;
--	struct request *rq = HWGROUP(drive)->rq;
--	u8 lowcyl = 0, highcyl = 0;
--	int stat;
--
--	/* Check for errors. */
--	if (cdrom_decode_status(drive, 0, &stat))
--		return ide_stopped;
--
--	/* Read the interrupt reason and the transfer length. */
--	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
--	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
--	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
--
--	len = lowcyl + (256 * highcyl);
--
--	/* If DRQ is clear, the command has completed.
--	   Complain if we still have data left to transfer. */
--	if ((stat & DRQ_STAT) == 0) {
--		/* Some of the trailing request sense fields are optional, and
--		   some drives don't send them.  Sigh. */
--		if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
--		    rq->data_len > 0 &&
--		    rq->data_len <= 5) {
--			while (rq->data_len > 0) {
--				*(unsigned char *)rq->data++ = 0;
--				--rq->data_len;
--			}
--		}
--
--		if (rq->data_len == 0)
--			cdrom_end_request(drive, 1);
--		else {
--			/* Comment this out, because this always happens 
--			   right after a reset occurs, and it is annoying to 
--			   always print expected stuff.  */
--			/*
--			printk ("%s: cdrom_pc_intr: data underrun %d\n",
--				drive->name, pc->buflen);
--			*/
--			rq->cmd_flags |= REQ_FAILED;
--			cdrom_end_request(drive, 0);
--		}
--		return ide_stopped;
--	}
--
--	/* Figure out how much data to transfer. */
--	thislen = rq->data_len;
--	if (thislen > len) thislen = len;
--
--	/* The drive wants to be written to. */
--	if (ireason == 0) {
--		if (!rq->data) {
--			blk_dump_rq_flags(rq, "cdrom_pc_intr, write");
--			goto confused;
--		}
--		/* Transfer the data. */
--		HWIF(drive)->atapi_output_bytes(drive, rq->data, thislen);
--
--		/* If we haven't moved enough data to satisfy the drive,
--		   add some padding. */
--		while (len > thislen) {
--			int dum = 0;
--			HWIF(drive)->atapi_output_bytes(drive, &dum, sizeof(dum));
--			len -= sizeof(dum);
--		}
--
--		/* Keep count of how much data we've moved. */
--		rq->data += thislen;
--		rq->data_len -= thislen;
--	}
--
--	/* Same drill for reading. */
--	else if (ireason == 2) {
--		if (!rq->data) {
--			blk_dump_rq_flags(rq, "cdrom_pc_intr, read");
--			goto confused;
--		}
--		/* Transfer the data. */
--		HWIF(drive)->atapi_input_bytes(drive, rq->data, thislen);
--
--		/* If we haven't moved enough data to satisfy the drive,
--		   add some padding. */
--		while (len > thislen) {
--			int dum = 0;
--			HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
--			len -= sizeof(dum);
-+	/*
-+	 * Some of the trailing request sense fields are optional,
-+	 * and some drives don't send them.  Sigh.
-+	 */
-+	if (rq->cmd[0] == GPCMD_REQUEST_SENSE &&
-+	    rq->data_len > 0 && rq->data_len <= 5)
-+		while (rq->data_len > 0) {
-+			*(u8 *)rq->data++ = 0;
-+			--rq->data_len;
- 		}
--
--		/* Keep count of how much data we've moved. */
--		rq->data += thislen;
--		rq->data_len -= thislen;
--
--		if (blk_sense_request(rq))
--			rq->sense_len += thislen;
--	} else {
--confused:
--		printk (KERN_ERR "%s: cdrom_pc_intr: The drive "
--			"appears confused (ireason = 0x%02x). "
--			"Trying to recover by ending request.\n",
--			drive->name, ireason);
--		rq->cmd_flags |= REQ_FAILED;
--		cdrom_end_request(drive, 0);
--		return ide_stopped;
+-	u16 *p = buffer;
++	ide_hwif_t *hwif = drive->hwif;
++	struct ide_taskfile *tf = &task->tf;
++	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
++
++	if (task->tf_flags & IDE_TFLAG_FLAGGED)
++		HIHI = 0xFF;
++
++#ifdef DEBUG
++	printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
++		"lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
++		drive->name, tf->feature, tf->nsect, tf->lbal,
++		tf->lbam, tf->lbah, tf->device, tf->command);
++	printk("%s: hob: nsect 0x%02x lbal 0x%02x "
++		"lbam 0x%02x lbah 0x%02x\n",
++		drive->name, tf->hob_nsect, tf->hob_lbal,
++		tf->hob_lbam, tf->hob_lbah);
++#endif
+ 
+-	while (wcount--) {
+-		*p = *p << 8 | *p >> 8; p++;
+-		*p = *p << 8 | *p >> 8; p++;
 -	}
--
--	/* Now we wait for another interrupt. */
--	ide_set_handler(drive, &cdrom_pc_intr, ATAPI_WAIT_PC, cdrom_timer_expiry);
--	return ide_started;
 -}
 -
--static ide_startstop_t cdrom_do_pc_continuation (ide_drive_t *drive)
+-static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
 -{
--	struct request *rq = HWGROUP(drive)->rq;
--
--	if (!rq->timeout)
--		rq->timeout = ATAPI_WAIT_PC;
--
--	/* Send the command to the drive and return. */
--	return cdrom_transfer_packet_command(drive, rq, &cdrom_pc_intr);
+-	HWIF(drive)->ata_input_data(drive, buffer, wcount);
+-	if (drive->bswap)
+-		ata_bswap_data(buffer, wcount);
 -}
 -
--
--static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
+-static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
 -{
--	int len;
--	struct request *rq = HWGROUP(drive)->rq;
--	struct cdrom_info *info = drive->driver_data;
--
--	info->dma = 0;
--	rq->cmd_flags &= ~REQ_FAILED;
--	len = rq->data_len;
--
--	/* Start sending the command to the drive. */
--	return cdrom_start_packet_command(drive, len, cdrom_do_pc_continuation);
+-	if (drive->bswap) {
+-		ata_bswap_data(buffer, wcount);
+-		HWIF(drive)->ata_output_data(drive, buffer, wcount);
+-		ata_bswap_data(buffer, wcount);
+-	} else {
+-		HWIF(drive)->ata_output_data(drive, buffer, wcount);
+-	}
++	ide_set_irq(drive, 1);
++
++	if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
++		SELECT_MASK(drive, 0);
++
++	if (task->tf_flags & IDE_TFLAG_OUT_DATA)
++		hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
++
++	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
++		hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
++		hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
++		hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
++		hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
++		hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
++
++	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
++		hwif->OUTB(tf->feature, IDE_FEATURE_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
++		hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
++		hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
++		hwif->OUTB(tf->lbam, IDE_LCYL_REG);
++	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
++		hwif->OUTB(tf->lbah, IDE_HCYL_REG);
++
++	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
++		hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
  }
  
--
--static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
-+int ide_cd_queue_pc(ide_drive_t *drive, struct request *rq)
+ int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
  {
- 	struct request_sense sense;
- 	int retries = 10;
-@@ -1623,59 +976,37 @@ static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+ 	ide_task_t args;
++
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	args.tfRegister[IDE_NSECTOR_OFFSET]	= 0x01;
++	args.tf.nsect = 0x01;
+ 	if (drive->media == ide_disk)
+-		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_IDENTIFY;
++		args.tf.command = WIN_IDENTIFY;
+ 	else
+-		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_PIDENTIFY;
+-	args.command_type = IDE_DRIVE_TASK_IN;
+-	args.data_phase   = TASKFILE_IN;
+-	args.handler	  = &task_in_intr;
+-	return ide_raw_taskfile(drive, &args, buf);
++		args.tf.command = WIN_PIDENTIFY;
++	args.tf_flags	= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	args.data_phase	= TASKFILE_IN;
++	return ide_raw_taskfile(drive, &args, buf, 1);
  }
  
- /*
-- * Write handling
-+ * Called from blk_end_request_callback() after the data of the request
-+ * is completed and before the request is completed.
-+ * By returning value '1', blk_end_request_callback() returns immediately
-+ * without completing the request.
-  */
--static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason)
-+static int cdrom_newpc_intr_dummy_cb(struct request *rq)
+-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
++static int inline task_dma_ok(ide_task_t *task)
  {
--	/* Two notes about IDE interrupt reason here - 0 means that
--	 * the drive wants to receive data from us, 2 means that
--	 * the drive is expecting to transfer data to us.
--	 */
--	if (ireason == 0)
--		return 0;
--	else if (ireason == 2) {
--		/* Whoops... The drive wants to send data. */
--		printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
--				drive->name, __FUNCTION__);
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	task_struct_t *taskfile	= (task_struct_t *) task->tfRegister;
+-	hob_struct_t *hobfile	= (hob_struct_t *) task->hobRegister;
+-	u8 HIHI			= (drive->addressing == 1) ? 0xE0 : 0xEF;
 -
--		while (len > 0) {
--			int dum = 0;
--			HWIF(drive)->atapi_input_bytes(drive, &dum, sizeof(dum));
--			len -= sizeof(dum);
--		}
--	} else {
--		/* Drive wants a command packet, or invalid ireason... */
--		printk(KERN_ERR "%s: %s: bad interrupt reason 0x%02x\n",
--				drive->name, __FUNCTION__, ireason);
+-	/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
+-	if (IDE_CONTROL_REG) {
+-		/* clear nIEN */
+-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
 -	}
+-	SELECT_MASK(drive, 0);
 -
--	cdrom_end_request(drive, 0);
- 	return 1;
- }
- 
--typedef void (xfer_func_t)(ide_drive_t *, void *, u32);
+-	if (drive->addressing == 1) {
+-		hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
+-		hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
+-		hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
+-		hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
+-		hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
+-	}
 -
--/*
-- * best way to deal with dma that is not sector aligned right now... note
-- * that in this path we are not using ->data or ->buffer at all. this irs
-- * can replace cdrom_pc_intr, cdrom_read_intr, and cdrom_write_intr in the
-- * future.
-- */
- static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
- {
- 	struct cdrom_info *info = drive->driver_data;
- 	struct request *rq = HWGROUP(drive)->rq;
--	int dma_error, dma, stat, ireason, len, thislen;
--	u8 lowcyl, highcyl;
- 	xfer_func_t *xferfunc;
--	unsigned long flags;
-+	ide_expiry_t *expiry = NULL;
-+	int dma_error = 0, dma, stat, ireason, len, thislen, uptodate = 0;
-+	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0;
-+	unsigned int timeout;
-+	u8 lowcyl, highcyl;
- 
- 	/* Check for errors. */
--	dma_error = 0;
- 	dma = info->dma;
- 	if (dma) {
- 		info->dma = 0;
- 		dma_error = HWIF(drive)->ide_dma_end(drive);
-+		if (dma_error) {
-+			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
-+					write ? "write" : "read");
-+			ide_dma_off(drive);
-+		}
- 	}
+-	hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
+-	hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
+-	hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
+-	hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
+-	hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
+-
+-	hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
+-
+-	if (task->handler != NULL) {
+-		if (task->prehandler != NULL) {
+-			hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
+-			ndelay(400);	/* FIXME */
+-			return task->prehandler(drive, task->rq);
+-		}
+-		ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
+-		return ide_started;
+-	}
++	if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
++		return 1;
  
- 	if (cdrom_decode_status(drive, 0, &stat))
-@@ -1685,14 +1016,12 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
- 	 * using dma, transfer is complete now
- 	 */
- 	if (dma) {
--		if (dma_error) {
--			printk(KERN_ERR "ide-cd: dma error\n");
--			ide_dma_off(drive);
-+		if (dma_error)
- 			return ide_error(drive, "dma error", stat);
-+		if (blk_fs_request(rq)) {
-+			ide_end_request(drive, 1, rq->nr_sectors);
-+			return ide_stopped;
- 		}
+-	if (!drive->using_dma)
+-		return ide_stopped;
 -
--		end_that_request_chunk(rq, 1, rq->data_len);
--		rq->data_len = 0;
- 		goto end_request;
+-	switch (taskfile->command) {
++	switch (task->tf.command) {
+ 		case WIN_WRITEDMA_ONCE:
+ 		case WIN_WRITEDMA:
+ 		case WIN_WRITEDMA_EXT:
+@@ -129,31 +115,85 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ 		case WIN_READDMA:
+ 		case WIN_READDMA_EXT:
+ 		case WIN_IDENTIFY_DMA:
+-			if (!hwif->dma_setup(drive)) {
+-				hwif->dma_exec_cmd(drive, taskfile->command);
+-				hwif->dma_start(drive);
+-				return ide_started;
+-			}
+-			break;
+-		default:
+-			if (task->handler == NULL)
+-				return ide_stopped;
++			return 1;
  	}
  
-@@ -1704,54 +1033,120 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
- 	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
+-	return ide_stopped;
++	return 0;
+ }
  
- 	len = lowcyl + (256 * highcyl);
--	thislen = rq->data_len;
++static ide_startstop_t task_no_data_intr(ide_drive_t *);
++static ide_startstop_t set_geometry_intr(ide_drive_t *);
++static ide_startstop_t recal_intr(ide_drive_t *);
++static ide_startstop_t set_multmode_intr(ide_drive_t *);
++static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
++static ide_startstop_t task_in_intr(ide_drive_t *);
 +
-+	thislen = blk_fs_request(rq) ? len : rq->data_len;
- 	if (thislen > len)
- 		thislen = len;
- 
- 	/*
- 	 * If DRQ is clear, the command has completed.
- 	 */
--	if ((stat & DRQ_STAT) == 0)
-+	if ((stat & DRQ_STAT) == 0) {
-+		if (blk_fs_request(rq)) {
-+			/*
-+			 * If we're not done reading/writing, complain.
-+			 * Otherwise, complete the command normally.
-+			 */
-+			uptodate = 1;
-+			if (rq->current_nr_sectors > 0) {
-+				printk(KERN_ERR "%s: %s: data underrun "
-+						"(%d blocks)\n",
-+						drive->name, __FUNCTION__,
-+						rq->current_nr_sectors);
-+				if (!write)
-+					rq->cmd_flags |= REQ_FAILED;
-+				uptodate = 0;
-+			}
-+			cdrom_end_request(drive, uptodate);
++ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
++{
++	ide_hwif_t *hwif	= HWIF(drive);
++	struct ide_taskfile *tf = &task->tf;
++	ide_handler_t *handler = NULL;
++
++	if (task->data_phase == TASKFILE_MULTI_IN ||
++	    task->data_phase == TASKFILE_MULTI_OUT) {
++		if (!drive->mult_count) {
++			printk(KERN_ERR "%s: multimode not set!\n",
++					drive->name);
 +			return ide_stopped;
-+		} else if (!blk_pc_request(rq)) {
-+			ide_cd_request_sense_fixup(rq);
-+			/* Complain if we still have data left to transfer. */
-+			uptodate = rq->data_len ? 0 : 1;
 +		}
- 		goto end_request;
 +	}
- 
- 	/*
- 	 * check which way to transfer data
- 	 */
--	if (rq_data_dir(rq) == WRITE) {
--		/*
--		 * write to drive
--		 */
--		if (cdrom_write_check_ireason(drive, len, ireason))
-+	if (blk_fs_request(rq) || blk_pc_request(rq)) {
-+		if (ide_cd_check_ireason(drive, len, ireason, write))
- 			return ide_stopped;
- 
--		xferfunc = HWIF(drive)->atapi_output_bytes;
--	} else  {
--		/*
--		 * read from drive
--		 */
--		if (cdrom_read_check_ireason(drive, len, ireason))
--			return ide_stopped;
-+		if (blk_fs_request(rq) && write == 0) {
-+			int nskip;
 +
-+			if (ide_cd_check_transfer_size(drive, len)) {
-+				cdrom_end_request(drive, 0);
-+				return ide_stopped;
-+			}
- 
-+			/*
-+			 * First, figure out if we need to bit-bucket
-+			 * any of the leading sectors.
-+			 */
-+			nskip = min_t(int, rq->current_nr_sectors
-+					   - bio_cur_sectors(rq->bio),
-+					   thislen >> 9);
-+			if (nskip > 0) {
-+				ide_cd_drain_data(drive, nskip);
-+				rq->current_nr_sectors -= nskip;
-+				thislen -= (nskip << 9);
++	if (task->tf_flags & IDE_TFLAG_FLAGGED)
++		task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
++
++	if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
++		ide_tf_load(drive, task);
++
++	switch (task->data_phase) {
++	case TASKFILE_MULTI_OUT:
++	case TASKFILE_OUT:
++		hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
++		ndelay(400);	/* FIXME */
++		return pre_task_out_intr(drive, task->rq);
++	case TASKFILE_MULTI_IN:
++	case TASKFILE_IN:
++		handler = task_in_intr;
++		/* fall-through */
++	case TASKFILE_NO_DATA:
++		if (handler == NULL)
++			handler = task_no_data_intr;
++		/* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
++		if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
++			switch (tf->command) {
++			case WIN_SPECIFY: handler = set_geometry_intr;	break;
++			case WIN_RESTORE: handler = recal_intr;		break;
++			case WIN_SETMULT: handler = set_multmode_intr;	break;
 +			}
 +		}
++		ide_execute_command(drive, tf->command, handler,
++				    WAIT_WORSTCASE, NULL);
++		return ide_started;
++	default:
++		if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
++		    hwif->dma_setup(drive))
++			return ide_stopped;
++		hwif->dma_exec_cmd(drive, tf->command);
++		hwif->dma_start(drive);
++		return ide_started;
 +	}
++}
++EXPORT_SYMBOL_GPL(do_rw_taskfile);
 +
-+	if (ireason == 0) {
-+		write = 1;
-+		xferfunc = HWIF(drive)->atapi_output_bytes;
-+	} else if (ireason == 2 || (ireason == 1 &&
-+		   (blk_fs_request(rq) || blk_pc_request(rq)))) {
-+		write = 0;
- 		xferfunc = HWIF(drive)->atapi_input_bytes;
-+	} else {
-+		printk(KERN_ERR "%s: %s: The drive "
-+				"appears confused (ireason = 0x%02x). "
-+				"Trying to recover by ending request.\n",
-+				drive->name, __FUNCTION__, ireason);
-+		goto end_request;
- 	}
+ /*
+  * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
+  */
+-ide_startstop_t set_multmode_intr (ide_drive_t *drive)
++static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+-	u8 stat;
++	u8 stat = ide_read_status(drive);
  
- 	/*
- 	 * transfer data
- 	 */
- 	while (thislen > 0) {
--		int blen = blen = rq->data_len;
--		char *ptr = rq->data;
-+		u8 *ptr = blk_fs_request(rq) ? NULL : rq->data;
-+		int blen = rq->data_len;
+-	if (OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
++	if (OK_STAT(stat, READY_STAT, BAD_STAT))
+ 		drive->mult_count = drive->mult_req;
+-	} else {
++	else {
+ 		drive->mult_req = drive->mult_count = 0;
+ 		drive->special.b.recalibrate = 1;
+ 		(void) ide_dump_status(drive, "set_multmode", stat);
+@@ -164,13 +204,12 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
+ /*
+  * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
+  */
+-ide_startstop_t set_geometry_intr (ide_drive_t *drive)
++static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+ 	int retries = 5;
+ 	u8 stat;
  
- 		/*
- 		 * bio backed?
- 		 */
- 		if (rq->bio) {
--			ptr = bio_data(rq->bio);
--			blen = bio_iovec(rq->bio)->bv_len;
-+			if (blk_fs_request(rq)) {
-+				ptr = rq->buffer;
-+				blen = rq->current_nr_sectors << 9;
-+			} else {
-+				ptr = bio_data(rq->bio);
-+				blen = bio_iovec(rq->bio)->bv_len;
-+			}
- 		}
+-	while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
++	while (((stat = ide_read_status(drive)) & BUSY_STAT) && retries--)
+ 		udelay(10);
  
- 		if (!ptr) {
--			printk(KERN_ERR "%s: confused, missing data\n", drive->name);
-+			if (blk_fs_request(rq) && !write)
-+				/*
-+				 * If the buffers are full, cache the rest
-+				 * of the data in our internal buffer.
-+				 */
-+				cdrom_buffer_sectors(drive, rq->sector,
-+						     thislen >> 9);
-+			else {
-+				printk(KERN_ERR "%s: confused, missing data\n",
-+						drive->name);
-+				blk_dump_rq_flags(rq, rq_data_dir(rq)
-+						  ? "cdrom_newpc_intr, write"
-+						  : "cdrom_newpc_intr, read");
-+			}
- 			break;
- 		}
+ 	if (OK_STAT(stat, READY_STAT, BAD_STAT))
+@@ -187,12 +226,11 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
+ /*
+  * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
+  */
+-ide_startstop_t recal_intr (ide_drive_t *drive)
++static ide_startstop_t recal_intr(ide_drive_t *drive)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+-	u8 stat;
++	u8 stat = ide_read_status(drive);
  
-@@ -1762,186 +1157,117 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
+-	if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), READY_STAT, BAD_STAT))
++	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ 		return ide_error(drive, "recal_intr", stat);
+ 	return ide_stopped;
+ }
+@@ -200,38 +238,37 @@ ide_startstop_t recal_intr (ide_drive_t *drive)
+ /*
+  * Handler for commands without a data phase
+  */
+-ide_startstop_t task_no_data_intr (ide_drive_t *drive)
++static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
+ {
+ 	ide_task_t *args	= HWGROUP(drive)->rq->special;
+-	ide_hwif_t *hwif	= HWIF(drive);
+ 	u8 stat;
  
- 		thislen -= blen;
- 		len -= blen;
--		rq->data_len -= blen;
--
--		if (rq->bio)
--			end_that_request_chunk(rq, 1, blen);
--		else
--			rq->data += blen;
--	}
--
--	/*
--	 * pad, if necessary
--	 */
--	if (len > 0) {
--		while (len > 0) {
--			int pad = 0;
--
--			xferfunc(drive, &pad, sizeof(pad));
--			len -= sizeof(pad);
--		}
+ 	local_irq_enable_in_hardirq();
+-	if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG),READY_STAT,BAD_STAT)) {
++	stat = ide_read_status(drive);
++
++	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
+ 		return ide_error(drive, "task_no_data_intr", stat);
+ 		/* calls ide_end_drive_cmd */
 -	}
--
--	BUG_ON(HWGROUP(drive)->handler != NULL);
++
+ 	if (args)
+-		ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
++		ide_end_drive_cmd(drive, stat, ide_read_error(drive));
  
--	ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL);
--	return ide_started;
--
--end_request:
--	spin_lock_irqsave(&ide_lock, flags);
--	blkdev_dequeue_request(rq);
--	end_that_request_last(rq, 1);
--	HWGROUP(drive)->rq = NULL;
--	spin_unlock_irqrestore(&ide_lock, flags);
--	return ide_stopped;
--}
+ 	return ide_stopped;
+ }
+ 
+-EXPORT_SYMBOL(task_no_data_intr);
 -
--static ide_startstop_t cdrom_write_intr(ide_drive_t *drive)
--{
--	int stat, ireason, len, sectors_to_transfer, uptodate;
--	struct cdrom_info *info = drive->driver_data;
--	int dma_error = 0, dma = info->dma;
--	u8 lowcyl = 0, highcyl = 0;
-+		if (blk_fs_request(rq)) {
-+			rq->buffer += blen;
-+			rq->nr_sectors -= (blen >> 9);
-+			rq->current_nr_sectors -= (blen >> 9);
-+			rq->sector += (blen >> 9);
+ static u8 wait_drive_not_busy(ide_drive_t *drive)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+ 	int retries;
+ 	u8 stat;
  
--	struct request *rq = HWGROUP(drive)->rq;
-+			if (rq->current_nr_sectors == 0 && rq->nr_sectors)
-+				cdrom_end_request(drive, 1);
-+		} else {
-+			rq->data_len -= blen;
+ 	/*
+ 	 * Last sector was transfered, wait until drive is ready.
+-	 * This can take up to 10 usec, but we will wait max 1 ms
+-	 * (drive_cmd_intr() waits that long).
++	 * This can take up to 10 usec, but we will wait max 1 ms.
+ 	 */
+ 	for (retries = 0; retries < 100; retries++) {
+-		if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
++		stat = ide_read_status(drive);
++
++		if (stat & BUSY_STAT)
+ 			udelay(10);
+ 		else
+ 			break;
+@@ -283,9 +320,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
  
--	/* Check for errors. */
--	if (dma) {
--		info->dma = 0;
--		dma_error = HWIF(drive)->ide_dma_end(drive);
--		if (dma_error) {
--			printk(KERN_ERR "%s: DMA write error\n", drive->name);
--			ide_dma_off(drive);
-+			/*
-+			 * The request can't be completed until DRQ is cleared.
-+			 * So complete the data, but don't complete the request
-+			 * using the dummy function for the callback feature
-+			 * of blk_end_request_callback().
-+			 */
-+			if (rq->bio)
-+				blk_end_request_callback(rq, 0, blen,
-+						 cdrom_newpc_intr_dummy_cb);
-+			else
-+				rq->data += blen;
- 		}
- 	}
+ 	/* do the actual data transfer */
+ 	if (write)
+-		taskfile_output_data(drive, buf, SECTOR_WORDS);
++		hwif->ata_output_data(drive, buf, SECTOR_WORDS);
+ 	else
+-		taskfile_input_data(drive, buf, SECTOR_WORDS);
++		hwif->ata_input_data(drive, buf, SECTOR_WORDS);
  
--	if (cdrom_decode_status(drive, 0, &stat))
--		return ide_stopped;
-+	if (write && blk_sense_request(rq))
-+		rq->sense_len += thislen;
+ 	kunmap_atomic(buf, KM_BIO_SRC_IRQ);
+ #ifdef CONFIG_HIGHMEM
+@@ -305,9 +342,18 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
+ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+ 				     unsigned int write)
+ {
++	u8 saved_io_32bit = drive->io_32bit;
++
+ 	if (rq->bio)	/* fs request */
+ 		rq->errors = 0;
  
- 	/*
--	 * using dma, transfer is complete now
-+	 * pad, if necessary
- 	 */
--	if (dma) {
--		if (dma_error)
--			return ide_error(drive, "dma error", stat);
-+	if (!blk_fs_request(rq) && len > 0)
-+		ide_cd_pad_transfer(drive, xferfunc, len);
++	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
++		ide_task_t *task = rq->special;
++
++		if (task->tf_flags & IDE_TFLAG_IO_16BIT)
++			drive->io_32bit = 0;
++	}
++
+ 	touch_softlockup_watchdog();
  
--		ide_end_request(drive, 1, rq->nr_sectors);
--		return ide_stopped;
-+	if (blk_pc_request(rq)) {
-+		timeout = rq->timeout;
-+	} else {
-+		timeout = ATAPI_WAIT_PC;
-+		if (!blk_fs_request(rq))
-+			expiry = cdrom_timer_expiry;
+ 	switch (drive->hwif->data_phase) {
+@@ -319,6 +365,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
+ 		ide_pio_sector(drive, write);
+ 		break;
  	}
++
++	drive->io_32bit = saved_io_32bit;
+ }
  
--	/* Read the interrupt reason and the transfer length. */
--	ireason = HWIF(drive)->INB(IDE_IREASON_REG) & 0x3;
--	lowcyl  = HWIF(drive)->INB(IDE_BCOUNTL_REG);
--	highcyl = HWIF(drive)->INB(IDE_BCOUNTH_REG);
-+	ide_set_handler(drive, cdrom_newpc_intr, timeout, expiry);
-+	return ide_started;
+ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
+@@ -356,40 +404,35 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
+ 	return ide_error(drive, s, stat);
+ }
  
--	len = lowcyl + (256 * highcyl);
-+end_request:
-+	if (blk_pc_request(rq)) {
-+		unsigned long flags;
+-static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
++void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
+ {
+-	HWIF(drive)->cursg = NULL;
+-
+ 	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
+-		ide_task_t *task = rq->special;
++		u8 err = ide_read_error(drive);
  
--	/* If DRQ is clear, the command has completed. */
--	if ((stat & DRQ_STAT) == 0) {
--		/* If we're not done writing, complain.
--		 * Otherwise, complete the command normally.
--		 */
--		uptodate = 1;
--		if (rq->current_nr_sectors > 0) {
--			printk(KERN_ERR "%s: %s: data underrun (%d blocks)\n",
--					drive->name, __FUNCTION__,
--					rq->current_nr_sectors);
--			uptodate = 0;
+-		if (task->tf_out_flags.all) {
+-			u8 err = drive->hwif->INB(IDE_ERROR_REG);
+-			ide_end_drive_cmd(drive, stat, err);
+-			return;
 -		}
-+		spin_lock_irqsave(&ide_lock, flags);
-+		if (__blk_end_request(rq, 0, rq->data_len))
-+			BUG();
-+		HWGROUP(drive)->rq = NULL;
-+		spin_unlock_irqrestore(&ide_lock, flags);
-+	} else {
-+		if (!uptodate)
-+			rq->cmd_flags |= REQ_FAILED;
- 		cdrom_end_request(drive, uptodate);
--		return ide_stopped;
++		ide_end_drive_cmd(drive, stat, err);
++		return;
  	}
-+	return ide_stopped;
-+}
  
--	/* Check that the drive is expecting to do the same thing we are. */
--	if (cdrom_write_check_ireason(drive, len, ireason))
--		return ide_stopped;
--
--	sectors_to_transfer = len / SECTOR_SIZE;
--
--	/*
--	 * now loop and write out the data
--	 */
--	while (sectors_to_transfer > 0) {
--		int this_transfer;
--
--		if (!rq->current_nr_sectors) {
--			printk(KERN_ERR "%s: %s: confused, missing data\n",
--					drive->name, __FUNCTION__);
--			break;
--		}
-+static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
-+{
-+	struct cdrom_info *cd = drive->driver_data;
-+	int write = rq_data_dir(rq) == WRITE;
-+	unsigned short sectors_per_frame =
-+		queue_hardsect_size(drive->queue) >> SECTOR_BITS;
+ 	if (rq->rq_disk) {
+ 		ide_driver_t *drv;
  
-+	if (write) {
- 		/*
--		 * Figure out how many sectors we can transfer
-+		 * disk has become write protected
- 		 */
--		this_transfer = min_t(int, sectors_to_transfer, rq->current_nr_sectors);
--
--		while (this_transfer > 0) {
--			HWIF(drive)->atapi_output_bytes(drive, rq->buffer, SECTOR_SIZE);
--			rq->buffer += SECTOR_SIZE;
--			--rq->nr_sectors;
--			--rq->current_nr_sectors;
--			++rq->sector;
--			--this_transfer;
--			--sectors_to_transfer;
-+		if (cd->disk->policy) {
-+			cdrom_end_request(drive, 0);
-+			return ide_stopped;
- 		}
--
-+	} else {
- 		/*
--		 * current buffer complete, move on
-+		 * We may be retrying this request after an error.  Fix up any
-+		 * weirdness which might be present in the request packet.
- 		 */
--		if (rq->current_nr_sectors == 0 && rq->nr_sectors)
--			cdrom_end_request(drive, 1);
--	}
--
--	/* re-arm handler */
--	ide_set_handler(drive, &cdrom_write_intr, ATAPI_WAIT_PC, NULL);
--	return ide_started;
--}
--
--static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive)
--{
--	struct request *rq = HWGROUP(drive)->rq;
-+		restore_request(rq);
+ 		drv = *(ide_driver_t **)rq->rq_disk->private_data;;
+-		drv->end_request(drive, 1, rq->hard_nr_sectors);
++		drv->end_request(drive, 1, rq->nr_sectors);
+ 	} else
+-		ide_end_request(drive, 1, rq->hard_nr_sectors);
++		ide_end_request(drive, 1, rq->nr_sectors);
+ }
  
--#if 0	/* the immediate bit */
--	rq->cmd[1] = 1 << 3;
--#endif
--	rq->timeout = ATAPI_WAIT_PC;
--
--	return cdrom_transfer_packet_command(drive, rq, cdrom_write_intr);
--}
--
--static ide_startstop_t cdrom_start_write(ide_drive_t *drive, struct request *rq)
--{
--	struct cdrom_info *info = drive->driver_data;
--	struct gendisk *g = info->disk;
--	unsigned short sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS;
-+		/* Satisfy whatever we can of this request from our cache. */
-+		if (cdrom_read_from_buffer(drive))
-+			return ide_stopped;
-+	}
+ /*
+  * Handler for command with PIO data-in phase (Read/Read Multiple).
+  */
+-ide_startstop_t task_in_intr (ide_drive_t *drive)
++static ide_startstop_t task_in_intr(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	u8 stat = hwif->INB(IDE_STATUS_REG);
++	u8 stat = ide_read_status(drive);
  
- 	/*
--	 * writes *must* be hardware frame aligned
-+	 * use DMA, if possible / writes *must* be hardware frame aligned
- 	 */
- 	if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
- 	    (rq->sector & (sectors_per_frame - 1))) {
--		cdrom_end_request(drive, 0);
--		return ide_stopped;
--	}
--
--	/*
--	 * disk has become write protected
--	 */
--	if (g->policy) {
--		cdrom_end_request(drive, 0);
--		return ide_stopped;
--	}
--
--	info->nsectors_buffered = 0;
-+		if (write) {
-+			cdrom_end_request(drive, 0);
-+			return ide_stopped;
-+		}
-+		cd->dma = 0;
-+	} else
-+		cd->dma = drive->using_dma;
+ 	/* new way for dealing with premature shared PCI interrupts */
+-	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
++	if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
+ 		if (stat & (ERR_STAT | DRQ_STAT))
+ 			return task_error(drive, rq, __FUNCTION__, stat);
+ 		/* No data yet, so wait for another IRQ. */
+@@ -402,7 +445,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
+ 	/* If it was the last datablock check status and finish transfer. */
+ 	if (!hwif->nleft) {
+ 		stat = wait_drive_not_busy(drive);
+-		if (!OK_STAT(stat, 0, BAD_R_STAT))
++		if (!OK_STAT(stat, 0, BAD_STAT))
+ 			return task_error(drive, rq, __FUNCTION__, stat);
+ 		task_end_request(drive, rq, stat);
+ 		return ide_stopped;
+@@ -413,7 +456,6 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
  
--	/* use dma, if possible. we don't need to check more, since we
--	 * know that the transfer is always (at least!) frame aligned */
--	info->dma = drive->using_dma ? 1 : 0;
-+	/* Clear the local sector buffer. */
-+	cd->nsectors_buffered = 0;
+ 	return ide_started;
+ }
+-EXPORT_SYMBOL(task_in_intr);
  
--	info->devinfo.media_written = 1;
-+	if (write)
-+		cd->devinfo.media_written = 1;
+ /*
+  * Handler for command with PIO data-out phase (Write/Write Multiple).
+@@ -422,7 +464,7 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
+ 	struct request *rq = HWGROUP(drive)->rq;
+-	u8 stat = hwif->INB(IDE_STATUS_REG);
++	u8 stat = ide_read_status(drive);
  
--	/* Start sending the write request to the drive. */
--	return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont);
-+	/* Start sending the read/write request to the drive. */
-+	return cdrom_start_packet_command(drive, 32768, cdrom_start_rw_cont);
+ 	if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat))
+ 		return task_error(drive, rq, __FUNCTION__, stat);
+@@ -443,11 +485,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
+ 	return ide_started;
  }
  
- static ide_startstop_t cdrom_do_newpc_cont(ide_drive_t *drive)
-@@ -1958,7 +1284,10 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
+-ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
++static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
  {
- 	struct cdrom_info *info = drive->driver_data;
- 
--	rq->cmd_flags |= REQ_QUIET;
-+	if (blk_pc_request(rq))
-+		rq->cmd_flags |= REQ_QUIET;
-+	else
-+		rq->cmd_flags &= ~REQ_FAILED;
+ 	ide_startstop_t startstop;
  
- 	info->dma = 0;
+-	if (ide_wait_stat(&startstop, drive, DATA_READY,
++	if (ide_wait_stat(&startstop, drive, DRQ_STAT,
+ 			  drive->bad_wstat, WAIT_DRQ)) {
+ 		printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
+ 				drive->name,
+@@ -464,9 +506,8 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
  
-@@ -1995,7 +1324,7 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
- 	struct cdrom_info *info = drive->driver_data;
+ 	return ide_started;
+ }
+-EXPORT_SYMBOL(pre_task_out_intr);
  
- 	if (blk_fs_request(rq)) {
--		if (CDROM_CONFIG_FLAGS(drive)->seeking) {
-+		if (info->cd_flags & IDE_CD_FLAG_SEEKING) {
- 			unsigned long elapsed = jiffies - info->start_seek;
- 			int stat = HWIF(drive)->INB(IDE_STATUS_REG);
+-static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
++int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
+ {
+ 	struct request rq;
  
-@@ -2006,22 +1335,16 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
- 				}
- 				printk (KERN_ERR "%s: DSC timeout\n", drive->name);
- 			}
--			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
-+			info->cd_flags &= ~IDE_CD_FLAG_SEEKING;
- 		}
- 		if ((rq_data_dir(rq) == READ) && IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
- 			action = cdrom_start_seek(drive, block);
--		} else {
--			if (rq_data_dir(rq) == READ)
--				action = cdrom_start_read(drive, block);
--			else
--				action = cdrom_start_write(drive, rq);
+@@ -481,36 +522,27 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
+ 	 * if we would find a solution to transfer any size.
+ 	 * To support special commands like READ LONG.
+ 	 */
+-	if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
+-		if (data_size == 0)
+-			rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
+-		else
+-			rq.nr_sectors = data_size / SECTOR_SIZE;
+-
+-		if (!rq.nr_sectors) {
+-			printk(KERN_ERR "%s: in/out command without data\n",
+-					drive->name);
+-			return -EFAULT;
 -		}
-+		} else
-+			action = cdrom_start_rw(drive, rq);
- 		info->last_block = block;
- 		return action;
--	} else if (rq->cmd_type == REQ_TYPE_SENSE ||
-+	} else if (blk_sense_request(rq) || blk_pc_request(rq) ||
- 		   rq->cmd_type == REQ_TYPE_ATA_PC) {
--		return cdrom_do_packet_command(drive);
--	} else if (blk_pc_request(rq)) {
- 		return cdrom_do_block_pc(drive, rq);
- 	} else if (blk_special_request(rq)) {
- 		/*
-@@ -2048,141 +1371,33 @@ ide_do_rw_cdrom (ide_drive_t *drive, struct request *rq, sector_t block)
-  * can also be NULL, in which case no sense information is returned.
-  */
++	rq.hard_nr_sectors = rq.nr_sectors = nsect;
++	rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
  
--#if ! STANDARD_ATAPI
--static inline
--int bin2bcd (int x)
--{
--	return (x%10) | ((x/10) << 4);
--}
--
--
--static inline
--int bcd2bin (int x)
--{
--	return (x >> 4) * 10 + (x & 0x0f);
--}
--
- static
- void msf_from_bcd (struct atapi_msf *msf)
- {
--	msf->minute = bcd2bin (msf->minute);
--	msf->second = bcd2bin (msf->second);
--	msf->frame  = bcd2bin (msf->frame);
--}
--
--#endif /* not STANDARD_ATAPI */
--
--
--static inline
--void lba_to_msf (int lba, byte *m, byte *s, byte *f)
--{
--	lba += CD_MSF_OFFSET;
--	lba &= 0xffffff;  /* negative lbas use only 24 bits */
--	*m = lba / (CD_SECS * CD_FRAMES);
--	lba %= (CD_SECS * CD_FRAMES);
--	*s = lba / CD_FRAMES;
--	*f = lba % CD_FRAMES;
--}
--
--
--static inline
--int msf_to_lba (byte m, byte s, byte f)
--{
--	return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
-+	msf->minute = BCD2BIN(msf->minute);
-+	msf->second = BCD2BIN(msf->second);
-+	msf->frame  = BCD2BIN(msf->frame);
+-		rq.hard_nr_sectors = rq.nr_sectors;
+-		rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
++	if (task->tf_flags & IDE_TFLAG_WRITE)
++		rq.cmd_flags |= REQ_RW;
+ 
+-		if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
+-			rq.cmd_flags |= REQ_RW;
+-	}
++	rq.special = task;
++	task->rq = &rq;
+ 
+-	rq.special = args;
+-	args->rq = &rq;
+ 	return ide_do_drive_cmd(drive, &rq, ide_wait);
  }
  
--static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
-+int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
+-int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
++EXPORT_SYMBOL(ide_raw_taskfile);
++
++int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
  {
- 	struct request req;
- 	struct cdrom_info *info = drive->driver_data;
- 	struct cdrom_device_info *cdi = &info->devinfo;
- 
--	cdrom_prepare_request(drive, &req);
-+	ide_cd_init_rq(drive, &req);
+-	return ide_diag_taskfile(drive, args, 0, buf);
+-}
++	task->data_phase = TASKFILE_NO_DATA;
  
- 	req.sense = sense;
- 	req.cmd[0] = GPCMD_TEST_UNIT_READY;
- 	req.cmd_flags |= REQ_QUIET;
+-EXPORT_SYMBOL(ide_raw_taskfile);
++	return ide_raw_taskfile(drive, task, NULL, 0);
++}
++EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
  
--#if ! STANDARD_ATAPI
--        /* the Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to 
--           switch CDs instead of supporting the LOAD_UNLOAD opcode   */
--
-+	/*
-+	 * Sanyo 3 CD changer uses byte 7 of TEST_UNIT_READY to
-+	 * switch CDs instead of supporting the LOAD_UNLOAD opcode.
-+	 */
- 	req.cmd[7] = cdi->sanyo_slot % 3;
--#endif /* not STANDARD_ATAPI */
--
--	return cdrom_queue_packet_command(drive, &req);
--}
+ #ifdef CONFIG_IDE_TASK_IOCTL
+ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+@@ -519,13 +551,12 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ 	ide_task_t		args;
+ 	u8 *outbuf		= NULL;
+ 	u8 *inbuf		= NULL;
+-	task_ioreg_t *argsptr	= args.tfRegister;
+-	task_ioreg_t *hobsptr	= args.hobRegister;
++	u8 *data_buf		= NULL;
+ 	int err			= 0;
+ 	int tasksize		= sizeof(struct ide_task_request_s);
+ 	unsigned int taskin	= 0;
+ 	unsigned int taskout	= 0;
+-	u8 io_32bit		= drive->io_32bit;
++	u16 nsect		= 0;
+ 	char __user *buf = (char __user *)arg;
  
--
--/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
--static int
--cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
--{
--	struct request_sense my_sense;
--	struct request req;
--	int stat;
--
--	if (sense == NULL)
--		sense = &my_sense;
--
--	/* If the drive cannot lock the door, just pretend. */
--	if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
--		stat = 0;
--	} else {
--		cdrom_prepare_request(drive, &req);
--		req.sense = sense;
--		req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
--		req.cmd[4] = lockflag ? 1 : 0;
--		stat = cdrom_queue_packet_command(drive, &req);
--	}
--
--	/* If we got an illegal field error, the drive
--	   probably cannot lock the door. */
--	if (stat != 0 &&
--	    sense->sense_key == ILLEGAL_REQUEST &&
--	    (sense->asc == 0x24 || sense->asc == 0x20)) {
--		printk (KERN_ERR "%s: door locking not supported\n",
--			drive->name);
--		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
--		stat = 0;
--	}
--	
--	/* no medium, that's alright. */
--	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
--		stat = 0;
--
--	if (stat == 0)
--		CDROM_STATE_FLAGS(drive)->door_locked = lockflag;
--
--	return stat;
--}
--
--
--/* Eject the disk if EJECTFLAG is 0.
--   If EJECTFLAG is 1, try to reload the disk. */
--static int cdrom_eject(ide_drive_t *drive, int ejectflag,
--		       struct request_sense *sense)
--{
--	struct request req;
--	char loej = 0x02;
--
--	if (CDROM_CONFIG_FLAGS(drive)->no_eject && !ejectflag)
--		return -EDRIVE_CANT_DO_THIS;
--	
--	/* reload fails on some drives, if the tray is locked */
--	if (CDROM_STATE_FLAGS(drive)->door_locked && ejectflag)
--		return 0;
--
--	cdrom_prepare_request(drive, &req);
--
--	/* only tell drive to close tray if open, if it can do that */
--	if (ejectflag && !CDROM_CONFIG_FLAGS(drive)->close_tray)
--		loej = 0;
--
--	req.sense = sense;
--	req.cmd[0] = GPCMD_START_STOP_UNIT;
--	req.cmd[4] = loej | (ejectflag != 0);
--	return cdrom_queue_packet_command(drive, &req);
-+	return ide_cd_queue_pc(drive, &req);
- }
+ //	printk("IDE Taskfile ...\n");
+@@ -572,24 +603,52 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ 	}
  
- static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
-@@ -2197,7 +1412,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
- 	int stat;
- 	struct request req;
+ 	memset(&args, 0, sizeof(ide_task_t));
+-	memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
+-	memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
  
--	cdrom_prepare_request(drive, &req);
-+	ide_cd_init_rq(drive, &req);
+-	args.tf_in_flags  = req_task->in_flags;
+-	args.tf_out_flags = req_task->out_flags;
+-	args.data_phase   = req_task->data_phase;
+-	args.command_type = req_task->req_cmd;
++	memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
++	memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
++
++	args.data_phase = req_task->data_phase;
++
++	args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
++			IDE_TFLAG_IN_TF;
++	if (drive->addressing == 1)
++		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
++
++	if (req_task->out_flags.all) {
++		args.tf_flags |= IDE_TFLAG_FLAGGED;
++
++		if (req_task->out_flags.b.data)
++			args.tf_flags |= IDE_TFLAG_OUT_DATA;
++
++		if (req_task->out_flags.b.nsector_hob)
++			args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
++		if (req_task->out_flags.b.sector_hob)
++			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
++		if (req_task->out_flags.b.lcyl_hob)
++			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
++		if (req_task->out_flags.b.hcyl_hob)
++			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
++
++		if (req_task->out_flags.b.error_feature)
++			args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
++		if (req_task->out_flags.b.nsector)
++			args.tf_flags |= IDE_TFLAG_OUT_NSECT;
++		if (req_task->out_flags.b.sector)
++			args.tf_flags |= IDE_TFLAG_OUT_LBAL;
++		if (req_task->out_flags.b.lcyl)
++			args.tf_flags |= IDE_TFLAG_OUT_LBAM;
++		if (req_task->out_flags.b.hcyl)
++			args.tf_flags |= IDE_TFLAG_OUT_LBAH;
++	} else {
++		args.tf_flags |= IDE_TFLAG_OUT_TF;
++		if (args.tf_flags & IDE_TFLAG_LBA48)
++			args.tf_flags |= IDE_TFLAG_OUT_HOB;
++	}
++
++	if (req_task->in_flags.b.data)
++		args.tf_flags |= IDE_TFLAG_IN_DATA;
  
- 	req.sense = sense;
- 	req.cmd[0] = GPCMD_READ_CDVD_CAPACITY;
-@@ -2205,7 +1420,7 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity,
- 	req.data_len = sizeof(capbuf);
- 	req.cmd_flags |= REQ_QUIET;
+-	drive->io_32bit = 0;
+ 	switch(req_task->data_phase) {
+-		case TASKFILE_OUT_DMAQ:
+-		case TASKFILE_OUT_DMA:
+-			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
+-			break;
+-		case TASKFILE_IN_DMAQ:
+-		case TASKFILE_IN_DMA:
+-			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
+-			break;
+ 		case TASKFILE_MULTI_OUT:
+ 			if (!drive->mult_count) {
+ 				/* (hs): give up if multcount is not set */
+@@ -601,9 +660,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ 			}
+ 			/* fall through */
+ 		case TASKFILE_OUT:
+-			args.prehandler = &pre_task_out_intr;
+-			args.handler = &task_out_intr;
+-			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
++			/* fall through */
++		case TASKFILE_OUT_DMAQ:
++		case TASKFILE_OUT_DMA:
++			nsect = taskout / SECTOR_SIZE;
++			data_buf = outbuf;
+ 			break;
+ 		case TASKFILE_MULTI_IN:
+ 			if (!drive->mult_count) {
+@@ -616,22 +677,46 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ 			}
+ 			/* fall through */
+ 		case TASKFILE_IN:
+-			args.handler = &task_in_intr;
+-			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
++			/* fall through */
++		case TASKFILE_IN_DMAQ:
++		case TASKFILE_IN_DMA:
++			nsect = taskin / SECTOR_SIZE;
++			data_buf = inbuf;
+ 			break;
+ 		case TASKFILE_NO_DATA:
+-			args.handler = &task_no_data_intr;
+-			err = ide_diag_taskfile(drive, &args, 0, NULL);
+ 			break;
+ 		default:
+ 			err = -EFAULT;
+ 			goto abort;
+ 	}
  
--	stat = cdrom_queue_packet_command(drive, &req);
-+	stat = ide_cd_queue_pc(drive, &req);
- 	if (stat == 0) {
- 		*capacity = 1 + be32_to_cpu(capbuf.lba);
- 		*sectors_per_frame =
-@@ -2221,7 +1436,7 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
- {
- 	struct request req;
+-	memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
+-	memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
+-	req_task->in_flags  = args.tf_in_flags;
+-	req_task->out_flags = args.tf_out_flags;
++	if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
++		nsect = 0;
++	else if (!nsect) {
++		nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
++
++		if (!nsect) {
++			printk(KERN_ERR "%s: in/out command without data\n",
++					drive->name);
++			err = -EFAULT;
++			goto abort;
++		}
++	}
++
++	if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
++		args.tf_flags |= IDE_TFLAG_WRITE;
++
++	err = ide_raw_taskfile(drive, &args, data_buf, nsect);
++
++	memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
++	memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
++
++	if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
++	    req_task->in_flags.all == 0) {
++		req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
++		if (drive->addressing == 1)
++			req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
++	}
  
--	cdrom_prepare_request(drive, &req);
-+	ide_cd_init_rq(drive, &req);
+ 	if (copy_to_user(buf, req_task, tasksize)) {
+ 		err = -EFAULT;
+@@ -658,40 +743,25 @@ abort:
  
- 	req.sense = sense;
- 	req.data =  buf;
-@@ -2236,12 +1451,11 @@ static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
- 	if (msf_flag)
- 		req.cmd[1] = 2;
+ //	printk("IDE Taskfile ioctl ended. rc = %i\n", err);
  
--	return cdrom_queue_packet_command(drive, &req);
-+	return ide_cd_queue_pc(drive, &req);
+-	drive->io_32bit = io_32bit;
+-
+ 	return err;
  }
+ #endif
  
+-int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
+-{
+-	struct request rq;
+-	u8 buffer[4];
 -
- /* Try to read the entire TOC for the disk into our internal buffer. */
--static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
-+int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense)
+-	if (!buf)
+-		buf = buffer;
+-	memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
+-	ide_init_drive_cmd(&rq);
+-	rq.buffer = buf;
+-	*buf++ = cmd;
+-	*buf++ = nsect;
+-	*buf++ = feature;
+-	*buf++ = sectors;
+-	return ide_do_drive_cmd(drive, &rq, ide_wait);
+-}
+-
+ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
  {
- 	int stat, ntracks, i;
- 	struct cdrom_info *info = drive->driver_data;
-@@ -2268,7 +1482,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
- 	   If it is, just return. */
- 	(void) cdrom_check_status(drive, sense);
- 
--	if (CDROM_STATE_FLAGS(drive)->toc_valid)
-+	if (info->cd_flags & IDE_CD_FLAG_TOC_VALID)
- 		return 0;
- 
- 	/* Try to get the total cdrom capacity and sector size. */
-@@ -2290,12 +1504,10 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
- 	if (stat)
- 		return stat;
- 
--#if ! STANDARD_ATAPI
--	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
--		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
--		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
-+	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
-+		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
-+		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
- 	}
--#endif  /* not STANDARD_ATAPI */
+-	int err = 0;
+-	u8 args[4], *argbuf = args;
+-	u8 xfer_rate = 0;
+-	int argsize = 4;
++	u8 *buf = NULL;
++	int bufsize = 0, err = 0;
++	u8 args[4], xfer_rate = 0;
+ 	ide_task_t tfargs;
++	struct ide_taskfile *tf = &tfargs.tf;
++	struct hd_driveid *id = drive->id;
  
- 	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
- 	if (ntracks <= 0)
-@@ -2327,16 +1539,13 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
- 					   (ntracks + 1) *
- 					   sizeof(struct atapi_toc_entry),
- 					   sense);
--		if (stat) {
-+		if (stat)
- 			return stat;
--		}
--#if ! STANDARD_ATAPI
--		if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
--			toc->hdr.first_track = bin2bcd(CDROM_LEADOUT);
--			toc->hdr.last_track = bin2bcd(CDROM_LEADOUT);
--		} else
--#endif  /* not STANDARD_ATAPI */
--		{
+ 	if (NULL == (void *) arg) {
+ 		struct request rq;
 +
-+		if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
-+			toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT);
-+			toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT);
-+		} else {
- 			toc->hdr.first_track = CDROM_LEADOUT;
- 			toc->hdr.last_track = CDROM_LEADOUT;
- 		}
-@@ -2347,21 +1556,17 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 		ide_init_drive_cmd(&rq);
++		rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
++
+ 		return ide_do_drive_cmd(drive, &rq, ide_wait);
+ 	}
  
- 	toc->hdr.toc_length = ntohs (toc->hdr.toc_length);
+@@ -699,27 +769,46 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ 		return -EFAULT;
  
--#if ! STANDARD_ATAPI
--	if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd) {
--		toc->hdr.first_track = bcd2bin(toc->hdr.first_track);
--		toc->hdr.last_track  = bcd2bin(toc->hdr.last_track);
-+	if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD) {
-+		toc->hdr.first_track = BCD2BIN(toc->hdr.first_track);
-+		toc->hdr.last_track  = BCD2BIN(toc->hdr.last_track);
- 	}
--#endif  /* not STANDARD_ATAPI */
+ 	memset(&tfargs, 0, sizeof(ide_task_t));
+-	tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
+-	tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
+-	tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
+-	tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
+-	tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
+-	tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
+-	tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
++	tf->feature = args[2];
++	if (args[0] == WIN_SMART) {
++		tf->nsect = args[3];
++		tf->lbal  = args[1];
++		tf->lbam  = 0x4f;
++		tf->lbah  = 0xc2;
++		tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
++	} else {
++		tf->nsect = args[1];
++		tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
++				  IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
++	}
++	tf->command = args[0];
++	tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
  
--	for (i=0; i<=ntracks; i++) {
--#if ! STANDARD_ATAPI
--		if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
--			if (CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd)
--				toc->ent[i].track = bcd2bin(toc->ent[i].track);
-+	for (i = 0; i <= ntracks; i++) {
-+		if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
-+			if (info->cd_flags & IDE_CD_FLAG_TOCTRACKS_AS_BCD)
-+				toc->ent[i].track = BCD2BIN(toc->ent[i].track);
- 			msf_from_bcd(&toc->ent[i].addr.msf);
- 		}
--#endif  /* not STANDARD_ATAPI */
- 		toc->ent[i].addr.lba = msf_to_lba (toc->ent[i].addr.msf.minute,
- 						   toc->ent[i].addr.msf.second,
- 						   toc->ent[i].addr.msf.frame);
-@@ -2381,8 +1586,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
- 		toc->last_session_lba = msf_to_lba(0, 2, 0); /* 0m 2s 0f */
+ 	if (args[3]) {
+-		argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
+-		argbuf = kzalloc(argsize, GFP_KERNEL);
+-		if (argbuf == NULL)
++		tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
++		bufsize = SECTOR_WORDS * 4 * args[3];
++		buf = kzalloc(bufsize, GFP_KERNEL);
++		if (buf == NULL)
+ 			return -ENOMEM;
  	}
- 
--#if ! STANDARD_ATAPI
--	if (CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd) {
-+	if (info->cd_flags & IDE_CD_FLAG_TOCADDR_AS_BCD) {
- 		/* Re-read multisession information using MSF format */
- 		stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
- 					   sizeof(ms_tmp), sense);
-@@ -2394,7 +1598,6 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
- 					  	   ms_tmp.ent.addr.msf.second,
- 						   ms_tmp.ent.addr.msf.frame);
+-	if (set_transfer(drive, &tfargs)) {
++
++	if (tf->command == WIN_SETFEATURES &&
++	    tf->feature == SETFEATURES_XFER &&
++	    tf->nsect >= XFER_SW_DMA_0 &&
++	    (id->dma_ultra || id->dma_mword || id->dma_1word)) {
+ 		xfer_rate = args[1];
+-		if (ide_ata66_check(drive, &tfargs))
++		if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
++			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
++					    "be set\n", drive->name);
+ 			goto abort;
++		}
  	}
--#endif  /* not STANDARD_ATAPI */
  
- 	toc->xa_flag = (ms_tmp.hdr.first_track != ms_tmp.hdr.last_track);
+-	err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
++	err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
++
++	args[0] = tf->status;
++	args[1] = tf->error;
++	args[2] = tf->nsect;
  
-@@ -2407,278 +1610,22 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
+ 	if (!err && xfer_rate) {
+ 		/* active-retuning-calls future */
+@@ -727,142 +816,38 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ 		ide_driveid_update(drive);
  	}
- 
- 	/* Remember that we've read this stuff. */
--	CDROM_STATE_FLAGS(drive)->toc_valid = 1;
-+	info->cd_flags |= IDE_CD_FLAG_TOC_VALID;
- 
- 	return 0;
+ abort:
+-	if (copy_to_user((void __user *)arg, argbuf, argsize))
++	if (copy_to_user((void __user *)arg, &args, 4))
+ 		err = -EFAULT;
+-	if (argsize > 4)
+-		kfree(argbuf);
++	if (buf) {
++		if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
++			err = -EFAULT;
++		kfree(buf);
++	}
+ 	return err;
  }
  
--
--static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
--				 int buflen, struct request_sense *sense)
--{
--	struct request req;
--
--	cdrom_prepare_request(drive, &req);
--
--	req.sense = sense;
--	req.data = buf;
--	req.data_len = buflen;
--	req.cmd[0] = GPCMD_READ_SUBCHANNEL;
--	req.cmd[1] = 2;     /* MSF addressing */
--	req.cmd[2] = 0x40;  /* request subQ data */
--	req.cmd[3] = format;
--	req.cmd[7] = (buflen >> 8);
--	req.cmd[8] = (buflen & 0xff);
--	return cdrom_queue_packet_command(drive, &req);
--}
--
--/* ATAPI cdrom drives are free to select the speed you request or any slower
--   rate :-( Requesting too fast a speed will _not_ produce an error. */
--static int cdrom_select_speed(ide_drive_t *drive, int speed,
--			      struct request_sense *sense)
--{
--	struct request req;
--	cdrom_prepare_request(drive, &req);
--
--	req.sense = sense;
--	if (speed == 0)
--		speed = 0xffff; /* set to max */
--	else
--		speed *= 177;   /* Nx to kbytes/s */
--
--	req.cmd[0] = GPCMD_SET_SPEED;
--	/* Read Drive speed in kbytes/second MSB */
--	req.cmd[2] = (speed >> 8) & 0xff;	
--	/* Read Drive speed in kbytes/second LSB */
--	req.cmd[3] = speed & 0xff;
--	if (CDROM_CONFIG_FLAGS(drive)->cd_r ||
--	    CDROM_CONFIG_FLAGS(drive)->cd_rw ||
--	    CDROM_CONFIG_FLAGS(drive)->dvd_r) {
--		/* Write Drive speed in kbytes/second MSB */
--		req.cmd[4] = (speed >> 8) & 0xff;
--		/* Write Drive speed in kbytes/second LSB */
--		req.cmd[5] = speed & 0xff;
--       }
--
--	return cdrom_queue_packet_command(drive, &req);
--}
--
--static int cdrom_play_audio(ide_drive_t *drive, int lba_start, int lba_end)
--{
--	struct request_sense sense;
--	struct request req;
--
--	cdrom_prepare_request(drive, &req);
--
--	req.sense = &sense;
--	req.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
--	lba_to_msf(lba_start, &req.cmd[3], &req.cmd[4], &req.cmd[5]);
--	lba_to_msf(lba_end-1, &req.cmd[6], &req.cmd[7], &req.cmd[8]);
--
--	return cdrom_queue_packet_command(drive, &req);
--}
--
--static int cdrom_get_toc_entry(ide_drive_t *drive, int track,
--				struct atapi_toc_entry **ent)
--{
--	struct cdrom_info *info = drive->driver_data;
--	struct atapi_toc *toc = info->toc;
--	int ntracks;
--
--	/*
--	 * don't serve cached data, if the toc isn't valid
--	 */
--	if (!CDROM_STATE_FLAGS(drive)->toc_valid)
--		return -EINVAL;
--
--	/* Check validity of requested track number. */
--	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
--	if (toc->hdr.first_track == CDROM_LEADOUT) ntracks = 0;
--	if (track == CDROM_LEADOUT)
--		*ent = &toc->ent[ntracks];
--	else if (track < toc->hdr.first_track ||
--		 track > toc->hdr.last_track)
--		return -EINVAL;
--	else
--		*ent = &toc->ent[track - toc->hdr.first_track];
--
--	return 0;
--}
--
--/* the generic packet interface to cdrom.c */
--static int ide_cdrom_packet(struct cdrom_device_info *cdi,
--			    struct packet_command *cgc)
--{
--	struct request req;
--	ide_drive_t *drive = cdi->handle;
--
--	if (cgc->timeout <= 0)
--		cgc->timeout = ATAPI_WAIT_PC;
--
--	/* here we queue the commands from the uniform CD-ROM
--	   layer. the packet must be complete, as we do not
--	   touch it at all. */
--	cdrom_prepare_request(drive, &req);
--	memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
--	if (cgc->sense)
--		memset(cgc->sense, 0, sizeof(struct request_sense));
--	req.data = cgc->buffer;
--	req.data_len = cgc->buflen;
--	req.timeout = cgc->timeout;
--
--	if (cgc->quiet)
--		req.cmd_flags |= REQ_QUIET;
--
--	req.sense = cgc->sense;
--	cgc->stat = cdrom_queue_packet_command(drive, &req);
--	if (!cgc->stat)
--		cgc->buflen -= req.data_len;
--	return cgc->stat;
--}
--
--static
--int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
--			   unsigned int cmd, void *arg)
--			   
--{
--	ide_drive_t *drive = cdi->handle;
--	struct cdrom_info *info = drive->driver_data;
--	int stat;
--
--	switch (cmd) {
--	/*
--	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
--	 * atapi doesn't support it
--	 */
--	case CDROMPLAYTRKIND: {
--		unsigned long lba_start, lba_end;
--		struct cdrom_ti *ti = arg;
--		struct atapi_toc_entry *first_toc, *last_toc;
--
--		stat = cdrom_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
--		if (stat)
--			return stat;
--
--		stat = cdrom_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
--		if (stat)
--			return stat;
--
--		if (ti->cdti_trk1 != CDROM_LEADOUT)
--			++last_toc;
--		lba_start = first_toc->addr.lba;
--		lba_end   = last_toc->addr.lba;
--
--		if (lba_end <= lba_start)
--			return -EINVAL;
--
--		return cdrom_play_audio(drive, lba_start, lba_end);
--	}
--
--	case CDROMREADTOCHDR: {
--		struct cdrom_tochdr *tochdr = arg;
--		struct atapi_toc *toc;
--
--		/* Make sure our saved TOC is valid. */
--		stat = cdrom_read_toc(drive, NULL);
--		if (stat)
--			return stat;
--
--		toc = info->toc;
--		tochdr->cdth_trk0 = toc->hdr.first_track;
--		tochdr->cdth_trk1 = toc->hdr.last_track;
--
--		return 0;
--	}
--
--	case CDROMREADTOCENTRY: {
--		struct cdrom_tocentry *tocentry = arg;
--		struct atapi_toc_entry *toce;
--
--		stat = cdrom_get_toc_entry(drive, tocentry->cdte_track, &toce);
--		if (stat)
--			return stat;
--
--		tocentry->cdte_ctrl = toce->control;
--		tocentry->cdte_adr  = toce->adr;
--		if (tocentry->cdte_format == CDROM_MSF) {
--			lba_to_msf (toce->addr.lba,
--				   &tocentry->cdte_addr.msf.minute,
--				   &tocentry->cdte_addr.msf.second,
--				   &tocentry->cdte_addr.msf.frame);
--		} else
--			tocentry->cdte_addr.lba = toce->addr.lba;
--
--		return 0;
--	}
--
--	default:
--		return -EINVAL;
--	}
--}
--
--static
--int ide_cdrom_reset (struct cdrom_device_info *cdi)
--{
--	ide_drive_t *drive = cdi->handle;
--	struct request_sense sense;
--	struct request req;
--	int ret;
--
--	cdrom_prepare_request(drive, &req);
--	req.cmd_type = REQ_TYPE_SPECIAL;
--	req.cmd_flags = REQ_QUIET;
--	ret = ide_do_drive_cmd(drive, &req, ide_wait);
--
--	/*
--	 * A reset will unlock the door. If it was previously locked,
--	 * lock it again.
--	 */
--	if (CDROM_STATE_FLAGS(drive)->door_locked)
--		(void) cdrom_lockdoor(drive, 1, &sense);
--
--	return ret;
--}
--
--
--static
--int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
+-static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
 -{
--	ide_drive_t *drive = cdi->handle;
--	struct request_sense sense;
--
--	if (position) {
--		int stat = cdrom_lockdoor(drive, 0, &sense);
--		if (stat)
--			return stat;
--	}
--
--	return cdrom_eject(drive, !position, &sense);
--}
+-	struct request rq;
 -
--static
--int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
--{
--	ide_drive_t *drive = cdi->handle;
--	return cdrom_lockdoor(drive, lock, NULL);
+-	ide_init_drive_cmd(&rq);
+-	rq.cmd_type = REQ_TYPE_ATA_TASK;
+-	rq.buffer = buf;
+-	return ide_do_drive_cmd(drive, &rq, ide_wait);
 -}
 -
--static
--int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
-+int ide_cdrom_get_capabilities(ide_drive_t *drive, u8 *buf)
+ int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
  {
- 	struct cdrom_info *info = drive->driver_data;
- 	struct cdrom_device_info *cdi = &info->devinfo;
- 	struct packet_command cgc;
--	int stat, attempts = 3, size = sizeof(*cap);
-+	int stat, attempts = 3, size = ATAPI_CAPABILITIES_PAGE_SIZE;
- 
--	/*
--	 * ACER50 (and others?) require the full spec length mode sense
--	 * page capabilities size, but older drives break.
--	 */
--	if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
--	    !strcmp(drive->id->model, "WPI CDS-32X")))
--		size -= sizeof(cap->pad);
-+	if ((info->cd_flags & IDE_CD_FLAG_FULL_CAPS_PAGE) == 0)
-+		size -= ATAPI_CAPABILITIES_PAGE_PAD_SIZE;
- 
--	init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
-+	init_cdrom_command(&cgc, buf, size, CGC_DATA_UNKNOWN);
- 	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
- 		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
- 		if (!stat)
-@@ -2687,177 +1634,33 @@ int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_pag
- 	return stat;
- }
+ 	void __user *p = (void __user *)arg;
+ 	int err = 0;
+-	u8 args[7], *argbuf = args;
+-	int argsize = 7;
++	u8 args[7];
++	ide_task_t task;
  
--static
--void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap)
--{
--	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
--	if (!drive->id->model[0] &&
--	    !strncmp(drive->id->fw_rev, "241N", 4)) {
--		CDROM_STATE_FLAGS(drive)->current_speed  =
--			(le16_to_cpu(cap->curspeed) + (176/2)) / 176;
--		CDROM_CONFIG_FLAGS(drive)->max_speed =
--			(le16_to_cpu(cap->maxspeed) + (176/2)) / 176;
--	} else {
--		CDROM_STATE_FLAGS(drive)->current_speed  =
--			(be16_to_cpu(cap->curspeed) + (176/2)) / 176;
--		CDROM_CONFIG_FLAGS(drive)->max_speed =
--			(be16_to_cpu(cap->maxspeed) + (176/2)) / 176;
--	}
--}
--
--static
--int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
--{
--	ide_drive_t *drive = cdi->handle;
--	struct request_sense sense;
--	struct atapi_capabilities_page cap;
--	int stat;
--
--	if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
--		return stat;
--
--	if (!ide_cdrom_get_capabilities(drive, &cap)) {
--		ide_cdrom_update_speed(drive, &cap);
--		cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
--	}
--        return 0;
+ 	if (copy_from_user(args, p, 7))
+ 		return -EFAULT;
+-	err = ide_wait_cmd_task(drive, argbuf);
+-	if (copy_to_user(p, argbuf, argsize))
+-		err = -EFAULT;
+-	return err;
 -}
--
+ 
 -/*
-- * add logic to try GET_EVENT command first to check for media and tray
-- * status. this should be supported by newer cd-r/w and all DVD etc
-- * drives
+- * NOTICE: This is additions from IBM to provide a discrete interface,
+- * for selective taskregister access operations.  Nice JOB Klaus!!!
+- * Glad to be able to work and co-develop this with you and IBM.
 - */
--static
--int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
+-ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
 -{
--	ide_drive_t *drive = cdi->handle;
--	struct media_event_desc med;
--	struct request_sense sense;
--	int stat;
--
--	if (slot_nr != CDSL_CURRENT)
--		return -EINVAL;
--
--	stat = cdrom_check_status(drive, &sense);
--	if (!stat || sense.sense_key == UNIT_ATTENTION)
--		return CDS_DISC_OK;
--
--	if (!cdrom_get_media_event(cdi, &med)) {
--		if (med.media_present)
--			return CDS_DISC_OK;
--		else if (med.door_open)
--			return CDS_TRAY_OPEN;
--		else
--			return CDS_NO_DISC;
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	task_struct_t *taskfile	= (task_struct_t *) task->tfRegister;
+-	hob_struct_t *hobfile	= (hob_struct_t *) task->hobRegister;
++	memset(&task, 0, sizeof(task));
++	memcpy(&task.tf_array[7], &args[1], 6);
++	task.tf.command = args[0];
++	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
+ 
+-	if (task->data_phase == TASKFILE_MULTI_IN ||
+-	    task->data_phase == TASKFILE_MULTI_OUT) {
+-		if (!drive->mult_count) {
+-			printk(KERN_ERR "%s: multimode not set!\n", drive->name);
+-			return ide_stopped;
+-		}
 -	}
 -
--	if (sense.sense_key == NOT_READY && sense.asc == 0x04 && sense.ascq == 0x04)
--		return CDS_DISC_OK;
--
 -	/*
--	 * If not using Mt Fuji extended media tray reports,
--	 * just return TRAY_OPEN since ATAPI doesn't provide
--	 * any other way to detect this...
+-	 * (ks) Check taskfile in flags.
+-	 * If set, then execute as it is defined.
+-	 * If not set, then define default settings.
+-	 * The default values are:
+-	 *	read all taskfile registers (except data)
+-	 *	read the hob registers (sector, nsector, lcyl, hcyl)
 -	 */
--	if (sense.sense_key == NOT_READY) {
--		if (sense.asc == 0x3a && sense.ascq == 1)
--			return CDS_NO_DISC;
--		else
--			return CDS_TRAY_OPEN;
--	}
--	return CDS_DRIVE_NOT_READY;
--}
--
--static
--int ide_cdrom_get_last_session (struct cdrom_device_info *cdi,
--				struct cdrom_multisession *ms_info)
--{
--	struct atapi_toc *toc;
--	ide_drive_t *drive = cdi->handle;
--	struct cdrom_info *info = drive->driver_data;
--	struct request_sense sense;
--	int ret;
--
--	if (!CDROM_STATE_FLAGS(drive)->toc_valid || info->toc == NULL)
--		if ((ret = cdrom_read_toc(drive, &sense)))
--			return ret;
+-	if (task->tf_in_flags.all == 0) {
+-		task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
+-		if (drive->addressing == 1)
+-			task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS  << 8);
+-        }
 -
--	toc = info->toc;
--	ms_info->addr.lba = toc->last_session_lba;
--	ms_info->xa_flag = toc->xa_flag;
+-	/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
+-	if (IDE_CONTROL_REG)
+-		/* clear nIEN */
+-		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+-	SELECT_MASK(drive, 0);
 -
--	return 0;
--}
+-	if (task->tf_out_flags.b.data) {
+-		u16 data =  taskfile->data + (hobfile->data << 8);
+-		hwif->OUTW(data, IDE_DATA_REG);
+-	}
 -
--static
--int ide_cdrom_get_mcn (struct cdrom_device_info *cdi,
--		       struct cdrom_mcn *mcn_info)
-+void ide_cdrom_update_speed(ide_drive_t *drive, u8 *buf)
- {
--	int stat;
--	char mcnbuf[24];
--	ide_drive_t *drive = cdi->handle;
+-	/* (ks) send hob registers first */
+-	if (task->tf_out_flags.b.nsector_hob)
+-		hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
+-	if (task->tf_out_flags.b.sector_hob)
+-		hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
+-	if (task->tf_out_flags.b.lcyl_hob)
+-		hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
+-	if (task->tf_out_flags.b.hcyl_hob)
+-		hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
 -
--/* get MCN */
--	if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
--		return stat;
+-	/* (ks) Send now the standard registers */
+-	if (task->tf_out_flags.b.error_feature)
+-		hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
+-	/* refers to number of sectors to transfer */
+-	if (task->tf_out_flags.b.nsector)
+-		hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
+-	/* refers to sector offset or start sector */
+-	if (task->tf_out_flags.b.sector)
+-		hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
+-	if (task->tf_out_flags.b.lcyl)
+-		hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
+-	if (task->tf_out_flags.b.hcyl)
+-		hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
 -
--	memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
--		sizeof (mcn_info->medium_catalog_number)-1);
--	mcn_info->medium_catalog_number[sizeof (mcn_info->medium_catalog_number)-1]
--		= '\0';
+-        /*
+-	 * (ks) In the flagged taskfile approch, we will use all specified
+-	 * registers and the register value will not be changed, except the
+-	 * select bit (master/slave) in the drive_head register. We must make
+-	 * sure that the desired drive is selected.
+-	 */
+-	hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
+-	switch(task->data_phase) {
 -
--	return 0;
--}
+-   	        case TASKFILE_OUT_DMAQ:
+-		case TASKFILE_OUT_DMA:
+-		case TASKFILE_IN_DMAQ:
+-		case TASKFILE_IN_DMA:
+-			if (!drive->using_dma)
+-				break;
 -
-+	struct cdrom_info *cd = drive->driver_data;
-+	u16 curspeed, maxspeed;
+-			if (!hwif->dma_setup(drive)) {
+-				hwif->dma_exec_cmd(drive, taskfile->command);
+-				hwif->dma_start(drive);
+-				return ide_started;
+-			}
+-			break;
++	err = ide_no_data_taskfile(drive, &task);
  
-+	curspeed = *(u16 *)&buf[8 + 14];
-+	maxspeed = *(u16 *)&buf[8 +  8];
+-	        default:
+- 			if (task->handler == NULL)
+-				return ide_stopped;
++	args[0] = task.tf.command;
++	memcpy(&args[1], &task.tf_array[7], 6);
  
--/****************************************************************************
-- * Other driver requests (open, close, check media change).
-- */
--
--static
--int ide_cdrom_check_media_change_real (struct cdrom_device_info *cdi,
--				       int slot_nr)
--{
--	ide_drive_t *drive = cdi->handle;
--	int retval;
--	
--	if (slot_nr == CDSL_CURRENT) {
--		(void) cdrom_check_status(drive, NULL);
--		retval = CDROM_STATE_FLAGS(drive)->media_changed;
--		CDROM_STATE_FLAGS(drive)->media_changed = 0;
--		return retval;
-+	if (cd->cd_flags & IDE_CD_FLAG_LE_SPEED_FIELDS) {
-+		curspeed = le16_to_cpu(curspeed);
-+		maxspeed = le16_to_cpu(maxspeed);
- 	} else {
--		return -EINVAL;
-+		curspeed = be16_to_cpu(curspeed);
-+		maxspeed = be16_to_cpu(maxspeed);
- 	}
--}
--
--
--static
--int ide_cdrom_open_real (struct cdrom_device_info *cdi, int purpose)
--{
--	return 0;
--}
+-			/* Issue the command */
+-			if (task->prehandler) {
+-				hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
+-				ndelay(400);	/* FIXME */
+-				return task->prehandler(drive, task->rq);
+-			}
+-			ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
+-			return ide_started;
+-	}
++	if (copy_to_user(p, args, 7))
++		err = -EFAULT;
  
--/*
-- * Close down the device.  Invalidate all cached blocks.
-- */
--
--static
--void ide_cdrom_release_real (struct cdrom_device_info *cdi)
--{
--	ide_drive_t *drive = cdi->handle;
--
--	if (!cdi->use_count)
--		CDROM_STATE_FLAGS(drive)->toc_valid = 0;
-+	cd->current_speed = (curspeed + (176/2)) / 176;
-+	cd->max_speed = (maxspeed + (176/2)) / 176;
+-	return ide_stopped;
++	return err;
  }
+diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
+index daffbb9..3b12ffe 100644
+--- a/drivers/ide/ide-timing.h
++++ b/drivers/ide/ide-timing.h
+@@ -2,8 +2,6 @@
+ #define _IDE_TIMING_H
  
-+#define IDE_CD_CAPABILITIES \
-+	(CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | \
-+	 CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | \
-+	 CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R | \
-+	 CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_GENERIC_PACKET | \
-+	 CDC_MO_DRIVE | CDC_MRW | CDC_MRW_W | CDC_RAM)
+ /*
+- * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $
+- *
+  *  Copyright (c) 1999-2001 Vojtech Pavlik
+  */
  
--
--/****************************************************************************
-- * Device initialization.
-- */
- static struct cdrom_device_ops ide_cdrom_dops = {
- 	.open			= ide_cdrom_open_real,
- 	.release		= ide_cdrom_release_real,
-@@ -2870,14 +1673,7 @@ static struct cdrom_device_ops ide_cdrom_dops = {
- 	.get_mcn		= ide_cdrom_get_mcn,
- 	.reset			= ide_cdrom_reset,
- 	.audio_ioctl		= ide_cdrom_audio_ioctl,
--	.capability		= CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
--				CDC_SELECT_SPEED | CDC_SELECT_DISC |
--				CDC_MULTI_SESSION | CDC_MCN |
--				CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
--				CDC_DRIVE_STATUS | CDC_CD_R |
--				CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
--				CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
--				CDC_MRW_W | CDC_RAM,
-+	.capability		= IDE_CD_CAPABILITIES,
- 	.generic_packet		= ide_cdrom_packet,
- };
+@@ -201,7 +199,7 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
+ 	}
  
-@@ -2887,35 +1683,12 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
- 	struct cdrom_device_info *devinfo = &info->devinfo;
+ /*
+- * Lenghten active & recovery time so that cycle time is correct.
++ * Lengthen active & recovery time so that cycle time is correct.
+  */
  
- 	devinfo->ops = &ide_cdrom_dops;
--	devinfo->mask = 0;
--	devinfo->speed = CDROM_STATE_FLAGS(drive)->current_speed;
-+	devinfo->speed = info->current_speed;
- 	devinfo->capacity = nslots;
- 	devinfo->handle = drive;
- 	strcpy(devinfo->name, drive->name);
--	
--	/* set capability mask to match the probe. */
--	if (!CDROM_CONFIG_FLAGS(drive)->cd_r)
--		devinfo->mask |= CDC_CD_R;
--	if (!CDROM_CONFIG_FLAGS(drive)->cd_rw)
--		devinfo->mask |= CDC_CD_RW;
--	if (!CDROM_CONFIG_FLAGS(drive)->dvd)
--		devinfo->mask |= CDC_DVD;
--	if (!CDROM_CONFIG_FLAGS(drive)->dvd_r)
--		devinfo->mask |= CDC_DVD_R;
--	if (!CDROM_CONFIG_FLAGS(drive)->dvd_ram)
--		devinfo->mask |= CDC_DVD_RAM;
--	if (!CDROM_CONFIG_FLAGS(drive)->is_changer)
--		devinfo->mask |= CDC_SELECT_DISC;
--	if (!CDROM_CONFIG_FLAGS(drive)->audio_play)
--		devinfo->mask |= CDC_PLAY_AUDIO;
--	if (!CDROM_CONFIG_FLAGS(drive)->close_tray)
--		devinfo->mask |= CDC_CLOSE_TRAY;
--	if (!CDROM_CONFIG_FLAGS(drive)->mo_drive)
--		devinfo->mask |= CDC_MO_DRIVE;
--	if (!CDROM_CONFIG_FLAGS(drive)->ram)
--		devinfo->mask |= CDC_RAM;
--
--	if (CDROM_CONFIG_FLAGS(drive)->no_speed_select)
-+
-+	if (info->cd_flags & IDE_CD_FLAG_NO_SPEED_SELECT)
- 		devinfo->mask |= CDC_SELECT_SPEED;
+ 	if (t->act8b + t->rec8b < t->cyc8b) {
+diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
+index 54943da..ad0e995 100644
+--- a/drivers/ide/ide.c
++++ b/drivers/ide/ide.c
+@@ -1,7 +1,6 @@
+ /*
+- *  linux/drivers/ide/ide.c		Version 7.00beta2	Mar 05 2003
+- *
+- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
++ *  Copyright (C) 1994-1998	    Linus Torvalds & authors (see below)
++ *  Copyrifht (C) 2003-2005, 2007   Bartlomiej Zolnierkiewicz
+  */
  
- 	devinfo->disk = info->disk;
-@@ -2925,22 +1698,25 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
- static
- int ide_cdrom_probe_capabilities (ide_drive_t *drive)
- {
--	struct cdrom_info *info = drive->driver_data;
--	struct cdrom_device_info *cdi = &info->devinfo;
--	struct atapi_capabilities_page cap;
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct cdrom_device_info *cdi = &cd->devinfo;
-+	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
-+	mechtype_t mechtype;
- 	int nslots = 1;
+ /*
+@@ -46,7 +45,6 @@
+  */
  
-+	cdi->mask = (CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R |
-+		     CDC_DVD_RAM | CDC_SELECT_DISC | CDC_PLAY_AUDIO |
-+		     CDC_MO_DRIVE | CDC_RAM);
-+
- 	if (drive->media == ide_optical) {
--		CDROM_CONFIG_FLAGS(drive)->mo_drive = 1;
--		CDROM_CONFIG_FLAGS(drive)->ram = 1;
-+		cdi->mask &= ~(CDC_MO_DRIVE | CDC_RAM);
- 		printk(KERN_ERR "%s: ATAPI magneto-optical drive\n", drive->name);
- 		return nslots;
- 	}
+ #define	REVISION	"Revision: 7.00alpha2"
+-#define	VERSION		"Id: ide.c 7.00a2 20020906"
  
--	if (CDROM_CONFIG_FLAGS(drive)->nec260 ||
--	    !strcmp(drive->id->model,"STINGRAY 8422 IDE 8X CD-ROM 7-27-95")) {
--		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
--		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
-+	if (cd->cd_flags & IDE_CD_FLAG_PRE_ATAPI12) {
-+		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
-+		cdi->mask &= ~CDC_PLAY_AUDIO;
- 		return nslots;
- 	}
+ #define _IDE_C			/* Tell ide.h it's really us */
  
-@@ -2954,83 +1730,66 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
- 	cdi->handle = drive;
- 	cdi->ops = &ide_cdrom_dops;
+@@ -95,7 +93,7 @@ DEFINE_MUTEX(ide_cfg_mtx);
+  __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
  
--	if (ide_cdrom_get_capabilities(drive, &cap))
-+	if (ide_cdrom_get_capabilities(drive, buf))
- 		return 0;
+ #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
++int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
+ #endif
  
--	if (cap.lock == 0)
--		CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
--	if (cap.eject)
--		CDROM_CONFIG_FLAGS(drive)->no_eject = 0;
--	if (cap.cd_r_write)
--		CDROM_CONFIG_FLAGS(drive)->cd_r = 1;
--	if (cap.cd_rw_write) {
--		CDROM_CONFIG_FLAGS(drive)->cd_rw = 1;
--		CDROM_CONFIG_FLAGS(drive)->ram = 1;
--	}
--	if (cap.test_write)
--		CDROM_CONFIG_FLAGS(drive)->test_write = 1;
--	if (cap.dvd_ram_read || cap.dvd_r_read || cap.dvd_rom)
--		CDROM_CONFIG_FLAGS(drive)->dvd = 1;
--	if (cap.dvd_ram_write) {
--		CDROM_CONFIG_FLAGS(drive)->dvd_ram = 1;
--		CDROM_CONFIG_FLAGS(drive)->ram = 1;
--	}
--	if (cap.dvd_r_write)
--		CDROM_CONFIG_FLAGS(drive)->dvd_r = 1;
--	if (cap.audio_play)
--		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
--	if (cap.mechtype == mechtype_caddy || cap.mechtype == mechtype_popup)
--		CDROM_CONFIG_FLAGS(drive)->close_tray = 0;
--
--	/* Some drives used by Apple don't advertise audio play
--	 * but they do support reading TOC & audio datas
--	 */
--	if (strcmp(drive->id->model, "MATSHITADVD-ROM SR-8187") == 0 ||
--	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8186") == 0 ||
--	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8176") == 0 ||
--	    strcmp(drive->id->model, "MATSHITADVD-ROM SR-8174") == 0)
--		CDROM_CONFIG_FLAGS(drive)->audio_play = 1;
-+	if ((buf[8 + 6] & 0x01) == 0)
-+		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
-+	if (buf[8 + 6] & 0x08)
-+		cd->cd_flags &= ~IDE_CD_FLAG_NO_EJECT;
-+	if (buf[8 + 3] & 0x01)
-+		cdi->mask &= ~CDC_CD_R;
-+	if (buf[8 + 3] & 0x02)
-+		cdi->mask &= ~(CDC_CD_RW | CDC_RAM);
-+	if (buf[8 + 2] & 0x38)
-+		cdi->mask &= ~CDC_DVD;
-+	if (buf[8 + 3] & 0x20)
-+		cdi->mask &= ~(CDC_DVD_RAM | CDC_RAM);
-+	if (buf[8 + 3] & 0x10)
-+		cdi->mask &= ~CDC_DVD_R;
-+	if ((buf[8 + 4] & 0x01) || (cd->cd_flags & IDE_CD_FLAG_PLAY_AUDIO_OK))
-+		cdi->mask &= ~CDC_PLAY_AUDIO;
-+
-+	mechtype = buf[8 + 6] >> 5;
-+	if (mechtype == mechtype_caddy || mechtype == mechtype_popup)
-+		cdi->mask |= CDC_CLOSE_TRAY;
+ int noautodma = 0;
+@@ -116,7 +114,7 @@ EXPORT_SYMBOL(ide_hwifs);
+ /*
+  * Do not even *think* about calling this!
+  */
+-static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
++void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ {
+ 	unsigned int unit;
  
--#if ! STANDARD_ATAPI
- 	if (cdi->sanyo_slot > 0) {
--		CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
-+		cdi->mask &= ~CDC_SELECT_DISC;
- 		nslots = 3;
-+	} else if (mechtype == mechtype_individual_changer ||
-+		   mechtype == mechtype_cartridge_changer) {
-+		nslots = cdrom_number_of_slots(cdi);
-+		if (nslots > 1)
-+			cdi->mask &= ~CDC_SELECT_DISC;
+@@ -159,6 +157,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
+ 		init_completion(&drive->gendev_rel_comp);
  	}
+ }
++EXPORT_SYMBOL_GPL(ide_init_port_data);
  
--	else
--#endif /* not STANDARD_ATAPI */
--	if (cap.mechtype == mechtype_individual_changer ||
--	    cap.mechtype == mechtype_cartridge_changer) {
--		if ((nslots = cdrom_number_of_slots(cdi)) > 1) {
--			CDROM_CONFIG_FLAGS(drive)->is_changer = 1;
--			CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 1;
+ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+ {
+@@ -177,8 +176,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+ #endif
+ }
+ 
+-extern void ide_arm_init(void);
+-
+ /*
+  * init_ide_data() sets reasonable default values into all fields
+  * of all instances of the hwifs and drives, but only on the first call.
+@@ -210,16 +207,13 @@ static void __init init_ide_data (void)
+ 	/* Initialise all interface structures */
+ 	for (index = 0; index < MAX_HWIFS; ++index) {
+ 		hwif = &ide_hwifs[index];
+-		init_hwif_data(hwif, index);
++		ide_init_port_data(hwif, index);
+ 		init_hwif_default(hwif, index);
+ #if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
+ 		hwif->irq =
+ 			ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
+ #endif
+ 	}
+-#ifdef CONFIG_IDE_ARM
+-	ide_arm_init();
+-#endif
+ }
+ 
+ /**
+@@ -246,22 +240,12 @@ static int ide_system_bus_speed(void)
+ #define pci_default 0
+ #endif /* CONFIG_PCI */
+ 
+-	if (!system_bus_speed) {
+-		if (idebus_parameter) {
+-			/* user supplied value */
+-			system_bus_speed = idebus_parameter;
+-		} else if (pci_dev_present(pci_default)) {
+-			/* safe default value for PCI */
+-			system_bus_speed = 33;
+-		} else {
+-			/* safe default value for VESA and PCI */
+-			system_bus_speed = 50;
 -		}
+-		printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
+-			"for PIO modes%s\n", system_bus_speed,
+-			idebus_parameter ? "" : "; override with idebus=xx");
 -	}
-+	ide_cdrom_update_speed(drive, buf);
+-	return system_bus_speed;
++	/* user supplied value */
++	if (idebus_parameter)
++		return idebus_parameter;
++
++	/* safe default value for PCI or VESA and PCI*/
++	return pci_dev_present(pci_default) ? 33 : 50;
+ }
  
--	ide_cdrom_update_speed(drive, &cap);
--	/* don't print speed if the drive reported 0.
--	 */
- 	printk(KERN_INFO "%s: ATAPI", drive->name);
--	if (CDROM_CONFIG_FLAGS(drive)->max_speed)
--		printk(" %dX", CDROM_CONFIG_FLAGS(drive)->max_speed);
--	printk(" %s", CDROM_CONFIG_FLAGS(drive)->dvd ? "DVD-ROM" : "CD-ROM");
+ ide_hwif_t * ide_find_port(unsigned long base)
+@@ -409,13 +393,12 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+ 	hwif->chipset			= tmp_hwif->chipset;
+ 	hwif->hold			= tmp_hwif->hold;
  
--	if (CDROM_CONFIG_FLAGS(drive)->dvd_r|CDROM_CONFIG_FLAGS(drive)->dvd_ram)
--        	printk(" DVD%s%s", 
--        	(CDROM_CONFIG_FLAGS(drive)->dvd_r)? "-R" : "", 
--        	(CDROM_CONFIG_FLAGS(drive)->dvd_ram)? "-RAM" : "");
-+	/* don't print speed if the drive reported 0 */
-+	if (cd->max_speed)
-+		printk(KERN_CONT " %dX", cd->max_speed);
++	hwif->dev			= tmp_hwif->dev;
++
+ #ifdef CONFIG_BLK_DEV_IDEPCI
+-	hwif->pci_dev			= tmp_hwif->pci_dev;
+ 	hwif->cds			= tmp_hwif->cds;
+ #endif
  
--        if (CDROM_CONFIG_FLAGS(drive)->cd_r|CDROM_CONFIG_FLAGS(drive)->cd_rw) 
--        	printk(" CD%s%s", 
--        	(CDROM_CONFIG_FLAGS(drive)->cd_r)? "-R" : "", 
--        	(CDROM_CONFIG_FLAGS(drive)->cd_rw)? "/RW" : "");
-+	printk(KERN_CONT " %s", (cdi->mask & CDC_DVD) ? "CD-ROM" : "DVD-ROM");
+-	hwif->fixup			= tmp_hwif->fixup;
+-
+ 	hwif->set_pio_mode		= tmp_hwif->set_pio_mode;
+ 	hwif->set_dma_mode		= tmp_hwif->set_dma_mode;
+ 	hwif->mdma_filter		= tmp_hwif->mdma_filter;
+@@ -424,7 +407,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+ 	hwif->reset_poll		= tmp_hwif->reset_poll;
+ 	hwif->pre_reset			= tmp_hwif->pre_reset;
+ 	hwif->resetproc			= tmp_hwif->resetproc;
+-	hwif->intrproc			= tmp_hwif->intrproc;
+ 	hwif->maskproc			= tmp_hwif->maskproc;
+ 	hwif->quirkproc			= tmp_hwif->quirkproc;
+ 	hwif->busproc			= tmp_hwif->busproc;
+@@ -434,16 +416,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+ 	hwif->atapi_input_bytes		= tmp_hwif->atapi_input_bytes;
+ 	hwif->atapi_output_bytes	= tmp_hwif->atapi_output_bytes;
  
--        if (CDROM_CONFIG_FLAGS(drive)->is_changer) 
--        	printk(" changer w/%d slots", nslots);
--        else 	
--        	printk(" drive");
-+	if ((cdi->mask & CDC_DVD_R) == 0 || (cdi->mask & CDC_DVD_RAM) == 0)
-+		printk(KERN_CONT " DVD%s%s",
-+				 (cdi->mask & CDC_DVD_R) ? "" : "-R",
-+				 (cdi->mask & CDC_DVD_RAM) ? "" : "-RAM");
++	hwif->dma_host_set		= tmp_hwif->dma_host_set;
+ 	hwif->dma_setup			= tmp_hwif->dma_setup;
+ 	hwif->dma_exec_cmd		= tmp_hwif->dma_exec_cmd;
+ 	hwif->dma_start			= tmp_hwif->dma_start;
+ 	hwif->ide_dma_end		= tmp_hwif->ide_dma_end;
+-	hwif->ide_dma_on		= tmp_hwif->ide_dma_on;
+-	hwif->dma_off_quietly		= tmp_hwif->dma_off_quietly;
+ 	hwif->ide_dma_test_irq		= tmp_hwif->ide_dma_test_irq;
+ 	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;
+-	hwif->dma_host_on		= tmp_hwif->dma_host_on;
+-	hwif->dma_host_off		= tmp_hwif->dma_host_off;
+ 	hwif->dma_lost_irq		= tmp_hwif->dma_lost_irq;
+ 	hwif->dma_timeout		= tmp_hwif->dma_timeout;
  
--	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(cap.buffer_size));
-+	if ((cdi->mask & CDC_CD_R) == 0 || (cdi->mask & CDC_CD_RW) == 0)
-+		printk(KERN_CONT " CD%s%s",
-+				 (cdi->mask & CDC_CD_R) ? "" : "-R",
-+				 (cdi->mask & CDC_CD_RW) ? "" : "/RW");
-+
-+	if ((cdi->mask & CDC_SELECT_DISC) == 0)
-+		printk(KERN_CONT " changer w/%d slots", nslots);
-+	else
-+		printk(KERN_CONT " drive");
-+
-+	printk(KERN_CONT ", %dkB Cache\n", be16_to_cpu(*(u16 *)&buf[8 + 12]));
+@@ -468,7 +447,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+ #endif
  
- 	return nslots;
- }
-@@ -3123,11 +1882,74 @@ static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq)
- 	return 0;
+ 	hwif->dma_base			= tmp_hwif->dma_base;
+-	hwif->dma_master		= tmp_hwif->dma_master;
+ 	hwif->dma_command		= tmp_hwif->dma_command;
+ 	hwif->dma_vendor1		= tmp_hwif->dma_vendor1;
+ 	hwif->dma_status		= tmp_hwif->dma_status;
+@@ -483,9 +461,46 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+ 	hwif->hwif_data			= tmp_hwif->hwif_data;
  }
  
-+struct cd_list_entry {
-+	const char	*id_model;
-+	const char	*id_firmware;
-+	unsigned int	cd_flags;
-+};
++void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
++{
++	ide_hwgroup_t *hwgroup = hwif->hwgroup;
 +
-+static const struct cd_list_entry ide_cd_quirks_list[] = {
-+	/* Limit transfer size per interrupt. */
-+	{ "SAMSUNG CD-ROM SCR-2430", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
-+	{ "SAMSUNG CD-ROM SCR-2432", NULL,   IDE_CD_FLAG_LIMIT_NFRAMES	    },
-+	/* SCR-3231 doesn't support the SET_CD_SPEED command. */
-+	{ "SAMSUNG CD-ROM SCR-3231", NULL,   IDE_CD_FLAG_NO_SPEED_SELECT    },
-+	/* Old NEC260 (not R) was released before ATAPI 1.2 spec. */
-+	{ "NEC CD-ROM DRIVE:260",    "1.01", IDE_CD_FLAG_TOCADDR_AS_BCD |
-+					     IDE_CD_FLAG_PRE_ATAPI12,	    },
-+	/* Vertos 300, some versions of this drive like to talk BCD. */
-+	{ "V003S0DS",		     NULL,   IDE_CD_FLAG_VERTOS_300_SSD,    },
-+	/* Vertos 600 ESD. */
-+	{ "V006E0DS",		     NULL,   IDE_CD_FLAG_VERTOS_600_ESD,    },
-+	/*
-+	 * Sanyo 3 CD changer uses a non-standard command for CD changing
-+	 * (by default standard ATAPI support for CD changers is used).
-+	 */
-+	{ "CD-ROM CDR-C3 G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
-+	{ "CD-ROM CDR-C3G",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
-+	{ "CD-ROM CDR_C36",	     NULL,   IDE_CD_FLAG_SANYO_3CD	    },
-+	/* Stingray 8X CD-ROM. */
-+	{ "STINGRAY 8422 IDE 8X CD-ROM 7-27-95", NULL, IDE_CD_FLAG_PRE_ATAPI12},
-+	/*
-+	 * ACER 50X CD-ROM and WPI 32X CD-ROM require the full spec length
-+	 * mode sense page capabilities size, but older drives break.
-+	 */
-+	{ "ATAPI CD ROM DRIVE 50X MAX",	NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
-+	{ "WPI CDS-32X",		NULL,	IDE_CD_FLAG_FULL_CAPS_PAGE  },
-+	/* ACER/AOpen 24X CD-ROM has the speed fields byte-swapped. */
-+	{ "",			     "241N", IDE_CD_FLAG_LE_SPEED_FIELDS    },
++	spin_lock_irq(&ide_lock);
 +	/*
-+	 * Some drives used by Apple don't advertise audio play
-+	 * but they do support reading TOC & audio datas.
++	 * Remove us from the hwgroup, and free
++	 * the hwgroup if we were the only member
 +	 */
-+	{ "MATSHITADVD-ROM SR-8187", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-+	{ "MATSHITADVD-ROM SR-8186", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-+	{ "MATSHITADVD-ROM SR-8176", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-+	{ "MATSHITADVD-ROM SR-8174", NULL,   IDE_CD_FLAG_PLAY_AUDIO_OK	    },
-+	{ NULL, NULL, 0 }
-+};
-+
-+static unsigned int ide_cd_flags(struct hd_driveid *id)
-+{
-+	const struct cd_list_entry *cle = ide_cd_quirks_list;
++	if (hwif->next == hwif) {
++		BUG_ON(hwgroup->hwif != hwif);
++		kfree(hwgroup);
++	} else {
++		/* There is another interface in hwgroup.
++		 * Unlink us, and set hwgroup->drive and ->hwif to
++		 * something sane.
++		 */
++		ide_hwif_t *g = hwgroup->hwif;
 +
-+	while (cle->id_model) {
-+		if (strcmp(cle->id_model, id->model) == 0 &&
-+		    (cle->id_firmware == NULL ||
-+		     strstr(id->fw_rev, cle->id_firmware)))
-+			return cle->cd_flags;
-+		cle++;
++		while (g->next != hwif)
++			g = g->next;
++		g->next = hwif->next;
++		if (hwgroup->hwif == hwif) {
++			/* Chose a random hwif for hwgroup->hwif.
++			 * It's guaranteed that there are no drives
++			 * left in the hwgroup.
++			 */
++			BUG_ON(hwgroup->drive != NULL);
++			hwgroup->hwif = g;
++		}
++		BUG_ON(hwgroup->hwif == hwif);
 +	}
-+
-+	return 0;
++	spin_unlock_irq(&ide_lock);
 +}
 +
- static
- int ide_cdrom_setup (ide_drive_t *drive)
+ /**
+  *	ide_unregister		-	free an IDE interface
+  *	@index: index of interface (will change soon to a pointer)
++ *	@init_default: init default hwif flag
++ *	@restore: restore hwif flag
+  *
+  *	Perform the final unregister of an IDE interface. At the moment
+  *	we don't refcount interfaces so this will also get split up.
+@@ -505,7 +520,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
+  *	This is raving bonkers.
+  */
+ 
+-void ide_unregister(unsigned int index)
++void ide_unregister(unsigned int index, int init_default, int restore)
  {
--	struct cdrom_info *info = drive->driver_data;
--	struct cdrom_device_info *cdi = &info->devinfo;
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct cdrom_device_info *cdi = &cd->devinfo;
-+	struct hd_driveid *id = drive->id;
- 	int nslots;
+ 	ide_drive_t *drive;
+ 	ide_hwif_t *hwif, *g;
+@@ -550,43 +565,8 @@ void ide_unregister(unsigned int index)
+ 	if (irq_count == 1)
+ 		free_irq(hwif->irq, hwgroup);
  
- 	blk_queue_prep_rq(drive->queue, ide_cdrom_prep_fn);
-@@ -3138,101 +1960,21 @@ int ide_cdrom_setup (ide_drive_t *drive)
+-	spin_lock_irq(&ide_lock);
+-	/*
+-	 * Note that we only release the standard ports,
+-	 * and do not even try to handle any extra ports
+-	 * allocated for weird IDE interface chipsets.
+-	 */
+-	ide_hwif_release_regions(hwif);
++	ide_remove_port_from_hwgroup(hwif);
  
- 	drive->special.all	= 0;
+-	/*
+-	 * Remove us from the hwgroup, and free
+-	 * the hwgroup if we were the only member
+-	 */
+-	if (hwif->next == hwif) {
+-		BUG_ON(hwgroup->hwif != hwif);
+-		kfree(hwgroup);
+-	} else {
+-		/* There is another interface in hwgroup.
+-		 * Unlink us, and set hwgroup->drive and ->hwif to
+-		 * something sane.
+-		 */
+-		g = hwgroup->hwif;
+-		while (g->next != hwif)
+-			g = g->next;
+-		g->next = hwif->next;
+-		if (hwgroup->hwif == hwif) {
+-			/* Chose a random hwif for hwgroup->hwif.
+-			 * It's guaranteed that there are no drives
+-			 * left in the hwgroup.
+-			 */
+-			BUG_ON(hwgroup->drive != NULL);
+-			hwgroup->hwif = g;
+-		}
+-		BUG_ON(hwgroup->hwif == hwif);
+-	}
+-
+-	/* More messed up locking ... */
+-	spin_unlock_irq(&ide_lock);
+ 	device_unregister(&hwif->gendev);
+ 	wait_for_completion(&hwif->gendev_rel_comp);
  
--	CDROM_STATE_FLAGS(drive)->media_changed = 1;
--	CDROM_STATE_FLAGS(drive)->toc_valid     = 0;
--	CDROM_STATE_FLAGS(drive)->door_locked   = 0;
-+	cd->cd_flags = IDE_CD_FLAG_MEDIA_CHANGED | IDE_CD_FLAG_NO_EJECT |
-+		       ide_cd_flags(id);
+@@ -602,7 +582,6 @@ void ide_unregister(unsigned int index)
+ 		(void) ide_release_dma(hwif);
  
--#if NO_DOOR_LOCKING
--	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 1;
--#else
--	CDROM_CONFIG_FLAGS(drive)->no_doorlock = 0;
--#endif
-+	if ((id->config & 0x0060) == 0x20)
-+		cd->cd_flags |= IDE_CD_FLAG_DRQ_INTERRUPT;
+ 		hwif->dma_base = 0;
+-		hwif->dma_master = 0;
+ 		hwif->dma_command = 0;
+ 		hwif->dma_vendor1 = 0;
+ 		hwif->dma_status = 0;
+@@ -613,14 +592,24 @@ void ide_unregister(unsigned int index)
+ 		hwif->extra_ports = 0;
+ 	}
  
--	CDROM_CONFIG_FLAGS(drive)->drq_interrupt = ((drive->id->config & 0x0060) == 0x20);
--	CDROM_CONFIG_FLAGS(drive)->is_changer = 0;
--	CDROM_CONFIG_FLAGS(drive)->cd_r = 0;
--	CDROM_CONFIG_FLAGS(drive)->cd_rw = 0;
--	CDROM_CONFIG_FLAGS(drive)->test_write = 0;
--	CDROM_CONFIG_FLAGS(drive)->dvd = 0;
--	CDROM_CONFIG_FLAGS(drive)->dvd_r = 0;
--	CDROM_CONFIG_FLAGS(drive)->dvd_ram = 0;
--	CDROM_CONFIG_FLAGS(drive)->no_eject = 1;
--	CDROM_CONFIG_FLAGS(drive)->supp_disc_present = 0;
--	CDROM_CONFIG_FLAGS(drive)->audio_play = 0;
--	CDROM_CONFIG_FLAGS(drive)->close_tray = 1;
--	
--	/* limit transfer size per interrupt. */
--	CDROM_CONFIG_FLAGS(drive)->limit_nframes = 0;
--	/* a testament to the nice quality of Samsung drives... */
--	if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2430"))
--		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
--	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-2432"))
--		CDROM_CONFIG_FLAGS(drive)->limit_nframes = 1;
--	/* the 3231 model does not support the SET_CD_SPEED command */
--	else if (!strcmp(drive->id->model, "SAMSUNG CD-ROM SCR-3231"))
--		CDROM_CONFIG_FLAGS(drive)->no_speed_select = 1;
--
--#if ! STANDARD_ATAPI
--	/* by default Sanyo 3 CD changer support is turned off and
--           ATAPI Rev 2.2+ standard support for CD changers is used */
--	cdi->sanyo_slot = 0;
--
--	CDROM_CONFIG_FLAGS(drive)->nec260 = 0;
--	CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 0;
--	CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 0;
--	CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 0;
--	CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 0;
--
--	if (strcmp (drive->id->model, "V003S0DS") == 0 &&
--	    drive->id->fw_rev[4] == '1' &&
--	    drive->id->fw_rev[6] <= '2') {
--		/* Vertos 300.
--		   Some versions of this drive like to talk BCD. */
--		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
--	}
--
--	else if (strcmp (drive->id->model, "V006E0DS") == 0 &&
--	    drive->id->fw_rev[4] == '1' &&
--	    drive->id->fw_rev[6] <= '2') {
--		/* Vertos 600 ESD. */
--		CDROM_CONFIG_FLAGS(drive)->toctracks_as_bcd = 1;
--	}
--	else if (strcmp(drive->id->model, "NEC CD-ROM DRIVE:260") == 0 &&
--		 strncmp(drive->id->fw_rev, "1.01", 4) == 0) { /* FIXME */
--		/* Old NEC260 (not R).
--		   This drive was released before the 1.2 version
--		   of the spec. */
--		CDROM_CONFIG_FLAGS(drive)->tocaddr_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->nec260         = 1;
--	}
--	else if (strcmp(drive->id->model, "WEARNES CDD-120") == 0 &&
--		 strncmp(drive->id->fw_rev, "A1.1", 4) == 0) { /* FIXME */
--		/* Wearnes */
--		CDROM_CONFIG_FLAGS(drive)->playmsf_as_bcd = 1;
--		CDROM_CONFIG_FLAGS(drive)->subchan_as_bcd = 1;
--	}
--        /* Sanyo 3 CD changer uses a non-standard command
--           for CD changing */
--        else if ((strcmp(drive->id->model, "CD-ROM CDR-C3 G") == 0) ||
--                 (strcmp(drive->id->model, "CD-ROM CDR-C3G") == 0) ||
--                 (strcmp(drive->id->model, "CD-ROM CDR_C36") == 0)) {
--                 /* uses CD in slot 0 when value is set to 3 */
--                 cdi->sanyo_slot = 3;
--        }
--#endif /* not STANDARD_ATAPI */
--
--	info->toc		= NULL;
--	info->buffer		= NULL;
--	info->sector_buffered	= 0;
--	info->nsectors_buffered	= 0;
--	info->changer_info      = NULL;
--	info->last_block	= 0;
--	info->start_seek	= 0;
-+	if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_300_SSD) &&
-+	    id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
-+		cd->cd_flags |= (IDE_CD_FLAG_TOCTRACKS_AS_BCD |
-+				 IDE_CD_FLAG_TOCADDR_AS_BCD);
-+	else if ((cd->cd_flags & IDE_CD_FLAG_VERTOS_600_ESD) &&
-+		 id->fw_rev[4] == '1' && id->fw_rev[6] <= '2')
-+		cd->cd_flags |= IDE_CD_FLAG_TOCTRACKS_AS_BCD;
-+	else if (cd->cd_flags & IDE_CD_FLAG_SANYO_3CD)
-+		cdi->sanyo_slot = 3;	/* 3 => use CD in slot 0 */
++	/*
++	 * Note that we only release the standard ports,
++	 * and do not even try to handle any extra ports
++	 * allocated for weird IDE interface chipsets.
++	 */
++	ide_hwif_release_regions(hwif);
++
+ 	/* copy original settings */
+ 	tmp_hwif = *hwif;
  
- 	nslots = ide_cdrom_probe_capabilities (drive);
+ 	/* restore hwif data to pristine status */
+-	init_hwif_data(hwif, index);
+-	init_hwif_default(hwif, index);
++	ide_init_port_data(hwif, index);
  
-@@ -3247,7 +1989,7 @@ int ide_cdrom_setup (ide_drive_t *drive)
+-	ide_hwif_restore(hwif, &tmp_hwif);
++	if (init_default)
++		init_hwif_default(hwif, index);
++
++	if (restore)
++		ide_hwif_restore(hwif, &tmp_hwif);
  
- 	if (ide_cdrom_register(drive, nslots)) {
- 		printk (KERN_ERR "%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name);
--		info->devinfo.handle = NULL;
-+		cd->devinfo.handle = NULL;
- 		return 1;
- 	}
- 	ide_cdrom_add_settings(drive);
-@@ -3287,7 +2029,6 @@ static void ide_cd_release(struct kref *kref)
+ abort:
+ 	spin_unlock_irq(&ide_lock);
+@@ -629,124 +618,86 @@ abort:
  
- 	kfree(info->buffer);
- 	kfree(info->toc);
--	kfree(info->changer_info);
- 	if (devinfo->handle == drive && unregister_cdrom(devinfo))
- 		printk(KERN_ERR "%s: %s failed to unregister device from the cdrom "
- 				"driver.\n", __FUNCTION__, drive->name);
-@@ -3443,7 +2184,9 @@ static int idecd_revalidate_disk(struct gendisk *disk)
+ EXPORT_SYMBOL(ide_unregister);
+ 
++void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
++{
++	memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
++	hwif->irq = hw->irq;
++	hwif->noprobe = 0;
++	hwif->chipset = hw->chipset;
++	hwif->gendev.parent = hw->dev;
++	hwif->ack_intr = hw->ack_intr;
++}
++EXPORT_SYMBOL_GPL(ide_init_port_hw);
+ 
+-/**
+- *	ide_setup_ports 	-	set up IDE interface ports
+- *	@hw: register descriptions
+- *	@base: base register
+- *	@offsets: table of register offsets
+- *	@ctrl: control register
+- *	@ack_irq: IRQ ack
+- *	@irq: interrupt lie
+- *
+- *	Setup hw_regs_t structure described by parameters.  You
+- *	may set up the hw structure yourself OR use this routine to
+- *	do it for you. This is basically a helper
+- *
+- */
+- 
+-void ide_setup_ports (	hw_regs_t *hw,
+-			unsigned long base, int *offsets,
+-			unsigned long ctrl, unsigned long intr,
+-			ide_ack_intr_t *ack_intr,
+-/*
+- *			ide_io_ops_t *iops,
+- */
+-			int irq)
++ide_hwif_t *ide_deprecated_find_port(unsigned long base)
  {
- 	struct cdrom_info *info = ide_cd_g(disk);
- 	struct request_sense sense;
--	cdrom_read_toc(info->drive, &sense);
++	ide_hwif_t *hwif;
+ 	int i;
+ 
+-	memset(hw, 0, sizeof(hw_regs_t));
+-	for (i = 0; i < IDE_NR_PORTS; i++) {
+-		if (offsets[i] == -1) {
+-			switch(i) {
+-				case IDE_CONTROL_OFFSET:
+-					hw->io_ports[i] = ctrl;
+-					break;
+-#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
+-				case IDE_IRQ_OFFSET:
+-					hw->io_ports[i] = intr;
+-					break;
+-#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
+-				default:
+-					hw->io_ports[i] = 0;
+-					break;
+-			}
+-		} else {
+-			hw->io_ports[i] = base + offsets[i];
+-		}
++	for (i = 0; i < MAX_HWIFS; i++) {
++		hwif = &ide_hwifs[i];
++		if (hwif->io_ports[IDE_DATA_OFFSET] == base)
++			goto found;
+ 	}
+-	hw->irq = irq;
+-	hw->ack_intr = ack_intr;
+-/*
+- *	hw->iops = iops;
+- */
 +
-+	ide_cd_read_toc(info->drive, &sense);
++	for (i = 0; i < MAX_HWIFS; i++) {
++		hwif = &ide_hwifs[i];
++		if (hwif->hold)
++			continue;
++		if (!hwif->present && hwif->mate == NULL)
++			goto found;
++	}
 +
- 	return  0;
++	hwif = NULL;
++found:
++	return hwif;
  }
++EXPORT_SYMBOL_GPL(ide_deprecated_find_port);
  
-@@ -3518,7 +2261,7 @@ static int ide_cd_probe(ide_drive_t *drive)
- 		goto failed;
- 	}
+ /**
+  *	ide_register_hw		-	register IDE interface
+  *	@hw: hardware registers
+- *	@fixup: fixup function
+- *	@initializing: set while initializing built-in drivers
++ *	@quirkproc: quirkproc function
+  *	@hwifp: pointer to returned hwif
+  *
+  *	Register an IDE interface, specifying exactly the registers etc.
+- *	Set init=1 iff calling before probes have taken place.
+  *
+  *	Returns -1 on error.
+  */
  
--	cdrom_read_toc(drive, &sense);
-+	ide_cd_read_toc(drive, &sense);
- 	g->fops = &idecd_ops;
- 	g->flags |= GENHD_FL_REMOVABLE;
- 	add_disk(g);
-@@ -3541,6 +2284,7 @@ static int __init ide_cdrom_init(void)
+-int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *),
+-		    int initializing, ide_hwif_t **hwifp)
++int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
++		    ide_hwif_t **hwifp)
+ {
+ 	int index, retry = 1;
+ 	ide_hwif_t *hwif;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+ 	do {
+-		for (index = 0; index < MAX_HWIFS; ++index) {
+-			hwif = &ide_hwifs[index];
+-			if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
+-				goto found;
+-		}
+-		for (index = 0; index < MAX_HWIFS; ++index) {
+-			hwif = &ide_hwifs[index];
+-			if (hwif->hold)
+-				continue;
+-			if ((!hwif->present && !hwif->mate && !initializing) ||
+-			    (!hwif->io_ports[IDE_DATA_OFFSET] && initializing))
+-				goto found;
+-		}
++		hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]);
++		index = hwif->index;
++		if (hwif)
++			goto found;
+ 		for (index = 0; index < MAX_HWIFS; index++)
+-			ide_unregister(index);
++			ide_unregister(index, 1, 1);
+ 	} while (retry--);
+ 	return -1;
+ found:
+ 	if (hwif->present)
+-		ide_unregister(index);
+-	else if (!hwif->hold) {
+-		init_hwif_data(hwif, index);
+-		init_hwif_default(hwif, index);
+-	}
+-	if (hwif->present)
+-		return -1;
+-	memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
+-	hwif->irq = hw->irq;
+-	hwif->noprobe = 0;
+-	hwif->fixup = fixup;
+-	hwif->chipset = hw->chipset;
+-	hwif->gendev.parent = hw->dev;
+-	hwif->ack_intr = hw->ack_intr;
++		ide_unregister(index, 0, 1);
++	else if (!hwif->hold)
++		ide_init_port_data(hwif, index);
+ 
+-	if (initializing == 0) {
+-		u8 idx[4] = { index, 0xff, 0xff, 0xff };
++	ide_init_port_hw(hwif, hw);
++	hwif->quirkproc = quirkproc;
+ 
+-		ide_device_add(idx);
+-	}
++	idx[0] = index;
++
++	ide_device_add(idx, NULL);
+ 
+ 	if (hwifp)
+ 		*hwifp = hwif;
+ 
+-	return (initializing || hwif->present) ? index : -1;
++	return hwif->present ? index : -1;
  }
  
- MODULE_ALIAS("ide:*m-cdrom*");
-+MODULE_ALIAS("ide-cd");
- module_init(ide_cdrom_init);
- module_exit(ide_cdrom_exit);
- MODULE_LICENSE("GPL");
-diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h
-index 1b302fe..22e3751 100644
---- a/drivers/ide/ide-cd.h
-+++ b/drivers/ide/ide-cd.h
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/ide_cd.h
-- *
-  *  Copyright (C) 1996-98  Erik Andersen
-  *  Copyright (C) 1998-2000 Jens Axboe
-  */
-@@ -10,31 +8,6 @@
- #include <linux/cdrom.h>
- #include <asm/byteorder.h>
+ EXPORT_SYMBOL(ide_register_hw);
+@@ -804,10 +755,6 @@ int set_io_32bit(ide_drive_t *drive, int arg)
+ 		return -EBUSY;
  
--/* Turn this on to have the driver print out the meanings of the
--   ATAPI error codes.  This will use up additional kernel-space
--   memory, though. */
--
--#ifndef VERBOSE_IDE_CD_ERRORS
--#define VERBOSE_IDE_CD_ERRORS 1
--#endif
--
--
--/* Turning this on will remove code to work around various nonstandard
--   ATAPI implementations.  If you know your drive follows the standard,
--   this will give you a slightly smaller kernel. */
--
--#ifndef STANDARD_ATAPI
--#define STANDARD_ATAPI 0
--#endif
--
--
--/* Turning this on will disable the door-locking functionality.
--   This is apparently needed for supermount. */
--
--#ifndef NO_DOOR_LOCKING
--#define NO_DOOR_LOCKING 0
--#endif
--
- /*
-  * typical timeout for packet command
-  */
-@@ -49,68 +22,47 @@
- #endif
- #define SECTORS_PER_FRAME	(CD_FRAMESIZE >> SECTOR_BITS)
- #define SECTOR_BUFFER_SIZE	(CD_FRAMESIZE * 32)
--#define SECTORS_BUFFER		(SECTOR_BUFFER_SIZE >> SECTOR_BITS)
--#define SECTORS_MAX		(131072 >> SECTOR_BITS)
--
--#define BLOCKS_PER_FRAME	(CD_FRAMESIZE / BLOCK_SIZE)
--
--/* special command codes for strategy routine. */
--#define PACKET_COMMAND        4315
--#define REQUEST_SENSE_COMMAND 4316
--#define RESET_DRIVE_COMMAND   4317
--
--
--/* Configuration flags.  These describe the capabilities of the drive.
--   They generally do not change after initialization, unless we learn
--   more about the drive from stuff failing. */
--struct ide_cd_config_flags {
--	__u8 drq_interrupt	: 1; /* Device sends an interrupt when ready
--					for a packet command. */
--	__u8 no_doorlock	: 1; /* Drive cannot lock the door. */
--	__u8 no_eject		: 1; /* Drive cannot eject the disc. */
--	__u8 nec260		: 1; /* Drive is a pre-1.2 NEC 260 drive. */
--	__u8 playmsf_as_bcd	: 1; /* PLAYMSF command takes BCD args. */
--	__u8 tocaddr_as_bcd	: 1; /* TOC addresses are in BCD. */
--	__u8 toctracks_as_bcd	: 1; /* TOC track numbers are in BCD. */
--	__u8 subchan_as_bcd	: 1; /* Subchannel info is in BCD. */
--	__u8 is_changer		: 1; /* Drive is a changer. */
--	__u8 cd_r		: 1; /* Drive can write to CD-R media . */
--	__u8 cd_rw		: 1; /* Drive can write to CD-R/W media . */
--	__u8 dvd		: 1; /* Drive is a DVD-ROM */
--	__u8 dvd_r		: 1; /* Drive can write DVD-R */
--	__u8 dvd_ram		: 1; /* Drive can write DVD-RAM */
--	__u8 ram		: 1; /* generic WRITE (dvd-ram/mrw) */
--	__u8 test_write		: 1; /* Drive can fake writes */
--	__u8 supp_disc_present	: 1; /* Changer can report exact contents
--					of slots. */
--	__u8 limit_nframes	: 1; /* Drive does not provide data in
--					multiples of SECTOR_SIZE when more
--					than one interrupt is needed. */
--	__u8 seeking		: 1; /* Seeking in progress */
--	__u8 audio_play		: 1; /* can do audio related commands */
--	__u8 close_tray		: 1; /* can close the tray */
--	__u8 writing		: 1; /* pseudo write in progress */
--	__u8 mo_drive		: 1; /* drive is an MO device */
--	__u8 no_speed_select	: 1; /* SET_CD_SPEED command is unsupported. */
--	__u8 reserved		: 1;
--	byte max_speed;		     /* Max speed of the drive */
--};
--#define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags))
+ 	drive->io_32bit = arg;
+-#ifdef CONFIG_BLK_DEV_DTC2278
+-	if (HWIF(drive)->chipset == ide_dtc2278)
+-		HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
+-#endif /* CONFIG_BLK_DEV_DTC2278 */
  
-- 
--/* State flags.  These give information about the current state of the
--   drive, and will change during normal operation. */
--struct ide_cd_state_flags {
--	__u8 media_changed : 1; /* Driver has noticed a media change. */
--	__u8 toc_valid     : 1; /* Saved TOC information is current. */
--	__u8 door_locked   : 1; /* We think that the drive door is locked. */
--	__u8 writing       : 1; /* the drive is currently writing */
--	__u8 reserved      : 4;
--	byte current_speed;	/* Current speed of the drive */
-+/* Capabilities Page size including 8 bytes of Mode Page Header */
-+#define ATAPI_CAPABILITIES_PAGE_SIZE		(8 + 20)
-+#define ATAPI_CAPABILITIES_PAGE_PAD_SIZE	4
+ 	spin_unlock_irq(&ide_lock);
+ 
+@@ -839,7 +786,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
+ 	if (!drive->id || !(drive->id->capability & 1))
+ 		goto out;
+ 
+-	if (hwif->ide_dma_on == NULL)
++	if (hwif->dma_host_set == NULL)
+ 		goto out;
+ 
+ 	err = -EBUSY;
+@@ -854,8 +801,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
+ 	err = 0;
+ 
+ 	if (arg) {
+-		hwif->dma_off_quietly(drive);
+-		if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
++		if (ide_set_dma(drive))
+ 			err = -EIO;
+ 	} else
+ 		ide_dma_off(drive);
+@@ -888,7 +834,10 @@ int set_pio_mode(ide_drive_t *drive, int arg)
+ 
+ 	if (drive->special.b.set_tune)
+ 		return -EBUSY;
 +
-+enum {
-+	/* Device sends an interrupt when ready for a packet command. */
-+	IDE_CD_FLAG_DRQ_INTERRUPT	= (1 << 0),
-+	/* Drive cannot lock the door. */
-+	IDE_CD_FLAG_NO_DOORLOCK		= (1 << 1),
-+	/* Drive cannot eject the disc. */
-+	IDE_CD_FLAG_NO_EJECT		= (1 << 2),
-+	/* Drive is a pre ATAPI 1.2 drive. */
-+	IDE_CD_FLAG_PRE_ATAPI12		= (1 << 3),
-+	/* TOC addresses are in BCD. */
-+	IDE_CD_FLAG_TOCADDR_AS_BCD	= (1 << 4),
-+	/* TOC track numbers are in BCD. */
-+	IDE_CD_FLAG_TOCTRACKS_AS_BCD	= (1 << 5),
-+	/*
-+	 * Drive does not provide data in multiples of SECTOR_SIZE
-+	 * when more than one interrupt is needed.
-+	 */
-+	IDE_CD_FLAG_LIMIT_NFRAMES	= (1 << 6),
-+	/* Seeking in progress. */
-+	IDE_CD_FLAG_SEEKING		= (1 << 7),
-+	/* Driver has noticed a media change. */
-+	IDE_CD_FLAG_MEDIA_CHANGED	= (1 << 8),
-+	/* Saved TOC information is current. */
-+	IDE_CD_FLAG_TOC_VALID		= (1 << 9),
-+	/* We think that the drive door is locked. */
-+	IDE_CD_FLAG_DOOR_LOCKED		= (1 << 10),
-+	/* SET_CD_SPEED command is unsupported. */
-+	IDE_CD_FLAG_NO_SPEED_SELECT	= (1 << 11),
-+	IDE_CD_FLAG_VERTOS_300_SSD	= (1 << 12),
-+	IDE_CD_FLAG_VERTOS_600_ESD	= (1 << 13),
-+	IDE_CD_FLAG_SANYO_3CD		= (1 << 14),
-+	IDE_CD_FLAG_FULL_CAPS_PAGE	= (1 << 15),
-+	IDE_CD_FLAG_PLAY_AUDIO_OK	= (1 << 16),
-+	IDE_CD_FLAG_LE_SPEED_FIELDS	= (1 << 17),
- };
+ 	ide_init_drive_cmd(&rq);
++	rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
++
+ 	drive->tune_req = (u8) arg;
+ 	drive->special.b.set_tune = 1;
+ 	(void) ide_do_drive_cmd(drive, &rq, ide_wait);
+@@ -920,7 +869,7 @@ static int set_unmaskirq(ide_drive_t *drive, int arg)
  
--#define CDROM_STATE_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->state_flags))
--
- /* Structure of a MSF cdrom address. */
- struct atapi_msf {
- 	byte reserved;
-@@ -155,310 +107,6 @@ struct atapi_toc {
- 	  /* One extra for the leadout. */
- };
+ int system_bus_clock (void)
+ {
+-	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
++	return system_bus_speed;
+ }
  
+ EXPORT_SYMBOL(system_bus_clock);
+@@ -1032,11 +981,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
+ 		case HDIO_GET_NICE:
+ 			return put_user(drive->dsc_overlap	<<	IDE_NICE_DSC_OVERLAP	|
+ 					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP	|
+-					drive->nice0		<< 	IDE_NICE_0		|
+-					drive->nice1		<<	IDE_NICE_1		|
+-					drive->nice2		<<	IDE_NICE_2,
++					drive->nice1 << IDE_NICE_1,
+ 					(long __user *) arg);
 -
--/* This structure is annoyingly close to, but not identical with,
--   the cdrom_subchnl structure from cdrom.h. */
--struct atapi_cdrom_subchnl {
-- 	u_char  acdsc_reserved;
-- 	u_char  acdsc_audiostatus;
-- 	u_short acdsc_length;
--	u_char  acdsc_format;
--
--#if defined(__BIG_ENDIAN_BITFIELD)
--	u_char  acdsc_ctrl:     4;
--	u_char  acdsc_adr:      4;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	u_char  acdsc_adr:	4;
--	u_char  acdsc_ctrl:	4;
--#else
--#error "Please fix <asm/byteorder.h>"
+ #ifdef CONFIG_IDE_TASK_IOCTL
+ 		case HDIO_DRIVE_TASKFILE:
+ 		        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+@@ -1070,14 +1016,14 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
+ 			ide_init_hwif_ports(&hw, (unsigned long) args[0],
+ 					    (unsigned long) args[1], NULL);
+ 			hw.irq = args[2];
+-			if (ide_register_hw(&hw, NULL, 0, NULL) == -1)
++			if (ide_register_hw(&hw, NULL, NULL) == -1)
+ 				return -EIO;
+ 			return 0;
+ 		}
+ 	        case HDIO_UNREGISTER_HWIF:
+ 			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
+ 			/* (arg > MAX_HWIFS) checked in function */
+-			ide_unregister(arg);
++			ide_unregister(arg, 1, 1);
+ 			return 0;
+ 		case HDIO_SET_NICE:
+ 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+@@ -1231,26 +1177,12 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
+ 	return 0;	/* zero = nothing matched */
+ }
+ 
+-#ifdef CONFIG_BLK_DEV_ALI14XX
+ extern int probe_ali14xx;
+-extern int ali14xx_init(void);
 -#endif
--	u_char  acdsc_trk;
--	u_char  acdsc_ind;
--	union {
--		struct atapi_msf msf;
--		int	lba;
--	} acdsc_absaddr;
--	union {
--		struct atapi_msf msf;
--		int	lba;
--	} acdsc_reladdr;
--};
--
--
--
--/* This should probably go into cdrom.h along with the other
-- * generic stuff now in the Mt. Fuji spec.
-- */
--struct atapi_capabilities_page {
--	struct mode_page_header header;
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 parameters_saveable : 1;
--	__u8 reserved1           : 1;
--	__u8 page_code           : 6;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	__u8 page_code           : 6;
--	__u8 reserved1           : 1;
--	__u8 parameters_saveable : 1;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_BLK_DEV_UMC8672
+ extern int probe_umc8672;
+-extern int umc8672_init(void);
 -#endif
--
--	byte     page_length;
--
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 reserved2           : 2;
--	/* Drive supports reading of DVD-RAM discs */
--	__u8 dvd_ram_read        : 1;
--	/* Drive supports reading of DVD-R discs */
--	__u8 dvd_r_read          : 1;
--	/* Drive supports reading of DVD-ROM discs */
--	__u8 dvd_rom             : 1;
--	/* Drive supports reading CD-R discs with addressing method 2 */
--	__u8 method2             : 1; /* reserved in 1.2 */
--	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
--	__u8 cd_rw_read		 : 1; /* reserved in 1.2 */
--	/* Drive supports read from CD-R discs (orange book, part II) */
--	__u8 cd_r_read           : 1; /* reserved in 1.2 */
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	/* Drive supports read from CD-R discs (orange book, part II) */
--	__u8 cd_r_read           : 1; /* reserved in 1.2 */
--	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
--	__u8 cd_rw_read          : 1; /* reserved in 1.2 */
--	/* Drive supports reading CD-R discs with addressing method 2 */
--	__u8 method2             : 1;
--	/* Drive supports reading of DVD-ROM discs */
--	__u8 dvd_rom             : 1;
--	/* Drive supports reading of DVD-R discs */
--	__u8 dvd_r_read          : 1;
--	/* Drive supports reading of DVD-RAM discs */
--	__u8 dvd_ram_read        : 1;
--	__u8 reserved2		 : 2;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_BLK_DEV_DTC2278
+ extern int probe_dtc2278;
+-extern int dtc2278_init(void);
 -#endif
--
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 reserved3           : 2;
--	/* Drive can write DVD-RAM discs */
--	__u8 dvd_ram_write       : 1;
--	/* Drive can write DVD-R discs */
--	__u8 dvd_r_write         : 1;
--	__u8 reserved3a          : 1;
--	/* Drive can fake writes */
--	__u8 test_write          : 1;
--	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
--	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
--	/* Drive supports write to CD-R discs (orange book, part II) */
--	__u8 cd_r_write          : 1; /* reserved in 1.2 */
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	/* Drive can write to CD-R discs (orange book, part II) */
--	__u8 cd_r_write          : 1; /* reserved in 1.2 */
--	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
--	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
--	/* Drive can fake writes */
--	__u8 test_write          : 1;
--	__u8 reserved3a          : 1;
--	/* Drive can write DVD-R discs */
--	__u8 dvd_r_write         : 1;
--	/* Drive can write DVD-RAM discs */
--	__u8 dvd_ram_write       : 1;
--	__u8 reserved3           : 2;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_BLK_DEV_HT6560B
+ extern int probe_ht6560b;
+-extern int ht6560b_init(void);
 -#endif
+-#ifdef CONFIG_BLK_DEV_QD65XX
+ extern int probe_qd65xx;
+-extern int qd65xx_init(void);
+-#endif
++extern int cmd640_vlb;
+ 
+ static int __initdata is_chipset_set[MAX_HWIFS];
+ 
+@@ -1327,7 +1259,7 @@ static int __init ide_setup(char *s)
+ 	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
+ 		const char *hd_words[] = {
+ 			"none", "noprobe", "nowerr", "cdrom", "nodma",
+-			"autotune", "noautotune", "minus8", "swapdata", "bswap",
++			"autotune", "noautotune", "-8", "-9", "-10",
+ 			"noflush", "remap", "remap63", "scsi", NULL };
+ 		unit = s[2] - 'a';
+ 		hw   = unit / MAX_DRIVES;
+@@ -1363,10 +1295,6 @@ static int __init ide_setup(char *s)
+ 			case -7: /* "noautotune" */
+ 				drive->autotune = IDE_TUNE_NOAUTO;
+ 				goto obsolete_option;
+-			case -9: /* "swapdata" */
+-			case -10: /* "bswap" */
+-				drive->bswap = 1;
+-				goto done;
+ 			case -11: /* noflush */
+ 				drive->noflush = 1;
+ 				goto done;
+@@ -1466,11 +1394,8 @@ static int __init ide_setup(char *s)
+ #endif
+ #ifdef CONFIG_BLK_DEV_CMD640
+ 			case -14: /* "cmd640_vlb" */
+-			{
+-				extern int cmd640_vlb; /* flag for cmd640.c */
+ 				cmd640_vlb = 1;
+ 				goto done;
+-			}
+ #endif
+ #ifdef CONFIG_BLK_DEV_HT6560B
+ 			case -13: /* "ht6560b" */
+@@ -1560,79 +1485,6 @@ done:
+ 	return 1;
+ }
+ 
+-extern void __init pnpide_init(void);
+-extern void __exit pnpide_exit(void);
+-extern void __init h8300_ide_init(void);
 -
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 reserved4           : 1;
--	/* Drive can read multisession discs. */
--	__u8 multisession        : 1;
--	/* Drive can read mode 2, form 2 data. */
--	__u8 mode2_form2         : 1;
--	/* Drive can read mode 2, form 1 (XA) data. */
--	__u8 mode2_form1         : 1;
--	/* Drive supports digital output on port 2. */
--	__u8 digport2            : 1;
--	/* Drive supports digital output on port 1. */
--	__u8 digport1            : 1;
--	/* Drive can deliver a composite audio/video data stream. */
--	__u8 composite           : 1;
--	/* Drive supports audio play operations. */
--	__u8 audio_play          : 1;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	/* Drive supports audio play operations. */
--	__u8 audio_play          : 1;
--	/* Drive can deliver a composite audio/video data stream. */
--	__u8 composite           : 1;
--	/* Drive supports digital output on port 1. */
--	__u8 digport1            : 1;
--	/* Drive supports digital output on port 2. */
--	__u8 digport2            : 1;
--	/* Drive can read mode 2, form 1 (XA) data. */
--	__u8 mode2_form1         : 1;
--	/* Drive can read mode 2, form 2 data. */
--	__u8 mode2_form2         : 1;
--	/* Drive can read multisession discs. */
--	__u8 multisession        : 1;
--	__u8 reserved4           : 1;
--#else
--#error "Please fix <asm/byteorder.h>"
+-/*
+- * probe_for_hwifs() finds/initializes "known" IDE interfaces
+- */
+-static void __init probe_for_hwifs (void)
+-{
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-	ide_scan_pcibus(ide_scan_direction);
 -#endif
 -
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 reserved5           : 1;
--	/* Drive can return Media Catalog Number (UPC) info. */
--	__u8 upc                 : 1;
--	/* Drive can return International Standard Recording Code info. */
--	__u8 isrc                : 1;
--	/* Drive supports C2 error pointers. */
--	__u8 c2_pointers         : 1;
--	/* R-W data will be returned deinterleaved and error corrected. */
--	__u8 rw_corr             : 1;
--	/* Subchannel reads can return combined R-W information. */
--	__u8 rw_supported        : 1;
--	/* Drive can continue a read cdda operation from a loss of streaming.*/
--	__u8 cdda_accurate       : 1;
--	/* Drive can read Red Book audio data. */
--	__u8 cdda                : 1;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	/* Drive can read Red Book audio data. */
--	__u8 cdda                : 1;
--	/* Drive can continue a read cdda operation from a loss of streaming.*/
--	__u8 cdda_accurate       : 1;
--	/* Subchannel reads can return combined R-W information. */
--	__u8 rw_supported        : 1;
--	/* R-W data will be returned deinterleaved and error corrected. */
--	__u8 rw_corr             : 1;
--	/* Drive supports C2 error pointers. */
--	__u8 c2_pointers         : 1;
--	/* Drive can return International Standard Recording Code info. */
--	__u8 isrc                : 1;
--	/* Drive can return Media Catalog Number (UPC) info. */
--	__u8 upc                 : 1;
--	__u8 reserved5           : 1;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_ETRAX_IDE
+-	{
+-		extern void init_e100_ide(void);
+-		init_e100_ide();
+-	}
+-#endif /* CONFIG_ETRAX_IDE */
+-#ifdef CONFIG_BLK_DEV_CMD640
+-	{
+-		extern void ide_probe_for_cmd640x(void);
+-		ide_probe_for_cmd640x();
+-	}
+-#endif /* CONFIG_BLK_DEV_CMD640 */
+-#ifdef CONFIG_BLK_DEV_IDE_PMAC
+-	{
+-		extern int pmac_ide_probe(void);
+-		(void)pmac_ide_probe();
+-	}
+-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+-#ifdef CONFIG_BLK_DEV_GAYLE
+-	{
+-		extern void gayle_init(void);
+-		gayle_init();
+-	}
+-#endif /* CONFIG_BLK_DEV_GAYLE */
+-#ifdef CONFIG_BLK_DEV_FALCON_IDE
+-	{
+-		extern void falconide_init(void);
+-		falconide_init();
+-	}
+-#endif /* CONFIG_BLK_DEV_FALCON_IDE */
+-#ifdef CONFIG_BLK_DEV_MAC_IDE
+-	{
+-		extern void macide_init(void);
+-		macide_init();
+-	}
+-#endif /* CONFIG_BLK_DEV_MAC_IDE */
+-#ifdef CONFIG_BLK_DEV_Q40IDE
+-	{
+-		extern void q40ide_init(void);
+-		q40ide_init();
+-	}
+-#endif /* CONFIG_BLK_DEV_Q40IDE */
+-#ifdef CONFIG_BLK_DEV_BUDDHA
+-	{
+-		extern void buddha_init(void);
+-		buddha_init();
+-	}
+-#endif /* CONFIG_BLK_DEV_BUDDHA */
+-#ifdef CONFIG_BLK_DEV_IDEPNP
+-	pnpide_init();
 -#endif
--
--#if defined(__BIG_ENDIAN_BITFIELD)
--	/* Drive mechanism types. */
--	mechtype_t mechtype	 : 3;
--	__u8 reserved6           : 1;
--	/* Drive can eject a disc or changer cartridge. */
--	__u8 eject               : 1;
--	/* State of prevent/allow jumper. */
--	__u8 prevent_jumper      : 1;
--	/* Present state of door lock. */
--	__u8 lock_state          : 1;
--	/* Drive can lock the door. */
--	__u8 lock                : 1;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--
--	/* Drive can lock the door. */
--	__u8 lock                : 1;
--	/* Present state of door lock. */
--	__u8 lock_state          : 1;
--	/* State of prevent/allow jumper. */
--	__u8 prevent_jumper      : 1;
--	/* Drive can eject a disc or changer cartridge. */
--	__u8 eject               : 1;
--	__u8 reserved6           : 1;
--	/* Drive mechanism types. */
--	mechtype_t mechtype	 : 3;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_H8300
+-	h8300_ide_init();
 -#endif
+-}
 -
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 reserved7           : 4;
--	/* Drive supports software slot selection. */
--	__u8 sss                 : 1;  /* reserved in 1.2 */
--	/* Changer can report exact contents of slots. */
--	__u8 disc_present        : 1;  /* reserved in 1.2 */
--	/* Audio for each channel can be muted independently. */
--	__u8 separate_mute       : 1;
--	/* Audio level for each channel can be controlled independently. */
--	__u8 separate_volume     : 1;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
+-/*
+- * Probe module
+- */
 -
--	/* Audio level for each channel can be controlled independently. */
--	__u8 separate_volume     : 1;
--	/* Audio for each channel can be muted independently. */
--	__u8 separate_mute       : 1;
--	/* Changer can report exact contents of slots. */
--	__u8 disc_present        : 1;  /* reserved in 1.2 */
--	/* Drive supports software slot selection. */
--	__u8 sss                 : 1;  /* reserved in 1.2 */
--	__u8 reserved7           : 4;
--#else
--#error "Please fix <asm/byteorder.h>"
+ EXPORT_SYMBOL(ide_lock);
+ 
+ static int ide_bus_match(struct device *dev, struct device_driver *drv)
+@@ -1769,6 +1621,10 @@ static int __init ide_init(void)
+ 	printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
+ 	system_bus_speed = ide_system_bus_speed();
+ 
++	printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
++			 "for PIO modes%s\n", system_bus_speed,
++			idebus_parameter ? "" : "; override with idebus=xx");
++
+ 	ret = bus_register(&ide_bus_type);
+ 	if (ret < 0) {
+ 		printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
+@@ -1779,30 +1635,6 @@ static int __init ide_init(void)
+ 
+ 	proc_ide_create();
+ 
+-#ifdef CONFIG_BLK_DEV_ALI14XX
+-	if (probe_ali14xx)
+-		(void)ali14xx_init();
 -#endif
--
--	/* Note: the following four fields are returned in big-endian form. */
--	/* Maximum speed (in kB/s). */
--	unsigned short maxspeed;
--	/* Number of discrete volume levels. */
--	unsigned short n_vol_levels;
--	/* Size of cache in drive, in kB. */
--	unsigned short buffer_size;
--	/* Current speed (in kB/s). */
--	unsigned short curspeed;
--	char pad[4];
--};
--
--
--struct atapi_mechstat_header {
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 fault         : 1;
--	__u8 changer_state : 2;
--	__u8 curslot       : 5;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	__u8 curslot       : 5;
--	__u8 changer_state : 2;
--	__u8 fault         : 1;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_BLK_DEV_UMC8672
+-	if (probe_umc8672)
+-		(void)umc8672_init();
 -#endif
--
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 mech_state    : 3;
--	__u8 door_open     : 1;
--	__u8 reserved1     : 4;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	__u8 reserved1     : 4;
--	__u8 door_open     : 1;
--	__u8 mech_state    : 3;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_BLK_DEV_DTC2278
+-	if (probe_dtc2278)
+-		(void)dtc2278_init();
 -#endif
--
--	byte     curlba[3];
--	byte     nslots;
--	__u16	 slot_tablelen;
--};
--
--
--struct atapi_slot {
--#if defined(__BIG_ENDIAN_BITFIELD)
--	__u8 disc_present : 1;
--	__u8 reserved1    : 6;
--	__u8 change       : 1;
--#elif defined(__LITTLE_ENDIAN_BITFIELD)
--	__u8 change       : 1;
--	__u8 reserved1    : 6;
--	__u8 disc_present : 1;
--#else
--#error "Please fix <asm/byteorder.h>"
+-#ifdef CONFIG_BLK_DEV_HT6560B
+-	if (probe_ht6560b)
+-		(void)ht6560b_init();
+-#endif
+-#ifdef CONFIG_BLK_DEV_QD65XX
+-	if (probe_qd65xx)
+-		(void)qd65xx_init();
 -#endif
 -
--	byte reserved2[3];
--};
+-	/* Probe for special PCI and other "known" interface chipsets. */
+-	probe_for_hwifs();
 -
--struct atapi_changer_info {
--	struct atapi_mechstat_header hdr;
--	struct atapi_slot slots[0];
--};
+ 	return 0;
+ }
+ 
+@@ -1836,11 +1668,7 @@ void __exit cleanup_module (void)
+ 	int index;
+ 
+ 	for (index = 0; index < MAX_HWIFS; ++index)
+-		ide_unregister(index);
 -
- /* Extra per-device info for cdrom drives. */
- struct cdrom_info {
- 	ide_drive_t	*drive;
-@@ -483,11 +131,11 @@ struct cdrom_info {
- 	int dma;
- 	unsigned long last_block;
- 	unsigned long start_seek;
--	/* Buffer to hold mechanism status and changer slot table. */
--	struct atapi_changer_info *changer_info;
+-#ifdef CONFIG_BLK_DEV_IDEPNP
+-	pnpide_exit();
+-#endif
++		ide_unregister(index, 0, 0);
  
--	struct ide_cd_config_flags	config_flags;
--	struct ide_cd_state_flags	state_flags;
-+	unsigned int cd_flags;
+ 	proc_ide_destroy();
+ 
+diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
+index 4098223..7043ec7 100644
+--- a/drivers/ide/legacy/Makefile
++++ b/drivers/ide/legacy/Makefile
+@@ -1,15 +1,24 @@
+ 
++# link order is important here
 +
-+	u8 max_speed;		/* Max speed of the drive. */
-+	u8 current_speed;	/* Current speed of the drive. */
+ obj-$(CONFIG_BLK_DEV_ALI14XX)		+= ali14xx.o
++obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
+ obj-$(CONFIG_BLK_DEV_DTC2278)		+= dtc2278.o
+ obj-$(CONFIG_BLK_DEV_HT6560B)		+= ht6560b.o
+ obj-$(CONFIG_BLK_DEV_QD65XX)		+= qd65xx.o
+-obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
  
-         /* Per-device info needed by cdrom.c generic driver. */
-         struct cdrom_device_info devinfo;
-@@ -495,250 +143,30 @@ struct cdrom_info {
- 	unsigned long write_timeout;
- };
+-obj-$(CONFIG_BLK_DEV_IDECS)		+= ide-cs.o
++obj-$(CONFIG_BLK_DEV_GAYLE)		+= gayle.o
++obj-$(CONFIG_BLK_DEV_FALCON_IDE)	+= falconide.o
++obj-$(CONFIG_BLK_DEV_MAC_IDE)		+= macide.o
++obj-$(CONFIG_BLK_DEV_Q40IDE)		+= q40ide.o
++obj-$(CONFIG_BLK_DEV_BUDDHA)		+= buddha.o
  
--/****************************************************************************
-- * Descriptions of ATAPI error codes.
-- */
--
--/* This stuff should be in cdrom.h, since it is now generic... */
--
--/* ATAPI sense keys (from table 140 of ATAPI 2.6) */
--#define NO_SENSE                0x00
--#define RECOVERED_ERROR         0x01
--#define NOT_READY               0x02
--#define MEDIUM_ERROR            0x03
--#define HARDWARE_ERROR          0x04
--#define ILLEGAL_REQUEST         0x05
--#define UNIT_ATTENTION          0x06
--#define DATA_PROTECT            0x07
--#define BLANK_CHECK             0x08
--#define ABORTED_COMMAND         0x0b
--#define MISCOMPARE              0x0e
--
-- 
--
--/* This stuff should be in cdrom.h, since it is now generic... */
--#if VERBOSE_IDE_CD_ERRORS
--
-- /* The generic packet command opcodes for CD/DVD Logical Units,
-- * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ 
--static const struct {
--	unsigned short packet_command;
--	const char * const text;
--} packet_command_texts[] = {
--	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
--	{ GPCMD_REQUEST_SENSE, "Request Sense" },
--	{ GPCMD_FORMAT_UNIT, "Format Unit" },
--	{ GPCMD_INQUIRY, "Inquiry" },
--	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
--	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
--	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
--	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
--	{ GPCMD_READ_10, "Read 10" },
--	{ GPCMD_WRITE_10, "Write 10" },
--	{ GPCMD_SEEK, "Seek" },
--	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
--	{ GPCMD_VERIFY_10, "Verify 10" },
--	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
--	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
--	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
--	{ GPCMD_READ_HEADER, "Read Header" },
--	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
--	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
--	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
--	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
--	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION, "Get Event Status Notification" },
--	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
--	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
--	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
--	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
--	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
--	{ GPCMD_SEND_OPC, "Send OPC" },
--	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
--	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
--	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
--	{ GPCMD_CLOSE_TRACK, "Close Track" },
--	{ GPCMD_BLANK, "Blank" },
--	{ GPCMD_SEND_EVENT, "Send Event" },
--	{ GPCMD_SEND_KEY, "Send Key" },
--	{ GPCMD_REPORT_KEY, "Report Key" },
--	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
--	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
--	{ GPCMD_READ_12, "Read 12" },
--	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
--	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
--	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
--	{ GPCMD_SET_STREAMING, "Set Streaming" },
--	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
--	{ GPCMD_SCAN, "Scan" },
--	{ GPCMD_SET_SPEED, "Set Speed" },
--	{ GPCMD_PLAY_CD, "Play CD" },
--	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
--	{ GPCMD_READ_CD, "Read CD" },
--};
--
--
--
--/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
--static const char * const sense_key_texts[16] = {
--	"No sense data",
--	"Recovered error",
--	"Not ready",
--	"Medium error",
--	"Hardware error",
--	"Illegal request",
--	"Unit attention",
--	"Data protect",
--	"Blank check",
--	"(reserved)",
--	"(reserved)",
--	"Aborted command",
--	"(reserved)",
--	"(reserved)",
--	"Miscompare",
--	"(reserved)",
--};
--
--/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
--static const struct {
--	unsigned long asc_ascq;
--	const char * const text;
--} sense_data_texts[] = {
--	{ 0x000000, "No additional sense information" },
--	{ 0x000011, "Play operation in progress" },
--	{ 0x000012, "Play operation paused" },
--	{ 0x000013, "Play operation successfully completed" },
--	{ 0x000014, "Play operation stopped due to error" },
--	{ 0x000015, "No current audio status to return" },
--	{ 0x010c0a, "Write error - padding blocks added" },
--	{ 0x011700, "Recovered data with no error correction applied" },
--	{ 0x011701, "Recovered data with retries" },
--	{ 0x011702, "Recovered data with positive head offset" },
--	{ 0x011703, "Recovered data with negative head offset" },
--	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
--	{ 0x011705, "Recovered data using previous sector ID" },
--	{ 0x011800, "Recovered data with error correction applied" },
--	{ 0x011801, "Recovered data with error correction and retries applied"},
--	{ 0x011802, "Recovered data - the data was auto-reallocated" },
--	{ 0x011803, "Recovered data with CIRC" },
--	{ 0x011804, "Recovered data with L-EC" },
--	{ 0x015d00, 
--	    "Failure prediction threshold exceeded - Predicted logical unit failure" },
--	{ 0x015d01, 
--	    "Failure prediction threshold exceeded - Predicted media failure" },
--	{ 0x015dff, "Failure prediction threshold exceeded - False" },
--	{ 0x017301, "Power calibration area almost full" },
--	{ 0x020400, "Logical unit not ready - cause not reportable" },
--	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
--	{ 0x020401,
--	  "Logical unit not ready - in progress [sic] of becoming ready" },
--	{ 0x020402, "Logical unit not ready - initializing command required" },
--	{ 0x020403, "Logical unit not ready - manual intervention required" },
--	{ 0x020404, "Logical unit not ready - format in progress" },
--	{ 0x020407, "Logical unit not ready - operation in progress" },
--	{ 0x020408, "Logical unit not ready - long write in progress" },
--	{ 0x020600, "No reference position found (media may be upside down)" },
--	{ 0x023000, "Incompatible medium installed" },
--	{ 0x023a00, "Medium not present" },
--	{ 0x025300, "Media load or eject failed" },
--	{ 0x025700, "Unable to recover table of contents" },
--	{ 0x030300, "Peripheral device write fault" },
--	{ 0x030301, "No write current" },
--	{ 0x030302, "Excessive write errors" },
--	{ 0x030c00, "Write error" },
--	{ 0x030c01, "Write error - Recovered with auto reallocation" },
--	{ 0x030c02, "Write error - auto reallocation failed" },
--	{ 0x030c03, "Write error - recommend reassignment" },
--	{ 0x030c04, "Compression check miscompare error" },
--	{ 0x030c05, "Data expansion occurred during compress" },
--	{ 0x030c06, "Block not compressible" },
--	{ 0x030c07, "Write error - recovery needed" },
--	{ 0x030c08, "Write error - recovery failed" },
--	{ 0x030c09, "Write error - loss of streaming" },
--	{ 0x031100, "Unrecovered read error" },
--	{ 0x031106, "CIRC unrecovered error" },
--	{ 0x033101, "Format command failed" },
--	{ 0x033200, "No defect spare location available" },
--	{ 0x033201, "Defect list update failure" },
--	{ 0x035100, "Erase failure" },
--	{ 0x037200, "Session fixation error" },
--	{ 0x037201, "Session fixation error writin lead-in" },
--	{ 0x037202, "Session fixation error writin lead-out" },
--	{ 0x037300, "CD control error" },
--	{ 0x037302, "Power calibration area is full" },
--	{ 0x037303, "Power calibration area error" },
--	{ 0x037304, "Program memory area / RMA update failure" },
--	{ 0x037305, "Program memory area / RMA is full" },
--	{ 0x037306, "Program memory area / RMA is (almost) full" },
+-obj-$(CONFIG_BLK_DEV_PLATFORM)		+= ide_platform.o
++ifeq ($(CONFIG_BLK_DEV_IDECS), m)
++	obj-m += ide-cs.o
++endif
+ 
+-# Last of all
+-obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
++ifeq ($(CONFIG_BLK_DEV_PLATFORM), m)
++	obj-m += ide_platform.o
++endif
+ 
+ EXTRA_CFLAGS	:= -Idrivers/ide
+diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
+index 38c3a6d..d4d1a6b 100644
+--- a/drivers/ide/legacy/ali14xx.c
++++ b/drivers/ide/legacy/ali14xx.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/legacy/ali14xx.c		Version 0.03	Feb 09, 1996
+- *
+  *  Copyright (C) 1996  Linus Torvalds & author (see below)
+  */
+ 
+@@ -193,9 +191,14 @@ static int __init initRegisters (void) {
+ 	return t;
+ }
+ 
++static const struct ide_port_info ali14xx_port_info = {
++	.chipset		= ide_ali14xx,
++	.host_flags		= IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
++	.pio_mask		= ATA_PIO4,
++};
++
+ static int __init ali14xx_probe(void)
+ {
+-	ide_hwif_t *hwif, *mate;
+ 	static u8 idx[4] = { 0, 1, 0xff, 0xff };
+ 
+ 	printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
+@@ -207,21 +210,10 @@ static int __init ali14xx_probe(void)
+ 		return 1;
+ 	}
+ 
+-	hwif = &ide_hwifs[0];
+-	mate = &ide_hwifs[1];
 -
--	{ 0x040200, "No seek complete" },
--	{ 0x040300, "Write fault" },
--	{ 0x040900, "Track following error" },
--	{ 0x040901, "Tracking servo failure" },
--	{ 0x040902, "Focus servo failure" },
--	{ 0x040903, "Spindle servo failure" },
--	{ 0x041500, "Random positioning error" },
--	{ 0x041501, "Mechanical positioning or changer error" },
--	{ 0x041502, "Positioning error detected by read of medium" },
--	{ 0x043c00, "Mechanical positioning or changer error" },
--	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
--	{ 0x044400, "Internal CD/DVD logical unit failure" },
--	{ 0x04b600, "Media load mechanism failed" },
--	{ 0x051a00, "Parameter list length error" },
--	{ 0x052000, "Invalid command operation code" },
--	{ 0x052100, "Logical block address out of range" },
--	{ 0x052102, "Invalid address for write" },
--	{ 0x052400, "Invalid field in command packet" },
--	{ 0x052600, "Invalid field in parameter list" },
--	{ 0x052601, "Parameter not supported" },
--	{ 0x052602, "Parameter value invalid" },
--	{ 0x052700, "Write protected media" },
--	{ 0x052c00, "Command sequence error" },
--	{ 0x052c03, "Current program area is not empty" },
--	{ 0x052c04, "Current program area is empty" },
--	{ 0x053001, "Cannot read medium - unknown format" },
--	{ 0x053002, "Cannot read medium - incompatible format" },
--	{ 0x053900, "Saving parameters not supported" },
--	{ 0x054e00, "Overlapped commands attempted" },
--	{ 0x055302, "Medium removal prevented" },
--	{ 0x055500, "System resource failure" },
--	{ 0x056300, "End of user area encountered on this track" },
--	{ 0x056400, "Illegal mode for this track or incompatible medium" },
--	{ 0x056f00, "Copy protection key exchange failure - Authentication failure" },
--	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
--	{ 0x056f02, "Copy protection key exchange failure - Key not established" },
--	{ 0x056f03, "Read of scrambled sector without authentication" },
--	{ 0x056f04, "Media region code is mismatched to logical unit" },
--	{ 0x056f05,  "Drive region must be permanent / region reset count error" },
--	{ 0x057203, "Session fixation error - incomplete track in session" },
--	{ 0x057204, "Empty or partially written reserved track" },
--	{ 0x057205, "No more RZONE reservations are allowed" },
--	{ 0x05bf00, "Loss of streaming" },
--	{ 0x062800, "Not ready to ready transition, medium may have changed" },
--	{ 0x062900, "Power on, reset or hardware reset occurred" },
--	{ 0x062a00, "Parameters changed" },
--	{ 0x062a01, "Mode parameters changed" },
--	{ 0x062e00, "Insufficient time for operation" },
--	{ 0x063f00, "Logical unit operating conditions have changed" },
--	{ 0x063f01, "Microcode has been changed" },
--	{ 0x065a00, "Operator request or state change input (unspecified)" },
--	{ 0x065a01, "Operator medium removal request" },
--	{ 0x0bb900, "Play operation aborted" },
+-	hwif->chipset = ide_ali14xx;
+-	hwif->pio_mask = ATA_PIO4;
+-	hwif->set_pio_mode = &ali14xx_set_pio_mode;
+-	hwif->mate = mate;
 -
--	/* Here we use 0xff for the key (not a valid key) to signify
--	 * that these can have _any_ key value associated with them... */
--	{ 0xff0401, "Logical unit is in process of becoming ready" },
--	{ 0xff0400, "Logical unit not ready, cause not reportable" },
--	{ 0xff0402, "Logical unit not ready, initializing command required" },
--	{ 0xff0403, "Logical unit not ready, manual intervention required" },
--	{ 0xff0500, "Logical unit does not respond to selection" },
--	{ 0xff0800, "Logical unit communication failure" },
--	{ 0xff0802, "Logical unit communication parity error" },
--	{ 0xff0801, "Logical unit communication time-out" },
--	{ 0xff2500, "Logical unit not supported" },
--	{ 0xff4c00, "Logical unit failed self-configuration" },
--	{ 0xff3e00, "Logical unit has not self-configured yet" },
--};
+-	mate->chipset = ide_ali14xx;
+-	mate->pio_mask = ATA_PIO4;
+-	mate->set_pio_mode = &ali14xx_set_pio_mode;
+-	mate->mate = hwif;
+-	mate->channel = 1;
++	ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
++	ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
+ 
+-	ide_device_add(idx);
++	ide_device_add(idx, &ali14xx_port_info);
+ 
+ 	return 0;
+ }
+@@ -231,8 +223,7 @@ int probe_ali14xx = 0;
+ module_param_named(probe, probe_ali14xx, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
+ 
+-/* Can be called directly from ide.c. */
+-int __init ali14xx_init(void)
++static int __init ali14xx_init(void)
+ {
+ 	if (probe_ali14xx == 0)
+ 		goto out;
+@@ -248,9 +239,7 @@ out:
+ 	return -ENODEV;
+ }
+ 
+-#ifdef MODULE
+ module_init(ali14xx_init);
 -#endif
+ 
+ MODULE_AUTHOR("see local file");
+ MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
+diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
+index 4a0be25..50ffa87 100644
+--- a/drivers/ide/legacy/buddha.c
++++ b/drivers/ide/legacy/buddha.c
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
++ *  Amiga Buddha, Catweasel and X-Surf IDE Driver
+  *
+  *	Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
+  *
+@@ -56,31 +56,11 @@ static u_int xsurf_bases[XSURF_NUM_HWIFS] __initdata = {
+      XSURF_BASE1, XSURF_BASE2
+ };
+ 
 -
-+/* ide-cd_verbose.c */
-+void ide_cd_log_error(const char *, struct request *, struct request_sense *);
-+
-+/* ide-cd.c functions used by ide-cd_ioctl.c */
-+void ide_cd_init_rq(ide_drive_t *, struct request *);
-+int ide_cd_queue_pc(ide_drive_t *, struct request *);
-+int ide_cd_read_toc(ide_drive_t *, struct request_sense *);
-+int ide_cdrom_get_capabilities(ide_drive_t *, u8 *);
-+void ide_cdrom_update_speed(ide_drive_t *, u8 *);
-+int cdrom_check_status(ide_drive_t *, struct request_sense *);
-+
-+/* ide-cd_ioctl.c */
-+int ide_cdrom_open_real(struct cdrom_device_info *, int);
-+void ide_cdrom_release_real(struct cdrom_device_info *);
-+int ide_cdrom_drive_status(struct cdrom_device_info *, int);
-+int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
-+int ide_cdrom_tray_move(struct cdrom_device_info *, int);
-+int ide_cdrom_lock_door(struct cdrom_device_info *, int);
-+int ide_cdrom_select_speed(struct cdrom_device_info *, int);
-+int ide_cdrom_get_last_session(struct cdrom_device_info *,
-+			       struct cdrom_multisession *);
-+int ide_cdrom_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
-+int ide_cdrom_reset(struct cdrom_device_info *cdi);
-+int ide_cdrom_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
-+int ide_cdrom_packet(struct cdrom_device_info *, struct packet_command *);
+     /*
+      *  Offsets from one of the above bases
+      */
  
- #endif /* _IDE_CD_H */
-diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c
-new file mode 100644
-index 0000000..b68284d
---- /dev/null
-+++ b/drivers/ide/ide-cd_ioctl.c
-@@ -0,0 +1,475 @@
-+/*
-+ * cdrom.c IOCTLs handling for ide-cd driver.
-+ *
-+ * Copyright (C) 1994-1996  Scott Snyder <snyder at fnald0.fnal.gov>
-+ * Copyright (C) 1996-1998  Erik Andersen <andersee at debian.org>
-+ * Copyright (C) 1998-2000  Jens Axboe <axboe at suse.de>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/cdrom.h>
-+#include <linux/ide.h>
-+#include <scsi/scsi.h>
-+
-+#include "ide-cd.h"
-+
-+/****************************************************************************
-+ * Other driver requests (open, close, check media change).
-+ */
-+int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose)
-+{
-+	return 0;
-+}
-+
-+/*
-+ * Close down the device.  Invalidate all cached blocks.
-+ */
-+void ide_cdrom_release_real(struct cdrom_device_info *cdi)
-+{
-+	ide_drive_t *drive = cdi->handle;
-+	struct cdrom_info *cd = drive->driver_data;
-+
-+	if (!cdi->use_count)
-+		cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID;
-+}
-+
-+/*
-+ * add logic to try GET_EVENT command first to check for media and tray
-+ * status. this should be supported by newer cd-r/w and all DVD etc
-+ * drives
-+ */
-+int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+-#define BUDDHA_DATA	0x00
+-#define BUDDHA_ERROR	0x06		/* see err-bits */
+-#define BUDDHA_NSECTOR	0x0a		/* nr of sectors to read/write */
+-#define BUDDHA_SECTOR	0x0e		/* starting sector */
+-#define BUDDHA_LCYL	0x12		/* starting cylinder */
+-#define BUDDHA_HCYL	0x16		/* high byte of starting cyl */
+-#define BUDDHA_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+-#define BUDDHA_STATUS	0x1e		/* see status-bits */
+ #define BUDDHA_CONTROL	0x11a
+-#define XSURF_CONTROL   -1              /* X-Surf has no CS1* (Control/AltStat) */
+-
+-static int buddha_offsets[IDE_NR_PORTS] __initdata = {
+-    BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+-    BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL, -1
+-};
+-
+-static int xsurf_offsets[IDE_NR_PORTS] __initdata = {
+-    BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL,
+-    BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, XSURF_CONTROL, -1
+-};
+ 
+     /*
+      *  Other registers
+@@ -112,6 +92,7 @@ typedef enum BuddhaType_Enum {
+     BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
+ } BuddhaType;
+ 
++static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" };
+ 
+     /*
+      *  Check and acknowledge the interrupt status
+@@ -139,15 +120,35 @@ static int xsurf_ack_intr(ide_hwif_t *hwif)
+     return 1;
+ }
+ 
++static void __init buddha_setup_ports(hw_regs_t *hw, unsigned long base,
++				      unsigned long ctl, unsigned long irq_port,
++				      ide_ack_intr_t *ack_intr)
 +{
-+	ide_drive_t *drive = cdi->handle;
-+	struct media_event_desc med;
-+	struct request_sense sense;
-+	int stat;
-+
-+	if (slot_nr != CDSL_CURRENT)
-+		return -EINVAL;
-+
-+	stat = cdrom_check_status(drive, &sense);
-+	if (!stat || sense.sense_key == UNIT_ATTENTION)
-+		return CDS_DISC_OK;
++	int i;
 +
-+	if (!cdrom_get_media_event(cdi, &med)) {
-+		if (med.media_present)
-+			return CDS_DISC_OK;
-+		else if (med.door_open)
-+			return CDS_TRAY_OPEN;
-+		else
-+			return CDS_NO_DISC;
-+	}
++	memset(hw, 0, sizeof(*hw));
 +
-+	if (sense.sense_key == NOT_READY && sense.asc == 0x04
-+			&& sense.ascq == 0x04)
-+		return CDS_DISC_OK;
++	hw->io_ports[IDE_DATA_OFFSET] = base;
 +
-+	/*
-+	 * If not using Mt Fuji extended media tray reports,
-+	 * just return TRAY_OPEN since ATAPI doesn't provide
-+	 * any other way to detect this...
-+	 */
-+	if (sense.sense_key == NOT_READY) {
-+		if (sense.asc == 0x3a && sense.ascq == 1)
-+			return CDS_NO_DISC;
-+		else
-+			return CDS_TRAY_OPEN;
-+	}
-+	return CDS_DRIVE_NOT_READY;
-+}
++	for (i = 1; i < 8; i++)
++		hw->io_ports[i] = base + 2 + i * 4;
 +
-+int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
-+				       int slot_nr)
-+{
-+	ide_drive_t *drive = cdi->handle;
-+	struct cdrom_info *cd = drive->driver_data;
-+	int retval;
++	hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
++	hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
 +
-+	if (slot_nr == CDSL_CURRENT) {
-+		(void) cdrom_check_status(drive, NULL);
-+		retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0;
-+		cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED;
-+		return retval;
-+	} else {
-+		return -EINVAL;
-+	}
++	hw->irq = IRQ_AMIGA_PORTS;
++	hw->ack_intr = ack_intr;
 +}
 +
-+/* Eject the disk if EJECTFLAG is 0.
-+   If EJECTFLAG is 1, try to reload the disk. */
-+static
-+int cdrom_eject(ide_drive_t *drive, int ejectflag,
-+		struct request_sense *sense)
-+{
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct cdrom_device_info *cdi = &cd->devinfo;
-+	struct request req;
-+	char loej = 0x02;
-+
-+	if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag)
-+		return -EDRIVE_CANT_DO_THIS;
-+
-+	/* reload fails on some drives, if the tray is locked */
-+	if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag)
-+		return 0;
+     /*
+      *  Probe for a Buddha or Catweasel IDE interface
+      */
+ 
+-void __init buddha_init(void)
++static int __init buddha_init(void)
+ {
+ 	hw_regs_t hw;
+ 	ide_hwif_t *hwif;
+-	int i, index;
++	int i;
+ 
+ 	struct zorro_dev *z = NULL;
+ 	u_long buddha_board = 0;
+@@ -156,6 +157,8 @@ void __init buddha_init(void)
+ 
+ 	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
+ 		unsigned long board;
++		u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 +
-+	ide_cd_init_rq(drive, &req);
+ 		if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
+ 			buddha_num_hwifs = BUDDHA_NUM_HWIFS;
+ 			type=BOARD_BUDDHA;
+@@ -195,41 +198,46 @@ fail_base2:
+ 		/* X-Surf doesn't have this.  IRQs are always on */
+ 		if (type != BOARD_XSURF)
+ 			z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
+-		
+-		for(i=0;i<buddha_num_hwifs;i++) {
+-			if(type != BOARD_XSURF) {
+-				ide_setup_ports(&hw, (buddha_board+buddha_bases[i]),
+-						buddha_offsets, 0,
+-						(buddha_board+buddha_irqports[i]),
+-						buddha_ack_intr,
+-//						budda_iops,
+-						IRQ_AMIGA_PORTS);
 +
-+	/* only tell drive to close tray if open, if it can do that */
-+	if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY))
-+		loej = 0;
++		printk(KERN_INFO "ide: %s IDE controller\n",
++				 buddha_board_name[type]);
 +
-+	req.sense = sense;
-+	req.cmd[0] = GPCMD_START_STOP_UNIT;
-+	req.cmd[4] = loej | (ejectflag != 0);
++		for (i = 0; i < buddha_num_hwifs; i++) {
++			unsigned long base, ctl, irq_port;
++			ide_ack_intr_t *ack_intr;
++
++			if (type != BOARD_XSURF) {
++				base = buddha_board + buddha_bases[i];
++				ctl = base + BUDDHA_CONTROL;
++				irq_port = buddha_board + buddha_irqports[i];
++				ack_intr = buddha_ack_intr;
+ 			} else {
+-				ide_setup_ports(&hw, (buddha_board+xsurf_bases[i]),
+-						xsurf_offsets, 0,
+-						(buddha_board+xsurf_irqports[i]),
+-						xsurf_ack_intr,
+-//						xsurf_iops,
+-						IRQ_AMIGA_PORTS);
+-			}	
+-
+-			index = ide_register_hw(&hw, NULL, 1, &hwif);
+-			if (index != -1) {
++				base = buddha_board + xsurf_bases[i];
++				/* X-Surf has no CS1* (Control/AltStat) */
++				ctl = 0;
++				irq_port = buddha_board + xsurf_irqports[i];
++				ack_intr = xsurf_ack_intr;
++			}
 +
-+	return ide_cd_queue_pc(drive, &req);
-+}
++			buddha_setup_ports(&hw, base, ctl, irq_port, ack_intr);
 +
-+/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
-+static
-+int ide_cd_lockdoor(ide_drive_t *drive, int lockflag,
-+		    struct request_sense *sense)
-+{
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct request_sense my_sense;
-+	struct request req;
-+	int stat;
++			hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++			if (hwif) {
++				u8 index = hwif->index;
 +
-+	if (sense == NULL)
-+		sense = &my_sense;
++				ide_init_port_data(hwif, index);
++				ide_init_port_hw(hwif, &hw);
 +
-+	/* If the drive cannot lock the door, just pretend. */
-+	if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) {
-+		stat = 0;
-+	} else {
-+		ide_cd_init_rq(drive, &req);
-+		req.sense = sense;
-+		req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
-+		req.cmd[4] = lockflag ? 1 : 0;
-+		stat = ide_cd_queue_pc(drive, &req);
-+	}
+ 				hwif->mmio = 1;
+-				printk("ide%d: ", index);
+-				switch(type) {
+-				case BOARD_BUDDHA:
+-					printk("Buddha");
+-					break;
+-				case BOARD_CATWEASEL:
+-					printk("Catweasel");
+-					break;
+-				case BOARD_XSURF:
+-					printk("X-Surf");
+-					break;
+-				}
+-				printk(" IDE interface\n");	    
+-			}		      
 +
-+	/* If we got an illegal field error, the drive
-+	   probably cannot lock the door. */
-+	if (stat != 0 &&
-+	    sense->sense_key == ILLEGAL_REQUEST &&
-+	    (sense->asc == 0x24 || sense->asc == 0x20)) {
-+		printk(KERN_ERR "%s: door locking not supported\n",
-+			drive->name);
-+		cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK;
-+		stat = 0;
-+	}
++				idx[i] = index;
++			}
+ 		}
 +
-+	/* no medium, that's alright. */
-+	if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a)
-+		stat = 0;
++		ide_device_add(idx, NULL);
+ 	}
 +
-+	if (stat == 0) {
-+		if (lockflag)
-+			cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED;
-+		else
-+			cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED;
-+	}
++	return 0;
+ }
 +
-+	return stat;
-+}
++module_init(buddha_init);
+diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
+index 24a845d..73396f7 100644
+--- a/drivers/ide/legacy/dtc2278.c
++++ b/drivers/ide/legacy/dtc2278.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/legacy/dtc2278.c		Version 0.02	Feb 10, 1996
+- *
+  *  Copyright (C) 1996  Linus Torvalds & author (see below)
+  */
+ 
+@@ -86,14 +84,20 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 		/* Actually we do - there is a data sheet available for the
+ 		   Winbond but does anyone actually care */
+ 	}
+-
+-	/*
+-	 * 32bit I/O has to be enabled for *both* drives at the same time.
+-	 */
+-	drive->io_32bit = 1;
+-	HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
+ }
+ 
++static const struct ide_port_info dtc2278_port_info __initdata = {
++	.chipset		= ide_dtc2278,
++	.host_flags		= IDE_HFLAG_SERIALIZE |
++				  IDE_HFLAG_NO_UNMASK_IRQS |
++				  IDE_HFLAG_IO_32BIT |
++				  /* disallow ->io_32bit changes */
++				  IDE_HFLAG_NO_IO_32BIT |
++				  IDE_HFLAG_NO_DMA |
++				  IDE_HFLAG_NO_AUTOTUNE,
++	.pio_mask		= ATA_PIO4,
++};
 +
-+int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position)
+ static int __init dtc2278_probe(void)
+ {
+ 	unsigned long flags;
+@@ -124,23 +128,9 @@ static int __init dtc2278_probe(void)
+ #endif
+ 	local_irq_restore(flags);
+ 
+-	hwif->serialized = 1;
+-	hwif->chipset = ide_dtc2278;
+-	hwif->pio_mask = ATA_PIO4;
+ 	hwif->set_pio_mode = &dtc2278_set_pio_mode;
+-	hwif->drives[0].no_unmask = 1;
+-	hwif->drives[1].no_unmask = 1;
+-	hwif->mate = mate;
+-
+-	mate->serialized = 1;
+-	mate->chipset = ide_dtc2278;
+-	mate->pio_mask = ATA_PIO4;
+-	mate->drives[0].no_unmask = 1;
+-	mate->drives[1].no_unmask = 1;
+-	mate->mate = hwif;
+-	mate->channel = 1;
+ 
+-	ide_device_add(idx);
++	ide_device_add(idx, &dtc2278_port_info);
+ 
+ 	return 0;
+ }
+@@ -150,8 +140,7 @@ int probe_dtc2278 = 0;
+ module_param_named(probe, probe_dtc2278, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
+ 
+-/* Can be called directly from ide.c. */
+-int __init dtc2278_init(void)
++static int __init dtc2278_init(void)
+ {
+ 	if (probe_dtc2278 == 0)
+ 		return -ENODEV;
+@@ -163,9 +152,7 @@ int __init dtc2278_init(void)
+ 	return 0;
+ }
+ 
+-#ifdef MODULE
+ module_init(dtc2278_init);
+-#endif
+ 
+ MODULE_AUTHOR("See Local File");
+ MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
+diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
+index 7d7936f..f044048 100644
+--- a/drivers/ide/legacy/falconide.c
++++ b/drivers/ide/legacy/falconide.c
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver
++ *  Atari Falcon IDE Driver
+  *
+  *     Created 12 Jul 1997 by Geert Uytterhoeven
+  *
+@@ -33,22 +33,8 @@
+      *  Offsets from the above base
+      */
+ 
+-#define ATA_HD_DATA	0x00
+-#define ATA_HD_ERROR	0x05		/* see err-bits */
+-#define ATA_HD_NSECTOR	0x09		/* nr of sectors to read/write */
+-#define ATA_HD_SECTOR	0x0d		/* starting sector */
+-#define ATA_HD_LCYL	0x11		/* starting cylinder */
+-#define ATA_HD_HCYL	0x15		/* high byte of starting cyl */
+-#define ATA_HD_SELECT	0x19		/* 101dhhhh , d=drive, hhhh=head */
+-#define ATA_HD_STATUS	0x1d		/* see status-bits */
+ #define ATA_HD_CONTROL	0x39
+ 
+-static int falconide_offsets[IDE_NR_PORTS] __initdata = {
+-    ATA_HD_DATA, ATA_HD_ERROR, ATA_HD_NSECTOR, ATA_HD_SECTOR, ATA_HD_LCYL,
+-    ATA_HD_HCYL, ATA_HD_SELECT, ATA_HD_STATUS, ATA_HD_CONTROL, -1
+-};
+-
+-
+     /*
+      *  falconide_intr_lock is used to obtain access to the IDE interrupt,
+      *  which is shared between several drivers.
+@@ -57,24 +43,51 @@ static int falconide_offsets[IDE_NR_PORTS] __initdata = {
+ int falconide_intr_lock;
+ EXPORT_SYMBOL(falconide_intr_lock);
+ 
++static void __init falconide_setup_ports(hw_regs_t *hw)
 +{
-+	ide_drive_t *drive = cdi->handle;
-+	struct request_sense sense;
++	int i;
 +
-+	if (position) {
-+		int stat = ide_cd_lockdoor(drive, 0, &sense);
++	memset(hw, 0, sizeof(*hw));
 +
-+		if (stat)
-+			return stat;
-+	}
++	hw->io_ports[IDE_DATA_OFFSET] = ATA_HD_BASE;
 +
-+	return cdrom_eject(drive, !position, &sense);
-+}
++	for (i = 1; i < 8; i++)
++		hw->io_ports[i] = ATA_HD_BASE + 1 + i * 4;
 +
-+int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock)
-+{
-+	ide_drive_t *drive = cdi->handle;
++	hw->io_ports[IDE_CONTROL_OFFSET] = ATA_HD_CONTROL;
 +
-+	return ide_cd_lockdoor(drive, lock, NULL);
++	hw->irq = IRQ_MFP_IDE;
++	hw->ack_intr = NULL;
 +}
+ 
+     /*
+      *  Probe for a Falcon IDE interface
+      */
+ 
+-void __init falconide_init(void)
++static int __init falconide_init(void)
+ {
+-    if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
+ 	hw_regs_t hw;
+-	int index;
++	ide_hwif_t *hwif;
 +
-+/*
-+ * ATAPI devices are free to select the speed you request or any slower
-+ * rate. :-(  Requesting too fast a speed will _not_ produce an error.
-+ */
-+int ide_cdrom_select_speed(struct cdrom_device_info *cdi, int speed)
-+{
-+	ide_drive_t *drive = cdi->handle;
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct request rq;
-+	struct request_sense sense;
-+	u8 buf[ATAPI_CAPABILITIES_PAGE_SIZE];
-+	int stat;
-+
-+	ide_cd_init_rq(drive, &rq);
-+
-+	rq.sense = &sense;
-+
-+	if (speed == 0)
-+		speed = 0xffff; /* set to max */
-+	else
-+		speed *= 177;   /* Nx to kbytes/s */
-+
-+	rq.cmd[0] = GPCMD_SET_SPEED;
-+	/* Read Drive speed in kbytes/second MSB/LSB */
-+	rq.cmd[2] = (speed >> 8) & 0xff;
-+	rq.cmd[3] = speed & 0xff;
-+	if ((cdi->mask & (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) !=
-+	    (CDC_CD_R | CDC_CD_RW | CDC_DVD_R)) {
-+		/* Write Drive speed in kbytes/second MSB/LSB */
-+		rq.cmd[4] = (speed >> 8) & 0xff;
-+		rq.cmd[5] = speed & 0xff;
-+	}
-+
-+	stat = ide_cd_queue_pc(drive, &rq);
-+
-+	if (!ide_cdrom_get_capabilities(drive, buf)) {
-+		ide_cdrom_update_speed(drive, buf);
-+		cdi->speed = cd->current_speed;
-+	}
++	if (!MACH_IS_ATARI || !ATARIHW_PRESENT(IDE))
++		return 0;
 +
-+	return 0;
-+}
++	printk(KERN_INFO "ide: Falcon IDE controller\n");
 +
-+int ide_cdrom_get_last_session(struct cdrom_device_info *cdi,
-+			       struct cdrom_multisession *ms_info)
-+{
-+	struct atapi_toc *toc;
-+	ide_drive_t *drive = cdi->handle;
-+	struct cdrom_info *info = drive->driver_data;
-+	struct request_sense sense;
-+	int ret;
++	falconide_setup_ports(&hw);
+ 
+-	ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets,
+-			0, 0, NULL,
+-//			falconide_iops,
+-			IRQ_MFP_IDE);
+-	index = ide_register_hw(&hw, NULL, 1, NULL);
++	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif) {
++		u8 index = hwif->index;
++		u8 idx[4] = { index, 0xff, 0xff, 0xff };
+ 
+-	if (index != -1)
+-	    printk("ide%d: Falcon IDE interface\n", index);
+-    }
++		ide_init_port_data(hwif, index);
++		ide_init_port_hw(hwif, &hw);
 +
-+	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0 || !info->toc) {
-+		ret = ide_cd_read_toc(drive, &sense);
-+		if (ret)
-+			return ret;
++		ide_device_add(idx, NULL);
 +	}
 +
-+	toc = info->toc;
-+	ms_info->addr.lba = toc->last_session_lba;
-+	ms_info->xa_flag = toc->xa_flag;
-+
-+	return 0;
-+}
-+
-+int ide_cdrom_get_mcn(struct cdrom_device_info *cdi,
-+		      struct cdrom_mcn *mcn_info)
-+{
-+	ide_drive_t *drive = cdi->handle;
-+	int stat, mcnlen;
-+	struct request rq;
-+	char buf[24];
-+
-+	ide_cd_init_rq(drive, &rq);
-+
-+	rq.data = buf;
-+	rq.data_len = sizeof(buf);
-+
-+	rq.cmd[0] = GPCMD_READ_SUBCHANNEL;
-+	rq.cmd[1] = 2;		/* MSF addressing */
-+	rq.cmd[2] = 0x40;	/* request subQ data */
-+	rq.cmd[3] = 2;		/* format */
-+	rq.cmd[8] = sizeof(buf);
-+
-+	stat = ide_cd_queue_pc(drive, &rq);
-+	if (stat)
-+		return stat;
-+
-+	mcnlen = sizeof(mcn_info->medium_catalog_number) - 1;
-+	memcpy(mcn_info->medium_catalog_number, buf + 9, mcnlen);
-+	mcn_info->medium_catalog_number[mcnlen] = '\0';
-+
 +	return 0;
-+}
-+
-+int ide_cdrom_reset(struct cdrom_device_info *cdi)
-+{
-+	ide_drive_t *drive = cdi->handle;
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct request_sense sense;
-+	struct request req;
-+	int ret;
-+
-+	ide_cd_init_rq(drive, &req);
-+	req.cmd_type = REQ_TYPE_SPECIAL;
-+	req.cmd_flags = REQ_QUIET;
-+	ret = ide_do_drive_cmd(drive, &req, ide_wait);
-+
-+	/*
-+	 * A reset will unlock the door. If it was previously locked,
-+	 * lock it again.
-+	 */
-+	if (cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED)
-+		(void)ide_cd_lockdoor(drive, 1, &sense);
-+
-+	return ret;
-+}
+ }
 +
-+static int ide_cd_get_toc_entry(ide_drive_t *drive, int track,
-+				struct atapi_toc_entry **ent)
++module_init(falconide_init);
+diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
+index 53331ee..9d3851d 100644
+--- a/drivers/ide/legacy/gayle.c
++++ b/drivers/ide/legacy/gayle.c
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
++ *  Amiga Gayle IDE Driver
+  *
+  *     Created 9 Jul 1997 by Geert Uytterhoeven
+  *
+@@ -34,22 +34,8 @@
+      *  Offsets from one of the above bases
+      */
+ 
+-#define GAYLE_DATA	0x00
+-#define GAYLE_ERROR	0x06		/* see err-bits */
+-#define GAYLE_NSECTOR	0x0a		/* nr of sectors to read/write */
+-#define GAYLE_SECTOR	0x0e		/* starting sector */
+-#define GAYLE_LCYL	0x12		/* starting cylinder */
+-#define GAYLE_HCYL	0x16		/* high byte of starting cyl */
+-#define GAYLE_SELECT	0x1a		/* 101dhhhh , d=drive, hhhh=head */
+-#define GAYLE_STATUS	0x1e		/* see status-bits */
+ #define GAYLE_CONTROL	0x101a
+ 
+-static int gayle_offsets[IDE_NR_PORTS] __initdata = {
+-    GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL,
+-    GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1
+-};
+-
+-
+     /*
+      *  These are at different offsets from the base
+      */
+@@ -106,16 +92,37 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
+     return 1;
+ }
+ 
++static void __init gayle_setup_ports(hw_regs_t *hw, unsigned long base,
++				     unsigned long ctl, unsigned long irq_port,
++				     ide_ack_intr_t *ack_intr);
 +{
-+	struct cdrom_info *info = drive->driver_data;
-+	struct atapi_toc *toc = info->toc;
-+	int ntracks;
++	int i;
 +
-+	/*
-+	 * don't serve cached data, if the toc isn't valid
-+	 */
-+	if ((info->cd_flags & IDE_CD_FLAG_TOC_VALID) == 0)
-+		return -EINVAL;
++	memset(hw, 0, sizeof(*hw));
 +
-+	/* Check validity of requested track number. */
-+	ntracks = toc->hdr.last_track - toc->hdr.first_track + 1;
++	hw->io_ports[IDE_DATA_OFFSET] = base;
 +
-+	if (toc->hdr.first_track == CDROM_LEADOUT)
-+		ntracks = 0;
++	for (i = 1; i < 8; i++)
++		hw->io_ports[i] = base + 2 + i * 4;
 +
-+	if (track == CDROM_LEADOUT)
-+		*ent = &toc->ent[ntracks];
-+	else if (track < toc->hdr.first_track || track > toc->hdr.last_track)
-+		return -EINVAL;
-+	else
-+		*ent = &toc->ent[track - toc->hdr.first_track];
++	hw->io_ports[IDE_CONTROL_OFFSET] = ctl;
++	hw->io_ports[IDE_IRQ_OFFSET] = irq_port;
 +
-+	return 0;
++	hw->irq = IRQ_AMIGA_PORTS;
++	hw->ack_intr = ack_intr;
 +}
 +
-+static int ide_cd_fake_play_trkind(ide_drive_t *drive, void *arg)
-+{
-+	struct cdrom_ti *ti = arg;
-+	struct atapi_toc_entry *first_toc, *last_toc;
-+	unsigned long lba_start, lba_end;
-+	int stat;
-+	struct request rq;
-+	struct request_sense sense;
-+
-+	stat = ide_cd_get_toc_entry(drive, ti->cdti_trk0, &first_toc);
-+	if (stat)
-+		return stat;
-+
-+	stat = ide_cd_get_toc_entry(drive, ti->cdti_trk1, &last_toc);
-+	if (stat)
-+		return stat;
-+
-+	if (ti->cdti_trk1 != CDROM_LEADOUT)
-+		++last_toc;
-+	lba_start = first_toc->addr.lba;
-+	lba_end   = last_toc->addr.lba;
-+
-+	if (lba_end <= lba_start)
-+		return -EINVAL;
-+
-+	ide_cd_init_rq(drive, &rq);
+     /*
+      *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
+      */
+ 
+-void __init gayle_init(void)
++static int __init gayle_init(void)
+ {
+     int a4000, i;
++    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+     if (!MACH_IS_AMIGA)
+-	return;
++	return -ENODEV;
+ 
+     if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
+ 	goto found;
+@@ -125,15 +132,21 @@ void __init gayle_init(void)
+ 			  NULL))
+ 	goto found;
+ #endif
+-    return;
++    return -ENODEV;
+ 
+ found:
++	printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
++			 a4000 ? 4000 : 1200,
++#ifdef CONFIG_BLK_DEV_IDEDOUBLER
++			 ide_doubler ? ", IDE doubler" :
++#endif
++			 "");
 +
-+	rq.sense = &sense;
-+	rq.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
-+	lba_to_msf(lba_start,   &rq.cmd[3], &rq.cmd[4], &rq.cmd[5]);
-+	lba_to_msf(lba_end - 1, &rq.cmd[6], &rq.cmd[7], &rq.cmd[8]);
+     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
+ 	unsigned long base, ctrlport, irqport;
+ 	ide_ack_intr_t *ack_intr;
+ 	hw_regs_t hw;
+ 	ide_hwif_t *hwif;
+-	int index;
+ 	unsigned long phys_base, res_start, res_n;
+ 
+ 	if (a4000) {
+@@ -160,26 +173,25 @@ found:
+ 	base = (unsigned long)ZTWO_VADDR(phys_base);
+ 	ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
+ 
+-	ide_setup_ports(&hw, base, gayle_offsets,
+-			ctrlport, irqport, ack_intr,
+-//			&gayle_iops,
+-			IRQ_AMIGA_PORTS);
++	gayle_setup_ports(&hw, base, ctrlport, irqport, ack_intr);
 +
-+	return ide_cd_queue_pc(drive, &rq);
-+}
++	hwif = ide_find_port(base);
++	if (hwif) {
++	    u8 index = hwif->index;
 +
-+static int ide_cd_read_tochdr(ide_drive_t *drive, void *arg)
-+{
-+	struct cdrom_info *cd = drive->driver_data;
-+	struct cdrom_tochdr *tochdr = arg;
-+	struct atapi_toc *toc;
-+	int stat;
++	    ide_init_port_data(hwif, index);
++	    ide_init_port_hw(hwif, &hw);
+ 
+-	index = ide_register_hw(&hw, NULL, 1, &hwif);
+-	if (index != -1) {
+ 	    hwif->mmio = 1;
+-	    switch (i) {
+-		case 0:
+-		    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
+-			   a4000 ? 4000 : 1200);
+-		    break;
+-#ifdef CONFIG_BLK_DEV_IDEDOUBLER
+-		case 1:
+-		    printk("ide%d: IDE doubler\n", index);
+-		    break;
+-#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
+-	    }
 +
-+	/* Make sure our saved TOC is valid. */
-+	stat = ide_cd_read_toc(drive, NULL);
-+	if (stat)
-+		return stat;
++	    idx[i] = index;
+ 	} else
+ 	    release_mem_region(res_start, res_n);
+     }
 +
-+	toc = cd->toc;
-+	tochdr->cdth_trk0 = toc->hdr.first_track;
-+	tochdr->cdth_trk1 = toc->hdr.last_track;
++    ide_device_add(idx, NULL);
 +
-+	return 0;
-+}
++    return 0;
+ }
 +
-+static int ide_cd_read_tocentry(ide_drive_t *drive, void *arg)
-+{
-+	struct cdrom_tocentry *tocentry = arg;
-+	struct atapi_toc_entry *toce;
++module_init(gayle_init);
+diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
+index 8e05d88..0b0d867 100644
+--- a/drivers/ide/legacy/hd.c
++++ b/drivers/ide/legacy/hd.c
+@@ -421,11 +421,14 @@ static void bad_rw_intr(void)
+ 
+ static inline int wait_DRQ(void)
+ {
+-	int retries = 100000, stat;
++	int retries;
 +	int stat;
-+
-+	stat = ide_cd_get_toc_entry(drive, tocentry->cdte_track, &toce);
-+	if (stat)
-+		return stat;
-+
-+	tocentry->cdte_ctrl = toce->control;
-+	tocentry->cdte_adr  = toce->adr;
-+	if (tocentry->cdte_format == CDROM_MSF) {
-+		lba_to_msf(toce->addr.lba,
-+			   &tocentry->cdte_addr.msf.minute,
-+			   &tocentry->cdte_addr.msf.second,
-+			   &tocentry->cdte_addr.msf.frame);
-+	} else
-+		tocentry->cdte_addr.lba = toce->addr.lba;
-+
-+	return 0;
-+}
-+
-+int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi,
-+			  unsigned int cmd, void *arg)
-+{
-+	ide_drive_t *drive = cdi->handle;
-+
-+	switch (cmd) {
-+	/*
-+	 * emulate PLAY_AUDIO_TI command with PLAY_AUDIO_10, since
-+	 * atapi doesn't support it
-+	 */
-+	case CDROMPLAYTRKIND:
-+		return ide_cd_fake_play_trkind(drive, arg);
-+	case CDROMREADTOCHDR:
-+		return ide_cd_read_tochdr(drive, arg);
-+	case CDROMREADTOCENTRY:
-+		return ide_cd_read_tocentry(drive, arg);
-+	default:
-+		return -EINVAL;
+ 
+-	while (--retries > 0)
+-		if ((stat = inb_p(HD_STATUS)) & DRQ_STAT)
++	for (retries = 0; retries < 100000; retries++) {
++		stat = inb_p(HD_STATUS);
++		if (stat & DRQ_STAT)
+ 			return 0;
 +	}
-+}
-+
-+/* the generic packet interface to cdrom.c */
-+int ide_cdrom_packet(struct cdrom_device_info *cdi,
-+			    struct packet_command *cgc)
+ 	dump_status("wait_DRQ", stat);
+ 	return -1;
+ }
+diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
+index a4245d1..02d12c7 100644
+--- a/drivers/ide/legacy/ht6560b.c
++++ b/drivers/ide/legacy/ht6560b.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/legacy/ht6560b.c		Version 0.07	Feb  1, 2000
+- *
+  *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
+  */
+ 
+@@ -302,17 +300,36 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ #endif
+ }
+ 
++static void __init ht6560b_port_init_devs(ide_hwif_t *hwif)
 +{
-+	struct request req;
-+	ide_drive_t *drive = cdi->handle;
-+
-+	if (cgc->timeout <= 0)
-+		cgc->timeout = ATAPI_WAIT_PC;
-+
-+	/* here we queue the commands from the uniform CD-ROM
-+	   layer. the packet must be complete, as we do not
-+	   touch it at all. */
-+	ide_cd_init_rq(drive, &req);
-+	memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE);
-+	if (cgc->sense)
-+		memset(cgc->sense, 0, sizeof(struct request_sense));
-+	req.data = cgc->buffer;
-+	req.data_len = cgc->buflen;
-+	req.timeout = cgc->timeout;
-+
-+	if (cgc->quiet)
-+		req.cmd_flags |= REQ_QUIET;
-+
-+	req.sense = cgc->sense;
-+	cgc->stat = ide_cd_queue_pc(drive, &req);
-+	if (!cgc->stat)
-+		cgc->buflen -= req.data_len;
-+	return cgc->stat;
-+}
-diff --git a/drivers/ide/ide-cd_verbose.c b/drivers/ide/ide-cd_verbose.c
-new file mode 100644
-index 0000000..6ed7ca0
---- /dev/null
-+++ b/drivers/ide/ide-cd_verbose.c
-@@ -0,0 +1,359 @@
-+/*
-+ * Verbose error logging for ATAPI CD/DVD devices.
-+ *
-+ * Copyright (C) 1994-1996  Scott Snyder <snyder at fnald0.fnal.gov>
-+ * Copyright (C) 1996-1998  Erik Andersen <andersee at debian.org>
-+ * Copyright (C) 1998-2000  Jens Axboe <axboe at suse.de>
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/blkdev.h>
-+#include <linux/cdrom.h>
-+#include <scsi/scsi.h>
++	/* Setting default configurations for drives. */
++	int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
 +
-+#ifndef CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS
-+void ide_cd_log_error(const char *name, struct request *failed_command,
-+		      struct request_sense *sense)
-+{
-+	/* Suppress printing unit attention and `in progress of becoming ready'
-+	   errors when we're not being verbose. */
-+	if (sense->sense_key == UNIT_ATTENTION ||
-+	    (sense->sense_key == NOT_READY && (sense->asc == 4 ||
-+						sense->asc == 0x3a)))
-+		return;
++	if (hwif->channel)
++		t |= (HT_SECONDARY_IF << 8);
 +
-+	printk(KERN_ERR "%s: error code: 0x%02x  sense_key: 0x%02x  "
-+			"asc: 0x%02x  ascq: 0x%02x\n",
-+			name, sense->error_code, sense->sense_key,
-+			sense->asc, sense->ascq);
++	hwif->drives[0].drive_data = t;
++	hwif->drives[1].drive_data = t;
 +}
-+#else
-+/* The generic packet command opcodes for CD/DVD Logical Units,
-+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-+static const struct {
-+	unsigned short packet_command;
-+	const char * const text;
-+} packet_command_texts[] = {
-+	{ GPCMD_TEST_UNIT_READY, "Test Unit Ready" },
-+	{ GPCMD_REQUEST_SENSE, "Request Sense" },
-+	{ GPCMD_FORMAT_UNIT, "Format Unit" },
-+	{ GPCMD_INQUIRY, "Inquiry" },
-+	{ GPCMD_START_STOP_UNIT, "Start/Stop Unit" },
-+	{ GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL, "Prevent/Allow Medium Removal" },
-+	{ GPCMD_READ_FORMAT_CAPACITIES, "Read Format Capacities" },
-+	{ GPCMD_READ_CDVD_CAPACITY, "Read Cd/Dvd Capacity" },
-+	{ GPCMD_READ_10, "Read 10" },
-+	{ GPCMD_WRITE_10, "Write 10" },
-+	{ GPCMD_SEEK, "Seek" },
-+	{ GPCMD_WRITE_AND_VERIFY_10, "Write and Verify 10" },
-+	{ GPCMD_VERIFY_10, "Verify 10" },
-+	{ GPCMD_FLUSH_CACHE, "Flush Cache" },
-+	{ GPCMD_READ_SUBCHANNEL, "Read Subchannel" },
-+	{ GPCMD_READ_TOC_PMA_ATIP, "Read Table of Contents" },
-+	{ GPCMD_READ_HEADER, "Read Header" },
-+	{ GPCMD_PLAY_AUDIO_10, "Play Audio 10" },
-+	{ GPCMD_GET_CONFIGURATION, "Get Configuration" },
-+	{ GPCMD_PLAY_AUDIO_MSF, "Play Audio MSF" },
-+	{ GPCMD_PLAYAUDIO_TI, "Play Audio TrackIndex" },
-+	{ GPCMD_GET_EVENT_STATUS_NOTIFICATION,
-+		"Get Event Status Notification" },
-+	{ GPCMD_PAUSE_RESUME, "Pause/Resume" },
-+	{ GPCMD_STOP_PLAY_SCAN, "Stop Play/Scan" },
-+	{ GPCMD_READ_DISC_INFO, "Read Disc Info" },
-+	{ GPCMD_READ_TRACK_RZONE_INFO, "Read Track Rzone Info" },
-+	{ GPCMD_RESERVE_RZONE_TRACK, "Reserve Rzone Track" },
-+	{ GPCMD_SEND_OPC, "Send OPC" },
-+	{ GPCMD_MODE_SELECT_10, "Mode Select 10" },
-+	{ GPCMD_REPAIR_RZONE_TRACK, "Repair Rzone Track" },
-+	{ GPCMD_MODE_SENSE_10, "Mode Sense 10" },
-+	{ GPCMD_CLOSE_TRACK, "Close Track" },
-+	{ GPCMD_BLANK, "Blank" },
-+	{ GPCMD_SEND_EVENT, "Send Event" },
-+	{ GPCMD_SEND_KEY, "Send Key" },
-+	{ GPCMD_REPORT_KEY, "Report Key" },
-+	{ GPCMD_LOAD_UNLOAD, "Load/Unload" },
-+	{ GPCMD_SET_READ_AHEAD, "Set Read-ahead" },
-+	{ GPCMD_READ_12, "Read 12" },
-+	{ GPCMD_GET_PERFORMANCE, "Get Performance" },
-+	{ GPCMD_SEND_DVD_STRUCTURE, "Send DVD Structure" },
-+	{ GPCMD_READ_DVD_STRUCTURE, "Read DVD Structure" },
-+	{ GPCMD_SET_STREAMING, "Set Streaming" },
-+	{ GPCMD_READ_CD_MSF, "Read CD MSF" },
-+	{ GPCMD_SCAN, "Scan" },
-+	{ GPCMD_SET_SPEED, "Set Speed" },
-+	{ GPCMD_PLAY_CD, "Play CD" },
-+	{ GPCMD_MECHANISM_STATUS, "Mechanism Status" },
-+	{ GPCMD_READ_CD, "Read CD" },
-+};
-+
-+/* From Table 303 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-+static const char * const sense_key_texts[16] = {
-+	"No sense data",
-+	"Recovered error",
-+	"Not ready",
-+	"Medium error",
-+	"Hardware error",
-+	"Illegal request",
-+	"Unit attention",
-+	"Data protect",
-+	"Blank check",
-+	"(reserved)",
-+	"(reserved)",
-+	"Aborted command",
-+	"(reserved)",
-+	"(reserved)",
-+	"Miscompare",
-+	"(reserved)",
-+};
 +
-+/* From Table 304 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
-+static const struct {
-+	unsigned long asc_ascq;
-+	const char * const text;
-+} sense_data_texts[] = {
-+	{ 0x000000, "No additional sense information" },
-+	{ 0x000011, "Play operation in progress" },
-+	{ 0x000012, "Play operation paused" },
-+	{ 0x000013, "Play operation successfully completed" },
-+	{ 0x000014, "Play operation stopped due to error" },
-+	{ 0x000015, "No current audio status to return" },
-+	{ 0x010c0a, "Write error - padding blocks added" },
-+	{ 0x011700, "Recovered data with no error correction applied" },
-+	{ 0x011701, "Recovered data with retries" },
-+	{ 0x011702, "Recovered data with positive head offset" },
-+	{ 0x011703, "Recovered data with negative head offset" },
-+	{ 0x011704, "Recovered data with retries and/or CIRC applied" },
-+	{ 0x011705, "Recovered data using previous sector ID" },
-+	{ 0x011800, "Recovered data with error correction applied" },
-+	{ 0x011801, "Recovered data with error correction and retries applied"},
-+	{ 0x011802, "Recovered data - the data was auto-reallocated" },
-+	{ 0x011803, "Recovered data with CIRC" },
-+	{ 0x011804, "Recovered data with L-EC" },
-+	{ 0x015d00, "Failure prediction threshold exceeded"
-+		    " - Predicted logical unit failure" },
-+	{ 0x015d01, "Failure prediction threshold exceeded"
-+		    " - Predicted media failure" },
-+	{ 0x015dff, "Failure prediction threshold exceeded - False" },
-+	{ 0x017301, "Power calibration area almost full" },
-+	{ 0x020400, "Logical unit not ready - cause not reportable" },
-+	/* Following is misspelled in ATAPI 2.6, _and_ in Mt. Fuji */
-+	{ 0x020401, "Logical unit not ready"
-+		    " - in progress [sic] of becoming ready" },
-+	{ 0x020402, "Logical unit not ready - initializing command required" },
-+	{ 0x020403, "Logical unit not ready - manual intervention required" },
-+	{ 0x020404, "Logical unit not ready - format in progress" },
-+	{ 0x020407, "Logical unit not ready - operation in progress" },
-+	{ 0x020408, "Logical unit not ready - long write in progress" },
-+	{ 0x020600, "No reference position found (media may be upside down)" },
-+	{ 0x023000, "Incompatible medium installed" },
-+	{ 0x023a00, "Medium not present" },
-+	{ 0x025300, "Media load or eject failed" },
-+	{ 0x025700, "Unable to recover table of contents" },
-+	{ 0x030300, "Peripheral device write fault" },
-+	{ 0x030301, "No write current" },
-+	{ 0x030302, "Excessive write errors" },
-+	{ 0x030c00, "Write error" },
-+	{ 0x030c01, "Write error - Recovered with auto reallocation" },
-+	{ 0x030c02, "Write error - auto reallocation failed" },
-+	{ 0x030c03, "Write error - recommend reassignment" },
-+	{ 0x030c04, "Compression check miscompare error" },
-+	{ 0x030c05, "Data expansion occurred during compress" },
-+	{ 0x030c06, "Block not compressible" },
-+	{ 0x030c07, "Write error - recovery needed" },
-+	{ 0x030c08, "Write error - recovery failed" },
-+	{ 0x030c09, "Write error - loss of streaming" },
-+	{ 0x031100, "Unrecovered read error" },
-+	{ 0x031106, "CIRC unrecovered error" },
-+	{ 0x033101, "Format command failed" },
-+	{ 0x033200, "No defect spare location available" },
-+	{ 0x033201, "Defect list update failure" },
-+	{ 0x035100, "Erase failure" },
-+	{ 0x037200, "Session fixation error" },
-+	{ 0x037201, "Session fixation error writin lead-in" },
-+	{ 0x037202, "Session fixation error writin lead-out" },
-+	{ 0x037300, "CD control error" },
-+	{ 0x037302, "Power calibration area is full" },
-+	{ 0x037303, "Power calibration area error" },
-+	{ 0x037304, "Program memory area / RMA update failure" },
-+	{ 0x037305, "Program memory area / RMA is full" },
-+	{ 0x037306, "Program memory area / RMA is (almost) full" },
-+	{ 0x040200, "No seek complete" },
-+	{ 0x040300, "Write fault" },
-+	{ 0x040900, "Track following error" },
-+	{ 0x040901, "Tracking servo failure" },
-+	{ 0x040902, "Focus servo failure" },
-+	{ 0x040903, "Spindle servo failure" },
-+	{ 0x041500, "Random positioning error" },
-+	{ 0x041501, "Mechanical positioning or changer error" },
-+	{ 0x041502, "Positioning error detected by read of medium" },
-+	{ 0x043c00, "Mechanical positioning or changer error" },
-+	{ 0x044000, "Diagnostic failure on component (ASCQ)" },
-+	{ 0x044400, "Internal CD/DVD logical unit failure" },
-+	{ 0x04b600, "Media load mechanism failed" },
-+	{ 0x051a00, "Parameter list length error" },
-+	{ 0x052000, "Invalid command operation code" },
-+	{ 0x052100, "Logical block address out of range" },
-+	{ 0x052102, "Invalid address for write" },
-+	{ 0x052400, "Invalid field in command packet" },
-+	{ 0x052600, "Invalid field in parameter list" },
-+	{ 0x052601, "Parameter not supported" },
-+	{ 0x052602, "Parameter value invalid" },
-+	{ 0x052700, "Write protected media" },
-+	{ 0x052c00, "Command sequence error" },
-+	{ 0x052c03, "Current program area is not empty" },
-+	{ 0x052c04, "Current program area is empty" },
-+	{ 0x053001, "Cannot read medium - unknown format" },
-+	{ 0x053002, "Cannot read medium - incompatible format" },
-+	{ 0x053900, "Saving parameters not supported" },
-+	{ 0x054e00, "Overlapped commands attempted" },
-+	{ 0x055302, "Medium removal prevented" },
-+	{ 0x055500, "System resource failure" },
-+	{ 0x056300, "End of user area encountered on this track" },
-+	{ 0x056400, "Illegal mode for this track or incompatible medium" },
-+	{ 0x056f00, "Copy protection key exchange failure"
-+		    " - Authentication failure" },
-+	{ 0x056f01, "Copy protection key exchange failure - Key not present" },
-+	{ 0x056f02, "Copy protection key exchange failure"
-+		     " - Key not established" },
-+	{ 0x056f03, "Read of scrambled sector without authentication" },
-+	{ 0x056f04, "Media region code is mismatched to logical unit" },
-+	{ 0x056f05, "Drive region must be permanent"
-+		    " / region reset count error" },
-+	{ 0x057203, "Session fixation error - incomplete track in session" },
-+	{ 0x057204, "Empty or partially written reserved track" },
-+	{ 0x057205, "No more RZONE reservations are allowed" },
-+	{ 0x05bf00, "Loss of streaming" },
-+	{ 0x062800, "Not ready to ready transition, medium may have changed" },
-+	{ 0x062900, "Power on, reset or hardware reset occurred" },
-+	{ 0x062a00, "Parameters changed" },
-+	{ 0x062a01, "Mode parameters changed" },
-+	{ 0x062e00, "Insufficient time for operation" },
-+	{ 0x063f00, "Logical unit operating conditions have changed" },
-+	{ 0x063f01, "Microcode has been changed" },
-+	{ 0x065a00, "Operator request or state change input (unspecified)" },
-+	{ 0x065a01, "Operator medium removal request" },
-+	{ 0x0bb900, "Play operation aborted" },
-+	/* Here we use 0xff for the key (not a valid key) to signify
-+	 * that these can have _any_ key value associated with them... */
-+	{ 0xff0401, "Logical unit is in process of becoming ready" },
-+	{ 0xff0400, "Logical unit not ready, cause not reportable" },
-+	{ 0xff0402, "Logical unit not ready, initializing command required" },
-+	{ 0xff0403, "Logical unit not ready, manual intervention required" },
-+	{ 0xff0500, "Logical unit does not respond to selection" },
-+	{ 0xff0800, "Logical unit communication failure" },
-+	{ 0xff0802, "Logical unit communication parity error" },
-+	{ 0xff0801, "Logical unit communication time-out" },
-+	{ 0xff2500, "Logical unit not supported" },
-+	{ 0xff4c00, "Logical unit failed self-configuration" },
-+	{ 0xff3e00, "Logical unit has not self-configured yet" },
+ int probe_ht6560b = 0;
+ 
+ module_param_named(probe, probe_ht6560b, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
+ 
+-/* Can be called directly from ide.c. */
+-int __init ht6560b_init(void)
++static const struct ide_port_info ht6560b_port_info __initdata = {
++	.chipset		= ide_ht6560b,
++	.host_flags		= IDE_HFLAG_SERIALIZE | /* is this needed? */
++				  IDE_HFLAG_NO_DMA |
++				  IDE_HFLAG_NO_AUTOTUNE |
++				  IDE_HFLAG_ABUSE_PREFETCH,
++	.pio_mask		= ATA_PIO5,
 +};
 +
-+void ide_cd_log_error(const char *name, struct request *failed_command,
-+		      struct request_sense *sense)
-+{
-+	int i;
-+	const char *s = "bad sense key!";
-+	char buf[80];
-+
-+	printk(KERN_ERR "ATAPI device %s:\n", name);
-+	if (sense->error_code == 0x70)
-+		printk(KERN_CONT "  Error: ");
-+	else if (sense->error_code == 0x71)
-+		printk("  Deferred Error: ");
-+	else if (sense->error_code == 0x7f)
-+		printk(KERN_CONT "  Vendor-specific Error: ");
-+	else
-+		printk(KERN_CONT "  Unknown Error Type: ");
-+
-+	if (sense->sense_key < ARRAY_SIZE(sense_key_texts))
-+		s = sense_key_texts[sense->sense_key];
-+
-+	printk(KERN_CONT "%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
-+
-+	if (sense->asc == 0x40) {
-+		sprintf(buf, "Diagnostic failure on component 0x%02x",
-+			sense->ascq);
-+		s = buf;
-+	} else {
-+		int lo = 0, mid, hi = ARRAY_SIZE(sense_data_texts);
-+		unsigned long key = (sense->sense_key << 16);
-+
-+		key |= (sense->asc << 8);
-+		if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
-+			key |= sense->ascq;
-+		s = NULL;
-+
-+		while (hi > lo) {
-+			mid = (lo + hi) / 2;
-+			if (sense_data_texts[mid].asc_ascq == key ||
-+			    sense_data_texts[mid].asc_ascq == (0xff0000|key)) {
-+				s = sense_data_texts[mid].text;
-+				break;
-+			} else if (sense_data_texts[mid].asc_ascq > key)
-+				hi = mid;
-+			else
-+				lo = mid + 1;
-+		}
-+	}
-+
-+	if (s == NULL) {
-+		if (sense->asc > 0x80)
-+			s = "(vendor-specific error)";
-+		else
-+			s = "(reserved error code)";
-+	}
-+
-+	printk(KERN_ERR "  %s -- (asc=0x%02x, ascq=0x%02x)\n",
-+			s, sense->asc, sense->ascq);
-+
-+	if (failed_command != NULL) {
-+		int lo = 0, mid, hi = ARRAY_SIZE(packet_command_texts);
-+		s = NULL;
-+
-+		while (hi > lo) {
-+			mid = (lo + hi) / 2;
-+			if (packet_command_texts[mid].packet_command ==
-+			    failed_command->cmd[0]) {
-+				s = packet_command_texts[mid].text;
-+				break;
-+			}
-+			if (packet_command_texts[mid].packet_command >
-+			    failed_command->cmd[0])
-+				hi = mid;
-+			else
-+				lo = mid + 1;
-+		}
-+
-+		printk(KERN_ERR "  The failed \"%s\" packet command "
-+				"was: \n  \"", s);
-+		for (i = 0; i < sizeof(failed_command->cmd); i++)
-+			printk(KERN_CONT "%02x ", failed_command->cmd[i]);
-+		printk(KERN_CONT "\"\n");
-+	}
-+
-+	/* The SKSV bit specifies validity of the sense_key_specific
-+	 * in the next two commands. It is bit 7 of the first byte.
-+	 * In the case of NOT_READY, if SKSV is set the drive can
-+	 * give us nice ETA readings.
-+	 */
-+	if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
-+		int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
-+
-+		printk(KERN_ERR "  Command is %02d%% complete\n",
-+				progress / 0xffff);
-+	}
-+
-+	if (sense->sense_key == ILLEGAL_REQUEST &&
-+	    (sense->sks[0] & 0x80) != 0) {
-+		printk(KERN_ERR "  Error in %s byte %d",
-+				(sense->sks[0] & 0x40) != 0 ?
-+				"command packet" : "command data",
-+				(sense->sks[1] << 8) + sense->sks[2]);
-+
-+		if ((sense->sks[0] & 0x40) != 0)
-+			printk(KERN_CONT " bit %d", sense->sks[0] & 0x07);
-+
-+		printk(KERN_CONT "\n");
-+	}
-+}
-+#endif
-diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
-index b178190..3c69822 100644
---- a/drivers/ide/ide-disk.c
-+++ b/drivers/ide/ide-disk.c
-@@ -1,10 +1,9 @@
- /*
-- *  linux/drivers/ide/ide-disk.c	Version 1.18	Mar 05, 2003
-- *
-- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
-- *  Copyright (C) 1998-2002  Linux ATA Development
-- *				Andre Hedrick <andre at linux-ide.org>
-- *  Copyright (C) 2003	     Red Hat <alan at redhat.com>
-+ *  Copyright (C) 1994-1998	   Linus Torvalds & authors (see below)
-+ *  Copyright (C) 1998-2002	   Linux ATA Development
-+ *				      Andre Hedrick <andre at linux-ide.org>
-+ *  Copyright (C) 2003		   Red Hat <alan at redhat.com>
-+ *  Copyright (C) 2003-2005, 2007  Bartlomiej Zolnierkiewicz
-  */
++static int __init ht6560b_init(void)
+ {
+ 	ide_hwif_t *hwif, *mate;
+ 	static u8 idx[4] = { 0, 1, 0xff, 0xff };
+-	int t;
  
- /*
-@@ -129,6 +128,50 @@ static int lba_capacity_is_ok (struct hd_driveid *id)
- 	return 0;	/* lba_capacity value may be bad */
+ 	if (probe_ht6560b == 0)
+ 		return -ENODEV;
+@@ -331,36 +348,16 @@ int __init ht6560b_init(void)
+ 		goto release_region;
+ 	}
+ 
+-	hwif->chipset = ide_ht6560b;
+ 	hwif->selectproc = &ht6560b_selectproc;
+-	hwif->host_flags = IDE_HFLAG_ABUSE_PREFETCH;
+-	hwif->pio_mask = ATA_PIO5;
+ 	hwif->set_pio_mode = &ht6560b_set_pio_mode;
+-	hwif->serialized = 1;	/* is this needed? */
+-	hwif->mate = mate;
+ 
+-	mate->chipset = ide_ht6560b;
+ 	mate->selectproc = &ht6560b_selectproc;
+-	mate->host_flags = IDE_HFLAG_ABUSE_PREFETCH;
+-	mate->pio_mask = ATA_PIO5;
+ 	mate->set_pio_mode = &ht6560b_set_pio_mode;
+-	mate->serialized = 1;	/* is this needed? */
+-	mate->mate = hwif;
+-	mate->channel = 1;
+ 
+-	/*
+-	 * Setting default configurations for drives
+-	 */
+-	t = (HT_CONFIG_DEFAULT << 8);
+-	t |= HT_TIMING_DEFAULT;
+-	hwif->drives[0].drive_data = t;
+-	hwif->drives[1].drive_data = t;
+-
+-	t |= (HT_SECONDARY_IF << 8);
+-	mate->drives[0].drive_data = t;
+-	mate->drives[1].drive_data = t;
++	hwif->port_init_devs = ht6560b_port_init_devs;
++	mate->port_init_devs = ht6560b_port_init_devs;
+ 
+-	ide_device_add(idx);
++	ide_device_add(idx, &ht6560b_port_info);
+ 
+ 	return 0;
+ 
+@@ -369,9 +366,7 @@ release_region:
+ 	return -ENODEV;
  }
  
-+static const u8 ide_rw_cmds[] = {
-+	WIN_MULTREAD,
-+	WIN_MULTWRITE,
-+	WIN_MULTREAD_EXT,
-+	WIN_MULTWRITE_EXT,
-+	WIN_READ,
-+	WIN_WRITE,
-+	WIN_READ_EXT,
-+	WIN_WRITE_EXT,
-+	WIN_READDMA,
-+	WIN_WRITEDMA,
-+	WIN_READDMA_EXT,
-+	WIN_WRITEDMA_EXT,
-+};
+-#ifdef MODULE
+ module_init(ht6560b_init);
+-#endif
+ 
+ MODULE_AUTHOR("See Local File");
+ MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
+diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
+index 03715c0..15ccf69 100644
+--- a/drivers/ide/legacy/ide-cs.c
++++ b/drivers/ide/legacy/ide-cs.c
+@@ -2,8 +2,6 @@
+ 
+     A driver for PCMCIA IDE/ATA disk cards
+ 
+-    ide-cs.c 1.3 2002/10/26 05:45:31
+-
+     The contents of this file are subject to the Mozilla Public
+     License Version 1.1 (the "License"); you may not use this file
+     except in compliance with the License. You may obtain a copy of
+@@ -147,13 +145,36 @@ static void ide_detach(struct pcmcia_device *link)
+ 
+ static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
+ {
++    ide_hwif_t *hwif;
+     hw_regs_t hw;
++    int i;
++    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
 +
-+static const u8 ide_data_phases[] = {
-+	TASKFILE_MULTI_IN,
-+	TASKFILE_MULTI_OUT,
-+	TASKFILE_IN,
-+	TASKFILE_OUT,
-+	TASKFILE_IN_DMA,
-+	TASKFILE_OUT_DMA,
-+};
+     memset(&hw, 0, sizeof(hw));
+-    ide_init_hwif_ports(&hw, io, ctl, NULL);
++    ide_std_init_ports(&hw, io, ctl);
+     hw.irq = irq;
+     hw.chipset = ide_pci;
+     hw.dev = &handle->dev;
+-    return ide_register_hw(&hw, &ide_undecoded_slave, 0, NULL);
 +
-+static void ide_tf_set_cmd(ide_drive_t *drive, ide_task_t *task, u8 dma)
-+{
-+	u8 index, lba48, write;
++    hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++    if (hwif == NULL)
++	return -1;
 +
-+	lba48 = (task->tf_flags & IDE_TFLAG_LBA48) ? 2 : 0;
-+	write = (task->tf_flags & IDE_TFLAG_WRITE) ? 1 : 0;
++    i = hwif->index;
 +
-+	if (dma)
-+		index = drive->vdma ? 4 : 8;
-+	else
-+		index = drive->mult_count ? 0 : 4;
++    if (hwif->present)
++	ide_unregister(i, 0, 0);
++    else if (!hwif->hold)
++	ide_init_port_data(hwif, i);
 +
-+	task->tf.command = ide_rw_cmds[index + lba48 + write];
++    ide_init_port_hw(hwif, &hw);
++    hwif->quirkproc = &ide_undecoded_slave;
 +
-+	if (dma)
-+		index = 8; /* fixup index */
++    idx[0] = i;
 +
-+	task->data_phase = ide_data_phases[index / 2 + write];
-+}
++    ide_device_add(idx, NULL);
 +
- /*
-  * __ide_do_rw_disk() issues READ and WRITE commands to a disk,
-  * using LBA if supported, or CHS otherwise, to address sectors.
-@@ -137,11 +180,11 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
- 	unsigned int dma	= drive->using_dma;
-+	u16 nsectors		= (u16)rq->nr_sectors;
- 	u8 lba48		= (drive->addressing == 1) ? 1 : 0;
--	task_ioreg_t command	= WIN_NOP;
--	ata_nsector_t		nsectors;
--
--	nsectors.all		= (u16) rq->nr_sectors;
-+	ide_task_t		task;
-+	struct ide_taskfile	*tf = &task.tf;
-+	ide_startstop_t		rc;
++    return hwif->present ? i : -1;
+ }
  
- 	if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) {
- 		if (block + rq->nr_sectors > 1ULL << 28)
-@@ -155,121 +198,71 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq,
- 		ide_map_sg(drive, rq);
- 	}
+ /*======================================================================
+@@ -339,7 +360,7 @@ void ide_release(struct pcmcia_device *link)
+     if (info->ndev) {
+ 	/* FIXME: if this fails we need to queue the cleanup somehow
+ 	   -- need to investigate the required PCMCIA magic */
+-	ide_unregister(info->hd);
++	ide_unregister(info->hd, 0, 0);
+     }
+     info->ndev = 0;
  
--	if (IDE_CONTROL_REG)
--		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
+diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
+index 7bb79f5..26c82ce 100644
+--- a/drivers/ide/legacy/ide_platform.c
++++ b/drivers/ide/legacy/ide_platform.c
+@@ -21,56 +21,39 @@
+ #include <linux/platform_device.h>
+ #include <linux/io.h>
+ 
+-static struct {
+-	void __iomem *plat_ide_mapbase;
+-	void __iomem *plat_ide_alt_mapbase;
+-	ide_hwif_t *hwif;
+-	int index;
+-} hwif_prop;
 -
--	/* FIXME: SELECT_MASK(drive, 0) ? */
-+	memset(&task, 0, sizeof(task));
-+	task.tf_flags = IDE_TFLAG_NO_SELECT_MASK;  /* FIXME? */
-+	task.tf_flags |= (IDE_TFLAG_TF | IDE_TFLAG_DEVICE);
+-static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base,
+-	    void __iomem *ctrl, struct pata_platform_info *pdata, int irq,
+-	    int mmio)
++static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
++					   void __iomem *base,
++					   void __iomem *ctrl,
++					   struct pata_platform_info *pdata,
++					   int irq)
+ {
+ 	unsigned long port = (unsigned long)base;
+-	ide_hwif_t *hwif = ide_find_port(port);
+ 	int i;
  
- 	if (drive->select.b.lba) {
- 		if (lba48) {
--			task_ioreg_t tasklets[10];
+-	if (hwif == NULL)
+-		goto out;
 -
- 			pr_debug("%s: LBA=0x%012llx\n", drive->name,
- 					(unsigned long long)block);
+-	hwif->io_ports[IDE_DATA_OFFSET] = port;
++	hw->io_ports[IDE_DATA_OFFSET] = port;
  
--			tasklets[0] = 0;
--			tasklets[1] = 0;
--			tasklets[2] = nsectors.b.low;
--			tasklets[3] = nsectors.b.high;
--			tasklets[4] = (task_ioreg_t) block;
--			tasklets[5] = (task_ioreg_t) (block>>8);
--			tasklets[6] = (task_ioreg_t) (block>>16);
--			tasklets[7] = (task_ioreg_t) (block>>24);
--			if (sizeof(block) == 4) {
--				tasklets[8] = (task_ioreg_t) 0;
--				tasklets[9] = (task_ioreg_t) 0;
--			} else {
--				tasklets[8] = (task_ioreg_t)((u64)block >> 32);
--				tasklets[9] = (task_ioreg_t)((u64)block >> 40);
-+			tf->hob_nsect = (nsectors >> 8) & 0xff;
-+			tf->hob_lbal  = (u8)(block >> 24);
-+			if (sizeof(block) != 4) {
-+				tf->hob_lbam = (u8)((u64)block >> 32);
-+				tf->hob_lbah = (u8)((u64)block >> 40);
- 			}
--#ifdef DEBUG
--			printk("%s: 0x%02x%02x 0x%02x%02x%02x%02x%02x%02x\n",
--				drive->name, tasklets[3], tasklets[2],
--				tasklets[9], tasklets[8], tasklets[7],
--				tasklets[6], tasklets[5], tasklets[4]);
--#endif
--			hwif->OUTB(tasklets[1], IDE_FEATURE_REG);
--			hwif->OUTB(tasklets[3], IDE_NSECTOR_REG);
--			hwif->OUTB(tasklets[7], IDE_SECTOR_REG);
--			hwif->OUTB(tasklets[8], IDE_LCYL_REG);
--			hwif->OUTB(tasklets[9], IDE_HCYL_REG);
+ 	port += (1 << pdata->ioport_shift);
+ 	for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
+ 	     i++, port += (1 << pdata->ioport_shift))
+-		hwif->io_ports[i] = port;
 -
--			hwif->OUTB(tasklets[0], IDE_FEATURE_REG);
--			hwif->OUTB(tasklets[2], IDE_NSECTOR_REG);
--			hwif->OUTB(tasklets[4], IDE_SECTOR_REG);
--			hwif->OUTB(tasklets[5], IDE_LCYL_REG);
--			hwif->OUTB(tasklets[6], IDE_HCYL_REG);
--			hwif->OUTB(0x00|drive->select.all,IDE_SELECT_REG);
-+
-+			tf->nsect  = nsectors & 0xff;
-+			tf->lbal   = (u8) block;
-+			tf->lbam   = (u8)(block >>  8);
-+			tf->lbah   = (u8)(block >> 16);
-+
-+			task.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
- 		} else {
--			hwif->OUTB(0x00, IDE_FEATURE_REG);
--			hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
--			hwif->OUTB(block, IDE_SECTOR_REG);
--			hwif->OUTB(block>>=8, IDE_LCYL_REG);
--			hwif->OUTB(block>>=8, IDE_HCYL_REG);
--			hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
-+			tf->nsect  = nsectors & 0xff;
-+			tf->lbal   = block;
-+			tf->lbam   = block >>= 8;
-+			tf->lbah   = block >>= 8;
-+			tf->device = (block >> 8) & 0xf;
- 		}
- 	} else {
- 		unsigned int sect,head,cyl,track;
- 		track = (int)block / drive->sect;
- 		sect  = (int)block % drive->sect + 1;
--		hwif->OUTB(sect, IDE_SECTOR_REG);
- 		head  = track % drive->head;
- 		cyl   = track / drive->head;
+-	hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
++		hw->io_ports[i] = port;
  
- 		pr_debug("%s: CHS=%u/%u/%u\n", drive->name, cyl, head, sect);
+-	hwif->irq = irq;
++	hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
  
--		hwif->OUTB(0x00, IDE_FEATURE_REG);
--		hwif->OUTB(nsectors.b.low, IDE_NSECTOR_REG);
--		hwif->OUTB(cyl, IDE_LCYL_REG);
--		hwif->OUTB(cyl>>8, IDE_HCYL_REG);
--		hwif->OUTB(head|drive->select.all,IDE_SELECT_REG);
-+		tf->nsect  = nsectors & 0xff;
-+		tf->lbal   = sect;
-+		tf->lbam   = cyl;
-+		tf->lbah   = cyl >> 8;
-+		tf->device = head;
+-	hwif->chipset = ide_generic;
++	hw->irq = irq;
+ 
+-	if (mmio) {
+-		hwif->mmio = 1;
+-		default_hwif_mmiops(hwif);
+-	}
+-
+-	hwif_prop.hwif = hwif;
+-	hwif_prop.index = hwif->index;
+-out:
+-	return hwif;
++	hw->chipset = ide_generic;
+ }
+ 
+ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ {
+ 	struct resource *res_base, *res_alt, *res_irq;
++	void __iomem *base, *alt_base;
+ 	ide_hwif_t *hwif;
+ 	struct pata_platform_info *pdata;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	int ret = 0;
+ 	int mmio = 0;
++	hw_regs_t hw;
+ 
+ 	pdata = pdev->dev.platform_data;
+ 
+@@ -95,30 +78,37 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
+ 	}
+ 
+ 	if (mmio) {
+-		hwif_prop.plat_ide_mapbase = devm_ioremap(&pdev->dev,
++		base = devm_ioremap(&pdev->dev,
+ 			res_base->start, res_base->end - res_base->start + 1);
+-		hwif_prop.plat_ide_alt_mapbase = devm_ioremap(&pdev->dev,
++		alt_base = devm_ioremap(&pdev->dev,
+ 			res_alt->start, res_alt->end - res_alt->start + 1);
+ 	} else {
+-		hwif_prop.plat_ide_mapbase = devm_ioport_map(&pdev->dev,
++		base = devm_ioport_map(&pdev->dev,
+ 			res_base->start, res_base->end - res_base->start + 1);
+-		hwif_prop.plat_ide_alt_mapbase = devm_ioport_map(&pdev->dev,
++		alt_base = devm_ioport_map(&pdev->dev,
+ 			res_alt->start, res_alt->end - res_alt->start + 1);
  	}
  
--	if (dma) {
--		if (!hwif->dma_setup(drive)) {
--			if (rq_data_dir(rq)) {
--				command = lba48 ? WIN_WRITEDMA_EXT : WIN_WRITEDMA;
--				if (drive->vdma)
--					command = lba48 ? WIN_WRITE_EXT: WIN_WRITE;
--			} else {
--				command = lba48 ? WIN_READDMA_EXT : WIN_READDMA;
--				if (drive->vdma)
--					command = lba48 ? WIN_READ_EXT: WIN_READ;
--			}
--			hwif->dma_exec_cmd(drive, command);
--			hwif->dma_start(drive);
--			return ide_started;
--		}
--		/* fallback to PIO */
--		ide_init_sg_cmd(drive, rq);
--	}
+-	hwif = plat_ide_locate_hwif(hwif_prop.plat_ide_mapbase,
+-	         hwif_prop.plat_ide_alt_mapbase, pdata, res_irq->start, mmio);
 -
--	if (rq_data_dir(rq) == READ) {
-+	if (rq_data_dir(rq))
-+		task.tf_flags |= IDE_TFLAG_WRITE;
++	hwif = ide_find_port((unsigned long)base);
+ 	if (!hwif) {
+ 		ret = -ENODEV;
+ 		goto out;
+ 	}
+-	hwif->gendev.parent = &pdev->dev;
+-	hwif->noprobe = 0;
++
++	memset(&hw, 0, sizeof(hw));
++	plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
++	hw.dev = &pdev->dev;
++
++	ide_init_port_hw(hwif, &hw);
++
++	if (mmio) {
++		hwif->mmio = 1;
++		default_hwif_mmiops(hwif);
++	}
  
--		if (drive->mult_count) {
--			hwif->data_phase = TASKFILE_MULTI_IN;
--			command = lba48 ? WIN_MULTREAD_EXT : WIN_MULTREAD;
--		} else {
--			hwif->data_phase = TASKFILE_IN;
--			command = lba48 ? WIN_READ_EXT : WIN_READ;
--		}
--
--		ide_execute_command(drive, command, &task_in_intr, WAIT_CMD, NULL);
--		return ide_started;
--	} else {
--		if (drive->mult_count) {
--			hwif->data_phase = TASKFILE_MULTI_OUT;
--			command = lba48 ? WIN_MULTWRITE_EXT : WIN_MULTWRITE;
--		} else {
--			hwif->data_phase = TASKFILE_OUT;
--			command = lba48 ? WIN_WRITE_EXT : WIN_WRITE;
--		}
-+	ide_tf_set_cmd(drive, &task, dma);
-+	if (!dma)
-+		hwif->data_phase = task.data_phase;
-+	task.rq = rq;
+ 	idx[0] = hwif->index;
  
--		/* FIXME: ->OUTBSYNC ? */
--		hwif->OUTB(command, IDE_COMMAND_REG);
-+	rc = do_rw_taskfile(drive, &task);
+-	ide_device_add(idx);
++	ide_device_add(idx, NULL);
  
--		return pre_task_out_intr(drive, rq);
-+	if (rc == ide_stopped && dma) {
-+		/* fallback to PIO */
-+		task.tf_flags |= IDE_TFLAG_DMA_PIO_FALLBACK;
-+		ide_tf_set_cmd(drive, &task, 0);
-+		hwif->data_phase = task.data_phase;
-+		ide_init_sg_cmd(drive, rq);
-+		rc = do_rw_taskfile(drive, &task);
- 	}
-+
-+	return rc;
- }
+ 	platform_set_drvdata(pdev, hwif);
+ 
+@@ -132,14 +122,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
+ {
+ 	ide_hwif_t *hwif = pdev->dev.driver_data;
+ 
+-	if (hwif != hwif_prop.hwif) {
+-		dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error",
+-		           pdev->name);
+-	} else {
+-		ide_unregister(hwif_prop.index);
+-		hwif_prop.index = 0;
+-		hwif_prop.hwif = NULL;
+-	}
++	ide_unregister(hwif->index, 0, 0);
  
+ 	return 0;
+ }
+diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
+index 5c6aa77..a61e607 100644
+--- a/drivers/ide/legacy/macide.c
++++ b/drivers/ide/legacy/macide.c
+@@ -1,5 +1,5 @@
  /*
-@@ -307,57 +300,29 @@ static ide_startstop_t ide_do_rw_disk (ide_drive_t *drive, struct request *rq, s
-  * Queries for true maximum capacity of the drive.
-  * Returns maximum LBA address (> 0) of the drive, 0 if failed.
+- *  linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver
++ *  Macintosh IDE Driver
+  *
+  *     Copyright (C) 1998 by Michael Schmitz
+  *
+@@ -31,14 +31,6 @@
+  * These match MkLinux so they should be correct.
   */
--static unsigned long idedisk_read_native_max_address(ide_drive_t *drive)
-+static u64 idedisk_read_native_max_address(ide_drive_t *drive, int lba48)
- {
- 	ide_task_t args;
--	unsigned long addr = 0;
-+	struct ide_taskfile *tf = &args.tf;
-+	u64 addr = 0;
  
- 	/* Create IDE/ATA command request structure */
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX;
--	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
--	args.handler				= &task_no_data_intr;
-+	if (lba48)
-+		tf->command = WIN_READ_NATIVE_MAX_EXT;
-+	else
-+		tf->command = WIN_READ_NATIVE_MAX;
-+	tf->device  = ATA_LBA;
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	if (lba48)
-+		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
- 	/* submit command request */
--	ide_raw_taskfile(drive, &args, NULL);
-+	ide_no_data_taskfile(drive, &args);
+-#define IDE_DATA	0x00
+-#define IDE_ERROR	0x04	/* see err-bits */
+-#define IDE_NSECTOR	0x08	/* nr of sectors to read/write */
+-#define IDE_SECTOR	0x0c	/* starting sector */
+-#define IDE_LCYL	0x10	/* starting cylinder */
+-#define IDE_HCYL	0x14	/* high byte of starting cyl */
+-#define IDE_SELECT	0x18	/* 101dhhhh , d=drive, hhhh=head */
+-#define IDE_STATUS	0x1c	/* see status-bits */
+ #define IDE_CONTROL	0x38	/* control/altstatus */
  
- 	/* if OK, compute maximum address value */
--	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
--		addr = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
--		     | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
--		     | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
--		     | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
--		addr++;	/* since the return value is (maxlba - 1), we add 1 */
--	}
--	return addr;
--}
-+	if ((tf->status & 0x01) == 0)
-+		addr = ide_get_lba_addr(tf, lba48) + 1;
+ /*
+@@ -63,11 +55,6 @@
  
--static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive)
--{
--	ide_task_t args;
--	unsigned long long addr = 0;
--
--	/* Create IDE/ATA command request structure */
--	memset(&args, 0, sizeof(ide_task_t));
--
--	args.tfRegister[IDE_SELECT_OFFSET]	= 0x40;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_READ_NATIVE_MAX_EXT;
--	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
--	args.handler				= &task_no_data_intr;
--        /* submit command request */
--        ide_raw_taskfile(drive, &args, NULL);
+ volatile unsigned char *ide_ifr = (unsigned char *) (IDE_BASE + IDE_IFR);
+ 
+-static int macide_offsets[IDE_NR_PORTS] = {
+-    IDE_DATA, IDE_ERROR,  IDE_NSECTOR, IDE_SECTOR, IDE_LCYL,
+-    IDE_HCYL, IDE_SELECT, IDE_STATUS,  IDE_CONTROL
+-};
 -
--	/* if OK, compute maximum address value */
--	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
--		u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
--			   (args.hobRegister[IDE_LCYL_OFFSET] <<  8) |
--			    args.hobRegister[IDE_SECTOR_OFFSET];
--		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
--			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
--			    (args.tfRegister[IDE_SECTOR_OFFSET]);
--		addr = ((__u64)high << 24) | low;
--		addr++;	/* since the return value is (maxlba - 1), we add 1 */
--	}
- 	return addr;
+ int macide_ack_intr(ide_hwif_t* hwif)
+ {
+ 	if (*ide_ifr & 0x20) {
+@@ -77,64 +64,76 @@ int macide_ack_intr(ide_hwif_t* hwif)
+ 	return 0;
  }
  
-@@ -365,67 +330,37 @@ static unsigned long long idedisk_read_native_max_address_ext(ide_drive_t *drive
-  * Sets maximum virtual LBA address of the drive.
-  * Returns new maximum virtual LBA address (> 0) or 0 on failure.
++static void __init macide_setup_ports(hw_regs_t *hw, unsigned long base,
++				      int irq, ide_ack_intr_t *ack_intr)
++{
++	int i;
++
++	memset(hw, 0, sizeof(*hw));
++
++	for (i = 0; i < 8; i++)
++		hw->io_ports[i] = base + i * 4;
++
++	hw->io_ports[IDE_CONTROL_OFFSET] = IDE_CONTROL;
++
++	hw->irq = irq;
++	hw->ack_intr = ack_intr;
++}
++
++static const char *mac_ide_name[] =
++	{ "Quadra", "Powerbook", "Powerbook Baboon" };
++
+ /*
+  * Probe for a Macintosh IDE interface
   */
--static unsigned long idedisk_set_max_address(ide_drive_t *drive, unsigned long addr_req)
-+static u64 idedisk_set_max_address(ide_drive_t *drive, u64 addr_req, int lba48)
+ 
+-void __init macide_init(void)
++static int __init macide_init(void)
  {
- 	ide_task_t args;
--	unsigned long addr_set = 0;
--	
--	addr_req--;
--	/* Create IDE/ATA command request structure */
--	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
--	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>  8) & 0xff);
--	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >> 16) & 0xff);
--	args.tfRegister[IDE_SELECT_OFFSET]	= ((addr_req >> 24) & 0x0f) | 0x40;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX;
--	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
--	args.handler				= &task_no_data_intr;
--	/* submit command request */
--	ide_raw_taskfile(drive, &args, NULL);
--	/* if OK, read new maximum address value */
--	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
--		addr_set = ((args.tfRegister[IDE_SELECT_OFFSET] & 0x0f) << 24)
--			 | ((args.tfRegister[  IDE_HCYL_OFFSET]       ) << 16)
--			 | ((args.tfRegister[  IDE_LCYL_OFFSET]       ) <<  8)
--			 | ((args.tfRegister[IDE_SECTOR_OFFSET]       ));
--		addr_set++;
--	}
--	return addr_set;
--}
+-	hw_regs_t hw;
+ 	ide_hwif_t *hwif;
+-	int index = -1;
++	ide_ack_intr_t *ack_intr;
++	unsigned long base;
++	int irq;
++	hw_regs_t hw;
+ 
+ 	switch (macintosh_config->ide_type) {
+ 	case MAC_IDE_QUADRA:
+-		ide_setup_ports(&hw, IDE_BASE, macide_offsets,
+-				0, 0, macide_ack_intr,
+-//				quadra_ide_iops,
+-				IRQ_NUBUS_F);
+-		index = ide_register_hw(&hw, NULL, 1, &hwif);
++		base = IDE_BASE;
++		ack_intr = macide_ack_intr;
++		irq = IRQ_NUBUS_F;
+ 		break;
+ 	case MAC_IDE_PB:
+-		ide_setup_ports(&hw, IDE_BASE, macide_offsets,
+-				0, 0, macide_ack_intr,
+-//				macide_pb_iops,
+-				IRQ_NUBUS_C);
+-		index = ide_register_hw(&hw, NULL, 1, &hwif);
++		base = IDE_BASE;
++		ack_intr = macide_ack_intr;
++		irq = IRQ_NUBUS_C;
+ 		break;
+ 	case MAC_IDE_BABOON:
+-		ide_setup_ports(&hw, BABOON_BASE, macide_offsets,
+-				0, 0, NULL,
+-//				macide_baboon_iops,
+-				IRQ_BABOON_1);
+-		index = ide_register_hw(&hw, NULL, 1, &hwif);
+-		if (index == -1) break;
+-		if (macintosh_config->ident == MAC_MODEL_PB190) {
 -
--static unsigned long long idedisk_set_max_address_ext(ide_drive_t *drive, unsigned long long addr_req)
--{
--	ide_task_t args;
--	unsigned long long addr_set = 0;
-+	struct ide_taskfile *tf = &args.tf;
-+	u64 addr_set = 0;
+-			/* Fix breakage in ide-disk.c: drive capacity	*/
+-			/* is not initialized for drives without a 	*/
+-			/* hardware ID, and we can't get that without	*/
+-			/* probing the drive which freezes a 190.	*/
+-
+-			ide_drive_t *drive = &ide_hwifs[index].drives[0];
+-			drive->capacity64 = drive->cyl*drive->head*drive->sect;
+-
+-		}
++		base = BABOON_BASE;
++		ack_intr = NULL;
++		irq = IRQ_BABOON_1;
+ 		break;
+-
+ 	default:
+-	    return;
++		return -ENODEV;
+ 	}
  
- 	addr_req--;
- 	/* Create IDE/ATA command request structure */
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_SECTOR_OFFSET]	= ((addr_req >>  0) & 0xff);
--	args.tfRegister[IDE_LCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
--	args.tfRegister[IDE_HCYL_OFFSET]	= ((addr_req >>= 8) & 0xff);
--	args.tfRegister[IDE_SELECT_OFFSET]      = 0x40;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SET_MAX_EXT;
--	args.hobRegister[IDE_SECTOR_OFFSET]	= (addr_req >>= 8) & 0xff;
--	args.hobRegister[IDE_LCYL_OFFSET]	= (addr_req >>= 8) & 0xff;
--	args.hobRegister[IDE_HCYL_OFFSET]	= (addr_req >>= 8) & 0xff;
--	args.hobRegister[IDE_SELECT_OFFSET]	= 0x40;
--	args.hobRegister[IDE_CONTROL_OFFSET_HOB]= (drive->ctl|0x80);
--	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
--	args.handler				= &task_no_data_intr;
-+	tf->lbal     = (addr_req >>  0) & 0xff;
-+	tf->lbam     = (addr_req >>= 8) & 0xff;
-+	tf->lbah     = (addr_req >>= 8) & 0xff;
-+	if (lba48) {
-+		tf->hob_lbal = (addr_req >>= 8) & 0xff;
-+		tf->hob_lbam = (addr_req >>= 8) & 0xff;
-+		tf->hob_lbah = (addr_req >>= 8) & 0xff;
-+		tf->command  = WIN_SET_MAX_EXT;
-+	} else {
-+		tf->device   = (addr_req >>= 8) & 0x0f;
-+		tf->command  = WIN_SET_MAX;
-+	}
-+	tf->device |= ATA_LBA;
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	if (lba48)
-+		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_HOB);
- 	/* submit command request */
--	ide_raw_taskfile(drive, &args, NULL);
-+	ide_no_data_taskfile(drive, &args);
- 	/* if OK, compute maximum address value */
--	if ((args.tfRegister[IDE_STATUS_OFFSET] & 0x01) == 0) {
--		u32 high = (args.hobRegister[IDE_HCYL_OFFSET] << 16) |
--			   (args.hobRegister[IDE_LCYL_OFFSET] <<  8) |
--			    args.hobRegister[IDE_SECTOR_OFFSET];
--		u32 low  = ((args.tfRegister[IDE_HCYL_OFFSET])<<16) |
--			   ((args.tfRegister[IDE_LCYL_OFFSET])<<8) |
--			    (args.tfRegister[IDE_SECTOR_OFFSET]);
--		addr_set = ((__u64)high << 24) | low;
--		addr_set++;
--	}
-+	if ((tf->status & 0x01) == 0)
-+		addr_set = ide_get_lba_addr(tf, lba48) + 1;
+-        if (index != -1) {
++	printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
++			 mac_ide_name[macintosh_config->ide_type - 1]);
 +
- 	return addr_set;
++	macide_setup_ports(&hw, base, irq, ack_intr);
++
++	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif) {
++		u8 index = hwif->index;
++		u8 idx[4] = { index, 0xff, 0xff, 0xff };
++
++		ide_init_port_data(hwif, index);
++		ide_init_port_hw(hwif, &hw);
++
+ 		hwif->mmio = 1;
+-		if (macintosh_config->ide_type == MAC_IDE_QUADRA)
+-			printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
+-		else if (macintosh_config->ide_type == MAC_IDE_PB)
+-			printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index);
+-		else if (macintosh_config->ide_type == MAC_IDE_BABOON)
+-			printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index);
+-		else
+-			printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index);
++
++		ide_device_add(idx, NULL);
+ 	}
++
++	return 0;
  }
- 
-@@ -471,10 +406,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
- 	int lba48 = idedisk_supports_lba48(drive->id);
- 
- 	capacity = drive->capacity64;
--	if (lba48)
--		set_max = idedisk_read_native_max_address_ext(drive);
--	else
--		set_max = idedisk_read_native_max_address(drive);
 +
-+	set_max = idedisk_read_native_max_address(drive, lba48);
++module_init(macide_init);
+diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
+index 6ea46a6..1381b91 100644
+--- a/drivers/ide/legacy/q40ide.c
++++ b/drivers/ide/legacy/q40ide.c
+@@ -1,5 +1,5 @@
+ /*
+- *  linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver
++ *  Q40 I/O port IDE Driver
+  *
+  *     (c) Richard Zidlicky
+  *
+@@ -66,16 +66,12 @@ static int q40ide_default_irq(unsigned long base)
  
- 	if (ide_in_drive_list(drive->id, hpa_list)) {
- 		/*
-@@ -495,10 +428,8 @@ static void idedisk_check_hpa(ide_drive_t *drive)
- 			 capacity, sectors_to_MB(capacity),
- 			 set_max, sectors_to_MB(set_max));
  
--	if (lba48)
--		set_max = idedisk_set_max_address_ext(drive, set_max);
--	else
--		set_max = idedisk_set_max_address(drive, set_max);
-+	set_max = idedisk_set_max_address(drive, set_max, lba48);
-+
- 	if (set_max) {
- 		drive->capacity64 = set_max;
- 		printk(KERN_INFO "%s: Host Protected Area disabled.\n",
-@@ -556,32 +487,32 @@ static sector_t idedisk_capacity (ide_drive_t *drive)
- static int smart_enable(ide_drive_t *drive)
+ /*
+- * This is very similar to ide_setup_ports except that addresses
+- * are pretranslated for q40 ISA access
++ * Addresses are pretranslated for Q40 ISA access.
+  */
+ void q40_ide_setup_ports ( hw_regs_t *hw,
+ 			unsigned long base, int *offsets,
+ 			unsigned long ctrl, unsigned long intr,
+ 			ide_ack_intr_t *ack_intr,
+-/*
+- *			ide_io_ops_t *iops,
+- */
+ 			int irq)
  {
- 	ide_task_t args;
-+	struct ide_taskfile *tf = &args.tf;
+ 	int i;
+@@ -92,9 +88,6 @@ void q40_ide_setup_ports ( hw_regs_t *hw,
  
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_FEATURE_OFFSET]	= SMART_ENABLE;
--	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;
--	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
--	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
--	args.handler				= &task_no_data_intr;
--	return ide_raw_taskfile(drive, &args, NULL);
-+	tf->feature = SMART_ENABLE;
-+	tf->lbam    = SMART_LCYL_PASS;
-+	tf->lbah    = SMART_HCYL_PASS;
-+	tf->command = WIN_SMART;
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	return ide_no_data_taskfile(drive, &args);
+ 	hw->irq = irq;
+ 	hw->ack_intr = ack_intr;
+-/*
+- *	hw->iops = iops;
+- */
  }
  
- static int get_smart_data(ide_drive_t *drive, u8 *buf, u8 sub_cmd)
- {
- 	ide_task_t args;
-+	struct ide_taskfile *tf = &args.tf;
  
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_FEATURE_OFFSET]	= sub_cmd;
--	args.tfRegister[IDE_NSECTOR_OFFSET]	= 0x01;
--	args.tfRegister[IDE_LCYL_OFFSET]	= SMART_LCYL_PASS;
--	args.tfRegister[IDE_HCYL_OFFSET]	= SMART_HCYL_PASS;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SMART;
--	args.command_type			= IDE_DRIVE_TASK_IN;
--	args.data_phase				= TASKFILE_IN;
--	args.handler				= &task_in_intr;
-+	tf->feature = sub_cmd;
-+	tf->nsect   = 0x01;
-+	tf->lbam    = SMART_LCYL_PASS;
-+	tf->lbah    = SMART_HCYL_PASS;
-+	tf->command = WIN_SMART;
-+	args.tf_flags	= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	args.data_phase	= TASKFILE_IN;
- 	(void) smart_enable(drive);
--	return ide_raw_taskfile(drive, &args, buf);
-+	return ide_raw_taskfile(drive, &args, buf, 1);
- }
+@@ -111,15 +104,17 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
+  *  Probe for Q40 IDE interfaces
+  */
  
- static int proc_idedisk_read_cache
-@@ -659,19 +590,20 @@ static ide_proc_entry_t idedisk_proc[] = {
- static void idedisk_prepare_flush(struct request_queue *q, struct request *rq)
+-void __init q40ide_init(void)
++static int __init q40ide_init(void)
  {
- 	ide_drive_t *drive = q->queuedata;
-+	ide_task_t task;
+     int i;
+     ide_hwif_t *hwif;
+-    int index;
+     const char *name;
++    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
  
--	memset(rq->cmd, 0, sizeof(rq->cmd));
--
-+	memset(&task, 0, sizeof(task));
- 	if (ide_id_has_flush_cache_ext(drive->id) &&
- 	    (drive->capacity64 >= (1UL << 28)))
--		rq->cmd[0] = WIN_FLUSH_CACHE_EXT;
-+		task.tf.command = WIN_FLUSH_CACHE_EXT;
- 	else
--		rq->cmd[0] = WIN_FLUSH_CACHE;
-+		task.tf.command = WIN_FLUSH_CACHE;
-+	task.tf_flags	= IDE_TFLAG_OUT_TF | IDE_TFLAG_OUT_DEVICE;
-+	task.data_phase	= TASKFILE_NO_DATA;
+     if (!MACH_IS_Q40)
+-      return ;
++      return -ENODEV;
++
++    printk(KERN_INFO "ide: Q40 IDE controller\n");
  
--
--	rq->cmd_type = REQ_TYPE_ATA_TASK;
-+	rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- 	rq->cmd_flags |= REQ_SOFTBARRIER;
--	rq->buffer = rq->cmd;
-+	rq->special = &task;
+     for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
+ 	hw_regs_t hw;
+@@ -141,10 +136,20 @@ void __init q40ide_init(void)
+ 			0, NULL,
+ //			m68kide_iops,
+ 			q40ide_default_irq(pcide_bases[i]));
+-	index = ide_register_hw(&hw, NULL, 1, &hwif);
+-	// **FIXME**
+-	if (index != -1)
++
++	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif) {
++		ide_init_port_data(hwif, hwif->index);
++		ide_init_port_hw(hwif, &hw);
+ 		hwif->mmio = 1;
++
++		idx[i] = hwif->index;
++	}
+     }
++
++    ide_device_add(idx, NULL);
++
++    return 0;
  }
  
++module_init(q40ide_init);
+diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
+index 912e738..bba29df 100644
+--- a/drivers/ide/legacy/qd65xx.c
++++ b/drivers/ide/legacy/qd65xx.c
+@@ -1,6 +1,4 @@
  /*
-@@ -687,8 +619,10 @@ static int set_multcount(ide_drive_t *drive, int arg)
+- *  linux/drivers/ide/legacy/qd65xx.c		Version 0.07	Sep 30, 2001
+- *
+  *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
+  */
  
- 	if (drive->special.b.set_multmode)
- 		return -EBUSY;
+@@ -307,18 +305,33 @@ static int __init qd_testreg(int port)
+  * called to setup an ata channel : adjusts attributes & links for tuning
+  */
+ 
+-static void __init qd_setup(ide_hwif_t *hwif, int base, int config,
+-			    unsigned int data0, unsigned int data1)
++static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
+ {
+-	hwif->chipset = ide_qd65xx;
+-	hwif->channel = hwif->index;
+ 	hwif->select_data = base;
+ 	hwif->config_data = config;
+-	hwif->drives[0].drive_data = data0;
+-	hwif->drives[1].drive_data = data1;
+-	hwif->drives[0].io_32bit =
+-	hwif->drives[1].io_32bit = 1;
+-	hwif->pio_mask = ATA_PIO4;
++}
 +
- 	ide_init_drive_cmd (&rq);
--	rq.cmd_type = REQ_TYPE_ATA_CMD;
-+	rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
++static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
++{
++	u8 base = hwif->select_data, config = QD_CONFIG(hwif);
 +
- 	drive->mult_req = arg;
- 	drive->special.b.set_multmode = 1;
- 	(void) ide_do_drive_cmd (drive, &rq, ide_wait);
-@@ -753,12 +687,11 @@ static int write_cache(ide_drive_t *drive, int arg)
- 
- 	if (ide_id_has_flush_cache(drive->id)) {
- 		memset(&args, 0, sizeof(ide_task_t));
--		args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ?
-+		args.tf.feature = arg ?
- 			SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE;
--		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
--		args.command_type		= IDE_DRIVE_TASK_NO_DATA;
--		args.handler			= &task_no_data_intr;
--		err = ide_raw_taskfile(drive, &args, NULL);
-+		args.tf.command = WIN_SETFEATURES;
-+		args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+		err = ide_no_data_taskfile(drive, &args);
- 		if (err == 0)
- 			drive->wcache = arg;
- 	}
-@@ -774,12 +707,11 @@ static int do_idedisk_flushcache (ide_drive_t *drive)
- 
- 	memset(&args, 0, sizeof(ide_task_t));
- 	if (ide_id_has_flush_cache_ext(drive->id))
--		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_FLUSH_CACHE_EXT;
-+		args.tf.command = WIN_FLUSH_CACHE_EXT;
- 	else
--		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_FLUSH_CACHE;
--	args.command_type			= IDE_DRIVE_TASK_NO_DATA;
--	args.handler				= &task_no_data_intr;
--	return ide_raw_taskfile(drive, &args, NULL);
-+		args.tf.command = WIN_FLUSH_CACHE;
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	return ide_no_data_taskfile(drive, &args);
++	hwif->drives[0].drive_data = QD6500_DEF_DATA;
++	hwif->drives[1].drive_data = QD6500_DEF_DATA;
++}
++
++static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
++{
++	u16 t1, t2;
++	u8 base = hwif->select_data, config = QD_CONFIG(hwif);
++
++	if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
++		t1 = QD6580_DEF_DATA;
++		t2 = QD6580_DEF_DATA2;
++	} else
++		t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
++
++	hwif->drives[0].drive_data = t1;
++	hwif->drives[1].drive_data = t2;
  }
  
- static int set_acoustic (ide_drive_t *drive, int arg)
-@@ -790,13 +722,11 @@ static int set_acoustic (ide_drive_t *drive, int arg)
- 		return -EINVAL;
- 
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_FEATURE_OFFSET]	= (arg) ? SETFEATURES_EN_AAM :
--							  SETFEATURES_DIS_AAM;
--	args.tfRegister[IDE_NSECTOR_OFFSET]	= arg;
--	args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_SETFEATURES;
--	args.command_type = IDE_DRIVE_TASK_NO_DATA;
--	args.handler	  = &task_no_data_intr;
--	ide_raw_taskfile(drive, &args, NULL);
-+	args.tf.feature = arg ? SETFEATURES_EN_AAM : SETFEATURES_DIS_AAM;
-+	args.tf.nsect   = arg;
-+	args.tf.command = WIN_SETFEATURES;
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	ide_no_data_taskfile(drive, &args);
- 	drive->acoustic = arg;
- 	return 0;
+ /*
+@@ -358,6 +371,14 @@ static void __exit qd_unsetup(ide_hwif_t *hwif)
  }
-@@ -832,7 +762,6 @@ static void idedisk_add_settings(ide_drive_t *drive)
- 	ide_add_setting(drive,	"bios_head",	SETTING_RW,	TYPE_BYTE,	0,	255,			1,	1,	&drive->bios_head,	NULL);
- 	ide_add_setting(drive,	"bios_sect",	SETTING_RW,	TYPE_BYTE,	0,	63,			1,	1,	&drive->bios_sect,	NULL);
- 	ide_add_setting(drive,	"address",	SETTING_RW,	TYPE_BYTE,	0,	2,			1,	1,	&drive->addressing,	set_lba_addressing);
--	ide_add_setting(drive,	"bswap",	SETTING_READ,	TYPE_BYTE,	0,	1,			1,	1,	&drive->bswap,		NULL);
- 	ide_add_setting(drive,	"multcount",	SETTING_RW,	TYPE_BYTE,	0,	id->max_multsect,	1,	1,	&drive->mult_count,	set_multcount);
- 	ide_add_setting(drive,	"nowerr",	SETTING_RW,	TYPE_BYTE,	0,	1,			1,	1,	&drive->nowerr,		set_nowerr);
- 	ide_add_setting(drive,	"lun",		SETTING_RW,	TYPE_INT,	0,	7,			1,	1,	&drive->lun,		NULL);
-@@ -1041,6 +970,17 @@ static ide_driver_t idedisk_driver = {
- #endif
- };
+ */
  
-+static int idedisk_set_doorlock(ide_drive_t *drive, int on)
-+{
-+	ide_task_t task;
-+
-+	memset(&task, 0, sizeof(task));
-+	task.tf.command = on ? WIN_DOORLOCK : WIN_DOORUNLOCK;
-+	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+
-+	return ide_no_data_taskfile(drive, &task);
-+}
++static const struct ide_port_info qd65xx_port_info __initdata = {
++	.chipset		= ide_qd65xx,
++	.host_flags		= IDE_HFLAG_IO_32BIT |
++				  IDE_HFLAG_NO_DMA |
++				  IDE_HFLAG_NO_AUTOTUNE,
++	.pio_mask		= ATA_PIO4,
++};
 +
- static int idedisk_open(struct inode *inode, struct file *filp)
- {
- 	struct gendisk *disk = inode->i_bdev->bd_disk;
-@@ -1055,18 +995,13 @@ static int idedisk_open(struct inode *inode, struct file *filp)
- 	idkp->openers++;
+ /*
+  * qd_probe:
+  *
+@@ -395,13 +416,14 @@ static int __init qd_probe(int base)
+ 			return 1;
+ 		}
  
- 	if (drive->removable && idkp->openers == 1) {
--		ide_task_t args;
--		memset(&args, 0, sizeof(ide_task_t));
--		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK;
--		args.command_type = IDE_DRIVE_TASK_NO_DATA;
--		args.handler	  = &task_no_data_intr;
- 		check_disk_change(inode->i_bdev);
- 		/*
- 		 * Ignore the return code from door_lock,
- 		 * since the open() has already succeeded,
- 		 * and the door_lock is irrelevant at this point.
- 		 */
--		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
-+		if (drive->doorlocking && idedisk_set_doorlock(drive, 1))
- 			drive->doorlocking = 0;
+-		qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA);
++		qd_setup(hwif, base, config);
+ 
++		hwif->port_init_devs = qd6500_port_init_devs;
+ 		hwif->set_pio_mode = &qd6500_set_pio_mode;
+ 
+-		idx[0] = unit;
++		idx[unit] = unit;
+ 
+-		ide_device_add(idx);
++		ide_device_add(idx, &qd65xx_port_info);
+ 
+ 		return 1;
  	}
+@@ -428,14 +450,15 @@ static int __init qd_probe(int base)
+ 			hwif = &ide_hwifs[unit];
+ 			printk(KERN_INFO "%s: qd6580: single IDE board\n",
+ 					 hwif->name);
+-			qd_setup(hwif, base, config | (control << 8),
+-				 QD6580_DEF_DATA, QD6580_DEF_DATA2);
+ 
++			qd_setup(hwif, base, config | (control << 8));
++
++			hwif->port_init_devs = qd6580_port_init_devs;
+ 			hwif->set_pio_mode = &qd6580_set_pio_mode;
+ 
+-			idx[0] = unit;
++			idx[unit] = unit;
+ 
+-			ide_device_add(idx);
++			ide_device_add(idx, &qd65xx_port_info);
+ 
+ 			outb(QD_DEF_CONTR, QD_CONTROL_PORT);
+ 
+@@ -449,20 +472,20 @@ static int __init qd_probe(int base)
+ 			printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
+ 					hwif->name, mate->name);
+ 
+-			qd_setup(hwif, base, config | (control << 8),
+-				 QD6580_DEF_DATA, QD6580_DEF_DATA);
++			qd_setup(hwif, base, config | (control << 8));
+ 
++			hwif->port_init_devs = qd6580_port_init_devs;
+ 			hwif->set_pio_mode = &qd6580_set_pio_mode;
+ 
+-			qd_setup(mate, base, config | (control << 8),
+-				 QD6580_DEF_DATA2, QD6580_DEF_DATA2);
++			qd_setup(mate, base, config | (control << 8));
+ 
++			mate->port_init_devs = qd6580_port_init_devs;
+ 			mate->set_pio_mode = &qd6580_set_pio_mode;
+ 
+ 			idx[0] = 0;
+ 			idx[1] = 1;
+ 
+-			ide_device_add(idx);
++			ide_device_add(idx, &qd65xx_port_info);
+ 
+ 			outb(QD_DEF_CONTR, QD_CONTROL_PORT);
+ 
+@@ -478,8 +501,7 @@ int probe_qd65xx = 0;
+ module_param_named(probe, probe_qd65xx, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
+ 
+-/* Can be called directly from ide.c. */
+-int __init qd65xx_init(void)
++static int __init qd65xx_init(void)
+ {
+ 	if (probe_qd65xx == 0)
+ 		return -ENODEV;
+@@ -492,9 +514,7 @@ int __init qd65xx_init(void)
  	return 0;
-@@ -1082,12 +1017,7 @@ static int idedisk_release(struct inode *inode, struct file *filp)
- 		ide_cacheflush_p(drive);
+ }
  
- 	if (drive->removable && idkp->openers == 1) {
--		ide_task_t args;
--		memset(&args, 0, sizeof(ide_task_t));
--		args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORUNLOCK;
--		args.command_type = IDE_DRIVE_TASK_NO_DATA;
--		args.handler	  = &task_no_data_intr;
--		if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL))
-+		if (drive->doorlocking && idedisk_set_doorlock(drive, 0))
- 			drive->doorlocking = 0;
- 	}
+-#ifdef MODULE
+ module_init(qd65xx_init);
+-#endif
  
-diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
-index 4703837..3cf59f2 100644
---- a/drivers/ide/ide-dma.c
-+++ b/drivers/ide/ide-dma.c
-@@ -1,15 +1,13 @@
+ MODULE_AUTHOR("Samuel Thibault");
+ MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
+diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
+index 633a424..28dd50a 100644
+--- a/drivers/ide/legacy/qd65xx.h
++++ b/drivers/ide/legacy/qd65xx.h
+@@ -1,6 +1,4 @@
  /*
-- *  linux/drivers/ide/ide-dma.c		Version 4.10	June 9, 2000
-+ *  Copyright (C) 1995-1998   Mark Lord
-+ *  Copyright (C) 1999-2000   Andre Hedrick <andre at linux-ide.org>
-+ *  Copyright (C) 2004, 2007  Bartlomiej Zolnierkiewicz
-  *
-- *  Copyright (c) 1999-2000	Andre Hedrick <andre at linux-ide.org>
-  *  May be copied or modified under the terms of the GNU General Public License
+- * linux/drivers/ide/legacy/qd65xx.h
+- *
+  * Copyright (c) 2000	Linus Torvalds & authors
   */
  
+diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
+index 79577b9..5696ba0 100644
+--- a/drivers/ide/legacy/umc8672.c
++++ b/drivers/ide/legacy/umc8672.c
+@@ -1,6 +1,4 @@
  /*
-  *  Special Thanks to Mark for his Six years of work.
+- *  linux/drivers/ide/legacy/umc8672.c		Version 0.05	Jul 31, 1996
 - *
-- *  Copyright (c) 1995-1998  Mark Lord
-- *  May be copied or modified under the terms of the GNU General Public License
+  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
   */
  
- /*
-@@ -85,6 +83,7 @@
- #include <linux/ide.h>
- #include <linux/delay.h>
- #include <linux/scatterlist.h>
-+#include <linux/dma-mapping.h>
- 
- #include <asm/io.h>
- #include <asm/irq.h>
-@@ -153,13 +152,7 @@ ide_startstop_t ide_dma_intr (ide_drive_t *drive)
- 		if (!dma_stat) {
- 			struct request *rq = HWGROUP(drive)->rq;
- 
--			if (rq->rq_disk) {
--				ide_driver_t *drv;
--
--				drv = *(ide_driver_t **)rq->rq_disk->private_data;
--				drv->end_request(drive, 1, rq->nr_sectors);
--			} else
--				ide_end_request(drive, 1, rq->nr_sectors);
-+			task_end_request(drive, rq, stat);
- 			return ide_stopped;
- 		}
- 		printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", 
-@@ -175,16 +168,15 @@ static int ide_dma_good_drive(ide_drive_t *drive)
- 	return ide_in_drive_list(drive->id, drive_whitelist);
+@@ -122,9 +120,14 @@ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	spin_unlock_irqrestore(&ide_lock, flags);
  }
  
--#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
- /**
-  *	ide_build_sglist	-	map IDE scatter gather for DMA I/O
-  *	@drive: the drive to build the DMA table for
-  *	@rq: the request holding the sg list
-  *
-- *	Perform the PCI mapping magic necessary to access the source or
-- *	target buffers of a request via PCI DMA. The lower layers of the
-+ *	Perform the DMA mapping magic necessary to access the source or
-+ *	target buffers of a request via DMA.  The lower layers of the
-  *	kernel provide the necessary cache management so that we can
-- *	operate in a portable fashion
-+ *	operate in a portable fashion.
-  */
++static const struct ide_port_info umc8672_port_info __initdata = {
++	.chipset		= ide_umc8672,
++	.host_flags		= IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
++	.pio_mask		= ATA_PIO4,
++};
++
+ static int __init umc8672_probe(void)
+ {
+-	ide_hwif_t *hwif, *mate;
+ 	unsigned long flags;
+ 	static u8 idx[4] = { 0, 1, 0xff, 0xff };
  
- int ide_build_sglist(ide_drive_t *drive, struct request *rq)
-@@ -192,20 +184,20 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq)
- 	ide_hwif_t *hwif = HWIF(drive);
- 	struct scatterlist *sg = hwif->sg_table;
+@@ -145,21 +148,10 @@ static int __init umc8672_probe(void)
+ 	umc_set_speeds (current_speeds);
+ 	local_irq_restore(flags);
  
--	BUG_ON((rq->cmd_type == REQ_TYPE_ATA_TASKFILE) && rq->nr_sectors > 256);
+-	hwif = &ide_hwifs[0];
+-	mate = &ide_hwifs[1];
 -
- 	ide_map_sg(drive, rq);
+-	hwif->chipset = ide_umc8672;
+-	hwif->pio_mask = ATA_PIO4;
+-	hwif->set_pio_mode = &umc_set_pio_mode;
+-	hwif->mate = mate;
+-
+-	mate->chipset = ide_umc8672;
+-	mate->pio_mask = ATA_PIO4;
+-	mate->set_pio_mode = &umc_set_pio_mode;
+-	mate->mate = hwif;
+-	mate->channel = 1;
++	ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
++	ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
  
- 	if (rq_data_dir(rq) == READ)
--		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
-+		hwif->sg_dma_direction = DMA_FROM_DEVICE;
- 	else
--		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
-+		hwif->sg_dma_direction = DMA_TO_DEVICE;
+-	ide_device_add(idx);
++	ide_device_add(idx, &umc8672_port_info);
  
--	return pci_map_sg(hwif->pci_dev, sg, hwif->sg_nents, hwif->sg_dma_direction);
-+	return dma_map_sg(hwif->dev, sg, hwif->sg_nents,
-+			  hwif->sg_dma_direction);
+ 	return 0;
  }
+@@ -169,8 +161,7 @@ int probe_umc8672 = 0;
+ module_param_named(probe, probe_umc8672, bool, 0);
+ MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
  
- EXPORT_SYMBOL_GPL(ide_build_sglist);
- 
-+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
- /**
-  *	ide_build_dmatable	-	build IDE DMA table
-  *
-@@ -290,16 +282,17 @@ int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
- 			*--table |= cpu_to_le32(0x80000000);
- 		return count;
- 	}
-+
- 	printk(KERN_ERR "%s: empty DMA table?\n", drive->name);
-+
- use_pio_instead:
--	pci_unmap_sg(hwif->pci_dev,
--		     hwif->sg_table,
--		     hwif->sg_nents,
--		     hwif->sg_dma_direction);
-+	ide_destroy_dmatable(drive);
-+
- 	return 0; /* revert to PIO for this request */
+-/* Can be called directly from ide.c. */
+-int __init umc8672_init(void)
++static int __init umc8672_init(void)
+ {
+ 	if (probe_umc8672 == 0)
+ 		goto out;
+@@ -181,9 +172,7 @@ out:
+ 	return -ENODEV;;
  }
  
- EXPORT_SYMBOL_GPL(ide_build_dmatable);
-+#endif
+-#ifdef MODULE
+ module_init(umc8672_init);
+-#endif
  
- /**
-  *	ide_destroy_dmatable	-	clean up DMA mapping
-@@ -314,15 +307,15 @@ EXPORT_SYMBOL_GPL(ide_build_dmatable);
-  
- void ide_destroy_dmatable (ide_drive_t *drive)
- {
--	struct pci_dev *dev = HWIF(drive)->pci_dev;
--	struct scatterlist *sg = HWIF(drive)->sg_table;
--	int nents = HWIF(drive)->sg_nents;
-+	ide_hwif_t *hwif = drive->hwif;
+ MODULE_AUTHOR("Wolfram Podien");
+ MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
+diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
+index a4ce3ba..0f4bf5d 100644
+--- a/drivers/ide/mips/au1xxx-ide.c
++++ b/drivers/ide/mips/au1xxx-ide.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/mips/au1xxx-ide.c  version 01.30.00        Aug. 02 2005
+- *
+  * BRIEF MODULE DESCRIPTION
+  * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
+  *
+@@ -50,7 +48,6 @@
+ #include <asm/mach-au1x00/au1xxx_ide.h>
  
--	pci_unmap_sg(dev, sg, nents, HWIF(drive)->sg_dma_direction);
-+	dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents,
-+		     hwif->sg_dma_direction);
- }
+ #define DRV_NAME	"au1200-ide"
+-#define DRV_VERSION	"1.0"
+ #define DRV_AUTHOR	"Enrico Walther <enrico.walther at amd.com> / Pete Popov <ppopov at embeddedalley.com>"
  
- EXPORT_SYMBOL_GPL(ide_destroy_dmatable);
+ /* enable the burstmode in the dbdma */
+@@ -198,8 +195,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
  
-+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
- /**
-  *	config_drive_for_dma	-	attempt to activate IDE DMA
-  *	@drive: the drive to place in DMA mode
-@@ -408,23 +401,29 @@ static int dma_timer_expiry (ide_drive_t *drive)
- }
+ 		break;
+ #endif
+-	default:
+-		return;
+ 	}
  
- /**
-- *	ide_dma_host_off	-	Generic DMA kill
-+ *	ide_dma_host_set	-	Enable/disable DMA on a host
-  *	@drive: drive to control
-  *
-- *	Perform the generic IDE controller DMA off operation. This
-- *	works for most IDE bus mastering controllers
-+ *	Enable/disable DMA on an IDE controller following generic
-+ *	bus-mastering IDE controller behaviour.
+ 	au_writel(mem_sttime,MEM_STTIME2);
+@@ -211,24 +206,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
   */
  
--void ide_dma_host_off(ide_drive_t *drive)
-+void ide_dma_host_set(ide_drive_t *drive, int on)
+ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+-
+-static int auide_build_sglist(ide_drive_t *drive,  struct request *rq)
+-{
+-	ide_hwif_t *hwif = drive->hwif;
+-	_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+-	struct scatterlist *sg = hwif->sg_table;
+-
+-	ide_map_sg(drive, rq);
+-
+-	if (rq_data_dir(rq) == READ)
+-		hwif->sg_dma_direction = DMA_FROM_DEVICE;
+-	else
+-		hwif->sg_dma_direction = DMA_TO_DEVICE;
+-
+-	return dma_map_sg(ahwif->dev, sg, hwif->sg_nents,
+-			  hwif->sg_dma_direction);
+-}
+-
+ static int auide_build_dmatable(ide_drive_t *drive)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
- 	u8 unit			= (drive->select.b.unit & 0x01);
- 	u8 dma_stat		= hwif->INB(hwif->dma_status);
+ 	int i, iswrite, count = 0;
+@@ -243,8 +220,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
+ 	/* Save for interrupt context */
+ 	ahwif->drive = drive;
  
--	hwif->OUTB((dma_stat & ~(1<<(5+unit))), hwif->dma_status);
-+	if (on)
-+		dma_stat |= (1 << (5 + unit));
-+	else
-+		dma_stat &= ~(1 << (5 + unit));
-+
-+	hwif->OUTB(dma_stat, hwif->dma_status);
- }
+-	/* Build sglist */
+-	hwif->sg_nents = i = auide_build_sglist(drive, rq);
++	hwif->sg_nents = i = ide_build_sglist(drive, rq);
  
--EXPORT_SYMBOL(ide_dma_host_off);
-+EXPORT_SYMBOL_GPL(ide_dma_host_set);
-+#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
+ 	if (!i)
+ 		return 0;
+@@ -302,10 +278,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
+ 		return 1;
  
- /**
-  *	ide_dma_off_quietly	-	Generic DMA kill
-@@ -438,11 +437,10 @@ void ide_dma_off_quietly(ide_drive_t *drive)
- 	drive->using_dma = 0;
- 	ide_toggle_bounce(drive, 0);
+  use_pio_instead:
+-	dma_unmap_sg(ahwif->dev,
+-		     hwif->sg_table,
+-		     hwif->sg_nents,
+-		     hwif->sg_dma_direction);
++	ide_destroy_dmatable(drive);
  
--	drive->hwif->dma_host_off(drive);
-+	drive->hwif->dma_host_set(drive, 0);
+ 	return 0; /* revert to PIO for this request */
  }
+@@ -313,11 +286,9 @@ static int auide_build_dmatable(ide_drive_t *drive)
+ static int auide_dma_end(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
  
- EXPORT_SYMBOL(ide_dma_off_quietly);
--#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
+ 	if (hwif->sg_nents) {
+-		dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents,
+-			     hwif->sg_dma_direction);
++		ide_destroy_dmatable(drive);
+ 		hwif->sg_nents = 0;
+ 	}
  
- /**
-  *	ide_dma_off	-	disable DMA on a device
-@@ -455,56 +453,27 @@ EXPORT_SYMBOL(ide_dma_off_quietly);
- void ide_dma_off(ide_drive_t *drive)
- {
- 	printk(KERN_INFO "%s: DMA disabled\n", drive->name);
--	drive->hwif->dma_off_quietly(drive);
-+	ide_dma_off_quietly(drive);
+@@ -397,26 +368,10 @@ static int auide_dma_test_irq(ide_drive_t *drive)
+ 	return 0;
  }
  
- EXPORT_SYMBOL(ide_dma_off);
+-static void auide_dma_host_on(ide_drive_t *drive)
++static void auide_dma_host_set(ide_drive_t *drive, int on)
+ {
+ }
  
--#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
--/**
-- *	ide_dma_host_on	-	Enable DMA on a host
-- *	@drive: drive to enable for DMA
-- *
-- *	Enable DMA on an IDE controller following generic bus mastering
-- *	IDE controller behaviour
-- */
--
--void ide_dma_host_on(ide_drive_t *drive)
+-static int auide_dma_on(ide_drive_t *drive)
 -{
--	if (drive->using_dma) {
--		ide_hwif_t *hwif	= HWIF(drive);
--		u8 unit			= (drive->select.b.unit & 0x01);
--		u8 dma_stat		= hwif->INB(hwif->dma_status);
+-	drive->using_dma = 1;
 -
--		hwif->OUTB((dma_stat|(1<<(5+unit))), hwif->dma_status);
--	}
+-	return 0;
 -}
 -
--EXPORT_SYMBOL(ide_dma_host_on);
+-static void auide_dma_host_off(ide_drive_t *drive)
+-{
+-}
 -
- /**
-- *	__ide_dma_on		-	Enable DMA on a device
-+ *	ide_dma_on		-	Enable DMA on a device
-  *	@drive: drive to enable DMA on
-  *
-  *	Enable IDE DMA for a device on this IDE controller.
-  */
-- 
--int __ide_dma_on (ide_drive_t *drive)
+-static void auide_dma_off_quietly(ide_drive_t *drive)
 -{
--	/* consult the list of known "bad" drives */
--	if (__ide_dma_bad_drive(drive))
--		return 1;
+-	drive->using_dma = 0;
+-}
+-
+ static void auide_dma_lost_irq(ide_drive_t *drive)
+ {
+ 	printk(KERN_ERR "%s: IRQ lost\n", drive->name);
+@@ -522,7 +477,7 @@ static int auide_ddma_init(_auide_hwif *auide) {
+ 	auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
+ 							     NUM_DESCRIPTORS);
+  
+-	hwif->dmatable_cpu = dma_alloc_coherent(auide->dev,
++	hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
+ 						PRD_ENTRIES * PRD_BYTES,        /* 1 Page */
+ 						&hwif->dmatable_dma, GFP_KERNEL);
+ 	
+@@ -593,6 +548,17 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
+ 	*ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET);
+ }
  
-+void ide_dma_on(ide_drive_t *drive)
-+{
- 	drive->using_dma = 1;
- 	ide_toggle_bounce(drive, 1);
++static const struct ide_port_info au1xxx_port_info = {
++	.host_flags		= IDE_HFLAG_POST_SET_MODE |
++				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
++				  IDE_HFLAG_NO_IO_32BIT |
++				  IDE_HFLAG_UNMASK_IRQS,
++	.pio_mask		= ATA_PIO4,
++#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
++	.mwdma_mask		= ATA_MWDMA2,
++#endif
++};
++
+ static int au_ide_probe(struct device *dev)
+ {
+ 	struct platform_device *pdev = to_platform_device(dev);
+@@ -610,9 +576,6 @@ static int au_ide_probe(struct device *dev)
+ #endif
  
--	drive->hwif->dma_host_on(drive);
+ 	memset(&auide_hwif, 0, sizeof(_auide_hwif));
+-	auide_hwif.dev                  = 0;
 -
--	return 0;
-+	drive->hwif->dma_host_set(drive, 1);
- }
+-	ahwif->dev = dev;
+ 	ahwif->irq = platform_get_irq(pdev, 0);
  
--EXPORT_SYMBOL(__ide_dma_on);
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -643,28 +606,16 @@ static int au_ide_probe(struct device *dev)
+ 	/* FIXME:  This might possibly break PCMCIA IDE devices */
+ 
+ 	hwif                            = &ide_hwifs[pdev->id];
+-	hwif->irq			= ahwif->irq;
+-	hwif->chipset                   = ide_au1xxx;
+ 
+ 	memset(&hw, 0, sizeof(hw));
+ 	auide_setup_ports(&hw, ahwif);
+-	memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
++	hw.irq = ahwif->irq;
++	hw.dev = dev;
++	hw.chipset = ide_au1xxx;
+ 
+-	hwif->ultra_mask                = 0x0;  /* Disable Ultra DMA */
+-#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+-	hwif->mwdma_mask                = 0x07; /* Multimode-2 DMA  */
+-	hwif->swdma_mask                = 0x00;
+-#else
+-	hwif->mwdma_mask                = 0x0;
+-	hwif->swdma_mask                = 0x0;
+-#endif
 -
-+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
- /**
-  *	ide_dma_setup	-	begin a DMA phase
-  *	@drive: target device
-@@ -759,6 +728,7 @@ EXPORT_SYMBOL_GPL(ide_find_dma_mode);
+-	hwif->pio_mask = ATA_PIO4;
+-	hwif->host_flags = IDE_HFLAG_POST_SET_MODE;
++	ide_init_port_hw(hwif, &hw);
  
- static int ide_tune_dma(ide_drive_t *drive)
- {
-+	ide_hwif_t *hwif = drive->hwif;
- 	u8 speed;
+-	hwif->noprobe = 0;
+-	hwif->drives[0].unmask          = 1;
+-	hwif->drives[1].unmask          = 1;
++	hwif->dev = dev;
  
- 	if (noautodma || drive->nodma || (drive->id->capability & 1) == 0)
-@@ -771,15 +741,21 @@ static int ide_tune_dma(ide_drive_t *drive)
- 	if (ide_id_dma_bug(drive))
- 		return 0;
+ 	/* hold should be on in all cases */
+ 	hwif->hold                      = 1;
+@@ -684,32 +635,21 @@ static int au_ide_probe(struct device *dev)
+ 	hwif->set_dma_mode		= &auide_set_dma_mode;
  
--	if (drive->hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
-+	if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA)
- 		return config_drive_for_dma(drive);
+ #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
+-	hwif->dma_off_quietly		= &auide_dma_off_quietly;
+ 	hwif->dma_timeout		= &auide_dma_timeout;
  
- 	speed = ide_max_dma_mode(drive);
+ 	hwif->mdma_filter		= &auide_mdma_filter;
  
--	if (!speed)
--		return 0;
-+	if (!speed) {
-+		 /* is this really correct/needed? */
-+		if ((hwif->host_flags & IDE_HFLAG_CY82C693) &&
-+		    ide_dma_good_drive(drive))
-+			return 1;
-+		else
-+			return 0;
-+	}
++	hwif->dma_host_set		= &auide_dma_host_set;
+ 	hwif->dma_exec_cmd              = &auide_dma_exec_cmd;
+ 	hwif->dma_start                 = &auide_dma_start;
+ 	hwif->ide_dma_end               = &auide_dma_end;
+ 	hwif->dma_setup                 = &auide_dma_setup;
+ 	hwif->ide_dma_test_irq          = &auide_dma_test_irq;
+-	hwif->dma_host_off		= &auide_dma_host_off;
+-	hwif->dma_host_on		= &auide_dma_host_on;
+ 	hwif->dma_lost_irq		= &auide_dma_lost_irq;
+-	hwif->ide_dma_on                = &auide_dma_on;
+-#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
+-	hwif->channel                   = 0;
+-	hwif->hold                      = 1;
++#endif
+ 	hwif->select_data               = 0;    /* no chipset-specific code */
+ 	hwif->config_data               = 0;    /* no chipset-specific code */
  
--	if (drive->hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
-+	if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
- 		return 0;
+-	hwif->drives[0].autotune        = 1;    /* 1=autotune, 2=noautotune, 0=default */
+-	hwif->drives[1].autotune	= 1;
+-#endif
+-	hwif->drives[0].no_io_32bit	= 1;
+-	hwif->drives[1].no_io_32bit	= 1;
+-
+ 	auide_hwif.hwif                 = hwif;
+ 	hwif->hwif_data                 = &auide_hwif;
  
- 	if (ide_set_dma_mode(drive, speed))
-@@ -824,25 +800,43 @@ err_out:
+@@ -720,7 +660,7 @@ static int au_ide_probe(struct device *dev)
  
- int ide_set_dma(ide_drive_t *drive)
- {
--	ide_hwif_t *hwif = drive->hwif;
- 	int rc;
+ 	idx[0] = hwif->index;
  
-+	/*
-+	 * Force DMAing for the beginning of the check.
-+	 * Some chipsets appear to do interesting
-+	 * things, if not checked and cleared.
-+	 *   PARANOIA!!!
-+	 */
-+	ide_dma_off_quietly(drive);
-+
- 	rc = ide_dma_check(drive);
-+	if (rc)
-+		return rc;
+-	ide_device_add(idx);
++	ide_device_add(idx, &au1xxx_port_info);
  
--	switch(rc) {
--	case -1: /* DMA needs to be disabled */
--		hwif->dma_off_quietly(drive);
--		return -1;
--	case  0: /* DMA needs to be enabled */
--		return hwif->ide_dma_on(drive);
--	case  1: /* DMA setting cannot be changed */
--		break;
--	default:
--		BUG();
--		break;
--	}
-+	ide_dma_on(drive);
-+
-+	return 0;
-+}
+ 	dev_set_drvdata(dev, hwif);
  
--	return rc;
-+void ide_check_dma_crc(ide_drive_t *drive)
-+{
-+	u8 mode;
-+
-+	ide_dma_off_quietly(drive);
-+	drive->crc_count = 0;
-+	mode = drive->current_speed;
-+	/*
-+	 * Don't try non Ultra-DMA modes without iCRC's.  Force the
-+	 * device to PIO and make the user enable SWDMA/MWDMA modes.
-+	 */
-+	if (mode > XFER_UDMA_0 && mode <= XFER_UDMA_7)
-+		mode--;
-+	else
-+		mode = XFER_PIO_4;
-+	ide_set_xfer_rate(drive, mode);
-+	if (drive->current_speed >= XFER_SW_DMA_0)
-+		ide_dma_on(drive);
- }
+@@ -737,7 +677,7 @@ static int au_ide_remove(struct device *dev)
+ 	ide_hwif_t *hwif = dev_get_drvdata(dev);
+ 	_auide_hwif *ahwif = &auide_hwif;
  
- #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-@@ -870,10 +864,10 @@ EXPORT_SYMBOL(ide_dma_timeout);
- static void ide_release_dma_engine(ide_hwif_t *hwif)
- {
- 	if (hwif->dmatable_cpu) {
--		pci_free_consistent(hwif->pci_dev,
--				    PRD_ENTRIES * PRD_BYTES,
--				    hwif->dmatable_cpu,
--				    hwif->dmatable_dma);
-+		struct pci_dev *pdev = to_pci_dev(hwif->dev);
-+
-+		pci_free_consistent(pdev, PRD_ENTRIES * PRD_BYTES,
-+				    hwif->dmatable_cpu, hwif->dmatable_dma);
- 		hwif->dmatable_cpu = NULL;
- 	}
- }
-@@ -901,7 +895,9 @@ int ide_release_dma(ide_hwif_t *hwif)
+-	ide_unregister(hwif - ide_hwifs);
++	ide_unregister(hwif->index, 0, 0);
  
- static int ide_allocate_dma_engine(ide_hwif_t *hwif)
- {
--	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
-+
-+	hwif->dmatable_cpu = pci_alloc_consistent(pdev,
- 						  PRD_ENTRIES * PRD_BYTES,
- 						  &hwif->dmatable_dma);
+ 	iounmap((void *)ahwif->regbase);
  
-@@ -914,19 +910,19 @@ static int ide_allocate_dma_engine(ide_hwif_t *hwif)
- 	return 1;
- }
+diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
+index 521edd4..956259f 100644
+--- a/drivers/ide/mips/swarm.c
++++ b/drivers/ide/mips/swarm.c
+@@ -117,6 +117,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
+ 	default_hwif_mmiops(hwif);
+ 	/* Prevent resource map manipulation.  */
+ 	hwif->mmio = 1;
++	hwif->chipset = ide_generic;
+ 	hwif->noprobe = 0;
  
--static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
-+static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base)
- {
- 	printk(KERN_INFO "    %s: MMIO-DMA ", hwif->name);
+ 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
+@@ -128,7 +129,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
  
- 	return 0;
- }
+ 	idx[0] = hwif->index;
  
--static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
-+static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base)
- {
- 	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
--	       hwif->name, base, base + ports - 1);
-+	       hwif->name, base, base + 7);
+-	ide_device_add(idx);
++	ide_device_add(idx, NULL);
  
--	if (!request_region(base, ports, hwif->name)) {
-+	if (!request_region(base, 8, hwif->name)) {
- 		printk(" -- Error, ports in use.\n");
- 		return 1;
- 	}
-@@ -938,7 +934,7 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
- 			if (!request_region(hwif->extra_base,
- 					    hwif->cds->extra, hwif->cds->name)) {
- 				printk(" -- Error, extra ports in use.\n");
--				release_region(base, ports);
-+				release_region(base, 8);
- 				return 1;
- 			}
- 			hwif->extra_ports = hwif->cds->extra;
-@@ -948,17 +944,19 @@ static int ide_iomio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int port
- 	return 0;
- }
+ 	dev_set_drvdata(dev, hwif);
  
--static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
-+static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base)
- {
- 	if (hwif->mmio)
--		return ide_mapped_mmio_dma(hwif, base,ports);
-+		return ide_mapped_mmio_dma(hwif, base);
+diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
+index 95d1ea8..02e6ee7 100644
+--- a/drivers/ide/pci/Makefile
++++ b/drivers/ide/pci/Makefile
+@@ -34,6 +34,11 @@ obj-$(CONFIG_BLK_DEV_TRM290)		+= trm290.o
+ obj-$(CONFIG_BLK_DEV_VIA82CXXX)		+= via82cxxx.o
  
--	return ide_iomio_dma(hwif, base, ports);
-+	return ide_iomio_dma(hwif, base);
- }
+ # Must appear at the end of the block
+-obj-$(CONFIG_BLK_DEV_GENERIC)          += generic.o
++obj-$(CONFIG_BLK_DEV_GENERIC)		+= ide-pci-generic.o
++ide-pci-generic-y			+= generic.o
++
++ifeq ($(CONFIG_BLK_DEV_CMD640), m)
++	obj-m += cmd640.o
++endif
  
--void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
-+void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
+ EXTRA_CFLAGS	:= -Idrivers/ide
+diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
+index 4426850..cfb3265 100644
+--- a/drivers/ide/pci/aec62xx.c
++++ b/drivers/ide/pci/aec62xx.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/aec62xx.c		Version 0.27	Sep 16, 2007
+- *
+  * Copyright (C) 1999-2002	Andre Hedrick <andre at linux-ide.org>
+  * Copyright (C) 2007		MontaVista Software, Inc. <source at mvista.com>
+  *
+@@ -9,7 +7,6 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+@@ -90,7 +87,7 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr
+ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
  {
--	if (ide_dma_iobase(hwif, base, num_ports))
-+	u8 dma_stat;
-+
-+	if (ide_dma_iobase(hwif, base))
- 		return;
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u16 d_conf		= 0;
+ 	u8 ultra = 0, ultra_conf = 0;
+ 	u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
+@@ -116,7 +113,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
+ static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 unit		= (drive->select.b.unit & 0x01);
+ 	u8 tmp1 = 0, tmp2 = 0;
+ 	u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
+@@ -168,29 +165,28 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
+ 	return dev->irq;
+ }
  
- 	if (ide_allocate_dma_engine(hwif)) {
-@@ -968,30 +966,19 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
++static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif)
++{
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
++
++	pci_read_config_byte(dev, 0x49, &ata66);
++
++	return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++}
++
+ static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
  
- 	hwif->dma_base = base;
+ 	hwif->set_pio_mode = &aec_set_pio_mode;
  
--	if (hwif->mate)
--		hwif->dma_master = hwif->channel ? hwif->mate->dma_base : base;
+ 	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
+ 		hwif->set_dma_mode = &aec6210_set_mode;
 -	else
--		hwif->dma_master = base;
++	else {
+ 		hwif->set_dma_mode = &aec6260_set_mode;
+ 
+-	if (hwif->dma_base == 0)
+-		return;
 -
--	if (!(hwif->dma_command))
--		hwif->dma_command	= hwif->dma_base;
--	if (!(hwif->dma_vendor1))
--		hwif->dma_vendor1	= (hwif->dma_base + 1);
--	if (!(hwif->dma_status))
--		hwif->dma_status	= (hwif->dma_base + 2);
--	if (!(hwif->dma_vendor3))
--		hwif->dma_vendor3	= (hwif->dma_base + 3);
--	if (!(hwif->dma_prdtable))
--		hwif->dma_prdtable	= (hwif->dma_base + 4);
+-	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
+-		return;
 -
--	if (!hwif->dma_off_quietly)
--		hwif->dma_off_quietly = &ide_dma_off_quietly;
--	if (!hwif->dma_host_off)
--		hwif->dma_host_off = &ide_dma_host_off;
--	if (!hwif->ide_dma_on)
--		hwif->ide_dma_on = &__ide_dma_on;
--	if (!hwif->dma_host_on)
--		hwif->dma_host_on = &ide_dma_host_on;
-+	if (!hwif->dma_command)
-+		hwif->dma_command	= hwif->dma_base + 0;
-+	if (!hwif->dma_vendor1)
-+		hwif->dma_vendor1	= hwif->dma_base + 1;
-+	if (!hwif->dma_status)
-+		hwif->dma_status	= hwif->dma_base + 2;
-+	if (!hwif->dma_vendor3)
-+		hwif->dma_vendor3	= hwif->dma_base + 3;
-+	if (!hwif->dma_prdtable)
-+		hwif->dma_prdtable	= hwif->dma_base + 4;
-+
-+	if (!hwif->dma_host_set)
-+		hwif->dma_host_set = &ide_dma_host_set;
- 	if (!hwif->dma_setup)
- 		hwif->dma_setup = &ide_dma_setup;
- 	if (!hwif->dma_exec_cmd)
-@@ -1007,15 +994,10 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base, unsigned num_ports)
- 	if (!hwif->dma_lost_irq)
- 		hwif->dma_lost_irq = &ide_dma_lost_irq;
- 
--	if (hwif->chipset != ide_trm290) {
--		u8 dma_stat = hwif->INB(hwif->dma_status);
--		printk(", BIOS settings: %s:%s, %s:%s",
--		       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "pio",
--		       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "pio");
--	}
--	printk("\n");
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+-		u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
 -
--	BUG_ON(!hwif->dma_master);
-+	dma_stat = hwif->INB(hwif->dma_status);
-+	printk(KERN_CONT ", BIOS settings: %s:%s, %s:%s\n",
-+	       hwif->drives[0].name, (dma_stat & 0x20) ? "DMA" : "PIO",
-+	       hwif->drives[1].name, (dma_stat & 0x40) ? "DMA" : "PIO");
+-		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+-
+-		hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++		hwif->cable_detect = atp86x_cable_detect;
+ 	}
  }
  
- EXPORT_SYMBOL_GPL(ide_setup_dma);
-diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
-index 04a3578..f8fe6ee 100644
---- a/drivers/ide/ide-floppy.c
-+++ b/drivers/ide/ide-floppy.c
-@@ -1,15 +1,9 @@
+@@ -202,6 +198,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+ 		.host_flags	= IDE_HFLAG_SERIALIZE |
+ 				  IDE_HFLAG_NO_ATAPI_DMA |
++				  IDE_HFLAG_NO_DSC |
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ 				  IDE_HFLAG_OFF_BOARD,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+@@ -211,6 +209,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_aec62xx,
+ 		.init_hwif	= init_hwif_aec62xx,
+ 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ 				  IDE_HFLAG_OFF_BOARD,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+@@ -220,7 +219,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_aec62xx,
+ 		.init_hwif	= init_hwif_aec62xx,
+ 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA,
++		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA4,
+@@ -228,7 +228,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ 		.name		= "AEC6280",
+ 		.init_chipset	= init_chipset_aec62xx,
+ 		.init_hwif	= init_hwif_aec62xx,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
++				  IDE_HFLAG_OFF_BOARD,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+@@ -237,7 +239,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_aec62xx,
+ 		.init_hwif	= init_hwif_aec62xx,
+ 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
++				  IDE_HFLAG_OFF_BOARD,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
+index ce29393..b3b6f51 100644
+--- a/drivers/ide/pci/alim15x3.c
++++ b/drivers/ide/pci/alim15x3.c
+@@ -1,6 +1,4 @@
  /*
-- * linux/drivers/ide/ide-floppy.c	Version 0.99	Feb 24 2002
+- * linux/drivers/ide/pci/alim15x3.c		Version 0.29	Sep 16 2007
 - *
-- * Copyright (C) 1996 - 1999 Gadi Oxman <gadio at netvision.net.il>
-- * Copyright (C) 2000 - 2002 Paul Bristow <paul at paulbristow.net>
-- */
+  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
+  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
+  *  Copyright (C) 1999-2000 CJ, cjtsai at ali.com.tw, Maintainer
+@@ -33,7 +31,6 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+@@ -293,7 +290,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
+ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	int s_time, a_time, c_time;
+ 	u8 s_clc, a_clc, r_clc;
+ 	unsigned long flags;
+@@ -396,15 +393,12 @@ static u8 ali_udma_filter(ide_drive_t *drive)
+ static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 speed1		= speed;
+ 	u8 unit			= (drive->select.b.unit & 0x01);
+ 	u8 tmpbyte		= 0x00;
+ 	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56;
+ 
+-	if (speed < XFER_PIO_0)
+-		return;
 -
--/*
-  * IDE ATAPI floppy driver.
-  *
-- * The driver currently doesn't have any fancy features, just the bare
-- * minimum read/write support.
-+ * Copyright (C) 1996-1999  Gadi Oxman <gadio at netvision.net.il>
-+ * Copyright (C) 2000-2002  Paul Bristow <paul at paulbristow.net>
-+ * Copyright (C) 2005       Bartlomiej Zolnierkiewicz
-  *
-  * This driver supports the following IDE floppy drives:
-  *
-@@ -17,70 +11,11 @@
-  * Iomega Zip 100/250
-  * Iomega PC Card Clik!/PocketZip
-  *
-- * Many thanks to Lode Leroy <Lode.Leroy at www.ibase.be>, who tested so many
-- * ALPHA patches to this driver on an EASYSTOR LS-120 ATAPI floppy drive.
-- *
-- * Ver 0.1   Oct 17 96   Initial test version, mostly based on ide-tape.c.
-- * Ver 0.2   Oct 31 96   Minor changes.
-- * Ver 0.3   Dec  2 96   Fixed error recovery bug.
-- * Ver 0.4   Jan 26 97   Add support for the HDIO_GETGEO ioctl.
-- * Ver 0.5   Feb 21 97   Add partitions support.
-- *                       Use the minimum of the LBA and CHS capacities.
-- *                       Avoid hwgroup->rq == NULL on the last irq.
-- *                       Fix potential null dereferencing with DEBUG_LOG.
-- * Ver 0.8   Dec  7 97   Increase irq timeout from 10 to 50 seconds.
-- *                       Add media write-protect detection.
-- *                       Issue START command only if TEST UNIT READY fails.
-- *                       Add work-around for IOMEGA ZIP revision 21.D.
-- *                       Remove idefloppy_get_capabilities().
-- * Ver 0.9   Jul  4 99   Fix a bug which might have caused the number of
-- *                        bytes requested on each interrupt to be zero.
-- *                        Thanks to <shanos at es.co.nz> for pointing this out.
-- * Ver 0.9.sv Jan 6 01   Sam Varshavchik <mrsam at courier-mta.com>
-- *                       Implement low level formatting.  Reimplemented
-- *                       IDEFLOPPY_CAPABILITIES_PAGE, since we need the srfp
-- *                       bit.  My LS-120 drive barfs on
-- *                       IDEFLOPPY_CAPABILITIES_PAGE, but maybe it's just me.
-- *                       Compromise by not reporting a failure to get this
-- *                       mode page.  Implemented four IOCTLs in order to
-- *                       implement formatting.  IOCTls begin with 0x4600,
-- *                       0x46 is 'F' as in Format.
-- *            Jan 9 01   Userland option to select format verify.
-- *                       Added PC_SUPPRESS_ERROR flag - some idefloppy drives
-- *                       do not implement IDEFLOPPY_CAPABILITIES_PAGE, and
-- *                       return a sense error.  Suppress error reporting in
-- *                       this particular case in order to avoid spurious
-- *                       errors in syslog.  The culprit is
-- *                       idefloppy_get_capability_page(), so move it to
-- *                       idefloppy_begin_format() so that it's not used
-- *                       unless absolutely necessary.
-- *                       If drive does not support format progress indication
-- *                       monitor the dsc bit in the status register.
-- *                       Also, O_NDELAY on open will allow the device to be
-- *                       opened without a disk available.  This can be used to
-- *                       open an unformatted disk, or get the device capacity.
-- * Ver 0.91  Dec 11 99   Added IOMEGA Clik! drive support by 
-- *     		   <paul at paulbristow.net>
-- * Ver 0.92  Oct 22 00   Paul Bristow became official maintainer for this 
-- *           		   driver.  Included Powerbook internal zip kludge.
-- * Ver 0.93  Oct 24 00   Fixed bugs for Clik! drive
-- *                        no disk on insert and disk change now works
-- * Ver 0.94  Oct 27 00   Tidied up to remove strstr(Clik) everywhere
-- * Ver 0.95  Nov  7 00   Brought across to kernel 2.4
-- * Ver 0.96  Jan  7 01   Actually in line with release version of 2.4.0
-- *                       including set_bit patch from Rusty Russell
-- * Ver 0.97  Jul 22 01   Merge 0.91-0.96 onto 0.9.sv for ac series
-- * Ver 0.97.sv Aug 3 01  Backported from 2.4.7-ac3
-- * Ver 0.98  Oct 26 01   Split idefloppy_transfer_pc into two pieces to
-- *                        fix a lost interrupt problem. It appears the busy
-- *                        bit was being deasserted by my IOMEGA ATAPI ZIP 100
-- *                        drive before the drive was actually ready.
-- * Ver 0.98a Oct 29 01   Expose delay value so we can play.
-- * Ver 0.99  Feb 24 02   Remove duplicate code, modify clik! detection code 
-- *                        to support new PocketZip drives 
-+ * For a historical changelog see
-+ * Documentation/ide/ChangeLog.ide-floppy.1996-2002
-  */
+ 	if (speed == XFER_UDMA_6)
+ 		speed1 = 0x47;
  
--#define IDEFLOPPY_VERSION "0.99.newide"
-+#define IDEFLOPPY_VERSION "1.00"
+@@ -628,7 +622,7 @@ static int ali_cable_override(struct pci_dev *pdev)
  
- #include <linux/module.h>
- #include <linux/types.h>
-@@ -102,179 +37,91 @@
- #include <scsi/scsi_ioctl.h>
+ static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	unsigned long flags;
+ 	u8 cbl = ATA_CBL_PATA40, tmpbyte;
  
- #include <asm/byteorder.h>
--#include <asm/irq.h>
--#include <asm/uaccess.h>
--#include <asm/io.h>
-+#include <linux/irq.h>
-+#include <linux/uaccess.h>
-+#include <linux/io.h>
- #include <asm/unaligned.h>
+@@ -671,13 +665,12 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
+ 	hwif->set_dma_mode = &ali_set_dma_mode;
+ 	hwif->udma_filter = &ali_udma_filter;
  
--/*
-- *	The following are used to debug the driver.
-- */
-+/* define to see debug info */
- #define IDEFLOPPY_DEBUG_LOG		0
--#define IDEFLOPPY_DEBUG_INFO		0
--#define IDEFLOPPY_DEBUG_BUGS		1
++	hwif->cable_detect = ata66_ali15x3;
++
+ 	if (hwif->dma_base == 0)
+ 		return;
  
- /* #define IDEFLOPPY_DEBUG(fmt, args...) printk(KERN_INFO fmt, ## args) */
--#define IDEFLOPPY_DEBUG( fmt, args... )
-+#define IDEFLOPPY_DEBUG(fmt, args...)
+ 	hwif->dma_setup = &ali15x3_dma_setup;
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = ata66_ali15x3(hwif);
+ }
  
- #if IDEFLOPPY_DEBUG_LOG
--#define debug_log printk
-+#define debug_log(fmt, args...) \
-+	printk(KERN_INFO "ide-floppy: " fmt, ## args)
- #else
--#define debug_log(fmt, args... ) do {} while(0)
-+#define debug_log(fmt, args...) do {} while (0)
- #endif
+ /**
+@@ -691,12 +684,13 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
  
+ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	u8 ideic, inmir;
+ 	s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
+ 				      1, 11, 0, 12, 0, 14, 0, 15 };
+ 	int irq = -1;
  
--/*
-- *	Some drives require a longer irq timeout.
-- */
-+/* Some drives require a longer irq timeout. */
- #define IDEFLOPPY_WAIT_CMD		(5 * WAIT_CMD)
+-	if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229)
++	if (dev->device == PCI_DEVICE_ID_AL_M5229)
+ 		hwif->irq = hwif->channel ? 15 : 14;
  
- /*
-- *	After each failed packet command we issue a request sense command
-- *	and retry the packet command IDEFLOPPY_MAX_PC_RETRIES times.
-+ * After each failed packet command we issue a request sense command and retry
-+ * the packet command IDEFLOPPY_MAX_PC_RETRIES times.
-  */
- #define IDEFLOPPY_MAX_PC_RETRIES	3
+ 	if (isa_dev) {
+@@ -748,7 +742,7 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
+ 		return;
+ 	if (!hwif->channel)
+ 		outb(inb(dmabase + 2) & 0x60, dmabase + 2);
+-	ide_setup_dma(hwif, dmabase, 8);
++	ide_setup_dma(hwif, dmabase);
+ }
  
- /*
-- *	With each packet command, we allocate a buffer of
-- *	IDEFLOPPY_PC_BUFFER_SIZE bytes.
-+ * With each packet command, we allocate a buffer of IDEFLOPPY_PC_BUFFER_SIZE
-+ * bytes.
-  */
- #define IDEFLOPPY_PC_BUFFER_SIZE	256
+ static const struct ide_port_info ali15x3_chipset __devinitdata = {
+@@ -778,7 +772,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
+ 	};
+ 
+ 	struct ide_port_info d = ali15x3_chipset;
+-	u8 rev = dev->revision;
++	u8 rev = dev->revision, idx = id->driver_data;
+ 
+ 	if (pci_dev_present(ati_rs100))
+ 		printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
+@@ -801,6 +795,9 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
+ 			d.udma_mask = ATA_UDMA6;
+ 	}
  
++	if (idx == 0)
++		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
++
+ #if defined(CONFIG_SPARC64)
+ 	d.init_hwif = init_hwif_common_ali15x3;
+ #endif /* CONFIG_SPARC64 */
+@@ -810,7 +807,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
+ 
+ static const struct pci_device_id alim15x3_pci_tbl[] = {
+ 	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
+-	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 },
++	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
+ 	{ 0, },
+ };
+ MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
+diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
+index 8d4125e..2ef890c 100644
+--- a/drivers/ide/pci/amd74xx.c
++++ b/drivers/ide/pci/amd74xx.c
+@@ -1,6 +1,4 @@
  /*
-- *	In various places in the driver, we need to allocate storage
-- *	for packet commands and requests, which will remain valid while
-- *	we leave the driver to wait for an interrupt or a timeout event.
-+ * In various places in the driver, we need to allocate storage for packet
-+ * commands and requests, which will remain valid while	we leave the driver to
-+ * wait for an interrupt or a timeout event.
-  */
- #define IDEFLOPPY_PC_STACK		(10 + IDEFLOPPY_MAX_PC_RETRIES)
+- * Version 2.24
+- *
+  * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
+  * IDE driver for Linux.
+  *
+@@ -19,90 +17,52 @@
  
--/*
-- *	Our view of a packet command.
-- */
- typedef struct idefloppy_packet_command_s {
- 	u8 c[12];				/* Actual packet bytes */
--	int retries;				/* On each retry, we increment retries */
-+	int retries;				/* On each retry, we increment
-+						   retries */
- 	int error;				/* Error code */
- 	int request_transfer;			/* Bytes to transfer */
- 	int actually_transferred;		/* Bytes actually transferred */
- 	int buffer_size;			/* Size of our data buffer */
--	int b_count;				/* Missing/Available data on the current buffer */
-+	int b_count;				/* Missing/Available data on
-+						   the current buffer */
- 	struct request *rq;			/* The corresponding request */
- 	u8 *buffer;				/* Data buffer */
--	u8 *current_position;			/* Pointer into the above buffer */
--	void (*callback) (ide_drive_t *);	/* Called when this packet command is completed */
-+	u8 *current_position;			/* Pointer into above buffer */
-+	void (*callback) (ide_drive_t *);	/* Called when this packet
-+						   command is completed */
- 	u8 pc_buffer[IDEFLOPPY_PC_BUFFER_SIZE];	/* Temporary buffer */
--	unsigned long flags;			/* Status/Action bit flags: long for set_bit */
-+	unsigned long flags;			/* Status/Action bit flags: long
-+						   for set_bit */
- } idefloppy_pc_t;
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
+-#include <asm/io.h>
  
--/*
-- *	Packet command flag bits.
-- */
--#define	PC_ABORT			0	/* Set when an error is considered normal - We won't retry */
--#define PC_DMA_RECOMMENDED		2	/* 1 when we prefer to use DMA if possible */
--#define	PC_DMA_IN_PROGRESS		3	/* 1 while DMA in progress */
--#define	PC_DMA_ERROR			4	/* 1 when encountered problem during DMA */
--#define	PC_WRITING			5	/* Data direction */
--
--#define	PC_SUPPRESS_ERROR		6	/* Suppress error reporting */
+ #include "ide-timing.h"
+ 
+-#define AMD_IDE_CONFIG		(0x01 + amd_config->base)
+-#define AMD_CABLE_DETECT	(0x02 + amd_config->base)
+-#define AMD_DRIVE_TIMING	(0x08 + amd_config->base)
+-#define AMD_8BIT_TIMING		(0x0e + amd_config->base)
+-#define AMD_ADDRESS_SETUP	(0x0c + amd_config->base)
+-#define AMD_UDMA_TIMING		(0x10 + amd_config->base)
 -
--/*
-- *	Removable Block Access Capabilities Page
-- */
--typedef struct {
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	page_code	:6;	/* Page code - Should be 0x1b */
--	unsigned	reserved1_6	:1;	/* Reserved */
--	unsigned	ps		:1;	/* Should be 0 */
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	ps		:1;	/* Should be 0 */
--	unsigned	reserved1_6	:1;	/* Reserved */
--	unsigned	page_code	:6;	/* Page code - Should be 0x1b */
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u8		page_length;		/* Page Length - Should be 0xa */
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	reserved2	:6;
--	unsigned	srfp		:1;	/* Supports reporting progress of format */
--	unsigned	sflp		:1;	/* System floppy type device */
--	unsigned	tlun		:3;	/* Total logical units supported by the device */
--	unsigned	reserved3	:3;
--	unsigned	sml		:1;	/* Single / Multiple lun supported */
--	unsigned	ncd		:1;	/* Non cd optical device */
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	sflp		:1;	/* System floppy type device */
--	unsigned	srfp		:1;	/* Supports reporting progress of format */
--	unsigned	reserved2	:6;
--	unsigned	ncd		:1;	/* Non cd optical device */
--	unsigned	sml		:1;	/* Single / Multiple lun supported */
--	unsigned	reserved3	:3;
--	unsigned	tlun		:3;	/* Total logical units supported by the device */
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u8		reserved[8];
--} idefloppy_capabilities_page_t;
+-#define AMD_CHECK_SWDMA		0x08
+-#define AMD_BAD_SWDMA		0x10
+-#define AMD_BAD_FIFO		0x20
+-#define AMD_CHECK_SERENADE	0x40
 -
 -/*
-- *	Flexible disk page.
-- */
--typedef struct {
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	page_code	:6;	/* Page code - Should be 0x5 */
--	unsigned	reserved1_6	:1;	/* Reserved */
--	unsigned	ps		:1;	/* The device is capable of saving the page */
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	ps		:1;	/* The device is capable of saving the page */
--	unsigned	reserved1_6	:1;	/* Reserved */
--	unsigned	page_code	:6;	/* Page code - Should be 0x5 */
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u8		page_length;		/* Page Length - Should be 0x1e */
--	u16		transfer_rate;		/* In kilobits per second */
--	u8		heads, sectors;		/* Number of heads, Number of sectors per track */
--	u16		sector_size;		/* Byes per sector */
--	u16		cyls;			/* Number of cylinders */
--	u8		reserved10[10];
--	u8		motor_delay;		/* Motor off delay */
--	u8		reserved21[7];
--	u16		rpm;			/* Rotations per minute */
--	u8		reserved30[2];
--} idefloppy_flexible_disk_page_t;
-- 
--/*
-- *	Format capacity
+- * AMD SouthBridge chips.
 - */
--typedef struct {
--	u8		reserved[3];
--	u8		length;			/* Length of the following descriptors in bytes */
--} idefloppy_capacity_header_t;
 -
--typedef struct {
--	u32		blocks;			/* Number of blocks */
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	dc		:2;	/* Descriptor Code */
--	unsigned	reserved	:6;
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	reserved	:6;
--	unsigned	dc		:2;	/* Descriptor Code */
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u8		length_msb;		/* Block Length (MSB)*/
--	u16		length;			/* Block Length */
--} idefloppy_capacity_descriptor_t;
-+/* Packet command flag bits. */
+-static struct amd_ide_chip {
+-	unsigned short id;
+-	u8 base;
+-	u8 udma_mask;
+-	u8 flags;
+-} amd_ide_chips[] = {
+-	{ PCI_DEVICE_ID_AMD_COBRA_7401,		 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
+-	{ PCI_DEVICE_ID_AMD_VIPER_7409,		 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
+-	{ PCI_DEVICE_ID_AMD_VIPER_7411,		 0x40, ATA_UDMA5, AMD_BAD_FIFO },
+-	{ PCI_DEVICE_ID_AMD_OPUS_7441,		 0x40, ATA_UDMA5, },
+-	{ PCI_DEVICE_ID_AMD_8111_IDE,		 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	 0x50, ATA_UDMA5, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
+-	{ PCI_DEVICE_ID_AMD_CS5536_IDE,		 0x40, ATA_UDMA5, },
+-	{ 0 }
 +enum {
-+	/* 1 when we prefer to use DMA if possible */
-+	PC_FLAG_DMA_RECOMMENDED	= (1 << 0),
-+	/* 1 while DMA in progress */
-+	PC_FLAG_DMA_IN_PROGRESS	= (1 << 1),
-+	/* 1 when encountered problem during DMA */
-+	PC_FLAG_DMA_ERROR	= (1 << 2),
-+	/* Data direction */
-+	PC_FLAG_WRITING		= (1 << 3),
-+	/* Suppress error reporting */
-+	PC_FLAG_SUPPRESS_ERROR	= (1 << 4),
-+};
++	AMD_IDE_CONFIG		= 0x41,
++	AMD_CABLE_DETECT	= 0x42,
++	AMD_DRIVE_TIMING	= 0x48,
++	AMD_8BIT_TIMING		= 0x4e,
++	AMD_ADDRESS_SETUP	= 0x4c,
++	AMD_UDMA_TIMING		= 0x50,
+ };
+ 
+-static struct amd_ide_chip *amd_config;
+-static const struct ide_port_info *amd_chipset;
+ static unsigned int amd_80w;
+ static unsigned int amd_clock;
+ 
+ static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
+ static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
+ 
++static inline u8 amd_offset(struct pci_dev *dev)
++{
++	return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
++}
++
+ /*
+  * amd_set_speed() writes timing values to the chipset registers
+  */
+ 
+-static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
++static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
++			  struct ide_timing *timing)
+ {
+-	unsigned char t;
++	u8 t = 0, offset = amd_offset(dev);
+ 
+-	pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
++	pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
+ 	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+-	pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t);
++	pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
+ 
+-	pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)),
++	pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
+ 		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
+ 
+-	pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
++	pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
+ 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
+ 
+-	switch (amd_config->udma_mask) {
++	switch (udma_mask) {
+ 	case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+ 	case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
+ 	case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
+@@ -110,7 +70,7 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
+ 	default: return;
+ 	}
+ 
+-	pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
++	pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
+ }
+ 
+ /*
+@@ -120,12 +80,15 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
+ 
+ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
+ {
+-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
++	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
+ 	struct ide_timing t, p;
+ 	int T, UT;
++	u8 udma_mask = hwif->ultra_mask;
  
-+/* format capacities descriptor codes */
- #define CAPACITY_INVALID	0x00
- #define CAPACITY_UNFORMATTED	0x01
- #define CAPACITY_CURRENT	0x02
- #define CAPACITY_NO_CARTRIDGE	0x03
+ 	T = 1000000000 / amd_clock;
+-	UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
++	UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
  
- /*
-- *	Most of our global data which we need to save even as we leave the
-- *	driver due to an interrupt or a timer event is stored in a variable
-- *	of type idefloppy_floppy_t, defined below.
-+ * Most of our global data which we need to save even as we leave the driver
-+ * due to an interrupt or a timer event is stored in a variable of type
-+ * idefloppy_floppy_t, defined below.
-  */
- typedef struct ide_floppy_obj {
- 	ide_drive_t	*drive;
-@@ -295,23 +142,19 @@ typedef struct ide_floppy_obj {
- 	/* We implement a circular array */
- 	int rq_stack_index;
+ 	ide_timing_compute(drive, speed, &t, T, UT);
  
--	/*
--	 *	Last error information
--	 */
-+	/* Last error information */
- 	u8 sense_key, asc, ascq;
- 	/* delay this long before sending packet command */
- 	u8 ticks;
- 	int progress_indication;
+@@ -137,7 +100,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
+ 	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
+ 	if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
  
--	/*
--	 *	Device information
--	 */
-+	/* Device information */
- 	/* Current format */
- 	int blocks, block_size, bs_factor;
--	/* Last format capacity */
--	idefloppy_capacity_descriptor_t capacity;
-+	/* Last format capacity descriptor */
-+	u8 cap_desc[8];
- 	/* Copy of the flexible disk page */
--	idefloppy_flexible_disk_page_t flexible_disk_page;
-+	u8 flexible_disk_page[32];
- 	/* Write protect */
- 	int wp;
- 	/* Supports format progress report */
-@@ -322,85 +165,40 @@ typedef struct ide_floppy_obj {
+-	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
++	amd_set_speed(dev, drive->dn, udma_mask, &t);
+ }
  
- #define IDEFLOPPY_TICKS_DELAY	HZ/20	/* default delay for ZIP 100 (50ms) */
+ /*
+@@ -149,67 +112,68 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	amd_set_drive(drive, XFER_PIO_0 + pio);
+ }
  
 -/*
-- *	Floppy flag bits values.
-- */
--#define IDEFLOPPY_DRQ_INTERRUPT		0	/* DRQ interrupt device */
--#define IDEFLOPPY_MEDIA_CHANGED		1	/* Media may have changed */
--#define IDEFLOPPY_USE_READ12		2	/* Use READ12/WRITE12 or READ10/WRITE10 */
--#define	IDEFLOPPY_FORMAT_IN_PROGRESS	3	/* Format in progress */
--#define IDEFLOPPY_CLIK_DRIVE	        4       /* Avoid commands not supported in Clik drive */
--#define IDEFLOPPY_ZIP_DRIVE		5	/* Requires BH algorithm for packets */
--
--/*
-- *	ATAPI floppy drive packet commands
+- * The initialization callback. Here we determine the IDE chip type
+- * and initialize its drive independent registers.
 - */
--#define IDEFLOPPY_FORMAT_UNIT_CMD	0x04
--#define IDEFLOPPY_INQUIRY_CMD		0x12
--#define IDEFLOPPY_MODE_SELECT_CMD	0x55
--#define IDEFLOPPY_MODE_SENSE_CMD	0x5a
--#define IDEFLOPPY_READ10_CMD		0x28
--#define IDEFLOPPY_READ12_CMD		0xa8
--#define IDEFLOPPY_READ_CAPACITY_CMD	0x23
--#define IDEFLOPPY_REQUEST_SENSE_CMD	0x03
--#define IDEFLOPPY_PREVENT_REMOVAL_CMD	0x1e
--#define IDEFLOPPY_SEEK_CMD		0x2b
--#define IDEFLOPPY_START_STOP_CMD	0x1b
--#define IDEFLOPPY_TEST_UNIT_READY_CMD	0x00
--#define IDEFLOPPY_VERIFY_CMD		0x2f
--#define IDEFLOPPY_WRITE10_CMD		0x2a
--#define IDEFLOPPY_WRITE12_CMD		0xaa
--#define IDEFLOPPY_WRITE_VERIFY_CMD	0x2e
-+/* Floppy flag bits values. */
-+enum {
-+	/* DRQ interrupt device */
-+	IDEFLOPPY_FLAG_DRQ_INTERRUPT		= (1 <<	0),
-+	/* Media may have changed */
-+	IDEFLOPPY_FLAG_MEDIA_CHANGED		= (1 << 1),
-+	/* Format in progress */
-+	IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS	= (1 << 2),
-+	/* Avoid commands not supported in Clik drive */
-+	IDEFLOPPY_FLAG_CLIK_DRIVE		= (1 << 3),
-+	/* Requires BH algorithm for packets */
-+	IDEFLOPPY_FLAG_ZIP_DRIVE		= (1 << 4),
-+};
++static void __devinit amd7409_cable_detect(struct pci_dev *dev,
++					   const char *name)
++{
++	/* no host side cable detection */
++	amd_80w = 0x03;
++}
  
--/*
-- *	Defines for the mode sense command
-- */
-+/* Defines for the MODE SENSE command */
- #define MODE_SENSE_CURRENT		0x00
- #define MODE_SENSE_CHANGEABLE		0x01
--#define MODE_SENSE_DEFAULT		0x02 
-+#define MODE_SENSE_DEFAULT		0x02
- #define MODE_SENSE_SAVED		0x03
+-static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const char *name)
++static void __devinit amd7411_cable_detect(struct pci_dev *dev,
++					   const char *name)
+ {
+-	unsigned char t;
+-	unsigned int u;
+ 	int i;
++	u32 u = 0;
++	u8 t = 0, offset = amd_offset(dev);
++
++	pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
++	pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
++	amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
++	for (i = 24; i >= 0; i -= 8)
++		if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
++			printk(KERN_WARNING "%s: BIOS didn't set cable bits "
++					    "correctly. Enabling workaround.\n",
++					    name);
++			amd_80w |= (1 << (1 - (i >> 4)));
++		}
++}
  
--/*
-- *	IOCTLs used in low-level formatting.
-- */
--
-+/* IOCTLs used in low-level formatting. */
- #define	IDEFLOPPY_IOCTL_FORMAT_SUPPORTED	0x4600
- #define	IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY	0x4601
- #define	IDEFLOPPY_IOCTL_FORMAT_START		0x4602
- #define IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS	0x4603
+ /*
+- * Check for bad SWDMA.
++ * The initialization callback.  Initialize drive independent registers.
+  */
  
--#if 0
--/*
-- *	Special requests for our block device strategy routine.
-- */
--#define	IDEFLOPPY_FIRST_RQ	90
--
--/*
-- * 	IDEFLOPPY_PC_RQ is used to queue a packet command in the request queue.
-- */
--#define	IDEFLOPPY_PC_RQ		90
--
--#define IDEFLOPPY_LAST_RQ	90
--
--/*
-- *	A macro which can be used to check if a given request command
-- *	originated in the driver or in the buffer cache layer.
-- */
--#define IDEFLOPPY_RQ_CMD(cmd) 	((cmd >= IDEFLOPPY_FIRST_RQ) && (cmd <= IDEFLOPPY_LAST_RQ))
+-	if (amd_config->flags & AMD_CHECK_SWDMA) {
+-		if (dev->revision <= 7)
+-			amd_config->flags |= AMD_BAD_SWDMA;
+-	}
++static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
++						   const char *name)
++{
++	u8 t = 0, offset = amd_offset(dev);
+ 
+ /*
+  * Check 80-wire cable presence.
+  */
+ 
+-	switch (amd_config->udma_mask) {
 -
--#endif
+-		case ATA_UDMA6:
+-		case ATA_UDMA5:
+-			pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
+-			pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
+-			amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
+-			for (i = 24; i >= 0; i -= 8)
+-				if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
+-					printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n",
+-						amd_chipset->name);
+-					amd_80w |= (1 << (1 - (i >> 4)));
+-				}
+-			break;
 -
--/*
-- *	Error codes which are returned in rq->errors to the higher part
-- *	of the driver.
-- */
-+/* Error code returned in rq->errors to the higher part of the driver. */
- #define	IDEFLOPPY_ERROR_GENERAL		101
+-		case ATA_UDMA4:
+-			/* no host side cable detection */
+-			amd_80w = 0x03;
+-			break;
+-	}
++	if (dev->vendor == PCI_VENDOR_ID_AMD &&
++	    dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
++		; /* no UDMA > 2 */
++	else if (dev->vendor == PCI_VENDOR_ID_AMD &&
++		 dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
++		amd7409_cable_detect(dev, name);
++	else
++		amd7411_cable_detect(dev, name);
  
  /*
-- *	The following is used to format the general configuration word of
-- *	the ATAPI IDENTIFY DEVICE command.
-+ * The following is used to format the general configuration word of the
-+ * ATAPI IDENTIFY DEVICE command.
+  * Take care of prefetch & postwrite.
   */
--struct idefloppy_id_gcw {	
-+struct idefloppy_id_gcw {
- #if defined(__LITTLE_ENDIAN_BITFIELD)
- 	unsigned packet_size		:2;	/* Packet Size */
- 	unsigned reserved234		:3;	/* Reserved */
-@@ -423,103 +221,12 @@ struct idefloppy_id_gcw {
- };
  
- /*
-- *	INQUIRY packet command - Data Format
-- */
--typedef struct {
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	device_type	:5;	/* Peripheral Device Type */
--	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */
--	unsigned	reserved1_6t0	:7;	/* Reserved */
--	unsigned	rmb		:1;	/* Removable Medium Bit */
--	unsigned	ansi_version	:3;	/* ANSI Version */
--	unsigned	ecma_version	:3;	/* ECMA Version */
--	unsigned	iso_version	:2;	/* ISO Version */
--	unsigned	response_format :4;	/* Response Data Format */
--	unsigned	reserved3_45	:2;	/* Reserved */
--	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */
--	unsigned	reserved3_7	:1;	/* AENC - Reserved */
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */
--	unsigned	device_type	:5;	/* Peripheral Device Type */
--	unsigned	rmb		:1;	/* Removable Medium Bit */
--	unsigned	reserved1_6t0	:7;	/* Reserved */
--	unsigned	iso_version	:2;	/* ISO Version */
--	unsigned	ecma_version	:3;	/* ECMA Version */
--	unsigned	ansi_version	:3;	/* ANSI Version */
--	unsigned	reserved3_7	:1;	/* AENC - Reserved */
--	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */
--	unsigned	reserved3_45	:2;	/* Reserved */
--	unsigned	response_format :4;	/* Response Data Format */
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u8		additional_length;	/* Additional Length (total_length-4) */
--	u8		rsv5, rsv6, rsv7;	/* Reserved */
--	u8		vendor_id[8];		/* Vendor Identification */
--	u8		product_id[16];		/* Product Identification */
--	u8		revision_level[4];	/* Revision Level */
--	u8		vendor_specific[20];	/* Vendor Specific - Optional */
--	u8		reserved56t95[40];	/* Reserved - Optional */
--						/* Additional information may be returned */
--} idefloppy_inquiry_result_t;
+-	pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
+-	pci_write_config_byte(dev, AMD_IDE_CONFIG,
+-		(amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
 -
 -/*
-- *	REQUEST SENSE packet command result - Data Format.
+- * Take care of incorrectly wired Serenade mainboards.
 - */
--typedef struct {
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	error_code	:7;	/* Current error (0x70) */
--	unsigned	valid		:1;	/* The information field conforms to SFF-8070i */
--	u8		reserved1	:8;	/* Reserved */
--	unsigned	sense_key	:4;	/* Sense Key */
--	unsigned	reserved2_4	:1;	/* Reserved */
--	unsigned	ili		:1;	/* Incorrect Length Indicator */
--	unsigned	reserved2_67	:2;
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	valid		:1;	/* The information field conforms to SFF-8070i */
--	unsigned	error_code	:7;	/* Current error (0x70) */
--	u8		reserved1	:8;	/* Reserved */
--	unsigned	reserved2_67	:2;
--	unsigned	ili		:1;	/* Incorrect Length Indicator */
--	unsigned	reserved2_4	:1;	/* Reserved */
--	unsigned	sense_key	:4;	/* Sense Key */
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u32		information __attribute__ ((packed));
--	u8		asl;			/* Additional sense length (n-7) */
--	u32		command_specific;	/* Additional command specific information */
--	u8		asc;			/* Additional Sense Code */
--	u8		ascq;			/* Additional Sense Code Qualifier */
--	u8		replaceable_unit_code;	/* Field Replaceable Unit Code */
--	u8		sksv[3];
--	u8		pad[2];			/* Padding to 20 bytes */
--} idefloppy_request_sense_result_t;
 -
--/*
-- *	Pages of the SELECT SENSE / MODE SENSE packet commands.
-+ * Pages of the SELECT SENSE / MODE SENSE packet commands.
-+ * See SFF-8070i spec.
-  */
- #define	IDEFLOPPY_CAPABILITIES_PAGE	0x1b
- #define IDEFLOPPY_FLEXIBLE_DISK_PAGE	0x05
+-	if ((amd_config->flags & AMD_CHECK_SERENADE) &&
+-		dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
+-		dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
+-			amd_config->udma_mask = ATA_UDMA5;
++	pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
++	/*
++	 * Check for broken FIFO support.
++	 */
++	if (dev->vendor == PCI_VENDOR_ID_AMD &&
++	    dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
++		t &= 0x0f;
++	else
++		t |= 0xf0;
++	pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
+ 
+ /*
+  * Determine the system bus clock.
+@@ -225,53 +189,44 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
+ 
+ 	if (amd_clock < 20000 || amd_clock > 50000) {
+ 		printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
+-			amd_chipset->name, amd_clock);
++				    name, amd_clock);
+ 		amd_clock = 33333;
+ 	}
  
 -/*
-- *	Mode Parameter Header for the MODE SENSE packet command
+- * Print the boot message.
 - */
--typedef struct {
--	u16		mode_data_length;	/* Length of the following data transfer */
--	u8		medium_type;		/* Medium Type */
--#if defined(__LITTLE_ENDIAN_BITFIELD)
--	unsigned	reserved3	:7;
--	unsigned	wp		:1;	/* Write protect */
--#elif defined(__BIG_ENDIAN_BITFIELD)
--	unsigned	wp		:1;	/* Write protect */
--	unsigned	reserved3	:7;
--#else
--#error "Bitfield endianness not defined! Check your byteorder.h"
--#endif
--	u8		reserved[4];
--} idefloppy_mode_parameter_header_t;
 -
- static DEFINE_MUTEX(idefloppy_ref_mutex);
- 
- #define to_ide_floppy(obj) container_of(obj, struct ide_floppy_obj, kref)
-@@ -539,39 +246,35 @@ static struct ide_floppy_obj *ide_floppy_get(struct gendisk *disk)
- 	return floppy;
+-	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
+-		amd_chipset->name, pci_name(dev), dev->revision,
+-		amd_dma[fls(amd_config->udma_mask) - 1]);
+-
+ 	return dev->irq;
  }
  
--static void ide_floppy_release(struct kref *);
-+static void idefloppy_cleanup_obj(struct kref *);
- 
- static void ide_floppy_put(struct ide_floppy_obj *floppy)
++static u8 __devinit amd_cable_detect(ide_hwif_t *hwif)
++{
++	if ((amd_80w >> hwif->channel) & 1)
++		return ATA_CBL_PATA80;
++	else
++		return ATA_CBL_PATA40;
++}
++
+ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
  {
- 	mutex_lock(&idefloppy_ref_mutex);
--	kref_put(&floppy->kref, ide_floppy_release);
-+	kref_put(&floppy->kref, idefloppy_cleanup_obj);
- 	mutex_unlock(&idefloppy_ref_mutex);
- }
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++
+ 	if (hwif->irq == 0) /* 0 is bogus but will do for now */
+-		hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel);
++		hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
  
- /*
-- *	Too bad. The drive wants to send us data which we are not ready to accept.
-- *	Just throw it away.
-+ * Too bad. The drive wants to send us data which we are not ready to accept.
-+ * Just throw it away.
-  */
--static void idefloppy_discard_data (ide_drive_t *drive, unsigned int bcount)
-+static void idefloppy_discard_data(ide_drive_t *drive, unsigned int bcount)
- {
- 	while (bcount--)
- 		(void) HWIF(drive)->INB(IDE_DATA_REG);
+ 	hwif->set_pio_mode = &amd_set_pio_mode;
+ 	hwif->set_dma_mode = &amd_set_drive;
+ 
+-	if (!hwif->dma_base)
+-		return;
+-
+-	hwif->ultra_mask = amd_config->udma_mask;
+-	if (amd_config->flags & AMD_BAD_SWDMA)
+-		hwif->swdma_mask = 0x00;
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+-		if ((amd_80w >> hwif->channel) & 1)
+-			hwif->cbl = ATA_CBL_PATA80;
+-		else
+-			hwif->cbl = ATA_CBL_PATA40;
+-	}
++	hwif->cable_detect = amd_cable_detect;
  }
  
--#if IDEFLOPPY_DEBUG_BUGS
--static void idefloppy_write_zeros (ide_drive_t *drive, unsigned int bcount)
-+static void idefloppy_write_zeros(ide_drive_t *drive, unsigned int bcount)
+ #define IDE_HFLAGS_AMD \
+ 	(IDE_HFLAG_PIO_NO_BLACKLIST | \
+ 	 IDE_HFLAG_PIO_NO_DOWNGRADE | \
++	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
+ 	 IDE_HFLAG_POST_SET_MODE | \
+ 	 IDE_HFLAG_IO_32BIT | \
+ 	 IDE_HFLAG_UNMASK_IRQS | \
+ 	 IDE_HFLAG_BOOTABLE)
+ 
+-#define DECLARE_AMD_DEV(name_str)					\
++#define DECLARE_AMD_DEV(name_str, swdma, udma)				\
+ 	{								\
+ 		.name		= name_str,				\
+ 		.init_chipset	= init_chipset_amd74xx,			\
+@@ -279,11 +234,12 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+ 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},	\
+ 		.host_flags	= IDE_HFLAGS_AMD,			\
+ 		.pio_mask	= ATA_PIO5,				\
+-		.swdma_mask	= ATA_SWDMA2,				\
++		.swdma_mask	= swdma,				\
+ 		.mwdma_mask	= ATA_MWDMA2,				\
++		.udma_mask	= udma,					\
+ 	}
+ 
+-#define DECLARE_NV_DEV(name_str)					\
++#define DECLARE_NV_DEV(name_str, udma)					\
+ 	{								\
+ 		.name		= name_str,				\
+ 		.init_chipset	= init_chipset_amd74xx,			\
+@@ -293,45 +249,62 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
+ 		.pio_mask	= ATA_PIO5,				\
+ 		.swdma_mask	= ATA_SWDMA2,				\
+ 		.mwdma_mask	= ATA_MWDMA2,				\
++		.udma_mask	= udma,					\
+ 	}
+ 
+ static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
+-	/*  0 */ DECLARE_AMD_DEV("AMD7401"),
+-	/*  1 */ DECLARE_AMD_DEV("AMD7409"),
+-	/*  2 */ DECLARE_AMD_DEV("AMD7411"),
+-	/*  3 */ DECLARE_AMD_DEV("AMD7441"),
+-	/*  4 */ DECLARE_AMD_DEV("AMD8111"),
+-
+-	/*  5 */ DECLARE_NV_DEV("NFORCE"),
+-	/*  6 */ DECLARE_NV_DEV("NFORCE2"),
+-	/*  7 */ DECLARE_NV_DEV("NFORCE2-U400R"),
+-	/*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA"),
+-	/*  9 */ DECLARE_NV_DEV("NFORCE3-150"),
+-	/* 10 */ DECLARE_NV_DEV("NFORCE3-250"),
+-	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"),
+-	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
+-	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
+-	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
+-	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
+-	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
+-	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
+-	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
+-	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
+-	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
+-	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
+-	/* 22 */ DECLARE_AMD_DEV("AMD5536"),
++	/*  0 */ DECLARE_AMD_DEV("AMD7401",	  0x00, ATA_UDMA2),
++	/*  1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4),
++	/*  2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5),
++	/*  3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5),
++	/*  4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6),
++
++	/*  5 */ DECLARE_NV_DEV("NFORCE",		ATA_UDMA5),
++	/*  6 */ DECLARE_NV_DEV("NFORCE2",		ATA_UDMA6),
++	/*  7 */ DECLARE_NV_DEV("NFORCE2-U400R",	ATA_UDMA6),
++	/*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA",	ATA_UDMA6),
++	/*  9 */ DECLARE_NV_DEV("NFORCE3-150",		ATA_UDMA6),
++	/* 10 */ DECLARE_NV_DEV("NFORCE3-250",		ATA_UDMA6),
++	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA",	ATA_UDMA6),
++	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2",	ATA_UDMA6),
++	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804",		ATA_UDMA6),
++	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04",		ATA_UDMA6),
++	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51",		ATA_UDMA6),
++	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55",		ATA_UDMA6),
++	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61",		ATA_UDMA6),
++	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65",		ATA_UDMA6),
++	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67",		ATA_UDMA6),
++	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73",		ATA_UDMA6),
++	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77",		ATA_UDMA6),
++
++	/* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5),
+ };
+ 
+ static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
  {
- 	while (bcount--)
- 		HWIF(drive)->OUTB(0, IDE_DATA_REG);
+-	amd_chipset = amd74xx_chipsets + id->driver_data;
+-	amd_config = amd_ide_chips + id->driver_data;
+-	if (dev->device != amd_config->id) {
+-		printk(KERN_ERR "%s: assertion 0x%02x == 0x%02x failed !\n",
+-		       pci_name(dev), dev->device, amd_config->id);
+-		return -ENODEV;
++	struct ide_port_info d;
++	u8 idx = id->driver_data;
++
++	d = amd74xx_chipsets[idx];
++
++	/*
++	 * Check for bad SWDMA and incorrectly wired Serenade mainboards.
++	 */
++	if (idx == 1) {
++		if (dev->revision <= 7)
++			d.swdma_mask = 0;
++		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
++	} else if (idx == 4) {
++		if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
++		    dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
++			d.udma_mask = ATA_UDMA5;
+ 	}
+-	return ide_setup_pci_device(dev, amd_chipset);
++
++	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
++			 d.name, pci_name(dev), dev->revision,
++			 amd_dma[fls(d.udma_mask) - 1]);
++
++	return ide_setup_pci_device(dev, &d);
  }
--#endif /* IDEFLOPPY_DEBUG_BUGS */
- 
  
+ static const struct pci_device_id amd74xx_pci_tbl[] = {
+diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
+index ef8e016..7e037c8 100644
+--- a/drivers/ide/pci/atiixp.c
++++ b/drivers/ide/pci/atiixp.c
+@@ -1,6 +1,4 @@
  /*
-- *	idefloppy_do_end_request is used to finish servicing a request.
+- *  linux/drivers/ide/pci/atiixp.c	Version 0.03	Aug 3 2007
 - *
-- *	For read/write requests, we will call ide_end_request to pass to the
-- *	next buffer.
-+ * Used to finish servicing a request. For read/write requests, we will call
-+ * ide_end_request to pass to the next buffer.
+  *  Copyright (C) 2003 ATI Inc. <hyu at ati.com>
+  *  Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
   */
- static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
- {
-@@ -579,12 +282,12 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
- 	struct request *rq = HWGROUP(drive)->rq;
- 	int error;
+@@ -8,15 +6,11 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/ioport.h>
+ #include <linux/pci.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+-#include <linux/delay.h>
+ #include <linux/init.h>
  
--	debug_log(KERN_INFO "Reached idefloppy_end_request\n");
-+	debug_log("Reached %s\n", __func__);
+-#include <asm/io.h>
+-
+ #define ATIIXP_IDE_PIO_TIMING		0x40
+ #define ATIIXP_IDE_MDMA_TIMING		0x44
+ #define ATIIXP_IDE_PIO_CONTROL		0x48
+@@ -43,47 +37,8 @@ static atiixp_ide_timing mdma_timing[] = {
+ 	{ 0x02, 0x00 },
+ };
  
- 	switch (uptodate) {
--		case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
--		case 1: error = 0; break;
--		default: error = uptodate;
-+	case 0: error = IDEFLOPPY_ERROR_GENERAL; break;
-+	case 1: error = 0; break;
-+	default: error = uptodate;
- 	}
- 	if (error)
- 		floppy->failed_pc = NULL;
-@@ -602,39 +305,8 @@ static int idefloppy_do_end_request(ide_drive_t *drive, int uptodate, int nsecs)
- 	return 0;
- }
+-static int save_mdma_mode[4];
+-
+ static DEFINE_SPINLOCK(atiixp_lock);
  
--static void idefloppy_input_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
+-static void atiixp_dma_host_on(ide_drive_t *drive)
 -{
--	struct request *rq = pc->rq;
--	struct bio_vec *bvec;
--	struct req_iterator iter;
+-	struct pci_dev *dev = drive->hwif->pci_dev;
 -	unsigned long flags;
--	char *data;
--	int count, done = 0;
+-	u16 tmp16;
 -
--	rq_for_each_segment(bvec, rq, iter) {
--		if (!bcount)
--			break;
+-	spin_lock_irqsave(&atiixp_lock, flags);
 -
--		count = min(bvec->bv_len, bcount);
+-	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+-	if (save_mdma_mode[drive->dn])
+-		tmp16 &= ~(1 << drive->dn);
+-	else
+-		tmp16 |= (1 << drive->dn);
+-	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
 -
--		data = bvec_kmap_irq(bvec, &flags);
--		drive->hwif->atapi_input_bytes(drive, data, count);
--		bvec_kunmap_irq(data, &flags);
+-	spin_unlock_irqrestore(&atiixp_lock, flags);
 -
--		bcount -= count;
--		pc->b_count += count;
--		done += count;
--	}
+-	ide_dma_host_on(drive);
+-}
 -
--	idefloppy_do_end_request(drive, 1, done >> 9);
+-static void atiixp_dma_host_off(ide_drive_t *drive)
+-{
+-	struct pci_dev *dev = drive->hwif->pci_dev;
+-	unsigned long flags;
+-	u16 tmp16;
 -
--	if (bcount) {
--		printk(KERN_ERR "%s: leftover data in idefloppy_input_buffers, bcount == %d\n", drive->name, bcount);
--		idefloppy_discard_data(drive, bcount);
--	}
+-	spin_lock_irqsave(&atiixp_lock, flags);
+-
+-	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
+-	tmp16 &= ~(1 << drive->dn);
+-	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
+-
+-	spin_unlock_irqrestore(&atiixp_lock, flags);
+-
+-	ide_dma_host_off(drive);
 -}
 -
--static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, unsigned int bcount)
-+static void ide_floppy_io_buffers(ide_drive_t *drive, idefloppy_pc_t *pc,
-+				  unsigned int bcount, int direction)
- {
- 	struct request *rq = pc->rq;
- 	struct req_iterator iter;
-@@ -650,7 +322,10 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
- 		count = min(bvec->bv_len, bcount);
- 
- 		data = bvec_kmap_irq(bvec, &flags);
--		drive->hwif->atapi_output_bytes(drive, data, count);
-+		if (direction)
-+			drive->hwif->atapi_output_bytes(drive, data, count);
-+		else
-+			drive->hwif->atapi_input_bytes(drive, data, count);
- 		bvec_kunmap_irq(data, &flags);
- 
- 		bcount -= count;
-@@ -660,15 +335,18 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
- 
- 	idefloppy_do_end_request(drive, 1, done >> 9);
- 
--#if IDEFLOPPY_DEBUG_BUGS
- 	if (bcount) {
--		printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
--		idefloppy_write_zeros(drive, bcount);
-+		printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
-+				drive->name, __func__, bcount);
-+		if (direction)
-+			idefloppy_write_zeros(drive, bcount);
-+		else
-+			idefloppy_discard_data(drive, bcount);
-+
- 	}
--#endif
- }
- 
--static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
-+static void idefloppy_update_buffers(ide_drive_t *drive, idefloppy_pc_t *pc)
- {
- 	struct request *rq = pc->rq;
- 	struct bio *bio = rq->bio;
-@@ -678,11 +356,12 @@ static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
- }
+ /**
+  *	atiixp_set_pio_mode	-	set host controller for PIO mode
+  *	@drive: drive
+@@ -94,7 +49,7 @@ static void atiixp_dma_host_off(ide_drive_t *drive)
  
- /*
-- *	idefloppy_queue_pc_head generates a new packet command request in front
-- *	of the request queue, before the current request, so that it will be
-- *	processed immediately, on the next pass through the driver.
-+ * Generate a new packet command request in front of the request queue, before
-+ * the current request so that it will be processed immediately, on the next
-+ * pass through the driver.
-  */
--static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struct request *rq)
-+static void idefloppy_queue_pc_head(ide_drive_t *drive, idefloppy_pc_t *pc,
-+		struct request *rq)
+ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
  {
- 	struct ide_floppy_obj *floppy = drive->driver_data;
- 
-@@ -693,16 +372,16 @@ static void idefloppy_queue_pc_head (ide_drive_t *drive,idefloppy_pc_t *pc,struc
- 	(void) ide_do_drive_cmd(drive, rq, ide_preempt);
- }
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	unsigned long flags;
+ 	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+ 	u32 pio_timing_data;
+@@ -127,37 +82,54 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
  
--static idefloppy_pc_t *idefloppy_next_pc_storage (ide_drive_t *drive)
-+static idefloppy_pc_t *idefloppy_next_pc_storage(ide_drive_t *drive)
+ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	unsigned long flags;
+ 	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
+ 	u32 tmp32;
+ 	u16 tmp16;
+-
+-	if (speed < XFER_MW_DMA_0)
+-		return;
++	u16 udma_ctl = 0;
  
- 	if (floppy->pc_stack_index == IDEFLOPPY_PC_STACK)
--		floppy->pc_stack_index=0;
-+		floppy->pc_stack_index = 0;
- 	return (&floppy->pc_stack[floppy->pc_stack_index++]);
- }
+ 	spin_lock_irqsave(&atiixp_lock, flags);
  
--static struct request *idefloppy_next_rq_storage (ide_drive_t *drive)
-+static struct request *idefloppy_next_rq_storage(ide_drive_t *drive)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
+-	save_mdma_mode[drive->dn] = 0;
++	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl);
++
+ 	if (speed >= XFER_UDMA_0) {
+ 		pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
+ 		tmp16 &= ~(0x07 << (drive->dn * 4));
+ 		tmp16 |= ((speed & 0x07) << (drive->dn * 4));
+ 		pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
+-	} else {
+-		if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) {
+-			save_mdma_mode[drive->dn] = speed;
+-			pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
+-			tmp32 &= ~(0xff << timing_shift);
+-			tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) |
+-				(mdma_timing[speed & 0x03].command_width << (timing_shift + 4));
+-			pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
+-		}
++
++		udma_ctl |= (1 << drive->dn);
++	} else if (speed >= XFER_MW_DMA_0) {
++		u8 i = speed & 0x03;
++
++		pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
++		tmp32 &= ~(0xff << timing_shift);
++		tmp32 |= (mdma_timing[i].recover_width << timing_shift) |
++			 (mdma_timing[i].command_width << (timing_shift + 4));
++		pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
++
++		udma_ctl &= ~(1 << drive->dn);
+ 	}
  
-@@ -711,60 +390,53 @@ static struct request *idefloppy_next_rq_storage (ide_drive_t *drive)
- 	return (&floppy->rq_stack[floppy->rq_stack_index++]);
++	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl);
++
+ 	spin_unlock_irqrestore(&atiixp_lock, flags);
  }
  
--/*
-- *	idefloppy_analyze_error is called on each failed packet command retry
-- *	to analyze the request sense.
-- */
--static void idefloppy_analyze_error (ide_drive_t *drive,idefloppy_request_sense_result_t *result)
-+static void idefloppy_request_sense_callback(ide_drive_t *drive)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
-+	u8 *buf = floppy->pc->buffer;
- 
--	floppy->sense_key = result->sense_key;
--	floppy->asc = result->asc;
--	floppy->ascq = result->ascq;
--	floppy->progress_indication = result->sksv[0] & 0x80 ?
--		(u16)get_unaligned((u16 *)(result->sksv+1)):0x10000;
--	if (floppy->failed_pc)
--		debug_log(KERN_INFO "ide-floppy: pc = %x, sense key = %x, "
--			"asc = %x, ascq = %x\n", floppy->failed_pc->c[0],
--			result->sense_key, result->asc, result->ascq);
--	else
--		debug_log(KERN_INFO "ide-floppy: sense key = %x, asc = %x, "
--			"ascq = %x\n", result->sense_key,
--			result->asc, result->ascq);
--}
--
--static void idefloppy_request_sense_callback (ide_drive_t *drive)
--{
--	idefloppy_floppy_t *floppy = drive->driver_data;
-+	debug_log("Reached %s\n", __func__);
- 
--	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
--	
- 	if (!floppy->pc->error) {
--		idefloppy_analyze_error(drive,(idefloppy_request_sense_result_t *) floppy->pc->buffer);
-+		floppy->sense_key = buf[2] & 0x0F;
-+		floppy->asc = buf[12];
-+		floppy->ascq = buf[13];
-+		floppy->progress_indication = buf[15] & 0x80 ?
-+			(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;
++static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif)
++{
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
++	u8 udma_mode = 0, ch = hwif->channel;
 +
-+		if (floppy->failed_pc)
-+			debug_log("pc = %x, sense key = %x, asc = %x,"
-+					" ascq = %x\n",
-+					floppy->failed_pc->c[0],
-+					floppy->sense_key,
-+					floppy->asc,
-+					floppy->ascq);
-+		else
-+			debug_log("sense key = %x, asc = %x, ascq = %x\n",
-+					floppy->sense_key,
-+					floppy->asc,
-+					floppy->ascq);
++	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
 +
++	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
++		return ATA_CBL_PATA80;
++	else
++		return ATA_CBL_PATA40;
++}
 +
- 		idefloppy_do_end_request(drive, 1, 0);
- 	} else {
--		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting request!\n");
-+		printk(KERN_ERR "Error in REQUEST SENSE itself - Aborting"
-+				" request!\n");
- 		idefloppy_do_end_request(drive, 0, 0);
- 	}
- }
+ /**
+  *	init_hwif_atiixp		-	fill in the hwif for the ATIIXP
+  *	@hwif: IDE interface
+@@ -168,25 +140,10 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
  
--/*
-- *	General packet command callback function.
-- */
--static void idefloppy_pc_callback (ide_drive_t *drive)
-+/* General packet command callback function. */
-+static void idefloppy_pc_callback(ide_drive_t *drive)
+ static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
--	
--	debug_log(KERN_INFO "ide-floppy: Reached %s\n", __FUNCTION__);
-+
-+	debug_log("Reached %s\n", __func__);
+-	u8 udma_mode = 0;
+-	u8 ch = hwif->channel;
+-	struct pci_dev *pdev = hwif->pci_dev;
+-
+ 	hwif->set_pio_mode = &atiixp_set_pio_mode;
+ 	hwif->set_dma_mode = &atiixp_set_dma_mode;
  
- 	idefloppy_do_end_request(drive, floppy->pc->error ? 0 : 1, 0);
+-	if (!hwif->dma_base)
+-		return;
+-
+-	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
+-
+-	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
+-		hwif->cbl = ATA_CBL_PATA80;
+-	else
+-		hwif->cbl = ATA_CBL_PATA40;
+-
+-	hwif->dma_host_on = &atiixp_dma_host_on;
+-	hwif->dma_host_off = &atiixp_dma_host_off;
++	hwif->cable_detect = atiixp_cable_detect;
  }
  
--/*
-- *	idefloppy_init_pc initializes a packet command.
-- */
--static void idefloppy_init_pc (idefloppy_pc_t *pc)
-+static void idefloppy_init_pc(idefloppy_pc_t *pc)
- {
- 	memset(pc->c, 0, 12);
- 	pc->retries = 0;
-@@ -775,76 +447,75 @@ static void idefloppy_init_pc (idefloppy_pc_t *pc)
- 	pc->callback = &idefloppy_pc_callback;
- }
+ static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
+diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
+index 4aa4810..bd24dad 100644
+--- a/drivers/ide/pci/cmd640.c
++++ b/drivers/ide/pci/cmd640.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/pci/cmd640.c		Version 1.02  Sep 01, 1996
+- *
+  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
+  */
  
--static void idefloppy_create_request_sense_cmd (idefloppy_pc_t *pc)
-+static void idefloppy_create_request_sense_cmd(idefloppy_pc_t *pc)
- {
--	idefloppy_init_pc(pc);	
--	pc->c[0] = IDEFLOPPY_REQUEST_SENSE_CMD;
-+	idefloppy_init_pc(pc);
-+	pc->c[0] = GPCMD_REQUEST_SENSE;
- 	pc->c[4] = 255;
- 	pc->request_transfer = 18;
- 	pc->callback = &idefloppy_request_sense_callback;
+@@ -105,10 +103,6 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+@@ -705,10 +699,22 @@ static int pci_conf2(void)
+ 	return 0;
  }
  
++static const struct ide_port_info cmd640_port_info __initdata = {
++	.chipset		= ide_cmd640,
++	.host_flags		= IDE_HFLAG_SERIALIZE |
++				  IDE_HFLAG_NO_DMA |
++				  IDE_HFLAG_NO_AUTOTUNE |
++				  IDE_HFLAG_ABUSE_PREFETCH |
++				  IDE_HFLAG_ABUSE_FAST_DEVSEL,
++#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
++	.pio_mask		= ATA_PIO5,
++#endif
++};
++
  /*
-- *	idefloppy_retry_pc is called when an error was detected during the
-- *	last packet command. We queue a request sense packet command in
-- *	the head of the request list.
-+ * Called when an error was detected during the last packet command. We queue a
-+ * request sense packet command in the head of the request list.
+- * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
++ * Probe for a cmd640 chipset, and initialize it if found.
   */
--static void idefloppy_retry_pc (ide_drive_t *drive)
-+static void idefloppy_retry_pc(ide_drive_t *drive)
+-int __init ide_probe_for_cmd640x (void)
++static int __init cmd640x_init(void)
  {
- 	idefloppy_pc_t *pc;
- 	struct request *rq;
--	atapi_error_t error;
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+ 	int second_port_toggled = 0;
+@@ -717,6 +723,7 @@ int __init ide_probe_for_cmd640x (void)
+ 	const char *bus_type, *port2;
+ 	unsigned int index;
+ 	u8 b, cfr;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
  
--	error.all = HWIF(drive)->INB(IDE_ERROR_REG);
-+	(void)drive->hwif->INB(IDE_ERROR_REG);
- 	pc = idefloppy_next_pc_storage(drive);
- 	rq = idefloppy_next_rq_storage(drive);
- 	idefloppy_create_request_sense_cmd(pc);
- 	idefloppy_queue_pc_head(drive, pc, rq);
- }
+ 	if (cmd640_vlb && probe_for_cmd640_vlb()) {
+ 		bus_type = "VLB";
+@@ -761,14 +768,12 @@ int __init ide_probe_for_cmd640x (void)
+ 	setup_device_ptrs ();
+ 	printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
+ 	       cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
+-	cmd_hwif0->chipset = ide_cmd640;
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+-	cmd_hwif0->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
+-				IDE_HFLAG_ABUSE_FAST_DEVSEL;
+-	cmd_hwif0->pio_mask = ATA_PIO5;
+ 	cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
  
--/*
-- *	idefloppy_pc_intr is the usual interrupt handler which will be called
-- *	during a packet command.
-- */
-+/* The usual interrupt handler called during a packet command. */
- static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
--	atapi_status_t status;
--	atapi_bcount_t bcount;
--	atapi_ireason_t ireason;
-+	ide_hwif_t *hwif = drive->hwif;
- 	idefloppy_pc_t *pc = floppy->pc;
- 	struct request *rq = pc->rq;
-+	xfer_func_t *xferfunc;
- 	unsigned int temp;
--
--	debug_log(KERN_INFO "ide-floppy: Reached %s interrupt handler\n",
--		__FUNCTION__);
--
--	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
--		if (HWIF(drive)->ide_dma_end(drive)) {
--			set_bit(PC_DMA_ERROR, &pc->flags);
-+	int dma_error = 0;
-+	u16 bcount;
-+	u8 stat, ireason;
++	idx[0] = cmd_hwif0->index;
 +
-+	debug_log("Reached %s interrupt handler\n", __func__);
+ 	/*
+ 	 * Ensure compatibility by always using the slowest timings
+ 	 * for access to the drive's command register block,
+@@ -814,21 +819,14 @@ int __init ide_probe_for_cmd640x (void)
+ 	 * Initialize data for secondary cmd640 port, if enabled
+ 	 */
+ 	if (second_port_cmd640) {
+-		cmd_hwif0->serialized = 1;
+-		cmd_hwif1->serialized = 1;
+-		cmd_hwif1->chipset = ide_cmd640;
+-		cmd_hwif0->mate = cmd_hwif1;
+-		cmd_hwif1->mate = cmd_hwif0;
+-		cmd_hwif1->channel = 1;
+ #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
+-		cmd_hwif1->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
+-					IDE_HFLAG_ABUSE_FAST_DEVSEL;
+-		cmd_hwif1->pio_mask = ATA_PIO5;
+ 		cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
+ #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
 +
-+	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-+		dma_error = hwif->ide_dma_end(drive);
-+		if (dma_error) {
-+			printk(KERN_ERR "%s: DMA %s error\n", drive->name,
-+					rq_data_dir(rq) ? "write" : "read");
-+			pc->flags |= PC_FLAG_DMA_ERROR;
- 		} else {
- 			pc->actually_transferred = pc->request_transfer;
- 			idefloppy_update_buffers(drive, pc);
- 		}
--		debug_log(KERN_INFO "ide-floppy: DMA finished\n");
-+		debug_log("DMA finished\n");
++		idx[1] = cmd_hwif1->index;
  	}
+ 	printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
+-		cmd_hwif0->serialized ? "" : "not ", port2);
++			 second_port_cmd640 ? "" : "not ", port2);
  
- 	/* Clear the interrupt */
--	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
-+	stat = drive->hwif->INB(IDE_STATUS_REG);
+ 	/*
+ 	 * Establish initial timings/prefetch for all drives.
+@@ -872,6 +870,13 @@ int __init ide_probe_for_cmd640x (void)
+ #ifdef CMD640_DUMP_REGS
+ 	cmd640_dump_regs();
+ #endif
++
++	ide_device_add(idx, &cmd640_port_info);
++
+ 	return 1;
+ }
  
--	if (!status.b.drq) {			/* No more interrupts */
--		debug_log(KERN_INFO "Packet command completed, %d bytes "
--			"transferred\n", pc->actually_transferred);
--		clear_bit(PC_DMA_IN_PROGRESS, &pc->flags);
-+	/* No more interrupts */
-+	if ((stat & DRQ_STAT) == 0) {
-+		debug_log("Packet command completed, %d bytes transferred\n",
-+				pc->actually_transferred);
-+		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
++module_param_named(probe_vlb, cmd640_vlb, bool, 0);
++MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset");
++
++module_init(cmd640x_init);
+diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
+index bc55333..edabe62 100644
+--- a/drivers/ide/pci/cmd64x.c
++++ b/drivers/ide/pci/cmd64x.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/cmd64x.c		Version 1.52	Dec 24, 2007
+- *
+  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
+  *           Due to massive hardware bugs, UltraDMA is only supported
+  *           on the 646U2 and not on the 646U.
+@@ -15,15 +13,12 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
  
- 		local_irq_enable_in_hardirq();
+ #include <asm/io.h>
  
--		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {
-+		if ((stat & ERR_STAT) || (pc->flags & PC_FLAG_DMA_ERROR)) {
- 			/* Error detected */
--			debug_log(KERN_INFO "ide-floppy: %s: I/O error\n",
--				drive->name);
-+			debug_log("%s: I/O error\n", drive->name);
- 			rq->errors++;
--			if (pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
-+			if (pc->c[0] == GPCMD_REQUEST_SENSE) {
- 				printk(KERN_ERR "ide-floppy: I/O error in "
- 					"request sense command\n");
- 				return ide_do_reset(drive);
-@@ -862,7 +533,8 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
- 		return ide_stopped;
- 	}
+-#define DISPLAY_CMD64X_TIMINGS
+-
+ #define CMD_DEBUG 0
  
--	if (test_and_clear_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
-+	if (pc->flags & PC_FLAG_DMA_IN_PROGRESS) {
-+		pc->flags &= ~PC_FLAG_DMA_IN_PROGRESS;
- 		printk(KERN_ERR "ide-floppy: The floppy wants to issue "
- 			"more interrupts in DMA mode\n");
- 		ide_dma_off(drive);
-@@ -870,67 +542,60 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
- 	}
+ #if CMD_DEBUG
+@@ -37,11 +32,6 @@
+  */
+ #define CFR		0x50
+ #define   CFR_INTR_CH0		0x04
+-#define CNTRL		0x51
+-#define   CNTRL_ENA_1ST 	0x04
+-#define   CNTRL_ENA_2ND 	0x08
+-#define   CNTRL_DIS_RA0 	0x40
+-#define   CNTRL_DIS_RA1 	0x80
  
- 	/* Get the number of bytes to transfer */
--	bcount.b.high = HWIF(drive)->INB(IDE_BCOUNTH_REG);
--	bcount.b.low = HWIF(drive)->INB(IDE_BCOUNTL_REG);
-+	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
-+		  hwif->INB(IDE_BCOUNTL_REG);
- 	/* on this interrupt */
--	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
-+	ireason = hwif->INB(IDE_IREASON_REG);
+ #define	CMDTIM		0x52
+ #define	ARTTIM0		0x53
+@@ -60,108 +50,13 @@
+ #define MRDMODE		0x71
+ #define   MRDMODE_INTR_CH0	0x04
+ #define   MRDMODE_INTR_CH1	0x08
+-#define   MRDMODE_BLK_CH0	0x10
+-#define   MRDMODE_BLK_CH1	0x20
+-#define BMIDESR0	0x72
+ #define UDIDETCR0	0x73
+ #define DTPR0		0x74
+ #define BMIDECR1	0x78
+ #define BMIDECSR	0x79
+-#define BMIDESR1	0x7A
+ #define UDIDETCR1	0x7B
+ #define DTPR1		0x7C
  
--	if (ireason.b.cod) {
--		printk(KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
-+	if (ireason & CD) {
-+		printk(KERN_ERR "ide-floppy: CoD != 0 in %s\n", __func__);
- 		return ide_do_reset(drive);
- 	}
--	if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
-+	if (((ireason & IO) == IO) == !!(pc->flags & PC_FLAG_WRITING)) {
- 		/* Hopefully, we will never get here */
- 		printk(KERN_ERR "ide-floppy: We wanted to %s, ",
--			ireason.b.io ? "Write":"Read");
-+				(ireason & IO) ? "Write" : "Read");
- 		printk(KERN_ERR "but the floppy wants us to %s !\n",
--			ireason.b.io ? "Read":"Write");
-+				(ireason & IO) ? "Read" : "Write");
- 		return ide_do_reset(drive);
- 	}
--	if (!test_bit(PC_WRITING, &pc->flags)) {
-+	if (!(pc->flags & PC_FLAG_WRITING)) {
- 		/* Reading - Check that we have enough space */
--		temp = pc->actually_transferred + bcount.all;
-+		temp = pc->actually_transferred + bcount;
- 		if (temp > pc->request_transfer) {
- 			if (temp > pc->buffer_size) {
- 				printk(KERN_ERR "ide-floppy: The floppy wants "
- 					"to send us more data than expected "
- 					"- discarding data\n");
--				idefloppy_discard_data(drive,bcount.all);
--				BUG_ON(HWGROUP(drive)->handler != NULL);
-+				idefloppy_discard_data(drive, bcount);
-+
- 				ide_set_handler(drive,
- 						&idefloppy_pc_intr,
- 						IDEFLOPPY_WAIT_CMD,
- 						NULL);
- 				return ide_started;
- 			}
--			debug_log(KERN_NOTICE "ide-floppy: The floppy wants to "
--				"send us more data than expected - "
--				"allowing transfer\n");
-+			debug_log("The floppy wants to send us more data than"
-+					" expected - allowing transfer\n");
- 		}
- 	}
--	if (test_bit(PC_WRITING, &pc->flags)) {
--		if (pc->buffer != NULL)
--			/* Write the current buffer */
--			HWIF(drive)->atapi_output_bytes(drive,
--						pc->current_position,
--						bcount.all);
--		else
--			idefloppy_output_buffers(drive, pc, bcount.all);
--	} else {
--		if (pc->buffer != NULL)
--			/* Read the current buffer */
--			HWIF(drive)->atapi_input_bytes(drive,
--						pc->current_position,
--						bcount.all);
--		else
--			idefloppy_input_buffers(drive, pc, bcount.all);
+-#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
+-#include <linux/stat.h>
+-#include <linux/proc_fs.h>
+-
+-static u8 cmd64x_proc = 0;
+-
+-#define CMD_MAX_DEVS		5
+-
+-static struct pci_dev *cmd_devs[CMD_MAX_DEVS];
+-static int n_cmd_devs;
+-
+-static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
+-{
+-	char *p = buf;
+-	u8 reg72 = 0, reg73 = 0;			/* primary */
+-	u8 reg7a = 0, reg7b = 0;			/* secondary */
+-	u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;	/* extra */
+-
+-	p += sprintf(p, "\nController: %d\n", index);
+-	p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
+-
+-	(void) pci_read_config_byte(dev, CFR,       &reg50);
+-	(void) pci_read_config_byte(dev, CNTRL,     &reg51);
+-	(void) pci_read_config_byte(dev, ARTTIM23,  &reg57);
+-	(void) pci_read_config_byte(dev, MRDMODE,   &reg71);
+-	(void) pci_read_config_byte(dev, BMIDESR0,  &reg72);
+-	(void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
+-	(void) pci_read_config_byte(dev, BMIDESR1,  &reg7a);
+-	(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
+-
+-	/* PCI0643/6 originally didn't have the primary channel enable bit */
+-	if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
+-	    (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))
+-		reg51 |= CNTRL_ENA_1ST;
+-
+-	p += sprintf(p, "---------------- Primary Channel "
+-			"---------------- Secondary Channel ------------\n");
+-	p += sprintf(p, "                 %s                         %s\n",
+-		 (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled",
+-		 (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled");
+-	p += sprintf(p, "---------------- drive0 --------- drive1 "
+-			"-------- drive0 --------- drive1 ------\n");
+-	p += sprintf(p, "DMA enabled:     %s              %s"
+-			"             %s              %s\n",
+-		(reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ",
+-		(reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no ");
+-	p += sprintf(p, "UltraDMA mode:   %s (%c)          %s (%c)",
+-		( reg73 & 0x01) ? " on" : "off",
+-		((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') :
+-		((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') :
+-		((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') :
+-		((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?',
+-		( reg73 & 0x02) ? " on" : "off",
+-		((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') :
+-		((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') :
+-		((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') :
+-		((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?');
+-	p += sprintf(p, "         %s (%c)          %s (%c)\n",
+-		( reg7b & 0x01) ? " on" : "off",
+-		((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') :
+-		((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') :
+-		((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') :
+-		((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?',
+-		( reg7b & 0x02) ? " on" : "off",
+-		((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') :
+-		((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') :
+-		((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') :
+-		((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?');
+-	p += sprintf(p, "Interrupt:       %s, %s                 %s, %s\n",
+-		(reg71 & MRDMODE_BLK_CH0  ) ? "blocked" : "enabled",
+-		(reg50 & CFR_INTR_CH0	  ) ? "pending" : "clear  ",
+-		(reg71 & MRDMODE_BLK_CH1  ) ? "blocked" : "enabled",
+-		(reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear  ");
+-
+-	return (char *)p;
+-}
+-
+-static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
+-{
+-	char *p = buffer;
+-	int i;
+-
+-	for (i = 0; i < n_cmd_devs; i++) {
+-		struct pci_dev *dev	= cmd_devs[i];
+-		p = print_cmd64x_get_info(p, dev, i);
 -	}
-+	if (pc->flags & PC_FLAG_WRITING)
-+		xferfunc = hwif->atapi_output_bytes;
-+	else
-+		xferfunc = hwif->atapi_input_bytes;
-+
-+	if (pc->buffer)
-+		xferfunc(drive, pc->current_position, bcount);
-+	else
-+		ide_floppy_io_buffers(drive, pc, bcount,
-+				      !!(pc->flags & PC_FLAG_WRITING));
-+
- 	/* Update the current position */
--	pc->actually_transferred += bcount.all;
--	pc->current_position += bcount.all;
-+	pc->actually_transferred += bcount;
-+	pc->current_position += bcount;
- 
--	BUG_ON(HWGROUP(drive)->handler != NULL);
--	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
-+	/* And set the interrupt handler again */
-+	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
- 	return ide_started;
- }
- 
-@@ -939,24 +604,24 @@ static ide_startstop_t idefloppy_pc_intr (ide_drive_t *drive)
-  * It fails at high speeds on the Iomega ZIP drive, so there's a slower version
-  * for that drive below. The algorithm is chosen based on drive type
+-	return p-buffer;	/* => must be less than 4k! */
+-}
+-
+-#endif	/* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
+-
+ static u8 quantize_timing(int timing, int quant)
+ {
+ 	return (timing + quant - 1) / quant;
+@@ -173,7 +68,7 @@ static u8 quantize_timing(int timing, int quant)
   */
--static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
-+static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
+ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
  {
- 	ide_startstop_t startstop;
- 	idefloppy_floppy_t *floppy = drive->driver_data;
--	atapi_ireason_t ireason;
-+	u8 ireason;
+-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
+ 	int clock_time		= 1000 / system_bus_clock();
+ 	u8  cycle_count, active_count, recovery_count, drwtim;
+ 	static const u8 recovery_values[] =
+@@ -220,7 +115,7 @@ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_
+ static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	unsigned int cycle_time;
+ 	u8 setup_count, arttim = 0;
  
- 	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
- 		printk(KERN_ERR "ide-floppy: Strange, packet command "
- 				"initiated yet DRQ isn't asserted\n");
- 		return startstop;
- 	}
--	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
--	if (!ireason.b.cod || ireason.b.io) {
-+	ireason = drive->hwif->INB(IDE_IREASON_REG);
-+	if ((ireason & CD) == 0 || (ireason & IO)) {
- 		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while "
- 				"issuing a packet command\n");
- 		return ide_do_reset(drive);
- 	}
--	BUG_ON(HWGROUP(drive)->handler != NULL);
-+
- 	/* Set the interrupt routine */
- 	ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
- 	/* Send the actual packet */
-@@ -966,18 +631,16 @@ static ide_startstop_t idefloppy_transfer_pc (ide_drive_t *drive)
+@@ -285,7 +180,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 unit			= drive->dn & 0x01;
+ 	u8 regU = 0, pciU	= hwif->channel ? UDIDETCR1 : UDIDETCR0;
  
+@@ -322,8 +217,6 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	case XFER_MW_DMA_0:
+ 		program_cycle_times(drive, 480, 215);
+ 		break;
+-	default:
+-		return;
+ 	}
  
- /*
-- * What we have here is a classic case of a top half / bottom half
-- * interrupt service routine. In interrupt mode, the device sends
-- * an interrupt to signal it's ready to receive a packet. However,
-- * we need to delay about 2-3 ticks before issuing the packet or we
-- * gets in trouble.
-+ * What we have here is a classic case of a top half / bottom half interrupt
-+ * service routine. In interrupt mode, the device sends an interrupt to signal
-+ * that it is ready to receive a packet. However, we need to delay about 2-3
-+ * ticks before issuing the packet or we gets in trouble.
-  *
-- * So, follow carefully. transfer_pc1 is called as an interrupt (or
-- * directly). In either case, when the device says it's ready for a 
-- * packet, we schedule the packet transfer to occur about 2-3 ticks
-- * later in transfer_pc2.
-+ * So, follow carefully. transfer_pc1 is called as an interrupt (or directly).
-+ * In either case, when the device says it's ready for a packet, we schedule
-+ * the packet transfer to occur about 2-3 ticks later in transfer_pc2.
-  */
--static int idefloppy_transfer_pc2 (ide_drive_t *drive)
-+static int idefloppy_transfer_pc2(ide_drive_t *drive)
+ 	if (speed >= XFER_SW_DMA_0)
+@@ -333,14 +226,15 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ static int cmd648_ide_dma_end (ide_drive_t *drive)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
+ 	int err			= __ide_dma_end(drive);
+ 	u8  irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
+ 						  MRDMODE_INTR_CH0;
+-	u8  mrdmode		= inb(hwif->dma_master + 0x01);
++	u8  mrdmode		= inb(base + 1);
  
-@@ -987,24 +650,24 @@ static int idefloppy_transfer_pc2 (ide_drive_t *drive)
- 	return IDEFLOPPY_WAIT_CMD;
+ 	/* clear the interrupt bit */
+ 	outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
+-	     hwif->dma_master + 0x01);
++	     base + 1);
+ 
+ 	return err;
  }
+@@ -348,7 +242,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
+ static int cmd64x_ide_dma_end (ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
+ 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
+ 						  CFR_INTR_CH0;
+@@ -365,10 +259,11 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
+ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
+ 	u8 irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
+ 						  MRDMODE_INTR_CH0;
+ 	u8 dma_stat		= inb(hwif->dma_status);
+-	u8 mrdmode		= inb(hwif->dma_master + 0x01);
++	u8 mrdmode		= inb(base + 1);
  
--static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
-+static ide_startstop_t idefloppy_transfer_pc1(ide_drive_t *drive)
+ #ifdef DEBUG
+ 	printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
+@@ -387,7 +282,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
+ static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	ide_startstop_t startstop;
--	atapi_ireason_t ireason;
-+	u8 ireason;
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
+ 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
+ 						  CFR_INTR_CH0;
+@@ -472,22 +367,12 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
+ 	mrdmode &= ~0x30;
+ 	(void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
  
- 	if (ide_wait_stat(&startstop, drive, DRQ_STAT, BUSY_STAT, WAIT_READY)) {
- 		printk(KERN_ERR "ide-floppy: Strange, packet command "
- 				"initiated yet DRQ isn't asserted\n");
- 		return startstop;
- 	}
--	ireason.all = HWIF(drive)->INB(IDE_IREASON_REG);
--	if (!ireason.b.cod || ireason.b.io) {
-+	ireason = drive->hwif->INB(IDE_IREASON_REG);
-+	if ((ireason & CD) == 0 || (ireason & IO)) {
- 		printk(KERN_ERR "ide-floppy: (IO,CoD) != (0,1) "
- 				"while issuing a packet command\n");
- 		return ide_do_reset(drive);
- 	}
--	/* 
-+	/*
- 	 * The following delay solves a problem with ATAPI Zip 100 drives
- 	 * where the Busy flag was apparently being deasserted before the
- 	 * unit was ready to receive data. This was happening on a
-@@ -1012,112 +675,82 @@ static ide_startstop_t idefloppy_transfer_pc1 (ide_drive_t *drive)
- 	 * 40 and 50msec work well. idefloppy_pc_intr will not be actually
- 	 * used until after the packet is moved in about 50 msec.
- 	 */
--	BUG_ON(HWGROUP(drive)->handler != NULL);
--	ide_set_handler(drive, 
--	  &idefloppy_pc_intr, 		/* service routine for packet command */
--	  floppy->ticks,		/* wait this long before "failing" */
--	  &idefloppy_transfer_pc2);	/* fail == transfer_pc2 */
-+
-+	ide_set_handler(drive, &idefloppy_pc_intr, floppy->ticks,
-+			&idefloppy_transfer_pc2);
- 	return ide_started;
+-#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
+-
+-	cmd_devs[n_cmd_devs++] = dev;
+-
+-	if (!cmd64x_proc) {
+-		cmd64x_proc = 1;
+-		ide_pci_create_host_proc("cmd64x", cmd64x_get_info);
+-	}
+-#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */
+-
+ 	return 0;
  }
  
--/**
-- * idefloppy_should_report_error()
-- *
-- * Supresses error messages resulting from Medium not present
-- */
--static inline int idefloppy_should_report_error(idefloppy_floppy_t *floppy)
-+static void ide_floppy_report_error(idefloppy_floppy_t *floppy,
-+				    idefloppy_pc_t *pc)
+ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
  {
-+	/* supress error messages resulting from Medium not present */
- 	if (floppy->sense_key == 0x02 &&
- 	    floppy->asc       == 0x3a &&
- 	    floppy->ascq      == 0x00)
--		return 0;
--	return 1;
-+		return;
-+
-+	printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x, key = %2x, "
-+			"asc = %2x, ascq = %2x\n",
-+			floppy->drive->name, pc->c[0], floppy->sense_key,
-+			floppy->asc, floppy->ascq);
-+
- }
+-	struct pci_dev  *dev	= hwif->pci_dev;
++	struct pci_dev  *dev	= to_pci_dev(hwif->dev);
+ 	u8 bmidecsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
  
--/*
-- *	Issue a packet command
-- */
--static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *pc)
-+static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
-+		idefloppy_pc_t *pc)
+ 	switch (dev->device) {
+@@ -502,11 +387,13 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
+ 
+ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	ide_hwif_t *hwif = drive->hwif;
--	atapi_feature_t feature;
--	atapi_bcount_t bcount;
- 	ide_handler_t *pkt_xfer_routine;
--
--#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
--         and have lived on another thread's stack; that stack may have become
--         unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
--#if IDEFLOPPY_DEBUG_BUGS
--	if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
--	    pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
--		printk(KERN_ERR "ide-floppy: possible ide-floppy.c bug - "
--			"Two request sense in serial were issued\n");
--	}
--#endif /* IDEFLOPPY_DEBUG_BUGS */
--#endif
-+	u16 bcount;
-+	u8 dma;
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
  
- 	if (floppy->failed_pc == NULL &&
--	    pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
-+	    pc->c[0] != GPCMD_REQUEST_SENSE)
- 		floppy->failed_pc = pc;
- 	/* Set the current packet command */
- 	floppy->pc = pc;
+ 	hwif->set_pio_mode = &cmd64x_set_pio_mode;
+ 	hwif->set_dma_mode = &cmd64x_set_dma_mode;
  
--	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES ||
--	    test_bit(PC_ABORT, &pc->flags)) {
--		/*
--		 *	We will "abort" retrying a packet command in case
--		 *	a legitimate error code was received.
--		 */
--		if (!test_bit(PC_ABORT, &pc->flags)) {
--			if (!test_bit(PC_SUPPRESS_ERROR, &pc->flags)) {
--				if (idefloppy_should_report_error(floppy))
--					printk(KERN_ERR "ide-floppy: %s: I/O error, "
--					       "pc = %2x, key = %2x, "
--					       "asc = %2x, ascq = %2x\n",
--					       drive->name, pc->c[0],
--					       floppy->sense_key,
--					       floppy->asc, floppy->ascq);
--			}
--			/* Giving up */
--			pc->error = IDEFLOPPY_ERROR_GENERAL;
--		}
-+	if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) {
-+		if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR))
-+			ide_floppy_report_error(floppy, pc);
-+		/* Giving up */
-+		pc->error = IDEFLOPPY_ERROR_GENERAL;
++	hwif->cable_detect = ata66_cmd64x;
 +
- 		floppy->failed_pc = NULL;
- 		pc->callback(drive);
- 		return ide_stopped;
- 	}
- 
--	debug_log(KERN_INFO "Retry number - %d\n",pc->retries);
-+	debug_log("Retry number - %d\n", pc->retries);
- 
- 	pc->retries++;
- 	/* We haven't transferred any data yet */
- 	pc->actually_transferred = 0;
- 	pc->current_position = pc->buffer;
--	bcount.all = min(pc->request_transfer, 63 * 1024);
-+	bcount = min(pc->request_transfer, 63 * 1024);
+ 	if (!hwif->dma_base)
+ 		return;
  
--	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags))
-+	if (pc->flags & PC_FLAG_DMA_ERROR) {
-+		pc->flags &= ~PC_FLAG_DMA_ERROR;
- 		ide_dma_off(drive);
-+	}
-+	dma = 0;
+@@ -525,9 +412,6 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
+ 	if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5)
+ 		hwif->ultra_mask = 0x00;
  
--	feature.all = 0;
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = ata66_cmd64x(hwif);
 -
--	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
--		feature.b.dma = !hwif->dma_setup(drive);
-+	if ((pc->flags & PC_FLAG_DMA_RECOMMENDED) && drive->using_dma)
-+		dma = !hwif->dma_setup(drive);
+ 	switch (dev->device) {
+ 	case PCI_DEVICE_ID_CMD_648:
+ 	case PCI_DEVICE_ID_CMD_649:
+@@ -555,7 +439,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_cmd64x,
+ 		.init_hwif	= init_hwif_cmd64x,
+ 		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
+-		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
++				  IDE_HFLAG_ABUSE_PREFETCH |
++				  IDE_HFLAG_BOOTABLE,
+ 		.pio_mask	= ATA_PIO5,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= 0x00, /* no udma */
+diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
+index 0466462..0be1a82 100644
+--- a/drivers/ide/pci/cs5520.c
++++ b/drivers/ide/pci/cs5520.c
+@@ -35,22 +35,12 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+-
+-#include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
+ #include <linux/ide.h>
+ #include <linux/dma-mapping.h>
  
--	if (IDE_CONTROL_REG)
--		HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
--	/* Use PIO/DMA */
--	HWIF(drive)->OUTB(feature.all, IDE_FEATURE_REG);
--	HWIF(drive)->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
--	HWIF(drive)->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
--	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
-+	ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
-+			   IDE_TFLAG_OUT_DEVICE, bcount, dma);
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-
+ struct pio_clocks
+ {
+ 	int address;
+@@ -69,9 +59,8 @@ static struct pio_clocks cs5520_pio_clocks[]={
+ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct pci_dev *pdev = hwif->pci_dev;
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ 	int controller = drive->dn > 1 ? 1 : 0;
+-	u8 reg;
  
--	if (feature.b.dma) {	/* Begin DMA, if necessary */
--		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
-+	if (dma) {
-+		/* Begin DMA, if necessary */
-+		pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
- 		hwif->dma_start(drive);
- 	}
+ 	/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
  
- 	/* Can we transfer the packet when we get the interrupt or wait? */
--	if (test_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags)) {
-+	if (floppy->flags & IDEFLOPPY_FLAG_ZIP_DRIVE) {
- 		/* wait */
- 		pkt_xfer_routine = &idefloppy_transfer_pc1;
- 	} else {
-@@ -1125,7 +758,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
- 		pkt_xfer_routine = &idefloppy_transfer_pc;
- 	}
- 	
--	if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
-+	if (floppy->flags & IDEFLOPPY_FLAG_DRQ_INTERRUPT) {
- 		/* Issue the packet command */
- 		ide_execute_command(drive, WIN_PACKETCMD,
- 				pkt_xfer_routine,
-@@ -1139,38 +772,37 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
- 	}
+@@ -91,11 +80,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
+ 		(cs5520_pio_clocks[pio].recovery << 4) |
+ 		(cs5520_pio_clocks[pio].assert));
+-		
+-	/* Set the DMA enable/disable flag */
+-	reg = inb(hwif->dma_base + 0x02 + 8*controller);
+-	reg |= 1<<((drive->dn&1)+5);
+-	outb(reg, hwif->dma_base + 0x02 + 8*controller);
  }
  
--static void idefloppy_rw_callback (ide_drive_t *drive)
-+static void idefloppy_rw_callback(ide_drive_t *drive)
+ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
+@@ -109,13 +93,14 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
+  *	We wrap the DMA activate to set the vdma flag. This is needed
+  *	so that the IDE DMA layer issues PIO not DMA commands over the
+  *	DMA channel
++ *
++ *	ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA
+  */
+- 
+-static int cs5520_dma_on(ide_drive_t *drive)
++
++static void cs5520_dma_host_set(ide_drive_t *drive, int on)
  {
--	debug_log(KERN_INFO "ide-floppy: Reached idefloppy_rw_callback\n");
-+	debug_log("Reached %s\n", __func__);
- 
- 	idefloppy_do_end_request(drive, 1, 0);
- 	return;
+-	/* ATAPI is harder so leave it for now */
+-	drive->vdma = 1;
+-	return 0;
++	drive->vdma = on;
++	ide_dma_host_set(drive, on);
  }
  
--static void idefloppy_create_prevent_cmd (idefloppy_pc_t *pc, int prevent)
-+static void idefloppy_create_prevent_cmd(idefloppy_pc_t *pc, int prevent)
- {
--	debug_log(KERN_INFO "ide-floppy: creating prevent removal command, "
--		"prevent = %d\n", prevent);
-+	debug_log("creating prevent removal command, prevent = %d\n", prevent);
+ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+@@ -126,7 +111,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+ 	if (hwif->dma_base == 0)
+ 		return;
  
- 	idefloppy_init_pc(pc);
--	pc->c[0] = IDEFLOPPY_PREVENT_REMOVAL_CMD;
-+	pc->c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
- 	pc->c[4] = prevent;
+-	hwif->ide_dma_on = &cs5520_dma_on;
++	hwif->dma_host_set = &cs5520_dma_host_set;
  }
  
--static void idefloppy_create_read_capacity_cmd (idefloppy_pc_t *pc)
-+static void idefloppy_create_read_capacity_cmd(idefloppy_pc_t *pc)
- {
- 	idefloppy_init_pc(pc);
--	pc->c[0] = IDEFLOPPY_READ_CAPACITY_CMD;
-+	pc->c[0] = GPCMD_READ_FORMAT_CAPACITIES;
- 	pc->c[7] = 255;
- 	pc->c[8] = 255;
- 	pc->request_transfer = 255;
- }
+ #define DECLARE_CS_DEV(name_str)				\
+@@ -137,6 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
+ 				  IDE_HFLAG_CS5520 |		\
+ 				  IDE_HFLAG_VDMA |		\
+ 				  IDE_HFLAG_NO_ATAPI_DMA |	\
++				  IDE_HFLAG_ABUSE_SET_DMA_MODE |\
+ 				  IDE_HFLAG_BOOTABLE,		\
+ 		.pio_mask	= ATA_PIO4,			\
+ 	}
+@@ -160,8 +146,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
+ 	ide_setup_pci_noise(dev, d);
  
--static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,
-+static void idefloppy_create_format_unit_cmd(idefloppy_pc_t *pc, int b, int l,
- 					      int flags)
- {
- 	idefloppy_init_pc(pc);
--	pc->c[0] = IDEFLOPPY_FORMAT_UNIT_CMD;
-+	pc->c[0] = GPCMD_FORMAT_UNIT;
- 	pc->c[1] = 0x17;
+ 	/* We must not grab the entire device, it has 'ISA' space in its
+-	   BARS too and we will freak out other bits of the kernel */
+-	if (pci_enable_device_bars(dev, 1<<2)) {
++	 * BARS too and we will freak out other bits of the kernel
++	 *
++	 * pci_enable_device_bars() is going away. I replaced it with
++	 * IO only enable for now but I'll need confirmation this is
++	 * allright for that device. If not, it will need some kind of
++	 * quirk. --BenH.
++	 */
++	if (pci_enable_device_io(dev)) {
+ 		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
+ 		return -ENODEV;
+ 	}
+@@ -178,7 +170,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
  
- 	memset(pc->buffer, 0, 12);
-@@ -1181,83 +813,79 @@ static void idefloppy_create_format_unit_cmd (idefloppy_pc_t *pc, int b, int l,
- 		pc->buffer[1] ^= 0x20;		/* ... turn off DCRT bit */
- 	pc->buffer[3] = 8;
+ 	ide_pci_setup_ports(dev, d, 14, &idx[0]);
  
--	put_unaligned(htonl(b), (unsigned int *)(&pc->buffer[4]));
--	put_unaligned(htonl(l), (unsigned int *)(&pc->buffer[8]));
--	pc->buffer_size=12;
--	set_bit(PC_WRITING, &pc->flags);
-+	put_unaligned(cpu_to_be32(b), (unsigned int *)(&pc->buffer[4]));
-+	put_unaligned(cpu_to_be32(l), (unsigned int *)(&pc->buffer[8]));
-+	pc->buffer_size = 12;
-+	pc->flags |= PC_FLAG_WRITING;
- }
+-	ide_device_add(idx);
++	ide_device_add(idx, d);
  
--/*
-- *	A mode sense command is used to "sense" floppy parameters.
-- */
--static void idefloppy_create_mode_sense_cmd (idefloppy_pc_t *pc, u8 page_code, u8 type)
-+/* A mode sense command is used to "sense" floppy parameters. */
-+static void idefloppy_create_mode_sense_cmd(idefloppy_pc_t *pc, u8 page_code,
-+		u8 type)
- {
--	u16 length = sizeof(idefloppy_mode_parameter_header_t);
--	
-+	u16 length = 8; /* sizeof(Mode Parameter Header) = 8 Bytes */
+ 	return 0;
+ }
+diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
+index 5476903..941a134 100644
+--- a/drivers/ide/pci/cs5530.c
++++ b/drivers/ide/pci/cs5530.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/cs5530.c		Version 0.77	Sep 24 2007
+- *
+  * Copyright (C) 2000			Andre Hedrick <andre at linux-ide.org>
+  * Copyright (C) 2000			Mark Lord <mlord at pobox.com>
+  * Copyright (C) 2007			Bartlomiej Zolnierkiewicz
+@@ -17,18 +15,12 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+-#include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
 +
- 	idefloppy_init_pc(pc);
--	pc->c[0] = IDEFLOPPY_MODE_SENSE_CMD;
-+	pc->c[0] = GPCMD_MODE_SENSE_10;
- 	pc->c[1] = 0;
- 	pc->c[2] = page_code + (type << 6);
+ #include <asm/io.h>
+-#include <asm/irq.h>
  
- 	switch (page_code) {
--		case IDEFLOPPY_CAPABILITIES_PAGE:
--			length += 12;
--			break;
--		case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
--			length += 32;
--			break;
+ /*
+  * Here are the standard PIO mode 0-4 timings for each "format".
+@@ -116,8 +108,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ 		case XFER_MW_DMA_0:	timings = 0x00077771; break;
+ 		case XFER_MW_DMA_1:	timings = 0x00012121; break;
+ 		case XFER_MW_DMA_2:	timings = 0x00002020; break;
 -		default:
--			printk(KERN_ERR "ide-floppy: unsupported page code "
-+	case IDEFLOPPY_CAPABILITIES_PAGE:
-+		length += 12;
-+		break;
-+	case IDEFLOPPY_FLEXIBLE_DISK_PAGE:
-+		length += 32;
-+		break;
-+	default:
-+		printk(KERN_ERR "ide-floppy: unsupported page code "
- 				"in create_mode_sense_cmd\n");
+-			return;
  	}
--	put_unaligned(htons(length), (u16 *) &pc->c[7]);
-+	put_unaligned(cpu_to_be16(length), (u16 *) &pc->c[7]);
- 	pc->request_transfer = length;
+ 	basereg = CS5530_BASEREG(drive->hwif);
+ 	reg = inl(basereg + 4);			/* get drive0 config register */
+diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
+index ddcbeba..d7b5ea9 100644
+--- a/drivers/ide/pci/cs5535.c
++++ b/drivers/ide/pci/cs5535.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/cs5535.c
+- *
+  * Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
+  * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
+  *
+@@ -157,8 +155,9 @@ static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	cs5535_set_speed(drive, XFER_PIO_0 + pio);
  }
  
--static void idefloppy_create_start_stop_cmd (idefloppy_pc_t *pc, int start)
-+static void idefloppy_create_start_stop_cmd(idefloppy_pc_t *pc, int start)
+-static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
++static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif)
  {
- 	idefloppy_init_pc(pc);
--	pc->c[0] = IDEFLOPPY_START_STOP_CMD;
-+	pc->c[0] = GPCMD_START_STOP_UNIT;
- 	pc->c[4] = start;
- }
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	u8 bit;
  
- static void idefloppy_create_test_unit_ready_cmd(idefloppy_pc_t *pc)
- {
- 	idefloppy_init_pc(pc);
--	pc->c[0] = IDEFLOPPY_TEST_UNIT_READY_CMD;
-+	pc->c[0] = GPCMD_TEST_UNIT_READY;
+ 	/* if a 80 wire cable was detected */
+@@ -180,17 +179,14 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
+ 	hwif->set_pio_mode = &cs5535_set_pio_mode;
+ 	hwif->set_dma_mode = &cs5535_set_dma_mode;
+ 
+-	if (hwif->dma_base == 0)
+-		return;
+-
+-	hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
++	hwif->cable_detect = cs5535_cable_detect;
  }
  
--static void idefloppy_create_rw_cmd (idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq, unsigned long sector)
-+static void idefloppy_create_rw_cmd(idefloppy_floppy_t *floppy,
-+				    idefloppy_pc_t *pc, struct request *rq,
-+				    unsigned long sector)
+ static const struct ide_port_info cs5535_chipset __devinitdata = {
+ 	.name		= "CS5535",
+ 	.init_hwif	= init_hwif_cs5535,
+ 	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
+-			  IDE_HFLAG_BOOTABLE,
++			  IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
+ 	.pio_mask	= ATA_PIO4,
+ 	.mwdma_mask	= ATA_MWDMA2,
+ 	.udma_mask	= ATA_UDMA4,
+diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
+index 1cd4e9c..724cbac 100644
+--- a/drivers/ide/pci/cy82c693.c
++++ b/drivers/ide/pci/cy82c693.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/cy82c693.c		Version 0.42	Oct 23, 2007
+- *
+  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs at altavista.net), Maintainer
+  *  Copyright (C) 1998-2002 Andre Hedrick <andre at linux-ide.org>, Integrator
+  *
+@@ -47,7 +45,6 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+ 
+@@ -176,17 +173,12 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
+  * set DMA mode a specific channel for CY82C693
+  */
+ 
+-static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
++static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
  {
- 	int block = sector / floppy->bs_factor;
- 	int blocks = rq->nr_sectors / floppy->bs_factor;
- 	int cmd = rq_data_dir(rq);
+-	u8 index = 0, data = 0;
++	ide_hwif_t *hwif = drive->hwif;
++	u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
  
--	debug_log("create_rw1%d_cmd: block == %d, blocks == %d\n",
--		2 * test_bit (IDEFLOPPY_USE_READ12, &floppy->flags),
-+	debug_log("create_rw10_cmd: block == %d, blocks == %d\n",
- 		block, blocks);
+-	if (mode>2)	/* make sure we set a valid mode */
+-		mode = 2;
+-			   
+-	if (mode > drive->id->tDMA)  /* to be absolutly sure we have a valid mode */
+-		mode = drive->id->tDMA;
+-	
+-	index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
++	index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
  
- 	idefloppy_init_pc(pc);
--	if (test_bit(IDEFLOPPY_USE_READ12, &floppy->flags)) {
--		pc->c[0] = cmd == READ ? IDEFLOPPY_READ12_CMD : IDEFLOPPY_WRITE12_CMD;
--		put_unaligned(htonl(blocks), (unsigned int *) &pc->c[6]);
--	} else {
--		pc->c[0] = cmd == READ ? IDEFLOPPY_READ10_CMD : IDEFLOPPY_WRITE10_CMD;
--		put_unaligned(htons(blocks), (unsigned short *) &pc->c[7]);
--	}
--	put_unaligned(htonl(block), (unsigned int *) &pc->c[2]);
-+	pc->c[0] = cmd == READ ? GPCMD_READ_10 : GPCMD_WRITE_10;
-+	put_unaligned(cpu_to_be16(blocks), (unsigned short *)&pc->c[7]);
-+	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[2]);
-+
- 	pc->callback = &idefloppy_rw_callback;
- 	pc->rq = rq;
- 	pc->b_count = cmd == READ ? 0 : rq->bio->bi_size;
- 	if (rq->cmd_flags & REQ_RW)
--		set_bit(PC_WRITING, &pc->flags);
-+		pc->flags |= PC_FLAG_WRITING;
- 	pc->buffer = NULL;
- 	pc->request_transfer = pc->buffer_size = blocks * floppy->block_size;
--	set_bit(PC_DMA_RECOMMENDED, &pc->flags);
-+	pc->flags |= PC_FLAG_DMA_RECOMMENDED;
- }
+ #if CY82C693_DEBUG_LOGS
+ 	/* for debug let's show the previous values */
+@@ -199,7 +191,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
+ 		(data&0x3), ((data>>2)&1));
+ #endif /* CY82C693_DEBUG_LOGS */
  
--static void
--idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct request *rq)
-+static void idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy,
-+		idefloppy_pc_t *pc, struct request *rq)
- {
- 	idefloppy_init_pc(pc);
- 	pc->callback = &idefloppy_rw_callback;
-@@ -1265,11 +893,10 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req
- 	pc->rq = rq;
- 	pc->b_count = rq->data_len;
- 	if (rq->data_len && rq_data_dir(rq) == WRITE)
--		set_bit(PC_WRITING, &pc->flags);
-+		pc->flags |= PC_FLAG_WRITING;
- 	pc->buffer = rq->data;
- 	if (rq->bio)
--		set_bit(PC_DMA_RECOMMENDED, &pc->flags);
--		
-+		pc->flags |= PC_FLAG_DMA_RECOMMENDED;
- 	/*
- 	 * possibly problematic, doesn't look like ide-floppy correctly
- 	 * handled scattered requests if dma fails...
-@@ -1277,30 +904,23 @@ idefloppy_blockpc_cmd(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc, struct req
- 	pc->request_transfer = pc->buffer_size = rq->data_len;
- }
+-	data = (u8)mode|(u8)(single<<2);
++	data = (mode & 3) | (single << 2);
  
--/*
-- *	idefloppy_do_request is our request handling function.	
-- */
--static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request *rq, sector_t block_s)
-+static ide_startstop_t idefloppy_do_request(ide_drive_t *drive,
-+		struct request *rq, sector_t block_s)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	idefloppy_pc_t *pc;
- 	unsigned long block = (unsigned long)block_s;
+ 	outb(index, CY82_INDEX_PORT);
+ 	outb(data, CY82_DATA_PORT);
+@@ -207,7 +199,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
+ #if CY82C693_DEBUG_INFO
+ 	printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
+ 		drive->name, HWIF(drive)->channel, drive->select.b.unit,
+-		mode, single);
++		mode & 3, single);
+ #endif /* CY82C693_DEBUG_INFO */
  
--	debug_log(KERN_INFO "dev: %s, flags: %lx, errors: %d\n",
-+	debug_log("dev: %s, cmd_type: %x, errors: %d\n",
- 			rq->rq_disk ? rq->rq_disk->disk_name : "?",
--			rq->flags, rq->errors);
--	debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
-+			rq->cmd_type, rq->errors);
-+	debug_log("sector: %ld, nr_sectors: %ld, "
- 			"current_nr_sectors: %d\n", (long)rq->sector,
- 			rq->nr_sectors, rq->current_nr_sectors);
+ 	/* 
+@@ -230,43 +222,10 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
+ #endif /* CY82C693_DEBUG_INFO */
+ }
  
- 	if (rq->errors >= ERROR_MAX) {
--		if (floppy->failed_pc != NULL) {
--			if (idefloppy_should_report_error(floppy))
--				printk(KERN_ERR "ide-floppy: %s: I/O error, pc = %2x,"
--				       " key = %2x, asc = %2x, ascq = %2x\n",
--				       drive->name, floppy->failed_pc->c[0],
--				       floppy->sense_key, floppy->asc, floppy->ascq);
+-/* 
+- * used to set DMA mode for CY82C693 (single and multi modes)
+- */
+-static int cy82c693_ide_dma_on (ide_drive_t *drive)
+-{
+-	struct hd_driveid *id = drive->id;
+-
+-#if CY82C693_DEBUG_INFO
+-	printk (KERN_INFO "dma_on: %s\n", drive->name);
+-#endif /* CY82C693_DEBUG_INFO */
+-
+-	if (id != NULL) {		
+-		/* Enable DMA on any drive that has DMA
+-		 * (multi or single) enabled
+-		 */
+-		if (id->field_valid & 2) {	/* regular DMA */
+-			int mmode, smode;
+-
+-			mmode = id->dma_mword & (id->dma_mword >> 8);
+-			smode = id->dma_1word & (id->dma_1word >> 8);
+-			       		      
+-			if (mmode != 0) {
+-				/* enable multi */
+-				cy82c693_dma_enable(drive, (mmode >> 1), 0);
+-			} else if (smode != 0) {
+-				/* enable single */
+-				cy82c693_dma_enable(drive, (smode >> 1), 1);
+-			}
 -		}
-+		if (floppy->failed_pc)
-+			ide_floppy_report_error(floppy, floppy->failed_pc);
- 		else
- 			printk(KERN_ERR "ide-floppy: %s: I/O error\n",
- 				drive->name);
-@@ -1310,8 +930,8 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
- 	if (blk_fs_request(rq)) {
- 		if (((long)rq->sector % floppy->bs_factor) ||
- 		    (rq->nr_sectors % floppy->bs_factor)) {
--			printk("%s: unsupported r/w request size\n",
--				drive->name);
-+			printk(KERN_ERR "%s: unsupported r/w request size\n",
-+					drive->name);
- 			idefloppy_do_end_request(drive, 0, 0);
- 			return ide_stopped;
- 		}
-@@ -1334,15 +954,15 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
+-	}
+-        return __ide_dma_on(drive);
+-}
+-
+ static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	pio_clocks_t pclk;
+ 	unsigned int addrCtrl;
+ 
+@@ -429,18 +388,15 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
+ static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
+ {
+ 	hwif->set_pio_mode = &cy82c693_set_pio_mode;
+-
+-	if (hwif->dma_base == 0)
+-		return;
+-
+-	hwif->ide_dma_on = &cy82c693_ide_dma_on;
++	hwif->set_dma_mode = &cy82c693_set_dma_mode;
  }
  
- /*
-- *	idefloppy_queue_pc_tail adds a special packet command request to the
-- *	tail of the request queue, and waits for it to be serviced.
-+ * Add a special packet command request to the tail of the request queue,
-+ * and wait for it to be serviced.
-  */
--static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
-+static int idefloppy_queue_pc_tail(ide_drive_t *drive, idefloppy_pc_t *pc)
+ static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
  {
- 	struct ide_floppy_obj *floppy = drive->driver_data;
- 	struct request rq;
+ 	static ide_hwif_t *primary;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
  
--	ide_init_drive_cmd (&rq);
-+	ide_init_drive_cmd(&rq);
- 	rq.buffer = (char *) pc;
- 	rq.cmd_type = REQ_TYPE_SPECIAL;
- 	rq.rq_disk = floppy->disk;
-@@ -1351,88 +971,90 @@ static int idefloppy_queue_pc_tail (ide_drive_t *drive,idefloppy_pc_t *pc)
- }
+-	if (PCI_FUNC(hwif->pci_dev->devfn) == 1)
++	if (PCI_FUNC(dev->devfn) == 1)
+ 		primary = hwif;
+ 	else {
+ 		hwif->mate = primary;
+@@ -454,11 +410,11 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
+ 	.init_iops	= init_iops_cy82c693,
+ 	.init_hwif	= init_hwif_cy82c693,
+ 	.chipset	= ide_cy82c693,
+-	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA |
++	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
+ 			  IDE_HFLAG_BOOTABLE,
+ 	.pio_mask	= ATA_PIO4,
+-	.swdma_mask	= ATA_SWDMA2_ONLY,
+-	.mwdma_mask	= ATA_MWDMA2_ONLY,
++	.swdma_mask	= ATA_SWDMA2,
++	.mwdma_mask	= ATA_MWDMA2,
+ };
  
+ static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
+index 8382908..3f9cd64 100644
+--- a/drivers/ide/pci/delkin_cb.c
++++ b/drivers/ide/pci/delkin_cb.c
+@@ -1,6 +1,4 @@
  /*
-- *	Look at the flexible disk page parameters. We will ignore the CHS
-- *	capacity parameters and use the LBA parameters instead.
-+ * Look at the flexible disk page parameters. We ignore the CHS capacity
-+ * parameters and use the LBA parameters instead.
+- *  linux/drivers/ide/pci/delkin_cb.c
+- *
+  *  Created 20 Oct 2004 by Mark Lord
+  *
+  *  Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
+@@ -18,15 +16,14 @@
+  *  License.  See the file COPYING in the main directory of this archive for
+  *  more details.
   */
--static int idefloppy_get_flexible_disk_page (ide_drive_t *drive)
-+static int ide_floppy_get_flexible_disk_page(ide_drive_t *drive)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	idefloppy_pc_t pc;
--	idefloppy_mode_parameter_header_t *header;
--	idefloppy_flexible_disk_page_t *page;
-+	u8 *page;
- 	int capacity, lba_capacity;
-+	u16 transfer_rate, sector_size, cyls, rpm;
-+	u8 heads, sectors;
+-#include <linux/autoconf.h>
 +
-+	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE,
-+					MODE_SENSE_CURRENT);
+ #include <linux/types.h>
+ #include <linux/module.h>
+-#include <linux/mm.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
++
+ #include <asm/io.h>
  
--	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_FLEXIBLE_DISK_PAGE, MODE_SENSE_CURRENT);
--	if (idefloppy_queue_pc_tail(drive,&pc)) {
--		printk(KERN_ERR "ide-floppy: Can't get flexible disk "
--			"page parameters\n");
-+	if (idefloppy_queue_pc_tail(drive, &pc)) {
-+		printk(KERN_ERR "ide-floppy: Can't get flexible disk page"
-+				" parameters\n");
- 		return 1;
- 	}
--	header = (idefloppy_mode_parameter_header_t *) pc.buffer;
--	floppy->wp = header->wp;
-+	floppy->wp = !!(pc.buffer[3] & 0x80);
- 	set_disk_ro(floppy->disk, floppy->wp);
--	page = (idefloppy_flexible_disk_page_t *) (header + 1);
--
--	page->transfer_rate = ntohs(page->transfer_rate);
--	page->sector_size = ntohs(page->sector_size);
--	page->cyls = ntohs(page->cyls);
--	page->rpm = ntohs(page->rpm);
--	capacity = page->cyls * page->heads * page->sectors * page->sector_size;
--	if (memcmp (page, &floppy->flexible_disk_page, sizeof (idefloppy_flexible_disk_page_t)))
-+	page = &pc.buffer[8];
+ /*
+@@ -54,6 +51,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ 	ide_hwif_t *hwif = NULL;
+ 	ide_drive_t *drive;
+ 	int i, rc;
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 
+ 	rc = pci_enable_device(dev);
+ 	if (rc) {
+@@ -80,20 +78,40 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
+ 	hw.irq = dev->irq;
+ 	hw.chipset = ide_pci;		/* this enables IRQ sharing */
+ 
+-	rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif);
+-	if (rc < 0) {
+-		printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc);
+-		pci_disable_device(dev);
+-		return -ENODEV;
+-	}
++	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
++	if (hwif == NULL)
++		goto out_disable;
 +
-+	transfer_rate = be16_to_cpu(*(u16 *)&pc.buffer[8 + 2]);
-+	sector_size   = be16_to_cpu(*(u16 *)&pc.buffer[8 + 6]);
-+	cyls          = be16_to_cpu(*(u16 *)&pc.buffer[8 + 8]);
-+	rpm           = be16_to_cpu(*(u16 *)&pc.buffer[8 + 28]);
-+	heads         = pc.buffer[8 + 4];
-+	sectors       = pc.buffer[8 + 5];
++	i = hwif->index;
 +
-+	capacity = cyls * heads * sectors * sector_size;
++	if (hwif->present)
++		ide_unregister(i, 0, 0);
++	else if (!hwif->hold)
++		ide_init_port_data(hwif, i);
 +
-+	if (memcmp(page, &floppy->flexible_disk_page, 32))
- 		printk(KERN_INFO "%s: %dkB, %d/%d/%d CHS, %d kBps, "
- 				"%d sector size, %d rpm\n",
--			drive->name, capacity / 1024, page->cyls,
--			page->heads, page->sectors,
--			page->transfer_rate / 8, page->sector_size, page->rpm);
--
--	floppy->flexible_disk_page = *page;
--	drive->bios_cyl = page->cyls;
--	drive->bios_head = page->heads;
--	drive->bios_sect = page->sectors;
-+				drive->name, capacity / 1024, cyls, heads,
-+				sectors, transfer_rate / 8, sector_size, rpm);
++	ide_init_port_hw(hwif, &hw);
++	hwif->quirkproc = &ide_undecoded_slave;
 +
-+	memcpy(&floppy->flexible_disk_page, page, 32);
-+	drive->bios_cyl = cyls;
-+	drive->bios_head = heads;
-+	drive->bios_sect = sectors;
- 	lba_capacity = floppy->blocks * floppy->block_size;
++	idx[0] = i;
 +
- 	if (capacity < lba_capacity) {
- 		printk(KERN_NOTICE "%s: The disk reports a capacity of %d "
- 			"bytes, but the drive only handles %d\n",
- 			drive->name, lba_capacity, capacity);
--		floppy->blocks = floppy->block_size ? capacity / floppy->block_size : 0;
-+		floppy->blocks = floppy->block_size ?
-+			capacity / floppy->block_size : 0;
++	ide_device_add(idx, NULL);
++
++	if (!hwif->present)
++		goto out_disable;
++
+ 	pci_set_drvdata(dev, hwif);
+-	hwif->pci_dev = dev;
++	hwif->dev = &dev->dev;
+ 	drive = &hwif->drives[0];
+ 	if (drive->present) {
+ 		drive->io_32bit = 1;
+ 		drive->unmask   = 1;
  	}
  	return 0;
++
++out_disable:
++	printk(KERN_ERR "delkin_cb: no IDE devices found\n");
++	pci_disable_device(dev);
++	return -ENODEV;
  }
  
--static int idefloppy_get_capability_page(ide_drive_t *drive)
-+static int idefloppy_get_sfrp_bit(ide_drive_t *drive)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	idefloppy_pc_t pc;
--	idefloppy_mode_parameter_header_t *header;
--	idefloppy_capabilities_page_t *page;
- 
- 	floppy->srfp = 0;
- 	idefloppy_create_mode_sense_cmd(&pc, IDEFLOPPY_CAPABILITIES_PAGE,
- 						 MODE_SENSE_CURRENT);
- 
--	set_bit(PC_SUPPRESS_ERROR, &pc.flags);
--	if (idefloppy_queue_pc_tail(drive,&pc)) {
-+	pc.flags |= PC_FLAG_SUPPRESS_ERROR;
-+	if (idefloppy_queue_pc_tail(drive, &pc))
- 		return 1;
--	}
+ static void
+@@ -102,7 +120,8 @@ delkin_cb_remove (struct pci_dev *dev)
+ 	ide_hwif_t *hwif = pci_get_drvdata(dev);
  
--	header = (idefloppy_mode_parameter_header_t *) pc.buffer;
--	page= (idefloppy_capabilities_page_t *)(header+1);
--	floppy->srfp = page->srfp;
-+	floppy->srfp = pc.buffer[8 + 2] & 0x40;
- 	return (0);
+ 	if (hwif)
+-		ide_unregister(hwif->index);
++		ide_unregister(hwif->index, 0, 0);
++
+ 	pci_disable_device(dev);
  }
  
+diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
+index 0688569..7fd83a9 100644
+--- a/drivers/ide/pci/generic.c
++++ b/drivers/ide/pci/generic.c
+@@ -1,6 +1,4 @@
  /*
-- *	Determine if a media is present in the floppy drive, and if so,
-- *	its LBA capacity.
-+ * Determine if a media is present in the floppy drive, and if so, its LBA
-+ * capacity.
-  */
--static int idefloppy_get_capacity (ide_drive_t *drive)
-+static int ide_floppy_get_capacity(ide_drive_t *drive)
- {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	idefloppy_pc_t pc;
--	idefloppy_capacity_header_t *header;
--	idefloppy_capacity_descriptor_t *descriptor;
--	int i, descriptors, rc = 1, blocks, length;
--	
-+	u8 *cap_desc;
-+	u8 header_len, desc_cnt;
-+	int i, rc = 1, blocks, length;
-+
- 	drive->bios_cyl = 0;
- 	drive->bios_head = drive->bios_sect = 0;
- 	floppy->blocks = 0;
-@@ -1444,44 +1066,55 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
- 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
- 		return 1;
- 	}
--	header = (idefloppy_capacity_header_t *) pc.buffer;
--	descriptors = header->length / sizeof(idefloppy_capacity_descriptor_t);
--	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
-+	header_len = pc.buffer[3];
-+	cap_desc = &pc.buffer[4];
-+	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
-+
-+	for (i = 0; i < desc_cnt; i++) {
-+		unsigned int desc_start = 4 + i*8;
-+
-+		blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
-+		length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
+- *  linux/drivers/ide/pci/generic.c	Version 0.11	December 30, 2002
+- *
+  *  Copyright (C) 2001-2002	Andre Hedrick <andre at linux-ide.org>
+  *  Portions (C) Copyright 2002  Red Hat Inc <alan at redhat.com>
+  *
+@@ -24,33 +22,13 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/pci.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
  
--	for (i = 0; i < descriptors; i++, descriptor++) {
--		blocks = descriptor->blocks = ntohl(descriptor->blocks);
--		length = descriptor->length = ntohs(descriptor->length);
-+		debug_log("Descriptor %d: %dkB, %d blocks, %d sector size\n",
-+				i, blocks * length / 1024, blocks, length);
-+
-+		if (i)
-+			continue;
-+		/*
-+		 * the code below is valid only for the 1st descriptor, ie i=0
-+		 */
+-#include <asm/io.h>
+-
+ static int ide_generic_all;		/* Set to claim all devices */
  
--		if (!i) 
--		{
--		switch (descriptor->dc) {
-+		switch (pc.buffer[desc_start + 4] & 0x03) {
- 		/* Clik! drive returns this instead of CAPACITY_CURRENT */
- 		case CAPACITY_UNFORMATTED:
--			if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags))
--                                /*
-+			if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
-+				/*
- 				 * If it is not a clik drive, break out
- 				 * (maintains previous driver behaviour)
- 				 */
- 				break;
- 		case CAPACITY_CURRENT:
- 			/* Normal Zip/LS-120 disks */
--			if (memcmp(descriptor, &floppy->capacity, sizeof (idefloppy_capacity_descriptor_t)))
-+			if (memcmp(cap_desc, &floppy->cap_desc, 8))
- 				printk(KERN_INFO "%s: %dkB, %d blocks, %d "
- 					"sector size\n", drive->name,
- 					blocks * length / 1024, blocks, length);
--			floppy->capacity = *descriptor;
-+			memcpy(&floppy->cap_desc, cap_desc, 8);
-+
- 			if (!length || length % 512) {
- 				printk(KERN_NOTICE "%s: %d bytes block size "
- 					"not supported\n", drive->name, length);
- 			} else {
--                                floppy->blocks = blocks;
--                                floppy->block_size = length;
--                                if ((floppy->bs_factor = length / 512) != 1)
--                                        printk(KERN_NOTICE "%s: warning: non "
-+				floppy->blocks = blocks;
-+				floppy->block_size = length;
-+				floppy->bs_factor = length / 512;
-+				if (floppy->bs_factor != 1)
-+					printk(KERN_NOTICE "%s: warning: non "
- 						"512 bytes block size not "
- 						"fully supported\n",
- 						drive->name);
--                                rc = 0;
-+				rc = 0;
- 			}
- 			break;
- 		case CAPACITY_NO_CARTRIDGE:
-@@ -1496,54 +1129,42 @@ static int idefloppy_get_capacity (ide_drive_t *drive)
- 				"in drive\n", drive->name);
- 			break;
- 		}
--		}
--		if (!i) {
--			debug_log( "Descriptor 0 Code: %d\n",
--				descriptor->dc);
--		}
--		debug_log( "Descriptor %d: %dkB, %d blocks, %d "
--			"sector size\n", i, blocks * length / 1024, blocks,
--			length);
-+		debug_log("Descriptor 0 Code: %d\n",
-+			  pc.buffer[desc_start + 4] & 0x03);
- 	}
+-/*
+- * the module_param_named() was added for the modular case
+- * the __setup() is left as compatibility for existing setups
+- */
+-#ifndef MODULE
+-static int __init ide_generic_all_on(char *unused)
+-{
+-	ide_generic_all = 1;
+-	printk(KERN_INFO "IDE generic will claim all unknown PCI IDE storage controllers.\n");
+-	return 1;
+-}
+-const __setup("all-generic-ide", ide_generic_all_on);
+-#endif
+ module_param_named(all_generic_ide, ide_generic_all, bool, 0444);
+ MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers.");
  
- 	/* Clik! disk does not support get_flexible_disk_page */
--        if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
--		(void) idefloppy_get_flexible_disk_page(drive);
--	}
-+	if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE))
-+		(void) ide_floppy_get_flexible_disk_page(drive);
+@@ -104,7 +82,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
  
- 	set_capacity(floppy->disk, floppy->blocks * floppy->bs_factor);
- 	return rc;
+ 	{	/* 14 */
+ 		.name		= "Revolution",
+-		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
++		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
++				  IDE_HFLAG_TRUST_BIOS_FOR_DMA |
+ 				  IDE_HFLAG_OFF_BOARD,
+ 		.swdma_mask	= ATA_SWDMA2,
+ 		.mwdma_mask	= ATA_MWDMA2,
+diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
+index ae6307f..9f01da4 100644
+--- a/drivers/ide/pci/hpt34x.c
++++ b/drivers/ide/pci/hpt34x.c
+@@ -1,7 +1,6 @@
+ /*
+- * linux/drivers/ide/pci/hpt34x.c		Version 0.40	Sept 10, 2002
+- *
+  * Copyright (C) 1998-2000	Andre Hedrick <andre at linux-ide.org>
++ *
+  * May be copied or modified under the terms of the GNU General Public License
+  *
+  *
+@@ -27,25 +26,18 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
+ 
+-#include <asm/io.h>
+-#include <asm/irq.h>
+-
+ #define HPT343_DEBUG_DRIVE_INFO		0
+ 
+ static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
+ {
+-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
+ 	u8			hi_speed, lo_speed;
+ 
+@@ -129,14 +121,19 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
+ 	hwif->set_dma_mode = &hpt34x_set_mode;
  }
  
++#define IDE_HFLAGS_HPT34X \
++	(IDE_HFLAG_NO_ATAPI_DMA | \
++	 IDE_HFLAG_NO_DSC | \
++	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
++	 IDE_HFLAG_NO_AUTODMA)
++
+ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
+ 	{ /* 0 */
+ 		.name		= "HPT343",
+ 		.init_chipset	= init_chipset_hpt34x,
+ 		.init_hwif	= init_hwif_hpt34x,
+ 		.extra		= 16,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
+-				  IDE_HFLAG_NO_AUTODMA,
++		.host_flags	= IDE_HFLAGS_HPT34X,
+ 		.pio_mask	= ATA_PIO5,
+ 	},
+ 	{ /* 1 */
+@@ -144,9 +141,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
+ 		.init_chipset	= init_chipset_hpt34x,
+ 		.init_hwif	= init_hwif_hpt34x,
+ 		.extra		= 16,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
+-				  IDE_HFLAG_NO_AUTODMA |
+-				  IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
+ 		.pio_mask	= ATA_PIO5,
+ #ifdef CONFIG_HPT34X_AUTODMA
+ 		.swdma_mask	= ATA_SWDMA2,
+diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
+index 9fce25b..d0f7bb8 100644
+--- a/drivers/ide/pci/hpt366.c
++++ b/drivers/ide/pci/hpt366.c
+@@ -1,6 +1,4 @@
  /*
--** Obtain the list of formattable capacities.
--** Very similar to idefloppy_get_capacity, except that we push the capacity
--** descriptors to userland, instead of our own structures.
--**
--** Userland gives us the following structure:
--**
--** struct idefloppy_format_capacities {
--**        int nformats;
--**        struct {
--**                int nblocks;
--**                int blocksize;
--**                } formats[];
--**        } ;
--**
--** userland initializes nformats to the number of allocated formats[]
--** records.  On exit we set nformats to the number of records we've
--** actually initialized.
--**
--*/
+- * linux/drivers/ide/pci/hpt366.c		Version 1.22	Dec 4, 2007
+- *
+  * Copyright (C) 1999-2003		Andre Hedrick <andre at linux-ide.org>
+  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
+  * Portions Copyright (C) 2003		Red Hat Inc
+@@ -88,7 +86,7 @@
+  * - rename all the register related variables consistently
+  * - move all the interrupt twiddling code from the speedproc handlers into
+  *   init_hwif_hpt366(), also grouping all the DMA related code together there
+- * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and
++ * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
+  *   separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
+  *   when setting an UltraDMA mode
+  * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
+@@ -123,12 +121,8 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+ #include <linux/blkdev.h>
+ #include <linux/hdreg.h>
 -
--static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
-+ * Obtain the list of formattable capacities.
-+ * Very similar to ide_floppy_get_capacity, except that we push the capacity
-+ * descriptors to userland, instead of our own structures.
-+ *
-+ * Userland gives us the following structure:
-+ *
-+ * struct idefloppy_format_capacities {
-+ *	int nformats;
-+ *	struct {
-+ *		int nblocks;
-+ *		int blocksize;
-+ *	} formats[];
-+ * };
-+ *
-+ * userland initializes nformats to the number of allocated formats[] records.
-+ * On exit we set nformats to the number of records we've actually initialized.
-+ */
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+@@ -136,7 +130,6 @@
+ 
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+-#include <asm/irq.h>
+ 
+ /* various tuning parameters */
+ #define HPT_RESET_STATE_ENGINE
+@@ -458,6 +451,13 @@ enum ata_clock {
+ 	NUM_ATA_CLOCKS
+ };
+ 
++struct hpt_timings {
++	u32 pio_mask;
++	u32 dma_mask;
++	u32 ultra_mask;
++	u32 *clock_table[NUM_ATA_CLOCKS];
++};
 +
-+static int ide_floppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
- {
--        idefloppy_pc_t pc;
--	idefloppy_capacity_header_t *header;
--        idefloppy_capacity_descriptor_t *descriptor;
--	int i, descriptors, blocks, length;
--	int u_array_size;
--	int u_index;
-+	idefloppy_pc_t pc;
-+	u8 header_len, desc_cnt;
-+	int i, blocks, length, u_array_size, u_index;
- 	int __user *argp;
+ /*
+  *	Hold all the HighPoint chip information in one place.
+  */
+@@ -468,7 +468,8 @@ struct hpt_info {
+ 	u8 udma_mask;		/* Allowed UltraDMA modes mask. */
+ 	u8 dpll_clk;		/* DPLL clock in MHz */
+ 	u8 pci_clk;		/* PCI  clock in MHz */
+-	u32 **settings; 	/* Chipset settings table */
++	struct hpt_timings *timings; /* Chipset timing data */
++	u8 clock;		/* ATA clock selected */
+ };
  
- 	if (get_user(u_array_size, arg))
-@@ -1555,30 +1176,27 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
- 	idefloppy_create_read_capacity_cmd(&pc);
- 	if (idefloppy_queue_pc_tail(drive, &pc)) {
- 		printk(KERN_ERR "ide-floppy: Can't get floppy parameters\n");
--                return (-EIO);
--        }
--        header = (idefloppy_capacity_header_t *) pc.buffer;
--        descriptors = header->length /
--		sizeof(idefloppy_capacity_descriptor_t);
--	descriptor = (idefloppy_capacity_descriptor_t *) (header + 1);
-+		return (-EIO);
+ /* Supported HighPoint chips */
+@@ -486,20 +487,30 @@ enum {
+ 	HPT371N
+ };
+ 
+-static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {
+-	twenty_five_base_hpt36x,
+-	thirty_three_base_hpt36x,
+-	forty_base_hpt36x,
+-	NULL,
+-	NULL
++static struct hpt_timings hpt36x_timings = {
++	.pio_mask	= 0xc1f8ffff,
++	.dma_mask	= 0x303800ff,
++	.ultra_mask	= 0x30070000,
++	.clock_table	= {
++		[ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
++		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
++		[ATA_CLOCK_40MHZ] = forty_base_hpt36x,
++		[ATA_CLOCK_50MHZ] = NULL,
++		[ATA_CLOCK_66MHZ] = NULL
 +	}
-+	header_len = pc.buffer[3];
-+	desc_cnt = header_len / 8; /* capacity descriptor of 8 bytes */
+ };
  
- 	u_index = 0;
- 	argp = arg + 1;
+-static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
+-	NULL,
+-	thirty_three_base_hpt37x,
+-	NULL,
+-	fifty_base_hpt37x,
+-	sixty_six_base_hpt37x
++static struct hpt_timings hpt37x_timings = {
++	.pio_mask	= 0xcfc3ffff,
++	.dma_mask	= 0x31c001ff,
++	.ultra_mask	= 0x303c0000,
++	.clock_table	= {
++		[ATA_CLOCK_25MHZ] = NULL,
++		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
++		[ATA_CLOCK_40MHZ] = NULL,
++		[ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
++		[ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
++	}
+ };
  
- 	/*
--	** We always skip the first capacity descriptor.  That's the
--	** current capacity.  We are interested in the remaining descriptors,
--	** the formattable capacities.
--	*/
-+	 * We always skip the first capacity descriptor.  That's the current
-+	 * capacity.  We are interested in the remaining descriptors, the
-+	 * formattable capacities.
-+	 */
-+	for (i = 1; i < desc_cnt; i++) {
-+		unsigned int desc_start = 4 + i*8;
+ static const struct hpt_info hpt36x __devinitdata = {
+@@ -507,7 +518,7 @@ static const struct hpt_info hpt36x __devinitdata = {
+ 	.chip_type	= HPT36x,
+ 	.udma_mask	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
+ 	.dpll_clk	= 0,	/* no DPLL */
+-	.settings	= hpt36x_settings
++	.timings	= &hpt36x_timings
+ };
  
--	for (i=0; i<descriptors; i++, descriptor++) {
- 		if (u_index >= u_array_size)
- 			break;	/* User-supplied buffer too small */
--		if (i == 0)
--			continue;	/* Skip the first descriptor */
+ static const struct hpt_info hpt370 __devinitdata = {
+@@ -515,7 +526,7 @@ static const struct hpt_info hpt370 __devinitdata = {
+ 	.chip_type	= HPT370,
+ 	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
+ 	.dpll_clk	= 48,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
  
--		blocks = ntohl(descriptor->blocks);
--		length = ntohs(descriptor->length);
-+		blocks = be32_to_cpu(*(u32 *)&pc.buffer[desc_start]);
-+		length = be16_to_cpu(*(u16 *)&pc.buffer[desc_start + 6]);
+ static const struct hpt_info hpt370a __devinitdata = {
+@@ -523,7 +534,7 @@ static const struct hpt_info hpt370a __devinitdata = {
+ 	.chip_type	= HPT370A,
+ 	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
+ 	.dpll_clk	= 48,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
  
- 		if (put_user(blocks, argp))
- 			return(-EFAULT);
-@@ -1597,53 +1215,14 @@ static int idefloppy_get_format_capacities(ide_drive_t *drive, int __user *arg)
+ static const struct hpt_info hpt374 __devinitdata = {
+@@ -531,7 +542,7 @@ static const struct hpt_info hpt374 __devinitdata = {
+ 	.chip_type	= HPT374,
+ 	.udma_mask	= ATA_UDMA5,
+ 	.dpll_clk	= 48,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt372 __devinitdata = {
+@@ -539,7 +550,7 @@ static const struct hpt_info hpt372 __devinitdata = {
+ 	.chip_type	= HPT372,
+ 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 55,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt372a __devinitdata = {
+@@ -547,7 +558,7 @@ static const struct hpt_info hpt372a __devinitdata = {
+ 	.chip_type	= HPT372A,
+ 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 66,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt302 __devinitdata = {
+@@ -555,7 +566,7 @@ static const struct hpt_info hpt302 __devinitdata = {
+ 	.chip_type	= HPT302,
+ 	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 66,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt371 __devinitdata = {
+@@ -563,7 +574,7 @@ static const struct hpt_info hpt371 __devinitdata = {
+ 	.chip_type	= HPT371,
+ 	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 66,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt372n __devinitdata = {
+@@ -571,7 +582,7 @@ static const struct hpt_info hpt372n __devinitdata = {
+ 	.chip_type	= HPT372N,
+ 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 77,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt302n __devinitdata = {
+@@ -579,7 +590,7 @@ static const struct hpt_info hpt302n __devinitdata = {
+ 	.chip_type	= HPT302N,
+ 	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 77,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static const struct hpt_info hpt371n __devinitdata = {
+@@ -587,7 +598,7 @@ static const struct hpt_info hpt371n __devinitdata = {
+ 	.chip_type	= HPT371N,
+ 	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
+ 	.dpll_clk	= 77,
+-	.settings	= hpt37x_settings
++	.timings	= &hpt37x_timings
+ };
+ 
+ static int check_in_drive_list(ide_drive_t *drive, const char **list)
+@@ -608,7 +619,8 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
+ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
++	struct hpt_info *info	= pci_get_drvdata(dev);
+ 	u8 mask 		= hwif->ultra_mask;
+ 
+ 	switch (info->chip_type) {
+@@ -647,7 +659,8 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
+ static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
++	struct hpt_info *info	= pci_get_drvdata(dev);
+ 
+ 	switch (info->chip_type) {
+ 	case HPT372 :
+@@ -675,100 +688,56 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
+ 	for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
+ 		if (xfer_speeds[i] == speed)
+ 			break;
+-	/*
+-	 * NOTE: info->settings only points to the pointer
+-	 * to the list of the actual register values
+-	 */
+-	return (*info->settings)[i];
++
++	return info->timings->clock_table[info->clock][i];
  }
  
- /*
--** Send ATAPI_FORMAT_UNIT to the drive.
--**
--** Userland gives us the following structure:
--**
--** struct idefloppy_format_command {
--**        int nblocks;
--**        int blocksize;
--**        int flags;
--**        } ;
--**
--** flags is a bitmask, currently, the only defined flag is:
--**
--**        0x01 - verify media after format.
--*/
+-static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed)
++static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
+ {
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev  *dev	= hwif->pci_dev;
++	struct pci_dev  *dev	= to_pci_dev(drive->hwif->dev);
+ 	struct hpt_info	*info	= pci_get_drvdata(dev);
+-	u8  itr_addr		= drive->dn ? 0x44 : 0x40;
++	struct hpt_timings *t	= info->timings;
++	u8  itr_addr		= 0x40 + (drive->dn * 4);
+ 	u32 old_itr		= 0;
+-	u32 itr_mask, new_itr;
 -
--static int idefloppy_begin_format(ide_drive_t *drive, int __user *arg)
+-	itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
+-		  (speed < XFER_UDMA_0   ? 0xc0070000 : 0xc03800ff);
+-
+-	new_itr = get_speed_setting(speed, info);
++	u32 new_itr		= get_speed_setting(speed, info);
++	u32 itr_mask		= speed < XFER_MW_DMA_0 ? t->pio_mask :
++				 (speed < XFER_UDMA_0   ? t->dma_mask :
++							  t->ultra_mask);
+ 
++	pci_read_config_dword(dev, itr_addr, &old_itr);
++	new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
+ 	/*
+ 	 * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
+ 	 * to avoid problems handling I/O errors later
+ 	 */
+-	pci_read_config_dword(dev, itr_addr, &old_itr);
+-	new_itr  = (new_itr & ~itr_mask) | (old_itr & itr_mask);
+ 	new_itr &= ~0xc0000000;
+ 
+ 	pci_write_config_dword(dev, itr_addr, new_itr);
+ }
+ 
+-static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed)
 -{
--	int blocks;
--	int length;
--	int flags;
--	idefloppy_pc_t pc;
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev  *dev	= hwif->pci_dev;
+-	struct hpt_info	*info	= pci_get_drvdata(dev);
+-	u8  itr_addr		= 0x40 + (drive->dn * 4);
+-	u32 old_itr		= 0;
+-	u32 itr_mask, new_itr;
 -
--	if (get_user(blocks, arg) ||
--	    get_user(length, arg+1) ||
--	    get_user(flags, arg+2)) {
--		return (-EFAULT);
--	}
+-	itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
+-		  (speed < XFER_UDMA_0   ? 0xc03c0000 : 0xc1c001ff);
 -
--	/* Get the SFRP bit */
--	(void) idefloppy_get_capability_page(drive);
--	idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
--	if (idefloppy_queue_pc_tail(drive, &pc)) {
--                return (-EIO);
--	}
+-	new_itr = get_speed_setting(speed, info);
 -
--	return (0);
+-	pci_read_config_dword(dev, itr_addr, &old_itr);
+-	new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
+-	
+-	if (speed < XFER_MW_DMA_0)
+-		new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
+-	pci_write_config_dword(dev, itr_addr, new_itr);
 -}
 -
--/*
--** Get ATAPI_FORMAT_UNIT progress indication.
--**
--** Userland gives a pointer to an int.  The int is set to a progress
--** indicator 0-65536, with 65536=100%.
--**
--** If the drive does not support format progress indication, we just check
--** the dsc bit, and return either 0 or 65536.
--*/
-+ * Get ATAPI_FORMAT_UNIT progress indication.
-+ *
-+ * Userland gives a pointer to an int.  The int is set to a progress
-+ * indicator 0-65536, with 65536=100%.
-+ *
-+ * If the drive does not support format progress indication, we just check
-+ * the dsc bit, and return either 0 or 65536.
-+ */
- 
- static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
+-static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
+-{
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct hpt_info	*info	= pci_get_drvdata(hwif->pci_dev);
+-
+-	if (info->chip_type >= HPT370)
+-		hpt37x_set_mode(drive, speed);
+-	else	/* hpt368: hpt_minimum_revision(dev, 2) */
+-		hpt36x_set_mode(drive, speed);
+-}
+-
+ static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
  {
-@@ -1653,26 +1232,24 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
- 
- 	if (floppy->srfp) {
- 		idefloppy_create_request_sense_cmd(&pc);
--		if (idefloppy_queue_pc_tail(drive, &pc)) {
-+		if (idefloppy_queue_pc_tail(drive, &pc))
- 			return (-EIO);
--		}
+ 	hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
+ }
  
- 		if (floppy->sense_key == 2 &&
- 		    floppy->asc == 4 &&
--		    floppy->ascq == 4) {
-+		    floppy->ascq == 4)
- 			progress_indication = floppy->progress_indication;
--		}
--		/* Else assume format_unit has finished, and we're
--		** at 0x10000 */
-+
-+		/* Else assume format_unit has finished, and we're at 0x10000 */
- 	} else {
--		atapi_status_t status;
- 		unsigned long flags;
-+		u8 stat;
+-static int hpt3xx_quirkproc(ide_drive_t *drive)
++static void hpt3xx_quirkproc(ide_drive_t *drive)
+ {
+ 	struct hd_driveid *id	= drive->id;
+ 	const  char **list	= quirk_drives;
  
- 		local_irq_save(flags);
--		status.all = HWIF(drive)->INB(IDE_STATUS_REG);
-+		stat = drive->hwif->INB(IDE_STATUS_REG);
- 		local_irq_restore(flags);
+ 	while (*list)
+-		if (strstr(id->model, *list++))
+-			return 1;
+-	return 0;
+-}
+-
+-static void hpt3xx_intrproc(ide_drive_t *drive)
+-{
+-	if (drive->quirk_list)
+-		return;
++		if (strstr(id->model, *list++)) {
++			drive->quirk_list = 1;
++			return;
++		}
  
--		progress_indication = !status.b.dsc ? 0 : 0x10000;
-+		progress_indication = ((stat & SEEK_STAT) == 0) ? 0 : 0x10000;
- 	}
- 	if (put_user(progress_indication, arg))
- 		return (-EFAULT);
-@@ -1680,10 +1257,7 @@ static int idefloppy_get_format_progress(ide_drive_t *drive, int __user *arg)
- 	return (0);
+-	/* drives in the quirk_list may not like intr setups/cleanups */
+-	outb(drive->ctl | 2, IDE_CONTROL_REG);
++	drive->quirk_list = 0;
  }
  
--/*
-- *	Return the current floppy capacity.
-- */
--static sector_t idefloppy_capacity (ide_drive_t *drive)
-+static sector_t idefloppy_capacity(ide_drive_t *drive)
+ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
- 	unsigned long capacity = floppy->blocks * floppy->bs_factor;
-@@ -1692,16 +1266,12 @@ static sector_t idefloppy_capacity (ide_drive_t *drive)
- }
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev	*dev	= hwif->pci_dev;
++	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
+ 	struct hpt_info *info	= pci_get_drvdata(dev);
  
- /*
-- *	idefloppy_identify_device checks if we can support a drive,
-- *	based on the ATAPI IDENTIFY command results.
-+ * Check whether we can support a drive, based on the ATAPI IDENTIFY command
-+ * results.
+ 	if (drive->quirk_list) {
+@@ -800,7 +769,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
   */
--static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
-+static int idefloppy_identify_device(ide_drive_t *drive, struct hd_driveid *id)
+ static void hpt366_dma_lost_irq(ide_drive_t *drive)
  {
- 	struct idefloppy_id_gcw gcw;
--#if IDEFLOPPY_DEBUG_INFO
--	u16 mask,i;
--	char buffer[80];
--#endif /* IDEFLOPPY_DEBUG_INFO */
- 
- 	*((u16 *) &gcw) = id->config;
- 
-@@ -1710,103 +1280,23 @@ static int idefloppy_identify_device (ide_drive_t *drive,struct hd_driveid *id)
- 	if ((gcw.device_type == 5) &&
- 	    !strstr(id->model, "CD-ROM") &&
- 	    strstr(id->model, "ZIP"))
--		gcw.device_type = 0;			
-+		gcw.device_type = 0;
- #endif
+-	struct pci_dev *dev = HWIF(drive)->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
  
--#if IDEFLOPPY_DEBUG_INFO
--	printk(KERN_INFO "Dumping ATAPI Identify Device floppy parameters\n");
--	switch (gcw.protocol) {
--		case 0: case 1: sprintf(buffer, "ATA");break;
--		case 2:	sprintf(buffer, "ATAPI");break;
--		case 3: sprintf(buffer, "Reserved (Unknown to ide-floppy)");break;
--	}
--	printk(KERN_INFO "Protocol Type: %s\n", buffer);
--	switch (gcw.device_type) {
--		case 0: sprintf(buffer, "Direct-access Device");break;
--		case 1: sprintf(buffer, "Streaming Tape Device");break;
--		case 2: case 3: case 4: sprintf (buffer, "Reserved");break;
--		case 5: sprintf(buffer, "CD-ROM Device");break;
--		case 6: sprintf(buffer, "Reserved");
--		case 7: sprintf(buffer, "Optical memory Device");break;
--		case 0x1f: sprintf(buffer, "Unknown or no Device type");break;
--		default: sprintf(buffer, "Reserved");
--	}
--	printk(KERN_INFO "Device Type: %x - %s\n", gcw.device_type, buffer);
--	printk(KERN_INFO "Removable: %s\n",gcw.removable ? "Yes":"No");	
--	switch (gcw.drq_type) {
--		case 0: sprintf(buffer, "Microprocessor DRQ");break;
--		case 1: sprintf(buffer, "Interrupt DRQ");break;
--		case 2: sprintf(buffer, "Accelerated DRQ");break;
--		case 3: sprintf(buffer, "Reserved");break;
--	}
--	printk(KERN_INFO "Command Packet DRQ Type: %s\n", buffer);
--	switch (gcw.packet_size) {
--		case 0: sprintf(buffer, "12 bytes");break;
--		case 1: sprintf(buffer, "16 bytes");break;
--		default: sprintf(buffer, "Reserved");break;
--	}
--	printk(KERN_INFO "Command Packet Size: %s\n", buffer);
--	printk(KERN_INFO "Model: %.40s\n",id->model);
--	printk(KERN_INFO "Firmware Revision: %.8s\n",id->fw_rev);
--	printk(KERN_INFO "Serial Number: %.20s\n",id->serial_no);
--	printk(KERN_INFO "Write buffer size(?): %d bytes\n",id->buf_size*512);
--	printk(KERN_INFO "DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
--	printk(KERN_INFO "LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
--	printk(KERN_INFO "IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
--	printk(KERN_INFO "IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
--	printk(KERN_INFO "ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
--	printk(KERN_INFO "PIO Cycle Timing Category: %d\n",id->tPIO);
--	printk(KERN_INFO "DMA Cycle Timing Category: %d\n",id->tDMA);
--	printk(KERN_INFO "Single Word DMA supported modes:\n");
--	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
--		if (id->dma_1word & mask)
--			printk(KERN_INFO "   Mode %d%s\n", i,
--			(id->dma_1word & (mask << 8)) ? " (active)" : "");
--	}
--	printk(KERN_INFO "Multi Word DMA supported modes:\n");
--	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
--		if (id->dma_mword & mask)
--			printk(KERN_INFO "   Mode %d%s\n", i,
--			(id->dma_mword & (mask << 8)) ? " (active)" : "");
--	}
--	if (id->field_valid & 0x0002) {
--		printk(KERN_INFO "Enhanced PIO Modes: %s\n",
--			id->eide_pio_modes & 1 ? "Mode 3":"None");
--		if (id->eide_dma_min == 0)
--			sprintf(buffer, "Not supported");
--		else
--			sprintf(buffer, "%d ns",id->eide_dma_min);
--		printk(KERN_INFO "Minimum Multi-word DMA cycle per word: %s\n", buffer);
--		if (id->eide_dma_time == 0)
--			sprintf(buffer, "Not supported");
--		else
--			sprintf(buffer, "%d ns",id->eide_dma_time);
--		printk(KERN_INFO "Manufacturer\'s Recommended Multi-word cycle: %s\n", buffer);
--		if (id->eide_pio == 0)
--			sprintf(buffer, "Not supported");
--		else
--			sprintf(buffer, "%d ns",id->eide_pio);
--		printk(KERN_INFO "Minimum PIO cycle without IORDY: %s\n",
--			buffer);
--		if (id->eide_pio_iordy == 0)
--			sprintf(buffer, "Not supported");
--		else
--			sprintf(buffer, "%d ns",id->eide_pio_iordy);
--		printk(KERN_INFO "Minimum PIO cycle with IORDY: %s\n", buffer);
--	} else
--		printk(KERN_INFO "According to the device, fields 64-70 are not valid.\n");
--#endif /* IDEFLOPPY_DEBUG_INFO */
--
- 	if (gcw.protocol != 2)
--		printk(KERN_ERR "ide-floppy: Protocol is not ATAPI\n");
-+		printk(KERN_ERR "ide-floppy: Protocol (0x%02x) is not ATAPI\n",
-+				gcw.protocol);
- 	else if (gcw.device_type != 0)
--		printk(KERN_ERR "ide-floppy: Device type is not set to floppy\n");
-+		printk(KERN_ERR "ide-floppy: Device type (0x%02x) is not set "
-+				"to floppy\n", gcw.device_type);
- 	else if (!gcw.removable)
- 		printk(KERN_ERR "ide-floppy: The removable flag is not set\n");
- 	else if (gcw.drq_type == 3) {
--		printk(KERN_ERR "ide-floppy: Sorry, DRQ type %d not supported\n", gcw.drq_type);
-+		printk(KERN_ERR "ide-floppy: Sorry, DRQ type (0x%02x) not "
-+				"supported\n", gcw.drq_type);
- 	} else if (gcw.packet_size != 0) {
--		printk(KERN_ERR "ide-floppy: Packet size is not 12 bytes long\n");
-+		printk(KERN_ERR "ide-floppy: Packet size (0x%02x) is not 12 "
-+				"bytes long\n", gcw.packet_size);
- 	} else
- 		return 1;
- 	return 0;
-@@ -1817,59 +1307,53 @@ static void idefloppy_add_settings(ide_drive_t *drive)
+ 	pci_read_config_byte(dev, 0x50, &mcr1);
+@@ -816,18 +785,20 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
+ static void hpt370_clear_engine(ide_drive_t *drive)
  {
- 	idefloppy_floppy_t *floppy = drive->driver_data;
+ 	ide_hwif_t *hwif = HWIF(drive);
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
  
--/*
-- *			drive	setting name	read/write	data type	min	max	mul_factor	div_factor	data pointer		set function
-- */
--	ide_add_setting(drive,	"bios_cyl",	SETTING_RW,	TYPE_INT,	0,	1023,		1,		1,	&drive->bios_cyl,	NULL);
--	ide_add_setting(drive,	"bios_head",	SETTING_RW,	TYPE_BYTE,	0,	255,		1,		1,	&drive->bios_head,	NULL);
--	ide_add_setting(drive,	"bios_sect",	SETTING_RW,	TYPE_BYTE,	0,	63,		1,		1,	&drive->bios_sect,	NULL);
--	ide_add_setting(drive,	"ticks",	SETTING_RW,	TYPE_BYTE,	0,	255,		1,		1,	&floppy->ticks,		NULL);
-+	ide_add_setting(drive, "bios_cyl", SETTING_RW, TYPE_INT, 0, 1023, 1, 1,
-+			&drive->bios_cyl, NULL);
-+	ide_add_setting(drive, "bios_head", SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
-+			&drive->bios_head, NULL);
-+	ide_add_setting(drive, "bios_sect", SETTING_RW,	TYPE_BYTE, 0,  63, 1, 1,
-+			&drive->bios_sect, NULL);
-+	ide_add_setting(drive, "ticks",	   SETTING_RW, TYPE_BYTE, 0, 255, 1, 1,
-+			&floppy->ticks,	 NULL);
+-	pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37);
++	pci_write_config_byte(dev, hwif->select_data, 0x37);
+ 	udelay(10);
  }
- #else
- static inline void idefloppy_add_settings(ide_drive_t *drive) { ; }
- #endif
  
--/*
-- *	Driver initialization.
-- */
--static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
-+static void idefloppy_setup(ide_drive_t *drive, idefloppy_floppy_t *floppy)
+ static void hpt370_irq_timeout(ide_drive_t *drive)
  {
- 	struct idefloppy_id_gcw gcw;
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u16 bfifo		= 0;
+ 	u8  dma_cmd;
  
- 	*((u16 *) &gcw) = drive->id->config;
- 	floppy->pc = floppy->pc_stack;
- 	if (gcw.drq_type == 1)
--		set_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags);
-+		floppy->flags |= IDEFLOPPY_FLAG_DRQ_INTERRUPT;
- 	/*
--	 *	We used to check revisions here. At this point however
--	 *	I'm giving up. Just assume they are all broken, its easier.
-+	 * We used to check revisions here. At this point however I'm giving up.
-+	 * Just assume they are all broken, its easier.
- 	 *
--	 *	The actual reason for the workarounds was likely
--	 *	a driver bug after all rather than a firmware bug,
--	 *	and the workaround below used to hide it. It should
--	 *	be fixed as of version 1.9, but to be on the safe side
--	 *	we'll leave the limitation below for the 2.2.x tree.
-+	 * The actual reason for the workarounds was likely a driver bug after
-+	 * all rather than a firmware bug, and the workaround below used to hide
-+	 * it. It should be fixed as of version 1.9, but to be on the safe side
-+	 * we'll leave the limitation below for the 2.2.x tree.
- 	 */
--
- 	if (!strncmp(drive->id->model, "IOMEGA ZIP 100 ATAPI", 20)) {
--		set_bit(IDEFLOPPY_ZIP_DRIVE, &floppy->flags);
-+		floppy->flags |= IDEFLOPPY_FLAG_ZIP_DRIVE;
- 		/* This value will be visible in the /proc/ide/hdx/settings */
- 		floppy->ticks = IDEFLOPPY_TICKS_DELAY;
- 		blk_queue_max_sectors(drive->queue, 64);
- 	}
+-	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
++	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
+ 	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
  
- 	/*
--	*      Guess what?  The IOMEGA Clik! drive also needs the
--	*      above fix.  It makes nasty clicking noises without
--	*      it, so please don't remove this.
--	*/
-+	 * Guess what? The IOMEGA Clik! drive also needs the above fix. It makes
-+	 * nasty clicking noises without it, so please don't remove this.
-+	 */
- 	if (strncmp(drive->id->model, "IOMEGA Clik!", 11) == 0) {
- 		blk_queue_max_sectors(drive->queue, 64);
--		set_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags);
-+		floppy->flags |= IDEFLOPPY_FLAG_CLIK_DRIVE;
- 	}
+ 	/* get DMA command mode */
+@@ -870,10 +841,11 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
+ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u16 bfifo		= 0;
+ 	u8  dma_stat;
  
--
--	(void) idefloppy_get_capacity(drive);
-+	(void) ide_floppy_get_capacity(drive);
- 	idefloppy_add_settings(drive);
- }
+-	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
++	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
+ 	if (bfifo & 0x1FF) {
+ //		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
+ 		return 0;
+@@ -893,7 +865,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
+ static int hpt374_ide_dma_end(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev	*dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 mcr	= 0, mcr_addr	= hwif->select_data;
+ 	u8 bwsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
  
-@@ -1885,7 +1369,7 @@ static void ide_floppy_remove(ide_drive_t *drive)
- 	ide_floppy_put(floppy);
- }
+@@ -914,32 +886,33 @@ static int hpt374_ide_dma_end(ide_drive_t *drive)
  
--static void ide_floppy_release(struct kref *kref)
-+static void idefloppy_cleanup_obj(struct kref *kref)
+ static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
  {
- 	struct ide_floppy_obj *floppy = to_ide_floppy(kref);
- 	ide_drive_t *drive = floppy->drive;
-@@ -1898,19 +1382,19 @@ static void ide_floppy_release(struct kref *kref)
- }
+-	u8 scr2 = inb(hwif->dma_master + 0x7b);
++	unsigned long base = hwif->extra_base;
++	u8 scr2 = inb(base + 0x6b);
  
- #ifdef CONFIG_IDE_PROC_FS
--static int proc_idefloppy_read_capacity
--	(char *page, char **start, off_t off, int count, int *eof, void *data)
-+static int proc_idefloppy_read_capacity(char *page, char **start, off_t off,
-+		int count, int *eof, void *data)
- {
- 	ide_drive_t*drive = (ide_drive_t *)data;
- 	int len;
+ 	if ((scr2 & 0x7f) == mode)
+ 		return;
  
--	len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive));
--	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
-+	len = sprintf(page, "%llu\n", (long long)idefloppy_capacity(drive));
-+	PROC_IDE_READ_RETURN(page, start, off, count, eof, len);
- }
+ 	/* Tristate the bus */
+-	outb(0x80, hwif->dma_master + 0x73);
+-	outb(0x80, hwif->dma_master + 0x77);
++	outb(0x80, base + 0x63);
++	outb(0x80, base + 0x67);
  
- static ide_proc_entry_t idefloppy_proc[] = {
--	{ "capacity",	S_IFREG|S_IRUGO,	proc_idefloppy_read_capacity, NULL },
--	{ "geometry",	S_IFREG|S_IRUGO,	proc_ide_read_geometry,	NULL },
-+	{ "capacity",	S_IFREG|S_IRUGO, proc_idefloppy_read_capacity,	NULL },
-+	{ "geometry",	S_IFREG|S_IRUGO, proc_ide_read_geometry,	NULL },
- 	{ NULL, 0, NULL, NULL }
- };
- #endif	/* CONFIG_IDE_PROC_FS */
-@@ -1945,9 +1429,10 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
- 	idefloppy_pc_t pc;
- 	int ret = 0;
+ 	/* Switch clock and reset channels */
+-	outb(mode, hwif->dma_master + 0x7b);
+-	outb(0xc0, hwif->dma_master + 0x79);
++	outb(mode, base + 0x6b);
++	outb(0xc0, base + 0x69);
  
--	debug_log(KERN_INFO "Reached idefloppy_open\n");
-+	debug_log("Reached %s\n", __func__);
+ 	/*
+ 	 * Reset the state machines.
+ 	 * NOTE: avoid accidentally enabling the disabled channels.
+ 	 */
+-	outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70);
+-	outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74);
++	outb(inb(base + 0x60) | 0x32, base + 0x60);
++	outb(inb(base + 0x64) | 0x32, base + 0x64);
  
--	if (!(floppy = ide_floppy_get(disk)))
-+	floppy = ide_floppy_get(disk);
-+	if (!floppy)
- 		return -ENXIO;
+ 	/* Complete reset */
+-	outb(0x00, hwif->dma_master + 0x79);
++	outb(0x00, base + 0x69);
  
- 	drive = floppy->drive;
-@@ -1955,7 +1440,7 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
- 	floppy->openers++;
+ 	/* Reconnect channels to bus */
+-	outb(0x00, hwif->dma_master + 0x73);
+-	outb(0x00, hwif->dma_master + 0x77);
++	outb(0x00, base + 0x63);
++	outb(0x00, base + 0x67);
+ }
  
- 	if (floppy->openers == 1) {
--		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
-+		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
- 		/* Just in case */
+ /**
+@@ -967,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
+ static int hpt3xx_busproc(ide_drive_t *drive, int state)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8  mcr_addr		= hwif->select_data + 2;
+ 	u8  resetmask		= hwif->channel ? 0x80 : 0x40;
+ 	u8  bsr2		= 0;
+@@ -1210,7 +1183,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
+ 	 * We also  don't like using  the DPLL because this causes glitches
+ 	 * on PRST-/SRST- when the state engine gets reset...
+ 	 */
+-	if (chip_type >= HPT374 || info->settings[clock] == NULL) {
++	if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
+ 		u16 f_low, delta = pci_clk < 50 ? 2 : 4;
+ 		int adjust;
  
- 		idefloppy_create_test_unit_ready_cmd(&pc);
-@@ -1964,13 +1449,13 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
- 			(void) idefloppy_queue_pc_tail(drive, &pc);
+@@ -1226,7 +1199,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
+ 			clock = ATA_CLOCK_50MHZ;
  		}
  
--		if (idefloppy_get_capacity (drive)
-+		if (ide_floppy_get_capacity(drive)
- 		   && (filp->f_flags & O_NDELAY) == 0
- 		    /*
--		    ** Allow O_NDELAY to open a drive without a disk, or with
--		    ** an unreadable disk, so that we can get the format
--		    ** capacity of the drive or begin the format - Sam
--		    */
-+		     * Allow O_NDELAY to open a drive without a disk, or with an
-+		     * unreadable disk, so that we can get the format capacity
-+		     * of the drive or begin the format - Sam
-+		     */
- 		    ) {
- 			ret = -EIO;
- 			goto out_put_floppy;
-@@ -1980,14 +1465,14 @@ static int idefloppy_open(struct inode *inode, struct file *filp)
- 			ret = -EROFS;
- 			goto out_put_floppy;
- 		}
--		set_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
-+		floppy->flags |= IDEFLOPPY_FLAG_MEDIA_CHANGED;
- 		/* IOMEGA Clik! drives do not support lock/unlock commands */
--                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
-+		if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
- 			idefloppy_create_prevent_cmd(&pc, 1);
- 			(void) idefloppy_queue_pc_tail(drive, &pc);
- 		}
- 		check_disk_change(inode->i_bdev);
--	} else if (test_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags)) {
-+	} else if (floppy->flags & IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS) {
- 		ret = -EBUSY;
- 		goto out_put_floppy;
+-		if (info->settings[clock] == NULL) {
++		if (info->timings->clock_table[clock] == NULL) {
+ 			printk(KERN_ERR "%s: unknown bus timing!\n", name);
+ 			kfree(info);
+ 			return -EIO;
+@@ -1267,15 +1240,10 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
+ 		printk("%s: using %d MHz PCI clock\n", name, pci_clk);
  	}
-@@ -2005,17 +1490,17 @@ static int idefloppy_release(struct inode *inode, struct file *filp)
- 	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
- 	ide_drive_t *drive = floppy->drive;
- 	idefloppy_pc_t pc;
--	
--	debug_log(KERN_INFO "Reached idefloppy_release\n");
-+
-+	debug_log("Reached %s\n", __func__);
- 
- 	if (floppy->openers == 1) {
- 		/* IOMEGA Clik! drives do not support lock/unlock commands */
--                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
-+		if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
- 			idefloppy_create_prevent_cmd(&pc, 0);
- 			(void) idefloppy_queue_pc_tail(drive, &pc);
- 		}
  
--		clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
-+		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
- 	}
+-	/*
+-	 * Advance the table pointer to a slot which points to the list
+-	 * of the register values settings matching the clock being used.
+-	 */
+-	info->settings += clock;
+-
+ 	/* Store the clock frequencies. */
+ 	info->dpll_clk	= dpll_clk;
+ 	info->pci_clk	= pci_clk;
++	info->clock	= clock;
  
- 	floppy->openers--;
-@@ -2036,64 +1521,105 @@ static int idefloppy_getgeo(struct block_device *bdev, struct hd_geometry *geo)
- 	return 0;
+ 	/* Point to this chip's own instance of the hpt_info structure. */
+ 	pci_set_drvdata(dev, info);
+@@ -1306,12 +1274,55 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
+ 	return dev->irq;
  }
  
-+static int ide_floppy_lockdoor(idefloppy_floppy_t *floppy, idefloppy_pc_t *pc,
-+			       unsigned long arg, unsigned int cmd)
++static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
 +{
-+	if (floppy->openers > 1)
-+		return -EBUSY;
-+
-+	/* The IOMEGA Clik! Drive doesn't support this command -
-+	 * no room for an eject mechanism */
-+	if (!(floppy->flags & IDEFLOPPY_FLAG_CLIK_DRIVE)) {
-+		int prevent = arg ? 1 : 0;
++	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
++	struct hpt_info *info	= pci_get_drvdata(dev);
++	u8 chip_type		= info->chip_type;
++	u8 scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
 +
-+		if (cmd == CDROMEJECT)
-+			prevent = 0;
++	/*
++	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
++	 * address lines to access an external EEPROM.  To read valid
++	 * cable detect state the pins must be enabled as inputs.
++	 */
++	if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
++		/*
++		 * HPT374 PCI function 1
++		 * - set bit 15 of reg 0x52 to enable TCBLID as input
++		 * - set bit 15 of reg 0x56 to enable FCBLID as input
++		 */
++		u8  mcr_addr = hwif->select_data + 2;
++		u16 mcr;
 +
-+		idefloppy_create_prevent_cmd(pc, prevent);
-+		(void) idefloppy_queue_pc_tail(floppy->drive, pc);
-+	}
++		pci_read_config_word(dev, mcr_addr, &mcr);
++		pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
++		/* now read cable id register */
++		pci_read_config_byte(dev, 0x5a, &scr1);
++		pci_write_config_word(dev, mcr_addr, mcr);
++	} else if (chip_type >= HPT370) {
++		/*
++		 * HPT370/372 and 374 pcifn 0
++		 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
++		 */
++		u8 scr2 = 0;
 +
-+	if (cmd == CDROMEJECT) {
-+		idefloppy_create_start_stop_cmd(pc, 2);
-+		(void) idefloppy_queue_pc_tail(floppy->drive, pc);
-+	}
++		pci_read_config_byte(dev, 0x5b, &scr2);
++		pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
++		/* now read cable id register */
++		pci_read_config_byte(dev, 0x5a, &scr1);
++		pci_write_config_byte(dev, 0x5b,  scr2);
++	} else
++		pci_read_config_byte(dev, 0x5a, &scr1);
 +
-+	return 0;
++	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
 +}
 +
-+static int ide_floppy_format_unit(idefloppy_floppy_t *floppy,
-+				  int __user *arg)
-+{
-+	int blocks, length, flags, err = 0;
-+	idefloppy_pc_t pc;
+ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+ {
+-	struct pci_dev	*dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	struct hpt_info *info	= pci_get_drvdata(dev);
+ 	int serialize		= HPT_SERIALIZE_IO;
+-	u8  scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
+ 	u8  chip_type		= info->chip_type;
+ 	u8  new_mcr, old_mcr	= 0;
+ 
+@@ -1320,14 +1331,16 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+ 
+ 	hwif->set_pio_mode	= &hpt3xx_set_pio_mode;
+ 	hwif->set_dma_mode	= &hpt3xx_set_mode;
 +
-+	if (floppy->openers > 1) {
-+		/* Don't format if someone is using the disk */
-+		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
-+		return -EBUSY;
-+	}
+ 	hwif->quirkproc		= &hpt3xx_quirkproc;
+-	hwif->intrproc		= &hpt3xx_intrproc;
+ 	hwif->maskproc		= &hpt3xx_maskproc;
+ 	hwif->busproc		= &hpt3xx_busproc;
+ 
+ 	hwif->udma_filter	= &hpt3xx_udma_filter;
+ 	hwif->mdma_filter	= &hpt3xx_mdma_filter;
+ 
++	hwif->cable_detect	= hpt3xx_cable_detect;
 +
-+	floppy->flags |= IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
+ 	/*
+ 	 * HPT3xxN chips have some complications:
+ 	 *
+@@ -1373,43 +1386,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+ 	if (hwif->dma_base == 0)
+ 		return;
+ 
+-	/*
+-	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
+-	 * address lines to access an external EEPROM.  To read valid
+-	 * cable detect state the pins must be enabled as inputs.
+-	 */
+-	if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
+-		/*
+-		 * HPT374 PCI function 1
+-		 * - set bit 15 of reg 0x52 to enable TCBLID as input
+-		 * - set bit 15 of reg 0x56 to enable FCBLID as input
+-		 */
+-		u8  mcr_addr = hwif->select_data + 2;
+-		u16 mcr;
+-
+-		pci_read_config_word (dev, mcr_addr, &mcr);
+-		pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
+-		/* now read cable id register */
+-		pci_read_config_byte (dev, 0x5a, &scr1);
+-		pci_write_config_word(dev, mcr_addr, mcr);
+-	} else if (chip_type >= HPT370) {
+-		/*
+-		 * HPT370/372 and 374 pcifn 0
+-		 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
+-		 */
+-		u8 scr2 = 0;
+-
+-		pci_read_config_byte (dev, 0x5b, &scr2);
+-		pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
+-		/* now read cable id register */
+-		pci_read_config_byte (dev, 0x5a, &scr1);
+-		pci_write_config_byte(dev, 0x5b,  scr2);
+-	} else
+-		pci_read_config_byte (dev, 0x5a, &scr1);
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+-
+ 	if (chip_type >= HPT374) {
+ 		hwif->ide_dma_test_irq	= &hpt374_ide_dma_test_irq;
+ 		hwif->ide_dma_end	= &hpt374_ide_dma_end;
+@@ -1423,7 +1399,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
+ 
+ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
+ {
+-	struct pci_dev	*dev		= hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	u8 masterdma	= 0, slavedma	= 0;
+ 	u8 dma_new	= 0, dma_old	= 0;
+ 	unsigned long flags;
+@@ -1443,7 +1419,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
+ 
+ 	local_irq_restore(flags);
+ 
+-	ide_setup_dma(hwif, dmabase, 8);
++	ide_setup_dma(hwif, dmabase);
+ }
+ 
+ static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
+@@ -1494,6 +1470,11 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
+ 	return 0;
+ }
+ 
++#define IDE_HFLAGS_HPT3XX \
++	(IDE_HFLAG_NO_ATAPI_DMA | \
++	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
++	 IDE_HFLAG_OFF_BOARD)
 +
-+	/*
-+	 * Send ATAPI_FORMAT_UNIT to the drive.
-+	 *
-+	 * Userland gives us the following structure:
-+	 *
-+	 * struct idefloppy_format_command {
-+	 *        int nblocks;
-+	 *        int blocksize;
-+	 *        int flags;
-+	 *        } ;
-+	 *
-+	 * flags is a bitmask, currently, the only defined flag is:
-+	 *
-+	 *        0x01 - verify media after format.
-+	 */
-+	if (get_user(blocks, arg) ||
-+			get_user(length, arg+1) ||
-+			get_user(flags, arg+2)) {
-+		err = -EFAULT;
-+		goto out;
-+	}
+ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 	{	/* 0 */
+ 		.name		= "HPT36x",
+@@ -1508,9 +1489,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 		 */
+ 		.enablebits	= {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
+ 		.extra		= 240,
+-		.host_flags	= IDE_HFLAG_SINGLE |
+-				  IDE_HFLAG_NO_ATAPI_DMA |
+-				  IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 	},{	/* 1 */
+@@ -1520,7 +1499,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 		.init_dma	= init_dma_hpt366,
+ 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ 		.extra		= 240,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT3XX,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 	},{	/* 2 */
+@@ -1530,7 +1509,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 		.init_dma	= init_dma_hpt366,
+ 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ 		.extra		= 240,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT3XX,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 	},{	/* 3 */
+@@ -1540,7 +1519,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 		.init_dma	= init_dma_hpt366,
+ 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ 		.extra		= 240,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT3XX,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 	},{	/* 4 */
+@@ -1551,7 +1530,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ 		.udma_mask	= ATA_UDMA5,
+ 		.extra		= 240,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT3XX,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 	},{	/* 5 */
+@@ -1561,7 +1540,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
+ 		.init_dma	= init_dma_hpt366,
+ 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
+ 		.extra		= 240,
+-		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_HPT3XX,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 	}
+diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
+index 90b52ed..e3427ea 100644
+--- a/drivers/ide/pci/it8213.c
++++ b/drivers/ide/pci/it8213.c
+@@ -10,13 +10,10 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+ 
+-#include <asm/io.h>
+-
+ /**
+  *	it8213_set_pio_mode	-	set host controller for PIO mode
+  *	@drive: drive
+@@ -28,7 +25,7 @@
+ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	int is_slave		= drive->dn & 1;
+ 	int master_port		= 0x40;
+ 	int slave_port		= 0x44;
+@@ -85,7 +82,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 maslave		= 0x40;
+ 	int a_speed		= 3 << (drive->dn * 4);
+ 	int u_flag		= 1 << drive->dn;
+@@ -101,24 +98,11 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	pci_read_config_byte(dev, 0x54, &reg54);
+ 	pci_read_config_byte(dev, 0x55, &reg55);
+ 
+-	switch(speed) {
+-		case XFER_UDMA_6:
+-		case XFER_UDMA_4:
+-		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
+-		case XFER_UDMA_5:
+-		case XFER_UDMA_3:
+-		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
+-		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
+-			break;
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_SW_DMA_2:
+-			break;
+-		default:
+-			return;
+-	}
+-
+ 	if (speed >= XFER_UDMA_0) {
++		u8 udma = speed - XFER_UDMA_0;
 +
-+	(void) idefloppy_get_sfrp_bit(floppy->drive);
-+	idefloppy_create_format_unit_cmd(&pc, blocks, length, flags);
++		u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
 +
-+	if (idefloppy_queue_pc_tail(floppy->drive, &pc))
-+		err = -EIO;
+ 		if (!(reg48 & u_flag))
+ 			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+ 		if (speed >= XFER_UDMA_5) {
+@@ -156,6 +140,16 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	}
+ }
+ 
++static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
++{
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	u8 reg42h = 0;
 +
-+out:
-+	if (err)
-+		floppy->flags &= ~IDEFLOPPY_FLAG_FORMAT_IN_PROGRESS;
-+	return err;
-+}
++	pci_read_config_byte(dev, 0x42, &reg42h);
 +
++	return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++}
 +
- static int idefloppy_ioctl(struct inode *inode, struct file *file,
- 			unsigned int cmd, unsigned long arg)
+ /**
+  *	init_hwif_it8213	-	set up hwif structs
+  *	@hwif: interface to set up
+@@ -165,18 +159,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 
+ static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
  {
- 	struct block_device *bdev = inode->i_bdev;
- 	struct ide_floppy_obj *floppy = ide_floppy_g(bdev->bd_disk);
- 	ide_drive_t *drive = floppy->drive;
-+	idefloppy_pc_t pc;
- 	void __user *argp = (void __user *)arg;
- 	int err;
--	int prevent = (arg) ? 1 : 0;
--	idefloppy_pc_t pc;
+-	u8 reg42h = 0;
+-
+ 	hwif->set_dma_mode = &it8213_set_dma_mode;
+ 	hwif->set_pio_mode = &it8213_set_pio_mode;
  
- 	switch (cmd) {
- 	case CDROMEJECT:
--		prevent = 0;
- 		/* fall through */
- 	case CDROM_LOCKDOOR:
--		if (floppy->openers > 1)
--			return -EBUSY;
+-	if (!hwif->dma_base)
+-		return;
 -
--		/* The IOMEGA Clik! Drive doesn't support this command - no room for an eject mechanism */
--                if (!test_bit(IDEFLOPPY_CLIK_DRIVE, &floppy->flags)) {
--			idefloppy_create_prevent_cmd(&pc, prevent);
--			(void) idefloppy_queue_pc_tail(drive, &pc);
--		}
--		if (cmd == CDROMEJECT) {
--			idefloppy_create_start_stop_cmd(&pc, 2);
--			(void) idefloppy_queue_pc_tail(drive, &pc);
--		}
--		return 0;
-+		return ide_floppy_lockdoor(floppy, &pc, arg, cmd);
- 	case IDEFLOPPY_IOCTL_FORMAT_SUPPORTED:
- 		return 0;
- 	case IDEFLOPPY_IOCTL_FORMAT_GET_CAPACITY:
--		return idefloppy_get_format_capacities(drive, argp);
-+		return ide_floppy_get_format_capacities(drive, argp);
- 	case IDEFLOPPY_IOCTL_FORMAT_START:
+-	pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
 -
- 		if (!(file->f_mode & 2))
- 			return -EPERM;
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++	hwif->cable_detect = it8213_cable_detect;
+ }
  
--		if (floppy->openers > 1) {
--			/* Don't format if someone is using the disk */
--
--			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS,
--				  &floppy->flags);
--			return -EBUSY;
--		}
+ 
+diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
+index 99b7d76..1597f0c 100644
+--- a/drivers/ide/pci/it821x.c
++++ b/drivers/ide/pci/it821x.c
+@@ -1,7 +1,4 @@
 -
--		set_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
+ /*
+- * linux/drivers/ide/pci/it821x.c		Version 0.16	Jul 3 2007
+- *
+  * Copyright (C) 2004		Red Hat <alan at redhat.com>
+  * Copyright (C) 2007		Bartlomiej Zolnierkiewicz
+  *
+@@ -66,13 +63,10 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+ 
+-#include <asm/io.h>
 -
--		err = idefloppy_begin_format(drive, argp);
--		if (err)
--			clear_bit(IDEFLOPPY_FORMAT_IN_PROGRESS, &floppy->flags);
--		return err;
--		/*
--		** Note, the bit will be cleared when the device is
--		** closed.  This is the cleanest way to handle the
--		** situation where the drive does not support
--		** format progress reporting.
--		*/
-+		return ide_floppy_format_unit(floppy, (int __user *)arg);
- 	case IDEFLOPPY_IOCTL_FORMAT_GET_PROGRESS:
- 		return idefloppy_get_format_progress(drive, argp);
- 	}
-@@ -2118,13 +1644,16 @@ static int idefloppy_media_changed(struct gendisk *disk)
+ struct it821x_dev
  {
- 	struct ide_floppy_obj *floppy = ide_floppy_g(disk);
- 	ide_drive_t *drive = floppy->drive;
-+	int ret;
+ 	unsigned int smart:1,		/* Are we in smart raid mode */
+@@ -113,7 +107,8 @@ static int it8212_noraid;
  
- 	/* do not scan partitions twice if this is a removable device */
- 	if (drive->attach) {
- 		drive->attach = 0;
- 		return 0;
- 	}
--	return test_and_clear_bit(IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
-+	ret = !!(floppy->flags & IDEFLOPPY_FLAG_MEDIA_CHANGED);
-+	floppy->flags &= ~IDEFLOPPY_FLAG_MEDIA_CHANGED;
-+	return ret;
+ static void it821x_program(ide_drive_t *drive, u16 timing)
+ {
+-	ide_hwif_t *hwif	= drive->hwif;
++	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+ 	int channel = hwif->channel;
+ 	u8 conf;
+@@ -123,7 +118,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
+ 		conf = timing >> 8;
+ 	else
+ 		conf = timing & 0xFF;
+-	pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
++
++	pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
  }
  
- static int idefloppy_revalidate_disk(struct gendisk *disk)
-@@ -2155,16 +1684,20 @@ static int ide_floppy_probe(ide_drive_t *drive)
- 		goto failed;
- 	if (drive->media != ide_floppy)
- 		goto failed;
--	if (!idefloppy_identify_device (drive, drive->id)) {
--		printk (KERN_ERR "ide-floppy: %s: not supported by this version of ide-floppy\n", drive->name);
-+	if (!idefloppy_identify_device(drive, drive->id)) {
-+		printk(KERN_ERR "ide-floppy: %s: not supported by this version"
-+				" of ide-floppy\n", drive->name);
- 		goto failed;
- 	}
- 	if (drive->scsi) {
--		printk("ide-floppy: passing drive %s to ide-scsi emulation.\n", drive->name);
-+		printk(KERN_INFO "ide-floppy: passing drive %s to ide-scsi"
-+				" emulation.\n", drive->name);
- 		goto failed;
+ /**
+@@ -137,7 +133,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
+ 
+ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
+ {
+-	ide_hwif_t *hwif	= drive->hwif;
++	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+ 	int channel = hwif->channel;
+ 	int unit = drive->select.b.unit;
+@@ -148,11 +145,12 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
+ 		conf = timing >> 8;
+ 	else
+ 		conf = timing & 0xFF;
+-	if(itdev->timing10 == 0)
+-		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
++
++	if (itdev->timing10 == 0)
++		pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
+ 	else {
+-		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf);
+-		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf);
++		pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
++		pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
  	}
--	if ((floppy = kzalloc(sizeof (idefloppy_floppy_t), GFP_KERNEL)) == NULL) {
--		printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name);
-+	floppy = kzalloc(sizeof(idefloppy_floppy_t), GFP_KERNEL);
-+	if (!floppy) {
-+		printk(KERN_ERR "ide-floppy: %s: Can't allocate a floppy"
-+				" structure\n", drive->name);
- 		goto failed;
+ }
+ 
+@@ -167,6 +165,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
+ static void it821x_clock_strategy(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+ 
+ 	u8 unit = drive->select.b.unit;
+@@ -205,10 +204,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
+ 		itdev->clock_mode = ATA_50;
+ 		sel = 1;
  	}
+-	pci_read_config_byte(hwif->pci_dev, 0x50, &v);
++
++	pci_read_config_byte(dev, 0x50, &v);
+ 	v &= ~(1 << (1 + hwif->channel));
+ 	v |= sel << (1 + hwif->channel);
+-	pci_write_config_byte(hwif->pci_dev, 0x50, v);
++	pci_write_config_byte(dev, 0x50, v);
  
-@@ -2186,7 +1719,7 @@ static int ide_floppy_probe(ide_drive_t *drive)
+ 	/*
+ 	 *	Reprogram the UDMA/PIO of the pair drive for the switch
+@@ -282,7 +282,8 @@ static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
  
- 	drive->driver_data = floppy;
+ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
+ {
+-	ide_hwif_t *hwif	= drive->hwif;
++	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
+ 	int unit = drive->select.b.unit;
+ 	int channel = hwif->channel;
+@@ -297,12 +298,12 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
+ 	itdev->udma[unit] = UDMA_OFF;
  
--	idefloppy_setup (drive, floppy);
-+	idefloppy_setup(drive, floppy);
+ 	/* UDMA bits off - Revision 0x10 do them in pairs */
+-	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+-	if(itdev->timing10)
++	pci_read_config_byte(dev, 0x50, &conf);
++	if (itdev->timing10)
+ 		conf |= channel ? 0x60: 0x18;
+ 	else
+ 		conf |= 1 << (3 + 2 * channel + unit);
+-	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
++	pci_write_config_byte(dev, 0x50, conf);
  
- 	g->minors = 1 << PARTN_BITS;
- 	g->driverfs_dev = &drive->gendev;
-@@ -2202,9 +1735,7 @@ failed:
- 	return -ENODEV;
- }
+ 	it821x_clock_strategy(drive);
+ 	/* FIXME: do we need to program this ? */
+@@ -320,7 +321,8 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
  
--MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
--
--static void __exit idefloppy_exit (void)
-+static void __exit idefloppy_exit(void)
+ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
  {
- 	driver_unregister(&idefloppy_driver.gen_driver);
- }
-@@ -2219,3 +1750,5 @@ MODULE_ALIAS("ide:*m-floppy*");
- module_init(idefloppy_init);
- module_exit(idefloppy_exit);
- MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
-+
-diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c
-index 0f72b98..be469db 100644
---- a/drivers/ide/ide-generic.c
-+++ b/drivers/ide/ide-generic.c
-@@ -14,10 +14,16 @@
+-	ide_hwif_t *hwif	= drive->hwif;
++	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+ 	int unit = drive->select.b.unit;
+ 	int channel = hwif->channel;
+@@ -337,12 +339,12 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
+ 		itdev->udma[unit] |= 0x8080;	/* UDMA 5/6 select on */
  
- static int __init ide_generic_init(void)
- {
-+	u8 idx[MAX_HWIFS];
-+	int i;
-+
- 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
- 		ide_get_lock(NULL, NULL); /* for atari only */
+ 	/* UDMA on. Again revision 0x10 must do the pair */
+-	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
+-	if(itdev->timing10)
++	pci_read_config_byte(dev, 0x50, &conf);
++	if (itdev->timing10)
+ 		conf &= channel ? 0x9F: 0xE7;
+ 	else
+ 		conf &= ~ (1 << (3 + 2 * channel + unit));
+-	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
++	pci_write_config_byte(dev, 0x50, conf);
+ 
+ 	it821x_clock_strategy(drive);
+ 	it821x_program_udma(drive, itdev->udma[unit]);
+@@ -431,33 +433,29 @@ static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
+ }
  
--	(void)ideprobe_init();
-+	for (i = 0; i < MAX_HWIFS; i++)
-+		idx[i] = ide_hwifs[i].present ? 0xff : i;
-+
-+	ide_device_add_all(idx, NULL);
+ /**
+- *	it821x_fixup	-	post init callback
+- *	@hwif: interface
++ *	it821x_quirkproc	-	post init callback
++ *	@drive: drive
+  *
+- *	This callback is run after the drives have been probed but
++ *	This callback is run after the drive has been probed but
+  *	before anything gets attached. It allows drivers to do any
+  *	final tuning that is needed, or fixups to work around bugs.
+  */
  
- 	if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET])
- 		ide_release_lock();	/* for atari only */
-diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
-index bef781f..4bddef0 100644
---- a/drivers/ide/ide-io.c
-+++ b/drivers/ide/ide-io.c
-@@ -58,15 +58,19 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
- 			     int uptodate, unsigned int nr_bytes, int dequeue)
+-static void __devinit it821x_fixups(ide_hwif_t *hwif)
++static void __devinit it821x_quirkproc(ide_drive_t *drive)
  {
- 	int ret = 1;
-+	int error = 0;
-+
-+	if (uptodate <= 0)
-+		error = uptodate ? uptodate : -EIO;
+-	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
+-	int i;
++	struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
++	struct hd_driveid *id = drive->id;
++	u16 *idbits = (u16 *)drive->id;
  
+-	if(!itdev->smart) {
++	if (!itdev->smart) {
+ 		/*
+ 		 *	If we are in pass through mode then not much
+ 		 *	needs to be done, but we do bother to clear the
+ 		 *	IRQ mask as we may well be in PIO (eg rev 0x10)
+ 		 *	for now and we know unmasking is safe on this chipset.
+ 		 */
+-		for (i = 0; i < 2; i++) {
+-			ide_drive_t *drive = &hwif->drives[i];
+-			if(drive->present)
+-				drive->unmask = 1;
+-		}
+-		return;
+-	}
++		drive->unmask = 1;
++	} else {
  	/*
- 	 * if failfast is set on a request, override number of sectors and
- 	 * complete the whole request right now
+ 	 *	Perform fixups on smart mode. We need to "lose" some
+ 	 *	capabilities the firmware lacks but does not filter, and
+@@ -465,16 +463,6 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
+ 	 *	in RAID mode.
  	 */
--	if (blk_noretry_request(rq) && end_io_error(uptodate))
-+	if (blk_noretry_request(rq) && error)
- 		nr_bytes = rq->hard_nr_sectors << 9;
- 
--	if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
-+	if (!blk_fs_request(rq) && error && !rq->errors)
- 		rq->errors = -EIO;
  
- 	/*
-@@ -75,17 +79,12 @@ static int __ide_end_request(ide_drive_t *drive, struct request *rq,
- 	 */
- 	if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
- 		drive->state = 0;
--		HWGROUP(drive)->hwif->ide_dma_on(drive);
-+		ide_dma_on(drive);
- 	}
+-	for(i = 0; i < 2; i++) {
+-		ide_drive_t *drive = &hwif->drives[i];
+-		struct hd_driveid *id;
+-		u16 *idbits;
+-
+-		if(!drive->present)
+-			continue;
+-		id = drive->id;
+-		idbits = (u16 *)drive->id;
+-
+ 		/* Check for RAID v native */
+ 		if(strstr(id->model, "Integrated Technology Express")) {
+ 			/* In raid mode the ident block is slightly buggy
+@@ -534,9 +522,12 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
  
--	if (!end_that_request_chunk(rq, uptodate, nr_bytes)) {
--		add_disk_randomness(rq->rq_disk);
--		if (dequeue) {
--			if (!list_empty(&rq->queuelist))
--				blkdev_dequeue_request(rq);
-+	if (!__blk_end_request(rq, error, nr_bytes)) {
-+		if (dequeue)
- 			HWGROUP(drive)->rq = NULL;
--		}
--		end_that_request_last(rq, uptodate);
- 		ret = 0;
- 	}
+ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
+ 	u8 conf;
  
-@@ -189,18 +188,14 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
- 			return ide_stopped;
- 		}
- 		if (ide_id_has_flush_cache_ext(drive->id))
--			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
-+			args->tf.command = WIN_FLUSH_CACHE_EXT;
- 		else
--			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
--		args->command_type = IDE_DRIVE_TASK_NO_DATA;
--		args->handler	   = &task_no_data_intr;
--		return do_rw_taskfile(drive, args);
-+			args->tf.command = WIN_FLUSH_CACHE;
-+		goto out_do_tf;
++	hwif->quirkproc = &it821x_quirkproc;
++
+ 	if (idev == NULL) {
+ 		printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
+ 		return;
+@@ -544,7 +535,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
  
- 	case idedisk_pm_standby:	/* Suspend step 2 (standby) */
--		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
--		args->command_type = IDE_DRIVE_TASK_NO_DATA;
--		args->handler	   = &task_no_data_intr;
--		return do_rw_taskfile(drive, args);
-+		args->tf.command = WIN_STANDBYNOW1;
-+		goto out_do_tf;
+ 	ide_set_hwifdata(hwif, idev);
  
- 	case idedisk_pm_restore_pio:	/* Resume step 1 (restore PIO) */
- 		ide_set_max_pio(drive);
-@@ -214,10 +209,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
- 		return ide_stopped;
+-	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
++	pci_read_config_byte(dev, 0x50, &conf);
+ 	if (conf & 1) {
+ 		idev->smart = 1;
+ 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+@@ -567,7 +558,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ 	 *	this is necessary.
+ 	 */
  
- 	case idedisk_pm_idle:		/* Resume step 2 (idle) */
--		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
--		args->command_type = IDE_DRIVE_TASK_NO_DATA;
--		args->handler = task_no_data_intr;
--		return do_rw_taskfile(drive, args);
-+		args->tf.command = WIN_IDLEIMMEDIATE;
-+		goto out_do_tf;
+-	pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
++	pci_read_config_byte(dev, 0x08, &conf);
+ 	if (conf == 0x10) {
+ 		idev->timing10 = 1;
+ 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+@@ -585,14 +576,13 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ 	} else
+ 		hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
  
- 	case ide_pm_restore_dma:	/* Resume step 3 (restore DMA) */
- 		/*
-@@ -225,9 +218,8 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
- 		 * we could be smarter and check for current xfer_speed
- 		 * in struct drive etc...
- 		 */
--		if (drive->hwif->ide_dma_on == NULL)
-+		if (drive->hwif->dma_host_set == NULL)
- 			break;
--		drive->hwif->dma_off_quietly(drive);
- 		/*
- 		 * TODO: respect ->using_dma setting
- 		 */
-@@ -236,6 +228,11 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
- 	}
- 	pm->pm_step = ide_pm_state_completed;
- 	return ide_stopped;
++	hwif->cable_detect = ata66_it821x;
 +
-+out_do_tf:
-+	args->tf_flags	 = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	args->data_phase = TASKFILE_NO_DATA;
-+	return do_rw_taskfile(drive, args);
+ 	if (hwif->dma_base == 0)
+ 		return;
+ 
+ 	hwif->ultra_mask = ATA_UDMA6;
+ 	hwif->mwdma_mask = ATA_MWDMA2;
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = ata66_it821x(hwif);
  }
  
- /**
-@@ -292,12 +289,54 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
- 		drive->blocked = 0;
- 		blk_start_queue(drive->queue);
+ static void __devinit it8212_disable_raid(struct pci_dev *dev)
+@@ -633,7 +623,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
+ 		.name		= name_str,		\
+ 		.init_chipset	= init_chipset_it821x,	\
+ 		.init_hwif	= init_hwif_it821x,	\
+-		.fixup	 	= it821x_fixups,	\
+ 		.host_flags	= IDE_HFLAG_BOOTABLE,	\
+ 		.pio_mask	= ATA_PIO4,		\
  	}
--	blkdev_dequeue_request(rq);
- 	HWGROUP(drive)->rq = NULL;
--	end_that_request_last(rq, 1);
-+	if (__blk_end_request(rq, 0, 0))
-+		BUG();
- 	spin_unlock_irqrestore(&ide_lock, flags);
- }
+diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
+index 0083eaf..a56bcb4 100644
+--- a/drivers/ide/pci/jmicron.c
++++ b/drivers/ide/pci/jmicron.c
+@@ -8,13 +8,10 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
  
-+void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
-+{
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct ide_taskfile *tf = &task->tf;
-+
-+	if (task->tf_flags & IDE_TFLAG_IN_DATA) {
-+		u16 data = hwif->INW(IDE_DATA_REG);
-+
-+		tf->data = data & 0xff;
-+		tf->hob_data = (data >> 8) & 0xff;
-+	}
-+
-+	/* be sure we're looking at the low order bits */
-+	hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
-+
-+	if (task->tf_flags & IDE_TFLAG_IN_NSECT)
-+		tf->nsect  = hwif->INB(IDE_NSECTOR_REG);
-+	if (task->tf_flags & IDE_TFLAG_IN_LBAL)
-+		tf->lbal   = hwif->INB(IDE_SECTOR_REG);
-+	if (task->tf_flags & IDE_TFLAG_IN_LBAM)
-+		tf->lbam   = hwif->INB(IDE_LCYL_REG);
-+	if (task->tf_flags & IDE_TFLAG_IN_LBAH)
-+		tf->lbah   = hwif->INB(IDE_HCYL_REG);
-+	if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
-+		tf->device = hwif->INB(IDE_SELECT_REG);
-+
-+	if (task->tf_flags & IDE_TFLAG_LBA48) {
-+		hwif->OUTB(drive->ctl | 0x80, IDE_CONTROL_REG);
-+
-+		if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
-+			tf->hob_feature = hwif->INB(IDE_FEATURE_REG);
-+		if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
-+			tf->hob_nsect   = hwif->INB(IDE_NSECTOR_REG);
-+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
-+			tf->hob_lbal    = hwif->INB(IDE_SECTOR_REG);
-+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
-+			tf->hob_lbam    = hwif->INB(IDE_LCYL_REG);
-+		if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
-+			tf->hob_lbah    = hwif->INB(IDE_HCYL_REG);
-+	}
-+}
-+
- /**
-  *	ide_end_drive_cmd	-	end an explicit drive command
-  *	@drive: command 
-@@ -314,7 +353,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
-  
- void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
+-#include <asm/io.h>
+-
+ typedef enum {
+ 	PORT_PATA0 = 0,
+ 	PORT_PATA1 = 1,
+@@ -30,7 +27,7 @@ typedef enum {
+ 
+ static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
  {
--	ide_hwif_t *hwif = HWIF(drive);
- 	unsigned long flags;
- 	struct request *rq;
+-	struct pci_dev *pdev = hwif->pci_dev;
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
  
-@@ -322,61 +360,18 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
- 	rq = HWGROUP(drive)->rq;
- 	spin_unlock_irqrestore(&ide_lock, flags);
+ 	u32 control;
+ 	u32 control5;
+@@ -111,11 +108,7 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
+ 	hwif->set_pio_mode = &jmicron_set_pio_mode;
+ 	hwif->set_dma_mode = &jmicron_set_dma_mode;
  
--	if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
--		u8 *args = (u8 *) rq->buffer;
--		if (rq->errors == 0)
--			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
--
--		if (args) {
--			args[0] = stat;
--			args[1] = err;
--			args[2] = hwif->INB(IDE_NSECTOR_REG);
--		}
--	} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
--		u8 *args = (u8 *) rq->buffer;
--		if (rq->errors == 0)
--			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
--
--		if (args) {
--			args[0] = stat;
--			args[1] = err;
--			/* be sure we're looking at the low order bits */
--			hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
--			args[2] = hwif->INB(IDE_NSECTOR_REG);
--			args[3] = hwif->INB(IDE_SECTOR_REG);
--			args[4] = hwif->INB(IDE_LCYL_REG);
--			args[5] = hwif->INB(IDE_HCYL_REG);
--			args[6] = hwif->INB(IDE_SELECT_REG);
--		}
--	} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-+	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
- 		ide_task_t *args = (ide_task_t *) rq->special;
- 		if (rq->errors == 0)
- 			rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
- 			
- 		if (args) {
--			if (args->tf_in_flags.b.data) {
--				u16 data				= hwif->INW(IDE_DATA_REG);
--				args->tfRegister[IDE_DATA_OFFSET]	= (data) & 0xFF;
--				args->hobRegister[IDE_DATA_OFFSET]	= (data >> 8) & 0xFF;
--			}
--			args->tfRegister[IDE_ERROR_OFFSET]   = err;
--			/* be sure we're looking at the low order bits */
--			hwif->OUTB(drive->ctl & ~0x80, IDE_CONTROL_REG);
--			args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG);
--			args->tfRegister[IDE_SECTOR_OFFSET]  = hwif->INB(IDE_SECTOR_REG);
--			args->tfRegister[IDE_LCYL_OFFSET]    = hwif->INB(IDE_LCYL_REG);
--			args->tfRegister[IDE_HCYL_OFFSET]    = hwif->INB(IDE_HCYL_REG);
--			args->tfRegister[IDE_SELECT_OFFSET]  = hwif->INB(IDE_SELECT_REG);
--			args->tfRegister[IDE_STATUS_OFFSET]  = stat;
+-	if (hwif->dma_base == 0)
+-		return;
 -
--			if (drive->addressing == 1) {
--				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
--				args->hobRegister[IDE_FEATURE_OFFSET]	= hwif->INB(IDE_FEATURE_REG);
--				args->hobRegister[IDE_NSECTOR_OFFSET]	= hwif->INB(IDE_NSECTOR_REG);
--				args->hobRegister[IDE_SECTOR_OFFSET]	= hwif->INB(IDE_SECTOR_REG);
--				args->hobRegister[IDE_LCYL_OFFSET]	= hwif->INB(IDE_LCYL_REG);
--				args->hobRegister[IDE_HCYL_OFFSET]	= hwif->INB(IDE_HCYL_REG);
--			}
-+			struct ide_taskfile *tf = &args->tf;
-+
-+			tf->error = err;
-+			tf->status = stat;
-+
-+			ide_tf_read(drive, args);
- 		}
- 	} else if (blk_pm_request(rq)) {
- 		struct request_pm_state *pm = rq->data;
-@@ -391,10 +386,10 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
- 	}
- 
- 	spin_lock_irqsave(&ide_lock, flags);
--	blkdev_dequeue_request(rq);
- 	HWGROUP(drive)->rq = NULL;
- 	rq->errors = err;
--	end_that_request_last(rq, !rq->errors);
-+	if (__blk_end_request(rq, (rq->errors ? -EIO : 0), 0))
-+		BUG();
- 	spin_unlock_irqrestore(&ide_lock, flags);
- }
- 
-@@ -615,90 +610,26 @@ ide_startstop_t ide_abort(ide_drive_t *drive, const char *msg)
- 		return __ide_abort(drive, rq);
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = ata66_jmicron(hwif);
++	hwif->cable_detect = ata66_jmicron;
  }
  
--/**
-- *	ide_cmd		-	issue a simple drive command
-- *	@drive: drive the command is for
-- *	@cmd: command byte
-- *	@nsect: sector byte
-- *	@handler: handler for the command completion
+ static const struct ide_port_info jmicron_chipset __devinitdata = {
+diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
+index d4df464..bf0d3b2 100644
+--- a/drivers/ide/pci/ns87415.c
++++ b/drivers/ide/pci/ns87415.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/ns87415.c		Version 2.00  Sep. 10, 2002
 - *
-- *	Issue a simple drive command with interrupts.
-- *	The drive must be selected beforehand.
-- */
--
--static void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect,
--		ide_handler_t *handler)
-+static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+  * Copyright (C) 1997-1998	Mark Lord <mlord at pobox.com>
+  * Copyright (C) 1998		Eddie C. Dost <ecd at skynet.be>
+  * Copyright (C) 1999-2000	Andre Hedrick <andre at linux-ide.org>
+@@ -12,11 +10,7 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+ #include <linux/interrupt.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
+@@ -71,10 +65,9 @@ static u8 superio_ide_inb (unsigned long port)
+ 
+ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
  {
--	ide_hwif_t *hwif = HWIF(drive);
--	if (IDE_CONTROL_REG)
--		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);	/* clear nIEN */
--	SELECT_MASK(drive,0);
--	hwif->OUTB(nsect,IDE_NSECTOR_REG);
--	ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL);
-+	tf->nsect   = drive->sect;
-+	tf->lbal    = drive->sect;
-+	tf->lbam    = drive->cyl;
-+	tf->lbah    = drive->cyl >> 8;
-+	tf->device  = ((drive->head - 1) | drive->select.all) & ~ATA_LBA;
-+	tf->command = WIN_SPECIFY;
- }
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ 	u32 base, dmabase;
+-	u8 tmp;
+-	struct pci_dev *pdev = hwif->pci_dev;
+-	u8 port = hwif->channel;
++	u8 port = hwif->channel, tmp;
  
--/**
-- *	drive_cmd_intr		- 	drive command completion interrupt
-- *	@drive: drive the completion interrupt occurred on
-- *
-- *	drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
-- *	We do any necessary data reading and then wait for the drive to
-- *	go non busy. At that point we may read the error data and complete
-- *	the request
-- */
-- 
--static ide_startstop_t drive_cmd_intr (ide_drive_t *drive)
-+static void ide_tf_set_restore_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+ 	base = pci_resource_start(pdev, port * 2) & ~3;
+ 	dmabase = pci_resource_start(pdev, 4) & ~3;
+@@ -93,10 +86,11 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+ 
+ static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
  {
--	struct request *rq = HWGROUP(drive)->rq;
--	ide_hwif_t *hwif = HWIF(drive);
--	u8 *args = (u8 *) rq->buffer;
--	u8 stat = hwif->INB(IDE_STATUS_REG);
--	int retries = 10;
--
--	local_irq_enable_in_hardirq();
--	if (rq->cmd_type == REQ_TYPE_ATA_CMD &&
--	    (stat & DRQ_STAT) && args && args[3]) {
--		u8 io_32bit = drive->io_32bit;
--		drive->io_32bit = 0;
--		hwif->ata_input_data(drive, &args[4], args[3] * SECTOR_WORDS);
--		drive->io_32bit = io_32bit;
--		while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
--			udelay(100);
+-	if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++
++	if (PCI_SLOT(dev->devfn) == 0xE)
+ 		/* Built-in - assume it's under superio. */
+ 		superio_ide_init_iops(hwif);
 -	}
--
--	if (!OK_STAT(stat, READY_STAT, BAD_STAT))
--		return ide_error(drive, "drive_cmd", stat);
--		/* calls ide_end_drive_cmd */
--	ide_end_drive_cmd(drive, stat, hwif->INB(IDE_ERROR_REG));
--	return ide_stopped;
-+	tf->nsect   = drive->sect;
-+	tf->command = WIN_RESTORE;
  }
+ #endif
  
--static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
-+static void ide_tf_set_setmult_cmd(ide_drive_t *drive, struct ide_taskfile *tf)
+@@ -110,8 +104,8 @@ static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
+ static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
  {
--	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
--	task->tfRegister[IDE_SECTOR_OFFSET]  = drive->sect;
--	task->tfRegister[IDE_LCYL_OFFSET]    = drive->cyl;
--	task->tfRegister[IDE_HCYL_OFFSET]    = drive->cyl>>8;
--	task->tfRegister[IDE_SELECT_OFFSET]  = ((drive->head-1)|drive->select.all)&0xBF;
--	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
--
--	task->handler = &set_geometry_intr;
--}
--
--static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
--{
--	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
--	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
--
--	task->handler = &recal_intr;
--}
--
--static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
--{
--	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
--	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
--
--	task->handler = &set_multmode_intr;
-+	tf->nsect   = drive->mult_req;
-+	tf->command = WIN_SETMULT;
- }
+ 	ide_hwif_t *hwif = HWIF(drive);
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
+-	struct pci_dev *dev = hwif->pci_dev;
+ 	unsigned long flags;
  
- static ide_startstop_t ide_disk_special(ide_drive_t *drive)
-@@ -707,19 +638,19 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
- 	ide_task_t args;
+ 	local_irq_save(flags);
+@@ -189,7 +183,7 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
  
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.command_type = IDE_DRIVE_TASK_NO_DATA;
-+	args.data_phase = TASKFILE_NO_DATA;
+ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	unsigned int ctrl, using_inta;
+ 	u8 progif;
+ #ifdef __sparc_v9__
+@@ -231,8 +225,8 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
  
- 	if (s->b.set_geometry) {
- 		s->b.set_geometry = 0;
--		ide_init_specify_cmd(drive, &args);
-+		ide_tf_set_specify_cmd(drive, &args.tf);
- 	} else if (s->b.recalibrate) {
- 		s->b.recalibrate = 0;
--		ide_init_restore_cmd(drive, &args);
-+		ide_tf_set_restore_cmd(drive, &args.tf);
- 	} else if (s->b.set_multmode) {
- 		s->b.set_multmode = 0;
- 		if (drive->mult_req > drive->id->max_multsect)
- 			drive->mult_req = drive->id->max_multsect;
--		ide_init_setmult_cmd(drive, &args);
-+		ide_tf_set_setmult_cmd(drive, &args.tf);
- 	} else if (s->all) {
- 		int special = s->all;
- 		s->all = 0;
-@@ -727,6 +658,9 @@ static ide_startstop_t ide_disk_special(ide_drive_t *drive)
- 		return ide_stopped;
- 	}
+ #ifdef __sparc_v9__
+ 		/*
+-		 * XXX: Reset the device, if we don't it will not respond
+-		 *      to SELECT_DRIVE() properly during first probe_hwif().
++		 * XXX: Reset the device, if we don't it will not respond to
++		 *      SELECT_DRIVE() properly during first ide_probe_port().
+ 		 */
+ 		timeout = 10000;
+ 		outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
+diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
+index 8953d9c..46e8748 100644
+--- a/drivers/ide/pci/opti621.c
++++ b/drivers/ide/pci/opti621.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/pci/opti621.c		Version 0.9	Sep 24, 2007
+- *
+  *  Copyright (C) 1996-1998  Linus Torvalds & authors (see below)
+  */
  
-+	args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE |
-+			IDE_TFLAG_CUSTOM_HANDLER;
+@@ -89,11 +87,6 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/pci.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+@@ -322,14 +315,18 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	spin_unlock_irqrestore(&opti621_lock, flags);
+ }
+ 
++static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
++{
++	hwif->drives[0].drive_data = PIO_DONT_KNOW;
++	hwif->drives[1].drive_data = PIO_DONT_KNOW;
++}
 +
- 	do_rw_taskfile(drive, &args);
+ /*
+  * init_hwif_opti621() is called once for each hwif found at boot.
+  */
+ static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
+ {
+-	hwif->drives[0].drive_data = PIO_DONT_KNOW;
+-	hwif->drives[1].drive_data = PIO_DONT_KNOW;
+-
++	hwif->port_init_devs = opti621_port_init_devs;
+ 	hwif->set_pio_mode = &opti621_set_pio_mode;
+ }
  
- 	return ide_started;
-@@ -801,7 +735,7 @@ static ide_startstop_t do_special (ide_drive_t *drive)
+diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
+index 2b4f44e..1c8cb77 100644
+--- a/drivers/ide/pci/pdc202xx_new.c
++++ b/drivers/ide/pci/pdc202xx_new.c
+@@ -19,18 +19,12 @@
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+-#include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
  
- 			if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) {
- 				if (keep_dma)
--					hwif->ide_dma_on(drive);
-+					ide_dma_on(drive);
- 			}
- 		}
+ #include <asm/io.h>
+-#include <asm/irq.h>
  
-@@ -861,13 +795,10 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
- 		struct request *rq)
+ #ifdef CONFIG_PPC_PMAC
+ #include <asm/prom.h>
+@@ -146,9 +140,10 @@ static struct udma_timing {
+ 	{ 0x1a, 0x01, 0xcb },	/* UDMA mode 6 */
+ };
+ 
+-static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
++static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
  {
- 	ide_hwif_t *hwif = HWIF(drive);
--	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-- 		ide_task_t *args = rq->special;
-- 
--		if (!args)
--			goto done;
-+	ide_task_t *task = rq->special;
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;
  
--		hwif->data_phase = args->data_phase;
-+	if (task) {
-+		hwif->data_phase = task->data_phase;
+ 	/*
+@@ -159,48 +154,21 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
+ 	 * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
+ 	 * chips, we must override the default register settings...
+ 	 */
+-	if (max_dma_rate(hwif->pci_dev) == 4) {
++	if (max_dma_rate(dev) == 4) {
+ 		u8 mode = speed & 0x07;
  
- 		switch (hwif->data_phase) {
- 		case TASKFILE_MULTI_OUT:
-@@ -880,57 +811,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
- 			break;
+-		switch (speed) {
+-			case XFER_UDMA_6:
+-			case XFER_UDMA_5:
+-			case XFER_UDMA_4:
+-			case XFER_UDMA_3:
+-			case XFER_UDMA_2:
+-			case XFER_UDMA_1:
+-			case XFER_UDMA_0:
+-				set_indexed_reg(hwif, 0x10 + adj,
+-						udma_timings[mode].reg10);
+-				set_indexed_reg(hwif, 0x11 + adj,
+-						udma_timings[mode].reg11);
+-				set_indexed_reg(hwif, 0x12 + adj,
+-						udma_timings[mode].reg12);
+-				break;
+-
+-			case XFER_MW_DMA_2:
+-			case XFER_MW_DMA_1:
+-			case XFER_MW_DMA_0:
+-				set_indexed_reg(hwif, 0x0e + adj,
+-						mwdma_timings[mode].reg0e);
+-				set_indexed_reg(hwif, 0x0f + adj,
+-						mwdma_timings[mode].reg0f);
+-				break;
+-			case XFER_PIO_4:
+-			case XFER_PIO_3:
+-			case XFER_PIO_2:
+-			case XFER_PIO_1:
+-			case XFER_PIO_0:
+-				set_indexed_reg(hwif, 0x0c + adj,
+-						pio_timings[mode].reg0c);
+-				set_indexed_reg(hwif, 0x0d + adj,
+-						pio_timings[mode].reg0d);
+-				set_indexed_reg(hwif, 0x13 + adj,
+-						pio_timings[mode].reg13);
+-				break;
+-			default:
+-				printk(KERN_ERR "pdc202xx_new: "
+-				       "Unknown speed %d ignored\n", speed);
++		if (speed >= XFER_UDMA_0) {
++			set_indexed_reg(hwif, 0x10 + adj,
++					udma_timings[mode].reg10);
++			set_indexed_reg(hwif, 0x11 + adj,
++					udma_timings[mode].reg11);
++			set_indexed_reg(hwif, 0x12 + adj,
++					udma_timings[mode].reg12);
++		} else {
++			set_indexed_reg(hwif, 0x0e + adj,
++					mwdma_timings[mode].reg0e);
++			set_indexed_reg(hwif, 0x0f + adj,
++					mwdma_timings[mode].reg0f);
  		}
+ 	} else if (speed == XFER_UDMA_2) {
+ 		/* Set tHOLD bit to 0 if using UDMA mode 2 */
+@@ -212,10 +180,18 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
  
--		if (args->tf_out_flags.all != 0) 
--			return flagged_taskfile(drive, args);
--		return do_rw_taskfile(drive, args);
--	} else if (rq->cmd_type == REQ_TYPE_ATA_TASK) {
--		u8 *args = rq->buffer;
-- 
--		if (!args)
--			goto done;
--#ifdef DEBUG
-- 		printk("%s: DRIVE_TASK_CMD ", drive->name);
-- 		printk("cmd=0x%02x ", args[0]);
-- 		printk("fr=0x%02x ", args[1]);
-- 		printk("ns=0x%02x ", args[2]);
-- 		printk("sc=0x%02x ", args[3]);
-- 		printk("lcyl=0x%02x ", args[4]);
-- 		printk("hcyl=0x%02x ", args[5]);
-- 		printk("sel=0x%02x\n", args[6]);
--#endif
-- 		hwif->OUTB(args[1], IDE_FEATURE_REG);
-- 		hwif->OUTB(args[3], IDE_SECTOR_REG);
-- 		hwif->OUTB(args[4], IDE_LCYL_REG);
-- 		hwif->OUTB(args[5], IDE_HCYL_REG);
-- 		hwif->OUTB((args[6] & 0xEF)|drive->select.all, IDE_SELECT_REG);
-- 		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
-- 		return ide_started;
-- 	} else if (rq->cmd_type == REQ_TYPE_ATA_CMD) {
-- 		u8 *args = rq->buffer;
--
--		if (!args)
--			goto done;
--#ifdef DEBUG
-- 		printk("%s: DRIVE_CMD ", drive->name);
-- 		printk("cmd=0x%02x ", args[0]);
-- 		printk("sc=0x%02x ", args[1]);
-- 		printk("fr=0x%02x ", args[2]);
-- 		printk("xx=0x%02x\n", args[3]);
--#endif
-- 		if (args[0] == WIN_SMART) {
-- 			hwif->OUTB(0x4f, IDE_LCYL_REG);
-- 			hwif->OUTB(0xc2, IDE_HCYL_REG);
-- 			hwif->OUTB(args[2],IDE_FEATURE_REG);
-- 			hwif->OUTB(args[1],IDE_SECTOR_REG);
-- 			ide_cmd(drive, args[0], args[3], &drive_cmd_intr);
-- 			return ide_started;
-- 		}
-- 		hwif->OUTB(args[2],IDE_FEATURE_REG);
-- 		ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
-- 		return ide_started;
-- 	}
--
--done:
-+		return do_rw_taskfile(drive, task);
-+	}
+ static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+-	pdcnew_set_mode(drive, XFER_PIO_0 + pio);
++	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
 +
-  	/*
-  	 * NULL is actually a valid way of waiting for
-  	 * all current requests to be flushed from the queue.
-@@ -970,8 +853,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
- 		if (rc)
- 			printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
- 		SELECT_DRIVE(drive);
--		if (IDE_CONTROL_REG)
--			HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG);
-+		ide_set_irq(drive, 1);
- 		rc = ide_wait_not_busy(HWIF(drive), 100000);
- 		if (rc)
- 			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
-@@ -1003,6 +885,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
++	if (max_dma_rate(dev) == 4) {
++		set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
++		set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
++		set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
++	}
+ }
  
- 	/* bail early if we've exceeded max_failures */
- 	if (drive->max_failures && (drive->failures > drive->max_failures)) {
-+		rq->cmd_flags |= REQ_FAILED;
- 		goto kill_rq;
- 	}
+-static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
++static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif)
+ {
+ 	if (get_indexed_reg(hwif, 0x0b) & 0x04)
+ 		return ATA_CBL_PATA40;
+@@ -223,14 +199,17 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
+ 		return ATA_CBL_PATA80;
+ }
  
-@@ -1034,9 +917,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
- 		if (drive->current_speed == 0xff)
- 			ide_config_drive_speed(drive, drive->desired_speed);
+-static int pdcnew_quirkproc(ide_drive_t *drive)
++static void pdcnew_quirkproc(ide_drive_t *drive)
+ {
+ 	const char **list, *model = drive->id->model;
  
--		if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
--		    rq->cmd_type == REQ_TYPE_ATA_TASK ||
--		    rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
-+		if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
- 			return execute_drive_cmd(drive, rq);
- 		else if (blk_pm_request(rq)) {
- 			struct request_pm_state *pm = rq->data;
-@@ -1244,11 +1125,13 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
- 		}
- 	again:
- 		hwif = HWIF(drive);
--		if (hwgroup->hwif->sharing_irq &&
--		    hwif != hwgroup->hwif &&
--		    hwif->io_ports[IDE_CONTROL_OFFSET]) {
--			/* set nIEN for previous hwif */
--			SELECT_INTERRUPT(drive);
-+		if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) {
-+			/*
-+			 * set nIEN for previous hwif, drives in the
-+			 * quirk_list may not like intr setups/cleanups
-+			 */
-+			if (drive->quirk_list != 1)
-+				ide_set_irq(drive, 0);
- 		}
- 		hwgroup->hwif = hwif;
- 		hwgroup->drive = drive;
-@@ -1361,7 +1244,7 @@ static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error)
- 	 */
- 	drive->retry_pio++;
- 	drive->state = DMA_PIO_RETRY;
--	hwif->dma_off_quietly(drive);
-+	ide_dma_off_quietly(drive);
+ 	for (list = pdc_quirk_drives; *list != NULL; list++)
+-		if (strstr(model, *list) != NULL)
+-			return 2;
+-	return 0;
++		if (strstr(model, *list) != NULL) {
++			drive->quirk_list = 2;
++			return;
++		}
++
++	drive->quirk_list = 0;
+ }
  
- 	/*
- 	 * un-busy drive etc (hwgroup->busy is cleared on return) and
-@@ -1454,12 +1337,8 @@ void ide_timer_expiry (unsigned long data)
- 			 */
- 			spin_unlock(&ide_lock);
- 			hwif  = HWIF(drive);
--#if DISABLE_IRQ_NOSYNC
--			disable_irq_nosync(hwif->irq);
--#else
- 			/* disable_irq_nosync ?? */
- 			disable_irq(hwif->irq);
--#endif /* DISABLE_IRQ_NOSYNC */
- 			/* local CPU only,
- 			 * as if we were handling an interrupt */
- 			local_irq_disable();
-@@ -1608,7 +1487,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
- 		 * remove all the ifdef PCI crap
- 		 */
- #ifdef CONFIG_BLK_DEV_IDEPCI
--		if (hwif->pci_dev && !hwif->pci_dev->vendor)
-+		if (hwif->chipset != ide_pci)
- #endif	/* CONFIG_BLK_DEV_IDEPCI */
- 		{
- 			/*
-@@ -1710,7 +1589,6 @@ irqreturn_t ide_intr (int irq, void *dev_id)
- void ide_init_drive_cmd (struct request *rq)
+ static void pdcnew_reset(ide_drive_t *drive)
+@@ -466,16 +445,12 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
+ static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
  {
- 	memset(rq, 0, sizeof(*rq));
--	rq->cmd_type = REQ_TYPE_ATA_CMD;
- 	rq->ref_count = 1;
- }
+ 	hwif->set_pio_mode = &pdcnew_set_pio_mode;
+-	hwif->set_dma_mode = &pdcnew_set_mode;
++	hwif->set_dma_mode = &pdcnew_set_dma_mode;
  
-@@ -1785,3 +1663,19 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
+ 	hwif->quirkproc = &pdcnew_quirkproc;
+ 	hwif->resetproc = &pdcnew_reset;
+ 
+-	if (hwif->dma_base == 0)
+-		return;
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = pdcnew_cable_detect(hwif);
++	hwif->cable_detect = pdcnew_cable_detect;
  }
  
- EXPORT_SYMBOL(ide_do_drive_cmd);
-+
-+void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
-+{
-+	ide_task_t task;
-+
-+	memset(&task, 0, sizeof(task));
-+	task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM |
-+			IDE_TFLAG_OUT_FEATURE | tf_flags;
-+	task.tf.feature = dma;		/* Use PIO/DMA */
-+	task.tf.lbam    = bcount & 0xff;
-+	task.tf.lbah    = (bcount >> 8) & 0xff;
-+
-+	ide_tf_load(drive, &task);
-+}
-+
-+EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
-diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
-index bb9693d..a95178f 100644
---- a/drivers/ide/ide-iops.c
-+++ b/drivers/ide/ide-iops.c
+ static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
+diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
+index e09742e..da43297 100644
+--- a/drivers/ide/pci/pdc202xx_old.c
++++ b/drivers/ide/pci/pdc202xx_old.c
 @@ -1,6 +1,4 @@
  /*
-- * linux/drivers/ide/ide-iops.c	Version 0.37	Mar 05, 2003
+- *  linux/drivers/ide/pci/pdc202xx_old.c	Version 0.52	Aug 27, 2007
 - *
-  *  Copyright (C) 2000-2002	Andre Hedrick <andre at linux-ide.org>
-  *  Copyright (C) 2003		Red Hat <alan at redhat.com>
-  *
-@@ -158,14 +156,6 @@ void default_hwif_mmiops (ide_hwif_t *hwif)
+  *  Copyright (C) 1998-2002		Andre Hedrick <andre at linux-ide.org>
+  *  Copyright (C) 2006-2007		MontaVista Software, Inc.
+  *  Copyright (C) 2007			Bartlomiej Zolnierkiewicz
+@@ -34,18 +32,13 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+ #include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+-#include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
  
- EXPORT_SYMBOL(default_hwif_mmiops);
+ #include <asm/io.h>
+-#include <asm/irq.h>
  
--u32 ide_read_24 (ide_drive_t *drive)
--{
--	u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG);
--	u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG);
--	u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG);
--	return (hcyl<<16)|(lcyl<<8)|sect;
--}
--
- void SELECT_DRIVE (ide_drive_t *drive)
+ #define PDC202XX_DEBUG_DRIVE_INFO	0
+ 
+@@ -66,7 +59,7 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
+ static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
  {
- 	if (HWIF(drive)->selectproc)
-@@ -173,28 +163,12 @@ void SELECT_DRIVE (ide_drive_t *drive)
- 	HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 drive_pci		= 0x60 + (drive->dn << 2);
+ 
+ 	u8			AP = 0, BP = 0, CP = 0;
+@@ -142,11 +135,12 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
  }
  
--EXPORT_SYMBOL(SELECT_DRIVE);
--
--void SELECT_INTERRUPT (ide_drive_t *drive)
--{
--	if (HWIF(drive)->intrproc)
--		HWIF(drive)->intrproc(drive);
--	else
--		HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);
--}
--
- void SELECT_MASK (ide_drive_t *drive, int mask)
+-static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
++static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif)
  {
- 	if (HWIF(drive)->maskproc)
- 		HWIF(drive)->maskproc(drive, mask);
+-	u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
+ 
+-	pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
++	pci_read_config_word(dev, 0x50, &CIS);
+ 
+ 	return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
  }
+@@ -162,7 +156,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
+  */
+ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
+ {
+-	unsigned long clock_reg = hwif->dma_master + 0x11;
++	unsigned long clock_reg = hwif->extra_base + 0x01;
+ 	u8 clock = inb(clock_reg);
  
--void QUIRK_LIST (ide_drive_t *drive)
--{
--	if (HWIF(drive)->quirkproc)
--		drive->quirk_list = HWIF(drive)->quirkproc(drive);
--}
--
- /*
-  * Some localbus EIDE interfaces require a special access sequence
-  * when using 32-bit I/O instructions to transfer data.  We call this
-@@ -449,7 +423,6 @@ int drive_is_ready (ide_drive_t *drive)
- 	udelay(1);
- #endif
+ 	outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
+@@ -170,20 +164,23 @@ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
  
--#ifdef CONFIG_IDEPCI_SHARE_IRQ
- 	/*
- 	 * We do a passive status test under shared PCI interrupts on
- 	 * cards that truly share the ATA side interrupt, but may also share
-@@ -459,7 +432,6 @@ int drive_is_ready (ide_drive_t *drive)
- 	if (IDE_CONTROL_REG)
- 		stat = hwif->INB(IDE_ALTSTATUS_REG);
- 	else
--#endif /* CONFIG_IDEPCI_SHARE_IRQ */
- 		/* Note: this may clear a pending IRQ!! */
- 		stat = hwif->INB(IDE_STATUS_REG);
+ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
+ {
+-	unsigned long clock_reg = hwif->dma_master + 0x11;
++	unsigned long clock_reg = hwif->extra_base + 0x01;
+ 	u8 clock = inb(clock_reg);
  
-@@ -640,66 +612,6 @@ no_80w:
- 	return 0;
+ 	outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
  }
  
--int ide_ata66_check (ide_drive_t *drive, ide_task_t *args)
--{
--	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
--	    (args->tfRegister[IDE_SECTOR_OFFSET] > XFER_UDMA_2) &&
--	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER)) {
--		if (eighty_ninty_three(drive) == 0) {
--			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
--					    "be set\n", drive->name);
--			return 1;
--		}
--	}
--
--	return 0;
--}
--
--/*
-- * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER.
-- * 1 : Safe to update drive->id DMA registers.
-- * 0 : OOPs not allowed.
-- */
--int set_transfer (ide_drive_t *drive, ide_task_t *args)
--{
--	if ((args->tfRegister[IDE_COMMAND_OFFSET] == WIN_SETFEATURES) &&
--	    (args->tfRegister[IDE_SECTOR_OFFSET] >= XFER_SW_DMA_0) &&
--	    (args->tfRegister[IDE_FEATURE_OFFSET] == SETFEATURES_XFER) &&
--	    (drive->id->dma_ultra ||
--	     drive->id->dma_mword ||
--	     drive->id->dma_1word))
--		return 1;
--
--	return 0;
--}
--
--#ifdef CONFIG_BLK_DEV_IDEDMA
--static u8 ide_auto_reduce_xfer (ide_drive_t *drive)
--{
--	if (!drive->crc_count)
--		return drive->current_speed;
--	drive->crc_count = 0;
--
--	switch(drive->current_speed) {
--		case XFER_UDMA_7:	return XFER_UDMA_6;
--		case XFER_UDMA_6:	return XFER_UDMA_5;
--		case XFER_UDMA_5:	return XFER_UDMA_4;
--		case XFER_UDMA_4:	return XFER_UDMA_3;
--		case XFER_UDMA_3:	return XFER_UDMA_2;
--		case XFER_UDMA_2:	return XFER_UDMA_1;
--		case XFER_UDMA_1:	return XFER_UDMA_0;
--			/*
--			 * OOPS we do not goto non Ultra DMA modes
--			 * without iCRC's available we force
--			 * the system to PIO and make the user
--			 * invoke the ATA-1 ATA-2 DMA modes.
--			 */
--		case XFER_UDMA_0:
--		default:		return XFER_PIO_4;
--	}
--}
--#endif /* CONFIG_BLK_DEV_IDEDMA */
--
- int ide_driveid_update(ide_drive_t *drive)
+-static int pdc202xx_quirkproc (ide_drive_t *drive)
++static void pdc202xx_quirkproc(ide_drive_t *drive)
  {
- 	ide_hwif_t *hwif = drive->hwif;
-@@ -712,8 +624,7 @@ int ide_driveid_update(ide_drive_t *drive)
- 	 */
+ 	const char **list, *model = drive->id->model;
  
- 	SELECT_MASK(drive, 1);
--	if (IDE_CONTROL_REG)
--		hwif->OUTB(drive->ctl,IDE_CONTROL_REG);
-+	ide_set_irq(drive, 1);
- 	msleep(50);
- 	hwif->OUTB(WIN_IDENTIFY, IDE_COMMAND_REG);
- 	timeout = jiffies + WAIT_WORSTCASE;
-@@ -766,8 +677,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
- //		msleep(50);
+ 	for (list = pdc_quirk_drives; *list != NULL; list++)
+-		if (strstr(model, *list) != NULL)
+-			return 2;
+-	return 0;
++		if (strstr(model, *list) != NULL) {
++			drive->quirk_list = 2;
++			return;
++		}
++
++	drive->quirk_list = 0;
+ }
  
- #ifdef CONFIG_BLK_DEV_IDEDMA
--	if (hwif->ide_dma_on)	/* check if host supports DMA */
--		hwif->dma_host_off(drive);
-+	if (hwif->dma_host_set)	/* check if host supports DMA */
-+		hwif->dma_host_set(drive, 0);
- #endif
+ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
+@@ -193,7 +190,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
+ 	if (drive->media != ide_disk || drive->addressing == 1) {
+ 		struct request *rq	= HWGROUP(drive)->rq;
+ 		ide_hwif_t *hwif	= HWIF(drive);
+-		unsigned long high_16   = hwif->dma_master;
++		unsigned long high_16	= hwif->extra_base - 16;
+ 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
+ 		u32 word_count	= 0;
+ 		u8 clock = inb(high_16 + 0x11);
+@@ -212,7 +209,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
+ {
+ 	if (drive->media != ide_disk || drive->addressing == 1) {
+ 		ide_hwif_t *hwif	= HWIF(drive);
+-		unsigned long high_16	= hwif->dma_master;
++		unsigned long high_16	= hwif->extra_base - 16;
+ 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
+ 		u8 clock		= 0;
  
- 	/* Skip setting PIO flow-control modes on pre-EIDE drives */
-@@ -796,13 +707,12 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
- 	SELECT_DRIVE(drive);
- 	SELECT_MASK(drive, 0);
- 	udelay(1);
--	if (IDE_CONTROL_REG)
--		hwif->OUTB(drive->ctl | 2, IDE_CONTROL_REG);
-+	ide_set_irq(drive, 0);
- 	hwif->OUTB(speed, IDE_NSECTOR_REG);
- 	hwif->OUTB(SETFEATURES_XFER, IDE_FEATURE_REG);
- 	hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
--	if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
--		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
-+	if (drive->quirk_list == 2)
-+		ide_set_irq(drive, 1);
+@@ -228,7 +225,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
+ static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	unsigned long high_16	= hwif->dma_master;
++	unsigned long high_16	= hwif->extra_base - 16;
+ 	u8 dma_stat		= inb(hwif->dma_status);
+ 	u8 sc1d			= inb(high_16 + 0x001d);
  
- 	error = __ide_wait_stat(drive, drive->ready_stat,
- 				BUSY_STAT|DRQ_STAT|ERR_STAT,
-@@ -823,10 +733,11 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
+@@ -271,7 +268,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
  
-  skip:
- #ifdef CONFIG_BLK_DEV_IDEDMA
--	if (speed >= XFER_SW_DMA_0)
--		hwif->dma_host_on(drive);
--	else if (hwif->ide_dma_on)	/* check if host supports DMA */
--		hwif->dma_off_quietly(drive);
-+	if ((speed >= XFER_SW_DMA_0 || (hwif->host_flags & IDE_HFLAG_VDMA)) &&
-+	    drive->using_dma)
-+		hwif->dma_host_set(drive, 1);
-+	else if (hwif->dma_host_set)	/* check if host supports DMA */
-+		ide_dma_off_quietly(drive);
- #endif
+ static void pdc202xx_reset_host (ide_hwif_t *hwif)
+ {
+-	unsigned long high_16	= hwif->dma_master;
++	unsigned long high_16	= hwif->extra_base - 16;
+ 	u8 udma_speed_flag	= inb(high_16 | 0x001f);
  
- 	switch(speed) {
-@@ -902,28 +813,24 @@ EXPORT_SYMBOL(ide_set_handler);
-  *	handler and IRQ setup do not race. All IDE command kick off
-  *	should go via this function or do equivalent locking.
-  */
-- 
--void ide_execute_command(ide_drive_t *drive, task_ioreg_t cmd, ide_handler_t *handler, unsigned timeout, ide_expiry_t *expiry)
-+
-+void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
-+			 unsigned timeout, ide_expiry_t *expiry)
+ 	outb(udma_speed_flag | 0x10, high_16 | 0x001f);
+@@ -302,24 +299,26 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
+ 
+ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
  {
- 	unsigned long flags;
- 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
- 	ide_hwif_t *hwif = HWIF(drive);
--	
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
 +
- 	spin_lock_irqsave(&ide_lock, flags);
--	
- 	BUG_ON(hwgroup->handler);
--	hwgroup->handler	= handler;
--	hwgroup->expiry		= expiry;
--	hwgroup->timer.expires	= jiffies + timeout;
--	hwgroup->req_gen_timer = hwgroup->req_gen;
--	add_timer(&hwgroup->timer);
-+	__ide_set_handler(drive, handler, timeout, expiry);
- 	hwif->OUTBSYNC(drive, cmd, IDE_COMMAND_REG);
--	/* Drive takes 400nS to respond, we must avoid the IRQ being
--	   serviced before that. 
--	   
--	   FIXME: we could skip this delay with care on non shared
--	   devices 
--	*/
-+	/*
-+	 * Drive takes 400nS to respond, we must avoid the IRQ being
-+	 * serviced before that.
-+	 *
-+	 * FIXME: we could skip this delay with care on non shared devices
-+	 */
- 	ndelay(400);
- 	spin_unlock_irqrestore(&ide_lock, flags);
- }
-@@ -1031,19 +938,6 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
- 	return ide_stopped;
- }
+ 	hwif->set_pio_mode = &pdc202xx_set_pio_mode;
+ 	hwif->set_dma_mode = &pdc202xx_set_mode;
  
--static void check_dma_crc(ide_drive_t *drive)
--{
--#ifdef CONFIG_BLK_DEV_IDEDMA
--	if (drive->crc_count) {
--		drive->hwif->dma_off_quietly(drive);
--		ide_set_xfer_rate(drive, ide_auto_reduce_xfer(drive));
--		if (drive->current_speed >= XFER_SW_DMA_0)
--			(void) HWIF(drive)->ide_dma_on(drive);
--	} else
--		ide_dma_off(drive);
--#endif
--}
--
- static void ide_disk_pre_reset(ide_drive_t *drive)
- {
- 	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
-@@ -1051,8 +945,7 @@ static void ide_disk_pre_reset(ide_drive_t *drive)
- 	drive->special.all = 0;
- 	drive->special.b.set_geometry = legacy;
- 	drive->special.b.recalibrate  = legacy;
--	if (OK_TO_RESET_CONTROLLER)
--		drive->mult_count = 0;
-+	drive->mult_count = 0;
- 	if (!drive->keep_settings && !drive->using_dma)
- 		drive->mult_req = 0;
- 	if (drive->mult_req != drive->mult_count)
-@@ -1066,17 +959,20 @@ static void pre_reset(ide_drive_t *drive)
- 	else
- 		drive->post_reset = 1;
+ 	hwif->quirkproc = &pdc202xx_quirkproc;
  
-+	if (drive->using_dma) {
-+		if (drive->crc_count)
-+			ide_check_dma_crc(drive);
-+		else
-+			ide_dma_off(drive);
+-	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
++	if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
+ 		hwif->resetproc = &pdc202xx_reset;
+ 
++		hwif->cable_detect = pdc2026x_old_cable_detect;
 +	}
 +
- 	if (!drive->keep_settings) {
--		if (drive->using_dma) {
--			check_dma_crc(drive);
--		} else {
-+		if (!drive->using_dma) {
- 			drive->unmask = 0;
- 			drive->io_32bit = 0;
- 		}
+ 	if (hwif->dma_base == 0)
  		return;
- 	}
--	if (drive->using_dma)
--		check_dma_crc(drive);
  
- 	if (HWIF(drive)->pre_reset != NULL)
- 		HWIF(drive)->pre_reset(drive);
-@@ -1137,7 +1033,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
- 	for (unit = 0; unit < MAX_DRIVES; ++unit)
- 		pre_reset(&hwif->drives[unit]);
+ 	hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
+ 	hwif->dma_timeout = &pdc202xx_dma_timeout;
  
--#if OK_TO_RESET_CONTROLLER
- 	if (!IDE_CONTROL_REG) {
- 		spin_unlock_irqrestore(&ide_lock, flags);
- 		return ide_stopped;
-@@ -1174,11 +1069,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
- 	 * state when the disks are reset this way. At least, the Winbond
- 	 * 553 documentation says that
- 	 */
--	if (hwif->resetproc != NULL) {
-+	if (hwif->resetproc)
- 		hwif->resetproc(drive);
--	}
--	
--#endif	/* OK_TO_RESET_CONTROLLER */
+-	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
+-		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-			hwif->cbl = pdc202xx_old_cable_detect(hwif);
+-
++	if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
+ 		hwif->dma_start = &pdc202xx_old_ide_dma_start;
+ 		hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
+ 	} 
+@@ -331,7 +330,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
+ 	u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
  
- 	spin_unlock_irqrestore(&ide_lock, flags);
- 	return ide_started;
-@@ -1197,7 +1089,7 @@ EXPORT_SYMBOL(ide_do_reset);
+ 	if (hwif->channel) {
+-		ide_setup_dma(hwif, dmabase, 8);
++		ide_setup_dma(hwif, dmabase);
+ 		return;
+ 	}
  
- /*
-  * ide_wait_not_busy() waits for the currently selected device on the hwif
-- * to report a non-busy status, see comments in probe_hwif().
-+ * to report a non-busy status, see comments in ide_probe_port().
-  */
- int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout)
- {
-diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
-index 062d3bc..b42940d 100644
---- a/drivers/ide/ide-lib.c
-+++ b/drivers/ide/ide-lib.c
-@@ -358,8 +358,10 @@ void ide_toggle_bounce(ide_drive_t *drive, int on)
- 	if (!PCI_DMA_BUS_IS_PHYS) {
- 		addr = BLK_BOUNCE_ANY;
- 	} else if (on && drive->media == ide_disk) {
--		if (HWIF(drive)->pci_dev)
--			addr = HWIF(drive)->pci_dev->dma_mask;
-+		struct device *dev = drive->hwif->dev;
-+
-+		if (dev && dev->dma_mask)
-+			addr = *dev->dma_mask;
+@@ -355,7 +354,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
  	}
+ #endif /* CONFIG_PDC202XX_BURST */
  
- 	if (drive->queue)
-@@ -441,6 +443,12 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
- 	 * case could happen iff the transfer mode has already been set on
- 	 * the device by ide-proc.c::set_xfer_rate()).
- 	 */
-+	if (rate < XFER_PIO_0) {
-+		if (hwif->host_flags & IDE_HFLAG_ABUSE_SET_DMA_MODE)
-+			return ide_set_dma_mode(drive, rate);
-+		else
-+			return ide_config_drive_speed(drive, rate);
-+	}
+-	ide_setup_dma(hwif, dmabase, 8);
++	ide_setup_dma(hwif, dmabase);
+ }
  
- 	return ide_set_dma_mode(drive, rate);
+ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+@@ -375,6 +374,11 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+ 	}
  }
-@@ -448,8 +456,7 @@ int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
- static void ide_dump_opcode(ide_drive_t *drive)
- {
- 	struct request *rq;
--	u8 opcode = 0;
--	int found = 0;
-+	ide_task_t *task = NULL;
  
- 	spin_lock(&ide_lock);
- 	rq = NULL;
-@@ -458,164 +465,129 @@ static void ide_dump_opcode(ide_drive_t *drive)
- 	spin_unlock(&ide_lock);
- 	if (!rq)
- 		return;
--	if (rq->cmd_type == REQ_TYPE_ATA_CMD ||
--	    rq->cmd_type == REQ_TYPE_ATA_TASK) {
--		char *args = rq->buffer;
--		if (args) {
--			opcode = args[0];
--			found = 1;
--		}
--	} else if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
--		ide_task_t *args = rq->special;
--		if (args) {
--			task_struct_t *tf = (task_struct_t *) args->tfRegister;
--			opcode = tf->command;
--			found = 1;
--		}
--	}
++#define IDE_HFLAGS_PDC202XX \
++	(IDE_HFLAG_ERROR_STOPS_FIFO | \
++	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
++	 IDE_HFLAG_OFF_BOARD)
 +
-+	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE)
-+		task = rq->special;
- 
- 	printk("ide: failed opcode was: ");
--	if (!found)
--		printk("unknown\n");
-+	if (task == NULL)
-+		printk(KERN_CONT "unknown\n");
- 	else
--		printk("0x%02x\n", opcode);
-+		printk(KERN_CONT "0x%02x\n", task->tf.command);
- }
+ #define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
+ 	{ \
+ 		.name		= name_str, \
+@@ -382,9 +386,7 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+ 		.init_hwif	= init_hwif_pdc202xx, \
+ 		.init_dma	= init_dma_pdc202xx, \
+ 		.extra		= 48, \
+-		.host_flags	= IDE_HFLAG_ERROR_STOPS_FIFO | \
+-				  extra_flags | \
+-				  IDE_HFLAG_OFF_BOARD, \
++		.host_flags	= IDE_HFLAGS_PDC202XX | extra_flags, \
+ 		.pio_mask	= ATA_PIO4, \
+ 		.mwdma_mask	= ATA_MWDMA2, \
+ 		.udma_mask	= udma, \
+@@ -397,8 +399,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
+ 		.init_hwif	= init_hwif_pdc202xx,
+ 		.init_dma	= init_dma_pdc202xx,
+ 		.extra		= 16,
+-		.host_flags	= IDE_HFLAG_ERROR_STOPS_FIFO |
+-				  IDE_HFLAG_OFF_BOARD,
++		.host_flags	= IDE_HFLAGS_PDC202XX,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA2,
+diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
+index 27781d2..decef0f 100644
+--- a/drivers/ide/pci/piix.c
++++ b/drivers/ide/pci/piix.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/pci/piix.c	Version 0.54	Sep 5, 2007
+- *
+  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
+  *  Copyright (C) 1998-2000 Andre Hedrick <andre at linux-ide.org>
+  *  Copyright (C) 2003 Red Hat Inc <alan at redhat.com>
+@@ -8,53 +6,8 @@
+  *
+  *  May be copied or modified under the terms of the GNU General Public License
+  *
+- *  PIO mode setting function for Intel chipsets.
+- *  For use instead of BIOS settings.
+- *
+- * 40-41
+- * 42-43
+- * 
+- *                 41
+- *                 43
+- *
+- * | PIO 0       | c0 | 80 | 0 |
+- * | PIO 2 | SW2 | d0 | 90 | 4 |
+- * | PIO 3 | MW1 | e1 | a1 | 9 |
+- * | PIO 4 | MW2 | e3 | a3 | b |
+- *
+- * sitre = word40 & 0x4000; primary
+- * sitre = word42 & 0x4000; secondary
+- *
+- * 44 8421|8421    hdd|hdb
+- *
+- * 48 8421         hdd|hdc|hdb|hda udma enabled
+- *
+- *    0001         hda
+- *    0010         hdb
+- *    0100         hdc
+- *    1000         hdd
+- *
+- * 4a 84|21        hdb|hda
+- * 4b 84|21        hdd|hdc
+- *
+- *    ata-33/82371AB
+- *    ata-33/82371EB
+- *    ata-33/82801AB            ata-66/82801AA
+- *    00|00 udma 0              00|00 reserved
+- *    01|01 udma 1              01|01 udma 3
+- *    10|10 udma 2              10|10 udma 4
+- *    11|11 reserved            11|11 reserved
++ * Documentation:
+  *
+- * 54 8421|8421    ata66 drive|ata66 enable
+- *
+- * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
+- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
+- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
+- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, &reg48);
+- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
+- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &reg54);
+- *
+- * Documentation
+  *	Publically available from Intel web site. Errata documentation
+  * is also publically available. As an aide to anyone hacking on this
+  * driver the list of errata that are relevant is below.going back to
+@@ -94,11 +47,9 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/ioport.h>
+ #include <linux/pci.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+-#include <linux/delay.h>
+ #include <linux/init.h>
  
--static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
-+u64 ide_get_lba_addr(struct ide_taskfile *tf, int lba48)
+ #include <asm/io.h>
+@@ -116,7 +67,7 @@ static int no_piix_dma;
+ static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
  {
--	ide_hwif_t *hwif = HWIF(drive);
--	unsigned long flags;
--	u8 err = 0;
-+	u32 high, low;
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	int is_slave		= drive->dn & 1;
+ 	int master_port		= hwif->channel ? 0x42 : 0x40;
+ 	int slave_port		= 0x44;
+@@ -185,7 +136,7 @@ static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
+ 	int a_speed		= 3 << (drive->dn * 4);
+ 	int u_flag		= 1 << drive->dn;
+@@ -203,20 +154,11 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	pci_read_config_byte(dev, 0x54, &reg54);
+ 	pci_read_config_byte(dev, 0x55, &reg55);
  
--	local_irq_save(flags);
--	printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
--	if (stat & BUSY_STAT)
--		printk("Busy ");
--	else {
--		if (stat & READY_STAT)	printk("DriveReady ");
--		if (stat & WRERR_STAT)	printk("DeviceFault ");
--		if (stat & SEEK_STAT)	printk("SeekComplete ");
--		if (stat & DRQ_STAT)	printk("DataRequest ");
--		if (stat & ECC_STAT)	printk("CorrectedError ");
--		if (stat & INDEX_STAT)	printk("Index ");
--		if (stat & ERR_STAT)	printk("Error ");
-+	if (lba48)
-+		high = (tf->hob_lbah << 16) | (tf->hob_lbam << 8) |
-+			tf->hob_lbal;
-+	else
-+		high = tf->device & 0xf;
-+	low  = (tf->lbah << 16) | (tf->lbam << 8) | tf->lbal;
-+
-+	return ((u64)high << 24) | low;
-+}
-+EXPORT_SYMBOL_GPL(ide_get_lba_addr);
-+
-+static void ide_dump_sector(ide_drive_t *drive)
-+{
-+	ide_task_t task;
-+	struct ide_taskfile *tf = &task.tf;
-+	int lba48 = (drive->addressing == 1) ? 1 : 0;
-+
-+	memset(&task, 0, sizeof(task));
-+	if (lba48)
-+		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_HOB_LBA |
-+				IDE_TFLAG_LBA48;
-+	else
-+		task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
-+
-+	ide_tf_read(drive, &task);
+-	switch(speed) {
+-		case XFER_UDMA_4:
+-		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
+-		case XFER_UDMA_5:
+-		case XFER_UDMA_3:
+-		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
+-		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_SW_DMA_2:	break;
+-		default:		return;
+-	}
+-
+ 	if (speed >= XFER_UDMA_0) {
++		u8 udma = speed - XFER_UDMA_0;
 +
-+	if (lba48 || (tf->device & ATA_LBA))
-+		printk(", LBAsect=%llu",
-+			(unsigned long long)ide_get_lba_addr(tf, lba48));
-+	else
-+		printk(", CHS=%d/%d/%d", (tf->lbah << 8) + tf->lbam,
-+					 tf->device & 0xf, tf->lbal);
-+}
++		u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
 +
-+static void ide_dump_ata_error(ide_drive_t *drive, u8 err)
-+{
-+	printk("{ ");
-+	if (err & ABRT_ERR)	printk("DriveStatusError ");
-+	if (err & ICRC_ERR)
-+		printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
-+	if (err & ECC_ERR)	printk("UncorrectableError ");
-+	if (err & ID_ERR)	printk("SectorIdNotFound ");
-+	if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
-+	if (err & MARK_ERR)	printk("AddrMarkNotFound ");
-+	printk("}");
-+	if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
-+	    (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
-+		ide_dump_sector(drive);
-+		if (HWGROUP(drive) && HWGROUP(drive)->rq)
-+			printk(", sector=%llu",
-+			       (unsigned long long)HWGROUP(drive)->rq->sector);
- 	}
-+	printk("\n");
-+}
+ 		if (!(reg48 & u_flag))
+ 			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
+ 		if (speed == XFER_UDMA_5) {
+@@ -314,7 +256,7 @@ static const struct ich_laptop ich_laptop[] = {
+ 
+ static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *pdev = hwif->pci_dev;
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ 	const struct ich_laptop *lap = &ich_laptop[0];
+ 	u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
+ 
+@@ -346,14 +288,11 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
+ 	hwif->set_pio_mode = &piix_set_pio_mode;
+ 	hwif->set_dma_mode = &piix_set_dma_mode;
+ 
++	hwif->cable_detect = piix_cable_detect;
 +
-+static void ide_dump_atapi_error(ide_drive_t *drive, u8 err)
-+{
-+	printk("{ ");
-+	if (err & ILI_ERR)	printk("IllegalLengthIndication ");
-+	if (err & EOM_ERR)	printk("EndOfMedia ");
-+	if (err & ABRT_ERR)	printk("AbortedCommand ");
-+	if (err & MCR_ERR)	printk("MediaChangeRequested ");
-+	if (err & LFS_ERR)	printk("LastFailedSense=0x%02x ",
-+				       (err & LFS_ERR) >> 4);
- 	printk("}\n");
--	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
--		err = hwif->INB(IDE_ERROR_REG);
--		printk("%s: %s: error=0x%02x { ", drive->name, msg, err);
--		if (err & ABRT_ERR)	printk("DriveStatusError ");
--		if (err & ICRC_ERR)
--			printk((err & ABRT_ERR) ? "BadCRC " : "BadSector ");
--		if (err & ECC_ERR)	printk("UncorrectableError ");
--		if (err & ID_ERR)	printk("SectorIdNotFound ");
--		if (err & TRK0_ERR)	printk("TrackZeroNotFound ");
--		if (err & MARK_ERR)	printk("AddrMarkNotFound ");
--		printk("}");
--		if ((err & (BBD_ERR | ABRT_ERR)) == BBD_ERR ||
--		    (err & (ECC_ERR|ID_ERR|MARK_ERR))) {
--			if (drive->addressing == 1) {
--				__u64 sectors = 0;
--				u32 low = 0, high = 0;
--				hwif->OUTB(drive->ctl&~0x80, IDE_CONTROL_REG);
--				low = ide_read_24(drive);
--				hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG);
--				high = ide_read_24(drive);
--				sectors = ((__u64)high << 24) | low;
--				printk(", LBAsect=%llu, high=%d, low=%d",
--				       (unsigned long long) sectors,
--				       high, low);
--			} else {
--				u8 cur = hwif->INB(IDE_SELECT_REG);
--				if (cur & 0x40) {	/* using LBA? */
--					printk(", LBAsect=%ld", (unsigned long)
--					 ((cur&0xf)<<24)
--					 |(hwif->INB(IDE_HCYL_REG)<<16)
--					 |(hwif->INB(IDE_LCYL_REG)<<8)
--					 | hwif->INB(IDE_SECTOR_REG));
--				} else {
--					printk(", CHS=%d/%d/%d",
--					 (hwif->INB(IDE_HCYL_REG)<<8) +
--					  hwif->INB(IDE_LCYL_REG),
--					  cur & 0xf,
--					  hwif->INB(IDE_SECTOR_REG));
--				}
--			}
--			if (HWGROUP(drive) && HWGROUP(drive)->rq)
--				printk(", sector=%llu",
--					(unsigned long long)HWGROUP(drive)->rq->sector);
--		}
--		printk("\n");
+ 	if (!hwif->dma_base)
+ 		return;
+ 
+-	if (hwif->ultra_mask & 0x78) {
+-		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-			hwif->cbl = piix_cable_detect(hwif);
 -	}
--	ide_dump_opcode(drive);
--	local_irq_restore(flags);
--	return err;
+-
+ 	if (no_piix_dma)
+ 		hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
  }
- 
- /**
-- *	ide_dump_atapi_status       -       print human readable atapi status
-+ *	ide_dump_status		-	translate ATA/ATAPI error
-  *	@drive: drive that status applies to
-  *	@msg: text message to print
-  *	@stat: status byte to decode
-  *
-  *	Error reporting, in human readable form (luxurious, but a memory hog).
-+ *	Combines the drive name, message and status byte to provide a
-+ *	user understandable explanation of the device error.
+diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
+index 6b10ae2..5167661 100644
+--- a/drivers/ide/pci/rz1000.c
++++ b/drivers/ide/pci/rz1000.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/pci/rz1000.c	Version 0.06	January 12, 2003
+- *
+  *  Copyright (C) 1995-1998  Linus Torvalds & author (see below)
   */
  
--static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
-+u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
- {
- 	unsigned long flags;
-+	u8 err = 0;
+@@ -18,22 +16,15 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/pci.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
  
--	atapi_status_t status;
--	atapi_error_t error;
--
--	status.all = stat;
--	error.all = 0;
- 	local_irq_save(flags);
- 	printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
--	if (status.b.bsy)
-+	if (stat & BUSY_STAT)
- 		printk("Busy ");
- 	else {
--		if (status.b.drdy)	printk("DriveReady ");
--		if (status.b.df)	printk("DeviceFault ");
--		if (status.b.dsc)	printk("SeekComplete ");
--		if (status.b.drq)	printk("DataRequest ");
--		if (status.b.corr)	printk("CorrectedError ");
--		if (status.b.idx)	printk("Index ");
--		if (status.b.check)	printk("Error ");
-+		if (stat & READY_STAT)	printk("DriveReady ");
-+		if (stat & WRERR_STAT)	printk("DeviceFault ");
-+		if (stat & SEEK_STAT)	printk("SeekComplete ");
-+		if (stat & DRQ_STAT)	printk("DataRequest ");
-+		if (stat & ECC_STAT)	printk("CorrectedError ");
-+		if (stat & INDEX_STAT)	printk("Index ");
-+		if (stat & ERR_STAT)	printk("Error ");
- 	}
- 	printk("}\n");
--	if (status.b.check && !status.b.bsy) {
--		error.all = HWIF(drive)->INB(IDE_ERROR_REG);
--		printk("%s: %s: error=0x%02x { ", drive->name, msg, error.all);
--		if (error.b.ili)	printk("IllegalLengthIndication ");
--		if (error.b.eom)	printk("EndOfMedia ");
--		if (error.b.abrt)	printk("AbortedCommand ");
--		if (error.b.mcr)	printk("MediaChangeRequested ");
--		if (error.b.sense_key)	printk("LastFailedSense=0x%02x ",
--						error.b.sense_key);
--		printk("}\n");
-+	if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
-+		err = drive->hwif->INB(IDE_ERROR_REG);
-+		printk("%s: %s: error=0x%02x ", drive->name, msg, err);
-+		if (drive->media == ide_disk)
-+			ide_dump_ata_error(drive, err);
-+		else
-+			ide_dump_atapi_error(drive, err);
- 	}
- 	ide_dump_opcode(drive);
- 	local_irq_restore(flags);
--	return error.all;
--}
--
--/**
-- *	ide_dump_status		-	translate ATA/ATAPI error
-- *	@drive: drive the error occured on
-- *	@msg: information string
-- *	@stat: status byte
-- *
-- *	Error reporting, in human readable form (luxurious, but a memory hog).
-- *	Combines the drive name, message and status byte to provide a
-- *	user understandable explanation of the device error.
-- */
+-#include <asm/io.h>
 -
--u8 ide_dump_status(ide_drive_t *drive, const char *msg, u8 stat)
--{
--	if (drive->media == ide_disk)
--		return ide_dump_ata_status(drive, msg, stat);
--	return ide_dump_atapi_status(drive, msg, stat);
-+	return err;
- }
+ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	u16 reg;
+-	struct pci_dev *dev = hwif->pci_dev;
  
- EXPORT_SYMBOL(ide_dump_status);
-diff --git a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c
-index e245521..b163b2e 100644
---- a/drivers/ide/ide-pnp.c
-+++ b/drivers/ide/ide-pnp.c
+ 	if (!pci_read_config_word (dev, 0x40, &reg) &&
+ 	    !pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
+@@ -42,8 +33,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
+ 	} else {
+ 		if (hwif->mate)
+ 			hwif->mate->serialized = hwif->serialized = 1;
+-		hwif->drives[0].no_unmask = 1;
+-		hwif->drives[1].no_unmask = 1;
++		hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
+ 		printk(KERN_INFO "%s: serialized, disabled unmasking "
+ 			"(buggy RZ1000/RZ1001)\n", hwif->name);
+ 	}
+diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
+index 707d5ff..561aa47 100644
+--- a/drivers/ide/pci/sc1200.c
++++ b/drivers/ide/pci/sc1200.c
 @@ -1,6 +1,4 @@
  /*
-- * linux/drivers/ide/ide-pnp.c
+- * linux/drivers/ide/pci/sc1200.c		Version 0.97	Aug 3 2007
 - *
-  * This file provides autodetection for ISA PnP IDE interfaces.
-  * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface.
+  * Copyright (C) 2000-2002		Mark Lord <mlord at pobox.com>
+  * Copyright (C)      2007		Bartlomiej Zolnierkiewicz
   *
-@@ -31,7 +29,6 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
+@@ -16,19 +14,13 @@
+ #include <linux/module.h>
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+-#include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
+ #include <linux/pm.h>
++
+ #include <asm/io.h>
+-#include <asm/irq.h>
+ 
+ #define SC1200_REV_A	0x00
+ #define SC1200_REV_B1	0x01
+@@ -87,7 +79,7 @@ static const unsigned int sc1200_pio_timings[4][5] =
+ static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
  {
- 	hw_regs_t hw;
- 	ide_hwif_t *hwif;
--	int index;
+ 	ide_hwif_t *hwif = drive->hwif;
+-	struct pci_dev *pdev = hwif->pci_dev;
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ 	unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
  
- 	if (!(pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) && pnp_irq_valid(dev, 0)))
- 		return -1;
-@@ -41,11 +38,19 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
- 				pnp_port_start(dev, 1));
- 	hw.irq = pnp_irq(dev, 0);
+ 	pci_read_config_dword(pdev, basereg + 4, &format);
+@@ -130,72 +122,42 @@ out:
+ static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
+ {
+ 	ide_hwif_t		*hwif = HWIF(drive);
++	struct pci_dev		*dev = to_pci_dev(hwif->dev);
+ 	int			unit = drive->select.b.unit;
+ 	unsigned int		reg, timings;
+ 	unsigned short		pci_clock;
+ 	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;
  
--	index = ide_register_hw(&hw, NULL, 1, &hwif);
-+	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif) {
-+		u8 index = hwif->index;
-+		u8 idx[4] = { index, 0xff, 0xff, 0xff };
++	static const u32 udma_timing[3][3] = {
++		{ 0x00921250, 0x00911140, 0x00911030 },
++		{ 0x00932470, 0x00922260, 0x00922140 },
++		{ 0x009436a1, 0x00933481, 0x00923261 },
++	};
 +
-+		ide_init_port_data(hwif, index);
-+		ide_init_port_hw(hwif, &hw);
- 
--	if (index != -1) {
--	    	printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
-+		printk(KERN_INFO "ide%d: generic PnP IDE interface\n", index);
- 		pnp_set_drvdata(dev,hwif);
++	static const u32 mwdma_timing[3][3] = {
++		{ 0x00077771, 0x00012121, 0x00002020 },
++		{ 0x000bbbb2, 0x00024241, 0x00013131 },
++		{ 0x000ffff3, 0x00035352, 0x00015151 },
++	};
 +
-+		ide_device_add(idx, NULL);
+ 	pci_clock = sc1200_get_pci_clock();
+ 
+ 	/*
+ 	 * Note that each DMA mode has several timings associated with it.
+ 	 * The correct timing depends on the fast PCI clock freq.
+ 	 */
+-	timings = 0;
+-	switch (mode) {
+-		case XFER_UDMA_0:
+-			switch (pci_clock) {
+-				case PCI_CLK_33:	timings = 0x00921250;	break;
+-				case PCI_CLK_48:	timings = 0x00932470;	break;
+-				case PCI_CLK_66:	timings = 0x009436a1;	break;
+-			}
+-			break;
+-		case XFER_UDMA_1:
+-			switch (pci_clock) {
+-				case PCI_CLK_33:	timings = 0x00911140;	break;
+-				case PCI_CLK_48:	timings = 0x00922260;	break;
+-				case PCI_CLK_66:	timings = 0x00933481;	break;
+-			}
+-			break;
+-		case XFER_UDMA_2:
+-			switch (pci_clock) {
+-				case PCI_CLK_33:	timings = 0x00911030;	break;
+-				case PCI_CLK_48:	timings = 0x00922140;	break;
+-				case PCI_CLK_66:	timings = 0x00923261;	break;
+-			}
+-			break;
+-		case XFER_MW_DMA_0:
+-			switch (pci_clock) {
+-				case PCI_CLK_33:	timings = 0x00077771;	break;
+-				case PCI_CLK_48:	timings = 0x000bbbb2;	break;
+-				case PCI_CLK_66:	timings = 0x000ffff3;	break;
+-			}
+-			break;
+-		case XFER_MW_DMA_1:
+-			switch (pci_clock) {
+-				case PCI_CLK_33:	timings = 0x00012121;	break;
+-				case PCI_CLK_48:	timings = 0x00024241;	break;
+-				case PCI_CLK_66:	timings = 0x00035352;	break;
+-			}
+-			break;
+-		case XFER_MW_DMA_2:
+-			switch (pci_clock) {
+-				case PCI_CLK_33:	timings = 0x00002020;	break;
+-				case PCI_CLK_48:	timings = 0x00013131;	break;
+-				case PCI_CLK_66:	timings = 0x00015151;	break;
+-			}
+-			break;
+-		default:
+-			return;
+-	}
 +
- 		return 0;
++	if (mode >= XFER_UDMA_0)
++		timings =  udma_timing[pci_clock][mode - XFER_UDMA_0];
++	else
++		timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
+ 
+ 	if (unit == 0) {			/* are we configuring drive0? */
+-		pci_read_config_dword(hwif->pci_dev, basereg+4, &reg);
++		pci_read_config_dword(dev, basereg + 4, &reg);
+ 		timings |= reg & 0x80000000;	/* preserve PIO format bit */
+-		pci_write_config_dword(hwif->pci_dev, basereg+4, timings);
+-	} else {
+-		pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
+-	}
++		pci_write_config_dword(dev, basereg + 4, timings);
++	} else
++		pci_write_config_dword(dev, basereg + 12, timings);
+ }
+ 
+ /*  Replacement for the standard ide_dma_end action in
+@@ -250,9 +212,9 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	}
+ 	if (mode != -1) {
+ 		printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
+-		hwif->dma_off_quietly(drive);
+-		if (ide_set_dma_mode(drive, mode) == 0)
+-			hwif->dma_host_on(drive);
++		ide_dma_off_quietly(drive);
++		if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
++			hwif->dma_host_set(drive, 1);
+ 		return;
  	}
  
-@@ -55,9 +60,10 @@ static int idepnp_probe(struct pnp_dev * dev, const struct pnp_device_id *dev_id
- static void idepnp_remove(struct pnp_dev * dev)
+@@ -260,66 +222,39 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ }
+ 
+ #ifdef CONFIG_PM
+-static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev)
+-{
+-	int	h;
+-
+-	for (h = 0; h < MAX_HWIFS; h++) {
+-		ide_hwif_t *hwif = &ide_hwifs[h];
+-		if (prev) {
+-			if (hwif == prev)
+-				prev = NULL;	// found previous, now look for next match
+-		} else {
+-			if (hwif && hwif->pci_dev == dev)
+-				return hwif;	// found next match
+-		}
+-	}
+-	return NULL;	// not found
+-}
+-
+-typedef struct sc1200_saved_state_s {
+-	__u32		regs[4];
+-} sc1200_saved_state_t;
+-
++struct sc1200_saved_state {
++	u32 regs[8];
++};
+ 
+ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
  {
- 	ide_hwif_t *hwif = pnp_get_drvdata(dev);
--	if (hwif) {
--		ide_unregister(hwif->index);
--	} else
+-	ide_hwif_t		*hwif = NULL;
+-
+ 	printk("SC1200: suspend(%u)\n", state.event);
+ 
++	/*
++	 * we only save state when going from full power to less
++	 */
+ 	if (state.event == PM_EVENT_ON) {
+-		// we only save state when going from full power to less
+-
+-		//
+-		// Loop over all interfaces that are part of this PCI device:
+-		//
+-		while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+-			sc1200_saved_state_t	*ss;
+-			unsigned int		basereg, r;
+-			//
+-			// allocate a permanent save area, if not already allocated
+-			//
+-			ss = (sc1200_saved_state_t *)hwif->config_data;
+-			if (ss == NULL) {
+-				ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
+-				if (ss == NULL)
+-					return -ENOMEM;
+-				hwif->config_data = (unsigned long)ss;
+-			}
+-			ss = (sc1200_saved_state_t *)hwif->config_data;
+-			//
+-			// Save timing registers:  this may be unnecessary if 
+-			// BIOS also does it
+-			//
+-			basereg = hwif->channel ? 0x50 : 0x40;
+-			for (r = 0; r < 4; ++r) {
+-				pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
+-			}
++		struct sc1200_saved_state *ss;
++		unsigned int r;
 +
-+	if (hwif)
-+		ide_unregister(hwif->index, 0, 0);
-+	else
- 		printk(KERN_ERR "idepnp: Unable to remove device, please report.\n");
- }
++		/*
++		 * allocate a permanent save area, if not already allocated
++		 */
++		ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
++		if (ss == NULL) {
++			ss = kmalloc(sizeof(*ss), GFP_KERNEL);
++			if (ss == NULL)
++				return -ENOMEM;
++			pci_set_drvdata(dev, ss);
+ 		}
+-	}
  
-@@ -68,12 +74,15 @@ static struct pnp_driver idepnp_driver = {
- 	.remove		= idepnp_remove,
- };
+-	/* You don't need to iterate over disks -- sysfs should have done that for you already */ 
++		/*
++		 * save timing registers
++		 * (this may be unnecessary if BIOS also does it)
++		 */
++		for (r = 0; r < 8; r++)
++			pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
++	}
  
--void __init pnpide_init(void)
-+static int __init pnpide_init(void)
- {
--	pnp_register_driver(&idepnp_driver);
-+	return pnp_register_driver(&idepnp_driver);
- }
+ 	pci_disable_device(dev);
+ 	pci_set_power_state(dev, pci_choose_state(dev, state));
+@@ -328,30 +263,25 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
  
--void __exit pnpide_exit(void)
-+static void __exit pnpide_exit(void)
+ static int sc1200_resume (struct pci_dev *dev)
  {
- 	pnp_unregister_driver(&idepnp_driver);
- }
-+
-+module_init(pnpide_init);
-+module_exit(pnpide_exit);
-diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
-index 2994523..9c07bdb 100644
---- a/drivers/ide/ide-probe.c
-+++ b/drivers/ide/ide-probe.c
-@@ -1,7 +1,6 @@
- /*
-- *  linux/drivers/ide/ide-probe.c	Version 1.11	Mar 05, 2003
-- *
-- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
-+ *  Copyright (C) 1994-1998   Linus Torvalds & authors (see below)
-+ *  Copyright (C) 2005, 2007  Bartlomiej Zolnierkiewicz
-  */
- 
- /*
-@@ -95,10 +94,10 @@ static void ide_disk_init_mult_count(ide_drive_t *drive)
- #ifdef CONFIG_IDEDISK_MULTI_MODE
- 		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
- 		id->multsect_valid = id->multsect ? 1 : 0;
--		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
-+		drive->mult_req = id->multsect_valid ? id->max_multsect : 0;
- 		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
- #else	/* original, pre IDE-NFG, per request of AC */
--		drive->mult_req = INITIAL_MULT_COUNT;
-+		drive->mult_req = 0;
- 		if (drive->mult_req > id->max_multsect)
- 			drive->mult_req = id->max_multsect;
- 		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
-@@ -129,6 +128,10 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
- 
- 	drive->id_read = 1;
- 	local_irq_enable();
-+#ifdef DEBUG
-+	printk(KERN_INFO "%s: dumping identify data\n", drive->name);
-+	ide_dump_identify((u8 *)id);
-+#endif
- 	ide_fix_driveid(id);
+-	ide_hwif_t	*hwif = NULL;
+-	int		i;
++	struct sc1200_saved_state *ss;
++	unsigned int r;
++	int i;
  
- #if defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
-@@ -234,7 +237,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
+ 	i = pci_enable_device(dev);
+ 	if (i)
+ 		return i;
  
- 	drive->media = ide_disk;
- 	printk("%s DISK drive\n", (id->config == 0x848a) ? "CFA" : "ATA" );
--	QUIRK_LIST(drive);
+-	//
+-	// loop over all interfaces that are part of this pci device:
+-	//
+-	while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
+-		unsigned int		basereg, r;
+-		sc1200_saved_state_t	*ss = (sc1200_saved_state_t *)hwif->config_data;
+-
+-		//
+-		// Restore timing registers:  this may be unnecessary if BIOS also does it
+-		//
+-		basereg = hwif->channel ? 0x50 : 0x40;
+-		if (ss != NULL) {
+-			for (r = 0; r < 4; ++r) {
+-				pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]);
+-			}
+-		}
++	ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
 +
- 	return;
- 
- err_misc:
-@@ -350,22 +353,19 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
- 	 * the irq handler isn't expecting.
- 	 */
- 	if (IDE_CONTROL_REG) {
--		u8 ctl = drive->ctl | 2;
- 		if (!hwif->irq) {
- 			autoprobe = 1;
- 			cookie = probe_irq_on();
--			/* enable device irq */
--			ctl &= ~2;
- 		}
--		hwif->OUTB(ctl, IDE_CONTROL_REG);
-+		ide_set_irq(drive, autoprobe);
++	/*
++	 * restore timing registers
++	 * (this may be unnecessary if BIOS also does it)
++	 */
++	if (ss) {
++		for (r = 0; r < 8; r++)
++			pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
  	}
- 
- 	retval = actual_try_to_identify(drive, cmd);
- 
- 	if (autoprobe) {
- 		int irq;
--		/* mask device irq */
--		hwif->OUTB(drive->ctl|2, IDE_CONTROL_REG);
 +
-+		ide_set_irq(drive, 0);
- 		/* clear drive IRQ */
- 		(void) hwif->INB(IDE_STATUS_REG);
- 		udelay(5);
-@@ -385,6 +385,20 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
- 	return retval;
+ 	return 0;
  }
+ #endif
+diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
+index ebb7132..238e3e1 100644
+--- a/drivers/ide/pci/scc_pata.c
++++ b/drivers/ide/pci/scc_pata.c
+@@ -254,19 +254,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 		offset = 0; /* 100MHz */
+ 	}
  
-+static int ide_busy_sleep(ide_hwif_t *hwif)
-+{
-+	unsigned long timeout = jiffies + WAIT_WORSTCASE;
-+	u8 stat;
-+
-+	do {
-+		msleep(50);
-+		stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
-+		if ((stat & BUSY_STAT) == 0)
-+			return 0;
-+	} while (time_before(jiffies, timeout));
-+
-+	return 1;
-+}
+-	switch (speed) {
+-	case XFER_UDMA_6:
+-	case XFER_UDMA_5:
+-	case XFER_UDMA_4:
+-	case XFER_UDMA_3:
+-	case XFER_UDMA_2:
+-	case XFER_UDMA_1:
+-	case XFER_UDMA_0:
+-		idx = speed - XFER_UDMA_0;
+-		break;
+-	default:
+-		return;
+-	}
++	idx = speed - XFER_UDMA_0;
  
- /**
-  *	do_probe		-	probe an IDE device
-@@ -409,8 +423,9 @@ static int try_to_identify (ide_drive_t *drive, u8 cmd)
+ 	jcactsel = JCACTSELtbl[offset][idx];
+ 	if (is_slave) {
+@@ -606,7 +594,7 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
  
- static int do_probe (ide_drive_t *drive, u8 cmd)
+ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
  {
--	int rc;
- 	ide_hwif_t *hwif = HWIF(drive);
-+	int rc;
-+	u8 stat;
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	struct scc_ports *ports = pci_get_drvdata(dev);
+ 	unsigned long dma_base = ports->dma;
  
- 	if (drive->present) {
- 		/* avoid waiting for inappropriate probes */
-@@ -447,31 +462,31 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
- 			/* failed: try again */
- 			rc = try_to_identify(drive,cmd);
- 		}
--		if (hwif->INB(IDE_STATUS_REG) == (BUSY_STAT|READY_STAT))
-+
-+		stat = hwif->INB(IDE_STATUS_REG);
-+
-+		if (stat == (BUSY_STAT | READY_STAT))
- 			return 4;
+@@ -632,7 +620,7 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
+ 	hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
+ 	hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
  
- 		if ((rc == 1 && cmd == WIN_PIDENTIFY) &&
- 			((drive->autotune == IDE_TUNE_DEFAULT) ||
- 			(drive->autotune == IDE_TUNE_AUTO))) {
--			unsigned long timeout;
--			printk("%s: no response (status = 0x%02x), "
--				"resetting drive\n", drive->name,
--				hwif->INB(IDE_STATUS_REG));
-+			printk(KERN_ERR "%s: no response (status = 0x%02x), "
-+					"resetting drive\n", drive->name, stat);
- 			msleep(50);
- 			hwif->OUTB(drive->select.all, IDE_SELECT_REG);
- 			msleep(50);
- 			hwif->OUTB(WIN_SRST, IDE_COMMAND_REG);
--			timeout = jiffies;
--			while (((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) &&
--			       time_before(jiffies, timeout + WAIT_WORSTCASE))
--				msleep(50);
-+			(void)ide_busy_sleep(hwif);
- 			rc = try_to_identify(drive, cmd);
- 		}
-+
-+		/* ensure drive IRQ is clear */
-+		stat = hwif->INB(IDE_STATUS_REG);
-+
- 		if (rc == 1)
--			printk("%s: no response (status = 0x%02x)\n",
--				drive->name, hwif->INB(IDE_STATUS_REG));
--		/* ensure drive irq is clear */
--		(void) hwif->INB(IDE_STATUS_REG);
-+			printk(KERN_ERR "%s: no response (status = 0x%02x)\n",
-+					drive->name, stat);
- 	} else {
- 		/* not present or maybe ATAPI */
- 		rc = 3;
-@@ -492,28 +507,26 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
- static void enable_nest (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
--	unsigned long timeout;
-+	u8 stat;
+-	hwif->irq = hwif->pci_dev->irq;
++	hwif->irq = dev->irq;
+ 	hwif->dma_base = dma_base;
+ 	hwif->config_data = ports->ctl;
+ 	hwif->mmio = 1;
+@@ -648,13 +636,19 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
  
- 	printk("%s: enabling %s -- ", hwif->name, drive->id->model);
- 	SELECT_DRIVE(drive);
- 	msleep(50);
- 	hwif->OUTB(EXABYTE_ENABLE_NEST, IDE_COMMAND_REG);
--	timeout = jiffies + WAIT_WORSTCASE;
--	do {
--		if (time_after(jiffies, timeout)) {
--			printk("failed (timeout)\n");
--			return;
--		}
--		msleep(50);
--	} while ((hwif->INB(IDE_STATUS_REG)) & BUSY_STAT);
+ static void __devinit init_iops_scc(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev =  hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
 +
-+	if (ide_busy_sleep(hwif)) {
-+		printk(KERN_CONT "failed (timeout)\n");
-+		return;
-+	}
- 
- 	msleep(50);
+ 	hwif->hwif_data = NULL;
+ 	if (pci_get_drvdata(dev) == NULL)
+ 		return;
+ 	init_mmio_iops_scc(hwif);
+ }
  
--	if (!OK_STAT((hwif->INB(IDE_STATUS_REG)), 0, BAD_STAT)) {
--		printk("failed (status = 0x%02x)\n", hwif->INB(IDE_STATUS_REG));
--	} else {
--		printk("success\n");
--	}
-+	stat = hwif->INB(IDE_STATUS_REG);
++static u8 __devinit scc_cable_detect(ide_hwif_t *hwif)
++{
++	return ATA_CBL_PATA80;
++}
 +
-+	if (!OK_STAT(stat, 0, BAD_STAT))
-+		printk(KERN_CONT "failed (status = 0x%02x)\n", stat);
-+	else
-+		printk(KERN_CONT "success\n");
+ /**
+  *	init_hwif_scc	-	set up hwif
+  *	@hwif: interface to set up
+@@ -689,8 +683,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
+ 	else
+ 		hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
  
- 	/* if !(success||timed-out) */
- 	if (do_probe(drive, WIN_IDENTIFY) >= 2) {
-@@ -607,7 +620,7 @@ static void hwif_release_dev (struct device *dev)
- 	complete(&hwif->gendev_rel_comp);
+-	/* we support 80c cable only. */
+-	hwif->cbl = ATA_CBL_PATA80;
++	hwif->cable_detect = scc_cable_detect;
  }
  
--static void hwif_register (ide_hwif_t *hwif)
-+static void ide_register_port(ide_hwif_t *hwif)
- {
- 	int ret;
+ #define DECLARE_SCC_DEV(name_str)			\
+@@ -738,14 +731,12 @@ static void __devexit scc_remove(struct pci_dev *dev)
+ 	unsigned long dma_size = pci_resource_len(dev, 1);
  
-@@ -615,8 +628,8 @@ static void hwif_register (ide_hwif_t *hwif)
- 	strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
- 	hwif->gendev.driver_data = hwif;
- 	if (hwif->gendev.parent == NULL) {
--		if (hwif->pci_dev)
--			hwif->gendev.parent = &hwif->pci_dev->dev;
-+		if (hwif->dev)
-+			hwif->gendev.parent = hwif->dev;
- 		else
- 			/* Would like to do = &device_legacy */
- 			hwif->gendev.parent = NULL;
-@@ -628,7 +641,33 @@ static void hwif_register (ide_hwif_t *hwif)
- 			__FUNCTION__, ret);
- }
+ 	if (hwif->dmatable_cpu) {
+-		pci_free_consistent(hwif->pci_dev,
+-				    PRD_ENTRIES * PRD_BYTES,
+-				    hwif->dmatable_cpu,
+-				    hwif->dmatable_dma);
++		pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
++				    hwif->dmatable_cpu, hwif->dmatable_dma);
+ 		hwif->dmatable_cpu = NULL;
+ 	}
  
--static int wait_hwif_ready(ide_hwif_t *hwif)
-+/**
-+ *	ide_port_wait_ready	-	wait for port to become ready
-+ *	@hwif: IDE port
-+ *
-+ *	This is needed on some PPCs and a bunch of BIOS-less embedded
-+ *	platforms.  Typical cases are:
-+ *
-+ *	- The firmware hard reset the disk before booting the kernel,
-+ *	  the drive is still doing it's poweron-reset sequence, that
-+ *	  can take up to 30 seconds.
-+ *
-+ *	- The firmware does nothing (or no firmware), the device is
-+ *	  still in POST state (same as above actually).
-+ *
-+ *	- Some CD/DVD/Writer combo drives tend to drive the bus during
-+ *	  their reset sequence even when they are non-selected slave
-+ *	  devices, thus preventing discovery of the main HD.
-+ *
-+ *	Doing this wait-for-non-busy should not harm any existing
-+ *	configuration and fix some issues like the above.
-+ *
-+ *	BenH.
-+ *
-+ *	Returns 0 on success, error code (< 0) otherwise.
-+ */
-+
-+static int ide_port_wait_ready(ide_hwif_t *hwif)
- {
- 	int unit, rc;
+-	ide_unregister(hwif->index);
++	ide_unregister(hwif->index, 0, 0);
  
-@@ -653,8 +692,7 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
- 		/* Ignore disks that we will not probe for later. */
- 		if (!drive->noprobe || drive->present) {
- 			SELECT_DRIVE(drive);
--			if (IDE_CONTROL_REG)
--				hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
-+			ide_set_irq(drive, 1);
- 			mdelay(2);
- 			rc = ide_wait_not_busy(hwif, 35000);
- 			if (rc)
-@@ -673,19 +711,18 @@ out:
+ 	hwif->chipset = ide_unknown;
+ 	iounmap((void*)ports->dma);
+diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
+index a728031..c11880b 100644
+--- a/drivers/ide/pci/serverworks.c
++++ b/drivers/ide/pci/serverworks.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/serverworks.c		Version 0.22	Jun 27 2007
+- *
+  * Copyright (C) 1998-2000 Michel Aubry
+  * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
+  * Copyright (C) 1998-2000 Andre Hedrick <andre at linux-ide.org>
+@@ -33,12 +31,10 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/ioport.h>
+ #include <linux/pci.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+-#include <linux/delay.h>
  
- /**
-  *	ide_undecoded_slave	-	look for bad CF adapters
-- *	@hwif: interface
-+ *	@drive1: drive
-  *
-  *	Analyse the drives on the interface and attempt to decide if we
-  *	have the same drive viewed twice. This occurs with crap CF adapters
-  *	and PCMCIA sometimes.
-  */
+ #include <asm/io.h>
  
--void ide_undecoded_slave(ide_hwif_t *hwif)
-+void ide_undecoded_slave(ide_drive_t *drive1)
+@@ -67,7 +63,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
+ 
+ static u8 svwks_udma_filter(ide_drive_t *drive)
  {
--	ide_drive_t *drive0 = &hwif->drives[0];
--	ide_drive_t *drive1 = &hwif->drives[1];
-+	ide_drive_t *drive0 = &drive1->hwif->drives[0];
+-	struct pci_dev *dev     = HWIF(drive)->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u8 mask = 0;
  
--	if (drive0->present == 0 || drive1->present == 0)
-+	if ((drive1->dn & 1) == 0 || drive0->present == 0)
- 		return;
+ 	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
+@@ -130,7 +126,7 @@ static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
+ 	static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
  
- 	/* If the models don't match they are not the same product */
-@@ -708,36 +745,16 @@ void ide_undecoded_slave(ide_hwif_t *hwif)
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
  
- EXPORT_SYMBOL_GPL(ide_undecoded_slave);
+ 	pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
  
--/*
-- * This routine only knows how to look for drive units 0 and 1
-- * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
-- */
--static void probe_hwif(ide_hwif_t *hwif)
-+static int ide_probe_port(ide_hwif_t *hwif)
- {
- 	unsigned long flags;
- 	unsigned int irqd;
--	int unit;
-+	int unit, rc = -ENODEV;
+@@ -153,7 +149,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	static const u8 drive_pci2[]		= { 0x45, 0x44, 0x47, 0x46 };
  
--	if (hwif->noprobe)
--		return;
-+	BUG_ON(hwif->present);
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 unit			= (drive->select.b.unit & 0x01);
  
--	if ((hwif->chipset != ide_4drives || !hwif->mate || !hwif->mate->present) &&
--	    (ide_hwif_request_regions(hwif))) {
--		u16 msgout = 0;
--		for (unit = 0; unit < MAX_DRIVES; ++unit) {
--			ide_drive_t *drive = &hwif->drives[unit];
--			if (drive->present) {
--				drive->present = 0;
--				printk(KERN_ERR "%s: ERROR, PORTS ALREADY IN USE\n",
--					drive->name);
--				msgout = 1;
--			}
--		}
--		if (!msgout)
--			printk(KERN_ERR "%s: ports already in use, skipping probe\n",
--				hwif->name);
--		return;	
+ 	u8 ultra_enable	 = 0, ultra_timing = 0, dma_timing = 0;
+@@ -164,25 +160,12 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	ultra_timing	&= ~(0x0F << (4*unit));
+ 	ultra_enable	&= ~(0x01 << drive->dn);
+ 
+-	switch(speed) {
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_MW_DMA_0:
+-			dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
+-			break;
+-
+-		case XFER_UDMA_5:
+-		case XFER_UDMA_4:
+-		case XFER_UDMA_3:
+-		case XFER_UDMA_2:
+-		case XFER_UDMA_1:
+-		case XFER_UDMA_0:
+-			dma_timing   |= dma_modes[2];
+-			ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
+-			ultra_enable |= (0x01 << drive->dn);
+-		default:
+-			break;
 -	}
-+	if (hwif->noprobe)
-+		return -EACCES;
++	if (speed >= XFER_UDMA_0) {
++		dma_timing   |= dma_modes[2];
++		ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit));
++		ultra_enable |= (0x01 << drive->dn);
++	} else if (speed >= XFER_MW_DMA_0)
++		dma_timing   |= dma_modes[speed - XFER_MW_DMA_0];
  
- 	/*
- 	 * We must always disable IRQ, as probe_for_drive will assert IRQ, but
-@@ -749,26 +766,7 @@ static void probe_hwif(ide_hwif_t *hwif)
+ 	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
+ 	pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
+@@ -300,7 +283,8 @@ static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
+  */
+ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++
+ 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
+ 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
+ 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
+@@ -318,7 +302,8 @@ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
+  */
+ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++
+ 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
+ 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
+ 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
+@@ -329,7 +314,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
  
- 	local_irq_set(flags);
+ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
  
--	/* This is needed on some PPCs and a bunch of BIOS-less embedded
--	 * platforms. Typical cases are:
--	 * 
--	 *  - The firmware hard reset the disk before booting the kernel,
--	 *    the drive is still doing it's poweron-reset sequence, that
--	 *    can take up to 30 seconds
--	 *  - The firmware does nothing (or no firmware), the device is
--	 *    still in POST state (same as above actually).
--	 *  - Some CD/DVD/Writer combo drives tend to drive the bus during
--	 *    their reset sequence even when they are non-selected slave
--	 *    devices, thus preventing discovery of the main HD
--	 *    
--	 *  Doing this wait-for-busy should not harm any existing configuration
--	 *  (at least things won't be worse than what current code does, that
--	 *  is blindly go & talk to the drive) and fix some issues like the
--	 *  above.
--	 *  
--	 *  BenH.
--	 */
--	if (wait_hwif_ready(hwif) == -EBUSY)
-+	if (ide_port_wait_ready(hwif) == -EBUSY)
- 		printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name);
+ 	/* Server Works */
+ 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
+@@ -353,25 +338,27 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
  
- 	/*
-@@ -778,28 +776,15 @@ static void probe_hwif(ide_hwif_t *hwif)
- 		ide_drive_t *drive = &hwif->drives[unit];
- 		drive->dn = (hwif->channel ? 2 : 0) + unit;
- 		(void) probe_for_drive(drive);
--		if (drive->present && !hwif->present) {
--			hwif->present = 1;
--			if (hwif->chipset != ide_4drives ||
--			    !hwif->mate || 
--			    !hwif->mate->present) {
--				hwif_register(hwif);
--			}
--		}
-+		if (drive->present)
-+			rc = 0;
- 	}
- 	if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) {
--		unsigned long timeout = jiffies + WAIT_WORSTCASE;
--		u8 stat;
--
- 		printk(KERN_WARNING "%s: reset\n", hwif->name);
- 		hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
- 		udelay(10);
- 		hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
--		do {
--			msleep(50);
--			stat = hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
--		} while ((stat & BUSY_STAT) && time_after(timeout, jiffies));
--
-+		(void)ide_busy_sleep(hwif);
- 	}
- 	local_irq_restore(flags);
- 	/*
-@@ -809,13 +794,19 @@ static void probe_hwif(ide_hwif_t *hwif)
- 	if (irqd)
- 		enable_irq(irqd);
+ static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++
+ 	hwif->set_pio_mode = &svwks_set_pio_mode;
+ 	hwif->set_dma_mode = &svwks_set_dma_mode;
+ 	hwif->udma_filter = &svwks_udma_filter;
  
--	if (!hwif->present) {
--		ide_hwif_release_regions(hwif);
+-	if (!hwif->dma_base)
 -		return;
+-
+-	if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
+-		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-			hwif->cbl = ata66_svwks(hwif);
 -	}
-+	return rc;
-+}
++	if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
++		hwif->cable_detect = ata66_svwks;
+ }
  
--	if (hwif->fixup)
--		hwif->fixup(hwif);
-+static void ide_port_tune_devices(ide_hwif_t *hwif)
-+{
-+	int unit;
-+
-+	for (unit = 0; unit < MAX_DRIVES; unit++) {
-+		ide_drive_t *drive = &hwif->drives[unit];
++#define IDE_HFLAGS_SVWKS \
++	(IDE_HFLAG_LEGACY_IRQS | \
++	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
++	 IDE_HFLAG_BOOTABLE)
 +
-+		if (drive->present && hwif->quirkproc)
-+			hwif->quirkproc(drive);
-+	}
- 
- 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
- 		ide_drive_t *drive = &hwif->drives[unit];
-@@ -830,48 +821,21 @@ static void probe_hwif(ide_hwif_t *hwif)
+ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ 	{	/* 0 */
+ 		.name		= "SvrWks OSB4",
+ 		.init_chipset	= init_chipset_svwks,
+ 		.init_hwif	= init_hwif_svwks,
+-		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAGS_SVWKS,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= 0x00, /* UDMA is problematic on OSB4 */
+@@ -379,7 +366,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ 		.name		= "SvrWks CSB5",
+ 		.init_chipset	= init_chipset_svwks,
+ 		.init_hwif	= init_hwif_svwks,
+-		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAGS_SVWKS,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+@@ -387,7 +374,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ 		.name		= "SvrWks CSB6",
+ 		.init_chipset	= init_chipset_svwks,
+ 		.init_hwif	= init_hwif_svwks,
+-		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAGS_SVWKS,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+@@ -395,8 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ 		.name		= "SvrWks CSB6",
+ 		.init_chipset	= init_chipset_svwks,
+ 		.init_hwif	= init_hwif_svwks,
+-		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
+-				  IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+@@ -404,8 +390,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
+ 		.name		= "SvrWks HT1000",
+ 		.init_chipset	= init_chipset_svwks,
+ 		.init_hwif	= init_hwif_svwks,
+-		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
+-				  IDE_HFLAG_BOOTABLE,
++		.host_flags	= IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
+ 		.pio_mask	= ATA_PIO4,
+ 		.mwdma_mask	= ATA_MWDMA2,
+ 		.udma_mask	= ATA_UDMA5,
+@@ -428,7 +413,9 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
  
- 			drive->nice1 = 1;
+ 	d = serverworks_chipsets[idx];
  
--			if (hwif->ide_dma_on) {
--				/*
--				 * Force DMAing for the beginning of the check.
--				 * Some chipsets appear to do interesting
--				 * things, if not checked and cleared.
--				 *   PARANOIA!!!
--				 */
--				hwif->dma_off_quietly(drive);
-+			if (hwif->dma_host_set)
- 				ide_set_dma(drive);
--			}
+-	if (idx == 2 || idx == 3) {
++	if (idx == 1)
++		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
++	else if (idx == 2 || idx == 3) {
+ 		if ((PCI_FUNC(dev->devfn) & 1) == 0) {
+ 			if (pci_resource_start(dev, 0) != 0x01f1)
+ 				d.host_flags &= ~IDE_HFLAG_BOOTABLE;
+diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
+index de820aa..0546264 100644
+--- a/drivers/ide/pci/sgiioc4.c
++++ b/drivers/ide/pci/sgiioc4.c
+@@ -25,8 +25,6 @@
+ #include <linux/hdreg.h>
+ #include <linux/init.h>
+ #include <linux/kernel.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+ #include <linux/ioport.h>
+ #include <linux/blkdev.h>
+ #include <linux/scatterlist.h>
+@@ -159,6 +157,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
  		}
- 	}
  
- 	for (unit = 0; unit < MAX_DRIVES; ++unit) {
- 		ide_drive_t *drive = &hwif->drives[unit];
+ 		if (intr_reg & 0x02) {
++			struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 			/* Error when transferring DMA data on PCI bus */
+ 			u32 pci_err_addr_low, pci_err_addr_high,
+ 			    pci_stat_cmd_reg;
+@@ -167,7 +166,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
+ 				readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
+ 			pci_err_addr_high =
+ 				readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
+-			pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
++			pci_read_config_dword(dev, PCI_COMMAND,
+ 					      &pci_stat_cmd_reg);
+ 			printk(KERN_ERR
+ 			       "%s(%s) : PCI Bus Error when doing DMA:"
+@@ -178,8 +177,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
+ 			       __FUNCTION__, drive->name,
+ 			       pci_err_addr_high, pci_err_addr_low);
+ 			/* Clear the PCI Error indicator */
+-			pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
+-					       0x00000146);
++			pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
+ 		}
  
--		if (hwif->no_io_32bit)
-+		if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT)
- 			drive->no_io_32bit = 1;
- 		else
- 			drive->no_io_32bit = drive->id->dword_io ? 1 : 0;
- 	}
+ 		/* Clear the Interrupt, Error bits on the IOC4 */
+@@ -277,21 +275,6 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
+ 	return dma_stat;
  }
  
--static int hwif_init(ide_hwif_t *hwif);
--static void hwif_register_devices(ide_hwif_t *hwif);
--
--static int probe_hwif_init(ide_hwif_t *hwif)
+-static int
+-sgiioc4_ide_dma_on(ide_drive_t * drive)
 -{
--	probe_hwif(hwif);
+-	drive->using_dma = 1;
 -
--	if (!hwif_init(hwif)) {
--		printk(KERN_INFO "%s: failed to initialize IDE interface\n",
--				 hwif->name);
--		return -1;
--	}
+-	return 0;
+-}
 -
--	if (hwif->present)
--		hwif_register_devices(hwif);
+-static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
+-{
+-	drive->using_dma = 0;
 -
--	return 0;
+-	drive->hwif->dma_host_off(drive);
 -}
 -
- #if MAX_HWIFS > 1
- /*
-  * save_match() is used to simplify logic in init_irq() below.
-@@ -924,13 +888,6 @@ static int ide_init_queue(ide_drive_t *drive)
- 	q->queuedata = drive;
- 	blk_queue_segment_boundary(q, 0xffff);
+ static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+ }
+@@ -303,13 +286,10 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
+ 	return sgiioc4_checkirq(HWIF(drive));
+ }
  
--	if (!hwif->rqsize) {
--		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
--		    (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
--			hwif->rqsize = 256;
--		else
--			hwif->rqsize = 65536;
--	}
- 	if (hwif->rqsize < max_sectors)
- 		max_sectors = hwif->rqsize;
- 	blk_queue_max_sectors(q, max_sectors);
-@@ -961,6 +918,48 @@ static int ide_init_queue(ide_drive_t *drive)
- 	return 0;
+-static void sgiioc4_dma_host_on(ide_drive_t * drive)
++static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
+ {
+-}
+-
+-static void sgiioc4_dma_host_off(ide_drive_t * drive)
+-{
+-	sgiioc4_clearirq(drive);
++	if (!on)
++		sgiioc4_clearirq(drive);
  }
  
-+static void ide_add_drive_to_hwgroup(ide_drive_t *drive)
-+{
-+	ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
-+
-+	spin_lock_irq(&ide_lock);
-+	if (!hwgroup->drive) {
-+		/* first drive for hwgroup. */
-+		drive->next = drive;
-+		hwgroup->drive = drive;
-+		hwgroup->hwif = HWIF(hwgroup->drive);
-+	} else {
-+		drive->next = hwgroup->drive->next;
-+		hwgroup->drive->next = drive;
-+	}
-+	spin_unlock_irq(&ide_lock);
-+}
-+
-+/*
-+ * For any present drive:
-+ * - allocate the block device queue
-+ * - link drive into the hwgroup
-+ */
-+static void ide_port_setup_devices(ide_hwif_t *hwif)
-+{
-+	int i;
-+
-+	for (i = 0; i < MAX_DRIVES; i++) {
-+		ide_drive_t *drive = &hwif->drives[i];
-+
-+		if (!drive->present)
-+			continue;
-+
-+		if (ide_init_queue(drive)) {
-+			printk(KERN_ERR "ide: failed to init %s\n",
-+					drive->name);
-+			continue;
-+		}
-+
-+		ide_add_drive_to_hwgroup(drive);
-+	}
-+}
-+
- /*
-  * This routine sets up the irq for an ide interface, and creates a new
-  * hwgroup for the irq/hwif if none was previously assigned.
-@@ -968,11 +967,6 @@ static int ide_init_queue(ide_drive_t *drive)
-  * Much of the code is for correctly detecting/handling irq sharing
-  * and irq serialization situations.  This is somewhat complex because
-  * it handles static as well as dynamic (PCMCIA) IDE interfaces.
-- *
-- * The IRQF_DISABLED in sa_flags means ide_intr() is always entered with
-- * interrupts completely disabled.  This can be bad for interrupt latency,
-- * but anything else has led to problems on some machines.  We re-enable
-- * interrupts as much as we can safely do in most places.
-  */
- static int init_irq (ide_hwif_t *hwif)
+ static void
+@@ -352,6 +332,7 @@ sgiioc4_INB(unsigned long port)
+ static int __devinit
+ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
  {
-@@ -1031,21 +1025,17 @@ static int init_irq (ide_hwif_t *hwif)
- 		spin_lock_irq(&ide_lock);
- 		hwif->next = hwgroup->hwif->next;
- 		hwgroup->hwif->next = hwif;
-+		BUG_ON(hwif->next == hwif);
- 		spin_unlock_irq(&ide_lock);
- 	} else {
--		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t),
--					GFP_KERNEL | __GFP_ZERO,
--					hwif_to_node(hwif->drives[0].hwif));
--		if (!hwgroup)
--	       		goto out_up;
-+		hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO,
-+				       hwif_to_node(hwif));
-+		if (hwgroup == NULL)
-+			goto out_up;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	void __iomem *virt_dma_base;
+ 	int num_ports = sizeof (ioc4_dma_regs_t);
+ 	void *pad;
+@@ -377,7 +358,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ 	}
+ 	hwif->dma_base = (unsigned long) virt_dma_base;
  
- 		hwif->hwgroup = hwgroup;
-+		hwgroup->hwif = hwif->next = hwif;
+-	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
++	hwif->dmatable_cpu = pci_alloc_consistent(dev,
+ 					  IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+ 					  &hwif->dmatable_dma);
  
--		hwgroup->hwif     = hwif->next = hwif;
--		hwgroup->rq       = NULL;
--		hwgroup->handler  = NULL;
--		hwgroup->drive    = NULL;
--		hwgroup->busy     = 0;
- 		init_timer(&hwgroup->timer);
- 		hwgroup->timer.function = &ide_timer_expiry;
- 		hwgroup->timer.data = (unsigned long) hwgroup;
-@@ -1055,17 +1045,13 @@ static int init_irq (ide_hwif_t *hwif)
- 	 * Allocate the irq, if not already obtained for another hwif
- 	 */
- 	if (!match || match->irq != hwif->irq) {
--		int sa = IRQF_DISABLED;
-+		int sa = 0;
- #if defined(__mc68000__) || defined(CONFIG_APUS)
- 		sa = IRQF_SHARED;
- #endif /* __mc68000__ || CONFIG_APUS */
+@@ -386,7 +367,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
  
--		if (IDE_CHIPSET_IS_PCI(hwif->chipset)) {
-+		if (IDE_CHIPSET_IS_PCI(hwif->chipset))
- 			sa = IRQF_SHARED;
--#ifndef CONFIG_IDEPCI_SHARE_IRQ
--			sa |= IRQF_DISABLED;
--#endif /* CONFIG_IDEPCI_SHARE_IRQ */
--		}
+ 	hwif->sg_max_nents = IOC4_PRD_ENTRIES;
  
- 		if (hwif->io_ports[IDE_CONTROL_OFFSET])
- 			/* clear nIEN */
-@@ -1075,30 +1061,12 @@ static int init_irq (ide_hwif_t *hwif)
- 	       		goto out_unlink;
+-	pad = pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE,
++	pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
+ 				   (dma_addr_t *) &(hwif->dma_status));
+ 
+ 	if (pad) {
+@@ -394,8 +375,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ 		return 0;
  	}
  
--	/*
--	 * For any present drive:
--	 * - allocate the block device queue
--	 * - link drive into the hwgroup
--	 */
--	for (index = 0; index < MAX_DRIVES; ++index) {
--		ide_drive_t *drive = &hwif->drives[index];
--		if (!drive->present)
--			continue;
--		if (ide_init_queue(drive)) {
--			printk(KERN_ERR "ide: failed to init %s\n",drive->name);
--			continue;
--		}
--		spin_lock_irq(&ide_lock);
--		if (!hwgroup->drive) {
--			/* first drive for hwgroup. */
--			drive->next = drive;
--			hwgroup->drive = drive;
--			hwgroup->hwif = HWIF(hwgroup->drive);
--		} else {
--			drive->next = hwgroup->drive->next;
--			hwgroup->drive->next = drive;
--		}
--		spin_unlock_irq(&ide_lock);
-+	if (!hwif->rqsize) {
-+		if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
-+		    (hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA))
-+			hwif->rqsize = 256;
-+		else
-+			hwif->rqsize = 65536;
+-	pci_free_consistent(hwif->pci_dev,
+-			    IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
++	pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
+ 			    hwif->dmatable_cpu, hwif->dmatable_dma);
+ 	printk(KERN_INFO
+ 	       "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
+@@ -535,8 +515,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
  	}
  
- #if !defined(__mc68000__) && !defined(CONFIG_APUS)
-@@ -1114,28 +1082,13 @@ static int init_irq (ide_hwif_t *hwif)
- 		printk(" (%sed with %s)",
- 			hwif->sharing_irq ? "shar" : "serializ", match->name);
- 	printk("\n");
-+
-+	ide_port_setup_devices(hwif);
-+
- 	mutex_unlock(&ide_cfg_mtx);
- 	return 0;
- out_unlink:
--	spin_lock_irq(&ide_lock);
--	if (hwif->next == hwif) {
--		BUG_ON(match);
--		BUG_ON(hwgroup->hwif != hwif);
--		kfree(hwgroup);
--	} else {
--		ide_hwif_t *g;
--		g = hwgroup->hwif;
--		while (g->next != hwif)
--			g = g->next;
--		g->next = hwif->next;
--		if (hwgroup->hwif == hwif) {
--			/* Impossible. */
--			printk(KERN_ERR "Duh. Uninitialized hwif listed as active hwif.\n");
--			hwgroup->hwif = g;
--		}
--		BUG_ON(hwgroup->hwif == hwif);
--	}
--	spin_unlock_irq(&ide_lock);
-+	ide_remove_port_from_hwgroup(hwif);
- out_up:
- 	mutex_unlock(&ide_cfg_mtx);
- 	return 1;
-@@ -1173,7 +1126,7 @@ static struct kobject *exact_match(dev_t dev, int *part, void *data)
- {
- 	struct gendisk *p = data;
- 	*part &= (1 << PARTN_BITS) - 1;
--	return &p->kobj;
-+	return &p->dev.kobj;
- }
+ use_pio_instead:
+-	pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
+-		     hwif->sg_dma_direction);
++	ide_destroy_dmatable(drive);
  
- static int exact_lock(dev_t dev, void *data)
-@@ -1256,56 +1209,25 @@ static void drive_release_dev (struct device *dev)
- 	complete(&drive->gendev_rel_comp);
+ 	return 0;		/* revert to PIO for this request */
  }
+@@ -574,7 +553,6 @@ static void __devinit
+ ide_init_sgiioc4(ide_hwif_t * hwif)
+ {
+ 	hwif->mmio = 1;
+-	hwif->pio_mask = 0x00;
+ 	hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
+ 	hwif->set_dma_mode = &sgiioc4_set_dma_mode;
+ 	hwif->selectproc = NULL;/* Use the default routine to select drive */
+@@ -582,7 +560,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
+ 	hwif->pre_reset = NULL;	/* No HBA specific pre_set needed */
+ 	hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
+ 						clear interrupts */
+-	hwif->intrproc = NULL;	/* Enable or Disable interrupt from drive */
+ 	hwif->maskproc = &sgiioc4_maskproc;	/* Mask on/off NIEN register */
+ 	hwif->quirkproc = NULL;
+ 	hwif->busproc = NULL;
+@@ -592,20 +569,22 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
+ 	if (hwif->dma_base == 0)
+ 		return;
  
--/*
-- * init_gendisk() (as opposed to ide_geninit) is called for each major device,
-- * after probing for drives, to allocate partition tables and other data
-- * structures needed for the routines in genhd.c.  ide_geninit() gets called
-- * somewhat later, during the partition check.
-- */
--static void init_gendisk (ide_hwif_t *hwif)
--{
--	unsigned int unit;
--
--	for (unit = 0; unit < MAX_DRIVES; ++unit) {
--		ide_drive_t * drive = &hwif->drives[unit];
--		ide_add_generic_settings(drive);
--		snprintf(drive->gendev.bus_id,BUS_ID_SIZE,"%u.%u",
--			 hwif->index,unit);
--		drive->gendev.parent = &hwif->gendev;
--		drive->gendev.bus = &ide_bus_type;
--		drive->gendev.driver_data = drive;
--		drive->gendev.release = drive_release_dev;
--	}
--	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
--			THIS_MODULE, ata_probe, ata_lock, hwif);
--}
+-	hwif->mwdma_mask = ATA_MWDMA2_ONLY;
 -
- static int hwif_init(ide_hwif_t *hwif)
++	hwif->dma_host_set = &sgiioc4_dma_host_set;
+ 	hwif->dma_setup = &sgiioc4_ide_dma_setup;
+ 	hwif->dma_start = &sgiioc4_ide_dma_start;
+ 	hwif->ide_dma_end = &sgiioc4_ide_dma_end;
+-	hwif->ide_dma_on = &sgiioc4_ide_dma_on;
+-	hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
+ 	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
+-	hwif->dma_host_on = &sgiioc4_dma_host_on;
+-	hwif->dma_host_off = &sgiioc4_dma_host_off;
+ 	hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
+ 	hwif->dma_timeout = &ide_dma_timeout;
+ }
+ 
++static const struct ide_port_info sgiioc4_port_info __devinitdata = {
++	.chipset		= ide_pci,
++	.host_flags		= IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
++				  IDE_HFLAG_NO_AUTOTUNE,
++	.mwdma_mask		= ATA_MWDMA2_ONLY,
++};
++
+ static int __devinit
+ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
  {
- 	int old_irq;
+@@ -615,6 +594,8 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ 	ide_hwif_t *hwif;
+ 	int h;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	hw_regs_t hw;
++	struct ide_port_info d = sgiioc4_port_info;
  
--	/* Return success if no device is connected */
--	if (!hwif->present)
--		return 1;
--
- 	if (!hwif->irq) {
- 		if (!(hwif->irq = ide_default_irq(hwif->io_ports[IDE_DATA_OFFSET])))
- 		{
- 			printk("%s: DISABLED, NO IRQ\n", hwif->name);
--			return (hwif->present = 0);
-+			return 0;
- 		}
- 	}
- #ifdef CONFIG_BLK_DEV_HD
- 	if (hwif->irq == HD_IRQ && hwif->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
- 		printk("%s: CANNOT SHARE IRQ WITH OLD "
- 			"HARDDISK DRIVER (hd.c)\n", hwif->name);
--		return (hwif->present = 0);
-+		return 0;
+ 	/*
+ 	 * Find an empty HWIF; if none available, return -ENOMEM.
+@@ -654,21 +635,15 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ 		return -ENOMEM;
  	}
- #endif /* CONFIG_BLK_DEV_HD */
- 
--	/* we set it back to 1 if all is ok below */	
--	hwif->present = 0;
--
- 	if (register_blkdev(hwif->major, hwif->name))
- 		return 0;
  
-@@ -1343,11 +1265,8 @@ static int hwif_init(ide_hwif_t *hwif)
- 		hwif->name, hwif->irq);
+-	if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
+-		hw_regs_t hw;
++	/* Initialize the IO registers */
++	memset(&hw, 0, sizeof(hw));
++	sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
++	hw.irq = dev->irq;
++	hw.chipset = ide_pci;
++	hw.dev = &dev->dev;
++	ide_init_port_hw(hwif, &hw);
  
- done:
--	init_gendisk(hwif);
--
--	ide_acpi_init(hwif);
+-		/* Initialize the IO registers */
+-		memset(&hw, 0, sizeof(hw));
+-		sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
+-		memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
+-		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+-	}
 -
--	hwif->present = 1;	/* success */
-+	blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS,
-+			    THIS_MODULE, ata_probe, ata_lock, hwif);
- 	return 1;
+-	hwif->irq = dev->irq;
+-	hwif->chipset = ide_pci;
+-	hwif->pci_dev = dev;
+-	hwif->channel = 0;	/* Single Channel chip */
+-	hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
++	hwif->dev = &dev->dev;
  
- out:
-@@ -1361,66 +1280,204 @@ static void hwif_register_devices(ide_hwif_t *hwif)
+ 	/* The IOC4 uses MMIO rather than Port IO. */
+ 	default_hwif_mmiops(hwif);
+@@ -676,15 +651,17 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
+ 	/* Initializing chipset IRQ Registers */
+ 	writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
  
- 	for (i = 0; i < MAX_DRIVES; i++) {
- 		ide_drive_t *drive = &hwif->drives[i];
-+		struct device *dev = &drive->gendev;
-+		int ret;
+-	if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base))
++	if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) {
+ 		printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
+ 				 hwif->name, DRV_NAME);
++		d.mwdma_mask = 0;
++	}
  
--		if (drive->present) {
--			int ret = device_register(&drive->gendev);
-+		if (!drive->present)
-+			continue;
+ 	ide_init_sgiioc4(hwif);
  
--			if (ret < 0)
--				printk(KERN_WARNING "IDE: %s: "
--					"device_register error: %d\n",
--					__FUNCTION__, ret);
--		}
-+		ide_add_generic_settings(drive);
-+
-+		snprintf(dev->bus_id, BUS_ID_SIZE, "%u.%u", hwif->index, i);
-+		dev->parent = &hwif->gendev;
-+		dev->bus = &ide_bus_type;
-+		dev->driver_data = drive;
-+		dev->release = drive_release_dev;
-+
-+		ret = device_register(dev);
-+		if (ret < 0)
-+			printk(KERN_WARNING "IDE: %s: device_register error: "
-+					    "%d\n", __func__, ret);
- 	}
- }
+ 	idx[0] = hwif->index;
  
--int ideprobe_init (void)
-+static void ide_port_init_devices(ide_hwif_t *hwif)
+-	if (ide_device_add(idx))
++	if (ide_device_add(idx, &d))
+ 		return -EIO;
+ 
+ 	return 0;
+diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
+index 5709c25..cc4be96 100644
+--- a/drivers/ide/pci/siimage.c
++++ b/drivers/ide/pci/siimage.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/siimage.c		Version 1.19	Nov 16 2007
+- *
+  * Copyright (C) 2001-2002	Andre Hedrick <andre at linux-ide.org>
+  * Copyright (C) 2003		Red Hat <alan at redhat.com>
+  * Copyright (C) 2007		MontaVista Software, Inc.
+@@ -41,7 +39,6 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+ #include <linux/init.h>
+@@ -79,7 +76,7 @@ static int pdev_is_sata(struct pci_dev *pdev)
+  
+ static inline int is_sata(ide_hwif_t *hwif)
  {
--	unsigned int index;
--	int probe[MAX_HWIFS];
--
--	memset(probe, 0, MAX_HWIFS * sizeof(int));
--	for (index = 0; index < MAX_HWIFS; ++index)
--		probe[index] = !ide_hwifs[index].present;
--
--	for (index = 0; index < MAX_HWIFS; ++index)
--		if (probe[index])
--			probe_hwif(&ide_hwifs[index]);
--	for (index = 0; index < MAX_HWIFS; ++index)
--		if (probe[index])
--			hwif_init(&ide_hwifs[index]);
--	for (index = 0; index < MAX_HWIFS; ++index) {
--		if (probe[index]) {
--			ide_hwif_t *hwif = &ide_hwifs[index];
--			if (!hwif->present)
--				continue;
--			if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced)
--				hwif->chipset = ide_generic;
--			hwif_register_devices(hwif);
--		}
-+	int i;
-+
-+	for (i = 0; i < MAX_DRIVES; i++) {
-+		ide_drive_t *drive = &hwif->drives[i];
-+
-+		if (hwif->host_flags & IDE_HFLAG_IO_32BIT)
-+			drive->io_32bit = 1;
-+		if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS)
-+			drive->unmask = 1;
-+		if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS)
-+			drive->no_unmask = 1;
-+		if ((hwif->host_flags & IDE_HFLAG_NO_AUTOTUNE) == 0)
-+			drive->autotune = 1;
- 	}
--	for (index = 0; index < MAX_HWIFS; ++index)
--		if (probe[index])
--			ide_proc_register_port(&ide_hwifs[index]);
--	return 0;
-+
-+	if (hwif->port_init_devs)
-+		hwif->port_init_devs(hwif);
+-	return pdev_is_sata(hwif->pci_dev);
++	return pdev_is_sata(to_pci_dev(hwif->dev));
  }
  
--EXPORT_SYMBOL_GPL(ideprobe_init);
-+static void ide_init_port(ide_hwif_t *hwif, unsigned int port,
-+			  const struct ide_port_info *d)
-+{
-+	if (d->chipset != ide_etrax100)
-+		hwif->channel = port;
- 
--int ide_device_add(u8 idx[4])
-+	if (d->chipset)
-+		hwif->chipset = d->chipset;
-+
-+	if (d->init_iops)
-+		d->init_iops(hwif);
-+
-+	if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
-+		ide_hwif_setup_dma(hwif, d);
-+
-+	if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
-+	    (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
-+		hwif->irq = port ? 15 : 14;
-+
-+	hwif->host_flags = d->host_flags;
-+	hwif->pio_mask = d->pio_mask;
-+
-+	if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
-+		hwif->mate->serialized = hwif->serialized = 1;
-+
-+	hwif->swdma_mask = d->swdma_mask;
-+	hwif->mwdma_mask = d->mwdma_mask;
-+	hwif->ultra_mask = d->udma_mask;
-+
-+	/* reset DMA masks only for SFF-style DMA controllers */
-+	if ((d->host_flags && IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0)
-+		hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0;
-+
-+	if (d->host_flags & IDE_HFLAG_RQSIZE_256)
-+		hwif->rqsize = 256;
-+
-+	/* call chipset specific routine for each enabled port */
-+	if (d->init_hwif)
-+		d->init_hwif(hwif);
-+
-+	if (hwif->cable_detect && (hwif->ultra_mask & 0x78)) {
-+		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
-+			hwif->cbl = hwif->cable_detect(hwif);
-+	}
-+}
-+
-+int ide_device_add_all(u8 *idx, const struct ide_port_info *d)
+ /**
+@@ -140,13 +137,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
+ static u8 sil_pata_udma_filter(ide_drive_t *drive)
  {
-+	ide_hwif_t *hwif, *mate = NULL;
- 	int i, rc = 0;
+ 	ide_hwif_t *hwif = drive->hwif;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	unsigned long base = (unsigned long) hwif->hwif_data;
+ 	u8 mask = 0, scsc = 0;
  
--	for (i = 0; i < 4; i++) {
--		if (idx[i] != 0xff)
--			rc |= probe_hwif_init(&ide_hwifs[idx[i]]);
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		if (d == NULL || idx[i] == 0xff) {
-+			mate = NULL;
-+			continue;
-+		}
-+
-+		hwif = &ide_hwifs[idx[i]];
-+
-+		if (d->chipset != ide_etrax100 && (i & 1) && mate) {
-+			hwif->mate = mate;
-+			mate->mate = hwif;
-+		}
-+
-+		mate = (i & 1) ? NULL : hwif;
-+
-+		ide_init_port(hwif, i & 1, d);
-+		ide_port_init_devices(hwif);
- 	}
+ 	if (hwif->mmio)
+ 		scsc = hwif->INB(base + 0x4A);
+ 	else
+-		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
++		pci_read_config_byte(dev, 0x8A, &scsc);
  
--	for (i = 0; i < 4; i++) {
--		if (idx[i] != 0xff)
--			ide_proc_register_port(&ide_hwifs[idx[i]]);
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		if (idx[i] == 0xff)
-+			continue;
-+
-+		hwif = &ide_hwifs[idx[i]];
-+
-+		if ((hwif->chipset != ide_4drives || !hwif->mate ||
-+		     !hwif->mate->present) && ide_hwif_request_regions(hwif)) {
-+			printk(KERN_ERR "%s: ports already in use, "
-+					"skipping probe\n", hwif->name);
-+			continue;
-+		}
-+
-+		if (ide_probe_port(hwif) < 0) {
-+			ide_hwif_release_regions(hwif);
-+			continue;
-+		}
-+
-+		hwif->present = 1;
-+
-+		if (hwif->chipset != ide_4drives || !hwif->mate ||
-+		    !hwif->mate->present)
-+			ide_register_port(hwif);
-+
-+		ide_port_tune_devices(hwif);
-+	}
-+
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		if (idx[i] == 0xff)
-+			continue;
-+
-+		hwif = &ide_hwifs[idx[i]];
-+
-+		if (!hwif->present)
-+			continue;
-+
-+		if (hwif_init(hwif) == 0) {
-+			printk(KERN_INFO "%s: failed to initialize IDE "
-+					 "interface\n", hwif->name);
-+			hwif->present = 0;
-+			rc = -1;
-+			continue;
-+		}
-+
-+		ide_acpi_init(hwif);
-+		ide_acpi_port_init_devices(hwif);
-+	}
-+
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		if (idx[i] == 0xff)
-+			continue;
-+
-+		hwif = &ide_hwifs[idx[i]];
-+
-+		if (hwif->present) {
-+			if (hwif->chipset == ide_unknown ||
-+			    hwif->chipset == ide_forced)
-+				hwif->chipset = ide_generic;
-+			hwif_register_devices(hwif);
-+		}
-+	}
-+
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		if (idx[i] == 0xff)
-+			continue;
-+
-+		hwif = &ide_hwifs[idx[i]];
+ 	if ((scsc & 0x30) == 0x10)	/* 133 */
+ 		mask = ATA_UDMA6;
+@@ -219,19 +217,21 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
+ 		mode |= (unit ? 0x10 : 0x01);
+ 		hwif->OUTB(mode, base + addr_mask);
+ 	} else {
+-		pci_write_config_word(hwif->pci_dev, addr, speedp);
+-		pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
+-		pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
++		struct pci_dev *dev = to_pci_dev(hwif->dev);
 +
-+		if (hwif->present) {
-+			ide_proc_register_port(hwif);
-+			ide_proc_port_register_devices(hwif);
-+		}
- 	}
++		pci_write_config_word(dev, addr, speedp);
++		pci_write_config_word(dev, tfaddr, speedt);
++		pci_read_config_word(dev, tfaddr - 2, &speedp);
+ 		speedp &= ~0x200;
+ 		/* Set IORDY for mode 3 or 4 */
+ 		if (pio > 2)
+ 			speedp |= 0x200;
+-		pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp);
++		pci_write_config_word(dev, tfaddr - 2, speedp);
  
- 	return rc;
+-		pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
++		pci_read_config_byte(dev, addr_mask, &mode);
+ 		mode &= ~(unit ? 0x30 : 0x03);
+ 		mode |= (unit ? 0x10 : 0x01);
+-		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
++		pci_write_config_byte(dev, addr_mask, mode);
+ 	}
  }
-+EXPORT_SYMBOL_GPL(ide_device_add_all);
  
-+int ide_device_add(u8 idx[4], const struct ide_port_info *d)
-+{
-+	u8 idx_all[MAX_HWIFS];
-+	int i;
-+
-+	for (i = 0; i < MAX_HWIFS; i++)
-+		idx_all[i] = (i < 4) ? idx[i] : 0xff;
-+
-+	return ide_device_add_all(idx_all, d);
-+}
- EXPORT_SYMBOL_GPL(ide_device_add);
-diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
-index a4007d3..975c0ff 100644
---- a/drivers/ide/ide-proc.c
-+++ b/drivers/ide/ide-proc.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/ide-proc.c	Version 1.05	Mar 05, 2003
-- *
-  *  Copyright (C) 1997-1998	Mark Lord
-  *  Copyright (C) 2003		Red Hat <alan at redhat.com>
-  *
-@@ -346,14 +344,20 @@ static int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int va
+@@ -250,6 +250,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	u16 dma[]		= { 0x2208, 0x10C2, 0x10C1 };
  
- static int set_xfer_rate (ide_drive_t *drive, int arg)
- {
-+	ide_task_t task;
- 	int err;
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u16 ultra = 0, multi	= 0;
+ 	u8 mode = 0, unit	= drive->select.b.unit;
+ 	unsigned long base	= (unsigned long)hwif->hwif_data;
+@@ -266,10 +267,10 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 		multi = hwif->INW(ma);
+ 		ultra = hwif->INW(ua);
+ 	} else {
+-		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
+-		pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
+-		pci_read_config_word(hwif->pci_dev, ma, &multi);
+-		pci_read_config_word(hwif->pci_dev, ua, &ultra);
++		pci_read_config_byte(dev, 0x8A, &scsc);
++		pci_read_config_byte(dev, addr_mask, &mode);
++		pci_read_config_word(dev, ma, &multi);
++		pci_read_config_word(dev, ua, &ultra);
+ 	}
  
- 	if (arg < 0 || arg > 70)
- 		return -EINVAL;
+ 	mode &= ~((unit) ? 0x30 : 0x03);
+@@ -278,27 +279,14 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
  
--	err = ide_wait_cmd(drive,
--			WIN_SETFEATURES, (u8) arg,
--			SETFEATURES_XFER, 0, NULL);
-+	memset(&task, 0, sizeof(task));
-+	task.tf.command = WIN_SETFEATURES;
-+	task.tf.feature = SETFEATURES_XFER;
-+	task.tf.nsect   = (u8)arg;
-+	task.tf_flags = IDE_TFLAG_OUT_FEATURE | IDE_TFLAG_OUT_NSECT |
-+			IDE_TFLAG_IN_NSECT;
-+
-+	err = ide_no_data_taskfile(drive, &task);
+ 	scsc = is_sata(hwif) ? 1 : scsc;
  
- 	if (!err && arg) {
- 		ide_set_xfer_rate(drive, (u8) arg);
-@@ -735,7 +739,7 @@ void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver)
+-	switch(speed) {
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_MW_DMA_0:
+-			multi = dma[speed - XFER_MW_DMA_0];
+-			mode |= ((unit) ? 0x20 : 0x02);
+-			break;
+-		case XFER_UDMA_6:
+-		case XFER_UDMA_5:
+-		case XFER_UDMA_4:
+-		case XFER_UDMA_3:
+-		case XFER_UDMA_2:
+-		case XFER_UDMA_1:
+-		case XFER_UDMA_0:
+-			multi = dma[2];
+-			ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
+-					   (ultra5[speed - XFER_UDMA_0]));
+-			mode |= ((unit) ? 0x30 : 0x03);
+-			break;
+-		default:
+-			return;
++	if (speed >= XFER_UDMA_0) {
++		multi = dma[2];
++		ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] :
++				 ultra5[speed - XFER_UDMA_0]);
++		mode |= (unit ? 0x30 : 0x03);
++	} else {
++		multi = dma[speed - XFER_MW_DMA_0];
++		mode |= (unit ? 0x20 : 0x02);
+ 	}
  
- EXPORT_SYMBOL(ide_proc_unregister_driver);
+ 	if (hwif->mmio) {
+@@ -306,9 +294,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 		hwif->OUTW(multi, ma);
+ 		hwif->OUTW(ultra, ua);
+ 	} else {
+-		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
+-		pci_write_config_word(hwif->pci_dev, ma, multi);
+-		pci_write_config_word(hwif->pci_dev, ua, ultra);
++		pci_write_config_byte(dev, addr_mask, mode);
++		pci_write_config_word(dev, ma, multi);
++		pci_write_config_word(dev, ua, ultra);
+ 	}
+ }
  
--static void create_proc_ide_drives(ide_hwif_t *hwif)
-+void ide_proc_port_register_devices(ide_hwif_t *hwif)
+@@ -316,6 +304,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
  {
- 	int	d;
- 	struct proc_dir_entry *ent;
-@@ -789,9 +793,6 @@ static ide_proc_entry_t hwif_entries[] = {
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 dma_altstat		= 0;
+ 	unsigned long addr	= siimage_selreg(hwif, 1);
  
- void ide_proc_register_port(ide_hwif_t *hwif)
- {
--	if (!hwif->present)
--		return;
--
- 	if (!hwif->proc) {
- 		hwif->proc = proc_mkdir(hwif->name, proc_ide_root);
+@@ -324,7 +313,7 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
+ 		return 1;
  
-@@ -800,8 +801,6 @@ void ide_proc_register_port(ide_hwif_t *hwif)
+ 	/* return 1 if Device INTR asserted */
+-	pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat);
++	pci_read_config_byte(dev, addr, &dma_altstat);
+ 	if (dma_altstat & 8)
+ 		return 0;	//return 1;
+ 	return 0;
+@@ -342,15 +331,18 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+ 	unsigned long addr	= siimage_selreg(hwif, 0x1);
++	void __iomem *sata_error_addr
++		= (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
  
- 		ide_add_proc_entries(hwif->proc, hwif_entries, hwif);
- 	}
+-	if (SATA_ERROR_REG) {
++	if (sata_error_addr) {
+ 		unsigned long base = (unsigned long)hwif->hwif_data;
 -
--	create_proc_ide_drives(hwif);
- }
- 
- #ifdef CONFIG_BLK_DEV_IDEPCI
-diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c
-new file mode 100644
-index 0000000..93d2e41
---- /dev/null
-+++ b/drivers/ide/ide-scan-pci.c
-@@ -0,0 +1,116 @@
-+/*
-+ * support for probing IDE PCI devices in the PCI bus order
-+ *
-+ * Copyright (c) 1998-2000  Andre Hedrick <andre at linux-ide.org>
-+ * Copyright (c) 1995-1998  Mark Lord
-+ *
-+ * May be copied or modified under the terms of the GNU General Public License
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/ide.h>
-+
-+/*
-+ *	Module interfaces
-+ */
-+
-+static int pre_init = 1;		/* Before first ordered IDE scan */
-+static LIST_HEAD(ide_pci_drivers);
-+
-+/*
-+ *	__ide_pci_register_driver	-	attach IDE driver
-+ *	@driver: pci driver
-+ *	@module: owner module of the driver
-+ *
-+ *	Registers a driver with the IDE layer. The IDE layer arranges that
-+ *	boot time setup is done in the expected device order and then
-+ *	hands the controllers off to the core PCI code to do the rest of
-+ *	the work.
-+ *
-+ *	Returns are the same as for pci_register_driver
-+ */
-+
-+int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
-+			      const char *mod_name)
-+{
-+	if (!pre_init)
-+		return __pci_register_driver(driver, module, mod_name);
-+	driver->driver.owner = module;
-+	list_add_tail(&driver->node, &ide_pci_drivers);
-+	return 0;
-+}
-+EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
-+
-+/**
-+ *	ide_scan_pcidev		-	find an IDE driver for a device
-+ *	@dev: PCI device to check
-+ *
-+ *	Look for an IDE driver to handle the device we are considering.
-+ *	This is only used during boot up to get the ordering correct. After
-+ *	boot up the pci layer takes over the job.
-+ */
-+
-+static int __init ide_scan_pcidev(struct pci_dev *dev)
-+{
-+	struct list_head *l;
-+	struct pci_driver *d;
-+
-+	list_for_each(l, &ide_pci_drivers) {
-+		d = list_entry(l, struct pci_driver, node);
-+		if (d->id_table) {
-+			const struct pci_device_id *id =
-+				pci_match_id(d->id_table, dev);
-+
-+			if (id != NULL && d->probe(dev, id) >= 0) {
-+				dev->driver = d;
-+				pci_dev_get(dev);
-+				return 1;
-+			}
-+		}
-+	}
-+	return 0;
-+}
-+
-+/**
-+ *	ide_scan_pcibus		-	perform the initial IDE driver scan
-+ *
-+ *	Perform the initial bus rather than driver ordered scan of the
-+ *	PCI drivers. After this all IDE pci handling becomes standard
-+ *	module ordering not traditionally ordered.
-+ */
-+
-+static int __init ide_scan_pcibus(void)
-+{
-+	struct pci_dev *dev = NULL;
-+	struct pci_driver *d;
-+	struct list_head *l, *n;
-+
-+	pre_init = 0;
-+	if (!ide_scan_direction)
-+		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
-+			ide_scan_pcidev(dev);
-+	else
-+		while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
-+						     dev)))
-+			ide_scan_pcidev(dev);
-+
-+	/*
-+	 *	Hand the drivers over to the PCI layer now we
-+	 *	are post init.
-+	 */
-+
-+	list_for_each_safe(l, n, &ide_pci_drivers) {
-+		list_del(l);
-+		d = list_entry(l, struct pci_driver, node);
-+		if (__pci_register_driver(d, d->driver.owner,
-+					  d->driver.mod_name))
-+			printk(KERN_ERR "%s: failed to register %s driver\n",
-+					__FUNCTION__, d->driver.mod_name);
-+	}
+ 		u32 ext_stat = readl((void __iomem *)(base + 0x10));
+ 		u8 watchdog = 0;
 +
-+	return 0;
-+}
+ 		if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
+-			u32 sata_error = readl((void __iomem *)SATA_ERROR_REG);
+-			writel(sata_error, (void __iomem *)SATA_ERROR_REG);
++			u32 sata_error = readl(sata_error_addr);
 +
-+module_init(ide_scan_pcibus);
-diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
-index 7b9181b..bf40d8c 100644
---- a/drivers/ide/ide-tape.c
-+++ b/drivers/ide/ide-tape.c
-@@ -1,9 +1,8 @@
- /*
-- * linux/drivers/ide/ide-tape.c		Version 1.19	Nov, 2003
-- *
-- * Copyright (C) 1995 - 1999 Gadi Oxman <gadio at netvision.net.il>
-+ * IDE ATAPI streaming tape driver.
-  *
-- * $Header$
-+ * Copyright (C) 1995-1999  Gadi Oxman <gadio at netvision.net.il>
-+ * Copyright (C) 2003-2005  Bartlomiej Zolnierkiewicz
-  *
-  * This driver was constructed as a student project in the software laboratory
-  * of the faculty of electrical engineering in the Technion - Israel's
-@@ -11,415 +10,9 @@
-  *
-  * It is hereby placed under the terms of the GNU general public license.
-  * (See linux/COPYING).
-- */
-- 
--/*
-- * IDE ATAPI streaming tape driver.
-- *
-- * This driver is a part of the Linux ide driver and works in co-operation
-- * with linux/drivers/block/ide.c.
-- *
-- * The driver, in co-operation with ide.c, basically traverses the 
-- * request-list for the block device interface. The character device
-- * interface, on the other hand, creates new requests, adds them
-- * to the request-list of the block device, and waits for their completion.
-- *
-- * Pipelined operation mode is now supported on both reads and writes.
-- *
-- * The block device major and minor numbers are determined from the
-- * tape's relative position in the ide interfaces, as explained in ide.c.
-- *
-- * The character device interface consists of the following devices:
-- *
-- * ht0		major 37, minor 0	first  IDE tape, rewind on close.
-- * ht1		major 37, minor 1	second IDE tape, rewind on close.
-- * ...
-- * nht0		major 37, minor 128	first  IDE tape, no rewind on close.
-- * nht1		major 37, minor 129	second IDE tape, no rewind on close.
-- * ...
-- *
-- * Run linux/scripts/MAKEDEV.ide to create the above entries.
-- *
-- * The general magnetic tape commands compatible interface, as defined by
-- * include/linux/mtio.h, is accessible through the character device.
-- *
-- * General ide driver configuration options, such as the interrupt-unmask
-- * flag, can be configured by issuing an ioctl to the block device interface,
-- * as any other ide device.
-- *
-- * Our own ide-tape ioctl's can be issued to either the block device or
-- * the character device interface.
-- *
-- * Maximal throughput with minimal bus load will usually be achieved in the
-- * following scenario:
-- *
-- *	1.	ide-tape is operating in the pipelined operation mode.
-- *	2.	No buffering is performed by the user backup program.
-- *
-- * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive.
-- * 
-- * Ver 0.1   Nov  1 95   Pre-working code :-)
-- * Ver 0.2   Nov 23 95   A short backup (few megabytes) and restore procedure
-- *                        was successful ! (Using tar cvf ... on the block
-- *                        device interface).
-- *                       A longer backup resulted in major swapping, bad
-- *                        overall Linux performance and eventually failed as
-- *                        we received non serial read-ahead requests from the
-- *                        buffer cache.
-- * Ver 0.3   Nov 28 95   Long backups are now possible, thanks to the
-- *                        character device interface. Linux's responsiveness
-- *                        and performance doesn't seem to be much affected
-- *                        from the background backup procedure.
-- *                       Some general mtio.h magnetic tape operations are
-- *                        now supported by our character device. As a result,
-- *                        popular tape utilities are starting to work with
-- *                        ide tapes :-)
-- *                       The following configurations were tested:
-- *                       	1. An IDE ATAPI TAPE shares the same interface
-- *                       	   and irq with an IDE ATAPI CDROM.
-- *                        	2. An IDE ATAPI TAPE shares the same interface
-- *                          	   and irq with a normal IDE disk.
-- *                        Both configurations seemed to work just fine !
-- *                        However, to be on the safe side, it is meanwhile
-- *                        recommended to give the IDE TAPE its own interface
-- *                        and irq.
-- *                       The one thing which needs to be done here is to
-- *                        add a "request postpone" feature to ide.c,
-- *                        so that we won't have to wait for the tape to finish
-- *                        performing a long media access (DSC) request (such
-- *                        as a rewind) before we can access the other device
-- *                        on the same interface. This effect doesn't disturb
-- *                        normal operation most of the time because read/write
-- *                        requests are relatively fast, and once we are
-- *                        performing one tape r/w request, a lot of requests
-- *                        from the other device can be queued and ide.c will
-- *			  service all of them after this single tape request.
-- * Ver 1.0   Dec 11 95   Integrated into Linux 1.3.46 development tree.
-- *                       On each read / write request, we now ask the drive
-- *                        if we can transfer a constant number of bytes
-- *                        (a parameter of the drive) only to its buffers,
-- *                        without causing actual media access. If we can't,
-- *                        we just wait until we can by polling the DSC bit.
-- *                        This ensures that while we are not transferring
-- *                        more bytes than the constant referred to above, the
-- *                        interrupt latency will not become too high and
-- *                        we won't cause an interrupt timeout, as happened
-- *                        occasionally in the previous version.
-- *                       While polling for DSC, the current request is
-- *                        postponed and ide.c is free to handle requests from
-- *                        the other device. This is handled transparently to
-- *                        ide.c. The hwgroup locking method which was used
-- *                        in the previous version was removed.
-- *                       Use of new general features which are provided by
-- *                        ide.c for use with atapi devices.
-- *                        (Programming done by Mark Lord)
-- *                       Few potential bug fixes (Again, suggested by Mark)
-- *                       Single character device data transfers are now
-- *                        not limited in size, as they were before.
-- *                       We are asking the tape about its recommended
-- *                        transfer unit and send a larger data transfer
-- *                        as several transfers of the above size.
-- *                        For best results, use an integral number of this
-- *                        basic unit (which is shown during driver
-- *                        initialization). I will soon add an ioctl to get
-- *                        this important parameter.
-- *                       Our data transfer buffer is allocated on startup,
-- *                        rather than before each data transfer. This should
-- *                        ensure that we will indeed have a data buffer.
-- * Ver 1.1   Dec 14 95   Fixed random problems which occurred when the tape
-- *                        shared an interface with another device.
-- *                        (poll_for_dsc was a complete mess).
-- *                       Removed some old (non-active) code which had
-- *                        to do with supporting buffer cache originated
-- *                        requests.
-- *                       The block device interface can now be opened, so
-- *                        that general ide driver features like the unmask
-- *                        interrupts flag can be selected with an ioctl.
-- *                        This is the only use of the block device interface.
-- *                       New fast pipelined operation mode (currently only on
-- *                        writes). When using the pipelined mode, the
-- *                        throughput can potentially reach the maximum
-- *                        tape supported throughput, regardless of the
-- *                        user backup program. On my tape drive, it sometimes
-- *                        boosted performance by a factor of 2. Pipelined
-- *                        mode is enabled by default, but since it has a few
-- *                        downfalls as well, you may want to disable it.
-- *                        A short explanation of the pipelined operation mode
-- *                        is available below.
-- * Ver 1.2   Jan  1 96   Eliminated pipelined mode race condition.
-- *                       Added pipeline read mode. As a result, restores
-- *                        are now as fast as backups.
-- *                       Optimized shared interface behavior. The new behavior
-- *                        typically results in better IDE bus efficiency and
-- *                        higher tape throughput.
-- *                       Pre-calculation of the expected read/write request
-- *                        service time, based on the tape's parameters. In
-- *                        the pipelined operation mode, this allows us to
-- *                        adjust our polling frequency to a much lower value,
-- *                        and thus to dramatically reduce our load on Linux,
-- *                        without any decrease in performance.
-- *                       Implemented additional mtio.h operations.
-- *                       The recommended user block size is returned by
-- *                        the MTIOCGET ioctl.
-- *                       Additional minor changes.
-- * Ver 1.3   Feb  9 96   Fixed pipelined read mode bug which prevented the
-- *                        use of some block sizes during a restore procedure.
-- *                       The character device interface will now present a
-- *                        continuous view of the media - any mix of block sizes
-- *                        during a backup/restore procedure is supported. The
-- *                        driver will buffer the requests internally and
-- *                        convert them to the tape's recommended transfer
-- *                        unit, making performance almost independent of the
-- *                        chosen user block size.
-- *                       Some improvements in error recovery.
-- *                       By cooperating with ide-dma.c, bus mastering DMA can
-- *                        now sometimes be used with IDE tape drives as well.
-- *                        Bus mastering DMA has the potential to dramatically
-- *                        reduce the CPU's overhead when accessing the device,
-- *                        and can be enabled by using hdparm -d1 on the tape's
-- *                        block device interface. For more info, read the
-- *                        comments in ide-dma.c.
-- * Ver 1.4   Mar 13 96   Fixed serialize support.
-- * Ver 1.5   Apr 12 96   Fixed shared interface operation, broken in 1.3.85.
-- *                       Fixed pipelined read mode inefficiency.
-- *                       Fixed nasty null dereferencing bug.
-- * Ver 1.6   Aug 16 96   Fixed FPU usage in the driver.
-- *                       Fixed end of media bug.
-- * Ver 1.7   Sep 10 96   Minor changes for the CONNER CTT8000-A model.
-- * Ver 1.8   Sep 26 96   Attempt to find a better balance between good
-- *                        interactive response and high system throughput.
-- * Ver 1.9   Nov  5 96   Automatically cross encountered filemarks rather
-- *                        than requiring an explicit FSF command.
-- *                       Abort pending requests at end of media.
-- *                       MTTELL was sometimes returning incorrect results.
-- *                       Return the real block size in the MTIOCGET ioctl.
-- *                       Some error recovery bug fixes.
-- * Ver 1.10  Nov  5 96   Major reorganization.
-- *                       Reduced CPU overhead a bit by eliminating internal
-- *                        bounce buffers.
-- *                       Added module support.
-- *                       Added multiple tape drives support.
-- *                       Added partition support.
-- *                       Rewrote DSC handling.
-- *                       Some portability fixes.
-- *                       Removed ide-tape.h.
-- *                       Additional minor changes.
-- * Ver 1.11  Dec  2 96   Bug fix in previous DSC timeout handling.
-- *                       Use ide_stall_queue() for DSC overlap.
-- *                       Use the maximum speed rather than the current speed
-- *                        to compute the request service time.
-- * Ver 1.12  Dec  7 97   Fix random memory overwriting and/or last block data
-- *                        corruption, which could occur if the total number
-- *                        of bytes written to the tape was not an integral
-- *                        number of tape blocks.
-- *                       Add support for INTERRUPT DRQ devices.
-- * Ver 1.13  Jan  2 98   Add "speed == 0" work-around for HP COLORADO 5GB
-- * Ver 1.14  Dec 30 98   Partial fixes for the Sony/AIWA tape drives.
-- *                       Replace cli()/sti() with hwgroup spinlocks.
-- * Ver 1.15  Mar 25 99   Fix SMP race condition by replacing hwgroup
-- *                        spinlock with private per-tape spinlock.
-- * Ver 1.16  Sep  1 99   Add OnStream tape support.
-- *                       Abort read pipeline on EOD.
-- *                       Wait for the tape to become ready in case it returns
-- *                        "in the process of becoming ready" on open().
-- *                       Fix zero padding of the last written block in
-- *                        case the tape block size is larger than PAGE_SIZE.
-- *                       Decrease the default disconnection time to tn.
-- * Ver 1.16e Oct  3 99   Minor fixes.
-- * Ver 1.16e1 Oct 13 99  Patches by Arnold Niessen,
-- *                          niessen at iae.nl / arnold.niessen at philips.com
-- *                   GO-1)  Undefined code in idetape_read_position
-- *				according to Gadi's email
-- *                   AJN-1) Minor fix asc == 11 should be asc == 0x11
-- *                               in idetape_issue_packet_command (did effect
-- *                               debugging output only)
-- *                   AJN-2) Added more debugging output, and
-- *                              added ide-tape: where missing. I would also
-- *				like to add tape->name where possible
-- *                   AJN-3) Added different debug_level's 
-- *                              via /proc/ide/hdc/settings
-- * 				"debug_level" determines amount of debugging output;
-- * 				can be changed using /proc/ide/hdx/settings
-- * 				0 : almost no debugging output
-- * 				1 : 0+output errors only
-- * 				2 : 1+output all sensekey/asc
-- * 				3 : 2+follow all chrdev related procedures
-- * 				4 : 3+follow all procedures
-- * 				5 : 4+include pc_stack rq_stack info
-- * 				6 : 5+USE_COUNT updates
-- *                   AJN-4) Fixed timeout for retension in idetape_queue_pc_tail
-- *				from 5 to 10 minutes
-- *                   AJN-5) Changed maximum number of blocks to skip when
-- *                              reading tapes with multiple consecutive write
-- *                              errors from 100 to 1000 in idetape_get_logical_blk
-- *                   Proposed changes to code:
-- *                   1) output "logical_blk_num" via /proc
-- *                   2) output "current_operation" via /proc
-- *                   3) Either solve or document the fact that `mt rewind' is
-- *                      required after reading from /dev/nhtx to be
-- *			able to rmmod the idetape module;
-- *			Also, sometimes an application finishes but the
-- *			device remains `busy' for some time. Same cause ?
-- *                   Proposed changes to release-notes:
-- *		     4) write a simple `quickstart' section in the
-- *                      release notes; I volunteer if you don't want to
-- * 		     5) include a pointer to video4linux in the doc
-- *                      to stimulate video applications
-- *                   6) release notes lines 331 and 362: explain what happens
-- *			if the application data rate is higher than 1100 KB/s; 
-- *			similar approach to lower-than-500 kB/s ?
-- *		     7) 6.6 Comparison; wouldn't it be better to allow different 
-- *			strategies for read and write ?
-- *			Wouldn't it be better to control the tape buffer
-- *			contents instead of the bandwidth ?
-- *		     8) line 536: replace will by would (if I understand
-- *			this section correctly, a hypothetical and unwanted situation
-- *			 is being described)
-- * Ver 1.16f Dec 15 99   Change place of the secondary OnStream header frames.
-- * Ver 1.17  Nov 2000 / Jan 2001  Marcel Mol, marcel at mesa.nl
-- *			- Add idetape_onstream_mode_sense_tape_parameter_page
-- *			  function to get tape capacity in frames: tape->capacity.
-- *			- Add support for DI-50 drives( or any DI- drive).
-- *			- 'workaround' for read error/blank block around block 3000.
-- *			- Implement Early warning for end of media for Onstream.
-- *			- Cosmetic code changes for readability.
-- *			- Idetape_position_tape should not use SKIP bit during
-- *			  Onstream read recovery.
-- *			- Add capacity, logical_blk_num and first/last_frame_position
-- *			  to /proc/ide/hd?/settings.
-- *			- Module use count was gone in the Linux 2.4 driver.
-- * Ver 1.17a Apr 2001 Willem Riede osst at riede.org
-- * 			- Get drive's actual block size from mode sense block descriptor
-- * 			- Limit size of pipeline
-- * Ver 1.17b Oct 2002   Alan Stern <stern at rowland.harvard.edu>
-- *			Changed IDETAPE_MIN_PIPELINE_STAGES to 1 and actually used
-- *			 it in the code!
-- *			Actually removed aborted stages in idetape_abort_pipeline
-- *			 instead of just changing the command code.
-- *			Made the transfer byte count for Request Sense equal to the
-- *			 actual length of the data transfer.
-- *			Changed handling of partial data transfers: they do not
-- *			 cause DMA errors.
-- *			Moved initiation of DMA transfers to the correct place.
-- *			Removed reference to unallocated memory.
-- *			Made __idetape_discard_read_pipeline return the number of
-- *			 sectors skipped, not the number of stages.
-- *			Replaced errant kfree() calls with __idetape_kfree_stage().
-- *			Fixed off-by-one error in testing the pipeline length.
-- *			Fixed handling of filemarks in the read pipeline.
-- *			Small code optimization for MTBSF and MTBSFM ioctls.
-- *			Don't try to unlock the door during device close if is
-- *			 already unlocked!
-- *			Cosmetic fixes to miscellaneous debugging output messages.
-- *			Set the minimum /proc/ide/hd?/settings values for "pipeline",
-- *			 "pipeline_min", and "pipeline_max" to 1.
-- *
-- * Here are some words from the first releases of hd.c, which are quoted
-- * in ide.c and apply here as well:
-- *
-- * | Special care is recommended.  Have Fun!
-- *
-- */
++			writel(sata_error, sata_error_addr);
+ 			watchdog = (sata_error & 0x00680000) ? 1 : 0;
+ 			printk(KERN_WARNING "%s: sata_error = 0x%08x, "
+ 				"watchdog = %d, %s\n",
+@@ -390,13 +382,14 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
+ static int sil_sata_busproc(ide_drive_t * drive, int state)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u32 stat_config		= 0;
+ 	unsigned long addr	= siimage_selreg(hwif, 0);
+ 
+ 	if (hwif->mmio)
+ 		stat_config = readl((void __iomem *)addr);
+ 	else
+-		pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
++		pci_read_config_dword(dev, addr, &stat_config);
+ 
+ 	switch (state) {
+ 		case BUSSTATE_ON:
+@@ -428,13 +421,17 @@ static int sil_sata_busproc(ide_drive_t * drive, int state)
+ 
+ static int sil_sata_reset_poll(ide_drive_t *drive)
+ {
+-	if (SATA_STATUS_REG) {
+-		ide_hwif_t *hwif	= HWIF(drive);
++	ide_hwif_t *hwif = drive->hwif;
++	void __iomem *sata_status_addr
++		= (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET];
+ 
+-		/* SATA_STATUS_REG is valid only when in MMIO mode */
+-		if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) {
++	if (sata_status_addr) {
++		/* SATA Status is available only when in MMIO mode */
++		u32 sata_stat = readl(sata_status_addr);
++
++		if ((sata_stat & 0x03) != 0x03) {
+ 			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
+-				hwif->name, readl((void __iomem *)SATA_STATUS_REG));
++					    hwif->name, sata_stat);
+ 			HWGROUP(drive)->polling = 0;
+ 			return ide_started;
+ 		}
+@@ -656,7 +653,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch
+ 
+ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	void *addr		= pci_get_drvdata(dev);
+ 	u8 ch			= hwif->channel;
+ 	hw_regs_t		hw;
+@@ -707,9 +704,6 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
+ 		hwif->sata_scr[SATA_STATUS_OFFSET]	= base + 0x104;
+ 		hwif->sata_scr[SATA_ERROR_OFFSET]	= base + 0x108;
+ 		hwif->sata_scr[SATA_CONTROL_OFFSET]	= base + 0x100;
+-		hwif->sata_misc[SATA_MISC_OFFSET]	= base + 0x140;
+-		hwif->sata_misc[SATA_PHY_OFFSET]	= base + 0x144;
+-		hwif->sata_misc[SATA_IEN_OFFSET]	= base + 0x148;
+ 	}
+ 
+ 	memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
+@@ -726,9 +720,6 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
+ 	const char *s = &drive->id->model[0];
+ 	unsigned len;
+ 
+-	if (!drive->present)
+-		return 0;
 -
--/*
-- * An overview of the pipelined operation mode.
-- *
-- * In the pipelined write mode, we will usually just add requests to our
-- * pipeline and return immediately, before we even start to service them. The
-- * user program will then have enough time to prepare the next request while
-- * we are still busy servicing previous requests. In the pipelined read mode,
-- * the situation is similar - we add read-ahead requests into the pipeline,
-- * before the user even requested them.
-- *
-- * The pipeline can be viewed as a "safety net" which will be activated when
-- * the system load is high and prevents the user backup program from keeping up
-- * with the current tape speed. At this point, the pipeline will get
-- * shorter and shorter but the tape will still be streaming at the same speed.
-- * Assuming we have enough pipeline stages, the system load will hopefully
-- * decrease before the pipeline is completely empty, and the backup program
-- * will be able to "catch up" and refill the pipeline again.
-- * 
-- * When using the pipelined mode, it would be best to disable any type of
-- * buffering done by the user program, as ide-tape already provides all the
-- * benefits in the kernel, where it can be done in a more efficient way.
-- * As we will usually not block the user program on a request, the most
-- * efficient user code will then be a simple read-write-read-... cycle.
-- * Any additional logic will usually just slow down the backup process.
-- *
-- * Using the pipelined mode, I get a constant over 400 KBps throughput,
-- * which seems to be the maximum throughput supported by my tape.
+ 	len = strnlen(s, sizeof(drive->id->model));
+ 
+ 	if ((len > 4) && (!memcmp(s, "ST", 2))) {
+@@ -743,18 +734,20 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
+ }
+ 
+ /**
+- *	siimage_fixup		-	post probe fixups
+- *	@hwif: interface to fix up
++ *	sil_quirkproc		-	post probe fixups
++ *	@drive: drive
   *
-- * However, there are some downfalls:
-- *
-- *	1.	We use memory (for data buffers) in proportional to the number
-- *		of pipeline stages (each stage is about 26 KB with my tape).
-- *	2.	In the pipelined write mode, we cheat and postpone error codes
-- *		to the user task. In read mode, the actual tape position
-- *		will be a bit further than the last requested block.
-- *
-- * Concerning (1):
-- *
-- *	1.	We allocate stages dynamically only when we need them. When
-- *		we don't need them, we don't consume additional memory. In
-- *		case we can't allocate stages, we just manage without them
-- *		(at the expense of decreased throughput) so when Linux is
-- *		tight in memory, we will not pose additional difficulties.
-- *
-- *	2.	The maximum number of stages (which is, in fact, the maximum
-- *		amount of memory) which we allocate is limited by the compile
-- *		time parameter IDETAPE_MAX_PIPELINE_STAGES.
-- *
-- *	3.	The maximum number of stages is a controlled parameter - We
-- *		don't start from the user defined maximum number of stages
-- *		but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we
-- *		will not even allocate this amount of stages if the user
-- *		program can't handle the speed). We then implement a feedback
-- *		loop which checks if the pipeline is empty, and if it is, we
-- *		increase the maximum number of stages as necessary until we
-- *		reach the optimum value which just manages to keep the tape
-- *		busy with minimum allocated memory or until we reach
-- *		IDETAPE_MAX_PIPELINE_STAGES.
-- *
-- * Concerning (2):
-- *
-- *	In pipelined write mode, ide-tape can not return accurate error codes
-- *	to the user program since we usually just add the request to the
-- *      pipeline without waiting for it to be serviced. In case an error
-- *      occurs, I will report it on the next user request.
-- *
-- *	In the pipelined read mode, subsequent read requests or forward
-- *	filemark spacing will perform correctly, as we preserve all blocks
-- *	and filemarks which we encountered during our excess read-ahead.
-- * 
-- *	For accurate tape positioning and error reporting, disabling
-- *	pipelined mode might be the best option.
-- *
-- * You can enable/disable/tune the pipelined operation mode by adjusting
-- * the compile time parameters below.
-- */
--
--/*
-- *	Possible improvements.
-- *
-- *	1.	Support for the ATAPI overlap protocol.
-- *
-- *		In order to maximize bus throughput, we currently use the DSC
-- *		overlap method which enables ide.c to service requests from the
-- *		other device while the tape is busy executing a command. The
-- *		DSC overlap method involves polling the tape's status register
-- *		for the DSC bit, and servicing the other device while the tape
-- *		isn't ready.
-- *
-- *		In the current QIC development standard (December 1995),
-- *		it is recommended that new tape drives will *in addition* 
-- *		implement the ATAPI overlap protocol, which is used for the
-- *		same purpose - efficient use of the IDE bus, but is interrupt
-- *		driven and thus has much less CPU overhead.
-- *
-- *		ATAPI overlap is likely to be supported in most new ATAPI
-- *		devices, including new ATAPI cdroms, and thus provides us
-- *		a method by which we can achieve higher throughput when
-- *		sharing a (fast) ATA-2 disk with any (slow) new ATAPI device.
-+ * For a historical changelog see
-+ * Documentation/ide/ChangeLog.ide-tape.1995-2002
+  *	Called after drive probe we use this to decide whether the
+  *	Seagate fixup must be applied. This used to be in init_iops but
+  *	that can occur before we know what drives are present.
   */
  
- #define IDETAPE_VERSION "1.19"
-@@ -443,49 +36,13 @@
- #include <linux/completion.h>
- #include <linux/bitops.h>
- #include <linux/mutex.h>
-+#include <scsi/scsi.h>
+-static void __devinit siimage_fixup(ide_hwif_t *hwif)
++static void __devinit sil_quirkproc(ide_drive_t *drive)
+ {
++	ide_hwif_t *hwif = drive->hwif;
++
+ 	/* Try and raise the rqsize */
+-	if (!is_sata(hwif) || !is_dev_seagate_sata(&hwif->drives[0]))
++	if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
+ 		hwif->rqsize = 128;
+ }
  
- #include <asm/byteorder.h>
- #include <asm/irq.h>
- #include <asm/uaccess.h>
- #include <asm/io.h>
- #include <asm/unaligned.h>
+@@ -770,12 +763,14 @@ static void __devinit siimage_fixup(ide_hwif_t *hwif)
+ 
+ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++
+ 	hwif->hwif_data = NULL;
+ 
+ 	/* Pessimal until we finish probing */
+ 	hwif->rqsize = 15;
+ 
+-	if (pci_get_drvdata(hwif->pci_dev) == NULL)
++	if (pci_get_drvdata(dev) == NULL)
+ 		return;
+ 
+ 	init_mmio_iops_siimage(hwif);
+@@ -791,11 +786,12 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
+ 
+ static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	unsigned long addr = siimage_selreg(hwif, 0);
+ 	u8 ata66 = 0;
+ 
+-	if (pci_get_drvdata(hwif->pci_dev) == NULL)
+-		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
++	if (pci_get_drvdata(dev) == NULL)
++		pci_read_config_byte(dev, addr, &ata66);
+ 	else
+ 		ata66 = hwif->INB(addr);
+ 
+@@ -817,6 +813,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ 
+ 	hwif->set_pio_mode = &sil_set_pio_mode;
+ 	hwif->set_dma_mode = &sil_set_dma_mode;
++	hwif->quirkproc = &sil_quirkproc;
+ 
+ 	if (sata) {
+ 		static int first = 1;
+@@ -833,15 +830,14 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ 	} else
+ 		hwif->udma_filter = &sil_pata_udma_filter;
+ 
++	hwif->cable_detect = ata66_siimage;
++
+ 	if (hwif->dma_base == 0)
+ 		return;
+ 
+ 	if (sata)
+ 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+ 
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = ata66_siimage(hwif);
 -
--/*
-- * partition
-- */
--typedef struct os_partition_s {
--	__u8	partition_num;
--	__u8	par_desc_ver;
--	__u16	wrt_pass_cntr;
--	__u32	first_frame_addr;
--	__u32	last_frame_addr;
--	__u32	eod_frame_addr;
--} os_partition_t;
+ 	if (hwif->mmio) {
+ 		hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
+ 	} else {
+@@ -855,7 +851,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+ 		.init_chipset	= init_chipset_siimage,	\
+ 		.init_iops	= init_iops_siimage,	\
+ 		.init_hwif	= init_hwif_siimage,	\
+-		.fixup		= siimage_fixup,	\
+ 		.host_flags	= IDE_HFLAG_BOOTABLE,	\
+ 		.pio_mask	= ATA_PIO4,		\
+ 		.mwdma_mask	= ATA_MWDMA2,		\
+diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
+index d90b429..512bb4c 100644
+--- a/drivers/ide/pci/sis5513.c
++++ b/drivers/ide/pci/sis5513.c
+@@ -1,6 +1,4 @@
+ /*
+- * linux/drivers/ide/pci/sis5513.c	Version 0.31	Aug 9, 2007
+- *
+  * Copyright (C) 1999-2000	Andre Hedrick <andre at linux-ide.org>
+  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton at inet6.fr>, Maintainer
+  * Copyright (C) 2003		Vojtech Pavlik <vojtech at suse.cz>
+@@ -49,20 +47,11 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
 -
--/*
-- * DAT entry
-- */
--typedef struct os_dat_entry_s {
--	__u32	blk_sz;
--	__u16	blk_cnt;
--	__u8	flags;
--	__u8	reserved;
--} os_dat_entry_t;
+-#include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
+ 
+-#include <asm/irq.h>
 -
--/*
-- * DAT
-- */
--#define OS_DAT_FLAGS_DATA	(0xc)
--#define OS_DAT_FLAGS_MARK	(0x1)
+ #include "ide-timing.h"
+ 
+ /* registers layout and init values are chipset family dependant */
+@@ -197,7 +186,7 @@ static char* chipset_capability[] = {
+ 
+ static u8 sis_ata133_get_base(ide_drive_t *drive)
+ {
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u32 reg54 = 0;
+ 
+ 	pci_read_config_dword(dev, 0x54, &reg54);
+@@ -207,7 +196,7 @@ static u8 sis_ata133_get_base(ide_drive_t *drive)
+ 
+ static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
+ {
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u16 t1 = 0;
+ 	u8 drive_pci = 0x40 + drive->dn * 2;
+ 
+@@ -230,7 +219,7 @@ static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
+ 
+ static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
+ {
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u8 t1, drive_pci = 0x40 + drive->dn * 2;
+ 
+ 	/* timing bits: 7:4 active 3:0 recovery */
+@@ -253,7 +242,7 @@ static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
+ 
+ static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
+ {
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u32 t1 = 0;
+ 	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
+ 
+@@ -286,7 +275,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
+ static void config_drive_art_rwp (ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 reg4bh		= 0;
+ 	u8 rw_prefetch		= 0;
+ 
+@@ -305,64 +294,61 @@ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	sis_program_timings(drive, XFER_PIO_0 + pio);
+ }
+ 
++static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
++{
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
++	u32 regdw = 0;
++	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
++
++	pci_read_config_dword(dev, drive_pci, &regdw);
++
++	regdw |= 0x04;
++	regdw &= 0xfffff00f;
++	/* check if ATA133 enable */
++	clk = (regdw & 0x08) ? ATA_133 : ATA_100;
++	idx = mode - XFER_UDMA_0;
++	regdw |= cycle_time_value[clk][idx] << 4;
++	regdw |= cvs_time_value[clk][idx] << 8;
++
++	pci_write_config_dword(dev, drive_pci, regdw);
++}
++
++static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
++{
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
++	u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
++
++	pci_read_config_byte(dev, drive_pci + 1, &reg);
++
++	/* force the UDMA bit on if we want to use UDMA */
++	reg |= 0x80;
++	/* clean reg cycle time bits */
++	reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
++	/* set reg cycle time bits */
++	reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
++
++	pci_write_config_byte(dev, drive_pci + 1, reg);
++}
++
++static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
++{
++	if (chipset_family >= ATA_133)	/* ATA_133 */
++		sis_ata133_program_udma_timings(drive, mode);
++	else				/* ATA_33/66/100a/100/133a */
++		sis_ata33_program_udma_timings(drive, mode);
++}
++
+ static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
 -
--typedef struct os_dat_s {
--	__u8		dat_sz;
--	__u8		reserved1;
--	__u8		entry_cnt;
--	__u8		reserved3;
--	os_dat_entry_t	dat_list[16];
--} os_dat_t;
+-	/* Config chip for mode */
+-	switch(speed) {
+-		case XFER_UDMA_6:
+-		case XFER_UDMA_5:
+-		case XFER_UDMA_4:
+-		case XFER_UDMA_3:
+-		case XFER_UDMA_2:
+-		case XFER_UDMA_1:
+-		case XFER_UDMA_0:
+-			if (chipset_family >= ATA_133) {
+-				u32 regdw = 0;
+-				u8 drive_pci = sis_ata133_get_base(drive);
+-
+-				pci_read_config_dword(dev, drive_pci, &regdw);
+-				regdw |= 0x04;
+-				regdw &= 0xfffff00f;
+-				/* check if ATA133 enable */
+-				if (regdw & 0x08) {
+-					regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;
+-					regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;
+-				} else {
+-					regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;
+-					regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;
+-				}
+-				pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
+-			} else {
+-				u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
+-
+-				pci_read_config_byte(dev, drive_pci+1, &reg);
+-				/* Force the UDMA bit on if we want to use UDMA */
+-				reg |= 0x80;
+-				/* clean reg cycle time bits */
+-				reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
+-					 << cycle_time_offset[chipset_family]);
+-				/* set reg cycle time bits */
+-				reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]
+-					<< cycle_time_offset[chipset_family];
+-				pci_write_config_byte(dev, drive_pci+1, reg);
+-			}
+-			break;
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_MW_DMA_0:
+-			sis_program_timings(drive, speed);
+-			break;
+-		default:
+-			break;
+-	}
++	if (speed >= XFER_UDMA_0)
++		sis_program_udma_timings(drive, speed);
++	else
++		sis_program_timings(drive, speed);
+ }
+ 
+ static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
+ {
+-	struct pci_dev *dev = drive->hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u32 regdw = 0;
+ 	u8 drive_pci = sis_ata133_get_base(drive);
+ 
+@@ -533,7 +519,7 @@ static const struct sis_laptop sis_laptop[] = {
+ 
+ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *pdev = hwif->pci_dev;
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ 	const struct sis_laptop *lap = &sis_laptop[0];
+ 	u8 ata66 = 0;
+ 
+@@ -548,12 +534,12 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
+ 	if (chipset_family >= ATA_133) {
+ 		u16 regw = 0;
+ 		u16 reg_addr = hwif->channel ? 0x52: 0x50;
+-		pci_read_config_word(hwif->pci_dev, reg_addr, &regw);
++		pci_read_config_word(pdev, reg_addr, &regw);
+ 		ata66 = (regw & 0x8000) ? 0 : 1;
+ 	} else if (chipset_family >= ATA_66) {
+ 		u8 reg48h = 0;
+ 		u8 mask = hwif->channel ? 0x20 : 0x10;
+-		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
++		pci_read_config_byte(pdev, 0x48, &reg48h);
+ 		ata66 = (reg48h & mask) ? 0 : 1;
+ 	}
+ 
+@@ -570,13 +556,12 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
+ 	if (chipset_family >= ATA_133)
+ 		hwif->udma_filter = sis5513_ata133_udma_filter;
+ 
++	hwif->cable_detect = ata66_sis5513;
++
+ 	if (hwif->dma_base == 0)
+ 		return;
+ 
+ 	hwif->ultra_mask = udma_rates[chipset_family];
 -
- #include <linux/mtio.h>
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = ata66_sis5513(hwif);
+ }
  
- /**************************** Tunable parameters *****************************/
-@@ -513,10 +70,7 @@ typedef struct os_dat_s {
+ static const struct ide_port_info sis5513_chipset __devinitdata = {
+diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
+index 147d783..ee261ae 100644
+--- a/drivers/ide/pci/sl82c105.c
++++ b/drivers/ide/pci/sl82c105.c
+@@ -1,6 +1,4 @@
  /*
-  *	The following are used to debug the driver:
-  *
-- *	Setting IDETAPE_DEBUG_INFO to 1 will report device capabilities.
-  *	Setting IDETAPE_DEBUG_LOG to 1 will log driver flow control.
-- *	Setting IDETAPE_DEBUG_BUGS to 1 will enable self-sanity checks in
-- *	some places.
+- * linux/drivers/ide/pci/sl82c105.c
+- *
+  * SL82C105/Winbond 553 IDE driver
   *
-  *	Setting them to 0 will restore normal operation mode:
+  * Maintainer unknown.
+@@ -13,22 +11,17 @@
+  *  -- Benjamin Herrenschmidt (01/11/03) benh at kernel.crashing.org
   *
-@@ -528,9 +82,7 @@ typedef struct os_dat_s {
-  *	is verified to be stable enough. This will make it much more
-  *	esthetic.
+  * Copyright (C) 2006-2007 MontaVista Software, Inc. <source at mvista.com>
++ * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
   */
--#define IDETAPE_DEBUG_INFO		0
- #define IDETAPE_DEBUG_LOG		0
--#define IDETAPE_DEBUG_BUGS		1
  
- /*
-  *	After each failed packet command we issue a request sense command
-@@ -615,16 +167,6 @@ typedef struct os_dat_s {
- /*************************** End of tunable parameters ***********************/
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/interrupt.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/pci.h>
+ #include <linux/ide.h>
  
- /*
-- *	Debugging/Performance analysis
-- *
-- *	I/O trace support
-- */
--#define USE_IOTRACE	0
--#if USE_IOTRACE
--#define IO_IDETAPE_FIFO	500
--#endif
--
--/*
-  *	Read/Write error simulation
+ #include <asm/io.h>
+-#include <asm/dma.h>
+ 
+ #undef DEBUG
+ 
+@@ -77,7 +70,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
   */
- #define SIMULATE_ERRORS			0
-@@ -682,65 +224,6 @@ typedef struct idetape_packet_command_s {
- #define	PC_WRITING			5
+ static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
+ 	int reg			= 0x44 + drive->dn * 4;
+ 	u16 drv_ctrl;
  
- /*
-- *	Capabilities and Mechanical Status Page
-- */
--typedef struct {
--	unsigned	page_code	:6;	/* Page code - Should be 0x2a */
--	__u8		reserved0_6	:1;
--	__u8		ps		:1;	/* parameters saveable */
--	__u8		page_length;		/* Page Length - Should be 0x12 */
--	__u8		reserved2, reserved3;
--	unsigned	ro		:1;	/* Read Only Mode */
--	unsigned	reserved4_1234	:4;
--	unsigned	sprev		:1;	/* Supports SPACE in the reverse direction */
--	unsigned	reserved4_67	:2;
--	unsigned	reserved5_012	:3;
--	unsigned	efmt		:1;	/* Supports ERASE command initiated formatting */
--	unsigned	reserved5_4	:1;
--	unsigned	qfa		:1;	/* Supports the QFA two partition formats */
--	unsigned	reserved5_67	:2;
--	unsigned	lock		:1;	/* Supports locking the volume */
--	unsigned	locked		:1;	/* The volume is locked */
--	unsigned	prevent		:1;	/* The device defaults in the prevent state after power up */	
--	unsigned	eject		:1;	/* The device can eject the volume */
--	__u8		disconnect	:1;	/* The device can break request > ctl */	
--	__u8		reserved6_5	:1;
--	unsigned	ecc		:1;	/* Supports error correction */
--	unsigned	cmprs		:1;	/* Supports data compression */
--	unsigned	reserved7_0	:1;
--	unsigned	blk512		:1;	/* Supports 512 bytes block size */
--	unsigned	blk1024		:1;	/* Supports 1024 bytes block size */
--	unsigned	reserved7_3_6	:4;
--	unsigned	blk32768	:1;	/* slowb - the device restricts the byte count for PIO */
--						/* transfers for slow buffer memory ??? */
--						/* Also 32768 block size in some cases */
--	__u16		max_speed;		/* Maximum speed supported in KBps */
--	__u8		reserved10, reserved11;
--	__u16		ctl;			/* Continuous Transfer Limit in blocks */
--	__u16		speed;			/* Current Speed, in KBps */
--	__u16		buffer_size;		/* Buffer Size, in 512 bytes */
--	__u8		reserved18, reserved19;
--} idetape_capabilities_page_t;
+@@ -90,14 +83,8 @@ static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	drive->drive_data &= 0xffff0000;
+ 	drive->drive_data |= drv_ctrl;
+ 
+-	if (!drive->using_dma) {
+-		/*
+-		 * If we are actually using MW DMA, then we can not
+-		 * reprogram the interface drive control register.
+-		 */
+-		pci_write_config_word(dev, reg,  drv_ctrl);
+-		pci_read_config_word (dev, reg, &drv_ctrl);
+-	}
++	pci_write_config_word(dev, reg,  drv_ctrl);
++	pci_read_config_word (dev, reg, &drv_ctrl);
+ 
+ 	printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
+ 			  ide_xfer_verbose(pio + XFER_PIO_0),
+@@ -115,33 +102,14 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
+  	DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
+ 	     drive->name, ide_xfer_verbose(speed)));
+ 
+-	switch (speed) {
+-	case XFER_MW_DMA_2:
+-	case XFER_MW_DMA_1:
+-	case XFER_MW_DMA_0:
+-		drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
++	drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
+ 
+-		/*
+-		 * Store the DMA timings so that we can actually program
+-		 * them when DMA will be turned on...
+-		 */
+-		drive->drive_data &= 0x0000ffff;
+-		drive->drive_data |= (unsigned long)drv_ctrl << 16;
 -
--/*
-- *	Block Size Page
-- */
--typedef struct {
--	unsigned	page_code	:6;	/* Page code - Should be 0x30 */
--	unsigned	reserved1_6	:1;
--	unsigned	ps		:1;
--	__u8		page_length;		/* Page Length - Should be 2 */
--	__u8		reserved2;
--	unsigned	play32		:1;
--	unsigned	play32_5	:1;
--	unsigned	reserved2_23	:2;
--	unsigned	record32	:1;
--	unsigned	record32_5	:1;
--	unsigned	reserved2_6	:1;
--	unsigned	one		:1;
--} idetape_block_size_page_t;
+-		/*
+-		 * If we are already using DMA, we just reprogram
+-		 * the drive control register.
+-		 */
+-		if (drive->using_dma) {
+-			struct pci_dev *dev	= HWIF(drive)->pci_dev;
+-			int reg 		= 0x44 + drive->dn * 4;
 -
--/*
-  *	A pipeline stage.
-  */
- typedef struct idetape_stage_s {
-@@ -750,32 +233,6 @@ typedef struct idetape_stage_s {
- } idetape_stage_t;
+-			pci_write_config_word(dev, reg, drv_ctrl);
+-		}
+-		break;
+-	default:
+-		return;
+-	}
++	/*
++	 * Store the DMA timings so that we can actually program
++	 * them when DMA will be turned on...
++	 */
++	drive->drive_data &= 0x0000ffff;
++	drive->drive_data |= (unsigned long)drv_ctrl << 16;
+ }
  
  /*
-- *	REQUEST SENSE packet command result - Data Format.
-- */
--typedef struct {
--	unsigned	error_code	:7;	/* Current of deferred errors */
--	unsigned	valid		:1;	/* The information field conforms to QIC-157C */
--	__u8		reserved1	:8;	/* Segment Number - Reserved */
--	unsigned	sense_key	:4;	/* Sense Key */
--	unsigned	reserved2_4	:1;	/* Reserved */
--	unsigned	ili		:1;	/* Incorrect Length Indicator */
--	unsigned	eom		:1;	/* End Of Medium */
--	unsigned	filemark 	:1;	/* Filemark */
--	__u32		information __attribute__ ((packed));
--	__u8		asl;			/* Additional sense length (n-7) */
--	__u32		command_specific;	/* Additional command specific information */
--	__u8		asc;			/* Additional Sense Code */
--	__u8		ascq;			/* Additional Sense Code Qualifier */
--	__u8		replaceable_unit_code;	/* Field Replaceable Unit Code */
--	unsigned	sk_specific1 	:7;	/* Sense Key Specific */
--	unsigned	sksv		:1;	/* Sense Key Specific information is valid */
--	__u8		sk_specific2;		/* Sense Key Specific */
--	__u8		sk_specific3;		/* Sense Key Specific */
--	__u8		pad[2];			/* Padding to 20 bytes */
--} idetape_request_sense_result_t;
--
--
--/*
-  *	Most of our global data which we need to save even as we leave the
-  *	driver due to an interrupt or a timer event is stored in a variable
-  *	of type idetape_tape_t, defined below.
-@@ -865,8 +322,9 @@ typedef struct ide_tape_obj {
- 	/* Usually 512 or 1024 bytes */
- 	unsigned short tape_block_size;
- 	int user_bs_factor;
+@@ -171,7 +139,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
+ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u32 val, mask		= hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
+ 	u8 dma_cmd;
+ 
+@@ -208,7 +176,12 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
+ static void sl82c105_dma_start(ide_drive_t *drive)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
++	int reg 		= 0x44 + drive->dn * 4;
 +
- 	/* Copy of the tape's Capabilities and Mechanical Page */
--	idetape_capabilities_page_t capabilities;
-+	u8 caps[20];
++	DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
++
++	pci_write_config_word(dev, reg, drive->drive_data >> 16);
  
- 	/*
- 	 *	Active data transfer request parameters.
-@@ -929,9 +387,6 @@ typedef struct ide_tape_obj {
- 	int avg_size;
- 	int avg_speed;
+ 	sl82c105_reset_host(dev);
+ 	ide_dma_start(drive);
+@@ -216,80 +189,43 @@ static void sl82c105_dma_start(ide_drive_t *drive)
  
--	/* last sense information */
--	idetape_request_sense_result_t sense;
--
- 	char vendor_id[10];
- 	char product_id[18];
- 	char firmware_revision[6];
-@@ -1063,27 +518,6 @@ static void ide_tape_put(struct ide_tape_obj *tape)
- #define IDETAPE_MEDIUM_PRESENT		9
+ static void sl82c105_dma_timeout(ide_drive_t *drive)
+ {
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
++
+ 	DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
  
- /*
-- *	Supported ATAPI tape drives packet commands
-- */
--#define IDETAPE_TEST_UNIT_READY_CMD	0x00
--#define IDETAPE_REWIND_CMD		0x01
--#define IDETAPE_REQUEST_SENSE_CMD	0x03
--#define IDETAPE_READ_CMD		0x08
--#define IDETAPE_WRITE_CMD		0x0a
--#define IDETAPE_WRITE_FILEMARK_CMD	0x10
--#define IDETAPE_SPACE_CMD		0x11
--#define IDETAPE_INQUIRY_CMD		0x12
--#define IDETAPE_ERASE_CMD		0x19
--#define IDETAPE_MODE_SENSE_CMD		0x1a
--#define IDETAPE_MODE_SELECT_CMD		0x15
--#define IDETAPE_LOAD_UNLOAD_CMD		0x1b
--#define IDETAPE_PREVENT_CMD		0x1e
--#define IDETAPE_LOCATE_CMD		0x2b
--#define IDETAPE_READ_POSITION_CMD	0x34
--#define IDETAPE_READ_BUFFER_CMD		0x3c
--#define IDETAPE_SET_SPEED_CMD		0xbb
--
--/*
-  *	Some defines for the READ BUFFER command
-  */
- #define IDETAPE_RETRIEVE_FAULTY_BLOCK	6
-@@ -1140,31 +574,6 @@ struct idetape_id_gcw {
- };
+-	sl82c105_reset_host(HWIF(drive)->pci_dev);
++	sl82c105_reset_host(dev);
+ 	ide_dma_timeout(drive);
+ }
  
- /*
-- *	INQUIRY packet command - Data Format (From Table 6-8 of QIC-157C)
-- */
--typedef struct {
--	unsigned	device_type	:5;	/* Peripheral Device Type */
--	unsigned	reserved0_765	:3;	/* Peripheral Qualifier - Reserved */
--	unsigned	reserved1_6t0	:7;	/* Reserved */
--	unsigned	rmb		:1;	/* Removable Medium Bit */
--	unsigned	ansi_version	:3;	/* ANSI Version */
--	unsigned	ecma_version	:3;	/* ECMA Version */
--	unsigned	iso_version	:2;	/* ISO Version */
--	unsigned	response_format :4;	/* Response Data Format */
--	unsigned	reserved3_45	:2;	/* Reserved */
--	unsigned	reserved3_6	:1;	/* TrmIOP - Reserved */
--	unsigned	reserved3_7	:1;	/* AENC - Reserved */
--	__u8		additional_length;	/* Additional Length (total_length-4) */
--	__u8		rsv5, rsv6, rsv7;	/* Reserved */
--	__u8		vendor_id[8];		/* Vendor Identification */
--	__u8		product_id[16];		/* Product Identification */
--	__u8		revision_level[4];	/* Revision Level */
--	__u8		vendor_specific[20];	/* Vendor Specific - Optional */
--	__u8		reserved56t95[40];	/* Reserved - Optional */
--						/* Additional information may be returned */
--} idetape_inquiry_result_t;
+-static int sl82c105_ide_dma_on(ide_drive_t *drive)
++static int sl82c105_dma_end(ide_drive_t *drive)
+ {
+-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
+-	int rc, reg 		= 0x44 + drive->dn * 4;
 -
--/*
-  *	READ POSITION packet command - Data Format (From Table 6-57)
-  */
- typedef struct {
-@@ -1182,100 +591,9 @@ typedef struct {
- 	u32		bytes_in_buffer;	/* Bytes In Buffer (Optional) */
- } idetape_read_position_result_t;
- 
--/*
-- *	Follows structures which are related to the SELECT SENSE / MODE SENSE
-- *	packet commands. Those packet commands are still not supported
-- *	by ide-tape.
-- */
-+/* Structures related to the SELECT SENSE / MODE SENSE packet commands. */
- #define IDETAPE_BLOCK_DESCRIPTOR	0
- #define	IDETAPE_CAPABILITIES_PAGE	0x2a
--#define IDETAPE_PARAMTR_PAGE		0x2b   /* Onstream DI-x0 only */
--#define IDETAPE_BLOCK_SIZE_PAGE		0x30
--#define IDETAPE_BUFFER_FILLING_PAGE	0x33
+-	DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
 -
--/*
-- *	Mode Parameter Header for the MODE SENSE packet command
-- */
--typedef struct {
--	__u8	mode_data_length;	/* Length of the following data transfer */
--	__u8	medium_type;		/* Medium Type */
--	__u8	dsp;			/* Device Specific Parameter */
--	__u8	bdl;			/* Block Descriptor Length */
--#if 0
--	/* data transfer page */
--	__u8	page_code	:6;
--	__u8	reserved0_6	:1;
--	__u8	ps		:1;	/* parameters saveable */
--	__u8	page_length;		/* page Length == 0x02 */
--	__u8	reserved2;
--	__u8	read32k		:1;	/* 32k blk size (data only) */
--	__u8	read32k5	:1;	/* 32.5k blk size (data&AUX) */
--	__u8	reserved3_23	:2;
--	__u8	write32k	:1;	/* 32k blk size (data only) */
--	__u8	write32k5	:1;	/* 32.5k blk size (data&AUX) */
--	__u8	reserved3_6	:1;
--	__u8	streaming	:1;	/* streaming mode enable */
--#endif
--} idetape_mode_parameter_header_t;
+-	rc = __ide_dma_on(drive);
+-	if (rc == 0) {
+-		pci_write_config_word(dev, reg, drive->drive_data >> 16);
 -
--/*
-- *	Mode Parameter Block Descriptor the MODE SENSE packet command
-- *
-- *	Support for block descriptors is optional.
-- */
--typedef struct {
--	__u8		density_code;		/* Medium density code */
--	__u8		blocks[3];		/* Number of blocks */
--	__u8		reserved4;		/* Reserved */
--	__u8		length[3];		/* Block Length */
--} idetape_parameter_block_descriptor_t;
+-		printk(KERN_INFO "%s: DMA enabled\n", drive->name);
+-	}
+-	return rc;
+-}
 -
+-static void sl82c105_dma_off_quietly(ide_drive_t *drive)
+-{
+-	struct pci_dev *dev	= HWIF(drive)->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
+ 	int reg 		= 0x44 + drive->dn * 4;
++	int ret;
+ 
+-	DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
++	DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
+ 
+-	pci_write_config_word(dev, reg, drive->drive_data);
++	ret = __ide_dma_end(drive);
+ 
+-	ide_dma_off_quietly(drive);
+-}
++	pci_write_config_word(dev, reg, drive->drive_data);
+ 
 -/*
-- *	The Data Compression Page, as returned by the MODE SENSE packet command.
+- * Ok, that is nasty, but we must make sure the DMA timings
+- * won't be used for a PIO access. The solution here is
+- * to make sure the 16 bits mode is diabled on the channel
+- * when DMA is enabled, thus causing the chip to use PIO0
+- * timings for those operations.
 - */
--typedef struct {
--	unsigned	page_code	:6;	/* Page Code - Should be 0xf */
--	unsigned	reserved0	:1;	/* Reserved */
--	unsigned	ps		:1;
--	__u8		page_length;		/* Page Length - Should be 14 */
--	unsigned	reserved2	:6;	/* Reserved */
--	unsigned	dcc		:1;	/* Data Compression Capable */
--	unsigned	dce		:1;	/* Data Compression Enable */
--	unsigned	reserved3	:5;	/* Reserved */
--	unsigned	red		:2;	/* Report Exception on Decompression */
--	unsigned	dde		:1;	/* Data Decompression Enable */
--	__u32		ca;			/* Compression Algorithm */
--	__u32		da;			/* Decompression Algorithm */
--	__u8		reserved[4];		/* Reserved */
--} idetape_data_compression_page_t;
+-static void sl82c105_selectproc(ide_drive_t *drive)
+-{
+-	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
+-	u32 val, old, mask;
 -
--/*
-- *	The Medium Partition Page, as returned by the MODE SENSE packet command.
-- */
--typedef struct {
--	unsigned	page_code	:6;	/* Page Code - Should be 0x11 */
--	unsigned	reserved1_6	:1;	/* Reserved */
--	unsigned	ps		:1;
--	__u8		page_length;		/* Page Length - Should be 6 */
--	__u8		map;			/* Maximum Additional Partitions - Should be 0 */
--	__u8		apd;			/* Additional Partitions Defined - Should be 0 */
--	unsigned	reserved4_012	:3;	/* Reserved */
--	unsigned	psum		:2;	/* Should be 0 */
--	unsigned	idp		:1;	/* Should be 0 */
--	unsigned	sdp		:1;	/* Should be 0 */
--	unsigned	fdp		:1;	/* Fixed Data Partitions */
--	__u8		mfr;			/* Medium Format Recognition */
--	__u8		reserved[2];		/* Reserved */
--} idetape_medium_partition_page_t;
+-	//DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
 -
--/*
-- *	Run time configurable parameters.
-- */
--typedef struct {
--	int	dsc_rw_frequency;
--	int	dsc_media_access_frequency;
--	int	nr_stages;
--} idetape_config_t;
+-	mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16;
+-	old = val = (u32)pci_get_drvdata(dev);
+-	if (drive->using_dma)
+-		val &= ~mask;
+-	else
+-		val |= mask;
+-	if (old != val) {
+-		pci_write_config_dword(dev, 0x40, val);	
+-		pci_set_drvdata(dev, (void *)val);
+-	}
++	return ret;
+ }
  
  /*
-  *	The variables below are used for the character device interface.
-@@ -1320,14 +638,12 @@ static void idetape_input_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsigne
- 	int count;
+  * ATA reset will clear the 16 bits mode in the control
+- * register, we need to update our cache
++ * register, we need to reprogram it
+  */
+ static void sl82c105_resetproc(ide_drive_t *drive)
+ {
+-	struct pci_dev *dev = HWIF(drive)->pci_dev;
++	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
+ 	u32 val;
  
- 	while (bcount) {
--#if IDETAPE_DEBUG_BUGS
- 		if (bh == NULL) {
- 			printk(KERN_ERR "ide-tape: bh == NULL in "
- 				"idetape_input_buffers\n");
- 			idetape_discard_data(drive, bcount);
- 			return;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), bcount);
- 		HWIF(drive)->atapi_input_bytes(drive, bh->b_data + atomic_read(&bh->b_count), count);
- 		bcount -= count;
-@@ -1347,13 +663,11 @@ static void idetape_output_buffers (ide_drive_t *drive, idetape_pc_t *pc, unsign
- 	int count;
+ 	DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
  
- 	while (bcount) {
--#if IDETAPE_DEBUG_BUGS
- 		if (bh == NULL) {
- 			printk(KERN_ERR "ide-tape: bh == NULL in "
- 				"idetape_output_buffers\n");
- 			return;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		count = min((unsigned int)pc->b_count, (unsigned int)bcount);
- 		HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count);
- 		bcount -= count;
-@@ -1378,13 +692,11 @@ static void idetape_update_buffers (idetape_pc_t *pc)
- 	if (test_bit(PC_WRITING, &pc->flags))
- 		return;
- 	while (bcount) {
--#if IDETAPE_DEBUG_BUGS
- 		if (bh == NULL) {
- 			printk(KERN_ERR "ide-tape: bh == NULL in "
- 				"idetape_update_buffers\n");
- 			return;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		count = min((unsigned int)bh->b_size, (unsigned int)bcount);
- 		atomic_set(&bh->b_count, count);
- 		if (atomic_read(&bh->b_count) == bh->b_size)
-@@ -1457,36 +769,34 @@ static void idetape_init_pc (idetape_pc_t *pc)
+ 	pci_read_config_dword(dev, 0x40, &val);
+-	pci_set_drvdata(dev, (void *)val);
++	val |= (CTRL_P1F16 | CTRL_P0F16);
++	pci_write_config_dword(dev, 0x40, val);
  }
  
  /*
-- *	idetape_analyze_error is called on each failed packet command retry
-- *	to analyze the request sense. We currently do not utilize this
-- *	information.
-+ * called on each failed packet command retry to analyze the request sense. We
-+ * currently do not utilize this information.
+@@ -342,7 +278,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
+ 	pci_read_config_dword(dev, 0x40, &val);
+ 	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
+ 	pci_write_config_dword(dev, 0x40, val);
+-	pci_set_drvdata(dev, (void *)val);
+ 
+ 	return dev->irq;
+ }
+@@ -352,19 +287,19 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
   */
--static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_result_t *result)
-+static void idetape_analyze_error(ide_drive_t *drive, u8 *sense)
+ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
  {
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t *pc = tape->failed_pc;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	unsigned int rev;
  
--	tape->sense     = *result;
--	tape->sense_key = result->sense_key;
--	tape->asc       = result->asc;
--	tape->ascq      = result->ascq;
-+	tape->sense_key = sense[2] & 0xF;
-+	tape->asc       = sense[12];
-+	tape->ascq      = sense[13];
- #if IDETAPE_DEBUG_LOG
- 	/*
--	 *	Without debugging, we only log an error if we decided to
--	 *	give up retrying.
-+	 * Without debugging, we only log an error if we decided to give up
-+	 * retrying.
- 	 */
- 	if (tape->debug_level >= 1)
- 		printk(KERN_INFO "ide-tape: pc = %x, sense key = %x, "
- 			"asc = %x, ascq = %x\n",
--			pc->c[0], result->sense_key,
--			result->asc, result->ascq);
-+			pc->c[0], tape->sense_key,
-+			tape->asc, tape->ascq);
- #endif /* IDETAPE_DEBUG_LOG */
+ 	DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
  
--	/*
--	 *	Correct pc->actually_transferred by asking the tape.
--	 */
-+	/* Correct pc->actually_transferred by asking the tape.	 */
- 	if (test_bit(PC_DMA_ERROR, &pc->flags)) {
--		pc->actually_transferred = pc->request_transfer - tape->tape_block_size * ntohl(get_unaligned(&result->information));
-+		pc->actually_transferred = pc->request_transfer -
-+			tape->tape_block_size *
-+			be32_to_cpu(get_unaligned((u32 *)&sense[3]));
- 		idetape_update_buffers(pc);
- 	}
+ 	hwif->set_pio_mode	= &sl82c105_set_pio_mode;
+ 	hwif->set_dma_mode	= &sl82c105_set_dma_mode;
+-	hwif->selectproc	= &sl82c105_selectproc;
+ 	hwif->resetproc 	= &sl82c105_resetproc;
  
-@@ -1495,29 +805,29 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
- 	 * with sense key=5, asc=0x22, ascq=0, let it slide.  Some drives
- 	 * (i.e. Seagate STT3401A Travan) don't support 0-length read/writes.
- 	 */
--	if ((pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD)
--	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) { /* length==0 */
--		if (result->sense_key == 5) {
-+	if ((pc->c[0] == READ_6 || pc->c[0] == WRITE_6)
-+	    /* length == 0 */
-+	    && pc->c[4] == 0 && pc->c[3] == 0 && pc->c[2] == 0) {
-+		if (tape->sense_key == 5) {
- 			/* don't report an error, everything's ok */
- 			pc->error = 0;
- 			/* don't retry read/write */
- 			set_bit(PC_ABORT, &pc->flags);
- 		}
- 	}
--	if (pc->c[0] == IDETAPE_READ_CMD && result->filemark) {
-+	if (pc->c[0] == READ_6 && (sense[2] & 0x80)) {
- 		pc->error = IDETAPE_ERROR_FILEMARK;
- 		set_bit(PC_ABORT, &pc->flags);
- 	}
--	if (pc->c[0] == IDETAPE_WRITE_CMD) {
--		if (result->eom ||
--		    (result->sense_key == 0xd && result->asc == 0x0 &&
--		     result->ascq == 0x2)) {
-+	if (pc->c[0] == WRITE_6) {
-+		if ((sense[2] & 0x40) || (tape->sense_key == 0xd
-+		     && tape->asc == 0x0 && tape->ascq == 0x2)) {
- 			pc->error = IDETAPE_ERROR_EOD;
- 			set_bit(PC_ABORT, &pc->flags);
- 		}
- 	}
--	if (pc->c[0] == IDETAPE_READ_CMD || pc->c[0] == IDETAPE_WRITE_CMD) {
--		if (result->sense_key == 8) {
-+	if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) {
-+		if (tape->sense_key == 8) {
- 			pc->error = IDETAPE_ERROR_EOD;
- 			set_bit(PC_ABORT, &pc->flags);
- 		}
-@@ -1527,10 +837,7 @@ static void idetape_analyze_error (ide_drive_t *drive, idetape_request_sense_res
+ 	if (!hwif->dma_base)
+ 		return;
+ 
+-	rev = sl82c105_bridge_revision(hwif->pci_dev);
++	rev = sl82c105_bridge_revision(dev);
+ 	if (rev <= 5) {
+ 		/*
+ 		 * Never ever EVER under any circumstances enable
+@@ -377,10 +312,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
+ 
+ 	hwif->mwdma_mask = ATA_MWDMA2;
+ 
+-	hwif->ide_dma_on		= &sl82c105_ide_dma_on;
+-	hwif->dma_off_quietly		= &sl82c105_dma_off_quietly;
+ 	hwif->dma_lost_irq		= &sl82c105_dma_lost_irq;
+ 	hwif->dma_start			= &sl82c105_dma_start;
++	hwif->ide_dma_end		= &sl82c105_dma_end;
+ 	hwif->dma_timeout		= &sl82c105_dma_timeout;
+ 
+ 	if (hwif->mate)
+diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
+index eb4445b..65f4c2f 100644
+--- a/drivers/ide/pci/slc90e66.c
++++ b/drivers/ide/pci/slc90e66.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/pci/slc90e66.c	Version 0.19	Sep 24, 2007
+- *
+  *  Copyright (C) 2000-2002 Andre Hedrick <andre at linux-ide.org>
+  *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source at mvista.com>
+  *
+@@ -12,21 +10,17 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/ioport.h>
+ #include <linux/pci.h>
+ #include <linux/hdreg.h>
+ #include <linux/ide.h>
+-#include <linux/delay.h>
+ #include <linux/init.h>
+ 
+-#include <asm/io.h>
+-
+ static DEFINE_SPINLOCK(slc90e66_lock);
+ 
+ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	int is_slave		= drive->dn & 1;
+ 	int master_port		= hwif->channel ? 0x42 : 0x40;
+ 	int slave_port		= 0x44;
+@@ -79,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif	= HWIF(drive);
+-	struct pci_dev *dev	= hwif->pci_dev;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
+ 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
+ 	int sitre = 0, a_speed	= 7 << (drive->dn * 4);
+ 	int u_speed = 0, u_flag = 1 << drive->dn;
+@@ -91,19 +85,9 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	pci_read_config_word(dev, 0x48, &reg48);
+ 	pci_read_config_word(dev, 0x4a, &reg4a);
+ 
+-	switch(speed) {
+-		case XFER_UDMA_4:	u_speed = 4 << (drive->dn * 4); break;
+-		case XFER_UDMA_3:	u_speed = 3 << (drive->dn * 4); break;
+-		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
+-		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
+-		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_SW_DMA_2:	break;
+-		default:		return;
+-	}
+-
+ 	if (speed >= XFER_UDMA_0) {
++		u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
++
+ 		if (!(reg48 & u_flag))
+ 			pci_write_config_word(dev, 0x48, reg48|u_flag);
+ 		/* FIXME: (reg4a & a_speed) ? */
+@@ -130,22 +114,23 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
  	}
  }
  
--/*
-- * idetape_active_next_stage will declare the next stage as "active".
-- */
--static void idetape_active_next_stage (ide_drive_t *drive)
-+static void idetape_activate_next_stage(ide_drive_t *drive)
+-static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
++static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif)
  {
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_stage_t *stage = tape->next_stage;
-@@ -1540,12 +847,10 @@ static void idetape_active_next_stage (ide_drive_t *drive)
- 	if (tape->debug_level >= 4)
- 		printk(KERN_INFO "ide-tape: Reached idetape_active_next_stage\n");
- #endif /* IDETAPE_DEBUG_LOG */
--#if IDETAPE_DEBUG_BUGS
- 	if (stage == NULL) {
- 		printk(KERN_ERR "ide-tape: bug: Trying to activate a non existing stage\n");
- 		return;
- 	}
--#endif /* IDETAPE_DEBUG_BUGS */	
+-	u8 reg47 = 0;
+-	u8 mask = hwif->channel ? 0x01 : 0x02;  /* bit0:Primary */
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02;
  
- 	rq->rq_disk = tape->disk;
- 	rq->buffer = NULL;
-@@ -1620,28 +925,24 @@ static void idetape_remove_stage_head (ide_drive_t *drive)
- 	if (tape->debug_level >= 4)
- 		printk(KERN_INFO "ide-tape: Reached idetape_remove_stage_head\n");
- #endif /* IDETAPE_DEBUG_LOG */
--#if IDETAPE_DEBUG_BUGS
- 	if (tape->first_stage == NULL) {
- 		printk(KERN_ERR "ide-tape: bug: tape->first_stage is NULL\n");
--		return;		
-+		return;
- 	}
- 	if (tape->active_stage == tape->first_stage) {
- 		printk(KERN_ERR "ide-tape: bug: Trying to free our active pipeline stage\n");
+-	hwif->set_pio_mode = &slc90e66_set_pio_mode;
+-	hwif->set_dma_mode = &slc90e66_set_dma_mode;
++	pci_read_config_byte(dev, 0x47, &reg47);
+ 
+-	pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
++	/* bit[0(1)]: 0:80, 1:40 */
++	return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++}
+ 
+-	if (hwif->dma_base == 0)
+-		return;
++static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
++{
++	hwif->set_pio_mode = &slc90e66_set_pio_mode;
++	hwif->set_dma_mode = &slc90e66_set_dma_mode;
+ 
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		/* bit[0(1)]: 0:80, 1:40 */
+-		hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++	hwif->cable_detect = slc90e66_cable_detect;
+ }
+ 
+ static const struct ide_port_info slc90e66_chipset __devinitdata = {
+diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
+index a66ebd1..2ef2ed2 100644
+--- a/drivers/ide/pci/tc86c001.c
++++ b/drivers/ide/pci/tc86c001.c
+@@ -1,6 +1,4 @@
+ /*
+- * drivers/ide/pci/tc86c001.c	Version 1.01	Sep 5, 2007
+- *
+  * Copyright (C) 2002 Toshiba Corporation
+  * Copyright (C) 2005-2006 MontaVista Software, Inc. <source at mvista.com>
+  *
+@@ -162,9 +160,23 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
+ 	return 0;
+ }
+ 
++static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
++{
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	unsigned long sc_base = pci_resource_start(dev, 5);
++	u16 scr1 = inw(sc_base + 0x00);
++
++	/*
++	 * System Control  1 Register bit 13 (PDIAGN):
++	 * 0=80-pin cable, 1=40-pin cable
++	 */
++	return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++}
++
+ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+ {
+-	unsigned long sc_base	= pci_resource_start(hwif->pci_dev, 5);
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
++	unsigned long sc_base	= pci_resource_start(dev, 5);
+ 	u16 scr1		= inw(sc_base + 0x00);
+ 
+ 	/* System Control 1 Register bit 15 (Soft Reset) set */
+@@ -184,6 +196,8 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+ 
+ 	hwif->busproc	= &tc86c001_busproc;
+ 
++	hwif->cable_detect = tc86c001_cable_detect;
++
+ 	if (!hwif->dma_base)
  		return;
+ 
+@@ -197,15 +211,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
+ 	hwif->rqsize	 = 0xffff;
+ 
+ 	hwif->dma_start 	= &tc86c001_dma_start;
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
+-		/*
+-		 * System Control  1 Register bit 13 (PDIAGN):
+-		 * 0=80-pin cable, 1=40-pin cable
+-		 */
+-		scr1 = inw(sc_base + 0x00);
+-		hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+-	}
+ }
+ 
+ static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
+@@ -222,7 +227,8 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
+ 	.name		= "TC86C001",
+ 	.init_chipset	= init_chipset_tc86c001,
+ 	.init_hwif	= init_hwif_tc86c001,
+-	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
++	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
++			  IDE_HFLAG_ABUSE_SET_DMA_MODE,
+ 	.pio_mask	= ATA_PIO4,
+ 	.mwdma_mask	= ATA_MWDMA2,
+ 	.udma_mask	= ATA_UDMA4,
+diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
+index a227c41..a67d02a 100644
+--- a/drivers/ide/pci/triflex.c
++++ b/drivers/ide/pci/triflex.c
+@@ -1,6 +1,4 @@
+ /*
+- * triflex.c
+- * 
+  * IDE Chipset driver for the Compaq TriFlex IDE controller.
+  * 
+  * Known to work with the Compaq Workstation 5x00 series.
+@@ -30,11 +28,6 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/delay.h>
+-#include <linux/timer.h>
+-#include <linux/mm.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/hdreg.h>
+ #include <linux/pci.h>
+ #include <linux/ide.h>
+@@ -43,7 +36,7 @@
+ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
+ {
+ 	ide_hwif_t *hwif = HWIF(drive);
+-	struct pci_dev *dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	u8 channel_offset = hwif->channel ? 0x74 : 0x70;
+ 	u16 timing = 0;
+ 	u32 triflex_timings = 0;
+@@ -81,8 +74,6 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
+ 		case XFER_PIO_0:
+ 			timing = 0x0808;
+ 			break;
+-		default:
+-			return;
  	}
--#endif /* IDETAPE_DEBUG_BUGS */
- 	stage = tape->first_stage;
- 	tape->first_stage = stage->next;
- 	idetape_kfree_stage(tape, stage);
- 	tape->nr_stages--;
- 	if (tape->first_stage == NULL) {
- 		tape->last_stage = NULL;
--#if IDETAPE_DEBUG_BUGS
- 		if (tape->next_stage != NULL)
- 			printk(KERN_ERR "ide-tape: bug: tape->next_stage != NULL\n");
- 		if (tape->nr_stages)
- 			printk(KERN_ERR "ide-tape: bug: nr_stages should be 0 now\n");
--#endif /* IDETAPE_DEBUG_BUGS */
+ 
+ 	triflex_timings &= ~(0xFFFF << (16 * unit));
+diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
+index 0151d7f..de750f7 100644
+--- a/drivers/ide/pci/trm290.c
++++ b/drivers/ide/pci/trm290.c
+@@ -1,8 +1,7 @@
+ /*
+- *  linux/drivers/ide/pci/trm290.c		Version 1.05	Dec. 26, 2007
+- *
+  *  Copyright (c) 1997-1998  Mark Lord
+  *  Copyright (c) 2007       MontaVista Software, Inc. <source at mvista.com>
++ *
+  *  May be copied or modified under the terms of the GNU General Public License
+  *
+  *  June 22, 2004 - get rid of check_region
+@@ -132,14 +131,12 @@
+ #include <linux/types.h>
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/mm.h>
+ #include <linux/ioport.h>
+ #include <linux/interrupt.h>
+ #include <linux/blkdev.h>
+ #include <linux/init.h>
+ #include <linux/hdreg.h>
+ #include <linux/pci.h>
+-#include <linux/delay.h>
+ #include <linux/ide.h>
+ 
+ #include <asm/io.h>
+@@ -180,10 +177,7 @@ static void trm290_selectproc (ide_drive_t *drive)
+ 
+ static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
+ {
+-	BUG_ON(HWGROUP(drive)->handler != NULL);	/* paranoia check */
+-	ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
+-	/* issue cmd to drive */
+-	outb(command, IDE_COMMAND_REG);
++	ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL);
+ }
+ 
+ static int trm290_dma_setup(ide_drive_t *drive)
+@@ -209,10 +203,10 @@ static int trm290_dma_setup(ide_drive_t *drive)
  	}
+ 	/* select DMA xfer */
+ 	trm290_prepare_drive(drive, 1);
+-	outl(hwif->dmatable_dma | rw, hwif->dma_command);
++	outl(hwif->dmatable_dma | rw, hwif->dma_base);
+ 	drive->waiting_for_dma = 1;
+ 	/* start DMA */
+-	outw((count * 2) - 1, hwif->dma_status);
++	outw(count * 2 - 1, hwif->dma_base + 2);
+ 	return 0;
  }
  
-@@ -1700,6 +1001,11 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
- 	if (error)
- 		tape->failed_pc = NULL;
+@@ -222,51 +216,61 @@ static void trm290_dma_start(ide_drive_t *drive)
  
-+	if (!blk_special_request(rq)) {
-+		ide_end_request(drive, uptodate, nr_sects);
-+		return 0;
-+	}
-+
- 	spin_lock_irqsave(&tape->spinlock, flags);
+ static int trm290_ide_dma_end (ide_drive_t *drive)
+ {
+-	ide_hwif_t *hwif = HWIF(drive);
+-	u16 status = 0;
++	u16 status;
  
- 	/* The request was a pipelined data transfer request */
-@@ -1722,7 +1028,7 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects)
- 			}
- 		}
- 		if (tape->next_stage != NULL) {
--			idetape_active_next_stage(drive);
-+			idetape_activate_next_stage(drive);
+ 	drive->waiting_for_dma = 0;
+ 	/* purge DMA mappings */
+ 	ide_destroy_dmatable(drive);
+-	status = inw(hwif->dma_status);
+-	return (status != 0x00ff);
++	status = inw(HWIF(drive)->dma_base + 2);
++	return status != 0x00ff;
+ }
  
- 			/*
- 			 * Insert the next request into the request queue.
-@@ -1754,7 +1060,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
- 		printk(KERN_INFO "ide-tape: Reached idetape_request_sense_callback\n");
- #endif /* IDETAPE_DEBUG_LOG */
- 	if (!tape->pc->error) {
--		idetape_analyze_error(drive, (idetape_request_sense_result_t *) tape->pc->buffer);
-+		idetape_analyze_error(drive, tape->pc->buffer);
- 		idetape_end_request(drive, 1, 0);
- 	} else {
- 		printk(KERN_ERR "ide-tape: Error in REQUEST SENSE itself - Aborting request!\n");
-@@ -1766,7 +1072,7 @@ static ide_startstop_t idetape_request_sense_callback (ide_drive_t *drive)
- static void idetape_create_request_sense_cmd (idetape_pc_t *pc)
+ static int trm290_ide_dma_test_irq (ide_drive_t *drive)
  {
- 	idetape_init_pc(pc);	
--	pc->c[0] = IDETAPE_REQUEST_SENSE_CMD;
-+	pc->c[0] = REQUEST_SENSE;
- 	pc->c[4] = 20;
- 	pc->request_transfer = 20;
- 	pc->callback = &idetape_request_sense_callback;
-@@ -1818,9 +1124,8 @@ static ide_startstop_t idetape_retry_pc (ide_drive_t *drive)
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t *pc;
- 	struct request *rq;
--	atapi_error_t error;
+-	ide_hwif_t *hwif = HWIF(drive);
+-	u16 status = 0;
++	u16 status;
  
--	error.all = HWIF(drive)->INB(IDE_ERROR_REG);
-+	(void)drive->hwif->INB(IDE_ERROR_REG);
- 	pc = idetape_next_pc_storage(drive);
- 	rq = idetape_next_rq_storage(drive);
- 	idetape_create_request_sense_cmd(pc);
-@@ -1858,15 +1163,13 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
+-	status = inw(hwif->dma_status);
+-	return (status == 0x00ff);
+-}
+-
+-static void trm290_dma_host_on(ide_drive_t *drive)
+-{
++	status = inw(HWIF(drive)->dma_base + 2);
++	return status == 0x00ff;
+ }
+ 
+-static void trm290_dma_host_off(ide_drive_t *drive)
++static void trm290_dma_host_set(ide_drive_t *drive, int on)
  {
- 	ide_hwif_t *hwif = drive->hwif;
- 	idetape_tape_t *tape = drive->driver_data;
--	atapi_status_t status;
--	atapi_bcount_t bcount;
--	atapi_ireason_t ireason;
- 	idetape_pc_t *pc = tape->pc;
+ }
+ 
+ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+ {
+-	unsigned int cfgbase = 0;
++	struct pci_dev *dev	= to_pci_dev(hwif->dev);
++	unsigned int  cfg_base	= pci_resource_start(dev, 4);
+ 	unsigned long flags;
+ 	u8 reg = 0;
+-	struct pci_dev *dev = hwif->pci_dev;
 -
- 	unsigned int temp;
- #if SIMULATE_ERRORS
- 	static int error_sim_count = 0;
- #endif
-+	u16 bcount;
-+	u8 stat, ireason;
+-	cfgbase = pci_resource_start(dev, 4);
+-	if ((dev->class & 5) && cfgbase) {
+-		hwif->config_data = cfgbase;
+-		printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n",
+-			hwif->config_data);
+-	} else {
+-		hwif->config_data = 0x3df0;
+-		printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n",
+-			hwif->config_data);
++
++	if ((dev->class & 5) && cfg_base)
++		printk(KERN_INFO "TRM290: chip");
++	else {
++		cfg_base = 0x3df0;
++		printk(KERN_INFO "TRM290: using default");
++	}
++	printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
++	hwif->config_data = cfg_base;
++	hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
++
++	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
++	       hwif->name, hwif->dma_base, hwif->dma_base + 3);
++
++	if (!request_region(hwif->dma_base, 4, hwif->name)) {
++		printk(KERN_CONT " -- Error, ports in use.\n");
++		return;
+ 	}
  
- #if IDETAPE_DEBUG_LOG
- 	if (tape->debug_level >= 4)
-@@ -1875,10 +1178,10 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
- #endif /* IDETAPE_DEBUG_LOG */	
++	hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES,
++						  &hwif->dmatable_dma);
++	if (!hwif->dmatable_cpu) {
++		printk(KERN_CONT " -- Error, unable to allocate DMA table.\n");
++		release_region(hwif->dma_base, 4);
++		return;
++	}
++	printk(KERN_CONT "\n");
++
+ 	local_irq_save(flags);
+ 	/* put config reg into first byte of hwif->select_data */
+ 	outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
+@@ -280,17 +284,14 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
+ 	outb(reg, hwif->config_data + 3);
+ 	local_irq_restore(flags);
  
- 	/* Clear the interrupt */
--	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
-+	stat = hwif->INB(IDE_STATUS_REG);
+-	if ((reg & 0x10))
++	if (reg & 0x10)
+ 		/* legacy mode */
+ 		hwif->irq = hwif->channel ? 15 : 14;
+ 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
+ 		/* sharing IRQ with mate */
+ 		hwif->irq = hwif->mate->irq;
  
- 	if (test_bit(PC_DMA_IN_PROGRESS, &pc->flags)) {
--		if (HWIF(drive)->ide_dma_end(drive) || status.b.check) {
-+		if (hwif->ide_dma_end(drive) || (stat & ERR_STAT)) {
- 			/*
- 			 * A DMA error is sometimes expected. For example,
- 			 * if the tape is crossing a filemark during a
-@@ -1912,7 +1215,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
- 	}
+-	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
+-
+-	hwif->dma_host_off	= &trm290_dma_host_off;
+-	hwif->dma_host_on	= &trm290_dma_host_on;
++	hwif->dma_host_set	= &trm290_dma_host_set;
+ 	hwif->dma_setup 	= &trm290_dma_setup;
+ 	hwif->dma_exec_cmd	= &trm290_dma_exec_cmd;
+ 	hwif->dma_start 	= &trm290_dma_start;
+diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
+index a0d3c16..f3f79f8 100644
+--- a/drivers/ide/pci/via82cxxx.c
++++ b/drivers/ide/pci/via82cxxx.c
+@@ -1,7 +1,4 @@
+ /*
+- *
+- * Version 3.50
+- *
+  * VIA IDE driver for Linux. Supported southbridges:
+  *
+  *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
+@@ -29,15 +26,11 @@
  
- 	/* No more interrupts */
--	if (!status.b.drq) {
-+	if ((stat & DRQ_STAT) == 0) {
- #if IDETAPE_DEBUG_LOG
- 		if (tape->debug_level >= 2)
- 			printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred);
-@@ -1922,23 +1225,23 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
- 		local_irq_enable();
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+-#include <linux/ioport.h>
+-#include <linux/blkdev.h>
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/ide.h>
+ #include <linux/dmi.h>
  
- #if SIMULATE_ERRORS
--		if ((pc->c[0] == IDETAPE_WRITE_CMD ||
--		     pc->c[0] == IDETAPE_READ_CMD) &&
-+		if ((pc->c[0] == WRITE_6 || pc->c[0] == READ_6) &&
- 		    (++error_sim_count % 100) == 0) {
- 			printk(KERN_INFO "ide-tape: %s: simulating error\n",
- 				tape->name);
--			status.b.check = 1;
-+			stat |= ERR_STAT;
- 		}
+-#include <asm/io.h>
+-
+ #ifdef CONFIG_PPC_CHRP
+ #include <asm/processor.h>
  #endif
--		if (status.b.check && pc->c[0] == IDETAPE_REQUEST_SENSE_CMD)
--			status.b.check = 0;
--		if (status.b.check || test_bit(PC_DMA_ERROR, &pc->flags)) {	/* Error detected */
-+		if ((stat & ERR_STAT) && pc->c[0] == REQUEST_SENSE)
-+			stat &= ~ERR_STAT;
-+		if ((stat & ERR_STAT) || test_bit(PC_DMA_ERROR, &pc->flags)) {
-+			/* Error detected */
- #if IDETAPE_DEBUG_LOG
- 			if (tape->debug_level >= 1)
- 				printk(KERN_INFO "ide-tape: %s: I/O error\n",
- 					tape->name);
- #endif /* IDETAPE_DEBUG_LOG */
--			if (pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
-+			if (pc->c[0] == REQUEST_SENSE) {
- 				printk(KERN_ERR "ide-tape: I/O error in request sense command\n");
- 				return ide_do_reset(drive);
- 			}
-@@ -1951,7 +1254,7 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
- 		}
- 		pc->error = 0;
- 		if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) &&
--		    !status.b.dsc) {
-+		    (stat & SEEK_STAT) == 0) {
- 			/* Media access command */
- 			tape->dsc_polling_start = jiffies;
- 			tape->dsc_polling_frequency = IDETAPE_DSC_MA_FAST;
-@@ -1973,30 +1276,30 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
- 		return ide_do_reset(drive);
- 	}
- 	/* Get the number of bytes to transfer on this interrupt. */
--	bcount.b.high = hwif->INB(IDE_BCOUNTH_REG);
--	bcount.b.low = hwif->INB(IDE_BCOUNTL_REG);
-+	bcount = (hwif->INB(IDE_BCOUNTH_REG) << 8) |
-+		  hwif->INB(IDE_BCOUNTL_REG);
+@@ -121,8 +114,8 @@ struct via82cxxx_dev
  
--	ireason.all = hwif->INB(IDE_IREASON_REG);
-+	ireason = hwif->INB(IDE_IREASON_REG);
+ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
+ {
+-	struct pci_dev *dev = hwif->pci_dev;
+-	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+ 	u8 t;
  
--	if (ireason.b.cod) {
-+	if (ireason & CD) {
- 		printk(KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
- 		return ide_do_reset(drive);
- 	}
--	if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {
-+	if (((ireason & IO) == IO) == test_bit(PC_WRITING, &pc->flags)) {
- 		/* Hopefully, we will never get here */
- 		printk(KERN_ERR "ide-tape: We wanted to %s, ",
--			ireason.b.io ? "Write":"Read");
-+				(ireason & IO) ? "Write" : "Read");
- 		printk(KERN_ERR "ide-tape: but the tape wants us to %s !\n",
--			ireason.b.io ? "Read":"Write");
-+				(ireason & IO) ? "Read" : "Write");
- 		return ide_do_reset(drive);
- 	}
- 	if (!test_bit(PC_WRITING, &pc->flags)) {
- 		/* Reading - Check that we have enough space */
--		temp = pc->actually_transferred + bcount.all;
-+		temp = pc->actually_transferred + bcount;
- 		if (temp > pc->request_transfer) {
- 			if (temp > pc->buffer_size) {
- 				printk(KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
--				idetape_discard_data(drive, bcount.all);
-+				idetape_discard_data(drive, bcount);
- 				ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
- 				return ide_started;
- 			}
-@@ -2008,23 +1311,26 @@ static ide_startstop_t idetape_pc_intr (ide_drive_t *drive)
- 	}
- 	if (test_bit(PC_WRITING, &pc->flags)) {
- 		if (pc->bh != NULL)
--			idetape_output_buffers(drive, pc, bcount.all);
-+			idetape_output_buffers(drive, pc, bcount);
- 		else
- 			/* Write the current buffer */
--			HWIF(drive)->atapi_output_bytes(drive, pc->current_position, bcount.all);
-+			hwif->atapi_output_bytes(drive, pc->current_position,
-+						 bcount);
- 	} else {
- 		if (pc->bh != NULL)
--			idetape_input_buffers(drive, pc, bcount.all);
-+			idetape_input_buffers(drive, pc, bcount);
- 		else
- 			/* Read the current buffer */
--			HWIF(drive)->atapi_input_bytes(drive, pc->current_position, bcount.all);
-+			hwif->atapi_input_bytes(drive, pc->current_position,
-+						bcount);
- 	}
- 	/* Update the current position */
--	pc->actually_transferred += bcount.all;
--	pc->current_position += bcount.all;
-+	pc->actually_transferred += bcount;
-+	pc->current_position += bcount;
- #if IDETAPE_DEBUG_LOG
- 	if (tape->debug_level >= 2)
--		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
-+		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes "
-+				 "on that interrupt\n", pc->c[0], bcount);
- #endif
- 	/* And set the interrupt handler again */
- 	ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
-@@ -2078,28 +1384,28 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
- 	ide_hwif_t *hwif = drive->hwif;
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t *pc = tape->pc;
--	atapi_ireason_t ireason;
- 	int retries = 100;
- 	ide_startstop_t startstop;
-+	u8 ireason;
+ 	if (~vdev->via_config->flags & VIA_BAD_AST) {
+@@ -159,8 +152,10 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
  
- 	if (ide_wait_stat(&startstop,drive,DRQ_STAT,BUSY_STAT,WAIT_READY)) {
- 		printk(KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
- 		return startstop;
- 	}
--	ireason.all = hwif->INB(IDE_IREASON_REG);
--	while (retries-- && (!ireason.b.cod || ireason.b.io)) {
-+	ireason = hwif->INB(IDE_IREASON_REG);
-+	while (retries-- && ((ireason & CD) == 0 || (ireason & IO))) {
- 		printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while issuing "
- 				"a packet command, retrying\n");
- 		udelay(100);
--		ireason.all = hwif->INB(IDE_IREASON_REG);
-+		ireason = hwif->INB(IDE_IREASON_REG);
- 		if (retries == 0) {
- 			printk(KERN_ERR "ide-tape: (IO,CoD != (0,1) while "
- 					"issuing a packet command, ignoring\n");
--			ireason.b.cod = 1;
--			ireason.b.io = 0;
-+			ireason |= CD;
-+			ireason &= ~IO;
- 		}
- 	}
--	if (!ireason.b.cod || ireason.b.io) {
-+	if ((ireason & CD) == 0 || (ireason & IO)) {
- 		printk(KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing "
- 				"a packet command\n");
- 		return ide_do_reset(drive);
-@@ -2120,18 +1426,16 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
+ static void via_set_drive(ide_drive_t *drive, const u8 speed)
  {
- 	ide_hwif_t *hwif = drive->hwif;
- 	idetape_tape_t *tape = drive->driver_data;
--	atapi_bcount_t bcount;
- 	int dma_ok = 0;
-+	u16 bcount;
+-	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+-	struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev);
++	ide_hwif_t *hwif = drive->hwif;
++	ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
+ 	struct ide_timing t, p;
+ 	unsigned int T, UT;
  
--#if IDETAPE_DEBUG_BUGS
--	if (tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD &&
--	    pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
-+	if (tape->pc->c[0] == REQUEST_SENSE &&
-+	    pc->c[0] == REQUEST_SENSE) {
- 		printk(KERN_ERR "ide-tape: possible ide-tape.c bug - "
- 			"Two request sense in serial were issued\n");
- 	}
--#endif /* IDETAPE_DEBUG_BUGS */
+@@ -408,7 +403,7 @@ static int via_cable_override(struct pci_dev *pdev)
  
--	if (tape->failed_pc == NULL && pc->c[0] != IDETAPE_REQUEST_SENSE_CMD)
-+	if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE)
- 		tape->failed_pc = pc;
- 	/* Set the current packet command */
- 	tape->pc = pc;
-@@ -2144,7 +1448,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
- 		 *	filemark, or end of the media, for example).
- 		 */
- 		if (!test_bit(PC_ABORT, &pc->flags)) {
--			if (!(pc->c[0] == IDETAPE_TEST_UNIT_READY_CMD &&
-+			if (!(pc->c[0] == TEST_UNIT_READY &&
- 			      tape->sense_key == 2 && tape->asc == 4 &&
- 			     (tape->ascq == 1 || tape->ascq == 8))) {
- 				printk(KERN_ERR "ide-tape: %s: I/O error, "
-@@ -2170,7 +1474,7 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
- 	pc->actually_transferred = 0;
- 	pc->current_position = pc->buffer;
- 	/* Request to transfer the entire buffer at once */
--	bcount.all = pc->request_transfer;
-+	bcount = pc->request_transfer;
+ static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
+ {
+-	struct pci_dev *pdev = hwif->pci_dev;
++	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ 	struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
  
- 	if (test_and_clear_bit(PC_DMA_ERROR, &pc->flags)) {
- 		printk(KERN_WARNING "ide-tape: DMA disabled, "
-@@ -2180,17 +1484,14 @@ static ide_startstop_t idetape_issue_packet_command (ide_drive_t *drive, idetape
- 	if (test_bit(PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma)
- 		dma_ok = !hwif->dma_setup(drive);
+ 	if (via_cable_override(pdev))
+@@ -425,11 +420,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
+ 	hwif->set_pio_mode = &via_set_pio_mode;
+ 	hwif->set_dma_mode = &via_set_drive;
  
--	if (IDE_CONTROL_REG)
--		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
--	hwif->OUTB(dma_ok ? 1 : 0, IDE_FEATURE_REG);	/* Use PIO/DMA */
--	hwif->OUTB(bcount.b.high, IDE_BCOUNTH_REG);
--	hwif->OUTB(bcount.b.low, IDE_BCOUNTL_REG);
--	hwif->OUTB(drive->select.all, IDE_SELECT_REG);
-+	ide_pktcmd_tf_load(drive, IDE_TFLAG_NO_SELECT_MASK |
-+			   IDE_TFLAG_OUT_DEVICE, bcount, dma_ok);
+-	if (!hwif->dma_base)
+-		return;
+-
+-	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
+-		hwif->cbl = via82cxxx_cable_detect(hwif);
++	hwif->cable_detect = via82cxxx_cable_detect;
+ }
+ 
+ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+@@ -439,6 +430,7 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
+ 	.enablebits	= { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
+ 	.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST |
+ 			  IDE_HFLAG_PIO_NO_DOWNGRADE |
++			  IDE_HFLAG_ABUSE_SET_DMA_MODE |
+ 			  IDE_HFLAG_POST_SET_MODE |
+ 			  IDE_HFLAG_IO_32BIT |
+ 			  IDE_HFLAG_BOOTABLE,
+diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
+new file mode 100644
+index 0000000..65af584
+--- /dev/null
++++ b/drivers/ide/ppc/Makefile
+@@ -0,0 +1,3 @@
 +
- 	if (dma_ok)			/* Will begin DMA later */
- 		set_bit(PC_DMA_IN_PROGRESS, &pc->flags);
- 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
--		ide_set_handler(drive, &idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
--		hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
-+		ide_execute_command(drive, WIN_PACKETCMD, &idetape_transfer_pc,
-+				    IDETAPE_WAIT_CMD, NULL);
- 		return ide_started;
- 	} else {
- 		hwif->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG);
-@@ -2220,7 +1521,7 @@ static ide_startstop_t idetape_pc_callback (ide_drive_t *drive)
- static void idetape_create_mode_sense_cmd (idetape_pc_t *pc, u8 page_code)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_MODE_SENSE_CMD;
-+	pc->c[0] = MODE_SENSE;
- 	if (page_code != IDETAPE_BLOCK_DESCRIPTOR)
- 		pc->c[1] = 8;	/* DBD = 1 - Don't return block descriptors */
- 	pc->c[2] = page_code;
-@@ -2295,13 +1596,13 @@ static ide_startstop_t idetape_media_access_finished (ide_drive_t *drive)
- {
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t *pc = tape->pc;
--	atapi_status_t status;
-+	u8 stat;
++obj-$(CONFIG_BLK_DEV_IDE_PMAC)		+= pmac.o
++obj-$(CONFIG_BLK_DEV_MPC8xx_IDE)	+= mpc8xx.o
+diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
+index 5f0da35..06190b1 100644
+--- a/drivers/ide/ppc/mpc8xx.c
++++ b/drivers/ide/ppc/mpc8xx.c
+@@ -1,6 +1,4 @@
+ /*
+- *  linux/drivers/ide/ppc/ide-m8xx.c
+- *
+  *  Copyright (C) 2000, 2001 Wolfgang Denk, wd at denx.de
+  *  Modified for direct IDE interface
+  *	by Thomas Lange, thomas at corelatus.com
+@@ -838,3 +836,21 @@ void m8xx_ide_init(void)
+ 	ppc_ide_md.default_io_base      = m8xx_ide_default_io_base;
+ 	ppc_ide_md.ide_init_hwif        = m8xx_ide_init_hwif_ports;
+ }
++
++static int __init mpc8xx_ide_probe(void)
++{
++	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++
++#ifdef IDE0_BASE_OFFSET
++	idx[0] = 0;
++#ifdef IDE1_BASE_OFFSET
++	idx[1] = 1;
++#endif
++#endif
++
++	ide_device_add(idx, NULL);
++
++	return 0;
++}
++
++module_init(mpc8xx_ide_probe);
+diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
+index 7f7a598..12ac3bf 100644
+--- a/drivers/ide/ppc/pmac.c
++++ b/drivers/ide/ppc/pmac.c
+@@ -1,7 +1,6 @@
+ /*
+- * linux/drivers/ide/ppc/pmac.c
+- *
+  * Support for IDE interfaces on PowerMacs.
++ *
+  * These IDE interfaces are memory-mapped and have a DBDMA channel
+  * for doing DMA.
+  *
+@@ -413,7 +412,7 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
+  */
+ #define IDE_WAKEUP_DELAY	(1*HZ)
  
--	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
--	if (status.b.dsc) {
--		if (status.b.check) {
-+	stat = drive->hwif->INB(IDE_STATUS_REG);
-+	if (stat & SEEK_STAT) {
-+		if (stat & ERR_STAT) {
- 			/* Error detected */
--			if (pc->c[0] != IDETAPE_TEST_UNIT_READY_CMD)
-+			if (pc->c[0] != TEST_UNIT_READY)
- 				printk(KERN_ERR "ide-tape: %s: I/O error, ",
- 						tape->name);
- 			/* Retry operation */
-@@ -2358,8 +1659,8 @@ static ide_startstop_t idetape_rw_callback (ide_drive_t *drive)
- static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_READ_CMD;
--	put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
-+	pc->c[0] = READ_6;
-+	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
- 	pc->c[1] = 1;
- 	pc->callback = &idetape_rw_callback;
- 	pc->bh = bh;
-@@ -2376,7 +1677,7 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p
- 	struct idetape_bh *p = bh;
+-static void pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
++static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
+ static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
+ static void pmac_ide_selectproc(ide_drive_t *drive);
+ static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
+@@ -438,13 +437,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
+ 		if (data_port == pmac_ide[ix].regbase)
+ 			break;
  
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_READ_BUFFER_CMD;
-+	pc->c[0] = READ_BUFFER;
- 	pc->c[1] = IDETAPE_RETRIEVE_FAULTY_BLOCK;
- 	pc->c[7] = size >> 8;
- 	pc->c[8] = size & 0xff;
-@@ -2394,8 +1695,8 @@ static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *p
- static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh)
+-	if (ix >= MAX_HWIFS) {
+-		/* Probably a PCI interface... */
+-		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
+-			hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
+-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+-		return;
+-	}
++	if (ix >= MAX_HWIFS)
++		return;		/* not an IDE PMAC interface */
+ 
+ 	for (i = 0; i < 8; ++i)
+ 		hw->io_ports[i] = data_port + i * 0x10;
+@@ -833,38 +827,20 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	tl[0] = *timings;
+ 	tl[1] = *timings2;
+ 
+-	switch(speed) {
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+-		case XFER_UDMA_6:
+-		case XFER_UDMA_5:
+-		case XFER_UDMA_4:
+-		case XFER_UDMA_3:
+-		case XFER_UDMA_2:
+-		case XFER_UDMA_1:
+-		case XFER_UDMA_0:
+-			if (pmif->kind == controller_kl_ata4)
+-				ret = set_timings_udma_ata4(&tl[0], speed);
+-			else if (pmif->kind == controller_un_ata6
+-				 || pmif->kind == controller_k2_ata6)
+-				ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
+-			else if (pmif->kind == controller_sh_ata6)
+-				ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
+-			else
+-				ret = 1;
+-			break;
+-		case XFER_MW_DMA_2:
+-		case XFER_MW_DMA_1:
+-		case XFER_MW_DMA_0:
+-			set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
+-			break;
+-		case XFER_SW_DMA_2:
+-		case XFER_SW_DMA_1:
+-		case XFER_SW_DMA_0:
+-			return;
++	if (speed >= XFER_UDMA_0) {
++		if (pmif->kind == controller_kl_ata4)
++			ret = set_timings_udma_ata4(&tl[0], speed);
++		else if (pmif->kind == controller_un_ata6
++			 || pmif->kind == controller_k2_ata6)
++			ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
++		else if (pmif->kind == controller_sh_ata6)
++			ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
++		else
++			ret = -1;
++	} else
++		set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+-		default:
+-			ret = 1;
+-	}
+ 	if (ret)
+ 		return;
+ 
+@@ -1027,6 +1003,17 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
+ 	return 0;
+ }
+ 
++static const struct ide_port_info pmac_port_info = {
++	.chipset		= ide_pmac,
++	.host_flags		= IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
++				  IDE_HFLAG_PIO_NO_DOWNGRADE |
++				  IDE_HFLAG_POST_SET_MODE |
++				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
++				  IDE_HFLAG_UNMASK_IRQS,
++	.pio_mask		= ATA_PIO4,
++	.mwdma_mask		= ATA_MWDMA2,
++};
++
+ /*
+  * Setup, register & probe an IDE channel driven by this driver, this is
+  * called by one of the 2 probe functions (macio or PCI). Note that a channel
+@@ -1034,30 +1021,34 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
+  * (it is kept in 2.4). This introduce an interface numbering change on some
+  * rare machines unfortunately, but it's better this way.
+  */
+-static int
+-pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
++static int __devinit
++pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
  {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_WRITE_CMD;
--	put_unaligned(htonl(length), (unsigned int *) &pc->c[1]);
-+	pc->c[0] = WRITE_6;
-+	put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]);
- 	pc->c[1] = 1;
- 	pc->callback = &idetape_rw_callback;
- 	set_bit(PC_WRITING, &pc->flags);
-@@ -2417,15 +1718,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t *pc = NULL;
- 	struct request *postponed_rq = tape->postponed_rq;
--	atapi_status_t status;
-+	u8 stat;
+ 	struct device_node *np = pmif->node;
+ 	const int *bidp;
+ 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+-	hw_regs_t hw;
++	struct ide_port_info d = pmac_port_info;
+ 
+ 	pmif->cable_80 = 0;
+ 	pmif->broken_dma = pmif->broken_dma_warn = 0;
+-	if (of_device_is_compatible(np, "shasta-ata"))
++	if (of_device_is_compatible(np, "shasta-ata")) {
+ 		pmif->kind = controller_sh_ata6;
+-	else if (of_device_is_compatible(np, "kauai-ata"))
++		d.udma_mask = ATA_UDMA6;
++	} else if (of_device_is_compatible(np, "kauai-ata")) {
+ 		pmif->kind = controller_un_ata6;
+-	else if (of_device_is_compatible(np, "K2-UATA"))
++		d.udma_mask = ATA_UDMA5;
++	} else if (of_device_is_compatible(np, "K2-UATA")) {
+ 		pmif->kind = controller_k2_ata6;
+-	else if (of_device_is_compatible(np, "keylargo-ata")) {
+-		if (strcmp(np->name, "ata-4") == 0)
++		d.udma_mask = ATA_UDMA5;
++	} else if (of_device_is_compatible(np, "keylargo-ata")) {
++		if (strcmp(np->name, "ata-4") == 0) {
+ 			pmif->kind = controller_kl_ata4;
+-		else
++			d.udma_mask = ATA_UDMA4;
++		} else
+ 			pmif->kind = controller_kl_ata3;
+-	} else if (of_device_is_compatible(np, "heathrow-ata"))
++	} else if (of_device_is_compatible(np, "heathrow-ata")) {
+ 		pmif->kind = controller_heathrow;
+-	else {
++	} else {
+ 		pmif->kind = controller_ohare;
+ 		pmif->broken_dma = 1;
+ 	}
+@@ -1126,21 +1117,10 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
+ 	/* Tell common code _not_ to mess with resources */
+ 	hwif->mmio = 1;
+ 	hwif->hwif_data = pmif;
+-	memset(&hw, 0, sizeof(hw));
+-	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, &hwif->irq);
+-	memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
+-	hwif->chipset = ide_pmac;
+-	hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
++	ide_init_port_hw(hwif, hw);
++	hwif->noprobe = pmif->mediabay;
+ 	hwif->hold = pmif->mediabay;
+ 	hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
+-	hwif->drives[0].unmask = 1;
+-	hwif->drives[1].unmask = 1;
+-	hwif->drives[0].autotune = IDE_TUNE_AUTO;
+-	hwif->drives[1].autotune = IDE_TUNE_AUTO;
+-	hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+-			   IDE_HFLAG_PIO_NO_DOWNGRADE |
+-			   IDE_HFLAG_POST_SET_MODE;
+-	hwif->pio_mask = ATA_PIO4;
+ 	hwif->set_pio_mode = pmac_ide_set_pio_mode;
+ 	if (pmif->kind == controller_un_ata6
+ 	    || pmif->kind == controller_k2_ata6
+@@ -1159,17 +1139,17 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
+ 		hwif->noprobe = 0;
+ #endif /* CONFIG_PMAC_MEDIABAY */
+ 
+-	hwif->sg_max_nents = MAX_DCMDS;
+-
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
++	if (pmif->cable_80 == 0)
++		d.udma_mask &= ATA_UDMA2;
+ 	/* has a DBDMA controller channel */
+-	if (pmif->dma_regs)
+-		pmac_ide_setup_dma(pmif, hwif);
+-#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
++	if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0)
++#endif
++		d.udma_mask = d.mwdma_mask = 0;
  
- #if IDETAPE_DEBUG_LOG
--#if 0
--	if (tape->debug_level >= 5)
--		printk(KERN_INFO "ide-tape:  %d, "
--			"dev: %s, cmd: %ld, errors: %d\n",
--			 rq->rq_disk->disk_name, rq->cmd[0], rq->errors);
--#endif
- 	if (tape->debug_level >= 2)
- 		printk(KERN_INFO "ide-tape: sector: %ld, "
- 			"nr_sectors: %ld, current_nr_sectors: %d\n",
-@@ -2446,10 +1741,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 	 *	Retry a failed packet command
- 	 */
- 	if (tape->failed_pc != NULL &&
--	    tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
-+	    tape->pc->c[0] == REQUEST_SENSE) {
- 		return idetape_issue_packet_command(drive, tape->failed_pc);
- 	}
--#if IDETAPE_DEBUG_BUGS
- 	if (postponed_rq != NULL)
- 		if (rq != postponed_rq) {
- 			printk(KERN_ERR "ide-tape: ide-tape.c bug - "
-@@ -2457,7 +1751,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 			idetape_end_request(drive, 0, 0);
- 			return ide_stopped;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
+ 	idx[0] = hwif->index;
  
- 	tape->postponed_rq = NULL;
+-	ide_device_add(idx);
++	ide_device_add(idx, &d);
  
-@@ -2465,7 +1758,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 	 * If the tape is still busy, postpone our request and service
- 	 * the other device meanwhile.
- 	 */
--	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
-+	stat = drive->hwif->INB(IDE_STATUS_REG);
+ 	return 0;
+ }
+@@ -1186,6 +1166,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ 	ide_hwif_t *hwif;
+ 	pmac_ide_hwif_t *pmif;
+ 	int i, rc;
++	hw_regs_t hw;
  
- 	if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
- 		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
-@@ -2481,7 +1774,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 		tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time);
- 	calculate_speeds(drive);
- 	if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) &&
--	    !status.b.dsc) {
-+	    (stat & SEEK_STAT) == 0) {
- 		if (postponed_rq == NULL) {
- 			tape->dsc_polling_start = jiffies;
- 			tape->dsc_polling_frequency = tape->best_dsc_rw_frequency;
-@@ -2502,9 +1795,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 	}
- 	if (rq->cmd[0] & REQ_IDETAPE_READ) {
- 		tape->buffer_head++;
--#if USE_IOTRACE
--		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
--#endif
- 		tape->postpone_cnt = 0;
- 		pc = idetape_next_pc_storage(drive);
- 		idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
-@@ -2512,9 +1802,6 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive,
- 	}
- 	if (rq->cmd[0] & REQ_IDETAPE_WRITE) {
- 		tape->buffer_head++;
--#if USE_IOTRACE
--		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
--#endif
- 		tape->postpone_cnt = 0;
- 		pc = idetape_next_pc_storage(drive);
- 		idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special);
-@@ -2650,13 +1937,11 @@ static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *
- 	int ret = 0;
+ 	i = 0;
+ 	while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
+@@ -1227,8 +1208,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ 	base = ioremap(macio_resource_start(mdev, 0), 0x400);
+ 	regbase = (unsigned long) base;
  
- 	while (n) {
--#if IDETAPE_DEBUG_BUGS
- 		if (bh == NULL) {
- 			printk(KERN_ERR "ide-tape: bh == NULL in "
- 				"idetape_copy_stage_from_user\n");
- 			return 1;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
- 		if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
- 			ret = 1;
-@@ -2680,13 +1965,11 @@ static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, i
- 	int ret = 0;
+-	hwif->pci_dev = mdev->bus->pdev;
+-	hwif->gendev.parent = &mdev->ofdev.dev;
++	hwif->dev = &mdev->bus->pdev->dev;
  
- 	while (n) {
--#if IDETAPE_DEBUG_BUGS
- 		if (bh == NULL) {
- 			printk(KERN_ERR "ide-tape: bh == NULL in "
- 				"idetape_copy_stage_to_user\n");
- 			return 1;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		count = min(tape->b_count, n);
- 		if  (copy_to_user(buf, tape->b_data, count))
- 			ret = 1;
-@@ -2766,12 +2049,10 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
- 	DECLARE_COMPLETION_ONSTACK(wait);
- 	idetape_tape_t *tape = drive->driver_data;
+ 	pmif->mdev = mdev;
+ 	pmif->node = mdev->ofdev.node;
+@@ -1246,17 +1226,22 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+ 	dev_set_drvdata(&mdev->ofdev.dev, hwif);
  
--#if IDETAPE_DEBUG_BUGS
- 	if (rq == NULL || !blk_special_request(rq)) {
- 		printk (KERN_ERR "ide-tape: bug: Trying to sleep on non-valid request\n");
- 		return;
+-	rc = pmac_ide_setup_device(pmif, hwif);
++	memset(&hw, 0, sizeof(hw));
++	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
++	hw.irq = irq;
++	hw.dev = &mdev->ofdev.dev;
++
++	rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ 	if (rc != 0) {
+ 		/* The inteface is released to the common IDE layer */
+ 		dev_set_drvdata(&mdev->ofdev.dev, NULL);
+ 		iounmap(base);
+-		if (pmif->dma_regs)
++		if (pmif->dma_regs) {
+ 			iounmap(pmif->dma_regs);
++			macio_release_resource(mdev, 1);
++		}
+ 		memset(pmif, 0, sizeof(*pmif));
+ 		macio_release_resource(mdev, 0);
+-		if (pmif->dma_regs)
+-			macio_release_resource(mdev, 1);
  	}
--#endif /* IDETAPE_DEBUG_BUGS */
- 	rq->end_io_data = &wait;
- 	rq->end_io = blk_end_sync_rq;
- 	spin_unlock_irq(&tape->spinlock);
-@@ -2831,7 +2112,7 @@ static ide_startstop_t idetape_read_position_callback (ide_drive_t *drive)
- static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD;
-+	pc->c[0] = WRITE_FILEMARKS;
- 	pc->c[4] = write_filemark;
- 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
- 	pc->callback = &idetape_pc_callback;
-@@ -2840,7 +2121,7 @@ static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t
- static void idetape_create_test_unit_ready_cmd(idetape_pc_t *pc)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_TEST_UNIT_READY_CMD;
-+	pc->c[0] = TEST_UNIT_READY;
- 	pc->callback = &idetape_pc_callback;
- }
- 
-@@ -2878,7 +2159,7 @@ static int __idetape_queue_pc_tail (ide_drive_t *drive, idetape_pc_t *pc)
- static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD;
-+	pc->c[0] = START_STOP;
- 	pc->c[4] = cmd;
- 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
- 	pc->callback = &idetape_pc_callback;
-@@ -2935,7 +2216,7 @@ static int idetape_flush_tape_buffers (ide_drive_t *drive)
- static void idetape_create_read_position_cmd (idetape_pc_t *pc)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_READ_POSITION_CMD;
-+	pc->c[0] = READ_POSITION;
- 	pc->request_transfer = 20;
- 	pc->callback = &idetape_read_position_callback;
- }
-@@ -2961,9 +2242,9 @@ static int idetape_read_position (ide_drive_t *drive)
- static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_LOCATE_CMD;
-+	pc->c[0] = POSITION_TO_ELEMENT;
- 	pc->c[1] = 2;
--	put_unaligned(htonl(block), (unsigned int *) &pc->c[3]);
-+	put_unaligned(cpu_to_be32(block), (unsigned int *) &pc->c[3]);
- 	pc->c[8] = partition;
- 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
- 	pc->callback = &idetape_pc_callback;
-@@ -2973,11 +2254,12 @@ static int idetape_create_prevent_cmd (ide_drive_t *drive, idetape_pc_t *pc, int
- {
- 	idetape_tape_t *tape = drive->driver_data;
  
--	if (!tape->capabilities.lock)
-+	/* device supports locking according to capabilities page */
-+	if (!(tape->caps[6] & 0x01))
- 		return 0;
+ 	return rc;
+@@ -1305,6 +1290,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 	void __iomem *base;
+ 	unsigned long rbase, rlen;
+ 	int i, rc;
++	hw_regs_t hw;
  
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_PREVENT_CMD;
-+	pc->c[0] = ALLOW_MEDIUM_REMOVAL;
- 	pc->c[4] = prevent;
- 	pc->callback = &idetape_pc_callback;
- 	return 1;
-@@ -3086,12 +2368,10 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, struct
- 	if (tape->debug_level >= 2)
- 		printk(KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd);
- #endif /* IDETAPE_DEBUG_LOG */
--#if IDETAPE_DEBUG_BUGS
- 	if (idetape_pipeline_active(tape)) {
- 		printk(KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n");
- 		return (0);
+ 	np = pci_device_to_OF_node(pdev);
+ 	if (np == NULL) {
+@@ -1337,8 +1323,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 		return -ENXIO;
  	}
--#endif /* IDETAPE_DEBUG_BUGS */	
  
- 	idetape_init_rq(&rq, cmd);
- 	rq.rq_disk = tape->disk;
-@@ -3122,7 +2402,7 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
- 		return;
- 	if (!idetape_pipeline_active(tape)) {
- 		set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags);
--		idetape_active_next_stage(drive);
-+		idetape_activate_next_stage(drive);
- 		(void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end);
+-	hwif->pci_dev = pdev;
+-	hwif->gendev.parent = &pdev->dev;
++	hwif->dev = &pdev->dev;
+ 	pmif->mdev = NULL;
+ 	pmif->node = np;
+ 
+@@ -1355,7 +1340,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
+ 
+ 	pci_set_drvdata(pdev, hwif);
+ 
+-	rc = pmac_ide_setup_device(pmif, hwif);
++	memset(&hw, 0, sizeof(hw));
++	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
++	hw.irq = pdev->irq;
++	hw.dev = &pdev->dev;
++
++	rc = pmac_ide_setup_device(pmif, hwif, &hw);
+ 	if (rc != 0) {
+ 		/* The inteface is released to the common IDE layer */
+ 		pci_set_drvdata(pdev, NULL);
+@@ -1553,11 +1543,10 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
  	}
+ 
+ 	printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
+- use_pio_instead:
+-	pci_unmap_sg(hwif->pci_dev,
+-		     hwif->sg_table,
+-		     hwif->sg_nents,
+-		     hwif->sg_dma_direction);
++
++use_pio_instead:
++	ide_destroy_dmatable(drive);
++
+ 	return 0; /* revert to PIO for this request */
  }
-@@ -3130,7 +2410,7 @@ static void idetape_insert_pipeline_into_queue (ide_drive_t *drive)
- static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
+ 
+@@ -1566,12 +1555,9 @@ static void
+ pmac_ide_destroy_dmatable (ide_drive_t *drive)
  {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_INQUIRY_CMD;
-+	pc->c[0] = INQUIRY;
- 	pc->c[4] = pc->request_transfer = 254;
- 	pc->callback = &idetape_pc_callback;
+ 	ide_hwif_t *hwif = drive->hwif;
+-	struct pci_dev *dev = HWIF(drive)->pci_dev;
+-	struct scatterlist *sg = hwif->sg_table;
+-	int nents = hwif->sg_nents;
+ 
+-	if (nents) {
+-		pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction);
++	if (hwif->sg_nents) {
++		ide_destroy_dmatable(drive);
+ 		hwif->sg_nents = 0;
+ 	}
  }
-@@ -3138,28 +2418,15 @@ static void idetape_create_inquiry_cmd (idetape_pc_t *pc)
- static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_REWIND_CMD;
-+	pc->c[0] = REZERO_UNIT;
- 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
- 	pc->callback = &idetape_pc_callback;
+@@ -1721,11 +1707,7 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
+ 	return 1;
  }
  
--#if 0
--static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length)
+-static void pmac_ide_dma_host_off(ide_drive_t *drive)
 -{
--	idetape_init_pc(pc);
--	set_bit(PC_WRITING, &pc->flags);
--	pc->c[0] = IDETAPE_MODE_SELECT_CMD;
--	pc->c[1] = 0x10;
--	put_unaligned(htons(length), (unsigned short *) &pc->c[3]);
--	pc->request_transfer = 255;
--	pc->callback = &idetape_pc_callback;
 -}
--#endif
 -
- static void idetape_create_erase_cmd (idetape_pc_t *pc)
- {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_ERASE_CMD;
-+	pc->c[0] = ERASE;
- 	pc->c[1] = 1;
- 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
- 	pc->callback = &idetape_pc_callback;
-@@ -3168,8 +2435,8 @@ static void idetape_create_erase_cmd (idetape_pc_t *pc)
- static void idetape_create_space_cmd (idetape_pc_t *pc,int count, u8 cmd)
+-static void pmac_ide_dma_host_on(ide_drive_t *drive)
++static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
  {
- 	idetape_init_pc(pc);
--	pc->c[0] = IDETAPE_SPACE_CMD;
--	put_unaligned(htonl(count), (unsigned int *) &pc->c[1]);
-+	pc->c[0] = SPACE;
-+	put_unaligned(cpu_to_be32(count), (unsigned int *) &pc->c[1]);
- 	pc->c[1] = cmd;
- 	set_bit(PC_WAIT_FOR_DSC, &pc->flags);
- 	pc->callback = &idetape_pc_callback;
-@@ -3241,9 +2508,6 @@ static int idetape_add_chrdev_write_request (ide_drive_t *drive, int blocks)
- 	idetape_switch_buffers(tape, new_stage);
- 	idetape_add_stage_tail(drive, new_stage);
- 	tape->pipeline_head++;
--#if USE_IOTRACE
--	IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
--#endif
- 	calculate_speeds(drive);
+ }
  
- 	/*
-@@ -3292,8 +2556,7 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
- 	idetape_tape_t *tape = drive->driver_data;
- 	int blocks, min;
- 	struct idetape_bh *bh;
--	
--#if IDETAPE_DEBUG_BUGS
+@@ -1748,64 +1730,44 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
+  * Allocate the data structures needed for using DMA with an interface
+  * and fill the proper list of functions pointers
+  */
+-static void __init 
+-pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
++static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
+ {
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
 +
- 	if (tape->chrdev_direction != idetape_direction_write) {
- 		printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline, but we are not writing.\n");
- 		return;
-@@ -3302,7 +2565,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
- 		printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
- 		tape->merge_stage_size = tape->stage_size;
- 	}
--#endif /* IDETAPE_DEBUG_BUGS */
- 	if (tape->merge_stage_size) {
- 		blocks = tape->merge_stage_size / tape->tape_block_size;
- 		if (tape->merge_stage_size % tape->tape_block_size) {
-@@ -3347,7 +2609,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
- 	 *	 can be totally different on the next backup).
+ 	/* We won't need pci_dev if we switch to generic consistent
+ 	 * DMA routines ...
  	 */
- 	tape->max_stages = tape->min_pipeline;
--#if IDETAPE_DEBUG_BUGS
- 	if (tape->first_stage != NULL ||
- 	    tape->next_stage != NULL ||
- 	    tape->last_stage != NULL ||
-@@ -3358,7 +2619,6 @@ static void idetape_empty_write_pipeline (ide_drive_t *drive)
- 			tape->first_stage, tape->next_stage,
- 			tape->last_stage, tape->nr_stages);
+-	if (hwif->pci_dev == NULL)
+-		return;
++	if (dev == NULL)
++		return -ENODEV;
+ 	/*
+ 	 * Allocate space for the DBDMA commands.
+ 	 * The +2 is +1 for the stop command and +1 to allow for
+ 	 * aligning the start address to a multiple of 16 bytes.
+ 	 */
+ 	pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
+-		hwif->pci_dev,
++		dev,
+ 		(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
+ 		&hwif->dmatable_dma);
+ 	if (pmif->dma_table_cpu == NULL) {
+ 		printk(KERN_ERR "%s: unable to allocate DMA command list\n",
+ 		       hwif->name);
+-		return;
++		return -ENOMEM;
  	}
--#endif /* IDETAPE_DEBUG_BUGS */
+ 
+-	hwif->dma_off_quietly = &ide_dma_off_quietly;
+-	hwif->ide_dma_on = &__ide_dma_on;
++	hwif->sg_max_nents = MAX_DCMDS;
++
++	hwif->dma_host_set = &pmac_ide_dma_host_set;
+ 	hwif->dma_setup = &pmac_ide_dma_setup;
+ 	hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
+ 	hwif->dma_start = &pmac_ide_dma_start;
+ 	hwif->ide_dma_end = &pmac_ide_dma_end;
+ 	hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
+-	hwif->dma_host_off = &pmac_ide_dma_host_off;
+-	hwif->dma_host_on = &pmac_ide_dma_host_on;
+ 	hwif->dma_timeout = &ide_dma_timeout;
+ 	hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
+ 
+-	switch(pmif->kind) {
+-		case controller_sh_ata6:
+-			hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07;
+-			hwif->mwdma_mask = 0x07;
+-			hwif->swdma_mask = 0x00;
+-			break;
+-		case controller_un_ata6:
+-		case controller_k2_ata6:
+-			hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;
+-			hwif->mwdma_mask = 0x07;
+-			hwif->swdma_mask = 0x00;
+-			break;
+-		case controller_kl_ata4:
+-			hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07;
+-			hwif->mwdma_mask = 0x07;
+-			hwif->swdma_mask = 0x00;
+-			break;
+-		default:
+-			hwif->ultra_mask = 0x00;
+-			hwif->mwdma_mask = 0x07;
+-			hwif->swdma_mask = 0x00;
+-			break;
+-	}
++	return 0;
  }
  
- static void idetape_restart_speed_control (ide_drive_t *drive)
-@@ -3381,7 +2641,7 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
- 	idetape_stage_t *new_stage;
- 	struct request rq;
- 	int bytes_read;
--	int blocks = tape->capabilities.ctl;
-+	u16 blocks = *(u16 *)&tape->caps[12];
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
++
++module_init(pmac_ide_probe);
+diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
+index d2cd5a3..634e3f6 100644
+--- a/drivers/ide/setup-pci.c
++++ b/drivers/ide/setup-pci.c
+@@ -1,9 +1,8 @@
+ /*
+- *  linux/drivers/ide/setup-pci.c		Version 1.10	2002/08/19
++ *  Copyright (C) 1998-2000  Andre Hedrick <andre at linux-ide.org>
++ *  Copyright (C) 1995-1998  Mark Lord
++ *  Copyright (C)      2007  Bartlomiej Zolnierkiewicz
+  *
+- *  Copyright (c) 1998-2000  Andre Hedrick <andre at linux-ide.org>
+- *
+- *  Copyright (c) 1995-1998  Mark Lord
+  *  May be copied or modified under the terms of the GNU General Public License
+  */
  
- 	/* Initialize read operation */
- 	if (tape->chrdev_direction != idetape_direction_read) {
-@@ -3389,12 +2649,10 @@ static int idetape_initiate_read (ide_drive_t *drive, int max_stages)
- 			idetape_empty_write_pipeline(drive);
- 			idetape_flush_tape_buffers(drive);
- 		}
--#if IDETAPE_DEBUG_BUGS
- 		if (tape->merge_stage || tape->merge_stage_size) {
- 			printk (KERN_ERR "ide-tape: merge_stage_size should be 0 now\n");
- 			tape->merge_stage_size = 0;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
- 			return -ENOMEM;
- 		tape->chrdev_direction = idetape_direction_read;
-@@ -3493,17 +2751,12 @@ static int idetape_add_chrdev_read_request (ide_drive_t *drive,int blocks)
- 		idetape_remove_stage_head(drive);
- 		spin_unlock_irqrestore(&tape->spinlock, flags);
- 		tape->pipeline_head++;
--#if USE_IOTRACE
--		IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor);
--#endif
- 		calculate_speeds(drive);
- 	}
--#if IDETAPE_DEBUG_BUGS
- 	if (bytes_read > blocks * tape->tape_block_size) {
- 		printk(KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
- 		bytes_read = blocks * tape->tape_block_size;
- 	}
--#endif /* IDETAPE_DEBUG_BUGS */
- 	return (bytes_read);
+@@ -140,6 +139,16 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
  }
  
-@@ -3587,16 +2840,21 @@ static int idetape_rewind_tape (ide_drive_t *drive)
- static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
++static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
++{
++	u8 dma_stat = inb(dma_base + 2);
++
++	outb(dma_stat & 0x60, dma_base + 2);
++	dma_stat = inb(dma_base + 2);
++	if (dma_stat & 0x80)
++		printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
++}
++
+ /**
+  *	ide_get_or_set_dma_base		-	setup BMIBA
+  *	@d: IDE port info
+@@ -152,8 +161,9 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
+ 
+ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
  {
- 	idetape_tape_t *tape = drive->driver_data;
--	idetape_config_t config;
- 	void __user *argp = (void __user *)arg;
+-	unsigned long	dma_base = 0;
+-	struct pci_dev	*dev = hwif->pci_dev;
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	unsigned long dma_base = 0;
++	u8 dma_stat = 0;
  
-+	struct idetape_config {
-+		int dsc_rw_frequency;
-+		int dsc_media_access_frequency;
-+		int nr_stages;
-+	} config;
-+
- #if IDETAPE_DEBUG_LOG	
- 	if (tape->debug_level >= 4)
- 		printk(KERN_INFO "ide-tape: Reached idetape_blkdev_ioctl\n");
- #endif /* IDETAPE_DEBUG_LOG */
- 	switch (cmd) {
- 		case 0x0340:
--			if (copy_from_user(&config, argp, sizeof (idetape_config_t)))
-+			if (copy_from_user(&config, argp, sizeof(config)))
- 				return -EFAULT;
- 			tape->best_dsc_rw_frequency = config.dsc_rw_frequency;
- 			tape->max_stages = config.nr_stages;
-@@ -3604,7 +2862,7 @@ static int idetape_blkdev_ioctl(ide_drive_t *drive, unsigned int cmd, unsigned l
- 		case 0x0350:
- 			config.dsc_rw_frequency = (int) tape->best_dsc_rw_frequency;
- 			config.nr_stages = tape->max_stages; 
--			if (copy_to_user(argp, &config, sizeof (idetape_config_t)))
-+			if (copy_to_user(argp, &config, sizeof(config)))
- 				return -EFAULT;
- 			break;
- 		default:
-@@ -3628,11 +2886,12 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
- 	idetape_pc_t pc;
- 	unsigned long flags;
- 	int retval,count=0;
-+	int sprev = !!(tape->caps[4] & 0x20);
+ 	if (hwif->mmio)
+ 		return hwif->dma_base;
+@@ -165,57 +175,39 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_
  
- 	if (mt_count == 0)
- 		return 0;
- 	if (MTBSF == mt_op || MTBSFM == mt_op) {
--		if (!tape->capabilities.sprev)
-+		if (!sprev)
- 			return -EIO;
- 		mt_count = - mt_count;
- 	}
-@@ -3686,7 +2945,7 @@ static int idetape_space_over_filemarks (ide_drive_t *drive,short mt_op,int mt_c
- 			return (idetape_queue_pc_tail(drive, &pc));
- 		case MTFSFM:
- 		case MTBSFM:
--			if (!tape->capabilities.sprev)
-+			if (!sprev)
- 				return (-EIO);
- 			retval = idetape_space_over_filemarks(drive, MTFSF, mt_count-count);
- 			if (retval) return (retval);
-@@ -3723,6 +2982,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
- 	ide_drive_t *drive = tape->drive;
- 	ssize_t bytes_read,temp, actually_read = 0, rc;
- 	ssize_t ret = 0;
-+	u16 ctl = *(u16 *)&tape->caps[12];
+ 		dma_base = pci_resource_start(dev, baridx);
  
- #if IDETAPE_DEBUG_LOG
- 	if (tape->debug_level >= 3)
-@@ -3748,7 +3008,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
- 		count -= actually_read;
- 	}
- 	while (count >= tape->stage_size) {
--		bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
-+		bytes_read = idetape_add_chrdev_read_request(drive, ctl);
- 		if (bytes_read <= 0)
- 			goto finish;
- 		if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
-@@ -3758,7 +3018,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
- 		actually_read += bytes_read;
+-		if (dma_base == 0)
++		if (dma_base == 0) {
+ 			printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
++			return 0;
++		}
  	}
- 	if (count) {
--		bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
-+		bytes_read = idetape_add_chrdev_read_request(drive, ctl);
- 		if (bytes_read <= 0)
- 			goto finish;
- 		temp = min((unsigned long)count, (unsigned long)bytes_read);
-@@ -3787,6 +3047,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
- 	ide_drive_t *drive = tape->drive;
- 	ssize_t actually_written = 0;
- 	ssize_t ret = 0;
-+	u16 ctl = *(u16 *)&tape->caps[12];
  
- 	/* The drive is write protected. */
- 	if (tape->write_prot)
-@@ -3802,13 +3063,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
- 	if (tape->chrdev_direction != idetape_direction_write) {
- 		if (tape->chrdev_direction == idetape_direction_read)
- 			idetape_discard_read_pipeline(drive, 1);
--#if IDETAPE_DEBUG_BUGS
- 		if (tape->merge_stage || tape->merge_stage_size) {
- 			printk(KERN_ERR "ide-tape: merge_stage_size "
- 				"should be 0 now\n");
- 			tape->merge_stage_size = 0;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL)
- 			return -ENOMEM;
- 		tape->chrdev_direction = idetape_direction_write;
-@@ -3836,12 +3095,10 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
- 	if (tape->restart_speed_control_req)
- 		idetape_restart_speed_control(drive);
- 	if (tape->merge_stage_size) {
--#if IDETAPE_DEBUG_BUGS
- 		if (tape->merge_stage_size >= tape->stage_size) {
- 			printk(KERN_ERR "ide-tape: bug: merge buffer too big\n");
- 			tape->merge_stage_size = 0;
- 		}
--#endif /* IDETAPE_DEBUG_BUGS */
- 		actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
- 		if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
- 				ret = -EFAULT;
-@@ -3852,7 +3109,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
- 		if (tape->merge_stage_size == tape->stage_size) {
- 			ssize_t retval;
- 			tape->merge_stage_size = 0;
--			retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
-+			retval = idetape_add_chrdev_write_request(drive, ctl);
- 			if (retval <= 0)
- 				return (retval);
- 		}
-@@ -3863,7 +3120,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
- 			ret = -EFAULT;
- 		buf += tape->stage_size;
- 		count -= tape->stage_size;
--		retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
-+		retval = idetape_add_chrdev_write_request(drive, ctl);
- 		actually_written += tape->stage_size;
- 		if (retval <= 0)
- 			return (retval);
-@@ -3891,69 +3148,20 @@ static int idetape_write_filemark (ide_drive_t *drive)
+-	if ((d->host_flags & IDE_HFLAG_CS5520) == 0 && dma_base) {
+-		u8 simplex_stat = 0;
+-		dma_base += hwif->channel ? 8 : 0;
+-
+-		switch(dev->device) {
+-			case PCI_DEVICE_ID_AL_M5219:
+-			case PCI_DEVICE_ID_AL_M5229:
+-			case PCI_DEVICE_ID_AMD_VIPER_7409:
+-			case PCI_DEVICE_ID_CMD_643:
+-			case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
+-			case PCI_DEVICE_ID_REVOLUTION:
+-				simplex_stat = inb(dma_base + 2);
+-				outb(simplex_stat & 0x60, dma_base + 2);
+-				simplex_stat = inb(dma_base + 2);
+-				if (simplex_stat & 0x80) {
+-					printk(KERN_INFO "%s: simplex device: "
+-							 "DMA forced\n",
+-							 d->name);
+-				}
+-				break;
+-			default:
+-				/*
+-				 * If the device claims "simplex" DMA,
+-				 * this means only one of the two interfaces
+-				 * can be trusted with DMA at any point in time.
+-				 * So we should enable DMA only on one of the
+-				 * two interfaces.
+-				 */
+-				simplex_stat = hwif->INB(dma_base + 2);
+-				if (simplex_stat & 0x80) {
+-					/* simplex device? */
+-/*
+- *	At this point we haven't probed the drives so we can't make the
+- *	appropriate decision. Really we should defer this problem
+- *	until we tune the drive then try to grab DMA ownership if we want
+- *	to be the DMA end. This has to be become dynamic to handle hot
+- *	plug.
+- */
+-					if (hwif->mate && hwif->mate->dma_base) {
+-						printk(KERN_INFO "%s: simplex device: "
+-								 "DMA disabled\n",
+-								 d->name);
+-						dma_base = 0;
+-					}
+-				}
+-		}
++	if (hwif->channel)
++		dma_base += 8;
++
++	if (d->host_flags & IDE_HFLAG_CS5520)
++		goto out;
++
++	if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
++		ide_pci_clear_simplex(dma_base, d->name);
++		goto out;
+ 	}
++
++	/*
++	 * If the device claims "simplex" DMA, this means that only one of
++	 * the two interfaces can be trusted with DMA at any point in time
++	 * (so we should enable DMA only on one of the two interfaces).
++	 *
++	 * FIXME: At this point we haven't probed the drives so we can't make
++	 * the appropriate decision.  Really we should defer this problem until
++	 * we tune the drive then try to grab DMA ownership if we want to be
++	 * the DMA end.  This has to be become dynamic to handle hot-plug.
++	 */
++	dma_stat = hwif->INB(dma_base + 2);
++	if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
++		printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
++		dma_base = 0;
++	}
++out:
+ 	return dma_base;
  }
- 
- /*
-- *	idetape_mtioctop is called from idetape_chrdev_ioctl when
-- *	the general mtio MTIOCTOP ioctl is requested.
-- *
-- *	We currently support the following mtio.h operations:
-- *
-- *	MTFSF	-	Space over mt_count filemarks in the positive direction.
-- *			The tape is positioned after the last spaced filemark.
-- *
-- *	MTFSFM	-	Same as MTFSF, but the tape is positioned before the
-- *			last filemark.
-- *
-- *	MTBSF	-	Steps background over mt_count filemarks, tape is
-- *			positioned before the last filemark.
-+ * Called from idetape_chrdev_ioctl when the general mtio MTIOCTOP ioctl is
-+ * requested.
-  *
-- *	MTBSFM	-	Like MTBSF, only tape is positioned after the last filemark.
-+ * Note: MTBSF and MTBSFM are not supported when the tape doesn't support
-+ * spacing over filemarks in the reverse direction. In this case, MTFSFM is also
-+ * usually not supported (it is supported in the rare case in which we crossed
-+ * the filemark during our read-ahead pipelined operation mode).
-  *
-- *	Note:
-+ * The following commands are currently not supported:
+ #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
+@@ -236,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
+  *	@d: IDE port info
   *
-- *		MTBSF and MTBSFM are not supported when the tape doesn't
-- *		support spacing over filemarks in the reverse direction.
-- *		In this case, MTFSFM is also usually not supported (it is
-- *		supported in the rare case in which we crossed the filemark
-- *		during our read-ahead pipelined operation mode).
-- *		
-- *	MTWEOF	-	Writes mt_count filemarks. Tape is positioned after
-- *			the last written filemark.
-- *
-- *	MTREW	-	Rewinds tape.
-- *
-- *	MTLOAD	-	Loads the tape.
-- *
-- *	MTOFFL	-	Puts the tape drive "Offline": Rewinds the tape and
-- *	MTUNLOAD	prevents further access until the media is replaced.
-- *
-- *	MTNOP	-	Flushes tape buffers.
-- *
-- *	MTRETEN	-	Retension media. This typically consists of one end
-- *			to end pass on the media.
-- *
-- *	MTEOM	-	Moves to the end of recorded data.
-- *
-- *	MTERASE	-	Erases tape.
-- *
-- *	MTSETBLK - 	Sets the user block size to mt_count bytes. If
-- *			mt_count is 0, we will attempt to autodetect
-- *			the block size.
-- *
-- *	MTSEEK	-	Positions the tape in a specific block number, where
-- *			each block is assumed to contain which user_block_size
-- *			bytes.
-- *
-- *	MTSETPART - 	Switches to another tape partition.
-- *
-- *	MTLOCK - 	Locks the tape door.
-- *
-- *	MTUNLOCK - 	Unlocks the tape door.
-- *
-- *	The following commands are currently not supported:
-- *
-- *	MTFSS, MTBSS, MTWSM, MTSETDENSITY,
-- *	MTSETDRVBUFFER, MT_ST_BOOLEANS, MT_ST_WRITE_THRESHOLD.
-+ * MTFSS, MTBSS, MTWSM, MTSETDENSITY, MTSETDRVBUFFER, MT_ST_BOOLEANS,
-+ * MT_ST_WRITE_THRESHOLD.
+  *	Enable the IDE PCI device. We attempt to enable the device in full
+- *	but if that fails then we only need BAR4 so we will enable that.
++ *	but if that fails then we only need IO space. The PCI code should
++ *	have setup the proper resources for us already for controllers in
++ *	legacy mode.
+  *	
+  *	Returns zero on success or an error code
   */
--static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count)
-+static int idetape_mtioctop(ide_drive_t *drive, short mt_op, int mt_count)
- {
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t pc;
-@@ -4068,29 +3276,12 @@ static int idetape_mtioctop (ide_drive_t *drive,short mt_op,int mt_count)
- }
+@@ -246,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
+ 	int ret;
  
- /*
-- *	Our character device ioctls.
-- *
-- *	General mtio.h magnetic io commands are supported here, and not in
-- *	the corresponding block interface.
-- *
-- *	The following ioctls are supported:
-- *
-- *	MTIOCTOP -	Refer to idetape_mtioctop for detailed description.
-- *
-- *	MTIOCGET - 	The mt_dsreg field in the returned mtget structure
-- *			will be set to (user block size in bytes <<
-- *			MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK.
-- *
-- *			The mt_blkno is set to the current user block number.
-- *			The other mtget fields are not supported.
-- *
-- *	MTIOCPOS -	The current tape "block position" is returned. We
-- *			assume that each block contains user_block_size
-- *			bytes.
-- *
-- *	Our own ide-tape ioctls are supported on both interfaces.
-+ * Our character device ioctls. General mtio.h magnetic io commands are
-+ * supported here, and not in the corresponding block interface. Our own
-+ * ide-tape ioctls are supported on both interfaces.
+ 	if (pci_enable_device(dev)) {
+-		ret = pci_enable_device_bars(dev, 1 << 4);
++		ret = pci_enable_device_io(dev);
+ 		if (ret < 0) {
+ 			printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
+ 				"Could not enable device.\n", d->name);
+@@ -345,7 +339,8 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
+  *	ide_hwif_configure	-	configure an IDE interface
+  *	@dev: PCI device holding interface
+  *	@d: IDE port info
+- *	@mate: Paired interface if any
++ *	@port: port number
++ *	@irq: PCI IRQ
+  *
+  *	Perform the initial set up for the hardware interface structure. This
+  *	is done per interface port rather than per PCI device. There may be
+@@ -354,11 +349,15 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
+  *	Returns the new hardware interface structure, or NULL on a failure
   */
--static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-+static int idetape_chrdev_ioctl(struct inode *inode, struct file *file,
-+				unsigned int cmd, unsigned long arg)
+ 
+-static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *mate, int port, int irq)
++static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
++				      const struct ide_port_info *d,
++				      unsigned int port, int irq)
  {
- 	struct ide_tape_obj *tape = ide_tape_f(file);
- 	ide_drive_t *drive = tape->drive;
-@@ -4144,7 +3335,30 @@ static int idetape_chrdev_ioctl (struct inode *inode, struct file *file, unsigne
+ 	unsigned long ctl = 0, base = 0;
+ 	ide_hwif_t *hwif;
+ 	u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
++	u8 oldnoprobe = 0;
++	struct hw_regs_s hw;
+ 
+ 	if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
+ 		/*  Possibly we should fail if these checks report true */
+@@ -381,47 +380,41 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port
  	}
+ 	if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
+ 		return NULL;	/* no room in ide_hwifs[] */
+-	if (hwif->io_ports[IDE_DATA_OFFSET] != base ||
+-	    hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) {
+-		hw_regs_t hw;
+-
+-		memset(&hw, 0, sizeof(hw));
+-#ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT
+-		ide_std_init_ports(&hw, base, ctl | 2);
+-#else
+-		ide_init_hwif_ports(&hw, base, ctl | 2, NULL);
+-#endif
+-		memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
+-		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+-	}
+-	hwif->chipset = d->chipset ? d->chipset : ide_pci;
+-	hwif->pci_dev = dev;
++
++	memset(&hw, 0, sizeof(hw));
++	hw.irq = hwif->irq ? hwif->irq : irq;
++	hw.dev = &dev->dev;
++	hw.chipset = d->chipset ? d->chipset : ide_pci;
++	ide_std_init_ports(&hw, base, ctl | 2);
++
++	if (hwif->io_ports[IDE_DATA_OFFSET] == base &&
++	    hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2))
++		oldnoprobe = hwif->noprobe;
++
++	ide_init_port_hw(hwif, &hw);
++
++	hwif->noprobe = oldnoprobe;
++
++	hwif->dev = &dev->dev;
+ 	hwif->cds = d;
+-	hwif->channel = port;
+ 
+-	if (!hwif->irq)
+-		hwif->irq = irq;
+-	if (mate) {
+-		hwif->mate = mate;
+-		mate->mate = hwif;
+-	}
+ 	return hwif;
  }
  
--static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive);
-+/*
-+ * Do a mode sense page 0 with block descriptor and if it succeeds set the tape
-+ * block size with the reported value.
-+ */
-+static void ide_tape_get_bsize_from_bdesc(ide_drive_t *drive)
-+{
-+	idetape_tape_t *tape = drive->driver_data;
-+	idetape_pc_t pc;
-+
-+	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
-+	if (idetape_queue_pc_tail(drive, &pc)) {
-+		printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
-+		if (tape->tape_block_size == 0) {
-+			printk(KERN_WARNING "ide-tape: Cannot deal with zero "
-+					    "block size, assuming 32k\n");
-+			tape->tape_block_size = 32768;
-+		}
-+		return;
-+	}
-+	tape->tape_block_size = (pc.buffer[4 + 5] << 16) +
-+				(pc.buffer[4 + 6] << 8)  +
-+				 pc.buffer[4 + 7];
-+	tape->drv_write_prot = (pc.buffer[2] & 0x80) >> 7;
-+}
++#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
+ /**
+  *	ide_hwif_setup_dma	-	configure DMA interface
+- *	@dev: PCI device
+- *	@d: IDE port info
+  *	@hwif: IDE interface
++ *	@d: IDE port info
+  *
+  *	Set up the DMA base for the interface. Enable the master bits as
+  *	necessary and attempt to bring the device DMA into a ready to use
+  *	state
+  */
  
- /*
-  *	Our character device open function.
-@@ -4198,7 +3412,7 @@ static int idetape_chrdev_open (struct inode *inode, struct file *filp)
- 		clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags);
+-static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *hwif)
++void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
+ {
+-#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
++	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	u16 pcicmd;
  
- 	/* Read block size and write protect status from drive. */
--	idetape_get_blocksize_from_block_descriptor(drive);
-+	ide_tape_get_bsize_from_bdesc(drive);
+ 	pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
+@@ -446,15 +439,15 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *
+ 			if (d->init_dma) {
+ 				d->init_dma(hwif, dma_base);
+ 			} else {
+-				ide_setup_dma(hwif, dma_base, 8);
++				ide_setup_dma(hwif, dma_base);
+ 			}
+ 		} else {
+ 			printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
+ 				"(BIOS)\n", hwif->name, d->name);
+ 		}
+ 	}
+-#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
+ }
++#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
  
- 	/* Set write protect flag if device is opened as read-only. */
- 	if ((filp->f_flags & O_ACCMODE) == O_RDONLY)
-@@ -4310,255 +3524,106 @@ static int idetape_identify_device (ide_drive_t *drive)
+ /**
+  *	ide_setup_pci_controller	-	set up IDE PCI
+@@ -516,7 +509,7 @@ out:
+ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
  {
- 	struct idetape_id_gcw gcw;
- 	struct hd_driveid *id = drive->id;
--#if IDETAPE_DEBUG_INFO
--	unsigned short mask,i;
--#endif /* IDETAPE_DEBUG_INFO */
+ 	int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
+-	ide_hwif_t *hwif, *mate = NULL;
++	ide_hwif_t *hwif;
+ 	u8 tmp;
  
- 	if (drive->id_read == 0)
- 		return 1;
+ 	/*
+@@ -532,62 +525,11 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
+ 			continue;	/* port not enabled */
+ 		}
  
- 	*((unsigned short *) &gcw) = id->config;
+-		if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
++		hwif = ide_hwif_configure(dev, d, port, pciirq);
++		if (hwif == NULL)
+ 			continue;
  
--#if IDETAPE_DEBUG_INFO
--	printk(KERN_INFO "ide-tape: Dumping ATAPI Identify Device tape parameters\n");
--	printk(KERN_INFO "ide-tape: Protocol Type: ");
--	switch (gcw.protocol) {
--		case 0: case 1: printk("ATA\n");break;
--		case 2:	printk("ATAPI\n");break;
--		case 3: printk("Reserved (Unknown to ide-tape)\n");break;
--	}
--	printk(KERN_INFO "ide-tape: Device Type: %x - ",gcw.device_type);	
--	switch (gcw.device_type) {
--		case 0: printk("Direct-access Device\n");break;
--		case 1: printk("Streaming Tape Device\n");break;
--		case 2: case 3: case 4: printk("Reserved\n");break;
--		case 5: printk("CD-ROM Device\n");break;
--		case 6: printk("Reserved\n");
--		case 7: printk("Optical memory Device\n");break;
--		case 0x1f: printk("Unknown or no Device type\n");break;
--		default: printk("Reserved\n");
--	}
--	printk(KERN_INFO "ide-tape: Removable: %s",gcw.removable ? "Yes\n":"No\n");	
--	printk(KERN_INFO "ide-tape: Command Packet DRQ Type: ");
--	switch (gcw.drq_type) {
--		case 0: printk("Microprocessor DRQ\n");break;
--		case 1: printk("Interrupt DRQ\n");break;
--		case 2: printk("Accelerated DRQ\n");break;
--		case 3: printk("Reserved\n");break;
--	}
--	printk(KERN_INFO "ide-tape: Command Packet Size: ");
--	switch (gcw.packet_size) {
--		case 0: printk("12 bytes\n");break;
--		case 1: printk("16 bytes\n");break;
--		default: printk("Reserved\n");break;
--	}
--	printk(KERN_INFO "ide-tape: Model: %.40s\n",id->model);
--	printk(KERN_INFO "ide-tape: Firmware Revision: %.8s\n",id->fw_rev);
--	printk(KERN_INFO "ide-tape: Serial Number: %.20s\n",id->serial_no);
--	printk(KERN_INFO "ide-tape: Write buffer size: %d bytes\n",id->buf_size*512);
--	printk(KERN_INFO "ide-tape: DMA: %s",id->capability & 0x01 ? "Yes\n":"No\n");
--	printk(KERN_INFO "ide-tape: LBA: %s",id->capability & 0x02 ? "Yes\n":"No\n");
--	printk(KERN_INFO "ide-tape: IORDY can be disabled: %s",id->capability & 0x04 ? "Yes\n":"No\n");
--	printk(KERN_INFO "ide-tape: IORDY supported: %s",id->capability & 0x08 ? "Yes\n":"Unknown\n");
--	printk(KERN_INFO "ide-tape: ATAPI overlap supported: %s",id->capability & 0x20 ? "Yes\n":"No\n");
--	printk(KERN_INFO "ide-tape: PIO Cycle Timing Category: %d\n",id->tPIO);
--	printk(KERN_INFO "ide-tape: DMA Cycle Timing Category: %d\n",id->tDMA);
--	printk(KERN_INFO "ide-tape: Single Word DMA supported modes: ");
--	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
--		if (id->dma_1word & mask)
--			printk("%d ",i);
--		if (id->dma_1word & (mask << 8))
--			printk("(active) ");
--	}
--	printk("\n");
--	printk(KERN_INFO "ide-tape: Multi Word DMA supported modes: ");
--	for (i=0,mask=1;i<8;i++,mask=mask << 1) {
--		if (id->dma_mword & mask)
--			printk("%d ",i);
--		if (id->dma_mword & (mask << 8))
--			printk("(active) ");
--	}
--	printk("\n");
--	if (id->field_valid & 0x0002) {
--		printk(KERN_INFO "ide-tape: Enhanced PIO Modes: %s\n",
--			id->eide_pio_modes & 1 ? "Mode 3":"None");
--		printk(KERN_INFO "ide-tape: Minimum Multi-word DMA cycle per word: ");
--		if (id->eide_dma_min == 0)
--			printk("Not supported\n");
--		else
--			printk("%d ns\n",id->eide_dma_min);
--
--		printk(KERN_INFO "ide-tape: Manufacturer\'s Recommended Multi-word cycle: ");
--		if (id->eide_dma_time == 0)
--			printk("Not supported\n");
--		else
--			printk("%d ns\n",id->eide_dma_time);
+-		/* setup proper ancestral information */
+-		hwif->gendev.parent = &dev->dev;
 -
--		printk(KERN_INFO "ide-tape: Minimum PIO cycle without IORDY: ");
--		if (id->eide_pio == 0)
--			printk("Not supported\n");
--		else
--			printk("%d ns\n",id->eide_pio);
+ 		*(idx + port) = hwif->index;
 -
--		printk(KERN_INFO "ide-tape: Minimum PIO cycle with IORDY: ");
--		if (id->eide_pio_iordy == 0)
--			printk("Not supported\n");
--		else
--			printk("%d ns\n",id->eide_pio_iordy);
 -		
--	} else
--		printk(KERN_INFO "ide-tape: According to the device, fields 64-70 are not valid.\n");
--#endif /* IDETAPE_DEBUG_INFO */
+-		if (d->init_iops)
+-			d->init_iops(hwif);
 -
- 	/* Check that we can support this device */
- 
--	if (gcw.protocol !=2 )
--		printk(KERN_ERR "ide-tape: Protocol is not ATAPI\n");
-+	if (gcw.protocol != 2)
-+		printk(KERN_ERR "ide-tape: Protocol (0x%02x) is not ATAPI\n",
-+				gcw.protocol);
- 	else if (gcw.device_type != 1)
--		printk(KERN_ERR "ide-tape: Device type is not set to tape\n");
-+		printk(KERN_ERR "ide-tape: Device type (0x%02x) is not set "
-+				"to tape\n", gcw.device_type);
- 	else if (!gcw.removable)
- 		printk(KERN_ERR "ide-tape: The removable flag is not set\n");
- 	else if (gcw.packet_size != 0) {
--		printk(KERN_ERR "ide-tape: Packet size is not 12 bytes long\n");
--		if (gcw.packet_size == 1)
--			printk(KERN_ERR "ide-tape: Sorry, padding to 16 bytes is still not supported\n");
-+		printk(KERN_ERR "ide-tape: Packet size (0x%02x) is not 12 "
-+				"bytes long\n", gcw.packet_size);
- 	} else
- 		return 1;
- 	return 0;
- }
- 
--/*
-- * Use INQUIRY to get the firmware revision
-- */
--static void idetape_get_inquiry_results (ide_drive_t *drive)
-+static void idetape_get_inquiry_results(ide_drive_t *drive)
- {
- 	char *r;
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t pc;
--	idetape_inquiry_result_t *inquiry;
--	
-+
- 	idetape_create_inquiry_cmd(&pc);
- 	if (idetape_queue_pc_tail(drive, &pc)) {
--		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n", tape->name);
-+		printk(KERN_ERR "ide-tape: %s: can't get INQUIRY results\n",
-+				tape->name);
- 		return;
+-		if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
+-			ide_hwif_setup_dma(dev, d, hwif);
+-
+-		if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
+-		    (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
+-			hwif->irq = port ? 15 : 14;
+-
+-		hwif->fixup = d->fixup;
+-
+-		hwif->host_flags = d->host_flags;
+-		hwif->pio_mask = d->pio_mask;
+-
+-		if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
+-			hwif->mate->serialized = hwif->serialized = 1;
+-
+-		if (d->host_flags & IDE_HFLAG_IO_32BIT) {
+-			hwif->drives[0].io_32bit = 1;
+-			hwif->drives[1].io_32bit = 1;
+-		}
+-
+-		if (d->host_flags & IDE_HFLAG_UNMASK_IRQS) {
+-			hwif->drives[0].unmask = 1;
+-			hwif->drives[1].unmask = 1;
+-		}
+-
+-		if (hwif->dma_base) {
+-			hwif->swdma_mask = d->swdma_mask;
+-			hwif->mwdma_mask = d->mwdma_mask;
+-			hwif->ultra_mask = d->udma_mask;
+-		}
+-
+-		hwif->drives[0].autotune = 1;
+-		hwif->drives[1].autotune = 1;
+-
+-		if (d->host_flags & IDE_HFLAG_RQSIZE_256)
+-			hwif->rqsize = 256;
+-
+-		if (d->init_hwif)
+-			/* Call chipset-specific routine
+-			 * for each enabled hwif
+-			 */
+-			d->init_hwif(hwif);
+-
+-		mate = hwif;
  	}
--	inquiry = (idetape_inquiry_result_t *) pc.buffer;
--	memcpy(tape->vendor_id, inquiry->vendor_id, 8);
--	memcpy(tape->product_id, inquiry->product_id, 16);
--	memcpy(tape->firmware_revision, inquiry->revision_level, 4);
-+	memcpy(tape->vendor_id, &pc.buffer[8], 8);
-+	memcpy(tape->product_id, &pc.buffer[16], 16);
-+	memcpy(tape->firmware_revision, &pc.buffer[32], 4);
-+
- 	ide_fixstring(tape->vendor_id, 10, 0);
- 	ide_fixstring(tape->product_id, 18, 0);
- 	ide_fixstring(tape->firmware_revision, 6, 0);
- 	r = tape->firmware_revision;
- 	if (*(r + 1) == '.')
--		tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0';
--	printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision);
-+		tape->firmware_revision_num = (*r - '0') * 100 +
-+			(*(r + 2) - '0') * 10 +	*(r + 3) - '0';
-+	printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n",
-+			drive->name, tape->name, tape->vendor_id,
-+			tape->product_id, tape->firmware_revision);
  }
  
- /*
-- *	idetape_get_mode_sense_results asks the tape about its various
-- *	parameters. In particular, we will adjust our data transfer buffer
-- *	size to the recommended value as returned by the tape.
-+ * Ask the tape about its various parameters. In particular, we will adjust our
-+ * data transfer buffer	size to the recommended value as returned by the tape.
-  */
- static void idetape_get_mode_sense_results (ide_drive_t *drive)
- {
- 	idetape_tape_t *tape = drive->driver_data;
- 	idetape_pc_t pc;
--	idetape_mode_parameter_header_t *header;
--	idetape_capabilities_page_t *capabilities;
--	
-+	u8 *caps;
-+	u8 speed, max_speed;
-+
- 	idetape_create_mode_sense_cmd(&pc, IDETAPE_CAPABILITIES_PAGE);
- 	if (idetape_queue_pc_tail(drive, &pc)) {
--		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming some default values\n");
-+		printk(KERN_ERR "ide-tape: Can't get tape parameters - assuming"
-+				" some default values\n");
- 		tape->tape_block_size = 512;
--		tape->capabilities.ctl = 52;
--		tape->capabilities.speed = 450;
--		tape->capabilities.buffer_size = 6 * 52;
-+		put_unaligned(52,   (u16 *)&tape->caps[12]);
-+		put_unaligned(540,  (u16 *)&tape->caps[14]);
-+		put_unaligned(6*52, (u16 *)&tape->caps[16]);
- 		return;
- 	}
--	header = (idetape_mode_parameter_header_t *) pc.buffer;
--	capabilities = (idetape_capabilities_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl);
-+	caps = pc.buffer + 4 + pc.buffer[3];
+@@ -669,7 +611,7 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
+ 	ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
  
--	capabilities->max_speed = ntohs(capabilities->max_speed);
--	capabilities->ctl = ntohs(capabilities->ctl);
--	capabilities->speed = ntohs(capabilities->speed);
--	capabilities->buffer_size = ntohs(capabilities->buffer_size);
-+	/* convert to host order and save for later use */
-+	speed = be16_to_cpu(*(u16 *)&caps[14]);
-+	max_speed = be16_to_cpu(*(u16 *)&caps[8]);
+ 	if (ret >= 0)
+-		ide_device_add(idx);
++		ide_device_add(idx, d);
  
--	if (!capabilities->speed) {
--		printk(KERN_INFO "ide-tape: %s: overriding capabilities->speed (assuming 650KB/sec)\n", drive->name);
--		capabilities->speed = 650;
-+	put_unaligned(max_speed, (u16 *)&caps[8]);
-+	put_unaligned(be16_to_cpu(*(u16 *)&caps[12]), (u16 *)&caps[12]);
-+	put_unaligned(speed, (u16 *)&caps[14]);
-+	put_unaligned(be16_to_cpu(*(u16 *)&caps[16]), (u16 *)&caps[16]);
-+
-+	if (!speed) {
-+		printk(KERN_INFO "ide-tape: %s: invalid tape speed "
-+				"(assuming 650KB/sec)\n", drive->name);
-+		put_unaligned(650, (u16 *)&caps[14]);
- 	}
--	if (!capabilities->max_speed) {
--		printk(KERN_INFO "ide-tape: %s: overriding capabilities->max_speed (assuming 650KB/sec)\n", drive->name);
--		capabilities->max_speed = 650;
-+	if (!max_speed) {
-+		printk(KERN_INFO "ide-tape: %s: invalid max_speed "
-+				"(assuming 650KB/sec)\n", drive->name);
-+		put_unaligned(650, (u16 *)&caps[8]);
+ 	return ret;
+ }
+@@ -693,111 +635,9 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
+ 			goto out;
  	}
  
--	tape->capabilities = *capabilities;		/* Save us a copy */
--	if (capabilities->blk512)
-+	memcpy(&tape->caps, caps, 20);
-+	if (caps[7] & 0x02)
- 		tape->tape_block_size = 512;
--	else if (capabilities->blk1024)
-+	else if (caps[7] & 0x04)
- 		tape->tape_block_size = 1024;
+-	ide_device_add(idx);
++	ide_device_add(idx, d);
+ out:
+ 	return ret;
+ }
+ 
+ EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
 -
--#if IDETAPE_DEBUG_INFO
--	printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n");
--	printk(KERN_INFO "ide-tape: Mode Parameter Header:\n");
--	printk(KERN_INFO "ide-tape: Mode Data Length - %d\n",header->mode_data_length);
--	printk(KERN_INFO "ide-tape: Medium Type - %d\n",header->medium_type);
--	printk(KERN_INFO "ide-tape: Device Specific Parameter - %d\n",header->dsp);
--	printk(KERN_INFO "ide-tape: Block Descriptor Length - %d\n",header->bdl);
--	
--	printk(KERN_INFO "ide-tape: Capabilities and Mechanical Status Page:\n");
--	printk(KERN_INFO "ide-tape: Page code - %d\n",capabilities->page_code);
--	printk(KERN_INFO "ide-tape: Page length - %d\n",capabilities->page_length);
--	printk(KERN_INFO "ide-tape: Read only - %s\n",capabilities->ro ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports reverse space - %s\n",capabilities->sprev ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports erase initiated formatting - %s\n",capabilities->efmt ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports QFA two Partition format - %s\n",capabilities->qfa ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports locking the medium - %s\n",capabilities->lock ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: The volume is currently locked - %s\n",capabilities->locked ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: The device defaults in the prevent state - %s\n",capabilities->prevent ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports ejecting the medium - %s\n",capabilities->eject ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports error correction - %s\n",capabilities->ecc ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports data compression - %s\n",capabilities->cmprs ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports 512 bytes block size - %s\n",capabilities->blk512 ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports 1024 bytes block size - %s\n",capabilities->blk1024 ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Supports 32768 bytes block size / Restricted byte count for PIO transfers - %s\n",capabilities->blk32768 ? "Yes":"No");
--	printk(KERN_INFO "ide-tape: Maximum supported speed in KBps - %d\n",capabilities->max_speed);
--	printk(KERN_INFO "ide-tape: Continuous transfer limits in blocks - %d\n",capabilities->ctl);
--	printk(KERN_INFO "ide-tape: Current speed in KBps - %d\n",capabilities->speed);	
--	printk(KERN_INFO "ide-tape: Buffer size - %d\n",capabilities->buffer_size*512);
--#endif /* IDETAPE_DEBUG_INFO */
--}
+-#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
+-/*
+- *	Module interfaces
+- */
+-
+-static int pre_init = 1;		/* Before first ordered IDE scan */
+-static LIST_HEAD(ide_pci_drivers);
 -
 -/*
-- *	ide_get_blocksize_from_block_descriptor does a mode sense page 0 with block descriptor
-- *	and if it succeeds sets the tape block size with the reported value
+- *	__ide_pci_register_driver	-	attach IDE driver
+- *	@driver: pci driver
+- *	@module: owner module of the driver
+- *
+- *	Registers a driver with the IDE layer. The IDE layer arranges that
+- *	boot time setup is done in the expected device order and then
+- *	hands the controllers off to the core PCI code to do the rest of
+- *	the work.
+- *
+- *	Returns are the same as for pci_register_driver
 - */
--static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive)
+-
+-int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
+-			      const char *mod_name)
 -{
+-	if (!pre_init)
+-		return __pci_register_driver(driver, module, mod_name);
+-	driver->driver.owner = module;
+-	list_add_tail(&driver->node, &ide_pci_drivers);
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
 -
--	idetape_tape_t *tape = drive->driver_data;
--	idetape_pc_t pc;
--	idetape_mode_parameter_header_t *header;
--	idetape_parameter_block_descriptor_t *block_descrp;
--	
--	idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_DESCRIPTOR);
--	if (idetape_queue_pc_tail(drive, &pc)) {
--		printk(KERN_ERR "ide-tape: Can't get block descriptor\n");
--		if (tape->tape_block_size == 0) {
--			printk(KERN_WARNING "ide-tape: Cannot deal with zero block size, assume 32k\n");
--			tape->tape_block_size =  32768;
+-/**
+- *	ide_scan_pcidev		-	find an IDE driver for a device
+- *	@dev: PCI device to check
+- *
+- *	Look for an IDE driver to handle the device we are considering.
+- *	This is only used during boot up to get the ordering correct. After
+- *	boot up the pci layer takes over the job.
+- */
+-
+-static int __init ide_scan_pcidev(struct pci_dev *dev)
+-{
+-	struct list_head *l;
+-	struct pci_driver *d;
+-
+-	list_for_each(l, &ide_pci_drivers) {
+-		d = list_entry(l, struct pci_driver, node);
+-		if (d->id_table) {
+-			const struct pci_device_id *id =
+-				pci_match_id(d->id_table, dev);
+-
+-			if (id != NULL && d->probe(dev, id) >= 0) {
+-				dev->driver = d;
+-				pci_dev_get(dev);
+-				return 1;
+-			}
 -		}
--		return;
 -	}
--	header = (idetape_mode_parameter_header_t *) pc.buffer;
--	block_descrp = (idetape_parameter_block_descriptor_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t));
--	tape->tape_block_size =( block_descrp->length[0]<<16) + (block_descrp->length[1]<<8) + block_descrp->length[2];
--	tape->drv_write_prot = (header->dsp & 0x80) >> 7;
+-	return 0;
+-}
+-
+-/**
+- *	ide_scan_pcibus		-	perform the initial IDE driver scan
+- *	@scan_direction: set for reverse order scanning
+- *
+- *	Perform the initial bus rather than driver ordered scan of the
+- *	PCI drivers. After this all IDE pci handling becomes standard
+- *	module ordering not traditionally ordered.
+- */
+- 	
+-void __init ide_scan_pcibus (int scan_direction)
+-{
+-	struct pci_dev *dev = NULL;
+-	struct pci_driver *d;
+-	struct list_head *l, *n;
+-
+-	pre_init = 0;
+-	if (!scan_direction)
+-		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
+-			ide_scan_pcidev(dev);
+-	else
+-		while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
+-						     dev)))
+-			ide_scan_pcidev(dev);
 -
--#if IDETAPE_DEBUG_INFO
--	printk(KERN_INFO "ide-tape: Adjusted block size - %d\n", tape->tape_block_size);
--#endif /* IDETAPE_DEBUG_INFO */
- }
- 
- #ifdef CONFIG_IDE_PROC_FS
-@@ -4569,13 +3634,15 @@ static void idetape_add_settings (ide_drive_t *drive)
- /*
-  *			drive	setting name		read/write	data type	min			max			mul_factor			div_factor	data pointer				set function
-  */
--	ide_add_setting(drive,	"buffer",		SETTING_READ,	TYPE_SHORT,	0,			0xffff,			1,				2,		&tape->capabilities.buffer_size,	NULL);
-+	ide_add_setting(drive, "buffer", SETTING_READ, TYPE_SHORT, 0, 0xffff,
-+			1, 2, (u16 *)&tape->caps[16], NULL);
- 	ide_add_setting(drive,	"pipeline_min",		SETTING_RW,	TYPE_INT,	1,			0xffff,			tape->stage_size / 1024,	1,		&tape->min_pipeline,			NULL);
- 	ide_add_setting(drive,	"pipeline",		SETTING_RW,	TYPE_INT,	1,			0xffff,			tape->stage_size / 1024,	1,		&tape->max_stages,			NULL);
- 	ide_add_setting(drive,	"pipeline_max",		SETTING_RW,	TYPE_INT,	1,			0xffff,			tape->stage_size / 1024,	1,		&tape->max_pipeline,			NULL);
- 	ide_add_setting(drive,	"pipeline_used",	SETTING_READ,	TYPE_INT,	0,			0xffff,			tape->stage_size / 1024,	1,		&tape->nr_stages,			NULL);
- 	ide_add_setting(drive,	"pipeline_pending",	SETTING_READ,	TYPE_INT,	0,			0xffff,			tape->stage_size / 1024,	1,		&tape->nr_pending_stages,		NULL);
--	ide_add_setting(drive,	"speed",		SETTING_READ,	TYPE_SHORT,	0,			0xffff,			1,				1,		&tape->capabilities.speed,		NULL);
-+	ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
-+			1, 1, (u16 *)&tape->caps[14], NULL);
- 	ide_add_setting(drive,	"stage",		SETTING_READ,	TYPE_INT,	0,			0xffff,			1,				1024,		&tape->stage_size,			NULL);
- 	ide_add_setting(drive,	"tdsc",			SETTING_RW,	TYPE_INT,	IDETAPE_DSC_RW_MIN,	IDETAPE_DSC_RW_MAX,	1000,				HZ,		&tape->best_dsc_rw_frequency,		NULL);
- 	ide_add_setting(drive,	"dsc_overlap",		SETTING_RW,	TYPE_BYTE,	0,			1,			1,				1,		&drive->dsc_overlap,			NULL);
-@@ -4607,22 +3674,15 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
- 	struct idetape_id_gcw gcw;
- 	int stage_size;
- 	struct sysinfo si;
-+	u16 *ctl = (u16 *)&tape->caps[12];
- 
- 	spin_lock_init(&tape->spinlock);
- 	drive->dsc_overlap = 1;
--#ifdef CONFIG_BLK_DEV_IDEPCI
--	if (HWIF(drive)->pci_dev != NULL) {
--		/*
--		 * These two ide-pci host adapters appear to need DSC overlap disabled.
--		 * This probably needs further analysis.
--		 */
--		if ((HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) ||
--		    (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_TTI_HPT343)) {
--			printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n", tape->name);
--		    	drive->dsc_overlap = 0;
--		}
-+	if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) {
-+		printk(KERN_INFO "ide-tape: %s: disabling DSC overlap\n",
-+				 tape->name);
-+		drive->dsc_overlap = 0;
- 	}
--#endif /* CONFIG_BLK_DEV_IDEPCI */
- 	/* Seagate Travan drives do not support DSC overlap. */
- 	if (strstr(drive->id->model, "Seagate STT3401"))
- 		drive->dsc_overlap = 0;
-@@ -4642,13 +3702,13 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
- 	
- 	idetape_get_inquiry_results(drive);
- 	idetape_get_mode_sense_results(drive);
--	idetape_get_blocksize_from_block_descriptor(drive);
-+	ide_tape_get_bsize_from_bdesc(drive);
- 	tape->user_bs_factor = 1;
--	tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
-+	tape->stage_size = *ctl * tape->tape_block_size;
- 	while (tape->stage_size > 0xffff) {
- 		printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
--		tape->capabilities.ctl /= 2;
--		tape->stage_size = tape->capabilities.ctl * tape->tape_block_size;
-+		*ctl /= 2;
-+		tape->stage_size = *ctl * tape->tape_block_size;
- 	}
- 	stage_size = tape->stage_size;
- 	tape->pages_per_stage = stage_size / PAGE_SIZE;
-@@ -4657,11 +3717,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
- 		tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
- 	}
- 
 -	/*
--	 *	Select the "best" DSC read/write polling frequency
--	 *	and pipeline size.
+-	 *	Hand the drivers over to the PCI layer now we
+-	 *	are post init.
 -	 */
--	speed = max(tape->capabilities.speed, tape->capabilities.max_speed);
-+	/* Select the "best" DSC read/write polling freq and pipeline size. */
-+	speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
+-
+-	list_for_each_safe(l, n, &ide_pci_drivers) {
+-		list_del(l);
+-		d = list_entry(l, struct pci_driver, node);
+-		if (__pci_register_driver(d, d->driver.owner,
+-					  d->driver.mod_name))
+-			printk(KERN_ERR "%s: failed to register %s driver\n",
+-					__FUNCTION__, d->driver.mod_name);
+-	}
+-}
+-#endif
+diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
+index 489c133..1f8153b 100644
+--- a/drivers/ieee1394/Makefile
++++ b/drivers/ieee1394/Makefile
+@@ -15,3 +15,4 @@ obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
+ obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
+ obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
  
- 	tape->max_stages = speed * 1000 * 10 / tape->stage_size;
++obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
+diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
+index 7c4eb39..73685e7 100644
+--- a/drivers/ieee1394/dma.c
++++ b/drivers/ieee1394/dma.c
+@@ -231,37 +231,24 @@ void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
  
-@@ -4678,7 +3735,7 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
- 		tape->max_stages = tape->min_pipeline = tape->max_pipeline = 1;
+ #ifdef CONFIG_MMU
  
- 	t1 = (tape->stage_size * HZ) / (speed * 1000);
--	tmid = (tape->capabilities.buffer_size * 32 * HZ) / (speed * 125);
-+	tmid = (*(u16 *)&tape->caps[16] * 32 * HZ) / (speed * 125);
- 	tn = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
+-/* nopage() handler for mmap access */
+-
+-static struct page *dma_region_pagefault(struct vm_area_struct *area,
+-					 unsigned long address, int *type)
++static int dma_region_pagefault(struct vm_area_struct *vma,
++				struct vm_fault *vmf)
+ {
+-	unsigned long offset;
+-	unsigned long kernel_virt_addr;
+-	struct page *ret = NOPAGE_SIGBUS;
+-
+-	struct dma_region *dma = (struct dma_region *)area->vm_private_data;
++	struct dma_region *dma = (struct dma_region *)vma->vm_private_data;
  
- 	if (tape->max_stages)
-@@ -4693,8 +3750,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
- 	tape->best_dsc_rw_frequency = max_t(unsigned long, min_t(unsigned long, t, IDETAPE_DSC_RW_MAX), IDETAPE_DSC_RW_MIN);
- 	printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
- 		"%dkB pipeline, %lums tDSC%s\n",
--		drive->name, tape->name, tape->capabilities.speed,
--		(tape->capabilities.buffer_size * 512) / tape->stage_size,
-+		drive->name, tape->name, *(u16 *)&tape->caps[14],
-+		(*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
- 		tape->stage_size / 1024,
- 		tape->max_stages * tape->stage_size / 1024,
- 		tape->best_dsc_rw_frequency * 1000 / HZ,
-@@ -4724,10 +3781,8 @@ static void ide_tape_release(struct kref *kref)
+ 	if (!dma->kvirt)
+-		goto out;
+-
+-	if ((address < (unsigned long)area->vm_start) ||
+-	    (address >
+-	     (unsigned long)area->vm_start + (dma->n_pages << PAGE_SHIFT)))
+-		goto out;
+-
+-	if (type)
+-		*type = VM_FAULT_MINOR;
+-	offset = address - area->vm_start;
+-	kernel_virt_addr = (unsigned long)dma->kvirt + offset;
+-	ret = vmalloc_to_page((void *)kernel_virt_addr);
+-	get_page(ret);
+-      out:
+-	return ret;
++		return VM_FAULT_SIGBUS;
++
++	if (vmf->pgoff >= dma->n_pages)
++		return VM_FAULT_SIGBUS;
++
++	vmf->page = vmalloc_to_page(dma->kvirt + (vmf->pgoff << PAGE_SHIFT));
++	get_page(vmf->page);
++	return 0;
+ }
  
- 	drive->dsc_overlap = 0;
- 	drive->driver_data = NULL;
--	class_device_destroy(idetape_sysfs_class,
--			MKDEV(IDETAPE_MAJOR, tape->minor));
--	class_device_destroy(idetape_sysfs_class,
--			MKDEV(IDETAPE_MAJOR, tape->minor + 128));
-+	device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor));
-+	device_destroy(idetape_sysfs_class, MKDEV(IDETAPE_MAJOR, tape->minor + 128));
- 	idetape_devs[tape->minor] = NULL;
- 	g->private_data = NULL;
- 	put_disk(g);
-@@ -4884,10 +3939,10 @@ static int ide_tape_probe(ide_drive_t *drive)
+ static struct vm_operations_struct dma_region_vm_ops = {
+-	.nopage = dma_region_pagefault,
++	.fault = dma_region_pagefault,
+ };
  
- 	idetape_setup(drive, tape, minor);
+ /**
+@@ -275,7 +262,7 @@ int dma_region_mmap(struct dma_region *dma, struct file *file,
+ 	if (!dma->kvirt)
+ 		return -EINVAL;
  
--	class_device_create(idetape_sysfs_class, NULL,
--			MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name);
--	class_device_create(idetape_sysfs_class, NULL,
--			MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name);
-+	device_create(idetape_sysfs_class, &drive->gendev,
-+		      MKDEV(IDETAPE_MAJOR, minor), "%s", tape->name);
-+	device_create(idetape_sysfs_class, &drive->gendev,
-+			MKDEV(IDETAPE_MAJOR, minor + 128), "n%s", tape->name);
+-	/* must be page-aligned */
++	/* must be page-aligned (XXX: comment is wrong, we could allow pgoff) */
+ 	if (vma->vm_pgoff != 0)
+ 		return -EINVAL;
  
- 	g->fops = &idetape_block_ops;
- 	ide_register_region(g);
-diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
-index 2b60f1b..4e1da1c 100644
---- a/drivers/ide/ide-taskfile.c
-+++ b/drivers/ide/ide-taskfile.c
-@@ -1,11 +1,9 @@
- /*
-- * linux/drivers/ide/ide-taskfile.c	Version 0.38	March 05, 2003
-- *
-- *  Copyright (C) 2000-2002	Michael Cornwell <cornwell at acm.org>
-- *  Copyright (C) 2000-2002	Andre Hedrick <andre at linux-ide.org>
-- *  Copyright (C) 2001-2002	Klaus Smolin
-+ *  Copyright (C) 2000-2002	   Michael Cornwell <cornwell at acm.org>
-+ *  Copyright (C) 2000-2002	   Andre Hedrick <andre at linux-ide.org>
-+ *  Copyright (C) 2001-2002	   Klaus Smolin
-  *					IBM Storage Technology Division
-- *  Copyright (C) 2003-2004	Bartlomiej Zolnierkiewicz
-+ *  Copyright (C) 2003-2004, 2007  Bartlomiej Zolnierkiewicz
-  *
-  *  The big the bad and the ugly.
-  */
-@@ -35,93 +33,81 @@
- #include <asm/uaccess.h>
- #include <asm/io.h>
+diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
+index 6779893..10c3d9f 100644
+--- a/drivers/ieee1394/ieee1394_transactions.c
++++ b/drivers/ieee1394/ieee1394_transactions.c
+@@ -570,71 +570,3 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
  
--static void ata_bswap_data (void *buffer, int wcount)
+ 	return retval;
+ }
+-
+-#if 0
+-
+-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
+-	      u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
 -{
--	u16 *p = buffer;
+-	struct hpsb_packet *packet;
+-	int retval = 0;
 -
--	while (wcount--) {
--		*p = *p << 8 | *p >> 8; p++;
--		*p = *p << 8 | *p >> 8; p++;
+-	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
+-
+-	packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
+-	if (!packet)
+-		return -ENOMEM;
+-
+-	packet->generation = generation;
+-	retval = hpsb_send_packet_and_wait(packet);
+-	if (retval < 0)
+-		goto hpsb_lock_fail;
+-
+-	retval = hpsb_packet_success(packet);
+-
+-	if (retval == 0) {
+-		*data = packet->data[0];
 -	}
+-
+-      hpsb_lock_fail:
+-	hpsb_free_tlabel(packet);
+-	hpsb_free_packet(packet);
+-
+-	return retval;
 -}
 -
--static void taskfile_input_data(ide_drive_t *drive, void *buffer, u32 wcount)
-+void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
- {
--	HWIF(drive)->ata_input_data(drive, buffer, wcount);
--	if (drive->bswap)
--		ata_bswap_data(buffer, wcount);
+-int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
+-		   quadlet_t * buffer, size_t length, u32 specifier_id,
+-		   unsigned int version)
+-{
+-	struct hpsb_packet *packet;
+-	int retval = 0;
+-	u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
+-	u8 specifier_id_lo = specifier_id & 0xff;
+-
+-	HPSB_VERBOSE("Send GASP: channel = %d, length = %Zd", channel, length);
+-
+-	length += 8;
+-
+-	packet = hpsb_make_streampacket(host, NULL, length, channel, 3, 0);
+-	if (!packet)
+-		return -ENOMEM;
+-
+-	packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
+-	packet->data[1] =
+-	    cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
+-
+-	memcpy(&(packet->data[2]), buffer, length - 8);
+-
+-	packet->generation = generation;
+-
+-	packet->no_waiter = 1;
+-
+-	retval = hpsb_send_packet(packet);
+-	if (retval < 0)
+-		hpsb_free_packet(packet);
+-
+-	return retval;
 -}
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct ide_taskfile *tf = &task->tf;
-+	u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
+-
+-#endif				/*  0  */
+diff --git a/drivers/ieee1394/init_ohci1394_dma.c b/drivers/ieee1394/init_ohci1394_dma.c
+new file mode 100644
+index 0000000..ddaab6e
+--- /dev/null
++++ b/drivers/ieee1394/init_ohci1394_dma.c
+@@ -0,0 +1,285 @@
++/*
++ * init_ohci1394_dma.c - Initializes physical DMA on all OHCI 1394 controllers
++ *
++ * Copyright (C) 2006-2007      Bernhard Kaindl <bk at suse.de>
++ *
++ * Derived from drivers/ieee1394/ohci1394.c and arch/x86/kernel/early-quirks.c
++ * this file has functions to:
++ * - scan the PCI very early on boot for all OHCI 1394-compliant controllers
++ * - reset and initialize them and make them join the IEEE1394 bus and
++ * - enable physical DMA on them to allow remote debugging
++ *
++ * All code and data is marked as __init and __initdata, respective as
++ * during boot, all OHCI1394 controllers may be claimed by the firewire
++ * stack and at this point, this code should not touch them anymore.
++ *
++ * To use physical DMA after the initialization of the firewire stack,
++ * be sure that the stack enables it and (re-)attach after the bus reset
++ * which may be caused by the firewire stack initialization.
++ *
++ * 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.
++ */
 +
-+	if (task->tf_flags & IDE_TFLAG_FLAGGED)
-+		HIHI = 0xFF;
++#include <linux/interrupt.h>	/* for ohci1394.h */
++#include <linux/delay.h>
++#include <linux/pci.h>		/* for PCI defines */
++#include <linux/init_ohci1394_dma.h>
++#include <asm/pci-direct.h>	/* for direct PCI config space access */
++#include <asm/fixmap.h>
 +
-+#ifdef DEBUG
-+	printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
-+		"lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
-+		drive->name, tf->feature, tf->nsect, tf->lbal,
-+		tf->lbam, tf->lbah, tf->device, tf->command);
-+	printk("%s: hob: nsect 0x%02x lbal 0x%02x "
-+		"lbam 0x%02x lbah 0x%02x\n",
-+		drive->name, tf->hob_nsect, tf->hob_lbal,
-+		tf->hob_lbam, tf->hob_lbah);
-+#endif
- 
--static void taskfile_output_data(ide_drive_t *drive, void *buffer, u32 wcount)
--{
--	if (drive->bswap) {
--		ata_bswap_data(buffer, wcount);
--		HWIF(drive)->ata_output_data(drive, buffer, wcount);
--		ata_bswap_data(buffer, wcount);
--	} else {
--		HWIF(drive)->ata_output_data(drive, buffer, wcount);
--	}
-+	ide_set_irq(drive, 1);
++#include "ieee1394_types.h"
++#include "ohci1394.h"
 +
-+	if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
-+		SELECT_MASK(drive, 0);
++int __initdata init_ohci1394_dma_early;
 +
-+	if (task->tf_flags & IDE_TFLAG_OUT_DATA)
-+		hwif->OUTW((tf->hob_data << 8) | tf->data, IDE_DATA_REG);
++/* Reads a PHY register of an OHCI-1394 controller */
++static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
++{
++	int i;
++	quadlet_t r;
 +
-+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
-+		hwif->OUTB(tf->hob_feature, IDE_FEATURE_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
-+		hwif->OUTB(tf->hob_nsect, IDE_NSECTOR_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
-+		hwif->OUTB(tf->hob_lbal, IDE_SECTOR_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
-+		hwif->OUTB(tf->hob_lbam, IDE_LCYL_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
-+		hwif->OUTB(tf->hob_lbah, IDE_HCYL_REG);
++	reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
 +
-+	if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
-+		hwif->OUTB(tf->feature, IDE_FEATURE_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
-+		hwif->OUTB(tf->nsect, IDE_NSECTOR_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
-+		hwif->OUTB(tf->lbal, IDE_SECTOR_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
-+		hwif->OUTB(tf->lbam, IDE_LCYL_REG);
-+	if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
-+		hwif->OUTB(tf->lbah, IDE_HCYL_REG);
++	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
++		if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
++			break;
++		mdelay(1);
++	}
++	r = reg_read(ohci, OHCI1394_PhyControl);
 +
-+	if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
-+		hwif->OUTB((tf->device & HIHI) | drive->select.all, IDE_SELECT_REG);
- }
- 
- int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
- {
- 	ide_task_t args;
++	return (r & 0x00ff0000) >> 16;
++}
 +
- 	memset(&args, 0, sizeof(ide_task_t));
--	args.tfRegister[IDE_NSECTOR_OFFSET]	= 0x01;
-+	args.tf.nsect = 0x01;
- 	if (drive->media == ide_disk)
--		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_IDENTIFY;
-+		args.tf.command = WIN_IDENTIFY;
- 	else
--		args.tfRegister[IDE_COMMAND_OFFSET]	= WIN_PIDENTIFY;
--	args.command_type = IDE_DRIVE_TASK_IN;
--	args.data_phase   = TASKFILE_IN;
--	args.handler	  = &task_in_intr;
--	return ide_raw_taskfile(drive, &args, buf);
-+		args.tf.command = WIN_PIDENTIFY;
-+	args.tf_flags	= IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
-+	args.data_phase	= TASKFILE_IN;
-+	return ide_raw_taskfile(drive, &args, buf, 1);
- }
- 
--ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
-+static int inline task_dma_ok(ide_task_t *task)
- {
--	ide_hwif_t *hwif	= HWIF(drive);
--	task_struct_t *taskfile	= (task_struct_t *) task->tfRegister;
--	hob_struct_t *hobfile	= (hob_struct_t *) task->hobRegister;
--	u8 HIHI			= (drive->addressing == 1) ? 0xE0 : 0xEF;
--
--	/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
--	if (IDE_CONTROL_REG) {
--		/* clear nIEN */
--		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
--	}
--	SELECT_MASK(drive, 0);
--
--	if (drive->addressing == 1) {
--		hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
--		hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
--		hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
--		hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
--		hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
--	}
--
--	hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
--	hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
--	hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
--	hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
--	hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
--
--	hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
--
--	if (task->handler != NULL) {
--		if (task->prehandler != NULL) {
--			hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
--			ndelay(400);	/* FIXME */
--			return task->prehandler(drive, task->rq);
--		}
--		ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
--		return ide_started;
--	}
--
--	if (!drive->using_dma)
--		return ide_stopped;
-+	if (blk_fs_request(task->rq) || (task->tf_flags & IDE_TFLAG_FLAGGED))
-+		return 1;
- 
--	switch (taskfile->command) {
-+	switch (task->tf.command) {
- 		case WIN_WRITEDMA_ONCE:
- 		case WIN_WRITEDMA:
- 		case WIN_WRITEDMA_EXT:
-@@ -129,24 +115,79 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
- 		case WIN_READDMA:
- 		case WIN_READDMA_EXT:
- 		case WIN_IDENTIFY_DMA:
--			if (!hwif->dma_setup(drive)) {
--				hwif->dma_exec_cmd(drive, taskfile->command);
--				hwif->dma_start(drive);
--				return ide_started;
--			}
--			break;
--		default:
--			if (task->handler == NULL)
--				return ide_stopped;
-+			return 1;
- 	}
- 
--	return ide_stopped;
-+	return 0;
++/* Writes to a PHY register of an OHCI-1394 controller */
++static inline void __init set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
++{
++	int i;
++
++	reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
++
++	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
++		u32 r = reg_read(ohci, OHCI1394_PhyControl);
++		if (!(r & 0x00004000))
++			break;
++		mdelay(1);
++	}
 +}
 +
-+static ide_startstop_t task_no_data_intr(ide_drive_t *);
-+static ide_startstop_t set_geometry_intr(ide_drive_t *);
-+static ide_startstop_t recal_intr(ide_drive_t *);
-+static ide_startstop_t set_multmode_intr(ide_drive_t *);
-+static ide_startstop_t pre_task_out_intr(ide_drive_t *, struct request *);
-+static ide_startstop_t task_in_intr(ide_drive_t *);
++/* Resets an OHCI-1394 controller (for sane state before initialization) */
++static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
++	int i;
 +
-+ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
-+{
-+	ide_hwif_t *hwif	= HWIF(drive);
-+	struct ide_taskfile *tf = &task->tf;
-+	ide_handler_t *handler = NULL;
++	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
 +
-+	if (task->data_phase == TASKFILE_MULTI_IN ||
-+	    task->data_phase == TASKFILE_MULTI_OUT) {
-+		if (!drive->mult_count) {
-+			printk(KERN_ERR "%s: multimode not set!\n",
-+					drive->name);
-+			return ide_stopped;
-+		}
++	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
++		if (!(reg_read(ohci, OHCI1394_HCControlSet)
++				   & OHCI1394_HCControl_softReset))
++			break;
++		mdelay(1);
 +	}
++}
 +
-+	if (task->tf_flags & IDE_TFLAG_FLAGGED)
-+		task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
++/* Basic OHCI-1394 register and port inititalization */
++static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
++{
++	quadlet_t bus_options;
++	int num_ports, i;
 +
-+	if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0)
-+		ide_tf_load(drive, task);
++	/* Put some defaults to these undefined bus options */
++	bus_options = reg_read(ohci, OHCI1394_BusOptions);
++	bus_options |=  0x60000000; /* Enable CMC and ISC */
++	bus_options &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
++	bus_options &= ~0x18000000; /* Disable PMC and BMC */
++	reg_write(ohci, OHCI1394_BusOptions, bus_options);
 +
-+	switch (task->data_phase) {
-+	case TASKFILE_MULTI_OUT:
-+	case TASKFILE_OUT:
-+		hwif->OUTBSYNC(drive, tf->command, IDE_COMMAND_REG);
-+		ndelay(400);	/* FIXME */
-+		return pre_task_out_intr(drive, task->rq);
-+	case TASKFILE_MULTI_IN:
-+	case TASKFILE_IN:
-+		handler = task_in_intr;
-+		/* fall-through */
-+	case TASKFILE_NO_DATA:
-+		if (handler == NULL)
-+			handler = task_no_data_intr;
-+		/* WIN_{SPECIFY,RESTORE,SETMULT} use custom handlers */
-+		if (task->tf_flags & IDE_TFLAG_CUSTOM_HANDLER) {
-+			switch (tf->command) {
-+			case WIN_SPECIFY: handler = set_geometry_intr;	break;
-+			case WIN_RESTORE: handler = recal_intr;		break;
-+			case WIN_SETMULT: handler = set_multmode_intr;	break;
-+			}
-+		}
-+		ide_execute_command(drive, tf->command, handler,
-+				    WAIT_WORSTCASE, NULL);
-+		return ide_started;
-+	default:
-+		if (task_dma_ok(task) == 0 || drive->using_dma == 0 ||
-+		    hwif->dma_setup(drive))
-+			return ide_stopped;
-+		hwif->dma_exec_cmd(drive, tf->command);
-+		hwif->dma_start(drive);
-+		return ide_started;
++	/* Set the bus number */
++	reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
++
++	/* Enable posted writes */
++	reg_write(ohci, OHCI1394_HCControlSet,
++			OHCI1394_HCControl_postedWriteEnable);
++
++	/* Clear link control register */
++	reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
++
++	/* enable phys */
++	reg_write(ohci, OHCI1394_LinkControlSet,
++			OHCI1394_LinkControl_RcvPhyPkt);
++
++	/* Don't accept phy packets into AR request context */
++	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
++
++	/* Clear the Isochonouys interrupt masks */
++	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
++	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
++	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
++	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
++
++	/* Accept asyncronous transfer requests from all nodes for now */
++	reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
++
++	/* Specify asyncronous transfer retries */
++	reg_write(ohci, OHCI1394_ATRetries,
++		  OHCI1394_MAX_AT_REQ_RETRIES |
++		  (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
++		  (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
++
++	/* We don't want hardware swapping */
++	reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
++
++	/* Enable link */
++	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
++
++	/* If anything is connected to a port, make sure it is enabled */
++	num_ports = get_phy_reg(ohci, 2) & 0xf;
++	for (i = 0; i < num_ports; i++) {
++		unsigned int status;
++
++		set_phy_reg(ohci, 7, i);
++		status = get_phy_reg(ohci, 8);
++
++		if (status & 0x20)
++			set_phy_reg(ohci, 8, status & ~1);
 +	}
- }
-+EXPORT_SYMBOL_GPL(do_rw_taskfile);
- 
- /*
-  * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
-  */
--ide_startstop_t set_multmode_intr (ide_drive_t *drive)
-+static ide_startstop_t set_multmode_intr(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
- 	u8 stat;
-@@ -164,7 +205,7 @@ ide_startstop_t set_multmode_intr (ide_drive_t *drive)
- /*
-  * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
-  */
--ide_startstop_t set_geometry_intr (ide_drive_t *drive)
-+static ide_startstop_t set_geometry_intr(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
- 	int retries = 5;
-@@ -187,7 +228,7 @@ ide_startstop_t set_geometry_intr (ide_drive_t *drive)
- /*
-  * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
-  */
--ide_startstop_t recal_intr (ide_drive_t *drive)
-+static ide_startstop_t recal_intr(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
- 	u8 stat;
-@@ -200,7 +241,7 @@ ide_startstop_t recal_intr (ide_drive_t *drive)
- /*
-  * Handler for commands without a data phase
-  */
--ide_startstop_t task_no_data_intr (ide_drive_t *drive)
-+static ide_startstop_t task_no_data_intr(ide_drive_t *drive)
- {
- 	ide_task_t *args	= HWGROUP(drive)->rq->special;
- 	ide_hwif_t *hwif	= HWIF(drive);
-@@ -217,8 +258,6 @@ ide_startstop_t task_no_data_intr (ide_drive_t *drive)
- 	return ide_stopped;
- }
- 
--EXPORT_SYMBOL(task_no_data_intr);
--
- static u8 wait_drive_not_busy(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
-@@ -227,8 +266,7 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
- 
- 	/*
- 	 * Last sector was transfered, wait until drive is ready.
--	 * This can take up to 10 usec, but we will wait max 1 ms
--	 * (drive_cmd_intr() waits that long).
-+	 * This can take up to 10 usec, but we will wait max 1 ms.
- 	 */
- 	for (retries = 0; retries < 100; retries++) {
- 		if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT)
-@@ -283,9 +321,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
- 
- 	/* do the actual data transfer */
- 	if (write)
--		taskfile_output_data(drive, buf, SECTOR_WORDS);
-+		hwif->ata_output_data(drive, buf, SECTOR_WORDS);
- 	else
--		taskfile_input_data(drive, buf, SECTOR_WORDS);
-+		hwif->ata_input_data(drive, buf, SECTOR_WORDS);
- 
- 	kunmap_atomic(buf, KM_BIO_SRC_IRQ);
- #ifdef CONFIG_HIGHMEM
-@@ -305,9 +343,18 @@ static void ide_pio_multi(ide_drive_t *drive, unsigned int write)
- static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
- 				     unsigned int write)
- {
-+	u8 saved_io_32bit = drive->io_32bit;
++}
++
++/**
++ * init_ohci1394_wait_for_busresets - wait until bus resets are completed
++ *
++ * OHCI1394 initialization itself and any device going on- or offline
++ * and any cable issue cause a IEEE1394 bus reset. The OHCI1394 spec
++ * specifies that physical DMA is disabled on each bus reset and it
++ * has to be enabled after each bus reset when needed. We resort
++ * to polling here because on early boot, we have no interrupts.
++ */
++static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
++{
++	int i, events;
++
++	for (i=0; i < 9; i++) {
++		mdelay(200);
++		events = reg_read(ohci, OHCI1394_IntEventSet);
++		if (events & OHCI1394_busReset)
++			reg_write(ohci, OHCI1394_IntEventClear,
++					OHCI1394_busReset);
++	}
++}
++
++/**
++ * init_ohci1394_enable_physical_dma - Enable physical DMA for remote debugging
++ * This enables remote DMA access over IEEE1394 from every host for the low
++ * 4GB of address space. DMA accesses above 4GB are not available currently.
++ */
++static inline void __init init_ohci1394_enable_physical_dma(struct ti_ohci *hci)
++{
++	reg_write(hci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
++	reg_write(hci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
++	reg_write(hci, OHCI1394_PhyUpperBound, 0xffff0000);
++}
++
++/**
++ * init_ohci1394_reset_and_init_dma - init controller and enable DMA
++ * This initializes the given controller and enables physical DMA engine in it.
++ */
++static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
++{
++	/* Start off with a soft reset, clears everything to a sane state. */
++	init_ohci1394_soft_reset(ohci);
++
++	/* Accessing some registers without LPS enabled may cause lock up */
++	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
++
++	/* Disable and clear interrupts */
++	reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
++	reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
++
++	mdelay(50); /* Wait 50msec to make sure we have full link enabled */
++
++	init_ohci1394_initialize(ohci);
++	/*
++	 * The initialization causes at least one IEEE1394 bus reset. Enabling
++	 * physical DMA only works *after* *all* bus resets have calmed down:
++	 */
++	init_ohci1394_wait_for_busresets(ohci);
++
++	/* We had to wait and do this now if we want to debug early problems */
++	init_ohci1394_enable_physical_dma(ohci);
++}
++
++/**
++ * init_ohci1394_controller - Map the registers of the controller and init DMA
++ * This maps the registers of the specified controller and initializes it
++ */
++static inline void __init init_ohci1394_controller(int num, int slot, int func)
++{
++	unsigned long ohci_base;
++	struct ti_ohci ohci;
++
++	printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
++			 " at %02x:%02x.%x\n", num, slot, func);
++
++	ohci_base = read_pci_config(num, slot, func, PCI_BASE_ADDRESS_0+(0<<2))
++						   & PCI_BASE_ADDRESS_MEM_MASK;
++
++	set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
++
++	ohci.registers = (void *)fix_to_virt(FIX_OHCI1394_BASE);
++
++	init_ohci1394_reset_and_init_dma(&ohci);
++}
++
++/**
++ * debug_init_ohci1394_dma - scan for OHCI1394 controllers and init DMA on them
++ * Scans the whole PCI space for OHCI1394 controllers and inits DMA on them
++ */
++void __init init_ohci1394_dma_on_all_controllers(void)
++{
++	int num, slot, func;
 +
- 	if (rq->bio)	/* fs request */
- 		rq->errors = 0;
- 
-+	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
-+		ide_task_t *task = rq->special;
++	if (!early_pci_allowed())
++		return;
 +
-+		if (task->tf_flags & IDE_TFLAG_IO_16BIT)
-+			drive->io_32bit = 0;
++	/* Poor man's PCI discovery, the only thing we can do at early boot */
++	for (num = 0; num < 32; num++) {
++		for (slot = 0; slot < 32; slot++) {
++			for (func = 0; func < 8; func++) {
++				u32 class = read_pci_config(num,slot,func,
++							PCI_CLASS_REVISION);
++				if ((class == 0xffffffff))
++					continue; /* No device at this func */
++
++				if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
++					continue; /* Not an OHCI-1394 device */
++
++				init_ohci1394_controller(num, slot, func);
++				break; /* Assume one controller per device */
++			}
++		}
 +	}
++	printk(KERN_INFO "init_ohci1394_dma: finished initializing OHCI DMA\n");
++}
 +
- 	touch_softlockup_watchdog();
- 
- 	switch (drive->hwif->data_phase) {
-@@ -319,6 +366,8 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
- 		ide_pio_sector(drive, write);
- 		break;
- 	}
++/**
++ * setup_init_ohci1394_early - enables early OHCI1394 DMA initialization
++ */
++static int __init setup_ohci1394_dma(char *opt)
++{
++	if (!strcmp(opt, "early"))
++		init_ohci1394_dma_early = 1;
++	return 0;
++}
 +
-+	drive->io_32bit = saved_io_32bit;
- }
++/* passing ohci1394_dma=early on boot causes early OHCI1394 DMA initialization */
++early_param("ohci1394_dma", setup_ohci1394_dma);
+diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
+index 90dc75b..511e432 100644
+--- a/drivers/ieee1394/nodemgr.c
++++ b/drivers/ieee1394/nodemgr.c
+@@ -727,33 +727,31 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
  
- static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
-@@ -356,40 +405,35 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq,
- 	return ide_error(drive, s, stat);
- }
+ static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
  
--static void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
-+void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat)
++static int __match_ne(struct device *dev, void *data)
++{
++	struct unit_directory *ud;
++	struct node_entry *ne = (struct node_entry *)data;
++
++	ud = container_of(dev, struct unit_directory, unit_dev);
++	return ud->ne == ne;
++}
++
+ static void nodemgr_remove_uds(struct node_entry *ne)
  {
--	HWIF(drive)->cursg = NULL;
+ 	struct device *dev;
+-	struct unit_directory *tmp, *ud;
 -
- 	if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) {
--		ide_task_t *task = rq->special;
-+		u8 err = drive->hwif->INB(IDE_ERROR_REG);
- 
--		if (task->tf_out_flags.all) {
--			u8 err = drive->hwif->INB(IDE_ERROR_REG);
--			ide_end_drive_cmd(drive, stat, err);
--			return;
+-	/* Iteration over nodemgr_ud_class.devices has to be protected by
+-	 * nodemgr_ud_class.sem, but device_unregister() will eventually
+-	 * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
+-	 * release the semaphore, and then unregister the ud. Since this code
+-	 * may be called from other contexts besides the knodemgrds, protect the
+-	 * gap after release of the semaphore by nodemgr_serialize_remove_uds.
++	struct unit_directory *ud;
++
++	/* Use class_find device to iterate the devices. Since this code
++	 * may be called from other contexts besides the knodemgrds,
++	 * protect it by nodemgr_serialize_remove_uds.
+ 	 */
+ 	mutex_lock(&nodemgr_serialize_remove_uds);
+ 	for (;;) {
+-		ud = NULL;
+-		down(&nodemgr_ud_class.sem);
+-		list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+-			tmp = container_of(dev, struct unit_directory,
+-					   unit_dev);
+-			if (tmp->ne == ne) {
+-				ud = tmp;
+-				break;
+-			}
 -		}
-+		ide_end_drive_cmd(drive, stat, err);
-+		return;
+-		up(&nodemgr_ud_class.sem);
+-		if (ud == NULL)
++		dev = class_find_device(&nodemgr_ud_class, ne, __match_ne);
++		if (!dev)
+ 			break;
++		ud = container_of(dev, struct unit_directory, unit_dev);
++		put_device(dev);
+ 		device_unregister(&ud->unit_dev);
+ 		device_unregister(&ud->device);
  	}
- 
- 	if (rq->rq_disk) {
- 		ide_driver_t *drv;
- 
- 		drv = *(ide_driver_t **)rq->rq_disk->private_data;;
--		drv->end_request(drive, 1, rq->hard_nr_sectors);
-+		drv->end_request(drive, 1, rq->nr_sectors);
- 	} else
--		ide_end_request(drive, 1, rq->hard_nr_sectors);
-+		ide_end_request(drive, 1, rq->nr_sectors);
+@@ -882,45 +880,66 @@ fail_alloc:
+ 	return NULL;
  }
  
- /*
-  * Handler for command with PIO data-in phase (Read/Read Multiple).
-  */
--ide_startstop_t task_in_intr (ide_drive_t *drive)
-+static ide_startstop_t task_in_intr(ide_drive_t *drive)
++static int __match_ne_guid(struct device *dev, void *data)
++{
++	struct node_entry *ne;
++	u64 *guid = (u64 *)data;
++
++	ne = container_of(dev, struct node_entry, node_dev);
++	return ne->guid == *guid;
++}
+ 
+ static struct node_entry *find_entry_by_guid(u64 guid)
  {
- 	ide_hwif_t *hwif = drive->hwif;
- 	struct request *rq = HWGROUP(drive)->rq;
- 	u8 stat = hwif->INB(IDE_STATUS_REG);
+ 	struct device *dev;
+-	struct node_entry *ne, *ret_ne = NULL;
+-
+-	down(&nodemgr_ne_class.sem);
+-	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+-		ne = container_of(dev, struct node_entry, node_dev);
++	struct node_entry *ne;
  
- 	/* new way for dealing with premature shared PCI interrupts */
--	if (!OK_STAT(stat, DATA_READY, BAD_R_STAT)) {
-+	if (!OK_STAT(stat, DRQ_STAT, BAD_R_STAT)) {
- 		if (stat & (ERR_STAT | DRQ_STAT))
- 			return task_error(drive, rq, __FUNCTION__, stat);
- 		/* No data yet, so wait for another IRQ. */
-@@ -402,7 +446,7 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
- 	/* If it was the last datablock check status and finish transfer. */
- 	if (!hwif->nleft) {
- 		stat = wait_drive_not_busy(drive);
--		if (!OK_STAT(stat, 0, BAD_R_STAT))
-+		if (!OK_STAT(stat, 0, BAD_STAT))
- 			return task_error(drive, rq, __FUNCTION__, stat);
- 		task_end_request(drive, rq, stat);
- 		return ide_stopped;
-@@ -413,7 +457,6 @@ ide_startstop_t task_in_intr (ide_drive_t *drive)
+-		if (ne->guid == guid) {
+-			ret_ne = ne;
+-			break;
+-		}
+-	}
+-	up(&nodemgr_ne_class.sem);
++	dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid);
++	if (!dev)
++		return NULL;
++	ne = container_of(dev, struct node_entry, node_dev);
++	put_device(dev);
  
- 	return ide_started;
+-	return ret_ne;
++	return ne;
  }
--EXPORT_SYMBOL(task_in_intr);
  
- /*
-  * Handler for command with PIO data-out phase (Write/Write Multiple).
-@@ -443,11 +486,11 @@ static ide_startstop_t task_out_intr (ide_drive_t *drive)
- 	return ide_started;
- }
++struct match_nodeid_param {
++	struct hpsb_host *host;
++	nodeid_t nodeid;
++};
++
++static int __match_ne_nodeid(struct device *dev, void *data)
++{
++	int found = 0;
++	struct node_entry *ne;
++	struct match_nodeid_param *param = (struct match_nodeid_param *)data;
++
++	if (!dev)
++		goto ret;
++	ne = container_of(dev, struct node_entry, node_dev);
++	if (ne->host == param->host && ne->nodeid == param->nodeid)
++		found = 1;
++ret:
++	return found;
++}
  
--ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
-+static ide_startstop_t pre_task_out_intr(ide_drive_t *drive, struct request *rq)
+ static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
+ 					       nodeid_t nodeid)
  {
- 	ide_startstop_t startstop;
- 
--	if (ide_wait_stat(&startstop, drive, DATA_READY,
-+	if (ide_wait_stat(&startstop, drive, DRQ_STAT,
- 			  drive->bad_wstat, WAIT_DRQ)) {
- 		printk(KERN_ERR "%s: no DRQ after issuing %sWRITE%s\n",
- 				drive->name,
-@@ -464,9 +507,8 @@ ide_startstop_t pre_task_out_intr (ide_drive_t *drive, struct request *rq)
- 
- 	return ide_started;
- }
--EXPORT_SYMBOL(pre_task_out_intr);
+ 	struct device *dev;
+-	struct node_entry *ne, *ret_ne = NULL;
++	struct node_entry *ne;
++	struct match_nodeid_param param;
  
--static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf)
-+int ide_raw_taskfile(ide_drive_t *drive, ide_task_t *task, u8 *buf, u16 nsect)
- {
- 	struct request rq;
+-	down(&nodemgr_ne_class.sem);
+-	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+-		ne = container_of(dev, struct node_entry, node_dev);
++	param.host = host;
++	param.nodeid = nodeid;
  
-@@ -481,36 +523,27 @@ static int ide_diag_taskfile(ide_drive_t *drive, ide_task_t *args, unsigned long
- 	 * if we would find a solution to transfer any size.
- 	 * To support special commands like READ LONG.
- 	 */
--	if (args->command_type != IDE_DRIVE_TASK_NO_DATA) {
--		if (data_size == 0)
--			rq.nr_sectors = (args->hobRegister[IDE_NSECTOR_OFFSET] << 8) | args->tfRegister[IDE_NSECTOR_OFFSET];
--		else
--			rq.nr_sectors = data_size / SECTOR_SIZE;
--
--		if (!rq.nr_sectors) {
--			printk(KERN_ERR "%s: in/out command without data\n",
--					drive->name);
--			return -EFAULT;
+-		if (ne->host == host && ne->nodeid == nodeid) {
+-			ret_ne = ne;
+-			break;
 -		}
-+	rq.hard_nr_sectors = rq.nr_sectors = nsect;
-+	rq.hard_cur_sectors = rq.current_nr_sectors = nsect;
+-	}
+-	up(&nodemgr_ne_class.sem);
++	dev = class_find_device(&nodemgr_ne_class, &param, __match_ne_nodeid);
++	if (!dev)
++		return NULL;
++	ne = container_of(dev, struct node_entry, node_dev);
++	put_device(dev);
  
--		rq.hard_nr_sectors = rq.nr_sectors;
--		rq.hard_cur_sectors = rq.current_nr_sectors = rq.nr_sectors;
-+	if (task->tf_flags & IDE_TFLAG_WRITE)
-+		rq.cmd_flags |= REQ_RW;
+-	return ret_ne;
++	return ne;
+ }
  
--		if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
--			rq.cmd_flags |= REQ_RW;
--	}
-+	rq.special = task;
-+	task->rq = &rq;
  
--	rq.special = args;
--	args->rq = &rq;
- 	return ide_do_drive_cmd(drive, &rq, ide_wait);
+@@ -1370,107 +1389,109 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
+ 	}
  }
  
--int ide_raw_taskfile (ide_drive_t *drive, ide_task_t *args, u8 *buf)
-+EXPORT_SYMBOL(ide_raw_taskfile);
-+
-+int ide_no_data_taskfile(ide_drive_t *drive, ide_task_t *task)
+-
+-static void nodemgr_suspend_ne(struct node_entry *ne)
++static int __nodemgr_driver_suspend(struct device *dev, void *data)
  {
--	return ide_diag_taskfile(drive, args, 0, buf);
--}
-+	task->data_phase = TASKFILE_NO_DATA;
+-	struct device *dev;
+ 	struct unit_directory *ud;
+ 	struct device_driver *drv;
++	struct node_entry *ne = (struct node_entry *)data;
+ 	int error;
  
--EXPORT_SYMBOL(ide_raw_taskfile);
-+	return ide_raw_taskfile(drive, task, NULL, 0);
+-	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+-		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
++	ud = container_of(dev, struct unit_directory, unit_dev);
++	if (ud->ne == ne) {
++		drv = get_driver(ud->device.driver);
++		if (drv) {
++			error = 1; /* release if suspend is not implemented */
++			if (drv->suspend) {
++				down(&ud->device.sem);
++				error = drv->suspend(&ud->device, PMSG_SUSPEND);
++				up(&ud->device.sem);
++			}
++			if (error)
++				device_release_driver(&ud->device);
++			put_driver(drv);
++		}
++	}
+ 
+-	ne->in_limbo = 1;
+-	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
++	return 0;
 +}
-+EXPORT_SYMBOL_GPL(ide_no_data_taskfile);
  
- #ifdef CONFIG_IDE_TASK_IOCTL
- int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
-@@ -519,13 +552,12 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
- 	ide_task_t		args;
- 	u8 *outbuf		= NULL;
- 	u8 *inbuf		= NULL;
--	task_ioreg_t *argsptr	= args.tfRegister;
--	task_ioreg_t *hobsptr	= args.hobRegister;
-+	u8 *data_buf		= NULL;
- 	int err			= 0;
- 	int tasksize		= sizeof(struct ide_task_request_s);
- 	unsigned int taskin	= 0;
- 	unsigned int taskout	= 0;
--	u8 io_32bit		= drive->io_32bit;
-+	u16 nsect		= 0;
- 	char __user *buf = (char __user *)arg;
+-	down(&nodemgr_ud_class.sem);
+-	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+-		ud = container_of(dev, struct unit_directory, unit_dev);
+-		if (ud->ne != ne)
+-			continue;
++static int __nodemgr_driver_resume(struct device *dev, void *data)
++{
++	struct unit_directory *ud;
++	struct device_driver *drv;
++	struct node_entry *ne = (struct node_entry *)data;
  
- //	printk("IDE Taskfile ...\n");
-@@ -572,24 +604,52 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
++	ud = container_of(dev, struct unit_directory, unit_dev);
++	if (ud->ne == ne) {
+ 		drv = get_driver(ud->device.driver);
+-		if (!drv)
+-			continue;
+-
+-		error = 1; /* release if suspend is not implemented */
+-		if (drv->suspend) {
+-			down(&ud->device.sem);
+-			error = drv->suspend(&ud->device, PMSG_SUSPEND);
+-			up(&ud->device.sem);
++		if (drv) {
++			if (drv->resume) {
++				down(&ud->device.sem);
++				drv->resume(&ud->device);
++				up(&ud->device.sem);
++			}
++			put_driver(drv);
+ 		}
+-		if (error)
+-			device_release_driver(&ud->device);
+-		put_driver(drv);
  	}
+-	up(&nodemgr_ud_class.sem);
+-}
  
- 	memset(&args, 0, sizeof(ide_task_t));
--	memcpy(argsptr, req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
--	memcpy(hobsptr, req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE);
++	return 0;
++}
  
--	args.tf_in_flags  = req_task->in_flags;
--	args.tf_out_flags = req_task->out_flags;
--	args.data_phase   = req_task->data_phase;
--	args.command_type = req_task->req_cmd;
-+	memcpy(&args.tf_array[0], req_task->hob_ports, HDIO_DRIVE_HOB_HDR_SIZE - 2);
-+	memcpy(&args.tf_array[6], req_task->io_ports, HDIO_DRIVE_TASK_HDR_SIZE);
-+
-+	args.data_phase = req_task->data_phase;
-+
-+	args.tf_flags = IDE_TFLAG_IO_16BIT | IDE_TFLAG_DEVICE |
-+			IDE_TFLAG_IN_TF;
-+	if (drive->addressing == 1)
-+		args.tf_flags |= (IDE_TFLAG_LBA48 | IDE_TFLAG_IN_HOB);
-+
-+	if (req_task->out_flags.all) {
-+		args.tf_flags |= IDE_TFLAG_FLAGGED;
-+
-+		if (req_task->out_flags.b.data)
-+			args.tf_flags |= IDE_TFLAG_OUT_DATA;
-+
-+		if (req_task->out_flags.b.nsector_hob)
-+			args.tf_flags |= IDE_TFLAG_OUT_HOB_NSECT;
-+		if (req_task->out_flags.b.sector_hob)
-+			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAL;
-+		if (req_task->out_flags.b.lcyl_hob)
-+			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAM;
-+		if (req_task->out_flags.b.hcyl_hob)
-+			args.tf_flags |= IDE_TFLAG_OUT_HOB_LBAH;
-+
-+		if (req_task->out_flags.b.error_feature)
-+			args.tf_flags |= IDE_TFLAG_OUT_FEATURE;
-+		if (req_task->out_flags.b.nsector)
-+			args.tf_flags |= IDE_TFLAG_OUT_NSECT;
-+		if (req_task->out_flags.b.sector)
-+			args.tf_flags |= IDE_TFLAG_OUT_LBAL;
-+		if (req_task->out_flags.b.lcyl)
-+			args.tf_flags |= IDE_TFLAG_OUT_LBAM;
-+		if (req_task->out_flags.b.hcyl)
-+			args.tf_flags |= IDE_TFLAG_OUT_LBAH;
-+	} else {
-+		args.tf_flags |= IDE_TFLAG_OUT_TF;
-+		if (args.tf_flags & IDE_TFLAG_LBA48)
-+			args.tf_flags |= IDE_TFLAG_OUT_HOB;
-+	}
-+
-+	if (req_task->in_flags.b.data)
-+		args.tf_flags |= IDE_TFLAG_IN_DATA;
+-static void nodemgr_resume_ne(struct node_entry *ne)
++static void nodemgr_suspend_ne(struct node_entry *ne)
+ {
+-	struct device *dev;
+-	struct unit_directory *ud;
+-	struct device_driver *drv;
++	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
++		   NODE_BUS_ARGS(ne->host, ne->nodeid),
++		   (unsigned long long)ne->guid);
  
--	drive->io_32bit = 0;
- 	switch(req_task->data_phase) {
--		case TASKFILE_OUT_DMAQ:
--		case TASKFILE_OUT_DMA:
--			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
--			break;
--		case TASKFILE_IN_DMAQ:
--		case TASKFILE_IN_DMA:
--			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
--			break;
- 		case TASKFILE_MULTI_OUT:
- 			if (!drive->mult_count) {
- 				/* (hs): give up if multcount is not set */
-@@ -601,9 +661,11 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
- 			}
- 			/* fall through */
- 		case TASKFILE_OUT:
--			args.prehandler = &pre_task_out_intr;
--			args.handler = &task_out_intr;
--			err = ide_diag_taskfile(drive, &args, taskout, outbuf);
-+			/* fall through */
-+		case TASKFILE_OUT_DMAQ:
-+		case TASKFILE_OUT_DMA:
-+			nsect = taskout / SECTOR_SIZE;
-+			data_buf = outbuf;
- 			break;
- 		case TASKFILE_MULTI_IN:
- 			if (!drive->mult_count) {
-@@ -616,22 +678,46 @@ int ide_taskfile_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
- 			}
- 			/* fall through */
- 		case TASKFILE_IN:
--			args.handler = &task_in_intr;
--			err = ide_diag_taskfile(drive, &args, taskin, inbuf);
-+			/* fall through */
-+		case TASKFILE_IN_DMAQ:
-+		case TASKFILE_IN_DMA:
-+			nsect = taskin / SECTOR_SIZE;
-+			data_buf = inbuf;
- 			break;
- 		case TASKFILE_NO_DATA:
--			args.handler = &task_no_data_intr;
--			err = ide_diag_taskfile(drive, &args, 0, NULL);
- 			break;
- 		default:
- 			err = -EFAULT;
- 			goto abort;
- 	}
+-	ne->in_limbo = 0;
+-	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
++	ne->in_limbo = 1;
++	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
  
--	memcpy(req_task->io_ports, &(args.tfRegister), HDIO_DRIVE_TASK_HDR_SIZE);
--	memcpy(req_task->hob_ports, &(args.hobRegister), HDIO_DRIVE_HOB_HDR_SIZE);
--	req_task->in_flags  = args.tf_in_flags;
--	req_task->out_flags = args.tf_out_flags;
-+	if (req_task->req_cmd == IDE_DRIVE_TASK_NO_DATA)
-+		nsect = 0;
-+	else if (!nsect) {
-+		nsect = (args.tf.hob_nsect << 8) | args.tf.nsect;
-+
-+		if (!nsect) {
-+			printk(KERN_ERR "%s: in/out command without data\n",
-+					drive->name);
-+			err = -EFAULT;
-+			goto abort;
-+		}
-+	}
-+
-+	if (req_task->req_cmd == IDE_DRIVE_TASK_RAW_WRITE)
-+		args.tf_flags |= IDE_TFLAG_WRITE;
-+
-+	err = ide_raw_taskfile(drive, &args, data_buf, nsect);
-+
-+	memcpy(req_task->hob_ports, &args.tf_array[0], HDIO_DRIVE_HOB_HDR_SIZE - 2);
-+	memcpy(req_task->io_ports, &args.tf_array[6], HDIO_DRIVE_TASK_HDR_SIZE);
-+
-+	if ((args.tf_flags & IDE_TFLAG_FLAGGED_SET_IN_FLAGS) &&
-+	    req_task->in_flags.all == 0) {
-+		req_task->in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
-+		if (drive->addressing == 1)
-+			req_task->in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
-+	}
+-	down(&nodemgr_ud_class.sem);
+-	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+-		ud = container_of(dev, struct unit_directory, unit_dev);
+-		if (ud->ne != ne)
+-			continue;
++	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend);
++}
  
- 	if (copy_to_user(buf, req_task, tasksize)) {
- 		err = -EFAULT;
-@@ -658,40 +744,25 @@ abort:
+-		drv = get_driver(ud->device.driver);
+-		if (!drv)
+-			continue;
  
- //	printk("IDE Taskfile ioctl ended. rc = %i\n", err);
+-		if (drv->resume) {
+-			down(&ud->device.sem);
+-			drv->resume(&ud->device);
+-			up(&ud->device.sem);
+-		}
+-		put_driver(drv);
+-	}
+-	up(&nodemgr_ud_class.sem);
++static void nodemgr_resume_ne(struct node_entry *ne)
++{
++	ne->in_limbo = 0;
++	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
  
--	drive->io_32bit = io_32bit;
--
- 	return err;
++	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume);
+ 	HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
+ 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
  }
- #endif
  
--int ide_wait_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, u8 feature, u8 sectors, u8 *buf)
--{
--	struct request rq;
--	u8 buffer[4];
--
--	if (!buf)
--		buf = buffer;
--	memset(buf, 0, 4 + SECTOR_WORDS * 4 * sectors);
--	ide_init_drive_cmd(&rq);
--	rq.buffer = buf;
--	*buf++ = cmd;
--	*buf++ = nsect;
--	*buf++ = feature;
--	*buf++ = sectors;
--	return ide_do_drive_cmd(drive, &rq, ide_wait);
--}
 -
- int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+-static void nodemgr_update_pdrv(struct node_entry *ne)
++static int __nodemgr_update_pdrv(struct device *dev, void *data)
  {
--	int err = 0;
--	u8 args[4], *argbuf = args;
--	u8 xfer_rate = 0;
--	int argsize = 4;
-+	u8 *buf = NULL;
-+	int bufsize = 0, err = 0;
-+	u8 args[4], xfer_rate = 0;
- 	ide_task_t tfargs;
-+	struct ide_taskfile *tf = &tfargs.tf;
-+	struct hd_driveid *id = drive->id;
+-	struct device *dev;
+ 	struct unit_directory *ud;
+ 	struct device_driver *drv;
+ 	struct hpsb_protocol_driver *pdrv;
++	struct node_entry *ne = (struct node_entry *)data;
+ 	int error;
  
- 	if (NULL == (void *) arg) {
- 		struct request rq;
+-	down(&nodemgr_ud_class.sem);
+-	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
+-		ud = container_of(dev, struct unit_directory, unit_dev);
+-		if (ud->ne != ne)
+-			continue;
+-
++	ud = container_of(dev, struct unit_directory, unit_dev);
++	if (ud->ne == ne) {
+ 		drv = get_driver(ud->device.driver);
+-		if (!drv)
+-			continue;
+-
+-		error = 0;
+-		pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
+-		if (pdrv->update) {
+-			down(&ud->device.sem);
+-			error = pdrv->update(ud);
+-			up(&ud->device.sem);
++		if (drv) {
++			error = 0;
++			pdrv = container_of(drv, struct hpsb_protocol_driver,
++					    driver);
++			if (pdrv->update) {
++				down(&ud->device.sem);
++				error = pdrv->update(ud);
++				up(&ud->device.sem);
++			}
++			if (error)
++				device_release_driver(&ud->device);
++			put_driver(drv);
+ 		}
+-		if (error)
+-			device_release_driver(&ud->device);
+-		put_driver(drv);
+ 	}
+-	up(&nodemgr_ud_class.sem);
 +
- 		ide_init_drive_cmd(&rq);
-+		rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
++	return 0;
++}
 +
- 		return ide_do_drive_cmd(drive, &rq, ide_wait);
- 	}
++static void nodemgr_update_pdrv(struct node_entry *ne)
++{
++	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv);
+ }
  
-@@ -699,27 +770,46 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
- 		return -EFAULT;
  
- 	memset(&tfargs, 0, sizeof(ide_task_t));
--	tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2];
--	tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3];
--	tfargs.tfRegister[IDE_SECTOR_OFFSET]  = args[1];
--	tfargs.tfRegister[IDE_LCYL_OFFSET]    = 0x00;
--	tfargs.tfRegister[IDE_HCYL_OFFSET]    = 0x00;
--	tfargs.tfRegister[IDE_SELECT_OFFSET]  = 0x00;
--	tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0];
-+	tf->feature = args[2];
-+	if (args[0] == WIN_SMART) {
-+		tf->nsect = args[3];
-+		tf->lbal  = args[1];
-+		tf->lbam  = 0x4f;
-+		tf->lbah  = 0xc2;
-+		tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
-+	} else {
-+		tf->nsect = args[1];
-+		tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
-+				  IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
-+	}
-+	tf->command = args[0];
-+	tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
+@@ -1529,13 +1550,31 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
+ 	put_device(dev);
+ }
  
- 	if (args[3]) {
--		argsize = 4 + (SECTOR_WORDS * 4 * args[3]);
--		argbuf = kzalloc(argsize, GFP_KERNEL);
--		if (argbuf == NULL)
-+		tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
-+		bufsize = SECTOR_WORDS * 4 * args[3];
-+		buf = kzalloc(bufsize, GFP_KERNEL);
-+		if (buf == NULL)
- 			return -ENOMEM;
- 	}
--	if (set_transfer(drive, &tfargs)) {
++struct probe_param {
++	struct host_info *hi;
++	int generation;
++};
 +
-+	if (tf->command == WIN_SETFEATURES &&
-+	    tf->feature == SETFEATURES_XFER &&
-+	    tf->nsect >= XFER_SW_DMA_0 &&
-+	    (id->dma_ultra || id->dma_mword || id->dma_1word)) {
- 		xfer_rate = args[1];
--		if (ide_ata66_check(drive, &tfargs))
-+		if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
-+			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
-+					    "be set\n", drive->name);
- 			goto abort;
-+		}
- 	}
- 
--	err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
-+	err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
++static int __nodemgr_node_probe(struct device *dev, void *data)
++{
++	struct probe_param *param = (struct probe_param *)data;
++	struct node_entry *ne;
 +
-+	args[0] = tf->status;
-+	args[1] = tf->error;
-+	args[2] = tf->nsect;
- 
- 	if (!err && xfer_rate) {
- 		/* active-retuning-calls future */
-@@ -727,142 +817,38 @@ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
- 		ide_driveid_update(drive);
- 	}
- abort:
--	if (copy_to_user((void __user *)arg, argbuf, argsize))
-+	if (copy_to_user((void __user *)arg, &args, 4))
- 		err = -EFAULT;
--	if (argsize > 4)
--		kfree(argbuf);
-+	if (buf) {
-+		if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
-+			err = -EFAULT;
-+		kfree(buf);
-+	}
- 	return err;
- }
++	ne = container_of(dev, struct node_entry, node_dev);
++	if (!ne->needs_probe)
++		nodemgr_probe_ne(param->hi, ne, param->generation);
++	if (ne->needs_probe)
++		nodemgr_probe_ne(param->hi, ne, param->generation);
++	return 0;
++}
  
--static int ide_wait_cmd_task(ide_drive_t *drive, u8 *buf)
--{
--	struct request rq;
--
--	ide_init_drive_cmd(&rq);
--	rq.cmd_type = REQ_TYPE_ATA_TASK;
--	rq.buffer = buf;
--	return ide_do_drive_cmd(drive, &rq, ide_wait);
--}
--
- int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
+ static void nodemgr_node_probe(struct host_info *hi, int generation)
  {
- 	void __user *p = (void __user *)arg;
- 	int err = 0;
--	u8 args[7], *argbuf = args;
--	int argsize = 7;
-+	u8 args[7];
-+	ide_task_t task;
- 
- 	if (copy_from_user(args, p, 7))
- 		return -EFAULT;
--	err = ide_wait_cmd_task(drive, argbuf);
--	if (copy_to_user(p, argbuf, argsize))
--		err = -EFAULT;
--	return err;
--}
+ 	struct hpsb_host *host = hi->host;
+-	struct device *dev;
+-	struct node_entry *ne;
++	struct probe_param param;
  
--/*
-- * NOTICE: This is additions from IBM to provide a discrete interface,
-- * for selective taskregister access operations.  Nice JOB Klaus!!!
-- * Glad to be able to work and co-develop this with you and IBM.
-- */
--ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
--{
--	ide_hwif_t *hwif	= HWIF(drive);
--	task_struct_t *taskfile	= (task_struct_t *) task->tfRegister;
--	hob_struct_t *hobfile	= (hob_struct_t *) task->hobRegister;
-+	memset(&task, 0, sizeof(task));
-+	memcpy(&task.tf_array[7], &args[1], 6);
-+	task.tf.command = args[0];
-+	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
++	param.hi = hi;
++	param.generation = generation;
+ 	/* Do some processing of the nodes we've probed. This pulls them
+ 	 * into the sysfs layer if needed, and can result in processing of
+ 	 * unit-directories, or just updating the node and it's
+@@ -1545,19 +1584,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
+ 	 * while probes are time-consuming. (Well, those probes need some
+ 	 * improvement...) */
  
--	if (task->data_phase == TASKFILE_MULTI_IN ||
--	    task->data_phase == TASKFILE_MULTI_OUT) {
--		if (!drive->mult_count) {
--			printk(KERN_ERR "%s: multimode not set!\n", drive->name);
--			return ide_stopped;
--		}
+-	down(&nodemgr_ne_class.sem);
+-	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+-		ne = container_of(dev, struct node_entry, node_dev);
+-		if (!ne->needs_probe)
+-			nodemgr_probe_ne(hi, ne, generation);
 -	}
--
--	/*
--	 * (ks) Check taskfile in flags.
--	 * If set, then execute as it is defined.
--	 * If not set, then define default settings.
--	 * The default values are:
--	 *	read all taskfile registers (except data)
--	 *	read the hob registers (sector, nsector, lcyl, hcyl)
--	 */
--	if (task->tf_in_flags.all == 0) {
--		task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
--		if (drive->addressing == 1)
--			task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS  << 8);
--        }
--
--	/* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
--	if (IDE_CONTROL_REG)
--		/* clear nIEN */
--		hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
--	SELECT_MASK(drive, 0);
--
--	if (task->tf_out_flags.b.data) {
--		u16 data =  taskfile->data + (hobfile->data << 8);
--		hwif->OUTW(data, IDE_DATA_REG);
+-	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
+-		ne = container_of(dev, struct node_entry, node_dev);
+-		if (ne->needs_probe)
+-			nodemgr_probe_ne(hi, ne, generation);
 -	}
+-	up(&nodemgr_ne_class.sem);
 -
--	/* (ks) send hob registers first */
--	if (task->tf_out_flags.b.nsector_hob)
--		hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
--	if (task->tf_out_flags.b.sector_hob)
--		hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
--	if (task->tf_out_flags.b.lcyl_hob)
--		hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
--	if (task->tf_out_flags.b.hcyl_hob)
--		hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
--
--	/* (ks) Send now the standard registers */
--	if (task->tf_out_flags.b.error_feature)
--		hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
--	/* refers to number of sectors to transfer */
--	if (task->tf_out_flags.b.nsector)
--		hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
--	/* refers to sector offset or start sector */
--	if (task->tf_out_flags.b.sector)
--		hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
--	if (task->tf_out_flags.b.lcyl)
--		hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
--	if (task->tf_out_flags.b.hcyl)
--		hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
--
--        /*
--	 * (ks) In the flagged taskfile approch, we will use all specified
--	 * registers and the register value will not be changed, except the
--	 * select bit (master/slave) in the drive_head register. We must make
--	 * sure that the desired drive is selected.
--	 */
--	hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
--	switch(task->data_phase) {
-+	err = ide_no_data_taskfile(drive, &task);
++	class_for_each_device(&nodemgr_ne_class, &param, __nodemgr_node_probe);
  
--   	        case TASKFILE_OUT_DMAQ:
--		case TASKFILE_OUT_DMA:
--		case TASKFILE_IN_DMAQ:
--		case TASKFILE_IN_DMA:
--			if (!drive->using_dma)
--				break;
-+	args[0] = task.tf.command;
-+	memcpy(&args[1], &task.tf_array[7], 6);
+ 	/* If we had a bus reset while we were scanning the bus, it is
+ 	 * possible that we did not probe all nodes.  In that case, we
+@@ -1757,6 +1784,22 @@ exit:
+ 	return 0;
+ }
  
--			if (!hwif->dma_setup(drive)) {
--				hwif->dma_exec_cmd(drive, taskfile->command);
--				hwif->dma_start(drive);
--				return ide_started;
--			}
--			break;
--
--	        default:
-- 			if (task->handler == NULL)
--				return ide_stopped;
++struct host_iter_param {
++	void *data;
++	int (*cb)(struct hpsb_host *, void *);
++};
++
++static int __nodemgr_for_each_host(struct device *dev, void *data)
++{
++	struct hpsb_host *host;
++	struct host_iter_param *hip = (struct host_iter_param *)data;
++	int error = 0;
++
++	host = container_of(dev, struct hpsb_host, host_dev);
++	error = hip->cb(host, hip->data);
++
++	return error;
++}
+ /**
+  * nodemgr_for_each_host - call a function for each IEEE 1394 host
+  * @data: an address to supply to the callback
+@@ -1771,18 +1814,13 @@ exit:
+  */
+ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
+ {
+-	struct device *dev;
+-	struct hpsb_host *host;
+-	int error = 0;
 -
--			/* Issue the command */
--			if (task->prehandler) {
--				hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
--				ndelay(400);	/* FIXME */
--				return task->prehandler(drive, task->rq);
--			}
--			ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
--			return ide_started;
+-	down(&hpsb_host_class.sem);
+-	list_for_each_entry(dev, &hpsb_host_class.devices, node) {
+-		host = container_of(dev, struct hpsb_host, host_dev);
++	struct host_iter_param hip;
++	int error;
+ 
+-		if ((error = cb(host, data)))
+-			break;
 -	}
-+	if (copy_to_user(p, args, 7))
-+		err = -EFAULT;
+-	up(&hpsb_host_class.sem);
++	hip.cb = cb;
++	hip.data = data;
++	error = class_for_each_device(&hpsb_host_class, &hip,
++				      __nodemgr_for_each_host);
  
--	return ide_stopped;
-+	return err;
+ 	return error;
  }
-diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
-index daffbb9..adeda76 100644
---- a/drivers/ide/ide-timing.h
-+++ b/drivers/ide/ide-timing.h
-@@ -2,8 +2,6 @@
- #define _IDE_TIMING_H
+diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
+index 372c5c1..969de2a 100644
+--- a/drivers/ieee1394/ohci1394.c
++++ b/drivers/ieee1394/ohci1394.c
+@@ -2126,10 +2126,14 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
+ 	list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
+ 		mask = 1 << t->context;
  
- /*
-- * $Id: ide-timing.h,v 1.6 2001/12/23 22:47:56 vojtech Exp $
-- *
-  *  Copyright (c) 1999-2001 Vojtech Pavlik
+-		if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask)
+-			tasklet_schedule(&t->tasklet);
+-		else if (rx_event & mask)
+-			tasklet_schedule(&t->tasklet);
++		if (t->type == OHCI_ISO_TRANSMIT) {
++			if (tx_event & mask)
++				tasklet_schedule(&t->tasklet);
++		} else {
++			/* OHCI_ISO_RECEIVE or OHCI_ISO_MULTICHANNEL_RECEIVE */
++			if (rx_event & mask)
++				tasklet_schedule(&t->tasklet);
++		}
+ 	}
+ 
+ 	spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
+diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
+index cadf047..37e7e10 100644
+--- a/drivers/ieee1394/raw1394.c
++++ b/drivers/ieee1394/raw1394.c
+@@ -858,7 +858,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
+ 	int found = 0, size = 0, rcode = -1;
+ 	struct arm_request_response *arm_req_resp = NULL;
+ 
+-	DBGMSG("arm_read  called by node: %X"
++	DBGMSG("arm_read  called by node: %X "
+ 	       "addr: %4.4x %8.8x length: %Zu", nodeid,
+ 	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+ 	       length);
+@@ -1012,7 +1012,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
+ 	int found = 0, size = 0, rcode = -1, length_conflict = 0;
+ 	struct arm_request_response *arm_req_resp = NULL;
+ 
+-	DBGMSG("arm_write called by node: %X"
++	DBGMSG("arm_write called by node: %X "
+ 	       "addr: %4.4x %8.8x length: %Zu", nodeid,
+ 	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+ 	       length);
+diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
+index b83d254..28e155a 100644
+--- a/drivers/ieee1394/sbp2.c
++++ b/drivers/ieee1394/sbp2.c
+@@ -51,6 +51,7 @@
+  * Grep for inline FIXME comments below.
   */
  
-diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
-index 54943da..ac61360 100644
---- a/drivers/ide/ide.c
-+++ b/drivers/ide/ide.c
-@@ -1,7 +1,6 @@
++#include <linux/blkdev.h>
+ #include <linux/compiler.h>
+ #include <linux/delay.h>
+ #include <linux/device.h>
+@@ -127,17 +128,21 @@ MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
+ 		 "(default = Y, faster but buggy = N)");
+ 
  /*
-- *  linux/drivers/ide/ide.c		Version 7.00beta2	Mar 05 2003
-- *
-- *  Copyright (C) 1994-1998  Linus Torvalds & authors (see below)
-+ *  Copyright (C) 1994-1998	    Linus Torvalds & authors (see below)
-+ *  Copyrifht (C) 2003-2005, 2007   Bartlomiej Zolnierkiewicz
+- * Bump up max_sectors if you'd like to support very large sized
+- * transfers. Please note that some older sbp2 bridge chips are broken for
+- * transfers greater or equal to 128KB.  Default is a value of 255
+- * sectors, or just under 128KB (at 512 byte sector size). I can note that
+- * the Oxsemi sbp2 chipsets have no problems supporting very large
+- * transfer sizes.
++ * Adjust max_sectors if you'd like to influence how many sectors each SCSI
++ * command can transfer at most. Please note that some older SBP-2 bridge
++ * chips are broken for transfers greater or equal to 128KB, therefore
++ * max_sectors used to be a safe 255 sectors for many years. We now have a
++ * default of 0 here which means that we let the SCSI stack choose a limit.
++ *
++ * The SBP2_WORKAROUND_128K_MAX_TRANS flag, if set either in the workarounds
++ * module parameter or in the sbp2_workarounds_table[], will override the
++ * value of max_sectors. We should use sbp2_workarounds_table[] to cover any
++ * bridge chip which becomes known to need the 255 sectors limit.
   */
+-static int sbp2_max_sectors = SBP2_MAX_SECTORS;
++static int sbp2_max_sectors;
+ module_param_named(max_sectors, sbp2_max_sectors, int, 0444);
+ MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
+-		 "(default = " __stringify(SBP2_MAX_SECTORS) ")");
++		 "(default = 0 = use SCSI stack's default)");
  
  /*
-@@ -46,7 +45,6 @@
-  */
+  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
+@@ -1451,7 +1456,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ 				     struct sbp2_fwhost_info *hi,
+ 				     struct sbp2_command_info *cmd,
+ 				     unsigned int scsi_use_sg,
+-				     struct scatterlist *sgpnt,
++				     struct scatterlist *sg,
+ 				     u32 orb_direction,
+ 				     enum dma_data_direction dma_dir)
+ {
+@@ -1460,13 +1465,12 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ 	orb->misc |= ORB_SET_DIRECTION(orb_direction);
  
- #define	REVISION	"Revision: 7.00alpha2"
--#define	VERSION		"Id: ide.c 7.00a2 20020906"
+ 	/* special case if only one element (and less than 64KB in size) */
+-	if ((scsi_use_sg == 1) &&
+-	    (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
++	if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) {
  
- #define _IDE_C			/* Tell ide.h it's really us */
+-		cmd->dma_size = sgpnt[0].length;
++		cmd->dma_size = sg->length;
+ 		cmd->dma_type = CMD_DMA_PAGE;
+ 		cmd->cmd_dma = dma_map_page(hi->host->device.parent,
+-					    sg_page(&sgpnt[0]), sgpnt[0].offset,
++					    sg_page(sg), sg->offset,
+ 					    cmd->dma_size, cmd->dma_dir);
  
-@@ -95,7 +93,7 @@ DEFINE_MUTEX(ide_cfg_mtx);
-  __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
+ 		orb->data_descriptor_lo = cmd->cmd_dma;
+@@ -1477,11 +1481,11 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ 						&cmd->scatter_gather_element[0];
+ 		u32 sg_count, sg_len;
+ 		dma_addr_t sg_addr;
+-		int i, count = dma_map_sg(hi->host->device.parent, sgpnt,
++		int i, count = dma_map_sg(hi->host->device.parent, sg,
+ 					  scsi_use_sg, dma_dir);
  
- #ifdef CONFIG_IDEPCI_PCIBUS_ORDER
--static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
-+int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
- #endif
+ 		cmd->dma_size = scsi_use_sg;
+-		cmd->sge_buffer = sgpnt;
++		cmd->sge_buffer = sg;
  
- int noautodma = 0;
-@@ -116,7 +114,7 @@ EXPORT_SYMBOL(ide_hwifs);
- /*
-  * Do not even *think* about calling this!
-  */
--static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
-+void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
+ 		/* use page tables (s/g) */
+ 		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
+@@ -1489,9 +1493,9 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
+ 
+ 		/* loop through and fill out our SBP-2 page tables
+ 		 * (and split up anything too large) */
+-		for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
+-			sg_len = sg_dma_len(sgpnt);
+-			sg_addr = sg_dma_address(sgpnt);
++		for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) {
++			sg_len = sg_dma_len(sg);
++			sg_addr = sg_dma_address(sg);
+ 			while (sg_len) {
+ 				sg_element[sg_count].segment_base_lo = sg_addr;
+ 				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
+@@ -1521,11 +1525,10 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
+ 				    unchar *scsi_cmd,
+ 				    unsigned int scsi_use_sg,
+ 				    unsigned int scsi_request_bufflen,
+-				    void *scsi_request_buffer,
++				    struct scatterlist *sg,
+ 				    enum dma_data_direction dma_dir)
  {
- 	unsigned int unit;
+ 	struct sbp2_fwhost_info *hi = lu->hi;
+-	struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
+ 	struct sbp2_command_orb *orb = &cmd->command_orb;
+ 	u32 orb_direction;
  
-@@ -159,6 +157,7 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
- 		init_completion(&drive->gendev_rel_comp);
- 	}
- }
-+EXPORT_SYMBOL_GPL(ide_init_port_data);
+@@ -1560,7 +1563,7 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
+ 		orb->data_descriptor_lo = 0x0;
+ 		orb->misc |= ORB_SET_DIRECTION(1);
+ 	} else
+-		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
++		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sg,
+ 					 orb_direction, dma_dir);
  
- static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
+ 	sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
+@@ -1650,7 +1653,6 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
+ 			     void (*done)(struct scsi_cmnd *))
  {
-@@ -177,8 +176,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index)
- #endif
- }
+ 	unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
+-	unsigned int request_bufflen = scsi_bufflen(SCpnt);
+ 	struct sbp2_command_info *cmd;
  
--extern void ide_arm_init(void);
--
- /*
-  * init_ide_data() sets reasonable default values into all fields
-  * of all instances of the hwifs and drives, but only on the first call.
-@@ -210,16 +207,13 @@ static void __init init_ide_data (void)
- 	/* Initialise all interface structures */
- 	for (index = 0; index < MAX_HWIFS; ++index) {
- 		hwif = &ide_hwifs[index];
--		init_hwif_data(hwif, index);
-+		ide_init_port_data(hwif, index);
- 		init_hwif_default(hwif, index);
- #if !defined(CONFIG_PPC32) || !defined(CONFIG_PCI)
- 		hwif->irq =
- 			ide_init_default_irq(hwif->io_ports[IDE_DATA_OFFSET]);
- #endif
- 	}
--#ifdef CONFIG_IDE_ARM
--	ide_arm_init();
--#endif
- }
+ 	cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
+@@ -1658,7 +1660,7 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
+ 		return -EIO;
  
- /**
-@@ -246,22 +240,12 @@ static int ide_system_bus_speed(void)
- #define pci_default 0
- #endif /* CONFIG_PCI */
+ 	sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
+-				request_bufflen, scsi_sglist(SCpnt),
++				scsi_bufflen(SCpnt), scsi_sglist(SCpnt),
+ 				SCpnt->sc_data_direction);
+ 	sbp2_link_orb_command(lu, cmd);
  
--	if (!system_bus_speed) {
--		if (idebus_parameter) {
--			/* user supplied value */
--			system_bus_speed = idebus_parameter;
--		} else if (pci_dev_present(pci_default)) {
--			/* safe default value for PCI */
--			system_bus_speed = 33;
--		} else {
--			/* safe default value for VESA and PCI */
--			system_bus_speed = 50;
--		}
--		printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
--			"for PIO modes%s\n", system_bus_speed,
--			idebus_parameter ? "" : "; override with idebus=xx");
--	}
--	return system_bus_speed;
-+	/* user supplied value */
-+	if (idebus_parameter)
-+		return idebus_parameter;
+@@ -1963,6 +1965,12 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
+ 	lu->sdev = sdev;
+ 	sdev->allow_restart = 1;
+ 
++	/*
++	 * Update the dma alignment (minimum alignment requirements for
++	 * start and end of DMA transfers) to be a sector
++	 */
++	blk_queue_update_dma_alignment(sdev->request_queue, 511);
 +
-+	/* safe default value for PCI or VESA and PCI*/
-+	return pci_dev_present(pci_default) ? 33 : 50;
+ 	if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
+ 		sdev->inquiry_len = 36;
+ 	return 0;
+@@ -1981,6 +1989,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
+ 		sdev->skip_ms_page_8 = 1;
+ 	if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
+ 		sdev->fix_capacity = 1;
++	if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
++		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
+ 	return 0;
  }
  
- ide_hwif_t * ide_find_port(unsigned long base)
-@@ -409,13 +393,12 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
- 	hwif->chipset			= tmp_hwif->chipset;
- 	hwif->hold			= tmp_hwif->hold;
+@@ -2087,9 +2097,6 @@ static int sbp2_module_init(void)
+ 		sbp2_shost_template.cmd_per_lun = 1;
+ 	}
  
-+	hwif->dev			= tmp_hwif->dev;
-+
- #ifdef CONFIG_BLK_DEV_IDEPCI
--	hwif->pci_dev			= tmp_hwif->pci_dev;
- 	hwif->cds			= tmp_hwif->cds;
- #endif
+-	if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
+-	    (sbp2_max_sectors * 512) > (128 * 1024))
+-		sbp2_max_sectors = 128 * 1024 / 512;
+ 	sbp2_shost_template.max_sectors = sbp2_max_sectors;
  
--	hwif->fixup			= tmp_hwif->fixup;
--
- 	hwif->set_pio_mode		= tmp_hwif->set_pio_mode;
- 	hwif->set_dma_mode		= tmp_hwif->set_dma_mode;
- 	hwif->mdma_filter		= tmp_hwif->mdma_filter;
-@@ -424,7 +407,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
- 	hwif->reset_poll		= tmp_hwif->reset_poll;
- 	hwif->pre_reset			= tmp_hwif->pre_reset;
- 	hwif->resetproc			= tmp_hwif->resetproc;
--	hwif->intrproc			= tmp_hwif->intrproc;
- 	hwif->maskproc			= tmp_hwif->maskproc;
- 	hwif->quirkproc			= tmp_hwif->quirkproc;
- 	hwif->busproc			= tmp_hwif->busproc;
-@@ -434,16 +416,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
- 	hwif->atapi_input_bytes		= tmp_hwif->atapi_input_bytes;
- 	hwif->atapi_output_bytes	= tmp_hwif->atapi_output_bytes;
+ 	hpsb_register_highlevel(&sbp2_highlevel);
+diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
+index 333a4bb..d2ecb0d 100644
+--- a/drivers/ieee1394/sbp2.h
++++ b/drivers/ieee1394/sbp2.h
+@@ -222,7 +222,6 @@ struct sbp2_status_block {
+  */
  
-+	hwif->dma_host_set		= tmp_hwif->dma_host_set;
- 	hwif->dma_setup			= tmp_hwif->dma_setup;
- 	hwif->dma_exec_cmd		= tmp_hwif->dma_exec_cmd;
- 	hwif->dma_start			= tmp_hwif->dma_start;
- 	hwif->ide_dma_end		= tmp_hwif->ide_dma_end;
--	hwif->ide_dma_on		= tmp_hwif->ide_dma_on;
--	hwif->dma_off_quietly		= tmp_hwif->dma_off_quietly;
- 	hwif->ide_dma_test_irq		= tmp_hwif->ide_dma_test_irq;
- 	hwif->ide_dma_clear_irq		= tmp_hwif->ide_dma_clear_irq;
--	hwif->dma_host_on		= tmp_hwif->dma_host_on;
--	hwif->dma_host_off		= tmp_hwif->dma_host_off;
- 	hwif->dma_lost_irq		= tmp_hwif->dma_lost_irq;
- 	hwif->dma_timeout		= tmp_hwif->dma_timeout;
+ #define SBP2_MAX_SG_ELEMENT_LENGTH		0xf000
+-#define SBP2_MAX_SECTORS			255
+ /* There is no real limitation of the queue depth (i.e. length of the linked
+  * list of command ORBs) at the target. The chosen depth is merely an
+  * implementation detail of the sbp2 driver. */
+diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
+index a193dfb..a5dc78a 100644
+--- a/drivers/infiniband/Kconfig
++++ b/drivers/infiniband/Kconfig
+@@ -44,8 +44,8 @@ source "drivers/infiniband/hw/ipath/Kconfig"
+ source "drivers/infiniband/hw/ehca/Kconfig"
+ source "drivers/infiniband/hw/amso1100/Kconfig"
+ source "drivers/infiniband/hw/cxgb3/Kconfig"
+-
+ source "drivers/infiniband/hw/mlx4/Kconfig"
++source "drivers/infiniband/hw/nes/Kconfig"
+ 
+ source "drivers/infiniband/ulp/ipoib/Kconfig"
+ 
+diff --git a/drivers/infiniband/Makefile b/drivers/infiniband/Makefile
+index 75f325e..ed35e44 100644
+--- a/drivers/infiniband/Makefile
++++ b/drivers/infiniband/Makefile
+@@ -5,6 +5,7 @@ obj-$(CONFIG_INFINIBAND_EHCA)		+= hw/ehca/
+ obj-$(CONFIG_INFINIBAND_AMSO1100)	+= hw/amso1100/
+ obj-$(CONFIG_INFINIBAND_CXGB3)		+= hw/cxgb3/
+ obj-$(CONFIG_MLX4_INFINIBAND)		+= hw/mlx4/
++obj-$(CONFIG_INFINIBAND_NES)		+= hw/nes/
+ obj-$(CONFIG_INFINIBAND_IPOIB)		+= ulp/ipoib/
+ obj-$(CONFIG_INFINIBAND_SRP)		+= ulp/srp/
+ obj-$(CONFIG_INFINIBAND_ISER)		+= ulp/iser/
+diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
+index 5381c80..a58ad8a 100644
+--- a/drivers/infiniband/core/addr.c
++++ b/drivers/infiniband/core/addr.c
+@@ -110,7 +110,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
+ 	__be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+ 	int ret;
  
-@@ -468,7 +447,6 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
- #endif
+-	dev = ip_dev_find(ip);
++	dev = ip_dev_find(&init_net, ip);
+ 	if (!dev)
+ 		return -EADDRNOTAVAIL;
  
- 	hwif->dma_base			= tmp_hwif->dma_base;
--	hwif->dma_master		= tmp_hwif->dma_master;
- 	hwif->dma_command		= tmp_hwif->dma_command;
- 	hwif->dma_vendor1		= tmp_hwif->dma_vendor1;
- 	hwif->dma_status		= tmp_hwif->dma_status;
-@@ -483,9 +461,46 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
- 	hwif->hwif_data			= tmp_hwif->hwif_data;
- }
+@@ -158,7 +158,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
  
-+void ide_remove_port_from_hwgroup(ide_hwif_t *hwif)
-+{
-+	ide_hwgroup_t *hwgroup = hwif->hwgroup;
-+
-+	spin_lock_irq(&ide_lock);
-+	/*
-+	 * Remove us from the hwgroup, and free
-+	 * the hwgroup if we were the only member
-+	 */
-+	if (hwif->next == hwif) {
-+		BUG_ON(hwgroup->hwif != hwif);
-+		kfree(hwgroup);
-+	} else {
-+		/* There is another interface in hwgroup.
-+		 * Unlink us, and set hwgroup->drive and ->hwif to
-+		 * something sane.
-+		 */
-+		ide_hwif_t *g = hwgroup->hwif;
-+
-+		while (g->next != hwif)
-+			g = g->next;
-+		g->next = hwif->next;
-+		if (hwgroup->hwif == hwif) {
-+			/* Chose a random hwif for hwgroup->hwif.
-+			 * It's guaranteed that there are no drives
-+			 * left in the hwgroup.
-+			 */
-+			BUG_ON(hwgroup->drive != NULL);
-+			hwgroup->hwif = g;
-+		}
-+		BUG_ON(hwgroup->hwif == hwif);
-+	}
-+	spin_unlock_irq(&ide_lock);
-+}
-+
- /**
-  *	ide_unregister		-	free an IDE interface
-  *	@index: index of interface (will change soon to a pointer)
-+ *	@init_default: init default hwif flag
-+ *	@restore: restore hwif flag
-  *
-  *	Perform the final unregister of an IDE interface. At the moment
-  *	we don't refcount interfaces so this will also get split up.
-@@ -505,7 +520,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
-  *	This is raving bonkers.
-  */
+ 	memset(&fl, 0, sizeof fl);
+ 	fl.nl_u.ip4_u.daddr = dst_ip;
+-	if (ip_route_output_key(&rt, &fl))
++	if (ip_route_output_key(&init_net, &rt, &fl))
+ 		return;
  
--void ide_unregister(unsigned int index)
-+void ide_unregister(unsigned int index, int init_default, int restore)
- {
- 	ide_drive_t *drive;
- 	ide_hwif_t *hwif, *g;
-@@ -550,43 +565,8 @@ void ide_unregister(unsigned int index)
- 	if (irq_count == 1)
- 		free_irq(hwif->irq, hwgroup);
+ 	neigh_event_send(rt->u.dst.neighbour, NULL);
+@@ -179,7 +179,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
+ 	memset(&fl, 0, sizeof fl);
+ 	fl.nl_u.ip4_u.daddr = dst_ip;
+ 	fl.nl_u.ip4_u.saddr = src_ip;
+-	ret = ip_route_output_key(&rt, &fl);
++	ret = ip_route_output_key(&init_net, &rt, &fl);
+ 	if (ret)
+ 		goto out;
  
--	spin_lock_irq(&ide_lock);
--	/*
--	 * Note that we only release the standard ports,
--	 * and do not even try to handle any extra ports
--	 * allocated for weird IDE interface chipsets.
--	 */
--	ide_hwif_release_regions(hwif);
--
--	/*
--	 * Remove us from the hwgroup, and free
--	 * the hwgroup if we were the only member
--	 */
--	if (hwif->next == hwif) {
--		BUG_ON(hwgroup->hwif != hwif);
--		kfree(hwgroup);
--	} else {
--		/* There is another interface in hwgroup.
--		 * Unlink us, and set hwgroup->drive and ->hwif to
--		 * something sane.
--		 */
--		g = hwgroup->hwif;
--		while (g->next != hwif)
--			g = g->next;
--		g->next = hwif->next;
--		if (hwgroup->hwif == hwif) {
--			/* Chose a random hwif for hwgroup->hwif.
--			 * It's guaranteed that there are no drives
--			 * left in the hwgroup.
--			 */
--			BUG_ON(hwgroup->drive != NULL);
--			hwgroup->hwif = g;
--		}
--		BUG_ON(hwgroup->hwif == hwif);
--	}
-+	ide_remove_port_from_hwgroup(hwif);
+@@ -261,15 +261,15 @@ static int addr_resolve_local(struct sockaddr_in *src_in,
+ 	__be32 dst_ip = dst_in->sin_addr.s_addr;
+ 	int ret;
  
--	/* More messed up locking ... */
--	spin_unlock_irq(&ide_lock);
- 	device_unregister(&hwif->gendev);
- 	wait_for_completion(&hwif->gendev_rel_comp);
+-	dev = ip_dev_find(dst_ip);
++	dev = ip_dev_find(&init_net, dst_ip);
+ 	if (!dev)
+ 		return -EADDRNOTAVAIL;
  
-@@ -602,7 +582,6 @@ void ide_unregister(unsigned int index)
- 		(void) ide_release_dma(hwif);
+-	if (ZERONET(src_ip)) {
++	if (ipv4_is_zeronet(src_ip)) {
+ 		src_in->sin_family = dst_in->sin_family;
+ 		src_in->sin_addr.s_addr = dst_ip;
+ 		ret = rdma_copy_addr(addr, dev, dev->dev_addr);
+-	} else if (LOOPBACK(src_ip)) {
++	} else if (ipv4_is_loopback(src_ip)) {
+ 		ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
+ 		if (!ret)
+ 			memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
+diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
+index 2e39236..638b727 100644
+--- a/drivers/infiniband/core/cm.c
++++ b/drivers/infiniband/core/cm.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2004-2006 Intel Corporation.  All rights reserved.
++ * Copyright (c) 2004-2007 Intel Corporation.  All rights reserved.
+  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
+  * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
+  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+@@ -37,12 +37,14 @@
  
- 		hwif->dma_base = 0;
--		hwif->dma_master = 0;
- 		hwif->dma_command = 0;
- 		hwif->dma_vendor1 = 0;
- 		hwif->dma_status = 0;
-@@ -613,14 +592,24 @@ void ide_unregister(unsigned int index)
- 		hwif->extra_ports = 0;
- 	}
+ #include <linux/completion.h>
+ #include <linux/dma-mapping.h>
++#include <linux/device.h>
+ #include <linux/err.h>
+ #include <linux/idr.h>
+ #include <linux/interrupt.h>
+ #include <linux/random.h>
+ #include <linux/rbtree.h>
+ #include <linux/spinlock.h>
++#include <linux/sysfs.h>
+ #include <linux/workqueue.h>
  
-+	/*
-+	 * Note that we only release the standard ports,
-+	 * and do not even try to handle any extra ports
-+	 * allocated for weird IDE interface chipsets.
-+	 */
-+	ide_hwif_release_regions(hwif);
-+
- 	/* copy original settings */
- 	tmp_hwif = *hwif;
+ #include <rdma/ib_cache.h>
+@@ -78,17 +80,94 @@ static struct ib_cm {
+ 	struct workqueue_struct *wq;
+ } cm;
  
- 	/* restore hwif data to pristine status */
--	init_hwif_data(hwif, index);
--	init_hwif_default(hwif, index);
-+	ide_init_port_data(hwif, index);
++/* Counter indexes ordered by attribute ID */
++enum {
++	CM_REQ_COUNTER,
++	CM_MRA_COUNTER,
++	CM_REJ_COUNTER,
++	CM_REP_COUNTER,
++	CM_RTU_COUNTER,
++	CM_DREQ_COUNTER,
++	CM_DREP_COUNTER,
++	CM_SIDR_REQ_COUNTER,
++	CM_SIDR_REP_COUNTER,
++	CM_LAP_COUNTER,
++	CM_APR_COUNTER,
++	CM_ATTR_COUNT,
++	CM_ATTR_ID_OFFSET = 0x0010,
++};
 +
-+	if (init_default)
-+		init_hwif_default(hwif, index);
- 
--	ide_hwif_restore(hwif, &tmp_hwif);
-+	if (restore)
-+		ide_hwif_restore(hwif, &tmp_hwif);
- 
- abort:
- 	spin_unlock_irq(&ide_lock);
-@@ -683,70 +672,86 @@ void ide_setup_ports (	hw_regs_t *hw,
-  */
- }
- 
-+void ide_init_port_hw(ide_hwif_t *hwif, hw_regs_t *hw)
-+{
-+	memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
-+	hwif->irq = hw->irq;
-+	hwif->noprobe = 0;
-+	hwif->chipset = hw->chipset;
-+	hwif->gendev.parent = hw->dev;
-+	hwif->ack_intr = hw->ack_intr;
-+}
-+EXPORT_SYMBOL_GPL(ide_init_port_hw);
++enum {
++	CM_XMIT,
++	CM_XMIT_RETRIES,
++	CM_RECV,
++	CM_RECV_DUPLICATES,
++	CM_COUNTER_GROUPS
++};
 +
-+ide_hwif_t *ide_deprecated_find_port(unsigned long base)
-+{
-+	ide_hwif_t *hwif;
-+	int i;
++static char const counter_group_names[CM_COUNTER_GROUPS]
++				     [sizeof("cm_rx_duplicates")] = {
++	"cm_tx_msgs", "cm_tx_retries",
++	"cm_rx_msgs", "cm_rx_duplicates"
++};
 +
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		hwif = &ide_hwifs[i];
-+		if (hwif->io_ports[IDE_DATA_OFFSET] == base)
-+			goto found;
-+	}
++struct cm_counter_group {
++	struct kobject obj;
++	atomic_long_t counter[CM_ATTR_COUNT];
++};
 +
-+	for (i = 0; i < MAX_HWIFS; i++) {
-+		hwif = &ide_hwifs[i];
-+		if (hwif->hold)
-+			continue;
-+		if (!hwif->present && hwif->mate == NULL)
-+			goto found;
-+	}
++struct cm_counter_attribute {
++	struct attribute attr;
++	int index;
++};
 +
-+	hwif = NULL;
-+found:
-+	return hwif;
++#define CM_COUNTER_ATTR(_name, _index) \
++struct cm_counter_attribute cm_##_name##_counter_attr = { \
++	.attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
++	.index = _index \
 +}
-+EXPORT_SYMBOL_GPL(ide_deprecated_find_port);
-+
- /**
-  *	ide_register_hw		-	register IDE interface
-  *	@hw: hardware registers
-- *	@fixup: fixup function
-- *	@initializing: set while initializing built-in drivers
-+ *	@quirkproc: quirkproc function
-  *	@hwifp: pointer to returned hwif
-  *
-  *	Register an IDE interface, specifying exactly the registers etc.
-- *	Set init=1 iff calling before probes have taken place.
-  *
-  *	Returns -1 on error.
-  */
- 
--int ide_register_hw(hw_regs_t *hw, void (*fixup)(ide_hwif_t *),
--		    int initializing, ide_hwif_t **hwifp)
-+int ide_register_hw(hw_regs_t *hw, void (*quirkproc)(ide_drive_t *),
-+		    ide_hwif_t **hwifp)
- {
- 	int index, retry = 1;
- 	ide_hwif_t *hwif;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- 
- 	do {
--		for (index = 0; index < MAX_HWIFS; ++index) {
--			hwif = &ide_hwifs[index];
--			if (hwif->io_ports[IDE_DATA_OFFSET] == hw->io_ports[IDE_DATA_OFFSET])
--				goto found;
--		}
--		for (index = 0; index < MAX_HWIFS; ++index) {
--			hwif = &ide_hwifs[index];
--			if (hwif->hold)
--				continue;
--			if ((!hwif->present && !hwif->mate && !initializing) ||
--			    (!hwif->io_ports[IDE_DATA_OFFSET] && initializing))
--				goto found;
--		}
-+		hwif = ide_deprecated_find_port(hw->io_ports[IDE_DATA_OFFSET]);
-+		index = hwif->index;
-+		if (hwif)
-+			goto found;
- 		for (index = 0; index < MAX_HWIFS; index++)
--			ide_unregister(index);
-+			ide_unregister(index, 1, 1);
- 	} while (retry--);
- 	return -1;
- found:
- 	if (hwif->present)
--		ide_unregister(index);
--	else if (!hwif->hold) {
--		init_hwif_data(hwif, index);
--		init_hwif_default(hwif, index);
--	}
--	if (hwif->present)
--		return -1;
--	memcpy(hwif->io_ports, hw->io_ports, sizeof(hwif->io_ports));
--	hwif->irq = hw->irq;
--	hwif->noprobe = 0;
--	hwif->fixup = fixup;
--	hwif->chipset = hw->chipset;
--	hwif->gendev.parent = hw->dev;
--	hwif->ack_intr = hw->ack_intr;
-+		ide_unregister(index, 0, 1);
-+	else if (!hwif->hold)
-+		ide_init_port_data(hwif, index);
- 
--	if (initializing == 0) {
--		u8 idx[4] = { index, 0xff, 0xff, 0xff };
-+	ide_init_port_hw(hwif, hw);
-+	hwif->quirkproc = quirkproc;
- 
--		ide_device_add(idx);
--	}
-+	idx[0] = index;
 +
-+	ide_device_add(idx, NULL);
- 
- 	if (hwifp)
- 		*hwifp = hwif;
- 
--	return (initializing || hwif->present) ? index : -1;
-+	return hwif->present ? index : -1;
- }
- 
- EXPORT_SYMBOL(ide_register_hw);
-@@ -804,10 +809,6 @@ int set_io_32bit(ide_drive_t *drive, int arg)
- 		return -EBUSY;
- 
- 	drive->io_32bit = arg;
--#ifdef CONFIG_BLK_DEV_DTC2278
--	if (HWIF(drive)->chipset == ide_dtc2278)
--		HWIF(drive)->drives[!drive->select.b.unit].io_32bit = arg;
--#endif /* CONFIG_BLK_DEV_DTC2278 */
- 
- 	spin_unlock_irq(&ide_lock);
- 
-@@ -839,7 +840,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
- 	if (!drive->id || !(drive->id->capability & 1))
- 		goto out;
- 
--	if (hwif->ide_dma_on == NULL)
-+	if (hwif->dma_host_set == NULL)
- 		goto out;
- 
- 	err = -EBUSY;
-@@ -854,8 +855,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
- 	err = 0;
- 
- 	if (arg) {
--		hwif->dma_off_quietly(drive);
--		if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
-+		if (ide_set_dma(drive))
- 			err = -EIO;
- 	} else
- 		ide_dma_off(drive);
-@@ -888,7 +888,10 @@ int set_pio_mode(ide_drive_t *drive, int arg)
- 
- 	if (drive->special.b.set_tune)
- 		return -EBUSY;
++static CM_COUNTER_ATTR(req, CM_REQ_COUNTER);
++static CM_COUNTER_ATTR(mra, CM_MRA_COUNTER);
++static CM_COUNTER_ATTR(rej, CM_REJ_COUNTER);
++static CM_COUNTER_ATTR(rep, CM_REP_COUNTER);
++static CM_COUNTER_ATTR(rtu, CM_RTU_COUNTER);
++static CM_COUNTER_ATTR(dreq, CM_DREQ_COUNTER);
++static CM_COUNTER_ATTR(drep, CM_DREP_COUNTER);
++static CM_COUNTER_ATTR(sidr_req, CM_SIDR_REQ_COUNTER);
++static CM_COUNTER_ATTR(sidr_rep, CM_SIDR_REP_COUNTER);
++static CM_COUNTER_ATTR(lap, CM_LAP_COUNTER);
++static CM_COUNTER_ATTR(apr, CM_APR_COUNTER);
 +
- 	ide_init_drive_cmd(&rq);
-+	rq.cmd_type = REQ_TYPE_ATA_TASKFILE;
++static struct attribute *cm_counter_default_attrs[] = {
++	&cm_req_counter_attr.attr,
++	&cm_mra_counter_attr.attr,
++	&cm_rej_counter_attr.attr,
++	&cm_rep_counter_attr.attr,
++	&cm_rtu_counter_attr.attr,
++	&cm_dreq_counter_attr.attr,
++	&cm_drep_counter_attr.attr,
++	&cm_sidr_req_counter_attr.attr,
++	&cm_sidr_rep_counter_attr.attr,
++	&cm_lap_counter_attr.attr,
++	&cm_apr_counter_attr.attr,
++	NULL
++};
 +
- 	drive->tune_req = (u8) arg;
- 	drive->special.b.set_tune = 1;
- 	(void) ide_do_drive_cmd(drive, &rq, ide_wait);
-@@ -920,7 +923,7 @@ static int set_unmaskirq(ide_drive_t *drive, int arg)
+ struct cm_port {
+ 	struct cm_device *cm_dev;
+ 	struct ib_mad_agent *mad_agent;
++	struct kobject port_obj;
+ 	u8 port_num;
++	struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
+ };
  
- int system_bus_clock (void)
- {
--	return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
-+	return system_bus_speed;
- }
+ struct cm_device {
+ 	struct list_head list;
+ 	struct ib_device *device;
++	struct kobject dev_obj;
+ 	u8 ack_delay;
+-	struct cm_port port[0];
++	struct cm_port *port[0];
+ };
  
- EXPORT_SYMBOL(system_bus_clock);
-@@ -1032,11 +1035,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
- 		case HDIO_GET_NICE:
- 			return put_user(drive->dsc_overlap	<<	IDE_NICE_DSC_OVERLAP	|
- 					drive->atapi_overlap	<<	IDE_NICE_ATAPI_OVERLAP	|
--					drive->nice0		<< 	IDE_NICE_0		|
--					drive->nice1		<<	IDE_NICE_1		|
--					drive->nice2		<<	IDE_NICE_2,
-+					drive->nice1 << IDE_NICE_1,
- 					(long __user *) arg);
--
- #ifdef CONFIG_IDE_TASK_IOCTL
- 		case HDIO_DRIVE_TASKFILE:
- 		        if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
-@@ -1070,14 +1070,14 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
- 			ide_init_hwif_ports(&hw, (unsigned long) args[0],
- 					    (unsigned long) args[1], NULL);
- 			hw.irq = args[2];
--			if (ide_register_hw(&hw, NULL, 0, NULL) == -1)
-+			if (ide_register_hw(&hw, NULL, NULL) == -1)
- 				return -EIO;
- 			return 0;
+ struct cm_av {
+@@ -278,7 +357,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
+ 	list_for_each_entry(cm_dev, &cm.device_list, list) {
+ 		if (!ib_find_cached_gid(cm_dev->device, &path->sgid,
+ 					&p, NULL)) {
+-			port = &cm_dev->port[p-1];
++			port = cm_dev->port[p-1];
+ 			break;
  		}
- 	        case HDIO_UNREGISTER_HWIF:
- 			if (!capable(CAP_SYS_RAWIO)) return -EACCES;
- 			/* (arg > MAX_HWIFS) checked in function */
--			ide_unregister(arg);
-+			ide_unregister(arg, 1, 1);
- 			return 0;
- 		case HDIO_SET_NICE:
- 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-@@ -1231,26 +1231,12 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m
- 	return 0;	/* zero = nothing matched */
- }
- 
--#ifdef CONFIG_BLK_DEV_ALI14XX
- extern int probe_ali14xx;
--extern int ali14xx_init(void);
--#endif
--#ifdef CONFIG_BLK_DEV_UMC8672
- extern int probe_umc8672;
--extern int umc8672_init(void);
--#endif
--#ifdef CONFIG_BLK_DEV_DTC2278
- extern int probe_dtc2278;
--extern int dtc2278_init(void);
--#endif
--#ifdef CONFIG_BLK_DEV_HT6560B
- extern int probe_ht6560b;
--extern int ht6560b_init(void);
--#endif
--#ifdef CONFIG_BLK_DEV_QD65XX
- extern int probe_qd65xx;
--extern int qd65xx_init(void);
--#endif
-+extern int cmd640_vlb;
- 
- static int __initdata is_chipset_set[MAX_HWIFS];
- 
-@@ -1327,7 +1313,7 @@ static int __init ide_setup(char *s)
- 	if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) {
- 		const char *hd_words[] = {
- 			"none", "noprobe", "nowerr", "cdrom", "nodma",
--			"autotune", "noautotune", "minus8", "swapdata", "bswap",
-+			"autotune", "noautotune", "-8", "-9", "-10",
- 			"noflush", "remap", "remap63", "scsi", NULL };
- 		unit = s[2] - 'a';
- 		hw   = unit / MAX_DRIVES;
-@@ -1363,10 +1349,6 @@ static int __init ide_setup(char *s)
- 			case -7: /* "noautotune" */
- 				drive->autotune = IDE_TUNE_NOAUTO;
- 				goto obsolete_option;
--			case -9: /* "swapdata" */
--			case -10: /* "bswap" */
--				drive->bswap = 1;
--				goto done;
- 			case -11: /* noflush */
- 				drive->noflush = 1;
- 				goto done;
-@@ -1466,11 +1448,8 @@ static int __init ide_setup(char *s)
- #endif
- #ifdef CONFIG_BLK_DEV_CMD640
- 			case -14: /* "cmd640_vlb" */
--			{
--				extern int cmd640_vlb; /* flag for cmd640.c */
- 				cmd640_vlb = 1;
- 				goto done;
--			}
- #endif
- #ifdef CONFIG_BLK_DEV_HT6560B
- 			case -13: /* "ht6560b" */
-@@ -1560,79 +1539,6 @@ done:
- 	return 1;
- }
- 
--extern void __init pnpide_init(void);
--extern void __exit pnpide_exit(void);
--extern void __init h8300_ide_init(void);
--
--/*
-- * probe_for_hwifs() finds/initializes "known" IDE interfaces
-- */
--static void __init probe_for_hwifs (void)
--{
--#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
--	ide_scan_pcibus(ide_scan_direction);
--#endif
--
--#ifdef CONFIG_ETRAX_IDE
--	{
--		extern void init_e100_ide(void);
--		init_e100_ide();
--	}
--#endif /* CONFIG_ETRAX_IDE */
--#ifdef CONFIG_BLK_DEV_CMD640
--	{
--		extern void ide_probe_for_cmd640x(void);
--		ide_probe_for_cmd640x();
--	}
--#endif /* CONFIG_BLK_DEV_CMD640 */
--#ifdef CONFIG_BLK_DEV_IDE_PMAC
--	{
--		extern int pmac_ide_probe(void);
--		(void)pmac_ide_probe();
--	}
--#endif /* CONFIG_BLK_DEV_IDE_PMAC */
--#ifdef CONFIG_BLK_DEV_GAYLE
--	{
--		extern void gayle_init(void);
--		gayle_init();
--	}
--#endif /* CONFIG_BLK_DEV_GAYLE */
--#ifdef CONFIG_BLK_DEV_FALCON_IDE
--	{
--		extern void falconide_init(void);
--		falconide_init();
--	}
--#endif /* CONFIG_BLK_DEV_FALCON_IDE */
--#ifdef CONFIG_BLK_DEV_MAC_IDE
--	{
--		extern void macide_init(void);
--		macide_init();
--	}
--#endif /* CONFIG_BLK_DEV_MAC_IDE */
--#ifdef CONFIG_BLK_DEV_Q40IDE
--	{
--		extern void q40ide_init(void);
--		q40ide_init();
--	}
--#endif /* CONFIG_BLK_DEV_Q40IDE */
--#ifdef CONFIG_BLK_DEV_BUDDHA
--	{
--		extern void buddha_init(void);
--		buddha_init();
--	}
--#endif /* CONFIG_BLK_DEV_BUDDHA */
--#ifdef CONFIG_BLK_DEV_IDEPNP
--	pnpide_init();
--#endif
--#ifdef CONFIG_H8300
--	h8300_ide_init();
--#endif
--}
--
--/*
-- * Probe module
-- */
--
- EXPORT_SYMBOL(ide_lock);
+ 	}
+@@ -895,6 +974,9 @@ static void cm_format_req(struct cm_req_msg *req_msg,
+ 			  struct cm_id_private *cm_id_priv,
+ 			  struct ib_cm_req_param *param)
+ {
++	struct ib_sa_path_rec *pri_path = param->primary_path;
++	struct ib_sa_path_rec *alt_path = param->alternate_path;
++
+ 	cm_format_mad_hdr(&req_msg->hdr, CM_REQ_ATTR_ID,
+ 			  cm_form_tid(cm_id_priv, CM_MSG_SEQUENCE_REQ));
+ 
+@@ -918,35 +1000,46 @@ static void cm_format_req(struct cm_req_msg *req_msg,
+ 	cm_req_set_max_cm_retries(req_msg, param->max_cm_retries);
+ 	cm_req_set_srq(req_msg, param->srq);
+ 
+-	req_msg->primary_local_lid = param->primary_path->slid;
+-	req_msg->primary_remote_lid = param->primary_path->dlid;
+-	req_msg->primary_local_gid = param->primary_path->sgid;
+-	req_msg->primary_remote_gid = param->primary_path->dgid;
+-	cm_req_set_primary_flow_label(req_msg, param->primary_path->flow_label);
+-	cm_req_set_primary_packet_rate(req_msg, param->primary_path->rate);
+-	req_msg->primary_traffic_class = param->primary_path->traffic_class;
+-	req_msg->primary_hop_limit = param->primary_path->hop_limit;
+-	cm_req_set_primary_sl(req_msg, param->primary_path->sl);
+-	cm_req_set_primary_subnet_local(req_msg, 1); /* local only... */
++	if (pri_path->hop_limit <= 1) {
++		req_msg->primary_local_lid = pri_path->slid;
++		req_msg->primary_remote_lid = pri_path->dlid;
++	} else {
++		/* Work-around until there's a way to obtain remote LID info */
++		req_msg->primary_local_lid = IB_LID_PERMISSIVE;
++		req_msg->primary_remote_lid = IB_LID_PERMISSIVE;
++	}
++	req_msg->primary_local_gid = pri_path->sgid;
++	req_msg->primary_remote_gid = pri_path->dgid;
++	cm_req_set_primary_flow_label(req_msg, pri_path->flow_label);
++	cm_req_set_primary_packet_rate(req_msg, pri_path->rate);
++	req_msg->primary_traffic_class = pri_path->traffic_class;
++	req_msg->primary_hop_limit = pri_path->hop_limit;
++	cm_req_set_primary_sl(req_msg, pri_path->sl);
++	cm_req_set_primary_subnet_local(req_msg, (pri_path->hop_limit <= 1));
+ 	cm_req_set_primary_local_ack_timeout(req_msg,
+ 		cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+-			       param->primary_path->packet_life_time));
++			       pri_path->packet_life_time));
+ 
+-	if (param->alternate_path) {
+-		req_msg->alt_local_lid = param->alternate_path->slid;
+-		req_msg->alt_remote_lid = param->alternate_path->dlid;
+-		req_msg->alt_local_gid = param->alternate_path->sgid;
+-		req_msg->alt_remote_gid = param->alternate_path->dgid;
++	if (alt_path) {
++		if (alt_path->hop_limit <= 1) {
++			req_msg->alt_local_lid = alt_path->slid;
++			req_msg->alt_remote_lid = alt_path->dlid;
++		} else {
++			req_msg->alt_local_lid = IB_LID_PERMISSIVE;
++			req_msg->alt_remote_lid = IB_LID_PERMISSIVE;
++		}
++		req_msg->alt_local_gid = alt_path->sgid;
++		req_msg->alt_remote_gid = alt_path->dgid;
+ 		cm_req_set_alt_flow_label(req_msg,
+-					  param->alternate_path->flow_label);
+-		cm_req_set_alt_packet_rate(req_msg, param->alternate_path->rate);
+-		req_msg->alt_traffic_class = param->alternate_path->traffic_class;
+-		req_msg->alt_hop_limit = param->alternate_path->hop_limit;
+-		cm_req_set_alt_sl(req_msg, param->alternate_path->sl);
+-		cm_req_set_alt_subnet_local(req_msg, 1); /* local only... */
++					  alt_path->flow_label);
++		cm_req_set_alt_packet_rate(req_msg, alt_path->rate);
++		req_msg->alt_traffic_class = alt_path->traffic_class;
++		req_msg->alt_hop_limit = alt_path->hop_limit;
++		cm_req_set_alt_sl(req_msg, alt_path->sl);
++		cm_req_set_alt_subnet_local(req_msg, (alt_path->hop_limit <= 1));
+ 		cm_req_set_alt_local_ack_timeout(req_msg,
+ 			cm_ack_timeout(cm_id_priv->av.port->cm_dev->ack_delay,
+-				       param->alternate_path->packet_life_time));
++				       alt_path->packet_life_time));
+ 	}
  
- static int ide_bus_match(struct device *dev, struct device_driver *drv)
-@@ -1769,6 +1675,10 @@ static int __init ide_init(void)
- 	printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
- 	system_bus_speed = ide_system_bus_speed();
+ 	if (param->private_data && param->private_data_len)
+@@ -1270,6 +1363,9 @@ static void cm_dup_req_handler(struct cm_work *work,
+ 	struct ib_mad_send_buf *msg = NULL;
+ 	int ret;
  
-+	printk(KERN_INFO "ide: Assuming %dMHz system bus speed "
-+			 "for PIO modes%s\n", system_bus_speed,
-+			idebus_parameter ? "" : "; override with idebus=xx");
++	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++			counter[CM_REQ_COUNTER]);
 +
- 	ret = bus_register(&ide_bus_type);
- 	if (ret < 0) {
- 		printk(KERN_WARNING "IDE: bus_register error: %d\n", ret);
-@@ -1779,30 +1689,6 @@ static int __init ide_init(void)
- 
- 	proc_ide_create();
- 
--#ifdef CONFIG_BLK_DEV_ALI14XX
--	if (probe_ali14xx)
--		(void)ali14xx_init();
--#endif
--#ifdef CONFIG_BLK_DEV_UMC8672
--	if (probe_umc8672)
--		(void)umc8672_init();
--#endif
--#ifdef CONFIG_BLK_DEV_DTC2278
--	if (probe_dtc2278)
--		(void)dtc2278_init();
--#endif
--#ifdef CONFIG_BLK_DEV_HT6560B
--	if (probe_ht6560b)
--		(void)ht6560b_init();
--#endif
--#ifdef CONFIG_BLK_DEV_QD65XX
--	if (probe_qd65xx)
--		(void)qd65xx_init();
--#endif
--
--	/* Probe for special PCI and other "known" interface chipsets. */
--	probe_for_hwifs();
--
- 	return 0;
+ 	/* Quick state check to discard duplicate REQs. */
+ 	if (cm_id_priv->id.state == IB_CM_REQ_RCVD)
+ 		return;
+@@ -1359,6 +1455,34 @@ out:
+ 	return listen_cm_id_priv;
  }
  
-@@ -1836,11 +1722,7 @@ void __exit cleanup_module (void)
- 	int index;
- 
- 	for (index = 0; index < MAX_HWIFS; ++index)
--		ide_unregister(index);
--
--#ifdef CONFIG_BLK_DEV_IDEPNP
--	pnpide_exit();
--#endif
-+		ide_unregister(index, 0, 0);
- 
- 	proc_ide_destroy();
- 
-diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
-index 4098223..7043ec7 100644
---- a/drivers/ide/legacy/Makefile
-+++ b/drivers/ide/legacy/Makefile
-@@ -1,15 +1,24 @@
- 
-+# link order is important here
++/*
++ * Work-around for inter-subnet connections.  If the LIDs are permissive,
++ * we need to override the LID/SL data in the REQ with the LID information
++ * in the work completion.
++ */
++static void cm_process_routed_req(struct cm_req_msg *req_msg, struct ib_wc *wc)
++{
++	if (!cm_req_get_primary_subnet_local(req_msg)) {
++		if (req_msg->primary_local_lid == IB_LID_PERMISSIVE) {
++			req_msg->primary_local_lid = cpu_to_be16(wc->slid);
++			cm_req_set_primary_sl(req_msg, wc->sl);
++		}
 +
- obj-$(CONFIG_BLK_DEV_ALI14XX)		+= ali14xx.o
-+obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
- obj-$(CONFIG_BLK_DEV_DTC2278)		+= dtc2278.o
- obj-$(CONFIG_BLK_DEV_HT6560B)		+= ht6560b.o
- obj-$(CONFIG_BLK_DEV_QD65XX)		+= qd65xx.o
--obj-$(CONFIG_BLK_DEV_UMC8672)		+= umc8672.o
- 
--obj-$(CONFIG_BLK_DEV_IDECS)		+= ide-cs.o
-+obj-$(CONFIG_BLK_DEV_GAYLE)		+= gayle.o
-+obj-$(CONFIG_BLK_DEV_FALCON_IDE)	+= falconide.o
-+obj-$(CONFIG_BLK_DEV_MAC_IDE)		+= macide.o
-+obj-$(CONFIG_BLK_DEV_Q40IDE)		+= q40ide.o
-+obj-$(CONFIG_BLK_DEV_BUDDHA)		+= buddha.o
- 
--obj-$(CONFIG_BLK_DEV_PLATFORM)		+= ide_platform.o
-+ifeq ($(CONFIG_BLK_DEV_IDECS), m)
-+	obj-m += ide-cs.o
-+endif
++		if (req_msg->primary_remote_lid == IB_LID_PERMISSIVE)
++			req_msg->primary_remote_lid = cpu_to_be16(wc->dlid_path_bits);
++	}
++
++	if (!cm_req_get_alt_subnet_local(req_msg)) {
++		if (req_msg->alt_local_lid == IB_LID_PERMISSIVE) {
++			req_msg->alt_local_lid = cpu_to_be16(wc->slid);
++			cm_req_set_alt_sl(req_msg, wc->sl);
++		}
++
++		if (req_msg->alt_remote_lid == IB_LID_PERMISSIVE)
++			req_msg->alt_remote_lid = cpu_to_be16(wc->dlid_path_bits);
++	}
++}
++
+ static int cm_req_handler(struct cm_work *work)
+ {
+ 	struct ib_cm_id *cm_id;
+@@ -1399,6 +1523,7 @@ static int cm_req_handler(struct cm_work *work)
+ 	cm_id_priv->id.service_id = req_msg->service_id;
+ 	cm_id_priv->id.service_mask = __constant_cpu_to_be64(~0ULL);
  
--# Last of all
--obj-$(CONFIG_BLK_DEV_HD)		+= hd.o
-+ifeq ($(CONFIG_BLK_DEV_PLATFORM), m)
-+	obj-m += ide_platform.o
-+endif
++	cm_process_routed_req(req_msg, work->mad_recv_wc->wc);
+ 	cm_format_paths_from_req(req_msg, &work->path[0], &work->path[1]);
+ 	ret = cm_init_av_by_path(&work->path[0], &cm_id_priv->av);
+ 	if (ret) {
+@@ -1616,6 +1741,8 @@ static void cm_dup_rep_handler(struct cm_work *work)
+ 	if (!cm_id_priv)
+ 		return;
  
- EXTRA_CFLAGS	:= -Idrivers/ide
-diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c
-index 38c3a6d..d4d1a6b 100644
---- a/drivers/ide/legacy/ali14xx.c
-+++ b/drivers/ide/legacy/ali14xx.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/legacy/ali14xx.c		Version 0.03	Feb 09, 1996
-- *
-  *  Copyright (C) 1996  Linus Torvalds & author (see below)
-  */
++	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++			counter[CM_REP_COUNTER]);
+ 	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
+ 	if (ret)
+ 		goto deref;
+@@ -1781,6 +1908,8 @@ static int cm_rtu_handler(struct cm_work *work)
+ 	if (cm_id_priv->id.state != IB_CM_REP_SENT &&
+ 	    cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
+ 		spin_unlock_irq(&cm_id_priv->lock);
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_RTU_COUNTER]);
+ 		goto out;
+ 	}
+ 	cm_id_priv->id.state = IB_CM_ESTABLISHED;
+@@ -1958,6 +2087,8 @@ static int cm_dreq_handler(struct cm_work *work)
+ 	cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
+ 				   dreq_msg->local_comm_id);
+ 	if (!cm_id_priv) {
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_DREQ_COUNTER]);
+ 		cm_issue_drep(work->port, work->mad_recv_wc);
+ 		return -EINVAL;
+ 	}
+@@ -1977,6 +2108,8 @@ static int cm_dreq_handler(struct cm_work *work)
+ 	case IB_CM_MRA_REP_RCVD:
+ 		break;
+ 	case IB_CM_TIMEWAIT:
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_DREQ_COUNTER]);
+ 		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
+ 			goto unlock;
  
-@@ -193,9 +191,14 @@ static int __init initRegisters (void) {
- 	return t;
- }
+@@ -1988,6 +2121,10 @@ static int cm_dreq_handler(struct cm_work *work)
+ 		if (ib_post_send_mad(msg, NULL))
+ 			cm_free_msg(msg);
+ 		goto deref;
++	case IB_CM_DREQ_RCVD:
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_DREQ_COUNTER]);
++		goto unlock;
+ 	default:
+ 		goto unlock;
+ 	}
+@@ -2339,10 +2476,20 @@ static int cm_mra_handler(struct cm_work *work)
+ 		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
+ 		    cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
+ 		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
+-				  cm_id_priv->msg, timeout))
++				  cm_id_priv->msg, timeout)) {
++			if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
++				atomic_long_inc(&work->port->
++						counter_group[CM_RECV_DUPLICATES].
++						counter[CM_MRA_COUNTER]);
+ 			goto out;
++		}
+ 		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
+ 		break;
++	case IB_CM_MRA_REQ_RCVD:
++	case IB_CM_MRA_REP_RCVD:
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_MRA_COUNTER]);
++		/* fall through */
+ 	default:
+ 		goto out;
+ 	}
+@@ -2502,6 +2649,8 @@ static int cm_lap_handler(struct cm_work *work)
+ 	case IB_CM_LAP_IDLE:
+ 		break;
+ 	case IB_CM_MRA_LAP_SENT:
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_LAP_COUNTER]);
+ 		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
+ 			goto unlock;
  
-+static const struct ide_port_info ali14xx_port_info = {
-+	.chipset		= ide_ali14xx,
-+	.host_flags		= IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
-+	.pio_mask		= ATA_PIO4,
-+};
+@@ -2515,6 +2664,10 @@ static int cm_lap_handler(struct cm_work *work)
+ 		if (ib_post_send_mad(msg, NULL))
+ 			cm_free_msg(msg);
+ 		goto deref;
++	case IB_CM_LAP_RCVD:
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_LAP_COUNTER]);
++		goto unlock;
+ 	default:
+ 		goto unlock;
+ 	}
+@@ -2796,6 +2949,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
+ 	cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
+ 	if (cur_cm_id_priv) {
+ 		spin_unlock_irq(&cm.lock);
++		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
++				counter[CM_SIDR_REQ_COUNTER]);
+ 		goto out; /* Duplicate message. */
+ 	}
+ 	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
+@@ -2990,6 +3145,27 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
+ 			    struct ib_mad_send_wc *mad_send_wc)
+ {
+ 	struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
++	struct cm_port *port;
++	u16 attr_index;
 +
- static int __init ali14xx_probe(void)
++	port = mad_agent->context;
++	attr_index = be16_to_cpu(((struct ib_mad_hdr *)
++				  msg->mad)->attr_id) - CM_ATTR_ID_OFFSET;
++
++	/*
++	 * If the send was in response to a received message (context[0] is not
++	 * set to a cm_id), and is not a REJ, then it is a send that was
++	 * manually retried.
++	 */
++	if (!msg->context[0] && (attr_index != CM_REJ_COUNTER))
++		msg->retries = 1;
++
++	atomic_long_add(1 + msg->retries,
++			&port->counter_group[CM_XMIT].counter[attr_index]);
++	if (msg->retries)
++		atomic_long_add(msg->retries,
++				&port->counter_group[CM_XMIT_RETRIES].
++				counter[attr_index]);
+ 
+ 	switch (mad_send_wc->status) {
+ 	case IB_WC_SUCCESS:
+@@ -3148,8 +3324,10 @@ EXPORT_SYMBOL(ib_cm_notify);
+ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
+ 			    struct ib_mad_recv_wc *mad_recv_wc)
  {
--	ide_hwif_t *hwif, *mate;
- 	static u8 idx[4] = { 0, 1, 0xff, 0xff };
++	struct cm_port *port = mad_agent->context;
+ 	struct cm_work *work;
+ 	enum ib_cm_event_type event;
++	u16 attr_id;
+ 	int paths = 0;
  
- 	printk(KERN_DEBUG "ali14xx: base=0x%03x, regOn=0x%02x.\n",
-@@ -207,21 +210,10 @@ static int __init ali14xx_probe(void)
- 		return 1;
+ 	switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
+@@ -3194,6 +3372,10 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
+ 		return;
  	}
  
--	hwif = &ide_hwifs[0];
--	mate = &ide_hwifs[1];
--
--	hwif->chipset = ide_ali14xx;
--	hwif->pio_mask = ATA_PIO4;
--	hwif->set_pio_mode = &ali14xx_set_pio_mode;
--	hwif->mate = mate;
--
--	mate->chipset = ide_ali14xx;
--	mate->pio_mask = ATA_PIO4;
--	mate->set_pio_mode = &ali14xx_set_pio_mode;
--	mate->mate = hwif;
--	mate->channel = 1;
-+	ide_hwifs[0].set_pio_mode = &ali14xx_set_pio_mode;
-+	ide_hwifs[1].set_pio_mode = &ali14xx_set_pio_mode;
- 
--	ide_device_add(idx);
-+	ide_device_add(idx, &ali14xx_port_info);
- 
- 	return 0;
++	attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
++	atomic_long_inc(&port->counter_group[CM_RECV].
++			counter[attr_id - CM_ATTR_ID_OFFSET]);
++
+ 	work = kmalloc(sizeof *work + sizeof(struct ib_sa_path_rec) * paths,
+ 		       GFP_KERNEL);
+ 	if (!work) {
+@@ -3204,7 +3386,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
+ 	INIT_DELAYED_WORK(&work->work, cm_work_handler);
+ 	work->cm_event.event = event;
+ 	work->mad_recv_wc = mad_recv_wc;
+-	work->port = (struct cm_port *)mad_agent->context;
++	work->port = port;
+ 	queue_delayed_work(cm.wq, &work->work, 0);
  }
-@@ -231,8 +223,7 @@ int probe_ali14xx = 0;
- module_param_named(probe, probe_ali14xx, bool, 0);
- MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets");
  
--/* Can be called directly from ide.c. */
--int __init ali14xx_init(void)
-+static int __init ali14xx_init(void)
- {
- 	if (probe_ali14xx == 0)
- 		goto out;
-@@ -248,9 +239,7 @@ out:
- 	return -ENODEV;
+@@ -3379,6 +3561,108 @@ static void cm_get_ack_delay(struct cm_device *cm_dev)
+ 		cm_dev->ack_delay = attr.local_ca_ack_delay;
  }
  
--#ifdef MODULE
- module_init(ali14xx_init);
--#endif
- 
- MODULE_AUTHOR("see local file");
- MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
-diff --git a/drivers/ide/legacy/buddha.c b/drivers/ide/legacy/buddha.c
-index 4a0be25..8bdb79d 100644
---- a/drivers/ide/legacy/buddha.c
-+++ b/drivers/ide/legacy/buddha.c
-@@ -1,5 +1,5 @@
- /*
-- *  linux/drivers/ide/legacy/buddha.c -- Amiga Buddha, Catweasel and X-Surf IDE Driver
-+ *  Amiga Buddha, Catweasel and X-Surf IDE Driver
-  *
-  *	Copyright (C) 1997, 2001 by Geert Uytterhoeven and others
-  *
-@@ -112,6 +112,7 @@ typedef enum BuddhaType_Enum {
-     BOARD_BUDDHA, BOARD_CATWEASEL, BOARD_XSURF
- } BuddhaType;
- 
-+static const char *buddha_board_name[] = { "Buddha", "Catweasel", "X-Surf" };
- 
-     /*
-      *  Check and acknowledge the interrupt status
-@@ -143,11 +144,11 @@ static int xsurf_ack_intr(ide_hwif_t *hwif)
-      *  Probe for a Buddha or Catweasel IDE interface
-      */
- 
--void __init buddha_init(void)
-+static int __init buddha_init(void)
- {
- 	hw_regs_t hw;
- 	ide_hwif_t *hwif;
--	int i, index;
-+	int i;
- 
- 	struct zorro_dev *z = NULL;
- 	u_long buddha_board = 0;
-@@ -156,6 +157,8 @@ void __init buddha_init(void)
- 
- 	while ((z = zorro_find_device(ZORRO_WILDCARD, z))) {
- 		unsigned long board;
-+		u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+
- 		if (z->id == ZORRO_PROD_INDIVIDUAL_COMPUTERS_BUDDHA) {
- 			buddha_num_hwifs = BUDDHA_NUM_HWIFS;
- 			type=BOARD_BUDDHA;
-@@ -195,7 +198,10 @@ fail_base2:
- 		/* X-Surf doesn't have this.  IRQs are always on */
- 		if (type != BOARD_XSURF)
- 			z_writeb(0, buddha_board+BUDDHA_IRQ_MR);
--		
++static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
++			       char *buf)
++{
++	struct cm_counter_group *group;
++	struct cm_counter_attribute *cm_attr;
 +
-+		printk(KERN_INFO "ide: %s IDE controller\n",
-+				 buddha_board_name[type]);
++	group = container_of(obj, struct cm_counter_group, obj);
++	cm_attr = container_of(attr, struct cm_counter_attribute, attr);
 +
- 		for(i=0;i<buddha_num_hwifs;i++) {
- 			if(type != BOARD_XSURF) {
- 				ide_setup_ports(&hw, (buddha_board+buddha_bases[i]),
-@@ -213,23 +219,23 @@ fail_base2:
- 						IRQ_AMIGA_PORTS);
- 			}	
- 
--			index = ide_register_hw(&hw, NULL, 1, &hwif);
--			if (index != -1) {
-+			hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+			if (hwif) {
-+				u8 index = hwif->index;
++	return sprintf(buf, "%ld\n",
++		       atomic_long_read(&group->counter[cm_attr->index]));
++}
 +
-+				ide_init_port_data(hwif, index);
-+				ide_init_port_hw(hwif, &hw);
++static struct sysfs_ops cm_counter_ops = {
++	.show = cm_show_counter
++};
 +
- 				hwif->mmio = 1;
--				printk("ide%d: ", index);
--				switch(type) {
--				case BOARD_BUDDHA:
--					printk("Buddha");
--					break;
--				case BOARD_CATWEASEL:
--					printk("Catweasel");
--					break;
--				case BOARD_XSURF:
--					printk("X-Surf");
--					break;
--				}
--				printk(" IDE interface\n");	    
--			}		      
++static struct kobj_type cm_counter_obj_type = {
++	.sysfs_ops = &cm_counter_ops,
++	.default_attrs = cm_counter_default_attrs
++};
 +
-+				idx[i] = index;
-+			}
- 		}
++static void cm_release_port_obj(struct kobject *obj)
++{
++	struct cm_port *cm_port;
 +
-+		ide_device_add(idx, NULL);
- 	}
++	printk(KERN_ERR "free cm port\n");
 +
-+	return 0;
- }
++	cm_port = container_of(obj, struct cm_port, port_obj);
++	kfree(cm_port);
++}
 +
-+module_init(buddha_init);
-diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c
-index 24a845d..73396f7 100644
---- a/drivers/ide/legacy/dtc2278.c
-+++ b/drivers/ide/legacy/dtc2278.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/legacy/dtc2278.c		Version 0.02	Feb 10, 1996
-- *
-  *  Copyright (C) 1996  Linus Torvalds & author (see below)
-  */
- 
-@@ -86,14 +84,20 @@ static void dtc2278_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 		/* Actually we do - there is a data sheet available for the
- 		   Winbond but does anyone actually care */
- 	}
--
--	/*
--	 * 32bit I/O has to be enabled for *both* drives at the same time.
--	 */
--	drive->io_32bit = 1;
--	HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
- }
- 
-+static const struct ide_port_info dtc2278_port_info __initdata = {
-+	.chipset		= ide_dtc2278,
-+	.host_flags		= IDE_HFLAG_SERIALIZE |
-+				  IDE_HFLAG_NO_UNMASK_IRQS |
-+				  IDE_HFLAG_IO_32BIT |
-+				  /* disallow ->io_32bit changes */
-+				  IDE_HFLAG_NO_IO_32BIT |
-+				  IDE_HFLAG_NO_DMA |
-+				  IDE_HFLAG_NO_AUTOTUNE,
-+	.pio_mask		= ATA_PIO4,
++static struct kobj_type cm_port_obj_type = {
++	.release = cm_release_port_obj
 +};
 +
- static int __init dtc2278_probe(void)
- {
- 	unsigned long flags;
-@@ -124,23 +128,9 @@ static int __init dtc2278_probe(void)
- #endif
- 	local_irq_restore(flags);
- 
--	hwif->serialized = 1;
--	hwif->chipset = ide_dtc2278;
--	hwif->pio_mask = ATA_PIO4;
- 	hwif->set_pio_mode = &dtc2278_set_pio_mode;
--	hwif->drives[0].no_unmask = 1;
--	hwif->drives[1].no_unmask = 1;
--	hwif->mate = mate;
--
--	mate->serialized = 1;
--	mate->chipset = ide_dtc2278;
--	mate->pio_mask = ATA_PIO4;
--	mate->drives[0].no_unmask = 1;
--	mate->drives[1].no_unmask = 1;
--	mate->mate = hwif;
--	mate->channel = 1;
- 
--	ide_device_add(idx);
-+	ide_device_add(idx, &dtc2278_port_info);
- 
- 	return 0;
- }
-@@ -150,8 +140,7 @@ int probe_dtc2278 = 0;
- module_param_named(probe, probe_dtc2278, bool, 0);
- MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets");
- 
--/* Can be called directly from ide.c. */
--int __init dtc2278_init(void)
-+static int __init dtc2278_init(void)
- {
- 	if (probe_dtc2278 == 0)
- 		return -ENODEV;
-@@ -163,9 +152,7 @@ int __init dtc2278_init(void)
- 	return 0;
- }
- 
--#ifdef MODULE
- module_init(dtc2278_init);
--#endif
- 
- MODULE_AUTHOR("See Local File");
- MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
-diff --git a/drivers/ide/legacy/falconide.c b/drivers/ide/legacy/falconide.c
-index 7d7936f..85b69a8 100644
---- a/drivers/ide/legacy/falconide.c
-+++ b/drivers/ide/legacy/falconide.c
-@@ -1,5 +1,5 @@
- /*
-- *  linux/drivers/ide/legacy/falconide.c -- Atari Falcon IDE Driver
-+ *  Atari Falcon IDE Driver
-  *
-  *     Created 12 Jul 1997 by Geert Uytterhoeven
-  *
-@@ -62,19 +62,32 @@ EXPORT_SYMBOL(falconide_intr_lock);
-      *  Probe for a Falcon IDE interface
-      */
- 
--void __init falconide_init(void)
-+static int __init falconide_init(void)
- {
-     if (MACH_IS_ATARI && ATARIHW_PRESENT(IDE)) {
- 	hw_regs_t hw;
--	int index;
-+	ide_hwif_t *hwif;
++static void cm_release_dev_obj(struct kobject *obj)
++{
++	struct cm_device *cm_dev;
 +
-+	printk(KERN_INFO "ide: Falcon IDE controller\n");
- 
- 	ide_setup_ports(&hw, ATA_HD_BASE, falconide_offsets,
- 			0, 0, NULL,
- //			falconide_iops,
- 			IRQ_MFP_IDE);
--	index = ide_register_hw(&hw, NULL, 1, NULL);
- 
--	if (index != -1)
--	    printk("ide%d: Falcon IDE interface\n", index);
-+	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif) {
-+		u8 index = hwif->index;
-+		u8 idx[4] = { index, 0xff, 0xff, 0xff };
++	printk(KERN_ERR "free cm dev\n");
 +
-+		ide_init_port_data(hwif, index);
-+		ide_init_port_hw(hwif, &hw);
++	cm_dev = container_of(obj, struct cm_device, dev_obj);
++	kfree(cm_dev);
++}
 +
-+		ide_device_add(idx, NULL);
-+	}
-     }
++static struct kobj_type cm_dev_obj_type = {
++	.release = cm_release_dev_obj
++};
 +
-+    return 0;
- }
++struct class cm_class = {
++	.name    = "infiniband_cm",
++};
++EXPORT_SYMBOL(cm_class);
 +
-+module_init(falconide_init);
-diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c
-index 53331ee..fc29ce7 100644
---- a/drivers/ide/legacy/gayle.c
-+++ b/drivers/ide/legacy/gayle.c
-@@ -1,5 +1,5 @@
- /*
-- *  linux/drivers/ide/legacy/gayle.c -- Amiga Gayle IDE Driver
-+ *  Amiga Gayle IDE Driver
-  *
-  *     Created 9 Jul 1997 by Geert Uytterhoeven
-  *
-@@ -110,12 +110,13 @@ static int gayle_ack_intr_a1200(ide_hwif_t *hwif)
-      *  Probe for a Gayle IDE interface (and optionally for an IDE doubler)
-      */
- 
--void __init gayle_init(void)
-+static int __init gayle_init(void)
- {
-     int a4000, i;
-+    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- 
-     if (!MACH_IS_AMIGA)
--	return;
-+	return -ENODEV;
- 
-     if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE))
- 	goto found;
-@@ -125,15 +126,21 @@ void __init gayle_init(void)
- 			  NULL))
- 	goto found;
- #endif
--    return;
-+    return -ENODEV;
- 
- found:
-+	printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n",
-+			 a4000 ? 4000 : 1200,
-+#ifdef CONFIG_BLK_DEV_IDEDOUBLER
-+			 ide_doubler ? ", IDE doubler" :
-+#endif
-+			 "");
++static void cm_remove_fs_obj(struct kobject *obj)
++{
++	kobject_put(obj->parent);
++	kobject_put(obj);
++}
 +
-     for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) {
- 	unsigned long base, ctrlport, irqport;
- 	ide_ack_intr_t *ack_intr;
- 	hw_regs_t hw;
- 	ide_hwif_t *hwif;
--	int index;
- 	unsigned long phys_base, res_start, res_n;
- 
- 	if (a4000) {
-@@ -165,21 +172,23 @@ found:
- //			&gayle_iops,
- 			IRQ_AMIGA_PORTS);
- 
--	index = ide_register_hw(&hw, NULL, 1, &hwif);
--	if (index != -1) {
-+	hwif = ide_find_port(base);
-+	if (hwif) {
-+	    u8 index = hwif->index;
++static int cm_create_port_fs(struct cm_port *port)
++{
++	int i, ret;
 +
-+	    ide_init_port_data(hwif, index);
-+	    ide_init_port_hw(hwif, &hw);
++	ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
++				   kobject_get(&port->cm_dev->dev_obj),
++				   "%d", port->port_num);
++	if (ret) {
++		kfree(port);
++		return ret;
++	}
 +
- 	    hwif->mmio = 1;
--	    switch (i) {
--		case 0:
--		    printk("ide%d: Gayle IDE interface (A%d style)\n", index,
--			   a4000 ? 4000 : 1200);
--		    break;
--#ifdef CONFIG_BLK_DEV_IDEDOUBLER
--		case 1:
--		    printk("ide%d: IDE doubler\n", index);
--		    break;
--#endif /* CONFIG_BLK_DEV_IDEDOUBLER */
--	    }
++	for (i = 0; i < CM_COUNTER_GROUPS; i++) {
++		ret = kobject_init_and_add(&port->counter_group[i].obj,
++					   &cm_counter_obj_type,
++					   kobject_get(&port->port_obj),
++					   "%s", counter_group_names[i]);
++		if (ret)
++			goto error;
++	}
 +
-+	    idx[i] = index;
- 	} else
- 	    release_mem_region(res_start, res_n);
-     }
++	return 0;
 +
-+    ide_device_add(idx, NULL);
++error:
++	while (i--)
++		cm_remove_fs_obj(&port->counter_group[i].obj);
++	cm_remove_fs_obj(&port->port_obj);
++	return ret;
 +
-+    return 0;
- }
++}
 +
-+module_init(gayle_init);
-diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c
-index a4245d1..02d12c7 100644
---- a/drivers/ide/legacy/ht6560b.c
-+++ b/drivers/ide/legacy/ht6560b.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/legacy/ht6560b.c		Version 0.07	Feb  1, 2000
-- *
-  *  Copyright (C) 1995-2000  Linus Torvalds & author (see below)
-  */
- 
-@@ -302,17 +300,36 @@ static void ht6560b_set_pio_mode(ide_drive_t *drive, const u8 pio)
- #endif
- }
- 
-+static void __init ht6560b_port_init_devs(ide_hwif_t *hwif)
++static void cm_remove_port_fs(struct cm_port *port)
 +{
-+	/* Setting default configurations for drives. */
-+	int t = (HT_CONFIG_DEFAULT << 8) | HT_TIMING_DEFAULT;
++	int i;
 +
-+	if (hwif->channel)
-+		t |= (HT_SECONDARY_IF << 8);
++	for (i = 0; i < CM_COUNTER_GROUPS; i++)
++		cm_remove_fs_obj(&port->counter_group[i].obj);
 +
-+	hwif->drives[0].drive_data = t;
-+	hwif->drives[1].drive_data = t;
++	cm_remove_fs_obj(&port->port_obj);
 +}
 +
- int probe_ht6560b = 0;
+ static void cm_add_one(struct ib_device *device)
+ {
+ 	struct cm_device *cm_dev;
+@@ -3397,7 +3681,7 @@ static void cm_add_one(struct ib_device *device)
+ 	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ 		return;
  
- module_param_named(probe, probe_ht6560b, bool, 0);
- MODULE_PARM_DESC(probe, "probe for HT6560B chipset");
+-	cm_dev = kmalloc(sizeof(*cm_dev) + sizeof(*port) *
++	cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
+ 			 device->phys_port_cnt, GFP_KERNEL);
+ 	if (!cm_dev)
+ 		return;
+@@ -3405,11 +3689,27 @@ static void cm_add_one(struct ib_device *device)
+ 	cm_dev->device = device;
+ 	cm_get_ack_delay(cm_dev);
  
--/* Can be called directly from ide.c. */
--int __init ht6560b_init(void)
-+static const struct ide_port_info ht6560b_port_info __initdata = {
-+	.chipset		= ide_ht6560b,
-+	.host_flags		= IDE_HFLAG_SERIALIZE | /* is this needed? */
-+				  IDE_HFLAG_NO_DMA |
-+				  IDE_HFLAG_NO_AUTOTUNE |
-+				  IDE_HFLAG_ABUSE_PREFETCH,
-+	.pio_mask		= ATA_PIO5,
-+};
++	ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type,
++				   &cm_class.subsys.kobj, "%s", device->name);
++	if (ret) {
++		kfree(cm_dev);
++		return;
++	}
 +
-+static int __init ht6560b_init(void)
- {
- 	ide_hwif_t *hwif, *mate;
- 	static u8 idx[4] = { 0, 1, 0xff, 0xff };
--	int t;
+ 	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
+ 	for (i = 1; i <= device->phys_port_cnt; i++) {
+-		port = &cm_dev->port[i-1];
++		port = kzalloc(sizeof *port, GFP_KERNEL);
++		if (!port)
++			goto error1;
++
++		cm_dev->port[i-1] = port;
+ 		port->cm_dev = cm_dev;
+ 		port->port_num = i;
++
++		ret = cm_create_port_fs(port);
++		if (ret)
++			goto error1;
++
+ 		port->mad_agent = ib_register_mad_agent(device, i,
+ 							IB_QPT_GSI,
+ 							&reg_req,
+@@ -3418,11 +3718,11 @@ static void cm_add_one(struct ib_device *device)
+ 							cm_recv_handler,
+ 							port);
+ 		if (IS_ERR(port->mad_agent))
+-			goto error1;
++			goto error2;
  
- 	if (probe_ht6560b == 0)
- 		return -ENODEV;
-@@ -331,36 +348,16 @@ int __init ht6560b_init(void)
- 		goto release_region;
+ 		ret = ib_modify_port(device, i, 0, &port_modify);
+ 		if (ret)
+-			goto error2;
++			goto error3;
  	}
+ 	ib_set_client_data(device, &cm_client, cm_dev);
  
--	hwif->chipset = ide_ht6560b;
- 	hwif->selectproc = &ht6560b_selectproc;
--	hwif->host_flags = IDE_HFLAG_ABUSE_PREFETCH;
--	hwif->pio_mask = ATA_PIO5;
- 	hwif->set_pio_mode = &ht6560b_set_pio_mode;
--	hwif->serialized = 1;	/* is this needed? */
--	hwif->mate = mate;
+@@ -3431,17 +3731,20 @@ static void cm_add_one(struct ib_device *device)
+ 	write_unlock_irqrestore(&cm.device_lock, flags);
+ 	return;
  
--	mate->chipset = ide_ht6560b;
- 	mate->selectproc = &ht6560b_selectproc;
--	mate->host_flags = IDE_HFLAG_ABUSE_PREFETCH;
--	mate->pio_mask = ATA_PIO5;
- 	mate->set_pio_mode = &ht6560b_set_pio_mode;
--	mate->serialized = 1;	/* is this needed? */
--	mate->mate = hwif;
--	mate->channel = 1;
+-error2:
++error3:
+ 	ib_unregister_mad_agent(port->mad_agent);
++error2:
++	cm_remove_port_fs(port);
+ error1:
+ 	port_modify.set_port_cap_mask = 0;
+ 	port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
+ 	while (--i) {
+-		port = &cm_dev->port[i-1];
++		port = cm_dev->port[i-1];
+ 		ib_modify_port(device, port->port_num, 0, &port_modify);
+ 		ib_unregister_mad_agent(port->mad_agent);
++		cm_remove_port_fs(port);
+ 	}
+-	kfree(cm_dev);
++	cm_remove_fs_obj(&cm_dev->dev_obj);
+ }
  
--	/*
--	 * Setting default configurations for drives
--	 */
--	t = (HT_CONFIG_DEFAULT << 8);
--	t |= HT_TIMING_DEFAULT;
--	hwif->drives[0].drive_data = t;
--	hwif->drives[1].drive_data = t;
--
--	t |= (HT_SECONDARY_IF << 8);
--	mate->drives[0].drive_data = t;
--	mate->drives[1].drive_data = t;
-+	hwif->port_init_devs = ht6560b_port_init_devs;
-+	mate->port_init_devs = ht6560b_port_init_devs;
+ static void cm_remove_one(struct ib_device *device)
+@@ -3463,11 +3766,12 @@ static void cm_remove_one(struct ib_device *device)
+ 	write_unlock_irqrestore(&cm.device_lock, flags);
  
--	ide_device_add(idx);
-+	ide_device_add(idx, &ht6560b_port_info);
+ 	for (i = 1; i <= device->phys_port_cnt; i++) {
+-		port = &cm_dev->port[i-1];
++		port = cm_dev->port[i-1];
+ 		ib_modify_port(device, port->port_num, 0, &port_modify);
+ 		ib_unregister_mad_agent(port->mad_agent);
++		cm_remove_port_fs(port);
+ 	}
+-	kfree(cm_dev);
++	cm_remove_fs_obj(&cm_dev->dev_obj);
+ }
+ 
+ static int __init ib_cm_init(void)
+@@ -3488,17 +3792,25 @@ static int __init ib_cm_init(void)
+ 	idr_pre_get(&cm.local_id_table, GFP_KERNEL);
+ 	INIT_LIST_HEAD(&cm.timewait_list);
+ 
+-	cm.wq = create_workqueue("ib_cm");
+-	if (!cm.wq)
++	ret = class_register(&cm_class);
++	if (ret)
+ 		return -ENOMEM;
+ 
++	cm.wq = create_workqueue("ib_cm");
++	if (!cm.wq) {
++		ret = -ENOMEM;
++		goto error1;
++	}
++
+ 	ret = ib_register_client(&cm_client);
+ 	if (ret)
+-		goto error;
++		goto error2;
  
  	return 0;
+-error:
++error2:
+ 	destroy_workqueue(cm.wq);
++error1:
++	class_unregister(&cm_class);
+ 	return ret;
+ }
  
-@@ -369,9 +366,7 @@ release_region:
- 	return -ENODEV;
+@@ -3519,6 +3831,7 @@ static void __exit ib_cm_cleanup(void)
+ 	}
+ 
+ 	ib_unregister_client(&cm_client);
++	class_unregister(&cm_class);
+ 	idr_destroy(&cm.local_id_table);
  }
  
--#ifdef MODULE
- module_init(ht6560b_init);
--#endif
+diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
+index 0751697..1eff1b2 100644
+--- a/drivers/infiniband/core/cma.c
++++ b/drivers/infiniband/core/cma.c
+@@ -488,7 +488,8 @@ void rdma_destroy_qp(struct rdma_cm_id *id)
+ }
+ EXPORT_SYMBOL(rdma_destroy_qp);
  
- MODULE_AUTHOR("See Local File");
- MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
-diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c
-index 03715c0..15ccf69 100644
---- a/drivers/ide/legacy/ide-cs.c
-+++ b/drivers/ide/legacy/ide-cs.c
-@@ -2,8 +2,6 @@
+-static int cma_modify_qp_rtr(struct rdma_id_private *id_priv)
++static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
++			     struct rdma_conn_param *conn_param)
+ {
+ 	struct ib_qp_attr qp_attr;
+ 	int qp_attr_mask, ret;
+@@ -514,13 +515,16 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv)
+ 	if (ret)
+ 		goto out;
  
-     A driver for PCMCIA IDE/ATA disk cards
++	if (conn_param)
++		qp_attr.max_dest_rd_atomic = conn_param->responder_resources;
+ 	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+ out:
+ 	mutex_unlock(&id_priv->qp_mutex);
+ 	return ret;
+ }
  
--    ide-cs.c 1.3 2002/10/26 05:45:31
--
-     The contents of this file are subject to the Mozilla Public
-     License Version 1.1 (the "License"); you may not use this file
-     except in compliance with the License. You may obtain a copy of
-@@ -147,13 +145,36 @@ static void ide_detach(struct pcmcia_device *link)
+-static int cma_modify_qp_rts(struct rdma_id_private *id_priv)
++static int cma_modify_qp_rts(struct rdma_id_private *id_priv,
++			     struct rdma_conn_param *conn_param)
+ {
+ 	struct ib_qp_attr qp_attr;
+ 	int qp_attr_mask, ret;
+@@ -536,6 +540,8 @@ static int cma_modify_qp_rts(struct rdma_id_private *id_priv)
+ 	if (ret)
+ 		goto out;
  
- static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle)
++	if (conn_param)
++		qp_attr.max_rd_atomic = conn_param->initiator_depth;
+ 	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+ out:
+ 	mutex_unlock(&id_priv->qp_mutex);
+@@ -624,7 +630,8 @@ static inline int cma_zero_addr(struct sockaddr *addr)
+ 	struct in6_addr *ip6;
+ 
+ 	if (addr->sa_family == AF_INET)
+-		return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
++		return ipv4_is_zeronet(
++			((struct sockaddr_in *)addr)->sin_addr.s_addr);
+ 	else {
+ 		ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
+ 		return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
+@@ -634,7 +641,7 @@ static inline int cma_zero_addr(struct sockaddr *addr)
+ 
+ static inline int cma_loopback_addr(struct sockaddr *addr)
  {
-+    ide_hwif_t *hwif;
-     hw_regs_t hw;
-+    int i;
-+    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+
-     memset(&hw, 0, sizeof(hw));
--    ide_init_hwif_ports(&hw, io, ctl, NULL);
-+    ide_std_init_ports(&hw, io, ctl);
-     hw.irq = irq;
-     hw.chipset = ide_pci;
-     hw.dev = &handle->dev;
--    return ide_register_hw(&hw, &ide_undecoded_slave, 0, NULL);
-+
-+    hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+    if (hwif == NULL)
-+	return -1;
-+
-+    i = hwif->index;
-+
-+    if (hwif->present)
-+	ide_unregister(i, 0, 0);
-+    else if (!hwif->hold)
-+	ide_init_port_data(hwif, i);
-+
-+    ide_init_port_hw(hwif, &hw);
-+    hwif->quirkproc = &ide_undecoded_slave;
-+
-+    idx[0] = i;
-+
-+    ide_device_add(idx, NULL);
-+
-+    return hwif->present ? i : -1;
+-	return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
++	return ipv4_is_loopback(((struct sockaddr_in *) addr)->sin_addr.s_addr);
  }
  
- /*======================================================================
-@@ -339,7 +360,7 @@ void ide_release(struct pcmcia_device *link)
-     if (info->ndev) {
- 	/* FIXME: if this fails we need to queue the cleanup somehow
- 	   -- need to investigate the required PCMCIA magic */
--	ide_unregister(info->hd);
-+	ide_unregister(info->hd, 0, 0);
-     }
-     info->ndev = 0;
+ static inline int cma_any_addr(struct sockaddr *addr)
+@@ -866,11 +873,11 @@ static int cma_rep_recv(struct rdma_id_private *id_priv)
+ {
+ 	int ret;
  
-diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
-index 7bb79f5..26c82ce 100644
---- a/drivers/ide/legacy/ide_platform.c
-+++ b/drivers/ide/legacy/ide_platform.c
-@@ -21,56 +21,39 @@
- #include <linux/platform_device.h>
- #include <linux/io.h>
+-	ret = cma_modify_qp_rtr(id_priv);
++	ret = cma_modify_qp_rtr(id_priv, NULL);
+ 	if (ret)
+ 		goto reject;
  
--static struct {
--	void __iomem *plat_ide_mapbase;
--	void __iomem *plat_ide_alt_mapbase;
--	ide_hwif_t *hwif;
--	int index;
--} hwif_prop;
--
--static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base,
--	    void __iomem *ctrl, struct pata_platform_info *pdata, int irq,
--	    int mmio)
-+static void __devinit plat_ide_setup_ports(hw_regs_t *hw,
-+					   void __iomem *base,
-+					   void __iomem *ctrl,
-+					   struct pata_platform_info *pdata,
-+					   int irq)
- {
- 	unsigned long port = (unsigned long)base;
--	ide_hwif_t *hwif = ide_find_port(port);
- 	int i;
+-	ret = cma_modify_qp_rts(id_priv);
++	ret = cma_modify_qp_rts(id_priv, NULL);
+ 	if (ret)
+ 		goto reject;
  
--	if (hwif == NULL)
--		goto out;
--
--	hwif->io_ports[IDE_DATA_OFFSET] = port;
-+	hw->io_ports[IDE_DATA_OFFSET] = port;
+@@ -1122,8 +1129,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
+ 	cm_id->cm_handler = cma_ib_handler;
  
- 	port += (1 << pdata->ioport_shift);
- 	for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
- 	     i++, port += (1 << pdata->ioport_shift))
--		hwif->io_ports[i] = port;
--
--	hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
-+		hw->io_ports[i] = port;
+ 	ret = conn_id->id.event_handler(&conn_id->id, &event);
+-	if (!ret)
++	if (!ret) {
++		cma_enable_remove(conn_id);
+ 		goto out;
++	}
  
--	hwif->irq = irq;
-+	hw->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
+ 	/* Destroy the CM ID by returning a non-zero value. */
+ 	conn_id->cm_id.ib = NULL;
+@@ -1262,6 +1271,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
+ 	struct net_device *dev = NULL;
+ 	struct rdma_cm_event event;
+ 	int ret;
++	struct ib_device_attr attr;
  
--	hwif->chipset = ide_generic;
-+	hw->irq = irq;
+ 	listen_id = cm_id->context;
+ 	if (cma_disable_remove(listen_id, CMA_LISTEN))
+@@ -1279,7 +1289,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
+ 	atomic_inc(&conn_id->dev_remove);
+ 	conn_id->state = CMA_CONNECT;
  
--	if (mmio) {
--		hwif->mmio = 1;
--		default_hwif_mmiops(hwif);
--	}
--
--	hwif_prop.hwif = hwif;
--	hwif_prop.index = hwif->index;
--out:
--	return hwif;
-+	hw->chipset = ide_generic;
- }
+-	dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr);
++	dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
+ 	if (!dev) {
+ 		ret = -EADDRNOTAVAIL;
+ 		cma_enable_remove(conn_id);
+@@ -1311,10 +1321,19 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
+ 	sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
+ 	*sin = iw_event->remote_addr;
  
- static int __devinit plat_ide_probe(struct platform_device *pdev)
++	ret = ib_query_device(conn_id->id.device, &attr);
++	if (ret) {
++		cma_enable_remove(conn_id);
++		rdma_destroy_id(new_cm_id);
++		goto out;
++	}
++
+ 	memset(&event, 0, sizeof event);
+ 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
+ 	event.param.conn.private_data = iw_event->private_data;
+ 	event.param.conn.private_data_len = iw_event->private_data_len;
++	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
++	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+ 	ret = conn_id->id.event_handler(&conn_id->id, &event);
+ 	if (ret) {
+ 		/* User wants to destroy the CM ID */
+@@ -2272,7 +2291,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
+ 	sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr;
+ 	cm_id->remote_addr = *sin;
+ 
+-	ret = cma_modify_qp_rtr(id_priv);
++	ret = cma_modify_qp_rtr(id_priv, conn_param);
+ 	if (ret)
+ 		goto out;
+ 
+@@ -2335,25 +2354,15 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
+ 			 struct rdma_conn_param *conn_param)
  {
- 	struct resource *res_base, *res_alt, *res_irq;
-+	void __iomem *base, *alt_base;
- 	ide_hwif_t *hwif;
- 	struct pata_platform_info *pdata;
- 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
- 	int ret = 0;
- 	int mmio = 0;
-+	hw_regs_t hw;
+ 	struct ib_cm_rep_param rep;
+-	struct ib_qp_attr qp_attr;
+-	int qp_attr_mask, ret;
+-
+-	if (id_priv->id.qp) {
+-		ret = cma_modify_qp_rtr(id_priv);
+-		if (ret)
+-			goto out;
++	int ret;
  
- 	pdata = pdev->dev.platform_data;
+-		qp_attr.qp_state = IB_QPS_RTS;
+-		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
+-					 &qp_attr_mask);
+-		if (ret)
+-			goto out;
++	ret = cma_modify_qp_rtr(id_priv, conn_param);
++	if (ret)
++		goto out;
  
-@@ -95,30 +78,37 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
- 	}
+-		qp_attr.max_rd_atomic = conn_param->initiator_depth;
+-		ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
+-		if (ret)
+-			goto out;
+-	}
++	ret = cma_modify_qp_rts(id_priv, conn_param);
++	if (ret)
++		goto out;
  
- 	if (mmio) {
--		hwif_prop.plat_ide_mapbase = devm_ioremap(&pdev->dev,
-+		base = devm_ioremap(&pdev->dev,
- 			res_base->start, res_base->end - res_base->start + 1);
--		hwif_prop.plat_ide_alt_mapbase = devm_ioremap(&pdev->dev,
-+		alt_base = devm_ioremap(&pdev->dev,
- 			res_alt->start, res_alt->end - res_alt->start + 1);
+ 	memset(&rep, 0, sizeof rep);
+ 	rep.qp_num = id_priv->qp_num;
+@@ -2378,7 +2387,7 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
+ 	struct iw_cm_conn_param iw_param;
+ 	int ret;
+ 
+-	ret = cma_modify_qp_rtr(id_priv);
++	ret = cma_modify_qp_rtr(id_priv, conn_param);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -2598,11 +2607,9 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
+ 		/* IPv6 address is an SA assigned MGID. */
+ 		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
  	} else {
--		hwif_prop.plat_ide_mapbase = devm_ioport_map(&pdev->dev,
-+		base = devm_ioport_map(&pdev->dev,
- 			res_base->start, res_base->end - res_base->start + 1);
--		hwif_prop.plat_ide_alt_mapbase = devm_ioport_map(&pdev->dev,
-+		alt_base = devm_ioport_map(&pdev->dev,
- 			res_alt->start, res_alt->end - res_alt->start + 1);
+-		ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
++		ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map);
+ 		if (id_priv->id.ps == RDMA_PS_UDP)
+ 			mc_map[7] = 0x01;	/* Use RDMA CM signature */
+-		mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
+-		mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
+ 		*mgid = *(union ib_gid *) (mc_map + 4);
  	}
+ }
+diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
+index e8d5f6b..7f00347 100644
+--- a/drivers/infiniband/core/fmr_pool.c
++++ b/drivers/infiniband/core/fmr_pool.c
+@@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
+ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
+ {
+ 	int                 ret;
+-	struct ib_pool_fmr *fmr;
++	struct ib_pool_fmr *fmr, *next;
+ 	LIST_HEAD(unmap_list);
+ 	LIST_HEAD(fmr_list);
  
--	hwif = plat_ide_locate_hwif(hwif_prop.plat_ide_mapbase,
--	         hwif_prop.plat_ide_alt_mapbase, pdata, res_irq->start, mmio);
--
-+	hwif = ide_find_port((unsigned long)base);
- 	if (!hwif) {
- 		ret = -ENODEV;
- 		goto out;
+@@ -158,6 +158,20 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
+ #endif
  	}
--	hwif->gendev.parent = &pdev->dev;
--	hwif->noprobe = 0;
-+
-+	memset(&hw, 0, sizeof(hw));
-+	plat_ide_setup_ports(&hw, base, alt_base, pdata, res_irq->start);
-+	hw.dev = &pdev->dev;
-+
-+	ide_init_port_hw(hwif, &hw);
-+
-+	if (mmio) {
-+		hwif->mmio = 1;
-+		default_hwif_mmiops(hwif);
+ 
++	/*
++	 * The free_list may hold FMRs that have been put there
++	 * because they haven't reached the max_remap count.
++	 * Invalidate their mapping as well.
++	 */
++	list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
++		if (fmr->remap_count == 0)
++			continue;
++		hlist_del_init(&fmr->cache_node);
++		fmr->remap_count = 0;
++		list_add_tail(&fmr->fmr->list, &fmr_list);
++		list_move(&fmr->list, &unmap_list);
 +	}
++
+ 	list_splice(&pool->dirty_list, &unmap_list);
+ 	INIT_LIST_HEAD(&pool->dirty_list);
+ 	pool->dirty_len = 0;
+@@ -182,8 +196,7 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
+ 	struct ib_fmr_pool *pool = pool_ptr;
  
- 	idx[0] = hwif->index;
+ 	do {
+-		if (pool->dirty_len >= pool->dirty_watermark ||
+-		    atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
++		if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
+ 			ib_fmr_batch_release(pool);
  
--	ide_device_add(idx);
-+	ide_device_add(idx, NULL);
+ 			atomic_inc(&pool->flush_ser);
+@@ -194,8 +207,7 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
+ 		}
  
- 	platform_set_drvdata(pdev, hwif);
+ 		set_current_state(TASK_INTERRUPTIBLE);
+-		if (pool->dirty_len < pool->dirty_watermark &&
+-		    atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
++		if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
+ 		    !kthread_should_stop())
+ 			schedule();
+ 		__set_current_state(TASK_RUNNING);
+@@ -308,10 +320,13 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd             *pd,
+ 			.max_maps   = pool->max_remaps,
+ 			.page_shift = params->page_shift
+ 		};
++		int bytes_per_fmr = sizeof *fmr;
++
++		if (pool->cache_bucket)
++			bytes_per_fmr += params->max_pages_per_fmr * sizeof (u64);
  
-@@ -132,14 +122,7 @@ static int __devexit plat_ide_remove(struct platform_device *pdev)
- {
- 	ide_hwif_t *hwif = pdev->dev.driver_data;
+ 		for (i = 0; i < params->pool_size; ++i) {
+-			fmr = kmalloc(sizeof *fmr + params->max_pages_per_fmr * sizeof (u64),
+-				      GFP_KERNEL);
++			fmr = kmalloc(bytes_per_fmr, GFP_KERNEL);
+ 			if (!fmr) {
+ 				printk(KERN_WARNING PFX "failed to allocate fmr "
+ 				       "struct for FMR %d\n", i);
+@@ -369,11 +384,6 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
  
--	if (hwif != hwif_prop.hwif) {
--		dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error",
--		           pdev->name);
--	} else {
--		ide_unregister(hwif_prop.index);
--		hwif_prop.index = 0;
--		hwif_prop.hwif = NULL;
--	}
-+	ide_unregister(hwif->index, 0, 0);
+ 	i = 0;
+ 	list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
+-		if (fmr->remap_count) {
+-			INIT_LIST_HEAD(&fmr_list);
+-			list_add_tail(&fmr->fmr->list, &fmr_list);
+-			ib_unmap_fmr(&fmr_list);
+-		}
+ 		ib_dealloc_fmr(fmr->fmr);
+ 		list_del(&fmr->list);
+ 		kfree(fmr);
+@@ -511,8 +521,10 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr)
+ 			list_add_tail(&fmr->list, &pool->free_list);
+ 		} else {
+ 			list_add_tail(&fmr->list, &pool->dirty_list);
+-			++pool->dirty_len;
+-			wake_up_process(pool->thread);
++			if (++pool->dirty_len >= pool->dirty_watermark) {
++				atomic_inc(&pool->req_ser);
++				wake_up_process(pool->thread);
++			}
+ 		}
+ 	}
  
- 	return 0;
- }
-diff --git a/drivers/ide/legacy/macide.c b/drivers/ide/legacy/macide.c
-index 5c6aa77..06df8df 100644
---- a/drivers/ide/legacy/macide.c
-+++ b/drivers/ide/legacy/macide.c
-@@ -1,5 +1,5 @@
- /*
-- *  linux/drivers/ide/legacy/macide.c -- Macintosh IDE Driver
-+ *  Macintosh IDE Driver
-  *
-  *     Copyright (C) 1998 by Michael Schmitz
-  *
-@@ -77,15 +77,17 @@ int macide_ack_intr(ide_hwif_t* hwif)
- 	return 0;
- }
+diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
+index 6f42877..fbe16d5 100644
+--- a/drivers/infiniband/core/mad.c
++++ b/drivers/infiniband/core/mad.c
+@@ -701,7 +701,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
+ 	}
  
-+static const char *mac_ide_name[] =
-+	{ "Quadra", "Powerbook", "Powerbook Baboon" };
-+
- /*
-  * Probe for a Macintosh IDE interface
-  */
+ 	/* Check to post send on QP or process locally */
+-	if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD)
++	if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD &&
++	    smi_check_local_returning_smp(smp, device) == IB_SMI_DISCARD)
+ 		goto out;
  
--void __init macide_init(void)
-+static int __init macide_init(void)
- {
- 	hw_regs_t hw;
- 	ide_hwif_t *hwif;
--	int index = -1;
+ 	local = kmalloc(sizeof *local, GFP_ATOMIC);
+@@ -752,8 +753,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
+ 		port_priv = ib_get_mad_port(mad_agent_priv->agent.device,
+ 					    mad_agent_priv->agent.port_num);
+ 		if (port_priv) {
+-			mad_priv->mad.mad.mad_hdr.tid =
+-				((struct ib_mad *)smp)->mad_hdr.tid;
++			memcpy(&mad_priv->mad.mad, smp, sizeof(struct ib_mad));
+ 			recv_mad_agent = find_mad_agent(port_priv,
+ 						        &mad_priv->mad.mad);
+ 		}
+@@ -1100,7 +1100,9 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
+ 		mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;
+ 		/* Timeout will be updated after send completes */
+ 		mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
+-		mad_send_wr->retries = send_buf->retries;
++		mad_send_wr->max_retries = send_buf->retries;
++		mad_send_wr->retries_left = send_buf->retries;
++		send_buf->retries = 0;
+ 		/* Reference for work request to QP + response */
+ 		mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
+ 		mad_send_wr->status = IB_WC_SUCCESS;
+@@ -1931,15 +1933,6 @@ local:
+ 	if (port_priv->device->process_mad) {
+ 		int ret;
  
- 	switch (macintosh_config->ide_type) {
- 	case MAC_IDE_QUADRA:
-@@ -93,48 +95,40 @@ void __init macide_init(void)
- 				0, 0, macide_ack_intr,
- //				quadra_ide_iops,
- 				IRQ_NUBUS_F);
--		index = ide_register_hw(&hw, NULL, 1, &hwif);
- 		break;
- 	case MAC_IDE_PB:
- 		ide_setup_ports(&hw, IDE_BASE, macide_offsets,
- 				0, 0, macide_ack_intr,
- //				macide_pb_iops,
- 				IRQ_NUBUS_C);
--		index = ide_register_hw(&hw, NULL, 1, &hwif);
- 		break;
- 	case MAC_IDE_BABOON:
- 		ide_setup_ports(&hw, BABOON_BASE, macide_offsets,
- 				0, 0, NULL,
- //				macide_baboon_iops,
- 				IRQ_BABOON_1);
--		index = ide_register_hw(&hw, NULL, 1, &hwif);
--		if (index == -1) break;
--		if (macintosh_config->ident == MAC_MODEL_PB190) {
--
--			/* Fix breakage in ide-disk.c: drive capacity	*/
--			/* is not initialized for drives without a 	*/
--			/* hardware ID, and we can't get that without	*/
--			/* probing the drive which freezes a 190.	*/
--
--			ide_drive_t *drive = &ide_hwifs[index].drives[0];
--			drive->capacity64 = drive->cyl*drive->head*drive->sect;
--
+-		if (!response) {
+-			printk(KERN_ERR PFX "No memory for response MAD\n");
+-			/*
+-			 * Is it better to assume that
+-			 * it wouldn't be processed ?
+-			 */
+-			goto out;
 -		}
- 		break;
 -
- 	default:
--	    return;
-+		return -ENODEV;
+ 		ret = port_priv->device->process_mad(port_priv->device, 0,
+ 						     port_priv->port_num,
+ 						     wc, &recv->grh,
+@@ -2282,8 +2275,6 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
+ 
+ 	/* Empty wait list to prevent receives from finding a request */
+ 	list_splice_init(&mad_agent_priv->wait_list, &cancel_list);
+-	/* Empty local completion list as well */
+-	list_splice_init(&mad_agent_priv->local_list, &cancel_list);
+ 	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+ 
+ 	/* Report all cancelled requests */
+@@ -2445,9 +2436,12 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
+ {
+ 	int ret;
+ 
+-	if (!mad_send_wr->retries--)
++	if (!mad_send_wr->retries_left)
+ 		return -ETIMEDOUT;
+ 
++	mad_send_wr->retries_left--;
++	mad_send_wr->send_buf.retries++;
++
+ 	mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
+ 
+ 	if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
+diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
+index 9be5cc0..8b75010 100644
+--- a/drivers/infiniband/core/mad_priv.h
++++ b/drivers/infiniband/core/mad_priv.h
+@@ -131,7 +131,8 @@ struct ib_mad_send_wr_private {
+ 	struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
+ 	__be64 tid;
+ 	unsigned long timeout;
+-	int retries;
++	int max_retries;
++	int retries_left;
+ 	int retry;
+ 	int refcount;
+ 	enum ib_wc_status status;
+diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
+index d43bc62..a5e2a31 100644
+--- a/drivers/infiniband/core/mad_rmpp.c
++++ b/drivers/infiniband/core/mad_rmpp.c
+@@ -684,7 +684,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
+ 
+ 	if (seg_num > mad_send_wr->last_ack) {
+ 		adjust_last_ack(mad_send_wr, seg_num);
+-		mad_send_wr->retries = mad_send_wr->send_buf.retries;
++		mad_send_wr->retries_left = mad_send_wr->max_retries;
  	}
+ 	mad_send_wr->newwin = newwin;
+ 	if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) {
+diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
+index 1bc1fe6..107f170 100644
+--- a/drivers/infiniband/core/multicast.c
++++ b/drivers/infiniband/core/multicast.c
+@@ -73,11 +73,20 @@ struct mcast_device {
+ };
  
--        if (index != -1) {
-+	printk(KERN_INFO "ide: Macintosh %s IDE controller\n",
-+			 mac_ide_name[macintosh_config->ide_type - 1]);
+ enum mcast_state {
+-	MCAST_IDLE,
+ 	MCAST_JOINING,
+ 	MCAST_MEMBER,
++	MCAST_ERROR,
++};
 +
-+	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif) {
-+		u8 index = hwif->index;
-+		u8 idx[4] = { index, 0xff, 0xff, 0xff };
++enum mcast_group_state {
++	MCAST_IDLE,
+ 	MCAST_BUSY,
+-	MCAST_ERROR
++	MCAST_GROUP_ERROR,
++	MCAST_PKEY_EVENT
++};
 +
-+		ide_init_port_data(hwif, index);
-+		ide_init_port_hw(hwif, &hw);
++enum {
++	MCAST_INVALID_PKEY_INDEX = 0xFFFF
+ };
+ 
+ struct mcast_member;
+@@ -93,9 +102,10 @@ struct mcast_group {
+ 	struct mcast_member	*last_join;
+ 	int			members[3];
+ 	atomic_t		refcount;
+-	enum mcast_state	state;
++	enum mcast_group_state	state;
+ 	struct ib_sa_query	*query;
+ 	int			query_id;
++	u16			pkey_index;
+ };
+ 
+ struct mcast_member {
+@@ -378,9 +388,19 @@ static int fail_join(struct mcast_group *group, struct mcast_member *member,
+ static void process_group_error(struct mcast_group *group)
+ {
+ 	struct mcast_member *member;
+-	int ret;
++	int ret = 0;
++	u16 pkey_index;
 +
- 		hwif->mmio = 1;
--		if (macintosh_config->ide_type == MAC_IDE_QUADRA)
--			printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
--		else if (macintosh_config->ide_type == MAC_IDE_PB)
--			printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index);
--		else if (macintosh_config->ide_type == MAC_IDE_BABOON)
--			printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index);
--		else
--			printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index);
++	if (group->state == MCAST_PKEY_EVENT)
++		ret = ib_find_pkey(group->port->dev->device,
++				   group->port->port_num,
++				   be16_to_cpu(group->rec.pkey), &pkey_index);
+ 
+ 	spin_lock_irq(&group->lock);
++	if (group->state == MCAST_PKEY_EVENT && !ret &&
++	    group->pkey_index == pkey_index)
++		goto out;
 +
-+		ide_device_add(idx, NULL);
+ 	while (!list_empty(&group->active_list)) {
+ 		member = list_entry(group->active_list.next,
+ 				    struct mcast_member, list);
+@@ -399,6 +419,7 @@ static void process_group_error(struct mcast_group *group)
  	}
-+
-+	return 0;
+ 
+ 	group->rec.join_state = 0;
++out:
+ 	group->state = MCAST_BUSY;
+ 	spin_unlock_irq(&group->lock);
  }
-+
-+module_init(macide_init);
-diff --git a/drivers/ide/legacy/q40ide.c b/drivers/ide/legacy/q40ide.c
-index 6ea46a6..2f0b34d 100644
---- a/drivers/ide/legacy/q40ide.c
-+++ b/drivers/ide/legacy/q40ide.c
-@@ -1,5 +1,5 @@
- /*
-- *  linux/drivers/ide/legacy/q40ide.c -- Q40 I/O port IDE Driver
-+ *  Q40 I/O port IDE Driver
-  *
-  *     (c) Richard Zidlicky
-  *
-@@ -111,15 +111,17 @@ static const char *q40_ide_names[Q40IDE_NUM_HWIFS]={
-  *  Probe for Q40 IDE interfaces
-  */
+@@ -415,9 +436,9 @@ static void mcast_work_handler(struct work_struct *work)
+ retest:
+ 	spin_lock_irq(&group->lock);
+ 	while (!list_empty(&group->pending_list) ||
+-	       (group->state == MCAST_ERROR)) {
++	       (group->state != MCAST_BUSY)) {
  
--void __init q40ide_init(void)
-+static int __init q40ide_init(void)
+-		if (group->state == MCAST_ERROR) {
++		if (group->state != MCAST_BUSY) {
+ 			spin_unlock_irq(&group->lock);
+ 			process_group_error(group);
+ 			goto retest;
+@@ -494,12 +515,19 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
+ 			 void *context)
  {
-     int i;
-     ide_hwif_t *hwif;
--    int index;
-     const char *name;
-+    u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	struct mcast_group *group = context;
++	u16 pkey_index = MCAST_INVALID_PKEY_INDEX;
  
-     if (!MACH_IS_Q40)
--      return ;
-+      return -ENODEV;
+ 	if (status)
+ 		process_join_error(group, status);
+ 	else {
++		ib_find_pkey(group->port->dev->device, group->port->port_num,
++			     be16_to_cpu(rec->pkey), &pkey_index);
 +
-+    printk(KERN_INFO "ide: Q40 IDE controller\n");
+ 		spin_lock_irq(&group->port->lock);
+ 		group->rec = *rec;
++		if (group->state == MCAST_BUSY &&
++		    group->pkey_index == MCAST_INVALID_PKEY_INDEX)
++			group->pkey_index = pkey_index;
+ 		if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
+ 			rb_erase(&group->node, &group->port->table);
+ 			mcast_insert(group->port, group, 1);
+@@ -539,6 +567,7 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
  
-     for (i = 0; i < Q40IDE_NUM_HWIFS; i++) {
- 	hw_regs_t hw;
-@@ -141,10 +143,20 @@ void __init q40ide_init(void)
- 			0, NULL,
- //			m68kide_iops,
- 			q40ide_default_irq(pcide_bases[i]));
--	index = ide_register_hw(&hw, NULL, 1, &hwif);
--	// **FIXME**
--	if (index != -1)
-+
-+	hwif = ide_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif) {
-+		ide_init_port_data(hwif, hwif->index);
-+		ide_init_port_hw(hwif, &hw);
- 		hwif->mmio = 1;
-+
-+		idx[i] = hwif->index;
-+	}
-     }
-+
-+    ide_device_add(idx, NULL);
-+
-+    return 0;
+ 	group->port = port;
+ 	group->rec.mgid = *mgid;
++	group->pkey_index = MCAST_INVALID_PKEY_INDEX;
+ 	INIT_LIST_HEAD(&group->pending_list);
+ 	INIT_LIST_HEAD(&group->active_list);
+ 	INIT_WORK(&group->work, mcast_work_handler);
+@@ -707,7 +736,8 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
  }
+ EXPORT_SYMBOL(ib_init_ah_from_mcmember);
  
-+module_init(q40ide_init);
-diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c
-index 912e738..bba29df 100644
---- a/drivers/ide/legacy/qd65xx.c
-+++ b/drivers/ide/legacy/qd65xx.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/legacy/qd65xx.c		Version 0.07	Sep 30, 2001
-- *
-  *  Copyright (C) 1996-2001  Linus Torvalds & author (see below)
-  */
+-static void mcast_groups_lost(struct mcast_port *port)
++static void mcast_groups_event(struct mcast_port *port,
++			       enum mcast_group_state state)
+ {
+ 	struct mcast_group *group;
+ 	struct rb_node *node;
+@@ -721,7 +751,8 @@ static void mcast_groups_lost(struct mcast_port *port)
+ 			atomic_inc(&group->refcount);
+ 			queue_work(mcast_wq, &group->work);
+ 		}
+-		group->state = MCAST_ERROR;
++		if (group->state != MCAST_GROUP_ERROR)
++			group->state = state;
+ 		spin_unlock(&group->lock);
+ 	}
+ 	spin_unlock_irqrestore(&port->lock, flags);
+@@ -731,16 +762,20 @@ static void mcast_event_handler(struct ib_event_handler *handler,
+ 				struct ib_event *event)
+ {
+ 	struct mcast_device *dev;
++	int index;
  
-@@ -307,18 +305,33 @@ static int __init qd_testreg(int port)
-  * called to setup an ata channel : adjusts attributes & links for tuning
-  */
+ 	dev = container_of(handler, struct mcast_device, event_handler);
++	index = event->element.port_num - dev->start_port;
  
--static void __init qd_setup(ide_hwif_t *hwif, int base, int config,
--			    unsigned int data0, unsigned int data1)
-+static void __init qd_setup(ide_hwif_t *hwif, int base, int config)
- {
--	hwif->chipset = ide_qd65xx;
--	hwif->channel = hwif->index;
- 	hwif->select_data = base;
- 	hwif->config_data = config;
--	hwif->drives[0].drive_data = data0;
--	hwif->drives[1].drive_data = data1;
--	hwif->drives[0].io_32bit =
--	hwif->drives[1].io_32bit = 1;
--	hwif->pio_mask = ATA_PIO4;
-+}
+ 	switch (event->event) {
+ 	case IB_EVENT_PORT_ERR:
+ 	case IB_EVENT_LID_CHANGE:
+ 	case IB_EVENT_SM_CHANGE:
+ 	case IB_EVENT_CLIENT_REREGISTER:
+-		mcast_groups_lost(&dev->port[event->element.port_num -
+-					     dev->start_port]);
++		mcast_groups_event(&dev->port[index], MCAST_GROUP_ERROR);
++		break;
++	case IB_EVENT_PKEY_CHANGE:
++		mcast_groups_event(&dev->port[index], MCAST_PKEY_EVENT);
+ 		break;
+ 	default:
+ 		break;
+diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
+index 1cfc298..aff96ba 100644
+--- a/drivers/infiniband/core/smi.h
++++ b/drivers/infiniband/core/smi.h
+@@ -59,7 +59,8 @@ extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
+ 					      u8 node_type, int port_num);
+ 
+ /*
+- * Return 1 if the SMP should be handled by the local SMA/SM via process_mad
++ * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
++ * via process_mad
+  */
+ static inline enum smi_action smi_check_local_smp(struct ib_smp *smp,
+ 						  struct ib_device *device)
+@@ -71,4 +72,19 @@ static inline enum smi_action smi_check_local_smp(struct ib_smp *smp,
+ 		(smp->hop_ptr == smp->hop_cnt + 1)) ?
+ 		IB_SMI_HANDLE : IB_SMI_DISCARD);
+ }
 +
-+static void __init qd6500_port_init_devs(ide_hwif_t *hwif)
++/*
++ * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
++ * via process_mad
++ */
++static inline enum smi_action smi_check_local_returning_smp(struct ib_smp *smp,
++						   struct ib_device *device)
 +{
-+	u8 base = hwif->select_data, config = QD_CONFIG(hwif);
-+
-+	hwif->drives[0].drive_data = QD6500_DEF_DATA;
-+	hwif->drives[1].drive_data = QD6500_DEF_DATA;
++	/* C14-13:3 -- We're at the end of the DR segment of path */
++	/* C14-13:4 -- Hop Pointer == 0 -> give to SM */
++	return ((device->process_mad &&
++		ib_get_smp_direction(smp) &&
++		!smp->hop_ptr) ? IB_SMI_HANDLE : IB_SMI_DISCARD);
 +}
 +
-+static void __init qd6580_port_init_devs(ide_hwif_t *hwif)
-+{
-+	u16 t1, t2;
-+	u8 base = hwif->select_data, config = QD_CONFIG(hwif);
-+
-+	if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
-+		t1 = QD6580_DEF_DATA;
-+		t2 = QD6580_DEF_DATA2;
-+	} else
-+		t2 = t1 = hwif->channel ? QD6580_DEF_DATA2 : QD6580_DEF_DATA;
-+
-+	hwif->drives[0].drive_data = t1;
-+	hwif->drives[1].drive_data = t2;
- }
+ #endif	/* __SMI_H_ */
+diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
+index 3d40506..c864ef7 100644
+--- a/drivers/infiniband/core/sysfs.c
++++ b/drivers/infiniband/core/sysfs.c
+@@ -508,19 +508,10 @@ static int add_port(struct ib_device *device, int port_num)
  
- /*
-@@ -358,6 +371,14 @@ static void __exit qd_unsetup(ide_hwif_t *hwif)
- }
- */
+ 	p->ibdev      = device;
+ 	p->port_num   = port_num;
+-	p->kobj.ktype = &port_type;
  
-+static const struct ide_port_info qd65xx_port_info __initdata = {
-+	.chipset		= ide_qd65xx,
-+	.host_flags		= IDE_HFLAG_IO_32BIT |
-+				  IDE_HFLAG_NO_DMA |
-+				  IDE_HFLAG_NO_AUTOTUNE,
-+	.pio_mask		= ATA_PIO4,
-+};
-+
- /*
-  * qd_probe:
-  *
-@@ -395,13 +416,14 @@ static int __init qd_probe(int base)
- 			return 1;
- 		}
+-	p->kobj.parent = kobject_get(&device->ports_parent);
+-	if (!p->kobj.parent) {
+-		ret = -EBUSY;
+-		goto err;
+-	}
+-
+-	ret = kobject_set_name(&p->kobj, "%d", port_num);
+-	if (ret)
+-		goto err_put;
+-
+-	ret = kobject_register(&p->kobj);
++	ret = kobject_init_and_add(&p->kobj, &port_type,
++				   kobject_get(device->ports_parent),
++				   "%d", port_num);
+ 	if (ret)
+ 		goto err_put;
  
--		qd_setup(hwif, base, config, QD6500_DEF_DATA, QD6500_DEF_DATA);
-+		qd_setup(hwif, base, config);
+@@ -549,6 +540,7 @@ static int add_port(struct ib_device *device, int port_num)
  
-+		hwif->port_init_devs = qd6500_port_init_devs;
- 		hwif->set_pio_mode = &qd6500_set_pio_mode;
+ 	list_add_tail(&p->kobj.entry, &device->port_list);
  
--		idx[0] = unit;
-+		idx[unit] = unit;
++	kobject_uevent(&p->kobj, KOBJ_ADD);
+ 	return 0;
  
--		ide_device_add(idx);
-+		ide_device_add(idx, &qd65xx_port_info);
+ err_free_pkey:
+@@ -570,9 +562,7 @@ err_remove_pma:
+ 	sysfs_remove_group(&p->kobj, &pma_group);
  
- 		return 1;
+ err_put:
+-	kobject_put(&device->ports_parent);
+-
+-err:
++	kobject_put(device->ports_parent);
+ 	kfree(p);
+ 	return ret;
+ }
+@@ -694,16 +684,9 @@ int ib_device_register_sysfs(struct ib_device *device)
+ 			goto err_unregister;
  	}
-@@ -428,14 +450,15 @@ static int __init qd_probe(int base)
- 			hwif = &ide_hwifs[unit];
- 			printk(KERN_INFO "%s: qd6580: single IDE board\n",
- 					 hwif->name);
--			qd_setup(hwif, base, config | (control << 8),
--				 QD6580_DEF_DATA, QD6580_DEF_DATA2);
- 
-+			qd_setup(hwif, base, config | (control << 8));
-+
-+			hwif->port_init_devs = qd6580_port_init_devs;
- 			hwif->set_pio_mode = &qd6580_set_pio_mode;
  
--			idx[0] = unit;
-+			idx[unit] = unit;
+-	device->ports_parent.parent = kobject_get(&class_dev->kobj);
+-	if (!device->ports_parent.parent) {
+-		ret = -EBUSY;
+-		goto err_unregister;
+-	}
+-	ret = kobject_set_name(&device->ports_parent, "ports");
+-	if (ret)
+-		goto err_put;
+-	ret = kobject_register(&device->ports_parent);
+-	if (ret)
++	device->ports_parent = kobject_create_and_add("ports",
++					kobject_get(&class_dev->kobj));
++	if (!device->ports_parent)
+ 		goto err_put;
  
--			ide_device_add(idx);
-+			ide_device_add(idx, &qd65xx_port_info);
+ 	if (device->node_type == RDMA_NODE_IB_SWITCH) {
+@@ -731,7 +714,7 @@ err_put:
+ 			sysfs_remove_group(p, &pma_group);
+ 			sysfs_remove_group(p, &port->pkey_group);
+ 			sysfs_remove_group(p, &port->gid_group);
+-			kobject_unregister(p);
++			kobject_put(p);
+ 		}
+ 	}
  
- 			outb(QD_DEF_CONTR, QD_CONTROL_PORT);
+@@ -755,10 +738,10 @@ void ib_device_unregister_sysfs(struct ib_device *device)
+ 		sysfs_remove_group(p, &pma_group);
+ 		sysfs_remove_group(p, &port->pkey_group);
+ 		sysfs_remove_group(p, &port->gid_group);
+-		kobject_unregister(p);
++		kobject_put(p);
+ 	}
  
-@@ -449,20 +472,20 @@ static int __init qd_probe(int base)
- 			printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
- 					hwif->name, mate->name);
+-	kobject_unregister(&device->ports_parent);
++	kobject_put(device->ports_parent);
+ 	class_device_unregister(&device->class_dev);
+ }
  
--			qd_setup(hwif, base, config | (control << 8),
--				 QD6580_DEF_DATA, QD6580_DEF_DATA);
-+			qd_setup(hwif, base, config | (control << 8));
+diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
+index 424983f..4291ab4 100644
+--- a/drivers/infiniband/core/ucm.c
++++ b/drivers/infiniband/core/ucm.c
+@@ -106,6 +106,9 @@ enum {
+ 	IB_UCM_MAX_DEVICES = 32
+ };
  
-+			hwif->port_init_devs = qd6580_port_init_devs;
- 			hwif->set_pio_mode = &qd6580_set_pio_mode;
++/* ib_cm and ib_user_cm modules share /sys/class/infiniband_cm */
++extern struct class cm_class;
++
+ #define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
  
--			qd_setup(mate, base, config | (control << 8),
--				 QD6580_DEF_DATA2, QD6580_DEF_DATA2);
-+			qd_setup(mate, base, config | (control << 8));
+ static void ib_ucm_add_one(struct ib_device *device);
+@@ -1199,7 +1202,7 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
+ 	return 0;
+ }
  
-+			mate->port_init_devs = qd6580_port_init_devs;
- 			mate->set_pio_mode = &qd6580_set_pio_mode;
+-static void ib_ucm_release_class_dev(struct class_device *class_dev)
++static void ucm_release_class_dev(struct class_device *class_dev)
+ {
+ 	struct ib_ucm_device *dev;
  
- 			idx[0] = 0;
- 			idx[1] = 1;
+@@ -1217,11 +1220,6 @@ static const struct file_operations ucm_fops = {
+ 	.poll    = ib_ucm_poll,
+ };
  
--			ide_device_add(idx);
-+			ide_device_add(idx, &qd65xx_port_info);
+-static struct class ucm_class = {
+-	.name    = "infiniband_cm",
+-	.release = ib_ucm_release_class_dev
+-};
+-
+ static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
+ {
+ 	struct ib_ucm_device *dev;
+@@ -1257,9 +1255,10 @@ static void ib_ucm_add_one(struct ib_device *device)
+ 	if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
+ 		goto err;
  
- 			outb(QD_DEF_CONTR, QD_CONTROL_PORT);
+-	ucm_dev->class_dev.class = &ucm_class;
++	ucm_dev->class_dev.class = &cm_class;
+ 	ucm_dev->class_dev.dev = device->dma_device;
+ 	ucm_dev->class_dev.devt = ucm_dev->dev.dev;
++	ucm_dev->class_dev.release = ucm_release_class_dev;
+ 	snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
+ 		 ucm_dev->devnum);
+ 	if (class_device_register(&ucm_dev->class_dev))
+@@ -1306,40 +1305,34 @@ static int __init ib_ucm_init(void)
+ 				     "infiniband_cm");
+ 	if (ret) {
+ 		printk(KERN_ERR "ucm: couldn't register device number\n");
+-		goto err;
++		goto error1;
+ 	}
  
-@@ -478,8 +501,7 @@ int probe_qd65xx = 0;
- module_param_named(probe, probe_qd65xx, bool, 0);
- MODULE_PARM_DESC(probe, "probe for QD65xx chipsets");
+-	ret = class_register(&ucm_class);
+-	if (ret) {
+-		printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
+-		goto err_chrdev;
+-	}
+-
+-	ret = class_create_file(&ucm_class, &class_attr_abi_version);
++	ret = class_create_file(&cm_class, &class_attr_abi_version);
+ 	if (ret) {
+ 		printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
+-		goto err_class;
++		goto error2;
+ 	}
  
--/* Can be called directly from ide.c. */
--int __init qd65xx_init(void)
-+static int __init qd65xx_init(void)
- {
- 	if (probe_qd65xx == 0)
- 		return -ENODEV;
-@@ -492,9 +514,7 @@ int __init qd65xx_init(void)
+ 	ret = ib_register_client(&ucm_client);
+ 	if (ret) {
+ 		printk(KERN_ERR "ucm: couldn't register client\n");
+-		goto err_class;
++		goto error3;
+ 	}
  	return 0;
- }
  
--#ifdef MODULE
- module_init(qd65xx_init);
--#endif
- 
- MODULE_AUTHOR("Samuel Thibault");
- MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
-diff --git a/drivers/ide/legacy/qd65xx.h b/drivers/ide/legacy/qd65xx.h
-index 633a424..28dd50a 100644
---- a/drivers/ide/legacy/qd65xx.h
-+++ b/drivers/ide/legacy/qd65xx.h
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/legacy/qd65xx.h
-- *
-  * Copyright (c) 2000	Linus Torvalds & authors
-  */
+-err_class:
+-	class_unregister(&ucm_class);
+-err_chrdev:
++error3:
++	class_remove_file(&cm_class, &class_attr_abi_version);
++error2:
+ 	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+-err:
++error1:
+ 	return ret;
+ }
  
-diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c
-index 79577b9..5696ba0 100644
---- a/drivers/ide/legacy/umc8672.c
-+++ b/drivers/ide/legacy/umc8672.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/legacy/umc8672.c		Version 0.05	Jul 31, 1996
-- *
-  *  Copyright (C) 1995-1996  Linus Torvalds & author (see below)
+ static void __exit ib_ucm_cleanup(void)
+ {
+ 	ib_unregister_client(&ucm_client);
+-	class_unregister(&ucm_class);
++	class_remove_file(&cm_class, &class_attr_abi_version);
+ 	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
+ 	idr_destroy(&ctx_id_table);
+ }
+diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
+index 90d675a..15937eb 100644
+--- a/drivers/infiniband/core/ucma.c
++++ b/drivers/infiniband/core/ucma.c
+@@ -31,6 +31,7 @@
   */
  
-@@ -122,9 +120,14 @@ static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	spin_unlock_irqrestore(&ide_lock, flags);
+ #include <linux/completion.h>
++#include <linux/file.h>
+ #include <linux/mutex.h>
+ #include <linux/poll.h>
+ #include <linux/idr.h>
+@@ -991,6 +992,96 @@ out:
+ 	return ret;
  }
  
-+static const struct ide_port_info umc8672_port_info __initdata = {
-+	.chipset		= ide_umc8672,
-+	.host_flags		= IDE_HFLAG_NO_DMA | IDE_HFLAG_NO_AUTOTUNE,
-+	.pio_mask		= ATA_PIO4,
-+};
++static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
++{
++	/* Acquire mutex's based on pointer comparison to prevent deadlock. */
++	if (file1 < file2) {
++		mutex_lock(&file1->mut);
++		mutex_lock(&file2->mut);
++	} else {
++		mutex_lock(&file2->mut);
++		mutex_lock(&file1->mut);
++	}
++}
 +
- static int __init umc8672_probe(void)
- {
--	ide_hwif_t *hwif, *mate;
- 	unsigned long flags;
- 	static u8 idx[4] = { 0, 1, 0xff, 0xff };
++static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
++{
++	if (file1 < file2) {
++		mutex_unlock(&file2->mut);
++		mutex_unlock(&file1->mut);
++	} else {
++		mutex_unlock(&file1->mut);
++		mutex_unlock(&file2->mut);
++	}
++}
++
++static void ucma_move_events(struct ucma_context *ctx, struct ucma_file *file)
++{
++	struct ucma_event *uevent, *tmp;
++
++	list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list)
++		if (uevent->ctx == ctx)
++			list_move_tail(&uevent->list, &file->event_list);
++}
++
++static ssize_t ucma_migrate_id(struct ucma_file *new_file,
++			       const char __user *inbuf,
++			       int in_len, int out_len)
++{
++	struct rdma_ucm_migrate_id cmd;
++	struct rdma_ucm_migrate_resp resp;
++	struct ucma_context *ctx;
++	struct file *filp;
++	struct ucma_file *cur_file;
++	int ret = 0;
++
++	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
++		return -EFAULT;
++
++	/* Get current fd to protect against it being closed */
++	filp = fget(cmd.fd);
++	if (!filp)
++		return -ENOENT;
++
++	/* Validate current fd and prevent destruction of id. */
++	ctx = ucma_get_ctx(filp->private_data, cmd.id);
++	if (IS_ERR(ctx)) {
++		ret = PTR_ERR(ctx);
++		goto file_put;
++	}
++
++	cur_file = ctx->file;
++	if (cur_file == new_file) {
++		resp.events_reported = ctx->events_reported;
++		goto response;
++	}
++
++	/*
++	 * Migrate events between fd's, maintaining order, and avoiding new
++	 * events being added before existing events.
++	 */
++	ucma_lock_files(cur_file, new_file);
++	mutex_lock(&mut);
++
++	list_move_tail(&ctx->list, &new_file->ctx_list);
++	ucma_move_events(ctx, new_file);
++	ctx->file = new_file;
++	resp.events_reported = ctx->events_reported;
++
++	mutex_unlock(&mut);
++	ucma_unlock_files(cur_file, new_file);
++
++response:
++	if (copy_to_user((void __user *)(unsigned long)cmd.response,
++			 &resp, sizeof(resp)))
++		ret = -EFAULT;
++
++	ucma_put_ctx(ctx);
++file_put:
++	fput(filp);
++	return ret;
++}
++
+ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
+ 				   const char __user *inbuf,
+ 				   int in_len, int out_len) = {
+@@ -1012,6 +1103,7 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
+ 	[RDMA_USER_CM_CMD_NOTIFY]	= ucma_notify,
+ 	[RDMA_USER_CM_CMD_JOIN_MCAST]	= ucma_join_multicast,
+ 	[RDMA_USER_CM_CMD_LEAVE_MCAST]	= ucma_leave_multicast,
++	[RDMA_USER_CM_CMD_MIGRATE_ID]	= ucma_migrate_id
+ };
  
-@@ -145,21 +148,10 @@ static int __init umc8672_probe(void)
- 	umc_set_speeds (current_speeds);
- 	local_irq_restore(flags);
+ static ssize_t ucma_write(struct file *filp, const char __user *buf,
+diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
+index b53eac4..4e91510 100644
+--- a/drivers/infiniband/core/user_mad.c
++++ b/drivers/infiniband/core/user_mad.c
+@@ -2,6 +2,7 @@
+  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
+  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
+  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
++ * Copyright (c) 2008 Cisco. All rights reserved.
+  *
+  * This software is available to you under a choice of one of two
+  * licenses.  You may choose to be licensed under the terms of the GNU
+@@ -42,7 +43,7 @@
+ #include <linux/cdev.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/poll.h>
+-#include <linux/rwsem.h>
++#include <linux/mutex.h>
+ #include <linux/kref.h>
+ #include <linux/compat.h>
  
--	hwif = &ide_hwifs[0];
--	mate = &ide_hwifs[1];
--
--	hwif->chipset = ide_umc8672;
--	hwif->pio_mask = ATA_PIO4;
--	hwif->set_pio_mode = &umc_set_pio_mode;
--	hwif->mate = mate;
--
--	mate->chipset = ide_umc8672;
--	mate->pio_mask = ATA_PIO4;
--	mate->set_pio_mode = &umc_set_pio_mode;
--	mate->mate = hwif;
--	mate->channel = 1;
-+	ide_hwifs[0].set_pio_mode = &umc_set_pio_mode;
-+	ide_hwifs[1].set_pio_mode = &umc_set_pio_mode;
+@@ -94,7 +95,7 @@ struct ib_umad_port {
+ 	struct class_device   *sm_class_dev;
+ 	struct semaphore       sm_sem;
  
--	ide_device_add(idx);
-+	ide_device_add(idx, &umc8672_port_info);
+-	struct rw_semaphore    mutex;
++	struct mutex	       file_mutex;
+ 	struct list_head       file_list;
  
- 	return 0;
+ 	struct ib_device      *ib_dev;
+@@ -110,11 +111,11 @@ struct ib_umad_device {
+ };
+ 
+ struct ib_umad_file {
++	struct mutex		mutex;
+ 	struct ib_umad_port    *port;
+ 	struct list_head	recv_list;
+ 	struct list_head	send_list;
+ 	struct list_head	port_list;
+-	spinlock_t		recv_lock;
+ 	spinlock_t		send_lock;
+ 	wait_queue_head_t	recv_wait;
+ 	struct ib_mad_agent    *agent[IB_UMAD_MAX_AGENTS];
+@@ -156,7 +157,7 @@ static int hdr_size(struct ib_umad_file *file)
+ 		sizeof (struct ib_user_mad_hdr_old);
  }
-@@ -169,8 +161,7 @@ int probe_umc8672 = 0;
- module_param_named(probe, probe_umc8672, bool, 0);
- MODULE_PARM_DESC(probe, "probe for UMC8672 chipset");
  
--/* Can be called directly from ide.c. */
--int __init umc8672_init(void)
-+static int __init umc8672_init(void)
+-/* caller must hold port->mutex at least for reading */
++/* caller must hold file->mutex */
+ static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
  {
- 	if (probe_umc8672 == 0)
- 		goto out;
-@@ -181,9 +172,7 @@ out:
- 	return -ENODEV;;
+ 	return file->agents_dead ? NULL : file->agent[id];
+@@ -168,32 +169,30 @@ static int queue_packet(struct ib_umad_file *file,
+ {
+ 	int ret = 1;
+ 
+-	down_read(&file->port->mutex);
++	mutex_lock(&file->mutex);
+ 
+ 	for (packet->mad.hdr.id = 0;
+ 	     packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
+ 	     packet->mad.hdr.id++)
+ 		if (agent == __get_agent(file, packet->mad.hdr.id)) {
+-			spin_lock_irq(&file->recv_lock);
+ 			list_add_tail(&packet->list, &file->recv_list);
+-			spin_unlock_irq(&file->recv_lock);
+ 			wake_up_interruptible(&file->recv_wait);
+ 			ret = 0;
+ 			break;
+ 		}
+ 
+-	up_read(&file->port->mutex);
++	mutex_unlock(&file->mutex);
+ 
+ 	return ret;
  }
  
--#ifdef MODULE
- module_init(umc8672_init);
--#endif
+ static void dequeue_send(struct ib_umad_file *file,
+ 			 struct ib_umad_packet *packet)
+- {
++{
+ 	spin_lock_irq(&file->send_lock);
+ 	list_del(&packet->list);
+ 	spin_unlock_irq(&file->send_lock);
+- }
++}
  
- MODULE_AUTHOR("Wolfram Podien");
- MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
-diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
-index a4ce3ba..0f4bf5d 100644
---- a/drivers/ide/mips/au1xxx-ide.c
-+++ b/drivers/ide/mips/au1xxx-ide.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/mips/au1xxx-ide.c  version 01.30.00        Aug. 02 2005
-- *
-  * BRIEF MODULE DESCRIPTION
-  * AMD Alchemy Au1xxx IDE interface routines over the Static Bus
-  *
-@@ -50,7 +48,6 @@
- #include <asm/mach-au1x00/au1xxx_ide.h>
+ static void send_handler(struct ib_mad_agent *agent,
+ 			 struct ib_mad_send_wc *send_wc)
+@@ -341,10 +340,10 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
+ 	if (count < hdr_size(file))
+ 		return -EINVAL;
  
- #define DRV_NAME	"au1200-ide"
--#define DRV_VERSION	"1.0"
- #define DRV_AUTHOR	"Enrico Walther <enrico.walther at amd.com> / Pete Popov <ppopov at embeddedalley.com>"
+-	spin_lock_irq(&file->recv_lock);
++	mutex_lock(&file->mutex);
  
- /* enable the burstmode in the dbdma */
-@@ -198,8 +195,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	while (list_empty(&file->recv_list)) {
+-		spin_unlock_irq(&file->recv_lock);
++		mutex_unlock(&file->mutex);
  
- 		break;
- #endif
--	default:
--		return;
+ 		if (filp->f_flags & O_NONBLOCK)
+ 			return -EAGAIN;
+@@ -353,13 +352,13 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
+ 					     !list_empty(&file->recv_list)))
+ 			return -ERESTARTSYS;
+ 
+-		spin_lock_irq(&file->recv_lock);
++		mutex_lock(&file->mutex);
  	}
  
- 	au_writel(mem_sttime,MEM_STTIME2);
-@@ -211,24 +206,6 @@ static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
-  */
+ 	packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
+ 	list_del(&packet->list);
  
- #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
--
--static int auide_build_sglist(ide_drive_t *drive,  struct request *rq)
--{
--	ide_hwif_t *hwif = drive->hwif;
--	_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
--	struct scatterlist *sg = hwif->sg_table;
--
--	ide_map_sg(drive, rq);
--
--	if (rq_data_dir(rq) == READ)
--		hwif->sg_dma_direction = DMA_FROM_DEVICE;
--	else
--		hwif->sg_dma_direction = DMA_TO_DEVICE;
--
--	return dma_map_sg(ahwif->dev, sg, hwif->sg_nents,
--			  hwif->sg_dma_direction);
--}
--
- static int auide_build_dmatable(ide_drive_t *drive)
- {
- 	int i, iswrite, count = 0;
-@@ -243,8 +220,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
- 	/* Save for interrupt context */
- 	ahwif->drive = drive;
+-	spin_unlock_irq(&file->recv_lock);
++	mutex_unlock(&file->mutex);
+ 
+ 	if (packet->recv_wc)
+ 		ret = copy_recv_mad(file, buf, packet, count);
+@@ -368,9 +367,9 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
+ 
+ 	if (ret < 0) {
+ 		/* Requeue packet */
+-		spin_lock_irq(&file->recv_lock);
++		mutex_lock(&file->mutex);
+ 		list_add(&packet->list, &file->recv_list);
+-		spin_unlock_irq(&file->recv_lock);
++		mutex_unlock(&file->mutex);
+ 	} else {
+ 		if (packet->recv_wc)
+ 			ib_free_recv_mad(packet->recv_wc);
+@@ -481,7 +480,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
+ 		goto err;
+ 	}
  
--	/* Build sglist */
--	hwif->sg_nents = i = auide_build_sglist(drive, rq);
-+	hwif->sg_nents = i = ide_build_sglist(drive, rq);
+-	down_read(&file->port->mutex);
++	mutex_lock(&file->mutex);
  
- 	if (!i)
- 		return 0;
-@@ -302,10 +278,7 @@ static int auide_build_dmatable(ide_drive_t *drive)
- 		return 1;
+ 	agent = __get_agent(file, packet->mad.hdr.id);
+ 	if (!agent) {
+@@ -577,7 +576,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
+ 	if (ret)
+ 		goto err_send;
  
-  use_pio_instead:
--	dma_unmap_sg(ahwif->dev,
--		     hwif->sg_table,
--		     hwif->sg_nents,
--		     hwif->sg_dma_direction);
-+	ide_destroy_dmatable(drive);
+-	up_read(&file->port->mutex);
++	mutex_unlock(&file->mutex);
+ 	return count;
  
- 	return 0; /* revert to PIO for this request */
- }
-@@ -313,11 +286,9 @@ static int auide_build_dmatable(ide_drive_t *drive)
- static int auide_dma_end(ide_drive_t *drive)
+ err_send:
+@@ -587,7 +586,7 @@ err_msg:
+ err_ah:
+ 	ib_destroy_ah(ah);
+ err_up:
+-	up_read(&file->port->mutex);
++	mutex_unlock(&file->mutex);
+ err:
+ 	kfree(packet);
+ 	return ret;
+@@ -613,11 +612,12 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
  {
- 	ide_hwif_t *hwif = HWIF(drive);
--	_auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data;
+ 	struct ib_user_mad_reg_req ureq;
+ 	struct ib_mad_reg_req req;
+-	struct ib_mad_agent *agent;
++	struct ib_mad_agent *agent = NULL;
+ 	int agent_id;
+ 	int ret;
  
- 	if (hwif->sg_nents) {
--		dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents,
--			     hwif->sg_dma_direction);
-+		ide_destroy_dmatable(drive);
- 		hwif->sg_nents = 0;
- 	}
+-	down_write(&file->port->mutex);
++	mutex_lock(&file->port->file_mutex);
++	mutex_lock(&file->mutex);
  
-@@ -397,26 +368,10 @@ static int auide_dma_test_irq(ide_drive_t *drive)
- 	return 0;
- }
+ 	if (!file->port->ib_dev) {
+ 		ret = -EPIPE;
+@@ -666,13 +666,13 @@ found:
+ 				      send_handler, recv_handler, file);
+ 	if (IS_ERR(agent)) {
+ 		ret = PTR_ERR(agent);
++		agent = NULL;
+ 		goto out;
+ 	}
  
--static void auide_dma_host_on(ide_drive_t *drive)
-+static void auide_dma_host_set(ide_drive_t *drive, int on)
- {
- }
+ 	if (put_user(agent_id,
+ 		     (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) {
+ 		ret = -EFAULT;
+-		ib_unregister_mad_agent(agent);
+ 		goto out;
+ 	}
  
--static int auide_dma_on(ide_drive_t *drive)
--{
--	drive->using_dma = 1;
--
--	return 0;
--}
--
--static void auide_dma_host_off(ide_drive_t *drive)
--{
--}
--
--static void auide_dma_off_quietly(ide_drive_t *drive)
--{
--	drive->using_dma = 0;
--}
--
- static void auide_dma_lost_irq(ide_drive_t *drive)
- {
- 	printk(KERN_ERR "%s: IRQ lost\n", drive->name);
-@@ -522,7 +477,7 @@ static int auide_ddma_init(_auide_hwif *auide) {
- 	auide->rx_desc_head = (void*)au1xxx_dbdma_ring_alloc(auide->rx_chan,
- 							     NUM_DESCRIPTORS);
-  
--	hwif->dmatable_cpu = dma_alloc_coherent(auide->dev,
-+	hwif->dmatable_cpu = dma_alloc_coherent(hwif->dev,
- 						PRD_ENTRIES * PRD_BYTES,        /* 1 Page */
- 						&hwif->dmatable_dma, GFP_KERNEL);
- 	
-@@ -593,6 +548,17 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif)
- 	*ata_regs = ahwif->regbase + (14 << AU1XXX_ATA_REG_OFFSET);
- }
+@@ -690,7 +690,13 @@ found:
+ 	ret = 0;
  
-+static const struct ide_port_info au1xxx_port_info = {
-+	.host_flags		= IDE_HFLAG_POST_SET_MODE |
-+				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
-+				  IDE_HFLAG_NO_IO_32BIT |
-+				  IDE_HFLAG_UNMASK_IRQS,
-+	.pio_mask		= ATA_PIO4,
-+#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
-+	.mwdma_mask		= ATA_MWDMA2,
-+#endif
-+};
+ out:
+-	up_write(&file->port->mutex);
++	mutex_unlock(&file->mutex);
 +
- static int au_ide_probe(struct device *dev)
- {
- 	struct platform_device *pdev = to_platform_device(dev);
-@@ -610,9 +576,6 @@ static int au_ide_probe(struct device *dev)
- #endif
++	if (ret && agent)
++		ib_unregister_mad_agent(agent);
++
++	mutex_unlock(&file->port->file_mutex);
++
+ 	return ret;
+ }
  
- 	memset(&auide_hwif, 0, sizeof(_auide_hwif));
--	auide_hwif.dev                  = 0;
--
--	ahwif->dev = dev;
- 	ahwif->irq = platform_get_irq(pdev, 0);
+@@ -703,7 +709,8 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
+ 	if (get_user(id, arg))
+ 		return -EFAULT;
  
- 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-@@ -643,28 +606,16 @@ static int au_ide_probe(struct device *dev)
- 	/* FIXME:  This might possibly break PCMCIA IDE devices */
+-	down_write(&file->port->mutex);
++	mutex_lock(&file->port->file_mutex);
++	mutex_lock(&file->mutex);
  
- 	hwif                            = &ide_hwifs[pdev->id];
--	hwif->irq			= ahwif->irq;
--	hwif->chipset                   = ide_au1xxx;
+ 	if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
+ 		ret = -EINVAL;
+@@ -714,11 +721,13 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
+ 	file->agent[id] = NULL;
  
- 	memset(&hw, 0, sizeof(hw));
- 	auide_setup_ports(&hw, ahwif);
--	memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
-+	hw.irq = ahwif->irq;
-+	hw.dev = dev;
-+	hw.chipset = ide_au1xxx;
+ out:
+-	up_write(&file->port->mutex);
++	mutex_unlock(&file->mutex);
  
--	hwif->ultra_mask                = 0x0;  /* Disable Ultra DMA */
--#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
--	hwif->mwdma_mask                = 0x07; /* Multimode-2 DMA  */
--	hwif->swdma_mask                = 0x00;
--#else
--	hwif->mwdma_mask                = 0x0;
--	hwif->swdma_mask                = 0x0;
--#endif
--
--	hwif->pio_mask = ATA_PIO4;
--	hwif->host_flags = IDE_HFLAG_POST_SET_MODE;
-+	ide_init_port_hw(hwif, &hw);
+ 	if (agent)
+ 		ib_unregister_mad_agent(agent);
  
--	hwif->noprobe = 0;
--	hwif->drives[0].unmask          = 1;
--	hwif->drives[1].unmask          = 1;
-+	hwif->dev = dev;
++	mutex_unlock(&file->port->file_mutex);
++
+ 	return ret;
+ }
  
- 	/* hold should be on in all cases */
- 	hwif->hold                      = 1;
-@@ -684,32 +635,21 @@ static int au_ide_probe(struct device *dev)
- 	hwif->set_dma_mode		= &auide_set_dma_mode;
+@@ -726,12 +735,12 @@ static long ib_umad_enable_pkey(struct ib_umad_file *file)
+ {
+ 	int ret = 0;
  
- #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
--	hwif->dma_off_quietly		= &auide_dma_off_quietly;
- 	hwif->dma_timeout		= &auide_dma_timeout;
+-	down_write(&file->port->mutex);
++	mutex_lock(&file->mutex);
+ 	if (file->already_used)
+ 		ret = -EINVAL;
+ 	else
+ 		file->use_pkey_index = 1;
+-	up_write(&file->port->mutex);
++	mutex_unlock(&file->mutex);
  
- 	hwif->mdma_filter		= &auide_mdma_filter;
+ 	return ret;
+ }
+@@ -783,7 +792,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
+ 	if (!port)
+ 		return -ENXIO;
  
-+	hwif->dma_host_set		= &auide_dma_host_set;
- 	hwif->dma_exec_cmd              = &auide_dma_exec_cmd;
- 	hwif->dma_start                 = &auide_dma_start;
- 	hwif->ide_dma_end               = &auide_dma_end;
- 	hwif->dma_setup                 = &auide_dma_setup;
- 	hwif->ide_dma_test_irq          = &auide_dma_test_irq;
--	hwif->dma_host_off		= &auide_dma_host_off;
--	hwif->dma_host_on		= &auide_dma_host_on;
- 	hwif->dma_lost_irq		= &auide_dma_lost_irq;
--	hwif->ide_dma_on                = &auide_dma_on;
--#else /* !CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */
--	hwif->channel                   = 0;
--	hwif->hold                      = 1;
-+#endif
- 	hwif->select_data               = 0;    /* no chipset-specific code */
- 	hwif->config_data               = 0;    /* no chipset-specific code */
+-	down_write(&port->mutex);
++	mutex_lock(&port->file_mutex);
  
--	hwif->drives[0].autotune        = 1;    /* 1=autotune, 2=noautotune, 0=default */
--	hwif->drives[1].autotune	= 1;
--#endif
--	hwif->drives[0].no_io_32bit	= 1;
--	hwif->drives[1].no_io_32bit	= 1;
--
- 	auide_hwif.hwif                 = hwif;
- 	hwif->hwif_data                 = &auide_hwif;
+ 	if (!port->ib_dev) {
+ 		ret = -ENXIO;
+@@ -797,7 +806,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
+ 		goto out;
+ 	}
  
-@@ -720,7 +660,7 @@ static int au_ide_probe(struct device *dev)
+-	spin_lock_init(&file->recv_lock);
++	mutex_init(&file->mutex);
+ 	spin_lock_init(&file->send_lock);
+ 	INIT_LIST_HEAD(&file->recv_list);
+ 	INIT_LIST_HEAD(&file->send_list);
+@@ -809,7 +818,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
+ 	list_add_tail(&file->port_list, &port->file_list);
  
- 	idx[0] = hwif->index;
+ out:
+-	up_write(&port->mutex);
++	mutex_unlock(&port->file_mutex);
+ 	return ret;
+ }
  
--	ide_device_add(idx);
-+	ide_device_add(idx, &au1xxx_port_info);
+@@ -821,7 +830,8 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
+ 	int already_dead;
+ 	int i;
  
- 	dev_set_drvdata(dev, hwif);
+-	down_write(&file->port->mutex);
++	mutex_lock(&file->port->file_mutex);
++	mutex_lock(&file->mutex);
  
-@@ -737,7 +677,7 @@ static int au_ide_remove(struct device *dev)
- 	ide_hwif_t *hwif = dev_get_drvdata(dev);
- 	_auide_hwif *ahwif = &auide_hwif;
+ 	already_dead = file->agents_dead;
+ 	file->agents_dead = 1;
+@@ -834,14 +844,14 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
  
--	ide_unregister(hwif - ide_hwifs);
-+	ide_unregister(hwif->index, 0, 0);
+ 	list_del(&file->port_list);
  
- 	iounmap((void *)ahwif->regbase);
+-	downgrade_write(&file->port->mutex);
++	mutex_unlock(&file->mutex);
  
-diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c
-index 521edd4..956259f 100644
---- a/drivers/ide/mips/swarm.c
-+++ b/drivers/ide/mips/swarm.c
-@@ -117,6 +117,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
- 	default_hwif_mmiops(hwif);
- 	/* Prevent resource map manipulation.  */
- 	hwif->mmio = 1;
-+	hwif->chipset = ide_generic;
- 	hwif->noprobe = 0;
+ 	if (!already_dead)
+ 		for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
+ 			if (file->agent[i])
+ 				ib_unregister_mad_agent(file->agent[i]);
  
- 	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
-@@ -128,7 +129,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
+-	up_read(&file->port->mutex);
++	mutex_unlock(&file->port->file_mutex);
  
- 	idx[0] = hwif->index;
+ 	kfree(file);
+ 	kref_put(&dev->ref, ib_umad_release_dev);
+@@ -914,10 +924,10 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
+ 	};
+ 	int ret = 0;
  
--	ide_device_add(idx);
-+	ide_device_add(idx, NULL);
+-	down_write(&port->mutex);
++	mutex_lock(&port->file_mutex);
+ 	if (port->ib_dev)
+ 		ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
+-	up_write(&port->mutex);
++	mutex_unlock(&port->file_mutex);
  
- 	dev_set_drvdata(dev, hwif);
+ 	up(&port->sm_sem);
  
-diff --git a/drivers/ide/pci/Makefile b/drivers/ide/pci/Makefile
-index 95d1ea8..9480325 100644
---- a/drivers/ide/pci/Makefile
-+++ b/drivers/ide/pci/Makefile
-@@ -36,4 +36,8 @@ obj-$(CONFIG_BLK_DEV_VIA82CXXX)		+= via82cxxx.o
- # Must appear at the end of the block
- obj-$(CONFIG_BLK_DEV_GENERIC)          += generic.o
+@@ -981,7 +991,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
+ 	port->ib_dev   = device;
+ 	port->port_num = port_num;
+ 	init_MUTEX(&port->sm_sem);
+-	init_rwsem(&port->mutex);
++	mutex_init(&port->file_mutex);
+ 	INIT_LIST_HEAD(&port->file_list);
  
-+ifeq ($(CONFIG_BLK_DEV_CMD640), m)
-+	obj-m += cmd640.o
-+endif
-+
- EXTRA_CFLAGS	:= -Idrivers/ide
-diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
-index 4426850..cfb3265 100644
---- a/drivers/ide/pci/aec62xx.c
-+++ b/drivers/ide/pci/aec62xx.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/aec62xx.c		Version 0.27	Sep 16, 2007
-- *
-  * Copyright (C) 1999-2002	Andre Hedrick <andre at linux-ide.org>
-  * Copyright (C) 2007		MontaVista Software, Inc. <source at mvista.com>
-  *
-@@ -9,7 +7,6 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
-@@ -90,7 +87,7 @@ static u8 pci_bus_clock_list_ultra (u8 speed, struct chipset_bus_clock_list_entr
- static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u16 d_conf		= 0;
- 	u8 ultra = 0, ultra_conf = 0;
- 	u8 tmp0 = 0, tmp1 = 0, tmp2 = 0;
-@@ -116,7 +113,7 @@ static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
- static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
+ 	port->dev = cdev_alloc();
+@@ -1052,6 +1062,7 @@ err_cdev:
+ static void ib_umad_kill_port(struct ib_umad_port *port)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 unit		= (drive->select.b.unit & 0x01);
- 	u8 tmp1 = 0, tmp2 = 0;
- 	u8 ultra = 0, drive_conf = 0, ultra_conf = 0;
-@@ -168,29 +165,28 @@ static unsigned int __devinit init_chipset_aec62xx(struct pci_dev *dev, const ch
- 	return dev->irq;
- }
+ 	struct ib_umad_file *file;
++	int already_dead;
+ 	int id;
  
-+static u8 __devinit atp86x_cable_detect(ide_hwif_t *hwif)
-+{
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
-+
-+	pci_read_config_byte(dev, 0x49, &ata66);
-+
-+	return (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-+}
-+
- static void __devinit init_hwif_aec62xx(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+ 	class_set_devdata(port->class_dev,    NULL);
+@@ -1067,42 +1078,22 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
+ 	umad_port[port->dev_num] = NULL;
+ 	spin_unlock(&port_lock);
  
- 	hwif->set_pio_mode = &aec_set_pio_mode;
+-	down_write(&port->mutex);
++	mutex_lock(&port->file_mutex);
  
- 	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
- 		hwif->set_dma_mode = &aec6210_set_mode;
--	else
-+	else {
- 		hwif->set_dma_mode = &aec6260_set_mode;
+ 	port->ib_dev = NULL;
  
--	if (hwif->dma_base == 0)
--		return;
--
--	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF)
--		return;
+-	/*
+-	 * Now go through the list of files attached to this port and
+-	 * unregister all of their MAD agents.  We need to hold
+-	 * port->mutex while doing this to avoid racing with
+-	 * ib_umad_close(), but we can't hold the mutex for writing
+-	 * while calling ib_unregister_mad_agent(), since that might
+-	 * deadlock by calling back into queue_packet().  So we
+-	 * downgrade our lock to a read lock, and then drop and
+-	 * reacquire the write lock for the next iteration.
+-	 *
+-	 * We do list_del_init() on the file's list_head so that the
+-	 * list_del in ib_umad_close() is still OK, even after the
+-	 * file is removed from the list.
+-	 */
+-	while (!list_empty(&port->file_list)) {
+-		file = list_entry(port->file_list.next, struct ib_umad_file,
+-				  port_list);
 -
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
--		u8 ata66 = 0, mask = hwif->channel ? 0x02 : 0x01;
++	list_for_each_entry(file, &port->file_list, port_list) {
++		mutex_lock(&file->mutex);
++		already_dead = file->agents_dead;
+ 		file->agents_dead = 1;
+-		list_del_init(&file->port_list);
 -
--		pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+-		downgrade_write(&port->mutex);
++		mutex_unlock(&file->mutex);
+ 
+ 		for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)
+ 			if (file->agent[id])
+ 				ib_unregister_mad_agent(file->agent[id]);
 -
--		hwif->cbl = (ata66 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-+		hwif->cable_detect = atp86x_cable_detect;
+-		up_read(&port->mutex);
+-		down_write(&port->mutex);
  	}
- }
  
-@@ -202,6 +198,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
- 		.host_flags	= IDE_HFLAG_SERIALIZE |
- 				  IDE_HFLAG_NO_ATAPI_DMA |
-+				  IDE_HFLAG_NO_DSC |
-+				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
- 				  IDE_HFLAG_OFF_BOARD,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
-@@ -211,6 +209,7 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- 		.init_chipset	= init_chipset_aec62xx,
- 		.init_hwif	= init_hwif_aec62xx,
- 		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_NO_AUTODMA |
-+				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
- 				  IDE_HFLAG_OFF_BOARD,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
-@@ -220,7 +219,8 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- 		.init_chipset	= init_chipset_aec62xx,
- 		.init_hwif	= init_hwif_aec62xx,
- 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA,
-+		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
-+				  IDE_HFLAG_ABUSE_SET_DMA_MODE,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA4,
-@@ -228,7 +228,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- 		.name		= "AEC6280",
- 		.init_chipset	= init_chipset_aec62xx,
- 		.init_hwif	= init_hwif_aec62xx,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
-+				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
-+				  IDE_HFLAG_OFF_BOARD,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA5,
-@@ -237,7 +239,9 @@ static const struct ide_port_info aec62xx_chipsets[] __devinitdata = {
- 		.init_chipset	= init_chipset_aec62xx,
- 		.init_hwif	= init_hwif_aec62xx,
- 		.enablebits	= {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}},
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
-+				  IDE_HFLAG_ABUSE_SET_DMA_MODE |
-+				  IDE_HFLAG_OFF_BOARD,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA5,
-diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
-index ce29393..b3b6f51 100644
---- a/drivers/ide/pci/alim15x3.c
-+++ b/drivers/ide/pci/alim15x3.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/alim15x3.c		Version 0.29	Sep 16 2007
-- *
-  *  Copyright (C) 1998-2000 Michel Aubry, Maintainer
-  *  Copyright (C) 1998-2000 Andrzej Krzysztofowicz, Maintainer
-  *  Copyright (C) 1999-2000 CJ, cjtsai at ali.com.tw, Maintainer
-@@ -33,7 +31,6 @@
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
-@@ -293,7 +290,7 @@ static int ali_get_info (char *buffer, char **addr, off_t offset, int count)
- static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	int s_time, a_time, c_time;
- 	u8 s_clc, a_clc, r_clc;
- 	unsigned long flags;
-@@ -396,15 +393,12 @@ static u8 ali_udma_filter(ide_drive_t *drive)
- static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 speed1		= speed;
- 	u8 unit			= (drive->select.b.unit & 0x01);
- 	u8 tmpbyte		= 0x00;
- 	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56;
+-	up_write(&port->mutex);
++	mutex_unlock(&port->file_mutex);
  
--	if (speed < XFER_PIO_0)
--		return;
--
- 	if (speed == XFER_UDMA_6)
- 		speed1 = 0x47;
+ 	clear_bit(port->dev_num, dev_map);
+ }
+diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile
+index 36b9898..7e7b5a6 100644
+--- a/drivers/infiniband/hw/cxgb3/Makefile
++++ b/drivers/infiniband/hw/cxgb3/Makefile
+@@ -1,5 +1,4 @@
+-EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 \
+-		-I$(TOPDIR)/drivers/infiniband/hw/cxgb3/core
++EXTRA_CFLAGS += -Idrivers/net/cxgb3
  
-@@ -628,7 +622,7 @@ static int ali_cable_override(struct pci_dev *pdev)
+ obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
  
- static u8 __devinit ata66_ali15x3(ide_hwif_t *hwif)
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
+index eec6a30..03c5ff6 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
++++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
+@@ -179,7 +179,7 @@ int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
+ 	setup.size = 1UL << cq->size_log2;
+ 	setup.credits = 65535;
+ 	setup.credit_thres = 1;
+-	if (rdev_p->t3cdev_p->type == T3B)
++	if (rdev_p->t3cdev_p->type != T3A)
+ 		setup.ovfl_mode = 0;
+ 	else
+ 		setup.ovfl_mode = 1;
+@@ -584,7 +584,7 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
  {
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	unsigned long flags;
- 	u8 cbl = ATA_CBL_PATA40, tmpbyte;
+ 	u32 i, nr_wqe, copy_len;
+ 	u8 *copy_data;
+-	u8 wr_len, utx_len;	/* lenght in 8 byte flit */
++	u8 wr_len, utx_len;	/* length in 8 byte flit */
+ 	enum t3_wr_flags flag;
+ 	__be64 *wqe;
+ 	u64 utx_cmd;
+diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
+index c84d4ac..969d4d9 100644
+--- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
++++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
+@@ -315,7 +315,7 @@ struct t3_rdma_init_wr {
+ 	__be32 ird;
+ 	__be64 qp_dma_addr;	/* 7 */
+ 	__be32 qp_dma_size;	/* 8 */
+-	u32 irs;
++	__be32 irs;
+ };
  
-@@ -671,13 +665,12 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
- 	hwif->set_dma_mode = &ali_set_dma_mode;
- 	hwif->udma_filter = &ali_udma_filter;
+ struct t3_genbit {
+@@ -324,7 +324,8 @@ struct t3_genbit {
+ };
  
-+	hwif->cable_detect = ata66_ali15x3;
-+
- 	if (hwif->dma_base == 0)
- 		return;
+ enum rdma_init_wr_flags {
+-	RECVS_POSTED = 1,
++	RECVS_POSTED = (1<<0),
++	PRIV_QP = (1<<1),
+ };
  
- 	hwif->dma_setup = &ali15x3_dma_setup;
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = ata66_ali15x3(hwif);
+ union t3_wr {
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+index 20ba372..e9a08fa 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
+@@ -332,7 +332,7 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
+ 			  }
+ 	};
+ 
+-	if (ip_route_output_flow(&rt, &fl, NULL, 0))
++	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+ 		return NULL;
+ 	return rt;
  }
+@@ -1118,7 +1118,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
+ 	     status2errno(rpl->status));
+ 	connect_reply_upcall(ep, status2errno(rpl->status));
+ 	state_set(&ep->com, DEAD);
+-	if (ep->com.tdev->type == T3B && act_open_has_tid(rpl->status))
++	if (ep->com.tdev->type != T3A && act_open_has_tid(rpl->status))
+ 		release_tid(ep->com.tdev, GET_TID(rpl), NULL);
+ 	cxgb3_free_atid(ep->com.tdev, ep->atid);
+ 	dst_release(ep->dst);
+@@ -1249,7 +1249,7 @@ static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip,
+ 	skb_trim(skb, sizeof(struct cpl_tid_release));
+ 	skb_get(skb);
  
- /**
-@@ -691,12 +684,13 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
+-	if (tdev->type == T3B)
++	if (tdev->type != T3A)
+ 		release_tid(tdev, hwtid, skb);
+ 	else {
+ 		struct cpl_pass_accept_rpl *rpl;
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
+index a6c2c4b..73bfd16 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_mem.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
+@@ -122,6 +122,13 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
+ 		*total_size += buffer_list[i].size;
+ 		if (i > 0)
+ 			mask |= buffer_list[i].addr;
++		else
++			mask |= buffer_list[i].addr & PAGE_MASK;
++		if (i != num_phys_buf - 1)
++			mask |= buffer_list[i].addr + buffer_list[i].size;
++		else
++			mask |= (buffer_list[i].addr + buffer_list[i].size +
++				PAGE_SIZE - 1) & PAGE_MASK;
+ 	}
  
- static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	u8 ideic, inmir;
- 	s8 irq_routing_table[] = { -1,  9, 3, 10, 4,  5, 7,  6,
- 				      1, 11, 0, 12, 0, 14, 0, 15 };
- 	int irq = -1;
+ 	if (*total_size > 0xFFFFFFFFULL)
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+index b5436ca..df1838f 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
+@@ -39,6 +39,7 @@
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+ #include <linux/ethtool.h>
++#include <linux/rtnetlink.h>
  
--	if (hwif->pci_dev->device == PCI_DEVICE_ID_AL_M5229)
-+	if (dev->device == PCI_DEVICE_ID_AL_M5229)
- 		hwif->irq = hwif->channel ? 15 : 14;
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -645,7 +646,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+ 	if (err)
+ 		goto err;
  
- 	if (isa_dev) {
-@@ -748,7 +742,7 @@ static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase)
- 		return;
- 	if (!hwif->channel)
- 		outb(inb(dmabase + 2) & 0x60, dmabase + 2);
--	ide_setup_dma(hwif, dmabase, 8);
-+	ide_setup_dma(hwif, dmabase);
+-	if (udata && t3b_device(rhp)) {
++	if (udata && !t3a_device(rhp)) {
+ 		uresp.pbl_addr = (mhp->attr.pbl_addr -
+ 	                         rhp->rdev.rnic_info.pbl_base) >> 3;
+ 		PDBG("%s user resp pbl_addr 0x%x\n", __FUNCTION__,
+@@ -1053,7 +1054,9 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
+ 	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
+ 
+ 	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
++	rtnl_lock();
+ 	lldev->ethtool_ops->get_drvinfo(lldev, &info);
++	rtnl_unlock();
+ 	return sprintf(buf, "%s\n", info.fw_version);
  }
  
- static const struct ide_port_info ali15x3_chipset __devinitdata = {
-@@ -778,7 +772,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
- 	};
+@@ -1065,7 +1068,9 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
+ 	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
  
- 	struct ide_port_info d = ali15x3_chipset;
--	u8 rev = dev->revision;
-+	u8 rev = dev->revision, idx = id->driver_data;
+ 	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
++	rtnl_lock();
+ 	lldev->ethtool_ops->get_drvinfo(lldev, &info);
++	rtnl_unlock();
+ 	return sprintf(buf, "%s\n", info.driver);
+ }
  
- 	if (pci_dev_present(ati_rs100))
- 		printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n");
-@@ -801,6 +795,9 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
- 			d.udma_mask = ATA_UDMA6;
+diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+index dd89b6b..ea2cdd7 100644
+--- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
++++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
+@@ -208,36 +208,19 @@ static int iwch_sgl2pbl_map(struct iwch_dev *rhp, struct ib_sge *sg_list,
+ static int iwch_build_rdma_recv(struct iwch_dev *rhp, union t3_wr *wqe,
+ 				struct ib_recv_wr *wr)
+ {
+-	int i, err = 0;
+-	u32 pbl_addr[4];
+-	u8 page_size[4];
++	int i;
+ 	if (wr->num_sge > T3_MAX_SGE)
+ 		return -EINVAL;
+-	err = iwch_sgl2pbl_map(rhp, wr->sg_list, wr->num_sge, pbl_addr,
+-			       page_size);
+-	if (err)
+-		return err;
+-	wqe->recv.pagesz[0] = page_size[0];
+-	wqe->recv.pagesz[1] = page_size[1];
+-	wqe->recv.pagesz[2] = page_size[2];
+-	wqe->recv.pagesz[3] = page_size[3];
+ 	wqe->recv.num_sgle = cpu_to_be32(wr->num_sge);
+ 	for (i = 0; i < wr->num_sge; i++) {
+ 		wqe->recv.sgl[i].stag = cpu_to_be32(wr->sg_list[i].lkey);
+ 		wqe->recv.sgl[i].len = cpu_to_be32(wr->sg_list[i].length);
+-
+-		/* to in the WQE == the offset into the page */
+-		wqe->recv.sgl[i].to = cpu_to_be64(((u32) wr->sg_list[i].addr) %
+-				(1UL << (12 + page_size[i])));
+-
+-		/* pbl_addr is the adapters address in the PBL */
+-		wqe->recv.pbl_addr[i] = cpu_to_be32(pbl_addr[i]);
++		wqe->recv.sgl[i].to = cpu_to_be64(wr->sg_list[i].addr);
+ 	}
+ 	for (; i < T3_MAX_SGE; i++) {
+ 		wqe->recv.sgl[i].stag = 0;
+ 		wqe->recv.sgl[i].len = 0;
+ 		wqe->recv.sgl[i].to = 0;
+-		wqe->recv.pbl_addr[i] = 0;
  	}
+ 	return 0;
+ }
+@@ -659,6 +642,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+ 	cxio_flush_rq(&qhp->wq, &rchp->cq, count);
+ 	spin_unlock(&qhp->lock);
+ 	spin_unlock_irqrestore(&rchp->lock, *flag);
++	(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
  
-+	if (idx == 0)
-+		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-+
- #if defined(CONFIG_SPARC64)
- 	d.init_hwif = init_hwif_common_ali15x3;
- #endif /* CONFIG_SPARC64 */
-@@ -810,7 +807,7 @@ static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_dev
+ 	/* locking heirarchy: cq lock first, then qp lock. */
+ 	spin_lock_irqsave(&schp->lock, *flag);
+@@ -668,6 +652,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+ 	cxio_flush_sq(&qhp->wq, &schp->cq, count);
+ 	spin_unlock(&qhp->lock);
+ 	spin_unlock_irqrestore(&schp->lock, *flag);
++	(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
  
- static const struct pci_device_id alim15x3_pci_tbl[] = {
- 	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5229), 0 },
--	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 0 },
-+	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), 1 },
- 	{ 0, },
- };
- MODULE_DEVICE_TABLE(pci, alim15x3_pci_tbl);
-diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
-index 8d4125e..2ef890c 100644
---- a/drivers/ide/pci/amd74xx.c
-+++ b/drivers/ide/pci/amd74xx.c
-@@ -1,6 +1,4 @@
+ 	/* deref */
+ 	if (atomic_dec_and_test(&qhp->refcnt))
+@@ -678,7 +663,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+ 
+ static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+ {
+-	if (t3b_device(qhp->rhp))
++	if (qhp->ibqp.uobject)
+ 		cxio_set_wq_in_error(&qhp->wq);
+ 	else
+ 		__flush_qp(qhp, flag);
+@@ -732,6 +717,7 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ 	init_attr.qp_dma_addr = qhp->wq.dma_addr;
+ 	init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
+ 	init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
++	init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
+ 	init_attr.irs = qhp->ep->rcv_seq;
+ 	PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
+ 	     "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
+@@ -847,10 +833,11 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
+ 				disconnect = 1;
+ 				ep = qhp->ep;
+ 			}
++			flush_qp(qhp, &flag);
+ 			break;
+ 		case IWCH_QP_STATE_TERMINATE:
+ 			qhp->attr.state = IWCH_QP_STATE_TERMINATE;
+-			if (t3b_device(qhp->rhp))
++			if (qhp->ibqp.uobject)
+ 				cxio_set_wq_in_error(&qhp->wq);
+ 			if (!internal)
+ 				terminate = 1;
+diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
+index f7782c8..194c1c3 100644
+--- a/drivers/infiniband/hw/ehca/ehca_av.c
++++ b/drivers/infiniband/hw/ehca/ehca_av.c
+@@ -1,7 +1,7 @@
  /*
-- * Version 2.24
-- *
-  * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
-  * IDE driver for Linux.
+  *  IBM eServer eHCA Infiniband device driver for Linux on POWER
   *
-@@ -19,90 +17,52 @@
+- *  adress vector functions
++ *  address vector functions
+  *
+  *  Authors: Hoang-Nam Nguyen <hnguyen at de.ibm.com>
+  *           Khadija Souissi <souissik at de.ibm.com>
+diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
+index 74d2b72..92cce8a 100644
+--- a/drivers/infiniband/hw/ehca/ehca_classes.h
++++ b/drivers/infiniband/hw/ehca/ehca_classes.h
+@@ -94,9 +94,14 @@ struct ehca_sma_attr {
  
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
--#include <asm/io.h>
+ struct ehca_sport {
+ 	struct ib_cq *ibcq_aqp1;
+-	struct ib_qp *ibqp_aqp1;
++	struct ib_qp *ibqp_sqp[2];
++	/* lock to serialze modify_qp() calls for sqp in normal
++	 * and irq path (when event PORT_ACTIVE is received first time)
++	 */
++	spinlock_t mod_sqp_lock;
+ 	enum ib_port_state port_state;
+ 	struct ehca_sma_attr saved_attr;
++	u32 pma_qp_nr;
+ };
  
- #include "ide-timing.h"
+ #define HCA_CAP_MR_PGSIZE_4K  0x80000000
+@@ -141,6 +146,14 @@ enum ehca_ext_qp_type {
+ 	EQPT_SRQ       = 3,
+ };
  
--#define AMD_IDE_CONFIG		(0x01 + amd_config->base)
--#define AMD_CABLE_DETECT	(0x02 + amd_config->base)
--#define AMD_DRIVE_TIMING	(0x08 + amd_config->base)
--#define AMD_8BIT_TIMING		(0x0e + amd_config->base)
--#define AMD_ADDRESS_SETUP	(0x0c + amd_config->base)
--#define AMD_UDMA_TIMING		(0x10 + amd_config->base)
--
--#define AMD_CHECK_SWDMA		0x08
--#define AMD_BAD_SWDMA		0x10
--#define AMD_BAD_FIFO		0x20
--#define AMD_CHECK_SERENADE	0x40
--
--/*
-- * AMD SouthBridge chips.
-- */
--
--static struct amd_ide_chip {
--	unsigned short id;
--	u8 base;
--	u8 udma_mask;
--	u8 flags;
--} amd_ide_chips[] = {
--	{ PCI_DEVICE_ID_AMD_COBRA_7401,		 0x40, ATA_UDMA2, AMD_BAD_SWDMA },
--	{ PCI_DEVICE_ID_AMD_VIPER_7409,		 0x40, ATA_UDMA4, AMD_CHECK_SWDMA },
--	{ PCI_DEVICE_ID_AMD_VIPER_7411,		 0x40, ATA_UDMA5, AMD_BAD_FIFO },
--	{ PCI_DEVICE_ID_AMD_OPUS_7441,		 0x40, ATA_UDMA5, },
--	{ PCI_DEVICE_ID_AMD_8111_IDE,		 0x40, ATA_UDMA6, AMD_CHECK_SERENADE },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_IDE,	 0x50, ATA_UDMA5, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2,	 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, ATA_UDMA6, },
--	{ PCI_DEVICE_ID_AMD_CS5536_IDE,		 0x40, ATA_UDMA5, },
--	{ 0 }
-+enum {
-+	AMD_IDE_CONFIG		= 0x41,
-+	AMD_CABLE_DETECT	= 0x42,
-+	AMD_DRIVE_TIMING	= 0x48,
-+	AMD_8BIT_TIMING		= 0x4e,
-+	AMD_ADDRESS_SETUP	= 0x4c,
-+	AMD_UDMA_TIMING		= 0x50,
++/* struct to cache modify_qp()'s parms for GSI/SMI qp */
++struct ehca_mod_qp_parm {
++	int mask;
++	struct ib_qp_attr attr;
++};
++
++#define EHCA_MOD_QP_PARM_MAX 4
++
+ struct ehca_qp {
+ 	union {
+ 		struct ib_qp ib_qp;
+@@ -164,10 +177,18 @@ struct ehca_qp {
+ 	struct ehca_cq *recv_cq;
+ 	unsigned int sqerr_purgeflag;
+ 	struct hlist_node list_entries;
++	/* array to cache modify_qp()'s parms for GSI/SMI qp */
++	struct ehca_mod_qp_parm *mod_qp_parm;
++	int mod_qp_parm_idx;
+ 	/* mmap counter for resources mapped into user space */
+ 	u32 mm_count_squeue;
+ 	u32 mm_count_rqueue;
+ 	u32 mm_count_galpa;
++	/* unsolicited ack circumvention */
++	int unsol_ack_circ;
++	int mtu_shift;
++	u32 message_count;
++	u32 packet_count;
  };
  
--static struct amd_ide_chip *amd_config;
--static const struct ide_port_info *amd_chipset;
- static unsigned int amd_80w;
- static unsigned int amd_clock;
+ #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
+@@ -323,6 +344,7 @@ extern int ehca_port_act_time;
+ extern int ehca_use_hp_mr;
+ extern int ehca_scaling_code;
+ extern int ehca_lock_hcalls;
++extern int ehca_nr_ports;
  
- static char *amd_dma[] = { "16", "25", "33", "44", "66", "100", "133" };
- static unsigned char amd_cyc2udma[] = { 6, 6, 5, 4, 0, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 7 };
+ struct ipzu_queue_resp {
+ 	u32 qe_size;      /* queue entry size */
+diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
+index 79c25f5..0467c15 100644
+--- a/drivers/infiniband/hw/ehca/ehca_cq.c
++++ b/drivers/infiniband/hw/ehca/ehca_cq.c
+@@ -246,7 +246,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
+ 		} else {
+ 			if (h_ret != H_PAGE_REGISTERED) {
+ 				ehca_err(device, "Registration of page failed "
+-					 "ehca_cq=%p cq_num=%x h_ret=%li"
++					 "ehca_cq=%p cq_num=%x h_ret=%li "
+ 					 "counter=%i act_pages=%i",
+ 					 my_cq, my_cq->cq_number,
+ 					 h_ret, counter, param.act_pages);
+diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
+index 3f617b2..b5ca94c 100644
+--- a/drivers/infiniband/hw/ehca/ehca_irq.c
++++ b/drivers/infiniband/hw/ehca/ehca_irq.c
+@@ -62,6 +62,7 @@
+ #define NEQE_PORT_NUMBER       EHCA_BMASK_IBM( 8, 15)
+ #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16)
+ #define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16, 16)
++#define NEQE_SPECIFIC_EVENT    EHCA_BMASK_IBM(16, 23)
  
-+static inline u8 amd_offset(struct pci_dev *dev)
-+{
-+	return (dev->vendor == PCI_VENDOR_ID_NVIDIA) ? 0x10 : 0;
-+}
+ #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52, 63)
+ #define ERROR_DATA_TYPE        EHCA_BMASK_IBM( 0,  7)
+@@ -354,17 +355,34 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
+ {
+ 	u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
+ 	u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
++	u8 spec_event;
++	struct ehca_sport *sport = &shca->sport[port - 1];
++	unsigned long flags;
+ 
+ 	switch (ec) {
+ 	case 0x30: /* port availability change */
+ 		if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
+-			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
++			int suppress_event;
++			/* replay modify_qp for sqps */
++			spin_lock_irqsave(&sport->mod_sqp_lock, flags);
++			suppress_event = !sport->ibqp_sqp[IB_QPT_GSI];
++			if (sport->ibqp_sqp[IB_QPT_SMI])
++				ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
++			if (!suppress_event)
++				ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
++			spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
 +
- /*
-  * amd_set_speed() writes timing values to the chipset registers
-  */
++			/* AQP1 was destroyed, ignore this event */
++			if (suppress_event)
++				break;
++
++			sport->port_state = IB_PORT_ACTIVE;
+ 			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+ 					    "is active");
+ 			ehca_query_sma_attr(shca, port,
+-					    &shca->sport[port - 1].saved_attr);
++					    &sport->saved_attr);
+ 		} else {
+-			shca->sport[port - 1].port_state = IB_PORT_DOWN;
++			sport->port_state = IB_PORT_DOWN;
+ 			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+ 					    "is inactive");
+ 		}
+@@ -378,13 +396,15 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
+ 			ehca_warn(&shca->ib_device, "disruptive port "
+ 				  "%d configuration change", port);
  
--static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
-+static void amd_set_speed(struct pci_dev *dev, u8 dn, u8 udma_mask,
-+			  struct ide_timing *timing)
- {
--	unsigned char t;
-+	u8 t = 0, offset = amd_offset(dev);
+-			shca->sport[port - 1].port_state = IB_PORT_DOWN;
++			sport->port_state = IB_PORT_DOWN;
+ 			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
+ 					    "is inactive");
  
--	pci_read_config_byte(dev, AMD_ADDRESS_SETUP, &t);
-+	pci_read_config_byte(dev, AMD_ADDRESS_SETUP + offset, &t);
- 	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
--	pci_write_config_byte(dev, AMD_ADDRESS_SETUP, t);
-+	pci_write_config_byte(dev, AMD_ADDRESS_SETUP + offset, t);
+-			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
++			sport->port_state = IB_PORT_ACTIVE;
+ 			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
+ 					    "is active");
++			ehca_query_sma_attr(shca, port,
++					    &sport->saved_attr);
+ 		} else
+ 			notify_port_conf_change(shca, port);
+ 		break;
+@@ -394,6 +414,16 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
+ 	case 0x33:  /* trace stopped */
+ 		ehca_err(&shca->ib_device, "Traced stopped.");
+ 		break;
++	case 0x34: /* util async event */
++		spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe);
++		if (spec_event == 0x80) /* client reregister required */
++			dispatch_port_event(shca, port,
++					    IB_EVENT_CLIENT_REREGISTER,
++					    "client reregister req.");
++		else
++			ehca_warn(&shca->ib_device, "Unknown util async "
++				  "event %x on port %x", spec_event, port);
++		break;
+ 	default:
+ 		ehca_err(&shca->ib_device, "Unknown event code: %x on %s.",
+ 			 ec, shca->ib_device.name);
+diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
+index 5485799..a8a2ea5 100644
+--- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
++++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
+@@ -187,6 +187,11 @@ int ehca_dealloc_ucontext(struct ib_ucontext *context);
  
--	pci_write_config_byte(dev, AMD_8BIT_TIMING + (1 - (dn >> 1)),
-+	pci_write_config_byte(dev, AMD_8BIT_TIMING + offset + (1 - (dn >> 1)),
- 		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
+ int ehca_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
  
--	pci_write_config_byte(dev, AMD_DRIVE_TIMING + (3 - dn),
-+	pci_write_config_byte(dev, AMD_DRIVE_TIMING + offset + (3 - dn),
- 		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
++int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
++		     struct ib_wc *in_wc, struct ib_grh *in_grh,
++		     struct ib_mad *in_mad,
++		     struct ib_mad *out_mad);
++
+ void ehca_poll_eqs(unsigned long data);
  
--	switch (amd_config->udma_mask) {
-+	switch (udma_mask) {
- 	case ATA_UDMA2: t = timing->udma ? (0xc0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
- 	case ATA_UDMA4: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 2, 10)]) : 0x03; break;
- 	case ATA_UDMA5: t = timing->udma ? (0xc0 | amd_cyc2udma[FIT(timing->udma, 1, 10)]) : 0x03; break;
-@@ -110,7 +70,7 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
- 	default: return;
+ int ehca_calc_ipd(struct ehca_shca *shca, int port,
+@@ -200,4 +205,6 @@ void ehca_free_fw_ctrlblock(void *ptr);
+ #define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
+ #endif
+ 
++void ehca_recover_sqp(struct ib_qp *sqp);
++
+ #endif
+diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
+index 6a56d86..a86ebcc 100644
+--- a/drivers/infiniband/hw/ehca/ehca_main.c
++++ b/drivers/infiniband/hw/ehca/ehca_main.c
+@@ -90,7 +90,8 @@ MODULE_PARM_DESC(hw_level,
+ 		 "hardware level"
+ 		 " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
+ MODULE_PARM_DESC(nr_ports,
+-		 "number of connected ports (default: 2)");
++		 "number of connected ports (-1: autodetect, 1: port one only, "
++		 "2: two ports (default)");
+ MODULE_PARM_DESC(use_hp_mr,
+ 		 "high performance MRs (0: no (default), 1: yes)");
+ MODULE_PARM_DESC(port_act_time,
+@@ -471,7 +472,7 @@ int ehca_init_device(struct ehca_shca *shca)
+ 	shca->ib_device.dealloc_fmr	    = ehca_dealloc_fmr;
+ 	shca->ib_device.attach_mcast	    = ehca_attach_mcast;
+ 	shca->ib_device.detach_mcast	    = ehca_detach_mcast;
+-	/* shca->ib_device.process_mad	    = ehca_process_mad;	    */
++	shca->ib_device.process_mad	    = ehca_process_mad;
+ 	shca->ib_device.mmap		    = ehca_mmap;
+ 
+ 	if (EHCA_BMASK_GET(HCA_CAP_SRQ, shca->hca_cap)) {
+@@ -511,7 +512,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
  	}
+ 	sport->ibcq_aqp1 = ibcq;
  
--	pci_write_config_byte(dev, AMD_UDMA_TIMING + (3 - dn), t);
-+	pci_write_config_byte(dev, AMD_UDMA_TIMING + offset + (3 - dn), t);
- }
+-	if (sport->ibqp_aqp1) {
++	if (sport->ibqp_sqp[IB_QPT_GSI]) {
+ 		ehca_err(&shca->ib_device, "AQP1 QP is already created.");
+ 		ret = -EPERM;
+ 		goto create_aqp1;
+@@ -537,7 +538,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
+ 		ret = PTR_ERR(ibqp);
+ 		goto create_aqp1;
+ 	}
+-	sport->ibqp_aqp1 = ibqp;
++	sport->ibqp_sqp[IB_QPT_GSI] = ibqp;
  
- /*
-@@ -120,12 +80,15 @@ static void amd_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timi
+ 	return 0;
  
- static void amd_set_drive(ide_drive_t *drive, const u8 speed)
+@@ -550,7 +551,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
  {
--	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
- 	struct ide_timing t, p;
- 	int T, UT;
-+	u8 udma_mask = hwif->ultra_mask;
+ 	int ret;
  
- 	T = 1000000000 / amd_clock;
--	UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
-+	UT = (udma_mask == ATA_UDMA2) ? T : (T / 2);
+-	ret = ib_destroy_qp(sport->ibqp_aqp1);
++	ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]);
+ 	if (ret) {
+ 		ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret);
+ 		return ret;
+@@ -590,6 +591,11 @@ static struct attribute_group ehca_drv_attr_grp = {
+ 	.attrs = ehca_drv_attrs
+ };
  
- 	ide_timing_compute(drive, speed, &t, T, UT);
++static struct attribute_group *ehca_drv_attr_groups[] = {
++	&ehca_drv_attr_grp,
++	NULL,
++};
++
+ #define EHCA_RESOURCE_ATTR(name)                                           \
+ static ssize_t  ehca_show_##name(struct device *dev,                       \
+ 				 struct device_attribute *attr,            \
+@@ -688,7 +694,7 @@ static int __devinit ehca_probe(struct of_device *dev,
+ 	struct ehca_shca *shca;
+ 	const u64 *handle;
+ 	struct ib_pd *ibpd;
+-	int ret;
++	int ret, i;
  
-@@ -137,7 +100,7 @@ static void amd_set_drive(ide_drive_t *drive, const u8 speed)
- 	if (speed == XFER_UDMA_5 && amd_clock <= 33333) t.udma = 1;
- 	if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
+ 	handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
+ 	if (!handle) {
+@@ -709,6 +715,8 @@ static int __devinit ehca_probe(struct of_device *dev,
+ 		return -ENOMEM;
+ 	}
+ 	mutex_init(&shca->modify_mutex);
++	for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
++		spin_lock_init(&shca->sport[i].mod_sqp_lock);
  
--	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
-+	amd_set_speed(dev, drive->dn, udma_mask, &t);
- }
+ 	shca->ofdev = dev;
+ 	shca->ipz_hca_handle.handle = *handle;
+@@ -899,6 +907,9 @@ static struct of_platform_driver ehca_driver = {
+ 	.match_table = ehca_device_table,
+ 	.probe       = ehca_probe,
+ 	.remove      = ehca_remove,
++	.driver	     = {
++		.groups = ehca_drv_attr_groups,
++	},
+ };
  
- /*
-@@ -149,67 +112,68 @@ static void amd_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	amd_set_drive(drive, XFER_PIO_0 + pio);
+ void ehca_poll_eqs(unsigned long data)
+@@ -926,7 +937,7 @@ void ehca_poll_eqs(unsigned long data)
+ 				ehca_process_eq(shca, 0);
+ 		}
+ 	}
+-	mod_timer(&poll_eqs_timer, jiffies + HZ);
++	mod_timer(&poll_eqs_timer, round_jiffies(jiffies + HZ));
+ 	spin_unlock(&shca_list_lock);
  }
  
--/*
-- * The initialization callback. Here we determine the IDE chip type
-- * and initialize its drive independent registers.
-- */
-+static void __devinit amd7409_cable_detect(struct pci_dev *dev,
-+					   const char *name)
-+{
-+	/* no host side cable detection */
-+	amd_80w = 0x03;
-+}
+@@ -957,10 +968,6 @@ int __init ehca_module_init(void)
+ 		goto module_init2;
+ 	}
  
--static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const char *name)
-+static void __devinit amd7411_cable_detect(struct pci_dev *dev,
-+					   const char *name)
- {
--	unsigned char t;
--	unsigned int u;
- 	int i;
-+	u32 u = 0;
-+	u8 t = 0, offset = amd_offset(dev);
-+
-+	pci_read_config_byte(dev, AMD_CABLE_DETECT + offset, &t);
-+	pci_read_config_dword(dev, AMD_UDMA_TIMING + offset, &u);
-+	amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
-+	for (i = 24; i >= 0; i -= 8)
-+		if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
-+			printk(KERN_WARNING "%s: BIOS didn't set cable bits "
-+					    "correctly. Enabling workaround.\n",
-+					    name);
-+			amd_80w |= (1 << (1 - (i >> 4)));
-+		}
-+}
+-	ret = sysfs_create_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp);
+-	if (ret) /* only complain; we can live without attributes */
+-		ehca_gen_err("Cannot create driver attributes  ret=%d", ret);
+-
+ 	if (ehca_poll_all_eqs != 1) {
+ 		ehca_gen_err("WARNING!!!");
+ 		ehca_gen_err("It is possible to lose interrupts.");
+@@ -986,7 +993,6 @@ void __exit ehca_module_exit(void)
+ 	if (ehca_poll_all_eqs == 1)
+ 		del_timer_sync(&poll_eqs_timer);
  
- /*
-- * Check for bad SWDMA.
-+ * The initialization callback.  Initialize drive independent registers.
-  */
+-	sysfs_remove_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp);
+ 	ibmebus_unregister_driver(&ehca_driver);
  
--	if (amd_config->flags & AMD_CHECK_SWDMA) {
--		if (dev->revision <= 7)
--			amd_config->flags |= AMD_BAD_SWDMA;
--	}
-+static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev,
-+						   const char *name)
-+{
-+	u8 t = 0, offset = amd_offset(dev);
+ 	ehca_destroy_slab_caches();
+diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
+index eff5fb5..1012f15 100644
+--- a/drivers/infiniband/hw/ehca/ehca_qp.c
++++ b/drivers/infiniband/hw/ehca/ehca_qp.c
+@@ -592,10 +592,8 @@ static struct ehca_qp *internal_create_qp(
+ 		goto create_qp_exit1;
+ 	}
  
- /*
-  * Check 80-wire cable presence.
-  */
+-	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
+-		parms.sigtype = HCALL_SIGT_EVERY;
+-	else
+-		parms.sigtype = HCALL_SIGT_BY_WQE;
++	/* Always signal by WQE so we can hide circ. WQEs */
++	parms.sigtype = HCALL_SIGT_BY_WQE;
  
--	switch (amd_config->udma_mask) {
--
--		case ATA_UDMA6:
--		case ATA_UDMA5:
--			pci_read_config_byte(dev, AMD_CABLE_DETECT, &t);
--			pci_read_config_dword(dev, AMD_UDMA_TIMING, &u);
--			amd_80w = ((t & 0x3) ? 1 : 0) | ((t & 0xc) ? 2 : 0);
--			for (i = 24; i >= 0; i -= 8)
--				if (((u >> i) & 4) && !(amd_80w & (1 << (1 - (i >> 4))))) {
--					printk(KERN_WARNING "%s: BIOS didn't set cable bits correctly. Enabling workaround.\n",
--						amd_chipset->name);
--					amd_80w |= (1 << (1 - (i >> 4)));
--				}
--			break;
--
--		case ATA_UDMA4:
--			/* no host side cable detection */
--			amd_80w = 0x03;
--			break;
--	}
-+	if (dev->vendor == PCI_VENDOR_ID_AMD &&
-+	    dev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
-+		; /* no UDMA > 2 */
-+	else if (dev->vendor == PCI_VENDOR_ID_AMD &&
-+		 dev->device == PCI_DEVICE_ID_AMD_VIPER_7409)
-+		amd7409_cable_detect(dev, name);
-+	else
-+		amd7411_cable_detect(dev, name);
+ 	/* UD_AV CIRCUMVENTION */
+ 	max_send_sge = init_attr->cap.max_send_sge;
+@@ -618,6 +616,10 @@ static struct ehca_qp *internal_create_qp(
+ 	parms.squeue.max_sge = max_send_sge;
+ 	parms.rqueue.max_sge = max_recv_sge;
  
- /*
-  * Take care of prefetch & postwrite.
-  */
++	/* RC QPs need one more SWQE for unsolicited ack circumvention */
++	if (qp_type == IB_QPT_RC)
++		parms.squeue.max_wr++;
++
+ 	if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
+ 		if (HAS_SQ(my_qp))
+ 			ehca_determine_small_queue(
+@@ -650,6 +652,8 @@ static struct ehca_qp *internal_create_qp(
+ 			parms.squeue.act_nr_sges = 1;
+ 			parms.rqueue.act_nr_sges = 1;
+ 		}
++		/* hide the extra WQE */
++		parms.squeue.act_nr_wqes--;
+ 		break;
+ 	case IB_QPT_UD:
+ 	case IB_QPT_GSI:
+@@ -729,12 +733,31 @@ static struct ehca_qp *internal_create_qp(
+ 	init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes;
+ 	my_qp->init_attr = *init_attr;
  
--	pci_read_config_byte(dev, AMD_IDE_CONFIG, &t);
--	pci_write_config_byte(dev, AMD_IDE_CONFIG,
--		(amd_config->flags & AMD_BAD_FIFO) ? (t & 0x0f) : (t | 0xf0));
--
--/*
-- * Take care of incorrectly wired Serenade mainboards.
-- */
--
--	if ((amd_config->flags & AMD_CHECK_SERENADE) &&
--		dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
--		dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
--			amd_config->udma_mask = ATA_UDMA5;
-+	pci_read_config_byte(dev, AMD_IDE_CONFIG + offset, &t);
-+	/*
-+	 * Check for broken FIFO support.
-+	 */
-+	if (dev->vendor == PCI_VENDOR_ID_AMD &&
-+	    dev->vendor == PCI_DEVICE_ID_AMD_VIPER_7411)
-+		t &= 0x0f;
-+	else
-+		t |= 0xf0;
-+	pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t);
++	if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
++		shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
++			&my_qp->ib_qp;
++		if (ehca_nr_ports < 0) {
++			/* alloc array to cache subsequent modify qp parms
++			 * for autodetect mode
++			 */
++			my_qp->mod_qp_parm =
++				kzalloc(EHCA_MOD_QP_PARM_MAX *
++					sizeof(*my_qp->mod_qp_parm),
++					GFP_KERNEL);
++			if (!my_qp->mod_qp_parm) {
++				ehca_err(pd->device,
++					 "Could not alloc mod_qp_parm");
++				goto create_qp_exit4;
++			}
++		}
++	}
++
+ 	/* NOTE: define_apq0() not supported yet */
+ 	if (qp_type == IB_QPT_GSI) {
+ 		h_ret = ehca_define_sqp(shca, my_qp, init_attr);
+ 		if (h_ret != H_SUCCESS) {
+ 			ret = ehca2ib_return_code(h_ret);
+-			goto create_qp_exit4;
++			goto create_qp_exit5;
+ 		}
+ 	}
  
- /*
-  * Determine the system bus clock.
-@@ -225,53 +189,44 @@ static unsigned int __devinit init_chipset_amd74xx(struct pci_dev *dev, const ch
+@@ -743,7 +766,7 @@ static struct ehca_qp *internal_create_qp(
+ 		if (ret) {
+ 			ehca_err(pd->device,
+ 				 "Couldn't assign qp to send_cq ret=%i", ret);
+-			goto create_qp_exit4;
++			goto create_qp_exit5;
+ 		}
+ 	}
  
- 	if (amd_clock < 20000 || amd_clock > 50000) {
- 		printk(KERN_WARNING "%s: User given PCI clock speed impossible (%d), using 33 MHz instead.\n",
--			amd_chipset->name, amd_clock);
-+				    name, amd_clock);
- 		amd_clock = 33333;
+@@ -769,12 +792,18 @@ static struct ehca_qp *internal_create_qp(
+ 		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
+ 			ehca_err(pd->device, "Copy to udata failed");
+ 			ret = -EINVAL;
+-			goto create_qp_exit4;
++			goto create_qp_exit6;
+ 		}
  	}
  
--/*
-- * Print the boot message.
-- */
--
--	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
--		amd_chipset->name, pci_name(dev), dev->revision,
--		amd_dma[fls(amd_config->udma_mask) - 1]);
--
- 	return dev->irq;
- }
+ 	return my_qp;
  
-+static u8 __devinit amd_cable_detect(ide_hwif_t *hwif)
-+{
-+	if ((amd_80w >> hwif->channel) & 1)
-+		return ATA_CBL_PATA80;
-+	else
-+		return ATA_CBL_PATA40;
-+}
++create_qp_exit6:
++	ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
 +
- static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++create_qp_exit5:
++	kfree(my_qp->mod_qp_parm);
 +
- 	if (hwif->irq == 0) /* 0 is bogus but will do for now */
--		hwif->irq = pci_get_legacy_ide_irq(hwif->pci_dev, hwif->channel);
-+		hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel);
+ create_qp_exit4:
+ 	if (HAS_RQ(my_qp))
+ 		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
+@@ -858,7 +887,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+ 				update_mask,
+ 				mqpcb, my_qp->galpas.kernel);
+ 	if (hret != H_SUCCESS) {
+-		ehca_err(pd->device, "Could not modify SRQ to INIT"
++		ehca_err(pd->device, "Could not modify SRQ to INIT "
+ 			 "ehca_qp=%p qp_num=%x h_ret=%li",
+ 			 my_qp, my_qp->real_qp_num, hret);
+ 		goto create_srq2;
+@@ -872,7 +901,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+ 				update_mask,
+ 				mqpcb, my_qp->galpas.kernel);
+ 	if (hret != H_SUCCESS) {
+-		ehca_err(pd->device, "Could not enable SRQ"
++		ehca_err(pd->device, "Could not enable SRQ "
+ 			 "ehca_qp=%p qp_num=%x h_ret=%li",
+ 			 my_qp, my_qp->real_qp_num, hret);
+ 		goto create_srq2;
+@@ -886,7 +915,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
+ 				update_mask,
+ 				mqpcb, my_qp->galpas.kernel);
+ 	if (hret != H_SUCCESS) {
+-		ehca_err(pd->device, "Could not modify SRQ to RTR"
++		ehca_err(pd->device, "Could not modify SRQ to RTR "
+ 			 "ehca_qp=%p qp_num=%x h_ret=%li",
+ 			 my_qp, my_qp->real_qp_num, hret);
+ 		goto create_srq2;
+@@ -992,7 +1021,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ 	unsigned long flags = 0;
  
- 	hwif->set_pio_mode = &amd_set_pio_mode;
- 	hwif->set_dma_mode = &amd_set_drive;
+ 	/* do query_qp to obtain current attr values */
+-	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
++	mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
+ 	if (!mqpcb) {
+ 		ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
+ 			 "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
+@@ -1180,6 +1209,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ 		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);
+ 	}
+ 	if (attr_mask & IB_QP_PORT) {
++		struct ehca_sport *sport;
++		struct ehca_qp *aqp1;
+ 		if (attr->port_num < 1 || attr->port_num > shca->num_ports) {
+ 			ret = -EINVAL;
+ 			ehca_err(ibqp->device, "Invalid port=%x. "
+@@ -1188,6 +1219,29 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ 				 shca->num_ports);
+ 			goto modify_qp_exit2;
+ 		}
++		sport = &shca->sport[attr->port_num - 1];
++		if (!sport->ibqp_sqp[IB_QPT_GSI]) {
++			/* should not occur */
++			ret = -EFAULT;
++			ehca_err(ibqp->device, "AQP1 was not created for "
++				 "port=%x", attr->port_num);
++			goto modify_qp_exit2;
++		}
++		aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI],
++				    struct ehca_qp, ib_qp);
++		if (ibqp->qp_type != IB_QPT_GSI &&
++		    ibqp->qp_type != IB_QPT_SMI &&
++		    aqp1->mod_qp_parm) {
++			/*
++			 * firmware will reject this modify_qp() because
++			 * port is not activated/initialized fully
++			 */
++			ret = -EFAULT;
++			ehca_warn(ibqp->device, "Couldn't modify qp port=%x: "
++				  "either port is being activated (try again) "
++				  "or cabling issue", attr->port_num);
++			goto modify_qp_exit2;
++		}
+ 		mqpcb->prim_phys_port = attr->port_num;
+ 		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1);
+ 	}
+@@ -1244,6 +1298,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
+ 	}
  
--	if (!hwif->dma_base)
--		return;
--
--	hwif->ultra_mask = amd_config->udma_mask;
--	if (amd_config->flags & AMD_BAD_SWDMA)
--		hwif->swdma_mask = 0x00;
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
--		if ((amd_80w >> hwif->channel) & 1)
--			hwif->cbl = ATA_CBL_PATA80;
--		else
--			hwif->cbl = ATA_CBL_PATA40;
--	}
-+	hwif->cable_detect = amd_cable_detect;
+ 	if (attr_mask & IB_QP_PATH_MTU) {
++		/* store ld(MTU) */
++		my_qp->mtu_shift = attr->path_mtu + 7;
+ 		mqpcb->path_mtu = attr->path_mtu;
+ 		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);
+ 	}
+@@ -1467,6 +1523,8 @@ modify_qp_exit1:
+ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ 		   struct ib_udata *udata)
+ {
++	struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
++					      ib_device);
+ 	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
+ 	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+ 					     ib_pd);
+@@ -1479,9 +1537,100 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
+ 		return -EINVAL;
+ 	}
+ 
++	/* The if-block below caches qp_attr to be modified for GSI and SMI
++	 * qps during the initialization by ib_mad. When the respective port
++	 * is activated, ie we got an event PORT_ACTIVE, we'll replay the
++	 * cached modify calls sequence, see ehca_recover_sqs() below.
++	 * Why that is required:
++	 * 1) If one port is connected, older code requires that port one
++	 *    to be connected and module option nr_ports=1 to be given by
++	 *    user, which is very inconvenient for end user.
++	 * 2) Firmware accepts modify_qp() only if respective port has become
++	 *    active. Older code had a wait loop of 30sec create_qp()/
++	 *    define_aqp1(), which is not appropriate in practice. This
++	 *    code now removes that wait loop, see define_aqp1(), and always
++	 *    reports all ports to ib_mad resp. users. Only activated ports
++	 *    will then usable for the users.
++	 */
++	if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) {
++		int port = my_qp->init_attr.port_num;
++		struct ehca_sport *sport = &shca->sport[port - 1];
++		unsigned long flags;
++		spin_lock_irqsave(&sport->mod_sqp_lock, flags);
++		/* cache qp_attr only during init */
++		if (my_qp->mod_qp_parm) {
++			struct ehca_mod_qp_parm *p;
++			if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) {
++				ehca_err(&shca->ib_device,
++					 "mod_qp_parm overflow state=%x port=%x"
++					 " type=%x", attr->qp_state,
++					 my_qp->init_attr.port_num,
++					 ibqp->qp_type);
++				spin_unlock_irqrestore(&sport->mod_sqp_lock,
++						       flags);
++				return -EINVAL;
++			}
++			p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx];
++			p->mask = attr_mask;
++			p->attr = *attr;
++			my_qp->mod_qp_parm_idx++;
++			ehca_dbg(&shca->ib_device,
++				 "Saved qp_attr for state=%x port=%x type=%x",
++				 attr->qp_state, my_qp->init_attr.port_num,
++				 ibqp->qp_type);
++			spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
++			return 0;
++		}
++		spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
++	}
++
+ 	return internal_modify_qp(ibqp, attr, attr_mask, 0);
  }
  
- #define IDE_HFLAGS_AMD \
- 	(IDE_HFLAG_PIO_NO_BLACKLIST | \
- 	 IDE_HFLAG_PIO_NO_DOWNGRADE | \
-+	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
- 	 IDE_HFLAG_POST_SET_MODE | \
- 	 IDE_HFLAG_IO_32BIT | \
- 	 IDE_HFLAG_UNMASK_IRQS | \
- 	 IDE_HFLAG_BOOTABLE)
++void ehca_recover_sqp(struct ib_qp *sqp)
++{
++	struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp);
++	int port = my_sqp->init_attr.port_num;
++	struct ib_qp_attr attr;
++	struct ehca_mod_qp_parm *qp_parm;
++	int i, qp_parm_idx, ret;
++	unsigned long flags, wr_cnt;
++
++	if (!my_sqp->mod_qp_parm)
++		return;
++	ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num);
++
++	qp_parm = my_sqp->mod_qp_parm;
++	qp_parm_idx = my_sqp->mod_qp_parm_idx;
++	for (i = 0; i < qp_parm_idx; i++) {
++		attr = qp_parm[i].attr;
++		ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0);
++		if (ret) {
++			ehca_err(sqp->device, "Could not modify SQP port=%x "
++				 "qp_num=%x ret=%x", port, sqp->qp_num, ret);
++			goto free_qp_parm;
++		}
++		ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x",
++			 port, sqp->qp_num, attr.qp_state);
++	}
++
++	/* re-trigger posted recv wrs */
++	wr_cnt =  my_sqp->ipz_rqueue.current_q_offset /
++		my_sqp->ipz_rqueue.qe_size;
++	if (wr_cnt) {
++		spin_lock_irqsave(&my_sqp->spinlock_r, flags);
++		hipz_update_rqa(my_sqp, wr_cnt);
++		spin_unlock_irqrestore(&my_sqp->spinlock_r, flags);
++		ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx",
++			 port, sqp->qp_num, wr_cnt);
++	}
++
++free_qp_parm:
++	kfree(qp_parm);
++	/* this prevents subsequent calls to modify_qp() to cache qp_attr */
++	my_sqp->mod_qp_parm = NULL;
++}
++
+ int ehca_query_qp(struct ib_qp *qp,
+ 		  struct ib_qp_attr *qp_attr,
+ 		  int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
+@@ -1769,6 +1918,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ 	struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
+ 	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
+ 					     ib_pd);
++	struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
+ 	u32 cur_pid = current->tgid;
+ 	u32 qp_num = my_qp->real_qp_num;
+ 	int ret;
+@@ -1815,6 +1965,14 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
+ 	port_num = my_qp->init_attr.port_num;
+ 	qp_type  = my_qp->init_attr.qp_type;
  
--#define DECLARE_AMD_DEV(name_str)					\
-+#define DECLARE_AMD_DEV(name_str, swdma, udma)				\
- 	{								\
- 		.name		= name_str,				\
- 		.init_chipset	= init_chipset_amd74xx,			\
-@@ -279,11 +234,12 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
- 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},	\
- 		.host_flags	= IDE_HFLAGS_AMD,			\
- 		.pio_mask	= ATA_PIO5,				\
--		.swdma_mask	= ATA_SWDMA2,				\
-+		.swdma_mask	= swdma,				\
- 		.mwdma_mask	= ATA_MWDMA2,				\
-+		.udma_mask	= udma,					\
- 	}
++	if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
++		spin_lock_irqsave(&sport->mod_sqp_lock, flags);
++		kfree(my_qp->mod_qp_parm);
++		my_qp->mod_qp_parm = NULL;
++		shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL;
++		spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
++	}
++
+ 	/* no support for IB_QPT_SMI yet */
+ 	if (qp_type == IB_QPT_GSI) {
+ 		struct ib_event event;
+diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
+index ea91360..2ce8cff 100644
+--- a/drivers/infiniband/hw/ehca/ehca_reqs.c
++++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
+@@ -50,6 +50,9 @@
+ #include "hcp_if.h"
+ #include "hipz_fns.h"
  
--#define DECLARE_NV_DEV(name_str)					\
-+#define DECLARE_NV_DEV(name_str, udma)					\
- 	{								\
- 		.name		= name_str,				\
- 		.init_chipset	= init_chipset_amd74xx,			\
-@@ -293,45 +249,62 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif)
- 		.pio_mask	= ATA_PIO5,				\
- 		.swdma_mask	= ATA_SWDMA2,				\
- 		.mwdma_mask	= ATA_MWDMA2,				\
-+		.udma_mask	= udma,					\
++/* in RC traffic, insert an empty RDMA READ every this many packets */
++#define ACK_CIRC_THRESHOLD 2000000
++
+ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
+ 				  struct ehca_wqe *wqe_p,
+ 				  struct ib_recv_wr *recv_wr)
+@@ -81,7 +84,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
+ 	if (ehca_debug_level) {
+ 		ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
+ 			     ipz_rqueue);
+-		ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
++		ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
  	}
  
- static const struct ide_port_info amd74xx_chipsets[] __devinitdata = {
--	/*  0 */ DECLARE_AMD_DEV("AMD7401"),
--	/*  1 */ DECLARE_AMD_DEV("AMD7409"),
--	/*  2 */ DECLARE_AMD_DEV("AMD7411"),
--	/*  3 */ DECLARE_AMD_DEV("AMD7441"),
--	/*  4 */ DECLARE_AMD_DEV("AMD8111"),
--
--	/*  5 */ DECLARE_NV_DEV("NFORCE"),
--	/*  6 */ DECLARE_NV_DEV("NFORCE2"),
--	/*  7 */ DECLARE_NV_DEV("NFORCE2-U400R"),
--	/*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA"),
--	/*  9 */ DECLARE_NV_DEV("NFORCE3-150"),
--	/* 10 */ DECLARE_NV_DEV("NFORCE3-250"),
--	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA"),
--	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
--	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
--	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
--	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
--	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
--	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
--	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
--	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
--	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
--	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
--	/* 22 */ DECLARE_AMD_DEV("AMD5536"),
-+	/*  0 */ DECLARE_AMD_DEV("AMD7401",	  0x00, ATA_UDMA2),
-+	/*  1 */ DECLARE_AMD_DEV("AMD7409", ATA_SWDMA2, ATA_UDMA4),
-+	/*  2 */ DECLARE_AMD_DEV("AMD7411", ATA_SWDMA2, ATA_UDMA5),
-+	/*  3 */ DECLARE_AMD_DEV("AMD7441", ATA_SWDMA2, ATA_UDMA5),
-+	/*  4 */ DECLARE_AMD_DEV("AMD8111", ATA_SWDMA2, ATA_UDMA6),
-+
-+	/*  5 */ DECLARE_NV_DEV("NFORCE",		ATA_UDMA5),
-+	/*  6 */ DECLARE_NV_DEV("NFORCE2",		ATA_UDMA6),
-+	/*  7 */ DECLARE_NV_DEV("NFORCE2-U400R",	ATA_UDMA6),
-+	/*  8 */ DECLARE_NV_DEV("NFORCE2-U400R-SATA",	ATA_UDMA6),
-+	/*  9 */ DECLARE_NV_DEV("NFORCE3-150",		ATA_UDMA6),
-+	/* 10 */ DECLARE_NV_DEV("NFORCE3-250",		ATA_UDMA6),
-+	/* 11 */ DECLARE_NV_DEV("NFORCE3-250-SATA",	ATA_UDMA6),
-+	/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2",	ATA_UDMA6),
-+	/* 13 */ DECLARE_NV_DEV("NFORCE-CK804",		ATA_UDMA6),
-+	/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04",		ATA_UDMA6),
-+	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51",		ATA_UDMA6),
-+	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55",		ATA_UDMA6),
-+	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61",		ATA_UDMA6),
-+	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65",		ATA_UDMA6),
-+	/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67",		ATA_UDMA6),
-+	/* 20 */ DECLARE_NV_DEV("NFORCE-MCP73",		ATA_UDMA6),
-+	/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77",		ATA_UDMA6),
-+
-+	/* 22 */ DECLARE_AMD_DEV("AMD5536", ATA_SWDMA2, ATA_UDMA5),
- };
+ 	return 0;
+@@ -135,7 +138,8 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
  
- static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
+ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ 				  struct ehca_wqe *wqe_p,
+-				  const struct ib_send_wr *send_wr)
++				  const struct ib_send_wr *send_wr,
++				  int hidden)
  {
--	amd_chipset = amd74xx_chipsets + id->driver_data;
--	amd_config = amd_ide_chips + id->driver_data;
--	if (dev->device != amd_config->id) {
--		printk(KERN_ERR "%s: assertion 0x%02x == 0x%02x failed !\n",
--		       pci_name(dev), dev->device, amd_config->id);
--		return -ENODEV;
-+	struct ide_port_info d;
-+	u8 idx = id->driver_data;
+ 	u32 idx;
+ 	u64 dma_length;
+@@ -176,7 +180,9 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ 
+ 	wqe_p->wr_flag = 0;
+ 
+-	if (send_wr->send_flags & IB_SEND_SIGNALED)
++	if ((send_wr->send_flags & IB_SEND_SIGNALED ||
++	    qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
++	    && !hidden)
+ 		wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
+ 
+ 	if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
+@@ -199,10 +205,14 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ 
+ 		wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8;
+ 		wqe_p->local_ee_context_qkey = remote_qkey;
+-		if (!send_wr->wr.ud.ah) {
++		if (unlikely(!send_wr->wr.ud.ah)) {
+ 			ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
+ 			return -EINVAL;
+ 		}
++		if (unlikely(send_wr->wr.ud.remote_qpn == 0)) {
++			ehca_gen_err("dest QP# is 0. qp=%x", qp->real_qp_num);
++			return -EINVAL;
++		}
+ 		my_av = container_of(send_wr->wr.ud.ah, struct ehca_av, ib_ah);
+ 		wqe_p->u.ud_av.ud_av = my_av->av;
+ 
+@@ -255,6 +265,15 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
+ 		} /* eof idx */
+ 		wqe_p->u.nud.atomic_1st_op_dma_len = dma_length;
+ 
++		/* unsolicited ack circumvention */
++		if (send_wr->opcode == IB_WR_RDMA_READ) {
++			/* on RDMA read, switch on and reset counters */
++			qp->message_count = qp->packet_count = 0;
++			qp->unsol_ack_circ = 1;
++		} else
++			/* else estimate #packets */
++			qp->packet_count += (dma_length >> qp->mtu_shift) + 1;
 +
-+	d = amd74xx_chipsets[idx];
+ 		break;
+ 
+ 	default:
+@@ -355,13 +374,49 @@ static inline void map_ib_wc_status(u32 cqe_status,
+ 		*wc_status = IB_WC_SUCCESS;
+ }
+ 
++static inline int post_one_send(struct ehca_qp *my_qp,
++			 struct ib_send_wr *cur_send_wr,
++			 struct ib_send_wr **bad_send_wr,
++			 int hidden)
++{
++	struct ehca_wqe *wqe_p;
++	int ret;
++	u64 start_offset = my_qp->ipz_squeue.current_q_offset;
 +
++	/* get pointer next to free WQE */
++	wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
++	if (unlikely(!wqe_p)) {
++		/* too many posted work requests: queue overflow */
++		if (bad_send_wr)
++			*bad_send_wr = cur_send_wr;
++		ehca_err(my_qp->ib_qp.device, "Too many posted WQEs "
++			 "qp_num=%x", my_qp->ib_qp.qp_num);
++		return -ENOMEM;
++	}
++	/* write a SEND WQE into the QUEUE */
++	ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, hidden);
 +	/*
-+	 * Check for bad SWDMA and incorrectly wired Serenade mainboards.
++	 * if something failed,
++	 * reset the free entry pointer to the start value
 +	 */
-+	if (idx == 1) {
-+		if (dev->revision <= 7)
-+			d.swdma_mask = 0;
-+		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-+	} else if (idx == 4) {
-+		if (dev->subsystem_vendor == PCI_VENDOR_ID_AMD &&
-+		    dev->subsystem_device == PCI_DEVICE_ID_AMD_SERENADE)
-+			d.udma_mask = ATA_UDMA5;
- 	}
--	return ide_setup_pci_device(dev, amd_chipset);
++	if (unlikely(ret)) {
++		my_qp->ipz_squeue.current_q_offset = start_offset;
++		if (bad_send_wr)
++			*bad_send_wr = cur_send_wr;
++		ehca_err(my_qp->ib_qp.device, "Could not write WQE "
++			 "qp_num=%x", my_qp->ib_qp.qp_num);
++		return -EINVAL;
++	}
 +
-+	printk(KERN_INFO "%s: %s (rev %02x) UDMA%s controller\n",
-+			 d.name, pci_name(dev), dev->revision,
-+			 amd_dma[fls(d.udma_mask) - 1]);
++	return 0;
++}
 +
-+	return ide_setup_pci_device(dev, &d);
- }
+ int ehca_post_send(struct ib_qp *qp,
+ 		   struct ib_send_wr *send_wr,
+ 		   struct ib_send_wr **bad_send_wr)
+ {
+ 	struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
+ 	struct ib_send_wr *cur_send_wr;
+-	struct ehca_wqe *wqe_p;
+ 	int wqe_cnt = 0;
+ 	int ret = 0;
+ 	unsigned long flags;
+@@ -369,37 +424,33 @@ int ehca_post_send(struct ib_qp *qp,
+ 	/* LOCK the QUEUE */
+ 	spin_lock_irqsave(&my_qp->spinlock_s, flags);
  
- static const struct pci_device_id amd74xx_pci_tbl[] = {
-diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
-index ef8e016..7e037c8 100644
---- a/drivers/ide/pci/atiixp.c
-+++ b/drivers/ide/pci/atiixp.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/atiixp.c	Version 0.03	Aug 3 2007
-- *
-  *  Copyright (C) 2003 ATI Inc. <hyu at ati.com>
-  *  Copyright (C) 2004,2007 Bartlomiej Zolnierkiewicz
++	/* Send an empty extra RDMA read if:
++	 *  1) there has been an RDMA read on this connection before
++	 *  2) no RDMA read occurred for ACK_CIRC_THRESHOLD link packets
++	 *  3) we can be sure that any previous extra RDMA read has been
++	 *     processed so we don't overflow the SQ
++	 */
++	if (unlikely(my_qp->unsol_ack_circ &&
++		     my_qp->packet_count > ACK_CIRC_THRESHOLD &&
++		     my_qp->message_count > my_qp->init_attr.cap.max_send_wr)) {
++		/* insert an empty RDMA READ to fix up the remote QP state */
++		struct ib_send_wr circ_wr;
++		memset(&circ_wr, 0, sizeof(circ_wr));
++		circ_wr.opcode = IB_WR_RDMA_READ;
++		post_one_send(my_qp, &circ_wr, NULL, 1); /* ignore retcode */
++		wqe_cnt++;
++		ehca_dbg(qp->device, "posted circ wr  qp_num=%x", qp->qp_num);
++		my_qp->message_count = my_qp->packet_count = 0;
++	}
++
+ 	/* loop processes list of send reqs */
+ 	for (cur_send_wr = send_wr; cur_send_wr != NULL;
+ 	     cur_send_wr = cur_send_wr->next) {
+-		u64 start_offset = my_qp->ipz_squeue.current_q_offset;
+-		/* get pointer next to free WQE */
+-		wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
+-		if (unlikely(!wqe_p)) {
+-			/* too many posted work requests: queue overflow */
+-			if (bad_send_wr)
+-				*bad_send_wr = cur_send_wr;
+-			if (wqe_cnt == 0) {
+-				ret = -ENOMEM;
+-				ehca_err(qp->device, "Too many posted WQEs "
+-					 "qp_num=%x", qp->qp_num);
+-			}
+-			goto post_send_exit0;
+-		}
+-		/* write a SEND WQE into the QUEUE */
+-		ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr);
+-		/*
+-		 * if something failed,
+-		 * reset the free entry pointer to the start value
+-		 */
++		ret = post_one_send(my_qp, cur_send_wr, bad_send_wr, 0);
+ 		if (unlikely(ret)) {
+-			my_qp->ipz_squeue.current_q_offset = start_offset;
+-			*bad_send_wr = cur_send_wr;
+-			if (wqe_cnt == 0) {
+-				ret = -EINVAL;
+-				ehca_err(qp->device, "Could not write WQE "
+-					 "qp_num=%x", qp->qp_num);
+-			}
++			/* if one or more WQEs were successful, don't fail */
++			if (wqe_cnt)
++				ret = 0;
+ 			goto post_send_exit0;
+ 		}
+ 		wqe_cnt++;
+@@ -410,6 +461,7 @@ int ehca_post_send(struct ib_qp *qp,
+ post_send_exit0:
+ 	iosync(); /* serialize GAL register access */
+ 	hipz_update_sqa(my_qp, wqe_cnt);
++	my_qp->message_count += wqe_cnt;
+ 	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
+ 	return ret;
+ }
+diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c
+index f0792e5..706d97a 100644
+--- a/drivers/infiniband/hw/ehca/ehca_sqp.c
++++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
+@@ -39,15 +39,18 @@
+  * POSSIBILITY OF SUCH DAMAGE.
   */
-@@ -8,15 +6,11 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/ioport.h>
- #include <linux/pci.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
--#include <linux/delay.h>
- #include <linux/init.h>
- 
--#include <asm/io.h>
--
- #define ATIIXP_IDE_PIO_TIMING		0x40
- #define ATIIXP_IDE_MDMA_TIMING		0x44
- #define ATIIXP_IDE_PIO_CONTROL		0x48
-@@ -43,47 +37,8 @@ static atiixp_ide_timing mdma_timing[] = {
- 	{ 0x02, 0x00 },
- };
  
--static int save_mdma_mode[4];
--
- static DEFINE_SPINLOCK(atiixp_lock);
++#include <rdma/ib_mad.h>
  
--static void atiixp_dma_host_on(ide_drive_t *drive)
--{
--	struct pci_dev *dev = drive->hwif->pci_dev;
--	unsigned long flags;
--	u16 tmp16;
--
--	spin_lock_irqsave(&atiixp_lock, flags);
--
--	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
--	if (save_mdma_mode[drive->dn])
--		tmp16 &= ~(1 << drive->dn);
--	else
--		tmp16 |= (1 << drive->dn);
--	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
--
--	spin_unlock_irqrestore(&atiixp_lock, flags);
--
--	ide_dma_host_on(drive);
--}
--
--static void atiixp_dma_host_off(ide_drive_t *drive)
--{
--	struct pci_dev *dev = drive->hwif->pci_dev;
--	unsigned long flags;
--	u16 tmp16;
--
--	spin_lock_irqsave(&atiixp_lock, flags);
--
--	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &tmp16);
--	tmp16 &= ~(1 << drive->dn);
--	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, tmp16);
--
--	spin_unlock_irqrestore(&atiixp_lock, flags);
--
--	ide_dma_host_off(drive);
--}
--
- /**
-  *	atiixp_set_pio_mode	-	set host controller for PIO mode
-  *	@drive: drive
-@@ -94,7 +49,7 @@ static void atiixp_dma_host_off(ide_drive_t *drive)
+-#include <linux/module.h>
+-#include <linux/err.h>
+ #include "ehca_classes.h"
+ #include "ehca_tools.h"
+-#include "ehca_qes.h"
+ #include "ehca_iverbs.h"
+ #include "hcp_if.h"
  
- static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	unsigned long flags;
- 	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
- 	u32 pio_timing_data;
-@@ -127,37 +82,54 @@ static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
++#define IB_MAD_STATUS_REDIRECT		__constant_htons(0x0002)
++#define IB_MAD_STATUS_UNSUP_VERSION	__constant_htons(0x0004)
++#define IB_MAD_STATUS_UNSUP_METHOD	__constant_htons(0x0008)
++
++#define IB_PMA_CLASS_PORT_INFO		__constant_htons(0x0001)
  
- static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
- {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	unsigned long flags;
- 	int timing_shift = (drive->dn & 2) ? 16 : 0 + (drive->dn & 1) ? 0 : 8;
- 	u32 tmp32;
- 	u16 tmp16;
--
--	if (speed < XFER_MW_DMA_0)
--		return;
-+	u16 udma_ctl = 0;
+ /**
+  * ehca_define_sqp - Defines special queue pair 1 (GSI QP). When special queue
+@@ -86,6 +89,9 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
+ 				 port, ret);
+ 			return ret;
+ 		}
++		shca->sport[port - 1].pma_qp_nr = pma_qp_nr;
++		ehca_dbg(&shca->ib_device, "port=%x pma_qp_nr=%x",
++			 port, pma_qp_nr);
+ 		break;
+ 	default:
+ 		ehca_err(&shca->ib_device, "invalid qp_type=%x",
+@@ -93,6 +99,9 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
+ 		return H_PARAMETER;
+ 	}
  
- 	spin_lock_irqsave(&atiixp_lock, flags);
++	if (ehca_nr_ports < 0) /* autodetect mode */
++		return H_SUCCESS;
++
+ 	for (counter = 0;
+ 	     shca->sport[port - 1].port_state != IB_PORT_ACTIVE &&
+ 		     counter < ehca_port_act_time;
+@@ -109,3 +118,85 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
  
--	save_mdma_mode[drive->dn] = 0;
-+	pci_read_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, &udma_ctl);
+ 	return H_SUCCESS;
+ }
 +
- 	if (speed >= XFER_UDMA_0) {
- 		pci_read_config_word(dev, ATIIXP_IDE_UDMA_MODE, &tmp16);
- 		tmp16 &= ~(0x07 << (drive->dn * 4));
- 		tmp16 |= ((speed & 0x07) << (drive->dn * 4));
- 		pci_write_config_word(dev, ATIIXP_IDE_UDMA_MODE, tmp16);
--	} else {
--		if ((speed >= XFER_MW_DMA_0) && (speed <= XFER_MW_DMA_2)) {
--			save_mdma_mode[drive->dn] = speed;
--			pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
--			tmp32 &= ~(0xff << timing_shift);
--			tmp32 |= (mdma_timing[speed & 0x03].recover_width << timing_shift) |
--				(mdma_timing[speed & 0x03].command_width << (timing_shift + 4));
--			pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
--		}
++struct ib_perf {
++	struct ib_mad_hdr mad_hdr;
++	u8 reserved[40];
++	u8 data[192];
++} __attribute__ ((packed));
 +
-+		udma_ctl |= (1 << drive->dn);
-+	} else if (speed >= XFER_MW_DMA_0) {
-+		u8 i = speed & 0x03;
 +
-+		pci_read_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, &tmp32);
-+		tmp32 &= ~(0xff << timing_shift);
-+		tmp32 |= (mdma_timing[i].recover_width << timing_shift) |
-+			 (mdma_timing[i].command_width << (timing_shift + 4));
-+		pci_write_config_dword(dev, ATIIXP_IDE_MDMA_TIMING, tmp32);
++static int ehca_process_perf(struct ib_device *ibdev, u8 port_num,
++			     struct ib_mad *in_mad, struct ib_mad *out_mad)
++{
++	struct ib_perf *in_perf = (struct ib_perf *)in_mad;
++	struct ib_perf *out_perf = (struct ib_perf *)out_mad;
++	struct ib_class_port_info *poi =
++		(struct ib_class_port_info *)out_perf->data;
++	struct ehca_shca *shca =
++		container_of(ibdev, struct ehca_shca, ib_device);
++	struct ehca_sport *sport = &shca->sport[port_num - 1];
++
++	ehca_dbg(ibdev, "method=%x", in_perf->mad_hdr.method);
++
++	*out_mad = *in_mad;
++
++	if (in_perf->mad_hdr.class_version != 1) {
++		ehca_warn(ibdev, "Unsupported class_version=%x",
++			  in_perf->mad_hdr.class_version);
++		out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_VERSION;
++		goto perf_reply;
++	}
++
++	switch (in_perf->mad_hdr.method) {
++	case IB_MGMT_METHOD_GET:
++	case IB_MGMT_METHOD_SET:
++		/* set class port info for redirection */
++		out_perf->mad_hdr.attr_id = IB_PMA_CLASS_PORT_INFO;
++		out_perf->mad_hdr.status = IB_MAD_STATUS_REDIRECT;
++		memset(poi, 0, sizeof(*poi));
++		poi->base_version = 1;
++		poi->class_version = 1;
++		poi->resp_time_value = 18;
++		poi->redirect_lid = sport->saved_attr.lid;
++		poi->redirect_qp = sport->pma_qp_nr;
++		poi->redirect_qkey = IB_QP1_QKEY;
++		poi->redirect_pkey = IB_DEFAULT_PKEY_FULL;
 +
-+		udma_ctl &= ~(1 << drive->dn);
- 	}
- 
-+	pci_write_config_word(dev, ATIIXP_IDE_UDMA_CONTROL, udma_ctl);
++		ehca_dbg(ibdev, "ehca_pma_lid=%x ehca_pma_qp=%x",
++			 sport->saved_attr.lid, sport->pma_qp_nr);
++		break;
 +
- 	spin_unlock_irqrestore(&atiixp_lock, flags);
- }
- 
-+static u8 __devinit atiixp_cable_detect(ide_hwif_t *hwif)
++	case IB_MGMT_METHOD_GET_RESP:
++		return IB_MAD_RESULT_FAILURE;
++
++	default:
++		out_perf->mad_hdr.status = IB_MAD_STATUS_UNSUP_METHOD;
++		break;
++	}
++
++perf_reply:
++	out_perf->mad_hdr.method = IB_MGMT_METHOD_GET_RESP;
++
++	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
++}
++
++int ehca_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
++		     struct ib_wc *in_wc, struct ib_grh *in_grh,
++		     struct ib_mad *in_mad,
++		     struct ib_mad *out_mad)
 +{
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
-+	u8 udma_mode = 0, ch = hwif->channel;
++	int ret;
 +
-+	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
++	if (!port_num || port_num > ibdev->phys_port_cnt)
++		return IB_MAD_RESULT_FAILURE;
 +
-+	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
-+		return ATA_CBL_PATA80;
-+	else
-+		return ATA_CBL_PATA40;
++	/* accept only pma request */
++	if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_PERF_MGMT)
++		return IB_MAD_RESULT_SUCCESS;
++
++	ehca_dbg(ibdev, "port_num=%x src_qp=%x", port_num, in_wc->src_qp);
++	ret = ehca_process_perf(ibdev, port_num, in_mad, out_mad);
++
++	return ret;
 +}
+diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
+index 851df8a..4146210 100644
+--- a/drivers/infiniband/hw/ipath/ipath_common.h
++++ b/drivers/infiniband/hw/ipath/ipath_common.h
+@@ -82,6 +82,16 @@
+ #define IPATH_IB_LINK_EXTERNAL	7 /* normal, disable local loopback */
+ 
+ /*
++ * These 3 values (SDR and DDR may be ORed for auto-speed
++ * negotiation) are used for the 3rd argument to path_f_set_ib_cfg
++ * with cmd IPATH_IB_CFG_SPD_ENB, by direct calls or via sysfs.  They
++ * are also the the possible values for ipath_link_speed_enabled and active
++ * The values were chosen to match values used within the IB spec.
++ */
++#define IPATH_IB_SDR 1
++#define IPATH_IB_DDR 2
 +
- /**
-  *	init_hwif_atiixp		-	fill in the hwif for the ATIIXP
-  *	@hwif: IDE interface
-@@ -168,25 +140,10 @@ static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
++/*
+  * stats maintained by the driver.  For now, at least, this is global
+  * to all minor devices.
+  */
+@@ -433,8 +443,9 @@ struct ipath_user_info {
+ #define IPATH_CMD_UNUSED_2	26
+ #define IPATH_CMD_PIOAVAILUPD	27	/* force an update of PIOAvail reg */
+ #define IPATH_CMD_POLL_TYPE	28	/* set the kind of polling we want */
++#define IPATH_CMD_ARMLAUNCH_CTRL	29 /* armlaunch detection control */
  
- static void __devinit init_hwif_atiixp(ide_hwif_t *hwif)
- {
--	u8 udma_mode = 0;
--	u8 ch = hwif->channel;
--	struct pci_dev *pdev = hwif->pci_dev;
--
- 	hwif->set_pio_mode = &atiixp_set_pio_mode;
- 	hwif->set_dma_mode = &atiixp_set_dma_mode;
+-#define IPATH_CMD_MAX		28
++#define IPATH_CMD_MAX		29
  
--	if (!hwif->dma_base)
--		return;
--
--	pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ch, &udma_mode);
--
--	if ((udma_mode & 0x07) >= 0x04 || (udma_mode & 0x70) >= 0x40)
--		hwif->cbl = ATA_CBL_PATA80;
--	else
--		hwif->cbl = ATA_CBL_PATA40;
--
--	hwif->dma_host_on = &atiixp_dma_host_on;
--	hwif->dma_host_off = &atiixp_dma_host_off;
-+	hwif->cable_detect = atiixp_cable_detect;
- }
+ /*
+  * Poll types
+@@ -477,6 +488,8 @@ struct ipath_cmd {
+ 		__u64 port_info;
+ 		/* enable/disable receipt of packets */
+ 		__u32 recv_ctrl;
++		/* enable/disable armlaunch errors (non-zero to enable) */
++		__u32 armlaunch_ctrl;
+ 		/* partition key to set */
+ 		__u16 part_key;
+ 		/* user address of __u32 bitmask of active slaves */
+@@ -579,7 +592,7 @@ struct ipath_flash {
+ struct infinipath_counters {
+ 	__u64 LBIntCnt;
+ 	__u64 LBFlowStallCnt;
+-	__u64 Reserved1;
++	__u64 TxSDmaDescCnt;	/* was Reserved1 */
+ 	__u64 TxUnsupVLErrCnt;
+ 	__u64 TxDataPktCnt;
+ 	__u64 TxFlowPktCnt;
+@@ -615,12 +628,26 @@ struct infinipath_counters {
+ 	__u64 RxP6HdrEgrOvflCnt;
+ 	__u64 RxP7HdrEgrOvflCnt;
+ 	__u64 RxP8HdrEgrOvflCnt;
+-	__u64 Reserved6;
+-	__u64 Reserved7;
++	__u64 RxP9HdrEgrOvflCnt;	/* was Reserved6 */
++	__u64 RxP10HdrEgrOvflCnt;	/* was Reserved7 */
++	__u64 RxP11HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP12HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP13HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP14HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP15HdrEgrOvflCnt;	/* new for IBA7220 */
++	__u64 RxP16HdrEgrOvflCnt;	/* new for IBA7220 */
+ 	__u64 IBStatusChangeCnt;
+ 	__u64 IBLinkErrRecoveryCnt;
+ 	__u64 IBLinkDownedCnt;
+ 	__u64 IBSymbolErrCnt;
++	/* The following are new for IBA7220 */
++	__u64 RxVL15DroppedPktCnt;
++	__u64 RxOtherLocalPhyErrCnt;
++	__u64 PcieRetryBufDiagQwordCnt;
++	__u64 ExcessBufferOvflCnt;
++	__u64 LocalLinkIntegrityErrCnt;
++	__u64 RxVlErrCnt;
++	__u64 RxDlidFltrCnt;
+ };
  
- static const struct ide_port_info atiixp_pci_info[] __devinitdata = {
-diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c
-index 4aa4810..bd24dad 100644
---- a/drivers/ide/pci/cmd640.c
-+++ b/drivers/ide/pci/cmd640.c
-@@ -1,6 +1,4 @@
  /*
-- *  linux/drivers/ide/pci/cmd640.c		Version 1.02  Sep 01, 1996
-- *
-  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
-  */
+diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
+index d1380c7..a03bd28 100644
+--- a/drivers/infiniband/hw/ipath/ipath_cq.c
++++ b/drivers/infiniband/hw/ipath/ipath_cq.c
+@@ -421,7 +421,7 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
+ 	else
+ 		n = head - tail;
+ 	if (unlikely((u32)cqe < n)) {
+-		ret = -EOVERFLOW;
++		ret = -EINVAL;
+ 		goto bail_unlock;
+ 	}
+ 	for (n = 0; tail != head; n++) {
+diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
+index 19c56e6..d6f6953 100644
+--- a/drivers/infiniband/hw/ipath/ipath_debug.h
++++ b/drivers/infiniband/hw/ipath/ipath_debug.h
+@@ -55,7 +55,7 @@
+ #define __IPATH_PKTDBG      0x80	/* print packet data */
+ /* print process startup (init)/exit messages */
+ #define __IPATH_PROCDBG     0x100
+-/* print mmap/nopage stuff, not using VDBG any more */
++/* print mmap/fault stuff, not using VDBG any more */
+ #define __IPATH_MMDBG       0x200
+ #define __IPATH_ERRPKTDBG   0x400
+ #define __IPATH_USER_SEND   0x1000	/* use user mode send */
+@@ -81,7 +81,7 @@
+ #define __IPATH_VERBDBG   0x0	/* very verbose debug */
+ #define __IPATH_PKTDBG    0x0	/* print packet data */
+ #define __IPATH_PROCDBG   0x0	/* process startup (init)/exit messages */
+-/* print mmap/nopage stuff, not using VDBG any more */
++/* print mmap/fault stuff, not using VDBG any more */
+ #define __IPATH_MMDBG     0x0
+ #define __IPATH_EPKTDBG   0x0	/* print ethernet packet data */
+ #define __IPATH_IPATHDBG  0x0	/* Ethernet (IPATH) table dump on */
+diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
+index 1f152de..d5ff6ca 100644
+--- a/drivers/infiniband/hw/ipath/ipath_driver.c
++++ b/drivers/infiniband/hw/ipath/ipath_driver.c
+@@ -121,6 +121,9 @@ static struct pci_driver ipath_driver = {
+ 	.probe = ipath_init_one,
+ 	.remove = __devexit_p(ipath_remove_one),
+ 	.id_table = ipath_pci_tbl,
++	.driver = {
++		.groups = ipath_driver_attr_groups,
++	},
+ };
  
-@@ -105,10 +103,6 @@
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
-@@ -705,10 +699,22 @@ static int pci_conf2(void)
- 	return 0;
- }
+ static void ipath_check_status(struct work_struct *work)
+@@ -331,6 +334,8 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+ 		udelay(1);
+ 	}
  
-+static const struct ide_port_info cmd640_port_info __initdata = {
-+	.chipset		= ide_cmd640,
-+	.host_flags		= IDE_HFLAG_SERIALIZE |
-+				  IDE_HFLAG_NO_DMA |
-+				  IDE_HFLAG_NO_AUTOTUNE |
-+				  IDE_HFLAG_ABUSE_PREFETCH |
-+				  IDE_HFLAG_ABUSE_FAST_DEVSEL,
-+#ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
-+	.pio_mask		= ATA_PIO5,
-+#endif
-+};
++	ipath_disable_armlaunch(dd);
 +
- /*
-- * Probe for a cmd640 chipset, and initialize it if found.  Called from ide.c
-+ * Probe for a cmd640 chipset, and initialize it if found.
-  */
--int __init ide_probe_for_cmd640x (void)
-+static int __init cmd640x_init(void)
- {
- #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
- 	int second_port_toggled = 0;
-@@ -717,6 +723,7 @@ int __init ide_probe_for_cmd640x (void)
- 	const char *bus_type, *port2;
- 	unsigned int index;
- 	u8 b, cfr;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
+ 	writeq(0, piobuf); /* length 0, no dwords actually sent */
+ 	ipath_flush_wc();
  
- 	if (cmd640_vlb && probe_for_cmd640_vlb()) {
- 		bus_type = "VLB";
-@@ -761,14 +768,12 @@ int __init ide_probe_for_cmd640x (void)
- 	setup_device_ptrs ();
- 	printk("%s: buggy cmd640%c interface on %s, config=0x%02x\n",
- 	       cmd_hwif0->name, 'a' + cmd640_chip_version - 1, bus_type, cfr);
--	cmd_hwif0->chipset = ide_cmd640;
- #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
--	cmd_hwif0->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
--				IDE_HFLAG_ABUSE_FAST_DEVSEL;
--	cmd_hwif0->pio_mask = ATA_PIO5;
- 	cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode;
- #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
+@@ -362,6 +367,7 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
+ done:
+ 	/* disarm piobuf, so it's available again */
+ 	ipath_disarm_piobufs(dd, pbnum, 1);
++	ipath_enable_armlaunch(dd);
+ }
  
-+	idx[0] = cmd_hwif0->index;
-+
- 	/*
- 	 * Ensure compatibility by always using the slowest timings
- 	 * for access to the drive's command register block,
-@@ -814,21 +819,14 @@ int __init ide_probe_for_cmd640x (void)
- 	 * Initialize data for secondary cmd640 port, if enabled
- 	 */
- 	if (second_port_cmd640) {
--		cmd_hwif0->serialized = 1;
--		cmd_hwif1->serialized = 1;
--		cmd_hwif1->chipset = ide_cmd640;
--		cmd_hwif0->mate = cmd_hwif1;
--		cmd_hwif1->mate = cmd_hwif0;
--		cmd_hwif1->channel = 1;
- #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED
--		cmd_hwif1->host_flags = IDE_HFLAG_ABUSE_PREFETCH |
--					IDE_HFLAG_ABUSE_FAST_DEVSEL;
--		cmd_hwif1->pio_mask = ATA_PIO5;
- 		cmd_hwif1->set_pio_mode = &cmd640_set_pio_mode;
- #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
-+
-+		idx[1] = cmd_hwif1->index;
+ static int __devinit ipath_init_one(struct pci_dev *pdev,
+@@ -800,31 +806,37 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
+ 			  unsigned cnt)
+ {
+ 	unsigned i, last = first + cnt;
+-	u64 sendctrl, sendorig;
++	unsigned long flags;
+ 
+ 	ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
+-	sendorig = dd->ipath_sendctrl;
+ 	for (i = first; i < last; i++) {
+-		sendctrl = sendorig  | INFINIPATH_S_DISARM |
+-			(i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
++		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++		/*
++		 * The disarm-related bits are write-only, so it
++		 * is ok to OR them in with our copy of sendctrl
++		 * while we hold the lock.
++		 */
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-				 sendctrl);
++			dd->ipath_sendctrl | INFINIPATH_S_DISARM |
++			(i << INFINIPATH_S_DISARMPIOBUF_SHIFT));
++		/* can't disarm bufs back-to-back per iba7220 spec */
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
  	}
- 	printk(KERN_INFO "%s: %sserialized, secondary interface %s\n", cmd_hwif1->name,
--		cmd_hwif0->serialized ? "" : "not ", port2);
-+			 second_port_cmd640 ? "" : "not ", port2);
  
  	/*
- 	 * Establish initial timings/prefetch for all drives.
-@@ -872,6 +870,13 @@ int __init ide_probe_for_cmd640x (void)
- #ifdef CMD640_DUMP_REGS
- 	cmd640_dump_regs();
- #endif
-+
-+	ide_device_add(idx, &cmd640_port_info);
-+
- 	return 1;
+-	 * Write it again with current value, in case ipath_sendctrl changed
+-	 * while we were looping; no critical bits that would require
+-	 * locking.
+-	 *
+-	 * disable PIOAVAILUPD, then re-enable, reading scratch in
++	 * Disable PIOAVAILUPD, then re-enable, reading scratch in
+ 	 * between.  This seems to avoid a chip timing race that causes
+-	 * pioavail updates to memory to stop.
++	 * pioavail updates to memory to stop.  We xor as we don't
++	 * know the state of the bit when we're called.
+ 	 */
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-			 sendorig & ~INFINIPATH_S_PIOBUFAVAILUPD);
+-	sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		dd->ipath_sendctrl ^ INFINIPATH_S_PIOBUFAVAILUPD);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ 			 dd->ipath_sendctrl);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
  }
  
-+module_param_named(probe_vlb, cmd640_vlb, bool, 0);
-+MODULE_PARM_DESC(probe_vlb, "probe for VLB version of CMD640 chipset");
-+
-+module_init(cmd640x_init);
-diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
-index bc55333..edabe62 100644
---- a/drivers/ide/pci/cmd64x.c
-+++ b/drivers/ide/pci/cmd64x.c
-@@ -1,6 +1,4 @@
+ /**
+@@ -1000,12 +1012,10 @@ static void get_rhf_errstring(u32 err, char *msg, size_t len)
+  * ipath_get_egrbuf - get an eager buffer
+  * @dd: the infinipath device
+  * @bufnum: the eager buffer to get
+- * @err: unused
+  *
+  * must only be called if ipath_pd[port] is known to be allocated
+  */
+-static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
+-				     int err)
++static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum)
+ {
+ 	return dd->ipath_port0_skbinfo ?
+ 		(void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL;
+@@ -1097,13 +1107,14 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
+ 
  /*
-- * linux/drivers/ide/pci/cmd64x.c		Version 1.52	Dec 24, 2007
-- *
-  * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
-  *           Due to massive hardware bugs, UltraDMA is only supported
-  *           on the 646U2 and not on the 646U.
-@@ -15,15 +13,12 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
+  * ipath_kreceive - receive a packet
+- * @dd: the infinipath device
++ * @pd: the infinipath port
+  *
+  * called from interrupt handler for errors or receive interrupt
+  */
+-void ipath_kreceive(struct ipath_devdata *dd)
++void ipath_kreceive(struct ipath_portdata *pd)
+ {
+ 	u64 *rc;
++	struct ipath_devdata *dd = pd->port_dd;
+ 	void *ebuf;
+ 	const u32 rsize = dd->ipath_rcvhdrentsize;	/* words */
+ 	const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize;	/* words */
+@@ -1118,8 +1129,8 @@ void ipath_kreceive(struct ipath_devdata *dd)
+ 		goto bail;
+ 	}
  
- #include <asm/io.h>
+-	l = dd->ipath_port0head;
+-	hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr);
++	l = pd->port_head;
++	hdrqtail = ipath_get_rcvhdrtail(pd);
+ 	if (l == hdrqtail)
+ 		goto bail;
  
--#define DISPLAY_CMD64X_TIMINGS
--
- #define CMD_DEBUG 0
+@@ -1128,7 +1139,7 @@ reloop:
+ 		u32 qp;
+ 		u8 *bthbytes;
  
- #if CMD_DEBUG
-@@ -37,11 +32,6 @@
-  */
- #define CFR		0x50
- #define   CFR_INTR_CH0		0x04
--#define CNTRL		0x51
--#define   CNTRL_ENA_1ST 	0x04
--#define   CNTRL_ENA_2ND 	0x08
--#define   CNTRL_DIS_RA0 	0x40
--#define   CNTRL_DIS_RA1 	0x80
+-		rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2));
++		rc = (u64 *) (pd->port_rcvhdrq + (l << 2));
+ 		hdr = (struct ipath_message_header *)&rc[1];
+ 		/*
+ 		 * could make a network order version of IPATH_KD_QP, and
+@@ -1153,7 +1164,7 @@ reloop:
+ 			etail = ipath_hdrget_index((__le32 *) rc);
+ 			if (tlen > sizeof(*hdr) ||
+ 			    etype == RCVHQ_RCV_TYPE_NON_KD)
+-				ebuf = ipath_get_egrbuf(dd, etail, 0);
++				ebuf = ipath_get_egrbuf(dd, etail);
+ 		}
  
- #define	CMDTIM		0x52
- #define	ARTTIM0		0x53
-@@ -60,108 +50,13 @@
- #define MRDMODE		0x71
- #define   MRDMODE_INTR_CH0	0x04
- #define   MRDMODE_INTR_CH1	0x08
--#define   MRDMODE_BLK_CH0	0x10
--#define   MRDMODE_BLK_CH1	0x20
--#define BMIDESR0	0x72
- #define UDIDETCR0	0x73
- #define DTPR0		0x74
- #define BMIDECR1	0x78
- #define BMIDECSR	0x79
--#define BMIDESR1	0x7A
- #define UDIDETCR1	0x7B
- #define DTPR1		0x7C
+ 		/*
+@@ -1188,7 +1199,7 @@ reloop:
+ 				  be32_to_cpu(hdr->bth[0]) & 0xff);
+ 		else {
+ 			/*
+-			 * error packet, type of error	unknown.
++			 * error packet, type of error unknown.
+ 			 * Probably type 3, but we don't know, so don't
+ 			 * even try to print the opcode, etc.
+ 			 */
+@@ -1238,7 +1249,7 @@ reloop:
+ 		 * earlier packets, we "almost" guarantee we have covered
+ 		 * that case.
+ 		 */
+-		u32 hqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
++		u32 hqtail = ipath_get_rcvhdrtail(pd);
+ 		if (hqtail != hdrqtail) {
+ 			hdrqtail = hqtail;
+ 			reloop = 1; /* loop 1 extra time at most */
+@@ -1248,7 +1259,7 @@ reloop:
  
--#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
--#include <linux/stat.h>
--#include <linux/proc_fs.h>
--
--static u8 cmd64x_proc = 0;
--
--#define CMD_MAX_DEVS		5
--
--static struct pci_dev *cmd_devs[CMD_MAX_DEVS];
--static int n_cmd_devs;
--
--static char * print_cmd64x_get_info (char *buf, struct pci_dev *dev, int index)
+ 	pkttot += i;
+ 
+-	dd->ipath_port0head = l;
++	pd->port_head = l;
+ 
+ 	if (pkttot > ipath_stats.sps_maxpkts_call)
+ 		ipath_stats.sps_maxpkts_call = pkttot;
+@@ -1332,14 +1343,9 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
+ 		/*
+ 		 * Chip Errata: bug 6641; even and odd qwords>3 are swapped
+ 		 */
+-		if (i > 3) {
+-			if (i & 1)
+-				piov = le64_to_cpu(
+-					dd->ipath_pioavailregs_dma[i - 1]);
+-			else
+-				piov = le64_to_cpu(
+-					dd->ipath_pioavailregs_dma[i + 1]);
+-		} else
++		if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
++			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i ^ 1]);
++		else
+ 			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
+ 		pchg = _IPATH_ALL_CHECKBITS &
+ 			~(dd->ipath_pioavailshadow[i] ^ piov);
+@@ -1598,7 +1604,8 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
+ 
+ 	/* clear for security and sanity on each use */
+ 	memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size);
+-	memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
++	if (pd->port_rcvhdrtail_kvaddr)
++		memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
+ 
+ 	/*
+ 	 * tell chip each time we init it, even if we are re-using previous
+@@ -1614,77 +1621,6 @@ bail:
+ 	return ret;
+ }
+ 
+-int ipath_waitfor_complete(struct ipath_devdata *dd, ipath_kreg reg_id,
+-			   u64 bits_to_wait_for, u64 * valp)
 -{
--	char *p = buf;
--	u8 reg72 = 0, reg73 = 0;			/* primary */
--	u8 reg7a = 0, reg7b = 0;			/* secondary */
--	u8 reg50 = 1, reg51 = 1, reg57 = 0, reg71 = 0;	/* extra */
--
--	p += sprintf(p, "\nController: %d\n", index);
--	p += sprintf(p, "PCI-%x Chipset.\n", dev->device);
--
--	(void) pci_read_config_byte(dev, CFR,       &reg50);
--	(void) pci_read_config_byte(dev, CNTRL,     &reg51);
--	(void) pci_read_config_byte(dev, ARTTIM23,  &reg57);
--	(void) pci_read_config_byte(dev, MRDMODE,   &reg71);
--	(void) pci_read_config_byte(dev, BMIDESR0,  &reg72);
--	(void) pci_read_config_byte(dev, UDIDETCR0, &reg73);
--	(void) pci_read_config_byte(dev, BMIDESR1,  &reg7a);
--	(void) pci_read_config_byte(dev, UDIDETCR1, &reg7b);
--
--	/* PCI0643/6 originally didn't have the primary channel enable bit */
--	if ((dev->device == PCI_DEVICE_ID_CMD_643) ||
--	    (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 3))
--		reg51 |= CNTRL_ENA_1ST;
+-	unsigned long timeout;
+-	u64 lastval, val;
+-	int ret;
 -
--	p += sprintf(p, "---------------- Primary Channel "
--			"---------------- Secondary Channel ------------\n");
--	p += sprintf(p, "                 %s                         %s\n",
--		 (reg51 & CNTRL_ENA_1ST) ? "enabled " : "disabled",
--		 (reg51 & CNTRL_ENA_2ND) ? "enabled " : "disabled");
--	p += sprintf(p, "---------------- drive0 --------- drive1 "
--			"-------- drive0 --------- drive1 ------\n");
--	p += sprintf(p, "DMA enabled:     %s              %s"
--			"             %s              %s\n",
--		(reg72 & 0x20) ? "yes" : "no ", (reg72 & 0x40) ? "yes" : "no ",
--		(reg7a & 0x20) ? "yes" : "no ", (reg7a & 0x40) ? "yes" : "no ");
--	p += sprintf(p, "UltraDMA mode:   %s (%c)          %s (%c)",
--		( reg73 & 0x01) ? " on" : "off",
--		((reg73 & 0x30) == 0x30) ? ((reg73 & 0x04) ? '3' : '0') :
--		((reg73 & 0x30) == 0x20) ? ((reg73 & 0x04) ? '3' : '1') :
--		((reg73 & 0x30) == 0x10) ? ((reg73 & 0x04) ? '4' : '2') :
--		((reg73 & 0x30) == 0x00) ? ((reg73 & 0x04) ? '5' : '2') : '?',
--		( reg73 & 0x02) ? " on" : "off",
--		((reg73 & 0xC0) == 0xC0) ? ((reg73 & 0x08) ? '3' : '0') :
--		((reg73 & 0xC0) == 0x80) ? ((reg73 & 0x08) ? '3' : '1') :
--		((reg73 & 0xC0) == 0x40) ? ((reg73 & 0x08) ? '4' : '2') :
--		((reg73 & 0xC0) == 0x00) ? ((reg73 & 0x08) ? '5' : '2') : '?');
--	p += sprintf(p, "         %s (%c)          %s (%c)\n",
--		( reg7b & 0x01) ? " on" : "off",
--		((reg7b & 0x30) == 0x30) ? ((reg7b & 0x04) ? '3' : '0') :
--		((reg7b & 0x30) == 0x20) ? ((reg7b & 0x04) ? '3' : '1') :
--		((reg7b & 0x30) == 0x10) ? ((reg7b & 0x04) ? '4' : '2') :
--		((reg7b & 0x30) == 0x00) ? ((reg7b & 0x04) ? '5' : '2') : '?',
--		( reg7b & 0x02) ? " on" : "off",
--		((reg7b & 0xC0) == 0xC0) ? ((reg7b & 0x08) ? '3' : '0') :
--		((reg7b & 0xC0) == 0x80) ? ((reg7b & 0x08) ? '3' : '1') :
--		((reg7b & 0xC0) == 0x40) ? ((reg7b & 0x08) ? '4' : '2') :
--		((reg7b & 0xC0) == 0x00) ? ((reg7b & 0x08) ? '5' : '2') : '?');
--	p += sprintf(p, "Interrupt:       %s, %s                 %s, %s\n",
--		(reg71 & MRDMODE_BLK_CH0  ) ? "blocked" : "enabled",
--		(reg50 & CFR_INTR_CH0	  ) ? "pending" : "clear  ",
--		(reg71 & MRDMODE_BLK_CH1  ) ? "blocked" : "enabled",
--		(reg57 & ARTTIM23_INTR_CH1) ? "pending" : "clear  ");
+-	lastval = ipath_read_kreg64(dd, reg_id);
+-	/* wait a ridiculously long time */
+-	timeout = jiffies + msecs_to_jiffies(5);
+-	do {
+-		val = ipath_read_kreg64(dd, reg_id);
+-		/* set so they have something, even on failures. */
+-		*valp = val;
+-		if ((val & bits_to_wait_for) == bits_to_wait_for) {
+-			ret = 0;
+-			break;
+-		}
+-		if (val != lastval)
+-			ipath_cdbg(VERBOSE, "Changed from %llx to %llx, "
+-				   "waiting for %llx bits\n",
+-				   (unsigned long long) lastval,
+-				   (unsigned long long) val,
+-				   (unsigned long long) bits_to_wait_for);
+-		cond_resched();
+-		if (time_after(jiffies, timeout)) {
+-			ipath_dbg("Didn't get bits %llx in register 0x%x, "
+-				  "got %llx\n",
+-				  (unsigned long long) bits_to_wait_for,
+-				  reg_id, (unsigned long long) *valp);
+-			ret = -ENODEV;
+-			break;
+-		}
+-	} while (1);
 -
--	return (char *)p;
+-	return ret;
 -}
 -
--static int cmd64x_get_info (char *buffer, char **addr, off_t offset, int count)
+-/**
+- * ipath_waitfor_mdio_cmdready - wait for last command to complete
+- * @dd: the infinipath device
+- *
+- * Like ipath_waitfor_complete(), but we wait for the CMDVALID bit to go
+- * away indicating the last command has completed.  It doesn't return data
+- */
+-int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
 -{
--	char *p = buffer;
--	int i;
+-	unsigned long timeout;
+-	u64 val;
+-	int ret;
 -
--	for (i = 0; i < n_cmd_devs; i++) {
--		struct pci_dev *dev	= cmd_devs[i];
--		p = print_cmd64x_get_info(p, dev, i);
--	}
--	return p-buffer;	/* => must be less than 4k! */
--}
+-	/* wait a ridiculously long time */
+-	timeout = jiffies + msecs_to_jiffies(5);
+-	do {
+-		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_mdio);
+-		if (!(val & IPATH_MDIO_CMDVALID)) {
+-			ret = 0;
+-			break;
+-		}
+-		cond_resched();
+-		if (time_after(jiffies, timeout)) {
+-			ipath_dbg("CMDVALID stuck in mdio reg? (%llx)\n",
+-				  (unsigned long long) val);
+-			ret = -ENODEV;
+-			break;
+-		}
+-	} while (1);
 -
--#endif	/* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
+-	return ret;
+-}
 -
- static u8 quantize_timing(int timing, int quant)
- {
- 	return (timing + quant - 1) / quant;
-@@ -173,7 +68,7 @@ static u8 quantize_timing(int timing, int quant)
-  */
- static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_time)
- {
--	struct pci_dev *dev	= HWIF(drive)->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
- 	int clock_time		= 1000 / system_bus_clock();
- 	u8  cycle_count, active_count, recovery_count, drwtim;
- 	static const u8 recovery_values[] =
-@@ -220,7 +115,7 @@ static void program_cycle_times (ide_drive_t *drive, int cycle_time, int active_
- static void cmd64x_tune_pio(ide_drive_t *drive, const u8 pio)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	unsigned int cycle_time;
- 	u8 setup_count, arttim = 0;
  
-@@ -285,7 +180,7 @@ static void cmd64x_set_pio_mode(ide_drive_t *drive, const u8 pio)
- static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ /*
+  * Flush all sends that might be in the ready to send state, as well as any
+@@ -2053,6 +1989,8 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
+  */
+ void ipath_shutdown_device(struct ipath_devdata *dd)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 unit			= drive->dn & 0x01;
- 	u8 regU = 0, pciU	= hwif->channel ? UDIDETCR1 : UDIDETCR0;
++	unsigned long flags;
++
+ 	ipath_dbg("Shutting down the device\n");
  
-@@ -322,8 +217,6 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	case XFER_MW_DMA_0:
- 		program_cycle_times(drive, 480, 215);
- 		break;
--	default:
--		return;
+ 	dd->ipath_flags |= IPATH_LINKUNK;
+@@ -2073,9 +2011,13 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
+ 	 * gracefully stop all sends allowing any in progress to trickle out
+ 	 * first.
+ 	 */
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl = 0;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
+ 	/* flush it */
+ 	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++
+ 	/*
+ 	 * enough for anything that's going to trickle out to have actually
+ 	 * done so.
+@@ -2217,25 +2159,15 @@ static int __init infinipath_init(void)
+ 		goto bail_unit;
  	}
  
- 	if (speed >= XFER_SW_DMA_0)
-@@ -333,14 +226,15 @@ static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
- static int cmd648_ide_dma_end (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
- 	int err			= __ide_dma_end(drive);
- 	u8  irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
- 						  MRDMODE_INTR_CH0;
--	u8  mrdmode		= inb(hwif->dma_master + 0x01);
-+	u8  mrdmode		= inb(base + 1);
+-	ret = ipath_driver_create_group(&ipath_driver.driver);
+-	if (ret < 0) {
+-		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create driver "
+-		       "sysfs entries: error %d\n", -ret);
+-		goto bail_pci;
+-	}
+-
+ 	ret = ipath_init_ipathfs();
+ 	if (ret < 0) {
+ 		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
+ 		       "ipathfs: error %d\n", -ret);
+-		goto bail_group;
++		goto bail_pci;
+ 	}
  
- 	/* clear the interrupt bit */
- 	outb((mrdmode & ~(MRDMODE_INTR_CH0 | MRDMODE_INTR_CH1)) | irq_mask,
--	     hwif->dma_master + 0x01);
-+	     base + 1);
+ 	goto bail;
  
- 	return err;
- }
-@@ -348,7 +242,7 @@ static int cmd648_ide_dma_end (ide_drive_t *drive)
- static int cmd64x_ide_dma_end (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
- 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
- 						  CFR_INTR_CH0;
-@@ -365,10 +259,11 @@ static int cmd64x_ide_dma_end (ide_drive_t *drive)
- static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	unsigned long base	= hwif->dma_base - (hwif->channel * 8);
- 	u8 irq_mask		= hwif->channel ? MRDMODE_INTR_CH1 :
- 						  MRDMODE_INTR_CH0;
- 	u8 dma_stat		= inb(hwif->dma_status);
--	u8 mrdmode		= inb(hwif->dma_master + 0x01);
-+	u8 mrdmode		= inb(base + 1);
+-bail_group:
+-	ipath_driver_remove_group(&ipath_driver.driver);
+-
+ bail_pci:
+ 	pci_unregister_driver(&ipath_driver);
  
- #ifdef DEBUG
- 	printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
-@@ -387,7 +282,7 @@ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
- static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
+@@ -2250,8 +2182,6 @@ static void __exit infinipath_cleanup(void)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	int irq_reg		= hwif->channel ? ARTTIM23 : CFR;
- 	u8  irq_mask		= hwif->channel ? ARTTIM23_INTR_CH1 :
- 						  CFR_INTR_CH0;
-@@ -472,22 +367,12 @@ static unsigned int __devinit init_chipset_cmd64x(struct pci_dev *dev, const cha
- 	mrdmode &= ~0x30;
- 	(void) pci_write_config_byte(dev, MRDMODE, (mrdmode | 0x02));
+ 	ipath_exit_ipathfs();
  
--#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_IDE_PROC_FS)
--
--	cmd_devs[n_cmd_devs++] = dev;
--
--	if (!cmd64x_proc) {
--		cmd64x_proc = 1;
--		ide_pci_create_host_proc("cmd64x", cmd64x_get_info);
--	}
--#endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_IDE_PROC_FS */
+-	ipath_driver_remove_group(&ipath_driver.driver);
 -
+ 	ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
+ 	pci_unregister_driver(&ipath_driver);
+ 
+@@ -2344,5 +2274,34 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv)
+ 	}
  	return 0;
  }
- 
- static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
++
++/*
++ * Disable and enable the armlaunch error.  Used for PIO bandwidth testing on
++ * the 7220, which is count-based, rather than trigger-based.  Safe for the
++ * driver check, since it's at init.   Not completely safe when used for
++ * user-mode checking, since some error checking can be lost, but not
++ * particularly risky, and only has problematic side-effects in the face of
++ * very buggy user code.  There is no reference counting, but that's also
++ * fine, given the intended use.
++ */
++void ipath_enable_armlaunch(struct ipath_devdata *dd)
++{
++	dd->ipath_lasterror &= ~INFINIPATH_E_SPIOARMLAUNCH;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
++		INFINIPATH_E_SPIOARMLAUNCH);
++	dd->ipath_errormask |= INFINIPATH_E_SPIOARMLAUNCH;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
++		dd->ipath_errormask);
++}
++
++void ipath_disable_armlaunch(struct ipath_devdata *dd)
++{
++	/* so don't re-enable if already set */
++	dd->ipath_maskederrs &= ~INFINIPATH_E_SPIOARMLAUNCH;
++	dd->ipath_errormask &= ~INFINIPATH_E_SPIOARMLAUNCH;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
++		dd->ipath_errormask);
++}
++
+ module_init(infinipath_init);
+ module_exit(infinipath_cleanup);
+diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
+index e7c25db..e28a42f 100644
+--- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
++++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
+@@ -510,10 +510,10 @@ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
  {
--	struct pci_dev  *dev	= hwif->pci_dev;
-+	struct pci_dev  *dev	= to_pci_dev(hwif->dev);
- 	u8 bmidecsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
+ 	int ret;
  
- 	switch (dev->device) {
-@@ -502,11 +387,13 @@ static u8 __devinit ata66_cmd64x(ide_hwif_t *hwif)
+-	ret = down_interruptible(&dd->ipath_eep_sem);
++	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
+ 	if (!ret) {
+ 		ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
+-		up(&dd->ipath_eep_sem);
++		mutex_unlock(&dd->ipath_eep_lock);
+ 	}
  
- static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
+ 	return ret;
+@@ -524,10 +524,10 @@ int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
  {
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 
- 	hwif->set_pio_mode = &cmd64x_set_pio_mode;
- 	hwif->set_dma_mode = &cmd64x_set_dma_mode;
- 
-+	hwif->cable_detect = ata66_cmd64x;
-+
- 	if (!hwif->dma_base)
- 		return;
- 
-@@ -525,9 +412,6 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
- 	if (dev->device == PCI_DEVICE_ID_CMD_646 && dev->revision < 5)
- 		hwif->ultra_mask = 0x00;
- 
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = ata66_cmd64x(hwif);
--
- 	switch (dev->device) {
- 	case PCI_DEVICE_ID_CMD_648:
- 	case PCI_DEVICE_ID_CMD_649:
-@@ -555,7 +439,9 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
- 		.init_chipset	= init_chipset_cmd64x,
- 		.init_hwif	= init_hwif_cmd64x,
- 		.enablebits	= {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
--		.host_flags	= IDE_HFLAG_ABUSE_PREFETCH | IDE_HFLAG_BOOTABLE,
-+		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
-+				  IDE_HFLAG_ABUSE_PREFETCH |
-+				  IDE_HFLAG_BOOTABLE,
- 		.pio_mask	= ATA_PIO5,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= 0x00, /* no udma */
-diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
-index 0466462..0be1a82 100644
---- a/drivers/ide/pci/cs5520.c
-+++ b/drivers/ide/pci/cs5520.c
-@@ -35,22 +35,12 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
--
--#include <linux/interrupt.h>
- #include <linux/init.h>
- #include <linux/pci.h>
- #include <linux/ide.h>
- #include <linux/dma-mapping.h>
+ 	int ret;
  
--#include <asm/io.h>
--#include <asm/irq.h>
--
- struct pio_clocks
- {
- 	int address;
-@@ -69,9 +59,8 @@ static struct pio_clocks cs5520_pio_clocks[]={
- static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct pci_dev *pdev = hwif->pci_dev;
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
- 	int controller = drive->dn > 1 ? 1 : 0;
--	u8 reg;
+-	ret = down_interruptible(&dd->ipath_eep_sem);
++	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
+ 	if (!ret) {
+ 		ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
+-		up(&dd->ipath_eep_sem);
++		mutex_unlock(&dd->ipath_eep_lock);
+ 	}
  
- 	/* FIXME: if DMA = 1 do we need to set the DMA bit here ? */
+ 	return ret;
+@@ -574,7 +574,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
+ 	struct ipath_devdata *dd0 = ipath_lookup(0);
  
-@@ -91,11 +80,6 @@ static void cs5520_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	pci_write_config_byte(pdev, 0x66 + 4*controller + (drive->dn&1),
- 		(cs5520_pio_clocks[pio].recovery << 4) |
- 		(cs5520_pio_clocks[pio].assert));
--		
--	/* Set the DMA enable/disable flag */
--	reg = inb(hwif->dma_base + 0x02 + 8*controller);
--	reg |= 1<<((drive->dn&1)+5);
--	outb(reg, hwif->dma_base + 0x02 + 8*controller);
- }
+ 	if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) {
+-		u8 *bguid, oguid;
++		u8 oguid;
+ 		dd->ipath_guid = dd0->ipath_guid;
+ 		bguid = (u8 *) & dd->ipath_guid;
  
- static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
-@@ -109,13 +93,14 @@ static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
-  *	We wrap the DMA activate to set the vdma flag. This is needed
-  *	so that the IDE DMA layer issues PIO not DMA commands over the
-  *	DMA channel
-+ *
-+ *	ATAPI is harder so disable it for now using IDE_HFLAG_NO_ATAPI_DMA
-  */
-- 
--static int cs5520_dma_on(ide_drive_t *drive)
-+
-+static void cs5520_dma_host_set(ide_drive_t *drive, int on)
- {
--	/* ATAPI is harder so leave it for now */
--	drive->vdma = 1;
--	return 0;
-+	drive->vdma = on;
-+	ide_dma_host_set(drive, on);
- }
+@@ -616,9 +616,9 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
+ 		goto bail;
+ 	}
  
- static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
-@@ -126,7 +111,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
- 	if (hwif->dma_base == 0)
- 		return;
+-	down(&dd->ipath_eep_sem);
++	mutex_lock(&dd->ipath_eep_lock);
+ 	eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
+-	up(&dd->ipath_eep_sem);
++	mutex_unlock(&dd->ipath_eep_lock);
  
--	hwif->ide_dma_on = &cs5520_dma_on;
-+	hwif->dma_host_set = &cs5520_dma_host_set;
- }
+ 	if (eep_stat) {
+ 		ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
+@@ -674,7 +674,6 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
+ 		 * elsewhere for backward-compatibility.
+ 		 */
+ 		char *snp = dd->ipath_serial;
+-		int len;
+ 		memcpy(snp, ifp->if_sprefix, sizeof ifp->if_sprefix);
+ 		snp[sizeof ifp->if_sprefix] = '\0';
+ 		len = strlen(snp);
+@@ -764,14 +763,14 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
+ 	/* Grab semaphore and read current EEPROM. If we get an
+ 	 * error, let go, but if not, keep it until we finish write.
+ 	 */
+-	ret = down_interruptible(&dd->ipath_eep_sem);
++	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
+ 	if (ret) {
+ 		ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
+ 		goto free_bail;
+ 	}
+ 	ret = ipath_eeprom_internal_read(dd, 0, buf, len);
+ 	if (ret) {
+-		up(&dd->ipath_eep_sem);
++		mutex_unlock(&dd->ipath_eep_lock);
+ 		ipath_dev_err(dd, "Unable read EEPROM for logging\n");
+ 		goto free_bail;
+ 	}
+@@ -779,7 +778,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
  
- #define DECLARE_CS_DEV(name_str)				\
-@@ -137,6 +122,7 @@ static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
- 				  IDE_HFLAG_CS5520 |		\
- 				  IDE_HFLAG_VDMA |		\
- 				  IDE_HFLAG_NO_ATAPI_DMA |	\
-+				  IDE_HFLAG_ABUSE_SET_DMA_MODE |\
- 				  IDE_HFLAG_BOOTABLE,		\
- 		.pio_mask	= ATA_PIO4,			\
+ 	csum = flash_csum(ifp, 0);
+ 	if (csum != ifp->if_csum) {
+-		up(&dd->ipath_eep_sem);
++		mutex_unlock(&dd->ipath_eep_lock);
+ 		ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
+ 				csum, ifp->if_csum);
+ 		ret = 1;
+@@ -849,7 +848,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
+ 		csum = flash_csum(ifp, 1);
+ 		ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
  	}
-@@ -160,8 +146,14 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
- 	ide_setup_pci_noise(dev, d);
+-	up(&dd->ipath_eep_sem);
++	mutex_unlock(&dd->ipath_eep_lock);
+ 	if (ret)
+ 		ipath_dev_err(dd, "Failed updating EEPROM\n");
  
- 	/* We must not grab the entire device, it has 'ISA' space in its
--	   BARS too and we will freak out other bits of the kernel */
--	if (pci_enable_device_bars(dev, 1<<2)) {
-+	 * BARS too and we will freak out other bits of the kernel
-+	 *
-+	 * pci_enable_device_bars() is going away. I replaced it with
-+	 * IO only enable for now but I'll need confirmation this is
-+	 * allright for that device. If not, it will need some kind of
-+	 * quirk. --BenH.
-+	 */
-+	if (pci_enable_device_io(dev)) {
- 		printk(KERN_WARNING "%s: Unable to enable 55x0.\n", d->name);
- 		return -ENODEV;
+diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+index 5de3243..7e025c8 100644
+--- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
++++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
+@@ -169,7 +169,7 @@ static int ipath_get_base_info(struct file *fp,
+ 		kinfo->spi_piocnt = dd->ipath_pbufsport;
+ 		kinfo->spi_piobufbase = (u64) pd->port_piobufs;
+ 		kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
+-			dd->ipath_palign * pd->port_port;
++			dd->ipath_ureg_align * pd->port_port;
+ 	} else if (master) {
+ 		kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
+ 				    (dd->ipath_pbufsport % subport_cnt);
+@@ -186,7 +186,7 @@ static int ipath_get_base_info(struct file *fp,
  	}
-@@ -178,7 +170,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic
+ 	if (shared) {
+ 		kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
+-			dd->ipath_palign * pd->port_port;
++			dd->ipath_ureg_align * pd->port_port;
+ 		kinfo->spi_port_rcvegrbuf = kinfo->spi_rcv_egrbufs;
+ 		kinfo->spi_port_rcvhdr_base = kinfo->spi_rcvhdr_base;
+ 		kinfo->spi_port_rcvhdr_tailaddr = kinfo->spi_rcvhdr_tailaddr;
+@@ -742,11 +742,12 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
+ 		 * updated and correct itself, even in the face of software
+ 		 * bugs.
+ 		 */
+-		*(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0;
+-		set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
++		if (pd->port_rcvhdrtail_kvaddr)
++			ipath_clear_rcvhdrtail(pd);
++		set_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ 			&dd->ipath_rcvctrl);
+ 	} else
+-		clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
++		clear_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ 			  &dd->ipath_rcvctrl);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
+@@ -881,7 +882,7 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
  
- 	ide_pci_setup_ports(dev, d, 14, &idx[0]);
+ 	egrcnt = dd->ipath_rcvegrcnt;
+ 	/* TID number offset for this port */
+-	egroff = pd->port_port * egrcnt;
++	egroff = (pd->port_port - 1) * egrcnt + dd->ipath_p0_rcvegrcnt;
+ 	egrsize = dd->ipath_rcvegrbufsize;
+ 	ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
+ 		   "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
+@@ -1049,11 +1050,6 @@ static int mmap_piobufs(struct vm_area_struct *vma,
  
--	ide_device_add(idx);
-+	ide_device_add(idx, d);
+ 	phys = dd->ipath_physaddr + piobufs;
  
- 	return 0;
+-	/*
+-	 * Don't mark this as non-cached, or we don't get the
+-	 * write combining behavior we want on the PIO buffers!
+-	 */
+-
+ #if defined(__powerpc__)
+ 	/* There isn't a generic way to specify writethrough mappings */
+ 	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
+@@ -1120,33 +1116,24 @@ bail:
  }
-diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
-index 5476903..941a134 100644
---- a/drivers/ide/pci/cs5530.c
-+++ b/drivers/ide/pci/cs5530.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/cs5530.c		Version 0.77	Sep 24 2007
-- *
-  * Copyright (C) 2000			Andre Hedrick <andre at linux-ide.org>
-  * Copyright (C) 2000			Mark Lord <mlord at pobox.com>
-  * Copyright (C) 2007			Bartlomiej Zolnierkiewicz
-@@ -17,18 +15,12 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
--#include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
-+
- #include <asm/io.h>
--#include <asm/irq.h>
  
  /*
-  * Here are the standard PIO mode 0-4 timings for each "format".
-@@ -116,8 +108,6 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
- 		case XFER_MW_DMA_0:	timings = 0x00077771; break;
- 		case XFER_MW_DMA_1:	timings = 0x00012121; break;
- 		case XFER_MW_DMA_2:	timings = 0x00002020; break;
--		default:
--			return;
- 	}
- 	basereg = CS5530_BASEREG(drive->hwif);
- 	reg = inl(basereg + 4);			/* get drive0 config register */
-diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
-index ddcbeba..d7b5ea9 100644
---- a/drivers/ide/pci/cs5535.c
-+++ b/drivers/ide/pci/cs5535.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/cs5535.c
-- *
-  * Copyright (C) 2004-2005 Advanced Micro Devices, Inc.
-  * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
-  *
-@@ -157,8 +155,9 @@ static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	cs5535_set_speed(drive, XFER_PIO_0 + pio);
- }
- 
--static u8 __devinit cs5535_cable_detect(struct pci_dev *dev)
-+static u8 __devinit cs5535_cable_detect(ide_hwif_t *hwif)
+- * ipath_file_vma_nopage - handle a VMA page fault.
++ * ipath_file_vma_fault - handle a VMA page fault.
+  */
+-static struct page *ipath_file_vma_nopage(struct vm_area_struct *vma,
+-					  unsigned long address, int *type)
++static int ipath_file_vma_fault(struct vm_area_struct *vma,
++					struct vm_fault *vmf)
  {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	u8 bit;
- 
- 	/* if a 80 wire cable was detected */
-@@ -180,17 +179,14 @@ static void __devinit init_hwif_cs5535(ide_hwif_t *hwif)
- 	hwif->set_pio_mode = &cs5535_set_pio_mode;
- 	hwif->set_dma_mode = &cs5535_set_dma_mode;
+-	unsigned long offset = address - vma->vm_start;
+-	struct page *page = NOPAGE_SIGBUS;
+-	void *pageptr;
++	struct page *page;
  
--	if (hwif->dma_base == 0)
--		return;
+-	/*
+-	 * Convert the vmalloc address into a struct page.
+-	 */
+-	pageptr = (void *)(offset + (vma->vm_pgoff << PAGE_SHIFT));
+-	page = vmalloc_to_page(pageptr);
++	page = vmalloc_to_page((void *)(vmf->pgoff << PAGE_SHIFT));
+ 	if (!page)
+-		goto out;
 -
--	hwif->cbl = cs5535_cable_detect(hwif->pci_dev);
-+	hwif->cable_detect = cs5535_cable_detect;
+-	/* Increment the reference count. */
++		return VM_FAULT_SIGBUS;
+ 	get_page(page);
+-	if (type)
+-		*type = VM_FAULT_MINOR;
+-out:
+-	return page;
++	vmf->page = page;
++
++	return 0;
  }
  
- static const struct ide_port_info cs5535_chipset __devinitdata = {
- 	.name		= "CS5535",
- 	.init_hwif	= init_hwif_cs5535,
- 	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE |
--			  IDE_HFLAG_BOOTABLE,
-+			  IDE_HFLAG_ABUSE_SET_DMA_MODE | IDE_HFLAG_BOOTABLE,
- 	.pio_mask	= ATA_PIO4,
- 	.mwdma_mask	= ATA_MWDMA2,
- 	.udma_mask	= ATA_UDMA4,
-diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c
-index 1cd4e9c..724cbac 100644
---- a/drivers/ide/pci/cy82c693.c
-+++ b/drivers/ide/pci/cy82c693.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/cy82c693.c		Version 0.42	Oct 23, 2007
-- *
-  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs at altavista.net), Maintainer
-  *  Copyright (C) 1998-2002 Andre Hedrick <andre at linux-ide.org>, Integrator
-  *
-@@ -47,7 +45,6 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/ide.h>
- #include <linux/init.h>
+ static struct vm_operations_struct ipath_file_vm_ops = {
+-	.nopage = ipath_file_vma_nopage,
++	.fault = ipath_file_vma_fault,
+ };
  
-@@ -176,17 +173,12 @@ static void compute_clocks (u8 pio, pio_clocks_t *p_pclk)
-  * set DMA mode a specific channel for CY82C693
-  */
+ static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
+@@ -1284,7 +1271,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
+ 		goto bail;
+ 	}
  
--static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
-+static void cy82c693_set_dma_mode(ide_drive_t *drive, const u8 mode)
- {
--	u8 index = 0, data = 0;
-+	ide_hwif_t *hwif = drive->hwif;
-+	u8 single = (mode & 0x10) >> 4, index = 0, data = 0;
+-	ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
++	ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port;
+ 	if (!pd->port_subport_cnt) {
+ 		/* port is not shared */
+ 		piocnt = dd->ipath_pbufsport;
+@@ -1400,7 +1387,10 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
+ 	pollflag = ipath_poll_hdrqfull(pd);
  
--	if (mode>2)	/* make sure we set a valid mode */
--		mode = 2;
--			   
--	if (mode > drive->id->tDMA)  /* to be absolutly sure we have a valid mode */
--		mode = drive->id->tDMA;
--	
--	index = (HWIF(drive)->channel==0) ? CY82_INDEX_CHANNEL0 : CY82_INDEX_CHANNEL1;
-+	index = hwif->channel ? CY82_INDEX_CHANNEL1 : CY82_INDEX_CHANNEL0;
+ 	head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
+-	tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
++	if (pd->port_rcvhdrtail_kvaddr)
++		tail = ipath_get_rcvhdrtail(pd);
++	else
++		tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
  
- #if CY82C693_DEBUG_LOGS
- 	/* for debug let's show the previous values */
-@@ -199,7 +191,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
- 		(data&0x3), ((data>>2)&1));
- #endif /* CY82C693_DEBUG_LOGS */
+ 	if (head != tail)
+ 		pollflag |= POLLIN | POLLRDNORM;
+@@ -1410,7 +1400,7 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
+ 		/* flush waiting flag so we don't miss an event */
+ 		wmb();
  
--	data = (u8)mode|(u8)(single<<2);
-+	data = (mode & 3) | (single << 2);
+-		set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
++		set_bit(pd->port_port + dd->ipath_r_intravail_shift,
+ 			&dd->ipath_rcvctrl);
  
- 	outb(index, CY82_INDEX_PORT);
- 	outb(data, CY82_DATA_PORT);
-@@ -207,7 +199,7 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
- #if CY82C693_DEBUG_INFO
- 	printk(KERN_INFO "%s (ch=%d, dev=%d): set DMA mode to %d (single=%d)\n",
- 		drive->name, HWIF(drive)->channel, drive->select.b.unit,
--		mode, single);
-+		mode & 3, single);
- #endif /* CY82C693_DEBUG_INFO */
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+@@ -1790,6 +1780,7 @@ static int find_shared_port(struct file *fp,
+ 			}
+ 			port_fp(fp) = pd;
+ 			subport_fp(fp) = pd->port_cnt++;
++			pd->port_subpid[subport_fp(fp)] = current->pid;
+ 			tidcursor_fp(fp) = 0;
+ 			pd->active_slaves |= 1 << subport_fp(fp);
+ 			ipath_cdbg(PROC,
+@@ -1920,8 +1911,7 @@ static int ipath_do_user_init(struct file *fp,
+ 	 */
+ 	head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
+ 	ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
+-	dd->ipath_lastegrheads[pd->port_port] = -1;
+-	dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
++	pd->port_lastrcvhdrqtail = -1;
+ 	ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n",
+ 		pd->port_port, head32);
+ 	pd->port_tidcursor = 0;	/* start at beginning after open */
+@@ -1941,11 +1931,13 @@ static int ipath_do_user_init(struct file *fp,
+ 	 * We explictly set the in-memory copy to 0 beforehand, so we don't
+ 	 * have to wait to be sure the DMA update has happened.
+ 	 */
+-	*(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL;
+-	set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
++	if (pd->port_rcvhdrtail_kvaddr)
++		ipath_clear_rcvhdrtail(pd);
++	set_bit(dd->ipath_r_portenable_shift + pd->port_port,
+ 		&dd->ipath_rcvctrl);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+-			 dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
++			dd->ipath_rcvctrl &
++			~(1ULL << dd->ipath_r_tailupd_shift));
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
+ 	/* Notify any waiting slaves */
+@@ -2022,6 +2014,7 @@ static int ipath_close(struct inode *in, struct file *fp)
+ 		 * the slave(s) don't wait for receive data forever.
+ 		 */
+ 		pd->active_slaves &= ~(1 << fd->subport);
++		pd->port_subpid[fd->subport] = 0;
+ 		mutex_unlock(&ipath_mutex);
+ 		goto bail;
+ 	}
+@@ -2054,9 +2047,9 @@ static int ipath_close(struct inode *in, struct file *fp)
+ 	if (dd->ipath_kregbase) {
+ 		int i;
+ 		/* atomically clear receive enable port and intr avail. */
+-		clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
++		clear_bit(dd->ipath_r_portenable_shift + port,
+ 			  &dd->ipath_rcvctrl);
+-		clear_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
++		clear_bit(pd->port_port + dd->ipath_r_intravail_shift,
+ 			  &dd->ipath_rcvctrl);
+ 		ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl,
+ 			dd->ipath_rcvctrl);
+@@ -2149,11 +2142,15 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
  
- 	/* 
-@@ -230,43 +222,10 @@ static void cy82c693_dma_enable (ide_drive_t *drive, int mode, int single)
- #endif /* CY82C693_DEBUG_INFO */
+ static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
+ {
+-	u64 reg = dd->ipath_sendctrl;
++	unsigned long flags;
+ 
+-	clear_bit(IPATH_S_PIOBUFAVAILUPD, &reg);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, reg);
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
++		dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ 
+ 	return 0;
  }
+@@ -2227,6 +2224,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ 		dest = &cmd.cmd.poll_type;
+ 		src = &ucmd->cmd.poll_type;
+ 		break;
++	case IPATH_CMD_ARMLAUNCH_CTRL:
++		copy = sizeof(cmd.cmd.armlaunch_ctrl);
++		dest = &cmd.cmd.armlaunch_ctrl;
++		src = &ucmd->cmd.armlaunch_ctrl;
++		break;
+ 	default:
+ 		ret = -EINVAL;
+ 		goto bail;
+@@ -2302,6 +2304,12 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
+ 	case IPATH_CMD_POLL_TYPE:
+ 		pd->poll_type = cmd.cmd.poll_type;
+ 		break;
++	case IPATH_CMD_ARMLAUNCH_CTRL:
++		if (cmd.cmd.armlaunch_ctrl)
++			ipath_enable_armlaunch(pd->port_dd);
++		else
++			ipath_disable_armlaunch(pd->port_dd);
++		break;
+ 	}
  
--/* 
-- * used to set DMA mode for CY82C693 (single and multi modes)
-- */
--static int cy82c693_ide_dma_on (ide_drive_t *drive)
--{
--	struct hd_driveid *id = drive->id;
--
--#if CY82C693_DEBUG_INFO
--	printk (KERN_INFO "dma_on: %s\n", drive->name);
--#endif /* CY82C693_DEBUG_INFO */
--
--	if (id != NULL) {		
--		/* Enable DMA on any drive that has DMA
--		 * (multi or single) enabled
--		 */
--		if (id->field_valid & 2) {	/* regular DMA */
--			int mmode, smode;
--
--			mmode = id->dma_mword & (id->dma_mword >> 8);
--			smode = id->dma_1word & (id->dma_1word >> 8);
--			       		      
--			if (mmode != 0) {
--				/* enable multi */
--				cy82c693_dma_enable(drive, (mmode >> 1), 0);
--			} else if (smode != 0) {
--				/* enable single */
--				cy82c693_dma_enable(drive, (smode >> 1), 1);
--			}
--		}
--	}
--        return __ide_dma_on(drive);
--}
+ 	if (ret >= 0)
+diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
+index 262c25d..23faba9 100644
+--- a/drivers/infiniband/hw/ipath/ipath_fs.c
++++ b/drivers/infiniband/hw/ipath/ipath_fs.c
+@@ -108,21 +108,16 @@ static const struct file_operations atomic_stats_ops = {
+ 	.read = atomic_stats_read,
+ };
+ 
+-#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64)
 -
- static void cy82c693_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ static ssize_t atomic_counters_read(struct file *file, char __user *buf,
+ 				    size_t count, loff_t *ppos)
  {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	pio_clocks_t pclk;
- 	unsigned int addrCtrl;
+-	u64 counters[NUM_COUNTERS];
+-	u16 i;
++	struct infinipath_counters counters;
+ 	struct ipath_devdata *dd;
  
-@@ -429,18 +388,15 @@ static unsigned int __devinit init_chipset_cy82c693(struct pci_dev *dev, const c
- static void __devinit init_hwif_cy82c693(ide_hwif_t *hwif)
- {
- 	hwif->set_pio_mode = &cy82c693_set_pio_mode;
--
--	if (hwif->dma_base == 0)
--		return;
+ 	dd = file->f_path.dentry->d_inode->i_private;
++	dd->ipath_f_read_counters(dd, &counters);
+ 
+-	for (i = 0; i < NUM_COUNTERS; i++)
+-		counters[i] = ipath_snap_cntr(dd, i);
 -
--	hwif->ide_dma_on = &cy82c693_ide_dma_on;
-+	hwif->set_dma_mode = &cy82c693_set_dma_mode;
+-	return simple_read_from_buffer(buf, count, ppos, counters,
++	return simple_read_from_buffer(buf, count, ppos, &counters,
+ 				       sizeof counters);
  }
  
- static void __devinit init_iops_cy82c693(ide_hwif_t *hwif)
- {
- 	static ide_hwif_t *primary;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
+@@ -243,8 +238,7 @@ static int create_device_files(struct super_block *sb,
  
--	if (PCI_FUNC(hwif->pci_dev->devfn) == 1)
-+	if (PCI_FUNC(dev->devfn) == 1)
- 		primary = hwif;
- 	else {
- 		hwif->mate = primary;
-@@ -454,11 +410,11 @@ static const struct ide_port_info cy82c693_chipset __devinitdata = {
- 	.init_iops	= init_iops_cy82c693,
- 	.init_hwif	= init_hwif_cy82c693,
- 	.chipset	= ide_cy82c693,
--	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-+	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_CY82C693 |
- 			  IDE_HFLAG_BOOTABLE,
- 	.pio_mask	= ATA_PIO4,
--	.swdma_mask	= ATA_SWDMA2_ONLY,
--	.mwdma_mask	= ATA_MWDMA2_ONLY,
-+	.swdma_mask	= ATA_SWDMA2,
-+	.mwdma_mask	= ATA_MWDMA2,
+ 	snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
+ 	ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
+-			  (struct file_operations *) &simple_dir_operations,
+-			  dd);
++			  &simple_dir_operations, dd);
+ 	if (ret) {
+ 		printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
+ 		goto bail;
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+index ddbebe4..9e2ced3 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
+@@ -148,10 +148,57 @@ struct _infinipath_do_not_use_kernel_regs {
+ 	unsigned long long ReservedSW2[4];
  };
  
- static int __devinit cy82c693_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-diff --git a/drivers/ide/pci/delkin_cb.c b/drivers/ide/pci/delkin_cb.c
-index 8382908..3f9cd64 100644
---- a/drivers/ide/pci/delkin_cb.c
-+++ b/drivers/ide/pci/delkin_cb.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/delkin_cb.c
-- *
-  *  Created 20 Oct 2004 by Mark Lord
-  *
-  *  Basic support for Delkin/ASKA/Workbit Cardbus CompactFlash adapter
-@@ -18,15 +16,14 @@
-  *  License.  See the file COPYING in the main directory of this archive for
-  *  more details.
-  */
--#include <linux/autoconf.h>
-+
- #include <linux/types.h>
- #include <linux/module.h>
--#include <linux/mm.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- #include <linux/pci.h>
+-#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+-    _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
++struct _infinipath_do_not_use_counters {
++	__u64 LBIntCnt;
++	__u64 LBFlowStallCnt;
++	__u64 Reserved1;
++	__u64 TxUnsupVLErrCnt;
++	__u64 TxDataPktCnt;
++	__u64 TxFlowPktCnt;
++	__u64 TxDwordCnt;
++	__u64 TxLenErrCnt;
++	__u64 TxMaxMinLenErrCnt;
++	__u64 TxUnderrunCnt;
++	__u64 TxFlowStallCnt;
++	__u64 TxDroppedPktCnt;
++	__u64 RxDroppedPktCnt;
++	__u64 RxDataPktCnt;
++	__u64 RxFlowPktCnt;
++	__u64 RxDwordCnt;
++	__u64 RxLenErrCnt;
++	__u64 RxMaxMinLenErrCnt;
++	__u64 RxICRCErrCnt;
++	__u64 RxVCRCErrCnt;
++	__u64 RxFlowCtrlErrCnt;
++	__u64 RxBadFormatCnt;
++	__u64 RxLinkProblemCnt;
++	__u64 RxEBPCnt;
++	__u64 RxLPCRCErrCnt;
++	__u64 RxBufOvflCnt;
++	__u64 RxTIDFullErrCnt;
++	__u64 RxTIDValidErrCnt;
++	__u64 RxPKeyMismatchCnt;
++	__u64 RxP0HdrEgrOvflCnt;
++	__u64 RxP1HdrEgrOvflCnt;
++	__u64 RxP2HdrEgrOvflCnt;
++	__u64 RxP3HdrEgrOvflCnt;
++	__u64 RxP4HdrEgrOvflCnt;
++	__u64 RxP5HdrEgrOvflCnt;
++	__u64 RxP6HdrEgrOvflCnt;
++	__u64 RxP7HdrEgrOvflCnt;
++	__u64 RxP8HdrEgrOvflCnt;
++	__u64 Reserved6;
++	__u64 Reserved7;
++	__u64 IBStatusChangeCnt;
++	__u64 IBLinkErrRecoveryCnt;
++	__u64 IBLinkDownedCnt;
++	__u64 IBSymbolErrCnt;
++};
 +
- #include <asm/io.h>
- 
- /*
-@@ -54,6 +51,7 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
- 	ide_hwif_t *hwif = NULL;
- 	ide_drive_t *drive;
- 	int i, rc;
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++#define IPATH_KREG_OFFSET(field) (offsetof( \
++	struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+ #define IPATH_CREG_OFFSET(field) (offsetof( \
+-    struct infinipath_counters, field) / sizeof(u64))
++	struct _infinipath_do_not_use_counters, field) / sizeof(u64))
  
- 	rc = pci_enable_device(dev);
- 	if (rc) {
-@@ -80,20 +78,40 @@ delkin_cb_probe (struct pci_dev *dev, const struct pci_device_id *id)
- 	hw.irq = dev->irq;
- 	hw.chipset = ide_pci;		/* this enables IRQ sharing */
+ static const struct ipath_kregs ipath_ht_kregs = {
+ 	.kr_control = IPATH_KREG_OFFSET(Control),
+@@ -282,6 +329,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
+ #define INFINIPATH_HWE_HTAPLL_RFSLIP        0x1000000000000000ULL
+ #define INFINIPATH_HWE_SERDESPLLFAILED      0x2000000000000000ULL
  
--	rc = ide_register_hw(&hw, &ide_undecoded_slave, 0, &hwif);
--	if (rc < 0) {
--		printk(KERN_ERR "delkin_cb: ide_register_hw failed (%d)\n", rc);
--		pci_disable_device(dev);
--		return -ENODEV;
--	}
-+	hwif = ide_deprecated_find_port(hw.io_ports[IDE_DATA_OFFSET]);
-+	if (hwif == NULL)
-+		goto out_disable;
-+
-+	i = hwif->index;
-+
-+	if (hwif->present)
-+		ide_unregister(i, 0, 0);
-+	else if (!hwif->hold)
-+		ide_init_port_data(hwif, i);
-+
-+	ide_init_port_hw(hwif, &hw);
-+	hwif->quirkproc = &ide_undecoded_slave;
-+
-+	idx[0] = i;
++#define IBA6110_IBCS_LINKTRAININGSTATE_MASK 0xf
++#define IBA6110_IBCS_LINKSTATE_SHIFT 4
 +
-+	ide_device_add(idx, NULL);
+ /* kr_extstatus bits */
+ #define INFINIPATH_EXTS_FREQSEL 0x2
+ #define INFINIPATH_EXTS_SERDESSEL 0x4
+@@ -296,6 +346,12 @@ static const struct ipath_cregs ipath_ht_cregs = {
+ #define INFINIPATH_RT_BUFSIZE_MASK 0x3FFFULL
+ #define INFINIPATH_RT_BUFSIZE_SHIFT 48
+ 
++#define INFINIPATH_R_INTRAVAIL_SHIFT 16
++#define INFINIPATH_R_TAILUPD_SHIFT 31
 +
-+	if (!hwif->present)
-+		goto out_disable;
++/* kr_xgxsconfig bits */
++#define INFINIPATH_XGXS_RESET          0x7ULL
 +
- 	pci_set_drvdata(dev, hwif);
--	hwif->pci_dev = dev;
-+	hwif->dev = &dev->dev;
- 	drive = &hwif->drives[0];
- 	if (drive->present) {
- 		drive->io_32bit = 1;
- 		drive->unmask   = 1;
+ /*
+  * masks and bits that are different in different chips, or present only
+  * in one
+@@ -652,7 +708,6 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+ 			      "with ID %u\n", boardrev);
+ 		snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u",
+ 			 boardrev);
+-		ret = 1;
+ 		break;
  	}
- 	return 0;
+ 	if (n)
+@@ -686,6 +741,13 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
+ 			      dd->ipath_htspeed);
+ 	ret = 0;
+ 
++	/*
++	 * set here, not in ipath_init_*_funcs because we have to do
++	 * it after we can read chip registers.
++	 */
++	dd->ipath_ureg_align =
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
 +
-+out_disable:
-+	printk(KERN_ERR "delkin_cb: no IDE devices found\n");
-+	pci_disable_device(dev);
-+	return -ENODEV;
+ bail:
+ 	return ret;
  }
+@@ -969,7 +1031,8 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
+ 	do {
+ 		u8 cap_type;
  
- static void
-@@ -102,7 +120,8 @@ delkin_cb_remove (struct pci_dev *dev)
- 	ide_hwif_t *hwif = pci_get_drvdata(dev);
+-		/* the HT capability type byte is 3 bytes after the
++		/*
++		 * The HT capability type byte is 3 bytes after the
+ 		 * capability byte.
+ 		 */
+ 		if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {
+@@ -982,6 +1045,8 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
+ 	} while ((pos = pci_find_next_capability(pdev, pos,
+ 						 PCI_CAP_ID_HT)));
  
- 	if (hwif)
--		ide_unregister(hwif->index);
-+		ide_unregister(hwif->index, 0, 0);
++	dd->ipath_flags |= IPATH_SWAP_PIOBUFS;
 +
- 	pci_disable_device(dev);
+ bail:
+ 	return ret;
  }
+@@ -1074,11 +1139,55 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
  
-diff --git a/drivers/ide/pci/generic.c b/drivers/ide/pci/generic.c
-index 0688569..9262a91 100644
---- a/drivers/ide/pci/generic.c
-+++ b/drivers/ide/pci/generic.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/generic.c	Version 0.11	December 30, 2002
-- *
-  *  Copyright (C) 2001-2002	Andre Hedrick <andre at linux-ide.org>
-  *  Portions (C) Copyright 2002  Red Hat Inc <alan at redhat.com>
-  *
-@@ -24,18 +22,11 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/pci.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- 
--#include <asm/io.h>
--
- static int ide_generic_all;		/* Set to claim all devices */
- 
- /*
-@@ -104,7 +95,8 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = {
- 
- 	{	/* 14 */
- 		.name		= "Revolution",
--		.host_flags	= IDE_HFLAG_TRUST_BIOS_FOR_DMA |
-+		.host_flags	= IDE_HFLAG_CLEAR_SIMPLEX |
-+				  IDE_HFLAG_TRUST_BIOS_FOR_DMA |
- 				  IDE_HFLAG_OFF_BOARD,
- 		.swdma_mask	= ATA_SWDMA2,
- 		.mwdma_mask	= ATA_MWDMA2,
-diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
-index ae6307f..9f01da4 100644
---- a/drivers/ide/pci/hpt34x.c
-+++ b/drivers/ide/pci/hpt34x.c
-@@ -1,7 +1,6 @@
- /*
-- * linux/drivers/ide/pci/hpt34x.c		Version 0.40	Sept 10, 2002
-- *
-  * Copyright (C) 1998-2000	Andre Hedrick <andre at linux-ide.org>
-+ *
-  * May be copied or modified under the terms of the GNU General Public License
-  *
-  *
-@@ -27,25 +26,18 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
- #include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
- 
--#include <asm/io.h>
--#include <asm/irq.h>
--
- #define HPT343_DEBUG_DRIVE_INFO		0
- 
- static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
+ static void ipath_init_ht_variables(struct ipath_devdata *dd)
  {
--	struct pci_dev *dev	= HWIF(drive)->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
- 	u8			hi_speed, lo_speed;
- 
-@@ -129,14 +121,19 @@ static void __devinit init_hwif_hpt34x(ide_hwif_t *hwif)
- 	hwif->set_dma_mode = &hpt34x_set_mode;
- }
- 
-+#define IDE_HFLAGS_HPT34X \
-+	(IDE_HFLAG_NO_ATAPI_DMA | \
-+	 IDE_HFLAG_NO_DSC | \
-+	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
-+	 IDE_HFLAG_NO_AUTODMA)
++	/*
++	 * setup the register offsets, since they are different for each
++	 * chip
++	 */
++	dd->ipath_kregs = &ipath_ht_kregs;
++	dd->ipath_cregs = &ipath_ht_cregs;
 +
- static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
- 	{ /* 0 */
- 		.name		= "HPT343",
- 		.init_chipset	= init_chipset_hpt34x,
- 		.init_hwif	= init_hwif_hpt34x,
- 		.extra		= 16,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
--				  IDE_HFLAG_NO_AUTODMA,
-+		.host_flags	= IDE_HFLAGS_HPT34X,
- 		.pio_mask	= ATA_PIO5,
- 	},
- 	{ /* 1 */
-@@ -144,9 +141,7 @@ static const struct ide_port_info hpt34x_chipsets[] __devinitdata = {
- 		.init_chipset	= init_chipset_hpt34x,
- 		.init_hwif	= init_hwif_hpt34x,
- 		.extra		= 16,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA |
--				  IDE_HFLAG_NO_AUTODMA |
--				  IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT34X | IDE_HFLAG_OFF_BOARD,
- 		.pio_mask	= ATA_PIO5,
- #ifdef CONFIG_HPT34X_AUTODMA
- 		.swdma_mask	= ATA_SWDMA2,
-diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
-index 9fce25b..d0f7bb8 100644
---- a/drivers/ide/pci/hpt366.c
-+++ b/drivers/ide/pci/hpt366.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/hpt366.c		Version 1.22	Dec 4, 2007
-- *
-  * Copyright (C) 1999-2003		Andre Hedrick <andre at linux-ide.org>
-  * Portions Copyright (C) 2001	        Sun Microsystems, Inc.
-  * Portions Copyright (C) 2003		Red Hat Inc
-@@ -88,7 +86,7 @@
-  * - rename all the register related variables consistently
-  * - move all the interrupt twiddling code from the speedproc handlers into
-  *   init_hwif_hpt366(), also grouping all the DMA related code together there
-- * - merge two HPT37x speedproc handlers, fix the PIO timing register mask and
-+ * - merge HPT36x/HPT37x speedproc handlers, fix PIO timing register mask and
-  *   separate the UltraDMA and MWDMA masks there to avoid changing PIO timings
-  *   when setting an UltraDMA mode
-  * - fix hpt3xx_tune_drive() to set the PIO mode requested, not always select
-@@ -123,12 +121,8 @@
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
- #include <linux/blkdev.h>
- #include <linux/hdreg.h>
--
- #include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
-@@ -136,7 +130,6 @@
- 
- #include <asm/uaccess.h>
- #include <asm/io.h>
--#include <asm/irq.h>
- 
- /* various tuning parameters */
- #define HPT_RESET_STATE_ENGINE
-@@ -458,6 +451,13 @@ enum ata_clock {
- 	NUM_ATA_CLOCKS
- };
+ 	dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
+ 	dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
+ 	dd->ipath_gpio_sda = IPATH_GPIO_SDA;
+ 	dd->ipath_gpio_scl = IPATH_GPIO_SCL;
  
-+struct hpt_timings {
-+	u32 pio_mask;
-+	u32 dma_mask;
-+	u32 ultra_mask;
-+	u32 *clock_table[NUM_ATA_CLOCKS];
-+};
++	/*
++	 * Fill in data for field-values that change in newer chips.
++	 * We dynamically specify only the mask for LINKTRAININGSTATE
++	 * and only the shift for LINKSTATE, as they are the only ones
++	 * that change.  Also precalculate the 3 link states of interest
++	 * and the combined mask.
++	 */
++	dd->ibcs_ls_shift = IBA6110_IBCS_LINKSTATE_SHIFT;
++	dd->ibcs_lts_mask = IBA6110_IBCS_LINKTRAININGSTATE_MASK;
++	dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
++		dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
++	dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
++	dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
++	dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
 +
- /*
-  *	Hold all the HighPoint chip information in one place.
-  */
-@@ -468,7 +468,8 @@ struct hpt_info {
- 	u8 udma_mask;		/* Allowed UltraDMA modes mask. */
- 	u8 dpll_clk;		/* DPLL clock in MHz */
- 	u8 pci_clk;		/* PCI  clock in MHz */
--	u32 **settings; 	/* Chipset settings table */
-+	struct hpt_timings *timings; /* Chipset timing data */
-+	u8 clock;		/* ATA clock selected */
- };
- 
- /* Supported HighPoint chips */
-@@ -486,20 +487,30 @@ enum {
- 	HPT371N
- };
- 
--static u32 *hpt36x_settings[NUM_ATA_CLOCKS] = {
--	twenty_five_base_hpt36x,
--	thirty_three_base_hpt36x,
--	forty_base_hpt36x,
--	NULL,
--	NULL
-+static struct hpt_timings hpt36x_timings = {
-+	.pio_mask	= 0xc1f8ffff,
-+	.dma_mask	= 0x303800ff,
-+	.ultra_mask	= 0x30070000,
-+	.clock_table	= {
-+		[ATA_CLOCK_25MHZ] = twenty_five_base_hpt36x,
-+		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt36x,
-+		[ATA_CLOCK_40MHZ] = forty_base_hpt36x,
-+		[ATA_CLOCK_50MHZ] = NULL,
-+		[ATA_CLOCK_66MHZ] = NULL
-+	}
- };
- 
--static u32 *hpt37x_settings[NUM_ATA_CLOCKS] = {
--	NULL,
--	thirty_three_base_hpt37x,
--	NULL,
--	fifty_base_hpt37x,
--	sixty_six_base_hpt37x
-+static struct hpt_timings hpt37x_timings = {
-+	.pio_mask	= 0xcfc3ffff,
-+	.dma_mask	= 0x31c001ff,
-+	.ultra_mask	= 0x303c0000,
-+	.clock_table	= {
-+		[ATA_CLOCK_25MHZ] = NULL,
-+		[ATA_CLOCK_33MHZ] = thirty_three_base_hpt37x,
-+		[ATA_CLOCK_40MHZ] = NULL,
-+		[ATA_CLOCK_50MHZ] = fifty_base_hpt37x,
-+		[ATA_CLOCK_66MHZ] = sixty_six_base_hpt37x
-+	}
- };
- 
- static const struct hpt_info hpt36x __devinitdata = {
-@@ -507,7 +518,7 @@ static const struct hpt_info hpt36x __devinitdata = {
- 	.chip_type	= HPT36x,
- 	.udma_mask	= HPT366_ALLOW_ATA66_3 ? (HPT366_ALLOW_ATA66_4 ? ATA_UDMA4 : ATA_UDMA3) : ATA_UDMA2,
- 	.dpll_clk	= 0,	/* no DPLL */
--	.settings	= hpt36x_settings
-+	.timings	= &hpt36x_timings
- };
- 
- static const struct hpt_info hpt370 __devinitdata = {
-@@ -515,7 +526,7 @@ static const struct hpt_info hpt370 __devinitdata = {
- 	.chip_type	= HPT370,
- 	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
- 	.dpll_clk	= 48,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt370a __devinitdata = {
-@@ -523,7 +534,7 @@ static const struct hpt_info hpt370a __devinitdata = {
- 	.chip_type	= HPT370A,
- 	.udma_mask	= HPT370_ALLOW_ATA100_5 ? ATA_UDMA5 : ATA_UDMA4,
- 	.dpll_clk	= 48,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt374 __devinitdata = {
-@@ -531,7 +542,7 @@ static const struct hpt_info hpt374 __devinitdata = {
- 	.chip_type	= HPT374,
- 	.udma_mask	= ATA_UDMA5,
- 	.dpll_clk	= 48,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt372 __devinitdata = {
-@@ -539,7 +550,7 @@ static const struct hpt_info hpt372 __devinitdata = {
- 	.chip_type	= HPT372,
- 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 55,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt372a __devinitdata = {
-@@ -547,7 +558,7 @@ static const struct hpt_info hpt372a __devinitdata = {
- 	.chip_type	= HPT372A,
- 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 66,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt302 __devinitdata = {
-@@ -555,7 +566,7 @@ static const struct hpt_info hpt302 __devinitdata = {
- 	.chip_type	= HPT302,
- 	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 66,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt371 __devinitdata = {
-@@ -563,7 +574,7 @@ static const struct hpt_info hpt371 __devinitdata = {
- 	.chip_type	= HPT371,
- 	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 66,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt372n __devinitdata = {
-@@ -571,7 +582,7 @@ static const struct hpt_info hpt372n __devinitdata = {
- 	.chip_type	= HPT372N,
- 	.udma_mask	= HPT372_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 77,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
- 
- static const struct hpt_info hpt302n __devinitdata = {
-@@ -579,7 +590,7 @@ static const struct hpt_info hpt302n __devinitdata = {
- 	.chip_type	= HPT302N,
- 	.udma_mask	= HPT302_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 77,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
++	/*
++	 * Fill in data for ibcc field-values that change in newer chips.
++	 * We dynamically specify only the mask for LINKINITCMD
++	 * and only the shift for LINKCMD and MAXPKTLEN, as they are
++	 * the only ones that change.
++	 */
++	dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
++	dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
++	dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
++
++	/* Fill in shifts for RcvCtrl. */
++	dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
++	dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
++	dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT;
++	dd->ipath_r_portcfg_shift = 0; /* Not on IBA6110 */
++
+ 	dd->ipath_i_bitsextant =
+ 		(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
+ 		(INFINIPATH_I_RCVAVAIL_MASK <<
+@@ -1135,6 +1244,8 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
  
- static const struct hpt_info hpt371n __devinitdata = {
-@@ -587,7 +598,7 @@ static const struct hpt_info hpt371n __devinitdata = {
- 	.chip_type	= HPT371N,
- 	.udma_mask	= HPT371_ALLOW_ATA133_6 ? ATA_UDMA6 : ATA_UDMA5,
- 	.dpll_clk	= 77,
--	.settings	= hpt37x_settings
-+	.timings	= &hpt37x_timings
- };
+ 	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+ 	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
++	dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
++	dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
  
- static int check_in_drive_list(ide_drive_t *drive, const char **list)
-@@ -608,7 +619,8 @@ static int check_in_drive_list(ide_drive_t *drive, const char **list)
- static u8 hpt3xx_udma_filter(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-+	struct hpt_info *info	= pci_get_drvdata(dev);
- 	u8 mask 		= hwif->ultra_mask;
+ 	/*
+ 	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+@@ -1148,9 +1259,17 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
+ 		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+ 		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
  
- 	switch (info->chip_type) {
-@@ -647,7 +659,8 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive)
- static u8 hpt3xx_mdma_filter(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct hpt_info *info	= pci_get_drvdata(hwif->pci_dev);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-+	struct hpt_info *info	= pci_get_drvdata(dev);
+-	dd->ipath_eep_st_masks[2].errs_to_log =
+-		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
++	dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
  
- 	switch (info->chip_type) {
- 	case HPT372 :
-@@ -675,100 +688,56 @@ static u32 get_speed_setting(u8 speed, struct hpt_info *info)
- 	for (i = 0; i < ARRAY_SIZE(xfer_speeds) - 1; i++)
- 		if (xfer_speeds[i] == speed)
- 			break;
--	/*
--	 * NOTE: info->settings only points to the pointer
--	 * to the list of the actual register values
--	 */
--	return (*info->settings)[i];
++	dd->delay_mult = 2; /* SDR, 4X, can't change */
 +
-+	return info->timings->clock_table[info->clock][i];
++	dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
++	dd->ipath_link_speed_supported = IPATH_IB_SDR;
++	dd->ipath_link_width_enabled = IB_WIDTH_4X;
++	dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
++	/* these can't change for this chip, so set once */
++	dd->ipath_link_width_active = dd->ipath_link_width_enabled;
++	dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
  }
  
--static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed)
-+static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
- {
--	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev  *dev	= hwif->pci_dev;
-+	struct pci_dev  *dev	= to_pci_dev(drive->hwif->dev);
- 	struct hpt_info	*info	= pci_get_drvdata(dev);
--	u8  itr_addr		= drive->dn ? 0x44 : 0x40;
-+	struct hpt_timings *t	= info->timings;
-+	u8  itr_addr		= 0x40 + (drive->dn * 4);
- 	u32 old_itr		= 0;
--	u32 itr_mask, new_itr;
--
--	itr_mask = speed < XFER_MW_DMA_0 ? 0x30070000 :
--		  (speed < XFER_UDMA_0   ? 0xc0070000 : 0xc03800ff);
--
--	new_itr = get_speed_setting(speed, info);
-+	u32 new_itr		= get_speed_setting(speed, info);
-+	u32 itr_mask		= speed < XFER_MW_DMA_0 ? t->pio_mask :
-+				 (speed < XFER_UDMA_0   ? t->dma_mask :
-+							  t->ultra_mask);
+ /**
+@@ -1205,14 +1324,16 @@ static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
+ 	val &= ~INFINIPATH_HWE_HTCMISCERR4;
  
-+	pci_read_config_dword(dev, itr_addr, &old_itr);
-+	new_itr = (old_itr & ~itr_mask) | (new_itr & itr_mask);
  	/*
- 	 * Disable on-chip PIO FIFO/buffer (and PIO MST mode as well)
- 	 * to avoid problems handling I/O errors later
+-	 * PLL ignored because MDIO interface has a logic problem
+-	 * for reads, on Comstock and Ponderosa.  BRINGUP
++	 * PLL ignored because unused MDIO interface has a logic problem
  	 */
--	pci_read_config_dword(dev, itr_addr, &old_itr);
--	new_itr  = (new_itr & ~itr_mask) | (old_itr & itr_mask);
- 	new_itr &= ~0xc0000000;
- 
- 	pci_write_config_dword(dev, itr_addr, new_itr);
+ 	if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)
+ 		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+ 	dd->ipath_hwerrmask = val;
  }
  
--static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed)
--{
--	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev  *dev	= hwif->pci_dev;
--	struct hpt_info	*info	= pci_get_drvdata(dev);
--	u8  itr_addr		= 0x40 + (drive->dn * 4);
--	u32 old_itr		= 0;
--	u32 itr_mask, new_itr;
--
--	itr_mask = speed < XFER_MW_DMA_0 ? 0x303c0000 :
--		  (speed < XFER_UDMA_0   ? 0xc03c0000 : 0xc1c001ff);
--
--	new_itr = get_speed_setting(speed, info);
--
--	pci_read_config_dword(dev, itr_addr, &old_itr);
--	new_itr = (new_itr & ~itr_mask) | (old_itr & itr_mask);
--	
--	if (speed < XFER_MW_DMA_0)
--		new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
--	pci_write_config_dword(dev, itr_addr, new_itr);
--}
--
--static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
--{
--	ide_hwif_t *hwif	= HWIF(drive);
--	struct hpt_info	*info	= pci_get_drvdata(hwif->pci_dev);
--
--	if (info->chip_type >= HPT370)
--		hpt37x_set_mode(drive, speed);
--	else	/* hpt368: hpt_minimum_revision(dev, 2) */
--		hpt36x_set_mode(drive, speed);
--}
--
- static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
- 	hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
- }
++
++
++
+ /**
+  * ipath_ht_bringup_serdes - bring up the serdes
+  * @dd: the infinipath device
+@@ -1284,16 +1405,6 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
+ 	}
  
--static int hpt3xx_quirkproc(ide_drive_t *drive)
-+static void hpt3xx_quirkproc(ide_drive_t *drive)
- {
- 	struct hd_driveid *id	= drive->id;
- 	const  char **list	= quirk_drives;
+ 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+-	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+-	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+-		val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+-			 INFINIPATH_XGXS_MDIOADDR_SHIFT);
+-		/*
+-		 * we use address 3
+-		 */
+-		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+-		change = 1;
+-	}
+ 	if (val & INFINIPATH_XGXS_RESET) {
+ 		/* normally true after boot */
+ 		val &= ~INFINIPATH_XGXS_RESET;
+@@ -1329,21 +1440,6 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
+ 		   (unsigned long long)
+ 		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
  
- 	while (*list)
--		if (strstr(id->model, *list++))
--			return 1;
--	return 0;
--}
+-	if (!ipath_waitfor_mdio_cmdready(dd)) {
+-		ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio,
+-				 ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+-						IPATH_MDIO_CTRL_XGXS_REG_8,
+-						0));
+-		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+-					   IPATH_MDIO_DATAVALID, &val))
+-			ipath_dbg("Never got MDIO data for XGXS status "
+-				  "read\n");
+-		else
+-			ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+-				   "'bank' 31 %x\n", (u32) val);
+-	} else
+-		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
 -
--static void hpt3xx_intrproc(ide_drive_t *drive)
--{
--	if (drive->quirk_list)
--		return;
-+		if (strstr(id->model, *list++)) {
-+			drive->quirk_list = 1;
-+			return;
-+		}
+ 	return ret;		/* for now, say we always succeeded */
+ }
  
--	/* drives in the quirk_list may not like intr setups/cleanups */
--	outb(drive->ctl | 2, IDE_CONTROL_REG);
-+	drive->quirk_list = 0;
+@@ -1396,6 +1492,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
+ 			pa |= lenvalid | INFINIPATH_RT_VALID;
+ 		}
+ 	}
++
+ 	writeq(pa, tidptr);
  }
  
- static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev	*dev	= hwif->pci_dev;
-+	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
- 	struct hpt_info *info	= pci_get_drvdata(dev);
+@@ -1526,8 +1623,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
+ 	}
  
- 	if (drive->quirk_list) {
-@@ -800,7 +769,7 @@ static void hpt3xx_maskproc(ide_drive_t *drive, int mask)
-  */
- static void hpt366_dma_lost_irq(ide_drive_t *drive)
- {
--	struct pci_dev *dev = HWIF(drive)->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u8 mcr1 = 0, mcr3 = 0, scr1 = 0;
+ 	ipath_get_eeprom_info(dd);
+-	if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
+-		dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') {
++	if (dd->ipath_boardrev == 5) {
+ 		/*
+ 		 * Later production QHT7040 has same changes as QHT7140, so
+ 		 * can use GPIO interrupts.  They have serial #'s starting
+@@ -1602,6 +1698,210 @@ static void ipath_ht_free_irq(struct ipath_devdata *dd)
+ 	dd->ipath_intconfig = 0;
+ }
  
- 	pci_read_config_byte(dev, 0x50, &mcr1);
-@@ -816,18 +785,20 @@ static void hpt366_dma_lost_irq(ide_drive_t *drive)
- static void hpt370_clear_engine(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++static struct ipath_message_header *
++ipath_ht_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
++{
++	return (struct ipath_message_header *)
++		&rhf_addr[sizeof(u64) / sizeof(u32)];
++}
++
++static void ipath_ht_config_ports(struct ipath_devdata *dd, ushort cfgports)
++{
++	dd->ipath_portcnt =
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
++	dd->ipath_p0_rcvegrcnt =
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
++}
++
++static void ipath_ht_read_counters(struct ipath_devdata *dd,
++				   struct infinipath_counters *cntrs)
++{
++	cntrs->LBIntCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt));
++	cntrs->LBFlowStallCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt));
++	cntrs->TxSDmaDescCnt = 0;
++	cntrs->TxUnsupVLErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt));
++	cntrs->TxDataPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt));
++	cntrs->TxFlowPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt));
++	cntrs->TxDwordCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt));
++	cntrs->TxLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt));
++	cntrs->TxMaxMinLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt));
++	cntrs->TxUnderrunCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt));
++	cntrs->TxFlowStallCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt));
++	cntrs->TxDroppedPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt));
++	cntrs->RxDroppedPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt));
++	cntrs->RxDataPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt));
++	cntrs->RxFlowPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt));
++	cntrs->RxDwordCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt));
++	cntrs->RxLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt));
++	cntrs->RxMaxMinLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt));
++	cntrs->RxICRCErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt));
++	cntrs->RxVCRCErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt));
++	cntrs->RxFlowCtrlErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt));
++	cntrs->RxBadFormatCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt));
++	cntrs->RxLinkProblemCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt));
++	cntrs->RxEBPCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt));
++	cntrs->RxLPCRCErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt));
++	cntrs->RxBufOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt));
++	cntrs->RxTIDFullErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt));
++	cntrs->RxTIDValidErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt));
++	cntrs->RxPKeyMismatchCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt));
++	cntrs->RxP0HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt));
++	cntrs->RxP1HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt));
++	cntrs->RxP2HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt));
++	cntrs->RxP3HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt));
++	cntrs->RxP4HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt));
++	cntrs->RxP5HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP5HdrEgrOvflCnt));
++	cntrs->RxP6HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP6HdrEgrOvflCnt));
++	cntrs->RxP7HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP7HdrEgrOvflCnt));
++	cntrs->RxP8HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP8HdrEgrOvflCnt));
++	cntrs->RxP9HdrEgrOvflCnt = 0;
++	cntrs->RxP10HdrEgrOvflCnt = 0;
++	cntrs->RxP11HdrEgrOvflCnt = 0;
++	cntrs->RxP12HdrEgrOvflCnt = 0;
++	cntrs->RxP13HdrEgrOvflCnt = 0;
++	cntrs->RxP14HdrEgrOvflCnt = 0;
++	cntrs->RxP15HdrEgrOvflCnt = 0;
++	cntrs->RxP16HdrEgrOvflCnt = 0;
++	cntrs->IBStatusChangeCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt));
++	cntrs->IBLinkErrRecoveryCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt));
++	cntrs->IBLinkDownedCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt));
++	cntrs->IBSymbolErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt));
++	cntrs->RxVL15DroppedPktCnt = 0;
++	cntrs->RxOtherLocalPhyErrCnt = 0;
++	cntrs->PcieRetryBufDiagQwordCnt = 0;
++	cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs;
++	cntrs->LocalLinkIntegrityErrCnt =
++		(dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
++		dd->ipath_lli_errs : dd->ipath_lli_errors;
++	cntrs->RxVlErrCnt = 0;
++	cntrs->RxDlidFltrCnt = 0;
++}
++
++
++/* no interrupt fallback for these chips */
++static int ipath_ht_nointr_fallback(struct ipath_devdata *dd)
++{
++	return 0;
++}
++
++
++/*
++ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
++ * than resetting the IBC or external link state, and useful in some
++ * cases to cause some retraining.  To do this right, we reset IBC
++ * as well.
++ */
++static void ipath_ht_xgxs_reset(struct ipath_devdata *dd)
++{
++	u64 val, prev_val;
++
++	prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++	val = prev_val | INFINIPATH_XGXS_RESET;
++	prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++			 dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++			 dd->ipath_control);
++}
++
++
++static int ipath_ht_get_ib_cfg(struct ipath_devdata *dd, int which)
++{
++	int ret;
++
++	switch (which) {
++	case IPATH_IB_CFG_LWID:
++		ret = dd->ipath_link_width_active;
++		break;
++	case IPATH_IB_CFG_SPD:
++		ret = dd->ipath_link_speed_active;
++		break;
++	case IPATH_IB_CFG_LWID_ENB:
++		ret = dd->ipath_link_width_enabled;
++		break;
++	case IPATH_IB_CFG_SPD_ENB:
++		ret = dd->ipath_link_speed_enabled;
++		break;
++	default:
++		ret =  -ENOTSUPP;
++		break;
++	}
++	return ret;
++}
++
++
++/* we assume range checking is already done, if needed */
++static int ipath_ht_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
++{
++	int ret = 0;
++
++	if (which == IPATH_IB_CFG_LWID_ENB)
++		dd->ipath_link_width_enabled = val;
++	else if (which == IPATH_IB_CFG_SPD_ENB)
++		dd->ipath_link_speed_enabled = val;
++	else
++		ret = -ENOTSUPP;
++	return ret;
++}
++
++
++static void ipath_ht_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
++{
++}
++
++
++static int ipath_ht_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++{
++	ipath_setup_ht_setextled(dd, ipath_ib_linkstate(dd, ibcs),
++		ipath_ib_linktrstate(dd, ibcs));
++	return 0;
++}
++
++
+ /**
+  * ipath_init_iba6110_funcs - set up the chip-specific function pointers
+  * @dd: the infinipath device
+@@ -1626,22 +1926,19 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd)
+ 	dd->ipath_f_setextled = ipath_setup_ht_setextled;
+ 	dd->ipath_f_get_base_info = ipath_ht_get_base_info;
+ 	dd->ipath_f_free_irq = ipath_ht_free_irq;
+-
+-	/*
+-	 * initialize chip-specific variables
+-	 */
+ 	dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
++	dd->ipath_f_intr_fallback = ipath_ht_nointr_fallback;
++	dd->ipath_f_get_msgheader = ipath_ht_get_msgheader;
++	dd->ipath_f_config_ports = ipath_ht_config_ports;
++	dd->ipath_f_read_counters = ipath_ht_read_counters;
++	dd->ipath_f_xgxs_reset = ipath_ht_xgxs_reset;
++	dd->ipath_f_get_ib_cfg = ipath_ht_get_ib_cfg;
++	dd->ipath_f_set_ib_cfg = ipath_ht_set_ib_cfg;
++	dd->ipath_f_config_jint = ipath_ht_config_jint;
++	dd->ipath_f_ib_updown = ipath_ht_ib_updown;
  
--	pci_write_config_byte(hwif->pci_dev, hwif->select_data, 0x37);
-+	pci_write_config_byte(dev, hwif->select_data, 0x37);
- 	udelay(10);
+ 	/*
+-	 * setup the register offsets, since they are different for each
+-	 * chip
+-	 */
+-	dd->ipath_kregs = &ipath_ht_kregs;
+-	dd->ipath_cregs = &ipath_ht_cregs;
+-
+-	/*
+-	 * do very early init that is needed before ipath_f_bus is
+-	 * called
++	 * initialize chip-specific variables
+ 	 */
+ 	ipath_init_ht_variables(dd);
  }
+diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+index 0103d6f..c7a2f50 100644
+--- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
++++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
+@@ -145,10 +145,57 @@ struct _infinipath_do_not_use_kernel_regs {
+ 	unsigned long long Reserved12;
+ };
  
- static void hpt370_irq_timeout(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u16 bfifo		= 0;
- 	u8  dma_cmd;
+-#define IPATH_KREG_OFFSET(field) (offsetof(struct \
+-    _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
++struct _infinipath_do_not_use_counters {
++	__u64 LBIntCnt;
++	__u64 LBFlowStallCnt;
++	__u64 Reserved1;
++	__u64 TxUnsupVLErrCnt;
++	__u64 TxDataPktCnt;
++	__u64 TxFlowPktCnt;
++	__u64 TxDwordCnt;
++	__u64 TxLenErrCnt;
++	__u64 TxMaxMinLenErrCnt;
++	__u64 TxUnderrunCnt;
++	__u64 TxFlowStallCnt;
++	__u64 TxDroppedPktCnt;
++	__u64 RxDroppedPktCnt;
++	__u64 RxDataPktCnt;
++	__u64 RxFlowPktCnt;
++	__u64 RxDwordCnt;
++	__u64 RxLenErrCnt;
++	__u64 RxMaxMinLenErrCnt;
++	__u64 RxICRCErrCnt;
++	__u64 RxVCRCErrCnt;
++	__u64 RxFlowCtrlErrCnt;
++	__u64 RxBadFormatCnt;
++	__u64 RxLinkProblemCnt;
++	__u64 RxEBPCnt;
++	__u64 RxLPCRCErrCnt;
++	__u64 RxBufOvflCnt;
++	__u64 RxTIDFullErrCnt;
++	__u64 RxTIDValidErrCnt;
++	__u64 RxPKeyMismatchCnt;
++	__u64 RxP0HdrEgrOvflCnt;
++	__u64 RxP1HdrEgrOvflCnt;
++	__u64 RxP2HdrEgrOvflCnt;
++	__u64 RxP3HdrEgrOvflCnt;
++	__u64 RxP4HdrEgrOvflCnt;
++	__u64 RxP5HdrEgrOvflCnt;
++	__u64 RxP6HdrEgrOvflCnt;
++	__u64 RxP7HdrEgrOvflCnt;
++	__u64 RxP8HdrEgrOvflCnt;
++	__u64 Reserved6;
++	__u64 Reserved7;
++	__u64 IBStatusChangeCnt;
++	__u64 IBLinkErrRecoveryCnt;
++	__u64 IBLinkDownedCnt;
++	__u64 IBSymbolErrCnt;
++};
++
++#define IPATH_KREG_OFFSET(field) (offsetof( \
++	struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
+ #define IPATH_CREG_OFFSET(field) (offsetof( \
+-    struct infinipath_counters, field) / sizeof(u64))
++	struct _infinipath_do_not_use_counters, field) / sizeof(u64))
  
--	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
-+	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
- 	printk(KERN_DEBUG "%s: %d bytes in FIFO\n", drive->name, bfifo & 0x1ff);
+ static const struct ipath_kregs ipath_pe_kregs = {
+ 	.kr_control = IPATH_KREG_OFFSET(Control),
+@@ -282,6 +329,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ #define INFINIPATH_HWE_PCIE0PLLFAILED       0x0800000000000000ULL
+ #define INFINIPATH_HWE_SERDESPLLFAILED      0x1000000000000000ULL
  
- 	/* get DMA command mode */
-@@ -870,10 +841,11 @@ static void hpt370_dma_timeout(ide_drive_t *drive)
- static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u16 bfifo		= 0;
- 	u8  dma_stat;
++#define IBA6120_IBCS_LINKTRAININGSTATE_MASK 0xf
++#define IBA6120_IBCS_LINKSTATE_SHIFT 4
++
+ /* kr_extstatus bits */
+ #define INFINIPATH_EXTS_FREQSEL 0x2
+ #define INFINIPATH_EXTS_SERDESSEL 0x4
+@@ -296,6 +346,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
+ #define IPATH_GPIO_SCL (1ULL << \
+ 	(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
  
--	pci_read_config_word(hwif->pci_dev, hwif->select_data + 2, &bfifo);
-+	pci_read_config_word(dev, hwif->select_data + 2, &bfifo);
- 	if (bfifo & 0x1FF) {
- //		printk("%s: %d bytes in FIFO\n", drive->name, bfifo);
- 		return 0;
-@@ -893,7 +865,7 @@ static int hpt374_ide_dma_test_irq(ide_drive_t *drive)
- static int hpt374_ide_dma_end(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev	*dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 mcr	= 0, mcr_addr	= hwif->select_data;
- 	u8 bwsr = 0, mask	= hwif->channel ? 0x02 : 0x01;
++#define INFINIPATH_R_INTRAVAIL_SHIFT 16
++#define INFINIPATH_R_TAILUPD_SHIFT 31
++
+ /* 6120 specific hardware errors... */
+ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
+ 	INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
+@@ -320,10 +373,28 @@ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
+ 		        INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \
+ 		        << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)
  
-@@ -914,32 +886,33 @@ static int hpt374_ide_dma_end(ide_drive_t *drive)
+-static int ipath_pe_txe_recover(struct ipath_devdata *);
+ static void ipath_pe_put_tid_2(struct ipath_devdata *, u64 __iomem *,
+ 			       u32, unsigned long);
  
- static void hpt3xxn_set_clock(ide_hwif_t *hwif, u8 mode)
- {
--	u8 scr2 = inb(hwif->dma_master + 0x7b);
-+	unsigned long base = hwif->extra_base;
-+	u8 scr2 = inb(base + 0x6b);
++/*
++ * On platforms using this chip, and not having ordered WC stores, we
++ * can get TXE parity errors due to speculative reads to the PIO buffers,
++ * and this, due to a chip bug can result in (many) false parity error
++ * reports.  So it's a debug print on those, and an info print on systems
++ * where the speculative reads don't occur.
++ */
++static void ipath_pe_txe_recover(struct ipath_devdata *dd)
++{
++	if (ipath_unordered_wc())
++		ipath_dbg("Recovering from TXE PIO parity error\n");
++	else {
++		++ipath_stats.sps_txeparity;
++		dev_info(&dd->pcidev->dev,
++			"Recovering from TXE PIO parity error\n");
++	}
++}
++
++
+ /**
+  * ipath_pe_handle_hwerrors - display hardware errors.
+  * @dd: the infinipath device
+@@ -403,35 +474,11 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
+ 		 * occur if a processor speculative read is done to the PIO
+ 		 * buffer while we are sending a packet, for example.
+ 		 */
+-		if ((hwerrs & TXE_PIO_PARITY) && ipath_pe_txe_recover(dd))
++		if (hwerrs & TXE_PIO_PARITY) {
++			ipath_pe_txe_recover(dd);
+ 			hwerrs &= ~TXE_PIO_PARITY;
+-		if (hwerrs) {
+-			/*
+-			 * if any set that we aren't ignoring only make the
+-			 * complaint once, in case it's stuck or recurring,
+-			 * and we get here multiple times
+-			 * Force link down, so switch knows, and
+-			 * LEDs are turned off
+-			 */
+-			if (dd->ipath_flags & IPATH_INITTED) {
+-				ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
+-				ipath_setup_pe_setextled(dd,
+-					INFINIPATH_IBCS_L_STATE_DOWN,
+-					INFINIPATH_IBCS_LT_STATE_DISABLED);
+-				ipath_dev_err(dd, "Fatal Hardware Error (freeze "
+-					      "mode), no longer usable, SN %.16s\n",
+-						  dd->ipath_serial);
+-				isfatal = 1;
+-			}
+-			/*
+-			 * Mark as having had an error for driver, and also
+-			 * for /sys and status word mapped to user programs.
+-			 * This marks unit as not usable, until reset
+-			 */
+-			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
+-			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
+-			dd->ipath_flags &= ~IPATH_INITTED;
+-		} else {
++		}
++		if (!hwerrs) {
+ 			static u32 freeze_cnt;
  
- 	if ((scr2 & 0x7f) == mode)
- 		return;
+ 			freeze_cnt++;
+@@ -485,7 +532,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
  
- 	/* Tristate the bus */
--	outb(0x80, hwif->dma_master + 0x73);
--	outb(0x80, hwif->dma_master + 0x77);
-+	outb(0x80, base + 0x63);
-+	outb(0x80, base + 0x67);
+ 	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
+ 		/*
+-		 * If it occurs, it is left masked since the eternal
++		 * If it occurs, it is left masked since the external
+ 		 * interface is unused
+ 		 */
+ 		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
+@@ -563,6 +610,14 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
+ 			dd->ipath_f_put_tid = ipath_pe_put_tid_2;
+ 	}
  
- 	/* Switch clock and reset channels */
--	outb(mode, hwif->dma_master + 0x7b);
--	outb(0xc0, hwif->dma_master + 0x79);
-+	outb(mode, base + 0x6b);
-+	outb(0xc0, base + 0x69);
++
++	/*
++	 * set here, not in ipath_init_*_funcs because we have to do
++	 * it after we can read chip registers.
++	 */
++	dd->ipath_ureg_align =
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
++
+ 	return ret;
+ }
  
- 	/*
- 	 * Reset the state machines.
- 	 * NOTE: avoid accidentally enabling the disabled channels.
- 	 */
--	outb(inb(hwif->dma_master + 0x70) | 0x32, hwif->dma_master + 0x70);
--	outb(inb(hwif->dma_master + 0x74) | 0x32, hwif->dma_master + 0x74);
-+	outb(inb(base + 0x60) | 0x32, base + 0x60);
-+	outb(inb(base + 0x64) | 0x32, base + 0x64);
+@@ -667,17 +722,8 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
  
- 	/* Complete reset */
--	outb(0x00, hwif->dma_master + 0x79);
-+	outb(0x00, base + 0x69);
+ 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
+ 	prev_val = val;
+-	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
+-	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
+-		val &=
+-			~(INFINIPATH_XGXS_MDIOADDR_MASK <<
+-			  INFINIPATH_XGXS_MDIOADDR_SHIFT);
+-		/* MDIO address 3 */
+-		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
+-	}
+-	if (val & INFINIPATH_XGXS_RESET) {
++	if (val & INFINIPATH_XGXS_RESET)
+ 		val &= ~INFINIPATH_XGXS_RESET;
+-	}
+ 	if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &
+ 	     INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {
+ 		/* need to compensate for Tx inversion in partner */
+@@ -707,21 +753,6 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
+ 		   (unsigned long long)
+ 		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
  
- 	/* Reconnect channels to bus */
--	outb(0x00, hwif->dma_master + 0x73);
--	outb(0x00, hwif->dma_master + 0x77);
-+	outb(0x00, base + 0x63);
-+	outb(0x00, base + 0x67);
+-	if (!ipath_waitfor_mdio_cmdready(dd)) {
+-		ipath_write_kreg(
+-			dd, dd->ipath_kregs->kr_mdio,
+-			ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
+-				       IPATH_MDIO_CTRL_XGXS_REG_8, 0));
+-		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
+-					   IPATH_MDIO_DATAVALID, &val))
+-			ipath_dbg("Never got MDIO data for XGXS "
+-				  "status read\n");
+-		else
+-			ipath_cdbg(VERBOSE, "MDIO Read reg8, "
+-				   "'bank' 31 %x\n", (u32) val);
+-	} else
+-		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
+-
+ 	return ret;
  }
  
- /**
-@@ -967,7 +940,7 @@ static void hpt3xxn_rw_disk(ide_drive_t *drive, struct request *rq)
- static int hpt3xx_busproc(ide_drive_t *drive, int state)
+@@ -902,12 +933,27 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
+ 	else
+ 		ipath_dev_err(dd, "Can't find PCI Express "
+ 			      "capability!\n");
++
++	dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
++	dd->ipath_link_speed_supported = IPATH_IB_SDR;
++	dd->ipath_link_width_enabled = IB_WIDTH_4X;
++	dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
++	/* these can't change for this chip, so set once */
++	dd->ipath_link_width_active = dd->ipath_link_width_enabled;
++	dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
+ 	return 0;
+ }
+ 
+ static void ipath_init_pe_variables(struct ipath_devdata *dd)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8  mcr_addr		= hwif->select_data + 2;
- 	u8  resetmask		= hwif->channel ? 0x80 : 0x40;
- 	u8  bsr2		= 0;
-@@ -1210,7 +1183,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
- 	 * We also  don't like using  the DPLL because this causes glitches
- 	 * on PRST-/SRST- when the state engine gets reset...
+ 	/*
++	 * setup the register offsets, since they are different for each
++	 * chip
++	 */
++	dd->ipath_kregs = &ipath_pe_kregs;
++	dd->ipath_cregs = &ipath_pe_cregs;
++
++	/*
+ 	 * bits for selecting i2c direction and values,
+ 	 * used for I2C serial flash
  	 */
--	if (chip_type >= HPT374 || info->settings[clock] == NULL) {
-+	if (chip_type >= HPT374 || info->timings->clock_table[clock] == NULL) {
- 		u16 f_low, delta = pci_clk < 50 ? 2 : 4;
- 		int adjust;
+@@ -916,6 +962,43 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
+ 	dd->ipath_gpio_sda = IPATH_GPIO_SDA;
+ 	dd->ipath_gpio_scl = IPATH_GPIO_SCL;
  
-@@ -1226,7 +1199,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
- 			clock = ATA_CLOCK_50MHZ;
- 		}
++	/*
++	 * Fill in data for field-values that change in newer chips.
++	 * We dynamically specify only the mask for LINKTRAININGSTATE
++	 * and only the shift for LINKSTATE, as they are the only ones
++	 * that change.  Also precalculate the 3 link states of interest
++	 * and the combined mask.
++	 */
++	dd->ibcs_ls_shift = IBA6120_IBCS_LINKSTATE_SHIFT;
++	dd->ibcs_lts_mask = IBA6120_IBCS_LINKTRAININGSTATE_MASK;
++	dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
++		dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
++	dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
++	dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
++	dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
++		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
++		(INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
++
++	/*
++	 * Fill in data for ibcc field-values that change in newer chips.
++	 * We dynamically specify only the mask for LINKINITCMD
++	 * and only the shift for LINKCMD and MAXPKTLEN, as they are
++	 * the only ones that change.
++	 */
++	dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
++	dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
++	dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
++
++	/* Fill in shifts for RcvCtrl. */
++	dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
++	dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
++	dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT;
++	dd->ipath_r_portcfg_shift = 0; /* Not on IBA6120 */
++
+ 	/* variables for sanity checking interrupt and errors */
+ 	dd->ipath_hwe_bitsextant =
+ 		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
+@@ -963,6 +1046,8 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
  
--		if (info->settings[clock] == NULL) {
-+		if (info->timings->clock_table[clock] == NULL) {
- 			printk(KERN_ERR "%s: unknown bus timing!\n", name);
- 			kfree(info);
- 			return -EIO;
-@@ -1267,15 +1240,10 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
- 		printk("%s: using %d MHz PCI clock\n", name, pci_clk);
- 	}
+ 	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
+ 	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
++	dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
++	dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
  
--	/*
--	 * Advance the table pointer to a slot which points to the list
--	 * of the register values settings matching the clock being used.
--	 */
--	info->settings += clock;
--
- 	/* Store the clock frequencies. */
- 	info->dpll_clk	= dpll_clk;
- 	info->pci_clk	= pci_clk;
-+	info->clock	= clock;
+ 	/*
+ 	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
+@@ -984,6 +1069,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
+ 		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
  
- 	/* Point to this chip's own instance of the hpt_info structure. */
- 	pci_set_drvdata(dev, info);
-@@ -1306,12 +1274,55 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha
- 	return dev->irq;
+ 
++	dd->delay_mult = 2; /* SDR, 4X, can't change */
  }
  
-+static u8 __devinit hpt3xx_cable_detect(ide_hwif_t *hwif)
+ /* setup the MSI stuff again after a reset.  I'd like to just call
+@@ -1289,6 +1375,9 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
+ 	 */
+ 	dd->ipath_rcvhdrentsize = 24;
+ 	dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
++	dd->ipath_rhf_offset = 0;
++	dd->ipath_egrtidbase = (u64 __iomem *)
++		((char __iomem *) dd->ipath_kregbase + dd->ipath_rcvegrbase);
+ 
+ 	/*
+ 	 * To truly support a 4KB MTU (for usermode), we need to
+@@ -1359,34 +1448,204 @@ static void ipath_pe_free_irq(struct ipath_devdata *dd)
+ 	dd->ipath_irq = 0;
+ }
+ 
++
++static struct ipath_message_header *
++ipath_pe_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
 +{
-+	struct pci_dev	*dev	= to_pci_dev(hwif->dev);
-+	struct hpt_info *info	= pci_get_drvdata(dev);
-+	u8 chip_type		= info->chip_type;
-+	u8 scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
++	return (struct ipath_message_header *)
++		&rhf_addr[sizeof(u64) / sizeof(u32)];
++}
 +
-+	/*
-+	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
-+	 * address lines to access an external EEPROM.  To read valid
-+	 * cable detect state the pins must be enabled as inputs.
-+	 */
-+	if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
-+		/*
-+		 * HPT374 PCI function 1
-+		 * - set bit 15 of reg 0x52 to enable TCBLID as input
-+		 * - set bit 15 of reg 0x56 to enable FCBLID as input
-+		 */
-+		u8  mcr_addr = hwif->select_data + 2;
-+		u16 mcr;
++static void ipath_pe_config_ports(struct ipath_devdata *dd, ushort cfgports)
++{
++	dd->ipath_portcnt =
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
++	dd->ipath_p0_rcvegrcnt =
++		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
++}
 +
-+		pci_read_config_word(dev, mcr_addr, &mcr);
-+		pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
-+		/* now read cable id register */
-+		pci_read_config_byte(dev, 0x5a, &scr1);
-+		pci_write_config_word(dev, mcr_addr, mcr);
-+	} else if (chip_type >= HPT370) {
-+		/*
-+		 * HPT370/372 and 374 pcifn 0
-+		 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
-+		 */
-+		u8 scr2 = 0;
++static void ipath_pe_read_counters(struct ipath_devdata *dd,
++				   struct infinipath_counters *cntrs)
++{
++	cntrs->LBIntCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt));
++	cntrs->LBFlowStallCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt));
++	cntrs->TxSDmaDescCnt = 0;
++	cntrs->TxUnsupVLErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt));
++	cntrs->TxDataPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt));
++	cntrs->TxFlowPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt));
++	cntrs->TxDwordCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt));
++	cntrs->TxLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt));
++	cntrs->TxMaxMinLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt));
++	cntrs->TxUnderrunCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt));
++	cntrs->TxFlowStallCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt));
++	cntrs->TxDroppedPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt));
++	cntrs->RxDroppedPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt));
++	cntrs->RxDataPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt));
++	cntrs->RxFlowPktCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt));
++	cntrs->RxDwordCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt));
++	cntrs->RxLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt));
++	cntrs->RxMaxMinLenErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt));
++	cntrs->RxICRCErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt));
++	cntrs->RxVCRCErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt));
++	cntrs->RxFlowCtrlErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt));
++	cntrs->RxBadFormatCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt));
++	cntrs->RxLinkProblemCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt));
++	cntrs->RxEBPCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt));
++	cntrs->RxLPCRCErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt));
++	cntrs->RxBufOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt));
++	cntrs->RxTIDFullErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt));
++	cntrs->RxTIDValidErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt));
++	cntrs->RxPKeyMismatchCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt));
++	cntrs->RxP0HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt));
++	cntrs->RxP1HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt));
++	cntrs->RxP2HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt));
++	cntrs->RxP3HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt));
++	cntrs->RxP4HdrEgrOvflCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt));
++	cntrs->RxP5HdrEgrOvflCnt = 0;
++	cntrs->RxP6HdrEgrOvflCnt = 0;
++	cntrs->RxP7HdrEgrOvflCnt = 0;
++	cntrs->RxP8HdrEgrOvflCnt = 0;
++	cntrs->RxP9HdrEgrOvflCnt = 0;
++	cntrs->RxP10HdrEgrOvflCnt = 0;
++	cntrs->RxP11HdrEgrOvflCnt = 0;
++	cntrs->RxP12HdrEgrOvflCnt = 0;
++	cntrs->RxP13HdrEgrOvflCnt = 0;
++	cntrs->RxP14HdrEgrOvflCnt = 0;
++	cntrs->RxP15HdrEgrOvflCnt = 0;
++	cntrs->RxP16HdrEgrOvflCnt = 0;
++	cntrs->IBStatusChangeCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt));
++	cntrs->IBLinkErrRecoveryCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt));
++	cntrs->IBLinkDownedCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt));
++	cntrs->IBSymbolErrCnt =
++		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt));
++	cntrs->RxVL15DroppedPktCnt = 0;
++	cntrs->RxOtherLocalPhyErrCnt = 0;
++	cntrs->PcieRetryBufDiagQwordCnt = 0;
++	cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs;
++	cntrs->LocalLinkIntegrityErrCnt = dd->ipath_lli_errs;
++	cntrs->RxVlErrCnt = 0;
++	cntrs->RxDlidFltrCnt = 0;
++}
 +
-+		pci_read_config_byte(dev, 0x5b, &scr2);
-+		pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
-+		/* now read cable id register */
-+		pci_read_config_byte(dev, 0x5a, &scr1);
-+		pci_write_config_byte(dev, 0x5b,  scr2);
-+	} else
-+		pci_read_config_byte(dev, 0x5a, &scr1);
 +
-+	return (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++/* no interrupt fallback for these chips */
++static int ipath_pe_nointr_fallback(struct ipath_devdata *dd)
++{
++	return 0;
 +}
 +
- static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
++
+ /*
+- * On platforms using this chip, and not having ordered WC stores, we
+- * can get TXE parity errors due to speculative reads to the PIO buffers,
+- * and this, due to a chip bug can result in (many) false parity error
+- * reports.  So it's a debug print on those, and an info print on systems
+- * where the speculative reads don't occur.
+- * Because we can get lots of false errors, we have no upper limit
+- * on recovery attempts on those platforms.
++ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
++ * than resetting the IBC or external link state, and useful in some
++ * cases to cause some retraining.  To do this right, we reset IBC
++ * as well.
+  */
+-static int ipath_pe_txe_recover(struct ipath_devdata *dd)
++static void ipath_pe_xgxs_reset(struct ipath_devdata *dd)
  {
--	struct pci_dev	*dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	struct hpt_info *info	= pci_get_drvdata(dev);
- 	int serialize		= HPT_SERIALIZE_IO;
--	u8  scr1 = 0, ata66	= hwif->channel ? 0x01 : 0x02;
- 	u8  chip_type		= info->chip_type;
- 	u8  new_mcr, old_mcr	= 0;
- 
-@@ -1320,14 +1331,16 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
- 
- 	hwif->set_pio_mode	= &hpt3xx_set_pio_mode;
- 	hwif->set_dma_mode	= &hpt3xx_set_mode;
+-	if (ipath_unordered_wc())
+-		ipath_dbg("Recovering from TXE PIO parity error\n");
+-	else {
+-		int cnt = ++ipath_stats.sps_txeparity;
+-		if (cnt >= IPATH_MAX_PARITY_ATTEMPTS)  {
+-			if (cnt == IPATH_MAX_PARITY_ATTEMPTS)
+-				ipath_dev_err(dd,
+-					"Too many attempts to recover from "
+-					"TXE parity, giving up\n");
+-			return 0;
+-		}
+-		dev_info(&dd->pcidev->dev,
+-			"Recovering from TXE PIO parity error\n");
++	u64 val, prev_val;
 +
- 	hwif->quirkproc		= &hpt3xx_quirkproc;
--	hwif->intrproc		= &hpt3xx_intrproc;
- 	hwif->maskproc		= &hpt3xx_maskproc;
- 	hwif->busproc		= &hpt3xx_busproc;
- 
- 	hwif->udma_filter	= &hpt3xx_udma_filter;
- 	hwif->mdma_filter	= &hpt3xx_mdma_filter;
++	prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
++	val = prev_val | INFINIPATH_XGXS_RESET;
++	prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++			 dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
++	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
++			 dd->ipath_control);
++}
++
++
++static int ipath_pe_get_ib_cfg(struct ipath_devdata *dd, int which)
++{
++	int ret;
++
++	switch (which) {
++	case IPATH_IB_CFG_LWID:
++		ret = dd->ipath_link_width_active;
++		break;
++	case IPATH_IB_CFG_SPD:
++		ret = dd->ipath_link_speed_active;
++		break;
++	case IPATH_IB_CFG_LWID_ENB:
++		ret = dd->ipath_link_width_enabled;
++		break;
++	case IPATH_IB_CFG_SPD_ENB:
++		ret = dd->ipath_link_speed_enabled;
++		break;
++	default:
++		ret =  -ENOTSUPP;
++		break;
+ 	}
+-	return 1;
++	return ret;
++}
++
++
++/* we assume range checking is already done, if needed */
++static int ipath_pe_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
++{
++	int ret = 0;
++
++	if (which == IPATH_IB_CFG_LWID_ENB)
++		dd->ipath_link_width_enabled = val;
++	else if (which == IPATH_IB_CFG_SPD_ENB)
++		dd->ipath_link_speed_enabled = val;
++	else
++		ret = -ENOTSUPP;
++	return ret;
+ }
  
-+	hwif->cable_detect	= hpt3xx_cable_detect;
++static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
++{
++}
++
++
++static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++{
++	ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs),
++		ipath_ib_linktrstate(dd, ibcs));
++	return 0;
++}
 +
++
+ /**
+  * ipath_init_iba6120_funcs - set up the chip-specific function pointers
+  * @dd: the infinipath device
+@@ -1407,7 +1666,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
+ 	dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
+ 	dd->ipath_f_clear_tids = ipath_pe_clear_tids;
  	/*
- 	 * HPT3xxN chips have some complications:
- 	 *
-@@ -1373,43 +1386,6 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
- 	if (hwif->dma_base == 0)
- 		return;
+-	 * this may get changed after we read the chip revision,
++	 * _f_put_tid may get changed after we read the chip revision,
+ 	 * but we start with the safe version for all revs
+ 	 */
+ 	dd->ipath_f_put_tid = ipath_pe_put_tid;
+@@ -1415,17 +1674,19 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
+ 	dd->ipath_f_setextled = ipath_setup_pe_setextled;
+ 	dd->ipath_f_get_base_info = ipath_pe_get_base_info;
+ 	dd->ipath_f_free_irq = ipath_pe_free_irq;
+-
+-	/* initialize chip-specific variables */
+ 	dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
++	dd->ipath_f_intr_fallback = ipath_pe_nointr_fallback;
++	dd->ipath_f_xgxs_reset = ipath_pe_xgxs_reset;
++	dd->ipath_f_get_msgheader = ipath_pe_get_msgheader;
++	dd->ipath_f_config_ports = ipath_pe_config_ports;
++	dd->ipath_f_read_counters = ipath_pe_read_counters;
++	dd->ipath_f_get_ib_cfg = ipath_pe_get_ib_cfg;
++	dd->ipath_f_set_ib_cfg = ipath_pe_set_ib_cfg;
++	dd->ipath_f_config_jint = ipath_pe_config_jint;
++	dd->ipath_f_ib_updown = ipath_pe_ib_updown;
  
 -	/*
--	 * The HPT37x uses the CBLID pins as outputs for MA15/MA16
--	 * address lines to access an external EEPROM.  To read valid
--	 * cable detect state the pins must be enabled as inputs.
+-	 * setup the register offsets, since they are different for each
+-	 * chip
 -	 */
--	if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) {
--		/*
--		 * HPT374 PCI function 1
--		 * - set bit 15 of reg 0x52 to enable TCBLID as input
--		 * - set bit 15 of reg 0x56 to enable FCBLID as input
--		 */
--		u8  mcr_addr = hwif->select_data + 2;
--		u16 mcr;
+-	dd->ipath_kregs = &ipath_pe_kregs;
+-	dd->ipath_cregs = &ipath_pe_cregs;
+ 
++	/* initialize chip-specific variables */
+ 	ipath_init_pe_variables(dd);
+ }
+ 
+diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
+index 9dd0bac..4471674 100644
+--- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
++++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
+@@ -91,7 +91,7 @@ static int create_port0_egr(struct ipath_devdata *dd)
+ 	struct ipath_skbinfo *skbinfo;
+ 	int ret;
+ 
+-	egrcnt = dd->ipath_rcvegrcnt;
++	egrcnt = dd->ipath_p0_rcvegrcnt;
+ 
+ 	skbinfo = vmalloc(sizeof(*dd->ipath_port0_skbinfo) * egrcnt);
+ 	if (skbinfo == NULL) {
+@@ -244,8 +244,7 @@ static int init_chip_first(struct ipath_devdata *dd,
+ 	 * cfgports.  We do still check and report a difference, if
+ 	 * not same (should be impossible).
+ 	 */
+-	dd->ipath_portcnt =
+-		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
++	dd->ipath_f_config_ports(dd, ipath_cfgports);
+ 	if (!ipath_cfgports)
+ 		dd->ipath_cfgports = dd->ipath_portcnt;
+ 	else if (ipath_cfgports <= dd->ipath_portcnt) {
+@@ -272,22 +271,7 @@ static int init_chip_first(struct ipath_devdata *dd,
+ 		goto done;
+ 	}
+ 
+-	dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads)
+-					 * dd->ipath_cfgports,
+-					 GFP_KERNEL);
+-	dd->ipath_lastrcvhdrqtails =
+-		kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails)
+-			* dd->ipath_cfgports, GFP_KERNEL);
 -
--		pci_read_config_word (dev, mcr_addr, &mcr);
--		pci_write_config_word(dev, mcr_addr, (mcr | 0x8000));
--		/* now read cable id register */
--		pci_read_config_byte (dev, 0x5a, &scr1);
--		pci_write_config_word(dev, mcr_addr, mcr);
--	} else if (chip_type >= HPT370) {
--		/*
--		 * HPT370/372 and 374 pcifn 0
--		 * - clear bit 0 of reg 0x5b to enable P/SCBLID as inputs
--		 */
--		u8 scr2 = 0;
+-	if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) {
+-		ipath_dev_err(dd, "Unable to allocate head arrays, "
+-			      "failing\n");
+-		ret = -ENOMEM;
+-		goto done;
+-	}
 -
--		pci_read_config_byte (dev, 0x5b, &scr2);
--		pci_write_config_byte(dev, 0x5b, (scr2 & ~1));
--		/* now read cable id register */
--		pci_read_config_byte (dev, 0x5a, &scr1);
--		pci_write_config_byte(dev, 0x5b,  scr2);
--	} else
--		pci_read_config_byte (dev, 0x5a, &scr1);
+ 	pd = create_portdata0(dd);
 -
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = (scr1 & ata66) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
+ 	if (!pd) {
+ 		ipath_dev_err(dd, "Unable to allocate portdata for port "
+ 			      "0, failing\n");
+@@ -345,10 +329,10 @@ static int init_chip_first(struct ipath_devdata *dd,
+ 		       dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
+ 
+ 	spin_lock_init(&dd->ipath_tid_lock);
 -
- 	if (chip_type >= HPT374) {
- 		hwif->ide_dma_test_irq	= &hpt374_ide_dma_test_irq;
- 		hwif->ide_dma_end	= &hpt374_ide_dma_end;
-@@ -1423,7 +1399,7 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif)
++	spin_lock_init(&dd->ipath_sendctrl_lock);
+ 	spin_lock_init(&dd->ipath_gpio_lock);
+ 	spin_lock_init(&dd->ipath_eep_st_lock);
+-	sema_init(&dd->ipath_eep_sem, 1);
++	mutex_init(&dd->ipath_eep_lock);
  
- static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
+ done:
+ 	*pdp = pd;
+@@ -372,9 +356,9 @@ static int init_chip_reset(struct ipath_devdata *dd,
+ 	*pdp = dd->ipath_pd[0];
+ 	/* ensure chip does no sends or receives while we re-initialize */
+ 	dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control);
+ 
+ 	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
+ 	if (dd->ipath_portcnt != rtmp)
+@@ -487,6 +471,7 @@ static void enable_chip(struct ipath_devdata *dd,
+ 			struct ipath_portdata *pd, int reinit)
  {
--	struct pci_dev	*dev		= hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	u8 masterdma	= 0, slavedma	= 0;
- 	u8 dma_new	= 0, dma_old	= 0;
- 	unsigned long flags;
-@@ -1443,7 +1419,7 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase)
+ 	u32 val;
++	unsigned long flags;
+ 	int i;
  
- 	local_irq_restore(flags);
+ 	if (!reinit)
+@@ -495,19 +480,21 @@ static void enable_chip(struct ipath_devdata *dd,
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
  
--	ide_setup_dma(hwif, dmabase, 8);
-+	ide_setup_dma(hwif, dmabase);
- }
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+ 	/* Enable PIO send, and update of PIOavail regs to memory. */
+ 	dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
+ 		INFINIPATH_S_PIOBUFAVAILUPD;
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-			 dd->ipath_sendctrl);
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
  
- static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2)
-@@ -1494,6 +1470,11 @@ static int __devinit hpt36x_init(struct pci_dev *dev, struct pci_dev *dev2)
- 	return 0;
- }
+ 	/*
+ 	 * enable port 0 receive, and receive interrupt.  other ports
+ 	 * done as user opens and inits them.
+ 	 */
+-	dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD |
+-		(1ULL << INFINIPATH_R_PORTENABLE_SHIFT) |
+-		(1ULL << INFINIPATH_R_INTRAVAIL_SHIFT);
++	dd->ipath_rcvctrl = (1ULL << dd->ipath_r_tailupd_shift) |
++		(1ULL << dd->ipath_r_portenable_shift) |
++		(1ULL << dd->ipath_r_intravail_shift);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
+ 			 dd->ipath_rcvctrl);
  
-+#define IDE_HFLAGS_HPT3XX \
-+	(IDE_HFLAG_NO_ATAPI_DMA | \
-+	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
-+	 IDE_HFLAG_OFF_BOARD)
-+
- static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 	{	/* 0 */
- 		.name		= "HPT36x",
-@@ -1508,9 +1489,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 		 */
- 		.enablebits	= {{0x50,0x10,0x10}, {0x54,0x04,0x04}},
- 		.extra		= 240,
--		.host_flags	= IDE_HFLAG_SINGLE |
--				  IDE_HFLAG_NO_ATAPI_DMA |
--				  IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT3XX | IDE_HFLAG_SINGLE,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 	},{	/* 1 */
-@@ -1520,7 +1499,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 		.init_dma	= init_dma_hpt366,
- 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- 		.extra		= 240,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT3XX,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 	},{	/* 2 */
-@@ -1530,7 +1509,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 		.init_dma	= init_dma_hpt366,
- 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- 		.extra		= 240,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT3XX,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 	},{	/* 3 */
-@@ -1540,7 +1519,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 		.init_dma	= init_dma_hpt366,
- 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- 		.extra		= 240,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT3XX,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 	},{	/* 4 */
-@@ -1551,7 +1530,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- 		.udma_mask	= ATA_UDMA5,
- 		.extra		= 240,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT3XX,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 	},{	/* 5 */
-@@ -1561,7 +1540,7 @@ static const struct ide_port_info hpt366_chipsets[] __devinitdata = {
- 		.init_dma	= init_dma_hpt366,
- 		.enablebits	= {{0x50,0x04,0x04}, {0x54,0x04,0x04}},
- 		.extra		= 240,
--		.host_flags	= IDE_HFLAG_NO_ATAPI_DMA | IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_HPT3XX,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 	}
-diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
-index 90b52ed..e3427ea 100644
---- a/drivers/ide/pci/it8213.c
-+++ b/drivers/ide/pci/it8213.c
-@@ -10,13 +10,10 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
+@@ -523,12 +510,11 @@ static void enable_chip(struct ipath_devdata *dd,
+ 	 */
+ 	val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
+ 	(void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
+-	dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0);
  
--#include <asm/io.h>
--
- /**
-  *	it8213_set_pio_mode	-	set host controller for PIO mode
-  *	@drive: drive
-@@ -28,7 +25,7 @@
- static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	int is_slave		= drive->dn & 1;
- 	int master_port		= 0x40;
- 	int slave_port		= 0x44;
-@@ -85,7 +82,7 @@ static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
- static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ 	/* Initialize so we interrupt on next packet received */
+ 	(void)ipath_write_ureg(dd, ur_rcvhdrhead,
+ 			       dd->ipath_rhdrhead_intr_off |
+-			       dd->ipath_port0head, 0);
++			       dd->ipath_pd[0]->port_head, 0);
+ 
+ 	/*
+ 	 * by now pioavail updates to memory should have occurred, so
+@@ -542,12 +528,8 @@ static void enable_chip(struct ipath_devdata *dd,
+ 		/*
+ 		 * Chip Errata bug 6641; even and odd qwords>3 are swapped.
+ 		 */
+-		if (i > 3) {
+-			if (i & 1)
+-				val = dd->ipath_pioavailregs_dma[i - 1];
+-			else
+-				val = dd->ipath_pioavailregs_dma[i + 1];
+-		}
++		if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
++			val = dd->ipath_pioavailregs_dma[i ^ 1];
+ 		else
+ 			val = dd->ipath_pioavailregs_dma[i];
+ 		dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
+@@ -690,12 +672,13 @@ done:
+  */
+ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 maslave		= 0x40;
- 	int a_speed		= 3 << (drive->dn * 4);
- 	int u_flag		= 1 << drive->dn;
-@@ -101,24 +98,11 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	pci_read_config_byte(dev, 0x54, &reg54);
- 	pci_read_config_byte(dev, 0x55, &reg55);
+-	int ret = 0, i;
++	int ret = 0;
+ 	u32 val32, kpiobufs;
+ 	u32 piobufs, uports;
+ 	u64 val;
+ 	struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
+ 	gfp_t gfp_flags = GFP_USER | __GFP_COMP;
++	unsigned long flags;
  
--	switch(speed) {
--		case XFER_UDMA_6:
--		case XFER_UDMA_4:
--		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
--		case XFER_UDMA_5:
--		case XFER_UDMA_3:
--		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
--		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
--			break;
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_SW_DMA_2:
--			break;
--		default:
--			return;
--	}
--
- 	if (speed >= XFER_UDMA_0) {
-+		u8 udma = speed - XFER_UDMA_0;
-+
-+		u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
-+
- 		if (!(reg48 & u_flag))
- 			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
- 		if (speed >= XFER_UDMA_5) {
-@@ -156,6 +140,16 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	}
- }
+ 	ret = init_housekeeping(dd, &pd, reinit);
+ 	if (ret)
+@@ -746,7 +729,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 		kpiobufs = ipath_kpiobufs;
  
-+static u8 __devinit it8213_cable_detect(ide_hwif_t *hwif)
-+{
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	u8 reg42h = 0;
-+
-+	pci_read_config_byte(dev, 0x42, &reg42h);
-+
-+	return (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-+}
+ 	if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) {
+-		i = (int) piobufs -
++		int i = (int) piobufs -
+ 			(int) (uports * IPATH_MIN_USER_PORT_BUFCNT);
+ 		if (i < 0)
+ 			i = 0;
+@@ -827,8 +810,12 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
+ 			 ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
+-	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-			 INFINIPATH_S_PIOENABLE);
 +
- /**
-  *	init_hwif_it8213	-	set up hwif structs
-  *	@hwif: interface to set up
-@@ -165,18 +159,10 @@ static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE;
++	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
  
- static void __devinit init_hwif_it8213(ide_hwif_t *hwif)
+ 	/*
+ 	 * before error clears, since we expect serdes pll errors during
+diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
+index c61f9da..92e58c9 100644
+--- a/drivers/infiniband/hw/ipath/ipath_intr.c
++++ b/drivers/infiniband/hw/ipath/ipath_intr.c
+@@ -683,7 +683,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		for (i = 0; i < dd->ipath_cfgports; i++) {
+ 			struct ipath_portdata *pd = dd->ipath_pd[i];
+ 			if (i == 0) {
+-				hd = dd->ipath_port0head;
++				hd = pd->port_head;
+ 				tl = (u32) le64_to_cpu(
+ 					*dd->ipath_hdrqtailptr);
+ 			} else if (pd && pd->port_cnt &&
+@@ -693,7 +693,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 				 * except kernel
+ 				 */
+ 				tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
+-				if (tl == dd->ipath_lastrcvhdrqtails[i])
++				if (tl == pd->port_lastrcvhdrqtail)
+ 					continue;
+ 				hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
+ 						       i);
+@@ -703,7 +703,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 			    (!hd && tl == dd->ipath_hdrqlast)) {
+ 				if (i == 0)
+ 					chkerrpkts = 1;
+-				dd->ipath_lastrcvhdrqtails[i] = tl;
++				pd->port_lastrcvhdrqtail = tl;
+ 				pd->port_hdrqfull++;
+ 				/* flush hdrqfull so that poll() sees it */
+ 				wmb();
+@@ -712,6 +712,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		}
+ 	}
+ 	if (errs & INFINIPATH_E_RRCVEGRFULL) {
++		struct ipath_portdata *pd = dd->ipath_pd[0];
++
+ 		/*
+ 		 * since this is of less importance and not likely to
+ 		 * happen without also getting hdrfull, only count
+@@ -719,7 +721,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
+ 		 * vs user)
+ 		 */
+ 		ipath_stats.sps_etidfull++;
+-		if (dd->ipath_port0head !=
++		if (pd->port_head !=
+ 		    (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
+ 			chkerrpkts = 1;
+ 	}
+@@ -795,6 +797,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
  {
--	u8 reg42h = 0;
--
- 	hwif->set_dma_mode = &it8213_set_dma_mode;
- 	hwif->set_pio_mode = &it8213_set_pio_mode;
+ 	int i, im;
+ 	__le64 val;
++	unsigned long flags;
  
--	if (!hwif->dma_base)
--		return;
--
--	pci_read_config_byte(hwif->pci_dev, 0x42, &reg42h);
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = (reg42h & 0x02) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-+	hwif->cable_detect = it8213_cable_detect;
- }
+ 	/* disable error interrupts, to avoid confusion */
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
+@@ -813,11 +816,14 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
+ 			 dd->ipath_control);
  
+ 	/* ensure pio avail updates continue */
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ 		 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
+ 	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+-		 dd->ipath_sendctrl);
++			 dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
  
-diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
-index 99b7d76..1597f0c 100644
---- a/drivers/ide/pci/it821x.c
-+++ b/drivers/ide/pci/it821x.c
-@@ -1,7 +1,4 @@
--
- /*
-- * linux/drivers/ide/pci/it821x.c		Version 0.16	Jul 3 2007
-- *
-  * Copyright (C) 2004		Red Hat <alan at redhat.com>
-  * Copyright (C) 2007		Bartlomiej Zolnierkiewicz
-  *
-@@ -66,13 +63,10 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
+ 	/*
+ 	 * We just enabled pioavailupdate, so dma copy is almost certainly
+@@ -825,8 +831,8 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
+ 	 */
+ 	for (i = 0; i < dd->ipath_pioavregs; i++) {
+ 		/* deal with 6110 chip bug */
+-		im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
+-		val = ipath_read_kreg64(dd, (0x1000/sizeof(u64))+im);
++		im = i > 3 ? i ^ 1 : i;
++		val = ipath_read_kreg64(dd, (0x1000 / sizeof(u64)) + im);
+ 		dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
+ 			= le64_to_cpu(val);
+ 	}
+@@ -849,7 +855,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
  
--#include <asm/io.h>
--
- struct it821x_dev
- {
- 	unsigned int smart:1,		/* Are we in smart raid mode */
-@@ -113,7 +107,8 @@ static int it8212_noraid;
+ /* this is separate to allow for better optimization of ipath_intr() */
  
- static void it821x_program(ide_drive_t *drive, u16 timing)
+-static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
++static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp)
  {
--	ide_hwif_t *hwif	= drive->hwif;
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- 	int channel = hwif->channel;
- 	u8 conf;
-@@ -123,7 +118,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
- 		conf = timing >> 8;
- 	else
- 		conf = timing & 0xFF;
--	pci_write_config_byte(hwif->pci_dev, 0x54 + 4 * channel, conf);
-+
-+	pci_write_config_byte(dev, 0x54 + 4 * channel, conf);
+ 	/*
+ 	 * sometimes happen during driver init and unload, don't want
+@@ -877,7 +883,7 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
+ 				dd->ipath_f_free_irq(dd);
+ 			}
+ 		}
+-		if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
++		if (ipath_read_ireg(dd, dd->ipath_kregs->kr_intmask)) {
+ 			ipath_dev_err(dd, "%u unexpected interrupts, "
+ 				      "disabling interrupts completely\n",
+ 				      *unexpectp);
+@@ -892,7 +898,7 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
+ 			  "ignoring\n");
  }
  
- /**
-@@ -137,7 +133,8 @@ static void it821x_program(ide_drive_t *drive, u16 timing)
- 
- static void it821x_program_udma(ide_drive_t *drive, u16 timing)
+-static void ipath_bad_regread(struct ipath_devdata *dd)
++static noinline void ipath_bad_regread(struct ipath_devdata *dd)
  {
--	ide_hwif_t *hwif	= drive->hwif;
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- 	int channel = hwif->channel;
- 	int unit = drive->select.b.unit;
-@@ -148,11 +145,12 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
- 		conf = timing >> 8;
- 	else
- 		conf = timing & 0xFF;
--	if(itdev->timing10 == 0)
--		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + unit, conf);
-+
-+	if (itdev->timing10 == 0)
-+		pci_write_config_byte(dev, 0x56 + 4 * channel + unit, conf);
- 	else {
--		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel, conf);
--		pci_write_config_byte(hwif->pci_dev, 0x56 + 4 * channel + 1, conf);
-+		pci_write_config_byte(dev, 0x56 + 4 * channel, conf);
-+		pci_write_config_byte(dev, 0x56 + 4 * channel + 1, conf);
+ 	static int allbits;
+ 
+@@ -920,31 +926,9 @@ static void ipath_bad_regread(struct ipath_devdata *dd)
  	}
  }
  
-@@ -167,6 +165,7 @@ static void it821x_program_udma(ide_drive_t *drive, u16 timing)
- static void it821x_clock_strategy(ide_drive_t *drive)
+-static void handle_port_pioavail(struct ipath_devdata *dd)
+-{
+-	u32 i;
+-	/*
+-	 * start from port 1, since for now port 0  is never using
+-	 * wait_event for PIO
+-	 */
+-	for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
+-		struct ipath_portdata *pd = dd->ipath_pd[i];
+-
+-		if (pd && pd->port_cnt &&
+-		    dd->ipath_portpiowait & (1U << i)) {
+-			clear_bit(i, &dd->ipath_portpiowait);
+-			if (test_bit(IPATH_PORT_WAITING_PIO,
+-				     &pd->port_flag)) {
+-				clear_bit(IPATH_PORT_WAITING_PIO,
+-					  &pd->port_flag);
+-				wake_up_interruptible(&pd->port_wait);
+-			}
+-		}
+-	}
+-}
+-
+ static void handle_layer_pioavail(struct ipath_devdata *dd)
  {
- 	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
++	unsigned long flags;
+ 	int ret;
  
- 	u8 unit = drive->select.b.unit;
-@@ -205,10 +204,11 @@ static void it821x_clock_strategy(ide_drive_t *drive)
- 		itdev->clock_mode = ATA_50;
- 		sel = 1;
- 	}
--	pci_read_config_byte(hwif->pci_dev, 0x50, &v);
-+
-+	pci_read_config_byte(dev, 0x50, &v);
- 	v &= ~(1 << (1 + hwif->channel));
- 	v |= sel << (1 + hwif->channel);
--	pci_write_config_byte(hwif->pci_dev, 0x50, v);
-+	pci_write_config_byte(dev, 0x50, v);
+ 	ret = ipath_ib_piobufavail(dd->verbs_dev);
+@@ -953,9 +937,12 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
  
- 	/*
- 	 *	Reprogram the UDMA/PIO of the pair drive for the switch
-@@ -282,7 +282,8 @@ static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
+ 	return;
+ set:
+-	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ 			 dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ }
  
- static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
- {
--	ide_hwif_t *hwif	= drive->hwif;
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct it821x_dev *itdev = (void *)ide_get_hwifdata(hwif);
- 	int unit = drive->select.b.unit;
- 	int channel = hwif->channel;
-@@ -297,12 +298,12 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
- 	itdev->udma[unit] = UDMA_OFF;
+ /*
+@@ -969,7 +956,15 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ 	int i;
+ 	int rcvdint = 0;
  
- 	/* UDMA bits off - Revision 0x10 do them in pairs */
--	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
--	if(itdev->timing10)
-+	pci_read_config_byte(dev, 0x50, &conf);
-+	if (itdev->timing10)
- 		conf |= channel ? 0x60: 0x18;
- 	else
- 		conf |= 1 << (3 + 2 * channel + unit);
--	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
-+	pci_write_config_byte(dev, 0x50, conf);
+-	/* test_bit below needs this... */
++	/*
++	 * test_and_clear_bit(IPATH_PORT_WAITING_RCV) and
++	 * test_and_clear_bit(IPATH_PORT_WAITING_URG) below
++	 * would both like timely updates of the bits so that
++	 * we don't pass them by unnecessarily.  the rmb()
++	 * here ensures that we see them promptly -- the
++	 * corresponding wmb()'s are in ipath_poll_urgent()
++	 * and ipath_poll_next()...
++	 */
+ 	rmb();
+ 	portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
+ 		 dd->ipath_i_rcvavail_mask)
+@@ -980,7 +975,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
+ 		if (portr & (1 << i) && pd && pd->port_cnt) {
+ 			if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
+ 					       &pd->port_flag)) {
+-				clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
++				clear_bit(i + dd->ipath_r_intravail_shift,
+ 					  &dd->ipath_rcvctrl);
+ 				wake_up_interruptible(&pd->port_wait);
+ 				rcvdint = 1;
+@@ -1039,7 +1034,7 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 		goto bail;
+ 	}
  
- 	it821x_clock_strategy(drive);
- 	/* FIXME: do we need to program this ? */
-@@ -320,7 +321,8 @@ static void it821x_tune_mwdma (ide_drive_t *drive, byte mode_wanted)
+-	istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
++	istat = ipath_read_ireg(dd, dd->ipath_kregs->kr_intstatus);
  
- static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
- {
--	ide_hwif_t *hwif	= drive->hwif;
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
- 	int unit = drive->select.b.unit;
- 	int channel = hwif->channel;
-@@ -337,12 +339,12 @@ static void it821x_tune_udma (ide_drive_t *drive, byte mode_wanted)
- 		itdev->udma[unit] |= 0x8080;	/* UDMA 5/6 select on */
+ 	if (unlikely(!istat)) {
+ 		ipath_stats.sps_nullintr++;
+@@ -1180,7 +1175,7 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 	 * for receive are at the bottom.
+ 	 */
+ 	if (chk0rcv) {
+-		ipath_kreceive(dd);
++		ipath_kreceive(dd->ipath_pd[0]);
+ 		istat &= ~port0rbits;
+ 	}
  
- 	/* UDMA on. Again revision 0x10 must do the pair */
--	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
--	if(itdev->timing10)
-+	pci_read_config_byte(dev, 0x50, &conf);
-+	if (itdev->timing10)
- 		conf &= channel ? 0x9F: 0xE7;
- 	else
- 		conf &= ~ (1 << (3 + 2 * channel + unit));
--	pci_write_config_byte(hwif->pci_dev, 0x50, conf);
-+	pci_write_config_byte(dev, 0x50, conf);
+@@ -1191,12 +1186,14 @@ irqreturn_t ipath_intr(int irq, void *data)
+ 		handle_urcv(dd, istat);
  
- 	it821x_clock_strategy(drive);
- 	it821x_program_udma(drive, itdev->udma[unit]);
-@@ -431,33 +433,29 @@ static u8 __devinit ata66_it821x(ide_hwif_t *hwif)
- }
+ 	if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
+-		clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
++		unsigned long flags;
++
++		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++		dd->ipath_sendctrl &= ~INFINIPATH_S_PIOINTBUFAVAIL;
+ 		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ 				 dd->ipath_sendctrl);
+-
+-		if (dd->ipath_portpiowait)
+-			handle_port_pioavail(dd);
++		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
  
- /**
-- *	it821x_fixup	-	post init callback
-- *	@hwif: interface
-+ *	it821x_quirkproc	-	post init callback
-+ *	@drive: drive
-  *
-- *	This callback is run after the drives have been probed but
-+ *	This callback is run after the drive has been probed but
-  *	before anything gets attached. It allows drivers to do any
-  *	final tuning that is needed, or fixups to work around bugs.
-  */
+ 		handle_layer_pioavail(dd);
+ 	}
+diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
+index 8786dd7..4cc0f95 100644
+--- a/drivers/infiniband/hw/ipath/ipath_kernel.h
++++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
+@@ -41,6 +41,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
+ #include <linux/dma-mapping.h>
++#include <linux/mutex.h>
+ #include <asm/io.h>
+ #include <rdma/ib_verbs.h>
  
--static void __devinit it821x_fixups(ide_hwif_t *hwif)
-+static void __devinit it821x_quirkproc(ide_drive_t *drive)
- {
--	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
--	int i;
-+	struct it821x_dev *itdev = ide_get_hwifdata(drive->hwif);
-+	struct hd_driveid *id = drive->id;
-+	u16 *idbits = (u16 *)drive->id;
+@@ -140,6 +141,11 @@ struct ipath_portdata {
+ 	u32 port_pionowait;
+ 	/* total number of rcvhdrqfull errors */
+ 	u32 port_hdrqfull;
++	/*
++	 * Used to suppress multiple instances of same
++	 * port staying stuck at same point.
++	 */
++	u32 port_lastrcvhdrqtail;
+ 	/* saved total number of rcvhdrqfull errors for poll edge trigger */
+ 	u32 port_hdrqfull_poll;
+ 	/* total number of polled urgent packets */
+@@ -148,6 +154,7 @@ struct ipath_portdata {
+ 	u32 port_urgent_poll;
+ 	/* pid of process using this port */
+ 	pid_t port_pid;
++	pid_t port_subpid[INFINIPATH_MAX_SUBPORT];
+ 	/* same size as task_struct .comm[] */
+ 	char port_comm[16];
+ 	/* pkeys set by this use of this port */
+@@ -166,6 +173,8 @@ struct ipath_portdata {
+ 	u32 active_slaves;
+ 	/* Type of packets or conditions we want to poll for */
+ 	u16 poll_type;
++	/* port rcvhdrq head offset */
++	u32 port_head;
+ };
  
--	if(!itdev->smart) {
-+	if (!itdev->smart) {
- 		/*
- 		 *	If we are in pass through mode then not much
- 		 *	needs to be done, but we do bother to clear the
- 		 *	IRQ mask as we may well be in PIO (eg rev 0x10)
- 		 *	for now and we know unmasking is safe on this chipset.
- 		 */
--		for (i = 0; i < 2; i++) {
--			ide_drive_t *drive = &hwif->drives[i];
--			if(drive->present)
--				drive->unmask = 1;
--		}
--		return;
--	}
-+		drive->unmask = 1;
-+	} else {
- 	/*
- 	 *	Perform fixups on smart mode. We need to "lose" some
- 	 *	capabilities the firmware lacks but does not filter, and
-@@ -465,16 +463,6 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
- 	 *	in RAID mode.
+ struct sk_buff;
+@@ -182,6 +191,22 @@ struct ipath_skbinfo {
+ 	dma_addr_t phys;
+ };
+ 
++/*
++ * Possible IB config parameters for ipath_f_get/set_ib_cfg()
++ */
++#define IPATH_IB_CFG_LIDLMC 0 /* Get/set LID (LS16b) and Mask (MS16b) */
++#define IPATH_IB_CFG_HRTBT 1 /* Get/set Heartbeat off/enable/auto */
++#define IPATH_IB_HRTBT_ON 3 /* Heartbeat enabled, sent every 100msec */
++#define IPATH_IB_HRTBT_OFF 0 /* Heartbeat off */
++#define IPATH_IB_CFG_LWID_ENB 2 /* Get/set allowed Link-width */
++#define IPATH_IB_CFG_LWID 3 /* Get currently active Link-width */
++#define IPATH_IB_CFG_SPD_ENB 4 /* Get/set allowed Link speeds */
++#define IPATH_IB_CFG_SPD 5 /* Get current Link spd */
++#define IPATH_IB_CFG_RXPOL_ENB 6 /* Get/set Auto-RX-polarity enable */
++#define IPATH_IB_CFG_LREV_ENB 7 /* Get/set Auto-Lane-reversal enable */
++#define IPATH_IB_CFG_LINKLATENCY 8 /* Get Auto-Lane-reversal enable */
++
++
+ struct ipath_devdata {
+ 	struct list_head ipath_list;
+ 
+@@ -222,6 +247,8 @@ struct ipath_devdata {
+ 	struct _ipath_layer ipath_layer;
+ 	/* setup intr */
+ 	int (*ipath_f_intrsetup)(struct ipath_devdata *);
++	/* fallback to alternate interrupt type if possible */
++	int (*ipath_f_intr_fallback)(struct ipath_devdata *);
+ 	/* setup on-chip bus config */
+ 	int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
+ 	/* hard reset chip */
+@@ -244,6 +271,18 @@ struct ipath_devdata {
+ 	int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
+ 	/* free irq */
+ 	void (*ipath_f_free_irq)(struct ipath_devdata *);
++	struct ipath_message_header *(*ipath_f_get_msgheader)
++					(struct ipath_devdata *, __le32 *);
++	void (*ipath_f_config_ports)(struct ipath_devdata *, ushort);
++	int (*ipath_f_get_ib_cfg)(struct ipath_devdata *, int);
++	int (*ipath_f_set_ib_cfg)(struct ipath_devdata *, int, u32);
++	void (*ipath_f_config_jint)(struct ipath_devdata *, u16 , u16);
++	void (*ipath_f_read_counters)(struct ipath_devdata *,
++					struct infinipath_counters *);
++	void (*ipath_f_xgxs_reset)(struct ipath_devdata *);
++	/* per chip actions needed for IB Link up/down changes */
++	int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
++
+ 	struct ipath_ibdev *verbs_dev;
+ 	struct timer_list verbs_timer;
+ 	/* total dwords sent (summed from counter) */
+@@ -313,22 +352,12 @@ struct ipath_devdata {
+ 	 * supports, less gives more pio bufs/port, etc.
  	 */
+ 	u32 ipath_cfgports;
+-	/* port0 rcvhdrq head offset */
+-	u32 ipath_port0head;
+ 	/* count of port 0 hdrqfull errors */
+ 	u32 ipath_p0_hdrqfull;
++	/* port 0 number of receive eager buffers */
++	u32 ipath_p0_rcvegrcnt;
  
--	for(i = 0; i < 2; i++) {
--		ide_drive_t *drive = &hwif->drives[i];
--		struct hd_driveid *id;
--		u16 *idbits;
--
--		if(!drive->present)
--			continue;
--		id = drive->id;
--		idbits = (u16 *)drive->id;
--
- 		/* Check for RAID v native */
- 		if(strstr(id->model, "Integrated Technology Express")) {
- 			/* In raid mode the ident block is slightly buggy
-@@ -534,9 +522,12 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
+ 	/*
+-	 * (*cfgports) used to suppress multiple instances of same
+-	 * port staying stuck at same point
+-	 */
+-	u32 *ipath_lastrcvhdrqtails;
+-	/*
+-	 * (*cfgports) used to suppress multiple instances of same
+-	 * port staying stuck at same point
+-	 */
+-	u32 *ipath_lastegrheads;
+-	/*
+ 	 * index of last piobuffer we used.  Speeds up searching, by
+ 	 * starting at this point.  Doesn't matter if multiple cpu's use and
+ 	 * update, last updater is only write that matters.  Whenever it
+@@ -367,14 +396,15 @@ struct ipath_devdata {
+ 	unsigned long ipath_wc_len;
+ 	/* ref count for each pkey */
+ 	atomic_t ipath_pkeyrefs[4];
+-	/* shadow copy of all exptids physaddr; used only by funcsim */
+-	u64 *ipath_tidsimshadow;
+ 	/* shadow copy of struct page *'s for exp tid pages */
+ 	struct page **ipath_pageshadow;
+ 	/* shadow copy of dma handles for exp tid pages */
+ 	dma_addr_t *ipath_physshadow;
+-	/* lock to workaround chip bug 9437 */
++	u64 __iomem *ipath_egrtidbase;
++	/* lock to workaround chip bug 9437 and others */
++	spinlock_t ipath_kernel_tid_lock;
+ 	spinlock_t ipath_tid_lock;
++	spinlock_t ipath_sendctrl_lock;
  
- static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct it821x_dev *idev = kzalloc(sizeof(struct it821x_dev), GFP_KERNEL);
- 	u8 conf;
+ 	/*
+ 	 * IPATH_STATUS_*,
+@@ -395,6 +425,8 @@ struct ipath_devdata {
+ 	void *ipath_dummy_hdrq;	/* used after port close */
+ 	dma_addr_t ipath_dummy_hdrq_phys;
  
-+	hwif->quirkproc = &it821x_quirkproc;
++	unsigned long ipath_ureg_align; /* user register alignment */
 +
- 	if (idev == NULL) {
- 		printk(KERN_ERR "it821x: out of memory, falling back to legacy behaviour.\n");
- 		return;
-@@ -544,7 +535,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
+ 	/*
+ 	 * Shadow copies of registers; size indicates read access size.
+ 	 * Most of them are readonly, but some are write-only register,
+@@ -456,8 +488,6 @@ struct ipath_devdata {
+ 	unsigned long ipath_rcvctrl;
+ 	/* shadow kr_sendctrl */
+ 	unsigned long ipath_sendctrl;
+-	/* ports waiting for PIOavail intr */
+-	unsigned long ipath_portpiowait;
+ 	unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
  
- 	ide_set_hwifdata(hwif, idev);
+ 	/* value we put in kr_rcvhdrcnt */
+@@ -550,12 +580,26 @@ struct ipath_devdata {
+ 	u8 ipath_minrev;
+ 	/* board rev, from ipath_revision */
+ 	u8 ipath_boardrev;
++
++	u8 ipath_r_portenable_shift;
++	u8 ipath_r_intravail_shift;
++	u8 ipath_r_tailupd_shift;
++	u8 ipath_r_portcfg_shift;
++
+ 	/* unit # of this chip, if present */
+ 	int ipath_unit;
+ 	/* saved for restore after reset */
+ 	u8 ipath_pci_cacheline;
+ 	/* LID mask control */
+ 	u8 ipath_lmc;
++	/* link width supported */
++	u8 ipath_link_width_supported;
++	/* link speed supported */
++	u8 ipath_link_speed_supported;
++	u8 ipath_link_width_enabled;
++	u8 ipath_link_speed_enabled;
++	u8 ipath_link_width_active;
++	u8 ipath_link_speed_active;
+ 	/* Rx Polarity inversion (compensate for ~tx on partner) */
+ 	u8 ipath_rx_pol_inv;
  
--	pci_read_config_byte(hwif->pci_dev, 0x50, &conf);
-+	pci_read_config_byte(dev, 0x50, &conf);
- 	if (conf & 1) {
- 		idev->smart = 1;
- 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
-@@ -567,7 +558,7 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
- 	 *	this is necessary.
+@@ -590,6 +634,8 @@ struct ipath_devdata {
  	 */
+ 	u32 ipath_i_rcvavail_mask;
+ 	u32 ipath_i_rcvurg_mask;
++	u16 ipath_i_rcvurg_shift;
++	u16 ipath_i_rcvavail_shift;
  
--	pci_read_config_byte(hwif->pci_dev, 0x08, &conf);
-+	pci_read_config_byte(dev, 0x08, &conf);
- 	if (conf == 0x10) {
- 		idev->timing10 = 1;
- 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
-@@ -585,14 +576,13 @@ static void __devinit init_hwif_it821x(ide_hwif_t *hwif)
- 	} else
- 		hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
+ 	/*
+ 	 * Register bits for selecting i2c direction and values, used for
+@@ -603,6 +649,29 @@ struct ipath_devdata {
+ 	/* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
+ 	spinlock_t ipath_gpio_lock;
  
-+	hwif->cable_detect = ata66_it821x;
++	/*
++	 * IB link and linktraining states and masks that vary per chip in
++	 * some way.  Set at init, to avoid each IB status change interrupt
++	 */
++	u8 ibcs_ls_shift;
++	u8 ibcs_lts_mask;
++	u32 ibcs_mask;
++	u32 ib_init;
++	u32 ib_arm;
++	u32 ib_active;
 +
- 	if (hwif->dma_base == 0)
- 		return;
++	u16 ipath_rhf_offset; /* offset of RHF within receive header entry */
++
++	/*
++	 * shift/mask for linkcmd, linkinitcmd, maxpktlen in ibccontol
++	 * reg. Changes for IBA7220
++	 */
++	u8 ibcc_lic_mask; /* LinkInitCmd */
++	u8 ibcc_lc_shift; /* LinkCmd */
++	u8 ibcc_mpl_shift; /* Maxpktlen */
++
++	u8 delay_mult;
++
+ 	/* used to override LED behavior */
+ 	u8 ipath_led_override;  /* Substituted for normal value, if non-zero */
+ 	u16 ipath_led_override_timeoff; /* delta to next timer event */
+@@ -616,7 +685,7 @@ struct ipath_devdata {
+ 	/* control access to actual counters, timer */
+ 	spinlock_t ipath_eep_st_lock;
+ 	/* control high-level access to EEPROM */
+-	struct semaphore ipath_eep_sem;
++	struct mutex ipath_eep_lock;
+ 	/* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
+ 	uint64_t ipath_traffic_wds;
+ 	/* active time is kept in seconds, but logged in hours */
+@@ -630,6 +699,10 @@ struct ipath_devdata {
+ 	 * each of the counters to increment.
+ 	 */
+ 	struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
++
++	/* interrupt mitigation reload register info */
++	u16 ipath_jint_idle_ticks;	/* idle clock ticks */
++	u16 ipath_jint_max_packets;	/* max packets across all ports */
+ };
  
- 	hwif->ultra_mask = ATA_UDMA6;
- 	hwif->mwdma_mask = ATA_MWDMA2;
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = ata66_it821x(hwif);
- }
+ /* Private data for file operations */
+@@ -690,7 +763,7 @@ void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
  
- static void __devinit it8212_disable_raid(struct pci_dev *dev)
-@@ -633,7 +623,6 @@ static unsigned int __devinit init_chipset_it821x(struct pci_dev *dev, const cha
- 		.name		= name_str,		\
- 		.init_chipset	= init_chipset_it821x,	\
- 		.init_hwif	= init_hwif_it821x,	\
--		.fixup	 	= it821x_fixups,	\
- 		.host_flags	= IDE_HFLAG_BOOTABLE,	\
- 		.pio_mask	= ATA_PIO4,		\
- 	}
-diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
-index 0083eaf..a56bcb4 100644
---- a/drivers/ide/pci/jmicron.c
-+++ b/drivers/ide/pci/jmicron.c
-@@ -8,13 +8,10 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
+ int ipath_parse_ushort(const char *str, unsigned short *valp);
  
--#include <asm/io.h>
--
- typedef enum {
- 	PORT_PATA0 = 0,
- 	PORT_PATA1 = 1,
-@@ -30,7 +27,7 @@ typedef enum {
+-void ipath_kreceive(struct ipath_devdata *);
++void ipath_kreceive(struct ipath_portdata *);
+ int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
+ int ipath_reset_device(int);
+ void ipath_get_faststats(unsigned long);
+@@ -698,6 +771,8 @@ int ipath_set_linkstate(struct ipath_devdata *, u8);
+ int ipath_set_mtu(struct ipath_devdata *, u16);
+ int ipath_set_lid(struct ipath_devdata *, u32, u8);
+ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
++void ipath_enable_armlaunch(struct ipath_devdata *);
++void ipath_disable_armlaunch(struct ipath_devdata *);
  
- static u8 __devinit ata66_jmicron(ide_hwif_t *hwif)
- {
--	struct pci_dev *pdev = hwif->pci_dev;
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
+ /* for use in system calls, where we want to know device type, etc. */
+ #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
+@@ -744,9 +819,15 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
+ 		 * are 64bit */
+ #define IPATH_32BITCOUNTERS 0x20000
+ 		/* can miss port0 rx interrupts */
++		/* Interrupt register is 64 bits */
++#define IPATH_INTREG_64     0x40000
+ #define IPATH_DISABLED      0x80000 /* administratively disabled */
+ 		/* Use GPIO interrupts for new counters */
+ #define IPATH_GPIO_ERRINTRS 0x100000
++#define IPATH_SWAP_PIOBUFS  0x200000
++		/* Suppress heartbeat, even if turning off loopback */
++#define IPATH_NO_HRTBT      0x1000000
++#define IPATH_HAS_MULT_IB_SPEED 0x8000000
  
- 	u32 control;
- 	u32 control5;
-@@ -111,11 +108,7 @@ static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
- 	hwif->set_pio_mode = &jmicron_set_pio_mode;
- 	hwif->set_dma_mode = &jmicron_set_dma_mode;
+ /* Bits in GPIO for the added interrupts */
+ #define IPATH_GPIO_PORT0_BIT 2
+@@ -758,8 +839,6 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
+ /* portdata flag bit offsets */
+ 		/* waiting for a packet to arrive */
+ #define IPATH_PORT_WAITING_RCV   2
+-		/* waiting for a PIO buffer to be available */
+-#define IPATH_PORT_WAITING_PIO   3
+ 		/* master has not finished initializing */
+ #define IPATH_PORT_MASTER_UNINIT 4
+ 		/* waiting for an urgent packet to arrive */
+@@ -767,8 +846,6 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
  
--	if (hwif->dma_base == 0)
--		return;
+ /* free up any allocated data at closes */
+ void ipath_free_data(struct ipath_portdata *dd);
+-int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
+-int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
+ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
+ void ipath_init_iba6120_funcs(struct ipath_devdata *);
+ void ipath_init_iba6110_funcs(struct ipath_devdata *);
+@@ -792,33 +869,6 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
+  */
+ #define IPATH_DFLT_RCVHDRSIZE 9
+ 
+-#define IPATH_MDIO_CMD_WRITE   1
+-#define IPATH_MDIO_CMD_READ    2
+-#define IPATH_MDIO_CLD_DIV     25	/* to get 2.5 Mhz mdio clock */
+-#define IPATH_MDIO_CMDVALID    0x40000000	/* bit 30 */
+-#define IPATH_MDIO_DATAVALID   0x80000000	/* bit 31 */
+-#define IPATH_MDIO_CTRL_STD    0x0
 -
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = ata66_jmicron(hwif);
-+	hwif->cable_detect = ata66_jmicron;
+-static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
+-{
+-	return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
+-		(cmd << 26) |
+-		(dev << 21) |
+-		(reg << 16) |
+-		(data & 0xFFFF);
+-}
+-
+-		/* signal and fifo status, in bank 31 */
+-#define IPATH_MDIO_CTRL_XGXS_REG_8  0x8
+-		/* controls loopback, redundancy */
+-#define IPATH_MDIO_CTRL_8355_REG_1  0x10
+-		/* premph, encdec, etc. */
+-#define IPATH_MDIO_CTRL_8355_REG_2  0x11
+-		/* Kchars, etc. */
+-#define IPATH_MDIO_CTRL_8355_REG_6  0x15
+-#define IPATH_MDIO_CTRL_8355_REG_9  0x18
+-#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
+-
+ int ipath_get_user_pages(unsigned long, size_t, struct page **);
+ void ipath_release_user_pages(struct page **, size_t);
+ void ipath_release_user_pages_on_close(struct page **, size_t);
+@@ -863,7 +913,7 @@ static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
+ 	return readl(regno + (u64 __iomem *)
+ 		     (dd->ipath_uregbase +
+ 		      (char __iomem *)dd->ipath_kregbase +
+-		      dd->ipath_palign * port));
++		      dd->ipath_ureg_align * port));
  }
  
- static const struct ide_port_info jmicron_chipset __devinitdata = {
-diff --git a/drivers/ide/pci/ns87415.c b/drivers/ide/pci/ns87415.c
-index d4df464..bf0d3b2 100644
---- a/drivers/ide/pci/ns87415.c
-+++ b/drivers/ide/pci/ns87415.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/ns87415.c		Version 2.00  Sep. 10, 2002
-- *
-  * Copyright (C) 1997-1998	Mark Lord <mlord at pobox.com>
-  * Copyright (C) 1998		Eddie C. Dost <ecd at skynet.be>
-  * Copyright (C) 1999-2000	Andre Hedrick <andre at linux-ide.org>
-@@ -12,11 +10,7 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
- #include <linux/interrupt.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/pci.h>
- #include <linux/delay.h>
-@@ -71,10 +65,9 @@ static u8 superio_ide_inb (unsigned long port)
- 
- static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
- {
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
- 	u32 base, dmabase;
--	u8 tmp;
--	struct pci_dev *pdev = hwif->pci_dev;
--	u8 port = hwif->channel;
-+	u8 port = hwif->channel, tmp;
- 
- 	base = pci_resource_start(pdev, port * 2) & ~3;
- 	dmabase = pci_resource_start(pdev, 4) & ~3;
-@@ -93,10 +86,11 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
- 
- static void __devinit init_iops_ns87415(ide_hwif_t *hwif)
+ /**
+@@ -880,7 +930,7 @@ static inline void ipath_write_ureg(const struct ipath_devdata *dd,
  {
--	if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+
-+	if (PCI_SLOT(dev->devfn) == 0xE)
- 		/* Built-in - assume it's under superio. */
- 		superio_ide_init_iops(hwif);
--	}
+ 	u64 __iomem *ubase = (u64 __iomem *)
+ 		(dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
+-		 dd->ipath_palign * port);
++		 dd->ipath_ureg_align * port);
+ 	if (dd->ipath_kregbase)
+ 		writeq(value, &ubase[regno]);
  }
- #endif
- 
-@@ -110,8 +104,8 @@ static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
- static void ns87415_prepare_drive (ide_drive_t *drive, unsigned int use_dma)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	unsigned int bit, other, new, *old = (unsigned int *) hwif->select_data;
--	struct pci_dev *dev = hwif->pci_dev;
- 	unsigned long flags;
- 
- 	local_irq_save(flags);
-@@ -189,7 +183,7 @@ static int ns87415_ide_dma_setup(ide_drive_t *drive)
- 
- static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
- {
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	unsigned int ctrl, using_inta;
- 	u8 progif;
- #ifdef __sparc_v9__
-@@ -231,8 +225,8 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif)
- 
- #ifdef __sparc_v9__
- 		/*
--		 * XXX: Reset the device, if we don't it will not respond
--		 *      to SELECT_DRIVE() properly during first probe_hwif().
-+		 * XXX: Reset the device, if we don't it will not respond to
-+		 *      SELECT_DRIVE() properly during first ide_probe_port().
- 		 */
- 		timeout = 10000;
- 		outb(12, hwif->io_ports[IDE_CONTROL_OFFSET]);
-diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c
-index 8953d9c..46e8748 100644
---- a/drivers/ide/pci/opti621.c
-+++ b/drivers/ide/pci/opti621.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/opti621.c		Version 0.9	Sep 24, 2007
-- *
-  *  Copyright (C) 1996-1998  Linus Torvalds & authors (see below)
-  */
- 
-@@ -89,11 +87,6 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/pci.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
-@@ -322,14 +315,18 @@ static void opti621_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	spin_unlock_irqrestore(&opti621_lock, flags);
+@@ -930,6 +980,53 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
+ 		      (char __iomem *)dd->ipath_kregbase));
  }
  
-+static void __devinit opti621_port_init_devs(ide_hwif_t *hwif)
++static inline void ipath_write_creg(const struct ipath_devdata *dd,
++				    ipath_creg regno, u64 value)
 +{
-+	hwif->drives[0].drive_data = PIO_DONT_KNOW;
-+	hwif->drives[1].drive_data = PIO_DONT_KNOW;
++	if (dd->ipath_kregbase)
++		writeq(value, regno + (u64 __iomem *)
++		       (dd->ipath_cregbase +
++			(char __iomem *)dd->ipath_kregbase));
++}
++
++static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd)
++{
++	*((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL;
++}
++
++static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
++{
++	return (u32) le64_to_cpu(*((volatile __le64 *)
++				pd->port_rcvhdrtail_kvaddr));
++}
++
++static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
++{
++	return (dd->ipath_flags & IPATH_INTREG_64) ?
++		ipath_read_kreg64(dd, r) : ipath_read_kreg32(dd, r);
++}
++
++/*
++ * from contents of IBCStatus (or a saved copy), return linkstate
++ * Report ACTIVE_DEFER as ACTIVE, because we treat them the same
++ * everywhere, anyway (and should be, for almost all purposes).
++ */
++static inline u32 ipath_ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
++{
++	u32 state = (u32)(ibcs >> dd->ibcs_ls_shift) &
++		INFINIPATH_IBCS_LINKSTATE_MASK;
++	if (state == INFINIPATH_IBCS_L_STATE_ACT_DEFER)
++		state = INFINIPATH_IBCS_L_STATE_ACTIVE;
++	return state;
++}
++
++/* from contents of IBCStatus (or a saved copy), return linktrainingstate */
++static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
++{
++	return (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
++		dd->ibcs_lts_mask;
 +}
 +
  /*
-  * init_hwif_opti621() is called once for each hwif found at boot.
+  * sysfs interface.
   */
- static void __devinit init_hwif_opti621 (ide_hwif_t *hwif)
- {
--	hwif->drives[0].drive_data = PIO_DONT_KNOW;
--	hwif->drives[1].drive_data = PIO_DONT_KNOW;
--
-+	hwif->port_init_devs = opti621_port_init_devs;
- 	hwif->set_pio_mode = &opti621_set_pio_mode;
- }
- 
-diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
-index 2b4f44e..1c8cb77 100644
---- a/drivers/ide/pci/pdc202xx_new.c
-+++ b/drivers/ide/pci/pdc202xx_new.c
-@@ -19,18 +19,12 @@
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
--#include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
+@@ -938,8 +1035,7 @@ struct device_driver;
  
- #include <asm/io.h>
--#include <asm/irq.h>
+ extern const char ib_ipath_version[];
  
- #ifdef CONFIG_PPC_PMAC
- #include <asm/prom.h>
-@@ -146,9 +140,10 @@ static struct udma_timing {
- 	{ 0x1a, 0x01, 0xcb },	/* UDMA mode 6 */
- };
+-int ipath_driver_create_group(struct device_driver *);
+-void ipath_driver_remove_group(struct device_driver *);
++extern struct attribute_group *ipath_driver_attr_groups[];
  
--static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
-+static void pdcnew_set_dma_mode(ide_drive_t *drive, const u8 speed)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;
+ int ipath_device_create_group(struct device *, struct ipath_devdata *);
+ void ipath_device_remove_group(struct device *, struct ipath_devdata *);
+diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
+index 85a4aef..8f32b17 100644
+--- a/drivers/infiniband/hw/ipath/ipath_keys.c
++++ b/drivers/infiniband/hw/ipath/ipath_keys.c
+@@ -128,9 +128,8 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
+ 	int ret;
  
  	/*
-@@ -159,48 +154,21 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
- 	 * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
- 	 * chips, we must override the default register settings...
+-	 * We use LKEY == zero to mean a physical kmalloc() address.
+-	 * This is a bit of a hack since we rely on dma_map_single()
+-	 * being reversible by calling bus_to_virt().
++	 * We use LKEY == zero for kernel virtual addresses
++	 * (see ipath_get_dma_mr and ipath_dma.c).
  	 */
--	if (max_dma_rate(hwif->pci_dev) == 4) {
-+	if (max_dma_rate(dev) == 4) {
- 		u8 mode = speed & 0x07;
+ 	if (sge->lkey == 0) {
+ 		struct ipath_pd *pd = to_ipd(qp->ibqp.pd);
+diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
+index 3d1432d..d98d5f1 100644
+--- a/drivers/infiniband/hw/ipath/ipath_mad.c
++++ b/drivers/infiniband/hw/ipath/ipath_mad.c
+@@ -934,6 +934,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+ 	struct ib_pma_portsamplescontrol *p =
+ 		(struct ib_pma_portsamplescontrol *)pmp->data;
+ 	struct ipath_ibdev *dev = to_idev(ibdev);
++	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
+ 	unsigned long flags;
+ 	u8 port_select = p->port_select;
  
--		switch (speed) {
--			case XFER_UDMA_6:
--			case XFER_UDMA_5:
--			case XFER_UDMA_4:
--			case XFER_UDMA_3:
--			case XFER_UDMA_2:
--			case XFER_UDMA_1:
--			case XFER_UDMA_0:
--				set_indexed_reg(hwif, 0x10 + adj,
--						udma_timings[mode].reg10);
--				set_indexed_reg(hwif, 0x11 + adj,
--						udma_timings[mode].reg11);
--				set_indexed_reg(hwif, 0x12 + adj,
--						udma_timings[mode].reg12);
--				break;
--
--			case XFER_MW_DMA_2:
--			case XFER_MW_DMA_1:
--			case XFER_MW_DMA_0:
--				set_indexed_reg(hwif, 0x0e + adj,
--						mwdma_timings[mode].reg0e);
--				set_indexed_reg(hwif, 0x0f + adj,
--						mwdma_timings[mode].reg0f);
--				break;
--			case XFER_PIO_4:
--			case XFER_PIO_3:
--			case XFER_PIO_2:
--			case XFER_PIO_1:
--			case XFER_PIO_0:
--				set_indexed_reg(hwif, 0x0c + adj,
--						pio_timings[mode].reg0c);
--				set_indexed_reg(hwif, 0x0d + adj,
--						pio_timings[mode].reg0d);
--				set_indexed_reg(hwif, 0x13 + adj,
--						pio_timings[mode].reg13);
--				break;
--			default:
--				printk(KERN_ERR "pdc202xx_new: "
--				       "Unknown speed %d ignored\n", speed);
-+		if (speed >= XFER_UDMA_0) {
-+			set_indexed_reg(hwif, 0x10 + adj,
-+					udma_timings[mode].reg10);
-+			set_indexed_reg(hwif, 0x11 + adj,
-+					udma_timings[mode].reg11);
-+			set_indexed_reg(hwif, 0x12 + adj,
-+					udma_timings[mode].reg12);
-+		} else {
-+			set_indexed_reg(hwif, 0x0e + adj,
-+					mwdma_timings[mode].reg0e);
-+			set_indexed_reg(hwif, 0x0f + adj,
-+					mwdma_timings[mode].reg0f);
- 		}
- 	} else if (speed == XFER_UDMA_2) {
- 		/* Set tHOLD bit to 0 if using UDMA mode 2 */
-@@ -212,10 +180,18 @@ static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
+@@ -955,7 +956,10 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
+ 	p->counter_width = 4;	/* 32 bit counters */
+ 	p->counter_mask0_9 = COUNTER_MASK0_9;
+ 	spin_lock_irqsave(&dev->pending_lock, flags);
+-	p->sample_status = dev->pma_sample_status;
++	if (crp->cr_psstat)
++		p->sample_status = ipath_read_creg32(dev->dd, crp->cr_psstat);
++	else
++		p->sample_status = dev->pma_sample_status;
+ 	p->sample_start = cpu_to_be32(dev->pma_sample_start);
+ 	p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
+ 	p->tag = cpu_to_be16(dev->pma_tag);
+@@ -975,8 +979,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+ 	struct ib_pma_portsamplescontrol *p =
+ 		(struct ib_pma_portsamplescontrol *)pmp->data;
+ 	struct ipath_ibdev *dev = to_idev(ibdev);
++	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
+ 	unsigned long flags;
+-	u32 start;
++	u8 status;
+ 	int ret;
  
- static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
--	pdcnew_set_mode(drive, XFER_PIO_0 + pio);
-+	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	u8 adj = (drive->dn & 1) ? 0x08 : 0x00;
+ 	if (pmp->attr_mod != 0 ||
+@@ -986,59 +991,67 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
+ 		goto bail;
+ 	}
+ 
+-	start = be32_to_cpu(p->sample_start);
+-	if (start != 0) {
+-		spin_lock_irqsave(&dev->pending_lock, flags);
+-		if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
+-			dev->pma_sample_status =
+-				IB_PMA_SAMPLE_STATUS_STARTED;
+-			dev->pma_sample_start = start;
+-			dev->pma_sample_interval =
+-				be32_to_cpu(p->sample_interval);
+-			dev->pma_tag = be16_to_cpu(p->tag);
+-			if (p->counter_select[0])
+-				dev->pma_counter_select[0] =
+-					p->counter_select[0];
+-			if (p->counter_select[1])
+-				dev->pma_counter_select[1] =
+-					p->counter_select[1];
+-			if (p->counter_select[2])
+-				dev->pma_counter_select[2] =
+-					p->counter_select[2];
+-			if (p->counter_select[3])
+-				dev->pma_counter_select[3] =
+-					p->counter_select[3];
+-			if (p->counter_select[4])
+-				dev->pma_counter_select[4] =
+-					p->counter_select[4];
+-		}
+-		spin_unlock_irqrestore(&dev->pending_lock, flags);
++	spin_lock_irqsave(&dev->pending_lock, flags);
++	if (crp->cr_psstat)
++		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
++	else
++		status = dev->pma_sample_status;
++	if (status == IB_PMA_SAMPLE_STATUS_DONE) {
++		dev->pma_sample_start = be32_to_cpu(p->sample_start);
++		dev->pma_sample_interval = be32_to_cpu(p->sample_interval);
++		dev->pma_tag = be16_to_cpu(p->tag);
++		dev->pma_counter_select[0] = p->counter_select[0];
++		dev->pma_counter_select[1] = p->counter_select[1];
++		dev->pma_counter_select[2] = p->counter_select[2];
++		dev->pma_counter_select[3] = p->counter_select[3];
++		dev->pma_counter_select[4] = p->counter_select[4];
++		if (crp->cr_psstat) {
++			ipath_write_creg(dev->dd, crp->cr_psinterval,
++					 dev->pma_sample_interval);
++			ipath_write_creg(dev->dd, crp->cr_psstart,
++					 dev->pma_sample_start);
++		} else
++			dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED;
+ 	}
++	spin_unlock_irqrestore(&dev->pending_lock, flags);
 +
-+	if (max_dma_rate(dev) == 4) {
-+		set_indexed_reg(hwif, 0x0c + adj, pio_timings[pio].reg0c);
-+		set_indexed_reg(hwif, 0x0d + adj, pio_timings[pio].reg0d);
-+		set_indexed_reg(hwif, 0x13 + adj, pio_timings[pio].reg13);
-+	}
- }
+ 	ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
  
--static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
-+static u8 __devinit pdcnew_cable_detect(ide_hwif_t *hwif)
- {
- 	if (get_indexed_reg(hwif, 0x0b) & 0x04)
- 		return ATA_CBL_PATA40;
-@@ -223,14 +199,17 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
- 		return ATA_CBL_PATA80;
+ bail:
+ 	return ret;
  }
  
--static int pdcnew_quirkproc(ide_drive_t *drive)
-+static void pdcnew_quirkproc(ide_drive_t *drive)
+-static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
++static u64 get_counter(struct ipath_ibdev *dev,
++		       struct ipath_cregs const *crp,
++		       __be16 sel)
  {
- 	const char **list, *model = drive->id->model;
- 
- 	for (list = pdc_quirk_drives; *list != NULL; list++)
--		if (strstr(model, *list) != NULL)
--			return 2;
--	return 0;
-+		if (strstr(model, *list) != NULL) {
-+			drive->quirk_list = 2;
-+			return;
-+		}
-+
-+	drive->quirk_list = 0;
- }
+ 	u64 ret;
  
- static void pdcnew_reset(ide_drive_t *drive)
-@@ -466,16 +445,12 @@ static unsigned int __devinit init_chipset_pdcnew(struct pci_dev *dev, const cha
- static void __devinit init_hwif_pdc202new(ide_hwif_t *hwif)
- {
- 	hwif->set_pio_mode = &pdcnew_set_pio_mode;
--	hwif->set_dma_mode = &pdcnew_set_mode;
-+	hwif->set_dma_mode = &pdcnew_set_dma_mode;
+ 	switch (sel) {
+ 	case IB_PMA_PORT_XMIT_DATA:
+-		ret = dev->ipath_sword;
++		ret = (crp->cr_psxmitdatacount) ?
++			ipath_read_creg32(dev->dd, crp->cr_psxmitdatacount) :
++			dev->ipath_sword;
+ 		break;
+ 	case IB_PMA_PORT_RCV_DATA:
+-		ret = dev->ipath_rword;
++		ret = (crp->cr_psrcvdatacount) ?
++			ipath_read_creg32(dev->dd, crp->cr_psrcvdatacount) :
++			dev->ipath_rword;
+ 		break;
+ 	case IB_PMA_PORT_XMIT_PKTS:
+-		ret = dev->ipath_spkts;
++		ret = (crp->cr_psxmitpktscount) ?
++			ipath_read_creg32(dev->dd, crp->cr_psxmitpktscount) :
++			dev->ipath_spkts;
+ 		break;
+ 	case IB_PMA_PORT_RCV_PKTS:
+-		ret = dev->ipath_rpkts;
++		ret = (crp->cr_psrcvpktscount) ?
++			ipath_read_creg32(dev->dd, crp->cr_psrcvpktscount) :
++			dev->ipath_rpkts;
+ 		break;
+ 	case IB_PMA_PORT_XMIT_WAIT:
+-		ret = dev->ipath_xmit_wait;
++		ret = (crp->cr_psxmitwaitcount) ?
++			ipath_read_creg32(dev->dd, crp->cr_psxmitwaitcount) :
++			dev->ipath_xmit_wait;
+ 		break;
+ 	default:
+ 		ret = 0;
+@@ -1053,14 +1066,21 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
+ 	struct ib_pma_portsamplesresult *p =
+ 		(struct ib_pma_portsamplesresult *)pmp->data;
+ 	struct ipath_ibdev *dev = to_idev(ibdev);
++	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
++	u8 status;
+ 	int i;
  
- 	hwif->quirkproc = &pdcnew_quirkproc;
- 	hwif->resetproc = &pdcnew_reset;
+ 	memset(pmp->data, 0, sizeof(pmp->data));
+ 	p->tag = cpu_to_be16(dev->pma_tag);
+-	p->sample_status = cpu_to_be16(dev->pma_sample_status);
++	if (crp->cr_psstat)
++		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
++	else
++		status = dev->pma_sample_status;
++	p->sample_status = cpu_to_be16(status);
+ 	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+-		p->counter[i] = cpu_to_be32(
+-			get_counter(dev, dev->pma_counter_select[i]));
++		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
++		    cpu_to_be32(
++			get_counter(dev, crp, dev->pma_counter_select[i]));
  
--	if (hwif->dma_base == 0)
--		return;
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = pdcnew_cable_detect(hwif);
-+	hwif->cable_detect = pdcnew_cable_detect;
+ 	return reply((struct ib_smp *) pmp);
  }
+@@ -1071,16 +1091,23 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
+ 	struct ib_pma_portsamplesresult_ext *p =
+ 		(struct ib_pma_portsamplesresult_ext *)pmp->data;
+ 	struct ipath_ibdev *dev = to_idev(ibdev);
++	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
++	u8 status;
+ 	int i;
  
- static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev)
-diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
-index e09742e..da43297 100644
---- a/drivers/ide/pci/pdc202xx_old.c
-+++ b/drivers/ide/pci/pdc202xx_old.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/pdc202xx_old.c	Version 0.52	Aug 27, 2007
-- *
-  *  Copyright (C) 1998-2002		Andre Hedrick <andre at linux-ide.org>
-  *  Copyright (C) 2006-2007		MontaVista Software, Inc.
-  *  Copyright (C) 2007			Bartlomiej Zolnierkiewicz
-@@ -34,18 +32,13 @@
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
- #include <linux/blkdev.h>
- #include <linux/hdreg.h>
--#include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
- 
- #include <asm/io.h>
--#include <asm/irq.h>
+ 	memset(pmp->data, 0, sizeof(pmp->data));
+ 	p->tag = cpu_to_be16(dev->pma_tag);
+-	p->sample_status = cpu_to_be16(dev->pma_sample_status);
++	if (crp->cr_psstat)
++		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
++	else
++		status = dev->pma_sample_status;
++	p->sample_status = cpu_to_be16(status);
+ 	/* 64 bits */
+ 	p->extended_width = __constant_cpu_to_be32(0x80000000);
+ 	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
+-		p->counter[i] = cpu_to_be64(
+-			get_counter(dev, dev->pma_counter_select[i]));
++		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
++		    cpu_to_be64(
++			get_counter(dev, crp, dev->pma_counter_select[i]));
  
- #define PDC202XX_DEBUG_DRIVE_INFO	0
+ 	return reply((struct ib_smp *) pmp);
+ }
+@@ -1113,6 +1140,8 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
+ 		dev->z_local_link_integrity_errors;
+ 	cntrs.excessive_buffer_overrun_errors -=
+ 		dev->z_excessive_buffer_overrun_errors;
++	cntrs.vl15_dropped -= dev->z_vl15_dropped;
++	cntrs.vl15_dropped += dev->n_vl15_dropped;
  
-@@ -66,7 +59,7 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
- static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 drive_pci		= 0x60 + (drive->dn << 2);
+ 	memset(pmp->data, 0, sizeof(pmp->data));
  
- 	u8			AP = 0, BP = 0, CP = 0;
-@@ -142,11 +135,12 @@ static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
- }
+@@ -1156,10 +1185,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
+ 		cntrs.excessive_buffer_overrun_errors = 0xFUL;
+ 	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
+ 		cntrs.excessive_buffer_overrun_errors;
+-	if (dev->n_vl15_dropped > 0xFFFFUL)
++	if (cntrs.vl15_dropped > 0xFFFFUL)
+ 		p->vl15_dropped = __constant_cpu_to_be16(0xFFFF);
+ 	else
+-		p->vl15_dropped = cpu_to_be16((u16)dev->n_vl15_dropped);
++		p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped);
+ 	if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
+ 		p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
+ 	else
+@@ -1262,8 +1291,10 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
+ 		dev->z_excessive_buffer_overrun_errors =
+ 			cntrs.excessive_buffer_overrun_errors;
  
--static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
-+static u8 __devinit pdc2026x_old_cable_detect(ide_hwif_t *hwif)
- {
--	u16 CIS = 0, mask = (hwif->channel) ? (1<<11) : (1<<10);
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	u16 CIS, mask = hwif->channel ? (1 << 11) : (1 << 10);
+-	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED)
++	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) {
+ 		dev->n_vl15_dropped = 0;
++		dev->z_vl15_dropped = cntrs.vl15_dropped;
++	}
  
--	pci_read_config_word(hwif->pci_dev, 0x50, &CIS);
-+	pci_read_config_word(dev, 0x50, &CIS);
+ 	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
+ 		dev->z_port_xmit_data = cntrs.port_xmit_data;
+@@ -1434,7 +1465,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
+ 		 * before checking for other consumers.
+ 		 * Just tell the caller to process it normally.
+ 		 */
+-		ret = IB_MAD_RESULT_FAILURE;
++		ret = IB_MAD_RESULT_SUCCESS;
+ 		goto bail;
+ 	default:
+ 		smp->status |= IB_SMP_UNSUP_METHOD;
+@@ -1516,7 +1547,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
+ 		 * before checking for other consumers.
+ 		 * Just tell the caller to process it normally.
+ 		 */
+-		ret = IB_MAD_RESULT_FAILURE;
++		ret = IB_MAD_RESULT_SUCCESS;
+ 		goto bail;
+ 	default:
+ 		pmp->status |= IB_SMP_UNSUP_METHOD;
+diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
+index b997ff8..80dc623 100644
+--- a/drivers/infiniband/hw/ipath/ipath_qp.c
++++ b/drivers/infiniband/hw/ipath/ipath_qp.c
+@@ -387,8 +387,8 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
+ 	struct ib_wc wc;
+ 	int ret = 0;
  
- 	return (CIS & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
- }
-@@ -162,7 +156,7 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
-  */
- static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
- {
--	unsigned long clock_reg = hwif->dma_master + 0x11;
-+	unsigned long clock_reg = hwif->extra_base + 0x01;
- 	u8 clock = inb(clock_reg);
+-	ipath_dbg("QP%d/%d in error state\n",
+-		  qp->ibqp.qp_num, qp->remote_qpn);
++	ipath_dbg("QP%d/%d in error state (%d)\n",
++		  qp->ibqp.qp_num, qp->remote_qpn, err);
  
- 	outb(clock | (hwif->channel ? 0x08 : 0x02), clock_reg);
-@@ -170,20 +164,23 @@ static void pdc_old_enable_66MHz_clock(ide_hwif_t *hwif)
+ 	spin_lock(&dev->pending_lock);
+ 	/* XXX What if its already removed by the timeout code? */
+@@ -855,8 +855,6 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
+ 	 * See ipath_mmap() for details.
+ 	 */
+ 	if (udata && udata->outlen >= sizeof(__u64)) {
+-		int err;
+-
+ 		if (!qp->r_rq.wq) {
+ 			__u64 offset = 0;
  
- static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
- {
--	unsigned long clock_reg = hwif->dma_master + 0x11;
-+	unsigned long clock_reg = hwif->extra_base + 0x01;
- 	u8 clock = inb(clock_reg);
+diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
+index 120a61b..459e46e 100644
+--- a/drivers/infiniband/hw/ipath/ipath_rc.c
++++ b/drivers/infiniband/hw/ipath/ipath_rc.c
+@@ -647,6 +647,7 @@ static void send_rc_ack(struct ipath_qp *qp)
  
- 	outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
- }
+ queue_ack:
+ 	spin_lock_irqsave(&qp->s_lock, flags);
++	dev->n_rc_qacks++;
+ 	qp->s_flags |= IPATH_S_ACK_PENDING;
+ 	qp->s_nak_state = qp->r_nak_state;
+ 	qp->s_ack_psn = qp->r_ack_psn;
+@@ -798,11 +799,13 @@ bail:
  
--static int pdc202xx_quirkproc (ide_drive_t *drive)
-+static void pdc202xx_quirkproc(ide_drive_t *drive)
+ static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
  {
- 	const char **list, *model = drive->id->model;
- 
- 	for (list = pdc_quirk_drives; *list != NULL; list++)
--		if (strstr(model, *list) != NULL)
--			return 2;
--	return 0;
-+		if (strstr(model, *list) != NULL) {
-+			drive->quirk_list = 2;
-+			return;
+-	if (qp->s_wait_credit) {
+-		qp->s_wait_credit = 0;
+-		tasklet_hi_schedule(&qp->s_task);
++	if (qp->s_last_psn != psn) {
++		qp->s_last_psn = psn;
++		if (qp->s_wait_credit) {
++			qp->s_wait_credit = 0;
++			tasklet_hi_schedule(&qp->s_task);
 +		}
-+
-+	drive->quirk_list = 0;
+ 	}
+-	qp->s_last_psn = psn;
  }
  
- static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
-@@ -193,7 +190,7 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
- 	if (drive->media != ide_disk || drive->addressing == 1) {
- 		struct request *rq	= HWGROUP(drive)->rq;
- 		ide_hwif_t *hwif	= HWIF(drive);
--		unsigned long high_16   = hwif->dma_master;
-+		unsigned long high_16	= hwif->extra_base - 16;
- 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
- 		u32 word_count	= 0;
- 		u8 clock = inb(high_16 + 0x11);
-@@ -212,7 +209,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
- {
- 	if (drive->media != ide_disk || drive->addressing == 1) {
- 		ide_hwif_t *hwif	= HWIF(drive);
--		unsigned long high_16	= hwif->dma_master;
-+		unsigned long high_16	= hwif->extra_base - 16;
- 		unsigned long atapi_reg	= high_16 + (hwif->channel ? 0x24 : 0x20);
- 		u8 clock		= 0;
- 
-@@ -228,7 +225,7 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
- static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	unsigned long high_16	= hwif->dma_master;
-+	unsigned long high_16	= hwif->extra_base - 16;
- 	u8 dma_stat		= inb(hwif->dma_status);
- 	u8 sc1d			= inb(high_16 + 0x001d);
- 
-@@ -271,7 +268,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive)
- 
- static void pdc202xx_reset_host (ide_hwif_t *hwif)
- {
--	unsigned long high_16	= hwif->dma_master;
-+	unsigned long high_16	= hwif->extra_base - 16;
- 	u8 udma_speed_flag	= inb(high_16 | 0x001f);
- 
- 	outb(udma_speed_flag | 0x10, high_16 | 0x001f);
-@@ -302,24 +299,26 @@ static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev,
- 
- static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+
- 	hwif->set_pio_mode = &pdc202xx_set_pio_mode;
- 	hwif->set_dma_mode = &pdc202xx_set_mode;
- 
- 	hwif->quirkproc = &pdc202xx_quirkproc;
- 
--	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
-+	if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- 		hwif->resetproc = &pdc202xx_reset;
+ /**
+@@ -1653,13 +1656,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
+ 	case OP(SEND_FIRST):
+ 		if (!ipath_get_rwqe(qp, 0)) {
+ 		rnr_nak:
+-			/*
+-			 * A RNR NAK will ACK earlier sends and RDMA writes.
+-			 * Don't queue the NAK if a RDMA read or atomic
+-			 * is pending though.
+-			 */
+-			if (qp->r_nak_state)
+-				goto done;
+ 			qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer;
+ 			qp->r_ack_psn = qp->r_psn;
+ 			goto send_ack;
+diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
+index 708eba3..6d2a17f 100644
+--- a/drivers/infiniband/hw/ipath/ipath_registers.h
++++ b/drivers/infiniband/hw/ipath/ipath_registers.h
+@@ -82,8 +82,7 @@
  
-+		hwif->cable_detect = pdc2026x_old_cable_detect;
-+	}
-+
- 	if (hwif->dma_base == 0)
- 		return;
+ /* kr_rcvctrl bits */
+ #define INFINIPATH_R_PORTENABLE_SHIFT 0
+-#define INFINIPATH_R_INTRAVAIL_SHIFT 16
+-#define INFINIPATH_R_TAILUPD   0x80000000
++#define INFINIPATH_R_QPMAP_ENABLE (1ULL << 38)
  
- 	hwif->dma_lost_irq = &pdc202xx_dma_lost_irq;
- 	hwif->dma_timeout = &pdc202xx_dma_timeout;
+ /* kr_intstatus, kr_intclear, kr_intmask bits */
+ #define INFINIPATH_I_RCVURG_SHIFT 0
+@@ -272,20 +271,6 @@
+ #define INFINIPATH_EXTC_LEDGBLOK_ON          0x00000002ULL
+ #define INFINIPATH_EXTC_LEDGBLERR_OFF        0x00000001ULL
  
--	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
--		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--			hwif->cbl = pdc202xx_old_cable_detect(hwif);
+-/* kr_mdio bits */
+-#define INFINIPATH_MDIO_CLKDIV_MASK 0x7FULL
+-#define INFINIPATH_MDIO_CLKDIV_SHIFT 32
+-#define INFINIPATH_MDIO_COMMAND_MASK 0x7ULL
+-#define INFINIPATH_MDIO_COMMAND_SHIFT 26
+-#define INFINIPATH_MDIO_DEVADDR_MASK 0x1FULL
+-#define INFINIPATH_MDIO_DEVADDR_SHIFT 21
+-#define INFINIPATH_MDIO_REGADDR_MASK 0x1FULL
+-#define INFINIPATH_MDIO_REGADDR_SHIFT 16
+-#define INFINIPATH_MDIO_DATA_MASK 0xFFFFULL
+-#define INFINIPATH_MDIO_DATA_SHIFT 0
+-#define INFINIPATH_MDIO_CMDVALID    0x0000000040000000ULL
+-#define INFINIPATH_MDIO_RDDATAVALID 0x0000000080000000ULL
 -
-+	if (dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- 		hwif->dma_start = &pdc202xx_old_ide_dma_start;
- 		hwif->ide_dma_end = &pdc202xx_old_ide_dma_end;
- 	} 
-@@ -331,7 +330,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
- 	u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0;
- 
- 	if (hwif->channel) {
--		ide_setup_dma(hwif, dmabase, 8);
-+		ide_setup_dma(hwif, dmabase);
- 		return;
- 	}
+ /* kr_partitionkey bits */
+ #define INFINIPATH_PKEY_SIZE 16
+ #define INFINIPATH_PKEY_MASK 0xFFFF
+@@ -303,8 +288,6 @@
  
-@@ -355,7 +354,7 @@ static void __devinit init_dma_pdc202xx(ide_hwif_t *hwif, unsigned long dmabase)
- 	}
- #endif /* CONFIG_PDC202XX_BURST */
+ /* kr_xgxsconfig bits */
+ #define INFINIPATH_XGXS_RESET          0x7ULL
+-#define INFINIPATH_XGXS_MDIOADDR_MASK  0xfULL
+-#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
+ #define INFINIPATH_XGXS_RX_POL_SHIFT 19
+ #define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
  
--	ide_setup_dma(hwif, dmabase, 8);
-+	ide_setup_dma(hwif, dmabase);
- }
+@@ -470,6 +453,20 @@ struct ipath_cregs {
+ 	ipath_creg cr_unsupvlcnt;
+ 	ipath_creg cr_wordrcvcnt;
+ 	ipath_creg cr_wordsendcnt;
++	ipath_creg cr_vl15droppedpktcnt;
++	ipath_creg cr_rxotherlocalphyerrcnt;
++	ipath_creg cr_excessbufferovflcnt;
++	ipath_creg cr_locallinkintegrityerrcnt;
++	ipath_creg cr_rxvlerrcnt;
++	ipath_creg cr_rxdlidfltrcnt;
++	ipath_creg cr_psstat;
++	ipath_creg cr_psstart;
++	ipath_creg cr_psinterval;
++	ipath_creg cr_psrcvdatacount;
++	ipath_creg cr_psrcvpktscount;
++	ipath_creg cr_psxmitdatacount;
++	ipath_creg cr_psxmitpktscount;
++	ipath_creg cr_psxmitwaitcount;
+ };
  
- static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
-@@ -375,6 +374,11 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
+ #endif				/* _IPATH_REGISTERS_H */
+diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
+index 54c61a9..a59bdbd 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ruc.c
++++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
+@@ -98,11 +98,15 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp)
+ 		while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
+ 			qp->s_rnr_timeout -= nqp->s_rnr_timeout;
+ 			l = l->next;
+-			if (l->next == &dev->rnrwait)
++			if (l->next == &dev->rnrwait) {
++				nqp = NULL;
+ 				break;
++			}
+ 			nqp = list_entry(l->next, struct ipath_qp,
+ 					 timerwait);
+ 		}
++		if (nqp)
++			nqp->s_rnr_timeout -= qp->s_rnr_timeout;
+ 		list_add(&qp->timerwait, l);
  	}
- }
+ 	spin_unlock_irqrestore(&dev->pending_lock, flags);
+@@ -479,9 +483,14 @@ done:
  
-+#define IDE_HFLAGS_PDC202XX \
-+	(IDE_HFLAG_ERROR_STOPS_FIFO | \
-+	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
-+	 IDE_HFLAG_OFF_BOARD)
+ static void want_buffer(struct ipath_devdata *dd)
+ {
+-	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
++	unsigned long flags;
 +
- #define DECLARE_PDC2026X_DEV(name_str, udma, extra_flags) \
- 	{ \
- 		.name		= name_str, \
-@@ -382,9 +386,7 @@ static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev,
- 		.init_hwif	= init_hwif_pdc202xx, \
- 		.init_dma	= init_dma_pdc202xx, \
- 		.extra		= 48, \
--		.host_flags	= IDE_HFLAG_ERROR_STOPS_FIFO | \
--				  extra_flags | \
--				  IDE_HFLAG_OFF_BOARD, \
-+		.host_flags	= IDE_HFLAGS_PDC202XX | extra_flags, \
- 		.pio_mask	= ATA_PIO4, \
- 		.mwdma_mask	= ATA_MWDMA2, \
- 		.udma_mask	= udma, \
-@@ -397,8 +399,7 @@ static const struct ide_port_info pdc202xx_chipsets[] __devinitdata = {
- 		.init_hwif	= init_hwif_pdc202xx,
- 		.init_dma	= init_dma_pdc202xx,
- 		.extra		= 16,
--		.host_flags	= IDE_HFLAG_ERROR_STOPS_FIFO |
--				  IDE_HFLAG_OFF_BOARD,
-+		.host_flags	= IDE_HFLAGS_PDC202XX,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA2,
-diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
-index 27781d2..decef0f 100644
---- a/drivers/ide/pci/piix.c
-+++ b/drivers/ide/pci/piix.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/piix.c	Version 0.54	Sep 5, 2007
-- *
-  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
-  *  Copyright (C) 1998-2000 Andre Hedrick <andre at linux-ide.org>
-  *  Copyright (C) 2003 Red Hat Inc <alan at redhat.com>
-@@ -8,53 +6,8 @@
-  *
-  *  May be copied or modified under the terms of the GNU General Public License
-  *
-- *  PIO mode setting function for Intel chipsets.
-- *  For use instead of BIOS settings.
-- *
-- * 40-41
-- * 42-43
-- * 
-- *                 41
-- *                 43
-- *
-- * | PIO 0       | c0 | 80 | 0 |
-- * | PIO 2 | SW2 | d0 | 90 | 4 |
-- * | PIO 3 | MW1 | e1 | a1 | 9 |
-- * | PIO 4 | MW2 | e3 | a3 | b |
-- *
-- * sitre = word40 & 0x4000; primary
-- * sitre = word42 & 0x4000; secondary
-- *
-- * 44 8421|8421    hdd|hdb
-- *
-- * 48 8421         hdd|hdc|hdb|hda udma enabled
-- *
-- *    0001         hda
-- *    0010         hdb
-- *    0100         hdc
-- *    1000         hdd
-- *
-- * 4a 84|21        hdb|hda
-- * 4b 84|21        hdd|hdc
-- *
-- *    ata-33/82371AB
-- *    ata-33/82371EB
-- *    ata-33/82801AB            ata-66/82801AA
-- *    00|00 udma 0              00|00 reserved
-- *    01|01 udma 1              01|01 udma 3
-- *    10|10 udma 2              10|10 udma 4
-- *    11|11 reserved            11|11 reserved
-+ * Documentation:
-  *
-- * 54 8421|8421    ata66 drive|ata66 enable
-- *
-- * pci_read_config_word(HWIF(drive)->pci_dev, 0x40, &reg40);
-- * pci_read_config_word(HWIF(drive)->pci_dev, 0x42, &reg42);
-- * pci_read_config_word(HWIF(drive)->pci_dev, 0x44, &reg44);
-- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x48, &reg48);
-- * pci_read_config_word(HWIF(drive)->pci_dev, 0x4a, &reg4a);
-- * pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &reg54);
-- *
-- * Documentation
-  *	Publically available from Intel web site. Errata documentation
-  * is also publically available. As an aide to anyone hacking on this
-  * driver the list of errata that are relevant is below.going back to
-@@ -94,11 +47,9 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/ioport.h>
- #include <linux/pci.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
--#include <linux/delay.h>
- #include <linux/init.h>
++	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
++	dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
+ 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
+ 			 dd->ipath_sendctrl);
++	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
++	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
+ }
  
- #include <asm/io.h>
-@@ -116,7 +67,7 @@ static int no_piix_dma;
- static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	int is_slave		= drive->dn & 1;
- 	int master_port		= hwif->channel ? 0x42 : 0x40;
- 	int slave_port		= 0x44;
-@@ -185,7 +136,7 @@ static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
- static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ /**
+diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
+index 2fef36f..f772102 100644
+--- a/drivers/infiniband/hw/ipath/ipath_srq.c
++++ b/drivers/infiniband/hw/ipath/ipath_srq.c
+@@ -94,8 +94,8 @@ bail:
+ /**
+  * ipath_create_srq - create a shared receive queue
+  * @ibpd: the protection domain of the SRQ to create
+- * @attr: the attributes of the SRQ
+- * @udata: not used by the InfiniPath verbs driver
++ * @srq_init_attr: the attributes of the SRQ
++ * @udata: data from libipathverbs when creating a user SRQ
+  */
+ struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
+ 				struct ib_srq_init_attr *srq_init_attr,
+diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
+index f027141..d2725cd 100644
+--- a/drivers/infiniband/hw/ipath/ipath_stats.c
++++ b/drivers/infiniband/hw/ipath/ipath_stats.c
+@@ -133,15 +133,16 @@ bail:
+ static void ipath_qcheck(struct ipath_devdata *dd)
  {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
- 	int a_speed		= 3 << (drive->dn * 4);
- 	int u_flag		= 1 << drive->dn;
-@@ -203,20 +154,11 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	pci_read_config_byte(dev, 0x54, &reg54);
- 	pci_read_config_byte(dev, 0x55, &reg55);
+ 	static u64 last_tot_hdrqfull;
++	struct ipath_portdata *pd = dd->ipath_pd[0];
+ 	size_t blen = 0;
+ 	char buf[128];
  
--	switch(speed) {
--		case XFER_UDMA_4:
--		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
--		case XFER_UDMA_5:
--		case XFER_UDMA_3:
--		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
--		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_SW_DMA_2:	break;
--		default:		return;
--	}
--
- 	if (speed >= XFER_UDMA_0) {
-+		u8 udma = speed - XFER_UDMA_0;
-+
-+		u_speed = min_t(u8, 2 - (udma & 1), udma) << (drive->dn * 4);
-+
- 		if (!(reg48 & u_flag))
- 			pci_write_config_byte(dev, 0x48, reg48 | u_flag);
- 		if (speed == XFER_UDMA_5) {
-@@ -314,7 +256,7 @@ static const struct ich_laptop ich_laptop[] = {
+ 	*buf = 0;
+-	if (dd->ipath_pd[0]->port_hdrqfull != dd->ipath_p0_hdrqfull) {
++	if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
+ 		blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
+-				dd->ipath_pd[0]->port_hdrqfull -
++				pd->port_hdrqfull -
+ 				dd->ipath_p0_hdrqfull);
+-		dd->ipath_p0_hdrqfull = dd->ipath_pd[0]->port_hdrqfull;
++		dd->ipath_p0_hdrqfull = pd->port_hdrqfull;
+ 	}
+ 	if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
+ 		blen += snprintf(buf + blen, sizeof buf - blen,
+@@ -173,7 +174,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
+ 	if (blen)
+ 		ipath_dbg("%s\n", buf);
  
- static u8 __devinit piix_cable_detect(ide_hwif_t *hwif)
+-	if (dd->ipath_port0head != (u32)
++	if (pd->port_head != (u32)
+ 	    le64_to_cpu(*dd->ipath_hdrqtailptr)) {
+ 		if (dd->ipath_lastport0rcv_cnt ==
+ 		    ipath_stats.sps_port0pkts) {
+@@ -181,7 +182,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
+ 				   "port0 hd=%llx tl=%x; port0pkts %llx\n",
+ 				   (unsigned long long)
+ 				   le64_to_cpu(*dd->ipath_hdrqtailptr),
+-				   dd->ipath_port0head,
++				   pd->port_head,
+ 				   (unsigned long long)
+ 				   ipath_stats.sps_port0pkts);
+ 		}
+@@ -237,7 +238,7 @@ static void ipath_chk_errormask(struct ipath_devdata *dd)
+ void ipath_get_faststats(unsigned long opaque)
  {
--	struct pci_dev *pdev = hwif->pci_dev;
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
- 	const struct ich_laptop *lap = &ich_laptop[0];
- 	u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
- 
-@@ -346,14 +288,11 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
- 	hwif->set_pio_mode = &piix_set_pio_mode;
- 	hwif->set_dma_mode = &piix_set_dma_mode;
+ 	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
+-	u32 val;
++	int i;
+ 	static unsigned cnt;
+ 	unsigned long flags;
+ 	u64 traffic_wds;
+@@ -321,12 +322,11 @@ void ipath_get_faststats(unsigned long opaque)
  
-+	hwif->cable_detect = piix_cable_detect;
+ 	/* limit qfull messages to ~one per minute per port */
+ 	if ((++cnt & 0x10)) {
+-		for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
+-		     val--) {
+-			if (dd->ipath_lastegrheads[val] != -1)
+-				dd->ipath_lastegrheads[val] = -1;
+-			if (dd->ipath_lastrcvhdrqtails[val] != -1)
+-				dd->ipath_lastrcvhdrqtails[val] = -1;
++		for (i = (int) dd->ipath_cfgports; --i >= 0; ) {
++			struct ipath_portdata *pd = dd->ipath_pd[i];
 +
- 	if (!hwif->dma_base)
- 		return;
++			if (pd && pd->port_lastrcvhdrqtail != -1)
++				pd->port_lastrcvhdrqtail = -1;
+ 		}
+ 	}
  
--	if (hwif->ultra_mask & 0x78) {
--		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--			hwif->cbl = piix_cable_detect(hwif);
--	}
--
- 	if (no_piix_dma)
- 		hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+index e1ad7cf..56dfc8a 100644
+--- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
++++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
+@@ -363,6 +363,60 @@ static ssize_t show_unit(struct device *dev,
+ 	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
  }
-diff --git a/drivers/ide/pci/rz1000.c b/drivers/ide/pci/rz1000.c
-index 6b10ae2..5167661 100644
---- a/drivers/ide/pci/rz1000.c
-+++ b/drivers/ide/pci/rz1000.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/rz1000.c	Version 0.06	January 12, 2003
-- *
-  *  Copyright (C) 1995-1998  Linus Torvalds & author (see below)
-  */
- 
-@@ -18,22 +16,15 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/pci.h>
- #include <linux/ide.h>
- #include <linux/init.h>
- 
--#include <asm/io.h>
--
- static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	u16 reg;
--	struct pci_dev *dev = hwif->pci_dev;
  
- 	if (!pci_read_config_word (dev, 0x40, &reg) &&
- 	    !pci_write_config_word(dev, 0x40, reg & 0xdfff)) {
-@@ -42,8 +33,7 @@ static void __devinit init_hwif_rz1000 (ide_hwif_t *hwif)
- 	} else {
- 		if (hwif->mate)
- 			hwif->mate->serialized = hwif->serialized = 1;
--		hwif->drives[0].no_unmask = 1;
--		hwif->drives[1].no_unmask = 1;
-+		hwif->host_flags |= IDE_HFLAG_NO_UNMASK_IRQS;
- 		printk(KERN_INFO "%s: serialized, disabled unmasking "
- 			"(buggy RZ1000/RZ1001)\n", hwif->name);
- 	}
-diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
-index 707d5ff..561aa47 100644
---- a/drivers/ide/pci/sc1200.c
-+++ b/drivers/ide/pci/sc1200.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/sc1200.c		Version 0.97	Aug 3 2007
-- *
-  * Copyright (C) 2000-2002		Mark Lord <mlord at pobox.com>
-  * Copyright (C)      2007		Bartlomiej Zolnierkiewicz
-  *
-@@ -16,19 +14,13 @@
- #include <linux/module.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
--#include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
- #include <linux/pm.h>
++static ssize_t show_jint_max_packets(struct device *dev,
++				     struct device_attribute *attr,
++				     char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
 +
- #include <asm/io.h>
--#include <asm/irq.h>
- 
- #define SC1200_REV_A	0x00
- #define SC1200_REV_B1	0x01
-@@ -87,7 +79,7 @@ static const unsigned int sc1200_pio_timings[4][5] =
- static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
- {
- 	ide_hwif_t *hwif = drive->hwif;
--	struct pci_dev *pdev = hwif->pci_dev;
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
- 	unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
- 
- 	pci_read_config_dword(pdev, basereg + 4, &format);
-@@ -130,72 +122,42 @@ out:
- static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
- {
- 	ide_hwif_t		*hwif = HWIF(drive);
-+	struct pci_dev		*dev = to_pci_dev(hwif->dev);
- 	int			unit = drive->select.b.unit;
- 	unsigned int		reg, timings;
- 	unsigned short		pci_clock;
- 	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;
- 
-+	static const u32 udma_timing[3][3] = {
-+		{ 0x00921250, 0x00911140, 0x00911030 },
-+		{ 0x00932470, 0x00922260, 0x00922140 },
-+		{ 0x009436a1, 0x00933481, 0x00923261 },
-+	};
++	return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_max_packets);
++}
 +
-+	static const u32 mwdma_timing[3][3] = {
-+		{ 0x00077771, 0x00012121, 0x00002020 },
-+		{ 0x000bbbb2, 0x00024241, 0x00013131 },
-+		{ 0x000ffff3, 0x00035352, 0x00015151 },
-+	};
++static ssize_t store_jint_max_packets(struct device *dev,
++				      struct device_attribute *attr,
++				      const char *buf,
++				      size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	u16 v = 0;
++	int ret;
 +
- 	pci_clock = sc1200_get_pci_clock();
- 
- 	/*
- 	 * Note that each DMA mode has several timings associated with it.
- 	 * The correct timing depends on the fast PCI clock freq.
- 	 */
--	timings = 0;
--	switch (mode) {
--		case XFER_UDMA_0:
--			switch (pci_clock) {
--				case PCI_CLK_33:	timings = 0x00921250;	break;
--				case PCI_CLK_48:	timings = 0x00932470;	break;
--				case PCI_CLK_66:	timings = 0x009436a1;	break;
--			}
--			break;
--		case XFER_UDMA_1:
--			switch (pci_clock) {
--				case PCI_CLK_33:	timings = 0x00911140;	break;
--				case PCI_CLK_48:	timings = 0x00922260;	break;
--				case PCI_CLK_66:	timings = 0x00933481;	break;
--			}
--			break;
--		case XFER_UDMA_2:
--			switch (pci_clock) {
--				case PCI_CLK_33:	timings = 0x00911030;	break;
--				case PCI_CLK_48:	timings = 0x00922140;	break;
--				case PCI_CLK_66:	timings = 0x00923261;	break;
--			}
--			break;
--		case XFER_MW_DMA_0:
--			switch (pci_clock) {
--				case PCI_CLK_33:	timings = 0x00077771;	break;
--				case PCI_CLK_48:	timings = 0x000bbbb2;	break;
--				case PCI_CLK_66:	timings = 0x000ffff3;	break;
--			}
--			break;
--		case XFER_MW_DMA_1:
--			switch (pci_clock) {
--				case PCI_CLK_33:	timings = 0x00012121;	break;
--				case PCI_CLK_48:	timings = 0x00024241;	break;
--				case PCI_CLK_66:	timings = 0x00035352;	break;
--			}
--			break;
--		case XFER_MW_DMA_2:
--			switch (pci_clock) {
--				case PCI_CLK_33:	timings = 0x00002020;	break;
--				case PCI_CLK_48:	timings = 0x00013131;	break;
--				case PCI_CLK_66:	timings = 0x00015151;	break;
--			}
--			break;
--		default:
--			return;
--	}
++	ret = ipath_parse_ushort(buf, &v);
++	if (ret < 0)
++		ipath_dev_err(dd, "invalid jint_max_packets.\n");
++	else
++		dd->ipath_f_config_jint(dd, dd->ipath_jint_idle_ticks, v);
 +
-+	if (mode >= XFER_UDMA_0)
-+		timings =  udma_timing[pci_clock][mode - XFER_UDMA_0];
++	return ret;
++}
++
++static ssize_t show_jint_idle_ticks(struct device *dev,
++				    struct device_attribute *attr,
++				    char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++
++	return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_idle_ticks);
++}
++
++static ssize_t store_jint_idle_ticks(struct device *dev,
++				     struct device_attribute *attr,
++				     const char *buf,
++				     size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	u16 v = 0;
++	int ret;
++
++	ret = ipath_parse_ushort(buf, &v);
++	if (ret < 0)
++		ipath_dev_err(dd, "invalid jint_idle_ticks.\n");
 +	else
-+		timings = mwdma_timing[pci_clock][mode - XFER_MW_DMA_0];
- 
- 	if (unit == 0) {			/* are we configuring drive0? */
--		pci_read_config_dword(hwif->pci_dev, basereg+4, &reg);
-+		pci_read_config_dword(dev, basereg + 4, &reg);
- 		timings |= reg & 0x80000000;	/* preserve PIO format bit */
--		pci_write_config_dword(hwif->pci_dev, basereg+4, timings);
--	} else {
--		pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
--	}
-+		pci_write_config_dword(dev, basereg + 4, timings);
-+	} else
-+		pci_write_config_dword(dev, basereg + 12, timings);
- }
- 
- /*  Replacement for the standard ide_dma_end action in
-@@ -250,9 +212,9 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	}
- 	if (mode != -1) {
- 		printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
--		hwif->dma_off_quietly(drive);
--		if (ide_set_dma_mode(drive, mode) == 0)
--			hwif->dma_host_on(drive);
-+		ide_dma_off_quietly(drive);
-+		if (ide_set_dma_mode(drive, mode) == 0 && drive->using_dma)
-+			hwif->dma_host_set(drive, 1);
- 		return;
- 	}
- 
-@@ -260,66 +222,39 @@ static void sc1200_set_pio_mode(ide_drive_t *drive, const u8 pio)
++		dd->ipath_f_config_jint(dd, v, dd->ipath_jint_max_packets);
++
++	return ret;
++}
++
+ #define DEVICE_COUNTER(name, attr) \
+ 	static ssize_t show_counter_##name(struct device *dev, \
+ 					   struct device_attribute *attr, \
+@@ -670,6 +724,257 @@ static ssize_t show_logged_errs(struct device *dev,
+ 	return count;
  }
  
- #ifdef CONFIG_PM
--static ide_hwif_t *lookup_pci_dev (ide_hwif_t *prev, struct pci_dev *dev)
--{
--	int	h;
--
--	for (h = 0; h < MAX_HWIFS; h++) {
--		ide_hwif_t *hwif = &ide_hwifs[h];
--		if (prev) {
--			if (hwif == prev)
--				prev = NULL;	// found previous, now look for next match
--		} else {
--			if (hwif && hwif->pci_dev == dev)
--				return hwif;	// found next match
--		}
--	}
--	return NULL;	// not found
--}
--
--typedef struct sc1200_saved_state_s {
--	__u32		regs[4];
--} sc1200_saved_state_t;
--
-+struct sc1200_saved_state {
-+	u32 regs[8];
-+};
- 
- static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
- {
--	ide_hwif_t		*hwif = NULL;
--
- 	printk("SC1200: suspend(%u)\n", state.event);
- 
-+	/*
-+	 * we only save state when going from full power to less
-+	 */
- 	if (state.event == PM_EVENT_ON) {
--		// we only save state when going from full power to less
--
--		//
--		// Loop over all interfaces that are part of this PCI device:
--		//
--		while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
--			sc1200_saved_state_t	*ss;
--			unsigned int		basereg, r;
--			//
--			// allocate a permanent save area, if not already allocated
--			//
--			ss = (sc1200_saved_state_t *)hwif->config_data;
--			if (ss == NULL) {
--				ss = kmalloc(sizeof(sc1200_saved_state_t), GFP_KERNEL);
--				if (ss == NULL)
--					return -ENOMEM;
--				hwif->config_data = (unsigned long)ss;
--			}
--			ss = (sc1200_saved_state_t *)hwif->config_data;
--			//
--			// Save timing registers:  this may be unnecessary if 
--			// BIOS also does it
--			//
--			basereg = hwif->channel ? 0x50 : 0x40;
--			for (r = 0; r < 4; ++r) {
--				pci_read_config_dword (hwif->pci_dev, basereg + (r<<2), &ss->regs[r]);
--			}
-+		struct sc1200_saved_state *ss;
-+		unsigned int r;
++/*
++ * New sysfs entries to control various IB config. These all turn into
++ * accesses via ipath_f_get/set_ib_cfg.
++ *
++ * Get/Set heartbeat enable. Or of 1=enabled, 2=auto
++ */
++static ssize_t show_hrtbt_enb(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
 +
-+		/*
-+		 * allocate a permanent save area, if not already allocated
-+		 */
-+		ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
-+		if (ss == NULL) {
-+			ss = kmalloc(sizeof(*ss), GFP_KERNEL);
-+			if (ss == NULL)
-+				return -ENOMEM;
-+			pci_set_drvdata(dev, ss);
- 		}
--	}
- 
--	/* You don't need to iterate over disks -- sysfs should have done that for you already */ 
-+		/*
-+		 * save timing registers
-+		 * (this may be unnecessary if BIOS also does it)
-+		 */
-+		for (r = 0; r < 8; r++)
-+			pci_read_config_dword(dev, 0x40 + r * 4, &ss->regs[r]);
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_HRTBT);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++static ssize_t store_hrtbt_enb(struct device *dev,
++			  struct device_attribute *attr,
++			  const char *buf,
++			  size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret, r;
++	u16 val;
++
++	ret = ipath_parse_ushort(buf, &val);
++	if (ret >= 0 && val > 3)
++		ret = -EINVAL;
++	if (ret < 0) {
++		ipath_dev_err(dd, "attempt to set invalid Heartbeat enable\n");
++		goto bail;
 +	}
- 
- 	pci_disable_device(dev);
- 	pci_set_power_state(dev, pci_choose_state(dev, state));
-@@ -328,30 +263,25 @@ static int sc1200_suspend (struct pci_dev *dev, pm_message_t state)
- 
- static int sc1200_resume (struct pci_dev *dev)
- {
--	ide_hwif_t	*hwif = NULL;
--	int		i;
-+	struct sc1200_saved_state *ss;
-+	unsigned int r;
-+	int i;
- 
- 	i = pci_enable_device(dev);
- 	if (i)
- 		return i;
- 
--	//
--	// loop over all interfaces that are part of this pci device:
--	//
--	while ((hwif = lookup_pci_dev(hwif, dev)) != NULL) {
--		unsigned int		basereg, r;
--		sc1200_saved_state_t	*ss = (sc1200_saved_state_t *)hwif->config_data;
--
--		//
--		// Restore timing registers:  this may be unnecessary if BIOS also does it
--		//
--		basereg = hwif->channel ? 0x50 : 0x40;
--		if (ss != NULL) {
--			for (r = 0; r < 4; ++r) {
--				pci_write_config_dword(hwif->pci_dev, basereg + (r<<2), ss->regs[r]);
--			}
--		}
-+	ss = (struct sc1200_saved_state *)pci_get_drvdata(dev);
 +
 +	/*
-+	 * restore timing registers
-+	 * (this may be unnecessary if BIOS also does it)
++	 * Set the "intentional" heartbeat enable per either of
++	 * "Enable" and "Auto", as these are normally set together.
++	 * This bit is consulted when leaving loopback mode,
++	 * because entering loopback mode overrides it and automatically
++	 * disables heartbeat.
 +	 */
-+	if (ss) {
-+		for (r = 0; r < 8; r++)
-+			pci_write_config_dword(dev, 0x40 + r * 4, ss->regs[r]);
- 	}
++	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, val);
++	if (r < 0)
++		ret = r;
++	else if (val == IPATH_IB_HRTBT_OFF)
++		dd->ipath_flags |= IPATH_NO_HRTBT;
++	else
++		dd->ipath_flags &= ~IPATH_NO_HRTBT;
 +
- 	return 0;
- }
- #endif
-diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
-index ebb7132..238e3e1 100644
---- a/drivers/ide/pci/scc_pata.c
-+++ b/drivers/ide/pci/scc_pata.c
-@@ -254,19 +254,7 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 		offset = 0; /* 100MHz */
- 	}
- 
--	switch (speed) {
--	case XFER_UDMA_6:
--	case XFER_UDMA_5:
--	case XFER_UDMA_4:
--	case XFER_UDMA_3:
--	case XFER_UDMA_2:
--	case XFER_UDMA_1:
--	case XFER_UDMA_0:
--		idx = speed - XFER_UDMA_0;
--		break;
--	default:
--		return;
--	}
-+	idx = speed - XFER_UDMA_0;
- 
- 	jcactsel = JCACTSELtbl[offset][idx];
- 	if (is_slave) {
-@@ -606,7 +594,7 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
- 
- static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	struct scc_ports *ports = pci_get_drvdata(dev);
- 	unsigned long dma_base = ports->dma;
- 
-@@ -632,7 +620,7 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
- 	hwif->io_ports[IDE_STATUS_OFFSET] = dma_base + 0x3c;
- 	hwif->io_ports[IDE_CONTROL_OFFSET] = dma_base + 0x40;
- 
--	hwif->irq = hwif->pci_dev->irq;
-+	hwif->irq = dev->irq;
- 	hwif->dma_base = dma_base;
- 	hwif->config_data = ports->ctl;
- 	hwif->mmio = 1;
-@@ -648,13 +636,19 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
- 
- static void __devinit init_iops_scc(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev =  hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++bail:
++	return ret;
++}
 +
- 	hwif->hwif_data = NULL;
- 	if (pci_get_drvdata(dev) == NULL)
- 		return;
- 	init_mmio_iops_scc(hwif);
- }
- 
-+static u8 __devinit scc_cable_detect(ide_hwif_t *hwif)
++/*
++ * Get/Set Link-widths enabled. Or of 1=1x, 2=4x (this is human/IB centric,
++ * _not_ the particular encoding of any given chip)
++ */
++static ssize_t show_lwid_enb(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++static ssize_t store_lwid_enb(struct device *dev,
++			  struct device_attribute *attr,
++			  const char *buf,
++			  size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret, r;
++	u16 val;
++
++	ret = ipath_parse_ushort(buf, &val);
++	if (ret >= 0 && (val == 0 || val > 3))
++		ret = -EINVAL;
++	if (ret < 0) {
++		ipath_dev_err(dd,
++			"attempt to set invalid Link Width (enable)\n");
++		goto bail;
++	}
++
++	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, val);
++	if (r < 0)
++		ret = r;
++
++bail:
++	return ret;
++}
++
++/* Get current link width */
++static ssize_t show_lwid(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++/*
++ * Get/Set Link-speeds enabled. Or of 1=SDR 2=DDR.
++ */
++static ssize_t show_spd_enb(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++static ssize_t store_spd_enb(struct device *dev,
++			  struct device_attribute *attr,
++			  const char *buf,
++			  size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret, r;
++	u16 val;
++
++	ret = ipath_parse_ushort(buf, &val);
++	if (ret >= 0 && (val == 0 || val > (IPATH_IB_SDR | IPATH_IB_DDR)))
++		ret = -EINVAL;
++	if (ret < 0) {
++		ipath_dev_err(dd,
++			"attempt to set invalid Link Speed (enable)\n");
++		goto bail;
++	}
++
++	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, val);
++	if (r < 0)
++		ret = r;
++
++bail:
++	return ret;
++}
++
++/* Get current link speed */
++static ssize_t show_spd(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++/*
++ * Get/Set RX polarity-invert enable. 0=no, 1=yes.
++ */
++static ssize_t show_rx_polinv_enb(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++static ssize_t store_rx_polinv_enb(struct device *dev,
++			  struct device_attribute *attr,
++			  const char *buf,
++			  size_t count)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret, r;
++	u16 val;
++
++	ret = ipath_parse_ushort(buf, &val);
++	if (ret < 0 || val > 1)
++		goto invalid;
++
++	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
++	if (r < 0) {
++		ret = r;
++		goto bail;
++	}
++
++	goto bail;
++invalid:
++	ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
++bail:
++	return ret;
++}
++/*
++ * Get/Set RX lane-reversal enable. 0=no, 1=yes.
++ */
++static ssize_t show_lanerev_enb(struct device *dev,
++			 struct device_attribute *attr,
++			 char *buf)
++{
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret;
++
++	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB);
++	if (ret >= 0)
++		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	return ret;
++}
++
++static ssize_t store_lanerev_enb(struct device *dev,
++			  struct device_attribute *attr,
++			  const char *buf,
++			  size_t count)
 +{
-+	return ATA_CBL_PATA80;
-+}
++	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	int ret, r;
++	u16 val;
 +
- /**
-  *	init_hwif_scc	-	set up hwif
-  *	@hwif: interface to set up
-@@ -689,8 +683,7 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
- 	else
- 		hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
- 
--	/* we support 80c cable only. */
--	hwif->cbl = ATA_CBL_PATA80;
-+	hwif->cable_detect = scc_cable_detect;
- }
- 
- #define DECLARE_SCC_DEV(name_str)			\
-@@ -738,14 +731,12 @@ static void __devexit scc_remove(struct pci_dev *dev)
- 	unsigned long dma_size = pci_resource_len(dev, 1);
- 
- 	if (hwif->dmatable_cpu) {
--		pci_free_consistent(hwif->pci_dev,
--				    PRD_ENTRIES * PRD_BYTES,
--				    hwif->dmatable_cpu,
--				    hwif->dmatable_dma);
-+		pci_free_consistent(dev, PRD_ENTRIES * PRD_BYTES,
-+				    hwif->dmatable_cpu, hwif->dmatable_dma);
- 		hwif->dmatable_cpu = NULL;
- 	}
- 
--	ide_unregister(hwif->index);
-+	ide_unregister(hwif->index, 0, 0);
- 
- 	hwif->chipset = ide_unknown;
- 	iounmap((void*)ports->dma);
-diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
-index a728031..c11880b 100644
---- a/drivers/ide/pci/serverworks.c
-+++ b/drivers/ide/pci/serverworks.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/serverworks.c		Version 0.22	Jun 27 2007
-- *
-  * Copyright (C) 1998-2000 Michel Aubry
-  * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
-  * Copyright (C) 1998-2000 Andre Hedrick <andre at linux-ide.org>
-@@ -33,12 +31,10 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/ioport.h>
- #include <linux/pci.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
--#include <linux/delay.h>
- 
- #include <asm/io.h>
- 
-@@ -67,7 +63,7 @@ static int check_in_drive_lists (ide_drive_t *drive, const char **list)
- 
- static u8 svwks_udma_filter(ide_drive_t *drive)
- {
--	struct pci_dev *dev     = HWIF(drive)->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u8 mask = 0;
- 
- 	if (dev->device == PCI_DEVICE_ID_SERVERWORKS_HT1000IDE)
-@@ -130,7 +126,7 @@ static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
- 	static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
- 
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 
- 	pci_write_config_byte(dev, drive_pci[drive->dn], pio_modes[pio]);
- 
-@@ -153,7 +149,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	static const u8 drive_pci2[]		= { 0x45, 0x44, 0x47, 0x46 };
- 
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 unit			= (drive->select.b.unit & 0x01);
- 
- 	u8 ultra_enable	 = 0, ultra_timing = 0, dma_timing = 0;
-@@ -164,25 +160,12 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	ultra_timing	&= ~(0x0F << (4*unit));
- 	ultra_enable	&= ~(0x01 << drive->dn);
- 
--	switch(speed) {
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_MW_DMA_0:
--			dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
--			break;
--
--		case XFER_UDMA_5:
--		case XFER_UDMA_4:
--		case XFER_UDMA_3:
--		case XFER_UDMA_2:
--		case XFER_UDMA_1:
--		case XFER_UDMA_0:
--			dma_timing   |= dma_modes[2];
--			ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit));
--			ultra_enable |= (0x01 << drive->dn);
--		default:
--			break;
--	}
-+	if (speed >= XFER_UDMA_0) {
-+		dma_timing   |= dma_modes[2];
-+		ultra_timing |= (udma_modes[speed - XFER_UDMA_0] << (4 * unit));
-+		ultra_enable |= (0x01 << drive->dn);
-+	} else if (speed >= XFER_MW_DMA_0)
-+		dma_timing   |= dma_modes[speed - XFER_MW_DMA_0];
- 
- 	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
- 	pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
-@@ -300,7 +283,8 @@ static u8 __devinit ata66_svwks_svwks(ide_hwif_t *hwif)
-  */
- static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	ret = ipath_parse_ushort(buf, &val);
++	if (ret >= 0 && val > 1) {
++		ret = -EINVAL;
++		ipath_dev_err(dd,
++			"attempt to set invalid Lane reversal (enable)\n");
++		goto bail;
++	}
 +
- 	if (dev->subsystem_vendor == PCI_VENDOR_ID_DELL &&
- 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
- 	    (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE ||
-@@ -318,7 +302,8 @@ static u8 __devinit ata66_svwks_dell(ide_hwif_t *hwif)
-  */
- static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB, val);
++	if (r < 0)
++		ret = r;
 +
- 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SUN &&
- 	    dev->vendor	== PCI_VENDOR_ID_SERVERWORKS &&
- 	    dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE)
-@@ -329,7 +314,7 @@ static u8 __devinit ata66_svwks_cobalt(ide_hwif_t *hwif)
- 
- static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 
- 	/* Server Works */
- 	if (dev->subsystem_vendor == PCI_VENDOR_ID_SERVERWORKS)
-@@ -353,25 +338,27 @@ static u8 __devinit ata66_svwks(ide_hwif_t *hwif)
- 
- static void __devinit init_hwif_svwks (ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++bail:
++	return ret;
++}
 +
- 	hwif->set_pio_mode = &svwks_set_pio_mode;
- 	hwif->set_dma_mode = &svwks_set_dma_mode;
- 	hwif->udma_filter = &svwks_udma_filter;
+ static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
+ static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
  
--	if (!hwif->dma_base)
--		return;
--
--	if (hwif->pci_dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
--		if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--			hwif->cbl = ata66_svwks(hwif);
--	}
-+	if (dev->device != PCI_DEVICE_ID_SERVERWORKS_OSB4IDE)
-+		hwif->cable_detect = ata66_svwks;
- }
+@@ -683,6 +988,11 @@ static struct attribute_group driver_attr_group = {
+ 	.attrs = driver_attributes
+ };
  
-+#define IDE_HFLAGS_SVWKS \
-+	(IDE_HFLAG_LEGACY_IRQS | \
-+	 IDE_HFLAG_ABUSE_SET_DMA_MODE | \
-+	 IDE_HFLAG_BOOTABLE)
++struct attribute_group *ipath_driver_attr_groups[] = {
++	&driver_attr_group,
++	NULL,
++};
 +
- static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- 	{	/* 0 */
- 		.name		= "SvrWks OSB4",
- 		.init_chipset	= init_chipset_svwks,
- 		.init_hwif	= init_hwif_svwks,
--		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
-+		.host_flags	= IDE_HFLAGS_SVWKS,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= 0x00, /* UDMA is problematic on OSB4 */
-@@ -379,7 +366,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- 		.name		= "SvrWks CSB5",
- 		.init_chipset	= init_chipset_svwks,
- 		.init_hwif	= init_hwif_svwks,
--		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
-+		.host_flags	= IDE_HFLAGS_SVWKS,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA5,
-@@ -387,7 +374,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- 		.name		= "SvrWks CSB6",
- 		.init_chipset	= init_chipset_svwks,
- 		.init_hwif	= init_hwif_svwks,
--		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_BOOTABLE,
-+		.host_flags	= IDE_HFLAGS_SVWKS,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA5,
-@@ -395,8 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- 		.name		= "SvrWks CSB6",
- 		.init_chipset	= init_chipset_svwks,
- 		.init_hwif	= init_hwif_svwks,
--		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
--				  IDE_HFLAG_BOOTABLE,
-+		.host_flags	= IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA5,
-@@ -404,8 +390,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = {
- 		.name		= "SvrWks HT1000",
- 		.init_chipset	= init_chipset_svwks,
- 		.init_hwif	= init_hwif_svwks,
--		.host_flags	= IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_SINGLE |
--				  IDE_HFLAG_BOOTABLE,
-+		.host_flags	= IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE,
- 		.pio_mask	= ATA_PIO4,
- 		.mwdma_mask	= ATA_MWDMA2,
- 		.udma_mask	= ATA_UDMA5,
-@@ -428,7 +413,9 @@ static int __devinit svwks_init_one(struct pci_dev *dev, const struct pci_device
- 
- 	d = serverworks_chipsets[idx];
- 
--	if (idx == 2 || idx == 3) {
-+	if (idx == 1)
-+		d.host_flags |= IDE_HFLAG_CLEAR_SIMPLEX;
-+	else if (idx == 2 || idx == 3) {
- 		if ((PCI_FUNC(dev->devfn) & 1) == 0) {
- 			if (pci_resource_start(dev, 0) != 0x01f1)
- 				d.host_flags &= ~IDE_HFLAG_BOOTABLE;
-diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
-index de820aa..0546264 100644
---- a/drivers/ide/pci/sgiioc4.c
-+++ b/drivers/ide/pci/sgiioc4.c
-@@ -25,8 +25,6 @@
- #include <linux/hdreg.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
- #include <linux/ioport.h>
- #include <linux/blkdev.h>
- #include <linux/scatterlist.h>
-@@ -159,6 +157,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
- 		}
+ static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
+ static DEVICE_ATTR(lmc, S_IWUSR | S_IRUGO, show_lmc, store_lmc);
+ static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
+@@ -701,6 +1011,10 @@ static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
+ static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
+ static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
+ static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
++static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
++		   show_jint_max_packets, store_jint_max_packets);
++static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
++		   show_jint_idle_ticks, store_jint_idle_ticks);
  
- 		if (intr_reg & 0x02) {
-+			struct pci_dev *dev = to_pci_dev(hwif->dev);
- 			/* Error when transferring DMA data on PCI bus */
- 			u32 pci_err_addr_low, pci_err_addr_high,
- 			    pci_stat_cmd_reg;
-@@ -167,7 +166,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
- 				readl((void __iomem *)hwif->io_ports[IDE_IRQ_OFFSET]);
- 			pci_err_addr_high =
- 				readl((void __iomem *)(hwif->io_ports[IDE_IRQ_OFFSET] + 4));
--			pci_read_config_dword(hwif->pci_dev, PCI_COMMAND,
-+			pci_read_config_dword(dev, PCI_COMMAND,
- 					      &pci_stat_cmd_reg);
- 			printk(KERN_ERR
- 			       "%s(%s) : PCI Bus Error when doing DMA:"
-@@ -178,8 +177,7 @@ sgiioc4_clearirq(ide_drive_t * drive)
- 			       __FUNCTION__, drive->name,
- 			       pci_err_addr_high, pci_err_addr_low);
- 			/* Clear the PCI Error indicator */
--			pci_write_config_dword(hwif->pci_dev, PCI_COMMAND,
--					       0x00000146);
-+			pci_write_config_dword(dev, PCI_COMMAND, 0x00000146);
- 		}
+ static struct attribute *dev_attributes[] = {
+ 	&dev_attr_guid.attr,
+@@ -727,6 +1041,34 @@ static struct attribute_group dev_attr_group = {
+ 	.attrs = dev_attributes
+ };
  
- 		/* Clear the Interrupt, Error bits on the IOC4 */
-@@ -277,21 +275,6 @@ sgiioc4_ide_dma_end(ide_drive_t * drive)
- 	return dma_stat;
++static DEVICE_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb,
++		   store_hrtbt_enb);
++static DEVICE_ATTR(link_width_enable, S_IWUSR | S_IRUGO, show_lwid_enb,
++		   store_lwid_enb);
++static DEVICE_ATTR(link_width, S_IRUGO, show_lwid, NULL);
++static DEVICE_ATTR(link_speed_enable, S_IWUSR | S_IRUGO, show_spd_enb,
++		   store_spd_enb);
++static DEVICE_ATTR(link_speed, S_IRUGO, show_spd, NULL);
++static DEVICE_ATTR(rx_pol_inv_enable, S_IWUSR | S_IRUGO, show_rx_polinv_enb,
++		   store_rx_polinv_enb);
++static DEVICE_ATTR(rx_lane_rev_enable, S_IWUSR | S_IRUGO, show_lanerev_enb,
++		   store_lanerev_enb);
++
++static struct attribute *dev_ibcfg_attributes[] = {
++	&dev_attr_hrtbt_enable.attr,
++	&dev_attr_link_width_enable.attr,
++	&dev_attr_link_width.attr,
++	&dev_attr_link_speed_enable.attr,
++	&dev_attr_link_speed.attr,
++	&dev_attr_rx_pol_inv_enable.attr,
++	&dev_attr_rx_lane_rev_enable.attr,
++	NULL
++};
++
++static struct attribute_group dev_ibcfg_attr_group = {
++	.attrs = dev_ibcfg_attributes
++};
++
+ /**
+  * ipath_expose_reset - create a device reset file
+  * @dev: the device structure
+@@ -753,24 +1095,9 @@ int ipath_expose_reset(struct device *dev)
+ 	return ret;
  }
  
--static int
--sgiioc4_ide_dma_on(ide_drive_t * drive)
+-int ipath_driver_create_group(struct device_driver *drv)
 -{
--	drive->using_dma = 1;
+-	int ret;
 -
--	return 0;
+-	ret = sysfs_create_group(&drv->kobj, &driver_attr_group);
+-
+-	return ret;
 -}
 -
--static void sgiioc4_dma_off_quietly(ide_drive_t *drive)
+-void ipath_driver_remove_group(struct device_driver *drv)
 -{
--	drive->using_dma = 0;
--
--	drive->hwif->dma_host_off(drive);
+-	sysfs_remove_group(&drv->kobj, &driver_attr_group);
 -}
 -
- static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
+ int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
  {
- }
-@@ -303,13 +286,10 @@ sgiioc4_ide_dma_test_irq(ide_drive_t * drive)
- 	return sgiioc4_checkirq(HWIF(drive));
- }
+ 	int ret;
+-	char unit[5];
  
--static void sgiioc4_dma_host_on(ide_drive_t * drive)
-+static void sgiioc4_dma_host_set(ide_drive_t *drive, int on)
- {
--}
--
--static void sgiioc4_dma_host_off(ide_drive_t * drive)
--{
--	sgiioc4_clearirq(drive);
-+	if (!on)
-+		sgiioc4_clearirq(drive);
- }
+ 	ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
+ 	if (ret)
+@@ -780,11 +1107,26 @@ int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
+ 	if (ret)
+ 		goto bail_attrs;
  
- static void
-@@ -352,6 +332,7 @@ sgiioc4_INB(unsigned long port)
- static int __devinit
- ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	void __iomem *virt_dma_base;
- 	int num_ports = sizeof (ioc4_dma_regs_t);
- 	void *pad;
-@@ -377,7 +358,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
- 	}
- 	hwif->dma_base = (unsigned long) virt_dma_base;
+-	snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+-	ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, unit);
+-	if (ret == 0)
+-		goto bail;
++	if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
++		ret = device_create_file(dev, &dev_attr_jint_idle_ticks);
++		if (ret)
++			goto bail_counter;
++		ret = device_create_file(dev, &dev_attr_jint_max_packets);
++		if (ret)
++			goto bail_idle;
  
--	hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
-+	hwif->dmatable_cpu = pci_alloc_consistent(dev,
- 					  IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
- 					  &hwif->dmatable_dma);
++		ret = sysfs_create_group(&dev->kobj, &dev_ibcfg_attr_group);
++		if (ret)
++			goto bail_max;
++	}
++
++	return 0;
++
++bail_max:
++	device_remove_file(dev, &dev_attr_jint_max_packets);
++bail_idle:
++	device_remove_file(dev, &dev_attr_jint_idle_ticks);
++bail_counter:
+ 	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+ bail_attrs:
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_group);
+@@ -794,12 +1136,14 @@ bail:
  
-@@ -386,7 +367,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
+ void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
+ {
+-	char unit[5];
++	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
  
- 	hwif->sg_max_nents = IOC4_PRD_ENTRIES;
+-	snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
+-	sysfs_remove_link(&dev->driver->kobj, unit);
++	if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
++		sysfs_remove_group(&dev->kobj, &dev_ibcfg_attr_group);
++		device_remove_file(dev, &dev_attr_jint_idle_ticks);
++		device_remove_file(dev, &dev_attr_jint_max_packets);
++	}
  
--	pad = pci_alloc_consistent(hwif->pci_dev, IOC4_IDE_CACHELINE_SIZE,
-+	pad = pci_alloc_consistent(dev, IOC4_IDE_CACHELINE_SIZE,
- 				   (dma_addr_t *) &(hwif->dma_status));
+-	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
+ 	sysfs_remove_group(&dev->kobj, &dev_attr_group);
  
- 	if (pad) {
-@@ -394,8 +375,7 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
- 		return 0;
- 	}
+ 	device_remove_file(dev, &dev_attr_reset);
+diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
+index b3df6f3..de67eed 100644
+--- a/drivers/infiniband/hw/ipath/ipath_ud.c
++++ b/drivers/infiniband/hw/ipath/ipath_ud.c
+@@ -301,8 +301,6 @@ int ipath_make_ud_req(struct ipath_qp *qp)
  
--	pci_free_consistent(hwif->pci_dev,
--			    IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
-+	pci_free_consistent(dev, IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
- 			    hwif->dmatable_cpu, hwif->dmatable_dma);
- 	printk(KERN_INFO
- 	       "%s() -- Error! Unable to allocate DMA Maps for drive %s\n",
-@@ -535,8 +515,7 @@ sgiioc4_build_dma_table(ide_drive_t * drive, struct request *rq, int ddir)
+ 	/* header size in 32-bit words LRH+BTH+DETH = (8+12+8)/4. */
+ 	qp->s_hdrwords = 7;
+-	if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM)
+-		qp->s_hdrwords++;
+ 	qp->s_cur_size = wqe->length;
+ 	qp->s_cur_sge = &qp->s_sge;
+ 	qp->s_wqe = wqe;
+@@ -327,6 +325,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
+ 		ohdr = &qp->s_hdr.u.oth;
  	}
+ 	if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
++		qp->s_hdrwords++;
+ 		ohdr->u.ud.imm_data = wqe->wr.imm_data;
+ 		bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
+ 	} else
+diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
+index c4c9984..32d8f88 100644
+--- a/drivers/infiniband/hw/ipath/ipath_verbs.c
++++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
+@@ -943,7 +943,7 @@ bail:
+  * ipath_verbs_send - send a packet
+  * @qp: the QP to send on
+  * @hdr: the packet header
+- * @hdrwords: the number of words in the header
++ * @hdrwords: the number of 32-bit words in the header
+  * @ss: the SGE to send
+  * @len: the length of the packet in bytes
+  */
+@@ -955,7 +955,10 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
+ 	int ret;
+ 	u32 dwords = (len + 3) >> 2;
  
- use_pio_instead:
--	pci_unmap_sg(hwif->pci_dev, hwif->sg_table, hwif->sg_nents,
--		     hwif->sg_dma_direction);
-+	ide_destroy_dmatable(drive);
+-	/* +1 is for the qword padding of pbc */
++	/*
++	 * Calculate the send buffer trigger address.
++	 * The +1 counts for the pbc control dword following the pbc length.
++	 */
+ 	plen = hdrwords + dwords + 1;
  
- 	return 0;		/* revert to PIO for this request */
+ 	/* Drop non-VL15 packets if we are not in the active state */
+@@ -1130,20 +1133,34 @@ static int ipath_query_device(struct ib_device *ibdev,
+ 	return 0;
  }
-@@ -574,7 +553,6 @@ static void __devinit
- ide_init_sgiioc4(ide_hwif_t * hwif)
- {
- 	hwif->mmio = 1;
--	hwif->pio_mask = 0x00;
- 	hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
- 	hwif->set_dma_mode = &sgiioc4_set_dma_mode;
- 	hwif->selectproc = NULL;/* Use the default routine to select drive */
-@@ -582,7 +560,6 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
- 	hwif->pre_reset = NULL;	/* No HBA specific pre_set needed */
- 	hwif->resetproc = &sgiioc4_resetproc;/* Reset DMA engine,
- 						clear interrupts */
--	hwif->intrproc = NULL;	/* Enable or Disable interrupt from drive */
- 	hwif->maskproc = &sgiioc4_maskproc;	/* Mask on/off NIEN register */
- 	hwif->quirkproc = NULL;
- 	hwif->busproc = NULL;
-@@ -592,20 +569,22 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
- 	if (hwif->dma_base == 0)
- 		return;
  
--	hwif->mwdma_mask = ATA_MWDMA2_ONLY;
--
-+	hwif->dma_host_set = &sgiioc4_dma_host_set;
- 	hwif->dma_setup = &sgiioc4_ide_dma_setup;
- 	hwif->dma_start = &sgiioc4_ide_dma_start;
- 	hwif->ide_dma_end = &sgiioc4_ide_dma_end;
--	hwif->ide_dma_on = &sgiioc4_ide_dma_on;
--	hwif->dma_off_quietly = &sgiioc4_dma_off_quietly;
- 	hwif->ide_dma_test_irq = &sgiioc4_ide_dma_test_irq;
--	hwif->dma_host_on = &sgiioc4_dma_host_on;
--	hwif->dma_host_off = &sgiioc4_dma_host_off;
- 	hwif->dma_lost_irq = &sgiioc4_dma_lost_irq;
- 	hwif->dma_timeout = &ide_dma_timeout;
- }
+-const u8 ipath_cvt_physportstate[16] = {
+-	[INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,
+-	[INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,
+-	[INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,
+-	[INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,
+-	[INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,
+-	[INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,
+-	[INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,
+-	[INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,
+-	[INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,
+-	[INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,
+-	[INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,
+-	[INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,
+-	[INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,
++const u8 ipath_cvt_physportstate[32] = {
++	[INFINIPATH_IBCS_LT_STATE_DISABLED] = IB_PHYSPORTSTATE_DISABLED,
++	[INFINIPATH_IBCS_LT_STATE_LINKUP] = IB_PHYSPORTSTATE_LINKUP,
++	[INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = IB_PHYSPORTSTATE_POLL,
++	[INFINIPATH_IBCS_LT_STATE_POLLQUIET] = IB_PHYSPORTSTATE_POLL,
++	[INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = IB_PHYSPORTSTATE_SLEEP,
++	[INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = IB_PHYSPORTSTATE_SLEEP,
++	[INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] =
++		IB_PHYSPORTSTATE_CFG_TRAIN,
++	[INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] =
++		IB_PHYSPORTSTATE_CFG_TRAIN,
++	[INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] =
++		IB_PHYSPORTSTATE_CFG_TRAIN,
++	[INFINIPATH_IBCS_LT_STATE_CFGIDLE] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] =
++		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
++	[INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] =
++		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
++	[INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] =
++		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
++	[0x10] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x11] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x12] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x13] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x14] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x15] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x16] = IB_PHYSPORTSTATE_CFG_TRAIN,
++	[0x17] = IB_PHYSPORTSTATE_CFG_TRAIN
+ };
  
-+static const struct ide_port_info sgiioc4_port_info __devinitdata = {
-+	.chipset		= ide_pci,
-+	.host_flags		= IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
-+				  IDE_HFLAG_NO_AUTOTUNE,
-+	.mwdma_mask		= ATA_MWDMA2_ONLY,
-+};
-+
- static int __devinit
- sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
- {
-@@ -615,6 +594,8 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
- 	ide_hwif_t *hwif;
- 	int h;
- 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
-+	hw_regs_t hw;
-+	struct ide_port_info d = sgiioc4_port_info;
+ u32 ipath_get_cr_errpkey(struct ipath_devdata *dd)
+@@ -1168,8 +1185,9 @@ static int ipath_query_port(struct ib_device *ibdev,
+ 	ibcstat = dd->ipath_lastibcstat;
+ 	props->state = ((ibcstat >> 4) & 0x3) + 1;
+ 	/* See phys_state_show() */
+-	props->phys_state = ipath_cvt_physportstate[
+-		dd->ipath_lastibcstat & 0xf];
++	props->phys_state = /* MEA: assumes shift == 0 */
++		ipath_cvt_physportstate[dd->ipath_lastibcstat &
++		dd->ibcs_lts_mask];
+ 	props->port_cap_flags = dev->port_cap_flags;
+ 	props->gid_tbl_len = 1;
+ 	props->max_msg_sz = 0x80000000;
+@@ -1641,6 +1659,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
+ 		cntrs.local_link_integrity_errors;
+ 	idev->z_excessive_buffer_overrun_errors =
+ 		cntrs.excessive_buffer_overrun_errors;
++	idev->z_vl15_dropped = cntrs.vl15_dropped;
  
  	/*
- 	 * Find an empty HWIF; if none available, return -ENOMEM.
-@@ -654,21 +635,15 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
- 		return -ENOMEM;
- 	}
+ 	 * The system image GUID is supposed to be the same for all
+diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
+index 6ccb54f..3d59736 100644
+--- a/drivers/infiniband/hw/ipath/ipath_verbs.h
++++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
+@@ -554,6 +554,7 @@ struct ipath_ibdev {
+ 	u32 z_pkey_violations;			/* starting count for PMA */
+ 	u32 z_local_link_integrity_errors;	/* starting count for PMA */
+ 	u32 z_excessive_buffer_overrun_errors;	/* starting count for PMA */
++	u32 z_vl15_dropped;			/* starting count for PMA */
+ 	u32 n_rc_resends;
+ 	u32 n_rc_acks;
+ 	u32 n_rc_qacks;
+@@ -598,6 +599,7 @@ struct ipath_verbs_counters {
+ 	u64 port_rcv_packets;
+ 	u32 local_link_integrity_errors;
+ 	u32 excessive_buffer_overrun_errors;
++	u32 vl15_dropped;
+ };
  
--	if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
--		hw_regs_t hw;
-+	/* Initialize the IO registers */
-+	memset(&hw, 0, sizeof(hw));
-+	sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
-+	hw.irq = dev->irq;
-+	hw.chipset = ide_pci;
-+	hw.dev = &dev->dev;
-+	ide_init_port_hw(hwif, &hw);
+ static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
+@@ -830,7 +832,17 @@ unsigned ipath_get_pkey(struct ipath_devdata *, unsigned);
  
--		/* Initialize the IO registers */
--		memset(&hw, 0, sizeof(hw));
--		sgiioc4_init_hwif_ports(&hw, cmd_base, ctl, irqport);
--		memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
--		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
--	}
--
--	hwif->irq = dev->irq;
--	hwif->chipset = ide_pci;
--	hwif->pci_dev = dev;
--	hwif->channel = 0;	/* Single Channel chip */
--	hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */
-+	hwif->dev = &dev->dev;
+ extern const enum ib_wc_opcode ib_ipath_wc_opcode[];
  
- 	/* The IOC4 uses MMIO rather than Port IO. */
- 	default_hwif_mmiops(hwif);
-@@ -676,15 +651,17 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev)
- 	/* Initializing chipset IRQ Registers */
- 	writel(0x03, (void __iomem *)(irqport + IOC4_INTR_SET * 4));
++/*
++ * Below converts HCA-specific LinkTrainingState to IB PhysPortState
++ * values.
++ */
+ extern const u8 ipath_cvt_physportstate[];
++#define IB_PHYSPORTSTATE_SLEEP 1
++#define IB_PHYSPORTSTATE_POLL 2
++#define IB_PHYSPORTSTATE_DISABLED 3
++#define IB_PHYSPORTSTATE_CFG_TRAIN 4
++#define IB_PHYSPORTSTATE_LINKUP 5
++#define IB_PHYSPORTSTATE_LINK_ERR_RECOVER 6
  
--	if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base))
-+	if (dma_base == 0 || ide_dma_sgiioc4(hwif, dma_base)) {
- 		printk(KERN_INFO "%s: %s Bus-Master DMA disabled\n",
- 				 hwif->name, DRV_NAME);
-+		d.mwdma_mask = 0;
-+	}
+ extern const int ib_ipath_state_ops[];
  
- 	ide_init_sgiioc4(hwif);
+diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
+index 9d32c49..7950aa6 100644
+--- a/drivers/infiniband/hw/mlx4/cq.c
++++ b/drivers/infiniband/hw/mlx4/cq.c
+@@ -313,6 +313,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
+ 	struct mlx4_ib_srq *srq;
+ 	int is_send;
+ 	int is_error;
++	u32 g_mlpath_rqpn;
+ 	u16 wqe_ctr;
  
- 	idx[0] = hwif->index;
+ 	cqe = next_cqe_sw(cq);
+@@ -426,10 +427,10 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
  
--	if (ide_device_add(idx))
-+	if (ide_device_add(idx, &d))
- 		return -EIO;
+ 		wc->slid	   = be16_to_cpu(cqe->rlid);
+ 		wc->sl		   = cqe->sl >> 4;
+-		wc->src_qp	   = be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff;
+-		wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f;
+-		wc->wc_flags      |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ?
+-			IB_WC_GRH : 0;
++		g_mlpath_rqpn	   = be32_to_cpu(cqe->g_mlpath_rqpn);
++		wc->src_qp	   = g_mlpath_rqpn & 0xffffff;
++		wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f;
++		wc->wc_flags	  |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0;
+ 		wc->pkey_index     = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
+ 	}
  
- 	return 0;
-diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
-index 5709c25..ef5b39f 100644
---- a/drivers/ide/pci/siimage.c
-+++ b/drivers/ide/pci/siimage.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/siimage.c		Version 1.19	Nov 16 2007
-- *
-  * Copyright (C) 2001-2002	Andre Hedrick <andre at linux-ide.org>
-  * Copyright (C) 2003		Red Hat <alan at redhat.com>
-  * Copyright (C) 2007		MontaVista Software, Inc.
-@@ -41,7 +39,6 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
- #include <linux/init.h>
-@@ -79,7 +76,7 @@ static int pdev_is_sata(struct pci_dev *pdev)
-  
- static inline int is_sata(ide_hwif_t *hwif)
- {
--	return pdev_is_sata(hwif->pci_dev);
-+	return pdev_is_sata(to_pci_dev(hwif->dev));
- }
+diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
+index d8287d9..96a39b5 100644
+--- a/drivers/infiniband/hw/mlx4/main.c
++++ b/drivers/infiniband/hw/mlx4/main.c
+@@ -52,7 +52,7 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
+ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_VERSION(DRV_VERSION);
  
- /**
-@@ -140,13 +137,14 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
- static u8 sil_pata_udma_filter(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = drive->hwif;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	unsigned long base = (unsigned long) hwif->hwif_data;
- 	u8 mask = 0, scsc = 0;
+-static const char mlx4_ib_version[] __devinitdata =
++static const char mlx4_ib_version[] =
+ 	DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
+ 	DRV_VERSION " (" DRV_RELDATE ")\n";
  
- 	if (hwif->mmio)
- 		scsc = hwif->INB(base + 0x4A);
- 	else
--		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
-+		pci_read_config_byte(dev, 0x8A, &scsc);
+@@ -468,6 +468,7 @@ static int init_node_data(struct mlx4_ib_dev *dev)
+ 	if (err)
+ 		goto out;
  
- 	if ((scsc & 0x30) == 0x10)	/* 133 */
- 		mask = ATA_UDMA6;
-@@ -219,19 +217,21 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
- 		mode |= (unit ? 0x10 : 0x01);
- 		hwif->OUTB(mode, base + addr_mask);
- 	} else {
--		pci_write_config_word(hwif->pci_dev, addr, speedp);
--		pci_write_config_word(hwif->pci_dev, tfaddr, speedt);
--		pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp);
-+		struct pci_dev *dev = to_pci_dev(hwif->dev);
-+
-+		pci_write_config_word(dev, addr, speedp);
-+		pci_write_config_word(dev, tfaddr, speedt);
-+		pci_read_config_word(dev, tfaddr - 2, &speedp);
- 		speedp &= ~0x200;
- 		/* Set IORDY for mode 3 or 4 */
- 		if (pio > 2)
- 			speedp |= 0x200;
--		pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp);
-+		pci_write_config_word(dev, tfaddr - 2, speedp);
++	dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
+ 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
  
--		pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
-+		pci_read_config_byte(dev, addr_mask, &mode);
- 		mode &= ~(unit ? 0x30 : 0x03);
- 		mode |= (unit ? 0x10 : 0x01);
--		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
-+		pci_write_config_byte(dev, addr_mask, mode);
- 	}
- }
+ out:
+@@ -516,9 +517,16 @@ static struct class_device_attribute *mlx4_class_attributes[] = {
  
-@@ -250,6 +250,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	u16 dma[]		= { 0x2208, 0x10C2, 0x10C1 };
+ static void *mlx4_ib_add(struct mlx4_dev *dev)
+ {
++	static int mlx4_ib_version_printed;
+ 	struct mlx4_ib_dev *ibdev;
+ 	int i;
  
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u16 ultra = 0, multi	= 0;
- 	u8 mode = 0, unit	= drive->select.b.unit;
- 	unsigned long base	= (unsigned long)hwif->hwif_data;
-@@ -266,10 +267,10 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 		multi = hwif->INW(ma);
- 		ultra = hwif->INW(ua);
- 	} else {
--		pci_read_config_byte(hwif->pci_dev, 0x8A, &scsc);
--		pci_read_config_byte(hwif->pci_dev, addr_mask, &mode);
--		pci_read_config_word(hwif->pci_dev, ma, &multi);
--		pci_read_config_word(hwif->pci_dev, ua, &ultra);
-+		pci_read_config_byte(dev, 0x8A, &scsc);
-+		pci_read_config_byte(dev, addr_mask, &mode);
-+		pci_read_config_word(dev, ma, &multi);
-+		pci_read_config_word(dev, ua, &ultra);
- 	}
++
++	if (!mlx4_ib_version_printed) {
++		printk(KERN_INFO "%s", mlx4_ib_version);
++		++mlx4_ib_version_printed;
++	}
++
+ 	ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev);
+ 	if (!ibdev) {
+ 		dev_err(&dev->pdev->dev, "Device struct alloc failed\n");
+diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
+index 6966f94..09a30dd 100644
+--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
++++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
+@@ -1255,9 +1255,14 @@ int mthca_QUERY_ADAPTER(struct mthca_dev *dev,
+ 	if (err)
+ 		goto out;
  
- 	mode &= ~((unit) ? 0x30 : 0x03);
-@@ -278,27 +279,14 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
+-	MTHCA_GET(adapter->vendor_id, outbox,   QUERY_ADAPTER_VENDOR_ID_OFFSET);
+-	MTHCA_GET(adapter->device_id, outbox,   QUERY_ADAPTER_DEVICE_ID_OFFSET);
+-	MTHCA_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
++	if (!mthca_is_memfree(dev)) {
++		MTHCA_GET(adapter->vendor_id, outbox,
++			  QUERY_ADAPTER_VENDOR_ID_OFFSET);
++		MTHCA_GET(adapter->device_id, outbox,
++			  QUERY_ADAPTER_DEVICE_ID_OFFSET);
++		MTHCA_GET(adapter->revision_id, outbox,
++			  QUERY_ADAPTER_REVISION_ID_OFFSET);
++	}
+ 	MTHCA_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
  
- 	scsc = is_sata(hwif) ? 1 : scsc;
+ 	get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
+diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
+index 15aa32e..7bbdd1f 100644
+--- a/drivers/infiniband/hw/mthca/mthca_dev.h
++++ b/drivers/infiniband/hw/mthca/mthca_dev.h
+@@ -60,13 +60,12 @@
+ enum {
+ 	MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
+ 	MTHCA_FLAG_SRQ        = 1 << 2,
+-	MTHCA_FLAG_MSI        = 1 << 3,
+-	MTHCA_FLAG_MSI_X      = 1 << 4,
+-	MTHCA_FLAG_NO_LAM     = 1 << 5,
+-	MTHCA_FLAG_FMR        = 1 << 6,
+-	MTHCA_FLAG_MEMFREE    = 1 << 7,
+-	MTHCA_FLAG_PCIE       = 1 << 8,
+-	MTHCA_FLAG_SINAI_OPT  = 1 << 9
++	MTHCA_FLAG_MSI_X      = 1 << 3,
++	MTHCA_FLAG_NO_LAM     = 1 << 4,
++	MTHCA_FLAG_FMR        = 1 << 5,
++	MTHCA_FLAG_MEMFREE    = 1 << 6,
++	MTHCA_FLAG_PCIE       = 1 << 7,
++	MTHCA_FLAG_SINAI_OPT  = 1 << 8
+ };
  
--	switch(speed) {
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_MW_DMA_0:
--			multi = dma[speed - XFER_MW_DMA_0];
--			mode |= ((unit) ? 0x20 : 0x02);
--			break;
--		case XFER_UDMA_6:
--		case XFER_UDMA_5:
--		case XFER_UDMA_4:
--		case XFER_UDMA_3:
--		case XFER_UDMA_2:
--		case XFER_UDMA_1:
--		case XFER_UDMA_0:
--			multi = dma[2];
--			ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) :
--					   (ultra5[speed - XFER_UDMA_0]));
--			mode |= ((unit) ? 0x30 : 0x03);
--			break;
--		default:
--			return;
-+	if (speed >= XFER_UDMA_0) {
-+		multi = dma[2];
-+		ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] :
-+				 ultra5[speed - XFER_UDMA_0]);
-+		mode |= (unit ? 0x30 : 0x03);
-+	} else {
-+		multi = dma[speed - XFER_MW_DMA_0];
-+		mode |= (unit ? 0x20 : 0x02);
- 	}
+ enum {
+diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
+index b29de51..b60eb5d 100644
+--- a/drivers/infiniband/hw/mthca/mthca_eq.c
++++ b/drivers/infiniband/hw/mthca/mthca_eq.c
+@@ -827,8 +827,7 @@ int mthca_init_eq_table(struct mthca_dev *dev)
+ 	if (err)
+ 		goto err_out_free;
  
- 	if (hwif->mmio) {
-@@ -306,9 +294,9 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 		hwif->OUTW(multi, ma);
- 		hwif->OUTW(ultra, ua);
+-	if (dev->mthca_flags & MTHCA_FLAG_MSI ||
+-	    dev->mthca_flags & MTHCA_FLAG_MSI_X) {
++	if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
+ 		dev->eq_table.clr_mask = 0;
  	} else {
--		pci_write_config_byte(hwif->pci_dev, addr_mask, mode);
--		pci_write_config_word(hwif->pci_dev, ma, multi);
--		pci_write_config_word(hwif->pci_dev, ua, ultra);
-+		pci_write_config_byte(dev, addr_mask, mode);
-+		pci_write_config_word(dev, ma, multi);
-+		pci_write_config_word(dev, ua, ultra);
- 	}
- }
+ 		dev->eq_table.clr_mask =
+@@ -839,8 +838,7 @@ int mthca_init_eq_table(struct mthca_dev *dev)
  
-@@ -316,6 +304,7 @@ static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
- static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 dma_altstat		= 0;
- 	unsigned long addr	= siimage_selreg(hwif, 1);
+ 	dev->eq_table.arm_mask = 0;
  
-@@ -324,7 +313,7 @@ static int siimage_io_ide_dma_test_irq (ide_drive_t *drive)
- 		return 1;
+-	intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
+-		128 : dev->eq_table.inta_pin;
++	intr = dev->eq_table.inta_pin;
  
- 	/* return 1 if Device INTR asserted */
--	pci_read_config_byte(hwif->pci_dev, addr, &dma_altstat);
-+	pci_read_config_byte(dev, addr, &dma_altstat);
- 	if (dma_altstat & 8)
- 		return 0;	//return 1;
- 	return 0;
-@@ -342,15 +331,18 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
- 	unsigned long addr	= siimage_selreg(hwif, 0x1);
-+	void __iomem *sata_error_addr
-+		= (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
+ 	err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
+ 			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
+diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
+index 60de6f9..cd3d8ad 100644
+--- a/drivers/infiniband/hw/mthca/mthca_main.c
++++ b/drivers/infiniband/hw/mthca/mthca_main.c
+@@ -65,14 +65,9 @@ static int msi_x = 1;
+ module_param(msi_x, int, 0444);
+ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
  
--	if (SATA_ERROR_REG) {
-+	if (sata_error_addr) {
- 		unsigned long base = (unsigned long)hwif->hwif_data;
+-static int msi = 0;
+-module_param(msi, int, 0444);
+-MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero (deprecated, use MSI-X instead)");
 -
- 		u32 ext_stat = readl((void __iomem *)(base + 0x10));
- 		u8 watchdog = 0;
-+
- 		if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
--			u32 sata_error = readl((void __iomem *)SATA_ERROR_REG);
--			writel(sata_error, (void __iomem *)SATA_ERROR_REG);
-+			u32 sata_error = readl(sata_error_addr);
-+
-+			writel(sata_error, sata_error_addr);
- 			watchdog = (sata_error & 0x00680000) ? 1 : 0;
- 			printk(KERN_WARNING "%s: sata_error = 0x%08x, "
- 				"watchdog = %d, %s\n",
-@@ -390,13 +382,14 @@ static int siimage_mmio_ide_dma_test_irq (ide_drive_t *drive)
- static int sil_sata_busproc(ide_drive_t * drive, int state)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u32 stat_config		= 0;
- 	unsigned long addr	= siimage_selreg(hwif, 0);
+ #else /* CONFIG_PCI_MSI */
  
- 	if (hwif->mmio)
- 		stat_config = readl((void __iomem *)addr);
- 	else
--		pci_read_config_dword(hwif->pci_dev, addr, &stat_config);
-+		pci_read_config_dword(dev, addr, &stat_config);
+ #define msi_x (0)
+-#define msi   (0)
  
- 	switch (state) {
- 		case BUSSTATE_ON:
-@@ -428,13 +421,17 @@ static int sil_sata_busproc(ide_drive_t * drive, int state)
+ #endif /* CONFIG_PCI_MSI */
  
- static int sil_sata_reset_poll(ide_drive_t *drive)
- {
--	if (SATA_STATUS_REG) {
--		ide_hwif_t *hwif	= HWIF(drive);
-+	ide_hwif_t *hwif = drive->hwif;
-+	void __iomem *sata_status_addr
-+		= (void __iomem *)hwif->sata_scr[SATA_STATUS_OFFSET];
+@@ -131,7 +126,7 @@ module_param_named(fmr_reserved_mtts, hca_profile.fmr_reserved_mtts, int, 0444);
+ MODULE_PARM_DESC(fmr_reserved_mtts,
+ 		 "number of memory translation table segments reserved for FMR");
  
--		/* SATA_STATUS_REG is valid only when in MMIO mode */
--		if ((readl((void __iomem *)SATA_STATUS_REG) & 0x03) != 0x03) {
-+	if (sata_status_addr) {
-+		/* SATA Status is available only when in MMIO mode */
-+		u32 sata_stat = readl(sata_status_addr);
-+
-+		if ((sata_stat & 0x03) != 0x03) {
- 			printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n",
--				hwif->name, readl((void __iomem *)SATA_STATUS_REG));
-+					    hwif->name, sata_stat);
- 			HWGROUP(drive)->polling = 0;
- 			return ide_started;
- 		}
-@@ -656,7 +653,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch
+-static const char mthca_version[] __devinitdata =
++static char mthca_version[] __devinitdata =
+ 	DRV_NAME ": Mellanox InfiniBand HCA driver v"
+ 	DRV_VERSION " (" DRV_RELDATE ")\n";
  
- static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
- {
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	void *addr		= pci_get_drvdata(dev);
- 	u8 ch			= hwif->channel;
- 	hw_regs_t		hw;
-@@ -726,9 +723,6 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
- 	const char *s = &drive->id->model[0];
- 	unsigned len;
+@@ -740,7 +735,8 @@ static int mthca_init_hca(struct mthca_dev *mdev)
+ 	}
  
--	if (!drive->present)
--		return 0;
--
- 	len = strnlen(s, sizeof(drive->id->model));
+ 	mdev->eq_table.inta_pin = adapter.inta_pin;
+-	mdev->rev_id            = adapter.revision_id;
++	if (!mthca_is_memfree(mdev))
++		mdev->rev_id = adapter.revision_id;
+ 	memcpy(mdev->board_id, adapter.board_id, sizeof mdev->board_id);
  
- 	if ((len > 4) && (!memcmp(s, "ST", 2))) {
-@@ -743,18 +737,20 @@ static int is_dev_seagate_sata(ide_drive_t *drive)
- }
+ 	return 0;
+@@ -816,13 +812,11 @@ static int mthca_setup_hca(struct mthca_dev *dev)
  
- /**
-- *	siimage_fixup		-	post probe fixups
-- *	@hwif: interface to fix up
-+ *	sil_quirkproc		-	post probe fixups
-+ *	@drive: drive
-  *
-  *	Called after drive probe we use this to decide whether the
-  *	Seagate fixup must be applied. This used to be in init_iops but
-  *	that can occur before we know what drives are present.
-  */
+ 	err = mthca_NOP(dev, &status);
+ 	if (err || status) {
+-		if (dev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X)) {
++		if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
+ 			mthca_warn(dev, "NOP command failed to generate interrupt "
+ 				   "(IRQ %d).\n",
+-				   dev->mthca_flags & MTHCA_FLAG_MSI_X ?
+-				   dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector :
+-				   dev->pdev->irq);
+-			mthca_warn(dev, "Trying again with MSI/MSI-X disabled.\n");
++				   dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector);
++			mthca_warn(dev, "Trying again with MSI-X disabled.\n");
+ 		} else {
+ 			mthca_err(dev, "NOP command failed to generate interrupt "
+ 				  "(IRQ %d), aborting.\n",
+@@ -1005,7 +999,7 @@ static struct {
+ 			   .flags     = 0 },
+ 	[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 8, 200),
+ 			   .flags     = MTHCA_FLAG_PCIE },
+-	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 2, 0),
++	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 3, 0),
+ 			   .flags     = MTHCA_FLAG_MEMFREE |
+ 					MTHCA_FLAG_PCIE },
+ 	[SINAI]        = { .latest_fw = MTHCA_FW_VER(1, 2, 0),
+@@ -1128,29 +1122,12 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
  
--static void __devinit siimage_fixup(ide_hwif_t *hwif)
-+static void __devinit sil_quirkproc(ide_drive_t *drive)
- {
-+	ide_hwif_t *hwif = drive->hwif;
-+
- 	/* Try and raise the rqsize */
--	if (!is_sata(hwif) || !is_dev_seagate_sata(&hwif->drives[0]))
-+	if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
- 		hwif->rqsize = 128;
- }
+ 	if (msi_x && !mthca_enable_msi_x(mdev))
+ 		mdev->mthca_flags |= MTHCA_FLAG_MSI_X;
+-	else if (msi) {
+-		static int warned;
+-
+-		if (!warned) {
+-			printk(KERN_WARNING PFX "WARNING: MSI support will be "
+-			       "removed from the ib_mthca driver in January 2008.\n");
+-			printk(KERN_WARNING "    If you are using MSI and cannot "
+-			       "switch to MSI-X, please tell "
+-			       "<general at lists.openfabrics.org>.\n");
+-			++warned;
+-		}
+-
+-		if (!pci_enable_msi(pdev))
+-			mdev->mthca_flags |= MTHCA_FLAG_MSI;
+-	}
  
-@@ -770,12 +766,14 @@ static void __devinit siimage_fixup(ide_hwif_t *hwif)
+ 	err = mthca_setup_hca(mdev);
+-	if (err == -EBUSY && (mdev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X))) {
++	if (err == -EBUSY && (mdev->mthca_flags & MTHCA_FLAG_MSI_X)) {
+ 		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
+ 			pci_disable_msix(pdev);
+-		if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+-			pci_disable_msi(pdev);
+-		mdev->mthca_flags &= ~(MTHCA_FLAG_MSI_X | MTHCA_FLAG_MSI);
++		mdev->mthca_flags &= ~MTHCA_FLAG_MSI_X;
  
- static void __devinit init_iops_siimage(ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+
- 	hwif->hwif_data = NULL;
+ 		err = mthca_setup_hca(mdev);
+ 	}
+@@ -1192,8 +1169,6 @@ err_cleanup:
+ err_close:
+ 	if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
+ 		pci_disable_msix(pdev);
+-	if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+-		pci_disable_msi(pdev);
  
- 	/* Pessimal until we finish probing */
- 	hwif->rqsize = 15;
+ 	mthca_close_hca(mdev);
  
--	if (pci_get_drvdata(hwif->pci_dev) == NULL)
-+	if (pci_get_drvdata(dev) == NULL)
- 		return;
+@@ -1246,8 +1221,6 @@ static void __mthca_remove_one(struct pci_dev *pdev)
  
- 	init_mmio_iops_siimage(hwif);
-@@ -791,11 +789,12 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
+ 		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
+ 			pci_disable_msix(pdev);
+-		if (mdev->mthca_flags & MTHCA_FLAG_MSI)
+-			pci_disable_msi(pdev);
  
- static u8 __devinit ata66_siimage(ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	unsigned long addr = siimage_selreg(hwif, 0);
- 	u8 ata66 = 0;
+ 		ib_dealloc_device(&mdev->ib_dev);
+ 		mthca_release_regions(pdev, mdev->mthca_flags &
+diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
+index aa6c70a..3b69855 100644
+--- a/drivers/infiniband/hw/mthca/mthca_mr.c
++++ b/drivers/infiniband/hw/mthca/mthca_mr.c
+@@ -613,8 +613,10 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
+ 			sizeof *(mr->mem.tavor.mpt) * idx;
+ 
+ 	mr->mtt = __mthca_alloc_mtt(dev, list_len, dev->mr_table.fmr_mtt_buddy);
+-	if (IS_ERR(mr->mtt))
++	if (IS_ERR(mr->mtt)) {
++		err = PTR_ERR(mr->mtt);
+ 		goto err_out_table;
++	}
+ 
+ 	mtt_seg = mr->mtt->first_seg * MTHCA_MTT_SEG_SIZE;
+ 
+@@ -627,8 +629,10 @@ int mthca_fmr_alloc(struct mthca_dev *dev, u32 pd,
+ 		mr->mem.tavor.mtts = dev->mr_table.tavor_fmr.mtt_base + mtt_seg;
+ 
+ 	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
+-	if (IS_ERR(mailbox))
++	if (IS_ERR(mailbox)) {
++		err = PTR_ERR(mailbox);
+ 		goto err_out_free_mtt;
++	}
+ 
+ 	mpt_entry = mailbox->buf;
+ 
+diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
+index 6bcde1c..9e491df 100644
+--- a/drivers/infiniband/hw/mthca/mthca_provider.c
++++ b/drivers/infiniband/hw/mthca/mthca_provider.c
+@@ -923,17 +923,13 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd       *pd,
+ 	struct mthca_mr *mr;
+ 	u64 *page_list;
+ 	u64 total_size;
+-	u64 mask;
++	unsigned long mask;
+ 	int shift;
+ 	int npages;
+ 	int err;
+ 	int i, j, n;
  
--	if (pci_get_drvdata(hwif->pci_dev) == NULL)
--		pci_read_config_byte(hwif->pci_dev, addr, &ata66);
-+	if (pci_get_drvdata(dev) == NULL)
-+		pci_read_config_byte(dev, addr, &ata66);
- 	else
- 		ata66 = hwif->INB(addr);
+-	/* First check that we have enough alignment */
+-	if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK))
+-		return ERR_PTR(-EINVAL);
+-
+-	mask = 0;
++	mask = buffer_list[0].addr ^ *iova_start;
+ 	total_size = 0;
+ 	for (i = 0; i < num_phys_buf; ++i) {
+ 		if (i != 0)
+@@ -947,17 +943,7 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd       *pd,
+ 	if (mask & ~PAGE_MASK)
+ 		return ERR_PTR(-EINVAL);
  
-@@ -817,6 +816,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
+-	/* Find largest page shift we can use to cover buffers */
+-	for (shift = PAGE_SHIFT; shift < 31; ++shift)
+-		if (num_phys_buf > 1) {
+-			if ((1ULL << shift) & mask)
+-				break;
+-		} else {
+-			if (1ULL << shift >=
+-			    buffer_list[0].size +
+-			    (buffer_list[0].addr & ((1ULL << shift) - 1)))
+-				break;
+-		}
++	shift = __ffs(mask | 1 << 31);
  
- 	hwif->set_pio_mode = &sil_set_pio_mode;
- 	hwif->set_dma_mode = &sil_set_dma_mode;
-+	hwif->quirkproc = &sil_quirkproc;
+ 	buffer_list[0].size += buffer_list[0].addr & ((1ULL << shift) - 1);
+ 	buffer_list[0].addr &= ~0ull << shift;
+@@ -1270,6 +1256,8 @@ static int mthca_init_node_data(struct mthca_dev *dev)
+ 		goto out;
+ 	}
  
- 	if (sata) {
- 		static int first = 1;
-@@ -833,15 +833,14 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
- 	} else
- 		hwif->udma_filter = &sil_pata_udma_filter;
++	if (mthca_is_memfree(dev))
++		dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
+ 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
  
-+	hwif->cable_detect = ata66_siimage;
+ out:
+diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
+index 0e5461c..db5595b 100644
+--- a/drivers/infiniband/hw/mthca/mthca_qp.c
++++ b/drivers/infiniband/hw/mthca/mthca_qp.c
+@@ -1175,6 +1175,7 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
+ {
+ 	int ret;
+ 	int i;
++	struct mthca_next_seg *next;
+ 
+ 	qp->refcount = 1;
+ 	init_waitqueue_head(&qp->wait);
+@@ -1217,7 +1218,6 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
+ 	}
+ 
+ 	if (mthca_is_memfree(dev)) {
+-		struct mthca_next_seg *next;
+ 		struct mthca_data_seg *scatter;
+ 		int size = (sizeof (struct mthca_next_seg) +
+ 			    qp->rq.max_gs * sizeof (struct mthca_data_seg)) / 16;
+@@ -1240,6 +1240,13 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
+ 						    qp->sq.wqe_shift) +
+ 						   qp->send_wqe_offset);
+ 		}
++	} else {
++		for (i = 0; i < qp->rq.max; ++i) {
++			next = get_recv_wqe(qp, i);
++			next->nda_op = htonl((((i + 1) % qp->rq.max) <<
++					      qp->rq.wqe_shift) | 1);
++		}
 +
- 	if (hwif->dma_base == 0)
- 		return;
+ 	}
  
- 	if (sata)
- 		hwif->host_flags |= IDE_HFLAG_NO_ATAPI_DMA;
+ 	qp->sq.last = get_send_wqe(qp, qp->sq.max - 1);
+@@ -1863,7 +1870,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+ 		prev_wqe = qp->rq.last;
+ 		qp->rq.last = wqe;
  
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = ata66_siimage(hwif);
--
- 	if (hwif->mmio) {
- 		hwif->ide_dma_test_irq = &siimage_mmio_ide_dma_test_irq;
- 	} else {
-@@ -855,7 +854,6 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif)
- 		.init_chipset	= init_chipset_siimage,	\
- 		.init_iops	= init_iops_siimage,	\
- 		.init_hwif	= init_hwif_siimage,	\
--		.fixup		= siimage_fixup,	\
- 		.host_flags	= IDE_HFLAG_BOOTABLE,	\
- 		.pio_mask	= ATA_PIO4,		\
- 		.mwdma_mask	= ATA_MWDMA2,		\
-diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
-index d90b429..512bb4c 100644
---- a/drivers/ide/pci/sis5513.c
-+++ b/drivers/ide/pci/sis5513.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/sis5513.c	Version 0.31	Aug 9, 2007
-- *
-  * Copyright (C) 1999-2000	Andre Hedrick <andre at linux-ide.org>
-  * Copyright (C) 2002		Lionel Bouton <Lionel.Bouton at inet6.fr>, Maintainer
-  * Copyright (C) 2003		Vojtech Pavlik <vojtech at suse.cz>
-@@ -49,20 +47,11 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
--
--#include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
+-		((struct mthca_next_seg *) wqe)->nda_op = 0;
+ 		((struct mthca_next_seg *) wqe)->ee_nds =
+ 			cpu_to_be32(MTHCA_NEXT_DBD);
+ 		((struct mthca_next_seg *) wqe)->flags = 0;
+@@ -1885,9 +1891,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
  
--#include <asm/irq.h>
--
- #include "ide-timing.h"
+ 		qp->wrid[ind] = wr->wr_id;
  
- /* registers layout and init values are chipset family dependant */
-@@ -197,7 +186,7 @@ static char* chipset_capability[] = {
+-		((struct mthca_next_seg *) prev_wqe)->nda_op =
+-			cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
+-		wmb();
+ 		((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ 			cpu_to_be32(MTHCA_NEXT_DBD | size);
  
- static u8 sis_ata133_get_base(ide_drive_t *drive)
+diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
+index 553d681..a5ffff6 100644
+--- a/drivers/infiniband/hw/mthca/mthca_srq.c
++++ b/drivers/infiniband/hw/mthca/mthca_srq.c
+@@ -175,9 +175,17 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
+ 	 * scatter list L_Keys to the sentry value of 0x100.
+ 	 */
+ 	for (i = 0; i < srq->max; ++i) {
+-		wqe = get_wqe(srq, i);
++		struct mthca_next_seg *next;
+ 
+-		*wqe_to_link(wqe) = i < srq->max - 1 ? i + 1 : -1;
++		next = wqe = get_wqe(srq, i);
++
++		if (i < srq->max - 1) {
++			*wqe_to_link(wqe) = i + 1;
++			next->nda_op = htonl(((i + 1) << srq->wqe_shift) | 1);
++		} else {
++			*wqe_to_link(wqe) = -1;
++			next->nda_op = 0;
++		}
+ 
+ 		for (scatter = wqe + sizeof (struct mthca_next_seg);
+ 		     (void *) scatter < wqe + (1 << srq->wqe_shift);
+@@ -470,16 +478,15 @@ out:
+ void mthca_free_srq_wqe(struct mthca_srq *srq, u32 wqe_addr)
  {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u32 reg54 = 0;
+ 	int ind;
++	struct mthca_next_seg *last_free;
  
- 	pci_read_config_dword(dev, 0x54, &reg54);
-@@ -207,7 +196,7 @@ static u8 sis_ata133_get_base(ide_drive_t *drive)
+ 	ind = wqe_addr >> srq->wqe_shift;
  
- static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
- {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u16 t1 = 0;
- 	u8 drive_pci = 0x40 + drive->dn * 2;
+ 	spin_lock(&srq->lock);
  
-@@ -230,7 +219,7 @@ static void sis_ata16_program_timings(ide_drive_t *drive, const u8 mode)
+-	if (likely(srq->first_free >= 0))
+-		*wqe_to_link(get_wqe(srq, srq->last_free)) = ind;
+-	else
+-		srq->first_free = ind;
+-
++	last_free = get_wqe(srq, srq->last_free);
++	*wqe_to_link(last_free) = ind;
++	last_free->nda_op = htonl((ind << srq->wqe_shift) | 1);
+ 	*wqe_to_link(get_wqe(srq, ind)) = -1;
+ 	srq->last_free = ind;
  
- static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
- {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u8 t1, drive_pci = 0x40 + drive->dn * 2;
+@@ -506,15 +513,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ 	first_ind = srq->first_free;
  
- 	/* timing bits: 7:4 active 3:0 recovery */
-@@ -253,7 +242,7 @@ static void sis_ata100_program_timings(ide_drive_t *drive, const u8 mode)
+ 	for (nreq = 0; wr; wr = wr->next) {
+-		ind = srq->first_free;
+-
+-		if (unlikely(ind < 0)) {
+-			mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+-			err = -ENOMEM;
+-			*bad_wr = wr;
+-			break;
+-		}
+-
++		ind       = srq->first_free;
+ 		wqe       = get_wqe(srq, ind);
+ 		next_ind  = *wqe_to_link(wqe);
+ 
+@@ -528,7 +527,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ 		prev_wqe  = srq->last;
+ 		srq->last = wqe;
+ 
+-		((struct mthca_next_seg *) wqe)->nda_op = 0;
+ 		((struct mthca_next_seg *) wqe)->ee_nds = 0;
+ 		/* flags field will always remain 0 */
+ 
+@@ -549,9 +547,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ 		if (i < srq->max_gs)
+ 			mthca_set_data_seg_inval(wqe);
  
- static void sis_ata133_program_timings(ide_drive_t *drive, const u8 mode)
- {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u32 t1 = 0;
- 	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
+-		((struct mthca_next_seg *) prev_wqe)->nda_op =
+-			cpu_to_be32((ind << srq->wqe_shift) | 1);
+-		wmb();
+ 		((struct mthca_next_seg *) prev_wqe)->ee_nds =
+ 			cpu_to_be32(MTHCA_NEXT_DBD);
  
-@@ -286,7 +275,7 @@ static void sis_program_timings(ide_drive_t *drive, const u8 mode)
- static void config_drive_art_rwp (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 reg4bh		= 0;
- 	u8 rw_prefetch		= 0;
+@@ -614,15 +609,7 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ 	spin_lock_irqsave(&srq->lock, flags);
  
-@@ -305,64 +294,61 @@ static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	sis_program_timings(drive, XFER_PIO_0 + pio);
- }
+ 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
+-		ind = srq->first_free;
+-
+-		if (unlikely(ind < 0)) {
+-			mthca_err(dev, "SRQ %06x full\n", srq->srqn);
+-			err = -ENOMEM;
+-			*bad_wr = wr;
+-			break;
+-		}
+-
++		ind       = srq->first_free;
+ 		wqe       = get_wqe(srq, ind);
+ 		next_ind  = *wqe_to_link(wqe);
  
-+static void sis_ata133_program_udma_timings(ide_drive_t *drive, const u8 mode)
+@@ -633,8 +620,6 @@ int mthca_arbel_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
+ 			break;
+ 		}
+ 
+-		((struct mthca_next_seg *) wqe)->nda_op =
+-			cpu_to_be32((next_ind << srq->wqe_shift) | 1);
+ 		((struct mthca_next_seg *) wqe)->ee_nds = 0;
+ 		/* flags field will always remain 0 */
+ 
+diff --git a/drivers/infiniband/hw/nes/Kconfig b/drivers/infiniband/hw/nes/Kconfig
+new file mode 100644
+index 0000000..2aeb7ac
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/Kconfig
+@@ -0,0 +1,16 @@
++config INFINIBAND_NES
++	tristate "NetEffect RNIC Driver"
++	depends on PCI && INET && INFINIBAND
++	select LIBCRC32C
++	---help---
++	  This is a low-level driver for NetEffect RDMA enabled
++	  Network Interface Cards (RNIC).
++
++config INFINIBAND_NES_DEBUG
++	bool "Verbose debugging output"
++	depends on INFINIBAND_NES
++	default n
++	---help---
++	  This option causes the NetEffect RNIC driver to produce debug
++	  messages.  Select this if you are developing the driver
++	  or trying to diagnose a problem.
+diff --git a/drivers/infiniband/hw/nes/Makefile b/drivers/infiniband/hw/nes/Makefile
+new file mode 100644
+index 0000000..3514851
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/Makefile
+@@ -0,0 +1,3 @@
++obj-$(CONFIG_INFINIBAND_NES) += iw_nes.o
++
++iw_nes-objs := nes.o nes_hw.o nes_nic.o nes_utils.o nes_verbs.o nes_cm.o
+diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
+new file mode 100644
+index 0000000..7f8853b
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes.c
+@@ -0,0 +1,1152 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/if_vlan.h>
++#include <linux/crc32.h>
++#include <linux/in.h>
++#include <linux/fs.h>
++#include <linux/init.h>
++#include <linux/if_arp.h>
++#include <linux/highmem.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/byteorder.h>
++#include <rdma/ib_smi.h>
++#include <rdma/ib_verbs.h>
++#include <rdma/ib_pack.h>
++#include <rdma/iw_cm.h>
++
++#include "nes.h"
++
++#include <net/netevent.h>
++#include <net/neighbour.h>
++#include <linux/route.h>
++#include <net/ip_fib.h>
++
++MODULE_AUTHOR("NetEffect");
++MODULE_DESCRIPTION("NetEffect RNIC Low-level iWARP Driver");
++MODULE_LICENSE("Dual BSD/GPL");
++MODULE_VERSION(DRV_VERSION);
++
++int max_mtu = 9000;
++int nics_per_function = 1;
++int interrupt_mod_interval = 0;
++
++
++/* Interoperability */
++int mpa_version = 1;
++module_param(mpa_version, int, 0);
++MODULE_PARM_DESC(mpa_version, "MPA version to be used int MPA Req/Resp (0 or 1)");
++
++/* Interoperability */
++int disable_mpa_crc = 0;
++module_param(disable_mpa_crc, int, 0);
++MODULE_PARM_DESC(disable_mpa_crc, "Disable checking of MPA CRC");
++
++unsigned int send_first = 0;
++module_param(send_first, int, 0);
++MODULE_PARM_DESC(send_first, "Send RDMA Message First on Active Connection");
++
++
++unsigned int nes_drv_opt = 0;
++module_param(nes_drv_opt, int, 0);
++MODULE_PARM_DESC(nes_drv_opt, "Driver option parameters");
++
++unsigned int nes_debug_level = 0;
++module_param_named(debug_level, nes_debug_level, uint, 0644);
++MODULE_PARM_DESC(debug_level, "Enable debug output level");
++
++LIST_HEAD(nes_adapter_list);
++LIST_HEAD(nes_dev_list);
++
++atomic_t qps_destroyed;
++atomic_t cqp_reqs_allocated;
++atomic_t cqp_reqs_freed;
++atomic_t cqp_reqs_dynallocated;
++atomic_t cqp_reqs_dynfreed;
++atomic_t cqp_reqs_queued;
++atomic_t cqp_reqs_redriven;
++
++static void nes_print_macaddr(struct net_device *netdev);
++static irqreturn_t nes_interrupt(int, void *);
++static int __devinit nes_probe(struct pci_dev *, const struct pci_device_id *);
++static void __devexit nes_remove(struct pci_dev *);
++static int __init nes_init_module(void);
++static void __exit nes_exit_module(void);
++static unsigned int ee_flsh_adapter;
++static unsigned int sysfs_nonidx_addr;
++static unsigned int sysfs_idx_addr;
++
++static struct pci_device_id nes_pci_table[] = {
++	{PCI_VENDOR_ID_NETEFFECT, PCI_DEVICE_ID_NETEFFECT_NE020, PCI_ANY_ID, PCI_ANY_ID},
++	{0}
++};
++
++MODULE_DEVICE_TABLE(pci, nes_pci_table);
++
++static int nes_inetaddr_event(struct notifier_block *, unsigned long, void *);
++static int nes_net_event(struct notifier_block *, unsigned long, void *);
++static int nes_notifiers_registered;
++
++
++static struct notifier_block nes_inetaddr_notifier = {
++	.notifier_call = nes_inetaddr_event
++};
++
++static struct notifier_block nes_net_notifier = {
++	.notifier_call = nes_net_event
++};
++
++
++
++
++/**
++ * nes_inetaddr_event
++ */
++static int nes_inetaddr_event(struct notifier_block *notifier,
++		unsigned long event, void *ptr)
++{
++	struct in_ifaddr *ifa = ptr;
++	struct net_device *event_netdev = ifa->ifa_dev->dev;
++	struct nes_device *nesdev;
++	struct net_device *netdev;
++	struct nes_vnic *nesvnic;
++	unsigned int addr;
++	unsigned int mask;
++
++	addr = ntohl(ifa->ifa_address);
++	mask = ntohl(ifa->ifa_mask);
++	nes_debug(NES_DBG_NETDEV, "nes_inetaddr_event: ip address %08X, netmask %08X.\n",
++			addr, mask);
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p. (%s)\n",
++				nesdev, nesdev->netdev[0]->name);
++		netdev = nesdev->netdev[0];
++		nesvnic = netdev_priv(netdev);
++		if (netdev == event_netdev) {
++			if (nesvnic->rdma_enabled == 0) {
++				nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since"
++						" RDMA is not enabled.\n",
++						netdev->name);
++				return NOTIFY_OK;
++			}
++			/* we have ifa->ifa_address/mask here if we need it */
++			switch (event) {
++				case NETDEV_DOWN:
++					nes_debug(NES_DBG_NETDEV, "event:DOWN\n");
++					nes_write_indexed(nesdev,
++							NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)), 0);
++
++					nes_manage_arp_cache(netdev, netdev->dev_addr,
++							ntohl(nesvnic->local_ipaddr), NES_ARP_DELETE);
++					nesvnic->local_ipaddr = 0;
++					return NOTIFY_OK;
++					break;
++				case NETDEV_UP:
++					nes_debug(NES_DBG_NETDEV, "event:UP\n");
++
++					if (nesvnic->local_ipaddr != 0) {
++						nes_debug(NES_DBG_NETDEV, "Interface already has local_ipaddr\n");
++						return NOTIFY_OK;
++					}
++					/* Add the address to the IP table */
++					nesvnic->local_ipaddr = ifa->ifa_address;
++
++					nes_write_indexed(nesdev,
++							NES_IDX_DST_IP_ADDR+(0x10*PCI_FUNC(nesdev->pcidev->devfn)),
++							ntohl(ifa->ifa_address));
++					nes_manage_arp_cache(netdev, netdev->dev_addr,
++							ntohl(nesvnic->local_ipaddr), NES_ARP_ADD);
++					return NOTIFY_OK;
++					break;
++				default:
++					break;
++			}
++		}
++	}
++
++	return NOTIFY_DONE;
++}
++
++
++/**
++ * nes_net_event
++ */
++static int nes_net_event(struct notifier_block *notifier,
++		unsigned long event, void *ptr)
++{
++	struct neighbour *neigh = ptr;
++	struct nes_device *nesdev;
++	struct net_device *netdev;
++	struct nes_vnic *nesvnic;
++
++	switch (event) {
++		case NETEVENT_NEIGH_UPDATE:
++			list_for_each_entry(nesdev, &nes_dev_list, list) {
++				/* nes_debug(NES_DBG_NETDEV, "Nesdev list entry = 0x%p.\n", nesdev); */
++				netdev = nesdev->netdev[0];
++				nesvnic = netdev_priv(netdev);
++				if (netdev == neigh->dev) {
++					if (nesvnic->rdma_enabled == 0) {
++						nes_debug(NES_DBG_NETDEV, "Skipping device %s since no RDMA\n",
++								netdev->name);
++					} else {
++						if (neigh->nud_state & NUD_VALID) {
++							nes_manage_arp_cache(neigh->dev, neigh->ha,
++									ntohl(*(__be32 *)neigh->primary_key), NES_ARP_ADD);
++						} else {
++							nes_manage_arp_cache(neigh->dev, neigh->ha,
++									ntohl(*(__be32 *)neigh->primary_key), NES_ARP_DELETE);
++						}
++					}
++					return NOTIFY_OK;
++				}
++			}
++			break;
++		default:
++			nes_debug(NES_DBG_NETDEV, "NETEVENT_ %lu undefined\n", event);
++			break;
++	}
++
++	return NOTIFY_DONE;
++}
++
++
++/**
++ * nes_add_ref
++ */
++void nes_add_ref(struct ib_qp *ibqp)
++{
++	struct nes_qp *nesqp;
++
++	nesqp = to_nesqp(ibqp);
++	nes_debug(NES_DBG_QP, "Bumping refcount for QP%u.  Pre-inc value = %u\n",
++			ibqp->qp_num, atomic_read(&nesqp->refcount));
++	atomic_inc(&nesqp->refcount);
++}
++
++static void nes_cqp_rem_ref_callback(struct nes_device *nesdev, struct nes_cqp_request *cqp_request)
++{
++	unsigned long flags;
++	struct nes_qp *nesqp = cqp_request->cqp_callback_pointer;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 qp_id;
++
++	atomic_inc(&qps_destroyed);
++
++	/* Free the control structures */
++
++	qp_id = nesqp->hwqp.qp_id;
++	if (nesqp->pbl_vbase) {
++		pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
++				nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase);
++		spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++		nesadapter->free_256pbl++;
++		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++		pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase);
++		nesqp->pbl_vbase = NULL;
++
++	} else {
++		pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
++				nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase);
++	}
++	nes_free_resource(nesadapter, nesadapter->allocated_qps, nesqp->hwqp.qp_id);
++
++	kfree(nesqp->allocated_buffer);
++
++}
++
++/**
++ * nes_rem_ref
++ */
++void nes_rem_ref(struct ib_qp *ibqp)
++{
++	u64 u64temp;
++	struct nes_qp *nesqp;
++	struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_cqp_request *cqp_request;
++	u32 opcode;
++
++	nesqp = to_nesqp(ibqp);
++
++	if (atomic_read(&nesqp->refcount) == 0) {
++		printk(KERN_INFO PFX "%s: Reference count already 0 for QP%d, last aeq = 0x%04X.\n",
++				__FUNCTION__, ibqp->qp_num, nesqp->last_aeq);
++		BUG();
++	}
++
++	if (atomic_dec_and_test(&nesqp->refcount)) {
++		nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = NULL;
++
++		/* Destroy the QP */
++		cqp_request = nes_get_cqp_request(nesdev);
++		if (cqp_request == NULL) {
++			nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
++			return;
++		}
++		cqp_request->waiting = 0;
++		cqp_request->callback = 1;
++		cqp_request->cqp_callback = nes_cqp_rem_ref_callback;
++		cqp_request->cqp_callback_pointer = nesqp;
++		cqp_wqe = &cqp_request->cqp_wqe;
++
++		nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++		opcode = NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_IWARP;
++
++		if (nesqp->hte_added) {
++			opcode  |= NES_CQP_QP_DEL_HTE;
++			nesqp->hte_added = 0;
++		}
++		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
++		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
++		u64temp = (u64)nesqp->nesqp_context_pbase;
++		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
++		nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++	}
++}
++
++
++/**
++ * nes_get_qp
++ */
++struct ib_qp *nes_get_qp(struct ib_device *device, int qpn)
++{
++	struct nes_vnic *nesvnic = to_nesvnic(device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++
++	if ((qpn < NES_FIRST_QPN) || (qpn >= (NES_FIRST_QPN + nesadapter->max_qp)))
++		return NULL;
++
++	return &nesadapter->qp_table[qpn - NES_FIRST_QPN]->ibqp;
++}
++
++
++/**
++ * nes_print_macaddr
++ */
++static void nes_print_macaddr(struct net_device *netdev)
++{
++	nes_debug(NES_DBG_INIT, "%s: MAC %02X:%02X:%02X:%02X:%02X:%02X, IRQ %u\n",
++			netdev->name,
++			netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
++			netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5],
++			netdev->irq);
++}
++
++
++/**
++ * nes_interrupt - handle interrupts
++ */
++static irqreturn_t nes_interrupt(int irq, void *dev_id)
++{
++	struct nes_device *nesdev = (struct nes_device *)dev_id;
++	int handled = 0;
++	u32 int_mask;
++	u32 int_req;
++	u32 int_stat;
++	u32 intf_int_stat;
++	u32 timer_stat;
++
++	if (nesdev->msi_enabled) {
++		/* No need to read the interrupt pending register if msi is enabled */
++		handled = 1;
++	} else {
++		if (unlikely(nesdev->nesadapter->hw_rev == NE020_REV)) {
++			/* Master interrupt enable provides synchronization for kicking off bottom half
++			  when interrupt sharing is going on */
++			int_mask = nes_read32(nesdev->regs + NES_INT_MASK);
++			if (int_mask & 0x80000000) {
++				/* Check interrupt status to see if this might be ours */
++				int_stat = nes_read32(nesdev->regs + NES_INT_STAT);
++				int_req = nesdev->int_req;
++				if (int_stat&int_req) {
++					/* if interesting CEQ or AEQ is pending, claim the interrupt */
++					if ((int_stat&int_req) & (~(NES_INT_TIMER|NES_INT_INTF))) {
++						handled = 1;
++					} else {
++						if (((int_stat & int_req) & NES_INT_TIMER) == NES_INT_TIMER) {
++							/* Timer might be running but might be for another function */
++							timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT);
++							if ((timer_stat & nesdev->timer_int_req) != 0) {
++								handled = 1;
++							}
++						}
++						if ((((int_stat & int_req) & NES_INT_INTF) == NES_INT_INTF) &&
++								(handled == 0)) {
++							intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
++							if ((intf_int_stat & nesdev->intf_int_req) != 0) {
++								handled = 1;
++							}
++						}
++					}
++					if (handled) {
++						nes_write32(nesdev->regs+NES_INT_MASK, int_mask & (~0x80000000));
++						int_mask = nes_read32(nesdev->regs+NES_INT_MASK);
++						/* Save off the status to save an additional read */
++						nesdev->int_stat = int_stat;
++						nesdev->napi_isr_ran = 1;
++					}
++				}
++			}
++		} else {
++			handled = nes_read32(nesdev->regs+NES_INT_PENDING);
++		}
++	}
++
++	if (handled) {
++
++		if (nes_napi_isr(nesdev) == 0) {
++			tasklet_schedule(&nesdev->dpc_tasklet);
++
++		}
++		return IRQ_HANDLED;
++	} else {
++		return IRQ_NONE;
++	}
++}
++
++
++/**
++ * nes_probe - Device initialization
++ */
++static int __devinit nes_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
++{
++	struct net_device *netdev = NULL;
++	struct nes_device *nesdev = NULL;
++	int ret = 0;
++	struct nes_vnic *nesvnic = NULL;
++	void __iomem *mmio_regs = NULL;
++	u8 hw_rev;
++
++	assert(pcidev != NULL);
++	assert(ent != NULL);
++
++	printk(KERN_INFO PFX "NetEffect RNIC driver v%s loading. (%s)\n",
++			DRV_VERSION, pci_name(pcidev));
++
++	ret = pci_enable_device(pcidev);
++	if (ret) {
++		printk(KERN_ERR PFX "Unable to enable PCI device. (%s)\n", pci_name(pcidev));
++		goto bail0;
++	}
++
++	nes_debug(NES_DBG_INIT, "BAR0 (@0x%08lX) size = 0x%lX bytes\n",
++			(long unsigned int)pci_resource_start(pcidev, BAR_0),
++			(long unsigned int)pci_resource_len(pcidev, BAR_0));
++	nes_debug(NES_DBG_INIT, "BAR1 (@0x%08lX) size = 0x%lX bytes\n",
++			(long unsigned int)pci_resource_start(pcidev, BAR_1),
++			(long unsigned int)pci_resource_len(pcidev, BAR_1));
++
++	/* Make sure PCI base addr are MMIO */
++	if (!(pci_resource_flags(pcidev, BAR_0) & IORESOURCE_MEM) ||
++			!(pci_resource_flags(pcidev, BAR_1) & IORESOURCE_MEM)) {
++		printk(KERN_ERR PFX "PCI regions not an MMIO resource\n");
++		ret = -ENODEV;
++		goto bail1;
++	}
++
++	/* Reserve PCI I/O and memory resources */
++	ret = pci_request_regions(pcidev, DRV_NAME);
++	if (ret) {
++		printk(KERN_ERR PFX "Unable to request regions. (%s)\n", pci_name(pcidev));
++		goto bail1;
++	}
++
++	if ((sizeof(dma_addr_t) > 4)) {
++		ret = pci_set_dma_mask(pcidev, DMA_64BIT_MASK);
++		if (ret < 0) {
++			printk(KERN_ERR PFX "64b DMA mask configuration failed\n");
++			goto bail2;
++		}
++		ret = pci_set_consistent_dma_mask(pcidev, DMA_64BIT_MASK);
++		if (ret) {
++			printk(KERN_ERR PFX "64b DMA consistent mask configuration failed\n");
++			goto bail2;
++		}
++	} else {
++		ret = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
++		if (ret < 0) {
++			printk(KERN_ERR PFX "32b DMA mask configuration failed\n");
++			goto bail2;
++		}
++		ret = pci_set_consistent_dma_mask(pcidev, DMA_32BIT_MASK);
++		if (ret) {
++			printk(KERN_ERR PFX "32b DMA consistent mask configuration failed\n");
++			goto bail2;
++		}
++	}
++
++	pci_set_master(pcidev);
++
++	/* Allocate hardware structure */
++	nesdev = kzalloc(sizeof(struct nes_device), GFP_KERNEL);
++	if (!nesdev) {
++		printk(KERN_ERR PFX "%s: Unable to alloc hardware struct\n", pci_name(pcidev));
++		ret = -ENOMEM;
++		goto bail2;
++	}
++
++	nes_debug(NES_DBG_INIT, "Allocated nes device at %p\n", nesdev);
++	nesdev->pcidev = pcidev;
++	pci_set_drvdata(pcidev, nesdev);
++
++	pci_read_config_byte(pcidev, 0x0008, &hw_rev);
++	nes_debug(NES_DBG_INIT, "hw_rev=%u\n", hw_rev);
++
++	spin_lock_init(&nesdev->indexed_regs_lock);
++
++	/* Remap the PCI registers in adapter BAR0 to kernel VA space */
++	mmio_regs = ioremap_nocache(pci_resource_start(pcidev, BAR_0), sizeof(mmio_regs));
++	if (mmio_regs == NULL) {
++		printk(KERN_ERR PFX "Unable to remap BAR0\n");
++		ret = -EIO;
++		goto bail3;
++	}
++	nesdev->regs = mmio_regs;
++	nesdev->index_reg = 0x50 + (PCI_FUNC(pcidev->devfn)*8) + mmio_regs;
++
++	/* Ensure interrupts are disabled */
++	nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff);
++
++	if (nes_drv_opt & NES_DRV_OPT_ENABLE_MSI) {
++		if (!pci_enable_msi(nesdev->pcidev)) {
++			nesdev->msi_enabled = 1;
++			nes_debug(NES_DBG_INIT, "MSI is enabled for device %s\n",
++					pci_name(pcidev));
++		} else {
++			nes_debug(NES_DBG_INIT, "MSI is disabled by linux for device %s\n",
++					pci_name(pcidev));
++		}
++	} else {
++		nes_debug(NES_DBG_INIT, "MSI not requested due to driver options for device %s\n",
++				pci_name(pcidev));
++	}
++
++	nesdev->csr_start = pci_resource_start(nesdev->pcidev, BAR_0);
++	nesdev->doorbell_region = pci_resource_start(nesdev->pcidev, BAR_1);
++
++	/* Init the adapter */
++	nesdev->nesadapter = nes_init_adapter(nesdev, hw_rev);
++	nesdev->nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval;
++	if (!nesdev->nesadapter) {
++		printk(KERN_ERR PFX "Unable to initialize adapter.\n");
++		ret = -ENOMEM;
++		goto bail5;
++	}
++
++	/* nesdev->base_doorbell_index =
++			nesdev->nesadapter->pd_config_base[PCI_FUNC(nesdev->pcidev->devfn)]; */
++	nesdev->base_doorbell_index = 1;
++	nesdev->doorbell_start = nesdev->nesadapter->doorbell_start;
++	nesdev->mac_index = PCI_FUNC(nesdev->pcidev->devfn) % nesdev->nesadapter->port_count;
++
++	tasklet_init(&nesdev->dpc_tasklet, nes_dpc, (unsigned long)nesdev);
++
++	/* bring up the Control QP */
++	if (nes_init_cqp(nesdev)) {
++		ret = -ENODEV;
++		goto bail6;
++	}
++
++	/* Arm the CCQ */
++	nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
++			PCI_FUNC(nesdev->pcidev->devfn));
++	nes_read32(nesdev->regs+NES_CQE_ALLOC);
++
++	/* Enable the interrupts */
++	nesdev->int_req = (0x101 << PCI_FUNC(nesdev->pcidev->devfn)) |
++			(1 << (PCI_FUNC(nesdev->pcidev->devfn)+16));
++	if (PCI_FUNC(nesdev->pcidev->devfn) < 4) {
++		nesdev->int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+24));
++	}
++
++	/* TODO: This really should be the first driver to load, not function 0 */
++	if (PCI_FUNC(nesdev->pcidev->devfn) == 0) {
++		/* pick up PCI and critical errors if the first driver to load */
++		nesdev->intf_int_req = NES_INTF_INT_PCIERR | NES_INTF_INT_CRITERR;
++		nesdev->int_req |= NES_INT_INTF;
++	} else {
++		nesdev->intf_int_req = 0;
++	}
++	nesdev->intf_int_req |= (1 << (PCI_FUNC(nesdev->pcidev->devfn)+16));
++	nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS0, 0);
++	nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 0);
++	nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS2, 0x00001265);
++	nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS4, 0x18021804);
++
++	nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS3, 0x17801790);
++
++	/* deal with both periodic and one_shot */
++	nesdev->timer_int_req = 0x101 << PCI_FUNC(nesdev->pcidev->devfn);
++	nesdev->nesadapter->timer_int_req |= nesdev->timer_int_req;
++	nes_debug(NES_DBG_INIT, "setting int_req for function %u, nesdev = 0x%04X, adapter = 0x%04X\n",
++			PCI_FUNC(nesdev->pcidev->devfn),
++			nesdev->timer_int_req, nesdev->nesadapter->timer_int_req);
++
++	nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
++
++	list_add_tail(&nesdev->list, &nes_dev_list);
++
++	/* Request an interrupt line for the driver */
++	ret = request_irq(pcidev->irq, nes_interrupt, IRQF_SHARED, DRV_NAME, nesdev);
++	if (ret) {
++		printk(KERN_ERR PFX "%s: requested IRQ %u is busy\n",
++				pci_name(pcidev), pcidev->irq);
++		goto bail65;
++	}
++
++	nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
++
++	if (nes_notifiers_registered == 0) {
++		register_inetaddr_notifier(&nes_inetaddr_notifier);
++		register_netevent_notifier(&nes_net_notifier);
++	}
++	nes_notifiers_registered++;
++
++	/* Initialize network devices */
++		if ((netdev = nes_netdev_init(nesdev, mmio_regs)) == NULL) {
++			goto bail7;
++		}
++
++		/* Register network device */
++		ret = register_netdev(netdev);
++		if (ret) {
++			printk(KERN_ERR PFX "Unable to register netdev, ret = %d\n", ret);
++			nes_netdev_destroy(netdev);
++			goto bail7;
++		}
++
++		nes_print_macaddr(netdev);
++		/* create a CM core for this netdev */
++		nesvnic = netdev_priv(netdev);
++
++		nesdev->netdev_count++;
++		nesdev->nesadapter->netdev_count++;
++
++
++	printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded.\n",
++			pci_name(pcidev));
++	return 0;
++
++	bail7:
++	printk(KERN_ERR PFX "bail7\n");
++	while (nesdev->netdev_count > 0) {
++		nesdev->netdev_count--;
++		nesdev->nesadapter->netdev_count--;
++
++		unregister_netdev(nesdev->netdev[nesdev->netdev_count]);
++		nes_netdev_destroy(nesdev->netdev[nesdev->netdev_count]);
++	}
++
++	nes_debug(NES_DBG_INIT, "netdev_count=%d, nesadapter->netdev_count=%d\n",
++			nesdev->netdev_count, nesdev->nesadapter->netdev_count);
++
++	nes_notifiers_registered--;
++	if (nes_notifiers_registered == 0) {
++		unregister_netevent_notifier(&nes_net_notifier);
++		unregister_inetaddr_notifier(&nes_inetaddr_notifier);
++	}
++
++	list_del(&nesdev->list);
++	nes_destroy_cqp(nesdev);
++
++	bail65:
++	printk(KERN_ERR PFX "bail65\n");
++	free_irq(pcidev->irq, nesdev);
++	if (nesdev->msi_enabled) {
++		pci_disable_msi(pcidev);
++	}
++	bail6:
++	printk(KERN_ERR PFX "bail6\n");
++	tasklet_kill(&nesdev->dpc_tasklet);
++	/* Deallocate the Adapter Structure */
++	nes_destroy_adapter(nesdev->nesadapter);
++
++	bail5:
++	printk(KERN_ERR PFX "bail5\n");
++	iounmap(nesdev->regs);
++
++	bail3:
++	printk(KERN_ERR PFX "bail3\n");
++	kfree(nesdev);
++
++	bail2:
++	pci_release_regions(pcidev);
++
++	bail1:
++	pci_disable_device(pcidev);
++
++	bail0:
++	return ret;
++}
++
++
++/**
++ * nes_remove - unload from kernel
++ */
++static void __devexit nes_remove(struct pci_dev *pcidev)
++{
++	struct nes_device *nesdev = pci_get_drvdata(pcidev);
++	struct net_device *netdev;
++	int netdev_index = 0;
++
++		if (nesdev->netdev_count) {
++			netdev = nesdev->netdev[netdev_index];
++			if (netdev) {
++				netif_stop_queue(netdev);
++				unregister_netdev(netdev);
++				nes_netdev_destroy(netdev);
++
++				nesdev->netdev[netdev_index] = NULL;
++				nesdev->netdev_count--;
++				nesdev->nesadapter->netdev_count--;
++			}
++		}
++
++	nes_notifiers_registered--;
++	if (nes_notifiers_registered == 0) {
++		unregister_netevent_notifier(&nes_net_notifier);
++		unregister_inetaddr_notifier(&nes_inetaddr_notifier);
++	}
++
++	list_del(&nesdev->list);
++	nes_destroy_cqp(nesdev);
++	tasklet_kill(&nesdev->dpc_tasklet);
++
++	/* Deallocate the Adapter Structure */
++	nes_destroy_adapter(nesdev->nesadapter);
++
++	free_irq(pcidev->irq, nesdev);
++
++	if (nesdev->msi_enabled) {
++		pci_disable_msi(pcidev);
++	}
++
++	iounmap(nesdev->regs);
++	kfree(nesdev);
++
++	/* nes_debug(NES_DBG_SHUTDOWN, "calling pci_release_regions.\n"); */
++	pci_release_regions(pcidev);
++	pci_disable_device(pcidev);
++	pci_set_drvdata(pcidev, NULL);
++}
++
++
++static struct pci_driver nes_pci_driver = {
++	.name = DRV_NAME,
++	.id_table = nes_pci_table,
++	.probe = nes_probe,
++	.remove = __devexit_p(nes_remove),
++};
++
++static ssize_t nes_show_adapter(struct device_driver *ddp, char *buf)
++{
++	unsigned int  devfn = 0xffffffff;
++	unsigned char bus_number = 0xff;
++	unsigned int  i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			devfn      = nesdev->nesadapter->devfn;
++			bus_number = nesdev->nesadapter->bus_number;
++			break;
++		}
++		i++;
++	}
++
++	return snprintf(buf, PAGE_SIZE, "%x:%x", bus_number, devfn);
++}
++
++static ssize_t nes_store_adapter(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++
++	ee_flsh_adapter = simple_strtoul(p, &p, 10);
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf)
++{
++	u32 eeprom_cmd = 0xdead;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			eeprom_cmd = nes_read32(nesdev->regs + NES_EEPROM_COMMAND);
++			break;
++		}
++		i++;
++	}
++	return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd);
++}
++
++static ssize_t nes_store_ee_cmd(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
++		val = simple_strtoul(p, &p, 16);
++		list_for_each_entry(nesdev, &nes_dev_list, list) {
++			if (i == ee_flsh_adapter) {
++				nes_write32(nesdev->regs + NES_EEPROM_COMMAND, val);
++				break;
++			}
++			i++;
++		}
++	}
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf)
++{
++	u32 eeprom_data = 0xdead;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			eeprom_data = nes_read32(nesdev->regs + NES_EEPROM_DATA);
++			break;
++		}
++		i++;
++	}
++
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data);
++}
++
++static ssize_t nes_store_ee_data(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
++		val = simple_strtoul(p, &p, 16);
++		list_for_each_entry(nesdev, &nes_dev_list, list) {
++			if (i == ee_flsh_adapter) {
++				nes_write32(nesdev->regs + NES_EEPROM_DATA, val);
++				break;
++			}
++			i++;
++		}
++	}
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf)
++{
++	u32 flash_cmd = 0xdead;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			flash_cmd = nes_read32(nesdev->regs + NES_FLASH_COMMAND);
++			break;
++		}
++		i++;
++	}
++
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd);
++}
++
++static ssize_t nes_store_flash_cmd(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
++		val = simple_strtoul(p, &p, 16);
++		list_for_each_entry(nesdev, &nes_dev_list, list) {
++			if (i == ee_flsh_adapter) {
++				nes_write32(nesdev->regs + NES_FLASH_COMMAND, val);
++				break;
++			}
++			i++;
++		}
++	}
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf)
++{
++	u32 flash_data = 0xdead;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			flash_data = nes_read32(nesdev->regs + NES_FLASH_DATA);
++			break;
++		}
++		i++;
++	}
++
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data);
++}
++
++static ssize_t nes_store_flash_data(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
++		val = simple_strtoul(p, &p, 16);
++		list_for_each_entry(nesdev, &nes_dev_list, list) {
++			if (i == ee_flsh_adapter) {
++				nes_write32(nesdev->regs + NES_FLASH_DATA, val);
++				break;
++			}
++			i++;
++		}
++	}
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_nonidx_addr(struct device_driver *ddp, char *buf)
++{
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_nonidx_addr);
++}
++
++static ssize_t nes_store_nonidx_addr(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X')
++		sysfs_nonidx_addr = simple_strtoul(p, &p, 16);
++
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_nonidx_data(struct device_driver *ddp, char *buf)
++{
++	u32 nonidx_data = 0xdead;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			nonidx_data = nes_read32(nesdev->regs + sysfs_nonidx_addr);
++			break;
++		}
++		i++;
++	}
++
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", nonidx_data);
++}
++
++static ssize_t nes_store_nonidx_data(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
++		val = simple_strtoul(p, &p, 16);
++		list_for_each_entry(nesdev, &nes_dev_list, list) {
++			if (i == ee_flsh_adapter) {
++				nes_write32(nesdev->regs + sysfs_nonidx_addr, val);
++				break;
++			}
++			i++;
++		}
++	}
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_idx_addr(struct device_driver *ddp, char *buf)
++{
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", sysfs_idx_addr);
++}
++
++static ssize_t nes_store_idx_addr(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X')
++		sysfs_idx_addr = simple_strtoul(p, &p, 16);
++
++	return strnlen(buf, count);
++}
++
++static ssize_t nes_show_idx_data(struct device_driver *ddp, char *buf)
++{
++	u32 idx_data = 0xdead;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	list_for_each_entry(nesdev, &nes_dev_list, list) {
++		if (i == ee_flsh_adapter) {
++			idx_data = nes_read_indexed(nesdev, sysfs_idx_addr);
++			break;
++		}
++		i++;
++	}
++
++	return  snprintf(buf, PAGE_SIZE, "0x%x\n", idx_data);
++}
++
++static ssize_t nes_store_idx_data(struct device_driver *ddp,
++	const char *buf, size_t count)
++{
++	char *p = (char *)buf;
++	u32 val;
++	u32 i = 0;
++	struct nes_device *nesdev;
++
++	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
++		val = simple_strtoul(p, &p, 16);
++		list_for_each_entry(nesdev, &nes_dev_list, list) {
++			if (i == ee_flsh_adapter) {
++				nes_write_indexed(nesdev, sysfs_idx_addr, val);
++				break;
++			}
++			i++;
++		}
++	}
++	return strnlen(buf, count);
++}
++
++static DRIVER_ATTR(adapter, S_IRUSR | S_IWUSR,
++		   nes_show_adapter, nes_store_adapter);
++static DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR,
++		   nes_show_ee_cmd, nes_store_ee_cmd);
++static DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR,
++		   nes_show_ee_data, nes_store_ee_data);
++static DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR,
++		   nes_show_flash_cmd, nes_store_flash_cmd);
++static DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR,
++		   nes_show_flash_data, nes_store_flash_data);
++static DRIVER_ATTR(nonidx_addr, S_IRUSR | S_IWUSR,
++		   nes_show_nonidx_addr, nes_store_nonidx_addr);
++static DRIVER_ATTR(nonidx_data, S_IRUSR | S_IWUSR,
++		   nes_show_nonidx_data, nes_store_nonidx_data);
++static DRIVER_ATTR(idx_addr, S_IRUSR | S_IWUSR,
++		   nes_show_idx_addr, nes_store_idx_addr);
++static DRIVER_ATTR(idx_data, S_IRUSR | S_IWUSR,
++		   nes_show_idx_data, nes_store_idx_data);
++
++static int nes_create_driver_sysfs(struct pci_driver *drv)
++{
++	int error;
++	error  = driver_create_file(&drv->driver, &driver_attr_adapter);
++	error |= driver_create_file(&drv->driver, &driver_attr_eeprom_cmd);
++	error |= driver_create_file(&drv->driver, &driver_attr_eeprom_data);
++	error |= driver_create_file(&drv->driver, &driver_attr_flash_cmd);
++	error |= driver_create_file(&drv->driver, &driver_attr_flash_data);
++	error |= driver_create_file(&drv->driver, &driver_attr_nonidx_addr);
++	error |= driver_create_file(&drv->driver, &driver_attr_nonidx_data);
++	error |= driver_create_file(&drv->driver, &driver_attr_idx_addr);
++	error |= driver_create_file(&drv->driver, &driver_attr_idx_data);
++	return error;
++}
++
++static void nes_remove_driver_sysfs(struct pci_driver *drv)
++{
++	driver_remove_file(&drv->driver, &driver_attr_adapter);
++	driver_remove_file(&drv->driver, &driver_attr_eeprom_cmd);
++	driver_remove_file(&drv->driver, &driver_attr_eeprom_data);
++	driver_remove_file(&drv->driver, &driver_attr_flash_cmd);
++	driver_remove_file(&drv->driver, &driver_attr_flash_data);
++	driver_remove_file(&drv->driver, &driver_attr_nonidx_addr);
++	driver_remove_file(&drv->driver, &driver_attr_nonidx_data);
++	driver_remove_file(&drv->driver, &driver_attr_idx_addr);
++	driver_remove_file(&drv->driver, &driver_attr_idx_data);
++}
++
++/**
++ * nes_init_module - module initialization entry point
++ */
++static int __init nes_init_module(void)
++{
++	int retval;
++	int retval1;
++
++	retval = nes_cm_start();
++	if (retval) {
++		printk(KERN_ERR PFX "Unable to start NetEffect iWARP CM.\n");
++		return retval;
++	}
++	retval = pci_register_driver(&nes_pci_driver);
++	if (retval >= 0) {
++		retval1 = nes_create_driver_sysfs(&nes_pci_driver);
++		if (retval1 < 0)
++			printk(KERN_ERR PFX "Unable to create NetEffect sys files.\n");
++	}
++	return retval;
++}
++
++
++/**
++ * nes_exit_module - module unload entry point
++ */
++static void __exit nes_exit_module(void)
++{
++	nes_cm_stop();
++	nes_remove_driver_sysfs(&nes_pci_driver);
++
++	pci_unregister_driver(&nes_pci_driver);
++}
++
++
++module_init(nes_init_module);
++module_exit(nes_exit_module);
+diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h
+new file mode 100644
+index 0000000..fd57e8a
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes.h
+@@ -0,0 +1,560 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef __NES_H
++#define __NES_H
++
++#include <linux/netdevice.h>
++#include <linux/inetdevice.h>
++#include <linux/spinlock.h>
++#include <linux/kernel.h>
++#include <linux/delay.h>
++#include <linux/pci.h>
++#include <linux/dma-mapping.h>
++#include <linux/workqueue.h>
++#include <linux/slab.h>
++#include <asm/semaphore.h>
++#include <linux/version.h>
++#include <asm/io.h>
++#include <linux/crc32c.h>
++
++#include <rdma/ib_smi.h>
++#include <rdma/ib_verbs.h>
++#include <rdma/ib_pack.h>
++#include <rdma/rdma_cm.h>
++#include <rdma/iw_cm.h>
++
++#define NES_SEND_FIRST_WRITE
++
++#define QUEUE_DISCONNECTS
++
++#define DRV_BUILD   "1"
++
++#define DRV_NAME    "iw_nes"
++#define DRV_VERSION "1.0 KO Build " DRV_BUILD
++#define PFX         DRV_NAME ": "
++
++/*
++ * NetEffect PCI vendor id and NE010 PCI device id.
++ */
++#ifndef PCI_VENDOR_ID_NETEFFECT	/* not in pci.ids yet */
++#define PCI_VENDOR_ID_NETEFFECT       0x1678
++#define PCI_DEVICE_ID_NETEFFECT_NE020 0x0100
++#endif
++
++#define NE020_REV   4
++#define NE020_REV1  5
++
++#define BAR_0       0
++#define BAR_1       2
++
++#define RX_BUF_SIZE             (1536 + 8)
++#define NES_REG0_SIZE           (4 * 1024)
++#define NES_TX_TIMEOUT          (6*HZ)
++#define NES_FIRST_QPN           64
++#define NES_SW_CONTEXT_ALIGN    1024
++
++#define NES_NIC_MAX_NICS        16
++#define NES_MAX_ARP_TABLE_SIZE  4096
++
++#define NES_NIC_CEQ_SIZE        8
++/* NICs will be on a separate CQ */
++#define NES_CCEQ_SIZE ((nesadapter->max_cq / nesadapter->port_count) - 32)
++
++#define NES_MAX_PORT_COUNT 4
++
++#define MAX_DPC_ITERATIONS               128
++
++#define NES_CQP_REQUEST_NO_DOORBELL_RING 0
++#define NES_CQP_REQUEST_RING_DOORBELL    1
++
++#define NES_DRV_OPT_ENABLE_MPA_VER_0     0x00000001
++#define NES_DRV_OPT_DISABLE_MPA_CRC      0x00000002
++#define NES_DRV_OPT_DISABLE_FIRST_WRITE  0x00000004
++#define NES_DRV_OPT_DISABLE_INTF         0x00000008
++#define NES_DRV_OPT_ENABLE_MSI           0x00000010
++#define NES_DRV_OPT_DUAL_LOGICAL_PORT    0x00000020
++#define NES_DRV_OPT_SUPRESS_OPTION_BC    0x00000040
++#define NES_DRV_OPT_NO_INLINE_DATA       0x00000080
++#define NES_DRV_OPT_DISABLE_INT_MOD      0x00000100
++#define NES_DRV_OPT_DISABLE_VIRT_WQ      0x00000200
++
++#define NES_AEQ_EVENT_TIMEOUT         2500
++#define NES_DISCONNECT_EVENT_TIMEOUT  2000
++
++/* debug levels */
++/* must match userspace */
++#define NES_DBG_HW          0x00000001
++#define NES_DBG_INIT        0x00000002
++#define NES_DBG_ISR         0x00000004
++#define NES_DBG_PHY         0x00000008
++#define NES_DBG_NETDEV      0x00000010
++#define NES_DBG_CM          0x00000020
++#define NES_DBG_CM1         0x00000040
++#define NES_DBG_NIC_RX      0x00000080
++#define NES_DBG_NIC_TX      0x00000100
++#define NES_DBG_CQP         0x00000200
++#define NES_DBG_MMAP        0x00000400
++#define NES_DBG_MR          0x00000800
++#define NES_DBG_PD          0x00001000
++#define NES_DBG_CQ          0x00002000
++#define NES_DBG_QP          0x00004000
++#define NES_DBG_MOD_QP      0x00008000
++#define NES_DBG_AEQ         0x00010000
++#define NES_DBG_IW_RX       0x00020000
++#define NES_DBG_IW_TX       0x00040000
++#define NES_DBG_SHUTDOWN    0x00080000
++#define NES_DBG_RSVD1       0x10000000
++#define NES_DBG_RSVD2       0x20000000
++#define NES_DBG_RSVD3       0x40000000
++#define NES_DBG_RSVD4       0x80000000
++#define NES_DBG_ALL         0xffffffff
++
++#ifdef CONFIG_INFINIBAND_NES_DEBUG
++#define nes_debug(level, fmt, args...) \
++	if (level & nes_debug_level) \
++		printk(KERN_ERR PFX "%s[%u]: " fmt, __FUNCTION__, __LINE__, ##args)
++
++#define assert(expr)                                                \
++if (!(expr)) {                                                       \
++	printk(KERN_ERR PFX "Assertion failed! %s, %s, %s, line %d\n",  \
++		   #expr, __FILE__, __FUNCTION__, __LINE__);                \
++}
++
++#define NES_EVENT_TIMEOUT   1200000
++#else
++#define nes_debug(level, fmt, args...)
++#define assert(expr)          do {} while (0)
++
++#define NES_EVENT_TIMEOUT   100000
++#endif
++
++#include "nes_hw.h"
++#include "nes_verbs.h"
++#include "nes_context.h"
++#include "nes_user.h"
++#include "nes_cm.h"
++
++extern int max_mtu;
++extern int nics_per_function;
++#define max_frame_len (max_mtu+ETH_HLEN)
++extern int interrupt_mod_interval;
++extern int nes_if_count;
++extern int mpa_version;
++extern int disable_mpa_crc;
++extern unsigned int send_first;
++extern unsigned int nes_drv_opt;
++extern unsigned int nes_debug_level;
++
++extern struct list_head nes_adapter_list;
++extern struct list_head nes_dev_list;
++
++extern struct nes_cm_core *g_cm_core;
++
++extern atomic_t cm_connects;
++extern atomic_t cm_accepts;
++extern atomic_t cm_disconnects;
++extern atomic_t cm_closes;
++extern atomic_t cm_connecteds;
++extern atomic_t cm_connect_reqs;
++extern atomic_t cm_rejects;
++extern atomic_t mod_qp_timouts;
++extern atomic_t qps_created;
++extern atomic_t qps_destroyed;
++extern atomic_t sw_qps_destroyed;
++extern u32 mh_detected;
++extern u32 mh_pauses_sent;
++extern u32 cm_packets_sent;
++extern u32 cm_packets_bounced;
++extern u32 cm_packets_created;
++extern u32 cm_packets_received;
++extern u32 cm_packets_dropped;
++extern u32 cm_packets_retrans;
++extern u32 cm_listens_created;
++extern u32 cm_listens_destroyed;
++extern u32 cm_backlog_drops;
++extern atomic_t cm_loopbacks;
++extern atomic_t cm_nodes_created;
++extern atomic_t cm_nodes_destroyed;
++extern atomic_t cm_accel_dropped_pkts;
++extern atomic_t cm_resets_recvd;
++
++extern u32 crit_err_count;
++extern u32 int_mod_timer_init;
++extern u32 int_mod_cq_depth_256;
++extern u32 int_mod_cq_depth_128;
++extern u32 int_mod_cq_depth_32;
++extern u32 int_mod_cq_depth_24;
++extern u32 int_mod_cq_depth_16;
++extern u32 int_mod_cq_depth_4;
++extern u32 int_mod_cq_depth_1;
++
++extern atomic_t cqp_reqs_allocated;
++extern atomic_t cqp_reqs_freed;
++extern atomic_t cqp_reqs_dynallocated;
++extern atomic_t cqp_reqs_dynfreed;
++extern atomic_t cqp_reqs_queued;
++extern atomic_t cqp_reqs_redriven;
++
++
++struct nes_device {
++	struct nes_adapter	   *nesadapter;
++	void __iomem           *regs;
++	void __iomem           *index_reg;
++	struct pci_dev         *pcidev;
++	struct net_device      *netdev[NES_NIC_MAX_NICS];
++	u64                    link_status_interrupts;
++	struct tasklet_struct  dpc_tasklet;
++	spinlock_t             indexed_regs_lock;
++	unsigned long          csr_start;
++	unsigned long          doorbell_region;
++	unsigned long          doorbell_start;
++	unsigned long          mac_tx_errors;
++	unsigned long          mac_pause_frames_sent;
++	unsigned long          mac_pause_frames_received;
++	unsigned long          mac_rx_errors;
++	unsigned long          mac_rx_crc_errors;
++	unsigned long          mac_rx_symbol_err_frames;
++	unsigned long          mac_rx_jabber_frames;
++	unsigned long          mac_rx_oversized_frames;
++	unsigned long          mac_rx_short_frames;
++	unsigned long          port_rx_discards;
++	unsigned long          port_tx_discards;
++	unsigned int           mac_index;
++	unsigned int           nes_stack_start;
++
++	/* Control Structures */
++	void                   *cqp_vbase;
++	dma_addr_t             cqp_pbase;
++	u32                    cqp_mem_size;
++	u8                     ceq_index;
++	u8                     nic_ceq_index;
++	struct nes_hw_cqp      cqp;
++	struct nes_hw_cq       ccq;
++	struct list_head       cqp_avail_reqs;
++	struct list_head       cqp_pending_reqs;
++	struct nes_cqp_request *nes_cqp_requests;
++
++	u32                    int_req;
++	u32                    int_stat;
++	u32                    timer_int_req;
++	u32                    timer_only_int_count;
++	u32                    intf_int_req;
++	u32                    last_mac_tx_pauses;
++	u32                    last_used_chunks_tx;
++	struct list_head       list;
++
++	u16                    base_doorbell_index;
++	u16                    currcq_count;
++	u16                    deepcq_count;
++	u8                     msi_enabled;
++	u8                     netdev_count;
++	u8                     napi_isr_ran;
++	u8                     disable_rx_flow_control;
++	u8                     disable_tx_flow_control;
++};
++
++
++static inline void
++set_wqe_64bit_value(__le32 *wqe_words, u32 index, u64 value)
++{
++	wqe_words[index]     = cpu_to_le32((u32) ((unsigned long)value));
++	wqe_words[index + 1] = cpu_to_le32((u32)(upper_32_bits((unsigned long)value)));
++}
++
++static inline void
++set_wqe_32bit_value(__le32 *wqe_words, u32 index, u32 value)
++{
++	wqe_words[index] = cpu_to_le32(value);
++}
++
++static inline void
++nes_fill_init_cqp_wqe(struct nes_hw_cqp_wqe *cqp_wqe, struct nes_device *nesdev)
++{
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_CTX_LOW_IDX,
++			(u64)((unsigned long) &nesdev->cqp));
++	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX]   = 0;
++	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX]  = 0;
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] = 0;
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_LEN_IDX]       = 0;
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_LOW_IDX]       = 0;
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_LOW_IDX]        = 0;
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PA_HIGH_IDX]       = 0;
++}
++
++static inline void
++nes_fill_init_qp_wqe(struct nes_hw_qp_wqe *wqe, struct nes_qp *nesqp, u32 head)
++{
++	u32 value;
++	value = ((u32)((unsigned long) nesqp)) | head;
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_HIGH_IDX,
++			(u32)(upper_32_bits((unsigned long)(nesqp))));
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, value);
++}
++
++/* Read from memory-mapped device */
++static inline u32 nes_read_indexed(struct nes_device *nesdev, u32 reg_index)
++{
++	unsigned long flags;
++	void __iomem *addr = nesdev->index_reg;
++	u32 value;
++
++	spin_lock_irqsave(&nesdev->indexed_regs_lock, flags);
++
++	writel(reg_index, addr);
++	value = readl((void __iomem *)addr + 4);
++
++	spin_unlock_irqrestore(&nesdev->indexed_regs_lock, flags);
++	return value;
++}
++
++static inline u32 nes_read32(const void __iomem *addr)
++{
++	return readl(addr);
++}
++
++static inline u16 nes_read16(const void __iomem *addr)
++{
++	return readw(addr);
++}
++
++static inline u8 nes_read8(const void __iomem *addr)
++{
++	return readb(addr);
++}
++
++/* Write to memory-mapped device */
++static inline void nes_write_indexed(struct nes_device *nesdev, u32 reg_index, u32 val)
++{
++	unsigned long flags;
++	void __iomem *addr = nesdev->index_reg;
++
++	spin_lock_irqsave(&nesdev->indexed_regs_lock, flags);
++
++	writel(reg_index, addr);
++	writel(val, (void __iomem *)addr + 4);
++
++	spin_unlock_irqrestore(&nesdev->indexed_regs_lock, flags);
++}
++
++static inline void nes_write32(void __iomem *addr, u32 val)
++{
++	writel(val, addr);
++}
++
++static inline void nes_write16(void __iomem *addr, u16 val)
++{
++	writew(val, addr);
++}
++
++static inline void nes_write8(void __iomem *addr, u8 val)
++{
++	writeb(val, addr);
++}
++
++
++
++static inline int nes_alloc_resource(struct nes_adapter *nesadapter,
++		unsigned long *resource_array, u32 max_resources,
++		u32 *req_resource_num, u32 *next)
++{
++	unsigned long flags;
++	u32 resource_num;
++
++	spin_lock_irqsave(&nesadapter->resource_lock, flags);
++
++	resource_num = find_next_zero_bit(resource_array, max_resources, *next);
++	if (resource_num >= max_resources) {
++		resource_num = find_first_zero_bit(resource_array, max_resources);
++		if (resource_num >= max_resources) {
++			printk(KERN_ERR PFX "%s: No available resourcess.\n", __FUNCTION__);
++			spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
++			return -EMFILE;
++		}
++	}
++	set_bit(resource_num, resource_array);
++	*next = resource_num+1;
++	if (*next == max_resources) {
++		*next = 0;
++	}
++	spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
++	*req_resource_num = resource_num;
++
++	return 0;
++}
++
++static inline int nes_is_resource_allocated(struct nes_adapter *nesadapter,
++		unsigned long *resource_array, u32 resource_num)
++{
++	unsigned long flags;
++	int bit_is_set;
++
++	spin_lock_irqsave(&nesadapter->resource_lock, flags);
++
++	bit_is_set = test_bit(resource_num, resource_array);
++	nes_debug(NES_DBG_HW, "resource_num %u is%s allocated.\n",
++			resource_num, (bit_is_set ? "": " not"));
++	spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
++
++	return bit_is_set;
++}
++
++static inline void nes_free_resource(struct nes_adapter *nesadapter,
++		unsigned long *resource_array, u32 resource_num)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&nesadapter->resource_lock, flags);
++	clear_bit(resource_num, resource_array);
++	spin_unlock_irqrestore(&nesadapter->resource_lock, flags);
++}
++
++static inline struct nes_vnic *to_nesvnic(struct ib_device *ibdev)
++{
++	return container_of(ibdev, struct nes_ib_device, ibdev)->nesvnic;
++}
++
++static inline struct nes_pd *to_nespd(struct ib_pd *ibpd)
++{
++	return container_of(ibpd, struct nes_pd, ibpd);
++}
++
++static inline struct nes_ucontext *to_nesucontext(struct ib_ucontext *ibucontext)
++{
++	return container_of(ibucontext, struct nes_ucontext, ibucontext);
++}
++
++static inline struct nes_mr *to_nesmr(struct ib_mr *ibmr)
++{
++	return container_of(ibmr, struct nes_mr, ibmr);
++}
++
++static inline struct nes_mr *to_nesmr_from_ibfmr(struct ib_fmr *ibfmr)
++{
++	return container_of(ibfmr, struct nes_mr, ibfmr);
++}
++
++static inline struct nes_mr *to_nesmw(struct ib_mw *ibmw)
++{
++	return container_of(ibmw, struct nes_mr, ibmw);
++}
++
++static inline struct nes_fmr *to_nesfmr(struct nes_mr *nesmr)
++{
++	return container_of(nesmr, struct nes_fmr, nesmr);
++}
++
++static inline struct nes_cq *to_nescq(struct ib_cq *ibcq)
++{
++	return container_of(ibcq, struct nes_cq, ibcq);
++}
++
++static inline struct nes_qp *to_nesqp(struct ib_qp *ibqp)
++{
++	return container_of(ibqp, struct nes_qp, ibqp);
++}
++
++
++
++/* nes.c */
++void nes_add_ref(struct ib_qp *);
++void nes_rem_ref(struct ib_qp *);
++struct ib_qp *nes_get_qp(struct ib_device *, int);
++
++
++/* nes_hw.c */
++struct nes_adapter *nes_init_adapter(struct nes_device *, u8);
++void  nes_nic_init_timer_defaults(struct nes_device *, u8);
++unsigned int nes_reset_adapter_ne020(struct nes_device *, u8 *);
++int nes_init_serdes(struct nes_device *, u8, u8, u8);
++void nes_init_csr_ne020(struct nes_device *, u8, u8);
++void nes_destroy_adapter(struct nes_adapter *);
++int nes_init_cqp(struct nes_device *);
++int nes_init_phy(struct nes_device *);
++int nes_init_nic_qp(struct nes_device *, struct net_device *);
++void nes_destroy_nic_qp(struct nes_vnic *);
++int nes_napi_isr(struct nes_device *);
++void nes_dpc(unsigned long);
++void nes_process_ceq(struct nes_device *, struct nes_hw_ceq *);
++void nes_process_aeq(struct nes_device *, struct nes_hw_aeq *);
++void nes_process_mac_intr(struct nes_device *, u32);
++void nes_nic_napi_ce_handler(struct nes_device *, struct nes_hw_nic_cq *);
++void nes_nic_ce_handler(struct nes_device *, struct nes_hw_nic_cq *);
++void nes_cqp_ce_handler(struct nes_device *, struct nes_hw_cq *);
++void nes_process_iwarp_aeqe(struct nes_device *, struct nes_hw_aeqe *);
++void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *);
++int nes_destroy_cqp(struct nes_device *);
++int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
++
++/* nes_nic.c */
++void nes_netdev_set_multicast_list(struct net_device *);
++void nes_netdev_exit(struct nes_vnic *);
++struct net_device *nes_netdev_init(struct nes_device *, void __iomem *);
++void nes_netdev_destroy(struct net_device *);
++int nes_nic_cm_xmit(struct sk_buff *, struct net_device *);
++
++/* nes_cm.c */
++void *nes_cm_create(struct net_device *);
++int nes_cm_recv(struct sk_buff *, struct net_device *);
++void nes_update_arp(unsigned char *, u32, u32, u16, u16);
++void nes_manage_arp_cache(struct net_device *, unsigned char *, u32, u32);
++void nes_sock_release(struct nes_qp *, unsigned long *);
++struct nes_cm_core *nes_cm_alloc_core(void);
++void flush_wqes(struct nes_device *nesdev, struct nes_qp *, u32, u32);
++int nes_manage_apbvt(struct nes_vnic *, u32, u32, u32);
++int nes_cm_disconn(struct nes_qp *);
++void nes_cm_disconn_worker(void *);
++
++/* nes_verbs.c */
++int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32);
++int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *);
++struct nes_ib_device *nes_init_ofa_device(struct net_device *);
++void nes_destroy_ofa_device(struct nes_ib_device *);
++int nes_register_ofa_device(struct nes_ib_device *);
++void nes_unregister_ofa_device(struct nes_ib_device *);
++
++/* nes_util.c */
++int nes_read_eeprom_values(struct nes_device *, struct nes_adapter *);
++void nes_write_1G_phy_reg(struct nes_device *, u8, u8, u16);
++void nes_read_1G_phy_reg(struct nes_device *, u8, u8, u16 *);
++void nes_write_10G_phy_reg(struct nes_device *, u16, u8, u16);
++void nes_read_10G_phy_reg(struct nes_device *, u16, u8);
++struct nes_cqp_request *nes_get_cqp_request(struct nes_device *);
++void nes_post_cqp_request(struct nes_device *, struct nes_cqp_request *, int);
++int nes_arp_table(struct nes_device *, u32, u8 *, u32);
++void nes_mh_fix(unsigned long);
++void nes_clc(unsigned long);
++void nes_dump_mem(unsigned int, void *, int);
++u32 nes_crc32(u32, u32, u32, u32, u8 *, u32, u32, u32);
++
++#endif	/* __NES_H */
+diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
+new file mode 100644
+index 0000000..bd5cfea
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_cm.c
+@@ -0,0 +1,3088 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++
++#define TCPOPT_TIMESTAMP 8
++
++#include <asm/atomic.h>
++#include <linux/skbuff.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/init.h>
++#include <linux/if_arp.h>
++#include <linux/notifier.h>
++#include <linux/net.h>
++#include <linux/types.h>
++#include <linux/timer.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++#include <linux/etherdevice.h>
++#include <linux/netdevice.h>
++#include <linux/random.h>
++#include <linux/list.h>
++#include <linux/threads.h>
++
++#include <net/neighbour.h>
++#include <net/route.h>
++#include <net/ip_fib.h>
++
++#include "nes.h"
++
++u32 cm_packets_sent;
++u32 cm_packets_bounced;
++u32 cm_packets_dropped;
++u32 cm_packets_retrans;
++u32 cm_packets_created;
++u32 cm_packets_received;
++u32 cm_listens_created;
++u32 cm_listens_destroyed;
++u32 cm_backlog_drops;
++atomic_t cm_loopbacks;
++atomic_t cm_nodes_created;
++atomic_t cm_nodes_destroyed;
++atomic_t cm_accel_dropped_pkts;
++atomic_t cm_resets_recvd;
++
++static inline int mini_cm_accelerated(struct nes_cm_core *, struct nes_cm_node *);
++static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *,
++		struct nes_vnic *, struct nes_cm_info *);
++static int add_ref_cm_node(struct nes_cm_node *);
++static int rem_ref_cm_node(struct nes_cm_core *, struct nes_cm_node *);
++static int mini_cm_del_listen(struct nes_cm_core *, struct nes_cm_listener *);
++
++
++/* External CM API Interface */
++/* instance of function pointers for client API */
++/* set address of this instance to cm_core->cm_ops at cm_core alloc */
++static struct nes_cm_ops nes_cm_api = {
++	mini_cm_accelerated,
++	mini_cm_listen,
++	mini_cm_del_listen,
++	mini_cm_connect,
++	mini_cm_close,
++	mini_cm_accept,
++	mini_cm_reject,
++	mini_cm_recv_pkt,
++	mini_cm_dealloc_core,
++	mini_cm_get,
++	mini_cm_set
++};
++
++struct nes_cm_core *g_cm_core;
++
++atomic_t cm_connects;
++atomic_t cm_accepts;
++atomic_t cm_disconnects;
++atomic_t cm_closes;
++atomic_t cm_connecteds;
++atomic_t cm_connect_reqs;
++atomic_t cm_rejects;
++
++
++/**
++ * create_event
++ */
++static struct nes_cm_event *create_event(struct nes_cm_node *cm_node,
++		enum nes_cm_event_type type)
++{
++	struct nes_cm_event *event;
++
++	if (!cm_node->cm_id)
++		return NULL;
++
++	/* allocate an empty event */
++	event = kzalloc(sizeof(*event), GFP_ATOMIC);
++
++	if (!event)
++		return NULL;
++
++	event->type = type;
++	event->cm_node = cm_node;
++	event->cm_info.rem_addr = cm_node->rem_addr;
++	event->cm_info.loc_addr = cm_node->loc_addr;
++	event->cm_info.rem_port = cm_node->rem_port;
++	event->cm_info.loc_port = cm_node->loc_port;
++	event->cm_info.cm_id = cm_node->cm_id;
++
++	nes_debug(NES_DBG_CM, "Created event=%p, type=%u, dst_addr=%08x[%x],"
++			" src_addr=%08x[%x]\n",
++			event, type,
++			event->cm_info.loc_addr, event->cm_info.loc_port,
++			event->cm_info.rem_addr, event->cm_info.rem_port);
++
++	nes_cm_post_event(event);
++	return event;
++}
++
++
++/**
++ * send_mpa_request
++ */
++int send_mpa_request(struct nes_cm_node *cm_node)
++{
++	struct sk_buff *skb;
++	int ret;
++
++	skb = get_free_pkt(cm_node);
++	if (!skb) {
++		nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
++		return -1;
++	}
++
++	/* send an MPA Request frame */
++	form_cm_frame(skb, cm_node, NULL, 0, &cm_node->mpa_frame,
++			cm_node->mpa_frame_size, SET_ACK);
++
++	ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
++	if (ret < 0) {
++		return ret;
++	}
++
++	return 0;
++}
++
++
++/**
++ * recv_mpa - process a received TCP pkt, we are expecting an
++ * IETF MPA frame
++ */
++static int parse_mpa(struct nes_cm_node *cm_node, u8 *buffer, u32 len)
++{
++	struct ietf_mpa_frame *mpa_frame;
++
++	/* assume req frame is in tcp data payload */
++	if (len < sizeof(struct ietf_mpa_frame)) {
++		nes_debug(NES_DBG_CM, "The received ietf buffer was too small (%x)\n", len);
++		return -1;
++	}
++
++	mpa_frame = (struct ietf_mpa_frame *)buffer;
++	cm_node->mpa_frame_size = ntohs(mpa_frame->priv_data_len);
++
++	if (cm_node->mpa_frame_size + sizeof(struct ietf_mpa_frame) != len) {
++		nes_debug(NES_DBG_CM, "The received ietf buffer was not right"
++				" complete (%x + %x != %x)\n",
++				cm_node->mpa_frame_size, (u32)sizeof(struct ietf_mpa_frame), len);
++		return -1;
++	}
++
++	/* copy entire MPA frame to our cm_node's frame */
++	memcpy(cm_node->mpa_frame_buf, buffer + sizeof(struct ietf_mpa_frame),
++			cm_node->mpa_frame_size);
++
++	return 0;
++}
++
++
++/**
++ * handle_exception_pkt - process an exception packet.
++ * We have been in a TSA state, and we have now received SW
++ * TCP/IP traffic should be a FIN request or IP pkt with options
++ */
++static int handle_exception_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb)
++{
++	int ret = 0;
++	struct tcphdr *tcph = tcp_hdr(skb);
++
++	/* first check to see if this a FIN pkt */
++	if (tcph->fin) {
++		/* we need to ACK the FIN request */
++		send_ack(cm_node);
++
++		/* check which side we are (client/server) and set next state accordingly */
++		if (cm_node->tcp_cntxt.client)
++			cm_node->state = NES_CM_STATE_CLOSING;
++		else {
++			/* we are the server side */
++			cm_node->state = NES_CM_STATE_CLOSE_WAIT;
++			/* since this is a self contained CM we don't wait for */
++			/* an APP to close us, just send final FIN immediately */
++			ret = send_fin(cm_node, NULL);
++			cm_node->state = NES_CM_STATE_LAST_ACK;
++		}
++	} else {
++		ret = -EINVAL;
++	}
++
++	return ret;
++}
++
++
++/**
++ * form_cm_frame - get a free packet and build empty frame Use
++ * node info to build.
++ */
++struct sk_buff *form_cm_frame(struct sk_buff *skb, struct nes_cm_node *cm_node,
++		void *options, u32 optionsize, void *data, u32 datasize, u8 flags)
++{
++	struct tcphdr *tcph;
++	struct iphdr *iph;
++	struct ethhdr *ethh;
++	u8 *buf;
++	u16 packetsize = sizeof(*iph);
++
++	packetsize += sizeof(*tcph);
++	packetsize +=  optionsize + datasize;
++
++	memset(skb->data, 0x00, ETH_HLEN + sizeof(*iph) + sizeof(*tcph));
++
++	skb->len = 0;
++	buf = skb_put(skb, packetsize + ETH_HLEN);
++
++	ethh = (struct ethhdr *) buf;
++	buf += ETH_HLEN;
++
++	iph = (struct iphdr *)buf;
++	buf += sizeof(*iph);
++	tcph = (struct tcphdr *)buf;
++	skb_reset_mac_header(skb);
++	skb_set_network_header(skb, ETH_HLEN);
++	skb_set_transport_header(skb, ETH_HLEN+sizeof(*iph));
++	buf += sizeof(*tcph);
++
++	skb->ip_summed = CHECKSUM_PARTIAL;
++	skb->protocol = htons(0x800);
++	skb->data_len = 0;
++	skb->mac_len = ETH_HLEN;
++
++	memcpy(ethh->h_dest, cm_node->rem_mac, ETH_ALEN);
++	memcpy(ethh->h_source, cm_node->loc_mac, ETH_ALEN);
++	ethh->h_proto = htons(0x0800);
++
++	iph->version = IPVERSION;
++	iph->ihl = 5;		/* 5 * 4Byte words, IP headr len */
++	iph->tos = 0;
++	iph->tot_len = htons(packetsize);
++	iph->id = htons(++cm_node->tcp_cntxt.loc_id);
++
++	iph->frag_off = htons(0x4000);
++	iph->ttl = 0x40;
++	iph->protocol = 0x06;	/* IPPROTO_TCP */
++
++	iph->saddr = htonl(cm_node->loc_addr);
++	iph->daddr = htonl(cm_node->rem_addr);
++
++	tcph->source = htons(cm_node->loc_port);
++	tcph->dest = htons(cm_node->rem_port);
++	tcph->seq = htonl(cm_node->tcp_cntxt.loc_seq_num);
++
++	if (flags & SET_ACK) {
++		cm_node->tcp_cntxt.loc_ack_num = cm_node->tcp_cntxt.rcv_nxt;
++		tcph->ack_seq = htonl(cm_node->tcp_cntxt.loc_ack_num);
++		tcph->ack = 1;
++	} else
++		tcph->ack_seq = 0;
++
++	if (flags & SET_SYN) {
++		cm_node->tcp_cntxt.loc_seq_num++;
++		tcph->syn = 1;
++	} else
++		cm_node->tcp_cntxt.loc_seq_num += datasize;	/* data (no headers) */
++
++	if (flags & SET_FIN)
++		tcph->fin = 1;
++
++	if (flags & SET_RST)
++		tcph->rst = 1;
++
++	tcph->doff = (u16)((sizeof(*tcph) + optionsize + 3) >> 2);
++	tcph->window = htons(cm_node->tcp_cntxt.rcv_wnd);
++	tcph->urg_ptr = 0;
++	if (optionsize)
++		memcpy(buf, options, optionsize);
++	buf += optionsize;
++	if (datasize)
++		memcpy(buf, data, datasize);
++
++	skb_shinfo(skb)->nr_frags = 0;
++	cm_packets_created++;
++
++	return skb;
++}
++
++
++/**
++ * print_core - dump a cm core
++ */
++static void print_core(struct nes_cm_core *core)
 +{
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-+	u32 regdw = 0;
-+	u8 drive_pci = sis_ata133_get_base(drive), clk, idx;
++	nes_debug(NES_DBG_CM, "---------------------------------------------\n");
++	nes_debug(NES_DBG_CM, "CM Core  -- (core = %p )\n", core);
++	if (!core)
++		return;
++	nes_debug(NES_DBG_CM, "---------------------------------------------\n");
++	nes_debug(NES_DBG_CM, "Session ID    : %u \n", atomic_read(&core->session_id));
 +
-+	pci_read_config_dword(dev, drive_pci, &regdw);
++	nes_debug(NES_DBG_CM, "State         : %u \n",  core->state);
 +
-+	regdw |= 0x04;
-+	regdw &= 0xfffff00f;
-+	/* check if ATA133 enable */
-+	clk = (regdw & 0x08) ? ATA_133 : ATA_100;
-+	idx = mode - XFER_UDMA_0;
-+	regdw |= cycle_time_value[clk][idx] << 4;
-+	regdw |= cvs_time_value[clk][idx] << 8;
++	nes_debug(NES_DBG_CM, "Tx Free cnt   : %u \n", skb_queue_len(&core->tx_free_list));
++	nes_debug(NES_DBG_CM, "Listen Nodes  : %u \n", atomic_read(&core->listen_node_cnt));
++	nes_debug(NES_DBG_CM, "Active Nodes  : %u \n", atomic_read(&core->node_cnt));
 +
-+	pci_write_config_dword(dev, drive_pci, regdw);
++	nes_debug(NES_DBG_CM, "core          : %p \n", core);
++
++	nes_debug(NES_DBG_CM, "-------------- end core ---------------\n");
 +}
 +
-+static void sis_ata33_program_udma_timings(ide_drive_t *drive, const u8 mode)
++
++/**
++ * schedule_nes_timer
++ * note - cm_node needs to be protected before calling this. Encase in:
++ *			rem_ref_cm_node(cm_core, cm_node);add_ref_cm_node(cm_node);
++ */
++int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
++		enum nes_timer_type type, int send_retrans,
++		int close_when_complete)
 +{
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
-+	u8 drive_pci = 0x40 + drive->dn * 2, reg = 0, i = chipset_family;
++	unsigned long  flags;
++	struct nes_cm_core *cm_core;
++	struct nes_timer_entry *new_send;
++	int ret = 0;
++	u32 was_timer_set;
 +
-+	pci_read_config_byte(dev, drive_pci + 1, &reg);
++	new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC);
++	if (!new_send)
++		return -1;
++	if (!cm_node)
++		return -EINVAL;
 +
-+	/* force the UDMA bit on if we want to use UDMA */
-+	reg |= 0x80;
-+	/* clean reg cycle time bits */
-+	reg &= ~((0xff >> (8 - cycle_time_range[i])) << cycle_time_offset[i]);
-+	/* set reg cycle time bits */
-+	reg |= cycle_time_value[i][mode - XFER_UDMA_0] << cycle_time_offset[i];
++	/* new_send->timetosend = currenttime */
++	new_send->retrycount = NES_DEFAULT_RETRYS;
++	new_send->retranscount = NES_DEFAULT_RETRANS;
++	new_send->skb = skb;
++	new_send->timetosend = jiffies;
++	new_send->type = type;
++	new_send->netdev = cm_node->netdev;
++	new_send->send_retrans = send_retrans;
++	new_send->close_when_complete = close_when_complete;
++
++	if (type == NES_TIMER_TYPE_CLOSE) {
++		new_send->timetosend += (HZ/2);	/* TODO: decide on the correct value here */
++		spin_lock_irqsave(&cm_node->recv_list_lock, flags);
++		list_add_tail(&new_send->list, &cm_node->recv_list);
++		spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
++	}
++
++	if (type == NES_TIMER_TYPE_SEND) {
++		new_send->seq_num = htonl(tcp_hdr(skb)->seq);
++		atomic_inc(&new_send->skb->users);
++
++		ret = nes_nic_cm_xmit(new_send->skb, cm_node->netdev);
++		if (ret != NETDEV_TX_OK) {
++			nes_debug(NES_DBG_CM, "Error sending packet %p (jiffies = %lu)\n",
++					new_send, jiffies);
++			atomic_dec(&new_send->skb->users);
++			new_send->timetosend = jiffies;
++		} else {
++			cm_packets_sent++;
++			if (!send_retrans) {
++				if (close_when_complete)
++					rem_ref_cm_node(cm_node->cm_core, cm_node);
++				dev_kfree_skb_any(new_send->skb);
++				kfree(new_send);
++				return ret;
++			}
++			new_send->timetosend = jiffies + NES_RETRY_TIMEOUT;
++		}
++		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++		list_add_tail(&new_send->list, &cm_node->retrans_list);
++		spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++	}
++	if (type == NES_TIMER_TYPE_RECV) {
++		new_send->seq_num = htonl(tcp_hdr(skb)->seq);
++		new_send->timetosend = jiffies;
++		spin_lock_irqsave(&cm_node->recv_list_lock, flags);
++		list_add_tail(&new_send->list, &cm_node->recv_list);
++		spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
++	}
++	cm_core = cm_node->cm_core;
++
++	was_timer_set = timer_pending(&cm_core->tcp_timer);
++
++	if (!was_timer_set) {
++		cm_core->tcp_timer.expires = new_send->timetosend;
++		add_timer(&cm_core->tcp_timer);
++	}
 +
-+	pci_write_config_byte(dev, drive_pci + 1, reg);
++	return ret;
 +}
 +
-+static void sis_program_udma_timings(ide_drive_t *drive, const u8 mode)
++
++/**
++ * nes_cm_timer_tick
++ */
++void nes_cm_timer_tick(unsigned long pass)
 +{
-+	if (chipset_family >= ATA_133)	/* ATA_133 */
-+		sis_ata133_program_udma_timings(drive, mode);
-+	else				/* ATA_33/66/100a/100/133a */
-+		sis_ata33_program_udma_timings(drive, mode);
++	unsigned long flags, qplockflags;
++	unsigned long nexttimeout = jiffies + NES_LONG_TIME;
++	struct iw_cm_id *cm_id;
++	struct nes_cm_node *cm_node;
++	struct nes_timer_entry *send_entry, *recv_entry;
++	struct list_head *list_core, *list_core_temp;
++	struct list_head *list_node, *list_node_temp;
++	struct nes_cm_core *cm_core = g_cm_core;
++	struct nes_qp *nesqp;
++	struct sk_buff *skb;
++	u32 settimer = 0;
++	int ret = NETDEV_TX_OK;
++	int    node_done;
++
++	spin_lock_irqsave(&cm_core->ht_lock, flags);
++
++	list_for_each_safe(list_node, list_core_temp, &cm_core->connected_nodes) {
++		cm_node = container_of(list_node, struct nes_cm_node, list);
++		add_ref_cm_node(cm_node);
++		spin_unlock_irqrestore(&cm_core->ht_lock, flags);
++		spin_lock_irqsave(&cm_node->recv_list_lock, flags);
++		list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) {
++			recv_entry = container_of(list_core, struct nes_timer_entry, list);
++			if ((time_after(recv_entry->timetosend, jiffies)) &&
++					(recv_entry->type == NES_TIMER_TYPE_CLOSE)) {
++				if (nexttimeout > recv_entry->timetosend || !settimer) {
++					nexttimeout = recv_entry->timetosend;
++					settimer = 1;
++				}
++				continue;
++			}
++			list_del(&recv_entry->list);
++			cm_id = cm_node->cm_id;
++			spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
++			if (recv_entry->type == NES_TIMER_TYPE_CLOSE) {
++				nesqp = (struct nes_qp *)recv_entry->skb;
++				spin_lock_irqsave(&nesqp->lock, qplockflags);
++				if (nesqp->cm_id) {
++					nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d: "
++							"****** HIT A NES_TIMER_TYPE_CLOSE"
++							" with something to do!!! ******\n",
++							nesqp->hwqp.qp_id, cm_id,
++							atomic_read(&nesqp->refcount));
++					nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++					nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
++					nesqp->ibqp_state = IB_QPS_ERR;
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_cm_disconn(nesqp);
++				} else {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_debug(NES_DBG_CM, "QP%u: cm_id = %p, refcount = %d:"
++							" ****** HIT A NES_TIMER_TYPE_CLOSE"
++							" with nothing to do!!! ******\n",
++							nesqp->hwqp.qp_id, cm_id,
++							atomic_read(&nesqp->refcount));
++					nes_rem_ref(&nesqp->ibqp);
++				}
++				if (cm_id)
++					cm_id->rem_ref(cm_id);
++			}
++			kfree(recv_entry);
++			spin_lock_irqsave(&cm_node->recv_list_lock, flags);
++		}
++		spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
++
++		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++		node_done = 0;
++		list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) {
++			if (node_done) {
++				break;
++			}
++			send_entry = container_of(list_core, struct nes_timer_entry, list);
++			if (time_after(send_entry->timetosend, jiffies)) {
++				if (cm_node->state != NES_CM_STATE_TSA) {
++					if ((nexttimeout > send_entry->timetosend) || !settimer) {
++						nexttimeout = send_entry->timetosend;
++						settimer = 1;
++					}
++					node_done = 1;
++					continue;
++				} else {
++					list_del(&send_entry->list);
++					skb = send_entry->skb;
++					spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++					dev_kfree_skb_any(skb);
++					kfree(send_entry);
++					spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++					continue;
++				}
++			}
++			if (send_entry->type == NES_TIMER_NODE_CLEANUP) {
++				list_del(&send_entry->list);
++				spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++				kfree(send_entry);
++				spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++				continue;
++			}
++			if ((send_entry->seq_num < cm_node->tcp_cntxt.rem_ack_num) ||
++					(cm_node->state == NES_CM_STATE_TSA) ||
++					(cm_node->state == NES_CM_STATE_CLOSED)) {
++				skb = send_entry->skb;
++				list_del(&send_entry->list);
++				spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++				kfree(send_entry);
++				dev_kfree_skb_any(skb);
++				spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++				continue;
++			}
++
++			if (!send_entry->retranscount || !send_entry->retrycount) {
++				cm_packets_dropped++;
++				skb = send_entry->skb;
++				list_del(&send_entry->list);
++				spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++				dev_kfree_skb_any(skb);
++				kfree(send_entry);
++				if (cm_node->state == NES_CM_STATE_SYN_RCVD) {
++					/* this node never even generated an indication up to the cm */
++					rem_ref_cm_node(cm_core, cm_node);
++				} else {
++					cm_node->state = NES_CM_STATE_CLOSED;
++					create_event(cm_node, NES_CM_EVENT_ABORTED);
++				}
++				spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++				continue;
++			}
++			/* this seems like the correct place, but leave send entry unprotected */
++			// spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++			atomic_inc(&send_entry->skb->users);
++			cm_packets_retrans++;
++			nes_debug(NES_DBG_CM, "Retransmitting send_entry %p for node %p,"
++					" jiffies = %lu, time to send =  %lu, retranscount = %u, "
++					"send_entry->seq_num = 0x%08X, cm_node->tcp_cntxt.rem_ack_num = 0x%08X\n",
++					send_entry, cm_node, jiffies, send_entry->timetosend, send_entry->retranscount,
++					send_entry->seq_num, cm_node->tcp_cntxt.rem_ack_num);
++
++			spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++			ret = nes_nic_cm_xmit(send_entry->skb, cm_node->netdev);
++			if (ret != NETDEV_TX_OK) {
++				cm_packets_bounced++;
++				atomic_dec(&send_entry->skb->users);
++				send_entry->retrycount--;
++				nexttimeout = jiffies + NES_SHORT_TIME;
++				settimer = 1;
++				node_done = 1;
++				spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++				continue;
++			} else {
++				cm_packets_sent++;
++			}
++			spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++			list_del(&send_entry->list);
++			nes_debug(NES_DBG_CM, "Packet Sent: retrans count = %u, retry count = %u.\n",
++					send_entry->retranscount, send_entry->retrycount);
++			if (send_entry->send_retrans) {
++				send_entry->retranscount--;
++				send_entry->timetosend = jiffies + NES_RETRY_TIMEOUT;
++				if (nexttimeout > send_entry->timetosend || !settimer) {
++					nexttimeout = send_entry->timetosend;
++					settimer = 1;
++				}
++				list_add(&send_entry->list, &cm_node->retrans_list);
++				continue;
++			} else {
++				int close_when_complete;
++				skb = send_entry->skb;
++				close_when_complete = send_entry->close_when_complete;
++				spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++				if (close_when_complete) {
++					BUG_ON(atomic_read(&cm_node->ref_count) == 1);
++					rem_ref_cm_node(cm_core, cm_node);
++				}
++				dev_kfree_skb_any(skb);
++				kfree(send_entry);
++				spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++				continue;
++			}
++		}
++		spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++
++		rem_ref_cm_node(cm_core, cm_node);
++
++		spin_lock_irqsave(&cm_core->ht_lock, flags);
++		if (ret != NETDEV_TX_OK)
++			break;
++	}
++	spin_unlock_irqrestore(&cm_core->ht_lock, flags);
++
++	if (settimer) {
++		if (!timer_pending(&cm_core->tcp_timer)) {
++			cm_core->tcp_timer.expires  = nexttimeout;
++			add_timer(&cm_core->tcp_timer);
++		}
++	}
 +}
 +
- static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
- {
--	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
--
--	/* Config chip for mode */
--	switch(speed) {
--		case XFER_UDMA_6:
--		case XFER_UDMA_5:
--		case XFER_UDMA_4:
--		case XFER_UDMA_3:
--		case XFER_UDMA_2:
--		case XFER_UDMA_1:
--		case XFER_UDMA_0:
--			if (chipset_family >= ATA_133) {
--				u32 regdw = 0;
--				u8 drive_pci = sis_ata133_get_base(drive);
--
--				pci_read_config_dword(dev, drive_pci, &regdw);
--				regdw |= 0x04;
--				regdw &= 0xfffff00f;
--				/* check if ATA133 enable */
--				if (regdw & 0x08) {
--					regdw |= (unsigned long)cycle_time_value[ATA_133][speed-XFER_UDMA_0] << 4;
--					regdw |= (unsigned long)cvs_time_value[ATA_133][speed-XFER_UDMA_0] << 8;
--				} else {
--					regdw |= (unsigned long)cycle_time_value[ATA_100][speed-XFER_UDMA_0] << 4;
--					regdw |= (unsigned long)cvs_time_value[ATA_100][speed-XFER_UDMA_0] << 8;
--				}
--				pci_write_config_dword(dev, (unsigned long)drive_pci, regdw);
--			} else {
--				u8 drive_pci = 0x40 + drive->dn * 2, reg = 0;
--
--				pci_read_config_byte(dev, drive_pci+1, &reg);
--				/* Force the UDMA bit on if we want to use UDMA */
--				reg |= 0x80;
--				/* clean reg cycle time bits */
--				reg &= ~((0xFF >> (8 - cycle_time_range[chipset_family]))
--					 << cycle_time_offset[chipset_family]);
--				/* set reg cycle time bits */
--				reg |= cycle_time_value[chipset_family][speed-XFER_UDMA_0]
--					<< cycle_time_offset[chipset_family];
--				pci_write_config_byte(dev, drive_pci+1, reg);
--			}
--			break;
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_MW_DMA_0:
--			sis_program_timings(drive, speed);
--			break;
--		default:
--			break;
--	}
-+	if (speed >= XFER_UDMA_0)
-+		sis_program_udma_timings(drive, speed);
-+	else
-+		sis_program_timings(drive, speed);
- }
- 
- static u8 sis5513_ata133_udma_filter(ide_drive_t *drive)
- {
--	struct pci_dev *dev = drive->hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u32 regdw = 0;
- 	u8 drive_pci = sis_ata133_get_base(drive);
- 
-@@ -533,7 +519,7 @@ static const struct sis_laptop sis_laptop[] = {
- 
- static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
- {
--	struct pci_dev *pdev = hwif->pci_dev;
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
- 	const struct sis_laptop *lap = &sis_laptop[0];
- 	u8 ata66 = 0;
- 
-@@ -548,12 +534,12 @@ static u8 __devinit ata66_sis5513(ide_hwif_t *hwif)
- 	if (chipset_family >= ATA_133) {
- 		u16 regw = 0;
- 		u16 reg_addr = hwif->channel ? 0x52: 0x50;
--		pci_read_config_word(hwif->pci_dev, reg_addr, &regw);
-+		pci_read_config_word(pdev, reg_addr, &regw);
- 		ata66 = (regw & 0x8000) ? 0 : 1;
- 	} else if (chipset_family >= ATA_66) {
- 		u8 reg48h = 0;
- 		u8 mask = hwif->channel ? 0x20 : 0x10;
--		pci_read_config_byte(hwif->pci_dev, 0x48, &reg48h);
-+		pci_read_config_byte(pdev, 0x48, &reg48h);
- 		ata66 = (reg48h & mask) ? 0 : 1;
- 	}
- 
-@@ -570,13 +556,12 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
- 	if (chipset_family >= ATA_133)
- 		hwif->udma_filter = sis5513_ata133_udma_filter;
- 
-+	hwif->cable_detect = ata66_sis5513;
 +
- 	if (hwif->dma_base == 0)
- 		return;
- 
- 	hwif->ultra_mask = udma_rates[chipset_family];
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = ata66_sis5513(hwif);
- }
- 
- static const struct ide_port_info sis5513_chipset __devinitdata = {
-diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
-index 147d783..ee261ae 100644
---- a/drivers/ide/pci/sl82c105.c
-+++ b/drivers/ide/pci/sl82c105.c
-@@ -1,6 +1,4 @@
- /*
-- * linux/drivers/ide/pci/sl82c105.c
-- *
-  * SL82C105/Winbond 553 IDE driver
-  *
-  * Maintainer unknown.
-@@ -13,22 +11,17 @@
-  *  -- Benjamin Herrenschmidt (01/11/03) benh at kernel.crashing.org
-  *
-  * Copyright (C) 2006-2007 MontaVista Software, Inc. <source at mvista.com>
-+ * Copyright (C)      2007 Bartlomiej Zolnierkiewicz
-  */
- 
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/interrupt.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/pci.h>
- #include <linux/ide.h>
- 
- #include <asm/io.h>
--#include <asm/dma.h>
- 
- #undef DEBUG
- 
-@@ -77,7 +70,7 @@ static unsigned int get_pio_timings(ide_drive_t *drive, u8 pio)
-  */
- static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
--	struct pci_dev *dev	= HWIF(drive)->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
- 	int reg			= 0x44 + drive->dn * 4;
- 	u16 drv_ctrl;
- 
-@@ -90,14 +83,8 @@ static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
- 	drive->drive_data &= 0xffff0000;
- 	drive->drive_data |= drv_ctrl;
- 
--	if (!drive->using_dma) {
--		/*
--		 * If we are actually using MW DMA, then we can not
--		 * reprogram the interface drive control register.
--		 */
--		pci_write_config_word(dev, reg,  drv_ctrl);
--		pci_read_config_word (dev, reg, &drv_ctrl);
--	}
-+	pci_write_config_word(dev, reg,  drv_ctrl);
-+	pci_read_config_word (dev, reg, &drv_ctrl);
- 
- 	printk(KERN_DEBUG "%s: selected %s (%dns) (%04X)\n", drive->name,
- 			  ide_xfer_verbose(pio + XFER_PIO_0),
-@@ -115,33 +102,14 @@ static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
-  	DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
- 	     drive->name, ide_xfer_verbose(speed)));
- 
--	switch (speed) {
--	case XFER_MW_DMA_2:
--	case XFER_MW_DMA_1:
--	case XFER_MW_DMA_0:
--		drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
-+	drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
- 
--		/*
--		 * Store the DMA timings so that we can actually program
--		 * them when DMA will be turned on...
--		 */
--		drive->drive_data &= 0x0000ffff;
--		drive->drive_data |= (unsigned long)drv_ctrl << 16;
--
--		/*
--		 * If we are already using DMA, we just reprogram
--		 * the drive control register.
--		 */
--		if (drive->using_dma) {
--			struct pci_dev *dev	= HWIF(drive)->pci_dev;
--			int reg 		= 0x44 + drive->dn * 4;
--
--			pci_write_config_word(dev, reg, drv_ctrl);
--		}
--		break;
--	default:
--		return;
--	}
-+	/*
-+	 * Store the DMA timings so that we can actually program
-+	 * them when DMA will be turned on...
-+	 */
-+	drive->drive_data &= 0x0000ffff;
-+	drive->drive_data |= (unsigned long)drv_ctrl << 16;
- }
- 
- /*
-@@ -171,7 +139,7 @@ static inline void sl82c105_reset_host(struct pci_dev *dev)
- static void sl82c105_dma_lost_irq(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u32 val, mask		= hwif->channel ? CTRL_IDE_IRQB : CTRL_IDE_IRQA;
- 	u8 dma_cmd;
- 
-@@ -208,7 +176,12 @@ static void sl82c105_dma_lost_irq(ide_drive_t *drive)
- static void sl82c105_dma_start(ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-+	int reg 		= 0x44 + drive->dn * 4;
++/**
++ * send_syn
++ */
++int send_syn(struct nes_cm_node *cm_node, u32 sendack)
++{
++	int ret;
++	int flags = SET_SYN;
++	struct sk_buff *skb;
++	char optionsbuffer[sizeof(struct option_mss) +
++			sizeof(struct option_windowscale) +
++			sizeof(struct option_base) + 1];
++
++	int optionssize = 0;
++	/* Sending MSS option */
++	union all_known_options *options;
 +
-+	DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
++	if (!cm_node)
++		return -EINVAL;
 +
-+	pci_write_config_word(dev, reg, drive->drive_data >> 16);
- 
- 	sl82c105_reset_host(dev);
- 	ide_dma_start(drive);
-@@ -216,80 +189,43 @@ static void sl82c105_dma_start(ide_drive_t *drive)
- 
- static void sl82c105_dma_timeout(ide_drive_t *drive)
- {
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
++	options = (union all_known_options *)&optionsbuffer[optionssize];
++	options->as_mss.optionnum = OPTION_NUMBER_MSS;
++	options->as_mss.length = sizeof(struct option_mss);
++	options->as_mss.mss = htons(cm_node->tcp_cntxt.mss);
++	optionssize += sizeof(struct option_mss);
++
++	options = (union all_known_options *)&optionsbuffer[optionssize];
++	options->as_windowscale.optionnum = OPTION_NUMBER_WINDOW_SCALE;
++	options->as_windowscale.length = sizeof(struct option_windowscale);
++	options->as_windowscale.shiftcount = cm_node->tcp_cntxt.rcv_wscale;
++	optionssize += sizeof(struct option_windowscale);
++
++	if (sendack && !(NES_DRV_OPT_SUPRESS_OPTION_BC & nes_drv_opt)
++			) {
++		options = (union all_known_options *)&optionsbuffer[optionssize];
++		options->as_base.optionnum = OPTION_NUMBER_WRITE0;
++		options->as_base.length = sizeof(struct option_base);
++		optionssize += sizeof(struct option_base);
++		/* we need the size to be a multiple of 4 */
++		options = (union all_known_options *)&optionsbuffer[optionssize];
++		options->as_end = 1;
++		optionssize += 1;
++		options = (union all_known_options *)&optionsbuffer[optionssize];
++		options->as_end = 1;
++		optionssize += 1;
++	}
++
++	options = (union all_known_options *)&optionsbuffer[optionssize];
++	options->as_end = OPTION_NUMBER_END;
++	optionssize += 1;
 +
- 	DBG(("sl82c105_dma_timeout(drive:%s)\n", drive->name));
- 
--	sl82c105_reset_host(HWIF(drive)->pci_dev);
-+	sl82c105_reset_host(dev);
- 	ide_dma_timeout(drive);
- }
- 
--static int sl82c105_ide_dma_on(ide_drive_t *drive)
-+static int sl82c105_dma_end(ide_drive_t *drive)
- {
--	struct pci_dev *dev	= HWIF(drive)->pci_dev;
--	int rc, reg 		= 0x44 + drive->dn * 4;
--
--	DBG(("sl82c105_ide_dma_on(drive:%s)\n", drive->name));
--
--	rc = __ide_dma_on(drive);
--	if (rc == 0) {
--		pci_write_config_word(dev, reg, drive->drive_data >> 16);
--
--		printk(KERN_INFO "%s: DMA enabled\n", drive->name);
--	}
--	return rc;
--}
--
--static void sl82c105_dma_off_quietly(ide_drive_t *drive)
--{
--	struct pci_dev *dev	= HWIF(drive)->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(drive->hwif->dev);
- 	int reg 		= 0x44 + drive->dn * 4;
++	skb = get_free_pkt(cm_node);
++	if (!skb) {
++		nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
++		return -1;
++	}
++
++	if (sendack)
++		flags |= SET_ACK;
++
++	form_cm_frame(skb, cm_node, optionsbuffer, optionssize, NULL, 0, flags);
++	ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
++
++	return ret;
++}
++
++
++/**
++ * send_reset
++ */
++int send_reset(struct nes_cm_node *cm_node)
++{
 +	int ret;
- 
--	DBG(("sl82c105_dma_off_quietly(drive:%s)\n", drive->name));
-+	DBG(("%s(drive:%s)\n", __FUNCTION__, drive->name));
- 
--	pci_write_config_word(dev, reg, drive->drive_data);
-+	ret = __ide_dma_end(drive);
- 
--	ide_dma_off_quietly(drive);
--}
-+	pci_write_config_word(dev, reg, drive->drive_data);
- 
--/*
-- * Ok, that is nasty, but we must make sure the DMA timings
-- * won't be used for a PIO access. The solution here is
-- * to make sure the 16 bits mode is diabled on the channel
-- * when DMA is enabled, thus causing the chip to use PIO0
-- * timings for those operations.
-- */
--static void sl82c105_selectproc(ide_drive_t *drive)
--{
--	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
--	u32 val, old, mask;
--
--	//DBG(("sl82c105_selectproc(drive:%s)\n", drive->name));
--
--	mask = hwif->channel ? CTRL_P1F16 : CTRL_P0F16;
--	old = val = (u32)pci_get_drvdata(dev);
--	if (drive->using_dma)
--		val &= ~mask;
--	else
--		val |= mask;
--	if (old != val) {
--		pci_write_config_dword(dev, 0x40, val);	
--		pci_set_drvdata(dev, (void *)val);
--	}
++	struct sk_buff *skb = get_free_pkt(cm_node);
++	int flags = SET_RST | SET_ACK;
++
++	if (!skb) {
++		nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
++		return -1;
++	}
++
++	add_ref_cm_node(cm_node);
++	form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, flags);
++	ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 1);
++
 +	return ret;
- }
- 
- /*
-  * ATA reset will clear the 16 bits mode in the control
-- * register, we need to update our cache
-+ * register, we need to reprogram it
-  */
- static void sl82c105_resetproc(ide_drive_t *drive)
- {
--	struct pci_dev *dev = HWIF(drive)->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(drive->hwif->dev);
- 	u32 val;
- 
- 	DBG(("sl82c105_resetproc(drive:%s)\n", drive->name));
- 
- 	pci_read_config_dword(dev, 0x40, &val);
--	pci_set_drvdata(dev, (void *)val);
-+	val |= (CTRL_P1F16 | CTRL_P0F16);
-+	pci_write_config_dword(dev, 0x40, val);
- }
- 
- /*
-@@ -342,7 +278,6 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
- 	pci_read_config_dword(dev, 0x40, &val);
- 	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
- 	pci_write_config_dword(dev, 0x40, val);
--	pci_set_drvdata(dev, (void *)val);
- 
- 	return dev->irq;
- }
-@@ -352,19 +287,19 @@ static unsigned int __devinit init_chipset_sl82c105(struct pci_dev *dev, const c
-  */
- static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	unsigned int rev;
- 
- 	DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
- 
- 	hwif->set_pio_mode	= &sl82c105_set_pio_mode;
- 	hwif->set_dma_mode	= &sl82c105_set_dma_mode;
--	hwif->selectproc	= &sl82c105_selectproc;
- 	hwif->resetproc 	= &sl82c105_resetproc;
- 
- 	if (!hwif->dma_base)
- 		return;
- 
--	rev = sl82c105_bridge_revision(hwif->pci_dev);
-+	rev = sl82c105_bridge_revision(dev);
- 	if (rev <= 5) {
- 		/*
- 		 * Never ever EVER under any circumstances enable
-@@ -377,10 +312,9 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
- 
- 	hwif->mwdma_mask = ATA_MWDMA2;
- 
--	hwif->ide_dma_on		= &sl82c105_ide_dma_on;
--	hwif->dma_off_quietly		= &sl82c105_dma_off_quietly;
- 	hwif->dma_lost_irq		= &sl82c105_dma_lost_irq;
- 	hwif->dma_start			= &sl82c105_dma_start;
-+	hwif->ide_dma_end		= &sl82c105_dma_end;
- 	hwif->dma_timeout		= &sl82c105_dma_timeout;
- 
- 	if (hwif->mate)
-diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
-index eb4445b..65f4c2f 100644
---- a/drivers/ide/pci/slc90e66.c
-+++ b/drivers/ide/pci/slc90e66.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/pci/slc90e66.c	Version 0.19	Sep 24, 2007
-- *
-  *  Copyright (C) 2000-2002 Andre Hedrick <andre at linux-ide.org>
-  *  Copyright (C) 2006-2007 MontaVista Software, Inc. <source at mvista.com>
-  *
-@@ -12,21 +10,17 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/ioport.h>
- #include <linux/pci.h>
- #include <linux/hdreg.h>
- #include <linux/ide.h>
--#include <linux/delay.h>
- #include <linux/init.h>
- 
--#include <asm/io.h>
--
- static DEFINE_SPINLOCK(slc90e66_lock);
- 
- static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	int is_slave		= drive->dn & 1;
- 	int master_port		= hwif->channel ? 0x42 : 0x40;
- 	int slave_port		= 0x44;
-@@ -79,7 +73,7 @@ static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
- static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
- {
- 	ide_hwif_t *hwif	= HWIF(drive);
--	struct pci_dev *dev	= hwif->pci_dev;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
- 	u8 maslave		= hwif->channel ? 0x42 : 0x40;
- 	int sitre = 0, a_speed	= 7 << (drive->dn * 4);
- 	int u_speed = 0, u_flag = 1 << drive->dn;
-@@ -91,19 +85,9 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	pci_read_config_word(dev, 0x48, &reg48);
- 	pci_read_config_word(dev, 0x4a, &reg4a);
- 
--	switch(speed) {
--		case XFER_UDMA_4:	u_speed = 4 << (drive->dn * 4); break;
--		case XFER_UDMA_3:	u_speed = 3 << (drive->dn * 4); break;
--		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
--		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
--		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_SW_DMA_2:	break;
--		default:		return;
--	}
--
- 	if (speed >= XFER_UDMA_0) {
-+		u_speed = (speed - XFER_UDMA_0) << (drive->dn * 4);
++}
 +
- 		if (!(reg48 & u_flag))
- 			pci_write_config_word(dev, 0x48, reg48|u_flag);
- 		/* FIXME: (reg4a & a_speed) ? */
-@@ -130,22 +114,23 @@ static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	}
- }
- 
--static void __devinit init_hwif_slc90e66 (ide_hwif_t *hwif)
-+static u8 __devinit slc90e66_cable_detect(ide_hwif_t *hwif)
- {
--	u8 reg47 = 0;
--	u8 mask = hwif->channel ? 0x01 : 0x02;  /* bit0:Primary */
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	u8 reg47 = 0, mask = hwif->channel ? 0x01 : 0x02;
- 
--	hwif->set_pio_mode = &slc90e66_set_pio_mode;
--	hwif->set_dma_mode = &slc90e66_set_dma_mode;
-+	pci_read_config_byte(dev, 0x47, &reg47);
- 
--	pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
-+	/* bit[0(1)]: 0:80, 1:40 */
-+	return (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++
++/**
++ * send_ack
++ */
++int send_ack(struct nes_cm_node *cm_node)
++{
++	int ret;
++	struct sk_buff *skb = get_free_pkt(cm_node);
++
++	if (!skb) {
++		nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
++		return -1;
++	}
++
++	form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, SET_ACK);
++	ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 0, 0);
++
++	return ret;
 +}
- 
--	if (hwif->dma_base == 0)
--		return;
-+static void __devinit init_hwif_slc90e66(ide_hwif_t *hwif)
++
++
++/**
++ * send_fin
++ */
++int send_fin(struct nes_cm_node *cm_node, struct sk_buff *skb)
 +{
-+	hwif->set_pio_mode = &slc90e66_set_pio_mode;
-+	hwif->set_dma_mode = &slc90e66_set_dma_mode;
- 
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		/* bit[0(1)]: 0:80, 1:40 */
--		hwif->cbl = (reg47 & mask) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
-+	hwif->cable_detect = slc90e66_cable_detect;
- }
- 
- static const struct ide_port_info slc90e66_chipset __devinitdata = {
-diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
-index a66ebd1..2ef2ed2 100644
---- a/drivers/ide/pci/tc86c001.c
-+++ b/drivers/ide/pci/tc86c001.c
-@@ -1,6 +1,4 @@
- /*
-- * drivers/ide/pci/tc86c001.c	Version 1.01	Sep 5, 2007
-- *
-  * Copyright (C) 2002 Toshiba Corporation
-  * Copyright (C) 2005-2006 MontaVista Software, Inc. <source at mvista.com>
-  *
-@@ -162,9 +160,23 @@ static int tc86c001_busproc(ide_drive_t *drive, int state)
- 	return 0;
- }
- 
-+static u8 __devinit tc86c001_cable_detect(ide_hwif_t *hwif)
++	int ret;
++
++	/* if we didn't get a frame get one */
++	if (!skb)
++		skb = get_free_pkt(cm_node);
++
++	if (!skb) {
++		nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
++		return -1;
++	}
++
++	form_cm_frame(skb, cm_node, NULL, 0, NULL, 0, SET_ACK | SET_FIN);
++	ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
++
++	return ret;
++}
++
++
++/**
++ * get_free_pkt
++ */
++struct sk_buff *get_free_pkt(struct nes_cm_node *cm_node)
 +{
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	unsigned long sc_base = pci_resource_start(dev, 5);
-+	u16 scr1 = inw(sc_base + 0x00);
++	struct sk_buff *skb, *new_skb;
 +
-+	/*
-+	 * System Control  1 Register bit 13 (PDIAGN):
-+	 * 0=80-pin cable, 1=40-pin cable
-+	 */
-+	return (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
++	/* check to see if we need to repopulate the free tx pkt queue */
++	if (skb_queue_len(&cm_node->cm_core->tx_free_list) < NES_CM_FREE_PKT_LO_WATERMARK) {
++		while (skb_queue_len(&cm_node->cm_core->tx_free_list) <
++				cm_node->cm_core->free_tx_pkt_max) {
++			/* replace the frame we took, we won't get it back */
++			new_skb = dev_alloc_skb(cm_node->cm_core->mtu);
++			BUG_ON(!new_skb);
++			/* add a replacement frame to the free tx list head */
++			skb_queue_head(&cm_node->cm_core->tx_free_list, new_skb);
++		}
++	}
++
++	skb = skb_dequeue(&cm_node->cm_core->tx_free_list);
++
++	return skb;
 +}
 +
- static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
- {
--	unsigned long sc_base	= pci_resource_start(hwif->pci_dev, 5);
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-+	unsigned long sc_base	= pci_resource_start(dev, 5);
- 	u16 scr1		= inw(sc_base + 0x00);
- 
- 	/* System Control 1 Register bit 15 (Soft Reset) set */
-@@ -184,6 +196,8 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
- 
- 	hwif->busproc	= &tc86c001_busproc;
- 
-+	hwif->cable_detect = tc86c001_cable_detect;
 +
- 	if (!hwif->dma_base)
- 		return;
- 
-@@ -197,15 +211,6 @@ static void __devinit init_hwif_tc86c001(ide_hwif_t *hwif)
- 	hwif->rqsize	 = 0xffff;
- 
- 	hwif->dma_start 	= &tc86c001_dma_start;
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT) {
--		/*
--		 * System Control  1 Register bit 13 (PDIAGN):
--		 * 0=80-pin cable, 1=40-pin cable
--		 */
--		scr1 = inw(sc_base + 0x00);
--		hwif->cbl = (scr1 & 0x2000) ? ATA_CBL_PATA40 : ATA_CBL_PATA80;
--	}
- }
- 
- static unsigned int __devinit init_chipset_tc86c001(struct pci_dev *dev,
-@@ -222,7 +227,8 @@ static const struct ide_port_info tc86c001_chipset __devinitdata = {
- 	.name		= "TC86C001",
- 	.init_chipset	= init_chipset_tc86c001,
- 	.init_hwif	= init_hwif_tc86c001,
--	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD,
-+	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_OFF_BOARD |
-+			  IDE_HFLAG_ABUSE_SET_DMA_MODE,
- 	.pio_mask	= ATA_PIO4,
- 	.mwdma_mask	= ATA_MWDMA2,
- 	.udma_mask	= ATA_UDMA4,
-diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
-index a227c41..a67d02a 100644
---- a/drivers/ide/pci/triflex.c
-+++ b/drivers/ide/pci/triflex.c
-@@ -1,6 +1,4 @@
- /*
-- * triflex.c
-- * 
-  * IDE Chipset driver for the Compaq TriFlex IDE controller.
-  * 
-  * Known to work with the Compaq Workstation 5x00 series.
-@@ -30,11 +28,6 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/delay.h>
--#include <linux/timer.h>
--#include <linux/mm.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/hdreg.h>
- #include <linux/pci.h>
- #include <linux/ide.h>
-@@ -43,7 +36,7 @@
- static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
- {
- 	ide_hwif_t *hwif = HWIF(drive);
--	struct pci_dev *dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	u8 channel_offset = hwif->channel ? 0x74 : 0x70;
- 	u16 timing = 0;
- 	u32 triflex_timings = 0;
-@@ -81,8 +74,6 @@ static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
- 		case XFER_PIO_0:
- 			timing = 0x0808;
- 			break;
--		default:
--			return;
- 	}
- 
- 	triflex_timings &= ~(0xFFFF << (16 * unit));
-diff --git a/drivers/ide/pci/trm290.c b/drivers/ide/pci/trm290.c
-index 0151d7f..de750f7 100644
---- a/drivers/ide/pci/trm290.c
-+++ b/drivers/ide/pci/trm290.c
-@@ -1,8 +1,7 @@
- /*
-- *  linux/drivers/ide/pci/trm290.c		Version 1.05	Dec. 26, 2007
-- *
-  *  Copyright (c) 1997-1998  Mark Lord
-  *  Copyright (c) 2007       MontaVista Software, Inc. <source at mvista.com>
-+ *
-  *  May be copied or modified under the terms of the GNU General Public License
-  *
-  *  June 22, 2004 - get rid of check_region
-@@ -132,14 +131,12 @@
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/mm.h>
- #include <linux/ioport.h>
- #include <linux/interrupt.h>
- #include <linux/blkdev.h>
- #include <linux/init.h>
- #include <linux/hdreg.h>
- #include <linux/pci.h>
--#include <linux/delay.h>
- #include <linux/ide.h>
- 
- #include <asm/io.h>
-@@ -180,10 +177,7 @@ static void trm290_selectproc (ide_drive_t *drive)
- 
- static void trm290_dma_exec_cmd(ide_drive_t *drive, u8 command)
- {
--	BUG_ON(HWGROUP(drive)->handler != NULL);	/* paranoia check */
--	ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL);
--	/* issue cmd to drive */
--	outb(command, IDE_COMMAND_REG);
-+	ide_execute_command(drive, command, &ide_dma_intr, WAIT_CMD, NULL);
- }
- 
- static int trm290_dma_setup(ide_drive_t *drive)
-@@ -209,10 +203,10 @@ static int trm290_dma_setup(ide_drive_t *drive)
- 	}
- 	/* select DMA xfer */
- 	trm290_prepare_drive(drive, 1);
--	outl(hwif->dmatable_dma | rw, hwif->dma_command);
-+	outl(hwif->dmatable_dma | rw, hwif->dma_base);
- 	drive->waiting_for_dma = 1;
- 	/* start DMA */
--	outw((count * 2) - 1, hwif->dma_status);
-+	outw(count * 2 - 1, hwif->dma_base + 2);
- 	return 0;
- }
- 
-@@ -222,51 +216,61 @@ static void trm290_dma_start(ide_drive_t *drive)
- 
- static int trm290_ide_dma_end (ide_drive_t *drive)
- {
--	ide_hwif_t *hwif = HWIF(drive);
--	u16 status = 0;
-+	u16 status;
- 
- 	drive->waiting_for_dma = 0;
- 	/* purge DMA mappings */
- 	ide_destroy_dmatable(drive);
--	status = inw(hwif->dma_status);
--	return (status != 0x00ff);
-+	status = inw(HWIF(drive)->dma_base + 2);
-+	return status != 0x00ff;
- }
- 
- static int trm290_ide_dma_test_irq (ide_drive_t *drive)
- {
--	ide_hwif_t *hwif = HWIF(drive);
--	u16 status = 0;
-+	u16 status;
- 
--	status = inw(hwif->dma_status);
--	return (status == 0x00ff);
--}
--
--static void trm290_dma_host_on(ide_drive_t *drive)
--{
-+	status = inw(HWIF(drive)->dma_base + 2);
-+	return status == 0x00ff;
- }
- 
--static void trm290_dma_host_off(ide_drive_t *drive)
-+static void trm290_dma_host_set(ide_drive_t *drive, int on)
- {
- }
- 
- static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
- {
--	unsigned int cfgbase = 0;
-+	struct pci_dev *dev	= to_pci_dev(hwif->dev);
-+	unsigned int  cfg_base	= pci_resource_start(dev, 4);
- 	unsigned long flags;
- 	u8 reg = 0;
--	struct pci_dev *dev = hwif->pci_dev;
--
--	cfgbase = pci_resource_start(dev, 4);
--	if ((dev->class & 5) && cfgbase) {
--		hwif->config_data = cfgbase;
--		printk(KERN_INFO "TRM290: chip config base at 0x%04lx\n",
--			hwif->config_data);
--	} else {
--		hwif->config_data = 0x3df0;
--		printk(KERN_INFO "TRM290: using default config base at 0x%04lx\n",
--			hwif->config_data);
++/**
++ * make_hashkey - generate hash key from node tuple
++ */
++static inline int make_hashkey(u16 loc_port, nes_addr_t loc_addr, u16 rem_port,
++		nes_addr_t rem_addr)
++{
++	u32 hashkey = 0;
 +
-+	if ((dev->class & 5) && cfg_base)
-+		printk(KERN_INFO "TRM290: chip");
-+	else {
-+		cfg_base = 0x3df0;
-+		printk(KERN_INFO "TRM290: using default");
++	hashkey = loc_addr + rem_addr + loc_port + rem_port;
++	hashkey = (hashkey % NES_CM_HASHTABLE_SIZE);
++
++	return hashkey;
++}
++
++
++/**
++ * find_node - find a cm node that matches the reference cm node
++ */
++static struct nes_cm_node *find_node(struct nes_cm_core *cm_core,
++		u16 rem_port, nes_addr_t rem_addr, u16 loc_port, nes_addr_t loc_addr)
++{
++	unsigned long flags;
++	u32 hashkey;
++	struct list_head *list_pos;
++	struct list_head *hte;
++	struct nes_cm_node *cm_node;
++
++	/* make a hash index key for this packet */
++	hashkey = make_hashkey(loc_port, loc_addr, rem_port, rem_addr);
++
++	/* get a handle on the hte */
++	hte = &cm_core->connected_nodes;
++
++	nes_debug(NES_DBG_CM, "Searching for an owner node:%x:%x from core %p->%p\n",
++			loc_addr, loc_port, cm_core, hte);
++
++	/* walk list and find cm_node associated with this session ID */
++	spin_lock_irqsave(&cm_core->ht_lock, flags);
++	list_for_each(list_pos, hte) {
++		cm_node = container_of(list_pos, struct nes_cm_node, list);
++		/* compare quad, return node handle if a match */
++		nes_debug(NES_DBG_CM, "finding node %x:%x =? %x:%x ^ %x:%x =? %x:%x\n",
++				cm_node->loc_addr, cm_node->loc_port,
++				loc_addr, loc_port,
++				cm_node->rem_addr, cm_node->rem_port,
++				rem_addr, rem_port);
++		if ((cm_node->loc_addr == loc_addr) && (cm_node->loc_port == loc_port) &&
++				(cm_node->rem_addr == rem_addr) && (cm_node->rem_port == rem_port)) {
++			add_ref_cm_node(cm_node);
++			spin_unlock_irqrestore(&cm_core->ht_lock, flags);
++			return cm_node;
++		}
 +	}
-+	printk(KERN_CONT " config base at 0x%04x\n", cfg_base);
-+	hwif->config_data = cfg_base;
-+	hwif->dma_base = (cfg_base + 4) ^ (hwif->channel ? 0x80 : 0);
++	spin_unlock_irqrestore(&cm_core->ht_lock, flags);
 +
-+	printk(KERN_INFO "    %s: BM-DMA at 0x%04lx-0x%04lx",
-+	       hwif->name, hwif->dma_base, hwif->dma_base + 3);
++	/* no owner node */
++	return NULL;
++}
 +
-+	if (!request_region(hwif->dma_base, 4, hwif->name)) {
-+		printk(KERN_CONT " -- Error, ports in use.\n");
-+		return;
- 	}
- 
-+	hwif->dmatable_cpu = pci_alloc_consistent(dev, PRD_ENTRIES * PRD_BYTES,
-+						  &hwif->dmatable_dma);
-+	if (!hwif->dmatable_cpu) {
-+		printk(KERN_CONT " -- Error, unable to allocate DMA table.\n");
-+		release_region(hwif->dma_base, 4);
-+		return;
++
++/**
++ * find_listener - find a cm node listening on this addr-port pair
++ */
++static struct nes_cm_listener *find_listener(struct nes_cm_core *cm_core,
++		nes_addr_t dst_addr, u16 dst_port, enum nes_cm_listener_state listener_state)
++{
++	unsigned long flags;
++	struct list_head *listen_list;
++	struct nes_cm_listener *listen_node;
++
++	/* walk list and find cm_node associated with this session ID */
++	spin_lock_irqsave(&cm_core->listen_list_lock, flags);
++	list_for_each(listen_list, &cm_core->listen_list.list) {
++		listen_node = container_of(listen_list, struct nes_cm_listener, list);
++		/* compare node pair, return node handle if a match */
++		if (((listen_node->loc_addr == dst_addr) ||
++				listen_node->loc_addr == 0x00000000) &&
++				(listen_node->loc_port == dst_port) &&
++				(listener_state & listen_node->listener_state)) {
++			atomic_inc(&listen_node->ref_count);
++			spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
++			return listen_node;
++		}
 +	}
-+	printk(KERN_CONT "\n");
++	spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
 +
- 	local_irq_save(flags);
- 	/* put config reg into first byte of hwif->select_data */
- 	outb(0x51 | (hwif->channel << 3), hwif->config_data + 1);
-@@ -280,17 +284,14 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif)
- 	outb(reg, hwif->config_data + 3);
- 	local_irq_restore(flags);
- 
--	if ((reg & 0x10))
-+	if (reg & 0x10)
- 		/* legacy mode */
- 		hwif->irq = hwif->channel ? 15 : 14;
- 	else if (!hwif->irq && hwif->mate && hwif->mate->irq)
- 		/* sharing IRQ with mate */
- 		hwif->irq = hwif->mate->irq;
- 
--	ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
--
--	hwif->dma_host_off	= &trm290_dma_host_off;
--	hwif->dma_host_on	= &trm290_dma_host_on;
-+	hwif->dma_host_set	= &trm290_dma_host_set;
- 	hwif->dma_setup 	= &trm290_dma_setup;
- 	hwif->dma_exec_cmd	= &trm290_dma_exec_cmd;
- 	hwif->dma_start 	= &trm290_dma_start;
-diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
-index a0d3c16..f3f79f8 100644
---- a/drivers/ide/pci/via82cxxx.c
-+++ b/drivers/ide/pci/via82cxxx.c
-@@ -1,7 +1,4 @@
- /*
-- *
-- * Version 3.50
-- *
-  * VIA IDE driver for Linux. Supported southbridges:
-  *
-  *   vt82c576, vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
-@@ -29,15 +26,11 @@
- 
- #include <linux/module.h>
- #include <linux/kernel.h>
--#include <linux/ioport.h>
--#include <linux/blkdev.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/ide.h>
- #include <linux/dmi.h>
- 
--#include <asm/io.h>
--
- #ifdef CONFIG_PPC_CHRP
- #include <asm/processor.h>
- #endif
-@@ -121,8 +114,8 @@ struct via82cxxx_dev
- 
- static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
- {
--	struct pci_dev *dev = hwif->pci_dev;
--	struct via82cxxx_dev *vdev = pci_get_drvdata(hwif->pci_dev);
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
- 	u8 t;
- 
- 	if (~vdev->via_config->flags & VIA_BAD_AST) {
-@@ -159,8 +152,10 @@ static void via_set_speed(ide_hwif_t *hwif, u8 dn, struct ide_timing *timing)
- 
- static void via_set_drive(ide_drive_t *drive, const u8 speed)
- {
--	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
--	struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev);
-+	ide_hwif_t *hwif = drive->hwif;
-+	ide_drive_t *peer = hwif->drives + (~drive->dn & 1);
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	struct via82cxxx_dev *vdev = pci_get_drvdata(dev);
- 	struct ide_timing t, p;
- 	unsigned int T, UT;
- 
-@@ -408,7 +403,7 @@ static int via_cable_override(struct pci_dev *pdev)
- 
- static u8 __devinit via82cxxx_cable_detect(ide_hwif_t *hwif)
- {
--	struct pci_dev *pdev = hwif->pci_dev;
-+	struct pci_dev *pdev = to_pci_dev(hwif->dev);
- 	struct via82cxxx_dev *vdev = pci_get_drvdata(pdev);
- 
- 	if (via_cable_override(pdev))
-@@ -425,11 +420,7 @@ static void __devinit init_hwif_via82cxxx(ide_hwif_t *hwif)
- 	hwif->set_pio_mode = &via_set_pio_mode;
- 	hwif->set_dma_mode = &via_set_drive;
- 
--	if (!hwif->dma_base)
--		return;
--
--	if (hwif->cbl != ATA_CBL_PATA40_SHORT)
--		hwif->cbl = via82cxxx_cable_detect(hwif);
-+	hwif->cable_detect = via82cxxx_cable_detect;
- }
- 
- static const struct ide_port_info via82cxxx_chipset __devinitdata = {
-@@ -439,6 +430,7 @@ static const struct ide_port_info via82cxxx_chipset __devinitdata = {
- 	.enablebits	= { { 0x40, 0x02, 0x02 }, { 0x40, 0x01, 0x01 } },
- 	.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST |
- 			  IDE_HFLAG_PIO_NO_DOWNGRADE |
-+			  IDE_HFLAG_ABUSE_SET_DMA_MODE |
- 			  IDE_HFLAG_POST_SET_MODE |
- 			  IDE_HFLAG_IO_32BIT |
- 			  IDE_HFLAG_BOOTABLE,
-diff --git a/drivers/ide/ppc/Makefile b/drivers/ide/ppc/Makefile
-new file mode 100644
-index 0000000..65af584
---- /dev/null
-+++ b/drivers/ide/ppc/Makefile
-@@ -0,0 +1,3 @@
++	nes_debug(NES_DBG_CM, "Unable to find listener- %x:%x\n",
++			dst_addr, dst_port);
 +
-+obj-$(CONFIG_BLK_DEV_IDE_PMAC)		+= pmac.o
-+obj-$(CONFIG_BLK_DEV_MPC8xx_IDE)	+= mpc8xx.o
-diff --git a/drivers/ide/ppc/mpc8xx.c b/drivers/ide/ppc/mpc8xx.c
-index 5f0da35..06190b1 100644
---- a/drivers/ide/ppc/mpc8xx.c
-+++ b/drivers/ide/ppc/mpc8xx.c
-@@ -1,6 +1,4 @@
- /*
-- *  linux/drivers/ide/ppc/ide-m8xx.c
-- *
-  *  Copyright (C) 2000, 2001 Wolfgang Denk, wd at denx.de
-  *  Modified for direct IDE interface
-  *	by Thomas Lange, thomas at corelatus.com
-@@ -838,3 +836,21 @@ void m8xx_ide_init(void)
- 	ppc_ide_md.default_io_base      = m8xx_ide_default_io_base;
- 	ppc_ide_md.ide_init_hwif        = m8xx_ide_init_hwif_ports;
- }
++	/* no listener */
++	return NULL;
++}
 +
-+static int __init mpc8xx_ide_probe(void)
++
++/**
++ * add_hte_node - add a cm node to the hash table
++ */
++static int add_hte_node(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
 +{
-+	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
++	unsigned long flags;
++	u32 hashkey;
++	struct list_head *hte;
 +
-+#ifdef IDE0_BASE_OFFSET
-+	idx[0] = 0;
-+#ifdef IDE1_BASE_OFFSET
-+	idx[1] = 1;
-+#endif
-+#endif
++	if (!cm_node || !cm_core)
++		return -EINVAL;
 +
-+	ide_device_add(idx, NULL);
++	nes_debug(NES_DBG_CM, "Adding Node to Active Connection HT\n");
++
++	/* first, make an index into our hash table */
++	hashkey = make_hashkey(cm_node->loc_port, cm_node->loc_addr,
++			cm_node->rem_port, cm_node->rem_addr);
++	cm_node->hashkey = hashkey;
++
++	spin_lock_irqsave(&cm_core->ht_lock, flags);
++
++	/* get a handle on the hash table element (list head for this slot) */
++	hte = &cm_core->connected_nodes;
++	list_add_tail(&cm_node->list, hte);
++	atomic_inc(&cm_core->ht_node_cnt);
++
++	spin_unlock_irqrestore(&cm_core->ht_lock, flags);
 +
 +	return 0;
 +}
 +
-+module_init(mpc8xx_ide_probe);
-diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
-index 7f7a598..12ac3bf 100644
---- a/drivers/ide/ppc/pmac.c
-+++ b/drivers/ide/ppc/pmac.c
-@@ -1,7 +1,6 @@
- /*
-- * linux/drivers/ide/ppc/pmac.c
-- *
-  * Support for IDE interfaces on PowerMacs.
-+ *
-  * These IDE interfaces are memory-mapped and have a DBDMA channel
-  * for doing DMA.
-  *
-@@ -413,7 +412,7 @@ kauai_lookup_timing(struct kauai_timing* table, int cycle_time)
-  */
- #define IDE_WAKEUP_DELAY	(1*HZ)
- 
--static void pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
-+static int pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif);
- static int pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq);
- static void pmac_ide_selectproc(ide_drive_t *drive);
- static void pmac_ide_kauai_selectproc(ide_drive_t *drive);
-@@ -438,13 +437,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw,
- 		if (data_port == pmac_ide[ix].regbase)
- 			break;
- 
--	if (ix >= MAX_HWIFS) {
--		/* Probably a PCI interface... */
--		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
--			hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
--		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
--		return;
--	}
-+	if (ix >= MAX_HWIFS)
-+		return;		/* not an IDE PMAC interface */
- 
- 	for (i = 0; i < 8; ++i)
- 		hw->io_ports[i] = data_port + i * 0x10;
-@@ -833,38 +827,20 @@ static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
- 	tl[0] = *timings;
- 	tl[1] = *timings2;
- 
--	switch(speed) {
- #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
--		case XFER_UDMA_6:
--		case XFER_UDMA_5:
--		case XFER_UDMA_4:
--		case XFER_UDMA_3:
--		case XFER_UDMA_2:
--		case XFER_UDMA_1:
--		case XFER_UDMA_0:
--			if (pmif->kind == controller_kl_ata4)
--				ret = set_timings_udma_ata4(&tl[0], speed);
--			else if (pmif->kind == controller_un_ata6
--				 || pmif->kind == controller_k2_ata6)
--				ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
--			else if (pmif->kind == controller_sh_ata6)
--				ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
--			else
--				ret = 1;
--			break;
--		case XFER_MW_DMA_2:
--		case XFER_MW_DMA_1:
--		case XFER_MW_DMA_0:
--			set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
--			break;
--		case XFER_SW_DMA_2:
--		case XFER_SW_DMA_1:
--		case XFER_SW_DMA_0:
--			return;
-+	if (speed >= XFER_UDMA_0) {
-+		if (pmif->kind == controller_kl_ata4)
-+			ret = set_timings_udma_ata4(&tl[0], speed);
-+		else if (pmif->kind == controller_un_ata6
-+			 || pmif->kind == controller_k2_ata6)
-+			ret = set_timings_udma_ata6(&tl[0], &tl[1], speed);
-+		else if (pmif->kind == controller_sh_ata6)
-+			ret = set_timings_udma_shasta(&tl[0], &tl[1], speed);
-+		else
-+			ret = -1;
-+	} else
-+		set_timings_mdma(drive, pmif->kind, &tl[0], &tl[1], speed);
- #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
--		default:
--			ret = 1;
--	}
- 	if (ret)
- 		return;
- 
-@@ -1027,6 +1003,17 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
- 	return 0;
- }
- 
-+static const struct ide_port_info pmac_port_info = {
-+	.chipset		= ide_pmac,
-+	.host_flags		= IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
-+				  IDE_HFLAG_PIO_NO_DOWNGRADE |
-+				  IDE_HFLAG_POST_SET_MODE |
-+				  IDE_HFLAG_NO_DMA | /* no SFF-style DMA */
-+				  IDE_HFLAG_UNMASK_IRQS,
-+	.pio_mask		= ATA_PIO4,
-+	.mwdma_mask		= ATA_MWDMA2,
-+};
 +
- /*
-  * Setup, register & probe an IDE channel driven by this driver, this is
-  * called by one of the 2 probe functions (macio or PCI). Note that a channel
-@@ -1034,30 +1021,34 @@ pmac_ide_do_resume(ide_hwif_t *hwif)
-  * (it is kept in 2.4). This introduce an interface numbering change on some
-  * rare machines unfortunately, but it's better this way.
-  */
--static int
--pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
-+static int __devinit
-+pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif, hw_regs_t *hw)
- {
- 	struct device_node *np = pmif->node;
- 	const int *bidp;
- 	u8 idx[4] = { 0xff, 0xff, 0xff, 0xff };
--	hw_regs_t hw;
-+	struct ide_port_info d = pmac_port_info;
- 
- 	pmif->cable_80 = 0;
- 	pmif->broken_dma = pmif->broken_dma_warn = 0;
--	if (of_device_is_compatible(np, "shasta-ata"))
-+	if (of_device_is_compatible(np, "shasta-ata")) {
- 		pmif->kind = controller_sh_ata6;
--	else if (of_device_is_compatible(np, "kauai-ata"))
-+		d.udma_mask = ATA_UDMA6;
-+	} else if (of_device_is_compatible(np, "kauai-ata")) {
- 		pmif->kind = controller_un_ata6;
--	else if (of_device_is_compatible(np, "K2-UATA"))
-+		d.udma_mask = ATA_UDMA5;
-+	} else if (of_device_is_compatible(np, "K2-UATA")) {
- 		pmif->kind = controller_k2_ata6;
--	else if (of_device_is_compatible(np, "keylargo-ata")) {
--		if (strcmp(np->name, "ata-4") == 0)
-+		d.udma_mask = ATA_UDMA5;
-+	} else if (of_device_is_compatible(np, "keylargo-ata")) {
-+		if (strcmp(np->name, "ata-4") == 0) {
- 			pmif->kind = controller_kl_ata4;
--		else
-+			d.udma_mask = ATA_UDMA4;
-+		} else
- 			pmif->kind = controller_kl_ata3;
--	} else if (of_device_is_compatible(np, "heathrow-ata"))
-+	} else if (of_device_is_compatible(np, "heathrow-ata")) {
- 		pmif->kind = controller_heathrow;
--	else {
-+	} else {
- 		pmif->kind = controller_ohare;
- 		pmif->broken_dma = 1;
- 	}
-@@ -1126,21 +1117,10 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
- 	/* Tell common code _not_ to mess with resources */
- 	hwif->mmio = 1;
- 	hwif->hwif_data = pmif;
--	memset(&hw, 0, sizeof(hw));
--	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, &hwif->irq);
--	memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
--	hwif->chipset = ide_pmac;
--	hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || pmif->mediabay;
-+	ide_init_port_hw(hwif, hw);
-+	hwif->noprobe = pmif->mediabay;
- 	hwif->hold = pmif->mediabay;
- 	hwif->cbl = pmif->cable_80 ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
--	hwif->drives[0].unmask = 1;
--	hwif->drives[1].unmask = 1;
--	hwif->drives[0].autotune = IDE_TUNE_AUTO;
--	hwif->drives[1].autotune = IDE_TUNE_AUTO;
--	hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
--			   IDE_HFLAG_PIO_NO_DOWNGRADE |
--			   IDE_HFLAG_POST_SET_MODE;
--	hwif->pio_mask = ATA_PIO4;
- 	hwif->set_pio_mode = pmac_ide_set_pio_mode;
- 	if (pmif->kind == controller_un_ata6
- 	    || pmif->kind == controller_k2_ata6
-@@ -1159,17 +1139,17 @@ pmac_ide_setup_device(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
- 		hwif->noprobe = 0;
- #endif /* CONFIG_PMAC_MEDIABAY */
- 
--	hwif->sg_max_nents = MAX_DCMDS;
--
- #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
-+	if (pmif->cable_80 == 0)
-+		d.udma_mask &= ATA_UDMA2;
- 	/* has a DBDMA controller channel */
--	if (pmif->dma_regs)
--		pmac_ide_setup_dma(pmif, hwif);
--#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
-+	if (pmif->dma_regs == 0 || pmac_ide_setup_dma(pmif, hwif) < 0)
-+#endif
-+		d.udma_mask = d.mwdma_mask = 0;
- 
- 	idx[0] = hwif->index;
- 
--	ide_device_add(idx);
-+	ide_device_add(idx, &d);
- 
- 	return 0;
- }
-@@ -1186,6 +1166,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
- 	ide_hwif_t *hwif;
- 	pmac_ide_hwif_t *pmif;
- 	int i, rc;
-+	hw_regs_t hw;
- 
- 	i = 0;
- 	while (i < MAX_HWIFS && (ide_hwifs[i].io_ports[IDE_DATA_OFFSET] != 0
-@@ -1227,8 +1208,7 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
- 	base = ioremap(macio_resource_start(mdev, 0), 0x400);
- 	regbase = (unsigned long) base;
- 
--	hwif->pci_dev = mdev->bus->pdev;
--	hwif->gendev.parent = &mdev->ofdev.dev;
-+	hwif->dev = &mdev->bus->pdev->dev;
- 
- 	pmif->mdev = mdev;
- 	pmif->node = mdev->ofdev.node;
-@@ -1246,17 +1226,22 @@ pmac_ide_macio_attach(struct macio_dev *mdev, const struct of_device_id *match)
- #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
- 	dev_set_drvdata(&mdev->ofdev.dev, hwif);
- 
--	rc = pmac_ide_setup_device(pmif, hwif);
-+	memset(&hw, 0, sizeof(hw));
-+	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
-+	hw.irq = irq;
-+	hw.dev = &mdev->ofdev.dev;
++/**
++ * mini_cm_dec_refcnt_listen
++ */
++static int mini_cm_dec_refcnt_listen(struct nes_cm_core *cm_core,
++		struct nes_cm_listener *listener, int free_hanging_nodes)
++{
++	int ret = 1;
++	unsigned long flags;
++	spin_lock_irqsave(&cm_core->listen_list_lock, flags);
++	if (!atomic_dec_return(&listener->ref_count)) {
++		list_del(&listener->list);
 +
-+	rc = pmac_ide_setup_device(pmif, hwif, &hw);
- 	if (rc != 0) {
- 		/* The inteface is released to the common IDE layer */
- 		dev_set_drvdata(&mdev->ofdev.dev, NULL);
- 		iounmap(base);
--		if (pmif->dma_regs)
-+		if (pmif->dma_regs) {
- 			iounmap(pmif->dma_regs);
-+			macio_release_resource(mdev, 1);
++		/* decrement our listen node count */
++		atomic_dec(&cm_core->listen_node_cnt);
++
++		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
++
++		if (listener->nesvnic) {
++			nes_manage_apbvt(listener->nesvnic, listener->loc_port,
++					PCI_FUNC(listener->nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
 +		}
- 		memset(pmif, 0, sizeof(*pmif));
- 		macio_release_resource(mdev, 0);
--		if (pmif->dma_regs)
--			macio_release_resource(mdev, 1);
- 	}
- 
- 	return rc;
-@@ -1305,6 +1290,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
- 	void __iomem *base;
- 	unsigned long rbase, rlen;
- 	int i, rc;
-+	hw_regs_t hw;
- 
- 	np = pci_device_to_OF_node(pdev);
- 	if (np == NULL) {
-@@ -1337,8 +1323,7 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
- 		return -ENXIO;
- 	}
- 
--	hwif->pci_dev = pdev;
--	hwif->gendev.parent = &pdev->dev;
-+	hwif->dev = &pdev->dev;
- 	pmif->mdev = NULL;
- 	pmif->node = np;
- 
-@@ -1355,7 +1340,12 @@ pmac_ide_pci_attach(struct pci_dev *pdev, const struct pci_device_id *id)
- 
- 	pci_set_drvdata(pdev, hwif);
- 
--	rc = pmac_ide_setup_device(pmif, hwif);
-+	memset(&hw, 0, sizeof(hw));
-+	pmac_ide_init_hwif_ports(&hw, pmif->regbase, 0, NULL);
-+	hw.irq = pdev->irq;
-+	hw.dev = &pdev->dev;
 +
-+	rc = pmac_ide_setup_device(pmif, hwif, &hw);
- 	if (rc != 0) {
- 		/* The inteface is released to the common IDE layer */
- 		pci_set_drvdata(pdev, NULL);
-@@ -1553,11 +1543,10 @@ pmac_ide_build_dmatable(ide_drive_t *drive, struct request *rq)
- 	}
- 
- 	printk(KERN_DEBUG "%s: empty DMA table?\n", drive->name);
-- use_pio_instead:
--	pci_unmap_sg(hwif->pci_dev,
--		     hwif->sg_table,
--		     hwif->sg_nents,
--		     hwif->sg_dma_direction);
++		nes_debug(NES_DBG_CM, "destroying listener (%p)\n", listener);
 +
-+use_pio_instead:
-+	ide_destroy_dmatable(drive);
++		kfree(listener);
++		ret = 0;
++		cm_listens_destroyed++;
++	} else {
++		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
++	}
++	if (listener) {
++		if (atomic_read(&listener->pend_accepts_cnt) > 0)
++			nes_debug(NES_DBG_CM, "destroying listener (%p)"
++					" with non-zero pending accepts=%u\n",
++					listener, atomic_read(&listener->pend_accepts_cnt));
++	}
 +
- 	return 0; /* revert to PIO for this request */
- }
- 
-@@ -1566,12 +1555,9 @@ static void
- pmac_ide_destroy_dmatable (ide_drive_t *drive)
- {
- 	ide_hwif_t *hwif = drive->hwif;
--	struct pci_dev *dev = HWIF(drive)->pci_dev;
--	struct scatterlist *sg = hwif->sg_table;
--	int nents = hwif->sg_nents;
- 
--	if (nents) {
--		pci_unmap_sg(dev, sg, nents, hwif->sg_dma_direction);
-+	if (hwif->sg_nents) {
-+		ide_destroy_dmatable(drive);
- 		hwif->sg_nents = 0;
- 	}
- }
-@@ -1721,11 +1707,7 @@ pmac_ide_dma_test_irq (ide_drive_t *drive)
- 	return 1;
- }
- 
--static void pmac_ide_dma_host_off(ide_drive_t *drive)
--{
--}
--
--static void pmac_ide_dma_host_on(ide_drive_t *drive)
-+static void pmac_ide_dma_host_set(ide_drive_t *drive, int on)
- {
- }
- 
-@@ -1748,64 +1730,44 @@ pmac_ide_dma_lost_irq (ide_drive_t *drive)
-  * Allocate the data structures needed for using DMA with an interface
-  * and fill the proper list of functions pointers
-  */
--static void __init 
--pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
-+static int __devinit pmac_ide_setup_dma(pmac_ide_hwif_t *pmif, ide_hwif_t *hwif)
- {
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
++	return ret;
++}
 +
- 	/* We won't need pci_dev if we switch to generic consistent
- 	 * DMA routines ...
- 	 */
--	if (hwif->pci_dev == NULL)
--		return;
-+	if (dev == NULL)
-+		return -ENODEV;
- 	/*
- 	 * Allocate space for the DBDMA commands.
- 	 * The +2 is +1 for the stop command and +1 to allow for
- 	 * aligning the start address to a multiple of 16 bytes.
- 	 */
- 	pmif->dma_table_cpu = (struct dbdma_cmd*)pci_alloc_consistent(
--		hwif->pci_dev,
-+		dev,
- 		(MAX_DCMDS + 2) * sizeof(struct dbdma_cmd),
- 		&hwif->dmatable_dma);
- 	if (pmif->dma_table_cpu == NULL) {
- 		printk(KERN_ERR "%s: unable to allocate DMA command list\n",
- 		       hwif->name);
--		return;
-+		return -ENOMEM;
- 	}
- 
--	hwif->dma_off_quietly = &ide_dma_off_quietly;
--	hwif->ide_dma_on = &__ide_dma_on;
-+	hwif->sg_max_nents = MAX_DCMDS;
 +
-+	hwif->dma_host_set = &pmac_ide_dma_host_set;
- 	hwif->dma_setup = &pmac_ide_dma_setup;
- 	hwif->dma_exec_cmd = &pmac_ide_dma_exec_cmd;
- 	hwif->dma_start = &pmac_ide_dma_start;
- 	hwif->ide_dma_end = &pmac_ide_dma_end;
- 	hwif->ide_dma_test_irq = &pmac_ide_dma_test_irq;
--	hwif->dma_host_off = &pmac_ide_dma_host_off;
--	hwif->dma_host_on = &pmac_ide_dma_host_on;
- 	hwif->dma_timeout = &ide_dma_timeout;
- 	hwif->dma_lost_irq = &pmac_ide_dma_lost_irq;
- 
--	switch(pmif->kind) {
--		case controller_sh_ata6:
--			hwif->ultra_mask = pmif->cable_80 ? 0x7f : 0x07;
--			hwif->mwdma_mask = 0x07;
--			hwif->swdma_mask = 0x00;
--			break;
--		case controller_un_ata6:
--		case controller_k2_ata6:
--			hwif->ultra_mask = pmif->cable_80 ? 0x3f : 0x07;
--			hwif->mwdma_mask = 0x07;
--			hwif->swdma_mask = 0x00;
--			break;
--		case controller_kl_ata4:
--			hwif->ultra_mask = pmif->cable_80 ? 0x1f : 0x07;
--			hwif->mwdma_mask = 0x07;
--			hwif->swdma_mask = 0x00;
--			break;
--		default:
--			hwif->ultra_mask = 0x00;
--			hwif->mwdma_mask = 0x07;
--			hwif->swdma_mask = 0x00;
--			break;
--	}
++/**
++ * mini_cm_del_listen
++ */
++static int mini_cm_del_listen(struct nes_cm_core *cm_core,
++		struct nes_cm_listener *listener)
++{
++	listener->listener_state = NES_CM_LISTENER_PASSIVE_STATE;
++	listener->cm_id = NULL; /* going to be destroyed pretty soon */
++	return mini_cm_dec_refcnt_listen(cm_core, listener, 1);
++}
++
++
++/**
++ * mini_cm_accelerated
++ */
++static inline int mini_cm_accelerated(struct nes_cm_core *cm_core,
++		struct nes_cm_node *cm_node)
++{
++	u32 was_timer_set;
++	cm_node->accelerated = 1;
++
++	if (cm_node->accept_pend) {
++		BUG_ON(!cm_node->listener);
++		atomic_dec(&cm_node->listener->pend_accepts_cnt);
++		BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
++	}
++
++	was_timer_set = timer_pending(&cm_core->tcp_timer);
++	if (!was_timer_set) {
++		cm_core->tcp_timer.expires = jiffies + NES_SHORT_TIME;
++		add_timer(&cm_core->tcp_timer);
++	}
++
 +	return 0;
- }
- 
- #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
++}
 +
-+module_init(pmac_ide_probe);
-diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
-index d2cd5a3..634e3f6 100644
---- a/drivers/ide/setup-pci.c
-+++ b/drivers/ide/setup-pci.c
-@@ -1,9 +1,8 @@
- /*
-- *  linux/drivers/ide/setup-pci.c		Version 1.10	2002/08/19
-+ *  Copyright (C) 1998-2000  Andre Hedrick <andre at linux-ide.org>
-+ *  Copyright (C) 1995-1998  Mark Lord
-+ *  Copyright (C)      2007  Bartlomiej Zolnierkiewicz
-  *
-- *  Copyright (c) 1998-2000  Andre Hedrick <andre at linux-ide.org>
-- *
-- *  Copyright (c) 1995-1998  Mark Lord
-  *  May be copied or modified under the terms of the GNU General Public License
-  */
- 
-@@ -140,6 +139,16 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
- }
- 
- #ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-+static void ide_pci_clear_simplex(unsigned long dma_base, const char *name)
++
++/**
++ * nes_addr_send_arp
++ */
++static void nes_addr_send_arp(u32 dst_ip)
 +{
-+	u8 dma_stat = inb(dma_base + 2);
++	struct rtable *rt;
++	struct flowi fl;
 +
-+	outb(dma_stat & 0x60, dma_base + 2);
-+	dma_stat = inb(dma_base + 2);
-+	if (dma_stat & 0x80)
-+		printk(KERN_INFO "%s: simplex device: DMA forced\n", name);
++	memset(&fl, 0, sizeof fl);
++	fl.nl_u.ip4_u.daddr = htonl(dst_ip);
++	if (ip_route_output_key(&init_net, &rt, &fl)) {
++		printk("%s: ip_route_output_key failed for 0x%08X\n",
++				__FUNCTION__, dst_ip);
++		return;
++	}
++
++	neigh_event_send(rt->u.dst.neighbour, NULL);
++	ip_rt_put(rt);
 +}
 +
- /**
-  *	ide_get_or_set_dma_base		-	setup BMIBA
-  *	@d: IDE port info
-@@ -152,8 +161,9 @@ static int ide_setup_pci_baseregs (struct pci_dev *dev, const char *name)
- 
- static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif)
- {
--	unsigned long	dma_base = 0;
--	struct pci_dev	*dev = hwif->pci_dev;
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
-+	unsigned long dma_base = 0;
-+	u8 dma_stat = 0;
- 
- 	if (hwif->mmio)
- 		return hwif->dma_base;
-@@ -165,57 +175,39 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_
- 
- 		dma_base = pci_resource_start(dev, baridx);
- 
--		if (dma_base == 0)
-+		if (dma_base == 0) {
- 			printk(KERN_ERR "%s: DMA base is invalid\n", d->name);
-+			return 0;
++
++/**
++ * make_cm_node - create a new instance of a cm node
++ */
++static struct nes_cm_node *make_cm_node(struct nes_cm_core *cm_core,
++		struct nes_vnic *nesvnic, struct nes_cm_info *cm_info,
++		struct nes_cm_listener *listener)
++{
++	struct nes_cm_node *cm_node;
++	struct timespec ts;
++	int arpindex = 0;
++	struct nes_device *nesdev;
++	struct nes_adapter *nesadapter;
++
++	/* create an hte and cm_node for this instance */
++	cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC);
++	if (!cm_node)
++		return NULL;
++
++	/* set our node specific transport info */
++	cm_node->loc_addr = cm_info->loc_addr;
++	cm_node->rem_addr = cm_info->rem_addr;
++	cm_node->loc_port = cm_info->loc_port;
++	cm_node->rem_port = cm_info->rem_port;
++	cm_node->send_write0 = send_first;
++	nes_debug(NES_DBG_CM, "Make node addresses : loc = %x:%x, rem = %x:%x\n",
++			cm_node->loc_addr, cm_node->loc_port, cm_node->rem_addr, cm_node->rem_port);
++	cm_node->listener = listener;
++	cm_node->netdev = nesvnic->netdev;
++	cm_node->cm_id = cm_info->cm_id;
++	memcpy(cm_node->loc_mac, nesvnic->netdev->dev_addr, ETH_ALEN);
++
++	nes_debug(NES_DBG_CM, "listener=%p, cm_id=%p\n",
++			cm_node->listener, cm_node->cm_id);
++
++	INIT_LIST_HEAD(&cm_node->retrans_list);
++	spin_lock_init(&cm_node->retrans_list_lock);
++	INIT_LIST_HEAD(&cm_node->recv_list);
++	spin_lock_init(&cm_node->recv_list_lock);
++
++	cm_node->loopbackpartner = NULL;
++	atomic_set(&cm_node->ref_count, 1);
++	/* associate our parent CM core */
++	cm_node->cm_core = cm_core;
++	cm_node->tcp_cntxt.loc_id = NES_CM_DEF_LOCAL_ID;
++	cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
++	cm_node->tcp_cntxt.rcv_wnd = NES_CM_DEFAULT_RCV_WND_SCALED >>
++			NES_CM_DEFAULT_RCV_WND_SCALE;
++	ts = current_kernel_time();
++	cm_node->tcp_cntxt.loc_seq_num = htonl(ts.tv_nsec);
++	cm_node->tcp_cntxt.mss = nesvnic->max_frame_size - sizeof(struct iphdr) -
++			sizeof(struct tcphdr) - ETH_HLEN;
++	cm_node->tcp_cntxt.rcv_nxt = 0;
++	/* get a unique session ID , add thread_id to an upcounter to handle race */
++	atomic_inc(&cm_core->node_cnt);
++	atomic_inc(&cm_core->session_id);
++	cm_node->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid);
++	cm_node->conn_type = cm_info->conn_type;
++	cm_node->apbvt_set = 0;
++	cm_node->accept_pend = 0;
++
++	cm_node->nesvnic = nesvnic;
++	/* get some device handles, for arp lookup */
++	nesdev = nesvnic->nesdev;
++	nesadapter = nesdev->nesadapter;
++
++	cm_node->loopbackpartner = NULL;
++	/* get the mac addr for the remote node */
++	arpindex = nes_arp_table(nesdev, cm_node->rem_addr, NULL, NES_ARP_RESOLVE);
++	if (arpindex < 0) {
++		kfree(cm_node);
++		nes_addr_send_arp(cm_info->rem_addr);
++		return NULL;
++	}
++
++	/* copy the mac addr to node context */
++	memcpy(cm_node->rem_mac, nesadapter->arp_table[arpindex].mac_addr, ETH_ALEN);
++	nes_debug(NES_DBG_CM, "Remote mac addr from arp table:%02x,"
++			" %02x, %02x, %02x, %02x, %02x\n",
++			cm_node->rem_mac[0], cm_node->rem_mac[1],
++			cm_node->rem_mac[2], cm_node->rem_mac[3],
++			cm_node->rem_mac[4], cm_node->rem_mac[5]);
++
++	add_hte_node(cm_core, cm_node);
++	atomic_inc(&cm_nodes_created);
++
++	return cm_node;
++}
++
++
++/**
++ * add_ref_cm_node - destroy an instance of a cm node
++ */
++static int add_ref_cm_node(struct nes_cm_node *cm_node)
++{
++	atomic_inc(&cm_node->ref_count);
++	return 0;
++}
++
++
++/**
++ * rem_ref_cm_node - destroy an instance of a cm node
++ */
++static int rem_ref_cm_node(struct nes_cm_core *cm_core,
++		struct nes_cm_node *cm_node)
++{
++	unsigned long flags, qplockflags;
++	struct nes_timer_entry *send_entry;
++	struct nes_timer_entry *recv_entry;
++	struct iw_cm_id *cm_id;
++	struct list_head *list_core, *list_node_temp;
++	struct nes_qp *nesqp;
++
++	if (!cm_node)
++		return -EINVAL;
++
++	spin_lock_irqsave(&cm_node->cm_core->ht_lock, flags);
++	if (atomic_dec_return(&cm_node->ref_count)) {
++		spin_unlock_irqrestore(&cm_node->cm_core->ht_lock, flags);
++		return 0;
++	}
++	list_del(&cm_node->list);
++	atomic_dec(&cm_core->ht_node_cnt);
++	spin_unlock_irqrestore(&cm_node->cm_core->ht_lock, flags);
++
++	/* if the node is destroyed before connection was accelerated */
++	if (!cm_node->accelerated && cm_node->accept_pend) {
++		BUG_ON(!cm_node->listener);
++		atomic_dec(&cm_node->listener->pend_accepts_cnt);
++		BUG_ON(atomic_read(&cm_node->listener->pend_accepts_cnt) < 0);
++	}
++
++	spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++	list_for_each_safe(list_core, list_node_temp, &cm_node->retrans_list) {
++		send_entry = container_of(list_core, struct nes_timer_entry, list);
++		list_del(&send_entry->list);
++		spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++		dev_kfree_skb_any(send_entry->skb);
++		kfree(send_entry);
++		spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
++		continue;
++	}
++	spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags);
++
++	spin_lock_irqsave(&cm_node->recv_list_lock, flags);
++	list_for_each_safe(list_core, list_node_temp, &cm_node->recv_list) {
++		recv_entry = container_of(list_core, struct nes_timer_entry, list);
++		list_del(&recv_entry->list);
++		cm_id = cm_node->cm_id;
++		spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
++		if (recv_entry->type == NES_TIMER_TYPE_CLOSE) {
++			nesqp = (struct nes_qp *)recv_entry->skb;
++			spin_lock_irqsave(&nesqp->lock, qplockflags);
++			if (nesqp->cm_id) {
++				nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE"
++						" with something to do!!! ******\n",
++						nesqp->hwqp.qp_id, cm_id);
++				nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++				nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
++				nesqp->ibqp_state = IB_QPS_ERR;
++				spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++				nes_cm_disconn(nesqp);
++			} else {
++				spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++				nes_debug(NES_DBG_CM, "QP%u: cm_id = %p: ****** HIT A NES_TIMER_TYPE_CLOSE"
++						" with nothing to do!!! ******\n",
++						nesqp->hwqp.qp_id, cm_id);
++				nes_rem_ref(&nesqp->ibqp);
++			}
++			cm_id->rem_ref(cm_id);
++		} else if (recv_entry->type == NES_TIMER_TYPE_RECV) {
++			dev_kfree_skb_any(recv_entry->skb);
 +		}
- 	}
- 
--	if ((d->host_flags & IDE_HFLAG_CS5520) == 0 && dma_base) {
--		u8 simplex_stat = 0;
--		dma_base += hwif->channel ? 8 : 0;
--
--		switch(dev->device) {
--			case PCI_DEVICE_ID_AL_M5219:
--			case PCI_DEVICE_ID_AL_M5229:
--			case PCI_DEVICE_ID_AMD_VIPER_7409:
--			case PCI_DEVICE_ID_CMD_643:
--			case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE:
--			case PCI_DEVICE_ID_REVOLUTION:
--				simplex_stat = inb(dma_base + 2);
--				outb(simplex_stat & 0x60, dma_base + 2);
--				simplex_stat = inb(dma_base + 2);
--				if (simplex_stat & 0x80) {
--					printk(KERN_INFO "%s: simplex device: "
--							 "DMA forced\n",
--							 d->name);
--				}
--				break;
--			default:
--				/*
--				 * If the device claims "simplex" DMA,
--				 * this means only one of the two interfaces
--				 * can be trusted with DMA at any point in time.
--				 * So we should enable DMA only on one of the
--				 * two interfaces.
--				 */
--				simplex_stat = hwif->INB(dma_base + 2);
--				if (simplex_stat & 0x80) {
--					/* simplex device? */
--/*
-- *	At this point we haven't probed the drives so we can't make the
-- *	appropriate decision. Really we should defer this problem
-- *	until we tune the drive then try to grab DMA ownership if we want
-- *	to be the DMA end. This has to be become dynamic to handle hot
-- *	plug.
-- */
--					if (hwif->mate && hwif->mate->dma_base) {
--						printk(KERN_INFO "%s: simplex device: "
--								 "DMA disabled\n",
--								 d->name);
--						dma_base = 0;
--					}
--				}
--		}
-+	if (hwif->channel)
-+		dma_base += 8;
++		kfree(recv_entry);
++		spin_lock_irqsave(&cm_node->recv_list_lock, flags);
++	}
++	spin_unlock_irqrestore(&cm_node->recv_list_lock, flags);
 +
-+	if (d->host_flags & IDE_HFLAG_CS5520)
-+		goto out;
++	if (cm_node->listener) {
++		mini_cm_dec_refcnt_listen(cm_core, cm_node->listener, 0);
++	} else {
++		if (cm_node->apbvt_set && cm_node->nesvnic) {
++			nes_manage_apbvt(cm_node->nesvnic, cm_node->loc_port,
++					PCI_FUNC(cm_node->nesvnic->nesdev->pcidev->devfn),
++					NES_MANAGE_APBVT_DEL);
++		}
++	}
 +
-+	if (d->host_flags & IDE_HFLAG_CLEAR_SIMPLEX) {
-+		ide_pci_clear_simplex(dma_base, d->name);
-+		goto out;
- 	}
++	kfree(cm_node);
++	atomic_dec(&cm_core->node_cnt);
++	atomic_inc(&cm_nodes_destroyed);
 +
-+	/*
-+	 * If the device claims "simplex" DMA, this means that only one of
-+	 * the two interfaces can be trusted with DMA at any point in time
-+	 * (so we should enable DMA only on one of the two interfaces).
-+	 *
-+	 * FIXME: At this point we haven't probed the drives so we can't make
-+	 * the appropriate decision.  Really we should defer this problem until
-+	 * we tune the drive then try to grab DMA ownership if we want to be
-+	 * the DMA end.  This has to be become dynamic to handle hot-plug.
-+	 */
-+	dma_stat = hwif->INB(dma_base + 2);
-+	if ((dma_stat & 0x80) && hwif->mate && hwif->mate->dma_base) {
-+		printk(KERN_INFO "%s: simplex device: DMA disabled\n", d->name);
-+		dma_base = 0;
++	return 0;
++}
++
++
++/**
++ * process_options
++ */
++static int process_options(struct nes_cm_node *cm_node, u8 *optionsloc, u32 optionsize, u32 syn_packet)
++{
++	u32 tmp;
++	u32 offset = 0;
++	union all_known_options *all_options;
++	char got_mss_option = 0;
++
++	while (offset < optionsize) {
++		all_options = (union all_known_options *)(optionsloc + offset);
++		switch (all_options->as_base.optionnum) {
++			case OPTION_NUMBER_END:
++				offset = optionsize;
++				break;
++			case OPTION_NUMBER_NONE:
++				offset += 1;
++				continue;
++			case OPTION_NUMBER_MSS:
++				nes_debug(NES_DBG_CM, "%s: MSS Length: %d Offset: %d Size: %d\n",
++						__FUNCTION__,
++						all_options->as_mss.length, offset, optionsize);
++				got_mss_option = 1;
++				if (all_options->as_mss.length != 4) {
++					return 1;
++				} else {
++					tmp = ntohs(all_options->as_mss.mss);
++					if (tmp > 0 && tmp < cm_node->tcp_cntxt.mss)
++						cm_node->tcp_cntxt.mss = tmp;
++				}
++				break;
++			case OPTION_NUMBER_WINDOW_SCALE:
++				cm_node->tcp_cntxt.snd_wscale = all_options->as_windowscale.shiftcount;
++				break;
++			case OPTION_NUMBER_WRITE0:
++				cm_node->send_write0 = 1;
++				break;
++			default:
++				nes_debug(NES_DBG_CM, "TCP Option not understood: %x\n",
++						all_options->as_base.optionnum);
++				break;
++		}
++		offset += all_options->as_base.length;
 +	}
-+out:
- 	return dma_base;
- }
- #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
-@@ -236,7 +228,9 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise);
-  *	@d: IDE port info
-  *
-  *	Enable the IDE PCI device. We attempt to enable the device in full
-- *	but if that fails then we only need BAR4 so we will enable that.
-+ *	but if that fails then we only need IO space. The PCI code should
-+ *	have setup the proper resources for us already for controllers in
-+ *	legacy mode.
-  *	
-  *	Returns zero on success or an error code
-  */
-@@ -246,7 +240,7 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d)
- 	int ret;
- 
- 	if (pci_enable_device(dev)) {
--		ret = pci_enable_device_bars(dev, 1 << 4);
-+		ret = pci_enable_device_io(dev);
- 		if (ret < 0) {
- 			printk(KERN_WARNING "%s: (ide_setup_pci_device:) "
- 				"Could not enable device.\n", d->name);
-@@ -345,7 +339,8 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
-  *	ide_hwif_configure	-	configure an IDE interface
-  *	@dev: PCI device holding interface
-  *	@d: IDE port info
-- *	@mate: Paired interface if any
-+ *	@port: port number
-+ *	@irq: PCI IRQ
-  *
-  *	Perform the initial set up for the hardware interface structure. This
-  *	is done per interface port rather than per PCI device. There may be
-@@ -354,11 +349,15 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info *
-  *	Returns the new hardware interface structure, or NULL on a failure
-  */
- 
--static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *mate, int port, int irq)
-+static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev,
-+				      const struct ide_port_info *d,
-+				      unsigned int port, int irq)
- {
- 	unsigned long ctl = 0, base = 0;
- 	ide_hwif_t *hwif;
- 	u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0;
-+	u8 oldnoprobe = 0;
-+	struct hw_regs_s hw;
- 
- 	if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) {
- 		/*  Possibly we should fail if these checks report true */
-@@ -381,47 +380,41 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, const struct ide_port
- 	}
- 	if ((hwif = ide_match_hwif(base, bootable, d->name)) == NULL)
- 		return NULL;	/* no room in ide_hwifs[] */
--	if (hwif->io_ports[IDE_DATA_OFFSET] != base ||
--	    hwif->io_ports[IDE_CONTROL_OFFSET] != (ctl | 2)) {
--		hw_regs_t hw;
--
--		memset(&hw, 0, sizeof(hw));
--#ifndef CONFIG_IDE_ARCH_OBSOLETE_INIT
--		ide_std_init_ports(&hw, base, ctl | 2);
--#else
--		ide_init_hwif_ports(&hw, base, ctl | 2, NULL);
--#endif
--		memcpy(hwif->io_ports, hw.io_ports, sizeof(hwif->io_ports));
--		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
--	}
--	hwif->chipset = d->chipset ? d->chipset : ide_pci;
--	hwif->pci_dev = dev;
++	if ((!got_mss_option) && (syn_packet))
++		cm_node->tcp_cntxt.mss = NES_CM_DEFAULT_MSS;
++	return 0;
++}
 +
-+	memset(&hw, 0, sizeof(hw));
-+	hw.irq = hwif->irq ? hwif->irq : irq;
-+	hw.dev = &dev->dev;
-+	hw.chipset = d->chipset ? d->chipset : ide_pci;
-+	ide_std_init_ports(&hw, base, ctl | 2);
 +
-+	if (hwif->io_ports[IDE_DATA_OFFSET] == base &&
-+	    hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2))
-+		oldnoprobe = hwif->noprobe;
++/**
++ * process_packet
++ */
++int process_packet(struct nes_cm_node *cm_node, struct sk_buff *skb,
++		struct nes_cm_core *cm_core)
++{
++	int optionsize;
++	int datasize;
++	int ret = 0;
++	struct tcphdr *tcph = tcp_hdr(skb);
++	u32 inc_sequence;
++	if (cm_node->state == NES_CM_STATE_SYN_SENT && tcph->syn) {
++		inc_sequence = ntohl(tcph->seq);
++		cm_node->tcp_cntxt.rcv_nxt = inc_sequence;
++	}
 +
-+	ide_init_port_hw(hwif, &hw);
++	if ((!tcph) || (cm_node->state == NES_CM_STATE_TSA)) {
++		BUG_ON(!tcph);
++		atomic_inc(&cm_accel_dropped_pkts);
++		return -1;
++	}
 +
-+	hwif->noprobe = oldnoprobe;
++	if (tcph->rst) {
++		atomic_inc(&cm_resets_recvd);
++		nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u. refcnt=%d\n",
++				cm_node, cm_node->state, atomic_read(&cm_node->ref_count));
++		switch (cm_node->state) {
++			case NES_CM_STATE_LISTENING:
++				rem_ref_cm_node(cm_core, cm_node);
++				break;
++			case NES_CM_STATE_TSA:
++			case NES_CM_STATE_CLOSED:
++				break;
++			case NES_CM_STATE_SYN_RCVD:
++					nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X,"
++							" remote 0x%08X:%04X, node state = %u\n",
++							cm_node->loc_addr, cm_node->loc_port,
++							cm_node->rem_addr, cm_node->rem_port,
++							cm_node->state);
++				rem_ref_cm_node(cm_core, cm_node);
++				break;
++			case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
++			case NES_CM_STATE_ESTABLISHED:
++			case NES_CM_STATE_MPAREQ_SENT:
++			default:
++					nes_debug(NES_DBG_CM, "Received a reset for local 0x%08X:%04X,"
++							" remote 0x%08X:%04X, node state = %u refcnt=%d\n",
++							cm_node->loc_addr, cm_node->loc_port,
++							cm_node->rem_addr, cm_node->rem_port,
++							cm_node->state, atomic_read(&cm_node->ref_count));
++				// create event
++				cm_node->state = NES_CM_STATE_CLOSED;
 +
-+	hwif->dev = &dev->dev;
- 	hwif->cds = d;
--	hwif->channel = port;
- 
--	if (!hwif->irq)
--		hwif->irq = irq;
--	if (mate) {
--		hwif->mate = mate;
--		mate->mate = hwif;
--	}
- 	return hwif;
- }
- 
-+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
- /**
-  *	ide_hwif_setup_dma	-	configure DMA interface
-- *	@dev: PCI device
-- *	@d: IDE port info
-  *	@hwif: IDE interface
-+ *	@d: IDE port info
-  *
-  *	Set up the DMA base for the interface. Enable the master bits as
-  *	necessary and attempt to bring the device DMA into a ready to use
-  *	state
-  */
- 
--static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *d, ide_hwif_t *hwif)
-+void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
- {
--#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
-+	struct pci_dev *dev = to_pci_dev(hwif->dev);
- 	u16 pcicmd;
- 
- 	pci_read_config_word(dev, PCI_COMMAND, &pcicmd);
-@@ -446,15 +439,15 @@ static void ide_hwif_setup_dma(struct pci_dev *dev, const struct ide_port_info *
- 			if (d->init_dma) {
- 				d->init_dma(hwif, dma_base);
- 			} else {
--				ide_setup_dma(hwif, dma_base, 8);
-+				ide_setup_dma(hwif, dma_base);
- 			}
- 		} else {
- 			printk(KERN_INFO "%s: %s Bus-Master DMA disabled "
- 				"(BIOS)\n", hwif->name, d->name);
- 		}
- 	}
--#endif /* CONFIG_BLK_DEV_IDEDMA_PCI*/
- }
-+#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
- 
- /**
-  *	ide_setup_pci_controller	-	set up IDE PCI
-@@ -516,7 +509,7 @@ out:
- void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int pciirq, u8 *idx)
- {
- 	int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port;
--	ide_hwif_t *hwif, *mate = NULL;
-+	ide_hwif_t *hwif;
- 	u8 tmp;
- 
- 	/*
-@@ -532,62 +525,11 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, int
- 			continue;	/* port not enabled */
- 		}
- 
--		if ((hwif = ide_hwif_configure(dev, d, mate, port, pciirq)) == NULL)
-+		hwif = ide_hwif_configure(dev, d, port, pciirq);
-+		if (hwif == NULL)
- 			continue;
- 
--		/* setup proper ancestral information */
--		hwif->gendev.parent = &dev->dev;
--
- 		*(idx + port) = hwif->index;
--
--		
--		if (d->init_iops)
--			d->init_iops(hwif);
--
--		if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0)
--			ide_hwif_setup_dma(dev, d, hwif);
--
--		if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) ||
--		    (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS))
--			hwif->irq = port ? 15 : 14;
--
--		hwif->fixup = d->fixup;
--
--		hwif->host_flags = d->host_flags;
--		hwif->pio_mask = d->pio_mask;
--
--		if ((d->host_flags & IDE_HFLAG_SERIALIZE) && hwif->mate)
--			hwif->mate->serialized = hwif->serialized = 1;
--
--		if (d->host_flags & IDE_HFLAG_IO_32BIT) {
--			hwif->drives[0].io_32bit = 1;
--			hwif->drives[1].io_32bit = 1;
--		}
--
--		if (d->host_flags & IDE_HFLAG_UNMASK_IRQS) {
--			hwif->drives[0].unmask = 1;
--			hwif->drives[1].unmask = 1;
--		}
--
--		if (hwif->dma_base) {
--			hwif->swdma_mask = d->swdma_mask;
--			hwif->mwdma_mask = d->mwdma_mask;
--			hwif->ultra_mask = d->udma_mask;
--		}
--
--		hwif->drives[0].autotune = 1;
--		hwif->drives[1].autotune = 1;
--
--		if (d->host_flags & IDE_HFLAG_RQSIZE_256)
--			hwif->rqsize = 256;
--
--		if (d->init_hwif)
--			/* Call chipset-specific routine
--			 * for each enabled hwif
--			 */
--			d->init_hwif(hwif);
--
--		mate = hwif;
- 	}
- }
- 
-@@ -669,7 +611,7 @@ int ide_setup_pci_device(struct pci_dev *dev, const struct ide_port_info *d)
- 	ret = do_ide_setup_pci_device(dev, d, &idx[0], 1);
- 
- 	if (ret >= 0)
--		ide_device_add(idx);
-+		ide_device_add(idx, d);
- 
- 	return ret;
- }
-@@ -693,111 +635,9 @@ int ide_setup_pci_devices(struct pci_dev *dev1, struct pci_dev *dev2,
- 			goto out;
- 	}
- 
--	ide_device_add(idx);
-+	ide_device_add(idx, d);
- out:
- 	return ret;
- }
- 
- EXPORT_SYMBOL_GPL(ide_setup_pci_devices);
--
--#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
--/*
-- *	Module interfaces
-- */
--
--static int pre_init = 1;		/* Before first ordered IDE scan */
--static LIST_HEAD(ide_pci_drivers);
--
--/*
-- *	__ide_pci_register_driver	-	attach IDE driver
-- *	@driver: pci driver
-- *	@module: owner module of the driver
-- *
-- *	Registers a driver with the IDE layer. The IDE layer arranges that
-- *	boot time setup is done in the expected device order and then
-- *	hands the controllers off to the core PCI code to do the rest of
-- *	the work.
-- *
-- *	Returns are the same as for pci_register_driver
-- */
--
--int __ide_pci_register_driver(struct pci_driver *driver, struct module *module,
--			      const char *mod_name)
--{
--	if (!pre_init)
--		return __pci_register_driver(driver, module, mod_name);
--	driver->driver.owner = module;
--	list_add_tail(&driver->node, &ide_pci_drivers);
--	return 0;
--}
--EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
--
--/**
-- *	ide_scan_pcidev		-	find an IDE driver for a device
-- *	@dev: PCI device to check
-- *
-- *	Look for an IDE driver to handle the device we are considering.
-- *	This is only used during boot up to get the ordering correct. After
-- *	boot up the pci layer takes over the job.
-- */
--
--static int __init ide_scan_pcidev(struct pci_dev *dev)
--{
--	struct list_head *l;
--	struct pci_driver *d;
--
--	list_for_each(l, &ide_pci_drivers) {
--		d = list_entry(l, struct pci_driver, node);
--		if (d->id_table) {
--			const struct pci_device_id *id =
--				pci_match_id(d->id_table, dev);
--
--			if (id != NULL && d->probe(dev, id) >= 0) {
--				dev->driver = d;
--				pci_dev_get(dev);
--				return 1;
--			}
--		}
--	}
--	return 0;
--}
--
--/**
-- *	ide_scan_pcibus		-	perform the initial IDE driver scan
-- *	@scan_direction: set for reverse order scanning
-- *
-- *	Perform the initial bus rather than driver ordered scan of the
-- *	PCI drivers. After this all IDE pci handling becomes standard
-- *	module ordering not traditionally ordered.
-- */
-- 	
--void __init ide_scan_pcibus (int scan_direction)
--{
--	struct pci_dev *dev = NULL;
--	struct pci_driver *d;
--	struct list_head *l, *n;
--
--	pre_init = 0;
--	if (!scan_direction)
--		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
--			ide_scan_pcidev(dev);
--	else
--		while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID,
--						     dev)))
--			ide_scan_pcidev(dev);
--
--	/*
--	 *	Hand the drivers over to the PCI layer now we
--	 *	are post init.
--	 */
--
--	list_for_each_safe(l, n, &ide_pci_drivers) {
--		list_del(l);
--		d = list_entry(l, struct pci_driver, node);
--		if (__pci_register_driver(d, d->driver.owner,
--					  d->driver.mod_name))
--			printk(KERN_ERR "%s: failed to register %s driver\n",
--					__FUNCTION__, d->driver.mod_name);
--	}
--}
--#endif
-diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
-index 489c133..1f8153b 100644
---- a/drivers/ieee1394/Makefile
-+++ b/drivers/ieee1394/Makefile
-@@ -15,3 +15,4 @@ obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
- obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
- obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
- 
-+obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
-diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
-index 7c4eb39..73685e7 100644
---- a/drivers/ieee1394/dma.c
-+++ b/drivers/ieee1394/dma.c
-@@ -231,37 +231,24 @@ void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
- 
- #ifdef CONFIG_MMU
- 
--/* nopage() handler for mmap access */
--
--static struct page *dma_region_pagefault(struct vm_area_struct *area,
--					 unsigned long address, int *type)
-+static int dma_region_pagefault(struct vm_area_struct *vma,
-+				struct vm_fault *vmf)
- {
--	unsigned long offset;
--	unsigned long kernel_virt_addr;
--	struct page *ret = NOPAGE_SIGBUS;
--
--	struct dma_region *dma = (struct dma_region *)area->vm_private_data;
-+	struct dma_region *dma = (struct dma_region *)vma->vm_private_data;
- 
- 	if (!dma->kvirt)
--		goto out;
--
--	if ((address < (unsigned long)area->vm_start) ||
--	    (address >
--	     (unsigned long)area->vm_start + (dma->n_pages << PAGE_SHIFT)))
--		goto out;
--
--	if (type)
--		*type = VM_FAULT_MINOR;
--	offset = address - area->vm_start;
--	kernel_virt_addr = (unsigned long)dma->kvirt + offset;
--	ret = vmalloc_to_page((void *)kernel_virt_addr);
--	get_page(ret);
--      out:
--	return ret;
-+		return VM_FAULT_SIGBUS;
++				create_event(cm_node, NES_CM_EVENT_ABORTED);
++				break;
++
++		}
++		return -1;
++	}
++
++	optionsize = (tcph->doff << 2) - sizeof(struct tcphdr);
++
++	skb_pull(skb, ip_hdr(skb)->ihl << 2);
++	skb_pull(skb, tcph->doff << 2);
++
++	datasize = skb->len;
++	inc_sequence = ntohl(tcph->seq);
++	nes_debug(NES_DBG_CM, "datasize = %u, sequence = 0x%08X, ack_seq = 0x%08X,"
++			" rcv_nxt = 0x%08X Flags: %s %s.\n",
++			datasize, inc_sequence, ntohl(tcph->ack_seq),
++			cm_node->tcp_cntxt.rcv_nxt, (tcph->syn ? "SYN":""),
++			(tcph->ack ? "ACK":""));
++
++	if (!tcph->syn && (inc_sequence != cm_node->tcp_cntxt.rcv_nxt)
++		) {
++		nes_debug(NES_DBG_CM, "dropping packet, datasize = %u, sequence = 0x%08X,"
++				" ack_seq = 0x%08X, rcv_nxt = 0x%08X Flags: %s.\n",
++				datasize, inc_sequence, ntohl(tcph->ack_seq),
++				cm_node->tcp_cntxt.rcv_nxt, (tcph->ack ? "ACK":""));
++		if (cm_node->state == NES_CM_STATE_LISTENING) {
++			rem_ref_cm_node(cm_core, cm_node);
++		}
++		return -1;
++	}
++
++		cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
++
++
++	if (optionsize) {
++		u8 *optionsloc = (u8 *)&tcph[1];
++		if (process_options(cm_node, optionsloc, optionsize, (u32)tcph->syn)) {
++			nes_debug(NES_DBG_CM, "%s: Node %p, Sending RESET\n", __FUNCTION__, cm_node);
++			send_reset(cm_node);
++			if (cm_node->state != NES_CM_STATE_SYN_SENT)
++			rem_ref_cm_node(cm_core, cm_node);
++			return 0;
++		}
++	} else if (tcph->syn)
++		cm_node->tcp_cntxt.mss = NES_CM_DEFAULT_MSS;
++
++	cm_node->tcp_cntxt.snd_wnd = ntohs(tcph->window) <<
++			cm_node->tcp_cntxt.snd_wscale;
++
++	if (cm_node->tcp_cntxt.snd_wnd > cm_node->tcp_cntxt.max_snd_wnd) {
++		cm_node->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.snd_wnd;
++	}
++
++	if (tcph->ack) {
++		cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->ack_seq);
++		switch (cm_node->state) {
++			case NES_CM_STATE_SYN_RCVD:
++			case NES_CM_STATE_SYN_SENT:
++				/* read and stash current sequence number */
++				if (cm_node->tcp_cntxt.rem_ack_num != cm_node->tcp_cntxt.loc_seq_num) {
++					nes_debug(NES_DBG_CM, "ERROR - cm_node->tcp_cntxt.rem_ack_num !="
++							" cm_node->tcp_cntxt.loc_seq_num\n");
++					send_reset(cm_node);
++					return 0;
++				}
++				if (cm_node->state == NES_CM_STATE_SYN_SENT)
++					cm_node->state = NES_CM_STATE_ONE_SIDE_ESTABLISHED;
++				else {
++						cm_node->state = NES_CM_STATE_ESTABLISHED;
++				}
++				break;
++			case NES_CM_STATE_LAST_ACK:
++				cm_node->state = NES_CM_STATE_CLOSED;
++				break;
++			case NES_CM_STATE_FIN_WAIT1:
++				cm_node->state = NES_CM_STATE_FIN_WAIT2;
++				break;
++			case NES_CM_STATE_CLOSING:
++				cm_node->state = NES_CM_STATE_TIME_WAIT;
++				/* need to schedule this to happen in 2MSL timeouts */
++				cm_node->state = NES_CM_STATE_CLOSED;
++				break;
++			case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
++			case NES_CM_STATE_ESTABLISHED:
++			case NES_CM_STATE_MPAREQ_SENT:
++			case NES_CM_STATE_CLOSE_WAIT:
++			case NES_CM_STATE_TIME_WAIT:
++			case NES_CM_STATE_CLOSED:
++				break;
++			case NES_CM_STATE_LISTENING:
++				nes_debug(NES_DBG_CM, "Received an ACK on a listening port (SYN %d)\n", tcph->syn);
++				cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
++				send_reset(cm_node);
++				/* send_reset bumps refcount, this should have been a new node */
++				rem_ref_cm_node(cm_core, cm_node);
++				return -1;
++				break;
++			case NES_CM_STATE_TSA:
++				nes_debug(NES_DBG_CM, "Received a packet with the ack bit set while in TSA state\n");
++				break;
++			case NES_CM_STATE_UNKNOWN:
++			case NES_CM_STATE_INITED:
++			case NES_CM_STATE_ACCEPTING:
++			case NES_CM_STATE_FIN_WAIT2:
++			default:
++				nes_debug(NES_DBG_CM, "Received ack from unknown state: %x\n",
++						cm_node->state);
++				send_reset(cm_node);
++				break;
++		}
++	}
 +
-+	if (vmf->pgoff >= dma->n_pages)
-+		return VM_FAULT_SIGBUS;
++	if (tcph->syn) {
++		if (cm_node->state == NES_CM_STATE_LISTENING) {
++			/* do not exceed backlog */
++			atomic_inc(&cm_node->listener->pend_accepts_cnt);
++			if (atomic_read(&cm_node->listener->pend_accepts_cnt) >
++					cm_node->listener->backlog) {
++				nes_debug(NES_DBG_CM, "drop syn due to backlog pressure \n");
++				cm_backlog_drops++;
++				atomic_dec(&cm_node->listener->pend_accepts_cnt);
++				rem_ref_cm_node(cm_core, cm_node);
++				return 0;
++			}
++			cm_node->accept_pend = 1;
 +
-+	vmf->page = vmalloc_to_page(dma->kvirt + (vmf->pgoff << PAGE_SHIFT));
-+	get_page(vmf->page);
-+	return 0;
- }
- 
- static struct vm_operations_struct dma_region_vm_ops = {
--	.nopage = dma_region_pagefault,
-+	.fault = dma_region_pagefault,
- };
- 
- /**
-@@ -275,7 +262,7 @@ int dma_region_mmap(struct dma_region *dma, struct file *file,
- 	if (!dma->kvirt)
- 		return -EINVAL;
- 
--	/* must be page-aligned */
-+	/* must be page-aligned (XXX: comment is wrong, we could allow pgoff) */
- 	if (vma->vm_pgoff != 0)
- 		return -EINVAL;
- 
-diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
-index 6779893..10c3d9f 100644
---- a/drivers/ieee1394/ieee1394_transactions.c
-+++ b/drivers/ieee1394/ieee1394_transactions.c
-@@ -570,71 +570,3 @@ int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- 
- 	return retval;
- }
--
--#if 0
--
--int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
--	      u64 addr, int extcode, quadlet_t * data, quadlet_t arg)
--{
--	struct hpsb_packet *packet;
--	int retval = 0;
--
--	BUG_ON(in_interrupt());	// We can't be called in an interrupt, yet
--
--	packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
--	if (!packet)
--		return -ENOMEM;
--
--	packet->generation = generation;
--	retval = hpsb_send_packet_and_wait(packet);
--	if (retval < 0)
--		goto hpsb_lock_fail;
--
--	retval = hpsb_packet_success(packet);
--
--	if (retval == 0) {
--		*data = packet->data[0];
--	}
--
--      hpsb_lock_fail:
--	hpsb_free_tlabel(packet);
--	hpsb_free_packet(packet);
--
--	return retval;
--}
--
--int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
--		   quadlet_t * buffer, size_t length, u32 specifier_id,
--		   unsigned int version)
--{
--	struct hpsb_packet *packet;
--	int retval = 0;
--	u16 specifier_id_hi = (specifier_id & 0x00ffff00) >> 8;
--	u8 specifier_id_lo = specifier_id & 0xff;
--
--	HPSB_VERBOSE("Send GASP: channel = %d, length = %Zd", channel, length);
--
--	length += 8;
--
--	packet = hpsb_make_streampacket(host, NULL, length, channel, 3, 0);
--	if (!packet)
--		return -ENOMEM;
--
--	packet->data[0] = cpu_to_be32((host->node_id << 16) | specifier_id_hi);
--	packet->data[1] =
--	    cpu_to_be32((specifier_id_lo << 24) | (version & 0x00ffffff));
--
--	memcpy(&(packet->data[2]), buffer, length - 8);
--
--	packet->generation = generation;
--
--	packet->no_waiter = 1;
--
--	retval = hpsb_send_packet(packet);
--	if (retval < 0)
--		hpsb_free_packet(packet);
--
--	return retval;
--}
--
--#endif				/*  0  */
-diff --git a/drivers/ieee1394/init_ohci1394_dma.c b/drivers/ieee1394/init_ohci1394_dma.c
-new file mode 100644
-index 0000000..ddaab6e
---- /dev/null
-+++ b/drivers/ieee1394/init_ohci1394_dma.c
-@@ -0,0 +1,285 @@
-+/*
-+ * init_ohci1394_dma.c - Initializes physical DMA on all OHCI 1394 controllers
-+ *
-+ * Copyright (C) 2006-2007      Bernhard Kaindl <bk at suse.de>
-+ *
-+ * Derived from drivers/ieee1394/ohci1394.c and arch/x86/kernel/early-quirks.c
-+ * this file has functions to:
-+ * - scan the PCI very early on boot for all OHCI 1394-compliant controllers
-+ * - reset and initialize them and make them join the IEEE1394 bus and
-+ * - enable physical DMA on them to allow remote debugging
-+ *
-+ * All code and data is marked as __init and __initdata, respective as
-+ * during boot, all OHCI1394 controllers may be claimed by the firewire
-+ * stack and at this point, this code should not touch them anymore.
-+ *
-+ * To use physical DMA after the initialization of the firewire stack,
-+ * be sure that the stack enables it and (re-)attach after the bus reset
-+ * which may be caused by the firewire stack initialization.
-+ *
-+ * 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.
++		}
++		if (datasize == 0)
++			cm_node->tcp_cntxt.rcv_nxt ++;
++
++		if (cm_node->state == NES_CM_STATE_LISTENING) {
++			cm_node->state = NES_CM_STATE_SYN_RCVD;
++			send_syn(cm_node, 1);
++		}
++		if (cm_node->state == NES_CM_STATE_ONE_SIDE_ESTABLISHED) {
++			cm_node->state = NES_CM_STATE_ESTABLISHED;
++			/* send final handshake ACK */
++			ret = send_ack(cm_node);
++			if (ret < 0)
++				return ret;
++
++				cm_node->state = NES_CM_STATE_MPAREQ_SENT;
++				ret = send_mpa_request(cm_node);
++				if (ret < 0)
++					return ret;
++		}
++	}
++
++	if (tcph->fin) {
++		cm_node->tcp_cntxt.rcv_nxt++;
++		switch (cm_node->state) {
++			case NES_CM_STATE_SYN_RCVD:
++			case NES_CM_STATE_SYN_SENT:
++			case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
++			case NES_CM_STATE_ESTABLISHED:
++			case NES_CM_STATE_ACCEPTING:
++			case NES_CM_STATE_MPAREQ_SENT:
++				cm_node->state = NES_CM_STATE_CLOSE_WAIT;
++				cm_node->state = NES_CM_STATE_LAST_ACK;
++				ret = send_fin(cm_node, NULL);
++				break;
++			case NES_CM_STATE_FIN_WAIT1:
++				cm_node->state = NES_CM_STATE_CLOSING;
++				ret = send_ack(cm_node);
++				break;
++			case NES_CM_STATE_FIN_WAIT2:
++				cm_node->state = NES_CM_STATE_TIME_WAIT;
++				cm_node->tcp_cntxt.loc_seq_num ++;
++				ret = send_ack(cm_node);
++				/* need to schedule this to happen in 2MSL timeouts */
++				cm_node->state = NES_CM_STATE_CLOSED;
++				break;
++			case NES_CM_STATE_CLOSE_WAIT:
++			case NES_CM_STATE_LAST_ACK:
++			case NES_CM_STATE_CLOSING:
++			case NES_CM_STATE_TSA:
++			default:
++				nes_debug(NES_DBG_CM, "Received a fin while in %x state\n",
++						cm_node->state);
++				ret = -EINVAL;
++				break;
++		}
++	}
++
++	if (datasize) {
++		u8 *dataloc = skb->data;
++		/* figure out what state we are in and handle transition to next state */
++		switch (cm_node->state) {
++			case NES_CM_STATE_LISTENING:
++			case NES_CM_STATE_SYN_RCVD:
++			case NES_CM_STATE_SYN_SENT:
++			case NES_CM_STATE_FIN_WAIT1:
++			case NES_CM_STATE_FIN_WAIT2:
++			case NES_CM_STATE_CLOSE_WAIT:
++			case NES_CM_STATE_LAST_ACK:
++			case NES_CM_STATE_CLOSING:
++				break;
++			case  NES_CM_STATE_MPAREQ_SENT:
++				/* recv the mpa res frame, ret=frame len (incl priv data) */
++				ret = parse_mpa(cm_node, dataloc, datasize);
++				if (ret < 0)
++					break;
++				/* set the req frame payload len in skb */
++				/* we are done handling this state, set node to a TSA state */
++				cm_node->state = NES_CM_STATE_TSA;
++				send_ack(cm_node);
++				create_event(cm_node, NES_CM_EVENT_CONNECTED);
++				break;
++
++			case  NES_CM_STATE_ESTABLISHED:
++				/* we are expecting an MPA req frame */
++				ret = parse_mpa(cm_node, dataloc, datasize);
++				if (ret < 0) {
++					break;
++				}
++				cm_node->state = NES_CM_STATE_TSA;
++				send_ack(cm_node);
++				/* we got a valid MPA request, create an event */
++				create_event(cm_node, NES_CM_EVENT_MPA_REQ);
++				break;
++			case  NES_CM_STATE_TSA:
++				handle_exception_pkt(cm_node, skb);
++				break;
++			case NES_CM_STATE_UNKNOWN:
++			case NES_CM_STATE_INITED:
++			default:
++				ret = -1;
++		}
++	}
++
++	return ret;
++}
++
++
++/**
++ * mini_cm_listen - create a listen node with params
 + */
++static struct nes_cm_listener *mini_cm_listen(struct nes_cm_core *cm_core,
++		struct nes_vnic *nesvnic, struct nes_cm_info *cm_info)
++{
++	struct nes_cm_listener *listener;
++	unsigned long flags;
 +
-+#include <linux/interrupt.h>	/* for ohci1394.h */
-+#include <linux/delay.h>
-+#include <linux/pci.h>		/* for PCI defines */
-+#include <linux/init_ohci1394_dma.h>
-+#include <asm/pci-direct.h>	/* for direct PCI config space access */
-+#include <asm/fixmap.h>
++	nes_debug(NES_DBG_CM, "Search for 0x%08x : 0x%04x\n",
++		cm_info->loc_addr, cm_info->loc_port);
 +
-+#include "ieee1394_types.h"
-+#include "ohci1394.h"
++	/* cannot have multiple matching listeners */
++	listener = find_listener(cm_core, htonl(cm_info->loc_addr),
++			htons(cm_info->loc_port), NES_CM_LISTENER_EITHER_STATE);
++	if (listener && listener->listener_state == NES_CM_LISTENER_ACTIVE_STATE) {
++		/* find automatically incs ref count ??? */
++		atomic_dec(&listener->ref_count);
++		nes_debug(NES_DBG_CM, "Not creating listener since it already exists\n");
++		return NULL;
++	}
 +
-+int __initdata init_ohci1394_dma_early;
++	if (!listener) {
++		/* create a CM listen node (1/2 node to compare incoming traffic to) */
++		listener = kzalloc(sizeof(*listener), GFP_ATOMIC);
++		if (!listener) {
++			nes_debug(NES_DBG_CM, "Not creating listener memory allocation failed\n");
++			return NULL;
++		}
 +
-+/* Reads a PHY register of an OHCI-1394 controller */
-+static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
++		memset(listener, 0, sizeof(struct nes_cm_listener));
++		listener->loc_addr = htonl(cm_info->loc_addr);
++		listener->loc_port = htons(cm_info->loc_port);
++		listener->reused_node = 0;
++
++		atomic_set(&listener->ref_count, 1);
++	}
++	/* pasive case */
++	/* find already inc'ed the ref count */
++	else {
++		listener->reused_node = 1;
++	}
++
++	listener->cm_id = cm_info->cm_id;
++	atomic_set(&listener->pend_accepts_cnt, 0);
++	listener->cm_core = cm_core;
++	listener->nesvnic = nesvnic;
++	atomic_inc(&cm_core->node_cnt);
++	atomic_inc(&cm_core->session_id);
++
++	listener->session_id = (u32)(atomic_read(&cm_core->session_id) + current->tgid);
++	listener->conn_type = cm_info->conn_type;
++	listener->backlog = cm_info->backlog;
++	listener->listener_state = NES_CM_LISTENER_ACTIVE_STATE;
++
++	if (!listener->reused_node) {
++		spin_lock_irqsave(&cm_core->listen_list_lock, flags);
++		list_add(&listener->list, &cm_core->listen_list.list);
++		spin_unlock_irqrestore(&cm_core->listen_list_lock, flags);
++		atomic_inc(&cm_core->listen_node_cnt);
++	}
++
++	nes_debug(NES_DBG_CM, "Api - listen(): addr=0x%08X, port=0x%04x,"
++			" listener = %p, backlog = %d, cm_id = %p.\n",
++			cm_info->loc_addr, cm_info->loc_port,
++			listener, listener->backlog, listener->cm_id);
++
++	return listener;
++}
++
++
++/**
++ * mini_cm_connect - make a connection node with params
++ */
++struct nes_cm_node *mini_cm_connect(struct nes_cm_core *cm_core,
++		struct nes_vnic *nesvnic, struct ietf_mpa_frame *mpa_frame,
++		struct nes_cm_info *cm_info)
 +{
-+	int i;
-+	quadlet_t r;
++	int ret = 0;
++	struct nes_cm_node *cm_node;
++	struct nes_cm_listener *loopbackremotelistener;
++	struct nes_cm_node *loopbackremotenode;
++	struct nes_cm_info loopback_cm_info;
++
++	u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) +
++			ntohs(mpa_frame->priv_data_len);
++
++	cm_info->loc_addr = htonl(cm_info->loc_addr);
++	cm_info->rem_addr = htonl(cm_info->rem_addr);
++	cm_info->loc_port = htons(cm_info->loc_port);
++	cm_info->rem_port = htons(cm_info->rem_port);
++
++	/* create a CM connection node */
++	cm_node = make_cm_node(cm_core, nesvnic, cm_info, NULL);
++	if (!cm_node)
++		return NULL;
 +
-+	reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
++	// set our node side to client (active) side
++	cm_node->tcp_cntxt.client = 1;
++	cm_node->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
++
++	if (cm_info->loc_addr == cm_info->rem_addr) {
++		loopbackremotelistener = find_listener(cm_core, cm_node->rem_addr,
++				cm_node->rem_port, NES_CM_LISTENER_ACTIVE_STATE);
++		if (loopbackremotelistener == NULL) {
++			create_event(cm_node, NES_CM_EVENT_ABORTED);
++		} else {
++			atomic_inc(&cm_loopbacks);
++			loopback_cm_info = *cm_info;
++			loopback_cm_info.loc_port = cm_info->rem_port;
++			loopback_cm_info.rem_port = cm_info->loc_port;
++			loopback_cm_info.cm_id = loopbackremotelistener->cm_id;
++			loopbackremotenode = make_cm_node(cm_core, nesvnic, &loopback_cm_info,
++					loopbackremotelistener);
++			loopbackremotenode->loopbackpartner = cm_node;
++			loopbackremotenode->tcp_cntxt.rcv_wscale = NES_CM_DEFAULT_RCV_WND_SCALE;
++			cm_node->loopbackpartner = loopbackremotenode;
++			memcpy(loopbackremotenode->mpa_frame_buf, &mpa_frame->priv_data,
++					mpa_frame_size);
++			loopbackremotenode->mpa_frame_size = mpa_frame_size -
++					sizeof(struct ietf_mpa_frame);
 +
-+	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-+		if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
-+			break;
-+		mdelay(1);
++			// we are done handling this state, set node to a TSA state
++			cm_node->state = NES_CM_STATE_TSA;
++			cm_node->tcp_cntxt.rcv_nxt = loopbackremotenode->tcp_cntxt.loc_seq_num;
++			loopbackremotenode->tcp_cntxt.rcv_nxt = cm_node->tcp_cntxt.loc_seq_num;
++			cm_node->tcp_cntxt.max_snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd;
++			loopbackremotenode->tcp_cntxt.max_snd_wnd = cm_node->tcp_cntxt.rcv_wnd;
++			cm_node->tcp_cntxt.snd_wnd = loopbackremotenode->tcp_cntxt.rcv_wnd;
++			loopbackremotenode->tcp_cntxt.snd_wnd = cm_node->tcp_cntxt.rcv_wnd;
++			cm_node->tcp_cntxt.snd_wscale = loopbackremotenode->tcp_cntxt.rcv_wscale;
++			loopbackremotenode->tcp_cntxt.snd_wscale = cm_node->tcp_cntxt.rcv_wscale;
++
++			create_event(loopbackremotenode, NES_CM_EVENT_MPA_REQ);
++		}
++		return cm_node;
 +	}
-+	r = reg_read(ohci, OHCI1394_PhyControl);
 +
-+	return (r & 0x00ff0000) >> 16;
++	/* set our node side to client (active) side */
++	cm_node->tcp_cntxt.client = 1;
++	/* init our MPA frame ptr */
++	memcpy(&cm_node->mpa_frame, mpa_frame, mpa_frame_size);
++	cm_node->mpa_frame_size = mpa_frame_size;
++
++	/* send a syn and goto syn sent state */
++	cm_node->state = NES_CM_STATE_SYN_SENT;
++	ret = send_syn(cm_node, 0);
++
++	nes_debug(NES_DBG_CM, "Api - connect(): dest addr=0x%08X, port=0x%04x,"
++			" cm_node=%p, cm_id = %p.\n",
++			cm_node->rem_addr, cm_node->rem_port, cm_node, cm_node->cm_id);
++
++	return cm_node;
 +}
 +
-+/* Writes to a PHY register of an OHCI-1394 controller */
-+static inline void __init set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
++
++/**
++ * mini_cm_accept - accept a connection
++ * This function is never called
++ */
++int mini_cm_accept(struct nes_cm_core *cm_core, struct ietf_mpa_frame *mpa_frame,
++		struct nes_cm_node *cm_node)
 +{
-+	int i;
++	return 0;
++}
 +
-+	reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
 +
-+	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-+		u32 r = reg_read(ohci, OHCI1394_PhyControl);
-+		if (!(r & 0x00004000))
-+			break;
-+		mdelay(1);
++/**
++ * mini_cm_reject - reject and teardown a connection
++ */
++int mini_cm_reject(struct nes_cm_core *cm_core,
++		struct ietf_mpa_frame *mpa_frame,
++		struct nes_cm_node *cm_node)
++{
++	int ret = 0;
++	struct sk_buff *skb;
++	u16 mpa_frame_size = sizeof(struct ietf_mpa_frame) +
++			ntohs(mpa_frame->priv_data_len);
++
++	skb = get_free_pkt(cm_node);
++	if (!skb) {
++		nes_debug(NES_DBG_CM, "Failed to get a Free pkt\n");
++		return -1;
++	}
++
++	/* send an MPA Request frame */
++	form_cm_frame(skb, cm_node, NULL, 0, mpa_frame, mpa_frame_size, SET_ACK | SET_FIN);
++	ret = schedule_nes_timer(cm_node, skb, NES_TIMER_TYPE_SEND, 1, 0);
++
++	cm_node->state = NES_CM_STATE_CLOSED;
++	ret = send_fin(cm_node, NULL);
++
++	if (ret < 0) {
++		printk(KERN_INFO PFX "failed to send MPA Reply (reject)\n");
++		return ret;
 +	}
++
++	return ret;
 +}
 +
-+/* Resets an OHCI-1394 controller (for sane state before initialization) */
-+static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
-+	int i;
 +
-+	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
++/**
++ * mini_cm_close
++ */
++int mini_cm_close(struct nes_cm_core *cm_core, struct nes_cm_node *cm_node)
++{
++	int ret = 0;
 +
-+	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-+		if (!(reg_read(ohci, OHCI1394_HCControlSet)
-+				   & OHCI1394_HCControl_softReset))
++	if (!cm_core || !cm_node)
++		return -EINVAL;
++
++	switch (cm_node->state) {
++		/* if passed in node is null, create a reference key node for node search */
++		/* check if we found an owner node for this pkt */
++		case NES_CM_STATE_SYN_RCVD:
++		case NES_CM_STATE_SYN_SENT:
++		case NES_CM_STATE_ONE_SIDE_ESTABLISHED:
++		case NES_CM_STATE_ESTABLISHED:
++		case NES_CM_STATE_ACCEPTING:
++		case NES_CM_STATE_MPAREQ_SENT:
++			cm_node->state = NES_CM_STATE_FIN_WAIT1;
++			send_fin(cm_node, NULL);
++			break;
++		case NES_CM_STATE_CLOSE_WAIT:
++			cm_node->state = NES_CM_STATE_LAST_ACK;
++			send_fin(cm_node, NULL);
++			break;
++		case NES_CM_STATE_FIN_WAIT1:
++		case NES_CM_STATE_FIN_WAIT2:
++		case NES_CM_STATE_LAST_ACK:
++		case NES_CM_STATE_TIME_WAIT:
++		case NES_CM_STATE_CLOSING:
++			ret = -1;
++			break;
++		case NES_CM_STATE_LISTENING:
++		case NES_CM_STATE_UNKNOWN:
++		case NES_CM_STATE_INITED:
++		case NES_CM_STATE_CLOSED:
++		case NES_CM_STATE_TSA:
++			ret = rem_ref_cm_node(cm_core, cm_node);
 +			break;
-+		mdelay(1);
 +	}
++	cm_node->cm_id = NULL;
++	return ret;
 +}
 +
-+/* Basic OHCI-1394 register and port inititalization */
-+static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
++
++/**
++ * recv_pkt - recv an ETHERNET packet, and process it through CM
++ * node state machine
++ */
++int mini_cm_recv_pkt(struct nes_cm_core *cm_core, struct nes_vnic *nesvnic,
++		struct sk_buff *skb)
 +{
-+	quadlet_t bus_options;
-+	int num_ports, i;
++	struct nes_cm_node *cm_node = NULL;
++	struct nes_cm_listener *listener = NULL;
++	struct iphdr *iph;
++	struct tcphdr *tcph;
++	struct nes_cm_info nfo;
++	int ret = 0;
 +
-+	/* Put some defaults to these undefined bus options */
-+	bus_options = reg_read(ohci, OHCI1394_BusOptions);
-+	bus_options |=  0x60000000; /* Enable CMC and ISC */
-+	bus_options &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
-+	bus_options &= ~0x18000000; /* Disable PMC and BMC */
-+	reg_write(ohci, OHCI1394_BusOptions, bus_options);
++	if (!skb || skb->len < sizeof(struct iphdr) + sizeof(struct tcphdr)) {
++		ret = -EINVAL;
++		goto out;
++	}
 +
-+	/* Set the bus number */
-+	reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
++	iph = (struct iphdr *)skb->data;
++	tcph = (struct tcphdr *)(skb->data + sizeof(struct iphdr));
++	skb_reset_network_header(skb);
++	skb_set_transport_header(skb, sizeof(*tcph));
++	skb->len = ntohs(iph->tot_len);
 +
-+	/* Enable posted writes */
-+	reg_write(ohci, OHCI1394_HCControlSet,
-+			OHCI1394_HCControl_postedWriteEnable);
++	nfo.loc_addr = ntohl(iph->daddr);
++	nfo.loc_port = ntohs(tcph->dest);
++	nfo.rem_addr = ntohl(iph->saddr);
++	nfo.rem_port = ntohs(tcph->source);
++
++	nes_debug(NES_DBG_CM, "Received packet: dest=0x%08X:0x%04X src=0x%08X:0x%04X\n",
++			iph->daddr, tcph->dest, iph->saddr, tcph->source);
++
++	/* note: this call is going to increment cm_node ref count */
++	cm_node = find_node(cm_core,
++			nfo.rem_port, nfo.rem_addr,
++			nfo.loc_port, nfo.loc_addr);
++
++	if (!cm_node) {
++		listener = find_listener(cm_core, nfo.loc_addr, nfo.loc_port,
++				NES_CM_LISTENER_ACTIVE_STATE);
++		if (listener) {
++			nfo.cm_id = listener->cm_id;
++			nfo.conn_type = listener->conn_type;
++		} else {
++			nfo.cm_id = NULL;
++			nfo.conn_type = 0;
++		}
 +
-+	/* Clear link control register */
-+	reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
++		cm_node = make_cm_node(cm_core, nesvnic, &nfo, listener);
++		if (!cm_node) {
++			nes_debug(NES_DBG_CM, "Unable to allocate node\n");
++			if (listener) {
++				nes_debug(NES_DBG_CM, "unable to allocate node and decrementing listener refcount\n");
++				atomic_dec(&listener->ref_count);
++			}
++			ret = -1;
++			goto out;
++		}
++		if (!listener) {
++			nes_debug(NES_DBG_CM, "Packet found for unknown port %x refcnt=%d\n",
++					nfo.loc_port, atomic_read(&cm_node->ref_count));
++			if (!tcph->rst) {
++				nes_debug(NES_DBG_CM, "Packet found for unknown port=%d"
++						" rem_port=%d refcnt=%d\n",
++						nfo.loc_port, nfo.rem_port, atomic_read(&cm_node->ref_count));
++
++				cm_node->tcp_cntxt.rcv_nxt = ntohl(tcph->seq);
++				cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->ack_seq);
++				send_reset(cm_node);
++			}
++			rem_ref_cm_node(cm_core, cm_node);
++			ret = -1;
++			goto out;
++		}
++		add_ref_cm_node(cm_node);
++		cm_node->state = NES_CM_STATE_LISTENING;
++	}
 +
-+	/* enable phys */
-+	reg_write(ohci, OHCI1394_LinkControlSet,
-+			OHCI1394_LinkControl_RcvPhyPkt);
++	nes_debug(NES_DBG_CM, "Processing Packet for node %p, data = (%p):\n",
++			cm_node, skb->data);
++	process_packet(cm_node, skb, cm_core);
 +
-+	/* Don't accept phy packets into AR request context */
-+	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
++	rem_ref_cm_node(cm_core, cm_node);
++	out:
++	if (skb)
++		dev_kfree_skb_any(skb);
++	return ret;
++}
 +
-+	/* Clear the Isochonouys interrupt masks */
-+	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-+	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-+	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-+	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
 +
-+	/* Accept asyncronous transfer requests from all nodes for now */
-+	reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
++/**
++ * nes_cm_alloc_core - allocate a top level instance of a cm core
++ */
++struct nes_cm_core *nes_cm_alloc_core(void)
++{
++	int i;
 +
-+	/* Specify asyncronous transfer retries */
-+	reg_write(ohci, OHCI1394_ATRetries,
-+		  OHCI1394_MAX_AT_REQ_RETRIES |
-+		  (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
-+		  (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
++	struct nes_cm_core *cm_core;
++	struct sk_buff *skb = NULL;
 +
-+	/* We don't want hardware swapping */
-+	reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
++	/* setup the CM core */
++	/* alloc top level core control structure */
++	cm_core = kzalloc(sizeof(*cm_core), GFP_KERNEL);
++	if (!cm_core)
++		return NULL;
 +
-+	/* Enable link */
-+	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
++	INIT_LIST_HEAD(&cm_core->connected_nodes);
++	init_timer(&cm_core->tcp_timer);
++	cm_core->tcp_timer.function = nes_cm_timer_tick;
++
++	cm_core->mtu   = NES_CM_DEFAULT_MTU;
++	cm_core->state = NES_CM_STATE_INITED;
++	cm_core->free_tx_pkt_max = NES_CM_DEFAULT_FREE_PKTS;
 +
-+	/* If anything is connected to a port, make sure it is enabled */
-+	num_ports = get_phy_reg(ohci, 2) & 0xf;
-+	for (i = 0; i < num_ports; i++) {
-+		unsigned int status;
++	atomic_set(&cm_core->session_id, 0);
++	atomic_set(&cm_core->events_posted, 0);
 +
-+		set_phy_reg(ohci, 7, i);
-+		status = get_phy_reg(ohci, 8);
++	/* init the packet lists */
++	skb_queue_head_init(&cm_core->tx_free_list);
 +
-+		if (status & 0x20)
-+			set_phy_reg(ohci, 8, status & ~1);
++	for (i = 0; i < NES_CM_DEFAULT_FRAME_CNT; i++) {
++		skb = dev_alloc_skb(cm_core->mtu);
++		if (!skb) {
++			kfree(cm_core);
++			return NULL;
++		}
++		/* add 'raw' skb to free frame list */
++		skb_queue_head(&cm_core->tx_free_list, skb);
 +	}
++
++	cm_core->api = &nes_cm_api;
++
++	spin_lock_init(&cm_core->ht_lock);
++	spin_lock_init(&cm_core->listen_list_lock);
++
++	INIT_LIST_HEAD(&cm_core->listen_list.list);
++
++	nes_debug(NES_DBG_CM, "Init CM Core completed -- cm_core=%p\n", cm_core);
++
++	nes_debug(NES_DBG_CM, "Enable QUEUE EVENTS\n");
++	cm_core->event_wq = create_singlethread_workqueue("nesewq");
++	cm_core->post_event = nes_cm_post_event;
++	nes_debug(NES_DBG_CM, "Enable QUEUE DISCONNECTS\n");
++	cm_core->disconn_wq = create_singlethread_workqueue("nesdwq");
++
++	print_core(cm_core);
++	return cm_core;
 +}
 +
++
 +/**
-+ * init_ohci1394_wait_for_busresets - wait until bus resets are completed
-+ *
-+ * OHCI1394 initialization itself and any device going on- or offline
-+ * and any cable issue cause a IEEE1394 bus reset. The OHCI1394 spec
-+ * specifies that physical DMA is disabled on each bus reset and it
-+ * has to be enabled after each bus reset when needed. We resort
-+ * to polling here because on early boot, we have no interrupts.
++ * mini_cm_dealloc_core - deallocate a top level instance of a cm core
 + */
-+static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
++int mini_cm_dealloc_core(struct nes_cm_core *cm_core)
 +{
-+	int i, events;
++	nes_debug(NES_DBG_CM, "De-Alloc CM Core (%p)\n", cm_core);
 +
-+	for (i=0; i < 9; i++) {
-+		mdelay(200);
-+		events = reg_read(ohci, OHCI1394_IntEventSet);
-+		if (events & OHCI1394_busReset)
-+			reg_write(ohci, OHCI1394_IntEventClear,
-+					OHCI1394_busReset);
++	if (!cm_core)
++		return -EINVAL;
++
++	barrier();
++
++	if (timer_pending(&cm_core->tcp_timer)) {
++		del_timer(&cm_core->tcp_timer);
 +	}
++
++	destroy_workqueue(cm_core->event_wq);
++	destroy_workqueue(cm_core->disconn_wq);
++	nes_debug(NES_DBG_CM, "\n");
++	kfree(cm_core);
++
++	return 0;
 +}
 +
++
 +/**
-+ * init_ohci1394_enable_physical_dma - Enable physical DMA for remote debugging
-+ * This enables remote DMA access over IEEE1394 from every host for the low
-+ * 4GB of address space. DMA accesses above 4GB are not available currently.
++ * mini_cm_get
 + */
-+static inline void __init init_ohci1394_enable_physical_dma(struct ti_ohci *hci)
++int mini_cm_get(struct nes_cm_core *cm_core)
 +{
-+	reg_write(hci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
-+	reg_write(hci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
-+	reg_write(hci, OHCI1394_PhyUpperBound, 0xffff0000);
++	return cm_core->state;
 +}
 +
++
 +/**
-+ * init_ohci1394_reset_and_init_dma - init controller and enable DMA
-+ * This initializes the given controller and enables physical DMA engine in it.
++ * mini_cm_set
 + */
-+static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
++int mini_cm_set(struct nes_cm_core *cm_core, u32 type, u32 value)
 +{
-+	/* Start off with a soft reset, clears everything to a sane state. */
-+	init_ohci1394_soft_reset(ohci);
++	int ret = 0;
 +
-+	/* Accessing some registers without LPS enabled may cause lock up */
-+	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
++	switch (type) {
++		case NES_CM_SET_PKT_SIZE:
++			cm_core->mtu = value;
++			break;
++		case NES_CM_SET_FREE_PKT_Q_SIZE:
++			cm_core->free_tx_pkt_max = value;
++			break;
++		default:
++			/* unknown set option */
++			ret = -EINVAL;
++	}
 +
-+	/* Disable and clear interrupts */
-+	reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-+	reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
++	return ret;
++}
 +
-+	mdelay(50); /* Wait 50msec to make sure we have full link enabled */
 +
-+	init_ohci1394_initialize(ohci);
-+	/*
-+	 * The initialization causes at least one IEEE1394 bus reset. Enabling
-+	 * physical DMA only works *after* *all* bus resets have calmed down:
-+	 */
-+	init_ohci1394_wait_for_busresets(ohci);
++/**
++ * nes_cm_init_tsa_conn setup HW; MPA frames must be
++ * successfully exchanged when this is called
++ */
++static int nes_cm_init_tsa_conn(struct nes_qp *nesqp, struct nes_cm_node *cm_node)
++{
++	int ret = 0;
 +
-+	/* We had to wait and do this now if we want to debug early problems */
-+	init_ohci1394_enable_physical_dma(ohci);
++	if (!nesqp)
++		return -EINVAL;
++
++	nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_IPV4 |
++			NES_QPCONTEXT_MISC_NO_NAGLE | NES_QPCONTEXT_MISC_DO_NOT_FRAG |
++			NES_QPCONTEXT_MISC_DROS);
++
++	if (cm_node->tcp_cntxt.snd_wscale || cm_node->tcp_cntxt.rcv_wscale)
++		nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WSCALE);
++
++	nesqp->nesqp_context->misc2 |= cpu_to_le32(64 << NES_QPCONTEXT_MISC2_TTL_SHIFT);
++
++	nesqp->nesqp_context->mss |= cpu_to_le32(((u32)cm_node->tcp_cntxt.mss) << 16);
++
++	nesqp->nesqp_context->tcp_state_flow_label |= cpu_to_le32(
++			(u32)NES_QPCONTEXT_TCPSTATE_EST << NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT);
++
++	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
++			(cm_node->tcp_cntxt.snd_wscale << NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT) &
++			NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK);
++
++	nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32(
++			(cm_node->tcp_cntxt.rcv_wscale << NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT) &
++			NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK);
++
++	nesqp->nesqp_context->keepalive = cpu_to_le32(0x80);
++	nesqp->nesqp_context->ts_recent = 0;
++	nesqp->nesqp_context->ts_age = 0;
++	nesqp->nesqp_context->snd_nxt = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
++	nesqp->nesqp_context->snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.snd_wnd);
++	nesqp->nesqp_context->rcv_nxt = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
++	nesqp->nesqp_context->rcv_wnd = cpu_to_le32(cm_node->tcp_cntxt.rcv_wnd <<
++			cm_node->tcp_cntxt.rcv_wscale);
++	nesqp->nesqp_context->snd_max = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
++	nesqp->nesqp_context->snd_una = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
++	nesqp->nesqp_context->srtt = 0;
++	nesqp->nesqp_context->rttvar = cpu_to_le32(0x6);
++	nesqp->nesqp_context->ssthresh = cpu_to_le32(0x3FFFC000);
++	nesqp->nesqp_context->cwnd = cpu_to_le32(2*cm_node->tcp_cntxt.mss);
++	nesqp->nesqp_context->snd_wl1 = cpu_to_le32(cm_node->tcp_cntxt.rcv_nxt);
++	nesqp->nesqp_context->snd_wl2 = cpu_to_le32(cm_node->tcp_cntxt.loc_seq_num);
++	nesqp->nesqp_context->max_snd_wnd = cpu_to_le32(cm_node->tcp_cntxt.max_snd_wnd);
++
++	nes_debug(NES_DBG_CM, "QP%u: rcv_nxt = 0x%08X, snd_nxt = 0x%08X,"
++			" Setting MSS to %u, PDWscale = 0x%08X, rcv_wnd = %u, context misc = 0x%08X.\n",
++			nesqp->hwqp.qp_id, le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
++			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
++			cm_node->tcp_cntxt.mss, le32_to_cpu(nesqp->nesqp_context->pd_index_wscale),
++			le32_to_cpu(nesqp->nesqp_context->rcv_wnd),
++			le32_to_cpu(nesqp->nesqp_context->misc));
++	nes_debug(NES_DBG_CM, "  snd_wnd  = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->snd_wnd));
++	nes_debug(NES_DBG_CM, "  snd_cwnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->cwnd));
++	nes_debug(NES_DBG_CM, "  max_swnd = 0x%08X.\n", le32_to_cpu(nesqp->nesqp_context->max_snd_wnd));
++
++	nes_debug(NES_DBG_CM, "Change cm_node state to TSA\n");
++	cm_node->state = NES_CM_STATE_TSA;
++
++	return ret;
 +}
 +
++
 +/**
-+ * init_ohci1394_controller - Map the registers of the controller and init DMA
-+ * This maps the registers of the specified controller and initializes it
++ * nes_cm_disconn
 + */
-+static inline void __init init_ohci1394_controller(int num, int slot, int func)
++int nes_cm_disconn(struct nes_qp *nesqp)
 +{
-+	unsigned long ohci_base;
-+	struct ti_ohci ohci;
++	unsigned long flags;
 +
-+	printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
-+			 " at %02x:%02x.%x\n", num, slot, func);
++	spin_lock_irqsave(&nesqp->lock, flags);
++	if (nesqp->disconn_pending == 0) {
++		nesqp->disconn_pending++;
++		spin_unlock_irqrestore(&nesqp->lock, flags);
++		/* nes_add_ref(&nesqp->ibqp); */
++		/* init our disconnect work element, to */
++		INIT_WORK(&nesqp->disconn_work, nes_disconnect_worker);
 +
-+	ohci_base = read_pci_config(num, slot, func, PCI_BASE_ADDRESS_0+(0<<2))
-+						   & PCI_BASE_ADDRESS_MEM_MASK;
++		queue_work(g_cm_core->disconn_wq, &nesqp->disconn_work);
++	} else {
++		spin_unlock_irqrestore(&nesqp->lock, flags);
++		nes_rem_ref(&nesqp->ibqp);
++	}
 +
-+	set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
++	return 0;
++}
 +
-+	ohci.registers = (void *)fix_to_virt(FIX_OHCI1394_BASE);
 +
-+	init_ohci1394_reset_and_init_dma(&ohci);
++/**
++ * nes_disconnect_worker
++ */
++void nes_disconnect_worker(struct work_struct *work)
++{
++	struct nes_qp *nesqp = container_of(work, struct nes_qp, disconn_work);
++
++	nes_debug(NES_DBG_CM, "processing AEQE id 0x%04X for QP%u.\n",
++			nesqp->last_aeq, nesqp->hwqp.qp_id);
++	nes_cm_disconn_true(nesqp);
 +}
 +
++
 +/**
-+ * debug_init_ohci1394_dma - scan for OHCI1394 controllers and init DMA on them
-+ * Scans the whole PCI space for OHCI1394 controllers and inits DMA on them
++ * nes_cm_disconn_true
 + */
-+void __init init_ohci1394_dma_on_all_controllers(void)
++int nes_cm_disconn_true(struct nes_qp *nesqp)
 +{
-+	int num, slot, func;
++	unsigned long flags;
++	int ret = 0;
++	struct iw_cm_id *cm_id;
++	struct iw_cm_event cm_event;
++	struct nes_vnic *nesvnic;
++	u16 last_ae;
++	u8 original_hw_tcp_state;
++	u8 original_ibqp_state;
++	u8 issued_disconnect_reset = 0;
 +
-+	if (!early_pci_allowed())
-+		return;
++	if (!nesqp) {
++		nes_debug(NES_DBG_CM, "disconnect_worker nesqp is NULL\n");
++		return -1;
++	}
 +
-+	/* Poor man's PCI discovery, the only thing we can do at early boot */
-+	for (num = 0; num < 32; num++) {
-+		for (slot = 0; slot < 32; slot++) {
-+			for (func = 0; func < 8; func++) {
-+				u32 class = read_pci_config(num,slot,func,
-+							PCI_CLASS_REVISION);
-+				if ((class == 0xffffffff))
-+					continue; /* No device at this func */
++	spin_lock_irqsave(&nesqp->lock, flags);
++	cm_id = nesqp->cm_id;
++	/* make sure we havent already closed this connection */
++	if (!cm_id) {
++		nes_debug(NES_DBG_CM, "QP%u disconnect_worker cmid is NULL\n",
++				nesqp->hwqp.qp_id);
++		spin_unlock_irqrestore(&nesqp->lock, flags);
++		nes_rem_ref(&nesqp->ibqp);
++		return -1;
++	}
 +
-+				if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
-+					continue; /* Not an OHCI-1394 device */
++	nesvnic = to_nesvnic(nesqp->ibqp.device);
++	nes_debug(NES_DBG_CM, "Disconnecting QP%u\n", nesqp->hwqp.qp_id);
 +
-+				init_ohci1394_controller(num, slot, func);
-+				break; /* Assume one controller per device */
++	original_hw_tcp_state = nesqp->hw_tcp_state;
++	original_ibqp_state   = nesqp->ibqp_state;
++	last_ae = nesqp->last_aeq;
++
++
++	nes_debug(NES_DBG_CM, "set ibqp_state=%u\n", nesqp->ibqp_state);
++
++	if ((nesqp->cm_id) && (cm_id->event_handler)) {
++		if ((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
++				((original_ibqp_state == IB_QPS_RTS) &&
++				(last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
++			atomic_inc(&cm_disconnects);
++			cm_event.event = IW_CM_EVENT_DISCONNECT;
++			if (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET) {
++				issued_disconnect_reset = 1;
++				cm_event.status = IW_CM_EVENT_STATUS_RESET;
++				nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event (status reset) for "
++						" QP%u, cm_id = %p. \n",
++						nesqp->hwqp.qp_id, cm_id);
++			} else {
++				cm_event.status = IW_CM_EVENT_STATUS_OK;
++			}
++
++			cm_event.local_addr = cm_id->local_addr;
++			cm_event.remote_addr = cm_id->remote_addr;
++			cm_event.private_data = NULL;
++			cm_event.private_data_len = 0;
++
++			nes_debug(NES_DBG_CM, "Generating a CM Disconnect Event for "
++					" QP%u, SQ Head = %u, SQ Tail = %u. cm_id = %p, refcount = %u.\n",
++					nesqp->hwqp.qp_id,
++					nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail, cm_id,
++					atomic_read(&nesqp->refcount));
++
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			ret = cm_id->event_handler(cm_id, &cm_event);
++			if (ret)
++				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
++			spin_lock_irqsave(&nesqp->lock, flags);
++		}
++
++		nesqp->disconn_pending = 0;
++		/* There might have been another AE while the lock was released */
++		original_hw_tcp_state = nesqp->hw_tcp_state;
++		original_ibqp_state   = nesqp->ibqp_state;
++		last_ae = nesqp->last_aeq;
++
++		if ((issued_disconnect_reset == 0) && (nesqp->cm_id) &&
++				((original_hw_tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
++				 (original_hw_tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT) ||
++				 (last_ae == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) ||
++				 (last_ae == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
++			atomic_inc(&cm_closes);
++			nesqp->cm_id = NULL;
++			nesqp->in_disconnect = 0;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_disconnect(nesqp, 1);
++
++			cm_id->provider_data = nesqp;
++			/* Send up the close complete event */
++			cm_event.event = IW_CM_EVENT_CLOSE;
++			cm_event.status = IW_CM_EVENT_STATUS_OK;
++			cm_event.provider_data = cm_id->provider_data;
++			cm_event.local_addr = cm_id->local_addr;
++			cm_event.remote_addr = cm_id->remote_addr;
++			cm_event.private_data = NULL;
++			cm_event.private_data_len = 0;
++
++			ret = cm_id->event_handler(cm_id, &cm_event);
++			if (ret) {
++				nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
++			}
++
++			cm_id->rem_ref(cm_id);
++
++			spin_lock_irqsave(&nesqp->lock, flags);
++			if (nesqp->flush_issued == 0) {
++				nesqp->flush_issued = 1;
++				spin_unlock_irqrestore(&nesqp->lock, flags);
++				flush_wqes(nesvnic->nesdev, nesqp, NES_CQP_FLUSH_RQ, 1);
++			} else {
++				spin_unlock_irqrestore(&nesqp->lock, flags);
++			}
++
++			/* This reference is from either ModifyQP or the AE processing,
++					there is still a race here with modifyqp */
++			nes_rem_ref(&nesqp->ibqp);
++
++		} else {
++			cm_id = nesqp->cm_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			/* check to see if the inbound reset beat the outbound reset */
++			if ((!cm_id) && (last_ae==NES_AEQE_AEID_RESET_SENT)) {
++				nes_debug(NES_DBG_CM, "QP%u: Decing refcount due to inbound reset"
++						" beating the outbound reset.\n",
++						nesqp->hwqp.qp_id);
++				nes_rem_ref(&nesqp->ibqp);
 +			}
 +		}
++	} else {
++		nesqp->disconn_pending = 0;
++		spin_unlock_irqrestore(&nesqp->lock, flags);
 +	}
-+	printk(KERN_INFO "init_ohci1394_dma: finished initializing OHCI DMA\n");
++	nes_rem_ref(&nesqp->ibqp);
++
++	return 0;
 +}
 +
++
 +/**
-+ * setup_init_ohci1394_early - enables early OHCI1394 DMA initialization
++ * nes_disconnect
 + */
-+static int __init setup_ohci1394_dma(char *opt)
++int nes_disconnect(struct nes_qp *nesqp, int abrupt)
 +{
-+	if (!strcmp(opt, "early"))
-+		init_ohci1394_dma_early = 1;
-+	return 0;
++	int ret = 0;
++	struct nes_vnic *nesvnic;
++	struct nes_device *nesdev;
++
++	nesvnic = to_nesvnic(nesqp->ibqp.device);
++	if (!nesvnic)
++		return -EINVAL;
++
++	nesdev = nesvnic->nesdev;
++
++	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
++			atomic_read(&nesvnic->netdev->refcnt));
++
++	if (nesqp->active_conn) {
++
++		/* indicate this connection is NOT active */
++		nesqp->active_conn = 0;
++	} else {
++		/* Need to free the Last Streaming Mode Message */
++		if (nesqp->ietf_frame) {
++			pci_free_consistent(nesdev->pcidev,
++					nesqp->private_data_len+sizeof(struct ietf_mpa_frame),
++					nesqp->ietf_frame, nesqp->ietf_frame_pbase);
++		}
++	}
++
++	/* close the CM node down if it is still active */
++	if (nesqp->cm_node) {
++		nes_debug(NES_DBG_CM, "Call close API\n");
++
++		g_cm_core->api->close(g_cm_core, nesqp->cm_node);
++		nesqp->cm_node = NULL;
++	}
++
++	return ret;
 +}
 +
-+/* passing ohci1394_dma=early on boot causes early OHCI1394 DMA initialization */
-+early_param("ohci1394_dma", setup_ohci1394_dma);
-diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
-index 90dc75b..511e432 100644
---- a/drivers/ieee1394/nodemgr.c
-+++ b/drivers/ieee1394/nodemgr.c
-@@ -727,33 +727,31 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
- 
- static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
- 
-+static int __match_ne(struct device *dev, void *data)
++
++/**
++ * nes_accept
++ */
++int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 +{
-+	struct unit_directory *ud;
-+	struct node_entry *ne = (struct node_entry *)data;
++	u64 u64temp;
++	struct ib_qp *ibqp;
++	struct nes_qp *nesqp;
++	struct nes_vnic *nesvnic;
++	struct nes_device *nesdev;
++	struct nes_cm_node *cm_node;
++	struct nes_adapter *adapter;
++	struct ib_qp_attr attr;
++	struct iw_cm_event cm_event;
++	struct nes_hw_qp_wqe *wqe;
++	struct nes_v4_quad nes_quad;
++	int ret;
 +
-+	ud = container_of(dev, struct unit_directory, unit_dev);
-+	return ud->ne == ne;
++	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
++	if (!ibqp)
++		return -EINVAL;
++
++	/* get all our handles */
++	nesqp = to_nesqp(ibqp);
++	nesvnic = to_nesvnic(nesqp->ibqp.device);
++	nesdev = nesvnic->nesdev;
++	adapter = nesdev->nesadapter;
++
++	nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n",
++			nesvnic, nesvnic->netdev, nesvnic->netdev->name);
++
++	/* since this is from a listen, we were able to put node handle into cm_id */
++	cm_node = (struct nes_cm_node *)cm_id->provider_data;
++
++	/* associate the node with the QP */
++	nesqp->cm_node = (void *)cm_node;
++
++	nes_debug(NES_DBG_CM, "QP%u, cm_node=%p, jiffies = %lu\n",
++			nesqp->hwqp.qp_id, cm_node, jiffies);
++	atomic_inc(&cm_accepts);
++
++	nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n",
++			atomic_read(&nesvnic->netdev->refcnt));
++
++		/* allocate the ietf frame and space for private data */
++		nesqp->ietf_frame = pci_alloc_consistent(nesdev->pcidev,
++				sizeof(struct ietf_mpa_frame) + conn_param->private_data_len,
++				&nesqp->ietf_frame_pbase);
++
++		if (!nesqp->ietf_frame) {
++			nes_debug(NES_DBG_CM, "Unable to allocate memory for private data\n");
++			return -ENOMEM;
++		}
++
++
++		/* setup the MPA frame */
++		nesqp->private_data_len = conn_param->private_data_len;
++		memcpy(nesqp->ietf_frame->key, IEFT_MPA_KEY_REP, IETF_MPA_KEY_SIZE);
++
++		memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
++				conn_param->private_data_len);
++
++		nesqp->ietf_frame->priv_data_len = cpu_to_be16(conn_param->private_data_len);
++		nesqp->ietf_frame->rev = mpa_version;
++		nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
++
++		/* setup our first outgoing iWarp send WQE (the IETF frame response) */
++		wqe = &nesqp->hwqp.sq_vbase[0];
++
++		if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) {
++			u64temp = (unsigned long)nesqp;
++			u64temp |= NES_SW_CONTEXT_ALIGN>>1;
++			set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
++					    u64temp);
++			wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] =
++					cpu_to_le32(NES_IWARP_SQ_WQE_STREAMING | NES_IWARP_SQ_WQE_WRPDU);
++			wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] =
++					cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame));
++			wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] =
++					cpu_to_le32((u32)nesqp->ietf_frame_pbase);
++			wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] =
++					cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32));
++			wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] =
++					cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame));
++			wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
++
++			nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(
++					NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | NES_QPCONTEXT_ORDIRD_WRPDU);
++		} else {
++			nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
++					NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM));
++		}
++		nesqp->skip_lsmm = 1;
++
++
++	/* Cache the cm_id in the qp */
++	nesqp->cm_id = cm_id;
++	cm_node->cm_id = cm_id;
++
++	/*  nesqp->cm_node = (void *)cm_id->provider_data; */
++	cm_id->provider_data = nesqp;
++	nesqp->active_conn   = 0;
++
++	nes_cm_init_tsa_conn(nesqp, cm_node);
++
++	nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
++	nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
++	nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
++
++	nesqp->nesqp_context->misc2 |= cpu_to_le32(
++			(u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
++
++	nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32(
++			nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0), NULL,
++			NES_ARP_RESOLVE) << 16);
++
++	nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
++			jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
++
++	nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id);
++
++	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(
++			((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT));
++	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
++
++	memset(&nes_quad, 0, sizeof(nes_quad));
++	nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
++	nes_quad.SrcIpadr      = cm_id->remote_addr.sin_addr.s_addr;
++	nes_quad.TcpPorts[0]   = cm_id->remote_addr.sin_port;
++	nes_quad.TcpPorts[1]   = cm_id->local_addr.sin_port;
++
++	/* Produce hash key */
++	nesqp->hte_index = cpu_to_be32(
++			crc32c(~0, (void *)&nes_quad, sizeof(nes_quad)) ^ 0xffffffff);
++	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, CRC = 0x%08X\n",
++			nesqp->hte_index, nesqp->hte_index & adapter->hte_index_mask);
++
++	nesqp->hte_index &= adapter->hte_index_mask;
++	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
++
++	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
++
++	nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X,"
++			" rcv_nxt=0x%08X, snd_nxt=0x%08X, mpa + private data length=%zu.\n",
++			nesqp->hwqp.qp_id,
++			ntohl(cm_id->remote_addr.sin_addr.s_addr),
++			ntohs(cm_id->remote_addr.sin_port),
++			ntohl(cm_id->local_addr.sin_addr.s_addr),
++			ntohs(cm_id->local_addr.sin_port),
++			le32_to_cpu(nesqp->nesqp_context->rcv_nxt),
++			le32_to_cpu(nesqp->nesqp_context->snd_nxt),
++			conn_param->private_data_len+sizeof(struct ietf_mpa_frame));
++
++	attr.qp_state = IB_QPS_RTS;
++	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
++
++	/* notify OF layer that accept event was successfull */
++	cm_id->add_ref(cm_id);
++
++	cm_event.event = IW_CM_EVENT_ESTABLISHED;
++	cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
++	cm_event.provider_data = (void *)nesqp;
++	cm_event.local_addr = cm_id->local_addr;
++	cm_event.remote_addr = cm_id->remote_addr;
++	cm_event.private_data = NULL;
++	cm_event.private_data_len = 0;
++	ret = cm_id->event_handler(cm_id, &cm_event);
++	if (cm_node->loopbackpartner) {
++		cm_node->loopbackpartner->mpa_frame_size = nesqp->private_data_len;
++		/* copy entire MPA frame to our cm_node's frame */
++		memcpy(cm_node->loopbackpartner->mpa_frame_buf, nesqp->ietf_frame->priv_data,
++			   nesqp->private_data_len);
++		create_event(cm_node->loopbackpartner, NES_CM_EVENT_CONNECTED);
++	}
++	if (ret)
++		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
++				__FUNCTION__, __LINE__, ret);
++
++	return 0;
 +}
 +
- static void nodemgr_remove_uds(struct node_entry *ne)
- {
- 	struct device *dev;
--	struct unit_directory *tmp, *ud;
--
--	/* Iteration over nodemgr_ud_class.devices has to be protected by
--	 * nodemgr_ud_class.sem, but device_unregister() will eventually
--	 * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time,
--	 * release the semaphore, and then unregister the ud. Since this code
--	 * may be called from other contexts besides the knodemgrds, protect the
--	 * gap after release of the semaphore by nodemgr_serialize_remove_uds.
-+	struct unit_directory *ud;
 +
-+	/* Use class_find device to iterate the devices. Since this code
-+	 * may be called from other contexts besides the knodemgrds,
-+	 * protect it by nodemgr_serialize_remove_uds.
- 	 */
- 	mutex_lock(&nodemgr_serialize_remove_uds);
- 	for (;;) {
--		ud = NULL;
--		down(&nodemgr_ud_class.sem);
--		list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
--			tmp = container_of(dev, struct unit_directory,
--					   unit_dev);
--			if (tmp->ne == ne) {
--				ud = tmp;
--				break;
--			}
--		}
--		up(&nodemgr_ud_class.sem);
--		if (ud == NULL)
-+		dev = class_find_device(&nodemgr_ud_class, ne, __match_ne);
-+		if (!dev)
- 			break;
-+		ud = container_of(dev, struct unit_directory, unit_dev);
-+		put_device(dev);
- 		device_unregister(&ud->unit_dev);
- 		device_unregister(&ud->device);
- 	}
-@@ -882,45 +880,66 @@ fail_alloc:
- 	return NULL;
- }
- 
-+static int __match_ne_guid(struct device *dev, void *data)
++/**
++ * nes_reject
++ */
++int nes_reject(struct iw_cm_id *cm_id, const void *pdata, u8 pdata_len)
 +{
-+	struct node_entry *ne;
-+	u64 *guid = (u64 *)data;
++	struct nes_cm_node *cm_node;
++	struct nes_cm_core *cm_core;
 +
-+	ne = container_of(dev, struct node_entry, node_dev);
-+	return ne->guid == *guid;
++	atomic_inc(&cm_rejects);
++	cm_node = (struct nes_cm_node *) cm_id->provider_data;
++	cm_core = cm_node->cm_core;
++	cm_node->mpa_frame_size = sizeof(struct ietf_mpa_frame) + pdata_len;
++
++	strcpy(&cm_node->mpa_frame.key[0], IEFT_MPA_KEY_REP);
++	memcpy(&cm_node->mpa_frame.priv_data, pdata, pdata_len);
++
++	cm_node->mpa_frame.priv_data_len = cpu_to_be16(pdata_len);
++	cm_node->mpa_frame.rev = mpa_version;
++	cm_node->mpa_frame.flags = IETF_MPA_FLAGS_CRC | IETF_MPA_FLAGS_REJECT;
++
++	cm_core->api->reject(cm_core, &cm_node->mpa_frame, cm_node);
++
++	return 0;
 +}
- 
- static struct node_entry *find_entry_by_guid(u64 guid)
- {
- 	struct device *dev;
--	struct node_entry *ne, *ret_ne = NULL;
--
--	down(&nodemgr_ne_class.sem);
--	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
--		ne = container_of(dev, struct node_entry, node_dev);
-+	struct node_entry *ne;
- 
--		if (ne->guid == guid) {
--			ret_ne = ne;
--			break;
--		}
--	}
--	up(&nodemgr_ne_class.sem);
-+	dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid);
-+	if (!dev)
-+		return NULL;
-+	ne = container_of(dev, struct node_entry, node_dev);
-+	put_device(dev);
- 
--	return ret_ne;
-+	return ne;
- }
- 
-+struct match_nodeid_param {
-+	struct hpsb_host *host;
-+	nodeid_t nodeid;
-+};
 +
-+static int __match_ne_nodeid(struct device *dev, void *data)
++
++/**
++ * nes_connect
++ * setup and launch cm connect node
++ */
++int nes_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
 +{
-+	int found = 0;
-+	struct node_entry *ne;
-+	struct match_nodeid_param *param = (struct match_nodeid_param *)data;
++	struct ib_qp *ibqp;
++	struct nes_qp *nesqp;
++	struct nes_vnic *nesvnic;
++	struct nes_device *nesdev;
++	struct nes_cm_node *cm_node;
++	struct nes_cm_info cm_info;
 +
-+	if (!dev)
-+		goto ret;
-+	ne = container_of(dev, struct node_entry, node_dev);
-+	if (ne->host == param->host && ne->nodeid == param->nodeid)
-+		found = 1;
-+ret:
-+	return found;
++	ibqp = nes_get_qp(cm_id->device, conn_param->qpn);
++	if (!ibqp)
++		return -EINVAL;
++	nesqp = to_nesqp(ibqp);
++	if (!nesqp)
++		return -EINVAL;
++	nesvnic = to_nesvnic(nesqp->ibqp.device);
++	if (!nesvnic)
++		return -EINVAL;
++	nesdev  = nesvnic->nesdev;
++	if (!nesdev)
++		return -EINVAL;
++
++	atomic_inc(&cm_connects);
++
++	nesqp->ietf_frame = kzalloc(sizeof(struct ietf_mpa_frame) +
++			conn_param->private_data_len, GFP_KERNEL);
++	if (!nesqp->ietf_frame)
++		return -ENOMEM;
++
++	/* set qp as having an active connection */
++	nesqp->active_conn = 1;
++
++	nes_debug(NES_DBG_CM, "QP%u, Destination IP = 0x%08X:0x%04X, local = 0x%08X:0x%04X.\n",
++			nesqp->hwqp.qp_id,
++			ntohl(cm_id->remote_addr.sin_addr.s_addr),
++			ntohs(cm_id->remote_addr.sin_port),
++			ntohl(cm_id->local_addr.sin_addr.s_addr),
++			ntohs(cm_id->local_addr.sin_port));
++
++	/* cache the cm_id in the qp */
++	nesqp->cm_id = cm_id;
++
++	cm_id->provider_data = nesqp;
++
++	/* copy the private data */
++	if (conn_param->private_data_len) {
++		memcpy(nesqp->ietf_frame->priv_data, conn_param->private_data,
++				conn_param->private_data_len);
++	}
++
++	nesqp->private_data_len = conn_param->private_data_len;
++	nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32((u32)conn_param->ord);
++	nes_debug(NES_DBG_CM, "requested ord = 0x%08X.\n", (u32)conn_param->ord);
++	nes_debug(NES_DBG_CM, "mpa private data len =%u\n", conn_param->private_data_len);
++
++	strcpy(&nesqp->ietf_frame->key[0], IEFT_MPA_KEY_REQ);
++	nesqp->ietf_frame->flags = IETF_MPA_FLAGS_CRC;
++	nesqp->ietf_frame->rev = IETF_MPA_VERSION;
++	nesqp->ietf_frame->priv_data_len = htons(conn_param->private_data_len);
++
++	if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr)
++		nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
++				PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
++
++	/* set up the connection params for the node */
++	cm_info.loc_addr = (cm_id->local_addr.sin_addr.s_addr);
++	cm_info.loc_port = (cm_id->local_addr.sin_port);
++	cm_info.rem_addr = (cm_id->remote_addr.sin_addr.s_addr);
++	cm_info.rem_port = (cm_id->remote_addr.sin_port);
++	cm_info.cm_id = cm_id;
++	cm_info.conn_type = NES_CM_IWARP_CONN_TYPE;
++
++	cm_id->add_ref(cm_id);
++	nes_add_ref(&nesqp->ibqp);
++
++	/* create a connect CM node connection */
++	cm_node = g_cm_core->api->connect(g_cm_core, nesvnic, nesqp->ietf_frame, &cm_info);
++	if (!cm_node) {
++		if (cm_id->local_addr.sin_addr.s_addr != cm_id->remote_addr.sin_addr.s_addr)
++			nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
++					PCI_FUNC(nesdev->pcidev->devfn), NES_MANAGE_APBVT_DEL);
++		nes_rem_ref(&nesqp->ibqp);
++		kfree(nesqp->ietf_frame);
++		nesqp->ietf_frame = NULL;
++		cm_id->rem_ref(cm_id);
++		return -ENOMEM;
++	}
++
++	cm_node->apbvt_set = 1;
++	nesqp->cm_node = cm_node;
++
++	return 0;
 +}
- 
- static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
- 					       nodeid_t nodeid)
- {
- 	struct device *dev;
--	struct node_entry *ne, *ret_ne = NULL;
-+	struct node_entry *ne;
-+	struct match_nodeid_param param;
- 
--	down(&nodemgr_ne_class.sem);
--	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
--		ne = container_of(dev, struct node_entry, node_dev);
-+	param.host = host;
-+	param.nodeid = nodeid;
- 
--		if (ne->host == host && ne->nodeid == nodeid) {
--			ret_ne = ne;
--			break;
--		}
--	}
--	up(&nodemgr_ne_class.sem);
-+	dev = class_find_device(&nodemgr_ne_class, &param, __match_ne_nodeid);
-+	if (!dev)
-+		return NULL;
-+	ne = container_of(dev, struct node_entry, node_dev);
-+	put_device(dev);
- 
--	return ret_ne;
-+	return ne;
- }
- 
- 
-@@ -1370,107 +1389,109 @@ static void nodemgr_node_scan(struct host_info *hi, int generation)
- 	}
- }
- 
--
--static void nodemgr_suspend_ne(struct node_entry *ne)
-+static int __nodemgr_driver_suspend(struct device *dev, void *data)
- {
--	struct device *dev;
- 	struct unit_directory *ud;
- 	struct device_driver *drv;
-+	struct node_entry *ne = (struct node_entry *)data;
- 	int error;
- 
--	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
--		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-+	ud = container_of(dev, struct unit_directory, unit_dev);
-+	if (ud->ne == ne) {
-+		drv = get_driver(ud->device.driver);
-+		if (drv) {
-+			error = 1; /* release if suspend is not implemented */
-+			if (drv->suspend) {
-+				down(&ud->device.sem);
-+				error = drv->suspend(&ud->device, PMSG_SUSPEND);
-+				up(&ud->device.sem);
-+			}
-+			if (error)
-+				device_release_driver(&ud->device);
-+			put_driver(drv);
++
++
++/**
++ * nes_create_listen
++ */
++int nes_create_listen(struct iw_cm_id *cm_id, int backlog)
++{
++	struct nes_vnic *nesvnic;
++	struct nes_cm_listener *cm_node;
++	struct nes_cm_info cm_info;
++	struct nes_adapter *adapter;
++	int err;
++
++
++	nes_debug(NES_DBG_CM, "cm_id = %p, local port = 0x%04X.\n",
++			cm_id, ntohs(cm_id->local_addr.sin_port));
++
++	nesvnic = to_nesvnic(cm_id->device);
++	if (!nesvnic)
++		return -EINVAL;
++	adapter = nesvnic->nesdev->nesadapter;
++	nes_debug(NES_DBG_CM, "nesvnic=%p, netdev=%p, %s\n",
++			nesvnic, nesvnic->netdev, nesvnic->netdev->name);
++
++	nes_debug(NES_DBG_CM, "nesvnic->local_ipaddr=0x%08x, sin_addr.s_addr=0x%08x\n",
++			nesvnic->local_ipaddr, cm_id->local_addr.sin_addr.s_addr);
++
++	/* setup listen params in our api call struct */
++	cm_info.loc_addr = nesvnic->local_ipaddr;
++	cm_info.loc_port = cm_id->local_addr.sin_port;
++	cm_info.backlog = backlog;
++	cm_info.cm_id = cm_id;
++
++	cm_info.conn_type = NES_CM_IWARP_CONN_TYPE;
++
++
++	cm_node = g_cm_core->api->listen(g_cm_core, nesvnic, &cm_info);
++	if (!cm_node) {
++		printk("%s[%u] Error returned from listen API call\n",
++				__FUNCTION__, __LINE__);
++		return -ENOMEM;
++	}
++
++	cm_id->provider_data = cm_node;
++
++	if (!cm_node->reused_node) {
++		err = nes_manage_apbvt(nesvnic, ntohs(cm_id->local_addr.sin_port),
++				PCI_FUNC(nesvnic->nesdev->pcidev->devfn), NES_MANAGE_APBVT_ADD);
++		if (err) {
++			printk("nes_manage_apbvt call returned %d.\n", err);
++			g_cm_core->api->stop_listener(g_cm_core, (void *)cm_node);
++			return err;
 +		}
++		cm_listens_created++;
 +	}
- 
--	ne->in_limbo = 1;
--	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
++
++	cm_id->add_ref(cm_id);
++	cm_id->provider_data = (void *)cm_node;
++
++
 +	return 0;
 +}
- 
--	down(&nodemgr_ud_class.sem);
--	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
--		ud = container_of(dev, struct unit_directory, unit_dev);
--		if (ud->ne != ne)
--			continue;
-+static int __nodemgr_driver_resume(struct device *dev, void *data)
++
++
++/**
++ * nes_destroy_listen
++ */
++int nes_destroy_listen(struct iw_cm_id *cm_id)
 +{
-+	struct unit_directory *ud;
-+	struct device_driver *drv;
-+	struct node_entry *ne = (struct node_entry *)data;
- 
-+	ud = container_of(dev, struct unit_directory, unit_dev);
-+	if (ud->ne == ne) {
- 		drv = get_driver(ud->device.driver);
--		if (!drv)
--			continue;
--
--		error = 1; /* release if suspend is not implemented */
--		if (drv->suspend) {
--			down(&ud->device.sem);
--			error = drv->suspend(&ud->device, PMSG_SUSPEND);
--			up(&ud->device.sem);
-+		if (drv) {
-+			if (drv->resume) {
-+				down(&ud->device.sem);
-+				drv->resume(&ud->device);
-+				up(&ud->device.sem);
-+			}
-+			put_driver(drv);
- 		}
--		if (error)
--			device_release_driver(&ud->device);
--		put_driver(drv);
- 	}
--	up(&nodemgr_ud_class.sem);
--}
- 
++	if (cm_id->provider_data)
++		g_cm_core->api->stop_listener(g_cm_core, cm_id->provider_data);
++	else
++		nes_debug(NES_DBG_CM, "cm_id->provider_data was NULL\n");
++
++	cm_id->rem_ref(cm_id);
++
 +	return 0;
 +}
- 
--static void nodemgr_resume_ne(struct node_entry *ne)
-+static void nodemgr_suspend_ne(struct node_entry *ne)
- {
--	struct device *dev;
--	struct unit_directory *ud;
--	struct device_driver *drv;
-+	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-+		   NODE_BUS_ARGS(ne->host, ne->nodeid),
-+		   (unsigned long long)ne->guid);
- 
--	ne->in_limbo = 0;
--	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
-+	ne->in_limbo = 1;
-+	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
- 
--	down(&nodemgr_ud_class.sem);
--	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
--		ud = container_of(dev, struct unit_directory, unit_dev);
--		if (ud->ne != ne)
--			continue;
-+	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend);
++
++
++/**
++ * nes_cm_recv
++ */
++int nes_cm_recv(struct sk_buff *skb, struct net_device *netdevice)
++{
++	cm_packets_received++;
++	if ((g_cm_core) && (g_cm_core->api)) {
++		g_cm_core->api->recv_pkt(g_cm_core, netdev_priv(netdevice), skb);
++	} else {
++		nes_debug(NES_DBG_CM, "Unable to process packet for CM,"
++				" cm is not setup properly.\n");
++	}
++
++	return 0;
 +}
- 
--		drv = get_driver(ud->device.driver);
--		if (!drv)
--			continue;
- 
--		if (drv->resume) {
--			down(&ud->device.sem);
--			drv->resume(&ud->device);
--			up(&ud->device.sem);
--		}
--		put_driver(drv);
--	}
--	up(&nodemgr_ud_class.sem);
-+static void nodemgr_resume_ne(struct node_entry *ne)
++
++
++/**
++ * nes_cm_start
++ * Start and init a cm core module
++ */
++int nes_cm_start(void)
 +{
-+	ne->in_limbo = 0;
-+	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
- 
-+	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume);
- 	HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
- 		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
- }
- 
--
--static void nodemgr_update_pdrv(struct node_entry *ne)
-+static int __nodemgr_update_pdrv(struct device *dev, void *data)
- {
--	struct device *dev;
- 	struct unit_directory *ud;
- 	struct device_driver *drv;
- 	struct hpsb_protocol_driver *pdrv;
-+	struct node_entry *ne = (struct node_entry *)data;
- 	int error;
- 
--	down(&nodemgr_ud_class.sem);
--	list_for_each_entry(dev, &nodemgr_ud_class.devices, node) {
--		ud = container_of(dev, struct unit_directory, unit_dev);
--		if (ud->ne != ne)
--			continue;
--
-+	ud = container_of(dev, struct unit_directory, unit_dev);
-+	if (ud->ne == ne) {
- 		drv = get_driver(ud->device.driver);
--		if (!drv)
--			continue;
--
--		error = 0;
--		pdrv = container_of(drv, struct hpsb_protocol_driver, driver);
--		if (pdrv->update) {
--			down(&ud->device.sem);
--			error = pdrv->update(ud);
--			up(&ud->device.sem);
-+		if (drv) {
-+			error = 0;
-+			pdrv = container_of(drv, struct hpsb_protocol_driver,
-+					    driver);
-+			if (pdrv->update) {
-+				down(&ud->device.sem);
-+				error = pdrv->update(ud);
-+				up(&ud->device.sem);
-+			}
-+			if (error)
-+				device_release_driver(&ud->device);
-+			put_driver(drv);
- 		}
--		if (error)
--			device_release_driver(&ud->device);
--		put_driver(drv);
- 	}
--	up(&nodemgr_ud_class.sem);
++	nes_debug(NES_DBG_CM, "\n");
++	/* create the primary CM core, pass this handle to subsequent core inits */
++	g_cm_core = nes_cm_alloc_core();
++	if (g_cm_core) {
++		return 0;
++	} else {
++		return -ENOMEM;
++	}
++}
 +
++
++/**
++ * nes_cm_stop
++ * stop and dealloc all cm core instances
++ */
++int nes_cm_stop(void)
++{
++	g_cm_core->api->destroy_cm_core(g_cm_core);
 +	return 0;
 +}
 +
-+static void nodemgr_update_pdrv(struct node_entry *ne)
++
++/**
++ * cm_event_connected
++ * handle a connected event, setup QPs and HW
++ */
++void cm_event_connected(struct nes_cm_event *event)
 +{
-+	class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv);
- }
- 
- 
-@@ -1529,13 +1550,31 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
- 	put_device(dev);
- }
- 
-+struct probe_param {
-+	struct host_info *hi;
-+	int generation;
-+};
++	u64 u64temp;
++	struct nes_qp *nesqp;
++	struct nes_vnic *nesvnic;
++	struct nes_device *nesdev;
++	struct nes_cm_node *cm_node;
++	struct nes_adapter *nesadapter;
++	struct ib_qp_attr attr;
++	struct iw_cm_id *cm_id;
++	struct iw_cm_event cm_event;
++	struct nes_hw_qp_wqe *wqe;
++	struct nes_v4_quad nes_quad;
++	int ret;
 +
-+static int __nodemgr_node_probe(struct device *dev, void *data)
++	/* get all our handles */
++	cm_node = event->cm_node;
++	cm_id = cm_node->cm_id;
++	nes_debug(NES_DBG_CM, "cm_event_connected - %p - cm_id = %p\n", cm_node, cm_id);
++	nesqp = (struct nes_qp *)cm_id->provider_data;
++	nesvnic = to_nesvnic(nesqp->ibqp.device);
++	nesdev = nesvnic->nesdev;
++	nesadapter = nesdev->nesadapter;
++
++	if (nesqp->destroyed) {
++		return;
++	}
++	atomic_inc(&cm_connecteds);
++	nes_debug(NES_DBG_CM, "QP%u attempting to connect to  0x%08X:0x%04X on"
++			" local port 0x%04X. jiffies = %lu.\n",
++			nesqp->hwqp.qp_id,
++			ntohl(cm_id->remote_addr.sin_addr.s_addr),
++			ntohs(cm_id->remote_addr.sin_port),
++			ntohs(cm_id->local_addr.sin_port),
++			jiffies);
++
++	nes_cm_init_tsa_conn(nesqp, cm_node);
++
++	/* set the QP tsa context */
++	nesqp->nesqp_context->tcpPorts[0] = cpu_to_le16(ntohs(cm_id->local_addr.sin_port));
++	nesqp->nesqp_context->tcpPorts[1] = cpu_to_le16(ntohs(cm_id->remote_addr.sin_port));
++	nesqp->nesqp_context->ip0 = cpu_to_le32(ntohl(cm_id->remote_addr.sin_addr.s_addr));
++
++	nesqp->nesqp_context->misc2 |= cpu_to_le32(
++			(u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_QPCONTEXT_MISC2_SRC_IP_SHIFT);
++	nesqp->nesqp_context->arp_index_vlan |= cpu_to_le32(
++			nes_arp_table(nesdev, le32_to_cpu(nesqp->nesqp_context->ip0),
++			NULL, NES_ARP_RESOLVE) << 16);
++	nesqp->nesqp_context->ts_val_delta = cpu_to_le32(
++			jiffies - nes_read_indexed(nesdev, NES_IDX_TCP_NOW));
++	nesqp->nesqp_context->ird_index = cpu_to_le32(nesqp->hwqp.qp_id);
++	nesqp->nesqp_context->ird_ord_sizes |=
++			cpu_to_le32((u32)1 << NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT);
++
++	/* Adjust tail for not having a LSMM */
++	nesqp->hwqp.sq_tail = 1;
++
++#if defined(NES_SEND_FIRST_WRITE)
++		if (cm_node->send_write0) {
++			nes_debug(NES_DBG_CM, "Sending first write.\n");
++			wqe = &nesqp->hwqp.sq_vbase[0];
++			u64temp = (unsigned long)nesqp;
++			u64temp |= NES_SW_CONTEXT_ALIGN>>1;
++			set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX,
++					    u64temp);
++			wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(NES_IWARP_SQ_OP_RDMAW);
++			wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = 0;
++			wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = 0;
++			wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = 0;
++			wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = 0;
++			wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0;
++
++			/* use the reserved spot on the WQ for the extra first WQE */
++			nesqp->nesqp_context->ird_ord_sizes &= cpu_to_le32(~(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT |
++					NES_QPCONTEXT_ORDIRD_WRPDU | NES_QPCONTEXT_ORDIRD_ALSMM));
++			nesqp->skip_lsmm = 1;
++			nesqp->hwqp.sq_tail = 0;
++			nes_write32(nesdev->regs + NES_WQE_ALLOC,
++					(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
++		}
++#endif
++
++	memset(&nes_quad, 0, sizeof(nes_quad));
++
++	nes_quad.DstIpAdrIndex = cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) << 24);
++	nes_quad.SrcIpadr = cm_id->remote_addr.sin_addr.s_addr;
++	nes_quad.TcpPorts[0] = cm_id->remote_addr.sin_port;
++	nes_quad.TcpPorts[1] = cm_id->local_addr.sin_port;
++
++	/* Produce hash key */
++	nesqp->hte_index = cpu_to_be32(
++			crc32c(~0, (void *)&nes_quad, sizeof(nes_quad)) ^ 0xffffffff);
++	nes_debug(NES_DBG_CM, "HTE Index = 0x%08X, After CRC = 0x%08X\n",
++			nesqp->hte_index, nesqp->hte_index & nesadapter->hte_index_mask);
++
++	nesqp->hte_index &= nesadapter->hte_index_mask;
++	nesqp->nesqp_context->hte_index = cpu_to_le32(nesqp->hte_index);
++
++	nesqp->ietf_frame = &cm_node->mpa_frame;
++	nesqp->private_data_len = (u8) cm_node->mpa_frame_size;
++	cm_node->cm_core->api->accelerated(cm_node->cm_core, cm_node);
++
++	/* modify QP state to rts */
++	attr.qp_state = IB_QPS_RTS;
++	nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
++
++	/* notify OF layer we successfully created the requested connection */
++	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
++	cm_event.status = IW_CM_EVENT_STATUS_ACCEPTED;
++	cm_event.provider_data = cm_id->provider_data;
++	cm_event.local_addr.sin_family = AF_INET;
++	cm_event.local_addr.sin_port = cm_id->local_addr.sin_port;
++	cm_event.remote_addr = cm_id->remote_addr;
++
++		cm_event.private_data = (void *)event->cm_node->mpa_frame_buf;
++		cm_event.private_data_len = (u8) event->cm_node->mpa_frame_size;
++
++	cm_event.local_addr.sin_addr.s_addr = event->cm_info.rem_addr;
++	ret = cm_id->event_handler(cm_id, &cm_event);
++	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
++
++	if (ret)
++		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
++				__FUNCTION__, __LINE__, ret);
++	nes_debug(NES_DBG_CM, "Exiting connect thread for QP%u. jiffies = %lu\n",
++			nesqp->hwqp.qp_id, jiffies );
++
++	nes_rem_ref(&nesqp->ibqp);
++
++	return;
++}
++
++
++/**
++ * cm_event_connect_error
++ */
++void cm_event_connect_error(struct nes_cm_event *event)
 +{
-+	struct probe_param *param = (struct probe_param *)data;
-+	struct node_entry *ne;
++	struct nes_qp *nesqp;
++	struct iw_cm_id *cm_id;
++	struct iw_cm_event cm_event;
++	/* struct nes_cm_info cm_info; */
++	int ret;
 +
-+	ne = container_of(dev, struct node_entry, node_dev);
-+	if (!ne->needs_probe)
-+		nodemgr_probe_ne(param->hi, ne, param->generation);
-+	if (ne->needs_probe)
-+		nodemgr_probe_ne(param->hi, ne, param->generation);
++	if (!event->cm_node)
++		return;
++
++	cm_id = event->cm_node->cm_id;
++	if (!cm_id) {
++		return;
++	}
++
++	nes_debug(NES_DBG_CM, "cm_node=%p, cm_id=%p\n", event->cm_node, cm_id);
++	nesqp = cm_id->provider_data;
++
++	if (!nesqp) {
++		return;
++	}
++
++	/* notify OF layer about this connection error event */
++	/* cm_id->rem_ref(cm_id); */
++	nesqp->cm_id = NULL;
++	cm_id->provider_data = NULL;
++	cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
++	cm_event.status = IW_CM_EVENT_STATUS_REJECTED;
++	cm_event.provider_data = cm_id->provider_data;
++	cm_event.local_addr = cm_id->local_addr;
++	cm_event.remote_addr = cm_id->remote_addr;
++	cm_event.private_data = NULL;
++	cm_event.private_data_len = 0;
++
++	nes_debug(NES_DBG_CM, "call CM_EVENT REJECTED, local_addr=%08x, remove_addr=%08x\n",
++			cm_event.local_addr.sin_addr.s_addr, cm_event.remote_addr.sin_addr.s_addr);
++
++	ret = cm_id->event_handler(cm_id, &cm_event);
++	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
++	if (ret)
++		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
++				__FUNCTION__, __LINE__, ret);
++	nes_rem_ref(&nesqp->ibqp);
++		cm_id->rem_ref(cm_id);
++
++	return;
++}
++
++
++/**
++ * cm_event_reset
++ */
++void cm_event_reset(struct nes_cm_event *event)
++{
++	struct nes_qp *nesqp;
++	struct iw_cm_id *cm_id;
++	struct iw_cm_event cm_event;
++	/* struct nes_cm_info cm_info; */
++	int ret;
++
++	if (!event->cm_node)
++		return;
++
++	if (!event->cm_node->cm_id)
++		return;
++
++	cm_id = event->cm_node->cm_id;
++
++	nes_debug(NES_DBG_CM, "%p - cm_id = %p\n", event->cm_node, cm_id);
++	nesqp = cm_id->provider_data;
++
++	nesqp->cm_id = NULL;
++	/* cm_id->provider_data = NULL; */
++	cm_event.event = IW_CM_EVENT_DISCONNECT;
++	cm_event.status = IW_CM_EVENT_STATUS_RESET;
++	cm_event.provider_data = cm_id->provider_data;
++	cm_event.local_addr = cm_id->local_addr;
++	cm_event.remote_addr = cm_id->remote_addr;
++	cm_event.private_data = NULL;
++	cm_event.private_data_len = 0;
++
++	ret = cm_id->event_handler(cm_id, &cm_event);
++	nes_debug(NES_DBG_CM, "OFA CM event_handler returned, ret=%d\n", ret);
++
++
++	/* notify OF layer about this connection error event */
++	cm_id->rem_ref(cm_id);
++
++	return;
++}
++
++
++/**
++ * cm_event_mpa_req
++ */
++void cm_event_mpa_req(struct nes_cm_event *event)
++{
++	struct iw_cm_id   *cm_id;
++	struct iw_cm_event cm_event;
++	int ret;
++	struct nes_cm_node *cm_node;
++
++	cm_node = event->cm_node;
++	if (!cm_node)
++		return;
++	cm_id = cm_node->cm_id;
++
++	atomic_inc(&cm_connect_reqs);
++	nes_debug(NES_DBG_CM, "cm_node = %p - cm_id = %p, jiffies = %lu\n",
++			cm_node, cm_id, jiffies);
++
++	cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;
++	cm_event.status = IW_CM_EVENT_STATUS_OK;
++	cm_event.provider_data = (void *)cm_node;
++
++	cm_event.local_addr.sin_family = AF_INET;
++	cm_event.local_addr.sin_port = htons(event->cm_info.loc_port);
++	cm_event.local_addr.sin_addr.s_addr = htonl(event->cm_info.loc_addr);
++
++	cm_event.remote_addr.sin_family = AF_INET;
++	cm_event.remote_addr.sin_port = htons(event->cm_info.rem_port);
++	cm_event.remote_addr.sin_addr.s_addr = htonl(event->cm_info.rem_addr);
++
++		cm_event.private_data                = cm_node->mpa_frame_buf;
++		cm_event.private_data_len            = (u8) cm_node->mpa_frame_size;
++
++	ret = cm_id->event_handler(cm_id, &cm_event);
++	if (ret)
++		printk("%s[%u] OFA CM event_handler returned, ret=%d\n",
++				__FUNCTION__, __LINE__, ret);
++
++	return;
++}
++
++
++static void nes_cm_event_handler(struct work_struct *);
++
++/**
++ * nes_cm_post_event
++ * post an event to the cm event handler
++ */
++int nes_cm_post_event(struct nes_cm_event *event)
++{
++	atomic_inc(&event->cm_node->cm_core->events_posted);
++	add_ref_cm_node(event->cm_node);
++	event->cm_info.cm_id->add_ref(event->cm_info.cm_id);
++	INIT_WORK(&event->event_work, nes_cm_event_handler);
++	nes_debug(NES_DBG_CM, "queue_work, event=%p\n", event);
++
++	queue_work(event->cm_node->cm_core->event_wq, &event->event_work);
++
++	nes_debug(NES_DBG_CM, "Exit\n");
 +	return 0;
 +}
- 
- static void nodemgr_node_probe(struct host_info *hi, int generation)
- {
- 	struct hpsb_host *host = hi->host;
--	struct device *dev;
--	struct node_entry *ne;
-+	struct probe_param param;
- 
-+	param.hi = hi;
-+	param.generation = generation;
- 	/* Do some processing of the nodes we've probed. This pulls them
- 	 * into the sysfs layer if needed, and can result in processing of
- 	 * unit-directories, or just updating the node and it's
-@@ -1545,19 +1584,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
- 	 * while probes are time-consuming. (Well, those probes need some
- 	 * improvement...) */
- 
--	down(&nodemgr_ne_class.sem);
--	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
--		ne = container_of(dev, struct node_entry, node_dev);
--		if (!ne->needs_probe)
--			nodemgr_probe_ne(hi, ne, generation);
--	}
--	list_for_each_entry(dev, &nodemgr_ne_class.devices, node) {
--		ne = container_of(dev, struct node_entry, node_dev);
--		if (ne->needs_probe)
--			nodemgr_probe_ne(hi, ne, generation);
--	}
--	up(&nodemgr_ne_class.sem);
--
-+	class_for_each_device(&nodemgr_ne_class, &param, __nodemgr_node_probe);
- 
- 	/* If we had a bus reset while we were scanning the bus, it is
- 	 * possible that we did not probe all nodes.  In that case, we
-@@ -1757,6 +1784,22 @@ exit:
- 	return 0;
- }
- 
-+struct host_iter_param {
-+	void *data;
-+	int (*cb)(struct hpsb_host *, void *);
-+};
 +
-+static int __nodemgr_for_each_host(struct device *dev, void *data)
++
++/**
++ * nes_cm_event_handler
++ * worker function to handle cm events
++ * will free instance of nes_cm_event
++ */
++static void nes_cm_event_handler(struct work_struct *work)
 +{
-+	struct hpsb_host *host;
-+	struct host_iter_param *hip = (struct host_iter_param *)data;
-+	int error = 0;
++	struct nes_cm_event *event = container_of(work, struct nes_cm_event, event_work);
++	struct nes_cm_core *cm_core;
 +
-+	host = container_of(dev, struct hpsb_host, host_dev);
-+	error = hip->cb(host, hip->data);
++	if ((!event) || (!event->cm_node) || (!event->cm_node->cm_core)) {
++		return;
++	}
++	cm_core = event->cm_node->cm_core;
++	nes_debug(NES_DBG_CM, "event=%p, event->type=%u, events posted=%u\n",
++			event, event->type, atomic_read(&cm_core->events_posted));
 +
-+	return error;
++	switch (event->type) {
++		case NES_CM_EVENT_MPA_REQ:
++			cm_event_mpa_req(event);
++			nes_debug(NES_DBG_CM, "CM Event: MPA REQUEST\n");
++			break;
++		case NES_CM_EVENT_RESET:
++			nes_debug(NES_DBG_CM, "CM Event: RESET\n");
++			cm_event_reset(event);
++			break;
++		case NES_CM_EVENT_CONNECTED:
++			if ((!event->cm_node->cm_id) ||
++				(event->cm_node->state != NES_CM_STATE_TSA)) {
++				break;
++			}
++			cm_event_connected(event);
++			nes_debug(NES_DBG_CM, "CM Event: CONNECTED\n");
++			break;
++		case NES_CM_EVENT_ABORTED:
++			if ((!event->cm_node->cm_id) || (event->cm_node->state == NES_CM_STATE_TSA)) {
++				break;
++			}
++			cm_event_connect_error(event);
++			nes_debug(NES_DBG_CM, "CM Event: ABORTED\n");
++			break;
++		case NES_CM_EVENT_DROPPED_PKT:
++			nes_debug(NES_DBG_CM, "CM Event: DROPPED PKT\n");
++			break;
++		default:
++			nes_debug(NES_DBG_CM, "CM Event: UNKNOWN EVENT TYPE\n");
++			break;
++	}
++
++	atomic_dec(&cm_core->events_posted);
++	event->cm_info.cm_id->rem_ref(event->cm_info.cm_id);
++	rem_ref_cm_node(cm_core, event->cm_node);
++	kfree(event);
++
++	return;
 +}
- /**
-  * nodemgr_for_each_host - call a function for each IEEE 1394 host
-  * @data: an address to supply to the callback
-@@ -1771,18 +1814,13 @@ exit:
-  */
- int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
- {
--	struct device *dev;
--	struct hpsb_host *host;
--	int error = 0;
--
--	down(&hpsb_host_class.sem);
--	list_for_each_entry(dev, &hpsb_host_class.devices, node) {
--		host = container_of(dev, struct hpsb_host, host_dev);
-+	struct host_iter_param hip;
-+	int error;
- 
--		if ((error = cb(host, data)))
--			break;
--	}
--	up(&hpsb_host_class.sem);
-+	hip.cb = cb;
-+	hip.data = data;
-+	error = class_for_each_device(&hpsb_host_class, &hip,
-+				      __nodemgr_for_each_host);
- 
- 	return error;
- }
-diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
-index 372c5c1..969de2a 100644
---- a/drivers/ieee1394/ohci1394.c
-+++ b/drivers/ieee1394/ohci1394.c
-@@ -2126,10 +2126,14 @@ static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
- 	list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
- 		mask = 1 << t->context;
- 
--		if (t->type == OHCI_ISO_TRANSMIT && tx_event & mask)
--			tasklet_schedule(&t->tasklet);
--		else if (rx_event & mask)
--			tasklet_schedule(&t->tasklet);
-+		if (t->type == OHCI_ISO_TRANSMIT) {
-+			if (tx_event & mask)
-+				tasklet_schedule(&t->tasklet);
-+		} else {
-+			/* OHCI_ISO_RECEIVE or OHCI_ISO_MULTICHANNEL_RECEIVE */
-+			if (rx_event & mask)
-+				tasklet_schedule(&t->tasklet);
-+		}
- 	}
- 
- 	spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
-index cadf047..37e7e10 100644
---- a/drivers/ieee1394/raw1394.c
-+++ b/drivers/ieee1394/raw1394.c
-@@ -858,7 +858,7 @@ static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
- 	int found = 0, size = 0, rcode = -1;
- 	struct arm_request_response *arm_req_resp = NULL;
- 
--	DBGMSG("arm_read  called by node: %X"
-+	DBGMSG("arm_read  called by node: %X "
- 	       "addr: %4.4x %8.8x length: %Zu", nodeid,
- 	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- 	       length);
-@@ -1012,7 +1012,7 @@ static int arm_write(struct hpsb_host *host, int nodeid, int destid,
- 	int found = 0, size = 0, rcode = -1, length_conflict = 0;
- 	struct arm_request_response *arm_req_resp = NULL;
- 
--	DBGMSG("arm_write called by node: %X"
-+	DBGMSG("arm_write called by node: %X "
- 	       "addr: %4.4x %8.8x length: %Zu", nodeid,
- 	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
- 	       length);
-diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
-index b83d254..28e155a 100644
---- a/drivers/ieee1394/sbp2.c
-+++ b/drivers/ieee1394/sbp2.c
-@@ -51,6 +51,7 @@
-  * Grep for inline FIXME comments below.
-  */
- 
-+#include <linux/blkdev.h>
- #include <linux/compiler.h>
- #include <linux/delay.h>
- #include <linux/device.h>
-@@ -127,17 +128,21 @@ MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
- 		 "(default = Y, faster but buggy = N)");
- 
- /*
-- * Bump up max_sectors if you'd like to support very large sized
-- * transfers. Please note that some older sbp2 bridge chips are broken for
-- * transfers greater or equal to 128KB.  Default is a value of 255
-- * sectors, or just under 128KB (at 512 byte sector size). I can note that
-- * the Oxsemi sbp2 chipsets have no problems supporting very large
-- * transfer sizes.
-+ * Adjust max_sectors if you'd like to influence how many sectors each SCSI
-+ * command can transfer at most. Please note that some older SBP-2 bridge
-+ * chips are broken for transfers greater or equal to 128KB, therefore
-+ * max_sectors used to be a safe 255 sectors for many years. We now have a
-+ * default of 0 here which means that we let the SCSI stack choose a limit.
+diff --git a/drivers/infiniband/hw/nes/nes_cm.h b/drivers/infiniband/hw/nes/nes_cm.h
+new file mode 100644
+index 0000000..a59f0a7
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_cm.h
+@@ -0,0 +1,433 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
 + *
-+ * The SBP2_WORKAROUND_128K_MAX_TRANS flag, if set either in the workarounds
-+ * module parameter or in the sbp2_workarounds_table[], will override the
-+ * value of max_sectors. We should use sbp2_workarounds_table[] to cover any
-+ * bridge chip which becomes known to need the 255 sectors limit.
-  */
--static int sbp2_max_sectors = SBP2_MAX_SECTORS;
-+static int sbp2_max_sectors;
- module_param_named(max_sectors, sbp2_max_sectors, int, 0444);
- MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
--		 "(default = " __stringify(SBP2_MAX_SECTORS) ")");
-+		 "(default = 0 = use SCSI stack's default)");
- 
- /*
-  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
-@@ -1451,7 +1456,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
- 				     struct sbp2_fwhost_info *hi,
- 				     struct sbp2_command_info *cmd,
- 				     unsigned int scsi_use_sg,
--				     struct scatterlist *sgpnt,
-+				     struct scatterlist *sg,
- 				     u32 orb_direction,
- 				     enum dma_data_direction dma_dir)
- {
-@@ -1460,13 +1465,12 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
- 	orb->misc |= ORB_SET_DIRECTION(orb_direction);
- 
- 	/* special case if only one element (and less than 64KB in size) */
--	if ((scsi_use_sg == 1) &&
--	    (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) {
-+	if (scsi_use_sg == 1 && sg->length <= SBP2_MAX_SG_ELEMENT_LENGTH) {
- 
--		cmd->dma_size = sgpnt[0].length;
-+		cmd->dma_size = sg->length;
- 		cmd->dma_type = CMD_DMA_PAGE;
- 		cmd->cmd_dma = dma_map_page(hi->host->device.parent,
--					    sg_page(&sgpnt[0]), sgpnt[0].offset,
-+					    sg_page(sg), sg->offset,
- 					    cmd->dma_size, cmd->dma_dir);
- 
- 		orb->data_descriptor_lo = cmd->cmd_dma;
-@@ -1477,11 +1481,11 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
- 						&cmd->scatter_gather_element[0];
- 		u32 sg_count, sg_len;
- 		dma_addr_t sg_addr;
--		int i, count = dma_map_sg(hi->host->device.parent, sgpnt,
-+		int i, count = dma_map_sg(hi->host->device.parent, sg,
- 					  scsi_use_sg, dma_dir);
- 
- 		cmd->dma_size = scsi_use_sg;
--		cmd->sge_buffer = sgpnt;
-+		cmd->sge_buffer = sg;
- 
- 		/* use page tables (s/g) */
- 		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1);
-@@ -1489,9 +1493,9 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
- 
- 		/* loop through and fill out our SBP-2 page tables
- 		 * (and split up anything too large) */
--		for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) {
--			sg_len = sg_dma_len(sgpnt);
--			sg_addr = sg_dma_address(sgpnt);
-+		for (i = 0, sg_count = 0; i < count; i++, sg = sg_next(sg)) {
-+			sg_len = sg_dma_len(sg);
-+			sg_addr = sg_dma_address(sg);
- 			while (sg_len) {
- 				sg_element[sg_count].segment_base_lo = sg_addr;
- 				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) {
-@@ -1521,11 +1525,10 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
- 				    unchar *scsi_cmd,
- 				    unsigned int scsi_use_sg,
- 				    unsigned int scsi_request_bufflen,
--				    void *scsi_request_buffer,
-+				    struct scatterlist *sg,
- 				    enum dma_data_direction dma_dir)
- {
- 	struct sbp2_fwhost_info *hi = lu->hi;
--	struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer;
- 	struct sbp2_command_orb *orb = &cmd->command_orb;
- 	u32 orb_direction;
- 
-@@ -1560,7 +1563,7 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
- 		orb->data_descriptor_lo = 0x0;
- 		orb->misc |= ORB_SET_DIRECTION(1);
- 	} else
--		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sgpnt,
-+		sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sg,
- 					 orb_direction, dma_dir);
- 
- 	sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
-@@ -1650,7 +1653,6 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
- 			     void (*done)(struct scsi_cmnd *))
- {
- 	unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
--	unsigned int request_bufflen = scsi_bufflen(SCpnt);
- 	struct sbp2_command_info *cmd;
- 
- 	cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
-@@ -1658,7 +1660,7 @@ static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
- 		return -EIO;
- 
- 	sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
--				request_bufflen, scsi_sglist(SCpnt),
-+				scsi_bufflen(SCpnt), scsi_sglist(SCpnt),
- 				SCpnt->sc_data_direction);
- 	sbp2_link_orb_command(lu, cmd);
- 
-@@ -1963,6 +1965,12 @@ static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
- 	lu->sdev = sdev;
- 	sdev->allow_restart = 1;
- 
-+	/*
-+	 * Update the dma alignment (minimum alignment requirements for
-+	 * start and end of DMA transfers) to be a sector
-+	 */
-+	blk_queue_update_dma_alignment(sdev->request_queue, 511);
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
 +
- 	if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
- 		sdev->inquiry_len = 36;
- 	return 0;
-@@ -1981,6 +1989,8 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
- 		sdev->skip_ms_page_8 = 1;
- 	if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
- 		sdev->fix_capacity = 1;
-+	if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
-+		blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
- 	return 0;
- }
- 
-@@ -2087,9 +2097,6 @@ static int sbp2_module_init(void)
- 		sbp2_shost_template.cmd_per_lun = 1;
- 	}
- 
--	if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
--	    (sbp2_max_sectors * 512) > (128 * 1024))
--		sbp2_max_sectors = 128 * 1024 / 512;
- 	sbp2_shost_template.max_sectors = sbp2_max_sectors;
- 
- 	hpsb_register_highlevel(&sbp2_highlevel);
-diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
-index 333a4bb..d2ecb0d 100644
---- a/drivers/ieee1394/sbp2.h
-+++ b/drivers/ieee1394/sbp2.h
-@@ -222,7 +222,6 @@ struct sbp2_status_block {
-  */
- 
- #define SBP2_MAX_SG_ELEMENT_LENGTH		0xf000
--#define SBP2_MAX_SECTORS			255
- /* There is no real limitation of the queue depth (i.e. length of the linked
-  * list of command ORBs) at the target. The chosen depth is merely an
-  * implementation detail of the sbp2 driver. */
-diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
-index 5381c80..a58ad8a 100644
---- a/drivers/infiniband/core/addr.c
-+++ b/drivers/infiniband/core/addr.c
-@@ -110,7 +110,7 @@ int rdma_translate_ip(struct sockaddr *addr, struct rdma_dev_addr *dev_addr)
- 	__be32 ip = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
- 	int ret;
- 
--	dev = ip_dev_find(ip);
-+	dev = ip_dev_find(&init_net, ip);
- 	if (!dev)
- 		return -EADDRNOTAVAIL;
- 
-@@ -158,7 +158,7 @@ static void addr_send_arp(struct sockaddr_in *dst_in)
- 
- 	memset(&fl, 0, sizeof fl);
- 	fl.nl_u.ip4_u.daddr = dst_ip;
--	if (ip_route_output_key(&rt, &fl))
-+	if (ip_route_output_key(&init_net, &rt, &fl))
- 		return;
- 
- 	neigh_event_send(rt->u.dst.neighbour, NULL);
-@@ -179,7 +179,7 @@ static int addr_resolve_remote(struct sockaddr_in *src_in,
- 	memset(&fl, 0, sizeof fl);
- 	fl.nl_u.ip4_u.daddr = dst_ip;
- 	fl.nl_u.ip4_u.saddr = src_ip;
--	ret = ip_route_output_key(&rt, &fl);
-+	ret = ip_route_output_key(&init_net, &rt, &fl);
- 	if (ret)
- 		goto out;
- 
-@@ -261,15 +261,15 @@ static int addr_resolve_local(struct sockaddr_in *src_in,
- 	__be32 dst_ip = dst_in->sin_addr.s_addr;
- 	int ret;
- 
--	dev = ip_dev_find(dst_ip);
-+	dev = ip_dev_find(&init_net, dst_ip);
- 	if (!dev)
- 		return -EADDRNOTAVAIL;
- 
--	if (ZERONET(src_ip)) {
-+	if (ipv4_is_zeronet(src_ip)) {
- 		src_in->sin_family = dst_in->sin_family;
- 		src_in->sin_addr.s_addr = dst_ip;
- 		ret = rdma_copy_addr(addr, dev, dev->dev_addr);
--	} else if (LOOPBACK(src_ip)) {
-+	} else if (ipv4_is_loopback(src_ip)) {
- 		ret = rdma_translate_ip((struct sockaddr *)dst_in, addr);
- 		if (!ret)
- 			memcpy(addr->dst_dev_addr, dev->dev_addr, MAX_ADDR_LEN);
-diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
-index 2e39236..c015014 100644
---- a/drivers/infiniband/core/cm.c
-+++ b/drivers/infiniband/core/cm.c
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (c) 2004-2006 Intel Corporation.  All rights reserved.
-+ * Copyright (c) 2004-2007 Intel Corporation.  All rights reserved.
-  * Copyright (c) 2004 Topspin Corporation.  All rights reserved.
-  * Copyright (c) 2004, 2005 Voltaire Corporation.  All rights reserved.
-  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
-@@ -37,12 +37,14 @@
- 
- #include <linux/completion.h>
- #include <linux/dma-mapping.h>
-+#include <linux/device.h>
- #include <linux/err.h>
- #include <linux/idr.h>
- #include <linux/interrupt.h>
- #include <linux/random.h>
- #include <linux/rbtree.h>
- #include <linux/spinlock.h>
-+#include <linux/sysfs.h>
- #include <linux/workqueue.h>
- 
- #include <rdma/ib_cache.h>
-@@ -78,17 +80,94 @@ static struct ib_cm {
- 	struct workqueue_struct *wq;
- } cm;
- 
-+/* Counter indexes ordered by attribute ID */
-+enum {
-+	CM_REQ_COUNTER,
-+	CM_MRA_COUNTER,
-+	CM_REJ_COUNTER,
-+	CM_REP_COUNTER,
-+	CM_RTU_COUNTER,
-+	CM_DREQ_COUNTER,
-+	CM_DREP_COUNTER,
-+	CM_SIDR_REQ_COUNTER,
-+	CM_SIDR_REP_COUNTER,
-+	CM_LAP_COUNTER,
-+	CM_APR_COUNTER,
-+	CM_ATTR_COUNT,
-+	CM_ATTR_ID_OFFSET = 0x0010,
++#ifndef NES_CM_H
++#define NES_CM_H
++
++#define QUEUE_EVENTS
++
++#define NES_MANAGE_APBVT_DEL 0
++#define NES_MANAGE_APBVT_ADD 1
++
++/* IETF MPA -- defines, enums, structs */
++#define IEFT_MPA_KEY_REQ  "MPA ID Req Frame"
++#define IEFT_MPA_KEY_REP  "MPA ID Rep Frame"
++#define IETF_MPA_KEY_SIZE 16
++#define IETF_MPA_VERSION  1
++
++enum ietf_mpa_flags {
++	IETF_MPA_FLAGS_MARKERS = 0x80,	/* receive Markers */
++	IETF_MPA_FLAGS_CRC     = 0x40,	/* receive Markers */
++	IETF_MPA_FLAGS_REJECT  = 0x20,	/* Reject */
 +};
 +
-+enum {
-+	CM_XMIT,
-+	CM_XMIT_RETRIES,
-+	CM_RECV,
-+	CM_RECV_DUPLICATES,
-+	CM_COUNTER_GROUPS
++struct ietf_mpa_frame {
++	u8 key[IETF_MPA_KEY_SIZE];
++	u8 flags;
++	u8 rev;
++	__be16 priv_data_len;
++	u8 priv_data[0];
 +};
 +
-+static char const counter_group_names[CM_COUNTER_GROUPS]
-+				     [sizeof("cm_rx_duplicates")] = {
-+	"cm_tx_msgs", "cm_tx_retries",
-+	"cm_rx_msgs", "cm_rx_duplicates"
++#define ietf_mpa_req_resp_frame ietf_mpa_frame
++
++struct nes_v4_quad {
++	u32 rsvd0;
++	__le32 DstIpAdrIndex;	/* Only most significant 5 bits are valid */
++	__be32 SrcIpadr;
++	__be16 TcpPorts[2];		/* src is low, dest is high */
 +};
 +
-+struct cm_counter_group {
-+	struct kobject obj;
-+	atomic_long_t counter[CM_ATTR_COUNT];
++struct nes_cm_node;
++enum nes_timer_type {
++	NES_TIMER_TYPE_SEND,
++	NES_TIMER_TYPE_RECV,
++	NES_TIMER_NODE_CLEANUP,
++	NES_TIMER_TYPE_CLOSE,
 +};
 +
-+struct cm_counter_attribute {
-+	struct attribute attr;
-+	int index;
++#define MAX_NES_IFS 4
++
++#define SET_ACK 1
++#define SET_SYN 2
++#define SET_FIN 4
++#define SET_RST 8
++
++struct option_base {
++	u8 optionnum;
++	u8 length;
 +};
 +
-+#define CM_COUNTER_ATTR(_name, _index) \
-+struct cm_counter_attribute cm_##_name##_counter_attr = { \
-+	.attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
-+	.index = _index \
-+}
++enum option_numbers {
++	OPTION_NUMBER_END,
++	OPTION_NUMBER_NONE,
++	OPTION_NUMBER_MSS,
++	OPTION_NUMBER_WINDOW_SCALE,
++	OPTION_NUMBER_SACK_PERM,
++	OPTION_NUMBER_SACK,
++	OPTION_NUMBER_WRITE0 = 0xbc
++};
 +
-+static CM_COUNTER_ATTR(req, CM_REQ_COUNTER);
-+static CM_COUNTER_ATTR(mra, CM_MRA_COUNTER);
-+static CM_COUNTER_ATTR(rej, CM_REJ_COUNTER);
-+static CM_COUNTER_ATTR(rep, CM_REP_COUNTER);
-+static CM_COUNTER_ATTR(rtu, CM_RTU_COUNTER);
-+static CM_COUNTER_ATTR(dreq, CM_DREQ_COUNTER);
-+static CM_COUNTER_ATTR(drep, CM_DREP_COUNTER);
-+static CM_COUNTER_ATTR(sidr_req, CM_SIDR_REQ_COUNTER);
-+static CM_COUNTER_ATTR(sidr_rep, CM_SIDR_REP_COUNTER);
-+static CM_COUNTER_ATTR(lap, CM_LAP_COUNTER);
-+static CM_COUNTER_ATTR(apr, CM_APR_COUNTER);
++struct option_mss {
++	u8 optionnum;
++	u8 length;
++	__be16 mss;
++};
 +
-+static struct attribute *cm_counter_default_attrs[] = {
-+	&cm_req_counter_attr.attr,
-+	&cm_mra_counter_attr.attr,
-+	&cm_rej_counter_attr.attr,
-+	&cm_rep_counter_attr.attr,
-+	&cm_rtu_counter_attr.attr,
-+	&cm_dreq_counter_attr.attr,
-+	&cm_drep_counter_attr.attr,
-+	&cm_sidr_req_counter_attr.attr,
-+	&cm_sidr_rep_counter_attr.attr,
-+	&cm_lap_counter_attr.attr,
-+	&cm_apr_counter_attr.attr,
-+	NULL
++struct option_windowscale {
++	u8 optionnum;
++	u8 length;
++	u8 shiftcount;
 +};
 +
- struct cm_port {
- 	struct cm_device *cm_dev;
- 	struct ib_mad_agent *mad_agent;
-+	struct kobject port_obj;
- 	u8 port_num;
-+	struct cm_counter_group counter_group[CM_COUNTER_GROUPS];
- };
- 
- struct cm_device {
- 	struct list_head list;
- 	struct ib_device *device;
-+	struct kobject dev_obj;
- 	u8 ack_delay;
--	struct cm_port port[0];
-+	struct cm_port *port[0];
- };
- 
- struct cm_av {
-@@ -278,7 +357,7 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av)
- 	list_for_each_entry(cm_dev, &cm.device_list, list) {
- 		if (!ib_find_cached_gid(cm_dev->device, &path->sgid,
- 					&p, NULL)) {
--			port = &cm_dev->port[p-1];
-+			port = cm_dev->port[p-1];
- 			break;
- 		}
- 	}
-@@ -1270,6 +1349,9 @@ static void cm_dup_req_handler(struct cm_work *work,
- 	struct ib_mad_send_buf *msg = NULL;
- 	int ret;
- 
-+	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+			counter[CM_REQ_COUNTER]);
++union all_known_options {
++	char as_end;
++	struct option_base as_base;
++	struct option_mss as_mss;
++	struct option_windowscale as_windowscale;
++};
 +
- 	/* Quick state check to discard duplicate REQs. */
- 	if (cm_id_priv->id.state == IB_CM_REQ_RCVD)
- 		return;
-@@ -1616,6 +1698,8 @@ static void cm_dup_rep_handler(struct cm_work *work)
- 	if (!cm_id_priv)
- 		return;
- 
-+	atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+			counter[CM_REP_COUNTER]);
- 	ret = cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg);
- 	if (ret)
- 		goto deref;
-@@ -1781,6 +1865,8 @@ static int cm_rtu_handler(struct cm_work *work)
- 	if (cm_id_priv->id.state != IB_CM_REP_SENT &&
- 	    cm_id_priv->id.state != IB_CM_MRA_REP_RCVD) {
- 		spin_unlock_irq(&cm_id_priv->lock);
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_RTU_COUNTER]);
- 		goto out;
- 	}
- 	cm_id_priv->id.state = IB_CM_ESTABLISHED;
-@@ -1958,6 +2044,8 @@ static int cm_dreq_handler(struct cm_work *work)
- 	cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
- 				   dreq_msg->local_comm_id);
- 	if (!cm_id_priv) {
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_DREQ_COUNTER]);
- 		cm_issue_drep(work->port, work->mad_recv_wc);
- 		return -EINVAL;
- 	}
-@@ -1977,6 +2065,8 @@ static int cm_dreq_handler(struct cm_work *work)
- 	case IB_CM_MRA_REP_RCVD:
- 		break;
- 	case IB_CM_TIMEWAIT:
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_DREQ_COUNTER]);
- 		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
- 			goto unlock;
- 
-@@ -1988,6 +2078,10 @@ static int cm_dreq_handler(struct cm_work *work)
- 		if (ib_post_send_mad(msg, NULL))
- 			cm_free_msg(msg);
- 		goto deref;
-+	case IB_CM_DREQ_RCVD:
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_DREQ_COUNTER]);
-+		goto unlock;
- 	default:
- 		goto unlock;
- 	}
-@@ -2339,10 +2433,20 @@ static int cm_mra_handler(struct cm_work *work)
- 		if (cm_mra_get_msg_mraed(mra_msg) != CM_MSG_RESPONSE_OTHER ||
- 		    cm_id_priv->id.lap_state != IB_CM_LAP_SENT ||
- 		    ib_modify_mad(cm_id_priv->av.port->mad_agent,
--				  cm_id_priv->msg, timeout))
-+				  cm_id_priv->msg, timeout)) {
-+			if (cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
-+				atomic_long_inc(&work->port->
-+						counter_group[CM_RECV_DUPLICATES].
-+						counter[CM_MRA_COUNTER]);
- 			goto out;
++struct nes_timer_entry {
++	struct list_head list;
++	unsigned long timetosend;	/* jiffies */
++	struct sk_buff *skb;
++	u32 type;
++	u32 retrycount;
++	u32 retranscount;
++	u32 context;
++	u32 seq_num;
++	u32 send_retrans;
++	int close_when_complete;
++	struct net_device *netdev;
++};
++
++#define NES_DEFAULT_RETRYS  64
++#define NES_DEFAULT_RETRANS 8
++#ifdef CONFIG_INFINIBAND_NES_DEBUG
++#define NES_RETRY_TIMEOUT   (1000*HZ/1000)
++#else
++#define NES_RETRY_TIMEOUT   (3000*HZ/1000)
++#endif
++#define NES_SHORT_TIME      (10)
++#define NES_LONG_TIME       (2000*HZ/1000)
++
++#define NES_CM_HASHTABLE_SIZE         1024
++#define NES_CM_TCP_TIMER_INTERVAL     3000
++#define NES_CM_DEFAULT_MTU            1540
++#define NES_CM_DEFAULT_FRAME_CNT      10
++#define NES_CM_THREAD_STACK_SIZE      256
++#define NES_CM_DEFAULT_RCV_WND        64240	// before we know that window scaling is allowed
++#define NES_CM_DEFAULT_RCV_WND_SCALED 256960  // after we know that window scaling is allowed
++#define NES_CM_DEFAULT_RCV_WND_SCALE  2
++#define NES_CM_DEFAULT_FREE_PKTS      0x000A
++#define NES_CM_FREE_PKT_LO_WATERMARK  2
++
++#define NES_CM_DEFAULT_MSS   536
++
++#define NES_CM_DEF_SEQ       0x159bf75f
++#define NES_CM_DEF_LOCAL_ID  0x3b47
++
++#define NES_CM_DEF_SEQ2      0x18ed5740
++#define NES_CM_DEF_LOCAL_ID2 0xb807
++
++typedef u32 nes_addr_t;
++
++#define nes_cm_tsa_context nes_qp_context
++
++struct nes_qp;
++
++/* cm node transition states */
++enum nes_cm_node_state {
++	NES_CM_STATE_UNKNOWN,
++	NES_CM_STATE_INITED,
++	NES_CM_STATE_LISTENING,
++	NES_CM_STATE_SYN_RCVD,
++	NES_CM_STATE_SYN_SENT,
++	NES_CM_STATE_ONE_SIDE_ESTABLISHED,
++	NES_CM_STATE_ESTABLISHED,
++	NES_CM_STATE_ACCEPTING,
++	NES_CM_STATE_MPAREQ_SENT,
++	NES_CM_STATE_TSA,
++	NES_CM_STATE_FIN_WAIT1,
++	NES_CM_STATE_FIN_WAIT2,
++	NES_CM_STATE_CLOSE_WAIT,
++	NES_CM_STATE_TIME_WAIT,
++	NES_CM_STATE_LAST_ACK,
++	NES_CM_STATE_CLOSING,
++	NES_CM_STATE_CLOSED
++};
++
++/* type of nes connection */
++enum nes_cm_conn_type {
++	NES_CM_IWARP_CONN_TYPE,
++};
++
++/* CM context params */
++struct nes_cm_tcp_context {
++	u8  client;
++
++	u32 loc_seq_num;
++	u32 loc_ack_num;
++	u32 rem_ack_num;
++	u32 rcv_nxt;
++
++	u32 loc_id;
++	u32 rem_id;
++
++	u32 snd_wnd;
++	u32 max_snd_wnd;
++
++	u32 rcv_wnd;
++	u32 mss;
++	u8  snd_wscale;
++	u8  rcv_wscale;
++
++	struct nes_cm_tsa_context tsa_cntxt;
++	struct timeval            sent_ts;
++};
++
++
++enum nes_cm_listener_state {
++	NES_CM_LISTENER_PASSIVE_STATE=1,
++	NES_CM_LISTENER_ACTIVE_STATE=2,
++	NES_CM_LISTENER_EITHER_STATE=3
++};
++
++struct nes_cm_listener {
++	struct list_head           list;
++	u64                        session_id;
++	struct nes_cm_core         *cm_core;
++	u8                         loc_mac[ETH_ALEN];
++	nes_addr_t                 loc_addr;
++	u16                        loc_port;
++	struct iw_cm_id            *cm_id;
++	enum nes_cm_conn_type      conn_type;
++	atomic_t                   ref_count;
++	struct nes_vnic            *nesvnic;
++	atomic_t                   pend_accepts_cnt;
++	int                        backlog;
++	enum nes_cm_listener_state listener_state;
++	u32                        reused_node;
++};
++
++/* per connection node and node state information */
++struct nes_cm_node {
++	u64                       session_id;
++	u32                       hashkey;
++
++	nes_addr_t                loc_addr, rem_addr;
++	u16                       loc_port, rem_port;
++
++	u8                        loc_mac[ETH_ALEN];
++	u8                        rem_mac[ETH_ALEN];
++
++	enum nes_cm_node_state    state;
++	struct nes_cm_tcp_context tcp_cntxt;
++	struct nes_cm_core        *cm_core;
++	struct sk_buff_head       resend_list;
++	atomic_t                  ref_count;
++	struct net_device         *netdev;
++
++	struct nes_cm_node        *loopbackpartner;
++	struct list_head          retrans_list;
++	spinlock_t                retrans_list_lock;
++	struct list_head          recv_list;
++	spinlock_t                recv_list_lock;
++
++	int                       send_write0;
++	union {
++		struct ietf_mpa_frame mpa_frame;
++		u8                    mpa_frame_buf[NES_CM_DEFAULT_MTU];
++	};
++	u16                       mpa_frame_size;
++	struct iw_cm_id           *cm_id;
++	struct list_head          list;
++	int                       accelerated;
++	struct nes_cm_listener    *listener;
++	enum nes_cm_conn_type     conn_type;
++	struct nes_vnic           *nesvnic;
++	int                       apbvt_set;
++	int                       accept_pend;
++};
++
++/* structure for client or CM to fill when making CM api calls. */
++/*	- only need to set relevant data, based on op. */
++struct nes_cm_info {
++	union {
++		struct iw_cm_id   *cm_id;
++		struct net_device *netdev;
++	};
++
++	u16 loc_port;
++	u16 rem_port;
++	nes_addr_t loc_addr;
++	nes_addr_t rem_addr;
++
++	enum nes_cm_conn_type  conn_type;
++	int backlog;
++};
++
++/* CM event codes */
++enum  nes_cm_event_type {
++	NES_CM_EVENT_UNKNOWN,
++	NES_CM_EVENT_ESTABLISHED,
++	NES_CM_EVENT_MPA_REQ,
++	NES_CM_EVENT_MPA_CONNECT,
++	NES_CM_EVENT_MPA_ACCEPT,
++	NES_CM_EVENT_MPA_ESTABLISHED,
++	NES_CM_EVENT_CONNECTED,
++	NES_CM_EVENT_CLOSED,
++	NES_CM_EVENT_RESET,
++	NES_CM_EVENT_DROPPED_PKT,
++	NES_CM_EVENT_CLOSE_IMMED,
++	NES_CM_EVENT_CLOSE_HARD,
++	NES_CM_EVENT_CLOSE_CLEAN,
++	NES_CM_EVENT_ABORTED,
++	NES_CM_EVENT_SEND_FIRST
++};
++
++/* event to post to CM event handler */
++struct nes_cm_event {
++	enum nes_cm_event_type type;
++
++	struct nes_cm_info cm_info;
++	struct work_struct event_work;
++	struct nes_cm_node *cm_node;
++};
++
++struct nes_cm_core {
++	enum nes_cm_node_state  state;
++	atomic_t                session_id;
++
++	atomic_t                listen_node_cnt;
++	struct nes_cm_node      listen_list;
++	spinlock_t              listen_list_lock;
++
++	u32                     mtu;
++	u32                     free_tx_pkt_max;
++	u32                     rx_pkt_posted;
++	struct sk_buff_head     tx_free_list;
++	atomic_t                ht_node_cnt;
++	struct list_head        connected_nodes;
++	/* struct list_head hashtable[NES_CM_HASHTABLE_SIZE]; */
++	spinlock_t              ht_lock;
++
++	struct timer_list       tcp_timer;
++
++	struct nes_cm_ops       *api;
++
++	int (*post_event)(struct nes_cm_event *event);
++	atomic_t                events_posted;
++	struct workqueue_struct *event_wq;
++	struct workqueue_struct *disconn_wq;
++
++	atomic_t                node_cnt;
++	u64                     aborted_connects;
++	u32                     options;
++
++	struct nes_cm_node      *current_listen_node;
++};
++
++
++#define NES_CM_SET_PKT_SIZE        (1 << 1)
++#define NES_CM_SET_FREE_PKT_Q_SIZE (1 << 2)
++
++/* CM ops/API for client interface */
++struct nes_cm_ops {
++	int (*accelerated)(struct nes_cm_core *, struct nes_cm_node *);
++	struct nes_cm_listener * (*listen)(struct nes_cm_core *, struct nes_vnic *,
++			struct nes_cm_info *);
++	int (*stop_listener)(struct nes_cm_core *, struct nes_cm_listener *);
++	struct nes_cm_node * (*connect)(struct nes_cm_core *,
++			struct nes_vnic *, struct ietf_mpa_frame *,
++			struct nes_cm_info *);
++	int (*close)(struct nes_cm_core *, struct nes_cm_node *);
++	int (*accept)(struct nes_cm_core *, struct ietf_mpa_frame *,
++			struct nes_cm_node *);
++	int (*reject)(struct nes_cm_core *, struct ietf_mpa_frame *,
++			struct nes_cm_node *);
++	int (*recv_pkt)(struct nes_cm_core *, struct nes_vnic *,
++			struct sk_buff *);
++	int (*destroy_cm_core)(struct nes_cm_core *);
++	int (*get)(struct nes_cm_core *);
++	int (*set)(struct nes_cm_core *, u32, u32);
++};
++
++
++int send_mpa_request(struct nes_cm_node *);
++struct sk_buff *form_cm_frame(struct sk_buff *, struct nes_cm_node *,
++		void *, u32, void *, u32, u8);
++int schedule_nes_timer(struct nes_cm_node *, struct sk_buff *,
++		enum nes_timer_type, int, int);
++void nes_cm_timer_tick(unsigned long);
++int send_syn(struct nes_cm_node *, u32);
++int send_reset(struct nes_cm_node *);
++int send_ack(struct nes_cm_node *);
++int send_fin(struct nes_cm_node *, struct sk_buff *);
++struct sk_buff *get_free_pkt(struct nes_cm_node *);
++int process_packet(struct nes_cm_node *, struct sk_buff *, struct nes_cm_core *);
++
++struct nes_cm_node * mini_cm_connect(struct nes_cm_core *,
++		struct nes_vnic *, struct ietf_mpa_frame *, struct nes_cm_info *);
++int mini_cm_accept(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *);
++int mini_cm_reject(struct nes_cm_core *, struct ietf_mpa_frame *, struct nes_cm_node *);
++int mini_cm_close(struct nes_cm_core *, struct nes_cm_node *);
++int mini_cm_recv_pkt(struct nes_cm_core *, struct nes_vnic *, struct sk_buff *);
++struct nes_cm_core *mini_cm_alloc_core(struct nes_cm_info *);
++int mini_cm_dealloc_core(struct nes_cm_core *);
++int mini_cm_get(struct nes_cm_core *);
++int mini_cm_set(struct nes_cm_core *, u32, u32);
++
++int nes_cm_disconn(struct nes_qp *);
++void nes_disconnect_worker(struct work_struct *);
++int nes_cm_disconn_true(struct nes_qp *);
++int nes_disconnect(struct nes_qp *, int);
++
++int nes_accept(struct iw_cm_id *, struct iw_cm_conn_param *);
++int nes_reject(struct iw_cm_id *, const void *, u8);
++int nes_connect(struct iw_cm_id *, struct iw_cm_conn_param *);
++int nes_create_listen(struct iw_cm_id *, int);
++int nes_destroy_listen(struct iw_cm_id *);
++
++int nes_cm_recv(struct sk_buff *, struct net_device *);
++int nes_cm_start(void);
++int nes_cm_stop(void);
++
++/* CM event handler functions */
++void cm_event_connected(struct nes_cm_event *);
++void cm_event_connect_error(struct nes_cm_event *);
++void cm_event_reset(struct nes_cm_event *);
++void cm_event_mpa_req(struct nes_cm_event *);
++int nes_cm_post_event(struct nes_cm_event *);
++
++#endif			/* NES_CM_H */
+diff --git a/drivers/infiniband/hw/nes/nes_context.h b/drivers/infiniband/hw/nes/nes_context.h
+new file mode 100644
+index 0000000..da9daba
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_context.h
+@@ -0,0 +1,193 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef NES_CONTEXT_H
++#define NES_CONTEXT_H
++
++struct nes_qp_context {
++	__le32   misc;
++	__le32   cqs;
++	__le32   sq_addr_low;
++	__le32   sq_addr_high;
++	__le32   rq_addr_low;
++	__le32   rq_addr_high;
++	__le32   misc2;
++	__le16   tcpPorts[2];
++	__le32   ip0;
++	__le32   ip1;
++	__le32   ip2;
++	__le32   ip3;
++	__le32   mss;
++	__le32   arp_index_vlan;
++	__le32   tcp_state_flow_label;
++	__le32   pd_index_wscale;
++	__le32   keepalive;
++	u32   ts_recent;
++	u32   ts_age;
++	__le32   snd_nxt;
++	__le32   snd_wnd;
++	__le32   rcv_nxt;
++	__le32   rcv_wnd;
++	__le32   snd_max;
++	__le32   snd_una;
++	u32   srtt;
++	__le32   rttvar;
++	__le32   ssthresh;
++	__le32   cwnd;
++	__le32   snd_wl1;
++	__le32   snd_wl2;
++	__le32   max_snd_wnd;
++	__le32   ts_val_delta;
++	u32   retransmit;
++	u32   probe_cnt;
++	u32   hte_index;
++	__le32   q2_addr_low;
++	__le32   q2_addr_high;
++	__le32   ird_index;
++	u32   Rsvd3;
++	__le32   ird_ord_sizes;
++	u32   mrkr_offset;
++	__le32   aeq_token_low;
++	__le32   aeq_token_high;
++};
++
++/* QP Context Misc Field */
++
++#define NES_QPCONTEXT_MISC_IWARP_VER_MASK    0x00000003
++#define NES_QPCONTEXT_MISC_IWARP_VER_SHIFT   0
++#define NES_QPCONTEXT_MISC_EFB_SIZE_MASK     0x000000C0
++#define NES_QPCONTEXT_MISC_EFB_SIZE_SHIFT    6
++#define NES_QPCONTEXT_MISC_RQ_SIZE_MASK      0x00000300
++#define NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT     8
++#define NES_QPCONTEXT_MISC_SQ_SIZE_MASK      0x00000c00
++#define NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT     10
++#define NES_QPCONTEXT_MISC_PCI_FCN_MASK      0x00007000
++#define NES_QPCONTEXT_MISC_PCI_FCN_SHIFT     12
++#define NES_QPCONTEXT_MISC_DUP_ACKS_MASK     0x00070000
++#define NES_QPCONTEXT_MISC_DUP_ACKS_SHIFT    16
++
++enum nes_qp_context_misc_bits {
++	NES_QPCONTEXT_MISC_RX_WQE_SIZE         = 0x00000004,
++	NES_QPCONTEXT_MISC_IPV4                = 0x00000008,
++	NES_QPCONTEXT_MISC_DO_NOT_FRAG         = 0x00000010,
++	NES_QPCONTEXT_MISC_INSERT_VLAN         = 0x00000020,
++	NES_QPCONTEXT_MISC_DROS                = 0x00008000,
++	NES_QPCONTEXT_MISC_WSCALE              = 0x00080000,
++	NES_QPCONTEXT_MISC_KEEPALIVE           = 0x00100000,
++	NES_QPCONTEXT_MISC_TIMESTAMP           = 0x00200000,
++	NES_QPCONTEXT_MISC_SACK                = 0x00400000,
++	NES_QPCONTEXT_MISC_RDMA_WRITE_EN       = 0x00800000,
++	NES_QPCONTEXT_MISC_RDMA_READ_EN        = 0x01000000,
++	NES_QPCONTEXT_MISC_WBIND_EN            = 0x10000000,
++	NES_QPCONTEXT_MISC_FAST_REGISTER_EN    = 0x20000000,
++	NES_QPCONTEXT_MISC_PRIV_EN             = 0x40000000,
++	NES_QPCONTEXT_MISC_NO_NAGLE            = 0x80000000
++};
++
++enum nes_qp_acc_wq_sizes {
++	HCONTEXT_TSA_WQ_SIZE_4 = 0,
++	HCONTEXT_TSA_WQ_SIZE_32 = 1,
++	HCONTEXT_TSA_WQ_SIZE_128 = 2,
++	HCONTEXT_TSA_WQ_SIZE_512 = 3
++};
++
++/* QP Context Misc2 Fields */
++#define NES_QPCONTEXT_MISC2_TTL_MASK            0x000000ff
++#define NES_QPCONTEXT_MISC2_TTL_SHIFT           0
++#define NES_QPCONTEXT_MISC2_HOP_LIMIT_MASK      0x000000ff
++#define NES_QPCONTEXT_MISC2_HOP_LIMIT_SHIFT     0
++#define NES_QPCONTEXT_MISC2_LIMIT_MASK          0x00000300
++#define NES_QPCONTEXT_MISC2_LIMIT_SHIFT         8
++#define NES_QPCONTEXT_MISC2_NIC_INDEX_MASK      0x0000fc00
++#define NES_QPCONTEXT_MISC2_NIC_INDEX_SHIFT     10
++#define NES_QPCONTEXT_MISC2_SRC_IP_MASK         0x001f0000
++#define NES_QPCONTEXT_MISC2_SRC_IP_SHIFT        16
++#define NES_QPCONTEXT_MISC2_TOS_MASK            0xff000000
++#define NES_QPCONTEXT_MISC2_TOS_SHIFT           24
++#define NES_QPCONTEXT_MISC2_TRAFFIC_CLASS_MASK  0xff000000
++#define NES_QPCONTEXT_MISC2_TRAFFIC_CLASS_SHIFT 24
++
++/* QP Context Tcp State/Flow Label Fields */
++#define NES_QPCONTEXT_TCPFLOW_FLOW_LABEL_MASK   0x000fffff
++#define NES_QPCONTEXT_TCPFLOW_FLOW_LABEL_SHIFT  0
++#define NES_QPCONTEXT_TCPFLOW_TCP_STATE_MASK    0xf0000000
++#define NES_QPCONTEXT_TCPFLOW_TCP_STATE_SHIFT   28
++
++enum nes_qp_tcp_state {
++	NES_QPCONTEXT_TCPSTATE_CLOSED = 1,
++	NES_QPCONTEXT_TCPSTATE_EST = 5,
++	NES_QPCONTEXT_TCPSTATE_TIME_WAIT = 11,
++};
++
++/* QP Context PD Index/wscale Fields */
++#define NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_MASK  0x0000000f
++#define NES_QPCONTEXT_PDWSCALE_RCV_WSCALE_SHIFT 0
++#define NES_QPCONTEXT_PDWSCALE_SND_WSCALE_MASK  0x00000f00
++#define NES_QPCONTEXT_PDWSCALE_SND_WSCALE_SHIFT 8
++#define NES_QPCONTEXT_PDWSCALE_PDINDEX_MASK     0xffff0000
++#define NES_QPCONTEXT_PDWSCALE_PDINDEX_SHIFT    16
++
++/* QP Context Keepalive Fields */
++#define NES_QPCONTEXT_KEEPALIVE_DELTA_MASK      0x0000ffff
++#define NES_QPCONTEXT_KEEPALIVE_DELTA_SHIFT     0
++#define NES_QPCONTEXT_KEEPALIVE_PROBE_CNT_MASK  0x00ff0000
++#define NES_QPCONTEXT_KEEPALIVE_PROBE_CNT_SHIFT 16
++#define NES_QPCONTEXT_KEEPALIVE_INTV_MASK       0xff000000
++#define NES_QPCONTEXT_KEEPALIVE_INTV_SHIFT      24
++
++/* QP Context ORD/IRD Fields */
++#define NES_QPCONTEXT_ORDIRD_ORDSIZE_MASK       0x0000007f
++#define NES_QPCONTEXT_ORDIRD_ORDSIZE_SHIFT      0
++#define NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK       0x00030000
++#define NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT      16
++#define NES_QPCONTEXT_ORDIRD_IWARP_MODE_MASK    0x30000000
++#define NES_QPCONTEXT_ORDIRD_IWARP_MODE_SHIFT   28
++
++enum nes_ord_ird_bits {
++	NES_QPCONTEXT_ORDIRD_WRPDU                   = 0x02000000,
++	NES_QPCONTEXT_ORDIRD_LSMM_PRESENT            = 0x04000000,
++	NES_QPCONTEXT_ORDIRD_ALSMM                   = 0x08000000,
++	NES_QPCONTEXT_ORDIRD_AAH                     = 0x40000000,
++	NES_QPCONTEXT_ORDIRD_RNMC                    = 0x80000000
++};
++
++enum nes_iwarp_qp_state {
++	NES_QPCONTEXT_IWARP_STATE_NONEXIST  = 0,
++	NES_QPCONTEXT_IWARP_STATE_IDLE      = 1,
++	NES_QPCONTEXT_IWARP_STATE_RTS       = 2,
++	NES_QPCONTEXT_IWARP_STATE_CLOSING   = 3,
++	NES_QPCONTEXT_IWARP_STATE_TERMINATE = 5,
++	NES_QPCONTEXT_IWARP_STATE_ERROR     = 6
++};
++
++
++#endif		/* NES_CONTEXT_H */
+diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
+new file mode 100644
+index 0000000..7c4c0fb
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_hw.c
+@@ -0,0 +1,3080 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/if_vlan.h>
++
++#include "nes.h"
++
++u32 crit_err_count = 0;
++u32 int_mod_timer_init;
++u32 int_mod_cq_depth_256;
++u32 int_mod_cq_depth_128;
++u32 int_mod_cq_depth_32;
++u32 int_mod_cq_depth_24;
++u32 int_mod_cq_depth_16;
++u32 int_mod_cq_depth_4;
++u32 int_mod_cq_depth_1;
++
++#include "nes_cm.h"
++
++
++#ifdef CONFIG_INFINIBAND_NES_DEBUG
++static unsigned char *nes_iwarp_state_str[] = {
++	"Non-Existant",
++	"Idle",
++	"RTS",
++	"Closing",
++	"RSVD1",
++	"Terminate",
++	"Error",
++	"RSVD2",
++};
++
++static unsigned char *nes_tcp_state_str[] = {
++	"Non-Existant",
++	"Closed",
++	"Listen",
++	"SYN Sent",
++	"SYN Rcvd",
++	"Established",
++	"Close Wait",
++	"FIN Wait 1",
++	"Closing",
++	"Last Ack",
++	"FIN Wait 2",
++	"Time Wait",
++	"RSVD1",
++	"RSVD2",
++	"RSVD3",
++	"RSVD4",
++};
++#endif
++
++
++/**
++ * nes_nic_init_timer_defaults
++ */
++void  nes_nic_init_timer_defaults(struct nes_device *nesdev, u8 jumbomode)
++{
++	unsigned long flags;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
++
++	spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
++
++	shared_timer->timer_in_use_min = NES_NIC_FAST_TIMER_LOW;
++	shared_timer->timer_in_use_max = NES_NIC_FAST_TIMER_HIGH;
++	if (jumbomode) {
++		shared_timer->threshold_low    = DEFAULT_JUMBO_NES_QL_LOW;
++		shared_timer->threshold_target = DEFAULT_JUMBO_NES_QL_TARGET;
++		shared_timer->threshold_high   = DEFAULT_JUMBO_NES_QL_HIGH;
++	} else {
++		shared_timer->threshold_low    = DEFAULT_NES_QL_LOW;
++		shared_timer->threshold_target = DEFAULT_NES_QL_TARGET;
++		shared_timer->threshold_high   = DEFAULT_NES_QL_HIGH;
++	}
++
++	/* todo use netdev->mtu to set thresholds */
++	spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
++}
++
++
++/**
++ * nes_nic_init_timer
++ */
++static void  nes_nic_init_timer(struct nes_device *nesdev)
++{
++	unsigned long flags;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
++
++	spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
++
++	if (shared_timer->timer_in_use_old == 0) {
++		nesdev->deepcq_count = 0;
++		shared_timer->timer_direction_upward = 0;
++		shared_timer->timer_direction_downward = 0;
++		shared_timer->timer_in_use = NES_NIC_FAST_TIMER;
++		shared_timer->timer_in_use_old = 0;
++
++	}
++	if (shared_timer->timer_in_use != shared_timer->timer_in_use_old) {
++		shared_timer->timer_in_use_old = shared_timer->timer_in_use;
++		nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
++			0x80000000 | ((u32)(shared_timer->timer_in_use*8)));
++	}
++	/* todo use netdev->mtu to set thresholds */
++	spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
++}
++
++
++/**
++ * nes_nic_tune_timer
++ */
++static void nes_nic_tune_timer(struct nes_device *nesdev)
++{
++	unsigned long flags;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
++	u16 cq_count = nesdev->currcq_count;
++
++	spin_lock_irqsave(&nesadapter->periodic_timer_lock, flags);
++
++	if (shared_timer->cq_count_old < cq_count) {
++		if (cq_count > shared_timer->threshold_low)
++			shared_timer->cq_direction_downward=0;
++	}
++	if (shared_timer->cq_count_old >= cq_count)
++		shared_timer->cq_direction_downward++;
++	shared_timer->cq_count_old = cq_count;
++	if (shared_timer->cq_direction_downward > NES_NIC_CQ_DOWNWARD_TREND) {
++		if (cq_count <= shared_timer->threshold_low) {
++			shared_timer->threshold_low = shared_timer->threshold_low/2;
++			shared_timer->cq_direction_downward=0;
++			nesdev->currcq_count = 0;
++			spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
++			return;
 +		}
- 		cm_id_priv->id.lap_state = IB_CM_MRA_LAP_RCVD;
- 		break;
-+	case IB_CM_MRA_REQ_RCVD:
-+	case IB_CM_MRA_REP_RCVD:
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_MRA_COUNTER]);
-+		/* fall through */
- 	default:
- 		goto out;
- 	}
-@@ -2502,6 +2606,8 @@ static int cm_lap_handler(struct cm_work *work)
- 	case IB_CM_LAP_IDLE:
- 		break;
- 	case IB_CM_MRA_LAP_SENT:
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_LAP_COUNTER]);
- 		if (cm_alloc_response_msg(work->port, work->mad_recv_wc, &msg))
- 			goto unlock;
- 
-@@ -2515,6 +2621,10 @@ static int cm_lap_handler(struct cm_work *work)
- 		if (ib_post_send_mad(msg, NULL))
- 			cm_free_msg(msg);
- 		goto deref;
-+	case IB_CM_LAP_RCVD:
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_LAP_COUNTER]);
-+		goto unlock;
- 	default:
- 		goto unlock;
- 	}
-@@ -2796,6 +2906,8 @@ static int cm_sidr_req_handler(struct cm_work *work)
- 	cur_cm_id_priv = cm_insert_remote_sidr(cm_id_priv);
- 	if (cur_cm_id_priv) {
- 		spin_unlock_irq(&cm.lock);
-+		atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES].
-+				counter[CM_SIDR_REQ_COUNTER]);
- 		goto out; /* Duplicate message. */
- 	}
- 	cm_id_priv->id.state = IB_CM_SIDR_REQ_RCVD;
-@@ -2990,6 +3102,27 @@ static void cm_send_handler(struct ib_mad_agent *mad_agent,
- 			    struct ib_mad_send_wc *mad_send_wc)
- {
- 	struct ib_mad_send_buf *msg = mad_send_wc->send_buf;
-+	struct cm_port *port;
-+	u16 attr_index;
++	}
 +
-+	port = mad_agent->context;
-+	attr_index = be16_to_cpu(((struct ib_mad_hdr *)
-+				  msg->mad)->attr_id) - CM_ATTR_ID_OFFSET;
++	if (cq_count > 1) {
++		nesdev->deepcq_count += cq_count;
++		if (cq_count <= shared_timer->threshold_low) {       /* increase timer gently */
++			shared_timer->timer_direction_upward++;
++			shared_timer->timer_direction_downward = 0;
++		} else if (cq_count <= shared_timer->threshold_target) { /* balanced */
++			shared_timer->timer_direction_upward = 0;
++			shared_timer->timer_direction_downward = 0;
++		} else if (cq_count <= shared_timer->threshold_high) {  /* decrease timer gently */
++			shared_timer->timer_direction_downward++;
++			shared_timer->timer_direction_upward = 0;
++		} else if (cq_count <= (shared_timer->threshold_high) * 2) {
++			shared_timer->timer_in_use -= 2;
++			shared_timer->timer_direction_upward = 0;
++			shared_timer->timer_direction_downward++;
++		} else {
++			shared_timer->timer_in_use -= 4;
++			shared_timer->timer_direction_upward = 0;
++			shared_timer->timer_direction_downward++;
++		}
 +
-+	/*
-+	 * If the send was in response to a received message (context[0] is not
-+	 * set to a cm_id), and is not a REJ, then it is a send that was
-+	 * manually retried.
-+	 */
-+	if (!msg->context[0] && (attr_index != CM_REJ_COUNTER))
-+		msg->retries = 1;
++		if (shared_timer->timer_direction_upward > 3 ) {  /* using history */
++			shared_timer->timer_in_use += 3;
++			shared_timer->timer_direction_upward = 0;
++			shared_timer->timer_direction_downward = 0;
++		}
++		if (shared_timer->timer_direction_downward > 5) { /* using history */
++			shared_timer->timer_in_use -= 4 ;
++			shared_timer->timer_direction_downward = 0;
++			shared_timer->timer_direction_upward = 0;
++		}
++	}
 +
-+	atomic_long_add(1 + msg->retries,
-+			&port->counter_group[CM_XMIT].counter[attr_index]);
-+	if (msg->retries)
-+		atomic_long_add(msg->retries,
-+				&port->counter_group[CM_XMIT_RETRIES].
-+				counter[attr_index]);
- 
- 	switch (mad_send_wc->status) {
- 	case IB_WC_SUCCESS:
-@@ -3148,8 +3281,10 @@ EXPORT_SYMBOL(ib_cm_notify);
- static void cm_recv_handler(struct ib_mad_agent *mad_agent,
- 			    struct ib_mad_recv_wc *mad_recv_wc)
- {
-+	struct cm_port *port = mad_agent->context;
- 	struct cm_work *work;
- 	enum ib_cm_event_type event;
-+	u16 attr_id;
- 	int paths = 0;
- 
- 	switch (mad_recv_wc->recv_buf.mad->mad_hdr.attr_id) {
-@@ -3194,6 +3329,10 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
- 		return;
- 	}
- 
-+	attr_id = be16_to_cpu(mad_recv_wc->recv_buf.mad->mad_hdr.attr_id);
-+	atomic_long_inc(&port->counter_group[CM_RECV].
-+			counter[attr_id - CM_ATTR_ID_OFFSET]);
++	/* boundary checking */
++	if (shared_timer->timer_in_use > NES_NIC_FAST_TIMER_HIGH)
++		shared_timer->timer_in_use = NES_NIC_FAST_TIMER_HIGH;
++	else if (shared_timer->timer_in_use < NES_NIC_FAST_TIMER_LOW) {
++		shared_timer->timer_in_use = NES_NIC_FAST_TIMER_LOW;
++	}
++
++	nesdev->currcq_count = 0;
++
++	spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
++}
++
++
++/**
++ * nes_init_adapter - initialize adapter
++ */
++struct nes_adapter *nes_init_adapter(struct nes_device *nesdev, u8 hw_rev) {
++	struct nes_adapter *nesadapter = NULL;
++	unsigned long num_pds;
++	u32 u32temp;
++	u32 port_count;
++	u16 max_rq_wrs;
++	u16 max_sq_wrs;
++	u32 max_mr;
++	u32 max_256pbl;
++	u32 max_4kpbl;
++	u32 max_qp;
++	u32 max_irrq;
++	u32 max_cq;
++	u32 hte_index_mask;
++	u32 adapter_size;
++	u32 arp_table_size;
++	u16 vendor_id;
++	u8  OneG_Mode;
++	u8  func_index;
++
++	/* search the list of existing adapters */
++	list_for_each_entry(nesadapter, &nes_adapter_list, list) {
++		nes_debug(NES_DBG_INIT, "Searching Adapter list for PCI devfn = 0x%X,"
++				" adapter PCI slot/bus = %u/%u, pci devices PCI slot/bus = %u/%u, .\n",
++				nesdev->pcidev->devfn,
++				PCI_SLOT(nesadapter->devfn),
++				nesadapter->bus_number,
++				PCI_SLOT(nesdev->pcidev->devfn),
++				nesdev->pcidev->bus->number );
++		if ((PCI_SLOT(nesadapter->devfn) == PCI_SLOT(nesdev->pcidev->devfn)) &&
++				(nesadapter->bus_number == nesdev->pcidev->bus->number)) {
++			nesadapter->ref_count++;
++			return nesadapter;
++		}
++	}
++
++	/* no adapter found */
++	num_pds = pci_resource_len(nesdev->pcidev, BAR_1) >> PAGE_SHIFT;
++	if ((hw_rev != NE020_REV) && (hw_rev != NE020_REV1)) {
++		nes_debug(NES_DBG_INIT, "NE020 driver detected unknown hardware revision 0x%x\n",
++				hw_rev);
++		return NULL;
++	}
++
++	nes_debug(NES_DBG_INIT, "Determine Soft Reset, QP_control=0x%x, CPU0=0x%x, CPU1=0x%x, CPU2=0x%x\n",
++			nes_read_indexed(nesdev, NES_IDX_QP_CONTROL + PCI_FUNC(nesdev->pcidev->devfn) * 8),
++			nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS),
++			nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 4),
++			nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS + 8));
++
++	nes_debug(NES_DBG_INIT, "Reset and init NE020\n");
++
++
++	if ((port_count = nes_reset_adapter_ne020(nesdev, &OneG_Mode)) == 0)
++		return NULL;
++	if (nes_init_serdes(nesdev, hw_rev, port_count, OneG_Mode))
++		return NULL;
++	nes_init_csr_ne020(nesdev, hw_rev, port_count);
++
++	max_qp = nes_read_indexed(nesdev, NES_IDX_QP_CTX_SIZE);
++	nes_debug(NES_DBG_INIT, "QP_CTX_SIZE=%u\n", max_qp);
++
++	u32temp = nes_read_indexed(nesdev, NES_IDX_QUAD_HASH_TABLE_SIZE);
++	if (max_qp > ((u32)1 << (u32temp & 0x001f))) {
++		nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to hash table size = 0x%08X\n",
++				max_qp, u32temp);
++		max_qp = (u32)1 << (u32temp & 0x001f);
++	}
++
++	hte_index_mask = ((u32)1 << ((u32temp & 0x001f)+1))-1;
++	nes_debug(NES_DBG_INIT, "Max QP = %u, hte_index_mask = 0x%08X.\n",
++			max_qp, hte_index_mask);
++
++	u32temp = nes_read_indexed(nesdev, NES_IDX_IRRQ_COUNT);
++
++	max_irrq = 1 << (u32temp & 0x001f);
++
++	if (max_qp > max_irrq) {
++		max_qp = max_irrq;
++		nes_debug(NES_DBG_INIT, "Reducing Max QPs to %u due to Available Q1s.\n",
++				max_qp);
++	}
++
++	/* there should be no reason to allocate more pds than qps */
++	if (num_pds > max_qp)
++		num_pds = max_qp;
++
++	u32temp = nes_read_indexed(nesdev, NES_IDX_MRT_SIZE);
++	max_mr = (u32)8192 << (u32temp & 0x7);
++
++	u32temp = nes_read_indexed(nesdev, NES_IDX_PBL_REGION_SIZE);
++	max_256pbl = (u32)1 << (u32temp & 0x0000001f);
++	max_4kpbl = (u32)1 << ((u32temp >> 16) & 0x0000001f);
++	max_cq = nes_read_indexed(nesdev, NES_IDX_CQ_CTX_SIZE);
++
++	u32temp = nes_read_indexed(nesdev, NES_IDX_ARP_CACHE_SIZE);
++	arp_table_size = 1 << u32temp;
++
++	adapter_size = (sizeof(struct nes_adapter) +
++			(sizeof(unsigned long)-1)) & (~(sizeof(unsigned long)-1));
++	adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_qp);
++	adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_mr);
++	adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(max_cq);
++	adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(num_pds);
++	adapter_size += sizeof(unsigned long) * BITS_TO_LONGS(arp_table_size);
++	adapter_size += sizeof(struct nes_qp **) * max_qp;
++
++	/* allocate a new adapter struct */
++	nesadapter = kzalloc(adapter_size, GFP_KERNEL);
++	if (nesadapter == NULL) {
++		return NULL;
++	}
++
++	nes_debug(NES_DBG_INIT, "Allocating new nesadapter @ %p, size = %u (actual size = %u).\n",
++			nesadapter, (u32)sizeof(struct nes_adapter), adapter_size);
++
++	/* populate the new nesadapter */
++	nesadapter->devfn = nesdev->pcidev->devfn;
++	nesadapter->bus_number = nesdev->pcidev->bus->number;
++	nesadapter->ref_count = 1;
++	nesadapter->timer_int_req = 0xffff0000;
++	nesadapter->OneG_Mode = OneG_Mode;
++	nesadapter->doorbell_start = nesdev->doorbell_region;
++
++	/* nesadapter->tick_delta = clk_divisor; */
++	nesadapter->hw_rev = hw_rev;
++	nesadapter->port_count = port_count;
++
++	nesadapter->max_qp = max_qp;
++	nesadapter->hte_index_mask = hte_index_mask;
++	nesadapter->max_irrq = max_irrq;
++	nesadapter->max_mr = max_mr;
++	nesadapter->max_256pbl = max_256pbl - 1;
++	nesadapter->max_4kpbl = max_4kpbl - 1;
++	nesadapter->max_cq = max_cq;
++	nesadapter->free_256pbl = max_256pbl - 1;
++	nesadapter->free_4kpbl = max_4kpbl - 1;
++	nesadapter->max_pd = num_pds;
++	nesadapter->arp_table_size = arp_table_size;
++
++	nesadapter->et_pkt_rate_low = NES_TIMER_ENABLE_LIMIT;
++	if (nes_drv_opt & NES_DRV_OPT_DISABLE_INT_MOD) {
++		nesadapter->et_use_adaptive_rx_coalesce = 0;
++		nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT;
++		nesadapter->et_rx_coalesce_usecs_irq = interrupt_mod_interval;
++	} else {
++		nesadapter->et_use_adaptive_rx_coalesce = 1;
++		nesadapter->timer_int_limit = NES_TIMER_INT_LIMIT_DYNAMIC;
++		nesadapter->et_rx_coalesce_usecs_irq = 0;
++		printk(PFX "%s: Using Adaptive Interrupt Moderation\n", __FUNCTION__);
++	}
++	/* Setup and enable the periodic timer */
++	if (nesadapter->et_rx_coalesce_usecs_irq)
++		nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x80000000 |
++				((u32)(nesadapter->et_rx_coalesce_usecs_irq * 8)));
++	else
++		nes_write32(nesdev->regs+NES_PERIODIC_CONTROL, 0x00000000);
++
++	nesadapter->base_pd = 1;
++
++	nesadapter->device_cap_flags =
++			IB_DEVICE_ZERO_STAG | IB_DEVICE_SEND_W_INV | IB_DEVICE_MEM_WINDOW;
++
++	nesadapter->allocated_qps = (unsigned long *)&(((unsigned char *)nesadapter)
++			[(sizeof(struct nes_adapter)+(sizeof(unsigned long)-1))&(~(sizeof(unsigned long)-1))]);
++	nesadapter->allocated_cqs = &nesadapter->allocated_qps[BITS_TO_LONGS(max_qp)];
++	nesadapter->allocated_mrs = &nesadapter->allocated_cqs[BITS_TO_LONGS(max_cq)];
++	nesadapter->allocated_pds = &nesadapter->allocated_mrs[BITS_TO_LONGS(max_mr)];
++	nesadapter->allocated_arps = &nesadapter->allocated_pds[BITS_TO_LONGS(num_pds)];
++	nesadapter->qp_table = (struct nes_qp **)(&nesadapter->allocated_arps[BITS_TO_LONGS(arp_table_size)]);
++
++
++	/* mark the usual suspect QPs and CQs as in use */
++	for (u32temp = 0; u32temp < NES_FIRST_QPN; u32temp++) {
++		set_bit(u32temp, nesadapter->allocated_qps);
++		set_bit(u32temp, nesadapter->allocated_cqs);
++	}
++
++	for (u32temp = 0; u32temp < 20; u32temp++)
++		set_bit(u32temp, nesadapter->allocated_pds);
++	u32temp = nes_read_indexed(nesdev, NES_IDX_QP_MAX_CFG_SIZES);
++
++	max_rq_wrs = ((u32temp >> 8) & 3);
++	switch (max_rq_wrs) {
++		case 0:
++			max_rq_wrs = 4;
++			break;
++		case 1:
++			max_rq_wrs = 16;
++			break;
++		case 2:
++			max_rq_wrs = 32;
++			break;
++		case 3:
++			max_rq_wrs = 512;
++			break;
++	}
++
++	max_sq_wrs = (u32temp & 3);
++	switch (max_sq_wrs) {
++		case 0:
++			max_sq_wrs = 4;
++			break;
++		case 1:
++			max_sq_wrs = 16;
++			break;
++		case 2:
++			max_sq_wrs = 32;
++			break;
++		case 3:
++			max_sq_wrs = 512;
++			break;
++	}
++	nesadapter->max_qp_wr = min(max_rq_wrs, max_sq_wrs);
++	nesadapter->max_irrq_wr = (u32temp >> 16) & 3;
++
++	nesadapter->max_sge = 4;
++	nesadapter->max_cqe = 32767;
++
++	if (nes_read_eeprom_values(nesdev, nesadapter)) {
++		printk(KERN_ERR PFX "Unable to read EEPROM data.\n");
++		kfree(nesadapter);
++		return NULL;
++	}
++
++	u32temp = nes_read_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG);
++	nes_write_indexed(nesdev, NES_IDX_TCP_TIMER_CONFIG,
++			(u32temp & 0xff000000) | (nesadapter->tcp_timer_core_clk_divisor & 0x00ffffff));
++
++	/* setup port configuration */
++	if (nesadapter->port_count == 1) {
++		u32temp = 0x00000000;
++		if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT)
++			nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000002);
++		else
++			nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
++	} else {
++		if (nesadapter->port_count == 2)
++			u32temp = 0x00000044;
++		else
++			u32temp = 0x000000e4;
++		nes_write_indexed(nesdev, NES_IDX_TX_POOL_SIZE, 0x00000003);
++	}
++
++	nes_write_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT, u32temp);
++	nes_debug(NES_DBG_INIT, "Probe time, LOG2PHY=%u\n",
++			nes_read_indexed(nesdev, NES_IDX_NIC_LOGPORT_TO_PHYPORT));
++
++	spin_lock_init(&nesadapter->resource_lock);
++	spin_lock_init(&nesadapter->phy_lock);
++	spin_lock_init(&nesadapter->pbl_lock);
++	spin_lock_init(&nesadapter->periodic_timer_lock);
++
++	INIT_LIST_HEAD(&nesadapter->nesvnic_list[0]);
++	INIT_LIST_HEAD(&nesadapter->nesvnic_list[1]);
++	INIT_LIST_HEAD(&nesadapter->nesvnic_list[2]);
++	INIT_LIST_HEAD(&nesadapter->nesvnic_list[3]);
++
++	if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
++		u32 pcs_control_status0, pcs_control_status1;
++		u32 reset_value;
++		u32 i = 0;
++		u32 int_cnt = 0;
++		u32 ext_cnt = 0;
++		unsigned long flags;
++		u32 j = 0;
++
++		pcs_control_status0 = nes_read_indexed(nesdev,
++			NES_IDX_PHY_PCS_CONTROL_STATUS0);
++		pcs_control_status1 = nes_read_indexed(nesdev,
++			NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
++
++		for (i = 0; i < NES_MAX_LINK_CHECK; i++) {
++			pcs_control_status0 = nes_read_indexed(nesdev,
++					NES_IDX_PHY_PCS_CONTROL_STATUS0);
++			pcs_control_status1 = nes_read_indexed(nesdev,
++					NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
++			if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))
++			    || (0x0F000100 == (pcs_control_status1 & 0x0F000100)))
++				int_cnt++;
++			msleep(1);
++		}
++		if (int_cnt > 1) {
++			spin_lock_irqsave(&nesadapter->phy_lock, flags);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
++			mh_detected++;
++			reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
++			reset_value |= 0x0000003d;
++			nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
++
++			while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
++				& 0x00000040) != 0x00000040) && (j++ < 5000));
++			spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++
++			pcs_control_status0 = nes_read_indexed(nesdev,
++					NES_IDX_PHY_PCS_CONTROL_STATUS0);
++			pcs_control_status1 = nes_read_indexed(nesdev,
++					NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
++
++			for (i = 0; i < NES_MAX_LINK_CHECK; i++) {
++				pcs_control_status0 = nes_read_indexed(nesdev,
++					NES_IDX_PHY_PCS_CONTROL_STATUS0);
++				pcs_control_status1 = nes_read_indexed(nesdev,
++					NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
++				if ((0x0F000100 == (pcs_control_status0 & 0x0F000100))
++					|| (0x0F000100 == (pcs_control_status1 & 0x0F000100))) {
++					if (++ext_cnt > int_cnt) {
++						spin_lock_irqsave(&nesadapter->phy_lock, flags);
++						nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1,
++								0x0000F0C8);
++						mh_detected++;
++						reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
++						reset_value |= 0x0000003d;
++						nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
++
++						while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
++							& 0x00000040) != 0x00000040) && (j++ < 5000));
++						spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++						break;
++					}
++				}
++				msleep(1);
++			}
++		}
++	}
++
++	if (nesadapter->hw_rev == NE020_REV) {
++		init_timer(&nesadapter->mh_timer);
++		nesadapter->mh_timer.function = nes_mh_fix;
++		nesadapter->mh_timer.expires = jiffies + (HZ/5);  /* 1 second */
++		nesadapter->mh_timer.data = (unsigned long)nesdev;
++		add_timer(&nesadapter->mh_timer);
++	} else {
++		nes_write32(nesdev->regs+NES_INTF_INT_STAT, 0x0f000000);
++	}
++
++	init_timer(&nesadapter->lc_timer);
++	nesadapter->lc_timer.function = nes_clc;
++	nesadapter->lc_timer.expires = jiffies + 3600 * HZ;  /* 1 hour */
++	nesadapter->lc_timer.data = (unsigned long)nesdev;
++	add_timer(&nesadapter->lc_timer);
++
++	list_add_tail(&nesadapter->list, &nes_adapter_list);
++
++	for (func_index = 0; func_index < 8; func_index++) {
++		pci_bus_read_config_word(nesdev->pcidev->bus,
++					PCI_DEVFN(PCI_SLOT(nesdev->pcidev->devfn),
++					func_index), 0, &vendor_id);
++		if (vendor_id == 0xffff)
++			break;
++	}
++	nes_debug(NES_DBG_INIT, "%s %d functions found for %s.\n", __FUNCTION__,
++		func_index, pci_name(nesdev->pcidev));
++	nesadapter->adapter_fcn_count = func_index;
++
++	return nesadapter;
++}
++
++
++/**
++ * nes_reset_adapter_ne020
++ */
++unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode)
++{
++	u32 port_count;
++	u32 u32temp;
++	u32 i;
++
++	u32temp = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
++	port_count = ((u32temp & 0x00000300) >> 8) + 1;
++	/* TODO: assuming that both SERDES are set the same for now */
++	*OneG_Mode = (u32temp & 0x00003c00) ? 0 : 1;
++	nes_debug(NES_DBG_INIT, "Initial Software Reset = 0x%08X, port_count=%u\n",
++			u32temp, port_count);
++	if (*OneG_Mode)
++		nes_debug(NES_DBG_INIT, "Running in 1G mode.\n");
++	u32temp &= 0xff00ffc0;
++	switch (port_count) {
++		case 1:
++			u32temp |= 0x00ee0000;
++			break;
++		case 2:
++			u32temp |= 0x00cc0000;
++			break;
++		case 4:
++			u32temp |= 0x00000000;
++			break;
++		default:
++			return 0;
++			break;
++	}
++
++	/* check and do full reset if needed */
++	if (nes_read_indexed(nesdev, NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8))) {
++		nes_debug(NES_DBG_INIT, "Issuing Full Soft reset = 0x%08X\n", u32temp | 0xd);
++		nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);
++
++		i = 0;
++		while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
++			mdelay(1);
++		if (i >= 10000) {
++			nes_debug(NES_DBG_INIT, "Did not see full soft reset done.\n");
++			return 0;
++		}
++	}
++
++	/* port reset */
++	switch (port_count) {
++		case 1:
++			u32temp |= 0x00ee0010;
++			break;
++		case 2:
++			u32temp |= 0x00cc0030;
++			break;
++		case 4:
++			u32temp |= 0x00000030;
++			break;
++	}
++
++	nes_debug(NES_DBG_INIT, "Issuing Port Soft reset = 0x%08X\n", u32temp | 0xd);
++	nes_write32(nesdev->regs+NES_SOFTWARE_RESET, u32temp | 0xd);
++
++	i = 0;
++	while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET) & 0x00000040) == 0) && i++ < 10000)
++		mdelay(1);
++	if (i >= 10000) {
++		nes_debug(NES_DBG_INIT, "Did not see port soft reset done.\n");
++		return 0;
++	}
++
++	/* serdes 0 */
++	i = 0;
++	while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
++			& 0x0000000f)) != 0x0000000f) && i++ < 5000)
++		mdelay(1);
++	if (i >= 5000) {
++		nes_debug(NES_DBG_INIT, "Serdes 0 not ready, status=%x\n", u32temp);
++		return 0;
++	}
++
++	/* serdes 1 */
++	if (port_count > 1) {
++		i = 0;
++		while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
++				& 0x0000000f)) != 0x0000000f) && i++ < 5000)
++			mdelay(1);
++		if (i >= 5000) {
++			nes_debug(NES_DBG_INIT, "Serdes 1 not ready, status=%x\n", u32temp);
++			return 0;
++		}
++	}
++
++
++
++	i = 0;
++	while ((nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS) != 0x80) && i++ < 10000)
++		mdelay(1);
++	if (i >= 10000) {
++		printk(KERN_ERR PFX "Internal CPU not ready, status = %02X\n",
++				nes_read_indexed(nesdev, NES_IDX_INT_CPU_STATUS));
++		return 0;
++	}
++
++	return port_count;
++}
++
++
++/**
++ * nes_init_serdes
++ */
++int nes_init_serdes(struct nes_device *nesdev, u8 hw_rev, u8 port_count, u8  OneG_Mode)
++{
++	int i;
++	u32 u32temp;
++
++	if (hw_rev != NE020_REV) {
++		/* init serdes 0 */
++
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000FF);
++		if (!OneG_Mode)
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0, 0x11110000);
++		if (port_count > 1) {
++			/* init serdes 1 */
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000FF);
++			if (!OneG_Mode)
++				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1, 0x11110000);
++			}
++	} else {
++		/* init serdes 0 */
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
++		i = 0;
++		while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0)
++				& 0x0000000f)) != 0x0000000f) && i++ < 5000)
++			mdelay(1);
++		if (i >= 5000) {
++			nes_debug(NES_DBG_PHY, "Init: serdes 0 not ready, status=%x\n", u32temp);
++			return 1;
++		}
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000);
++		if (OneG_Mode)
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222);
++		else
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222);
++
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff);
++		if (port_count > 1) {
++			/* init serdes 1 */
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x00000048);
++			i = 0;
++			while (((u32temp = (nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS1)
++				& 0x0000000f)) != 0x0000000f) && (i++ < 5000))
++				mdelay(1);
++			if (i >= 5000) {
++				printk("%s: Init: serdes 1 not ready, status=%x\n", __FUNCTION__, u32temp);
++				/* return 1; */
++			}
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP1, 0x000bdef7);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE1, 0x9ce73000);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE1, 0x0ff00000);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET1, 0x00000000);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS1, 0x00000000);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1, 0x00000000);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL1, 0xf0002222);
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL1, 0x000000ff);
++		}
++	}
++	return 0;
++}
++
++
++/**
++ * nes_init_csr_ne020
++ * Initialize registers for ne020 hardware
++ */
++void nes_init_csr_ne020(struct nes_device *nesdev, u8 hw_rev, u8 port_count)
++{
++	u32 u32temp;
++
++	nes_debug(NES_DBG_INIT, "port_count=%d\n", port_count);
++
++	nes_write_indexed(nesdev, 0x000001E4, 0x00000007);
++	/* nes_write_indexed(nesdev, 0x000001E8, 0x000208C4); */
++	nes_write_indexed(nesdev, 0x000001E8, 0x00020874);
++	nes_write_indexed(nesdev, 0x000001D8, 0x00048002);
++	/* nes_write_indexed(nesdev, 0x000001D8, 0x0004B002); */
++	nes_write_indexed(nesdev, 0x000001FC, 0x00050005);
++	nes_write_indexed(nesdev, 0x00000600, 0x55555555);
++	nes_write_indexed(nesdev, 0x00000604, 0x55555555);
++
++	/* TODO: move these MAC register settings to NIC bringup */
++	nes_write_indexed(nesdev, 0x00002000, 0x00000001);
++	nes_write_indexed(nesdev, 0x00002004, 0x00000001);
++	nes_write_indexed(nesdev, 0x00002008, 0x0000FFFF);
++	nes_write_indexed(nesdev, 0x0000200C, 0x00000001);
++	nes_write_indexed(nesdev, 0x00002010, 0x000003c1);
++	nes_write_indexed(nesdev, 0x0000201C, 0x75345678);
++	if (port_count > 1) {
++		nes_write_indexed(nesdev, 0x00002200, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002204, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002208, 0x0000FFFF);
++		nes_write_indexed(nesdev, 0x0000220C, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002210, 0x000003c1);
++		nes_write_indexed(nesdev, 0x0000221C, 0x75345678);
++		nes_write_indexed(nesdev, 0x00000908, 0x20000001);
++	}
++	if (port_count > 2) {
++		nes_write_indexed(nesdev, 0x00002400, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002404, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002408, 0x0000FFFF);
++		nes_write_indexed(nesdev, 0x0000240C, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002410, 0x000003c1);
++		nes_write_indexed(nesdev, 0x0000241C, 0x75345678);
++		nes_write_indexed(nesdev, 0x00000910, 0x20000001);
++
++		nes_write_indexed(nesdev, 0x00002600, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002604, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002608, 0x0000FFFF);
++		nes_write_indexed(nesdev, 0x0000260C, 0x00000001);
++		nes_write_indexed(nesdev, 0x00002610, 0x000003c1);
++		nes_write_indexed(nesdev, 0x0000261C, 0x75345678);
++		nes_write_indexed(nesdev, 0x00000918, 0x20000001);
++	}
++
++	nes_write_indexed(nesdev, 0x00005000, 0x00018000);
++	/* nes_write_indexed(nesdev, 0x00005000, 0x00010000); */
++	nes_write_indexed(nesdev, 0x00005004, 0x00020001);
++	nes_write_indexed(nesdev, 0x00005008, 0x1F1F1F1F);
++	nes_write_indexed(nesdev, 0x00005010, 0x1F1F1F1F);
++	nes_write_indexed(nesdev, 0x00005018, 0x1F1F1F1F);
++	nes_write_indexed(nesdev, 0x00005020, 0x1F1F1F1F);
++	nes_write_indexed(nesdev, 0x00006090, 0xFFFFFFFF);
++
++	/* TODO: move this to code, get from EEPROM */
++	nes_write_indexed(nesdev, 0x00000900, 0x20000001);
++	nes_write_indexed(nesdev, 0x000060C0, 0x0000028e);
++	nes_write_indexed(nesdev, 0x000060C8, 0x00000020);
++														//
++	nes_write_indexed(nesdev, 0x000001EC, 0x7b2625a0);
++	/* nes_write_indexed(nesdev, 0x000001EC, 0x5f2625a0); */
++
++	if (hw_rev != NE020_REV) {
++		u32temp = nes_read_indexed(nesdev, 0x000008e8);
++		u32temp |= 0x80000000;
++		nes_write_indexed(nesdev, 0x000008e8, u32temp);
++		u32temp = nes_read_indexed(nesdev, 0x000021f8);
++		u32temp &= 0x7fffffff;
++		u32temp |= 0x7fff0010;
++		nes_write_indexed(nesdev, 0x000021f8, u32temp);
++	}
++}
++
++
++/**
++ * nes_destroy_adapter - destroy the adapter structure
++ */
++void nes_destroy_adapter(struct nes_adapter *nesadapter)
++{
++	struct nes_adapter *tmp_adapter;
++
++	list_for_each_entry(tmp_adapter, &nes_adapter_list, list) {
++		nes_debug(NES_DBG_SHUTDOWN, "Nes Adapter list entry = 0x%p.\n",
++				tmp_adapter);
++	}
++
++	nesadapter->ref_count--;
++	if (!nesadapter->ref_count) {
++		if (nesadapter->hw_rev == NE020_REV) {
++			del_timer(&nesadapter->mh_timer);
++		}
++		del_timer(&nesadapter->lc_timer);
++
++		list_del(&nesadapter->list);
++		kfree(nesadapter);
++	}
++}
++
++
++/**
++ * nes_init_cqp
++ */
++int nes_init_cqp(struct nes_device *nesdev)
++{
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_cqp_qp_context *cqp_qp_context;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_hw_ceq *ceq;
++	struct nes_hw_ceq *nic_ceq;
++	struct nes_hw_aeq *aeq;
++	void *vmem;
++	dma_addr_t pmem;
++	u32 count=0;
++	u32 cqp_head;
++	u64 u64temp;
++	u32 u32temp;
++
++	/* allocate CQP memory */
++	/* Need to add max_cq to the aeq size once cq overflow checking is added back */
++	/* SQ is 512 byte aligned, others are 256 byte aligned */
++	nesdev->cqp_mem_size = 512 +
++			(sizeof(struct nes_hw_cqp_wqe) * NES_CQP_SQ_SIZE) +
++			(sizeof(struct nes_hw_cqe) * NES_CCQ_SIZE) +
++			max(((u32)sizeof(struct nes_hw_ceqe) * NES_CCEQ_SIZE), (u32)256) +
++			max(((u32)sizeof(struct nes_hw_ceqe) * NES_NIC_CEQ_SIZE), (u32)256) +
++			(sizeof(struct nes_hw_aeqe) * nesadapter->max_qp) +
++			sizeof(struct nes_hw_cqp_qp_context);
++
++	nesdev->cqp_vbase = pci_alloc_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
++			&nesdev->cqp_pbase);
++	if (!nesdev->cqp_vbase) {
++		nes_debug(NES_DBG_INIT, "Unable to allocate memory for host descriptor rings\n");
++		return -ENOMEM;
++	}
++	memset(nesdev->cqp_vbase, 0, nesdev->cqp_mem_size);
++
++	/* Allocate a twice the number of CQP requests as the SQ size */
++	nesdev->nes_cqp_requests = kzalloc(sizeof(struct nes_cqp_request) *
++			2 * NES_CQP_SQ_SIZE, GFP_KERNEL);
++	if (nesdev->nes_cqp_requests == NULL) {
++		nes_debug(NES_DBG_INIT, "Unable to allocate memory CQP request entries.\n");
++		pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
++				nesdev->cqp.sq_pbase);
++		return -ENOMEM;
++	}
++
++	nes_debug(NES_DBG_INIT, "Allocated CQP structures at %p (phys = %016lX), size = %u.\n",
++			nesdev->cqp_vbase, (unsigned long)nesdev->cqp_pbase, nesdev->cqp_mem_size);
++
++	spin_lock_init(&nesdev->cqp.lock);
++	init_waitqueue_head(&nesdev->cqp.waitq);
++
++	/* Setup Various Structures */
++	vmem = (void *)(((unsigned long)nesdev->cqp_vbase + (512 - 1)) &
++			~(unsigned long)(512 - 1));
++	pmem = (dma_addr_t)(((unsigned long long)nesdev->cqp_pbase + (512 - 1)) &
++			~(unsigned long long)(512 - 1));
++
++	nesdev->cqp.sq_vbase = vmem;
++	nesdev->cqp.sq_pbase = pmem;
++	nesdev->cqp.sq_size = NES_CQP_SQ_SIZE;
++	nesdev->cqp.sq_head = 0;
++	nesdev->cqp.sq_tail = 0;
++	nesdev->cqp.qp_id = PCI_FUNC(nesdev->pcidev->devfn);
++
++	vmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
++	pmem += (sizeof(struct nes_hw_cqp_wqe) * nesdev->cqp.sq_size);
++
++	nesdev->ccq.cq_vbase = vmem;
++	nesdev->ccq.cq_pbase = pmem;
++	nesdev->ccq.cq_size = NES_CCQ_SIZE;
++	nesdev->ccq.cq_head = 0;
++	nesdev->ccq.ce_handler = nes_cqp_ce_handler;
++	nesdev->ccq.cq_number = PCI_FUNC(nesdev->pcidev->devfn);
++
++	vmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
++	pmem += (sizeof(struct nes_hw_cqe) * nesdev->ccq.cq_size);
++
++	nesdev->ceq_index = PCI_FUNC(nesdev->pcidev->devfn);
++	ceq = &nesadapter->ceq[nesdev->ceq_index];
++	ceq->ceq_vbase = vmem;
++	ceq->ceq_pbase = pmem;
++	ceq->ceq_size = NES_CCEQ_SIZE;
++	ceq->ceq_head = 0;
++
++	vmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
++	pmem += max(((u32)sizeof(struct nes_hw_ceqe) * ceq->ceq_size), (u32)256);
++
++	nesdev->nic_ceq_index = PCI_FUNC(nesdev->pcidev->devfn) + 8;
++	nic_ceq = &nesadapter->ceq[nesdev->nic_ceq_index];
++	nic_ceq->ceq_vbase = vmem;
++	nic_ceq->ceq_pbase = pmem;
++	nic_ceq->ceq_size = NES_NIC_CEQ_SIZE;
++	nic_ceq->ceq_head = 0;
++
++	vmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
++	pmem += max(((u32)sizeof(struct nes_hw_ceqe) * nic_ceq->ceq_size), (u32)256);
++
++	aeq = &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)];
++	aeq->aeq_vbase = vmem;
++	aeq->aeq_pbase = pmem;
++	aeq->aeq_size = nesadapter->max_qp;
++	aeq->aeq_head = 0;
++
++	/* Setup QP Context */
++	vmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
++	pmem += (sizeof(struct nes_hw_aeqe) * aeq->aeq_size);
++
++	cqp_qp_context = vmem;
++	cqp_qp_context->context_words[0] =
++			cpu_to_le32((PCI_FUNC(nesdev->pcidev->devfn) << 12) + (2 << 10));
++	cqp_qp_context->context_words[1] = 0;
++	cqp_qp_context->context_words[2] = cpu_to_le32((u32)nesdev->cqp.sq_pbase);
++	cqp_qp_context->context_words[3] = cpu_to_le32(((u64)nesdev->cqp.sq_pbase) >> 32);
++
++
++	/* Write the address to Create CQP */
++	if ((sizeof(dma_addr_t) > 4)) {
++		nes_write_indexed(nesdev,
++				NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
++				((u64)pmem) >> 32);
++	} else {
++		nes_write_indexed(nesdev,
++				NES_IDX_CREATE_CQP_HIGH + (PCI_FUNC(nesdev->pcidev->devfn) * 8), 0);
++	}
++	nes_write_indexed(nesdev,
++			NES_IDX_CREATE_CQP_LOW + (PCI_FUNC(nesdev->pcidev->devfn) * 8),
++			(u32)pmem);
++
++	INIT_LIST_HEAD(&nesdev->cqp_avail_reqs);
++	INIT_LIST_HEAD(&nesdev->cqp_pending_reqs);
++
++	for (count = 0; count < 2*NES_CQP_SQ_SIZE; count++) {
++		init_waitqueue_head(&nesdev->nes_cqp_requests[count].waitq);
++		list_add_tail(&nesdev->nes_cqp_requests[count].list, &nesdev->cqp_avail_reqs);
++	}
++
++	/* Write Create CCQ WQE */
++	cqp_head = nesdev->cqp.sq_head++;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++			(NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
++			NES_CQP_CQ_CHK_OVERFLOW | ((u32)nesdev->ccq.cq_size << 16)));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
++			    (nesdev->ccq.cq_number |
++			     ((u32)nesdev->ceq_index << 16)));
++	u64temp = (u64)nesdev->ccq.cq_pbase;
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
++	u64temp = (unsigned long)&nesdev->ccq;
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =
++			cpu_to_le32((u32)(u64temp >> 1));
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
++			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
++
++	/* Write Create CEQ WQE */
++	cqp_head = nesdev->cqp.sq_head++;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++			    (NES_CQP_CREATE_CEQ + ((u32)nesdev->ceq_index << 8)));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, ceq->ceq_size);
++	u64temp = (u64)ceq->ceq_pbase;
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
++
++	/* Write Create AEQ WQE */
++	cqp_head = nesdev->cqp.sq_head++;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++			(NES_CQP_CREATE_AEQ + ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8)));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX, aeq->aeq_size);
++	u64temp = (u64)aeq->aeq_pbase;
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
++
++	/* Write Create NIC CEQ WQE */
++	cqp_head = nesdev->cqp.sq_head++;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++			(NES_CQP_CREATE_CEQ + ((u32)nesdev->nic_ceq_index << 8)));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX, nic_ceq->ceq_size);
++	u64temp = (u64)nic_ceq->ceq_pbase;
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
++
++	/* Poll until CCQP done */
++	count = 0;
++	do {
++		if (count++ > 1000) {
++			printk(KERN_ERR PFX "Error creating CQP\n");
++			pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
++					nesdev->cqp_vbase, nesdev->cqp_pbase);
++			return -1;
++		}
++		udelay(10);
++	} while (!(nes_read_indexed(nesdev,
++			NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn) * 8)) & (1 << 8)));
++
++	nes_debug(NES_DBG_INIT, "CQP Status = 0x%08X\n", nes_read_indexed(nesdev,
++			NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
++
++	u32temp = 0x04800000;
++	nes_write32(nesdev->regs+NES_WQE_ALLOC, u32temp | nesdev->cqp.qp_id);
++
++	/* wait for the CCQ, CEQ, and AEQ to get created */
++	count = 0;
++	do {
++		if (count++ > 1000) {
++			printk(KERN_ERR PFX "Error creating CCQ, CEQ, and AEQ\n");
++			pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size,
++					nesdev->cqp_vbase, nesdev->cqp_pbase);
++			return -1;
++		}
++		udelay(10);
++	} while (((nes_read_indexed(nesdev,
++			NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15<<8)) != (15<<8)));
++
++	/* dump the QP status value */
++	nes_debug(NES_DBG_INIT, "QP Status = 0x%08X\n", nes_read_indexed(nesdev,
++			NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
++
++	nesdev->cqp.sq_tail++;
++
++	return 0;
++}
++
++
++/**
++ * nes_destroy_cqp
++ */
++int nes_destroy_cqp(struct nes_device *nesdev)
++{
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	u32 count = 0;
++	u32 cqp_head;
++	unsigned long flags;
++
++	do {
++		if (count++ > 1000)
++			break;
++		udelay(10);
++	} while (!(nesdev->cqp.sq_head == nesdev->cqp.sq_tail));
++
++	/* Reset CCQ */
++	nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_RESET |
++			nesdev->ccq.cq_number);
++
++	/* Disable device interrupts */
++	nes_write32(nesdev->regs+NES_INT_MASK, 0x7fffffff);
++
++	spin_lock_irqsave(&nesdev->cqp.lock, flags);
++
++	/* Destroy the AEQ */
++	cqp_head = nesdev->cqp.sq_head++;
++	nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_AEQ |
++			((u32)PCI_FUNC(nesdev->pcidev->devfn) << 8));
++	cqp_wqe->wqe_words[NES_CQP_WQE_COMP_CTX_HIGH_IDX] = 0;
++
++	/* Destroy the NIC CEQ */
++	cqp_head = nesdev->cqp.sq_head++;
++	nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
++			((u32)nesdev->nic_ceq_index << 8));
++
++	/* Destroy the CEQ */
++	cqp_head = nesdev->cqp.sq_head++;
++	nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CEQ |
++			(nesdev->ceq_index << 8));
++
++	/* Destroy the CCQ */
++	cqp_head = nesdev->cqp.sq_head++;
++	nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_CQ);
++	cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->ccq.cq_number |
++			((u32)nesdev->ceq_index << 16));
++
++	/* Destroy CQP */
++	cqp_head = nesdev->cqp.sq_head++;
++	nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_DESTROY_QP |
++			NES_CQP_QP_TYPE_CQP);
++	cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesdev->cqp.qp_id);
++
++	barrier();
++	/* Ring doorbell (5 WQEs) */
++	nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x05800000 | nesdev->cqp.qp_id);
++
++	spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++
++	/* wait for the CCQ, CEQ, and AEQ to get destroyed */
++	count = 0;
++	do {
++		if (count++ > 1000) {
++			printk(KERN_ERR PFX "Function%d: Error destroying CCQ, CEQ, and AEQ\n",
++					PCI_FUNC(nesdev->pcidev->devfn));
++			break;
++		}
++		udelay(10);
++	} while (((nes_read_indexed(nesdev,
++			NES_IDX_QP_CONTROL + (PCI_FUNC(nesdev->pcidev->devfn)*8)) & (15 << 8)) != 0));
++
++	/* dump the QP status value */
++	nes_debug(NES_DBG_SHUTDOWN, "Function%d: QP Status = 0x%08X\n",
++			PCI_FUNC(nesdev->pcidev->devfn),
++			nes_read_indexed(nesdev,
++			NES_IDX_QP_CONTROL+(PCI_FUNC(nesdev->pcidev->devfn)*8)));
++
++	kfree(nesdev->nes_cqp_requests);
++
++	/* Free the control structures */
++	pci_free_consistent(nesdev->pcidev, nesdev->cqp_mem_size, nesdev->cqp.sq_vbase,
++			nesdev->cqp.sq_pbase);
++
++	return 0;
++}
++
++
++/**
++ * nes_init_phy
++ */
++int nes_init_phy(struct nes_device *nesdev)
++{
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 counter = 0;
++	u32 mac_index = nesdev->mac_index;
++	u32 tx_config;
++	u16 phy_data;
++
++	if (nesadapter->OneG_Mode) {
++		nes_debug(NES_DBG_PHY, "1G PHY, mac_index = %d.\n", mac_index);
++		if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_1G) {
++			printk(PFX "%s: Programming mdc config for 1G\n", __FUNCTION__);
++			tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
++			tx_config |= 0x04;
++			nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
++		}
++
++		nes_read_1G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 1 phy address %u = 0x%X.\n",
++				nesadapter->phy_index[mac_index], phy_data);
++		nes_write_1G_phy_reg(nesdev, 23, nesadapter->phy_index[mac_index],  0xb000);
++
++		/* Reset the PHY */
++		nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], 0x8000);
++		udelay(100);
++		counter = 0;
++		do {
++			nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data);
++			nes_debug(NES_DBG_PHY, "Phy data from register 0 = 0x%X.\n", phy_data);
++			if (counter++ > 100) break;
++		} while (phy_data & 0x8000);
++
++		/* Setting no phy loopback */
++		phy_data &= 0xbfff;
++		phy_data |= 0x1140;
++		nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index],  phy_data);
++		nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0 = 0x%X.\n", phy_data);
++
++		nes_read_1G_phy_reg(nesdev, 0x17, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x17 = 0x%X.\n", phy_data);
++
++		nes_read_1G_phy_reg(nesdev, 0x1e, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x1e = 0x%X.\n", phy_data);
++
++		/* Setting the interrupt mask */
++		nes_read_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x19 = 0x%X.\n", phy_data);
++		nes_write_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], 0xffee);
++
++		nes_read_1G_phy_reg(nesdev, 0x19, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x19 = 0x%X.\n", phy_data);
++
++		/* turning on flow control */
++		nes_read_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x4 = 0x%X.\n", phy_data);
++		nes_write_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index],
++				(phy_data & ~(0x03E0)) | 0xc00);
++		/* nes_write_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index],
++				phy_data | 0xc00); */
++		nes_read_1G_phy_reg(nesdev, 4, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x4 = 0x%X.\n", phy_data);
++
++		nes_read_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x9 = 0x%X.\n", phy_data);
++		/* Clear Half duplex */
++		nes_write_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index],
++				phy_data & ~(0x0100));
++		nes_read_1G_phy_reg(nesdev, 9, nesadapter->phy_index[mac_index], &phy_data);
++		nes_debug(NES_DBG_PHY, "Phy data from register 0x9 = 0x%X.\n", phy_data);
++
++		nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], &phy_data);
++		nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[mac_index], phy_data | 0x0300);
++	} else {
++		if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) {
++			/* setup 10G MDIO operation */
++			tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
++			tx_config |= 0x14;
++			nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
++		}
++	}
++	return 0;
++}
 +
- 	work = kmalloc(sizeof *work + sizeof(struct ib_sa_path_rec) * paths,
- 		       GFP_KERNEL);
- 	if (!work) {
-@@ -3204,7 +3343,7 @@ static void cm_recv_handler(struct ib_mad_agent *mad_agent,
- 	INIT_DELAYED_WORK(&work->work, cm_work_handler);
- 	work->cm_event.event = event;
- 	work->mad_recv_wc = mad_recv_wc;
--	work->port = (struct cm_port *)mad_agent->context;
-+	work->port = port;
- 	queue_delayed_work(cm.wq, &work->work, 0);
- }
- 
-@@ -3379,6 +3518,108 @@ static void cm_get_ack_delay(struct cm_device *cm_dev)
- 		cm_dev->ack_delay = attr.local_ca_ack_delay;
- }
- 
-+static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
-+			       char *buf)
++
++/**
++ * nes_replenish_nic_rq
++ */
++static void nes_replenish_nic_rq(struct nes_vnic *nesvnic)
 +{
-+	struct cm_counter_group *group;
-+	struct cm_counter_attribute *cm_attr;
++	unsigned long flags;
++	dma_addr_t bus_address;
++	struct sk_buff *skb;
++	struct nes_hw_nic_rq_wqe *nic_rqe;
++	struct nes_hw_nic *nesnic;
++	struct nes_device *nesdev;
++	u32 rx_wqes_posted = 0;
++
++	nesnic = &nesvnic->nic;
++	nesdev = nesvnic->nesdev;
++	spin_lock_irqsave(&nesnic->rq_lock, flags);
++	if (nesnic->replenishing_rq !=0) {
++		if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
++				(atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
++			atomic_set(&nesvnic->rx_skb_timer_running, 1);
++			spin_unlock_irqrestore(&nesnic->rq_lock, flags);
++			nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2);	/* 1/2 second */
++			add_timer(&nesvnic->rq_wqes_timer);
++		} else
++		spin_unlock_irqrestore(&nesnic->rq_lock, flags);
++		return;
++	}
++	nesnic->replenishing_rq = 1;
++	spin_unlock_irqrestore(&nesnic->rq_lock, flags);
++	do {
++		skb = dev_alloc_skb(nesvnic->max_frame_size);
++		if (skb) {
++			skb->dev = nesvnic->netdev;
 +
-+	group = container_of(obj, struct cm_counter_group, obj);
-+	cm_attr = container_of(attr, struct cm_counter_attribute, attr);
++			bus_address = pci_map_single(nesdev->pcidev,
++					skb->data, nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
 +
-+	return sprintf(buf, "%ld\n",
-+		       atomic_long_read(&group->counter[cm_attr->index]));
++			nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_head];
++			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] =
++					cpu_to_le32(nesvnic->max_frame_size);
++			nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
++			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] =
++					cpu_to_le32((u32)bus_address);
++			nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] =
++					cpu_to_le32((u32)((u64)bus_address >> 32));
++			nesnic->rx_skb[nesnic->rq_head] = skb;
++			nesnic->rq_head++;
++			nesnic->rq_head &= nesnic->rq_size - 1;
++			atomic_dec(&nesvnic->rx_skbs_needed);
++			barrier();
++			if (++rx_wqes_posted == 255) {
++				nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
++				rx_wqes_posted = 0;
++			}
++		} else {
++			spin_lock_irqsave(&nesnic->rq_lock, flags);
++			if (((nesnic->rq_size-1) == atomic_read(&nesvnic->rx_skbs_needed)) &&
++					(atomic_read(&nesvnic->rx_skb_timer_running) == 0)) {
++				atomic_set(&nesvnic->rx_skb_timer_running, 1);
++				spin_unlock_irqrestore(&nesnic->rq_lock, flags);
++				nesvnic->rq_wqes_timer.expires = jiffies + (HZ/2);	/* 1/2 second */
++				add_timer(&nesvnic->rq_wqes_timer);
++			} else
++				spin_unlock_irqrestore(&nesnic->rq_lock, flags);
++			break;
++		}
++	} while (atomic_read(&nesvnic->rx_skbs_needed));
++	barrier();
++	if (rx_wqes_posted)
++		nes_write32(nesdev->regs+NES_WQE_ALLOC, (rx_wqes_posted << 24) | nesnic->qp_id);
++	nesnic->replenishing_rq = 0;
 +}
 +
-+static struct sysfs_ops cm_counter_ops = {
-+	.show = cm_show_counter
-+};
 +
-+static struct kobj_type cm_counter_obj_type = {
-+	.sysfs_ops = &cm_counter_ops,
-+	.default_attrs = cm_counter_default_attrs
-+};
++/**
++ * nes_rq_wqes_timeout
++ */
++static void nes_rq_wqes_timeout(unsigned long parm)
++{
++	struct nes_vnic *nesvnic = (struct nes_vnic *)parm;
++	printk("%s: Timer fired.\n", __FUNCTION__);
++	atomic_set(&nesvnic->rx_skb_timer_running, 0);
++	if (atomic_read(&nesvnic->rx_skbs_needed))
++		nes_replenish_nic_rq(nesvnic);
++}
 +
-+static void cm_release_port_obj(struct kobject *obj)
++
++/**
++ * nes_init_nic_qp
++ */
++int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev)
 +{
-+	struct cm_port *cm_port;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_hw_nic_sq_wqe *nic_sqe;
++	struct nes_hw_nic_qp_context *nic_context;
++	struct sk_buff *skb;
++	struct nes_hw_nic_rq_wqe *nic_rqe;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	unsigned long flags;
++	void *vmem;
++	dma_addr_t pmem;
++	u64 u64temp;
++	int ret;
++	u32 cqp_head;
++	u32 counter;
++	u32 wqe_count;
++	u8 jumbomode=0;
++
++	/* Allocate fragment, SQ, RQ, and CQ; Reuse CEQ based on the PCI function */
++	nesvnic->nic_mem_size = 256 +
++			(NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag)) +
++			(NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe)) +
++			(NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe)) +
++			(NES_NIC_WQ_SIZE * 2 * sizeof(struct nes_hw_nic_cqe)) +
++			sizeof(struct nes_hw_nic_qp_context);
++
++	nesvnic->nic_vbase = pci_alloc_consistent(nesdev->pcidev, nesvnic->nic_mem_size,
++			&nesvnic->nic_pbase);
++	if (!nesvnic->nic_vbase) {
++		nes_debug(NES_DBG_INIT, "Unable to allocate memory for NIC host descriptor rings\n");
++		return -ENOMEM;
++	}
++	memset(nesvnic->nic_vbase, 0, nesvnic->nic_mem_size);
++	nes_debug(NES_DBG_INIT, "Allocated NIC QP structures at %p (phys = %016lX), size = %u.\n",
++			nesvnic->nic_vbase, (unsigned long)nesvnic->nic_pbase, nesvnic->nic_mem_size);
++
++	vmem = (void *)(((unsigned long)nesvnic->nic_vbase + (256 - 1)) &
++			~(unsigned long)(256 - 1));
++	pmem = (dma_addr_t)(((unsigned long long)nesvnic->nic_pbase + (256 - 1)) &
++			~(unsigned long long)(256 - 1));
++
++	/* Setup the first Fragment buffers */
++	nesvnic->nic.first_frag_vbase = vmem;
++
++	for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
++		nesvnic->nic.frag_paddr[counter] = pmem;
++		pmem += sizeof(struct nes_first_frag);
++	}
++
++	/* setup the SQ */
++	vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_first_frag));
++
++	nesvnic->nic.sq_vbase = (void *)vmem;
++	nesvnic->nic.sq_pbase = pmem;
++	nesvnic->nic.sq_head = 0;
++	nesvnic->nic.sq_tail = 0;
++	nesvnic->nic.sq_size = NES_NIC_WQ_SIZE;
++	for (counter = 0; counter < NES_NIC_WQ_SIZE; counter++) {
++		nic_sqe = &nesvnic->nic.sq_vbase[counter];
++		nic_sqe->wqe_words[NES_NIC_SQ_WQE_MISC_IDX] =
++				cpu_to_le32(NES_NIC_SQ_WQE_DISABLE_CHKSUM |
++				NES_NIC_SQ_WQE_COMPLETION);
++		nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX] =
++				cpu_to_le32((u32)NES_FIRST_FRAG_SIZE << 16);
++		nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX] =
++				cpu_to_le32((u32)nesvnic->nic.frag_paddr[counter]);
++		nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX] =
++				cpu_to_le32((u32)((u64)nesvnic->nic.frag_paddr[counter] >> 32));
++	}
++
++	nesvnic->get_cqp_request = nes_get_cqp_request;
++	nesvnic->post_cqp_request = nes_post_cqp_request;
++	nesvnic->mcrq_mcast_filter = NULL;
++
++	spin_lock_init(&nesvnic->nic.sq_lock);
++	spin_lock_init(&nesvnic->nic.rq_lock);
++
++	/* setup the RQ */
++	vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
++	pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_sq_wqe));
++
++
++	nesvnic->nic.rq_vbase = vmem;
++	nesvnic->nic.rq_pbase = pmem;
++	nesvnic->nic.rq_head = 0;
++	nesvnic->nic.rq_tail = 0;
++	nesvnic->nic.rq_size = NES_NIC_WQ_SIZE;
++
++	/* setup the CQ */
++	vmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
++	pmem += (NES_NIC_WQ_SIZE * sizeof(struct nes_hw_nic_rq_wqe));
 +
-+	printk(KERN_ERR "free cm port\n");
++	if (nesdev->nesadapter->netdev_count > 2)
++		nesvnic->mcrq_qp_id = nesvnic->nic_index + 32;
++	else
++		nesvnic->mcrq_qp_id = nesvnic->nic.qp_id + 4;
 +
-+	cm_port = container_of(obj, struct cm_port, port_obj);
-+	kfree(cm_port);
++	nesvnic->nic_cq.cq_vbase = vmem;
++	nesvnic->nic_cq.cq_pbase = pmem;
++	nesvnic->nic_cq.cq_head = 0;
++	nesvnic->nic_cq.cq_size = NES_NIC_WQ_SIZE * 2;
++
++	nesvnic->nic_cq.ce_handler = nes_nic_napi_ce_handler;
++
++	/* Send CreateCQ request to CQP */
++	spin_lock_irqsave(&nesdev->cqp.lock, flags);
++	cqp_head = nesdev->cqp.sq_head;
++
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
++			NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
++			((u32)nesvnic->nic_cq.cq_size << 16));
++	cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(
++			nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16));
++	u64temp = (u64)nesvnic->nic_cq.cq_pbase;
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =  0;
++	u64temp = (unsigned long)&nesvnic->nic_cq;
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =  cpu_to_le32((u32)(u64temp >> 1));
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
++			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
++	if (++cqp_head >= nesdev->cqp.sq_size)
++		cqp_head = 0;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++
++	/* Send CreateQP request to CQP */
++	nic_context = (void *)(&nesvnic->nic_cq.cq_vbase[nesvnic->nic_cq.cq_size]);
++	nic_context->context_words[NES_NIC_CTX_MISC_IDX] =
++			cpu_to_le32((u32)NES_NIC_CTX_SIZE |
++			((u32)PCI_FUNC(nesdev->pcidev->devfn) << 12));
++	nes_debug(NES_DBG_INIT, "RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x%08X, RX_WINDOW_BUFFER_SIZE = 0x%08X\n",
++			nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE),
++			nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE));
++	if (nes_read_indexed(nesdev, NES_IDX_RX_WINDOW_BUFFER_SIZE) != 0) {
++		nic_context->context_words[NES_NIC_CTX_MISC_IDX] |= cpu_to_le32(NES_NIC_BACK_STORE);
++	}
++
++	u64temp = (u64)nesvnic->nic.sq_pbase;
++	nic_context->context_words[NES_NIC_CTX_SQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
++	nic_context->context_words[NES_NIC_CTX_SQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
++	u64temp = (u64)nesvnic->nic.rq_pbase;
++	nic_context->context_words[NES_NIC_CTX_RQ_LOW_IDX] = cpu_to_le32((u32)u64temp);
++	nic_context->context_words[NES_NIC_CTX_RQ_HIGH_IDX] = cpu_to_le32((u32)(u64temp >> 32));
++
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(NES_CQP_CREATE_QP |
++			NES_CQP_QP_TYPE_NIC);
++	cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesvnic->nic.qp_id);
++	u64temp = (u64)nesvnic->nic_cq.cq_pbase +
++			(nesvnic->nic_cq.cq_size * sizeof(struct nes_hw_nic_cqe));
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
++
++	if (++cqp_head >= nesdev->cqp.sq_size)
++		cqp_head = 0;
++	nesdev->cqp.sq_head = cqp_head;
++
++	barrier();
++
++	/* Ring doorbell (2 WQEs) */
++	nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
++
++	spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++	nes_debug(NES_DBG_INIT, "Waiting for create NIC QP%u to complete.\n",
++			nesvnic->nic.qp_id);
++
++	ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_INIT, "Create NIC QP%u completed, wait_event_timeout ret = %u.\n",
++			nesvnic->nic.qp_id, ret);
++	if (!ret) {
++		nes_debug(NES_DBG_INIT, "NIC QP%u create timeout expired\n", nesvnic->nic.qp_id);
++		pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
++				nesvnic->nic_pbase);
++		return -EIO;
++	}
++
++	/* Populate the RQ */
++	for (counter = 0; counter < (NES_NIC_WQ_SIZE - 1); counter++) {
++		skb = dev_alloc_skb(nesvnic->max_frame_size);
++		if (!skb) {
++			nes_debug(NES_DBG_INIT, "%s: out of memory for receive skb\n", netdev->name);
++
++			nes_destroy_nic_qp(nesvnic);
++			return -ENOMEM;
++		}
++
++		skb->dev = netdev;
++
++		pmem = pci_map_single(nesdev->pcidev, skb->data,
++				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
++
++		nic_rqe = &nesvnic->nic.rq_vbase[counter];
++		nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_1_0_IDX] = cpu_to_le32(nesvnic->max_frame_size);
++		nic_rqe->wqe_words[NES_NIC_RQ_WQE_LENGTH_3_2_IDX] = 0;
++		nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX] = cpu_to_le32((u32)pmem);
++		nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX] = cpu_to_le32((u32)((u64)pmem >> 32));
++		nesvnic->nic.rx_skb[counter] = skb;
++	}
++
++	wqe_count = NES_NIC_WQ_SIZE - 1;
++	nesvnic->nic.rq_head = wqe_count;
++	barrier();
++	do {
++		counter = min(wqe_count, ((u32)255));
++		wqe_count -= counter;
++		nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter << 24) | nesvnic->nic.qp_id);
++	} while (wqe_count);
++	init_timer(&nesvnic->rq_wqes_timer);
++	nesvnic->rq_wqes_timer.function = nes_rq_wqes_timeout;
++	nesvnic->rq_wqes_timer.data = (unsigned long)nesvnic;
++	nes_debug(NES_DBG_INIT, "NAPI support Enabled\n");
++
++	if (nesdev->nesadapter->et_use_adaptive_rx_coalesce)
++	{
++		nes_nic_init_timer(nesdev);
++		if (netdev->mtu > 1500)
++			jumbomode = 1;
++                nes_nic_init_timer_defaults(nesdev, jumbomode);
++	}
++
++	return 0;
 +}
 +
-+static struct kobj_type cm_port_obj_type = {
-+	.release = cm_release_port_obj
-+};
 +
-+static void cm_release_dev_obj(struct kobject *obj)
++/**
++ * nes_destroy_nic_qp
++ */
++void nes_destroy_nic_qp(struct nes_vnic *nesvnic)
 +{
-+	struct cm_device *cm_dev;
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_hw_nic_rq_wqe *nic_rqe;
++	u64 wqe_frag;
++	u32 cqp_head;
++	unsigned long flags;
++	int ret;
 +
-+	printk(KERN_ERR "free cm dev\n");
++	/* Free remaining NIC receive buffers */
++	while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) {
++		nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail];
++		wqe_frag = (u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
++		wqe_frag |= ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
++		pci_unmap_single(nesdev->pcidev, (dma_addr_t)wqe_frag,
++				nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
++		dev_kfree_skb(nesvnic->nic.rx_skb[nesvnic->nic.rq_tail++]);
++		nesvnic->nic.rq_tail &= (nesvnic->nic.rq_size - 1);
++	}
++
++	spin_lock_irqsave(&nesdev->cqp.lock, flags);
++
++	/* Destroy NIC QP */
++	cqp_head = nesdev->cqp.sq_head;
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++		(NES_CQP_DESTROY_QP | NES_CQP_QP_TYPE_NIC));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
++		nesvnic->nic.qp_id);
++
++	if (++cqp_head >= nesdev->cqp.sq_size)
++		cqp_head = 0;
++
++	cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++
++	/* Destroy NIC CQ */
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++		(NES_CQP_DESTROY_CQ | ((u32)nesvnic->nic_cq.cq_size << 16)));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
++		(nesvnic->nic_cq.cq_number | ((u32)nesdev->nic_ceq_index << 16)));
 +
-+	cm_dev = container_of(obj, struct cm_device, dev_obj);
-+	kfree(cm_dev);
-+}
++	if (++cqp_head >= nesdev->cqp.sq_size)
++		cqp_head = 0;
 +
-+static struct kobj_type cm_dev_obj_type = {
-+	.release = cm_release_dev_obj
-+};
++	nesdev->cqp.sq_head = cqp_head;
++	barrier();
 +
-+struct class cm_class = {
-+	.name    = "infiniband_cm",
-+};
-+EXPORT_SYMBOL(cm_class);
++	/* Ring doorbell (2 WQEs) */
++	nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x02800000 | nesdev->cqp.qp_id);
 +
-+static void cm_remove_fs_obj(struct kobject *obj)
-+{
-+	kobject_put(obj->parent);
-+	kobject_put(obj);
++	spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++	nes_debug(NES_DBG_SHUTDOWN, "Waiting for CQP, cqp_head=%u, cqp.sq_head=%u,"
++			" cqp.sq_tail=%u, cqp.sq_size=%u\n",
++			cqp_head, nesdev->cqp.sq_head,
++			nesdev->cqp.sq_tail, nesdev->cqp.sq_size);
++
++	ret = wait_event_timeout(nesdev->cqp.waitq, (nesdev->cqp.sq_tail == cqp_head),
++			NES_EVENT_TIMEOUT);
++
++	nes_debug(NES_DBG_SHUTDOWN, "Destroy NIC QP returned, wait_event_timeout ret = %u, cqp_head=%u,"
++			" cqp.sq_head=%u, cqp.sq_tail=%u\n",
++			ret, cqp_head, nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
++	if (!ret) {
++		nes_debug(NES_DBG_SHUTDOWN, "NIC QP%u destroy timeout expired\n",
++				nesvnic->nic.qp_id);
++	}
++
++	pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase,
++			nesvnic->nic_pbase);
 +}
 +
-+static int cm_create_port_fs(struct cm_port *port)
++/**
++ * nes_napi_isr
++ */
++int nes_napi_isr(struct nes_device *nesdev)
 +{
-+	int i, ret;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 int_stat;
 +
-+	ret = kobject_init_and_add(&port->port_obj, &cm_port_obj_type,
-+				   kobject_get(&port->cm_dev->dev_obj),
-+				   "%d", port->port_num);
-+	if (ret) {
-+		kfree(port);
-+		return ret;
++	if (nesdev->napi_isr_ran) {
++		/* interrupt status has already been read in ISR */
++		int_stat = nesdev->int_stat;
++	} else {
++		int_stat = nes_read32(nesdev->regs + NES_INT_STAT);
++		nesdev->int_stat = int_stat;
++		nesdev->napi_isr_ran = 1;
++	}
++
++	int_stat &= nesdev->int_req;
++	/* iff NIC, process here, else wait for DPC */
++	if ((int_stat) && ((int_stat & 0x0000ff00) == int_stat)) {
++		nesdev->napi_isr_ran = 0;
++		nes_write32(nesdev->regs+NES_INT_STAT,
++				(int_stat &
++				~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
++
++		/* Process the CEQs */
++		nes_process_ceq(nesdev, &nesdev->nesadapter->ceq[nesdev->nic_ceq_index]);
++
++		if (unlikely((((nesadapter->et_rx_coalesce_usecs_irq) &&
++					   (!nesadapter->et_use_adaptive_rx_coalesce)) ||
++					  ((nesadapter->et_use_adaptive_rx_coalesce) &&
++					   (nesdev->deepcq_count > nesadapter->et_pkt_rate_low)))) ) {
++			if ((nesdev->int_req & NES_INT_TIMER) == 0) {
++				/* Enable Periodic timer interrupts */
++				nesdev->int_req |= NES_INT_TIMER;
++				/* ack any pending periodic timer interrupts so we don't get an immediate interrupt */
++				/* TODO: need to also ack other unused periodic timer values, get from nesadapter */
++				nes_write32(nesdev->regs+NES_TIMER_STAT,
++						nesdev->timer_int_req  | ~(nesdev->nesadapter->timer_int_req));
++				nes_write32(nesdev->regs+NES_INTF_INT_MASK,
++						~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
++			}
++
++			if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
++			{
++				nes_nic_init_timer(nesdev);
++			}
++			/* Enable interrupts, except CEQs */
++			nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
++		} else {
++			/* Enable interrupts, make sure timer is off */
++			nesdev->int_req &= ~NES_INT_TIMER;
++			nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
++			nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
++			nesadapter->tune_timer.timer_in_use_old = 0;
++		}
++		nesdev->deepcq_count = 0;
++		return 1;
++	} else {
++		return 0;
 +	}
++}
 +
-+	for (i = 0; i < CM_COUNTER_GROUPS; i++) {
-+		ret = kobject_init_and_add(&port->counter_group[i].obj,
-+					   &cm_counter_obj_type,
-+					   kobject_get(&port->port_obj),
-+					   "%s", counter_group_names[i]);
-+		if (ret)
-+			goto error;
++
++/**
++ * nes_dpc
++ */
++void nes_dpc(unsigned long param)
++{
++	struct nes_device *nesdev = (struct nes_device *)param;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 counter;
++	u32 loop_counter = 0;
++	u32 int_status_bit;
++	u32 int_stat;
++	u32 timer_stat;
++	u32 temp_int_stat;
++	u32 intf_int_stat;
++	u32 debug_error;
++	u32 processed_intf_int = 0;
++	u16 processed_timer_int = 0;
++	u16 completion_ints = 0;
++	u16 timer_ints = 0;
++
++	/* nes_debug(NES_DBG_ISR, "\n"); */
++
++	do {
++		timer_stat = 0;
++		if (nesdev->napi_isr_ran) {
++			nesdev->napi_isr_ran = 0;
++			int_stat = nesdev->int_stat;
++		} else
++			int_stat = nes_read32(nesdev->regs+NES_INT_STAT);
++		if (processed_intf_int != 0)
++			int_stat &= nesdev->int_req & ~NES_INT_INTF;
++		else
++			int_stat &= nesdev->int_req;
++		if (processed_timer_int == 0) {
++			processed_timer_int = 1;
++			if (int_stat & NES_INT_TIMER) {
++				timer_stat = nes_read32(nesdev->regs + NES_TIMER_STAT);
++				if ((timer_stat & nesdev->timer_int_req) == 0) {
++					int_stat &= ~NES_INT_TIMER;
++				}
++			}
++		} else {
++			int_stat &= ~NES_INT_TIMER;
++		}
++
++		if (int_stat) {
++			if (int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
++					NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)) {
++				/* Ack the interrupts */
++				nes_write32(nesdev->regs+NES_INT_STAT,
++						(int_stat & ~(NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
++						NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3)));
++			}
++
++			temp_int_stat = int_stat;
++			for (counter = 0, int_status_bit = 1; counter < 16; counter++) {
++				if (int_stat & int_status_bit) {
++					nes_process_ceq(nesdev, &nesadapter->ceq[counter]);
++					temp_int_stat &= ~int_status_bit;
++					completion_ints = 1;
++				}
++				if (!(temp_int_stat & 0x0000ffff))
++					break;
++				int_status_bit <<= 1;
++			}
++
++			/* Process the AEQ for this pci function */
++			int_status_bit = 1 << (16 + PCI_FUNC(nesdev->pcidev->devfn));
++			if (int_stat & int_status_bit) {
++				nes_process_aeq(nesdev, &nesadapter->aeq[PCI_FUNC(nesdev->pcidev->devfn)]);
++			}
++
++			/* Process the MAC interrupt for this pci function */
++			int_status_bit = 1 << (24 + nesdev->mac_index);
++			if (int_stat & int_status_bit) {
++				nes_process_mac_intr(nesdev, nesdev->mac_index);
++			}
++
++			if (int_stat & NES_INT_TIMER) {
++				if (timer_stat & nesdev->timer_int_req) {
++					nes_write32(nesdev->regs + NES_TIMER_STAT,
++							(timer_stat & nesdev->timer_int_req) |
++							~(nesdev->nesadapter->timer_int_req));
++					timer_ints = 1;
++				}
++			}
++
++			if (int_stat & NES_INT_INTF) {
++				processed_intf_int = 1;
++				intf_int_stat = nes_read32(nesdev->regs+NES_INTF_INT_STAT);
++				intf_int_stat &= nesdev->intf_int_req;
++				if (NES_INTF_INT_CRITERR & intf_int_stat) {
++					debug_error = nes_read_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS);
++					printk(KERN_ERR PFX "Critical Error reported by device!!! 0x%02X\n",
++							(u16)debug_error);
++					nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_CONTROL_STATUS,
++							0x01010000 | (debug_error & 0x0000ffff));
++					/* BUG(); */
++					if (crit_err_count++ > 10)
++						nes_write_indexed(nesdev, NES_IDX_DEBUG_ERROR_MASKS1, 1 << 0x17);
++				}
++				if (NES_INTF_INT_PCIERR & intf_int_stat) {
++					printk(KERN_ERR PFX "PCI Error reported by device!!!\n");
++					BUG();
++				}
++				if (NES_INTF_INT_AEQ_OFLOW & intf_int_stat) {
++					printk(KERN_ERR PFX "AEQ Overflow reported by device!!!\n");
++					BUG();
++				}
++				nes_write32(nesdev->regs+NES_INTF_INT_STAT, intf_int_stat);
++			}
++
++			if (int_stat & NES_INT_TSW) {
++			}
++		}
++		/* Don't use the interface interrupt bit stay in loop */
++		int_stat &= ~NES_INT_INTF|NES_INT_TIMER|NES_INT_MAC0|
++				NES_INT_MAC1|NES_INT_MAC2|NES_INT_MAC3;
++	} while ((int_stat != 0) && (loop_counter++ < MAX_DPC_ITERATIONS));
++
++	if (timer_ints == 1) {
++		if ((nesadapter->et_rx_coalesce_usecs_irq) || (nesadapter->et_use_adaptive_rx_coalesce)) {
++			if (completion_ints == 0) {
++				nesdev->timer_only_int_count++;
++				if (nesdev->timer_only_int_count>=nesadapter->timer_int_limit) {
++					nesdev->timer_only_int_count = 0;
++					nesdev->int_req &= ~NES_INT_TIMER;
++					nes_write32(nesdev->regs + NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
++					nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
++					nesdev->nesadapter->tune_timer.timer_in_use_old = 0;
++				} else {
++					nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
++				}
++			} else {
++				if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
++				{
++					nes_nic_init_timer(nesdev);
++				}
++				nesdev->timer_only_int_count = 0;
++				nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff|(~nesdev->int_req));
++			}
++		} else {
++			nesdev->timer_only_int_count = 0;
++			nesdev->int_req &= ~NES_INT_TIMER;
++			nes_write32(nesdev->regs+NES_INTF_INT_MASK, ~(nesdev->intf_int_req));
++			nes_write32(nesdev->regs+NES_TIMER_STAT,
++					nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
++			nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
++		}
++	} else {
++		if ( (completion_ints == 1) &&
++			 (((nesadapter->et_rx_coalesce_usecs_irq) &&
++			   (!nesadapter->et_use_adaptive_rx_coalesce)) ||
++			  ((nesdev->deepcq_count > nesadapter->et_pkt_rate_low) &&
++			   (nesadapter->et_use_adaptive_rx_coalesce) )) ) {
++			/* nes_debug(NES_DBG_ISR, "Enabling periodic timer interrupt.\n" ); */
++			nesdev->timer_only_int_count = 0;
++			nesdev->int_req |= NES_INT_TIMER;
++			nes_write32(nesdev->regs+NES_TIMER_STAT,
++					nesdev->timer_int_req | ~(nesdev->nesadapter->timer_int_req));
++			nes_write32(nesdev->regs+NES_INTF_INT_MASK,
++					~(nesdev->intf_int_req | NES_INTF_PERIODIC_TIMER));
++			nes_write32(nesdev->regs+NES_INT_MASK, 0x0000ffff | (~nesdev->int_req));
++		} else {
++			nes_write32(nesdev->regs+NES_INT_MASK, ~nesdev->int_req);
++		}
 +	}
++	nesdev->deepcq_count = 0;
++}
 +
-+	return 0;
 +
-+error:
-+	while (i--)
-+		cm_remove_fs_obj(&port->counter_group[i].obj);
-+	cm_remove_fs_obj(&port->port_obj);
-+	return ret;
++/**
++ * nes_process_ceq
++ */
++void nes_process_ceq(struct nes_device *nesdev, struct nes_hw_ceq *ceq)
++{
++	u64 u64temp;
++	struct nes_hw_cq *cq;
++	u32 head;
++	u32 ceq_size;
++
++	/* nes_debug(NES_DBG_CQ, "\n"); */
++	head = ceq->ceq_head;
++	ceq_size = ceq->ceq_size;
++
++	do {
++		if (le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX]) &
++				NES_CEQE_VALID) {
++			u64temp = (((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX])))<<32) |
++						((u64)(le32_to_cpu(ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_LOW_IDX])));
++			u64temp <<= 1;
++			cq = *((struct nes_hw_cq **)&u64temp);
++			/* nes_debug(NES_DBG_CQ, "pCQ = %p\n", cq); */
++			barrier();
++			ceq->ceq_vbase[head].ceqe_words[NES_CEQE_CQ_CTX_HIGH_IDX] = 0;
++
++			/* call the event handler */
++			cq->ce_handler(nesdev, cq);
++
++			if (++head >= ceq_size)
++				head = 0;
++		} else {
++			break;
++		}
 +
++	} while (1);
++
++	ceq->ceq_head = head;
 +}
 +
-+static void cm_remove_port_fs(struct cm_port *port)
++
++/**
++ * nes_process_aeq
++ */
++void nes_process_aeq(struct nes_device *nesdev, struct nes_hw_aeq *aeq)
 +{
-+	int i;
++//	u64 u64temp;
++	u32 head;
++	u32 aeq_size;
++	u32 aeqe_misc;
++	u32 aeqe_cq_id;
++	struct nes_hw_aeqe volatile *aeqe;
 +
-+	for (i = 0; i < CM_COUNTER_GROUPS; i++)
-+		cm_remove_fs_obj(&port->counter_group[i].obj);
++	head = aeq->aeq_head;
++	aeq_size = aeq->aeq_size;
 +
-+	cm_remove_fs_obj(&port->port_obj);
++	do {
++		aeqe = &aeq->aeq_vbase[head];
++		if ((le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]) & NES_AEQE_VALID) == 0)
++			break;
++		aeqe_misc  = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
++		aeqe_cq_id = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]);
++		if (aeqe_misc & (NES_AEQE_QP|NES_AEQE_CQ)) {
++			if (aeqe_cq_id >= NES_FIRST_QPN) {
++				/* dealing with an accelerated QP related AE */
++//				u64temp = (((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])))<<32) |
++//					((u64)(le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX])));
++				nes_process_iwarp_aeqe(nesdev, (struct nes_hw_aeqe *)aeqe);
++			} else {
++				/* TODO: dealing with a CQP related AE */
++				nes_debug(NES_DBG_AEQ, "Processing CQP related AE, misc = 0x%04X\n",
++						(u16)(aeqe_misc >> 16));
++			}
++		}
++
++		aeqe->aeqe_words[NES_AEQE_MISC_IDX] = 0;
++
++		if (++head >= aeq_size)
++			head = 0;
++	}
++	while (1);
++	aeq->aeq_head = head;
 +}
 +
- static void cm_add_one(struct ib_device *device)
- {
- 	struct cm_device *cm_dev;
-@@ -3397,7 +3638,7 @@ static void cm_add_one(struct ib_device *device)
- 	if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
- 		return;
- 
--	cm_dev = kmalloc(sizeof(*cm_dev) + sizeof(*port) *
-+	cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
- 			 device->phys_port_cnt, GFP_KERNEL);
- 	if (!cm_dev)
- 		return;
-@@ -3405,11 +3646,27 @@ static void cm_add_one(struct ib_device *device)
- 	cm_dev->device = device;
- 	cm_get_ack_delay(cm_dev);
- 
-+	ret = kobject_init_and_add(&cm_dev->dev_obj, &cm_dev_obj_type,
-+				   &cm_class.subsys.kobj, "%s", device->name);
-+	if (ret) {
-+		kfree(cm_dev);
++static void nes_reset_link(struct nes_device *nesdev, u32 mac_index)
++{
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 reset_value;
++	u32 i=0;
++	u32 u32temp;
++
++	if (nesadapter->hw_rev == NE020_REV) {
 +		return;
 +	}
++	mh_detected++;
 +
- 	set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
- 	for (i = 1; i <= device->phys_port_cnt; i++) {
--		port = &cm_dev->port[i-1];
-+		port = kzalloc(sizeof *port, GFP_KERNEL);
-+		if (!port)
-+			goto error1;
++	reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
 +
-+		cm_dev->port[i-1] = port;
- 		port->cm_dev = cm_dev;
- 		port->port_num = i;
++	if ((mac_index == 0) || ((mac_index == 1) && (nesadapter->OneG_Mode)))
++		reset_value |= 0x0000001d;
++	else
++		reset_value |= 0x0000002d;
 +
-+		ret = cm_create_port_fs(port);
-+		if (ret)
-+			goto error1;
++	if (4 <= (nesadapter->link_interrupt_count[mac_index] / ((u16)NES_MAX_LINK_INTERRUPTS))) {
++		if ((!nesadapter->OneG_Mode) && (nesadapter->port_count == 2)) {
++			nesadapter->link_interrupt_count[0] = 0;
++			nesadapter->link_interrupt_count[1] = 0;
++			u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
++			if (0x00000040 & u32temp)
++				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
++			else
++				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
 +
- 		port->mad_agent = ib_register_mad_agent(device, i,
- 							IB_QPT_GSI,
- 							&reg_req,
-@@ -3418,11 +3675,11 @@ static void cm_add_one(struct ib_device *device)
- 							cm_recv_handler,
- 							port);
- 		if (IS_ERR(port->mad_agent))
--			goto error1;
-+			goto error2;
- 
- 		ret = ib_modify_port(device, i, 0, &port_modify);
- 		if (ret)
--			goto error2;
-+			goto error3;
- 	}
- 	ib_set_client_data(device, &cm_client, cm_dev);
- 
-@@ -3431,17 +3688,20 @@ static void cm_add_one(struct ib_device *device)
- 	write_unlock_irqrestore(&cm.device_lock, flags);
- 	return;
- 
--error2:
-+error3:
- 	ib_unregister_mad_agent(port->mad_agent);
-+error2:
-+	cm_remove_port_fs(port);
- error1:
- 	port_modify.set_port_cap_mask = 0;
- 	port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
- 	while (--i) {
--		port = &cm_dev->port[i-1];
-+		port = cm_dev->port[i-1];
- 		ib_modify_port(device, port->port_num, 0, &port_modify);
- 		ib_unregister_mad_agent(port->mad_agent);
-+		cm_remove_port_fs(port);
- 	}
--	kfree(cm_dev);
-+	cm_remove_fs_obj(&cm_dev->dev_obj);
- }
- 
- static void cm_remove_one(struct ib_device *device)
-@@ -3463,11 +3723,12 @@ static void cm_remove_one(struct ib_device *device)
- 	write_unlock_irqrestore(&cm.device_lock, flags);
- 
- 	for (i = 1; i <= device->phys_port_cnt; i++) {
--		port = &cm_dev->port[i-1];
-+		port = cm_dev->port[i-1];
- 		ib_modify_port(device, port->port_num, 0, &port_modify);
- 		ib_unregister_mad_agent(port->mad_agent);
-+		cm_remove_port_fs(port);
- 	}
--	kfree(cm_dev);
-+	cm_remove_fs_obj(&cm_dev->dev_obj);
- }
- 
- static int __init ib_cm_init(void)
-@@ -3488,17 +3749,25 @@ static int __init ib_cm_init(void)
- 	idr_pre_get(&cm.local_id_table, GFP_KERNEL);
- 	INIT_LIST_HEAD(&cm.timewait_list);
- 
--	cm.wq = create_workqueue("ib_cm");
--	if (!cm.wq)
-+	ret = class_register(&cm_class);
-+	if (ret)
- 		return -ENOMEM;
- 
-+	cm.wq = create_workqueue("ib_cm");
-+	if (!cm.wq) {
-+		ret = -ENOMEM;
-+		goto error1;
++			reset_value |= 0x0000003d;
++		}
++		nesadapter->link_interrupt_count[mac_index] = 0;
 +	}
 +
- 	ret = ib_register_client(&cm_client);
- 	if (ret)
--		goto error;
-+		goto error2;
- 
- 	return 0;
--error:
-+error2:
- 	destroy_workqueue(cm.wq);
-+error1:
-+	class_unregister(&cm_class);
- 	return ret;
- }
- 
-@@ -3519,6 +3788,7 @@ static void __exit ib_cm_cleanup(void)
- 	}
- 
- 	ib_unregister_client(&cm_client);
-+	class_unregister(&cm_class);
- 	idr_destroy(&cm.local_id_table);
- }
- 
-diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
-index 0751697..1eff1b2 100644
---- a/drivers/infiniband/core/cma.c
-+++ b/drivers/infiniband/core/cma.c
-@@ -488,7 +488,8 @@ void rdma_destroy_qp(struct rdma_cm_id *id)
- }
- EXPORT_SYMBOL(rdma_destroy_qp);
- 
--static int cma_modify_qp_rtr(struct rdma_id_private *id_priv)
-+static int cma_modify_qp_rtr(struct rdma_id_private *id_priv,
-+			     struct rdma_conn_param *conn_param)
- {
- 	struct ib_qp_attr qp_attr;
- 	int qp_attr_mask, ret;
-@@ -514,13 +515,16 @@ static int cma_modify_qp_rtr(struct rdma_id_private *id_priv)
- 	if (ret)
- 		goto out;
- 
-+	if (conn_param)
-+		qp_attr.max_dest_rd_atomic = conn_param->responder_resources;
- 	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
- out:
- 	mutex_unlock(&id_priv->qp_mutex);
- 	return ret;
- }
- 
--static int cma_modify_qp_rts(struct rdma_id_private *id_priv)
-+static int cma_modify_qp_rts(struct rdma_id_private *id_priv,
-+			     struct rdma_conn_param *conn_param)
- {
- 	struct ib_qp_attr qp_attr;
- 	int qp_attr_mask, ret;
-@@ -536,6 +540,8 @@ static int cma_modify_qp_rts(struct rdma_id_private *id_priv)
- 	if (ret)
- 		goto out;
- 
-+	if (conn_param)
-+		qp_attr.max_rd_atomic = conn_param->initiator_depth;
- 	ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
- out:
- 	mutex_unlock(&id_priv->qp_mutex);
-@@ -624,7 +630,8 @@ static inline int cma_zero_addr(struct sockaddr *addr)
- 	struct in6_addr *ip6;
- 
- 	if (addr->sa_family == AF_INET)
--		return ZERONET(((struct sockaddr_in *) addr)->sin_addr.s_addr);
-+		return ipv4_is_zeronet(
-+			((struct sockaddr_in *)addr)->sin_addr.s_addr);
- 	else {
- 		ip6 = &((struct sockaddr_in6 *) addr)->sin6_addr;
- 		return (ip6->s6_addr32[0] | ip6->s6_addr32[1] |
-@@ -634,7 +641,7 @@ static inline int cma_zero_addr(struct sockaddr *addr)
- 
- static inline int cma_loopback_addr(struct sockaddr *addr)
- {
--	return LOOPBACK(((struct sockaddr_in *) addr)->sin_addr.s_addr);
-+	return ipv4_is_loopback(((struct sockaddr_in *) addr)->sin_addr.s_addr);
- }
- 
- static inline int cma_any_addr(struct sockaddr *addr)
-@@ -866,11 +873,11 @@ static int cma_rep_recv(struct rdma_id_private *id_priv)
- {
- 	int ret;
- 
--	ret = cma_modify_qp_rtr(id_priv);
-+	ret = cma_modify_qp_rtr(id_priv, NULL);
- 	if (ret)
- 		goto reject;
- 
--	ret = cma_modify_qp_rts(id_priv);
-+	ret = cma_modify_qp_rts(id_priv, NULL);
- 	if (ret)
- 		goto reject;
- 
-@@ -1122,8 +1129,10 @@ static int cma_req_handler(struct ib_cm_id *cm_id, struct ib_cm_event *ib_event)
- 	cm_id->cm_handler = cma_ib_handler;
- 
- 	ret = conn_id->id.event_handler(&conn_id->id, &event);
--	if (!ret)
-+	if (!ret) {
-+		cma_enable_remove(conn_id);
- 		goto out;
-+	}
- 
- 	/* Destroy the CM ID by returning a non-zero value. */
- 	conn_id->cm_id.ib = NULL;
-@@ -1262,6 +1271,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
- 	struct net_device *dev = NULL;
- 	struct rdma_cm_event event;
- 	int ret;
-+	struct ib_device_attr attr;
- 
- 	listen_id = cm_id->context;
- 	if (cma_disable_remove(listen_id, CMA_LISTEN))
-@@ -1279,7 +1289,7 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
- 	atomic_inc(&conn_id->dev_remove);
- 	conn_id->state = CMA_CONNECT;
- 
--	dev = ip_dev_find(iw_event->local_addr.sin_addr.s_addr);
-+	dev = ip_dev_find(&init_net, iw_event->local_addr.sin_addr.s_addr);
- 	if (!dev) {
- 		ret = -EADDRNOTAVAIL;
- 		cma_enable_remove(conn_id);
-@@ -1311,10 +1321,19 @@ static int iw_conn_req_handler(struct iw_cm_id *cm_id,
- 	sin = (struct sockaddr_in *) &new_cm_id->route.addr.dst_addr;
- 	*sin = iw_event->remote_addr;
- 
-+	ret = ib_query_device(conn_id->id.device, &attr);
-+	if (ret) {
-+		cma_enable_remove(conn_id);
-+		rdma_destroy_id(new_cm_id);
-+		goto out;
++	nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
++
++	while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
++			& 0x00000040) != 0x00000040) && (i++ < 5000));
++
++	if (0x0000003d == (reset_value & 0x0000003d)) {
++		u32 pcs_control_status0, pcs_control_status1;
++
++		for (i = 0; i < 10; i++) {
++			pcs_control_status0 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0);
++			pcs_control_status1 = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + 0x200);
++			if (((0x0F000000 == (pcs_control_status0 & 0x0F000000))
++			     && (pcs_control_status0 & 0x00100000))
++			    || ((0x0F000000 == (pcs_control_status1 & 0x0F000000))
++				&& (pcs_control_status1 & 0x00100000)))
++				continue;
++			else
++				break;
++		}
++		if (10 == i) {
++			u32temp = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1);
++			if (0x00000040 & u32temp)
++				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F088);
++			else
++				nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL1, 0x0000F0C8);
++
++			nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value);
++
++			while (((nes_read32(nesdev->regs + NES_SOFTWARE_RESET)
++				 & 0x00000040) != 0x00000040) && (i++ < 5000));
++		}
 +	}
++}
 +
- 	memset(&event, 0, sizeof event);
- 	event.event = RDMA_CM_EVENT_CONNECT_REQUEST;
- 	event.param.conn.private_data = iw_event->private_data;
- 	event.param.conn.private_data_len = iw_event->private_data_len;
-+	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
-+	event.param.conn.responder_resources = attr.max_qp_rd_atom;
- 	ret = conn_id->id.event_handler(&conn_id->id, &event);
- 	if (ret) {
- 		/* User wants to destroy the CM ID */
-@@ -2272,7 +2291,7 @@ static int cma_connect_iw(struct rdma_id_private *id_priv,
- 	sin = (struct sockaddr_in*) &id_priv->id.route.addr.dst_addr;
- 	cm_id->remote_addr = *sin;
- 
--	ret = cma_modify_qp_rtr(id_priv);
-+	ret = cma_modify_qp_rtr(id_priv, conn_param);
- 	if (ret)
- 		goto out;
- 
-@@ -2335,25 +2354,15 @@ static int cma_accept_ib(struct rdma_id_private *id_priv,
- 			 struct rdma_conn_param *conn_param)
- {
- 	struct ib_cm_rep_param rep;
--	struct ib_qp_attr qp_attr;
--	int qp_attr_mask, ret;
--
--	if (id_priv->id.qp) {
--		ret = cma_modify_qp_rtr(id_priv);
--		if (ret)
--			goto out;
-+	int ret;
- 
--		qp_attr.qp_state = IB_QPS_RTS;
--		ret = ib_cm_init_qp_attr(id_priv->cm_id.ib, &qp_attr,
--					 &qp_attr_mask);
--		if (ret)
--			goto out;
-+	ret = cma_modify_qp_rtr(id_priv, conn_param);
-+	if (ret)
-+		goto out;
- 
--		qp_attr.max_rd_atomic = conn_param->initiator_depth;
--		ret = ib_modify_qp(id_priv->id.qp, &qp_attr, qp_attr_mask);
--		if (ret)
--			goto out;
--	}
-+	ret = cma_modify_qp_rts(id_priv, conn_param);
-+	if (ret)
-+		goto out;
- 
- 	memset(&rep, 0, sizeof rep);
- 	rep.qp_num = id_priv->qp_num;
-@@ -2378,7 +2387,7 @@ static int cma_accept_iw(struct rdma_id_private *id_priv,
- 	struct iw_cm_conn_param iw_param;
- 	int ret;
- 
--	ret = cma_modify_qp_rtr(id_priv);
-+	ret = cma_modify_qp_rtr(id_priv, conn_param);
- 	if (ret)
- 		return ret;
- 
-@@ -2598,11 +2607,9 @@ static void cma_set_mgid(struct rdma_id_private *id_priv,
- 		/* IPv6 address is an SA assigned MGID. */
- 		memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
- 	} else {
--		ip_ib_mc_map(sin->sin_addr.s_addr, mc_map);
-+		ip_ib_mc_map(sin->sin_addr.s_addr, dev_addr->broadcast, mc_map);
- 		if (id_priv->id.ps == RDMA_PS_UDP)
- 			mc_map[7] = 0x01;	/* Use RDMA CM signature */
--		mc_map[8] = ib_addr_get_pkey(dev_addr) >> 8;
--		mc_map[9] = (unsigned char) ib_addr_get_pkey(dev_addr);
- 		*mgid = *(union ib_gid *) (mc_map + 4);
- 	}
- }
-diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
-index e8d5f6b..6c7aa59 100644
---- a/drivers/infiniband/core/fmr_pool.c
-+++ b/drivers/infiniband/core/fmr_pool.c
-@@ -139,7 +139,7 @@ static inline struct ib_pool_fmr *ib_fmr_cache_lookup(struct ib_fmr_pool *pool,
- static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
- {
- 	int                 ret;
--	struct ib_pool_fmr *fmr;
-+	struct ib_pool_fmr *fmr, *next;
- 	LIST_HEAD(unmap_list);
- 	LIST_HEAD(fmr_list);
- 
-@@ -158,6 +158,20 @@ static void ib_fmr_batch_release(struct ib_fmr_pool *pool)
- #endif
- 	}
- 
-+	/*
-+	 * The free_list may hold FMRs that have been put there
-+	 * because they haven't reached the max_remap count.
-+	 * Invalidate their mapping as well.
-+	 */
-+	list_for_each_entry_safe(fmr, next, &pool->free_list, list) {
-+		if (fmr->remap_count == 0)
-+			continue;
-+		hlist_del_init(&fmr->cache_node);
-+		fmr->remap_count = 0;
-+		list_add_tail(&fmr->fmr->list, &fmr_list);
-+		list_move(&fmr->list, &unmap_list);
++/**
++ * nes_process_mac_intr
++ */
++void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number)
++{
++	unsigned long flags;
++	u32 pcs_control_status;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_vnic *nesvnic;
++	u32 mac_status;
++	u32 mac_index = nesdev->mac_index;
++	u32 u32temp;
++	u16 phy_data;
++	u16 temp_phy_data;
++
++	spin_lock_irqsave(&nesadapter->phy_lock, flags);
++	if (nesadapter->mac_sw_state[mac_number] != NES_MAC_SW_IDLE) {
++		spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++		return;
 +	}
++	nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_INTERRUPT;
++	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
 +
- 	list_splice(&pool->dirty_list, &unmap_list);
- 	INIT_LIST_HEAD(&pool->dirty_list);
- 	pool->dirty_len = 0;
-@@ -182,8 +196,7 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
- 	struct ib_fmr_pool *pool = pool_ptr;
- 
- 	do {
--		if (pool->dirty_len >= pool->dirty_watermark ||
--		    atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
-+		if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) < 0) {
- 			ib_fmr_batch_release(pool);
- 
- 			atomic_inc(&pool->flush_ser);
-@@ -194,8 +207,7 @@ static int ib_fmr_cleanup_thread(void *pool_ptr)
- 		}
- 
- 		set_current_state(TASK_INTERRUPTIBLE);
--		if (pool->dirty_len < pool->dirty_watermark &&
--		    atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
-+		if (atomic_read(&pool->flush_ser) - atomic_read(&pool->req_ser) >= 0 &&
- 		    !kthread_should_stop())
- 			schedule();
- 		__set_current_state(TASK_RUNNING);
-@@ -369,11 +381,6 @@ void ib_destroy_fmr_pool(struct ib_fmr_pool *pool)
- 
- 	i = 0;
- 	list_for_each_entry_safe(fmr, tmp, &pool->free_list, list) {
--		if (fmr->remap_count) {
--			INIT_LIST_HEAD(&fmr_list);
--			list_add_tail(&fmr->fmr->list, &fmr_list);
--			ib_unmap_fmr(&fmr_list);
--		}
- 		ib_dealloc_fmr(fmr->fmr);
- 		list_del(&fmr->list);
- 		kfree(fmr);
-@@ -511,8 +518,10 @@ int ib_fmr_pool_unmap(struct ib_pool_fmr *fmr)
- 			list_add_tail(&fmr->list, &pool->free_list);
- 		} else {
- 			list_add_tail(&fmr->list, &pool->dirty_list);
--			++pool->dirty_len;
--			wake_up_process(pool->thread);
-+			if (++pool->dirty_len >= pool->dirty_watermark) {
-+				atomic_inc(&pool->req_ser);
-+				wake_up_process(pool->thread);
++	/* ack the MAC interrupt */
++	mac_status = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200));
++	/* Clear the interrupt */
++	nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (mac_index * 0x200), mac_status);
++
++	nes_debug(NES_DBG_PHY, "MAC%u interrupt status = 0x%X.\n", mac_number, mac_status);
++
++	if (mac_status & (NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT)) {
++		nesdev->link_status_interrupts++;
++		if (0 == (++nesadapter->link_interrupt_count[mac_index] % ((u16)NES_MAX_LINK_INTERRUPTS))) {
++			spin_lock_irqsave(&nesadapter->phy_lock, flags);
++			nes_reset_link(nesdev, mac_index);
++			spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++		}
++		/* read the PHY interrupt status register */
++		if (nesadapter->OneG_Mode) {
++			do {
++				nes_read_1G_phy_reg(nesdev, 0x1a,
++						nesadapter->phy_index[mac_index], &phy_data);
++				nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1a = 0x%X.\n",
++						nesadapter->phy_index[mac_index], phy_data);
++			} while (phy_data&0x8000);
++
++			temp_phy_data = 0;
++			do {
++				nes_read_1G_phy_reg(nesdev, 0x11,
++						nesadapter->phy_index[mac_index], &phy_data);
++				nes_debug(NES_DBG_PHY, "Phy%d data from register 0x11 = 0x%X.\n",
++						nesadapter->phy_index[mac_index], phy_data);
++				if (temp_phy_data == phy_data)
++					break;
++				temp_phy_data = phy_data;
++			} while (1);
++
++			nes_read_1G_phy_reg(nesdev, 0x1e,
++					nesadapter->phy_index[mac_index], &phy_data);
++			nes_debug(NES_DBG_PHY, "Phy%d data from register 0x1e = 0x%X.\n",
++					nesadapter->phy_index[mac_index], phy_data);
++
++			nes_read_1G_phy_reg(nesdev, 1,
++					nesadapter->phy_index[mac_index], &phy_data);
++			nes_debug(NES_DBG_PHY, "1G phy%u data from register 1 = 0x%X\n",
++					nesadapter->phy_index[mac_index], phy_data);
++
++			if (temp_phy_data & 0x1000) {
++				nes_debug(NES_DBG_PHY, "The Link is up according to the PHY\n");
++				phy_data = 4;
++			} else {
++				nes_debug(NES_DBG_PHY, "The Link is down according to the PHY\n");
 +			}
- 		}
- 	}
- 
-diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
-index 6f42877..fbe16d5 100644
---- a/drivers/infiniband/core/mad.c
-+++ b/drivers/infiniband/core/mad.c
-@@ -701,7 +701,8 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
- 	}
- 
- 	/* Check to post send on QP or process locally */
--	if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD)
-+	if (smi_check_local_smp(smp, device) == IB_SMI_DISCARD &&
-+	    smi_check_local_returning_smp(smp, device) == IB_SMI_DISCARD)
- 		goto out;
- 
- 	local = kmalloc(sizeof *local, GFP_ATOMIC);
-@@ -752,8 +753,7 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
- 		port_priv = ib_get_mad_port(mad_agent_priv->agent.device,
- 					    mad_agent_priv->agent.port_num);
- 		if (port_priv) {
--			mad_priv->mad.mad.mad_hdr.tid =
--				((struct ib_mad *)smp)->mad_hdr.tid;
-+			memcpy(&mad_priv->mad.mad, smp, sizeof(struct ib_mad));
- 			recv_mad_agent = find_mad_agent(port_priv,
- 						        &mad_priv->mad.mad);
- 		}
-@@ -1100,7 +1100,9 @@ int ib_post_send_mad(struct ib_mad_send_buf *send_buf,
- 		mad_send_wr->tid = ((struct ib_mad_hdr *) send_buf->mad)->tid;
- 		/* Timeout will be updated after send completes */
- 		mad_send_wr->timeout = msecs_to_jiffies(send_buf->timeout_ms);
--		mad_send_wr->retries = send_buf->retries;
-+		mad_send_wr->max_retries = send_buf->retries;
-+		mad_send_wr->retries_left = send_buf->retries;
-+		send_buf->retries = 0;
- 		/* Reference for work request to QP + response */
- 		mad_send_wr->refcount = 1 + (mad_send_wr->timeout > 0);
- 		mad_send_wr->status = IB_WC_SUCCESS;
-@@ -1931,15 +1933,6 @@ local:
- 	if (port_priv->device->process_mad) {
- 		int ret;
- 
--		if (!response) {
--			printk(KERN_ERR PFX "No memory for response MAD\n");
--			/*
--			 * Is it better to assume that
--			 * it wouldn't be processed ?
--			 */
--			goto out;
--		}
--
- 		ret = port_priv->device->process_mad(port_priv->device, 0,
- 						     port_priv->port_num,
- 						     wc, &recv->grh,
-@@ -2282,8 +2275,6 @@ static void cancel_mads(struct ib_mad_agent_private *mad_agent_priv)
- 
- 	/* Empty wait list to prevent receives from finding a request */
- 	list_splice_init(&mad_agent_priv->wait_list, &cancel_list);
--	/* Empty local completion list as well */
--	list_splice_init(&mad_agent_priv->local_list, &cancel_list);
- 	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
- 
- 	/* Report all cancelled requests */
-@@ -2445,9 +2436,12 @@ static int retry_send(struct ib_mad_send_wr_private *mad_send_wr)
- {
- 	int ret;
- 
--	if (!mad_send_wr->retries--)
-+	if (!mad_send_wr->retries_left)
- 		return -ETIMEDOUT;
- 
-+	mad_send_wr->retries_left--;
-+	mad_send_wr->send_buf.retries++;
++		}
++		nes_debug(NES_DBG_PHY, "Eth SERDES Common Status: 0=0x%08X, 1=0x%08X\n",
++				nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0),
++				nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0+0x200));
++		pcs_control_status = nes_read_indexed(nesdev,
++				NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200));
++		pcs_control_status = nes_read_indexed(nesdev,
++				NES_IDX_PHY_PCS_CONTROL_STATUS0 + ((mac_index&1)*0x200));
++		nes_debug(NES_DBG_PHY, "PCS PHY Control/Status%u: 0x%08X\n",
++				mac_index, pcs_control_status);
++		if (nesadapter->OneG_Mode) {
++			u32temp = 0x01010000;
++			if (nesadapter->port_count > 2) {
++				u32temp |= 0x02020000;
++			}
++			if ((pcs_control_status & u32temp)!= u32temp) {
++				phy_data = 0;
++				nes_debug(NES_DBG_PHY, "PCS says the link is down\n");
++			}
++		} else if (nesadapter->phy_type[mac_index] == NES_PHY_TYPE_IRIS) {
++			nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]);
++			temp_phy_data = (u16)nes_read_indexed(nesdev,
++								NES_IDX_MAC_MDIO_CONTROL);
++			u32temp = 20;
++			do {
++				nes_read_10G_phy_reg(nesdev, 1, nesadapter->phy_index[mac_index]);
++				phy_data = (u16)nes_read_indexed(nesdev,
++								NES_IDX_MAC_MDIO_CONTROL);
++				if ((phy_data == temp_phy_data) || (!(--u32temp)))
++					break;
++				temp_phy_data = phy_data;
++			} while (1);
++			nes_debug(NES_DBG_PHY, "%s: Phy data = 0x%04X, link was %s.\n",
++				__FUNCTION__, phy_data, nesadapter->mac_link_down ? "DOWN" : "UP");
 +
- 	mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms);
- 
- 	if (mad_send_wr->mad_agent_priv->agent.rmpp_version) {
-diff --git a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
-index 9be5cc0..8b75010 100644
---- a/drivers/infiniband/core/mad_priv.h
-+++ b/drivers/infiniband/core/mad_priv.h
-@@ -131,7 +131,8 @@ struct ib_mad_send_wr_private {
- 	struct ib_sge sg_list[IB_MAD_SEND_REQ_MAX_SG];
- 	__be64 tid;
- 	unsigned long timeout;
--	int retries;
-+	int max_retries;
-+	int retries_left;
- 	int retry;
- 	int refcount;
- 	enum ib_wc_status status;
-diff --git a/drivers/infiniband/core/mad_rmpp.c b/drivers/infiniband/core/mad_rmpp.c
-index d43bc62..a5e2a31 100644
---- a/drivers/infiniband/core/mad_rmpp.c
-+++ b/drivers/infiniband/core/mad_rmpp.c
-@@ -684,7 +684,7 @@ static void process_rmpp_ack(struct ib_mad_agent_private *agent,
- 
- 	if (seg_num > mad_send_wr->last_ack) {
- 		adjust_last_ack(mad_send_wr, seg_num);
--		mad_send_wr->retries = mad_send_wr->send_buf.retries;
-+		mad_send_wr->retries_left = mad_send_wr->max_retries;
- 	}
- 	mad_send_wr->newwin = newwin;
- 	if (mad_send_wr->last_ack == mad_send_wr->send_buf.seg_count) {
-diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
-index 1bc1fe6..107f170 100644
---- a/drivers/infiniband/core/multicast.c
-+++ b/drivers/infiniband/core/multicast.c
-@@ -73,11 +73,20 @@ struct mcast_device {
- };
- 
- enum mcast_state {
--	MCAST_IDLE,
- 	MCAST_JOINING,
- 	MCAST_MEMBER,
-+	MCAST_ERROR,
-+};
++		} else {
++			phy_data = (0x0f0f0000 == (pcs_control_status & 0x0f1f0000)) ? 4 : 0;
++		}
 +
-+enum mcast_group_state {
-+	MCAST_IDLE,
- 	MCAST_BUSY,
--	MCAST_ERROR
-+	MCAST_GROUP_ERROR,
-+	MCAST_PKEY_EVENT
-+};
++		if (phy_data & 0x0004) {
++			nesadapter->mac_link_down[mac_index] = 0;
++			list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
++				nes_debug(NES_DBG_PHY, "The Link is UP!!.  linkup was %d\n",
++						nesvnic->linkup);
++				if (nesvnic->linkup == 0) {
++					printk(PFX "The Link is now up for port %u, netdev %p.\n",
++							mac_index, nesvnic->netdev);
++					if (netif_queue_stopped(nesvnic->netdev))
++						netif_start_queue(nesvnic->netdev);
++					nesvnic->linkup = 1;
++					netif_carrier_on(nesvnic->netdev);
++				}
++			}
++		} else {
++			nesadapter->mac_link_down[mac_index] = 1;
++			list_for_each_entry(nesvnic, &nesadapter->nesvnic_list[mac_index], list) {
++				nes_debug(NES_DBG_PHY, "The Link is Down!!. linkup was %d\n",
++						nesvnic->linkup);
++				if (nesvnic->linkup == 1) {
++					printk(PFX "The Link is now down for port %u, netdev %p.\n",
++							mac_index, nesvnic->netdev);
++					if (!(netif_queue_stopped(nesvnic->netdev)))
++						netif_stop_queue(nesvnic->netdev);
++					nesvnic->linkup = 0;
++					netif_carrier_off(nesvnic->netdev);
++				}
++			}
++		}
++	}
 +
-+enum {
-+	MCAST_INVALID_PKEY_INDEX = 0xFFFF
- };
- 
- struct mcast_member;
-@@ -93,9 +102,10 @@ struct mcast_group {
- 	struct mcast_member	*last_join;
- 	int			members[3];
- 	atomic_t		refcount;
--	enum mcast_state	state;
-+	enum mcast_group_state	state;
- 	struct ib_sa_query	*query;
- 	int			query_id;
-+	u16			pkey_index;
- };
- 
- struct mcast_member {
-@@ -378,9 +388,19 @@ static int fail_join(struct mcast_group *group, struct mcast_member *member,
- static void process_group_error(struct mcast_group *group)
- {
- 	struct mcast_member *member;
--	int ret;
-+	int ret = 0;
-+	u16 pkey_index;
++	nesadapter->mac_sw_state[mac_number] = NES_MAC_SW_IDLE;
++}
 +
-+	if (group->state == MCAST_PKEY_EVENT)
-+		ret = ib_find_pkey(group->port->dev->device,
-+				   group->port->port_num,
-+				   be16_to_cpu(group->rec.pkey), &pkey_index);
- 
- 	spin_lock_irq(&group->lock);
-+	if (group->state == MCAST_PKEY_EVENT && !ret &&
-+	    group->pkey_index == pkey_index)
-+		goto out;
 +
- 	while (!list_empty(&group->active_list)) {
- 		member = list_entry(group->active_list.next,
- 				    struct mcast_member, list);
-@@ -399,6 +419,7 @@ static void process_group_error(struct mcast_group *group)
- 	}
- 
- 	group->rec.join_state = 0;
-+out:
- 	group->state = MCAST_BUSY;
- 	spin_unlock_irq(&group->lock);
- }
-@@ -415,9 +436,9 @@ static void mcast_work_handler(struct work_struct *work)
- retest:
- 	spin_lock_irq(&group->lock);
- 	while (!list_empty(&group->pending_list) ||
--	       (group->state == MCAST_ERROR)) {
-+	       (group->state != MCAST_BUSY)) {
- 
--		if (group->state == MCAST_ERROR) {
-+		if (group->state != MCAST_BUSY) {
- 			spin_unlock_irq(&group->lock);
- 			process_group_error(group);
- 			goto retest;
-@@ -494,12 +515,19 @@ static void join_handler(int status, struct ib_sa_mcmember_rec *rec,
- 			 void *context)
- {
- 	struct mcast_group *group = context;
-+	u16 pkey_index = MCAST_INVALID_PKEY_INDEX;
- 
- 	if (status)
- 		process_join_error(group, status);
- 	else {
-+		ib_find_pkey(group->port->dev->device, group->port->port_num,
-+			     be16_to_cpu(rec->pkey), &pkey_index);
 +
- 		spin_lock_irq(&group->port->lock);
- 		group->rec = *rec;
-+		if (group->state == MCAST_BUSY &&
-+		    group->pkey_index == MCAST_INVALID_PKEY_INDEX)
-+			group->pkey_index = pkey_index;
- 		if (!memcmp(&mgid0, &group->rec.mgid, sizeof mgid0)) {
- 			rb_erase(&group->node, &group->port->table);
- 			mcast_insert(group->port, group, 1);
-@@ -539,6 +567,7 @@ static struct mcast_group *acquire_group(struct mcast_port *port,
- 
- 	group->port = port;
- 	group->rec.mgid = *mgid;
-+	group->pkey_index = MCAST_INVALID_PKEY_INDEX;
- 	INIT_LIST_HEAD(&group->pending_list);
- 	INIT_LIST_HEAD(&group->active_list);
- 	INIT_WORK(&group->work, mcast_work_handler);
-@@ -707,7 +736,8 @@ int ib_init_ah_from_mcmember(struct ib_device *device, u8 port_num,
- }
- EXPORT_SYMBOL(ib_init_ah_from_mcmember);
- 
--static void mcast_groups_lost(struct mcast_port *port)
-+static void mcast_groups_event(struct mcast_port *port,
-+			       enum mcast_group_state state)
- {
- 	struct mcast_group *group;
- 	struct rb_node *node;
-@@ -721,7 +751,8 @@ static void mcast_groups_lost(struct mcast_port *port)
- 			atomic_inc(&group->refcount);
- 			queue_work(mcast_wq, &group->work);
- 		}
--		group->state = MCAST_ERROR;
-+		if (group->state != MCAST_GROUP_ERROR)
-+			group->state = state;
- 		spin_unlock(&group->lock);
- 	}
- 	spin_unlock_irqrestore(&port->lock, flags);
-@@ -731,16 +762,20 @@ static void mcast_event_handler(struct ib_event_handler *handler,
- 				struct ib_event *event)
- {
- 	struct mcast_device *dev;
-+	int index;
- 
- 	dev = container_of(handler, struct mcast_device, event_handler);
-+	index = event->element.port_num - dev->start_port;
- 
- 	switch (event->event) {
- 	case IB_EVENT_PORT_ERR:
- 	case IB_EVENT_LID_CHANGE:
- 	case IB_EVENT_SM_CHANGE:
- 	case IB_EVENT_CLIENT_REREGISTER:
--		mcast_groups_lost(&dev->port[event->element.port_num -
--					     dev->start_port]);
-+		mcast_groups_event(&dev->port[index], MCAST_GROUP_ERROR);
-+		break;
-+	case IB_EVENT_PKEY_CHANGE:
-+		mcast_groups_event(&dev->port[index], MCAST_PKEY_EVENT);
- 		break;
- 	default:
- 		break;
-diff --git a/drivers/infiniband/core/smi.h b/drivers/infiniband/core/smi.h
-index 1cfc298..aff96ba 100644
---- a/drivers/infiniband/core/smi.h
-+++ b/drivers/infiniband/core/smi.h
-@@ -59,7 +59,8 @@ extern enum smi_action smi_handle_dr_smp_send(struct ib_smp *smp,
- 					      u8 node_type, int port_num);
- 
- /*
-- * Return 1 if the SMP should be handled by the local SMA/SM via process_mad
-+ * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
-+ * via process_mad
-  */
- static inline enum smi_action smi_check_local_smp(struct ib_smp *smp,
- 						  struct ib_device *device)
-@@ -71,4 +72,19 @@ static inline enum smi_action smi_check_local_smp(struct ib_smp *smp,
- 		(smp->hop_ptr == smp->hop_cnt + 1)) ?
- 		IB_SMI_HANDLE : IB_SMI_DISCARD);
- }
++void nes_nic_napi_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
++{
++	struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
 +
-+/*
-+ * Return IB_SMI_HANDLE if the SMP should be handled by the local SMA/SM
-+ * via process_mad
++	netif_rx_schedule(nesdev->netdev[nesvnic->netdev_index], &nesvnic->napi);
++}
++
++
++/* The MAX_RQES_TO_PROCESS defines how many max read requests to complete before
++* getting out of nic_ce_handler
++*/
++#define	MAX_RQES_TO_PROCESS	384
++
++/**
++ * nes_nic_ce_handler
 + */
-+static inline enum smi_action smi_check_local_returning_smp(struct ib_smp *smp,
-+						   struct ib_device *device)
++void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
 +{
-+	/* C14-13:3 -- We're at the end of the DR segment of path */
-+	/* C14-13:4 -- Hop Pointer == 0 -> give to SM */
-+	return ((device->process_mad &&
-+		ib_get_smp_direction(smp) &&
-+		!smp->hop_ptr) ? IB_SMI_HANDLE : IB_SMI_DISCARD);
-+}
++	u64 u64temp;
++	dma_addr_t bus_address;
++	struct nes_hw_nic *nesnic;
++	struct nes_vnic *nesvnic = container_of(cq, struct nes_vnic, nic_cq);
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_nic_rq_wqe *nic_rqe;
++	struct nes_hw_nic_sq_wqe *nic_sqe;
++	struct sk_buff *skb;
++	struct sk_buff *rx_skb;
++	__le16 *wqe_fragment_length;
++	u32 head;
++	u32 cq_size;
++	u32 rx_pkt_size;
++	u32 cqe_count=0;
++	u32 cqe_errv;
++	u32 cqe_misc;
++	u16 wqe_fragment_index = 1;	/* first fragment (0) is used by copy buffer */
++	u16 vlan_tag;
++	u16 pkt_type;
++	u16 rqes_processed = 0;
++	u8 sq_cqes = 0;
++
++	head = cq->cq_head;
++	cq_size = cq->cq_size;
++	cq->cqes_pending = 1;
++	do {
++		if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]) &
++				NES_NIC_CQE_VALID) {
++			nesnic = &nesvnic->nic;
++			cqe_misc = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX]);
++			if (cqe_misc & NES_NIC_CQE_SQ) {
++				sq_cqes++;
++				wqe_fragment_index = 1;
++				nic_sqe = &nesnic->sq_vbase[nesnic->sq_tail];
++				skb = nesnic->tx_skb[nesnic->sq_tail];
++				wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
++				/* bump past the vlan tag */
++				wqe_fragment_length++;
++				if (le16_to_cpu(wqe_fragment_length[wqe_fragment_index]) != 0) {
++					u64temp = (u64) le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
++					u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
++					bus_address = (dma_addr_t)u64temp;
++					if (test_and_clear_bit(nesnic->sq_tail, nesnic->first_frag_overflow)) {
++						pci_unmap_single(nesdev->pcidev,
++								bus_address,
++								le16_to_cpu(wqe_fragment_length[wqe_fragment_index++]),
++								PCI_DMA_TODEVICE);
++					}
++					for (; wqe_fragment_index < 5; wqe_fragment_index++) {
++						if (wqe_fragment_length[wqe_fragment_index]) {
++							u64temp = le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX+wqe_fragment_index*2]);
++							u64temp += ((u64)le32_to_cpu(nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_HIGH_IDX+wqe_fragment_index*2]))<<32;
++							bus_address = (dma_addr_t)u64temp;
++							pci_unmap_page(nesdev->pcidev,
++									bus_address,
++									le16_to_cpu(wqe_fragment_length[wqe_fragment_index]),
++									PCI_DMA_TODEVICE);
++						} else
++							break;
++					}
++					if (skb)
++						dev_kfree_skb_any(skb);
++				}
++				nesnic->sq_tail++;
++				nesnic->sq_tail &= nesnic->sq_size-1;
++				if (sq_cqes > 128) {
++					barrier();
++				/* restart the queue if it had been stopped */
++				if (netif_queue_stopped(nesvnic->netdev))
++					netif_wake_queue(nesvnic->netdev);
++					sq_cqes = 0;
++				}
++			} else {
++				rqes_processed ++;
 +
- #endif	/* __SMI_H_ */
-diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
-index 3d40506..c864ef7 100644
---- a/drivers/infiniband/core/sysfs.c
-+++ b/drivers/infiniband/core/sysfs.c
-@@ -508,19 +508,10 @@ static int add_port(struct ib_device *device, int port_num)
- 
- 	p->ibdev      = device;
- 	p->port_num   = port_num;
--	p->kobj.ktype = &port_type;
- 
--	p->kobj.parent = kobject_get(&device->ports_parent);
--	if (!p->kobj.parent) {
--		ret = -EBUSY;
--		goto err;
--	}
--
--	ret = kobject_set_name(&p->kobj, "%d", port_num);
--	if (ret)
--		goto err_put;
--
--	ret = kobject_register(&p->kobj);
-+	ret = kobject_init_and_add(&p->kobj, &port_type,
-+				   kobject_get(device->ports_parent),
-+				   "%d", port_num);
- 	if (ret)
- 		goto err_put;
- 
-@@ -549,6 +540,7 @@ static int add_port(struct ib_device *device, int port_num)
- 
- 	list_add_tail(&p->kobj.entry, &device->port_list);
- 
-+	kobject_uevent(&p->kobj, KOBJ_ADD);
- 	return 0;
- 
- err_free_pkey:
-@@ -570,9 +562,7 @@ err_remove_pma:
- 	sysfs_remove_group(&p->kobj, &pma_group);
- 
- err_put:
--	kobject_put(&device->ports_parent);
--
--err:
-+	kobject_put(device->ports_parent);
- 	kfree(p);
- 	return ret;
- }
-@@ -694,16 +684,9 @@ int ib_device_register_sysfs(struct ib_device *device)
- 			goto err_unregister;
- 	}
- 
--	device->ports_parent.parent = kobject_get(&class_dev->kobj);
--	if (!device->ports_parent.parent) {
--		ret = -EBUSY;
--		goto err_unregister;
--	}
--	ret = kobject_set_name(&device->ports_parent, "ports");
--	if (ret)
--		goto err_put;
--	ret = kobject_register(&device->ports_parent);
--	if (ret)
-+	device->ports_parent = kobject_create_and_add("ports",
-+					kobject_get(&class_dev->kobj));
-+	if (!device->ports_parent)
- 		goto err_put;
- 
- 	if (device->node_type == RDMA_NODE_IB_SWITCH) {
-@@ -731,7 +714,7 @@ err_put:
- 			sysfs_remove_group(p, &pma_group);
- 			sysfs_remove_group(p, &port->pkey_group);
- 			sysfs_remove_group(p, &port->gid_group);
--			kobject_unregister(p);
-+			kobject_put(p);
- 		}
- 	}
- 
-@@ -755,10 +738,10 @@ void ib_device_unregister_sysfs(struct ib_device *device)
- 		sysfs_remove_group(p, &pma_group);
- 		sysfs_remove_group(p, &port->pkey_group);
- 		sysfs_remove_group(p, &port->gid_group);
--		kobject_unregister(p);
-+		kobject_put(p);
- 	}
- 
--	kobject_unregister(&device->ports_parent);
-+	kobject_put(device->ports_parent);
- 	class_device_unregister(&device->class_dev);
- }
- 
-diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
-index 424983f..4291ab4 100644
---- a/drivers/infiniband/core/ucm.c
-+++ b/drivers/infiniband/core/ucm.c
-@@ -106,6 +106,9 @@ enum {
- 	IB_UCM_MAX_DEVICES = 32
- };
- 
-+/* ib_cm and ib_user_cm modules share /sys/class/infiniband_cm */
-+extern struct class cm_class;
++				cq->rx_cqes_completed++;
++				cq->rx_pkts_indicated++;
++				rx_pkt_size = cqe_misc & 0x0000ffff;
++				nic_rqe = &nesnic->rq_vbase[nesnic->rq_tail];
++				/* Get the skb */
++				rx_skb = nesnic->rx_skb[nesnic->rq_tail];
++				nic_rqe = &nesnic->rq_vbase[nesvnic->nic.rq_tail];
++				bus_address = (dma_addr_t)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_LOW_IDX]);
++				bus_address += ((u64)le32_to_cpu(nic_rqe->wqe_words[NES_NIC_RQ_WQE_FRAG0_HIGH_IDX])) << 32;
++				pci_unmap_single(nesdev->pcidev, bus_address,
++						nesvnic->max_frame_size, PCI_DMA_FROMDEVICE);
++				/* rx_skb->tail = rx_skb->data + rx_pkt_size; */
++				/* rx_skb->len = rx_pkt_size; */
++				rx_skb->len = 0;  /* TODO: see if this is necessary */
++				skb_put(rx_skb, rx_pkt_size);
++				rx_skb->protocol = eth_type_trans(rx_skb, nesvnic->netdev);
++				nesnic->rq_tail++;
++				nesnic->rq_tail &= nesnic->rq_size - 1;
++
++				atomic_inc(&nesvnic->rx_skbs_needed);
++				if (atomic_read(&nesvnic->rx_skbs_needed) > (nesvnic->nic.rq_size>>1)) {
++					nes_write32(nesdev->regs+NES_CQE_ALLOC,
++							cq->cq_number | (cqe_count << 16));
++//					nesadapter->tune_timer.cq_count += cqe_count;
++					nesdev->currcq_count += cqe_count;
++					cqe_count = 0;
++					nes_replenish_nic_rq(nesvnic);
++				}
++				pkt_type = (u16)(le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX]));
++				cqe_errv = (cqe_misc & NES_NIC_CQE_ERRV_MASK) >> NES_NIC_CQE_ERRV_SHIFT;
++				rx_skb->ip_summed = CHECKSUM_NONE;
++
++				if ((NES_PKT_TYPE_TCPV4_BITS == (pkt_type & NES_PKT_TYPE_TCPV4_MASK)) ||
++						(NES_PKT_TYPE_UDPV4_BITS == (pkt_type & NES_PKT_TYPE_UDPV4_MASK))) {
++					if ((cqe_errv &
++							(NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |
++							NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
++						if (nesvnic->rx_checksum_disabled == 0) {
++							rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
++						}
++					} else
++						nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
++								" errv = 0x%X, pkt_type = 0x%X.\n",
++								nesvnic->netdev->name, cqe_errv, pkt_type);
++
++				} else if ((pkt_type & NES_PKT_TYPE_IPV4_MASK) == NES_PKT_TYPE_IPV4_BITS) {
++					if ((cqe_errv &
++							(NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |
++							NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
++						if (nesvnic->rx_checksum_disabled == 0) {
++							rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
++							/* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",
++								  nesvnic->netdev->name); */
++						}
++					} else
++						nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
++								" errv = 0x%X, pkt_type = 0x%X.\n",
++								nesvnic->netdev->name, cqe_errv, pkt_type);
++					}
++				/* nes_debug(NES_DBG_CQ, "pkt_type=%x, APBVT_MASK=%x\n",
++							pkt_type, (pkt_type & NES_PKT_TYPE_APBVT_MASK)); */
 +
- #define IB_UCM_BASE_DEV MKDEV(IB_UCM_MAJOR, IB_UCM_BASE_MINOR)
- 
- static void ib_ucm_add_one(struct ib_device *device);
-@@ -1199,7 +1202,7 @@ static int ib_ucm_close(struct inode *inode, struct file *filp)
- 	return 0;
- }
- 
--static void ib_ucm_release_class_dev(struct class_device *class_dev)
-+static void ucm_release_class_dev(struct class_device *class_dev)
- {
- 	struct ib_ucm_device *dev;
- 
-@@ -1217,11 +1220,6 @@ static const struct file_operations ucm_fops = {
- 	.poll    = ib_ucm_poll,
- };
- 
--static struct class ucm_class = {
--	.name    = "infiniband_cm",
--	.release = ib_ucm_release_class_dev
--};
--
- static ssize_t show_ibdev(struct class_device *class_dev, char *buf)
- {
- 	struct ib_ucm_device *dev;
-@@ -1257,9 +1255,10 @@ static void ib_ucm_add_one(struct ib_device *device)
- 	if (cdev_add(&ucm_dev->dev, IB_UCM_BASE_DEV + ucm_dev->devnum, 1))
- 		goto err;
- 
--	ucm_dev->class_dev.class = &ucm_class;
-+	ucm_dev->class_dev.class = &cm_class;
- 	ucm_dev->class_dev.dev = device->dma_device;
- 	ucm_dev->class_dev.devt = ucm_dev->dev.dev;
-+	ucm_dev->class_dev.release = ucm_release_class_dev;
- 	snprintf(ucm_dev->class_dev.class_id, BUS_ID_SIZE, "ucm%d",
- 		 ucm_dev->devnum);
- 	if (class_device_register(&ucm_dev->class_dev))
-@@ -1306,40 +1305,34 @@ static int __init ib_ucm_init(void)
- 				     "infiniband_cm");
- 	if (ret) {
- 		printk(KERN_ERR "ucm: couldn't register device number\n");
--		goto err;
-+		goto error1;
- 	}
- 
--	ret = class_register(&ucm_class);
--	if (ret) {
--		printk(KERN_ERR "ucm: couldn't create class infiniband_cm\n");
--		goto err_chrdev;
--	}
--
--	ret = class_create_file(&ucm_class, &class_attr_abi_version);
-+	ret = class_create_file(&cm_class, &class_attr_abi_version);
- 	if (ret) {
- 		printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
--		goto err_class;
-+		goto error2;
- 	}
- 
- 	ret = ib_register_client(&ucm_client);
- 	if (ret) {
- 		printk(KERN_ERR "ucm: couldn't register client\n");
--		goto err_class;
-+		goto error3;
- 	}
- 	return 0;
- 
--err_class:
--	class_unregister(&ucm_class);
--err_chrdev:
-+error3:
-+	class_remove_file(&cm_class, &class_attr_abi_version);
-+error2:
- 	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
--err:
-+error1:
- 	return ret;
- }
- 
- static void __exit ib_ucm_cleanup(void)
- {
- 	ib_unregister_client(&ucm_client);
--	class_unregister(&ucm_class);
-+	class_remove_file(&cm_class, &class_attr_abi_version);
- 	unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
- 	idr_destroy(&ctx_id_table);
- }
-diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
-index 90d675a..15937eb 100644
---- a/drivers/infiniband/core/ucma.c
-+++ b/drivers/infiniband/core/ucma.c
-@@ -31,6 +31,7 @@
-  */
- 
- #include <linux/completion.h>
-+#include <linux/file.h>
- #include <linux/mutex.h>
- #include <linux/poll.h>
- #include <linux/idr.h>
-@@ -991,6 +992,96 @@ out:
- 	return ret;
- }
- 
-+static void ucma_lock_files(struct ucma_file *file1, struct ucma_file *file2)
++				if ((pkt_type & NES_PKT_TYPE_APBVT_MASK) == NES_PKT_TYPE_APBVT_BITS) {
++					nes_cm_recv(rx_skb, nesvnic->netdev);
++				} else {
++					if ((cqe_misc & NES_NIC_CQE_TAG_VALID) && (nesvnic->vlan_grp != NULL)) {
++						vlan_tag = (u16)(le32_to_cpu(
++								cq->cq_vbase[head].cqe_words[NES_NIC_CQE_TAG_PKT_TYPE_IDX])
++								>> 16);
++						nes_debug(NES_DBG_CQ, "%s: Reporting stripped VLAN packet. Tag = 0x%04X\n",
++								nesvnic->netdev->name, vlan_tag);
++						nes_vlan_rx(rx_skb, nesvnic->vlan_grp, vlan_tag);
++					} else {
++						nes_netif_rx(rx_skb);
++					}
++				}
++
++				nesvnic->netdev->last_rx = jiffies;
++				/* nesvnic->netstats.rx_packets++; */
++				/* nesvnic->netstats.rx_bytes += rx_pkt_size; */
++			}
++
++			cq->cq_vbase[head].cqe_words[NES_NIC_CQE_MISC_IDX] = 0;
++			/* Accounting... */
++			cqe_count++;
++			if (++head >= cq_size)
++				head = 0;
++			if (cqe_count == 255) {
++				/* Replenish Nic CQ */
++				nes_write32(nesdev->regs+NES_CQE_ALLOC,
++						cq->cq_number | (cqe_count << 16));
++//				nesdev->nesadapter->tune_timer.cq_count += cqe_count;
++				nesdev->currcq_count += cqe_count;
++				cqe_count = 0;
++			}
++
++			if (cq->rx_cqes_completed >= nesvnic->budget)
++				break;
++		} else {
++			cq->cqes_pending = 0;
++			break;
++		}
++
++	} while (1);
++
++	if (sq_cqes) {
++		barrier();
++		/* restart the queue if it had been stopped */
++		if (netif_queue_stopped(nesvnic->netdev))
++			netif_wake_queue(nesvnic->netdev);
++	}
++
++	cq->cq_head = head;
++	/* nes_debug(NES_DBG_CQ, "CQ%u Processed = %u cqes, new head = %u.\n",
++			cq->cq_number, cqe_count, cq->cq_head); */
++	cq->cqe_allocs_pending = cqe_count;
++	if (unlikely(nesadapter->et_use_adaptive_rx_coalesce))
++	{
++//		nesdev->nesadapter->tune_timer.cq_count += cqe_count;
++		nesdev->currcq_count += cqe_count;
++		nes_nic_tune_timer(nesdev);
++	}
++	if (atomic_read(&nesvnic->rx_skbs_needed))
++		nes_replenish_nic_rq(nesvnic);
++	}
++
++
++/**
++ * nes_cqp_ce_handler
++ */
++void nes_cqp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *cq)
 +{
-+	/* Acquire mutex's based on pointer comparison to prevent deadlock. */
-+	if (file1 < file2) {
-+		mutex_lock(&file1->mut);
-+		mutex_lock(&file2->mut);
-+	} else {
-+		mutex_lock(&file2->mut);
-+		mutex_lock(&file1->mut);
++	u64 u64temp;
++	unsigned long flags;
++	struct nes_hw_cqp *cqp = NULL;
++	struct nes_cqp_request *cqp_request;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	u32 head;
++	u32 cq_size;
++	u32 cqe_count=0;
++	u32 error_code;
++	/* u32 counter; */
++
++	head = cq->cq_head;
++	cq_size = cq->cq_size;
++
++	do {
++		/* process the CQE */
++		/* nes_debug(NES_DBG_CQP, "head=%u cqe_words=%08X\n", head,
++			  le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])); */
++
++		if (le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_VALID) {
++			u64temp = (((u64)(le32_to_cpu(cq->cq_vbase[head].
++					cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
++					((u64)(le32_to_cpu(cq->cq_vbase[head].
++					cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX])));
++			cqp = *((struct nes_hw_cqp **)&u64temp);
++
++			error_code = le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_ERROR_CODE_IDX]);
++			if (error_code) {
++				nes_debug(NES_DBG_CQP, "Bad Completion code for opcode 0x%02X from CQP,"
++						" Major/Minor codes = 0x%04X:%04X.\n",
++						le32_to_cpu(cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX])&0x3f,
++						(u16)(error_code >> 16),
++						(u16)error_code);
++				nes_debug(NES_DBG_CQP, "cqp: qp_id=%u, sq_head=%u, sq_tail=%u\n",
++						cqp->qp_id, cqp->sq_head, cqp->sq_tail);
++			}
++
++			u64temp = (((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
++					wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX])))<<32) |
++					((u64)(le32_to_cpu(nesdev->cqp.sq_vbase[cqp->sq_tail].
++					wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX])));
++			cqp_request = *((struct nes_cqp_request **)&u64temp);
++			if (cqp_request) {
++				if (cqp_request->waiting) {
++					/* nes_debug(NES_DBG_CQP, "%s: Waking up requestor\n"); */
++					cqp_request->major_code = (u16)(error_code >> 16);
++					cqp_request->minor_code = (u16)error_code;
++					barrier();
++					cqp_request->request_done = 1;
++					wake_up(&cqp_request->waitq);
++					if (atomic_dec_and_test(&cqp_request->refcount)) {
++						nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n",
++								cqp_request,
++								le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f);
++						if (cqp_request->dynamic) {
++							kfree(cqp_request);
++						} else {
++							spin_lock_irqsave(&nesdev->cqp.lock, flags);
++							list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++							spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++						}
++					}
++				} else if (cqp_request->callback) {
++					/* Envoke the callback routine */
++					cqp_request->cqp_callback(nesdev, cqp_request);
++					if (cqp_request->dynamic) {
++						kfree(cqp_request);
++					} else {
++						spin_lock_irqsave(&nesdev->cqp.lock, flags);
++						list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++						spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++					}
++				} else {
++					nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) freed.\n",
++							cqp_request,
++							le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f);
++					if (cqp_request->dynamic) {
++						kfree(cqp_request);
++					} else {
++						spin_lock_irqsave(&nesdev->cqp.lock, flags);
++						list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++						spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++					}
++				}
++			} else {
++				wake_up(&nesdev->cqp.waitq);
++			}
++
++			cq->cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
++			nes_write32(nesdev->regs+NES_CQE_ALLOC, cq->cq_number | (1 << 16));
++			if (++cqp->sq_tail >= cqp->sq_size)
++				cqp->sq_tail = 0;
++
++			/* Accounting... */
++			cqe_count++;
++			if (++head >= cq_size)
++				head = 0;
++		} else {
++			break;
++		}
++	} while (1);
++	cq->cq_head = head;
++
++	spin_lock_irqsave(&nesdev->cqp.lock, flags);
++	while ((!list_empty(&nesdev->cqp_pending_reqs)) &&
++			((((nesdev->cqp.sq_tail+nesdev->cqp.sq_size)-nesdev->cqp.sq_head) &
++			(nesdev->cqp.sq_size - 1)) != 1)) {
++		cqp_request = list_entry(nesdev->cqp_pending_reqs.next,
++				struct nes_cqp_request, list);
++		list_del_init(&cqp_request->list);
++		head = nesdev->cqp.sq_head++;
++		nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++		cqp_wqe = &nesdev->cqp.sq_vbase[head];
++		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
++		barrier();
++		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_LOW_IDX] =
++			cpu_to_le32((u32)((unsigned long)cqp_request));
++		cqp_wqe->wqe_words[NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX] =
++			cpu_to_le32((u32)(upper_32_bits((unsigned long)cqp_request)));
++		nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X) put on CQPs SQ wqe%u.\n",
++				cqp_request, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f, head);
++		/* Ring doorbell (1 WQEs) */
++		barrier();
++		nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id);
 +	}
++	spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++
++	/* Arm the CCQ */
++	nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
++			cq->cq_number);
++	nes_read32(nesdev->regs+NES_CQE_ALLOC);
 +}
 +
-+static void ucma_unlock_files(struct ucma_file *file1, struct ucma_file *file2)
++
++/**
++ * nes_process_iwarp_aeqe
++ */
++void nes_process_iwarp_aeqe(struct nes_device *nesdev, struct nes_hw_aeqe *aeqe)
 +{
-+	if (file1 < file2) {
-+		mutex_unlock(&file2->mut);
-+		mutex_unlock(&file1->mut);
++	u64 context;
++	u64 aeqe_context = 0;
++	unsigned long flags;
++	struct nes_qp *nesqp;
++	int resource_allocated;
++	/* struct iw_cm_id *cm_id; */
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct ib_event ibevent;
++	/* struct iw_cm_event cm_event; */
++	u32 aeq_info;
++	u32 next_iwarp_state = 0;
++	u16 async_event_id;
++	u8 tcp_state;
++	u8 iwarp_state;
++
++	nes_debug(NES_DBG_AEQ, "\n");
++	aeq_info = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_MISC_IDX]);
++	if ((NES_AEQE_INBOUND_RDMA&aeq_info) || (!(NES_AEQE_QP&aeq_info))) {
++		context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
++		context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
 +	} else {
-+		mutex_unlock(&file1->mut);
-+		mutex_unlock(&file2->mut);
++		aeqe_context = le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_LOW_IDX]);
++		aeqe_context += ((u64)le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_CTXT_HIGH_IDX])) << 32;
++		context = (unsigned long)nesadapter->qp_table[le32_to_cpu(
++						aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
++		BUG_ON(!context);
++	}
++
++	async_event_id = (u16)aeq_info;
++	tcp_state = (aeq_info & NES_AEQE_TCP_STATE_MASK) >> NES_AEQE_TCP_STATE_SHIFT;
++	iwarp_state = (aeq_info & NES_AEQE_IWARP_STATE_MASK) >> NES_AEQE_IWARP_STATE_SHIFT;
++	nes_debug(NES_DBG_AEQ, "aeid = 0x%04X, qp-cq id = %d, aeqe = %p,"
++			" Tcp state = %s, iWARP state = %s\n",
++			async_event_id,
++			le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), aeqe,
++			nes_tcp_state_str[tcp_state], nes_iwarp_state_str[iwarp_state]);
++
++
++	switch (async_event_id) {
++		case NES_AEQE_AEID_LLP_FIN_RECEIVED:
++			nesqp = *((struct nes_qp **)&context);
++			if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
++				nesqp->cm_id->add_ref(nesqp->cm_id);
++				nes_add_ref(&nesqp->ibqp);
++				schedule_nes_timer(nesqp->cm_node, (struct sk_buff *)nesqp,
++						NES_TIMER_TYPE_CLOSE, 1, 0);
++				nes_debug(NES_DBG_AEQ, "QP%u Not decrementing QP refcount (%d),"
++						" need ae to finish up, original_last_aeq = 0x%04X."
++						" last_aeq = 0x%04X, scheduling timer. TCP state = %d\n",
++						nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++						async_event_id, nesqp->last_aeq, tcp_state);
++			}
++			if ((tcp_state != NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
++					(nesqp->ibqp_state != IB_QPS_RTS)) {
++				/* FIN Received but tcp state or IB state moved on,
++						should expect a	close complete */
++				return;
++			}
++		case NES_AEQE_AEID_LLP_CLOSE_COMPLETE:
++		case NES_AEQE_AEID_LLP_CONNECTION_RESET:
++		case NES_AEQE_AEID_TERMINATE_SENT:
++		case NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE:
++		case NES_AEQE_AEID_RESET_SENT:
++			nesqp = *((struct nes_qp **)&context);
++			if (async_event_id == NES_AEQE_AEID_RESET_SENT) {
++				tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++			}
++			nes_add_ref(&nesqp->ibqp);
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++
++			if ((tcp_state == NES_AEQE_TCP_STATE_CLOSED) ||
++					(tcp_state == NES_AEQE_TCP_STATE_TIME_WAIT)) {
++				nesqp->hte_added = 0;
++				spin_unlock_irqrestore(&nesqp->lock, flags);
++				nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u to remove hte\n",
++						nesqp->hwqp.qp_id);
++				nes_hw_modify_qp(nesdev, nesqp,
++						NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_DEL_HTE, 0);
++				spin_lock_irqsave(&nesqp->lock, flags);
++			}
++
++			if ((nesqp->ibqp_state == IB_QPS_RTS) &&
++					((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
++					(async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
++				switch (nesqp->hw_iwarp_state) {
++					case NES_AEQE_IWARP_STATE_RTS:
++						next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
++						nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
++						break;
++					case NES_AEQE_IWARP_STATE_TERMINATE:
++						next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
++						nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;
++						if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
++							next_iwarp_state |= 0x02000000;
++							nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++						}
++						break;
++					default:
++						next_iwarp_state = 0;
++				}
++				spin_unlock_irqrestore(&nesqp->lock, flags);
++				if (next_iwarp_state) {
++					nes_add_ref(&nesqp->ibqp);
++					nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
++							" also added another reference\n",
++							nesqp->hwqp.qp_id, next_iwarp_state);
++					nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
++				}
++				nes_cm_disconn(nesqp);
++			} else {
++				if (async_event_id ==  NES_AEQE_AEID_LLP_FIN_RECEIVED) {
++					/* FIN Received but ib state not RTS,
++							close complete will be on its way */
++					spin_unlock_irqrestore(&nesqp->lock, flags);
++					nes_rem_ref(&nesqp->ibqp);
++					return;
++				}
++				spin_unlock_irqrestore(&nesqp->lock, flags);
++				if (async_event_id == NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) {
++					next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000;
++					nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++					nes_debug(NES_DBG_AEQ, "issuing hw modifyqp for QP%u. next state = 0x%08X,"
++							" also added another reference\n",
++							nesqp->hwqp.qp_id, next_iwarp_state);
++					nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
++				}
++				nes_cm_disconn(nesqp);
++			}
++			break;
++		case NES_AEQE_AEID_LLP_TERMINATE_RECEIVED:
++			nesqp = *((struct nes_qp **)&context);
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TERMINATE_RECEIVED"
++					" event on QP%u \n  Q2 Data:\n",
++					nesqp->hwqp.qp_id);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_FATAL;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			if ((tcp_state == NES_AEQE_TCP_STATE_CLOSE_WAIT) ||
++					((nesqp->ibqp_state == IB_QPS_RTS)&&
++					(async_event_id == NES_AEQE_AEID_LLP_CONNECTION_RESET))) {
++				nes_add_ref(&nesqp->ibqp);
++				nes_cm_disconn(nesqp);
++			} else {
++				nesqp->in_disconnect = 0;
++				wake_up(&nesqp->kick_waitq);
++			}
++			break;
++		case NES_AEQE_AEID_LLP_TOO_MANY_RETRIES:
++			nesqp = *((struct nes_qp **)&context);
++			nes_add_ref(&nesqp->ibqp);
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
++			nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++			nesqp->last_aeq = async_event_id;
++			if (nesqp->cm_id) {
++				nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
++						" event on QP%u, remote IP = 0x%08X \n",
++						nesqp->hwqp.qp_id,
++						ntohl(nesqp->cm_id->remote_addr.sin_addr.s_addr));
++			} else {
++				nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_TOO_MANY_RETRIES"
++						" event on QP%u \n",
++						nesqp->hwqp.qp_id);
++			}
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR | NES_CQP_QP_RESET;
++			nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 0);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_FATAL;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			break;
++		case NES_AEQE_AEID_AMP_BAD_STAG_INDEX:
++			if (NES_AEQE_INBOUND_RDMA&aeq_info) {
++				nesqp = nesadapter->qp_table[le32_to_cpu(
++						aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
++			} else {
++				/* TODO: get the actual WQE and mask off wqe index */
++				context &= ~((u64)511);
++				nesqp = *((struct nes_qp **)&context);
++			}
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_BAD_STAG_INDEX event on QP%u\n",
++					nesqp->hwqp.qp_id);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_ACCESS_ERR;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			break;
++		case NES_AEQE_AEID_AMP_UNALLOCATED_STAG:
++			nesqp = *((struct nes_qp **)&context);
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_AMP_UNALLOCATED_STAG event on QP%u\n",
++					nesqp->hwqp.qp_id);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_ACCESS_ERR;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			break;
++		case NES_AEQE_AEID_PRIV_OPERATION_DENIED:
++			nesqp = nesadapter->qp_table[le32_to_cpu(aeqe->aeqe_words
++					[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_PRIV_OPERATION_DENIED event on QP%u,"
++					" nesqp = %p, AE reported %p\n",
++					nesqp->hwqp.qp_id, nesqp, *((struct nes_qp **)&context));
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_ACCESS_ERR;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			break;
++		case NES_AEQE_AEID_CQ_OPERATION_ERROR:
++			context <<= 1;
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u, %p\n",
++					le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]), (void *)(unsigned long)context);
++			resource_allocated = nes_is_resource_allocated(nesadapter, nesadapter->allocated_cqs,
++					le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
++			if (resource_allocated) {
++				printk(KERN_ERR PFX "%s: Processing an NES_AEQE_AEID_CQ_OPERATION_ERROR event on CQ%u\n",
++						__FUNCTION__, le32_to_cpu(aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX]));
++			}
++			break;
++		case NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER:
++			nesqp = nesadapter->qp_table[le32_to_cpu(
++					aeqe->aeqe_words[NES_AEQE_COMP_QP_CQ_ID_IDX])-NES_FIRST_QPN];
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG"
++					"_FOR_AVAILABLE_BUFFER event on QP%u\n",
++					nesqp->hwqp.qp_id);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_ACCESS_ERR;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			/* tell cm to disconnect, cm will queue work to thread */
++			nes_add_ref(&nesqp->ibqp);
++			nes_cm_disconn(nesqp);
++			break;
++		case NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE:
++			nesqp = *((struct nes_qp **)&context);
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_DDP_UBE_INVALID_MSN"
++					"_NO_BUFFER_AVAILABLE event on QP%u\n",
++					nesqp->hwqp.qp_id);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_FATAL;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			/* tell cm to disconnect, cm will queue work to thread */
++			nes_add_ref(&nesqp->ibqp);
++			nes_cm_disconn(nesqp);
++			break;
++		case NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR:
++			nesqp = *((struct nes_qp **)&context);
++			spin_lock_irqsave(&nesqp->lock, flags);
++			nesqp->hw_iwarp_state = iwarp_state;
++			nesqp->hw_tcp_state = tcp_state;
++			nesqp->last_aeq = async_event_id;
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++			nes_debug(NES_DBG_AEQ, "Processing an NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR"
++					" event on QP%u \n  Q2 Data:\n",
++					nesqp->hwqp.qp_id);
++			if (nesqp->ibqp.event_handler) {
++				ibevent.device = nesqp->ibqp.device;
++				ibevent.element.qp = &nesqp->ibqp;
++				ibevent.event = IB_EVENT_QP_FATAL;
++				nesqp->ibqp.event_handler(&ibevent, nesqp->ibqp.qp_context);
++			}
++			/* tell cm to disconnect, cm will queue work to thread */
++			nes_add_ref(&nesqp->ibqp);
++			nes_cm_disconn(nesqp);
++			break;
++			/* TODO: additional AEs need to be here */
++		default:
++			nes_debug(NES_DBG_AEQ, "Processing an iWARP related AE for QP, misc = 0x%04X\n",
++					async_event_id);
++			break;
 +	}
++
 +}
 +
-+static void ucma_move_events(struct ucma_context *ctx, struct ucma_file *file)
++
++/**
++ * nes_iwarp_ce_handler
++ */
++void nes_iwarp_ce_handler(struct nes_device *nesdev, struct nes_hw_cq *hw_cq)
 +{
-+	struct ucma_event *uevent, *tmp;
++	struct nes_cq *nescq = container_of(hw_cq, struct nes_cq, hw_cq);
 +
-+	list_for_each_entry_safe(uevent, tmp, &ctx->file->event_list, list)
-+		if (uevent->ctx == ctx)
-+			list_move_tail(&uevent->list, &file->event_list);
++	/* nes_debug(NES_DBG_CQ, "Processing completion event for iWARP CQ%u.\n",
++			nescq->hw_cq.cq_number); */
++	nes_write32(nesdev->regs+NES_CQ_ACK, nescq->hw_cq.cq_number);
++
++	if (nescq->ibcq.comp_handler)
++		nescq->ibcq.comp_handler(&nescq->ibcq, nescq->ibcq.cq_context);
++
++	return;
 +}
 +
-+static ssize_t ucma_migrate_id(struct ucma_file *new_file,
-+			       const char __user *inbuf,
-+			       int in_len, int out_len)
++
++/**
++ * nes_manage_apbvt()
++ */
++int nes_manage_apbvt(struct nes_vnic *nesvnic, u32 accel_local_port,
++		u32 nic_index, u32 add_port)
 +{
-+	struct rdma_ucm_migrate_id cmd;
-+	struct rdma_ucm_migrate_resp resp;
-+	struct ucma_context *ctx;
-+	struct file *filp;
-+	struct ucma_file *cur_file;
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	unsigned long flags;
++	struct nes_cqp_request *cqp_request;
 +	int ret = 0;
++	u16 major_code;
 +
-+	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
-+		return -EFAULT;
-+
-+	/* Get current fd to protect against it being closed */
-+	filp = fget(cmd.fd);
-+	if (!filp)
-+		return -ENOENT;
-+
-+	/* Validate current fd and prevent destruction of id. */
-+	ctx = ucma_get_ctx(filp->private_data, cmd.id);
-+	if (IS_ERR(ctx)) {
-+		ret = PTR_ERR(ctx);
-+		goto file_put;
++	/* Send manage APBVT request to CQP */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
++		return -ENOMEM;
 +	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
 +
-+	cur_file = ctx->file;
-+	if (cur_file == new_file) {
-+		resp.events_reported = ctx->events_reported;
-+		goto response;
++	nes_debug(NES_DBG_QP, "%s APBV for local port=%u(0x%04x), nic_index=%u\n",
++			(add_port == NES_MANAGE_APBVT_ADD) ? "ADD" : "DEL",
++			accel_local_port, accel_local_port, nic_index);
++
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, (NES_CQP_MANAGE_APBVT |
++			((add_port == NES_MANAGE_APBVT_ADD) ? NES_CQP_APBVT_ADD : 0)));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
++			((nic_index << NES_CQP_APBVT_NIC_SHIFT) | accel_local_port));
++
++	nes_debug(NES_DBG_QP, "Waiting for CQP completion for APBVT.\n");
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	if (add_port == NES_MANAGE_APBVT_ADD)
++		ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
++				NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_QP, "Completed, ret=%u,  CQP Major:Minor codes = 0x%04X:0x%04X\n",
++			ret, cqp_request->major_code, cqp_request->minor_code);
++	major_code = cqp_request->major_code;
++	if (atomic_dec_and_test(&cqp_request->refcount)) {
++		if (cqp_request->dynamic) {
++			kfree(cqp_request);
++		} else {
++			spin_lock_irqsave(&nesdev->cqp.lock, flags);
++			list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++			spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++		}
 +	}
++	if (!ret)
++		return -ETIME;
++	else if (major_code)
++		return -EIO;
++	else
++		return 0;
++}
 +
-+	/*
-+	 * Migrate events between fd's, maintaining order, and avoiding new
-+	 * events being added before existing events.
-+	 */
-+	ucma_lock_files(cur_file, new_file);
-+	mutex_lock(&mut);
 +
-+	list_move_tail(&ctx->list, &new_file->ctx_list);
-+	ucma_move_events(ctx, new_file);
-+	ctx->file = new_file;
-+	resp.events_reported = ctx->events_reported;
++/**
++ * nes_manage_arp_cache
++ */
++void nes_manage_arp_cache(struct net_device *netdev, unsigned char *mac_addr,
++		u32 ip_addr, u32 action)
++{
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev;
++	struct nes_cqp_request *cqp_request;
++	int arp_index;
++
++	nesdev = nesvnic->nesdev;
++	arp_index = nes_arp_table(nesdev, ip_addr, mac_addr, action);
++	if (arp_index == -1) {
++		return;
++	}
 +
-+	mutex_unlock(&mut);
-+	ucma_unlock_files(cur_file, new_file);
++	/* update the ARP entry */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_NETDEV, "Failed to get a cqp_request.\n");
++		return;
++	}
++	cqp_request->waiting = 0;
++	cqp_wqe = &cqp_request->cqp_wqe;
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] = cpu_to_le32(
++			NES_CQP_MANAGE_ARP_CACHE | NES_CQP_ARP_PERM);
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(
++			(u32)PCI_FUNC(nesdev->pcidev->devfn) << NES_CQP_ARP_AEQ_INDEX_SHIFT);
++	cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(arp_index);
++
++	if (action == NES_ARP_ADD) {
++		cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_ARP_VALID);
++		cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = cpu_to_le32(
++				(((u32)mac_addr[2]) << 24) | (((u32)mac_addr[3]) << 16) |
++				(((u32)mac_addr[4]) << 8) | (u32)mac_addr[5]);
++		cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = cpu_to_le32(
++				(((u32)mac_addr[0]) << 16) | (u32)mac_addr[1]);
++	} else {
++		cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX] = 0;
++		cqp_wqe->wqe_words[NES_CQP_ARP_WQE_MAC_HIGH_IDX] = 0;
++	}
 +
-+response:
-+	if (copy_to_user((void __user *)(unsigned long)cmd.response,
-+			 &resp, sizeof(resp)))
-+		ret = -EFAULT;
++	nes_debug(NES_DBG_NETDEV, "Not waiting for CQP, cqp.sq_head=%u, cqp.sq_tail=%u\n",
++			nesdev->cqp.sq_head, nesdev->cqp.sq_tail);
 +
-+	ucma_put_ctx(ctx);
-+file_put:
-+	fput(filp);
-+	return ret;
++	atomic_set(&cqp_request->refcount, 1);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
 +}
 +
- static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
- 				   const char __user *inbuf,
- 				   int in_len, int out_len) = {
-@@ -1012,6 +1103,7 @@ static ssize_t (*ucma_cmd_table[])(struct ucma_file *file,
- 	[RDMA_USER_CM_CMD_NOTIFY]	= ucma_notify,
- 	[RDMA_USER_CM_CMD_JOIN_MCAST]	= ucma_join_multicast,
- 	[RDMA_USER_CM_CMD_LEAVE_MCAST]	= ucma_leave_multicast,
-+	[RDMA_USER_CM_CMD_MIGRATE_ID]	= ucma_migrate_id
- };
- 
- static ssize_t ucma_write(struct file *filp, const char __user *buf,
-diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
-index b53eac4..4e91510 100644
---- a/drivers/infiniband/core/user_mad.c
-+++ b/drivers/infiniband/core/user_mad.c
-@@ -2,6 +2,7 @@
-  * Copyright (c) 2004 Topspin Communications.  All rights reserved.
-  * Copyright (c) 2005 Voltaire, Inc. All rights reserved.
-  * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
-+ * Copyright (c) 2008 Cisco. All rights reserved.
-  *
-  * This software is available to you under a choice of one of two
-  * licenses.  You may choose to be licensed under the terms of the GNU
-@@ -42,7 +43,7 @@
- #include <linux/cdev.h>
- #include <linux/dma-mapping.h>
- #include <linux/poll.h>
--#include <linux/rwsem.h>
-+#include <linux/mutex.h>
- #include <linux/kref.h>
- #include <linux/compat.h>
- 
-@@ -94,7 +95,7 @@ struct ib_umad_port {
- 	struct class_device   *sm_class_dev;
- 	struct semaphore       sm_sem;
- 
--	struct rw_semaphore    mutex;
-+	struct mutex	       file_mutex;
- 	struct list_head       file_list;
- 
- 	struct ib_device      *ib_dev;
-@@ -110,11 +111,11 @@ struct ib_umad_device {
- };
- 
- struct ib_umad_file {
-+	struct mutex		mutex;
- 	struct ib_umad_port    *port;
- 	struct list_head	recv_list;
- 	struct list_head	send_list;
- 	struct list_head	port_list;
--	spinlock_t		recv_lock;
- 	spinlock_t		send_lock;
- 	wait_queue_head_t	recv_wait;
- 	struct ib_mad_agent    *agent[IB_UMAD_MAX_AGENTS];
-@@ -156,7 +157,7 @@ static int hdr_size(struct ib_umad_file *file)
- 		sizeof (struct ib_user_mad_hdr_old);
- }
- 
--/* caller must hold port->mutex at least for reading */
-+/* caller must hold file->mutex */
- static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
- {
- 	return file->agents_dead ? NULL : file->agent[id];
-@@ -168,32 +169,30 @@ static int queue_packet(struct ib_umad_file *file,
- {
- 	int ret = 1;
- 
--	down_read(&file->port->mutex);
-+	mutex_lock(&file->mutex);
- 
- 	for (packet->mad.hdr.id = 0;
- 	     packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
- 	     packet->mad.hdr.id++)
- 		if (agent == __get_agent(file, packet->mad.hdr.id)) {
--			spin_lock_irq(&file->recv_lock);
- 			list_add_tail(&packet->list, &file->recv_list);
--			spin_unlock_irq(&file->recv_lock);
- 			wake_up_interruptible(&file->recv_wait);
- 			ret = 0;
- 			break;
- 		}
- 
--	up_read(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
- 
- 	return ret;
- }
- 
- static void dequeue_send(struct ib_umad_file *file,
- 			 struct ib_umad_packet *packet)
-- {
++
++/**
++ * flush_wqes
++ */
++void flush_wqes(struct nes_device *nesdev, struct nes_qp *nesqp,
++		u32 which_wq, u32 wait_completion)
 +{
- 	spin_lock_irq(&file->send_lock);
- 	list_del(&packet->list);
- 	spin_unlock_irq(&file->send_lock);
-- }
++	unsigned long flags;
++	struct nes_cqp_request *cqp_request;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	int ret;
++
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_QP, "Failed to get a cqp_request.\n");
++		return;
++	}
++	if (wait_completion) {
++		cqp_request->waiting = 1;
++		atomic_set(&cqp_request->refcount, 2);
++	} else {
++		cqp_request->waiting = 0;
++	}
++	cqp_wqe = &cqp_request->cqp_wqe;
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
++			cpu_to_le32(NES_CQP_FLUSH_WQES | which_wq);
++	cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX] = cpu_to_le32(nesqp->hwqp.qp_id);
++
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	if (wait_completion) {
++		/* Wait for CQP */
++		ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
++				NES_EVENT_TIMEOUT);
++		nes_debug(NES_DBG_QP, "Flush SQ QP WQEs completed, ret=%u,"
++				" CQP Major:Minor codes = 0x%04X:0x%04X\n",
++				ret, cqp_request->major_code, cqp_request->minor_code);
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++	}
 +}
- 
- static void send_handler(struct ib_mad_agent *agent,
- 			 struct ib_mad_send_wc *send_wc)
-@@ -341,10 +340,10 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
- 	if (count < hdr_size(file))
- 		return -EINVAL;
- 
--	spin_lock_irq(&file->recv_lock);
-+	mutex_lock(&file->mutex);
- 
- 	while (list_empty(&file->recv_list)) {
--		spin_unlock_irq(&file->recv_lock);
-+		mutex_unlock(&file->mutex);
- 
- 		if (filp->f_flags & O_NONBLOCK)
- 			return -EAGAIN;
-@@ -353,13 +352,13 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
- 					     !list_empty(&file->recv_list)))
- 			return -ERESTARTSYS;
- 
--		spin_lock_irq(&file->recv_lock);
-+		mutex_lock(&file->mutex);
- 	}
- 
- 	packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
- 	list_del(&packet->list);
- 
--	spin_unlock_irq(&file->recv_lock);
-+	mutex_unlock(&file->mutex);
- 
- 	if (packet->recv_wc)
- 		ret = copy_recv_mad(file, buf, packet, count);
-@@ -368,9 +367,9 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
- 
- 	if (ret < 0) {
- 		/* Requeue packet */
--		spin_lock_irq(&file->recv_lock);
-+		mutex_lock(&file->mutex);
- 		list_add(&packet->list, &file->recv_list);
--		spin_unlock_irq(&file->recv_lock);
-+		mutex_unlock(&file->mutex);
- 	} else {
- 		if (packet->recv_wc)
- 			ib_free_recv_mad(packet->recv_wc);
-@@ -481,7 +480,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
- 		goto err;
- 	}
- 
--	down_read(&file->port->mutex);
-+	mutex_lock(&file->mutex);
- 
- 	agent = __get_agent(file, packet->mad.hdr.id);
- 	if (!agent) {
-@@ -577,7 +576,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
- 	if (ret)
- 		goto err_send;
- 
--	up_read(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
- 	return count;
- 
- err_send:
-@@ -587,7 +586,7 @@ err_msg:
- err_ah:
- 	ib_destroy_ah(ah);
- err_up:
--	up_read(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
- err:
- 	kfree(packet);
- 	return ret;
-@@ -613,11 +612,12 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, void __user *arg,
- {
- 	struct ib_user_mad_reg_req ureq;
- 	struct ib_mad_reg_req req;
--	struct ib_mad_agent *agent;
-+	struct ib_mad_agent *agent = NULL;
- 	int agent_id;
- 	int ret;
- 
--	down_write(&file->port->mutex);
-+	mutex_lock(&file->port->file_mutex);
-+	mutex_lock(&file->mutex);
- 
- 	if (!file->port->ib_dev) {
- 		ret = -EPIPE;
-@@ -666,13 +666,13 @@ found:
- 				      send_handler, recv_handler, file);
- 	if (IS_ERR(agent)) {
- 		ret = PTR_ERR(agent);
-+		agent = NULL;
- 		goto out;
- 	}
- 
- 	if (put_user(agent_id,
- 		     (u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) {
- 		ret = -EFAULT;
--		ib_unregister_mad_agent(agent);
- 		goto out;
- 	}
- 
-@@ -690,7 +690,13 @@ found:
- 	ret = 0;
- 
- out:
--	up_write(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
+diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
+new file mode 100644
+index 0000000..1e10df5
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_hw.h
+@@ -0,0 +1,1206 @@
++/*
++* Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++*
++* This software is available to you under a choice of one of two
++* licenses.  You may choose to be licensed under the terms of the GNU
++* General Public License (GPL) Version 2, available from the file
++* COPYING in the main directory of this source tree, or the
++* OpenIB.org BSD license below:
++*
++*     Redistribution and use in source and binary forms, with or
++*     without modification, are permitted provided that the following
++*     conditions are met:
++*
++*      - Redistributions of source code must retain the above
++*        copyright notice, this list of conditions and the following
++*        disclaimer.
++*
++*      - Redistributions in binary form must reproduce the above
++*        copyright notice, this list of conditions and the following
++*        disclaimer in the documentation and/or other materials
++*        provided with the distribution.
++*
++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++* SOFTWARE.
++*/
 +
-+	if (ret && agent)
-+		ib_unregister_mad_agent(agent);
++#ifndef __NES_HW_H
++#define __NES_HW_H
 +
-+	mutex_unlock(&file->port->file_mutex);
++#define NES_PHY_TYPE_1G   2
++#define NES_PHY_TYPE_IRIS 3
++#define NES_PHY_TYPE_PUMA_10G  6
++
++#define NES_MULTICAST_PF_MAX 8
++
++enum pci_regs {
++	NES_INT_STAT = 0x0000,
++	NES_INT_MASK = 0x0004,
++	NES_INT_PENDING = 0x0008,
++	NES_INTF_INT_STAT = 0x000C,
++	NES_INTF_INT_MASK = 0x0010,
++	NES_TIMER_STAT = 0x0014,
++	NES_PERIODIC_CONTROL = 0x0018,
++	NES_ONE_SHOT_CONTROL = 0x001C,
++	NES_EEPROM_COMMAND = 0x0020,
++	NES_EEPROM_DATA = 0x0024,
++	NES_FLASH_COMMAND = 0x0028,
++	NES_FLASH_DATA  = 0x002C,
++	NES_SOFTWARE_RESET = 0x0030,
++	NES_CQ_ACK = 0x0034,
++	NES_WQE_ALLOC = 0x0040,
++	NES_CQE_ALLOC = 0x0044,
++};
++
++enum indexed_regs {
++	NES_IDX_CREATE_CQP_LOW = 0x0000,
++	NES_IDX_CREATE_CQP_HIGH = 0x0004,
++	NES_IDX_QP_CONTROL = 0x0040,
++	NES_IDX_FLM_CONTROL = 0x0080,
++	NES_IDX_INT_CPU_STATUS = 0x00a0,
++	NES_IDX_GPIO_CONTROL = 0x00f0,
++	NES_IDX_GPIO_DATA = 0x00f4,
++	NES_IDX_TCP_CONFIG0 = 0x01e4,
++	NES_IDX_TCP_TIMER_CONFIG = 0x01ec,
++	NES_IDX_TCP_NOW = 0x01f0,
++	NES_IDX_QP_MAX_CFG_SIZES = 0x0200,
++	NES_IDX_QP_CTX_SIZE = 0x0218,
++	NES_IDX_TCP_TIMER_SIZE0 = 0x0238,
++	NES_IDX_TCP_TIMER_SIZE1 = 0x0240,
++	NES_IDX_ARP_CACHE_SIZE = 0x0258,
++	NES_IDX_CQ_CTX_SIZE = 0x0260,
++	NES_IDX_MRT_SIZE = 0x0278,
++	NES_IDX_PBL_REGION_SIZE = 0x0280,
++	NES_IDX_IRRQ_COUNT = 0x02b0,
++	NES_IDX_RX_WINDOW_BUFFER_PAGE_TABLE_SIZE = 0x02f0,
++	NES_IDX_RX_WINDOW_BUFFER_SIZE = 0x0300,
++	NES_IDX_DST_IP_ADDR = 0x0400,
++	NES_IDX_PCIX_DIAG = 0x08e8,
++	NES_IDX_MPP_DEBUG = 0x0a00,
++	NES_IDX_PORT_RX_DISCARDS = 0x0a30,
++	NES_IDX_PORT_TX_DISCARDS = 0x0a34,
++	NES_IDX_MPP_LB_DEBUG = 0x0b00,
++	NES_IDX_DENALI_CTL_22 = 0x1058,
++	NES_IDX_MAC_TX_CONTROL = 0x2000,
++	NES_IDX_MAC_TX_CONFIG = 0x2004,
++	NES_IDX_MAC_TX_PAUSE_QUANTA = 0x2008,
++	NES_IDX_MAC_RX_CONTROL = 0x200c,
++	NES_IDX_MAC_RX_CONFIG = 0x2010,
++	NES_IDX_MAC_EXACT_MATCH_BOTTOM = 0x201c,
++	NES_IDX_MAC_MDIO_CONTROL = 0x2084,
++	NES_IDX_MAC_TX_OCTETS_LOW = 0x2100,
++	NES_IDX_MAC_TX_OCTETS_HIGH = 0x2104,
++	NES_IDX_MAC_TX_FRAMES_LOW = 0x2108,
++	NES_IDX_MAC_TX_FRAMES_HIGH = 0x210c,
++	NES_IDX_MAC_TX_PAUSE_FRAMES = 0x2118,
++	NES_IDX_MAC_TX_ERRORS = 0x2138,
++	NES_IDX_MAC_RX_OCTETS_LOW = 0x213c,
++	NES_IDX_MAC_RX_OCTETS_HIGH = 0x2140,
++	NES_IDX_MAC_RX_FRAMES_LOW = 0x2144,
++	NES_IDX_MAC_RX_FRAMES_HIGH = 0x2148,
++	NES_IDX_MAC_RX_BC_FRAMES_LOW = 0x214c,
++	NES_IDX_MAC_RX_MC_FRAMES_HIGH = 0x2150,
++	NES_IDX_MAC_RX_PAUSE_FRAMES = 0x2154,
++	NES_IDX_MAC_RX_SHORT_FRAMES = 0x2174,
++	NES_IDX_MAC_RX_OVERSIZED_FRAMES = 0x2178,
++	NES_IDX_MAC_RX_JABBER_FRAMES = 0x217c,
++	NES_IDX_MAC_RX_CRC_ERR_FRAMES = 0x2180,
++	NES_IDX_MAC_RX_LENGTH_ERR_FRAMES = 0x2184,
++	NES_IDX_MAC_RX_SYMBOL_ERR_FRAMES = 0x2188,
++	NES_IDX_MAC_INT_STATUS = 0x21f0,
++	NES_IDX_MAC_INT_MASK = 0x21f4,
++	NES_IDX_PHY_PCS_CONTROL_STATUS0 = 0x2800,
++	NES_IDX_PHY_PCS_CONTROL_STATUS1 = 0x2a00,
++	NES_IDX_ETH_SERDES_COMMON_CONTROL0 = 0x2808,
++	NES_IDX_ETH_SERDES_COMMON_CONTROL1 = 0x2a08,
++	NES_IDX_ETH_SERDES_COMMON_STATUS0 = 0x280c,
++	NES_IDX_ETH_SERDES_COMMON_STATUS1 = 0x2a0c,
++	NES_IDX_ETH_SERDES_TX_EMP0 = 0x2810,
++	NES_IDX_ETH_SERDES_TX_EMP1 = 0x2a10,
++	NES_IDX_ETH_SERDES_TX_DRIVE0 = 0x2814,
++	NES_IDX_ETH_SERDES_TX_DRIVE1 = 0x2a14,
++	NES_IDX_ETH_SERDES_RX_MODE0 = 0x2818,
++	NES_IDX_ETH_SERDES_RX_MODE1 = 0x2a18,
++	NES_IDX_ETH_SERDES_RX_SIGDET0 = 0x281c,
++	NES_IDX_ETH_SERDES_RX_SIGDET1 = 0x2a1c,
++	NES_IDX_ETH_SERDES_BYPASS0 = 0x2820,
++	NES_IDX_ETH_SERDES_BYPASS1 = 0x2a20,
++	NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0 = 0x2824,
++	NES_IDX_ETH_SERDES_LOOPBACK_CONTROL1 = 0x2a24,
++	NES_IDX_ETH_SERDES_RX_EQ_CONTROL0 = 0x2828,
++	NES_IDX_ETH_SERDES_RX_EQ_CONTROL1 = 0x2a28,
++	NES_IDX_ETH_SERDES_RX_EQ_STATUS0 = 0x282c,
++	NES_IDX_ETH_SERDES_RX_EQ_STATUS1 = 0x2a2c,
++	NES_IDX_ETH_SERDES_CDR_RESET0 = 0x2830,
++	NES_IDX_ETH_SERDES_CDR_RESET1 = 0x2a30,
++	NES_IDX_ETH_SERDES_CDR_CONTROL0 = 0x2834,
++	NES_IDX_ETH_SERDES_CDR_CONTROL1 = 0x2a34,
++	NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE0 = 0x2838,
++	NES_IDX_ETH_SERDES_TX_HIGHZ_LANE_MODE1 = 0x2a38,
++	NES_IDX_ENDNODE0_NSTAT_RX_DISCARD = 0x3080,
++	NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO = 0x3000,
++	NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI = 0x3004,
++	NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO = 0x3008,
++	NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI = 0x300c,
++	NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO = 0x7000,
++	NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI = 0x7004,
++	NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO = 0x7008,
++	NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI = 0x700c,
++	NES_IDX_CM_CONFIG = 0x5100,
++	NES_IDX_NIC_LOGPORT_TO_PHYPORT = 0x6000,
++	NES_IDX_NIC_PHYPORT_TO_USW = 0x6008,
++	NES_IDX_NIC_ACTIVE = 0x6010,
++	NES_IDX_NIC_UNICAST_ALL = 0x6018,
++	NES_IDX_NIC_MULTICAST_ALL = 0x6020,
++	NES_IDX_NIC_MULTICAST_ENABLE = 0x6028,
++	NES_IDX_NIC_BROADCAST_ON = 0x6030,
++	NES_IDX_USED_CHUNKS_TX = 0x60b0,
++	NES_IDX_TX_POOL_SIZE = 0x60b8,
++	NES_IDX_QUAD_HASH_TABLE_SIZE = 0x6148,
++	NES_IDX_PERFECT_FILTER_LOW = 0x6200,
++	NES_IDX_PERFECT_FILTER_HIGH = 0x6204,
++	NES_IDX_IPV4_TCP_REXMITS = 0x7080,
++	NES_IDX_DEBUG_ERROR_CONTROL_STATUS = 0x913c,
++	NES_IDX_DEBUG_ERROR_MASKS0 = 0x9140,
++	NES_IDX_DEBUG_ERROR_MASKS1 = 0x9144,
++	NES_IDX_DEBUG_ERROR_MASKS2 = 0x9148,
++	NES_IDX_DEBUG_ERROR_MASKS3 = 0x914c,
++	NES_IDX_DEBUG_ERROR_MASKS4 = 0x9150,
++	NES_IDX_DEBUG_ERROR_MASKS5 = 0x9154,
++};
++
++#define NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE   1
++#define NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE (1 << 17)
++
++enum nes_cqp_opcodes {
++	NES_CQP_CREATE_QP = 0x00,
++	NES_CQP_MODIFY_QP = 0x01,
++	NES_CQP_DESTROY_QP = 0x02,
++	NES_CQP_CREATE_CQ = 0x03,
++	NES_CQP_MODIFY_CQ = 0x04,
++	NES_CQP_DESTROY_CQ = 0x05,
++	NES_CQP_ALLOCATE_STAG = 0x09,
++	NES_CQP_REGISTER_STAG = 0x0a,
++	NES_CQP_QUERY_STAG = 0x0b,
++	NES_CQP_REGISTER_SHARED_STAG = 0x0c,
++	NES_CQP_DEALLOCATE_STAG = 0x0d,
++	NES_CQP_MANAGE_ARP_CACHE = 0x0f,
++	NES_CQP_SUSPEND_QPS = 0x11,
++	NES_CQP_UPLOAD_CONTEXT = 0x13,
++	NES_CQP_CREATE_CEQ = 0x16,
++	NES_CQP_DESTROY_CEQ = 0x18,
++	NES_CQP_CREATE_AEQ = 0x19,
++	NES_CQP_DESTROY_AEQ = 0x1b,
++	NES_CQP_LMI_ACCESS = 0x20,
++	NES_CQP_FLUSH_WQES = 0x22,
++	NES_CQP_MANAGE_APBVT = 0x23
++};
++
++enum nes_cqp_wqe_word_idx {
++	NES_CQP_WQE_OPCODE_IDX = 0,
++	NES_CQP_WQE_ID_IDX = 1,
++	NES_CQP_WQE_COMP_CTX_LOW_IDX = 2,
++	NES_CQP_WQE_COMP_CTX_HIGH_IDX = 3,
++	NES_CQP_WQE_COMP_SCRATCH_LOW_IDX = 4,
++	NES_CQP_WQE_COMP_SCRATCH_HIGH_IDX = 5,
++};
++
++enum nes_cqp_cq_wqeword_idx {
++	NES_CQP_CQ_WQE_PBL_LOW_IDX = 6,
++	NES_CQP_CQ_WQE_PBL_HIGH_IDX = 7,
++	NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX = 8,
++	NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX = 9,
++	NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX = 10,
++};
++
++enum nes_cqp_stag_wqeword_idx {
++	NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX = 1,
++	NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX = 6,
++	NES_CQP_STAG_WQE_LEN_LOW_IDX = 7,
++	NES_CQP_STAG_WQE_STAG_IDX = 8,
++	NES_CQP_STAG_WQE_VA_LOW_IDX = 10,
++	NES_CQP_STAG_WQE_VA_HIGH_IDX = 11,
++	NES_CQP_STAG_WQE_PA_LOW_IDX = 12,
++	NES_CQP_STAG_WQE_PA_HIGH_IDX = 13,
++	NES_CQP_STAG_WQE_PBL_LEN_IDX = 14
++};
++
++#define NES_CQP_OP_IWARP_STATE_SHIFT 28
++
++enum nes_cqp_qp_bits {
++	NES_CQP_QP_ARP_VALID = (1<<8),
++	NES_CQP_QP_WINBUF_VALID = (1<<9),
++	NES_CQP_QP_CONTEXT_VALID = (1<<10),
++	NES_CQP_QP_ORD_VALID = (1<<11),
++	NES_CQP_QP_WINBUF_DATAIND_EN = (1<<12),
++	NES_CQP_QP_VIRT_WQS = (1<<13),
++	NES_CQP_QP_DEL_HTE = (1<<14),
++	NES_CQP_QP_CQS_VALID = (1<<15),
++	NES_CQP_QP_TYPE_TSA = 0,
++	NES_CQP_QP_TYPE_IWARP = (1<<16),
++	NES_CQP_QP_TYPE_CQP = (4<<16),
++	NES_CQP_QP_TYPE_NIC = (5<<16),
++	NES_CQP_QP_MSS_CHG = (1<<20),
++	NES_CQP_QP_STATIC_RESOURCES = (1<<21),
++	NES_CQP_QP_IGNORE_MW_BOUND = (1<<22),
++	NES_CQP_QP_VWQ_USE_LMI = (1<<23),
++	NES_CQP_QP_IWARP_STATE_IDLE = (1<<NES_CQP_OP_IWARP_STATE_SHIFT),
++	NES_CQP_QP_IWARP_STATE_RTS = (2<<NES_CQP_OP_IWARP_STATE_SHIFT),
++	NES_CQP_QP_IWARP_STATE_CLOSING = (3<<NES_CQP_OP_IWARP_STATE_SHIFT),
++	NES_CQP_QP_IWARP_STATE_TERMINATE = (5<<NES_CQP_OP_IWARP_STATE_SHIFT),
++	NES_CQP_QP_IWARP_STATE_ERROR = (6<<NES_CQP_OP_IWARP_STATE_SHIFT),
++	NES_CQP_QP_IWARP_STATE_MASK = (7<<NES_CQP_OP_IWARP_STATE_SHIFT),
++	NES_CQP_QP_RESET = (1<<31),
++};
++
++enum nes_cqp_qp_wqe_word_idx {
++	NES_CQP_QP_WQE_CONTEXT_LOW_IDX = 6,
++	NES_CQP_QP_WQE_CONTEXT_HIGH_IDX = 7,
++	NES_CQP_QP_WQE_NEW_MSS_IDX = 15,
++};
++
++enum nes_nic_ctx_bits {
++	NES_NIC_CTX_RQ_SIZE_32 = (3<<8),
++	NES_NIC_CTX_RQ_SIZE_512 = (3<<8),
++	NES_NIC_CTX_SQ_SIZE_32 = (1<<10),
++	NES_NIC_CTX_SQ_SIZE_512 = (3<<10),
++};
++
++enum nes_nic_qp_ctx_word_idx {
++	NES_NIC_CTX_MISC_IDX = 0,
++	NES_NIC_CTX_SQ_LOW_IDX = 2,
++	NES_NIC_CTX_SQ_HIGH_IDX = 3,
++	NES_NIC_CTX_RQ_LOW_IDX = 4,
++	NES_NIC_CTX_RQ_HIGH_IDX = 5,
++};
++
++enum nes_cqp_cq_bits {
++	NES_CQP_CQ_CEQE_MASK = (1<<9),
++	NES_CQP_CQ_CEQ_VALID = (1<<10),
++	NES_CQP_CQ_RESIZE = (1<<11),
++	NES_CQP_CQ_CHK_OVERFLOW = (1<<12),
++	NES_CQP_CQ_4KB_CHUNK = (1<<14),
++	NES_CQP_CQ_VIRT = (1<<15),
++};
++
++enum nes_cqp_stag_bits {
++	NES_CQP_STAG_VA_TO = (1<<9),
++	NES_CQP_STAG_DEALLOC_PBLS = (1<<10),
++	NES_CQP_STAG_PBL_BLK_SIZE = (1<<11),
++	NES_CQP_STAG_MR = (1<<13),
++	NES_CQP_STAG_RIGHTS_LOCAL_READ = (1<<16),
++	NES_CQP_STAG_RIGHTS_LOCAL_WRITE = (1<<17),
++	NES_CQP_STAG_RIGHTS_REMOTE_READ = (1<<18),
++	NES_CQP_STAG_RIGHTS_REMOTE_WRITE = (1<<19),
++	NES_CQP_STAG_RIGHTS_WINDOW_BIND = (1<<20),
++	NES_CQP_STAG_REM_ACC_EN = (1<<21),
++	NES_CQP_STAG_LEAVE_PENDING = (1<<31),
++};
++
++enum nes_cqp_ceq_wqeword_idx {
++	NES_CQP_CEQ_WQE_ELEMENT_COUNT_IDX = 1,
++	NES_CQP_CEQ_WQE_PBL_LOW_IDX = 6,
++	NES_CQP_CEQ_WQE_PBL_HIGH_IDX = 7,
++};
++
++enum nes_cqp_ceq_bits {
++	NES_CQP_CEQ_4KB_CHUNK = (1<<14),
++	NES_CQP_CEQ_VIRT = (1<<15),
++};
++
++enum nes_cqp_aeq_wqeword_idx {
++	NES_CQP_AEQ_WQE_ELEMENT_COUNT_IDX = 1,
++	NES_CQP_AEQ_WQE_PBL_LOW_IDX = 6,
++	NES_CQP_AEQ_WQE_PBL_HIGH_IDX = 7,
++};
++
++enum nes_cqp_aeq_bits {
++	NES_CQP_AEQ_4KB_CHUNK = (1<<14),
++	NES_CQP_AEQ_VIRT = (1<<15),
++};
++
++enum nes_cqp_lmi_wqeword_idx {
++	NES_CQP_LMI_WQE_LMI_OFFSET_IDX = 1,
++	NES_CQP_LMI_WQE_FRAG_LOW_IDX = 8,
++	NES_CQP_LMI_WQE_FRAG_HIGH_IDX = 9,
++	NES_CQP_LMI_WQE_FRAG_LEN_IDX = 10,
++};
++
++enum nes_cqp_arp_wqeword_idx {
++	NES_CQP_ARP_WQE_MAC_ADDR_LOW_IDX = 6,
++	NES_CQP_ARP_WQE_MAC_HIGH_IDX = 7,
++	NES_CQP_ARP_WQE_REACHABILITY_MAX_IDX = 1,
++};
++
++enum nes_cqp_upload_wqeword_idx {
++	NES_CQP_UPLOAD_WQE_CTXT_LOW_IDX = 6,
++	NES_CQP_UPLOAD_WQE_CTXT_HIGH_IDX = 7,
++	NES_CQP_UPLOAD_WQE_HTE_IDX = 8,
++};
++
++enum nes_cqp_arp_bits {
++	NES_CQP_ARP_VALID = (1<<8),
++	NES_CQP_ARP_PERM = (1<<9),
++};
++
++enum nes_cqp_flush_bits {
++	NES_CQP_FLUSH_SQ = (1<<30),
++	NES_CQP_FLUSH_RQ = (1<<31),
++};
++
++enum nes_cqe_opcode_bits {
++	NES_CQE_STAG_VALID = (1<<6),
++	NES_CQE_ERROR = (1<<7),
++	NES_CQE_SQ = (1<<8),
++	NES_CQE_SE = (1<<9),
++	NES_CQE_PSH = (1<<29),
++	NES_CQE_FIN = (1<<30),
++	NES_CQE_VALID = (1<<31),
++};
++
++
++enum nes_cqe_word_idx {
++	NES_CQE_PAYLOAD_LENGTH_IDX = 0,
++	NES_CQE_COMP_COMP_CTX_LOW_IDX = 2,
++	NES_CQE_COMP_COMP_CTX_HIGH_IDX = 3,
++	NES_CQE_INV_STAG_IDX = 4,
++	NES_CQE_QP_ID_IDX = 5,
++	NES_CQE_ERROR_CODE_IDX = 6,
++	NES_CQE_OPCODE_IDX = 7,
++};
++
++enum nes_ceqe_word_idx {
++	NES_CEQE_CQ_CTX_LOW_IDX = 0,
++	NES_CEQE_CQ_CTX_HIGH_IDX = 1,
++};
++
++enum nes_ceqe_status_bit {
++	NES_CEQE_VALID = (1<<31),
++};
++
++enum nes_int_bits {
++	NES_INT_CEQ0 = (1<<0),
++	NES_INT_CEQ1 = (1<<1),
++	NES_INT_CEQ2 = (1<<2),
++	NES_INT_CEQ3 = (1<<3),
++	NES_INT_CEQ4 = (1<<4),
++	NES_INT_CEQ5 = (1<<5),
++	NES_INT_CEQ6 = (1<<6),
++	NES_INT_CEQ7 = (1<<7),
++	NES_INT_CEQ8 = (1<<8),
++	NES_INT_CEQ9 = (1<<9),
++	NES_INT_CEQ10 = (1<<10),
++	NES_INT_CEQ11 = (1<<11),
++	NES_INT_CEQ12 = (1<<12),
++	NES_INT_CEQ13 = (1<<13),
++	NES_INT_CEQ14 = (1<<14),
++	NES_INT_CEQ15 = (1<<15),
++	NES_INT_AEQ0 = (1<<16),
++	NES_INT_AEQ1 = (1<<17),
++	NES_INT_AEQ2 = (1<<18),
++	NES_INT_AEQ3 = (1<<19),
++	NES_INT_AEQ4 = (1<<20),
++	NES_INT_AEQ5 = (1<<21),
++	NES_INT_AEQ6 = (1<<22),
++	NES_INT_AEQ7 = (1<<23),
++	NES_INT_MAC0 = (1<<24),
++	NES_INT_MAC1 = (1<<25),
++	NES_INT_MAC2 = (1<<26),
++	NES_INT_MAC3 = (1<<27),
++	NES_INT_TSW = (1<<28),
++	NES_INT_TIMER = (1<<29),
++	NES_INT_INTF = (1<<30),
++};
++
++enum nes_intf_int_bits {
++	NES_INTF_INT_PCIERR = (1<<0),
++	NES_INTF_PERIODIC_TIMER = (1<<2),
++	NES_INTF_ONE_SHOT_TIMER = (1<<3),
++	NES_INTF_INT_CRITERR = (1<<14),
++	NES_INTF_INT_AEQ0_OFLOW = (1<<16),
++	NES_INTF_INT_AEQ1_OFLOW = (1<<17),
++	NES_INTF_INT_AEQ2_OFLOW = (1<<18),
++	NES_INTF_INT_AEQ3_OFLOW = (1<<19),
++	NES_INTF_INT_AEQ4_OFLOW = (1<<20),
++	NES_INTF_INT_AEQ5_OFLOW = (1<<21),
++	NES_INTF_INT_AEQ6_OFLOW = (1<<22),
++	NES_INTF_INT_AEQ7_OFLOW = (1<<23),
++	NES_INTF_INT_AEQ_OFLOW = (0xff<<16),
++};
++
++enum nes_mac_int_bits {
++	NES_MAC_INT_LINK_STAT_CHG = (1<<1),
++	NES_MAC_INT_XGMII_EXT = (1<<2),
++	NES_MAC_INT_TX_UNDERFLOW = (1<<6),
++	NES_MAC_INT_TX_ERROR = (1<<7),
++};
++
++enum nes_cqe_allocate_bits {
++	NES_CQE_ALLOC_INC_SELECT = (1<<28),
++	NES_CQE_ALLOC_NOTIFY_NEXT = (1<<29),
++	NES_CQE_ALLOC_NOTIFY_SE = (1<<30),
++	NES_CQE_ALLOC_RESET = (1<<31),
++};
++
++enum nes_nic_rq_wqe_word_idx {
++	NES_NIC_RQ_WQE_LENGTH_1_0_IDX = 0,
++	NES_NIC_RQ_WQE_LENGTH_3_2_IDX = 1,
++	NES_NIC_RQ_WQE_FRAG0_LOW_IDX = 2,
++	NES_NIC_RQ_WQE_FRAG0_HIGH_IDX = 3,
++	NES_NIC_RQ_WQE_FRAG1_LOW_IDX = 4,
++	NES_NIC_RQ_WQE_FRAG1_HIGH_IDX = 5,
++	NES_NIC_RQ_WQE_FRAG2_LOW_IDX = 6,
++	NES_NIC_RQ_WQE_FRAG2_HIGH_IDX = 7,
++	NES_NIC_RQ_WQE_FRAG3_LOW_IDX = 8,
++	NES_NIC_RQ_WQE_FRAG3_HIGH_IDX = 9,
++};
++
++enum nes_nic_sq_wqe_word_idx {
++	NES_NIC_SQ_WQE_MISC_IDX = 0,
++	NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX = 1,
++	NES_NIC_SQ_WQE_LSO_INFO_IDX = 2,
++	NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX = 3,
++	NES_NIC_SQ_WQE_LENGTH_2_1_IDX = 4,
++	NES_NIC_SQ_WQE_LENGTH_4_3_IDX = 5,
++	NES_NIC_SQ_WQE_FRAG0_LOW_IDX = 6,
++	NES_NIC_SQ_WQE_FRAG0_HIGH_IDX = 7,
++	NES_NIC_SQ_WQE_FRAG1_LOW_IDX = 8,
++	NES_NIC_SQ_WQE_FRAG1_HIGH_IDX = 9,
++	NES_NIC_SQ_WQE_FRAG2_LOW_IDX = 10,
++	NES_NIC_SQ_WQE_FRAG2_HIGH_IDX = 11,
++	NES_NIC_SQ_WQE_FRAG3_LOW_IDX = 12,
++	NES_NIC_SQ_WQE_FRAG3_HIGH_IDX = 13,
++	NES_NIC_SQ_WQE_FRAG4_LOW_IDX = 14,
++	NES_NIC_SQ_WQE_FRAG4_HIGH_IDX = 15,
++};
++
++enum nes_iwarp_sq_wqe_word_idx {
++	NES_IWARP_SQ_WQE_MISC_IDX = 0,
++	NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX = 1,
++	NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX = 2,
++	NES_IWARP_SQ_WQE_COMP_CTX_HIGH_IDX = 3,
++	NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX = 4,
++	NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX = 5,
++	NES_IWARP_SQ_WQE_INV_STAG_LOW_IDX = 7,
++	NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX = 8,
++	NES_IWARP_SQ_WQE_RDMA_TO_HIGH_IDX = 9,
++	NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX = 10,
++	NES_IWARP_SQ_WQE_RDMA_STAG_IDX = 11,
++	NES_IWARP_SQ_WQE_IMM_DATA_START_IDX = 12,
++	NES_IWARP_SQ_WQE_FRAG0_LOW_IDX = 16,
++	NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX = 17,
++	NES_IWARP_SQ_WQE_LENGTH0_IDX = 18,
++	NES_IWARP_SQ_WQE_STAG0_IDX = 19,
++	NES_IWARP_SQ_WQE_FRAG1_LOW_IDX = 20,
++	NES_IWARP_SQ_WQE_FRAG1_HIGH_IDX = 21,
++	NES_IWARP_SQ_WQE_LENGTH1_IDX = 22,
++	NES_IWARP_SQ_WQE_STAG1_IDX = 23,
++	NES_IWARP_SQ_WQE_FRAG2_LOW_IDX = 24,
++	NES_IWARP_SQ_WQE_FRAG2_HIGH_IDX = 25,
++	NES_IWARP_SQ_WQE_LENGTH2_IDX = 26,
++	NES_IWARP_SQ_WQE_STAG2_IDX = 27,
++	NES_IWARP_SQ_WQE_FRAG3_LOW_IDX = 28,
++	NES_IWARP_SQ_WQE_FRAG3_HIGH_IDX = 29,
++	NES_IWARP_SQ_WQE_LENGTH3_IDX = 30,
++	NES_IWARP_SQ_WQE_STAG3_IDX = 31,
++};
++
++enum nes_iwarp_sq_bind_wqe_word_idx {
++	NES_IWARP_SQ_BIND_WQE_MR_IDX = 6,
++	NES_IWARP_SQ_BIND_WQE_MW_IDX = 7,
++	NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX = 8,
++	NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX = 9,
++	NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX = 10,
++	NES_IWARP_SQ_BIND_WQE_VA_FBO_HIGH_IDX = 11,
++};
++
++enum nes_iwarp_sq_fmr_wqe_word_idx {
++	NES_IWARP_SQ_FMR_WQE_MR_STAG_IDX = 7,
++	NES_IWARP_SQ_FMR_WQE_LENGTH_LOW_IDX = 8,
++	NES_IWARP_SQ_FMR_WQE_LENGTH_HIGH_IDX = 9,
++	NES_IWARP_SQ_FMR_WQE_VA_FBO_LOW_IDX = 10,
++	NES_IWARP_SQ_FMR_WQE_VA_FBO_HIGH_IDX = 11,
++	NES_IWARP_SQ_FMR_WQE_PBL_ADDR_LOW_IDX = 12,
++	NES_IWARP_SQ_FMR_WQE_PBL_ADDR_HIGH_IDX = 13,
++	NES_IWARP_SQ_FMR_WQE_PBL_LENGTH_IDX = 14,
++};
++
++enum nes_iwarp_sq_locinv_wqe_word_idx {
++	NES_IWARP_SQ_LOCINV_WQE_INV_STAG_IDX = 6,
++};
++
++
++enum nes_iwarp_rq_wqe_word_idx {
++	NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX = 1,
++	NES_IWARP_RQ_WQE_COMP_CTX_LOW_IDX = 2,
++	NES_IWARP_RQ_WQE_COMP_CTX_HIGH_IDX = 3,
++	NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX = 4,
++	NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX = 5,
++	NES_IWARP_RQ_WQE_FRAG0_LOW_IDX = 8,
++	NES_IWARP_RQ_WQE_FRAG0_HIGH_IDX = 9,
++	NES_IWARP_RQ_WQE_LENGTH0_IDX = 10,
++	NES_IWARP_RQ_WQE_STAG0_IDX = 11,
++	NES_IWARP_RQ_WQE_FRAG1_LOW_IDX = 12,
++	NES_IWARP_RQ_WQE_FRAG1_HIGH_IDX = 13,
++	NES_IWARP_RQ_WQE_LENGTH1_IDX = 14,
++	NES_IWARP_RQ_WQE_STAG1_IDX = 15,
++	NES_IWARP_RQ_WQE_FRAG2_LOW_IDX = 16,
++	NES_IWARP_RQ_WQE_FRAG2_HIGH_IDX = 17,
++	NES_IWARP_RQ_WQE_LENGTH2_IDX = 18,
++	NES_IWARP_RQ_WQE_STAG2_IDX = 19,
++	NES_IWARP_RQ_WQE_FRAG3_LOW_IDX = 20,
++	NES_IWARP_RQ_WQE_FRAG3_HIGH_IDX = 21,
++	NES_IWARP_RQ_WQE_LENGTH3_IDX = 22,
++	NES_IWARP_RQ_WQE_STAG3_IDX = 23,
++};
++
++enum nes_nic_sq_wqe_bits {
++	NES_NIC_SQ_WQE_PHDR_CS_READY =  (1<<21),
++	NES_NIC_SQ_WQE_LSO_ENABLE = (1<<22),
++	NES_NIC_SQ_WQE_TAGVALUE_ENABLE = (1<<23),
++	NES_NIC_SQ_WQE_DISABLE_CHKSUM = (1<<30),
++	NES_NIC_SQ_WQE_COMPLETION = (1<<31),
++};
++
++enum nes_nic_cqe_word_idx {
++	NES_NIC_CQE_ACCQP_ID_IDX = 0,
++	NES_NIC_CQE_TAG_PKT_TYPE_IDX = 2,
++	NES_NIC_CQE_MISC_IDX = 3,
++};
++
++#define NES_PKT_TYPE_APBVT_BITS 0xC112
++#define NES_PKT_TYPE_APBVT_MASK 0xff3e
++
++#define NES_PKT_TYPE_PVALID_BITS 0x10000000
++#define NES_PKT_TYPE_PVALID_MASK 0x30000000
++
++#define NES_PKT_TYPE_TCPV4_BITS 0x0110
++#define NES_PKT_TYPE_TCPV4_MASK 0x3f30
++
++#define NES_PKT_TYPE_UDPV4_BITS 0x0210
++#define NES_PKT_TYPE_UDPV4_MASK 0x3f30
++
++#define NES_PKT_TYPE_IPV4_BITS  0x0010
++#define NES_PKT_TYPE_IPV4_MASK  0x3f30
++
++#define NES_PKT_TYPE_OTHER_BITS 0x0000
++#define NES_PKT_TYPE_OTHER_MASK 0x0030
++
++#define NES_NIC_CQE_ERRV_SHIFT 16
++enum nes_nic_ev_bits {
++	NES_NIC_ERRV_BITS_MODE = (1<<0),
++	NES_NIC_ERRV_BITS_IPV4_CSUM_ERR = (1<<1),
++	NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR = (1<<2),
++	NES_NIC_ERRV_BITS_WQE_OVERRUN = (1<<3),
++	NES_NIC_ERRV_BITS_IPH_ERR = (1<<4),
++};
++
++enum nes_nic_cqe_bits {
++	NES_NIC_CQE_ERRV_MASK = (0xff<<NES_NIC_CQE_ERRV_SHIFT),
++	NES_NIC_CQE_SQ = (1<<24),
++	NES_NIC_CQE_ACCQP_PORT = (1<<28),
++	NES_NIC_CQE_ACCQP_VALID = (1<<29),
++	NES_NIC_CQE_TAG_VALID = (1<<30),
++	NES_NIC_CQE_VALID = (1<<31),
++};
++
++enum nes_aeqe_word_idx {
++	NES_AEQE_COMP_CTXT_LOW_IDX = 0,
++	NES_AEQE_COMP_CTXT_HIGH_IDX = 1,
++	NES_AEQE_COMP_QP_CQ_ID_IDX = 2,
++	NES_AEQE_MISC_IDX = 3,
++};
++
++enum nes_aeqe_bits {
++	NES_AEQE_QP = (1<<16),
++	NES_AEQE_CQ = (1<<17),
++	NES_AEQE_SQ = (1<<18),
++	NES_AEQE_INBOUND_RDMA = (1<<19),
++	NES_AEQE_IWARP_STATE_MASK = (7<<20),
++	NES_AEQE_TCP_STATE_MASK = (0xf<<24),
++	NES_AEQE_VALID = (1<<31),
++};
++
++#define NES_AEQE_IWARP_STATE_SHIFT	20
++#define NES_AEQE_TCP_STATE_SHIFT	24
++
++enum nes_aeqe_iwarp_state {
++	NES_AEQE_IWARP_STATE_NON_EXISTANT = 0,
++	NES_AEQE_IWARP_STATE_IDLE = 1,
++	NES_AEQE_IWARP_STATE_RTS = 2,
++	NES_AEQE_IWARP_STATE_CLOSING = 3,
++	NES_AEQE_IWARP_STATE_TERMINATE = 5,
++	NES_AEQE_IWARP_STATE_ERROR = 6
++};
++
++enum nes_aeqe_tcp_state {
++	NES_AEQE_TCP_STATE_NON_EXISTANT = 0,
++	NES_AEQE_TCP_STATE_CLOSED = 1,
++	NES_AEQE_TCP_STATE_LISTEN = 2,
++	NES_AEQE_TCP_STATE_SYN_SENT = 3,
++	NES_AEQE_TCP_STATE_SYN_RCVD = 4,
++	NES_AEQE_TCP_STATE_ESTABLISHED = 5,
++	NES_AEQE_TCP_STATE_CLOSE_WAIT = 6,
++	NES_AEQE_TCP_STATE_FIN_WAIT_1 = 7,
++	NES_AEQE_TCP_STATE_CLOSING = 8,
++	NES_AEQE_TCP_STATE_LAST_ACK = 9,
++	NES_AEQE_TCP_STATE_FIN_WAIT_2 = 10,
++	NES_AEQE_TCP_STATE_TIME_WAIT = 11
++};
++
++enum nes_aeqe_aeid {
++	NES_AEQE_AEID_AMP_UNALLOCATED_STAG                            = 0x0102,
++	NES_AEQE_AEID_AMP_INVALID_STAG                                = 0x0103,
++	NES_AEQE_AEID_AMP_BAD_QP                                      = 0x0104,
++	NES_AEQE_AEID_AMP_BAD_PD                                      = 0x0105,
++	NES_AEQE_AEID_AMP_BAD_STAG_KEY                                = 0x0106,
++	NES_AEQE_AEID_AMP_BAD_STAG_INDEX                              = 0x0107,
++	NES_AEQE_AEID_AMP_BOUNDS_VIOLATION                            = 0x0108,
++	NES_AEQE_AEID_AMP_RIGHTS_VIOLATION                            = 0x0109,
++	NES_AEQE_AEID_AMP_TO_WRAP                                     = 0x010a,
++	NES_AEQE_AEID_AMP_FASTREG_SHARED                              = 0x010b,
++	NES_AEQE_AEID_AMP_FASTREG_VALID_STAG                          = 0x010c,
++	NES_AEQE_AEID_AMP_FASTREG_MW_STAG                             = 0x010d,
++	NES_AEQE_AEID_AMP_FASTREG_INVALID_RIGHTS                      = 0x010e,
++	NES_AEQE_AEID_AMP_FASTREG_PBL_TABLE_OVERFLOW                  = 0x010f,
++	NES_AEQE_AEID_AMP_FASTREG_INVALID_LENGTH                      = 0x0110,
++	NES_AEQE_AEID_AMP_INVALIDATE_SHARED                           = 0x0111,
++	NES_AEQE_AEID_AMP_INVALIDATE_NO_REMOTE_ACCESS_RIGHTS          = 0x0112,
++	NES_AEQE_AEID_AMP_INVALIDATE_MR_WITH_BOUND_WINDOWS            = 0x0113,
++	NES_AEQE_AEID_AMP_MWBIND_VALID_STAG                           = 0x0114,
++	NES_AEQE_AEID_AMP_MWBIND_OF_MR_STAG                           = 0x0115,
++	NES_AEQE_AEID_AMP_MWBIND_TO_ZERO_BASED_STAG                   = 0x0116,
++	NES_AEQE_AEID_AMP_MWBIND_TO_MW_STAG                           = 0x0117,
++	NES_AEQE_AEID_AMP_MWBIND_INVALID_RIGHTS                       = 0x0118,
++	NES_AEQE_AEID_AMP_MWBIND_INVALID_BOUNDS                       = 0x0119,
++	NES_AEQE_AEID_AMP_MWBIND_TO_INVALID_PARENT                    = 0x011a,
++	NES_AEQE_AEID_AMP_MWBIND_BIND_DISABLED                        = 0x011b,
++	NES_AEQE_AEID_BAD_CLOSE                                       = 0x0201,
++	NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE                         = 0x0202,
++	NES_AEQE_AEID_CQ_OPERATION_ERROR                              = 0x0203,
++	NES_AEQE_AEID_PRIV_OPERATION_DENIED                           = 0x0204,
++	NES_AEQE_AEID_RDMA_READ_WHILE_ORD_ZERO                        = 0x0205,
++	NES_AEQE_AEID_STAG_ZERO_INVALID                               = 0x0206,
++	NES_AEQE_AEID_DDP_INVALID_MSN_GAP_IN_MSN                      = 0x0301,
++	NES_AEQE_AEID_DDP_INVALID_MSN_RANGE_IS_NOT_VALID              = 0x0302,
++	NES_AEQE_AEID_DDP_UBE_DDP_MESSAGE_TOO_LONG_FOR_AVAILABLE_BUFFER = 0x0303,
++	NES_AEQE_AEID_DDP_UBE_INVALID_DDP_VERSION                     = 0x0304,
++	NES_AEQE_AEID_DDP_UBE_INVALID_MO                              = 0x0305,
++	NES_AEQE_AEID_DDP_UBE_INVALID_MSN_NO_BUFFER_AVAILABLE         = 0x0306,
++	NES_AEQE_AEID_DDP_UBE_INVALID_QN                              = 0x0307,
++	NES_AEQE_AEID_DDP_NO_L_BIT                                    = 0x0308,
++	NES_AEQE_AEID_RDMAP_ROE_INVALID_RDMAP_VERSION                 = 0x0311,
++	NES_AEQE_AEID_RDMAP_ROE_UNEXPECTED_OPCODE                     = 0x0312,
++	NES_AEQE_AEID_ROE_INVALID_RDMA_READ_REQUEST                   = 0x0313,
++	NES_AEQE_AEID_ROE_INVALID_RDMA_WRITE_OR_READ_RESP             = 0x0314,
++	NES_AEQE_AEID_INVALID_ARP_ENTRY                               = 0x0401,
++	NES_AEQE_AEID_INVALID_TCP_OPTION_RCVD                         = 0x0402,
++	NES_AEQE_AEID_STALE_ARP_ENTRY                                 = 0x0403,
++	NES_AEQE_AEID_LLP_CLOSE_COMPLETE                              = 0x0501,
++	NES_AEQE_AEID_LLP_CONNECTION_RESET                            = 0x0502,
++	NES_AEQE_AEID_LLP_FIN_RECEIVED                                = 0x0503,
++	NES_AEQE_AEID_LLP_RECEIVED_MARKER_AND_LENGTH_FIELDS_DONT_MATCH =  0x0504,
++	NES_AEQE_AEID_LLP_RECEIVED_MPA_CRC_ERROR                      = 0x0505,
++	NES_AEQE_AEID_LLP_SEGMENT_TOO_LARGE                           = 0x0506,
++	NES_AEQE_AEID_LLP_SEGMENT_TOO_SMALL                           = 0x0507,
++	NES_AEQE_AEID_LLP_SYN_RECEIVED                                = 0x0508,
++	NES_AEQE_AEID_LLP_TERMINATE_RECEIVED                          = 0x0509,
++	NES_AEQE_AEID_LLP_TOO_MANY_RETRIES                            = 0x050a,
++	NES_AEQE_AEID_LLP_TOO_MANY_KEEPALIVE_RETRIES                  = 0x050b,
++	NES_AEQE_AEID_RESET_SENT                                      = 0x0601,
++	NES_AEQE_AEID_TERMINATE_SENT                                  = 0x0602,
++	NES_AEQE_AEID_DDP_LCE_LOCAL_CATASTROPHIC                      = 0x0700
++};
++
++enum nes_iwarp_sq_opcodes {
++	NES_IWARP_SQ_WQE_WRPDU = (1<<15),
++	NES_IWARP_SQ_WQE_PSH = (1<<21),
++	NES_IWARP_SQ_WQE_STREAMING = (1<<23),
++	NES_IWARP_SQ_WQE_IMM_DATA = (1<<28),
++	NES_IWARP_SQ_WQE_READ_FENCE = (1<<29),
++	NES_IWARP_SQ_WQE_LOCAL_FENCE = (1<<30),
++	NES_IWARP_SQ_WQE_SIGNALED_COMPL = (1<<31),
++};
++
++enum nes_iwarp_sq_wqe_bits {
++	NES_IWARP_SQ_OP_RDMAW = 0,
++	NES_IWARP_SQ_OP_RDMAR = 1,
++	NES_IWARP_SQ_OP_SEND = 3,
++	NES_IWARP_SQ_OP_SENDINV = 4,
++	NES_IWARP_SQ_OP_SENDSE = 5,
++	NES_IWARP_SQ_OP_SENDSEINV = 6,
++	NES_IWARP_SQ_OP_BIND = 8,
++	NES_IWARP_SQ_OP_FAST_REG = 9,
++	NES_IWARP_SQ_OP_LOCINV = 10,
++	NES_IWARP_SQ_OP_RDMAR_LOCINV = 11,
++	NES_IWARP_SQ_OP_NOP = 12,
++};
 +
- 	return ret;
- }
- 
-@@ -703,7 +709,8 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
- 	if (get_user(id, arg))
- 		return -EFAULT;
- 
--	down_write(&file->port->mutex);
-+	mutex_lock(&file->port->file_mutex);
-+	mutex_lock(&file->mutex);
- 
- 	if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
- 		ret = -EINVAL;
-@@ -714,11 +721,13 @@ static int ib_umad_unreg_agent(struct ib_umad_file *file, u32 __user *arg)
- 	file->agent[id] = NULL;
- 
- out:
--	up_write(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
- 
- 	if (agent)
- 		ib_unregister_mad_agent(agent);
- 
-+	mutex_unlock(&file->port->file_mutex);
++#define NES_EEPROM_READ_REQUEST (1<<16)
++#define NES_MAC_ADDR_VALID      (1<<20)
 +
- 	return ret;
- }
- 
-@@ -726,12 +735,12 @@ static long ib_umad_enable_pkey(struct ib_umad_file *file)
- {
- 	int ret = 0;
- 
--	down_write(&file->port->mutex);
-+	mutex_lock(&file->mutex);
- 	if (file->already_used)
- 		ret = -EINVAL;
- 	else
- 		file->use_pkey_index = 1;
--	up_write(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
- 
- 	return ret;
- }
-@@ -783,7 +792,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
- 	if (!port)
- 		return -ENXIO;
- 
--	down_write(&port->mutex);
-+	mutex_lock(&port->file_mutex);
- 
- 	if (!port->ib_dev) {
- 		ret = -ENXIO;
-@@ -797,7 +806,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
- 		goto out;
- 	}
- 
--	spin_lock_init(&file->recv_lock);
-+	mutex_init(&file->mutex);
- 	spin_lock_init(&file->send_lock);
- 	INIT_LIST_HEAD(&file->recv_list);
- 	INIT_LIST_HEAD(&file->send_list);
-@@ -809,7 +818,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
- 	list_add_tail(&file->port_list, &port->file_list);
- 
- out:
--	up_write(&port->mutex);
-+	mutex_unlock(&port->file_mutex);
- 	return ret;
- }
- 
-@@ -821,7 +830,8 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
- 	int already_dead;
- 	int i;
- 
--	down_write(&file->port->mutex);
-+	mutex_lock(&file->port->file_mutex);
-+	mutex_lock(&file->mutex);
- 
- 	already_dead = file->agents_dead;
- 	file->agents_dead = 1;
-@@ -834,14 +844,14 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
- 
- 	list_del(&file->port_list);
- 
--	downgrade_write(&file->port->mutex);
-+	mutex_unlock(&file->mutex);
- 
- 	if (!already_dead)
- 		for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
- 			if (file->agent[i])
- 				ib_unregister_mad_agent(file->agent[i]);
- 
--	up_read(&file->port->mutex);
-+	mutex_unlock(&file->port->file_mutex);
- 
- 	kfree(file);
- 	kref_put(&dev->ref, ib_umad_release_dev);
-@@ -914,10 +924,10 @@ static int ib_umad_sm_close(struct inode *inode, struct file *filp)
- 	};
- 	int ret = 0;
- 
--	down_write(&port->mutex);
-+	mutex_lock(&port->file_mutex);
- 	if (port->ib_dev)
- 		ret = ib_modify_port(port->ib_dev, port->port_num, 0, &props);
--	up_write(&port->mutex);
-+	mutex_unlock(&port->file_mutex);
- 
- 	up(&port->sm_sem);
- 
-@@ -981,7 +991,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
- 	port->ib_dev   = device;
- 	port->port_num = port_num;
- 	init_MUTEX(&port->sm_sem);
--	init_rwsem(&port->mutex);
-+	mutex_init(&port->file_mutex);
- 	INIT_LIST_HEAD(&port->file_list);
- 
- 	port->dev = cdev_alloc();
-@@ -1052,6 +1062,7 @@ err_cdev:
- static void ib_umad_kill_port(struct ib_umad_port *port)
- {
- 	struct ib_umad_file *file;
-+	int already_dead;
- 	int id;
- 
- 	class_set_devdata(port->class_dev,    NULL);
-@@ -1067,42 +1078,22 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
- 	umad_port[port->dev_num] = NULL;
- 	spin_unlock(&port_lock);
- 
--	down_write(&port->mutex);
-+	mutex_lock(&port->file_mutex);
- 
- 	port->ib_dev = NULL;
- 
--	/*
--	 * Now go through the list of files attached to this port and
--	 * unregister all of their MAD agents.  We need to hold
--	 * port->mutex while doing this to avoid racing with
--	 * ib_umad_close(), but we can't hold the mutex for writing
--	 * while calling ib_unregister_mad_agent(), since that might
--	 * deadlock by calling back into queue_packet().  So we
--	 * downgrade our lock to a read lock, and then drop and
--	 * reacquire the write lock for the next iteration.
--	 *
--	 * We do list_del_init() on the file's list_head so that the
--	 * list_del in ib_umad_close() is still OK, even after the
--	 * file is removed from the list.
--	 */
--	while (!list_empty(&port->file_list)) {
--		file = list_entry(port->file_list.next, struct ib_umad_file,
--				  port_list);
--
-+	list_for_each_entry(file, &port->file_list, port_list) {
-+		mutex_lock(&file->mutex);
-+		already_dead = file->agents_dead;
- 		file->agents_dead = 1;
--		list_del_init(&file->port_list);
--
--		downgrade_write(&port->mutex);
-+		mutex_unlock(&file->mutex);
- 
- 		for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)
- 			if (file->agent[id])
- 				ib_unregister_mad_agent(file->agent[id]);
--
--		up_read(&port->mutex);
--		down_write(&port->mutex);
- 	}
- 
--	up_write(&port->mutex);
-+	mutex_unlock(&port->file_mutex);
- 
- 	clear_bit(port->dev_num, dev_map);
- }
-diff --git a/drivers/infiniband/hw/cxgb3/Makefile b/drivers/infiniband/hw/cxgb3/Makefile
-index 36b9898..7e7b5a6 100644
---- a/drivers/infiniband/hw/cxgb3/Makefile
-+++ b/drivers/infiniband/hw/cxgb3/Makefile
-@@ -1,5 +1,4 @@
--EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3 \
--		-I$(TOPDIR)/drivers/infiniband/hw/cxgb3/core
-+EXTRA_CFLAGS += -Idrivers/net/cxgb3
- 
- obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
- 
-diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
-index eec6a30..03c5ff6 100644
---- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
-+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
-@@ -179,7 +179,7 @@ int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq)
- 	setup.size = 1UL << cq->size_log2;
- 	setup.credits = 65535;
- 	setup.credit_thres = 1;
--	if (rdev_p->t3cdev_p->type == T3B)
-+	if (rdev_p->t3cdev_p->type != T3A)
- 		setup.ovfl_mode = 0;
- 	else
- 		setup.ovfl_mode = 1;
-@@ -584,7 +584,7 @@ static int cxio_hal_ctrl_qp_write_mem(struct cxio_rdev *rdev_p, u32 addr,
- {
- 	u32 i, nr_wqe, copy_len;
- 	u8 *copy_data;
--	u8 wr_len, utx_len;	/* lenght in 8 byte flit */
-+	u8 wr_len, utx_len;	/* length in 8 byte flit */
- 	enum t3_wr_flags flag;
- 	__be64 *wqe;
- 	u64 utx_cmd;
-diff --git a/drivers/infiniband/hw/cxgb3/cxio_wr.h b/drivers/infiniband/hw/cxgb3/cxio_wr.h
-index c84d4ac..969d4d9 100644
---- a/drivers/infiniband/hw/cxgb3/cxio_wr.h
-+++ b/drivers/infiniband/hw/cxgb3/cxio_wr.h
-@@ -315,7 +315,7 @@ struct t3_rdma_init_wr {
- 	__be32 ird;
- 	__be64 qp_dma_addr;	/* 7 */
- 	__be32 qp_dma_size;	/* 8 */
--	u32 irs;
-+	__be32 irs;
- };
- 
- struct t3_genbit {
-@@ -324,7 +324,8 @@ struct t3_genbit {
- };
- 
- enum rdma_init_wr_flags {
--	RECVS_POSTED = 1,
-+	RECVS_POSTED = (1<<0),
-+	PRIV_QP = (1<<1),
- };
- 
- union t3_wr {
-diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
-index 20ba372..e9a08fa 100644
---- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
-+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
-@@ -332,7 +332,7 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
- 			  }
- 	};
- 
--	if (ip_route_output_flow(&rt, &fl, NULL, 0))
-+	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
- 		return NULL;
- 	return rt;
- }
-@@ -1118,7 +1118,7 @@ static int act_open_rpl(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
- 	     status2errno(rpl->status));
- 	connect_reply_upcall(ep, status2errno(rpl->status));
- 	state_set(&ep->com, DEAD);
--	if (ep->com.tdev->type == T3B && act_open_has_tid(rpl->status))
-+	if (ep->com.tdev->type != T3A && act_open_has_tid(rpl->status))
- 		release_tid(ep->com.tdev, GET_TID(rpl), NULL);
- 	cxgb3_free_atid(ep->com.tdev, ep->atid);
- 	dst_release(ep->dst);
-@@ -1249,7 +1249,7 @@ static void reject_cr(struct t3cdev *tdev, u32 hwtid, __be32 peer_ip,
- 	skb_trim(skb, sizeof(struct cpl_tid_release));
- 	skb_get(skb);
- 
--	if (tdev->type == T3B)
-+	if (tdev->type != T3A)
- 		release_tid(tdev, hwtid, skb);
- 	else {
- 		struct cpl_pass_accept_rpl *rpl;
-diff --git a/drivers/infiniband/hw/cxgb3/iwch_mem.c b/drivers/infiniband/hw/cxgb3/iwch_mem.c
-index a6c2c4b..73bfd16 100644
---- a/drivers/infiniband/hw/cxgb3/iwch_mem.c
-+++ b/drivers/infiniband/hw/cxgb3/iwch_mem.c
-@@ -122,6 +122,13 @@ int build_phys_page_list(struct ib_phys_buf *buffer_list,
- 		*total_size += buffer_list[i].size;
- 		if (i > 0)
- 			mask |= buffer_list[i].addr;
-+		else
-+			mask |= buffer_list[i].addr & PAGE_MASK;
-+		if (i != num_phys_buf - 1)
-+			mask |= buffer_list[i].addr + buffer_list[i].size;
-+		else
-+			mask |= (buffer_list[i].addr + buffer_list[i].size +
-+				PAGE_SIZE - 1) & PAGE_MASK;
- 	}
- 
- 	if (*total_size > 0xFFFFFFFFULL)
-diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
-index b5436ca..df1838f 100644
---- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
-+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
-@@ -39,6 +39,7 @@
- #include <linux/list.h>
- #include <linux/spinlock.h>
- #include <linux/ethtool.h>
-+#include <linux/rtnetlink.h>
- 
- #include <asm/io.h>
- #include <asm/irq.h>
-@@ -645,7 +646,7 @@ static struct ib_mr *iwch_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
- 	if (err)
- 		goto err;
- 
--	if (udata && t3b_device(rhp)) {
-+	if (udata && !t3a_device(rhp)) {
- 		uresp.pbl_addr = (mhp->attr.pbl_addr -
- 	                         rhp->rdev.rnic_info.pbl_base) >> 3;
- 		PDBG("%s user resp pbl_addr 0x%x\n", __FUNCTION__,
-@@ -1053,7 +1054,9 @@ static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
- 	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
- 
- 	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
-+	rtnl_lock();
- 	lldev->ethtool_ops->get_drvinfo(lldev, &info);
-+	rtnl_unlock();
- 	return sprintf(buf, "%s\n", info.fw_version);
- }
- 
-@@ -1065,7 +1068,9 @@ static ssize_t show_hca(struct class_device *cdev, char *buf)
- 	struct net_device *lldev = dev->rdev.t3cdev_p->lldev;
- 
- 	PDBG("%s class dev 0x%p\n", __FUNCTION__, cdev);
-+	rtnl_lock();
- 	lldev->ethtool_ops->get_drvinfo(lldev, &info);
-+	rtnl_unlock();
- 	return sprintf(buf, "%s\n", info.driver);
- }
- 
-diff --git a/drivers/infiniband/hw/cxgb3/iwch_qp.c b/drivers/infiniband/hw/cxgb3/iwch_qp.c
-index dd89b6b..ea2cdd7 100644
---- a/drivers/infiniband/hw/cxgb3/iwch_qp.c
-+++ b/drivers/infiniband/hw/cxgb3/iwch_qp.c
-@@ -208,36 +208,19 @@ static int iwch_sgl2pbl_map(struct iwch_dev *rhp, struct ib_sge *sg_list,
- static int iwch_build_rdma_recv(struct iwch_dev *rhp, union t3_wr *wqe,
- 				struct ib_recv_wr *wr)
- {
--	int i, err = 0;
--	u32 pbl_addr[4];
--	u8 page_size[4];
-+	int i;
- 	if (wr->num_sge > T3_MAX_SGE)
- 		return -EINVAL;
--	err = iwch_sgl2pbl_map(rhp, wr->sg_list, wr->num_sge, pbl_addr,
--			       page_size);
--	if (err)
--		return err;
--	wqe->recv.pagesz[0] = page_size[0];
--	wqe->recv.pagesz[1] = page_size[1];
--	wqe->recv.pagesz[2] = page_size[2];
--	wqe->recv.pagesz[3] = page_size[3];
- 	wqe->recv.num_sgle = cpu_to_be32(wr->num_sge);
- 	for (i = 0; i < wr->num_sge; i++) {
- 		wqe->recv.sgl[i].stag = cpu_to_be32(wr->sg_list[i].lkey);
- 		wqe->recv.sgl[i].len = cpu_to_be32(wr->sg_list[i].length);
--
--		/* to in the WQE == the offset into the page */
--		wqe->recv.sgl[i].to = cpu_to_be64(((u32) wr->sg_list[i].addr) %
--				(1UL << (12 + page_size[i])));
--
--		/* pbl_addr is the adapters address in the PBL */
--		wqe->recv.pbl_addr[i] = cpu_to_be32(pbl_addr[i]);
-+		wqe->recv.sgl[i].to = cpu_to_be64(wr->sg_list[i].addr);
- 	}
- 	for (; i < T3_MAX_SGE; i++) {
- 		wqe->recv.sgl[i].stag = 0;
- 		wqe->recv.sgl[i].len = 0;
- 		wqe->recv.sgl[i].to = 0;
--		wqe->recv.pbl_addr[i] = 0;
- 	}
- 	return 0;
- }
-@@ -659,6 +642,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
- 	cxio_flush_rq(&qhp->wq, &rchp->cq, count);
- 	spin_unlock(&qhp->lock);
- 	spin_unlock_irqrestore(&rchp->lock, *flag);
-+	(*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
- 
- 	/* locking heirarchy: cq lock first, then qp lock. */
- 	spin_lock_irqsave(&schp->lock, *flag);
-@@ -668,6 +652,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
- 	cxio_flush_sq(&qhp->wq, &schp->cq, count);
- 	spin_unlock(&qhp->lock);
- 	spin_unlock_irqrestore(&schp->lock, *flag);
-+	(*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
- 
- 	/* deref */
- 	if (atomic_dec_and_test(&qhp->refcnt))
-@@ -678,7 +663,7 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
- 
- static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
- {
--	if (t3b_device(qhp->rhp))
-+	if (qhp->ibqp.uobject)
- 		cxio_set_wq_in_error(&qhp->wq);
- 	else
- 		__flush_qp(qhp, flag);
-@@ -732,6 +717,7 @@ static int rdma_init(struct iwch_dev *rhp, struct iwch_qp *qhp,
- 	init_attr.qp_dma_addr = qhp->wq.dma_addr;
- 	init_attr.qp_dma_size = (1UL << qhp->wq.size_log2);
- 	init_attr.flags = rqes_posted(qhp) ? RECVS_POSTED : 0;
-+	init_attr.flags |= capable(CAP_NET_BIND_SERVICE) ? PRIV_QP : 0;
- 	init_attr.irs = qhp->ep->rcv_seq;
- 	PDBG("%s init_attr.rq_addr 0x%x init_attr.rq_size = %d "
- 	     "flags 0x%x qpcaps 0x%x\n", __FUNCTION__,
-@@ -847,10 +833,11 @@ int iwch_modify_qp(struct iwch_dev *rhp, struct iwch_qp *qhp,
- 				disconnect = 1;
- 				ep = qhp->ep;
- 			}
-+			flush_qp(qhp, &flag);
- 			break;
- 		case IWCH_QP_STATE_TERMINATE:
- 			qhp->attr.state = IWCH_QP_STATE_TERMINATE;
--			if (t3b_device(qhp->rhp))
-+			if (qhp->ibqp.uobject)
- 				cxio_set_wq_in_error(&qhp->wq);
- 			if (!internal)
- 				terminate = 1;
-diff --git a/drivers/infiniband/hw/ehca/ehca_av.c b/drivers/infiniband/hw/ehca/ehca_av.c
-index f7782c8..194c1c3 100644
---- a/drivers/infiniband/hw/ehca/ehca_av.c
-+++ b/drivers/infiniband/hw/ehca/ehca_av.c
-@@ -1,7 +1,7 @@
- /*
-  *  IBM eServer eHCA Infiniband device driver for Linux on POWER
-  *
-- *  adress vector functions
-+ *  address vector functions
-  *
-  *  Authors: Hoang-Nam Nguyen <hnguyen at de.ibm.com>
-  *           Khadija Souissi <souissik at de.ibm.com>
-diff --git a/drivers/infiniband/hw/ehca/ehca_classes.h b/drivers/infiniband/hw/ehca/ehca_classes.h
-index 74d2b72..f281d16 100644
---- a/drivers/infiniband/hw/ehca/ehca_classes.h
-+++ b/drivers/infiniband/hw/ehca/ehca_classes.h
-@@ -94,7 +94,11 @@ struct ehca_sma_attr {
- 
- struct ehca_sport {
- 	struct ib_cq *ibcq_aqp1;
--	struct ib_qp *ibqp_aqp1;
-+	struct ib_qp *ibqp_sqp[2];
-+	/* lock to serialze modify_qp() calls for sqp in normal
-+	 * and irq path (when event PORT_ACTIVE is received first time)
-+	 */
-+	spinlock_t mod_sqp_lock;
- 	enum ib_port_state port_state;
- 	struct ehca_sma_attr saved_attr;
- };
-@@ -141,6 +145,14 @@ enum ehca_ext_qp_type {
- 	EQPT_SRQ       = 3,
- };
- 
-+/* struct to cache modify_qp()'s parms for GSI/SMI qp */
-+struct ehca_mod_qp_parm {
-+	int mask;
-+	struct ib_qp_attr attr;
++/*
++ * NES index registers init values.
++ */
++struct nes_init_values {
++	u32 index;
++	u32 data;
++	u8  wrt;
++};
++
++/*
++ * NES registers in BAR0.
++ */
++struct nes_pci_regs {
++	u32 int_status;
++	u32 int_mask;
++	u32 int_pending;
++	u32 intf_int_status;
++	u32 intf_int_mask;
++	u32 other_regs[59];	 /* pad out to 256 bytes for now */
++};
++
++#define NES_CQP_SQ_SIZE    128
++#define NES_CCQ_SIZE       128
++#define NES_NIC_WQ_SIZE    512
++#define NES_NIC_CTX_SIZE   ((NES_NIC_CTX_RQ_SIZE_512) | (NES_NIC_CTX_SQ_SIZE_512))
++#define NES_NIC_BACK_STORE 0x00038000
++
++struct nes_device;
++
++struct nes_hw_nic_qp_context {
++	__le32 context_words[6];
++};
++
++struct nes_hw_nic_sq_wqe {
++	__le32 wqe_words[16];
++};
++
++struct nes_hw_nic_rq_wqe {
++	__le32 wqe_words[16];
++};
++
++struct nes_hw_nic_cqe {
++	__le32 cqe_words[4];
++};
++
++struct nes_hw_cqp_qp_context {
++	__le32 context_words[4];
++};
++
++struct nes_hw_cqp_wqe {
++	__le32 wqe_words[16];
++};
++
++struct nes_hw_qp_wqe {
++	__le32 wqe_words[32];
++};
++
++struct nes_hw_cqe {
++	__le32 cqe_words[8];
++};
++
++struct nes_hw_ceqe {
++	__le32 ceqe_words[2];
++};
++
++struct nes_hw_aeqe {
++	__le32 aeqe_words[4];
++};
++
++struct nes_cqp_request {
++	union {
++		u64 cqp_callback_context;
++		void *cqp_callback_pointer;
++	};
++	wait_queue_head_t     waitq;
++	struct nes_hw_cqp_wqe cqp_wqe;
++	struct list_head      list;
++	atomic_t              refcount;
++	void (*cqp_callback)(struct nes_device *nesdev, struct nes_cqp_request *cqp_request);
++	u16                   major_code;
++	u16                   minor_code;
++	u8                    waiting;
++	u8                    request_done;
++	u8                    dynamic;
++	u8                    callback;
++};
++
++struct nes_hw_cqp {
++	struct nes_hw_cqp_wqe *sq_vbase;
++	dma_addr_t            sq_pbase;
++	spinlock_t            lock;
++	wait_queue_head_t     waitq;
++	u16                   qp_id;
++	u16                   sq_head;
++	u16                   sq_tail;
++	u16                   sq_size;
++};
++
++#define NES_FIRST_FRAG_SIZE 128
++struct nes_first_frag {
++	u8 buffer[NES_FIRST_FRAG_SIZE];
++};
++
++struct nes_hw_nic {
++	struct nes_first_frag    *first_frag_vbase;	/* virtual address of first frags */
++	struct nes_hw_nic_sq_wqe *sq_vbase;			/* virtual address of sq */
++	struct nes_hw_nic_rq_wqe *rq_vbase;			/* virtual address of rq */
++	struct sk_buff           *tx_skb[NES_NIC_WQ_SIZE];
++	struct sk_buff           *rx_skb[NES_NIC_WQ_SIZE];
++	dma_addr_t frag_paddr[NES_NIC_WQ_SIZE];
++	unsigned long first_frag_overflow[BITS_TO_LONGS(NES_NIC_WQ_SIZE)];
++	dma_addr_t sq_pbase;			/* PCI memory for host rings */
++	dma_addr_t rq_pbase;			/* PCI memory for host rings */
++
++	u16 qp_id;
++	u16 sq_head;
++	u16 sq_tail;
++	u16 sq_size;
++	u16 rq_head;
++	u16 rq_tail;
++	u16 rq_size;
++	u8 replenishing_rq;
++	u8 reserved;
++
++	spinlock_t sq_lock;
++	spinlock_t rq_lock;
 +};
 +
-+#define EHCA_MOD_QP_PARM_MAX 4
++struct nes_hw_nic_cq {
++	struct nes_hw_nic_cqe volatile *cq_vbase;	/* PCI memory for host rings */
++	void (*ce_handler)(struct nes_device *nesdev, struct nes_hw_nic_cq *cq);
++	dma_addr_t cq_pbase;	/* PCI memory for host rings */
++	int rx_cqes_completed;
++	int cqe_allocs_pending;
++	int rx_pkts_indicated;
++	u16 cq_head;
++	u16 cq_size;
++	u16 cq_number;
++	u8  cqes_pending;
++};
++
++struct nes_hw_qp {
++	struct nes_hw_qp_wqe *sq_vbase;		/* PCI memory for host rings */
++	struct nes_hw_qp_wqe *rq_vbase;		/* PCI memory for host rings */
++	void                 *q2_vbase;			/* PCI memory for host rings */
++	dma_addr_t sq_pbase;	/* PCI memory for host rings */
++	dma_addr_t rq_pbase;	/* PCI memory for host rings */
++	dma_addr_t q2_pbase;	/* PCI memory for host rings */
++	u32 qp_id;
++	u16 sq_head;
++	u16 sq_tail;
++	u16 sq_size;
++	u16 rq_head;
++	u16 rq_tail;
++	u16 rq_size;
++	u8  rq_encoded_size;
++	u8  sq_encoded_size;
++};
++
++struct nes_hw_cq {
++	struct nes_hw_cqe volatile *cq_vbase;	/* PCI memory for host rings */
++	void (*ce_handler)(struct nes_device *nesdev, struct nes_hw_cq *cq);
++	dma_addr_t cq_pbase;	/* PCI memory for host rings */
++	u16 cq_head;
++	u16 cq_size;
++	u16 cq_number;
++};
++
++struct nes_hw_ceq {
++	struct nes_hw_ceqe volatile *ceq_vbase;	/* PCI memory for host rings */
++	dma_addr_t ceq_pbase;	/* PCI memory for host rings */
++	u16 ceq_head;
++	u16 ceq_size;
++};
++
++struct nes_hw_aeq {
++	struct nes_hw_aeqe volatile *aeq_vbase;	/* PCI memory for host rings */
++	dma_addr_t aeq_pbase;	/* PCI memory for host rings */
++	u16 aeq_head;
++	u16 aeq_size;
++};
++
++struct nic_qp_map {
++	u8 qpid;
++	u8 nic_index;
++	u8 logical_port;
++	u8 is_hnic;
++};
++
++#define	NES_CQP_ARP_AEQ_INDEX_MASK  0x000f0000
++#define	NES_CQP_ARP_AEQ_INDEX_SHIFT 16
++
++#define NES_CQP_APBVT_ADD			0x00008000
++#define NES_CQP_APBVT_NIC_SHIFT		16
++
++#define NES_ARP_ADD     1
++#define NES_ARP_DELETE  2
++#define NES_ARP_RESOLVE 3
++
++#define NES_MAC_SW_IDLE      0
++#define NES_MAC_SW_INTERRUPT 1
++#define NES_MAC_SW_MH        2
++
++struct nes_arp_entry {
++	u32 ip_addr;
++	u8  mac_addr[ETH_ALEN];
++};
++
++#define NES_NIC_FAST_TIMER          96
++#define NES_NIC_FAST_TIMER_LOW      40
++#define NES_NIC_FAST_TIMER_HIGH     1000
++#define DEFAULT_NES_QL_HIGH         256
++#define DEFAULT_NES_QL_LOW          16
++#define DEFAULT_NES_QL_TARGET       64
++#define DEFAULT_JUMBO_NES_QL_LOW    12
++#define DEFAULT_JUMBO_NES_QL_TARGET 40
++#define DEFAULT_JUMBO_NES_QL_HIGH   128
++#define NES_NIC_CQ_DOWNWARD_TREND   8
++
++struct nes_hw_tune_timer {
++    //u16 cq_count;
++    u16 threshold_low;
++    u16 threshold_target;
++    u16 threshold_high;
++    u16 timer_in_use;
++    u16 timer_in_use_old;
++    u16 timer_in_use_min;
++    u16 timer_in_use_max;
++    u8  timer_direction_upward;
++    u8  timer_direction_downward;
++    u16 cq_count_old;
++    u8  cq_direction_downward;
++};
++
++#define NES_TIMER_INT_LIMIT         2
++#define NES_TIMER_INT_LIMIT_DYNAMIC 10
++#define NES_TIMER_ENABLE_LIMIT      4
++#define NES_MAX_LINK_INTERRUPTS		128
++#define NES_MAX_LINK_CHECK		200
++
++struct nes_adapter {
++	u64              fw_ver;
++	unsigned long    *allocated_qps;
++	unsigned long    *allocated_cqs;
++	unsigned long    *allocated_mrs;
++	unsigned long    *allocated_pds;
++	unsigned long    *allocated_arps;
++	struct nes_qp    **qp_table;
++	struct workqueue_struct *work_q;
 +
- struct ehca_qp {
- 	union {
- 		struct ib_qp ib_qp;
-@@ -164,10 +176,18 @@ struct ehca_qp {
- 	struct ehca_cq *recv_cq;
- 	unsigned int sqerr_purgeflag;
- 	struct hlist_node list_entries;
-+	/* array to cache modify_qp()'s parms for GSI/SMI qp */
-+	struct ehca_mod_qp_parm *mod_qp_parm;
-+	int mod_qp_parm_idx;
- 	/* mmap counter for resources mapped into user space */
- 	u32 mm_count_squeue;
- 	u32 mm_count_rqueue;
- 	u32 mm_count_galpa;
-+	/* unsolicited ack circumvention */
-+	int unsol_ack_circ;
-+	int mtu_shift;
-+	u32 message_count;
-+	u32 packet_count;
- };
- 
- #define IS_SRQ(qp) (qp->ext_type == EQPT_SRQ)
-@@ -323,6 +343,7 @@ extern int ehca_port_act_time;
- extern int ehca_use_hp_mr;
- extern int ehca_scaling_code;
- extern int ehca_lock_hcalls;
-+extern int ehca_nr_ports;
- 
- struct ipzu_queue_resp {
- 	u32 qe_size;      /* queue entry size */
-diff --git a/drivers/infiniband/hw/ehca/ehca_cq.c b/drivers/infiniband/hw/ehca/ehca_cq.c
-index 79c25f5..0467c15 100644
---- a/drivers/infiniband/hw/ehca/ehca_cq.c
-+++ b/drivers/infiniband/hw/ehca/ehca_cq.c
-@@ -246,7 +246,7 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
- 		} else {
- 			if (h_ret != H_PAGE_REGISTERED) {
- 				ehca_err(device, "Registration of page failed "
--					 "ehca_cq=%p cq_num=%x h_ret=%li"
-+					 "ehca_cq=%p cq_num=%x h_ret=%li "
- 					 "counter=%i act_pages=%i",
- 					 my_cq, my_cq->cq_number,
- 					 h_ret, counter, param.act_pages);
-diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c
-index 3f617b2..863b34f 100644
---- a/drivers/infiniband/hw/ehca/ehca_irq.c
-+++ b/drivers/infiniband/hw/ehca/ehca_irq.c
-@@ -62,6 +62,7 @@
- #define NEQE_PORT_NUMBER       EHCA_BMASK_IBM( 8, 15)
- #define NEQE_PORT_AVAILABILITY EHCA_BMASK_IBM(16, 16)
- #define NEQE_DISRUPTIVE        EHCA_BMASK_IBM(16, 16)
-+#define NEQE_SPECIFIC_EVENT    EHCA_BMASK_IBM(16, 23)
- 
- #define ERROR_DATA_LENGTH      EHCA_BMASK_IBM(52, 63)
- #define ERROR_DATA_TYPE        EHCA_BMASK_IBM( 0,  7)
-@@ -354,17 +355,34 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
- {
- 	u8 ec   = EHCA_BMASK_GET(NEQE_EVENT_CODE, eqe);
- 	u8 port = EHCA_BMASK_GET(NEQE_PORT_NUMBER, eqe);
-+	u8 spec_event;
-+	struct ehca_sport *sport = &shca->sport[port - 1];
-+	unsigned long flags;
- 
- 	switch (ec) {
- 	case 0x30: /* port availability change */
- 		if (EHCA_BMASK_GET(NEQE_PORT_AVAILABILITY, eqe)) {
--			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-+			int suppress_event;
-+			/* replay modify_qp for sqps */
-+			spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-+			suppress_event = !sport->ibqp_sqp[IB_QPT_GSI];
-+			if (sport->ibqp_sqp[IB_QPT_SMI])
-+				ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_SMI]);
-+			if (!suppress_event)
-+				ehca_recover_sqp(sport->ibqp_sqp[IB_QPT_GSI]);
-+			spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
++	struct list_head list;
++	struct list_head active_listeners;
++	/* list of the netdev's associated with each logical port */
++	struct list_head nesvnic_list[4];
 +
-+			/* AQP1 was destroyed, ignore this event */
-+			if (suppress_event)
-+				break;
++	struct timer_list  mh_timer;
++	struct timer_list  lc_timer;
++	struct work_struct work;
++	spinlock_t         resource_lock;
++	spinlock_t         phy_lock;
++	spinlock_t         pbl_lock;
++	spinlock_t         periodic_timer_lock;
++
++	struct nes_arp_entry arp_table[NES_MAX_ARP_TABLE_SIZE];
++
++	/* Adapter CEQ and AEQs */
++	struct nes_hw_ceq ceq[16];
++	struct nes_hw_aeq aeq[8];
++
++	struct nes_hw_tune_timer tune_timer;
++
++	unsigned long doorbell_start;
++
++	u32 hw_rev;
++	u32 vendor_id;
++	u32 vendor_part_id;
++	u32 device_cap_flags;
++	u32 tick_delta;
++	u32 timer_int_req;
++	u32 arp_table_size;
++	u32 next_arp_index;
++
++	u32 max_mr;
++	u32 max_256pbl;
++	u32 max_4kpbl;
++	u32 free_256pbl;
++	u32 free_4kpbl;
++	u32 max_mr_size;
++	u32 max_qp;
++	u32 next_qp;
++	u32 max_irrq;
++	u32 max_qp_wr;
++	u32 max_sge;
++	u32 max_cq;
++	u32 next_cq;
++	u32 max_cqe;
++	u32 max_pd;
++	u32 base_pd;
++	u32 next_pd;
++	u32 hte_index_mask;
++
++	/* EEPROM information */
++	u32 rx_pool_size;
++	u32 tx_pool_size;
++	u32 rx_threshold;
++	u32 tcp_timer_core_clk_divisor;
++	u32 iwarp_config;
++	u32 cm_config;
++	u32 sws_timer_config;
++	u32 tcp_config1;
++	u32 wqm_wat;
++	u32 core_clock;
++	u32 firmware_version;
++
++	u32 nic_rx_eth_route_err;
++
++	u32 et_rx_coalesce_usecs;
++	u32	et_rx_max_coalesced_frames;
++	u32 et_rx_coalesce_usecs_irq;
++	u32 et_rx_max_coalesced_frames_irq;
++	u32 et_pkt_rate_low;
++	u32 et_rx_coalesce_usecs_low;
++	u32 et_rx_max_coalesced_frames_low;
++	u32 et_pkt_rate_high;
++	u32 et_rx_coalesce_usecs_high;
++	u32 et_rx_max_coalesced_frames_high;
++	u32 et_rate_sample_interval;
++	u32 timer_int_limit;
++
++	/* Adapter base MAC address */
++	u32 mac_addr_low;
++	u16 mac_addr_high;
++
++	u16 firmware_eeprom_offset;
++	u16 software_eeprom_offset;
++
++	u16 max_irrq_wr;
++
++	/* pd config for each port */
++	u16 pd_config_size[4];
++	u16 pd_config_base[4];
++
++	u16 link_interrupt_count[4];
++
++	/* the phy index for each port */
++	u8  phy_index[4];
++	u8  mac_sw_state[4];
++	u8  mac_link_down[4];
++	u8  phy_type[4];
++
++	/* PCI information */
++	unsigned int  devfn;
++	unsigned char bus_number;
++	unsigned char OneG_Mode;
++
++	unsigned char ref_count;
++	u8            netdev_count;
++	u8            netdev_max;	/* from host nic address count in EEPROM */
++	u8            port_count;
++	u8            virtwq;
++	u8            et_use_adaptive_rx_coalesce;
++	u8            adapter_fcn_count;
++};
++
++struct nes_pbl {
++	u64              *pbl_vbase;
++	dma_addr_t       pbl_pbase;
++	struct page      *page;
++	unsigned long    user_base;
++	u32              pbl_size;
++	struct list_head list;
++	/* TODO: need to add list for two level tables */
++};
 +
-+			sport->port_state = IB_PORT_ACTIVE;
- 			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
- 					    "is active");
- 			ehca_query_sma_attr(shca, port,
--					    &shca->sport[port - 1].saved_attr);
-+					    &sport->saved_attr);
- 		} else {
--			shca->sport[port - 1].port_state = IB_PORT_DOWN;
-+			sport->port_state = IB_PORT_DOWN;
- 			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
- 					    "is inactive");
- 		}
-@@ -378,11 +396,11 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
- 			ehca_warn(&shca->ib_device, "disruptive port "
- 				  "%d configuration change", port);
- 
--			shca->sport[port - 1].port_state = IB_PORT_DOWN;
-+			sport->port_state = IB_PORT_DOWN;
- 			dispatch_port_event(shca, port, IB_EVENT_PORT_ERR,
- 					    "is inactive");
- 
--			shca->sport[port - 1].port_state = IB_PORT_ACTIVE;
-+			sport->port_state = IB_PORT_ACTIVE;
- 			dispatch_port_event(shca, port, IB_EVENT_PORT_ACTIVE,
- 					    "is active");
- 		} else
-@@ -394,6 +412,16 @@ static void parse_ec(struct ehca_shca *shca, u64 eqe)
- 	case 0x33:  /* trace stopped */
- 		ehca_err(&shca->ib_device, "Traced stopped.");
- 		break;
-+	case 0x34: /* util async event */
-+		spec_event = EHCA_BMASK_GET(NEQE_SPECIFIC_EVENT, eqe);
-+		if (spec_event == 0x80) /* client reregister required */
-+			dispatch_port_event(shca, port,
-+					    IB_EVENT_CLIENT_REREGISTER,
-+					    "client reregister req.");
-+		else
-+			ehca_warn(&shca->ib_device, "Unknown util async "
-+				  "event %x on port %x", spec_event, port);
-+		break;
- 	default:
- 		ehca_err(&shca->ib_device, "Unknown event code: %x on %s.",
- 			 ec, shca->ib_device.name);
-diff --git a/drivers/infiniband/hw/ehca/ehca_iverbs.h b/drivers/infiniband/hw/ehca/ehca_iverbs.h
-index 5485799..c469bfd 100644
---- a/drivers/infiniband/hw/ehca/ehca_iverbs.h
-+++ b/drivers/infiniband/hw/ehca/ehca_iverbs.h
-@@ -200,4 +200,6 @@ void ehca_free_fw_ctrlblock(void *ptr);
- #define ehca_free_fw_ctrlblock(ptr) free_page((unsigned long)(ptr))
- #endif
- 
-+void ehca_recover_sqp(struct ib_qp *sqp);
++struct nes_listener {
++	struct work_struct      work;
++	struct workqueue_struct *wq;
++	struct nes_vnic         *nesvnic;
++	struct iw_cm_id         *cm_id;
++	struct list_head        list;
++	unsigned long           socket;
++	u8                      accept_failed;
++};
++
++struct nes_ib_device;
++
++struct nes_vnic {
++	struct nes_ib_device *nesibdev;
++	u64 sq_full;
++	u64 sq_locked;
++	u64 tso_requests;
++	u64 segmented_tso_requests;
++	u64 linearized_skbs;
++	u64 tx_sw_dropped;
++	u64 endnode_nstat_rx_discard;
++	u64 endnode_nstat_rx_octets;
++	u64 endnode_nstat_rx_frames;
++	u64 endnode_nstat_tx_octets;
++	u64 endnode_nstat_tx_frames;
++	u64 endnode_ipv4_tcp_retransmits;
++	/* void *mem; */
++	struct nes_device *nesdev;
++	struct net_device *netdev;
++	struct vlan_group *vlan_grp;
++	atomic_t          rx_skbs_needed;
++	atomic_t          rx_skb_timer_running;
++	int               budget;
++	u32               msg_enable;
++	/* u32 tx_avail; */
++	__be32            local_ipaddr;
++	struct napi_struct   napi;
++	spinlock_t           tx_lock;	/* could use netdev tx lock? */
++	struct timer_list    rq_wqes_timer;
++	u32                  nic_mem_size;
++	void                 *nic_vbase;
++	dma_addr_t           nic_pbase;
++	struct nes_hw_nic    nic;
++	struct nes_hw_nic_cq nic_cq;
++	u32    mcrq_qp_id;
++	struct nes_ucontext *mcrq_ucontext;
++	struct nes_cqp_request* (*get_cqp_request)(struct nes_device *nesdev);
++	void (*post_cqp_request)(struct nes_device*, struct nes_cqp_request *, int);
++	int (*mcrq_mcast_filter)( struct nes_vnic* nesvnic, __u8* dmi_addr );
++	struct net_device_stats netstats;
++	/* used to put the netdev on the adapters logical port list */
++	struct list_head list;
++	u16 max_frame_size;
++	u8  netdev_open;
++	u8  linkup;
++	u8  logical_port;
++	u8  netdev_index;  /* might not be needed, indexes nesdev->netdev */
++	u8  perfect_filter_index;
++	u8  nic_index;
++	u8  qp_nic_index[4];
++	u8  next_qp_nic_index;
++	u8  of_device_registered;
++	u8  rdma_enabled;
++	u8  rx_checksum_disabled;
++};
++
++struct nes_ib_device {
++	struct ib_device ibdev;
++	struct nes_vnic *nesvnic;
++
++	/* Virtual RNIC Limits */
++	u32 max_mr;
++	u32 max_qp;
++	u32 max_cq;
++	u32 max_pd;
++	u32 num_mr;
++	u32 num_qp;
++	u32 num_cq;
++	u32 num_pd;
++};
++
++#define nes_vlan_rx vlan_hwaccel_receive_skb
++#define nes_netif_rx netif_receive_skb
++
++#endif		/* __NES_HW_H */
+diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
+new file mode 100644
+index 0000000..b6cc265
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_nic.c
+@@ -0,0 +1,1703 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
 +
- #endif
-diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
-index 6a56d86..84c9b7b 100644
---- a/drivers/infiniband/hw/ehca/ehca_main.c
-+++ b/drivers/infiniband/hw/ehca/ehca_main.c
-@@ -90,7 +90,8 @@ MODULE_PARM_DESC(hw_level,
- 		 "hardware level"
- 		 " (0: autosensing (default), 1: v. 0.20, 2: v. 0.21)");
- MODULE_PARM_DESC(nr_ports,
--		 "number of connected ports (default: 2)");
-+		 "number of connected ports (-1: autodetect, 1: port one only, "
-+		 "2: two ports (default)");
- MODULE_PARM_DESC(use_hp_mr,
- 		 "high performance MRs (0: no (default), 1: yes)");
- MODULE_PARM_DESC(port_act_time,
-@@ -511,7 +512,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
- 	}
- 	sport->ibcq_aqp1 = ibcq;
- 
--	if (sport->ibqp_aqp1) {
-+	if (sport->ibqp_sqp[IB_QPT_GSI]) {
- 		ehca_err(&shca->ib_device, "AQP1 QP is already created.");
- 		ret = -EPERM;
- 		goto create_aqp1;
-@@ -537,7 +538,7 @@ static int ehca_create_aqp1(struct ehca_shca *shca, u32 port)
- 		ret = PTR_ERR(ibqp);
- 		goto create_aqp1;
- 	}
--	sport->ibqp_aqp1 = ibqp;
-+	sport->ibqp_sqp[IB_QPT_GSI] = ibqp;
- 
- 	return 0;
- 
-@@ -550,7 +551,7 @@ static int ehca_destroy_aqp1(struct ehca_sport *sport)
- {
- 	int ret;
- 
--	ret = ib_destroy_qp(sport->ibqp_aqp1);
-+	ret = ib_destroy_qp(sport->ibqp_sqp[IB_QPT_GSI]);
- 	if (ret) {
- 		ehca_gen_err("Cannot destroy AQP1 QP. ret=%i", ret);
- 		return ret;
-@@ -590,6 +591,11 @@ static struct attribute_group ehca_drv_attr_grp = {
- 	.attrs = ehca_drv_attrs
- };
- 
-+static struct attribute_group *ehca_drv_attr_groups[] = {
-+	&ehca_drv_attr_grp,
-+	NULL,
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/if_arp.h>
++#include <linux/if_vlan.h>
++#include <linux/ethtool.h>
++#include <net/tcp.h>
++
++#include <net/inet_common.h>
++#include <linux/inet.h>
++
++#include "nes.h"
++
++static struct nic_qp_map nic_qp_mapping_0[] = {
++	{16,0,0,1},{24,4,0,0},{28,8,0,0},{32,12,0,0},
++	{20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0},
++	{18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0},
++	{22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}
 +};
 +
- #define EHCA_RESOURCE_ATTR(name)                                           \
- static ssize_t  ehca_show_##name(struct device *dev,                       \
- 				 struct device_attribute *attr,            \
-@@ -688,7 +694,7 @@ static int __devinit ehca_probe(struct of_device *dev,
- 	struct ehca_shca *shca;
- 	const u64 *handle;
- 	struct ib_pd *ibpd;
--	int ret;
-+	int ret, i;
- 
- 	handle = of_get_property(dev->node, "ibm,hca-handle", NULL);
- 	if (!handle) {
-@@ -709,6 +715,8 @@ static int __devinit ehca_probe(struct of_device *dev,
- 		return -ENOMEM;
- 	}
- 	mutex_init(&shca->modify_mutex);
-+	for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
-+		spin_lock_init(&shca->sport[i].mod_sqp_lock);
- 
- 	shca->ofdev = dev;
- 	shca->ipz_hca_handle.handle = *handle;
-@@ -899,6 +907,9 @@ static struct of_platform_driver ehca_driver = {
- 	.match_table = ehca_device_table,
- 	.probe       = ehca_probe,
- 	.remove      = ehca_remove,
-+	.driver	     = {
-+		.groups = ehca_drv_attr_groups,
-+	},
- };
- 
- void ehca_poll_eqs(unsigned long data)
-@@ -926,7 +937,7 @@ void ehca_poll_eqs(unsigned long data)
- 				ehca_process_eq(shca, 0);
- 		}
- 	}
--	mod_timer(&poll_eqs_timer, jiffies + HZ);
-+	mod_timer(&poll_eqs_timer, round_jiffies(jiffies + HZ));
- 	spin_unlock(&shca_list_lock);
- }
- 
-@@ -957,10 +968,6 @@ int __init ehca_module_init(void)
- 		goto module_init2;
- 	}
- 
--	ret = sysfs_create_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp);
--	if (ret) /* only complain; we can live without attributes */
--		ehca_gen_err("Cannot create driver attributes  ret=%d", ret);
--
- 	if (ehca_poll_all_eqs != 1) {
- 		ehca_gen_err("WARNING!!!");
- 		ehca_gen_err("It is possible to lose interrupts.");
-@@ -986,7 +993,6 @@ void __exit ehca_module_exit(void)
- 	if (ehca_poll_all_eqs == 1)
- 		del_timer_sync(&poll_eqs_timer);
- 
--	sysfs_remove_group(&ehca_driver.driver.kobj, &ehca_drv_attr_grp);
- 	ibmebus_unregister_driver(&ehca_driver);
- 
- 	ehca_destroy_slab_caches();
-diff --git a/drivers/infiniband/hw/ehca/ehca_qp.c b/drivers/infiniband/hw/ehca/ehca_qp.c
-index eff5fb5..1012f15 100644
---- a/drivers/infiniband/hw/ehca/ehca_qp.c
-+++ b/drivers/infiniband/hw/ehca/ehca_qp.c
-@@ -592,10 +592,8 @@ static struct ehca_qp *internal_create_qp(
- 		goto create_qp_exit1;
- 	}
- 
--	if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
--		parms.sigtype = HCALL_SIGT_EVERY;
--	else
--		parms.sigtype = HCALL_SIGT_BY_WQE;
-+	/* Always signal by WQE so we can hide circ. WQEs */
-+	parms.sigtype = HCALL_SIGT_BY_WQE;
- 
- 	/* UD_AV CIRCUMVENTION */
- 	max_send_sge = init_attr->cap.max_send_sge;
-@@ -618,6 +616,10 @@ static struct ehca_qp *internal_create_qp(
- 	parms.squeue.max_sge = max_send_sge;
- 	parms.rqueue.max_sge = max_recv_sge;
- 
-+	/* RC QPs need one more SWQE for unsolicited ack circumvention */
-+	if (qp_type == IB_QPT_RC)
-+		parms.squeue.max_wr++;
++static struct nic_qp_map nic_qp_mapping_1[] = {
++	{18,1,1,1},{25,5,1,0},{29,9,1,0},{33,13,1,0},
++	{22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}
++};
 +
- 	if (EHCA_BMASK_GET(HCA_CAP_MINI_QP, shca->hca_cap)) {
- 		if (HAS_SQ(my_qp))
- 			ehca_determine_small_queue(
-@@ -650,6 +652,8 @@ static struct ehca_qp *internal_create_qp(
- 			parms.squeue.act_nr_sges = 1;
- 			parms.rqueue.act_nr_sges = 1;
- 		}
-+		/* hide the extra WQE */
-+		parms.squeue.act_nr_wqes--;
- 		break;
- 	case IB_QPT_UD:
- 	case IB_QPT_GSI:
-@@ -729,12 +733,31 @@ static struct ehca_qp *internal_create_qp(
- 	init_attr->cap.max_send_wr = parms.squeue.act_nr_wqes;
- 	my_qp->init_attr = *init_attr;
- 
-+	if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
-+		shca->sport[init_attr->port_num - 1].ibqp_sqp[qp_type] =
-+			&my_qp->ib_qp;
-+		if (ehca_nr_ports < 0) {
-+			/* alloc array to cache subsequent modify qp parms
-+			 * for autodetect mode
-+			 */
-+			my_qp->mod_qp_parm =
-+				kzalloc(EHCA_MOD_QP_PARM_MAX *
-+					sizeof(*my_qp->mod_qp_parm),
-+					GFP_KERNEL);
-+			if (!my_qp->mod_qp_parm) {
-+				ehca_err(pd->device,
-+					 "Could not alloc mod_qp_parm");
-+				goto create_qp_exit4;
++static struct nic_qp_map nic_qp_mapping_2[] = {
++	{20,2,2,1},{26,6,2,0},{30,10,2,0},{34,14,2,0}
++};
++
++static struct nic_qp_map nic_qp_mapping_3[] = {
++	{22,3,3,1},{27,7,3,0},{31,11,3,0},{35,15,3,0}
++};
++
++static struct nic_qp_map nic_qp_mapping_4[] = {
++	{28,8,0,0},{32,12,0,0}
++};
++
++static struct nic_qp_map nic_qp_mapping_5[] = {
++	{29,9,1,0},{33,13,1,0}
++};
++
++static struct nic_qp_map nic_qp_mapping_6[] = {
++	{30,10,2,0},{34,14,2,0}
++};
++
++static struct nic_qp_map nic_qp_mapping_7[] = {
++	{31,11,3,0},{35,15,3,0}
++};
++
++static struct nic_qp_map *nic_qp_mapping_per_function[] = {
++	nic_qp_mapping_0, nic_qp_mapping_1, nic_qp_mapping_2, nic_qp_mapping_3,
++	nic_qp_mapping_4, nic_qp_mapping_5, nic_qp_mapping_6, nic_qp_mapping_7
++};
++
++static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK
++		| NETIF_MSG_IFUP | NETIF_MSG_IFDOWN;
++static int debug = -1;
++
++
++static int nes_netdev_open(struct net_device *);
++static int nes_netdev_stop(struct net_device *);
++static int nes_netdev_start_xmit(struct sk_buff *, struct net_device *);
++static struct net_device_stats *nes_netdev_get_stats(struct net_device *);
++static void nes_netdev_tx_timeout(struct net_device *);
++static int nes_netdev_set_mac_address(struct net_device *, void *);
++static int nes_netdev_change_mtu(struct net_device *, int);
++
++/**
++ * nes_netdev_poll
++ */
++static int nes_netdev_poll(struct napi_struct *napi, int budget)
++{
++	struct nes_vnic *nesvnic = container_of(napi, struct nes_vnic, napi);
++	struct net_device *netdev = nesvnic->netdev;
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_hw_nic_cq *nescq = &nesvnic->nic_cq;
++
++	nesvnic->budget = budget;
++	nescq->cqes_pending = 0;
++	nescq->rx_cqes_completed = 0;
++	nescq->cqe_allocs_pending = 0;
++	nescq->rx_pkts_indicated = 0;
++
++	nes_nic_ce_handler(nesdev, nescq);
++
++	if (nescq->cqes_pending == 0) {
++		netif_rx_complete(netdev, napi);
++		/* clear out completed cqes and arm */
++		nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
++				nescq->cq_number | (nescq->cqe_allocs_pending << 16));
++		nes_read32(nesdev->regs+NES_CQE_ALLOC);
++	} else {
++		/* clear out completed cqes but don't arm */
++		nes_write32(nesdev->regs+NES_CQE_ALLOC,
++				nescq->cq_number | (nescq->cqe_allocs_pending << 16));
++		nes_debug(NES_DBG_NETDEV, "%s: exiting with work pending\n",
++				nesvnic->netdev->name);
++	}
++	return nescq->rx_pkts_indicated;
++}
++
++
++/**
++ * nes_netdev_open - Activate the network interface; ifconfig
++ * ethx up.
++ */
++static int nes_netdev_open(struct net_device *netdev)
++{
++	u32 macaddr_low;
++	u16 macaddr_high;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	int ret;
++	int i;
++	struct nes_vnic *first_nesvnic;
++	u32 nic_active_bit;
++	u32 nic_active;
++
++	assert(nesdev != NULL);
++
++	first_nesvnic = list_entry(nesdev->nesadapter->nesvnic_list[nesdev->mac_index].next,
++			struct nes_vnic, list);
++
++	if (netif_msg_ifup(nesvnic))
++		printk(KERN_INFO PFX "%s: enabling interface\n", netdev->name);
++
++	ret = nes_init_nic_qp(nesdev, netdev);
++	if (ret) {
++		return ret;
++	}
++
++	netif_carrier_off(netdev);
++	netif_stop_queue(netdev);
++
++	if ((!nesvnic->of_device_registered) && (nesvnic->rdma_enabled)) {
++		nesvnic->nesibdev = nes_init_ofa_device(netdev);
++		if (nesvnic->nesibdev == NULL) {
++			printk(KERN_ERR PFX "%s: nesvnic->nesibdev alloc failed", netdev->name);
++		} else {
++			nesvnic->nesibdev->nesvnic = nesvnic;
++			ret = nes_register_ofa_device(nesvnic->nesibdev);
++			if (ret) {
++				printk(KERN_ERR PFX "%s: Unable to register RDMA device, ret = %d\n",
++						netdev->name, ret);
 +			}
 +		}
 +	}
++	/* Set packet filters */
++	nic_active_bit = 1 << nesvnic->nic_index;
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);
++	nic_active |= nic_active_bit;
++	nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);
++	nic_active |= nic_active_bit;
++	nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);
++	nic_active |= nic_active_bit;
++	nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
 +
- 	/* NOTE: define_apq0() not supported yet */
- 	if (qp_type == IB_QPT_GSI) {
- 		h_ret = ehca_define_sqp(shca, my_qp, init_attr);
- 		if (h_ret != H_SUCCESS) {
- 			ret = ehca2ib_return_code(h_ret);
--			goto create_qp_exit4;
-+			goto create_qp_exit5;
- 		}
- 	}
- 
-@@ -743,7 +766,7 @@ static struct ehca_qp *internal_create_qp(
- 		if (ret) {
- 			ehca_err(pd->device,
- 				 "Couldn't assign qp to send_cq ret=%i", ret);
--			goto create_qp_exit4;
-+			goto create_qp_exit5;
- 		}
- 	}
- 
-@@ -769,12 +792,18 @@ static struct ehca_qp *internal_create_qp(
- 		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
- 			ehca_err(pd->device, "Copy to udata failed");
- 			ret = -EINVAL;
--			goto create_qp_exit4;
-+			goto create_qp_exit6;
- 		}
- 	}
- 
- 	return my_qp;
- 
-+create_qp_exit6:
-+	ehca_cq_unassign_qp(my_qp->send_cq, my_qp->real_qp_num);
++	macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
++	macaddr_high += (u16)netdev->dev_addr[1];
++	macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
++	macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
++	macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
++	macaddr_low += (u32)netdev->dev_addr[5];
 +
-+create_qp_exit5:
-+	kfree(my_qp->mod_qp_parm);
++	/* Program the various MAC regs */
++	for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
++		if (nesvnic->qp_nic_index[i] == 0xf) {
++			break;
++		}
++		nes_debug(NES_DBG_NETDEV, "i=%d, perfect filter table index= %d, PERF FILTER LOW"
++				" (Addr:%08X) = %08X, HIGH = %08X.\n",
++				i, nesvnic->qp_nic_index[i],
++				NES_IDX_PERFECT_FILTER_LOW+((nesvnic->perfect_filter_index + i) * 8),
++				macaddr_low,
++				(u32)macaddr_high | NES_MAC_ADDR_VALID |
++				((((u32)nesvnic->nic_index) << 16)));
++		nes_write_indexed(nesdev,
++				NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),
++				macaddr_low);
++		nes_write_indexed(nesdev,
++				NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),
++				(u32)macaddr_high | NES_MAC_ADDR_VALID |
++				((((u32)nesvnic->nic_index) << 16)));
++	}
 +
- create_qp_exit4:
- 	if (HAS_RQ(my_qp))
- 		ipz_queue_dtor(my_pd, &my_qp->ipz_rqueue);
-@@ -858,7 +887,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
- 				update_mask,
- 				mqpcb, my_qp->galpas.kernel);
- 	if (hret != H_SUCCESS) {
--		ehca_err(pd->device, "Could not modify SRQ to INIT"
-+		ehca_err(pd->device, "Could not modify SRQ to INIT "
- 			 "ehca_qp=%p qp_num=%x h_ret=%li",
- 			 my_qp, my_qp->real_qp_num, hret);
- 		goto create_srq2;
-@@ -872,7 +901,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
- 				update_mask,
- 				mqpcb, my_qp->galpas.kernel);
- 	if (hret != H_SUCCESS) {
--		ehca_err(pd->device, "Could not enable SRQ"
-+		ehca_err(pd->device, "Could not enable SRQ "
- 			 "ehca_qp=%p qp_num=%x h_ret=%li",
- 			 my_qp, my_qp->real_qp_num, hret);
- 		goto create_srq2;
-@@ -886,7 +915,7 @@ struct ib_srq *ehca_create_srq(struct ib_pd *pd,
- 				update_mask,
- 				mqpcb, my_qp->galpas.kernel);
- 	if (hret != H_SUCCESS) {
--		ehca_err(pd->device, "Could not modify SRQ to RTR"
-+		ehca_err(pd->device, "Could not modify SRQ to RTR "
- 			 "ehca_qp=%p qp_num=%x h_ret=%li",
- 			 my_qp, my_qp->real_qp_num, hret);
- 		goto create_srq2;
-@@ -992,7 +1021,7 @@ static int internal_modify_qp(struct ib_qp *ibqp,
- 	unsigned long flags = 0;
- 
- 	/* do query_qp to obtain current attr values */
--	mqpcb = ehca_alloc_fw_ctrlblock(GFP_KERNEL);
-+	mqpcb = ehca_alloc_fw_ctrlblock(GFP_ATOMIC);
- 	if (!mqpcb) {
- 		ehca_err(ibqp->device, "Could not get zeroed page for mqpcb "
- 			 "ehca_qp=%p qp_num=%x ", my_qp, ibqp->qp_num);
-@@ -1180,6 +1209,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
- 		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_P_KEY_IDX, 1);
- 	}
- 	if (attr_mask & IB_QP_PORT) {
-+		struct ehca_sport *sport;
-+		struct ehca_qp *aqp1;
- 		if (attr->port_num < 1 || attr->port_num > shca->num_ports) {
- 			ret = -EINVAL;
- 			ehca_err(ibqp->device, "Invalid port=%x. "
-@@ -1188,6 +1219,29 @@ static int internal_modify_qp(struct ib_qp *ibqp,
- 				 shca->num_ports);
- 			goto modify_qp_exit2;
- 		}
-+		sport = &shca->sport[attr->port_num - 1];
-+		if (!sport->ibqp_sqp[IB_QPT_GSI]) {
-+			/* should not occur */
-+			ret = -EFAULT;
-+			ehca_err(ibqp->device, "AQP1 was not created for "
-+				 "port=%x", attr->port_num);
-+			goto modify_qp_exit2;
++
++	nes_write32(nesdev->regs+NES_CQE_ALLOC, NES_CQE_ALLOC_NOTIFY_NEXT |
++			nesvnic->nic_cq.cq_number);
++	nes_read32(nesdev->regs+NES_CQE_ALLOC);
++
++	if (first_nesvnic->linkup) {
++		/* Enable network packets */
++		nesvnic->linkup = 1;
++		netif_start_queue(netdev);
++		netif_carrier_on(netdev);
++	}
++	napi_enable(&nesvnic->napi);
++	nesvnic->netdev_open = 1;
++
++	return 0;
++}
++
++
++/**
++ * nes_netdev_stop
++ */
++static int nes_netdev_stop(struct net_device *netdev)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	u32 nic_active_mask;
++	u32 nic_active;
++
++	nes_debug(NES_DBG_SHUTDOWN, "nesvnic=%p, nesdev=%p, netdev=%p %s\n",
++			nesvnic, nesdev, netdev, netdev->name);
++	if (nesvnic->netdev_open == 0)
++		return 0;
++
++	if (netif_msg_ifdown(nesvnic))
++		printk(KERN_INFO PFX "%s: disabling interface\n", netdev->name);
++
++	/* Disable network packets */
++	napi_disable(&nesvnic->napi);
++	netif_stop_queue(netdev);
++	if ((nesdev->netdev[0] == netdev) & (nesvnic->logical_port == nesdev->mac_index)) {
++		nes_write_indexed(nesdev,
++				NES_IDX_MAC_INT_MASK+(0x200*nesdev->mac_index), 0xffffffff);
++	}
++
++	nic_active_mask = ~((u32)(1 << nesvnic->nic_index));
++	nes_write_indexed(nesdev, NES_IDX_PERFECT_FILTER_HIGH+
++			(nesvnic->perfect_filter_index*8), 0);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_ACTIVE);
++	nic_active &= nic_active_mask;
++	nes_write_indexed(nesdev, NES_IDX_NIC_ACTIVE, nic_active);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
++	nic_active &= nic_active_mask;
++	nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE);
++	nic_active &= nic_active_mask;
++	nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ENABLE, nic_active);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
++	nic_active &= nic_active_mask;
++	nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
++	nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON);
++	nic_active &= nic_active_mask;
++	nes_write_indexed(nesdev, NES_IDX_NIC_BROADCAST_ON, nic_active);
++
++
++	if (nesvnic->of_device_registered) {
++		nes_destroy_ofa_device(nesvnic->nesibdev);
++		nesvnic->nesibdev = NULL;
++		nesvnic->of_device_registered = 0;
++	}
++	nes_destroy_nic_qp(nesvnic);
++
++	nesvnic->netdev_open = 0;
++
++	return 0;
++}
++
++
++/**
++ * nes_nic_send
++ */
++static int nes_nic_send(struct sk_buff *skb, struct net_device *netdev)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_hw_nic *nesnic = &nesvnic->nic;
++	struct nes_hw_nic_sq_wqe *nic_sqe;
++	struct tcphdr *tcph;
++	__le16 *wqe_fragment_length;
++	u32 wqe_misc;
++	u16 wqe_fragment_index = 1;	/* first fragment (0) is used by copy buffer */
++	u16 skb_fragment_index;
++	dma_addr_t bus_address;
++
++	nic_sqe = &nesnic->sq_vbase[nesnic->sq_head];
++	wqe_fragment_length = (__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
++
++	/* setup the VLAN tag if present */
++	if (vlan_tx_tag_present(skb)) {
++		nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n",
++				netdev->name, vlan_tx_tag_get(skb));
++		wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE;
++		wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb);
++	} else
++		wqe_misc = 0;
++
++	/* bump past the vlan tag */
++	wqe_fragment_length++;
++	/*	wqe_fragment_address = (u64 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_FRAG0_LOW_IDX]; */
++
++	if (skb->ip_summed == CHECKSUM_PARTIAL) {
++		tcph = tcp_hdr(skb);
++		if (1) {
++			if (skb_is_gso(skb)) {
++				/* nes_debug(NES_DBG_NIC_TX, "%s: TSO request... seg size = %u\n",
++						netdev->name, skb_is_gso(skb)); */
++				wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE |
++						NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
++				set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,
++						((u32)tcph->doff) |
++						(((u32)(((unsigned char *)tcph) - skb->data)) << 4));
++			} else {
++				wqe_misc |= NES_NIC_SQ_WQE_COMPLETION;
++			}
 +		}
-+		aqp1 = container_of(sport->ibqp_sqp[IB_QPT_GSI],
-+				    struct ehca_qp, ib_qp);
-+		if (ibqp->qp_type != IB_QPT_GSI &&
-+		    ibqp->qp_type != IB_QPT_SMI &&
-+		    aqp1->mod_qp_parm) {
-+			/*
-+			 * firmware will reject this modify_qp() because
-+			 * port is not activated/initialized fully
-+			 */
-+			ret = -EFAULT;
-+			ehca_warn(ibqp->device, "Couldn't modify qp port=%x: "
-+				  "either port is being activated (try again) "
-+				  "or cabling issue", attr->port_num);
-+			goto modify_qp_exit2;
++	} else {	/* CHECKSUM_HW */
++		wqe_misc |= NES_NIC_SQ_WQE_DISABLE_CHKSUM | NES_NIC_SQ_WQE_COMPLETION;
++	}
++
++	set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,
++				skb->len);
++	memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,
++			skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE), skb_headlen(skb)));
++	wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),
++			skb_headlen(skb)));
++	wqe_fragment_length[1] = 0;
++	if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {
++		if ((skb_shinfo(skb)->nr_frags + 1) > 4) {
++			nes_debug(NES_DBG_NIC_TX, "%s: Packet with %u fragments not sent, skb_headlen=%u\n",
++					netdev->name, skb_shinfo(skb)->nr_frags + 2, skb_headlen(skb));
++			kfree_skb(skb);
++			nesvnic->tx_sw_dropped++;
++			return NETDEV_TX_LOCKED;
 +		}
- 		mqpcb->prim_phys_port = attr->port_num;
- 		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PRIM_PHYS_PORT, 1);
- 	}
-@@ -1244,6 +1298,8 @@ static int internal_modify_qp(struct ib_qp *ibqp,
- 	}
- 
- 	if (attr_mask & IB_QP_PATH_MTU) {
-+		/* store ld(MTU) */
-+		my_qp->mtu_shift = attr->path_mtu + 7;
- 		mqpcb->path_mtu = attr->path_mtu;
- 		update_mask |= EHCA_BMASK_SET(MQPCB_MASK_PATH_MTU, 1);
- 	}
-@@ -1467,6 +1523,8 @@ modify_qp_exit1:
- int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
- 		   struct ib_udata *udata)
- {
-+	struct ehca_shca *shca = container_of(ibqp->device, struct ehca_shca,
-+					      ib_device);
- 	struct ehca_qp *my_qp = container_of(ibqp, struct ehca_qp, ib_qp);
- 	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
- 					     ib_pd);
-@@ -1479,9 +1537,100 @@ int ehca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask,
- 		return -EINVAL;
- 	}
- 
-+	/* The if-block below caches qp_attr to be modified for GSI and SMI
-+	 * qps during the initialization by ib_mad. When the respective port
-+	 * is activated, ie we got an event PORT_ACTIVE, we'll replay the
-+	 * cached modify calls sequence, see ehca_recover_sqs() below.
-+	 * Why that is required:
-+	 * 1) If one port is connected, older code requires that port one
-+	 *    to be connected and module option nr_ports=1 to be given by
-+	 *    user, which is very inconvenient for end user.
-+	 * 2) Firmware accepts modify_qp() only if respective port has become
-+	 *    active. Older code had a wait loop of 30sec create_qp()/
-+	 *    define_aqp1(), which is not appropriate in practice. This
-+	 *    code now removes that wait loop, see define_aqp1(), and always
-+	 *    reports all ports to ib_mad resp. users. Only activated ports
-+	 *    will then usable for the users.
-+	 */
-+	if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_SMI) {
-+		int port = my_qp->init_attr.port_num;
-+		struct ehca_sport *sport = &shca->sport[port - 1];
-+		unsigned long flags;
-+		spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-+		/* cache qp_attr only during init */
-+		if (my_qp->mod_qp_parm) {
-+			struct ehca_mod_qp_parm *p;
-+			if (my_qp->mod_qp_parm_idx >= EHCA_MOD_QP_PARM_MAX) {
-+				ehca_err(&shca->ib_device,
-+					 "mod_qp_parm overflow state=%x port=%x"
-+					 " type=%x", attr->qp_state,
-+					 my_qp->init_attr.port_num,
-+					 ibqp->qp_type);
-+				spin_unlock_irqrestore(&sport->mod_sqp_lock,
-+						       flags);
-+				return -EINVAL;
-+			}
-+			p = &my_qp->mod_qp_parm[my_qp->mod_qp_parm_idx];
-+			p->mask = attr_mask;
-+			p->attr = *attr;
-+			my_qp->mod_qp_parm_idx++;
-+			ehca_dbg(&shca->ib_device,
-+				 "Saved qp_attr for state=%x port=%x type=%x",
-+				 attr->qp_state, my_qp->init_attr.port_num,
-+				 ibqp->qp_type);
-+			spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-+			return 0;
++		set_bit(nesnic->sq_head, nesnic->first_frag_overflow);
++		bus_address = pci_map_single(nesdev->pcidev, skb->data + NES_FIRST_FRAG_SIZE,
++				skb_headlen(skb) - NES_FIRST_FRAG_SIZE, PCI_DMA_TODEVICE);
++		wqe_fragment_length[wqe_fragment_index++] =
++				cpu_to_le16(skb_headlen(skb) - NES_FIRST_FRAG_SIZE);
++		wqe_fragment_length[wqe_fragment_index] = 0;
++		set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
++				((u64)(bus_address)));
++		nesnic->tx_skb[nesnic->sq_head] = skb;
++	}
++
++	if (skb_headlen(skb) == skb->len) {
++		if (skb_headlen(skb) <= NES_FIRST_FRAG_SIZE) {
++			nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_2_1_IDX] = 0;
++			nesnic->tx_skb[nesnic->sq_head] = NULL;
++			dev_kfree_skb(skb);
++		}
++	} else {
++		/* Deal with Fragments */
++		nesnic->tx_skb[nesnic->sq_head] = skb;
++		for (skb_fragment_index = 0; skb_fragment_index < skb_shinfo(skb)->nr_frags;
++				skb_fragment_index++) {
++			bus_address = pci_map_page( nesdev->pcidev,
++					skb_shinfo(skb)->frags[skb_fragment_index].page,
++					skb_shinfo(skb)->frags[skb_fragment_index].page_offset,
++					skb_shinfo(skb)->frags[skb_fragment_index].size,
++					PCI_DMA_TODEVICE);
++			wqe_fragment_length[wqe_fragment_index] =
++					cpu_to_le16(skb_shinfo(skb)->frags[skb_fragment_index].size);
++			set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
++				bus_address);
++			wqe_fragment_index++;
++			if (wqe_fragment_index < 5)
++				wqe_fragment_length[wqe_fragment_index] = 0;
 +		}
-+		spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
 +	}
 +
- 	return internal_modify_qp(ibqp, attr, attr_mask, 0);
- }
- 
-+void ehca_recover_sqp(struct ib_qp *sqp)
++	set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX, wqe_misc);
++	nesnic->sq_head++;
++	nesnic->sq_head &= nesnic->sq_size - 1;
++
++	return NETDEV_TX_OK;
++}
++
++
++/**
++ * nes_netdev_start_xmit
++ */
++static int nes_netdev_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 +{
-+	struct ehca_qp *my_sqp = container_of(sqp, struct ehca_qp, ib_qp);
-+	int port = my_sqp->init_attr.port_num;
-+	struct ib_qp_attr attr;
-+	struct ehca_mod_qp_parm *qp_parm;
-+	int i, qp_parm_idx, ret;
-+	unsigned long flags, wr_cnt;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_hw_nic *nesnic = &nesvnic->nic;
++	struct nes_hw_nic_sq_wqe *nic_sqe;
++	struct tcphdr *tcph;
++	/* struct udphdr *udph; */
++#define NES_MAX_TSO_FRAGS 18
++	/* 64K segment plus overflow on each side */
++	dma_addr_t tso_bus_address[NES_MAX_TSO_FRAGS];
++	dma_addr_t bus_address;
++	u32 tso_frag_index;
++	u32 tso_frag_count;
++	u32 tso_wqe_length;
++	u32 curr_tcp_seq;
++	u32 wqe_count=1;
++	u32 send_rc;
++	struct iphdr *iph;
++	unsigned long flags;
++	__le16 *wqe_fragment_length;
++	u32 nr_frags;
++	u32 original_first_length;
++//	u64 *wqe_fragment_address;
++	/* first fragment (0) is used by copy buffer */
++	u16 wqe_fragment_index=1;
++	u16 hoffset;
++	u16 nhoffset;
++	u16 wqes_needed;
++	u16 wqes_available;
++	u32 old_head;
++	u32 wqe_misc;
++
++	/* nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
++			" (%u frags), tso_size=%u\n",
++			netdev->name, skb->len, skb_headlen(skb),
++			skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
++	*/
 +
-+	if (!my_sqp->mod_qp_parm)
-+		return;
-+	ehca_dbg(sqp->device, "SQP port=%x qp_num=%x", port, sqp->qp_num);
++	if (!netif_carrier_ok(netdev))
++		return NETDEV_TX_OK;
 +
-+	qp_parm = my_sqp->mod_qp_parm;
-+	qp_parm_idx = my_sqp->mod_qp_parm_idx;
-+	for (i = 0; i < qp_parm_idx; i++) {
-+		attr = qp_parm[i].attr;
-+		ret = internal_modify_qp(sqp, &attr, qp_parm[i].mask, 0);
-+		if (ret) {
-+			ehca_err(sqp->device, "Could not modify SQP port=%x "
-+				 "qp_num=%x ret=%x", port, sqp->qp_num, ret);
-+			goto free_qp_parm;
++	if (netif_queue_stopped(netdev))
++		return NETDEV_TX_BUSY;
++
++	local_irq_save(flags);
++	if (!spin_trylock(&nesnic->sq_lock)) {
++		local_irq_restore(flags);
++		nesvnic->sq_locked++;
++		return NETDEV_TX_LOCKED;
++	}
++
++	/* Check if SQ is full */
++	if ((((nesnic->sq_tail+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) == 1) {
++		if (!netif_queue_stopped(netdev)) {
++			netif_stop_queue(netdev);
++			barrier();
++			if ((((((volatile u16)nesnic->sq_tail)+(nesnic->sq_size*2))-nesnic->sq_head) & (nesnic->sq_size - 1)) != 1) {
++				netif_start_queue(netdev);
++				goto sq_no_longer_full;
++			}
 +		}
-+		ehca_dbg(sqp->device, "SQP port=%x qp_num=%x in state=%x",
-+			 port, sqp->qp_num, attr.qp_state);
++		nesvnic->sq_full++;
++		spin_unlock_irqrestore(&nesnic->sq_lock, flags);
++		return NETDEV_TX_BUSY;
 +	}
 +
-+	/* re-trigger posted recv wrs */
-+	wr_cnt =  my_sqp->ipz_rqueue.current_q_offset /
-+		my_sqp->ipz_rqueue.qe_size;
-+	if (wr_cnt) {
-+		spin_lock_irqsave(&my_sqp->spinlock_r, flags);
-+		hipz_update_rqa(my_sqp, wr_cnt);
-+		spin_unlock_irqrestore(&my_sqp->spinlock_r, flags);
-+		ehca_dbg(sqp->device, "doorbell port=%x qp_num=%x wr_cnt=%lx",
-+			 port, sqp->qp_num, wr_cnt);
++sq_no_longer_full:
++	nr_frags = skb_shinfo(skb)->nr_frags;
++	if (skb_headlen(skb) > NES_FIRST_FRAG_SIZE) {
++		nr_frags++;
++	}
++	/* Check if too many fragments */
++	if (unlikely((nr_frags > 4))) {
++		if (skb_is_gso(skb)) {
++			nesvnic->segmented_tso_requests++;
++			nesvnic->tso_requests++;
++			old_head = nesnic->sq_head;
++			/* Basically 4 fragments available per WQE with extended fragments */
++			wqes_needed = nr_frags >> 2;
++			wqes_needed += (nr_frags&3)?1:0;
++			wqes_available = (((nesnic->sq_tail+nesnic->sq_size)-nesnic->sq_head) - 1) &
++					(nesnic->sq_size - 1);
++
++			if (unlikely(wqes_needed > wqes_available)) {
++				if (!netif_queue_stopped(netdev)) {
++					netif_stop_queue(netdev);
++					barrier();
++					wqes_available = (((((volatile u16)nesnic->sq_tail)+nesnic->sq_size)-nesnic->sq_head) - 1) &
++						(nesnic->sq_size - 1);
++					if (wqes_needed <= wqes_available) {
++						netif_start_queue(netdev);
++						goto tso_sq_no_longer_full;
++					}
++				}
++				nesvnic->sq_full++;
++				spin_unlock_irqrestore(&nesnic->sq_lock, flags);
++				nes_debug(NES_DBG_NIC_TX, "%s: HNIC SQ full- TSO request has too many frags!\n",
++						netdev->name);
++				return NETDEV_TX_BUSY;
++			}
++tso_sq_no_longer_full:
++			/* Map all the buffers */
++			for (tso_frag_count=0; tso_frag_count < skb_shinfo(skb)->nr_frags;
++					tso_frag_count++) {
++				tso_bus_address[tso_frag_count] = pci_map_page( nesdev->pcidev,
++						skb_shinfo(skb)->frags[tso_frag_count].page,
++						skb_shinfo(skb)->frags[tso_frag_count].page_offset,
++						skb_shinfo(skb)->frags[tso_frag_count].size,
++						PCI_DMA_TODEVICE);
++			}
++
++			tso_frag_index = 0;
++			curr_tcp_seq = ntohl(tcp_hdr(skb)->seq);
++			hoffset = skb_transport_header(skb) - skb->data;
++			nhoffset = skb_network_header(skb) - skb->data;
++			original_first_length = hoffset + ((((struct tcphdr *)skb_transport_header(skb))->doff)<<2);
++
++			for (wqe_count=0; wqe_count<((u32)wqes_needed); wqe_count++) {
++				tso_wqe_length = 0;
++				nic_sqe = &nesnic->sq_vbase[nesnic->sq_head];
++				wqe_fragment_length =
++						(__le16 *)&nic_sqe->wqe_words[NES_NIC_SQ_WQE_LENGTH_0_TAG_IDX];
++				/* setup the VLAN tag if present */
++				if (vlan_tx_tag_present(skb)) {
++					nes_debug(NES_DBG_NIC_TX, "%s: VLAN packet to send... VLAN = %08X\n",
++							netdev->name, vlan_tx_tag_get(skb) );
++					wqe_misc = NES_NIC_SQ_WQE_TAGVALUE_ENABLE;
++					wqe_fragment_length[0] = (__force __le16) vlan_tx_tag_get(skb);
++				} else
++					wqe_misc = 0;
++
++				/* bump past the vlan tag */
++				wqe_fragment_length++;
++
++				/* Assumes header totally fits in allocated buffer and is in first fragment */
++				if (original_first_length > NES_FIRST_FRAG_SIZE) {
++					nes_debug(NES_DBG_NIC_TX, "ERROR: SKB header too big, headlen=%u, FIRST_FRAG_SIZE=%u\n",
++							original_first_length, NES_FIRST_FRAG_SIZE);
++					nes_debug(NES_DBG_NIC_TX, "%s Request to tx NIC packet length %u, headlen %u,"
++							" (%u frags), tso_size=%u\n",
++							netdev->name,
++							skb->len, skb_headlen(skb),
++							skb_shinfo(skb)->nr_frags, skb_is_gso(skb));
++				}
++				memcpy(&nesnic->first_frag_vbase[nesnic->sq_head].buffer,
++						skb->data, min(((unsigned int)NES_FIRST_FRAG_SIZE),
++						original_first_length));
++				iph = (struct iphdr *)
++				(&nesnic->first_frag_vbase[nesnic->sq_head].buffer[nhoffset]);
++				tcph = (struct tcphdr *)
++				(&nesnic->first_frag_vbase[nesnic->sq_head].buffer[hoffset]);
++				if ((wqe_count+1)!=(u32)wqes_needed) {
++					tcph->fin = 0;
++					tcph->psh = 0;
++					tcph->rst = 0;
++					tcph->urg = 0;
++				}
++				if (wqe_count) {
++					tcph->syn = 0;
++				}
++				tcph->seq = htonl(curr_tcp_seq);
++				wqe_fragment_length[0] = cpu_to_le16(min(((unsigned int)NES_FIRST_FRAG_SIZE),
++						original_first_length));
++
++				wqe_fragment_index = 1;
++				if ((wqe_count==0) && (skb_headlen(skb) > original_first_length)) {
++					set_bit(nesnic->sq_head, nesnic->first_frag_overflow);
++					bus_address = pci_map_single(nesdev->pcidev, skb->data + original_first_length,
++							skb_headlen(skb) - original_first_length, PCI_DMA_TODEVICE);
++					wqe_fragment_length[wqe_fragment_index++] =
++						cpu_to_le16(skb_headlen(skb) - original_first_length);
++					wqe_fragment_length[wqe_fragment_index] = 0;
++					set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG1_LOW_IDX,
++									bus_address);
++				}
++				while (wqe_fragment_index < 5) {
++					wqe_fragment_length[wqe_fragment_index] =
++							cpu_to_le16(skb_shinfo(skb)->frags[tso_frag_index].size);
++					set_wqe_64bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_FRAG0_LOW_IDX+(2*wqe_fragment_index),
++						(u64)tso_bus_address[tso_frag_index]);
++					wqe_fragment_index++;
++					tso_wqe_length += skb_shinfo(skb)->frags[tso_frag_index++].size;
++					if (wqe_fragment_index < 5)
++						wqe_fragment_length[wqe_fragment_index] = 0;
++					if (tso_frag_index == tso_frag_count)
++						break;
++				}
++				if ((wqe_count+1) == (u32)wqes_needed) {
++					nesnic->tx_skb[nesnic->sq_head] = skb;
++				} else {
++					nesnic->tx_skb[nesnic->sq_head] = NULL;
++				}
++				wqe_misc |= NES_NIC_SQ_WQE_COMPLETION | (u16)skb_is_gso(skb);
++				if ((tso_wqe_length + original_first_length) > skb_is_gso(skb)) {
++					wqe_misc |= NES_NIC_SQ_WQE_LSO_ENABLE;
++				} else {
++					iph->tot_len = htons(tso_wqe_length + original_first_length - nhoffset);
++				}
++
++				set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_MISC_IDX,
++						 wqe_misc);
++				set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_LSO_INFO_IDX,
++						((u32)tcph->doff) | (((u32)hoffset) << 4));
++
++				set_wqe_32bit_value(nic_sqe->wqe_words, NES_NIC_SQ_WQE_TOTAL_LENGTH_IDX,
++						tso_wqe_length + original_first_length);
++				curr_tcp_seq += tso_wqe_length;
++				nesnic->sq_head++;
++				nesnic->sq_head &= nesnic->sq_size-1;
++			}
++		} else {
++			nesvnic->linearized_skbs++;
++			hoffset = skb_transport_header(skb) - skb->data;
++			nhoffset = skb_network_header(skb) - skb->data;
++			skb_linearize(skb);
++			skb_set_transport_header(skb, hoffset);
++			skb_set_network_header(skb, nhoffset);
++			send_rc = nes_nic_send(skb, netdev);
++			if (send_rc != NETDEV_TX_OK) {
++				spin_unlock_irqrestore(&nesnic->sq_lock, flags);
++				return NETDEV_TX_OK;
++			}
++		}
++	} else {
++		send_rc = nes_nic_send(skb, netdev);
++		if (send_rc != NETDEV_TX_OK) {
++			spin_unlock_irqrestore(&nesnic->sq_lock, flags);
++			return NETDEV_TX_OK;
++		}
 +	}
 +
-+free_qp_parm:
-+	kfree(qp_parm);
-+	/* this prevents subsequent calls to modify_qp() to cache qp_attr */
-+	my_sqp->mod_qp_parm = NULL;
++	barrier();
++
++	if (wqe_count)
++		nes_write32(nesdev->regs+NES_WQE_ALLOC,
++				(wqe_count << 24) | (1 << 23) | nesvnic->nic.qp_id);
++
++	netdev->trans_start = jiffies;
++	spin_unlock_irqrestore(&nesnic->sq_lock, flags);
++
++	return NETDEV_TX_OK;
 +}
 +
- int ehca_query_qp(struct ib_qp *qp,
- 		  struct ib_qp_attr *qp_attr,
- 		  int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
-@@ -1769,6 +1918,7 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
- 	struct ehca_shca *shca = container_of(dev, struct ehca_shca, ib_device);
- 	struct ehca_pd *my_pd = container_of(my_qp->ib_qp.pd, struct ehca_pd,
- 					     ib_pd);
-+	struct ehca_sport *sport = &shca->sport[my_qp->init_attr.port_num - 1];
- 	u32 cur_pid = current->tgid;
- 	u32 qp_num = my_qp->real_qp_num;
- 	int ret;
-@@ -1815,6 +1965,14 @@ static int internal_destroy_qp(struct ib_device *dev, struct ehca_qp *my_qp,
- 	port_num = my_qp->init_attr.port_num;
- 	qp_type  = my_qp->init_attr.qp_type;
- 
-+	if (qp_type == IB_QPT_SMI || qp_type == IB_QPT_GSI) {
-+		spin_lock_irqsave(&sport->mod_sqp_lock, flags);
-+		kfree(my_qp->mod_qp_parm);
-+		my_qp->mod_qp_parm = NULL;
-+		shca->sport[port_num - 1].ibqp_sqp[qp_type] = NULL;
-+		spin_unlock_irqrestore(&sport->mod_sqp_lock, flags);
-+	}
 +
- 	/* no support for IB_QPT_SMI yet */
- 	if (qp_type == IB_QPT_GSI) {
- 		struct ib_event event;
-diff --git a/drivers/infiniband/hw/ehca/ehca_reqs.c b/drivers/infiniband/hw/ehca/ehca_reqs.c
-index ea91360..3aacc8c 100644
---- a/drivers/infiniband/hw/ehca/ehca_reqs.c
-+++ b/drivers/infiniband/hw/ehca/ehca_reqs.c
-@@ -50,6 +50,9 @@
- #include "hcp_if.h"
- #include "hipz_fns.h"
- 
-+/* in RC traffic, insert an empty RDMA READ every this many packets */
-+#define ACK_CIRC_THRESHOLD 2000000
++/**
++ * nes_netdev_get_stats
++ */
++static struct net_device_stats *nes_netdev_get_stats(struct net_device *netdev)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	u64 u64temp;
++	u32 u32temp;
 +
- static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
- 				  struct ehca_wqe *wqe_p,
- 				  struct ib_recv_wr *recv_wr)
-@@ -81,7 +84,7 @@ static inline int ehca_write_rwqe(struct ipz_queue *ipz_rqueue,
- 	if (ehca_debug_level) {
- 		ehca_gen_dbg("RECEIVE WQE written into ipz_rqueue=%p",
- 			     ipz_rqueue);
--		ehca_dmp( wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
-+		ehca_dmp(wqe_p, 16*(6 + wqe_p->nr_of_data_seg), "recv wqe");
- 	}
- 
- 	return 0;
-@@ -135,7 +138,8 @@ static void trace_send_wr_ud(const struct ib_send_wr *send_wr)
- 
- static inline int ehca_write_swqe(struct ehca_qp *qp,
- 				  struct ehca_wqe *wqe_p,
--				  const struct ib_send_wr *send_wr)
-+				  const struct ib_send_wr *send_wr,
-+				  int hidden)
- {
- 	u32 idx;
- 	u64 dma_length;
-@@ -176,7 +180,9 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
- 
- 	wqe_p->wr_flag = 0;
- 
--	if (send_wr->send_flags & IB_SEND_SIGNALED)
-+	if ((send_wr->send_flags & IB_SEND_SIGNALED ||
-+	    qp->init_attr.sq_sig_type == IB_SIGNAL_ALL_WR)
-+	    && !hidden)
- 		wqe_p->wr_flag |= WQE_WRFLAG_REQ_SIGNAL_COM;
- 
- 	if (send_wr->opcode == IB_WR_SEND_WITH_IMM ||
-@@ -199,7 +205,7 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
- 
- 		wqe_p->destination_qp_number = send_wr->wr.ud.remote_qpn << 8;
- 		wqe_p->local_ee_context_qkey = remote_qkey;
--		if (!send_wr->wr.ud.ah) {
-+		if (unlikely(!send_wr->wr.ud.ah)) {
- 			ehca_gen_err("wr.ud.ah is NULL. qp=%p", qp);
- 			return -EINVAL;
- 		}
-@@ -255,6 +261,15 @@ static inline int ehca_write_swqe(struct ehca_qp *qp,
- 		} /* eof idx */
- 		wqe_p->u.nud.atomic_1st_op_dma_len = dma_length;
- 
-+		/* unsolicited ack circumvention */
-+		if (send_wr->opcode == IB_WR_RDMA_READ) {
-+			/* on RDMA read, switch on and reset counters */
-+			qp->message_count = qp->packet_count = 0;
-+			qp->unsol_ack_circ = 1;
-+		} else
-+			/* else estimate #packets */
-+			qp->packet_count += (dma_length >> qp->mtu_shift) + 1;
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_RX_DISCARD + (nesvnic->nic_index*0x200));
++	nesvnic->netstats.rx_dropped += u32temp;
++	nesvnic->endnode_nstat_rx_discard += u32temp;
 +
- 		break;
- 
- 	default:
-@@ -355,13 +370,49 @@ static inline void map_ib_wc_status(u32 cqe_status,
- 		*wc_status = IB_WC_SUCCESS;
- }
- 
-+static inline int post_one_send(struct ehca_qp *my_qp,
-+			 struct ib_send_wr *cur_send_wr,
-+			 struct ib_send_wr **bad_send_wr,
-+			 int hidden)
++	u64temp = (u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO + (nesvnic->nic_index*0x200));
++	u64temp += ((u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI + (nesvnic->nic_index*0x200))) << 32;
++
++	nesvnic->endnode_nstat_rx_octets += u64temp;
++	nesvnic->netstats.rx_bytes += u64temp;
++
++	u64temp = (u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO + (nesvnic->nic_index*0x200));
++	u64temp += ((u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI + (nesvnic->nic_index*0x200))) << 32;
++
++	nesvnic->endnode_nstat_rx_frames += u64temp;
++	nesvnic->netstats.rx_packets += u64temp;
++
++	u64temp = (u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO + (nesvnic->nic_index*0x200));
++	u64temp += ((u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI + (nesvnic->nic_index*0x200))) << 32;
++
++	nesvnic->endnode_nstat_tx_octets += u64temp;
++	nesvnic->netstats.tx_bytes += u64temp;
++
++	u64temp = (u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO + (nesvnic->nic_index*0x200));
++	u64temp += ((u64)nes_read_indexed(nesdev,
++			NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI + (nesvnic->nic_index*0x200))) << 32;
++
++	nesvnic->endnode_nstat_tx_frames += u64temp;
++	nesvnic->netstats.tx_packets += u64temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_SHORT_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->netstats.rx_dropped += u32temp;
++	nesvnic->nesdev->mac_rx_errors += u32temp;
++	nesvnic->nesdev->mac_rx_short_frames += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_OVERSIZED_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->netstats.rx_dropped += u32temp;
++	nesvnic->nesdev->mac_rx_errors += u32temp;
++	nesvnic->nesdev->mac_rx_oversized_frames += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_JABBER_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->netstats.rx_dropped += u32temp;
++	nesvnic->nesdev->mac_rx_errors += u32temp;
++	nesvnic->nesdev->mac_rx_jabber_frames += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_SYMBOL_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->netstats.rx_dropped += u32temp;
++	nesvnic->nesdev->mac_rx_errors += u32temp;
++	nesvnic->nesdev->mac_rx_symbol_err_frames += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_LENGTH_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->netstats.rx_length_errors += u32temp;
++	nesvnic->nesdev->mac_rx_errors += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_CRC_ERR_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->nesdev->mac_rx_errors += u32temp;
++	nesvnic->nesdev->mac_rx_crc_errors += u32temp;
++	nesvnic->netstats.rx_crc_errors += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_TX_ERRORS + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->nesdev->mac_tx_errors += u32temp;
++	nesvnic->netstats.tx_errors += u32temp;
++
++	return &nesvnic->netstats;
++}
++
++
++/**
++ * nes_netdev_tx_timeout
++ */
++static void nes_netdev_tx_timeout(struct net_device *netdev)
 +{
-+	struct ehca_wqe *wqe_p;
-+	int ret;
-+	u64 start_offset = my_qp->ipz_squeue.current_q_offset;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
 +
-+	/* get pointer next to free WQE */
-+	wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
-+	if (unlikely(!wqe_p)) {
-+		/* too many posted work requests: queue overflow */
-+		if (bad_send_wr)
-+			*bad_send_wr = cur_send_wr;
-+		ehca_err(my_qp->ib_qp.device, "Too many posted WQEs "
-+			 "qp_num=%x", my_qp->ib_qp.qp_num);
-+		return -ENOMEM;
++	if (netif_msg_timer(nesvnic))
++		nes_debug(NES_DBG_NIC_TX, "%s: tx timeout\n", netdev->name);
++}
++
++
++/**
++ * nes_netdev_set_mac_address
++ */
++static int nes_netdev_set_mac_address(struct net_device *netdev, void *p)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct sockaddr *mac_addr = p;
++	int i;
++	u32 macaddr_low;
++	u16 macaddr_high;
++
++	if (!is_valid_ether_addr(mac_addr->sa_data))
++		return -EADDRNOTAVAIL;
++
++	memcpy(netdev->dev_addr, mac_addr->sa_data, netdev->addr_len);
++	printk(PFX "%s: Address length = %d, Address = %02X%02X%02X%02X%02X%02X..\n",
++		   __FUNCTION__, netdev->addr_len,
++		   mac_addr->sa_data[0], mac_addr->sa_data[1],
++		   mac_addr->sa_data[2], mac_addr->sa_data[3],
++		   mac_addr->sa_data[4], mac_addr->sa_data[5]);
++	macaddr_high = ((u16)netdev->dev_addr[0]) << 8;
++	macaddr_high += (u16)netdev->dev_addr[1];
++	macaddr_low = ((u32)netdev->dev_addr[2]) << 24;
++	macaddr_low += ((u32)netdev->dev_addr[3]) << 16;
++	macaddr_low += ((u32)netdev->dev_addr[4]) << 8;
++	macaddr_low += (u32)netdev->dev_addr[5];
++
++	for (i = 0; i < NES_MAX_PORT_COUNT; i++) {
++		if (nesvnic->qp_nic_index[i] == 0xf) {
++			break;
++		}
++		nes_write_indexed(nesdev,
++				NES_IDX_PERFECT_FILTER_LOW + (nesvnic->qp_nic_index[i] * 8),
++				macaddr_low);
++		nes_write_indexed(nesdev,
++				NES_IDX_PERFECT_FILTER_HIGH + (nesvnic->qp_nic_index[i] * 8),
++				(u32)macaddr_high | NES_MAC_ADDR_VALID |
++				((((u32)nesvnic->nic_index) << 16)));
 +	}
-+	/* write a SEND WQE into the QUEUE */
-+	ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr, hidden);
-+	/*
-+	 * if something failed,
-+	 * reset the free entry pointer to the start value
-+	 */
-+	if (unlikely(ret)) {
-+		my_qp->ipz_squeue.current_q_offset = start_offset;
-+		if (bad_send_wr)
-+			*bad_send_wr = cur_send_wr;
-+		ehca_err(my_qp->ib_qp.device, "Could not write WQE "
-+			 "qp_num=%x", my_qp->ib_qp.qp_num);
++	return 0;
++}
++
++
++/**
++ * nes_netdev_set_multicast_list
++ */
++void nes_netdev_set_multicast_list(struct net_device *netdev)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct dev_mc_list *multicast_addr;
++	u32 nic_active_bit;
++	u32 nic_active;
++	u32 perfect_filter_register_address;
++	u32 macaddr_low;
++	u16 macaddr_high;
++	u8 mc_all_on = 0;
++	u8 mc_index;
++	int mc_nic_index = -1;
++
++	nic_active_bit = 1 << nesvnic->nic_index;
++
++	if (netdev->flags & IFF_PROMISC) {
++		nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
++		nic_active |= nic_active_bit;
++		nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
++		nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
++		nic_active |= nic_active_bit;
++		nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
++		mc_all_on = 1;
++	} else if ((netdev->flags & IFF_ALLMULTI) || (netdev->mc_count > NES_MULTICAST_PF_MAX) ||
++			   (nesvnic->nic_index > 3)) {
++		nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
++		nic_active |= nic_active_bit;
++		nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
++		nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
++		nic_active &= ~nic_active_bit;
++		nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
++		mc_all_on = 1;
++	} else {
++		nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL);
++		nic_active &= ~nic_active_bit;
++		nes_write_indexed(nesdev, NES_IDX_NIC_MULTICAST_ALL, nic_active);
++		nic_active = nes_read_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL);
++		nic_active &= ~nic_active_bit;
++		nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
++	}
++
++	nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
++			  netdev->mc_count, (netdev->flags & IFF_PROMISC)?1:0,
++			  (netdev->flags & IFF_ALLMULTI)?1:0);
++	if (!mc_all_on) {
++		multicast_addr = netdev->mc_list;
++		perfect_filter_register_address = NES_IDX_PERFECT_FILTER_LOW + 0x80;
++		perfect_filter_register_address += nesvnic->nic_index*0x40;
++		for (mc_index=0; mc_index < NES_MULTICAST_PF_MAX; mc_index++) {
++			while (multicast_addr && nesvnic->mcrq_mcast_filter && ((mc_nic_index = nesvnic->mcrq_mcast_filter(nesvnic, multicast_addr->dmi_addr)) == 0))
++				multicast_addr = multicast_addr->next;
++
++			if (mc_nic_index < 0)
++				mc_nic_index = nesvnic->nic_index;
++			if (multicast_addr) {
++				nes_debug(NES_DBG_NIC_RX, "Assigning MC Address = %02X%02X%02X%02X%02X%02X to register 0x%04X nic_idx=%d\n",
++						  multicast_addr->dmi_addr[0], multicast_addr->dmi_addr[1],
++						  multicast_addr->dmi_addr[2], multicast_addr->dmi_addr[3],
++						  multicast_addr->dmi_addr[4], multicast_addr->dmi_addr[5],
++						  perfect_filter_register_address+(mc_index * 8), mc_nic_index);
++				macaddr_high = ((u16)multicast_addr->dmi_addr[0]) << 8;
++				macaddr_high += (u16)multicast_addr->dmi_addr[1];
++				macaddr_low = ((u32)multicast_addr->dmi_addr[2]) << 24;
++				macaddr_low += ((u32)multicast_addr->dmi_addr[3]) << 16;
++				macaddr_low += ((u32)multicast_addr->dmi_addr[4]) << 8;
++				macaddr_low += (u32)multicast_addr->dmi_addr[5];
++				nes_write_indexed(nesdev,
++						perfect_filter_register_address+(mc_index * 8),
++						macaddr_low);
++				nes_write_indexed(nesdev,
++						perfect_filter_register_address+4+(mc_index * 8),
++						(u32)macaddr_high | NES_MAC_ADDR_VALID |
++						((((u32)(1<<mc_nic_index)) << 16)));
++				multicast_addr = multicast_addr->next;
++			} else {
++				nes_debug(NES_DBG_NIC_RX, "Clearing MC Address at register 0x%04X\n",
++						  perfect_filter_register_address+(mc_index * 8));
++				nes_write_indexed(nesdev,
++						perfect_filter_register_address+4+(mc_index * 8),
++						0);
++			}
++		}
++	}
++}
++
++
++/**
++ * nes_netdev_change_mtu
++ */
++static int nes_netdev_change_mtu(struct	net_device *netdev,	int	new_mtu)
++{
++	struct nes_vnic	*nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev =	nesvnic->nesdev;
++	int	ret	= 0;
++	u8 jumbomode=0;
++
++	if ((new_mtu < ETH_ZLEN) ||	(new_mtu > max_mtu))
 +		return -EINVAL;
++
++	netdev->mtu	= new_mtu;
++	nesvnic->max_frame_size	= new_mtu+ETH_HLEN;
++
++	if (netdev->mtu	> 1500)	{
++		jumbomode=1;
++	}
++	nes_nic_init_timer_defaults(nesdev,	jumbomode);
++
++	if (netif_running(netdev)) {
++		nes_netdev_stop(netdev);
++		nes_netdev_open(netdev);
++	}
++
++	return ret;
++}
++
++
++/**
++ * nes_netdev_exit - destroy network device
++ */
++void nes_netdev_exit(struct nes_vnic *nesvnic)
++{
++	struct net_device *netdev = nesvnic->netdev;
++	struct nes_ib_device *nesibdev = nesvnic->nesibdev;
++
++	nes_debug(NES_DBG_SHUTDOWN, "\n");
++
++	// destroy the ibdevice if RDMA enabled
++	if ((nesvnic->rdma_enabled)&&(nesvnic->of_device_registered)) {
++		nes_destroy_ofa_device( nesibdev );
++		nesvnic->of_device_registered = 0;
++		nesvnic->nesibdev = NULL;
 +	}
++	unregister_netdev(netdev);
++	nes_debug(NES_DBG_SHUTDOWN, "\n");
++}
++
++
++#define NES_ETHTOOL_STAT_COUNT 55
++static const char nes_ethtool_stringset[NES_ETHTOOL_STAT_COUNT][ETH_GSTRING_LEN] = {
++	"Link Change Interrupts",
++	"Linearized SKBs",
++	"T/GSO Requests",
++	"Pause Frames Sent",
++	"Pause Frames Received",
++	"Internal Routing Errors",
++	"SQ SW Dropped SKBs",
++	"SQ Locked",
++	"SQ Full",
++	"Segmented TSO Requests",
++	"Rx Symbol Errors",
++	"Rx Jabber Errors",
++	"Rx Oversized Frames",
++	"Rx Short Frames",
++	"Endnode Rx Discards",
++	"Endnode Rx Octets",
++	"Endnode Rx Frames",
++	"Endnode Tx Octets",
++	"Endnode Tx Frames",
++	"mh detected",
++	"mh pauses",
++	"Retransmission Count",
++	"CM Connects",
++	"CM Accepts",
++	"Disconnects",
++	"Connected Events",
++	"Connect Requests",
++	"CM Rejects",
++	"ModifyQP Timeouts",
++	"CreateQPs",
++	"SW DestroyQPs",
++	"DestroyQPs",
++	"CM Closes",
++	"CM Packets Sent",
++	"CM Packets Bounced",
++	"CM Packets Created",
++	"CM Packets Rcvd",
++	"CM Packets Dropped",
++	"CM Packets Retrans",
++	"CM Listens Created",
++	"CM Listens Destroyed",
++	"CM Backlog Drops",
++	"CM Loopbacks",
++	"CM Nodes Created",
++	"CM Nodes Destroyed",
++	"CM Accel Drops",
++	"CM Resets Received",
++	"Timer Inits",
++	"CQ Depth 1",
++	"CQ Depth 4",
++	"CQ Depth 16",
++	"CQ Depth 24",
++	"CQ Depth 32",
++	"CQ Depth 128",
++	"CQ Depth 256",
++};
++
++
++/**
++ * nes_netdev_get_rx_csum
++ */
++static u32 nes_netdev_get_rx_csum (struct net_device *netdev)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++
++	if (nesvnic->rx_checksum_disabled)
++		return 0;
++	else
++		return 1;
++}
++
++
++/**
++ * nes_netdev_set_rc_csum
++ */
++static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
 +
++	if (enable)
++		nesvnic->rx_checksum_disabled = 0;
++	else
++		nesvnic->rx_checksum_disabled = 1;
 +	return 0;
 +}
 +
- int ehca_post_send(struct ib_qp *qp,
- 		   struct ib_send_wr *send_wr,
- 		   struct ib_send_wr **bad_send_wr)
- {
- 	struct ehca_qp *my_qp = container_of(qp, struct ehca_qp, ib_qp);
- 	struct ib_send_wr *cur_send_wr;
--	struct ehca_wqe *wqe_p;
- 	int wqe_cnt = 0;
- 	int ret = 0;
- 	unsigned long flags;
-@@ -369,37 +420,33 @@ int ehca_post_send(struct ib_qp *qp,
- 	/* LOCK the QUEUE */
- 	spin_lock_irqsave(&my_qp->spinlock_s, flags);
- 
-+	/* Send an empty extra RDMA read if:
-+	 *  1) there has been an RDMA read on this connection before
-+	 *  2) no RDMA read occurred for ACK_CIRC_THRESHOLD link packets
-+	 *  3) we can be sure that any previous extra RDMA read has been
-+	 *     processed so we don't overflow the SQ
-+	 */
-+	if (unlikely(my_qp->unsol_ack_circ &&
-+		     my_qp->packet_count > ACK_CIRC_THRESHOLD &&
-+		     my_qp->message_count > my_qp->init_attr.cap.max_send_wr)) {
-+		/* insert an empty RDMA READ to fix up the remote QP state */
-+		struct ib_send_wr circ_wr;
-+		memset(&circ_wr, 0, sizeof(circ_wr));
-+		circ_wr.opcode = IB_WR_RDMA_READ;
-+		post_one_send(my_qp, &circ_wr, NULL, 1); /* ignore retcode */
-+		wqe_cnt++;
-+		ehca_dbg(qp->device, "posted circ wr  qp_num=%x", qp->qp_num);
-+		my_qp->message_count = my_qp->packet_count = 0;
++
++/**
++ * nes_netdev_get_stats_count
++ */
++static int nes_netdev_get_stats_count(struct net_device *netdev)
++{
++	return NES_ETHTOOL_STAT_COUNT;
++}
++
++
++/**
++ * nes_netdev_get_strings
++ */
++static void nes_netdev_get_strings(struct net_device *netdev, u32 stringset,
++		u8 *ethtool_strings)
++{
++	if (stringset == ETH_SS_STATS)
++		memcpy(ethtool_strings,
++				&nes_ethtool_stringset,
++				sizeof(nes_ethtool_stringset));
++}
++
++
++/**
++ * nes_netdev_get_ethtool_stats
++ */
++static void nes_netdev_get_ethtool_stats(struct net_device *netdev,
++		struct ethtool_stats *target_ethtool_stats, u64 *target_stat_values)
++{
++	u64 u64temp;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	u32 nic_count;
++	u32 u32temp;
++
++	target_ethtool_stats->n_stats = NES_ETHTOOL_STAT_COUNT;
++	target_stat_values[0] = nesvnic->nesdev->link_status_interrupts;
++	target_stat_values[1] = nesvnic->linearized_skbs;
++	target_stat_values[2] = nesvnic->tso_requests;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_TX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->nesdev->mac_pause_frames_sent += u32temp;
++	target_stat_values[3] = nesvnic->nesdev->mac_pause_frames_sent;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_MAC_RX_PAUSE_FRAMES + (nesvnic->nesdev->mac_index*0x200));
++	nesvnic->nesdev->mac_pause_frames_received += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_PORT_RX_DISCARDS + (nesvnic->nesdev->mac_index*0x40));
++	nesvnic->nesdev->port_rx_discards += u32temp;
++	nesvnic->netstats.rx_dropped += u32temp;
++
++	u32temp = nes_read_indexed(nesdev,
++			NES_IDX_PORT_TX_DISCARDS + (nesvnic->nesdev->mac_index*0x40));
++	nesvnic->nesdev->port_tx_discards += u32temp;
++	nesvnic->netstats.tx_dropped += u32temp;
++
++	for (nic_count = 0; nic_count < NES_MAX_PORT_COUNT; nic_count++) {
++		if (nesvnic->qp_nic_index[nic_count] == 0xf)
++			break;
++
++		u32temp = nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_RX_DISCARD +
++				(nesvnic->qp_nic_index[nic_count]*0x200));
++		nesvnic->netstats.rx_dropped += u32temp;
++		nesvnic->endnode_nstat_rx_discard += u32temp;
++
++		u64temp = (u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_LO +
++				(nesvnic->qp_nic_index[nic_count]*0x200));
++		u64temp += ((u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_RX_OCTETS_HI +
++				(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
++
++		nesvnic->endnode_nstat_rx_octets += u64temp;
++		nesvnic->netstats.rx_bytes += u64temp;
++
++		u64temp = (u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_LO +
++				(nesvnic->qp_nic_index[nic_count]*0x200));
++		u64temp += ((u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_RX_FRAMES_HI +
++				(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
++
++		nesvnic->endnode_nstat_rx_frames += u64temp;
++		nesvnic->netstats.rx_packets += u64temp;
++
++		u64temp = (u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_LO +
++				(nesvnic->qp_nic_index[nic_count]*0x200));
++		u64temp += ((u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI +
++				(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
++
++		nesvnic->endnode_nstat_tx_octets += u64temp;
++		nesvnic->netstats.tx_bytes += u64temp;
++
++		u64temp = (u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO +
++				(nesvnic->qp_nic_index[nic_count]*0x200));
++		u64temp += ((u64)nes_read_indexed(nesdev,
++				NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI +
++				(nesvnic->qp_nic_index[nic_count]*0x200))) << 32;
++
++		nesvnic->endnode_nstat_tx_frames += u64temp;
++		nesvnic->netstats.tx_packets += u64temp;
++
++		u32temp = nes_read_indexed(nesdev,
++				NES_IDX_IPV4_TCP_REXMITS + (nesvnic->qp_nic_index[nic_count]*0x200));
++		nesvnic->endnode_ipv4_tcp_retransmits += u32temp;
 +	}
 +
- 	/* loop processes list of send reqs */
- 	for (cur_send_wr = send_wr; cur_send_wr != NULL;
- 	     cur_send_wr = cur_send_wr->next) {
--		u64 start_offset = my_qp->ipz_squeue.current_q_offset;
--		/* get pointer next to free WQE */
--		wqe_p = ipz_qeit_get_inc(&my_qp->ipz_squeue);
--		if (unlikely(!wqe_p)) {
--			/* too many posted work requests: queue overflow */
--			if (bad_send_wr)
--				*bad_send_wr = cur_send_wr;
--			if (wqe_cnt == 0) {
--				ret = -ENOMEM;
--				ehca_err(qp->device, "Too many posted WQEs "
--					 "qp_num=%x", qp->qp_num);
--			}
--			goto post_send_exit0;
--		}
--		/* write a SEND WQE into the QUEUE */
--		ret = ehca_write_swqe(my_qp, wqe_p, cur_send_wr);
--		/*
--		 * if something failed,
--		 * reset the free entry pointer to the start value
--		 */
-+		ret = post_one_send(my_qp, cur_send_wr, bad_send_wr, 0);
- 		if (unlikely(ret)) {
--			my_qp->ipz_squeue.current_q_offset = start_offset;
--			*bad_send_wr = cur_send_wr;
--			if (wqe_cnt == 0) {
--				ret = -EINVAL;
--				ehca_err(qp->device, "Could not write WQE "
--					 "qp_num=%x", qp->qp_num);
--			}
-+			/* if one or more WQEs were successful, don't fail */
-+			if (wqe_cnt)
-+				ret = 0;
- 			goto post_send_exit0;
- 		}
- 		wqe_cnt++;
-@@ -410,6 +457,7 @@ int ehca_post_send(struct ib_qp *qp,
- post_send_exit0:
- 	iosync(); /* serialize GAL register access */
- 	hipz_update_sqa(my_qp, wqe_cnt);
-+	my_qp->message_count += wqe_cnt;
- 	spin_unlock_irqrestore(&my_qp->spinlock_s, flags);
- 	return ret;
- }
-diff --git a/drivers/infiniband/hw/ehca/ehca_sqp.c b/drivers/infiniband/hw/ehca/ehca_sqp.c
-index f0792e5..79e72b2 100644
---- a/drivers/infiniband/hw/ehca/ehca_sqp.c
-+++ b/drivers/infiniband/hw/ehca/ehca_sqp.c
-@@ -40,11 +40,8 @@
-  */
- 
- 
--#include <linux/module.h>
--#include <linux/err.h>
- #include "ehca_classes.h"
- #include "ehca_tools.h"
--#include "ehca_qes.h"
- #include "ehca_iverbs.h"
- #include "hcp_if.h"
- 
-@@ -93,6 +90,9 @@ u64 ehca_define_sqp(struct ehca_shca *shca,
- 		return H_PARAMETER;
- 	}
- 
-+	if (ehca_nr_ports < 0) /* autodetect mode */
-+		return H_SUCCESS;
++	target_stat_values[4] = nesvnic->nesdev->mac_pause_frames_received;
++	target_stat_values[5] = nesdev->nesadapter->nic_rx_eth_route_err;
++	target_stat_values[6] = nesvnic->tx_sw_dropped;
++	target_stat_values[7] = nesvnic->sq_locked;
++	target_stat_values[8] = nesvnic->sq_full;
++	target_stat_values[9] = nesvnic->segmented_tso_requests;
++	target_stat_values[10] = nesvnic->nesdev->mac_rx_symbol_err_frames;
++	target_stat_values[11] = nesvnic->nesdev->mac_rx_jabber_frames;
++	target_stat_values[12] = nesvnic->nesdev->mac_rx_oversized_frames;
++	target_stat_values[13] = nesvnic->nesdev->mac_rx_short_frames;
++	target_stat_values[14] = nesvnic->endnode_nstat_rx_discard;
++	target_stat_values[15] = nesvnic->endnode_nstat_rx_octets;
++	target_stat_values[16] = nesvnic->endnode_nstat_rx_frames;
++	target_stat_values[17] = nesvnic->endnode_nstat_tx_octets;
++	target_stat_values[18] = nesvnic->endnode_nstat_tx_frames;
++	target_stat_values[19] = mh_detected;
++	target_stat_values[20] = mh_pauses_sent;
++	target_stat_values[21] = nesvnic->endnode_ipv4_tcp_retransmits;
++	target_stat_values[22] = atomic_read(&cm_connects);
++	target_stat_values[23] = atomic_read(&cm_accepts);
++	target_stat_values[24] = atomic_read(&cm_disconnects);
++	target_stat_values[25] = atomic_read(&cm_connecteds);
++	target_stat_values[26] = atomic_read(&cm_connect_reqs);
++	target_stat_values[27] = atomic_read(&cm_rejects);
++	target_stat_values[28] = atomic_read(&mod_qp_timouts);
++	target_stat_values[29] = atomic_read(&qps_created);
++	target_stat_values[30] = atomic_read(&sw_qps_destroyed);
++	target_stat_values[31] = atomic_read(&qps_destroyed);
++	target_stat_values[32] = atomic_read(&cm_closes);
++	target_stat_values[33] = cm_packets_sent;
++	target_stat_values[34] = cm_packets_bounced;
++	target_stat_values[35] = cm_packets_created;
++	target_stat_values[36] = cm_packets_received;
++	target_stat_values[37] = cm_packets_dropped;
++	target_stat_values[38] = cm_packets_retrans;
++	target_stat_values[39] = cm_listens_created;
++	target_stat_values[40] = cm_listens_destroyed;
++	target_stat_values[41] = cm_backlog_drops;
++	target_stat_values[42] = atomic_read(&cm_loopbacks);
++	target_stat_values[43] = atomic_read(&cm_nodes_created);
++	target_stat_values[44] = atomic_read(&cm_nodes_destroyed);
++	target_stat_values[45] = atomic_read(&cm_accel_dropped_pkts);
++	target_stat_values[46] = atomic_read(&cm_resets_recvd);
++	target_stat_values[47] = int_mod_timer_init;
++	target_stat_values[48] = int_mod_cq_depth_1;
++	target_stat_values[49] = int_mod_cq_depth_4;
++	target_stat_values[50] = int_mod_cq_depth_16;
++	target_stat_values[51] = int_mod_cq_depth_24;
++	target_stat_values[52] = int_mod_cq_depth_32;
++	target_stat_values[53] = int_mod_cq_depth_128;
++	target_stat_values[54] = int_mod_cq_depth_256;
 +
- 	for (counter = 0;
- 	     shca->sport[port - 1].port_state != IB_PORT_ACTIVE &&
- 		     counter < ehca_port_act_time;
-diff --git a/drivers/infiniband/hw/ipath/ipath_common.h b/drivers/infiniband/hw/ipath/ipath_common.h
-index 851df8a..4146210 100644
---- a/drivers/infiniband/hw/ipath/ipath_common.h
-+++ b/drivers/infiniband/hw/ipath/ipath_common.h
-@@ -82,6 +82,16 @@
- #define IPATH_IB_LINK_EXTERNAL	7 /* normal, disable local loopback */
- 
- /*
-+ * These 3 values (SDR and DDR may be ORed for auto-speed
-+ * negotiation) are used for the 3rd argument to path_f_set_ib_cfg
-+ * with cmd IPATH_IB_CFG_SPD_ENB, by direct calls or via sysfs.  They
-+ * are also the the possible values for ipath_link_speed_enabled and active
-+ * The values were chosen to match values used within the IB spec.
++}
++
++
++/**
++ * nes_netdev_get_drvinfo
 + */
-+#define IPATH_IB_SDR 1
-+#define IPATH_IB_DDR 2
++static void nes_netdev_get_drvinfo(struct net_device *netdev,
++		struct ethtool_drvinfo *drvinfo)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
 +
-+/*
-  * stats maintained by the driver.  For now, at least, this is global
-  * to all minor devices.
-  */
-@@ -433,8 +443,9 @@ struct ipath_user_info {
- #define IPATH_CMD_UNUSED_2	26
- #define IPATH_CMD_PIOAVAILUPD	27	/* force an update of PIOAvail reg */
- #define IPATH_CMD_POLL_TYPE	28	/* set the kind of polling we want */
-+#define IPATH_CMD_ARMLAUNCH_CTRL	29 /* armlaunch detection control */
- 
--#define IPATH_CMD_MAX		28
-+#define IPATH_CMD_MAX		29
- 
- /*
-  * Poll types
-@@ -477,6 +488,8 @@ struct ipath_cmd {
- 		__u64 port_info;
- 		/* enable/disable receipt of packets */
- 		__u32 recv_ctrl;
-+		/* enable/disable armlaunch errors (non-zero to enable) */
-+		__u32 armlaunch_ctrl;
- 		/* partition key to set */
- 		__u16 part_key;
- 		/* user address of __u32 bitmask of active slaves */
-@@ -579,7 +592,7 @@ struct ipath_flash {
- struct infinipath_counters {
- 	__u64 LBIntCnt;
- 	__u64 LBFlowStallCnt;
--	__u64 Reserved1;
-+	__u64 TxSDmaDescCnt;	/* was Reserved1 */
- 	__u64 TxUnsupVLErrCnt;
- 	__u64 TxDataPktCnt;
- 	__u64 TxFlowPktCnt;
-@@ -615,12 +628,26 @@ struct infinipath_counters {
- 	__u64 RxP6HdrEgrOvflCnt;
- 	__u64 RxP7HdrEgrOvflCnt;
- 	__u64 RxP8HdrEgrOvflCnt;
--	__u64 Reserved6;
--	__u64 Reserved7;
-+	__u64 RxP9HdrEgrOvflCnt;	/* was Reserved6 */
-+	__u64 RxP10HdrEgrOvflCnt;	/* was Reserved7 */
-+	__u64 RxP11HdrEgrOvflCnt;	/* new for IBA7220 */
-+	__u64 RxP12HdrEgrOvflCnt;	/* new for IBA7220 */
-+	__u64 RxP13HdrEgrOvflCnt;	/* new for IBA7220 */
-+	__u64 RxP14HdrEgrOvflCnt;	/* new for IBA7220 */
-+	__u64 RxP15HdrEgrOvflCnt;	/* new for IBA7220 */
-+	__u64 RxP16HdrEgrOvflCnt;	/* new for IBA7220 */
- 	__u64 IBStatusChangeCnt;
- 	__u64 IBLinkErrRecoveryCnt;
- 	__u64 IBLinkDownedCnt;
- 	__u64 IBSymbolErrCnt;
-+	/* The following are new for IBA7220 */
-+	__u64 RxVL15DroppedPktCnt;
-+	__u64 RxOtherLocalPhyErrCnt;
-+	__u64 PcieRetryBufDiagQwordCnt;
-+	__u64 ExcessBufferOvflCnt;
-+	__u64 LocalLinkIntegrityErrCnt;
-+	__u64 RxVlErrCnt;
-+	__u64 RxDlidFltrCnt;
- };
- 
- /*
-diff --git a/drivers/infiniband/hw/ipath/ipath_cq.c b/drivers/infiniband/hw/ipath/ipath_cq.c
-index d1380c7..a03bd28 100644
---- a/drivers/infiniband/hw/ipath/ipath_cq.c
-+++ b/drivers/infiniband/hw/ipath/ipath_cq.c
-@@ -421,7 +421,7 @@ int ipath_resize_cq(struct ib_cq *ibcq, int cqe, struct ib_udata *udata)
- 	else
- 		n = head - tail;
- 	if (unlikely((u32)cqe < n)) {
--		ret = -EOVERFLOW;
-+		ret = -EINVAL;
- 		goto bail_unlock;
- 	}
- 	for (n = 0; tail != head; n++) {
-diff --git a/drivers/infiniband/hw/ipath/ipath_debug.h b/drivers/infiniband/hw/ipath/ipath_debug.h
-index 19c56e6..d6f6953 100644
---- a/drivers/infiniband/hw/ipath/ipath_debug.h
-+++ b/drivers/infiniband/hw/ipath/ipath_debug.h
-@@ -55,7 +55,7 @@
- #define __IPATH_PKTDBG      0x80	/* print packet data */
- /* print process startup (init)/exit messages */
- #define __IPATH_PROCDBG     0x100
--/* print mmap/nopage stuff, not using VDBG any more */
-+/* print mmap/fault stuff, not using VDBG any more */
- #define __IPATH_MMDBG       0x200
- #define __IPATH_ERRPKTDBG   0x400
- #define __IPATH_USER_SEND   0x1000	/* use user mode send */
-@@ -81,7 +81,7 @@
- #define __IPATH_VERBDBG   0x0	/* very verbose debug */
- #define __IPATH_PKTDBG    0x0	/* print packet data */
- #define __IPATH_PROCDBG   0x0	/* process startup (init)/exit messages */
--/* print mmap/nopage stuff, not using VDBG any more */
-+/* print mmap/fault stuff, not using VDBG any more */
- #define __IPATH_MMDBG     0x0
- #define __IPATH_EPKTDBG   0x0	/* print ethernet packet data */
- #define __IPATH_IPATHDBG  0x0	/* Ethernet (IPATH) table dump on */
-diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
-index 1f152de..d5ff6ca 100644
---- a/drivers/infiniband/hw/ipath/ipath_driver.c
-+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
-@@ -121,6 +121,9 @@ static struct pci_driver ipath_driver = {
- 	.probe = ipath_init_one,
- 	.remove = __devexit_p(ipath_remove_one),
- 	.id_table = ipath_pci_tbl,
-+	.driver = {
-+		.groups = ipath_driver_attr_groups,
-+	},
- };
- 
- static void ipath_check_status(struct work_struct *work)
-@@ -331,6 +334,8 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
- 		udelay(1);
- 	}
- 
-+	ipath_disable_armlaunch(dd);
++	strcpy(drvinfo->driver, DRV_NAME);
++	strcpy(drvinfo->bus_info, pci_name(nesvnic->nesdev->pcidev));
++	strcpy(drvinfo->fw_version, "TBD");
++	strcpy(drvinfo->version, DRV_VERSION);
++	drvinfo->n_stats = nes_netdev_get_stats_count(netdev);
++	drvinfo->testinfo_len = 0;
++	drvinfo->eedump_len = 0;
++	drvinfo->regdump_len = 0;
++}
 +
- 	writeq(0, piobuf); /* length 0, no dwords actually sent */
- 	ipath_flush_wc();
- 
-@@ -362,6 +367,7 @@ static void ipath_verify_pioperf(struct ipath_devdata *dd)
- done:
- 	/* disarm piobuf, so it's available again */
- 	ipath_disarm_piobufs(dd, pbnum, 1);
-+	ipath_enable_armlaunch(dd);
- }
- 
- static int __devinit ipath_init_one(struct pci_dev *pdev,
-@@ -800,31 +806,37 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
- 			  unsigned cnt)
- {
- 	unsigned i, last = first + cnt;
--	u64 sendctrl, sendorig;
++
++/**
++ * nes_netdev_set_coalesce
++ */
++static int nes_netdev_set_coalesce(struct net_device *netdev,
++		struct ethtool_coalesce	*et_coalesce)
++{
++	struct nes_vnic	*nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev =	nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
 +	unsigned long flags;
- 
- 	ipath_cdbg(PKT, "disarm %u PIObufs first=%u\n", cnt, first);
--	sendorig = dd->ipath_sendctrl;
- 	for (i = first; i < last; i++) {
--		sendctrl = sendorig  | INFINIPATH_S_DISARM |
--			(i << INFINIPATH_S_DISARMPIOBUF_SHIFT);
-+		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+		/*
-+		 * The disarm-related bits are write-only, so it
-+		 * is ok to OR them in with our copy of sendctrl
-+		 * while we hold the lock.
-+		 */
- 		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
--				 sendctrl);
-+			dd->ipath_sendctrl | INFINIPATH_S_DISARM |
-+			(i << INFINIPATH_S_DISARMPIOBUF_SHIFT));
-+		/* can't disarm bufs back-to-back per iba7220 spec */
-+		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- 	}
- 
- 	/*
--	 * Write it again with current value, in case ipath_sendctrl changed
--	 * while we were looping; no critical bits that would require
--	 * locking.
--	 *
--	 * disable PIOAVAILUPD, then re-enable, reading scratch in
-+	 * Disable PIOAVAILUPD, then re-enable, reading scratch in
- 	 * between.  This seems to avoid a chip timing race that causes
--	 * pioavail updates to memory to stop.
-+	 * pioavail updates to memory to stop.  We xor as we don't
-+	 * know the state of the bit when we're called.
- 	 */
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
--			 sendorig & ~INFINIPATH_S_PIOBUFAVAILUPD);
--	sendorig = ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+		dd->ipath_sendctrl ^ INFINIPATH_S_PIOBUFAVAILUPD);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- 			 dd->ipath_sendctrl);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- }
- 
- /**
-@@ -1000,12 +1012,10 @@ static void get_rhf_errstring(u32 err, char *msg, size_t len)
-  * ipath_get_egrbuf - get an eager buffer
-  * @dd: the infinipath device
-  * @bufnum: the eager buffer to get
-- * @err: unused
-  *
-  * must only be called if ipath_pd[port] is known to be allocated
-  */
--static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum,
--				     int err)
-+static inline void *ipath_get_egrbuf(struct ipath_devdata *dd, u32 bufnum)
- {
- 	return dd->ipath_port0_skbinfo ?
- 		(void *) dd->ipath_port0_skbinfo[bufnum].skb->data : NULL;
-@@ -1097,13 +1107,14 @@ static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
- 
- /*
-  * ipath_kreceive - receive a packet
-- * @dd: the infinipath device
-+ * @pd: the infinipath port
-  *
-  * called from interrupt handler for errors or receive interrupt
-  */
--void ipath_kreceive(struct ipath_devdata *dd)
-+void ipath_kreceive(struct ipath_portdata *pd)
- {
- 	u64 *rc;
-+	struct ipath_devdata *dd = pd->port_dd;
- 	void *ebuf;
- 	const u32 rsize = dd->ipath_rcvhdrentsize;	/* words */
- 	const u32 maxcnt = dd->ipath_rcvhdrcnt * rsize;	/* words */
-@@ -1118,8 +1129,8 @@ void ipath_kreceive(struct ipath_devdata *dd)
- 		goto bail;
- 	}
- 
--	l = dd->ipath_port0head;
--	hdrqtail = (u32) le64_to_cpu(*dd->ipath_hdrqtailptr);
-+	l = pd->port_head;
-+	hdrqtail = ipath_get_rcvhdrtail(pd);
- 	if (l == hdrqtail)
- 		goto bail;
- 
-@@ -1128,7 +1139,7 @@ reloop:
- 		u32 qp;
- 		u8 *bthbytes;
- 
--		rc = (u64 *) (dd->ipath_pd[0]->port_rcvhdrq + (l << 2));
-+		rc = (u64 *) (pd->port_rcvhdrq + (l << 2));
- 		hdr = (struct ipath_message_header *)&rc[1];
- 		/*
- 		 * could make a network order version of IPATH_KD_QP, and
-@@ -1153,7 +1164,7 @@ reloop:
- 			etail = ipath_hdrget_index((__le32 *) rc);
- 			if (tlen > sizeof(*hdr) ||
- 			    etype == RCVHQ_RCV_TYPE_NON_KD)
--				ebuf = ipath_get_egrbuf(dd, etail, 0);
-+				ebuf = ipath_get_egrbuf(dd, etail);
- 		}
- 
- 		/*
-@@ -1188,7 +1199,7 @@ reloop:
- 				  be32_to_cpu(hdr->bth[0]) & 0xff);
- 		else {
- 			/*
--			 * error packet, type of error	unknown.
-+			 * error packet, type of error unknown.
- 			 * Probably type 3, but we don't know, so don't
- 			 * even try to print the opcode, etc.
- 			 */
-@@ -1238,7 +1249,7 @@ reloop:
- 		 * earlier packets, we "almost" guarantee we have covered
- 		 * that case.
- 		 */
--		u32 hqtail = (u32)le64_to_cpu(*dd->ipath_hdrqtailptr);
-+		u32 hqtail = ipath_get_rcvhdrtail(pd);
- 		if (hqtail != hdrqtail) {
- 			hdrqtail = hqtail;
- 			reloop = 1; /* loop 1 extra time at most */
-@@ -1248,7 +1259,7 @@ reloop:
- 
- 	pkttot += i;
- 
--	dd->ipath_port0head = l;
-+	pd->port_head = l;
- 
- 	if (pkttot > ipath_stats.sps_maxpkts_call)
- 		ipath_stats.sps_maxpkts_call = pkttot;
-@@ -1332,14 +1343,9 @@ static void ipath_update_pio_bufs(struct ipath_devdata *dd)
- 		/*
- 		 * Chip Errata: bug 6641; even and odd qwords>3 are swapped
- 		 */
--		if (i > 3) {
--			if (i & 1)
--				piov = le64_to_cpu(
--					dd->ipath_pioavailregs_dma[i - 1]);
--			else
--				piov = le64_to_cpu(
--					dd->ipath_pioavailregs_dma[i + 1]);
--		} else
-+		if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
-+			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i ^ 1]);
-+		else
- 			piov = le64_to_cpu(dd->ipath_pioavailregs_dma[i]);
- 		pchg = _IPATH_ALL_CHECKBITS &
- 			~(dd->ipath_pioavailshadow[i] ^ piov);
-@@ -1598,7 +1604,8 @@ int ipath_create_rcvhdrq(struct ipath_devdata *dd,
- 
- 	/* clear for security and sanity on each use */
- 	memset(pd->port_rcvhdrq, 0, pd->port_rcvhdrq_size);
--	memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
-+	if (pd->port_rcvhdrtail_kvaddr)
-+		memset(pd->port_rcvhdrtail_kvaddr, 0, PAGE_SIZE);
- 
- 	/*
- 	 * tell chip each time we init it, even if we are re-using previous
-@@ -1614,77 +1621,6 @@ bail:
- 	return ret;
- }
- 
--int ipath_waitfor_complete(struct ipath_devdata *dd, ipath_kreg reg_id,
--			   u64 bits_to_wait_for, u64 * valp)
--{
--	unsigned long timeout;
--	u64 lastval, val;
--	int ret;
--
--	lastval = ipath_read_kreg64(dd, reg_id);
--	/* wait a ridiculously long time */
--	timeout = jiffies + msecs_to_jiffies(5);
--	do {
--		val = ipath_read_kreg64(dd, reg_id);
--		/* set so they have something, even on failures. */
--		*valp = val;
--		if ((val & bits_to_wait_for) == bits_to_wait_for) {
--			ret = 0;
--			break;
--		}
--		if (val != lastval)
--			ipath_cdbg(VERBOSE, "Changed from %llx to %llx, "
--				   "waiting for %llx bits\n",
--				   (unsigned long long) lastval,
--				   (unsigned long long) val,
--				   (unsigned long long) bits_to_wait_for);
--		cond_resched();
--		if (time_after(jiffies, timeout)) {
--			ipath_dbg("Didn't get bits %llx in register 0x%x, "
--				  "got %llx\n",
--				  (unsigned long long) bits_to_wait_for,
--				  reg_id, (unsigned long long) *valp);
--			ret = -ENODEV;
--			break;
--		}
--	} while (1);
--
--	return ret;
--}
--
--/**
-- * ipath_waitfor_mdio_cmdready - wait for last command to complete
-- * @dd: the infinipath device
-- *
-- * Like ipath_waitfor_complete(), but we wait for the CMDVALID bit to go
-- * away indicating the last command has completed.  It doesn't return data
-- */
--int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
--{
--	unsigned long timeout;
--	u64 val;
--	int ret;
--
--	/* wait a ridiculously long time */
--	timeout = jiffies + msecs_to_jiffies(5);
--	do {
--		val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_mdio);
--		if (!(val & IPATH_MDIO_CMDVALID)) {
--			ret = 0;
--			break;
--		}
--		cond_resched();
--		if (time_after(jiffies, timeout)) {
--			ipath_dbg("CMDVALID stuck in mdio reg? (%llx)\n",
--				  (unsigned long long) val);
--			ret = -ENODEV;
--			break;
--		}
--	} while (1);
--
--	return ret;
--}
--
- 
- /*
-  * Flush all sends that might be in the ready to send state, as well as any
-@@ -2053,6 +1989,8 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val)
-  */
- void ipath_shutdown_device(struct ipath_devdata *dd)
- {
++
++	spin_lock_irqsave(&nesadapter->periodic_timer_lock,	flags);
++	if (et_coalesce->rx_max_coalesced_frames_low) {
++		shared_timer->threshold_low	 = et_coalesce->rx_max_coalesced_frames_low;
++	}
++	if (et_coalesce->rx_max_coalesced_frames_irq) {
++		shared_timer->threshold_target = et_coalesce->rx_max_coalesced_frames_irq;
++	}
++	if (et_coalesce->rx_max_coalesced_frames_high) {
++		shared_timer->threshold_high = et_coalesce->rx_max_coalesced_frames_high;
++	}
++	if (et_coalesce->rx_coalesce_usecs_low) {
++		shared_timer->timer_in_use_min = et_coalesce->rx_coalesce_usecs_low;
++	}
++	if (et_coalesce->rx_coalesce_usecs_high) {
++		shared_timer->timer_in_use_max = et_coalesce->rx_coalesce_usecs_high;
++	}
++	spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
++
++	/* using this to drive total interrupt moderation */
++	nesadapter->et_rx_coalesce_usecs_irq = et_coalesce->rx_coalesce_usecs_irq;
++	if (et_coalesce->use_adaptive_rx_coalesce) {
++		nesadapter->et_use_adaptive_rx_coalesce	= 1;
++		nesadapter->timer_int_limit	= NES_TIMER_INT_LIMIT_DYNAMIC;
++		nesadapter->et_rx_coalesce_usecs_irq = 0;
++		if (et_coalesce->pkt_rate_low) {
++			nesadapter->et_pkt_rate_low	= et_coalesce->pkt_rate_low;
++		}
++	} else {
++		nesadapter->et_use_adaptive_rx_coalesce	= 0;
++		nesadapter->timer_int_limit	= NES_TIMER_INT_LIMIT;
++		if (nesadapter->et_rx_coalesce_usecs_irq) {
++			nes_write32(nesdev->regs+NES_PERIODIC_CONTROL,
++					0x80000000 | ((u32)(nesadapter->et_rx_coalesce_usecs_irq*8)));
++		}
++	}
++	return 0;
++}
++
++
++/**
++ * nes_netdev_get_coalesce
++ */
++static int nes_netdev_get_coalesce(struct net_device *netdev,
++		struct ethtool_coalesce	*et_coalesce)
++{
++	struct nes_vnic	*nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev =	nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct ethtool_coalesce	temp_et_coalesce;
++	struct nes_hw_tune_timer *shared_timer = &nesadapter->tune_timer;
 +	unsigned long flags;
 +
- 	ipath_dbg("Shutting down the device\n");
- 
- 	dd->ipath_flags |= IPATH_LINKUNK;
-@@ -2073,9 +2011,13 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
- 	 * gracefully stop all sends allowing any in progress to trickle out
- 	 * first.
- 	 */
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0ULL);
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+	dd->ipath_sendctrl = 0;
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
- 	/* flush it */
- 	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
++	memset(&temp_et_coalesce, 0, sizeof(temp_et_coalesce));
++	temp_et_coalesce.rx_coalesce_usecs_irq = nesadapter->et_rx_coalesce_usecs_irq;
++	temp_et_coalesce.use_adaptive_rx_coalesce =	nesadapter->et_use_adaptive_rx_coalesce;
++	temp_et_coalesce.rate_sample_interval =	nesadapter->et_rate_sample_interval;
++	temp_et_coalesce.pkt_rate_low =	nesadapter->et_pkt_rate_low;
++	spin_lock_irqsave(&nesadapter->periodic_timer_lock,	flags);
++	temp_et_coalesce.rx_max_coalesced_frames_low =	shared_timer->threshold_low;
++	temp_et_coalesce.rx_max_coalesced_frames_irq =	shared_timer->threshold_target;
++	temp_et_coalesce.rx_max_coalesced_frames_high = shared_timer->threshold_high;
++	temp_et_coalesce.rx_coalesce_usecs_low = shared_timer->timer_in_use_min;
++	temp_et_coalesce.rx_coalesce_usecs_high = shared_timer->timer_in_use_max;
++	if (nesadapter->et_use_adaptive_rx_coalesce) {
++		temp_et_coalesce.rx_coalesce_usecs_irq = shared_timer->timer_in_use;
++	}
++	spin_unlock_irqrestore(&nesadapter->periodic_timer_lock, flags);
++	memcpy(et_coalesce,	&temp_et_coalesce, sizeof(*et_coalesce));
++	return 0;
++}
 +
- 	/*
- 	 * enough for anything that's going to trickle out to have actually
- 	 * done so.
-@@ -2217,25 +2159,15 @@ static int __init infinipath_init(void)
- 		goto bail_unit;
- 	}
- 
--	ret = ipath_driver_create_group(&ipath_driver.driver);
--	if (ret < 0) {
--		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create driver "
--		       "sysfs entries: error %d\n", -ret);
--		goto bail_pci;
--	}
--
- 	ret = ipath_init_ipathfs();
- 	if (ret < 0) {
- 		printk(KERN_ERR IPATH_DRV_NAME ": Unable to create "
- 		       "ipathfs: error %d\n", -ret);
--		goto bail_group;
-+		goto bail_pci;
- 	}
- 
- 	goto bail;
- 
--bail_group:
--	ipath_driver_remove_group(&ipath_driver.driver);
--
- bail_pci:
- 	pci_unregister_driver(&ipath_driver);
- 
-@@ -2250,8 +2182,6 @@ static void __exit infinipath_cleanup(void)
- {
- 	ipath_exit_ipathfs();
- 
--	ipath_driver_remove_group(&ipath_driver.driver);
--
- 	ipath_cdbg(VERBOSE, "Unregistering pci driver\n");
- 	pci_unregister_driver(&ipath_driver);
- 
-@@ -2344,5 +2274,34 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv)
- 	}
- 	return 0;
- }
 +
-+/*
-+ * Disable and enable the armlaunch error.  Used for PIO bandwidth testing on
-+ * the 7220, which is count-based, rather than trigger-based.  Safe for the
-+ * driver check, since it's at init.   Not completely safe when used for
-+ * user-mode checking, since some error checking can be lost, but not
-+ * particularly risky, and only has problematic side-effects in the face of
-+ * very buggy user code.  There is no reference counting, but that's also
-+ * fine, given the intended use.
++/**
++ * nes_netdev_get_pauseparam
 + */
-+void ipath_enable_armlaunch(struct ipath_devdata *dd)
++static void nes_netdev_get_pauseparam(struct net_device *netdev,
++		struct ethtool_pauseparam *et_pauseparam)
 +{
-+	dd->ipath_lasterror &= ~INFINIPATH_E_SPIOARMLAUNCH;
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errorclear,
-+		INFINIPATH_E_SPIOARMLAUNCH);
-+	dd->ipath_errormask |= INFINIPATH_E_SPIOARMLAUNCH;
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
-+		dd->ipath_errormask);
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++
++	et_pauseparam->autoneg = 0;
++	et_pauseparam->rx_pause = (nesvnic->nesdev->disable_rx_flow_control == 0) ? 1:0;
++	et_pauseparam->tx_pause = (nesvnic->nesdev->disable_tx_flow_control == 0) ? 1:0;
 +}
 +
-+void ipath_disable_armlaunch(struct ipath_devdata *dd)
++
++/**
++ * nes_netdev_set_pauseparam
++ */
++static int nes_netdev_set_pauseparam(struct net_device *netdev,
++		struct ethtool_pauseparam *et_pauseparam)
 +{
-+	/* so don't re-enable if already set */
-+	dd->ipath_maskederrs &= ~INFINIPATH_E_SPIOARMLAUNCH;
-+	dd->ipath_errormask &= ~INFINIPATH_E_SPIOARMLAUNCH;
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask,
-+		dd->ipath_errormask);
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	u32 u32temp;
++
++	if (et_pauseparam->autoneg) {
++		/* TODO: should return unsupported */
++		return 0;
++	}
++	if ((et_pauseparam->tx_pause == 1) && (nesdev->disable_tx_flow_control == 1)) {
++		u32temp = nes_read_indexed(nesdev,
++				NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
++		u32temp |= NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
++		nes_write_indexed(nesdev,
++				NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
++		nesdev->disable_tx_flow_control = 0;
++	} else if ((et_pauseparam->tx_pause == 0) && (nesdev->disable_tx_flow_control == 0)) {
++		u32temp = nes_read_indexed(nesdev,
++				NES_IDX_MAC_TX_CONFIG + (nesdev->mac_index*0x200));
++		u32temp &= ~NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE;
++		nes_write_indexed(nesdev,
++				NES_IDX_MAC_TX_CONFIG_ENABLE_PAUSE + (nesdev->mac_index*0x200), u32temp);
++		nesdev->disable_tx_flow_control = 1;
++	}
++	if ((et_pauseparam->rx_pause == 1) && (nesdev->disable_rx_flow_control == 1)) {
++		u32temp = nes_read_indexed(nesdev,
++				NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));
++		u32temp &= ~NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;
++		nes_write_indexed(nesdev,
++				NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);
++		nesdev->disable_rx_flow_control = 0;
++	} else if ((et_pauseparam->rx_pause == 0) && (nesdev->disable_rx_flow_control == 0)) {
++		u32temp = nes_read_indexed(nesdev,
++				NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40));
++		u32temp |= NES_IDX_MPP_DEBUG_PORT_DISABLE_PAUSE;
++		nes_write_indexed(nesdev,
++				NES_IDX_MPP_DEBUG + (nesdev->mac_index*0x40), u32temp);
++		nesdev->disable_rx_flow_control = 1;
++	}
++
++	return 0;
 +}
 +
- module_init(infinipath_init);
- module_exit(infinipath_cleanup);
-diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c
-index e7c25db..e28a42f 100644
---- a/drivers/infiniband/hw/ipath/ipath_eeprom.c
-+++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c
-@@ -510,10 +510,10 @@ int ipath_eeprom_read(struct ipath_devdata *dd, u8 eeprom_offset,
- {
- 	int ret;
- 
--	ret = down_interruptible(&dd->ipath_eep_sem);
-+	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
- 	if (!ret) {
- 		ret = ipath_eeprom_internal_read(dd, eeprom_offset, buff, len);
--		up(&dd->ipath_eep_sem);
-+		mutex_unlock(&dd->ipath_eep_lock);
- 	}
- 
- 	return ret;
-@@ -524,10 +524,10 @@ int ipath_eeprom_write(struct ipath_devdata *dd, u8 eeprom_offset,
- {
- 	int ret;
- 
--	ret = down_interruptible(&dd->ipath_eep_sem);
-+	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
- 	if (!ret) {
- 		ret = ipath_eeprom_internal_write(dd, eeprom_offset, buff, len);
--		up(&dd->ipath_eep_sem);
-+		mutex_unlock(&dd->ipath_eep_lock);
- 	}
- 
- 	return ret;
-@@ -574,7 +574,7 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
- 	struct ipath_devdata *dd0 = ipath_lookup(0);
- 
- 	if (t && dd0->ipath_nguid > 1 && t <= dd0->ipath_nguid) {
--		u8 *bguid, oguid;
-+		u8 oguid;
- 		dd->ipath_guid = dd0->ipath_guid;
- 		bguid = (u8 *) & dd->ipath_guid;
- 
-@@ -616,9 +616,9 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
- 		goto bail;
- 	}
- 
--	down(&dd->ipath_eep_sem);
-+	mutex_lock(&dd->ipath_eep_lock);
- 	eep_stat = ipath_eeprom_internal_read(dd, 0, buf, len);
--	up(&dd->ipath_eep_sem);
-+	mutex_unlock(&dd->ipath_eep_lock);
- 
- 	if (eep_stat) {
- 		ipath_dev_err(dd, "Failed reading GUID from eeprom\n");
-@@ -674,7 +674,6 @@ void ipath_get_eeprom_info(struct ipath_devdata *dd)
- 		 * elsewhere for backward-compatibility.
- 		 */
- 		char *snp = dd->ipath_serial;
--		int len;
- 		memcpy(snp, ifp->if_sprefix, sizeof ifp->if_sprefix);
- 		snp[sizeof ifp->if_sprefix] = '\0';
- 		len = strlen(snp);
-@@ -764,14 +763,14 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
- 	/* Grab semaphore and read current EEPROM. If we get an
- 	 * error, let go, but if not, keep it until we finish write.
- 	 */
--	ret = down_interruptible(&dd->ipath_eep_sem);
-+	ret = mutex_lock_interruptible(&dd->ipath_eep_lock);
- 	if (ret) {
- 		ipath_dev_err(dd, "Unable to acquire EEPROM for logging\n");
- 		goto free_bail;
- 	}
- 	ret = ipath_eeprom_internal_read(dd, 0, buf, len);
- 	if (ret) {
--		up(&dd->ipath_eep_sem);
-+		mutex_unlock(&dd->ipath_eep_lock);
- 		ipath_dev_err(dd, "Unable read EEPROM for logging\n");
- 		goto free_bail;
- 	}
-@@ -779,7 +778,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
- 
- 	csum = flash_csum(ifp, 0);
- 	if (csum != ifp->if_csum) {
--		up(&dd->ipath_eep_sem);
-+		mutex_unlock(&dd->ipath_eep_lock);
- 		ipath_dev_err(dd, "EEPROM cks err (0x%02X, S/B 0x%02X)\n",
- 				csum, ifp->if_csum);
- 		ret = 1;
-@@ -849,7 +848,7 @@ int ipath_update_eeprom_log(struct ipath_devdata *dd)
- 		csum = flash_csum(ifp, 1);
- 		ret = ipath_eeprom_internal_write(dd, 0, buf, hi_water + 1);
- 	}
--	up(&dd->ipath_eep_sem);
-+	mutex_unlock(&dd->ipath_eep_lock);
- 	if (ret)
- 		ipath_dev_err(dd, "Failed updating EEPROM\n");
- 
-diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c
-index 5de3243..7e025c8 100644
---- a/drivers/infiniband/hw/ipath/ipath_file_ops.c
-+++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c
-@@ -169,7 +169,7 @@ static int ipath_get_base_info(struct file *fp,
- 		kinfo->spi_piocnt = dd->ipath_pbufsport;
- 		kinfo->spi_piobufbase = (u64) pd->port_piobufs;
- 		kinfo->__spi_uregbase = (u64) dd->ipath_uregbase +
--			dd->ipath_palign * pd->port_port;
-+			dd->ipath_ureg_align * pd->port_port;
- 	} else if (master) {
- 		kinfo->spi_piocnt = (dd->ipath_pbufsport / subport_cnt) +
- 				    (dd->ipath_pbufsport % subport_cnt);
-@@ -186,7 +186,7 @@ static int ipath_get_base_info(struct file *fp,
- 	}
- 	if (shared) {
- 		kinfo->spi_port_uregbase = (u64) dd->ipath_uregbase +
--			dd->ipath_palign * pd->port_port;
-+			dd->ipath_ureg_align * pd->port_port;
- 		kinfo->spi_port_rcvegrbuf = kinfo->spi_rcv_egrbufs;
- 		kinfo->spi_port_rcvhdr_base = kinfo->spi_rcvhdr_base;
- 		kinfo->spi_port_rcvhdr_tailaddr = kinfo->spi_rcvhdr_tailaddr;
-@@ -742,11 +742,12 @@ static int ipath_manage_rcvq(struct ipath_portdata *pd, unsigned subport,
- 		 * updated and correct itself, even in the face of software
- 		 * bugs.
- 		 */
--		*(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0;
--		set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
-+		if (pd->port_rcvhdrtail_kvaddr)
-+			ipath_clear_rcvhdrtail(pd);
-+		set_bit(dd->ipath_r_portenable_shift + pd->port_port,
- 			&dd->ipath_rcvctrl);
- 	} else
--		clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
-+		clear_bit(dd->ipath_r_portenable_shift + pd->port_port,
- 			  &dd->ipath_rcvctrl);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- 			 dd->ipath_rcvctrl);
-@@ -881,7 +882,7 @@ static int ipath_create_user_egr(struct ipath_portdata *pd)
- 
- 	egrcnt = dd->ipath_rcvegrcnt;
- 	/* TID number offset for this port */
--	egroff = pd->port_port * egrcnt;
-+	egroff = (pd->port_port - 1) * egrcnt + dd->ipath_p0_rcvegrcnt;
- 	egrsize = dd->ipath_rcvegrbufsize;
- 	ipath_cdbg(VERBOSE, "Allocating %d egr buffers, at egrtid "
- 		   "offset %x, egrsize %u\n", egrcnt, egroff, egrsize);
-@@ -1049,11 +1050,6 @@ static int mmap_piobufs(struct vm_area_struct *vma,
- 
- 	phys = dd->ipath_physaddr + piobufs;
- 
--	/*
--	 * Don't mark this as non-cached, or we don't get the
--	 * write combining behavior we want on the PIO buffers!
--	 */
--
- #if defined(__powerpc__)
- 	/* There isn't a generic way to specify writethrough mappings */
- 	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
-@@ -1120,33 +1116,24 @@ bail:
- }
- 
- /*
-- * ipath_file_vma_nopage - handle a VMA page fault.
-+ * ipath_file_vma_fault - handle a VMA page fault.
-  */
--static struct page *ipath_file_vma_nopage(struct vm_area_struct *vma,
--					  unsigned long address, int *type)
-+static int ipath_file_vma_fault(struct vm_area_struct *vma,
-+					struct vm_fault *vmf)
- {
--	unsigned long offset = address - vma->vm_start;
--	struct page *page = NOPAGE_SIGBUS;
--	void *pageptr;
-+	struct page *page;
- 
--	/*
--	 * Convert the vmalloc address into a struct page.
--	 */
--	pageptr = (void *)(offset + (vma->vm_pgoff << PAGE_SHIFT));
--	page = vmalloc_to_page(pageptr);
-+	page = vmalloc_to_page((void *)(vmf->pgoff << PAGE_SHIFT));
- 	if (!page)
--		goto out;
--
--	/* Increment the reference count. */
-+		return VM_FAULT_SIGBUS;
- 	get_page(page);
--	if (type)
--		*type = VM_FAULT_MINOR;
--out:
--	return page;
-+	vmf->page = page;
++
++/**
++ * nes_netdev_get_settings
++ */
++static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u16 phy_data;
++
++	et_cmd->duplex = DUPLEX_FULL;
++	et_cmd->port = PORT_MII;
++	if (nesadapter->OneG_Mode) {
++		et_cmd->supported = SUPPORTED_1000baseT_Full|SUPPORTED_Autoneg;
++		et_cmd->advertising = ADVERTISED_1000baseT_Full|ADVERTISED_Autoneg;
++		et_cmd->speed = SPEED_1000;
++		nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
++				&phy_data);
++		if (phy_data&0x1000) {
++			et_cmd->autoneg = AUTONEG_ENABLE;
++		} else {
++			et_cmd->autoneg = AUTONEG_DISABLE;
++		}
++		et_cmd->transceiver = XCVR_EXTERNAL;
++		et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
++	} else {
++		if (nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
++			et_cmd->transceiver = XCVR_EXTERNAL;
++			et_cmd->port = PORT_FIBRE;
++			et_cmd->supported = SUPPORTED_FIBRE;
++			et_cmd->advertising = ADVERTISED_FIBRE;
++			et_cmd->phy_address = nesadapter->phy_index[nesdev->mac_index];
++		} else {
++			et_cmd->transceiver = XCVR_INTERNAL;
++			et_cmd->supported = SUPPORTED_10000baseT_Full;
++			et_cmd->advertising = ADVERTISED_10000baseT_Full;
++			et_cmd->phy_address = nesdev->mac_index;
++		}
++		et_cmd->speed = SPEED_10000;
++		et_cmd->autoneg = AUTONEG_DISABLE;
++	}
++	et_cmd->maxtxpkt = 511;
++	et_cmd->maxrxpkt = 511;
++	return 0;
++}
++
++
++/**
++ * nes_netdev_set_settings
++ */
++static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd *et_cmd)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u16 phy_data;
++
++	if (nesadapter->OneG_Mode) {
++		nes_read_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
++				&phy_data);
++		if (et_cmd->autoneg) {
++			/* Turn on Full duplex, Autoneg, and restart autonegotiation */
++			phy_data |= 0x1300;
++		} else {
++			// Turn off autoneg
++			phy_data &= ~0x1000;
++		}
++		nes_write_1G_phy_reg(nesdev, 0, nesadapter->phy_index[nesdev->mac_index],
++				phy_data);
++	}
 +
 +	return 0;
- }
- 
- static struct vm_operations_struct ipath_file_vm_ops = {
--	.nopage = ipath_file_vma_nopage,
-+	.fault = ipath_file_vma_fault,
- };
- 
- static int mmap_kvaddr(struct vm_area_struct *vma, u64 pgaddr,
-@@ -1284,7 +1271,7 @@ static int ipath_mmap(struct file *fp, struct vm_area_struct *vma)
- 		goto bail;
- 	}
- 
--	ureg = dd->ipath_uregbase + dd->ipath_palign * pd->port_port;
-+	ureg = dd->ipath_uregbase + dd->ipath_ureg_align * pd->port_port;
- 	if (!pd->port_subport_cnt) {
- 		/* port is not shared */
- 		piocnt = dd->ipath_pbufsport;
-@@ -1400,7 +1387,10 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
- 	pollflag = ipath_poll_hdrqfull(pd);
- 
- 	head = ipath_read_ureg32(dd, ur_rcvhdrhead, pd->port_port);
--	tail = *(volatile u64 *)pd->port_rcvhdrtail_kvaddr;
-+	if (pd->port_rcvhdrtail_kvaddr)
-+		tail = ipath_get_rcvhdrtail(pd);
++}
++
++
++static struct ethtool_ops nes_ethtool_ops = {
++	.get_link = ethtool_op_get_link,
++	.get_settings = nes_netdev_get_settings,
++	.set_settings = nes_netdev_set_settings,
++	.get_tx_csum = ethtool_op_get_tx_csum,
++	.get_rx_csum = nes_netdev_get_rx_csum,
++	.get_sg = ethtool_op_get_sg,
++	.get_strings = nes_netdev_get_strings,
++	.get_stats_count = nes_netdev_get_stats_count,
++	.get_ethtool_stats = nes_netdev_get_ethtool_stats,
++	.get_drvinfo = nes_netdev_get_drvinfo,
++	.get_coalesce = nes_netdev_get_coalesce,
++	.set_coalesce = nes_netdev_set_coalesce,
++	.get_pauseparam = nes_netdev_get_pauseparam,
++	.set_pauseparam = nes_netdev_set_pauseparam,
++	.set_tx_csum = ethtool_op_set_tx_csum,
++	.set_rx_csum = nes_netdev_set_rx_csum,
++	.set_sg = ethtool_op_set_sg,
++	.get_tso = ethtool_op_get_tso,
++	.set_tso = ethtool_op_set_tso,
++};
++
++
++static void nes_netdev_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	u32 u32temp;
++
++	nesvnic->vlan_grp = grp;
++
++	/* Enable/Disable VLAN Stripping */
++	u32temp = nes_read_indexed(nesdev, NES_IDX_PCIX_DIAG);
++	if (grp)
++		u32temp &= 0xfdffffff;
 +	else
-+		tail = ipath_read_ureg32(dd, ur_rcvhdrtail, pd->port_port);
- 
- 	if (head != tail)
- 		pollflag |= POLLIN | POLLRDNORM;
-@@ -1410,7 +1400,7 @@ static unsigned int ipath_poll_next(struct ipath_portdata *pd,
- 		/* flush waiting flag so we don't miss an event */
- 		wmb();
- 
--		set_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
-+		set_bit(pd->port_port + dd->ipath_r_intravail_shift,
- 			&dd->ipath_rcvctrl);
- 
- 		ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
-@@ -1790,6 +1780,7 @@ static int find_shared_port(struct file *fp,
- 			}
- 			port_fp(fp) = pd;
- 			subport_fp(fp) = pd->port_cnt++;
-+			pd->port_subpid[subport_fp(fp)] = current->pid;
- 			tidcursor_fp(fp) = 0;
- 			pd->active_slaves |= 1 << subport_fp(fp);
- 			ipath_cdbg(PROC,
-@@ -1920,8 +1911,7 @@ static int ipath_do_user_init(struct file *fp,
- 	 */
- 	head32 = ipath_read_ureg32(dd, ur_rcvegrindextail, pd->port_port);
- 	ipath_write_ureg(dd, ur_rcvegrindexhead, head32, pd->port_port);
--	dd->ipath_lastegrheads[pd->port_port] = -1;
--	dd->ipath_lastrcvhdrqtails[pd->port_port] = -1;
-+	pd->port_lastrcvhdrqtail = -1;
- 	ipath_cdbg(VERBOSE, "Wrote port%d egrhead %x from tail regs\n",
- 		pd->port_port, head32);
- 	pd->port_tidcursor = 0;	/* start at beginning after open */
-@@ -1941,11 +1931,13 @@ static int ipath_do_user_init(struct file *fp,
- 	 * We explictly set the in-memory copy to 0 beforehand, so we don't
- 	 * have to wait to be sure the DMA update has happened.
- 	 */
--	*(volatile u64 *)pd->port_rcvhdrtail_kvaddr = 0ULL;
--	set_bit(INFINIPATH_R_PORTENABLE_SHIFT + pd->port_port,
-+	if (pd->port_rcvhdrtail_kvaddr)
-+		ipath_clear_rcvhdrtail(pd);
-+	set_bit(dd->ipath_r_portenable_shift + pd->port_port,
- 		&dd->ipath_rcvctrl);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
--			 dd->ipath_rcvctrl & ~INFINIPATH_R_TAILUPD);
-+			dd->ipath_rcvctrl &
-+			~(1ULL << dd->ipath_r_tailupd_shift));
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- 			 dd->ipath_rcvctrl);
- 	/* Notify any waiting slaves */
-@@ -2022,6 +2014,7 @@ static int ipath_close(struct inode *in, struct file *fp)
- 		 * the slave(s) don't wait for receive data forever.
- 		 */
- 		pd->active_slaves &= ~(1 << fd->subport);
-+		pd->port_subpid[fd->subport] = 0;
- 		mutex_unlock(&ipath_mutex);
- 		goto bail;
- 	}
-@@ -2054,9 +2047,9 @@ static int ipath_close(struct inode *in, struct file *fp)
- 	if (dd->ipath_kregbase) {
- 		int i;
- 		/* atomically clear receive enable port and intr avail. */
--		clear_bit(INFINIPATH_R_PORTENABLE_SHIFT + port,
-+		clear_bit(dd->ipath_r_portenable_shift + port,
- 			  &dd->ipath_rcvctrl);
--		clear_bit(pd->port_port + INFINIPATH_R_INTRAVAIL_SHIFT,
-+		clear_bit(pd->port_port + dd->ipath_r_intravail_shift,
- 			  &dd->ipath_rcvctrl);
- 		ipath_write_kreg( dd, dd->ipath_kregs->kr_rcvctrl,
- 			dd->ipath_rcvctrl);
-@@ -2149,11 +2142,15 @@ static int ipath_get_slave_info(struct ipath_portdata *pd,
- 
- static int ipath_force_pio_avail_update(struct ipath_devdata *dd)
- {
--	u64 reg = dd->ipath_sendctrl;
-+	unsigned long flags;
- 
--	clear_bit(IPATH_S_PIOBUFAVAILUPD, &reg);
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, reg);
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
-+		dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- 
- 	return 0;
- }
-@@ -2227,6 +2224,11 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
- 		dest = &cmd.cmd.poll_type;
- 		src = &ucmd->cmd.poll_type;
- 		break;
-+	case IPATH_CMD_ARMLAUNCH_CTRL:
-+		copy = sizeof(cmd.cmd.armlaunch_ctrl);
-+		dest = &cmd.cmd.armlaunch_ctrl;
-+		src = &ucmd->cmd.armlaunch_ctrl;
-+		break;
- 	default:
- 		ret = -EINVAL;
- 		goto bail;
-@@ -2302,6 +2304,12 @@ static ssize_t ipath_write(struct file *fp, const char __user *data,
- 	case IPATH_CMD_POLL_TYPE:
- 		pd->poll_type = cmd.cmd.poll_type;
- 		break;
-+	case IPATH_CMD_ARMLAUNCH_CTRL:
-+		if (cmd.cmd.armlaunch_ctrl)
-+			ipath_enable_armlaunch(pd->port_dd);
-+		else
-+			ipath_disable_armlaunch(pd->port_dd);
-+		break;
- 	}
- 
- 	if (ret >= 0)
-diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c
-index 262c25d..23faba9 100644
---- a/drivers/infiniband/hw/ipath/ipath_fs.c
-+++ b/drivers/infiniband/hw/ipath/ipath_fs.c
-@@ -108,21 +108,16 @@ static const struct file_operations atomic_stats_ops = {
- 	.read = atomic_stats_read,
- };
- 
--#define NUM_COUNTERS sizeof(struct infinipath_counters) / sizeof(u64)
--
- static ssize_t atomic_counters_read(struct file *file, char __user *buf,
- 				    size_t count, loff_t *ppos)
- {
--	u64 counters[NUM_COUNTERS];
--	u16 i;
-+	struct infinipath_counters counters;
- 	struct ipath_devdata *dd;
- 
- 	dd = file->f_path.dentry->d_inode->i_private;
-+	dd->ipath_f_read_counters(dd, &counters);
- 
--	for (i = 0; i < NUM_COUNTERS; i++)
--		counters[i] = ipath_snap_cntr(dd, i);
--
--	return simple_read_from_buffer(buf, count, ppos, counters,
-+	return simple_read_from_buffer(buf, count, ppos, &counters,
- 				       sizeof counters);
- }
- 
-@@ -243,8 +238,7 @@ static int create_device_files(struct super_block *sb,
- 
- 	snprintf(unit, sizeof unit, "%02d", dd->ipath_unit);
- 	ret = create_file(unit, S_IFDIR|S_IRUGO|S_IXUGO, sb->s_root, &dir,
--			  (struct file_operations *) &simple_dir_operations,
--			  dd);
-+			  &simple_dir_operations, dd);
- 	if (ret) {
- 		printk(KERN_ERR "create_file(%s) failed: %d\n", unit, ret);
- 		goto bail;
-diff --git a/drivers/infiniband/hw/ipath/ipath_iba6110.c b/drivers/infiniband/hw/ipath/ipath_iba6110.c
-index ddbebe4..9e2ced3 100644
---- a/drivers/infiniband/hw/ipath/ipath_iba6110.c
-+++ b/drivers/infiniband/hw/ipath/ipath_iba6110.c
-@@ -148,10 +148,57 @@ struct _infinipath_do_not_use_kernel_regs {
- 	unsigned long long ReservedSW2[4];
- };
- 
--#define IPATH_KREG_OFFSET(field) (offsetof(struct \
--    _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
-+struct _infinipath_do_not_use_counters {
-+	__u64 LBIntCnt;
-+	__u64 LBFlowStallCnt;
-+	__u64 Reserved1;
-+	__u64 TxUnsupVLErrCnt;
-+	__u64 TxDataPktCnt;
-+	__u64 TxFlowPktCnt;
-+	__u64 TxDwordCnt;
-+	__u64 TxLenErrCnt;
-+	__u64 TxMaxMinLenErrCnt;
-+	__u64 TxUnderrunCnt;
-+	__u64 TxFlowStallCnt;
-+	__u64 TxDroppedPktCnt;
-+	__u64 RxDroppedPktCnt;
-+	__u64 RxDataPktCnt;
-+	__u64 RxFlowPktCnt;
-+	__u64 RxDwordCnt;
-+	__u64 RxLenErrCnt;
-+	__u64 RxMaxMinLenErrCnt;
-+	__u64 RxICRCErrCnt;
-+	__u64 RxVCRCErrCnt;
-+	__u64 RxFlowCtrlErrCnt;
-+	__u64 RxBadFormatCnt;
-+	__u64 RxLinkProblemCnt;
-+	__u64 RxEBPCnt;
-+	__u64 RxLPCRCErrCnt;
-+	__u64 RxBufOvflCnt;
-+	__u64 RxTIDFullErrCnt;
-+	__u64 RxTIDValidErrCnt;
-+	__u64 RxPKeyMismatchCnt;
-+	__u64 RxP0HdrEgrOvflCnt;
-+	__u64 RxP1HdrEgrOvflCnt;
-+	__u64 RxP2HdrEgrOvflCnt;
-+	__u64 RxP3HdrEgrOvflCnt;
-+	__u64 RxP4HdrEgrOvflCnt;
-+	__u64 RxP5HdrEgrOvflCnt;
-+	__u64 RxP6HdrEgrOvflCnt;
-+	__u64 RxP7HdrEgrOvflCnt;
-+	__u64 RxP8HdrEgrOvflCnt;
-+	__u64 Reserved6;
-+	__u64 Reserved7;
-+	__u64 IBStatusChangeCnt;
-+	__u64 IBLinkErrRecoveryCnt;
-+	__u64 IBLinkDownedCnt;
-+	__u64 IBSymbolErrCnt;
++		u32temp	|= 0x02000000;
++
++	nes_write_indexed(nesdev, NES_IDX_PCIX_DIAG, u32temp);
++}
++
++
++/**
++ * nes_netdev_init - initialize network device
++ */
++struct net_device *nes_netdev_init(struct nes_device *nesdev,
++		void __iomem *mmio_addr)
++{
++	u64 u64temp;
++	struct nes_vnic *nesvnic = NULL;
++	struct net_device *netdev;
++	struct nic_qp_map *curr_qp_map;
++	u32 u32temp;
++	u16 phy_data;
++	u16 temp_phy_data;
++
++	netdev = alloc_etherdev(sizeof(struct nes_vnic));
++	if (!netdev) {
++		printk(KERN_ERR PFX "nesvnic etherdev alloc failed");
++		return NULL;
++	}
++
++	nes_debug(NES_DBG_INIT, "netdev = %p, %s\n", netdev, netdev->name);
++
++	SET_NETDEV_DEV(netdev, &nesdev->pcidev->dev);
++
++	nesvnic = netdev_priv(netdev);
++	memset(nesvnic, 0, sizeof(*nesvnic));
++
++	netdev->open = nes_netdev_open;
++	netdev->stop = nes_netdev_stop;
++	netdev->hard_start_xmit = nes_netdev_start_xmit;
++	netdev->get_stats = nes_netdev_get_stats;
++	netdev->tx_timeout = nes_netdev_tx_timeout;
++	netdev->set_mac_address = nes_netdev_set_mac_address;
++	netdev->set_multicast_list = nes_netdev_set_multicast_list;
++	netdev->change_mtu = nes_netdev_change_mtu;
++	netdev->watchdog_timeo = NES_TX_TIMEOUT;
++	netdev->irq = nesdev->pcidev->irq;
++	netdev->mtu = ETH_DATA_LEN;
++	netdev->hard_header_len = ETH_HLEN;
++	netdev->addr_len = ETH_ALEN;
++	netdev->type = ARPHRD_ETHER;
++	netdev->features = NETIF_F_HIGHDMA;
++	netdev->ethtool_ops = &nes_ethtool_ops;
++	netif_napi_add(netdev, &nesvnic->napi, nes_netdev_poll, 128);
++	nes_debug(NES_DBG_INIT, "Enabling VLAN Insert/Delete.\n");
++	netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
++	netdev->vlan_rx_register = nes_netdev_vlan_rx_register;
++	netdev->features |= NETIF_F_LLTX;
++
++	/* Fill in the port structure */
++	nesvnic->netdev = netdev;
++	nesvnic->nesdev = nesdev;
++	nesvnic->msg_enable = netif_msg_init(debug, default_msg);
++	nesvnic->netdev_index = nesdev->netdev_count;
++	nesvnic->perfect_filter_index = nesdev->nesadapter->netdev_count;
++	nesvnic->max_frame_size = netdev->mtu+netdev->hard_header_len;
++
++	curr_qp_map = nic_qp_mapping_per_function[PCI_FUNC(nesdev->pcidev->devfn)];
++	nesvnic->nic.qp_id = curr_qp_map[nesdev->netdev_count].qpid;
++	nesvnic->nic_index = curr_qp_map[nesdev->netdev_count].nic_index;
++	nesvnic->logical_port = curr_qp_map[nesdev->netdev_count].logical_port;
++
++	/* Setup the burned in MAC address */
++	u64temp = (u64)nesdev->nesadapter->mac_addr_low;
++	u64temp += ((u64)nesdev->nesadapter->mac_addr_high) << 32;
++	u64temp += nesvnic->nic_index;
++	netdev->dev_addr[0] = (u8)(u64temp>>40);
++	netdev->dev_addr[1] = (u8)(u64temp>>32);
++	netdev->dev_addr[2] = (u8)(u64temp>>24);
++	netdev->dev_addr[3] = (u8)(u64temp>>16);
++	netdev->dev_addr[4] = (u8)(u64temp>>8);
++	netdev->dev_addr[5] = (u8)u64temp;
++	memcpy(netdev->perm_addr, netdev->dev_addr, 6);
++
++	if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) {
++		netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
++		netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM;
++	} else {
++		netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
++	}
++
++	nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"
++			" nic_index = %d, logical_port = %d, mac_index = %d.\n",
++			nesvnic, (unsigned long)netdev->features, nesvnic->nic.qp_id,
++			nesvnic->nic_index, nesvnic->logical_port,  nesdev->mac_index);
++
++	if (nesvnic->nesdev->nesadapter->port_count == 1) {
++		nesvnic->qp_nic_index[0] = nesvnic->nic_index;
++		nesvnic->qp_nic_index[1] = nesvnic->nic_index + 1;
++		if (nes_drv_opt & NES_DRV_OPT_DUAL_LOGICAL_PORT) {
++			nesvnic->qp_nic_index[2] = 0xf;
++			nesvnic->qp_nic_index[3] = 0xf;
++		} else {
++			nesvnic->qp_nic_index[2] = nesvnic->nic_index + 2;
++			nesvnic->qp_nic_index[3] = nesvnic->nic_index + 3;
++		}
++	} else {
++		if (nesvnic->nesdev->nesadapter->port_count == 2) {
++			nesvnic->qp_nic_index[0] = nesvnic->nic_index;
++			nesvnic->qp_nic_index[1] = nesvnic->nic_index + 2;
++			nesvnic->qp_nic_index[2] = 0xf;
++			nesvnic->qp_nic_index[3] = 0xf;
++		} else {
++			nesvnic->qp_nic_index[0] = nesvnic->nic_index;
++			nesvnic->qp_nic_index[1] = 0xf;
++			nesvnic->qp_nic_index[2] = 0xf;
++			nesvnic->qp_nic_index[3] = 0xf;
++		}
++	}
++	nesvnic->next_qp_nic_index = 0;
++
++	if (nesdev->netdev_count == 0) {
++		nesvnic->rdma_enabled = 1;
++	} else {
++		nesvnic->rdma_enabled = 0;
++	}
++	nesvnic->nic_cq.cq_number = nesvnic->nic.qp_id;
++	spin_lock_init(&nesvnic->tx_lock);
++	nesdev->netdev[nesdev->netdev_count] = netdev;
++
++	nes_debug(NES_DBG_INIT, "Adding nesvnic (%p) to the adapters nesvnic_list for MAC%d.\n",
++			nesvnic, nesdev->mac_index);
++	list_add_tail(&nesvnic->list, &nesdev->nesadapter->nesvnic_list[nesdev->mac_index]);
++
++	if ((nesdev->netdev_count == 0) &&
++			(PCI_FUNC(nesdev->pcidev->devfn) == nesdev->mac_index)) {
++		nes_debug(NES_DBG_INIT, "Setting up PHY interrupt mask. Using register index 0x%04X\n",
++				NES_IDX_PHY_PCS_CONTROL_STATUS0+(0x200*(nesvnic->logical_port&1)));
++		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
++				(0x200*(nesvnic->logical_port&1)));
++		u32temp |= 0x00200000;
++		nes_write_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
++				(0x200*(nesvnic->logical_port&1)), u32temp);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 +
++				(0x200*(nesvnic->logical_port&1)) );
++		if ((u32temp&0x0f1f0000) == 0x0f0f0000) {
++			if (nesdev->nesadapter->phy_type[nesvnic->logical_port] == NES_PHY_TYPE_IRIS) {
++				nes_init_phy(nesdev);
++				nes_read_10G_phy_reg(nesdev, 1,
++						nesdev->nesadapter->phy_index[nesvnic->logical_port]);
++				temp_phy_data = (u16)nes_read_indexed(nesdev,
++									NES_IDX_MAC_MDIO_CONTROL);
++				u32temp = 20;
++				do {
++					nes_read_10G_phy_reg(nesdev, 1,
++							nesdev->nesadapter->phy_index[nesvnic->logical_port]);
++					phy_data = (u16)nes_read_indexed(nesdev,
++									NES_IDX_MAC_MDIO_CONTROL);
++					if ((phy_data == temp_phy_data) || (!(--u32temp)))
++						break;
++					temp_phy_data = phy_data;
++				} while (1);
++				if (phy_data & 4) {
++					nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
++					nesvnic->linkup = 1;
++				} else {
++					nes_debug(NES_DBG_INIT, "The Link is DOWN!!.\n");
++				}
++			} else {
++				nes_debug(NES_DBG_INIT, "The Link is UP!!.\n");
++				nesvnic->linkup = 1;
++			}
++		}
++		nes_debug(NES_DBG_INIT, "Setting up MAC interrupt mask.\n");
++		/* clear the MAC interrupt status, assumes direct logical to physical mapping */
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port));
++		nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp);
++		nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS+(0x200*nesvnic->logical_port), u32temp);
++
++		if (nesdev->nesadapter->phy_type[nesvnic->logical_port] != NES_PHY_TYPE_IRIS)
++			nes_init_phy(nesdev);
++
++		nes_write_indexed(nesdev, NES_IDX_MAC_INT_MASK+(0x200*nesvnic->logical_port),
++				~(NES_MAC_INT_LINK_STAT_CHG | NES_MAC_INT_XGMII_EXT |
++				NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR));
++	}
++
++	return netdev;
++}
++
++
++/**
++ * nes_netdev_destroy - destroy network device structure
++ */
++void nes_netdev_destroy(struct net_device *netdev)
++{
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++
++	/* make sure 'stop' method is called by Linux stack */
++	/* nes_netdev_stop(netdev); */
++
++	list_del(&nesvnic->list);
++
++	if (nesvnic->of_device_registered) {
++		nes_destroy_ofa_device(nesvnic->nesibdev);
++	}
++
++	free_netdev(netdev);
++}
++
++
++/**
++ * nes_nic_cm_xmit -- CM calls this to send out pkts
++ */
++int nes_nic_cm_xmit(struct sk_buff *skb, struct net_device *netdev)
++{
++	int ret;
++
++	skb->dev = netdev;
++	ret = dev_queue_xmit(skb);
++	if (ret) {
++		nes_debug(NES_DBG_CM, "Bad return code from dev_queue_xmit %d\n", ret);
++	}
++
++	return ret;
++}
+diff --git a/drivers/infiniband/hw/nes/nes_user.h b/drivers/infiniband/hw/nes/nes_user.h
+new file mode 100644
+index 0000000..e64306b
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_user.h
+@@ -0,0 +1,112 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect.  All rights reserved.
++ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
++ * Copyright (c) 2005 Cisco Systems.  All rights reserved.
++ * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#ifndef NES_USER_H
++#define NES_USER_H
++
++#include <linux/types.h>
++
++#define NES_ABI_USERSPACE_VER 1
++#define NES_ABI_KERNEL_VER    1
++
++/*
++ * Make sure that all structs defined in this file remain laid out so
++ * that they pack the same way on 32-bit and 64-bit architectures (to
++ * avoid incompatibility between 32-bit userspace and 64-bit kernels).
++ * In particular do not use pointer types -- pass pointers in __u64
++ * instead.
++ */
++
++struct nes_alloc_ucontext_req {
++	__u32 reserved32;
++	__u8  userspace_ver;
++	__u8  reserved8[3];
 +};
 +
-+#define IPATH_KREG_OFFSET(field) (offsetof( \
-+	struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
- #define IPATH_CREG_OFFSET(field) (offsetof( \
--    struct infinipath_counters, field) / sizeof(u64))
-+	struct _infinipath_do_not_use_counters, field) / sizeof(u64))
- 
- static const struct ipath_kregs ipath_ht_kregs = {
- 	.kr_control = IPATH_KREG_OFFSET(Control),
-@@ -282,6 +329,9 @@ static const struct ipath_cregs ipath_ht_cregs = {
- #define INFINIPATH_HWE_HTAPLL_RFSLIP        0x1000000000000000ULL
- #define INFINIPATH_HWE_SERDESPLLFAILED      0x2000000000000000ULL
- 
-+#define IBA6110_IBCS_LINKTRAININGSTATE_MASK 0xf
-+#define IBA6110_IBCS_LINKSTATE_SHIFT 4
++struct nes_alloc_ucontext_resp {
++	__u32 max_pds; /* maximum pds allowed for this user process */
++	__u32 max_qps; /* maximum qps allowed for this user process */
++	__u32 wq_size; /* size of the WQs (sq+rq) allocated to the mmaped area */
++	__u8  virtwq;  /* flag to indicate if virtual WQ are to be used or not */
++	__u8  kernel_ver;
++	__u8  reserved[2];
++};
 +
- /* kr_extstatus bits */
- #define INFINIPATH_EXTS_FREQSEL 0x2
- #define INFINIPATH_EXTS_SERDESSEL 0x4
-@@ -296,6 +346,12 @@ static const struct ipath_cregs ipath_ht_cregs = {
- #define INFINIPATH_RT_BUFSIZE_MASK 0x3FFFULL
- #define INFINIPATH_RT_BUFSIZE_SHIFT 48
- 
-+#define INFINIPATH_R_INTRAVAIL_SHIFT 16
-+#define INFINIPATH_R_TAILUPD_SHIFT 31
++struct nes_alloc_pd_resp {
++	__u32 pd_id;
++	__u32 mmap_db_index;
++};
 +
-+/* kr_xgxsconfig bits */
-+#define INFINIPATH_XGXS_RESET          0x7ULL
++struct nes_create_cq_req {
++	__u64 user_cq_buffer;
++	__u32 mcrqf;
++	__u8 reserved[4];
++};
 +
- /*
-  * masks and bits that are different in different chips, or present only
-  * in one
-@@ -652,7 +708,6 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
- 			      "with ID %u\n", boardrev);
- 		snprintf(name, namelen, "Unknown_InfiniPath_QHT7xxx_%u",
- 			 boardrev);
--		ret = 1;
- 		break;
- 	}
- 	if (n)
-@@ -686,6 +741,13 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name,
- 			      dd->ipath_htspeed);
- 	ret = 0;
- 
-+	/*
-+	 * set here, not in ipath_init_*_funcs because we have to do
-+	 * it after we can read chip registers.
-+	 */
-+	dd->ipath_ureg_align =
-+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
++struct nes_create_qp_req {
++	__u64 user_wqe_buffers;
++};
 +
- bail:
- 	return ret;
- }
-@@ -969,7 +1031,8 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
- 	do {
- 		u8 cap_type;
- 
--		/* the HT capability type byte is 3 bytes after the
-+		/*
-+		 * The HT capability type byte is 3 bytes after the
- 		 * capability byte.
- 		 */
- 		if (pci_read_config_byte(pdev, pos + 3, &cap_type)) {
-@@ -982,6 +1045,8 @@ static int ipath_setup_ht_config(struct ipath_devdata *dd,
- 	} while ((pos = pci_find_next_capability(pdev, pos,
- 						 PCI_CAP_ID_HT)));
- 
-+	dd->ipath_flags |= IPATH_SWAP_PIOBUFS;
++enum iwnes_memreg_type {
++	IWNES_MEMREG_TYPE_MEM = 0x0000,
++	IWNES_MEMREG_TYPE_QP = 0x0001,
++	IWNES_MEMREG_TYPE_CQ = 0x0002,
++	IWNES_MEMREG_TYPE_MW = 0x0003,
++	IWNES_MEMREG_TYPE_FMR = 0x0004,
++};
 +
- bail:
- 	return ret;
- }
-@@ -1074,11 +1139,55 @@ static void ipath_setup_ht_setextled(struct ipath_devdata *dd,
- 
- static void ipath_init_ht_variables(struct ipath_devdata *dd)
- {
-+	/*
-+	 * setup the register offsets, since they are different for each
-+	 * chip
-+	 */
-+	dd->ipath_kregs = &ipath_ht_kregs;
-+	dd->ipath_cregs = &ipath_ht_cregs;
++struct nes_mem_reg_req {
++	__u32 reg_type;	/* indicates if id is memory, QP or CQ */
++	__u32 reserved;
++};
 +
- 	dd->ipath_gpio_sda_num = _IPATH_GPIO_SDA_NUM;
- 	dd->ipath_gpio_scl_num = _IPATH_GPIO_SCL_NUM;
- 	dd->ipath_gpio_sda = IPATH_GPIO_SDA;
- 	dd->ipath_gpio_scl = IPATH_GPIO_SCL;
- 
-+	/*
-+	 * Fill in data for field-values that change in newer chips.
-+	 * We dynamically specify only the mask for LINKTRAININGSTATE
-+	 * and only the shift for LINKSTATE, as they are the only ones
-+	 * that change.  Also precalculate the 3 link states of interest
-+	 * and the combined mask.
-+	 */
-+	dd->ibcs_ls_shift = IBA6110_IBCS_LINKSTATE_SHIFT;
-+	dd->ibcs_lts_mask = IBA6110_IBCS_LINKTRAININGSTATE_MASK;
-+	dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
-+		dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
-+	dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
-+		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
-+		(INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
-+	dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
-+		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
-+		(INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
-+	dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
-+		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
-+		(INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
++struct nes_create_cq_resp {
++	__u32 cq_id;
++	__u32 cq_size;
++	__u32 mmap_db_index;
++	__u32 reserved;
++};
 +
-+	/*
-+	 * Fill in data for ibcc field-values that change in newer chips.
-+	 * We dynamically specify only the mask for LINKINITCMD
-+	 * and only the shift for LINKCMD and MAXPKTLEN, as they are
-+	 * the only ones that change.
-+	 */
-+	dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
-+	dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
-+	dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
++struct nes_create_qp_resp {
++	__u32 qp_id;
++	__u32 actual_sq_size;
++	__u32 actual_rq_size;
++	__u32 mmap_sq_db_index;
++	__u32 mmap_rq_db_index;
++	__u32 nes_drv_opt;
++};
 +
-+	/* Fill in shifts for RcvCtrl. */
-+	dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
-+	dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
-+	dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT;
-+	dd->ipath_r_portcfg_shift = 0; /* Not on IBA6110 */
++#endif				/* NES_USER_H */
+diff --git a/drivers/infiniband/hw/nes/nes_utils.c b/drivers/infiniband/hw/nes/nes_utils.c
+new file mode 100644
+index 0000000..c4ec6ac
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_utils.c
+@@ -0,0 +1,917 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
 +
- 	dd->ipath_i_bitsextant =
- 		(INFINIPATH_I_RCVURG_MASK << INFINIPATH_I_RCVURG_SHIFT) |
- 		(INFINIPATH_I_RCVAVAIL_MASK <<
-@@ -1135,6 +1244,8 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
- 
- 	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
- 	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
-+	dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
-+	dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
- 
- 	/*
- 	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
-@@ -1148,9 +1259,17 @@ static void ipath_init_ht_variables(struct ipath_devdata *dd)
- 		INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
- 		INFINIPATH_HWE_RXEMEMPARITYERR_SHIFT;
- 
--	dd->ipath_eep_st_masks[2].errs_to_log =
--		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
-+	dd->ipath_eep_st_masks[2].errs_to_log = INFINIPATH_E_RESET;
- 
-+	dd->delay_mult = 2; /* SDR, 4X, can't change */
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/ethtool.h>
++#include <linux/mii.h>
++#include <linux/if_vlan.h>
++#include <linux/crc32.h>
++#include <linux/in.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/init.h>
 +
-+	dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
-+	dd->ipath_link_speed_supported = IPATH_IB_SDR;
-+	dd->ipath_link_width_enabled = IB_WIDTH_4X;
-+	dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
-+	/* these can't change for this chip, so set once */
-+	dd->ipath_link_width_active = dd->ipath_link_width_enabled;
-+	dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
- }
- 
- /**
-@@ -1205,14 +1324,16 @@ static void ipath_ht_init_hwerrors(struct ipath_devdata *dd)
- 	val &= ~INFINIPATH_HWE_HTCMISCERR4;
- 
- 	/*
--	 * PLL ignored because MDIO interface has a logic problem
--	 * for reads, on Comstock and Ponderosa.  BRINGUP
-+	 * PLL ignored because unused MDIO interface has a logic problem
- 	 */
- 	if (dd->ipath_boardrev == 4 || dd->ipath_boardrev == 9)
- 		val &= ~INFINIPATH_HWE_SERDESPLLFAILED;
- 	dd->ipath_hwerrmask = val;
- }
- 
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/byteorder.h>
 +
++#include "nes.h"
 +
 +
- /**
-  * ipath_ht_bringup_serdes - bring up the serdes
-  * @dd: the infinipath device
-@@ -1284,16 +1405,6 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
- 	}
- 
- 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
--	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
--	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
--		val &= ~(INFINIPATH_XGXS_MDIOADDR_MASK <<
--			 INFINIPATH_XGXS_MDIOADDR_SHIFT);
--		/*
--		 * we use address 3
--		 */
--		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
--		change = 1;
--	}
- 	if (val & INFINIPATH_XGXS_RESET) {
- 		/* normally true after boot */
- 		val &= ~INFINIPATH_XGXS_RESET;
-@@ -1329,21 +1440,6 @@ static int ipath_ht_bringup_serdes(struct ipath_devdata *dd)
- 		   (unsigned long long)
- 		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
- 
--	if (!ipath_waitfor_mdio_cmdready(dd)) {
--		ipath_write_kreg(dd, dd->ipath_kregs->kr_mdio,
--				 ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
--						IPATH_MDIO_CTRL_XGXS_REG_8,
--						0));
--		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
--					   IPATH_MDIO_DATAVALID, &val))
--			ipath_dbg("Never got MDIO data for XGXS status "
--				  "read\n");
--		else
--			ipath_cdbg(VERBOSE, "MDIO Read reg8, "
--				   "'bank' 31 %x\n", (u32) val);
--	} else
--		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
--
- 	return ret;		/* for now, say we always succeeded */
- }
- 
-@@ -1396,6 +1492,7 @@ static void ipath_ht_put_tid(struct ipath_devdata *dd,
- 			pa |= lenvalid | INFINIPATH_RT_VALID;
- 		}
- 	}
 +
- 	writeq(pa, tidptr);
- }
- 
-@@ -1526,8 +1623,7 @@ static int ipath_ht_early_init(struct ipath_devdata *dd)
- 	}
- 
- 	ipath_get_eeprom_info(dd);
--	if (dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' &&
--		dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') {
-+	if (dd->ipath_boardrev == 5) {
- 		/*
- 		 * Later production QHT7040 has same changes as QHT7140, so
- 		 * can use GPIO interrupts.  They have serial #'s starting
-@@ -1602,6 +1698,210 @@ static void ipath_ht_free_irq(struct ipath_devdata *dd)
- 	dd->ipath_intconfig = 0;
- }
- 
-+static struct ipath_message_header *
-+ipath_ht_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
++static u16 nes_read16_eeprom(void __iomem *addr, u16 offset);
++
++u32 mh_detected;
++u32 mh_pauses_sent;
++
++/**
++ * nes_read_eeprom_values -
++ */
++int nes_read_eeprom_values(struct nes_device *nesdev, struct nes_adapter *nesadapter)
 +{
-+	return (struct ipath_message_header *)
-+		&rhf_addr[sizeof(u64) / sizeof(u32)];
++	u32 mac_addr_low;
++	u16 mac_addr_high;
++	u16 eeprom_data;
++	u16 eeprom_offset;
++	u16 next_section_address;
++	u16 sw_section_ver;
++	u8  major_ver = 0;
++	u8  minor_ver = 0;
++
++	/* TODO: deal with EEPROM endian issues */
++	if (nesadapter->firmware_eeprom_offset == 0) {
++		/* Read the EEPROM Parameters */
++		eeprom_data = nes_read16_eeprom(nesdev->regs, 0);
++		nes_debug(NES_DBG_HW, "EEPROM Offset 0  = 0x%04X\n", eeprom_data);
++		eeprom_offset = 2 + (((eeprom_data & 0x007f) << 3) <<
++				((eeprom_data & 0x0080) >> 7));
++		nes_debug(NES_DBG_HW, "Firmware Offset = 0x%04X\n", eeprom_offset);
++		nesadapter->firmware_eeprom_offset = eeprom_offset;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 4);
++		if (eeprom_data != 0x5746) {
++			nes_debug(NES_DBG_HW, "Not a valid Firmware Image = 0x%04X\n", eeprom_data);
++			return -1;
++		}
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		eeprom_offset += ((eeprom_data & 0x00ff) << 3) << ((eeprom_data & 0x0100) >> 8);
++		nes_debug(NES_DBG_HW, "Software Offset = 0x%04X\n", eeprom_offset);
++		nesadapter->software_eeprom_offset = eeprom_offset;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 4);
++		if (eeprom_data != 0x5753) {
++			printk("Not a valid Software Image = 0x%04X\n", eeprom_data);
++			return -1;
++		}
++		sw_section_ver = nes_read16_eeprom(nesdev->regs, nesadapter->software_eeprom_offset  + 6);
++		nes_debug(NES_DBG_HW, "Software section version number = 0x%04X\n",
++				sw_section_ver);
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section)  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		next_section_address = eeprom_offset + (((eeprom_data & 0x00ff) << 3) <<
++				((eeprom_data & 0x0100) >> 8));
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4);
++		if (eeprom_data != 0x414d) {
++			nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x414d but was 0x%04X\n",
++					eeprom_data);
++			goto no_fw_rev;
++		}
++		eeprom_offset = next_section_address;
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section)  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		next_section_address = eeprom_offset + (((eeprom_data & 0x00ff) << 3) <<
++				((eeprom_data & 0x0100) >> 8));
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4);
++		if (eeprom_data != 0x4f52) {
++			nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x4f52 but was 0x%04X\n",
++					eeprom_data);
++			goto no_fw_rev;
++		}
++		eeprom_offset = next_section_address;
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section)  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3);
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4);
++		if (eeprom_data != 0x5746) {
++			nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x5746 but was 0x%04X\n",
++					eeprom_data);
++			goto no_fw_rev;
++		}
++		eeprom_offset = next_section_address;
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section)  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3);
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4);
++		if (eeprom_data != 0x5753) {
++			nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x5753 but was 0x%04X\n",
++					eeprom_data);
++			goto no_fw_rev;
++		}
++		eeprom_offset = next_section_address;
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section)  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3);
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4);
++		if (eeprom_data != 0x414d) {
++			nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x414d but was 0x%04X\n",
++					eeprom_data);
++			goto no_fw_rev;
++		}
++		eeprom_offset = next_section_address;
++
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset + 2);
++		nes_debug(NES_DBG_HW, "EEPROM Offset %u (next section)  = 0x%04X\n",
++				eeprom_offset + 2, eeprom_data);
++		next_section_address = eeprom_offset + ((eeprom_data & 0x00ff) << 3);
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 4);
++		if (eeprom_data != 0x464e) {
++			nes_debug(NES_DBG_HW, "EEPROM Changed offset should be 0x464e but was 0x%04X\n",
++					eeprom_data);
++			goto no_fw_rev;
++		}
++		eeprom_data = nes_read16_eeprom(nesdev->regs, next_section_address + 8);
++		printk(PFX "Firmware version %u.%u\n", (u8)(eeprom_data>>8), (u8)eeprom_data);
++		major_ver = (u8)(eeprom_data >> 8);
++		minor_ver = (u8)(eeprom_data);
++
++		if (nes_drv_opt & NES_DRV_OPT_DISABLE_VIRT_WQ) {
++			nes_debug(NES_DBG_HW, "Virtual WQs have been disabled\n");
++		} else if (((major_ver == 2) && (minor_ver > 21)) || ((major_ver > 2) && (major_ver != 255))) {
++			nesadapter->virtwq = 1;
++		}
++		nesadapter->firmware_version = (((u32)(u8)(eeprom_data>>8))  <<  16) +
++				(u32)((u8)eeprom_data);
++
++no_fw_rev:
++		/* eeprom is valid */
++		eeprom_offset = nesadapter->software_eeprom_offset;
++		eeprom_offset += 8;
++		nesadapter->netdev_max = (u8)nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		mac_addr_high = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		mac_addr_low = (u32)nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		mac_addr_low <<= 16;
++		mac_addr_low += (u32)nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "Base MAC Address = 0x%04X%08X\n",
++				mac_addr_high, mac_addr_low);
++		nes_debug(NES_DBG_HW, "MAC Address count = %u\n", nesadapter->netdev_max);
++
++		nesadapter->mac_addr_low = mac_addr_low;
++		nesadapter->mac_addr_high = mac_addr_high;
++
++		/* Read the Phy Type array */
++		eeprom_offset += 10;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->phy_type[0] = (u8)(eeprom_data >> 8);
++		nesadapter->phy_type[1] = (u8)eeprom_data;
++
++		/* Read the port array */
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->phy_type[2] = (u8)(eeprom_data >> 8);
++		nesadapter->phy_type[3] = (u8)eeprom_data;
++		/* port_count is set by soft reset reg */
++		nes_debug(NES_DBG_HW, "port_count = %u, port 0 -> %u, port 1 -> %u,"
++				" port 2 -> %u, port 3 -> %u\n",
++				nesadapter->port_count,
++				nesadapter->phy_type[0], nesadapter->phy_type[1],
++				nesadapter->phy_type[2], nesadapter->phy_type[3]);
++
++		/* Read PD config array */
++		eeprom_offset += 10;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_size[0] = eeprom_data;
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_base[0] = eeprom_data;
++		nes_debug(NES_DBG_HW, "PD0 config, size=0x%04x, base=0x%04x\n",
++				nesadapter->pd_config_size[0], nesadapter->pd_config_base[0]);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_size[1] = eeprom_data;
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_base[1] = eeprom_data;
++		nes_debug(NES_DBG_HW, "PD1 config, size=0x%04x, base=0x%04x\n",
++				nesadapter->pd_config_size[1], nesadapter->pd_config_base[1]);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_size[2] = eeprom_data;
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_base[2] = eeprom_data;
++		nes_debug(NES_DBG_HW, "PD2 config, size=0x%04x, base=0x%04x\n",
++				nesadapter->pd_config_size[2], nesadapter->pd_config_base[2]);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_size[3] = eeprom_data;
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nesadapter->pd_config_base[3] = eeprom_data;
++		nes_debug(NES_DBG_HW, "PD3 config, size=0x%04x, base=0x%04x\n",
++				nesadapter->pd_config_size[3], nesadapter->pd_config_base[3]);
++
++		/* Read Rx Pool Size */
++		eeprom_offset += 22;   /* 46 */
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->rx_pool_size = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "rx_pool_size = 0x%08X\n", nesadapter->rx_pool_size);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->tx_pool_size = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "tx_pool_size = 0x%08X\n", nesadapter->tx_pool_size);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->rx_threshold = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "rx_threshold = 0x%08X\n", nesadapter->rx_threshold);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->tcp_timer_core_clk_divisor = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "tcp_timer_core_clk_divisor = 0x%08X\n",
++				nesadapter->tcp_timer_core_clk_divisor);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->iwarp_config = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "iwarp_config = 0x%08X\n", nesadapter->iwarp_config);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->cm_config = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "cm_config = 0x%08X\n", nesadapter->cm_config);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->sws_timer_config = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "sws_timer_config = 0x%08X\n", nesadapter->sws_timer_config);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->tcp_config1 = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "tcp_config1 = 0x%08X\n", nesadapter->tcp_config1);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->wqm_wat = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "wqm_wat = 0x%08X\n", nesadapter->wqm_wat);
++
++		eeprom_offset += 2;
++		eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		eeprom_offset += 2;
++		nesadapter->core_clock = (((u32)eeprom_data) << 16) +
++				nes_read16_eeprom(nesdev->regs, eeprom_offset);
++		nes_debug(NES_DBG_HW, "core_clock = 0x%08X\n", nesadapter->core_clock);
++
++		if ((sw_section_ver) && (nesadapter->hw_rev != NE020_REV)) {
++			eeprom_offset += 2;
++			eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++			nesadapter->phy_index[0] = (eeprom_data & 0xff00)>>8;
++			nesadapter->phy_index[1] = eeprom_data & 0x00ff;
++			eeprom_offset += 2;
++			eeprom_data = nes_read16_eeprom(nesdev->regs, eeprom_offset);
++			nesadapter->phy_index[2] = (eeprom_data & 0xff00)>>8;
++			nesadapter->phy_index[3] = eeprom_data & 0x00ff;
++		} else {
++			nesadapter->phy_index[0] = 4;
++			nesadapter->phy_index[1] = 5;
++			nesadapter->phy_index[2] = 6;
++			nesadapter->phy_index[3] = 7;
++		}
++		nes_debug(NES_DBG_HW, "Phy address map = 0 > %u,  1 > %u, 2 > %u, 3 > %u\n",
++			   nesadapter->phy_index[0],nesadapter->phy_index[1],
++			   nesadapter->phy_index[2],nesadapter->phy_index[3]);
++	}
++
++	return 0;
 +}
 +
-+static void ipath_ht_config_ports(struct ipath_devdata *dd, ushort cfgports)
++
++/**
++ * nes_read16_eeprom
++ */
++static u16 nes_read16_eeprom(void __iomem *addr, u16 offset)
 +{
-+	dd->ipath_portcnt =
-+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
-+	dd->ipath_p0_rcvegrcnt =
-+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
++	writel(NES_EEPROM_READ_REQUEST + (offset >> 1),
++			(void __iomem *)addr + NES_EEPROM_COMMAND);
++
++	do {
++	} while (readl((void __iomem *)addr + NES_EEPROM_COMMAND) &
++			NES_EEPROM_READ_REQUEST);
++
++	return readw((void __iomem *)addr + NES_EEPROM_DATA);
 +}
 +
-+static void ipath_ht_read_counters(struct ipath_devdata *dd,
-+				   struct infinipath_counters *cntrs)
++
++/**
++ * nes_write_1G_phy_reg
++ */
++void nes_write_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16 data)
 +{
-+	cntrs->LBIntCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt));
-+	cntrs->LBFlowStallCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt));
-+	cntrs->TxSDmaDescCnt = 0;
-+	cntrs->TxUnsupVLErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt));
-+	cntrs->TxDataPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt));
-+	cntrs->TxFlowPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt));
-+	cntrs->TxDwordCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt));
-+	cntrs->TxLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt));
-+	cntrs->TxMaxMinLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt));
-+	cntrs->TxUnderrunCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt));
-+	cntrs->TxFlowStallCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt));
-+	cntrs->TxDroppedPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt));
-+	cntrs->RxDroppedPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt));
-+	cntrs->RxDataPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt));
-+	cntrs->RxFlowPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt));
-+	cntrs->RxDwordCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt));
-+	cntrs->RxLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt));
-+	cntrs->RxMaxMinLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt));
-+	cntrs->RxICRCErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt));
-+	cntrs->RxVCRCErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt));
-+	cntrs->RxFlowCtrlErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt));
-+	cntrs->RxBadFormatCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt));
-+	cntrs->RxLinkProblemCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt));
-+	cntrs->RxEBPCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt));
-+	cntrs->RxLPCRCErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt));
-+	cntrs->RxBufOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt));
-+	cntrs->RxTIDFullErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt));
-+	cntrs->RxTIDValidErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt));
-+	cntrs->RxPKeyMismatchCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt));
-+	cntrs->RxP0HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt));
-+	cntrs->RxP1HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt));
-+	cntrs->RxP2HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt));
-+	cntrs->RxP3HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt));
-+	cntrs->RxP4HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt));
-+	cntrs->RxP5HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP5HdrEgrOvflCnt));
-+	cntrs->RxP6HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP6HdrEgrOvflCnt));
-+	cntrs->RxP7HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP7HdrEgrOvflCnt));
-+	cntrs->RxP8HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP8HdrEgrOvflCnt));
-+	cntrs->RxP9HdrEgrOvflCnt = 0;
-+	cntrs->RxP10HdrEgrOvflCnt = 0;
-+	cntrs->RxP11HdrEgrOvflCnt = 0;
-+	cntrs->RxP12HdrEgrOvflCnt = 0;
-+	cntrs->RxP13HdrEgrOvflCnt = 0;
-+	cntrs->RxP14HdrEgrOvflCnt = 0;
-+	cntrs->RxP15HdrEgrOvflCnt = 0;
-+	cntrs->RxP16HdrEgrOvflCnt = 0;
-+	cntrs->IBStatusChangeCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt));
-+	cntrs->IBLinkErrRecoveryCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt));
-+	cntrs->IBLinkDownedCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt));
-+	cntrs->IBSymbolErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt));
-+	cntrs->RxVL15DroppedPktCnt = 0;
-+	cntrs->RxOtherLocalPhyErrCnt = 0;
-+	cntrs->PcieRetryBufDiagQwordCnt = 0;
-+	cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs;
-+	cntrs->LocalLinkIntegrityErrCnt =
-+		(dd->ipath_flags & IPATH_GPIO_ERRINTRS) ?
-+		dd->ipath_lli_errs : dd->ipath_lli_errors;
-+	cntrs->RxVlErrCnt = 0;
-+	cntrs->RxDlidFltrCnt = 0;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 u32temp;
++	u32 counter;
++	unsigned long flags;
++
++	spin_lock_irqsave(&nesadapter->phy_lock, flags);
++
++	nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL,
++			0x50020000 | data | ((u32)phy_reg << 18) | ((u32)phy_addr << 23));
++	for (counter = 0; counter < 100 ; counter++) {
++		udelay(30);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS);
++		if (u32temp & 1) {
++			/* nes_debug(NES_DBG_PHY, "Phy interrupt status = 0x%X.\n", u32temp); */
++			nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1);
++			break;
++		}
++	}
++	if (!(u32temp & 1))
++		nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n",
++				u32temp);
++
++	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
 +}
 +
 +
-+/* no interrupt fallback for these chips */
-+static int ipath_ht_nointr_fallback(struct ipath_devdata *dd)
++/**
++ * nes_read_1G_phy_reg
++ * This routine only issues the read, the data must be read
++ * separately.
++ */
++void nes_read_1G_phy_reg(struct nes_device *nesdev, u8 phy_reg, u8 phy_addr, u16 *data)
 +{
-+	return 0;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 u32temp;
++	u32 counter;
++	unsigned long flags;
++
++	/* nes_debug(NES_DBG_PHY, "phy addr = %d, mac_index = %d\n",
++			phy_addr, nesdev->mac_index); */
++	spin_lock_irqsave(&nesadapter->phy_lock, flags);
++
++	nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL,
++			0x60020000 | ((u32)phy_reg << 18) | ((u32)phy_addr << 23));
++	for (counter = 0; counter < 100 ; counter++) {
++		udelay(30);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS);
++		if (u32temp & 1) {
++			/* nes_debug(NES_DBG_PHY, "Phy interrupt status = 0x%X.\n", u32temp); */
++			nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1);
++			break;
++		}
++	}
++	if (!(u32temp & 1)) {
++		nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n",
++				u32temp);
++		*data = 0xffff;
++	} else {
++		*data = (u16)nes_read_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL);
++	}
++	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
 +}
 +
 +
-+/*
-+ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
-+ * than resetting the IBC or external link state, and useful in some
-+ * cases to cause some retraining.  To do this right, we reset IBC
-+ * as well.
++/**
++ * nes_write_10G_phy_reg
 + */
-+static void ipath_ht_xgxs_reset(struct ipath_devdata *dd)
++void nes_write_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg,
++		u8 phy_addr, u16 data)
 +{
-+	u64 val, prev_val;
++	u32 dev_addr;
++	u32 port_addr;
++	u32 u32temp;
++	u32 counter;
 +
-+	prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
-+	val = prev_val | INFINIPATH_XGXS_RESET;
-+	prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-+			 dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
-+	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-+			 dd->ipath_control);
++	dev_addr = 1;
++	port_addr = phy_addr;
++
++	/* set address */
++	nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL,
++			0x00020000 | (u32)phy_reg | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23));
++	for (counter = 0; counter < 100 ; counter++) {
++		udelay(30);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS);
++		if (u32temp & 1) {
++			nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1);
++			break;
++		}
++	}
++	if (!(u32temp & 1))
++		nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n",
++				u32temp);
++
++	/* set data */
++	nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL,
++			0x10020000 | (u32)data | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23));
++	for (counter = 0; counter < 100 ; counter++) {
++		udelay(30);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS);
++		if (u32temp & 1) {
++			nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1);
++			break;
++		}
++	}
++	if (!(u32temp & 1))
++		nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n",
++				u32temp);
 +}
 +
 +
-+static int ipath_ht_get_ib_cfg(struct ipath_devdata *dd, int which)
++/**
++ * nes_read_10G_phy_reg
++ * This routine only issues the read, the data must be read
++ * separately.
++ */
++void nes_read_10G_phy_reg(struct nes_device *nesdev, u16 phy_reg, u8 phy_addr)
 +{
-+	int ret;
++	u32 dev_addr;
++	u32 port_addr;
++	u32 u32temp;
++	u32 counter;
 +
-+	switch (which) {
-+	case IPATH_IB_CFG_LWID:
-+		ret = dd->ipath_link_width_active;
-+		break;
-+	case IPATH_IB_CFG_SPD:
-+		ret = dd->ipath_link_speed_active;
-+		break;
-+	case IPATH_IB_CFG_LWID_ENB:
-+		ret = dd->ipath_link_width_enabled;
-+		break;
-+	case IPATH_IB_CFG_SPD_ENB:
-+		ret = dd->ipath_link_speed_enabled;
-+		break;
-+	default:
-+		ret =  -ENOTSUPP;
-+		break;
++	dev_addr = 1;
++	port_addr = phy_addr;
++
++	/* set address */
++	nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL,
++			0x00020000 | (u32)phy_reg | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23));
++	for (counter = 0; counter < 100 ; counter++) {
++		udelay(30);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS);
++		if (u32temp & 1) {
++			nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1);
++			break;
++		}
 +	}
-+	return ret;
++	if (!(u32temp & 1))
++		nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n",
++				u32temp);
++
++	/* issue read */
++	nes_write_indexed(nesdev, NES_IDX_MAC_MDIO_CONTROL,
++			0x30020000 | (((u32)dev_addr) << 18) | (((u32)port_addr) << 23));
++	for (counter = 0; counter < 100 ; counter++) {
++		udelay(30);
++		u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS);
++		if (u32temp & 1) {
++			nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS, 1);
++			break;
++		}
++	}
++	if (!(u32temp & 1))
++		nes_debug(NES_DBG_PHY, "Phy is not responding. interrupt status = 0x%X.\n",
++				u32temp);
 +}
 +
 +
-+/* we assume range checking is already done, if needed */
-+static int ipath_ht_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
++/**
++ * nes_get_cqp_request
++ */
++struct nes_cqp_request *nes_get_cqp_request(struct nes_device *nesdev)
 +{
-+	int ret = 0;
++	unsigned long flags;
++	struct nes_cqp_request *cqp_request = NULL;
 +
-+	if (which == IPATH_IB_CFG_LWID_ENB)
-+		dd->ipath_link_width_enabled = val;
-+	else if (which == IPATH_IB_CFG_SPD_ENB)
-+		dd->ipath_link_speed_enabled = val;
-+	else
-+		ret = -ENOTSUPP;
-+	return ret;
++	if (!list_empty(&nesdev->cqp_avail_reqs)) {
++		spin_lock_irqsave(&nesdev->cqp.lock, flags);
++		cqp_request = list_entry(nesdev->cqp_avail_reqs.next,
++				struct nes_cqp_request, list);
++		list_del_init(&cqp_request->list);
++		spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++	} else {
++		cqp_request = kzalloc(sizeof(struct nes_cqp_request), GFP_KERNEL);
++		if (cqp_request) {
++			cqp_request->dynamic = 1;
++			INIT_LIST_HEAD(&cqp_request->list);
++		}
++	}
++
++	if (cqp_request) {
++		init_waitqueue_head(&cqp_request->waitq);
++		cqp_request->waiting = 0;
++		cqp_request->request_done = 0;
++		cqp_request->callback = 0;
++		init_waitqueue_head(&cqp_request->waitq);
++		nes_debug(NES_DBG_CQP, "Got cqp request %p from the available list \n",
++				cqp_request);
++	} else
++		printk(KERN_ERR PFX "%s: Could not allocated a CQP request.\n",
++			   __FUNCTION__);
++
++	return cqp_request;
 +}
 +
 +
-+static void ipath_ht_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
++/**
++ * nes_post_cqp_request
++ */
++void nes_post_cqp_request(struct nes_device *nesdev,
++		struct nes_cqp_request *cqp_request, int ring_doorbell)
 +{
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	unsigned long flags;
++	u32 cqp_head;
++	u64 u64temp;
++
++	spin_lock_irqsave(&nesdev->cqp.lock, flags);
++
++	if (((((nesdev->cqp.sq_tail+(nesdev->cqp.sq_size*2))-nesdev->cqp.sq_head) &
++			(nesdev->cqp.sq_size - 1)) != 1)
++			&& (list_empty(&nesdev->cqp_pending_reqs))) {
++		cqp_head = nesdev->cqp.sq_head++;
++		nesdev->cqp.sq_head &= nesdev->cqp.sq_size-1;
++		cqp_wqe = &nesdev->cqp.sq_vbase[cqp_head];
++		memcpy(cqp_wqe, &cqp_request->cqp_wqe, sizeof(*cqp_wqe));
++		barrier();
++		u64temp = (unsigned long)cqp_request;
++		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_COMP_SCRATCH_LOW_IDX,
++				    u64temp);
++		nes_debug(NES_DBG_CQP, "CQP request (opcode 0x%02X), line 1 = 0x%08X put on CQPs SQ,"
++				" request = %p, cqp_head = %u, cqp_tail = %u, cqp_size = %u,"
++				" waiting = %d, refcount = %d.\n",
++				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
++				le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_ID_IDX]), cqp_request,
++				nesdev->cqp.sq_head, nesdev->cqp.sq_tail, nesdev->cqp.sq_size,
++				cqp_request->waiting, atomic_read(&cqp_request->refcount));
++		barrier();
++		if (ring_doorbell) {
++			/* Ring doorbell (1 WQEs) */
++			nes_write32(nesdev->regs+NES_WQE_ALLOC, 0x01800000 | nesdev->cqp.qp_id);
++		}
++
++		barrier();
++	} else {
++		nes_debug(NES_DBG_CQP, "CQP request %p (opcode 0x%02X), line 1 = 0x%08X"
++				" put on the pending queue.\n",
++				cqp_request,
++				le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_OPCODE_IDX])&0x3f,
++				le32_to_cpu(cqp_request->cqp_wqe.wqe_words[NES_CQP_WQE_ID_IDX]));
++		list_add_tail(&cqp_request->list, &nesdev->cqp_pending_reqs);
++	}
++
++	spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++
++	return;
 +}
 +
 +
-+static int ipath_ht_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++/**
++ * nes_arp_table
++ */
++int nes_arp_table(struct nes_device *nesdev, u32 ip_addr, u8 *mac_addr, u32 action)
 +{
-+	ipath_setup_ht_setextled(dd, ipath_ib_linkstate(dd, ibcs),
-+		ipath_ib_linktrstate(dd, ibcs));
-+	return 0;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	int arp_index;
++	int err = 0;
++
++	for (arp_index = 0; (u32) arp_index < nesadapter->arp_table_size; arp_index++) {
++		if (nesadapter->arp_table[arp_index].ip_addr == ip_addr)
++			break;
++	}
++
++	if (action == NES_ARP_ADD) {
++		if (arp_index != nesadapter->arp_table_size) {
++			return -1;
++		}
++
++		arp_index = 0;
++		err = nes_alloc_resource(nesadapter, nesadapter->allocated_arps,
++				nesadapter->arp_table_size, (u32 *)&arp_index, &nesadapter->next_arp_index);
++		if (err) {
++			nes_debug(NES_DBG_NETDEV, "nes_alloc_resource returned error = %u\n", err);
++			return err;
++		}
++		nes_debug(NES_DBG_NETDEV, "ADD, arp_index=%d\n", arp_index);
++
++		nesadapter->arp_table[arp_index].ip_addr = ip_addr;
++		memcpy(nesadapter->arp_table[arp_index].mac_addr, mac_addr, ETH_ALEN);
++		return arp_index;
++	}
++
++	/* DELETE or RESOLVE */
++	if (arp_index == nesadapter->arp_table_size) {
++		nes_debug(NES_DBG_NETDEV, "mac address not in ARP table - cannot delete or resolve\n");
++		return -1;
++	}
++
++	if (action == NES_ARP_RESOLVE) {
++		nes_debug(NES_DBG_NETDEV, "RESOLVE, arp_index=%d\n", arp_index);
++		return arp_index;
++	}
++
++	if (action == NES_ARP_DELETE) {
++		nes_debug(NES_DBG_NETDEV, "DELETE, arp_index=%d\n", arp_index);
++		nesadapter->arp_table[arp_index].ip_addr = 0;
++		memset(nesadapter->arp_table[arp_index].mac_addr, 0x00, ETH_ALEN);
++		nes_free_resource(nesadapter, nesadapter->allocated_arps, arp_index);
++		return arp_index;
++	}
++
++	return -1;
 +}
 +
 +
- /**
-  * ipath_init_iba6110_funcs - set up the chip-specific function pointers
-  * @dd: the infinipath device
-@@ -1626,22 +1926,19 @@ void ipath_init_iba6110_funcs(struct ipath_devdata *dd)
- 	dd->ipath_f_setextled = ipath_setup_ht_setextled;
- 	dd->ipath_f_get_base_info = ipath_ht_get_base_info;
- 	dd->ipath_f_free_irq = ipath_ht_free_irq;
--
--	/*
--	 * initialize chip-specific variables
--	 */
- 	dd->ipath_f_tidtemplate = ipath_ht_tidtemplate;
-+	dd->ipath_f_intr_fallback = ipath_ht_nointr_fallback;
-+	dd->ipath_f_get_msgheader = ipath_ht_get_msgheader;
-+	dd->ipath_f_config_ports = ipath_ht_config_ports;
-+	dd->ipath_f_read_counters = ipath_ht_read_counters;
-+	dd->ipath_f_xgxs_reset = ipath_ht_xgxs_reset;
-+	dd->ipath_f_get_ib_cfg = ipath_ht_get_ib_cfg;
-+	dd->ipath_f_set_ib_cfg = ipath_ht_set_ib_cfg;
-+	dd->ipath_f_config_jint = ipath_ht_config_jint;
-+	dd->ipath_f_ib_updown = ipath_ht_ib_updown;
- 
- 	/*
--	 * setup the register offsets, since they are different for each
--	 * chip
--	 */
--	dd->ipath_kregs = &ipath_ht_kregs;
--	dd->ipath_cregs = &ipath_ht_cregs;
--
--	/*
--	 * do very early init that is needed before ipath_f_bus is
--	 * called
-+	 * initialize chip-specific variables
- 	 */
- 	ipath_init_ht_variables(dd);
- }
-diff --git a/drivers/infiniband/hw/ipath/ipath_iba6120.c b/drivers/infiniband/hw/ipath/ipath_iba6120.c
-index 0103d6f..c7a2f50 100644
---- a/drivers/infiniband/hw/ipath/ipath_iba6120.c
-+++ b/drivers/infiniband/hw/ipath/ipath_iba6120.c
-@@ -145,10 +145,57 @@ struct _infinipath_do_not_use_kernel_regs {
- 	unsigned long long Reserved12;
- };
- 
--#define IPATH_KREG_OFFSET(field) (offsetof(struct \
--    _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
-+struct _infinipath_do_not_use_counters {
-+	__u64 LBIntCnt;
-+	__u64 LBFlowStallCnt;
-+	__u64 Reserved1;
-+	__u64 TxUnsupVLErrCnt;
-+	__u64 TxDataPktCnt;
-+	__u64 TxFlowPktCnt;
-+	__u64 TxDwordCnt;
-+	__u64 TxLenErrCnt;
-+	__u64 TxMaxMinLenErrCnt;
-+	__u64 TxUnderrunCnt;
-+	__u64 TxFlowStallCnt;
-+	__u64 TxDroppedPktCnt;
-+	__u64 RxDroppedPktCnt;
-+	__u64 RxDataPktCnt;
-+	__u64 RxFlowPktCnt;
-+	__u64 RxDwordCnt;
-+	__u64 RxLenErrCnt;
-+	__u64 RxMaxMinLenErrCnt;
-+	__u64 RxICRCErrCnt;
-+	__u64 RxVCRCErrCnt;
-+	__u64 RxFlowCtrlErrCnt;
-+	__u64 RxBadFormatCnt;
-+	__u64 RxLinkProblemCnt;
-+	__u64 RxEBPCnt;
-+	__u64 RxLPCRCErrCnt;
-+	__u64 RxBufOvflCnt;
-+	__u64 RxTIDFullErrCnt;
-+	__u64 RxTIDValidErrCnt;
-+	__u64 RxPKeyMismatchCnt;
-+	__u64 RxP0HdrEgrOvflCnt;
-+	__u64 RxP1HdrEgrOvflCnt;
-+	__u64 RxP2HdrEgrOvflCnt;
-+	__u64 RxP3HdrEgrOvflCnt;
-+	__u64 RxP4HdrEgrOvflCnt;
-+	__u64 RxP5HdrEgrOvflCnt;
-+	__u64 RxP6HdrEgrOvflCnt;
-+	__u64 RxP7HdrEgrOvflCnt;
-+	__u64 RxP8HdrEgrOvflCnt;
-+	__u64 Reserved6;
-+	__u64 Reserved7;
-+	__u64 IBStatusChangeCnt;
-+	__u64 IBLinkErrRecoveryCnt;
-+	__u64 IBLinkDownedCnt;
-+	__u64 IBSymbolErrCnt;
-+};
++/**
++ * nes_mh_fix
++ */
++void nes_mh_fix(unsigned long parm)
++{
++	unsigned long flags;
++	struct nes_device *nesdev = (struct nes_device *)parm;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_vnic *nesvnic;
++	u32 used_chunks_tx;
++	u32 temp_used_chunks_tx;
++	u32 temp_last_used_chunks_tx;
++	u32 used_chunks_mask;
++	u32 mac_tx_frames_low;
++	u32 mac_tx_frames_high;
++	u32 mac_tx_pauses;
++	u32 serdes_status;
++	u32 reset_value;
++	u32 tx_control;
++	u32 tx_config;
++	u32 tx_pause_quanta;
++	u32 rx_control;
++	u32 rx_config;
++	u32 mac_exact_match;
++	u32 mpp_debug;
++	u32 i=0;
++	u32 chunks_tx_progress = 0;
++
++	spin_lock_irqsave(&nesadapter->phy_lock, flags);
++	if ((nesadapter->mac_sw_state[0] != NES_MAC_SW_IDLE) || (nesadapter->mac_link_down[0])) {
++		spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++		goto no_mh_work;
++	}
++	nesadapter->mac_sw_state[0] = NES_MAC_SW_MH;
++	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++	do {
++		mac_tx_frames_low = nes_read_indexed(nesdev, NES_IDX_MAC_TX_FRAMES_LOW);
++		mac_tx_frames_high = nes_read_indexed(nesdev, NES_IDX_MAC_TX_FRAMES_HIGH);
++		mac_tx_pauses = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_FRAMES);
++		used_chunks_tx = nes_read_indexed(nesdev, NES_IDX_USED_CHUNKS_TX);
++		nesdev->mac_pause_frames_sent += mac_tx_pauses;
++		used_chunks_mask = 0;
++		temp_used_chunks_tx = used_chunks_tx;
++		temp_last_used_chunks_tx = nesdev->last_used_chunks_tx;
 +
-+#define IPATH_KREG_OFFSET(field) (offsetof( \
-+	struct _infinipath_do_not_use_kernel_regs, field) / sizeof(u64))
- #define IPATH_CREG_OFFSET(field) (offsetof( \
--    struct infinipath_counters, field) / sizeof(u64))
-+	struct _infinipath_do_not_use_counters, field) / sizeof(u64))
- 
- static const struct ipath_kregs ipath_pe_kregs = {
- 	.kr_control = IPATH_KREG_OFFSET(Control),
-@@ -282,6 +329,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
- #define INFINIPATH_HWE_PCIE0PLLFAILED       0x0800000000000000ULL
- #define INFINIPATH_HWE_SERDESPLLFAILED      0x1000000000000000ULL
- 
-+#define IBA6120_IBCS_LINKTRAININGSTATE_MASK 0xf
-+#define IBA6120_IBCS_LINKSTATE_SHIFT 4
++		if (nesdev->netdev[0]) {
++			nesvnic = netdev_priv(nesdev->netdev[0]);
++		} else {
++			break;
++		}
 +
- /* kr_extstatus bits */
- #define INFINIPATH_EXTS_FREQSEL 0x2
- #define INFINIPATH_EXTS_SERDESSEL 0x4
-@@ -296,6 +346,9 @@ static const struct ipath_cregs ipath_pe_cregs = {
- #define IPATH_GPIO_SCL (1ULL << \
- 	(_IPATH_GPIO_SCL_NUM+INFINIPATH_EXTC_GPIOOE_SHIFT))
- 
-+#define INFINIPATH_R_INTRAVAIL_SHIFT 16
-+#define INFINIPATH_R_TAILUPD_SHIFT 31
++		for (i=0; i<4; i++) {
++			used_chunks_mask <<= 8;
++			if (nesvnic->qp_nic_index[i] != 0xff) {
++				used_chunks_mask |= 0xff;
++				if ((temp_used_chunks_tx&0xff)<(temp_last_used_chunks_tx&0xff)) {
++					chunks_tx_progress = 1;
++				}
++			}
++			temp_used_chunks_tx >>= 8;
++			temp_last_used_chunks_tx >>= 8;
++		}
++		if ((mac_tx_frames_low) || (mac_tx_frames_high) ||
++			(!(used_chunks_tx&used_chunks_mask)) ||
++			(!(nesdev->last_used_chunks_tx&used_chunks_mask)) ||
++			(chunks_tx_progress) ) {
++			nesdev->last_used_chunks_tx = used_chunks_tx;
++			break;
++		}
++		nesdev->last_used_chunks_tx = used_chunks_tx;
++		barrier();
 +
- /* 6120 specific hardware errors... */
- static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
- 	INFINIPATH_HWE_MSG(PCIEPOISONEDTLP, "PCIe Poisoned TLP"),
-@@ -320,10 +373,28 @@ static const struct ipath_hwerror_msgs ipath_6120_hwerror_msgs[] = {
- 		        INFINIPATH_HWE_TXEMEMPARITYERR_PIOPBC) \
- 		        << INFINIPATH_HWE_TXEMEMPARITYERR_SHIFT)
- 
--static int ipath_pe_txe_recover(struct ipath_devdata *);
- static void ipath_pe_put_tid_2(struct ipath_devdata *, u64 __iomem *,
- 			       u32, unsigned long);
- 
-+/*
-+ * On platforms using this chip, and not having ordered WC stores, we
-+ * can get TXE parity errors due to speculative reads to the PIO buffers,
-+ * and this, due to a chip bug can result in (many) false parity error
-+ * reports.  So it's a debug print on those, and an info print on systems
-+ * where the speculative reads don't occur.
++		nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONTROL, 0x00000005);
++		mh_pauses_sent++;
++		mac_tx_pauses = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_FRAMES);
++		if (mac_tx_pauses) {
++			nesdev->mac_pause_frames_sent += mac_tx_pauses;
++			break;
++		}
++
++		tx_control = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONTROL);
++		tx_config = nes_read_indexed(nesdev, NES_IDX_MAC_TX_CONFIG);
++		tx_pause_quanta = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_QUANTA);
++		rx_control = nes_read_indexed(nesdev, NES_IDX_MAC_RX_CONTROL);
++		rx_config = nes_read_indexed(nesdev, NES_IDX_MAC_RX_CONFIG);
++		mac_exact_match = nes_read_indexed(nesdev, NES_IDX_MAC_EXACT_MATCH_BOTTOM);
++		mpp_debug = nes_read_indexed(nesdev, NES_IDX_MPP_DEBUG);
++
++		/* one last ditch effort to avoid a false positive */
++		mac_tx_pauses = nes_read_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_FRAMES);
++		if (mac_tx_pauses) {
++			nesdev->last_mac_tx_pauses = nesdev->mac_pause_frames_sent;
++			nes_debug(NES_DBG_HW, "failsafe caught slow outbound pause\n");
++			break;
++		}
++		mh_detected++;
++
++		nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONTROL, 0x00000000);
++		nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, 0x00000000);
++		reset_value = nes_read32(nesdev->regs+NES_SOFTWARE_RESET);
++
++		nes_write32(nesdev->regs+NES_SOFTWARE_RESET, reset_value | 0x0000001d);
++
++		while (((nes_read32(nesdev->regs+NES_SOFTWARE_RESET)
++				& 0x00000040) != 0x00000040) && (i++ < 5000)) {
++			/* mdelay(1); */
++		}
++
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_CONTROL0, 0x00000008);
++		serdes_status = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_COMMON_STATUS0);
++
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_EMP0, 0x000bdef7);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_TX_DRIVE0, 0x9ce73000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_MODE0, 0x0ff00000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_SIGDET0, 0x00000000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_BYPASS0, 0x00000000);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_LOOPBACK_CONTROL0, 0x00000000);
++		if (nesadapter->OneG_Mode) {
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0182222);
++		} else {
++			nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_CONTROL0, 0xf0042222);
++		}
++		serdes_status = nes_read_indexed(nesdev, NES_IDX_ETH_SERDES_RX_EQ_STATUS0);
++		nes_write_indexed(nesdev, NES_IDX_ETH_SERDES_CDR_CONTROL0, 0x000000ff);
++
++		nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONTROL, tx_control);
++		nes_write_indexed(nesdev, NES_IDX_MAC_TX_CONFIG, tx_config);
++		nes_write_indexed(nesdev, NES_IDX_MAC_TX_PAUSE_QUANTA, tx_pause_quanta);
++		nes_write_indexed(nesdev, NES_IDX_MAC_RX_CONTROL, rx_control);
++		nes_write_indexed(nesdev, NES_IDX_MAC_RX_CONFIG, rx_config);
++		nes_write_indexed(nesdev, NES_IDX_MAC_EXACT_MATCH_BOTTOM, mac_exact_match);
++		nes_write_indexed(nesdev, NES_IDX_MPP_DEBUG, mpp_debug);
++
++	} while (0);
++
++	nesadapter->mac_sw_state[0] = NES_MAC_SW_IDLE;
++no_mh_work:
++	nesdev->nesadapter->mh_timer.expires = jiffies + (HZ/5);
++	add_timer(&nesdev->nesadapter->mh_timer);
++}
++
++/**
++ * nes_clc
 + */
-+static void ipath_pe_txe_recover(struct ipath_devdata *dd)
++void nes_clc(unsigned long parm)
 +{
-+	if (ipath_unordered_wc())
-+		ipath_dbg("Recovering from TXE PIO parity error\n");
-+	else {
-+		++ipath_stats.sps_txeparity;
-+		dev_info(&dd->pcidev->dev,
-+			"Recovering from TXE PIO parity error\n");
++	unsigned long flags;
++	struct nes_device *nesdev = (struct nes_device *)parm;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++
++	spin_lock_irqsave(&nesadapter->phy_lock, flags);
++    nesadapter->link_interrupt_count[0] = 0;
++    nesadapter->link_interrupt_count[1] = 0;
++    nesadapter->link_interrupt_count[2] = 0;
++    nesadapter->link_interrupt_count[3] = 0;
++	spin_unlock_irqrestore(&nesadapter->phy_lock, flags);
++
++	nesadapter->lc_timer.expires = jiffies + 3600 * HZ;  /* 1 hour */
++	add_timer(&nesadapter->lc_timer);
++}
++
++
++/**
++ * nes_dump_mem
++ */
++void nes_dump_mem(unsigned int dump_debug_level, void *addr, int length)
++{
++	char  xlate[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
++		'a', 'b', 'c', 'd', 'e', 'f'};
++	char  *ptr;
++	char  hex_buf[80];
++	char  ascii_buf[20];
++	int   num_char;
++	int   num_ascii;
++	int   num_hex;
++
++	if (!(nes_debug_level & dump_debug_level)) {
++		return;
++	}
++
++	ptr = addr;
++	if (length > 0x100) {
++		nes_debug(dump_debug_level, "Length truncated from %x to %x\n", length, 0x100);
++		length = 0x100;
++	}
++	nes_debug(dump_debug_level, "Address=0x%p, length=0x%x (%d)\n", ptr, length, length);
++
++	memset(ascii_buf, 0, 20);
++	memset(hex_buf, 0, 80);
++
++	num_ascii = 0;
++	num_hex = 0;
++	for (num_char = 0; num_char < length; num_char++) {
++		if (num_ascii == 8) {
++			ascii_buf[num_ascii++] = ' ';
++			hex_buf[num_hex++] = '-';
++			hex_buf[num_hex++] = ' ';
++		}
++
++		if (*ptr < 0x20 || *ptr > 0x7e)
++			ascii_buf[num_ascii++] = '.';
++		else
++			ascii_buf[num_ascii++] = *ptr;
++		hex_buf[num_hex++] = xlate[((*ptr & 0xf0) >> 4)];
++		hex_buf[num_hex++] = xlate[*ptr & 0x0f];
++		hex_buf[num_hex++] = ' ';
++		ptr++;
++
++		if (num_ascii >= 17) {
++			/* output line and reset */
++			nes_debug(dump_debug_level, "   %s |  %s\n", hex_buf, ascii_buf);
++			memset(ascii_buf, 0, 20);
++			memset(hex_buf, 0, 80);
++			num_ascii = 0;
++			num_hex = 0;
++		}
++	}
++
++	/* output the rest */
++	if (num_ascii) {
++		while (num_ascii < 17) {
++			if (num_ascii == 8) {
++				hex_buf[num_hex++] = ' ';
++				hex_buf[num_hex++] = ' ';
++			}
++			hex_buf[num_hex++] = ' ';
++			hex_buf[num_hex++] = ' ';
++			hex_buf[num_hex++] = ' ';
++			num_ascii++;
++		}
++
++		nes_debug(dump_debug_level, "   %s |  %s\n", hex_buf, ascii_buf);
 +	}
 +}
+diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
+new file mode 100644
+index 0000000..ffd4b42
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_verbs.c
+@@ -0,0 +1,3917 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
 +
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/random.h>
++#include <linux/highmem.h>
++#include <asm/byteorder.h>
 +
- /**
-  * ipath_pe_handle_hwerrors - display hardware errors.
-  * @dd: the infinipath device
-@@ -403,35 +474,11 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
- 		 * occur if a processor speculative read is done to the PIO
- 		 * buffer while we are sending a packet, for example.
- 		 */
--		if ((hwerrs & TXE_PIO_PARITY) && ipath_pe_txe_recover(dd))
-+		if (hwerrs & TXE_PIO_PARITY) {
-+			ipath_pe_txe_recover(dd);
- 			hwerrs &= ~TXE_PIO_PARITY;
--		if (hwerrs) {
--			/*
--			 * if any set that we aren't ignoring only make the
--			 * complaint once, in case it's stuck or recurring,
--			 * and we get here multiple times
--			 * Force link down, so switch knows, and
--			 * LEDs are turned off
--			 */
--			if (dd->ipath_flags & IPATH_INITTED) {
--				ipath_set_linkstate(dd, IPATH_IB_LINKDOWN);
--				ipath_setup_pe_setextled(dd,
--					INFINIPATH_IBCS_L_STATE_DOWN,
--					INFINIPATH_IBCS_LT_STATE_DISABLED);
--				ipath_dev_err(dd, "Fatal Hardware Error (freeze "
--					      "mode), no longer usable, SN %.16s\n",
--						  dd->ipath_serial);
--				isfatal = 1;
--			}
--			/*
--			 * Mark as having had an error for driver, and also
--			 * for /sys and status word mapped to user programs.
--			 * This marks unit as not usable, until reset
--			 */
--			*dd->ipath_statusp &= ~IPATH_STATUS_IB_READY;
--			*dd->ipath_statusp |= IPATH_STATUS_HWERROR;
--			dd->ipath_flags &= ~IPATH_INITTED;
--		} else {
++#include <rdma/ib_verbs.h>
++#include <rdma/iw_cm.h>
++#include <rdma/ib_user_verbs.h>
++
++#include "nes.h"
++
++#include <rdma/ib_umem.h>
++
++atomic_t mod_qp_timouts;
++atomic_t qps_created;
++atomic_t sw_qps_destroyed;
++
++
++/**
++ * nes_alloc_mw
++ */
++static struct ib_mw *nes_alloc_mw(struct ib_pd *ibpd) {
++	unsigned long flags;
++	struct nes_pd *nespd = to_nespd(ibpd);
++	struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_cqp_request *cqp_request;
++	struct nes_mr *nesmr;
++	struct ib_mw *ibmw;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	int ret;
++	u32 stag;
++	u32 stag_index = 0;
++	u32 next_stag_index = 0;
++	u32 driver_key = 0;
++	u8 stag_key = 0;
++
++	get_random_bytes(&next_stag_index, sizeof(next_stag_index));
++	stag_key = (u8)next_stag_index;
++
++	driver_key = 0;
++
++	next_stag_index >>= 8;
++	next_stag_index %= nesadapter->max_mr;
++
++	ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
++			nesadapter->max_mr, &stag_index, &next_stag_index);
++	if (ret) {
++		return ERR_PTR(ret);
++	}
++
++	nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
++	if (!nesmr) {
++		nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++		return ERR_PTR(-ENOMEM);
++	}
++
++	stag = stag_index << 8;
++	stag |= driver_key;
++	stag += (u32)stag_key;
++
++	nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n",
++			stag, stag_index);
++
++	/* Register the region with the adapter */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		kfree(nesmr);
++		nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++		return ERR_PTR(-ENOMEM);
++	}
++
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
++
++	cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] =
++			cpu_to_le32( NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_RIGHTS_REMOTE_READ |
++			NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_VA_TO |
++			NES_CQP_STAG_REM_ACC_EN);
++
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"
++			" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++			stag, ret, cqp_request->major_code, cqp_request->minor_code);
++	if ((!ret) || (cqp_request->major_code)) {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
 +		}
-+		if (!hwerrs) {
- 			static u32 freeze_cnt;
- 
- 			freeze_cnt++;
-@@ -485,7 +532,7 @@ static void ipath_pe_handle_hwerrors(struct ipath_devdata *dd, char *msg,
- 
- 	if (hwerrs & INFINIPATH_HWE_SERDESPLLFAILED) {
- 		/*
--		 * If it occurs, it is left masked since the eternal
-+		 * If it occurs, it is left masked since the external
- 		 * interface is unused
- 		 */
- 		dd->ipath_hwerrmask &= ~INFINIPATH_HWE_SERDESPLLFAILED;
-@@ -563,6 +610,14 @@ static int ipath_pe_boardname(struct ipath_devdata *dd, char *name,
- 			dd->ipath_f_put_tid = ipath_pe_put_tid_2;
- 	}
- 
++		kfree(nesmr);
++		nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++		if (!ret) {
++			return ERR_PTR(-ETIME);
++		} else {
++			return ERR_PTR(-ENOMEM);
++		}
++	} else {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++	}
 +
-+	/*
-+	 * set here, not in ipath_init_*_funcs because we have to do
-+	 * it after we can read chip registers.
-+	 */
-+	dd->ipath_ureg_align =
-+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_pagealign);
++	nesmr->ibmw.rkey = stag;
++	nesmr->mode = IWNES_MEMREG_TYPE_MW;
++	ibmw = &nesmr->ibmw;
++	nesmr->pbl_4k = 0;
++	nesmr->pbls_used = 0;
 +
- 	return ret;
- }
- 
-@@ -667,17 +722,8 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
- 
- 	val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
- 	prev_val = val;
--	if (((val >> INFINIPATH_XGXS_MDIOADDR_SHIFT) &
--	     INFINIPATH_XGXS_MDIOADDR_MASK) != 3) {
--		val &=
--			~(INFINIPATH_XGXS_MDIOADDR_MASK <<
--			  INFINIPATH_XGXS_MDIOADDR_SHIFT);
--		/* MDIO address 3 */
--		val |= 3ULL << INFINIPATH_XGXS_MDIOADDR_SHIFT;
--	}
--	if (val & INFINIPATH_XGXS_RESET) {
-+	if (val & INFINIPATH_XGXS_RESET)
- 		val &= ~INFINIPATH_XGXS_RESET;
--	}
- 	if (((val >> INFINIPATH_XGXS_RX_POL_SHIFT) &
- 	     INFINIPATH_XGXS_RX_POL_MASK) != dd->ipath_rx_pol_inv ) {
- 		/* need to compensate for Tx inversion in partner */
-@@ -707,21 +753,6 @@ static int ipath_pe_bringup_serdes(struct ipath_devdata *dd)
- 		   (unsigned long long)
- 		   ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig));
- 
--	if (!ipath_waitfor_mdio_cmdready(dd)) {
--		ipath_write_kreg(
--			dd, dd->ipath_kregs->kr_mdio,
--			ipath_mdio_req(IPATH_MDIO_CMD_READ, 31,
--				       IPATH_MDIO_CTRL_XGXS_REG_8, 0));
--		if (ipath_waitfor_complete(dd, dd->ipath_kregs->kr_mdio,
--					   IPATH_MDIO_DATAVALID, &val))
--			ipath_dbg("Never got MDIO data for XGXS "
--				  "status read\n");
--		else
--			ipath_cdbg(VERBOSE, "MDIO Read reg8, "
--				   "'bank' 31 %x\n", (u32) val);
--	} else
--		ipath_dbg("Never got MDIO cmdready for XGXS status read\n");
--
- 	return ret;
- }
- 
-@@ -902,12 +933,27 @@ static int ipath_setup_pe_config(struct ipath_devdata *dd,
- 	else
- 		ipath_dev_err(dd, "Can't find PCI Express "
- 			      "capability!\n");
++	return ibmw;
++}
 +
-+	dd->ipath_link_width_supported = IB_WIDTH_1X | IB_WIDTH_4X;
-+	dd->ipath_link_speed_supported = IPATH_IB_SDR;
-+	dd->ipath_link_width_enabled = IB_WIDTH_4X;
-+	dd->ipath_link_speed_enabled = dd->ipath_link_speed_supported;
-+	/* these can't change for this chip, so set once */
-+	dd->ipath_link_width_active = dd->ipath_link_width_enabled;
-+	dd->ipath_link_speed_active = dd->ipath_link_speed_enabled;
- 	return 0;
- }
- 
- static void ipath_init_pe_variables(struct ipath_devdata *dd)
- {
- 	/*
-+	 * setup the register offsets, since they are different for each
-+	 * chip
-+	 */
-+	dd->ipath_kregs = &ipath_pe_kregs;
-+	dd->ipath_cregs = &ipath_pe_cregs;
 +
-+	/*
- 	 * bits for selecting i2c direction and values,
- 	 * used for I2C serial flash
- 	 */
-@@ -916,6 +962,43 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
- 	dd->ipath_gpio_sda = IPATH_GPIO_SDA;
- 	dd->ipath_gpio_scl = IPATH_GPIO_SCL;
- 
-+	/*
-+	 * Fill in data for field-values that change in newer chips.
-+	 * We dynamically specify only the mask for LINKTRAININGSTATE
-+	 * and only the shift for LINKSTATE, as they are the only ones
-+	 * that change.  Also precalculate the 3 link states of interest
-+	 * and the combined mask.
-+	 */
-+	dd->ibcs_ls_shift = IBA6120_IBCS_LINKSTATE_SHIFT;
-+	dd->ibcs_lts_mask = IBA6120_IBCS_LINKTRAININGSTATE_MASK;
-+	dd->ibcs_mask = (INFINIPATH_IBCS_LINKSTATE_MASK <<
-+		dd->ibcs_ls_shift) | dd->ibcs_lts_mask;
-+	dd->ib_init = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
-+		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
-+		(INFINIPATH_IBCS_L_STATE_INIT << dd->ibcs_ls_shift);
-+	dd->ib_arm = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
-+		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
-+		(INFINIPATH_IBCS_L_STATE_ARM << dd->ibcs_ls_shift);
-+	dd->ib_active = (INFINIPATH_IBCS_LT_STATE_LINKUP <<
-+		INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) |
-+		(INFINIPATH_IBCS_L_STATE_ACTIVE << dd->ibcs_ls_shift);
++/**
++ * nes_dealloc_mw
++ */
++static int nes_dealloc_mw(struct ib_mw *ibmw)
++{
++	struct nes_mr *nesmr = to_nesmw(ibmw);
++	struct nes_vnic *nesvnic = to_nesvnic(ibmw->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_cqp_request *cqp_request;
++	int err = 0;
++	unsigned long flags;
++	int ret;
 +
-+	/*
-+	 * Fill in data for ibcc field-values that change in newer chips.
-+	 * We dynamically specify only the mask for LINKINITCMD
-+	 * and only the shift for LINKCMD and MAXPKTLEN, as they are
-+	 * the only ones that change.
-+	 */
-+	dd->ibcc_lic_mask = INFINIPATH_IBCC_LINKINITCMD_MASK;
-+	dd->ibcc_lc_shift = INFINIPATH_IBCC_LINKCMD_SHIFT;
-+	dd->ibcc_mpl_shift = INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
++	/* Deallocate the window with the adapter */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
++		return -ENOMEM;
++	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, NES_CQP_DEALLOCATE_STAG);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ibmw->rkey);
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X to complete.\n",
++			ibmw->rkey);
++	ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_MR, "Deallocate STag completed, wait_event_timeout ret = %u,"
++			" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++			ret, cqp_request->major_code, cqp_request->minor_code);
++	if ((!ret) || (cqp_request->major_code)) {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++		if (!ret) {
++			err = -ETIME;
++		} else {
++			err = -EIO;
++		}
++	} else {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++	}
 +
-+	/* Fill in shifts for RcvCtrl. */
-+	dd->ipath_r_portenable_shift = INFINIPATH_R_PORTENABLE_SHIFT;
-+	dd->ipath_r_intravail_shift = INFINIPATH_R_INTRAVAIL_SHIFT;
-+	dd->ipath_r_tailupd_shift = INFINIPATH_R_TAILUPD_SHIFT;
-+	dd->ipath_r_portcfg_shift = 0; /* Not on IBA6120 */
++	nes_free_resource(nesadapter, nesadapter->allocated_mrs,
++			(ibmw->rkey & 0x0fffff00) >> 8);
++	kfree(nesmr);
 +
- 	/* variables for sanity checking interrupt and errors */
- 	dd->ipath_hwe_bitsextant =
- 		(INFINIPATH_HWE_RXEMEMPARITYERR_MASK <<
-@@ -963,6 +1046,8 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
- 
- 	dd->ipath_i_rcvavail_mask = INFINIPATH_I_RCVAVAIL_MASK;
- 	dd->ipath_i_rcvurg_mask = INFINIPATH_I_RCVURG_MASK;
-+	dd->ipath_i_rcvavail_shift = INFINIPATH_I_RCVAVAIL_SHIFT;
-+	dd->ipath_i_rcvurg_shift = INFINIPATH_I_RCVURG_SHIFT;
- 
- 	/*
- 	 * EEPROM error log 0 is TXE Parity errors. 1 is RXE Parity.
-@@ -984,6 +1069,7 @@ static void ipath_init_pe_variables(struct ipath_devdata *dd)
- 		INFINIPATH_E_INVALIDADDR | INFINIPATH_E_RESET;
- 
- 
-+	dd->delay_mult = 2; /* SDR, 4X, can't change */
- }
- 
- /* setup the MSI stuff again after a reset.  I'd like to just call
-@@ -1289,6 +1375,9 @@ static int ipath_pe_early_init(struct ipath_devdata *dd)
- 	 */
- 	dd->ipath_rcvhdrentsize = 24;
- 	dd->ipath_rcvhdrsize = IPATH_DFLT_RCVHDRSIZE;
-+	dd->ipath_rhf_offset = 0;
-+	dd->ipath_egrtidbase = (u64 __iomem *)
-+		((char __iomem *) dd->ipath_kregbase + dd->ipath_rcvegrbase);
- 
- 	/*
- 	 * To truly support a 4KB MTU (for usermode), we need to
-@@ -1359,34 +1448,204 @@ static void ipath_pe_free_irq(struct ipath_devdata *dd)
- 	dd->ipath_irq = 0;
- }
- 
++	return err;
++}
 +
-+static struct ipath_message_header *
-+ipath_pe_get_msgheader(struct ipath_devdata *dd, __le32 *rhf_addr)
++
++/**
++ * nes_bind_mw
++ */
++static int nes_bind_mw(struct ib_qp *ibqp, struct ib_mw *ibmw,
++		struct ib_mw_bind *ibmw_bind)
 +{
-+	return (struct ipath_message_header *)
-+		&rhf_addr[sizeof(u64) / sizeof(u32)];
++	u64 u64temp;
++	struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	/* struct nes_mr *nesmr = to_nesmw(ibmw); */
++	struct nes_qp *nesqp = to_nesqp(ibqp);
++	struct nes_hw_qp_wqe *wqe;
++	unsigned long flags = 0;
++	u32 head;
++	u32 wqe_misc = 0;
++	u32 qsize;
++
++	if (nesqp->ibqp_state > IB_QPS_RTS)
++		return -EINVAL;
++
++		spin_lock_irqsave(&nesqp->lock, flags);
++
++	head = nesqp->hwqp.sq_head;
++	qsize = nesqp->hwqp.sq_tail;
++
++	/* Check for SQ overflow */
++	if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
++			spin_unlock_irqrestore(&nesqp->lock, flags);
++		return -EINVAL;
++	}
++
++	wqe = &nesqp->hwqp.sq_vbase[head];
++	/* nes_debug(NES_DBG_MR, "processing sq wqe at %p, head = %u.\n", wqe, head); */
++	nes_fill_init_qp_wqe(wqe, nesqp, head);
++	u64temp = ibmw_bind->wr_id;
++	set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX, u64temp);
++	wqe_misc = NES_IWARP_SQ_OP_BIND;
++
++	wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
++
++	if (ibmw_bind->send_flags & IB_SEND_SIGNALED)
++		wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;
++
++	if (ibmw_bind->mw_access_flags & IB_ACCESS_REMOTE_WRITE) {
++		wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE;
++	}
++	if (ibmw_bind->mw_access_flags & IB_ACCESS_REMOTE_READ) {
++		wqe_misc |= NES_CQP_STAG_RIGHTS_REMOTE_READ;
++	}
++
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_MISC_IDX, wqe_misc);
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MR_IDX, ibmw_bind->mr->lkey);
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_MW_IDX, ibmw->rkey);
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_LENGTH_LOW_IDX,
++			ibmw_bind->length);
++	wqe->wqe_words[NES_IWARP_SQ_BIND_WQE_LENGTH_HIGH_IDX] = 0;
++	u64temp = (u64)ibmw_bind->addr;
++	set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_BIND_WQE_VA_FBO_LOW_IDX, u64temp);
++
++	head++;
++	if (head >= qsize)
++		head = 0;
++
++	nesqp->hwqp.sq_head = head;
++	barrier();
++
++	nes_write32(nesdev->regs+NES_WQE_ALLOC,
++			(1 << 24) | 0x00800000 | nesqp->hwqp.qp_id);
++
++		spin_unlock_irqrestore(&nesqp->lock, flags);
++
++	return 0;
 +}
 +
-+static void ipath_pe_config_ports(struct ipath_devdata *dd, ushort cfgports)
++
++/**
++ * nes_alloc_fmr
++ */
++static struct ib_fmr *nes_alloc_fmr(struct ib_pd *ibpd,
++		int ibmr_access_flags,
++		struct ib_fmr_attr *ibfmr_attr)
 +{
-+	dd->ipath_portcnt =
-+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
-+	dd->ipath_p0_rcvegrcnt =
-+		ipath_read_kreg32(dd, dd->ipath_kregs->kr_rcvegrcnt);
++	unsigned long flags;
++	struct nes_pd *nespd = to_nespd(ibpd);
++	struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_fmr *nesfmr;
++	struct nes_cqp_request *cqp_request;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	int ret;
++	u32 stag;
++	u32 stag_index = 0;
++	u32 next_stag_index = 0;
++	u32 driver_key = 0;
++	u32 opcode = 0;
++	u8 stag_key = 0;
++	int i=0;
++	struct nes_vpbl vpbl;
++
++	get_random_bytes(&next_stag_index, sizeof(next_stag_index));
++	stag_key = (u8)next_stag_index;
++
++	driver_key = 0;
++
++	next_stag_index >>= 8;
++	next_stag_index %= nesadapter->max_mr;
++
++	ret = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
++			nesadapter->max_mr, &stag_index, &next_stag_index);
++	if (ret) {
++		goto failed_resource_alloc;
++	}
++
++	nesfmr = kzalloc(sizeof(*nesfmr), GFP_KERNEL);
++	if (!nesfmr) {
++		ret = -ENOMEM;
++		goto failed_fmr_alloc;
++	}
++
++	nesfmr->nesmr.mode = IWNES_MEMREG_TYPE_FMR;
++	if (ibfmr_attr->max_pages == 1) {
++		/* use zero length PBL */
++		nesfmr->nesmr.pbl_4k = 0;
++		nesfmr->nesmr.pbls_used = 0;
++	} else if (ibfmr_attr->max_pages <= 32) {
++		/* use PBL 256 */
++		nesfmr->nesmr.pbl_4k = 0;
++		nesfmr->nesmr.pbls_used = 1;
++	} else if (ibfmr_attr->max_pages <= 512) {
++		/* use 4K PBLs */
++		nesfmr->nesmr.pbl_4k = 1;
++		nesfmr->nesmr.pbls_used = 1;
++	} else {
++		/* use two level 4K PBLs */
++		/* add support for two level 256B PBLs */
++		nesfmr->nesmr.pbl_4k = 1;
++		nesfmr->nesmr.pbls_used = 1 + (ibfmr_attr->max_pages >> 9) +
++				((ibfmr_attr->max_pages & 511) ? 1 : 0);
++	}
++	/* Register the region with the adapter */
++	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++
++	/* track PBL resources */
++	if (nesfmr->nesmr.pbls_used != 0) {
++		if (nesfmr->nesmr.pbl_4k) {
++			if (nesfmr->nesmr.pbls_used > nesadapter->free_4kpbl) {
++				spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				ret = -ENOMEM;
++				goto failed_vpbl_alloc;
++			} else {
++				nesadapter->free_4kpbl -= nesfmr->nesmr.pbls_used;
++			}
++		} else {
++			if (nesfmr->nesmr.pbls_used > nesadapter->free_256pbl) {
++				spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				ret = -ENOMEM;
++				goto failed_vpbl_alloc;
++			} else {
++				nesadapter->free_256pbl -= nesfmr->nesmr.pbls_used;
++			}
++		}
++	}
++
++	/* one level pbl */
++	if (nesfmr->nesmr.pbls_used == 0) {
++		nesfmr->root_vpbl.pbl_vbase = NULL;
++		nes_debug(NES_DBG_MR,  "zero level pbl \n");
++	} else if (nesfmr->nesmr.pbls_used == 1) {
++		/* can change it to kmalloc & dma_map_single */
++		nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
++				&nesfmr->root_vpbl.pbl_pbase);
++		if (!nesfmr->root_vpbl.pbl_vbase) {
++			spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++			ret = -ENOMEM;
++			goto failed_vpbl_alloc;
++		}
++		nesfmr->leaf_pbl_cnt = 0;
++		nes_debug(NES_DBG_MR, "one level pbl, root_vpbl.pbl_vbase=%p \n",
++				nesfmr->root_vpbl.pbl_vbase);
++	}
++	/* two level pbl */
++	else {
++		nesfmr->root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192,
++				&nesfmr->root_vpbl.pbl_pbase);
++		if (!nesfmr->root_vpbl.pbl_vbase) {
++			spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++			ret = -ENOMEM;
++			goto failed_vpbl_alloc;
++		}
++
++		nesfmr->root_vpbl.leaf_vpbl = kzalloc(sizeof(*nesfmr->root_vpbl.leaf_vpbl)*1024, GFP_KERNEL);
++		if (!nesfmr->root_vpbl.leaf_vpbl) {
++			spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++			ret = -ENOMEM;
++			goto failed_leaf_vpbl_alloc;
++		}
++
++		nesfmr->leaf_pbl_cnt = nesfmr->nesmr.pbls_used-1;
++		nes_debug(NES_DBG_MR, "two level pbl, root_vpbl.pbl_vbase=%p"
++				" leaf_pbl_cnt=%d root_vpbl.leaf_vpbl=%p\n",
++				nesfmr->root_vpbl.pbl_vbase, nesfmr->leaf_pbl_cnt, nesfmr->root_vpbl.leaf_vpbl);
++
++		for (i=0; i<nesfmr->leaf_pbl_cnt; i++)
++			nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase = NULL;
++
++		for (i=0; i<nesfmr->leaf_pbl_cnt; i++) {
++			vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
++					&vpbl.pbl_pbase);
++
++			if (!vpbl.pbl_vbase) {
++				ret = -ENOMEM;
++				spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				goto failed_leaf_vpbl_pages_alloc;
++			}
++
++			nesfmr->root_vpbl.pbl_vbase[i].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase);
++			nesfmr->root_vpbl.pbl_vbase[i].pa_high = cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32)));
++			nesfmr->root_vpbl.leaf_vpbl[i] = vpbl;
++
++			nes_debug(NES_DBG_MR, "pbase_low=0x%x, pbase_high=0x%x, vpbl=%p\n",
++					nesfmr->root_vpbl.pbl_vbase[i].pa_low,
++					nesfmr->root_vpbl.pbl_vbase[i].pa_high,
++					&nesfmr->root_vpbl.leaf_vpbl[i]);
++		}
++	}
++	nesfmr->ib_qp = NULL;
++	nesfmr->access_rights =0;
++
++	stag = stag_index << 8;
++	stag |= driver_key;
++	stag += (u32)stag_key;
++
++	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
++		ret = -ENOMEM;
++		goto failed_leaf_vpbl_pages_alloc;
++	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
++
++	nes_debug(NES_DBG_MR, "Registering STag 0x%08X, index = 0x%08X\n",
++			stag, stag_index);
++
++	opcode = NES_CQP_ALLOCATE_STAG | NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR;
++
++	if (nesfmr->nesmr.pbl_4k == 1)
++		opcode |= NES_CQP_STAG_PBL_BLK_SIZE;
++
++	if (ibmr_access_flags & IB_ACCESS_REMOTE_WRITE) {
++		opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE |
++				NES_CQP_STAG_RIGHTS_LOCAL_WRITE | NES_CQP_STAG_REM_ACC_EN;
++		nesfmr->access_rights |=
++				NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_RIGHTS_LOCAL_WRITE |
++				NES_CQP_STAG_REM_ACC_EN;
++	}
++
++	if (ibmr_access_flags & IB_ACCESS_REMOTE_READ) {
++		opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ |
++				NES_CQP_STAG_RIGHTS_LOCAL_READ | NES_CQP_STAG_REM_ACC_EN;
++		nesfmr->access_rights |=
++				NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_RIGHTS_LOCAL_READ |
++				NES_CQP_STAG_REM_ACC_EN;
++	}
++
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX, (nespd->pd_id & 0x00007fff));
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
++
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX] =
++			cpu_to_le32((nesfmr->nesmr.pbls_used>1) ?
++			(nesfmr->nesmr.pbls_used-1) : nesfmr->nesmr.pbls_used);
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"
++			" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++			stag, ret, cqp_request->major_code, cqp_request->minor_code);
++
++	if ((!ret) || (cqp_request->major_code)) {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++		ret = (!ret) ? -ETIME : -EIO;
++		goto failed_leaf_vpbl_pages_alloc;
++	} else {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++	}
++
++	nesfmr->nesmr.ibfmr.lkey = stag;
++	nesfmr->nesmr.ibfmr.rkey = stag;
++	nesfmr->attr = *ibfmr_attr;
++
++	return &nesfmr->nesmr.ibfmr;
++
++	failed_leaf_vpbl_pages_alloc:
++	/* unroll all allocated pages */
++	for (i=0; i<nesfmr->leaf_pbl_cnt; i++) {
++		if (nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase) {
++			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase,
++					nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase);
++		}
++	}
++	if (nesfmr->root_vpbl.leaf_vpbl)
++		kfree(nesfmr->root_vpbl.leaf_vpbl);
++
++	failed_leaf_vpbl_alloc:
++	if (nesfmr->leaf_pbl_cnt == 0) {
++		if (nesfmr->root_vpbl.pbl_vbase)
++			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase,
++					nesfmr->root_vpbl.pbl_pbase);
++	} else
++		pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase,
++				nesfmr->root_vpbl.pbl_pbase);
++
++	failed_vpbl_alloc:
++	kfree(nesfmr);
++
++	failed_fmr_alloc:
++	nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++
++	failed_resource_alloc:
++	return ERR_PTR(ret);
 +}
 +
-+static void ipath_pe_read_counters(struct ipath_devdata *dd,
-+				   struct infinipath_counters *cntrs)
++
++/**
++ * nes_dealloc_fmr
++ */
++static int nes_dealloc_fmr(struct ib_fmr *ibfmr)
 +{
-+	cntrs->LBIntCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBIntCnt));
-+	cntrs->LBFlowStallCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(LBFlowStallCnt));
-+	cntrs->TxSDmaDescCnt = 0;
-+	cntrs->TxUnsupVLErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnsupVLErrCnt));
-+	cntrs->TxDataPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDataPktCnt));
-+	cntrs->TxFlowPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowPktCnt));
-+	cntrs->TxDwordCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDwordCnt));
-+	cntrs->TxLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxLenErrCnt));
-+	cntrs->TxMaxMinLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxMaxMinLenErrCnt));
-+	cntrs->TxUnderrunCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxUnderrunCnt));
-+	cntrs->TxFlowStallCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxFlowStallCnt));
-+	cntrs->TxDroppedPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(TxDroppedPktCnt));
-+	cntrs->RxDroppedPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDroppedPktCnt));
-+	cntrs->RxDataPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDataPktCnt));
-+	cntrs->RxFlowPktCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowPktCnt));
-+	cntrs->RxDwordCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxDwordCnt));
-+	cntrs->RxLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLenErrCnt));
-+	cntrs->RxMaxMinLenErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxMaxMinLenErrCnt));
-+	cntrs->RxICRCErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxICRCErrCnt));
-+	cntrs->RxVCRCErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxVCRCErrCnt));
-+	cntrs->RxFlowCtrlErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxFlowCtrlErrCnt));
-+	cntrs->RxBadFormatCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBadFormatCnt));
-+	cntrs->RxLinkProblemCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLinkProblemCnt));
-+	cntrs->RxEBPCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxEBPCnt));
-+	cntrs->RxLPCRCErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxLPCRCErrCnt));
-+	cntrs->RxBufOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxBufOvflCnt));
-+	cntrs->RxTIDFullErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDFullErrCnt));
-+	cntrs->RxTIDValidErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxTIDValidErrCnt));
-+	cntrs->RxPKeyMismatchCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxPKeyMismatchCnt));
-+	cntrs->RxP0HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP0HdrEgrOvflCnt));
-+	cntrs->RxP1HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP1HdrEgrOvflCnt));
-+	cntrs->RxP2HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP2HdrEgrOvflCnt));
-+	cntrs->RxP3HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP3HdrEgrOvflCnt));
-+	cntrs->RxP4HdrEgrOvflCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(RxP4HdrEgrOvflCnt));
-+	cntrs->RxP5HdrEgrOvflCnt = 0;
-+	cntrs->RxP6HdrEgrOvflCnt = 0;
-+	cntrs->RxP7HdrEgrOvflCnt = 0;
-+	cntrs->RxP8HdrEgrOvflCnt = 0;
-+	cntrs->RxP9HdrEgrOvflCnt = 0;
-+	cntrs->RxP10HdrEgrOvflCnt = 0;
-+	cntrs->RxP11HdrEgrOvflCnt = 0;
-+	cntrs->RxP12HdrEgrOvflCnt = 0;
-+	cntrs->RxP13HdrEgrOvflCnt = 0;
-+	cntrs->RxP14HdrEgrOvflCnt = 0;
-+	cntrs->RxP15HdrEgrOvflCnt = 0;
-+	cntrs->RxP16HdrEgrOvflCnt = 0;
-+	cntrs->IBStatusChangeCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBStatusChangeCnt));
-+	cntrs->IBLinkErrRecoveryCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkErrRecoveryCnt));
-+	cntrs->IBLinkDownedCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBLinkDownedCnt));
-+	cntrs->IBSymbolErrCnt =
-+		ipath_snap_cntr(dd, IPATH_CREG_OFFSET(IBSymbolErrCnt));
-+	cntrs->RxVL15DroppedPktCnt = 0;
-+	cntrs->RxOtherLocalPhyErrCnt = 0;
-+	cntrs->PcieRetryBufDiagQwordCnt = 0;
-+	cntrs->ExcessBufferOvflCnt = dd->ipath_overrun_thresh_errs;
-+	cntrs->LocalLinkIntegrityErrCnt = dd->ipath_lli_errs;
-+	cntrs->RxVlErrCnt = 0;
-+	cntrs->RxDlidFltrCnt = 0;
++	struct nes_mr *nesmr = to_nesmr_from_ibfmr(ibfmr);
++	struct nes_fmr *nesfmr = to_nesfmr(nesmr);
++	struct nes_vnic *nesvnic = to_nesvnic(ibfmr->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_mr temp_nesmr = *nesmr;
++	int i = 0;
++
++	temp_nesmr.ibmw.device = ibfmr->device;
++	temp_nesmr.ibmw.pd = ibfmr->pd;
++	temp_nesmr.ibmw.rkey = ibfmr->rkey;
++	temp_nesmr.ibmw.uobject = NULL;
++
++	/* free the resources */
++	if (nesfmr->leaf_pbl_cnt == 0) {
++		/* single PBL case */
++		if (nesfmr->root_vpbl.pbl_vbase)
++			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.pbl_vbase,
++					nesfmr->root_vpbl.pbl_pbase);
++	} else {
++		for (i = 0; i < nesfmr->leaf_pbl_cnt; i++) {
++			pci_free_consistent(nesdev->pcidev, 4096, nesfmr->root_vpbl.leaf_vpbl[i].pbl_vbase,
++					nesfmr->root_vpbl.leaf_vpbl[i].pbl_pbase);
++		}
++		kfree(nesfmr->root_vpbl.leaf_vpbl);
++		pci_free_consistent(nesdev->pcidev, 8192, nesfmr->root_vpbl.pbl_vbase,
++				nesfmr->root_vpbl.pbl_pbase);
++	}
++
++	return nes_dealloc_mw(&temp_nesmr.ibmw);
 +}
 +
 +
-+/* no interrupt fallback for these chips */
-+static int ipath_pe_nointr_fallback(struct ipath_devdata *dd)
++/**
++ * nes_map_phys_fmr
++ */
++static int nes_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list,
++		int list_len, u64 iova)
 +{
 +	return 0;
 +}
 +
 +
- /*
-- * On platforms using this chip, and not having ordered WC stores, we
-- * can get TXE parity errors due to speculative reads to the PIO buffers,
-- * and this, due to a chip bug can result in (many) false parity error
-- * reports.  So it's a debug print on those, and an info print on systems
-- * where the speculative reads don't occur.
-- * Because we can get lots of false errors, we have no upper limit
-- * on recovery attempts on those platforms.
-+ * reset the XGXS (between serdes and IBC).  Slightly less intrusive
-+ * than resetting the IBC or external link state, and useful in some
-+ * cases to cause some retraining.  To do this right, we reset IBC
-+ * as well.
-  */
--static int ipath_pe_txe_recover(struct ipath_devdata *dd)
-+static void ipath_pe_xgxs_reset(struct ipath_devdata *dd)
- {
--	if (ipath_unordered_wc())
--		ipath_dbg("Recovering from TXE PIO parity error\n");
--	else {
--		int cnt = ++ipath_stats.sps_txeparity;
--		if (cnt >= IPATH_MAX_PARITY_ATTEMPTS)  {
--			if (cnt == IPATH_MAX_PARITY_ATTEMPTS)
--				ipath_dev_err(dd,
--					"Too many attempts to recover from "
--					"TXE parity, giving up\n");
--			return 0;
--		}
--		dev_info(&dd->pcidev->dev,
--			"Recovering from TXE PIO parity error\n");
-+	u64 val, prev_val;
++/**
++ * nes_unmap_frm
++ */
++static int nes_unmap_fmr(struct list_head *ibfmr_list)
++{
++	return 0;
++}
 +
-+	prev_val = ipath_read_kreg64(dd, dd->ipath_kregs->kr_xgxsconfig);
-+	val = prev_val | INFINIPATH_XGXS_RESET;
-+	prev_val &= ~INFINIPATH_XGXS_RESET; /* be sure */
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-+			 dd->ipath_control & ~INFINIPATH_C_LINKENABLE);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, val);
-+	ipath_read_kreg32(dd, dd->ipath_kregs->kr_scratch);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_xgxsconfig, prev_val);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
-+			 dd->ipath_control);
++
++
++/**
++ * nes_query_device
++ */
++static int nes_query_device(struct ib_device *ibdev, struct ib_device_attr *props)
++{
++	struct nes_vnic *nesvnic = to_nesvnic(ibdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_ib_device *nesibdev = nesvnic->nesibdev;
++
++	memset(props, 0, sizeof(*props));
++	memcpy(&props->sys_image_guid, nesvnic->netdev->dev_addr, 6);
++
++	props->fw_ver = nesdev->nesadapter->fw_ver;
++	props->device_cap_flags = nesdev->nesadapter->device_cap_flags;
++	props->vendor_id = nesdev->nesadapter->vendor_id;
++	props->vendor_part_id = nesdev->nesadapter->vendor_part_id;
++	props->hw_ver = nesdev->nesadapter->hw_rev;
++	props->max_mr_size = 0x80000000;
++	props->max_qp = nesibdev->max_qp;
++	props->max_qp_wr = nesdev->nesadapter->max_qp_wr - 2;
++	props->max_sge = nesdev->nesadapter->max_sge;
++	props->max_cq = nesibdev->max_cq;
++	props->max_cqe = nesdev->nesadapter->max_cqe - 1;
++	props->max_mr = nesibdev->max_mr;
++	props->max_mw = nesibdev->max_mr;
++	props->max_pd = nesibdev->max_pd;
++	props->max_sge_rd = 1;
++	switch (nesdev->nesadapter->max_irrq_wr) {
++		case 0:
++			props->max_qp_rd_atom = 1;
++			break;
++		case 1:
++			props->max_qp_rd_atom = 4;
++			break;
++		case 2:
++			props->max_qp_rd_atom = 16;
++			break;
++		case 3:
++			props->max_qp_rd_atom = 32;
++			break;
++		default:
++			props->max_qp_rd_atom = 0;
++	}
++	props->max_qp_init_rd_atom = props->max_qp_wr;
++	props->atomic_cap = IB_ATOMIC_NONE;
++	props->max_map_per_fmr = 1;
++
++	return 0;
 +}
 +
 +
-+static int ipath_pe_get_ib_cfg(struct ipath_devdata *dd, int which)
++/**
++ * nes_query_port
++ */
++static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr *props)
 +{
-+	int ret;
++	memset(props, 0, sizeof(*props));
 +
-+	switch (which) {
-+	case IPATH_IB_CFG_LWID:
-+		ret = dd->ipath_link_width_active;
-+		break;
-+	case IPATH_IB_CFG_SPD:
-+		ret = dd->ipath_link_speed_active;
-+		break;
-+	case IPATH_IB_CFG_LWID_ENB:
-+		ret = dd->ipath_link_width_enabled;
-+		break;
-+	case IPATH_IB_CFG_SPD_ENB:
-+		ret = dd->ipath_link_speed_enabled;
-+		break;
-+	default:
-+		ret =  -ENOTSUPP;
-+		break;
- 	}
--	return 1;
-+	return ret;
++	props->max_mtu = IB_MTU_2048;
++	props->active_mtu = IB_MTU_2048;
++	props->lid = 1;
++	props->lmc = 0;
++	props->sm_lid = 0;
++	props->sm_sl = 0;
++	props->state = IB_PORT_ACTIVE;
++	props->phys_state = 0;
++	props->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_REINIT_SUP |
++			IB_PORT_VENDOR_CLASS_SUP | IB_PORT_BOOT_MGMT_SUP;
++	props->gid_tbl_len = 1;
++	props->pkey_tbl_len = 1;
++	props->qkey_viol_cntr = 0;
++	props->active_width = IB_WIDTH_4X;
++	props->active_speed = 1;
++	props->max_msg_sz = 0x80000000;
++
++	return 0;
 +}
 +
 +
-+/* we assume range checking is already done, if needed */
-+static int ipath_pe_set_ib_cfg(struct ipath_devdata *dd, int which, u32 val)
++/**
++ * nes_modify_port
++ */
++static int nes_modify_port(struct ib_device *ibdev, u8 port,
++		int port_modify_mask, struct ib_port_modify *props)
 +{
-+	int ret = 0;
++	return 0;
++}
 +
-+	if (which == IPATH_IB_CFG_LWID_ENB)
-+		dd->ipath_link_width_enabled = val;
-+	else if (which == IPATH_IB_CFG_SPD_ENB)
-+		dd->ipath_link_speed_enabled = val;
-+	else
-+		ret = -ENOTSUPP;
-+	return ret;
- }
- 
-+static void ipath_pe_config_jint(struct ipath_devdata *dd, u16 a, u16 b)
++
++/**
++ * nes_query_pkey
++ */
++static int nes_query_pkey(struct ib_device *ibdev, u8 port, u16 index, u16 *pkey)
 +{
++	*pkey = 0;
++	return 0;
 +}
 +
 +
-+static int ipath_pe_ib_updown(struct ipath_devdata *dd, int ibup, u64 ibcs)
++/**
++ * nes_query_gid
++ */
++static int nes_query_gid(struct ib_device *ibdev, u8 port,
++		int index, union ib_gid *gid)
 +{
-+	ipath_setup_pe_setextled(dd, ipath_ib_linkstate(dd, ibcs),
-+		ipath_ib_linktrstate(dd, ibcs));
++	struct nes_vnic *nesvnic = to_nesvnic(ibdev);
++
++	memset(&(gid->raw[0]), 0, sizeof(gid->raw));
++	memcpy(&(gid->raw[0]), nesvnic->netdev->dev_addr, 6);
++
 +	return 0;
 +}
 +
 +
- /**
-  * ipath_init_iba6120_funcs - set up the chip-specific function pointers
-  * @dd: the infinipath device
-@@ -1407,7 +1666,7 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
- 	dd->ipath_f_bringup_serdes = ipath_pe_bringup_serdes;
- 	dd->ipath_f_clear_tids = ipath_pe_clear_tids;
- 	/*
--	 * this may get changed after we read the chip revision,
-+	 * _f_put_tid may get changed after we read the chip revision,
- 	 * but we start with the safe version for all revs
- 	 */
- 	dd->ipath_f_put_tid = ipath_pe_put_tid;
-@@ -1415,17 +1674,19 @@ void ipath_init_iba6120_funcs(struct ipath_devdata *dd)
- 	dd->ipath_f_setextled = ipath_setup_pe_setextled;
- 	dd->ipath_f_get_base_info = ipath_pe_get_base_info;
- 	dd->ipath_f_free_irq = ipath_pe_free_irq;
--
--	/* initialize chip-specific variables */
- 	dd->ipath_f_tidtemplate = ipath_pe_tidtemplate;
-+	dd->ipath_f_intr_fallback = ipath_pe_nointr_fallback;
-+	dd->ipath_f_xgxs_reset = ipath_pe_xgxs_reset;
-+	dd->ipath_f_get_msgheader = ipath_pe_get_msgheader;
-+	dd->ipath_f_config_ports = ipath_pe_config_ports;
-+	dd->ipath_f_read_counters = ipath_pe_read_counters;
-+	dd->ipath_f_get_ib_cfg = ipath_pe_get_ib_cfg;
-+	dd->ipath_f_set_ib_cfg = ipath_pe_set_ib_cfg;
-+	dd->ipath_f_config_jint = ipath_pe_config_jint;
-+	dd->ipath_f_ib_updown = ipath_pe_ib_updown;
- 
--	/*
--	 * setup the register offsets, since they are different for each
--	 * chip
--	 */
--	dd->ipath_kregs = &ipath_pe_kregs;
--	dd->ipath_cregs = &ipath_pe_cregs;
- 
-+	/* initialize chip-specific variables */
- 	ipath_init_pe_variables(dd);
- }
- 
-diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c
-index 9dd0bac..4471674 100644
---- a/drivers/infiniband/hw/ipath/ipath_init_chip.c
-+++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c
-@@ -91,7 +91,7 @@ static int create_port0_egr(struct ipath_devdata *dd)
- 	struct ipath_skbinfo *skbinfo;
- 	int ret;
- 
--	egrcnt = dd->ipath_rcvegrcnt;
-+	egrcnt = dd->ipath_p0_rcvegrcnt;
- 
- 	skbinfo = vmalloc(sizeof(*dd->ipath_port0_skbinfo) * egrcnt);
- 	if (skbinfo == NULL) {
-@@ -244,8 +244,7 @@ static int init_chip_first(struct ipath_devdata *dd,
- 	 * cfgports.  We do still check and report a difference, if
- 	 * not same (should be impossible).
- 	 */
--	dd->ipath_portcnt =
--		ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
-+	dd->ipath_f_config_ports(dd, ipath_cfgports);
- 	if (!ipath_cfgports)
- 		dd->ipath_cfgports = dd->ipath_portcnt;
- 	else if (ipath_cfgports <= dd->ipath_portcnt) {
-@@ -272,22 +271,7 @@ static int init_chip_first(struct ipath_devdata *dd,
- 		goto done;
- 	}
- 
--	dd->ipath_lastegrheads = kzalloc(sizeof(*dd->ipath_lastegrheads)
--					 * dd->ipath_cfgports,
--					 GFP_KERNEL);
--	dd->ipath_lastrcvhdrqtails =
--		kzalloc(sizeof(*dd->ipath_lastrcvhdrqtails)
--			* dd->ipath_cfgports, GFP_KERNEL);
--
--	if (!dd->ipath_lastegrheads || !dd->ipath_lastrcvhdrqtails) {
--		ipath_dev_err(dd, "Unable to allocate head arrays, "
--			      "failing\n");
--		ret = -ENOMEM;
--		goto done;
--	}
--
- 	pd = create_portdata0(dd);
--
- 	if (!pd) {
- 		ipath_dev_err(dd, "Unable to allocate portdata for port "
- 			      "0, failing\n");
-@@ -345,10 +329,10 @@ static int init_chip_first(struct ipath_devdata *dd,
- 		       dd->ipath_piobcnt2k, dd->ipath_pio2kbase);
- 
- 	spin_lock_init(&dd->ipath_tid_lock);
--
-+	spin_lock_init(&dd->ipath_sendctrl_lock);
- 	spin_lock_init(&dd->ipath_gpio_lock);
- 	spin_lock_init(&dd->ipath_eep_st_lock);
--	sema_init(&dd->ipath_eep_sem, 1);
-+	mutex_init(&dd->ipath_eep_lock);
- 
- done:
- 	*pdp = pd;
-@@ -372,9 +356,9 @@ static int init_chip_reset(struct ipath_devdata *dd,
- 	*pdp = dd->ipath_pd[0];
- 	/* ensure chip does no sends or receives while we re-initialize */
- 	dd->ipath_control = dd->ipath_sendctrl = dd->ipath_rcvctrl = 0U;
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, 0);
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, 0);
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl, dd->ipath_rcvctrl);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, dd->ipath_control);
- 
- 	rtmp = ipath_read_kreg32(dd, dd->ipath_kregs->kr_portcnt);
- 	if (dd->ipath_portcnt != rtmp)
-@@ -487,6 +471,7 @@ static void enable_chip(struct ipath_devdata *dd,
- 			struct ipath_portdata *pd, int reinit)
- {
- 	u32 val;
-+	unsigned long flags;
- 	int i;
- 
- 	if (!reinit)
-@@ -495,19 +480,21 @@ static void enable_chip(struct ipath_devdata *dd,
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- 			 dd->ipath_rcvctrl);
- 
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- 	/* Enable PIO send, and update of PIOavail regs to memory. */
- 	dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE |
- 		INFINIPATH_S_PIOBUFAVAILUPD;
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
--			 dd->ipath_sendctrl);
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- 
- 	/*
- 	 * enable port 0 receive, and receive interrupt.  other ports
- 	 * done as user opens and inits them.
- 	 */
--	dd->ipath_rcvctrl = INFINIPATH_R_TAILUPD |
--		(1ULL << INFINIPATH_R_PORTENABLE_SHIFT) |
--		(1ULL << INFINIPATH_R_INTRAVAIL_SHIFT);
-+	dd->ipath_rcvctrl = (1ULL << dd->ipath_r_tailupd_shift) |
-+		(1ULL << dd->ipath_r_portenable_shift) |
-+		(1ULL << dd->ipath_r_intravail_shift);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_rcvctrl,
- 			 dd->ipath_rcvctrl);
- 
-@@ -523,12 +510,11 @@ static void enable_chip(struct ipath_devdata *dd,
- 	 */
- 	val = ipath_read_ureg32(dd, ur_rcvegrindextail, 0);
- 	(void)ipath_write_ureg(dd, ur_rcvegrindexhead, val, 0);
--	dd->ipath_port0head = ipath_read_ureg32(dd, ur_rcvhdrtail, 0);
- 
- 	/* Initialize so we interrupt on next packet received */
- 	(void)ipath_write_ureg(dd, ur_rcvhdrhead,
- 			       dd->ipath_rhdrhead_intr_off |
--			       dd->ipath_port0head, 0);
-+			       dd->ipath_pd[0]->port_head, 0);
- 
- 	/*
- 	 * by now pioavail updates to memory should have occurred, so
-@@ -542,12 +528,8 @@ static void enable_chip(struct ipath_devdata *dd,
- 		/*
- 		 * Chip Errata bug 6641; even and odd qwords>3 are swapped.
- 		 */
--		if (i > 3) {
--			if (i & 1)
--				val = dd->ipath_pioavailregs_dma[i - 1];
--			else
--				val = dd->ipath_pioavailregs_dma[i + 1];
--		}
-+		if (i > 3 && (dd->ipath_flags & IPATH_SWAP_PIOBUFS))
-+			val = dd->ipath_pioavailregs_dma[i ^ 1];
- 		else
- 			val = dd->ipath_pioavailregs_dma[i];
- 		dd->ipath_pioavailshadow[i] = le64_to_cpu(val);
-@@ -690,12 +672,13 @@ done:
-  */
- int ipath_init_chip(struct ipath_devdata *dd, int reinit)
- {
--	int ret = 0, i;
-+	int ret = 0;
- 	u32 val32, kpiobufs;
- 	u32 piobufs, uports;
- 	u64 val;
- 	struct ipath_portdata *pd = NULL; /* keep gcc4 happy */
- 	gfp_t gfp_flags = GFP_USER | __GFP_COMP;
-+	unsigned long flags;
- 
- 	ret = init_housekeeping(dd, &pd, reinit);
- 	if (ret)
-@@ -746,7 +729,7 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
- 		kpiobufs = ipath_kpiobufs;
- 
- 	if (kpiobufs + (uports * IPATH_MIN_USER_PORT_BUFCNT) > piobufs) {
--		i = (int) piobufs -
-+		int i = (int) piobufs -
- 			(int) (uports * IPATH_MIN_USER_PORT_BUFCNT);
- 		if (i < 0)
- 			i = 0;
-@@ -827,8 +810,12 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit)
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_hwerrclear,
- 			 ~0ULL&~INFINIPATH_HWE_MEMBISTFAILED);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_control, 0ULL);
--	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
--			 INFINIPATH_S_PIOENABLE);
++/**
++ * nes_alloc_ucontext - Allocate the user context data structure. This keeps track
++ * of all objects associated with a particular user-mode client.
++ */
++static struct ib_ucontext *nes_alloc_ucontext(struct ib_device *ibdev,
++		struct ib_udata *udata)
++{
++	struct nes_vnic *nesvnic = to_nesvnic(ibdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_alloc_ucontext_req req;
++	struct nes_alloc_ucontext_resp uresp;
++	struct nes_ucontext *nes_ucontext;
++	struct nes_ib_device *nesibdev = nesvnic->nesibdev;
 +
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+	dd->ipath_sendctrl = INFINIPATH_S_PIOENABLE;
-+	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, dd->ipath_sendctrl);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- 
- 	/*
- 	 * before error clears, since we expect serdes pll errors during
-diff --git a/drivers/infiniband/hw/ipath/ipath_intr.c b/drivers/infiniband/hw/ipath/ipath_intr.c
-index c61f9da..92e58c9 100644
---- a/drivers/infiniband/hw/ipath/ipath_intr.c
-+++ b/drivers/infiniband/hw/ipath/ipath_intr.c
-@@ -683,7 +683,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
- 		for (i = 0; i < dd->ipath_cfgports; i++) {
- 			struct ipath_portdata *pd = dd->ipath_pd[i];
- 			if (i == 0) {
--				hd = dd->ipath_port0head;
-+				hd = pd->port_head;
- 				tl = (u32) le64_to_cpu(
- 					*dd->ipath_hdrqtailptr);
- 			} else if (pd && pd->port_cnt &&
-@@ -693,7 +693,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
- 				 * except kernel
- 				 */
- 				tl = *(u64 *) pd->port_rcvhdrtail_kvaddr;
--				if (tl == dd->ipath_lastrcvhdrqtails[i])
-+				if (tl == pd->port_lastrcvhdrqtail)
- 					continue;
- 				hd = ipath_read_ureg32(dd, ur_rcvhdrhead,
- 						       i);
-@@ -703,7 +703,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
- 			    (!hd && tl == dd->ipath_hdrqlast)) {
- 				if (i == 0)
- 					chkerrpkts = 1;
--				dd->ipath_lastrcvhdrqtails[i] = tl;
-+				pd->port_lastrcvhdrqtail = tl;
- 				pd->port_hdrqfull++;
- 				/* flush hdrqfull so that poll() sees it */
- 				wmb();
-@@ -712,6 +712,8 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
- 		}
- 	}
- 	if (errs & INFINIPATH_E_RRCVEGRFULL) {
-+		struct ipath_portdata *pd = dd->ipath_pd[0];
 +
- 		/*
- 		 * since this is of less importance and not likely to
- 		 * happen without also getting hdrfull, only count
-@@ -719,7 +721,7 @@ static int handle_errors(struct ipath_devdata *dd, ipath_err_t errs)
- 		 * vs user)
- 		 */
- 		ipath_stats.sps_etidfull++;
--		if (dd->ipath_port0head !=
-+		if (pd->port_head !=
- 		    (u32) le64_to_cpu(*dd->ipath_hdrqtailptr))
- 			chkerrpkts = 1;
- 	}
-@@ -795,6 +797,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
- {
- 	int i, im;
- 	__le64 val;
-+	unsigned long flags;
- 
- 	/* disable error interrupts, to avoid confusion */
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_errormask, 0ULL);
-@@ -813,11 +816,14 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
- 			 dd->ipath_control);
- 
- 	/* ensure pio avail updates continue */
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- 		 dd->ipath_sendctrl & ~INFINIPATH_S_PIOBUFAVAILUPD);
- 	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
--		 dd->ipath_sendctrl);
-+			 dd->ipath_sendctrl);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- 
- 	/*
- 	 * We just enabled pioavailupdate, so dma copy is almost certainly
-@@ -825,8 +831,8 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
- 	 */
- 	for (i = 0; i < dd->ipath_pioavregs; i++) {
- 		/* deal with 6110 chip bug */
--		im = i > 3 ? ((i&1) ? i-1 : i+1) : i;
--		val = ipath_read_kreg64(dd, (0x1000/sizeof(u64))+im);
-+		im = i > 3 ? i ^ 1 : i;
-+		val = ipath_read_kreg64(dd, (0x1000 / sizeof(u64)) + im);
- 		dd->ipath_pioavailregs_dma[i] = dd->ipath_pioavailshadow[i]
- 			= le64_to_cpu(val);
- 	}
-@@ -849,7 +855,7 @@ void ipath_clear_freeze(struct ipath_devdata *dd)
- 
- /* this is separate to allow for better optimization of ipath_intr() */
- 
--static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
-+static noinline void ipath_bad_intr(struct ipath_devdata *dd, u32 *unexpectp)
- {
- 	/*
- 	 * sometimes happen during driver init and unload, don't want
-@@ -877,7 +883,7 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
- 				dd->ipath_f_free_irq(dd);
- 			}
- 		}
--		if (ipath_read_kreg32(dd, dd->ipath_kregs->kr_intmask)) {
-+		if (ipath_read_ireg(dd, dd->ipath_kregs->kr_intmask)) {
- 			ipath_dev_err(dd, "%u unexpected interrupts, "
- 				      "disabling interrupts completely\n",
- 				      *unexpectp);
-@@ -892,7 +898,7 @@ static void ipath_bad_intr(struct ipath_devdata *dd, u32 * unexpectp)
- 			  "ignoring\n");
- }
- 
--static void ipath_bad_regread(struct ipath_devdata *dd)
-+static noinline void ipath_bad_regread(struct ipath_devdata *dd)
- {
- 	static int allbits;
- 
-@@ -920,31 +926,9 @@ static void ipath_bad_regread(struct ipath_devdata *dd)
- 	}
- }
- 
--static void handle_port_pioavail(struct ipath_devdata *dd)
--{
--	u32 i;
--	/*
--	 * start from port 1, since for now port 0  is never using
--	 * wait_event for PIO
--	 */
--	for (i = 1; dd->ipath_portpiowait && i < dd->ipath_cfgports; i++) {
--		struct ipath_portdata *pd = dd->ipath_pd[i];
--
--		if (pd && pd->port_cnt &&
--		    dd->ipath_portpiowait & (1U << i)) {
--			clear_bit(i, &dd->ipath_portpiowait);
--			if (test_bit(IPATH_PORT_WAITING_PIO,
--				     &pd->port_flag)) {
--				clear_bit(IPATH_PORT_WAITING_PIO,
--					  &pd->port_flag);
--				wake_up_interruptible(&pd->port_wait);
--			}
--		}
--	}
--}
--
- static void handle_layer_pioavail(struct ipath_devdata *dd)
- {
-+	unsigned long flags;
- 	int ret;
- 
- 	ret = ipath_ib_piobufavail(dd->verbs_dev);
-@@ -953,9 +937,12 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
- 
- 	return;
- set:
--	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+	dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- 			 dd->ipath_sendctrl);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- }
- 
- /*
-@@ -969,7 +956,15 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
- 	int i;
- 	int rcvdint = 0;
- 
--	/* test_bit below needs this... */
-+	/*
-+	 * test_and_clear_bit(IPATH_PORT_WAITING_RCV) and
-+	 * test_and_clear_bit(IPATH_PORT_WAITING_URG) below
-+	 * would both like timely updates of the bits so that
-+	 * we don't pass them by unnecessarily.  the rmb()
-+	 * here ensures that we see them promptly -- the
-+	 * corresponding wmb()'s are in ipath_poll_urgent()
-+	 * and ipath_poll_next()...
-+	 */
- 	rmb();
- 	portr = ((istat >> INFINIPATH_I_RCVAVAIL_SHIFT) &
- 		 dd->ipath_i_rcvavail_mask)
-@@ -980,7 +975,7 @@ static void handle_urcv(struct ipath_devdata *dd, u32 istat)
- 		if (portr & (1 << i) && pd && pd->port_cnt) {
- 			if (test_and_clear_bit(IPATH_PORT_WAITING_RCV,
- 					       &pd->port_flag)) {
--				clear_bit(i + INFINIPATH_R_INTRAVAIL_SHIFT,
-+				clear_bit(i + dd->ipath_r_intravail_shift,
- 					  &dd->ipath_rcvctrl);
- 				wake_up_interruptible(&pd->port_wait);
- 				rcvdint = 1;
-@@ -1039,7 +1034,7 @@ irqreturn_t ipath_intr(int irq, void *data)
- 		goto bail;
- 	}
- 
--	istat = ipath_read_kreg32(dd, dd->ipath_kregs->kr_intstatus);
-+	istat = ipath_read_ireg(dd, dd->ipath_kregs->kr_intstatus);
- 
- 	if (unlikely(!istat)) {
- 		ipath_stats.sps_nullintr++;
-@@ -1180,7 +1175,7 @@ irqreturn_t ipath_intr(int irq, void *data)
- 	 * for receive are at the bottom.
- 	 */
- 	if (chk0rcv) {
--		ipath_kreceive(dd);
-+		ipath_kreceive(dd->ipath_pd[0]);
- 		istat &= ~port0rbits;
- 	}
- 
-@@ -1191,12 +1186,14 @@ irqreturn_t ipath_intr(int irq, void *data)
- 		handle_urcv(dd, istat);
- 
- 	if (istat & INFINIPATH_I_SPIOBUFAVAIL) {
--		clear_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
-+		unsigned long flags;
++	if (ib_copy_from_udata(&req, udata, sizeof(struct nes_alloc_ucontext_req))) {
++		printk(KERN_ERR PFX "Invalid structure size on allocate user context.\n");
++		return ERR_PTR(-EINVAL);
++	}
 +
-+		spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+		dd->ipath_sendctrl &= ~INFINIPATH_S_PIOINTBUFAVAIL;
- 		ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- 				 dd->ipath_sendctrl);
--
--		if (dd->ipath_portpiowait)
--			handle_port_pioavail(dd);
-+		ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+		spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- 
- 		handle_layer_pioavail(dd);
- 	}
-diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h
-index 8786dd7..4cc0f95 100644
---- a/drivers/infiniband/hw/ipath/ipath_kernel.h
-+++ b/drivers/infiniband/hw/ipath/ipath_kernel.h
-@@ -41,6 +41,7 @@
- #include <linux/interrupt.h>
- #include <linux/pci.h>
- #include <linux/dma-mapping.h>
-+#include <linux/mutex.h>
- #include <asm/io.h>
- #include <rdma/ib_verbs.h>
- 
-@@ -140,6 +141,11 @@ struct ipath_portdata {
- 	u32 port_pionowait;
- 	/* total number of rcvhdrqfull errors */
- 	u32 port_hdrqfull;
-+	/*
-+	 * Used to suppress multiple instances of same
-+	 * port staying stuck at same point.
-+	 */
-+	u32 port_lastrcvhdrqtail;
- 	/* saved total number of rcvhdrqfull errors for poll edge trigger */
- 	u32 port_hdrqfull_poll;
- 	/* total number of polled urgent packets */
-@@ -148,6 +154,7 @@ struct ipath_portdata {
- 	u32 port_urgent_poll;
- 	/* pid of process using this port */
- 	pid_t port_pid;
-+	pid_t port_subpid[INFINIPATH_MAX_SUBPORT];
- 	/* same size as task_struct .comm[] */
- 	char port_comm[16];
- 	/* pkeys set by this use of this port */
-@@ -166,6 +173,8 @@ struct ipath_portdata {
- 	u32 active_slaves;
- 	/* Type of packets or conditions we want to poll for */
- 	u16 poll_type;
-+	/* port rcvhdrq head offset */
-+	u32 port_head;
- };
- 
- struct sk_buff;
-@@ -182,6 +191,22 @@ struct ipath_skbinfo {
- 	dma_addr_t phys;
- };
- 
-+/*
-+ * Possible IB config parameters for ipath_f_get/set_ib_cfg()
++	if (req.userspace_ver != NES_ABI_USERSPACE_VER) {
++		printk(KERN_ERR PFX "Invalid userspace driver version detected. Detected version %d, should be %d\n",
++			req.userspace_ver, NES_ABI_USERSPACE_VER);
++		return ERR_PTR(-EINVAL);
++	}
++
++
++	memset(&uresp, 0, sizeof uresp);
++
++	uresp.max_qps = nesibdev->max_qp;
++	uresp.max_pds = nesibdev->max_pd;
++	uresp.wq_size = nesdev->nesadapter->max_qp_wr * 2;
++	uresp.virtwq = nesadapter->virtwq;
++	uresp.kernel_ver = NES_ABI_KERNEL_VER;
++
++	nes_ucontext = kzalloc(sizeof *nes_ucontext, GFP_KERNEL);
++	if (!nes_ucontext)
++		return ERR_PTR(-ENOMEM);
++
++	nes_ucontext->nesdev = nesdev;
++	nes_ucontext->mmap_wq_offset = uresp.max_pds;
++	nes_ucontext->mmap_cq_offset = nes_ucontext->mmap_wq_offset +
++			((sizeof(struct nes_hw_qp_wqe) * uresp.max_qps * 2) + PAGE_SIZE-1) /
++			PAGE_SIZE;
++
++
++	if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {
++		kfree(nes_ucontext);
++		return ERR_PTR(-EFAULT);
++	}
++
++	INIT_LIST_HEAD(&nes_ucontext->cq_reg_mem_list);
++	INIT_LIST_HEAD(&nes_ucontext->qp_reg_mem_list);
++	atomic_set(&nes_ucontext->usecnt, 1);
++	return &nes_ucontext->ibucontext;
++}
++
++
++/**
++ * nes_dealloc_ucontext
 + */
-+#define IPATH_IB_CFG_LIDLMC 0 /* Get/set LID (LS16b) and Mask (MS16b) */
-+#define IPATH_IB_CFG_HRTBT 1 /* Get/set Heartbeat off/enable/auto */
-+#define IPATH_IB_HRTBT_ON 3 /* Heartbeat enabled, sent every 100msec */
-+#define IPATH_IB_HRTBT_OFF 0 /* Heartbeat off */
-+#define IPATH_IB_CFG_LWID_ENB 2 /* Get/set allowed Link-width */
-+#define IPATH_IB_CFG_LWID 3 /* Get currently active Link-width */
-+#define IPATH_IB_CFG_SPD_ENB 4 /* Get/set allowed Link speeds */
-+#define IPATH_IB_CFG_SPD 5 /* Get current Link spd */
-+#define IPATH_IB_CFG_RXPOL_ENB 6 /* Get/set Auto-RX-polarity enable */
-+#define IPATH_IB_CFG_LREV_ENB 7 /* Get/set Auto-Lane-reversal enable */
-+#define IPATH_IB_CFG_LINKLATENCY 8 /* Get Auto-Lane-reversal enable */
++static int nes_dealloc_ucontext(struct ib_ucontext *context)
++{
++	/* struct nes_vnic *nesvnic = to_nesvnic(context->device); */
++	/* struct nes_device *nesdev = nesvnic->nesdev; */
++	struct nes_ucontext *nes_ucontext = to_nesucontext(context);
 +
++	if (!atomic_dec_and_test(&nes_ucontext->usecnt))
++	  return 0;
++	kfree(nes_ucontext);
++	return 0;
++}
 +
- struct ipath_devdata {
- 	struct list_head ipath_list;
- 
-@@ -222,6 +247,8 @@ struct ipath_devdata {
- 	struct _ipath_layer ipath_layer;
- 	/* setup intr */
- 	int (*ipath_f_intrsetup)(struct ipath_devdata *);
-+	/* fallback to alternate interrupt type if possible */
-+	int (*ipath_f_intr_fallback)(struct ipath_devdata *);
- 	/* setup on-chip bus config */
- 	int (*ipath_f_bus)(struct ipath_devdata *, struct pci_dev *);
- 	/* hard reset chip */
-@@ -244,6 +271,18 @@ struct ipath_devdata {
- 	int (*ipath_f_get_base_info)(struct ipath_portdata *, void *);
- 	/* free irq */
- 	void (*ipath_f_free_irq)(struct ipath_devdata *);
-+	struct ipath_message_header *(*ipath_f_get_msgheader)
-+					(struct ipath_devdata *, __le32 *);
-+	void (*ipath_f_config_ports)(struct ipath_devdata *, ushort);
-+	int (*ipath_f_get_ib_cfg)(struct ipath_devdata *, int);
-+	int (*ipath_f_set_ib_cfg)(struct ipath_devdata *, int, u32);
-+	void (*ipath_f_config_jint)(struct ipath_devdata *, u16 , u16);
-+	void (*ipath_f_read_counters)(struct ipath_devdata *,
-+					struct infinipath_counters *);
-+	void (*ipath_f_xgxs_reset)(struct ipath_devdata *);
-+	/* per chip actions needed for IB Link up/down changes */
-+	int (*ipath_f_ib_updown)(struct ipath_devdata *, int, u64);
 +
- 	struct ipath_ibdev *verbs_dev;
- 	struct timer_list verbs_timer;
- 	/* total dwords sent (summed from counter) */
-@@ -313,22 +352,12 @@ struct ipath_devdata {
- 	 * supports, less gives more pio bufs/port, etc.
- 	 */
- 	u32 ipath_cfgports;
--	/* port0 rcvhdrq head offset */
--	u32 ipath_port0head;
- 	/* count of port 0 hdrqfull errors */
- 	u32 ipath_p0_hdrqfull;
-+	/* port 0 number of receive eager buffers */
-+	u32 ipath_p0_rcvegrcnt;
- 
- 	/*
--	 * (*cfgports) used to suppress multiple instances of same
--	 * port staying stuck at same point
--	 */
--	u32 *ipath_lastrcvhdrqtails;
--	/*
--	 * (*cfgports) used to suppress multiple instances of same
--	 * port staying stuck at same point
--	 */
--	u32 *ipath_lastegrheads;
--	/*
- 	 * index of last piobuffer we used.  Speeds up searching, by
- 	 * starting at this point.  Doesn't matter if multiple cpu's use and
- 	 * update, last updater is only write that matters.  Whenever it
-@@ -367,14 +396,15 @@ struct ipath_devdata {
- 	unsigned long ipath_wc_len;
- 	/* ref count for each pkey */
- 	atomic_t ipath_pkeyrefs[4];
--	/* shadow copy of all exptids physaddr; used only by funcsim */
--	u64 *ipath_tidsimshadow;
- 	/* shadow copy of struct page *'s for exp tid pages */
- 	struct page **ipath_pageshadow;
- 	/* shadow copy of dma handles for exp tid pages */
- 	dma_addr_t *ipath_physshadow;
--	/* lock to workaround chip bug 9437 */
-+	u64 __iomem *ipath_egrtidbase;
-+	/* lock to workaround chip bug 9437 and others */
-+	spinlock_t ipath_kernel_tid_lock;
- 	spinlock_t ipath_tid_lock;
-+	spinlock_t ipath_sendctrl_lock;
- 
- 	/*
- 	 * IPATH_STATUS_*,
-@@ -395,6 +425,8 @@ struct ipath_devdata {
- 	void *ipath_dummy_hdrq;	/* used after port close */
- 	dma_addr_t ipath_dummy_hdrq_phys;
- 
-+	unsigned long ipath_ureg_align; /* user register alignment */
++/**
++ * nes_mmap
++ */
++static int nes_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
++{
++	unsigned long index;
++	struct nes_vnic *nesvnic = to_nesvnic(context->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	/* struct nes_adapter *nesadapter = nesdev->nesadapter; */
++	struct nes_ucontext *nes_ucontext;
++	struct nes_qp *nesqp;
 +
- 	/*
- 	 * Shadow copies of registers; size indicates read access size.
- 	 * Most of them are readonly, but some are write-only register,
-@@ -456,8 +488,6 @@ struct ipath_devdata {
- 	unsigned long ipath_rcvctrl;
- 	/* shadow kr_sendctrl */
- 	unsigned long ipath_sendctrl;
--	/* ports waiting for PIOavail intr */
--	unsigned long ipath_portpiowait;
- 	unsigned long ipath_lastcancel; /* to not count armlaunch after cancel */
- 
- 	/* value we put in kr_rcvhdrcnt */
-@@ -550,12 +580,26 @@ struct ipath_devdata {
- 	u8 ipath_minrev;
- 	/* board rev, from ipath_revision */
- 	u8 ipath_boardrev;
++	nes_ucontext = to_nesucontext(context);
 +
-+	u8 ipath_r_portenable_shift;
-+	u8 ipath_r_intravail_shift;
-+	u8 ipath_r_tailupd_shift;
-+	u8 ipath_r_portcfg_shift;
 +
- 	/* unit # of this chip, if present */
- 	int ipath_unit;
- 	/* saved for restore after reset */
- 	u8 ipath_pci_cacheline;
- 	/* LID mask control */
- 	u8 ipath_lmc;
-+	/* link width supported */
-+	u8 ipath_link_width_supported;
-+	/* link speed supported */
-+	u8 ipath_link_speed_supported;
-+	u8 ipath_link_width_enabled;
-+	u8 ipath_link_speed_enabled;
-+	u8 ipath_link_width_active;
-+	u8 ipath_link_speed_active;
- 	/* Rx Polarity inversion (compensate for ~tx on partner) */
- 	u8 ipath_rx_pol_inv;
- 
-@@ -590,6 +634,8 @@ struct ipath_devdata {
- 	 */
- 	u32 ipath_i_rcvavail_mask;
- 	u32 ipath_i_rcvurg_mask;
-+	u16 ipath_i_rcvurg_shift;
-+	u16 ipath_i_rcvavail_shift;
- 
- 	/*
- 	 * Register bits for selecting i2c direction and values, used for
-@@ -603,6 +649,29 @@ struct ipath_devdata {
- 	/* lock for doing RMW of shadows/regs for ExtCtrl and GPIO */
- 	spinlock_t ipath_gpio_lock;
- 
-+	/*
-+	 * IB link and linktraining states and masks that vary per chip in
-+	 * some way.  Set at init, to avoid each IB status change interrupt
-+	 */
-+	u8 ibcs_ls_shift;
-+	u8 ibcs_lts_mask;
-+	u32 ibcs_mask;
-+	u32 ib_init;
-+	u32 ib_arm;
-+	u32 ib_active;
++	if (vma->vm_pgoff >= nes_ucontext->mmap_wq_offset) {
++		index = (vma->vm_pgoff - nes_ucontext->mmap_wq_offset) * PAGE_SIZE;
++		index /= ((sizeof(struct nes_hw_qp_wqe) * nesdev->nesadapter->max_qp_wr * 2) +
++				PAGE_SIZE-1) & (~(PAGE_SIZE-1));
++		if (!test_bit(index, nes_ucontext->allocated_wqs)) {
++			nes_debug(NES_DBG_MMAP, "wq %lu not allocated\n", index);
++			return -EFAULT;
++		}
++		nesqp = nes_ucontext->mmap_nesqp[index];
++		if (nesqp == NULL) {
++			nes_debug(NES_DBG_MMAP, "wq %lu has a NULL QP base.\n", index);
++			return -EFAULT;
++		}
++		if (remap_pfn_range(vma, vma->vm_start,
++				virt_to_phys(nesqp->hwqp.sq_vbase) >> PAGE_SHIFT,
++				vma->vm_end - vma->vm_start,
++				vma->vm_page_prot)) {
++			nes_debug(NES_DBG_MMAP, "remap_pfn_range failed.\n");
++			return -EAGAIN;
++		}
++		vma->vm_private_data = nesqp;
++		return 0;
++	} else {
++		index = vma->vm_pgoff;
++		if (!test_bit(index, nes_ucontext->allocated_doorbells))
++			return -EFAULT;
++
++		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++		if (io_remap_pfn_range(vma, vma->vm_start,
++				(nesdev->doorbell_start +
++				((nes_ucontext->mmap_db_index[index] - nesdev->base_doorbell_index) * 4096))
++				>> PAGE_SHIFT, PAGE_SIZE, vma->vm_page_prot))
++			return -EAGAIN;
++		vma->vm_private_data = nes_ucontext;
++		return 0;
++	}
++
++	return -ENOSYS;
++}
++
++
++/**
++ * nes_alloc_pd
++ */
++static struct ib_pd *nes_alloc_pd(struct ib_device *ibdev,
++		struct ib_ucontext *context, struct ib_udata *udata)
++{
++	struct nes_pd *nespd;
++	struct nes_vnic *nesvnic = to_nesvnic(ibdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_ucontext *nesucontext;
++	struct nes_alloc_pd_resp uresp;
++	u32 pd_num = 0;
++	int err;
 +
-+	u16 ipath_rhf_offset; /* offset of RHF within receive header entry */
++	nes_debug(NES_DBG_PD, "nesvnic=%p, netdev=%p %s, ibdev=%p, context=%p, netdev refcnt=%u\n",
++			nesvnic, nesdev->netdev[0], nesdev->netdev[0]->name, ibdev, context,
++			atomic_read(&nesvnic->netdev->refcnt));
 +
-+	/*
-+	 * shift/mask for linkcmd, linkinitcmd, maxpktlen in ibccontol
-+	 * reg. Changes for IBA7220
-+	 */
-+	u8 ibcc_lic_mask; /* LinkInitCmd */
-+	u8 ibcc_lc_shift; /* LinkCmd */
-+	u8 ibcc_mpl_shift; /* Maxpktlen */
++	err = nes_alloc_resource(nesadapter, nesadapter->allocated_pds,
++			nesadapter->max_pd, &pd_num, &nesadapter->next_pd);
++	if (err) {
++		return ERR_PTR(err);
++	}
 +
-+	u8 delay_mult;
++	nespd = kzalloc(sizeof (struct nes_pd), GFP_KERNEL);
++	if (!nespd) {
++		nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);
++		return ERR_PTR(-ENOMEM);
++	}
 +
- 	/* used to override LED behavior */
- 	u8 ipath_led_override;  /* Substituted for normal value, if non-zero */
- 	u16 ipath_led_override_timeoff; /* delta to next timer event */
-@@ -616,7 +685,7 @@ struct ipath_devdata {
- 	/* control access to actual counters, timer */
- 	spinlock_t ipath_eep_st_lock;
- 	/* control high-level access to EEPROM */
--	struct semaphore ipath_eep_sem;
-+	struct mutex ipath_eep_lock;
- 	/* Below inc'd by ipath_snap_cntrs(), locked by ipath_eep_st_lock */
- 	uint64_t ipath_traffic_wds;
- 	/* active time is kept in seconds, but logged in hours */
-@@ -630,6 +699,10 @@ struct ipath_devdata {
- 	 * each of the counters to increment.
- 	 */
- 	struct ipath_eep_log_mask ipath_eep_st_masks[IPATH_EEP_LOG_CNT];
++	nes_debug(NES_DBG_PD, "Allocating PD (%p) for ib device %s\n",
++			nespd, nesvnic->nesibdev->ibdev.name);
 +
-+	/* interrupt mitigation reload register info */
-+	u16 ipath_jint_idle_ticks;	/* idle clock ticks */
-+	u16 ipath_jint_max_packets;	/* max packets across all ports */
- };
- 
- /* Private data for file operations */
-@@ -690,7 +763,7 @@ void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);
- 
- int ipath_parse_ushort(const char *str, unsigned short *valp);
- 
--void ipath_kreceive(struct ipath_devdata *);
-+void ipath_kreceive(struct ipath_portdata *);
- int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
- int ipath_reset_device(int);
- void ipath_get_faststats(unsigned long);
-@@ -698,6 +771,8 @@ int ipath_set_linkstate(struct ipath_devdata *, u8);
- int ipath_set_mtu(struct ipath_devdata *, u16);
- int ipath_set_lid(struct ipath_devdata *, u32, u8);
- int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
-+void ipath_enable_armlaunch(struct ipath_devdata *);
-+void ipath_disable_armlaunch(struct ipath_devdata *);
- 
- /* for use in system calls, where we want to know device type, etc. */
- #define port_fp(fp) ((struct ipath_filedata *)(fp)->private_data)->pd
-@@ -744,9 +819,15 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
- 		 * are 64bit */
- #define IPATH_32BITCOUNTERS 0x20000
- 		/* can miss port0 rx interrupts */
-+		/* Interrupt register is 64 bits */
-+#define IPATH_INTREG_64     0x40000
- #define IPATH_DISABLED      0x80000 /* administratively disabled */
- 		/* Use GPIO interrupts for new counters */
- #define IPATH_GPIO_ERRINTRS 0x100000
-+#define IPATH_SWAP_PIOBUFS  0x200000
-+		/* Suppress heartbeat, even if turning off loopback */
-+#define IPATH_NO_HRTBT      0x1000000
-+#define IPATH_HAS_MULT_IB_SPEED 0x8000000
- 
- /* Bits in GPIO for the added interrupts */
- #define IPATH_GPIO_PORT0_BIT 2
-@@ -758,8 +839,6 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
- /* portdata flag bit offsets */
- 		/* waiting for a packet to arrive */
- #define IPATH_PORT_WAITING_RCV   2
--		/* waiting for a PIO buffer to be available */
--#define IPATH_PORT_WAITING_PIO   3
- 		/* master has not finished initializing */
- #define IPATH_PORT_MASTER_UNINIT 4
- 		/* waiting for an urgent packet to arrive */
-@@ -767,8 +846,6 @@ int ipath_set_rx_pol_inv(struct ipath_devdata *dd, u8 new_pol_inv);
- 
- /* free up any allocated data at closes */
- void ipath_free_data(struct ipath_portdata *dd);
--int ipath_waitfor_mdio_cmdready(struct ipath_devdata *);
--int ipath_waitfor_complete(struct ipath_devdata *, ipath_kreg, u64, u64 *);
- u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *);
- void ipath_init_iba6120_funcs(struct ipath_devdata *);
- void ipath_init_iba6110_funcs(struct ipath_devdata *);
-@@ -792,33 +869,6 @@ void ipath_set_led_override(struct ipath_devdata *dd, unsigned int val);
-  */
- #define IPATH_DFLT_RCVHDRSIZE 9
- 
--#define IPATH_MDIO_CMD_WRITE   1
--#define IPATH_MDIO_CMD_READ    2
--#define IPATH_MDIO_CLD_DIV     25	/* to get 2.5 Mhz mdio clock */
--#define IPATH_MDIO_CMDVALID    0x40000000	/* bit 30 */
--#define IPATH_MDIO_DATAVALID   0x80000000	/* bit 31 */
--#define IPATH_MDIO_CTRL_STD    0x0
--
--static inline u64 ipath_mdio_req(int cmd, int dev, int reg, int data)
--{
--	return (((u64) IPATH_MDIO_CLD_DIV) << 32) |
--		(cmd << 26) |
--		(dev << 21) |
--		(reg << 16) |
--		(data & 0xFFFF);
--}
--
--		/* signal and fifo status, in bank 31 */
--#define IPATH_MDIO_CTRL_XGXS_REG_8  0x8
--		/* controls loopback, redundancy */
--#define IPATH_MDIO_CTRL_8355_REG_1  0x10
--		/* premph, encdec, etc. */
--#define IPATH_MDIO_CTRL_8355_REG_2  0x11
--		/* Kchars, etc. */
--#define IPATH_MDIO_CTRL_8355_REG_6  0x15
--#define IPATH_MDIO_CTRL_8355_REG_9  0x18
--#define IPATH_MDIO_CTRL_8355_REG_10 0x1D
--
- int ipath_get_user_pages(unsigned long, size_t, struct page **);
- void ipath_release_user_pages(struct page **, size_t);
- void ipath_release_user_pages_on_close(struct page **, size_t);
-@@ -863,7 +913,7 @@ static inline u32 ipath_read_ureg32(const struct ipath_devdata *dd,
- 	return readl(regno + (u64 __iomem *)
- 		     (dd->ipath_uregbase +
- 		      (char __iomem *)dd->ipath_kregbase +
--		      dd->ipath_palign * port));
-+		      dd->ipath_ureg_align * port));
- }
- 
- /**
-@@ -880,7 +930,7 @@ static inline void ipath_write_ureg(const struct ipath_devdata *dd,
- {
- 	u64 __iomem *ubase = (u64 __iomem *)
- 		(dd->ipath_uregbase + (char __iomem *) dd->ipath_kregbase +
--		 dd->ipath_palign * port);
-+		 dd->ipath_ureg_align * port);
- 	if (dd->ipath_kregbase)
- 		writeq(value, &ubase[regno]);
- }
-@@ -930,6 +980,53 @@ static inline u32 ipath_read_creg32(const struct ipath_devdata *dd,
- 		      (char __iomem *)dd->ipath_kregbase));
- }
- 
-+static inline void ipath_write_creg(const struct ipath_devdata *dd,
-+				    ipath_creg regno, u64 value)
-+{
-+	if (dd->ipath_kregbase)
-+		writeq(value, regno + (u64 __iomem *)
-+		       (dd->ipath_cregbase +
-+			(char __iomem *)dd->ipath_kregbase));
++	nespd->pd_id = (pd_num << (PAGE_SHIFT-12)) + nesadapter->base_pd;
++
++	if (context) {
++		nesucontext = to_nesucontext(context);
++		nespd->mmap_db_index = find_next_zero_bit(nesucontext->allocated_doorbells,
++				NES_MAX_USER_DB_REGIONS, nesucontext->first_free_db);
++		nes_debug(NES_DBG_PD, "find_first_zero_biton doorbells returned %u, mapping pd_id %u.\n",
++				nespd->mmap_db_index, nespd->pd_id);
++		if (nespd->mmap_db_index > NES_MAX_USER_DB_REGIONS) {
++			nes_debug(NES_DBG_PD, "mmap_db_index > MAX\n");
++			nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);
++			kfree(nespd);
++			return ERR_PTR(-ENOMEM);
++		}
++
++		uresp.pd_id = nespd->pd_id;
++		uresp.mmap_db_index = nespd->mmap_db_index;
++		if (ib_copy_to_udata(udata, &uresp, sizeof (struct nes_alloc_pd_resp))) {
++			nes_free_resource(nesadapter, nesadapter->allocated_pds, pd_num);
++			kfree(nespd);
++			return ERR_PTR(-EFAULT);
++		}
++
++		set_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells);
++		nesucontext->mmap_db_index[nespd->mmap_db_index] = nespd->pd_id;
++		nesucontext->first_free_db = nespd->mmap_db_index + 1;
++	}
++
++	nes_debug(NES_DBG_PD, "PD%u structure located @%p.\n", nespd->pd_id, nespd);
++	return &nespd->ibpd;
 +}
 +
-+static inline void ipath_clear_rcvhdrtail(const struct ipath_portdata *pd)
++
++/**
++ * nes_dealloc_pd
++ */
++static int nes_dealloc_pd(struct ib_pd *ibpd)
 +{
-+	*((u64 *) pd->port_rcvhdrtail_kvaddr) = 0ULL;
++	struct nes_ucontext *nesucontext;
++	struct nes_pd *nespd = to_nespd(ibpd);
++	struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++
++	if ((ibpd->uobject) && (ibpd->uobject->context)) {
++		nesucontext = to_nesucontext(ibpd->uobject->context);
++		nes_debug(NES_DBG_PD, "Clearing bit %u from allocated doorbells\n",
++				nespd->mmap_db_index);
++		clear_bit(nespd->mmap_db_index, nesucontext->allocated_doorbells);
++		nesucontext->mmap_db_index[nespd->mmap_db_index] = 0;
++		if (nesucontext->first_free_db > nespd->mmap_db_index) {
++			nesucontext->first_free_db = nespd->mmap_db_index;
++		}
++	}
++
++	nes_debug(NES_DBG_PD, "Deallocating PD%u structure located @%p.\n",
++			nespd->pd_id, nespd);
++	nes_free_resource(nesadapter, nesadapter->allocated_pds,
++			(nespd->pd_id-nesadapter->base_pd)>>(PAGE_SHIFT-12));
++	kfree(nespd);
++
++	return 0;
 +}
 +
-+static inline u32 ipath_get_rcvhdrtail(const struct ipath_portdata *pd)
++
++/**
++ * nes_create_ah
++ */
++static struct ib_ah *nes_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
 +{
-+	return (u32) le64_to_cpu(*((volatile __le64 *)
-+				pd->port_rcvhdrtail_kvaddr));
++	return ERR_PTR(-ENOSYS);
 +}
 +
-+static inline u64 ipath_read_ireg(const struct ipath_devdata *dd, ipath_kreg r)
++
++/**
++ * nes_destroy_ah
++ */
++static int nes_destroy_ah(struct ib_ah *ah)
 +{
-+	return (dd->ipath_flags & IPATH_INTREG_64) ?
-+		ipath_read_kreg64(dd, r) : ipath_read_kreg32(dd, r);
++	return -ENOSYS;
 +}
 +
-+/*
-+ * from contents of IBCStatus (or a saved copy), return linkstate
-+ * Report ACTIVE_DEFER as ACTIVE, because we treat them the same
-+ * everywhere, anyway (and should be, for almost all purposes).
++
++/**
++ * nes_get_encoded_size
 + */
-+static inline u32 ipath_ib_linkstate(struct ipath_devdata *dd, u64 ibcs)
++static inline u8 nes_get_encoded_size(int *size)
 +{
-+	u32 state = (u32)(ibcs >> dd->ibcs_ls_shift) &
-+		INFINIPATH_IBCS_LINKSTATE_MASK;
-+	if (state == INFINIPATH_IBCS_L_STATE_ACT_DEFER)
-+		state = INFINIPATH_IBCS_L_STATE_ACTIVE;
-+	return state;
++	u8 encoded_size = 0;
++	if (*size <= 32) {
++		*size = 32;
++		encoded_size = 1;
++	} else if (*size <= 128) {
++		*size = 128;
++		encoded_size = 2;
++	} else if (*size <= 512) {
++		*size = 512;
++		encoded_size = 3;
++	}
++	return (encoded_size);
 +}
 +
-+/* from contents of IBCStatus (or a saved copy), return linktrainingstate */
-+static inline u32 ipath_ib_linktrstate(struct ipath_devdata *dd, u64 ibcs)
++
++
++/**
++ * nes_setup_virt_qp
++ */
++static int nes_setup_virt_qp(struct nes_qp *nesqp, struct nes_pbl *nespbl,
++		struct nes_vnic *nesvnic, int sq_size, int rq_size)
 +{
-+	return (u32)(ibcs >> INFINIPATH_IBCS_LINKTRAININGSTATE_SHIFT) &
-+		dd->ibcs_lts_mask;
-+}
++	unsigned long flags;
++	void *mem;
++	__le64 *pbl = NULL;
++	__le64 *tpbl;
++	__le64 *pblbuffer;
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	u32 pbl_entries;
++	u8 rq_pbl_entries;
++	u8 sq_pbl_entries;
++
++	pbl_entries = nespbl->pbl_size >> 3;
++	nes_debug(NES_DBG_QP, "Userspace PBL, pbl_size=%u, pbl_entries = %d pbl_vbase=%p, pbl_pbase=%p\n",
++			nespbl->pbl_size, pbl_entries,
++			(void *)nespbl->pbl_vbase,
++			(void *)nespbl->pbl_pbase);
++	pbl = (__le64 *) nespbl->pbl_vbase; /* points to first pbl entry */
++	/* now lets set the sq_vbase as well as rq_vbase addrs we will assign */
++	/* the first pbl to be fro the rq_vbase... */
++	rq_pbl_entries = (rq_size * sizeof(struct nes_hw_qp_wqe)) >> 12;
++	sq_pbl_entries = (sq_size * sizeof(struct nes_hw_qp_wqe)) >> 12;
++	nesqp->hwqp.sq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32);
++	if (!nespbl->page) {
++		nes_debug(NES_DBG_QP, "QP nespbl->page is NULL \n");
++		kfree(nespbl);
++		return -ENOMEM;
++	}
 +
- /*
-  * sysfs interface.
-  */
-@@ -938,8 +1035,7 @@ struct device_driver;
- 
- extern const char ib_ipath_version[];
- 
--int ipath_driver_create_group(struct device_driver *);
--void ipath_driver_remove_group(struct device_driver *);
-+extern struct attribute_group *ipath_driver_attr_groups[];
- 
- int ipath_device_create_group(struct device *, struct ipath_devdata *);
- void ipath_device_remove_group(struct device *, struct ipath_devdata *);
-diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c
-index 85a4aef..8f32b17 100644
---- a/drivers/infiniband/hw/ipath/ipath_keys.c
-+++ b/drivers/infiniband/hw/ipath/ipath_keys.c
-@@ -128,9 +128,8 @@ int ipath_lkey_ok(struct ipath_qp *qp, struct ipath_sge *isge,
- 	int ret;
- 
- 	/*
--	 * We use LKEY == zero to mean a physical kmalloc() address.
--	 * This is a bit of a hack since we rely on dma_map_single()
--	 * being reversible by calling bus_to_virt().
-+	 * We use LKEY == zero for kernel virtual addresses
-+	 * (see ipath_get_dma_mr and ipath_dma.c).
- 	 */
- 	if (sge->lkey == 0) {
- 		struct ipath_pd *pd = to_ipd(qp->ibqp.pd);
-diff --git a/drivers/infiniband/hw/ipath/ipath_mad.c b/drivers/infiniband/hw/ipath/ipath_mad.c
-index 3d1432d..d98d5f1 100644
---- a/drivers/infiniband/hw/ipath/ipath_mad.c
-+++ b/drivers/infiniband/hw/ipath/ipath_mad.c
-@@ -934,6 +934,7 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
- 	struct ib_pma_portsamplescontrol *p =
- 		(struct ib_pma_portsamplescontrol *)pmp->data;
- 	struct ipath_ibdev *dev = to_idev(ibdev);
-+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
- 	unsigned long flags;
- 	u8 port_select = p->port_select;
- 
-@@ -955,7 +956,10 @@ static int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
- 	p->counter_width = 4;	/* 32 bit counters */
- 	p->counter_mask0_9 = COUNTER_MASK0_9;
- 	spin_lock_irqsave(&dev->pending_lock, flags);
--	p->sample_status = dev->pma_sample_status;
-+	if (crp->cr_psstat)
-+		p->sample_status = ipath_read_creg32(dev->dd, crp->cr_psstat);
-+	else
-+		p->sample_status = dev->pma_sample_status;
- 	p->sample_start = cpu_to_be32(dev->pma_sample_start);
- 	p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
- 	p->tag = cpu_to_be16(dev->pma_tag);
-@@ -975,8 +979,9 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
- 	struct ib_pma_portsamplescontrol *p =
- 		(struct ib_pma_portsamplescontrol *)pmp->data;
- 	struct ipath_ibdev *dev = to_idev(ibdev);
-+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
- 	unsigned long flags;
--	u32 start;
-+	u8 status;
- 	int ret;
- 
- 	if (pmp->attr_mod != 0 ||
-@@ -986,59 +991,67 @@ static int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
- 		goto bail;
- 	}
- 
--	start = be32_to_cpu(p->sample_start);
--	if (start != 0) {
--		spin_lock_irqsave(&dev->pending_lock, flags);
--		if (dev->pma_sample_status == IB_PMA_SAMPLE_STATUS_DONE) {
--			dev->pma_sample_status =
--				IB_PMA_SAMPLE_STATUS_STARTED;
--			dev->pma_sample_start = start;
--			dev->pma_sample_interval =
--				be32_to_cpu(p->sample_interval);
--			dev->pma_tag = be16_to_cpu(p->tag);
--			if (p->counter_select[0])
--				dev->pma_counter_select[0] =
--					p->counter_select[0];
--			if (p->counter_select[1])
--				dev->pma_counter_select[1] =
--					p->counter_select[1];
--			if (p->counter_select[2])
--				dev->pma_counter_select[2] =
--					p->counter_select[2];
--			if (p->counter_select[3])
--				dev->pma_counter_select[3] =
--					p->counter_select[3];
--			if (p->counter_select[4])
--				dev->pma_counter_select[4] =
--					p->counter_select[4];
--		}
--		spin_unlock_irqrestore(&dev->pending_lock, flags);
-+	spin_lock_irqsave(&dev->pending_lock, flags);
-+	if (crp->cr_psstat)
-+		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
-+	else
-+		status = dev->pma_sample_status;
-+	if (status == IB_PMA_SAMPLE_STATUS_DONE) {
-+		dev->pma_sample_start = be32_to_cpu(p->sample_start);
-+		dev->pma_sample_interval = be32_to_cpu(p->sample_interval);
-+		dev->pma_tag = be16_to_cpu(p->tag);
-+		dev->pma_counter_select[0] = p->counter_select[0];
-+		dev->pma_counter_select[1] = p->counter_select[1];
-+		dev->pma_counter_select[2] = p->counter_select[2];
-+		dev->pma_counter_select[3] = p->counter_select[3];
-+		dev->pma_counter_select[4] = p->counter_select[4];
-+		if (crp->cr_psstat) {
-+			ipath_write_creg(dev->dd, crp->cr_psinterval,
-+					 dev->pma_sample_interval);
-+			ipath_write_creg(dev->dd, crp->cr_psstart,
-+					 dev->pma_sample_start);
-+		} else
-+			dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED;
- 	}
-+	spin_unlock_irqrestore(&dev->pending_lock, flags);
++	nesqp->hwqp.sq_vbase = kmap(nespbl->page);
++	nesqp->page = nespbl->page;
++	if (!nesqp->hwqp.sq_vbase) {
++		nes_debug(NES_DBG_QP, "QP sq_vbase kmap failed\n");
++		kfree(nespbl);
++		return -ENOMEM;
++	}
 +
- 	ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
- 
- bail:
- 	return ret;
- }
- 
--static u64 get_counter(struct ipath_ibdev *dev, __be16 sel)
-+static u64 get_counter(struct ipath_ibdev *dev,
-+		       struct ipath_cregs const *crp,
-+		       __be16 sel)
- {
- 	u64 ret;
- 
- 	switch (sel) {
- 	case IB_PMA_PORT_XMIT_DATA:
--		ret = dev->ipath_sword;
-+		ret = (crp->cr_psxmitdatacount) ?
-+			ipath_read_creg32(dev->dd, crp->cr_psxmitdatacount) :
-+			dev->ipath_sword;
- 		break;
- 	case IB_PMA_PORT_RCV_DATA:
--		ret = dev->ipath_rword;
-+		ret = (crp->cr_psrcvdatacount) ?
-+			ipath_read_creg32(dev->dd, crp->cr_psrcvdatacount) :
-+			dev->ipath_rword;
- 		break;
- 	case IB_PMA_PORT_XMIT_PKTS:
--		ret = dev->ipath_spkts;
-+		ret = (crp->cr_psxmitpktscount) ?
-+			ipath_read_creg32(dev->dd, crp->cr_psxmitpktscount) :
-+			dev->ipath_spkts;
- 		break;
- 	case IB_PMA_PORT_RCV_PKTS:
--		ret = dev->ipath_rpkts;
-+		ret = (crp->cr_psrcvpktscount) ?
-+			ipath_read_creg32(dev->dd, crp->cr_psrcvpktscount) :
-+			dev->ipath_rpkts;
- 		break;
- 	case IB_PMA_PORT_XMIT_WAIT:
--		ret = dev->ipath_xmit_wait;
-+		ret = (crp->cr_psxmitwaitcount) ?
-+			ipath_read_creg32(dev->dd, crp->cr_psxmitwaitcount) :
-+			dev->ipath_xmit_wait;
- 		break;
- 	default:
- 		ret = 0;
-@@ -1053,14 +1066,21 @@ static int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
- 	struct ib_pma_portsamplesresult *p =
- 		(struct ib_pma_portsamplesresult *)pmp->data;
- 	struct ipath_ibdev *dev = to_idev(ibdev);
-+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
-+	u8 status;
- 	int i;
- 
- 	memset(pmp->data, 0, sizeof(pmp->data));
- 	p->tag = cpu_to_be16(dev->pma_tag);
--	p->sample_status = cpu_to_be16(dev->pma_sample_status);
-+	if (crp->cr_psstat)
-+		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
-+	else
-+		status = dev->pma_sample_status;
-+	p->sample_status = cpu_to_be16(status);
- 	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
--		p->counter[i] = cpu_to_be32(
--			get_counter(dev, dev->pma_counter_select[i]));
-+		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
-+		    cpu_to_be32(
-+			get_counter(dev, crp, dev->pma_counter_select[i]));
- 
- 	return reply((struct ib_smp *) pmp);
- }
-@@ -1071,16 +1091,23 @@ static int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
- 	struct ib_pma_portsamplesresult_ext *p =
- 		(struct ib_pma_portsamplesresult_ext *)pmp->data;
- 	struct ipath_ibdev *dev = to_idev(ibdev);
-+	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
-+	u8 status;
- 	int i;
- 
- 	memset(pmp->data, 0, sizeof(pmp->data));
- 	p->tag = cpu_to_be16(dev->pma_tag);
--	p->sample_status = cpu_to_be16(dev->pma_sample_status);
-+	if (crp->cr_psstat)
-+		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
-+	else
-+		status = dev->pma_sample_status;
-+	p->sample_status = cpu_to_be16(status);
- 	/* 64 bits */
- 	p->extended_width = __constant_cpu_to_be32(0x80000000);
- 	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
--		p->counter[i] = cpu_to_be64(
--			get_counter(dev, dev->pma_counter_select[i]));
-+		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
-+		    cpu_to_be64(
-+			get_counter(dev, crp, dev->pma_counter_select[i]));
- 
- 	return reply((struct ib_smp *) pmp);
- }
-@@ -1113,6 +1140,8 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
- 		dev->z_local_link_integrity_errors;
- 	cntrs.excessive_buffer_overrun_errors -=
- 		dev->z_excessive_buffer_overrun_errors;
-+	cntrs.vl15_dropped -= dev->z_vl15_dropped;
-+	cntrs.vl15_dropped += dev->n_vl15_dropped;
- 
- 	memset(pmp->data, 0, sizeof(pmp->data));
- 
-@@ -1156,10 +1185,10 @@ static int recv_pma_get_portcounters(struct ib_perf *pmp,
- 		cntrs.excessive_buffer_overrun_errors = 0xFUL;
- 	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
- 		cntrs.excessive_buffer_overrun_errors;
--	if (dev->n_vl15_dropped > 0xFFFFUL)
-+	if (cntrs.vl15_dropped > 0xFFFFUL)
- 		p->vl15_dropped = __constant_cpu_to_be16(0xFFFF);
- 	else
--		p->vl15_dropped = cpu_to_be16((u16)dev->n_vl15_dropped);
-+		p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped);
- 	if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
- 		p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
- 	else
-@@ -1262,8 +1291,10 @@ static int recv_pma_set_portcounters(struct ib_perf *pmp,
- 		dev->z_excessive_buffer_overrun_errors =
- 			cntrs.excessive_buffer_overrun_errors;
- 
--	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED)
-+	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) {
- 		dev->n_vl15_dropped = 0;
-+		dev->z_vl15_dropped = cntrs.vl15_dropped;
++	/* Now to get to sq.. we need to calculate how many */
++	/* PBL entries were used by the rq.. */
++	pbl += sq_pbl_entries;
++	nesqp->hwqp.rq_pbase = (le32_to_cpu(((__le32 *)pbl)[0])) | ((u64)((le32_to_cpu(((__le32 *)pbl)[1]))) << 32);
++	/* nesqp->hwqp.rq_vbase = bus_to_virt(*pbl); */
++	/*nesqp->hwqp.rq_vbase = phys_to_virt(*pbl); */
++
++	nes_debug(NES_DBG_QP, "QP sq_vbase= %p sq_pbase=%p rq_vbase=%p rq_pbase=%p\n",
++			nesqp->hwqp.sq_vbase, (void *)nesqp->hwqp.sq_pbase,
++			nesqp->hwqp.rq_vbase, (void *)nesqp->hwqp.rq_pbase);
++	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++	if (!nesadapter->free_256pbl) {
++		pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
++				nespbl->pbl_pbase);
++		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++		kunmap(nesqp->page);
++		kfree(nespbl);
++		return -ENOMEM;
 +	}
- 
- 	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
- 		dev->z_port_xmit_data = cntrs.port_xmit_data;
-@@ -1434,7 +1465,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags,
- 		 * before checking for other consumers.
- 		 * Just tell the caller to process it normally.
- 		 */
--		ret = IB_MAD_RESULT_FAILURE;
-+		ret = IB_MAD_RESULT_SUCCESS;
- 		goto bail;
- 	default:
- 		smp->status |= IB_SMP_UNSUP_METHOD;
-@@ -1516,7 +1547,7 @@ static int process_perf(struct ib_device *ibdev, u8 port_num,
- 		 * before checking for other consumers.
- 		 * Just tell the caller to process it normally.
- 		 */
--		ret = IB_MAD_RESULT_FAILURE;
-+		ret = IB_MAD_RESULT_SUCCESS;
- 		goto bail;
- 	default:
- 		pmp->status |= IB_SMP_UNSUP_METHOD;
-diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c
-index b997ff8..80dc623 100644
---- a/drivers/infiniband/hw/ipath/ipath_qp.c
-+++ b/drivers/infiniband/hw/ipath/ipath_qp.c
-@@ -387,8 +387,8 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err)
- 	struct ib_wc wc;
- 	int ret = 0;
- 
--	ipath_dbg("QP%d/%d in error state\n",
--		  qp->ibqp.qp_num, qp->remote_qpn);
-+	ipath_dbg("QP%d/%d in error state (%d)\n",
-+		  qp->ibqp.qp_num, qp->remote_qpn, err);
- 
- 	spin_lock(&dev->pending_lock);
- 	/* XXX What if its already removed by the timeout code? */
-@@ -855,8 +855,6 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd,
- 	 * See ipath_mmap() for details.
- 	 */
- 	if (udata && udata->outlen >= sizeof(__u64)) {
--		int err;
--
- 		if (!qp->r_rq.wq) {
- 			__u64 offset = 0;
- 
-diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c
-index 120a61b..459e46e 100644
---- a/drivers/infiniband/hw/ipath/ipath_rc.c
-+++ b/drivers/infiniband/hw/ipath/ipath_rc.c
-@@ -647,6 +647,7 @@ static void send_rc_ack(struct ipath_qp *qp)
- 
- queue_ack:
- 	spin_lock_irqsave(&qp->s_lock, flags);
-+	dev->n_rc_qacks++;
- 	qp->s_flags |= IPATH_S_ACK_PENDING;
- 	qp->s_nak_state = qp->r_nak_state;
- 	qp->s_ack_psn = qp->r_ack_psn;
-@@ -798,11 +799,13 @@ bail:
- 
- static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
- {
--	if (qp->s_wait_credit) {
--		qp->s_wait_credit = 0;
--		tasklet_hi_schedule(&qp->s_task);
-+	if (qp->s_last_psn != psn) {
-+		qp->s_last_psn = psn;
-+		if (qp->s_wait_credit) {
-+			qp->s_wait_credit = 0;
-+			tasklet_hi_schedule(&qp->s_task);
-+		}
- 	}
--	qp->s_last_psn = psn;
- }
- 
- /**
-@@ -1653,13 +1656,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
- 	case OP(SEND_FIRST):
- 		if (!ipath_get_rwqe(qp, 0)) {
- 		rnr_nak:
--			/*
--			 * A RNR NAK will ACK earlier sends and RDMA writes.
--			 * Don't queue the NAK if a RDMA read or atomic
--			 * is pending though.
--			 */
--			if (qp->r_nak_state)
--				goto done;
- 			qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer;
- 			qp->r_ack_psn = qp->r_psn;
- 			goto send_ack;
-diff --git a/drivers/infiniband/hw/ipath/ipath_registers.h b/drivers/infiniband/hw/ipath/ipath_registers.h
-index 708eba3..6d2a17f 100644
---- a/drivers/infiniband/hw/ipath/ipath_registers.h
-+++ b/drivers/infiniband/hw/ipath/ipath_registers.h
-@@ -82,8 +82,7 @@
- 
- /* kr_rcvctrl bits */
- #define INFINIPATH_R_PORTENABLE_SHIFT 0
--#define INFINIPATH_R_INTRAVAIL_SHIFT 16
--#define INFINIPATH_R_TAILUPD   0x80000000
-+#define INFINIPATH_R_QPMAP_ENABLE (1ULL << 38)
- 
- /* kr_intstatus, kr_intclear, kr_intmask bits */
- #define INFINIPATH_I_RCVURG_SHIFT 0
-@@ -272,20 +271,6 @@
- #define INFINIPATH_EXTC_LEDGBLOK_ON          0x00000002ULL
- #define INFINIPATH_EXTC_LEDGBLERR_OFF        0x00000001ULL
- 
--/* kr_mdio bits */
--#define INFINIPATH_MDIO_CLKDIV_MASK 0x7FULL
--#define INFINIPATH_MDIO_CLKDIV_SHIFT 32
--#define INFINIPATH_MDIO_COMMAND_MASK 0x7ULL
--#define INFINIPATH_MDIO_COMMAND_SHIFT 26
--#define INFINIPATH_MDIO_DEVADDR_MASK 0x1FULL
--#define INFINIPATH_MDIO_DEVADDR_SHIFT 21
--#define INFINIPATH_MDIO_REGADDR_MASK 0x1FULL
--#define INFINIPATH_MDIO_REGADDR_SHIFT 16
--#define INFINIPATH_MDIO_DATA_MASK 0xFFFFULL
--#define INFINIPATH_MDIO_DATA_SHIFT 0
--#define INFINIPATH_MDIO_CMDVALID    0x0000000040000000ULL
--#define INFINIPATH_MDIO_RDDATAVALID 0x0000000080000000ULL
--
- /* kr_partitionkey bits */
- #define INFINIPATH_PKEY_SIZE 16
- #define INFINIPATH_PKEY_MASK 0xFFFF
-@@ -303,8 +288,6 @@
- 
- /* kr_xgxsconfig bits */
- #define INFINIPATH_XGXS_RESET          0x7ULL
--#define INFINIPATH_XGXS_MDIOADDR_MASK  0xfULL
--#define INFINIPATH_XGXS_MDIOADDR_SHIFT 4
- #define INFINIPATH_XGXS_RX_POL_SHIFT 19
- #define INFINIPATH_XGXS_RX_POL_MASK 0xfULL
- 
-@@ -470,6 +453,20 @@ struct ipath_cregs {
- 	ipath_creg cr_unsupvlcnt;
- 	ipath_creg cr_wordrcvcnt;
- 	ipath_creg cr_wordsendcnt;
-+	ipath_creg cr_vl15droppedpktcnt;
-+	ipath_creg cr_rxotherlocalphyerrcnt;
-+	ipath_creg cr_excessbufferovflcnt;
-+	ipath_creg cr_locallinkintegrityerrcnt;
-+	ipath_creg cr_rxvlerrcnt;
-+	ipath_creg cr_rxdlidfltrcnt;
-+	ipath_creg cr_psstat;
-+	ipath_creg cr_psstart;
-+	ipath_creg cr_psinterval;
-+	ipath_creg cr_psrcvdatacount;
-+	ipath_creg cr_psrcvpktscount;
-+	ipath_creg cr_psxmitdatacount;
-+	ipath_creg cr_psxmitpktscount;
-+	ipath_creg cr_psxmitwaitcount;
- };
- 
- #endif				/* _IPATH_REGISTERS_H */
-diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c
-index 54c61a9..a59bdbd 100644
---- a/drivers/infiniband/hw/ipath/ipath_ruc.c
-+++ b/drivers/infiniband/hw/ipath/ipath_ruc.c
-@@ -98,11 +98,15 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp)
- 		while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
- 			qp->s_rnr_timeout -= nqp->s_rnr_timeout;
- 			l = l->next;
--			if (l->next == &dev->rnrwait)
-+			if (l->next == &dev->rnrwait) {
-+				nqp = NULL;
- 				break;
-+			}
- 			nqp = list_entry(l->next, struct ipath_qp,
- 					 timerwait);
- 		}
-+		if (nqp)
-+			nqp->s_rnr_timeout -= qp->s_rnr_timeout;
- 		list_add(&qp->timerwait, l);
- 	}
- 	spin_unlock_irqrestore(&dev->pending_lock, flags);
-@@ -479,9 +483,14 @@ done:
- 
- static void want_buffer(struct ipath_devdata *dd)
- {
--	set_bit(IPATH_S_PIOINTBUFAVAIL, &dd->ipath_sendctrl);
-+	unsigned long flags;
++	nesadapter->free_256pbl--;
++	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
 +
-+	spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags);
-+	dd->ipath_sendctrl |= INFINIPATH_S_PIOINTBUFAVAIL;
- 	ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl,
- 			 dd->ipath_sendctrl);
-+	ipath_read_kreg64(dd, dd->ipath_kregs->kr_scratch);
-+	spin_unlock_irqrestore(&dd->ipath_sendctrl_lock, flags);
- }
- 
- /**
-diff --git a/drivers/infiniband/hw/ipath/ipath_srq.c b/drivers/infiniband/hw/ipath/ipath_srq.c
-index 2fef36f..f772102 100644
---- a/drivers/infiniband/hw/ipath/ipath_srq.c
-+++ b/drivers/infiniband/hw/ipath/ipath_srq.c
-@@ -94,8 +94,8 @@ bail:
- /**
-  * ipath_create_srq - create a shared receive queue
-  * @ibpd: the protection domain of the SRQ to create
-- * @attr: the attributes of the SRQ
-- * @udata: not used by the InfiniPath verbs driver
-+ * @srq_init_attr: the attributes of the SRQ
-+ * @udata: data from libipathverbs when creating a user SRQ
-  */
- struct ib_srq *ipath_create_srq(struct ib_pd *ibpd,
- 				struct ib_srq_init_attr *srq_init_attr,
-diff --git a/drivers/infiniband/hw/ipath/ipath_stats.c b/drivers/infiniband/hw/ipath/ipath_stats.c
-index f027141..d2725cd 100644
---- a/drivers/infiniband/hw/ipath/ipath_stats.c
-+++ b/drivers/infiniband/hw/ipath/ipath_stats.c
-@@ -133,15 +133,16 @@ bail:
- static void ipath_qcheck(struct ipath_devdata *dd)
- {
- 	static u64 last_tot_hdrqfull;
-+	struct ipath_portdata *pd = dd->ipath_pd[0];
- 	size_t blen = 0;
- 	char buf[128];
- 
- 	*buf = 0;
--	if (dd->ipath_pd[0]->port_hdrqfull != dd->ipath_p0_hdrqfull) {
-+	if (pd->port_hdrqfull != dd->ipath_p0_hdrqfull) {
- 		blen = snprintf(buf, sizeof buf, "port 0 hdrqfull %u",
--				dd->ipath_pd[0]->port_hdrqfull -
-+				pd->port_hdrqfull -
- 				dd->ipath_p0_hdrqfull);
--		dd->ipath_p0_hdrqfull = dd->ipath_pd[0]->port_hdrqfull;
-+		dd->ipath_p0_hdrqfull = pd->port_hdrqfull;
- 	}
- 	if (ipath_stats.sps_etidfull != dd->ipath_last_tidfull) {
- 		blen += snprintf(buf + blen, sizeof buf - blen,
-@@ -173,7 +174,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
- 	if (blen)
- 		ipath_dbg("%s\n", buf);
- 
--	if (dd->ipath_port0head != (u32)
-+	if (pd->port_head != (u32)
- 	    le64_to_cpu(*dd->ipath_hdrqtailptr)) {
- 		if (dd->ipath_lastport0rcv_cnt ==
- 		    ipath_stats.sps_port0pkts) {
-@@ -181,7 +182,7 @@ static void ipath_qcheck(struct ipath_devdata *dd)
- 				   "port0 hd=%llx tl=%x; port0pkts %llx\n",
- 				   (unsigned long long)
- 				   le64_to_cpu(*dd->ipath_hdrqtailptr),
--				   dd->ipath_port0head,
-+				   pd->port_head,
- 				   (unsigned long long)
- 				   ipath_stats.sps_port0pkts);
- 		}
-@@ -237,7 +238,7 @@ static void ipath_chk_errormask(struct ipath_devdata *dd)
- void ipath_get_faststats(unsigned long opaque)
- {
- 	struct ipath_devdata *dd = (struct ipath_devdata *) opaque;
--	u32 val;
-+	int i;
- 	static unsigned cnt;
- 	unsigned long flags;
- 	u64 traffic_wds;
-@@ -321,12 +322,11 @@ void ipath_get_faststats(unsigned long opaque)
- 
- 	/* limit qfull messages to ~one per minute per port */
- 	if ((++cnt & 0x10)) {
--		for (val = dd->ipath_cfgports - 1; ((int)val) >= 0;
--		     val--) {
--			if (dd->ipath_lastegrheads[val] != -1)
--				dd->ipath_lastegrheads[val] = -1;
--			if (dd->ipath_lastrcvhdrqtails[val] != -1)
--				dd->ipath_lastrcvhdrqtails[val] = -1;
-+		for (i = (int) dd->ipath_cfgports; --i >= 0; ) {
-+			struct ipath_portdata *pd = dd->ipath_pd[i];
++	nesqp->pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 256, &nesqp->pbl_pbase);
++	pblbuffer = nesqp->pbl_vbase;
++	if (!nesqp->pbl_vbase) {
++		/* memory allocated during nes_reg_user_mr() */
++		pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
++				    nespbl->pbl_pbase);
++		kfree(nespbl);
++		spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++		nesadapter->free_256pbl++;
++		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++		kunmap(nesqp->page);
++		return -ENOMEM;
++	}
++	memset(nesqp->pbl_vbase, 0, 256);
++	/* fill in the page address in the pbl buffer.. */
++	tpbl = pblbuffer + 16;
++	pbl = (__le64 *)nespbl->pbl_vbase;
++	while (sq_pbl_entries--)
++		*tpbl++ = *pbl++;
++	tpbl = pblbuffer;
++	while (rq_pbl_entries--)
++		*tpbl++ = *pbl++;
++
++	/* done with memory allocated during nes_reg_user_mr() */
++	pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
++			    nespbl->pbl_pbase);
++	kfree(nespbl);
++
++	nesqp->qp_mem_size =
++			max((u32)sizeof(struct nes_qp_context), ((u32)256)) + 256;     /* this is Q2 */
++	/* Round up to a multiple of a page */
++	nesqp->qp_mem_size += PAGE_SIZE - 1;
++	nesqp->qp_mem_size &= ~(PAGE_SIZE - 1);
 +
-+			if (pd && pd->port_lastrcvhdrqtail != -1)
-+				pd->port_lastrcvhdrqtail = -1;
- 		}
- 	}
- 
-diff --git a/drivers/infiniband/hw/ipath/ipath_sysfs.c b/drivers/infiniband/hw/ipath/ipath_sysfs.c
-index e1ad7cf..56dfc8a 100644
---- a/drivers/infiniband/hw/ipath/ipath_sysfs.c
-+++ b/drivers/infiniband/hw/ipath/ipath_sysfs.c
-@@ -363,6 +363,60 @@ static ssize_t show_unit(struct device *dev,
- 	return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
- }
- 
-+static ssize_t show_jint_max_packets(struct device *dev,
-+				     struct device_attribute *attr,
-+				     char *buf)
++	mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size,
++			&nesqp->hwqp.q2_pbase);
++
++	if (!mem) {
++		pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase);
++		nesqp->pbl_vbase = NULL;
++		spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++		nesadapter->free_256pbl++;
++		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++		kunmap(nesqp->page);
++		return -ENOMEM;
++	}
++	nesqp->hwqp.q2_vbase = mem;
++	mem += 256;
++	memset(nesqp->hwqp.q2_vbase, 0, 256);
++	nesqp->nesqp_context = mem;
++	memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context));
++	nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256;
++
++	return 0;
++}
++
++
++/**
++ * nes_setup_mmap_qp
++ */
++static int nes_setup_mmap_qp(struct nes_qp *nesqp, struct nes_vnic *nesvnic,
++		int sq_size, int rq_size)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	void *mem;
++	struct nes_device *nesdev = nesvnic->nesdev;
 +
-+	return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_max_packets);
++	nesqp->qp_mem_size = (sizeof(struct nes_hw_qp_wqe) * sq_size) +
++			(sizeof(struct nes_hw_qp_wqe) * rq_size) +
++			max((u32)sizeof(struct nes_qp_context), ((u32)256)) +
++			256; /* this is Q2 */
++	/* Round up to a multiple of a page */
++	nesqp->qp_mem_size += PAGE_SIZE - 1;
++	nesqp->qp_mem_size &= ~(PAGE_SIZE - 1);
++
++	mem = pci_alloc_consistent(nesdev->pcidev, nesqp->qp_mem_size,
++			&nesqp->hwqp.sq_pbase);
++	if (!mem)
++		return -ENOMEM;
++	nes_debug(NES_DBG_QP, "PCI consistent memory for "
++			"host descriptor rings located @ %p (pa = 0x%08lX.) size = %u.\n",
++			mem, (unsigned long)nesqp->hwqp.sq_pbase, nesqp->qp_mem_size);
++
++	memset(mem, 0, nesqp->qp_mem_size);
++
++	nesqp->hwqp.sq_vbase = mem;
++	mem += sizeof(struct nes_hw_qp_wqe) * sq_size;
++
++	nesqp->hwqp.rq_vbase = mem;
++	nesqp->hwqp.rq_pbase = nesqp->hwqp.sq_pbase +
++			sizeof(struct nes_hw_qp_wqe) * sq_size;
++	mem += sizeof(struct nes_hw_qp_wqe) * rq_size;
++
++	nesqp->hwqp.q2_vbase = mem;
++	nesqp->hwqp.q2_pbase = nesqp->hwqp.rq_pbase +
++			sizeof(struct nes_hw_qp_wqe) * rq_size;
++	mem += 256;
++	memset(nesqp->hwqp.q2_vbase, 0, 256);
++
++	nesqp->nesqp_context = mem;
++	nesqp->nesqp_context_pbase = nesqp->hwqp.q2_pbase + 256;
++	memset(nesqp->nesqp_context, 0, sizeof(*nesqp->nesqp_context));
++	return 0;
 +}
 +
-+static ssize_t store_jint_max_packets(struct device *dev,
-+				      struct device_attribute *attr,
-+				      const char *buf,
-+				      size_t count)
++
++/**
++ * nes_free_qp_mem() is to free up the qp's pci_alloc_consistent() memory.
++ */
++static inline void nes_free_qp_mem(struct nes_device *nesdev,
++		struct nes_qp *nesqp, int virt_wqs)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	u16 v = 0;
++	unsigned long flags;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	if (!virt_wqs) {
++		pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size,
++				nesqp->hwqp.sq_vbase, nesqp->hwqp.sq_pbase);
++	}else {
++		spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++		nesadapter->free_256pbl++;
++		spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++		pci_free_consistent(nesdev->pcidev, nesqp->qp_mem_size, nesqp->hwqp.q2_vbase, nesqp->hwqp.q2_pbase);
++		pci_free_consistent(nesdev->pcidev, 256, nesqp->pbl_vbase, nesqp->pbl_pbase );
++		nesqp->pbl_vbase = NULL;
++		kunmap(nesqp->page);
++	}
++}
++
++
++/**
++ * nes_create_qp
++ */
++static struct ib_qp *nes_create_qp(struct ib_pd *ibpd,
++		struct ib_qp_init_attr *init_attr, struct ib_udata *udata)
++{
++	u64 u64temp= 0;
++	u64 u64nesqp = 0;
++	struct nes_pd *nespd = to_nespd(ibpd);
++	struct nes_vnic *nesvnic = to_nesvnic(ibpd->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_qp *nesqp;
++	struct nes_cq *nescq;
++	struct nes_ucontext *nes_ucontext;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_cqp_request *cqp_request;
++	struct nes_create_qp_req req;
++	struct nes_create_qp_resp uresp;
++	struct nes_pbl  *nespbl = NULL;
++	u32 qp_num = 0;
++	u32 opcode = 0;
++	/* u32 counter = 0; */
++	void *mem;
++	unsigned long flags;
 +	int ret;
++	int err;
++	int virt_wqs = 0;
++	int sq_size;
++	int rq_size;
++	u8 sq_encoded_size;
++	u8 rq_encoded_size;
++	/* int counter; */
++
++	atomic_inc(&qps_created);
++	switch (init_attr->qp_type) {
++		case IB_QPT_RC:
++			if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) {
++				init_attr->cap.max_inline_data = 0;
++			} else {
++				init_attr->cap.max_inline_data = 64;
++			}
++			sq_size = init_attr->cap.max_send_wr;
++			rq_size = init_attr->cap.max_recv_wr;
 +
-+	ret = ipath_parse_ushort(buf, &v);
-+	if (ret < 0)
-+		ipath_dev_err(dd, "invalid jint_max_packets.\n");
-+	else
-+		dd->ipath_f_config_jint(dd, dd->ipath_jint_idle_ticks, v);
++			// check if the encoded sizes are OK or not...
++			sq_encoded_size = nes_get_encoded_size(&sq_size);
++			rq_encoded_size = nes_get_encoded_size(&rq_size);
++
++			if ((!sq_encoded_size) || (!rq_encoded_size)) {
++				nes_debug(NES_DBG_QP, "ERROR bad rq (%u) or sq (%u) size\n",
++						rq_size, sq_size);
++				return ERR_PTR(-EINVAL);
++			}
 +
-+	return ret;
++			init_attr->cap.max_send_wr = sq_size -2;
++			init_attr->cap.max_recv_wr = rq_size -1;
++			nes_debug(NES_DBG_QP, "RQ size=%u, SQ Size=%u\n", rq_size, sq_size);
++
++			ret = nes_alloc_resource(nesadapter, nesadapter->allocated_qps,
++					nesadapter->max_qp, &qp_num, &nesadapter->next_qp);
++			if (ret) {
++				return ERR_PTR(ret);
++			}
++
++			/* Need 512 (actually now 1024) byte alignment on this structure */
++			mem = kzalloc(sizeof(*nesqp)+NES_SW_CONTEXT_ALIGN-1, GFP_KERNEL);
++			if (!mem) {
++				nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++				nes_debug(NES_DBG_QP, "Unable to allocate QP\n");
++				return ERR_PTR(-ENOMEM);
++			}
++			u64nesqp = (unsigned long)mem;
++			u64nesqp += ((u64)NES_SW_CONTEXT_ALIGN) - 1;
++			u64temp = ((u64)NES_SW_CONTEXT_ALIGN) - 1;
++			u64nesqp &= ~u64temp;
++			nesqp = (struct nes_qp *)(unsigned long)u64nesqp;
++			/* nes_debug(NES_DBG_QP, "nesqp=%p, allocated buffer=%p.  Rounded to closest %u\n",
++					nesqp, mem, NES_SW_CONTEXT_ALIGN); */
++			nesqp->allocated_buffer = mem;
++
++			if (udata) {
++				if (ib_copy_from_udata(&req, udata, sizeof(struct nes_create_qp_req))) {
++					nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++					kfree(nesqp->allocated_buffer);
++					nes_debug(NES_DBG_QP, "ib_copy_from_udata() Failed \n");
++					return NULL;
++				}
++				if (req.user_wqe_buffers) {
++					virt_wqs = 1;
++				}
++				if ((ibpd->uobject) && (ibpd->uobject->context)) {
++					nesqp->user_mode = 1;
++					nes_ucontext = to_nesucontext(ibpd->uobject->context);
++					if (virt_wqs) {
++						err = 1;
++						list_for_each_entry(nespbl, &nes_ucontext->qp_reg_mem_list, list) {
++							if (nespbl->user_base == (unsigned long )req.user_wqe_buffers) {
++								list_del(&nespbl->list);
++								err = 0;
++								nes_debug(NES_DBG_QP, "Found PBL for virtual QP. nespbl=%p. user_base=0x%lx\n",
++									  nespbl, nespbl->user_base);
++								break;
++							}
++						}
++						if (err) {
++							nes_debug(NES_DBG_QP, "Didn't Find PBL for virtual QP. address = %llx.\n",
++								  (long long unsigned int)req.user_wqe_buffers);
++							nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++							kfree(nesqp->allocated_buffer);
++							return ERR_PTR(-ENOMEM);
++						}
++					}
++
++					nes_ucontext = to_nesucontext(ibpd->uobject->context);
++					nesqp->mmap_sq_db_index =
++						find_next_zero_bit(nes_ucontext->allocated_wqs,
++								   NES_MAX_USER_WQ_REGIONS, nes_ucontext->first_free_wq);
++					/* nes_debug(NES_DBG_QP, "find_first_zero_biton wqs returned %u\n",
++							nespd->mmap_db_index); */
++					if (nesqp->mmap_sq_db_index > NES_MAX_USER_WQ_REGIONS) {
++						nes_debug(NES_DBG_QP,
++							  "db index > max user regions, failing create QP\n");
++						nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++						if (virt_wqs) {
++							pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
++									    nespbl->pbl_pbase);
++							kfree(nespbl);
++						}
++						kfree(nesqp->allocated_buffer);
++						return ERR_PTR(-ENOMEM);
++					}
++					set_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs);
++					nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = nesqp;
++					nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index + 1;
++				} else {
++					nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++					kfree(nesqp->allocated_buffer);
++					return ERR_PTR(-EFAULT);
++				}
++			}
++			err = (!virt_wqs) ? nes_setup_mmap_qp(nesqp, nesvnic, sq_size, rq_size) :
++					nes_setup_virt_qp(nesqp, nespbl, nesvnic, sq_size, rq_size);
++			if (err) {
++				nes_debug(NES_DBG_QP,
++					  "error geting qp mem code = %d\n", err);
++				nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++				kfree(nesqp->allocated_buffer);
++				return ERR_PTR(-ENOMEM);
++			}
++
++			nesqp->hwqp.sq_size = sq_size;
++			nesqp->hwqp.sq_encoded_size = sq_encoded_size;
++			nesqp->hwqp.sq_head = 1;
++			nesqp->hwqp.rq_size = rq_size;
++			nesqp->hwqp.rq_encoded_size = rq_encoded_size;
++			/* nes_debug(NES_DBG_QP, "nesqp->nesqp_context_pbase = %p\n",
++					(void *)nesqp->nesqp_context_pbase);
++			*/
++			nesqp->hwqp.qp_id = qp_num;
++			nesqp->ibqp.qp_num = nesqp->hwqp.qp_id;
++			nesqp->nespd = nespd;
++
++			nescq = to_nescq(init_attr->send_cq);
++			nesqp->nesscq = nescq;
++			nescq = to_nescq(init_attr->recv_cq);
++			nesqp->nesrcq = nescq;
++
++			nesqp->nesqp_context->misc |= cpu_to_le32((u32)PCI_FUNC(nesdev->pcidev->devfn) <<
++					NES_QPCONTEXT_MISC_PCI_FCN_SHIFT);
++			nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.rq_encoded_size <<
++					NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT);
++			nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size <<
++					NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT);
++				nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN);
++				nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN);
++			nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number +
++					((u32)nesqp->nesrcq->hw_cq.cq_number << 16));
++			u64temp = (u64)nesqp->hwqp.sq_pbase;
++			nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp);
++			nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
++
++
++			if (!virt_wqs) {
++				u64temp = (u64)nesqp->hwqp.sq_pbase;
++				nesqp->nesqp_context->sq_addr_low = cpu_to_le32((u32)u64temp);
++				nesqp->nesqp_context->sq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
++				u64temp = (u64)nesqp->hwqp.rq_pbase;
++				nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp);
++				nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
++			} else {
++				u64temp = (u64)nesqp->pbl_pbase;
++				nesqp->nesqp_context->rq_addr_low = cpu_to_le32((u32)u64temp);
++				nesqp->nesqp_context->rq_addr_high = cpu_to_le32((u32)(u64temp >> 32));
++			}
++
++			/* nes_debug(NES_DBG_QP, "next_qp_nic_index=%u, using nic_index=%d\n",
++					nesvnic->next_qp_nic_index,
++					nesvnic->qp_nic_index[nesvnic->next_qp_nic_index]); */
++			spin_lock_irqsave(&nesdev->cqp.lock, flags);
++			nesqp->nesqp_context->misc2 |= cpu_to_le32(
++					(u32)nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] <<
++					NES_QPCONTEXT_MISC2_NIC_INDEX_SHIFT);
++			nesvnic->next_qp_nic_index++;
++			if ((nesvnic->next_qp_nic_index > 3) ||
++					(nesvnic->qp_nic_index[nesvnic->next_qp_nic_index] == 0xf)) {
++				nesvnic->next_qp_nic_index = 0;
++			}
++			spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++
++			nesqp->nesqp_context->pd_index_wscale |= cpu_to_le32((u32)nesqp->nespd->pd_id << 16);
++			u64temp = (u64)nesqp->hwqp.q2_pbase;
++			nesqp->nesqp_context->q2_addr_low = cpu_to_le32((u32)u64temp);
++			nesqp->nesqp_context->q2_addr_high = cpu_to_le32((u32)(u64temp >> 32));
++			nesqp->nesqp_context->aeq_token_low =  cpu_to_le32((u32)((unsigned long)(nesqp)));
++			nesqp->nesqp_context->aeq_token_high =  cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp))));
++			nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM |
++					((((u32)nesadapter->max_irrq_wr) <<
++					NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK));
++			if (disable_mpa_crc) {
++				nes_debug(NES_DBG_QP, "Disabling MPA crc checking due to module option.\n");
++				nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_RNMC);
++			}
++
++
++			/* Create the QP */
++			cqp_request = nes_get_cqp_request(nesdev);
++			if (cqp_request == NULL) {
++				nes_debug(NES_DBG_QP, "Failed to get a cqp_request\n");
++				nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++				nes_free_qp_mem(nesdev, nesqp,virt_wqs);
++				kfree(nesqp->allocated_buffer);
++				return ERR_PTR(-ENOMEM);
++			}
++			cqp_request->waiting = 1;
++			cqp_wqe = &cqp_request->cqp_wqe;
++
++			if (!virt_wqs) {
++				opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP |
++					NES_CQP_QP_IWARP_STATE_IDLE;
++			} else {
++				opcode = NES_CQP_CREATE_QP | NES_CQP_QP_TYPE_IWARP | NES_CQP_QP_VIRT_WQS |
++					NES_CQP_QP_IWARP_STATE_IDLE;
++			}
++			opcode |= NES_CQP_QP_CQS_VALID;
++			nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++			set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
++			set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
++
++			u64temp = (u64)nesqp->nesqp_context_pbase;
++			set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, u64temp);
++
++			atomic_set(&cqp_request->refcount, 2);
++			nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++			/* Wait for CQP */
++			nes_debug(NES_DBG_QP, "Waiting for create iWARP QP%u to complete.\n",
++					nesqp->hwqp.qp_id);
++			ret = wait_event_timeout(cqp_request->waitq,
++					(cqp_request->request_done != 0), NES_EVENT_TIMEOUT);
++			nes_debug(NES_DBG_QP, "Create iwarp QP%u completed, wait_event_timeout ret=%u,"
++					" nesdev->cqp_head = %u, nesdev->cqp.sq_tail = %u,"
++					" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++					nesqp->hwqp.qp_id, ret, nesdev->cqp.sq_head, nesdev->cqp.sq_tail,
++					cqp_request->major_code, cqp_request->minor_code);
++			if ((!ret) || (cqp_request->major_code)) {
++				if (atomic_dec_and_test(&cqp_request->refcount)) {
++					if (cqp_request->dynamic) {
++						kfree(cqp_request);
++					} else {
++						spin_lock_irqsave(&nesdev->cqp.lock, flags);
++						list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++						spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++					}
++				}
++				nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++				nes_free_qp_mem(nesdev, nesqp,virt_wqs);
++				kfree(nesqp->allocated_buffer);
++				if (!ret) {
++					return ERR_PTR(-ETIME);
++				} else {
++					return ERR_PTR(-EIO);
++				}
++			} else {
++				if (atomic_dec_and_test(&cqp_request->refcount)) {
++					if (cqp_request->dynamic) {
++						kfree(cqp_request);
++					} else {
++						spin_lock_irqsave(&nesdev->cqp.lock, flags);
++						list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++						spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++					}
++				}
++			}
++
++			if (ibpd->uobject) {
++				uresp.mmap_sq_db_index = nesqp->mmap_sq_db_index;
++				uresp.actual_sq_size = sq_size;
++				uresp.actual_rq_size = rq_size;
++				uresp.qp_id = nesqp->hwqp.qp_id;
++				uresp.nes_drv_opt = nes_drv_opt;
++				if (ib_copy_to_udata(udata, &uresp, sizeof uresp)) {
++					nes_free_resource(nesadapter, nesadapter->allocated_qps, qp_num);
++					nes_free_qp_mem(nesdev, nesqp,virt_wqs);
++					kfree(nesqp->allocated_buffer);
++					return ERR_PTR(-EFAULT);
++				}
++			}
++
++			nes_debug(NES_DBG_QP, "QP%u structure located @%p.Size = %u.\n",
++					nesqp->hwqp.qp_id, nesqp, (u32)sizeof(*nesqp));
++			spin_lock_init(&nesqp->lock);
++			init_waitqueue_head(&nesqp->state_waitq);
++			init_waitqueue_head(&nesqp->kick_waitq);
++			nes_add_ref(&nesqp->ibqp);
++			break;
++		default:
++			nes_debug(NES_DBG_QP, "Invalid QP type: %d\n", init_attr->qp_type);
++			return ERR_PTR(-EINVAL);
++			break;
++	}
++
++	/* update the QP table */
++	nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp;
++	nes_debug(NES_DBG_QP, "netdev refcnt=%u\n",
++			atomic_read(&nesvnic->netdev->refcnt));
++
++	return &nesqp->ibqp;
 +}
 +
-+static ssize_t show_jint_idle_ticks(struct device *dev,
-+				    struct device_attribute *attr,
-+				    char *buf)
++
++/**
++ * nes_destroy_qp
++ */
++static int nes_destroy_qp(struct ib_qp *ibqp)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	struct nes_qp *nesqp = to_nesqp(ibqp);
++	/* struct nes_vnic *nesvnic = to_nesvnic(ibqp->device); */
++	struct nes_ucontext *nes_ucontext;
++	struct ib_qp_attr attr;
++	struct iw_cm_id *cm_id;
++	struct iw_cm_event cm_event;
++	int ret;
 +
-+	return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_idle_ticks);
++	atomic_inc(&sw_qps_destroyed);
++	nesqp->destroyed = 1;
++
++	/* Blow away the connection if it exists. */
++	if (nesqp->ibqp_state >= IB_QPS_INIT && nesqp->ibqp_state <= IB_QPS_RTS) {
++		/* if (nesqp->ibqp_state == IB_QPS_RTS) { */
++		attr.qp_state = IB_QPS_ERR;
++		nes_modify_qp(&nesqp->ibqp, &attr, IB_QP_STATE, NULL);
++	}
++
++	if (((nesqp->ibqp_state == IB_QPS_INIT) ||
++			(nesqp->ibqp_state == IB_QPS_RTR)) && (nesqp->cm_id)) {
++		cm_id = nesqp->cm_id;
++		cm_event.event = IW_CM_EVENT_CONNECT_REPLY;
++		cm_event.status = IW_CM_EVENT_STATUS_TIMEOUT;
++		cm_event.local_addr = cm_id->local_addr;
++		cm_event.remote_addr = cm_id->remote_addr;
++		cm_event.private_data = NULL;
++		cm_event.private_data_len = 0;
++
++		nes_debug(NES_DBG_QP, "Generating a CM Timeout Event for "
++				"QP%u. cm_id = %p, refcount = %u. \n",
++				nesqp->hwqp.qp_id, cm_id, atomic_read(&nesqp->refcount));
++
++		cm_id->rem_ref(cm_id);
++		ret = cm_id->event_handler(cm_id, &cm_event);
++		if (ret)
++			nes_debug(NES_DBG_QP, "OFA CM event_handler returned, ret=%d\n", ret);
++	}
++
++
++	if (nesqp->user_mode) {
++		if ((ibqp->uobject)&&(ibqp->uobject->context)) {
++			nes_ucontext = to_nesucontext(ibqp->uobject->context);
++			clear_bit(nesqp->mmap_sq_db_index, nes_ucontext->allocated_wqs);
++			nes_ucontext->mmap_nesqp[nesqp->mmap_sq_db_index] = NULL;
++			if (nes_ucontext->first_free_wq > nesqp->mmap_sq_db_index) {
++				nes_ucontext->first_free_wq = nesqp->mmap_sq_db_index;
++			}
++		}
++		if (nesqp->pbl_pbase)
++			kunmap(nesqp->page);
++	}
++
++	nes_rem_ref(&nesqp->ibqp);
++	return 0;
 +}
 +
-+static ssize_t store_jint_idle_ticks(struct device *dev,
-+				     struct device_attribute *attr,
-+				     const char *buf,
-+				     size_t count)
++
++/**
++ * nes_create_cq
++ */
++static struct ib_cq *nes_create_cq(struct ib_device *ibdev, int entries,
++		int comp_vector,
++		struct ib_ucontext *context, struct ib_udata *udata)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	u16 v = 0;
++	u64 u64temp;
++	struct nes_vnic *nesvnic = to_nesvnic(ibdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_cq *nescq;
++	struct nes_ucontext *nes_ucontext = NULL;
++	struct nes_cqp_request *cqp_request;
++	void *mem = NULL;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_pbl *nespbl = NULL;
++	struct nes_create_cq_req req;
++	struct nes_create_cq_resp resp;
++	u32 cq_num = 0;
++	u32 opcode = 0;
++	u32 pbl_entries = 1;
++	int err;
++	unsigned long flags;
 +	int ret;
 +
-+	ret = ipath_parse_ushort(buf, &v);
-+	if (ret < 0)
-+		ipath_dev_err(dd, "invalid jint_idle_ticks.\n");
-+	else
-+		dd->ipath_f_config_jint(dd, v, dd->ipath_jint_max_packets);
++	err = nes_alloc_resource(nesadapter, nesadapter->allocated_cqs,
++			nesadapter->max_cq, &cq_num, &nesadapter->next_cq);
++	if (err) {
++		return ERR_PTR(err);
++	}
 +
-+	return ret;
++	nescq = kzalloc(sizeof(struct nes_cq), GFP_KERNEL);
++	if (!nescq) {
++		nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++		nes_debug(NES_DBG_CQ, "Unable to allocate nes_cq struct\n");
++		return ERR_PTR(-ENOMEM);
++	}
++
++	nescq->hw_cq.cq_size = max(entries + 1, 5);
++	nescq->hw_cq.cq_number = cq_num;
++	nescq->ibcq.cqe = nescq->hw_cq.cq_size - 1;
++
++
++	if (context) {
++		nes_ucontext = to_nesucontext(context);
++		if (ib_copy_from_udata(&req, udata, sizeof (struct nes_create_cq_req))) {
++			nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++			kfree(nescq);
++			return ERR_PTR(-EFAULT);
++		}
++		nesvnic->mcrq_ucontext = nes_ucontext;
++		nes_ucontext->mcrqf = req.mcrqf;
++		if (nes_ucontext->mcrqf) {
++			if (nes_ucontext->mcrqf & 0x80000000)
++				nescq->hw_cq.cq_number = nesvnic->nic.qp_id + 12 + (nes_ucontext->mcrqf & 0xf) - 1;
++			else if (nes_ucontext->mcrqf & 0x40000000)
++				nescq->hw_cq.cq_number = nes_ucontext->mcrqf & 0xffff;
++			else
++				nescq->hw_cq.cq_number = nesvnic->mcrq_qp_id + nes_ucontext->mcrqf-1;
++			nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++		}
++		nes_debug(NES_DBG_CQ, "CQ Virtual Address = %08lX, size = %u.\n",
++				(unsigned long)req.user_cq_buffer, entries);
++		list_for_each_entry(nespbl, &nes_ucontext->cq_reg_mem_list, list) {
++			if (nespbl->user_base == (unsigned long )req.user_cq_buffer) {
++				list_del(&nespbl->list);
++				err = 0;
++				nes_debug(NES_DBG_CQ, "Found PBL for virtual CQ. nespbl=%p.\n",
++						nespbl);
++				break;
++			}
++		}
++		if (err) {
++			nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++			kfree(nescq);
++			return ERR_PTR(err);
++		}
++
++		pbl_entries = nespbl->pbl_size >> 3;
++		nescq->cq_mem_size = 0;
++	} else {
++		nescq->cq_mem_size = nescq->hw_cq.cq_size * sizeof(struct nes_hw_cqe);
++		nes_debug(NES_DBG_CQ, "Attempting to allocate pci memory (%u entries, %u bytes) for CQ%u.\n",
++				entries, nescq->cq_mem_size, nescq->hw_cq.cq_number);
++
++		/* allocate the physical buffer space */
++		mem = pci_alloc_consistent(nesdev->pcidev, nescq->cq_mem_size,
++				&nescq->hw_cq.cq_pbase);
++		if (!mem) {
++			printk(KERN_ERR PFX "Unable to allocate pci memory for cq\n");
++			nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++			kfree(nescq);
++			return ERR_PTR(-ENOMEM);
++		}
++
++		memset(mem, 0, nescq->cq_mem_size);
++		nescq->hw_cq.cq_vbase = mem;
++		nescq->hw_cq.cq_head = 0;
++		nes_debug(NES_DBG_CQ, "CQ%u virtual address @ %p, phys = 0x%08X\n",
++				nescq->hw_cq.cq_number, nescq->hw_cq.cq_vbase,
++				(u32)nescq->hw_cq.cq_pbase);
++	}
++
++	nescq->hw_cq.ce_handler = nes_iwarp_ce_handler;
++	spin_lock_init(&nescq->lock);
++
++	/* send CreateCQ request to CQP */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n");
++		if (!context)
++			pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
++					nescq->hw_cq.cq_pbase);
++		nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++		kfree(nescq);
++		return ERR_PTR(-ENOMEM);
++	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
++
++	opcode = NES_CQP_CREATE_CQ | NES_CQP_CQ_CEQ_VALID |
++			NES_CQP_CQ_CHK_OVERFLOW |
++			NES_CQP_CQ_CEQE_MASK | ((u32)nescq->hw_cq.cq_size << 16);
++
++	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++
++	if (pbl_entries != 1) {
++		if (pbl_entries > 32) {
++			/* use 4k pbl */
++			nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 4k PBL\n", pbl_entries);
++			if (nesadapter->free_4kpbl == 0) {
++				if (cqp_request->dynamic) {
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++					kfree(cqp_request);
++				} else {
++					list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				}
++				if (!context)
++					pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
++							nescq->hw_cq.cq_pbase);
++				nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++				kfree(nescq);
++				return ERR_PTR(-ENOMEM);
++			} else {
++				opcode |= (NES_CQP_CQ_VIRT | NES_CQP_CQ_4KB_CHUNK);
++				nescq->virtual_cq = 2;
++				nesadapter->free_4kpbl--;
++			}
++		} else {
++			/* use 256 byte pbl */
++			nes_debug(NES_DBG_CQ, "pbl_entries=%u, use a 256 byte PBL\n", pbl_entries);
++			if (nesadapter->free_256pbl == 0) {
++				if (cqp_request->dynamic) {
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++					kfree(cqp_request);
++				} else {
++					list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				}
++				if (!context)
++					pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
++							nescq->hw_cq.cq_pbase);
++				nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++				kfree(nescq);
++				return ERR_PTR(-ENOMEM);
++			} else {
++				opcode |= NES_CQP_CQ_VIRT;
++				nescq->virtual_cq = 1;
++				nesadapter->free_256pbl--;
++			}
++		}
++	}
++
++	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
++			(nescq->hw_cq.cq_number | ((u32)nesdev->ceq_index << 16)));
++
++	if (context) {
++		if (pbl_entries != 1)
++			u64temp = (u64)nespbl->pbl_pbase;
++		else
++			u64temp	= le64_to_cpu(nespbl->pbl_vbase[0]);
++		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX,
++				nes_ucontext->mmap_db_index[0]);
++	} else {
++		u64temp = (u64)nescq->hw_cq.cq_pbase;
++		cqp_wqe->wqe_words[NES_CQP_CQ_WQE_DOORBELL_INDEX_HIGH_IDX] = 0;
++	}
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_CQ_WQE_PBL_LOW_IDX, u64temp);
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] = 0;
++	u64temp = (u64)(unsigned long)&nescq->hw_cq;
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_LOW_IDX] =
++			cpu_to_le32((u32)(u64temp >> 1));
++	cqp_wqe->wqe_words[NES_CQP_CQ_WQE_CQ_CONTEXT_HIGH_IDX] =
++			cpu_to_le32(((u32)((u64temp) >> 33)) & 0x7FFFFFFF);
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	nes_debug(NES_DBG_CQ, "Waiting for create iWARP CQ%u to complete.\n",
++			nescq->hw_cq.cq_number);
++	ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
++			NES_EVENT_TIMEOUT * 2);
++	nes_debug(NES_DBG_CQ, "Create iWARP CQ%u completed, wait_event_timeout ret = %d.\n",
++			nescq->hw_cq.cq_number, ret);
++	if ((!ret) || (cqp_request->major_code)) {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++		nes_debug(NES_DBG_CQ, "iWARP CQ%u create timeout expired, major code = 0x%04X,"
++				" minor code = 0x%04X\n",
++				nescq->hw_cq.cq_number, cqp_request->major_code, cqp_request->minor_code);
++		if (!context)
++			pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size, mem,
++					nescq->hw_cq.cq_pbase);
++		nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++		kfree(nescq);
++		return ERR_PTR(-EIO);
++	} else {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++	}
++
++	if (context) {
++		/* free the nespbl */
++		pci_free_consistent(nesdev->pcidev, nespbl->pbl_size, nespbl->pbl_vbase,
++				nespbl->pbl_pbase);
++		kfree(nespbl);
++		resp.cq_id = nescq->hw_cq.cq_number;
++		resp.cq_size = nescq->hw_cq.cq_size;
++		resp.mmap_db_index = 0;
++		if (ib_copy_to_udata(udata, &resp, sizeof resp)) {
++			nes_free_resource(nesadapter, nesadapter->allocated_cqs, cq_num);
++			kfree(nescq);
++			return ERR_PTR(-EFAULT);
++		}
++	}
++
++	return &nescq->ibcq;
 +}
 +
- #define DEVICE_COUNTER(name, attr) \
- 	static ssize_t show_counter_##name(struct device *dev, \
- 					   struct device_attribute *attr, \
-@@ -670,6 +724,257 @@ static ssize_t show_logged_errs(struct device *dev,
- 	return count;
- }
- 
-+/*
-+ * New sysfs entries to control various IB config. These all turn into
-+ * accesses via ipath_f_get/set_ib_cfg.
-+ *
-+ * Get/Set heartbeat enable. Or of 1=enabled, 2=auto
++
++/**
++ * nes_destroy_cq
 + */
-+static ssize_t show_hrtbt_enb(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
++static int nes_destroy_cq(struct ib_cq *ib_cq)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	struct nes_cq *nescq;
++	struct nes_device *nesdev;
++	struct nes_vnic *nesvnic;
++	struct nes_adapter *nesadapter;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_cqp_request *cqp_request;
++	unsigned long flags;
++	u32 opcode = 0;
 +	int ret;
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_HRTBT);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
++	if (ib_cq == NULL)
++		return 0;
++
++	nescq = to_nescq(ib_cq);
++	nesvnic = to_nesvnic(ib_cq->device);
++	nesdev = nesvnic->nesdev;
++	nesadapter = nesdev->nesadapter;
++
++	nes_debug(NES_DBG_CQ, "Destroy CQ%u\n", nescq->hw_cq.cq_number);
++
++	/* Send DestroyCQ request to CQP */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_CQ, "Failed to get a cqp_request.\n");
++		return -ENOMEM;
++	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
++	opcode = NES_CQP_DESTROY_CQ | (nescq->hw_cq.cq_size << 16);
++	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++	if (nescq->virtual_cq == 1) {
++		nesadapter->free_256pbl++;
++		if (nesadapter->free_256pbl > nesadapter->max_256pbl) {
++			printk(KERN_ERR PFX "%s: free 256B PBLs(%u) has exceeded the max(%u)\n",
++					__FUNCTION__, nesadapter->free_256pbl, nesadapter->max_256pbl);
++		}
++	} else if (nescq->virtual_cq == 2) {
++		nesadapter->free_4kpbl++;
++		if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {
++			printk(KERN_ERR PFX "%s: free 4K PBLs(%u) has exceeded the max(%u)\n",
++					__FUNCTION__, nesadapter->free_4kpbl, nesadapter->max_4kpbl);
++		}
++		opcode |= NES_CQP_CQ_4KB_CHUNK;
++	}
++
++	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX,
++		(nescq->hw_cq.cq_number | ((u32)PCI_FUNC(nesdev->pcidev->devfn) << 16)));
++	nes_free_resource(nesadapter, nesadapter->allocated_cqs, nescq->hw_cq.cq_number);
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	nes_debug(NES_DBG_CQ, "Waiting for destroy iWARP CQ%u to complete.\n",
++			nescq->hw_cq.cq_number);
++	ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_CQ, "Destroy iWARP CQ%u completed, wait_event_timeout ret = %u,"
++			" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++			nescq->hw_cq.cq_number, ret, cqp_request->major_code,
++			cqp_request->minor_code);
++	if ((!ret) || (cqp_request->major_code)) {
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++		if (!ret) {
++			nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy timeout expired\n",
++					nescq->hw_cq.cq_number);
++			ret = -ETIME;
++		} else {
++			nes_debug(NES_DBG_CQ, "iWARP CQ%u destroy failed\n",
++					nescq->hw_cq.cq_number);
++			ret = -EIO;
++		}
++	} else {
++		ret = 0;
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++	}
++
++	if (nescq->cq_mem_size)
++		pci_free_consistent(nesdev->pcidev, nescq->cq_mem_size,
++				(void *)nescq->hw_cq.cq_vbase, nescq->hw_cq.cq_pbase);
++	kfree(nescq);
++
 +	return ret;
 +}
 +
-+static ssize_t store_hrtbt_enb(struct device *dev,
-+			  struct device_attribute *attr,
-+			  const char *buf,
-+			  size_t count)
++
++/**
++ * nes_reg_mr
++ */
++static int nes_reg_mr(struct nes_device *nesdev, struct nes_pd *nespd,
++		u32 stag, u64 region_length, struct nes_root_vpbl *root_vpbl,
++		dma_addr_t single_buffer, u16 pbl_count, u16 residual_page_count,
++		int acc, u64 *iova_start)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret, r;
-+	u16 val;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_cqp_request *cqp_request;
++	unsigned long flags;
++	int ret;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	/* int count; */
++	u32 opcode = 0;
++	u16 major_code;
++
++	/* Register the region with the adapter */
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
++		return -ENOMEM;
++	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
 +
-+	ret = ipath_parse_ushort(buf, &val);
-+	if (ret >= 0 && val > 3)
-+		ret = -EINVAL;
-+	if (ret < 0) {
-+		ipath_dev_err(dd, "attempt to set invalid Heartbeat enable\n");
-+		goto bail;
++	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++	/* track PBL resources */
++	if (pbl_count != 0) {
++		if (pbl_count > 1) {
++			/* Two level PBL */
++			if ((pbl_count+1) > nesadapter->free_4kpbl) {
++				nes_debug(NES_DBG_MR, "Out of 4KB Pbls for two level request.\n");
++				if (cqp_request->dynamic) {
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++					kfree(cqp_request);
++				} else {
++					list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				}
++				return -ENOMEM;
++			} else {
++				nesadapter->free_4kpbl -= pbl_count+1;
++			}
++		} else if (residual_page_count > 32) {
++			if (pbl_count > nesadapter->free_4kpbl) {
++				nes_debug(NES_DBG_MR, "Out of 4KB Pbls.\n");
++				if (cqp_request->dynamic) {
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++					kfree(cqp_request);
++				} else {
++					list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				}
++				return -ENOMEM;
++			} else {
++				nesadapter->free_4kpbl -= pbl_count;
++			}
++		} else {
++			if (pbl_count > nesadapter->free_256pbl) {
++				nes_debug(NES_DBG_MR, "Out of 256B Pbls.\n");
++				if (cqp_request->dynamic) {
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++					kfree(cqp_request);
++				} else {
++					list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++					spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++				}
++				return -ENOMEM;
++			} else {
++				nesadapter->free_256pbl -= pbl_count;
++			}
++		}
 +	}
 +
-+	/*
-+	 * Set the "intentional" heartbeat enable per either of
-+	 * "Enable" and "Auto", as these are normally set together.
-+	 * This bit is consulted when leaving loopback mode,
-+	 * because entering loopback mode overrides it and automatically
-+	 * disables heartbeat.
-+	 */
-+	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, val);
-+	if (r < 0)
-+		ret = r;
-+	else if (val == IPATH_IB_HRTBT_OFF)
-+		dd->ipath_flags |= IPATH_NO_HRTBT;
++	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++
++	opcode = NES_CQP_REGISTER_STAG | NES_CQP_STAG_RIGHTS_LOCAL_READ |
++					NES_CQP_STAG_VA_TO | NES_CQP_STAG_MR;
++	if (acc & IB_ACCESS_LOCAL_WRITE)
++		opcode |= NES_CQP_STAG_RIGHTS_LOCAL_WRITE;
++	if (acc & IB_ACCESS_REMOTE_WRITE)
++		opcode |= NES_CQP_STAG_RIGHTS_REMOTE_WRITE | NES_CQP_STAG_REM_ACC_EN;
++	if (acc & IB_ACCESS_REMOTE_READ)
++		opcode |= NES_CQP_STAG_RIGHTS_REMOTE_READ | NES_CQP_STAG_REM_ACC_EN;
++	if (acc & IB_ACCESS_MW_BIND)
++		opcode |= NES_CQP_STAG_RIGHTS_WINDOW_BIND | NES_CQP_STAG_REM_ACC_EN;
++
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX, opcode);
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_VA_LOW_IDX, *iova_start);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_LEN_LOW_IDX, region_length);
++
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] =
++			cpu_to_le32((u32)(region_length >> 8) & 0xff000000);
++	cqp_wqe->wqe_words[NES_CQP_STAG_WQE_LEN_HIGH_PD_IDX] |=
++			cpu_to_le32(nespd->pd_id & 0x00007fff);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, stag);
++
++	if (pbl_count == 0) {
++		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, single_buffer);
++	} else {
++		set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PA_LOW_IDX, root_vpbl->pbl_pbase);
++		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_BLK_COUNT_IDX, pbl_count);
++		set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_PBL_LEN_IDX,
++				(((pbl_count - 1) * 4096) + (residual_page_count*8)));
++
++		if ((pbl_count > 1) || (residual_page_count > 32))
++			cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX] |= cpu_to_le32(NES_CQP_STAG_PBL_BLK_SIZE);
++	}
++	barrier();
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	ret = wait_event_timeout(cqp_request->waitq, (0 != cqp_request->request_done),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_MR, "Register STag 0x%08X completed, wait_event_timeout ret = %u,"
++			" CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++			stag, ret, cqp_request->major_code, cqp_request->minor_code);
++	major_code = cqp_request->major_code;
++	if (atomic_dec_and_test(&cqp_request->refcount)) {
++		if (cqp_request->dynamic) {
++			kfree(cqp_request);
++		} else {
++			spin_lock_irqsave(&nesdev->cqp.lock, flags);
++			list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++			spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++		}
++	}
++	if (!ret)
++		return -ETIME;
++	else if (major_code)
++		return -EIO;
 +	else
-+		dd->ipath_flags &= ~IPATH_NO_HRTBT;
++		return 0;
 +
-+bail:
-+	return ret;
++	return 0;
 +}
 +
-+/*
-+ * Get/Set Link-widths enabled. Or of 1=1x, 2=4x (this is human/IB centric,
-+ * _not_ the particular encoding of any given chip)
++
++/**
++ * nes_reg_phys_mr
 + */
-+static ssize_t show_lwid_enb(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
++static struct ib_mr *nes_reg_phys_mr(struct ib_pd *ib_pd,
++		struct ib_phys_buf *buffer_list, int num_phys_buf, int acc,
++		u64 * iova_start)
++{
++	u64 region_length;
++	struct nes_pd *nespd = to_nespd(ib_pd);
++	struct nes_vnic *nesvnic = to_nesvnic(ib_pd->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_mr *nesmr;
++	struct ib_mr *ibmr;
++	struct nes_vpbl vpbl;
++	struct nes_root_vpbl root_vpbl;
++	u32 stag;
++	u32 i;
++	u32 stag_index = 0;
++	u32 next_stag_index = 0;
++	u32 driver_key = 0;
++	u32 root_pbl_index = 0;
++	u32 cur_pbl_index = 0;
++	int err = 0, pbl_depth = 0;
++	int ret = 0;
++	u16 pbl_count = 0;
++	u8 single_page = 1;
++	u8 stag_key = 0;
++
++	pbl_depth = 0;
++	region_length = 0;
++	vpbl.pbl_vbase = NULL;
++	root_vpbl.pbl_vbase = NULL;
++	root_vpbl.pbl_pbase = 0;
++
++	get_random_bytes(&next_stag_index, sizeof(next_stag_index));
++	stag_key = (u8)next_stag_index;
++
++	driver_key = 0;
++
++	next_stag_index >>= 8;
++	next_stag_index %= nesadapter->max_mr;
++	if (num_phys_buf > (1024*512)) {
++		return ERR_PTR(-E2BIG);
++	}
++
++	err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs, nesadapter->max_mr,
++			&stag_index, &next_stag_index);
++	if (err) {
++		return ERR_PTR(err);
++	}
++
++	nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
++	if (!nesmr) {
++		nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++		return ERR_PTR(-ENOMEM);
++	}
++
++	for (i = 0; i < num_phys_buf; i++) {
++
++		if ((i & 0x01FF) == 0) {
++			if (root_pbl_index == 1) {
++				/* Allocate the root PBL */
++				root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 8192,
++						&root_vpbl.pbl_pbase);
++				nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n",
++						root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase);
++				if (!root_vpbl.pbl_vbase) {
++					pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
++							vpbl.pbl_pbase);
++					nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++					kfree(nesmr);
++					return ERR_PTR(-ENOMEM);
++				}
++				root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024, GFP_KERNEL);
++				if (!root_vpbl.leaf_vpbl) {
++					pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
++							root_vpbl.pbl_pbase);
++					pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
++							vpbl.pbl_pbase);
++					nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++					kfree(nesmr);
++					return ERR_PTR(-ENOMEM);
++				}
++				root_vpbl.pbl_vbase[0].pa_low = cpu_to_le32((u32)vpbl.pbl_pbase);
++				root_vpbl.pbl_vbase[0].pa_high =
++						cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));
++				root_vpbl.leaf_vpbl[0] = vpbl;
++			}
++			/* Allocate a 4K buffer for the PBL */
++			vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
++					&vpbl.pbl_pbase);
++			nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%016lX\n",
++					vpbl.pbl_vbase, (unsigned long)vpbl.pbl_pbase);
++			if (!vpbl.pbl_vbase) {
++				nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++				ibmr = ERR_PTR(-ENOMEM);
++				kfree(nesmr);
++				goto reg_phys_err;
++			}
++			/* Fill in the root table */
++			if (1 <= root_pbl_index) {
++				root_vpbl.pbl_vbase[root_pbl_index].pa_low =
++						cpu_to_le32((u32)vpbl.pbl_pbase);
++				root_vpbl.pbl_vbase[root_pbl_index].pa_high =
++						cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));
++				root_vpbl.leaf_vpbl[root_pbl_index] = vpbl;
++			}
++			root_pbl_index++;
++			cur_pbl_index = 0;
++		}
++		if (buffer_list[i].addr & ~PAGE_MASK) {
++			/* TODO: Unwind allocated buffers */
++			nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++			nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",
++					(unsigned int) buffer_list[i].addr);
++			ibmr = ERR_PTR(-EINVAL);
++			kfree(nesmr);
++			goto reg_phys_err;
++		}
++
++		if (!buffer_list[i].size) {
++			nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++			nes_debug(NES_DBG_MR, "Invalid Buffer Size\n");
++			ibmr = ERR_PTR(-EINVAL);
++			kfree(nesmr);
++			goto reg_phys_err;
++		}
++
++		region_length += buffer_list[i].size;
++		if ((i != 0) && (single_page)) {
++			if ((buffer_list[i-1].addr+PAGE_SIZE) != buffer_list[i].addr)
++				single_page = 0;
++		}
++		vpbl.pbl_vbase[cur_pbl_index].pa_low = cpu_to_le32((u32)buffer_list[i].addr);
++		vpbl.pbl_vbase[cur_pbl_index++].pa_high =
++				cpu_to_le32((u32)((((u64)buffer_list[i].addr) >> 32)));
++	}
++
++	stag = stag_index << 8;
++	stag |= driver_key;
++	stag += (u32)stag_key;
++
++	nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%016lX,"
++			" length = 0x%016lX, index = 0x%08X\n",
++			stag, (unsigned long)*iova_start, (unsigned long)region_length, stag_index);
++
++	region_length -= (*iova_start)&PAGE_MASK;
++
++	/* Make the leaf PBL the root if only one PBL */
++	if (root_pbl_index == 1) {
++		root_vpbl.pbl_pbase = vpbl.pbl_pbase;
++	}
++
++	if (single_page) {
++		pbl_count = 0;
++	} else {
++		pbl_count = root_pbl_index;
++	}
++	ret = nes_reg_mr(nesdev, nespd, stag, region_length, &root_vpbl,
++			buffer_list[0].addr, pbl_count, (u16)cur_pbl_index, acc, iova_start);
++
++	if (ret == 0) {
++		nesmr->ibmr.rkey = stag;
++		nesmr->ibmr.lkey = stag;
++		nesmr->mode = IWNES_MEMREG_TYPE_MEM;
++		ibmr = &nesmr->ibmr;
++		nesmr->pbl_4k = ((pbl_count > 1) || (cur_pbl_index > 32)) ? 1 : 0;
++		nesmr->pbls_used = pbl_count;
++		if (pbl_count > 1) {
++			nesmr->pbls_used++;
++		}
++	} else {
++		kfree(nesmr);
++		ibmr = ERR_PTR(-ENOMEM);
++	}
++
++	reg_phys_err:
++	/* free the resources */
++	if (root_pbl_index == 1) {
++		/* single PBL case */
++		pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase, vpbl.pbl_pbase);
++	} else {
++		for (i=0; i<root_pbl_index; i++) {
++			pci_free_consistent(nesdev->pcidev, 4096, root_vpbl.leaf_vpbl[i].pbl_vbase,
++					root_vpbl.leaf_vpbl[i].pbl_pbase);
++		}
++		kfree(root_vpbl.leaf_vpbl);
++		pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
++				root_vpbl.pbl_pbase);
++	}
++
++	return ibmr;
++}
++
++
++/**
++ * nes_get_dma_mr
++ */
++static struct ib_mr *nes_get_dma_mr(struct ib_pd *pd, int acc)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	struct ib_phys_buf bl;
++	u64 kva = 0;
++
++	nes_debug(NES_DBG_MR, "\n");
++
++	bl.size = (u64)0xffffffffffULL;
++	bl.addr = 0;
++	return nes_reg_phys_mr(pd, &bl, 1, acc, &kva);
++}
++
++
++/**
++ * nes_reg_user_mr
++ */
++static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
++		u64 virt, int acc, struct ib_udata *udata)
++{
++	u64 iova_start;
++	__le64 *pbl;
++	u64 region_length;
++	dma_addr_t last_dma_addr = 0;
++	dma_addr_t first_dma_addr = 0;
++	struct nes_pd *nespd = to_nespd(pd);
++	struct nes_vnic *nesvnic = to_nesvnic(pd->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct ib_mr *ibmr = ERR_PTR(-EINVAL);
++	struct ib_umem_chunk *chunk;
++	struct nes_ucontext *nes_ucontext;
++	struct nes_pbl *nespbl;
++	struct nes_mr *nesmr;
++	struct ib_umem *region;
++	struct nes_mem_reg_req req;
++	struct nes_vpbl vpbl;
++	struct nes_root_vpbl root_vpbl;
++	int nmap_index, page_index;
++	int page_count = 0;
++	int err, pbl_depth = 0;
++	int chunk_pages;
 +	int ret;
++	u32 stag;
++	u32 stag_index = 0;
++	u32 next_stag_index;
++	u32 driver_key;
++	u32 root_pbl_index = 0;
++	u32 cur_pbl_index = 0;
++	u32 skip_pages;
++	u16 pbl_count;
++	u8 single_page = 1;
++	u8 stag_key;
++
++	region = ib_umem_get(pd->uobject->context, start, length, acc);
++	if (IS_ERR(region)) {
++		return (struct ib_mr *)region;
++	}
++
++	nes_debug(NES_DBG_MR, "User base = 0x%lX, Virt base = 0x%lX, length = %u,"
++			" offset = %u, page size = %u.\n",
++			(unsigned long int)start, (unsigned long int)virt, (u32)length,
++			region->offset, region->page_size);
++
++	skip_pages = ((u32)region->offset) >> 12;
++
++	if (ib_copy_from_udata(&req, udata, sizeof(req)))
++		return ERR_PTR(-EFAULT);
++	nes_debug(NES_DBG_MR, "Memory Registration type = %08X.\n", req.reg_type);
++
++	switch (req.reg_type) {
++		case IWNES_MEMREG_TYPE_MEM:
++			pbl_depth = 0;
++			region_length = 0;
++			vpbl.pbl_vbase = NULL;
++			root_vpbl.pbl_vbase = NULL;
++			root_vpbl.pbl_pbase = 0;
++
++			get_random_bytes(&next_stag_index, sizeof(next_stag_index));
++			stag_key = (u8)next_stag_index;
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
-+	return ret;
++			driver_key = next_stag_index & 0x70000000;
++
++			next_stag_index >>= 8;
++			next_stag_index %= nesadapter->max_mr;
++
++			err = nes_alloc_resource(nesadapter, nesadapter->allocated_mrs,
++					nesadapter->max_mr, &stag_index, &next_stag_index);
++			if (err) {
++				ib_umem_release(region);
++				return ERR_PTR(err);
++			}
++
++			nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
++			if (!nesmr) {
++				ib_umem_release(region);
++				nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++				return ERR_PTR(-ENOMEM);
++			}
++			nesmr->region = region;
++
++			list_for_each_entry(chunk, &region->chunk_list, list) {
++				nes_debug(NES_DBG_MR, "Chunk: nents = %u, nmap = %u .\n",
++						chunk->nents, chunk->nmap);
++				for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {
++					if (sg_dma_address(&chunk->page_list[nmap_index]) & ~PAGE_MASK) {
++						ib_umem_release(region);
++						nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++						nes_debug(NES_DBG_MR, "Unaligned Memory Buffer: 0x%x\n",
++								(unsigned int) sg_dma_address(&chunk->page_list[nmap_index]));
++						ibmr = ERR_PTR(-EINVAL);
++						kfree(nesmr);
++						goto reg_user_mr_err;
++					}
++
++					if (!sg_dma_len(&chunk->page_list[nmap_index])) {
++						ib_umem_release(region);
++						nes_free_resource(nesadapter, nesadapter->allocated_mrs,
++								stag_index);
++						nes_debug(NES_DBG_MR, "Invalid Buffer Size\n");
++						ibmr = ERR_PTR(-EINVAL);
++						kfree(nesmr);
++						goto reg_user_mr_err;
++					}
++
++					region_length += sg_dma_len(&chunk->page_list[nmap_index]);
++					chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12;
++					region_length -= skip_pages << 12;
++					for (page_index=skip_pages; page_index < chunk_pages; page_index++) {
++						skip_pages = 0;
++						if ((page_count!=0)&&(page_count<<12)-(region->offset&(4096-1))>=region->length)
++							goto enough_pages;
++						if ((page_count&0x01FF) == 0) {
++							if (page_count>(1024*512)) {
++								ib_umem_release(region);
++								pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
++										vpbl.pbl_pbase);
++								nes_free_resource(nesadapter,
++										nesadapter->allocated_mrs, stag_index);
++								kfree(nesmr);
++								ibmr = ERR_PTR(-E2BIG);
++								goto reg_user_mr_err;
++							}
++							if (root_pbl_index == 1) {
++								root_vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev,
++										8192, &root_vpbl.pbl_pbase);
++								nes_debug(NES_DBG_MR, "Allocating root PBL, va = %p, pa = 0x%08X\n",
++										root_vpbl.pbl_vbase, (unsigned int)root_vpbl.pbl_pbase);
++								if (!root_vpbl.pbl_vbase) {
++									ib_umem_release(region);
++									pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
++											vpbl.pbl_pbase);
++									nes_free_resource(nesadapter, nesadapter->allocated_mrs,
++											stag_index);
++									kfree(nesmr);
++									ibmr = ERR_PTR(-ENOMEM);
++									goto reg_user_mr_err;
++								}
++								root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024,
++										GFP_KERNEL);
++								if (!root_vpbl.leaf_vpbl) {
++									ib_umem_release(region);
++									pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
++											root_vpbl.pbl_pbase);
++									pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
++											vpbl.pbl_pbase);
++									nes_free_resource(nesadapter, nesadapter->allocated_mrs,
++											stag_index);
++									kfree(nesmr);
++									ibmr = ERR_PTR(-ENOMEM);
++									goto reg_user_mr_err;
++								}
++								root_vpbl.pbl_vbase[0].pa_low =
++										cpu_to_le32((u32)vpbl.pbl_pbase);
++								root_vpbl.pbl_vbase[0].pa_high =
++										cpu_to_le32((u32)((((u64)vpbl.pbl_pbase) >> 32)));
++								root_vpbl.leaf_vpbl[0] = vpbl;
++							}
++							vpbl.pbl_vbase = pci_alloc_consistent(nesdev->pcidev, 4096,
++									&vpbl.pbl_pbase);
++							nes_debug(NES_DBG_MR, "Allocating leaf PBL, va = %p, pa = 0x%08X\n",
++									vpbl.pbl_vbase, (unsigned int)vpbl.pbl_pbase);
++							if (!vpbl.pbl_vbase) {
++								ib_umem_release(region);
++								nes_free_resource(nesadapter, nesadapter->allocated_mrs, stag_index);
++								ibmr = ERR_PTR(-ENOMEM);
++								kfree(nesmr);
++								goto reg_user_mr_err;
++							}
++							if (1 <= root_pbl_index) {
++								root_vpbl.pbl_vbase[root_pbl_index].pa_low =
++										cpu_to_le32((u32)vpbl.pbl_pbase);
++								root_vpbl.pbl_vbase[root_pbl_index].pa_high =
++										cpu_to_le32((u32)((((u64)vpbl.pbl_pbase)>>32)));
++								root_vpbl.leaf_vpbl[root_pbl_index] = vpbl;
++							}
++							root_pbl_index++;
++							cur_pbl_index = 0;
++						}
++						if (single_page) {
++							if (page_count != 0) {
++								if ((last_dma_addr+4096) !=
++										(sg_dma_address(&chunk->page_list[nmap_index])+
++										(page_index*4096)))
++									single_page = 0;
++								last_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+
++										(page_index*4096);
++							} else {
++								first_dma_addr = sg_dma_address(&chunk->page_list[nmap_index])+
++										(page_index*4096);
++								last_dma_addr = first_dma_addr;
++							}
++						}
++
++						vpbl.pbl_vbase[cur_pbl_index].pa_low =
++								cpu_to_le32((u32)(sg_dma_address(&chunk->page_list[nmap_index])+
++								(page_index*4096)));
++						vpbl.pbl_vbase[cur_pbl_index].pa_high =
++								cpu_to_le32((u32)((((u64)(sg_dma_address(&chunk->page_list[nmap_index])+
++								(page_index*4096))) >> 32)));
++						cur_pbl_index++;
++						page_count++;
++					}
++				}
++			}
++			enough_pages:
++			nes_debug(NES_DBG_MR, "calculating stag, stag_index=0x%08x, driver_key=0x%08x,"
++					" stag_key=0x%08x\n",
++					stag_index, driver_key, stag_key);
++			stag = stag_index << 8;
++			stag |= driver_key;
++			stag += (u32)stag_key;
++			if (stag == 0) {
++				stag = 1;
++			}
++
++			iova_start = virt;
++			/* Make the leaf PBL the root if only one PBL */
++			if (root_pbl_index == 1) {
++				root_vpbl.pbl_pbase = vpbl.pbl_pbase;
++			}
++
++			if (single_page) {
++				pbl_count = 0;
++			} else {
++				pbl_count = root_pbl_index;
++				first_dma_addr = 0;
++			}
++			nes_debug(NES_DBG_MR, "Registering STag 0x%08X, VA = 0x%08X, length = 0x%08X,"
++					" index = 0x%08X, region->length=0x%08llx, pbl_count = %u\n",
++					stag, (unsigned int)iova_start,
++					(unsigned int)region_length, stag_index,
++					(unsigned long long)region->length, pbl_count);
++			ret = nes_reg_mr( nesdev, nespd, stag, region->length, &root_vpbl,
++					first_dma_addr, pbl_count, (u16)cur_pbl_index, acc, &iova_start);
++
++			nes_debug(NES_DBG_MR, "ret=%d\n", ret);
++
++			if (ret == 0) {
++				nesmr->ibmr.rkey = stag;
++				nesmr->ibmr.lkey = stag;
++				nesmr->mode = IWNES_MEMREG_TYPE_MEM;
++				ibmr = &nesmr->ibmr;
++				nesmr->pbl_4k = ((pbl_count > 1) || (cur_pbl_index > 32)) ? 1 : 0;
++				nesmr->pbls_used = pbl_count;
++				if (pbl_count > 1) {
++					nesmr->pbls_used++;
++				}
++			} else {
++				ib_umem_release(region);
++				kfree(nesmr);
++				ibmr = ERR_PTR(-ENOMEM);
++			}
++
++			reg_user_mr_err:
++			/* free the resources */
++			if (root_pbl_index == 1) {
++				pci_free_consistent(nesdev->pcidev, 4096, vpbl.pbl_vbase,
++						vpbl.pbl_pbase);
++			} else {
++				for (page_index=0; page_index<root_pbl_index; page_index++) {
++					pci_free_consistent(nesdev->pcidev, 4096,
++							root_vpbl.leaf_vpbl[page_index].pbl_vbase,
++							root_vpbl.leaf_vpbl[page_index].pbl_pbase);
++				}
++				kfree(root_vpbl.leaf_vpbl);
++				pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
++						root_vpbl.pbl_pbase);
++			}
++
++			nes_debug(NES_DBG_MR, "Leaving, ibmr=%p", ibmr);
++
++			return ibmr;
++			break;
++		case IWNES_MEMREG_TYPE_QP:
++		case IWNES_MEMREG_TYPE_CQ:
++			nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL);
++			if (!nespbl) {
++				nes_debug(NES_DBG_MR, "Unable to allocate PBL\n");
++				ib_umem_release(region);
++				return ERR_PTR(-ENOMEM);
++			}
++			nesmr = kzalloc(sizeof(*nesmr), GFP_KERNEL);
++			if (!nesmr) {
++				ib_umem_release(region);
++				kfree(nespbl);
++				nes_debug(NES_DBG_MR, "Unable to allocate nesmr\n");
++				return ERR_PTR(-ENOMEM);
++			}
++			nesmr->region = region;
++			nes_ucontext = to_nesucontext(pd->uobject->context);
++			pbl_depth = region->length >> 12;
++			pbl_depth += (region->length & (4096-1)) ? 1 : 0;
++			nespbl->pbl_size = pbl_depth*sizeof(u64);
++			if (req.reg_type == IWNES_MEMREG_TYPE_QP) {
++				nes_debug(NES_DBG_MR, "Attempting to allocate QP PBL memory");
++			} else {
++				nes_debug(NES_DBG_MR, "Attempting to allocate CP PBL memory");
++			}
++
++			nes_debug(NES_DBG_MR, " %u bytes, %u entries.\n",
++					nespbl->pbl_size, pbl_depth);
++			pbl = pci_alloc_consistent(nesdev->pcidev, nespbl->pbl_size,
++					&nespbl->pbl_pbase);
++			if (!pbl) {
++				ib_umem_release(region);
++				kfree(nesmr);
++				kfree(nespbl);
++				nes_debug(NES_DBG_MR, "Unable to allocate PBL memory\n");
++				return ERR_PTR(-ENOMEM);
++			}
++
++			nespbl->pbl_vbase = (u64 *)pbl;
++			nespbl->user_base = start;
++			nes_debug(NES_DBG_MR, "Allocated PBL memory, %u bytes, pbl_pbase=%p,"
++					" pbl_vbase=%p user_base=0x%lx\n",
++					nespbl->pbl_size, (void *)nespbl->pbl_pbase,
++					(void*)nespbl->pbl_vbase, nespbl->user_base);
++
++			list_for_each_entry(chunk, &region->chunk_list, list) {
++				for (nmap_index = 0; nmap_index < chunk->nmap; ++nmap_index) {
++					chunk_pages = sg_dma_len(&chunk->page_list[nmap_index]) >> 12;
++					chunk_pages += (sg_dma_len(&chunk->page_list[nmap_index]) & (4096-1)) ? 1 : 0;
++					nespbl->page = sg_page(&chunk->page_list[0]);
++					for (page_index=0; page_index<chunk_pages; page_index++) {
++						((__le32 *)pbl)[0] = cpu_to_le32((u32)
++								(sg_dma_address(&chunk->page_list[nmap_index])+
++								(page_index*4096)));
++						((__le32 *)pbl)[1] = cpu_to_le32(((u64)
++								(sg_dma_address(&chunk->page_list[nmap_index])+
++								(page_index*4096)))>>32);
++						nes_debug(NES_DBG_MR, "pbl=%p, *pbl=0x%016llx, 0x%08x%08x\n", pbl,
++								(unsigned long long)*pbl,
++								le32_to_cpu(((__le32 *)pbl)[1]), le32_to_cpu(((__le32 *)pbl)[0]));
++						pbl++;
++					}
++				}
++			}
++			if (req.reg_type == IWNES_MEMREG_TYPE_QP) {
++				list_add_tail(&nespbl->list, &nes_ucontext->qp_reg_mem_list);
++			} else {
++				list_add_tail(&nespbl->list, &nes_ucontext->cq_reg_mem_list);
++			}
++			nesmr->ibmr.rkey = -1;
++			nesmr->ibmr.lkey = -1;
++			nesmr->mode = req.reg_type;
++			return &nesmr->ibmr;
++			break;
++	}
++
++	return ERR_PTR(-ENOSYS);
 +}
 +
-+static ssize_t store_lwid_enb(struct device *dev,
-+			  struct device_attribute *attr,
-+			  const char *buf,
-+			  size_t count)
++
++/**
++ * nes_dereg_mr
++ */
++static int nes_dereg_mr(struct ib_mr *ib_mr)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret, r;
-+	u16 val;
++	struct nes_mr *nesmr = to_nesmr(ib_mr);
++	struct nes_vnic *nesvnic = to_nesvnic(ib_mr->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	struct nes_cqp_request *cqp_request;
++	unsigned long flags;
++	int ret;
++	u16 major_code;
++	u16 minor_code;
 +
-+	ret = ipath_parse_ushort(buf, &val);
-+	if (ret >= 0 && (val == 0 || val > 3))
-+		ret = -EINVAL;
-+	if (ret < 0) {
-+		ipath_dev_err(dd,
-+			"attempt to set invalid Link Width (enable)\n");
-+		goto bail;
++	if (nesmr->region) {
++		ib_umem_release(nesmr->region);
++	}
++	if (nesmr->mode != IWNES_MEMREG_TYPE_MEM) {
++		kfree(nesmr);
++		return 0;
 +	}
 +
-+	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, val);
-+	if (r < 0)
-+		ret = r;
++	/* Deallocate the region with the adapter */
 +
-+bail:
-+	return ret;
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_MR, "Failed to get a cqp_request.\n");
++		return -ENOMEM;
++	}
++	cqp_request->waiting = 1;
++	cqp_wqe = &cqp_request->cqp_wqe;
++
++	spin_lock_irqsave(&nesadapter->pbl_lock, flags);
++	if (nesmr->pbls_used != 0) {
++		if (nesmr->pbl_4k) {
++			nesadapter->free_4kpbl += nesmr->pbls_used;
++			if (nesadapter->free_4kpbl > nesadapter->max_4kpbl) {
++				printk(KERN_ERR PFX "free 4KB PBLs(%u) has exceeded the max(%u)\n",
++						nesadapter->free_4kpbl, nesadapter->max_4kpbl);
++			}
++		} else {
++			nesadapter->free_256pbl += nesmr->pbls_used;
++			if (nesadapter->free_256pbl > nesadapter->max_256pbl) {
++				printk(KERN_ERR PFX "free 256B PBLs(%u) has exceeded the max(%u)\n",
++						nesadapter->free_256pbl, nesadapter->max_256pbl);
++			}
++		}
++	}
++
++	spin_unlock_irqrestore(&nesadapter->pbl_lock, flags);
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++			NES_CQP_DEALLOCATE_STAG | NES_CQP_STAG_VA_TO |
++			NES_CQP_STAG_DEALLOC_PBLS | NES_CQP_STAG_MR);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_STAG_WQE_STAG_IDX, ib_mr->rkey);
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	nes_debug(NES_DBG_MR, "Waiting for deallocate STag 0x%08X completed\n", ib_mr->rkey);
++	ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
++			NES_EVENT_TIMEOUT);
++	nes_debug(NES_DBG_MR, "Deallocate STag 0x%08X completed, wait_event_timeout ret = %u,"
++			" CQP Major:Minor codes = 0x%04X:0x%04X\n",
++			ib_mr->rkey, ret, cqp_request->major_code, cqp_request->minor_code);
++
++	nes_free_resource(nesadapter, nesadapter->allocated_mrs,
++			(ib_mr->rkey & 0x0fffff00) >> 8);
++
++	kfree(nesmr);
++
++	major_code = cqp_request->major_code;
++	minor_code = cqp_request->minor_code;
++	if (atomic_dec_and_test(&cqp_request->refcount)) {
++		if (cqp_request->dynamic) {
++			kfree(cqp_request);
++		} else {
++			spin_lock_irqsave(&nesdev->cqp.lock, flags);
++			list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++			spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++		}
++	}
++	if (!ret) {
++		nes_debug(NES_DBG_MR, "Timeout waiting to destroy STag,"
++				" ib_mr=%p, rkey = 0x%08X\n",
++				ib_mr, ib_mr->rkey);
++		return -ETIME;
++	} else if (major_code) {
++		nes_debug(NES_DBG_MR, "Error (0x%04X:0x%04X) while attempting"
++				" to destroy STag, ib_mr=%p, rkey = 0x%08X\n",
++				major_code, minor_code, ib_mr, ib_mr->rkey);
++		return -EIO;
++	} else
++		return 0;
 +}
 +
-+/* Get current link width */
-+static ssize_t show_lwid(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
 +
++/**
++ * show_rev
++ */
++static ssize_t show_rev(struct class_device *cdev, char *buf)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret;
++	struct nes_ib_device *nesibdev =
++			container_of(cdev, struct nes_ib_device, ibdev.class_dev);
++	struct nes_vnic *nesvnic = nesibdev->nesvnic;
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
-+	return ret;
++	nes_debug(NES_DBG_INIT, "\n");
++	return sprintf(buf, "%x\n", nesvnic->nesdev->nesadapter->hw_rev);
 +}
 +
-+/*
-+ * Get/Set Link-speeds enabled. Or of 1=SDR 2=DDR.
++
++/**
++ * show_fw_ver
 + */
-+static ssize_t show_spd_enb(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
++static ssize_t show_fw_ver(struct class_device *cdev, char *buf)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret;
++	struct nes_ib_device *nesibdev =
++			container_of(cdev, struct nes_ib_device, ibdev.class_dev);
++	struct nes_vnic *nesvnic = nesibdev->nesvnic;
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
-+	return ret;
++	nes_debug(NES_DBG_INIT, "\n");
++	return sprintf(buf, "%x.%x.%x\n",
++			(int)(nesvnic->nesdev->nesadapter->fw_ver >> 32),
++			(int)(nesvnic->nesdev->nesadapter->fw_ver >> 16) & 0xffff,
++			(int)(nesvnic->nesdev->nesadapter->fw_ver & 0xffff));
 +}
 +
-+static ssize_t store_spd_enb(struct device *dev,
-+			  struct device_attribute *attr,
-+			  const char *buf,
-+			  size_t count)
++
++/**
++ * show_hca
++ */
++static ssize_t show_hca(struct class_device *cdev, char *buf)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret, r;
-+	u16 val;
++	nes_debug(NES_DBG_INIT, "\n");
++	return sprintf(buf, "NES020\n");
++}
 +
-+	ret = ipath_parse_ushort(buf, &val);
-+	if (ret >= 0 && (val == 0 || val > (IPATH_IB_SDR | IPATH_IB_DDR)))
-+		ret = -EINVAL;
-+	if (ret < 0) {
-+		ipath_dev_err(dd,
-+			"attempt to set invalid Link Speed (enable)\n");
-+		goto bail;
++
++/**
++ * show_board
++ */
++static ssize_t show_board(struct class_device *cdev, char *buf)
++{
++	nes_debug(NES_DBG_INIT, "\n");
++	return sprintf(buf, "%.*s\n", 32, "NES020 Board ID");
++}
++
++
++static CLASS_DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
++static CLASS_DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
++static CLASS_DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
++static CLASS_DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
++
++static struct class_device_attribute *nes_class_attributes[] = {
++	&class_device_attr_hw_rev,
++	&class_device_attr_fw_ver,
++	&class_device_attr_hca_type,
++	&class_device_attr_board_id
++};
++
++
++/**
++ * nes_query_qp
++ */
++static int nes_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
++		int attr_mask, struct ib_qp_init_attr *init_attr)
++{
++	struct nes_qp *nesqp = to_nesqp(ibqp);
++
++	nes_debug(NES_DBG_QP, "\n");
++
++	attr->qp_access_flags = 0;
++	attr->cap.max_send_wr = nesqp->hwqp.sq_size;
++	attr->cap.max_recv_wr = nesqp->hwqp.rq_size;
++	attr->cap.max_recv_sge = 1;
++	if (nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) {
++		init_attr->cap.max_inline_data = 0;
++	} else {
++		init_attr->cap.max_inline_data = 64;
 +	}
 +
-+	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, val);
-+	if (r < 0)
-+		ret = r;
++	init_attr->event_handler = nesqp->ibqp.event_handler;
++	init_attr->qp_context = nesqp->ibqp.qp_context;
++	init_attr->send_cq = nesqp->ibqp.send_cq;
++	init_attr->recv_cq = nesqp->ibqp.recv_cq;
++	init_attr->srq = nesqp->ibqp.srq = nesqp->ibqp.srq;
++	init_attr->cap = attr->cap;
 +
-+bail:
-+	return ret;
++	return 0;
 +}
 +
-+/* Get current link speed */
-+static ssize_t show_spd(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
++
++/**
++ * nes_hw_modify_qp
++ */
++int nes_hw_modify_qp(struct nes_device *nesdev, struct nes_qp *nesqp,
++		u32 next_iwarp_state, u32 wait_completion)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	struct nes_hw_cqp_wqe *cqp_wqe;
++	/* struct iw_cm_id *cm_id = nesqp->cm_id; */
++	/* struct iw_cm_event cm_event; */
++	struct nes_cqp_request *cqp_request;
++	unsigned long flags;
 +	int ret;
++	u16 major_code;
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
-+	return ret;
++	nes_debug(NES_DBG_MOD_QP, "QP%u, refcount=%d\n",
++			nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
++
++	cqp_request = nes_get_cqp_request(nesdev);
++	if (cqp_request == NULL) {
++		nes_debug(NES_DBG_MOD_QP, "Failed to get a cqp_request.\n");
++		return -ENOMEM;
++	}
++	if (wait_completion) {
++		cqp_request->waiting = 1;
++	} else {
++		cqp_request->waiting = 0;
++	}
++	cqp_wqe = &cqp_request->cqp_wqe;
++
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_OPCODE_IDX,
++			NES_CQP_MODIFY_QP | NES_CQP_QP_TYPE_IWARP | next_iwarp_state);
++	nes_debug(NES_DBG_MOD_QP, "using next_iwarp_state=%08x, wqe_words=%08x\n",
++			next_iwarp_state, le32_to_cpu(cqp_wqe->wqe_words[NES_CQP_WQE_OPCODE_IDX]));
++	nes_fill_init_cqp_wqe(cqp_wqe, nesdev);
++	set_wqe_32bit_value(cqp_wqe->wqe_words, NES_CQP_WQE_ID_IDX, nesqp->hwqp.qp_id);
++	set_wqe_64bit_value(cqp_wqe->wqe_words, NES_CQP_QP_WQE_CONTEXT_LOW_IDX, (u64)nesqp->nesqp_context_pbase);
++
++	atomic_set(&cqp_request->refcount, 2);
++	nes_post_cqp_request(nesdev, cqp_request, NES_CQP_REQUEST_RING_DOORBELL);
++
++	/* Wait for CQP */
++	if (wait_completion) {
++		/* nes_debug(NES_DBG_MOD_QP, "Waiting for modify iWARP QP%u to complete.\n",
++				nesqp->hwqp.qp_id); */
++		ret = wait_event_timeout(cqp_request->waitq, (cqp_request->request_done != 0),
++				NES_EVENT_TIMEOUT);
++		nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u completed, wait_event_timeout ret=%u, "
++				"CQP Major:Minor codes = 0x%04X:0x%04X.\n",
++				nesqp->hwqp.qp_id, ret, cqp_request->major_code, cqp_request->minor_code);
++		major_code = cqp_request->major_code;
++		if (major_code) {
++			nes_debug(NES_DBG_MOD_QP, "Modify iwarp QP%u failed"
++					"CQP Major:Minor codes = 0x%04X:0x%04X, intended next state = 0x%08X.\n",
++					nesqp->hwqp.qp_id, cqp_request->major_code,
++					cqp_request->minor_code, next_iwarp_state);
++		}
++		if (atomic_dec_and_test(&cqp_request->refcount)) {
++			if (cqp_request->dynamic) {
++				kfree(cqp_request);
++			} else {
++				spin_lock_irqsave(&nesdev->cqp.lock, flags);
++				list_add_tail(&cqp_request->list, &nesdev->cqp_avail_reqs);
++				spin_unlock_irqrestore(&nesdev->cqp.lock, flags);
++			}
++		}
++		if (!ret)
++			return -ETIME;
++		else if (major_code)
++			return -EIO;
++		else
++			return 0;
++	} else {
++		return 0;
++	}
 +}
 +
-+/*
-+ * Get/Set RX polarity-invert enable. 0=no, 1=yes.
++
++/**
++ * nes_modify_qp
 + */
-+static ssize_t show_rx_polinv_enb(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
++int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
++		int attr_mask, struct ib_udata *udata)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
++	struct nes_qp *nesqp = to_nesqp(ibqp);
++	struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	/* u32 cqp_head; */
++	/* u32 counter; */
++	u32 next_iwarp_state = 0;
++	int err;
++	unsigned long qplockflags;
 +	int ret;
++	u16 original_last_aeq;
++	u8 issue_modify_qp = 0;
++	u8 issue_disconnect = 0;
++	u8 dont_wait = 0;
++
++	nes_debug(NES_DBG_MOD_QP, "QP%u: QP State=%u, cur QP State=%u,"
++			" iwarp_state=0x%X, refcount=%d\n",
++			nesqp->hwqp.qp_id, attr->qp_state, nesqp->ibqp_state,
++			nesqp->iwarp_state, atomic_read(&nesqp->refcount));
++
++	nes_add_ref(&nesqp->ibqp);
++	spin_lock_irqsave(&nesqp->lock, qplockflags);
++
++	nes_debug(NES_DBG_MOD_QP, "QP%u: hw_iwarp_state=0x%X, hw_tcp_state=0x%X,"
++			" QP Access Flags=0x%X, attr_mask = 0x%0x\n",
++			nesqp->hwqp.qp_id, nesqp->hw_iwarp_state,
++			nesqp->hw_tcp_state, attr->qp_access_flags, attr_mask);
++
++	if (attr_mask & IB_QP_STATE) {
++		switch (attr->qp_state) {
++			case IB_QPS_INIT:
++				nes_debug(NES_DBG_MOD_QP, "QP%u: new state = init\n",
++						nesqp->hwqp.qp_id);
++				if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_IDLE) {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return -EINVAL;
++				}
++				next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;
++				issue_modify_qp = 1;
++				break;
++			case IB_QPS_RTR:
++				nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rtr\n",
++						nesqp->hwqp.qp_id);
++				if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_IDLE) {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return -EINVAL;
++				}
++				next_iwarp_state = NES_CQP_QP_IWARP_STATE_IDLE;
++				issue_modify_qp = 1;
++				break;
++			case IB_QPS_RTS:
++				nes_debug(NES_DBG_MOD_QP, "QP%u: new state = rts\n",
++						nesqp->hwqp.qp_id);
++				if (nesqp->iwarp_state>(u32)NES_CQP_QP_IWARP_STATE_RTS) {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return -EINVAL;
++				}
++				if (nesqp->cm_id == NULL) {
++					nes_debug(NES_DBG_MOD_QP, "QP%u: Failing attempt to move QP to RTS without a CM_ID. \n",
++							nesqp->hwqp.qp_id );
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return -EINVAL;
++				}
++				next_iwarp_state = NES_CQP_QP_IWARP_STATE_RTS;
++				if (nesqp->iwarp_state != NES_CQP_QP_IWARP_STATE_RTS)
++					next_iwarp_state |= NES_CQP_QP_CONTEXT_VALID |
++							NES_CQP_QP_ARP_VALID | NES_CQP_QP_ORD_VALID;
++				issue_modify_qp = 1;
++				nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_ESTABLISHED;
++				nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_RTS;
++				nesqp->hte_added = 1;
++				break;
++			case IB_QPS_SQD:
++				issue_modify_qp = 1;
++				nes_debug(NES_DBG_MOD_QP, "QP%u: new state=closing. SQ head=%u, SQ tail=%u\n",
++						nesqp->hwqp.qp_id, nesqp->hwqp.sq_head, nesqp->hwqp.sq_tail);
++				if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return 0;
++				} else {
++					if (nesqp->iwarp_state > (u32)NES_CQP_QP_IWARP_STATE_CLOSING) {
++						nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing"
++								" ignored due to current iWARP state\n",
++								nesqp->hwqp.qp_id);
++						spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++						nes_rem_ref(&nesqp->ibqp);
++						return -EINVAL;
++					}
++					if (nesqp->hw_iwarp_state != NES_AEQE_IWARP_STATE_RTS) {
++						nes_debug(NES_DBG_MOD_QP, "QP%u: State change to closing"
++								" already done based on hw state.\n",
++								nesqp->hwqp.qp_id);
++						issue_modify_qp = 0;
++						nesqp->in_disconnect = 0;
++					}
++					switch (nesqp->hw_iwarp_state) {
++						case NES_AEQE_IWARP_STATE_CLOSING:
++							next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
++						case NES_AEQE_IWARP_STATE_TERMINATE:
++							next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
++							break;
++						case NES_AEQE_IWARP_STATE_ERROR:
++							next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
++							break;
++						default:
++							next_iwarp_state = NES_CQP_QP_IWARP_STATE_CLOSING;
++							nesqp->in_disconnect = 1;
++							nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_CLOSING;
++							break;
++					}
++				}
++				break;
++			case IB_QPS_SQE:
++				nes_debug(NES_DBG_MOD_QP, "QP%u: new state = terminate\n",
++						nesqp->hwqp.qp_id);
++				if (nesqp->iwarp_state>=(u32)NES_CQP_QP_IWARP_STATE_TERMINATE) {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return -EINVAL;
++				}
++				/* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */
++				next_iwarp_state = NES_CQP_QP_IWARP_STATE_TERMINATE;
++				nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_TERMINATE;
++				issue_modify_qp = 1;
++				nesqp->in_disconnect = 1;
++				break;
++			case IB_QPS_ERR:
++			case IB_QPS_RESET:
++				if (nesqp->iwarp_state == (u32)NES_CQP_QP_IWARP_STATE_ERROR) {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_rem_ref(&nesqp->ibqp);
++					return -EINVAL;
++				}
++				nes_debug(NES_DBG_MOD_QP, "QP%u: new state = error\n",
++						nesqp->hwqp.qp_id);
++				next_iwarp_state = NES_CQP_QP_IWARP_STATE_ERROR;
++				/* next_iwarp_state = (NES_CQP_QP_IWARP_STATE_TERMINATE | 0x02000000); */
++					if (nesqp->hte_added) {
++						nes_debug(NES_DBG_MOD_QP, "set CQP_QP_DEL_HTE\n");
++						next_iwarp_state |= NES_CQP_QP_DEL_HTE;
++						nesqp->hte_added = 0;
++					}
++				if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) &&
++						(nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) {
++					next_iwarp_state |= NES_CQP_QP_RESET;
++					nesqp->in_disconnect = 1;
++				} else {
++					nes_debug(NES_DBG_MOD_QP, "QP%u NOT setting NES_CQP_QP_RESET since TCP state = %u\n",
++							nesqp->hwqp.qp_id, nesqp->hw_tcp_state);
++					dont_wait = 1;
++				}
++				issue_modify_qp = 1;
++				nesqp->hw_iwarp_state = NES_AEQE_IWARP_STATE_ERROR;
++				break;
++			default:
++				spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++				nes_rem_ref(&nesqp->ibqp);
++				return -EINVAL;
++				break;
++		}
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
-+	return ret;
++		nesqp->ibqp_state = attr->qp_state;
++		if (((nesqp->iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) ==
++				(u32)NES_CQP_QP_IWARP_STATE_RTS) &&
++				((next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK) >
++				(u32)NES_CQP_QP_IWARP_STATE_RTS)) {
++			nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;
++			nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",
++					nesqp->iwarp_state);
++			issue_disconnect = 1;
++		} else {
++			nesqp->iwarp_state = next_iwarp_state & NES_CQP_QP_IWARP_STATE_MASK;
++			nes_debug(NES_DBG_MOD_QP, "Change nesqp->iwarp_state=%08x\n",
++					nesqp->iwarp_state);
++		}
++	}
++
++	if (attr_mask & IB_QP_ACCESS_FLAGS) {
++		if (attr->qp_access_flags & IB_ACCESS_LOCAL_WRITE) {
++			nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN |
++					NES_QPCONTEXT_MISC_RDMA_READ_EN);
++			issue_modify_qp = 1;
++		}
++		if (attr->qp_access_flags & IB_ACCESS_REMOTE_WRITE) {
++			nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN);
++			issue_modify_qp = 1;
++		}
++		if (attr->qp_access_flags & IB_ACCESS_REMOTE_READ) {
++			nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_READ_EN);
++			issue_modify_qp = 1;
++		}
++		if (attr->qp_access_flags & IB_ACCESS_MW_BIND) {
++			nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_WBIND_EN);
++			issue_modify_qp = 1;
++		}
++
++		if (nesqp->user_mode) {
++			nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_RDMA_WRITE_EN |
++					NES_QPCONTEXT_MISC_RDMA_READ_EN);
++			issue_modify_qp = 1;
++		}
++	}
++
++	original_last_aeq = nesqp->last_aeq;
++	spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++
++	nes_debug(NES_DBG_MOD_QP, "issue_modify_qp=%u\n", issue_modify_qp);
++
++	ret = 0;
++
++
++	if (issue_modify_qp) {
++		nes_debug(NES_DBG_MOD_QP, "call nes_hw_modify_qp\n");
++		ret = nes_hw_modify_qp(nesdev, nesqp, next_iwarp_state, 1);
++		if (ret)
++			nes_debug(NES_DBG_MOD_QP, "nes_hw_modify_qp (next_iwarp_state = 0x%08X)"
++					" failed for QP%u.\n",
++					next_iwarp_state, nesqp->hwqp.qp_id);
++
++	}
++
++	if ((issue_modify_qp) && (nesqp->ibqp_state > IB_QPS_RTS)) {
++		nes_debug(NES_DBG_MOD_QP, "QP%u Issued ModifyQP refcount (%d),"
++				" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
++				nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++				original_last_aeq, nesqp->last_aeq);
++		if ((!ret) ||
++				((original_last_aeq != NES_AEQE_AEID_RDMAP_ROE_BAD_LLP_CLOSE) &&
++				(ret))) {
++			if (dont_wait) {
++				if (nesqp->cm_id && nesqp->hw_tcp_state != 0) {
++					nes_debug(NES_DBG_MOD_QP, "QP%u Queuing fake disconnect for QP refcount (%d),"
++							" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
++							nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++							original_last_aeq, nesqp->last_aeq);
++					/* this one is for the cm_disconnect thread */
++					nes_add_ref(&nesqp->ibqp);
++					spin_lock_irqsave(&nesqp->lock, qplockflags);
++					nesqp->hw_tcp_state = NES_AEQE_TCP_STATE_CLOSED;
++					nesqp->last_aeq = NES_AEQE_AEID_RESET_SENT;
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_cm_disconn(nesqp);
++				} else {
++					nes_debug(NES_DBG_MOD_QP, "QP%u No fake disconnect, QP refcount=%d\n",
++							nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
++					nes_rem_ref(&nesqp->ibqp);
++				}
++			} else {
++				spin_lock_irqsave(&nesqp->lock, qplockflags);
++				if (nesqp->cm_id) {
++					/* These two are for the timer thread */
++					if (atomic_inc_return(&nesqp->close_timer_started) == 1) {
++						nes_add_ref(&nesqp->ibqp);
++						nesqp->cm_id->add_ref(nesqp->cm_id);
++						nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
++								" need ae to finish up, original_last_aeq = 0x%04X."
++								" last_aeq = 0x%04X, scheduling timer.\n",
++								nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++								original_last_aeq, nesqp->last_aeq);
++						schedule_nes_timer(nesqp->cm_node, (struct sk_buff *) nesqp, NES_TIMER_TYPE_CLOSE, 1, 0);
++					}
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++				} else {
++					spin_unlock_irqrestore(&nesqp->lock, qplockflags);
++					nes_debug(NES_DBG_MOD_QP, "QP%u Not decrementing QP refcount (%d),"
++							" need ae to finish up, original_last_aeq = 0x%04X."
++							" last_aeq = 0x%04X.\n",
++							nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++							original_last_aeq, nesqp->last_aeq);
++				}
++			}
++		} else {
++			nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
++					" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
++					nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++					original_last_aeq, nesqp->last_aeq);
++			nes_rem_ref(&nesqp->ibqp);
++		}
++	} else {
++		nes_debug(NES_DBG_MOD_QP, "QP%u Decrementing QP refcount (%d), No ae to finish up,"
++				" original_last_aeq = 0x%04X. last_aeq = 0x%04X.\n",
++				nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount),
++				original_last_aeq, nesqp->last_aeq);
++		nes_rem_ref(&nesqp->ibqp);
++	}
++
++	err = 0;
++
++	nes_debug(NES_DBG_MOD_QP, "QP%u Leaving, refcount=%d\n",
++			nesqp->hwqp.qp_id, atomic_read(&nesqp->refcount));
++
++	return err;
 +}
 +
-+static ssize_t store_rx_polinv_enb(struct device *dev,
-+			  struct device_attribute *attr,
-+			  const char *buf,
-+			  size_t count)
++
++/**
++ * nes_muticast_attach
++ */
++static int nes_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret, r;
-+	u16 val;
++	nes_debug(NES_DBG_INIT, "\n");
++	return -ENOSYS;
++}
 +
-+	ret = ipath_parse_ushort(buf, &val);
-+	if (ret < 0 || val > 1)
-+		goto invalid;
 +
-+	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
-+	if (r < 0) {
-+		ret = r;
-+		goto bail;
-+	}
++/**
++ * nes_multicast_detach
++ */
++static int nes_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
++{
++	nes_debug(NES_DBG_INIT, "\n");
++	return -ENOSYS;
++}
 +
-+	goto bail;
-+invalid:
-+	ipath_dev_err(dd, "attempt to set invalid Rx Polarity (enable)\n");
-+bail:
-+	return ret;
++
++/**
++ * nes_process_mad
++ */
++static int nes_process_mad(struct ib_device *ibdev, int mad_flags,
++		u8 port_num, struct ib_wc *in_wc, struct ib_grh *in_grh,
++		struct ib_mad *in_mad, struct ib_mad *out_mad)
++{
++	nes_debug(NES_DBG_INIT, "\n");
++	return -ENOSYS;
 +}
-+/*
-+ * Get/Set RX lane-reversal enable. 0=no, 1=yes.
++
++static inline void
++fill_wqe_sg_send(struct nes_hw_qp_wqe *wqe, struct ib_send_wr *ib_wr, u32 uselkey)
++{
++	int sge_index;
++	int total_payload_length = 0;
++	for (sge_index = 0; sge_index < ib_wr->num_sge; sge_index++) {
++		set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX+(sge_index*4),
++			ib_wr->sg_list[sge_index].addr);
++		set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_LENGTH0_IDX + (sge_index*4),
++			ib_wr->sg_list[sge_index].length);
++		if (uselkey)
++			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index*4),
++						(ib_wr->sg_list[sge_index].lkey));
++		else
++			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX + (sge_index*4), 0);
++
++		total_payload_length += ib_wr->sg_list[sge_index].length;
++	}
++	nes_debug(NES_DBG_IW_TX, "UC UC UC, sending total_payload_length=%u \n",
++			total_payload_length);
++	set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
++				total_payload_length);
++}
++
++/**
++ * nes_post_send
 + */
-+static ssize_t show_lanerev_enb(struct device *dev,
-+			 struct device_attribute *attr,
-+			 char *buf)
++static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
++		struct ib_send_wr **bad_wr)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret;
++	u64 u64temp;
++	unsigned long flags = 0;
++	struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_qp *nesqp = to_nesqp(ibqp);
++	struct nes_hw_qp_wqe *wqe;
++	int err;
++	u32 qsize = nesqp->hwqp.sq_size;
++	u32 head;
++	u32 wqe_misc;
++	u32 wqe_count;
++	u32 counter;
++	u32 total_payload_length;
 +
-+	ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB);
-+	if (ret >= 0)
-+		ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
-+	return ret;
++	err = 0;
++	wqe_misc = 0;
++	wqe_count = 0;
++	total_payload_length = 0;
++
++	if (nesqp->ibqp_state > IB_QPS_RTS)
++		return -EINVAL;
++
++		spin_lock_irqsave(&nesqp->lock, flags);
++
++	head = nesqp->hwqp.sq_head;
++
++	while (ib_wr) {
++		/* Check for SQ overflow */
++		if (((head + (2 * qsize) - nesqp->hwqp.sq_tail) % qsize) == (qsize - 1)) {
++			err = -EINVAL;
++			break;
++		}
++
++		wqe = &nesqp->hwqp.sq_vbase[head];
++		/* nes_debug(NES_DBG_IW_TX, "processing sq wqe for QP%u at %p, head = %u.\n",
++				nesqp->hwqp.qp_id, wqe, head); */
++		nes_fill_init_qp_wqe(wqe, nesqp, head);
++		u64temp = (u64)(ib_wr->wr_id);
++		set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,
++					u64temp);
++			switch (ib_wr->opcode) {
++				case IB_WR_SEND:
++					if (ib_wr->send_flags & IB_SEND_SOLICITED) {
++						wqe_misc = NES_IWARP_SQ_OP_SENDSE;
++					} else {
++						wqe_misc = NES_IWARP_SQ_OP_SEND;
++					}
++					if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
++						err = -EINVAL;
++						break;
++					}
++					if (ib_wr->send_flags & IB_SEND_FENCE) {
++						wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
++					}
++					if ((ib_wr->send_flags & IB_SEND_INLINE) &&
++							((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
++							(ib_wr->sg_list[0].length <= 64)) {
++						memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
++							       (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
++						set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
++								ib_wr->sg_list[0].length);
++						wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
++					} else {
++						fill_wqe_sg_send(wqe, ib_wr, 1);
++					}
++
++					break;
++				case IB_WR_RDMA_WRITE:
++					wqe_misc = NES_IWARP_SQ_OP_RDMAW;
++					if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
++						nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=%u\n",
++								ib_wr->num_sge,
++								nesdev->nesadapter->max_sge);
++						err = -EINVAL;
++						break;
++					}
++					if (ib_wr->send_flags & IB_SEND_FENCE) {
++						wqe_misc |= NES_IWARP_SQ_WQE_LOCAL_FENCE;
++					}
++
++					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
++							ib_wr->wr.rdma.rkey);
++					set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
++							ib_wr->wr.rdma.remote_addr);
++
++					if ((ib_wr->send_flags & IB_SEND_INLINE) &&
++							((nes_drv_opt & NES_DRV_OPT_NO_INLINE_DATA) == 0) &&
++							(ib_wr->sg_list[0].length <= 64)) {
++						memcpy(&wqe->wqe_words[NES_IWARP_SQ_WQE_IMM_DATA_START_IDX],
++							       (void *)(unsigned long)ib_wr->sg_list[0].addr, ib_wr->sg_list[0].length);
++						set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX,
++								ib_wr->sg_list[0].length);
++						wqe_misc |= NES_IWARP_SQ_WQE_IMM_DATA;
++					} else {
++						fill_wqe_sg_send(wqe, ib_wr, 1);
++					}
++					wqe->wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX] =
++							wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX];
++					break;
++				case IB_WR_RDMA_READ:
++					/* iWARP only supports 1 sge for RDMA reads */
++					if (ib_wr->num_sge > 1) {
++						nes_debug(NES_DBG_IW_TX, "Exceeded max sge, ib_wr=%u, max=1\n",
++								ib_wr->num_sge);
++						err = -EINVAL;
++						break;
++					}
++					wqe_misc = NES_IWARP_SQ_OP_RDMAR;
++					set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_TO_LOW_IDX,
++							ib_wr->wr.rdma.remote_addr);
++					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_STAG_IDX,
++							ib_wr->wr.rdma.rkey);
++					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX,
++							ib_wr->sg_list->length);
++					set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_FRAG0_LOW_IDX,
++							ib_wr->sg_list->addr);
++					set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_STAG0_IDX,
++							ib_wr->sg_list->lkey);
++					break;
++				default:
++					/* error */
++					err = -EINVAL;
++					break;
++			}
++
++		if (ib_wr->send_flags & IB_SEND_SIGNALED) {
++			wqe_misc |= NES_IWARP_SQ_WQE_SIGNALED_COMPL;
++		}
++		wqe->wqe_words[NES_IWARP_SQ_WQE_MISC_IDX] = cpu_to_le32(wqe_misc);
++
++		ib_wr = ib_wr->next;
++		head++;
++		wqe_count++;
++		if (head >= qsize)
++			head = 0;
++
++	}
++
++	nesqp->hwqp.sq_head = head;
++	barrier();
++	while (wqe_count) {
++		counter = min(wqe_count, ((u32)255));
++		wqe_count -= counter;
++		nes_write32(nesdev->regs + NES_WQE_ALLOC,
++				(counter << 24) | 0x00800000 | nesqp->hwqp.qp_id);
++	}
++
++		spin_unlock_irqrestore(&nesqp->lock, flags);
++
++	if (err)
++		*bad_wr = ib_wr;
++	return err;
 +}
 +
-+static ssize_t store_lanerev_enb(struct device *dev,
-+			  struct device_attribute *attr,
-+			  const char *buf,
-+			  size_t count)
++
++/**
++ * nes_post_recv
++ */
++static int nes_post_recv(struct ib_qp *ibqp, struct ib_recv_wr *ib_wr,
++		struct ib_recv_wr **bad_wr)
 +{
-+	struct ipath_devdata *dd = dev_get_drvdata(dev);
-+	int ret, r;
-+	u16 val;
++	u64 u64temp;
++	unsigned long flags = 0;
++	struct nes_vnic *nesvnic = to_nesvnic(ibqp->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_qp *nesqp = to_nesqp(ibqp);
++	struct nes_hw_qp_wqe *wqe;
++	int err = 0;
++	int sge_index;
++	u32 qsize = nesqp->hwqp.rq_size;
++	u32 head;
++	u32 wqe_count = 0;
++	u32 counter;
++	u32 total_payload_length;
 +
-+	ret = ipath_parse_ushort(buf, &val);
-+	if (ret >= 0 && val > 1) {
-+		ret = -EINVAL;
-+		ipath_dev_err(dd,
-+			"attempt to set invalid Lane reversal (enable)\n");
-+		goto bail;
++	if (nesqp->ibqp_state > IB_QPS_RTS)
++		return -EINVAL;
++
++		spin_lock_irqsave(&nesqp->lock, flags);
++
++	head = nesqp->hwqp.rq_head;
++
++	while (ib_wr) {
++		if (ib_wr->num_sge > nesdev->nesadapter->max_sge) {
++			err = -EINVAL;
++			break;
++		}
++		/* Check for RQ overflow */
++		if (((head + (2 * qsize) - nesqp->hwqp.rq_tail) % qsize) == (qsize - 1)) {
++			err = -EINVAL;
++			break;
++		}
++
++		nes_debug(NES_DBG_IW_RX, "ibwr sge count = %u.\n", ib_wr->num_sge);
++		wqe = &nesqp->hwqp.rq_vbase[head];
++
++		/* nes_debug(NES_DBG_IW_RX, "QP%u:processing rq wqe at %p, head = %u.\n",
++				nesqp->hwqp.qp_id, wqe, head); */
++		nes_fill_init_qp_wqe(wqe, nesqp, head);
++		u64temp = (u64)(ib_wr->wr_id);
++		set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX,
++					u64temp);
++		total_payload_length = 0;
++		for (sge_index=0; sge_index < ib_wr->num_sge; sge_index++) {
++			set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_FRAG0_LOW_IDX+(sge_index*4),
++					ib_wr->sg_list[sge_index].addr);
++			set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_LENGTH0_IDX+(sge_index*4),
++					ib_wr->sg_list[sge_index].length);
++			set_wqe_32bit_value(wqe->wqe_words,NES_IWARP_RQ_WQE_STAG0_IDX+(sge_index*4),
++					ib_wr->sg_list[sge_index].lkey);
++
++			total_payload_length += ib_wr->sg_list[sge_index].length;
++		}
++		set_wqe_32bit_value(wqe->wqe_words, NES_IWARP_RQ_WQE_TOTAL_PAYLOAD_IDX,
++					total_payload_length);
++
++		ib_wr = ib_wr->next;
++		head++;
++		wqe_count++;
++		if (head >= qsize)
++			head = 0;
 +	}
 +
-+	r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB, val);
-+	if (r < 0)
-+		ret = r;
++	nesqp->hwqp.rq_head = head;
++	barrier();
++	while (wqe_count) {
++		counter = min(wqe_count, ((u32)255));
++		wqe_count -= counter;
++		nes_write32(nesdev->regs+NES_WQE_ALLOC, (counter<<24) | nesqp->hwqp.qp_id);
++	}
 +
-+bail:
-+	return ret;
++		spin_unlock_irqrestore(&nesqp->lock, flags);
++
++	if (err)
++		*bad_wr = ib_wr;
++	return err;
 +}
 +
- static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
- static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
- 
-@@ -683,6 +988,11 @@ static struct attribute_group driver_attr_group = {
- 	.attrs = driver_attributes
- };
- 
-+struct attribute_group *ipath_driver_attr_groups[] = {
-+	&driver_attr_group,
-+	NULL,
-+};
 +
- static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
- static DEVICE_ATTR(lmc, S_IWUSR | S_IRUGO, show_lmc, store_lmc);
- static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
-@@ -701,6 +1011,10 @@ static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
- static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
- static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
- static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
-+static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
-+		   show_jint_max_packets, store_jint_max_packets);
-+static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
-+		   show_jint_idle_ticks, store_jint_idle_ticks);
- 
- static struct attribute *dev_attributes[] = {
- 	&dev_attr_guid.attr,
-@@ -727,6 +1041,34 @@ static struct attribute_group dev_attr_group = {
- 	.attrs = dev_attributes
- };
- 
-+static DEVICE_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb,
-+		   store_hrtbt_enb);
-+static DEVICE_ATTR(link_width_enable, S_IWUSR | S_IRUGO, show_lwid_enb,
-+		   store_lwid_enb);
-+static DEVICE_ATTR(link_width, S_IRUGO, show_lwid, NULL);
-+static DEVICE_ATTR(link_speed_enable, S_IWUSR | S_IRUGO, show_spd_enb,
-+		   store_spd_enb);
-+static DEVICE_ATTR(link_speed, S_IRUGO, show_spd, NULL);
-+static DEVICE_ATTR(rx_pol_inv_enable, S_IWUSR | S_IRUGO, show_rx_polinv_enb,
-+		   store_rx_polinv_enb);
-+static DEVICE_ATTR(rx_lane_rev_enable, S_IWUSR | S_IRUGO, show_lanerev_enb,
-+		   store_lanerev_enb);
++/**
++ * nes_poll_cq
++ */
++static int nes_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *entry)
++{
++	u64 u64temp;
++	u64 wrid;
++	/* u64 u64temp; */
++	unsigned long flags = 0;
++	struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_cq *nescq = to_nescq(ibcq);
++	struct nes_qp *nesqp;
++	struct nes_hw_cqe cqe;
++	u32 head;
++	u32 wq_tail;
++	u32 cq_size;
++	u32 cqe_count = 0;
++	u32 wqe_index;
++	u32 u32temp;
++	/* u32 counter; */
++
++	nes_debug(NES_DBG_CQ, "\n");
++
++		spin_lock_irqsave(&nescq->lock, flags);
++
++	head = nescq->hw_cq.cq_head;
++	cq_size = nescq->hw_cq.cq_size;
++
++	while (cqe_count < num_entries) {
++		if (le32_to_cpu(nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX]) &
++				NES_CQE_VALID) {
++			cqe = nescq->hw_cq.cq_vbase[head];
++			nescq->hw_cq.cq_vbase[head].cqe_words[NES_CQE_OPCODE_IDX] = 0;
++			u32temp = le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_LOW_IDX]);
++			wqe_index = u32temp &
++					(nesdev->nesadapter->max_qp_wr - 1);
++			u32temp &= ~(NES_SW_CONTEXT_ALIGN-1);
++			/* parse CQE, get completion context from WQE (either rq or sq */
++			u64temp = (((u64)(le32_to_cpu(cqe.cqe_words[NES_CQE_COMP_COMP_CTX_HIGH_IDX])))<<32) |
++					((u64)u32temp);
++			nesqp = *((struct nes_qp **)&u64temp);
++			memset(entry, 0, sizeof *entry);
++			if (cqe.cqe_words[NES_CQE_ERROR_CODE_IDX] == 0) {
++				entry->status = IB_WC_SUCCESS;
++			} else {
++				entry->status = IB_WC_WR_FLUSH_ERR;
++			}
 +
-+static struct attribute *dev_ibcfg_attributes[] = {
-+	&dev_attr_hrtbt_enable.attr,
-+	&dev_attr_link_width_enable.attr,
-+	&dev_attr_link_width.attr,
-+	&dev_attr_link_speed_enable.attr,
-+	&dev_attr_link_speed.attr,
-+	&dev_attr_rx_pol_inv_enable.attr,
-+	&dev_attr_rx_lane_rev_enable.attr,
-+	NULL
-+};
++			entry->qp = &nesqp->ibqp;
++			entry->src_qp = nesqp->hwqp.qp_id;
 +
-+static struct attribute_group dev_ibcfg_attr_group = {
-+	.attrs = dev_ibcfg_attributes
-+};
++			if (le32_to_cpu(cqe.cqe_words[NES_CQE_OPCODE_IDX]) & NES_CQE_SQ) {
++				if (nesqp->skip_lsmm) {
++					nesqp->skip_lsmm = 0;
++					wq_tail = nesqp->hwqp.sq_tail++;
++				}
 +
- /**
-  * ipath_expose_reset - create a device reset file
-  * @dev: the device structure
-@@ -753,24 +1095,9 @@ int ipath_expose_reset(struct device *dev)
- 	return ret;
- }
- 
--int ipath_driver_create_group(struct device_driver *drv)
--{
--	int ret;
--
--	ret = sysfs_create_group(&drv->kobj, &driver_attr_group);
--
--	return ret;
--}
--
--void ipath_driver_remove_group(struct device_driver *drv)
--{
--	sysfs_remove_group(&drv->kobj, &driver_attr_group);
--}
--
- int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
- {
- 	int ret;
--	char unit[5];
- 
- 	ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
- 	if (ret)
-@@ -780,11 +1107,26 @@ int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
- 	if (ret)
- 		goto bail_attrs;
- 
--	snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
--	ret = sysfs_create_link(&dev->driver->kobj, &dev->kobj, unit);
--	if (ret == 0)
--		goto bail;
-+	if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
-+		ret = device_create_file(dev, &dev_attr_jint_idle_ticks);
-+		if (ret)
-+			goto bail_counter;
-+		ret = device_create_file(dev, &dev_attr_jint_max_packets);
-+		if (ret)
-+			goto bail_idle;
- 
-+		ret = sysfs_create_group(&dev->kobj, &dev_ibcfg_attr_group);
-+		if (ret)
-+			goto bail_max;
++				/* Working on a SQ Completion*/
++				wq_tail = wqe_index;
++				nesqp->hwqp.sq_tail = (wqe_index+1)&(nesqp->hwqp.sq_size - 1);
++				wrid = (((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wq_tail].
++						wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_HIGH_IDX]))) << 32) |
++						((u64)(cpu_to_le32((u32)nesqp->hwqp.sq_vbase[wq_tail].
++						wqe_words[NES_IWARP_SQ_WQE_COMP_SCRATCH_LOW_IDX])));
++				entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail].
++						wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX]);
++
++				switch (le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail].
++						wqe_words[NES_IWARP_SQ_WQE_MISC_IDX]) & 0x3f) {
++					case NES_IWARP_SQ_OP_RDMAW:
++						nes_debug(NES_DBG_CQ, "Operation = RDMA WRITE.\n");
++						entry->opcode = IB_WC_RDMA_WRITE;
++						break;
++					case NES_IWARP_SQ_OP_RDMAR:
++						nes_debug(NES_DBG_CQ, "Operation = RDMA READ.\n");
++						entry->opcode = IB_WC_RDMA_READ;
++						entry->byte_len = le32_to_cpu(nesqp->hwqp.sq_vbase[wq_tail].
++								wqe_words[NES_IWARP_SQ_WQE_RDMA_LENGTH_IDX]);
++						break;
++					case NES_IWARP_SQ_OP_SENDINV:
++					case NES_IWARP_SQ_OP_SENDSEINV:
++					case NES_IWARP_SQ_OP_SEND:
++					case NES_IWARP_SQ_OP_SENDSE:
++						nes_debug(NES_DBG_CQ, "Operation = Send.\n");
++						entry->opcode = IB_WC_SEND;
++						break;
++				}
++			} else {
++				/* Working on a RQ Completion*/
++				wq_tail = wqe_index;
++					nesqp->hwqp.rq_tail = (wqe_index+1)&(nesqp->hwqp.rq_size - 1);
++				entry->byte_len = le32_to_cpu(cqe.cqe_words[NES_CQE_PAYLOAD_LENGTH_IDX]);
++				wrid = ((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_LOW_IDX]))) |
++					((u64)(le32_to_cpu(nesqp->hwqp.rq_vbase[wq_tail].wqe_words[NES_IWARP_RQ_WQE_COMP_SCRATCH_HIGH_IDX]))<<32);
++					entry->opcode = IB_WC_RECV;
++			}
++			entry->wr_id = wrid;
++
++			if (++head >= cq_size)
++				head = 0;
++			cqe_count++;
++			nescq->polled_completions++;
++			if ((nescq->polled_completions > (cq_size / 2)) ||
++					(nescq->polled_completions == 255)) {
++				nes_debug(NES_DBG_CQ, "CQ%u Issuing CQE Allocate since more than half of cqes"
++						" are pending %u of %u.\n",
++						nescq->hw_cq.cq_number, nescq->polled_completions, cq_size);
++				nes_write32(nesdev->regs+NES_CQE_ALLOC,
++						nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
++				nescq->polled_completions = 0;
++			}
++			entry++;
++		} else
++			break;
++	}
++
++	if (nescq->polled_completions) {
++		nes_write32(nesdev->regs+NES_CQE_ALLOC,
++				nescq->hw_cq.cq_number | (nescq->polled_completions << 16));
++		nescq->polled_completions = 0;
 +	}
 +
++	nescq->hw_cq.cq_head = head;
++	nes_debug(NES_DBG_CQ, "Reporting %u completions for CQ%u.\n",
++			cqe_count, nescq->hw_cq.cq_number);
++
++		spin_unlock_irqrestore(&nescq->lock, flags);
++
++	return cqe_count;
++}
++
++
++/**
++ * nes_req_notify_cq
++ */
++static int nes_req_notify_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags notify_flags)
++		{
++	struct nes_vnic *nesvnic = to_nesvnic(ibcq->device);
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_cq *nescq = to_nescq(ibcq);
++	u32 cq_arm;
++
++	nes_debug(NES_DBG_CQ, "Requesting notification for CQ%u.\n",
++			nescq->hw_cq.cq_number);
++
++	cq_arm = nescq->hw_cq.cq_number;
++	if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_NEXT_COMP)
++		cq_arm |= NES_CQE_ALLOC_NOTIFY_NEXT;
++	else if ((notify_flags & IB_CQ_SOLICITED_MASK) == IB_CQ_SOLICITED)
++		cq_arm |= NES_CQE_ALLOC_NOTIFY_SE;
++	else
++		return -EINVAL;
++
++	nes_write32(nesdev->regs+NES_CQE_ALLOC, cq_arm);
++	nes_read32(nesdev->regs+NES_CQE_ALLOC);
++
 +	return 0;
++}
 +
-+bail_max:
-+	device_remove_file(dev, &dev_attr_jint_max_packets);
-+bail_idle:
-+	device_remove_file(dev, &dev_attr_jint_idle_ticks);
-+bail_counter:
- 	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
- bail_attrs:
- 	sysfs_remove_group(&dev->kobj, &dev_attr_group);
-@@ -794,12 +1136,14 @@ bail:
- 
- void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
- {
--	char unit[5];
-+	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
- 
--	snprintf(unit, sizeof(unit), "%02d", dd->ipath_unit);
--	sysfs_remove_link(&dev->driver->kobj, unit);
-+	if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
-+		sysfs_remove_group(&dev->kobj, &dev_ibcfg_attr_group);
-+		device_remove_file(dev, &dev_attr_jint_idle_ticks);
-+		device_remove_file(dev, &dev_attr_jint_max_packets);
++
++/**
++ * nes_init_ofa_device
++ */
++struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev)
++{
++	struct nes_ib_device *nesibdev;
++	struct nes_vnic *nesvnic = netdev_priv(netdev);
++	struct nes_device *nesdev = nesvnic->nesdev;
++
++	nesibdev = (struct nes_ib_device *)ib_alloc_device(sizeof(struct nes_ib_device));
++	if (nesibdev == NULL) {
++		return NULL;
 +	}
- 
--	sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
- 	sysfs_remove_group(&dev->kobj, &dev_attr_group);
- 
- 	device_remove_file(dev, &dev_attr_reset);
-diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c
-index b3df6f3..de67eed 100644
---- a/drivers/infiniband/hw/ipath/ipath_ud.c
-+++ b/drivers/infiniband/hw/ipath/ipath_ud.c
-@@ -301,8 +301,6 @@ int ipath_make_ud_req(struct ipath_qp *qp)
- 
- 	/* header size in 32-bit words LRH+BTH+DETH = (8+12+8)/4. */
- 	qp->s_hdrwords = 7;
--	if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM)
--		qp->s_hdrwords++;
- 	qp->s_cur_size = wqe->length;
- 	qp->s_cur_sge = &qp->s_sge;
- 	qp->s_wqe = wqe;
-@@ -327,6 +325,7 @@ int ipath_make_ud_req(struct ipath_qp *qp)
- 		ohdr = &qp->s_hdr.u.oth;
- 	}
- 	if (wqe->wr.opcode == IB_WR_SEND_WITH_IMM) {
-+		qp->s_hdrwords++;
- 		ohdr->u.ud.imm_data = wqe->wr.imm_data;
- 		bth0 = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE << 24;
- 	} else
-diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c
-index c4c9984..32d8f88 100644
---- a/drivers/infiniband/hw/ipath/ipath_verbs.c
-+++ b/drivers/infiniband/hw/ipath/ipath_verbs.c
-@@ -943,7 +943,7 @@ bail:
-  * ipath_verbs_send - send a packet
-  * @qp: the QP to send on
-  * @hdr: the packet header
-- * @hdrwords: the number of words in the header
-+ * @hdrwords: the number of 32-bit words in the header
-  * @ss: the SGE to send
-  * @len: the length of the packet in bytes
-  */
-@@ -955,7 +955,10 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr,
- 	int ret;
- 	u32 dwords = (len + 3) >> 2;
- 
--	/* +1 is for the qword padding of pbc */
-+	/*
-+	 * Calculate the send buffer trigger address.
-+	 * The +1 counts for the pbc control dword following the pbc length.
-+	 */
- 	plen = hdrwords + dwords + 1;
- 
- 	/* Drop non-VL15 packets if we are not in the active state */
-@@ -1130,20 +1133,34 @@ static int ipath_query_device(struct ib_device *ibdev,
- 	return 0;
- }
- 
--const u8 ipath_cvt_physportstate[16] = {
--	[INFINIPATH_IBCS_LT_STATE_DISABLED] = 3,
--	[INFINIPATH_IBCS_LT_STATE_LINKUP] = 5,
--	[INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = 2,
--	[INFINIPATH_IBCS_LT_STATE_POLLQUIET] = 2,
--	[INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = 1,
--	[INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = 1,
--	[INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] = 4,
--	[INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] = 4,
--	[INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] = 4,
--	[INFINIPATH_IBCS_LT_STATE_CFGIDLE] = 4,
--	[INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] = 6,
--	[INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] = 6,
--	[INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] = 6,
-+const u8 ipath_cvt_physportstate[32] = {
-+	[INFINIPATH_IBCS_LT_STATE_DISABLED] = IB_PHYSPORTSTATE_DISABLED,
-+	[INFINIPATH_IBCS_LT_STATE_LINKUP] = IB_PHYSPORTSTATE_LINKUP,
-+	[INFINIPATH_IBCS_LT_STATE_POLLACTIVE] = IB_PHYSPORTSTATE_POLL,
-+	[INFINIPATH_IBCS_LT_STATE_POLLQUIET] = IB_PHYSPORTSTATE_POLL,
-+	[INFINIPATH_IBCS_LT_STATE_SLEEPDELAY] = IB_PHYSPORTSTATE_SLEEP,
-+	[INFINIPATH_IBCS_LT_STATE_SLEEPQUIET] = IB_PHYSPORTSTATE_SLEEP,
-+	[INFINIPATH_IBCS_LT_STATE_CFGDEBOUNCE] =
-+		IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[INFINIPATH_IBCS_LT_STATE_CFGRCVFCFG] =
-+		IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[INFINIPATH_IBCS_LT_STATE_CFGWAITRMT] =
-+		IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[INFINIPATH_IBCS_LT_STATE_CFGIDLE] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[INFINIPATH_IBCS_LT_STATE_RECOVERRETRAIN] =
-+		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
-+	[INFINIPATH_IBCS_LT_STATE_RECOVERWAITRMT] =
-+		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
-+	[INFINIPATH_IBCS_LT_STATE_RECOVERIDLE] =
-+		IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
-+	[0x10] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x11] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x12] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x13] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x14] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x15] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x16] = IB_PHYSPORTSTATE_CFG_TRAIN,
-+	[0x17] = IB_PHYSPORTSTATE_CFG_TRAIN
- };
- 
- u32 ipath_get_cr_errpkey(struct ipath_devdata *dd)
-@@ -1168,8 +1185,9 @@ static int ipath_query_port(struct ib_device *ibdev,
- 	ibcstat = dd->ipath_lastibcstat;
- 	props->state = ((ibcstat >> 4) & 0x3) + 1;
- 	/* See phys_state_show() */
--	props->phys_state = ipath_cvt_physportstate[
--		dd->ipath_lastibcstat & 0xf];
-+	props->phys_state = /* MEA: assumes shift == 0 */
-+		ipath_cvt_physportstate[dd->ipath_lastibcstat &
-+		dd->ibcs_lts_mask];
- 	props->port_cap_flags = dev->port_cap_flags;
- 	props->gid_tbl_len = 1;
- 	props->max_msg_sz = 0x80000000;
-@@ -1641,6 +1659,7 @@ int ipath_register_ib_device(struct ipath_devdata *dd)
- 		cntrs.local_link_integrity_errors;
- 	idev->z_excessive_buffer_overrun_errors =
- 		cntrs.excessive_buffer_overrun_errors;
-+	idev->z_vl15_dropped = cntrs.vl15_dropped;
- 
- 	/*
- 	 * The system image GUID is supposed to be the same for all
-diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h
-index 6ccb54f..3d59736 100644
---- a/drivers/infiniband/hw/ipath/ipath_verbs.h
-+++ b/drivers/infiniband/hw/ipath/ipath_verbs.h
-@@ -554,6 +554,7 @@ struct ipath_ibdev {
- 	u32 z_pkey_violations;			/* starting count for PMA */
- 	u32 z_local_link_integrity_errors;	/* starting count for PMA */
- 	u32 z_excessive_buffer_overrun_errors;	/* starting count for PMA */
-+	u32 z_vl15_dropped;			/* starting count for PMA */
- 	u32 n_rc_resends;
- 	u32 n_rc_acks;
- 	u32 n_rc_qacks;
-@@ -598,6 +599,7 @@ struct ipath_verbs_counters {
- 	u64 port_rcv_packets;
- 	u32 local_link_integrity_errors;
- 	u32 excessive_buffer_overrun_errors;
-+	u32 vl15_dropped;
- };
- 
- static inline struct ipath_mr *to_imr(struct ib_mr *ibmr)
-@@ -830,7 +832,17 @@ unsigned ipath_get_pkey(struct ipath_devdata *, unsigned);
- 
- extern const enum ib_wc_opcode ib_ipath_wc_opcode[];
- 
-+/*
-+ * Below converts HCA-specific LinkTrainingState to IB PhysPortState
-+ * values.
++	strlcpy(nesibdev->ibdev.name, "nes%d", IB_DEVICE_NAME_MAX);
++	nesibdev->ibdev.owner = THIS_MODULE;
++
++	nesibdev->ibdev.node_type = RDMA_NODE_RNIC;
++	memset(&nesibdev->ibdev.node_guid, 0, sizeof(nesibdev->ibdev.node_guid));
++	memcpy(&nesibdev->ibdev.node_guid, netdev->dev_addr, 6);
++
++	nesibdev->ibdev.uverbs_cmd_mask =
++			(1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
++			(1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
++			(1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
++			(1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
++			(1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
++			(1ull << IB_USER_VERBS_CMD_REG_MR) |
++			(1ull << IB_USER_VERBS_CMD_DEREG_MR) |
++			(1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
++			(1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
++			(1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
++			(1ull << IB_USER_VERBS_CMD_CREATE_AH) |
++			(1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
++			(1ull << IB_USER_VERBS_CMD_REQ_NOTIFY_CQ) |
++			(1ull << IB_USER_VERBS_CMD_CREATE_QP) |
++			(1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
++			(1ull << IB_USER_VERBS_CMD_POLL_CQ) |
++			(1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
++			(1ull << IB_USER_VERBS_CMD_ALLOC_MW) |
++			(1ull << IB_USER_VERBS_CMD_BIND_MW) |
++			(1ull << IB_USER_VERBS_CMD_DEALLOC_MW) |
++			(1ull << IB_USER_VERBS_CMD_POST_RECV) |
++			(1ull << IB_USER_VERBS_CMD_POST_SEND);
++
++	nesibdev->ibdev.phys_port_cnt = 1;
++	nesibdev->ibdev.num_comp_vectors = 1;
++	nesibdev->ibdev.dma_device = &nesdev->pcidev->dev;
++	nesibdev->ibdev.class_dev.dev = &nesdev->pcidev->dev;
++	nesibdev->ibdev.query_device = nes_query_device;
++	nesibdev->ibdev.query_port = nes_query_port;
++	nesibdev->ibdev.modify_port = nes_modify_port;
++	nesibdev->ibdev.query_pkey = nes_query_pkey;
++	nesibdev->ibdev.query_gid = nes_query_gid;
++	nesibdev->ibdev.alloc_ucontext = nes_alloc_ucontext;
++	nesibdev->ibdev.dealloc_ucontext = nes_dealloc_ucontext;
++	nesibdev->ibdev.mmap = nes_mmap;
++	nesibdev->ibdev.alloc_pd = nes_alloc_pd;
++	nesibdev->ibdev.dealloc_pd = nes_dealloc_pd;
++	nesibdev->ibdev.create_ah = nes_create_ah;
++	nesibdev->ibdev.destroy_ah = nes_destroy_ah;
++	nesibdev->ibdev.create_qp = nes_create_qp;
++	nesibdev->ibdev.modify_qp = nes_modify_qp;
++	nesibdev->ibdev.query_qp = nes_query_qp;
++	nesibdev->ibdev.destroy_qp = nes_destroy_qp;
++	nesibdev->ibdev.create_cq = nes_create_cq;
++	nesibdev->ibdev.destroy_cq = nes_destroy_cq;
++	nesibdev->ibdev.poll_cq = nes_poll_cq;
++	nesibdev->ibdev.get_dma_mr = nes_get_dma_mr;
++	nesibdev->ibdev.reg_phys_mr = nes_reg_phys_mr;
++	nesibdev->ibdev.reg_user_mr = nes_reg_user_mr;
++	nesibdev->ibdev.dereg_mr = nes_dereg_mr;
++	nesibdev->ibdev.alloc_mw = nes_alloc_mw;
++	nesibdev->ibdev.dealloc_mw = nes_dealloc_mw;
++	nesibdev->ibdev.bind_mw = nes_bind_mw;
++
++	nesibdev->ibdev.alloc_fmr = nes_alloc_fmr;
++	nesibdev->ibdev.unmap_fmr = nes_unmap_fmr;
++	nesibdev->ibdev.dealloc_fmr = nes_dealloc_fmr;
++	nesibdev->ibdev.map_phys_fmr = nes_map_phys_fmr;
++
++	nesibdev->ibdev.attach_mcast = nes_multicast_attach;
++	nesibdev->ibdev.detach_mcast = nes_multicast_detach;
++	nesibdev->ibdev.process_mad = nes_process_mad;
++
++	nesibdev->ibdev.req_notify_cq = nes_req_notify_cq;
++	nesibdev->ibdev.post_send = nes_post_send;
++	nesibdev->ibdev.post_recv = nes_post_recv;
++
++	nesibdev->ibdev.iwcm = kzalloc(sizeof(*nesibdev->ibdev.iwcm), GFP_KERNEL);
++	if (nesibdev->ibdev.iwcm == NULL) {
++		ib_dealloc_device(&nesibdev->ibdev);
++		return NULL;
++	}
++	nesibdev->ibdev.iwcm->add_ref = nes_add_ref;
++	nesibdev->ibdev.iwcm->rem_ref = nes_rem_ref;
++	nesibdev->ibdev.iwcm->get_qp = nes_get_qp;
++	nesibdev->ibdev.iwcm->connect = nes_connect;
++	nesibdev->ibdev.iwcm->accept = nes_accept;
++	nesibdev->ibdev.iwcm->reject = nes_reject;
++	nesibdev->ibdev.iwcm->create_listen = nes_create_listen;
++	nesibdev->ibdev.iwcm->destroy_listen = nes_destroy_listen;
++
++	return nesibdev;
++}
++
++
++/**
++ * nes_destroy_ofa_device
 + */
- extern const u8 ipath_cvt_physportstate[];
-+#define IB_PHYSPORTSTATE_SLEEP 1
-+#define IB_PHYSPORTSTATE_POLL 2
-+#define IB_PHYSPORTSTATE_DISABLED 3
-+#define IB_PHYSPORTSTATE_CFG_TRAIN 4
-+#define IB_PHYSPORTSTATE_LINKUP 5
-+#define IB_PHYSPORTSTATE_LINK_ERR_RECOVER 6
- 
- extern const int ib_ipath_state_ops[];
- 
-diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c
-index 9d32c49..7950aa6 100644
---- a/drivers/infiniband/hw/mlx4/cq.c
-+++ b/drivers/infiniband/hw/mlx4/cq.c
-@@ -313,6 +313,7 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
- 	struct mlx4_ib_srq *srq;
- 	int is_send;
- 	int is_error;
-+	u32 g_mlpath_rqpn;
- 	u16 wqe_ctr;
- 
- 	cqe = next_cqe_sw(cq);
-@@ -426,10 +427,10 @@ static int mlx4_ib_poll_one(struct mlx4_ib_cq *cq,
- 
- 		wc->slid	   = be16_to_cpu(cqe->rlid);
- 		wc->sl		   = cqe->sl >> 4;
--		wc->src_qp	   = be32_to_cpu(cqe->g_mlpath_rqpn) & 0xffffff;
--		wc->dlid_path_bits = (be32_to_cpu(cqe->g_mlpath_rqpn) >> 24) & 0x7f;
--		wc->wc_flags      |= be32_to_cpu(cqe->g_mlpath_rqpn) & 0x80000000 ?
--			IB_WC_GRH : 0;
-+		g_mlpath_rqpn	   = be32_to_cpu(cqe->g_mlpath_rqpn);
-+		wc->src_qp	   = g_mlpath_rqpn & 0xffffff;
-+		wc->dlid_path_bits = (g_mlpath_rqpn >> 24) & 0x7f;
-+		wc->wc_flags	  |= g_mlpath_rqpn & 0x80000000 ? IB_WC_GRH : 0;
- 		wc->pkey_index     = be32_to_cpu(cqe->immed_rss_invalid) & 0x7f;
- 	}
- 
-diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
-index 15aa32e..7bbdd1f 100644
---- a/drivers/infiniband/hw/mthca/mthca_dev.h
-+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
-@@ -60,13 +60,12 @@
- enum {
- 	MTHCA_FLAG_DDR_HIDDEN = 1 << 1,
- 	MTHCA_FLAG_SRQ        = 1 << 2,
--	MTHCA_FLAG_MSI        = 1 << 3,
--	MTHCA_FLAG_MSI_X      = 1 << 4,
--	MTHCA_FLAG_NO_LAM     = 1 << 5,
--	MTHCA_FLAG_FMR        = 1 << 6,
--	MTHCA_FLAG_MEMFREE    = 1 << 7,
--	MTHCA_FLAG_PCIE       = 1 << 8,
--	MTHCA_FLAG_SINAI_OPT  = 1 << 9
-+	MTHCA_FLAG_MSI_X      = 1 << 3,
-+	MTHCA_FLAG_NO_LAM     = 1 << 4,
-+	MTHCA_FLAG_FMR        = 1 << 5,
-+	MTHCA_FLAG_MEMFREE    = 1 << 6,
-+	MTHCA_FLAG_PCIE       = 1 << 7,
-+	MTHCA_FLAG_SINAI_OPT  = 1 << 8
- };
- 
- enum {
-diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
-index b29de51..b60eb5d 100644
---- a/drivers/infiniband/hw/mthca/mthca_eq.c
-+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
-@@ -827,8 +827,7 @@ int mthca_init_eq_table(struct mthca_dev *dev)
- 	if (err)
- 		goto err_out_free;
- 
--	if (dev->mthca_flags & MTHCA_FLAG_MSI ||
--	    dev->mthca_flags & MTHCA_FLAG_MSI_X) {
-+	if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
- 		dev->eq_table.clr_mask = 0;
- 	} else {
- 		dev->eq_table.clr_mask =
-@@ -839,8 +838,7 @@ int mthca_init_eq_table(struct mthca_dev *dev)
- 
- 	dev->eq_table.arm_mask = 0;
- 
--	intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
--		128 : dev->eq_table.inta_pin;
-+	intr = dev->eq_table.inta_pin;
- 
- 	err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
- 			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
-diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
-index 60de6f9..5cf8250 100644
---- a/drivers/infiniband/hw/mthca/mthca_main.c
-+++ b/drivers/infiniband/hw/mthca/mthca_main.c
-@@ -65,14 +65,9 @@ static int msi_x = 1;
- module_param(msi_x, int, 0444);
- MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
- 
--static int msi = 0;
--module_param(msi, int, 0444);
--MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero (deprecated, use MSI-X instead)");
--
- #else /* CONFIG_PCI_MSI */
- 
- #define msi_x (0)
--#define msi   (0)
- 
- #endif /* CONFIG_PCI_MSI */
- 
-@@ -816,13 +811,11 @@ static int mthca_setup_hca(struct mthca_dev *dev)
- 
- 	err = mthca_NOP(dev, &status);
- 	if (err || status) {
--		if (dev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X)) {
-+		if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
- 			mthca_warn(dev, "NOP command failed to generate interrupt "
- 				   "(IRQ %d).\n",
--				   dev->mthca_flags & MTHCA_FLAG_MSI_X ?
--				   dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector :
--				   dev->pdev->irq);
--			mthca_warn(dev, "Trying again with MSI/MSI-X disabled.\n");
-+				   dev->eq_table.eq[MTHCA_EQ_CMD].msi_x_vector);
-+			mthca_warn(dev, "Trying again with MSI-X disabled.\n");
- 		} else {
- 			mthca_err(dev, "NOP command failed to generate interrupt "
- 				  "(IRQ %d), aborting.\n",
-@@ -1005,7 +998,7 @@ static struct {
- 			   .flags     = 0 },
- 	[ARBEL_COMPAT] = { .latest_fw = MTHCA_FW_VER(4, 8, 200),
- 			   .flags     = MTHCA_FLAG_PCIE },
--	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 2, 0),
-+	[ARBEL_NATIVE] = { .latest_fw = MTHCA_FW_VER(5, 3, 0),
- 			   .flags     = MTHCA_FLAG_MEMFREE |
- 					MTHCA_FLAG_PCIE },
- 	[SINAI]        = { .latest_fw = MTHCA_FW_VER(1, 2, 0),
-@@ -1128,29 +1121,12 @@ static int __mthca_init_one(struct pci_dev *pdev, int hca_type)
- 
- 	if (msi_x && !mthca_enable_msi_x(mdev))
- 		mdev->mthca_flags |= MTHCA_FLAG_MSI_X;
--	else if (msi) {
--		static int warned;
--
--		if (!warned) {
--			printk(KERN_WARNING PFX "WARNING: MSI support will be "
--			       "removed from the ib_mthca driver in January 2008.\n");
--			printk(KERN_WARNING "    If you are using MSI and cannot "
--			       "switch to MSI-X, please tell "
--			       "<general at lists.openfabrics.org>.\n");
--			++warned;
--		}
--
--		if (!pci_enable_msi(pdev))
--			mdev->mthca_flags |= MTHCA_FLAG_MSI;
--	}
- 
- 	err = mthca_setup_hca(mdev);
--	if (err == -EBUSY && (mdev->mthca_flags & (MTHCA_FLAG_MSI | MTHCA_FLAG_MSI_X))) {
-+	if (err == -EBUSY && (mdev->mthca_flags & MTHCA_FLAG_MSI_X)) {
- 		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
- 			pci_disable_msix(pdev);
--		if (mdev->mthca_flags & MTHCA_FLAG_MSI)
--			pci_disable_msi(pdev);
--		mdev->mthca_flags &= ~(MTHCA_FLAG_MSI_X | MTHCA_FLAG_MSI);
-+		mdev->mthca_flags &= ~MTHCA_FLAG_MSI_X;
- 
- 		err = mthca_setup_hca(mdev);
- 	}
-@@ -1192,8 +1168,6 @@ err_cleanup:
- err_close:
- 	if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
- 		pci_disable_msix(pdev);
--	if (mdev->mthca_flags & MTHCA_FLAG_MSI)
--		pci_disable_msi(pdev);
- 
- 	mthca_close_hca(mdev);
- 
-@@ -1246,8 +1220,6 @@ static void __mthca_remove_one(struct pci_dev *pdev)
- 
- 		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
- 			pci_disable_msix(pdev);
--		if (mdev->mthca_flags & MTHCA_FLAG_MSI)
--			pci_disable_msi(pdev);
- 
- 		ib_dealloc_device(&mdev->ib_dev);
- 		mthca_release_regions(pdev, mdev->mthca_flags &
++void nes_destroy_ofa_device(struct nes_ib_device *nesibdev)
++{
++	if (nesibdev == NULL)
++		return;
++
++	nes_unregister_ofa_device(nesibdev);
++
++	kfree(nesibdev->ibdev.iwcm);
++	ib_dealloc_device(&nesibdev->ibdev);
++}
++
++
++/**
++ * nes_register_ofa_device
++ */
++int nes_register_ofa_device(struct nes_ib_device *nesibdev)
++{
++	struct nes_vnic *nesvnic = nesibdev->nesvnic;
++	struct nes_device *nesdev = nesvnic->nesdev;
++	struct nes_adapter *nesadapter = nesdev->nesadapter;
++	int i, ret;
++
++	ret = ib_register_device(&nesvnic->nesibdev->ibdev);
++	if (ret) {
++		return ret;
++	}
++
++	/* Get the resources allocated to this device */
++	nesibdev->max_cq = (nesadapter->max_cq-NES_FIRST_QPN) / nesadapter->port_count;
++	nesibdev->max_mr = nesadapter->max_mr / nesadapter->port_count;
++	nesibdev->max_qp = (nesadapter->max_qp-NES_FIRST_QPN) / nesadapter->port_count;
++	nesibdev->max_pd = nesadapter->max_pd / nesadapter->port_count;
++
++	for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) {
++		ret = class_device_create_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]);
++		if (ret) {
++			while (i > 0) {
++				i--;
++				class_device_remove_file(&nesibdev->ibdev.class_dev,
++						nes_class_attributes[i]);
++			}
++			ib_unregister_device(&nesibdev->ibdev);
++			return ret;
++		}
++	}
++
++	nesvnic->of_device_registered = 1;
++
++	return 0;
++}
++
++
++/**
++ * nes_unregister_ofa_device
++ */
++void nes_unregister_ofa_device(struct nes_ib_device *nesibdev)
++{
++	struct nes_vnic *nesvnic = nesibdev->nesvnic;
++	int i;
++
++	if (nesibdev == NULL)
++		return;
++
++	for (i = 0; i < ARRAY_SIZE(nes_class_attributes); ++i) {
++		class_device_remove_file(&nesibdev->ibdev.class_dev, nes_class_attributes[i]);
++	}
++
++	if (nesvnic->of_device_registered) {
++		ib_unregister_device(&nesibdev->ibdev);
++	}
++
++	nesvnic->of_device_registered = 0;
++}
+diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h
+new file mode 100644
+index 0000000..6c6b4da
+--- /dev/null
++++ b/drivers/infiniband/hw/nes/nes_verbs.h
+@@ -0,0 +1,169 @@
++/*
++ * Copyright (c) 2006 - 2008 NetEffect, Inc. All rights reserved.
++ * Copyright (c) 2005 Open Grid Computing, Inc. All rights reserved.
++ *
++ * This software is available to you under a choice of one of two
++ * licenses.  You may choose to be licensed under the terms of the GNU
++ * General Public License (GPL) Version 2, available from the file
++ * COPYING in the main directory of this source tree, or the
++ * OpenIB.org BSD license below:
++ *
++ *     Redistribution and use in source and binary forms, with or
++ *     without modification, are permitted provided that the following
++ *     conditions are met:
++ *
++ *      - Redistributions of source code must retain the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer.
++ *
++ *      - Redistributions in binary form must reproduce the above
++ *        copyright notice, this list of conditions and the following
++ *        disclaimer in the documentation and/or other materials
++ *        provided with the distribution.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ */
++
++#ifndef NES_VERBS_H
++#define NES_VERBS_H
++
++struct nes_device;
++
++#define NES_MAX_USER_DB_REGIONS  4096
++#define NES_MAX_USER_WQ_REGIONS  4096
++
++struct nes_ucontext {
++	struct ib_ucontext ibucontext;
++	struct nes_device  *nesdev;
++	unsigned long      mmap_wq_offset;
++	unsigned long      mmap_cq_offset; /* to be removed */
++	int                index;		/* rnic index (minor) */
++	unsigned long      allocated_doorbells[BITS_TO_LONGS(NES_MAX_USER_DB_REGIONS)];
++	u16                mmap_db_index[NES_MAX_USER_DB_REGIONS];
++	u16                first_free_db;
++	unsigned long      allocated_wqs[BITS_TO_LONGS(NES_MAX_USER_WQ_REGIONS)];
++	struct nes_qp      *mmap_nesqp[NES_MAX_USER_WQ_REGIONS];
++	u16                first_free_wq;
++	struct list_head   cq_reg_mem_list;
++	struct list_head   qp_reg_mem_list;
++	u32                mcrqf;
++	atomic_t	   usecnt;
++};
++
++struct nes_pd {
++	struct ib_pd ibpd;
++	u16          pd_id;
++	atomic_t     sqp_count;
++	u16          mmap_db_index;
++};
++
++struct nes_mr {
++	union {
++		struct ib_mr  ibmr;
++		struct ib_mw  ibmw;
++		struct ib_fmr ibfmr;
++	};
++	struct ib_umem    *region;
++	u16               pbls_used;
++	u8                mode;
++	u8                pbl_4k;
++};
++
++struct nes_hw_pb {
++	__le32 pa_low;
++	__le32 pa_high;
++};
++
++struct nes_vpbl {
++	dma_addr_t       pbl_pbase;
++	struct nes_hw_pb *pbl_vbase;
++};
++
++struct nes_root_vpbl {
++	dma_addr_t       pbl_pbase;
++	struct nes_hw_pb *pbl_vbase;
++	struct nes_vpbl  *leaf_vpbl;
++};
++
++struct nes_fmr {
++	struct nes_mr        nesmr;
++	u32                  leaf_pbl_cnt;
++	struct nes_root_vpbl root_vpbl;
++	struct ib_qp         *ib_qp;
++	int                  access_rights;
++	struct ib_fmr_attr   attr;
++};
++
++struct nes_av;
++
++struct nes_cq {
++	struct ib_cq     ibcq;
++	struct nes_hw_cq hw_cq;
++	u32              polled_completions;
++	u32              cq_mem_size;
++	spinlock_t       lock;
++	u8               virtual_cq;
++	u8               pad[3];
++};
++
++struct nes_wq {
++	spinlock_t lock;
++};
++
++struct iw_cm_id;
++struct ietf_mpa_frame;
++
++struct nes_qp {
++	struct ib_qp          ibqp;
++	void                  *allocated_buffer;
++	struct iw_cm_id       *cm_id;
++	struct workqueue_struct *wq;
++	struct work_struct    disconn_work;
++	struct nes_cq         *nesscq;
++	struct nes_cq         *nesrcq;
++	struct nes_pd         *nespd;
++	void *cm_node; /* handle of the node this QP is associated with */
++	struct ietf_mpa_frame *ietf_frame;
++	dma_addr_t            ietf_frame_pbase;
++	wait_queue_head_t     state_waitq;
++	unsigned long         socket;
++	struct nes_hw_qp      hwqp;
++	struct work_struct    work;
++	struct work_struct    ae_work;
++	enum ib_qp_state      ibqp_state;
++	u32                   iwarp_state;
++	u32                   hte_index;
++	u32                   last_aeq;
++	u32                   qp_mem_size;
++	atomic_t              refcount;
++	atomic_t              close_timer_started;
++	u32                   mmap_sq_db_index;
++	u32                   mmap_rq_db_index;
++	spinlock_t            lock;
++	struct nes_qp_context *nesqp_context;
++	dma_addr_t            nesqp_context_pbase;
++	void	              *pbl_vbase;
++	dma_addr_t            pbl_pbase;
++	struct page           *page;
++	wait_queue_head_t     kick_waitq;
++	u16                   in_disconnect;
++	u16                   private_data_len;
++	u8                    active_conn;
++	u8                    skip_lsmm;
++	u8                    user_mode;
++	u8                    hte_added;
++	u8                    hw_iwarp_state;
++	u8                    flush_issued;
++	u8                    hw_tcp_state;
++	u8                    disconn_pending;
++	u8                    destroyed;
++};
++#endif			/* NES_VERBS_H */
 diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
 index eb7edab..fe250c6 100644
 --- a/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -429599,7 +480716,7 @@
  	return ib_post_send(priv->qp, &priv->tx_wr, &bad_wr);
  }
 diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
-index c9f6077..a082466 100644
+index c9f6077..09f5371 100644
 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
 +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
 @@ -182,17 +182,20 @@ static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
@@ -429654,7 +480771,48 @@
  	if (likely(skb->dst && skb->dst->neighbour)) {
  		if (unlikely(!*to_ipoib_neigh(skb->dst->neighbour))) {
  			ipoib_path_lookup(skb, dev);
-@@ -950,34 +943,34 @@ static void ipoib_setup(struct net_device *dev)
+@@ -687,12 +680,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 		neigh = *to_ipoib_neigh(skb->dst->neighbour);
+ 
+-		if (ipoib_cm_get(neigh)) {
+-			if (ipoib_cm_up(neigh)) {
+-				ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
+-				goto out;
+-			}
+-		} else if (neigh->ah) {
++		if (neigh->ah)
+ 			if (unlikely((memcmp(&neigh->dgid.raw,
+ 					    skb->dst->neighbour->ha + 4,
+ 					    sizeof(union ib_gid))) ||
+@@ -713,6 +701,12 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 				goto out;
+ 			}
+ 
++		if (ipoib_cm_get(neigh)) {
++			if (ipoib_cm_up(neigh)) {
++				ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
++				goto out;
++			}
++		} else if (neigh->ah) {
+ 			ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb->dst->neighbour->ha));
+ 			goto out;
+ 		}
+@@ -820,11 +814,9 @@ static void ipoib_neigh_cleanup(struct neighbour *n)
+ 	struct ipoib_ah *ah = NULL;
+ 
+ 	neigh = *to_ipoib_neigh(n);
+-	if (neigh) {
++	if (neigh)
+ 		priv = netdev_priv(neigh->dev);
+-		ipoib_dbg(priv, "neigh_destructor for bonding device: %s\n",
+-			  n->dev->name);
+-	} else
++	else
+ 		return;
+ 	ipoib_dbg(priv,
+ 		  "neigh_cleanup for %06x " IPOIB_GID_FMT "\n",
+@@ -950,34 +942,34 @@ static void ipoib_setup(struct net_device *dev)
  {
  	struct ipoib_dev_priv *priv = netdev_priv(dev);
  
@@ -429706,7 +480864,7 @@
  
  	memcpy(dev->broadcast, ipv4_bcast_addr, INFINIBAND_ALEN);
  
-@@ -1268,6 +1261,9 @@ static int __init ipoib_init_module(void)
+@@ -1268,6 +1260,9 @@ static int __init ipoib_init_module(void)
  	ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
  	ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
  	ipoib_sendq_size = max(ipoib_sendq_size, IPOIB_MIN_QUEUE_SIZE);
@@ -429919,10 +481077,33 @@
  	}
  	return ret;
 diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
-index bdb6f85..195ce7c 100644
+index bdb6f85..fd4a49f 100644
 --- a/drivers/infiniband/ulp/srp/ib_srp.c
 +++ b/drivers/infiniband/ulp/srp/ib_srp.c
-@@ -272,7 +272,8 @@ static void srp_path_rec_completion(int status,
+@@ -204,6 +204,22 @@ out:
+ 	return ret;
+ }
+ 
++static int srp_new_cm_id(struct srp_target_port *target)
++{
++	struct ib_cm_id *new_cm_id;
++
++	new_cm_id = ib_create_cm_id(target->srp_host->dev->dev,
++				    srp_cm_handler, target);
++	if (IS_ERR(new_cm_id))
++		return PTR_ERR(new_cm_id);
++
++	if (target->cm_id)
++		ib_destroy_cm_id(target->cm_id);
++	target->cm_id = new_cm_id;
++
++	return 0;
++}
++
+ static int srp_create_target_ib(struct srp_target_port *target)
+ {
+ 	struct ib_qp_init_attr *init_attr;
+@@ -272,7 +288,8 @@ static void srp_path_rec_completion(int status,
  
  	target->status = status;
  	if (status)
@@ -429932,7 +481113,7 @@
  	else
  		target->path = *pathrec;
  	complete(&target->done);
-@@ -303,7 +304,8 @@ static int srp_lookup_path(struct srp_target_port *target)
+@@ -303,7 +320,8 @@ static int srp_lookup_path(struct srp_target_port *target)
  	wait_for_completion(&target->done);
  
  	if (target->status < 0)
@@ -429942,7 +481123,7 @@
  
  	return target->status;
  }
-@@ -379,9 +381,10 @@ static int srp_send_req(struct srp_target_port *target)
+@@ -379,9 +397,10 @@ static int srp_send_req(struct srp_target_port *target)
  	 * the second 8 bytes to the local node GUID.
  	 */
  	if (srp_target_is_topspin(target)) {
@@ -429956,7 +481137,7 @@
  		memset(req->priv.initiator_port_id, 0, 8);
  		memcpy(req->priv.initiator_port_id + 8,
  		       &target->srp_host->dev->dev->node_guid, 8);
-@@ -400,7 +403,8 @@ static void srp_disconnect_target(struct srp_target_port *target)
+@@ -400,7 +419,8 @@ static void srp_disconnect_target(struct srp_target_port *target)
  
  	init_completion(&target->done);
  	if (ib_send_cm_dreq(target->cm_id, NULL, 0)) {
@@ -429966,7 +481147,62 @@
  		return;
  	}
  	wait_for_completion(&target->done);
-@@ -568,7 +572,8 @@ static int srp_reconnect_target(struct srp_target_port *target)
+@@ -432,6 +452,7 @@ static void srp_remove_work(struct work_struct *work)
+ 
+ static int srp_connect_target(struct srp_target_port *target)
+ {
++	int retries = 3;
+ 	int ret;
+ 
+ 	ret = srp_lookup_path(target);
+@@ -464,6 +485,21 @@ static int srp_connect_target(struct srp_target_port *target)
+ 		case SRP_DLID_REDIRECT:
+ 			break;
+ 
++		case SRP_STALE_CONN:
++			/* Our current CM id was stale, and is now in timewait.
++			 * Try to reconnect with a new one.
++			 */
++			if (!retries-- || srp_new_cm_id(target)) {
++				shost_printk(KERN_ERR, target->scsi_host, PFX
++					     "giving up on stale connection\n");
++				target->status = -ECONNRESET;
++				return target->status;
++			}
++
++			shost_printk(KERN_ERR, target->scsi_host, PFX
++				     "retrying stale connection\n");
++			break;
++
+ 		default:
+ 			return target->status;
+ 		}
+@@ -503,7 +539,6 @@ static void srp_reset_req(struct srp_target_port *target, struct srp_request *re
+ 
+ static int srp_reconnect_target(struct srp_target_port *target)
+ {
+-	struct ib_cm_id *new_cm_id;
+ 	struct ib_qp_attr qp_attr;
+ 	struct srp_request *req, *tmp;
+ 	struct ib_wc wc;
+@@ -522,14 +557,9 @@ static int srp_reconnect_target(struct srp_target_port *target)
+ 	 * Now get a new local CM ID so that we avoid confusing the
+ 	 * target in case things are really fouled up.
+ 	 */
+-	new_cm_id = ib_create_cm_id(target->srp_host->dev->dev,
+-				    srp_cm_handler, target);
+-	if (IS_ERR(new_cm_id)) {
+-		ret = PTR_ERR(new_cm_id);
++	ret = srp_new_cm_id(target);
++	if (ret)
+ 		goto err;
+-	}
+-	ib_destroy_cm_id(target->cm_id);
+-	target->cm_id = new_cm_id;
+ 
+ 	qp_attr.qp_state = IB_QPS_RESET;
+ 	ret = ib_modify_qp(target->qp, &qp_attr, IB_QP_STATE);
+@@ -568,7 +598,8 @@ static int srp_reconnect_target(struct srp_target_port *target)
  	return ret;
  
  err:
@@ -429976,7 +481212,7 @@
  
  	/*
  	 * We couldn't reconnect, so kill our target port off.
-@@ -683,8 +688,9 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
+@@ -683,8 +714,9 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
  
  	if (scmnd->sc_data_direction != DMA_FROM_DEVICE &&
  	    scmnd->sc_data_direction != DMA_TO_DEVICE) {
@@ -429988,7 +481224,7 @@
  		return -EINVAL;
  	}
  
-@@ -786,8 +792,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
+@@ -786,8 +818,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
  	} else {
  		scmnd = req->scmnd;
  		if (!scmnd)
@@ -430000,7 +481236,7 @@
  		scmnd->result = rsp->status;
  
  		if (rsp->flags & SRP_RSP_FLAG_SNSVALID) {
-@@ -831,7 +838,8 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+@@ -831,7 +864,8 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
  	if (0) {
  		int i;
  
@@ -430010,7 +481246,7 @@
  
  		for (i = 0; i < wc->byte_len; ++i) {
  			if (i % 8 == 0)
-@@ -852,11 +860,13 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
+@@ -852,11 +886,13 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
  
  	case SRP_T_LOGOUT:
  		/* XXX Handle target logout */
@@ -430026,7 +481262,7 @@
  		break;
  	}
  
-@@ -872,9 +882,10 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr)
+@@ -872,9 +908,10 @@ static void srp_completion(struct ib_cq *cq, void *target_ptr)
  	ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
  	while (ib_poll_cq(cq, 1, &wc) > 0) {
  		if (wc.status) {
@@ -430040,7 +481276,7 @@
  			target->qp_in_error = 1;
  			break;
  		}
-@@ -930,13 +941,18 @@ static int srp_post_recv(struct srp_target_port *target)
+@@ -930,13 +967,18 @@ static int srp_post_recv(struct srp_target_port *target)
   * req_lim and tx_head.  Lock cannot be dropped between call here and
   * call to __srp_post_send().
   */
@@ -430061,7 +481297,7 @@
  
  	return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
  }
-@@ -993,7 +1009,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
+@@ -993,7 +1035,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
  		return 0;
  	}
  
@@ -430070,7 +481306,7 @@
  	if (!iu)
  		goto err;
  
-@@ -1022,12 +1038,13 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
+@@ -1022,12 +1064,13 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
  
  	len = srp_map_data(scmnd, target, req);
  	if (len < 0) {
@@ -430086,7 +481322,7 @@
  		goto err_unmap;
  	}
  
-@@ -1035,7 +1052,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
+@@ -1035,7 +1078,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
  				      DMA_TO_DEVICE);
  
  	if (__srp_post_send(target, iu, len)) {
@@ -430095,7 +481331,7 @@
  		goto err_unmap;
  	}
  
-@@ -1090,6 +1107,7 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
+@@ -1090,6 +1133,7 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
  			       struct ib_cm_event *event,
  			       struct srp_target_port *target)
  {
@@ -430103,7 +481339,7 @@
  	struct ib_class_port_info *cpi;
  	int opcode;
  
-@@ -1115,19 +1133,22 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
+@@ -1115,19 +1159,22 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
  			memcpy(target->path.dgid.raw,
  			       event->param.rej_rcvd.ari, 16);
  
@@ -430131,7 +481367,7 @@
  		target->status = -ECONNRESET;
  		break;
  
-@@ -1138,20 +1159,21 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
+@@ -1138,20 +1185,26 @@ static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
  			u32 reason = be32_to_cpu(rej->reason);
  
  			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)
@@ -430153,6 +481389,11 @@
  		target->status = -ECONNRESET;
  		break;
  
++	case IB_CM_REJ_STALE_CONN:
++		shost_printk(KERN_WARNING, shost, "  REJ reason: stale connection\n");
++		target->status = SRP_STALE_CONN;
++		break;
++
  	default:
 -		printk(KERN_WARNING "  REJ reason 0x%x\n",
 -		       event->param.rej_rcvd.reason);
@@ -430161,7 +481402,7 @@
  		target->status = -ECONNRESET;
  	}
  }
-@@ -1166,7 +1188,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+@@ -1166,7 +1219,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
  
  	switch (event->event) {
  	case IB_CM_REQ_ERROR:
@@ -430171,7 +481412,7 @@
  		comp = 1;
  		target->status = -ECONNRESET;
  		break;
-@@ -1184,7 +1207,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+@@ -1184,7 +1238,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
  			target->scsi_host->can_queue = min(target->req_lim,
  							   target->scsi_host->can_queue);
  		} else {
@@ -430181,7 +481422,7 @@
  			target->status = -ECONNRESET;
  			break;
  		}
-@@ -1230,20 +1254,23 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+@@ -1230,20 +1285,23 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
  		break;
  
  	case IB_CM_REJ_RECEIVED:
@@ -430209,7 +481450,7 @@
  
  		comp = 1;
  		target->status = 0;
-@@ -1255,7 +1282,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
+@@ -1255,7 +1313,8 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
  		break;
  
  	default:
@@ -430219,7 +481460,7 @@
  		break;
  	}
  
-@@ -1283,7 +1311,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
+@@ -1283,7 +1342,7 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
  
  	init_completion(&req->done);
  
@@ -430228,7 +481469,7 @@
  	if (!iu)
  		goto out;
  
-@@ -1332,7 +1360,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
+@@ -1332,7 +1391,7 @@ static int srp_abort(struct scsi_cmnd *scmnd)
  	struct srp_request *req;
  	int ret = SUCCESS;
  
@@ -430237,7 +481478,7 @@
  
  	if (target->qp_in_error)
  		return FAILED;
-@@ -1362,7 +1390,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
+@@ -1362,7 +1421,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
  	struct srp_target_port *target = host_to_target(scmnd->device->host);
  	struct srp_request *req, *tmp;
  
@@ -430246,7 +481487,7 @@
  
  	if (target->qp_in_error)
  		return FAILED;
-@@ -1389,7 +1417,7 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
+@@ -1389,7 +1448,7 @@ static int srp_reset_host(struct scsi_cmnd *scmnd)
  	struct srp_target_port *target = host_to_target(scmnd->device->host);
  	int ret = FAILED;
  
@@ -430255,7 +481496,7 @@
  
  	if (!srp_reconnect_target(target))
  		ret = SUCCESS;
-@@ -1814,8 +1842,9 @@ static ssize_t srp_create_target(struct class_device *class_dev,
+@@ -1814,8 +1873,9 @@ static ssize_t srp_create_target(struct class_device *class_dev,
  
  	ib_get_cached_gid(host->dev->dev, host->port, 0, &target->path.sgid);
  
@@ -430267,7 +481508,18 @@
  	       (unsigned long long) be64_to_cpu(target->id_ext),
  	       (unsigned long long) be64_to_cpu(target->ioc_guid),
  	       be16_to_cpu(target->path.pkey),
-@@ -1842,7 +1871,8 @@ static ssize_t srp_create_target(struct class_device *class_dev,
+@@ -1833,16 +1893,15 @@ static ssize_t srp_create_target(struct class_device *class_dev,
+ 	if (ret)
+ 		goto err;
+ 
+-	target->cm_id = ib_create_cm_id(host->dev->dev, srp_cm_handler, target);
+-	if (IS_ERR(target->cm_id)) {
+-		ret = PTR_ERR(target->cm_id);
++	ret = srp_new_cm_id(target);
++	if (ret)
+ 		goto err_free;
+-	}
+ 
  	target->qp_in_error = 0;
  	ret = srp_connect_target(target);
  	if (ret) {
@@ -430278,10 +481530,18 @@
  	}
  
 diff --git a/drivers/infiniband/ulp/srp/ib_srp.h b/drivers/infiniband/ulp/srp/ib_srp.h
-index e3573e7..4a3c1f3 100644
+index e3573e7..cb6eb81 100644
 --- a/drivers/infiniband/ulp/srp/ib_srp.h
 +++ b/drivers/infiniband/ulp/srp/ib_srp.h
-@@ -79,6 +79,11 @@ enum srp_target_state {
+@@ -54,6 +54,7 @@ enum {
+ 
+ 	SRP_PORT_REDIRECT	= 1,
+ 	SRP_DLID_REDIRECT	= 2,
++	SRP_STALE_CONN		= 3,
+ 
+ 	SRP_MAX_LUN		= 512,
+ 	SRP_DEF_SG_TABLESIZE	= 12,
+@@ -79,6 +80,11 @@ enum srp_target_state {
  	SRP_TARGET_REMOVED
  };
  
@@ -430293,6 +481553,42 @@
  struct srp_device {
  	struct list_head	dev_list;
  	struct ib_device       *dev;
+diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
+index 1dc2ac9..c5600ac 100644
+--- a/drivers/input/gameport/gameport.c
++++ b/drivers/input/gameport/gameport.c
+@@ -17,7 +17,6 @@
+ #include <linux/init.h>
+ #include <linux/gameport.h>
+ #include <linux/wait.h>
+-#include <linux/sched.h>
+ #include <linux/slab.h>
+ #include <linux/delay.h>
+ #include <linux/kthread.h>
+diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c
+index e5f4da9..05e3494 100644
+--- a/drivers/input/keyboard/bf54x-keys.c
++++ b/drivers/input/keyboard/bf54x-keys.c
+@@ -42,7 +42,6 @@
+ #include <linux/delay.h>
+ #include <linux/platform_device.h>
+ #include <linux/input.h>
+-#include <linux/irq.h>
+ 
+ #include <asm/portmux.h>
+ #include <asm/mach/bf54x_keys.h>
+diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c
+index e6696b3..986f93c 100644
+--- a/drivers/input/keyboard/jornada720_kbd.c
++++ b/drivers/input/keyboard/jornada720_kbd.c
+@@ -17,7 +17,6 @@
+  */
+ #include <linux/device.h>
+ #include <linux/errno.h>
+-#include <linux/init.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/input.h>
 diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c
 index 8991ab0..61cff83 100644
 --- a/drivers/input/mouse/pc110pad.c
@@ -430318,6 +481614,19 @@
  	inb_p(0x64);
  
  	pc110pad_data[pc110pad_count++] = value;
+diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
+index 3e99df6..adc3bd6 100644
+--- a/drivers/input/serio/gscps2.c
++++ b/drivers/input/serio/gscps2.c
+@@ -141,7 +141,7 @@ static void gscps2_flush(struct gscps2port *ps2port)
+ /*
+  * gscps2_writeb_output() - write a byte to the port
+  *
+- * returns 1 on sucess, 0 on error
++ * returns 1 on success, 0 on error
+  */
+ 
+ static inline int gscps2_writeb_output(struct gscps2port *ps2port, u8 data)
 diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
 index b1b2e07..99d92f5 100644
 --- a/drivers/input/touchscreen/corgi_ts.c
@@ -430424,6 +481733,71 @@
  /* Kernel message macros for situations where dev_printk and friends cannot be
   * used for lack of reliable access to a device structure.
   * linux/usb.h already contains these but in an obsolete form which clutters
+diff --git a/drivers/isdn/hardware/eicon/debuglib.c b/drivers/isdn/hardware/eicon/debuglib.c
+index a19b7ff..e39c5c1 100644
+--- a/drivers/isdn/hardware/eicon/debuglib.c
++++ b/drivers/isdn/hardware/eicon/debuglib.c
+@@ -106,7 +106,7 @@ DbgRegister (char *drvName, char *drvTag, unsigned long dbgMask)
+   return (1) ;
+  }
+ /*
+- * Check if we registered whith an old maint driver (see debuglib.h)
++ * Check if we registered with an old maint driver (see debuglib.h)
+  */
+  if ( myDriverDebugHandle.dbg_end != NULL
+    /* location of 'dbg_prt' in _OldDbgHandle_ struct */
+diff --git a/drivers/isdn/hardware/eicon/debuglib.h b/drivers/isdn/hardware/eicon/debuglib.h
+index 11b3b9e..016410c 100644
+--- a/drivers/isdn/hardware/eicon/debuglib.h
++++ b/drivers/isdn/hardware/eicon/debuglib.h
+@@ -177,7 +177,7 @@ DBG_DECL(PRV3)
+ } }
+ #endif
+ /*
+- * For event level debug use a separate define, the paramete are
++ * For event level debug use a separate define, the parameter are
+  * different and cause compiler errors on some systems.
+  */
+ #define DBG_EVL_ID(args) \
+diff --git a/drivers/isdn/hardware/eicon/di.c b/drivers/isdn/hardware/eicon/di.c
+index ce8df38..10760b3 100644
+--- a/drivers/isdn/hardware/eicon/di.c
++++ b/drivers/isdn/hardware/eicon/di.c
+@@ -285,7 +285,7 @@ byte pr_dpc(ADAPTER * a)
+                 a->ram_in(a, &RcIn->RcId),
+                 a->ram_in(a, &RcIn->RcCh),
+                 a->ram_inw(a, &RcIn->Reference),
+-                tmp[0],  /* type of extended informtion */
++                tmp[0],  /* type of extended information */
+                 tmp[1]); /* extended information        */
+         a->ram_out(a, &RcIn->Rc, 0);
+       }
+diff --git a/drivers/isdn/hardware/eicon/message.c b/drivers/isdn/hardware/eicon/message.c
+index ccd35d0..b9177ca 100644
+--- a/drivers/isdn/hardware/eicon/message.c
++++ b/drivers/isdn/hardware/eicon/message.c
+@@ -4941,7 +4941,7 @@ void sig_ind(PLCI   * plci)
+       /* b = IE1                */
+       /* S = IE1 length + cont. */
+       /* b = IE2                */
+-      /* S = IE2 lenght + cont. */
++      /* S = IE2 length + cont. */
+       sendf(plci->appl,
+         _MANUFACTURER_I,
+         Id,
+diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c
+index f854501..d3999a8 100644
+--- a/drivers/isdn/hysdn/hycapi.c
++++ b/drivers/isdn/hysdn/hycapi.c
+@@ -541,7 +541,7 @@ hycapi_rx_capipkt(hysdn_card * card, unsigned char *buf, unsigned short len)
+ 	}
+ 	ctrl = &cinfo->capi_ctrl;
+ 	if(len < CAPI_MSG_BASELEN) {
+-		printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, lenght %d!\n",
++		printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, length %d!\n",
+ 		       card->myid, len);
+ 		return;
+ 	}	
 diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig
 deleted file mode 100644
 index 6569206..0000000
@@ -446049,6 +497423,46 @@
 -		      struct x86_emulate_ops *ops);
 -
 -#endif				/* __X86_EMULATE_H__ */
+diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
+index 64c66b3..4a93878 100644
+--- a/drivers/leds/led-class.c
++++ b/drivers/leds/led-class.c
+@@ -137,12 +137,14 @@ err_out:
+ EXPORT_SYMBOL_GPL(led_classdev_register);
+ 
+ /**
+- * led_classdev_unregister - unregisters a object of led_properties class.
++ * __led_classdev_unregister - unregisters a object of led_properties class.
+  * @led_cdev: the led device to unregister
++ * @suspended: indicates whether system-wide suspend or resume is in progress
+  *
+  * Unregisters a previously registered via led_classdev_register object.
+  */
+-void led_classdev_unregister(struct led_classdev *led_cdev)
++void __led_classdev_unregister(struct led_classdev *led_cdev,
++				      bool suspended)
+ {
+ 	device_remove_file(led_cdev->dev, &dev_attr_brightness);
+ #ifdef CONFIG_LEDS_TRIGGERS
+@@ -153,13 +155,16 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
+ 	up_write(&led_cdev->trigger_lock);
+ #endif
+ 
+-	device_unregister(led_cdev->dev);
++	if (suspended)
++		device_pm_schedule_removal(led_cdev->dev);
++	else
++		device_unregister(led_cdev->dev);
+ 
+ 	down_write(&leds_list_lock);
+ 	list_del(&led_cdev->node);
+ 	up_write(&leds_list_lock);
+ }
+-EXPORT_SYMBOL_GPL(led_classdev_unregister);
++EXPORT_SYMBOL_GPL(__led_classdev_unregister);
+ 
+ static int __init leds_init(void)
+ {
 diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
 index cb4c670..7743d73 100644
 --- a/drivers/lguest/core.c
@@ -447086,6 +498500,231 @@
  	}							\
  } while(0)
  /* (End of aside) :*/
+diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
+index e2eec38..84f85e2 100644
+--- a/drivers/lguest/lguest_device.c
++++ b/drivers/lguest/lguest_device.c
+@@ -52,57 +52,82 @@ struct lguest_device {
+ /*D:130
+  * Device configurations
+  *
+- * The configuration information for a device consists of a series of fields.
+- * We don't really care what they are: the Launcher set them up, and the driver
+- * will look at them during setup.
++ * The configuration information for a device consists of one or more
++ * virtqueues, a feature bitmaks, and some configuration bytes.  The
++ * configuration bytes don't really matter to us: the Launcher sets them up, and
++ * the driver will look at them during setup.
+  *
+- * For us these fields come immediately after that device's descriptor in the
+- * lguest_devices page.
+- *
+- * Each field starts with a "type" byte, a "length" byte, then that number of
+- * bytes of configuration information.  The device descriptor tells us the
+- * total configuration length so we know when we've reached the last field. */
++ * A convenient routine to return the device's virtqueue config array:
++ * immediately after the descriptor. */
++static struct lguest_vqconfig *lg_vq(const struct lguest_device_desc *desc)
++{
++	return (void *)(desc + 1);
++}
+ 
+-/* type + length bytes */
+-#define FHDR_LEN 2
++/* The features come immediately after the virtqueues. */
++static u8 *lg_features(const struct lguest_device_desc *desc)
++{
++	return (void *)(lg_vq(desc) + desc->num_vq);
++}
+ 
+-/* This finds the first field of a given type for a device's configuration. */
+-static void *lg_find(struct virtio_device *vdev, u8 type, unsigned int *len)
++/* The config space comes after the two feature bitmasks. */
++static u8 *lg_config(const struct lguest_device_desc *desc)
+ {
+-	struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
+-	int i;
+-
+-	for (i = 0; i < desc->config_len; i += FHDR_LEN + desc->config[i+1]) {
+-		if (desc->config[i] == type) {
+-			/* Mark it used, so Host can know we looked at it, and
+-			 * also so we won't find the same one twice. */
+-			desc->config[i] |= 0x80;
+-			/* Remember, the second byte is the length. */
+-			*len = desc->config[i+1];
+-			/* We return a pointer to the field header. */
+-			return desc->config + i;
+-		}
+-	}
++	return lg_features(desc) + desc->feature_len * 2;
++}
+ 
+-	/* Not found: return NULL for failure. */
+-	return NULL;
++/* The total size of the config page used by this device (incl. desc) */
++static unsigned desc_size(const struct lguest_device_desc *desc)
++{
++	return sizeof(*desc)
++		+ desc->num_vq * sizeof(struct lguest_vqconfig)
++		+ desc->feature_len * 2
++		+ desc->config_len;
++}
++
++/* This tests (and acknowleges) a feature bit. */
++static bool lg_feature(struct virtio_device *vdev, unsigned fbit)
++{
++	struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
++	u8 *features;
++
++	/* Obviously if they ask for a feature off the end of our feature
++	 * bitmap, it's not set. */
++	if (fbit / 8 > desc->feature_len)
++		return false;
++
++	/* The feature bitmap comes after the virtqueues. */
++	features = lg_features(desc);
++	if (!(features[fbit / 8] & (1 << (fbit % 8))))
++		return false;
++
++	/* We set the matching bit in the other half of the bitmap to tell the
++	 * Host we want to use this feature.  We don't use this yet, but we
++	 * could in future. */
++	features[desc->feature_len + fbit / 8] |= (1 << (fbit % 8));
++	return true;
+ }
+ 
+ /* Once they've found a field, getting a copy of it is easy. */
+-static void lg_get(struct virtio_device *vdev, void *token,
++static void lg_get(struct virtio_device *vdev, unsigned int offset,
+ 		   void *buf, unsigned len)
+ {
+-	/* Check they didn't ask for more than the length of the field! */
+-	BUG_ON(len > ((u8 *)token)[1]);
+-	memcpy(buf, token + FHDR_LEN, len);
++	struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
++
++	/* Check they didn't ask for more than the length of the config! */
++	BUG_ON(offset + len > desc->config_len);
++	memcpy(buf, lg_config(desc) + offset, len);
+ }
+ 
+ /* Setting the contents is also trivial. */
+-static void lg_set(struct virtio_device *vdev, void *token,
++static void lg_set(struct virtio_device *vdev, unsigned int offset,
+ 		   const void *buf, unsigned len)
+ {
+-	BUG_ON(len > ((u8 *)token)[1]);
+-	memcpy(token + FHDR_LEN, buf, len);
++	struct lguest_device_desc *desc = to_lgdev(vdev)->desc;
++
++	/* Check they didn't ask for more than the length of the config! */
++	BUG_ON(offset + len > desc->config_len);
++	memcpy(lg_config(desc) + offset, buf, len);
+ }
+ 
+ /* The operations to get and set the status word just access the status field
+@@ -114,9 +139,20 @@ static u8 lg_get_status(struct virtio_device *vdev)
+ 
+ static void lg_set_status(struct virtio_device *vdev, u8 status)
+ {
++	BUG_ON(!status);
+ 	to_lgdev(vdev)->desc->status = status;
+ }
+ 
++/* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor
++ * address of the device.  The Host will zero the status and all the
++ * features. */
++static void lg_reset(struct virtio_device *vdev)
++{
++	unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
++
++	hcall(LHCALL_NOTIFY, (max_pfn<<PAGE_SHIFT) + offset, 0, 0);
++}
++
+ /*
+  * Virtqueues
+  *
+@@ -165,39 +201,29 @@ static void lg_notify(struct virtqueue *vq)
+  *
+  * So we provide devices with a "find virtqueue and set it up" function. */
+ static struct virtqueue *lg_find_vq(struct virtio_device *vdev,
+-				    bool (*callback)(struct virtqueue *vq))
++				    unsigned index,
++				    void (*callback)(struct virtqueue *vq))
+ {
++	struct lguest_device *ldev = to_lgdev(vdev);
+ 	struct lguest_vq_info *lvq;
+ 	struct virtqueue *vq;
+-	unsigned int len;
+-	void *token;
+ 	int err;
+ 
+-	/* Look for a field of the correct type to mark a virtqueue.  Note that
+-	 * if this succeeds, then the type will be changed so it won't be found
+-	 * again, and future lg_find_vq() calls will find the next
+-	 * virtqueue (if any). */
+-	token = vdev->config->find(vdev, VIRTIO_CONFIG_F_VIRTQUEUE, &len);
+-	if (!token)
++	/* We must have this many virtqueues. */
++	if (index >= ldev->desc->num_vq)
+ 		return ERR_PTR(-ENOENT);
+ 
+ 	lvq = kmalloc(sizeof(*lvq), GFP_KERNEL);
+ 	if (!lvq)
+ 		return ERR_PTR(-ENOMEM);
+ 
+-	/* Note: we could use a configuration space inside here, just like we
+-	 * do for the device.  This would allow expansion in future, because
+-	 * our configuration system is designed to be expansible.  But this is
+-	 * way easier. */
+-	if (len != sizeof(lvq->config)) {
+-		dev_err(&vdev->dev, "Unexpected virtio config len %u\n", len);
+-		err = -EIO;
+-		goto free_lvq;
+-	}
+-	/* Make a copy of the "struct lguest_vqconfig" field.  We need a copy
+-	 * because the config space might not be aligned correctly. */
+-	vdev->config->get(vdev, token, &lvq->config, sizeof(lvq->config));
++	/* Make a copy of the "struct lguest_vqconfig" entry, which sits after
++	 * the descriptor.  We need a copy because the config space might not
++	 * be aligned correctly. */
++	memcpy(&lvq->config, lg_vq(ldev->desc)+index, sizeof(lvq->config));
+ 
++	printk("Mapping virtqueue %i addr %lx\n", index,
++	       (unsigned long)lvq->config.pfn << PAGE_SHIFT);
+ 	/* Figure out how many pages the ring will take, and map that memory */
+ 	lvq->pages = lguest_map((unsigned long)lvq->config.pfn << PAGE_SHIFT,
+ 				DIV_ROUND_UP(vring_size(lvq->config.num,
+@@ -259,11 +285,12 @@ static void lg_del_vq(struct virtqueue *vq)
+ 
+ /* The ops structure which hooks everything together. */
+ static struct virtio_config_ops lguest_config_ops = {
+-	.find = lg_find,
++	.feature = lg_feature,
+ 	.get = lg_get,
+ 	.set = lg_set,
+ 	.get_status = lg_get_status,
+ 	.set_status = lg_set_status,
++	.reset = lg_reset,
+ 	.find_vq = lg_find_vq,
+ 	.del_vq = lg_del_vq,
+ };
+@@ -329,13 +356,14 @@ static void scan_devices(void)
+ 	struct lguest_device_desc *d;
+ 
+ 	/* We start at the page beginning, and skip over each entry. */
+-	for (i = 0; i < PAGE_SIZE; i += sizeof(*d) + d->config_len) {
++	for (i = 0; i < PAGE_SIZE; i += desc_size(d)) {
+ 		d = lguest_devices + i;
+ 
+ 		/* Once we hit a zero, stop. */
+ 		if (d->type == 0)
+ 			break;
+ 
++		printk("Device at %i has size %u\n", i, desc_size(d));
+ 		add_lguest_device(d);
+ 	}
+ }
 diff --git a/drivers/lguest/lguest_user.c b/drivers/lguest/lguest_user.c
 index 3b92a61..85d42d3 100644
 --- a/drivers/lguest/lguest_user.c
@@ -448358,18 +499997,19 @@
 +	setup_guest_gdt(cpu);
  }
 diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
-index 5c742a5..7ce0ea6 100644
+index 5c742a5..2895810 100644
 --- a/drivers/macintosh/adb.c
 +++ b/drivers/macintosh/adb.c
-@@ -35,6 +35,7 @@
+@@ -35,6 +35,8 @@
  #include <linux/spinlock.h>
  #include <linux/completion.h>
  #include <linux/device.h>
 +#include <linux/kthread.h>
++#include <linux/platform_device.h>
  
  #include <asm/uaccess.h>
  #include <asm/semaphore.h>
-@@ -82,21 +83,11 @@ struct adb_driver *adb_controller;
+@@ -82,21 +84,11 @@ struct adb_driver *adb_controller;
  BLOCKING_NOTIFIER_HEAD(adb_client_list);
  static int adb_got_sleep;
  static int adb_inited;
@@ -448391,7 +500031,7 @@
  static int adb_scan_bus(void);
  static int do_adb_reset_bus(void);
  static void adbdev_init(void);
-@@ -134,16 +125,6 @@ static void printADBreply(struct adb_request *req)
+@@ -134,16 +126,6 @@ static void printADBreply(struct adb_request *req)
  }
  #endif
  
@@ -448408,7 +500048,7 @@
  static int adb_scan_bus(void)
  {
  	int i, highFree=0, noMovement;
-@@ -248,13 +229,10 @@ static int adb_scan_bus(void)
+@@ -248,13 +230,10 @@ static int adb_scan_bus(void)
  static int
  adb_probe_task(void *x)
  {
@@ -448422,7 +500062,7 @@
  	up(&adb_probe_mutex);
  
  	return 0;
-@@ -263,7 +241,7 @@ adb_probe_task(void *x)
+@@ -263,7 +242,7 @@ adb_probe_task(void *x)
  static void
  __adb_probe_task(struct work_struct *bullshit)
  {
@@ -448431,7 +500071,7 @@
  }
  
  static DECLARE_WORK(adb_reset_work, __adb_probe_task);
-@@ -281,6 +259,36 @@ adb_reset_bus(void)
+@@ -281,6 +260,36 @@ adb_reset_bus(void)
  	return 0;
  }
  
@@ -448468,7 +500108,7 @@
  int __init adb_init(void)
  {
  	struct adb_driver *driver;
-@@ -313,15 +321,12 @@ int __init adb_init(void)
+@@ -313,15 +322,12 @@ int __init adb_init(void)
  		printk(KERN_WARNING "Warning: no ADB interface detected\n");
  		adb_controller = NULL;
  	} else {
@@ -448485,7 +500125,7 @@
  		adbdev_init();
  		adb_reset_bus();
  	}
-@@ -330,33 +335,6 @@ int __init adb_init(void)
+@@ -330,33 +336,6 @@ int __init adb_init(void)
  
  __initcall(adb_init);
  
@@ -448519,7 +500159,7 @@
  static int
  do_adb_reset_bus(void)
  {
-@@ -373,7 +351,7 @@ do_adb_reset_bus(void)
+@@ -373,7 +352,7 @@ do_adb_reset_bus(void)
  
  	if (sleepy_trackpad) {
  		/* Let the trackpad settle down */
@@ -448528,7 +500168,7 @@
  	}
  
  	down(&adb_handler_sem);
-@@ -389,7 +367,7 @@ do_adb_reset_bus(void)
+@@ -389,7 +368,7 @@ do_adb_reset_bus(void)
  
  	if (sleepy_trackpad) {
  		/* Let the trackpad settle down */
@@ -448537,7 +500177,7 @@
  	}
  
  	if (!ret) {
-@@ -413,41 +391,27 @@ adb_poll(void)
+@@ -413,41 +392,27 @@ adb_poll(void)
  	adb_controller->poll();
  }
  
@@ -448586,7 +500226,7 @@
  	req->nbytes = nbytes+1;
  	req->done = done;
  	req->reply_expected = flags & ADBREQ_REPLY;
-@@ -460,25 +424,18 @@ adb_request(struct adb_request *req, void (*done)(struct adb_request *),
+@@ -460,25 +425,18 @@ adb_request(struct adb_request *req, void (*done)(struct adb_request *),
  	if (flags & ADBREQ_NOSEND)
  		return 0;
  
@@ -448622,7 +500262,7 @@
  
  	return rc;
  }
-@@ -864,7 +821,29 @@ static const struct file_operations adb_fops = {
+@@ -864,7 +822,29 @@ static const struct file_operations adb_fops = {
  	.release	= adb_release,
  };
  
@@ -448653,7 +500293,7 @@
  adbdev_init(void)
  {
  	if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) {
-@@ -875,5 +854,8 @@ adbdev_init(void)
+@@ -875,5 +855,8 @@ adbdev_init(void)
  	adb_dev_class = class_create(THIS_MODULE, "adb");
  	if (IS_ERR(adb_dev_class))
  		return;
@@ -448664,7 +500304,7 @@
 +	platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
  }
 diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
-index 48d647a..de9ebbf 100644
+index 48d647a..9367882 100644
 --- a/drivers/macintosh/mediabay.c
 +++ b/drivers/macintosh/mediabay.c
 @@ -20,6 +20,7 @@
@@ -448683,7 +500323,136 @@
  
  #ifdef MB_DEBUG
  #define MBDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
-@@ -563,7 +563,8 @@ static void media_bay_step(int i)
+@@ -78,12 +78,14 @@ struct media_bay_info {
+ 	int				cached_gpio;
+ 	int				sleeping;
+ 	struct semaphore		lock;
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ 	void __iomem			*cd_base;
+-	int 				cd_index;
+ 	int				cd_irq;
+ 	int				cd_retry;
+ #endif
++#if defined(CONFIG_BLK_DEV_IDE_PMAC) || defined(CONFIG_MAC_FLOPPY)
++	int 				cd_index;
++#endif
+ };
+ 
+ #define MAX_BAYS	2
+@@ -91,7 +93,7 @@ struct media_bay_info {
+ static struct media_bay_info media_bays[MAX_BAYS];
+ int media_bay_count = 0;
+ 
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ /* check the busy bit in the media-bay ide interface
+    (assumes the media-bay contains an ide device) */
+ #define MB_IDE_READY(i)	((readb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
+@@ -401,7 +403,7 @@ static void poll_media_bay(struct media_bay_info* bay)
+ 				set_mb_power(bay, id != MB_NO);
+ 				bay->content_id = id;
+ 				if (id == MB_NO) {
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ 					bay->cd_retry = 0;
+ #endif
+ 					printk(KERN_INFO "media bay %d is empty\n", bay->index);
+@@ -414,9 +416,9 @@ static void poll_media_bay(struct media_bay_info* bay)
+ 	}
+ }
+ 
++#ifdef CONFIG_MAC_FLOPPY
+ int check_media_bay(struct device_node *which_bay, int what)
+ {
+-#ifdef CONFIG_BLK_DEV_IDE
+ 	int	i;
+ 
+ 	for (i=0; i<media_bay_count; i++)
+@@ -426,14 +428,14 @@ int check_media_bay(struct device_node *which_bay, int what)
+ 			media_bays[i].cd_index = -1;
+ 			return -EINVAL;
+ 		}
+-#endif /* CONFIG_BLK_DEV_IDE */
+ 	return -ENODEV;
+ }
+ EXPORT_SYMBOL(check_media_bay);
++#endif /* CONFIG_MAC_FLOPPY */
+ 
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ int check_media_bay_by_base(unsigned long base, int what)
+ {
+-#ifdef CONFIG_BLK_DEV_IDE
+ 	int	i;
+ 
+ 	for (i=0; i<media_bay_count; i++)
+@@ -443,15 +445,13 @@ int check_media_bay_by_base(unsigned long base, int what)
+ 			media_bays[i].cd_index = -1;
+ 			return -EINVAL;
+ 		} 
+-#endif
+-	
++
+ 	return -ENODEV;
+ }
+ 
+ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+-	int irq, int index)
++			    int irq, int index)
+ {
+-#ifdef CONFIG_BLK_DEV_IDE
+ 	int	i;
+ 
+ 	for (i=0; i<media_bay_count; i++) {
+@@ -483,10 +483,10 @@ int media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
+ 			return -ENODEV;
+ 		}
+ 	}
+-#endif /* CONFIG_BLK_DEV_IDE */
+-	
++
+ 	return -ENODEV;
+ }
++#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+ 
+ static void media_bay_step(int i)
+ {
+@@ -521,14 +521,13 @@ static void media_bay_step(int i)
+ 	    	bay->state = mb_resetting;
+ 		MBDBG("mediabay%d: waiting reset (kind:%d)\n", i, bay->content_id);
+ 	    	break;
+-	    
+ 	case mb_resetting:
+ 		if (bay->content_id != MB_CD) {
+ 			MBDBG("mediabay%d: bay is up (kind:%d)\n", i, bay->content_id);
+ 			bay->state = mb_up;
+ 			break;
+ 	    	}
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ 		MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id);
+ 		bay->ops->un_reset_ide(bay);
+ 	    	bay->timer = msecs_to_jiffies(MB_IDE_WAIT);
+@@ -536,16 +535,14 @@ static void media_bay_step(int i)
+ #else
+ 		printk(KERN_DEBUG "media-bay %d is ide (not compiled in kernel)\n", i);
+ 		set_mb_power(bay, 0);
+-#endif /* CONFIG_BLK_DEV_IDE */
++#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+ 	    	break;
+-	    
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ 	case mb_ide_resetting:
+ 	    	bay->timer = msecs_to_jiffies(MB_IDE_TIMEOUT);
+ 	    	bay->state = mb_ide_waiting;
+ 		MBDBG("mediabay%d: waiting IDE ready (kind:%d)\n", i, bay->content_id);
+ 	    	break;
+-	    
+ 	case mb_ide_waiting:
+ 		if (bay->cd_base == NULL) {
+ 			bay->timer = 0;
+@@ -563,7 +560,8 @@ static void media_bay_step(int i)
  				ide_init_hwif_ports(&hw, (unsigned long) bay->cd_base, (unsigned long) 0, NULL);
  				hw.irq = bay->cd_irq;
  				hw.chipset = ide_pmac;
@@ -448693,7 +500462,17 @@
  				pmu_resume();
  			}
  			if (bay->cd_index == -1) {
-@@ -594,7 +595,7 @@ static void media_bay_step(int i)
+@@ -586,15 +584,14 @@ static void media_bay_step(int i)
+ 			bay->timer = 0;
+ 	    	}
+ 		break;
+-#endif /* CONFIG_BLK_DEV_IDE */
+-
++#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+ 	case mb_powering_down:
+ 	    	bay->state = mb_empty;
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
      	        if (bay->cd_index >= 0) {
  			printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i,
  			       bay->cd_index);
@@ -448702,7 +500481,16 @@
  			bay->cd_index = -1;
  		}
  	    	if (bay->cd_retry) {
-@@ -622,12 +623,7 @@ static int media_bay_task(void *x)
+@@ -606,7 +603,7 @@ static void media_bay_step(int i)
+ 				bay->content_id = MB_NO;
+ 			}
+ 	    	}
+-#endif /* CONFIG_BLK_DEV_IDE */    
++#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+ 		MBDBG("mediabay%d: end of power down\n", i);
+ 	    	break;
+ 	}
+@@ -622,12 +619,7 @@ static int media_bay_task(void *x)
  {
  	int	i;
  
@@ -448716,7 +500504,7 @@
  		for (i = 0; i < media_bay_count; ++i) {
  			down(&media_bays[i].lock);
  			if (!media_bays[i].sleeping)
-@@ -636,9 +632,8 @@ static int media_bay_task(void *x)
+@@ -636,9 +628,8 @@ static int media_bay_task(void *x)
  		}
  
  		msleep_interruptible(MB_POLL_DELAY);
@@ -448727,7 +500515,7 @@
  }
  
  static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_device_id *match)
-@@ -699,7 +694,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
+@@ -699,7 +690,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
  
  	/* Startup kernel thread */
  	if (i == 0)
@@ -448736,6 +500524,46 @@
  
  	return 0;
  
+@@ -744,7 +735,7 @@ static int media_bay_resume(struct macio_dev *mdev)
+ 	       	bay->last_value = bay->content_id;
+ 	       	bay->value_count = msecs_to_jiffies(MB_STABLE_DELAY);
+ 	       	bay->timer = msecs_to_jiffies(MB_POWER_DELAY);
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ 	       	bay->cd_retry = 0;
+ #endif
+ 	       	do {
+@@ -834,7 +825,7 @@ static int __init media_bay_init(void)
+ 	for (i=0; i<MAX_BAYS; i++) {
+ 		memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info));
+ 		media_bays[i].content_id	= -1;
+-#ifdef CONFIG_BLK_DEV_IDE
++#ifdef CONFIG_BLK_DEV_IDE_PMAC
+ 		media_bays[i].cd_index		= -1;
+ #endif
+ 	}
+diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
+index d409f67..8ba4938 100644
+--- a/drivers/macintosh/smu.c
++++ b/drivers/macintosh/smu.c
+@@ -12,7 +12,7 @@
+  *  - maybe add timeout to commands ?
+  *  - blocking version of time functions
+  *  - polling version of i2c commands (including timer that works with
+- *    interrutps off)
++ *    interrupts off)
+  *  - maybe avoid some data copies with i2c by directly using the smu cmd
+  *    buffer and a lower level internal interface
+  *  - understand SMU -> CPU events and implement reception of them via
+@@ -179,7 +179,7 @@ static irqreturn_t smu_db_intr(int irq, void *arg)
+ 		/* CPU might have brought back the cache line, so we need
+ 		 * to flush again before peeking at the SMU response. We
+ 		 * flush the entire buffer for now as we haven't read the
+-		 * reply lenght (it's only 2 cache lines anyway)
++		 * reply length (it's only 2 cache lines anyway)
+ 		 */
+ 		faddr = (unsigned long)smu->cmd_buf;
+ 		flush_inval_dcache_range(faddr, faddr + 256);
 diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
 index 276945d..54f4942 100644
 --- a/drivers/macintosh/therm_adt746x.c
@@ -449073,6 +500901,19 @@
  	.attach_adapter = do_attach,
  	.detach_client	= do_detach,
  };
+diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c
+index 01b8eca..6e6dd17 100644
+--- a/drivers/macintosh/via-macii.c
++++ b/drivers/macintosh/via-macii.c
+@@ -111,7 +111,7 @@ static enum macii_state {
+ static struct adb_request *current_req; /* first request struct in the queue */
+ static struct adb_request *last_req;     /* last request struct in the queue */
+ static unsigned char reply_buf[16];        /* storage for autopolled replies */
+-static unsigned char *reply_ptr;      /* next byte in req->data or reply_buf */
++static unsigned char *reply_ptr;     /* next byte in reply_buf or req->reply */
+ static int reading_reply;        /* store reply in reply_buf else req->reply */
+ static int data_index;      /* index of the next byte to send from req->data */
+ static int reply_len; /* number of bytes received in reply_buf or req->reply */
 diff --git a/drivers/macintosh/via-pmu-backlight.c b/drivers/macintosh/via-pmu-backlight.c
 index 7e27071..741a2e3 100644
 --- a/drivers/macintosh/via-pmu-backlight.c
@@ -450488,6 +502329,19 @@
 +};
 +
 +EXPORT_SYMBOL_GPL(ir_codes_behold);
+diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
+index 7d04a6f..168a8d3 100644
+--- a/drivers/media/common/saa7146_core.c
++++ b/drivers/media/common/saa7146_core.c
+@@ -388,7 +388,7 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
+ 	}
+ 	dev->revision &= 0xf;
+ 
+-	/* remap the memory from virtual to physical adress */
++	/* remap the memory from virtual to physical address */
+ 
+ 	err = pci_request_region(pci, 0, "saa7146");
+ 	if (err < 0)
 diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
 index 67d1b1b..f0703d8 100644
 --- a/drivers/media/common/saa7146_fops.c
@@ -450995,6 +502849,19 @@
  
  extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
  
+diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
+index a33eb59..ed3f826 100644
+--- a/drivers/media/dvb/dvb-core/dvb_net.c
++++ b/drivers/media/dvb/dvb-core/dvb_net.c
+@@ -681,7 +681,7 @@ static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
+ 							drop = 1;
+ 						/* else: destination address matches the MAC address of our receiver device */
+ 					}
+-					/* else: promiscious mode; pass everything up the stack */
++					/* else: promiscuous mode; pass everything up the stack */
+ 
+ 					if (drop) {
+ #ifdef ULE_DEBUG
 diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
 index 9878183..ac9d93c 100644
 --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -461813,7 +513680,7 @@
 +void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *tuner, int set);
 +
 diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c
-index 585d1ef..63a47cd 100644
+index 585d1ef..7374c02 100644
 --- a/drivers/media/video/bt8xx/bttv-cards.c
 +++ b/drivers/media/video/bt8xx/bttv-cards.c
 @@ -39,6 +39,7 @@
@@ -462407,6 +514274,15 @@
  /* RemoteVision MX (rv605) muxsel helper [Miguel Freitas]
   *
   * This is needed because rv605 don't use a normal multiplex, but a crosspoint
+@@ -4732,7 +4344,7 @@ static void rv605_muxsel(struct bttv *btv, unsigned int input)
+ 	gpio_bits(0x200,0x000);
+ 	mdelay(1);
+ 
+-	/* create a new conection */
++	/* create a new connection */
+ 	gpio_bits(0x480,0x080);
+ 	gpio_bits(0x480,0x480);
+ 	mdelay(1);
 diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
 index 581a3c9..907dc62 100644
 --- a/drivers/media/video/bt8xx/bttv-driver.c
@@ -477732,6 +529608,19 @@
  extern int et61x251_i2c_raw_write(struct et61x251_device*, u8 n, u8 data1,
  				  u8 data2, u8 data3, u8 data4, u8 data5,
  				  u8 data6, u8 data7, u8 data8, u8 address);
+diff --git a/drivers/media/video/indycam.c b/drivers/media/video/indycam.c
+index 5c2c402..84b9e4f 100644
+--- a/drivers/media/video/indycam.c
++++ b/drivers/media/video/indycam.c
+@@ -326,7 +326,7 @@ static int indycam_attach(struct i2c_adapter *adap, int addr, int kind)
+ 	// initialize
+ 	err = indycam_write_block(client, 0, sizeof(initseq), (u8 *)&initseq);
+ 	if (err) {
+-		printk(KERN_ERR "IndyCam initalization failed\n");
++		printk(KERN_ERR "IndyCam initialization failed\n");
+ 		err = -EIO;
+ 		goto out_detach_client;
+ 	}
 diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c
 index 29779d8..9851987 100644
 --- a/drivers/media/video/ir-kbd-i2c.c
@@ -482284,7 +534173,7 @@
  	return (oldrx != state->rxsubchans);
  }
 diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
-index f49d1f4..b630c26 100644
+index f49d1f4..58bab65 100644
 --- a/drivers/media/video/mt20xx.c
 +++ b/drivers/media/video/mt20xx.c
 @@ -14,7 +14,7 @@ static int debug = 0;
@@ -482296,6 +534185,15 @@
  
  /* ---------------------------------------------------------------------- */
  
+@@ -369,7 +369,7 @@ static struct dvb_tuner_ops mt2032_tuner_ops = {
+ 	.get_frequency     = microtune_get_frequency,
+ };
+ 
+-// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
++// Initialization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+ static int mt2032_init(struct dvb_frontend *fe)
+ {
+ 	struct microtune_priv *priv = fe->tuner_priv;
 diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c
 index 98ad309..add6d0d 100644
 --- a/drivers/media/video/mxb.c
@@ -486039,6 +537937,32 @@
  	cp->handler = &ctxt->handler;
  	pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x saa711x V4L2 handler set up",
  		   cp->client->addr);
+diff --git a/drivers/media/video/pvrusb2/pvrusb2.h b/drivers/media/video/pvrusb2/pvrusb2.h
+index 074533e..1a9a4ba 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2.h
++++ b/drivers/media/video/pvrusb2/pvrusb2.h
+@@ -27,7 +27,7 @@
+    might want to increase this - however the driver operation will not
+    be impaired if it is too small.  Instead additional units just
+    won't have an ID assigned and it might not be possible to specify
+-   module paramters for those extra units. */
++   module parameters for those extra units. */
+ #define PVR_NUM 20
+ 
+ #endif /* __PVRUSB2_H */
+diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
+index 7300ace..f991d72 100644
+--- a/drivers/media/video/pwc/pwc-if.c
++++ b/drivers/media/video/pwc/pwc-if.c
+@@ -542,7 +542,7 @@ int pwc_handle_frame(struct pwc_device *pdev)
+ 	}
+ 
+ 	if (pdev->read_frame != NULL) {
+-		/* Decompression is a lenghty process, so it's outside of the lock.
++		/* Decompression is a lengthy process, so it's outside of the lock.
+ 		   This gives the isoc_handler the opportunity to fill more frames
+ 		   in the mean time.
+ 		*/
 diff --git a/drivers/media/video/saa7115.c b/drivers/media/video/saa7115.c
 index 2d18f00..41e5e51 100644
 --- a/drivers/media/video/saa7115.c
@@ -496116,6 +548040,19 @@
  #if defined(CONFIG_TUNER_TEA5767) || (defined(CONFIG_TUNER_TEA5767_MODULE) && defined(MODULE))
  extern int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr);
  
+diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
+index e0ff811..ca05cd6 100644
+--- a/drivers/media/video/tea6420.c
++++ b/drivers/media/video/tea6420.c
+@@ -57,7 +57,7 @@ static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
+ 
+ 	dprintk("adr:0x%02x, i:%d, o:%d, g:%d\n", client->addr, i, o, g);
+ 
+-	/* check if the paramters are valid */
++	/* check if the parameters are valid */
+ 	if (i < 1 || i > 6 || o < 1 || o > 4 || g < 0 || g > 6 || g % 2 != 0)
+ 		return -1;
+ 
 diff --git a/drivers/media/video/tlv320aic23b.c b/drivers/media/video/tlv320aic23b.c
 index 76b2e96..dc7b9c2 100644
 --- a/drivers/media/video/tlv320aic23b.c
@@ -501125,6 +553062,19 @@
 -
 -module_init(upd64083_init_module);
 -module_exit(upd64083_exit_module);
+diff --git a/drivers/media/video/usbvideo/quickcam_messenger.c b/drivers/media/video/usbvideo/quickcam_messenger.c
+index d847273..5e7b795 100644
+--- a/drivers/media/video/usbvideo/quickcam_messenger.c
++++ b/drivers/media/video/usbvideo/quickcam_messenger.c
+@@ -258,7 +258,7 @@ static void qcm_hsv2rgb(u16 hue, u16 sat, u16 val, u16 *r, u16 *g, u16 *b)
+ 	unsigned int p;
+ 
+ 	/*
+-	the registers controling gain are 8 bit of which
++	the registers controlling gain are 8 bit of which
+ 	we affect only the last 4 bits with our gain.
+ 	we know that if saturation is 0, (unsaturated) then
+ 	we're grayscale (center axis of the colour cone) so
 diff --git a/drivers/media/video/usbvision/usbvision-cards.c b/drivers/media/video/usbvision/usbvision-cards.c
 index f09eb10..503b13b 100644
 --- a/drivers/media/video/usbvision/usbvision-cards.c
@@ -501614,9 +553564,18 @@
  
  static void usbvision_powerOffTimer(unsigned long data)
 diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
-index 36e689f..b52b826 100644
+index 36e689f..df52f8a 100644
 --- a/drivers/media/video/usbvision/usbvision-video.c
 +++ b/drivers/media/video/usbvision/usbvision-video.c
+@@ -131,7 +131,7 @@ static struct usbvision_v4l2_format_st usbvision_v4l2_format[] = {
+ /* Function prototypes */
+ static void usbvision_release(struct usb_usbvision *usbvision);
+ 
+-/* Default initalization of device driver parameters */
++/* Default initialization of device driver parameters */
+ /* Set the default format for ISOC endpoint */
+ static int isocMode = ISOC_MODE_COMPRESS;
+ /* Set the default Debug Mode of the device driver */
 @@ -410,7 +410,7 @@ static int usbvision_v4l2_open(struct inode *inode, struct file *file)
  
  	/* If so far no errors then we shall start the camera */
@@ -504544,6 +556503,19 @@
 -
 -module_init(vp27smpx_init_module);
 -module_exit(vp27smpx_cleanup_module);
+diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
+index 8ef31ed..a913385 100644
+--- a/drivers/media/video/vpx3220.c
++++ b/drivers/media/video/vpx3220.c
+@@ -566,7 +566,7 @@ vpx3220_init_client (struct i2c_client *client)
+ }
+ 
+ /* -----------------------------------------------------------------------
+- * Client managment code
++ * Client management code
+  */
+ 
+ /*
 diff --git a/drivers/media/video/wm8739.c b/drivers/media/video/wm8739.c
 index 1bf4cbe..31795b4 100644
 --- a/drivers/media/video/wm8739.c
@@ -504984,6 +556956,45 @@
 -
 -module_init(wm8775_init_module);
 -module_exit(wm8775_cleanup_module);
+diff --git a/drivers/media/video/zoran_card.c b/drivers/media/video/zoran_card.c
+index 6e0ac4c..690281b 100644
+--- a/drivers/media/video/zoran_card.c
++++ b/drivers/media/video/zoran_card.c
+@@ -1270,7 +1270,7 @@ zoran_setup_videocodec (struct zoran *zr,
+ }
+ 
+ /*
+- *   Scan for a Buz card (actually for the PCI contoler ZR36057),
++ *   Scan for a Buz card (actually for the PCI controller ZR36057),
+  *   request the irq and map the io memory
+  */
+ static int __devinit
+diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c
+index 9f622e0..faae4ec 100644
+--- a/drivers/media/video/zr36050.c
++++ b/drivers/media/video/zr36050.c
+@@ -161,7 +161,7 @@ zr36050_wait_end (struct zr36050 *ptr)
+ 		udelay(1);
+ 		if (i++ > 200000) {	// 200ms, there is for sure something wrong!!!
+ 			dprintk(1,
+-				"%s: timout at wait_end (last status: 0x%02x)\n",
++				"%s: timeout at wait_end (last status: 0x%02x)\n",
+ 				ptr->name, ptr->status1);
+ 			break;
+ 		}
+diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c
+index 1ef14fe..7849b65 100644
+--- a/drivers/media/video/zr36060.c
++++ b/drivers/media/video/zr36060.c
+@@ -163,7 +163,7 @@ zr36060_wait_end (struct zr36060 *ptr)
+ 		udelay(1);
+ 		if (i++ > 200000) {	// 200ms, there is for sure something wrong!!!
+ 			dprintk(1,
+-				"%s: timout at wait_end (last status: 0x%02x)\n",
++				"%s: timeout at wait_end (last status: 0x%02x)\n",
+ 				ptr->name, ptr->status);
+ 			break;
+ 		}
 diff --git a/drivers/media/video/zr364xx.c b/drivers/media/video/zr364xx.c
 index 6f18925..1fdbb46 100644
 --- a/drivers/media/video/zr364xx.c
@@ -504997,6 +557008,19 @@
  	.owner = THIS_MODULE,
  	.open = zr364xx_open,
  	.release = zr364xx_release,
+diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
+index 6be1f6b..af9da03 100644
+--- a/drivers/message/fusion/lsi/mpi_log_sas.h
++++ b/drivers/message/fusion/lsi/mpi_log_sas.h
+@@ -162,7 +162,7 @@
+ #define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                 (0x00000400) /* Bits 0-3 encode Transport Status Register (offset 0x08) */
+                                                                           /* Bit 0 is Status Bit 0: FrameXferErr */
+                                                                           /* Bit 1 & 2 are Status Bits 16 and 17: FrameXmitErrStatus */
+-                                                                          /* Bit 3 is Status Bit 18 WriteDataLenghtGTDataLengthErr */
++                                                                          /* Bit 3 is Status Bit 18 WriteDataLengthGTDataLengthErr */
+ 
+ #define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW              (0x00000500)
+ #define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET      (0x00000600)
 diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
 index 52fb216..425f60c 100644
 --- a/drivers/message/fusion/mptbase.c
@@ -505207,6 +557231,46 @@
  extern void	 mpt_free_fw_memory(MPT_ADAPTER *ioc);
  extern int	 mpt_findImVolumes(MPT_ADAPTER *ioc);
  extern int	 mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
+index 6029509..e630b50 100644
+--- a/drivers/message/fusion/mptctl.c
++++ b/drivers/message/fusion/mptctl.c
+@@ -1708,7 +1708,7 @@ mptctl_replace_fw (unsigned long arg)
+  *
+  * Outputs:	None.
+  * Return:	0 if successful
+- *		-EBUSY  if previous command timout and IOC reset is not complete.
++ *		-EBUSY  if previous command timeout and IOC reset is not complete.
+  *		-EFAULT if data unavailable
+  *		-ENODEV if no such device/adapter
+  *		-ETIME	if timer expires
+@@ -1748,7 +1748,7 @@ mptctl_mpt_command (unsigned long arg)
+  *
+  * Outputs:	None.
+  * Return:	0 if successful
+- *		-EBUSY  if previous command timout and IOC reset is not complete.
++ *		-EBUSY  if previous command timeout and IOC reset is not complete.
+  *		-EFAULT if data unavailable
+  *		-ENODEV if no such device/adapter
+  *		-ETIME	if timer expires
+@@ -2316,7 +2316,7 @@ done_free_mem:
+  * Outputs:	None.
+  * Return:	0 if successful
+  *		-EFAULT if data unavailable
+- *		-EBUSY  if previous command timout and IOC reset is not complete.
++ *		-EBUSY  if previous command timeout and IOC reset is not complete.
+  *		-ENODEV if no such device/adapter
+  *		-ETIME	if timer expires
+  *		-ENOMEM if memory allocation error
+@@ -2553,7 +2553,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
+  * Outputs:	None.
+  * Return:	0 if successful
+  *		-EFAULT if data unavailable
+- *		-EBUSY  if previous command timout and IOC reset is not complete.
++ *		-EBUSY  if previous command timeout and IOC reset is not complete.
+  *		-ENODEV if no such device/adapter
+  *		-ETIME	if timer expires
+  *		-ENOMEM if memory allocation error
 diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
 index e4c94f9..f77b329 100644
 --- a/drivers/message/fusion/mptsas.c
@@ -505221,7 +557285,7 @@
  		printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
  		    ioc->name, __FUNCTION__);
 diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
-index 626bb3c..5c614ec 100644
+index 626bb3c..af1de0c 100644
 --- a/drivers/message/fusion/mptscsih.c
 +++ b/drivers/message/fusion/mptscsih.c
 @@ -111,7 +111,7 @@ int 		mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
@@ -505233,6 +557297,15 @@
  
  /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
  /**
+@@ -1736,7 +1736,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i
+  fail_out:
+ 
+ 	/*
+-	 * Free task managment mf, and corresponding tm flags
++	 * Free task management mf, and corresponding tm flags
+ 	 */
+ 	mpt_free_msg_frame(ioc, mf);
+ 	hd->tmPending = 0;
 diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
 index e4ad7a1..a953148 100644
 --- a/drivers/message/i2o/i2o_block.c
@@ -505314,6 +557387,19 @@
  
  	/* only output error code if AdapterStatus is not HBA_SUCCESS */
  	if ((error >> 8) & 0xff)
+diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
+index 7814a06..da715e1 100644
+--- a/drivers/message/i2o/iop.c
++++ b/drivers/message/i2o/iop.c
+@@ -916,7 +916,7 @@ static int i2o_parse_hrt(struct i2o_controller *c)
+  *	status block. The status block could then be accessed through
+  *	c->status_block.
+  *
+- *	Returns 0 on sucess or negative error code on failure.
++ *	Returns 0 on success or negative error code on failure.
+  */
+ int i2o_status_get(struct i2o_controller *c)
+ {
 diff --git a/drivers/mfd/ucb1x00-assabet.c b/drivers/mfd/ucb1x00-assabet.c
 index e325fa7..61aeaf7 100644
 --- a/drivers/mfd/ucb1x00-assabet.c
@@ -505839,6 +557925,19 @@
  #define MMC_I_MASK_ALL          0x00001fff
  #else
  #define MMC_I_MASK_ALL          0x0000007f
+diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
+index c73e96b..90acf57 100644
+--- a/drivers/mtd/devices/doc2000.c
++++ b/drivers/mtd/devices/doc2000.c
+@@ -376,7 +376,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
+ 	 * hardware restriction. */
+ 	if (doc->mfr) {
+ 		if (doc->mfr == mfr && doc->id == id)
+-			return 1;	/* This is another the same the first */
++			return 1;	/* This is the same as the first */
+ 		else
+ 			printk(KERN_WARNING
+ 			       "Flash chip at floor %d, chip %d is different:\n",
 diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
 index 22ed96c..a0cee86 100644
 --- a/drivers/mtd/mtdchar.c
@@ -505870,6 +557969,141 @@
  }
  
  static struct mtd_notifier notifier = {
+diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c
+index e3744eb..dd38011 100644
+--- a/drivers/mtd/nand/autcpu12.c
++++ b/drivers/mtd/nand/autcpu12.c
+@@ -20,7 +20,7 @@
+  *
+  *	02-12-2002 TG	Cleanup of module params
+  *
+- *	02-20-2002 TG	adjusted for different rd/wr adress support
++ *	02-20-2002 TG	adjusted for different rd/wr address support
+  *			added support for read device ready/busy line
+  *			added page_cache
+  *
+@@ -144,7 +144,7 @@ static int __init autcpu12_init(void)
+ 		goto out;
+ 	}
+ 
+-	/* map physical adress */
++	/* map physical address */
+ 	autcpu12_fio_base = ioremap(AUTCPU12_PHYS_SMC, SZ_1K);
+ 	if (!autcpu12_fio_base) {
+ 		printk("Ioremap autcpu12 SmartMedia Card failed\n");
+@@ -227,7 +227,7 @@ static void __exit autcpu12_cleanup(void)
+ 	/* Release resources, unregister device */
+ 	nand_release(autcpu12_mtd);
+ 
+-	/* unmap physical adress */
++	/* unmap physical address */
+ 	iounmap(autcpu12_fio_base);
+ 
+ 	/* Free the MTD device structure */
+diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c
+index 1657ecd..a52f3a7 100644
+--- a/drivers/mtd/nand/bf5xx_nand.c
++++ b/drivers/mtd/nand/bf5xx_nand.c
+@@ -4,7 +4,7 @@
+  *	http://blackfin.uclinux.org/
+  *	Bryan Wu <bryan.wu at analog.com>
+  *
+- * Blackfin BF5xx on-chip NAND flash controler driver
++ * Blackfin BF5xx on-chip NAND flash controller driver
+  *
+  * Derived from drivers/mtd/nand/s3c2410.c
+  * Copyright (c) 2007 Ben Dooks <ben at simtec.co.uk>
+diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
+index 89deff0..19e1594 100644
+--- a/drivers/mtd/nand/cs553x_nand.c
++++ b/drivers/mtd/nand/cs553x_nand.c
+@@ -337,7 +337,7 @@ static void __exit cs553x_cleanup(void)
+ 		nand_release(cs553x_mtd[i]);
+ 		cs553x_mtd[i] = NULL;
+ 
+-		/* unmap physical adress */
++		/* unmap physical address */
+ 		iounmap(mmio_base);
+ 
+ 		/* Free the MTD device structure */
+diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
+index 0146cdc..ba67bbe 100644
+--- a/drivers/mtd/nand/edb7312.c
++++ b/drivers/mtd/nand/edb7312.c
+@@ -125,7 +125,7 @@ static int __init ep7312_init(void)
+ 		return -ENOMEM;
+ 	}
+ 
+-	/* map physical adress */
++	/* map physical address */
+ 	ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
+ 	if (!ep7312_fio_base) {
+ 		printk("ioremap EDB7312 NAND flash failed\n");
+diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
+index e29c1da..ddd4fc0 100644
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -89,7 +89,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
+ 			     struct mtd_oob_ops *ops);
+ 
+ /*
+- * For devices which display every fart in the system on a seperate LED. Is
++ * For devices which display every fart in the system on a separate LED. Is
+  * compiled away when LED support is disabled.
+  */
+ DEFINE_LED_TRIGGER(nand_led_trigger);
+diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c
+index 10490b4..bb885d1 100644
+--- a/drivers/mtd/nand/nandsim.c
++++ b/drivers/mtd/nand/nandsim.c
+@@ -210,7 +210,7 @@ MODULE_PARM_DESC(overridesize,   "Specifies the NAND Flash size overriding the I
+ #define STATE_CMD_RESET        0x0000000C /* reset */
+ #define STATE_CMD_MASK         0x0000000F /* command states mask */
+ 
+-/* After an addres is input, the simulator goes to one of these states */
++/* After an address is input, the simulator goes to one of these states */
+ #define STATE_ADDR_PAGE        0x00000010 /* full (row, column) address is accepted */
+ #define STATE_ADDR_SEC         0x00000020 /* sector address was accepted */
+ #define STATE_ADDR_ZERO        0x00000030 /* one byte zero address was accepted */
+diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
+index 66f76e9..2bd0737 100644
+--- a/drivers/mtd/nand/s3c2410.c
++++ b/drivers/mtd/nand/s3c2410.c
+@@ -8,7 +8,7 @@
+  *
+  * Changelog:
+  *	21-Sep-2004  BJD  Initial version
+- *	23-Sep-2004  BJD  Mulitple device support
++ *	23-Sep-2004  BJD  Multiple device support
+  *	28-Sep-2004  BJD  Fixed ECC placement for Hardware mode
+  *	12-Oct-2004  BJD  Fixed errors in use of platform data
+  *	18-Feb-2005  BJD  Fix sparse errors
+diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
+index 51c7288..033f880 100644
+--- a/drivers/mtd/nand/sharpsl.c
++++ b/drivers/mtd/nand/sharpsl.c
+@@ -165,7 +165,7 @@ static int __init sharpsl_nand_init(void)
+ 		return -ENOMEM;
+ 	}
+ 
+-	/* map physical adress */
++	/* map physical address */
+ 	sharpsl_io_base = ioremap(sharpsl_phys_base, 0x1000);
+ 	if (!sharpsl_io_base) {
+ 		printk("ioremap to access Sharp SL NAND chip failed\n");
+diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
+index 067262e..0513cbc 100644
+--- a/drivers/mtd/nftlmount.c
++++ b/drivers/mtd/nftlmount.c
+@@ -429,7 +429,7 @@ static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_b
+ 	}
+ }
+ 
+-/* calc_chain_lenght: Walk through a Virtual Unit Chain and estimate chain length */
++/* calc_chain_length: Walk through a Virtual Unit Chain and estimate chain length */
+ static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block)
+ {
+ 	unsigned int length = 0, block = first_block;
 diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
 index be71868..7d25368 100644
 --- a/drivers/net/3c501.c
@@ -506424,7 +558658,7 @@
                                          dev->name);
                                  dev->stats.rx_dropped++;
 diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
-index 9af05a2..389980f 100644
+index 9af05a2..7d170cd 100644
 --- a/drivers/net/Kconfig
 +++ b/drivers/net/Kconfig
 @@ -212,7 +212,7 @@ config MII
@@ -506436,7 +558670,37 @@
  	select PHYLIB
  	help
  	  The Atmel MACB ethernet interface is found on many AT32 and AT91
-@@ -912,6 +912,24 @@ config DM9000
+@@ -814,8 +814,8 @@ config ULTRA32
+ 	  will be called smc-ultra32.
+ 
+ config BFIN_MAC
+-	tristate "Blackfin 536/537 on-chip mac support"
+-	depends on NET_ETHERNET && (BF537 || BF536) && (!BF537_PORT_H)
++	tristate "Blackfin 527/536/537 on-chip mac support"
++	depends on NET_ETHERNET && (BF527 || BF537 || BF536) && (!BF537_PORT_H)
+ 	select CRC32
+ 	select MII
+ 	select PHYLIB
+@@ -828,7 +828,7 @@ config BFIN_MAC
+ 
+ config BFIN_MAC_USE_L1
+ 	bool "Use L1 memory for rx/tx packets"
+-	depends on BFIN_MAC && BF537
++	depends on BFIN_MAC && (BF527 || BF537)
+ 	default y
+ 	help
+ 	  To get maximum network performance, you should use L1 memory as rx/tx buffers.
+@@ -855,7 +855,8 @@ config BFIN_RX_DESC_NUM
+ config BFIN_MAC_RMII
+ 	bool "RMII PHY Interface (EXPERIMENTAL)"
+ 	depends on BFIN_MAC && EXPERIMENTAL
+-	default n
++	default y if BFIN527_EZKIT
++	default n if BFIN537_STAMP
+ 	help
+ 	  Use Reduced PHY MII Interface
+ 
+@@ -912,6 +913,23 @@ config DM9000
  	  To compile this driver as a module, choose M here.  The module
  	  will be called dm9000.
  
@@ -506447,8 +558711,7 @@
 +	---help---
 +	  Support for the Microchip EN28J60 ethernet chip.
 +
-+	  To compile this driver as a module, choose M here and read
-+	  <file:Documentation/networking/net-modules.txt>.  The module will be
++	  To compile this driver as a module, choose M here. The module will be
 +	  called enc28j60.
 +
 +config ENC28J60_WRITEVERIFY
@@ -506461,6 +558724,15 @@
  config SMC911X
  	tristate "SMSC LAN911[5678] support"
  	select CRC32
+@@ -1181,7 +1199,7 @@ config NE2_MCA
+ 
+ config IBMLANA
+ 	tristate "IBM LAN Adapter/A support"
+-	depends on MCA && MCA_LEGACY
++	depends on MCA
+ 	---help---
+ 	  This is a Micro Channel Ethernet adapter.  You need to set
+ 	  CONFIG_MCA to use this driver.  It is both available as an in-kernel
 @@ -1584,6 +1602,18 @@ config 8139_OLD_RX_RESET
  	  experience problems, you can enable this option to restore the
  	  old RX-reset behavior.  If unsure, say N.
@@ -506499,7 +558771,7 @@
  config IP1000
  	tristate "IP1000 Gigabit Ethernet support"
  	depends on PCI && EXPERIMENTAL
-@@ -1989,6 +2022,28 @@ config IP1000
+@@ -1989,6 +2022,27 @@ config IP1000
  	  To compile this driver as a module, choose M here: the module
  	  will be called ipg.  This is recommended.
  
@@ -506521,14 +558793,13 @@
 +         More specific information on configuring the driver is in
 +         <file:Documentation/networking/e1000.txt>.
 +
-+         To compile this driver as a module, choose M here and read
-+         <file:Documentation/networking/net-modules.txt>.  The module
++         To compile this driver as a module, choose M here. The module
 +         will be called igb.
 +
  source "drivers/net/ixp2000/Kconfig"
  
  config MYRI_SBUS
-@@ -2301,7 +2356,7 @@ config GELIC_NET
+@@ -2301,7 +2355,7 @@ config GELIC_NET
  
  config GIANFAR
  	tristate "Gianfar Ethernet"
@@ -506537,7 +558808,7 @@
  	select PHYLIB
  	select CRC32
  	help
-@@ -2560,6 +2615,7 @@ config PASEMI_MAC
+@@ -2560,6 +2614,7 @@ config PASEMI_MAC
  	tristate "PA Semi 1/10Gbit MAC"
  	depends on PPC64 && PCI
  	select PHYLIB
@@ -506545,7 +558816,7 @@
  	help
  	  This driver supports the on-chip 1/10Gbit Ethernet controller on
  	  PA Semi's PWRficient line of chips.
-@@ -2585,6 +2641,16 @@ config TEHUTI
+@@ -2585,6 +2640,16 @@ config TEHUTI
  	help
  	  Tehuti Networks 10G Ethernet NIC
  
@@ -506562,7 +558833,7 @@
  endif # NETDEV_10000
  
  source "drivers/net/tokenring/Kconfig"
-@@ -3015,23 +3081,6 @@ config NET_FC
+@@ -3015,23 +3080,6 @@ config NET_FC
  	  adaptor below. You also should have said Y to "SCSI support" and
  	  "SCSI generic support".
  
@@ -506586,6 +558857,15 @@
  config NETCONSOLE
  	tristate "Network console logging support (EXPERIMENTAL)"
  	depends on EXPERIMENTAL
+@@ -3064,6 +3112,7 @@ config VIRTIO_NET
+ 	tristate "Virtio network driver (EXPERIMENTAL)"
+ 	depends on EXPERIMENTAL && VIRTIO
+ 	---help---
+-	  This is the virtual network driver for lguest.  Say Y or M.
++	  This is the virtual network driver for virtio.  It can be used with
++          lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
+ 
+ endif # NETDEVICES
 diff --git a/drivers/net/Makefile b/drivers/net/Makefile
 index 0e5fde4..9fc7794 100644
 --- a/drivers/net/Makefile
@@ -506693,6 +558973,19 @@
  		       "exiting.\n");
  		err = -ENODEV;
  		goto err_disable_pdev;
+diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
+index 25b114a..0ae0d83 100644
+--- a/drivers/net/arm/at91_ether.c
++++ b/drivers/net/arm/at91_ether.c
+@@ -384,7 +384,7 @@ static void reset_phy(struct net_device *dev)
+ 	/* Wait until PHY reset is complete */
+ 	do {
+ 		read_phy(lp->phy_address, MII_BMCR, &bmcr);
+-	} while (!(bmcr && BMCR_RESET));
++	} while (!(bmcr & BMCR_RESET));
+ 
+ 	disable_mdi();
+ 	spin_unlock_irq(&lp->lock);
 diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
 index b032c1b..24d81f9 100644
 --- a/drivers/net/at1700.c
@@ -506709,6 +559002,130 @@
  		goto err_mca;
  	}
  
+diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
+index 7495a9e..194949a 100644
+--- a/drivers/net/ax88796.c
++++ b/drivers/net/ax88796.c
+@@ -137,11 +137,12 @@ static int ax_initial_check(struct net_device *dev)
+ static void ax_reset_8390(struct net_device *dev)
+ {
+ 	struct ei_device *ei_local = netdev_priv(dev);
++	struct ax_device  *ax = to_ax_dev(dev);
+ 	unsigned long reset_start_time = jiffies;
+ 	void __iomem *addr = (void __iomem *)dev->base_addr;
+ 
+ 	if (ei_debug > 1)
+-		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
++		dev_dbg(&ax->dev->dev, "resetting the 8390 t=%ld\n", jiffies);
+ 
+ 	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
+ 
+@@ -151,7 +152,7 @@ static void ax_reset_8390(struct net_device *dev)
+ 	/* This check _should_not_ be necessary, omit eventually. */
+ 	while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
+ 		if (jiffies - reset_start_time > 2*HZ/100) {
+-			printk(KERN_WARNING "%s: %s did not complete.\n",
++			dev_warn(&ax->dev->dev, "%s: %s did not complete.\n",
+ 			       __FUNCTION__, dev->name);
+ 			break;
+ 		}
+@@ -165,13 +166,15 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
+ 			    int ring_page)
+ {
+ 	struct ei_device *ei_local = netdev_priv(dev);
++	struct ax_device  *ax = to_ax_dev(dev);
+ 	void __iomem *nic_base = ei_local->mem;
+ 
+ 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ 	if (ei_status.dmaing) {
+-		printk(KERN_EMERG "%s: DMAing conflict in %s [DMAstat:%d][irqlock:%d].\n",
++		dev_err(&ax->dev->dev, "%s: DMAing conflict in %s "
++			"[DMAstat:%d][irqlock:%d].\n",
+ 			dev->name, __FUNCTION__,
+-		       ei_status.dmaing, ei_status.irqlock);
++			ei_status.dmaing, ei_status.irqlock);
+ 		return;
+ 	}
+ 
+@@ -204,13 +207,16 @@ static void ax_block_input(struct net_device *dev, int count,
+ 			   struct sk_buff *skb, int ring_offset)
+ {
+ 	struct ei_device *ei_local = netdev_priv(dev);
++	struct ax_device  *ax = to_ax_dev(dev);
+ 	void __iomem *nic_base = ei_local->mem;
+ 	char *buf = skb->data;
+ 
+ 	if (ei_status.dmaing) {
+-		printk(KERN_EMERG "%s: DMAing conflict in ax_block_input "
++		dev_err(&ax->dev->dev,
++			"%s: DMAing conflict in %s "
+ 			"[DMAstat:%d][irqlock:%d].\n",
+-			dev->name, ei_status.dmaing, ei_status.irqlock);
++			dev->name, __FUNCTION__,
++			ei_status.dmaing, ei_status.irqlock);
+ 		return;
+ 	}
+ 
+@@ -239,6 +245,7 @@ static void ax_block_output(struct net_device *dev, int count,
+ 			    const unsigned char *buf, const int start_page)
+ {
+ 	struct ei_device *ei_local = netdev_priv(dev);
++	struct ax_device  *ax = to_ax_dev(dev);
+ 	void __iomem *nic_base = ei_local->mem;
+ 	unsigned long dma_start;
+ 
+@@ -251,7 +258,7 @@ static void ax_block_output(struct net_device *dev, int count,
+ 
+ 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+ 	if (ei_status.dmaing) {
+-		printk(KERN_EMERG "%s: DMAing conflict in %s."
++		dev_err(&ax->dev->dev, "%s: DMAing conflict in %s."
+ 			"[DMAstat:%d][irqlock:%d]\n",
+ 			dev->name, __FUNCTION__,
+ 		       ei_status.dmaing, ei_status.irqlock);
+@@ -281,7 +288,8 @@ static void ax_block_output(struct net_device *dev, int count,
+ 
+ 	while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
+ 		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+-			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
++			dev_warn(&ax->dev->dev,
++				 "%s: timeout waiting for Tx RDC.\n", dev->name);
+ 			ax_reset_8390(dev);
+ 			ax_NS8390_init(dev,1);
+ 			break;
+@@ -424,10 +432,11 @@ static void
+ ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
+ {
+ 	struct ei_device *ei = (struct ei_device *) netdev_priv(dev);
++	struct ax_device  *ax = to_ax_dev(dev);
+ 	unsigned long flags;
+ 
+-	printk(KERN_DEBUG "%s: %p, %04x, %04x %04x\n",
+-	       __FUNCTION__, dev, phy_addr, reg, value);
++	dev_dbg(&ax->dev->dev, "%s: %p, %04x, %04x %04x\n",
++		__FUNCTION__, dev, phy_addr, reg, value);
+ 
+       	spin_lock_irqsave(&ei->page_lock, flags);
+ 
+@@ -750,14 +759,11 @@ static int ax_init_dev(struct net_device *dev, int first_init)
+ 	ax_NS8390_init(dev, 0);
+ 
+ 	if (first_init) {
+-		printk("AX88796: %dbit, irq %d, %lx, MAC: ",
+-		       ei_status.word16 ? 16:8, dev->irq, dev->base_addr);
+-
+-		for (i = 0; i < ETHER_ADDR_LEN; i++)
+-			printk("%2.2x%c", dev->dev_addr[i],
+-			       (i < (ETHER_ADDR_LEN-1) ? ':' : ' '));
++		DECLARE_MAC_BUF(mac);
+ 
+-		printk("\n");
++		dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %s\n",
++			 ei_status.word16 ? 16:8, dev->irq, dev->base_addr,
++			 print_mac(mac, dev->dev_addr));
+ 	}
+ 
+ 	ret = register_netdev(dev);
 diff --git a/drivers/net/b44.c b/drivers/net/b44.c
 index 3d247f3..ea2a2b5 100644
 --- a/drivers/net/b44.c
@@ -506820,6 +559237,271 @@
  	return 0;
  }
  
+diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
+index eb97175..c993a32 100644
+--- a/drivers/net/bfin_mac.c
++++ b/drivers/net/bfin_mac.c
+@@ -1,34 +1,11 @@
+ /*
+- * File:	drivers/net/bfin_mac.c
+- * Based on:
+- * Maintainer:
+- * 		Bryan Wu <bryan.wu at analog.com>
++ * Blackfin On-Chip MAC Driver
+  *
+- * Original author:
+- * 		Luke Yang <luke.yang at analog.com>
++ * Copyright 2004-2007 Analog Devices Inc.
+  *
+- * Created:
+- * Description:
++ * Enter bugs at http://blackfin.uclinux.org/
+  *
+- * Modified:
+- *		Copyright 2004-2006 Analog Devices Inc.
+- *
+- * Bugs:	Enter bugs at http://blackfin.uclinux.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, 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 ;  see the file COPYING.
+- * If not, write to the Free Software Foundation,
+- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ * Licensed under the GPL-2 or later.
+  */
+ 
+ #include <linux/init.h>
+@@ -65,7 +42,7 @@
+ #define DRV_NAME	"bfin_mac"
+ #define DRV_VERSION	"1.1"
+ #define DRV_AUTHOR	"Bryan Wu, Luke Yang"
+-#define DRV_DESC	"Blackfin BF53[67] on-chip Ethernet MAC driver"
++#define DRV_DESC	"Blackfin BF53[67] BF527 on-chip Ethernet MAC driver"
+ 
+ MODULE_AUTHOR(DRV_AUTHOR);
+ MODULE_LICENSE("GPL");
+@@ -296,7 +273,7 @@ static void mdio_poll(void)
+ 
+ 	/* poll the STABUSY bit */
+ 	while ((bfin_read_EMAC_STAADD()) & STABUSY) {
+-		mdelay(10);
++		udelay(1);
+ 		if (timeout_cnt-- < 0) {
+ 			printk(KERN_ERR DRV_NAME
+ 			": wait MDC/MDIO transaction to complete timeout\n");
+@@ -412,20 +389,26 @@ static void bf537_adjust_link(struct net_device *dev)
+ 	spin_unlock_irqrestore(&lp->lock, flags);
+ }
+ 
++/* MDC  = 2.5 MHz */
++#define MDC_CLK 2500000
++
+ static int mii_probe(struct net_device *dev)
+ {
+ 	struct bf537mac_local *lp = netdev_priv(dev);
+ 	struct phy_device *phydev = NULL;
+ 	unsigned short sysctl;
+ 	int i;
++	u32 sclk, mdc_div;
+ 
+ 	/* Enable PHY output early */
+ 	if (!(bfin_read_VR_CTL() & PHYCLKOE))
+ 		bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE);
+ 
+-	/* MDC  = 2.5 MHz */
++	sclk = get_sclk();
++	mdc_div = ((sclk / MDC_CLK) / 2) - 1;
++
+ 	sysctl = bfin_read_EMAC_SYSCTL();
+-	sysctl |= SET_MDCDIV(24);
++	sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
+ 	bfin_write_EMAC_SYSCTL(sysctl);
+ 
+ 	/* search for connect PHY device */
+@@ -477,8 +460,10 @@ static int mii_probe(struct net_device *dev)
+ 	lp->phydev = phydev;
+ 
+ 	printk(KERN_INFO "%s: attached PHY driver [%s] "
+-	       "(mii_bus:phy_addr=%s, irq=%d)\n",
+-	       DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
++	       "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)"
++	       "@sclk=%dMHz)\n",
++	       DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq,
++	       MDC_CLK, mdc_div, sclk/1000000);
+ 
+ 	return 0;
+ }
+@@ -551,7 +536,7 @@ static void adjust_tx_list(void)
+ 	 */
+ 	if (current_tx_ptr->next->next == tx_list_head) {
+ 		while (tx_list_head->status.status_word == 0) {
+-			mdelay(10);
++			mdelay(1);
+ 			if (tx_list_head->status.status_word != 0
+ 			    || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) {
+ 				goto adjust_head;
+@@ -666,6 +651,12 @@ static void bf537mac_rx(struct net_device *dev)
+ 	current_rx_ptr->skb = new_skb;
+ 	current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2;
+ 
++	/* Invidate the data cache of skb->data range when it is write back
++	 * cache. It will prevent overwritting the new data from DMA
++	 */
++	blackfin_dcache_invalidate_range((unsigned long)new_skb->head,
++					 (unsigned long)new_skb->end);
++
+ 	len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN);
+ 	skb_put(skb, len);
+ 	blackfin_dcache_invalidate_range((unsigned long)skb->head,
+@@ -767,7 +758,7 @@ static void bf537mac_enable(void)
+ 
+ #if defined(CONFIG_BFIN_MAC_RMII)
+ 	opmode |= RMII; /* For Now only 100MBit are supported */
+-#ifdef CONFIG_BF_REV_0_2
++#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
+ 	opmode |= TE;
+ #endif
+ #endif
+@@ -792,6 +783,39 @@ static void bf537mac_timeout(struct net_device *dev)
+ 	netif_wake_queue(dev);
+ }
+ 
++static void bf537mac_multicast_hash(struct net_device *dev)
++{
++	u32 emac_hashhi, emac_hashlo;
++	struct dev_mc_list *dmi = dev->mc_list;
++	char *addrs;
++	int i;
++	u32 crc;
++
++	emac_hashhi = emac_hashlo = 0;
++
++	for (i = 0; i < dev->mc_count; i++) {
++		addrs = dmi->dmi_addr;
++		dmi = dmi->next;
++
++		/* skip non-multicast addresses */
++		if (!(*addrs & 1))
++			continue;
++
++		crc = ether_crc(ETH_ALEN, addrs);
++		crc >>= 26;
++
++		if (crc & 0x20)
++			emac_hashhi |= 1 << (crc & 0x1f);
++		else
++			emac_hashlo |= 1 << (crc & 0x1f);
++	}
++
++	bfin_write_EMAC_HASHHI(emac_hashhi);
++	bfin_write_EMAC_HASHLO(emac_hashlo);
++
++	return;
++}
++
+ /*
+  * This routine will, depending on the values passed to it,
+  * either make it accept multicast packets, go into
+@@ -807,11 +831,17 @@ static void bf537mac_set_multicast_list(struct net_device *dev)
+ 		sysctl = bfin_read_EMAC_OPMODE();
+ 		sysctl |= RAF;
+ 		bfin_write_EMAC_OPMODE(sysctl);
+-	} else if (dev->flags & IFF_ALLMULTI || dev->mc_count) {
++	} else if (dev->flags & IFF_ALLMULTI) {
+ 		/* accept all multicast */
+ 		sysctl = bfin_read_EMAC_OPMODE();
+ 		sysctl |= PAM;
+ 		bfin_write_EMAC_OPMODE(sysctl);
++	} else if (dev->mc_count) {
++		/* set up multicast hash table */
++		sysctl = bfin_read_EMAC_OPMODE();
++		sysctl |= HM;
++		bfin_write_EMAC_OPMODE(sysctl);
++		bf537mac_multicast_hash(dev);
+ 	} else {
+ 		/* clear promisc or multicast mode */
+ 		sysctl = bfin_read_EMAC_OPMODE();
+@@ -860,10 +890,10 @@ static int bf537mac_open(struct net_device *dev)
+ 		return retval;
+ 
+ 	phy_start(lp->phydev);
++	phy_write(lp->phydev, MII_BMCR, BMCR_RESET);
+ 	setup_system_regs(dev);
+ 	bf537mac_disable();
+ 	bf537mac_enable();
+-
+ 	pr_debug("hardware init finished\n");
+ 	netif_start_queue(dev);
+ 	netif_carrier_on(dev);
+@@ -886,6 +916,7 @@ static int bf537mac_close(struct net_device *dev)
+ 	netif_carrier_off(dev);
+ 
+ 	phy_stop(lp->phydev);
++	phy_write(lp->phydev, MII_BMCR, BMCR_PDOWN);
+ 
+ 	/* clear everything */
+ 	bf537mac_shutdown(dev);
+@@ -970,7 +1001,7 @@ static int __init bf537mac_probe(struct net_device *dev)
+ 	/* register irq handler */
+ 	if (request_irq
+ 	    (IRQ_MAC_RX, bf537mac_interrupt, IRQF_DISABLED | IRQF_SHARED,
+-	     "BFIN537_MAC_RX", dev)) {
++	     "EMAC_RX", dev)) {
+ 		printk(KERN_WARNING DRV_NAME
+ 		       ": Unable to attach BlackFin MAC RX interrupt\n");
+ 		return -EBUSY;
+diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h
+index 5970ea7..f774d5a 100644
+--- a/drivers/net/bfin_mac.h
++++ b/drivers/net/bfin_mac.h
+@@ -1,34 +1,11 @@
+ /*
+- * File:	drivers/net/bfin_mac.c
+- * Based on:
+- * Maintainer:
+- * 		Bryan Wu <bryan.wu at analog.com>
++ * Blackfin On-Chip MAC Driver
+  *
+- * Original author:
+- * 		Luke Yang <luke.yang at analog.com>
++ * Copyright 2004-2007 Analog Devices Inc.
+  *
+- * Created:
+- * Description:
++ * Enter bugs at http://blackfin.uclinux.org/
+  *
+- * Modified:
+- *		Copyright 2004-2006 Analog Devices Inc.
+- *
+- * Bugs:	Enter bugs at http://blackfin.uclinux.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, 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 ;  see the file COPYING.
+- * If not, write to the Free Software Foundation,
+- * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ * Licensed under the GPL-2 or later.
+  */
+ 
+ #define BFIN_MAC_CSUM_OFFLOAD
 diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
 index 4e7b46e..8b552c6 100644
 --- a/drivers/net/bnx2.c
@@ -534222,10 +586904,43 @@
 +#define EXT_PHY_KR_ROM_CODE				0xca19
 +
 diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
-index 49a1982..2039f78 100644
+index 49a1982..0942d82 100644
 --- a/drivers/net/bonding/bond_main.c
 +++ b/drivers/net/bonding/bond_main.c
-@@ -2517,7 +2517,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
+@@ -1464,10 +1464,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
+ 			dev_set_allmulti(slave_dev, 1);
+ 		}
+ 
++		netif_tx_lock_bh(bond_dev);
+ 		/* upload master's mc_list to new slave */
+ 		for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
+ 			dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
+ 		}
++		netif_tx_unlock_bh(bond_dev);
+ 	}
+ 
+ 	if (bond->params.mode == BOND_MODE_8023AD) {
+@@ -1821,7 +1823,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
+ 		}
+ 
+ 		/* flush master's mc_list from slave */
++		netif_tx_lock_bh(bond_dev);
+ 		bond_mc_list_flush(bond_dev, slave_dev);
++		netif_tx_unlock_bh(bond_dev);
+ 	}
+ 
+ 	netdev_set_master(slave_dev, NULL);
+@@ -1942,7 +1946,9 @@ static int bond_release_all(struct net_device *bond_dev)
+ 			}
+ 
+ 			/* flush master's mc_list from slave */
++			netif_tx_lock_bh(bond_dev);
+ 			bond_mc_list_flush(bond_dev, slave_dev);
++			netif_tx_unlock_bh(bond_dev);
+ 		}
+ 
+ 		netdev_set_master(slave_dev, NULL);
+@@ -2517,7 +2523,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
  		fl.fl4_dst = targets[i];
  		fl.fl4_tos = RTO_ONLINK;
  
@@ -534234,6 +586949,239 @@
  		if (rv) {
  			if (net_ratelimit()) {
  				printk(KERN_WARNING DRV_NAME
+@@ -2795,14 +2801,11 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
+ 	}
+ 
+ 	if (do_failover) {
+-		rtnl_lock();
+ 		write_lock_bh(&bond->curr_slave_lock);
+ 
+ 		bond_select_active_slave(bond);
+ 
+ 		write_unlock_bh(&bond->curr_slave_lock);
+-		rtnl_unlock();
+-
+ 	}
+ 
+ re_arm:
+@@ -2859,8 +2862,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
+ 
+ 				slave->link = BOND_LINK_UP;
+ 
+-				rtnl_lock();
+-
+ 				write_lock_bh(&bond->curr_slave_lock);
+ 
+ 				if ((!bond->curr_active_slave) &&
+@@ -2896,7 +2897,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
+ 				}
+ 
+ 				write_unlock_bh(&bond->curr_slave_lock);
+-				rtnl_unlock();
+ 			}
+ 		} else {
+ 			read_lock(&bond->curr_slave_lock);
+@@ -2966,7 +2966,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
+ 			       bond->dev->name,
+ 			       slave->dev->name);
+ 
+-			rtnl_lock();
+ 			write_lock_bh(&bond->curr_slave_lock);
+ 
+ 			bond_select_active_slave(bond);
+@@ -2974,8 +2973,6 @@ void bond_activebackup_arp_mon(struct work_struct *work)
+ 
+ 			write_unlock_bh(&bond->curr_slave_lock);
+ 
+-			rtnl_unlock();
+-
+ 			bond->current_arp_slave = slave;
+ 
+ 			if (slave) {
+@@ -2993,13 +2990,10 @@ void bond_activebackup_arp_mon(struct work_struct *work)
+ 			       bond->primary_slave->dev->name);
+ 
+ 			/* primary is up so switch to it */
+-			rtnl_lock();
+ 			write_lock_bh(&bond->curr_slave_lock);
+ 			bond_change_active_slave(bond, bond->primary_slave);
+ 			write_unlock_bh(&bond->curr_slave_lock);
+ 
+-			rtnl_unlock();
+-
+ 			slave = bond->primary_slave;
+ 			slave->jiffies = jiffies;
+ 		} else {
+@@ -3769,42 +3763,45 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
+ {
+ 	struct bonding *bond = bond_dev->priv;
+ 	struct net_device_stats *stats = &(bond->stats), *sstats;
++	struct net_device_stats local_stats;
+ 	struct slave *slave;
+ 	int i;
+ 
+-	memset(stats, 0, sizeof(struct net_device_stats));
++	memset(&local_stats, 0, sizeof(struct net_device_stats));
+ 
+ 	read_lock_bh(&bond->lock);
+ 
+ 	bond_for_each_slave(bond, slave, i) {
+ 		sstats = slave->dev->get_stats(slave->dev);
+-		stats->rx_packets += sstats->rx_packets;
+-		stats->rx_bytes += sstats->rx_bytes;
+-		stats->rx_errors += sstats->rx_errors;
+-		stats->rx_dropped += sstats->rx_dropped;
++		local_stats.rx_packets += sstats->rx_packets;
++		local_stats.rx_bytes += sstats->rx_bytes;
++		local_stats.rx_errors += sstats->rx_errors;
++		local_stats.rx_dropped += sstats->rx_dropped;
+ 
+-		stats->tx_packets += sstats->tx_packets;
+-		stats->tx_bytes += sstats->tx_bytes;
+-		stats->tx_errors += sstats->tx_errors;
+-		stats->tx_dropped += sstats->tx_dropped;
++		local_stats.tx_packets += sstats->tx_packets;
++		local_stats.tx_bytes += sstats->tx_bytes;
++		local_stats.tx_errors += sstats->tx_errors;
++		local_stats.tx_dropped += sstats->tx_dropped;
+ 
+-		stats->multicast += sstats->multicast;
+-		stats->collisions += sstats->collisions;
++		local_stats.multicast += sstats->multicast;
++		local_stats.collisions += sstats->collisions;
+ 
+-		stats->rx_length_errors += sstats->rx_length_errors;
+-		stats->rx_over_errors += sstats->rx_over_errors;
+-		stats->rx_crc_errors += sstats->rx_crc_errors;
+-		stats->rx_frame_errors += sstats->rx_frame_errors;
+-		stats->rx_fifo_errors += sstats->rx_fifo_errors;
+-		stats->rx_missed_errors += sstats->rx_missed_errors;
++		local_stats.rx_length_errors += sstats->rx_length_errors;
++		local_stats.rx_over_errors += sstats->rx_over_errors;
++		local_stats.rx_crc_errors += sstats->rx_crc_errors;
++		local_stats.rx_frame_errors += sstats->rx_frame_errors;
++		local_stats.rx_fifo_errors += sstats->rx_fifo_errors;
++		local_stats.rx_missed_errors += sstats->rx_missed_errors;
+ 
+-		stats->tx_aborted_errors += sstats->tx_aborted_errors;
+-		stats->tx_carrier_errors += sstats->tx_carrier_errors;
+-		stats->tx_fifo_errors += sstats->tx_fifo_errors;
+-		stats->tx_heartbeat_errors += sstats->tx_heartbeat_errors;
+-		stats->tx_window_errors += sstats->tx_window_errors;
++		local_stats.tx_aborted_errors += sstats->tx_aborted_errors;
++		local_stats.tx_carrier_errors += sstats->tx_carrier_errors;
++		local_stats.tx_fifo_errors += sstats->tx_fifo_errors;
++		local_stats.tx_heartbeat_errors += sstats->tx_heartbeat_errors;
++		local_stats.tx_window_errors += sstats->tx_window_errors;
+ 	}
+ 
++	memcpy(stats, &local_stats, sizeof(struct net_device_stats));
++
+ 	read_unlock_bh(&bond->lock);
+ 
+ 	return stats;
+@@ -3937,8 +3934,6 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
+ 	struct bonding *bond = bond_dev->priv;
+ 	struct dev_mc_list *dmi;
+ 
+-	write_lock_bh(&bond->lock);
+-
+ 	/*
+ 	 * Do promisc before checking multicast_mode
+ 	 */
+@@ -3959,6 +3954,8 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
+ 		bond_set_allmulti(bond, -1);
+ 	}
+ 
++	read_lock(&bond->lock);
++
+ 	bond->flags = bond_dev->flags;
+ 
+ 	/* looking for addresses to add to slaves' mc list */
+@@ -3979,7 +3976,7 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
+ 	bond_mc_list_destroy(bond);
+ 	bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC);
+ 
+-	write_unlock_bh(&bond->lock);
++	read_unlock(&bond->lock);
+ }
+ 
+ /*
+@@ -4526,7 +4523,9 @@ static void bond_free_all(void)
+ 		struct net_device *bond_dev = bond->dev;
+ 
+ 		bond_work_cancel_all(bond);
++		netif_tx_lock_bh(bond_dev);
+ 		bond_mc_list_destroy(bond);
++		netif_tx_unlock_bh(bond_dev);
+ 		/* Release the bonded slaves */
+ 		bond_release_all(bond_dev);
+ 		bond_deinit(bond_dev);
+@@ -4549,14 +4548,19 @@ static void bond_free_all(void)
+ int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl)
+ {
+ 	int mode = -1, i, rv;
+-	char modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };
++	char *p, modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };
+ 
+-	rv = sscanf(buf, "%d", &mode);
+-	if (!rv) {
++	for (p = (char *)buf; *p; p++)
++		if (!(isdigit(*p) || isspace(*p)))
++			break;
++
++	if (*p)
+ 		rv = sscanf(buf, "%20s", modestr);
+-		if (!rv)
+-			return -1;
+-	}
++	else
++		rv = sscanf(buf, "%d", &mode);
++
++	if (!rv)
++		return -1;
+ 
+ 	for (i = 0; tbl[i].modename; i++) {
+ 		if (mode == tbl[i].mode)
+@@ -4883,14 +4887,16 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond
+ 	down_write(&bonding_rwsem);
+ 
+ 	/* Check to see if the bond already exists. */
+-	list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
+-		if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
+-			printk(KERN_ERR DRV_NAME
++	if (name) {
++		list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
++			if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
++				printk(KERN_ERR DRV_NAME
+ 			       ": cannot add bond %s; it already exists\n",
+-			       name);
+-			res = -EPERM;
+-			goto out_rtnl;
+-		}
++				       name);
++				res = -EPERM;
++				goto out_rtnl;
++			}
++	}
+ 
+ 	bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
+ 				ether_setup);
+diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
+index 6d83be4..67ccad6 100644
+--- a/drivers/net/bonding/bonding.h
++++ b/drivers/net/bonding/bonding.h
+@@ -22,8 +22,8 @@
+ #include "bond_3ad.h"
+ #include "bond_alb.h"
+ 
+-#define DRV_VERSION	"3.2.3"
+-#define DRV_RELDATE	"December 6, 2007"
++#define DRV_VERSION	"3.2.4"
++#define DRV_RELDATE	"January 28, 2008"
+ #define DRV_NAME	"bonding"
+ #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
+ 
 diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
 new file mode 100644
 index 0000000..57def0d
@@ -535129,7 +588077,7 @@
  
  static int __init cxgb3_init_module(void)
 diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
-index bd25421..d48c396 100644
+index bd25421..901c824 100644
 --- a/drivers/net/cxgb3/cxgb3_offload.c
 +++ b/drivers/net/cxgb3/cxgb3_offload.c
 @@ -403,8 +403,6 @@ static int cxgb_offload_ctl(struct t3cdev *tdev, unsigned int req, void *data)
@@ -535178,7 +588126,18 @@
  		       "device ignored.\n", __FUNCTION__);
  		return;
  	}
-@@ -1257,6 +1267,7 @@ void __init cxgb3_offload_init(void)
+@@ -1060,9 +1070,7 @@ void *cxgb_alloc_mem(unsigned long size)
+  */
+ void cxgb_free_mem(void *addr)
+ {
+-	unsigned long p = (unsigned long)addr;
+-
+-	if (p >= VMALLOC_START && p < VMALLOC_END)
++	if (is_vmalloc_addr(addr))
+ 		vfree(addr);
+ 	else
+ 		kfree(addr);
+@@ -1257,6 +1265,7 @@ void __init cxgb3_offload_init(void)
  
  	t3_register_cpl_handler(CPL_SMT_WRITE_RPL, do_smt_write_rpl);
  	t3_register_cpl_handler(CPL_L2T_WRITE_RPL, do_l2t_write_rpl);
@@ -535262,6 +588221,19 @@
  		else
  			e->vlan = VLAN_NONE;
  		spin_unlock(&e->lock);
+diff --git a/drivers/net/cxgb3/mc5.c b/drivers/net/cxgb3/mc5.c
+index 84c1ffa..4c4d6e8 100644
+--- a/drivers/net/cxgb3/mc5.c
++++ b/drivers/net/cxgb3/mc5.c
+@@ -452,7 +452,7 @@ void t3_mc5_intr_handler(struct mc5 *mc5)
+ 	t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
+ }
+ 
+-void __devinit t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
++void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
+ {
+ #define K * 1024
+ 
 diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h
 index 6e12bf4..02dbbb3 100644
 --- a/drivers/net/cxgb3/regs.h
@@ -535645,7 +588617,7 @@
  #define V_CIM_OVFL_ERROR(x) ((x) << S_CIM_OVFL_ERROR)
  #define F_CIM_OVFL_ERROR    V_CIM_OVFL_ERROR(1U)
 diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
-index c15e43a..cb684d3 100644
+index c15e43a..9ca8c66 100644
 --- a/drivers/net/cxgb3/sge.c
 +++ b/drivers/net/cxgb3/sge.c
 @@ -91,6 +91,10 @@ struct rx_desc {
@@ -535971,8 +588943,17 @@
  	t3_write_reg(adap, A_SG_HI_DRB_LO_THRSH, 256);
  	t3_write_reg(adap, A_SG_LO_DRB_HI_THRSH, 1000);
  	t3_write_reg(adap, A_SG_LO_DRB_LO_THRSH, 256);
+@@ -2814,7 +2836,7 @@ void t3_sge_init(struct adapter *adap, struct sge_params *p)
+  *	defaults for the assorted SGE parameters, which admins can change until
+  *	they are used to initialize the SGE.
+  */
+-void __devinit t3_sge_prep(struct adapter *adap, struct sge_params *p)
++void t3_sge_prep(struct adapter *adap, struct sge_params *p)
+ {
+ 	int i;
+ 
 diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
-index 522834c..7469935 100644
+index 522834c..a99496a 100644
 --- a/drivers/net/cxgb3/t3_hw.c
 +++ b/drivers/net/cxgb3/t3_hw.c
 @@ -62,7 +62,7 @@ int t3_wait_op_done_val(struct adapter *adapter, int reg, u32 mask,
@@ -536314,6 +589295,24 @@
  	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT1, 0);
  	t3_write_reg(adap, A_TP_TX_MOD_QUEUE_WEIGHT0, 0);
  	t3_write_reg(adap, A_TP_MOD_CHANNEL_WEIGHT, 0);
+@@ -2606,7 +2675,7 @@ void t3_tp_set_max_rxsize(struct adapter *adap, unsigned int size)
+ 		     V_PMMAXXFERLEN0(size) | V_PMMAXXFERLEN1(size));
+ }
+ 
+-static void __devinit init_mtus(unsigned short mtus[])
++static void init_mtus(unsigned short mtus[])
+ {
+ 	/*
+ 	 * See draft-mathis-plpmtud-00.txt for the values.  The min is 88 so
+@@ -2634,7 +2703,7 @@ static void __devinit init_mtus(unsigned short mtus[])
+ /*
+  * Initial congestion control parameters.
+  */
+-static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b)
++static void init_cong_ctrl(unsigned short *a, unsigned short *b)
+ {
+ 	a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
+ 	a[9] = 2;
 @@ -2809,15 +2878,15 @@ static void ulp_config(struct adapter *adap, const struct tp_params *p)
  int t3_set_proto_sram(struct adapter *adap, u8 *data)
  {
@@ -536389,7 +589388,47 @@
  	do {			/* wait for uP to initialize */
  		msleep(20);
  	} while (t3_read_reg(adapter, A_CIM_HOST_ACC_DATA) && --attempts);
-@@ -3387,6 +3467,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
+@@ -3274,8 +3354,7 @@ out_err:
+  *	Determines a card's PCI mode and associated parameters, such as speed
+  *	and width.
+  */
+-static void __devinit get_pci_mode(struct adapter *adapter,
+-				   struct pci_params *p)
++static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
+ {
+ 	static unsigned short speed_map[] = { 33, 66, 100, 133 };
+ 	u32 pci_mode, pcie_cap;
+@@ -3315,8 +3394,7 @@ static void __devinit get_pci_mode(struct adapter *adapter,
+  *	capabilities and default speed/duplex/flow-control/autonegotiation
+  *	settings.
+  */
+-static void __devinit init_link_config(struct link_config *lc,
+-				       unsigned int caps)
++static void init_link_config(struct link_config *lc, unsigned int caps)
+ {
+ 	lc->supported = caps;
+ 	lc->requested_speed = lc->speed = SPEED_INVALID;
+@@ -3339,7 +3417,7 @@ static void __devinit init_link_config(struct link_config *lc,
+  *	Calculates the size of an MC7 memory in bytes from the value of its
+  *	configuration register.
+  */
+-static unsigned int __devinit mc7_calc_size(u32 cfg)
++static unsigned int mc7_calc_size(u32 cfg)
+ {
+ 	unsigned int width = G_WIDTH(cfg);
+ 	unsigned int banks = !!(cfg & F_BKS) + 1;
+@@ -3350,8 +3428,8 @@ static unsigned int __devinit mc7_calc_size(u32 cfg)
+ 	return MBs << 20;
+ }
+ 
+-static void __devinit mc7_prep(struct adapter *adapter, struct mc7 *mc7,
+-			       unsigned int base_addr, const char *name)
++static void mc7_prep(struct adapter *adapter, struct mc7 *mc7,
++		     unsigned int base_addr, const char *name)
+ {
+ 	u32 cfg;
+ 
+@@ -3387,6 +3465,7 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
  	t3_write_reg(adapter, A_T3DBG_GPIO_EN,
  		     ai->gpio_out | F_GPIO0_OEN | F_GPIO0_OUT_VAL);
  	t3_write_reg(adapter, A_MC5_DB_SERVER_INDEX, 0);
@@ -536397,7 +589436,7 @@
  
  	if (adapter->params.rev == 0 || !uses_xaui(adapter))
  		val |= F_ENRGMII;
-@@ -3403,13 +3484,13 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
+@@ -3403,13 +3482,13 @@ void early_hw_init(struct adapter *adapter, const struct adapter_info *ai)
  }
  
  /*
@@ -536413,11 +589452,11 @@
  	    adapter->params.rev < T3_REV_B2 && is_pcie(adapter);
  	uint16_t devid = 0;
  
-@@ -3436,6 +3517,36 @@ static int t3_reset_adapter(struct adapter *adapter)
+@@ -3436,13 +3515,43 @@ static int t3_reset_adapter(struct adapter *adapter)
  	return 0;
  }
  
-+static int __devinit init_parity(struct adapter *adap)
++static int init_parity(struct adapter *adap)
 +{
 +		int i, err, addr;
 +
@@ -536450,7 +589489,16 @@
  /*
   * Initialize adapter SW state for the various HW modules, set initial values
   * for some adapter tunables, take PHYs out of reset, and initialize the MDIO
-@@ -3503,6 +3614,9 @@ int __devinit t3_prep_adapter(struct adapter *adapter,
+  * interface.
+  */
+-int __devinit t3_prep_adapter(struct adapter *adapter,
+-			      const struct adapter_info *ai, int reset)
++int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai,
++		    int reset)
+ {
+ 	int ret;
+ 	unsigned int i, j = 0;
+@@ -3503,6 +3612,9 @@ int __devinit t3_prep_adapter(struct adapter *adapter,
  	}
  
  	early_hw_init(adapter, ai);
@@ -536579,9 +589627,18 @@
  
  /*
 diff --git a/drivers/net/e100.c b/drivers/net/e100.c
-index b87402b..51cf577 100644
+index b87402b..36ba6dc 100644
 --- a/drivers/net/e100.c
 +++ b/drivers/net/e100.c
+@@ -94,7 +94,7 @@
+  * 	enabled.  82557 pads with 7Eh, while the later controllers pad
+  * 	with 00h.
+  *
+- *	IV.  Recieve
++ *	IV.  Receive
+  *
+  *	The Receive Frame Area (RFA) comprises a ring of Receive Frame
+  *	Descriptors (RFD) + data buffer, thus forming the simplified mode
 @@ -106,6 +106,13 @@
   *	the RFD, the RFD must be dma_sync'ed to maintain a consistent
   *	view from software and hardware.
@@ -536596,6 +589653,15 @@
   *	Under typical operation, the  receive unit (RU) is start once,
   *	and the controller happily fills RFDs as frames arrive.  If
   *	replacement RFDs cannot be allocated, or the RU goes non-active,
+@@ -113,7 +120,7 @@
+  *	and Rx indication and re-allocation happen in the same context,
+  *	therefore no locking is required.  A software-generated interrupt
+  *	is generated from the watchdog to recover from a failed allocation
+- *	senario where all Rx resources have been indicated and none re-
++ *	scenario where all Rx resources have been indicated and none re-
+  *	placed.
+  *
+  *	V.   Miscellaneous
 @@ -281,6 +288,7 @@ struct csr {
  };
  
@@ -536766,7 +589832,13 @@
  	e100_eeprom_write(nic, addr_len, nic->eeprom_wc - 1,
  		nic->eeprom[nic->eeprom_wc - 1]);
  
-@@ -952,7 +959,7 @@ static void e100_get_defaults(struct nic *nic)
+@@ -947,12 +954,12 @@ static void e100_get_defaults(struct nic *nic)
+ 	/* Quadwords to DMA into FIFO before starting frame transmit */
+ 	nic->tx_threshold = 0xE0;
+ 
+-	/* no interrupt for every tx completion, delay = 256us if not 557*/
++	/* no interrupt for every tx completion, delay = 256us if not 557 */
+ 	nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
  		((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
  
  	/* Template for a freshly allocated RFD */
@@ -536786,7 +589858,8 @@
  		&s->complete;
  
  	/* Device's stats reporting may take several microseconds to
- 	 * complete, so where always waiting for results of the
+-	 * complete, so where always waiting for results of the
++	 * complete, so we're always waiting for results of the
  	 * previous command. */
  
 -	if(*complete == le32_to_cpu(cuc_dump_reset_complete)) {
@@ -536953,8 +590026,9 @@
 +
  	if(restart_required) {
  		// ack the rnr?
- 		writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
+-		writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
 -		e100_start_receiver(nic, rx_to_start);
++		iowrite8(stat_ack_rnr, &nic->csr->scb.stat_ack);
 +		e100_start_receiver(nic, nic->rx_to_clean);
  		if(work_done)
  			(*work_done)++;
@@ -537005,6 +590079,36 @@
  
  static int e100_get_sset_count(struct net_device *netdev, int sset)
  {
+@@ -2706,7 +2774,7 @@ static void __devexit e100_remove(struct pci_dev *pdev)
+ 		struct nic *nic = netdev_priv(netdev);
+ 		unregister_netdev(netdev);
+ 		e100_free(nic);
+-		iounmap(nic->csr);
++		pci_iounmap(pdev, nic->csr);
+ 		free_netdev(netdev);
+ 		pci_release_regions(pdev);
+ 		pci_disable_device(pdev);
+@@ -2790,17 +2858,17 @@ static void e100_shutdown(struct pci_dev *pdev)
+ /**
+  * e100_io_error_detected - called when PCI error is detected.
+  * @pdev: Pointer to PCI device
+- * @state: The current pci conneection state
++ * @state: The current pci connection state
+  */
+ static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
+ {
+ 	struct net_device *netdev = pci_get_drvdata(pdev);
+ 	struct nic *nic = netdev_priv(netdev);
+ 
+-	/* Similar to calling e100_down(), but avoids adpater I/O. */
++	/* Similar to calling e100_down(), but avoids adapter I/O. */
+ 	netdev->stop(netdev);
+ 
+-	/* Detach; put netif into state similar to hotplug unplug. */
++	/* Detach; put netif into a state similar to hotplug unplug. */
+ 	napi_enable(&nic->napi);
+ 	netif_device_detach(netdev);
+ 	pci_disable_device(pdev);
 diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
 index b83ccce..d876787 100644
 --- a/drivers/net/e1000/e1000_ethtool.c
@@ -537317,7 +590421,7 @@
  
  /* Number of entries in the Multicast Table Array (MTA). */
 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
-index 76c0fa6..8c87940 100644
+index 76c0fa6..7c5b05a 100644
 --- a/drivers/net/e1000/e1000_main.c
 +++ b/drivers/net/e1000/e1000_main.c
 @@ -47,6 +47,12 @@ static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation
@@ -537445,7 +590549,7 @@
  /**
 + *  Dump the eeprom for users having checksum issues
 + **/
-+void e1000_dump_eeprom(struct e1000_adapter *adapter)
++static void e1000_dump_eeprom(struct e1000_adapter *adapter)
 +{
 +	struct net_device *netdev = adapter->netdev;
 +	struct ethtool_eeprom eeprom;
@@ -537793,10 +590897,18 @@
  				  | FLAG_HAS_SWSM_ON_LOAD,
  	.pba			= 20,
 diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
-index b32ed45..f2175ea 100644
+index b32ed45..6232c3e 100644
 --- a/drivers/net/e1000e/defines.h
 +++ b/drivers/net/e1000e/defines.h
-@@ -557,6 +557,7 @@
+@@ -63,6 +63,7 @@
+ #define E1000_WUFC_EX   0x00000004 /* Directed Exact Wakeup Enable */
+ #define E1000_WUFC_MC   0x00000008 /* Directed Multicast Wakeup Enable */
+ #define E1000_WUFC_BC   0x00000010 /* Broadcast Wakeup Enable */
++#define E1000_WUFC_ARP  0x00000020 /* ARP Request Packet Wakeup Enable */
+ 
+ /* Extended Device Control */
+ #define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */
+@@ -557,6 +558,7 @@
  #define NVM_INIT_3GIO_3            0x001A
  #define NVM_INIT_CONTROL3_PORT_A   0x0024
  #define NVM_CFG                    0x0012
@@ -537817,7 +590929,7 @@
  #define FLAG_HAS_STATS_PTC_PRC            (1 << 10)
  #define FLAG_HAS_SMART_POWER_DOWN         (1 << 11)
 diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
-index 87f9da1..6d9c27f 100644
+index 87f9da1..f77a742 100644
 --- a/drivers/net/e1000e/ethtool.c
 +++ b/drivers/net/e1000e/ethtool.c
 @@ -95,15 +95,14 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
@@ -537861,8 +590973,8 @@
 -			return 1;					      \
 -		}							      \
 -	}								      \
-+bool reg_pattern_test_array(struct e1000_adapter *adapter, u64 *data,
-+			    int reg, int offset, u32 mask, u32 write)
++static bool reg_pattern_test_array(struct e1000_adapter *adapter, u64 *data,
++				   int reg, int offset, u32 mask, u32 write)
 +{
 +	int i;
 +	u32 read;
@@ -537933,6 +591045,47 @@
  static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
  {
  	struct e1000_hw *hw = &adapter->hw;
+@@ -1611,7 +1632,8 @@ static void e1000_get_wol(struct net_device *netdev,
+ 		return;
+ 
+ 	wol->supported = WAKE_UCAST | WAKE_MCAST |
+-			 WAKE_BCAST | WAKE_MAGIC;
++	                 WAKE_BCAST | WAKE_MAGIC |
++	                 WAKE_PHY | WAKE_ARP;
+ 
+ 	/* apply any specific unsupported masks here */
+ 	if (adapter->flags & FLAG_NO_WAKE_UCAST) {
+@@ -1630,6 +1652,10 @@ static void e1000_get_wol(struct net_device *netdev,
+ 		wol->wolopts |= WAKE_BCAST;
+ 	if (adapter->wol & E1000_WUFC_MAG)
+ 		wol->wolopts |= WAKE_MAGIC;
++	if (adapter->wol & E1000_WUFC_LNKC)
++		wol->wolopts |= WAKE_PHY;
++	if (adapter->wol & E1000_WUFC_ARP)
++		wol->wolopts |= WAKE_ARP;
+ }
+ 
+ static int e1000_set_wol(struct net_device *netdev,
+@@ -1637,7 +1663,7 @@ static int e1000_set_wol(struct net_device *netdev,
+ {
+ 	struct e1000_adapter *adapter = netdev_priv(netdev);
+ 
+-	if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE))
++	if (wol->wolopts & WAKE_MAGICSECURE)
+ 		return -EOPNOTSUPP;
+ 
+ 	if (!(adapter->flags & FLAG_HAS_WOL))
+@@ -1654,6 +1680,10 @@ static int e1000_set_wol(struct net_device *netdev,
+ 		adapter->wol |= E1000_WUFC_BC;
+ 	if (wol->wolopts & WAKE_MAGIC)
+ 		adapter->wol |= E1000_WUFC_MAG;
++	if (wol->wolopts & WAKE_PHY)
++		adapter->wol |= E1000_WUFC_LNKC;
++	if (wol->wolopts & WAKE_ARP)
++		adapter->wol |= E1000_WUFC_ARP;
+ 
+ 	return 0;
+ }
 diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
 index 6451578..3c5862f 100644
 --- a/drivers/net/e1000e/hw.h
@@ -538194,7 +591347,7 @@
  
  	for (i = 0; i < ETH_ALEN; i++)
 diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
-index 9cc5a6b..0a2cb79 100644
+index 9cc5a6b..f58f017 100644
 --- a/drivers/net/e1000e/netdev.c
 +++ b/drivers/net/e1000e/netdev.c
 @@ -91,7 +91,7 @@ static int e1000_desc_unused(struct e1000_ring *ring)
@@ -538253,7 +591406,7 @@
  	return cleaned;
  }
  
-@@ -935,7 +941,7 @@ static irqreturn_t e1000_intr(int irq, void *data)
+@@ -935,27 +941,25 @@ static irqreturn_t e1000_intr(int irq, void *data)
  static int e1000_request_irq(struct e1000_adapter *adapter)
  {
  	struct net_device *netdev = adapter->netdev;
@@ -538262,16 +591415,33 @@
  	int irq_flags = IRQF_SHARED;
  	int err;
  
-@@ -945,7 +951,7 @@ static int e1000_request_irq(struct e1000_adapter *adapter)
- 		 "Unable to allocate MSI interrupt Error: %d\n", err);
- 	} else {
+-	err = pci_enable_msi(adapter->pdev);
+-	if (err) {
+-		ndev_warn(netdev,
+-		 "Unable to allocate MSI interrupt Error: %d\n", err);
+-	} else {
++	if (!pci_enable_msi(adapter->pdev)) {
  		adapter->flags |= FLAG_MSI_ENABLED;
 -		handler = &e1000_intr_msi;
 +		handler = e1000_intr_msi;
  		irq_flags = 0;
  	}
  
-@@ -2535,10 +2541,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
+ 	err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name,
+ 			  netdev);
+ 	if (err) {
++		ndev_err(netdev,
++		       "Unable to allocate %s interrupt (return: %d)\n",
++			adapter->flags & FLAG_MSI_ENABLED ? "MSI":"INTx",
++			err);
+ 		if (adapter->flags & FLAG_MSI_ENABLED)
+ 			pci_disable_msi(adapter->pdev);
+-		ndev_err(netdev,
+-		       "Unable to allocate interrupt Error: %d\n", err);
+ 	}
+ 
+ 	return err;
+@@ -2535,10 +2539,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
  	}
  
  	/* Fill out the OS statistics structure */
@@ -538282,7 +591452,7 @@
  	adapter->net_stats.multicast = adapter->stats.mprc;
  	adapter->net_stats.collisions = adapter->stats.colc;
  
-@@ -3509,6 +3511,33 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
+@@ -3509,6 +3509,33 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
  	return 0;
  }
  
@@ -538316,7 +591486,7 @@
  #ifdef CONFIG_PM
  static int e1000_resume(struct pci_dev *pdev)
  {
-@@ -3519,6 +3548,7 @@ static int e1000_resume(struct pci_dev *pdev)
+@@ -3519,6 +3546,7 @@ static int e1000_resume(struct pci_dev *pdev)
  
  	pci_set_power_state(pdev, PCI_D0);
  	pci_restore_state(pdev);
@@ -538324,7 +591494,7 @@
  	err = pci_enable_device(pdev);
  	if (err) {
  		dev_err(&pdev->dev,
-@@ -3619,6 +3649,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
+@@ -3619,6 +3647,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
  	struct e1000_adapter *adapter = netdev_priv(netdev);
  	struct e1000_hw *hw = &adapter->hw;
  
@@ -538332,7 +591502,7 @@
  	if (pci_enable_device(pdev)) {
  		dev_err(&pdev->dev,
  			"Cannot re-enable PCI device after reset.\n");
-@@ -3720,6 +3751,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
+@@ -3720,6 +3749,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
  	u16 eeprom_data = 0;
  	u16 eeprom_apme_mask = E1000_EEPROM_APME;
  
@@ -538340,7 +591510,7 @@
  	err = pci_enable_device(pdev);
  	if (err)
  		return err;
-@@ -4056,16 +4088,15 @@ static struct pci_error_handlers e1000_err_handler = {
+@@ -4056,16 +4086,15 @@ static struct pci_error_handlers e1000_err_handler = {
  };
  
  static struct pci_device_id e1000_pci_tbl[] = {
@@ -538360,7 +591530,7 @@
  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 },
  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 },
  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 },
-@@ -4088,8 +4119,6 @@ static struct pci_device_id e1000_pci_tbl[] = {
+@@ -4088,8 +4117,6 @@ static struct pci_device_id e1000_pci_tbl[] = {
  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan },
  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan },
  	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan },
@@ -538604,9 +591774,18 @@
  			*setup_params++ = *eaddrs++;
  			*setup_params++ = *eaddrs++;
 diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
-index 70509ed..d5459a8 100644
+index 70509ed..2eb82ab 100644
 --- a/drivers/net/eexpress.c
 +++ b/drivers/net/eexpress.c
+@@ -9,7 +9,7 @@
+  * Many modifications, and currently maintained, by
+  *  Philip Blundell <philb at gnu.org>
+  * Added the Compaq LTE  Alan Cox <alan at redhat.com>
+- * Added MCA support Adam Fritzler <mid at auk.cx>
++ * Added MCA support Adam Fritzler
+  *
+  * Note - this driver is experimental still - it has problems on faster
+  * machines. Someone needs to sit down and go through it line by line with
 @@ -456,8 +456,9 @@ static int eexp_open(struct net_device *dev)
  	if (!dev->irq || !irqrmap[dev->irq])
  		return -ENXIO;
@@ -538647,6 +591826,920 @@
  
  #if NET_DEBUG > 6
  	printk("%s: leaving eexp_irq()\n", dev->name);
+diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
+index 5f82a46..88fb53e 100644
+--- a/drivers/net/ehea/ehea.h
++++ b/drivers/net/ehea/ehea.h
+@@ -458,4 +458,7 @@ void ehea_set_ethtool_ops(struct net_device *netdev);
+ int ehea_sense_port_attr(struct ehea_port *port);
+ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed);
+ 
++extern u64 ehea_driver_flags;
++extern struct work_struct ehea_rereg_mr_task;
++
+ #endif	/* __EHEA_H__ */
+diff --git a/drivers/net/ehea/ehea_ethtool.c b/drivers/net/ehea/ehea_ethtool.c
+index 679f40e..d768852 100644
+--- a/drivers/net/ehea/ehea_ethtool.c
++++ b/drivers/net/ehea/ehea_ethtool.c
+@@ -40,7 +40,7 @@ static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ 		return ret;
+ 
+ 	if (netif_carrier_ok(dev)) {
+-		switch(port->port_speed) {
++		switch (port->port_speed) {
+ 		case EHEA_SPEED_10M: cmd->speed = SPEED_10; break;
+ 		case EHEA_SPEED_100M: cmd->speed = SPEED_100; break;
+ 		case EHEA_SPEED_1G: cmd->speed = SPEED_1000; break;
+@@ -78,7 +78,7 @@ static int ehea_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ 		goto doit;
+ 	}
+ 
+-	switch(cmd->speed) {
++	switch (cmd->speed) {
+ 	case SPEED_10:
+ 		if (cmd->duplex == DUPLEX_FULL)
+ 			sp = H_SPEED_10M_F;
+diff --git a/drivers/net/ehea/ehea_hw.h b/drivers/net/ehea/ehea_hw.h
+index 1af7ca4..567981b 100644
+--- a/drivers/net/ehea/ehea_hw.h
++++ b/drivers/net/ehea/ehea_hw.h
+@@ -29,10 +29,10 @@
+ #ifndef __EHEA_HW_H__
+ #define __EHEA_HW_H__
+ 
+-#define QPX_SQA_VALUE   EHEA_BMASK_IBM(48,63)
+-#define QPX_RQ1A_VALUE  EHEA_BMASK_IBM(48,63)
+-#define QPX_RQ2A_VALUE  EHEA_BMASK_IBM(48,63)
+-#define QPX_RQ3A_VALUE  EHEA_BMASK_IBM(48,63)
++#define QPX_SQA_VALUE   EHEA_BMASK_IBM(48, 63)
++#define QPX_RQ1A_VALUE  EHEA_BMASK_IBM(48, 63)
++#define QPX_RQ2A_VALUE  EHEA_BMASK_IBM(48, 63)
++#define QPX_RQ3A_VALUE  EHEA_BMASK_IBM(48, 63)
+ 
+ #define QPTEMM_OFFSET(x) offsetof(struct ehea_qptemm, x)
+ 
+diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
+index 869e160..c051c7e 100644
+--- a/drivers/net/ehea/ehea_main.c
++++ b/drivers/net/ehea/ehea_main.c
+@@ -6,9 +6,9 @@
+  *  (C) Copyright IBM Corp. 2006
+  *
+  *  Authors:
+- *       Christoph Raisch <raisch at de.ibm.com>
+- *       Jan-Bernd Themann <themann at de.ibm.com>
+- *       Thomas Klein <tklein at de.ibm.com>
++ *	 Christoph Raisch <raisch at de.ibm.com>
++ *	 Jan-Bernd Themann <themann at de.ibm.com>
++ *	 Thomas Klein <tklein at de.ibm.com>
+  *
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -54,11 +54,11 @@ static int rq1_entries = EHEA_DEF_ENTRIES_RQ1;
+ static int rq2_entries = EHEA_DEF_ENTRIES_RQ2;
+ static int rq3_entries = EHEA_DEF_ENTRIES_RQ3;
+ static int sq_entries = EHEA_DEF_ENTRIES_SQ;
+-static int use_mcs = 0;
+-static int use_lro = 0;
++static int use_mcs;
++static int use_lro;
+ static int lro_max_aggr = EHEA_LRO_MAX_AGGR;
+ static int num_tx_qps = EHEA_NUM_TX_QP;
+-static int prop_carrier_state = 0;
++static int prop_carrier_state;
+ 
+ module_param(msg_level, int, 0);
+ module_param(rq1_entries, int, 0);
+@@ -94,9 +94,9 @@ MODULE_PARM_DESC(lro_max_aggr, " LRO: Max packets to be aggregated. Default = "
+ MODULE_PARM_DESC(use_lro, " Large Receive Offload, 1: enable, 0: disable, "
+ 		 "Default = 0");
+ 
+-static int port_name_cnt = 0;
++static int port_name_cnt;
+ static LIST_HEAD(adapter_list);
+-u64 ehea_driver_flags = 0;
++u64 ehea_driver_flags;
+ struct work_struct ehea_rereg_mr_task;
+ 
+ struct semaphore dlpar_mem_lock;
+@@ -121,12 +121,13 @@ static struct of_platform_driver ehea_driver = {
+ 	.remove = ehea_remove,
+ };
+ 
+-void ehea_dump(void *adr, int len, char *msg) {
++void ehea_dump(void *adr, int len, char *msg)
++{
+ 	int x;
+ 	unsigned char *deb = adr;
+ 	for (x = 0; x < len; x += 16) {
+ 		printk(DRV_NAME " %s adr=%p ofs=%04x %016lx %016lx\n", msg,
+-			  deb, x, *((u64*)&deb[0]), *((u64*)&deb[8]));
++			  deb, x, *((u64 *)&deb[0]), *((u64 *)&deb[8]));
+ 		deb += 16;
+ 	}
+ }
+@@ -518,7 +519,8 @@ static int ehea_proc_rwqes(struct net_device *dev,
+ 		last_wqe_index = wqe_index;
+ 		rmb();
+ 		if (!ehea_check_cqe(cqe, &rq)) {
+-			if (rq == 1) {	/* LL RQ1 */
++			if (rq == 1) {
++				/* LL RQ1 */
+ 				skb = get_skb_by_index_ll(skb_arr_rq1,
+ 							  skb_arr_rq1_len,
+ 							  wqe_index);
+@@ -531,10 +533,11 @@ static int ehea_proc_rwqes(struct net_device *dev,
+ 					if (!skb)
+ 						break;
+ 				}
+-				skb_copy_to_linear_data(skb, ((char*)cqe) + 64,
++				skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
+ 						 cqe->num_bytes_transfered - 4);
+ 				ehea_fill_skb(dev, skb, cqe);
+-			} else if (rq == 2) {  /* RQ2 */
++			} else if (rq == 2) {
++				/* RQ2 */
+ 				skb = get_skb_by_index(skb_arr_rq2,
+ 						       skb_arr_rq2_len, cqe);
+ 				if (unlikely(!skb)) {
+@@ -544,7 +547,8 @@ static int ehea_proc_rwqes(struct net_device *dev,
+ 				}
+ 				ehea_fill_skb(dev, skb, cqe);
+ 				processed_rq2++;
+-			} else {  /* RQ3 */
++			} else {
++				/* RQ3 */
+ 				skb = get_skb_by_index(skb_arr_rq3,
+ 						       skb_arr_rq3_len, cqe);
+ 				if (unlikely(!skb)) {
+@@ -592,7 +596,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
+ 	unsigned long flags;
+ 
+ 	cqe = ehea_poll_cq(send_cq);
+-	while(cqe && (quota > 0)) {
++	while (cqe && (quota > 0)) {
+ 		ehea_inc_cq(send_cq);
+ 
+ 		cqe_counter++;
+@@ -643,7 +647,8 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
+ 
+ static int ehea_poll(struct napi_struct *napi, int budget)
+ {
+-	struct ehea_port_res *pr = container_of(napi, struct ehea_port_res, napi);
++	struct ehea_port_res *pr = container_of(napi, struct ehea_port_res,
++						napi);
+ 	struct net_device *dev = pr->port->netdev;
+ 	struct ehea_cqe *cqe;
+ 	struct ehea_cqe *cqe_skb = NULL;
+@@ -743,8 +748,9 @@ int ehea_sense_port_attr(struct ehea_port *port)
+ 	u64 hret;
+ 	struct hcp_ehea_port_cb0 *cb0;
+ 
+-	cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC);   /* May be called via */
+-	if (!cb0) {                             /* ehea_neq_tasklet() */
++	/* may be called via ehea_neq_tasklet() */
++	cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
++	if (!cb0) {
+ 		ehea_error("no mem for cb0");
+ 		ret = -ENOMEM;
+ 		goto out;
+@@ -762,7 +768,7 @@ int ehea_sense_port_attr(struct ehea_port *port)
+ 	/* MAC address */
+ 	port->mac_addr = cb0->port_mac_addr << 16;
+ 
+-	if (!is_valid_ether_addr((u8*)&port->mac_addr)) {
++	if (!is_valid_ether_addr((u8 *)&port->mac_addr)) {
+ 		ret = -EADDRNOTAVAIL;
+ 		goto out_free;
+ 	}
+@@ -994,7 +1000,7 @@ static void ehea_parse_eqe(struct ehea_adapter *adapter, u64 eqe)
+ 
+ static void ehea_neq_tasklet(unsigned long data)
+ {
+-	struct ehea_adapter *adapter = (struct ehea_adapter*)data;
++	struct ehea_adapter *adapter = (struct ehea_adapter *)data;
+ 	struct ehea_eqe *eqe;
+ 	u64 event_mask;
+ 
+@@ -1204,7 +1210,7 @@ int ehea_rem_smrs(struct ehea_port_res *pr)
+ 
+ static int ehea_init_q_skba(struct ehea_q_skb_arr *q_skba, int max_q_entries)
+ {
+-	int arr_size = sizeof(void*) * max_q_entries;
++	int arr_size = sizeof(void *) * max_q_entries;
+ 
+ 	q_skba->arr = vmalloc(arr_size);
+ 	if (!q_skba->arr)
+@@ -1489,7 +1495,7 @@ static inline void write_swqe2_data(struct sk_buff *skb, struct net_device *dev,
+ 
+ 	nfrags = skb_shinfo(skb)->nr_frags;
+ 	sg1entry = &swqe->u.immdata_desc.sg_entry;
+-	sg_list = (struct ehea_vsgentry*)&swqe->u.immdata_desc.sg_list;
++	sg_list = (struct ehea_vsgentry *)&swqe->u.immdata_desc.sg_list;
+ 	swqe->descriptors = 0;
+ 	sg1entry_contains_frag_data = 0;
+ 
+@@ -1542,7 +1548,7 @@ static int ehea_broadcast_reg_helper(struct ehea_port *port, u32 hcallid)
+ 				     reg_type, port->mac_addr, 0, hcallid);
+ 	if (hret != H_SUCCESS) {
+ 		ehea_error("%sregistering bc address failed (tagged)",
+-                           hcallid == H_REG_BCMC ? "" : "de");
++			   hcallid == H_REG_BCMC ? "" : "de");
+ 		ret = -EIO;
+ 		goto out_herr;
+ 	}
+@@ -1732,7 +1738,7 @@ static void ehea_allmulti(struct net_device *dev, int enable)
+ 		}
+ }
+ 
+-static void ehea_add_multicast_entry(struct ehea_port* port, u8* mc_mac_addr)
++static void ehea_add_multicast_entry(struct ehea_port *port, u8 *mc_mac_addr)
+ {
+ 	struct ehea_mc_list *ehea_mcl_entry;
+ 	u64 hret;
+@@ -1791,11 +1797,10 @@ static void ehea_set_multicast_list(struct net_device *dev)
+ 			goto out;
+ 		}
+ 
+-		for (i = 0, k_mcl_entry = dev->mc_list;
+-		     i < dev->mc_count;
+-		     i++, k_mcl_entry = k_mcl_entry->next) {
++		for (i = 0, k_mcl_entry = dev->mc_list; i < dev->mc_count; i++,
++			     k_mcl_entry = k_mcl_entry->next)
+ 			ehea_add_multicast_entry(port, k_mcl_entry->dmi_addr);
+-		}
++
+ 	}
+ out:
+ 	return;
+@@ -1925,12 +1930,12 @@ static inline int ehea_hash_skb(struct sk_buff *skb, int num_qps)
+ 
+ 	if ((skb->protocol == htons(ETH_P_IP)) &&
+ 	    (ip_hdr(skb)->protocol == IPPROTO_TCP)) {
+-		tcp = (struct tcphdr*)(skb_network_header(skb) + (ip_hdr(skb)->ihl * 4));
++		tcp = (struct tcphdr *)(skb_network_header(skb) +
++					(ip_hdr(skb)->ihl * 4));
+ 		tmp = (tcp->source + (tcp->dest << 16)) % 31;
+ 		tmp += ip_hdr(skb)->daddr % 31;
+ 		return tmp % num_qps;
+-	}
+-	else
++	} else
+ 		return 0;
+ }
+ 
+@@ -2122,7 +2127,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
+ 	u64 hret;
+ 	u16 dummy16 = 0;
+ 	u64 dummy64 = 0;
+-	struct hcp_modify_qp_cb0* cb0;
++	struct hcp_modify_qp_cb0 *cb0;
+ 
+ 	cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ 	if (!cb0) {
+@@ -2248,7 +2253,7 @@ static int ehea_clean_all_portres(struct ehea_port *port)
+ 	int ret = 0;
+ 	int i;
+ 
+-	for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
++	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++)
+ 		ret |= ehea_clean_portres(port, &port->port_res[i]);
+ 
+ 	ret |= ehea_destroy_eq(port->qp_eq);
+@@ -2300,7 +2305,7 @@ static int ehea_up(struct net_device *dev)
+ 		goto out_clean_pr;
+ 	}
+ 
+-	for(i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
++	for (i = 0; i < port->num_def_qps + port->num_add_tx_qps; i++) {
+ 		ret = ehea_activate_qp(port->adapter, port->port_res[i].qp);
+ 		if (ret) {
+ 			ehea_error("activate_qp failed");
+@@ -2308,7 +2313,7 @@ static int ehea_up(struct net_device *dev)
+ 		}
+ 	}
+ 
+-	for(i = 0; i < port->num_def_qps; i++) {
++	for (i = 0; i < port->num_def_qps; i++) {
+ 		ret = ehea_fill_port_res(&port->port_res[i]);
+ 		if (ret) {
+ 			ehea_error("out_free_irqs");
+@@ -2425,7 +2430,7 @@ int ehea_stop_qps(struct net_device *dev)
+ {
+ 	struct ehea_port *port = netdev_priv(dev);
+ 	struct ehea_adapter *adapter = port->adapter;
+-	struct hcp_modify_qp_cb0* cb0;
++	struct hcp_modify_qp_cb0 *cb0;
+ 	int ret = -EIO;
+ 	int dret;
+ 	int i;
+@@ -2490,7 +2495,7 @@ out:
+ 	return ret;
+ }
+ 
+-void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res * pr)
++void ehea_update_rqs(struct ehea_qp *orig_qp, struct ehea_port_res *pr)
+ {
+ 	struct ehea_qp qp = *orig_qp;
+ 	struct ehea_qp_init_attr *init_attr = &qp.init_attr;
+@@ -2530,7 +2535,7 @@ int ehea_restart_qps(struct net_device *dev)
+ 	int ret = 0;
+ 	int i;
+ 
+-	struct hcp_modify_qp_cb0* cb0;
++	struct hcp_modify_qp_cb0 *cb0;
+ 	u64 hret;
+ 	u64 dummy64 = 0;
+ 	u16 dummy16 = 0;
+@@ -2804,34 +2809,6 @@ static void __devinit logical_port_release(struct device *dev)
+ 	of_node_put(port->ofdev.node);
+ }
+ 
+-static int ehea_driver_sysfs_add(struct device *dev,
+-				 struct device_driver *driver)
+-{
+-	int ret;
+-
+-	ret = sysfs_create_link(&driver->kobj, &dev->kobj,
+-				kobject_name(&dev->kobj));
+-	if (ret == 0) {
+-		ret = sysfs_create_link(&dev->kobj, &driver->kobj,
+-					"driver");
+-		if (ret)
+-			sysfs_remove_link(&driver->kobj,
+-					  kobject_name(&dev->kobj));
+-	}
+-	return ret;
+-}
+-
+-static void ehea_driver_sysfs_remove(struct device *dev,
+-				     struct device_driver *driver)
+-{
+-	struct device_driver *drv = driver;
+-
+-	if (drv) {
+-		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+-		sysfs_remove_link(&dev->kobj, "driver");
+-	}
+-}
+-
+ static struct device *ehea_register_port(struct ehea_port *port,
+ 					 struct device_node *dn)
+ {
+@@ -2856,16 +2833,8 @@ static struct device *ehea_register_port(struct ehea_port *port,
+ 		goto out_unreg_of_dev;
+ 	}
+ 
+-	ret = ehea_driver_sysfs_add(&port->ofdev.dev, &ehea_driver.driver);
+-	if (ret) {
+-		ehea_error("failed to register sysfs driver link");
+-		goto out_rem_dev_file;
+-	}
+-
+ 	return &port->ofdev.dev;
+ 
+-out_rem_dev_file:
+-	device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
+ out_unreg_of_dev:
+ 	of_device_unregister(&port->ofdev);
+ out:
+@@ -2874,7 +2843,6 @@ out:
+ 
+ static void ehea_unregister_port(struct ehea_port *port)
+ {
+-	ehea_driver_sysfs_remove(&port->ofdev.dev, &ehea_driver.driver);
+ 	device_remove_file(&port->ofdev.dev, &dev_attr_log_port_id);
+ 	of_device_unregister(&port->ofdev);
+ }
+@@ -3109,7 +3077,7 @@ static ssize_t ehea_probe_port(struct device *dev,
+ 	of_node_put(eth_dn);
+ 
+ 	if (port) {
+-		for (i=0; i < EHEA_MAX_PORTS; i++)
++		for (i = 0; i < EHEA_MAX_PORTS; i++)
+ 			if (!adapter->port[i]) {
+ 				adapter->port[i] = port;
+ 				break;
+@@ -3144,7 +3112,7 @@ static ssize_t ehea_remove_port(struct device *dev,
+ 
+ 		ehea_shutdown_single_port(port);
+ 
+-		for (i=0; i < EHEA_MAX_PORTS; i++)
++		for (i = 0; i < EHEA_MAX_PORTS; i++)
+ 			if (adapter->port[i] == port) {
+ 				adapter->port[i] = NULL;
+ 				break;
+@@ -3313,7 +3281,7 @@ static int ehea_reboot_notifier(struct notifier_block *nb,
+ }
+ 
+ static struct notifier_block ehea_reboot_nb = {
+-        .notifier_call = ehea_reboot_notifier,
++	.notifier_call = ehea_reboot_notifier,
+ };
+ 
+ static int check_module_parm(void)
+diff --git a/drivers/net/ehea/ehea_phyp.c b/drivers/net/ehea/ehea_phyp.c
+index 95c4a7f..156eb63 100644
+--- a/drivers/net/ehea/ehea_phyp.c
++++ b/drivers/net/ehea/ehea_phyp.c
+@@ -6,9 +6,9 @@
+  *  (C) Copyright IBM Corp. 2006
+  *
+  *  Authors:
+- *       Christoph Raisch <raisch at de.ibm.com>
+- *       Jan-Bernd Themann <themann at de.ibm.com>
+- *       Thomas Klein <tklein at de.ibm.com>
++ *	 Christoph Raisch <raisch at de.ibm.com>
++ *	 Jan-Bernd Themann <themann at de.ibm.com>
++ *	 Thomas Klein <tklein at de.ibm.com>
+  *
+  *
+  * This program is free software; you can redistribute it and/or modify
+@@ -38,11 +38,11 @@ static inline u16 get_order_of_qentries(u16 queue_entries)
+ }
+ 
+ /* Defines for H_CALL H_ALLOC_RESOURCE */
+-#define H_ALL_RES_TYPE_QP        1
+-#define H_ALL_RES_TYPE_CQ        2
+-#define H_ALL_RES_TYPE_EQ        3
+-#define H_ALL_RES_TYPE_MR        5
+-#define H_ALL_RES_TYPE_MW        6
++#define H_ALL_RES_TYPE_QP	 1
++#define H_ALL_RES_TYPE_CQ	 2
++#define H_ALL_RES_TYPE_EQ	 3
++#define H_ALL_RES_TYPE_MR	 5
++#define H_ALL_RES_TYPE_MW	 6
+ 
+ static long ehea_plpar_hcall_norets(unsigned long opcode,
+ 				    unsigned long arg1,
+@@ -137,77 +137,77 @@ u64 ehea_h_query_ehea_qp(const u64 adapter_handle, const u8 qp_category,
+ 			 const u64 qp_handle, const u64 sel_mask, void *cb_addr)
+ {
+ 	return ehea_plpar_hcall_norets(H_QUERY_HEA_QP,
+-				       adapter_handle,	        /* R4 */
+-				       qp_category,	        /* R5 */
+-				       qp_handle,               /* R6 */
+-				       sel_mask,                /* R7 */
++				       adapter_handle,		/* R4 */
++				       qp_category,		/* R5 */
++				       qp_handle,		/* R6 */
++				       sel_mask,		/* R7 */
+ 				       virt_to_abs(cb_addr),	/* R8 */
+ 				       0, 0);
+ }
+ 
+ /* input param R5 */
+-#define H_ALL_RES_QP_EQPO         EHEA_BMASK_IBM(9, 11)
+-#define H_ALL_RES_QP_QPP          EHEA_BMASK_IBM(12, 12)
+-#define H_ALL_RES_QP_RQR          EHEA_BMASK_IBM(13, 15)
+-#define H_ALL_RES_QP_EQEG         EHEA_BMASK_IBM(16, 16)
+-#define H_ALL_RES_QP_LL_QP        EHEA_BMASK_IBM(17, 17)
+-#define H_ALL_RES_QP_DMA128       EHEA_BMASK_IBM(19, 19)
+-#define H_ALL_RES_QP_HSM          EHEA_BMASK_IBM(20, 21)
+-#define H_ALL_RES_QP_SIGT         EHEA_BMASK_IBM(22, 23)
+-#define H_ALL_RES_QP_TENURE       EHEA_BMASK_IBM(48, 55)
+-#define H_ALL_RES_QP_RES_TYP      EHEA_BMASK_IBM(56, 63)
++#define H_ALL_RES_QP_EQPO	  EHEA_BMASK_IBM(9, 11)
++#define H_ALL_RES_QP_QPP	  EHEA_BMASK_IBM(12, 12)
++#define H_ALL_RES_QP_RQR	  EHEA_BMASK_IBM(13, 15)
++#define H_ALL_RES_QP_EQEG	  EHEA_BMASK_IBM(16, 16)
++#define H_ALL_RES_QP_LL_QP	  EHEA_BMASK_IBM(17, 17)
++#define H_ALL_RES_QP_DMA128	  EHEA_BMASK_IBM(19, 19)
++#define H_ALL_RES_QP_HSM	  EHEA_BMASK_IBM(20, 21)
++#define H_ALL_RES_QP_SIGT	  EHEA_BMASK_IBM(22, 23)
++#define H_ALL_RES_QP_TENURE	  EHEA_BMASK_IBM(48, 55)
++#define H_ALL_RES_QP_RES_TYP	  EHEA_BMASK_IBM(56, 63)
+ 
+ /* input param R9  */
+-#define H_ALL_RES_QP_TOKEN        EHEA_BMASK_IBM(0, 31)
+-#define H_ALL_RES_QP_PD           EHEA_BMASK_IBM(32,63)
++#define H_ALL_RES_QP_TOKEN	  EHEA_BMASK_IBM(0, 31)
++#define H_ALL_RES_QP_PD		  EHEA_BMASK_IBM(32, 63)
+ 
+ /* input param R10 */
+-#define H_ALL_RES_QP_MAX_SWQE     EHEA_BMASK_IBM(4, 7)
+-#define H_ALL_RES_QP_MAX_R1WQE    EHEA_BMASK_IBM(12, 15)
+-#define H_ALL_RES_QP_MAX_R2WQE    EHEA_BMASK_IBM(20, 23)
+-#define H_ALL_RES_QP_MAX_R3WQE    EHEA_BMASK_IBM(28, 31)
++#define H_ALL_RES_QP_MAX_SWQE	  EHEA_BMASK_IBM(4, 7)
++#define H_ALL_RES_QP_MAX_R1WQE	  EHEA_BMASK_IBM(12, 15)
++#define H_ALL_RES_QP_MAX_R2WQE	  EHEA_BMASK_IBM(20, 23)
++#define H_ALL_RES_QP_MAX_R3WQE	  EHEA_BMASK_IBM(28, 31)
+ /* Max Send Scatter Gather Elements */
+-#define H_ALL_RES_QP_MAX_SSGE     EHEA_BMASK_IBM(37, 39)
+-#define H_ALL_RES_QP_MAX_R1SGE    EHEA_BMASK_IBM(45, 47)
++#define H_ALL_RES_QP_MAX_SSGE	  EHEA_BMASK_IBM(37, 39)
++#define H_ALL_RES_QP_MAX_R1SGE	  EHEA_BMASK_IBM(45, 47)
+ /* Max Receive SG Elements RQ1 */
+-#define H_ALL_RES_QP_MAX_R2SGE    EHEA_BMASK_IBM(53, 55)
+-#define H_ALL_RES_QP_MAX_R3SGE    EHEA_BMASK_IBM(61, 63)
++#define H_ALL_RES_QP_MAX_R2SGE	  EHEA_BMASK_IBM(53, 55)
++#define H_ALL_RES_QP_MAX_R3SGE	  EHEA_BMASK_IBM(61, 63)
+ 
+ /* input param R11 */
+-#define H_ALL_RES_QP_SWQE_IDL     EHEA_BMASK_IBM(0, 7)
++#define H_ALL_RES_QP_SWQE_IDL	  EHEA_BMASK_IBM(0, 7)
+ /* max swqe immediate data length */
+-#define H_ALL_RES_QP_PORT_NUM     EHEA_BMASK_IBM(48, 63)
++#define H_ALL_RES_QP_PORT_NUM	  EHEA_BMASK_IBM(48, 63)
+ 
+ /* input param R12 */
+-#define H_ALL_RES_QP_TH_RQ2       EHEA_BMASK_IBM(0, 15)
++#define H_ALL_RES_QP_TH_RQ2	  EHEA_BMASK_IBM(0, 15)
+ /* Threshold RQ2 */
+-#define H_ALL_RES_QP_TH_RQ3       EHEA_BMASK_IBM(16, 31)
++#define H_ALL_RES_QP_TH_RQ3	  EHEA_BMASK_IBM(16, 31)
+ /* Threshold RQ3 */
+ 
+ /* output param R6 */
+-#define H_ALL_RES_QP_ACT_SWQE     EHEA_BMASK_IBM(0, 15)
+-#define H_ALL_RES_QP_ACT_R1WQE    EHEA_BMASK_IBM(16, 31)
+-#define H_ALL_RES_QP_ACT_R2WQE    EHEA_BMASK_IBM(32, 47)
+-#define H_ALL_RES_QP_ACT_R3WQE    EHEA_BMASK_IBM(48, 63)
++#define H_ALL_RES_QP_ACT_SWQE	  EHEA_BMASK_IBM(0, 15)
++#define H_ALL_RES_QP_ACT_R1WQE	  EHEA_BMASK_IBM(16, 31)
++#define H_ALL_RES_QP_ACT_R2WQE	  EHEA_BMASK_IBM(32, 47)
++#define H_ALL_RES_QP_ACT_R3WQE	  EHEA_BMASK_IBM(48, 63)
+ 
+ /* output param, R7 */
+-#define H_ALL_RES_QP_ACT_SSGE     EHEA_BMASK_IBM(0, 7)
+-#define H_ALL_RES_QP_ACT_R1SGE    EHEA_BMASK_IBM(8, 15)
+-#define H_ALL_RES_QP_ACT_R2SGE    EHEA_BMASK_IBM(16, 23)
+-#define H_ALL_RES_QP_ACT_R3SGE    EHEA_BMASK_IBM(24, 31)
++#define H_ALL_RES_QP_ACT_SSGE	  EHEA_BMASK_IBM(0, 7)
++#define H_ALL_RES_QP_ACT_R1SGE	  EHEA_BMASK_IBM(8, 15)
++#define H_ALL_RES_QP_ACT_R2SGE	  EHEA_BMASK_IBM(16, 23)
++#define H_ALL_RES_QP_ACT_R3SGE	  EHEA_BMASK_IBM(24, 31)
+ #define H_ALL_RES_QP_ACT_SWQE_IDL EHEA_BMASK_IBM(32, 39)
+ 
+ /* output param R8,R9 */
+-#define H_ALL_RES_QP_SIZE_SQ      EHEA_BMASK_IBM(0, 31)
+-#define H_ALL_RES_QP_SIZE_RQ1     EHEA_BMASK_IBM(32, 63)
+-#define H_ALL_RES_QP_SIZE_RQ2     EHEA_BMASK_IBM(0, 31)
+-#define H_ALL_RES_QP_SIZE_RQ3     EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_QP_SIZE_SQ	  EHEA_BMASK_IBM(0, 31)
++#define H_ALL_RES_QP_SIZE_RQ1	  EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_QP_SIZE_RQ2	  EHEA_BMASK_IBM(0, 31)
++#define H_ALL_RES_QP_SIZE_RQ3	  EHEA_BMASK_IBM(32, 63)
+ 
+ /* output param R11,R12 */
+-#define H_ALL_RES_QP_LIOBN_SQ     EHEA_BMASK_IBM(0, 31)
+-#define H_ALL_RES_QP_LIOBN_RQ1    EHEA_BMASK_IBM(32, 63)
+-#define H_ALL_RES_QP_LIOBN_RQ2    EHEA_BMASK_IBM(0, 31)
+-#define H_ALL_RES_QP_LIOBN_RQ3    EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_QP_LIOBN_SQ	  EHEA_BMASK_IBM(0, 31)
++#define H_ALL_RES_QP_LIOBN_RQ1	  EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_QP_LIOBN_RQ2	  EHEA_BMASK_IBM(0, 31)
++#define H_ALL_RES_QP_LIOBN_RQ3	  EHEA_BMASK_IBM(32, 63)
+ 
+ u64 ehea_h_alloc_resource_qp(const u64 adapter_handle,
+ 			     struct ehea_qp_init_attr *init_attr, const u32 pd,
+@@ -334,28 +334,28 @@ u64 ehea_h_alloc_resource_cq(const u64 adapter_handle,
+ }
+ 
+ /* Defines for H_CALL H_ALLOC_RESOURCE */
+-#define H_ALL_RES_TYPE_QP        1
+-#define H_ALL_RES_TYPE_CQ        2
+-#define H_ALL_RES_TYPE_EQ        3
+-#define H_ALL_RES_TYPE_MR        5
+-#define H_ALL_RES_TYPE_MW        6
++#define H_ALL_RES_TYPE_QP	 1
++#define H_ALL_RES_TYPE_CQ	 2
++#define H_ALL_RES_TYPE_EQ	 3
++#define H_ALL_RES_TYPE_MR	 5
++#define H_ALL_RES_TYPE_MW	 6
+ 
+ /*  input param R5 */
+-#define H_ALL_RES_EQ_NEQ             EHEA_BMASK_IBM(0, 0)
++#define H_ALL_RES_EQ_NEQ	     EHEA_BMASK_IBM(0, 0)
+ #define H_ALL_RES_EQ_NON_NEQ_ISN     EHEA_BMASK_IBM(6, 7)
+ #define H_ALL_RES_EQ_INH_EQE_GEN     EHEA_BMASK_IBM(16, 16)
+-#define H_ALL_RES_EQ_RES_TYPE        EHEA_BMASK_IBM(56, 63)
++#define H_ALL_RES_EQ_RES_TYPE	     EHEA_BMASK_IBM(56, 63)
+ /*  input param R6 */
+-#define H_ALL_RES_EQ_MAX_EQE         EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_EQ_MAX_EQE	     EHEA_BMASK_IBM(32, 63)
+ 
+ /*  output param R6 */
+-#define H_ALL_RES_EQ_LIOBN           EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_EQ_LIOBN	     EHEA_BMASK_IBM(32, 63)
+ 
+ /*  output param R7 */
+-#define H_ALL_RES_EQ_ACT_EQE         EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_EQ_ACT_EQE	     EHEA_BMASK_IBM(32, 63)
+ 
+ /*  output param R8 */
+-#define H_ALL_RES_EQ_ACT_PS          EHEA_BMASK_IBM(32, 63)
++#define H_ALL_RES_EQ_ACT_PS	     EHEA_BMASK_IBM(32, 63)
+ 
+ /*  output param R9 */
+ #define H_ALL_RES_EQ_ACT_EQ_IST_C    EHEA_BMASK_IBM(30, 31)
+@@ -453,12 +453,12 @@ u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
+ 
+ 	hret = ehea_plpar_hcall9(H_REGISTER_SMR,
+ 				 outs,
+-				 adapter_handle       ,        	 /* R4 */
+-				 orig_mr_handle,                 /* R5 */
+-				 vaddr_in,                       /* R6 */
+-				 (((u64)access_ctrl) << 32ULL),  /* R7 */
+-				 pd,                             /* R8 */
+-				 0, 0, 0, 0);	   		 /* R9-R12 */
++				 adapter_handle	      ,		 /* R4 */
++				 orig_mr_handle,		 /* R5 */
++				 vaddr_in,			 /* R6 */
++				 (((u64)access_ctrl) << 32ULL),	 /* R7 */
++				 pd,				 /* R8 */
++				 0, 0, 0, 0);			 /* R9-R12 */
+ 
+ 	mr->handle = outs[0];
+ 	mr->lkey = (u32)outs[2];
+@@ -471,11 +471,11 @@ u64 ehea_h_disable_and_get_hea(const u64 adapter_handle, const u64 qp_handle)
+ 	u64 outs[PLPAR_HCALL9_BUFSIZE];
+ 
+ 	return ehea_plpar_hcall9(H_DISABLE_AND_GET_HEA,
+-       				 outs,
++				 outs,
+ 				 adapter_handle,		/* R4 */
+ 				 H_DISABLE_GET_EHEA_WQE_P,	/* R5 */
+ 				 qp_handle,			/* R6 */
+-				 0, 0, 0, 0, 0, 0);             /* R7-R12 */
++				 0, 0, 0, 0, 0, 0);		/* R7-R12 */
+ }
+ 
+ u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle,
+@@ -483,9 +483,9 @@ u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle,
+ {
+ 	return ehea_plpar_hcall_norets(H_FREE_RESOURCE,
+ 				       adapter_handle,	   /* R4 */
+-				       res_handle,         /* R5 */
++				       res_handle,	   /* R5 */
+ 				       force_bit,
+-				       0, 0, 0, 0);        /* R7-R10 */
++				       0, 0, 0, 0);	   /* R7-R10 */
+ }
+ 
+ u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
+@@ -493,13 +493,13 @@ u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
+ 			     const u32 pd, u64 *mr_handle, u32 *lkey)
+ {
+ 	u64 hret;
+- 	u64 outs[PLPAR_HCALL9_BUFSIZE];
++	u64 outs[PLPAR_HCALL9_BUFSIZE];
+ 
+ 	hret = ehea_plpar_hcall9(H_ALLOC_HEA_RESOURCE,
+ 				 outs,
+ 				 adapter_handle,		   /* R4 */
+ 				 5,				   /* R5 */
+-				 vaddr,			           /* R6 */
++				 vaddr,				   /* R6 */
+ 				 length,			   /* R7 */
+ 				 (((u64) access_ctrl) << 32ULL),   /* R8 */
+ 				 pd,				   /* R9 */
+@@ -619,8 +619,8 @@ u64 ehea_h_error_data(const u64 adapter_handle, const u64 ressource_handle,
+ 		      void *rblock)
+ {
+ 	return ehea_plpar_hcall_norets(H_ERROR_DATA,
+-				       adapter_handle,          /* R4 */
+-				       ressource_handle,        /* R5 */
+-				       virt_to_abs(rblock),     /* R6 */
+-				       0, 0, 0, 0);             /* R7-R12 */
++				       adapter_handle,		/* R4 */
++				       ressource_handle,	/* R5 */
++				       virt_to_abs(rblock),	/* R6 */
++				       0, 0, 0, 0);		/* R7-R12 */
+ }
+diff --git a/drivers/net/ehea/ehea_phyp.h b/drivers/net/ehea/ehea_phyp.h
+index faa191d..f3628c8 100644
+--- a/drivers/net/ehea/ehea_phyp.h
++++ b/drivers/net/ehea/ehea_phyp.h
+@@ -93,7 +93,7 @@ static inline void hcp_epas_ctor(struct h_epas *epas, u64 paddr_kernel,
+ static inline void hcp_epas_dtor(struct h_epas *epas)
+ {
+ 	if (epas->kernel.addr)
+-		iounmap((void __iomem*)((u64)epas->kernel.addr & PAGE_MASK));
++		iounmap((void __iomem *)((u64)epas->kernel.addr & PAGE_MASK));
+ 
+ 	epas->user.addr = 0;
+ 	epas->kernel.addr = 0;
+@@ -388,23 +388,23 @@ u64 ehea_h_modify_ehea_qp(const u64 adapter_handle,
+ 			  const u64 qp_handle,
+ 			  const u64 sel_mask,
+ 			  void *cb_addr,
+-			  u64 * inv_attr_id,
+-			  u64 * proc_mask, u16 * out_swr, u16 * out_rwr);
++			  u64 *inv_attr_id,
++			  u64 *proc_mask, u16 *out_swr, u16 *out_rwr);
+ 
+ u64 ehea_h_alloc_resource_eq(const u64 adapter_handle,
+-			     struct ehea_eq_attr *eq_attr, u64 * eq_handle);
++			     struct ehea_eq_attr *eq_attr, u64 *eq_handle);
+ 
+ u64 ehea_h_alloc_resource_cq(const u64 adapter_handle,
+ 			     struct ehea_cq_attr *cq_attr,
+-			     u64 * cq_handle, struct h_epas *epas);
++			     u64 *cq_handle, struct h_epas *epas);
+ 
+ u64 ehea_h_alloc_resource_qp(const u64 adapter_handle,
+ 			     struct ehea_qp_init_attr *init_attr,
+ 			     const u32 pd,
+-			     u64 * qp_handle, struct h_epas *h_epas);
++			     u64 *qp_handle, struct h_epas *h_epas);
+ 
+-#define H_REG_RPAGE_PAGE_SIZE          EHEA_BMASK_IBM(48,55)
+-#define H_REG_RPAGE_QT                 EHEA_BMASK_IBM(62,63)
++#define H_REG_RPAGE_PAGE_SIZE          EHEA_BMASK_IBM(48, 55)
++#define H_REG_RPAGE_QT                 EHEA_BMASK_IBM(62, 63)
+ 
+ u64 ehea_h_register_rpage(const u64 adapter_handle,
+ 			  const u8 pagesize,
+@@ -426,7 +426,7 @@ u64 ehea_h_free_resource(const u64 adapter_handle, const u64 res_handle,
+ 
+ u64 ehea_h_alloc_resource_mr(const u64 adapter_handle, const u64 vaddr,
+ 			     const u64 length, const u32 access_ctrl,
+-			     const u32 pd, u64 * mr_handle, u32 * lkey);
++			     const u32 pd, u64 *mr_handle, u32 *lkey);
+ 
+ u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle,
+ 			     const u8 pagesize, const u8 queue_type,
+@@ -439,8 +439,8 @@ u64 ehea_h_register_smr(const u64 adapter_handle, const u64 orig_mr_handle,
+ u64 ehea_h_query_ehea(const u64 adapter_handle, void *cb_addr);
+ 
+ /* output param R5 */
+-#define H_MEHEAPORT_CAT		EHEA_BMASK_IBM(40,47)
+-#define H_MEHEAPORT_PN		EHEA_BMASK_IBM(48,63)
++#define H_MEHEAPORT_CAT		EHEA_BMASK_IBM(40, 47)
++#define H_MEHEAPORT_PN		EHEA_BMASK_IBM(48, 63)
+ 
+ u64 ehea_h_query_ehea_port(const u64 adapter_handle, const u16 port_num,
+ 			   const u8 cb_cat, const u64 select_mask,
+diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
+index 83b7643..d522e90 100644
+--- a/drivers/net/ehea/ehea_qmr.c
++++ b/drivers/net/ehea/ehea_qmr.c
+@@ -33,8 +33,6 @@
+ 
+ 
+ struct ehea_busmap ehea_bmap = { 0, 0, NULL };
+-extern u64 ehea_driver_flags;
+-extern struct work_struct ehea_rereg_mr_task;
+ 
+ 
+ static void *hw_qpageit_get_inc(struct hw_queue *queue)
+@@ -65,7 +63,7 @@ static int hw_queue_ctor(struct hw_queue *queue, const u32 nr_of_pages,
+ 	}
+ 
+ 	queue->queue_length = nr_of_pages * pagesize;
+-	queue->queue_pages = kmalloc(nr_of_pages * sizeof(void*), GFP_KERNEL);
++	queue->queue_pages = kmalloc(nr_of_pages * sizeof(void *), GFP_KERNEL);
+ 	if (!queue->queue_pages) {
+ 		ehea_error("no mem for queue_pages");
+ 		return -ENOMEM;
+@@ -78,11 +76,11 @@ static int hw_queue_ctor(struct hw_queue *queue, const u32 nr_of_pages,
+ 	 */
+ 	i = 0;
+ 	while (i < nr_of_pages) {
+-		u8 *kpage = (u8*)get_zeroed_page(GFP_KERNEL);
++		u8 *kpage = (u8 *)get_zeroed_page(GFP_KERNEL);
+ 		if (!kpage)
+ 			goto out_nomem;
+ 		for (k = 0; k < pages_per_kpage && i < nr_of_pages; k++) {
+-			(queue->queue_pages)[i] = (struct ehea_page*)kpage;
++			(queue->queue_pages)[i] = (struct ehea_page *)kpage;
+ 			kpage += pagesize;
+ 			i++;
+ 		}
+@@ -235,8 +233,8 @@ int ehea_destroy_cq(struct ehea_cq *cq)
+ 		return 0;
+ 
+ 	hcp_epas_dtor(&cq->epas);
+-
+-	if ((hret = ehea_destroy_cq_res(cq, NORMAL_FREE)) == H_R_STATE) {
++	hret = ehea_destroy_cq_res(cq, NORMAL_FREE);
++	if (hret == H_R_STATE) {
+ 		ehea_error_data(cq->adapter, cq->fw_handle);
+ 		hret = ehea_destroy_cq_res(cq, FORCE_FREE);
+ 	}
+@@ -301,13 +299,13 @@ struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
+ 		if (i == (eq->attr.nr_pages - 1)) {
+ 			/* last page */
+ 			vpage = hw_qpageit_get_inc(&eq->hw_queue);
+-			if ((hret != H_SUCCESS) || (vpage)) {
++			if ((hret != H_SUCCESS) || (vpage))
+ 				goto out_kill_hwq;
+-			}
++
+ 		} else {
+-			if ((hret != H_PAGE_REGISTERED) || (!vpage)) {
++			if ((hret != H_PAGE_REGISTERED) || (!vpage))
+ 				goto out_kill_hwq;
+-			}
++
+ 		}
+ 	}
+ 
+@@ -331,7 +329,7 @@ struct ehea_eqe *ehea_poll_eq(struct ehea_eq *eq)
+ 	unsigned long flags;
+ 
+ 	spin_lock_irqsave(&eq->spinlock, flags);
+-	eqe = (struct ehea_eqe*)hw_eqit_eq_get_inc_valid(&eq->hw_queue);
++	eqe = (struct ehea_eqe *)hw_eqit_eq_get_inc_valid(&eq->hw_queue);
+ 	spin_unlock_irqrestore(&eq->spinlock, flags);
+ 
+ 	return eqe;
+@@ -364,7 +362,8 @@ int ehea_destroy_eq(struct ehea_eq *eq)
+ 
+ 	hcp_epas_dtor(&eq->epas);
+ 
+-	if ((hret = ehea_destroy_eq_res(eq, NORMAL_FREE)) == H_R_STATE) {
++	hret = ehea_destroy_eq_res(eq, NORMAL_FREE);
++	if (hret == H_R_STATE) {
+ 		ehea_error_data(eq->adapter, eq->fw_handle);
+ 		hret = ehea_destroy_eq_res(eq, FORCE_FREE);
+ 	}
+@@ -546,7 +545,8 @@ int ehea_destroy_qp(struct ehea_qp *qp)
+ 
+ 	hcp_epas_dtor(&qp->epas);
+ 
+-	if ((hret = ehea_destroy_qp_res(qp, NORMAL_FREE)) == H_R_STATE) {
++	hret = ehea_destroy_qp_res(qp, NORMAL_FREE);
++	if (hret == H_R_STATE) {
+ 		ehea_error_data(qp->adapter, qp->fw_handle);
+ 		hret = ehea_destroy_qp_res(qp, FORCE_FREE);
+ 	}
+@@ -559,7 +559,7 @@ int ehea_destroy_qp(struct ehea_qp *qp)
+ 	return 0;
+ }
+ 
+-int ehea_create_busmap( void )
++int ehea_create_busmap(void)
+ {
+ 	u64 vaddr = EHEA_BUSMAP_START;
+ 	unsigned long high_section_index = 0;
+@@ -595,7 +595,7 @@ int ehea_create_busmap( void )
+ 	return 0;
+ }
+ 
+-void ehea_destroy_busmap( void )
++void ehea_destroy_busmap(void)
+ {
+ 	vfree(ehea_bmap.vaddr);
+ }
+diff --git a/drivers/net/ehea/ehea_qmr.h b/drivers/net/ehea/ehea_qmr.h
+index bc62d38..0bb6f92 100644
+--- a/drivers/net/ehea/ehea_qmr.h
++++ b/drivers/net/ehea/ehea_qmr.h
+@@ -41,8 +41,8 @@
+ #define EHEA_SECTSIZE          (1UL << 24)
+ #define EHEA_PAGES_PER_SECTION (EHEA_SECTSIZE >> EHEA_PAGESHIFT)
+ 
+-#if (1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE
+-#error eHEA module can't work if kernel sectionsize < ehea sectionsize
++#if ((1UL << SECTION_SIZE_BITS) < EHEA_SECTSIZE)
++#error eHEA module cannot work if kernel sectionsize < ehea sectionsize
+ #endif
+ 
+ /* Some abbreviations used here:
+@@ -188,8 +188,8 @@ struct ehea_eqe {
+ 	u64 entry;
+ };
+ 
+-#define ERROR_DATA_LENGTH  EHEA_BMASK_IBM(52,63)
+-#define ERROR_DATA_TYPE    EHEA_BMASK_IBM(0,7)
++#define ERROR_DATA_LENGTH  EHEA_BMASK_IBM(52, 63)
++#define ERROR_DATA_TYPE    EHEA_BMASK_IBM(0, 7)
+ 
+ static inline void *hw_qeit_calc(struct hw_queue *queue, u64 q_offset)
+ {
+@@ -279,7 +279,7 @@ static inline void *hw_qeit_eq_get_inc(struct hw_queue *queue)
+ static inline void *hw_eqit_eq_get_inc_valid(struct hw_queue *queue)
+ {
+ 	void *retvalue = hw_qeit_get(queue);
+-	u32 qe = *(u8*)retvalue;
++	u32 qe = *(u8 *)retvalue;
+ 	if ((qe >> 7) == (queue->toggle_state & 1))
+ 		hw_qeit_eq_get_inc(queue);
+ 	else
+@@ -364,7 +364,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter, int cqe,
+ 
+ int ehea_destroy_cq(struct ehea_cq *cq);
+ 
+-struct ehea_qp *ehea_create_qp(struct ehea_adapter * adapter, u32 pd,
++struct ehea_qp *ehea_create_qp(struct ehea_adapter *adapter, u32 pd,
+ 			       struct ehea_qp_init_attr *init_attr);
+ 
+ int ehea_destroy_qp(struct ehea_qp *qp);
+@@ -378,8 +378,8 @@ int ehea_rem_mr(struct ehea_mr *mr);
+ 
+ void ehea_error_data(struct ehea_adapter *adapter, u64 res_handle);
+ 
+-int ehea_create_busmap( void );
+-void ehea_destroy_busmap( void );
++int ehea_create_busmap(void);
++void ehea_destroy_busmap(void);
+ u64 ehea_map_vaddr(void *caddr);
+ 
+ #endif	/* __EHEA_QMR_H__ */
 diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
 new file mode 100644
 index 0000000..0809a6a
@@ -540644,10 +594737,62 @@
  
  struct of_platform_driver mpc52xx_fec_mdio_driver = {
 diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
-index f84c752..7667a62 100644
+index f84c752..3634223 100644
 --- a/drivers/net/forcedeth.c
 +++ b/drivers/net/forcedeth.c
-@@ -712,8 +712,8 @@ static const struct nv_ethtool_str nv_etests_str[] = {
+@@ -13,7 +13,7 @@
+  * Copyright (C) 2004 Andrew de Quincey (wol support)
+  * Copyright (C) 2004 Carl-Daniel Hailfinger (invalid MAC handling, insane
+  *		IRQ rate fixes, bigendian fixes, cleanups, verification)
+- * Copyright (c) 2004,5,6 NVIDIA Corporation
++ * Copyright (c) 2004,2005,2006,2007,2008 NVIDIA Corporation
+  *
+  * 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
+@@ -226,7 +226,7 @@ enum {
+ #define NVREG_MISC1_HD		0x02
+ #define NVREG_MISC1_FORCE	0x3b0f3c
+ 
+-	NvRegMacReset = 0x3c,
++	NvRegMacReset = 0x34,
+ #define NVREG_MAC_RESET_ASSERT	0x0F3
+ 	NvRegTransmitterControl = 0x084,
+ #define NVREG_XMITCTL_START	0x01
+@@ -277,7 +277,9 @@ enum {
+ #define NVREG_MCASTADDRA_FORCE	0x01
+ 	NvRegMulticastAddrB = 0xB4,
+ 	NvRegMulticastMaskA = 0xB8,
++#define NVREG_MCASTMASKA_NONE		0xffffffff
+ 	NvRegMulticastMaskB = 0xBC,
++#define NVREG_MCASTMASKB_NONE		0xffff
+ 
+ 	NvRegPhyInterface = 0xC0,
+ #define PHY_RGMII		0x10000000
+@@ -316,8 +318,8 @@ enum {
+ 	NvRegTxRingPhysAddrHigh = 0x148,
+ 	NvRegRxRingPhysAddrHigh = 0x14C,
+ 	NvRegTxPauseFrame = 0x170,
+-#define NVREG_TX_PAUSEFRAME_DISABLE	0x1ff0080
+-#define NVREG_TX_PAUSEFRAME_ENABLE	0x0c00030
++#define NVREG_TX_PAUSEFRAME_DISABLE	0x01ff0080
++#define NVREG_TX_PAUSEFRAME_ENABLE	0x01800010
+ 	NvRegMIIStatus = 0x180,
+ #define NVREG_MIISTAT_ERROR		0x0001
+ #define NVREG_MIISTAT_LINKCHANGE	0x0008
+@@ -471,9 +473,9 @@ union ring_type {
+ #define NV_RX_AVAIL		(1<<31)
+ 
+ #define NV_RX2_CHECKSUMMASK	(0x1C000000)
+-#define NV_RX2_CHECKSUMOK1	(0x10000000)
+-#define NV_RX2_CHECKSUMOK2	(0x14000000)
+-#define NV_RX2_CHECKSUMOK3	(0x18000000)
++#define NV_RX2_CHECKSUM_IP	(0x10000000)
++#define NV_RX2_CHECKSUM_IP_TCP	(0x14000000)
++#define NV_RX2_CHECKSUM_IP_UDP	(0x18000000)
+ #define NV_RX2_DESCRIPTORVALID	(1<<29)
+ #define NV_RX2_SUBSTRACT1	(1<<25)
+ #define NV_RX2_ERROR1		(1<<18)
+@@ -712,8 +714,8 @@ static const struct nv_ethtool_str nv_etests_str[] = {
  };
  
  struct register_test {
@@ -540658,7 +594803,7 @@
  };
  
  static const struct register_test nv_registers_test[] = {
-@@ -929,6 +929,16 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
+@@ -929,6 +931,16 @@ static int reg_delay(struct net_device *dev, int offset, u32 mask, u32 target,
  #define NV_SETUP_RX_RING 0x01
  #define NV_SETUP_TX_RING 0x02
  
@@ -540675,7 +594820,7 @@
  static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
  {
  	struct fe_priv *np = get_nvpriv(dev);
-@@ -936,19 +946,19 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
+@@ -936,19 +948,19 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags)
  
  	if (np->desc_ver == DESC_VER_1 || np->desc_ver == DESC_VER_2) {
  		if (rxtx_flags & NV_SETUP_RX_RING) {
@@ -540701,7 +594846,7 @@
  		}
  	}
  }
-@@ -1571,8 +1581,8 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
+@@ -1571,8 +1583,8 @@ static int nv_alloc_rx_optimized(struct net_device *dev)
  							     skb_tailroom(skb),
  							     PCI_DMA_FROMDEVICE);
  			np->put_rx_ctx->dma_len = skb_tailroom(skb);
@@ -540712,7 +594857,7 @@
  			wmb();
  			np->put_rx.ex->flaglen = cpu_to_le32(np->rx_buf_sz | NV_RX2_AVAIL);
  			if (unlikely(np->put_rx.ex++ == np->last_rx.ex))
-@@ -1937,8 +1947,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
+@@ -1937,8 +1949,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
  		np->put_tx_ctx->dma = pci_map_single(np->pci_dev, skb->data + offset, bcnt,
  						PCI_DMA_TODEVICE);
  		np->put_tx_ctx->dma_len = bcnt;
@@ -540723,7 +594868,7 @@
  		put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
  
  		tx_flags = NV_TX2_VALID;
-@@ -1963,8 +1973,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
+@@ -1963,8 +1975,8 @@ static int nv_start_xmit_optimized(struct sk_buff *skb, struct net_device *dev)
  			np->put_tx_ctx->dma = pci_map_page(np->pci_dev, frag->page, frag->page_offset+offset, bcnt,
  							   PCI_DMA_TODEVICE);
  			np->put_tx_ctx->dma_len = bcnt;
@@ -540734,7 +594879,41 @@
  			put_tx->flaglen = cpu_to_le32((bcnt-1) | tx_flags);
  
  			offset += bcnt;
-@@ -2680,8 +2690,8 @@ static void nv_set_multicast(struct net_device *dev)
+@@ -2365,14 +2377,9 @@ static int nv_rx_process(struct net_device *dev, int limit)
+ 						goto next_pkt;
+ 					}
+ 				}
+-				if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ {
++				if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
++				    ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP))   /*ip and udp */
+ 					skb->ip_summed = CHECKSUM_UNNECESSARY;
+-				} else {
+-					if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
+-					    (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
+-						skb->ip_summed = CHECKSUM_UNNECESSARY;
+-					}
+-				}
+ 			} else {
+ 				dev_kfree_skb(skb);
+ 				goto next_pkt;
+@@ -2464,14 +2471,9 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
+ 				}
+ 			}
+ 
+-			if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK2)/*ip and tcp */ {
++			if (((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_TCP) || /*ip and tcp */
++			    ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUM_IP_UDP))   /*ip and udp */
+ 				skb->ip_summed = CHECKSUM_UNNECESSARY;
+-			} else {
+-				if ((flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK1 ||
+-				    (flags & NV_RX2_CHECKSUMMASK) == NV_RX2_CHECKSUMOK3) {
+-					skb->ip_summed = CHECKSUM_UNNECESSARY;
+-				}
+-			}
+ 
+ 			/* got a valid packet - forward it to the network core */
+ 			skb_put(skb, len);
+@@ -2680,8 +2682,8 @@ static void nv_set_multicast(struct net_device *dev)
  				walk = dev->mc_list;
  				while (walk != NULL) {
  					u32 a, b;
@@ -540745,7 +594924,17 @@
  					alwaysOn[0] &= a;
  					alwaysOff[0] &= ~a;
  					alwaysOn[1] &= b;
-@@ -4539,8 +4549,8 @@ static int nv_loopback_test(struct net_device *dev)
+@@ -2693,6 +2695,9 @@ static void nv_set_multicast(struct net_device *dev)
+ 			addr[1] = alwaysOn[1];
+ 			mask[0] = alwaysOn[0] | alwaysOff[0];
+ 			mask[1] = alwaysOn[1] | alwaysOff[1];
++		} else {
++			mask[0] = NVREG_MCASTMASKA_NONE;
++			mask[1] = NVREG_MCASTMASKB_NONE;
+ 		}
+ 	}
+ 	addr[0] |= NVREG_MCASTADDRA_FORCE;
+@@ -4539,8 +4544,8 @@ static int nv_loopback_test(struct net_device *dev)
  		np->tx_ring.orig[0].buf = cpu_to_le32(test_dma_addr);
  		np->tx_ring.orig[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
  	} else {
@@ -540756,6 +594945,72 @@
  		np->tx_ring.ex[0].flaglen = cpu_to_le32((pkt_len-1) | np->tx_flags | tx_flags_extra);
  	}
  	writel(NVREG_TXRXCTL_KICK|np->txrxctl_bits, get_hwbase(dev) + NvRegTxRxControl);
+@@ -4803,8 +4808,8 @@ static int nv_open(struct net_device *dev)
+ 		nv_mac_reset(dev);
+ 	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
+ 	writel(0, base + NvRegMulticastAddrB);
+-	writel(0, base + NvRegMulticastMaskA);
+-	writel(0, base + NvRegMulticastMaskB);
++	writel(NVREG_MCASTMASKA_NONE, base + NvRegMulticastMaskA);
++	writel(NVREG_MCASTMASKB_NONE, base + NvRegMulticastMaskB);
+ 	writel(0, base + NvRegPacketFilterFlags);
+ 
+ 	writel(0, base + NvRegTransmitterControl);
+@@ -4898,8 +4903,8 @@ static int nv_open(struct net_device *dev)
+ 	spin_lock_irq(&np->lock);
+ 	writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA);
+ 	writel(0, base + NvRegMulticastAddrB);
+-	writel(0, base + NvRegMulticastMaskA);
+-	writel(0, base + NvRegMulticastMaskB);
++	writel(NVREG_MCASTMASKA_NONE, base + NvRegMulticastMaskA);
++	writel(NVREG_MCASTMASKB_NONE, base + NvRegMulticastMaskB);
+ 	writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
+ 	/* One manual link speed update: Interrupts are enabled, future link
+ 	 * speed changes cause interrupts and are handled by nv_link_irq().
+@@ -5593,35 +5598,35 @@ static struct pci_device_id pci_tbl[] = {
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP77 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{	/* MCP79 Ethernet Controller */
+ 		PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39),
+-		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT,
++		.driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR,
+ 	},
+ 	{0,},
+ };
 diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
 index c83bd65..42d94ed 100644
 --- a/drivers/net/fs_enet/fs_enet-main.c
@@ -540985,6 +595240,21 @@
  		return;
  
  	/*
+diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
+index 11b83da..e04bf99 100644
+--- a/drivers/net/hamradio/dmascc.c
++++ b/drivers/net/hamradio/dmascc.c
+@@ -262,8 +262,8 @@ static void tm_isr(struct scc_priv *priv);
+ 
+ static int io[MAX_NUM_DEVS] __initdata = { 0, };
+ 
+-/* Beware! hw[] is also used in cleanup_module(). */
+-static struct scc_hardware hw[NUM_TYPES] __initdata_or_module = HARDWARE;
++/* Beware! hw[] is also used in dmascc_exit(). */
++static struct scc_hardware hw[NUM_TYPES] = HARDWARE;
+ 
+ 
+ /* Global variables */
 diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
 index 803a3bd..cfcd15a 100644
 --- a/drivers/net/hamradio/mkiss.c
@@ -541109,7 +595379,7 @@
  	SET_ETHTOOL_OPS(ndev, &emac_ethtool_ops);
  
 diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
-index 91d83ac..46e2c52 100644
+index 91d83ac..95e3464 100644
 --- a/drivers/net/ibmlana.c
 +++ b/drivers/net/ibmlana.c
 @@ -83,7 +83,7 @@ History:
@@ -541181,12 +595451,12 @@
 +	0x0000
 +};
 +
-+static char *ibmlana_adapter_names[] __initdata = {
++static char *ibmlana_adapter_names[] __devinitdata = {
 +	"IBM LAN Adapter/A",
 +	NULL
 +};
 +
-+static int ibmlana_init_one(struct device *kdev)
++static int __devinit ibmlana_init_one(struct device *kdev)
  {
 -	int slot, z;
 +	struct mca_device *mdev = to_mca_device(kdev);
@@ -551008,10 +605278,10 @@
 +}
 diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
 new file mode 100644
-index 0000000..f3c144d
+index 0000000..d4eb8e2
 --- /dev/null
 +++ b/drivers/net/igb/igb_main.c
-@@ -0,0 +1,4138 @@
+@@ -0,0 +1,4137 @@
 +/*******************************************************************************
 +
 +  Intel(R) Gigabit Ethernet Linux driver
@@ -551452,7 +605722,6 @@
 +	if (adapter->msix_entries) {
 +		err = igb_request_msix(adapter);
 +		if (!err) {
-+			struct e1000_hw *hw = &adapter->hw;
 +			/* enable IAM, auto-mask,
 +			 * DO NOT USE EIAME or IAME in legacy mode */
 +			wr32(E1000_IAM, IMS_ENABLE_MASK);
@@ -556888,6 +611157,26 @@
 - *
 - */
 -module_exit(actisys_cleanup);
+diff --git a/drivers/net/irda/ali-ircc.h b/drivers/net/irda/ali-ircc.h
+index e489c66..0787657 100644
+--- a/drivers/net/irda/ali-ircc.h
++++ b/drivers/net/irda/ali-ircc.h
+@@ -173,13 +173,13 @@ struct st_fifo {
+ 
+ struct frame_cb {
+ 	void *start; /* Start of frame in DMA mem */
+-	int len;     /* Lenght of frame in DMA mem */
++	int len;     /* Length of frame in DMA mem */
+ };
+ 
+ struct tx_fifo {
+ 	struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
+ 	int             ptr;                  /* Currently being sent */
+-	int             len;                  /* Lenght of queue */
++	int             len;                  /* Length of queue */
+ 	int             free;                 /* Next free slot */
+ 	void           *tail;                 /* Next free start in DMA mem */
+ };
 diff --git a/drivers/net/irda/ep7211_ir.c b/drivers/net/irda/ep7211_ir.c
 deleted file mode 100644
 index 4cba38f..0000000
@@ -559436,6 +613725,26 @@
 - *
 - */
 -module_exit(mcp2120_cleanup);
+diff --git a/drivers/net/irda/nsc-ircc.h b/drivers/net/irda/nsc-ircc.h
+index bbdc97f..29398a4 100644
+--- a/drivers/net/irda/nsc-ircc.h
++++ b/drivers/net/irda/nsc-ircc.h
+@@ -231,13 +231,13 @@ struct st_fifo {
+ 
+ struct frame_cb {
+ 	void *start; /* Start of frame in DMA mem */
+-	int len;     /* Lenght of frame in DMA mem */
++	int len;     /* Length of frame in DMA mem */
+ };
+ 
+ struct tx_fifo {
+ 	struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
+ 	int             ptr;                  /* Currently being sent */
+-	int             len;                  /* Lenght of queue */
++	int             len;                  /* Length of queue */
+ 	int             free;                 /* Next free slot */
+ 	void           *tail;                 /* Next free start in DMA mem */
+ };
 diff --git a/drivers/net/irda/old_belkin.c b/drivers/net/irda/old_belkin.c
 deleted file mode 100644
 index 26f81fd..0000000
@@ -559960,6 +614269,26 @@
  	iobase = self->io.fir_base;
  	spin_lock(&self->lock);
  	iHostIntType = GetHostStatus(iobase);
+diff --git a/drivers/net/irda/via-ircc.h b/drivers/net/irda/via-ircc.h
+index 204b1b3..9d012f0 100644
+--- a/drivers/net/irda/via-ircc.h
++++ b/drivers/net/irda/via-ircc.h
+@@ -54,13 +54,13 @@ struct st_fifo {
+ 
+ struct frame_cb {
+ 	void *start;		/* Start of frame in DMA mem */
+-	int len;		/* Lenght of frame in DMA mem */
++	int len;		/* Length of frame in DMA mem */
+ };
+ 
+ struct tx_fifo {
+ 	struct frame_cb queue[MAX_TX_WINDOW + 2];	/* Info about frames in queue */
+ 	int ptr;		/* Currently being sent */
+-	int len;		/* Lenght of queue */
++	int len;		/* Length of queue */
+ 	int free;		/* Next free slot */
+ 	void *tail;		/* Next free start in DMA mem */
+ };
 diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
 index 97bd9dc..419861c 100644
 --- a/drivers/net/iseries_veth.c
@@ -560834,6 +615163,19 @@
  };
  
  struct ixgbe_hw {
+diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
+index c429a50..0c5447d 100644
+--- a/drivers/net/lib8390.c
++++ b/drivers/net/lib8390.c
+@@ -148,7 +148,7 @@ static void __NS8390_init(struct net_device *dev, int startp);
+  *
+  *	"The author (me) didn't use spin_lock_irqsave because the slowness of the
+  *	card means that approach caused horrible problems like losing serial data
+- *	at 38400 baud on some chips. Rememeber many 8390 nics on PCI were ISA
++ *	at 38400 baud on some chips. Remember many 8390 nics on PCI were ISA
+  *	chips with FPGA front ends.
+  *	
+  *	Ok the logic behind the 8390 is very simple:
 diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
 index fa147cd..f2a6e71 100644
 --- a/drivers/net/loopback.c
@@ -560883,6 +615225,47 @@
  out1:
  	nubus_writew(0, dev->base_addr + ADD_PORT);
  out:
+diff --git a/drivers/net/macb.c b/drivers/net/macb.c
+index e10528e..81bf005 100644
+--- a/drivers/net/macb.c
++++ b/drivers/net/macb.c
+@@ -1084,7 +1084,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ 	return phy_mii_ioctl(phydev, if_mii(rq), cmd);
+ }
+ 
+-static int __devinit macb_probe(struct platform_device *pdev)
++static int __init macb_probe(struct platform_device *pdev)
+ {
+ 	struct eth_platform_data *pdata;
+ 	struct resource *regs;
+@@ -1248,7 +1248,7 @@ err_out:
+ 	return err;
+ }
+ 
+-static int __devexit macb_remove(struct platform_device *pdev)
++static int __exit macb_remove(struct platform_device *pdev)
+ {
+ 	struct net_device *dev;
+ 	struct macb *bp;
+@@ -1276,8 +1276,7 @@ static int __devexit macb_remove(struct platform_device *pdev)
+ }
+ 
+ static struct platform_driver macb_driver = {
+-	.probe		= macb_probe,
+-	.remove		= __devexit_p(macb_remove),
++	.remove		= __exit_p(macb_remove),
+ 	.driver		= {
+ 		.name		= "macb",
+ 	},
+@@ -1285,7 +1284,7 @@ static struct platform_driver macb_driver = {
+ 
+ static int __init macb_init(void)
+ {
+-	return platform_driver_register(&macb_driver);
++	return platform_driver_probe(&macb_driver, macb_probe);
+ }
+ 
+ static void __exit macb_exit(void)
 diff --git a/drivers/net/mace.c b/drivers/net/mace.c
 index 95ebe72..451acdc 100644
 --- a/drivers/net/mace.c
@@ -560995,8 +615378,443 @@
  	unregister_netdevice_notifier(&macvlan_notifier_block);
  	return err;
  }
+diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c
+index aafc3ce..6d343ef 100644
+--- a/drivers/net/mipsnet.c
++++ b/drivers/net/mipsnet.c
+@@ -4,8 +4,6 @@
+  * for more details.
+  */
+ 
+-#define DEBUG
+-
+ #include <linux/init.h>
+ #include <linux/io.h>
+ #include <linux/kernel.h>
+@@ -15,11 +13,93 @@
+ #include <linux/platform_device.h>
+ #include <asm/mips-boards/simint.h>
+ 
+-#include "mipsnet.h"		/* actual device IO mapping */
++#define MIPSNET_VERSION "2007-11-17"
++
++/*
++ * Net status/control block as seen by sw in the core.
++ */
++struct mipsnet_regs {
++	/*
++	 * Device info for probing, reads as MIPSNET%d where %d is some
++	 * form of version.
++	 */
++	u64 devId;		/*0x00 */
+ 
+-#define MIPSNET_VERSION "2005-06-20"
++	/*
++	 * read only busy flag.
++	 * Set and cleared by the Net Device to indicate that an rx or a tx
++	 * is in progress.
++	 */
++	u32 busy;		/*0x08 */
+ 
+-#define mipsnet_reg_address(dev, field) (dev->base_addr + field_offset(field))
++	/*
++	 * Set by the Net Device.
++	 * The device will set it once data has been received.
++	 * The value is the number of bytes that should be read from
++	 * rxDataBuffer.  The value will decrease till 0 until all the data
++	 * from rxDataBuffer has been read.
++	 */
++	u32 rxDataCount;	/*0x0c */
++#define MIPSNET_MAX_RXTX_DATACOUNT (1 << 16)
++
++	/*
++	 * Settable from the MIPS core, cleared by the Net Device.
++	 * The core should set the number of bytes it wants to send,
++	 * then it should write those bytes of data to txDataBuffer.
++	 * The device will clear txDataCount has been processed (not
++	 * necessarily sent).
++	 */
++	u32 txDataCount;	/*0x10 */
++
++	/*
++	 * Interrupt control
++	 *
++	 * Used to clear the interrupted generated by this dev.
++	 * Write a 1 to clear the interrupt. (except bit31).
++	 *
++	 * Bit0 is set if it was a tx-done interrupt.
++	 * Bit1 is set when new rx-data is available.
++	 *    Until this bit is cleared there will be no other RXs.
++	 *
++	 * Bit31 is used for testing, it clears after a read.
++	 *    Writing 1 to this bit will cause an interrupt to be generated.
++	 *    To clear the test interrupt, write 0 to this register.
++	 */
++	u32 interruptControl;	/*0x14 */
++#define MIPSNET_INTCTL_TXDONE     (1u << 0)
++#define MIPSNET_INTCTL_RXDONE     (1u << 1)
++#define MIPSNET_INTCTL_TESTBIT    (1u << 31)
++
++	/*
++	 * Readonly core-specific interrupt info for the device to signal
++	 * the core. The meaning of the contents of this field might change.
++	 */
++	/* XXX: the whole memIntf interrupt scheme is messy: the device
++	 * should have no control what so ever of what VPE/register set is
++	 * being used.
++	 * The MemIntf should only expose interrupt lines, and something in
++	 * the config should be responsible for the line<->core/vpe bindings.
++	 */
++	u32 interruptInfo;	/*0x18 */
++
++	/*
++	 * This is where the received data is read out.
++	 * There is more data to read until rxDataReady is 0.
++	 * Only 1 byte at this regs offset is used.
++	 */
++	u32 rxDataBuffer;	/*0x1c */
++
++	/*
++	 * This is where the data to transmit is written.
++	 * Data should be written for the amount specified in the
++	 * txDataCount register.
++	 * Only 1 byte at this regs offset is used.
++	 */
++	u32 txDataBuffer;	/*0x20 */
++};
++
++#define regaddr(dev, field) \
++  (dev->base_addr + offsetof(struct mipsnet_regs, field))
+ 
+ static char mipsnet_string[] = "mipsnet";
+ 
+@@ -29,32 +109,27 @@ static char mipsnet_string[] = "mipsnet";
+ static int ioiocpy_frommipsnet(struct net_device *dev, unsigned char *kdata,
+ 			int len)
+ {
+-	uint32_t available_len = inl(mipsnet_reg_address(dev, rxDataCount));
+-
+-	if (available_len < len)
+-		return -EFAULT;
+-
+ 	for (; len > 0; len--, kdata++)
+-		*kdata = inb(mipsnet_reg_address(dev, rxDataBuffer));
++		*kdata = inb(regaddr(dev, rxDataBuffer));
+ 
+-	return inl(mipsnet_reg_address(dev, rxDataCount));
++	return inl(regaddr(dev, rxDataCount));
+ }
+ 
+-static inline ssize_t mipsnet_put_todevice(struct net_device *dev,
++static inline void mipsnet_put_todevice(struct net_device *dev,
+ 	struct sk_buff *skb)
+ {
+ 	int count_to_go = skb->len;
+ 	char *buf_ptr = skb->data;
+ 
+-	outl(skb->len, mipsnet_reg_address(dev, txDataCount));
++	outl(skb->len, regaddr(dev, txDataCount));
+ 
+ 	for (; count_to_go; buf_ptr++, count_to_go--)
+-		outb(*buf_ptr, mipsnet_reg_address(dev, txDataBuffer));
++		outb(*buf_ptr, regaddr(dev, txDataBuffer));
+ 
+ 	dev->stats.tx_packets++;
+ 	dev->stats.tx_bytes += skb->len;
+ 
+-	return skb->len;
++	dev_kfree_skb(skb);
+ }
+ 
+ static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -69,18 +144,20 @@ static int mipsnet_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	return 0;
+ }
+ 
+-static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
++static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t len)
+ {
+ 	struct sk_buff *skb;
+-	size_t len = count;
+ 
+-	skb = alloc_skb(len + 2, GFP_KERNEL);
++	if (!len)
++		return len;
++
++	skb = dev_alloc_skb(len + NET_IP_ALIGN);
+ 	if (!skb) {
+ 		dev->stats.rx_dropped++;
+ 		return -ENOMEM;
+ 	}
+ 
+-	skb_reserve(skb, 2);
++	skb_reserve(skb, NET_IP_ALIGN);
+ 	if (ioiocpy_frommipsnet(dev, skb_put(skb, len), len))
+ 		return -EFAULT;
+ 
+@@ -92,50 +169,42 @@ static inline ssize_t mipsnet_get_fromdev(struct net_device *dev, size_t count)
+ 	dev->stats.rx_packets++;
+ 	dev->stats.rx_bytes += len;
+ 
+-	return count;
++	return len;
+ }
+ 
+ static irqreturn_t mipsnet_interrupt(int irq, void *dev_id)
+ {
+ 	struct net_device *dev = dev_id;
+-
+-	irqreturn_t retval = IRQ_NONE;
+-	uint64_t interruptFlags;
+-
+-	if (irq == dev->irq) {
+-		retval = IRQ_HANDLED;
+-
+-		interruptFlags =
+-		    inl(mipsnet_reg_address(dev, interruptControl));
+-
+-		if (interruptFlags & MIPSNET_INTCTL_TXDONE) {
+-			outl(MIPSNET_INTCTL_TXDONE,
+-			     mipsnet_reg_address(dev, interruptControl));
+-			/* only one packet at a time, we are done. */
+-			netif_wake_queue(dev);
+-		} else if (interruptFlags & MIPSNET_INTCTL_RXDONE) {
+-			mipsnet_get_fromdev(dev,
+-				    inl(mipsnet_reg_address(dev, rxDataCount)));
+-			outl(MIPSNET_INTCTL_RXDONE,
+-			     mipsnet_reg_address(dev, interruptControl));
+-
+-		} else if (interruptFlags & MIPSNET_INTCTL_TESTBIT) {
+-			/*
+-			 * TESTBIT is cleared on read.
+-			 * And takes effect after a write with 0
+-			 */
+-			outl(0, mipsnet_reg_address(dev, interruptControl));
+-		} else {
+-			/* Maybe shared IRQ, just ignore, no clearing. */
+-			retval = IRQ_NONE;
+-		}
+-
+-	} else {
+-		printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
+-		       dev->name, __FUNCTION__, irq);
+-		retval = IRQ_NONE;
++	u32 int_flags;
++	irqreturn_t ret = IRQ_NONE;
++
++	if (irq != dev->irq)
++		goto out_badirq;
++
++	/* TESTBIT is cleared on read. */
++	int_flags = inl(regaddr(dev, interruptControl));
++	if (int_flags & MIPSNET_INTCTL_TESTBIT) {
++		/* TESTBIT takes effect after a write with 0. */
++		outl(0, regaddr(dev, interruptControl));
++		ret = IRQ_HANDLED;
++	} else if (int_flags & MIPSNET_INTCTL_TXDONE) {
++		/* Only one packet at a time, we are done. */
++		dev->stats.tx_packets++;
++		netif_wake_queue(dev);
++		outl(MIPSNET_INTCTL_TXDONE,
++		     regaddr(dev, interruptControl));
++		ret = IRQ_HANDLED;
++	} else if (int_flags & MIPSNET_INTCTL_RXDONE) {
++		mipsnet_get_fromdev(dev, inl(regaddr(dev, rxDataCount)));
++		outl(MIPSNET_INTCTL_RXDONE, regaddr(dev, interruptControl));
++		ret = IRQ_HANDLED;
+ 	}
+-	return retval;
++	return ret;
++
++out_badirq:
++	printk(KERN_INFO "%s: %s(): irq %d for unknown device\n",
++	       dev->name, __FUNCTION__, irq);
++	return ret;
+ }
+ 
+ static int mipsnet_open(struct net_device *dev)
+@@ -144,18 +213,15 @@ static int mipsnet_open(struct net_device *dev)
+ 
+ 	err = request_irq(dev->irq, &mipsnet_interrupt,
+ 			  IRQF_SHARED, dev->name, (void *) dev);
+-
+ 	if (err) {
+-		release_region(dev->base_addr, MIPSNET_IO_EXTENT);
++		release_region(dev->base_addr, sizeof(struct mipsnet_regs));
+ 		return err;
+ 	}
+ 
+ 	netif_start_queue(dev);
+ 
+ 	/* test interrupt handler */
+-	outl(MIPSNET_INTCTL_TESTBIT,
+-	     mipsnet_reg_address(dev, interruptControl));
+-
++	outl(MIPSNET_INTCTL_TESTBIT, regaddr(dev, interruptControl));
+ 
+ 	return 0;
+ }
+@@ -163,7 +229,7 @@ static int mipsnet_open(struct net_device *dev)
+ static int mipsnet_close(struct net_device *dev)
+ {
+ 	netif_stop_queue(dev);
+-
++	free_irq(dev->irq, dev);
+ 	return 0;
+ }
+ 
+@@ -194,10 +260,11 @@ static int __init mipsnet_probe(struct device *dev)
+ 	 */
+ 	netdev->base_addr = 0x4200;
+ 	netdev->irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB0 +
+-		      inl(mipsnet_reg_address(netdev, interruptInfo));
++		      inl(regaddr(netdev, interruptInfo));
+ 
+ 	/* Get the io region now, get irq on open() */
+-	if (!request_region(netdev->base_addr, MIPSNET_IO_EXTENT, "mipsnet")) {
++	if (!request_region(netdev->base_addr, sizeof(struct mipsnet_regs),
++			    "mipsnet")) {
+ 		err = -EBUSY;
+ 		goto out_free_netdev;
+ 	}
+@@ -217,7 +284,7 @@ static int __init mipsnet_probe(struct device *dev)
+ 	return 0;
+ 
+ out_free_region:
+-	release_region(netdev->base_addr, MIPSNET_IO_EXTENT);
++	release_region(netdev->base_addr, sizeof(struct mipsnet_regs));
+ 
+ out_free_netdev:
+ 	free_netdev(netdev);
+@@ -231,7 +298,7 @@ static int __devexit mipsnet_device_remove(struct device *device)
+ 	struct net_device *dev = dev_get_drvdata(device);
+ 
+ 	unregister_netdev(dev);
+-	release_region(dev->base_addr, MIPSNET_IO_EXTENT);
++	release_region(dev->base_addr, sizeof(struct mipsnet_regs));
+ 	free_netdev(dev);
+ 	dev_set_drvdata(device, NULL);
+ 
+diff --git a/drivers/net/mipsnet.h b/drivers/net/mipsnet.h
+deleted file mode 100644
+index 0132c67..0000000
+--- a/drivers/net/mipsnet.h
++++ /dev/null
+@@ -1,112 +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.
+- */
+-#ifndef __MIPSNET_H
+-#define __MIPSNET_H
+-
+-/*
+- *  Id of this Net device, as seen by the core.
+- */
+-#define MIPS_NET_DEV_ID ((uint64_t)	   \
+-			     ((uint64_t) 'M' <<  0)| \
+-			     ((uint64_t) 'I' <<  8)| \
+-			     ((uint64_t) 'P' << 16)| \
+-			     ((uint64_t) 'S' << 24)| \
+-			     ((uint64_t) 'N' << 32)| \
+-			     ((uint64_t) 'E' << 40)| \
+-			     ((uint64_t) 'T' << 48)| \
+-			     ((uint64_t) '0' << 56))
+-
+-/*
+- * Net status/control block as seen by sw in the core.
+- * (Why not use bit fields? can't be bothered with cross-platform struct
+- *  packing.)
+- */
+-struct net_control_block {
+-	/*
+-	 * dev info for probing
+-	 * reads as MIPSNET%d where %d is some form of version
+-	 */
+-	uint64_t devId;		/* 0x00 */
+-
+-	/*
+-	 * read only busy flag.
+-	 * Set and cleared by the Net Device to indicate that an rx or a tx
+-	 * is in progress.
+-	 */
+-	uint32_t busy;		/* 0x08 */
+-
+-	/*
+-	 * Set by the Net Device.
+-	 * The device will set it once data has been received.
+-	 * The value is the number of bytes that should be read from
+-	 * rxDataBuffer.  The value will decrease till 0 until all the data
+-	 * from rxDataBuffer has been read.
+-	 */
+-	uint32_t rxDataCount;	/* 0x0c */
+-#define MIPSNET_MAX_RXTX_DATACOUNT (1<<16)
+-
+-	/*
+-	 * Settable from the MIPS core, cleared by the Net Device.  The core
+-	 * should set the number of bytes it wants to send, then it should
+-	 * write those bytes of data to txDataBuffer.  The device will clear
+-	 * txDataCount has been processed (not necessarily sent).
+-	 */
+-	uint32_t txDataCount;	/* 0x10 */
+-
+-	/*
+-	 * Interrupt control
+-	 *
+-	 * Used to clear the interrupted generated by this dev.
+-	 * Write a 1 to clear the interrupt. (except bit31).
+-	 *
+-	 * Bit0 is set if it was a tx-done interrupt.
+-	 * Bit1 is set when new rx-data is available.
+-	 *      Until this bit is cleared there will be no other RXs.
+-	 *
+-	 * Bit31 is used for testing, it clears after a read.
+-	 *    Writing 1 to this bit will cause an interrupt to be generated.
+-	 *    To clear the test interrupt, write 0 to this register.
+-	 */
+-	uint32_t interruptControl;	/*0x14 */
+-#define MIPSNET_INTCTL_TXDONE     ((uint32_t)(1 <<  0))
+-#define MIPSNET_INTCTL_RXDONE     ((uint32_t)(1 <<  1))
+-#define MIPSNET_INTCTL_TESTBIT    ((uint32_t)(1 << 31))
+-#define MIPSNET_INTCTL_ALLSOURCES	(MIPSNET_INTCTL_TXDONE | \
+-					 MIPSNET_INTCTL_RXDONE | \
+-					 MIPSNET_INTCTL_TESTBIT)
+-
+-	/*
+-	 * Readonly core-specific interrupt info for the device to signal the
+-	 * core.  The meaning of the contents of this field might change.
+-	 *
+-	 * TODO: the whole memIntf interrupt scheme is messy: the device should
+-	 *       have no control what so ever of what VPE/register set is being
+-	 *       used.  The MemIntf should only expose interrupt lines, and
+-	 *       something in the config should be responsible for the
+-	 *       line<->core/vpe bindings.
+-	 */
+-	uint32_t interruptInfo;	/* 0x18 */
+-
+-	/*
+-	 *  This is where the received data is read out.
+-	 *  There is more data to read until rxDataReady is 0.
+-	 *  Only 1 byte at this regs offset is used.
+-	 */
+-	uint32_t rxDataBuffer;	/* 0x1c */
+-
+-	/*
+-	 * This is where the data to transmit is written.  Data should be
+-	 * written for the amount specified in the txDataCount register.  Only
+-	 * 1 byte at this regs offset is used.
+-	 */
+-	uint32_t txDataBuffer;	/* 0x20 */
+-};
+-
+-#define MIPSNET_IO_EXTENT 0x40	/* being generous */
+-
+-#define field_offset(field) (offsetof(struct net_control_block, field))
+-
+-#endif /* __MIPSNET_H */
 diff --git a/drivers/net/mlx4/fw.c b/drivers/net/mlx4/fw.c
-index 5064873..535a446 100644
+index 5064873..61dc495 100644
 --- a/drivers/net/mlx4/fw.c
 +++ b/drivers/net/mlx4/fw.c
 @@ -202,7 +202,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
@@ -561008,6 +615826,103 @@
  	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_MTT_OFFSET);
  	dev_cap->reserved_mtts = 1 << (field >> 4);
  	MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_MRW_SZ_OFFSET);
+@@ -617,9 +617,6 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
+ 	int err;
+ 
+ #define QUERY_ADAPTER_OUT_SIZE             0x100
+-#define QUERY_ADAPTER_VENDOR_ID_OFFSET     0x00
+-#define QUERY_ADAPTER_DEVICE_ID_OFFSET     0x04
+-#define QUERY_ADAPTER_REVISION_ID_OFFSET   0x08
+ #define QUERY_ADAPTER_INTA_PIN_OFFSET      0x10
+ #define QUERY_ADAPTER_VSD_OFFSET           0x20
+ 
+@@ -633,9 +630,6 @@ int mlx4_QUERY_ADAPTER(struct mlx4_dev *dev, struct mlx4_adapter *adapter)
+ 	if (err)
+ 		goto out;
+ 
+-	MLX4_GET(adapter->vendor_id, outbox,   QUERY_ADAPTER_VENDOR_ID_OFFSET);
+-	MLX4_GET(adapter->device_id, outbox,   QUERY_ADAPTER_DEVICE_ID_OFFSET);
+-	MLX4_GET(adapter->revision_id, outbox, QUERY_ADAPTER_REVISION_ID_OFFSET);
+ 	MLX4_GET(adapter->inta_pin, outbox,    QUERY_ADAPTER_INTA_PIN_OFFSET);
+ 
+ 	get_board_id(outbox + QUERY_ADAPTER_VSD_OFFSET / 4,
+diff --git a/drivers/net/mlx4/fw.h b/drivers/net/mlx4/fw.h
+index 7e1dd9e..e16dec8 100644
+--- a/drivers/net/mlx4/fw.h
++++ b/drivers/net/mlx4/fw.h
+@@ -99,9 +99,6 @@ struct mlx4_dev_cap {
+ };
+ 
+ struct mlx4_adapter {
+-	u32  vendor_id;
+-	u32  device_id;
+-	u32  revision_id;
+ 	char board_id[MLX4_BOARD_ID_LEN];
+ 	u8   inta_pin;
+ };
+diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
+index 89b3f0b..08bfc13 100644
+--- a/drivers/net/mlx4/main.c
++++ b/drivers/net/mlx4/main.c
+@@ -71,7 +71,7 @@ MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");
+ 
+ #endif /* CONFIG_PCI_MSI */
+ 
+-static const char mlx4_version[] __devinitdata =
++static char mlx4_version[] __devinitdata =
+ 	DRV_NAME ": Mellanox ConnectX core driver v"
+ 	DRV_VERSION " (" DRV_RELDATE ")\n";
+ 
+@@ -163,7 +163,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
+ 	return 0;
+ }
+ 
+-static int __devinit mlx4_load_fw(struct mlx4_dev *dev)
++static int mlx4_load_fw(struct mlx4_dev *dev)
+ {
+ 	struct mlx4_priv *priv = mlx4_priv(dev);
+ 	int err;
+@@ -197,8 +197,8 @@ err_free:
+ 	return err;
+ }
+ 
+-static int __devinit mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
+-					  int cmpt_entry_sz)
++static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
++				int cmpt_entry_sz)
+ {
+ 	struct mlx4_priv *priv = mlx4_priv(dev);
+ 	int err;
+@@ -534,7 +534,6 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
+ 	}
+ 
+ 	priv->eq_table.inta_pin = adapter.inta_pin;
+-	dev->rev_id		= adapter.revision_id;
+ 	memcpy(dev->board_id, adapter.board_id, sizeof dev->board_id);
+ 
+ 	return 0;
+@@ -688,7 +687,7 @@ err_uar_table_free:
+ 	return err;
+ }
+ 
+-static void __devinit mlx4_enable_msi_x(struct mlx4_dev *dev)
++static void mlx4_enable_msi_x(struct mlx4_dev *dev)
+ {
+ 	struct mlx4_priv *priv = mlx4_priv(dev);
+ 	struct msix_entry entries[MLX4_NUM_EQ];
+diff --git a/drivers/net/mlx4/mr.c b/drivers/net/mlx4/mr.c
+index 0c05a10..9c9e308 100644
+--- a/drivers/net/mlx4/mr.c
++++ b/drivers/net/mlx4/mr.c
+@@ -122,7 +122,7 @@ static void mlx4_buddy_free(struct mlx4_buddy *buddy, u32 seg, int order)
+ 	spin_unlock(&buddy->lock);
+ }
+ 
+-static int __devinit mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
++static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
+ {
+ 	int i, s;
+ 
 diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
 index c90958f..cead81e 100644
 --- a/drivers/net/myri10ge/myri10ge.c
@@ -561070,6 +615985,35 @@
  	mgp->rdma_tags_available = 15;
  
  	lro_mgr = &mgp->rx_done.lro_mgr;
+diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
+index c329a4f..0a3e604 100644
+--- a/drivers/net/natsemi.c
++++ b/drivers/net/natsemi.c
+@@ -203,22 +203,8 @@ skbuff at an offset of "+2", 16-byte aligning the IP header.
+ IIId. Synchronization
+ 
+ Most operations are synchronized on the np->lock irq spinlock, except the
+-performance critical codepaths:
+-
+-The rx process only runs in the interrupt handler. Access from outside
+-the interrupt handler is only permitted after disable_irq().
+-
+-The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
+-is set, then access is permitted under spin_lock_irq(&np->lock).
+-
+-Thus configuration functions that want to access everything must call
+-	disable_irq(dev->irq);
+-	netif_tx_lock_bh(dev);
+-	spin_lock_irq(&np->lock);
+-
+-IV. Notes
+-
+-NatSemi PCI network controllers are very uncommon.
++recieve and transmit paths which are synchronised using a combination of
++hardware descriptor ownership, disabling interrupts and NAPI poll scheduling.
+ 
+ IVb. References
+ 
 diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
 index 5ffbb88..31e047d 100644
 --- a/drivers/net/netconsole.c
@@ -562518,7 +617462,7 @@
  	struct ns83820 *dev = PRIV(ndev);
  	struct rx_info *info = &dev->rx_info;
 diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
-index 816a59e..bb88a41 100644
+index 816a59e..2e39e02 100644
 --- a/drivers/net/pasemi_mac.c
 +++ b/drivers/net/pasemi_mac.c
 @@ -32,9 +32,11 @@
@@ -562533,7 +617477,7 @@
  
  #include "pasemi_mac.h"
  
-@@ -55,9 +57,11 @@
+@@ -55,9 +57,15 @@
  
  
  /* Must be a power of two */
@@ -562543,10 +617487,14 @@
  
 +#define LRO_MAX_AGGR 64
 +
++#define PE_MIN_MTU	64
++#define PE_MAX_MTU	1500
++#define PE_DEF_MTU	ETH_DATA_LEN
++
  #define DEFAULT_MSG_ENABLE	  \
  	(NETIF_MSG_DRV		| \
  	 NETIF_MSG_PROBE	| \
-@@ -68,11 +72,11 @@
+@@ -68,18 +76,16 @@
  	 NETIF_MSG_RX_ERR	| \
  	 NETIF_MSG_TX_ERR)
  
@@ -562563,7 +617511,14 @@
  
  #define RING_USED(ring)		(((ring)->next_to_fill - (ring)->next_to_clean) \
  				 & ((ring)->size - 1))
-@@ -88,8 +92,6 @@ static int debug = -1;	/* -1 == use DEFAULT_MSG_ENABLE as value */
+ #define RING_AVAIL(ring)	((ring->size) - RING_USED(ring))
+ 
+-#define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
+-
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR ("Olof Johansson <olof at lixom.net>");
+ MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
+@@ -88,8 +94,6 @@ static int debug = -1;	/* -1 == use DEFAULT_MSG_ENABLE as value */
  module_param(debug, int, 0);
  MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
  
@@ -562572,7 +617527,7 @@
  static int translation_enabled(void)
  {
  #if defined(CONFIG_PPC_PASEMI_IOMMU_DMA_FORCE)
-@@ -99,32 +101,78 @@ static int translation_enabled(void)
+@@ -99,32 +103,96 @@ static int translation_enabled(void)
  #endif
  }
  
@@ -562614,8 +617569,7 @@
 +}
 +
 +static struct pasemi_mac_rxring *rx_ring(const struct pasemi_mac *mac)
- {
--	out_le32(mac->dma_regs+reg, val);
++{
 +	return mac->rx;
 +}
 +
@@ -562660,10 +617614,29 @@
 +		}
 +	}
 +	return -1;
++}
++
++static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
+ {
+-	out_le32(mac->dma_regs+reg, val);
++	unsigned int flags;
++
++	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
++	flags &= ~PAS_MAC_CFG_PCFG_PE;
++	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
++}
++
++static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
++{
++	unsigned int flags;
++
++	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
++	flags |= PAS_MAC_CFG_PCFG_PE;
++	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
  }
  
  static int pasemi_get_mac_addr(struct pasemi_mac *mac)
-@@ -161,7 +209,6 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
+@@ -161,7 +229,6 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
  		return -ENOENT;
  	}
  
@@ -562671,10 +617644,37 @@
  	if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
  		   &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
  		dev_warn(&pdev->dev,
-@@ -174,21 +221,51 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
+@@ -174,21 +241,78 @@ static int pasemi_get_mac_addr(struct pasemi_mac *mac)
  	return 0;
  }
  
++static int pasemi_mac_set_mac_addr(struct net_device *dev, void *p)
++{
++	struct pasemi_mac *mac = netdev_priv(dev);
++	struct sockaddr *addr = p;
++	unsigned int adr0, adr1;
++
++	if (!is_valid_ether_addr(addr->sa_data))
++		return -EINVAL;
++
++	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
++
++	adr0 = dev->dev_addr[2] << 24 |
++	       dev->dev_addr[3] << 16 |
++	       dev->dev_addr[4] << 8 |
++	       dev->dev_addr[5];
++	adr1 = read_mac_reg(mac, PAS_MAC_CFG_ADR1);
++	adr1 &= ~0xffff;
++	adr1 |= dev->dev_addr[0] << 8 | dev->dev_addr[1];
++
++	pasemi_mac_intf_disable(mac);
++	write_mac_reg(mac, PAS_MAC_CFG_ADR0, adr0);
++	write_mac_reg(mac, PAS_MAC_CFG_ADR1, adr1);
++	pasemi_mac_intf_enable(mac);
++
++	return 0;
++}
++
 +static int get_skb_hdr(struct sk_buff *skb, void **iphdr,
 +		       void **tcph, u64 *hdr_flags, void *data)
 +{
@@ -562729,7 +617729,7 @@
  	}
  	dev_kfree_skb_irq(skb);
  
-@@ -198,17 +275,21 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
+@@ -198,17 +322,21 @@ static int pasemi_mac_unmap_tx_skb(struct pasemi_mac *mac,
  	return (nfrags + 3) & ~1;
  }
  
@@ -562756,7 +617756,7 @@
  
  	spin_lock_init(&ring->lock);
  
-@@ -220,85 +301,80 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev)
+@@ -220,85 +348,80 @@ static int pasemi_mac_setup_rx_resources(struct net_device *dev)
  		goto out_ring_info;
  
  	/* Allocate descriptors */
@@ -562872,7 +617872,7 @@
  
  	spin_lock_init(&ring->lock);
  
-@@ -309,20 +385,15 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
+@@ -309,20 +432,15 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
  		goto out_ring_info;
  
  	/* Allocate descriptors */
@@ -562898,7 +617898,7 @@
  
  	cfg = PAS_DMA_TXCHAN_CFG_TY_IFACE |
  	      PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
-@@ -332,71 +403,64 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
+@@ -332,71 +450,64 @@ static int pasemi_mac_setup_tx_resources(struct net_device *dev)
  	if (translation_enabled())
  		cfg |= PAS_DMA_TXCHAN_CFG_TRD | PAS_DMA_TXCHAN_CFG_TRR;
  
@@ -562967,20 +617967,20 @@
  
 -	for (i = 0; i < TX_RING_SIZE; i++)
 -		TX_RING(mac, i) = 0;
--
--	dma_free_coherent(&mac->dma_pdev->dev,
--			  TX_RING_SIZE * sizeof(u64),
--			  mac->tx->ring, mac->tx->dma);
 +	kfree(txring->ring_info);
 +	pasemi_dma_free_chan(&txring->chan);
  
+-	dma_free_coherent(&mac->dma_pdev->dev,
+-			  TX_RING_SIZE * sizeof(u64),
+-			  mac->tx->ring, mac->tx->dma);
+-
 -	kfree(mac->tx->ring_info);
 -	kfree(mac->tx);
 -	mac->tx = NULL;
  }
  
 -static void pasemi_mac_free_rx_resources(struct net_device *dev)
-+static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
++static void pasemi_mac_free_rx_buffers(struct pasemi_mac *mac)
  {
 -	struct pasemi_mac *mac = netdev_priv(dev);
 +	struct pasemi_mac_rxring *rx = rx_ring(mac);
@@ -562993,16 +617993,20 @@
  		if (info->skb && info->dma) {
  			pci_unmap_single(mac->dma_pdev,
  					 info->dma,
-@@ -409,45 +473,38 @@ static void pasemi_mac_free_rx_resources(struct net_device *dev)
+@@ -409,51 +520,49 @@ static void pasemi_mac_free_rx_resources(struct net_device *dev)
  	}
  
  	for (i = 0; i < RX_RING_SIZE; i++)
 -		RX_RING(mac, i) = 0;
--
++		RX_BUFF(rx, i) = 0;
++}
+ 
 -	dma_free_coherent(&mac->dma_pdev->dev,
 -			  RX_RING_SIZE * sizeof(u64),
 -			  mac->rx->ring, mac->rx->dma);
-+		RX_DESC(rx, i) = 0;
++static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
++{
++	pasemi_mac_free_rx_buffers(mac);
  
  	dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
 -			  mac->rx->buffers, mac->rx->buf_dma);
@@ -563047,12 +618051,26 @@
 -			skb = dev_alloc_skb(BUF_SIZE);
 -			skb_reserve(skb, LOCAL_SKB_ALIGN);
 -		}
-+		skb = dev_alloc_skb(BUF_SIZE);
++		skb = dev_alloc_skb(mac->bufsz);
 +		skb_reserve(skb, LOCAL_SKB_ALIGN);
  
  		if (unlikely(!skb))
  			break;
-@@ -469,94 +526,108 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
+ 
+ 		dma = pci_map_single(mac->dma_pdev, skb->data,
+-				     BUF_SIZE - LOCAL_SKB_ALIGN,
++				     mac->bufsz - LOCAL_SKB_ALIGN,
+ 				     PCI_DMA_FROMDEVICE);
+ 
+ 		if (unlikely(dma_mapping_error(dma))) {
+@@ -463,100 +572,114 @@ static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
+ 
+ 		info->skb = skb;
+ 		info->dma = dma;
+-		*buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
++		*buff = XCT_RXB_LEN(mac->bufsz) | XCT_RXB_ADDR(dma);
+ 		fill++;
+ 	}
  
  	wmb();
  
@@ -563166,13 +618184,13 @@
 -	spin_lock(&mac->rx->lock);
 +	tot_bytes = 0;
 +	packets = 0;
++
++	spin_lock(&rx->lock);
  
 -	n = mac->rx->next_to_clean;
-+	spin_lock(&rx->lock);
++	n = rx->next_to_clean;
  
 -	prefetch(&RX_RING(mac, n));
-+	n = rx->next_to_clean;
-+
 +	prefetch(&RX_DESC(rx, n));
  
  	for (count = 0; count < limit; count++) {
@@ -563186,7 +618204,7 @@
  			pasemi_mac_rx_error(mac, macrx);
  
  		if (!(macrx & XCT_MACRX_O))
-@@ -566,21 +637,21 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
+@@ -566,21 +689,21 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
  
  		BUG_ON(!(macrx & XCT_MACRX_RR_8BRES));
  
@@ -563209,12 +618227,12 @@
  		len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
  
 -		pci_unmap_single(mac->dma_pdev, dma, len, PCI_DMA_FROMDEVICE);
-+		pci_unmap_single(pdev, dma, BUF_SIZE-LOCAL_SKB_ALIGN,
++		pci_unmap_single(pdev, dma, mac->bufsz - LOCAL_SKB_ALIGN,
 +				 PCI_DMA_FROMDEVICE);
  
  		if (macrx & XCT_MACRX_CRC) {
  			/* CRC error flagged */
-@@ -590,26 +661,9 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
+@@ -590,26 +713,9 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
  			goto next;
  		}
  
@@ -563242,7 +618260,7 @@
  		if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
  			skb->ip_summed = CHECKSUM_UNNECESSARY;
  			skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
-@@ -617,41 +671,49 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
+@@ -617,41 +723,49 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
  		} else
  			skb->ip_summed = CHECKSUM_NONE;
  
@@ -563302,7 +618320,7 @@
  
  	return count;
  }
-@@ -659,8 +721,10 @@ next:
+@@ -659,8 +773,10 @@ next:
  /* Can't make this too large or we blow the kernel stack limits */
  #define TX_CLEAN_BATCHSIZE (128/MAX_SKB_FRAGS)
  
@@ -563314,7 +618332,7 @@
  	int i, j;
  	unsigned int start, descr_count, buf_count, batch_limit;
  	unsigned int ring_limit;
-@@ -668,14 +732,18 @@ static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
+@@ -668,14 +784,18 @@ static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
  	unsigned long flags;
  	struct sk_buff *skbs[TX_CLEAN_BATCHSIZE];
  	dma_addr_t dmas[TX_CLEAN_BATCHSIZE][MAX_SKB_FRAGS+1];
@@ -563336,7 +618354,7 @@
  
  	/* Compensate for when fill has wrapped but clean has not */
  	if (start > ring_limit)
-@@ -687,41 +755,45 @@ restart:
+@@ -687,41 +807,45 @@ restart:
  	for (i = start;
  	     descr_count < batch_limit && i < ring_limit;
  	     i += buf_count) {
@@ -563397,7 +618415,7 @@
  
  	total_count += descr_count;
  
-@@ -735,11 +807,13 @@ restart:
+@@ -735,11 +859,13 @@ restart:
  
  static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
  {
@@ -563414,7 +618432,7 @@
  		return IRQ_NONE;
  
  	/* Don't reset packet count so it won't fire again but clear
-@@ -747,45 +821,77 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
+@@ -747,41 +873,55 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
  	 */
  
  	reg = 0;
@@ -563467,10 +618485,10 @@
 -	reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
 +	if (!(*chan->status & PAS_STATUS_CAUSE_M))
 +		return IRQ_NONE;
++
++	reg = 0;
  
 -	if (*mac->tx_status & PAS_STATUS_SOFT)
-+	reg = 0;
-+
 +	if (*chan->status & PAS_STATUS_SOFT)
  		reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
 -	if (*mac->tx_status & PAS_STATUS_ERROR)
@@ -563487,29 +618505,7 @@
  
  	return IRQ_HANDLED;
  }
- 
-+static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
-+{
-+	unsigned int flags;
-+
-+	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
-+	flags &= ~PAS_MAC_CFG_PCFG_PE;
-+	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
-+}
-+
-+static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
-+{
-+	unsigned int flags;
-+
-+	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
-+	flags |= PAS_MAC_CFG_PCFG_PE;
-+	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
-+}
-+
- static void pasemi_adjust_link(struct net_device *dev)
- {
- 	struct pasemi_mac *mac = netdev_priv(dev);
-@@ -801,11 +907,14 @@ static void pasemi_adjust_link(struct net_device *dev)
+@@ -801,11 +941,14 @@ static void pasemi_adjust_link(struct net_device *dev)
  			printk(KERN_INFO "%s: Link is down.\n", dev->name);
  
  		netif_carrier_off(dev);
@@ -563525,7 +618521,7 @@
  
  	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
  	new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M |
-@@ -897,15 +1006,14 @@ err:
+@@ -897,15 +1040,14 @@ err:
  static int pasemi_mac_open(struct net_device *dev)
  {
  	struct pasemi_mac *mac = netdev_priv(dev);
@@ -563543,7 +618539,7 @@
  
  	flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
  		PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
-@@ -913,62 +1021,59 @@ static int pasemi_mac_open(struct net_device *dev)
+@@ -913,62 +1055,59 @@ static int pasemi_mac_open(struct net_device *dev)
  
  	write_mac_reg(mac, PAS_MAC_CFG_TXP, flags);
  
@@ -563631,18 +618627,18 @@
 -	write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), RX_RING_SIZE>>1);
 +	write_dma_reg(PAS_DMA_RXCHAN_INCR(rx_ring(mac)->chan.chno),
 +		      RX_RING_SIZE>>1);
-+
-+	/* Clear out any residual packet count state from firmware */
-+	pasemi_mac_restart_rx_intr(mac);
-+	pasemi_mac_restart_tx_intr(mac);
  
 -	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
 -		PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
++	/* Clear out any residual packet count state from firmware */
++	pasemi_mac_restart_rx_intr(mac);
++	pasemi_mac_restart_tx_intr(mac);
++
 +	flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
  
  	if (mac->type == MAC_TYPE_GMAC)
  		flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
-@@ -979,55 +1084,63 @@ static int pasemi_mac_open(struct net_device *dev)
+@@ -979,55 +1118,63 @@ static int pasemi_mac_open(struct net_device *dev)
  	write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
  
  	ret = pasemi_mac_phy_init(dev);
@@ -563731,104 +618727,171 @@
  out_rx_resources:
  
  	return ret;
-@@ -1040,46 +1153,53 @@ static int pasemi_mac_close(struct net_device *dev)
- 	struct pasemi_mac *mac = netdev_priv(dev);
- 	unsigned int sta;
- 	int retries;
-+	int rxch, txch;
-+
-+	rxch = rx_ring(mac)->chan.chno;
-+	txch = tx_ring(mac)->chan.chno;
+@@ -1035,93 +1182,119 @@ out_rx_resources:
  
- 	if (mac->phydev) {
- 		phy_stop(mac->phydev);
- 		phy_disconnect(mac->phydev);
- 	}
- 
-+	del_timer_sync(&mac->tx->clean_timer);
-+
- 	netif_stop_queue(dev);
- 	napi_disable(&mac->napi);
+ #define MAX_RETRIES 5000
  
+-static int pasemi_mac_close(struct net_device *dev)
++static void pasemi_mac_pause_txchan(struct pasemi_mac *mac)
+ {
+-	struct pasemi_mac *mac = netdev_priv(dev);
+-	unsigned int sta;
+-	int retries;
+-
+-	if (mac->phydev) {
+-		phy_stop(mac->phydev);
+-		phy_disconnect(mac->phydev);
+-	}
+-
+-	netif_stop_queue(dev);
+-	napi_disable(&mac->napi);
+-
 -	sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
-+	sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
- 	if (sta & (PAS_DMA_RXINT_RCMDSTA_BP |
- 		      PAS_DMA_RXINT_RCMDSTA_OO |
- 		      PAS_DMA_RXINT_RCMDSTA_BT))
- 		printk(KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n", sta);
- 
+-	if (sta & (PAS_DMA_RXINT_RCMDSTA_BP |
+-		      PAS_DMA_RXINT_RCMDSTA_OO |
+-		      PAS_DMA_RXINT_RCMDSTA_BT))
+-		printk(KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n", sta);
+-
 -	sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
-+	sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
- 	if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU |
- 		     PAS_DMA_RXCHAN_CCMDSTA_OD |
- 		     PAS_DMA_RXCHAN_CCMDSTA_FD |
- 		     PAS_DMA_RXCHAN_CCMDSTA_DT))
- 		printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta);
- 
+-	if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU |
+-		     PAS_DMA_RXCHAN_CCMDSTA_OD |
+-		     PAS_DMA_RXCHAN_CCMDSTA_FD |
+-		     PAS_DMA_RXCHAN_CCMDSTA_DT))
+-		printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta);
+-
 -	sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
 -	if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ |
 -		      PAS_DMA_TXCHAN_TCMDSTA_DB |
 -		      PAS_DMA_TXCHAN_TCMDSTA_DE |
 -		      PAS_DMA_TXCHAN_TCMDSTA_DA))
-+	sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch));
-+	if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ | PAS_DMA_TXCHAN_TCMDSTA_DB |
-+		      PAS_DMA_TXCHAN_TCMDSTA_DE | PAS_DMA_TXCHAN_TCMDSTA_DA))
- 		printk(KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n", sta);
- 
- 	/* Clean out any pending buffers */
+-		printk(KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n", sta);
+-
+-	/* Clean out any pending buffers */
 -	pasemi_mac_clean_tx(mac);
 -	pasemi_mac_clean_rx(mac, RX_RING_SIZE);
-+	pasemi_mac_clean_tx(tx_ring(mac));
-+	pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
++	unsigned int sta, retries;
++	int txch = tx_ring(mac)->chan.chno;
  
- 	/* Disable interface */
+-	/* Disable interface */
 -	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), PAS_DMA_TXCHAN_TCMDSTA_ST);
 -	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), PAS_DMA_RXINT_RCMDSTA_ST);
 -	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), PAS_DMA_RXCHAN_CCMDSTA_ST);
 +	write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch),
 +		      PAS_DMA_TXCHAN_TCMDSTA_ST);
-+	write_dma_reg( PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
-+		      PAS_DMA_RXINT_RCMDSTA_ST);
-+	write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
-+		      PAS_DMA_RXCHAN_CCMDSTA_ST);
  
  	for (retries = 0; retries < MAX_RETRIES; retries++) {
 -		sta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
-+		sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(rxch));
++		sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch));
  		if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
  			break;
  		cond_resched();
-@@ -1089,7 +1209,7 @@ static int pasemi_mac_close(struct net_device *dev)
- 		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
+ 	}
+ 
+ 	if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
+-		dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
++		dev_err(&mac->dma_pdev->dev,
++			"Failed to stop tx channel, tcmdsta %08x\n", sta);
  
++	write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
++}
++
++static void pasemi_mac_pause_rxchan(struct pasemi_mac *mac)
++{
++	unsigned int sta, retries;
++	int rxch = rx_ring(mac)->chan.chno;
++
++	write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
++		      PAS_DMA_RXCHAN_CCMDSTA_ST);
  	for (retries = 0; retries < MAX_RETRIES; retries++) {
 -		sta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
 +		sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
  		if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
  			break;
  		cond_resched();
-@@ -1099,7 +1219,7 @@ static int pasemi_mac_close(struct net_device *dev)
- 		dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
+ 	}
  
+ 	if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
+-		dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
++		dev_err(&mac->dma_pdev->dev,
++			"Failed to stop rx channel, ccmdsta 08%x\n", sta);
++	write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
++}
+ 
++static void pasemi_mac_pause_rxint(struct pasemi_mac *mac)
++{
++	unsigned int sta, retries;
++
++	write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
++		      PAS_DMA_RXINT_RCMDSTA_ST);
  	for (retries = 0; retries < MAX_RETRIES; retries++) {
 -		sta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
 +		sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
  		if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
  			break;
  		cond_resched();
-@@ -1112,16 +1232,16 @@ static int pasemi_mac_close(struct net_device *dev)
- 	 * stopping, since you can't disable when active.
- 	 */
+ 	}
+ 
+ 	if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
+-		dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
++		dev_err(&mac->dma_pdev->dev,
++			"Failed to stop rx interface, rcmdsta %08x\n", sta);
++	write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
++}
+ 
+-	/* Then, disable the channel. This must be done separately from
+-	 * stopping, since you can't disable when active.
+-	 */
++static int pasemi_mac_close(struct net_device *dev)
++{
++	struct pasemi_mac *mac = netdev_priv(dev);
++	unsigned int sta;
++	int rxch, txch;
++
++	rxch = rx_ring(mac)->chan.chno;
++	txch = tx_ring(mac)->chan.chno;
  
 -	write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), 0);
 -	write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), 0);
 -	write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
-+	write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
-+	write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
-+	write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
++	if (mac->phydev) {
++		phy_stop(mac->phydev);
++		phy_disconnect(mac->phydev);
++	}
  
 -	free_irq(mac->tx_irq, dev);
 -	free_irq(mac->rx_irq, dev);
++	del_timer_sync(&mac->tx->clean_timer);
++
++	netif_stop_queue(dev);
++	napi_disable(&mac->napi);
++
++	sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
++	if (sta & (PAS_DMA_RXINT_RCMDSTA_BP |
++		      PAS_DMA_RXINT_RCMDSTA_OO |
++		      PAS_DMA_RXINT_RCMDSTA_BT))
++		printk(KERN_DEBUG "pasemi_mac: rcmdsta error: 0x%08x\n", sta);
++
++	sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
++	if (sta & (PAS_DMA_RXCHAN_CCMDSTA_DU |
++		     PAS_DMA_RXCHAN_CCMDSTA_OD |
++		     PAS_DMA_RXCHAN_CCMDSTA_FD |
++		     PAS_DMA_RXCHAN_CCMDSTA_DT))
++		printk(KERN_DEBUG "pasemi_mac: ccmdsta error: 0x%08x\n", sta);
++
++	sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch));
++	if (sta & (PAS_DMA_TXCHAN_TCMDSTA_SZ | PAS_DMA_TXCHAN_TCMDSTA_DB |
++		      PAS_DMA_TXCHAN_TCMDSTA_DE | PAS_DMA_TXCHAN_TCMDSTA_DA))
++		printk(KERN_DEBUG "pasemi_mac: tcmdsta error: 0x%08x\n", sta);
++
++	/* Clean out any pending buffers */
++	pasemi_mac_clean_tx(tx_ring(mac));
++	pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
++
++	pasemi_mac_pause_txchan(mac);
++	pasemi_mac_pause_rxint(mac);
++	pasemi_mac_pause_rxchan(mac);
++	pasemi_mac_intf_disable(mac);
++
 +	free_irq(mac->tx->chan.irq, mac->tx);
 +	free_irq(mac->rx->chan.irq, mac->rx);
  
@@ -563840,7 +618903,7 @@
  
  	return 0;
  }
-@@ -1135,6 +1255,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+@@ -1135,6 +1308,7 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
  	unsigned int map_size[MAX_SKB_FRAGS+1];
  	unsigned long flags;
  	int i, nfrags;
@@ -563848,7 +618911,7 @@
  
  	dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_CRC_PAD;
  
-@@ -1178,10 +1299,12 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+@@ -1178,10 +1352,12 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
  
  	mactx = dflags | XCT_MACTX_LLEN(skb->len);
  
@@ -563862,7 +618925,7 @@
  	/* Avoid stepping on the same cache line that the DMA controller
  	 * is currently about to send, so leave at least 8 words available.
  	 * Total free space needed is mactx + fragments + 8
-@@ -1192,13 +1315,14 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+@@ -1192,13 +1368,14 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
  		goto out_err;
  	}
  
@@ -563883,7 +618946,7 @@
  	}
  
  	/* We have to add an even number of 8-byte entries to the ring
-@@ -1208,15 +1332,14 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
+@@ -1208,15 +1385,14 @@ static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
  	if (nfrags & 1)
  		nfrags++;
  
@@ -563901,7 +618964,7 @@
  
  	return NETDEV_TX_OK;
  
-@@ -1232,7 +1355,7 @@ out_err_nolock:
+@@ -1232,7 +1408,7 @@ out_err_nolock:
  
  static void pasemi_mac_set_rx_mode(struct net_device *dev)
  {
@@ -563910,7 +618973,7 @@
  	unsigned int flags;
  
  	flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
-@@ -1253,88 +1376,21 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
+@@ -1253,79 +1429,69 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
  	struct net_device *dev = mac->netdev;
  	int pkts;
  
@@ -563929,18 +618992,26 @@
  }
  
 -static void __iomem * __devinit map_onedev(struct pci_dev *p, int index)
--{
++static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
+ {
 -	struct device_node *dn;
 -	void __iomem *ret;
--
++	struct pasemi_mac *mac = netdev_priv(dev);
++	unsigned int reg;
++	unsigned int rcmdsta;
++	int running;
+ 
 -	dn = pci_device_to_OF_node(p);
 -	if (!dn)
 -		goto fallback;
--
++	if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
++		return -EINVAL;
+ 
 -	ret = of_iomap(dn, index);
 -	if (!ret)
 -		goto fallback;
--
++	running = netif_running(dev);
+ 
 -	return ret;
 -fallback:
 -	/* This is hardcoded and ugly, but we have some firmware versions
@@ -563949,34 +619020,60 @@
 -	 */
 -	return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
 -}
--
++	if (running) {
++		/* Need to stop the interface, clean out all already
++		 * received buffers, free all unused buffers on the RX
++		 * interface ring, then finally re-fill the rx ring with
++		 * the new-size buffers and restart.
++		 */
+ 
 -static int __devinit pasemi_mac_map_regs(struct pasemi_mac *mac)
 -{
 -	struct resource res;
 -	struct device_node *dn;
 -	int err;
--
++		napi_disable(&mac->napi);
++		netif_tx_disable(dev);
++		pasemi_mac_intf_disable(mac);
+ 
 -	mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
 -	if (!mac->dma_pdev) {
 -		dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
 -		return -ENODEV;
--	}
--
++		rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
++		pasemi_mac_pause_rxint(mac);
++		pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
++		pasemi_mac_free_rx_buffers(mac);
+ 	}
+ 
 -	mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
 -	if (!mac->iob_pdev) {
 -		dev_err(&mac->pdev->dev, "Can't find I/O Bridge\n");
 -		return -ENODEV;
 -	}
--
++	/* Change maxf, i.e. what size frames are accepted.
++	 * Need room for ethernet header and CRC word
++	 */
++	reg = read_mac_reg(mac, PAS_MAC_CFG_MACCFG);
++	reg &= ~PAS_MAC_CFG_MACCFG_MAXF_M;
++	reg |= PAS_MAC_CFG_MACCFG_MAXF(new_mtu + ETH_HLEN + 4);
++	write_mac_reg(mac, PAS_MAC_CFG_MACCFG, reg);
+ 
 -	mac->regs = map_onedev(mac->pdev, 0);
 -	mac->dma_regs = map_onedev(mac->dma_pdev, 0);
 -	mac->iob_regs = map_onedev(mac->iob_pdev, 0);
--
++	dev->mtu = new_mtu;
++	/* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
++	mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
+ 
 -	if (!mac->regs || !mac->dma_regs || !mac->iob_regs) {
 -		dev_err(&mac->pdev->dev, "Can't map registers\n");
 -		return -ENODEV;
 -	}
--
++	if (running) {
++		write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
++			      rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
+ 
 -	/* The dma status structure is located in the I/O bridge, and
 -	 * is cache coherent.
 -	 */
@@ -563990,11 +619087,16 @@
 -			res.end = res.start + 0x1000;
 -		}
 -		dma_status = __ioremap(res.start, res.end-res.start, 0);
--	}
--
--	return 0;
--}
--
++		rx_ring(mac)->next_to_fill = 0;
++		pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE-1);
++
++		napi_enable(&mac->napi);
++		netif_start_queue(dev);
++		pasemi_mac_intf_enable(mac);
+ 	}
+ 
+ 	return 0;
+@@ -1334,7 +1500,6 @@ static int __devinit pasemi_mac_map_regs(struct pasemi_mac *mac)
  static int __devinit
  pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  {
@@ -564002,7 +619104,7 @@
  	struct net_device *dev;
  	struct pasemi_mac *mac;
  	int err;
-@@ -1362,20 +1418,46 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -1362,20 +1527,46 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  
  	netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
  
@@ -564061,7 +619163,7 @@
  
  	switch (pdev->device) {
  	case 0xa005:
-@@ -1389,25 +1471,14 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -1389,25 +1580,20 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  		goto out;
  	}
  
@@ -564076,6 +619178,12 @@
  	dev->stop = pasemi_mac_close;
  	dev->hard_start_xmit = pasemi_mac_start_tx;
  	dev->set_multicast_list = pasemi_mac_set_rx_mode;
++	dev->set_mac_address = pasemi_mac_set_mac_addr;
++	dev->mtu = PE_DEF_MTU;
++	/* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
++	mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
++
++	dev->change_mtu = pasemi_mac_change_mtu;
  
 -	err = pasemi_mac_map_regs(mac);
  	if (err)
@@ -564087,7 +619195,7 @@
  	mac->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
  
  	/* Enable most messages by default */
-@@ -1420,11 +1491,9 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+@@ -1420,11 +1606,9 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
  			err);
  		goto out;
  	} else if netif_msg_probe(mac)
@@ -564101,7 +619209,7 @@
  
  	return err;
  
-@@ -1433,12 +1502,6 @@ out:
+@@ -1433,12 +1617,6 @@ out:
  		pci_dev_put(mac->iob_pdev);
  	if (mac->dma_pdev)
  		pci_dev_put(mac->dma_pdev);
@@ -564114,7 +619222,7 @@
  
  	free_netdev(dev);
  out_disable_device:
-@@ -1463,9 +1526,8 @@ static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
+@@ -1463,9 +1641,8 @@ static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
  	pci_dev_put(mac->dma_pdev);
  	pci_dev_put(mac->iob_pdev);
  
@@ -564126,7 +619234,7 @@
  
  	pci_set_drvdata(pdev, NULL);
  	free_netdev(netdev);
-@@ -1489,12 +1551,16 @@ static struct pci_driver pasemi_mac_driver = {
+@@ -1489,12 +1666,16 @@ static struct pci_driver pasemi_mac_driver = {
  static void __exit pasemi_mac_cleanup_module(void)
  {
  	pci_unregister_driver(&pasemi_mac_driver);
@@ -564146,10 +619254,10 @@
  }
  
 diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
-index 60368df..8bee2a6 100644
+index 60368df..99e7b93 100644
 --- a/drivers/net/pasemi_mac.h
 +++ b/drivers/net/pasemi_mac.h
-@@ -26,60 +26,55 @@
+@@ -26,60 +26,56 @@
  #include <linux/spinlock.h>
  #include <linux/phy.h>
  
@@ -564199,6 +619307,7 @@
 -	u64	*rx_status;
 -	u64	*tx_status;
 -
++	int		bufsz; /* RX ring buffer size */
  	u8		type;
  #define MAC_TYPE_GMAC	1
  #define MAC_TYPE_XAUI	2
@@ -564222,7 +619331,7 @@
  	int	link;
  	int	speed;
  	int	duplex;
-@@ -95,11 +90,8 @@ struct pasemi_mac_buffer {
+@@ -95,15 +91,15 @@ struct pasemi_mac_buffer {
  };
  
  
@@ -564236,7 +619345,33 @@
  
  /* MAC CFG register offsets */
  enum {
-@@ -173,333 +165,4 @@ enum {
+ 	PAS_MAC_CFG_PCFG = 0x80,
++	PAS_MAC_CFG_MACCFG = 0x84,
++	PAS_MAC_CFG_ADR0 = 0x8c,
++	PAS_MAC_CFG_ADR1 = 0x90,
+ 	PAS_MAC_CFG_TXP = 0x98,
+ 	PAS_MAC_IPC_CHNL = 0x208,
+ };
+@@ -138,6 +134,18 @@ enum {
+ #define PAS_MAC_CFG_PCFG_SPD_100M	0x00000001
+ #define PAS_MAC_CFG_PCFG_SPD_1G		0x00000002
+ #define PAS_MAC_CFG_PCFG_SPD_10G	0x00000003
++
++#define PAS_MAC_CFG_MACCFG_TXT_M	0x70000000
++#define PAS_MAC_CFG_MACCFG_TXT_S	28
++#define PAS_MAC_CFG_MACCFG_PRES_M	0x0f000000
++#define PAS_MAC_CFG_MACCFG_PRES_S	24
++#define PAS_MAC_CFG_MACCFG_MAXF_M	0x00ffff00
++#define PAS_MAC_CFG_MACCFG_MAXF_S	8
++#define PAS_MAC_CFG_MACCFG_MAXF(x)	(((x) << PAS_MAC_CFG_MACCFG_MAXF_S) & \
++					 PAS_MAC_CFG_MACCFG_MAXF_M)
++#define PAS_MAC_CFG_MACCFG_MINF_M	0x000000ff
++#define PAS_MAC_CFG_MACCFG_MINF_S	0
++
+ #define PAS_MAC_CFG_TXP_FCF		0x01000000
+ #define PAS_MAC_CFG_TXP_FCE		0x00800000
+ #define PAS_MAC_CFG_TXP_FC		0x00400000
+@@ -173,333 +181,4 @@ enum {
  #define PAS_MAC_IPC_CHNL_BCH(x)		(((x) << PAS_MAC_IPC_CHNL_BCH_S) & \
  					 PAS_MAC_IPC_CHNL_BCH_M)
  
@@ -564570,10 +619705,683 @@
 -
 -
  #endif /* PASEMI_MAC_H */
+diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
+index ed402e0..fffc49b 100644
+--- a/drivers/net/pci-skeleton.c
++++ b/drivers/net/pci-skeleton.c
+@@ -541,7 +541,7 @@ static void netdrv_hw_start (struct net_device *dev);
+ #define NETDRV_W32_F(reg, val32)	do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)
+ 
+ 
+-#if MMIO_FLUSH_AUDIT_COMPLETE
++#ifdef MMIO_FLUSH_AUDIT_COMPLETE
+ 
+ /* write MMIO register */
+ #define NETDRV_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
+@@ -603,7 +603,7 @@ static int __devinit netdrv_init_board (struct pci_dev *pdev,
+ 		return -ENOMEM;
+ 	}
+ 	SET_NETDEV_DEV(dev, &pdev->dev);
+-	tp = dev->priv;
++	tp = netdev_priv(dev);
+ 
+ 	/* enable device (incl. PCI PM wakeup), and bus-mastering */
+ 	rc = pci_enable_device (pdev);
+@@ -759,7 +759,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev,
+ 		return i;
+ 	}
+ 
+-	tp = dev->priv;
++	tp = netdev_priv(dev);
+ 
+ 	assert (ioaddr != NULL);
+ 	assert (dev != NULL);
+@@ -783,7 +783,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev,
+ 	dev->base_addr = (unsigned long) ioaddr;
+ 
+ 	/* dev->priv/tp zeroed and aligned in alloc_etherdev */
+-	tp = dev->priv;
++	tp = netdev_priv(dev);
+ 
+ 	/* note: tp->chipset set in netdrv_init_board */
+ 	tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+@@ -841,7 +841,7 @@ static void __devexit netdrv_remove_one (struct pci_dev *pdev)
+ 
+ 	assert (dev != NULL);
+ 
+-	np = dev->priv;
++	np = netdev_priv(dev);
+ 	assert (np != NULL);
+ 
+ 	unregister_netdev (dev);
+@@ -974,7 +974,7 @@ static void mdio_sync (void *mdio_addr)
+ 
+ static int mdio_read (struct net_device *dev, int phy_id, int location)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *mdio_addr = tp->mmio_addr + Config4;
+ 	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ 	int retval = 0;
+@@ -1017,7 +1017,7 @@ static int mdio_read (struct net_device *dev, int phy_id, int location)
+ static void mdio_write (struct net_device *dev, int phy_id, int location,
+ 			int value)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *mdio_addr = tp->mmio_addr + Config4;
+ 	int mii_cmd =
+ 	    (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+@@ -1060,7 +1060,7 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
+ 
+ static int netdrv_open (struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	int retval;
+ #ifdef NETDRV_DEBUG
+ 	void *ioaddr = tp->mmio_addr;
+@@ -1121,7 +1121,7 @@ static int netdrv_open (struct net_device *dev)
+ /* Start the hardware at open or resume. */
+ static void netdrv_hw_start (struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	u32 i;
+ 
+@@ -1191,7 +1191,7 @@ static void netdrv_hw_start (struct net_device *dev)
+ /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+ static void netdrv_init_ring (struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	int i;
+ 
+ 	DPRINTK ("ENTER\n");
+@@ -1213,7 +1213,7 @@ static void netdrv_init_ring (struct net_device *dev)
+ static void netdrv_timer (unsigned long data)
+ {
+ 	struct net_device *dev = (struct net_device *) data;
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	int next_tick = 60 * HZ;
+ 	int mii_lpa;
+@@ -1252,9 +1252,10 @@ static void netdrv_timer (unsigned long data)
+ }
+ 
+ 
+-static void netdrv_tx_clear (struct netdrv_private *tp)
++static void netdrv_tx_clear (struct net_device *dev)
+ {
+ 	int i;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 
+ 	atomic_set (&tp->cur_tx, 0);
+ 	atomic_set (&tp->dirty_tx, 0);
+@@ -1278,7 +1279,7 @@ static void netdrv_tx_clear (struct netdrv_private *tp)
+ 
+ static void netdrv_tx_timeout (struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	int i;
+ 	u8 tmp8;
+@@ -1311,7 +1312,7 @@ static void netdrv_tx_timeout (struct net_device *dev)
+ 	/* Stop a shared interrupt from scavenging while we are. */
+ 	spin_lock_irqsave (&tp->lock, flags);
+ 
+-	netdrv_tx_clear (tp);
++	netdrv_tx_clear (dev);
+ 
+ 	spin_unlock_irqrestore (&tp->lock, flags);
+ 
+@@ -1325,7 +1326,7 @@ static void netdrv_tx_timeout (struct net_device *dev)
+ 
+ static int netdrv_start_xmit (struct sk_buff *skb, struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	int entry;
+ 
+@@ -1525,7 +1526,7 @@ static void netdrv_rx_interrupt (struct net_device *dev,
+ 		DPRINTK ("%s:  netdrv_rx() status %4.4x, size %4.4x,"
+ 			 " cur %4.4x.\n", dev->name, rx_status,
+ 			 rx_size, cur_rx);
+-#if NETDRV_DEBUG > 2
++#if defined(NETDRV_DEBUG) && (NETDRV_DEBUG > 2)
+ 		{
+ 			int i;
+ 			DPRINTK ("%s: Frame contents ", dev->name);
+@@ -1648,7 +1649,7 @@ static void netdrv_weird_interrupt (struct net_device *dev,
+ static irqreturn_t netdrv_interrupt (int irq, void *dev_instance)
+ {
+ 	struct net_device *dev = (struct net_device *) dev_instance;
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	int boguscnt = max_interrupt_work;
+ 	void *ioaddr = tp->mmio_addr;
+ 	int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
+@@ -1711,7 +1712,7 @@ static irqreturn_t netdrv_interrupt (int irq, void *dev_instance)
+ 
+ static int netdrv_close (struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	unsigned long flags;
+ 
+@@ -1738,10 +1739,10 @@ static int netdrv_close (struct net_device *dev)
+ 
+ 	spin_unlock_irqrestore (&tp->lock, flags);
+ 
+-	synchronize_irq ();
++	synchronize_irq (dev->irq);
+ 	free_irq (dev->irq, dev);
+ 
+-	netdrv_tx_clear (tp);
++	netdrv_tx_clear (dev);
+ 
+ 	pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
+ 			    tp->rx_ring, tp->rx_ring_dma);
+@@ -1762,7 +1763,7 @@ static int netdrv_close (struct net_device *dev)
+ 
+ static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	struct mii_ioctl_data *data = if_mii(rq);
+ 	unsigned long flags;
+ 	int rc = 0;
+@@ -1805,7 +1806,7 @@ static int netdrv_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+ 
+ static void netdrv_set_rx_mode (struct net_device *dev)
+ {
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	u32 mc_filter[2];	/* Multicast hash filter */
+ 	int i, rx_mode;
+@@ -1862,7 +1863,7 @@ static void netdrv_set_rx_mode (struct net_device *dev)
+ static int netdrv_suspend (struct pci_dev *pdev, pm_message_t state)
+ {
+ 	struct net_device *dev = pci_get_drvdata (pdev);
+-	struct netdrv_private *tp = dev->priv;
++	struct netdrv_private *tp = netdev_priv(dev);
+ 	void *ioaddr = tp->mmio_addr;
+ 	unsigned long flags;
+ 
+@@ -1892,7 +1893,7 @@ static int netdrv_suspend (struct pci_dev *pdev, pm_message_t state)
+ static int netdrv_resume (struct pci_dev *pdev)
+ {
+ 	struct net_device *dev = pci_get_drvdata (pdev);
+-	struct netdrv_private *tp = dev->priv;
++	/*struct netdrv_private *tp = netdev_priv(dev);*/
+ 
+ 	if (!netif_running(dev))
+ 		return 0;
+diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
+index 36a7ba3..3b78a38 100644
+--- a/drivers/net/pcmcia/3c574_cs.c
++++ b/drivers/net/pcmcia/3c574_cs.c
+@@ -230,10 +230,11 @@ static char mii_preamble_required = 0;
+ static int tc574_config(struct pcmcia_device *link);
+ static void tc574_release(struct pcmcia_device *link);
+ 
+-static void mdio_sync(kio_addr_t ioaddr, int bits);
+-static int mdio_read(kio_addr_t ioaddr, int phy_id, int location);
+-static void mdio_write(kio_addr_t ioaddr, int phy_id, int location, int value);
+-static unsigned short read_eeprom(kio_addr_t ioaddr, int index);
++static void mdio_sync(unsigned int ioaddr, int bits);
++static int mdio_read(unsigned int ioaddr, int phy_id, int location);
++static void mdio_write(unsigned int ioaddr, int phy_id, int location,
++		       int value);
++static unsigned short read_eeprom(unsigned int ioaddr, int index);
+ static void tc574_wait_for_completion(struct net_device *dev, int cmd);
+ 
+ static void tc574_reset(struct net_device *dev);
+@@ -341,7 +342,7 @@ static int tc574_config(struct pcmcia_device *link)
+ 	tuple_t tuple;
+ 	__le16 buf[32];
+ 	int last_fn, last_ret, i, j;
+-	kio_addr_t ioaddr;
++	unsigned int ioaddr;
+ 	__be16 *phys_addr;
+ 	char *cardname;
+ 	__u32 config;
+@@ -515,7 +516,7 @@ static int tc574_resume(struct pcmcia_device *link)
+ 
+ static void dump_status(struct net_device *dev)
+ {
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	EL3WINDOW(1);
+ 	printk(KERN_INFO "  irq status %04x, rx status %04x, tx status "
+ 		   "%02x, tx free %04x\n", inw(ioaddr+EL3_STATUS),
+@@ -544,7 +545,7 @@ static void tc574_wait_for_completion(struct net_device *dev, int cmd)
+ /* Read a word from the EEPROM using the regular EEPROM access register.
+    Assume that we are in register window zero.
+  */
+-static unsigned short read_eeprom(kio_addr_t ioaddr, int index)
++static unsigned short read_eeprom(unsigned int ioaddr, int index)
+ {
+ 	int timer;
+ 	outw(EEPROM_Read + index, ioaddr + Wn0EepromCmd);
+@@ -572,9 +573,9 @@ static unsigned short read_eeprom(kio_addr_t ioaddr, int index)
+ 
+ /* Generate the preamble required for initial synchronization and
+    a few older transceivers. */
+-static void mdio_sync(kio_addr_t ioaddr, int bits)
++static void mdio_sync(unsigned int ioaddr, int bits)
+ {
+-	kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt;
++	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ 
+ 	/* Establish sync by sending at least 32 logic ones. */
+ 	while (-- bits >= 0) {
+@@ -583,12 +584,12 @@ static void mdio_sync(kio_addr_t ioaddr, int bits)
+ 	}
+ }
+ 
+-static int mdio_read(kio_addr_t ioaddr, int phy_id, int location)
++static int mdio_read(unsigned int ioaddr, int phy_id, int location)
+ {
+ 	int i;
+ 	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+ 	unsigned int retval = 0;
+-	kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt;
++	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ 
+ 	if (mii_preamble_required)
+ 		mdio_sync(ioaddr, 32);
+@@ -608,10 +609,10 @@ static int mdio_read(kio_addr_t ioaddr, int phy_id, int location)
+ 	return (retval>>1) & 0xffff;
+ }
+ 
+-static void mdio_write(kio_addr_t ioaddr, int phy_id, int location, int value)
++static void mdio_write(unsigned int ioaddr, int phy_id, int location, int value)
+ {
+ 	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value;
+-	kio_addr_t mdio_addr = ioaddr + Wn4_PhysicalMgmt;
++	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt;
+ 	int i;
+ 
+ 	if (mii_preamble_required)
+@@ -637,7 +638,7 @@ static void tc574_reset(struct net_device *dev)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+ 	int i;
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	unsigned long flags;
+ 
+ 	tc574_wait_for_completion(dev, TotalReset|0x10);
+@@ -695,7 +696,7 @@ static void tc574_reset(struct net_device *dev)
+ 	mdio_write(ioaddr, lp->phys, 4, lp->advertising);
+ 	if (!auto_polarity) {
+ 		/* works for TDK 78Q2120 series MII's */
+-		int i = mdio_read(ioaddr, lp->phys, 16) | 0x20;
++		i = mdio_read(ioaddr, lp->phys, 16) | 0x20;
+ 		mdio_write(ioaddr, lp->phys, 16, i);
+ 	}
+ 
+@@ -741,7 +742,7 @@ static int el3_open(struct net_device *dev)
+ static void el3_tx_timeout(struct net_device *dev)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	
+ 	printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);
+ 	dump_status(dev);
+@@ -756,7 +757,7 @@ static void el3_tx_timeout(struct net_device *dev)
+ static void pop_tx_status(struct net_device *dev)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	int i;
+     
+ 	/* Clear the Tx status stack. */
+@@ -779,7 +780,7 @@ static void pop_tx_status(struct net_device *dev)
+ 
+ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	struct el3_private *lp = netdev_priv(dev);
+ 	unsigned long flags;
+ 
+@@ -813,7 +814,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)
+ {
+ 	struct net_device *dev = (struct net_device *) dev_id;
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr;
++	unsigned int ioaddr;
+ 	unsigned status;
+ 	int work_budget = max_interrupt_work;
+ 	int handled = 0;
+@@ -907,7 +908,7 @@ static void media_check(unsigned long arg)
+ {
+ 	struct net_device *dev = (struct net_device *) arg;
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	unsigned long flags;
+ 	unsigned short /* cable, */ media, partner;
+ 
+@@ -996,7 +997,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
+ static void update_stats(struct net_device *dev)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	u8 rx, tx, up;
+ 
+ 	DEBUG(2, "%s: updating the statistics.\n", dev->name);
+@@ -1033,7 +1034,7 @@ static void update_stats(struct net_device *dev)
+ static int el3_rx(struct net_device *dev, int worklimit)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	short rx_status;
+ 	
+ 	DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
+@@ -1094,7 +1095,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
+ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+ 	struct el3_private *lp = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	u16 *data = (u16 *)&rq->ifr_ifru;
+ 	int phy = lp->phys & 0x1f;
+ 
+@@ -1148,7 +1149,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ 
+ static void set_rx_mode(struct net_device *dev)
+ {
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 
+ 	if (dev->flags & IFF_PROMISC)
+ 		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
+@@ -1161,7 +1162,7 @@ static void set_rx_mode(struct net_device *dev)
+ 
+ static int el3_close(struct net_device *dev)
+ {
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	struct el3_private *lp = netdev_priv(dev);
+ 	struct pcmcia_device *link = lp->p_dev;
+ 
+diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
+index e862d14..1b1abb1 100644
+--- a/drivers/net/pcmcia/3c589_cs.c
++++ b/drivers/net/pcmcia/3c589_cs.c
+@@ -145,7 +145,7 @@ DRV_NAME ".c " DRV_VERSION " 2001/10/13 00:08:50 (David Hinds)";
+ static int tc589_config(struct pcmcia_device *link);
+ static void tc589_release(struct pcmcia_device *link);
+ 
+-static u16 read_eeprom(kio_addr_t ioaddr, int index);
++static u16 read_eeprom(unsigned int ioaddr, int index);
+ static void tc589_reset(struct net_device *dev);
+ static void media_check(unsigned long arg);
+ static int el3_config(struct net_device *dev, struct ifmap *map);
+@@ -254,7 +254,7 @@ static int tc589_config(struct pcmcia_device *link)
+     __le16 buf[32];
+     __be16 *phys_addr;
+     int last_fn, last_ret, i, j, multi = 0, fifo;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+     DECLARE_MAC_BUF(mac);
+     
+@@ -403,7 +403,7 @@ static void tc589_wait_for_completion(struct net_device *dev, int cmd)
+   Read a word from the EEPROM using the regular EEPROM access register.
+   Assume that we are in register window zero.
+ */
+-static u16 read_eeprom(kio_addr_t ioaddr, int index)
++static u16 read_eeprom(unsigned int ioaddr, int index)
+ {
+     int i;
+     outw(EEPROM_READ + index, ioaddr + 10);
+@@ -421,7 +421,7 @@ static u16 read_eeprom(kio_addr_t ioaddr, int index)
+ static void tc589_set_xcvr(struct net_device *dev, int if_port)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     
+     EL3WINDOW(0);
+     switch (if_port) {
+@@ -443,7 +443,7 @@ static void tc589_set_xcvr(struct net_device *dev, int if_port)
+ 
+ static void dump_status(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     EL3WINDOW(1);
+     printk(KERN_INFO "  irq status %04x, rx status %04x, tx status "
+ 	   "%02x  tx free %04x\n", inw(ioaddr+EL3_STATUS),
+@@ -459,7 +459,7 @@ static void dump_status(struct net_device *dev)
+ /* Reset and restore all of the 3c589 registers. */
+ static void tc589_reset(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int i;
+     
+     EL3WINDOW(0);
+@@ -567,7 +567,7 @@ static int el3_open(struct net_device *dev)
+ static void el3_tx_timeout(struct net_device *dev)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     
+     printk(KERN_WARNING "%s: Transmit timed out!\n", dev->name);
+     dump_status(dev);
+@@ -582,7 +582,7 @@ static void el3_tx_timeout(struct net_device *dev)
+ static void pop_tx_status(struct net_device *dev)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int i;
+     
+     /* Clear the Tx status stack. */
+@@ -604,7 +604,7 @@ static void pop_tx_status(struct net_device *dev)
+ 
+ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     struct el3_private *priv = netdev_priv(dev);
+     unsigned long flags;
+ 
+@@ -641,7 +641,7 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id)
+ {
+     struct net_device *dev = (struct net_device *) dev_id;
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     __u16 status;
+     int i = 0, handled = 1;
+     
+@@ -727,7 +727,7 @@ static void media_check(unsigned long arg)
+ {
+     struct net_device *dev = (struct net_device *)(arg);
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u16 media, errs;
+     unsigned long flags;
+ 
+@@ -828,7 +828,7 @@ static struct net_device_stats *el3_get_stats(struct net_device *dev)
+ static void update_stats(struct net_device *dev)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     DEBUG(2, "%s: updating the statistics.\n", dev->name);
+     /* Turn off statistics updates while reading. */
+@@ -855,7 +855,7 @@ static void update_stats(struct net_device *dev)
+ static int el3_rx(struct net_device *dev)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int worklimit = 32;
+     short rx_status;
+     
+@@ -909,7 +909,7 @@ static void set_multicast_list(struct net_device *dev)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+     struct pcmcia_device *link = lp->p_dev;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u16 opts = SetRxFilter | RxStation | RxBroadcast;
+ 
+     if (!pcmcia_dev_present(link)) return;
+@@ -924,7 +924,7 @@ static int el3_close(struct net_device *dev)
+ {
+     struct el3_private *lp = netdev_priv(dev);
+     struct pcmcia_device *link = lp->p_dev;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     
+     DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
+ 
 diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
-index 8d910a3..6d342f6 100644
+index 8d910a3..e8a63e4 100644
 --- a/drivers/net/pcmcia/axnet_cs.c
 +++ b/drivers/net/pcmcia/axnet_cs.c
+@@ -96,8 +96,8 @@ static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
+ static void ei_watchdog(u_long arg);
+ static void axnet_reset_8390(struct net_device *dev);
+ 
+-static int mdio_read(kio_addr_t addr, int phy_id, int loc);
+-static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value);
++static int mdio_read(unsigned int addr, int phy_id, int loc);
++static void mdio_write(unsigned int addr, int phy_id, int loc, int value);
+ 
+ static void get_8390_hdr(struct net_device *,
+ 			 struct e8390_pkt_hdr *, int);
+@@ -203,7 +203,7 @@ static void axnet_detach(struct pcmcia_device *link)
+ static int get_prom(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int i, j;
+ 
+     /* This is based on drivers/net/ne.c */
+@@ -473,7 +473,7 @@ static int axnet_resume(struct pcmcia_device *link)
+ #define MDIO_MASK		0x0f
+ #define MDIO_ENB_IN		0x02
+ 
+-static void mdio_sync(kio_addr_t addr)
++static void mdio_sync(unsigned int addr)
+ {
+     int bits;
+     for (bits = 0; bits < 32; bits++) {
+@@ -482,7 +482,7 @@ static void mdio_sync(kio_addr_t addr)
+     }
+ }
+ 
+-static int mdio_read(kio_addr_t addr, int phy_id, int loc)
++static int mdio_read(unsigned int addr, int phy_id, int loc)
+ {
+     u_int cmd = (0xf6<<10)|(phy_id<<5)|loc;
+     int i, retval = 0;
+@@ -501,7 +501,7 @@ static int mdio_read(kio_addr_t addr, int phy_id, int loc)
+     return (retval>>1) & 0xffff;
+ }
+ 
+-static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
++static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
+ {
+     u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+     int i;
+@@ -575,7 +575,7 @@ static int axnet_close(struct net_device *dev)
+ 
+ static void axnet_reset_8390(struct net_device *dev)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+     int i;
+ 
+     ei_status.txing = ei_status.dmaing = 0;
+@@ -610,8 +610,8 @@ static void ei_watchdog(u_long arg)
+ {
+     struct net_device *dev = (struct net_device *)(arg);
+     axnet_dev_t *info = PRIV(dev);
+-    kio_addr_t nic_base = dev->base_addr;
+-    kio_addr_t mii_addr = nic_base + AXNET_MII_EEP;
++    unsigned int nic_base = dev->base_addr;
++    unsigned int mii_addr = nic_base + AXNET_MII_EEP;
+     u_short link;
+ 
+     if (!netif_device_present(dev)) goto reschedule;
+@@ -681,7 +681,7 @@ static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+     axnet_dev_t *info = PRIV(dev);
+     u16 *data = (u16 *)&rq->ifr_ifru;
+-    kio_addr_t mii_addr = dev->base_addr + AXNET_MII_EEP;
++    unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
+     switch (cmd) {
+     case SIOCGMIIPHY:
+ 	data[0] = info->phy_id;
+@@ -703,7 +703,7 @@ static void get_8390_hdr(struct net_device *dev,
+ 			 struct e8390_pkt_hdr *hdr,
+ 			 int ring_page)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+ 
+     outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+     outb_p(ring_page, nic_base + EN0_RSARHI);
+@@ -721,7 +721,7 @@ static void get_8390_hdr(struct net_device *dev,
+ static void block_input(struct net_device *dev, int count,
+ 			struct sk_buff *skb, int ring_offset)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+     int xfer_count = count;
+     char *buf = skb->data;
+ 
+@@ -744,7 +744,7 @@ static void block_input(struct net_device *dev, int count,
+ static void block_output(struct net_device *dev, int count,
+ 			 const u_char *buf, const int start_page)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+ 
+ #ifdef PCMCIA_DEBUG
+     if (ei_debug > 4)
+@@ -991,7 +991,7 @@ static int ax_open(struct net_device *dev)
+  *
+  * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
+  */
+-int ax_close(struct net_device *dev)
++static int ax_close(struct net_device *dev)
+ {
+ 	unsigned long flags;
+ 
+@@ -1014,7 +1014,7 @@ int ax_close(struct net_device *dev)
+  * completed (or failed) - i.e. never posted a Tx related interrupt.
+  */
+ 
+-void ei_tx_timeout(struct net_device *dev)
++static void ei_tx_timeout(struct net_device *dev)
+ {
+ 	long e8390_base = dev->base_addr;
+ 	struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
 @@ -1040,15 +1040,13 @@ void ei_tx_timeout(struct net_device *dev)
  
  	/* Ugly but a reset can be slow, yet must be protected */
@@ -564592,7 +620400,7 @@
  	netif_wake_queue(dev);
  }
      
-@@ -1085,9 +1083,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+@@ -1085,14 +1083,12 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
  	 *	Slow phase with lock held.
  	 */
  	 
@@ -564603,6 +620411,13 @@
  	
  	ei_local->irqlock = 1;
  
+-	send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
+-	
++	send_length = max(length, ETH_ZLEN);
++
+ 	/*
+ 	 * We have two Tx slots available for use. Find the first free
+ 	 * slot, and then perform some sanity checks. With two Tx bufs,
 @@ -1125,8 +1121,7 @@ static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
  		ei_local->irqlock = 0;
  		netif_stop_queue(dev);
@@ -564624,10 +620439,47 @@
  	dev_kfree_skb (skb);
  	ei_local->stat.tx_bytes += send_length;
 diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
-index 8c719b4..949c6df 100644
+index 8c719b4..8f328a0 100644
 --- a/drivers/net/pcmcia/fmvj18x_cs.c
 +++ b/drivers/net/pcmcia/fmvj18x_cs.c
-@@ -731,18 +731,13 @@ module_exit(exit_fmvj18x_cs);
+@@ -298,7 +298,8 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
+ static int mfc_try_io_port(struct pcmcia_device *link)
+ {
+     int i, ret;
+-    static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
++    static const unsigned int serial_base[5] =
++	{ 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ 
+     for (i = 0; i < 5; i++) {
+ 	link->io.BasePort2 = serial_base[i];
+@@ -316,7 +317,7 @@ static int mfc_try_io_port(struct pcmcia_device *link)
+ static int ungermann_try_io_port(struct pcmcia_device *link)
+ {
+     int ret;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     /*
+ 	Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
+ 	0x380,0x3c0 only for ioport.
+@@ -342,7 +343,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
+     cisparse_t parse;
+     u_short buf[32];
+     int i, last_fn = 0, last_ret = 0, ret;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     cardtype_t cardtype;
+     char *card_name = "unknown";
+     u_char *node_id;
+@@ -610,7 +611,7 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
+     u_char __iomem *base;
+     int i, j;
+     struct net_device *dev = link->priv;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+ 
+     /* Allocate a small memory window */
+     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
+@@ -731,18 +732,13 @@ module_exit(exit_fmvj18x_cs);
  
  /*====================================================================*/
  
@@ -564636,7 +620488,8 @@
  {
      struct net_device *dev = dev_id;
      local_info_t *lp = netdev_priv(dev);
-     kio_addr_t ioaddr;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
      unsigned short tx_stat, rx_stat;
  
 -    if (lp == NULL) {
@@ -564647,8 +620500,185 @@
      ioaddr = dev->base_addr;
  
      /* avoid multiple interrupts */
+@@ -794,7 +790,7 @@ static irqreturn_t fjn_interrupt(int irq, void *dev_id)
+ static void fjn_tx_timeout(struct net_device *dev)
+ {
+     struct local_info_t *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
+ 	   dev->name, htons(inw(ioaddr + TX_STATUS)),
+@@ -824,7 +820,7 @@ static void fjn_tx_timeout(struct net_device *dev)
+ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+     struct local_info_t *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     short length = skb->len;
+     
+     if (length < ETH_ZLEN)
+@@ -897,7 +893,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ static void fjn_reset(struct net_device *dev)
+ {
+     struct local_info_t *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int i;
+ 
+     DEBUG(4, "fjn_reset(%s) called.\n",dev->name);
+@@ -976,7 +972,7 @@ static void fjn_reset(struct net_device *dev)
+ static void fjn_rx(struct net_device *dev)
+ {
+     struct local_info_t *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int boguscount = 10;	/* 5 -> 10: by agy 19940922 */
+ 
+     DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n",
+@@ -1130,7 +1126,7 @@ static int fjn_close(struct net_device *dev)
+ {
+     struct local_info_t *lp = netdev_priv(dev);
+     struct pcmcia_device *link = lp->p_dev;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     DEBUG(4, "fjn_close('%s').\n", dev->name);
+ 
+@@ -1173,7 +1169,7 @@ static struct net_device_stats *fjn_get_stats(struct net_device *dev)
+ 
+ static void set_rx_mode(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_char mc_filter[8];		 /* Multicast hash filter */
+     u_long flags;
+     int i;
+@@ -1202,8 +1198,7 @@ static void set_rx_mode(struct net_device *dev)
+ 	outb(1, ioaddr + RX_MODE);	/* Ignore almost all multicasts. */
+     } else {
+ 	struct dev_mc_list *mclist;
+-	int i;
+-	
++
+ 	memset(mc_filter, 0, sizeof(mc_filter));
+ 	for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ 	     i++, mclist = mclist->next) {
+diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
+index a355a93..cfcbea9 100644
+--- a/drivers/net/pcmcia/nmclan_cs.c
++++ b/drivers/net/pcmcia/nmclan_cs.c
+@@ -518,7 +518,7 @@ mace_read
+ 	assuming that during normal operation, the MACE is always in
+ 	bank 0.
+ ---------------------------------------------------------------------------- */
+-static int mace_read(mace_private *lp, kio_addr_t ioaddr, int reg)
++static int mace_read(mace_private *lp, unsigned int ioaddr, int reg)
+ {
+   int data = 0xFF;
+   unsigned long flags;
+@@ -545,7 +545,8 @@ mace_write
+ 	are assuming that during normal operation, the MACE is always in
+ 	bank 0.
+ ---------------------------------------------------------------------------- */
+-static void mace_write(mace_private *lp, kio_addr_t ioaddr, int reg, int data)
++static void mace_write(mace_private *lp, unsigned int ioaddr, int reg,
++		       int data)
+ {
+   unsigned long flags;
+ 
+@@ -567,7 +568,7 @@ static void mace_write(mace_private *lp, kio_addr_t ioaddr, int reg, int data)
+ mace_init
+ 	Resets the MACE chip.
+ ---------------------------------------------------------------------------- */
+-static int mace_init(mace_private *lp, kio_addr_t ioaddr, char *enet_addr)
++static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr)
+ {
+   int i;
+   int ct = 0;
+@@ -657,7 +658,7 @@ static int nmclan_config(struct pcmcia_device *link)
+   tuple_t tuple;
+   u_char buf[64];
+   int i, last_ret, last_fn;
+-  kio_addr_t ioaddr;
++  unsigned int ioaddr;
+   DECLARE_MAC_BUF(mac);
+ 
+   DEBUG(0, "nmclan_config(0x%p)\n", link);
+@@ -839,7 +840,7 @@ mace_open
+ ---------------------------------------------------------------------------- */
+ static int mace_open(struct net_device *dev)
+ {
+-  kio_addr_t ioaddr = dev->base_addr;
++  unsigned int ioaddr = dev->base_addr;
+   mace_private *lp = netdev_priv(dev);
+   struct pcmcia_device *link = lp->p_dev;
+ 
+@@ -862,7 +863,7 @@ mace_close
+ ---------------------------------------------------------------------------- */
+ static int mace_close(struct net_device *dev)
+ {
+-  kio_addr_t ioaddr = dev->base_addr;
++  unsigned int ioaddr = dev->base_addr;
+   mace_private *lp = netdev_priv(dev);
+   struct pcmcia_device *link = lp->p_dev;
+ 
+@@ -935,7 +936,7 @@ static void mace_tx_timeout(struct net_device *dev)
+ static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+   mace_private *lp = netdev_priv(dev);
+-  kio_addr_t ioaddr = dev->base_addr;
++  unsigned int ioaddr = dev->base_addr;
+ 
+   netif_stop_queue(dev);
+ 
+@@ -996,7 +997,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
+ {
+   struct net_device *dev = (struct net_device *) dev_id;
+   mace_private *lp = netdev_priv(dev);
+-  kio_addr_t ioaddr;
++  unsigned int ioaddr;
+   int status;
+   int IntrCnt = MACE_MAX_IR_ITERATIONS;
+ 
+@@ -1140,7 +1141,7 @@ mace_rx
+ static int mace_rx(struct net_device *dev, unsigned char RxCnt)
+ {
+   mace_private *lp = netdev_priv(dev);
+-  kio_addr_t ioaddr = dev->base_addr;
++  unsigned int ioaddr = dev->base_addr;
+   unsigned char rx_framecnt;
+   unsigned short rx_status;
+ 
+@@ -1302,7 +1303,7 @@ update_stats
+ 	card's SRAM fast enough.  If this happens, something is
+ 	seriously wrong with the hardware.
+ ---------------------------------------------------------------------------- */
+-static void update_stats(kio_addr_t ioaddr, struct net_device *dev)
++static void update_stats(unsigned int ioaddr, struct net_device *dev)
+ {
+   mace_private *lp = netdev_priv(dev);
+ 
+@@ -1448,7 +1449,7 @@ static void restore_multicast_list(struct net_device *dev)
+   mace_private *lp = netdev_priv(dev);
+   int num_addrs = lp->multicast_num_addrs;
+   int *ladrf = lp->multicast_ladrf;
+-  kio_addr_t ioaddr = dev->base_addr;
++  unsigned int ioaddr = dev->base_addr;
+   int i;
+ 
+   DEBUG(2, "%s: restoring Rx mode to %d addresses.\n",
+@@ -1540,7 +1541,7 @@ static void set_multicast_list(struct net_device *dev)
+ 
+ static void restore_multicast_list(struct net_device *dev)
+ {
+-  kio_addr_t ioaddr = dev->base_addr;
++  unsigned int ioaddr = dev->base_addr;
+   mace_private *lp = netdev_priv(dev);
+ 
+   DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name,
 diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
-index 51bbd58..9ba56aa 100644
+index 51bbd58..6323988 100644
 --- a/drivers/net/pcmcia/pcnet_cs.c
 +++ b/drivers/net/pcmcia/pcnet_cs.c
 @@ -38,6 +38,7 @@
@@ -564659,6 +620689,196 @@
  #include "../8390.h"
  
  #include <pcmcia/cs_types.h>
+@@ -348,7 +349,7 @@ static hw_info_t *get_hwinfo(struct pcmcia_device *link)
+ static hw_info_t *get_prom(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_char prom[32];
+     int i, j;
+ 
+@@ -424,7 +425,7 @@ static hw_info_t *get_dl10019(struct pcmcia_device *link)
+ static hw_info_t *get_ax88190(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int i, j;
+ 
+     /* Not much of a test, but the alternatives are messy */
+@@ -520,7 +521,7 @@ static int pcnet_config(struct pcmcia_device *link)
+     int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
+     int has_shmem = 0;
+     u_short buf[64];
+-    hw_info_t *hw_info;
++    hw_info_t *local_hw_info;
+     DECLARE_MAC_BUF(mac);
+ 
+     DEBUG(0, "pcnet_config(0x%p)\n", link);
+@@ -589,23 +590,23 @@ static int pcnet_config(struct pcmcia_device *link)
+ 	dev->if_port = 0;
+     }
+ 
+-    hw_info = get_hwinfo(link);
+-    if (hw_info == NULL)
+-	hw_info = get_prom(link);
+-    if (hw_info == NULL)
+-	hw_info = get_dl10019(link);
+-    if (hw_info == NULL)
+-	hw_info = get_ax88190(link);
+-    if (hw_info == NULL)
+-	hw_info = get_hwired(link);
+-
+-    if (hw_info == NULL) {
++    local_hw_info = get_hwinfo(link);
++    if (local_hw_info == NULL)
++	local_hw_info = get_prom(link);
++    if (local_hw_info == NULL)
++	local_hw_info = get_dl10019(link);
++    if (local_hw_info == NULL)
++	local_hw_info = get_ax88190(link);
++    if (local_hw_info == NULL)
++	local_hw_info = get_hwired(link);
++
++    if (local_hw_info == NULL) {
+ 	printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
+ 	       " address for io base %#3lx\n", dev->base_addr);
+ 	goto failed;
+     }
+ 
+-    info->flags = hw_info->flags;
++    info->flags = local_hw_info->flags;
+     /* Check for user overrides */
+     info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
+     if ((link->manf_id == MANFID_SOCKET) &&
+@@ -755,7 +756,7 @@ static int pcnet_resume(struct pcmcia_device *link)
+ #define MDIO_DATA_READ		0x10
+ #define MDIO_MASK		0x0f
+ 
+-static void mdio_sync(kio_addr_t addr)
++static void mdio_sync(unsigned int addr)
+ {
+     int bits, mask = inb(addr) & MDIO_MASK;
+     for (bits = 0; bits < 32; bits++) {
+@@ -764,7 +765,7 @@ static void mdio_sync(kio_addr_t addr)
+     }
+ }
+ 
+-static int mdio_read(kio_addr_t addr, int phy_id, int loc)
++static int mdio_read(unsigned int addr, int phy_id, int loc)
+ {
+     u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+     int i, retval = 0, mask = inb(addr) & MDIO_MASK;
+@@ -783,7 +784,7 @@ static int mdio_read(kio_addr_t addr, int phy_id, int loc)
+     return (retval>>1) & 0xffff;
+ }
+ 
+-static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
++static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
+ {
+     u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+     int i, mask = inb(addr) & MDIO_MASK;
+@@ -817,10 +818,10 @@ static void mdio_write(kio_addr_t addr, int phy_id, int loc, int value)
+ 
+ #define DL19FDUPLX	0x0400	/* DL10019 Full duplex mode */
+ 
+-static int read_eeprom(kio_addr_t ioaddr, int location)
++static int read_eeprom(unsigned int ioaddr, int location)
+ {
+     int i, retval = 0;
+-    kio_addr_t ee_addr = ioaddr + DLINK_EEPROM;
++    unsigned int ee_addr = ioaddr + DLINK_EEPROM;
+     int read_cmd = location | (EE_READ_CMD << 8);
+ 
+     outb(0, ee_addr);
+@@ -851,10 +852,10 @@ static int read_eeprom(kio_addr_t ioaddr, int location)
+     In ASIC mode, EE_ADOT is used to output the data to the ASIC.
+ */
+ 
+-static void write_asic(kio_addr_t ioaddr, int location, short asic_data)
++static void write_asic(unsigned int ioaddr, int location, short asic_data)
+ {
+ 	int i;
+-	kio_addr_t ee_addr = ioaddr + DLINK_EEPROM;
++	unsigned int ee_addr = ioaddr + DLINK_EEPROM;
+ 	short dataval;
+ 	int read_cmd = location | (EE_READ_CMD << 8);
+ 
+@@ -896,7 +897,7 @@ static void write_asic(kio_addr_t ioaddr, int location, short asic_data)
+ 
+ static void set_misc_reg(struct net_device *dev)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+     pcnet_dev_t *info = PRIV(dev);
+     u_char tmp;
+ 
+@@ -935,7 +936,7 @@ static void set_misc_reg(struct net_device *dev)
+ static void mii_phy_probe(struct net_device *dev)
+ {
+     pcnet_dev_t *info = PRIV(dev);
+-    kio_addr_t mii_addr = dev->base_addr + DLINK_GPIO;
++    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
+     int i;
+     u_int tmp, phyid;
+ 
+@@ -1013,7 +1014,7 @@ static int pcnet_close(struct net_device *dev)
+ 
+ static void pcnet_reset_8390(struct net_device *dev)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+     int i;
+ 
+     ei_status.txing = ei_status.dmaing = 0;
+@@ -1073,8 +1074,8 @@ static void ei_watchdog(u_long arg)
+ {
+     struct net_device *dev = (struct net_device *)arg;
+     pcnet_dev_t *info = PRIV(dev);
+-    kio_addr_t nic_base = dev->base_addr;
+-    kio_addr_t mii_addr = nic_base + DLINK_GPIO;
++    unsigned int nic_base = dev->base_addr;
++    unsigned int mii_addr = nic_base + DLINK_GPIO;
+     u_short link;
+ 
+     if (!netif_device_present(dev)) goto reschedule;
+@@ -1176,7 +1177,7 @@ static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+     pcnet_dev_t *info = PRIV(dev);
+     u16 *data = (u16 *)&rq->ifr_ifru;
+-    kio_addr_t mii_addr = dev->base_addr + DLINK_GPIO;
++    unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
+     switch (cmd) {
+     case SIOCGMIIPHY:
+ 	data[0] = info->phy_id;
+@@ -1198,7 +1199,7 @@ static void dma_get_8390_hdr(struct net_device *dev,
+ 			     struct e8390_pkt_hdr *hdr,
+ 			     int ring_page)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+ 
+     if (ei_status.dmaing) {
+ 	printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
+@@ -1229,7 +1230,7 @@ static void dma_get_8390_hdr(struct net_device *dev,
+ static void dma_block_input(struct net_device *dev, int count,
+ 			    struct sk_buff *skb, int ring_offset)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+     int xfer_count = count;
+     char *buf = skb->data;
+ 
+@@ -1284,7 +1285,7 @@ static void dma_block_input(struct net_device *dev, int count,
+ static void dma_block_output(struct net_device *dev, int count,
+ 			     const u_char *buf, const int start_page)
+ {
+-    kio_addr_t nic_base = dev->base_addr;
++    unsigned int nic_base = dev->base_addr;
+     pcnet_dev_t *info = PRIV(dev);
+ #ifdef PCMCIA_DEBUG
+     int retries = 0;
 @@ -1484,8 +1485,7 @@ static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
  	window_size = 32 * 1024;
  
@@ -564669,6 +620889,477 @@
  
      /* Allocate a memory window */
      req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
+diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
+index c9868e9..f18eca9 100644
+--- a/drivers/net/pcmcia/smc91c92_cs.c
++++ b/drivers/net/pcmcia/smc91c92_cs.c
+@@ -295,7 +295,7 @@ static int s9k_config(struct net_device *dev, struct ifmap *map);
+ static void smc_set_xcvr(struct net_device *dev, int if_port);
+ static void smc_reset(struct net_device *dev);
+ static void media_check(u_long arg);
+-static void mdio_sync(kio_addr_t addr);
++static void mdio_sync(unsigned int addr);
+ static int mdio_read(struct net_device *dev, int phy_id, int loc);
+ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
+ static int smc_link_ok(struct net_device *dev);
+@@ -601,8 +601,8 @@ static void mot_config(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
+-    kio_addr_t iouart = link->io.BasePort2;
++    unsigned int ioaddr = dev->base_addr;
++    unsigned int iouart = link->io.BasePort2;
+ 
+     /* Set UART base address and force map with COR bit 1 */
+     writeb(iouart & 0xff,        smc->base + MOT_UART + CISREG_IOBASE_0);
+@@ -621,7 +621,7 @@ static void mot_config(struct pcmcia_device *link)
+ static int mot_setup(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int i, wait, loop;
+     u_int addr;
+ 
+@@ -754,7 +754,7 @@ free_cfg_mem:
+ static int osi_config(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+-    static const kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
++    static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+     int i, j;
+ 
+     link->conf.Attributes |= CONF_ENABLE_SPKR;
+@@ -900,7 +900,7 @@ static int smc91c92_resume(struct pcmcia_device *link)
+ static int check_sig(struct pcmcia_device *link)
+ {
+     struct net_device *dev = link->priv;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int width;
+     u_short s;
+ 
+@@ -960,7 +960,7 @@ static int smc91c92_config(struct pcmcia_device *link)
+     struct smc_private *smc = netdev_priv(dev);
+     char *name;
+     int i, j, rev;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     u_long mir;
+     DECLARE_MAC_BUF(mac);
+ 
+@@ -1136,7 +1136,7 @@ static void smc91c92_release(struct pcmcia_device *link)
+ #define MDIO_DATA_WRITE1	(MDIO_DIR_WRITE | MDIO_DATA_OUT)
+ #define MDIO_DATA_READ		0x02
+ 
+-static void mdio_sync(kio_addr_t addr)
++static void mdio_sync(unsigned int addr)
+ {
+     int bits;
+     for (bits = 0; bits < 32; bits++) {
+@@ -1147,7 +1147,7 @@ static void mdio_sync(kio_addr_t addr)
+ 
+ static int mdio_read(struct net_device *dev, int phy_id, int loc)
+ {
+-    kio_addr_t addr = dev->base_addr + MGMT;
++    unsigned int addr = dev->base_addr + MGMT;
+     u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+     int i, retval = 0;
+ 
+@@ -1167,7 +1167,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int loc)
+ 
+ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
+ {
+-    kio_addr_t addr = dev->base_addr + MGMT;
++    unsigned int addr = dev->base_addr + MGMT;
+     u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+     int i;
+ 
+@@ -1193,7 +1193,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
+ #ifdef PCMCIA_DEBUG
+ static void smc_dump(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_short i, w, save;
+     save = inw(ioaddr + BANK_SELECT);
+     for (w = 0; w < 4; w++) {
+@@ -1248,7 +1248,7 @@ static int smc_close(struct net_device *dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+     struct pcmcia_device *link = smc->p_dev;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     DEBUG(0, "%s: smc_close(), status %4.4x.\n",
+ 	  dev->name, inw(ioaddr + BANK_SELECT));
+@@ -1285,7 +1285,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+     struct sk_buff *skb = smc->saved_skb;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_char packet_no;
+ 
+     if (!skb) {
+@@ -1349,7 +1349,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
+ static void smc_tx_timeout(struct net_device *dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
+ 	   "Tx_status %2.2x status %4.4x.\n",
+@@ -1364,7 +1364,7 @@ static void smc_tx_timeout(struct net_device *dev)
+ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_short num_pages;
+     short time_out, ir;
+     unsigned long flags;
+@@ -1434,7 +1434,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ static void smc_tx_err(struct net_device * dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int saved_packet = inw(ioaddr + PNR_ARR) & 0xff;
+     int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
+     int tx_status;
+@@ -1478,7 +1478,7 @@ static void smc_tx_err(struct net_device * dev)
+ static void smc_eph_irq(struct net_device *dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_short card_stats, ephs;
+ 
+     SMC_SELECT_BANK(0);
+@@ -1513,7 +1513,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id)
+ {
+     struct net_device *dev = dev_id;
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     u_short saved_bank, saved_pointer, mask, status;
+     unsigned int handled = 1;
+     char bogus_cnt = INTR_WORK;		/* Work we are willing to do. */
+@@ -1633,7 +1633,7 @@ irq_done:
+ static void smc_rx(struct net_device *dev)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int rx_status;
+     int packet_length;	/* Caution: not frame length, rather words
+ 			   to transfer from the chip. */
+@@ -1738,7 +1738,7 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
+ 
+ static void set_rx_mode(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     struct smc_private *smc = netdev_priv(dev);
+     u_int multicast_table[ 2 ] = { 0, };
+     unsigned long flags;
+@@ -1804,7 +1804,7 @@ static int s9k_config(struct net_device *dev, struct ifmap *map)
+ static void smc_set_xcvr(struct net_device *dev, int if_port)
+ {
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_short saved_bank;
+ 
+     saved_bank = inw(ioaddr + BANK_SELECT);
+@@ -1827,7 +1827,7 @@ static void smc_set_xcvr(struct net_device *dev, int if_port)
+ 
+ static void smc_reset(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     struct smc_private *smc = netdev_priv(dev);
+     int i;
+ 
+@@ -1904,7 +1904,7 @@ static void media_check(u_long arg)
+ {
+     struct net_device *dev = (struct net_device *) arg;
+     struct smc_private *smc = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u_short i, media, saved_bank;
+     u_short link;
+     unsigned long flags;
+@@ -2021,7 +2021,7 @@ reschedule:
+ 
+ static int smc_link_ok(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     struct smc_private *smc = netdev_priv(dev);
+ 
+     if (smc->cfg & CFG_MII_SELECT) {
+@@ -2035,7 +2035,7 @@ static int smc_link_ok(struct net_device *dev)
+ static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+ {
+     u16 tmp;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     ecmd->supported = (SUPPORTED_TP | SUPPORTED_AUI |
+ 	SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full);
+@@ -2057,7 +2057,7 @@ static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+ static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+ {
+     u16 tmp;
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     if (ecmd->speed != SPEED_10)
+     	return -EINVAL;
+@@ -2100,7 +2100,7 @@ static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
+ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ {
+ 	struct smc_private *smc = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	u16 saved_bank = inw(ioaddr + BANK_SELECT);
+ 	int ret;
+ 
+@@ -2118,7 +2118,7 @@ static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ {
+ 	struct smc_private *smc = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	u16 saved_bank = inw(ioaddr + BANK_SELECT);
+ 	int ret;
+ 
+@@ -2136,7 +2136,7 @@ static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+ static u32 smc_get_link(struct net_device *dev)
+ {
+ 	struct smc_private *smc = netdev_priv(dev);
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 	u16 saved_bank = inw(ioaddr + BANK_SELECT);
+ 	u32 ret;
+ 
+@@ -2164,7 +2164,7 @@ static int smc_nway_reset(struct net_device *dev)
+ {
+ 	struct smc_private *smc = netdev_priv(dev);
+ 	if (smc->cfg & CFG_MII_SELECT) {
+-		kio_addr_t ioaddr = dev->base_addr;
++		unsigned int ioaddr = dev->base_addr;
+ 		u16 saved_bank = inw(ioaddr + BANK_SELECT);
+ 		int res;
+ 
+@@ -2196,7 +2196,7 @@ static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+ 	struct mii_ioctl_data *mii = if_mii(rq);
+ 	int rc = 0;
+ 	u16 saved_bank;
+-	kio_addr_t ioaddr = dev->base_addr;
++	unsigned int ioaddr = dev->base_addr;
+ 
+ 	if (!netif_running(dev))
+ 		return -EINVAL;
+diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
+index 1f09bea..d041f83 100644
+--- a/drivers/net/pcmcia/xirc2ps_cs.c
++++ b/drivers/net/pcmcia/xirc2ps_cs.c
+@@ -273,12 +273,12 @@ INT_MODULE_PARM(lockup_hack,	0);  /* anti lockup hack */
+ static unsigned maxrx_bytes = 22000;
+ 
+ /* MII management prototypes */
+-static void mii_idle(kio_addr_t ioaddr);
+-static void mii_putbit(kio_addr_t ioaddr, unsigned data);
+-static int  mii_getbit(kio_addr_t ioaddr);
+-static void mii_wbits(kio_addr_t ioaddr, unsigned data, int len);
+-static unsigned mii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg);
+-static void mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg,
++static void mii_idle(unsigned int ioaddr);
++static void mii_putbit(unsigned int ioaddr, unsigned data);
++static int  mii_getbit(unsigned int ioaddr);
++static void mii_wbits(unsigned int ioaddr, unsigned data, int len);
++static unsigned mii_rd(unsigned int ioaddr, u_char phyaddr, u_char phyreg);
++static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg,
+ 		   unsigned data, int len);
+ 
+ /*
+@@ -403,7 +403,7 @@ next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
+ static void
+ PrintRegisters(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     if (pc_debug > 1) {
+ 	int i, page;
+@@ -439,7 +439,7 @@ PrintRegisters(struct net_device *dev)
+  * Turn around for read
+  */
+ static void
+-mii_idle(kio_addr_t ioaddr)
++mii_idle(unsigned int ioaddr)
+ {
+     PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */
+     udelay(1);
+@@ -451,7 +451,7 @@ mii_idle(kio_addr_t ioaddr)
+  * Write a bit to MDI/O
+  */
+ static void
+-mii_putbit(kio_addr_t ioaddr, unsigned data)
++mii_putbit(unsigned int ioaddr, unsigned data)
+ {
+   #if 1
+     if (data) {
+@@ -484,7 +484,7 @@ mii_putbit(kio_addr_t ioaddr, unsigned data)
+  * Get a bit from MDI/O
+  */
+ static int
+-mii_getbit(kio_addr_t ioaddr)
++mii_getbit(unsigned int ioaddr)
+ {
+     unsigned d;
+ 
+@@ -497,7 +497,7 @@ mii_getbit(kio_addr_t ioaddr)
+ }
+ 
+ static void
+-mii_wbits(kio_addr_t ioaddr, unsigned data, int len)
++mii_wbits(unsigned int ioaddr, unsigned data, int len)
+ {
+     unsigned m = 1 << (len-1);
+     for (; m; m >>= 1)
+@@ -505,7 +505,7 @@ mii_wbits(kio_addr_t ioaddr, unsigned data, int len)
+ }
+ 
+ static unsigned
+-mii_rd(kio_addr_t ioaddr,	u_char phyaddr, u_char phyreg)
++mii_rd(unsigned int ioaddr,	u_char phyaddr, u_char phyreg)
+ {
+     int i;
+     unsigned data=0, m;
+@@ -527,7 +527,8 @@ mii_rd(kio_addr_t ioaddr,	u_char phyaddr, u_char phyreg)
+ }
+ 
+ static void
+-mii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len)
++mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg, unsigned data,
++       int len)
+ {
+     int i;
+ 
+@@ -726,7 +727,7 @@ xirc2ps_config(struct pcmcia_device * link)
+     local_info_t *local = netdev_priv(dev);
+     tuple_t tuple;
+     cisparse_t parse;
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     int err, i;
+     u_char buf[64];
+     cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
+@@ -1104,7 +1105,7 @@ xirc2ps_interrupt(int irq, void *dev_id)
+ {
+     struct net_device *dev = (struct net_device *)dev_id;
+     local_info_t *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr;
++    unsigned int ioaddr;
+     u_char saved_page;
+     unsigned bytes_rcvd;
+     unsigned int_status, eth_status, rx_status, tx_status;
+@@ -1209,7 +1210,7 @@ xirc2ps_interrupt(int irq, void *dev_id)
+ 		    unsigned i;
+ 		    u_long *p = skb_put(skb, pktlen);
+ 		    register u_long a;
+-		    kio_addr_t edpreg = ioaddr+XIRCREG_EDP-2;
++		    unsigned int edpreg = ioaddr+XIRCREG_EDP-2;
+ 		    for (i=0; i < len ; i += 4, p++) {
+ 			a = inl(edpreg);
+ 			__asm__("rorl $16,%0\n\t"
+@@ -1346,7 +1347,7 @@ static int
+ do_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+     local_info_t *lp = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     int okay;
+     unsigned freespace;
+     unsigned pktlen = skb->len;
+@@ -1415,7 +1416,7 @@ do_get_stats(struct net_device *dev)
+ static void
+ set_addresses(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     local_info_t *lp = netdev_priv(dev);
+     struct dev_mc_list *dmi = dev->mc_list;
+     unsigned char *addr;
+@@ -1459,7 +1460,7 @@ set_addresses(struct net_device *dev)
+ static void
+ set_multicast_list(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     SelectPage(0x42);
+     if (dev->flags & IFF_PROMISC) { /* snoop */
+@@ -1543,7 +1544,7 @@ static int
+ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+ {
+     local_info_t *local = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     u16 *data = (u16 *)&rq->ifr_ifru;
+ 
+     DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n",
+@@ -1575,7 +1576,7 @@ static void
+ hardreset(struct net_device *dev)
+ {
+     local_info_t *local = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     SelectPage(4);
+     udelay(1);
+@@ -1592,7 +1593,7 @@ static void
+ do_reset(struct net_device *dev, int full)
+ {
+     local_info_t *local = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     unsigned value;
+ 
+     DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full);
+@@ -1753,7 +1754,7 @@ static int
+ init_mii(struct net_device *dev)
+ {
+     local_info_t *local = netdev_priv(dev);
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     unsigned control, status, linkpartner;
+     int i;
+ 
+@@ -1826,7 +1827,7 @@ static void
+ do_powerdown(struct net_device *dev)
+ {
+ 
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+ 
+     DEBUG(0, "do_powerdown(%p)\n", dev);
+ 
+@@ -1838,7 +1839,7 @@ do_powerdown(struct net_device *dev)
+ static int
+ do_stop(struct net_device *dev)
+ {
+-    kio_addr_t ioaddr = dev->base_addr;
++    unsigned int ioaddr = dev->base_addr;
+     local_info_t *lp = netdev_priv(dev);
+     struct pcmcia_device *link = lp->p_dev;
+ 
 diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
 index 90498ff..c4b74e9 100644
 --- a/drivers/net/pcnet32.c
@@ -564683,12 +621374,18 @@
  #define PCNET32_NUM_REGS 136
  
 diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
-index 54b2ba9..7fe03ce 100644
+index 54b2ba9..f4ca059 100644
 --- a/drivers/net/phy/Kconfig
 +++ b/drivers/net/phy/Kconfig
-@@ -61,34 +61,12 @@ config ICPLUS_PHY
+@@ -60,35 +60,18 @@ config ICPLUS_PHY
+ 	---help---
  	  Currently supports the IP175C PHY.
  
++config REALTEK_PHY
++	tristate "Drivers for Realtek PHYs"
++	---help---
++	  Supports the Realtek 821x PHY.
++
  config FIXED_PHY
 -	tristate "Drivers for PHY emulation on fixed speed/link"
 +	bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
@@ -564726,6 +621423,64 @@
  
  config MDIO_BITBANG
  	tristate "Support for bitbanged MDIO buses"
+diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
+index 3d6cc7b..5997d6e 100644
+--- a/drivers/net/phy/Makefile
++++ b/drivers/net/phy/Makefile
+@@ -12,5 +12,6 @@ obj-$(CONFIG_SMSC_PHY)		+= smsc.o
+ obj-$(CONFIG_VITESSE_PHY)	+= vitesse.o
+ obj-$(CONFIG_BROADCOM_PHY)	+= broadcom.o
+ obj-$(CONFIG_ICPLUS_PHY)	+= icplus.o
++obj-$(CONFIG_REALTEK_PHY)	+= realtek.o
+ obj-$(CONFIG_FIXED_PHY)		+= fixed.o
+ obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
+diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
+index 29666c8..5b80358 100644
+--- a/drivers/net/phy/broadcom.c
++++ b/drivers/net/phy/broadcom.c
+@@ -141,6 +141,20 @@ static struct phy_driver bcm5461_driver = {
+ 	.driver 	= { .owner = THIS_MODULE },
+ };
+ 
++static struct phy_driver bcm5482_driver = {
++    .phy_id		= 0x0143bcb0,
++	.phy_id_mask	= 0xfffffff0,
++	.name		= "Broadcom BCM5482",
++	.features	= PHY_GBIT_FEATURES,
++	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
++	.config_init	= bcm54xx_config_init,
++	.config_aneg	= genphy_config_aneg,
++	.read_status	= genphy_read_status,
++	.ack_interrupt	= bcm54xx_ack_interrupt,
++	.config_intr	= bcm54xx_config_intr,
++	.driver 	= { .owner = THIS_MODULE },
++};
++
+ static int __init broadcom_init(void)
+ {
+ 	int ret;
+@@ -154,8 +168,13 @@ static int __init broadcom_init(void)
+ 	ret = phy_driver_register(&bcm5461_driver);
+ 	if (ret)
+ 		goto out_5461;
++	ret = phy_driver_register(&bcm5482_driver);
++	if (ret)
++		goto out_5482;
+ 	return ret;
+ 
++out_5482:
++	phy_driver_unregister(&bcm5461_driver);
+ out_5461:
+ 	phy_driver_unregister(&bcm5421_driver);
+ out_5421:
+@@ -166,6 +185,7 @@ out_5411:
+ 
+ static void __exit broadcom_exit(void)
+ {
++	phy_driver_unregister(&bcm5482_driver);
+ 	phy_driver_unregister(&bcm5461_driver);
+ 	phy_driver_unregister(&bcm5421_driver);
+ 	phy_driver_unregister(&bcm5411_driver);
 diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
 index 5619182..73b6d39 100644
 --- a/drivers/net/phy/fixed.c
@@ -565261,6 +622016,352 @@
 -
 -module_init(fixed_init);
 -module_exit(fixed_exit);
+diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
+index c30196d..6e9f619 100644
+--- a/drivers/net/phy/mdio_bus.c
++++ b/drivers/net/phy/mdio_bus.c
+@@ -49,7 +49,7 @@ int mdiobus_register(struct mii_bus *bus)
+ 	int i;
+ 	int err = 0;
+ 
+-	spin_lock_init(&bus->mdio_lock);
++	mutex_init(&bus->mdio_lock);
+ 
+ 	if (NULL == bus || NULL == bus->name ||
+ 			NULL == bus->read ||
+diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
+index 7c9e6e3..12fccb1 100644
+--- a/drivers/net/phy/phy.c
++++ b/drivers/net/phy/phy.c
+@@ -26,7 +26,6 @@
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+-#include <linux/spinlock.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
+ #include <linux/mii.h>
+@@ -72,9 +71,11 @@ int phy_read(struct phy_device *phydev, u16 regnum)
+ 	int retval;
+ 	struct mii_bus *bus = phydev->bus;
+ 
+-	spin_lock_bh(&bus->mdio_lock);
++	BUG_ON(in_interrupt());
++
++	mutex_lock(&bus->mdio_lock);
+ 	retval = bus->read(bus, phydev->addr, regnum);
+-	spin_unlock_bh(&bus->mdio_lock);
++	mutex_unlock(&bus->mdio_lock);
+ 
+ 	return retval;
+ }
+@@ -95,9 +96,11 @@ int phy_write(struct phy_device *phydev, u16 regnum, u16 val)
+ 	int err;
+ 	struct mii_bus *bus = phydev->bus;
+ 
+-	spin_lock_bh(&bus->mdio_lock);
++	BUG_ON(in_interrupt());
++
++	mutex_lock(&bus->mdio_lock);
+ 	err = bus->write(bus, phydev->addr, regnum, val);
+-	spin_unlock_bh(&bus->mdio_lock);
++	mutex_unlock(&bus->mdio_lock);
+ 
+ 	return err;
+ }
+@@ -428,7 +431,7 @@ int phy_start_aneg(struct phy_device *phydev)
+ {
+ 	int err;
+ 
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 
+ 	if (AUTONEG_DISABLE == phydev->autoneg)
+ 		phy_sanitize_settings(phydev);
+@@ -449,13 +452,14 @@ int phy_start_aneg(struct phy_device *phydev)
+ 	}
+ 
+ out_unlock:
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 	return err;
+ }
+ EXPORT_SYMBOL(phy_start_aneg);
+ 
+ 
+ static void phy_change(struct work_struct *work);
++static void phy_state_machine(struct work_struct *work);
+ static void phy_timer(unsigned long data);
+ 
+ /**
+@@ -476,6 +480,7 @@ void phy_start_machine(struct phy_device *phydev,
+ {
+ 	phydev->adjust_state = handler;
+ 
++	INIT_WORK(&phydev->state_queue, phy_state_machine);
+ 	init_timer(&phydev->phy_timer);
+ 	phydev->phy_timer.function = &phy_timer;
+ 	phydev->phy_timer.data = (unsigned long) phydev;
+@@ -493,11 +498,12 @@ void phy_start_machine(struct phy_device *phydev,
+ void phy_stop_machine(struct phy_device *phydev)
+ {
+ 	del_timer_sync(&phydev->phy_timer);
++	cancel_work_sync(&phydev->state_queue);
+ 
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 	if (phydev->state > PHY_UP)
+ 		phydev->state = PHY_UP;
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 
+ 	phydev->adjust_state = NULL;
+ }
+@@ -541,9 +547,9 @@ static void phy_force_reduction(struct phy_device *phydev)
+  */
+ void phy_error(struct phy_device *phydev)
+ {
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 	phydev->state = PHY_HALTED;
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ }
+ 
+ /**
+@@ -705,10 +711,10 @@ static void phy_change(struct work_struct *work)
+ 	if (err)
+ 		goto phy_err;
+ 
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 	if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
+ 		phydev->state = PHY_CHANGELINK;
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 
+ 	atomic_dec(&phydev->irq_disable);
+ 	enable_irq(phydev->irq);
+@@ -735,7 +741,7 @@ phy_err:
+  */
+ void phy_stop(struct phy_device *phydev)
+ {
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 
+ 	if (PHY_HALTED == phydev->state)
+ 		goto out_unlock;
+@@ -751,7 +757,7 @@ void phy_stop(struct phy_device *phydev)
+ 	phydev->state = PHY_HALTED;
+ 
+ out_unlock:
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 
+ 	/*
+ 	 * Cannot call flush_scheduled_work() here as desired because
+@@ -773,7 +779,7 @@ out_unlock:
+  */
+ void phy_start(struct phy_device *phydev)
+ {
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 
+ 	switch (phydev->state) {
+ 		case PHY_STARTING:
+@@ -787,19 +793,26 @@ void phy_start(struct phy_device *phydev)
+ 		default:
+ 			break;
+ 	}
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ }
+ EXPORT_SYMBOL(phy_stop);
+ EXPORT_SYMBOL(phy_start);
+ 
+-/* PHY timer which handles the state machine */
+-static void phy_timer(unsigned long data)
++/**
++ * phy_state_machine - Handle the state machine
++ * @work: work_struct that describes the work to be done
++ *
++ * Description: Scheduled by the state_queue workqueue each time
++ *   phy_timer is triggered.
++ */
++static void phy_state_machine(struct work_struct *work)
+ {
+-	struct phy_device *phydev = (struct phy_device *)data;
++	struct phy_device *phydev =
++			container_of(work, struct phy_device, state_queue);
+ 	int needs_aneg = 0;
+ 	int err = 0;
+ 
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 
+ 	if (phydev->adjust_state)
+ 		phydev->adjust_state(phydev->attached_dev);
+@@ -965,7 +978,7 @@ static void phy_timer(unsigned long data)
+ 			break;
+ 	}
+ 
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 
+ 	if (needs_aneg)
+ 		err = phy_start_aneg(phydev);
+@@ -976,3 +989,14 @@ static void phy_timer(unsigned long data)
+ 	mod_timer(&phydev->phy_timer, jiffies + PHY_STATE_TIME * HZ);
+ }
+ 
++/* PHY timer which schedules the state machine work */
++static void phy_timer(unsigned long data)
++{
++	struct phy_device *phydev = (struct phy_device *)data;
++
++	/*
++	 * PHY I/O operations can potentially sleep so we ensure that
++	 * it's done from a process context
++	 */
++	schedule_work(&phydev->state_queue);
++}
+diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
+index 5b9e175..f4c4fd8 100644
+--- a/drivers/net/phy/phy_device.c
++++ b/drivers/net/phy/phy_device.c
+@@ -25,7 +25,6 @@
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/skbuff.h>
+-#include <linux/spinlock.h>
+ #include <linux/mm.h>
+ #include <linux/module.h>
+ #include <linux/mii.h>
+@@ -80,7 +79,7 @@ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
+ 
+ 	dev->state = PHY_DOWN;
+ 
+-	spin_lock_init(&dev->lock);
++	mutex_init(&dev->lock);
+ 
+ 	return dev;
+ }
+@@ -656,7 +655,7 @@ static int phy_probe(struct device *dev)
+ 	if (!(phydrv->flags & PHY_HAS_INTERRUPT))
+ 		phydev->irq = PHY_POLL;
+ 
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 
+ 	/* Start out supporting everything. Eventually,
+ 	 * a controller will attach, and may modify one
+@@ -670,7 +669,7 @@ static int phy_probe(struct device *dev)
+ 	if (phydev->drv->probe)
+ 		err = phydev->drv->probe(phydev);
+ 
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 
+ 	return err;
+ 
+@@ -682,9 +681,9 @@ static int phy_remove(struct device *dev)
+ 
+ 	phydev = to_phy_device(dev);
+ 
+-	spin_lock_bh(&phydev->lock);
++	mutex_lock(&phydev->lock);
+ 	phydev->state = PHY_DOWN;
+-	spin_unlock_bh(&phydev->lock);
++	mutex_unlock(&phydev->lock);
+ 
+ 	if (phydev->drv->remove)
+ 		phydev->drv->remove(phydev);
+diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
+new file mode 100644
+index 0000000..a052a67
+--- /dev/null
++++ b/drivers/net/phy/realtek.c
+@@ -0,0 +1,80 @@
++/*
++ * drivers/net/phy/realtek.c
++ *
++ * Driver for Realtek PHYs
++ *
++ * Author: Johnson Leung <r58129 at freescale.com>
++ *
++ * Copyright (c) 2004 Freescale Semiconductor, Inc.
++ *
++ * 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/phy.h>
++
++#define RTL821x_PHYSR		0x11
++#define RTL821x_PHYSR_DUPLEX	0x2000
++#define RTL821x_PHYSR_SPEED	0xc000
++#define RTL821x_INER		0x12
++#define RTL821x_INER_INIT	0x6400
++#define RTL821x_INSR		0x13
++
++MODULE_DESCRIPTION("Realtek PHY driver");
++MODULE_AUTHOR("Johnson Leung");
++MODULE_LICENSE("GPL");
++
++static int rtl821x_ack_interrupt(struct phy_device *phydev)
++{
++	int err;
++
++	err = phy_read(phydev, RTL821x_INSR);
++
++	return (err < 0) ? err : 0;
++}
++
++static int rtl821x_config_intr(struct phy_device *phydev)
++{
++	int err;
++
++	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
++		err = phy_write(phydev, RTL821x_INER,
++				RTL821x_INER_INIT);
++	else
++		err = phy_write(phydev, RTL821x_INER, 0);
++
++	return err;
++}
++
++/* RTL8211B */
++static struct phy_driver rtl821x_driver = {
++	.phy_id		= 0x001cc912,
++	.name		= "RTL821x Gigabit Ethernet",
++	.phy_id_mask	= 0x001fffff,
++	.features	= PHY_GBIT_FEATURES,
++	.flags		= PHY_HAS_INTERRUPT,
++	.config_aneg	= &genphy_config_aneg,
++	.read_status	= &genphy_read_status,
++	.ack_interrupt	= &rtl821x_ack_interrupt,
++	.config_intr	= &rtl821x_config_intr,
++	.driver		= { .owner = THIS_MODULE,},
++};
++
++static int __init realtek_init(void)
++{
++	int ret;
++
++	ret = phy_driver_register(&rtl821x_driver);
++
++	return ret;
++}
++
++static void __exit realtek_exit(void)
++{
++	phy_driver_unregister(&rtl821x_driver);
++}
++
++module_init(realtek_init);
++module_exit(realtek_exit);
 diff --git a/drivers/net/plip.c b/drivers/net/plip.c
 index 57c9866..fee3d7b 100644
 --- a/drivers/net/plip.c
@@ -566816,7 +623917,7 @@
  #define RMAC_ADDR_CMD_MEM_WE                    s2BIT(7)
  #define RMAC_ADDR_CMD_MEM_RD                    0
 diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
-index f2ba944..5fab7d7 100644
+index f2ba944..6179a0a 100644
 --- a/drivers/net/s2io.c
 +++ b/drivers/net/s2io.c
 @@ -84,7 +84,7 @@
@@ -567222,7 +624323,7 @@
 -		if (use_continuous_tx_intrs)
 -			val64 |= TTI_DATA1_MEM_TX_TIMER_CI_EN;
 -	writeq(val64, &bar0->tti_data1_mem);
--
+ 
 -	val64 = TTI_DATA2_MEM_TX_UFC_A(0x10) |
 -	    TTI_DATA2_MEM_TX_UFC_B(0x20) |
 -	    TTI_DATA2_MEM_TX_UFC_C(0x40) | TTI_DATA2_MEM_TX_UFC_D(0x80);
@@ -567230,7 +624331,7 @@
 -
 -	val64 = TTI_CMD_MEM_WE | TTI_CMD_MEM_STROBE_NEW_CMD;
 -	writeq(val64, &bar0->tti_command_mem);
- 
+-
 -	/*
 -	 * Once the operation completes, the Strobe bit of the command
 -	 * register will be reset. We poll for this particular condition
@@ -567856,8 +624957,68 @@
  
  	if (!napi)
  		spin_lock_init(&sp->put_lock);
+@@ -7902,7 +8118,7 @@ static void initiate_new_session(struct lro *lro, u8 *l2h,
+ 	lro->iph = ip;
+ 	lro->tcph = tcp;
+ 	lro->tcp_next_seq = tcp_pyld_len + ntohl(tcp->seq);
+-	lro->tcp_ack = ntohl(tcp->ack_seq);
++	lro->tcp_ack = tcp->ack_seq;
+ 	lro->sg_num = 1;
+ 	lro->total_len = ntohs(ip->tot_len);
+ 	lro->frags_len = 0;
+@@ -7911,10 +8127,10 @@ static void initiate_new_session(struct lro *lro, u8 *l2h,
+ 	 * already been done.
+  	 */
+ 	if (tcp->doff == 8) {
+-		u32 *ptr;
+-		ptr = (u32 *)(tcp+1);
++		__be32 *ptr;
++		ptr = (__be32 *)(tcp+1);
+ 		lro->saw_ts = 1;
+-		lro->cur_tsval = *(ptr+1);
++		lro->cur_tsval = ntohl(*(ptr+1));
+ 		lro->cur_tsecr = *(ptr+2);
+ 	}
+ 	lro->in_use = 1;
+@@ -7940,7 +8156,7 @@ static void update_L3L4_header(struct s2io_nic *sp, struct lro *lro)
+ 
+ 	/* Update tsecr field if this session has timestamps enabled */
+ 	if (lro->saw_ts) {
+-		u32 *ptr = (u32 *)(tcp + 1);
++		__be32 *ptr = (__be32 *)(tcp + 1);
+ 		*(ptr+2) = lro->cur_tsecr;
+ 	}
+ 
+@@ -7965,10 +8181,10 @@ static void aggregate_new_rx(struct lro *lro, struct iphdr *ip,
+ 	lro->window = tcp->window;
+ 
+ 	if (lro->saw_ts) {
+-		u32 *ptr;
++		__be32 *ptr;
+ 		/* Update tsecr and tsval from this packet */
+-		ptr = (u32 *) (tcp + 1);
+-		lro->cur_tsval = *(ptr + 1);
++		ptr = (__be32 *)(tcp+1);
++		lro->cur_tsval = ntohl(*(ptr+1));
+ 		lro->cur_tsecr = *(ptr + 2);
+ 	}
+ }
+@@ -8019,11 +8235,11 @@ static int verify_l3_l4_lro_capable(struct lro *l_lro, struct iphdr *ip,
+ 
+ 		/* Ensure timestamp value increases monotonically */
+ 		if (l_lro)
+-			if (l_lro->cur_tsval > *((u32 *)(ptr+2)))
++			if (l_lro->cur_tsval > ntohl(*((__be32 *)(ptr+2))))
+ 				return -1;
+ 
+ 		/* timestamp echo reply should be non-zero */
+-		if (*((u32 *)(ptr+6)) == 0)
++		if (*((__be32 *)(ptr+6)) == 0)
+ 			return -1;
+ 	}
+ 
 diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
-index cc1797a..9f6016c 100644
+index cc1797a..64b88eb 100644
 --- a/drivers/net/s2io.h
 +++ b/drivers/net/s2io.h
 @@ -31,6 +31,7 @@
@@ -567903,6 +625064,15 @@
  
  /* Information related to the Tx and Rx FIFOs and Rings of Xena
   * is maintained in this structure.
+@@ -797,7 +809,7 @@ struct lro {
+ 	int		in_use;
+ 	__be16		window;
+ 	u32		cur_tsval;
+-	u32		cur_tsecr;
++	__be32		cur_tsecr;
+ 	u8		saw_ts;
+ };
+ 
 @@ -826,7 +838,7 @@ struct s2io_nic {
  #define MAX_MAC_SUPPORTED   16
  #define MAX_SUPPORTED_MULTICASTS MAX_MAC_SUPPORTED
@@ -569037,6 +626207,19 @@
 -module_exit(shaper_exit);
 -MODULE_LICENSE("GPL");
 -
+diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
+index b570402..2e9e88b 100644
+--- a/drivers/net/sis190.c
++++ b/drivers/net/sis190.c
+@@ -326,7 +326,7 @@ static const struct {
+ 	{ "SiS 191 PCI Gigabit Ethernet adapter" },
+ };
+ 
+-static struct pci_device_id sis190_pci_tbl[] __devinitdata = {
++static struct pci_device_id sis190_pci_tbl[] = {
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0190), 0, 0, 0 },
+ 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x0191), 0, 0, 1 },
+ 	{ 0, },
 diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
 index 0857d2c..ec95e49 100644
 --- a/drivers/net/sis900.c
@@ -569123,10 +626306,45 @@
  		
  		(void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
  		
+diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c
+index 62b0132..889f987 100644
+--- a/drivers/net/skfp/ess.c
++++ b/drivers/net/skfp/ess.c
+@@ -598,7 +598,7 @@ static void ess_send_alc_req(struct s_smc *smc)
+ 	req->cmd.sba_cmd = REQUEST_ALLOCATION ;
+ 
+ 	/*
+-	 * set the parameter type and parameter lenght of all used
++	 * set the parameter type and parameter length of all used
+ 	 * parameters
+ 	 */
+ 
+diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c
+index a45205d..76dc8ad 100644
+--- a/drivers/net/skfp/fplustm.c
++++ b/drivers/net/skfp/fplustm.c
+@@ -398,7 +398,7 @@ static void copy_tx_mac(struct s_smc *smc, u_long td, struct fddi_mac *mac,
+ /* u_long td;		 transmit descriptor */
+ /* struct fddi_mac *mac; mac frame pointer */
+ /* unsigned off;	 start address within buffer memory */
+-/* int len ;		 lenght of the frame including the FC */
++/* int len ;		 length of the frame including the FC */
+ {
+ 	int	i ;
+ 	u_int	*p ;
 diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c
-index 438f424..8a430a3 100644
+index 438f424..46e3393 100644
 --- a/drivers/net/skfp/hwmtm.c
 +++ b/drivers/net/skfp/hwmtm.c
+@@ -1185,7 +1185,7 @@ void process_receive(struct s_smc *smc)
+ 
+ 		DB_RX("frame length = %d",len,0,4) ;
+ 		/*
+-		 * check the frame_lenght and all error flags
++		 * check the frame_length and all error flags
+ 		 */
+ 		if (rfsw & (RX_MSRABT|RX_FS_E|RX_FS_CRC|RX_FS_IMPL)){
+ 			if (rfsw & RD_S_MSRABT) {
 @@ -1746,7 +1746,7 @@ static void queue_llc_rx(struct s_smc *smc, SMbuf *mb)
  	DB_GEN("queue_llc_rx: mb = %x",(void *)mb,0,4) ;
  	smc->os.hwm.queued_rx_frames++ ;
@@ -569159,7 +626377,7 @@
  				break ;
  			}
 diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
-index bc15940..626190e 100644
+index bc15940..dc06236 100644
 --- a/drivers/net/sky2.c
 +++ b/drivers/net/sky2.c
 @@ -51,7 +51,7 @@
@@ -569196,7 +626414,25 @@
  		pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
  
  		/* select page 3 to access LED control register */
-@@ -714,23 +716,33 @@ static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
+@@ -621,6 +623,7 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
+ 	static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD };
+ 	static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA };
+ 
++	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ 	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ 	/* Turn on/off phy power saving */
+ 	if (onoff)
+@@ -632,7 +635,8 @@ static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff)
+ 		reg1 |= coma_mode[port];
+ 
+ 	sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+-	reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
++	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++	sky2_pci_read32(hw, PCI_DEV_REG1);
+ 
+ 	udelay(100);
+ }
+@@ -714,23 +718,33 @@ static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
  {
  	struct net_device *dev = hw->dev[port];
  
@@ -569233,18 +626469,18 @@
 +			/* set Tx GMAC FIFO Almost Empty Threshold */
 +			sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
 +				     (ECU_JUMBO_WM << 16) | ECU_AE_THR);
++
++			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
  
 -		/* Can't do offload because of lack of store/forward */
 -		dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
-+			sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), TX_STFW_DIS);
-+
 +			/* Can't do offload because of lack of store/forward */
 +			dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
 +		}
  	}
  }
  
-@@ -1174,24 +1186,32 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
+@@ -1174,24 +1188,32 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp
  /*
   * Allocate an skb for receiving. If the MTU is large enough
   * make the skb non-linear with a fragment list of pages.
@@ -569289,7 +626525,7 @@
  
  	for (i = 0; i < sky2->rx_nfrags; i++) {
  		struct page *page = alloc_page(GFP_ATOMIC);
-@@ -1227,7 +1247,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
+@@ -1227,7 +1249,7 @@ static int sky2_rx_start(struct sky2_port *sky2)
  	struct sky2_hw *hw = sky2->hw;
  	struct rx_ring_info *re;
  	unsigned rxq = rxqaddr[sky2->port];
@@ -569298,7 +626534,7 @@
  
  	sky2->rx_put = sky2->rx_next = 0;
  	sky2_qset(hw, rxq);
-@@ -1254,28 +1274,18 @@ static int sky2_rx_start(struct sky2_port *sky2)
+@@ -1254,28 +1276,18 @@ static int sky2_rx_start(struct sky2_port *sky2)
  	/* Stopping point for hardware truncation */
  	thresh = (size - 8) / sizeof(u32);
  
@@ -569335,7 +626571,46 @@
  	sky2->rx_data_size = size;
  
  	/* Fill Rx ring */
-@@ -2663,6 +2673,7 @@ static u32 sky2_mhz(const struct sky2_hw *hw)
+@@ -1412,6 +1424,7 @@ static int sky2_up(struct net_device *dev)
+ 	imask |= portirq_msk[port];
+ 	sky2_write32(hw, B0_IMSK, imask);
+ 
++	sky2_set_multicast(dev);
+ 	return 0;
+ 
+ err_out:
+@@ -2426,6 +2439,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
+ 	if (status & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) {
+ 		u16 pci_err;
+ 
++		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ 		pci_err = sky2_pci_read16(hw, PCI_STATUS);
+ 		if (net_ratelimit())
+ 			dev_err(&pdev->dev, "PCI hardware error (0x%x)\n",
+@@ -2433,12 +2447,14 @@ static void sky2_hw_intr(struct sky2_hw *hw)
+ 
+ 		sky2_pci_write16(hw, PCI_STATUS,
+ 				      pci_err | PCI_STATUS_ERROR_BITS);
++		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ 	}
+ 
+ 	if (status & Y2_IS_PCI_EXP) {
+ 		/* PCI-Express uncorrectable Error occurred */
+ 		u32 err;
+ 
++		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ 		err = sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
+ 		sky2_write32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS,
+ 			     0xfffffffful);
+@@ -2446,6 +2462,7 @@ static void sky2_hw_intr(struct sky2_hw *hw)
+ 			dev_err(&pdev->dev, "PCI Express error (0x%x)\n", err);
+ 
+ 		sky2_read32(hw, Y2_CFG_AER + PCI_ERR_UNCOR_STATUS);
++		sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ 	}
+ 
+ 	if (status & Y2_HWE_L1_MASK)
+@@ -2663,6 +2680,7 @@ static u32 sky2_mhz(const struct sky2_hw *hw)
  	case CHIP_ID_YUKON_EC:
  	case CHIP_ID_YUKON_EC_U:
  	case CHIP_ID_YUKON_EX:
@@ -569343,7 +626618,7 @@
  		return 125;
  
  	case CHIP_ID_YUKON_FE:
-@@ -2746,6 +2757,15 @@ static int __devinit sky2_init(struct sky2_hw *hw)
+@@ -2746,6 +2764,15 @@ static int __devinit sky2_init(struct sky2_hw *hw)
  			| SKY2_HW_AUTO_TX_SUM
  			| SKY2_HW_ADV_POWER_CTL;
  		break;
@@ -569359,7 +626634,13 @@
  	default:
  		dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
  			hw->chip_id);
-@@ -2816,7 +2836,8 @@ static void sky2_reset(struct sky2_hw *hw)
+@@ -2811,12 +2838,14 @@ static void sky2_reset(struct sky2_hw *hw)
+ 	}
+ 
+ 	sky2_power_on(hw);
++	sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+ 
+ 	for (i = 0; i < hw->ports; i++) {
  		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
  		sky2_write8(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
  
@@ -569369,6 +626650,24 @@
  			sky2_write16(hw, SK_REG(i, GMAC_CTRL),
  				     GMC_BYP_MACSECRX_ON | GMC_BYP_MACSECTX_ON
  				     | GMC_BYP_RETR_ON);
+@@ -3533,8 +3562,6 @@ static int sky2_set_ringparam(struct net_device *dev,
+ 		err = sky2_up(dev);
+ 		if (err)
+ 			dev_close(dev);
+-		else
+-			sky2_set_multicast(dev);
+ 	}
+ 
+ 	return err;
+@@ -4368,8 +4395,6 @@ static int sky2_resume(struct pci_dev *pdev)
+ 				dev_close(dev);
+ 				goto out;
+ 			}
+-
+-			sky2_set_multicast(dev);
+ 		}
+ 	}
+ 
 diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
 index ffe9b8a..2bced1a 100644
 --- a/drivers/net/sky2.h
@@ -570503,6 +627802,19 @@
  
  #else
  
+diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
+index fe3ac6f..0e4a88d 100644
+--- a/drivers/net/sunbmac.c
++++ b/drivers/net/sunbmac.c
+@@ -1075,7 +1075,7 @@ static const struct ethtool_ops bigmac_ethtool_ops = {
+ 	.get_link		= bigmac_get_link,
+ };
+ 
+-static int __init bigmac_ether_init(struct sbus_dev *qec_sdev)
++static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev)
+ {
+ 	struct net_device *dev;
+ 	static int version_printed;
 diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
 index 0a6186d..7d5561b 100644
 --- a/drivers/net/sundance.c
@@ -570786,10 +628098,50 @@
  	void (*write_txd)(struct happy_meal_txd *, u32, u32);
  	void (*write_rxd)(struct happy_meal_rxd *, u32, u32);
  	u32 (*dma_map)(void *, void *, long, int);
+diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
+index ff23c64..e811331 100644
+--- a/drivers/net/sunqe.c
++++ b/drivers/net/sunqe.c
+@@ -747,7 +747,7 @@ static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev)
+ 		    qecp->gregs + GLOB_RSIZE);
+ }
+ 
+-static u8 __init qec_get_burst(struct device_node *dp)
++static u8 __devinit qec_get_burst(struct device_node *dp)
+ {
+ 	u8 bsizes, bsizes_more;
+ 
+@@ -767,7 +767,7 @@ static u8 __init qec_get_burst(struct device_node *dp)
+ 	return bsizes;
+ }
+ 
+-static struct sunqec * __init get_qec(struct sbus_dev *child_sdev)
++static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev)
+ {
+ 	struct sbus_dev *qec_sdev = child_sdev->parent;
+ 	struct sunqec *qecp;
+@@ -823,7 +823,7 @@ fail:
+ 	return NULL;
+ }
+ 
+-static int __init qec_ether_init(struct sbus_dev *sdev)
++static int __devinit qec_ether_init(struct sbus_dev *sdev)
+ {
+ 	static unsigned version_printed;
+ 	struct net_device *dev;
 diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
-index ff1028a..4a0035f 100644
+index ff1028a..6415ce1 100644
 --- a/drivers/net/sunvnet.c
 +++ b/drivers/net/sunvnet.c
+@@ -1130,7 +1130,7 @@ static struct vio_driver_ops vnet_vio_ops = {
+ 	.handshake_complete	= vnet_handshake_complete,
+ };
+ 
+-static void print_version(void)
++static void __devinit print_version(void)
+ {
+ 	static int version_printed;
+ 
 @@ -1149,6 +1149,7 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
  	struct vnet *vp;
  	const u64 *rmac;
@@ -571621,8 +628973,60 @@
  #define TG3_FLAG_PCIX_MODE		0x00020000
  #define TG3_FLAG_PCI_HIGH_SPEED		0x00040000
  #define TG3_FLAG_PCI_32BIT		0x00080000
+diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
+index 124cfd4..7a7de04 100644
+--- a/drivers/net/tokenring/abyss.c
++++ b/drivers/net/tokenring/abyss.c
+@@ -10,7 +10,7 @@
+  *      - Madge Smart 16/4 PCI Mk2
+  *
+  *  Maintainer(s):
+- *    AF	Adam Fritzler		mid at auk.cx
++ *    AF	Adam Fritzler
+  *
+  *  Modification History:
+  *	30-Dec-99	AF	Split off from the tms380tr driver.
+diff --git a/drivers/net/tokenring/abyss.h b/drivers/net/tokenring/abyss.h
+index 0ee6e4f..b0a473b 100644
+--- a/drivers/net/tokenring/abyss.h
++++ b/drivers/net/tokenring/abyss.h
+@@ -2,7 +2,7 @@
+  * abyss.h: Header for the abyss tms380tr module
+  *
+  * Authors:
+- * - Adam Fritzler <mid at auk.cx>
++ * - Adam Fritzler
+  */
+ 
+ #ifndef __LINUX_MADGETR_H
+diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
+index 5a41513..c9c5a2b 100644
+--- a/drivers/net/tokenring/madgemc.c
++++ b/drivers/net/tokenring/madgemc.c
+@@ -11,7 +11,7 @@
+  *	- Madge Smart 16/4 Ringnode MC32 (??)
+  *
+  *  Maintainer(s):
+- *    AF	Adam Fritzler		mid at auk.cx
++ *    AF	Adam Fritzler
+  *
+  *  Modification History:
+  *	16-Jan-00	AF	Created
+diff --git a/drivers/net/tokenring/madgemc.h b/drivers/net/tokenring/madgemc.h
+index 2dd8222..fe88e27 100644
+--- a/drivers/net/tokenring/madgemc.h
++++ b/drivers/net/tokenring/madgemc.h
+@@ -2,7 +2,7 @@
+  * madgemc.h: Header for the madgemc tms380tr module
+  *
+  * Authors:
+- * - Adam Fritzler <mid at auk.cx>
++ * - Adam Fritzler
+  */
+ 
+ #ifndef __LINUX_MADGEMC_H
 diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
-index 74c1f0f..e7b4adc 100644
+index 74c1f0f..433c994 100644
 --- a/drivers/net/tokenring/olympic.c
 +++ b/drivers/net/tokenring/olympic.c
 @@ -357,7 +357,7 @@ static int __devinit olympic_init(struct net_device *dev)
@@ -571634,6 +629038,15 @@
  			schedule() ; 
  			if(time_after(jiffies, t + 2*HZ)) {
  				printk(KERN_ERR "IBM Cardbus tokenring adapter not responsing.\n") ; 
+@@ -434,7 +434,7 @@ static int __devinit olympic_init(struct net_device *dev)
+ 
+ }
+ 
+-static int olympic_open(struct net_device *dev) 
++static int __devinit olympic_open(struct net_device *dev) 
+ {
+ 	struct olympic_private *olympic_priv=netdev_priv(dev);
+ 	u8 __iomem *olympic_mmio=olympic_priv->olympic_mmio,*init_srb;
 @@ -671,7 +671,7 @@ static int olympic_open(struct net_device *dev)
  
  	writel(BMCTL_TX1_DIS,olympic_mmio+BMCTL_RWM); /* Yes, this enables TX channel 1 */
@@ -571715,6 +629128,71 @@
  	u8 frame_data ; 
  };
  
+diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
+index ca6b659..00ea945 100644
+--- a/drivers/net/tokenring/proteon.c
++++ b/drivers/net/tokenring/proteon.c
+@@ -12,7 +12,7 @@
+  *	- Proteon 1392, 1392+
+  *
+  *  Maintainer(s):
+- *    AF        Adam Fritzler           mid at auk.cx
++ *    AF        Adam Fritzler
+  *    JF	Jochen Friedrich	jochen at scram.de
+  *
+  *  Modification History:
+diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
+index 32e8d5a..41b6999 100644
+--- a/drivers/net/tokenring/skisa.c
++++ b/drivers/net/tokenring/skisa.c
+@@ -13,7 +13,7 @@
+  *	- SysKonnect TR4/16(+) ISA	(SK-4190)
+  *
+  *  Maintainer(s):
+- *    AF        Adam Fritzler           mid at auk.cx
++ *    AF        Adam Fritzler
+  *    JF	Jochen Friedrich	jochen at scram.de
+  *
+  *  Modification History:
+diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
+index d5fa36d..d07c452 100644
+--- a/drivers/net/tokenring/tms380tr.c
++++ b/drivers/net/tokenring/tms380tr.c
+@@ -30,7 +30,7 @@
+  *  Maintainer(s):
+  *    JS	Jay Schulist		jschlst at samba.org
+  *    CG	Christoph Goos		cgoos at syskonnect.de
+- *    AF	Adam Fritzler		mid at auk.cx
++ *    AF	Adam Fritzler
+  *    MLP       Mike Phillips           phillim at amtrak.com
+  *    JF	Jochen Friedrich	jochen at scram.de
+  *     
+diff --git a/drivers/net/tokenring/tms380tr.h b/drivers/net/tokenring/tms380tr.h
+index 7daf74e..7af76d7 100644
+--- a/drivers/net/tokenring/tms380tr.h
++++ b/drivers/net/tokenring/tms380tr.h
+@@ -3,7 +3,7 @@
+  *
+  * Authors:
+  * - Christoph Goos <cgoos at syskonnect.de>
+- * - Adam Fritzler <mid at auk.cx>
++ * - Adam Fritzler
+  */
+ 
+ #ifndef __LINUX_TMS380TR_H
+diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
+index 1c18f78..5f0ee88 100644
+--- a/drivers/net/tokenring/tmspci.c
++++ b/drivers/net/tokenring/tmspci.c
+@@ -14,7 +14,7 @@
+  *      - 3Com 3C339 Token Link Velocity
+  *
+  *  Maintainer(s):
+- *    AF	Adam Fritzler		mid at auk.cx
++ *    AF	Adam Fritzler
+  *
+  *  Modification History:
+  *	30-Dec-99	AF	Split off from the tms380tr driver.
 diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
 index 6e8b18a..6c6fc32 100644
 --- a/drivers/net/tulip/de4x5.c
@@ -571738,7 +629216,7 @@
      }
  
 diff --git a/drivers/net/tun.c b/drivers/net/tun.c
-index f8b8c71..46339f6 100644
+index f8b8c71..038c1ef 100644
 --- a/drivers/net/tun.c
 +++ b/drivers/net/tun.c
 @@ -292,17 +292,6 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
@@ -571786,11 +629264,48 @@
  		get_random_bytes(tun->dev_addr + sizeof(u16), 4);
  		memset(tun->chr_filter, 0, sizeof tun->chr_filter);
  
+@@ -540,9 +529,13 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
+ 
+ 	if (ifr->ifr_flags & IFF_NO_PI)
+ 		tun->flags |= TUN_NO_PI;
++	else
++		tun->flags &= ~TUN_NO_PI;
+ 
+ 	if (ifr->ifr_flags & IFF_ONE_QUEUE)
+ 		tun->flags |= TUN_ONE_QUEUE;
++	else
++		tun->flags &= ~TUN_ONE_QUEUE;
+ 
+ 	file->private_data = tun;
+ 	tun->attached = 1;
 diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
-index abac7db..4ffd873 100644
+index abac7db..fba0811 100644
 --- a/drivers/net/ucc_geth.c
 +++ b/drivers/net/ucc_geth.c
-@@ -3614,9 +3614,6 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
+@@ -2084,8 +2084,10 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
+ 	if (!ugeth)
+ 		return;
+ 
+-	if (ugeth->uccf)
++	if (ugeth->uccf) {
+ 		ucc_fast_free(ugeth->uccf);
++		ugeth->uccf = NULL;
++	}
+ 
+ 	if (ugeth->p_thread_data_tx) {
+ 		qe_muram_free(ugeth->thread_dat_tx_offset);
+@@ -2305,10 +2307,6 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
+ 	ug_info = ugeth->ug_info;
+ 	uf_info = &ug_info->uf_info;
+ 
+-	/* Create CQs for hash tables */
+-	INIT_LIST_HEAD(&ugeth->group_hash_q);
+-	INIT_LIST_HEAD(&ugeth->ind_hash_q);
+-
+ 	if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) ||
+ 	      (uf_info->bd_mem_part == MEM_PART_MURAM))) {
+ 		if (netif_msg_probe(ugeth))
+@@ -3614,9 +3612,6 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
  
  	ugeth_vdbg("%s: IN", __FUNCTION__);
  
@@ -571800,7 +629315,31 @@
  	uccf = ugeth->uccf;
  	ug_info = ugeth->ug_info;
  
-@@ -3822,6 +3819,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+@@ -3671,6 +3666,23 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
+ 	return IRQ_HANDLED;
+ }
+ 
++#ifdef CONFIG_NET_POLL_CONTROLLER
++/*
++ * Polling 'interrupt' - used by things like netconsole to send skbs
++ * without having to re-enable interrupts. It's not called while
++ * the interrupt routine is executing.
++ */
++static void ucc_netpoll(struct net_device *dev)
++{
++	struct ucc_geth_private *ugeth = netdev_priv(dev);
++	int irq = ugeth->ug_info->uf_info.irq;
++
++	disable_irq(irq);
++	ucc_geth_irq_handler(irq, dev);
++	enable_irq(irq);
++}
++#endif /* CONFIG_NET_POLL_CONTROLLER */
++
+ /* Called when something needs to use the ethernet device */
+ /* Returns 0 for success. */
+ static int ucc_geth_open(struct net_device *dev)
+@@ -3822,6 +3834,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
  	int err, ucc_num, max_speed = 0;
  	const phandle *ph;
  	const unsigned int *prop;
@@ -571808,7 +629347,7 @@
  	const void *mac_addr;
  	phy_interface_t phy_interface;
  	static const int enet_to_speed[] = {
-@@ -3854,10 +3852,56 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+@@ -3854,10 +3867,56 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
  
  	ug_info->uf_info.ucc_num = ucc_num;
  
@@ -571869,6 +629408,40 @@
  	err = of_address_to_resource(np, 0, &res);
  	if (err)
  		return -EINVAL;
+@@ -3946,6 +4005,10 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ 	ugeth = netdev_priv(dev);
+ 	spin_lock_init(&ugeth->lock);
+ 
++	/* Create CQs for hash tables */
++	INIT_LIST_HEAD(&ugeth->group_hash_q);
++	INIT_LIST_HEAD(&ugeth->ind_hash_q);
++
+ 	dev_set_drvdata(device, dev);
+ 
+ 	/* Set the dev->base_addr to the gfar reg region */
+@@ -3962,6 +4025,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
+ #ifdef CONFIG_UGETH_NAPI
+ 	netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT);
+ #endif				/* CONFIG_UGETH_NAPI */
++#ifdef CONFIG_NET_POLL_CONTROLLER
++	dev->poll_controller = ucc_netpoll;
++#endif
+ 	dev->stop = ucc_geth_close;
+ //    dev->change_mtu = ucc_geth_change_mtu;
+ 	dev->mtu = 1500;
+@@ -3996,9 +4062,10 @@ static int ucc_geth_remove(struct of_device* ofdev)
+ 	struct net_device *dev = dev_get_drvdata(device);
+ 	struct ucc_geth_private *ugeth = netdev_priv(dev);
+ 
+-	dev_set_drvdata(device, NULL);
+-	ucc_geth_memclean(ugeth);
++	unregister_netdev(dev);
+ 	free_netdev(dev);
++	ucc_geth_memclean(ugeth);
++	dev_set_drvdata(device, NULL);
+ 
+ 	return 0;
+ }
 diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c
 index df884f0..e3ba14a 100644
 --- a/drivers/net/ucc_geth_mii.c
@@ -572556,6 +630129,18 @@
  
  
  static const struct driver_info	rndis_info = {
+diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
+index 33cbc30..7e1f001 100644
+--- a/drivers/net/usb/rtl8150.c
++++ b/drivers/net/usb/rtl8150.c
+@@ -926,7 +926,6 @@ static int rtl8150_probe(struct usb_interface *intf,
+ 	netdev->set_multicast_list = rtl8150_set_multicast;
+ 	netdev->set_mac_address = rtl8150_set_mac_address;
+ 	netdev->get_stats = rtl8150_netdev_stats;
+-	netdev->mtu = RTL8150_MTU;
+ 	SET_ETHTOOL_OPS(netdev, &ops);
+ 	dev->intr_interval = 100;	/* 100ms */
+ 
 diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
 index 8ed1fc5..8463efb 100644
 --- a/drivers/net/usb/usbnet.c
@@ -572803,9 +630388,18 @@
  
  /*
 diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
-index 07263cd..87c180b 100644
+index 07263cd..7c851b1 100644
 --- a/drivers/net/via-rhine.c
 +++ b/drivers/net/via-rhine.c
+@@ -606,7 +606,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget)
+ }
+ #endif
+ 
+-static void rhine_hw_init(struct net_device *dev, long pioaddr)
++static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
+ {
+ 	struct rhine_private *rp = netdev_priv(dev);
+ 
 @@ -1338,7 +1338,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
  				if (debug > 2 &&
  				    ioread8(ioaddr+ChipCmd) & CmdTxOn)
@@ -572815,6 +630409,956 @@
  					       "still on.\n", dev->name);
  			}
  			rhine_tx(dev);
+diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
+index 35cd65d..8c9fb82 100644
+--- a/drivers/net/via-velocity.c
++++ b/drivers/net/via-velocity.c
+@@ -8,7 +8,6 @@
+  * for 64bit hardware platforms.
+  *
+  * TODO
+- *	Big-endian support
+  *	rx_copybreak/alignment
+  *	Scatter gather
+  *	More testing
+@@ -681,7 +680,7 @@ static void velocity_rx_reset(struct velocity_info *vptr)
+ 	 *	Init state, all RD entries belong to the NIC
+ 	 */
+ 	for (i = 0; i < vptr->options.numrx; ++i)
+-		vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;
++		vptr->rd_ring[i].rdesc0.len |= OWNED_BY_NIC;
+ 
+ 	writew(vptr->options.numrx, &regs->RBRDU);
+ 	writel(vptr->rd_pool_dma, &regs->RDBaseLo);
+@@ -777,7 +776,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
+ 
+ 		vptr->int_mask = INT_MASK_DEF;
+ 
+-		writel(cpu_to_le32(vptr->rd_pool_dma), &regs->RDBaseLo);
++		writel(vptr->rd_pool_dma, &regs->RDBaseLo);
+ 		writew(vptr->options.numrx - 1, &regs->RDCSize);
+ 		mac_rx_queue_run(regs);
+ 		mac_rx_queue_wake(regs);
+@@ -785,7 +784,7 @@ static void velocity_init_registers(struct velocity_info *vptr,
+ 		writew(vptr->options.numtx - 1, &regs->TDCSize);
+ 
+ 		for (i = 0; i < vptr->num_txq; i++) {
+-			writel(cpu_to_le32(vptr->td_pool_dma[i]), &(regs->TDBaseLo[i]));
++			writel(vptr->td_pool_dma[i], &regs->TDBaseLo[i]);
+ 			mac_tx_queue_run(regs, i);
+ 		}
+ 
+@@ -1195,7 +1194,7 @@ static inline void velocity_give_many_rx_descs(struct velocity_info *vptr)
+ 	dirty = vptr->rd_dirty - unusable;
+ 	for (avail = vptr->rd_filled & 0xfffc; avail; avail--) {
+ 		dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
+-		vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC;
++		vptr->rd_ring[dirty].rdesc0.len |= OWNED_BY_NIC;
+ 	}
+ 
+ 	writew(vptr->rd_filled & 0xfffc, &regs->RBRDU);
+@@ -1210,7 +1209,7 @@ static int velocity_rx_refill(struct velocity_info *vptr)
+ 		struct rx_desc *rd = vptr->rd_ring + dirty;
+ 
+ 		/* Fine for an all zero Rx desc at init time as well */
+-		if (rd->rdesc0.owner == OWNED_BY_NIC)
++		if (rd->rdesc0.len & OWNED_BY_NIC)
+ 			break;
+ 
+ 		if (!vptr->rd_info[dirty].skb) {
+@@ -1413,7 +1412,7 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
+ 		if (!vptr->rd_info[rd_curr].skb)
+ 			break;
+ 
+-		if (rd->rdesc0.owner == OWNED_BY_NIC)
++		if (rd->rdesc0.len & OWNED_BY_NIC)
+ 			break;
+ 
+ 		rmb();
+@@ -1421,7 +1420,7 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
+ 		/*
+ 		 *	Don't drop CE or RL error frame although RXOK is off
+ 		 */
+-		if ((rd->rdesc0.RSR & RSR_RXOK) || (!(rd->rdesc0.RSR & RSR_RXOK) && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
++		if (rd->rdesc0.RSR & (RSR_RXOK | RSR_CE | RSR_RL)) {
+ 			if (velocity_receive_frame(vptr, rd_curr) < 0)
+ 				stats->rx_dropped++;
+ 		} else {
+@@ -1433,7 +1432,7 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
+ 			stats->rx_dropped++;
+ 		}
+ 
+-		rd->inten = 1;
++		rd->size |= RX_INTEN;
+ 
+ 		vptr->dev->last_rx = jiffies;
+ 
+@@ -1554,7 +1553,7 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx)
+ 	struct net_device_stats *stats = &vptr->stats;
+ 	struct velocity_rd_info *rd_info = &(vptr->rd_info[idx]);
+ 	struct rx_desc *rd = &(vptr->rd_ring[idx]);
+-	int pkt_len = rd->rdesc0.len;
++	int pkt_len = le16_to_cpu(rd->rdesc0.len) & 0x3fff;
+ 	struct sk_buff *skb;
+ 
+ 	if (rd->rdesc0.RSR & (RSR_STP | RSR_EDP)) {
+@@ -1637,8 +1636,7 @@ static int velocity_alloc_rx_buf(struct velocity_info *vptr, int idx)
+  	 */
+ 
+ 	*((u32 *) & (rd->rdesc0)) = 0;
+-	rd->len = cpu_to_le32(vptr->rx_buf_sz);
+-	rd->inten = 1;
++	rd->size = cpu_to_le16(vptr->rx_buf_sz) | RX_INTEN;
+ 	rd->pa_low = cpu_to_le32(rd_info->skb_dma);
+ 	rd->pa_high = 0;
+ 	return 0;
+@@ -1674,7 +1672,7 @@ static int velocity_tx_srv(struct velocity_info *vptr, u32 status)
+ 			td = &(vptr->td_rings[qnum][idx]);
+ 			tdinfo = &(vptr->td_infos[qnum][idx]);
+ 
+-			if (td->tdesc0.owner == OWNED_BY_NIC)
++			if (td->tdesc0.len & OWNED_BY_NIC)
+ 				break;
+ 
+ 			if ((works++ > 15))
+@@ -1874,7 +1872,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_
+ 
+ 		for (i = 0; i < tdinfo->nskb_dma; i++) {
+ #ifdef VELOCITY_ZERO_COPY_SUPPORT
+-			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], td->tdesc1.len, PCI_DMA_TODEVICE);
++			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE);
+ #else
+ 			pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE);
+ #endif
+@@ -2067,8 +2065,8 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	struct velocity_td_info *tdinfo;
+ 	unsigned long flags;
+ 	int index;
+-
+ 	int pktlen = skb->len;
++	__le16 len = cpu_to_le16(pktlen);
+ 
+ #ifdef VELOCITY_ZERO_COPY_SUPPORT
+ 	if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
+@@ -2083,9 +2081,8 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	td_ptr = &(vptr->td_rings[qnum][index]);
+ 	tdinfo = &(vptr->td_infos[qnum][index]);
+ 
+-	td_ptr->tdesc1.TCPLS = TCPLS_NORMAL;
+ 	td_ptr->tdesc1.TCR = TCR0_TIC;
+-	td_ptr->td_buf[0].queue = 0;
++	td_ptr->td_buf[0].size &= ~TD_QUEUE;
+ 
+ 	/*
+ 	 *	Pad short frames.
+@@ -2093,16 +2090,16 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	if (pktlen < ETH_ZLEN) {
+ 		/* Cannot occur until ZC support */
+ 		pktlen = ETH_ZLEN;
++		len = cpu_to_le16(ETH_ZLEN);
+ 		skb_copy_from_linear_data(skb, tdinfo->buf, skb->len);
+ 		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
+ 		tdinfo->skb = skb;
+ 		tdinfo->skb_dma[0] = tdinfo->buf_dma;
+-		td_ptr->tdesc0.pktsize = pktlen;
++		td_ptr->tdesc0.len = len;
+ 		td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+ 		td_ptr->td_buf[0].pa_high = 0;
+-		td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
++		td_ptr->td_buf[0].size = len;	/* queue is 0 anyway */
+ 		tdinfo->nskb_dma = 1;
+-		td_ptr->tdesc1.CMDZ = 2;
+ 	} else
+ #ifdef VELOCITY_ZERO_COPY_SUPPORT
+ 	if (skb_shinfo(skb)->nr_frags > 0) {
+@@ -2111,36 +2108,35 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		if (nfrags > 6) {
+ 			skb_copy_from_linear_data(skb, tdinfo->buf, skb->len);
+ 			tdinfo->skb_dma[0] = tdinfo->buf_dma;
+-			td_ptr->tdesc0.pktsize =
++			td_ptr->tdesc0.len = len;
+ 			td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+ 			td_ptr->td_buf[0].pa_high = 0;
+-			td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
++			td_ptr->td_buf[0].size = len;	/* queue is 0 anyway */
+ 			tdinfo->nskb_dma = 1;
+-			td_ptr->tdesc1.CMDZ = 2;
+ 		} else {
+ 			int i = 0;
+ 			tdinfo->nskb_dma = 0;
+-			tdinfo->skb_dma[i] = pci_map_single(vptr->pdev, skb->data, skb->len - skb->data_len, PCI_DMA_TODEVICE);
++			tdinfo->skb_dma[i] = pci_map_single(vptr->pdev, skb->data,
++						skb_headlen(skb), PCI_DMA_TODEVICE);
+ 
+-			td_ptr->tdesc0.pktsize = pktlen;
++			td_ptr->tdesc0.len = len;
+ 
+ 			/* FIXME: support 48bit DMA later */
+ 			td_ptr->td_buf[i].pa_low = cpu_to_le32(tdinfo->skb_dma);
+ 			td_ptr->td_buf[i].pa_high = 0;
+-			td_ptr->td_buf[i].bufsize = skb->len->skb->data_len;
++			td_ptr->td_buf[i].size = cpu_to_le16(skb_headlen(skb));
+ 
+ 			for (i = 0; i < nfrags; i++) {
+ 				skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+-				void *addr = ((void *) page_address(frag->page + frag->page_offset));
++				void *addr = (void *)page_address(frag->page) + frag->page_offset;
+ 
+ 				tdinfo->skb_dma[i + 1] = pci_map_single(vptr->pdev, addr, frag->size, PCI_DMA_TODEVICE);
+ 
+ 				td_ptr->td_buf[i + 1].pa_low = cpu_to_le32(tdinfo->skb_dma[i + 1]);
+ 				td_ptr->td_buf[i + 1].pa_high = 0;
+-				td_ptr->td_buf[i + 1].bufsize = frag->size;
++				td_ptr->td_buf[i + 1].size = cpu_to_le16(frag->size);
+ 			}
+ 			tdinfo->nskb_dma = i - 1;
+-			td_ptr->tdesc1.CMDZ = i;
+ 		}
+ 
+ 	} else
+@@ -2152,18 +2148,16 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 		 */
+ 		tdinfo->skb = skb;
+ 		tdinfo->skb_dma[0] = pci_map_single(vptr->pdev, skb->data, pktlen, PCI_DMA_TODEVICE);
+-		td_ptr->tdesc0.pktsize = pktlen;
++		td_ptr->tdesc0.len = len;
+ 		td_ptr->td_buf[0].pa_low = cpu_to_le32(tdinfo->skb_dma[0]);
+ 		td_ptr->td_buf[0].pa_high = 0;
+-		td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
++		td_ptr->td_buf[0].size = len;
+ 		tdinfo->nskb_dma = 1;
+-		td_ptr->tdesc1.CMDZ = 2;
+ 	}
++	td_ptr->tdesc1.cmd = TCPLS_NORMAL + (tdinfo->nskb_dma + 1) * 16;
+ 
+ 	if (vptr->vlgrp && vlan_tx_tag_present(skb)) {
+-		td_ptr->tdesc1.pqinf.VID = vlan_tx_tag_get(skb);
+-		td_ptr->tdesc1.pqinf.priority = 0;
+-		td_ptr->tdesc1.pqinf.CFI = 0;
++		td_ptr->tdesc1.vlan = cpu_to_le16(vlan_tx_tag_get(skb));
+ 		td_ptr->tdesc1.TCR |= TCR0_VETAG;
+ 	}
+ 
+@@ -2185,7 +2179,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 		if (prev < 0)
+ 			prev = vptr->options.numtx - 1;
+-		td_ptr->tdesc0.owner = OWNED_BY_NIC;
++		td_ptr->tdesc0.len |= OWNED_BY_NIC;
+ 		vptr->td_used[qnum]++;
+ 		vptr->td_curr[qnum] = (index + 1) % vptr->options.numtx;
+ 
+@@ -2193,7 +2187,7 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev)
+ 			netif_stop_queue(dev);
+ 
+ 		td_ptr = &(vptr->td_rings[qnum][prev]);
+-		td_ptr->td_buf[0].queue = 1;
++		td_ptr->td_buf[0].size |= TD_QUEUE;
+ 		mac_tx_queue_wake(vptr->mac_regs, qnum);
+ 	}
+ 	dev->trans_start = jiffies;
+@@ -3410,7 +3404,7 @@ static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
+ 		velocity_save_context(vptr, &vptr->context);
+ 		velocity_shutdown(vptr);
+ 		velocity_set_wol(vptr);
+-		pci_enable_wake(pdev, 3, 1);
++		pci_enable_wake(pdev, PCI_D3hot, 1);
+ 		pci_set_power_state(pdev, PCI_D3hot);
+ 	} else {
+ 		velocity_save_context(vptr, &vptr->context);
+diff --git a/drivers/net/via-velocity.h b/drivers/net/via-velocity.h
+index aa91796..7387be4 100644
+--- a/drivers/net/via-velocity.h
++++ b/drivers/net/via-velocity.h
+@@ -70,40 +70,27 @@
+  * Bits in the RSR0 register
+  */
+ 
+-#define RSR_DETAG          0x0080
+-#define RSR_SNTAG          0x0040
+-#define RSR_RXER           0x0020
+-#define RSR_RL             0x0010
+-#define RSR_CE             0x0008
+-#define RSR_FAE            0x0004
+-#define RSR_CRC            0x0002
+-#define RSR_VIDM           0x0001
++#define RSR_DETAG	cpu_to_le16(0x0080)
++#define RSR_SNTAG	cpu_to_le16(0x0040)
++#define RSR_RXER	cpu_to_le16(0x0020)
++#define RSR_RL		cpu_to_le16(0x0010)
++#define RSR_CE		cpu_to_le16(0x0008)
++#define RSR_FAE		cpu_to_le16(0x0004)
++#define RSR_CRC		cpu_to_le16(0x0002)
++#define RSR_VIDM	cpu_to_le16(0x0001)
+ 
+ /*
+  * Bits in the RSR1 register
+  */
+ 
+-#define RSR_RXOK           0x8000	// rx OK
+-#define RSR_PFT            0x4000	// Perfect filtering address match
+-#define RSR_MAR            0x2000	// MAC accept multicast address packet
+-#define RSR_BAR            0x1000	// MAC accept broadcast address packet
+-#define RSR_PHY            0x0800	// MAC accept physical address packet
+-#define RSR_VTAG           0x0400	// 802.1p/1q tagging packet indicator
+-#define RSR_STP            0x0200	// start of packet
+-#define RSR_EDP            0x0100	// end of packet
+-
+-/*
+- * Bits in the RSR1 register
+- */
+-
+-#define RSR1_RXOK           0x80	// rx OK
+-#define RSR1_PFT            0x40	// Perfect filtering address match
+-#define RSR1_MAR            0x20	// MAC accept multicast address packet
+-#define RSR1_BAR            0x10	// MAC accept broadcast address packet
+-#define RSR1_PHY            0x08	// MAC accept physical address packet
+-#define RSR1_VTAG           0x04	// 802.1p/1q tagging packet indicator
+-#define RSR1_STP            0x02	// start of packet
+-#define RSR1_EDP            0x01	// end of packet
++#define RSR_RXOK	cpu_to_le16(0x8000) // rx OK
++#define RSR_PFT		cpu_to_le16(0x4000) // Perfect filtering address match
++#define RSR_MAR		cpu_to_le16(0x2000) // MAC accept multicast address packet
++#define RSR_BAR		cpu_to_le16(0x1000) // MAC accept broadcast address packet
++#define RSR_PHY		cpu_to_le16(0x0800) // MAC accept physical address packet
++#define RSR_VTAG	cpu_to_le16(0x0400) // 802.1p/1q tagging packet indicator
++#define RSR_STP		cpu_to_le16(0x0200) // start of packet
++#define RSR_EDP		cpu_to_le16(0x0100) // end of packet
+ 
+ /*
+  * Bits in the CSM register
+@@ -120,33 +107,21 @@
+  * Bits in the TSR0 register
+  */
+ 
+-#define TSR0_ABT            0x0080	// Tx abort because of excessive collision
+-#define TSR0_OWT            0x0040	// Jumbo frame Tx abort
+-#define TSR0_OWC            0x0020	// Out of window collision
+-#define TSR0_COLS           0x0010	// experience collision in this transmit event
+-#define TSR0_NCR3           0x0008	// collision retry counter[3]
+-#define TSR0_NCR2           0x0004	// collision retry counter[2]
+-#define TSR0_NCR1           0x0002	// collision retry counter[1]
+-#define TSR0_NCR0           0x0001	// collision retry counter[0]
+-#define TSR0_TERR           0x8000	//
+-#define TSR0_FDX            0x4000	// current transaction is serviced by full duplex mode
+-#define TSR0_GMII           0x2000	// current transaction is serviced by GMII mode
+-#define TSR0_LNKFL          0x1000	// packet serviced during link down
+-#define TSR0_SHDN           0x0400	// shutdown case
+-#define TSR0_CRS            0x0200	// carrier sense lost
+-#define TSR0_CDH            0x0100	// AQE test fail (CD heartbeat)
+-
+-/*
+- * Bits in the TSR1 register
+- */
+-
+-#define TSR1_TERR           0x80	//
+-#define TSR1_FDX            0x40	// current transaction is serviced by full duplex mode
+-#define TSR1_GMII           0x20	// current transaction is serviced by GMII mode
+-#define TSR1_LNKFL          0x10	// packet serviced during link down
+-#define TSR1_SHDN           0x04	// shutdown case
+-#define TSR1_CRS            0x02	// carrier sense lost
+-#define TSR1_CDH            0x01	// AQE test fail (CD heartbeat)
++#define TSR0_ABT	cpu_to_le16(0x0080) // Tx abort because of excessive collision
++#define TSR0_OWT	cpu_to_le16(0x0040) // Jumbo frame Tx abort
++#define TSR0_OWC	cpu_to_le16(0x0020) // Out of window collision
++#define TSR0_COLS	cpu_to_le16(0x0010) // experience collision in this transmit event
++#define TSR0_NCR3	cpu_to_le16(0x0008) // collision retry counter[3]
++#define TSR0_NCR2	cpu_to_le16(0x0004) // collision retry counter[2]
++#define TSR0_NCR1	cpu_to_le16(0x0002) // collision retry counter[1]
++#define TSR0_NCR0	cpu_to_le16(0x0001) // collision retry counter[0]
++#define TSR0_TERR	cpu_to_le16(0x8000) //
++#define TSR0_FDX	cpu_to_le16(0x4000) // current transaction is serviced by full duplex mode
++#define TSR0_GMII	cpu_to_le16(0x2000) // current transaction is serviced by GMII mode
++#define TSR0_LNKFL	cpu_to_le16(0x1000) // packet serviced during link down
++#define TSR0_SHDN	cpu_to_le16(0x0400) // shutdown case
++#define TSR0_CRS	cpu_to_le16(0x0200) // carrier sense lost
++#define TSR0_CDH	cpu_to_le16(0x0100) // AQE test fail (CD heartbeat)
+ 
+ //
+ // Bits in the TCR0 register
+@@ -197,25 +172,26 @@
+  */
+ 
+ struct rdesc0 {
+-	u16 RSR;		/* Receive status */
+-	u16 len:14;		/* Received packet length */
+-	u16 reserved:1;
+-	u16 owner:1;		/* Who owns this buffer ? */
++	__le16 RSR;		/* Receive status */
++	__le16 len;		/* bits 0--13; bit 15 - owner */
+ };
+ 
+ struct rdesc1 {
+-	u16 PQTAG;
++	__le16 PQTAG;
+ 	u8 CSM;
+ 	u8 IPKT;
+ };
+ 
++enum {
++	RX_INTEN = __constant_cpu_to_le16(0x8000)
++};
++
+ struct rx_desc {
+ 	struct rdesc0 rdesc0;
+ 	struct rdesc1 rdesc1;
+-	u32 pa_low;		/* Low 32 bit PCI address */
+-	u16 pa_high;		/* Next 16 bit PCI address (48 total) */
+-	u16 len:15;		/* Frame size */
+-	u16 inten:1;		/* Enable interrupt */
++	__le32 pa_low;		/* Low 32 bit PCI address */
++	__le16 pa_high;		/* Next 16 bit PCI address (48 total) */
++	__le16 size;		/* bits 0--14 - frame size, bit 15 - enable int. */
+ } __attribute__ ((__packed__));
+ 
+ /*
+@@ -223,32 +199,24 @@ struct rx_desc {
+  */
+ 
+ struct tdesc0 {
+-	u16 TSR;		/* Transmit status register */
+-	u16 pktsize:14;		/* Size of frame */
+-	u16 reserved:1;
+-	u16 owner:1;		/* Who owns the buffer */
++	__le16 TSR;		/* Transmit status register */
++	__le16 len;		/* bits 0--13 - size of frame, bit 15 - owner */
+ };
+ 
+-struct pqinf {			/* Priority queue info */
+-	u16 VID:12;
+-	u16 CFI:1;
+-	u16 priority:3;
+-} __attribute__ ((__packed__));
+-
+ struct tdesc1 {
+-	struct pqinf pqinf;
++	__le16 vlan;
+ 	u8 TCR;
+-	u8 TCPLS:2;
+-	u8 reserved:2;
+-	u8 CMDZ:4;
++	u8 cmd;			/* bits 0--1 - TCPLS, bits 4--7 - CMDZ */
+ } __attribute__ ((__packed__));
+ 
++enum {
++	TD_QUEUE = __constant_cpu_to_le16(0x8000)
++};
++
+ struct td_buf {
+-	u32 pa_low;
+-	u16 pa_high;
+-	u16 bufsize:14;
+-	u16 reserved:1;
+-	u16 queue:1;
++	__le32 pa_low;
++	__le16 pa_high;
++	__le16 size;		/* bits 0--13 - size, bit 15 - queue */
+ } __attribute__ ((__packed__));
+ 
+ struct tx_desc {
+@@ -276,7 +244,7 @@ struct velocity_td_info {
+ 
+ enum  velocity_owner {
+ 	OWNED_BY_HOST = 0,
+-	OWNED_BY_NIC = 1
++	OWNED_BY_NIC = __constant_cpu_to_le16(0x8000)
+ };
+ 
+ 
+@@ -1012,45 +980,45 @@ struct mac_regs {
+ 	volatile u8 RCR;
+ 	volatile u8 TCR;
+ 
+-	volatile u32 CR0Set;		/* 0x08 */
+-	volatile u32 CR0Clr;		/* 0x0C */
++	volatile __le32 CR0Set;		/* 0x08 */
++	volatile __le32 CR0Clr;		/* 0x0C */
+ 
+ 	volatile u8 MARCAM[8];		/* 0x10 */
+ 
+-	volatile u32 DecBaseHi;		/* 0x18 */
+-	volatile u16 DbfBaseHi;		/* 0x1C */
+-	volatile u16 reserved_1E;
++	volatile __le32 DecBaseHi;	/* 0x18 */
++	volatile __le16 DbfBaseHi;	/* 0x1C */
++	volatile __le16 reserved_1E;
+ 
+-	volatile u16 ISRCTL;		/* 0x20 */
++	volatile __le16 ISRCTL;		/* 0x20 */
+ 	volatile u8 TXESR;
+ 	volatile u8 RXESR;
+ 
+-	volatile u32 ISR;		/* 0x24 */
+-	volatile u32 IMR;
++	volatile __le32 ISR;		/* 0x24 */
++	volatile __le32 IMR;
+ 
+-	volatile u32 TDStatusPort;	/* 0x2C */
++	volatile __le32 TDStatusPort;	/* 0x2C */
+ 
+-	volatile u16 TDCSRSet;		/* 0x30 */
++	volatile __le16 TDCSRSet;	/* 0x30 */
+ 	volatile u8 RDCSRSet;
+ 	volatile u8 reserved_33;
+-	volatile u16 TDCSRClr;
++	volatile __le16 TDCSRClr;
+ 	volatile u8 RDCSRClr;
+ 	volatile u8 reserved_37;
+ 
+-	volatile u32 RDBaseLo;		/* 0x38 */
+-	volatile u16 RDIdx;		/* 0x3C */
+-	volatile u16 reserved_3E;
++	volatile __le32 RDBaseLo;	/* 0x38 */
++	volatile __le16 RDIdx;		/* 0x3C */
++	volatile __le16 reserved_3E;
+ 
+-	volatile u32 TDBaseLo[4];	/* 0x40 */
++	volatile __le32 TDBaseLo[4];	/* 0x40 */
+ 
+-	volatile u16 RDCSize;		/* 0x50 */
+-	volatile u16 TDCSize;		/* 0x52 */
+-	volatile u16 TDIdx[4];		/* 0x54 */
+-	volatile u16 tx_pause_timer;	/* 0x5C */
+-	volatile u16 RBRDU;		/* 0x5E */
++	volatile __le16 RDCSize;	/* 0x50 */
++	volatile __le16 TDCSize;	/* 0x52 */
++	volatile __le16 TDIdx[4];	/* 0x54 */
++	volatile __le16 tx_pause_timer;	/* 0x5C */
++	volatile __le16 RBRDU;		/* 0x5E */
+ 
+-	volatile u32 FIFOTest0;		/* 0x60 */
+-	volatile u32 FIFOTest1;		/* 0x64 */
++	volatile __le32 FIFOTest0;	/* 0x60 */
++	volatile __le32 FIFOTest1;	/* 0x64 */
+ 
+ 	volatile u8 CAMADDR;		/* 0x68 */
+ 	volatile u8 CAMCR;		/* 0x69 */
+@@ -1063,18 +1031,18 @@ struct mac_regs {
+ 	volatile u8 PHYSR1;
+ 	volatile u8 MIICR;
+ 	volatile u8 MIIADR;
+-	volatile u16 MIIDATA;
++	volatile __le16 MIIDATA;
+ 
+-	volatile u16 SoftTimer0;	/* 0x74 */
+-	volatile u16 SoftTimer1;
++	volatile __le16 SoftTimer0;	/* 0x74 */
++	volatile __le16 SoftTimer1;
+ 
+ 	volatile u8 CFGA;		/* 0x78 */
+ 	volatile u8 CFGB;
+ 	volatile u8 CFGC;
+ 	volatile u8 CFGD;
+ 
+-	volatile u16 DCFG;		/* 0x7C */
+-	volatile u16 MCFG;
++	volatile __le16 DCFG;		/* 0x7C */
++	volatile __le16 MCFG;
+ 
+ 	volatile u8 TBIST;		/* 0x80 */
+ 	volatile u8 RBIST;
+@@ -1086,9 +1054,9 @@ struct mac_regs {
+ 	volatile u8 rev_id;
+ 	volatile u8 PORSTS;
+ 
+-	volatile u32 MIBData;		/* 0x88 */
++	volatile __le32 MIBData;	/* 0x88 */
+ 
+-	volatile u16 EEWrData;
++	volatile __le16 EEWrData;
+ 
+ 	volatile u8 reserved_8E;
+ 	volatile u8 BPMDWr;
+@@ -1098,7 +1066,7 @@ struct mac_regs {
+ 	volatile u8 EECHKSUM;		/* 0x92 */
+ 	volatile u8 EECSR;
+ 
+-	volatile u16 EERdData;		/* 0x94 */
++	volatile __le16 EERdData;	/* 0x94 */
+ 	volatile u8 EADDR;
+ 	volatile u8 EMBCMD;
+ 
+@@ -1112,22 +1080,22 @@ struct mac_regs {
+ 	volatile u8 DEBUG;
+ 	volatile u8 CHIPGCR;
+ 
+-	volatile u16 WOLCRSet;		/* 0xA0 */
++	volatile __le16 WOLCRSet;	/* 0xA0 */
+ 	volatile u8 PWCFGSet;
+ 	volatile u8 WOLCFGSet;
+ 
+-	volatile u16 WOLCRClr;		/* 0xA4 */
++	volatile __le16 WOLCRClr;	/* 0xA4 */
+ 	volatile u8 PWCFGCLR;
+ 	volatile u8 WOLCFGClr;
+ 
+-	volatile u16 WOLSRSet;		/* 0xA8 */
+-	volatile u16 reserved_AA;
++	volatile __le16 WOLSRSet;	/* 0xA8 */
++	volatile __le16 reserved_AA;
+ 
+-	volatile u16 WOLSRClr;		/* 0xAC */
+-	volatile u16 reserved_AE;
++	volatile __le16 WOLSRClr;	/* 0xAC */
++	volatile __le16 reserved_AE;
+ 
+-	volatile u16 PatternCRC[8];	/* 0xB0 */
+-	volatile u32 ByteMask[4][4];	/* 0xC0 */
++	volatile __le16 PatternCRC[8];	/* 0xB0 */
++	volatile __le32 ByteMask[4][4];	/* 0xC0 */
+ } __attribute__ ((__packed__));
+ 
+ 
+@@ -1238,12 +1206,12 @@ typedef u8 MCAM_ADDR[ETH_ALEN];
+ struct arp_packet {
+ 	u8 dest_mac[ETH_ALEN];
+ 	u8 src_mac[ETH_ALEN];
+-	u16 type;
+-	u16 ar_hrd;
+-	u16 ar_pro;
++	__be16 type;
++	__be16 ar_hrd;
++	__be16 ar_pro;
+ 	u8 ar_hln;
+ 	u8 ar_pln;
+-	u16 ar_op;
++	__be16 ar_op;
+ 	u8 ar_sha[ETH_ALEN];
+ 	u8 ar_sip[4];
+ 	u8 ar_tha[ETH_ALEN];
+@@ -1253,7 +1221,7 @@ struct arp_packet {
+ struct _magic_packet {
+ 	u8 dest_mac[6];
+ 	u8 src_mac[6];
+-	u16 type;
++	__be16 type;
+ 	u8 MAC[16][6];
+ 	u8 password[6];
+ } __attribute__ ((__packed__));
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 5413dbf..e66de0c 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -24,6 +24,13 @@
+ #include <linux/virtio_net.h>
+ #include <linux/scatterlist.h>
+ 
++static int napi_weight = 128;
++module_param(napi_weight, int, 0444);
++
++static int csum = 1, gso = 1;
++module_param(csum, bool, 0444);
++module_param(gso, bool, 0444);
++
+ /* FIXME: MTU in config. */
+ #define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
+ 
+@@ -52,13 +59,14 @@ static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
+ 	sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
+ }
+ 
+-static bool skb_xmit_done(struct virtqueue *rvq)
++static void skb_xmit_done(struct virtqueue *svq)
+ {
+-	struct virtnet_info *vi = rvq->vdev->priv;
++	struct virtnet_info *vi = svq->vdev->priv;
+ 
+-	/* In case we were waiting for output buffers. */
++	/* Suppress further interrupts. */
++	svq->vq_ops->disable_cb(svq);
++	/* We were waiting for more output buffers. */
+ 	netif_wake_queue(vi->dev);
+-	return true;
+ }
+ 
+ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
+@@ -83,28 +91,16 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
+ 
+ 	if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
+ 		pr_debug("Needs csum!\n");
+-		skb->ip_summed = CHECKSUM_PARTIAL;
+-		skb->csum_start = hdr->csum_start;
+-		skb->csum_offset = hdr->csum_offset;
+-		if (skb->csum_start > skb->len - 2
+-		    || skb->csum_offset > skb->len - 2) {
+-			if (net_ratelimit())
+-				printk(KERN_WARNING "%s: csum=%u/%u len=%u\n",
+-				       dev->name, skb->csum_start,
+-				       skb->csum_offset, skb->len);
++		if (!skb_partial_csum_set(skb,hdr->csum_start,hdr->csum_offset))
+ 			goto frame_err;
+-		}
+ 	}
+ 
+ 	if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+ 		pr_debug("GSO!\n");
+-		switch (hdr->gso_type) {
++		switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
+ 		case VIRTIO_NET_HDR_GSO_TCPV4:
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+ 			break;
+-		case VIRTIO_NET_HDR_GSO_TCPV4_ECN:
+-			skb_shinfo(skb)->gso_type = SKB_GSO_TCP_ECN;
+-			break;
+ 		case VIRTIO_NET_HDR_GSO_UDP:
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ 			break;
+@@ -118,6 +114,9 @@ static void receive_skb(struct net_device *dev, struct sk_buff *skb,
+ 			goto frame_err;
+ 		}
+ 
++		if (hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
++			skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN;
++
+ 		skb_shinfo(skb)->gso_size = hdr->gso_size;
+ 		if (skb_shinfo(skb)->gso_size == 0) {
+ 			if (net_ratelimit())
+@@ -170,12 +169,14 @@ static void try_fill_recv(struct virtnet_info *vi)
+ 	vi->rvq->vq_ops->kick(vi->rvq);
+ }
+ 
+-static bool skb_recv_done(struct virtqueue *rvq)
++static void skb_recv_done(struct virtqueue *rvq)
+ {
+ 	struct virtnet_info *vi = rvq->vdev->priv;
+-	netif_rx_schedule(vi->dev, &vi->napi);
+-	/* Suppress further interrupts. */
+-	return false;
++	/* Schedule NAPI, Suppress further interrupts if successful. */
++	if (netif_rx_schedule_prep(vi->dev, &vi->napi)) {
++		rvq->vq_ops->disable_cb(rvq);
++		__netif_rx_schedule(vi->dev, &vi->napi);
++	}
+ }
+ 
+ static int virtnet_poll(struct napi_struct *napi, int budget)
+@@ -201,7 +202,7 @@ again:
+ 	/* Out of packets? */
+ 	if (received < budget) {
+ 		netif_rx_complete(vi->dev, napi);
+-		if (unlikely(!vi->rvq->vq_ops->restart(vi->rvq))
++		if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
+ 		    && netif_rx_reschedule(vi->dev, napi))
+ 			goto again;
+ 	}
+@@ -236,8 +237,6 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 
+ 	pr_debug("%s: xmit %p %s\n", dev->name, skb, print_mac(mac, dest));
+ 
+-	free_old_xmit_skbs(vi);
+-
+ 	/* Encode metadata header at front. */
+ 	hdr = skb_vnet_hdr(skb);
+ 	if (skb->ip_summed == CHECKSUM_PARTIAL) {
+@@ -250,10 +249,9 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	}
+ 
+ 	if (skb_is_gso(skb)) {
++		hdr->hdr_len = skb_transport_header(skb) - skb->data;
+ 		hdr->gso_size = skb_shinfo(skb)->gso_size;
+-		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
+-			hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4_ECN;
+-		else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
++		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4)
+ 			hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ 		else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+ 			hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+@@ -261,19 +259,34 @@ static int start_xmit(struct sk_buff *skb, struct net_device *dev)
+ 			hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ 		else
+ 			BUG();
++		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
++			hdr->gso_type |= VIRTIO_NET_HDR_GSO_ECN;
+ 	} else {
+ 		hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
+-		hdr->gso_size = 0;
++		hdr->gso_size = hdr->hdr_len = 0;
+ 	}
+ 
+ 	vnet_hdr_to_sg(sg, skb);
+ 	num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
+ 	__skb_queue_head(&vi->send, skb);
++
++again:
++	/* Free up any pending old buffers before queueing new ones. */
++	free_old_xmit_skbs(vi);
+ 	err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
+ 	if (err) {
+ 		pr_debug("%s: virtio not prepared to send\n", dev->name);
+-		skb_unlink(skb, &vi->send);
+ 		netif_stop_queue(dev);
++
++		/* Activate callback for using skbs: if this fails it
++		 * means some were used in the meantime. */
++		if (unlikely(!vi->svq->vq_ops->enable_cb(vi->svq))) {
++			printk("Unlikely: restart svq failed\n");
++			netif_start_queue(dev);
++			goto again;
++		}
++		__skb_unlink(skb, &vi->send);
++
+ 		return NETDEV_TX_BUSY;
+ 	}
+ 	vi->svq->vq_ops->kick(vi->svq);
+@@ -285,45 +298,31 @@ static int virtnet_open(struct net_device *dev)
+ {
+ 	struct virtnet_info *vi = netdev_priv(dev);
+ 
+-	try_fill_recv(vi);
++	napi_enable(&vi->napi);
+ 
+-	/* If we didn't even get one input buffer, we're useless. */
+-	if (vi->num == 0)
+-		return -ENOMEM;
++	/* If all buffers were filled by other side before we napi_enabled, we
++	 * won't get another interrupt, so process any outstanding packets
++	 * now.  virtnet_poll wants re-enable the queue, so we disable here. */
++	vi->rvq->vq_ops->disable_cb(vi->rvq);
++	netif_rx_schedule(vi->dev, &vi->napi);
+ 
+-	napi_enable(&vi->napi);
+ 	return 0;
+ }
+ 
+ static int virtnet_close(struct net_device *dev)
+ {
+ 	struct virtnet_info *vi = netdev_priv(dev);
+-	struct sk_buff *skb;
+ 
+ 	napi_disable(&vi->napi);
+ 
+-	/* networking core has neutered skb_xmit_done/skb_recv_done, so don't
+-	 * worry about races vs. get(). */
+-	vi->rvq->vq_ops->shutdown(vi->rvq);
+-	while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
+-		kfree_skb(skb);
+-		vi->num--;
+-	}
+-	vi->svq->vq_ops->shutdown(vi->svq);
+-	while ((skb = __skb_dequeue(&vi->send)) != NULL)
+-		kfree_skb(skb);
+-
+-	BUG_ON(vi->num != 0);
+ 	return 0;
+ }
+ 
+ static int virtnet_probe(struct virtio_device *vdev)
+ {
+ 	int err;
+-	unsigned int len;
+ 	struct net_device *dev;
+ 	struct virtnet_info *vi;
+-	void *token;
+ 
+ 	/* Allocate ourselves a network device with room for our info */
+ 	dev = alloc_etherdev(sizeof(struct virtnet_info));
+@@ -331,7 +330,6 @@ static int virtnet_probe(struct virtio_device *vdev)
+ 		return -ENOMEM;
+ 
+ 	/* Set up network device as normal. */
+-	ether_setup(dev);
+ 	dev->open = virtnet_open;
+ 	dev->stop = virtnet_close;
+ 	dev->hard_start_xmit = start_xmit;
+@@ -339,42 +337,37 @@ static int virtnet_probe(struct virtio_device *vdev)
+ 	SET_NETDEV_DEV(dev, &vdev->dev);
+ 
+ 	/* Do we support "hardware" checksums? */
+-	token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_F, &len);
+-	if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_NO_CSUM)) {
++	if (csum && vdev->config->feature(vdev, VIRTIO_NET_F_CSUM)) {
+ 		/* This opens up the world of extra features. */
+ 		dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+-		if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4))
+-			dev->features |= NETIF_F_TSO;
+-		if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_UFO))
+-			dev->features |= NETIF_F_UFO;
+-		if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO4_ECN))
+-			dev->features |= NETIF_F_TSO_ECN;
+-		if (virtio_use_bit(vdev, token, len, VIRTIO_NET_F_TSO6))
+-			dev->features |= NETIF_F_TSO6;
++		if (gso && vdev->config->feature(vdev, VIRTIO_NET_F_GSO)) {
++			dev->features |= NETIF_F_TSO | NETIF_F_UFO
++				| NETIF_F_TSO_ECN | NETIF_F_TSO6;
++		}
+ 	}
+ 
+ 	/* Configuration may specify what MAC to use.  Otherwise random. */
+-	token = vdev->config->find(vdev, VIRTIO_CONFIG_NET_MAC_F, &len);
+-	if (token) {
+-		dev->addr_len = len;
+-		vdev->config->get(vdev, token, dev->dev_addr, len);
++	if (vdev->config->feature(vdev, VIRTIO_NET_F_MAC)) {
++		vdev->config->get(vdev,
++				  offsetof(struct virtio_net_config, mac),
++				  dev->dev_addr, dev->addr_len);
+ 	} else
+ 		random_ether_addr(dev->dev_addr);
+ 
+ 	/* Set up our device-specific information */
+ 	vi = netdev_priv(dev);
+-	netif_napi_add(dev, &vi->napi, virtnet_poll, 16);
++	netif_napi_add(dev, &vi->napi, virtnet_poll, napi_weight);
+ 	vi->dev = dev;
+ 	vi->vdev = vdev;
+ 
+ 	/* We expect two virtqueues, receive then send. */
+-	vi->rvq = vdev->config->find_vq(vdev, skb_recv_done);
++	vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
+ 	if (IS_ERR(vi->rvq)) {
+ 		err = PTR_ERR(vi->rvq);
+ 		goto free;
+ 	}
+ 
+-	vi->svq = vdev->config->find_vq(vdev, skb_xmit_done);
++	vi->svq = vdev->config->find_vq(vdev, 1, skb_xmit_done);
+ 	if (IS_ERR(vi->svq)) {
+ 		err = PTR_ERR(vi->svq);
+ 		goto free_recv;
+@@ -389,10 +382,22 @@ static int virtnet_probe(struct virtio_device *vdev)
+ 		pr_debug("virtio_net: registering device failed\n");
+ 		goto free_send;
+ 	}
++
++	/* Last of all, set up some receive buffers. */
++	try_fill_recv(vi);
++
++	/* If we didn't even get one input buffer, we're useless. */
++	if (vi->num == 0) {
++		err = -ENOMEM;
++		goto unregister;
++	}
++
+ 	pr_debug("virtnet: registered device %s\n", dev->name);
+ 	vdev->priv = vi;
+ 	return 0;
+ 
++unregister:
++	unregister_netdev(dev);
+ free_send:
+ 	vdev->config->del_vq(vi->svq);
+ free_recv:
+@@ -405,6 +410,20 @@ free:
+ static void virtnet_remove(struct virtio_device *vdev)
+ {
+ 	struct virtnet_info *vi = vdev->priv;
++	struct sk_buff *skb;
++
++	/* Stop all the virtqueues. */
++	vdev->config->reset(vdev);
++
++	/* Free our skbs in send and recv queues, if any. */
++	while ((skb = __skb_dequeue(&vi->recv)) != NULL) {
++		kfree_skb(skb);
++		vi->num--;
++	}
++	while ((skb = __skb_dequeue(&vi->send)) != NULL)
++		kfree_skb(skb);
++
++	BUG_ON(vi->num != 0);
+ 
+ 	vdev->config->del_vq(vi->svq);
+ 	vdev->config->del_vq(vi->rvq);
 diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
 index ff37bf4..1d706ea 100644
 --- a/drivers/net/wan/cosa.c
@@ -572838,6 +631382,28 @@
  	class_destroy(cosa_class);
  	for (cosa=cosa_cards; nr_cards--; cosa++) {
  		/* Clean up the per-channel data */
+diff --git a/drivers/net/wan/cycx_drv.c b/drivers/net/wan/cycx_drv.c
+index d347d59..d14e667 100644
+--- a/drivers/net/wan/cycx_drv.c
++++ b/drivers/net/wan/cycx_drv.c
+@@ -322,7 +322,7 @@ static int cycx_data_boot(void __iomem *addr, u8 *code, u32 len)
+ 	void __iomem *pt_boot_cmd = addr + CMD_OFFSET;
+ 	u32 i;
+ 
+-	/* boot buffer lenght */
++	/* boot buffer length */
+ 	writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
+ 	writew(GEN_DEFPAR, pt_boot_cmd);
+ 
+@@ -353,7 +353,7 @@ static int cycx_code_boot(void __iomem *addr, u8 *code, u32 len)
+ 	void __iomem *pt_boot_cmd = addr + CMD_OFFSET;
+ 	u32 i;
+ 
+-	/* boot buffer lenght */
++	/* boot buffer length */
+ 	writew(CFM_LOAD_BUFSZ, pt_boot_cmd + sizeof(u16));
+ 	writew(GEN_DEFPAR, pt_boot_cmd);
+ 
 diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
 index 12dae8e..cf27bf4 100644
 --- a/drivers/net/wan/farsync.c
@@ -577053,7 +635619,7 @@
 +#endif
 diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
 new file mode 100644
-index 0000000..d6599d2
+index 0000000..ddc8714
 --- /dev/null
 +++ b/drivers/net/wireless/ath5k/base.c
 @@ -0,0 +1,2974 @@
@@ -577212,7 +635778,7 @@
 +#define ath5k_pci_resume NULL
 +#endif /* CONFIG_PM */
 +
-+static struct pci_driver ath5k_pci_drv_id = {
++static struct pci_driver ath5k_pci_driver = {
 +	.name		= "ath5k_pci",
 +	.id_table	= ath5k_pci_id_table,
 +	.probe		= ath5k_pci_probe,
@@ -577388,7 +635954,7 @@
 +
 +	ath5k_debug_init();
 +
-+	ret = pci_register_driver(&ath5k_pci_drv_id);
++	ret = pci_register_driver(&ath5k_pci_driver);
 +	if (ret) {
 +		printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
 +		return ret;
@@ -577400,7 +635966,7 @@
 +static void __exit
 +exit_ath5k_pci(void)
 +{
-+	pci_unregister_driver(&ath5k_pci_drv_id);
++	pci_unregister_driver(&ath5k_pci_driver);
 +
 +	ath5k_debug_finish();
 +}
@@ -592188,7 +650754,7 @@
  
  obj-$(CONFIG_B43)		+= b43.o
 diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
-index 7b6fc1a..32a24f5 100644
+index 7b6fc1a..08a011f 100644
 --- a/drivers/net/wireless/b43/b43.h
 +++ b/drivers/net/wireless/b43/b43.h
 @@ -35,8 +35,8 @@
@@ -592431,7 +650997,7 @@
  	/* Firmware revision */
  	u16 rev;
  	/* Firmware patchlevel */
-@@ -683,21 +719,17 @@ struct b43_wldev {
+@@ -683,21 +719,18 @@ struct b43_wldev {
  	/* Saved init status for handling suspend. */
  	int suspend_init_status;
  
@@ -592442,6 +651008,7 @@
  	bool short_preamble;	/* TRUE, if short preamble is enabled. */
  	bool short_slot;	/* TRUE, if short slot timing is enabled. */
  	bool radio_hw_enable;	/* saved state of radio hardware enabled state */
++	bool suspend_in_progress;	/* TRUE, if we are in a suspend/resume cycle */
  
  	/* PHY/Radio device. */
  	struct b43_phy phy;
@@ -592457,7 +651024,7 @@
  
  	/* Various statistics about the physical device. */
  	struct b43_stats stats;
-@@ -732,9 +764,6 @@ struct b43_wldev {
+@@ -732,9 +765,6 @@ struct b43_wldev {
  	u8 max_nr_keys;
  	struct b43_key key[58];
  
@@ -592467,7 +651034,7 @@
  	/* Firmware data */
  	struct b43_firmware fw;
  
-@@ -752,28 +781,6 @@ static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
+@@ -752,28 +782,6 @@ static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
  	return hw->priv;
  }
  
@@ -593036,7 +651603,7 @@
 -#endif /* CONFIG_B43_DMA */
  #endif /* B43_DMA_H_ */
 diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
-index 6c0e2b9..4b590d8 100644
+index 6c0e2b9..0908335 100644
 --- a/drivers/net/wireless/b43/leds.c
 +++ b/drivers/net/wireless/b43/leds.c
 @@ -4,7 +4,7 @@
@@ -593048,7 +651615,19 @@
    Copyright (c) 2005-2007 Michael Buesch <mb at bu3sch.de>
    Copyright (c) 2005 Danny van Dyk <kugelfang at gentoo.org>
    Copyright (c) 2005 Andreas Jaggi <andreas.jaggi at waterwave.ch>
-@@ -190,10 +190,10 @@ void b43_leds_init(struct b43_wldev *dev)
+@@ -116,7 +116,10 @@ static void b43_unregister_led(struct b43_led *led)
+ {
+ 	if (!led->dev)
+ 		return;
+-	led_classdev_unregister(&led->led_dev);
++	if (led->dev->suspend_in_progress)
++		led_classdev_unregister_suspended(&led->led_dev);
++	else
++		led_classdev_unregister(&led->led_dev);
+ 	b43_led_turn_off(led->dev, led->index, led->activelow);
+ 	led->dev = NULL;
+ }
+@@ -190,10 +193,10 @@ void b43_leds_init(struct b43_wldev *dev)
  	enum b43_led_behaviour behaviour;
  	bool activelow;
  
@@ -593285,7 +651864,7 @@
  	}
  	b43_radio_selectchannel(dev, sav->old_channel, 1);
 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
-index 1c93b4f..64c154d 100644
+index 1c93b4f..ef65c41 100644
 --- a/drivers/net/wireless/b43/main.c
 +++ b/drivers/net/wireless/b43/main.c
 @@ -3,7 +3,7 @@
@@ -593297,7 +651876,15 @@
    Copyright (c) 2005, 2006 Michael Buesch <mb at bu3sch.de>
    Copyright (c) 2005 Danny van Dyk <kugelfang at gentoo.org>
    Copyright (c) 2005 Andreas Jaggi <andreas.jaggi at waterwave.ch>
-@@ -46,7 +46,6 @@
+@@ -38,6 +38,7 @@
+ #include <linux/wireless.h>
+ #include <linux/workqueue.h>
+ #include <linux/skbuff.h>
++#include <linux/io.h>
+ #include <linux/dma-mapping.h>
+ #include <asm/unaligned.h>
+ 
+@@ -46,7 +47,6 @@
  #include "debugfs.h"
  #include "phy.h"
  #include "dma.h"
@@ -593305,7 +651892,7 @@
  #include "sysfs.h"
  #include "xmit.h"
  #include "lo.h"
-@@ -58,31 +57,12 @@ MODULE_AUTHOR("Stefano Brivio");
+@@ -58,31 +58,12 @@ MODULE_AUTHOR("Stefano Brivio");
  MODULE_AUTHOR("Michael Buesch");
  MODULE_LICENSE("GPL");
  
@@ -593337,7 +651924,7 @@
  static char modparam_fwpostfix[16];
  module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
  MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
-@@ -101,6 +81,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
+@@ -101,6 +82,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
  	SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
@@ -593346,7 +651933,7 @@
  	SSB_DEVTABLE_END
  };
  
-@@ -150,7 +132,7 @@ static struct ieee80211_rate __b43_ratetable[] = {
+@@ -150,7 +133,7 @@ static struct ieee80211_rate __b43_ratetable[] = {
  		.power_level	= 0xFF,				\
  		.antenna_max	= 0xFF,				\
  	}
@@ -593355,7 +651942,7 @@
  	CHANTAB_ENT(1, 2412),
  	CHANTAB_ENT(2, 2417),
  	CHANTAB_ENT(3, 2422),
-@@ -166,9 +148,10 @@ static struct ieee80211_channel b43_bg_chantable[] = {
+@@ -166,9 +149,10 @@ static struct ieee80211_channel b43_bg_chantable[] = {
  	CHANTAB_ENT(13, 2472),
  	CHANTAB_ENT(14, 2484),
  };
@@ -593368,7 +651955,7 @@
  	CHANTAB_ENT(36, 5180),
  	CHANTAB_ENT(40, 5200),
  	CHANTAB_ENT(44, 5220),
-@@ -183,8 +166,8 @@ static struct ieee80211_channel b43_a_chantable[] = {
+@@ -183,8 +167,8 @@ static struct ieee80211_channel b43_a_chantable[] = {
  	CHANTAB_ENT(161, 5805),
  	CHANTAB_ENT(165, 5825),
  };
@@ -593379,7 +651966,7 @@
  
  static void b43_wireless_core_exit(struct b43_wldev *dev);
  static int b43_wireless_core_init(struct b43_wldev *dev);
-@@ -269,13 +252,12 @@ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
+@@ -269,13 +253,12 @@ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
  	b43_write32(dev, B43_MMIO_RAM_DATA, val);
  }
  
@@ -593395,7 +651982,7 @@
  	control = routing;
  	control <<= 16;
  	control |= offset;
-@@ -284,8 +266,11 @@ static inline
+@@ -284,8 +267,11 @@ static inline
  
  u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
  {
@@ -593407,7 +651994,7 @@
  	if (routing == B43_SHM_SHARED) {
  		B43_WARN_ON(offset & 0x0001);
  		if (offset & 0x0003) {
-@@ -296,20 +281,25 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
+@@ -296,20 +282,25 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
  			b43_shm_control_word(dev, routing, (offset >> 2) + 1);
  			ret |= b43_read16(dev, B43_MMIO_SHM_DATA);
  
@@ -593434,7 +652021,7 @@
  	if (routing == B43_SHM_SHARED) {
  		B43_WARN_ON(offset & 0x0001);
  		if (offset & 0x0003) {
-@@ -317,55 +307,63 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
+@@ -317,55 +308,63 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
  			b43_shm_control_word(dev, routing, offset >> 2);
  			ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
  
@@ -593507,7 +652094,7 @@
  }
  
  /* Read HostFlags */
-@@ -1012,9 +1010,8 @@ static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
+@@ -1012,9 +1011,8 @@ static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
  static void b43_generate_noise_sample(struct b43_wldev *dev)
  {
  	b43_jssi_write(dev, 0x7F7F7F7F);
@@ -593519,7 +652106,7 @@
  	B43_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel);
  }
  
-@@ -1100,18 +1097,18 @@ static void handle_irq_tbtt_indication(struct b43_wldev *dev)
+@@ -1100,18 +1098,18 @@ static void handle_irq_tbtt_indication(struct b43_wldev *dev)
  		if (1 /*FIXME: the last PSpoll frame was sent successfully */ )
  			b43_power_saving_ctl_bits(dev, 0);
  	}
@@ -593545,7 +652132,7 @@
  }
  
  static void handle_irq_pmq(struct b43_wldev *dev)
-@@ -1166,15 +1163,59 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
+@@ -1166,15 +1164,59 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
  				      u16 ram_offset,
  				      u16 shm_size_offset, u8 rate)
  {
@@ -593611,7 +652198,7 @@
  }
  
  static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
-@@ -1187,7 +1228,7 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
+@@ -1187,7 +1229,7 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
  	plcp.data = 0;
  	b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
  	dur = ieee80211_generic_frame_duration(dev->wl->hw,
@@ -593620,7 +652207,7 @@
  					       B43_RATE_TO_BASE100KBPS(rate));
  	/* Write PLCP in two parts and timing for packet transfer */
  	tmp = le32_to_cpu(plcp.data);
-@@ -1202,40 +1243,43 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
+@@ -1202,40 +1244,43 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
   * 2) Patching duration field
   * 3) Stripping TIM
   */
@@ -593682,7 +652269,7 @@
  	}
  	*dest_size = dest_pos;
  	hdr = (struct ieee80211_hdr *)dest_data;
-@@ -1244,7 +1288,7 @@ static u8 *b43_generate_probe_resp(struct b43_wldev *dev,
+@@ -1244,7 +1289,7 @@ static u8 *b43_generate_probe_resp(struct b43_wldev *dev,
  	hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
  					 IEEE80211_STYPE_PROBE_RESP);
  	dur = ieee80211_generic_frame_duration(dev->wl->hw,
@@ -593691,7 +652278,7 @@
  					       B43_RATE_TO_BASE100KBPS(rate));
  	hdr->duration_id = dur;
  
-@@ -1255,11 +1299,10 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
+@@ -1255,11 +1300,10 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
  					  u16 ram_offset,
  					  u16 shm_size_offset, u8 rate)
  {
@@ -593705,17 +652292,25 @@
  	probe_resp_data = b43_generate_probe_resp(dev, &size, rate);
  	if (unlikely(!probe_resp_data))
  		return;
-@@ -1278,39 +1321,21 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
+@@ -1278,39 +1322,21 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
  	kfree(probe_resp_data);
  }
  
 -static int b43_refresh_cached_beacon(struct b43_wldev *dev,
 -				     struct sk_buff *beacon)
--{
++/* Asynchronously update the packet templates in template RAM.
++ * Locking: Requires wl->irq_lock to be locked. */
++static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
+ {
 -	if (dev->cached_beacon)
 -		kfree_skb(dev->cached_beacon);
 -	dev->cached_beacon = beacon;
--
++	/* This is the top half of the ansynchronous beacon update.
++	 * The bottom half is the beacon IRQ.
++	 * Beacon update must be asynchronous to avoid sending an
++	 * invalid beacon. This can happen for example, if the firmware
++	 * transmits a beacon while we are updating it. */
+ 
 -	return 0;
 -}
 -
@@ -593735,17 +652330,9 @@
 -}
 -
 -static void b43_refresh_templates(struct b43_wldev *dev, struct sk_buff *beacon)
-+/* Asynchronously update the packet templates in template RAM.
-+ * Locking: Requires wl->irq_lock to be locked. */
-+static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
- {
+-{
 -	int err;
-+	/* This is the top half of the ansynchronous beacon update.
-+	 * The bottom half is the beacon IRQ.
-+	 * Beacon update must be asynchronous to avoid sending an
-+	 * invalid beacon. This can happen for example, if the firmware
-+	 * transmits a beacon while we are updating it. */
- 
+-
 -	err = b43_refresh_cached_beacon(dev, beacon);
 -	if (unlikely(err))
 -		return;
@@ -593758,7 +652345,7 @@
  }
  
  static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
-@@ -1346,33 +1371,34 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
+@@ -1346,33 +1372,34 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
  
  static void handle_irq_beacon(struct b43_wldev *dev)
  {
@@ -593814,7 +652401,7 @@
  }
  
  static void handle_irq_ucode_debug(struct b43_wldev *dev)
-@@ -1402,8 +1428,17 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
+@@ -1402,8 +1429,17 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
  	if (unlikely(reason & B43_IRQ_MAC_TXERR))
  		b43err(dev->wl, "MAC transmission error\n");
  
@@ -593833,7 +652420,7 @@
  
  	if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
  					  B43_DMAIRQ_NONFATALMASK))) {
-@@ -1445,20 +1480,12 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
+@@ -1445,20 +1481,12 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
  		handle_irq_noise(dev);
  
  	/* Check the DMA reason registers for received data. */
@@ -593858,7 +652445,7 @@
  	B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
  	B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
  
-@@ -1470,29 +1497,8 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
+@@ -1470,29 +1498,8 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
  	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
  }
  
@@ -593888,7 +652475,7 @@
  	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
  
  	b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
-@@ -1551,54 +1557,73 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
+@@ -1551,54 +1558,73 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
  	return ret;
  }
  
@@ -593979,7 +652566,7 @@
  			goto err_format;
  		/* fallthrough */
  	case B43_FW_TYPE_IV:
-@@ -1609,10 +1634,15 @@ static int do_request_fw(struct b43_wldev *dev,
+@@ -1609,10 +1635,15 @@ static int do_request_fw(struct b43_wldev *dev,
  		goto err_format;
  	}
  
@@ -593996,7 +652583,7 @@
  	return -EPROTO;
  }
  
-@@ -1624,90 +1654,101 @@ static int b43_request_firmware(struct b43_wldev *dev)
+@@ -1624,90 +1655,101 @@ static int b43_request_firmware(struct b43_wldev *dev)
  	u32 tmshigh;
  	int err;
  
@@ -594166,7 +652753,7 @@
  	goto error;
  
  err_no_ucode:
-@@ -1737,22 +1778,33 @@ static int b43_upload_microcode(struct b43_wldev *dev)
+@@ -1737,22 +1779,33 @@ static int b43_upload_microcode(struct b43_wldev *dev)
  	const __be32 *data;
  	unsigned int i, len;
  	u16 fwrev, fwpatch, fwdate, fwtime;
@@ -594206,7 +652793,7 @@
  		b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);
  		b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);
  		/* No need for autoinc bit in SHM_HW */
-@@ -1764,9 +1816,12 @@ static int b43_upload_microcode(struct b43_wldev *dev)
+@@ -1764,9 +1817,12 @@ static int b43_upload_microcode(struct b43_wldev *dev)
  	}
  
  	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
@@ -594222,7 +652809,7 @@
  
  	/* Wait for the microcode to load and respond */
  	i = 0;
-@@ -1775,13 +1830,17 @@ static int b43_upload_microcode(struct b43_wldev *dev)
+@@ -1775,13 +1831,17 @@ static int b43_upload_microcode(struct b43_wldev *dev)
  		if (tmp == B43_IRQ_MAC_SUSPENDED)
  			break;
  		i++;
@@ -594244,7 +652831,7 @@
  	}
  	b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);	/* dummy read */
  
-@@ -1795,10 +1854,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
+@@ -1795,10 +1855,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
  		b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from "
  		       "binary drivers older than version 4.x is unsupported. "
  		       "You must upgrade your firmware files.\n");
@@ -594257,7 +652844,7 @@
  	}
  	b43dbg(dev->wl, "Loading firmware version %u.%u "
  	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
-@@ -1809,7 +1867,20 @@ static int b43_upload_microcode(struct b43_wldev *dev)
+@@ -1809,7 +1868,20 @@ static int b43_upload_microcode(struct b43_wldev *dev)
  	dev->fw.rev = fwrev;
  	dev->fw.patch = fwpatch;
  
@@ -594279,7 +652866,7 @@
  	return err;
  }
  
-@@ -1869,7 +1940,7 @@ static int b43_write_initvals(struct b43_wldev *dev,
+@@ -1869,7 +1941,7 @@ static int b43_write_initvals(struct b43_wldev *dev,
  
  err_format:
  	b43err(dev->wl, "Initial Values Firmware file-format error.\n");
@@ -594288,7 +652875,7 @@
  
  	return -EPROTO;
  }
-@@ -1883,19 +1954,19 @@ static int b43_upload_initvals(struct b43_wldev *dev)
+@@ -1883,19 +1955,19 @@ static int b43_upload_initvals(struct b43_wldev *dev)
  	size_t count;
  	int err;
  
@@ -594315,7 +652902,7 @@
  		if (err)
  			goto out;
  	}
-@@ -1932,7 +2003,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
+@@ -1932,7 +2004,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
  		mask |= 0x0180;
  		set |= 0x0180;
  	}
@@ -594324,7 +652911,7 @@
  		b43_write16(dev, B43_MMIO_GPIO_MASK,
  			    b43_read16(dev, B43_MMIO_GPIO_MASK)
  			    | 0x0200);
-@@ -2102,6 +2173,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
+@@ -2102,6 +2174,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
  	switch (dev->phy.type) {
  	case B43_PHYTYPE_A:
  	case B43_PHYTYPE_G:
@@ -594332,7 +652919,7 @@
  		b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
  		b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
  		b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
-@@ -2131,13 +2203,19 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
+@@ -2131,13 +2204,19 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
  
  	switch (antenna) {
  	case B43_ANTENNA0:
@@ -594355,7 +652942,7 @@
  		break;
  	default:
  		B43_WARN_ON(1);
-@@ -2147,15 +2225,15 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
+@@ -2147,15 +2226,15 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
  
  	/* For Beacons */
  	tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
@@ -594374,7 +652961,7 @@
  	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
  }
  
-@@ -2174,11 +2252,15 @@ static int b43_chip_init(struct b43_wldev *dev)
+@@ -2174,11 +2253,15 @@ static int b43_chip_init(struct b43_wldev *dev)
  {
  	struct b43_phy *phy = &dev->phy;
  	int err, tmp;
@@ -594393,7 +652980,7 @@
  
  	err = b43_request_firmware(dev);
  	if (err)
-@@ -2223,14 +2305,6 @@ static int b43_chip_init(struct b43_wldev *dev)
+@@ -2223,14 +2306,6 @@ static int b43_chip_init(struct b43_wldev *dev)
  	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
  		    | B43_MACCTL_INFRA);
  
@@ -594408,7 +652995,7 @@
  	/* Probe Response Timeout value */
  	/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
  	b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000);
-@@ -2292,9 +2366,11 @@ static void b43_periodic_every60sec(struct b43_wldev *dev)
+@@ -2292,9 +2367,11 @@ static void b43_periodic_every60sec(struct b43_wldev *dev)
  {
  	struct b43_phy *phy = &dev->phy;
  
@@ -594421,7 +653008,7 @@
  		b43_mac_suspend(dev);
  		b43_calc_nrssi_slope(dev);
  		if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
-@@ -2346,6 +2422,9 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
+@@ -2346,6 +2423,9 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
  	}
  	b43_phy_xmitpower(dev);	//FIXME: unless scanning?
  	//TODO for APHY (temperature?)
@@ -594431,7 +653018,7 @@
  }
  
  static void do_periodic_work(struct b43_wldev *dev)
-@@ -2403,32 +2482,42 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
+@@ -2403,32 +2483,42 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
  	queue_delayed_work(dev->wl->hw->workqueue, work, 0);
  }
  
@@ -594489,7 +653076,20 @@
  	b43err(dev->wl, "Failed to validate the chipaccess\n");
  	return -ENODEV;
  }
-@@ -2491,40 +2580,35 @@ static int b43_rng_init(struct b43_wl *wl)
+@@ -2465,10 +2555,10 @@ static int b43_rng_read(struct hwrng *rng, u32 * data)
+ 	return (sizeof(u16));
+ }
+ 
+-static void b43_rng_exit(struct b43_wl *wl)
++static void b43_rng_exit(struct b43_wl *wl, bool suspended)
+ {
+ 	if (wl->rng_initialized)
+-		hwrng_unregister(&wl->rng);
++		__hwrng_unregister(&wl->rng, suspended);
+ }
+ 
+ static int b43_rng_init(struct b43_wl *wl)
+@@ -2491,40 +2581,35 @@ static int b43_rng_init(struct b43_wl *wl)
  	return err;
  }
  
@@ -594540,7 +653140,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	struct b43_wldev *dev = wl->current_dev;
-@@ -2535,19 +2619,16 @@ static int b43_get_tx_stats(struct ieee80211_hw *hw,
+@@ -2535,19 +2620,16 @@ static int b43_get_tx_stats(struct ieee80211_hw *hw,
  		goto out;
  	spin_lock_irqsave(&wl->irq_lock, flags);
  	if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
@@ -594564,7 +653164,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	unsigned long flags;
-@@ -2686,8 +2767,36 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
+@@ -2686,8 +2768,36 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
  	return err;
  }
  
@@ -594574,7 +653174,7 @@
 + * "antenna_nr" is the antenna identifier we got from ieee80211. */
 +u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
 +				  u8 antenna_nr)
- {
++{
 +	u8 antenna_mask;
 +
 +	if (antenna_nr == 0) {
@@ -594597,12 +653197,12 @@
 +}
 +
 +static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
-+{
+ {
 +	antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
  	switch (antenna) {
  	case 0:		/* default/diversity */
  		return B43_ANTENNA_DEFAULT;
-@@ -2695,26 +2804,26 @@ static int b43_antenna_from_ieee80211(u8 antenna)
+@@ -2695,26 +2805,26 @@ static int b43_antenna_from_ieee80211(u8 antenna)
  		return B43_ANTENNA0;
  	case 2:		/* Antenna 1 */
  		return B43_ANTENNA1;
@@ -594635,7 +653235,7 @@
  	mutex_lock(&wl->mutex);
  
  	/* Switch the PHY mode (if necessary). */
-@@ -2764,6 +2873,8 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+@@ -2764,6 +2874,8 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
  			b43_short_slot_timing_disable(dev);
  	}
  
@@ -594644,7 +653244,7 @@
  	/* Adjust the desired TX power level. */
  	if (conf->power_level != 0) {
  		if (conf->power_level != phy->power_level) {
-@@ -2773,8 +2884,10 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+@@ -2773,8 +2885,10 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
  	}
  
  	/* Antennas for RX and management frame TX. */
@@ -594657,7 +653257,7 @@
  
  	/* Update templates for AP mode. */
  	if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
-@@ -2805,23 +2918,30 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+@@ -2805,23 +2919,30 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
  	return err;
  }
  
@@ -594693,7 +653293,7 @@
  	switch (key->alg) {
  	case ALG_WEP:
  		if (key->keylen == 5)
-@@ -2837,20 +2957,11 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+@@ -2837,20 +2958,11 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
  		break;
  	default:
  		B43_WARN_ON(1);
@@ -594715,7 +653315,7 @@
  
  	switch (cmd) {
  	case SET_KEY:
-@@ -2896,7 +3007,6 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+@@ -2896,7 +3008,6 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
  out_unlock:
  	spin_unlock_irqrestore(&wl->irq_lock, flags);
  	mutex_unlock(&wl->mutex);
@@ -594723,7 +653323,7 @@
  	if (!err) {
  		b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
  		       "mac: %s\n",
-@@ -2906,9 +3016,9 @@ out:
+@@ -2906,9 +3017,9 @@ out:
  	return err;
  }
  
@@ -594736,7 +653336,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	struct b43_wldev *dev = wl->current_dev;
-@@ -2943,8 +3053,9 @@ static void b43_configure_filter(struct ieee80211_hw *hw,
+@@ -2943,8 +3054,9 @@ static void b43_configure_filter(struct ieee80211_hw *hw,
  	spin_unlock_irqrestore(&wl->irq_lock, flags);
  }
  
@@ -594748,7 +653348,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	struct b43_wldev *dev = wl->current_dev;
-@@ -2954,7 +3065,7 @@ static int b43_config_interface(struct ieee80211_hw *hw,
+@@ -2954,7 +3066,7 @@ static int b43_config_interface(struct ieee80211_hw *hw,
  		return -ENODEV;
  	mutex_lock(&wl->mutex);
  	spin_lock_irqsave(&wl->irq_lock, flags);
@@ -594757,7 +653357,7 @@
  	if (conf->bssid)
  		memcpy(wl->bssid, conf->bssid, ETH_ALEN);
  	else
-@@ -2964,7 +3075,7 @@ static int b43_config_interface(struct ieee80211_hw *hw,
+@@ -2964,7 +3076,7 @@ static int b43_config_interface(struct ieee80211_hw *hw,
  			B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
  			b43_set_ssid(dev, conf->ssid, conf->ssid_len);
  			if (conf->beacon)
@@ -594766,24 +653366,24 @@
  		}
  		b43_write_mac_bssid_templates(dev);
  	}
-@@ -3067,9 +3178,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
+@@ -3067,9 +3179,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
  			unsupported = 1;
  		break;
  	case B43_PHYTYPE_G:
 -		if (phy_rev > 8)
 +		if (phy_rev > 9)
-+			unsupported = 1;
-+		break;
+ 			unsupported = 1;
+ 		break;
 +#ifdef CONFIG_B43_NPHY
 +	case B43_PHYTYPE_N:
 +		if (phy_rev > 1)
- 			unsupported = 1;
- 		break;
++			unsupported = 1;
++		break;
 +#endif
  	default:
  		unsupported = 1;
  	};
-@@ -3092,14 +3209,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
+@@ -3092,14 +3210,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
  			tmp = 0x5205017F;
  	} else {
  		b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
@@ -594802,7 +653402,7 @@
  	switch (phy_type) {
  	case B43_PHYTYPE_A:
  		if (radio_ver != 0x2060)
-@@ -3117,6 +3235,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
+@@ -3117,6 +3236,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
  		if (radio_ver != 0x2050)
  			unsupported = 1;
  		break;
@@ -594813,7 +653413,7 @@
  	default:
  		B43_WARN_ON(1);
  	}
-@@ -3149,9 +3271,6 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
+@@ -3149,9 +3272,6 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
  	memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
  	memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
  
@@ -594823,7 +653423,7 @@
  	phy->aci_enable = 0;
  	phy->aci_wlan_automatic = 0;
  	phy->aci_hw_rssi = 0;
-@@ -3178,17 +3297,22 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
+@@ -3178,17 +3298,22 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
  	phy->lofcal = 0xFFFF;
  	phy->initval = 0xFFFF;
  
@@ -594849,7 +653449,7 @@
  	/* Assume the radio is enabled. If it's not enabled, the state will
  	 * immediately get fixed on the first periodic work run. */
  	dev->radio_hw_enable = 1;
-@@ -3214,13 +3338,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
+@@ -3214,13 +3339,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
  	struct ssb_sprom *sprom = &dev->dev->bus->sprom;
  	u32 hf;
  
@@ -594865,7 +653465,7 @@
  		hf |= B43_HF_BTCOEXALT;
  	else
  		hf |= B43_HF_BTCOEX;
-@@ -3259,20 +3383,42 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
+@@ -3259,20 +3384,44 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
  #endif /* CONFIG_SSB_DRIVER_PCICORE */
  }
  
@@ -594897,19 +653497,23 @@
  		return;
  	b43_set_status(dev, B43_STAT_UNINIT);
  
+-	b43_leds_exit(dev);
+-	b43_rng_exit(dev->wl);
+-	b43_pio_free(dev);
 +	/* Stop the microcode PSM. */
 +	macctl = b43_read32(dev, B43_MMIO_MACCTL);
 +	macctl &= ~B43_MACCTL_PSM_RUN;
 +	macctl |= B43_MACCTL_PSM_JMP0;
 +	b43_write32(dev, B43_MMIO_MACCTL, macctl);
 +
- 	b43_leds_exit(dev);
- 	b43_rng_exit(dev->wl);
--	b43_pio_free(dev);
++	if (!dev->suspend_in_progress) {
++		b43_leds_exit(dev);
++		b43_rng_exit(dev->wl, false);
++	}
  	b43_dma_free(dev);
  	b43_chip_exit(dev);
  	b43_radio_turn_off(dev, 1);
-@@ -3281,6 +3427,11 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
+@@ -3281,6 +3430,11 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
  		kfree(phy->tssi2dbm);
  	kfree(phy->lo_control);
  	phy->lo_control = NULL;
@@ -594921,7 +653525,7 @@
  	ssb_device_disable(dev->dev, 0);
  	ssb_bus_may_powerdown(dev->dev->bus);
  }
-@@ -3335,7 +3486,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+@@ -3335,7 +3489,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
  		hf |= B43_HF_SYMW;
  		if (phy->rev == 1)
  			hf |= B43_HF_GDCW;
@@ -594930,7 +653534,7 @@
  			hf |= B43_HF_OFDMPABOOST;
  	} else if (phy->type == B43_PHYTYPE_B) {
  		hf |= B43_HF_SYMW;
-@@ -3344,15 +3495,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+@@ -3344,15 +3498,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
  	}
  	b43_hf_write(dev, hf);
  
@@ -594948,7 +653552,7 @@
  	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SFFBLIM, 3);
  	b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_LFFBLIM, 2);
  
-@@ -3373,17 +3517,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+@@ -3373,17 +3520,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
  	/* Maximum Contention Window */
  	b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
  
@@ -594968,7 +653572,7 @@
  
  //FIXME
  #if 1
-@@ -3395,8 +3532,6 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
+@@ -3395,15 +3535,15 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
  	b43_bluetooth_coext_enable(dev);
  
  	ssb_bus_powerup(bus, 1);	/* Enable dynamic PCTL */
@@ -594976,8 +653580,19 @@
 -	memset(wl->mac_addr, 0, ETH_ALEN);
  	b43_upload_card_macaddress(dev);
  	b43_security_init(dev);
- 	b43_rng_init(wl);
-@@ -3421,8 +3556,8 @@ out:
+-	b43_rng_init(wl);
++	if (!dev->suspend_in_progress)
++		b43_rng_init(wl);
+ 
+ 	b43_set_status(dev, B43_STAT_INITIALIZED);
+ 
+-	b43_leds_init(dev);
++	if (!dev->suspend_in_progress)
++		b43_leds_init(dev);
+ out:
+ 	return err;
+ 
+@@ -3421,8 +3561,8 @@ out:
  	return err;
  }
  
@@ -594988,7 +653603,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	struct b43_wldev *dev;
-@@ -3445,7 +3580,7 @@ static int b43_add_interface(struct ieee80211_hw *hw,
+@@ -3445,7 +3585,7 @@ static int b43_add_interface(struct ieee80211_hw *hw,
  
  	dev = wl->current_dev;
  	wl->operating = 1;
@@ -594997,7 +653612,7 @@
  	wl->if_type = conf->type;
  	memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
  
-@@ -3461,8 +3596,8 @@ static int b43_add_interface(struct ieee80211_hw *hw,
+@@ -3461,8 +3601,8 @@ static int b43_add_interface(struct ieee80211_hw *hw,
  	return err;
  }
  
@@ -595008,7 +653623,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	struct b43_wldev *dev = wl->current_dev;
-@@ -3473,7 +3608,8 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
+@@ -3473,7 +3613,8 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
  	mutex_lock(&wl->mutex);
  
  	B43_WARN_ON(!wl->operating);
@@ -595018,7 +653633,7 @@
  
  	wl->operating = 0;
  
-@@ -3486,12 +3622,21 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
+@@ -3486,12 +3627,21 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
  	mutex_unlock(&wl->mutex);
  }
  
@@ -595041,7 +653656,7 @@
  
  	/* First register RFkill.
  	 * LEDs that are registered later depend on it. */
-@@ -3501,8 +3646,10 @@ static int b43_start(struct ieee80211_hw *hw)
+@@ -3501,8 +3651,10 @@ static int b43_start(struct ieee80211_hw *hw)
  
  	if (b43_status(dev) < B43_STAT_INITIALIZED) {
  		err = b43_wireless_core_init(dev);
@@ -595053,7 +653668,7 @@
  		did_init = 1;
  	}
  
-@@ -3511,6 +3658,7 @@ static int b43_start(struct ieee80211_hw *hw)
+@@ -3511,6 +3663,7 @@ static int b43_start(struct ieee80211_hw *hw)
  		if (err) {
  			if (did_init)
  				b43_wireless_core_exit(dev);
@@ -595061,7 +653676,7 @@
  			goto out_mutex_unlock;
  		}
  	}
-@@ -3518,10 +3666,13 @@ static int b43_start(struct ieee80211_hw *hw)
+@@ -3518,10 +3671,13 @@ static int b43_start(struct ieee80211_hw *hw)
   out_mutex_unlock:
  	mutex_unlock(&wl->mutex);
  
@@ -595076,7 +653691,7 @@
  {
  	struct b43_wl *wl = hw_to_b43_wl(hw);
  	struct b43_wldev *dev = wl->current_dev;
-@@ -3535,19 +3686,76 @@ static void b43_stop(struct ieee80211_hw *hw)
+@@ -3535,19 +3691,76 @@ static void b43_stop(struct ieee80211_hw *hw)
  	mutex_unlock(&wl->mutex);
  }
  
@@ -595165,7 +653780,7 @@
  };
  
  /* Hard-reset the chip. Do not call this directly.
-@@ -3592,72 +3800,30 @@ static void b43_chip_reset(struct work_struct *work)
+@@ -3592,72 +3805,30 @@ static void b43_chip_reset(struct work_struct *work)
  }
  
  static int b43_setup_modes(struct b43_wldev *dev,
@@ -595256,7 +653871,7 @@
  
  	return 0;
  }
-@@ -3675,7 +3841,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
+@@ -3675,7 +3846,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
  	struct ssb_bus *bus = dev->dev->bus;
  	struct pci_dev *pdev = bus->host_pci;
  	int err;
@@ -595265,7 +653880,7 @@
  	u32 tmp;
  
  	/* Do NOT do any device initialization here.
-@@ -3695,17 +3861,12 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
+@@ -3695,17 +3866,12 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
  		u32 tmshigh;
  
  		tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
@@ -595287,7 +653902,7 @@
  	tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
  	b43_wireless_core_reset(dev, tmp);
  
-@@ -3717,31 +3878,34 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
+@@ -3717,31 +3883,34 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
  	    (pdev->device != 0x4312 &&
  	     pdev->device != 0x4319 && pdev->device != 0x4324)) {
  		/* No multiband support. */
@@ -595332,7 +653947,7 @@
  	if (err)
  		goto err_powerdown;
  
-@@ -3812,8 +3976,6 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
+@@ -3812,8 +3981,6 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
  	tasklet_init(&wldev->isr_tasklet,
  		     (void (*)(unsigned long))b43_interrupt_tasklet,
  		     (unsigned long)wldev);
@@ -595341,7 +653956,7 @@
  	INIT_LIST_HEAD(&wldev->list);
  
  	err = b43_wireless_core_attach(wldev);
-@@ -3838,20 +4000,10 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
+@@ -3838,20 +4005,10 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
  	/* boardflags workarounds */
  	if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
  	    bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
@@ -595364,7 +653979,7 @@
  }
  
  static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
-@@ -3878,16 +4030,17 @@ static int b43_wireless_init(struct ssb_device *dev)
+@@ -3878,16 +4035,17 @@ static int b43_wireless_init(struct ssb_device *dev)
  	}
  
  	/* fill hw info */
@@ -595386,7 +654001,7 @@
  
  	/* Get and initialize struct b43_wl */
  	wl = hw_to_b43_wl(hw);
-@@ -3895,6 +4048,7 @@ static int b43_wireless_init(struct ssb_device *dev)
+@@ -3895,6 +4053,7 @@ static int b43_wireless_init(struct ssb_device *dev)
  	wl->hw = hw;
  	spin_lock_init(&wl->irq_lock);
  	spin_lock_init(&wl->leds_lock);
@@ -595394,6 +654009,35 @@
  	mutex_init(&wl->mutex);
  	INIT_LIST_HEAD(&wl->devlist);
  
+@@ -3981,6 +4140,7 @@ static int b43_suspend(struct ssb_device *dev, pm_message_t state)
+ 	b43dbg(wl, "Suspending...\n");
+ 
+ 	mutex_lock(&wl->mutex);
++	wldev->suspend_in_progress = true;
+ 	wldev->suspend_init_status = b43_status(wldev);
+ 	if (wldev->suspend_init_status >= B43_STAT_STARTED)
+ 		b43_wireless_core_stop(wldev);
+@@ -4012,15 +4172,17 @@ static int b43_resume(struct ssb_device *dev)
+ 	if (wldev->suspend_init_status >= B43_STAT_STARTED) {
+ 		err = b43_wireless_core_start(wldev);
+ 		if (err) {
++			b43_leds_exit(wldev);
++			b43_rng_exit(wldev->wl, true);
+ 			b43_wireless_core_exit(wldev);
+ 			b43err(wl, "Resume failed at core start\n");
+ 			goto out;
+ 		}
+ 	}
+-	mutex_unlock(&wl->mutex);
+-
+ 	b43dbg(wl, "Device resumed.\n");
+-      out:
++ out:
++	wldev->suspend_in_progress = false;
++	mutex_unlock(&wl->mutex);
+ 	return err;
+ }
+ 
 diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
 index 08e2e56..2d52d9d 100644
 --- a/drivers/net/wireless/b43/main.h
@@ -607883,10 +666527,38 @@
  
  struct comm_tallies_sums {
 diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
-index fc6cdd8..2ab107f 100644
+index fc6cdd8..5bf9e00 100644
 --- a/drivers/net/wireless/ipw2100.c
 +++ b/drivers/net/wireless/ipw2100.c
-@@ -2509,9 +2509,9 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
+@@ -162,7 +162,7 @@ that only one external action is invoked at a time.
+ #include <linux/firmware.h>
+ #include <linux/acpi.h>
+ #include <linux/ctype.h>
+-#include <linux/latency.h>
++#include <linux/pm_qos_params.h>
+ 
+ #include "ipw2100.h"
+ 
+@@ -1701,7 +1701,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
+ 	/* the ipw2100 hardware really doesn't want power management delays
+ 	 * longer than 175usec
+ 	 */
+-	modify_acceptable_latency("ipw2100", 175);
++	pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
+ 
+ 	/* If the interrupt is enabled, turn it off... */
+ 	spin_lock_irqsave(&priv->low_lock, flags);
+@@ -1856,7 +1856,8 @@ static void ipw2100_down(struct ipw2100_priv *priv)
+ 	ipw2100_disable_interrupts(priv);
+ 	spin_unlock_irqrestore(&priv->low_lock, flags);
+ 
+-	modify_acceptable_latency("ipw2100", INFINITE_LATENCY);
++	pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
++			PM_QOS_DEFAULT_VALUE);
+ 
+ 	/* We have to signal any supplicant if we are disassociating */
+ 	if (associated)
+@@ -2509,9 +2510,9 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
  
  	ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
  	ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
@@ -607898,7 +666570,7 @@
  
  	ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM;
  
-@@ -2558,7 +2558,7 @@ static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
+@@ -2558,7 +2559,7 @@ static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
  #ifdef CONFIG_IPW2100_MONITOR
  		return 0;
  #else
@@ -607907,7 +666579,7 @@
  		case IEEE80211_FTYPE_MGMT:
  		case IEEE80211_FTYPE_CTL:
  			return 0;
-@@ -2677,7 +2677,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
+@@ -2677,7 +2678,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
  #endif
  			if (stats.len < sizeof(struct ieee80211_hdr_3addr))
  				break;
@@ -607916,7 +666588,26 @@
  			case IEEE80211_FTYPE_MGMT:
  				ieee80211_rx_mgt(priv->ieee,
  						 &u->rx_data.header, &stats);
-@@ -6591,8 +6591,7 @@ static const long ipw2100_frequencies[] = {
+@@ -6554,7 +6555,8 @@ static int __init ipw2100_init(void)
+ 	if (ret)
+ 		goto out;
+ 
+-	set_acceptable_latency("ipw2100", INFINITE_LATENCY);
++	pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
++			PM_QOS_DEFAULT_VALUE);
+ #ifdef CONFIG_IPW2100_DEBUG
+ 	ipw2100_debug_level = debug;
+ 	ret = driver_create_file(&ipw2100_pci_driver.driver,
+@@ -6576,7 +6578,7 @@ static void __exit ipw2100_exit(void)
+ 			   &driver_attr_debug_level);
+ #endif
+ 	pci_unregister_driver(&ipw2100_pci_driver);
+-	remove_acceptable_latency("ipw2100");
++	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
+ }
+ 
+ module_init(ipw2100_init);
+@@ -6591,8 +6593,7 @@ static const long ipw2100_frequencies[] = {
  	2472, 2484
  };
  
@@ -607926,7 +666617,7 @@
  
  static const long ipw2100_rates_11b[] = {
  	1000000,
-@@ -7796,7 +7795,7 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
+@@ -7796,7 +7797,7 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
  {
  	struct ipw2100_priv *priv = ieee80211_priv(dev);
  	struct iw_mlme *mlme = (struct iw_mlme *)extra;
@@ -613119,7 +671810,7 @@
  
  #endif
 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
-index 3a45fe9..4fdeb53 100644
+index 3a45fe9..8d4d91d 100644
 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c
 +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
 @@ -35,15 +35,12 @@
@@ -613245,7 +671936,7 @@
  		     le32_to_cpu(pkt->len));
  
  	memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics));
-@@ -242,15 +238,107 @@ void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+@@ -242,15 +238,108 @@ void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
  	priv->last_statistics_time = jiffies;
  }
  
@@ -613253,9 +671944,10 @@
 -				   struct iwl_rx_mem_buffer *rxb,
 -				   struct ieee80211_rx_status *stats,
 -				   u16 phy_flags)
-+void iwl3945_add_radiotap(struct iwl3945_priv *priv, struct sk_buff *skb,
-+			  struct iwl3945_rx_frame_hdr *rx_hdr,
-+			  struct ieee80211_rx_status *stats)
++static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
++				 struct sk_buff *skb,
++				 struct iwl3945_rx_frame_hdr *rx_hdr,
++				 struct ieee80211_rx_status *stats)
 +{
 +	/* First cache any information we need before we overwrite
 +	 * the information provided in the skb from the hardware */
@@ -613360,7 +672052,7 @@
  	short len = le16_to_cpu(rx_hdr->len);
  
  	/* We received data from the HW, so stop the watchdog */
-@@ -265,15 +353,6 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
+@@ -265,15 +354,6 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
  		    ("Dropping packet while interface is not open.\n");
  		return;
  	}
@@ -613376,7 +672068,7 @@
  
  	skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
  	/* Set the size of the skb to the size of the frame */
-@@ -281,23 +360,27 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
+@@ -281,23 +361,27 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
  
  	hdr = (void *)rxb->skb->data;
  
@@ -613413,7 +672105,7 @@
  	u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
  	u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
  	struct ieee80211_rx_status stats = {
-@@ -327,7 +410,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+@@ -327,7 +411,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
  	}
  
  	if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
@@ -613422,7 +672114,7 @@
  		return;
  	}
  
-@@ -351,14 +434,14 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+@@ -351,14 +435,14 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
  	 * Calculate stats.signal (quality indicator in %) based on SNR. */
  	if (rx_stats_noise_diff) {
  		snr = rx_stats_sig_avg / rx_stats_noise_diff;
@@ -613440,7 +672132,7 @@
  	}
  
  
-@@ -368,24 +451,24 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+@@ -368,24 +452,24 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
  
  	stats.freq = ieee80211chan2mhz(stats.channel);
  
@@ -613471,7 +672163,7 @@
  #endif
  
  	if (network_packet) {
-@@ -437,15 +520,20 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+@@ -437,15 +521,20 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
  			break;
  
  			/*
@@ -613496,7 +672188,7 @@
  				priv->assoc_id = (~((1 << 15) | (1 << 14)) &
  						  le16_to_cpu(mgnt->u.
  							      assoc_resp.aid));
-@@ -474,7 +562,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+@@ -474,7 +563,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
  			}
  		}
  
@@ -613505,7 +672197,7 @@
  		break;
  
  	case IEEE80211_FTYPE_CTL:
-@@ -485,25 +573,24 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+@@ -485,25 +574,24 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
  		DECLARE_MAC_BUF(mac2);
  		DECLARE_MAC_BUF(mac3);
  
@@ -613535,7 +672227,7 @@
  
  	count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
  	pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags));
-@@ -526,14 +613,14 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+@@ -526,14 +614,14 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
  }
  
  /**
@@ -613554,7 +672246,7 @@
  	struct pci_dev *dev = priv->pci_dev;
  	int i;
  	int counter;
-@@ -556,19 +643,19 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+@@ -556,19 +644,19 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
  	for (i = 1; i < counter; i++) {
  		pci_unmap_single(dev, le32_to_cpu(bd->pa[i].addr),
  				 le32_to_cpu(bd->pa[i].len), PCI_DMA_TODEVICE);
@@ -613579,7 +672271,7 @@
  {
  	int i;
  	int ret = IWL_INVALID_STATION;
-@@ -592,11 +679,11 @@ u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *addr)
+@@ -592,11 +680,11 @@ u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *addr)
  }
  
  /**
@@ -613594,7 +672286,7 @@
  			      struct ieee80211_tx_control *ctrl,
  			      struct ieee80211_hdr *hdr, int sta_id, int tx_id)
  {
-@@ -609,7 +696,7 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+@@ -609,7 +697,7 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
  	__le32 tx_flags;
  	u16 fc = le16_to_cpu(hdr->frame_control);
  
@@ -613603,7 +672295,7 @@
  	tx_flags = cmd->cmd.tx.tx_flags;
  
  	/* We need to figure out how to get the sta->supp_rates while
-@@ -676,10 +763,10 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+@@ -676,10 +764,10 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
  		       cmd->cmd.tx.supp_rates[1], cmd->cmd.tx.supp_rates[0]);
  }
  
@@ -613616,7 +672308,7 @@
  
  	if (sta_id == IWL_INVALID_STATION)
  		return IWL_INVALID_STATION;
-@@ -694,34 +781,19 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
+@@ -694,34 +782,19 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
  
  	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
  
@@ -613654,7 +672346,7 @@
  	if (rc) {
  		spin_unlock_irqrestore(&priv->lock, flags);
  		return rc;
-@@ -733,23 +805,23 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
+@@ -733,23 +806,23 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
  		rc = pci_read_config_dword(priv->pci_dev,
  				PCI_POWER_SOURCE, &val);
  		if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) {
@@ -613685,7 +672377,7 @@
  			     CSR_GPIO_IN_BIT_AUX_POWER, 5000);	/* uS */
  	}
  	spin_unlock_irqrestore(&priv->lock, flags);
-@@ -757,24 +829,24 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
+@@ -757,24 +830,24 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
  	return rc;
  }
  
@@ -613717,7 +672409,7 @@
  		ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
  		ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
  		ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
-@@ -785,44 +857,44 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+@@ -785,44 +858,44 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
  		ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
  
  	/* fake read to flush all prev I/O */
@@ -613775,7 +672467,7 @@
  		ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
  		ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
  		ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
-@@ -831,7 +903,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
+@@ -831,7 +904,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
  		ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
  		ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
  
@@ -613784,7 +672476,7 @@
  	spin_unlock_irqrestore(&priv->lock, flags);
  
  	return 0;
-@@ -842,12 +914,12 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
+@@ -842,12 +915,12 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
   *
   * Destroys all DMA structures and initialize them again
   */
@@ -613799,7 +672491,7 @@
  
  	/* Tx CMD queue */
  	rc = iwl3945_tx_reset(priv);
-@@ -858,7 +930,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
+@@ -858,7 +931,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
  	for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) {
  		slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
  				TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
@@ -613808,7 +672500,7 @@
  				txq_id);
  		if (rc) {
  			IWL_ERROR("Tx %d queue init failed\n", txq_id);
-@@ -869,26 +941,26 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
+@@ -869,26 +942,26 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
  	return rc;
  
   error:
@@ -613843,7 +672535,7 @@
  			  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
  			  CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
  	if (rc < 0) {
-@@ -897,18 +969,18 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
+@@ -897,18 +970,18 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
  		return rc;
  	}
  
@@ -613866,7 +672558,7 @@
  	spin_unlock_irqrestore(&priv->lock, flags);
  
  	/* Determine HW type */
-@@ -924,25 +996,17 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
+@@ -924,25 +997,17 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
  		IWL_DEBUG_INFO("RTP type \n");
  	else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
  		IWL_DEBUG_INFO("ALM-MB type\n");
@@ -613895,7 +672587,7 @@
  			    CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC);
  	} else
  		IWL_DEBUG_INFO("SKU OP mode is basic\n");
-@@ -950,24 +1014,24 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
+@@ -950,24 +1015,24 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
  	if ((priv->eeprom.board_revision & 0xF0) == 0xD0) {
  		IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
  			       priv->eeprom.board_revision);
@@ -613924,7 +672616,7 @@
  			    CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
  	}
  	spin_unlock_irqrestore(&priv->lock, flags);
-@@ -980,15 +1044,15 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
+@@ -980,15 +1045,15 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
  
  	/* Allocate the RX queue, or reset if it is already allocated */
  	if (!rxq->bd) {
@@ -613943,7 +672635,7 @@
  
  	iwl3945_rx_init(priv, rxq);
  
-@@ -996,16 +1060,16 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
+@@ -996,16 +1061,16 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
  
  	/* Look at using this instead:
  	rxq->need_update = 1;
@@ -613964,7 +672656,7 @@
  
  	spin_unlock_irqrestore(&priv->lock, flags);
  
-@@ -1019,49 +1083,49 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
+@@ -1019,49 +1084,49 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
  }
  
  /**
@@ -614026,7 +672718,7 @@
  {
  	int rc = 0;
  	u32 reg_val;
-@@ -1070,16 +1134,16 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
+@@ -1070,16 +1135,16 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
  	spin_lock_irqsave(&priv->lock, flags);
  
  	/* set stop master bit */
@@ -614046,7 +672738,7 @@
  				  CSR_RESET_REG_FLAG_MASTER_DISABLED,
  				  CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
  		if (rc < 0) {
-@@ -1094,47 +1158,47 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
+@@ -1094,47 +1159,47 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
  	return rc;
  }
  
@@ -614107,7 +672799,7 @@
  	}
  
  	/* Clear the 'host command active' bit... */
-@@ -1147,41 +1211,43 @@ int iwl_hw_nic_reset(struct iwl_priv *priv)
+@@ -1147,41 +1212,43 @@ int iwl_hw_nic_reset(struct iwl_priv *priv)
  }
  
  /**
@@ -614163,7 +672855,7 @@
  		IWL_ERROR("Error bad temperature value  %d\n", temperature);
  
  		/* if really really hot(?),
-@@ -1206,11 +1272,11 @@ static int iwl_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
+@@ -1206,11 +1273,11 @@ static int iwl_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
   * records new temperature in tx_mgr->temperature.
   * replaces tx_mgr->last_temperature *only* if calib needed
   *    (assumes caller will actually do the calibration!). */
@@ -614177,7 +672869,7 @@
  	temp_diff = priv->temperature - priv->last_temperature;
  
  	/* get absolute value */
-@@ -1242,7 +1308,7 @@ static int is_temp_calib_needed(struct iwl_priv *priv)
+@@ -1242,7 +1309,7 @@ static int is_temp_calib_needed(struct iwl_priv *priv)
  
  /* radio and DSP power table, each step is 1/2 dB.
   * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
@@ -614186,7 +672878,7 @@
  	{
  	 {251, 127},		/* 2.4 GHz, highest power */
  	 {251, 127},
-@@ -1403,7 +1469,7 @@ static struct iwl_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
+@@ -1403,7 +1470,7 @@ static struct iwl_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
  	 {3, 120} }		/* 5.x GHz, lowest power */
  };
  
@@ -614195,7 +672887,7 @@
  {
  	if (index < 0)
  		return 0;
-@@ -1416,17 +1482,17 @@ static inline u8 iwl_hw_reg_fix_power_index(int index)
+@@ -1416,17 +1483,17 @@ static inline u8 iwl_hw_reg_fix_power_index(int index)
  #define REG_RECALIB_PERIOD (60)
  
  /**
@@ -614217,7 +672909,7 @@
  	s8 power;
  	u8 power_index;
  
-@@ -1462,7 +1528,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
+@@ -1462,7 +1529,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
  	 *   of the table. */
  
  	/* don't exceed table bounds for "real" setting */
@@ -614226,7 +672918,7 @@
  
  	scan_power_info->power_table_index = power_index;
  	scan_power_info->tpc.tx_gain =
-@@ -1472,21 +1538,21 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
+@@ -1472,21 +1539,21 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
  }
  
  /**
@@ -614253,7 +672945,7 @@
  				       priv->phymode,
  				       le16_to_cpu(priv->active_rxon.channel));
  	if (!ch_info) {
-@@ -1508,7 +1574,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
+@@ -1508,7 +1575,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
  	     rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) {
  
  		txpower.power[i].tpc = ch_info->power_info[i].tpc;
@@ -614262,7 +672954,7 @@
  
  		IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
  				le16_to_cpu(txpower.channel),
-@@ -1521,7 +1587,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
+@@ -1521,7 +1588,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
  	for (rate_idx = IWL_FIRST_CCK_RATE;
  	     rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
  		txpower.power[i].tpc = ch_info->power_info[i].tpc;
@@ -614271,7 +672963,7 @@
  
  		IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
  				le16_to_cpu(txpower.channel),
-@@ -1531,13 +1597,13 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
+@@ -1531,13 +1598,13 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
  				txpower.power[i].rate);
  	}
  
@@ -614288,7 +672980,7 @@
   * @ch_info: Channel to update.  Uses power_info.requested_power.
   *
   * Replace requested_power and base_power_index ch_info fields for
-@@ -1552,10 +1618,10 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
+@@ -1552,10 +1619,10 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
   *	 properly fill out the scan powers, and actual h/w gain settings,
   *	 and send changes to NIC
   */
@@ -614302,7 +672994,7 @@
  	int power_changed = 0;
  	int i;
  	const s8 *clip_pwrs;
-@@ -1595,7 +1661,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
+@@ -1595,7 +1662,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
  		    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
  		    requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
  
@@ -614311,7 +673003,7 @@
  		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
  			power_info->requested_power = power;
  			power_info->base_power_index =
-@@ -1609,13 +1675,13 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
+@@ -1609,13 +1676,13 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
  }
  
  /**
@@ -614327,7 +673019,7 @@
  {
  	s8 max_power;
  
-@@ -1634,7 +1700,7 @@ static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
+@@ -1634,7 +1701,7 @@ static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
  }
  
  /**
@@ -614336,7 +673028,7 @@
   *
   * Compensate txpower settings of *all* channels for temperature.
   * This only accounts for the difference between current temperature
-@@ -1643,9 +1709,9 @@ static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
+@@ -1643,9 +1710,9 @@ static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
   *
   * If RxOn is "associated", this sends the new Txpower to NIC!
   */
@@ -614348,7 +673040,7 @@
  	int delta_index;
  	const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
  	u8 a_band;
-@@ -1666,7 +1732,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
+@@ -1666,7 +1733,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
  
  		/* get power index adjustment based on curr and factory
  		 * temps */
@@ -614357,7 +673049,7 @@
  							      ref_temp);
  
  		/* set tx power value for all rates, OFDM and CCK */
-@@ -1679,7 +1745,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
+@@ -1679,7 +1746,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
  			power_idx += delta_index;
  
  			/* stay within table range */
@@ -614366,7 +673058,7 @@
  			ch_info->power_info[rate_index].
  			    power_table_index = (u8) power_idx;
  			ch_info->power_info[rate_index].tpc =
-@@ -1694,19 +1760,19 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
+@@ -1694,19 +1761,19 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
  		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
  			s32 actual_index = (scan_tbl_index == 0) ?
  			    IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
@@ -614390,7 +673082,7 @@
  	s8 max_power;
  	u8 a_band;
  	u8 i;
-@@ -1728,26 +1794,26 @@ int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+@@ -1728,26 +1795,26 @@ int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
  
  		/* find minimum power of all user and regulatory constraints
  		 *    (does not consider h/w clipping limitations) */
@@ -614421,7 +673113,7 @@
  {
  	return 0;
  }
-@@ -1762,26 +1828,26 @@ int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+@@ -1762,26 +1829,26 @@ int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel)
   *     -- send new set of gain settings to NIC
   * NOTE:  This should continue working, even when we're not associated,
   *   so we can keep our internal table of scan powers current. */
@@ -614453,7 +673145,7 @@
  					     thermal_periodic.work);
  
  	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-@@ -1793,7 +1859,7 @@ void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
+@@ -1793,7 +1860,7 @@ void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
  }
  
  /**
@@ -614462,7 +673154,7 @@
   * 				   for the channel.
   *
   * This function is used when initializing channel-info structs.
-@@ -1803,10 +1869,10 @@ void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
+@@ -1803,10 +1870,10 @@ void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
   *	 on A-band, EEPROM's "group frequency" entries represent the top
   *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0.
   */
@@ -614476,7 +673168,7 @@
  	u8 group;
  	u16 group_index = 0;	/* based on factory calib frequencies */
  	u8 grp_channel;
-@@ -1832,20 +1898,20 @@ static u16 iwl_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
+@@ -1832,20 +1899,20 @@ static u16 iwl_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
  }
  
  /**
@@ -614501,7 +673193,7 @@
  	s32 gains0, gains1;
  	s32 res;
  	s32 denominator;
-@@ -1885,11 +1951,11 @@ static int iwl_hw_reg_get_matched_power_index(struct iwl_priv *priv,
+@@ -1885,11 +1952,11 @@ static int iwl_hw_reg_get_matched_power_index(struct iwl_priv *priv,
  	return 0;
  }
  
@@ -614515,7 +673207,7 @@
  
  	IWL_DEBUG_POWER("Initializing factory calib info from EEPROM\n");
  
-@@ -1965,10 +2031,10 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv)
+@@ -1965,10 +2032,10 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv)
   *
   * This does *not* write values to NIC, just sets up our internal table.
   */
@@ -614529,7 +673221,7 @@
  	int delta_index;
  	u8 rate_index;
  	u8 scan_tbl_index;
-@@ -1981,10 +2047,10 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -1981,10 +2048,10 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  
  	/* save temperature reference,
  	 *   so we can determine next time to calibrate */
@@ -614542,7 +673234,7 @@
  
  	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
  	for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
-@@ -1995,14 +2061,14 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -1995,14 +2062,14 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  
  		/* find this channel's channel group (*not* "band") index */
  		ch_info->group_index =
@@ -614559,7 +673251,7 @@
  				priv->eeprom.groups[ch_info->group_index].
  				temperature);
  
-@@ -2025,7 +2091,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -2025,7 +2092,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  
  			/* get base (i.e. at factory-measured temperature)
  			 *    power table index for this rate's power */
@@ -614568,7 +673260,7 @@
  							 ch_info->group_index,
  							 &power_idx);
  			if (rc) {
-@@ -2038,9 +2104,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -2038,9 +2105,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  			power_idx += delta_index;
  
  			/* stay within range of gain table */
@@ -614580,7 +673272,7 @@
  			pwr_info->requested_power = pwr;
  			pwr_info->power_table_index = (u8) power_idx;
  			pwr_info->tpc.tx_gain =
-@@ -2059,11 +2125,11 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -2059,11 +2126,11 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  			IWL_CCK_FROM_OFDM_INDEX_DIFF;
  
  		/* stay within table range */
@@ -614594,7 +673286,7 @@
  		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
  		 * NOTE:  CCK rates start at end of OFDM rates! */
  		for (rate_index = 0;
-@@ -2081,7 +2147,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -2081,7 +2148,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
  			s32 actual_index = (scan_tbl_index == 0) ?
  				IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
@@ -614603,7 +673295,7 @@
  				actual_index, clip_pwrs, ch_info, a_band);
  		}
  	}
-@@ -2089,66 +2155,66 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+@@ -2089,66 +2156,66 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
  	return 0;
  }
  
@@ -614685,7 +673377,7 @@
  
  	return le32_to_cpu(shared_data->rx_read_ptr[0]);
  }
-@@ -2156,22 +2222,22 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv)
+@@ -2156,22 +2223,22 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv)
  /**
   * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
   */
@@ -614716,7 +673408,7 @@
  	}
  
  	switch (priv->phymode) {
-@@ -2180,14 +2246,14 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
+@@ -2180,14 +2247,14 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
  		/* If one of the following CCK rates is used,
  		 * have it fall back to the 6M OFDM rate */
  		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)
@@ -614733,7 +673425,7 @@
  		break;
  
  	case MODE_IEEE80211B:
-@@ -2195,7 +2261,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
+@@ -2195,7 +2262,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
  		/* If an OFDM rate is used, have it fall back to the
  		 * 1M CCK rates */
  		for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
@@ -614742,7 +673434,7 @@
  
  		/* CCK shouldn't fall back to OFDM... */
  		table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
-@@ -2208,25 +2274,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
+@@ -2208,25 +2275,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
  
  	/* Update the rate scaling for control frame Tx */
  	rate_cmd.table_id = 0;
@@ -614774,7 +673466,7 @@
  				 &priv->hw_setting.shared_phys);
  
  	if (!priv->hw_setting.shared_virt) {
-@@ -2236,31 +2303,31 @@ int iwl_hw_set_hw_setting(struct iwl_priv *priv)
+@@ -2236,31 +2304,31 @@ int iwl_hw_set_hw_setting(struct iwl_priv *priv)
  	}
  
  	priv->hw_setting.ac_queue_count = AC_NUM;
@@ -614815,7 +673507,7 @@
  				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
  
  	BUG_ON(frame_size > MAX_MPDU_SIZE);
-@@ -2277,35 +2344,29 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
+@@ -2277,35 +2345,29 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
  	tx_beacon_cmd->tx.supp_rates[1] =
  		(IWL_CCK_BASIC_RATES_MASK & 0xF);
  
@@ -624417,7 +683109,7 @@
  
  #endif
 diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
-index 891f90d..569347f 100644
+index 891f90d..d727de8 100644
 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c
 +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
 @@ -36,13 +36,13 @@
@@ -624590,12 +683282,12 @@
 +
 +	/* Stop Rx DMA */
 +	iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
-+
-+	/* Reset driver's Rx queue write index */
-+	iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
  
 -	iwl_write_restricted(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
 -	iwl_write_restricted(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
++	/* Reset driver's Rx queue write index */
++	iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
++
 +	/* Tell device where to find RBD circular buffer in DRAM */
 +	iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
  			     rxq->dma_addr >> 8);
@@ -625458,11 +684150,11 @@
 -		 offsetof(struct iwl_shared, queues_byte_cnt_tbls)) >> 10);
 -	iwl_write_restricted_reg(priv, SCD_QUEUECHAIN_SEL, 0);
 +		 offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
- 
--	/* initiate the queues */
++
 +	/* Disable chain mode for all queues */
 +	iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0);
-+
+ 
+-	/* initiate the queues */
 +	/* Initialize each Tx queue (including the command queue) */
  	for (i = 0; i < priv->hw_setting.max_txq_num; i++) {
 -		iwl_write_restricted_reg(priv, SCD_QUEUE_RDPTR(i), 0);
@@ -627331,7 +686023,7 @@
  	switch (ht_info->extension_chan_offset) {
  	case IWL_EXT_CHANNEL_OFFSET_ABOVE:
  		rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
-@@ -4416,66 +4637,56 @@ void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct sta_ht_info *ht_info)
+@@ -4416,66 +4637,69 @@ void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct sta_ht_info *ht_info)
  		break;
  	}
  
@@ -627363,20 +686055,35 @@
  {
  	__le32 sta_flags;
 -	struct sta_ht_info *ht_info = &priv->current_assoc_ht;
++	u8 mimo_ps_mode;
  
 -	priv->current_channel_width = IWL_CHANNEL_WIDTH_20MHZ;
 -	if (!ht_info->is_ht)
 +	if (!sta_ht_inf || !sta_ht_inf->ht_supported)
  		goto done;
  
++	mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2;
++
  	sta_flags = priv->stations[index].sta.station_flags;
  
 -	if (ht_info->tx_mimo_ps_mode == IWL_MIMO_PS_DYNAMIC)
-+	if (((sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS >> 2))
-+						== IWL_MIMO_PS_DYNAMIC)
++	sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
++
++	switch (mimo_ps_mode) {
++	case WLAN_HT_CAP_MIMO_PS_STATIC:
++		sta_flags |= STA_FLG_MIMO_DIS_MSK;
++		break;
++	case WLAN_HT_CAP_MIMO_PS_DYNAMIC:
  		sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
- 	else
- 		sta_flags &= ~STA_FLG_RTS_MIMO_PROT_MSK;
+-	else
+-		sta_flags &= ~STA_FLG_RTS_MIMO_PROT_MSK;
++		break;
++	case WLAN_HT_CAP_MIMO_PS_DISABLED:
++		break;
++	default:
++		IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode);
++		break;
++	}
  
  	sta_flags |= cpu_to_le32(
 -		(u32)ht_info->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
@@ -627399,7 +686106,7 @@
 -	}
 -	priv->current_channel_width = ht_info->tx_chan_width;
 +	else
-+		sta_flags &= (~STA_FLG_FAT_EN_MSK);
++		sta_flags &= ~STA_FLG_FAT_EN_MSK;
 +
  	priv->stations[index].sta.station_flags = sta_flags;
   done:
@@ -627413,7 +686120,7 @@
  					  int sta_id, int tid, u16 ssn)
  {
  	unsigned long flags;
-@@ -4488,10 +4699,10 @@ static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv,
+@@ -4488,10 +4712,10 @@ static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv,
  	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
  	spin_unlock_irqrestore(&priv->sta_lock, flags);
  
@@ -627426,14 +686133,14 @@
  					  int sta_id, int tid)
  {
  	unsigned long flags;
-@@ -4503,9 +4714,39 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv,
+@@ -4503,9 +4727,39 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv,
  	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
  	spin_unlock_irqrestore(&priv->sta_lock, flags);
  
 -	iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
 +	iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-+}
-+
+ }
+ 
 +int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
 +			     enum ieee80211_ampdu_mlme_action action,
 +			     const u8 *addr, u16 tid, u16 ssn)
@@ -627460,14 +686167,14 @@
 +		break;
 +	}
 +	return 0;
- }
- 
++}
++
 +#ifdef CONFIG_IWL4965_HT_AGG
 +
  static const u16 default_tid_to_tx_fifo[] = {
  	IWL_TX_FIFO_AC1,
  	IWL_TX_FIFO_AC0,
-@@ -4526,7 +4767,13 @@ static const u16 default_tid_to_tx_fifo[] = {
+@@ -4526,7 +4780,13 @@ static const u16 default_tid_to_tx_fifo[] = {
  	IWL_TX_FIFO_AC3
  };
  
@@ -627482,7 +686189,7 @@
  {
  	int txq_id;
  
-@@ -4536,55 +4783,65 @@ static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
+@@ -4536,55 +4796,65 @@ static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
  	return -1;
  }
  
@@ -627557,7 +686264,7 @@
  	int rc;
  	DECLARE_MAC_BUF(mac);
  
-@@ -4598,7 +4855,7 @@ int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+@@ -4598,7 +4868,7 @@ int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
  	else
  		return -EINVAL;
  
@@ -627566,7 +686273,7 @@
  
  	if (sta_id == IWL_INVALID_STATION)
  		return -ENXIO;
-@@ -4613,45 +4870,18 @@ int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+@@ -4613,45 +4883,18 @@ int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
  		return rc;
  
  	iwl4965_ba_status(priv, tid, BA_STATUS_INITIATOR_DELBA);
@@ -627583,7 +686290,7 @@
 -	struct iwl_priv *priv = hw->priv;
 -	int sta_id;
 -	DECLARE_MAC_BUF(mac);
- 
+-
 -	IWL_WARNING("iwl-AGG iwl_mac_ht_rx_agg_start on da=%s"
 -		    " tid=%d\n", print_mac(mac, da), tid);
 -	sta_id = iwl_hw_find_station(priv, da);
@@ -627597,7 +686304,7 @@
 -	struct iwl_priv *priv = hw->priv;
 -	int sta_id;
 -	DECLARE_MAC_BUF(mac);
--
+ 
 -	IWL_WARNING("iwl-AGG iwl_mac_ht_rx_agg_stop on da=%s tid=%d\n",
 -		    print_mac(mac, da), tid);
 -	sta_id = iwl_hw_find_station(priv, da);
@@ -627616,7 +686323,7 @@
  {
  	/* Legacy Rx frames */
  	priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx;
-@@ -4663,57 +4893,66 @@ void iwl_hw_rx_handler_setup(struct iwl_priv *priv)
+@@ -4663,57 +4906,66 @@ void iwl_hw_rx_handler_setup(struct iwl_priv *priv)
  	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
  	    iwl4965_rx_missed_beacon_notif;
  
@@ -627701,7 +686408,7 @@
  				count+1);
  			return rc;
  		}
-@@ -4722,11 +4961,4 @@ int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv)
+@@ -4722,11 +4974,4 @@ int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv)
  	return rc;
  }
  
@@ -631428,10 +690135,20 @@
 -
 -#endif
 diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
-index e2a8d95..cb009f4 100644
+index e2a8d95..8993cca 100644
 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
 +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
-@@ -246,10 +246,33 @@ static inline int iwl_check_bits(unsigned long field, unsigned long mask)
+@@ -147,9 +147,6 @@ static inline struct ieee80211_conf *ieee80211_get_hw_conf(
+ 
+ #define QOS_CONTROL_LEN 2
+ 
+-#define IEEE80211_STYPE_BACK_REQ	0x0080
+-#define IEEE80211_STYPE_BACK		0x0090
+-
+ 
+ static inline int ieee80211_is_management(u16 fc)
+ {
+@@ -246,10 +243,33 @@ static inline int iwl_check_bits(unsigned long field, unsigned long mask)
  static inline unsigned long elapsed_jiffies(unsigned long start,
  					    unsigned long end)
  {
@@ -632885,7 +691602,7 @@
 +
  #endif				/* __iwl_prph_h__ */
 diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
-index 0b3ec7e..33239f1 100644
+index 0b3ec7e..f55c757 100644
 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
 +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
 @@ -27,16 +27,6 @@
@@ -638191,14 +696908,20 @@
  	int rc, i;
  
  	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-@@ -6339,7 +6327,19 @@ static int __iwl_up(struct iwl_priv *priv)
+@@ -6339,7 +6327,7 @@ static int __iwl_up(struct iwl_priv *priv)
  	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
  		IWL_WARNING("Radio disabled by SW RF kill (module "
  			    "parameter)\n");
 -		return 0;
 +		return -ENODEV;
-+	}
-+
+ 	}
+ 
+ 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+@@ -6347,41 +6335,57 @@ static int __iwl_up(struct iwl_priv *priv)
+ 		return -EIO;
+ 	}
+ 
+-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 +	/* If platform's RF_KILL switch is NOT set to KILL */
 +	if (iwl3945_read32(priv, CSR_GP_CNTRL) &
 +				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
@@ -638209,14 +696932,8 @@
 +			IWL_WARNING("Radio disabled by HW RF Kill switch\n");
 +			return -ENODEV;
 +		}
- 	}
- 
- 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-@@ -6347,41 +6347,45 @@ static int __iwl_up(struct iwl_priv *priv)
- 		return -EIO;
- 	}
- 
--	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	}
++
 +	iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
  
 -	rc = iwl_hw_nic_init(priv);
@@ -640574,7 +699291,7 @@
 +module_exit(iwl3945_exit);
 +module_init(iwl3945_init);
 diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
-index 15a45f4..bf3a60c 100644
+index 15a45f4..f423241 100644
 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
 +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
 @@ -27,16 +27,6 @@
@@ -646394,14 +705111,20 @@
  
  	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
  		IWL_WARNING("Exit pending; will not bring the NIC up\n");
-@@ -6695,7 +6752,19 @@ static int __iwl_up(struct iwl_priv *priv)
+@@ -6695,7 +6752,7 @@ static int __iwl_up(struct iwl_priv *priv)
  	if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
  		IWL_WARNING("Radio disabled by SW RF kill (module "
  			    "parameter)\n");
 -		return 0;
 +		return -ENODEV;
-+	}
-+
+ 	}
+ 
+ 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+@@ -6703,53 +6760,57 @@ static int __iwl_up(struct iwl_priv *priv)
+ 		return -EIO;
+ 	}
+ 
+-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
 +	/* If platform's RF_KILL switch is NOT set to KILL */
 +	if (iwl4965_read32(priv, CSR_GP_CNTRL) &
 +				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
@@ -646412,14 +705135,8 @@
 +			IWL_WARNING("Radio disabled by HW RF Kill switch\n");
 +			return -ENODEV;
 +		}
- 	}
- 
- 	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
-@@ -6703,53 +6772,45 @@ static int __iwl_up(struct iwl_priv *priv)
- 		return -EIO;
- 	}
- 
--	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
++	}
++
 +	iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
  
 -	rc = iwl_hw_nic_init(priv);
@@ -663917,7 +722634,7 @@
  	ret = 0;
  
 diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
-index ad1e67d..9a61188 100644
+index ad1e67d..69f94c9 100644
 --- a/drivers/net/wireless/libertas/scan.c
 +++ b/drivers/net/wireless/libertas/scan.c
 @@ -39,9 +39,8 @@
@@ -665662,7 +724379,8 @@
 + *  Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...)
 + *  from cmd.c
   *
-  *  Sends a fixed lenght data part (specifying the BSS type and BSSID filters)
+- *  Sends a fixed lenght data part (specifying the BSS type and BSSID filters)
++ *  Sends a fixed length data part (specifying the BSS type and BSSID filters)
   *  as well as a variable number/length of TLVs to the firmware.
   *
 - *  @param priv       A pointer to wlan_private structure
@@ -668269,6 +726987,118 @@
  
 -#endif				/* _WLAN_WEXT_H_ */
 +#endif
+diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
+index d2fa079..f479c1a 100644
+--- a/drivers/net/wireless/netwave_cs.c
++++ b/drivers/net/wireless/netwave_cs.c
+@@ -195,7 +195,7 @@ static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card
+ static void netwave_detach(struct pcmcia_device *p_dev);    /* Destroy instance */
+ 
+ /* Hardware configuration */
+-static void netwave_doreset(kio_addr_t iobase, u_char __iomem *ramBase);
++static void netwave_doreset(unsigned int iobase, u_char __iomem *ramBase);
+ static void netwave_reset(struct net_device *dev);
+ 
+ /* Misc device stuff */
+@@ -309,7 +309,7 @@ static inline void wait_WOC(unsigned int iobase)
+ }
+ 
+ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase, 
+-			     kio_addr_t iobase) {
++			     unsigned int iobase) {
+     u_short resultBuffer;
+ 
+     /* if time since last snapshot is > 1 sec. (100 jiffies?)  then take 
+@@ -340,7 +340,7 @@ static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase,
+ static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev)
+ {	
+     unsigned long flags;
+-    kio_addr_t iobase = dev->base_addr;
++    unsigned int iobase = dev->base_addr;
+     netwave_private *priv = netdev_priv(dev);
+     u_char __iomem *ramBase = priv->ramBase;
+     struct iw_statistics* wstats;
+@@ -471,7 +471,7 @@ static int netwave_set_nwid(struct net_device *dev,
+ 			    char *extra)
+ {
+ 	unsigned long flags;
+-	kio_addr_t iobase = dev->base_addr;
++	unsigned int iobase = dev->base_addr;
+ 	netwave_private *priv = netdev_priv(dev);
+ 	u_char __iomem *ramBase = priv->ramBase;
+ 
+@@ -518,7 +518,7 @@ static int netwave_set_scramble(struct net_device *dev,
+ 				char *key)
+ {
+ 	unsigned long flags;
+-	kio_addr_t iobase = dev->base_addr;
++	unsigned int iobase = dev->base_addr;
+ 	netwave_private *priv = netdev_priv(dev);
+ 	u_char __iomem *ramBase = priv->ramBase;
+ 
+@@ -621,7 +621,7 @@ static int netwave_get_snap(struct net_device *dev,
+ 			    char *extra)
+ {
+ 	unsigned long flags;
+-	kio_addr_t iobase = dev->base_addr;
++	unsigned int iobase = dev->base_addr;
+ 	netwave_private *priv = netdev_priv(dev);
+ 	u_char __iomem *ramBase = priv->ramBase;
+ 
+@@ -874,7 +874,7 @@ static int netwave_resume(struct pcmcia_device *link)
+  *
+  *    Proper hardware reset of the card.
+  */
+-static void netwave_doreset(kio_addr_t ioBase, u_char __iomem *ramBase)
++static void netwave_doreset(unsigned int ioBase, u_char __iomem *ramBase)
+ {
+     /* Reset card */
+     wait_WOC(ioBase);
+@@ -892,7 +892,7 @@ static void netwave_reset(struct net_device *dev) {
+     /* u_char state; */
+     netwave_private *priv = netdev_priv(dev);
+     u_char __iomem *ramBase = priv->ramBase;
+-    kio_addr_t iobase = dev->base_addr;
++    unsigned int iobase = dev->base_addr;
+ 
+     DEBUG(0, "netwave_reset: Done with hardware reset\n");
+ 
+@@ -973,7 +973,7 @@ static int netwave_hw_xmit(unsigned char* data, int len,
+ 	
+     netwave_private *priv = netdev_priv(dev);
+     u_char __iomem * ramBase = priv->ramBase;
+-    kio_addr_t iobase = dev->base_addr;
++    unsigned int iobase = dev->base_addr;
+ 
+     /* Disable interrupts & save flags */
+     spin_lock_irqsave(&priv->spinlock, flags);
+@@ -1065,7 +1065,7 @@ static int netwave_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+  */
+ static irqreturn_t netwave_interrupt(int irq, void* dev_id)
+ {
+-    kio_addr_t iobase;
++    unsigned int iobase;
+     u_char __iomem *ramBase;
+     struct net_device *dev = (struct net_device *)dev_id;
+     struct netwave_private *priv = netdev_priv(dev);
+@@ -1235,7 +1235,7 @@ static int netwave_rx(struct net_device *dev)
+ {
+     netwave_private *priv = netdev_priv(dev);
+     u_char __iomem *ramBase = priv->ramBase;
+-    kio_addr_t iobase = dev->base_addr;
++    unsigned int iobase = dev->base_addr;
+     u_char rxStatus;
+     struct sk_buff *skb = NULL;
+     unsigned int curBuffer,
+@@ -1388,7 +1388,7 @@ module_exit(exit_netwave_cs);
+  */
+ static void set_multicast_list(struct net_device *dev)
+ {
+-    kio_addr_t iobase = dev->base_addr;
++    unsigned int iobase = dev->base_addr;
+     netwave_private *priv = netdev_priv(dev);
+     u_char __iomem * ramBase = priv->ramBase;
+     u_char  rcvMode = 0;
 diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
 index ca6c2da..6d13a0d 100644
 --- a/drivers/net/wireless/orinoco.c
@@ -681861,7 +740691,7 @@
  #define MULTICAST_AVOID		/* Avoid extra multicast (I'm sceptical). */
  #undef SET_MAC_ADDRESS		/* Experimental */
 diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
-index 577c647..c2037b2 100644
+index 577c647..06eea6a 100644
 --- a/drivers/net/wireless/wavelan_cs.c
 +++ b/drivers/net/wireless/wavelan_cs.c
 @@ -71,27 +71,6 @@ static void wv_nwid_filter(unsigned char mode, net_local *lp);
@@ -681892,6 +740722,186 @@
  /******************* MODEM MANAGEMENT SUBROUTINES *******************/
  /*
   * Useful subroutines to manage the modem of the wavelan
+@@ -170,7 +149,7 @@ psa_write(struct net_device *	dev,
+   net_local *lp = netdev_priv(dev);
+   u_char __iomem *ptr = lp->mem + PSA_ADDR + (o << 1);
+   int		count = 0;
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   /* As there seem to have no flag PSA_BUSY as in the ISA model, we are
+    * oblige to verify this address to know when the PSA is ready... */
+   volatile u_char __iomem *verify = lp->mem + PSA_ADDR +
+@@ -729,7 +708,7 @@ static void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqua
+ /* Perform a handover to a new WavePoint */
+ static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp)
+ {
+-  kio_addr_t		base = lp->dev->base_addr;
++  unsigned int		base = lp->dev->base_addr;
+   mm_t                  m;
+   unsigned long         flags;
+ 
+@@ -842,7 +821,7 @@ wv_82593_cmd(struct net_device *	dev,
+ 	     int	cmd,
+ 	     int	result)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   int		status;
+   int		wait_completed;
+   long		spin;
+@@ -966,7 +945,7 @@ read_ringbuf(struct net_device *	dev,
+ 	     char *	buf,
+ 	     int	len)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   int		ring_ptr = addr;
+   int		chunk_len;
+   char *	buf_ptr = buf;
+@@ -1117,7 +1096,7 @@ wv_psa_show(psa_t *	p)
+ static void
+ wv_mmc_show(struct net_device *	dev)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   net_local *	lp = netdev_priv(dev);
+   mmr_t		m;
+ 
+@@ -1296,7 +1275,7 @@ wv_packet_info(u_char *		p,		/* Packet to dump */
+ static inline void
+ wv_init_info(struct net_device *	dev)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   psa_t		psa;
+   DECLARE_MAC_BUF(mac);
+ 
+@@ -1315,7 +1294,7 @@ wv_init_info(struct net_device *	dev)
+ 
+ #ifdef DEBUG_BASIC_SHOW
+   /* Now, let's go for the basic stuff */
+-  printk(KERN_NOTICE "%s: WaveLAN: port %#lx, irq %d, "
++  printk(KERN_NOTICE "%s: WaveLAN: port %#x, irq %d, "
+ 	 "hw_addr %s",
+ 	 dev->name, base, dev->irq,
+ 	 print_mac(mac, dev->dev_addr));
+@@ -1849,7 +1828,7 @@ static int wavelan_set_nwid(struct net_device *dev,
+ 			    union iwreq_data *wrqu,
+ 			    char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	psa_t psa;
+ 	mm_t m;
+@@ -1939,7 +1918,7 @@ static int wavelan_set_freq(struct net_device *dev,
+ 			    union iwreq_data *wrqu,
+ 			    char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	unsigned long flags;
+ 	int ret;
+@@ -1969,7 +1948,7 @@ static int wavelan_get_freq(struct net_device *dev,
+ 			    union iwreq_data *wrqu,
+ 			    char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	psa_t psa;
+ 	unsigned long flags;
+@@ -2015,7 +1994,7 @@ static int wavelan_set_sens(struct net_device *dev,
+ 			    union iwreq_data *wrqu,
+ 			    char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	psa_t psa;
+ 	unsigned long flags;
+@@ -2081,7 +2060,7 @@ static int wavelan_set_encode(struct net_device *dev,
+ 			      union iwreq_data *wrqu,
+ 			      char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	unsigned long flags;
+ 	psa_t psa;
+@@ -2151,7 +2130,7 @@ static int wavelan_get_encode(struct net_device *dev,
+ 			      union iwreq_data *wrqu,
+ 			      char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	psa_t psa;
+ 	unsigned long flags;
+@@ -2370,7 +2349,7 @@ static int wavelan_get_range(struct net_device *dev,
+ 			     union iwreq_data *wrqu,
+ 			     char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	struct iw_range *range = (struct iw_range *) extra;
+ 	unsigned long flags;
+@@ -2446,7 +2425,7 @@ static int wavelan_set_qthr(struct net_device *dev,
+ 			    union iwreq_data *wrqu,
+ 			    char *extra)
+ {
+-	kio_addr_t base = dev->base_addr;
++	unsigned int base = dev->base_addr;
+ 	net_local *lp = netdev_priv(dev);
+ 	psa_t psa;
+ 	unsigned long flags;
+@@ -2722,7 +2701,7 @@ static const struct iw_handler_def	wavelan_handler_def =
+ static iw_stats *
+ wavelan_get_wireless_stats(struct net_device *	dev)
+ {
+-  kio_addr_t		base = dev->base_addr;
++  unsigned int		base = dev->base_addr;
+   net_local *		lp = netdev_priv(dev);
+   mmr_t			m;
+   iw_stats *		wstats;
+@@ -2785,7 +2764,7 @@ wv_start_of_frame(struct net_device *	dev,
+ 		  int		rfp,	/* end of frame */
+ 		  int		wrap)	/* start of buffer */
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   int		rp;
+   int		len;
+ 
+@@ -2946,7 +2925,7 @@ wv_packet_read(struct net_device *		dev,
+ static inline void
+ wv_packet_rcv(struct net_device *	dev)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   net_local *	lp = netdev_priv(dev);
+   int		newrfp;
+   int		rp;
+@@ -3083,7 +3062,7 @@ wv_packet_write(struct net_device *	dev,
+ 		short		length)
+ {
+   net_local *		lp = netdev_priv(dev);
+-  kio_addr_t		base = dev->base_addr;
++  unsigned int		base = dev->base_addr;
+   unsigned long		flags;
+   int			clen = length;
+   register u_short	xmtdata_base = TX_BASE;
+@@ -3204,7 +3183,7 @@ wavelan_packet_xmit(struct sk_buff *	skb,
+ static inline int
+ wv_mmc_init(struct net_device *	dev)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   psa_t		psa;
+   mmw_t		m;
+   int		configured;
 @@ -3223,14 +3202,14 @@ wv_mmc_init(struct net_device *	dev)
     * non-NCR/AT&T/Lucent PCMCIA cards, see wavelan_cs.h for detail on
     * how to configure your card...
@@ -681912,6 +740922,42 @@
      {
  #ifdef DEBUG_CONFIG_ERRORS
        printk(KERN_WARNING "%s: wv_mmc_init(): Invalid MAC address: %02X:%02X:%02X:...\n",
+@@ -3398,7 +3377,7 @@ wv_mmc_init(struct net_device *	dev)
+ static int
+ wv_ru_stop(struct net_device *	dev)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   net_local *	lp = netdev_priv(dev);
+   unsigned long	flags;
+   int		status;
+@@ -3461,7 +3440,7 @@ wv_ru_stop(struct net_device *	dev)
+ static int
+ wv_ru_start(struct net_device *	dev)
+ {
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+   net_local *	lp = netdev_priv(dev);
+   unsigned long	flags;
+ 
+@@ -3549,7 +3528,7 @@ wv_ru_start(struct net_device *	dev)
+ static int
+ wv_82593_config(struct net_device *	dev)
+ {
+-  kio_addr_t			base = dev->base_addr;
++  unsigned int			base = dev->base_addr;
+   net_local *			lp = netdev_priv(dev);
+   struct i82593_conf_block	cfblk;
+   int				ret = TRUE;
+@@ -3786,7 +3765,7 @@ static int
+ wv_hw_config(struct net_device *	dev)
+ {
+   net_local *		lp = netdev_priv(dev);
+-  kio_addr_t		base = dev->base_addr;
++  unsigned int		base = dev->base_addr;
+   unsigned long		flags;
+   int			ret = FALSE;
+ 
 @@ -3794,14 +3773,10 @@ wv_hw_config(struct net_device *	dev)
    printk(KERN_DEBUG "%s: ->wv_hw_config()\n", dev->name);
  #endif
@@ -681931,6 +740977,42 @@
  
    /* Reset the pcmcia interface */
    if(wv_pcmcia_reset(dev) == FALSE)
+@@ -4072,7 +4047,7 @@ wavelan_interrupt(int		irq,
+ {
+   struct net_device *	dev = dev_id;
+   net_local *	lp;
+-  kio_addr_t	base;
++  unsigned int	base;
+   int		status0;
+   u_int		tx_status;
+ 
+@@ -4331,7 +4306,7 @@ static void
+ wavelan_watchdog(struct net_device *	dev)
+ {
+   net_local *		lp = netdev_priv(dev);
+-  kio_addr_t		base = dev->base_addr;
++  unsigned int		base = dev->base_addr;
+   unsigned long		flags;
+   int			aborted = FALSE;
+ 
+@@ -4407,7 +4382,7 @@ wavelan_open(struct net_device *	dev)
+ {
+   net_local *	lp = netdev_priv(dev);
+   struct pcmcia_device *	link = lp->link;
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+ 
+ #ifdef DEBUG_CALLBACK_TRACE
+   printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name,
+@@ -4461,7 +4436,7 @@ static int
+ wavelan_close(struct net_device *	dev)
+ {
+   struct pcmcia_device *	link = ((net_local *)netdev_priv(dev))->link;
+-  kio_addr_t	base = dev->base_addr;
++  unsigned int	base = dev->base_addr;
+ 
+ #ifdef DEBUG_CALLBACK_TRACE
+   printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name,
 diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
 index 4b9de00..33dd970 100644
 --- a/drivers/net/wireless/wavelan_cs.p.h
@@ -685777,6 +744859,194 @@
  			mcl++;
  			HYPERVISOR_multicall(np->rx_mcl, mcl - np->rx_mcl);
  		}
+diff --git a/drivers/nubus/Makefile b/drivers/nubus/Makefile
+index f5ef03c..21bda20 100644
+--- a/drivers/nubus/Makefile
++++ b/drivers/nubus/Makefile
+@@ -4,5 +4,4 @@
+ 
+ obj-y   := nubus.o
+ 
+-obj-$(CONFIG_MODULES) += nubus_syms.o 
+ obj-$(CONFIG_PROC_FS) += proc.o
+diff --git a/drivers/nubus/nubus.c b/drivers/nubus/nubus.c
+index e503c9c..2f047e5 100644
+--- a/drivers/nubus/nubus.c
++++ b/drivers/nubus/nubus.c
+@@ -14,6 +14,7 @@
+ #include <linux/errno.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
++#include <linux/module.h>
+ #include <asm/setup.h>
+ #include <asm/system.h>
+ #include <asm/page.h>
+@@ -186,6 +187,7 @@ void nubus_get_rsrc_mem(void *dest, const struct nubus_dirent* dirent,
+ 		len--;
+ 	}
+ }
++EXPORT_SYMBOL(nubus_get_rsrc_mem);
+ 
+ void nubus_get_rsrc_str(void *dest, const struct nubus_dirent* dirent,
+ 			int len)
+@@ -200,6 +202,7 @@ void nubus_get_rsrc_str(void *dest, const struct nubus_dirent* dirent,
+ 		len--;
+ 	}
+ }
++EXPORT_SYMBOL(nubus_get_rsrc_str);
+ 
+ int nubus_get_root_dir(const struct nubus_board* board,
+ 		       struct nubus_dir* dir)
+@@ -209,6 +212,7 @@ int nubus_get_root_dir(const struct nubus_board* board,
+ 	dir->mask = board->lanes;
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_get_root_dir);
+ 
+ /* This is a slyly renamed version of the above */
+ int nubus_get_func_dir(const struct nubus_dev* dev,
+@@ -219,6 +223,7 @@ int nubus_get_func_dir(const struct nubus_dev* dev,
+ 	dir->mask = dev->board->lanes;
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_get_func_dir);
+ 
+ int nubus_get_board_dir(const struct nubus_board* board,
+ 			struct nubus_dir* dir)
+@@ -237,6 +242,7 @@ int nubus_get_board_dir(const struct nubus_board* board,
+ 		return -1;
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_get_board_dir);
+ 
+ int nubus_get_subdir(const struct nubus_dirent *ent,
+ 		     struct nubus_dir *dir)
+@@ -246,6 +252,7 @@ int nubus_get_subdir(const struct nubus_dirent *ent,
+ 	dir->mask = ent->mask;
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_get_subdir);
+ 
+ int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
+ {
+@@ -274,12 +281,14 @@ int nubus_readdir(struct nubus_dir *nd, struct nubus_dirent *ent)
+ 	ent->mask  = nd->mask;
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_readdir);
+ 
+ int nubus_rewinddir(struct nubus_dir* dir)
+ {
+ 	dir->ptr = dir->base;
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_rewinddir);
+ 
+ /* Driver interface functions, more or less like in pci.c */
+ 
+@@ -303,6 +312,7 @@ nubus_find_device(unsigned short category,
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL(nubus_find_device);
+ 
+ struct nubus_dev*
+ nubus_find_type(unsigned short category,
+@@ -320,6 +330,7 @@ nubus_find_type(unsigned short category,
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL(nubus_find_type);
+ 
+ struct nubus_dev*
+ nubus_find_slot(unsigned int slot,
+@@ -335,6 +346,7 @@ nubus_find_slot(unsigned int slot,
+ 	}
+ 	return NULL;
+ }
++EXPORT_SYMBOL(nubus_find_slot);
+ 
+ int
+ nubus_find_rsrc(struct nubus_dir* dir, unsigned char rsrc_type,
+@@ -346,13 +358,14 @@ nubus_find_rsrc(struct nubus_dir* dir, unsigned char rsrc_type,
+ 	}	
+ 	return -1;
+ }
++EXPORT_SYMBOL(nubus_find_rsrc);
+ 
+ /* Initialization functions - decide which slots contain stuff worth
+    looking at, and print out lots and lots of information from the
+    resource blocks. */
+ 
+ /* FIXME: A lot of this stuff will eventually be useful after
+-   initializaton, for intelligently probing Ethernet and video chips,
++   initialization, for intelligently probing Ethernet and video chips,
+    among other things.  The rest of it should go in the /proc code.
+    For now, we just use it to give verbose boot logs. */
+ 
+diff --git a/drivers/nubus/nubus_syms.c b/drivers/nubus/nubus_syms.c
+deleted file mode 100644
+index 9204f04..0000000
+--- a/drivers/nubus/nubus_syms.c
++++ /dev/null
+@@ -1,28 +0,0 @@
+-/* Exported symbols for NuBus services
+-
+-   (c) 1999 David Huggins-Daines <dhd at debian.org> */
+-
+-#include <linux/module.h>
+-#include <linux/types.h>
+-#include <linux/nubus.h>
+-
+-#ifdef CONFIG_PROC_FS
+-EXPORT_SYMBOL(nubus_proc_attach_device);
+-EXPORT_SYMBOL(nubus_proc_detach_device);
+-#endif
+-
+-MODULE_LICENSE("GPL");
+-
+-EXPORT_SYMBOL(nubus_find_device);
+-EXPORT_SYMBOL(nubus_find_type);
+-EXPORT_SYMBOL(nubus_find_slot);
+-EXPORT_SYMBOL(nubus_get_root_dir);
+-EXPORT_SYMBOL(nubus_get_board_dir);
+-EXPORT_SYMBOL(nubus_get_func_dir);
+-EXPORT_SYMBOL(nubus_readdir);
+-EXPORT_SYMBOL(nubus_find_rsrc);
+-EXPORT_SYMBOL(nubus_rewinddir);
+-EXPORT_SYMBOL(nubus_get_subdir);
+-EXPORT_SYMBOL(nubus_get_rsrc_mem);
+-EXPORT_SYMBOL(nubus_get_rsrc_str);
+-
+diff --git a/drivers/nubus/proc.c b/drivers/nubus/proc.c
+index 5271a4a..e07492b 100644
+--- a/drivers/nubus/proc.c
++++ b/drivers/nubus/proc.c
+@@ -22,6 +22,8 @@
+ #include <linux/nubus.h>
+ #include <linux/proc_fs.h>
+ #include <linux/init.h>
++#include <linux/module.h>
++
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+ 
+@@ -140,6 +142,7 @@ int nubus_proc_attach_device(struct nubus_dev *dev)
+ 
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_proc_attach_device);
+ 
+ /* FIXME: this is certainly broken! */
+ int nubus_proc_detach_device(struct nubus_dev *dev)
+@@ -154,6 +157,7 @@ int nubus_proc_detach_device(struct nubus_dev *dev)
+ 	}
+ 	return 0;
+ }
++EXPORT_SYMBOL(nubus_proc_detach_device);
+ 
+ void __init proc_bus_nubus_add_devices(void)
+ {
 diff --git a/drivers/of/base.c b/drivers/of/base.c
 index 9377f3b..b306fef 100644
 --- a/drivers/of/base.c
@@ -685883,6 +745153,80 @@
   * of_match_device - Tell if an of_device structure has a matching
   * of_match structure
   * @ids: array of of device match structures to search in
+diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
+index 7c60cbd..d08b284 100644
+--- a/drivers/parisc/ccio-dma.c
++++ b/drivers/parisc/ccio-dma.c
+@@ -363,7 +363,7 @@ ccio_alloc_range(struct ioc *ioc, size_t size)
+ 	if (pages_needed <= 8) {
+ 		/*
+ 		 * LAN traffic will not thrash the TLB IFF the same NIC
+-		 * uses 8 adjacent pages to map seperate payload data.
++		 * uses 8 adjacent pages to map separate payload data.
+ 		 * ie the same byte in the resource bit map.
+ 		 */
+ #if 0
+@@ -941,7 +941,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
+ 	** w/o this association, we wouldn't have coherent DMA!
+ 	** Access to the virtual address is what forces a two pass algorithm.
+ 	*/
+-	coalesced = iommu_coalesce_chunks(ioc, sglist, nents, ccio_alloc_range);
++	coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, ccio_alloc_range);
+ 
+ 	/*
+ 	** Program the I/O Pdir
+@@ -1589,7 +1589,7 @@ static int __init ccio_probe(struct parisc_device *dev)
+ }
+ 
+ /**
+- * ccio_init - ccio initalization procedure.
++ * ccio_init - ccio initialization procedure.
+  *
+  * Register this driver.
+  */
+diff --git a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
+index a728a7c..65eee67 100644
+--- a/drivers/parisc/hppb.c
++++ b/drivers/parisc/hppb.c
+@@ -95,7 +95,7 @@ static struct parisc_driver hppb_driver = {
+ };
+ 
+ /**
+- * hppb_init - HP-PB bus initalization procedure.
++ * hppb_init - HP-PB bus initialization procedure.
+  *
+  * Register this driver.   
+  */
+diff --git a/drivers/parisc/iommu-helpers.h b/drivers/parisc/iommu-helpers.h
+index 0a1f99a..97ba828 100644
+--- a/drivers/parisc/iommu-helpers.h
++++ b/drivers/parisc/iommu-helpers.h
+@@ -95,12 +95,14 @@ iommu_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents,
+ */
+ 
+ static inline unsigned int
+-iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents,
++iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
++		      struct scatterlist *startsg, int nents,
+ 		      int (*iommu_alloc_range)(struct ioc *, size_t))
+ {
+ 	struct scatterlist *contig_sg;	   /* contig chunk head */
+ 	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+ 	unsigned int n_mappings = 0;
++	unsigned int max_seg_size = dma_get_max_seg_size(dev);
+ 
+ 	while (nents > 0) {
+ 
+@@ -142,6 +144,9 @@ iommu_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents,
+ 					    IOVP_SIZE) > DMA_CHUNK_SIZE))
+ 				break;
+ 
++			if (startsg->length + dma_len > max_seg_size)
++				break;
++
+ 			/*
+ 			** Next see if we can append the next chunk (i.e.
+ 			** it must end on one page and begin on another
 diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
 index a6d6b24..703b85e 100644
 --- a/drivers/parisc/led.c
@@ -686382,11 +745726,47 @@
  }
  
  
+diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
+index e527a0e..d06627c 100644
+--- a/drivers/parisc/sba_iommu.c
++++ b/drivers/parisc/sba_iommu.c
+@@ -946,7 +946,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
+ 	** w/o this association, we wouldn't have coherent DMA!
+ 	** Access to the virtual address is what forces a two pass algorithm.
+ 	*/
+-	coalesced = iommu_coalesce_chunks(ioc, sglist, nents, sba_alloc_range);
++	coalesced = iommu_coalesce_chunks(ioc, dev, sglist, nents, sba_alloc_range);
+ 
+ 	/*
+ 	** Program the I/O Pdir
+diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
+index 853a15f..cd565bb 100644
+--- a/drivers/parport/probe.c
++++ b/drivers/parport/probe.c
+@@ -163,7 +163,7 @@ static ssize_t parport_read_device_id (struct parport *port, char *buffer,
+ 	idlens[1] = idlens[0]+2;
+ 	if (belen != lelen) {
+ 		int off = 2;
+-		/* Don't try lenghts of 0x100 and 0x200 as 1 and 2 */
++		/* Don't try lengths of 0x100 and 0x200 as 1 and 2 */
+ 		if (idlens[0] <= 2)
+ 			off = 0;
+ 		idlens[off] = max(belen, lelen);
 diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
-index 5550556..f697f3d 100644
+index 5550556..9f04d17 100644
 --- a/drivers/pci/Makefile
 +++ b/drivers/pci/Makefile
-@@ -32,7 +32,7 @@ obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+@@ -13,6 +13,9 @@ obj-$(CONFIG_HOTPLUG) += hotplug.o
+ 
+ # Build the PCI Hotplug drivers if we were asked to
+ obj-$(CONFIG_HOTPLUG_PCI) += hotplug/
++ifdef CONFIG_HOTPLUG_PCI
++obj-y += hotplug-pci.o
++endif
+ 
+ # Build the PCI MSI interrupt support
+ obj-$(CONFIG_PCI_MSI) += msi.o
+@@ -32,7 +35,7 @@ obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
  obj-$(CONFIG_PARISC) += setup-bus.o
  obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
  obj-$(CONFIG_PPC32) += setup-irq.o
@@ -686488,6 +745868,32 @@
  	return 0;
  }
  
+diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c
+new file mode 100644
+index 0000000..a590ef6
+--- /dev/null
++++ b/drivers/pci/hotplug-pci.c
+@@ -0,0 +1,20 @@
++/* Core PCI functionality used only by PCI hotplug */
++
++#include <linux/pci.h>
++#include "pci.h"
++
++
++unsigned int pci_do_scan_bus(struct pci_bus *bus)
++{
++	unsigned int max;
++
++	max = pci_scan_child_bus(bus);
++
++	/*
++	 * Make the discovered devices available.
++	 */
++	pci_bus_add_devices(bus);
++
++	return max;
++}
++EXPORT_SYMBOL(pci_do_scan_bus);
 diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
 index a64449d..2cdd832 100644
 --- a/drivers/pci/hotplug/Kconfig
@@ -688189,18 +747595,10 @@
  	pci_free_dynids(drv);
  }
 diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
-index 7d18773..abf4203 100644
+index 7d18773..8dcf145 100644
 --- a/drivers/pci/pci-sysfs.c
 +++ b/drivers/pci/pci-sysfs.c
-@@ -21,6 +21,7 @@
- #include <linux/topology.h>
- #include <linux/mm.h>
- #include <linux/capability.h>
-+#include <linux/aspm.h>
- #include "pci.h"
- 
- static int sysfs_initialized;	/* = 0 */
-@@ -358,7 +359,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+@@ -358,7 +358,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
  		   char *buf, loff_t off, size_t count)
  {
          struct pci_bus *bus = to_pci_bus(container_of(kobj,
@@ -688209,7 +747607,7 @@
  						      kobj));
  
          /* Only support 1, 2 or 4 byte accesses */
-@@ -383,7 +384,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
+@@ -383,7 +383,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
  		    char *buf, loff_t off, size_t count)
  {
          struct pci_bus *bus = to_pci_bus(container_of(kobj,
@@ -688218,7 +747616,7 @@
  						      kobj));
          /* Only support 1, 2 or 4 byte accesses */
          if (count != 1 && count != 2 && count != 4)
-@@ -407,7 +408,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
+@@ -407,7 +407,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
                      struct vm_area_struct *vma)
  {
          struct pci_bus *bus = to_pci_bus(container_of(kobj,
@@ -688227,37 +747625,11 @@
  						      kobj));
  
          return pci_mmap_legacy_page_range(bus, vma);
-@@ -650,6 +651,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
- 	if (pcibios_add_platform_entries(pdev))
- 		goto err_rom_file;
- 
-+	pcie_aspm_create_sysfs_dev_files(pdev);
-+
- 	return 0;
- 
- err_rom_file:
-@@ -679,6 +682,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
- 	if (!sysfs_initialized)
- 		return;
- 
-+	pcie_aspm_remove_sysfs_dev_files(pdev);
-+
- 	if (pdev->cfg_size < 4096)
- 		sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
- 	else
 diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
-index 71d561f..b3e9294 100644
+index 71d561f..ae3df46 100644
 --- a/drivers/pci/pci.c
 +++ b/drivers/pci/pci.c
-@@ -18,6 +18,7 @@
- #include <linux/spinlock.h>
- #include <linux/string.h>
- #include <linux/log2.h>
-+#include <linux/aspm.h>
- #include <asm/dma.h>	/* isa_dma_bridge_buggy */
- #include "pci.h"
- 
-@@ -314,6 +315,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
+@@ -314,6 +314,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
  }
  EXPORT_SYMBOL_GPL(pci_find_ht_capability);
  
@@ -688282,7 +747654,7 @@
  /**
   * pci_find_parent_resource - return resource region of parent bus of given region
   * @dev: PCI device structure contains resources to be searched
-@@ -353,7 +372,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
+@@ -353,7 +371,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
   * Restore the BAR values for a given device, so as to make it
   * accessible by its driver.
   */
@@ -688291,17 +747663,7 @@
  pci_restore_bars(struct pci_dev *dev)
  {
  	int i, numres;
-@@ -501,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
- 	if (need_restore)
- 		pci_restore_bars(dev);
- 
-+	if (dev->bus->self)
-+		pcie_aspm_pm_state_change(dev->bus->self);
-+
- 	return 0;
- }
- 
-@@ -551,6 +573,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
+@@ -551,6 +569,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
  	int pos, i = 0;
  	struct pci_cap_saved_state *save_state;
  	u16 *cap;
@@ -688309,7 +747671,7 @@
  
  	pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
  	if (pos <= 0)
-@@ -559,6 +582,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
+@@ -559,6 +578,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
  	save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
  	if (!save_state)
  		save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
@@ -688318,7 +747680,7 @@
  	if (!save_state) {
  		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
  		return -ENOMEM;
-@@ -569,7 +594,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
+@@ -569,7 +590,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
  	pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
  	pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
  	pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
@@ -688329,7 +747691,7 @@
  	return 0;
  }
  
-@@ -597,14 +624,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
+@@ -597,14 +620,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
  	int pos, i = 0;
  	struct pci_cap_saved_state *save_state;
  	u16 *cap;
@@ -688348,7 +747710,7 @@
  	if (!save_state) {
  		dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
  		return -ENOMEM;
-@@ -612,7 +642,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
+@@ -612,7 +638,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
  	cap = (u16 *)&save_state->data[0];
  
  	pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
@@ -688359,7 +747721,7 @@
  	return 0;
  }
  
-@@ -713,23 +745,19 @@ int pci_reenable_device(struct pci_dev *dev)
+@@ -713,23 +741,19 @@ int pci_reenable_device(struct pci_dev *dev)
  	return 0;
  }
  
@@ -688390,7 +747752,7 @@
  	err = do_pci_enable_device(dev, bars);
  	if (err < 0)
  		atomic_dec(&dev->enable_cnt);
-@@ -737,6 +765,32 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
+@@ -737,6 +761,32 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
  }
  
  /**
@@ -688423,7 +747785,7 @@
   * pci_enable_device - Initialize device before it's used by a driver.
   * @dev: PCI device to be initialized
   *
-@@ -749,7 +803,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
+@@ -749,7 +799,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
   */
  int pci_enable_device(struct pci_dev *dev)
  {
@@ -688432,7 +747794,7 @@
  }
  
  /*
-@@ -823,7 +877,8 @@ int pcim_enable_device(struct pci_dev *pdev)
+@@ -823,7 +873,8 @@ int pcim_enable_device(struct pci_dev *pdev)
  	dr = get_pci_dr(pdev);
  	if (unlikely(!dr))
  		return -ENOMEM;
@@ -688442,7 +747804,7 @@
  
  	rc = pci_enable_device(pdev);
  	if (!rc) {
-@@ -884,6 +939,9 @@ pci_disable_device(struct pci_dev *dev)
+@@ -884,6 +935,9 @@ pci_disable_device(struct pci_dev *dev)
  	if (atomic_sub_return(1, &dev->enable_cnt) != 0)
  		return;
  
@@ -688452,7 +747814,30 @@
  	pci_read_config_word(dev, PCI_COMMAND, &pci_command);
  	if (pci_command & PCI_COMMAND_MASTER) {
  		pci_command &= ~PCI_COMMAND_MASTER;
-@@ -1618,9 +1676,9 @@ early_param("pci", pci_setup);
+@@ -1397,6 +1451,22 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
+ }
+ #endif
+ 
++#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
++int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
++{
++	return dma_set_max_seg_size(&dev->dev, size);
++}
++EXPORT_SYMBOL(pci_set_dma_max_seg_size);
++#endif
++
++#ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY
++int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
++{
++	return dma_set_seg_boundary(&dev->dev, mask);
++}
++EXPORT_SYMBOL(pci_set_dma_seg_boundary);
++#endif
++
+ /**
+  * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count
+  * @dev: PCI device to query
+@@ -1618,9 +1688,9 @@ early_param("pci", pci_setup);
  
  device_initcall(pci_init);
  
@@ -688511,48 +747896,6 @@
   * Returns the matching pci_device_id structure or %NULL if there is no match.
   */
  static inline const struct pci_device_id *
-diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
-index 287a931..60104cf 100644
---- a/drivers/pci/pcie/Kconfig
-+++ b/drivers/pci/pcie/Kconfig
-@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
- 	  When in doubt, say N.
- 
- source "drivers/pci/pcie/aer/Kconfig"
-+
-+#
-+# PCI Express ASPM
-+#
-+config PCIEASPM
-+	bool "PCI Express ASPM support(Experimental)"
-+	depends on PCI && EXPERIMENTAL
-+	default y
-+	help
-+	  This enables PCI Express ASPM (Active State Power Management) and
-+	  Clock Power Management. ASPM supports state L0/L0s/L1.
-+
-+	  When in doubt, say N.
-+config PCIEASPM_DEBUG
-+	bool "Debug PCI Express ASPM"
-+	depends on PCIEASPM
-+	default n
-+	help
-+	  This enables PCI Express ASPM debug support. It will add per-device
-+	  interface to control ASPM.
-diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
-index e00fb99..11f6bb1 100644
---- a/drivers/pci/pcie/Makefile
-+++ b/drivers/pci/pcie/Makefile
-@@ -2,6 +2,9 @@
- # Makefile for PCI-Express PORT Driver
- #
- 
-+# Build PCI Express ASPM if needed
-+obj-$(CONFIG_PCIEASPM)		+= aspm.o
-+
- pcieportdrv-y			:= portdrv_core.o portdrv_pci.o portdrv_bus.o
- 
- obj-$(CONFIG_PCIEPORTBUS)	+= pcieportdrv.o
 diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
 index 1a1eb45..8c199ae 100644
 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -688591,814 +747934,6 @@
  		status = pci_osc_control_set(handle,
  					OSC_PCI_EXPRESS_AER_CONTROL |
  					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
-new file mode 100644
-index 0000000..1a5adeb
---- /dev/null
-+++ b/drivers/pci/pcie/aspm.c
-@@ -0,0 +1,802 @@
-+/*
-+ * File:	drivers/pci/pcie/aspm.c
-+ * Enabling PCIE link L0s/L1 state and Clock Power Management
-+ *
-+ * Copyright (C) 2007 Intel
-+ * Copyright (C) Zhang Yanmin (yanmin.zhang at intel.com)
-+ * Copyright (C) Shaohua Li (shaohua.li at intel.com)
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/moduleparam.h>
-+#include <linux/pci.h>
-+#include <linux/pci_regs.h>
-+#include <linux/errno.h>
-+#include <linux/pm.h>
-+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/aspm.h>
-+#include <acpi/acpi_bus.h>
-+#include <linux/pci-acpi.h>
-+#include "../pci.h"
-+
-+#ifdef MODULE_PARAM_PREFIX
-+#undef MODULE_PARAM_PREFIX
-+#endif
-+#define MODULE_PARAM_PREFIX "pcie_aspm."
-+
-+struct endpoint_state {
-+	unsigned int l0s_acceptable_latency;
-+	unsigned int l1_acceptable_latency;
-+};
-+
-+struct pcie_link_state {
-+	struct list_head sibiling;
-+	struct pci_dev *pdev;
-+
-+	/* ASPM state */
-+	unsigned int support_state;
-+	unsigned int enabled_state;
-+	unsigned int bios_aspm_state;
-+	/* upstream component */
-+	unsigned int l0s_upper_latency;
-+	unsigned int l1_upper_latency;
-+	/* downstream component */
-+	unsigned int l0s_down_latency;
-+	unsigned int l1_down_latency;
-+	/* Clock PM state*/
-+	unsigned int clk_pm_capable;
-+	unsigned int clk_pm_enabled;
-+	unsigned int bios_clk_state;
-+
-+	/*
-+	 * A pcie downstream port only has one slot under it, so at most there
-+	 * are 8 functions
-+	 */
-+	struct endpoint_state endpoints[8];
-+};
-+
-+static int aspm_disabled;
-+static DEFINE_MUTEX(aspm_lock);
-+static LIST_HEAD(link_list);
-+
-+#define POLICY_DEFAULT 0	/* BIOS default setting */
-+#define POLICY_PERFORMANCE 1	/* high performance */
-+#define POLICY_POWERSAVE 2	/* high power saving */
-+static int aspm_policy;
-+static const char *policy_str[] = {
-+	[POLICY_DEFAULT] = "default",
-+	[POLICY_PERFORMANCE] = "performance",
-+	[POLICY_POWERSAVE] = "powersave"
-+};
-+
-+static int policy_to_aspm_state(struct pci_dev *pdev)
-+{
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	switch (aspm_policy) {
-+	case POLICY_PERFORMANCE:
-+		/* Disable ASPM and Clock PM */
-+		return 0;
-+	case POLICY_POWERSAVE:
-+		/* Enable ASPM L0s/L1 */
-+		return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
-+	case POLICY_DEFAULT:
-+		return link_state->bios_aspm_state;
-+	}
-+	return 0;
-+}
-+
-+static int policy_to_clkpm_state(struct pci_dev *pdev)
-+{
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	switch (aspm_policy) {
-+	case POLICY_PERFORMANCE:
-+		/* Disable ASPM and Clock PM */
-+		return 0;
-+	case POLICY_POWERSAVE:
-+		/* Disable Clock PM */
-+		return 1;
-+	case POLICY_DEFAULT:
-+		return link_state->bios_clk_state;
-+	}
-+	return 0;
-+}
-+
-+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
-+{
-+	struct pci_dev *child_dev;
-+	int pos;
-+	u16 reg16;
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+		if (!pos)
-+			return;
-+		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
-+		if (enable)
-+			reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
-+		else
-+			reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
-+		pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
-+	}
-+	link_state->clk_pm_enabled = !!enable;
-+}
-+
-+static void pcie_check_clock_pm(struct pci_dev *pdev)
-+{
-+	int pos;
-+	u32 reg32;
-+	u16 reg16;
-+	int capable = 1, enabled = 1;
-+	struct pci_dev *child_dev;
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	/* All functions should have the same cap and state, take the worst */
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+		if (!pos)
-+			return;
-+		pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
-+		if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
-+			capable = 0;
-+			enabled = 0;
-+			break;
-+		}
-+		pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
-+		if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
-+			enabled = 0;
-+	}
-+	link_state->clk_pm_capable = capable;
-+	link_state->clk_pm_enabled = enabled;
-+	link_state->bios_clk_state = enabled;
-+	pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
-+}
-+
-+/*
-+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
-+ *   could use common clock. If they are, configure them to use the
-+ *   common clock. That will reduce the ASPM state exit latency.
-+ */
-+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
-+{
-+	int pos, child_pos;
-+	u16 reg16 = 0;
-+	struct pci_dev *child_dev;
-+	int same_clock = 1;
-+
-+	/*
-+	 * all functions of a slot should have the same Slot Clock
-+	 * Configuration, so just check one function
-+	 * */
-+	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
-+		bus_list);
-+	BUG_ON(!child_dev->is_pcie);
-+
-+	/* Check downstream component if bit Slot Clock Configuration is 1 */
-+	child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+	pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
-+	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
-+		same_clock = 0;
-+
-+	/* Check upstream component if bit Slot Clock Configuration is 1 */
-+	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+	pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
-+	if (!(reg16 & PCI_EXP_LNKSTA_SLC))
-+		same_clock = 0;
-+
-+	/* Configure downstream component, all functions */
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+		child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+		pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
-+			&reg16);
-+		if (same_clock)
-+			reg16 |= PCI_EXP_LNKCTL_CCC;
-+		else
-+			reg16 &= ~PCI_EXP_LNKCTL_CCC;
-+		pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
-+			reg16);
-+	}
-+
-+	/* Configure upstream component */
-+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-+	if (same_clock)
-+		reg16 |= PCI_EXP_LNKCTL_CCC;
-+	else
-+		reg16 &= ~PCI_EXP_LNKCTL_CCC;
-+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-+
-+	/* retrain link */
-+	reg16 |= PCI_EXP_LNKCTL_RL;
-+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-+
-+	/* Wait for link training end */
-+	while (1) {
-+		pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
-+		if (!(reg16 & PCI_EXP_LNKSTA_LT))
-+			break;
-+		cpu_relax();
-+	}
-+}
-+
-+/*
-+ * calc_L0S_latency: Convert L0s latency encoding to ns
-+ */
-+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
-+{
-+	unsigned int ns = 64;
-+
-+	if (latency_encoding == 0x7) {
-+		if (ac)
-+			ns = -1U;
-+		else
-+			ns = 5*1000; /* > 4us */
-+	} else
-+		ns *= (1 << latency_encoding);
-+	return ns;
-+}
-+
-+/*
-+ * calc_L1_latency: Convert L1 latency encoding to ns
-+ */
-+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
-+{
-+	unsigned int ns = 1000;
-+
-+	if (latency_encoding == 0x7) {
-+		if (ac)
-+			ns = -1U;
-+		else
-+			ns = 65*1000; /* > 64us */
-+	} else
-+		ns *= (1 << latency_encoding);
-+	return ns;
-+}
-+
-+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
-+	unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
-+{
-+	int pos;
-+	u16 reg16;
-+	u32 reg32;
-+	unsigned int latency;
-+
-+	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+	pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
-+	*state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
-+	if (*state != PCIE_LINK_STATE_L0S &&
-+		*state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
-+		* state = 0;
-+	if (*state == 0)
-+		return;
-+
-+	latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
-+	*l0s = calc_L0S_latency(latency, 0);
-+	if (*state & PCIE_LINK_STATE_L1) {
-+		latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
-+		*l1 = calc_L1_latency(latency, 0);
-+	}
-+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-+	*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
-+}
-+
-+static void pcie_aspm_cap_init(struct pci_dev *pdev)
-+{
-+	struct pci_dev *child_dev;
-+	u32 state, tmp;
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	/* upstream component states */
-+	pcie_aspm_get_cap_device(pdev, &link_state->support_state,
-+		&link_state->l0s_upper_latency,
-+		&link_state->l1_upper_latency,
-+		&link_state->enabled_state);
-+	/* downstream component states, all functions have the same setting */
-+	child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
-+		bus_list);
-+	pcie_aspm_get_cap_device(child_dev, &state,
-+		&link_state->l0s_down_latency,
-+		&link_state->l1_down_latency,
-+		&tmp);
-+	link_state->support_state &= state;
-+	if (!link_state->support_state)
-+		return;
-+	link_state->enabled_state &= link_state->support_state;
-+	link_state->bios_aspm_state = link_state->enabled_state;
-+
-+	/* ENDPOINT states*/
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+		int pos;
-+		u32 reg32;
-+		unsigned int latency;
-+		struct endpoint_state *ep_state =
-+			&link_state->endpoints[PCI_FUNC(child_dev->devfn)];
-+
-+		if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-+			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
-+			continue;
-+
-+		pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
-+		pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
-+		latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
-+		latency = calc_L0S_latency(latency, 1);
-+		ep_state->l0s_acceptable_latency = latency;
-+		if (link_state->support_state & PCIE_LINK_STATE_L1) {
-+			latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
-+			latency = calc_L1_latency(latency, 1);
-+			ep_state->l1_acceptable_latency = latency;
-+		}
-+	}
-+}
-+
-+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
-+	unsigned int state)
-+{
-+	struct pci_dev *parent_dev, *tmp_dev;
-+	unsigned int latency, l1_latency = 0;
-+	struct pcie_link_state *link_state;
-+	struct endpoint_state *ep_state;
-+
-+	parent_dev = pdev->bus->self;
-+	link_state = parent_dev->link_state;
-+	state &= link_state->support_state;
-+	if (state == 0)
-+		return 0;
-+	ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
-+
-+	/*
-+	 * Check latency for endpoint device.
-+	 * TBD: The latency from the endpoint to root complex vary per
-+	 * switch's upstream link state above the device. Here we just do a
-+	 * simple check which assumes all links above the device can be in L1
-+	 * state, that is we just consider the worst case. If switch's upstream
-+	 * link can't be put into L0S/L1, then our check is too strictly.
-+	 */
-+	tmp_dev = pdev;
-+	while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
-+		parent_dev = tmp_dev->bus->self;
-+		link_state = parent_dev->link_state;
-+		if (state & PCIE_LINK_STATE_L0S) {
-+			latency = max_t(unsigned int,
-+					link_state->l0s_upper_latency,
-+					link_state->l0s_down_latency);
-+			if (latency > ep_state->l0s_acceptable_latency)
-+				state &= ~PCIE_LINK_STATE_L0S;
-+		}
-+		if (state & PCIE_LINK_STATE_L1) {
-+			latency = max_t(unsigned int,
-+					link_state->l1_upper_latency,
-+					link_state->l1_down_latency);
-+			if (latency + l1_latency >
-+					ep_state->l1_acceptable_latency)
-+				state &= ~PCIE_LINK_STATE_L1;
-+		}
-+		if (!parent_dev->bus->self) /* parent_dev is a root port */
-+			break;
-+		else {
-+			/*
-+			 * parent_dev is the downstream port of a switch, make
-+			 * tmp_dev the upstream port of the switch
-+			 */
-+			tmp_dev = parent_dev->bus->self;
-+			/*
-+			 * every switch on the path to root complex need 1 more
-+			 * microsecond for L1. Spec doesn't mention L0S.
-+			 */
-+			if (state & PCIE_LINK_STATE_L1)
-+				l1_latency += 1000;
-+		}
-+	}
-+	return state;
-+}
-+
-+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
-+	unsigned int state)
-+{
-+	struct pci_dev *child_dev;
-+
-+	/* If no child, disable the link */
-+	if (list_empty(&pdev->subordinate->devices))
-+		return 0;
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
-+			/*
-+			 * If downstream component of a link is pci bridge, we
-+			 * disable ASPM for now for the link
-+			 * */
-+			state = 0;
-+			break;
-+		}
-+		if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
-+			child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
-+			continue;
-+		/* Device not in D0 doesn't need check latency */
-+		if (child_dev->current_state == PCI_D1 ||
-+			child_dev->current_state == PCI_D2 ||
-+			child_dev->current_state == PCI_D3hot ||
-+			child_dev->current_state == PCI_D3cold)
-+			continue;
-+		state = __pcie_aspm_check_state_one(child_dev, state);
-+	}
-+	return state;
-+}
-+
-+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
-+{
-+	u16 reg16;
-+	int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
-+
-+	pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
-+	reg16 &= ~0x3;
-+	reg16 |= state;
-+	pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
-+}
-+
-+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
-+{
-+	struct pci_dev *child_dev;
-+	int valid = 1;
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	/*
-+	 * if the downstream component has pci bridge function, don't do ASPM
-+	 * now
-+	 */
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
-+		if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
-+			valid = 0;
-+			break;
-+		}
-+	}
-+	if (!valid)
-+		return;
-+
-+	/*
-+	 * spec 2.0 suggests all functions should be configured the same
-+	 * setting for ASPM. Enabling ASPM L1 should be done in upstream
-+	 * component first and then downstream, and vice versa for disabling
-+	 * ASPM L1. Spec doesn't mention L0S.
-+	 */
-+	if (state & PCIE_LINK_STATE_L1)
-+		__pcie_aspm_config_one_dev(pdev, state);
-+
-+	list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
-+		__pcie_aspm_config_one_dev(child_dev, state);
-+
-+	if (!(state & PCIE_LINK_STATE_L1))
-+		__pcie_aspm_config_one_dev(pdev, state);
-+
-+	link_state->enabled_state = state;
-+}
-+
-+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
-+	unsigned int state)
-+{
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	if (link_state->support_state == 0)
-+		return;
-+	state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
-+
-+	/* state 0 means disabling aspm */
-+	state = pcie_aspm_check_state(pdev, state);
-+	if (link_state->enabled_state == state)
-+		return;
-+	__pcie_aspm_config_link(pdev, state);
-+}
-+
-+/*
-+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
-+ * @pdev: the root port or switch downstream port
-+ */
-+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
-+	unsigned int state)
-+{
-+	down_read(&pci_bus_sem);
-+	mutex_lock(&aspm_lock);
-+	__pcie_aspm_configure_link_state(pdev, state);
-+	mutex_unlock(&aspm_lock);
-+	up_read(&pci_bus_sem);
-+}
-+
-+static void free_link_state(struct pci_dev *pdev)
-+{
-+	kfree(pdev->link_state);
-+	pdev->link_state = NULL;
-+}
-+
-+/*
-+ * pcie_aspm_init_link_state: Initiate PCI express link state.
-+ * It is called after the pcie and its children devices are scaned.
-+ * @pdev: the root port or switch downstream port
-+ */
-+void pcie_aspm_init_link_state(struct pci_dev *pdev)
-+{
-+	unsigned int state;
-+	struct pcie_link_state *link_state;
-+	int error = 0;
-+
-+	if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
-+		return;
-+	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
-+		return;
-+	down_read(&pci_bus_sem);
-+	if (list_empty(&pdev->subordinate->devices))
-+		goto out;
-+
-+	mutex_lock(&aspm_lock);
-+
-+	link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
-+	if (!link_state)
-+		goto unlock_out;
-+	pdev->link_state = link_state;
-+
-+	pcie_aspm_configure_common_clock(pdev);
-+
-+	pcie_aspm_cap_init(pdev);
-+
-+	/* config link state to avoid BIOS error */
-+	state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
-+	__pcie_aspm_config_link(pdev, state);
-+
-+	pcie_check_clock_pm(pdev);
-+
-+	link_state->pdev = pdev;
-+	list_add(&link_state->sibiling, &link_list);
-+
-+unlock_out:
-+	if (error)
-+		free_link_state(pdev);
-+	mutex_unlock(&aspm_lock);
-+out:
-+	up_read(&pci_bus_sem);
-+}
-+
-+/* @pdev: the endpoint device */
-+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
-+{
-+	struct pci_dev *parent = pdev->bus->self;
-+	struct pcie_link_state *link_state = parent->link_state;
-+
-+	if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
-+		return;
-+	if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+		parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
-+		return;
-+	down_read(&pci_bus_sem);
-+	mutex_lock(&aspm_lock);
-+
-+	/*
-+	 * All PCIe functions are in one slot, remove one function will remove
-+	 * the the whole slot, so just wait
-+	 */
-+	if (!list_empty(&parent->subordinate->devices))
-+		goto out;
-+
-+	/* All functions are removed, so just disable ASPM for the link */
-+	__pcie_aspm_config_one_dev(parent, 0);
-+	list_del(&link_state->sibiling);
-+	/* Clock PM is for endpoint device */
-+
-+	free_link_state(parent);
-+out:
-+	mutex_unlock(&aspm_lock);
-+	up_read(&pci_bus_sem);
-+}
-+
-+/* @pdev: the root port or switch downstream port */
-+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
-+{
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
-+		return;
-+	if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
-+		return;
-+	/*
-+	 * devices changed PM state, we should recheck if latency meets all
-+	 * functions' requirement
-+	 */
-+	pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
-+}
-+
-+/*
-+ * pci_disable_link_state - disable pci device's link state, so the link will
-+ * never enter specific states
-+ */
-+void pci_disable_link_state(struct pci_dev *pdev, int state)
-+{
-+	struct pci_dev *parent = pdev->bus->self;
-+	struct pcie_link_state *link_state;
-+
-+	if (aspm_disabled || !pdev->is_pcie)
-+		return;
-+	if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
-+	    pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
-+		parent = pdev;
-+	if (!parent)
-+		return;
-+
-+	down_read(&pci_bus_sem);
-+	mutex_lock(&aspm_lock);
-+	link_state = parent->link_state;
-+	link_state->support_state &=
-+		~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
-+	if (state & PCIE_LINK_STATE_CLKPM)
-+		link_state->clk_pm_capable = 0;
-+
-+	__pcie_aspm_configure_link_state(parent, link_state->enabled_state);
-+	if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
-+		pcie_set_clock_pm(parent, 0);
-+	mutex_unlock(&aspm_lock);
-+	up_read(&pci_bus_sem);
-+}
-+EXPORT_SYMBOL(pci_disable_link_state);
-+
-+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
-+{
-+	int i;
-+	struct pci_dev *pdev;
-+	struct pcie_link_state *link_state;
-+
-+	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
-+		if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
-+			break;
-+	if (i >= ARRAY_SIZE(policy_str))
-+		return -EINVAL;
-+	if (i == aspm_policy)
-+		return 0;
-+
-+	down_read(&pci_bus_sem);
-+	mutex_lock(&aspm_lock);
-+	aspm_policy = i;
-+	list_for_each_entry(link_state, &link_list, sibiling) {
-+		pdev = link_state->pdev;
-+		__pcie_aspm_configure_link_state(pdev,
-+			policy_to_aspm_state(pdev));
-+		if (link_state->clk_pm_capable &&
-+		    link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
-+			pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
-+
-+	}
-+	mutex_unlock(&aspm_lock);
-+	up_read(&pci_bus_sem);
-+	return 0;
-+}
-+
-+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
-+{
-+	int i, cnt = 0;
-+	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
-+		if (i == aspm_policy)
-+			cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
-+		else
-+			cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
-+	return cnt;
-+}
-+
-+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
-+	NULL, 0644);
-+
-+#ifdef CONFIG_PCIEASPM_DEBUG
-+static ssize_t link_state_show(struct device *dev,
-+		struct device_attribute *attr,
-+		char *buf)
-+{
-+	struct pci_dev *pci_device = to_pci_dev(dev);
-+	struct pcie_link_state *link_state = pci_device->link_state;
-+
-+	return sprintf(buf, "%d\n", link_state->enabled_state);
-+}
-+
-+static ssize_t link_state_store(struct device *dev,
-+		struct device_attribute *attr,
-+		const char *buf,
-+		size_t n)
-+{
-+	struct pci_dev *pci_device = to_pci_dev(dev);
-+	int state;
-+
-+	if (n < 1)
-+		return -EINVAL;
-+	state = buf[0]-'0';
-+	if (state >= 0 && state <= 3) {
-+		/* setup link aspm state */
-+		pcie_aspm_configure_link_state(pci_device, state);
-+		return n;
-+	}
-+
-+	return -EINVAL;
-+}
-+
-+static ssize_t clk_ctl_show(struct device *dev,
-+		struct device_attribute *attr,
-+		char *buf)
-+{
-+	struct pci_dev *pci_device = to_pci_dev(dev);
-+	struct pcie_link_state *link_state = pci_device->link_state;
-+
-+	return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
-+}
-+
-+static ssize_t clk_ctl_store(struct device *dev,
-+		struct device_attribute *attr,
-+		const char *buf,
-+		size_t n)
-+{
-+	struct pci_dev *pci_device = to_pci_dev(dev);
-+	int state;
-+
-+	if (n < 1)
-+		return -EINVAL;
-+	state = buf[0]-'0';
-+
-+	down_read(&pci_bus_sem);
-+	mutex_lock(&aspm_lock);
-+	pcie_set_clock_pm(pci_device, !!state);
-+	mutex_unlock(&aspm_lock);
-+	up_read(&pci_bus_sem);
-+
-+	return n;
-+}
-+
-+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
-+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
-+
-+static char power_group[] = "power";
-+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
-+{
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
-+		return;
-+
-+	if (link_state->support_state)
-+		sysfs_add_file_to_group(&pdev->dev.kobj,
-+			&dev_attr_link_state.attr, power_group);
-+	if (link_state->clk_pm_capable)
-+		sysfs_add_file_to_group(&pdev->dev.kobj,
-+			&dev_attr_clk_ctl.attr, power_group);
-+}
-+
-+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
-+{
-+	struct pcie_link_state *link_state = pdev->link_state;
-+
-+	if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
-+		pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
-+		return;
-+
-+	if (link_state->support_state)
-+		sysfs_remove_file_from_group(&pdev->dev.kobj,
-+			&dev_attr_link_state.attr, power_group);
-+	if (link_state->clk_pm_capable)
-+		sysfs_remove_file_from_group(&pdev->dev.kobj,
-+			&dev_attr_clk_ctl.attr, power_group);
-+}
-+#endif
-+
-+static int __init pcie_aspm_disable(char *str)
-+{
-+	aspm_disabled = 1;
-+	return 1;
-+}
-+
-+__setup("pcie_noaspm", pcie_aspm_disable);
-+
-+static int __init pcie_aspm_init(void)
-+{
-+	if (aspm_disabled)
-+		return 0;
-+	pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
-+		OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
-+	return 0;
-+}
-+
-+fs_initcall(pcie_aspm_init);
 diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
 index b20a9b8..23d9eb0 100644
 --- a/drivers/pci/pcie/portdrv_core.c
@@ -689416,18 +747951,10 @@
  	
  	pos = PCI_CFG_SPACE_SIZE;
 diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
-index c5ca313..8b505bd 100644
+index c5ca313..4d23b9f 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 <linux/aspm.h>
- #include "pci.h"
- 
- #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */
-@@ -53,7 +54,7 @@ static void pci_create_legacy_files(struct pci_bus *b)
+@@ -53,7 +53,7 @@ static void pci_create_legacy_files(struct pci_bus *b)
  		b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
  		b->legacy_io->read = pci_read_legacy_io;
  		b->legacy_io->write = pci_write_legacy_io;
@@ -689436,7 +747963,7 @@
  
  		/* Allocated above after the legacy_io struct */
  		b->legacy_mem = b->legacy_io + 1;
-@@ -61,15 +62,15 @@ static void pci_create_legacy_files(struct pci_bus *b)
+@@ -61,15 +61,15 @@ static void pci_create_legacy_files(struct pci_bus *b)
  		b->legacy_mem->size = 1024*1024;
  		b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
  		b->legacy_mem->mmap = pci_mmap_legacy_mem;
@@ -689455,7 +747982,7 @@
  		kfree(b->legacy_io); /* both are allocated here */
  	}
  }
-@@ -81,26 +82,27 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
+@@ -81,26 +81,27 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
  /*
   * PCI Bus Class Devices
   */
@@ -689488,7 +748015,7 @@
  
  	if (pci_bus->bridge)
  		put_device(pci_bus->bridge);
-@@ -109,7 +111,7 @@ static void release_pcibus_dev(struct class_device *class_dev)
+@@ -109,7 +110,7 @@ static void release_pcibus_dev(struct class_device *class_dev)
  
  static struct class pcibus_class = {
  	.name		= "pci_bus",
@@ -689497,7 +748024,7 @@
  };
  
  static int __init pcibus_class_init(void)
-@@ -392,7 +394,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
+@@ -392,7 +393,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
  {
  	struct pci_bus *child;
  	int i;
@@ -689505,7 +748032,7 @@
  
  	/*
  	 * Allocate a new bus, and inherit stuff from the parent..
-@@ -408,15 +409,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
+@@ -408,15 +408,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
  	child->bus_flags = parent->bus_flags;
  	child->bridge = get_device(&bridge->dev);
  
@@ -689527,7 +748054,7 @@
  
  	/*
  	 * Set up the primary, secondary and subordinate
-@@ -434,12 +432,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
+@@ -434,15 +431,9 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
  	bridge->subordinate = child;
  
  	return child;
@@ -689539,8 +748066,12 @@
 -	return NULL;
  }
  
- struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
-@@ -471,8 +463,6 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
+-struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
++struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
+ {
+ 	struct pci_bus *child;
+ 
+@@ -471,8 +462,6 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
  	}
  }
  
@@ -689549,7 +748080,7 @@
  /*
   * If it's a bridge, configure it and scan the bus behind it.
   * For CardBus bridges, we don't scan behind as the devices will
-@@ -641,13 +631,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
+@@ -641,13 +630,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
  		    (child->number > bus->subordinate) ||
  		    (child->number < bus->number) ||
  		    (child->subordinate < bus->number)) {
@@ -689566,7 +748097,29 @@
  				bus->number, bus->subordinate);
  		}
  		bus = bus->parent;
-@@ -971,6 +961,7 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
+@@ -944,8 +933,12 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+ 
+ 	set_dev_node(&dev->dev, pcibus_to_node(bus));
+ 	dev->dev.dma_mask = &dev->dma_mask;
++	dev->dev.dma_parms = &dev->dma_parms;
+ 	dev->dev.coherent_dma_mask = 0xffffffffull;
+ 
++	pci_set_dma_max_seg_size(dev, 65536);
++	pci_set_dma_seg_boundary(dev, 0xffffffff);
++
+ 	/* Fix up broken headers */
+ 	pci_fixup_device(pci_fixup_header, dev);
+ 
+@@ -959,7 +952,7 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
+ 	up_write(&pci_bus_sem);
+ }
+ 
+-struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
++struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
+ {
+ 	struct pci_dev *dev;
+ 
+@@ -971,6 +964,7 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
  
  	return dev;
  }
@@ -689574,18 +748127,28 @@
  
  /**
   * pci_scan_slot - scan a PCI slot on a bus for devices.
-@@ -1011,6 +1002,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
- 				break;
- 		}
- 	}
-+
-+	if (bus->self)
-+		pcie_aspm_init_link_state(bus->self);
-+
- 	return nr;
+@@ -1050,20 +1044,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
+ 	return max;
  }
  
-@@ -1103,32 +1098,27 @@ struct pci_bus * pci_create_bus(struct device *parent,
+-unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
+-{
+-	unsigned int max;
+-
+-	max = pci_scan_child_bus(bus);
+-
+-	/*
+-	 * Make the discovered devices available.
+-	 */
+-	pci_bus_add_devices(bus);
+-
+-	return max;
+-}
+-
+ struct pci_bus * pci_create_bus(struct device *parent,
+ 		int bus, struct pci_ops *ops, void *sysdata)
+ {
+@@ -1103,32 +1083,27 @@ struct pci_bus * pci_create_bus(struct device *parent,
  		goto dev_reg_err;
  	b->bridge = get_device(dev);
  
@@ -689626,7 +748189,7 @@
  class_dev_reg_err:
  	device_unregister(dev);
  dev_reg_err:
-@@ -1140,7 +1130,6 @@ err_out:
+@@ -1140,7 +1115,6 @@ err_out:
  	kfree(b);
  	return NULL;
  }
@@ -689634,15 +748197,18 @@
  
  struct pci_bus *pci_scan_bus_parented(struct device *parent,
  		int bus, struct pci_ops *ops, void *sysdata)
-@@ -1159,7 +1148,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
- EXPORT_SYMBOL(pci_do_scan_bus);
+@@ -1156,10 +1130,8 @@ EXPORT_SYMBOL(pci_scan_bus_parented);
+ 
+ #ifdef CONFIG_HOTPLUG
+ EXPORT_SYMBOL(pci_add_new_bus);
+-EXPORT_SYMBOL(pci_do_scan_bus);
  EXPORT_SYMBOL(pci_scan_slot);
  EXPORT_SYMBOL(pci_scan_bridge);
 -EXPORT_SYMBOL(pci_scan_single_device);
  EXPORT_SYMBOL_GPL(pci_scan_child_bus);
  #endif
  
-@@ -1210,16 +1198,19 @@ static void __init pci_sort_breadthfirst_klist(void)
+@@ -1210,16 +1182,19 @@ static void __init pci_sort_breadthfirst_klist(void)
  	struct klist_node *n;
  	struct device *dev;
  	struct pci_dev *pdev;
@@ -690790,27 +749356,10 @@
  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373,
  			quirk_msi_intx_disable_bug);
 diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
-index 430281b..ec4a82b 100644
+index 430281b..9684e1b 100644
 --- a/drivers/pci/remove.c
 +++ b/drivers/pci/remove.c
-@@ -1,5 +1,6 @@
- #include <linux/pci.h>
- #include <linux/module.h>
-+#include <linux/aspm.h>
- #include "pci.h"
- 
- static void pci_free_resources(struct pci_dev *dev)
-@@ -30,6 +31,9 @@ static void pci_stop_dev(struct pci_dev *dev)
- 		dev->global_list.next = dev->global_list.prev = NULL;
- 		up_write(&pci_bus_sem);
- 	}
-+
-+	if (dev->bus->self)
-+		pcie_aspm_exit_link_state(dev);
- }
- 
- static void pci_destroy_dev(struct pci_dev *dev)
-@@ -74,10 +78,8 @@ void pci_remove_bus(struct pci_bus *pci_bus)
+@@ -74,10 +74,8 @@ void pci_remove_bus(struct pci_bus *pci_bus)
  	list_del(&pci_bus->node);
  	up_write(&pci_bus_sem);
  	pci_remove_legacy_files(pci_bus);
@@ -690867,7 +749416,7 @@
  EXPORT_SYMBOL(pci_unmap_rom);
 -EXPORT_SYMBOL(pci_remove_rom);
 diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
-index 401e03c..8a7232f 100644
+index 401e03c..262b043 100644
 --- a/drivers/pci/setup-bus.c
 +++ b/drivers/pci/setup-bus.c
 @@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
@@ -691030,6 +749579,24 @@
  		if (!align)
  			min_align = align1;
  		else if (ALIGN(align + min_align, min_align) < align1)
+@@ -440,7 +456,7 @@ pci_bus_size_cardbus(struct pci_bus *bus)
+ 	}
+ }
+ 
+-void pci_bus_size_bridges(struct pci_bus *bus)
++void __ref pci_bus_size_bridges(struct pci_bus *bus)
+ {
+ 	struct pci_dev *dev;
+ 	unsigned long mask, prefmask;
+@@ -495,7 +511,7 @@ void pci_bus_size_bridges(struct pci_bus *bus)
+ }
+ EXPORT_SYMBOL(pci_bus_size_bridges);
+ 
+-void pci_bus_assign_resources(struct pci_bus *bus)
++void __ref pci_bus_assign_resources(struct pci_bus *bus)
+ {
+ 	struct pci_bus *b;
+ 	struct pci_dev *dev;
 diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
 index 6dfd861..4be7ccf 100644
 --- a/drivers/pci/setup-res.c
@@ -691096,8 +749663,183 @@
  	pci_dev_put(dev);
  	return err;
  }
+diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c
+index eb6abd3..385e145 100644
+--- a/drivers/pcmcia/at91_cf.c
++++ b/drivers/pcmcia/at91_cf.c
+@@ -21,9 +21,9 @@
+ #include <asm/hardware.h>
+ #include <asm/io.h>
+ #include <asm/sizes.h>
++#include <asm/gpio.h>
+ 
+ #include <asm/arch/board.h>
+-#include <asm/arch/gpio.h>
+ #include <asm/arch/at91rm9200_mc.h>
+ 
+ 
+@@ -56,7 +56,7 @@ struct at91_cf_socket {
+ 
+ static inline int at91_cf_present(struct at91_cf_socket *cf)
+ {
+-	return !at91_get_gpio_value(cf->board->det_pin);
++	return !gpio_get_value(cf->board->det_pin);
+ }
+ 
+ /*--------------------------------------------------------------------------*/
+@@ -100,9 +100,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp)
+ 		int vcc	= cf->board->vcc_pin;
+ 
+ 		*sp = SS_DETECT | SS_3VCARD;
+-		if (!rdy || at91_get_gpio_value(rdy))
++		if (!rdy || gpio_get_value(rdy))
+ 			*sp |= SS_READY;
+-		if (!vcc || at91_get_gpio_value(vcc))
++		if (!vcc || gpio_get_value(vcc))
+ 			*sp |= SS_POWERON;
+ 	} else
+ 		*sp = 0;
+@@ -121,10 +121,10 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+ 	if (cf->board->vcc_pin) {
+ 		switch (s->Vcc) {
+ 			case 0:
+-				at91_set_gpio_value(cf->board->vcc_pin, 0);
++				gpio_set_value(cf->board->vcc_pin, 0);
+ 				break;
+ 			case 33:
+-				at91_set_gpio_value(cf->board->vcc_pin, 1);
++				gpio_set_value(cf->board->vcc_pin, 1);
+ 				break;
+ 			default:
+ 				return -EINVAL;
+@@ -132,7 +132,7 @@ at91_cf_set_socket(struct pcmcia_socket *sock, struct socket_state_t *s)
+ 	}
+ 
+ 	/* toggle reset if needed */
+-	at91_set_gpio_value(cf->board->rst_pin, s->flags & SS_RESET);
++	gpio_set_value(cf->board->rst_pin, s->flags & SS_RESET);
+ 
+ 	pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
+ 		driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
+@@ -239,11 +239,24 @@ static int __init at91_cf_probe(struct platform_device *pdev)
+ 	platform_set_drvdata(pdev, cf);
+ 
+ 	/* must be a GPIO; ergo must trigger on both edges */
+-	status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
++	status = gpio_request(board->det_pin, "cf_det");
+ 	if (status < 0)
+ 		goto fail0;
++	status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
++	if (status < 0)
++		goto fail00;
+ 	device_init_wakeup(&pdev->dev, 1);
+ 
++	status = gpio_request(board->rst_pin, "cf_rst");
++	if (status < 0)
++		goto fail0a;
++
++	if (board->vcc_pin) {
++		status = gpio_request(board->vcc_pin, "cf_vcc");
++		if (status < 0)
++			goto fail0b;
++	}
++
+ 	/*
+ 	 * The card driver will request this irq later as needed.
+ 	 * but it causes lots of "irqNN: nobody cared" messages
+@@ -251,16 +264,20 @@ static int __init at91_cf_probe(struct platform_device *pdev)
+ 	 * (Note:  DK board doesn't wire the IRQ pin...)
+ 	 */
+ 	if (board->irq_pin) {
++		status = gpio_request(board->irq_pin, "cf_irq");
++		if (status < 0)
++			goto fail0c;
+ 		status = request_irq(board->irq_pin, at91_cf_irq,
+ 				IRQF_SHARED, driver_name, cf);
+ 		if (status < 0)
+-			goto fail0a;
++			goto fail0d;
+ 		cf->socket.pci_irq = board->irq_pin;
+ 	} else
+ 		cf->socket.pci_irq = NR_IRQS + 1;
+ 
+ 	/* pcmcia layer only remaps "real" memory not iospace */
+-	cf->socket.io_offset = (unsigned long) ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
++	cf->socket.io_offset = (unsigned long)
++			ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
+ 	if (!cf->socket.io_offset) {
+ 		status = -ENXIO;
+ 		goto fail1;
+@@ -296,11 +313,21 @@ fail2:
+ fail1:
+ 	if (cf->socket.io_offset)
+ 		iounmap((void __iomem *) cf->socket.io_offset);
+-	if (board->irq_pin)
++	if (board->irq_pin) {
+ 		free_irq(board->irq_pin, cf);
++fail0d:
++		gpio_free(board->irq_pin);
++	}
++fail0c:
++	if (board->vcc_pin)
++		gpio_free(board->vcc_pin);
++fail0b:
++	gpio_free(board->rst_pin);
+ fail0a:
+ 	device_init_wakeup(&pdev->dev, 0);
+ 	free_irq(board->det_pin, cf);
++fail00:
++	gpio_free(board->det_pin);
+ fail0:
+ 	kfree(cf);
+ 	return status;
+@@ -313,13 +340,18 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
+ 	struct resource		*io = cf->socket.io[0].res;
+ 
+ 	pcmcia_unregister_socket(&cf->socket);
+-	if (board->irq_pin)
++	release_mem_region(io->start, io->end + 1 - io->start);
++	iounmap((void __iomem *) cf->socket.io_offset);
++	if (board->irq_pin) {
+ 		free_irq(board->irq_pin, cf);
++		gpio_free(board->irq_pin);
++	}
++	if (board->vcc_pin)
++		gpio_free(board->vcc_pin);
++	gpio_free(board->rst_pin);
+ 	device_init_wakeup(&pdev->dev, 0);
+ 	free_irq(board->det_pin, cf);
+-	iounmap((void __iomem *) cf->socket.io_offset);
+-	release_mem_region(io->start, io->end + 1 - io->start);
+-
++	gpio_free(board->det_pin);
+ 	kfree(cf);
+ 	return 0;
+ }
+diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c
+index a1bd763..714baae 100644
+--- a/drivers/pcmcia/cardbus.c
++++ b/drivers/pcmcia/cardbus.c
+@@ -143,7 +143,7 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void
+ 	/* Config space? */
+ 	if (space == 0) {
+ 		if (addr + len > 0x100)
+-			goto fail;
++			goto failput;
+ 		for (; len; addr++, ptr++, len--)
+ 			pci_read_config_byte(dev, addr, ptr);
+ 		return 0;
+@@ -171,6 +171,8 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void
+ 	memcpy_fromio(ptr, s->cb_cis_virt + addr, len);
+ 	return 0;
+ 
++failput:
++	pci_dev_put(dev);
+ fail:
+ 	memset(ptr, 0xff, len);
+ 	return -1;
 diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
-index 5cf89a9..15c18f5 100644
+index 5cf89a9..5a85871 100644
 --- a/drivers/pcmcia/ds.c
 +++ b/drivers/pcmcia/ds.c
 @@ -312,8 +312,7 @@ pcmcia_create_newid_file(struct pcmcia_driver *drv)
@@ -691110,6 +749852,315 @@
  	return error;
  }
  
+@@ -866,11 +865,12 @@ static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
+ 	ds_dbg(1, "trying to load CIS file %s\n", filename);
+ 
+ 	if (strlen(filename) > 14) {
+-		printk(KERN_WARNING "pcmcia: CIS filename is too long\n");
++		printk(KERN_WARNING "pcmcia: CIS filename is too long [%s]\n",
++			filename);
+ 		return -EINVAL;
+ 	}
+ 
+-	snprintf(path, 20, "%s", filename);
++	snprintf(path, sizeof(path), "%s", filename);
+ 
+ 	if (request_firmware(&fw, path, &dev->dev) == 0) {
+ 		if (fw->size >= CISTPL_MAX_CIS_SIZE) {
+@@ -1131,8 +1131,6 @@ static int runtime_suspend(struct device *dev)
+ 	down(&dev->sem);
+ 	rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
+ 	up(&dev->sem);
+-	if (!rc)
+-		dev->power.power_state.event = PM_EVENT_SUSPEND;
+ 	return rc;
+ }
+ 
+@@ -1143,8 +1141,6 @@ static void runtime_resume(struct device *dev)
+ 	down(&dev->sem);
+ 	rc = pcmcia_dev_resume(dev);
+ 	up(&dev->sem);
+-	if (!rc)
+-		dev->power.power_state.event = PM_EVENT_ON;
+ }
+ 
+ /************************ per-device sysfs output ***************************/
+@@ -1266,6 +1262,9 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
+ 	struct pcmcia_driver *p_drv = NULL;
+ 	int ret = 0;
+ 
++	if (p_dev->suspended)
++		return 0;
++
+ 	ds_dbg(2, "suspending %s\n", dev->bus_id);
+ 
+ 	if (dev->driver)
+@@ -1302,6 +1301,9 @@ static int pcmcia_dev_resume(struct device * dev)
+         struct pcmcia_driver *p_drv = NULL;
+ 	int ret = 0;
+ 
++	if (!p_dev->suspended)
++		return 0;
++
+ 	ds_dbg(2, "resuming %s\n", dev->bus_id);
+ 
+ 	if (dev->driver)
+diff --git a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c
+index df21e2d..7495155 100644
+--- a/drivers/pcmcia/i82092.c
++++ b/drivers/pcmcia/i82092.c
+@@ -82,7 +82,7 @@ struct socket_info {
+ 				    1 = empty socket, 
+ 				    2 = card but not initialized,
+ 				    3 = operational card */
+-	kio_addr_t io_base; 	/* base io address of the socket */
++	unsigned int io_base; 	/* base io address of the socket */
+ 	
+ 	struct pcmcia_socket socket;
+ 	struct pci_dev *dev;	/* The PCI device for the socket */
+diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
+index 839bb1c..32a2ab1 100644
+--- a/drivers/pcmcia/i82365.c
++++ b/drivers/pcmcia/i82365.c
+@@ -164,7 +164,7 @@ struct i82365_socket {
+     u_short		type, flags;
+     struct pcmcia_socket	socket;
+     unsigned int	number;
+-    kio_addr_t		ioaddr;
++    unsigned int	ioaddr;
+     u_short		psock;
+     u_char		cs_irq, intr;
+     union {
+@@ -238,7 +238,7 @@ static u_char i365_get(u_short sock, u_short reg)
+     unsigned long flags;
+     spin_lock_irqsave(&bus_lock,flags);
+     {
+-	kio_addr_t port = socket[sock].ioaddr;
++	unsigned int port = socket[sock].ioaddr;
+ 	u_char val;
+ 	reg = I365_REG(socket[sock].psock, reg);
+ 	outb(reg, port); val = inb(port+1);
+@@ -252,7 +252,7 @@ static void i365_set(u_short sock, u_short reg, u_char data)
+     unsigned long flags;
+     spin_lock_irqsave(&bus_lock,flags);
+     {
+-	kio_addr_t port = socket[sock].ioaddr;
++	unsigned int port = socket[sock].ioaddr;
+ 	u_char val = I365_REG(socket[sock].psock, reg);
+ 	outb(val, port); outb(data, port+1);
+ 	spin_unlock_irqrestore(&bus_lock,flags);
+@@ -588,7 +588,7 @@ static int to_cycles(int ns)
+ 
+ /*====================================================================*/
+ 
+-static int __init identify(kio_addr_t port, u_short sock)
++static int __init identify(unsigned int port, u_short sock)
+ {
+     u_char val;
+     int type = -1;
+@@ -659,7 +659,7 @@ static int __init identify(kio_addr_t port, u_short sock)
+ static int __init is_alive(u_short sock)
+ {
+     u_char stat;
+-    kio_addr_t start, stop;
++    unsigned int start, stop;
+     
+     stat = i365_get(sock, I365_STATUS);
+     start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
+@@ -678,7 +678,7 @@ static int __init is_alive(u_short sock)
+ 
+ /*====================================================================*/
+ 
+-static void __init add_socket(kio_addr_t port, int psock, int type)
++static void __init add_socket(unsigned int port, int psock, int type)
+ {
+     socket[sockets].ioaddr = port;
+     socket[sockets].psock = psock;
+@@ -698,7 +698,7 @@ static void __init add_pcic(int ns, int type)
+     base = sockets-ns;
+     if (base == 0) printk("\n");
+     printk(KERN_INFO "  %s", pcic[type].name);
+-    printk(" ISA-to-PCMCIA at port %#lx ofs 0x%02x",
++    printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
+ 	       t->ioaddr, t->psock*0x40);
+     printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
+ 
+@@ -772,7 +772,7 @@ static struct pnp_dev *i82365_pnpdev;
+ static void __init isa_probe(void)
+ {
+     int i, j, sock, k, ns, id;
+-    kio_addr_t port;
++    unsigned int port;
+ #ifdef CONFIG_PNP
+     struct isapnp_device_id *devid;
+     struct pnp_dev *dev;
+@@ -1053,7 +1053,7 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
+     u_char map, ioctl;
+     
+     debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
+-	  "%#lx-%#lx)\n", sock, io->map, io->flags,
++	  "%#x-%#x)\n", sock, io->map, io->flags,
+ 	  io->speed, io->start, io->stop);
+     map = io->map;
+     if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
+diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
+index 91da15b..3616da2 100644
+--- a/drivers/pcmcia/m32r_cfc.c
++++ b/drivers/pcmcia/m32r_cfc.c
+@@ -58,7 +58,7 @@ typedef struct pcc_socket {
+ 	u_short			type, flags;
+ 	struct pcmcia_socket	socket;
+ 	unsigned int		number;
+- 	kio_addr_t		ioaddr;
++	unsigned int		ioaddr;
+ 	u_long			mapaddr;
+ 	u_long			base;	/* PCC register base */
+ 	u_char			cs_irq1, cs_irq2, intr;
+@@ -298,7 +298,8 @@ static int __init is_alive(u_short sock)
+ 	return 0;
+ }
+ 
+-static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr)
++static void add_pcc_socket(ulong base, int irq, ulong mapaddr,
++			   unsigned int ioaddr)
+ {
+ 	pcc_socket_t *t = &socket[pcc_sockets];
+ 
+@@ -738,7 +739,7 @@ static int __init init_m32r_pcc(void)
+ #else	/* CONFIG_PLAT_USRV */
+ 	{
+ 		ulong base, mapaddr;
+-		kio_addr_t ioaddr;
++		unsigned int ioaddr;
+ 
+ 		for (i = 0 ; i < M32R_MAX_PCC ; i++) {
+ 			base = (ulong)PLD_CFRSTCR;
+diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
+index c5e0d89..2b42b71 100644
+--- a/drivers/pcmcia/m32r_pcc.c
++++ b/drivers/pcmcia/m32r_pcc.c
+@@ -65,7 +65,7 @@ typedef struct pcc_socket {
+ 	u_short			type, flags;
+ 	struct pcmcia_socket	socket;
+ 	unsigned int		number;
+- 	kio_addr_t		ioaddr;
++	unsigned int		ioaddr;
+ 	u_long			mapaddr;
+ 	u_long			base;	/* PCC register base */
+ 	u_char			cs_irq, intr;
+@@ -310,7 +310,8 @@ static int __init is_alive(u_short sock)
+ 	return 0;
+ }
+ 
+-static void add_pcc_socket(ulong base, int irq, ulong mapaddr, kio_addr_t ioaddr)
++static void add_pcc_socket(ulong base, int irq, ulong mapaddr,
++			   unsigned int ioaddr)
+ {
+   	pcc_socket_t *t = &socket[pcc_sockets];
+ 
+@@ -368,7 +369,7 @@ static irqreturn_t pcc_interrupt(int irq, void *dev)
+ 			handled = 1;
+ 			irc = pcc_get(i, PCIRC);
+ 			irc >>=16;
+-			debug(2, "m32r-pcc:interrput: socket %d pcirc 0x%02x ", i, irc);
++			debug(2, "m32r-pcc:interrupt: socket %d pcirc 0x%02x ", i, irc);
+ 			if (!irc)
+ 				continue;
+ 
+@@ -491,7 +492,7 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
+ 	u_char map;
+ 
+ 	debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, "
+-		  "%#lx-%#lx)\n", sock, io->map, io->flags,
++		  "%#x-%#x)\n", sock, io->map, io->flags,
+ 		  io->speed, io->start, io->stop);
+ 	map = io->map;
+ 
+diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
+index d182760..ac70d2c 100644
+--- a/drivers/pcmcia/m8xx_pcmcia.c
++++ b/drivers/pcmcia/m8xx_pcmcia.c
+@@ -851,7 +851,7 @@ static int m8xx_set_socket(struct pcmcia_socket *sock, socket_state_t * state)
+ 	   I tried to control the CxOE signal with SS_OUTPUT_ENA,
+ 	   but the reset signal seems connected via the 541.
+ 	   If the CxOE is left high are some signals tristated and
+-	   no pullups are present -> the cards act wierd.
++	   no pullups are present -> the cards act weird.
+ 	   So right now the buffers are enabled if the power is on. */
+ 
+ 	if (state->Vcc || state->Vpp)
+@@ -1174,8 +1174,10 @@ static int __init m8xx_probe(struct of_device *ofdev,
+ 
+ 	pcmcia_schlvl = irq_of_parse_and_map(np, 0);
+ 	hwirq = irq_map[pcmcia_schlvl].hwirq;
+-	if (pcmcia_schlvl < 0)
++	if (pcmcia_schlvl < 0) {
++		iounmap(pcmcia);
+ 		return -EINVAL;
++	}
+ 
+ 	m8xx_pgcrx[0] = &pcmcia->pcmc_pgcra;
+ 	m8xx_pgcrx[1] = &pcmcia->pcmc_pgcrb;
+@@ -1189,6 +1191,7 @@ static int __init m8xx_probe(struct of_device *ofdev,
+ 			driver_name, socket)) {
+ 		pcmcia_error("Cannot allocate IRQ %u for SCHLVL!\n",
+ 			     pcmcia_schlvl);
++		iounmap(pcmcia);
+ 		return -1;
+ 	}
+ 
+@@ -1284,6 +1287,7 @@ static int m8xx_remove(struct of_device *ofdev)
+ 	}
+ 	for (i = 0; i < PCMCIA_SOCKETS_NO; i++)
+ 		pcmcia_unregister_socket(&socket[i].socket);
++	iounmap(pcmcia);
+ 
+ 	free_irq(pcmcia_schlvl, NULL);
+ 
+diff --git a/drivers/pcmcia/pcmcia_resource.c b/drivers/pcmcia/pcmcia_resource.c
+index 0ce39de..1d128fb 100644
+--- a/drivers/pcmcia/pcmcia_resource.c
++++ b/drivers/pcmcia/pcmcia_resource.c
+@@ -65,23 +65,23 @@ extern int ds_pc_debug;
+  * Special stuff for managing IO windows, because they are scarce
+  */
+ 
+-static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
+-			  ioaddr_t num, u_int lines)
++static int alloc_io_space(struct pcmcia_socket *s, u_int attr,
++			  unsigned int *base, unsigned int num, u_int lines)
+ {
+ 	int i;
+-	kio_addr_t try, align;
++	unsigned int try, align;
+ 
+ 	align = (*base) ? (lines ? 1<<lines : 0) : 1;
+ 	if (align && (align < num)) {
+ 		if (*base) {
+-			ds_dbg(s, 0, "odd IO request: num %#x align %#lx\n",
++			ds_dbg(s, 0, "odd IO request: num %#x align %#x\n",
+ 			       num, align);
+ 			align = 0;
+ 		} else
+ 			while (align && (align < num)) align <<= 1;
+ 	}
+ 	if (*base & ~(align-1)) {
+-		ds_dbg(s, 0, "odd IO request: base %#x align %#lx\n",
++		ds_dbg(s, 0, "odd IO request: base %#x align %#x\n",
+ 		       *base, align);
+ 		align = 0;
+ 	}
+@@ -132,8 +132,8 @@ static int alloc_io_space(struct pcmcia_socket *s, u_int attr, ioaddr_t *base,
+ } /* alloc_io_space */
+ 
+ 
+-static void release_io_space(struct pcmcia_socket *s, ioaddr_t base,
+-			     ioaddr_t num)
++static void release_io_space(struct pcmcia_socket *s, unsigned int base,
++			     unsigned int num)
+ {
+ 	int i;
+ 
 diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
 index 874923f..e439044 100644
 --- a/drivers/pcmcia/pxa2xx_base.c
@@ -691122,6 +750173,74 @@
  
  #include <pcmcia/cs_types.h>
  #include <pcmcia/ss.h>
+diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
+index bfcaad6..a8d1007 100644
+--- a/drivers/pcmcia/rsrc_nonstatic.c
++++ b/drivers/pcmcia/rsrc_nonstatic.c
+@@ -186,15 +186,16 @@ static int sub_interval(struct resource_map *map, u_long base, u_long num)
+ ======================================================================*/
+ 
+ #ifdef CONFIG_PCMCIA_PROBE
+-static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num)
++static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
++			unsigned int num)
+ {
+     struct resource *res;
+     struct socket_data *s_data = s->resource_data;
+-    kio_addr_t i, j, bad;
++    unsigned int i, j, bad;
+     int any;
+     u_char *b, hole, most;
+ 
+-    printk(KERN_INFO "cs: IO port probe %#lx-%#lx:",
++    printk(KERN_INFO "cs: IO port probe %#x-%#x:",
+ 	   base, base+num-1);
+ 
+     /* First, what does a floating port look like? */
+@@ -233,7 +234,7 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num
+ 	} else {
+ 	    if (bad) {
+ 		sub_interval(&s_data->io_db, bad, i-bad);
+-		printk(" %#lx-%#lx", bad, i-1);
++		printk(" %#x-%#x", bad, i-1);
+ 		bad = 0;
+ 	    }
+ 	}
+@@ -244,7 +245,7 @@ static void do_io_probe(struct pcmcia_socket *s, kio_addr_t base, kio_addr_t num
+ 	    return;
+ 	} else {
+ 	    sub_interval(&s_data->io_db, bad, i-bad);
+-	    printk(" %#lx-%#lx", bad, i-1);
++	    printk(" %#x-%#x", bad, i-1);
+ 	}
+     }
+ 
+diff --git a/drivers/pcmcia/sa1100_jornada720.c b/drivers/pcmcia/sa1100_jornada720.c
+index af485ae..6284c35 100644
+--- a/drivers/pcmcia/sa1100_jornada720.c
++++ b/drivers/pcmcia/sa1100_jornada720.c
+@@ -101,7 +101,7 @@ static struct pcmcia_low_level jornada720_pcmcia_ops = {
+   .socket_suspend	= sa1111_pcmcia_socket_suspend,
+ };
+ 
+-int __init pcmcia_jornada720_init(struct device *dev)
++int __devinit pcmcia_jornada720_init(struct device *dev)
+ {
+ 	int ret = -ENODEV;
+ 
+diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
+index 749ac37..5792bd5 100644
+--- a/drivers/pcmcia/tcic.c
++++ b/drivers/pcmcia/tcic.c
+@@ -719,7 +719,7 @@ static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
+     u_short base, len, ioctl;
+     
+     debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
+-	  "%#lx-%#lx)\n", psock, io->map, io->flags,
++	  "%#x-%#x)\n", psock, io->map, io->flags,
+ 	  io->speed, io->start, io->stop);
+     if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
+ 	(io->stop < io->start)) return -EINVAL;
 diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c
 index 5dba68f..a8364d8 100644
 --- a/drivers/pnp/pnpbios/bioscalls.c
@@ -693884,7 +753003,7 @@
  dasd_mod-objs      := dasd.o dasd_ioctl.o dasd_proc.o dasd_devmap.o \
  			dasd_genhd.o dasd_erp.o
 diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
-index e6bfce6..d640427 100644
+index e6bfce6..d984e0f 100644
 --- a/drivers/s390/block/dasd.c
 +++ b/drivers/s390/block/dasd.c
 @@ -48,13 +48,15 @@ MODULE_LICENSE("GPL");
@@ -694709,7 +753828,7 @@
  		return;
  	}
  
-@@ -1017,277 +1040,170 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
+@@ -1017,277 +1040,169 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
  	}
  	DBF_DEV_EVENT(DBF_DEBUG, device, "Int: CS/DS 0x%04x for cqr %p",
  		      ((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr);
@@ -694767,12 +753886,11 @@
 -			cqr->stopclk = now;
 -			break;
 -		case dasd_era_recover:
-+		/* If we have no sense data, or we just don't want complex ERP
-+		 * for this request, but if we have retries left, then just
-+		 * reset this request and retry it in the fastpath
++		/*
++		 * If we don't want complex ERP for this request, then just
++		 * reset this and retry it in the fastpath
 +		 */
-+		if (!(cqr->irb.esw.esw0.erw.cons &&
-+		      test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) &&
++		if (!test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags) &&
 +		    cqr->retries > 0) {
 +			DEV_MESSAGE(KERN_DEBUG, device,
 +				    "default ERP in fastpath (%i retries left)",
@@ -695089,7 +754207,7 @@
  		} else {
  			DEV_MESSAGE(KERN_ERR, device,
  				    "internal error - timeout (%is) expired "
-@@ -1301,77 +1217,53 @@ __dasd_check_expire(struct dasd_device * device)
+@@ -1301,77 +1216,53 @@ __dasd_check_expire(struct dasd_device * device)
   * Take a look at the first request on the ccw queue and check
   * if it needs to be started.
   */
@@ -695188,7 +754306,7 @@
  		/* Check status and move request to flush_queue */
  		switch (cqr->status) {
  		case DASD_CQR_IN_IO:
-@@ -1387,90 +1279,60 @@ restart:
+@@ -1387,90 +1278,60 @@ restart:
  			}
  			break;
  		case DASD_CQR_QUEUED:
@@ -695304,7 +754422,7 @@
  {
  	/* Protect against rescheduling. */
  	if (atomic_cmpxchg (&device->tasklet_scheduled, 0, 1) != 0)
-@@ -1480,160 +1342,109 @@ dasd_schedule_bh(struct dasd_device * device)
+@@ -1480,160 +1341,109 @@ dasd_schedule_bh(struct dasd_device * device)
  }
  
  /*
@@ -695504,7 +754622,7 @@
  	return rc;
  }
  
-@@ -1643,25 +1454,23 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr)
+@@ -1643,25 +1453,23 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr)
   * and be put back to status queued, before the special request is added
   * to the head of the queue. Then the special request is waited on normally.
   */
@@ -695534,7 +754652,7 @@
  	spin_lock_irq(get_ccwdev_lock(device->cdev));
  	rc = _dasd_term_running_cqr(device);
  	if (rc) {
-@@ -1673,17 +1482,17 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr)
+@@ -1673,17 +1481,17 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr)
  	cqr->callback = dasd_wakeup_cb;
  	cqr->callback_data = (void *) &wait_q;
  	cqr->status = DASD_CQR_QUEUED;
@@ -695555,7 +754673,7 @@
  	return rc;
  }
  
-@@ -1692,11 +1501,14 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr)
+@@ -1692,11 +1500,14 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr)
   * This is useful to timeout requests. The request will be
   * terminated if it is currently in i/o.
   * Returns 1 if the request has been terminated.
@@ -695573,7 +754691,7 @@
  	unsigned long flags;
  	int rc;
  
-@@ -1704,74 +1516,454 @@ dasd_cancel_req(struct dasd_ccw_req *cqr)
+@@ -1704,74 +1515,450 @@ dasd_cancel_req(struct dasd_ccw_req *cqr)
  	spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
  	switch (cqr->status) {
  	case DASD_CQR_QUEUED:
@@ -695783,7 +754901,7 @@
 +
 +	req = (struct request *) cqr->callback_data;
 +	dasd_profile_end(cqr->block, cqr, req);
-+	status = cqr->memdev->discipline->free_cp(cqr, req);
++	status = cqr->block->base->discipline->free_cp(cqr, req);
 +	if (status <= 0)
 +		error = status ? status : -EIO;
 +	dasd_end_request(req, error);
@@ -695818,12 +754936,8 @@
 +
 +		/*  Process requests that may be recovered */
 +		if (cqr->status == DASD_CQR_NEED_ERP) {
-+			if (cqr->irb.esw.esw0.erw.cons &&
-+			    test_bit(DASD_CQR_FLAGS_USE_ERP,
-+				     &cqr->flags)) {
-+				erp_fn = base->discipline->erp_action(cqr);
-+				erp_fn(cqr);
-+			}
++			erp_fn = base->discipline->erp_action(cqr);
++			erp_fn(cqr);
 +			goto restart;
 +		}
 +
@@ -696063,7 +755177,7 @@
  		return rc;
  	}
  	return 0;
-@@ -1780,79 +1972,76 @@ dasd_alloc_queue(struct dasd_device * device)
+@@ -1780,79 +1967,76 @@ dasd_alloc_queue(struct dasd_device * device)
  /*
   * Allocate and initialize request queue.
   */
@@ -696171,7 +755285,7 @@
  			      " Cannot open unrecognized device");
  		rc = -ENODEV;
  		goto out;
-@@ -1861,41 +2050,41 @@ dasd_open(struct inode *inp, struct file *filp)
+@@ -1861,41 +2045,41 @@ dasd_open(struct inode *inp, struct file *filp)
  	return 0;
  
  out:
@@ -696229,7 +755343,7 @@
  	return 0;
  }
  
-@@ -1909,6 +2098,9 @@ dasd_device_operations = {
+@@ -1909,6 +2093,9 @@ dasd_device_operations = {
  	.getgeo		= dasd_getgeo,
  };
  
@@ -696239,7 +755353,7 @@
  
  static void
  dasd_exit(void)
-@@ -1937,9 +2129,8 @@ dasd_exit(void)
+@@ -1937,9 +2124,8 @@ dasd_exit(void)
   * Initial attempt at a probe function. this can be simplified once
   * the other detection code is gone.
   */
@@ -696251,7 +755365,7 @@
  {
  	int ret;
  
-@@ -1969,19 +2160,20 @@ dasd_generic_probe (struct ccw_device *cdev,
+@@ -1969,19 +2155,20 @@ dasd_generic_probe (struct ccw_device *cdev,
  		ret = ccw_device_set_online(cdev);
  	if (ret)
  		printk(KERN_WARNING
@@ -696277,7 +755391,7 @@
  
  	cdev->handler = NULL;
  
-@@ -2001,7 +2193,15 @@ dasd_generic_remove (struct ccw_device *cdev)
+@@ -2001,7 +2188,15 @@ dasd_generic_remove (struct ccw_device *cdev)
  	 */
  	dasd_set_target_state(device, DASD_STATE_NEW);
  	/* dasd_delete_device destroys the device reference. */
@@ -696293,7 +755407,7 @@
  }
  
  /*
-@@ -2009,10 +2209,8 @@ dasd_generic_remove (struct ccw_device *cdev)
+@@ -2009,10 +2204,8 @@ dasd_generic_remove (struct ccw_device *cdev)
   * the device is detected for the first time and is supposed to be used
   * or the user has started activation through sysfs.
   */
@@ -696306,7 +755420,7 @@
  {
  	struct dasd_discipline *discipline;
  	struct dasd_device *device;
-@@ -2048,6 +2246,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
+@@ -2048,6 +2241,7 @@ dasd_generic_set_online (struct ccw_device *cdev,
  	device->base_discipline = base_discipline;
  	device->discipline = discipline;
  
@@ -696314,7 +755428,7 @@
  	rc = discipline->check_device(device);
  	if (rc) {
  		printk (KERN_WARNING
-@@ -2067,6 +2266,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
+@@ -2067,6 +2261,8 @@ dasd_generic_set_online (struct ccw_device *cdev,
  			cdev->dev.bus_id);
  		rc = -ENODEV;
  		dasd_set_target_state(device, DASD_STATE_NEW);
@@ -696323,7 +755437,7 @@
  		dasd_delete_device(device);
  	} else
  		pr_debug("dasd_generic device %s found\n",
-@@ -2081,10 +2282,10 @@ dasd_generic_set_online (struct ccw_device *cdev,
+@@ -2081,10 +2277,10 @@ dasd_generic_set_online (struct ccw_device *cdev,
  	return rc;
  }
  
@@ -696336,7 +755450,7 @@
  	int max_count, open_count;
  
  	device = dasd_device_from_cdev(cdev);
-@@ -2101,30 +2302,39 @@ dasd_generic_set_offline (struct ccw_device *cdev)
+@@ -2101,30 +2297,39 @@ dasd_generic_set_offline (struct ccw_device *cdev)
  	 * the blkdev_get in dasd_scan_partitions. We are only interested
  	 * in the other openers.
  	 */
@@ -696393,7 +755507,7 @@
  {
  	struct dasd_device *device;
  	struct dasd_ccw_req *cqr;
-@@ -2145,27 +2355,22 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
+@@ -2145,27 +2350,22 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
  		if (device->state < DASD_STATE_BASIC)
  			break;
  		/* Device is active. We want to keep it. */
@@ -696433,7 +755547,7 @@
  		ret = 1;
  		break;
  	}
-@@ -2195,7 +2400,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
+@@ -2195,7 +2395,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
  	ccw->cda = (__u32)(addr_t)rdc_buffer;
  	ccw->count = rdc_buffer_size;
  
@@ -696443,7 +755557,7 @@
  	cqr->expires = 10*HZ;
  	clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
  	cqr->retries = 2;
-@@ -2217,13 +2423,12 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
+@@ -2217,13 +2418,12 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
  		return PTR_ERR(cqr);
  
  	ret = dasd_sleep_on(cqr);
@@ -696459,7 +755573,7 @@
  {
  	int rc;
  
-@@ -2231,7 +2436,7 @@ dasd_init(void)
+@@ -2231,7 +2431,7 @@ dasd_init(void)
  	init_waitqueue_head(&dasd_flush_wq);
  
  	/* register 'common' DASD debug area, used for all DBF_XXX calls */
@@ -696468,7 +755582,7 @@
  	if (dasd_debug_area == NULL) {
  		rc = -ENOMEM;
  		goto failed;
-@@ -2277,15 +2482,18 @@ EXPORT_SYMBOL(dasd_diag_discipline_pointer);
+@@ -2277,15 +2477,18 @@ EXPORT_SYMBOL(dasd_diag_discipline_pointer);
  EXPORT_SYMBOL(dasd_add_request_head);
  EXPORT_SYMBOL(dasd_add_request_tail);
  EXPORT_SYMBOL(dasd_cancel_req);
@@ -696490,7 +755604,7 @@
  EXPORT_SYMBOL(dasd_sfree_request);
  EXPORT_SYMBOL(dasd_sleep_on);
  EXPORT_SYMBOL(dasd_sleep_on_immediatly);
-@@ -2299,4 +2507,7 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove);
+@@ -2299,4 +2502,7 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove);
  EXPORT_SYMBOL_GPL(dasd_generic_notify);
  EXPORT_SYMBOL_GPL(dasd_generic_set_online);
  EXPORT_SYMBOL_GPL(dasd_generic_set_offline);
@@ -696590,7 +755704,7 @@
 -
 -}				/* END dasd_3370_erp_examine */
 diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
-index 5b7385e..c361ab6 100644
+index 5b7385e..f69714a 100644
 --- a/drivers/s390/block/dasd_3990_erp.c
 +++ b/drivers/s390/block/dasd_3990_erp.c
 @@ -26,158 +26,6 @@ struct DCTL_data {
@@ -696808,18 +755922,20 @@
  	//FIXME: start with get_opm ?
  	if (erp->lpm == 0)
  		erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
-@@ -309,9 +162,8 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
+@@ -309,10 +162,9 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
  			    "try alternate lpm=%x (lpum=%x / opm=%x)",
  			    erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);
  
 -		/* reset status to queued to handle the request again... */
 -		if (erp->status > DASD_CQR_QUEUED)
 -			erp->status = DASD_CQR_QUEUED;
+-		erp->retries = 1;
 +		/* reset status to submit the request again... */
 +		erp->status = DASD_CQR_FILLED;
- 		erp->retries = 1;
++		erp->retries = 10;
  	} else {
  		DEV_MESSAGE(KERN_ERR, device,
+ 			    "No alternate channel path left (lpum=%x / "
 @@ -320,8 +172,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
  			    erp->irb.esw.esw0.sublog.lpum, opm);
  
@@ -696874,7 +755990,26 @@
  
  	/* first time set initial retry counter and erp_function    */
  	/* and retry once without waiting for state change pending  */
-@@ -472,7 +324,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
+@@ -449,8 +301,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
+ 		erp->function = dasd_3990_erp_action_4;
+ 
+ 	} else {
+-
+-		if (sense[25] == 0x1D) {	/* state change pending */
++		if (sense && (sense[25] == 0x1D)) { /* state change pending */
+ 
+ 			DEV_MESSAGE(KERN_INFO, device,
+ 				    "waiting for state change pending "
+@@ -459,7 +310,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
+ 
+ 			dasd_3990_erp_block_queue(erp, 30*HZ);
+ 
+-                } else if (sense[25] == 0x1E) {	/* busy */
++		} else if (sense && (sense[25] == 0x1E)) {	/* busy */
+ 			DEV_MESSAGE(KERN_INFO, device,
+ 				    "busy - redriving request later, "
+ 				    "%d retries left",
+@@ -472,7 +323,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
  				     "redriving request immediately, "
  				     "%d retries left",
  				     erp->retries);
@@ -696883,7 +756018,7 @@
  		}
  	}
  
-@@ -530,7 +382,7 @@ static void
+@@ -530,7 +381,7 @@ static void
  dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696892,7 +756027,7 @@
  	char msg_format = (sense[7] & 0xF0);
  	char msg_no = (sense[7] & 0x0F);
  
-@@ -1157,7 +1009,7 @@ static struct dasd_ccw_req *
+@@ -1157,7 +1008,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696901,7 +756036,7 @@
  
  	erp->function = dasd_3990_erp_com_rej;
  
-@@ -1198,7 +1050,7 @@ static struct dasd_ccw_req *
+@@ -1198,7 +1049,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_bus_out(struct dasd_ccw_req * erp)
  {
  
@@ -696910,7 +756045,7 @@
  
  	/* first time set initial retry counter and erp_function */
  	/* and retry once without blocking queue		 */
-@@ -1237,7 +1089,7 @@ static struct dasd_ccw_req *
+@@ -1237,7 +1088,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696919,7 +756054,7 @@
  
  	erp->function = dasd_3990_erp_equip_check;
  
-@@ -1279,7 +1131,6 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
+@@ -1279,7 +1130,6 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
  
  		erp = dasd_3990_erp_action_5(erp);
  	}
@@ -696927,7 +756062,7 @@
  	return erp;
  
  }				/* end dasd_3990_erp_equip_check */
-@@ -1299,7 +1150,7 @@ static struct dasd_ccw_req *
+@@ -1299,7 +1149,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696936,7 +756071,7 @@
  
  	erp->function = dasd_3990_erp_data_check;
  
-@@ -1358,7 +1209,7 @@ static struct dasd_ccw_req *
+@@ -1358,7 +1208,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696945,7 +756080,7 @@
  
  	erp->function = dasd_3990_erp_overrun;
  
-@@ -1387,7 +1238,7 @@ static struct dasd_ccw_req *
+@@ -1387,7 +1237,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696954,7 +756089,7 @@
  
  	erp->function = dasd_3990_erp_inv_format;
  
-@@ -1403,8 +1254,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
+@@ -1403,8 +1253,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
  
  	} else {
  		DEV_MESSAGE(KERN_ERR, device, "%s",
@@ -696964,7 +756099,7 @@
  
  		erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
  	}
-@@ -1428,7 +1278,7 @@ static struct dasd_ccw_req *
+@@ -1428,7 +1277,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense)
  {
  
@@ -696973,7 +756108,7 @@
  
  	DEV_MESSAGE(KERN_ERR, device, "%s",
  		    "End-of-Cylinder - must never happen");
-@@ -1453,7 +1303,7 @@ static struct dasd_ccw_req *
+@@ -1453,7 +1302,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -696982,7 +756117,7 @@
  
  	erp->function = dasd_3990_erp_env_data;
  
-@@ -1463,11 +1313,9 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
+@@ -1463,11 +1312,9 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
  
  	/* don't retry on disabled interface */
  	if (sense[7] != 0x0F) {
@@ -696995,7 +756130,7 @@
  	}
  
  	return erp;
-@@ -1490,11 +1338,10 @@ static struct dasd_ccw_req *
+@@ -1490,11 +1337,10 @@ static struct dasd_ccw_req *
  dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense)
  {
  
@@ -697009,7 +756144,7 @@
  
  	return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
  
-@@ -1517,7 +1364,7 @@ static struct dasd_ccw_req *
+@@ -1517,7 +1363,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
  {
  
@@ -697018,7 +756153,7 @@
  
  	DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected");
  
-@@ -1526,6 +1373,43 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
+@@ -1526,6 +1372,43 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
  }				/* end dasd_3990_erp_file_prot */
  
  /*
@@ -697062,7 +756197,7 @@
   * DASD_3990_ERP_INSPECT_24
   *
   * DESCRIPTION
-@@ -1623,7 +1507,7 @@ static struct dasd_ccw_req *
+@@ -1623,7 +1506,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -697071,7 +756206,7 @@
  
  	erp->retries = 256;
  	erp->function = dasd_3990_erp_action_10_32;
-@@ -1657,13 +1541,14 @@ static struct dasd_ccw_req *
+@@ -1657,13 +1540,14 @@ static struct dasd_ccw_req *
  dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
  {
  
@@ -697088,7 +756223,7 @@
  
  	DEV_MESSAGE(KERN_DEBUG, device, "%s",
  		    "Write not finished because of unexpected condition");
-@@ -1702,8 +1587,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
+@@ -1702,8 +1586,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
  	/* Build new ERP request including DE/LO */
  	erp = dasd_alloc_erp_request((char *) &cqr->magic,
  				     2 + 1,/* DE/LO + TIC */
@@ -697099,7 +756234,7 @@
  
  	if (IS_ERR(erp)) {
  		DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP");
-@@ -1712,10 +1597,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
+@@ -1712,10 +1596,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
  
  	/* use original DE */
  	DE_data = erp->data;
@@ -697118,7 +756253,7 @@
  
  	if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
  
-@@ -1748,7 +1639,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
+@@ -1748,7 +1638,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
  
  	/* create DE ccw */
  	ccw = erp->cpaddr;
@@ -697127,7 +756262,7 @@
  	ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
  	ccw->flags = CCW_FLAG_CC;
  	ccw->count = 16;
-@@ -1756,7 +1647,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
+@@ -1756,7 +1646,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
  
  	/* create LO ccw */
  	ccw++;
@@ -697136,7 +756271,7 @@
  	ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
  	ccw->flags = CCW_FLAG_CC;
  	ccw->count = 16;
-@@ -1770,7 +1661,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
+@@ -1770,7 +1660,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
  	/* fill erp related fields */
  	erp->function = dasd_3990_erp_action_1B_32;
  	erp->refers = default_erp->refers;
@@ -697146,7 +756281,7 @@
  	erp->magic = default_erp->magic;
  	erp->expires = 0;
  	erp->retries = 256;
-@@ -1803,7 +1695,7 @@ static struct dasd_ccw_req *
+@@ -1803,7 +1694,7 @@ static struct dasd_ccw_req *
  dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
  {
  
@@ -697155,7 +756290,7 @@
  	__u32 cpa = 0;
  	struct dasd_ccw_req *cqr;
  	struct dasd_ccw_req *erp;
-@@ -1827,7 +1719,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
+@@ -1827,7 +1718,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
  		DEV_MESSAGE(KERN_DEBUG, device, "%s",
  			    "Imprecise ending is set - just retry");
  
@@ -697164,7 +756299,7 @@
  
  		return previous_erp;
  	}
-@@ -1850,7 +1742,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
+@@ -1850,7 +1741,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
  	erp = previous_erp;
  
  	/* update the LO with the new returned sense data  */
@@ -697173,7 +756308,7 @@
  
  	if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
  
-@@ -1889,7 +1781,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
+@@ -1889,7 +1780,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
  	ccw++;			/* addr of TIC ccw */
  	ccw->cda = cpa;
  
@@ -697182,7 +756317,7 @@
  
  	return erp;
  
-@@ -1968,9 +1860,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
+@@ -1968,9 +1859,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
  			 * try further actions. */
  
  			erp->lpm = 0;
@@ -697193,7 +756328,7 @@
  		}
  	}
  
-@@ -2047,7 +1937,7 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)
+@@ -2047,7 +1936,7 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)
  	if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) {
  
  		/* set to suspended duplex state then restart */
@@ -697202,7 +756337,7 @@
  
  		DEV_MESSAGE(KERN_ERR, device, "%s",
  			    "Set device to suspended duplex state should be "
-@@ -2081,28 +1971,26 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
+@@ -2081,28 +1970,26 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
  {
  
  	if ((erp->function == dasd_3990_erp_compound_retry) &&
@@ -697235,7 +756370,7 @@
  
  	return erp;
  
-@@ -2127,7 +2015,7 @@ static struct dasd_ccw_req *
+@@ -2127,7 +2014,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
  {
  
@@ -697244,7 +756379,7 @@
  
  	erp->function = dasd_3990_erp_inspect_32;
  
-@@ -2149,8 +2037,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
+@@ -2149,8 +2036,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
  
  		case 0x01:	/* fatal error */
  			DEV_MESSAGE(KERN_ERR, device, "%s",
@@ -697254,7 +756389,42 @@
  
  			erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
  			break;
-@@ -2253,6 +2140,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
+@@ -2233,6 +2119,34 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
+  */
+ 
+ /*
++ * DASD_3990_ERP_CONTROL_CHECK
++ *
++ * DESCRIPTION
++ *   Does a generic inspection if a control check occured and sets up
++ *   the related error recovery procedure
++ *
++ * PARAMETER
++ *   erp		pointer to the currently created default ERP
++ *
++ * RETURN VALUES
++ *   erp_filled		pointer to the erp
++ */
++
++static struct dasd_ccw_req *
++dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
++{
++	struct dasd_device *device = erp->startdev;
++
++	if (erp->refers->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK
++					   | SCHN_STAT_CHN_CTRL_CHK)) {
++		DEV_MESSAGE(KERN_DEBUG, device, "%s",
++			    "channel or interface control check");
++		erp = dasd_3990_erp_action_4(erp, NULL);
++	}
++	return erp;
++}
++
++/*
+  * DASD_3990_ERP_INSPECT
+  *
+  * DESCRIPTION
+@@ -2253,8 +2167,16 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp)
  	/* already set up new ERP !			      */
  	char *sense = erp->refers->irb.ecw;
  
@@ -697263,10 +756433,16 @@
 +	if (erp_new)
 +		return erp_new;
 +
++	/* check if no concurrent sens is available */
++	if (!erp->refers->irb.esw.esw0.erw.cons)
++		erp_new = dasd_3990_erp_control_check(erp);
  	/* distinguish between 24 and 32 byte sense data */
- 	if (sense[27] & DASD_SENSE_BIT_0) {
+-	if (sense[27] & DASD_SENSE_BIT_0) {
++	else if (sense[27] & DASD_SENSE_BIT_0) {
  
-@@ -2287,13 +2179,13 @@ static struct dasd_ccw_req *
+ 		/* inspect the 24 byte sense data */
+ 		erp_new = dasd_3990_erp_inspect_24(erp, sense);
+@@ -2287,13 +2209,13 @@ static struct dasd_ccw_req *
  dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
  {
  
@@ -697282,7 +756458,7 @@
  	if (IS_ERR(erp)) {
                  if (cqr->retries <= 0) {
  		        DEV_MESSAGE(KERN_ERR, device, "%s",
-@@ -2305,7 +2197,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
+@@ -2305,7 +2227,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
                                       "Unable to allocate ERP request "
  				     "(%i retries left)",
                                       cqr->retries);
@@ -697291,7 +756467,7 @@
                  }
  		return cqr;
  	}
-@@ -2319,7 +2211,9 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
+@@ -2319,7 +2241,9 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr)
  	ccw->cda      = (long)(cqr->cpaddr);
  	erp->function = dasd_3990_erp_add_erp;
  	erp->refers   = cqr;
@@ -697302,7 +756478,25 @@
  	erp->magic    = cqr->magic;
  	erp->expires  = 0;
  	erp->retries  = 256;
-@@ -2466,7 +2360,7 @@ static struct dasd_ccw_req *
+@@ -2391,6 +2315,17 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2)
+ 		//	return 0;	/* CCW doesn't match */
+ 	}
+ 
++	if (cqr1->irb.esw.esw0.erw.cons != cqr2->irb.esw.esw0.erw.cons)
++		return 0;
++
++	if ((cqr1->irb.esw.esw0.erw.cons == 0) &&
++	    (cqr2->irb.esw.esw0.erw.cons == 0))	{
++		if ((cqr1->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK |
++					     SCHN_STAT_CHN_CTRL_CHK)) ==
++		    (cqr2->irb.scsw.cstat & (SCHN_STAT_INTF_CTRL_CHK |
++					     SCHN_STAT_CHN_CTRL_CHK)))
++			return 1; /* match with ifcc*/
++	}
+ 	/* check sense data; byte 0-2,25,27 */
+ 	if (!((memcmp (cqr1->irb.ecw, cqr2->irb.ecw, 3) == 0) &&
+ 	      (cqr1->irb.ecw[27] == cqr2->irb.ecw[27]) &&
+@@ -2466,7 +2401,7 @@ static struct dasd_ccw_req *
  dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
  {
  
@@ -697311,7 +756505,7 @@
  	char *sense = erp->irb.ecw;
  
  	/* check for 24 byte sense ERP */
-@@ -2557,7 +2451,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
+@@ -2557,7 +2492,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
  			       struct dasd_ccw_req *erp)
  {
  
@@ -697320,7 +756514,7 @@
  	struct dasd_ccw_req *erp_done = erp_head;	/* finished req */
  	struct dasd_ccw_req *erp_free = NULL;	/* req to be freed */
  
-@@ -2569,13 +2463,13 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
+@@ -2569,13 +2504,13 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
  			      "original request was lost\n");
  
  		/* remove the request from the device queue */
@@ -697336,7 +756530,7 @@
  
  	}			/* end while */
  
-@@ -2603,7 +2497,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
+@@ -2603,7 +2538,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
  				    erp->retries, erp);
  
  			/* handle the request again... */
@@ -697345,7 +756539,7 @@
  		}
  
  	} else {
-@@ -2620,7 +2514,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
+@@ -2620,7 +2555,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
   * DASD_3990_ERP_ACTION
   *
   * DESCRIPTION
@@ -697354,7 +756548,7 @@
   *   Has to be called with the queue lock (namely the s390_irq_lock) acquired.
   *
   * PARAMETER
-@@ -2636,9 +2530,8 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
+@@ -2636,9 +2571,8 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
  struct dasd_ccw_req *
  dasd_3990_erp_action(struct dasd_ccw_req * cqr)
  {
@@ -697365,7 +756559,25 @@
  	struct dasd_ccw_req *temp_erp = NULL;
  
  	if (device->features & DASD_FEATURE_ERPLOG) {
-@@ -2704,10 +2597,11 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
+@@ -2667,17 +2601,6 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
+ 
+ 		return cqr;
+ 	}
+-	/* check if sense data are available */
+-	if (!cqr->irb.ecw) {
+-		DEV_MESSAGE(KERN_DEBUG, device,
+-			    "ERP called witout sense data avail ..."
+-			    "request %p - NO ERP possible", cqr);
+-
+-		cqr->status = DASD_CQR_FAILED;
+-
+-		return cqr;
+-
+-	}
+ 
+ 	/* check if error happened before */
+ 	erp = dasd_3990_erp_in_erp(cqr);
+@@ -2704,10 +2627,11 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr)
  		}
  	}
  
@@ -701653,7 +760865,7 @@
  	.next		= dasd_devices_next,
  	.stop		= dasd_devices_stop,
 diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
-index 15a5789..7779bfc 100644
+index 15a5789..3faf053 100644
 --- a/drivers/s390/block/dcssblk.c
 +++ b/drivers/s390/block/dcssblk.c
 @@ -82,7 +82,7 @@ struct dcssblk_dev_info {
@@ -701665,6 +760877,25 @@
  static struct rw_semaphore dcssblk_devices_sem;
  
  /*
+@@ -415,6 +415,8 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
+ 	dev_info->gd->queue = dev_info->dcssblk_queue;
+ 	dev_info->gd->private_data = dev_info;
+ 	dev_info->gd->driverfs_dev = &dev_info->dev;
++	blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request);
++	blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
+ 	/*
+ 	 * load the segment
+ 	 */
+@@ -472,9 +474,6 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
+ 	if (rc)
+ 		goto unregister_dev;
+ 
+-	blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request);
+-	blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096);
+-
+ 	add_disk(dev_info->gd);
+ 
+ 	switch (dev_info->segment_type) {
 diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
 index 130de19..7e73e39 100644
 --- a/drivers/s390/char/Makefile
@@ -703202,6 +762433,32 @@
   * the buffer.
   */
  void *
+diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
+index e3b3d39..2e616e3 100644
+--- a/drivers/s390/char/sclp_tty.c
++++ b/drivers/s390/char/sclp_tty.c
+@@ -332,7 +332,7 @@ sclp_tty_write_string(const unsigned char *str, int count)
+ 		if (sclp_ttybuf == NULL) {
+ 			while (list_empty(&sclp_tty_pages)) {
+ 				spin_unlock_irqrestore(&sclp_tty_lock, flags);
+-				if (in_interrupt())
++				if (in_atomic())
+ 					sclp_sync_wait();
+ 				else
+ 					wait_event(sclp_tty_waitq,
+diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c
+index 40cd21b..6807162 100644
+--- a/drivers/s390/char/sclp_vt220.c
++++ b/drivers/s390/char/sclp_vt220.c
+@@ -400,7 +400,7 @@ __sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
+ 			while (list_empty(&sclp_vt220_empty)) {
+ 				spin_unlock_irqrestore(&sclp_vt220_lock,
+ 						       flags);
+-				if (in_interrupt())
++				if (in_atomic())
+ 					sclp_sync_wait();
+ 				else
+ 					wait_event(sclp_vt220_waitq,
 diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
 index da25f8e..8246ef3 100644
 --- a/drivers/s390/char/tape_3590.c
@@ -703569,7 +762826,7 @@
  	.stop  = cio_ignore_proc_seq_stop,
  	.next  = cio_ignore_proc_seq_next,
 diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
-index 5baa517..3964056 100644
+index 5baa517..03914fa 100644
 --- a/drivers/s390/cio/ccwgroup.c
 +++ b/drivers/s390/cio/ccwgroup.c
 @@ -35,8 +35,8 @@ ccwgroup_bus_match (struct device * dev, struct device_driver * drv)
@@ -703630,7 +762887,32 @@
  			put_device(&gdev->cdev[i]->dev);
  		}
  	mutex_unlock(&gdev->reg_mutex);
-@@ -408,6 +410,7 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
+@@ -389,12 +391,24 @@ ccwgroup_remove (struct device *dev)
+ 	return 0;
+ }
+ 
++static void ccwgroup_shutdown(struct device *dev)
++{
++	struct ccwgroup_device *gdev;
++	struct ccwgroup_driver *gdrv;
++
++	gdev = to_ccwgroupdev(dev);
++	gdrv = to_ccwgroupdrv(dev->driver);
++	if (gdrv && gdrv->shutdown)
++		gdrv->shutdown(gdev);
++}
++
+ static struct bus_type ccwgroup_bus_type = {
+ 	.name   = "ccwgroup",
+ 	.match  = ccwgroup_bus_match,
+ 	.uevent = ccwgroup_uevent,
+ 	.probe  = ccwgroup_probe,
+ 	.remove = ccwgroup_remove,
++	.shutdown = ccwgroup_shutdown,
+ };
+ 
+ /**
+@@ -408,6 +422,7 @@ int ccwgroup_driver_register(struct ccwgroup_driver *cdriver)
  	/* register our new driver with the core */
  	cdriver->driver.bus = &ccwgroup_bus_type;
  	cdriver->driver.name = cdriver->name;
@@ -703638,7 +762920,7 @@
  
  	return driver_register(&cdriver->driver);
  }
-@@ -463,8 +466,8 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
+@@ -463,8 +478,8 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
  {
  	struct ccwgroup_device *gdev;
  
@@ -703650,10 +762932,50 @@
  			mutex_lock(&gdev->reg_mutex);
  			if (device_is_registered(&gdev->dev))
 diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
-index 597c0c7..e7ba16a 100644
+index 597c0c7..007aaeb 100644
 --- a/drivers/s390/cio/chsc.c
 +++ b/drivers/s390/cio/chsc.c
-@@ -89,7 +89,8 @@ int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
+@@ -26,6 +26,25 @@
+ 
+ static void *sei_page;
+ 
++static int chsc_error_from_response(int response)
++{
++	switch (response) {
++	case 0x0001:
++		return 0;
++	case 0x0002:
++	case 0x0003:
++	case 0x0006:
++	case 0x0007:
++	case 0x0008:
++	case 0x000a:
++		return -EINVAL;
++	case 0x0004:
++		return -EOPNOTSUPP;
++	default:
++		return -EIO;
++	}
++}
++
+ struct chsc_ssd_area {
+ 	struct chsc_header request;
+ 	u16 :10;
+@@ -75,11 +94,11 @@ int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
+ 		ret = (ccode == 3) ? -ENODEV : -EBUSY;
+ 		goto out_free;
+ 	}
+-	if (ssd_area->response.code != 0x0001) {
++	ret = chsc_error_from_response(ssd_area->response.code);
++	if (ret != 0) {
+ 		CIO_MSG_EVENT(2, "chsc: ssd failed for 0.%x.%04x (rc=%04x)\n",
+ 			      schid.ssid, schid.sch_no,
+ 			      ssd_area->response.code);
+-		ret = -EIO;
+ 		goto out_free;
+ 	}
+ 	if (!ssd_area->sch_valid) {
+@@ -89,7 +108,8 @@ int chsc_get_ssd_info(struct subchannel_id schid, struct chsc_ssd_info *ssd)
  	/* Copy data */
  	ret = 0;
  	memset(ssd, 0, sizeof(struct chsc_ssd_info));
@@ -703663,7 +762985,7 @@
  		goto out_free;
  	ssd->path_mask = ssd_area->path_mask;
  	ssd->fla_valid_mask = ssd_area->fla_valid_mask;
-@@ -132,20 +133,16 @@ static void terminate_internal_io(struct subchannel *sch)
+@@ -132,20 +152,16 @@ static void terminate_internal_io(struct subchannel *sch)
  	device_set_intretry(sch);
  	/* Call handler. */
  	if (sch->driver && sch->driver->termination)
@@ -703687,7 +763009,7 @@
  	for (j = 0; j < 8; j++) {
  		mask = 0x80 >> j;
  		if ((sch->schib.pmcw.pim & mask) &&
-@@ -158,7 +155,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
+@@ -158,7 +174,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
  	spin_lock_irq(sch->lock);
  
  	stsch(sch->schid, &schib);
@@ -703696,7 +763018,7 @@
  		goto out_unreg;
  	memcpy(&sch->schib, &schib, sizeof(struct schib));
  	/* Check for single path devices. */
-@@ -172,12 +169,12 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
+@@ -172,12 +188,12 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
  			terminate_internal_io(sch);
  			/* Re-start path verification. */
  			if (sch->driver && sch->driver->verify)
@@ -703711,7 +763033,7 @@
  		else if (sch->lpm == mask)
  			goto out_unreg;
  	}
-@@ -201,12 +198,10 @@ void chsc_chp_offline(struct chp_id chpid)
+@@ -201,12 +217,10 @@ void chsc_chp_offline(struct chp_id chpid)
  
  	if (chp_get_status(chpid) <= 0)
  		return;
@@ -703726,7 +763048,7 @@
  {
  	struct schib schib;
  	/*
-@@ -252,18 +247,10 @@ static int get_res_chpid_mask(struct chsc_ssd_info *ssd,
+@@ -252,18 +266,10 @@ static int get_res_chpid_mask(struct chsc_ssd_info *ssd,
  	return 0;
  }
  
@@ -703747,7 +763069,7 @@
  
  	spin_lock_irq(sch->lock);
  	chp_mask = get_res_chpid_mask(&sch->ssd_info, res_data);
-@@ -279,10 +266,10 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
+@@ -279,10 +285,10 @@ __s390_process_res_acc(struct subchannel_id schid, void *data)
  	if (!old_lpm && sch->lpm)
  		device_trigger_reprobe(sch);
  	else if (sch->driver && sch->driver->verify)
@@ -703760,7 +763082,7 @@
  	return 0;
  }
  
-@@ -305,7 +292,8 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
+@@ -305,7 +311,8 @@ static void s390_process_res_acc (struct res_acc_data *res_data)
  	 * The more information we have (info), the less scanning
  	 * will we have to do.
  	 */
@@ -703770,7 +763092,7 @@
  }
  
  static int
-@@ -499,8 +487,7 @@ void chsc_process_crw(void)
+@@ -499,8 +506,7 @@ void chsc_process_crw(void)
  	} while (sei_area->flags & 0x80);
  }
  
@@ -703780,7 +763102,7 @@
  {
  	struct schib schib;
  
-@@ -514,45 +501,37 @@ __chp_add_new_sch(struct subchannel_id schid)
+@@ -514,45 +520,37 @@ __chp_add_new_sch(struct subchannel_id schid)
  }
  
  
@@ -703837,7 +763159,7 @@
  	return 0;
  }
  
-@@ -564,7 +543,8 @@ void chsc_chp_online(struct chp_id chpid)
+@@ -564,7 +562,8 @@ void chsc_chp_online(struct chp_id chpid)
  	CIO_TRACE_EVENT(2, dbf_txt);
  
  	if (chp_get_status(chpid) != 0)
@@ -703847,7 +763169,7 @@
  }
  
  static void __s390_subchannel_vary_chpid(struct subchannel *sch,
-@@ -589,7 +569,7 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
+@@ -589,7 +588,7 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
  			if (!old_lpm)
  				device_trigger_reprobe(sch);
  			else if (sch->driver && sch->driver->verify)
@@ -703856,7 +763178,7 @@
  			break;
  		}
  		sch->opm &= ~mask;
-@@ -603,37 +583,29 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
+@@ -603,37 +602,29 @@ static void __s390_subchannel_vary_chpid(struct subchannel *sch,
  				terminate_internal_io(sch);
  				/* Re-start path verification. */
  				if (sch->driver && sch->driver->verify)
@@ -703900,7 +763222,7 @@
  
  	__s390_subchannel_vary_chpid(sch, *chpid, 1);
  	return 0;
-@@ -643,13 +615,7 @@ static int
+@@ -643,13 +634,7 @@ static int
  __s390_vary_chpid_on(struct subchannel_id schid, void *data)
  {
  	struct schib schib;
@@ -703914,7 +763236,7 @@
  	if (stsch_err(schid, &schib))
  		/* We're through */
  		return -ENXIO;
-@@ -669,12 +635,13 @@ int chsc_chp_vary(struct chp_id chpid, int on)
+@@ -669,12 +654,13 @@ int chsc_chp_vary(struct chp_id chpid, int on)
  	 * Redo PathVerification on the devices the chpid connects to
  	 */
  
@@ -703933,15 +763255,193 @@
  	return 0;
  }
  
-@@ -1075,7 +1042,7 @@ chsc_determine_css_characteristics(void)
+@@ -750,36 +736,15 @@ __chsc_do_secm(struct channel_subsystem *css, int enable, void *page)
+ 		return (ccode == 3) ? -ENODEV : -EBUSY;
+ 
+ 	switch (secm_area->response.code) {
+-	case 0x0001: /* Success. */
+-		ret = 0;
+-		break;
+-	case 0x0003: /* Invalid block. */
+-	case 0x0007: /* Invalid format. */
+-	case 0x0008: /* Other invalid block. */
+-		CIO_CRW_EVENT(2, "Error in chsc request block!\n");
++	case 0x0102:
++	case 0x0103:
+ 		ret = -EINVAL;
+-		break;
+-	case 0x0004: /* Command not provided in model. */
+-		CIO_CRW_EVENT(2, "Model does not provide secm\n");
+-		ret = -EOPNOTSUPP;
+-		break;
+-	case 0x0102: /* cub adresses incorrect */
+-		CIO_CRW_EVENT(2, "Invalid addresses in chsc request block\n");
+-		ret = -EINVAL;
+-		break;
+-	case 0x0103: /* key error */
+-		CIO_CRW_EVENT(2, "Access key error in secm\n");
+-		ret = -EINVAL;
+-		break;
+-	case 0x0105: /* error while starting */
+-		CIO_CRW_EVENT(2, "Error while starting channel measurement\n");
+-		ret = -EIO;
+-		break;
+ 	default:
+-		CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",
+-			      secm_area->response.code);
+-		ret = -EIO;
++		ret = chsc_error_from_response(secm_area->response.code);
+ 	}
++	if (ret != 0)
++		CIO_CRW_EVENT(2, "chsc: secm failed (rc=%04x)\n",
++			      secm_area->response.code);
+ 	return ret;
+ }
+ 
+@@ -860,27 +825,14 @@ int chsc_determine_channel_path_description(struct chp_id chpid,
+ 		goto out;
+ 	}
+ 
+-	switch (scpd_area->response.code) {
+-	case 0x0001: /* Success. */
++	ret = chsc_error_from_response(scpd_area->response.code);
++	if (ret == 0)
++		/* Success. */
+ 		memcpy(desc, &scpd_area->desc,
+ 		       sizeof(struct channel_path_desc));
+-		ret = 0;
+-		break;
+-	case 0x0003: /* Invalid block. */
+-	case 0x0007: /* Invalid format. */
+-	case 0x0008: /* Other invalid block. */
+-		CIO_CRW_EVENT(2, "Error in chsc request block!\n");
+-		ret = -EINVAL;
+-		break;
+-	case 0x0004: /* Command not provided in model. */
+-		CIO_CRW_EVENT(2, "Model does not provide scpd\n");
+-		ret = -EOPNOTSUPP;
+-		break;
+-	default:
+-		CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",
++	else
++		CIO_CRW_EVENT(2, "chsc: scpd failed (rc=%04x)\n",
+ 			      scpd_area->response.code);
+-		ret = -EIO;
+-	}
+ out:
+ 	free_page((unsigned long)scpd_area);
+ 	return ret;
+@@ -956,8 +908,9 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
+ 		goto out;
+ 	}
+ 
+-	switch (scmc_area->response.code) {
+-	case 0x0001: /* Success. */
++	ret = chsc_error_from_response(scmc_area->response.code);
++	if (ret == 0) {
++		/* Success. */
+ 		if (!scmc_area->not_valid) {
+ 			chp->cmg = scmc_area->cmg;
+ 			chp->shared = scmc_area->shared;
+@@ -968,22 +921,9 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
+ 			chp->cmg = -1;
+ 			chp->shared = -1;
+ 		}
+-		ret = 0;
+-		break;
+-	case 0x0003: /* Invalid block. */
+-	case 0x0007: /* Invalid format. */
+-	case 0x0008: /* Invalid bit combination. */
+-		CIO_CRW_EVENT(2, "Error in chsc request block!\n");
+-		ret = -EINVAL;
+-		break;
+-	case 0x0004: /* Command not provided. */
+-		CIO_CRW_EVENT(2, "Model does not provide scmc\n");
+-		ret = -EOPNOTSUPP;
+-		break;
+-	default:
+-		CIO_CRW_EVENT(2, "Unknown CHSC response %d\n",
++	} else {
++		CIO_CRW_EVENT(2, "chsc: scmc failed (rc=%04x)\n",
+ 			      scmc_area->response.code);
+-		ret = -EIO;
+ 	}
+ out:
+ 	free_page((unsigned long)scmc_area);
+@@ -1035,21 +975,17 @@ chsc_enable_facility(int operation_code)
+ 		ret = (ret == 3) ? -ENODEV : -EBUSY;
+ 		goto out;
+ 	}
++
+ 	switch (sda_area->response.code) {
+-	case 0x0001: /* everything ok */
+-		ret = 0;
+-		break;
+-	case 0x0003: /* invalid request block */
+-	case 0x0007:
+-		ret = -EINVAL;
+-		break;
+-	case 0x0004: /* command not provided */
+-	case 0x0101: /* facility not provided */
++	case 0x0101:
+ 		ret = -EOPNOTSUPP;
+ 		break;
+-	default: /* something went wrong */
+-		ret = -EIO;
++	default:
++		ret = chsc_error_from_response(sda_area->response.code);
+ 	}
++	if (ret != 0)
++		CIO_CRW_EVENT(2, "chsc: sda (oc=%x) failed (rc=%04x)\n",
++			      operation_code, sda_area->response.code);
+  out:
+ 	free_page((unsigned long)sda_area);
+ 	return ret;
+@@ -1074,33 +1010,27 @@ chsc_determine_css_characteristics(void)
+ 	} __attribute__ ((packed)) *scsc_area;
  
  	scsc_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
- 	if (!scsc_area) {
+-	if (!scsc_area) {
 -		CIO_MSG_EVENT(0, "Was not able to determine available"
-+		CIO_MSG_EVENT(0, "Was not able to determine available "
- 			      "CHSCs due to no memory.\n");
+-			      "CHSCs due to no memory.\n");
++	if (!scsc_area)
  		return -ENOMEM;
+-	}
+ 
+ 	scsc_area->request.length = 0x0010;
+ 	scsc_area->request.code = 0x0010;
+ 
+ 	result = chsc(scsc_area);
+ 	if (result) {
+-		CIO_MSG_EVENT(0, "Was not able to determine available CHSCs, "
+-			      "cc=%i.\n", result);
+-		result = -EIO;
++		result = (result == 3) ? -ENODEV : -EBUSY;
+ 		goto exit;
  	}
+ 
+-	if (scsc_area->response.code != 1) {
+-		CIO_MSG_EVENT(0, "Was not able to determine "
+-			      "available CHSCs.\n");
+-		result = -EIO;
+-		goto exit;
+-	}
+-	memcpy(&css_general_characteristics, scsc_area->general_char,
+-	       sizeof(css_general_characteristics));
+-	memcpy(&css_chsc_characteristics, scsc_area->chsc_char,
+-	       sizeof(css_chsc_characteristics));
++	result = chsc_error_from_response(scsc_area->response.code);
++	if (result == 0) {
++		memcpy(&css_general_characteristics, scsc_area->general_char,
++		       sizeof(css_general_characteristics));
++		memcpy(&css_chsc_characteristics, scsc_area->chsc_char,
++		       sizeof(css_chsc_characteristics));
++	} else
++		CIO_CRW_EVENT(2, "chsc: scsc failed (rc=%04x)\n",
++			      scsc_area->response.code);
+ exit:
+ 	free_page ((unsigned long) scsc_area);
+ 	return result;
 diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
 index 4690534..60590a1 100644
 --- a/drivers/s390/cio/cio.c
@@ -705504,18 +765004,142 @@
 -
  EXPORT_SYMBOL_GPL(ccw_device_set_timeout);
 diff --git a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
-index 156f3f9..918b8b8 100644
+index 156f3f9..dc4d87f 100644
 --- a/drivers/s390/cio/device_id.c
 +++ b/drivers/s390/cio/device_id.c
-@@ -24,6 +24,7 @@
+@@ -24,18 +24,20 @@
  #include "css.h"
  #include "device.h"
  #include "ioasm.h"
 +#include "io_sch.h"
  
+-/*
+- * Input :
+- *   devno - device number
+- *   ps	   - pointer to sense ID data area
+- * Output : none
++/**
++ * vm_vdev_to_cu_type - Convert vm virtual device into control unit type
++ *			for certain devices.
++ * @class: virtual device class
++ * @type: virtual device type
++ *
++ * Returns control unit type if a match was made or %0xffff otherwise.
+  */
+-static void
+-VM_virtual_device_info (__u16 devno, struct senseid *ps)
++static int vm_vdev_to_cu_type(int class, int type)
+ {
+ 	static struct {
+-		int vrdcvcla, vrdcvtyp, cu_type;
++		int class, type, cu_type;
+ 	} vm_devices[] = {
+ 		{ 0x08, 0x01, 0x3480 },
+ 		{ 0x08, 0x02, 0x3430 },
+@@ -67,8 +69,26 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
+ 		{ 0x40, 0xc0, 0x5080 },
+ 		{ 0x80, 0x00, 0x3215 },
+ 	};
++	int i;
++
++	for (i = 0; i < ARRAY_SIZE(vm_devices); i++)
++		if (class == vm_devices[i].class && type == vm_devices[i].type)
++			return vm_devices[i].cu_type;
++
++	return 0xffff;
++}
++
++/**
++ * diag_get_dev_info - retrieve device information via DIAG X'210'
++ * @devno: device number
++ * @ps: pointer to sense ID data area
++ *
++ * Returns zero on success, non-zero otherwise.
++ */
++static int diag_get_dev_info(u16 devno, struct senseid *ps)
++{
+ 	struct diag210 diag_data;
+-	int ccode, i;
++	int ccode;
+ 
+ 	CIO_TRACE_EVENT (4, "VMvdinf");
+ 
+@@ -78,21 +98,21 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
+ 	};
+ 
+ 	ccode = diag210 (&diag_data);
+-	ps->reserved = 0xff;
++	if ((ccode == 0) || (ccode == 2)) {
++		ps->reserved = 0xff;
+ 
+-	/* Special case for bloody osa devices. */
+-	if (diag_data.vrdcvcla == 0x02 &&
+-	    diag_data.vrdcvtyp == 0x20) {
+-		ps->cu_type = 0x3088;
+-		ps->cu_model = 0x60;
+-		return;
+-	}
+-	for (i = 0; i < ARRAY_SIZE(vm_devices); i++)
+-		if (diag_data.vrdcvcla == vm_devices[i].vrdcvcla &&
+-		    diag_data.vrdcvtyp == vm_devices[i].vrdcvtyp) {
+-			ps->cu_type = vm_devices[i].cu_type;
+-			return;
++		/* Special case for osa devices. */
++		if (diag_data.vrdcvcla == 0x02 && diag_data.vrdcvtyp == 0x20) {
++			ps->cu_type = 0x3088;
++			ps->cu_model = 0x60;
++			return 0;
+ 		}
++		ps->cu_type = vm_vdev_to_cu_type(diag_data.vrdcvcla,
++						diag_data.vrdcvtyp);
++		if (ps->cu_type != 0xffff)
++			return 0;
++	}
++
+ 	CIO_MSG_EVENT(0, "DIAG X'210' for device %04X returned (cc = %d):"
+ 		      "vdev class : %02X, vdev type : %04X \n ...  "
+ 		      "rdev class : %02X, rdev type : %04X, "
+@@ -101,6 +121,8 @@ VM_virtual_device_info (__u16 devno, struct senseid *ps)
+ 		      diag_data.vrdcvcla, diag_data.vrdcvtyp,
+ 		      diag_data.vrdcrccl, diag_data.vrdccrty,
+ 		      diag_data.vrdccrmd);
++
++	return -ENODEV;
+ }
+ 
  /*
-  * Input :
-@@ -219,11 +220,13 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
+@@ -129,6 +151,7 @@ __ccw_device_sense_id_start(struct ccw_device *cdev)
+ 	/* Try on every path. */
+ 	ret = -ENODEV;
+ 	while (cdev->private->imask != 0) {
++		cdev->private->senseid.cu_type = 0xFFFF;
+ 		if ((sch->opm & cdev->private->imask) != 0 &&
+ 		    cdev->private->iretry > 0) {
+ 			cdev->private->iretry--;
+@@ -152,7 +175,6 @@ ccw_device_sense_id_start(struct ccw_device *cdev)
+ 	int ret;
+ 
+ 	memset (&cdev->private->senseid, 0, sizeof (struct senseid));
+-	cdev->private->senseid.cu_type = 0xFFFF;
+ 	cdev->private->imask = 0x80;
+ 	cdev->private->iretry = 5;
+ 	ret = __ccw_device_sense_id_start(cdev);
+@@ -172,13 +194,7 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
+ 
+ 	sch = to_subchannel(cdev->dev.parent);
+ 	irb = &cdev->private->irb;
+-	/* Did we get a proper answer ? */
+-	if (cdev->private->senseid.cu_type != 0xFFFF && 
+-	    cdev->private->senseid.reserved == 0xFF) {
+-		if (irb->scsw.count < sizeof (struct senseid) - 8)
+-			cdev->private->flags.esid = 1;
+-		return 0; /* Success */
+-	}
++
+ 	/* Check the error cases. */
+ 	if (irb->scsw.fctl & (SCSW_FCTL_HALT_FUNC | SCSW_FCTL_CLEAR_FUNC)) {
+ 		/* Retry Sense ID if requested. */
+@@ -219,15 +235,26 @@ ccw_device_check_sense_id(struct ccw_device *cdev)
  		return -EAGAIN;
  	}
  	if (irb->scsw.cc == 3) {
@@ -705532,6 +765156,50 @@
  				      cdev->private->dev_id.devno,
  				      sch->schid.ssid, sch->schid.sch_no);
  		return -EACCES;
+ 	}
++
++	/* Did we get a proper answer ? */
++	if (irb->scsw.cc == 0 && cdev->private->senseid.cu_type != 0xFFFF &&
++	    cdev->private->senseid.reserved == 0xFF) {
++		if (irb->scsw.count < sizeof(struct senseid) - 8)
++			cdev->private->flags.esid = 1;
++		return 0; /* Success */
++	}
++
+ 	/* Hmm, whatever happened, try again. */
+ 	CIO_MSG_EVENT(2, "SenseID : start_IO() for device %04x on "
+ 		      "subchannel 0.%x.%04x returns status %02X%02X\n",
+@@ -280,20 +307,17 @@ ccw_device_sense_id_irq(struct ccw_device *cdev, enum dev_event dev_event)
+ 			break;
+ 		/* fall through. */
+ 	default:		/* Sense ID failed. Try asking VM. */
+-		if (MACHINE_IS_VM) {
+-			VM_virtual_device_info (cdev->private->dev_id.devno,
++		if (MACHINE_IS_VM)
++			ret = diag_get_dev_info(cdev->private->dev_id.devno,
+ 						&cdev->private->senseid);
+-			if (cdev->private->senseid.cu_type != 0xFFFF) {
+-				/* Got the device information from VM. */
+-				ccw_device_sense_id_done(cdev, 0);
+-				return;
+-			}
+-		}
+-		/*
+-		 * If we can't couldn't identify the device type we
+-		 *  consider the device "not operational".
+-		 */
+-		ccw_device_sense_id_done(cdev, -ENODEV);
++		else
++			/*
++			 * If we can't couldn't identify the device type we
++			 *  consider the device "not operational".
++			 */
++			ret = -ENODEV;
++
++		ccw_device_sense_id_done(cdev, ret);
+ 		break;
+ 	}
+ }
 diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
 index 7fd2dad..49b58eb 100644
 --- a/drivers/s390/cio/device_ops.c
@@ -706985,6 +766653,18 @@
  
  	do {
  		done = 1;
+diff --git a/drivers/scsi/NCR53C9x.h b/drivers/scsi/NCR53C9x.h
+index d85cb73..00a0ba0 100644
+--- a/drivers/scsi/NCR53C9x.h
++++ b/drivers/scsi/NCR53C9x.h
+@@ -1,6 +1,6 @@
+ /* NCR53C9x.c:  Defines and structures for the NCR53C9x generic driver.
+  *
+- * Originaly esp.h:  Defines and structures for the Sparc ESP 
++ * Originally esp.h:  Defines and structures for the Sparc ESP 
+  *                   (Enhanced SCSI Processor) driver under Linux.
+  *
+  * Copyright (C) 1995 David S. Miller (davem at caip.rutgers.edu)
 diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
 index 137d065..6961f78 100644
 --- a/drivers/scsi/NCR53c406a.c
@@ -710233,7 +769913,7 @@
  		} else {
  			unsigned long flagv;
 diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
-index 9dd331b..0e8267c 100644
+index 9dd331b..fb08861 100644
 --- a/drivers/scsi/aacraid/linit.c
 +++ b/drivers/scsi/aacraid/linit.c
 @@ -159,27 +159,27 @@ static struct pci_device_id aac_pci_tbl[] = {
@@ -710413,7 +770093,17 @@
  				++num_one;
  		}
  		if (num_lsu == 0)
-@@ -481,9 +495,35 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
+@@ -435,9 +449,6 @@ static int aac_slave_configure(struct scsi_device *sdev)
+ 		else if (depth < 2)
+ 			depth = 2;
+ 		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth);
+-		if (!(((struct aac_dev *)host->hostdata)->adapter_info.options &
+-				AAC_OPT_NEW_COMM))
+-			blk_queue_max_segment_size(sdev->request_queue, 65536);
+ 	} else
+ 		scsi_adjust_queue_depth(sdev, 0, 1);
+ 
+@@ -481,9 +492,35 @@ static int aac_change_queue_depth(struct scsi_device *sdev, int depth)
  	return sdev->queue_depth;
  }
  
@@ -710449,7 +770139,7 @@
  	return aac_do_ioctl(dev, cmd, arg);
  }
  
-@@ -506,17 +546,33 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
+@@ -506,17 +543,33 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
  			break;
  	case INQUIRY:
  	case READ_CAPACITY:
@@ -710484,7 +770174,7 @@
  	}
  	return ret;
  }
-@@ -539,12 +595,13 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
+@@ -539,12 +592,13 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
  	for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) {
  		struct fib * fib = &aac->fibs[count];
  		if (fib->hw_fib_va->header.XferState &&
@@ -710499,7 +770189,7 @@
  					AAC_DRIVERNAME);
  
  	if ((count = aac_check_health(aac)))
-@@ -584,8 +641,11 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
+@@ -584,8 +638,11 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
  	 * support a register, instead of a commanded, reset.
  	 */
  	if ((aac->supplement_adapter_info.SupportedOptions2 &
@@ -710513,7 +770203,7 @@
  		aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */
  	return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */
  }
-@@ -632,8 +692,8 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
+@@ -632,8 +689,8 @@ static int aac_cfg_open(struct inode *inode, struct file *file)
   *	Bugs: Needs locking against parallel ioctls lower down
   *	Bugs: Needs to handle hot plugging
   */
@@ -710524,7 +770214,7 @@
  		unsigned int cmd, unsigned long arg)
  {
  	if (!capable(CAP_SYS_RAWIO))
-@@ -646,7 +706,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
+@@ -646,7 +703,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
  {
  	long ret;
  	lock_kernel();
@@ -710533,7 +770223,7 @@
  	case FSACTL_MINIPORT_REV_CHECK:
  	case FSACTL_SENDFIB:
  	case FSACTL_OPEN_GET_ADAPTER_FIB:
-@@ -656,14 +716,14 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
+@@ -656,14 +713,14 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
  	case FSACTL_QUERY_DISK:
  	case FSACTL_DELETE_DISK:
  	case FSACTL_FORCE_DELETE_DISK:
@@ -710550,7 +770240,7 @@
  		f = compat_alloc_user_space(sizeof(*f));
  		ret = 0;
  		if (clear_user(f, sizeof(*f)))
-@@ -676,9 +736,9 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
+@@ -676,9 +733,9 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
  	}
  
  	default:
@@ -710562,7 +770252,7 @@
  	unlock_kernel();
  	return ret;
  }
-@@ -735,6 +795,25 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
+@@ -735,6 +792,25 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
  	return len;
  }
  
@@ -710588,7 +770278,7 @@
  static ssize_t aac_show_kernel_version(struct class_device *class_dev,
  		char *buf)
  {
-@@ -742,7 +821,7 @@ static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+@@ -742,7 +818,7 @@ static ssize_t aac_show_kernel_version(struct class_device *class_dev,
  	int len, tmp;
  
  	tmp = le32_to_cpu(dev->adapter_info.kernelrev);
@@ -710597,7 +770287,7 @@
  	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
  	  le32_to_cpu(dev->adapter_info.kernelbuild));
  	return len;
-@@ -755,7 +834,7 @@ static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+@@ -755,7 +831,7 @@ static ssize_t aac_show_monitor_version(struct class_device *class_dev,
  	int len, tmp;
  
  	tmp = le32_to_cpu(dev->adapter_info.monitorrev);
@@ -710606,7 +770296,7 @@
  	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
  	  le32_to_cpu(dev->adapter_info.monitorbuild));
  	return len;
-@@ -768,7 +847,7 @@ static ssize_t aac_show_bios_version(struct class_device *class_dev,
+@@ -768,7 +844,7 @@ static ssize_t aac_show_bios_version(struct class_device *class_dev,
  	int len, tmp;
  
  	tmp = le32_to_cpu(dev->adapter_info.biosrev);
@@ -710615,7 +770305,7 @@
  	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
  	  le32_to_cpu(dev->adapter_info.biosbuild));
  	return len;
-@@ -844,6 +923,13 @@ static struct class_device_attribute aac_vendor = {
+@@ -844,6 +920,13 @@ static struct class_device_attribute aac_vendor = {
  	},
  	.show = aac_show_vendor,
  };
@@ -710629,7 +770319,7 @@
  static struct class_device_attribute aac_kernel_version = {
  	.attr = {
  		.name = "hba_kernel_version",
-@@ -898,6 +984,7 @@ static struct class_device_attribute aac_reset = {
+@@ -898,6 +981,7 @@ static struct class_device_attribute aac_reset = {
  static struct class_device_attribute *aac_attrs[] = {
  	&aac_model,
  	&aac_vendor,
@@ -710637,7 +770327,7 @@
  	&aac_kernel_version,
  	&aac_monitor_version,
  	&aac_bios_version,
-@@ -928,23 +1015,23 @@ static struct scsi_host_template aac_driver_template = {
+@@ -928,23 +1012,23 @@ static struct scsi_host_template aac_driver_template = {
  	.compat_ioctl			= aac_compat_ioctl,
  #endif
  	.queuecommand   		= aac_queuecommand,
@@ -710667,7 +770357,7 @@
  	.emulated                       = 1,
  };
  
-@@ -979,18 +1066,18 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
+@@ -979,18 +1063,18 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
  		goto out;
  	error = -ENODEV;
  
@@ -710689,7 +770379,7 @@
  	pci_set_master(pdev);
  
  	shost = scsi_host_alloc(&aac_driver_template, sizeof(struct aac_dev));
-@@ -1003,7 +1090,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
+@@ -1003,7 +1087,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
  	shost->max_cmd_len = 16;
  
  	aac = (struct aac_dev *)shost->hostdata;
@@ -710698,7 +770388,7 @@
  	aac->pdev = pdev;
  	aac->name = aac_driver_template.name;
  	aac->id = shost->unique_id;
-@@ -1040,7 +1127,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
+@@ -1040,16 +1124,22 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
  	if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
  		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
  			goto out_deinit;
@@ -710707,7 +770397,14 @@
  	aac->maximum_num_channels = aac_drivers[index].channels;
  	error = aac_get_adapter_info(aac);
  	if (error < 0)
-@@ -1049,7 +1136,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
+ 		goto out_deinit;
+ 
++	if (!(aac->adapter_info.options & AAC_OPT_NEW_COMM)) {
++		error = pci_set_dma_max_seg_size(pdev, 65536);
++		if (error)
++			goto out_deinit;
++	}
++
  	/*
   	 * Lets override negotiations and drop the maximum SG limit to 34
   	 */
@@ -710716,7 +770413,7 @@
  			(aac->scsi_host_ptr->sg_tablesize > 34)) {
   		aac->scsi_host_ptr->sg_tablesize = 34;
   		aac->scsi_host_ptr->max_sectors
-@@ -1066,17 +1153,17 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
+@@ -1066,17 +1156,17 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
  	/*
  	 * Firware printf works only with older firmware.
  	 */
@@ -710737,7 +770434,7 @@
  		shost->max_channel = aac->maximum_num_channels;
  	else
  		shost->max_channel = 0;
-@@ -1148,10 +1235,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
+@@ -1148,10 +1238,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
  	kfree(aac->queues);
  
  	aac_adapter_ioremap(aac, 0);
@@ -710750,7 +770447,7 @@
  	list_del(&aac->entry);
  	scsi_host_put(shost);
  	pci_disable_device(pdev);
-@@ -1172,7 +1259,7 @@ static struct pci_driver aac_pci_driver = {
+@@ -1172,7 +1262,7 @@ static struct pci_driver aac_pci_driver = {
  static int __init aac_init(void)
  {
  	int error;
@@ -710925,9 +770622,18 @@
  				DO_UNLOCK(flags);
  				aha152x_internal_queue(ptr, NULL, check_condition, ptr->scsi_done);
 diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
-index bbcc2c5..190568e 100644
+index bbcc2c5..5a1471c 100644
 --- a/drivers/scsi/aha1542.c
 +++ b/drivers/scsi/aha1542.c
+@@ -21,7 +21,7 @@
+  *  Modified by Chris Faulhaber <jedgar at fxp.org>
+  *        Added module command-line options
+  *        19-Jul-99
+- *  Modified by Adam Fritzler <mid at auk.cx>
++ *  Modified by Adam Fritzler
+  *        Added proper detection of the AHA-1640 (MCA version of AHA-1540)
+  */
+ 
 @@ -51,15 +51,6 @@
  #define SCSI_BUF_PA(address)	isa_virt_to_bus(address)
  #define SCSI_SG_PA(sgent)	(isa_page_to_bus(sg_page((sgent))) + (sgent)->offset)
@@ -711057,7 +770763,7 @@
  };
  
 diff --git a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile
-index 9a6ce19..e4f70c5 100644
+index 9a6ce19..4c54954 100644
 --- a/drivers/scsi/aic7xxx/Makefile
 +++ b/drivers/scsi/aic7xxx/Makefile
 @@ -33,11 +33,10 @@ aic79xx-y					+= aic79xx_osm.o	\
@@ -711074,20 +770780,19 @@
  
  # Files generated that shall be removed upon make clean
  clean-files := aic7xxx_seq.h aic7xxx_reg.h aic7xxx_reg_print.c
-@@ -46,53 +45,45 @@ clean-files += aic79xx_seq.h aic79xx_reg.h aic79xx_reg_print.c
+@@ -45,54 +44,41 @@ clean-files += aic79xx_seq.h aic79xx_reg.h aic79xx_reg_print.c
+ 
  # Dependencies for generated files need to be listed explicitly
  
- $(obj)/aic7xxx_core.o: $(obj)/aic7xxx_seq.h
-+$(obj)/aic7xxx_core.o: $(obj)/aic7xxx_reg.h
- $(obj)/aic79xx_core.o: $(obj)/aic79xx_seq.h
+-$(obj)/aic7xxx_core.o: $(obj)/aic7xxx_seq.h
+-$(obj)/aic79xx_core.o: $(obj)/aic79xx_seq.h
 -$(obj)/aic79xx_reg_print.c: $(src)/aic79xx_reg_print.c_shipped
 -$(obj)/aic7xxx_reg_print.c: $(src)/aic7xxx_reg_print.c_shipped
-+$(obj)/aic79xx_core.o: $(obj)/aic79xx_reg.h
- 
+-
 -$(addprefix $(obj)/,$(aic7xxx-y)): $(obj)/aic7xxx_reg.h
 -$(addprefix $(obj)/,$(aic79xx-y)): $(obj)/aic79xx_reg.h
-+$(addprefix $(obj)/,$(aic7xxx-y)): $(obj)/aic7xxx_seq.h
-+$(addprefix $(obj)/,$(aic79xx-y)): $(obj)/aic79xx_seq.h
++$(addprefix $(src)/,$(aic7xxx-y:.o=.c)): $(obj)/aic7xxx_seq.h $(obj)/aic7xxx_reg.h
++$(addprefix $(src)/,$(aic79xx-y:.o=.c)): $(obj)/aic79xx_seq.h $(obj)/aic79xx_reg.h
  
 -aic7xxx-gen-$(CONFIG_AIC7XXX_BUILD_FIRMWARE)	:= $(obj)/aic7xxx_seq.h \
 -						   $(obj)/aic7xxx_reg.h
@@ -711198,10 +770903,32 @@
  
  /************************** Busy Target Table *********************************/
  /*
+diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
+index 2ceb67f..45e5557 100644
+--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
++++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
+@@ -417,7 +417,7 @@ ahd_targetcmd_offset(struct ahd_softc *ahd, u_int index)
+ 	       - (uint8_t *)ahd->qoutfifo);
+ }
+ 
+-/*********************** Miscelaneous Support Functions ***********************/
++/*********************** Miscellaneous Support Functions ***********************/
+ static __inline struct ahd_initiator_tinfo *
+ 			ahd_fetch_transinfo(struct ahd_softc *ahd,
+ 					    char channel, u_int our_id,
 diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
-index 2d02040..0146547 100644
+index 2d02040..72fccd9 100644
 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c
 +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
+@@ -325,7 +325,7 @@ MODULE_PARM_DESC(aic79xx,
+ "	verbose			Enable verbose/diagnostic logging\n"
+ "	allow_memio		Allow device registers to be memory mapped\n"
+ "	debug			Bitmask of debug values to enable\n"
+-"	no_reset		Supress initial bus resets\n"
++"	no_reset		Suppress initial bus resets\n"
+ "	extended		Enable extended geometry on all controllers\n"
+ "	periodic_otag		Send an ordered tagged transaction\n"
+ "				periodically to prevent tag starvation.\n"
 @@ -766,7 +766,6 @@ struct scsi_host_template aic79xx_driver_template = {
  	.max_sectors		= 8192,
  	.cmd_per_lun		= 2,
@@ -711309,7 +771036,7 @@
  ahd_linux_pci_init(void)
  {
 diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
-index 7a203a9..df85367 100644
+index 7a203a9..c9f79fd 100644
 --- a/drivers/scsi/aic7xxx/aic79xx_pci.c
 +++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
 @@ -389,6 +389,7 @@ ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry)
@@ -711328,6 +771055,24 @@
  
  /*
   * Perform some simple tests that should catch situations where
+@@ -977,7 +979,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd)
+ 			  |  AHD_FAINT_LED_BUG;
+ 
+ 		/*
+-		 * IO Cell paramter setup.
++		 * IO Cell parameter setup.
+ 		 */
+ 		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
+ 
+@@ -1004,7 +1006,7 @@ ahd_aic790X_setup(struct ahd_softc *ahd)
+ 			ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;
+ 
+ 		/*
+-		 * IO Cell paramter setup.
++		 * IO Cell parameter setup.
+ 		 */
+ 		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
+ 		AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
 diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
 index 3d4e42d..c0344e6 100644
 --- a/drivers/scsi/aic7xxx/aic7xxx.h
@@ -711374,10 +771119,32 @@
  /************************** Busy Target Table *********************************/
  /*
   * Return the untagged transaction id for a given target/channel lun.
+diff --git a/drivers/scsi/aic7xxx/aic7xxx_inline.h b/drivers/scsi/aic7xxx/aic7xxx_inline.h
+index 8e1954c..cba2f23 100644
+--- a/drivers/scsi/aic7xxx/aic7xxx_inline.h
++++ b/drivers/scsi/aic7xxx/aic7xxx_inline.h
+@@ -229,7 +229,7 @@ ahc_name(struct ahc_softc *ahc)
+ 	return (ahc->name);
+ }
+ 
+-/*********************** Miscelaneous Support Functions ***********************/
++/*********************** Miscellaneous Support Functions ***********************/
+ 
+ static __inline void	ahc_update_residual(struct ahc_softc *ahc,
+ 					    struct scb *scb);
 diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
-index 390b0fc..99a3b33 100644
+index 390b0fc..282aff6 100644
 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
 +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
+@@ -347,7 +347,7 @@ MODULE_PARM_DESC(aic7xxx,
+ "	debug			Bitmask of debug values to enable\n"
+ "	no_probe		Toggle EISA/VLB controller probing\n"
+ "	probe_eisa_vl		Toggle EISA/VLB controller probing\n"
+-"	no_reset		Supress initial bus resets\n"
++"	no_reset		Suppress initial bus resets\n"
+ "	extended		Enable extended geometry on all controllers\n"
+ "	periodic_otag		Send an ordered tagged transaction\n"
+ "				periodically to prevent tag starvation.\n"
 @@ -747,7 +747,6 @@ struct scsi_host_template aic7xxx_driver_template = {
  	.max_sectors		= 8192,
  	.cmd_per_lun		= 2,
@@ -715264,7 +775031,7 @@
  
  	spin_lock_irqsave(&target->lock, flags);
 diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
-index 9706de9..6c4f0f0 100644
+index 9706de9..68e5c63 100644
 --- a/drivers/scsi/ide-scsi.c
 +++ b/drivers/scsi/ide-scsi.c
 @@ -1,7 +1,6 @@
@@ -715277,6 +775044,15 @@
   */
  
  /*
+@@ -288,7 +287,7 @@ static int idescsi_end_request(ide_drive_t *, int, int);
+ static ide_startstop_t
+ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
+ {
+-	if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
++	if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ 		/* force an abort */
+ 		HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
+ 
 @@ -395,14 +394,12 @@ static int idescsi_expiry(ide_drive_t *drive)
  static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
  {
@@ -715303,7 +775079,7 @@
 -	feature.all = 0;
  	/* Clear the interrupt */
 -	status.all = HWIF(drive)->INB(IDE_STATUS_REG);
-+	stat = drive->hwif->INB(IDE_STATUS_REG);
++	stat = ide_read_status(drive);
  
 -	if (!status.b.drq) {
 +	if ((stat & DRQ_STAT) == 0) {
@@ -715542,7 +775318,7 @@
  
  static int initio_probe_one(struct pci_dev *pdev,
 diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
-index 0841df0..73270ff 100644
+index 0841df0..2074701 100644
 --- a/drivers/scsi/ipr.c
 +++ b/drivers/scsi/ipr.c
 @@ -84,7 +84,7 @@
@@ -715587,8 +775363,17 @@
  		regs->flags |= IPR_ATA_FLAG_PACKET_CMD;
  		regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA;
  		break;
+@@ -7052,7 +7053,7 @@ static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev,
+  * where it can accept new commands.
+ 
+  * Return value:
+- * 	0 on sucess / -EIO on failure
++ * 	0 on success / -EIO on failure
+  **/
+ static int __devinit ipr_probe_ioa_part2(struct ipr_ioa_cfg *ioa_cfg)
+ {
 diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
-index 5c5a9b2..7505cca 100644
+index 5c5a9b2..bb152fb 100644
 --- a/drivers/scsi/ips.c
 +++ b/drivers/scsi/ips.c
 @@ -389,17 +389,17 @@ static struct  pci_device_id  ips_pci_table[] = {
@@ -715635,6 +775420,15 @@
  
  	scsi_host_put(sh);
  
+@@ -1313,7 +1309,7 @@ ips_intr_copperhead(ips_ha_t * ha)
+ 			cstatus.value = (*ha->func.statupd) (ha);
+ 
+ 		if (cstatus.fields.command_id > (IPS_MAX_CMDS - 1)) {
+-			/* Spurious Interupt ? */
++			/* Spurious Interrupt ? */
+ 			continue;
+ 		}
+ 
 @@ -1637,7 +1633,7 @@ ips_make_passthru(ips_ha_t *ha, struct scsi_cmnd *SC, ips_scb_t *scb, int intr)
  				return (IPS_FAILURE);
  			}
@@ -721814,7 +781608,7 @@
  	err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun,
  				     cmd->tag);
 diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
-index ba3ecab..f26b953 100644
+index ba3ecab..83567b9 100644
 --- a/drivers/scsi/lpfc/lpfc.h
 +++ b/drivers/scsi/lpfc/lpfc.h
 @@ -29,7 +29,8 @@ struct lpfc_sli2_slim;
@@ -721853,6 +781647,15 @@
  	struct list_head fc_nodes;
  
  	/* Keep counters for the number of entries in each list. */
+@@ -317,7 +325,7 @@ struct lpfc_vport {
+ 
+ #define WORKER_MBOX_TMO                0x100	/* hba: MBOX timeout */
+ #define WORKER_HB_TMO                  0x200	/* hba: Heart beat timeout */
+-#define WORKER_FABRIC_BLOCK_TMO        0x400	/* hba: fabric block timout */
++#define WORKER_FABRIC_BLOCK_TMO        0x400	/* hba: fabric block timeout */
+ #define WORKER_RAMP_DOWN_QUEUE         0x800	/* hba: Decrease Q depth */
+ #define WORKER_RAMP_UP_QUEUE           0x1000	/* hba: Increase Q depth */
+ 
 @@ -344,6 +352,7 @@ struct lpfc_vport {
  	uint32_t cfg_discovery_threads;
  	uint32_t cfg_log_verbose;
@@ -725770,7 +785573,7 @@
  		return 1;
  	else
 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
-index ecebdfa..29b4cf9 100644
+index ecebdfa..6cfeba7 100644
 --- a/drivers/scsi/lpfc/lpfc_init.c
 +++ b/drivers/scsi/lpfc/lpfc_init.c
 @@ -212,6 +212,18 @@ out_free_mbox:
@@ -726403,7 +786206,7 @@
 +	int bars = pci_select_bars(pdev, IORESOURCE_MEM);
  
 -	if (pci_enable_device(pdev))
-+	if (pci_enable_device_bars(pdev, bars))
++	if (pci_enable_device_mem(pdev))
  		goto out;
 -	if (pci_request_regions(pdev, LPFC_DRIVER_NAME))
 +	if (pci_request_selected_regions(pdev, bars, LPFC_DRIVER_NAME))
@@ -726589,7 +786392,7 @@
  #define LOG_SLI                       0x800	/* SLI events */
  #define LOG_FCP_ERROR                 0x1000	/* log errors, not underruns */
 diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
-index a592733..dfc63f6 100644
+index a592733..7a9be4c 100644
 --- a/drivers/scsi/lpfc/lpfc_mbox.c
 +++ b/drivers/scsi/lpfc/lpfc_mbox.c
 @@ -82,6 +82,24 @@ lpfc_read_nv(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
@@ -726643,6 +786446,15 @@
  		kfree(mp);
  		mb->mbxCommand = MBX_REG_LOGIN64;
  		/* REG_LOGIN: no buffers */
+@@ -858,7 +880,7 @@ lpfc_mbox_get(struct lpfc_hba * phba)
+ void
+ lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
+ {
+-	/* This function expects to be called from interupt context */
++	/* This function expects to be called from interrupt context */
+ 	spin_lock(&phba->hbalock);
+ 	list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl);
+ 	spin_unlock(&phba->hbalock);
 @@ -874,7 +896,7 @@ lpfc_mbox_tmo_val(struct lpfc_hba *phba, int cmd)
  	case MBX_DOWN_LOAD:	/* 0x1C */
  	case MBX_DEL_LD_ENTRY:	/* 0x1D */
@@ -728361,7 +788173,7 @@
  {
  	struct Scsi_Host *host = pci_get_drvdata(pdev);
 diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
-index c892310..6db77c0 100644
+index c892310..9f04192 100644
 --- a/drivers/scsi/megaraid/megaraid_mbox.c
 +++ b/drivers/scsi/megaraid/megaraid_mbox.c
 @@ -300,7 +300,7 @@ static struct pci_device_id pci_id_table_g[] =  {
@@ -728399,6 +788211,48 @@
  
  	return;
  }
+@@ -3465,12 +3464,12 @@ megaraid_mbox_setup_device_map(adapter_t *adapter)
+ /*
+  * START: Interface for the common management module
+  *
+- * This is the module, which interfaces with the common mangement module to
++ * This is the module, which interfaces with the common management module to
+  * provide support for ioctl and sysfs
+  */
+ 
+ /**
+- * megaraid_cmm_register - register with the mangement module
++ * megaraid_cmm_register - register with the management module
+  * @adapter		: HBA soft state
+  *
+  * Register with the management module, which allows applications to issue
+@@ -3558,7 +3557,7 @@ megaraid_cmm_register(adapter_t *adapter)
+ 
+ 
+ /**
+- * megaraid_cmm_unregister - un-register with the mangement module
++ * megaraid_cmm_unregister - un-register with the management module
+  * @adapter		: HBA soft state
+  *
+  * Un-register with the management module.
+@@ -3580,7 +3579,7 @@ megaraid_cmm_unregister(adapter_t *adapter)
+  * @kioc		: CMM interface packet
+  * @action		: command action
+  *
+- * This routine is invoked whenever the Common Mangement Module (CMM) has a
++ * This routine is invoked whenever the Common Management Module (CMM) has a
+  * command for us. The 'action' parameter specifies if this is a new command
+  * or otherwise.
+  */
+@@ -3945,7 +3944,7 @@ megaraid_sysfs_get_ldmap_timeout(unsigned long data)
+  *
+  * This routine will be called whenever user reads the logical drive
+  * attributes, go get the current logical drive mapping table from the
+- * firmware. We use the managment API's to issue commands to the controller.
++ * firmware. We use the management API's to issue commands to the controller.
+  *
+  * NOTE: The commands issuance functionality is not generalized and
+  * implemented in context of "get ld map" command only. If required, the
 diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
 index e3c5c52..672c759 100644
 --- a/drivers/scsi/megaraid/megaraid_sas.c
@@ -729362,6 +789216,19 @@
  
  config PCMCIA_AHA152X
  	tristate "Adaptec AHA152X PCMCIA support"
+diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c
+index 4b82b20..d8b9935 100644
+--- a/drivers/scsi/pcmcia/fdomain_stub.c
++++ b/drivers/scsi/pcmcia/fdomain_stub.c
+@@ -130,7 +130,7 @@ static int fdomain_config(struct pcmcia_device *link)
+     cisparse_t parse;
+     int i, last_ret, last_fn;
+     u_char tuple_data[64];
+-    char str[16];
++    char str[22];
+     struct Scsi_Host *host;
+ 
+     DEBUG(0, "fdomain_config(0x%p)\n", link);
 diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
 index a45d89b..5082ca3 100644
 --- a/drivers/scsi/pcmcia/nsp_cs.c
@@ -731509,6 +791376,19 @@
 +extern int qla2x00_dfs_setup(scsi_qla_host_t *);
 +extern int qla2x00_dfs_remove(scsi_qla_host_t *);
  #endif /* _QLA_GBL_H */
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index eb0784c..6226d88 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -1094,7 +1094,7 @@ qla2x00_sns_rnn_id(scsi_qla_host_t *ha)
+ }
+ 
+ /**
+- * qla2x00_mgmt_svr_login() - Login to fabric Managment Service.
++ * qla2x00_mgmt_svr_login() - Login to fabric Management Service.
+  * @ha: HA context
+  *
+  * Returns 0 on success.
 diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
 index 191dafd..d0633ca 100644
 --- a/drivers/scsi/qla2xxx/qla_init.c
@@ -733087,8 +792967,21 @@
  
  #define QLA_DRIVER_MAJOR_VER	8
  #define QLA_DRIVER_MINOR_VER	2
+diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
+index accaf69..d6be076 100644
+--- a/drivers/scsi/qla4xxx/ql4_def.h
++++ b/drivers/scsi/qla4xxx/ql4_def.h
+@@ -121,7 +121,7 @@
+ #define MAX_REQS_SERVICED_PER_INTR	16
+ 
+ #define ISCSI_IPADDR_SIZE		4	/* IP address size */
+-#define ISCSI_ALIAS_SIZE		32	/* ISCSI Alais name size */
++#define ISCSI_ALIAS_SIZE		32	/* ISCSI Alias name size */
+ #define ISCSI_NAME_SIZE			0xE0	/* ISCSI Name size */
+ 
+ #define LSDW(x) ((u32)((u64)(x)))
 diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
-index d692c71..cbe0a17 100644
+index d692c71..49925f9 100644
 --- a/drivers/scsi/qla4xxx/ql4_init.c
 +++ b/drivers/scsi/qla4xxx/ql4_init.c
 @@ -5,6 +5,7 @@
@@ -733099,6 +792992,15 @@
  #include "ql4_def.h"
  #include "ql4_glbl.h"
  #include "ql4_dbg.h"
+@@ -1097,7 +1098,7 @@ static int qla4xxx_start_firmware(struct scsi_qla_host *ha)
+ 		}
+ 		config_chip = 1;
+ 
+-		/* Reset clears the semaphore, so aquire again */
++		/* Reset clears the semaphore, so acquire again */
+ 		if (ql4xxx_lock_drvr_wait(ha) != QLA_SUCCESS)
+ 			return QLA_ERROR;
+ 	}
 @@ -1305,7 +1306,8 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
  		atomic_set(&ddb_entry->relogin_timer, 0);
  		clear_bit(DF_RELOGIN, &ddb_entry->flags);
@@ -734818,7 +794720,7 @@
  			return -ENODEV;
  	} else if (!scsi_block_when_processing_errors(sdev))
 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
-index a9ac5b1..b12fb31 100644
+index a9ac5b1..f243fc3 100644
 --- a/drivers/scsi/scsi_lib.c
 +++ b/drivers/scsi/scsi_lib.c
 @@ -8,6 +8,7 @@
@@ -735062,33 +794964,29 @@
 -			index = scsi_sgtable_index(this);
 -
 -		left -= this;
- 
+-
 -		sgp = scsi_sg_pools + index;
-+	sgp = scsi_sg_pools + scsi_sgtable_index(nents);
-+	mempool_free(sgl, sgp->pool);
-+}
  
 -		sgl = mempool_alloc(sgp->pool, gfp_mask);
 -		if (unlikely(!sgl))
 -			goto enomem;
++	sgp = scsi_sg_pools + scsi_sgtable_index(nents);
++	mempool_free(sgl, sgp->pool);
++}
+ 
+-		sg_init_table(sgl, sgp->size);
 +static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask)
 +{
 +	struct scsi_host_sg_pool *sgp;
  
--		sg_init_table(sgl, sgp->size);
-+	sgp = scsi_sg_pools + scsi_sgtable_index(nents);
-+	return mempool_alloc(sgp->pool, gfp_mask);
-+}
- 
 -		/*
 -		 * first loop through, set initial index and return value
 -		 */
 -		if (!ret)
 -			ret = sgl;
-+static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
-+			      gfp_t gfp_mask)
-+{
-+	int ret;
++	sgp = scsi_sg_pools + scsi_sgtable_index(nents);
++	return mempool_alloc(sgp->pool, gfp_mask);
++}
  
 -		/*
 -		 * chain previous sglist, if any. we know the previous
@@ -735097,7 +794995,10 @@
 -		 */
 -		if (prev)
 -			sg_chain(prev, SCSI_MAX_SG_SEGMENTS, sgl);
-+	BUG_ON(!nents);
++static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents,
++			      gfp_t gfp_mask)
++{
++	int ret;
  
 -		/*
 -		 * if we have nothing left, mark the last segment as
@@ -735105,7 +795006,8 @@
 -		 */
 -		if (!left)
 -			sg_mark_end(&sgl[this - 1]);
--
++	BUG_ON(!nents);
+ 
 -		/*
 -		 * don't allow subsequent mempool allocs to sleep, it would
 -		 * violate the mempool principle.
@@ -735208,7 +795110,9 @@
   */
 -static void scsi_release_buffers(struct scsi_cmnd *cmd)
 +void scsi_release_buffers(struct scsi_cmnd *cmd)
-+{
+ {
+-	if (cmd->use_sg)
+-		scsi_free_sgtable(cmd);
 +	if (cmd->sdb.table.nents)
 +		scsi_free_sgtable(&cmd->sdb);
 +
@@ -735232,9 +795136,7 @@
 + * decide what to do with this information.
 + */
 +void scsi_end_bidi_request(struct scsi_cmnd *cmd)
- {
--	if (cmd->use_sg)
--		scsi_free_sgtable(cmd);
++{
 +	struct request *req = cmd->request;
 +	unsigned int dlen = req->data_len;
 +	unsigned int next_dlen = req->next_rq->data_len;
@@ -735505,7 +795407,15 @@
  			if (scsi_target(sdev)->starget_sdev_user &&
  			    scsi_target(sdev)->starget_sdev_user != sdev)
  				goto not_ready;
-@@ -1654,20 +1578,7 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
+@@ -1645,6 +1569,7 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
+ 					 request_fn_proc *request_fn)
+ {
+ 	struct request_queue *q;
++	struct device *dev = shost->shost_gendev.parent;
+ 
+ 	q = blk_init_queue(request_fn, NULL);
+ 	if (!q)
+@@ -1654,27 +1579,25 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
  	 * this limit is imposed by hardware restrictions
  	 */
  	blk_queue_max_hw_segments(q, shost->sg_tablesize);
@@ -735527,7 +795437,10 @@
  
  	blk_queue_max_sectors(q, shost->max_sectors);
  	blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
-@@ -1675,6 +1586,14 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
+ 	blk_queue_segment_boundary(q, shost->dma_boundary);
++	dma_set_seg_boundary(dev, shost->dma_boundary);
++
++	blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
  
  	if (!shost->use_clustering)
  		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
@@ -735542,7 +795455,7 @@
  	return q;
  }
  EXPORT_SYMBOL(__scsi_alloc_queue);
-@@ -1758,6 +1677,14 @@ int __init scsi_init_queue(void)
+@@ -1758,6 +1681,14 @@ int __init scsi_init_queue(void)
  		return -ENOMEM;
  	}
  
@@ -735557,7 +795470,7 @@
  	for (i = 0; i < SG_MEMPOOL_NR; i++) {
  		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
  		int size = sgp->size * sizeof(struct scatterlist);
-@@ -1767,6 +1694,7 @@ int __init scsi_init_queue(void)
+@@ -1767,6 +1698,7 @@ int __init scsi_init_queue(void)
  		if (!sgp->slab) {
  			printk(KERN_ERR "SCSI: can't init sg slab %s\n",
  					sgp->name);
@@ -735565,7 +795478,7 @@
  		}
  
  		sgp->pool = mempool_create_slab_pool(SG_MEMPOOL_SIZE,
-@@ -1774,10 +1702,25 @@ int __init scsi_init_queue(void)
+@@ -1774,10 +1706,25 @@ int __init scsi_init_queue(void)
  		if (!sgp->pool) {
  			printk(KERN_ERR "SCSI: can't init sg mempool %s\n",
  					sgp->name);
@@ -735591,7 +795504,7 @@
  }
  
  void scsi_exit_queue(void)
-@@ -1785,6 +1728,7 @@ void scsi_exit_queue(void)
+@@ -1785,6 +1732,7 @@ void scsi_exit_queue(void)
  	int i;
  
  	kmem_cache_destroy(scsi_io_context_cache);
@@ -735599,7 +795512,7 @@
  
  	for (i = 0; i < SG_MEMPOOL_NR; i++) {
  		struct scsi_host_sg_pool *sgp = scsi_sg_pools + i;
-@@ -1804,7 +1748,7 @@ void scsi_exit_queue(void)
+@@ -1804,7 +1752,7 @@ void scsi_exit_queue(void)
   *	@timeout: command timeout
   *	@retries: number of retries before failing
   *	@data: returns a structure abstracting the mode header data
@@ -735608,7 +795521,7 @@
   *		must be SCSI_SENSE_BUFFERSIZE big.
   *
   *	Returns zero if successful; negative error number or scsi
-@@ -1871,8 +1815,7 @@ scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage,
+@@ -1871,8 +1819,7 @@ scsi_mode_select(struct scsi_device *sdev, int pf, int sp, int modepage,
  EXPORT_SYMBOL_GPL(scsi_mode_select);
  
  /**
@@ -735618,7 +795531,7 @@
   *	@sdev:	SCSI device to be queried
   *	@dbd:	set if mode sense will allow block descriptors to be returned
   *	@modepage: mode page being requested
-@@ -1881,13 +1824,13 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
+@@ -1881,13 +1828,13 @@ EXPORT_SYMBOL_GPL(scsi_mode_select);
   *	@timeout: command timeout
   *	@retries: number of retries before failing
   *	@data: returns a structure abstracting the mode header data
@@ -735634,7 +795547,7 @@
  int
  scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
  		  unsigned char *buffer, int len, int timeout, int retries,
-@@ -1981,40 +1924,69 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+@@ -1981,40 +1928,69 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
  }
  EXPORT_SYMBOL(scsi_mode_sense);
  
@@ -735715,7 +795628,7 @@
  int
  scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
  {
-@@ -2264,7 +2236,7 @@ EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
+@@ -2264,7 +2240,7 @@ EXPORT_SYMBOL_GPL(sdev_evt_send_simple);
   *	Must be called with user context, may sleep.
   *
   *	Returns zero if unsuccessful or an error if not.
@@ -735724,7 +795637,7 @@
  int
  scsi_device_quiesce(struct scsi_device *sdev)
  {
-@@ -2289,7 +2261,7 @@ EXPORT_SYMBOL(scsi_device_quiesce);
+@@ -2289,7 +2265,7 @@ EXPORT_SYMBOL(scsi_device_quiesce);
   *	queues.
   *
   *	Must be called with user context, may sleep.
@@ -735733,7 +795646,7 @@
  void
  scsi_device_resume(struct scsi_device *sdev)
  {
-@@ -2326,8 +2298,7 @@ scsi_target_resume(struct scsi_target *starget)
+@@ -2326,8 +2302,7 @@ scsi_target_resume(struct scsi_target *starget)
  EXPORT_SYMBOL(scsi_target_resume);
  
  /**
@@ -735743,7 +795656,7 @@
   * @sdev:	device to block
   *
   * Block request made by scsi lld's to temporarily stop all
-@@ -2342,7 +2313,7 @@ EXPORT_SYMBOL(scsi_target_resume);
+@@ -2342,7 +2317,7 @@ EXPORT_SYMBOL(scsi_target_resume);
   *	state, all commands are deferred until the scsi lld reenables
   *	the device with scsi_device_unblock or device_block_tmo fires.
   *	This routine assumes the host_lock is held on entry.
@@ -735752,7 +795665,7 @@
  int
  scsi_internal_device_block(struct scsi_device *sdev)
  {
-@@ -2382,7 +2353,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+@@ -2382,7 +2357,7 @@ EXPORT_SYMBOL_GPL(scsi_internal_device_block);
   *	(which must be a legal transition) allowing the midlayer to
   *	goose the queue for this device.  This routine assumes the 
   *	host_lock is held upon entry.
@@ -735761,7 +795674,7 @@
  int
  scsi_internal_device_unblock(struct scsi_device *sdev)
  {
-@@ -2460,7 +2431,7 @@ EXPORT_SYMBOL_GPL(scsi_target_unblock);
+@@ -2460,7 +2435,7 @@ EXPORT_SYMBOL_GPL(scsi_target_unblock);
  
  /**
   * scsi_kmap_atomic_sg - find and atomically map an sg-elemnt
@@ -735770,7 +795683,7 @@
   * @sg_count:	number of segments in sg
   * @offset:	offset in bytes into sg, on return offset into the mapped area
   * @len:	bytes to map, on return number of bytes mapped
-@@ -2509,8 +2480,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count,
+@@ -2509,8 +2484,7 @@ void *scsi_kmap_atomic_sg(struct scatterlist *sgl, int sg_count,
  EXPORT_SYMBOL(scsi_kmap_atomic_sg);
  
  /**
@@ -736199,7 +796112,7 @@
  	memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun));
  	ev.p.cmd_req.attribute = cmd->tag;
 diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c
-index a91761c..91630ba 100644
+index a91761c..3677fbb 100644
 --- a/drivers/scsi/scsi_tgt_lib.c
 +++ b/drivers/scsi/scsi_tgt_lib.c
 @@ -180,7 +180,7 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work)
@@ -736211,7 +796124,15 @@
  		rq_data_dir(cmd->request));
  	scsi_unmap_user_pages(tcmd);
  	scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd);
-@@ -327,12 +327,11 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
+@@ -320,19 +320,18 @@ int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id,
+ EXPORT_SYMBOL_GPL(scsi_tgt_queue_command);
+ 
+ /*
+- * This is run from a interrpt handler normally and the unmap
++ * This is run from a interrupt handler normally and the unmap
+  * needs process context so we must queue
+  */
+ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd)
  {
  	struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data;
  
@@ -737271,9 +797192,18 @@
  	transport_class_unregister(&iscsi_session_class);
  	transport_class_unregister(&iscsi_host_class);
 diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
-index 3120f4b..f2149d0 100644
+index 3120f4b..43a964d 100644
 --- a/drivers/scsi/scsi_transport_sas.c
 +++ b/drivers/scsi/scsi_transport_sas.c
+@@ -6,7 +6,7 @@
+  *
+  * The SAS transport class contains common code to deal with SAS HBAs,
+  * an aproximated representation of SAS topologies in the driver model,
+- * and various sysfs attributes to expose these topologies and managment
++ * and various sysfs attributes to expose these topologies and management
+  * interfaces to userspace.
+  *
+  * In addition to the basic SCSI core objects this transport class
 @@ -173,6 +173,7 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
  
  		handler = to_sas_internal(shost->transportt)->f->smp_handler;
@@ -740718,18 +800648,22 @@
  
  #include "scsi_module.c"
 diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
-index facb678..6a48dfa 100644
+index facb678..0276471 100644
 --- a/drivers/serial/21285.c
 +++ b/drivers/serial/21285.c
-@@ -277,6 +277,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
- 	if (termios->c_iflag & INPCK)
- 		port->read_status_mask |= RXSTAT_FRAME | RXSTAT_PARITY;
- 
-+	tty_encode_baud_rate(tty,  baud, baud);
+@@ -237,6 +237,12 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
+ 	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); 
+ 	quot = uart_get_divisor(port, baud);
+ 
++	if (port->info && port->info->tty) {
++		struct tty_struct *tty = port->info->tty;
++		unsigned int b = port->uartclk / (16 * quot);
++		tty_encode_baud_rate(tty, b, b);
++	}
 +
- 	/*
- 	 * Which character status flags should we ignore?
- 	 */
+ 	switch (termios->c_cflag & CSIZE) {
+ 	case CS5:
+ 		h_lcr = 0x00;
 diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
 index aad4012..0d99120 100644
 --- a/drivers/serial/68328serial.c
@@ -740743,8 +800677,268 @@
  			    "M68328_UART", NULL))
                  panic("Unable to attach 68328 serial interrupt\n");
  	}
+diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
+index f94109c..b8a4bd9 100644
+--- a/drivers/serial/8250.c
++++ b/drivers/serial/8250.c
+@@ -2047,7 +2047,7 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+ 	 * Oxford Semi 952 rev B workaround
+ 	 */
+ 	if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
+-		quot ++;
++		quot++;
+ 
+ 	if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
+ 		if (baud < 2400)
+@@ -2662,16 +2662,17 @@ static int __devinit serial8250_probe(struct platform_device *dev)
+ 	memset(&port, 0, sizeof(struct uart_port));
+ 
+ 	for (i = 0; p && p->flags != 0; p++, i++) {
+-		port.iobase	= p->iobase;
+-		port.membase	= p->membase;
+-		port.irq	= p->irq;
+-		port.uartclk	= p->uartclk;
+-		port.regshift	= p->regshift;
+-		port.iotype	= p->iotype;
+-		port.flags	= p->flags;
+-		port.mapbase	= p->mapbase;
+-		port.hub6	= p->hub6;
+-		port.dev	= &dev->dev;
++		port.iobase		= p->iobase;
++		port.membase		= p->membase;
++		port.irq		= p->irq;
++		port.uartclk		= p->uartclk;
++		port.regshift		= p->regshift;
++		port.iotype		= p->iotype;
++		port.flags		= p->flags;
++		port.mapbase		= p->mapbase;
++		port.hub6		= p->hub6;
++		port.private_data	= p->private_data;
++		port.dev		= &dev->dev;
+ 		if (share_irqs)
+ 			port.flags |= UPF_SHARE_IRQ;
+ 		ret = serial8250_register_port(&port);
+@@ -2812,15 +2813,16 @@ int serial8250_register_port(struct uart_port *port)
+ 	if (uart) {
+ 		uart_remove_one_port(&serial8250_reg, &uart->port);
+ 
+-		uart->port.iobase   = port->iobase;
+-		uart->port.membase  = port->membase;
+-		uart->port.irq      = port->irq;
+-		uart->port.uartclk  = port->uartclk;
+-		uart->port.fifosize = port->fifosize;
+-		uart->port.regshift = port->regshift;
+-		uart->port.iotype   = port->iotype;
+-		uart->port.flags    = port->flags | UPF_BOOT_AUTOCONF;
+-		uart->port.mapbase  = port->mapbase;
++		uart->port.iobase       = port->iobase;
++		uart->port.membase      = port->membase;
++		uart->port.irq          = port->irq;
++		uart->port.uartclk      = port->uartclk;
++		uart->port.fifosize     = port->fifosize;
++		uart->port.regshift     = port->regshift;
++		uart->port.iotype       = port->iotype;
++		uart->port.flags        = port->flags | UPF_BOOT_AUTOCONF;
++		uart->port.mapbase      = port->mapbase;
++		uart->port.private_data = port->private_data;
+ 		if (port->dev)
+ 			uart->port.dev = port->dev;
+ 
+diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
+index ceb03c9..0a4ac2b 100644
+--- a/drivers/serial/8250_pci.c
++++ b/drivers/serial/8250_pci.c
+@@ -106,6 +106,32 @@ setup_port(struct serial_private *priv, struct uart_port *port,
+ }
+ 
+ /*
++ * ADDI-DATA GmbH communication cards <info at addi-data.com>
++ */
++static int addidata_apci7800_setup(struct serial_private *priv,
++				struct pciserial_board *board,
++				struct uart_port *port, int idx)
++{
++	unsigned int bar = 0, offset = board->first_offset;
++	bar = FL_GET_BASE(board->flags);
++
++	if (idx < 2) {
++		offset += idx * board->uart_offset;
++	} else if ((idx >= 2) && (idx < 4)) {
++		bar += 1;
++		offset += ((idx - 2) * board->uart_offset);
++	} else if ((idx >= 4) && (idx < 6)) {
++		bar += 2;
++		offset += ((idx - 4) * board->uart_offset);
++	} else if (idx >= 6) {
++		bar += 3;
++		offset += ((idx - 6) * board->uart_offset);
++	}
++
++	return setup_port(priv, port, bar, offset, board->reg_shift);
++}
++
++/*
+  * AFAVLAB uses a different mixture of BARs and offsets
+  * Not that ugly ;) -- HW
+  */
+@@ -752,6 +778,16 @@ pci_default_setup(struct serial_private *priv, struct pciserial_board *board,
+  */
+ static struct pci_serial_quirk pci_serial_quirks[] = {
+ 	/*
++	* ADDI-DATA GmbH communication cards <info at addi-data.com>
++	*/
++	{
++		.vendor         = PCI_VENDOR_ID_ADDIDATA_OLD,
++		.device         = PCI_DEVICE_ID_ADDIDATA_APCI7800,
++		.subvendor      = PCI_ANY_ID,
++		.subdevice      = PCI_ANY_ID,
++		.setup          = addidata_apci7800_setup,
++	},
++	/*
+ 	 * AFAVLAB cards - these may be called via parport_serial
+ 	 *  It is not clear whether this applies to all products.
+ 	 */
+@@ -1179,6 +1215,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
+ 		.base_baud	= 115200,
+ 		.uart_offset	= 8,
+ 	},
++	[pbn_b0_8_115200] = {
++		.flags		= FL_BASE0,
++		.num_ports	= 8,
++		.base_baud	= 115200,
++		.uart_offset	= 8,
++	},
+ 
+ 	[pbn_b0_1_921600] = {
+ 		.flags		= FL_BASE0,
+@@ -2697,6 +2739,97 @@ static struct pci_device_id serial_pci_tbl[] = {
+ 		pbn_pasemi_1682M },
+ 
+ 	/*
++	* ADDI-DATA GmbH communication cards <info at addi-data.com>
++	*/
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7500,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_4_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7420,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_2_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7300,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_1_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA_OLD,
++		PCI_DEVICE_ID_ADDIDATA_APCI7800,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b1_8_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7500_2,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_4_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7420_2,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_2_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7300_2,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_1_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7500_3,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_4_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7420_3,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_2_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7300_3,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_1_115200 },
++
++	{	PCI_VENDOR_ID_ADDIDATA,
++		PCI_DEVICE_ID_ADDIDATA_APCI7800_3,
++		PCI_ANY_ID,
++		PCI_ANY_ID,
++		0,
++		0,
++		pbn_b0_8_115200 },
++
++	/*
+ 	 * These entries match devices with class COMMUNICATION_SERIAL,
+ 	 * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
+ 	 */
+diff --git a/drivers/serial/8250_pnp.c b/drivers/serial/8250_pnp.c
+index 1de098e..6f09cbd 100644
+--- a/drivers/serial/8250_pnp.c
++++ b/drivers/serial/8250_pnp.c
+@@ -414,8 +414,9 @@ static int __devinit check_resources(struct pnp_option *option)
+  */
+ static int __devinit serial_pnp_guess_board(struct pnp_dev *dev, int *flags)
+ {
+-	if (!(check_name(pnp_dev_name(dev)) || (dev->card && check_name(dev->card->name))))
+-		return -ENODEV;
++	if (!(check_name(pnp_dev_name(dev)) ||
++		(dev->card && check_name(dev->card->name))))
++			return -ENODEV;
+ 
+ 	if (check_resources(dev->independent))
+ 		return 0;
+@@ -452,8 +453,9 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
+ 		return -ENODEV;
+ 
+ #ifdef SERIAL_DEBUG_PNP
+-	printk("Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
+-	       port.iobase, port.mapbase, port.irq, port.iotype);
++	printk(KERN_DEBUG
++		"Setup PNP port: port %x, mem 0x%lx, irq %d, type %d\n",
++		       port.iobase, port.mapbase, port.irq, port.iotype);
+ #endif
+ 
+ 	port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
 diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
-index d7e1996..8a053ea 100644
+index d7e1996..4fa7927 100644
 --- a/drivers/serial/Kconfig
 +++ b/drivers/serial/Kconfig
 @@ -960,6 +960,30 @@ config SERIAL_COLDFIRE
@@ -740778,6 +800972,17 @@
  config SERIAL_68360_SMC
  	bool "68360 SMC uart support"
  	depends on M68360
+@@ -1271,8 +1295,8 @@ config SERIAL_NETX_CONSOLE
+ 	depends on SERIAL_NETX
+ 	select SERIAL_CORE_CONSOLE
+ 	help
+-	  If you have enabled the serial port on the Motorola IMX
+-	  CPU you can make it the console by answering Y to this option.
++	  If you have enabled the serial port on the Hilscher NetX SoC
++	  you can make it the console by answering Y to this option.
+ 
+ config SERIAL_OF_PLATFORM
+ 	tristate "Serial port on Open Firmware platform bus"
 @@ -1284,4 +1308,14 @@ config SERIAL_OF_PLATFORM
  	  Currently, only 8250 compatible ports are supported, but
  	  others can easily be added.
@@ -740810,6 +801015,160 @@
  obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
  obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
 +obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
+diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
+index 111da57..60f5290 100644
+--- a/drivers/serial/atmel_serial.c
++++ b/drivers/serial/atmel_serial.c
+@@ -34,6 +34,7 @@
+ #include <linux/tty_flip.h>
+ #include <linux/platform_device.h>
+ #include <linux/atmel_pdc.h>
++#include <linux/atmel_serial.h>
+ 
+ #include <asm/io.h>
+ 
+@@ -45,8 +46,6 @@
+ #include <asm/arch/gpio.h>
+ #endif
+ 
+-#include "atmel_serial.h"
+-
+ #if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+ #define SUPPORT_SYSRQ
+ #endif
+diff --git a/drivers/serial/atmel_serial.h b/drivers/serial/atmel_serial.h
+deleted file mode 100644
+index e014177..0000000
+--- a/drivers/serial/atmel_serial.h
++++ /dev/null
+@@ -1,127 +0,0 @@
+-/*
+- * drivers/serial/atmel_serial.h
+- *
+- * Copyright (C) 2005 Ivan Kokshaysky
+- * Copyright (C) SAN People
+- *
+- * USART registers.
+- * Based on AT91RM9200 datasheet revision E.
+- *
+- * 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.
+- */
+-
+-#ifndef ATMEL_SERIAL_H
+-#define ATMEL_SERIAL_H
+-
+-#define ATMEL_US_CR		0x00			/* Control Register */
+-#define		ATMEL_US_RSTRX		(1 <<  2)		/* Reset Receiver */
+-#define		ATMEL_US_RSTTX		(1 <<  3)		/* Reset Transmitter */
+-#define		ATMEL_US_RXEN		(1 <<  4)		/* Receiver Enable */
+-#define		ATMEL_US_RXDIS		(1 <<  5)		/* Receiver Disable */
+-#define		ATMEL_US_TXEN		(1 <<  6)		/* Transmitter Enable */
+-#define		ATMEL_US_TXDIS		(1 <<  7)		/* Transmitter Disable */
+-#define		ATMEL_US_RSTSTA		(1 <<  8)		/* Reset Status Bits */
+-#define		ATMEL_US_STTBRK		(1 <<  9)		/* Start Break */
+-#define		ATMEL_US_STPBRK		(1 << 10)		/* Stop Break */
+-#define		ATMEL_US_STTTO		(1 << 11)		/* Start Time-out */
+-#define		ATMEL_US_SENDA		(1 << 12)		/* Send Address */
+-#define		ATMEL_US_RSTIT		(1 << 13)		/* Reset Iterations */
+-#define		ATMEL_US_RSTNACK	(1 << 14)		/* Reset Non Acknowledge */
+-#define		ATMEL_US_RETTO		(1 << 15)		/* Rearm Time-out */
+-#define		ATMEL_US_DTREN		(1 << 16)		/* Data Terminal Ready Enable [AT91RM9200 only] */
+-#define		ATMEL_US_DTRDIS		(1 << 17)		/* Data Terminal Ready Disable [AT91RM9200 only] */
+-#define		ATMEL_US_RTSEN		(1 << 18)		/* Request To Send Enable */
+-#define		ATMEL_US_RTSDIS		(1 << 19)		/* Request To Send Disable */
+-
+-#define ATMEL_US_MR		0x04			/* Mode Register */
+-#define		ATMEL_US_USMODE		(0xf <<  0)		/* Mode of the USART */
+-#define			ATMEL_US_USMODE_NORMAL		0
+-#define			ATMEL_US_USMODE_RS485		1
+-#define			ATMEL_US_USMODE_HWHS		2
+-#define			ATMEL_US_USMODE_MODEM		3
+-#define			ATMEL_US_USMODE_ISO7816_T0	4
+-#define			ATMEL_US_USMODE_ISO7816_T1	6
+-#define			ATMEL_US_USMODE_IRDA		8
+-#define		ATMEL_US_USCLKS		(3   <<  4)		/* Clock Selection */
+-#define			ATMEL_US_USCLKS_MCK		(0 <<  4)
+-#define			ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
+-#define			ATMEL_US_USCLKS_SCK		(3 <<  4)
+-#define		ATMEL_US_CHRL		(3   <<  6)		/* Character Length */
+-#define			ATMEL_US_CHRL_5			(0 <<  6)
+-#define			ATMEL_US_CHRL_6			(1 <<  6)
+-#define			ATMEL_US_CHRL_7			(2 <<  6)
+-#define			ATMEL_US_CHRL_8			(3 <<  6)
+-#define		ATMEL_US_SYNC		(1 <<  8)		/* Synchronous Mode Select */
+-#define		ATMEL_US_PAR		(7 <<  9)		/* Parity Type */
+-#define			ATMEL_US_PAR_EVEN		(0 <<  9)
+-#define			ATMEL_US_PAR_ODD		(1 <<  9)
+-#define			ATMEL_US_PAR_SPACE		(2 <<  9)
+-#define			ATMEL_US_PAR_MARK		(3 <<  9)
+-#define			ATMEL_US_PAR_NONE		(4 <<  9)
+-#define			ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
+-#define		ATMEL_US_NBSTOP		(3 << 12)		/* Number of Stop Bits */
+-#define			ATMEL_US_NBSTOP_1		(0 << 12)
+-#define			ATMEL_US_NBSTOP_1_5		(1 << 12)
+-#define			ATMEL_US_NBSTOP_2		(2 << 12)
+-#define		ATMEL_US_CHMODE		(3 << 14)		/* Channel Mode */
+-#define			ATMEL_US_CHMODE_NORMAL		(0 << 14)
+-#define			ATMEL_US_CHMODE_ECHO		(1 << 14)
+-#define			ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
+-#define			ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
+-#define		ATMEL_US_MSBF		(1 << 16)		/* Bit Order */
+-#define		ATMEL_US_MODE9		(1 << 17)		/* 9-bit Character Length */
+-#define		ATMEL_US_CLKO		(1 << 18)		/* Clock Output Select */
+-#define		ATMEL_US_OVER		(1 << 19)		/* Oversampling Mode */
+-#define		ATMEL_US_INACK		(1 << 20)		/* Inhibit Non Acknowledge */
+-#define		ATMEL_US_DSNACK		(1 << 21)		/* Disable Successive NACK */
+-#define		ATMEL_US_MAX_ITER	(7 << 24)		/* Max Iterations */
+-#define		ATMEL_US_FILTER		(1 << 28)		/* Infrared Receive Line Filter */
+-
+-#define ATMEL_US_IER		0x08			/* Interrupt Enable Register */
+-#define		ATMEL_US_RXRDY		(1 <<  0)		/* Receiver Ready */
+-#define		ATMEL_US_TXRDY		(1 <<  1)		/* Transmitter Ready */
+-#define		ATMEL_US_RXBRK		(1 <<  2)		/* Break Received / End of Break */
+-#define		ATMEL_US_ENDRX		(1 <<  3)		/* End of Receiver Transfer */
+-#define		ATMEL_US_ENDTX		(1 <<  4)		/* End of Transmitter Transfer */
+-#define		ATMEL_US_OVRE		(1 <<  5)		/* Overrun Error */
+-#define		ATMEL_US_FRAME		(1 <<  6)		/* Framing Error */
+-#define		ATMEL_US_PARE		(1 <<  7)		/* Parity Error */
+-#define		ATMEL_US_TIMEOUT	(1 <<  8)		/* Receiver Time-out */
+-#define		ATMEL_US_TXEMPTY	(1 <<  9)		/* Transmitter Empty */
+-#define		ATMEL_US_ITERATION	(1 << 10)		/* Max number of Repetitions Reached */
+-#define		ATMEL_US_TXBUFE		(1 << 11)		/* Transmission Buffer Empty */
+-#define		ATMEL_US_RXBUFF		(1 << 12)		/* Reception Buffer Full */
+-#define		ATMEL_US_NACK		(1 << 13)		/* Non Acknowledge */
+-#define		ATMEL_US_RIIC		(1 << 16)		/* Ring Indicator Input Change [AT91RM9200 only] */
+-#define		ATMEL_US_DSRIC		(1 << 17)		/* Data Set Ready Input Change [AT91RM9200 only] */
+-#define		ATMEL_US_DCDIC		(1 << 18)		/* Data Carrier Detect Input Change [AT91RM9200 only] */
+-#define		ATMEL_US_CTSIC		(1 << 19)		/* Clear to Send Input Change */
+-#define		ATMEL_US_RI		(1 << 20)		/* RI */
+-#define		ATMEL_US_DSR		(1 << 21)		/* DSR */
+-#define		ATMEL_US_DCD		(1 << 22)		/* DCD */
+-#define		ATMEL_US_CTS		(1 << 23)		/* CTS */
+-
+-#define ATMEL_US_IDR		0x0c			/* Interrupt Disable Register */
+-#define ATMEL_US_IMR		0x10			/* Interrupt Mask Register */
+-#define ATMEL_US_CSR		0x14			/* Channel Status Register */
+-#define ATMEL_US_RHR		0x18			/* Receiver Holding Register */
+-#define ATMEL_US_THR		0x1c			/* Transmitter Holding Register */
+-#define		ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [AT91SAM9261 only] */
+-
+-#define ATMEL_US_BRGR		0x20			/* Baud Rate Generator Register */
+-#define		ATMEL_US_CD		(0xffff << 0)		/* Clock Divider */
+-
+-#define ATMEL_US_RTOR		0x24			/* Receiver Time-out Register */
+-#define		ATMEL_US_TO		(0xffff << 0)		/* Time-out Value */
+-
+-#define ATMEL_US_TTGR		0x28			/* Transmitter Timeguard Register */
+-#define		ATMEL_US_TG		(0xff << 0)		/* Timeguard Value */
+-
+-#define ATMEL_US_FIDI		0x40			/* FI DI Ratio Register */
+-#define ATMEL_US_NER		0x44			/* Number of Errors Register */
+-#define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
+-
+-#endif
 diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
 index 6f475b6..ac2a3ef 100644
 --- a/drivers/serial/bfin_5xx.c
@@ -740988,9 +801347,18 @@
  		}
  	}
 diff --git a/drivers/serial/icom.h b/drivers/serial/icom.h
-index e8578d8..0274554 100644
+index e8578d8..c8029e0 100644
 --- a/drivers/serial/icom.h
 +++ b/drivers/serial/icom.h
+@@ -20,7 +20,7 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+  */
+ 
+-#include<linux/serial_core.h>
++#include <linux/serial_core.h>
+ 
+ #define BAUD_TABLE_LIMIT	((sizeof(icom_acfg_baud)/sizeof(int)) - 1)
+ static int icom_acfg_baud[] = {
 @@ -270,7 +270,7 @@ struct icom_adapter {
  #define V2_ONE_PORT_RVX_ONE_PORT_IMBED_MDM	0x0251
  	int numb_ports;
@@ -741001,7 +801369,7 @@
  
  /* prototype */
 diff --git a/drivers/serial/mcf.c b/drivers/serial/mcf.c
-index a7d4360..051fcc2 100644
+index a7d4360..e76fc72 100644
 --- a/drivers/serial/mcf.c
 +++ b/drivers/serial/mcf.c
 @@ -69,7 +69,7 @@ static unsigned int mcf_tx_empty(struct uart_port *port)
@@ -741094,6 +801462,15 @@
  	unsigned int isr;
  
  	isr = readb(port->membase + MCFUART_UISR) & pp->imr;
+@@ -434,7 +434,7 @@ static struct uart_ops mcf_uart_ops = {
+ 
+ static struct mcf_uart mcf_ports[3];
+ 
+-#define	MCF_MAXPORTS	(sizeof(mcf_ports) / sizeof(struct mcf_uart))
++#define	MCF_MAXPORTS	ARRAY_SIZE(mcf_ports)
+ 
+ /****************************************************************************/
+ #if defined(CONFIG_SERIAL_MCF_CONSOLE)
 diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
 index ec36ad7..3c4d29e 100644
 --- a/drivers/serial/mpc52xx_uart.c
@@ -741689,6 +802066,160 @@
  		printk(KERN_ERR "%s: uart_register_driver failed (%i)\n",
  		       __FILE__, ret);
  		return ret;
+diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
+index 4d643c9..cb3a919 100644
+--- a/drivers/serial/mpsc.c
++++ b/drivers/serial/mpsc.c
+@@ -612,6 +612,7 @@ static void mpsc_hw_init(struct mpsc_port_info *pi)
+ 
+ 	/* No preamble, 16x divider, low-latency, */
+ 	writel(0x04400400, pi->mpsc_base + MPSC_MMCRH);
++	mpsc_set_baudrate(pi, pi->default_baud);
+ 
+ 	if (pi->mirror_regs) {
+ 		pi->MPSC_CHR_1_m = 0;
+diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c
+index 8321101..e940317 100644
+--- a/drivers/serial/mux.c
++++ b/drivers/serial/mux.c
+@@ -582,7 +582,7 @@ static struct parisc_driver serial_mux_driver = {
+ };
+ 
+ /**
+- * mux_init - Serial MUX initalization procedure.
++ * mux_init - Serial MUX initialization procedure.
+  *
+  * Register the Serial MUX driver.
+  */
+diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
+index e773c8e..45de193 100644
+--- a/drivers/serial/s3c2410.c
++++ b/drivers/serial/s3c2410.c
+@@ -1527,7 +1527,7 @@ static inline void s3c2440_serial_exit(void)
+ #define s3c2440_uart_inf_at NULL
+ #endif /* CONFIG_CPU_S3C2440 */
+ 
+-#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
++#if defined(CONFIG_CPU_S3C2412)
+ 
+ static int s3c2412_serial_setsource(struct uart_port *port,
+ 				     struct s3c24xx_uart_clksrc *clk)
+diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
+index 3bb5d24..276da14 100644
+--- a/drivers/serial/serial_core.c
++++ b/drivers/serial/serial_core.c
+@@ -371,7 +371,8 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ 		 */
+ 		termios->c_cflag &= ~CBAUD;
+ 		if (old) {
+-			termios->c_cflag |= old->c_cflag & CBAUD;
++			baud = tty_termios_baud_rate(old);
++			tty_termios_encode_baud_rate(termios, baud, baud);
+ 			old = NULL;
+ 			continue;
+ 		}
+@@ -380,7 +381,7 @@ uart_get_baud_rate(struct uart_port *port, struct ktermios *termios,
+ 		 * As a last resort, if the quotient is zero,
+ 		 * default to 9600 bps
+ 		 */
+-		termios->c_cflag |= B9600;
++		tty_termios_encode_baud_rate(termios, 9600, 9600);
+ 	}
+ 
+ 	return 0;
+@@ -1977,6 +1978,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
+ 
+ 	if (state->info && state->info->flags & UIF_INITIALIZED) {
+ 		const struct uart_ops *ops = port->ops;
++		int tries;
+ 
+ 		state->info->flags = (state->info->flags & ~UIF_INITIALIZED)
+ 				     | UIF_SUSPENDED;
+@@ -1990,9 +1992,14 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port)
+ 		/*
+ 		 * Wait for the transmitter to empty.
+ 		 */
+-		while (!ops->tx_empty(port)) {
++		for (tries = 3; !ops->tx_empty(port) && tries; tries--) {
+ 			msleep(10);
+ 		}
++		if (!tries)
++			printk(KERN_ERR "%s%s%s%d: Unable to drain transmitter\n",
++			       port->dev ? port->dev->bus_id : "",
++			       port->dev ? ": " : "",
++			       drv->dev_name, port->line);
+ 
+ 		ops->shutdown(port);
+ 	}
+@@ -2029,8 +2036,6 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
+ 	}
+ 	port->suspended = 0;
+ 
+-	uart_change_pm(state, 0);
+-
+ 	/*
+ 	 * Re-enable the console device after suspending.
+ 	 */
+@@ -2049,6 +2054,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
+ 		if (state->info && state->info->tty && termios.c_cflag == 0)
+ 			termios = *state->info->tty->termios;
+ 
++		uart_change_pm(state, 0);
+ 		port->ops->set_termios(port, &termios, NULL);
+ 		console_start(port->cons);
+ 	}
+@@ -2057,6 +2063,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port)
+ 		const struct uart_ops *ops = port->ops;
+ 		int ret;
+ 
++		uart_change_pm(state, 0);
+ 		ops->set_mctrl(port, 0);
+ 		ret = ops->startup(port);
+ 		if (ret == 0) {
+@@ -2150,10 +2157,11 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
+ 
+ 		/*
+ 		 * Ensure that the modem control lines are de-activated.
++		 * keep the DTR setting that is set in uart_set_options()
+ 		 * We probably don't need a spinlock around this, but
+ 		 */
+ 		spin_lock_irqsave(&port->lock, flags);
+-		port->ops->set_mctrl(port, 0);
++		port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);
+ 		spin_unlock_irqrestore(&port->lock, flags);
+ 
+ 		/*
+diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
+index d8b6600..164d2a4 100644
+--- a/drivers/serial/serial_cs.c
++++ b/drivers/serial/serial_cs.c
+@@ -389,7 +389,7 @@ static void serial_detach(struct pcmcia_device *link)
+ /*====================================================================*/
+ 
+ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info,
+-			kio_addr_t iobase, int irq)
++			unsigned int iobase, int irq)
+ {
+ 	struct uart_port port;
+ 	int line;
+@@ -456,7 +456,7 @@ next_tuple(struct pcmcia_device *handle, tuple_t * tuple, cisparse_t * parse)
+ 
+ static int simple_config(struct pcmcia_device *link)
+ {
+-	static const kio_addr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
++	static const unsigned int base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
+ 	static const int size_table[2] = { 8, 16 };
+ 	struct serial_info *info = link->priv;
+ 	struct serial_cfg_mem *cfg_mem;
+@@ -480,7 +480,7 @@ static int simple_config(struct pcmcia_device *link)
+ 	/* If the card is already configured, look up the port and irq */
+ 	i = pcmcia_get_configuration_info(link, &config);
+ 	if ((i == CS_SUCCESS) && (config.Attributes & CONF_VALID_CLIENT)) {
+-		kio_addr_t port = 0;
++		unsigned int port = 0;
+ 		if ((config.BasePort2 != 0) && (config.NumPorts2 == 8)) {
+ 			port = config.BasePort2;
+ 			info->slave = 1;
 diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
 index 73440e2..ddf6391 100644
 --- a/drivers/serial/sh-sci.c
@@ -743896,6 +804427,19 @@
  	return master;
  }
  EXPORT_SYMBOL_GPL(spi_busnum_to_master);
+diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c
+index 2cd8573..639963e 100644
+--- a/drivers/spi/spi_imx.c
++++ b/drivers/spi/spi_imx.c
+@@ -157,7 +157,7 @@
+ #define SPI_FIFO_BYTE_WIDTH		(2)
+ #define SPI_FIFO_OVERFLOW_MARGIN	(2)
+ 
+-/* DMA burst lenght for half full/empty request trigger */
++/* DMA burst length for half full/empty request trigger */
+ #define SPI_DMA_BLR			(SPI_FIFO_DEPTH * SPI_FIFO_BYTE_WIDTH / 2)
+ 
+ /* Dummy char output to achieve reads.
 diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c
 index 4580b9c..04f7cd9 100644
 --- a/drivers/spi/spi_mpc83xx.c
@@ -743914,9 +804458,18 @@
  	mpc83xx_spi->rx_shift = 0;
  	mpc83xx_spi->tx_shift = 0;
 diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c
-index f145d8a..1a31f7a 100644
+index f145d8a..2d27d6d 100644
 --- a/drivers/ssb/b43_pci_bridge.c
 +++ b/drivers/ssb/b43_pci_bridge.c
+@@ -1,7 +1,7 @@
+ /*
+  * Broadcom 43xx PCI-SSB bridge module
+  *
+- * This technically is a seperate PCI driver module, but
++ * This technically is a separate PCI driver module, but
+  * because of its small size we include it in the SSB core
+  * instead of creating a standalone module.
+  *
 @@ -27,6 +27,8 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
  	{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) },
@@ -762744,6 +823297,19 @@
  #define ATMEL_LCDC_FIFO_SIZE		2048
  #else
  #define ATMEL_LCDC_FIFO_SIZE		512
+diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
+index 83ee3e7..675abda 100644
+--- a/drivers/video/aty/radeon_pm.c
++++ b/drivers/video/aty/radeon_pm.c
+@@ -2561,7 +2561,7 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend)
+ 			pci_read_config_dword(rinfo->pdev, i * 4,
+ 					      &rinfo->cfg_save[i]);
+ 
+-		/* Switch PCI power managment to D2. */
++		/* Switch PCI power management to D2. */
+ 		pci_disable_device(rinfo->pdev);
+ 		for (;;) {
+ 			pci_read_config_word(
 diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c
 index 74d11c3..c8e7427 100644
 --- a/drivers/video/bf54x-lq043fb.c
@@ -762781,6 +823347,32 @@
  	default y
  	help
  	  Saying Y here will allow you to use Linux in text mode through a
+diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
+index e23324d..9704b73 100644
+--- a/drivers/video/cyblafb.c
++++ b/drivers/video/cyblafb.c
+@@ -1156,7 +1156,7 @@ static struct fb_ops cyblafb_ops __devinitdata = {
+ // need altered timings to display correctly. So I decided that it is much
+ // better to provide a limited optimized set of modes plus the option of
+ // using the mode in effect at startup time (might be selected using the
+-// vga=??? paramter). After that the user might use fbset to select any
++// vga=??? parameter). After that the user might use fbset to select any
+ // mode he likes, check_var will not try to alter geometry parameters as
+ // it would be necessary otherwise.
+ //
+diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
+index 2fe3f7d..8367961 100644
+--- a/drivers/video/intelfb/intelfb.h
++++ b/drivers/video/intelfb/intelfb.h
+@@ -111,7 +111,7 @@
+ 
+ #define FIXED_MODE(d) ((d)->fixed_mode)
+ 
+-/*** Driver paramters ***/
++/*** Driver parameters ***/
+ 
+ #define RINGBUFFER_SIZE		KB(64)
+ #define HW_CURSOR_SIZE		KB(4)
 diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
 index 49cd53e..0cd58f8 100644
 --- a/drivers/video/matrox/matroxfb_maven.c
@@ -762809,6 +823401,19 @@
  #include <asm/arch/omapfb.h>
  
  #define MODULE_NAME	"omapfb-lcd_h3"
+diff --git a/drivers/video/omap/lcdc.c b/drivers/video/omap/lcdc.c
+index 9085188..fb19ed4 100644
+--- a/drivers/video/omap/lcdc.c
++++ b/drivers/video/omap/lcdc.c
+@@ -312,7 +312,7 @@ static irqreturn_t lcdc_irq_handler(int irq, void *dev_id)
+ /*
+  * Change to a new video mode. We defer this to a later time to avoid any
+  * flicker and not to mess up the current LCD DMA context. For this we disable
+- * the LCD controler, which will generate a DONE irq after the last frame has
++ * the LCD controller, which will generate a DONE irq after the last frame has
+  * been transferred. Then it'll be safe to reconfigure both the LCD controller
+  * as well as the LCD DMA.
+  */
 diff --git a/drivers/video/sis/sis.h b/drivers/video/sis/sis.h
 index d53bf69..9b05da6 100644
 --- a/drivers/video/sis/sis.h
@@ -762909,6 +823514,19 @@
  	/* Unmap */
  	iounmap(ivideo->mmio_vbase);
  	iounmap(ivideo->video_vbase);
+diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
+index 1be95a6..58f200c 100644
+--- a/drivers/video/sm501fb.c
++++ b/drivers/video/sm501fb.c
+@@ -48,7 +48,7 @@ enum sm501_controller {
+ 	HEAD_PANEL	= 1,
+ };
+ 
+-/* SM501 memory adress */
++/* SM501 memory address */
+ struct sm501_mem {
+ 	unsigned long	 size;
+ 	unsigned long	 sm_addr;
 diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c
 index c31f549..1c65666 100644
 --- a/drivers/video/vermilion/vermilion.c
@@ -762951,6 +823569,1015 @@
  
  		/*
  		 * Decrease the usage count on the pages we've used
+diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
+index 9e33fc4..3dd6294 100644
+--- a/drivers/virtio/Kconfig
++++ b/drivers/virtio/Kconfig
+@@ -1,8 +1,35 @@
+ # Virtio always gets selected by whoever wants it.
+ config VIRTIO
+-	bool
++	tristate
+ 
+ # Similarly the virtio ring implementation.
+ config VIRTIO_RING
+-	bool
++	tristate
+ 	depends on VIRTIO
++
++config VIRTIO_PCI
++	tristate "PCI driver for virtio devices (EXPERIMENTAL)"
++	depends on PCI && EXPERIMENTAL
++	select VIRTIO
++	select VIRTIO_RING
++	---help---
++	  This drivers provides support for virtio based paravirtual device
++	  drivers over PCI.  This requires that your VMM has appropriate PCI
++	  virtio backends.  Most QEMU based VMMs should support these devices
++	  (like KVM or Xen).
++
++	  Currently, the ABI is not considered stable so there is no guarantee
++	  that this version of the driver will work with your VMM.
++
++	  If unsure, say M.
++
++config VIRTIO_BALLOON
++	tristate "Virtio balloon driver (EXPERIMENTAL)"
++	select VIRTIO
++	select VIRTIO_RING
++	---help---
++	 This driver supports increasing and decreasing the amount
++	 of memory within a KVM guest.
++
++	 If unsure, say M.
++
+diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
+index f70e409..6738c44 100644
+--- a/drivers/virtio/Makefile
++++ b/drivers/virtio/Makefile
+@@ -1,2 +1,4 @@
+ obj-$(CONFIG_VIRTIO) += virtio.o
+ obj-$(CONFIG_VIRTIO_RING) += virtio_ring.o
++obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o
++obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
+diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
+index 69d7ea0..b535483 100644
+--- a/drivers/virtio/virtio.c
++++ b/drivers/virtio/virtio.c
+@@ -102,9 +102,13 @@ static int virtio_dev_remove(struct device *_d)
+ 	struct virtio_driver *drv = container_of(dev->dev.driver,
+ 						 struct virtio_driver, driver);
+ 
+-	dev->config->set_status(dev, dev->config->get_status(dev)
+-				& ~VIRTIO_CONFIG_S_DRIVER);
+ 	drv->remove(dev);
++
++	/* Driver should have reset device. */
++	BUG_ON(dev->config->get_status(dev));
++
++	/* Acknowledge the device's existence again. */
++	add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
+ 	return 0;
+ }
+ 
+@@ -130,6 +134,10 @@ int register_virtio_device(struct virtio_device *dev)
+ 	dev->dev.bus = &virtio_bus;
+ 	sprintf(dev->dev.bus_id, "%u", dev->index);
+ 
++	/* We always start by resetting the device, in case a previous
++	 * driver messed it up.  This also tests that code path a little. */
++	dev->config->reset(dev);
++
+ 	/* Acknowledge that we've seen the device. */
+ 	add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
+ 
+@@ -148,55 +156,18 @@ void unregister_virtio_device(struct virtio_device *dev)
+ }
+ EXPORT_SYMBOL_GPL(unregister_virtio_device);
+ 
+-int __virtio_config_val(struct virtio_device *vdev,
+-			u8 type, void *val, size_t size)
+-{
+-	void *token;
+-	unsigned int len;
+-
+-	token = vdev->config->find(vdev, type, &len);
+-	if (!token)
+-		return -ENOENT;
+-
+-	if (len != size)
+-		return -EIO;
+-
+-	vdev->config->get(vdev, token, val, size);
+-	return 0;
+-}
+-EXPORT_SYMBOL_GPL(__virtio_config_val);
+-
+-int virtio_use_bit(struct virtio_device *vdev,
+-		   void *token, unsigned int len, unsigned int bitnum)
+-{
+-	unsigned long bits[16];
+-
+-	/* This makes it convenient to pass-through find() results. */
+-	if (!token)
+-		return 0;
+-
+-	/* bit not in range of this bitfield? */
+-	if (bitnum * 8 >= len / 2)
+-		return 0;
+-
+-	/* Giant feature bitfields are silly. */
+-	BUG_ON(len > sizeof(bits));
+-	vdev->config->get(vdev, token, bits, len);
+-
+-	if (!test_bit(bitnum, bits))
+-		return 0;
+-
+-	/* Set acknowledge bit, and write it back. */
+-	set_bit(bitnum + len * 8 / 2, bits);
+-	vdev->config->set(vdev, token, bits, len);
+-	return 1;
+-}
+-EXPORT_SYMBOL_GPL(virtio_use_bit);
+-
+ static int virtio_init(void)
+ {
+ 	if (bus_register(&virtio_bus) != 0)
+ 		panic("virtio bus registration failed");
+ 	return 0;
+ }
++
++static void __exit virtio_exit(void)
++{
++	bus_unregister(&virtio_bus);
++}
+ core_initcall(virtio_init);
++module_exit(virtio_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
+new file mode 100644
+index 0000000..622aece
+--- /dev/null
++++ b/drivers/virtio/virtio_balloon.c
+@@ -0,0 +1,284 @@
++/* Virtio balloon implementation, inspired by Dor Loar and Marcelo
++ * Tosatti's implementations.
++ *
++ *  Copyright 2008 Rusty Russell IBM Corporation
++ *
++ *  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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
++ */
++//#define DEBUG
++#include <linux/virtio.h>
++#include <linux/virtio_balloon.h>
++#include <linux/swap.h>
++#include <linux/kthread.h>
++#include <linux/freezer.h>
++
++struct virtio_balloon
++{
++	struct virtio_device *vdev;
++	struct virtqueue *inflate_vq, *deflate_vq;
++
++	/* Where the ballooning thread waits for config to change. */
++	wait_queue_head_t config_change;
++
++	/* The thread servicing the balloon. */
++	struct task_struct *thread;
++
++	/* Waiting for host to ack the pages we released. */
++	struct completion acked;
++
++	/* Do we have to tell Host *before* we reuse pages? */
++	bool tell_host_first;
++
++	/* The pages we've told the Host we're not using. */
++	unsigned int num_pages;
++	struct list_head pages;
++
++	/* The array of pfns we tell the Host about. */
++	unsigned int num_pfns;
++	u32 pfns[256];
++};
++
++static struct virtio_device_id id_table[] = {
++	{ VIRTIO_ID_BALLOON, VIRTIO_DEV_ANY_ID },
++	{ 0 },
++};
++
++static void balloon_ack(struct virtqueue *vq)
++{
++	struct virtio_balloon *vb;
++	unsigned int len;
++
++	vb = vq->vq_ops->get_buf(vq, &len);
++	if (vb)
++		complete(&vb->acked);
++}
++
++static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
++{
++	struct scatterlist sg;
++
++	sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
++
++	init_completion(&vb->acked);
++
++	/* We should always be able to add one buffer to an empty queue. */
++	if (vq->vq_ops->add_buf(vq, &sg, 1, 0, vb) != 0)
++		BUG();
++	vq->vq_ops->kick(vq);
++
++	/* When host has read buffer, this completes via balloon_ack */
++	wait_for_completion(&vb->acked);
++}
++
++static void fill_balloon(struct virtio_balloon *vb, size_t num)
++{
++	/* We can only do one array worth at a time. */
++	num = min(num, ARRAY_SIZE(vb->pfns));
++
++	for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
++		struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY);
++		if (!page) {
++			if (printk_ratelimit())
++				dev_printk(KERN_INFO, &vb->vdev->dev,
++					   "Out of puff! Can't get %zu pages\n",
++					   num);
++			/* Sleep for at least 1/5 of a second before retry. */
++			msleep(200);
++			break;
++		}
++		vb->pfns[vb->num_pfns] = page_to_pfn(page);
++		totalram_pages--;
++		vb->num_pages++;
++		list_add(&page->lru, &vb->pages);
++	}
++
++	/* Didn't get any?  Oh well. */
++	if (vb->num_pfns == 0)
++		return;
++
++	tell_host(vb, vb->inflate_vq);
++}
++
++static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
++{
++	unsigned int i;
++
++	for (i = 0; i < num; i++) {
++		__free_page(pfn_to_page(pfns[i]));
++		totalram_pages++;
++	}
++}
++
++static void leak_balloon(struct virtio_balloon *vb, size_t num)
++{
++	struct page *page;
++
++	/* We can only do one array worth at a time. */
++	num = min(num, ARRAY_SIZE(vb->pfns));
++
++	for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
++		page = list_first_entry(&vb->pages, struct page, lru);
++		list_del(&page->lru);
++		vb->pfns[vb->num_pfns] = page_to_pfn(page);
++		vb->num_pages--;
++	}
++
++	if (vb->tell_host_first) {
++		tell_host(vb, vb->deflate_vq);
++		release_pages_by_pfn(vb->pfns, vb->num_pfns);
++	} else {
++		release_pages_by_pfn(vb->pfns, vb->num_pfns);
++		tell_host(vb, vb->deflate_vq);
++	}
++}
++
++static void virtballoon_changed(struct virtio_device *vdev)
++{
++	struct virtio_balloon *vb = vdev->priv;
++
++	wake_up(&vb->config_change);
++}
++
++static inline int towards_target(struct virtio_balloon *vb)
++{
++	u32 v;
++	__virtio_config_val(vb->vdev,
++			    offsetof(struct virtio_balloon_config, num_pages),
++			    &v);
++	return v - vb->num_pages;
++}
++
++static void update_balloon_size(struct virtio_balloon *vb)
++{
++	__le32 actual = cpu_to_le32(vb->num_pages);
++
++	vb->vdev->config->set(vb->vdev,
++			      offsetof(struct virtio_balloon_config, actual),
++			      &actual, sizeof(actual));
++}
++
++static int balloon(void *_vballoon)
++{
++	struct virtio_balloon *vb = _vballoon;
++
++	set_freezable();
++	while (!kthread_should_stop()) {
++		int diff;
++
++		try_to_freeze();
++		wait_event_interruptible(vb->config_change,
++					 (diff = towards_target(vb)) != 0
++					 || kthread_should_stop());
++		if (diff > 0)
++			fill_balloon(vb, diff);
++		else if (diff < 0)
++			leak_balloon(vb, -diff);
++		update_balloon_size(vb);
++	}
++	return 0;
++}
++
++static int virtballoon_probe(struct virtio_device *vdev)
++{
++	struct virtio_balloon *vb;
++	int err;
++
++	vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
++	if (!vb) {
++		err = -ENOMEM;
++		goto out;
++	}
++
++	INIT_LIST_HEAD(&vb->pages);
++	vb->num_pages = 0;
++	init_waitqueue_head(&vb->config_change);
++	vb->vdev = vdev;
++
++	/* We expect two virtqueues. */
++	vb->inflate_vq = vdev->config->find_vq(vdev, 0, balloon_ack);
++	if (IS_ERR(vb->inflate_vq)) {
++		err = PTR_ERR(vb->inflate_vq);
++		goto out_free_vb;
++	}
++
++	vb->deflate_vq = vdev->config->find_vq(vdev, 1, balloon_ack);
++	if (IS_ERR(vb->deflate_vq)) {
++		err = PTR_ERR(vb->deflate_vq);
++		goto out_del_inflate_vq;
++	}
++
++	vb->thread = kthread_run(balloon, vb, "vballoon");
++	if (IS_ERR(vb->thread)) {
++		err = PTR_ERR(vb->thread);
++		goto out_del_deflate_vq;
++	}
++
++	vb->tell_host_first
++		= vdev->config->feature(vdev, VIRTIO_BALLOON_F_MUST_TELL_HOST);
++
++	return 0;
++
++out_del_deflate_vq:
++	vdev->config->del_vq(vb->deflate_vq);
++out_del_inflate_vq:
++	vdev->config->del_vq(vb->inflate_vq);
++out_free_vb:
++	kfree(vb);
++out:
++	return err;
++}
++
++static void virtballoon_remove(struct virtio_device *vdev)
++{
++	struct virtio_balloon *vb = vdev->priv;
++
++	kthread_stop(vb->thread);
++
++	/* There might be pages left in the balloon: free them. */
++	while (vb->num_pages)
++		leak_balloon(vb, vb->num_pages);
++
++	/* Now we reset the device so we can clean up the queues. */
++	vdev->config->reset(vdev);
++
++	vdev->config->del_vq(vb->deflate_vq);
++	vdev->config->del_vq(vb->inflate_vq);
++	kfree(vb);
++}
++
++static struct virtio_driver virtio_balloon = {
++	.driver.name =	KBUILD_MODNAME,
++	.driver.owner =	THIS_MODULE,
++	.id_table =	id_table,
++	.probe =	virtballoon_probe,
++	.remove =	__devexit_p(virtballoon_remove),
++	.config_changed = virtballoon_changed,
++};
++
++static int __init init(void)
++{
++	return register_virtio_driver(&virtio_balloon);
++}
++
++static void __exit fini(void)
++{
++	unregister_virtio_driver(&virtio_balloon);
++}
++module_init(init);
++module_exit(fini);
++
++MODULE_DEVICE_TABLE(virtio, id_table);
++MODULE_DESCRIPTION("Virtio balloon driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
+new file mode 100644
+index 0000000..26f787d
+--- /dev/null
++++ b/drivers/virtio/virtio_pci.c
+@@ -0,0 +1,446 @@
++/*
++ * Virtio PCI driver
++ *
++ * This module allows virtio devices to be used over a virtual PCI device.
++ * This can be used with QEMU based VMMs like KVM or Xen.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors:
++ *  Anthony Liguori  <aliguori at us.ibm.com>
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2 or later.
++ * See the COPYING file in the top-level directory.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/list.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <linux/virtio.h>
++#include <linux/virtio_config.h>
++#include <linux/virtio_ring.h>
++#include <linux/virtio_pci.h>
++#include <linux/highmem.h>
++#include <linux/spinlock.h>
++
++MODULE_AUTHOR("Anthony Liguori <aliguori at us.ibm.com>");
++MODULE_DESCRIPTION("virtio-pci");
++MODULE_LICENSE("GPL");
++MODULE_VERSION("1");
++
++/* Our device structure */
++struct virtio_pci_device
++{
++	struct virtio_device vdev;
++	struct pci_dev *pci_dev;
++
++	/* the IO mapping for the PCI config space */
++	void *ioaddr;
++
++	/* a list of queues so we can dispatch IRQs */
++	spinlock_t lock;
++	struct list_head virtqueues;
++};
++
++struct virtio_pci_vq_info
++{
++	/* the actual virtqueue */
++	struct virtqueue *vq;
++
++	/* the number of entries in the queue */
++	int num;
++
++	/* the index of the queue */
++	int queue_index;
++
++	/* the virtual address of the ring queue */
++	void *queue;
++
++	/* the list node for the virtqueues list */
++	struct list_head node;
++};
++
++/* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
++static struct pci_device_id virtio_pci_id_table[] = {
++	{ 0x1af4, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
++	{ 0 },
++};
++
++MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
++
++/* A PCI device has it's own struct device and so does a virtio device so
++ * we create a place for the virtio devices to show up in sysfs.  I think it
++ * would make more sense for virtio to not insist on having it's own device. */
++static struct device virtio_pci_root = {
++	.parent		= NULL,
++	.bus_id		= "virtio-pci",
++};
++
++/* Unique numbering for devices under the kvm root */
++static unsigned int dev_index;
++
++/* Convert a generic virtio device to our structure */
++static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev)
++{
++	return container_of(vdev, struct virtio_pci_device, vdev);
++}
++
++/* virtio config->feature() implementation */
++static bool vp_feature(struct virtio_device *vdev, unsigned bit)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	u32 mask;
++
++	/* Since this function is supposed to have the side effect of
++	 * enabling a queried feature, we simulate that by doing a read
++	 * from the host feature bitmask and then writing to the guest
++	 * feature bitmask */
++	mask = ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
++	if (mask & (1 << bit)) {
++		mask |= (1 << bit);
++		iowrite32(mask, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
++	}
++
++	return !!(mask & (1 << bit));
++}
++
++/* virtio config->get() implementation */
++static void vp_get(struct virtio_device *vdev, unsigned offset,
++		   void *buf, unsigned len)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	void *ioaddr = vp_dev->ioaddr + VIRTIO_PCI_CONFIG + offset;
++	u8 *ptr = buf;
++	int i;
++
++	for (i = 0; i < len; i++)
++		ptr[i] = ioread8(ioaddr + i);
++}
++
++/* the config->set() implementation.  it's symmetric to the config->get()
++ * implementation */
++static void vp_set(struct virtio_device *vdev, unsigned offset,
++		   const void *buf, unsigned len)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	void *ioaddr = vp_dev->ioaddr + VIRTIO_PCI_CONFIG + offset;
++	const u8 *ptr = buf;
++	int i;
++
++	for (i = 0; i < len; i++)
++		iowrite8(ptr[i], ioaddr + i);
++}
++
++/* config->{get,set}_status() implementations */
++static u8 vp_get_status(struct virtio_device *vdev)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	return ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS);
++}
++
++static void vp_set_status(struct virtio_device *vdev, u8 status)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	/* We should never be setting status to 0. */
++	BUG_ON(status == 0);
++	return iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
++}
++
++static void vp_reset(struct virtio_device *vdev)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	/* 0 status means a reset. */
++	return iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
++}
++
++/* the notify function used when creating a virt queue */
++static void vp_notify(struct virtqueue *vq)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
++	struct virtio_pci_vq_info *info = vq->priv;
++
++	/* we write the queue's selector into the notification register to
++	 * signal the other end */
++	iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY);
++}
++
++/* A small wrapper to also acknowledge the interrupt when it's handled.
++ * I really need an EIO hook for the vring so I can ack the interrupt once we
++ * know that we'll be handling the IRQ but before we invoke the callback since
++ * the callback may notify the host which results in the host attempting to
++ * raise an interrupt that we would then mask once we acknowledged the
++ * interrupt. */
++static irqreturn_t vp_interrupt(int irq, void *opaque)
++{
++	struct virtio_pci_device *vp_dev = opaque;
++	struct virtio_pci_vq_info *info;
++	irqreturn_t ret = IRQ_NONE;
++	u8 isr;
++
++	/* reading the ISR has the effect of also clearing it so it's very
++	 * important to save off the value. */
++	isr = ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR);
++
++	/* It's definitely not us if the ISR was not high */
++	if (!isr)
++		return IRQ_NONE;
++
++	/* Configuration change?  Tell driver if it wants to know. */
++	if (isr & VIRTIO_PCI_ISR_CONFIG) {
++		struct virtio_driver *drv;
++		drv = container_of(vp_dev->vdev.dev.driver,
++				   struct virtio_driver, driver);
++
++		if (drv->config_changed)
++			drv->config_changed(&vp_dev->vdev);
++	}
++
++	spin_lock(&vp_dev->lock);
++	list_for_each_entry(info, &vp_dev->virtqueues, node) {
++		if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
++			ret = IRQ_HANDLED;
++	}
++	spin_unlock(&vp_dev->lock);
++
++	return ret;
++}
++
++/* the config->find_vq() implementation */
++static struct virtqueue *vp_find_vq(struct virtio_device *vdev, unsigned index,
++				    void (*callback)(struct virtqueue *vq))
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
++	struct virtio_pci_vq_info *info;
++	struct virtqueue *vq;
++	u16 num;
++	int err;
++
++	/* Select the queue we're interested in */
++	iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
++
++	/* Check if queue is either not available or already active. */
++	num = ioread16(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NUM);
++	if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN))
++		return ERR_PTR(-ENOENT);
++
++	/* allocate and fill out our structure the represents an active
++	 * queue */
++	info = kmalloc(sizeof(struct virtio_pci_vq_info), GFP_KERNEL);
++	if (!info)
++		return ERR_PTR(-ENOMEM);
++
++	info->queue_index = index;
++	info->num = num;
++
++	info->queue = kzalloc(PAGE_ALIGN(vring_size(num,PAGE_SIZE)), GFP_KERNEL);
++	if (info->queue == NULL) {
++		err = -ENOMEM;
++		goto out_info;
++	}
++
++	/* activate the queue */
++	iowrite32(virt_to_phys(info->queue) >> PAGE_SHIFT,
++		  vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
++
++	/* create the vring */
++	vq = vring_new_virtqueue(info->num, vdev, info->queue,
++				 vp_notify, callback);
++	if (!vq) {
++		err = -ENOMEM;
++		goto out_activate_queue;
++	}
++
++	vq->priv = info;
++	info->vq = vq;
++
++	spin_lock(&vp_dev->lock);
++	list_add(&info->node, &vp_dev->virtqueues);
++	spin_unlock(&vp_dev->lock);
++
++	return vq;
++
++out_activate_queue:
++	iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
++	kfree(info->queue);
++out_info:
++	kfree(info);
++	return ERR_PTR(err);
++}
++
++/* the config->del_vq() implementation */
++static void vp_del_vq(struct virtqueue *vq)
++{
++	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
++	struct virtio_pci_vq_info *info = vq->priv;
++
++	spin_lock(&vp_dev->lock);
++	list_del(&info->node);
++	spin_unlock(&vp_dev->lock);
++
++	vring_del_virtqueue(vq);
++
++	/* Select and deactivate the queue */
++	iowrite16(info->queue_index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
++	iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
++
++	kfree(info->queue);
++	kfree(info);
++}
++
++static struct virtio_config_ops virtio_pci_config_ops = {
++	.feature	= vp_feature,
++	.get		= vp_get,
++	.set		= vp_set,
++	.get_status	= vp_get_status,
++	.set_status	= vp_set_status,
++	.reset		= vp_reset,
++	.find_vq	= vp_find_vq,
++	.del_vq		= vp_del_vq,
++};
++
++/* the PCI probing function */
++static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
++				      const struct pci_device_id *id)
++{
++	struct virtio_pci_device *vp_dev;
++	int err;
++
++	/* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */
++	if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f)
++		return -ENODEV;
++
++	if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) {
++		printk(KERN_ERR "virtio_pci: expected ABI version %d, got %d\n",
++		       VIRTIO_PCI_ABI_VERSION, pci_dev->revision);
++		return -ENODEV;
++	}
++
++	/* allocate our structure and fill it out */
++	vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
++	if (vp_dev == NULL)
++		return -ENOMEM;
++
++	snprintf(vp_dev->vdev.dev.bus_id, BUS_ID_SIZE, "virtio%d", dev_index);
++	vp_dev->vdev.index = dev_index;
++	dev_index++;
++
++	vp_dev->vdev.dev.parent = &virtio_pci_root;
++	vp_dev->vdev.config = &virtio_pci_config_ops;
++	vp_dev->pci_dev = pci_dev;
++	INIT_LIST_HEAD(&vp_dev->virtqueues);
++	spin_lock_init(&vp_dev->lock);
++
++	/* enable the device */
++	err = pci_enable_device(pci_dev);
++	if (err)
++		goto out;
++
++	err = pci_request_regions(pci_dev, "virtio-pci");
++	if (err)
++		goto out_enable_device;
++
++	vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0);
++	if (vp_dev->ioaddr == NULL)
++		goto out_req_regions;
++
++	pci_set_drvdata(pci_dev, vp_dev);
++
++	/* we use the subsystem vendor/device id as the virtio vendor/device
++	 * id.  this allows us to use the same PCI vendor/device id for all
++	 * virtio devices and to identify the particular virtio driver by
++	 * the subsytem ids */
++	vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor;
++	vp_dev->vdev.id.device = pci_dev->subsystem_device;
++
++	/* register a handler for the queue with the PCI device's interrupt */
++	err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
++			  vp_dev->vdev.dev.bus_id, vp_dev);
++	if (err)
++		goto out_set_drvdata;
++
++	/* finally register the virtio device */
++	err = register_virtio_device(&vp_dev->vdev);
++	if (err)
++		goto out_req_irq;
++
++	return 0;
++
++out_req_irq:
++	free_irq(pci_dev->irq, vp_dev);
++out_set_drvdata:
++	pci_set_drvdata(pci_dev, NULL);
++	pci_iounmap(pci_dev, vp_dev->ioaddr);
++out_req_regions:
++	pci_release_regions(pci_dev);
++out_enable_device:
++	pci_disable_device(pci_dev);
++out:
++	kfree(vp_dev);
++	return err;
++}
++
++static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
++{
++	struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
++
++	free_irq(pci_dev->irq, vp_dev);
++	pci_set_drvdata(pci_dev, NULL);
++	pci_iounmap(pci_dev, vp_dev->ioaddr);
++	pci_release_regions(pci_dev);
++	pci_disable_device(pci_dev);
++	kfree(vp_dev);
++}
++
++#ifdef CONFIG_PM
++static int virtio_pci_suspend(struct pci_dev *pci_dev, pm_message_t state)
++{
++	pci_save_state(pci_dev);
++	pci_set_power_state(pci_dev, PCI_D3hot);
++	return 0;
++}
++
++static int virtio_pci_resume(struct pci_dev *pci_dev)
++{
++	pci_restore_state(pci_dev);
++	pci_set_power_state(pci_dev, PCI_D0);
++	return 0;
++}
++#endif
++
++static struct pci_driver virtio_pci_driver = {
++	.name		= "virtio-pci",
++	.id_table	= virtio_pci_id_table,
++	.probe		= virtio_pci_probe,
++	.remove		= virtio_pci_remove,
++#ifdef CONFIG_PM
++	.suspend	= virtio_pci_suspend,
++	.resume		= virtio_pci_resume,
++#endif
++};
++
++static int __init virtio_pci_init(void)
++{
++	int err;
++
++	err = device_register(&virtio_pci_root);
++	if (err)
++		return err;
++
++	err = pci_register_driver(&virtio_pci_driver);
++	if (err)
++		device_unregister(&virtio_pci_root);
++
++	return err;
++}
++
++module_init(virtio_pci_init);
++
++static void __exit virtio_pci_exit(void)
++{
++	device_unregister(&virtio_pci_root);
++	pci_unregister_driver(&virtio_pci_driver);
++}
++
++module_exit(virtio_pci_exit);
+diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
+index 1dc04b6..3a28c13 100644
+--- a/drivers/virtio/virtio_ring.c
++++ b/drivers/virtio/virtio_ring.c
+@@ -87,6 +87,8 @@ static int vring_add_buf(struct virtqueue *_vq,
+ 	if (vq->num_free < out + in) {
+ 		pr_debug("Can't add buf len %i - avail = %i\n",
+ 			 out + in, vq->num_free);
++		/* We notify *even if* VRING_USED_F_NO_NOTIFY is set here. */
++		vq->notify(&vq->vq);
+ 		END_USE(vq);
+ 		return -ENOSPC;
+ 	}
+@@ -97,16 +99,14 @@ static int vring_add_buf(struct virtqueue *_vq,
+ 	head = vq->free_head;
+ 	for (i = vq->free_head; out; i = vq->vring.desc[i].next, out--) {
+ 		vq->vring.desc[i].flags = VRING_DESC_F_NEXT;
+-		vq->vring.desc[i].addr = (page_to_pfn(sg_page(sg))<<PAGE_SHIFT)
+-			+ sg->offset;
++		vq->vring.desc[i].addr = sg_phys(sg);
+ 		vq->vring.desc[i].len = sg->length;
+ 		prev = i;
+ 		sg++;
+ 	}
+ 	for (; in; i = vq->vring.desc[i].next, in--) {
+ 		vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE;
+-		vq->vring.desc[i].addr = (page_to_pfn(sg_page(sg))<<PAGE_SHIFT)
+-			+ sg->offset;
++		vq->vring.desc[i].addr = sg_phys(sg);
+ 		vq->vring.desc[i].len = sg->length;
+ 		prev = i;
+ 		sg++;
+@@ -171,16 +171,6 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
+ 	vq->num_free++;
+ }
+ 
+-/* FIXME: We need to tell other side about removal, to synchronize. */
+-static void vring_shutdown(struct virtqueue *_vq)
+-{
+-	struct vring_virtqueue *vq = to_vvq(_vq);
+-	unsigned int i;
+-
+-	for (i = 0; i < vq->vring.num; i++)
+-		detach_buf(vq, i);
+-}
+-
+ static inline bool more_used(const struct vring_virtqueue *vq)
+ {
+ 	return vq->last_used_idx != vq->vring.used->idx;
+@@ -220,7 +210,17 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
+ 	return ret;
+ }
+ 
+-static bool vring_restart(struct virtqueue *_vq)
++static void vring_disable_cb(struct virtqueue *_vq)
++{
++	struct vring_virtqueue *vq = to_vvq(_vq);
++
++	START_USE(vq);
++	BUG_ON(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
++	vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
++	END_USE(vq);
++}
++
++static bool vring_enable_cb(struct virtqueue *_vq)
+ {
+ 	struct vring_virtqueue *vq = to_vvq(_vq);
+ 
+@@ -253,26 +253,34 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
+ 	if (unlikely(vq->broken))
+ 		return IRQ_HANDLED;
+ 
++	/* Other side may have missed us turning off the interrupt,
++	 * but we should preserve disable semantic for virtio users. */
++	if (unlikely(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) {
++		pr_debug("virtqueue interrupt after disable for %p\n", vq);
++		return IRQ_HANDLED;
++	}
++
+ 	pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback);
+-	if (vq->vq.callback && !vq->vq.callback(&vq->vq))
+-		vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
++	if (vq->vq.callback)
++		vq->vq.callback(&vq->vq);
+ 
+ 	return IRQ_HANDLED;
+ }
++EXPORT_SYMBOL_GPL(vring_interrupt);
+ 
+ static struct virtqueue_ops vring_vq_ops = {
+ 	.add_buf = vring_add_buf,
+ 	.get_buf = vring_get_buf,
+ 	.kick = vring_kick,
+-	.restart = vring_restart,
+-	.shutdown = vring_shutdown,
++	.disable_cb = vring_disable_cb,
++	.enable_cb = vring_enable_cb,
+ };
+ 
+ struct virtqueue *vring_new_virtqueue(unsigned int num,
+ 				      struct virtio_device *vdev,
+ 				      void *pages,
+ 				      void (*notify)(struct virtqueue *),
+-				      bool (*callback)(struct virtqueue *))
++				      void (*callback)(struct virtqueue *))
+ {
+ 	struct vring_virtqueue *vq;
+ 	unsigned int i;
+@@ -311,9 +319,12 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
+ 
+ 	return &vq->vq;
+ }
++EXPORT_SYMBOL_GPL(vring_new_virtqueue);
+ 
+ void vring_del_virtqueue(struct virtqueue *vq)
+ {
+ 	kfree(to_vvq(vq));
+ }
++EXPORT_SYMBOL_GPL(vring_del_virtqueue);
+ 
++MODULE_LICENSE("GPL");
 diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
 index d93eb62..0fd5820 100644
 --- a/drivers/w1/masters/ds2482.c
@@ -763247,6 +824874,19 @@
  	release_region(scx200_cb_base + SCx200_WDT_OFFSET,
  		       SCx200_WDT_SIZE);
  }
+diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
+index cecbedd..61dde86 100644
+--- a/drivers/watchdog/shwdt.c
++++ b/drivers/watchdog/shwdt.c
+@@ -52,7 +52,7 @@
+  * overflow periods respectively.
+  *
+  * Also, since we can't really expect userspace to be responsive enough
+- * before the overflow happens, we maintain two seperate timers .. One in
++ * before the overflow happens, we maintain two separate timers .. One in
+  * the kernel for clearing out WOVF every 2ms or so (again, this depends on
+  * HZ == 1000), and another for monitoring userspace writes to the WDT device.
+  *
 diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c
 new file mode 100644
 index 0000000..328b3c7
@@ -763765,7 +825405,7 @@
  	if (!machine_is_netwinder())
  	        release_region(IO_INDEX_PORT,2);
 diff --git a/fs/Kconfig b/fs/Kconfig
-index 781b47d..987b5d7 100644
+index 781b47d..ea5b359 100644
 --- a/fs/Kconfig
 +++ b/fs/Kconfig
 @@ -236,6 +236,7 @@ config JBD_DEBUG
@@ -763804,6 +825444,46 @@
  	help
  	  configfs is a ram-based filesystem that provides the converse
  	  of sysfs's functionality. Where sysfs is a filesystem-based
+@@ -1157,7 +1152,7 @@ config BEFS_DEBUG
+ 	depends on BEFS_FS
+ 	help
+ 	  If you say Y here, you can use the 'debug' mount option to enable
+-	  debugging output from the driver. 
++	  debugging output from the driver.
+ 
+ config BFS_FS
+ 	tristate "BFS file system support (EXPERIMENTAL)"
+@@ -1268,7 +1263,7 @@ config JFFS2_FS_XATTR
+ 	  Extended attributes are name:value pairs associated with inodes by
+ 	  the kernel or by users (see the attr(5) manual page, or visit
+ 	  <http://acl.bestbits.at/> for details).
+-	  
++
+ 	  If unsure, say N.
+ 
+ config JFFS2_FS_POSIX_ACL
+@@ -1279,10 +1274,10 @@ config JFFS2_FS_POSIX_ACL
+ 	help
+ 	  Posix Access Control Lists (ACLs) support permissions for users and
+ 	  groups beyond the owner/group/world scheme.
+-	  
++
+ 	  To learn more about Access Control Lists, visit the Posix ACLs for
+ 	  Linux website <http://acl.bestbits.at/>.
+-	  
++
+ 	  If you don't know what Access Control Lists are, say N
+ 
+ config JFFS2_FS_SECURITY
+@@ -1294,7 +1289,7 @@ config JFFS2_FS_SECURITY
+ 	  implemented by security modules like SELinux.  This option
+ 	  enables an extended attribute handler for file security
+ 	  labels in the jffs2 filesystem.
+-	  
++
+ 	  If you are not using a security module that requires using
+ 	  extended attributes for file security labels, say N.
+ 
 @@ -1679,6 +1674,8 @@ config NFSD
  	select CRYPTO_MD5 if NFSD_V4
  	select CRYPTO if NFSD_V4
@@ -763813,6 +825493,35 @@
  	help
  	  If you want your Linux box to act as an NFS *server*, so that other
  	  computers on your local network which support NFS can access certain
+@@ -1838,7 +1835,7 @@ config RPCSEC_GSS_SPKM3
+ 	  If unsure, say N.
+ 
+ config SMB_FS
+-	tristate "SMB file system support (to mount Windows shares etc.)"
++	tristate "SMB file system support (OBSOLETE, please use CIFS)"
+ 	depends on INET
+ 	select NLS
+ 	help
+@@ -1861,8 +1858,8 @@ config SMB_FS
+ 	  General information about how to connect Linux, Windows machines and
+ 	  Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>.
+ 
+-	  To compile the SMB support as a module, choose M here: the module will
+-	  be called smbfs.  Most people say N, however.
++	  To compile the SMB support as a module, choose M here:
++	  the module will be called smbfs.  Most people say N, however.
+ 
+ config SMB_NLS_DEFAULT
+ 	bool "Use a default NLS"
+@@ -1894,7 +1891,7 @@ config SMB_NLS_REMOTE
+ 	  smbmount from samba 2.2.0 or later supports this.
+ 
+ config CIFS
+-	tristate "CIFS support (advanced network filesystem for Samba, Window and other CIFS compliant servers)"
++	tristate "CIFS support (advanced network filesystem, SMBFS successor)"
+ 	depends on INET
+ 	select NLS
+ 	help
 @@ -1905,13 +1902,15 @@ config CIFS
  	  file servers such as Windows 2000 (including Windows 2003, NT 4  
  	  and Windows XP) as well by Samba (which provides excellent CIFS
@@ -763836,7 +825545,7 @@
  	  If you need to mount to Samba or Windows from this machine, say Y.
  
  config CIFS_STATS
-@@ -1943,7 +1942,8 @@ config CIFS_WEAK_PW_HASH
+@@ -1943,22 +1942,23 @@ config CIFS_WEAK_PW_HASH
  	  (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
  	  security mechanisms. These hash the password more securely
  	  than the mechanisms used in the older LANMAN version of the
@@ -763846,9 +825555,10 @@
  
  	  Enabling this option allows the cifs module to mount to older
  	  LANMAN based servers such as OS/2 and Windows 95, but such
-@@ -1951,8 +1951,8 @@ config CIFS_WEAK_PW_HASH
+ 	  mounts may be less secure than mounts using NTLM or more recent
  	  security mechanisms if you are on a public network.  Unless you
- 	  have a need to access old SMB servers (and are on a private 
+-	  have a need to access old SMB servers (and are on a private 
++	  have a need to access old SMB servers (and are on a private
  	  network) you probably want to say N.  Even if this support
 -	  is enabled in the kernel build, they will not be used
 -	  automatically. At runtime LANMAN mounts are disabled but
@@ -763856,7 +825566,24 @@
 +	  used automatically. At runtime LANMAN mounts are disabled but
  	  can be set to required (or optional) either in
  	  /proc/fs/cifs (see fs/cifs/README for more detail) or via an
- 	  option on the mount command. This support is disabled by 
+-	  option on the mount command. This support is disabled by 
++	  option on the mount command. This support is disabled by
+ 	  default in order to reduce the possibility of a downgrade
+ 	  attack.
+- 
++
+ 	  If unsure, say N.
+ 
+ config CIFS_XATTR
+@@ -1999,7 +1999,7 @@ config CIFS_DEBUG2
+ 	   messages in some error paths, slowing performance. This
+ 	   option can be turned off unless you are debugging
+ 	   cifs problems.  If unsure, say N.
+-	   
++
+ config CIFS_EXPERIMENTAL
+ 	  bool "CIFS Experimental Features (EXPERIMENTAL)"
+ 	  depends on CIFS && EXPERIMENTAL
 @@ -2018,12 +2018,22 @@ config CIFS_UPCALL
  	  depends on CIFS_EXPERIMENTAL
  	  depends on KEYS
@@ -763883,6 +825610,15 @@
  config NCP_FS
  	tristate "NCP file system support (to mount NetWare volumes)"
  	depends on IPX!=n || INET
+@@ -2080,7 +2090,7 @@ config CODA_FS_OLD_API
+ 	  However this new API is not backward compatible with older
+ 	  clients. If you really need to run the old Coda userspace
+ 	  cache manager then say Y.
+-	  
++
+ 	  For most cases you probably want to say N.
+ 
+ config AFS_FS
 @@ -2130,4 +2140,3 @@ source "fs/nls/Kconfig"
  source "fs/dlm/Kconfig"
  
@@ -763973,8 +825709,34 @@
  static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
  {
  	struct kiocb *req = NULL;
+diff --git a/fs/befs/btree.c b/fs/befs/btree.c
+index af5bb93..4202db7 100644
+--- a/fs/befs/btree.c
++++ b/fs/befs/btree.c
+@@ -232,7 +232,7 @@ befs_bt_read_node(struct super_block *sb, befs_data_stream * ds,
+  * @key: Key string to lookup in btree
+  * @value: Value stored with @key
+  *
+- * On sucess, returns BEFS_OK and sets *@value to the value stored
++ * On success, returns BEFS_OK and sets *@value to the value stored
+  * with @key (usually the disk block number of an inode).
+  *
+  * On failure, returns BEFS_ERR or BEFS_BT_NOT_FOUND.
+diff --git a/fs/befs/datastream.c b/fs/befs/datastream.c
+index aacb4da..e3287d0 100644
+--- a/fs/befs/datastream.c
++++ b/fs/befs/datastream.c
+@@ -236,7 +236,7 @@ befs_count_blocks(struct super_block * sb, befs_data_stream * ds)
+ 	as in the indirect region code).
+ 	
+ 	When/if blockno is found, if blockno is inside of a block 
+-	run as stored on disk, we offset the start and lenght members 
++	run as stored on disk, we offset the start and length members
+ 	of the block run, so that blockno is the start and len is
+ 	still valid (the run ends in the same place).
+ 	
 diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
-index f0b3171..18ed6dd 100644
+index f0b3171..4628c42 100644
 --- a/fs/binfmt_elf.c
 +++ b/fs/binfmt_elf.c
 @@ -45,7 +45,8 @@
@@ -763987,6 +825749,15 @@
  
  /*
   * If we don't support core dumping, then supply a NULL so we
+@@ -116,7 +117,7 @@ static int padzero(unsigned long elf_bss)
+ 	return 0;
+ }
+ 
+-/* Let's use some macros to make this stack manipulation a litle clearer */
++/* Let's use some macros to make this stack manipulation a little clearer */
+ #ifdef CONFIG_STACK_GROWSUP
+ #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items))
+ #define STACK_ROUND(sp, items) \
 @@ -298,33 +299,70 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec,
  #ifndef elf_map
  
@@ -764947,10 +826718,140 @@
  		}
  		bdev->bd_disk = NULL;
 diff --git a/fs/buffer.c b/fs/buffer.c
-index 7249e01..456c9ab 100644
+index 7249e01..826baf4 100644
 --- a/fs/buffer.c
 +++ b/fs/buffer.c
-@@ -3213,6 +3213,50 @@ static int buffer_cpu_notify(struct notifier_block *self,
+@@ -1798,7 +1798,7 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to)
+ 					start = max(from, block_start);
+ 					size = min(to, block_end) - start;
+ 
+-					zero_user_page(page, start, size, KM_USER0);
++					zero_user(page, start, size);
+ 					set_buffer_uptodate(bh);
+ 				}
+ 
+@@ -1861,19 +1861,10 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
+ 					mark_buffer_dirty(bh);
+ 					continue;
+ 				}
+-				if (block_end > to || block_start < from) {
+-					void *kaddr;
+-
+-					kaddr = kmap_atomic(page, KM_USER0);
+-					if (block_end > to)
+-						memset(kaddr+to, 0,
+-							block_end-to);
+-					if (block_start < from)
+-						memset(kaddr+block_start,
+-							0, from-block_start);
+-					flush_dcache_page(page);
+-					kunmap_atomic(kaddr, KM_USER0);
+-				}
++				if (block_end > to || block_start < from)
++					zero_user_segments(page,
++						to, block_end,
++						block_start, from);
+ 				continue;
+ 			}
+ 		}
+@@ -2104,8 +2095,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
+ 					SetPageError(page);
+ 			}
+ 			if (!buffer_mapped(bh)) {
+-				zero_user_page(page, i * blocksize, blocksize,
+-						KM_USER0);
++				zero_user(page, i * blocksize, blocksize);
+ 				if (!err)
+ 					set_buffer_uptodate(bh);
+ 				continue;
+@@ -2218,7 +2208,7 @@ int cont_expand_zero(struct file *file, struct address_space *mapping,
+ 						&page, &fsdata);
+ 		if (err)
+ 			goto out;
+-		zero_user_page(page, zerofrom, len, KM_USER0);
++		zero_user(page, zerofrom, len);
+ 		err = pagecache_write_end(file, mapping, curpos, len, len,
+ 						page, fsdata);
+ 		if (err < 0)
+@@ -2245,7 +2235,7 @@ int cont_expand_zero(struct file *file, struct address_space *mapping,
+ 						&page, &fsdata);
+ 		if (err)
+ 			goto out;
+-		zero_user_page(page, zerofrom, len, KM_USER0);
++		zero_user(page, zerofrom, len);
+ 		err = pagecache_write_end(file, mapping, curpos, len, len,
+ 						page, fsdata);
+ 		if (err < 0)
+@@ -2422,7 +2412,6 @@ int nobh_write_begin(struct file *file, struct address_space *mapping,
+ 	unsigned block_in_page;
+ 	unsigned block_start, block_end;
+ 	sector_t block_in_file;
+-	char *kaddr;
+ 	int nr_reads = 0;
+ 	int ret = 0;
+ 	int is_mapped_to_disk = 1;
+@@ -2493,13 +2482,8 @@ int nobh_write_begin(struct file *file, struct address_space *mapping,
+ 			continue;
+ 		}
+ 		if (buffer_new(bh) || !buffer_mapped(bh)) {
+-			kaddr = kmap_atomic(page, KM_USER0);
+-			if (block_start < from)
+-				memset(kaddr+block_start, 0, from-block_start);
+-			if (block_end > to)
+-				memset(kaddr + to, 0, block_end - to);
+-			flush_dcache_page(page);
+-			kunmap_atomic(kaddr, KM_USER0);
++			zero_user_segments(page, block_start, from,
++							to, block_end);
+ 			continue;
+ 		}
+ 		if (buffer_uptodate(bh))
+@@ -2636,7 +2620,7 @@ int nobh_writepage(struct page *page, get_block_t *get_block,
+ 	 * the  page size, the remaining memory is zeroed when mapped, and
+ 	 * writes to that region are not written out to the file."
+ 	 */
+-	zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
++	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ out:
+ 	ret = mpage_writepage(page, get_block, wbc);
+ 	if (ret == -EAGAIN)
+@@ -2709,7 +2693,7 @@ has_buffers:
+ 		if (page_has_buffers(page))
+ 			goto has_buffers;
+ 	}
+-	zero_user_page(page, offset, length, KM_USER0);
++	zero_user(page, offset, length);
+ 	set_page_dirty(page);
+ 	err = 0;
+ 
+@@ -2785,7 +2769,7 @@ int block_truncate_page(struct address_space *mapping,
+ 			goto unlock;
+ 	}
+ 
+-	zero_user_page(page, offset, length, KM_USER0);
++	zero_user(page, offset, length);
+ 	mark_buffer_dirty(bh);
+ 	err = 0;
+ 
+@@ -2831,7 +2815,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block,
+ 	 * the  page size, the remaining memory is zeroed when mapped, and
+ 	 * writes to that region are not written out to the file."
+ 	 */
+-	zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
++	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ 	return __block_write_full_page(inode, page, get_block, wbc);
+ }
+ 
+@@ -3169,7 +3153,7 @@ static void recalc_bh_state(void)
+ 	
+ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags)
+ {
+-	struct buffer_head *ret = kmem_cache_zalloc(bh_cachep,
++	struct buffer_head *ret = kmem_cache_alloc(bh_cachep,
+ 				set_migrateflags(gfp_flags, __GFP_RECLAIMABLE));
+ 	if (ret) {
+ 		INIT_LIST_HEAD(&ret->b_assoc_buffers);
+@@ -3213,12 +3197,68 @@ static int buffer_cpu_notify(struct notifier_block *self,
  	return NOTIFY_OK;
  }
  
@@ -764998,9 +826899,29 @@
 +}
 +EXPORT_SYMBOL(bh_submit_read);
 +
++static void
++init_buffer_head(struct kmem_cache *cachep, void *data)
++{
++	struct buffer_head *bh = data;
++
++	memset(bh, 0, sizeof(*bh));
++	INIT_LIST_HEAD(&bh->b_assoc_buffers);
++}
++
  void __init buffer_init(void)
  {
  	int nrpages;
+ 
+-	bh_cachep = KMEM_CACHE(buffer_head,
+-			SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD);
++	bh_cachep = kmem_cache_create("buffer_head",
++			sizeof(struct buffer_head), 0,
++				(SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|
++				SLAB_MEM_SPREAD),
++				init_buffer_head);
+ 
+ 	/*
+ 	 * Limit the bh occupancy to 10% of ZONE_NORMAL
 diff --git a/fs/char_dev.c b/fs/char_dev.c
 index c3bfa76..2c7a8b5 100644
 --- a/fs/char_dev.c
@@ -766547,7 +828468,7 @@
  		cFYI(1, ("No writeable filehandles for inode"));
  		rc = -EIO;
 diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
-index e915eb1..d9567ba 100644
+index e915eb1..47f2621 100644
 --- a/fs/cifs/inode.c
 +++ b/fs/cifs/inode.c
 @@ -54,9 +54,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
@@ -766581,6 +828502,15 @@
  			kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
  		if (pInfo == NULL) {
  			rc = -ENOMEM;
+@@ -1385,7 +1386,7 @@ static int cifs_truncate_page(struct address_space *mapping, loff_t from)
+ 	if (!page)
+ 		return -ENOMEM;
+ 
+-	zero_user_page(page, offset, PAGE_CACHE_SIZE - offset, KM_USER0);
++	zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ 	unlock_page(page);
+ 	page_cache_release(page);
+ 	return rc;
 @@ -1607,7 +1608,14 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
  						CIFS_MOUNT_MAP_SPECIAL_CHR);
  	else if (attrs->ia_valid & ATTR_MODE) {
@@ -766735,7 +828665,7 @@
  	unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
  	coda_sysctl_clean();
 diff --git a/fs/compat.c b/fs/compat.c
-index 15078ce..5216c3f 100644
+index 15078ce..69baca5 100644
 --- a/fs/compat.c
 +++ b/fs/compat.c
 @@ -1104,10 +1104,6 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
@@ -766749,6 +828679,53 @@
  	fnv = NULL;
  	if (type == READ) {
  		fn = file->f_op->read;
+@@ -2210,19 +2206,41 @@ asmlinkage long compat_sys_signalfd(int ufd,
+ 
+ #ifdef CONFIG_TIMERFD
+ 
+-asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags,
+-				   const struct compat_itimerspec __user *utmr)
++asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
++				   const struct compat_itimerspec __user *utmr,
++				   struct compat_itimerspec __user *otmr)
+ {
++	int error;
+ 	struct itimerspec t;
+ 	struct itimerspec __user *ut;
+ 
+ 	if (get_compat_itimerspec(&t, utmr))
+ 		return -EFAULT;
+-	ut = compat_alloc_user_space(sizeof(*ut));
+-	if (copy_to_user(ut, &t, sizeof(t)))
++	ut = compat_alloc_user_space(2 * sizeof(struct itimerspec));
++	if (copy_to_user(&ut[0], &t, sizeof(t)))
+ 		return -EFAULT;
++	error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]);
++	if (!error && otmr)
++		error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) ||
++			 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
++
++	return error;
++}
++
++asmlinkage long compat_sys_timerfd_gettime(int ufd,
++				   struct compat_itimerspec __user *otmr)
++{
++	int error;
++	struct itimerspec t;
++	struct itimerspec __user *ut;
+ 
+-	return sys_timerfd(ufd, clockid, flags, ut);
++	ut = compat_alloc_user_space(sizeof(struct itimerspec));
++	error = sys_timerfd_gettime(ufd, ut);
++	if (!error)
++		error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) ||
++			 put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
++
++	return error;
+ }
+ 
+ #endif /* CONFIG_TIMERFD */
 diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c
 new file mode 100644
 index 0000000..0adced2
@@ -767026,6 +829003,21 @@
  }
  
  core_initcall(debugfs_init);
+diff --git a/fs/direct-io.c b/fs/direct-io.c
+index acf0da1..9e81add 100644
+--- a/fs/direct-io.c
++++ b/fs/direct-io.c
+@@ -878,8 +878,8 @@ do_holes:
+ 					page_cache_release(page);
+ 					goto out;
+ 				}
+-				zero_user_page(page, block_in_page << blkbits,
+-						1 << blkbits, KM_USER0);
++				zero_user(page, block_in_page << blkbits,
++						1 << blkbits);
+ 				dio->block_in_file++;
+ 				block_in_page++;
+ 				goto next_block;
 diff --git a/fs/dlm/dir.c b/fs/dlm/dir.c
 index 4675455..ff97ba9 100644
 --- a/fs/dlm/dir.c
@@ -768826,6 +830818,29 @@
  	rc = do_sysfs_registration();
  	if (rc) {
  		printk(KERN_ERR "sysfs registration failed\n");
+diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
+index 32c5711..0535412 100644
+--- a/fs/ecryptfs/mmap.c
++++ b/fs/ecryptfs/mmap.c
+@@ -257,8 +257,7 @@ static int fill_zeros_to_end_of_page(struct page *page, unsigned int to)
+ 	end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE;
+ 	if (to > end_byte_in_page)
+ 		end_byte_in_page = to;
+-	zero_user_page(page, end_byte_in_page,
+-		PAGE_CACHE_SIZE - end_byte_in_page, KM_USER0);
++	zero_user_segment(page, end_byte_in_page, PAGE_CACHE_SIZE);
+ out:
+ 	return 0;
+ }
+@@ -307,7 +306,7 @@ static int ecryptfs_prepare_write(struct file *file, struct page *page,
+ 	 */
+ 	if ((i_size_read(page->mapping->host) == prev_page_end_size) &&
+ 	    (from != 0)) {
+-		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
++		zero_user(page, 0, PAGE_CACHE_SIZE);
+ 	}
+ out:
+ 	return rc;
 diff --git a/fs/ecryptfs/netlink.c b/fs/ecryptfs/netlink.c
 index 9aa3451..f638a69 100644
 --- a/fs/ecryptfs/netlink.c
@@ -768840,9 +830855,18 @@
  	ecryptfs_nl_sock = NULL;
  }
 diff --git a/fs/eventpoll.c b/fs/eventpoll.c
-index 34f68f3..81c04ab 100644
+index 34f68f3..a415f42 100644
 --- a/fs/eventpoll.c
 +++ b/fs/eventpoll.c
+@@ -353,7 +353,7 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq)
+ 	spin_unlock_irqrestore(&psw->lock, flags);
+ 
+ 	/* Do really wake up now */
+-	wake_up(wq);
++	wake_up_nested(wq, 1 + wake_nests);
+ 
+ 	/* Remove the current task from the list */
+ 	spin_lock_irqsave(&psw->lock, flags);
 @@ -656,8 +656,7 @@ is_linked:
  	 * wait list.
  	 */
@@ -768882,6 +830906,76 @@
  		if (waitqueue_active(&ep->poll_wait))
  			pwake++;
  	}
+diff --git a/fs/exec.c b/fs/exec.c
+index 282240a..be923e4 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -760,7 +760,7 @@ static int de_thread(struct task_struct *tsk)
+ 	 */
+ 	read_lock(&tasklist_lock);
+ 	spin_lock_irq(lock);
+-	if (sig->flags & SIGNAL_GROUP_EXIT) {
++	if (signal_group_exit(sig)) {
+ 		/*
+ 		 * Another group action in progress, just
+ 		 * return so that the signal is processed.
+@@ -778,6 +778,7 @@ static int de_thread(struct task_struct *tsk)
+ 	if (unlikely(tsk->group_leader == task_child_reaper(tsk)))
+ 		task_active_pid_ns(tsk)->child_reaper = tsk;
+ 
++	sig->group_exit_task = tsk;
+ 	zap_other_threads(tsk);
+ 	read_unlock(&tasklist_lock);
+ 
+@@ -802,7 +803,6 @@ static int de_thread(struct task_struct *tsk)
+ 	}
+ 
+ 	sig->notify_count = count;
+-	sig->group_exit_task = tsk;
+ 	while (atomic_read(&sig->count) > count) {
+ 		__set_current_state(TASK_UNINTERRUPTIBLE);
+ 		spin_unlock_irq(lock);
+@@ -871,15 +871,10 @@ static int de_thread(struct task_struct *tsk)
+ 		leader->exit_state = EXIT_DEAD;
+ 
+ 		write_unlock_irq(&tasklist_lock);
+-        }
++	}
+ 
+ 	sig->group_exit_task = NULL;
+ 	sig->notify_count = 0;
+-	/*
+-	 * There may be one thread left which is just exiting,
+-	 * but it's safe to stop telling the group to kill themselves.
+-	 */
+-	sig->flags = 0;
+ 
+ no_thread_group:
+ 	exit_itimers(sig);
+@@ -947,12 +942,13 @@ static void flush_old_files(struct files_struct * files)
+ 	spin_unlock(&files->file_lock);
+ }
+ 
+-void get_task_comm(char *buf, struct task_struct *tsk)
++char *get_task_comm(char *buf, struct task_struct *tsk)
+ {
+ 	/* buf must be at least sizeof(tsk->comm) in size */
+ 	task_lock(tsk);
+ 	strncpy(buf, tsk->comm, sizeof(tsk->comm));
+ 	task_unlock(tsk);
++	return buf;
+ }
+ 
+ void set_task_comm(struct task_struct *tsk, char *buf)
+@@ -1548,7 +1544,7 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
+ 	int err = -EAGAIN;
+ 
+ 	spin_lock_irq(&tsk->sighand->siglock);
+-	if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) {
++	if (!signal_group_exit(tsk->signal)) {
+ 		tsk->signal->group_exit_code = exit_code;
+ 		zap_process(tsk);
+ 		err = 0;
 diff --git a/fs/ext2/super.c b/fs/ext2/super.c
 index 154e25f..6abaf75 100644
 --- a/fs/ext2/super.c
@@ -768933,6 +831027,28 @@
  	return res;
  }
  
+diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
+index 9b162cd..0775354 100644
+--- a/fs/ext3/inode.c
++++ b/fs/ext3/inode.c
+@@ -1845,7 +1845,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
+ 	 */
+ 	if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
+ 	     ext3_should_writeback_data(inode) && PageUptodate(page)) {
+-		zero_user_page(page, offset, length, KM_USER0);
++		zero_user(page, offset, length);
+ 		set_page_dirty(page);
+ 		goto unlock;
+ 	}
+@@ -1898,7 +1898,7 @@ static int ext3_block_truncate_page(handle_t *handle, struct page *page,
+ 			goto unlock;
+ 	}
+ 
+-	zero_user_page(page, offset, length, KM_USER0);
++	zero_user(page, offset, length);
+ 	BUFFER_TRACE(bh, "zeroed end of block");
+ 
+ 	err = 0;
 diff --git a/fs/ext3/super.c b/fs/ext3/super.c
 index cb14de1..f3675cc 100644
 --- a/fs/ext3/super.c
@@ -770918,7 +833034,7 @@
  	for (i = 0; i < EXT4_SB(sb)->s_groups_count; i++) {
  		struct ext4_group_desc *gdp = ext4_get_group_desc (sb, i, NULL);
 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
-index 5489703..bb717cb 100644
+index 5489703..05c4145 100644
 --- a/fs/ext4/inode.c
 +++ b/fs/ext4/inode.c
 @@ -105,7 +105,7 @@ int ext4_forget(handle_t *handle, int is_metadata, struct inode *inode,
@@ -771263,6 +833379,24 @@
  	struct inode *inode = mapping->host;
  	struct buffer_head *bh;
  	int err = 0;
+@@ -1843,7 +1840,7 @@ int ext4_block_truncate_page(handle_t *handle, struct page *page,
+ 	 */
+ 	if (!page_has_buffers(page) && test_opt(inode->i_sb, NOBH) &&
+ 	     ext4_should_writeback_data(inode) && PageUptodate(page)) {
+-		zero_user_page(page, offset, length, KM_USER0);
++		zero_user(page, offset, length);
+ 		set_page_dirty(page);
+ 		goto unlock;
+ 	}
+@@ -1896,7 +1893,7 @@ int ext4_block_truncate_page(handle_t *handle, struct page *page,
+ 			goto unlock;
+ 	}
+ 
+-	zero_user_page(page, offset, length, KM_USER0);
++	zero_user(page, offset, length);
+ 
+ 	BUFFER_TRACE(bh, "zeroed end of block");
+ 
 @@ -1964,7 +1961,7 @@ static inline int all_zeroes(__le32 *p, __le32 *q)
   *			(no partially truncated stuff there).  */
  
@@ -778067,6 +840201,96 @@
  				error = -EIO;
  				goto cleanup;
  			}
+diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h
+index 3c96d6e..aaf1fb0 100644
+--- a/fs/freevxfs/vxfs_dir.h
++++ b/fs/freevxfs/vxfs_dir.h
+@@ -41,7 +41,7 @@
+  * VxFS directory block header.
+  *
+  * This entry is the head of every filesystem block in a directory.
+- * It is used for free space managment and additionally includes
++ * It is used for free space management and additionally includes
+  * a hash for speeding up directory search (lookup).
+  *
+  * The hash may be empty and in fact we do not use it all in the
+diff --git a/fs/freevxfs/vxfs_immed.c b/fs/freevxfs/vxfs_immed.c
+index 24b5a77..8a5959a 100644
+--- a/fs/freevxfs/vxfs_immed.c
++++ b/fs/freevxfs/vxfs_immed.c
+@@ -54,7 +54,7 @@ const struct inode_operations vxfs_immed_symlink_iops = {
+ };
+ 
+ /*
+- * Adress space operations for immed files and directories.
++ * Address space operations for immed files and directories.
+  */
+ const struct address_space_operations vxfs_immed_aops = {
+ 	.readpage =		vxfs_immed_readpage,
+diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
+index 300324b..0b30640 100644
+--- a/fs/fs-writeback.c
++++ b/fs/fs-writeback.c
+@@ -284,7 +284,17 @@ __sync_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 				 * soon as the queue becomes uncongested.
+ 				 */
+ 				inode->i_state |= I_DIRTY_PAGES;
+-				requeue_io(inode);
++				if (wbc->nr_to_write <= 0) {
++					/*
++					 * slice used up: queue for next turn
++					 */
++					requeue_io(inode);
++				} else {
++					/*
++					 * somehow blocked: retry later
++					 */
++					redirty_tail(inode);
++				}
+ 			} else {
+ 				/*
+ 				 * Otherwise fully redirty the inode so that
+@@ -334,9 +344,6 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 		WARN_ON(inode->i_state & I_WILL_FREE);
+ 
+ 	if ((wbc->sync_mode != WB_SYNC_ALL) && (inode->i_state & I_SYNC)) {
+-		struct address_space *mapping = inode->i_mapping;
+-		int ret;
+-
+ 		/*
+ 		 * We're skipping this inode because it's locked, and we're not
+ 		 * doing writeback-for-data-integrity.  Move it to s_more_io so
+@@ -345,15 +352,7 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
+ 		 * completed a full scan of s_io.
+ 		 */
+ 		requeue_io(inode);
+-
+-		/*
+-		 * Even if we don't actually write the inode itself here,
+-		 * we can at least start some of the data writeout..
+-		 */
+-		spin_unlock(&inode_lock);
+-		ret = do_writepages(mapping, wbc);
+-		spin_lock(&inode_lock);
+-		return ret;
++		return 0;
+ 	}
+ 
+ 	/*
+@@ -479,8 +478,12 @@ sync_sb_inodes(struct super_block *sb, struct writeback_control *wbc)
+ 		iput(inode);
+ 		cond_resched();
+ 		spin_lock(&inode_lock);
+-		if (wbc->nr_to_write <= 0)
++		if (wbc->nr_to_write <= 0) {
++			wbc->more_io = 1;
+ 			break;
++		}
++		if (!list_empty(&sb->s_more_io))
++			wbc->more_io = 1;
+ 	}
+ 	return;		/* Leave any unwritten inodes on s_io */
+ }
 diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
 index 84f9f7d..e5e80d1 100644
 --- a/fs/fuse/inode.c
@@ -778142,7 +840366,7 @@
  
  obj-$(CONFIG_GFS2_FS_LOCKING_NOLOCK) += locking/nolock/
 diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
-index 93fa427..e4effc4 100644
+index 93fa427..e9456eb 100644
 --- a/fs/gfs2/bmap.c
 +++ b/fs/gfs2/bmap.c
 @@ -59,7 +59,6 @@ struct strip_mine {
@@ -778259,7 +840483,7 @@
  		/* unmapped? It's a hole - nothing to do */
  		if (!buffer_mapped(bh))
  			goto unlock;
-@@ -931,7 +929,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
+@@ -931,10 +929,10 @@ static int gfs2_block_truncate_page(struct address_space *mapping)
  		err = 0;
  	}
  
@@ -778267,7 +840491,11 @@
 +	if (!gfs2_is_writeback(ip))
  		gfs2_trans_add_bh(ip->i_gl, bh, 0);
  
- 	zero_user_page(page, offset, length, KM_USER0);
+-	zero_user_page(page, offset, length, KM_USER0);
++	zero_user(page, offset, length);
+ 
+ unlock:
+ 	unlock_page(page);
 @@ -1224,8 +1222,13 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
  		do_div(lblock_stop, bsize);
  	} else {
@@ -780060,7 +842288,7 @@
  			      int new, struct buffer_head **bhp);
  
 diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
-index 9679f8b..38dbe99 100644
+index 9679f8b..ac772b6 100644
 --- a/fs/gfs2/ops_address.c
 +++ b/fs/gfs2/ops_address.c
 @@ -20,6 +20,8 @@
@@ -780495,6 +842723,15 @@
  }
  
  /**
+@@ -209,7 +446,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
+ 	 * so we need to supply one here. It doesn't happen often.
+ 	 */
+ 	if (unlikely(page->index)) {
+-		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
++		zero_user(page, 0, PAGE_CACHE_SIZE);
+ 		return 0;
+ 	}
+ 
 @@ -231,62 +468,107 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page)
  
  
@@ -781831,7 +844068,7 @@
  	}
  }
 diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
-index beb6c7a..b249e29 100644
+index beb6c7a..6fb07d6 100644
 --- a/fs/gfs2/recovery.c
 +++ b/fs/gfs2/recovery.c
 @@ -391,7 +391,7 @@ static int clean_journal(struct gfs2_jdesc *jd, struct gfs2_log_header_host *hea
@@ -781843,6 +844080,15 @@
  	if (error)
  		return error;
  	if (!bh_map.b_blocknr) {
+@@ -450,7 +450,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
+ 		fs_info(sdp, "jid=%u: Trying to acquire journal lock...\n",
+ 			jd->jd_jid);
+ 
+-		/* Aquire the journal lock so we can do recovery */
++		/* Acquire the journal lock so we can do recovery */
+ 
+ 		error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops,
+ 					  LM_ST_EXCLUSIVE,
 @@ -504,13 +504,21 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
  			if (!test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags))
  				ro = 1;
@@ -782359,6 +844605,45 @@
  void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta);
  void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
  void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno);
+diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
+index 35c1a9f..53fd0a6 100644
+--- a/fs/hostfs/hostfs_user.c
++++ b/fs/hostfs/hostfs_user.c
+@@ -285,17 +285,17 @@ int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
+ 			return err;
+ 
+ 		times[0].tv_sec = atime_ts.tv_sec;
+-		times[0].tv_usec = atime_ts.tv_nsec * 1000;
++		times[0].tv_usec = atime_ts.tv_nsec / 1000;
+ 		times[1].tv_sec = mtime_ts.tv_sec;
+-		times[1].tv_usec = mtime_ts.tv_nsec * 1000;
++		times[1].tv_usec = mtime_ts.tv_nsec / 1000;
+ 
+ 		if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) {
+ 			times[0].tv_sec = attrs->ia_atime.tv_sec;
+-			times[0].tv_usec = attrs->ia_atime.tv_nsec * 1000;
++			times[0].tv_usec = attrs->ia_atime.tv_nsec / 1000;
+ 		}
+ 		if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) {
+ 			times[1].tv_sec = attrs->ia_mtime.tv_sec;
+-			times[1].tv_usec = attrs->ia_mtime.tv_nsec * 1000;
++			times[1].tv_usec = attrs->ia_mtime.tv_nsec / 1000;
+ 		}
+ 
+ 		if (fd >= 0) {
+diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
+index 09ee07f..3b3cc28 100644
+--- a/fs/hugetlbfs/inode.c
++++ b/fs/hugetlbfs/inode.c
+@@ -768,7 +768,7 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig)
+ 		case Opt_mode:
+ 			if (match_octal(&args[0], &option))
+  				goto bad_val;
+-			pconfig->mode = option & 0777U;
++			pconfig->mode = option & 01777U;
+ 			break;
+ 
+ 		case Opt_size: {
 diff --git a/fs/inode.c b/fs/inode.c
 index ed35383..276ffd6 100644
 --- a/fs/inode.c
@@ -783761,6 +846046,19 @@
  
  	if (jh->b_transaction && jh->b_jlist == jlist)
  		return;
+diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
+index 2eae5d2..6c1ba35 100644
+--- a/fs/jffs2/readinode.c
++++ b/fs/jffs2/readinode.c
+@@ -741,7 +741,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
+ 			 * are not obsolete.
+ 			 *
+ 			 * Of course, this optimization only makes sense in case
+-			 * of NAND flashes (or other flashes whith
++			 * of NAND flashes (or other flashes with
+ 			 * !jffs2_can_mark_obsolete()), since on NOR flashes
+ 			 * nodes are marked obsolete physically.
+ 			 *
 diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
 index df25ecc..4dcc058 100644
 --- a/fs/jfs/jfs_dtree.c
@@ -784160,6 +846458,19 @@
  
  	/*
  	 * Make sure all metadata makes it to disk
+diff --git a/fs/jfs/jfs_xtree.c b/fs/jfs/jfs_xtree.c
+index 1543906..a000aaa 100644
+--- a/fs/jfs/jfs_xtree.c
++++ b/fs/jfs/jfs_xtree.c
+@@ -3965,7 +3965,7 @@ s64 xtTruncate(tid_t tid, struct inode *ip, s64 newsize, int flag)
+  *	xtTruncate_pmap()
+  *
+  * function:
+- *	Perform truncate to zero lenghth for deleted file, leaving the
++ *	Perform truncate to zero length for deleted file, leaving the
+  *	the xtree and working map untouched.  This allows the file to
+  *	be accessed via open file handles, while the delete of the file
+  *	is committed to disk.
 diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
 index 4e0a849..f8718de 100644
 --- a/fs/jfs/namei.c
@@ -784205,6 +846516,28 @@
  
  #ifdef CONFIG_QUOTA
  	if (sbi->flag & JFS_USRQUOTA)
+diff --git a/fs/libfs.c b/fs/libfs.c
+index 6e68b70..5523bde 100644
+--- a/fs/libfs.c
++++ b/fs/libfs.c
+@@ -341,13 +341,10 @@ int simple_prepare_write(struct file *file, struct page *page,
+ 			unsigned from, unsigned to)
+ {
+ 	if (!PageUptodate(page)) {
+-		if (to - from != PAGE_CACHE_SIZE) {
+-			void *kaddr = kmap_atomic(page, KM_USER0);
+-			memset(kaddr, 0, from);
+-			memset(kaddr + to, 0, PAGE_CACHE_SIZE - to);
+-			flush_dcache_page(page);
+-			kunmap_atomic(kaddr, KM_USER0);
+-		}
++		if (to - from != PAGE_CACHE_SIZE)
++			zero_user_segments(page,
++				0, from,
++				to, PAGE_CACHE_SIZE);
+ 	}
+ 	return 0;
+ }
 diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
 index d070b18..0b45fd3 100644
 --- a/fs/lockd/clntlock.c
@@ -784687,6 +847020,249 @@
  	char *p = buf;
  
  	len--;	/* allow for trailing \0 */
+diff --git a/fs/locks.c b/fs/locks.c
+index 8b8388e..49354b9 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -125,6 +125,7 @@
+ #include <linux/syscalls.h>
+ #include <linux/time.h>
+ #include <linux/rcupdate.h>
++#include <linux/pid_namespace.h>
+ 
+ #include <asm/semaphore.h>
+ #include <asm/uaccess.h>
+@@ -185,6 +186,7 @@ void locks_init_lock(struct file_lock *fl)
+ 	fl->fl_fasync = NULL;
+ 	fl->fl_owner = NULL;
+ 	fl->fl_pid = 0;
++	fl->fl_nspid = NULL;
+ 	fl->fl_file = NULL;
+ 	fl->fl_flags = 0;
+ 	fl->fl_type = 0;
+@@ -553,6 +555,8 @@ static void locks_insert_lock(struct file_lock **pos, struct file_lock *fl)
+ {
+ 	list_add(&fl->fl_link, &file_lock_list);
+ 
++	fl->fl_nspid = get_pid(task_tgid(current));
++
+ 	/* insert into file's list */
+ 	fl->fl_next = *pos;
+ 	*pos = fl;
+@@ -584,6 +588,11 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
+ 	if (fl->fl_ops && fl->fl_ops->fl_remove)
+ 		fl->fl_ops->fl_remove(fl);
+ 
++	if (fl->fl_nspid) {
++		put_pid(fl->fl_nspid);
++		fl->fl_nspid = NULL;
++	}
++
+ 	locks_wake_up_blocks(fl);
+ 	locks_free_lock(fl);
+ }
+@@ -634,33 +643,6 @@ static int flock_locks_conflict(struct file_lock *caller_fl, struct file_lock *s
+ 	return (locks_conflict(caller_fl, sys_fl));
+ }
+ 
+-static int interruptible_sleep_on_locked(wait_queue_head_t *fl_wait, int timeout)
+-{
+-	int result = 0;
+-	DECLARE_WAITQUEUE(wait, current);
+-
+-	__set_current_state(TASK_INTERRUPTIBLE);
+-	add_wait_queue(fl_wait, &wait);
+-	if (timeout == 0)
+-		schedule();
+-	else
+-		result = schedule_timeout(timeout);
+-	if (signal_pending(current))
+-		result = -ERESTARTSYS;
+-	remove_wait_queue(fl_wait, &wait);
+-	__set_current_state(TASK_RUNNING);
+-	return result;
+-}
+-
+-static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *waiter, int time)
+-{
+-	int result;
+-	locks_insert_block(blocker, waiter);
+-	result = interruptible_sleep_on_locked(&waiter->fl_wait, time);
+-	__locks_delete_block(waiter);
+-	return result;
+-}
+-
+ void
+ posix_test_lock(struct file *filp, struct file_lock *fl)
+ {
+@@ -673,55 +655,67 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
+ 		if (posix_locks_conflict(fl, cfl))
+ 			break;
+ 	}
+-	if (cfl)
++	if (cfl) {
+ 		__locks_copy_lock(fl, cfl);
+-	else
++		if (cfl->fl_nspid)
++			fl->fl_pid = pid_nr_ns(cfl->fl_nspid,
++						task_active_pid_ns(current));
++	} else
+ 		fl->fl_type = F_UNLCK;
+ 	unlock_kernel();
+ 	return;
+ }
+-
+ EXPORT_SYMBOL(posix_test_lock);
+ 
+-/* This function tests for deadlock condition before putting a process to
+- * sleep. The detection scheme is no longer recursive. Recursive was neat,
+- * but dangerous - we risked stack corruption if the lock data was bad, or
+- * if the recursion was too deep for any other reason.
++/*
++ * Deadlock detection:
++ *
++ * We attempt to detect deadlocks that are due purely to posix file
++ * locks.
+  *
+- * We rely on the fact that a task can only be on one lock's wait queue
+- * at a time. When we find blocked_task on a wait queue we can re-search
+- * with blocked_task equal to that queue's owner, until either blocked_task
+- * isn't found, or blocked_task is found on a queue owned by my_task.
++ * We assume that a task can be waiting for at most one lock at a time.
++ * So for any acquired lock, the process holding that lock may be
++ * waiting on at most one other lock.  That lock in turns may be held by
++ * someone waiting for at most one other lock.  Given a requested lock
++ * caller_fl which is about to wait for a conflicting lock block_fl, we
++ * follow this chain of waiters to ensure we are not about to create a
++ * cycle.
+  *
+- * Note: the above assumption may not be true when handling lock requests
+- * from a broken NFS client. But broken NFS clients have a lot more to
+- * worry about than proper deadlock detection anyway... --okir
++ * Since we do this before we ever put a process to sleep on a lock, we
++ * are ensured that there is never a cycle; that is what guarantees that
++ * the while() loop in posix_locks_deadlock() eventually completes.
+  *
+- * However, the failure of this assumption (also possible in the case of
+- * multiple tasks sharing the same open file table) also means there's no
+- * guarantee that the loop below will terminate.  As a hack, we give up
+- * after a few iterations.
++ * Note: the above assumption may not be true when handling lock
++ * requests from a broken NFS client. It may also fail in the presence
++ * of tasks (such as posix threads) sharing the same open file table.
++ *
++ * To handle those cases, we just bail out after a few iterations.
+  */
+ 
+ #define MAX_DEADLK_ITERATIONS 10
+ 
++/* Find a lock that the owner of the given block_fl is blocking on. */
++static struct file_lock *what_owner_is_waiting_for(struct file_lock *block_fl)
++{
++	struct file_lock *fl;
++
++	list_for_each_entry(fl, &blocked_list, fl_link) {
++		if (posix_same_owner(fl, block_fl))
++			return fl->fl_next;
++	}
++	return NULL;
++}
++
+ static int posix_locks_deadlock(struct file_lock *caller_fl,
+ 				struct file_lock *block_fl)
+ {
+-	struct file_lock *fl;
+ 	int i = 0;
+ 
+-next_task:
+-	if (posix_same_owner(caller_fl, block_fl))
+-		return 1;
+-	list_for_each_entry(fl, &blocked_list, fl_link) {
+-		if (posix_same_owner(fl, block_fl)) {
+-			if (i++ > MAX_DEADLK_ITERATIONS)
+-				return 0;
+-			fl = fl->fl_next;
+-			block_fl = fl;
+-			goto next_task;
+-		}
++	while ((block_fl = what_owner_is_waiting_for(block_fl))) {
++		if (i++ > MAX_DEADLK_ITERATIONS)
++			return 0;
++		if (posix_same_owner(caller_fl, block_fl))
++			return 1;
+ 	}
+ 	return 0;
+ }
+@@ -1256,7 +1250,10 @@ restart:
+ 		if (break_time == 0)
+ 			break_time++;
+ 	}
+-	error = locks_block_on_timeout(flock, new_fl, break_time);
++	locks_insert_block(flock, new_fl);
++	error = wait_event_interruptible_timeout(new_fl->fl_wait,
++						!new_fl->fl_next, break_time);
++	__locks_delete_block(new_fl);
+ 	if (error >= 0) {
+ 		if (error == 0)
+ 			time_out_leases(inode);
+@@ -2084,6 +2081,12 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
+ 							int id, char *pfx)
+ {
+ 	struct inode *inode = NULL;
++	unsigned int fl_pid;
++
++	if (fl->fl_nspid)
++		fl_pid = pid_nr_ns(fl->fl_nspid, task_active_pid_ns(current));
++	else
++		fl_pid = fl->fl_pid;
+ 
+ 	if (fl->fl_file != NULL)
+ 		inode = fl->fl_file->f_path.dentry->d_inode;
+@@ -2124,16 +2127,16 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
+ 	}
+ 	if (inode) {
+ #ifdef WE_CAN_BREAK_LSLK_NOW
+-		seq_printf(f, "%d %s:%ld ", fl->fl_pid,
++		seq_printf(f, "%d %s:%ld ", fl_pid,
+ 				inode->i_sb->s_id, inode->i_ino);
+ #else
+ 		/* userspace relies on this representation of dev_t ;-( */
+-		seq_printf(f, "%d %02x:%02x:%ld ", fl->fl_pid,
++		seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
+ 				MAJOR(inode->i_sb->s_dev),
+ 				MINOR(inode->i_sb->s_dev), inode->i_ino);
+ #endif
+ 	} else {
+-		seq_printf(f, "%d <none>:0 ", fl->fl_pid);
++		seq_printf(f, "%d <none>:0 ", fl_pid);
+ 	}
+ 	if (IS_POSIX(fl)) {
+ 		if (fl->fl_end == OFFSET_MAX)
+diff --git a/fs/mpage.c b/fs/mpage.c
+index d54f8f8..5df5643 100644
+--- a/fs/mpage.c
++++ b/fs/mpage.c
+@@ -276,9 +276,7 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages,
+ 	}
+ 
+ 	if (first_hole != blocks_per_page) {
+-		zero_user_page(page, first_hole << blkbits,
+-				PAGE_CACHE_SIZE - (first_hole << blkbits),
+-				KM_USER0);
++		zero_user_segment(page, first_hole << blkbits, PAGE_CACHE_SIZE);
+ 		if (first_hole == 0) {
+ 			SetPageUptodate(page);
+ 			unlock_page(page);
+@@ -571,8 +569,7 @@ page_is_mapped:
+ 
+ 		if (page->index > end_index || !offset)
+ 			goto confused;
+-		zero_user_page(page, offset, PAGE_CACHE_SIZE - offset,
+-				KM_USER0);
++		zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ 	}
+ 
+ 	/*
 diff --git a/fs/namespace.c b/fs/namespace.c
 index 0608388..61bf376 100644
 --- a/fs/namespace.c
@@ -784716,6 +847292,21 @@
  	init_rootfs();
  	init_mount_tree();
  }
+diff --git a/fs/ncpfs/mmap.c b/fs/ncpfs/mmap.c
+index a94473d..5d8dcb9 100644
+--- a/fs/ncpfs/mmap.c
++++ b/fs/ncpfs/mmap.c
+@@ -50,10 +50,6 @@ static int ncp_file_mmap_fault(struct vm_area_struct *area,
+ 	pos = vmf->pgoff << PAGE_SHIFT;
+ 
+ 	count = PAGE_SIZE;
+-	if ((unsigned long)vmf->virtual_address + PAGE_SIZE > area->vm_end) {
+-		WARN_ON(1); /* shouldn't happen? */
+-		count = area->vm_end - (unsigned long)vmf->virtual_address;
+-	}
+ 	/* what we can read in one go */
+ 	bufsize = NCP_SERVER(inode)->buffer_size;
+ 
 diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
 index a796be5..bd185a5 100644
 --- a/fs/nfs/callback.c
@@ -788091,9 +850682,40 @@
  
  
 diff --git a/fs/nfs/read.c b/fs/nfs/read.c
-index 4587a86..8fd6dfb 100644
+index 4587a86..3d7d963 100644
 --- a/fs/nfs/read.c
 +++ b/fs/nfs/read.c
+@@ -79,7 +79,7 @@ void nfs_readdata_release(void *data)
+ static
+ int nfs_return_empty_page(struct page *page)
+ {
+-	zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
++	zero_user(page, 0, PAGE_CACHE_SIZE);
+ 	SetPageUptodate(page);
+ 	unlock_page(page);
+ 	return 0;
+@@ -103,10 +103,10 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
+ 	pglen = PAGE_CACHE_SIZE - base;
+ 	for (;;) {
+ 		if (remainder <= pglen) {
+-			zero_user_page(*pages, base, remainder, KM_USER0);
++			zero_user(*pages, base, remainder);
+ 			break;
+ 		}
+-		zero_user_page(*pages, base, pglen, KM_USER0);
++		zero_user(*pages, base, pglen);
+ 		pages++;
+ 		remainder -= pglen;
+ 		pglen = PAGE_CACHE_SIZE;
+@@ -130,7 +130,7 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
+ 		return PTR_ERR(new);
+ 	}
+ 	if (len < PAGE_CACHE_SIZE)
+-		zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
++		zero_user_segment(page, len, PAGE_CACHE_SIZE);
+ 
+ 	nfs_list_add_request(new, &one_request);
+ 	if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
 @@ -160,12 +160,26 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
  		const struct rpc_call_ops *call_ops,
  		unsigned int count, unsigned int offset)
@@ -788195,6 +850817,15 @@
  		nfs_mark_for_revalidate(data->inode);
  	}
  	return 0;
+@@ -534,7 +532,7 @@ readpage_async_filler(void *data, struct page *page)
+ 		goto out_error;
+ 
+ 	if (len < PAGE_CACHE_SIZE)
+-		zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);
++		zero_user_segment(page, len, PAGE_CACHE_SIZE);
+ 	nfs_pageio_add_request(desc->pgio, new);
+ 	return 0;
+ out_error:
 diff --git a/fs/nfs/super.c b/fs/nfs/super.c
 index 0b0c72a..7f4505f 100644
 --- a/fs/nfs/super.c
@@ -788892,7 +851523,7 @@
  		rpc_put_task(task);
  	return 1;
 diff --git a/fs/nfs/write.c b/fs/nfs/write.c
-index 51cc1bd..522efff 100644
+index 51cc1bd..b144b19 100644
 --- a/fs/nfs/write.c
 +++ b/fs/nfs/write.c
 @@ -196,7 +196,7 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
@@ -788978,7 +851609,18 @@
  		return ERR_PTR(-EBUSY);
  	}
  
-@@ -755,7 +753,7 @@ static void nfs_writepage_release(struct nfs_page *req)
+@@ -667,9 +665,7 @@ zero_page:
+ 	 * then we need to zero any uninitalised data. */
+ 	if (req->wb_pgbase == 0 && req->wb_bytes != PAGE_CACHE_SIZE
+ 			&& !PageUptodate(req->wb_page))
+-		zero_user_page(req->wb_page, req->wb_bytes,
+-				PAGE_CACHE_SIZE - req->wb_bytes,
+-				KM_USER0);
++		zero_user_segment(req->wb_page, req->wb_bytes, PAGE_CACHE_SIZE);
+ 	return req;
+ }
+ 
+@@ -755,7 +751,7 @@ static void nfs_writepage_release(struct nfs_page *req)
  	nfs_clear_page_tag_locked(req);
  }
  
@@ -788987,7 +851629,7 @@
  {
  	switch (how & (FLUSH_HIGHPRI|FLUSH_LOWPRI)) {
  		case FLUSH_HIGHPRI:
-@@ -775,15 +773,31 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+@@ -775,15 +771,31 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
  		unsigned int count, unsigned int offset,
  		int how)
  {
@@ -789022,7 +851664,7 @@
  
  	data->args.fh     = NFS_FH(inode);
  	data->args.offset = req_offset(req) + offset;
-@@ -791,6 +805,12 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+@@ -791,6 +803,12 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
  	data->args.pages  = data->pagevec;
  	data->args.count  = count;
  	data->args.context = req->wb_context;
@@ -789035,7 +851677,7 @@
  
  	data->res.fattr   = &data->fattr;
  	data->res.count   = count;
-@@ -798,12 +818,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+@@ -798,12 +816,7 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
  	nfs_fattr_init(&data->fattr);
  
  	/* Set up the initial task struct.  */
@@ -789049,7 +851691,7 @@
  
  	dprintk("NFS: %5u initiated write call "
  		"(req %s/%Ld, %u bytes @ offset %Lu)\n",
-@@ -812,16 +827,10 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
+@@ -812,16 +825,10 @@ static void nfs_write_rpcsetup(struct nfs_page *req,
  		(long long)NFS_FILEID(inode),
  		count,
  		(unsigned long long)data->args.offset);
@@ -789069,7 +851711,7 @@
  }
  
  /*
-@@ -868,7 +877,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
+@@ -868,7 +875,6 @@ static int nfs_flush_multi(struct inode *inode, struct list_head *head, unsigned
  				   wsize, offset, how);
  		offset += wsize;
  		nbytes -= wsize;
@@ -789077,7 +851719,7 @@
  	} while (nbytes != 0);
  
  	return 0;
-@@ -916,7 +924,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
+@@ -916,7 +922,6 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
  	/* Set up the argument struct */
  	nfs_write_rpcsetup(req, data, &nfs_write_full_ops, count, 0, how);
  
@@ -789085,7 +851727,7 @@
  	return 0;
   out_bad:
  	while (!list_empty(head)) {
-@@ -932,7 +939,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
+@@ -932,7 +937,7 @@ static int nfs_flush_one(struct inode *inode, struct list_head *head, unsigned i
  static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
  				  struct inode *inode, int ioflags)
  {
@@ -789094,7 +851736,7 @@
  
  	if (wsize < PAGE_CACHE_SIZE)
  		nfs_pageio_init(pgio, inode, nfs_flush_multi, wsize, ioflags);
-@@ -1146,19 +1153,33 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+@@ -1146,19 +1151,33 @@ static void nfs_commit_rpcsetup(struct list_head *head,
  		struct nfs_write_data *data,
  		int how)
  {
@@ -789134,7 +851776,7 @@
  
  	data->args.fh     = NFS_FH(data->inode);
  	/* Note: we always request a commit of the entire inode */
-@@ -1170,14 +1191,13 @@ static void nfs_commit_rpcsetup(struct list_head *head,
+@@ -1170,14 +1189,13 @@ static void nfs_commit_rpcsetup(struct list_head *head,
  	nfs_fattr_init(&data->fattr);
  
  	/* Set up the initial task struct.  */
@@ -789154,7 +851796,7 @@
  }
  
  /*
-@@ -1197,7 +1217,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
+@@ -1197,7 +1215,6 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how)
  	/* Set up the argument struct */
  	nfs_commit_rpcsetup(head, data, how);
  
@@ -789162,6 +851804,35 @@
  	return 0;
   out_bad:
  	while (!list_empty(head)) {
+diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
+index 2192805..d13403e 100644
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -11,8 +11,6 @@
+ #include <linux/nfsd/nfsd.h>
+ #include <linux/nfsd/export.h>
+ 
+-#define	CAP_NFSD_MASK (CAP_FS_MASK|CAP_TO_MASK(CAP_SYS_RESOURCE))
+-
+ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export *exp)
+ {
+ 	struct exp_flavor_info *f;
+@@ -69,10 +67,12 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
+ 	ret = set_current_groups(cred.cr_group_info);
+ 	put_group_info(cred.cr_group_info);
+ 	if ((cred.cr_uid)) {
+-		cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
++		current->cap_effective =
++			cap_drop_nfsd_set(current->cap_effective);
+ 	} else {
+-		cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
+-						  current->cap_permitted);
++		current->cap_effective =
++			cap_raise_nfsd_set(current->cap_effective,
++					   current->cap_permitted);
+ 	}
+ 	return ret;
+ }
 diff --git a/fs/nfsd/auth.h b/fs/nfsd/auth.h
 new file mode 100644
 index 0000000..78b3c0e
@@ -790528,6 +853199,203 @@
  
  	/*
  	 * Update the filehandle to get the new inode info.
+diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c
+index ad87cb0..00e9ccd 100644
+--- a/fs/ntfs/aops.c
++++ b/fs/ntfs/aops.c
+@@ -87,13 +87,17 @@ static void ntfs_end_buffer_async_read(struct buffer_head *bh, int uptodate)
+ 		/* Check for the current buffer head overflowing. */
+ 		if (unlikely(file_ofs + bh->b_size > init_size)) {
+ 			int ofs;
++			void *kaddr;
+ 
+ 			ofs = 0;
+ 			if (file_ofs < init_size)
+ 				ofs = init_size - file_ofs;
+ 			local_irq_save(flags);
+-			zero_user_page(page, bh_offset(bh) + ofs,
+-					 bh->b_size - ofs, KM_BIO_SRC_IRQ);
++			kaddr = kmap_atomic(page, KM_BIO_SRC_IRQ);
++			memset(kaddr + bh_offset(bh) + ofs, 0,
++					bh->b_size - ofs);
++			flush_dcache_page(page);
++			kunmap_atomic(kaddr, KM_BIO_SRC_IRQ);
+ 			local_irq_restore(flags);
+ 		}
+ 	} else {
+@@ -334,7 +338,7 @@ handle_hole:
+ 		bh->b_blocknr = -1UL;
+ 		clear_buffer_mapped(bh);
+ handle_zblock:
+-		zero_user_page(page, i * blocksize, blocksize, KM_USER0);
++		zero_user(page, i * blocksize, blocksize);
+ 		if (likely(!err))
+ 			set_buffer_uptodate(bh);
+ 	} while (i++, iblock++, (bh = bh->b_this_page) != head);
+@@ -410,7 +414,7 @@ retry_readpage:
+ 	/* Is the page fully outside i_size? (truncate in progress) */
+ 	if (unlikely(page->index >= (i_size + PAGE_CACHE_SIZE - 1) >>
+ 			PAGE_CACHE_SHIFT)) {
+-		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
++		zero_user(page, 0, PAGE_CACHE_SIZE);
+ 		ntfs_debug("Read outside i_size - truncated?");
+ 		goto done;
+ 	}
+@@ -459,7 +463,7 @@ retry_readpage:
+ 	 * ok to ignore the compressed flag here.
+ 	 */
+ 	if (unlikely(page->index > 0)) {
+-		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
++		zero_user(page, 0, PAGE_CACHE_SIZE);
+ 		goto done;
+ 	}
+ 	if (!NInoAttr(ni))
+@@ -788,8 +792,7 @@ lock_retry_remap:
+ 		if (err == -ENOENT || lcn == LCN_ENOENT) {
+ 			bh->b_blocknr = -1;
+ 			clear_buffer_dirty(bh);
+-			zero_user_page(page, bh_offset(bh), blocksize,
+-					KM_USER0);
++			zero_user(page, bh_offset(bh), blocksize);
+ 			set_buffer_uptodate(bh);
+ 			err = 0;
+ 			continue;
+@@ -1414,8 +1417,7 @@ retry_writepage:
+ 		if (page->index >= (i_size >> PAGE_CACHE_SHIFT)) {
+ 			/* The page straddles i_size. */
+ 			unsigned int ofs = i_size & ~PAGE_CACHE_MASK;
+-			zero_user_page(page, ofs, PAGE_CACHE_SIZE - ofs,
+-					KM_USER0);
++			zero_user_segment(page, ofs, PAGE_CACHE_SIZE);
+ 		}
+ 		/* Handle mst protected attributes. */
+ 		if (NInoMstProtected(ni))
+diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
+index d1619d0..33ff314 100644
+--- a/fs/ntfs/compress.c
++++ b/fs/ntfs/compress.c
+@@ -565,7 +565,7 @@ int ntfs_read_compressed_block(struct page *page)
+ 	if (xpage >= max_page) {
+ 		kfree(bhs);
+ 		kfree(pages);
+-		zero_user_page(page, 0, PAGE_CACHE_SIZE, KM_USER0);
++		zero_user(page, 0, PAGE_CACHE_SIZE);
+ 		ntfs_debug("Compressed read outside i_size - truncated?");
+ 		SetPageUptodate(page);
+ 		unlock_page(page);
+diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c
+index 6cd08df..3c5550c 100644
+--- a/fs/ntfs/file.c
++++ b/fs/ntfs/file.c
+@@ -607,8 +607,8 @@ do_next_page:
+ 					ntfs_submit_bh_for_read(bh);
+ 					*wait_bh++ = bh;
+ 				} else {
+-					zero_user_page(page, bh_offset(bh),
+-							blocksize, KM_USER0);
++					zero_user(page, bh_offset(bh),
++							blocksize);
+ 					set_buffer_uptodate(bh);
+ 				}
+ 			}
+@@ -683,9 +683,8 @@ map_buffer_cached:
+ 						ntfs_submit_bh_for_read(bh);
+ 						*wait_bh++ = bh;
+ 					} else {
+-						zero_user_page(page,
+-							bh_offset(bh),
+-							blocksize, KM_USER0);
++						zero_user(page, bh_offset(bh),
++								blocksize);
+ 						set_buffer_uptodate(bh);
+ 					}
+ 				}
+@@ -703,8 +702,8 @@ map_buffer_cached:
+ 			 */
+ 			if (bh_end <= pos || bh_pos >= end) {
+ 				if (!buffer_uptodate(bh)) {
+-					zero_user_page(page, bh_offset(bh),
+-							blocksize, KM_USER0);
++					zero_user(page, bh_offset(bh),
++							blocksize);
+ 					set_buffer_uptodate(bh);
+ 				}
+ 				mark_buffer_dirty(bh);
+@@ -743,8 +742,7 @@ map_buffer_cached:
+ 				if (!buffer_uptodate(bh))
+ 					set_buffer_uptodate(bh);
+ 			} else if (!buffer_uptodate(bh)) {
+-				zero_user_page(page, bh_offset(bh), blocksize,
+-						KM_USER0);
++				zero_user(page, bh_offset(bh), blocksize);
+ 				set_buffer_uptodate(bh);
+ 			}
+ 			continue;
+@@ -868,8 +866,8 @@ rl_not_mapped_enoent:
+ 					if (!buffer_uptodate(bh))
+ 						set_buffer_uptodate(bh);
+ 				} else if (!buffer_uptodate(bh)) {
+-					zero_user_page(page, bh_offset(bh),
+-							blocksize, KM_USER0);
++					zero_user(page, bh_offset(bh),
++						blocksize);
+ 					set_buffer_uptodate(bh);
+ 				}
+ 				continue;
+@@ -1128,8 +1126,8 @@ rl_not_mapped_enoent:
+ 
+ 				if (likely(bh_pos < initialized_size))
+ 					ofs = initialized_size - bh_pos;
+-				zero_user_page(page, bh_offset(bh) + ofs,
+-						blocksize - ofs, KM_USER0);
++				zero_user_segment(page, bh_offset(bh) + ofs,
++						blocksize);
+ 			}
+ 		} else /* if (unlikely(!buffer_uptodate(bh))) */
+ 			err = -EIO;
+@@ -1269,8 +1267,8 @@ rl_not_mapped_enoent:
+ 				if (PageUptodate(page))
+ 					set_buffer_uptodate(bh);
+ 				else {
+-					zero_user_page(page, bh_offset(bh),
+-							blocksize, KM_USER0);
++					zero_user(page, bh_offset(bh),
++							blocksize);
+ 					set_buffer_uptodate(bh);
+ 				}
+ 			}
+@@ -1330,7 +1328,7 @@ err_out:
+ 		len = PAGE_CACHE_SIZE;
+ 		if (len > bytes)
+ 			len = bytes;
+-		zero_user_page(*pages, 0, len, KM_USER0);
++		zero_user(*pages, 0, len);
+ 	}
+ 	goto out;
+ }
+@@ -1451,7 +1449,7 @@ err_out:
+ 		len = PAGE_CACHE_SIZE;
+ 		if (len > bytes)
+ 			len = bytes;
+-		zero_user_page(*pages, 0, len, KM_USER0);
++		zero_user(*pages, 0, len);
+ 	}
+ 	goto out;
+ }
+diff --git a/fs/ntfs/malloc.h b/fs/ntfs/malloc.h
+index e38e402..cd0be3f 100644
+--- a/fs/ntfs/malloc.h
++++ b/fs/ntfs/malloc.h
+@@ -85,8 +85,7 @@ static inline void *ntfs_malloc_nofs_nofail(unsigned long size)
+ 
+ static inline void ntfs_free(void *addr)
+ {
+-	if (likely(((unsigned long)addr < VMALLOC_START) ||
+-			((unsigned long)addr >= VMALLOC_END ))) {
++	if (!is_vmalloc_addr(addr)) {
+ 		kfree(addr);
+ 		/* free_page((unsigned long)addr); */
+ 		return;
 diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
 index 9fb8132..4d4ce48 100644
 --- a/fs/ocfs2/Makefile
@@ -790553,9 +853421,18 @@
  obj-$(CONFIG_OCFS2_FS) += cluster/
  obj-$(CONFIG_OCFS2_FS) += dlm/
 diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
-index 23c8cda..e6df06a 100644
+index 23c8cda..447206e 100644
 --- a/fs/ocfs2/alloc.c
 +++ b/fs/ocfs2/alloc.c
+@@ -3338,7 +3338,7 @@ static int ocfs2_insert_path(struct inode *inode,
+ 	if (insert->ins_split != SPLIT_NONE) {
+ 		/*
+ 		 * We could call ocfs2_insert_at_leaf() for some types
+-		 * of splits, but it's easier to just let one seperate
++		 * of splits, but it's easier to just let one separate
+ 		 * function sort it all out.
+ 		 */
+ 		ocfs2_split_record(inode, left_path, right_path,
 @@ -4731,7 +4731,7 @@ int __ocfs2_flush_truncate_log(struct ocfs2_super *osb)
  
  	mutex_lock(&data_alloc_inode->i_mutex);
@@ -790592,8 +853469,17 @@
  	brelse(di_bh);
  out_mutex:
  	mutex_unlock(&inode->i_mutex);
+@@ -5670,7 +5670,7 @@ static void ocfs2_map_and_dirty_page(struct inode *inode, handle_t *handle,
+ 		mlog_errno(ret);
+ 
+ 	if (zero)
+-		zero_user_page(page, from, to - from, KM_USER0);
++		zero_user_segment(page, from, to);
+ 
+ 	/*
+ 	 * Need to set the buffers we zero'd into uptodate
 diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
-index 56f7790..bc7b4cb 100644
+index 56f7790..8224312 100644
 --- a/fs/ocfs2/aops.c
 +++ b/fs/ocfs2/aops.c
 @@ -26,6 +26,7 @@
@@ -790681,7 +853567,14 @@
  	}
  
  	/*
-@@ -305,25 +313,16 @@ static int ocfs2_readpage(struct file *file, struct page *page)
+@@ -299,31 +307,22 @@ static int ocfs2_readpage(struct file *file, struct page *page)
+ 	 * XXX sys_readahead() seems to get that wrong?
+ 	 */
+ 	if (start >= i_size_read(inode)) {
+-		zero_user_page(page, 0, PAGE_SIZE, KM_USER0);
++		zero_user(page, 0, PAGE_SIZE);
+ 		SetPageUptodate(page);
+ 		ret = 0;
  		goto out_alloc;
  	}
  
@@ -790826,6 +853719,24 @@
  	mlog_exit(ret);
  	return ret;
  }
+@@ -836,7 +869,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
+ 		if (block_start >= to)
+ 			break;
+ 
+-		zero_user_page(page, block_start, bh->b_size, KM_USER0);
++		zero_user(page, block_start, bh->b_size);
+ 		set_buffer_uptodate(bh);
+ 		mark_buffer_dirty(bh);
+ 
+@@ -1001,7 +1034,7 @@ static void ocfs2_zero_new_buffers(struct page *page, unsigned from, unsigned to
+ 					start = max(from, block_start);
+ 					end = min(to, block_end);
+ 
+-					zero_user_page(page, start, end - start, KM_USER0);
++					zero_user_segment(page, start, end);
+ 					set_buffer_uptodate(bh);
+ 				}
+ 
 @@ -1754,7 +1787,7 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
  	struct buffer_head *di_bh = NULL;
  	struct inode *inode = mapping->host;
@@ -791224,7 +854135,7 @@
  	dl->dl_inode = igrab(inode);
  	dl->dl_parent_blkno = parent_blkno;
 diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
-index 63b28fd..6b0107f 100644
+index 63b28fd..e280833 100644
 --- a/fs/ocfs2/dir.c
 +++ b/fs/ocfs2/dir.c
 @@ -846,14 +846,14 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
@@ -791254,6 +854165,15 @@
  
  bail_nolock:
  	mlog_exit(error);
+@@ -1215,7 +1215,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
+ 	down_write(&oi->ip_alloc_sem);
+ 
+ 	/*
+-	 * Prepare for worst case allocation scenario of two seperate
++	 * Prepare for worst case allocation scenario of two separate
+ 	 * extents.
+ 	 */
+ 	if (alloc == 2)
 diff --git a/fs/ocfs2/dlm/dlmfsver.c b/fs/ocfs2/dlm/dlmfsver.c
 index d2be3ad..a733b33 100644
 --- a/fs/ocfs2/dlm/dlmfsver.c
@@ -794172,6 +857092,19 @@
  
  		mlog_errno(status);
  		goto leave;
+diff --git a/fs/ocfs2/ocfs1_fs_compat.h b/fs/ocfs2/ocfs1_fs_compat.h
+index 0b499bc..dfb313b 100644
+--- a/fs/ocfs2/ocfs1_fs_compat.h
++++ b/fs/ocfs2/ocfs1_fs_compat.h
+@@ -77,7 +77,7 @@ struct ocfs1_disk_lock
+ {
+ /*00*/	__u32 curr_master;
+ 	__u8 file_lock;
+-	__u8 compat_pad[3];  /* Not in orignal definition.  Used to
++	__u8 compat_pad[3];  /* Not in original definition.  Used to
+ 				make the already existing alignment
+ 				explicit */
+ 	__u64 last_write_time;
 diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
 index 60a23e1..d084805 100644
 --- a/fs/ocfs2/ocfs2.h
@@ -795044,7 +857977,7 @@
  				      int slot_num)
  {
 diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
-index 8f09f52..7e397e2 100644
+index 8f09f52..72c198a 100644
 --- a/fs/ocfs2/suballoc.c
 +++ b/fs/ocfs2/suballoc.c
 @@ -101,8 +101,6 @@ static inline int ocfs2_block_group_reasonably_empty(struct ocfs2_group_desc *bg
@@ -795087,6 +858020,15 @@
  	if (status < 0) {
  		mutex_unlock(&alloc_inode->i_mutex);
  		iput(alloc_inode);
+@@ -648,7 +646,7 @@ bail:
+  * sync-data inodes."
+  *
+  * Note: OCFS2 already does this differently for metadata vs data
+- * allocations, as those bitmaps are seperate and undo access is never
++ * allocations, as those bitmaps are separate and undo access is never
+  * called on a metadata group descriptor.
+  */
+ static int ocfs2_test_bg_bit_allocatable(struct buffer_head *bg_bh,
 @@ -1443,8 +1441,7 @@ static inline u32 ocfs2_desc_bitmap_to_cluster_off(struct inode *inode,
  
  /* given a cluster offset, calculate which block group it belongs to
@@ -796751,7 +859693,7 @@
 +	device_del(&disk->dev);
  }
 diff --git a/fs/proc/array.c b/fs/proc/array.c
-index eb97f28..b380313 100644
+index eb97f28..6ba2746 100644
 --- a/fs/proc/array.c
 +++ b/fs/proc/array.c
 @@ -141,12 +141,7 @@ static const char *task_state_array[] = {
@@ -796768,11 +859710,52 @@
  	const char **p = &task_state_array[0];
  
  	while (state) {
+@@ -286,14 +281,23 @@ static inline char *task_sig(struct task_struct *p, char *buffer)
+ 	return buffer;
+ }
+ 
++static char *render_cap_t(const char *header, kernel_cap_t *a, char *buffer)
++{
++	unsigned __capi;
++
++	buffer += sprintf(buffer, "%s", header);
++	CAP_FOR_EACH_U32(__capi) {
++		buffer += sprintf(buffer, "%08x",
++				  a->cap[(_LINUX_CAPABILITY_U32S-1) - __capi]);
++	}
++	return buffer + sprintf(buffer, "\n");
++}
++
+ static inline char *task_cap(struct task_struct *p, char *buffer)
+ {
+-    return buffer + sprintf(buffer, "CapInh:\t%016x\n"
+-			    "CapPrm:\t%016x\n"
+-			    "CapEff:\t%016x\n",
+-			    cap_t(p->cap_inheritable),
+-			    cap_t(p->cap_permitted),
+-			    cap_t(p->cap_effective));
++	buffer = render_cap_t("CapInh:\t", &p->cap_inheritable, buffer);
++	buffer = render_cap_t("CapPrm:\t", &p->cap_permitted, buffer);
++	return render_cap_t("CapEff:\t", &p->cap_effective, buffer);
+ }
+ 
+ static inline char *task_context_switch_counts(struct task_struct *p,
 diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 7411bfb..3353748 100644
+index 7411bfb..c59852b 100644
 --- a/fs/proc/base.c
 +++ b/fs/proc/base.c
-@@ -199,7 +199,7 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
+@@ -88,10 +88,6 @@
+  *	in /proc for a task before it execs a suid executable.
+  */
+ 
+-
+-/* Worst case buffer size needed for holding an integer. */
+-#define PROC_NUMBUF 13
+-
+ struct pid_entry {
+ 	char *name;
+ 	int len;
+@@ -199,7 +195,7 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
  	(task == current || \
  	(task->parent == current && \
  	(task->ptrace & PT_PTRACED) && \
@@ -796781,7 +859764,7 @@
  	 security_ptrace(current,task) == 0))
  
  struct mm_struct *mm_for_maps(struct task_struct *task)
-@@ -310,6 +310,77 @@ static int proc_pid_schedstat(struct task_struct *task, char *buffer)
+@@ -310,6 +306,77 @@ static int proc_pid_schedstat(struct task_struct *task, char *buffer)
  }
  #endif
  
@@ -796859,7 +859842,59 @@
  /* The badness from the OOM killer */
  unsigned long badness(struct task_struct *p, unsigned long uptime);
  static int proc_oom_score(struct task_struct *task, char *buffer)
-@@ -913,7 +984,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
+@@ -716,7 +783,7 @@ out_no_task:
+ }
+ #endif
+ 
+-static loff_t mem_lseek(struct file * file, loff_t offset, int orig)
++loff_t mem_lseek(struct file *file, loff_t offset, int orig)
+ {
+ 	switch (orig) {
+ 	case 0:
+@@ -864,42 +931,6 @@ static const struct file_operations proc_oom_adjust_operations = {
+ 	.write		= oom_adjust_write,
+ };
+ 
+-#ifdef CONFIG_MMU
+-static ssize_t clear_refs_write(struct file *file, const char __user *buf,
+-				size_t count, loff_t *ppos)
+-{
+-	struct task_struct *task;
+-	char buffer[PROC_NUMBUF], *end;
+-	struct mm_struct *mm;
+-
+-	memset(buffer, 0, sizeof(buffer));
+-	if (count > sizeof(buffer) - 1)
+-		count = sizeof(buffer) - 1;
+-	if (copy_from_user(buffer, buf, count))
+-		return -EFAULT;
+-	if (!simple_strtol(buffer, &end, 0))
+-		return -EINVAL;
+-	if (*end == '\n')
+-		end++;
+-	task = get_proc_task(file->f_path.dentry->d_inode);
+-	if (!task)
+-		return -ESRCH;
+-	mm = get_task_mm(task);
+-	if (mm) {
+-		clear_refs_smap(mm);
+-		mmput(mm);
+-	}
+-	put_task_struct(task);
+-	if (end - buffer == 0)
+-		return -EIO;
+-	return end - buffer;
+-}
+-
+-static struct file_operations proc_clear_refs_operations = {
+-	.write		= clear_refs_write,
+-};
+-#endif
+-
+ #ifdef CONFIG_AUDITSYSCALL
+ #define TMPBUFLEN 21
+ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
+@@ -913,7 +944,7 @@ static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
  	if (!task)
  		return -ESRCH;
  	length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
@@ -796868,7 +859903,7 @@
  	put_task_struct(task);
  	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
  }
-@@ -1020,6 +1091,7 @@ static const struct file_operations proc_fault_inject_operations = {
+@@ -1020,6 +1051,7 @@ static const struct file_operations proc_fault_inject_operations = {
  };
  #endif
  
@@ -796876,7 +859911,19 @@
  #ifdef CONFIG_SCHED_DEBUG
  /*
   * Print out various scheduling related per-task fields:
-@@ -2230,6 +2302,9 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2217,9 +2249,10 @@ static const struct pid_entry tgid_base_stuff[] = {
+ 	LNK("exe",        exe),
+ 	REG("mounts",     S_IRUGO, mounts),
+ 	REG("mountstats", S_IRUSR, mountstats),
+-#ifdef CONFIG_MMU
++#ifdef CONFIG_PROC_PAGE_MONITOR
+ 	REG("clear_refs", S_IWUSR, clear_refs),
+ 	REG("smaps",      S_IRUGO, smaps),
++	REG("pagemap",    S_IRUSR, pagemap),
+ #endif
+ #ifdef CONFIG_SECURITY
+ 	DIR("attr",       S_IRUGO|S_IXUGO, attr_dir),
+@@ -2230,6 +2263,9 @@ static const struct pid_entry tgid_base_stuff[] = {
  #ifdef CONFIG_SCHEDSTATS
  	INF("schedstat",  S_IRUGO, pid_schedstat),
  #endif
@@ -796886,7 +859933,29 @@
  #ifdef CONFIG_PROC_PID_CPUSET
  	REG("cpuset",     S_IRUGO, cpuset),
  #endif
-@@ -2555,6 +2630,9 @@ static const struct pid_entry tid_base_stuff[] = {
+@@ -2285,7 +2321,8 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)
+ 	name.len = snprintf(buf, sizeof(buf), "%d", pid);
+ 	dentry = d_hash_and_lookup(mnt->mnt_root, &name);
+ 	if (dentry) {
+-		shrink_dcache_parent(dentry);
++		if (!(current->flags & PF_EXITING))
++			shrink_dcache_parent(dentry);
+ 		d_drop(dentry);
+ 		dput(dentry);
+ 	}
+@@ -2542,9 +2579,10 @@ static const struct pid_entry tid_base_stuff[] = {
+ 	LNK("root",      root),
+ 	LNK("exe",       exe),
+ 	REG("mounts",    S_IRUGO, mounts),
+-#ifdef CONFIG_MMU
++#ifdef CONFIG_PROC_PAGE_MONITOR
+ 	REG("clear_refs", S_IWUSR, clear_refs),
+ 	REG("smaps",     S_IRUGO, smaps),
++	REG("pagemap",    S_IRUSR, pagemap),
+ #endif
+ #ifdef CONFIG_SECURITY
+ 	DIR("attr",      S_IRUGO|S_IXUGO, attr_dir),
+@@ -2555,6 +2593,9 @@ static const struct pid_entry tid_base_stuff[] = {
  #ifdef CONFIG_SCHEDSTATS
  	INF("schedstat", S_IRUGO, pid_schedstat),
  #endif
@@ -796896,6 +859965,203 @@
  #ifdef CONFIG_PROC_PID_CPUSET
  	REG("cpuset",    S_IRUGO, cpuset),
  #endif
+diff --git a/fs/proc/internal.h b/fs/proc/internal.h
+index 05b3e90..7d57e80 100644
+--- a/fs/proc/internal.h
++++ b/fs/proc/internal.h
+@@ -52,15 +52,13 @@ extern int proc_tid_stat(struct task_struct *,  char *);
+ extern int proc_tgid_stat(struct task_struct *, char *);
+ extern int proc_pid_status(struct task_struct *, char *);
+ extern int proc_pid_statm(struct task_struct *, char *);
++extern loff_t mem_lseek(struct file *file, loff_t offset, int orig);
+ 
+ extern const struct file_operations proc_maps_operations;
+ extern const struct file_operations proc_numa_maps_operations;
+ extern const struct file_operations proc_smaps_operations;
+-
+-extern const struct file_operations proc_maps_operations;
+-extern const struct file_operations proc_numa_maps_operations;
+-extern const struct file_operations proc_smaps_operations;
+-
++extern const struct file_operations proc_clear_refs_operations;
++extern const struct file_operations proc_pagemap_operations;
+ 
+ void free_proc_entry(struct proc_dir_entry *de);
+ 
+diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
+index 1be7308..7dd26e1 100644
+--- a/fs/proc/kcore.c
++++ b/fs/proc/kcore.c
+@@ -325,7 +325,7 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
+ 		if (m == NULL) {
+ 			if (clear_user(buffer, tsz))
+ 				return -EFAULT;
+-		} else if ((start >= VMALLOC_START) && (start < VMALLOC_END)) {
++		} else if (is_vmalloc_addr((void *)start)) {
+ 			char * elf_buf;
+ 			struct vm_struct *m;
+ 			unsigned long curstart = start;
+diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
+index 3462bfd..51288db 100644
+--- a/fs/proc/proc_misc.c
++++ b/fs/proc/proc_misc.c
+@@ -46,6 +46,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/crash_dump.h>
+ #include <linux/pid_namespace.h>
++#include <linux/bootmem.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/io.h>
+@@ -675,6 +676,137 @@ static const struct file_operations proc_sysrq_trigger_operations = {
+ };
+ #endif
+ 
++#ifdef CONFIG_PROC_PAGE_MONITOR
++#define KPMSIZE sizeof(u64)
++#define KPMMASK (KPMSIZE - 1)
++/* /proc/kpagecount - an array exposing page counts
++ *
++ * Each entry is a u64 representing the corresponding
++ * physical page count.
++ */
++static ssize_t kpagecount_read(struct file *file, char __user *buf,
++			     size_t count, loff_t *ppos)
++{
++	u64 __user *out = (u64 __user *)buf;
++	struct page *ppage;
++	unsigned long src = *ppos;
++	unsigned long pfn;
++	ssize_t ret = 0;
++	u64 pcount;
++
++	pfn = src / KPMSIZE;
++	count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
++	if (src & KPMMASK || count & KPMMASK)
++		return -EIO;
++
++	while (count > 0) {
++		ppage = NULL;
++		if (pfn_valid(pfn))
++			ppage = pfn_to_page(pfn);
++		pfn++;
++		if (!ppage)
++			pcount = 0;
++		else
++			pcount = atomic_read(&ppage->_count);
++
++		if (put_user(pcount, out++)) {
++			ret = -EFAULT;
++			break;
++		}
++
++		count -= KPMSIZE;
++	}
++
++	*ppos += (char __user *)out - buf;
++	if (!ret)
++		ret = (char __user *)out - buf;
++	return ret;
++}
++
++static struct file_operations proc_kpagecount_operations = {
++	.llseek = mem_lseek,
++	.read = kpagecount_read,
++};
++
++/* /proc/kpageflags - an array exposing page flags
++ *
++ * Each entry is a u64 representing the corresponding
++ * physical page flags.
++ */
++
++/* These macros are used to decouple internal flags from exported ones */
++
++#define KPF_LOCKED     0
++#define KPF_ERROR      1
++#define KPF_REFERENCED 2
++#define KPF_UPTODATE   3
++#define KPF_DIRTY      4
++#define KPF_LRU        5
++#define KPF_ACTIVE     6
++#define KPF_SLAB       7
++#define KPF_WRITEBACK  8
++#define KPF_RECLAIM    9
++#define KPF_BUDDY     10
++
++#define kpf_copy_bit(flags, srcpos, dstpos) (((flags >> srcpos) & 1) << dstpos)
++
++static ssize_t kpageflags_read(struct file *file, char __user *buf,
++			     size_t count, loff_t *ppos)
++{
++	u64 __user *out = (u64 __user *)buf;
++	struct page *ppage;
++	unsigned long src = *ppos;
++	unsigned long pfn;
++	ssize_t ret = 0;
++	u64 kflags, uflags;
++
++	pfn = src / KPMSIZE;
++	count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
++	if (src & KPMMASK || count & KPMMASK)
++		return -EIO;
++
++	while (count > 0) {
++		ppage = NULL;
++		if (pfn_valid(pfn))
++			ppage = pfn_to_page(pfn);
++		pfn++;
++		if (!ppage)
++			kflags = 0;
++		else
++			kflags = ppage->flags;
++
++		uflags = kpf_copy_bit(KPF_LOCKED, PG_locked, kflags) |
++			kpf_copy_bit(kflags, KPF_ERROR, PG_error) |
++			kpf_copy_bit(kflags, KPF_REFERENCED, PG_referenced) |
++			kpf_copy_bit(kflags, KPF_UPTODATE, PG_uptodate) |
++			kpf_copy_bit(kflags, KPF_DIRTY, PG_dirty) |
++			kpf_copy_bit(kflags, KPF_LRU, PG_lru) |
++			kpf_copy_bit(kflags, KPF_ACTIVE, PG_active) |
++			kpf_copy_bit(kflags, KPF_SLAB, PG_slab) |
++			kpf_copy_bit(kflags, KPF_WRITEBACK, PG_writeback) |
++			kpf_copy_bit(kflags, KPF_RECLAIM, PG_reclaim) |
++			kpf_copy_bit(kflags, KPF_BUDDY, PG_buddy);
++
++		if (put_user(uflags, out++)) {
++			ret = -EFAULT;
++			break;
++		}
++
++		count -= KPMSIZE;
++	}
++
++	*ppos += (char __user *)out - buf;
++	if (!ret)
++		ret = (char __user *)out - buf;
++	return ret;
++}
++
++static struct file_operations proc_kpageflags_operations = {
++	.llseek = mem_lseek,
++	.read = kpageflags_read,
++};
++#endif /* CONFIG_PROC_PAGE_MONITOR */
++
+ struct proc_dir_entry *proc_root_kcore;
+ 
+ void create_seq_entry(char *name, mode_t mode, const struct file_operations *f)
+@@ -755,6 +887,10 @@ void __init proc_misc_init(void)
+ 				(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
+ 	}
+ #endif
++#ifdef CONFIG_PROC_PAGE_MONITOR
++	create_seq_entry("kpagecount", S_IRUSR, &proc_kpagecount_operations);
++	create_seq_entry("kpageflags", S_IRUSR, &proc_kpageflags_operations);
++#endif
+ #ifdef CONFIG_PROC_VMCORE
+ 	proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
+ 	if (proc_vmcore)
 diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
 index 0afe21e..4823c96 100644
 --- a/fs/proc/proc_net.c
@@ -796988,6 +860254,800 @@
  
  	net->proc_net_root = root;
  	net->proc_net = netd;
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 8043a3e..38338ed 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -5,7 +5,10 @@
+ #include <linux/highmem.h>
+ #include <linux/ptrace.h>
+ #include <linux/pagemap.h>
++#include <linux/ptrace.h>
+ #include <linux/mempolicy.h>
++#include <linux/swap.h>
++#include <linux/swapops.h>
+ 
+ #include <asm/elf.h>
+ #include <asm/uaccess.h>
+@@ -114,24 +117,124 @@ static void pad_len_spaces(struct seq_file *m, int len)
+ 	seq_printf(m, "%*c", len, ' ');
+ }
+ 
+-struct mem_size_stats
++static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
+ {
+-	unsigned long resident;
+-	unsigned long shared_clean;
+-	unsigned long shared_dirty;
+-	unsigned long private_clean;
+-	unsigned long private_dirty;
+-	unsigned long referenced;
+-};
++	if (vma && vma != priv->tail_vma) {
++		struct mm_struct *mm = vma->vm_mm;
++		up_read(&mm->mmap_sem);
++		mmput(mm);
++	}
++}
+ 
+-struct pmd_walker {
+-	struct vm_area_struct *vma;
+-	void *private;
+-	void (*action)(struct vm_area_struct *, pmd_t *, unsigned long,
+-		       unsigned long, void *);
+-};
++static void *m_start(struct seq_file *m, loff_t *pos)
++{
++	struct proc_maps_private *priv = m->private;
++	unsigned long last_addr = m->version;
++	struct mm_struct *mm;
++	struct vm_area_struct *vma, *tail_vma = NULL;
++	loff_t l = *pos;
++
++	/* Clear the per syscall fields in priv */
++	priv->task = NULL;
++	priv->tail_vma = NULL;
++
++	/*
++	 * We remember last_addr rather than next_addr to hit with
++	 * mmap_cache most of the time. We have zero last_addr at
++	 * the beginning and also after lseek. We will have -1 last_addr
++	 * after the end of the vmas.
++	 */
++
++	if (last_addr == -1UL)
++		return NULL;
++
++	priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
++	if (!priv->task)
++		return NULL;
++
++	mm = mm_for_maps(priv->task);
++	if (!mm)
++		return NULL;
++
++	tail_vma = get_gate_vma(priv->task);
++	priv->tail_vma = tail_vma;
++
++	/* Start with last addr hint */
++	vma = find_vma(mm, last_addr);
++	if (last_addr && vma) {
++		vma = vma->vm_next;
++		goto out;
++	}
++
++	/*
++	 * Check the vma index is within the range and do
++	 * sequential scan until m_index.
++	 */
++	vma = NULL;
++	if ((unsigned long)l < mm->map_count) {
++		vma = mm->mmap;
++		while (l-- && vma)
++			vma = vma->vm_next;
++		goto out;
++	}
++
++	if (l != mm->map_count)
++		tail_vma = NULL; /* After gate vma */
++
++out:
++	if (vma)
++		return vma;
++
++	/* End of vmas has been reached */
++	m->version = (tail_vma != NULL)? 0: -1UL;
++	up_read(&mm->mmap_sem);
++	mmput(mm);
++	return tail_vma;
++}
+ 
+-static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
++static void *m_next(struct seq_file *m, void *v, loff_t *pos)
++{
++	struct proc_maps_private *priv = m->private;
++	struct vm_area_struct *vma = v;
++	struct vm_area_struct *tail_vma = priv->tail_vma;
++
++	(*pos)++;
++	if (vma && (vma != tail_vma) && vma->vm_next)
++		return vma->vm_next;
++	vma_stop(priv, vma);
++	return (vma != tail_vma)? tail_vma: NULL;
++}
++
++static void m_stop(struct seq_file *m, void *v)
++{
++	struct proc_maps_private *priv = m->private;
++	struct vm_area_struct *vma = v;
++
++	vma_stop(priv, vma);
++	if (priv->task)
++		put_task_struct(priv->task);
++}
++
++static int do_maps_open(struct inode *inode, struct file *file,
++			struct seq_operations *ops)
++{
++	struct proc_maps_private *priv;
++	int ret = -ENOMEM;
++	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++	if (priv) {
++		priv->pid = proc_pid(inode);
++		ret = seq_open(file, ops);
++		if (!ret) {
++			struct seq_file *m = file->private_data;
++			m->private = priv;
++		} else {
++			kfree(priv);
++		}
++	}
++	return ret;
++}
++
++static int show_map(struct seq_file *m, void *v)
+ {
+ 	struct proc_maps_private *priv = m->private;
+ 	struct task_struct *task = priv->task;
+@@ -191,41 +294,71 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
+ 	}
+ 	seq_putc(m, '\n');
+ 
+-	if (mss)
+-		seq_printf(m,
+-			   "Size:           %8lu kB\n"
+-			   "Rss:            %8lu kB\n"
+-			   "Shared_Clean:   %8lu kB\n"
+-			   "Shared_Dirty:   %8lu kB\n"
+-			   "Private_Clean:  %8lu kB\n"
+-			   "Private_Dirty:  %8lu kB\n"
+-			   "Referenced:     %8lu kB\n",
+-			   (vma->vm_end - vma->vm_start) >> 10,
+-			   mss->resident >> 10,
+-			   mss->shared_clean  >> 10,
+-			   mss->shared_dirty  >> 10,
+-			   mss->private_clean >> 10,
+-			   mss->private_dirty >> 10,
+-			   mss->referenced >> 10);
+-
+ 	if (m->count < m->size)  /* vma is copied successfully */
+ 		m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
+ 	return 0;
+ }
+ 
+-static int show_map(struct seq_file *m, void *v)
++static struct seq_operations proc_pid_maps_op = {
++	.start	= m_start,
++	.next	= m_next,
++	.stop	= m_stop,
++	.show	= show_map
++};
++
++static int maps_open(struct inode *inode, struct file *file)
+ {
+-	return show_map_internal(m, v, NULL);
++	return do_maps_open(inode, file, &proc_pid_maps_op);
+ }
+ 
+-static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+-			    unsigned long addr, unsigned long end,
+-			    void *private)
++const struct file_operations proc_maps_operations = {
++	.open		= maps_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= seq_release_private,
++};
++
++/*
++ * Proportional Set Size(PSS): my share of RSS.
++ *
++ * PSS of a process is the count of pages it has in memory, where each
++ * page is divided by the number of processes sharing it.  So if a
++ * process has 1000 pages all to itself, and 1000 shared with one other
++ * process, its PSS will be 1500.
++ *
++ * To keep (accumulated) division errors low, we adopt a 64bit
++ * fixed-point pss counter to minimize division errors. So (pss >>
++ * PSS_SHIFT) would be the real byte count.
++ *
++ * A shift of 12 before division means (assuming 4K page size):
++ * 	- 1M 3-user-pages add up to 8KB errors;
++ * 	- supports mapcount up to 2^24, or 16M;
++ * 	- supports PSS up to 2^52 bytes, or 4PB.
++ */
++#define PSS_SHIFT 12
++
++#ifdef CONFIG_PROC_PAGE_MONITOR
++struct mem_size_stats
++{
++	struct vm_area_struct *vma;
++	unsigned long resident;
++	unsigned long shared_clean;
++	unsigned long shared_dirty;
++	unsigned long private_clean;
++	unsigned long private_dirty;
++	unsigned long referenced;
++	u64 pss;
++};
++
++static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
++			   void *private)
+ {
+ 	struct mem_size_stats *mss = private;
++	struct vm_area_struct *vma = mss->vma;
+ 	pte_t *pte, ptent;
+ 	spinlock_t *ptl;
+ 	struct page *page;
++	int mapcount;
+ 
+ 	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
+ 	for (; addr != end; pte++, addr += PAGE_SIZE) {
+@@ -242,26 +375,88 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ 		/* Accumulate the size in pages that have been accessed. */
+ 		if (pte_young(ptent) || PageReferenced(page))
+ 			mss->referenced += PAGE_SIZE;
+-		if (page_mapcount(page) >= 2) {
++		mapcount = page_mapcount(page);
++		if (mapcount >= 2) {
+ 			if (pte_dirty(ptent))
+ 				mss->shared_dirty += PAGE_SIZE;
+ 			else
+ 				mss->shared_clean += PAGE_SIZE;
++			mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+ 		} else {
+ 			if (pte_dirty(ptent))
+ 				mss->private_dirty += PAGE_SIZE;
+ 			else
+ 				mss->private_clean += PAGE_SIZE;
++			mss->pss += (PAGE_SIZE << PSS_SHIFT);
+ 		}
+ 	}
+ 	pte_unmap_unlock(pte - 1, ptl);
+ 	cond_resched();
++	return 0;
+ }
+ 
+-static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+-				 unsigned long addr, unsigned long end,
+-				 void *private)
++static struct mm_walk smaps_walk = { .pmd_entry = smaps_pte_range };
++
++static int show_smap(struct seq_file *m, void *v)
+ {
++	struct vm_area_struct *vma = v;
++	struct mem_size_stats mss;
++	int ret;
++
++	memset(&mss, 0, sizeof mss);
++	mss.vma = vma;
++	if (vma->vm_mm && !is_vm_hugetlb_page(vma))
++		walk_page_range(vma->vm_mm, vma->vm_start, vma->vm_end,
++				&smaps_walk, &mss);
++
++	ret = show_map(m, v);
++	if (ret)
++		return ret;
++
++	seq_printf(m,
++		   "Size:           %8lu kB\n"
++		   "Rss:            %8lu kB\n"
++		   "Pss:            %8lu kB\n"
++		   "Shared_Clean:   %8lu kB\n"
++		   "Shared_Dirty:   %8lu kB\n"
++		   "Private_Clean:  %8lu kB\n"
++		   "Private_Dirty:  %8lu kB\n"
++		   "Referenced:     %8lu kB\n",
++		   (vma->vm_end - vma->vm_start) >> 10,
++		   mss.resident >> 10,
++		   (unsigned long)(mss.pss >> (10 + PSS_SHIFT)),
++		   mss.shared_clean  >> 10,
++		   mss.shared_dirty  >> 10,
++		   mss.private_clean >> 10,
++		   mss.private_dirty >> 10,
++		   mss.referenced >> 10);
++
++	return ret;
++}
++
++static struct seq_operations proc_pid_smaps_op = {
++	.start	= m_start,
++	.next	= m_next,
++	.stop	= m_stop,
++	.show	= show_smap
++};
++
++static int smaps_open(struct inode *inode, struct file *file)
++{
++	return do_maps_open(inode, file, &proc_pid_smaps_op);
++}
++
++const struct file_operations proc_smaps_operations = {
++	.open		= smaps_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= seq_release_private,
++};
++
++static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
++				unsigned long end, void *private)
++{
++	struct vm_area_struct *vma = private;
+ 	pte_t *pte, ptent;
+ 	spinlock_t *ptl;
+ 	struct page *page;
+@@ -282,235 +477,248 @@ static void clear_refs_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ 	}
+ 	pte_unmap_unlock(pte - 1, ptl);
+ 	cond_resched();
++	return 0;
+ }
+ 
+-static inline void walk_pmd_range(struct pmd_walker *walker, pud_t *pud,
+-				  unsigned long addr, unsigned long end)
++static struct mm_walk clear_refs_walk = { .pmd_entry = clear_refs_pte_range };
++
++static ssize_t clear_refs_write(struct file *file, const char __user *buf,
++				size_t count, loff_t *ppos)
+ {
+-	pmd_t *pmd;
+-	unsigned long next;
++	struct task_struct *task;
++	char buffer[PROC_NUMBUF], *end;
++	struct mm_struct *mm;
++	struct vm_area_struct *vma;
+ 
+-	for (pmd = pmd_offset(pud, addr); addr != end;
+-	     pmd++, addr = next) {
+-		next = pmd_addr_end(addr, end);
+-		if (pmd_none_or_clear_bad(pmd))
+-			continue;
+-		walker->action(walker->vma, pmd, addr, next, walker->private);
++	memset(buffer, 0, sizeof(buffer));
++	if (count > sizeof(buffer) - 1)
++		count = sizeof(buffer) - 1;
++	if (copy_from_user(buffer, buf, count))
++		return -EFAULT;
++	if (!simple_strtol(buffer, &end, 0))
++		return -EINVAL;
++	if (*end == '\n')
++		end++;
++	task = get_proc_task(file->f_path.dentry->d_inode);
++	if (!task)
++		return -ESRCH;
++	mm = get_task_mm(task);
++	if (mm) {
++		down_read(&mm->mmap_sem);
++		for (vma = mm->mmap; vma; vma = vma->vm_next)
++			if (!is_vm_hugetlb_page(vma))
++				walk_page_range(mm, vma->vm_start, vma->vm_end,
++						&clear_refs_walk, vma);
++		flush_tlb_mm(mm);
++		up_read(&mm->mmap_sem);
++		mmput(mm);
+ 	}
++	put_task_struct(task);
++	if (end - buffer == 0)
++		return -EIO;
++	return end - buffer;
+ }
+ 
+-static inline void walk_pud_range(struct pmd_walker *walker, pgd_t *pgd,
+-				  unsigned long addr, unsigned long end)
+-{
+-	pud_t *pud;
+-	unsigned long next;
++const struct file_operations proc_clear_refs_operations = {
++	.write		= clear_refs_write,
++};
+ 
+-	for (pud = pud_offset(pgd, addr); addr != end;
+-	     pud++, addr = next) {
+-		next = pud_addr_end(addr, end);
+-		if (pud_none_or_clear_bad(pud))
+-			continue;
+-		walk_pmd_range(walker, pud, addr, next);
++struct pagemapread {
++	char __user *out, *end;
++};
++
++#define PM_ENTRY_BYTES sizeof(u64)
++#define PM_RESERVED_BITS    3
++#define PM_RESERVED_OFFSET  (64 - PM_RESERVED_BITS)
++#define PM_RESERVED_MASK    (((1LL<<PM_RESERVED_BITS)-1) << PM_RESERVED_OFFSET)
++#define PM_SPECIAL(nr)      (((nr) << PM_RESERVED_OFFSET) | PM_RESERVED_MASK)
++#define PM_NOT_PRESENT      PM_SPECIAL(1LL)
++#define PM_SWAP             PM_SPECIAL(2LL)
++#define PM_END_OF_BUFFER    1
++
++static int add_to_pagemap(unsigned long addr, u64 pfn,
++			  struct pagemapread *pm)
++{
++	/*
++	 * Make sure there's room in the buffer for an
++	 * entire entry.  Otherwise, only copy part of
++	 * the pfn.
++	 */
++	if (pm->out + PM_ENTRY_BYTES >= pm->end) {
++		if (copy_to_user(pm->out, &pfn, pm->end - pm->out))
++			return -EFAULT;
++		pm->out = pm->end;
++		return PM_END_OF_BUFFER;
+ 	}
++
++	if (put_user(pfn, pm->out))
++		return -EFAULT;
++	pm->out += PM_ENTRY_BYTES;
++	return 0;
+ }
+ 
+-/*
+- * walk_page_range - walk the page tables of a VMA with a callback
+- * @vma - VMA to walk
+- * @action - callback invoked for every bottom-level (PTE) page table
+- * @private - private data passed to the callback function
+- *
+- * Recursively walk the page table for the memory area in a VMA, calling
+- * a callback for every bottom-level (PTE) page table.
+- */
+-static inline void walk_page_range(struct vm_area_struct *vma,
+-				   void (*action)(struct vm_area_struct *,
+-						  pmd_t *, unsigned long,
+-						  unsigned long, void *),
+-				   void *private)
++static int pagemap_pte_hole(unsigned long start, unsigned long end,
++				void *private)
+ {
+-	unsigned long addr = vma->vm_start;
+-	unsigned long end = vma->vm_end;
+-	struct pmd_walker walker = {
+-		.vma		= vma,
+-		.private	= private,
+-		.action		= action,
+-	};
+-	pgd_t *pgd;
+-	unsigned long next;
+-
+-	for (pgd = pgd_offset(vma->vm_mm, addr); addr != end;
+-	     pgd++, addr = next) {
+-		next = pgd_addr_end(addr, end);
+-		if (pgd_none_or_clear_bad(pgd))
+-			continue;
+-		walk_pud_range(&walker, pgd, addr, next);
++	struct pagemapread *pm = private;
++	unsigned long addr;
++	int err = 0;
++	for (addr = start; addr < end; addr += PAGE_SIZE) {
++		err = add_to_pagemap(addr, PM_NOT_PRESENT, pm);
++		if (err)
++			break;
+ 	}
++	return err;
+ }
+ 
+-static int show_smap(struct seq_file *m, void *v)
++u64 swap_pte_to_pagemap_entry(pte_t pte)
+ {
+-	struct vm_area_struct *vma = v;
+-	struct mem_size_stats mss;
+-
+-	memset(&mss, 0, sizeof mss);
+-	if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+-		walk_page_range(vma, smaps_pte_range, &mss);
+-	return show_map_internal(m, v, &mss);
++	swp_entry_t e = pte_to_swp_entry(pte);
++	return PM_SWAP | swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
+ }
+ 
+-void clear_refs_smap(struct mm_struct *mm)
++static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
++			     void *private)
+ {
+-	struct vm_area_struct *vma;
++	struct pagemapread *pm = private;
++	pte_t *pte;
++	int err = 0;
++
++	for (; addr != end; addr += PAGE_SIZE) {
++		u64 pfn = PM_NOT_PRESENT;
++		pte = pte_offset_map(pmd, addr);
++		if (is_swap_pte(*pte))
++			pfn = swap_pte_to_pagemap_entry(*pte);
++		else if (pte_present(*pte))
++			pfn = pte_pfn(*pte);
++		/* unmap so we're not in atomic when we copy to userspace */
++		pte_unmap(pte);
++		err = add_to_pagemap(addr, pfn, pm);
++		if (err)
++			return err;
++	}
+ 
+-	down_read(&mm->mmap_sem);
+-	for (vma = mm->mmap; vma; vma = vma->vm_next)
+-		if (vma->vm_mm && !is_vm_hugetlb_page(vma))
+-			walk_page_range(vma, clear_refs_pte_range, NULL);
+-	flush_tlb_mm(mm);
+-	up_read(&mm->mmap_sem);
++	cond_resched();
++
++	return err;
+ }
+ 
+-static void *m_start(struct seq_file *m, loff_t *pos)
++static struct mm_walk pagemap_walk = {
++	.pmd_entry = pagemap_pte_range,
++	.pte_hole = pagemap_pte_hole
++};
++
++/*
++ * /proc/pid/pagemap - an array mapping virtual pages to pfns
++ *
++ * For each page in the address space, this file contains one 64-bit
++ * entry representing the corresponding physical page frame number
++ * (PFN) if the page is present. If there is a swap entry for the
++ * physical page, then an encoding of the swap file number and the
++ * page's offset into the swap file are returned. If no page is
++ * present at all, PM_NOT_PRESENT is returned. This allows determining
++ * precisely which pages are mapped (or in swap) and comparing mapped
++ * pages between processes.
++ *
++ * Efficient users of this interface will use /proc/pid/maps to
++ * determine which areas of memory are actually mapped and llseek to
++ * skip over unmapped regions.
++ */
++static ssize_t pagemap_read(struct file *file, char __user *buf,
++			    size_t count, loff_t *ppos)
+ {
+-	struct proc_maps_private *priv = m->private;
+-	unsigned long last_addr = m->version;
++	struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
++	struct page **pages, *page;
++	unsigned long uaddr, uend;
+ 	struct mm_struct *mm;
+-	struct vm_area_struct *vma, *tail_vma = NULL;
+-	loff_t l = *pos;
+-
+-	/* Clear the per syscall fields in priv */
+-	priv->task = NULL;
+-	priv->tail_vma = NULL;
++	struct pagemapread pm;
++	int pagecount;
++	int ret = -ESRCH;
+ 
+-	/*
+-	 * We remember last_addr rather than next_addr to hit with
+-	 * mmap_cache most of the time. We have zero last_addr at
+-	 * the beginning and also after lseek. We will have -1 last_addr
+-	 * after the end of the vmas.
+-	 */
++	if (!task)
++		goto out;
+ 
+-	if (last_addr == -1UL)
+-		return NULL;
++	ret = -EACCES;
++	if (!ptrace_may_attach(task))
++		goto out;
+ 
+-	priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
+-	if (!priv->task)
+-		return NULL;
++	ret = -EINVAL;
++	/* file position must be aligned */
++	if (*ppos % PM_ENTRY_BYTES)
++		goto out;
+ 
+-	mm = mm_for_maps(priv->task);
++	ret = 0;
++	mm = get_task_mm(task);
+ 	if (!mm)
+-		return NULL;
+-
+-	priv->tail_vma = tail_vma = get_gate_vma(priv->task);
+-
+-	/* Start with last addr hint */
+-	if (last_addr && (vma = find_vma(mm, last_addr))) {
+-		vma = vma->vm_next;
+ 		goto out;
+-	}
+ 
+-	/*
+-	 * Check the vma index is within the range and do
+-	 * sequential scan until m_index.
+-	 */
+-	vma = NULL;
+-	if ((unsigned long)l < mm->map_count) {
+-		vma = mm->mmap;
+-		while (l-- && vma)
+-			vma = vma->vm_next;
+-		goto out;
+-	}
++	ret = -ENOMEM;
++	uaddr = (unsigned long)buf & PAGE_MASK;
++	uend = (unsigned long)(buf + count);
++	pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE;
++	pages = kmalloc(pagecount * sizeof(struct page *), GFP_KERNEL);
++	if (!pages)
++		goto out_task;
+ 
+-	if (l != mm->map_count)
+-		tail_vma = NULL; /* After gate vma */
++	down_read(&current->mm->mmap_sem);
++	ret = get_user_pages(current, current->mm, uaddr, pagecount,
++			     1, 0, pages, NULL);
++	up_read(&current->mm->mmap_sem);
+ 
+-out:
+-	if (vma)
+-		return vma;
++	if (ret < 0)
++		goto out_free;
+ 
+-	/* End of vmas has been reached */
+-	m->version = (tail_vma != NULL)? 0: -1UL;
+-	up_read(&mm->mmap_sem);
+-	mmput(mm);
+-	return tail_vma;
+-}
++	pm.out = buf;
++	pm.end = buf + count;
+ 
+-static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
+-{
+-	if (vma && vma != priv->tail_vma) {
+-		struct mm_struct *mm = vma->vm_mm;
+-		up_read(&mm->mmap_sem);
+-		mmput(mm);
++	if (!ptrace_may_attach(task)) {
++		ret = -EIO;
++	} else {
++		unsigned long src = *ppos;
++		unsigned long svpfn = src / PM_ENTRY_BYTES;
++		unsigned long start_vaddr = svpfn << PAGE_SHIFT;
++		unsigned long end_vaddr = TASK_SIZE_OF(task);
++
++		/* watch out for wraparound */
++		if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT)
++			start_vaddr = end_vaddr;
++
++		/*
++		 * The odds are that this will stop walking way
++		 * before end_vaddr, because the length of the
++		 * user buffer is tracked in "pm", and the walk
++		 * will stop when we hit the end of the buffer.
++		 */
++		ret = walk_page_range(mm, start_vaddr, end_vaddr,
++					&pagemap_walk, &pm);
++		if (ret == PM_END_OF_BUFFER)
++			ret = 0;
++		/* don't need mmap_sem for these, but this looks cleaner */
++		*ppos += pm.out - buf;
++		if (!ret)
++			ret = pm.out - buf;
+ 	}
+-}
+-
+-static void *m_next(struct seq_file *m, void *v, loff_t *pos)
+-{
+-	struct proc_maps_private *priv = m->private;
+-	struct vm_area_struct *vma = v;
+-	struct vm_area_struct *tail_vma = priv->tail_vma;
+-
+-	(*pos)++;
+-	if (vma && (vma != tail_vma) && vma->vm_next)
+-		return vma->vm_next;
+-	vma_stop(priv, vma);
+-	return (vma != tail_vma)? tail_vma: NULL;
+-}
+-
+-static void m_stop(struct seq_file *m, void *v)
+-{
+-	struct proc_maps_private *priv = m->private;
+-	struct vm_area_struct *vma = v;
+ 
+-	vma_stop(priv, vma);
+-	if (priv->task)
+-		put_task_struct(priv->task);
+-}
+-
+-static struct seq_operations proc_pid_maps_op = {
+-	.start	= m_start,
+-	.next	= m_next,
+-	.stop	= m_stop,
+-	.show	= show_map
+-};
+-
+-static struct seq_operations proc_pid_smaps_op = {
+-	.start	= m_start,
+-	.next	= m_next,
+-	.stop	= m_stop,
+-	.show	= show_smap
+-};
+-
+-static int do_maps_open(struct inode *inode, struct file *file,
+-			struct seq_operations *ops)
+-{
+-	struct proc_maps_private *priv;
+-	int ret = -ENOMEM;
+-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+-	if (priv) {
+-		priv->pid = proc_pid(inode);
+-		ret = seq_open(file, ops);
+-		if (!ret) {
+-			struct seq_file *m = file->private_data;
+-			m->private = priv;
+-		} else {
+-			kfree(priv);
+-		}
++	for (; pagecount; pagecount--) {
++		page = pages[pagecount-1];
++		if (!PageReserved(page))
++			SetPageDirty(page);
++		page_cache_release(page);
+ 	}
++	mmput(mm);
++out_free:
++	kfree(pages);
++out_task:
++	put_task_struct(task);
++out:
+ 	return ret;
+ }
+ 
+-static int maps_open(struct inode *inode, struct file *file)
+-{
+-	return do_maps_open(inode, file, &proc_pid_maps_op);
+-}
+-
+-const struct file_operations proc_maps_operations = {
+-	.open		= maps_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= seq_release_private,
++const struct file_operations proc_pagemap_operations = {
++	.llseek		= mem_lseek, /* borrow this */
++	.read		= pagemap_read,
+ };
++#endif /* CONFIG_PROC_PAGE_MONITOR */
+ 
+ #ifdef CONFIG_NUMA
+ extern int show_numa_map(struct seq_file *m, void *v);
+@@ -545,15 +753,3 @@ const struct file_operations proc_numa_maps_operations = {
+ 	.release	= seq_release_private,
+ };
+ #endif
+-
+-static int smaps_open(struct inode *inode, struct file *file)
+-{
+-	return do_maps_open(inode, file, &proc_pid_smaps_op);
+-}
+-
+-const struct file_operations proc_smaps_operations = {
+-	.open		= smaps_open,
+-	.read		= seq_read,
+-	.llseek		= seq_lseek,
+-	.release	= seq_release_private,
+-};
 diff --git a/fs/read_write.c b/fs/read_write.c
 index ea1f94c..1c177f2 100644
 --- a/fs/read_write.c
@@ -797136,6 +861196,72 @@
  	res = -ENOENT;
  	if (!IS_DEADDIR(inode)) {
  		res = file->f_op->readdir(file, buf, filler);
+diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
+index 16b331d..f491ceb 100644
+--- a/fs/reiserfs/bitmap.c
++++ b/fs/reiserfs/bitmap.c
+@@ -272,7 +272,7 @@ static inline int block_group_used(struct super_block *s, u32 id)
+ 
+ 	/* If we don't have cached information on this bitmap block, we're
+ 	 * going to have to load it later anyway. Loading it here allows us
+-	 * to make a better decision. This favors long-term performace gain
++	 * to make a better decision. This favors long-term performance gain
+ 	 * with a better on-disk layout vs. a short term gain of skipping the
+ 	 * read and potentially having a bad placement. */
+ 	if (info->free_count == UINT_MAX) {
+@@ -663,7 +663,7 @@ static inline void new_hashed_relocation(reiserfs_blocknr_hint_t * hint)
+ 
+ /*
+  * Relocation based on dirid, hashing them into a given bitmap block
+- * files. Formatted nodes are unaffected, a seperate policy covers them
++ * files. Formatted nodes are unaffected, a separate policy covers them
+  */
+ static void dirid_groups(reiserfs_blocknr_hint_t * hint)
+ {
+@@ -688,7 +688,7 @@ static void dirid_groups(reiserfs_blocknr_hint_t * hint)
+ 
+ /*
+  * Relocation based on oid, hashing them into a given bitmap block
+- * files. Formatted nodes are unaffected, a seperate policy covers them
++ * files. Formatted nodes are unaffected, a separate policy covers them
+  */
+ static void oid_groups(reiserfs_blocknr_hint_t * hint)
+ {
+diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
+index 231fd5c..1953098 100644
+--- a/fs/reiserfs/inode.c
++++ b/fs/reiserfs/inode.c
+@@ -2143,7 +2143,7 @@ int reiserfs_truncate_file(struct inode *p_s_inode, int update_timestamps)
+ 		/* if we are not on a block boundary */
+ 		if (length) {
+ 			length = blocksize - length;
+-			zero_user_page(page, offset, length, KM_USER0);
++			zero_user(page, offset, length);
+ 			if (buffer_mapped(bh) && bh->b_blocknr != 0) {
+ 				mark_buffer_dirty(bh);
+ 			}
+@@ -2367,7 +2367,7 @@ static int reiserfs_write_full_page(struct page *page,
+ 			unlock_page(page);
+ 			return 0;
+ 		}
+-		zero_user_page(page, last_offset, PAGE_CACHE_SIZE - last_offset, KM_USER0);
++		zero_user_segment(page, last_offset, PAGE_CACHE_SIZE);
+ 	}
+ 	bh = head;
+ 	block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits);
+diff --git a/fs/signalfd.c b/fs/signalfd.c
+index fb7f7e8..2d3e107 100644
+--- a/fs/signalfd.c
++++ b/fs/signalfd.c
+@@ -66,7 +66,7 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
+ 	BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
+ 
+ 	/*
+-	 * Unused memebers should be zero ...
++	 * Unused members should be zero ...
+ 	 */
+ 	err = __clear_user(uinfo, sizeof(*uinfo));
+ 
 diff --git a/fs/smbfs/Makefile b/fs/smbfs/Makefile
 index 6673ee8..4faf8c4 100644
 --- a/fs/smbfs/Makefile
@@ -797164,6 +861290,24 @@
 -	@echo >> proto2.h ""
 -	cproto -E "gcc -E" -e -v -I $(TOPDIR)/include -DMAKING_PROTO -D__KERNEL__ $(SRC) >> proto2.h
 -	mv proto2.h proto.h
+diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c
+index 9416ead..4e5c22c 100644
+--- a/fs/smbfs/inode.c
++++ b/fs/smbfs/inode.c
+@@ -500,6 +500,13 @@ static int smb_fill_super(struct super_block *sb, void *raw_data, int silent)
+ 	struct smb_fattr root;
+ 	int ver;
+ 	void *mem;
++	static int warn_count;
++
++	if (warn_count < 5) {
++		warn_count++;
++		printk(KERN_EMERG "smbfs is deprecated and will be removed"
++			"from the 2.6.27 kernel.  Please migrate to cifs\n");
++	}
+ 
+ 	if (!raw_data)
+ 		goto out_no_data;
 diff --git a/fs/smbfs/request.c b/fs/smbfs/request.c
 index ca4b2d5..45f4593 100644
 --- a/fs/smbfs/request.c
@@ -797585,6 +861729,417 @@
  
  	return 0;
  }
+diff --git a/fs/timerfd.c b/fs/timerfd.c
+index 61983f3..10c80b5 100644
+--- a/fs/timerfd.c
++++ b/fs/timerfd.c
+@@ -25,13 +25,15 @@ struct timerfd_ctx {
+ 	struct hrtimer tmr;
+ 	ktime_t tintv;
+ 	wait_queue_head_t wqh;
++	u64 ticks;
+ 	int expired;
++	int clockid;
+ };
+ 
+ /*
+  * This gets called when the timer event triggers. We set the "expired"
+  * flag, but we do not re-arm the timer (in case it's necessary,
+- * tintv.tv64 != 0) until the timer is read.
++ * tintv.tv64 != 0) until the timer is accessed.
+  */
+ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
+ {
+@@ -40,13 +42,24 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
+ 
+ 	spin_lock_irqsave(&ctx->wqh.lock, flags);
+ 	ctx->expired = 1;
++	ctx->ticks++;
+ 	wake_up_locked(&ctx->wqh);
+ 	spin_unlock_irqrestore(&ctx->wqh.lock, flags);
+ 
+ 	return HRTIMER_NORESTART;
+ }
+ 
+-static void timerfd_setup(struct timerfd_ctx *ctx, int clockid, int flags,
++static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
++{
++	ktime_t now, remaining;
++
++	now = ctx->tmr.base->get_time();
++	remaining = ktime_sub(ctx->tmr.expires, now);
++
++	return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
++}
++
++static void timerfd_setup(struct timerfd_ctx *ctx, int flags,
+ 			  const struct itimerspec *ktmr)
+ {
+ 	enum hrtimer_mode htmode;
+@@ -57,8 +70,9 @@ static void timerfd_setup(struct timerfd_ctx *ctx, int clockid, int flags,
+ 
+ 	texp = timespec_to_ktime(ktmr->it_value);
+ 	ctx->expired = 0;
++	ctx->ticks = 0;
+ 	ctx->tintv = timespec_to_ktime(ktmr->it_interval);
+-	hrtimer_init(&ctx->tmr, clockid, htmode);
++	hrtimer_init(&ctx->tmr, ctx->clockid, htmode);
+ 	ctx->tmr.expires = texp;
+ 	ctx->tmr.function = timerfd_tmrproc;
+ 	if (texp.tv64 != 0)
+@@ -83,7 +97,7 @@ static unsigned int timerfd_poll(struct file *file, poll_table *wait)
+ 	poll_wait(file, &ctx->wqh, wait);
+ 
+ 	spin_lock_irqsave(&ctx->wqh.lock, flags);
+-	if (ctx->expired)
++	if (ctx->ticks)
+ 		events |= POLLIN;
+ 	spin_unlock_irqrestore(&ctx->wqh.lock, flags);
+ 
+@@ -102,11 +116,11 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
+ 		return -EINVAL;
+ 	spin_lock_irq(&ctx->wqh.lock);
+ 	res = -EAGAIN;
+-	if (!ctx->expired && !(file->f_flags & O_NONBLOCK)) {
++	if (!ctx->ticks && !(file->f_flags & O_NONBLOCK)) {
+ 		__add_wait_queue(&ctx->wqh, &wait);
+ 		for (res = 0;;) {
+ 			set_current_state(TASK_INTERRUPTIBLE);
+-			if (ctx->expired) {
++			if (ctx->ticks) {
+ 				res = 0;
+ 				break;
+ 			}
+@@ -121,22 +135,21 @@ static ssize_t timerfd_read(struct file *file, char __user *buf, size_t count,
+ 		__remove_wait_queue(&ctx->wqh, &wait);
+ 		__set_current_state(TASK_RUNNING);
+ 	}
+-	if (ctx->expired) {
+-		ctx->expired = 0;
+-		if (ctx->tintv.tv64 != 0) {
++	if (ctx->ticks) {
++		ticks = ctx->ticks;
++		if (ctx->expired && ctx->tintv.tv64) {
+ 			/*
+ 			 * If tintv.tv64 != 0, this is a periodic timer that
+ 			 * needs to be re-armed. We avoid doing it in the timer
+ 			 * callback to avoid DoS attacks specifying a very
+ 			 * short timer period.
+ 			 */
+-			ticks = (u64)
+-				hrtimer_forward(&ctx->tmr,
+-						hrtimer_cb_get_time(&ctx->tmr),
+-						ctx->tintv);
++			ticks += hrtimer_forward_now(&ctx->tmr,
++						     ctx->tintv) - 1;
+ 			hrtimer_restart(&ctx->tmr);
+-		} else
+-			ticks = 1;
++		}
++		ctx->expired = 0;
++		ctx->ticks = 0;
+ 	}
+ 	spin_unlock_irq(&ctx->wqh.lock);
+ 	if (ticks)
+@@ -150,76 +163,132 @@ static const struct file_operations timerfd_fops = {
+ 	.read		= timerfd_read,
+ };
+ 
+-asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+-			    const struct itimerspec __user *utmr)
++static struct file *timerfd_fget(int fd)
++{
++	struct file *file;
++
++	file = fget(fd);
++	if (!file)
++		return ERR_PTR(-EBADF);
++	if (file->f_op != &timerfd_fops) {
++		fput(file);
++		return ERR_PTR(-EINVAL);
++	}
++
++	return file;
++}
++
++asmlinkage long sys_timerfd_create(int clockid, int flags)
+ {
+-	int error;
++	int error, ufd;
+ 	struct timerfd_ctx *ctx;
+ 	struct file *file;
+ 	struct inode *inode;
+-	struct itimerspec ktmr;
+-
+-	if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
+-		return -EFAULT;
+ 
++	if (flags)
++		return -EINVAL;
+ 	if (clockid != CLOCK_MONOTONIC &&
+ 	    clockid != CLOCK_REALTIME)
+ 		return -EINVAL;
++
++	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
++	if (!ctx)
++		return -ENOMEM;
++
++	init_waitqueue_head(&ctx->wqh);
++	ctx->clockid = clockid;
++	hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
++
++	error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]",
++				 &timerfd_fops, ctx);
++	if (error) {
++		kfree(ctx);
++		return error;
++	}
++
++	return ufd;
++}
++
++asmlinkage long sys_timerfd_settime(int ufd, int flags,
++				    const struct itimerspec __user *utmr,
++				    struct itimerspec __user *otmr)
++{
++	struct file *file;
++	struct timerfd_ctx *ctx;
++	struct itimerspec ktmr, kotmr;
++
++	if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
++		return -EFAULT;
++
+ 	if (!timespec_valid(&ktmr.it_value) ||
+ 	    !timespec_valid(&ktmr.it_interval))
+ 		return -EINVAL;
+ 
+-	if (ufd == -1) {
+-		ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+-		if (!ctx)
+-			return -ENOMEM;
+-
+-		init_waitqueue_head(&ctx->wqh);
+-
+-		timerfd_setup(ctx, clockid, flags, &ktmr);
+-
+-		/*
+-		 * When we call this, the initialization must be complete, since
+-		 * anon_inode_getfd() will install the fd.
+-		 */
+-		error = anon_inode_getfd(&ufd, &inode, &file, "[timerfd]",
+-					 &timerfd_fops, ctx);
+-		if (error)
+-			goto err_tmrcancel;
+-	} else {
+-		file = fget(ufd);
+-		if (!file)
+-			return -EBADF;
+-		ctx = file->private_data;
+-		if (file->f_op != &timerfd_fops) {
+-			fput(file);
+-			return -EINVAL;
+-		}
+-		/*
+-		 * We need to stop the existing timer before reprogramming
+-		 * it to the new values.
+-		 */
+-		for (;;) {
+-			spin_lock_irq(&ctx->wqh.lock);
+-			if (hrtimer_try_to_cancel(&ctx->tmr) >= 0)
+-				break;
+-			spin_unlock_irq(&ctx->wqh.lock);
+-			cpu_relax();
+-		}
+-		/*
+-		 * Re-program the timer to the new value ...
+-		 */
+-		timerfd_setup(ctx, clockid, flags, &ktmr);
++	file = timerfd_fget(ufd);
++	if (IS_ERR(file))
++		return PTR_ERR(file);
++	ctx = file->private_data;
+ 
++	/*
++	 * We need to stop the existing timer before reprogramming
++	 * it to the new values.
++	 */
++	for (;;) {
++		spin_lock_irq(&ctx->wqh.lock);
++		if (hrtimer_try_to_cancel(&ctx->tmr) >= 0)
++			break;
+ 		spin_unlock_irq(&ctx->wqh.lock);
+-		fput(file);
++		cpu_relax();
+ 	}
+ 
+-	return ufd;
++	/*
++	 * If the timer is expired and it's periodic, we need to advance it
++	 * because the caller may want to know the previous expiration time.
++	 * We do not update "ticks" and "expired" since the timer will be
++	 * re-programmed again in the following timerfd_setup() call.
++	 */
++	if (ctx->expired && ctx->tintv.tv64)
++		hrtimer_forward_now(&ctx->tmr, ctx->tintv);
+ 
+-err_tmrcancel:
+-	hrtimer_cancel(&ctx->tmr);
+-	kfree(ctx);
+-	return error;
++	kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
++	kotmr.it_interval = ktime_to_timespec(ctx->tintv);
++
++	/*
++	 * Re-program the timer to the new value ...
++	 */
++	timerfd_setup(ctx, flags, &ktmr);
++
++	spin_unlock_irq(&ctx->wqh.lock);
++	fput(file);
++	if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr)))
++		return -EFAULT;
++
++	return 0;
++}
++
++asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr)
++{
++	struct file *file;
++	struct timerfd_ctx *ctx;
++	struct itimerspec kotmr;
++
++	file = timerfd_fget(ufd);
++	if (IS_ERR(file))
++		return PTR_ERR(file);
++	ctx = file->private_data;
++
++	spin_lock_irq(&ctx->wqh.lock);
++	if (ctx->expired && ctx->tintv.tv64) {
++		ctx->expired = 0;
++		ctx->ticks +=
++			hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1;
++		hrtimer_restart(&ctx->tmr);
++	}
++	kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx));
++	kotmr.it_interval = ktime_to_timespec(ctx->tintv);
++	spin_unlock_irq(&ctx->wqh.lock);
++	fput(file);
++
++	return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0;
+ }
+ 
+diff --git a/fs/xattr.c b/fs/xattr.c
+index 6645b73..f7c8f87 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -105,6 +105,33 @@ out:
+ EXPORT_SYMBOL_GPL(vfs_setxattr);
+ 
+ ssize_t
++xattr_getsecurity(struct inode *inode, const char *name, void *value,
++			size_t size)
++{
++	void *buffer = NULL;
++	ssize_t len;
++
++	if (!value || !size) {
++		len = security_inode_getsecurity(inode, name, &buffer, false);
++		goto out_noalloc;
++	}
++
++	len = security_inode_getsecurity(inode, name, &buffer, true);
++	if (len < 0)
++		return len;
++	if (size < len) {
++		len = -ERANGE;
++		goto out;
++	}
++	memcpy(value, buffer, len);
++out:
++	security_release_secctx(buffer, len);
++out_noalloc:
++	return len;
++}
++EXPORT_SYMBOL_GPL(xattr_getsecurity);
++
++ssize_t
+ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+ {
+ 	struct inode *inode = dentry->d_inode;
+@@ -118,23 +145,23 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
+ 	if (error)
+ 		return error;
+ 
+-	if (inode->i_op->getxattr)
+-		error = inode->i_op->getxattr(dentry, name, value, size);
+-	else
+-		error = -EOPNOTSUPP;
+-
+ 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
+ 				XATTR_SECURITY_PREFIX_LEN)) {
+ 		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
+-		int ret = security_inode_getsecurity(inode, suffix, value,
+-						     size, error);
++		int ret = xattr_getsecurity(inode, suffix, value, size);
+ 		/*
+ 		 * Only overwrite the return value if a security module
+ 		 * is actually active.
+ 		 */
+-		if (ret != -EOPNOTSUPP)
+-			error = ret;
++		if (ret == -EOPNOTSUPP)
++			goto nolsm;
++		return ret;
+ 	}
++nolsm:
++	if (inode->i_op->getxattr)
++		error = inode->i_op->getxattr(dentry, name, value, size);
++	else
++		error = -EOPNOTSUPP;
+ 
+ 	return error;
+ }
+diff --git a/fs/xfs/linux-2.6/kmem.c b/fs/xfs/linux-2.6/kmem.c
+index ed2b16d..e040f1c 100644
+--- a/fs/xfs/linux-2.6/kmem.c
++++ b/fs/xfs/linux-2.6/kmem.c
+@@ -92,8 +92,7 @@ kmem_zalloc_greedy(size_t *size, size_t minsize, size_t maxsize,
+ void
+ kmem_free(void *ptr, size_t size)
+ {
+-	if (((unsigned long)ptr < VMALLOC_START) ||
+-	    ((unsigned long)ptr >= VMALLOC_END)) {
++	if (!is_vmalloc_addr(ptr)) {
+ 		kfree(ptr);
+ 	} else {
+ 		vfree(ptr);
+diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
+index a49dd8d..0382c19 100644
+--- a/fs/xfs/linux-2.6/xfs_buf.c
++++ b/fs/xfs/linux-2.6/xfs_buf.c
+@@ -709,8 +709,7 @@ static inline struct page *
+ mem_to_page(
+ 	void			*addr)
+ {
+-	if (((unsigned long)addr < VMALLOC_START) ||
+-	    ((unsigned long)addr >= VMALLOC_END)) {
++	if ((!is_vmalloc_addr(addr))) {
+ 		return virt_to_page(addr);
+ 	} else {
+ 		return vmalloc_to_page(addr);
+diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
+index d6a8ddd..6f614f3 100644
+--- a/fs/xfs/linux-2.6/xfs_lrw.c
++++ b/fs/xfs/linux-2.6/xfs_lrw.c
+@@ -155,7 +155,7 @@ xfs_iozero(
+ 		if (status)
+ 			break;
+ 
+-		zero_user_page(page, offset, bytes, KM_USER0);
++		zero_user(page, offset, bytes);
+ 
+ 		status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
+ 					page, fsdata);
 diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
 index 7b74b60..fb7171b 100644
 --- a/include/acpi/acpi_bus.h
@@ -797599,9 +862154,18 @@
  /*
   * External Functions
 diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
-index 9512f04..b729e64 100644
+index 9512f04..d970f7f 100644
 --- a/include/acpi/acpixf.h
 +++ b/include/acpi/acpixf.h
+@@ -85,7 +85,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function);
+ #endif
+ 
+ /*
+- * ACPI Memory managment
++ * ACPI Memory management
+  */
+ void *acpi_allocate(u32 size);
+ 
 @@ -335,6 +335,8 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state);
  
  acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void);
@@ -797611,6 +862175,19 @@
  acpi_status acpi_leave_sleep_state(u8 sleep_state);
  
  #endif				/* __ACXFACE_H__ */
+diff --git a/include/acpi/processor.h b/include/acpi/processor.h
+index 76411b1..6e253b5 100644
+--- a/include/acpi/processor.h
++++ b/include/acpi/processor.h
+@@ -182,7 +182,7 @@ struct acpi_processor_throttling {
+ /* Limit Interface */
+ 
+ struct acpi_processor_lx {
+-	int px;			/* performace state */
++	int px;			/* performance state */
+ 	int tx;			/* throttle level */
+ };
+ 
 diff --git a/include/acpi/reboot.h b/include/acpi/reboot.h
 new file mode 100644
 index 0000000..8857f57
@@ -797638,6 +862215,71 @@
  #define flush_agp_cache() mb()
  
  /* Convert a physical address to an address suitable for the GART. */
+diff --git a/include/asm-alpha/atomic.h b/include/asm-alpha/atomic.h
+index f5cb7b8..ca88e54 100644
+--- a/include/asm-alpha/atomic.h
++++ b/include/asm-alpha/atomic.h
+@@ -100,7 +100,7 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v)
+ /*
+  * Same as above, but return the result value
+  */
+-static __inline__ long atomic_add_return(int i, atomic_t * v)
++static inline int atomic_add_return(int i, atomic_t *v)
+ {
+ 	long temp, result;
+ 	smp_mb();
+diff --git a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
+index 30ee766..d5b10ef 100644
+--- a/include/asm-alpha/pci.h
++++ b/include/asm-alpha/pci.h
+@@ -4,6 +4,7 @@
+ #ifdef __KERNEL__
+ 
+ #include <linux/spinlock.h>
++#include <linux/dma-mapping.h>
+ #include <asm/scatterlist.h>
+ #include <asm/machvec.h>
+ 
+diff --git a/include/asm-alpha/pgalloc.h b/include/asm-alpha/pgalloc.h
+index 471864e..fdbedac 100644
+--- a/include/asm-alpha/pgalloc.h
++++ b/include/asm-alpha/pgalloc.h
+@@ -31,7 +31,7 @@ pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+ extern pgd_t *pgd_alloc(struct mm_struct *mm);
+ 
+ static inline void
+-pgd_free(pgd_t *pgd)
++pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_page((unsigned long)pgd);
+ }
+@@ -44,7 +44,7 @@ pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+ }
+ 
+ static inline void
+-pmd_free(pmd_t *pmd)
++pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	free_page((unsigned long)pmd);
+ }
+@@ -52,7 +52,7 @@ pmd_free(pmd_t *pmd)
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+ 
+ static inline void
+-pte_free_kernel(pte_t *pte)
++pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+@@ -67,7 +67,7 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+ }
+ 
+ static inline void
+-pte_free(struct page *page)
++pte_free(struct mm_struct *mm, struct page *page)
+ {
+ 	__free_page(page);
+ }
 diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h
 index 1fede7f..08c9793 100644
 --- a/include/asm-alpha/socket.h
@@ -797649,8 +862291,22 @@
 +#define SO_MARK			36
 +
  #endif /* _ASM_SOCKET_H */
+diff --git a/include/asm-alpha/tlb.h b/include/asm-alpha/tlb.h
+index aa91335..c136365 100644
+--- a/include/asm-alpha/tlb.h
++++ b/include/asm-alpha/tlb.h
+@@ -9,7 +9,7 @@
+ 
+ #include <asm-generic/tlb.h>
+ 
+-#define __pte_free_tlb(tlb,pte)			pte_free(pte)
+-#define __pmd_free_tlb(tlb,pmd)			pmd_free(pmd)
++#define __pte_free_tlb(tlb, pte)			pte_free((tlb)->mm, pte)
++#define __pmd_free_tlb(tlb, pmd)			pmd_free((tlb)->mm, pmd)
+  
+ #endif
 diff --git a/include/asm-alpha/tlbflush.h b/include/asm-alpha/tlbflush.h
-index eefab3f..b9e9147 100644
+index eefab3f..9d87aaa 100644
 --- a/include/asm-alpha/tlbflush.h
 +++ b/include/asm-alpha/tlbflush.h
 @@ -3,6 +3,7 @@
@@ -797661,6 +862317,30 @@
  
  #ifndef __EXTERN_INLINE
  #define __EXTERN_INLINE extern inline
+@@ -141,6 +142,10 @@ extern void flush_tlb_range(struct vm_area_struct *, unsigned long,
+ 
+ #endif /* CONFIG_SMP */
+ 
+-#define flush_tlb_kernel_range(start, end) flush_tlb_all()
++static inline void flush_tlb_kernel_range(unsigned long start,
++					unsigned long end)
++{
++	flush_tlb_all();
++}
+ 
+ #endif /* _ALPHA_TLBFLUSH_H */
+diff --git a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
+index 29bf2fd..5b5c174 100644
+--- a/include/asm-alpha/unistd.h
++++ b/include/asm-alpha/unistd.h
+@@ -442,7 +442,6 @@
+ #define __ARCH_WANT_OLD_READDIR
+ #define __ARCH_WANT_STAT64
+ #define __ARCH_WANT_SYS_GETHOSTNAME
+-#define __ARCH_WANT_SYS_SOCKETCALL
+ #define __ARCH_WANT_SYS_FADVISE64
+ #define __ARCH_WANT_SYS_GETPGRP
+ #define __ARCH_WANT_SYS_OLD_GETRLIMIT
 diff --git a/include/asm-arm/arch-at91/at91_lcdc.h b/include/asm-arm/arch-at91/at91_lcdc.h
 deleted file mode 100644
 index ab040a4..0000000
@@ -797815,6 +862495,19 @@
 -#define AT91_LCDC_LUT_(n)	(0x0c00 + ((n)*4))	/* Palette Entry 0..255 */
 -
 -#endif
+diff --git a/include/asm-arm/arch-at91/at91_mci.h b/include/asm-arm/arch-at91/at91_mci.h
+index c2e11cc..1551fc2 100644
+--- a/include/asm-arm/arch-at91/at91_mci.h
++++ b/include/asm-arm/arch-at91/at91_mci.h
+@@ -89,7 +89,7 @@
+ #define		AT91_MCI_ENDRX		(1 <<  6)	/* End of RX Buffer */
+ #define		AT91_MCI_ENDTX		(1 <<  7)	/* End fo TX Buffer */
+ #define		AT91_MCI_SDIOIRQA	(1 <<  8)	/* SDIO Interrupt for Slot A */
+-#define		At91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B [AT91RM9200 only] */
++#define		AT91_MCI_SDIOIRQB	(1 <<  9)	/* SDIO Interrupt for Slot B */
+ #define		AT91_MCI_RXBUFF		(1 << 14)	/* RX Buffer Full */
+ #define		AT91_MCI_TXBUFE		(1 << 15)	/* TX Buffer Empty */
+ #define		AT91_MCI_RINDE		(1 << 16)	/* Response Index Error */
 diff --git a/include/asm-arm/arch-at91/at91_pmc.h b/include/asm-arm/arch-at91/at91_pmc.h
 index 33ff5b6..52cd8e5 100644
 --- a/include/asm-arm/arch-at91/at91_pmc.h
@@ -798181,6 +862874,40 @@
 +#define AT91_APB_SFR		(AT91_MATRIX + 0x134)	/* APB Bridge Special Function Register */
 +
 +#endif
+diff --git a/include/asm-arm/arch-at91/at91rm9200.h b/include/asm-arm/arch-at91/at91rm9200.h
+index 802891a..e8fc0b1 100644
+--- a/include/asm-arm/arch-at91/at91rm9200.h
++++ b/include/asm-arm/arch-at91/at91rm9200.h
+@@ -93,6 +93,11 @@
+ #define AT91_RTC	(0xfffffe00 - AT91_BASE_SYS)	/* Real-Time Clock */
+ #define AT91_MC		(0xffffff00 - AT91_BASE_SYS)	/* Memory Controllers */
+ 
++#define AT91_USART0	AT91RM9200_BASE_US0
++#define AT91_USART1	AT91RM9200_BASE_US1
++#define AT91_USART2	AT91RM9200_BASE_US2
++#define AT91_USART3	AT91RM9200_BASE_US3
++
+ #define AT91_MATRIX	0	/* not supported */
+ 
+ /*
+diff --git a/include/asm-arm/arch-at91/at91sam9260.h b/include/asm-arm/arch-at91/at91sam9260.h
+index 0427f86..c8934fe 100644
+--- a/include/asm-arm/arch-at91/at91sam9260.h
++++ b/include/asm-arm/arch-at91/at91sam9260.h
+@@ -99,6 +99,13 @@
+ #define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
+ #define AT91_GPBR	(0xfffffd50 - AT91_BASE_SYS)
+ 
++#define AT91_USART0	AT91SAM9260_BASE_US0
++#define AT91_USART1	AT91SAM9260_BASE_US1
++#define AT91_USART2	AT91SAM9260_BASE_US2
++#define AT91_USART3	AT91SAM9260_BASE_US3
++#define AT91_USART4	AT91SAM9260_BASE_US4
++#define AT91_USART5	AT91SAM9260_BASE_US5
++
+ 
+ /*
+  * Internal Memory.
 diff --git a/include/asm-arm/arch-at91/at91sam9260_matrix.h b/include/asm-arm/arch-at91/at91sam9260_matrix.h
 index aacb1e9..a8e9fec 100644
 --- a/include/asm-arm/arch-at91/at91sam9260_matrix.h
@@ -798194,6 +862921,36 @@
  #define			AT91_MATRIX_CS5A_SMC		(0 << 5)
  #define			AT91_MATRIX_CS5A_SMC_CF2	(1 << 5)
  #define		AT91_MATRIX_DBPUC		(1 << 8)	/* Data Bus Pull-up Configuration */
+diff --git a/include/asm-arm/arch-at91/at91sam9261.h b/include/asm-arm/arch-at91/at91sam9261.h
+index 9eb4595..c7c4778 100644
+--- a/include/asm-arm/arch-at91/at91sam9261.h
++++ b/include/asm-arm/arch-at91/at91sam9261.h
+@@ -84,6 +84,10 @@
+ #define AT91_WDT	(0xfffffd40 - AT91_BASE_SYS)
+ #define AT91_GPBR	(0xfffffd50 - AT91_BASE_SYS)
+ 
++#define AT91_USART0	AT91SAM9261_BASE_US0
++#define AT91_USART1	AT91SAM9261_BASE_US1
++#define AT91_USART2	AT91SAM9261_BASE_US2
++
+ 
+ /*
+  * Internal Memory.
+diff --git a/include/asm-arm/arch-at91/at91sam9263.h b/include/asm-arm/arch-at91/at91sam9263.h
+index 115c47a..018a647 100644
+--- a/include/asm-arm/arch-at91/at91sam9263.h
++++ b/include/asm-arm/arch-at91/at91sam9263.h
+@@ -101,6 +101,10 @@
+ #define AT91_RTT1	(0xfffffd50 - AT91_BASE_SYS)
+ #define AT91_GPBR	(0xfffffd60 - AT91_BASE_SYS)
+ 
++#define AT91_USART0	AT91SAM9263_BASE_US0
++#define AT91_USART1	AT91SAM9263_BASE_US1
++#define AT91_USART2	AT91SAM9263_BASE_US2
++
+ #define AT91_SMC	AT91_SMC0
+ 
+ /*
 diff --git a/include/asm-arm/arch-at91/at91sam9263_matrix.h b/include/asm-arm/arch-at91/at91sam9263_matrix.h
 index 6fc6e4b..72f6e66 100644
 --- a/include/asm-arm/arch-at91/at91sam9263_matrix.h
@@ -798207,6 +862964,22 @@
  #define		AT91_MATRIX_ARBT		(3    << 24)	/* Arbitration Type */
  #define			AT91_MATRIX_ARBT_ROUND_ROBIN	(0 << 24)
  #define			AT91_MATRIX_ARBT_FIXED_PRIORITY	(1 << 24)
+diff --git a/include/asm-arm/arch-at91/at91sam9rl.h b/include/asm-arm/arch-at91/at91sam9rl.h
+index 8a9708a..16d2832 100644
+--- a/include/asm-arm/arch-at91/at91sam9rl.h
++++ b/include/asm-arm/arch-at91/at91sam9rl.h
+@@ -94,6 +94,11 @@
+ #define AT91_GPBR	(0xfffffd60 - AT91_BASE_SYS)
+ #define AT91_RTC	(0xfffffe00 - AT91_BASE_SYS)
+ 
++#define AT91_USART0	AT91SAM9RL_BASE_US0
++#define AT91_USART1	AT91SAM9RL_BASE_US1
++#define AT91_USART2	AT91SAM9RL_BASE_US2
++#define AT91_USART3	AT91SAM9RL_BASE_US3
++
+ 
+ /*
+  * Internal Memory.
 diff --git a/include/asm-arm/arch-at91/at91sam9rl_matrix.h b/include/asm-arm/arch-at91/at91sam9rl_matrix.h
 index b15f11b..8422417 100644
 --- a/include/asm-arm/arch-at91/at91sam9rl_matrix.h
@@ -798393,6 +863166,65 @@
  #elif defined(CONFIG_ARCH_AT91X40)
  
  #define AT91X40_MASTER_CLOCK	40000000
+diff --git a/include/asm-arm/arch-at91/uncompress.h b/include/asm-arm/arch-at91/uncompress.h
+index 272a7e0..f5636a8 100644
+--- a/include/asm-arm/arch-at91/uncompress.h
++++ b/include/asm-arm/arch-at91/uncompress.h
+@@ -22,7 +22,23 @@
+ #define __ASM_ARCH_UNCOMPRESS_H
+ 
+ #include <asm/io.h>
+-#include <asm/arch/at91_dbgu.h>
++#include <linux/atmel_serial.h>
++
++#if defined(CONFIG_AT91_EARLY_DBGU)
++#define UART_OFFSET (AT91_DBGU + AT91_BASE_SYS)
++#elif defined(CONFIG_AT91_EARLY_USART0)
++#define UART_OFFSET AT91_USART0
++#elif defined(CONFIG_AT91_EARLY_USART1)
++#define UART_OFFSET AT91_USART1
++#elif defined(CONFIG_AT91_EARLY_USART2)
++#define UART_OFFSET AT91_USART2
++#elif defined(CONFIG_AT91_EARLY_USART3)
++#define UART_OFFSET AT91_USART3
++#elif defined(CONFIG_AT91_EARLY_USART4)
++#define UART_OFFSET AT91_USART4
++#elif defined(CONFIG_AT91_EARLY_USART5)
++#define UART_OFFSET AT91_USART5
++#endif
+ 
+ /*
+  * The following code assumes the serial port has already been
+@@ -33,22 +49,22 @@
+  */
+ static void putc(int c)
+ {
+-#ifdef AT91_DBGU
+-	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
++#ifdef UART_OFFSET
++	void __iomem *sys = (void __iomem *) UART_OFFSET;	/* physical address */
+ 
+-	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXRDY))
++	while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXRDY))
+ 		barrier();
+-	__raw_writel(c, sys + AT91_DBGU_THR);
++	__raw_writel(c, sys + ATMEL_US_THR);
+ #endif
+ }
+ 
+ static inline void flush(void)
+ {
+-#ifdef AT91_DBGU
+-	void __iomem *sys = (void __iomem *) AT91_BASE_SYS;	/* physical address */
++#ifdef UART_OFFSET
++	void __iomem *sys = (void __iomem *) UART_OFFSET;	/* physical address */
+ 
+ 	/* wait for transmission to complete */
+-	while (!(__raw_readl(sys + AT91_DBGU_SR) & AT91_DBGU_TXEMPTY))
++	while (!(__raw_readl(sys + ATMEL_US_CSR) & ATMEL_US_TXEMPTY))
+ 		barrier();
+ #endif
+ }
 diff --git a/include/asm-arm/arch-ep93xx/gpio.h b/include/asm-arm/arch-ep93xx/gpio.h
 index 1ee14a1..9b1864b 100644
 --- a/include/asm-arm/arch-ep93xx/gpio.h
@@ -798499,11 +863331,89 @@
  #define NR_EP93XX_IRQS			(64 + 24)
  
  #define EP93XX_BOARD_IRQ(x)		(NR_EP93XX_IRQS + (x))
+diff --git a/include/asm-arm/arch-ixp4xx/cpu.h b/include/asm-arm/arch-ixp4xx/cpu.h
+index d2523b3..2fa3d6b 100644
+--- a/include/asm-arm/arch-ixp4xx/cpu.h
++++ b/include/asm-arm/arch-ixp4xx/cpu.h
+@@ -28,4 +28,19 @@ extern unsigned int processor_id;
+ #define cpu_is_ixp46x()	((processor_id & IXP4XX_PROCESSOR_ID_MASK) == \
+ 			  IXP465_PROCESSOR_ID_VALUE)
+ 
++static inline u32 ixp4xx_read_feature_bits(void)
++{
++	unsigned int val = ~*IXP4XX_EXP_CFG2;
++	val &= ~IXP4XX_FEATURE_RESERVED;
++	if (!cpu_is_ixp46x())
++		val &= ~IXP4XX_FEATURE_IXP46X_ONLY;
++
++	return val;
++}
++
++static inline void ixp4xx_write_feature_bits(u32 value)
++{
++	*IXP4XX_EXP_CFG2 = ~value;
++}
++
+ #endif  /* _ASM_ARCH_CPU_H */
+diff --git a/include/asm-arm/arch-ixp4xx/dsmg600.h b/include/asm-arm/arch-ixp4xx/dsmg600.h
+index a19605a..b7673e1 100644
+--- a/include/asm-arm/arch-ixp4xx/dsmg600.h
++++ b/include/asm-arm/arch-ixp4xx/dsmg600.h
+@@ -40,18 +40,13 @@
+ /* Buttons */
+ 
+ #define DSMG600_PB_GPIO		15	/* power button */
+-#define DSMG600_PB_BM		(1L << DSMG600_PB_GPIO)
+-
+ #define DSMG600_RB_GPIO		3	/* reset button */
+ 
+-#define DSMG600_RB_IRQ		IRQ_IXP4XX_GPIO3
++/* Power control */
+ 
+ #define DSMG600_PO_GPIO		2	/* power off */
+ 
+ /* LEDs */
+ 
+ #define DSMG600_LED_PWR_GPIO	0
+-#define DSMG600_LED_PWR_BM	(1L << DSMG600_LED_PWR_GPIO)
+-
+ #define DSMG600_LED_WLAN_GPIO	14
+-#define DSMG600_LED_WLAN_BM	(1L << DSMG600_LED_WLAN_GPIO)
+diff --git a/include/asm-arm/arch-ixp4xx/hardware.h b/include/asm-arm/arch-ixp4xx/hardware.h
+index 297ceda..73e8dc3 100644
+--- a/include/asm-arm/arch-ixp4xx/hardware.h
++++ b/include/asm-arm/arch-ixp4xx/hardware.h
+@@ -27,13 +27,13 @@
+ 
+ #define pcibios_assign_all_busses()	1
+ 
++/* Register locations and bits */
++#include "ixp4xx-regs.h"
++
+ #ifndef __ASSEMBLER__
+ #include <asm/arch/cpu.h>
+ #endif
+ 
+-/* Register locations and bits */
+-#include "ixp4xx-regs.h"
+-
+ /* Platform helper functions and definitions */
+ #include "platform.h"
+ 
 diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h
-index eeeea90..9c5d235 100644
+index eeeea90..de181ce 100644
 --- a/include/asm-arm/arch-ixp4xx/io.h
 +++ b/include/asm-arm/arch-ixp4xx/io.h
-@@ -61,13 +61,13 @@ __ixp4xx_ioremap(unsigned long addr, size_t size, unsigned int mtype)
+@@ -13,6 +13,8 @@
+ #ifndef __ASM_ARM_ARCH_IO_H
+ #define __ASM_ARM_ARCH_IO_H
+ 
++#include <linux/bitops.h>
++
+ #include <asm/hardware.h>
+ 
+ #define IO_SPACE_LIMIT 0xffff0000
+@@ -61,13 +63,13 @@ __ixp4xx_ioremap(unsigned long addr, size_t size, unsigned int mtype)
  	if((addr < PCIBIOS_MIN_MEM) || (addr > 0x4fffffff))
  		return __arm_ioremap(addr, size, mtype);
  
@@ -798519,7 +863429,7 @@
  		__iounmap(addr);
  }
  
-@@ -141,9 +141,9 @@ __ixp4xx_writesw(volatile void __iomem *bus_addr, const u16 *vaddr, int count)
+@@ -141,9 +143,9 @@ __ixp4xx_writesw(volatile void __iomem *bus_addr, const u16 *vaddr, int count)
  static inline void 
  __ixp4xx_writel(u32 value, volatile void __iomem *p)
  {
@@ -798531,7 +863441,7 @@
  		return;
  	}
  
-@@ -208,11 +208,11 @@ __ixp4xx_readsw(const volatile void __iomem *bus_addr, u16 *vaddr, u32 count)
+@@ -208,11 +210,11 @@ __ixp4xx_readsw(const volatile void __iomem *bus_addr, u16 *vaddr, u32 count)
  static inline unsigned long 
  __ixp4xx_readl(const volatile void __iomem *p)
  {
@@ -798545,7 +863455,7 @@
  
  	if (ixp4xx_pci_read(addr, NP_CMD_MEMREAD, &data))
  		return 0xffffffff;
-@@ -438,7 +438,7 @@ __ixp4xx_ioread32(const void __iomem *addr)
+@@ -438,7 +440,7 @@ __ixp4xx_ioread32(const void __iomem *addr)
  		return	(unsigned int)__ixp4xx_inl(port & PIO_MASK);
  	else {
  #ifndef CONFIG_IXP4XX_INDIRECT_PCI
@@ -798554,7 +863464,7 @@
  #else
  		return (unsigned int)__ixp4xx_readl(addr);
  #endif
-@@ -523,7 +523,7 @@ __ixp4xx_iowrite32(u32 value, void __iomem *addr)
+@@ -523,7 +525,7 @@ __ixp4xx_iowrite32(u32 value, void __iomem *addr)
  		__ixp4xx_outl(value, port & PIO_MASK);
  	else
  #ifndef CONFIG_IXP4XX_INDIRECT_PCI
@@ -798563,8 +863473,212 @@
  #else
  		__ixp4xx_writel(value, addr);
  #endif
+diff --git a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
+index 5d949d7..68aca85 100644
+--- a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
++++ b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
+@@ -15,10 +15,6 @@
+  *
+  */
+ 
+-#ifndef __ASM_ARCH_HARDWARE_H__
+-#error "Do not include this directly, instead #include <asm/hardware.h>"
+-#endif
+-
+ #ifndef _ASM_ARM_IXP4XX_H_
+ #define _ASM_ARM_IXP4XX_H_
+ 
+@@ -587,24 +583,56 @@
+ #define UICR1_IM14	(1 << 6)	/* Interrupt mask ep 14 */
+ #define UICR1_IM15	(1 << 7)	/* Interrupt mask ep 15 */
+ 
+-#define USIR0_IR0	(1 << 0)	/* Interrup request ep 0 */
+-#define USIR0_IR1	(1 << 1)	/* Interrup request ep 1 */
+-#define USIR0_IR2	(1 << 2)	/* Interrup request ep 2 */
+-#define USIR0_IR3	(1 << 3)	/* Interrup request ep 3 */
+-#define USIR0_IR4	(1 << 4)	/* Interrup request ep 4 */
+-#define USIR0_IR5	(1 << 5)	/* Interrup request ep 5 */
+-#define USIR0_IR6	(1 << 6)	/* Interrup request ep 6 */
+-#define USIR0_IR7	(1 << 7)	/* Interrup request ep 7 */
+-
+-#define USIR1_IR8	(1 << 0)	/* Interrup request ep 8 */
+-#define USIR1_IR9	(1 << 1)	/* Interrup request ep 9 */
+-#define USIR1_IR10	(1 << 2)	/* Interrup request ep 10 */
+-#define USIR1_IR11	(1 << 3)	/* Interrup request ep 11 */
+-#define USIR1_IR12	(1 << 4)	/* Interrup request ep 12 */
+-#define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */
+-#define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */
+-#define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */
++#define USIR0_IR0	(1 << 0)	/* Interrupt request ep 0 */
++#define USIR0_IR1	(1 << 1)	/* Interrupt request ep 1 */
++#define USIR0_IR2	(1 << 2)	/* Interrupt request ep 2 */
++#define USIR0_IR3	(1 << 3)	/* Interrupt request ep 3 */
++#define USIR0_IR4	(1 << 4)	/* Interrupt request ep 4 */
++#define USIR0_IR5	(1 << 5)	/* Interrupt request ep 5 */
++#define USIR0_IR6	(1 << 6)	/* Interrupt request ep 6 */
++#define USIR0_IR7	(1 << 7)	/* Interrupt request ep 7 */
++
++#define USIR1_IR8	(1 << 0)	/* Interrupt request ep 8 */
++#define USIR1_IR9	(1 << 1)	/* Interrupt request ep 9 */
++#define USIR1_IR10	(1 << 2)	/* Interrupt request ep 10 */
++#define USIR1_IR11	(1 << 3)	/* Interrupt request ep 11 */
++#define USIR1_IR12	(1 << 4)	/* Interrupt request ep 12 */
++#define USIR1_IR13	(1 << 5)	/* Interrupt request ep 13 */
++#define USIR1_IR14	(1 << 6)	/* Interrupt request ep 14 */
++#define USIR1_IR15	(1 << 7)	/* Interrupt request ep 15 */
+ 
+ #define DCMD_LENGTH	0x01fff		/* length mask (max = 8K - 1) */
+ 
++/* "fuse" bits of IXP_EXP_CFG2 */
++#define IXP4XX_FEATURE_RCOMP		(1 << 0)
++#define IXP4XX_FEATURE_USB_DEVICE	(1 << 1)
++#define IXP4XX_FEATURE_HASH		(1 << 2)
++#define IXP4XX_FEATURE_AES		(1 << 3)
++#define IXP4XX_FEATURE_DES		(1 << 4)
++#define IXP4XX_FEATURE_HDLC		(1 << 5)
++#define IXP4XX_FEATURE_AAL		(1 << 6)
++#define IXP4XX_FEATURE_HSS		(1 << 7)
++#define IXP4XX_FEATURE_UTOPIA		(1 << 8)
++#define IXP4XX_FEATURE_NPEB_ETH0	(1 << 9)
++#define IXP4XX_FEATURE_NPEC_ETH		(1 << 10)
++#define IXP4XX_FEATURE_RESET_NPEA	(1 << 11)
++#define IXP4XX_FEATURE_RESET_NPEB	(1 << 12)
++#define IXP4XX_FEATURE_RESET_NPEC	(1 << 13)
++#define IXP4XX_FEATURE_PCI		(1 << 14)
++#define IXP4XX_FEATURE_ECC_TIMESYNC	(1 << 15)
++#define IXP4XX_FEATURE_UTOPIA_PHY_LIMIT	(3 << 16)
++#define IXP4XX_FEATURE_USB_HOST		(1 << 18)
++#define IXP4XX_FEATURE_NPEA_ETH		(1 << 19)
++#define IXP4XX_FEATURE_NPEB_ETH_1_TO_3	(1 << 20)
++#define IXP4XX_FEATURE_RSA		(1 << 21)
++#define IXP4XX_FEATURE_XSCALE_MAX_FREQ	(3 << 22)
++#define IXP4XX_FEATURE_RESERVED		(0xFF << 24)
++
++#define IXP4XX_FEATURE_IXP46X_ONLY (IXP4XX_FEATURE_ECC_TIMESYNC |	\
++				    IXP4XX_FEATURE_USB_HOST |		\
++				    IXP4XX_FEATURE_NPEA_ETH |		\
++				    IXP4XX_FEATURE_NPEB_ETH_1_TO_3 |	\
++				    IXP4XX_FEATURE_RSA |		\
++				    IXP4XX_FEATURE_XSCALE_MAX_FREQ)
++
+ #endif
+diff --git a/include/asm-arm/arch-ixp4xx/nas100d.h b/include/asm-arm/arch-ixp4xx/nas100d.h
+index 131e0a1..98d9378 100644
+--- a/include/asm-arm/arch-ixp4xx/nas100d.h
++++ b/include/asm-arm/arch-ixp4xx/nas100d.h
+@@ -38,15 +38,15 @@
+ 
+ /* Buttons */
+ 
+-#define NAS100D_PB_GPIO         14
+-#define NAS100D_RB_GPIO         4
++#define NAS100D_PB_GPIO         14   /* power button */
++#define NAS100D_RB_GPIO         4    /* reset button */
++
++/* Power control */
++
+ #define NAS100D_PO_GPIO         12   /* power off */
+ 
+-#define NAS100D_PB_IRQ          IRQ_IXP4XX_GPIO14
+-#define NAS100D_RB_IRQ          IRQ_IXP4XX_GPIO4
++/* LEDs */
+ 
+-/*
+-#define NAS100D_PB_BM           (1L << NAS100D_PB_GPIO)
+-#define NAS100D_PO_BM           (1L << NAS100D_PO_GPIO)
+-#define NAS100D_RB_BM           (1L << NAS100D_RB_GPIO)
+-*/
++#define NAS100D_LED_WLAN_GPIO	0
++#define NAS100D_LED_DISK_GPIO	3
++#define NAS100D_LED_PWR_GPIO	15
+diff --git a/include/asm-arm/arch-ixp4xx/npe.h b/include/asm-arm/arch-ixp4xx/npe.h
+new file mode 100644
+index 0000000..37d0511
+--- /dev/null
++++ b/include/asm-arm/arch-ixp4xx/npe.h
+@@ -0,0 +1,39 @@
++#ifndef __IXP4XX_NPE_H
++#define __IXP4XX_NPE_H
++
++#include <linux/kernel.h>
++
++extern const char *npe_names[];
++
++struct npe_regs {
++	u32 exec_addr, exec_data, exec_status_cmd, exec_count;
++	u32 action_points[4];
++	u32 watchpoint_fifo, watch_count;
++	u32 profile_count;
++	u32 messaging_status, messaging_control;
++	u32 mailbox_status, /*messaging_*/ in_out_fifo;
++};
++
++struct npe {
++	struct resource *mem_res;
++	struct npe_regs __iomem *regs;
++	u32 regs_phys;
++	int id;
++	int valid;
++};
++
++
++static inline const char *npe_name(struct npe *npe)
++{
++	return npe_names[npe->id];
++}
++
++int npe_running(struct npe *npe);
++int npe_send_message(struct npe *npe, const void *msg, const char *what);
++int npe_recv_message(struct npe *npe, void *msg, const char *what);
++int npe_send_recv_message(struct npe *npe, void *msg, const char *what);
++int npe_load_firmware(struct npe *npe, const char *name, struct device *dev);
++struct npe *npe_request(int id);
++void npe_release(struct npe *npe);
++
++#endif /* __IXP4XX_NPE_H */
+diff --git a/include/asm-arm/arch-ixp4xx/nslu2.h b/include/asm-arm/arch-ixp4xx/nslu2.h
+index 850fdc5..714bbc6 100644
+--- a/include/asm-arm/arch-ixp4xx/nslu2.h
++++ b/include/asm-arm/arch-ixp4xx/nslu2.h
+@@ -39,34 +39,17 @@
+ 
+ /* Buttons */
+ 
+-#define NSLU2_PB_GPIO		5
++#define NSLU2_PB_GPIO		5	/* power button */
+ #define NSLU2_PO_GPIO		8	/* power off */
+-#define NSLU2_RB_GPIO		12
+-
+-#define NSLU2_PB_IRQ		IRQ_IXP4XX_GPIO5
+-#define NSLU2_RB_IRQ		IRQ_IXP4XX_GPIO12
+-
+-#define NSLU2_PB_BM		(1L << NSLU2_PB_GPIO)
+-#define NSLU2_PO_BM		(1L << NSLU2_PO_GPIO)
+-#define NSLU2_RB_BM		(1L << NSLU2_RB_GPIO)
++#define NSLU2_RB_GPIO		12	/* reset button */
+ 
+ /* Buzzer */
+ 
+ #define NSLU2_GPIO_BUZZ		4
+-#define NSLU2_BZ_BM		(1L << NSLU2_GPIO_BUZZ)
+ 
+ /* LEDs */
+ 
+ #define NSLU2_LED_RED_GPIO	0
+ #define NSLU2_LED_GRN_GPIO	1
+-
+-#define NSLU2_LED_RED_BM	(1L << NSLU2_LED_RED_GPIO)
+-#define NSLU2_LED_GRN_BM	(1L << NSLU2_LED_GRN_GPIO)
+-
+ #define NSLU2_LED_DISK1_GPIO	3
+ #define NSLU2_LED_DISK2_GPIO	2
+-
+-#define NSLU2_LED_DISK1_BM	(1L << NSLU2_LED_DISK1_GPIO)
+-#define NSLU2_LED_DISK2_BM	(1L << NSLU2_LED_DISK2_GPIO)
+-
+-
 diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
-index 2a44d3d..2ce28e3 100644
+index 2a44d3d..a1f2b54 100644
 --- a/include/asm-arm/arch-ixp4xx/platform.h
 +++ b/include/asm-arm/arch-ixp4xx/platform.h
 @@ -76,17 +76,6 @@ extern unsigned long ixp4xx_exp_bus_size;
@@ -798585,6 +863699,179 @@
   * This structure provide a means for the board setup code
   * to give information to th pata_ixp4xx driver. It is
   * passed as platform_data.
+@@ -102,6 +91,27 @@ struct ixp4xx_pata_data {
+ 
+ struct sys_timer;
+ 
++#define IXP4XX_ETH_NPEA		0x00
++#define IXP4XX_ETH_NPEB		0x10
++#define IXP4XX_ETH_NPEC		0x20
++
++/* Information about built-in Ethernet MAC interfaces */
++struct eth_plat_info {
++	u8 phy;		/* MII PHY ID, 0 - 31 */
++	u8 rxq;		/* configurable, currently 0 - 31 only */
++	u8 txreadyq;
++	u8 hwaddr[6];
++};
++
++/* Information about built-in HSS (synchronous serial) interfaces */
++struct hss_plat_info {
++	int (*set_clock)(int port, unsigned int clock_type);
++	int (*open)(int port, void *pdev,
++		    void (*set_carrier_cb)(void *pdev, int carrier));
++	void (*close)(int port, void *pdev);
++	u8 txreadyq;
++};
++
+ /*
+  * Frequency of clock used for primary clocksource
+  */
+diff --git a/include/asm-arm/arch-ixp4xx/qmgr.h b/include/asm-arm/arch-ixp4xx/qmgr.h
+new file mode 100644
+index 0000000..1e52b95
+--- /dev/null
++++ b/include/asm-arm/arch-ixp4xx/qmgr.h
+@@ -0,0 +1,126 @@
++/*
++ * Copyright (C) 2007 Krzysztof Halasa <khc at pm.waw.pl>
++ *
++ * 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 published by the Free Software Foundation.
++ */
++
++#ifndef IXP4XX_QMGR_H
++#define IXP4XX_QMGR_H
++
++#include <linux/io.h>
++#include <linux/kernel.h>
++
++#define HALF_QUEUES	32
++#define QUEUES		64	/* only 32 lower queues currently supported */
++#define MAX_QUEUE_LENGTH 4	/* in dwords */
++
++#define QUEUE_STAT1_EMPTY		1 /* queue status bits */
++#define QUEUE_STAT1_NEARLY_EMPTY	2
++#define QUEUE_STAT1_NEARLY_FULL		4
++#define QUEUE_STAT1_FULL		8
++#define QUEUE_STAT2_UNDERFLOW		1
++#define QUEUE_STAT2_OVERFLOW		2
++
++#define QUEUE_WATERMARK_0_ENTRIES	0
++#define QUEUE_WATERMARK_1_ENTRY		1
++#define QUEUE_WATERMARK_2_ENTRIES	2
++#define QUEUE_WATERMARK_4_ENTRIES	3
++#define QUEUE_WATERMARK_8_ENTRIES	4
++#define QUEUE_WATERMARK_16_ENTRIES	5
++#define QUEUE_WATERMARK_32_ENTRIES	6
++#define QUEUE_WATERMARK_64_ENTRIES	7
++
++/* queue interrupt request conditions */
++#define QUEUE_IRQ_SRC_EMPTY		0
++#define QUEUE_IRQ_SRC_NEARLY_EMPTY	1
++#define QUEUE_IRQ_SRC_NEARLY_FULL	2
++#define QUEUE_IRQ_SRC_FULL		3
++#define QUEUE_IRQ_SRC_NOT_EMPTY		4
++#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY	5
++#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL	6
++#define QUEUE_IRQ_SRC_NOT_FULL		7
++
++struct qmgr_regs {
++	u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */
++	u32 stat1[4];		/* 0x400 - 0x40F */
++	u32 stat2[2];		/* 0x410 - 0x417 */
++	u32 statne_h;		/* 0x418 - queue nearly empty */
++	u32 statf_h;		/* 0x41C - queue full */
++	u32 irqsrc[4];		/* 0x420 - 0x42F IRC source */
++	u32 irqen[2];		/* 0x430 - 0x437 IRQ enabled */
++	u32 irqstat[2];		/* 0x438 - 0x43F - IRQ access only */
++	u32 reserved[1776];
++	u32 sram[2048];		/* 0x2000 - 0x3FFF - config and buffer */
++};
++
++void qmgr_set_irq(unsigned int queue, int src,
++		  void (*handler)(void *pdev), void *pdev);
++void qmgr_enable_irq(unsigned int queue);
++void qmgr_disable_irq(unsigned int queue);
++
++/* request_ and release_queue() must be called from non-IRQ context */
++int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
++		       unsigned int nearly_empty_watermark,
++		       unsigned int nearly_full_watermark);
++void qmgr_release_queue(unsigned int queue);
++
++
++static inline void qmgr_put_entry(unsigned int queue, u32 val)
++{
++	extern struct qmgr_regs __iomem *qmgr_regs;
++	__raw_writel(val, &qmgr_regs->acc[queue][0]);
++}
++
++static inline u32 qmgr_get_entry(unsigned int queue)
++{
++	extern struct qmgr_regs __iomem *qmgr_regs;
++	return __raw_readl(&qmgr_regs->acc[queue][0]);
++}
++
++static inline int qmgr_get_stat1(unsigned int queue)
++{
++	extern struct qmgr_regs __iomem *qmgr_regs;
++	return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
++		>> ((queue & 7) << 2)) & 0xF;
++}
++
++static inline int qmgr_get_stat2(unsigned int queue)
++{
++	extern struct qmgr_regs __iomem *qmgr_regs;
++	return (__raw_readl(&qmgr_regs->stat2[queue >> 4])
++		>> ((queue & 0xF) << 1)) & 0x3;
++}
++
++static inline int qmgr_stat_empty(unsigned int queue)
++{
++	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY);
++}
++
++static inline int qmgr_stat_nearly_empty(unsigned int queue)
++{
++	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY);
++}
++
++static inline int qmgr_stat_nearly_full(unsigned int queue)
++{
++	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL);
++}
++
++static inline int qmgr_stat_full(unsigned int queue)
++{
++	return !!(qmgr_get_stat1(queue) & QUEUE_STAT1_FULL);
++}
++
++static inline int qmgr_stat_underflow(unsigned int queue)
++{
++	return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW);
++}
++
++static inline int qmgr_stat_overflow(unsigned int queue)
++{
++	return !!(qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW);
++}
++
++#endif
+diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h
+index f7a35b7..34ef48f 100644
+--- a/include/asm-arm/arch-ixp4xx/uncompress.h
++++ b/include/asm-arm/arch-ixp4xx/uncompress.h
+@@ -13,7 +13,7 @@
+ #ifndef _ARCH_UNCOMPRESS_H_
+ #define _ARCH_UNCOMPRESS_H_
+ 
+-#include <asm/hardware.h>
++#include "ixp4xx-regs.h"
+ #include <asm/mach-types.h>
+ #include <linux/serial_reg.h>
+ 
 diff --git a/include/asm-arm/arch-ks8695/regs-gpio.h b/include/asm-arm/arch-ks8695/regs-gpio.h
 index 57fcf9f..6b95d77 100644
 --- a/include/asm-arm/arch-ks8695/regs-gpio.h
@@ -800096,6 +865383,74 @@
  
  #endif /* __ASM_ARCH_CORGI_H  */
  
+diff --git a/include/asm-arm/arch-pxa/gpio.h b/include/asm-arm/arch-pxa/gpio.h
+index 9dbc2dc..bdbf5f9 100644
+--- a/include/asm-arm/arch-pxa/gpio.h
++++ b/include/asm-arm/arch-pxa/gpio.h
+@@ -28,43 +28,35 @@
+ #include <asm/irq.h>
+ #include <asm/hardware.h>
+ 
+-static inline int gpio_request(unsigned gpio, const char *label)
+-{
+-	return 0;
+-}
++#include <asm-generic/gpio.h>
+ 
+-static inline void gpio_free(unsigned gpio)
+-{
+-	return;
+-}
+ 
+-extern int gpio_direction_input(unsigned gpio);
+-extern int gpio_direction_output(unsigned gpio, int value);
++/* NOTE: some PXAs have fewer on-chip GPIOs (like PXA255, with 85).
++ * Those cases currently cause holes in the GPIO number space.
++ */
++#define NR_BUILTIN_GPIO 128
+ 
+-static inline int __gpio_get_value(unsigned gpio)
++static inline int gpio_get_value(unsigned gpio)
+ {
+-	return GPLR(gpio) & GPIO_bit(gpio);
++	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO))
++		return GPLR(gpio) & GPIO_bit(gpio);
++	else
++		return __gpio_get_value(gpio);
+ }
+ 
+-#define gpio_get_value(gpio)			\
+-	(__builtin_constant_p(gpio) ?		\
+-	 __gpio_get_value(gpio) :		\
+-	 pxa_gpio_get_value(gpio))
+-
+-static inline void __gpio_set_value(unsigned gpio, int value)
++static inline void gpio_set_value(unsigned gpio, int value)
+ {
+-	if (value)
+-		GPSR(gpio) = GPIO_bit(gpio);
+-	else
+-		GPCR(gpio) = GPIO_bit(gpio);
++	if (__builtin_constant_p(gpio) && (gpio < NR_BUILTIN_GPIO)) {
++		if (value)
++			GPSR(gpio) = GPIO_bit(gpio);
++		else
++			GPCR(gpio) = GPIO_bit(gpio);
++	} else {
++		__gpio_set_value(gpio, value);
++	}
+ }
+ 
+-#define gpio_set_value(gpio,value)		\
+-	(__builtin_constant_p(gpio) ?		\
+-	 __gpio_set_value(gpio, value) :	\
+-	 pxa_gpio_set_value(gpio, value))
+-
+-#include <asm-generic/gpio.h>			/* cansleep wrappers */
++#define gpio_cansleep __gpio_cansleep
+ 
+ #define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
+ #define irq_to_gpio(irq)	IRQ_TO_GPIO(irq)
 diff --git a/include/asm-arm/arch-pxa/i2c.h b/include/asm-arm/arch-pxa/i2c.h
 index e404b23..80596b0 100644
 --- a/include/asm-arm/arch-pxa/i2c.h
@@ -801377,10 +866732,81 @@
 +#define PCM990_USB_OVERCURRENT (88 | GPIO_ALT_FN_1_IN)
 +#define PCM990_USB_PWR_EN (89 | GPIO_ALT_FN_2_OUT)
 diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
-index 1bd398d..442494d 100644
+index 1bd398d..ac175b4 100644
 --- a/include/asm-arm/arch-pxa/pxa-regs.h
 +++ b/include/asm-arm/arch-pxa/pxa-regs.h
-@@ -1597,176 +1597,10 @@
+@@ -737,25 +737,25 @@
+ 
+ #define USIR0		__REG(0x40600058)  /* UDC Status Interrupt Register 0 */
+ 
+-#define USIR0_IR0	(1 << 0)	/* Interrup request ep 0 */
+-#define USIR0_IR1	(1 << 1)	/* Interrup request ep 1 */
+-#define USIR0_IR2	(1 << 2)	/* Interrup request ep 2 */
+-#define USIR0_IR3	(1 << 3)	/* Interrup request ep 3 */
+-#define USIR0_IR4	(1 << 4)	/* Interrup request ep 4 */
+-#define USIR0_IR5	(1 << 5)	/* Interrup request ep 5 */
+-#define USIR0_IR6	(1 << 6)	/* Interrup request ep 6 */
+-#define USIR0_IR7	(1 << 7)	/* Interrup request ep 7 */
++#define USIR0_IR0	(1 << 0)	/* Interrupt request ep 0 */
++#define USIR0_IR1	(1 << 1)	/* Interrupt request ep 1 */
++#define USIR0_IR2	(1 << 2)	/* Interrupt request ep 2 */
++#define USIR0_IR3	(1 << 3)	/* Interrupt request ep 3 */
++#define USIR0_IR4	(1 << 4)	/* Interrupt request ep 4 */
++#define USIR0_IR5	(1 << 5)	/* Interrupt request ep 5 */
++#define USIR0_IR6	(1 << 6)	/* Interrupt request ep 6 */
++#define USIR0_IR7	(1 << 7)	/* Interrupt request ep 7 */
+ 
+ #define USIR1		__REG(0x4060005C)  /* UDC Status Interrupt Register 1 */
+ 
+-#define USIR1_IR8	(1 << 0)	/* Interrup request ep 8 */
+-#define USIR1_IR9	(1 << 1)	/* Interrup request ep 9 */
+-#define USIR1_IR10	(1 << 2)	/* Interrup request ep 10 */
+-#define USIR1_IR11	(1 << 3)	/* Interrup request ep 11 */
+-#define USIR1_IR12	(1 << 4)	/* Interrup request ep 12 */
+-#define USIR1_IR13	(1 << 5)	/* Interrup request ep 13 */
+-#define USIR1_IR14	(1 << 6)	/* Interrup request ep 14 */
+-#define USIR1_IR15	(1 << 7)	/* Interrup request ep 15 */
++#define USIR1_IR8	(1 << 0)	/* Interrupt request ep 8 */
++#define USIR1_IR9	(1 << 1)	/* Interrupt request ep 9 */
++#define USIR1_IR10	(1 << 2)	/* Interrupt request ep 10 */
++#define USIR1_IR11	(1 << 3)	/* Interrupt request ep 11 */
++#define USIR1_IR12	(1 << 4)	/* Interrupt request ep 12 */
++#define USIR1_IR13	(1 << 5)	/* Interrupt request ep 13 */
++#define USIR1_IR14	(1 << 6)	/* Interrupt request ep 14 */
++#define USIR1_IR15	(1 << 7)	/* Interrupt request ep 15 */
+ 
+ #elif defined(CONFIG_PXA27x)
+ 
+@@ -1020,7 +1020,7 @@
+ #define ICSR0		__REG(0x40800014)  /* ICP Status Register 0 */
+ #define ICSR1		__REG(0x40800018)  /* ICP Status Register 1 */
+ 
+-#define ICCR0_AME	(1 << 7)	/* Adress match enable */
++#define ICCR0_AME	(1 << 7)	/* Address match enable */
+ #define ICCR0_TIE	(1 << 6)	/* Transmit FIFO interrupt enable */
+ #define ICCR0_RIE	(1 << 5)	/* Recieve FIFO interrupt enable */
+ #define ICCR0_RXE	(1 << 4)	/* Receive enable */
+@@ -1131,6 +1131,19 @@
+  * General Purpose I/O
+  */
+ 
++#define GPIO0_BASE	((void __iomem *)io_p2v(0x40E00000))
++#define GPIO1_BASE	((void __iomem *)io_p2v(0x40E00004))
++#define GPIO2_BASE	((void __iomem *)io_p2v(0x40E00008))
++#define GPIO3_BASE	((void __iomem *)io_p2v(0x40E00100))
++
++#define GPLR_OFFSET	0x00
++#define GPDR_OFFSET	0x0C
++#define GPSR_OFFSET	0x18
++#define GPCR_OFFSET	0x24
++#define GRER_OFFSET	0x30
++#define GFER_OFFSET	0x3C
++#define GEDR_OFFSET	0x48
++
+ #define GPLR0		__REG(0x40E00000)  /* GPIO Pin-Level Register GPIO<31:0> */
+ #define GPLR1		__REG(0x40E00004)  /* GPIO Pin-Level Register GPIO<63:32> */
+ #define GPLR2		__REG(0x40E00008)  /* GPIO Pin-Level Register GPIO<80:64> */
+@@ -1597,176 +1610,10 @@
  #define PWER_GPIO15	PWER_GPIO (15)	/* GPIO [15] wake-up enable        */
  #define PWER_RTC	0x80000000	/* RTC alarm wake-up enable        */
  
@@ -801558,7 +866984,7 @@
  /*
   * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h
   */
-@@ -2014,71 +1848,8 @@
+@@ -2014,71 +1861,8 @@
  
  #define LDCMD_PAL	(1 << 26)	/* instructs DMA to load palette buffer */
  
@@ -801630,7 +867056,7 @@
  /*
   * Keypad
   */
-@@ -2135,74 +1906,6 @@
+@@ -2135,74 +1919,6 @@
  #define KPAS_SO         (0x1 << 31)
  #define KPASMKPx_SO     (0x1 << 31)
  
@@ -801705,7 +867131,7 @@
  /* Camera Interface */
  #define CICR0		__REG(0x50000000)
  #define CICR1		__REG(0x50000004)
-@@ -2350,6 +2053,77 @@
+@@ -2350,6 +2066,77 @@
  
  #endif
  
@@ -801911,13 +867337,28 @@
  	u16 num_chipselect;
  	u8 enable_dma;
 diff --git a/include/asm-arm/arch-pxa/pxa3xx-regs.h b/include/asm-arm/arch-pxa/pxa3xx-regs.h
-index 3900a0c..66d5411 100644
+index 3900a0c..8e1b3ea 100644
 --- a/include/asm-arm/arch-pxa/pxa3xx-regs.h
 +++ b/include/asm-arm/arch-pxa/pxa3xx-regs.h
-@@ -14,6 +14,92 @@
- #define __ASM_ARCH_PXA3XX_REGS_H
+@@ -12,6 +12,105 @@
  
- /*
+ #ifndef __ASM_ARCH_PXA3XX_REGS_H
+ #define __ASM_ARCH_PXA3XX_REGS_H
++/*
++ * Service Power Management Unit (MPMU)
++ */
++#define PMCR		__REG(0x40F50000)	/* Power Manager Control Register */
++#define PSR		__REG(0x40F50004)	/* Power Manager S2 Status Register */
++#define PSPR		__REG(0x40F50008)	/* Power Manager Scratch Pad Register */
++#define PCFR		__REG(0x40F5000C)	/* Power Manager General Configuration Register */
++#define PWER		__REG(0x40F50010)	/* Power Manager Wake-up Enable Register */
++#define PWSR		__REG(0x40F50014)	/* Power Manager Wake-up Status Register */
++#define PECR		__REG(0x40F50018)	/* Power Manager EXT_WAKEUP[1:0] Control Register */
++#define DCDCSR		__REG(0x40F50080)	/* DC-DC Controller Status Register */
++#define PVCR		__REG(0x40F50100)	/* Power Manager Voltage Change Control Register */
++#define PCMD(x)		__REG(0x40F50110 + ((x) << 2))
++
++/*
 + * Slave Power Managment Unit
 + */
 +#define ASCR		__REG(0x40f40000)	/* Application Subsystem Power Status/Configuration */
@@ -802002,11 +867443,9 @@
 +#define PXA3xx_PM_S0D2C2	0x03	/* aka standby */
 +#define PXA3xx_PM_S0D1C2	0x02	/* aka LCD refresh */
 +#define PXA3xx_PM_S0D0C1	0x01
-+
-+/*
+ 
+ /*
   * Application Subsystem Clock
-  */
- #define ACCR		__REG(0x41340000)	/* Application Subsystem Clock Configuration Register */
 diff --git a/include/asm-arm/arch-pxa/regs-ssp.h b/include/asm-arm/arch-pxa/regs-ssp.h
 new file mode 100644
 index 0000000..991cb68
@@ -802263,6 +867702,570 @@
  extern int gpio_backlight;
  extern int gpio_eth_irq;
  
+diff --git a/include/asm-arm/arch-realview/board-eb.h b/include/asm-arm/arch-realview/board-eb.h
+new file mode 100644
+index 0000000..3e437b7
+--- /dev/null
++++ b/include/asm-arm/arch-realview/board-eb.h
+@@ -0,0 +1,171 @@
++/*
++ * include/asm-arm/arch-realview/board-eb.h
++ *
++ * Copyright (C) 2007 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
++ * MA 02110-1301, USA.
++ */
++
++#ifndef __ASM_ARCH_BOARD_EB_H
++#define __ASM_ARCH_BOARD_EB_H
++
++#include <asm/arch/platform.h>
++
++/*
++ * RealView EB + ARM11MPCore peripheral addresses
++ */
++#ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB
++#define REALVIEW_EB11MP_SCU_BASE	0x10100000	/* SCU registers */
++#define REALVIEW_EB11MP_GIC_CPU_BASE	0x10100100	/* Generic interrupt controller CPU interface */
++#define REALVIEW_EB11MP_TWD_BASE	0x10100700
++#define REALVIEW_EB11MP_TWD_SIZE	0x00000100
++#define REALVIEW_EB11MP_GIC_DIST_BASE	0x10101000	/* Generic interrupt controller distributor */
++#define REALVIEW_EB11MP_L220_BASE	0x10102000	/* L220 registers */
++#define REALVIEW_EB11MP_SYS_PLD_CTRL1	0xD8		/* Register offset for MPCore sysctl */
++#else
++#define REALVIEW_EB11MP_SCU_BASE	0x1F000000	/* SCU registers */
++#define REALVIEW_EB11MP_GIC_CPU_BASE	0x1F000100	/* Generic interrupt controller CPU interface */
++#define REALVIEW_EB11MP_TWD_BASE	0x1F000700
++#define REALVIEW_EB11MP_TWD_SIZE	0x00000100
++#define REALVIEW_EB11MP_GIC_DIST_BASE	0x1F001000	/* Generic interrupt controller distributor */
++#define REALVIEW_EB11MP_L220_BASE	0x1F002000	/* L220 registers */
++#define REALVIEW_EB11MP_SYS_PLD_CTRL1	0x74		/* Register offset for MPCore sysctl */
++#endif
++
++#define IRQ_EB_GIC_START	32
++
++/*
++ * RealView EB interrupt sources
++ */
++#define IRQ_EB_WDOG		(IRQ_EB_GIC_START + 0)		/* Watchdog timer */
++#define IRQ_EB_SOFT		(IRQ_EB_GIC_START + 1)		/* Software interrupt */
++#define IRQ_EB_COMMRx		(IRQ_EB_GIC_START + 2)		/* Debug Comm Rx interrupt */
++#define IRQ_EB_COMMTx		(IRQ_EB_GIC_START + 3)		/* Debug Comm Tx interrupt */
++#define IRQ_EB_TIMER0_1		(IRQ_EB_GIC_START + 4)		/* Timer 0 and 1 */
++#define IRQ_EB_TIMER2_3		(IRQ_EB_GIC_START + 5)		/* Timer 2 and 3 */
++#define IRQ_EB_GPIO0		(IRQ_EB_GIC_START + 6)		/* GPIO 0 */
++#define IRQ_EB_GPIO1		(IRQ_EB_GIC_START + 7)		/* GPIO 1 */
++#define IRQ_EB_GPIO2		(IRQ_EB_GIC_START + 8)		/* GPIO 2 */
++								/* 9 reserved */
++#define IRQ_EB_RTC		(IRQ_EB_GIC_START + 10)		/* Real Time Clock */
++#define IRQ_EB_SSP		(IRQ_EB_GIC_START + 11)		/* Synchronous Serial Port */
++#define IRQ_EB_UART0		(IRQ_EB_GIC_START + 12)		/* UART 0 on development chip */
++#define IRQ_EB_UART1		(IRQ_EB_GIC_START + 13)		/* UART 1 on development chip */
++#define IRQ_EB_UART2		(IRQ_EB_GIC_START + 14)		/* UART 2 on development chip */
++#define IRQ_EB_UART3		(IRQ_EB_GIC_START + 15)		/* UART 3 on development chip */
++#define IRQ_EB_SCI		(IRQ_EB_GIC_START + 16)		/* Smart Card Interface */
++#define IRQ_EB_MMCI0A		(IRQ_EB_GIC_START + 17)		/* Multimedia Card 0A */
++#define IRQ_EB_MMCI0B		(IRQ_EB_GIC_START + 18)		/* Multimedia Card 0B */
++#define IRQ_EB_AACI		(IRQ_EB_GIC_START + 19)		/* Audio Codec */
++#define IRQ_EB_KMI0		(IRQ_EB_GIC_START + 20)		/* Keyboard/Mouse port 0 */
++#define IRQ_EB_KMI1		(IRQ_EB_GIC_START + 21)		/* Keyboard/Mouse port 1 */
++#define IRQ_EB_CHARLCD		(IRQ_EB_GIC_START + 22)		/* Character LCD */
++#define IRQ_EB_CLCD		(IRQ_EB_GIC_START + 23)		/* CLCD controller */
++#define IRQ_EB_DMA		(IRQ_EB_GIC_START + 24)		/* DMA controller */
++#define IRQ_EB_PWRFAIL		(IRQ_EB_GIC_START + 25)		/* Power failure */
++#define IRQ_EB_PISMO		(IRQ_EB_GIC_START + 26)		/* PISMO interface */
++#define IRQ_EB_DoC		(IRQ_EB_GIC_START + 27)		/* Disk on Chip memory controller */
++#define IRQ_EB_ETH		(IRQ_EB_GIC_START + 28)		/* Ethernet controller */
++#define IRQ_EB_USB		(IRQ_EB_GIC_START + 29)		/* USB controller */
++#define IRQ_EB_TSPEN		(IRQ_EB_GIC_START + 30)		/* Touchscreen pen */
++#define IRQ_EB_TSKPAD		(IRQ_EB_GIC_START + 31)		/* Touchscreen keypad */
++
++/*
++ * RealView EB + ARM11MPCore interrupt sources (primary GIC on the core tile)
++ */
++#define IRQ_EB11MP_AACI		(IRQ_EB_GIC_START + 0)
++#define IRQ_EB11MP_TIMER0_1	(IRQ_EB_GIC_START + 1)
++#define IRQ_EB11MP_TIMER2_3	(IRQ_EB_GIC_START + 2)
++#define IRQ_EB11MP_USB		(IRQ_EB_GIC_START + 3)
++#define IRQ_EB11MP_UART0	(IRQ_EB_GIC_START + 4)
++#define IRQ_EB11MP_UART1	(IRQ_EB_GIC_START + 5)
++#define IRQ_EB11MP_RTC		(IRQ_EB_GIC_START + 6)
++#define IRQ_EB11MP_KMI0		(IRQ_EB_GIC_START + 7)
++#define IRQ_EB11MP_KMI1		(IRQ_EB_GIC_START + 8)
++#define IRQ_EB11MP_ETH		(IRQ_EB_GIC_START + 9)
++#define IRQ_EB11MP_EB_IRQ1	(IRQ_EB_GIC_START + 10)		/* main GIC */
++#define IRQ_EB11MP_EB_IRQ2	(IRQ_EB_GIC_START + 11)		/* tile GIC */
++#define IRQ_EB11MP_EB_FIQ1	(IRQ_EB_GIC_START + 12)		/* main GIC */
++#define IRQ_EB11MP_EB_FIQ2	(IRQ_EB_GIC_START + 13)		/* tile GIC */
++#define IRQ_EB11MP_MMCI0A	(IRQ_EB_GIC_START + 14)
++#define IRQ_EB11MP_MMCI0B	(IRQ_EB_GIC_START + 15)
++
++#define IRQ_EB11MP_PMU_CPU0	(IRQ_EB_GIC_START + 17)
++#define IRQ_EB11MP_PMU_CPU1	(IRQ_EB_GIC_START + 18)
++#define IRQ_EB11MP_PMU_CPU2	(IRQ_EB_GIC_START + 19)
++#define IRQ_EB11MP_PMU_CPU3	(IRQ_EB_GIC_START + 20)
++#define IRQ_EB11MP_PMU_SCU0	(IRQ_EB_GIC_START + 21)
++#define IRQ_EB11MP_PMU_SCU1	(IRQ_EB_GIC_START + 22)
++#define IRQ_EB11MP_PMU_SCU2	(IRQ_EB_GIC_START + 23)
++#define IRQ_EB11MP_PMU_SCU3	(IRQ_EB_GIC_START + 24)
++#define IRQ_EB11MP_PMU_SCU4	(IRQ_EB_GIC_START + 25)
++#define IRQ_EB11MP_PMU_SCU5	(IRQ_EB_GIC_START + 26)
++#define IRQ_EB11MP_PMU_SCU6	(IRQ_EB_GIC_START + 27)
++#define IRQ_EB11MP_PMU_SCU7	(IRQ_EB_GIC_START + 28)
++
++#define IRQ_EB11MP_L220_EVENT	(IRQ_EB_GIC_START + 29)
++#define IRQ_EB11MP_L220_SLAVE	(IRQ_EB_GIC_START + 30)
++#define IRQ_EB11MP_L220_DECODE	(IRQ_EB_GIC_START + 31)
++
++#define IRQ_EB11MP_UART2	-1
++#define IRQ_EB11MP_UART3	-1
++#define IRQ_EB11MP_CLCD		-1
++#define IRQ_EB11MP_DMA		-1
++#define IRQ_EB11MP_WDOG		-1
++#define IRQ_EB11MP_GPIO0	-1
++#define IRQ_EB11MP_GPIO1	-1
++#define IRQ_EB11MP_GPIO2	-1
++#define IRQ_EB11MP_SCI		-1
++#define IRQ_EB11MP_SSP		-1
++
++#define NR_GIC_EB11MP		2
++
++/*
++ * Only define NR_IRQS if less than NR_IRQS_EB
++ */
++#define NR_IRQS_EB		(IRQ_EB_GIC_START + 96)
++
++#if defined(CONFIG_MACH_REALVIEW_EB) \
++	&& (!defined(NR_IRQS) || (NR_IRQS < NR_IRQS_EB))
++#undef NR_IRQS
++#define NR_IRQS			NR_IRQS_EB
++#endif
++
++#if defined(CONFIG_REALVIEW_EB_ARM11MP) \
++	&& (!defined(MAX_GIC_NR) || (MAX_GIC_NR < NR_GIC_EB11MP))
++#undef MAX_GIC_NR
++#define MAX_GIC_NR		NR_GIC_EB11MP
++#endif
++
++/*
++ * Core tile identification (REALVIEW_SYS_PROCID)
++ */
++#define REALVIEW_EB_PROC_MASK		0xFF000000
++#define REALVIEW_EB_PROC_ARM7TDMI	0x00000000
++#define REALVIEW_EB_PROC_ARM9		0x02000000
++#define REALVIEW_EB_PROC_ARM11		0x04000000
++#define REALVIEW_EB_PROC_ARM11MP	0x06000000
++
++#define check_eb_proc(proc_type)						\
++	((readl(__io_address(REALVIEW_SYS_PROCID)) & REALVIEW_EB_PROC_MASK)	\
++	 == proc_type)
++
++#ifdef CONFIG_REALVIEW_EB_ARM11MP
++#define core_tile_eb11mp()	check_eb_proc(REALVIEW_EB_PROC_ARM11MP)
++#else
++#define core_tile_eb11mp()	0
++#endif
++
++#endif	/* __ASM_ARCH_BOARD_EB_H */
+diff --git a/include/asm-arm/arch-realview/entry-macro.S b/include/asm-arm/arch-realview/entry-macro.S
+index 3b4e207..cd26306 100644
+--- a/include/asm-arm/arch-realview/entry-macro.S
++++ b/include/asm-arm/arch-realview/entry-macro.S
+@@ -14,7 +14,8 @@
+ 		.endm
+ 
+ 		.macro  get_irqnr_preamble, base, tmp
+-		ldr     \base, =IO_ADDRESS(REALVIEW_GIC_CPU_BASE)
++		ldr	\base, =gic_cpu_base_addr
++		ldr	\base, [\base]
+ 		.endm
+ 
+ 		.macro  arch_ret_to_user, tmp1, tmp2
+diff --git a/include/asm-arm/arch-realview/hardware.h b/include/asm-arm/arch-realview/hardware.h
+index aa78fe0..bad8d7c 100644
+--- a/include/asm-arm/arch-realview/hardware.h
++++ b/include/asm-arm/arch-realview/hardware.h
+@@ -23,7 +23,6 @@
+ #define __ASM_ARCH_HARDWARE_H
+ 
+ #include <asm/sizes.h>
+-#include <asm/arch/platform.h>
+ 
+ /* macro to get at IO space when running virtually */
+ #define IO_ADDRESS(x)		((((x) & 0x0effffff) | (((x) >> 4) & 0x0f000000)) + 0xf0000000)
+diff --git a/include/asm-arm/arch-realview/irqs.h b/include/asm-arm/arch-realview/irqs.h
+index 5a5db56..ad0c911 100644
+--- a/include/asm-arm/arch-realview/irqs.h
++++ b/include/asm-arm/arch-realview/irqs.h
+@@ -19,103 +19,18 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ 
+-#include <asm/arch/platform.h>
++#ifndef __ASM_ARCH_IRQS_H
++#define __ASM_ARCH_IRQS_H
+ 
+-#define IRQ_LOCALTIMER			29
+-#define IRQ_LOCALWDOG			30
++#include <asm/arch/board-eb.h>
+ 
+-/* 
+- *  IRQ interrupts definitions are the same the INT definitions
+- *  held within platform.h
+- */
+-#define IRQ_GIC_START		32
+-#define IRQ_WDOGINT		(IRQ_GIC_START + INT_WDOGINT)
+-#define IRQ_SOFTINT		(IRQ_GIC_START + INT_SOFTINT)
+-#define IRQ_COMMRx		(IRQ_GIC_START + INT_COMMRx)
+-#define IRQ_COMMTx		(IRQ_GIC_START + INT_COMMTx)
+-#define IRQ_TIMERINT0_1		(IRQ_GIC_START + INT_TIMERINT0_1)
+-#define IRQ_TIMERINT2_3		(IRQ_GIC_START + INT_TIMERINT2_3)
+-#define IRQ_GPIOINT0		(IRQ_GIC_START + INT_GPIOINT0)
+-#define IRQ_GPIOINT1		(IRQ_GIC_START + INT_GPIOINT1)
+-#define IRQ_GPIOINT2		(IRQ_GIC_START + INT_GPIOINT2)
+-#define IRQ_GPIOINT3		(IRQ_GIC_START + INT_GPIOINT3)
+-#define IRQ_RTCINT		(IRQ_GIC_START + INT_RTCINT)
+-#define IRQ_SSPINT		(IRQ_GIC_START + INT_SSPINT)
+-#define IRQ_UARTINT0		(IRQ_GIC_START + INT_UARTINT0)
+-#define IRQ_UARTINT1		(IRQ_GIC_START + INT_UARTINT1)
+-#define IRQ_UARTINT2		(IRQ_GIC_START + INT_UARTINT2)
+-#define IRQ_UART3		(IRQ_GIC_START + INT_UARTINT3)
+-#define IRQ_SCIINT		(IRQ_GIC_START + INT_SCIINT)
+-#define IRQ_CLCDINT		(IRQ_GIC_START + INT_CLCDINT)
+-#define IRQ_DMAINT		(IRQ_GIC_START + INT_DMAINT)
+-#define IRQ_PWRFAILINT 		(IRQ_GIC_START + INT_PWRFAILINT)
+-#define IRQ_MBXINT		(IRQ_GIC_START + INT_MBXINT)
+-#define IRQ_GNDINT		(IRQ_GIC_START + INT_GNDINT)
+-#define IRQ_MMCI0B 		(IRQ_GIC_START + INT_MMCI0B)
+-#define IRQ_MMCI1B 		(IRQ_GIC_START + INT_MMCI1B)
+-#define IRQ_KMI0		(IRQ_GIC_START + INT_KMI0)
+-#define IRQ_KMI1		(IRQ_GIC_START + INT_KMI1)
+-#define IRQ_SCI3		(IRQ_GIC_START + INT_SCI3)
+-#define IRQ_CLCD		(IRQ_GIC_START + INT_CLCD)
+-#define IRQ_TOUCH		(IRQ_GIC_START + INT_TOUCH)
+-#define IRQ_KEYPAD 		(IRQ_GIC_START + INT_KEYPAD)
+-#define IRQ_DoC			(IRQ_GIC_START + INT_DoC)
+-#define IRQ_MMCI0A 		(IRQ_GIC_START + INT_MMCI0A)
+-#define IRQ_MMCI1A 		(IRQ_GIC_START + INT_MMCI1A)
+-#define IRQ_AACI		(IRQ_GIC_START + INT_AACI)
+-#define IRQ_ETH			(IRQ_GIC_START + INT_ETH)
+-#define IRQ_USB			(IRQ_GIC_START + INT_USB)
+-#define IRQ_PMU_CPU0		(IRQ_GIC_START + INT_PMU_CPU0)
+-#define IRQ_PMU_CPU1		(IRQ_GIC_START + INT_PMU_CPU1)
+-#define IRQ_PMU_CPU2		(IRQ_GIC_START + INT_PMU_CPU2)
+-#define IRQ_PMU_CPU3		(IRQ_GIC_START + INT_PMU_CPU3)
+-#define IRQ_PMU_SCU0		(IRQ_GIC_START + INT_PMU_SCU0)
+-#define IRQ_PMU_SCU1		(IRQ_GIC_START + INT_PMU_SCU1)
+-#define IRQ_PMU_SCU2		(IRQ_GIC_START + INT_PMU_SCU2)
+-#define IRQ_PMU_SCU3		(IRQ_GIC_START + INT_PMU_SCU3)
+-#define IRQ_PMU_SCU4		(IRQ_GIC_START + INT_PMU_SCU4)
+-#define IRQ_PMU_SCU5		(IRQ_GIC_START + INT_PMU_SCU5)
+-#define IRQ_PMU_SCU6		(IRQ_GIC_START + INT_PMU_SCU6)
+-#define IRQ_PMU_SCU7		(IRQ_GIC_START + INT_PMU_SCU7)
++#define IRQ_LOCALTIMER		29
++#define IRQ_LOCALWDOG		30
+ 
+-#define IRQ_EB_IRQ1		(IRQ_GIC_START + INT_EB_IRQ1)
+-#define IRQ_EB_IRQ2		(IRQ_GIC_START + INT_EB_IRQ2)
++#define IRQ_GIC_START		32
+ 
+-#define IRQMASK_WDOGINT		INTMASK_WDOGINT
+-#define IRQMASK_SOFTINT		INTMASK_SOFTINT
+-#define IRQMASK_COMMRx 		INTMASK_COMMRx
+-#define IRQMASK_COMMTx 		INTMASK_COMMTx
+-#define IRQMASK_TIMERINT0_1	INTMASK_TIMERINT0_1
+-#define IRQMASK_TIMERINT2_3	INTMASK_TIMERINT2_3
+-#define IRQMASK_GPIOINT0	INTMASK_GPIOINT0
+-#define IRQMASK_GPIOINT1	INTMASK_GPIOINT1
+-#define IRQMASK_GPIOINT2	INTMASK_GPIOINT2
+-#define IRQMASK_GPIOINT3	INTMASK_GPIOINT3
+-#define IRQMASK_RTCINT 		INTMASK_RTCINT
+-#define IRQMASK_SSPINT 		INTMASK_SSPINT
+-#define IRQMASK_UARTINT0	INTMASK_UARTINT0
+-#define IRQMASK_UARTINT1	INTMASK_UARTINT1
+-#define IRQMASK_UARTINT2	INTMASK_UARTINT2
+-#define IRQMASK_SCIINT 		INTMASK_SCIINT
+-#define IRQMASK_CLCDINT		INTMASK_CLCDINT
+-#define IRQMASK_DMAINT 		INTMASK_DMAINT
+-#define IRQMASK_PWRFAILINT	INTMASK_PWRFAILINT
+-#define IRQMASK_MBXINT 		INTMASK_MBXINT
+-#define IRQMASK_GNDINT 		INTMASK_GNDINT
+-#define IRQMASK_MMCI0B		INTMASK_MMCI0B
+-#define IRQMASK_MMCI1B		INTMASK_MMCI1B
+-#define IRQMASK_KMI0		INTMASK_KMI0
+-#define IRQMASK_KMI1		INTMASK_KMI1
+-#define IRQMASK_SCI3		INTMASK_SCI3
+-#define IRQMASK_UART3		INTMASK_UART3
+-#define IRQMASK_CLCD		INTMASK_CLCD
+-#define IRQMASK_TOUCH		INTMASK_TOUCH
+-#define IRQMASK_KEYPAD		INTMASK_KEYPAD
+-#define IRQMASK_DoC		INTMASK_DoC
+-#define IRQMASK_MMCI0A		INTMASK_MMCI0A
+-#define IRQMASK_MMCI1A		INTMASK_MMCI1A
+-#define IRQMASK_AACI		INTMASK_AACI
+-#define IRQMASK_ETH		INTMASK_ETH
+-#define IRQMASK_USB		INTMASK_USB
++#ifndef NR_IRQS
++#error "NR_IRQS not defined by the board-specific files"
++#endif
+ 
+-#define NR_IRQS			(IRQ_GIC_START + 96)
++#endif
+diff --git a/include/asm-arm/arch-realview/platform.h b/include/asm-arm/arch-realview/platform.h
+index 6e0eab9..4fd351b 100644
+--- a/include/asm-arm/arch-realview/platform.h
++++ b/include/asm-arm/arch-realview/platform.h
+@@ -18,8 +18,8 @@
+  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ 
+-#ifndef __address_h
+-#define __address_h                     1
++#ifndef __ASM_ARCH_PLATFORM_H
++#define __ASM_ARCH_PLATFORM_H
+ 
+ /*
+  * Memory definitions
+@@ -81,11 +81,12 @@
+ #define REALVIEW_SYS_24MHz_OFFSET            0x5C
+ #define REALVIEW_SYS_MISC_OFFSET             0x60
+ #define REALVIEW_SYS_IOSEL_OFFSET            0x70
+-#define REALVIEW_SYS_TEST_OSC0_OFFSET        0x80
+-#define REALVIEW_SYS_TEST_OSC1_OFFSET        0x84
+-#define REALVIEW_SYS_TEST_OSC2_OFFSET        0x88
+-#define REALVIEW_SYS_TEST_OSC3_OFFSET        0x8C
+-#define REALVIEW_SYS_TEST_OSC4_OFFSET        0x90
++#define REALVIEW_SYS_PROCID_OFFSET           0x84
++#define REALVIEW_SYS_TEST_OSC0_OFFSET        0xC0
++#define REALVIEW_SYS_TEST_OSC1_OFFSET        0xC4
++#define REALVIEW_SYS_TEST_OSC2_OFFSET        0xC8
++#define REALVIEW_SYS_TEST_OSC3_OFFSET        0xCC
++#define REALVIEW_SYS_TEST_OSC4_OFFSET        0xD0
+ 
+ #define REALVIEW_SYS_BASE                    0x10000000
+ #define REALVIEW_SYS_ID                      (REALVIEW_SYS_BASE + REALVIEW_SYS_ID_OFFSET)
+@@ -114,6 +115,7 @@
+ #define REALVIEW_SYS_24MHz                   (REALVIEW_SYS_BASE + REALVIEW_SYS_24MHz_OFFSET)
+ #define REALVIEW_SYS_MISC                    (REALVIEW_SYS_BASE + REALVIEW_SYS_MISC_OFFSET)
+ #define REALVIEW_SYS_IOSEL                   (REALVIEW_SYS_BASE + REALVIEW_SYS_IOSEL_OFFSET)
++#define REALVIEW_SYS_PROCID                  (REALVIEW_SYS_BASE + REALVIEW_SYS_PROCID_OFFSET)
+ #define REALVIEW_SYS_TEST_OSC0               (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC0_OFFSET)
+ #define REALVIEW_SYS_TEST_OSC1               (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC1_OFFSET)
+ #define REALVIEW_SYS_TEST_OSC2               (REALVIEW_SYS_BASE + REALVIEW_SYS_TEST_OSC2_OFFSET)
+@@ -203,30 +205,8 @@
+ 	/* Reserved 0x1001A000 - 0x1001FFFF */
+ #define REALVIEW_CLCD_BASE            0x10020000	/* CLCD */
+ #define REALVIEW_DMAC_BASE            0x10030000	/* DMA controller */
+-#ifndef CONFIG_REALVIEW_MPCORE
+ #define REALVIEW_GIC_CPU_BASE         0x10040000	/* Generic interrupt controller CPU interface */
+ #define REALVIEW_GIC_DIST_BASE        0x10041000	/* Generic interrupt controller distributor */
+-#else
+-#ifdef CONFIG_REALVIEW_MPCORE_REVB
+-#define REALVIEW_MPCORE_SCU_BASE	0x10100000	/*  SCU registers */
+-#define REALVIEW_GIC_CPU_BASE		0x10100100	/* Generic interrupt controller CPU interface */
+-#define REALVIEW_TWD_BASE		0x10100700
+-#define REALVIEW_TWD_SIZE		0x00000100
+-#define REALVIEW_GIC_DIST_BASE		0x10101000	/* Generic interrupt controller distributor */
+-#define REALVIEW_MPCORE_L220_BASE	0x10102000	/* L220 registers */
+-#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0xD8		/*  Register offset for MPCore sysctl */
+-#else
+-#define REALVIEW_MPCORE_SCU_BASE      0x1F000000	/*  SCU registers */
+-#define REALVIEW_GIC_CPU_BASE         0x1F000100	/* Generic interrupt controller CPU interface */
+-#define REALVIEW_TWD_BASE             0x1F000700
+-#define REALVIEW_TWD_SIZE             0x00000100
+-#define REALVIEW_GIC_DIST_BASE        0x1F001000	/* Generic interrupt controller distributor */
+-#define REALVIEW_MPCORE_L220_BASE     0x1F002000	/* L220 registers */
+-#define REALVIEW_MPCORE_SYS_PLD_CTRL1 0x74		/*  Register offset for MPCore sysctl */
+-#endif
+-#define REALVIEW_GIC1_CPU_BASE        0x10040000	/* Generic interrupt controller CPU interface */
+-#define REALVIEW_GIC1_DIST_BASE       0x10041000	/* Generic interrupt controller distributor */
+-#endif
+ #define REALVIEW_SMC_BASE             0x10080000	/* SMC */
+ 	/* Reserved 0x10090000 - 0x100EFFFF */
+ 
+@@ -283,134 +263,6 @@
+ #define REALVIEW_INTREG_OFFSET		0x8	/* Interrupt control */
+ #define REALVIEW_DECODE_OFFSET		0xC	/* Fitted logic modules */
+ 
+-/* ------------------------------------------------------------------------
+- *  Interrupts - bit assignment (primary)
+- * ------------------------------------------------------------------------
+- */
+-#ifndef CONFIG_REALVIEW_MPCORE
+-#define INT_WDOGINT			0	/* Watchdog timer */
+-#define INT_SOFTINT			1	/* Software interrupt */
+-#define INT_COMMRx			2	/* Debug Comm Rx interrupt */
+-#define INT_COMMTx			3	/* Debug Comm Tx interrupt */
+-#define INT_TIMERINT0_1			4	/* Timer 0 and 1 */
+-#define INT_TIMERINT2_3			5	/* Timer 2 and 3 */
+-#define INT_GPIOINT0			6	/* GPIO 0 */
+-#define INT_GPIOINT1			7	/* GPIO 1 */
+-#define INT_GPIOINT2			8	/* GPIO 2 */
+-/* 9 reserved */
+-#define INT_RTCINT			10	/* Real Time Clock */
+-#define INT_SSPINT			11	/* Synchronous Serial Port */
+-#define INT_UARTINT0			12	/* UART 0 on development chip */
+-#define INT_UARTINT1			13	/* UART 1 on development chip */
+-#define INT_UARTINT2			14	/* UART 2 on development chip */
+-#define INT_UARTINT3			15	/* UART 3 on development chip */
+-#define INT_SCIINT			16	/* Smart Card Interface */
+-#define INT_MMCI0A			17	/* Multimedia Card 0A */
+-#define INT_MMCI0B			18	/* Multimedia Card 0B */
+-#define INT_AACI			19	/* Audio Codec */
+-#define INT_KMI0			20	/* Keyboard/Mouse port 0 */
+-#define INT_KMI1			21	/* Keyboard/Mouse port 1 */
+-#define INT_CHARLCD			22	/* Character LCD */
+-#define INT_CLCDINT			23	/* CLCD controller */
+-#define INT_DMAINT			24	/* DMA controller */
+-#define INT_PWRFAILINT			25	/* Power failure */
+-#define INT_PISMO			26
+-#define INT_DoC				27	/* Disk on Chip memory controller */
+-#define INT_ETH				28	/* Ethernet controller */
+-#define INT_USB				29	/* USB controller */
+-#define INT_TSPENINT			30	/* Touchscreen pen */
+-#define INT_TSKPADINT			31	/* Touchscreen keypad */
+-
+-#else
+-
+-#define MAX_GIC_NR			2
+-
+-#define INT_AACI			0
+-#define INT_TIMERINT0_1			1
+-#define INT_TIMERINT2_3			2
+-#define INT_USB				3
+-#define INT_UARTINT0			4
+-#define INT_UARTINT1			5
+-#define INT_RTCINT			6
+-#define INT_KMI0			7
+-#define INT_KMI1			8
+-#define INT_ETH				9
+-#define INT_EB_IRQ1			10	/* main GIC */
+-#define INT_EB_IRQ2			11	/* tile GIC */
+-#define INT_EB_FIQ1			12	/* main GIC */
+-#define INT_EB_FIQ2			13	/* tile GIC */
+-#define INT_MMCI0A			14
+-#define INT_MMCI0B			15
+-
+-#define INT_PMU_CPU0			17
+-#define INT_PMU_CPU1			18
+-#define INT_PMU_CPU2			19
+-#define INT_PMU_CPU3			20
+-#define INT_PMU_SCU0			21
+-#define INT_PMU_SCU1			22
+-#define INT_PMU_SCU2			23
+-#define INT_PMU_SCU3			24
+-#define INT_PMU_SCU4			25
+-#define INT_PMU_SCU5			26
+-#define INT_PMU_SCU6			27
+-#define INT_PMU_SCU7			28
+-
+-#define INT_L220_EVENT			29
+-#define INT_L220_SLAVE			30
+-#define INT_L220_DECODE			31
+-
+-#define INT_UARTINT2			-1
+-#define INT_UARTINT3			-1
+-#define INT_CLCDINT			-1
+-#define INT_DMAINT			-1
+-#define INT_WDOGINT			-1
+-#define INT_GPIOINT0			-1
+-#define INT_GPIOINT1			-1
+-#define INT_GPIOINT2			-1
+-#define INT_SCIINT			-1
+-#define INT_SSPINT			-1
+-#endif
+-
+-/* 
+- *  Interrupt bit positions
+- * 
+- */
+-#define INTMASK_WDOGINT			(1 << INT_WDOGINT)
+-#define INTMASK_SOFTINT			(1 << INT_SOFTINT)
+-#define INTMASK_COMMRx			(1 << INT_COMMRx)
+-#define INTMASK_COMMTx			(1 << INT_COMMTx)
+-#define INTMASK_TIMERINT0_1		(1 << INT_TIMERINT0_1)
+-#define INTMASK_TIMERINT2_3		(1 << INT_TIMERINT2_3)
+-#define INTMASK_GPIOINT0		(1 << INT_GPIOINT0)
+-#define INTMASK_GPIOINT1		(1 << INT_GPIOINT1)
+-#define INTMASK_GPIOINT2		(1 << INT_GPIOINT2)
+-#define INTMASK_RTCINT			(1 << INT_RTCINT)
+-#define INTMASK_SSPINT			(1 << INT_SSPINT)
+-#define INTMASK_UARTINT0		(1 << INT_UARTINT0)
+-#define INTMASK_UARTINT1		(1 << INT_UARTINT1)
+-#define INTMASK_UARTINT2		(1 << INT_UARTINT2)
+-#define INTMASK_UARTINT3		(1 << INT_UARTINT3)
+-#define INTMASK_SCIINT			(1 << INT_SCIINT)
+-#define INTMASK_MMCI0A			(1 << INT_MMCI0A)
+-#define INTMASK_MMCI0B			(1 << INT_MMCI0B)
+-#define INTMASK_AACI			(1 << INT_AACI)
+-#define INTMASK_KMI0			(1 << INT_KMI0)
+-#define INTMASK_KMI1			(1 << INT_KMI1)
+-#define INTMASK_CHARLCD			(1 << INT_CHARLCD)
+-#define INTMASK_CLCDINT			(1 << INT_CLCDINT)
+-#define INTMASK_DMAINT			(1 << INT_DMAINT)
+-#define INTMASK_PWRFAILINT		(1 << INT_PWRFAILINT)
+-#define INTMASK_PISMO			(1 << INT_PISMO)
+-#define INTMASK_DoC			(1 << INT_DoC)
+-#define INTMASK_ETH			(1 << INT_ETH)
+-#define INTMASK_USB			(1 << INT_USB)
+-#define INTMASK_TSPENINT		(1 << INT_TSPENINT)
+-#define INTMASK_TSKPADINT		(1 << INT_TSKPADINT)
+-
+-#define MAXIRQNUM                       31
+-#define MAXFIQNUM                       31
+-#define MAXSWINUM                       31
+-
+ /* 
+  *  Application Flash
+  * 
+@@ -463,6 +315,4 @@
+ #define REALVIEW_CSR_BASE             0x10000000
+ #define REALVIEW_CSR_SIZE             0x10000000
+ 
+-#endif
+-
+-/* 	END */
++#endif	/* __ASM_ARCH_PLATFORM_H */
+diff --git a/include/asm-arm/arch-realview/scu.h b/include/asm-arm/arch-realview/scu.h
+index cc29364..08b3db8 100644
+--- a/include/asm-arm/arch-realview/scu.h
++++ b/include/asm-arm/arch-realview/scu.h
+@@ -1,8 +1,8 @@
+ #ifndef __ASMARM_ARCH_SCU_H
+ #define __ASMARM_ARCH_SCU_H
+ 
+-#include <asm/arch/platform.h>
++#include <asm/arch/board-eb.h>
+ 
+-#define SCU_BASE	REALVIEW_MPCORE_SCU_BASE
++#define SCU_BASE	REALVIEW_EB11MP_SCU_BASE
+ 
+ #endif
+diff --git a/include/asm-arm/arch-realview/uncompress.h b/include/asm-arm/arch-realview/uncompress.h
+index f05631d..3d5c2db 100644
+--- a/include/asm-arm/arch-realview/uncompress.h
++++ b/include/asm-arm/arch-realview/uncompress.h
+@@ -19,6 +19,8 @@
+  */
+ #include <asm/hardware.h>
+ 
++#include <asm/arch/platform.h>
++
+ #define AMBA_UART_DR	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x00))
+ #define AMBA_UART_LCRH	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x2c))
+ #define AMBA_UART_CR	(*(volatile unsigned char *) (REALVIEW_UART0_BASE + 0x30))
 diff --git a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
 index 9c8cd9a..89076c3 100644
 --- a/include/asm-arm/arch-s3c2410/debug-macro.S
@@ -802517,6 +868520,28 @@
  	/* we'll take a jump through zero as a poor second */
  	cpu_reset(0);
  }
+diff --git a/include/asm-arm/arch-versatile/irqs.h b/include/asm-arm/arch-versatile/irqs.h
+index 745aa84..f7263b9 100644
+--- a/include/asm-arm/arch-versatile/irqs.h
++++ b/include/asm-arm/arch-versatile/irqs.h
+@@ -22,7 +22,7 @@
+ #include <asm/arch/platform.h>
+ 
+ /* 
+- *  IRQ interrupts definitions are the same the INT definitions
++ *  IRQ interrupts definitions are the same as the INT definitions
+  *  held within platform.h
+  */
+ #define IRQ_VIC_START		0
+@@ -94,7 +94,7 @@
+ #define IRQMASK_VICSOURCE31	INTMASK_VICSOURCE31
+ 
+ /* 
+- *  FIQ interrupts definitions are the same the INT definitions.
++ *  FIQ interrupts definitions are the same as the INT definitions.
+  */
+ #define FIQ_WDOGINT		INT_WDOGINT
+ #define FIQ_SOFTINT		INT_SOFTINT
 diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h
 index 47a6b08..5c60bfc 100644
 --- a/include/asm-arm/bitops.h
@@ -802582,6 +868607,56 @@
  #ifdef CONFIG_SMP
  	__u32 cpu;
  #endif
+diff --git a/include/asm-arm/hardware/arm_twd.h b/include/asm-arm/hardware/arm_twd.h
+index 131d5b4..e521b70 100644
+--- a/include/asm-arm/hardware/arm_twd.h
++++ b/include/asm-arm/hardware/arm_twd.h
+@@ -1,7 +1,7 @@
+ #ifndef __ASM_HARDWARE_TWD_H
+ #define __ASM_HARDWARE_TWD_H
+ 
+-#define TWD_TIMER_LOAD 		0x00
++#define TWD_TIMER_LOAD 			0x00
+ #define TWD_TIMER_COUNTER		0x04
+ #define TWD_TIMER_CONTROL		0x08
+ #define TWD_TIMER_INTSTAT		0x0C
+@@ -13,4 +13,9 @@
+ #define TWD_WDOG_RESETSTAT		0x30
+ #define TWD_WDOG_DISABLE		0x34
+ 
++#define TWD_TIMER_CONTROL_ENABLE	(1 << 0)
++#define TWD_TIMER_CONTROL_ONESHOT	(0 << 1)
++#define TWD_TIMER_CONTROL_PERIODIC	(1 << 1)
++#define TWD_TIMER_CONTROL_IT_ENABLE	(1 << 2)
++
+ #endif
+diff --git a/include/asm-arm/hardware/it8152.h b/include/asm-arm/hardware/it8152.h
+index aaebb61..74b5fff 100644
+--- a/include/asm-arm/hardware/it8152.h
++++ b/include/asm-arm/hardware/it8152.h
+@@ -42,7 +42,7 @@ extern unsigned long it8152_base_address;
+ #define IT8152_GPIO_GPDR		__REG_IT8152(0x3f00500)
+ 
+ /*
+-  Interrup contoler per register summary:
++  Interrupt controller per register summary:
+   ---------------------------------------
+   LCDNIRR:
+   IT8152_LD_IRQ(8) PCICLK stop
+diff --git a/include/asm-arm/kexec.h b/include/asm-arm/kexec.h
+index 46dcc4d..1ee17b6 100644
+--- a/include/asm-arm/kexec.h
++++ b/include/asm-arm/kexec.h
+@@ -16,6 +16,9 @@
+ 
+ #define KEXEC_BOOT_PARAMS_SIZE 1536
+ 
++#define KEXEC_ARM_ATAGS_OFFSET  0x1000
++#define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
++
+ #ifndef __ASSEMBLY__
+ 
+ struct kimage;
 diff --git a/include/asm-arm/kprobes.h b/include/asm-arm/kprobes.h
 new file mode 100644
 index 0000000..4e7bd32
@@ -802668,11 +868743,15 @@
 +
 +#endif /* _ARM_KPROBES_H */
 diff --git a/include/asm-arm/mach/udc_pxa2xx.h b/include/asm-arm/mach/udc_pxa2xx.h
-index ff0a957..f191e14 100644
+index ff0a957..f9f3606 100644
 --- a/include/asm-arm/mach/udc_pxa2xx.h
 +++ b/include/asm-arm/mach/udc_pxa2xx.h
-@@ -19,7 +19,9 @@ struct pxa2xx_udc_mach_info {
- 	 * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
+@@ -16,10 +16,12 @@ struct pxa2xx_udc_mach_info {
+ #define	PXA2XX_UDC_CMD_DISCONNECT	1	/* so host won't see us */
+ 
+ 	/* Boards following the design guidelines in the developer's manual,
+-	 * with on-chip GPIOs not Lubbock's wierd hardware, can have a sane
++	 * with on-chip GPIOs not Lubbock's weird hardware, can have a sane
  	 * VBUS IRQ and omit the methods above.  Store the GPIO number
  	 * here; for GPIO 0, also mask in one of the pxa_gpio_mode() bits.
 +	 * Note that sometimes the signals go through inverters...
@@ -802681,6 +868760,46 @@
  	u16	gpio_vbus;			/* high == vbus present */
  	u16	gpio_pullup;			/* high == pullup activated */
  };
+diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
+index 4d43945..fb6c6e3 100644
+--- a/include/asm-arm/pgalloc.h
++++ b/include/asm-arm/pgalloc.h
+@@ -27,14 +27,14 @@
+  * Since we have only two-level page tables, these are trivial
+  */
+ #define pmd_alloc_one(mm,addr)		({ BUG(); ((pmd_t *)2); })
+-#define pmd_free(pmd)			do { } while (0)
++#define pmd_free(mm, pmd)		do { } while (0)
+ #define pgd_populate(mm,pmd,pte)	BUG()
+ 
+ extern pgd_t *get_pgd_slow(struct mm_struct *mm);
+-extern void free_pgd_slow(pgd_t *pgd);
++extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
+ 
+ #define pgd_alloc(mm)			get_pgd_slow(mm)
+-#define pgd_free(pgd)			free_pgd_slow(pgd)
++#define pgd_free(mm, pgd)		free_pgd_slow(mm, pgd)
+ 
+ /*
+  * Allocate one PTE table.
+@@ -83,7 +83,7 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+ /*
+  * Free one PTE table.
+  */
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	if (pte) {
+ 		pte -= PTRS_PER_PTE;
+@@ -91,7 +91,7 @@ static inline void pte_free_kernel(pte_t *pte)
+ 	}
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ }
 diff --git a/include/asm-arm/plat-s3c24xx/dma.h b/include/asm-arm/plat-s3c24xx/dma.h
 index 2c59406..c78efe3 100644
 --- a/include/asm-arm/plat-s3c24xx/dma.h
@@ -802877,6 +868996,61 @@
  # ifdef CONFIG_CPU_V6
  #  ifdef CPU_NAME
  #   undef  MULTI_CPU
+diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h
+index f67acce..af99636 100644
+--- a/include/asm-arm/smp.h
++++ b/include/asm-arm/smp.h
+@@ -61,6 +61,11 @@ extern void smp_cross_call(cpumask_t callmap);
+ extern void smp_send_timer(void);
+ 
+ /*
++ * Broadcast a clock event to other CPUs.
++ */
++extern void smp_timer_broadcast(cpumask_t mask);
++
++/*
+  * Boot a secondary CPU, and assign it the specified idle task.
+  * This also gives us the initial stack to use for this CPU.
+  */
+@@ -96,11 +101,12 @@ extern void platform_cpu_die(unsigned int cpu);
+ extern int platform_cpu_kill(unsigned int cpu);
+ extern void platform_cpu_enable(unsigned int cpu);
+ 
+-#ifdef CONFIG_LOCAL_TIMERS
+ /*
+- * Setup a local timer interrupt for a CPU.
++ * Local timer interrupt handling function (can be IPI'ed).
+  */
+-extern void local_timer_setup(unsigned int cpu);
++extern void local_timer_interrupt(void);
++
++#ifdef CONFIG_LOCAL_TIMERS
+ 
+ /*
+  * Stop a local timer interrupt.
+@@ -114,10 +120,6 @@ extern int local_timer_ack(void);
+ 
+ #else
+ 
+-static inline void local_timer_setup(unsigned int cpu)
+-{
+-}
+-
+ static inline void local_timer_stop(unsigned int cpu)
+ {
+ }
+@@ -125,6 +127,11 @@ static inline void local_timer_stop(unsigned int cpu)
+ #endif
+ 
+ /*
++ * Setup a local timer interrupt for a CPU.
++ */
++extern void local_timer_setup(unsigned int cpu);
++
++/*
+  * show local interrupt info
+  */
+ extern void show_local_irqs(struct seq_file *);
 diff --git a/include/asm-arm/socket.h b/include/asm-arm/socket.h
 index 65a1a64..6817be9 100644
 --- a/include/asm-arm/socket.h
@@ -802888,6 +869062,21 @@
 +#define SO_MARK			36
 +
  #endif /* _ASM_SOCKET_H */
+diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
+index cb74002..36bd402 100644
+--- a/include/asm-arm/tlb.h
++++ b/include/asm-arm/tlb.h
+@@ -85,8 +85,8 @@ tlb_end_vma(struct mmu_gather *tlb, struct vm_area_struct *vma)
+ }
+ 
+ #define tlb_remove_page(tlb,page)	free_page_and_swap_cache(page)
+-#define pte_free_tlb(tlb,ptep)		pte_free(ptep)
+-#define pmd_free_tlb(tlb,pmdp)		pmd_free(pmdp)
++#define pte_free_tlb(tlb, ptep)		pte_free((tlb)->mm, ptep)
++#define pmd_free_tlb(tlb, pmdp)		pmd_free((tlb)->mm, pmdp)
+ 
+ #define tlb_migrate_finish(mm)		do { } while (0)
+ 
 diff --git a/include/asm-arm/traps.h b/include/asm-arm/traps.h
 index d4f34dc..f1541af 100644
 --- a/include/asm-arm/traps.h
@@ -803049,10 +869238,10 @@
 -#endif /* __ASM_ARCH_AT32AP7000_H__ */
 diff --git a/include/asm-avr32/arch-at32ap/at32ap700x.h b/include/asm-avr32/arch-at32ap/at32ap700x.h
 new file mode 100644
-index 0000000..99684d6
+index 0000000..31e48b0
 --- /dev/null
 +++ b/include/asm-avr32/arch-at32ap/at32ap700x.h
-@@ -0,0 +1,35 @@
+@@ -0,0 +1,33 @@
 +/*
 + * Pin definitions for AT32AP7000.
 + *
@@ -803068,8 +869257,6 @@
 +#define GPIO_PERIPH_A	0
 +#define GPIO_PERIPH_B	1
 +
-+#define NR_GPIO_CONTROLLERS	4
-+
 +/*
 + * Pin numbers identifying specific GPIO pins on the chip. They can
 + * also be converted to IRQ numbers by passing them through
@@ -803108,6 +869295,56 @@
 +#define cpu_is_at91cap9()	(0)
  
  #endif /* __ASM_ARCH_CPU_H */
+diff --git a/include/asm-avr32/arch-at32ap/gpio.h b/include/asm-avr32/arch-at32ap/gpio.h
+index af7f953..0180f58 100644
+--- a/include/asm-avr32/arch-at32ap/gpio.h
++++ b/include/asm-avr32/arch-at32ap/gpio.h
+@@ -5,20 +5,36 @@
+ #include <asm/irq.h>
+ 
+ 
+-/* Arch-neutral GPIO API */
+-int __must_check gpio_request(unsigned int gpio, const char *label);
+-void gpio_free(unsigned int gpio);
++/* Some GPIO chips can manage IRQs; some can't.  The exact numbers can
++ * be changed if needed, but for the moment they're not configurable.
++ */
++#define ARCH_NR_GPIOS	(NR_GPIO_IRQS + 2 * 32)
+ 
+-int gpio_direction_input(unsigned int gpio);
+-int gpio_direction_output(unsigned int gpio, int value);
+-int gpio_get_value(unsigned int gpio);
+-void gpio_set_value(unsigned int gpio, int value);
+ 
+-#include <asm-generic/gpio.h>		/* cansleep wrappers */
++/* Arch-neutral GPIO API, supporting both "native" and external GPIOs. */
++#include <asm-generic/gpio.h>
++
++static inline int gpio_get_value(unsigned int gpio)
++{
++	return __gpio_get_value(gpio);
++}
++
++static inline void gpio_set_value(unsigned int gpio, int value)
++{
++	__gpio_set_value(gpio, value);
++}
++
++static inline int gpio_cansleep(unsigned int gpio)
++{
++	return __gpio_cansleep(gpio);
++}
++
+ 
+ static inline int gpio_to_irq(unsigned int gpio)
+ {
+-	return gpio + GPIO_IRQ_BASE;
++	if (gpio < NR_GPIO_IRQS)
++		return gpio + GPIO_IRQ_BASE;
++	return -EINVAL;
+ }
+ 
+ static inline int irq_to_gpio(unsigned int irq)
 diff --git a/include/asm-avr32/arch-at32ap/io.h b/include/asm-avr32/arch-at32ap/io.h
 index ee59e40..4ec6abc 100644
 --- a/include/asm-avr32/arch-at32ap/io.h
@@ -803130,6 +869367,24 @@
  # define __swizzle_addr_b(addr)	(addr ^ 1UL)
  # define __swizzle_addr_w(addr)	(addr)
  # define __swizzle_addr_l(addr)	(addr)
+diff --git a/include/asm-avr32/arch-at32ap/irq.h b/include/asm-avr32/arch-at32ap/irq.h
+index 5adffab..608e350 100644
+--- a/include/asm-avr32/arch-at32ap/irq.h
++++ b/include/asm-avr32/arch-at32ap/irq.h
+@@ -3,11 +3,11 @@
+ 
+ #define EIM_IRQ_BASE	NR_INTERNAL_IRQS
+ #define NR_EIM_IRQS	32
+-
+ #define AT32_EXTINT(n)	(EIM_IRQ_BASE + (n))
+ 
+ #define GPIO_IRQ_BASE	(EIM_IRQ_BASE + NR_EIM_IRQS)
+-#define NR_GPIO_IRQS	(5 * 32)
++#define NR_GPIO_CTLR	(5 /*internal*/ + 1 /*external*/)
++#define NR_GPIO_IRQS	(NR_GPIO_CTLR * 32)
+ 
+ #define NR_IRQS		(GPIO_IRQ_BASE + NR_GPIO_IRQS)
+ 
 diff --git a/include/asm-avr32/irq.h b/include/asm-avr32/irq.h
 index 83e6549..9315724 100644
 --- a/include/asm-avr32/irq.h
@@ -803172,6 +869427,34 @@
  #endif /* !__ASSEMBLER__ */
  
  #endif /* __ASM_AVR32_OCD_H */
+diff --git a/include/asm-avr32/pgalloc.h b/include/asm-avr32/pgalloc.h
+index 0e680f4..b77e364 100644
+--- a/include/asm-avr32/pgalloc.h
++++ b/include/asm-avr32/pgalloc.h
+@@ -30,7 +30,7 @@ static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return kcalloc(USER_PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL);
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	kfree(pgd);
+ }
+@@ -55,12 +55,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return pte;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ }
 diff --git a/include/asm-avr32/processor.h b/include/asm-avr32/processor.h
 index a52576b..4212551 100644
 --- a/include/asm-avr32/processor.h
@@ -803269,6 +869552,19 @@
  #define TIF_USERSPACE		31      /* true if FS sets userspace */
  
  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+diff --git a/include/asm-avr32/unistd.h b/include/asm-avr32/unistd.h
+index de09009..89861a2 100644
+--- a/include/asm-avr32/unistd.h
++++ b/include/asm-avr32/unistd.h
+@@ -297,7 +297,7 @@
+ 
+ #define __NR_utimensat		278
+ #define __NR_signalfd		279
+-#define __NR_timerfd		280
++/* 280 was __NR_timerfd */
+ #define __NR_eventfd		281
+ 
+ #ifdef __KERNEL__
 diff --git a/include/asm-blackfin/bfin-global.h b/include/asm-blackfin/bfin-global.h
 index 39bdd86..6ae0619 100644
 --- a/include/asm-blackfin/bfin-global.h
@@ -804337,6 +870633,52 @@
  #define IDE_ARCH_ACK_INTR
  #define ide_ack_intr(hwif)	((hwif)->ack_intr(hwif))
  
+diff --git a/include/asm-cris/bitops.h b/include/asm-cris/bitops.h
+index e2f49c2..75ea6e0 100644
+--- a/include/asm-cris/bitops.h
++++ b/include/asm-cris/bitops.h
+@@ -24,13 +24,6 @@
+ #include <linux/compiler.h>
+ 
+ /*
+- * Some hacks to defeat gcc over-optimizations..
+- */
+-struct __dummy { unsigned long a[100]; };
+-#define ADDR (*(struct __dummy *) addr)
+-#define CONST_ADDR (*(const struct __dummy *) addr)
+-
+-/*
+  * set_bit - Atomically set a bit in memory
+  * @nr: the bit to set
+  * @addr: the address to start counting from
+diff --git a/include/asm-cris/pgalloc.h b/include/asm-cris/pgalloc.h
+index deaddfe..8ddd66f 100644
+--- a/include/asm-cris/pgalloc.h
++++ b/include/asm-cris/pgalloc.h
+@@ -16,7 +16,7 @@ static inline pgd_t *pgd_alloc (struct mm_struct *mm)
+ 	return (pgd_t *)get_zeroed_page(GFP_KERNEL);
+ }
+ 
+-static inline void pgd_free (pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_page((unsigned long)pgd);
+ }
+@@ -34,12 +34,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
+ 	return pte;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ }
 diff --git a/include/asm-cris/socket.h b/include/asm-cris/socket.h
 index 5b18dfd..9df0ca8 100644
 --- a/include/asm-cris/socket.h
@@ -804350,6 +870692,79 @@
  #endif /* _ASM_SOCKET_H */
  
  
+diff --git a/include/asm-frv/atomic.h b/include/asm-frv/atomic.h
+index d425d8d..6ec494a 100644
+--- a/include/asm-frv/atomic.h
++++ b/include/asm-frv/atomic.h
+@@ -1,7 +1,7 @@
+ /* atomic.h: atomic operation emulation for FR-V
+  *
+  * For an explanation of how atomic ops work in this arch, see:
+- *   Documentation/fujitsu/frv/atomic-ops.txt
++ *   Documentation/frv/atomic-ops.txt
+  *
+  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+  * Written by David Howells (dhowells at redhat.com)
+diff --git a/include/asm-frv/bitops.h b/include/asm-frv/bitops.h
+index e29de71..5f86b87 100644
+--- a/include/asm-frv/bitops.h
++++ b/include/asm-frv/bitops.h
+@@ -1,7 +1,7 @@
+ /* bitops.h: bit operations for the Fujitsu FR-V CPUs
+  *
+  * For an explanation of how atomic ops work in this arch, see:
+- *   Documentation/fujitsu/frv/atomic-ops.txt
++ *   Documentation/frv/atomic-ops.txt
+  *
+  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+  * Written by David Howells (dhowells at redhat.com)
+diff --git a/include/asm-frv/cacheflush.h b/include/asm-frv/cacheflush.h
+index 0250040..432a69e 100644
+--- a/include/asm-frv/cacheflush.h
++++ b/include/asm-frv/cacheflush.h
+@@ -29,7 +29,7 @@
+ #define flush_dcache_mmap_unlock(mapping)	do {} while(0)
+ 
+ /*
+- * physically-indexed cache managment
++ * physically-indexed cache management
+  * - see arch/frv/lib/cache.S
+  */
+ extern void frv_dcache_writeback(unsigned long start, unsigned long size);
+diff --git a/include/asm-frv/dma-mapping.h b/include/asm-frv/dma-mapping.h
+index bcb2df6..2e8966c 100644
+--- a/include/asm-frv/dma-mapping.h
++++ b/include/asm-frv/dma-mapping.h
+@@ -17,16 +17,6 @@ void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle
+ void dma_free_coherent(struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle);
+ 
+ /*
+- * These macros should be used after a pci_map_sg call has been done
+- * to get bus addresses of each of the SG entries and their lengths.
+- * You should only work with the number of sg entries pci_map_sg
+- * returns, or alternatively stop on the first sg_dma_len(sg) which
+- * is 0.
+- */
+-#define sg_dma_address(sg)	((sg)->dma_address)
+-#define sg_dma_len(sg)		((sg)->length)
+-
+-/*
+  * Map a single buffer of the indicated size for DMA in streaming mode.
+  * The 32-bit bus address to use is returned.
+  *
+diff --git a/include/asm-frv/highmem.h b/include/asm-frv/highmem.h
+index ff4d6cd..26cefcd 100644
+--- a/include/asm-frv/highmem.h
++++ b/include/asm-frv/highmem.h
+@@ -4,7 +4,7 @@
+  * Written by David Howells (dhowells at redhat.com)
+  * - Derived from include/asm-i386/highmem.h
+  *
+- * See Documentation/fujitsu/frv/mmu-layout.txt for more information.
++ * See Documentation/frv/mmu-layout.txt for more information.
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
 diff --git a/include/asm-frv/ide.h b/include/asm-frv/ide.h
 index f0bd2cb..8c9a540 100644
 --- a/include/asm-frv/ide.h
@@ -804367,6 +870782,112 @@
  #ifndef MAX_HWIFS
  #define MAX_HWIFS 8
  #endif
+diff --git a/include/asm-frv/mem-layout.h b/include/asm-frv/mem-layout.h
+index aaf2a77..8353225 100644
+--- a/include/asm-frv/mem-layout.h
++++ b/include/asm-frv/mem-layout.h
+@@ -39,7 +39,7 @@
+ 
+ #ifdef CONFIG_MMU
+ 
+-/* see Documentation/fujitsu/frv/mmu-layout.txt */
++/* see Documentation/frv/mmu-layout.txt */
+ #define KERNEL_LOWMEM_START		__UL(0xc0000000)
+ #define KERNEL_LOWMEM_END		__UL(0xd0000000)
+ #define VMALLOC_START			__UL(0xd0000000)
+diff --git a/include/asm-frv/page.h b/include/asm-frv/page.h
+index 213d92f..bd9bd2d 100644
+--- a/include/asm-frv/page.h
++++ b/include/asm-frv/page.h
+@@ -76,10 +76,6 @@ extern unsigned long max_pfn;
+ 
+ #endif /* __ASSEMBLY__ */
+ 
+-#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
+-#define WANT_PAGE_VIRTUAL	1
+-#endif
+-
+ #include <asm-generic/memory_model.h>
+ #include <asm-generic/page.h>
+ 
+diff --git a/include/asm-frv/pgalloc.h b/include/asm-frv/pgalloc.h
+index ce982a6..e89620e 100644
+--- a/include/asm-frv/pgalloc.h
++++ b/include/asm-frv/pgalloc.h
+@@ -31,18 +31,18 @@ do {										\
+  */
+ 
+ extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(pgd_t *);
++extern void pgd_free(struct mm_struct *mm, pgd_t *);
+ 
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+ 
+ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ }
+@@ -55,7 +55,7 @@ static inline void pte_free(struct page *pte)
+  * (In the PAE case we free the pmds as part of the pgd.)
+  */
+ #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *) 2); })
+-#define pmd_free(x)			do { } while (0)
++#define pmd_free(mm, x)			do { } while (0)
+ #define __pmd_free_tlb(tlb,x)		do { } while (0)
+ 
+ #endif /* CONFIG_MMU */
+diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
+index 147e995..6c0682e 100644
+--- a/include/asm-frv/pgtable.h
++++ b/include/asm-frv/pgtable.h
+@@ -93,7 +93,7 @@ extern unsigned long empty_zero_page;
+ 
+ /*
+  * we use 2-level page tables, folding the PMD (mid-level table) into the PGE (top-level entry)
+- * [see Documentation/fujitsu/frv/mmu-layout.txt]
++ * [see Documentation/frv/mmu-layout.txt]
+  *
+  * Page Directory:
+  *  - Size: 16KB
+@@ -226,7 +226,7 @@ static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
+  * inside the pgd, so has no extra memory associated with it.
+  */
+ #define pud_alloc_one(mm, address)		NULL
+-#define pud_free(x)				do { } while (0)
++#define pud_free(mm, x)				do { } while (0)
+ #define __pud_free_tlb(tlb, x)			do { } while (0)
+ 
+ /*
+diff --git a/include/asm-frv/scatterlist.h b/include/asm-frv/scatterlist.h
+index 2e7143b..4bca8a2 100644
+--- a/include/asm-frv/scatterlist.h
++++ b/include/asm-frv/scatterlist.h
+@@ -31,6 +31,16 @@ struct scatterlist {
+ 	unsigned int	length;
+ };
+ 
++/*
++ * These macros should be used after a pci_map_sg call has been done
++ * to get bus addresses of each of the SG entries and their lengths.
++ * You should only work with the number of sg entries pci_map_sg
++ * returns, or alternatively stop on the first sg_dma_len(sg) which
++ * is 0.
++ */
++#define sg_dma_address(sg)	((sg)->dma_address)
++#define sg_dma_len(sg)		((sg)->length)
++
+ #define ISA_DMA_THRESHOLD (0xffffffffUL)
+ 
+ #endif /* !_ASM_SCATTERLIST_H */
 diff --git a/include/asm-frv/socket.h b/include/asm-frv/socket.h
 index a823bef..e51ca67 100644
 --- a/include/asm-frv/socket.h
@@ -804379,6 +870900,32 @@
 +
  #endif /* _ASM_SOCKET_H */
  
+diff --git a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
+index cd84f17..e8c9866 100644
+--- a/include/asm-frv/unistd.h
++++ b/include/asm-frv/unistd.h
+@@ -328,7 +328,7 @@
+ #define __NR_epoll_pwait	319
+ #define __NR_utimensat		320
+ #define __NR_signalfd		321
+-#define __NR_timerfd		322
++/* #define __NR_timerfd		322 removed */
+ #define __NR_eventfd		323
+ #define __NR_fallocate		324
+ 
+diff --git a/include/asm-generic/4level-fixup.h b/include/asm-generic/4level-fixup.h
+index 7b88d39..9d40e87 100644
+--- a/include/asm-generic/4level-fixup.h
++++ b/include/asm-generic/4level-fixup.h
+@@ -28,7 +28,7 @@
+ 
+ #undef pud_free_tlb
+ #define pud_free_tlb(tlb, x)            do { } while (0)
+-#define pud_free(x)			do { } while (0)
++#define pud_free(mm, x)			do { } while (0)
+ #define __pud_free_tlb(tlb, x)		do { } while (0)
+ 
+ #undef  pud_addr_end
 diff --git a/include/asm-generic/bitops/ext2-non-atomic.h b/include/asm-generic/bitops/ext2-non-atomic.h
 index 1697404..63cf822 100644
 --- a/include/asm-generic/bitops/ext2-non-atomic.h
@@ -804443,6 +870990,120 @@
  	unlikely(__ret_warn_on);					\
  })
  #endif
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index 2d0aab1..f29a502 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -1,6 +1,102 @@
+ #ifndef _ASM_GENERIC_GPIO_H
+ #define _ASM_GENERIC_GPIO_H
+ 
++#ifdef CONFIG_HAVE_GPIO_LIB
++
++/* Platforms may implement their GPIO interface with library code,
++ * at a small performance cost for non-inlined operations and some
++ * extra memory (for code and for per-GPIO table entries).
++ *
++ * While the GPIO programming interface defines valid GPIO numbers
++ * to be in the range 0..MAX_INT, this library restricts them to the
++ * smaller range 0..ARCH_NR_GPIOS.
++ */
++
++#ifndef ARCH_NR_GPIOS
++#define ARCH_NR_GPIOS		256
++#endif
++
++struct seq_file;
++
++/**
++ * struct gpio_chip - abstract a GPIO controller
++ * @label: for diagnostics
++ * @direction_input: configures signal "offset" as input, or returns error
++ * @get: returns value for signal "offset"; for output signals this
++ *	returns either the value actually sensed, or zero
++ * @direction_output: configures signal "offset" as output, or returns error
++ * @set: assigns output value for signal "offset"
++ * @dbg_show: optional routine to show contents in debugfs; default code
++ *	will be used when this is omitted, but custom code can show extra
++ *	state (such as pullup/pulldown configuration).
++ * @base: identifies the first GPIO number handled by this chip; or, if
++ *	negative during registration, requests dynamic ID allocation.
++ * @ngpio: the number of GPIOs handled by this controller; the last GPIO
++ *	handled is (base + ngpio - 1).
++ * @can_sleep: flag must be set iff get()/set() methods sleep, as they
++ *	must while accessing GPIO expander chips over I2C or SPI
++ *
++ * A gpio_chip can help platforms abstract various sources of GPIOs so
++ * they can all be accessed through a common programing interface.
++ * Example sources would be SOC controllers, FPGAs, multifunction
++ * chips, dedicated GPIO expanders, and so on.
++ *
++ * Each chip controls a number of signals, identified in method calls
++ * by "offset" values in the range 0..(@ngpio - 1).  When those signals
++ * are referenced through calls like gpio_get_value(gpio), the offset
++ * is calculated by subtracting @base from the gpio number.
++ */
++struct gpio_chip {
++	char			*label;
++
++	int			(*direction_input)(struct gpio_chip *chip,
++						unsigned offset);
++	int			(*get)(struct gpio_chip *chip,
++						unsigned offset);
++	int			(*direction_output)(struct gpio_chip *chip,
++						unsigned offset, int value);
++	void			(*set)(struct gpio_chip *chip,
++						unsigned offset, int value);
++	void			(*dbg_show)(struct seq_file *s,
++						struct gpio_chip *chip);
++	int			base;
++	u16			ngpio;
++	unsigned		can_sleep:1;
++};
++
++extern const char *gpiochip_is_requested(struct gpio_chip *chip,
++			unsigned offset);
++
++/* add/remove chips */
++extern int gpiochip_add(struct gpio_chip *chip);
++extern int __must_check gpiochip_remove(struct gpio_chip *chip);
++
++
++/* Always use the library code for GPIO management calls,
++ * or when sleeping may be involved.
++ */
++extern int gpio_request(unsigned gpio, const char *label);
++extern void gpio_free(unsigned gpio);
++
++extern int gpio_direction_input(unsigned gpio);
++extern int gpio_direction_output(unsigned gpio, int value);
++
++extern int gpio_get_value_cansleep(unsigned gpio);
++extern void gpio_set_value_cansleep(unsigned gpio, int value);
++
++
++/* A platform's <asm/gpio.h> code may want to inline the I/O calls when
++ * the GPIO is constant and refers to some always-present controller,
++ * giving direct access to chip registers and tight bitbanging loops.
++ */
++extern int __gpio_get_value(unsigned gpio);
++extern void __gpio_set_value(unsigned gpio, int value);
++
++extern int __gpio_cansleep(unsigned gpio);
++
++
++#else
++
+ /* platforms that don't directly support access to GPIOs through I2C, SPI,
+  * or other blocking infrastructure can use these wrappers.
+  */
+@@ -22,4 +118,6 @@ static inline void gpio_set_value_cansleep(unsigned gpio, int value)
+ 	gpio_set_value(gpio, value);
+ }
+ 
++#endif
++
+ #endif /* _ASM_GENERIC_GPIO_H */
 diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
 index d85172e..4b8d31c 100644
 --- a/include/asm-generic/percpu.h
@@ -804563,6 +871224,32 @@
 +					__typeof__(type) per_cpu_var(name)
  
  #endif /* _ASM_GENERIC_PERCPU_H_ */
+diff --git a/include/asm-generic/pgtable-nopmd.h b/include/asm-generic/pgtable-nopmd.h
+index 29ff5d8..087325e 100644
+--- a/include/asm-generic/pgtable-nopmd.h
++++ b/include/asm-generic/pgtable-nopmd.h
+@@ -54,7 +54,7 @@ static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
+  * inside the pud, so has no extra memory associated with it.
+  */
+ #define pmd_alloc_one(mm, address)		NULL
+-#define pmd_free(x)				do { } while (0)
++#define pmd_free(mm, x)				do { } while (0)
+ #define __pmd_free_tlb(tlb, x)			do { } while (0)
+ 
+ #undef  pmd_addr_end
+diff --git a/include/asm-generic/pgtable-nopud.h b/include/asm-generic/pgtable-nopud.h
+index 5664645..87cf449 100644
+--- a/include/asm-generic/pgtable-nopud.h
++++ b/include/asm-generic/pgtable-nopud.h
+@@ -51,7 +51,7 @@ static inline pud_t * pud_offset(pgd_t * pgd, unsigned long address)
+  * inside the pgd, so has no extra memory associated with it.
+  */
+ #define pud_alloc_one(mm, address)		NULL
+-#define pud_free(x)				do { } while (0)
++#define pud_free(mm, x)				do { } while (0)
+ #define __pud_free_tlb(tlb, x)			do { } while (0)
+ 
+ #undef  pud_addr_end
 diff --git a/include/asm-generic/resource.h b/include/asm-generic/resource.h
 index a4a22cc..587566f 100644
 --- a/include/asm-generic/resource.h
@@ -804586,6 +871273,63 @@
  }
  
  #endif	/* __KERNEL__ */
+diff --git a/include/asm-generic/rtc.h b/include/asm-generic/rtc.h
+index d3238f1..dd1bed8 100644
+--- a/include/asm-generic/rtc.h
++++ b/include/asm-generic/rtc.h
+@@ -35,10 +35,11 @@
+ static inline unsigned char rtc_is_updating(void)
+ {
+ 	unsigned char uip;
++	unsigned long flags;
+ 
+-	spin_lock_irq(&rtc_lock);
++	spin_lock_irqsave(&rtc_lock, flags);
+ 	uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
+-	spin_unlock_irq(&rtc_lock);
++	spin_unlock_irqrestore(&rtc_lock, flags);
+ 	return uip;
+ }
+ 
+@@ -46,6 +47,8 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
+ {
+ 	unsigned long uip_watchdog = jiffies;
+ 	unsigned char ctrl;
++	unsigned long flags;
++
+ #ifdef CONFIG_MACH_DECSTATION
+ 	unsigned int real_year;
+ #endif
+@@ -72,7 +75,7 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
+ 	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
+ 	 * by the RTC when initially set to a non-zero value.
+ 	 */
+-	spin_lock_irq(&rtc_lock);
++	spin_lock_irqsave(&rtc_lock, flags);
+ 	time->tm_sec = CMOS_READ(RTC_SECONDS);
+ 	time->tm_min = CMOS_READ(RTC_MINUTES);
+ 	time->tm_hour = CMOS_READ(RTC_HOURS);
+@@ -83,7 +86,7 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
+ 	real_year = CMOS_READ(RTC_DEC_YEAR);
+ #endif
+ 	ctrl = CMOS_READ(RTC_CONTROL);
+-	spin_unlock_irq(&rtc_lock);
++	spin_unlock_irqrestore(&rtc_lock, flags);
+ 
+ 	if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+ 	{
+diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h
+index 75f2bfa..f490e43 100644
+--- a/include/asm-generic/tlb.h
++++ b/include/asm-generic/tlb.h
+@@ -14,7 +14,6 @@
+ #define _ASM_GENERIC__TLB_H
+ 
+ #include <linux/swap.h>
+-#include <linux/quicklist.h>
+ #include <asm/pgalloc.h>
+ #include <asm/tlbflush.h>
+ 
 diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
 index 9f584cc..f784d2f 100644
 --- a/include/asm-generic/vmlinux.lds.h
@@ -804756,19 +871500,194 @@
  #define flush_agp_cache()		mb()
  
  /* Convert a physical address to an address suitable for the GART. */
+diff --git a/include/asm-ia64/bitops.h b/include/asm-ia64/bitops.h
+index a1b9719..953d3df 100644
+--- a/include/asm-ia64/bitops.h
++++ b/include/asm-ia64/bitops.h
+@@ -122,38 +122,40 @@ clear_bit_unlock (int nr, volatile void *addr)
+ }
+ 
+ /**
+- * __clear_bit_unlock - Non-atomically clear a bit with release
++ * __clear_bit_unlock - Non-atomically clears a bit in memory with release
++ * @nr: Bit to clear
++ * @addr: Address to start counting from
+  *
+- * This is like clear_bit_unlock, but the implementation uses a store
++ * Similarly to clear_bit_unlock, the implementation uses a store
+  * with release semantics. See also __raw_spin_unlock().
+  */
+ static __inline__ void
+-__clear_bit_unlock(int nr, volatile void *addr)
++__clear_bit_unlock(int nr, void *addr)
+ {
+-	__u32 mask, new;
+-	volatile __u32 *m;
++	__u32 * const m = (__u32 *) addr + (nr >> 5);
++	__u32 const new = *m & ~(1 << (nr & 31));
+ 
+-	m = (volatile __u32 *)addr + (nr >> 5);
+-	mask = ~(1 << (nr & 31));
+-	new = *m & mask;
+-	barrier();
+ 	ia64_st4_rel_nta(m, new);
+ }
+ 
+ /**
+  * __clear_bit - Clears a bit in memory (non-atomic version)
++ * @nr: the bit to clear
++ * @addr: the address to start counting from
++ *
++ * Unlike clear_bit(), this function is non-atomic and may be reordered.
++ * If it's called on the same region of memory simultaneously, the effect
++ * may be that only one operation succeeds.
+  */
+ static __inline__ void
+ __clear_bit (int nr, volatile void *addr)
+ {
+-	volatile __u32 *p = (__u32 *) addr + (nr >> 5);
+-	__u32 m = 1 << (nr & 31);
+-	*p &= ~m;
++	*((__u32 *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
+ }
+ 
+ /**
+  * change_bit - Toggle a bit in memory
+- * @nr: Bit to clear
++ * @nr: Bit to toggle
+  * @addr: Address to start counting from
+  *
+  * change_bit() is atomic and may not be reordered.
+@@ -178,7 +180,7 @@ change_bit (int nr, volatile void *addr)
+ 
+ /**
+  * __change_bit - Toggle a bit in memory
+- * @nr: the bit to set
++ * @nr: the bit to toggle
+  * @addr: the address to start counting from
+  *
+  * Unlike change_bit(), this function is non-atomic and may be reordered.
+@@ -197,7 +199,7 @@ __change_bit (int nr, volatile void *addr)
+  * @addr: Address to count from
+  *
+  * This operation is atomic and cannot be reordered.  
+- * It also implies a memory barrier.
++ * It also implies the acquisition side of the memory barrier.
+  */
+ static __inline__ int
+ test_and_set_bit (int nr, volatile void *addr)
+@@ -247,11 +249,11 @@ __test_and_set_bit (int nr, volatile void *addr)
+ 
+ /**
+  * test_and_clear_bit - Clear a bit and return its old value
+- * @nr: Bit to set
++ * @nr: Bit to clear
+  * @addr: Address to count from
+  *
+  * This operation is atomic and cannot be reordered.  
+- * It also implies a memory barrier.
++ * It also implies the acquisition side of the memory barrier.
+  */
+ static __inline__ int
+ test_and_clear_bit (int nr, volatile void *addr)
+@@ -272,7 +274,7 @@ test_and_clear_bit (int nr, volatile void *addr)
+ 
+ /**
+  * __test_and_clear_bit - Clear a bit and return its old value
+- * @nr: Bit to set
++ * @nr: Bit to clear
+  * @addr: Address to count from
+  *
+  * This operation is non-atomic and can be reordered.  
+@@ -292,11 +294,11 @@ __test_and_clear_bit(int nr, volatile void * addr)
+ 
+ /**
+  * test_and_change_bit - Change a bit and return its old value
+- * @nr: Bit to set
++ * @nr: Bit to change
+  * @addr: Address to count from
+  *
+  * This operation is atomic and cannot be reordered.  
+- * It also implies a memory barrier.
++ * It also implies the acquisition side of the memory barrier.
+  */
+ static __inline__ int
+ test_and_change_bit (int nr, volatile void *addr)
+@@ -315,8 +317,12 @@ test_and_change_bit (int nr, volatile void *addr)
+ 	return (old & bit) != 0;
+ }
+ 
+-/*
+- * WARNING: non atomic version.
++/**
++ * __test_and_change_bit - Change a bit and return its old value
++ * @nr: Bit to change
++ * @addr: Address to count from
++ *
++ * This operation is non-atomic and can be reordered.
+  */
+ static __inline__ int
+ __test_and_change_bit (int nr, void *addr)
+diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
+index 0f6e526..dfcf75b 100644
+--- a/include/asm-ia64/compat.h
++++ b/include/asm-ia64/compat.h
+@@ -181,7 +181,7 @@ struct compat_shmid64_ds {
+ /*
+  * A pointer passed in from user mode. This should not be used for syscall parameters,
+  * just declare them as pointers because the syscall entry code will have appropriately
+- * comverted them already.
++ * converted them already.
+  */
+ typedef	u32		compat_uptr_t;
+ 
 diff --git a/include/asm-ia64/gcc_intrin.h b/include/asm-ia64/gcc_intrin.h
-index e58d329..5b6665c 100644
+index e58d329..de2ed2c 100644
 --- a/include/asm-ia64/gcc_intrin.h
 +++ b/include/asm-ia64/gcc_intrin.h
-@@ -24,7 +24,7 @@
+@@ -24,7 +24,9 @@
  extern void ia64_bad_param_for_setreg (void);
  extern void ia64_bad_param_for_getreg (void);
  
 -register unsigned long ia64_r13 asm ("r13") __attribute_used__;
++#ifdef __KERNEL__
 +register unsigned long ia64_r13 asm ("r13") __used;
++#endif
  
  #define ia64_setreg(regnum, val)						\
  ({										\
+diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h
+index 823553b..f1663aa 100644
+--- a/include/asm-ia64/mca.h
++++ b/include/asm-ia64/mca.h
+@@ -3,9 +3,9 @@
+  * Purpose:	Machine check handling specific defines
+  *
+  * Copyright (C) 1999, 2004 Silicon Graphics, Inc.
+- * Copyright (C) Vijay Chander (vijay at engr.sgi.com)
+- * Copyright (C) Srinivasa Thirumalachar (sprasad at engr.sgi.com)
+- * Copyright (C) Russ Anderson (rja at sgi.com)
++ * Copyright (C) Vijay Chander <vijay at engr.sgi.com>
++ * Copyright (C) Srinivasa Thirumalachar <sprasad at engr.sgi.com>
++ * Copyright (C) Russ Anderson <rja at sgi.com>
+  */
+ 
+ #ifndef _ASM_IA64_MCA_H
+diff --git a/include/asm-ia64/mca_asm.h b/include/asm-ia64/mca_asm.h
+index 76203f9..dd2a5b1 100644
+--- a/include/asm-ia64/mca_asm.h
++++ b/include/asm-ia64/mca_asm.h
+@@ -1,8 +1,9 @@
+ /*
+  * File:	mca_asm.h
++ * Purpose:	Machine check handling specific defines
+  *
+  * Copyright (C) 1999 Silicon Graphics, Inc.
+- * Copyright (C) Vijay Chander (vijay at engr.sgi.com)
++ * Copyright (C) Vijay Chander <vijay at engr.sgi.com>
+  * Copyright (C) Srinivasa Thirumalachar <sprasad at engr.sgi.com>
+  * Copyright (C) 2000 Hewlett-Packard Co.
+  * Copyright (C) 2000 David Mosberger-Tang <davidm at hpl.hp.com>
 diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
 index c4f1e32..77f30b6 100644
 --- a/include/asm-ia64/percpu.h
@@ -804855,6 +871774,126 @@
  
  #endif /* !__ASSEMBLY__ */
  
+diff --git a/include/asm-ia64/pgalloc.h b/include/asm-ia64/pgalloc.h
+index 67552ca..556d988 100644
+--- a/include/asm-ia64/pgalloc.h
++++ b/include/asm-ia64/pgalloc.h
+@@ -27,7 +27,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return quicklist_alloc(0, GFP_KERNEL, NULL);
+ }
+ 
+-static inline void pgd_free(pgd_t * pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	quicklist_free(0, NULL, pgd);
+ }
+@@ -44,11 +44,11 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+ 	return quicklist_alloc(0, GFP_KERNEL, NULL);
+ }
+ 
+-static inline void pud_free(pud_t * pud)
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+ {
+ 	quicklist_free(0, NULL, pud);
+ }
+-#define __pud_free_tlb(tlb, pud)	pud_free(pud)
++#define __pud_free_tlb(tlb, pud)	pud_free((tlb)->mm, pud)
+ #endif /* CONFIG_PGTABLE_4 */
+ 
+ static inline void
+@@ -62,12 +62,12 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+ 	return quicklist_alloc(0, GFP_KERNEL, NULL);
+ }
+ 
+-static inline void pmd_free(pmd_t * pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	quicklist_free(0, NULL, pmd);
+ }
+ 
+-#define __pmd_free_tlb(tlb, pmd)	pmd_free(pmd)
++#define __pmd_free_tlb(tlb, pmd)	pmd_free((tlb)->mm, pmd)
+ 
+ static inline void
+ pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte)
+@@ -94,12 +94,12 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
+ 	return quicklist_alloc(0, GFP_KERNEL, NULL);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	quicklist_free_page(0, NULL, pte);
+ }
+ 
+-static inline void pte_free_kernel(pte_t * pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	quicklist_free(0, NULL, pte);
+ }
+@@ -109,6 +109,6 @@ static inline void check_pgt_cache(void)
+ 	quicklist_trim(0, NULL, 25, 16);
+ }
+ 
+-#define __pte_free_tlb(tlb, pte)	pte_free(pte)
++#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+ 
+ #endif				/* _ASM_IA64_PGALLOC_H */
+diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
+index be3b0ae..741f7ec 100644
+--- a/include/asm-ia64/processor.h
++++ b/include/asm-ia64/processor.h
+@@ -31,7 +31,8 @@
+  * each (assuming 8KB page size), for a total of 8TB of user virtual
+  * address space.
+  */
+-#define TASK_SIZE		(current->thread.task_size)
++#define TASK_SIZE_OF(tsk)	((tsk)->thread.task_size)
++#define TASK_SIZE       	TASK_SIZE_OF(current)
+ 
+ /*
+  * This decides where the kernel will search for a free chunk of vm
+@@ -472,7 +473,7 @@ ia64_set_psr (__u64 psr)
+ {
+ 	ia64_stop();
+ 	ia64_setreg(_IA64_REG_PSR_L, psr);
+-	ia64_srlz_d();
++	ia64_srlz_i();
+ }
+ 
+ /*
+diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h
+index 1f5412d..2251118 100644
+--- a/include/asm-ia64/sal.h
++++ b/include/asm-ia64/sal.h
+@@ -649,17 +649,6 @@ typedef struct err_rec {
+  * Now define a couple of inline functions for improved type checking
+  * and convenience.
+  */
+-static inline long
+-ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
+-		    unsigned long *drift_info)
+-{
+-	struct ia64_sal_retval isrv;
+-
+-	SAL_CALL(isrv, SAL_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
+-	*ticks_per_second = isrv.v0;
+-	*drift_info = isrv.v1;
+-	return isrv.status;
+-}
+ 
+ extern s64 ia64_sal_cache_flush (u64 cache_type);
+ extern void __init check_sal_cache_flush (void);
+@@ -841,6 +830,9 @@ extern int ia64_sal_oemcall_nolock(struct ia64_sal_retval *, u64, u64, u64,
+ 				   u64, u64, u64, u64, u64);
+ extern int ia64_sal_oemcall_reentrant(struct ia64_sal_retval *, u64, u64, u64,
+ 				      u64, u64, u64, u64, u64);
++extern long
++ia64_sal_freq_base (unsigned long which, unsigned long *ticks_per_second,
++		    unsigned long *drift_info);
+ #ifdef CONFIG_HOTPLUG_CPU
+ /*
+  * System Abstraction Layer Specification
 diff --git a/include/asm-ia64/socket.h b/include/asm-ia64/socket.h
 index 9e42ce4..d5ef0aa 100644
 --- a/include/asm-ia64/socket.h
@@ -804866,6 +871905,77 @@
 +#define SO_MARK			36
 +
  #endif /* _ASM_IA64_SOCKET_H */
+diff --git a/include/asm-m32r/irq.h b/include/asm-m32r/irq.h
+index 2f93f47..242028b 100644
+--- a/include/asm-m32r/irq.h
++++ b/include/asm-m32r/irq.h
+@@ -3,7 +3,7 @@
+ #define _ASM_M32R_IRQ_H
+ 
+ 
+-#if defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_USRV)
++#if defined(CONFIG_PLAT_USRV)
+ /*
+  * IRQ definitions for M32700UT
+  *  M32700 Chip: 64 interrupts
+diff --git a/include/asm-m32r/m32700ut/m32700ut_pld.h b/include/asm-m32r/m32700ut/m32700ut_pld.h
+index d391212..57623be 100644
+--- a/include/asm-m32r/m32700ut/m32700ut_pld.h
++++ b/include/asm-m32r/m32700ut/m32700ut_pld.h
+@@ -13,9 +13,7 @@
+  * this archive for more details.
+  */
+ 
+-#if defined(CONFIG_PLAT_M32700UT_Alpha)
+-#define PLD_PLAT_BASE		0x08c00000
+-#elif defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV)
++#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV)
+ #define PLD_PLAT_BASE		0x04c00000
+ #else
+ #error "no platform configuration"
+diff --git a/include/asm-m32r/pgalloc.h b/include/asm-m32r/pgalloc.h
+index 943ba63..e5921ad 100644
+--- a/include/asm-m32r/pgalloc.h
++++ b/include/asm-m32r/pgalloc.h
+@@ -24,7 +24,7 @@ static __inline__ pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return pgd;
+ }
+ 
+-static __inline__ void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_page((unsigned long)pgd);
+ }
+@@ -46,17 +46,17 @@ static __inline__ struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return pte;
+ }
+ 
+-static __inline__ void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-static __inline__ void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ }
+ 
+-#define __pte_free_tlb(tlb, pte)	pte_free((pte))
++#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, (pte))
+ 
+ /*
+  * allocating and freeing a pmd is trivial: the 1-entry pmd is
+@@ -65,7 +65,7 @@ static __inline__ void pte_free(struct page *pte)
+  */
+ 
+ #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
+-#define pmd_free(x)			do { } while (0)
++#define pmd_free(mm, x)			do { } while (0)
+ #define __pmd_free_tlb(tlb, x)		do { } while (0)
+ #define pgd_populate(mm, pmd, pte)	BUG()
+ 
 diff --git a/include/asm-m32r/signal.h b/include/asm-m32r/signal.h
 index 9372586..1a60706 100644
 --- a/include/asm-m32r/signal.h
@@ -804890,6 +872000,19 @@
 +#define SO_MARK			36
 +
  #endif /* _ASM_M32R_SOCKET_H */
+diff --git a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
+index f467eac..cf701c9 100644
+--- a/include/asm-m32r/unistd.h
++++ b/include/asm-m32r/unistd.h
+@@ -327,7 +327,7 @@
+ #define __NR_epoll_pwait	319
+ #define __NR_utimensat		320
+ #define __NR_signalfd		321
+-#define __NR_timerfd		322
++/* #define __NR_timerfd		322 removed */
+ #define __NR_eventfd		323
+ #define __NR_fallocate		324
+ 
 diff --git a/include/asm-m68k/bitops.h b/include/asm-m68k/bitops.h
 index 2976b5d..83d1f28 100644
 --- a/include/asm-m68k/bitops.h
@@ -804903,6 +872026,62 @@
  
  #endif /* __KERNEL__ */
  
+diff --git a/include/asm-m68k/macintosh.h b/include/asm-m68k/macintosh.h
+index 27d11da..28b0f49 100644
+--- a/include/asm-m68k/macintosh.h
++++ b/include/asm-m68k/macintosh.h
+@@ -14,8 +14,6 @@ extern void mac_init_IRQ(void);
+ extern int mac_irq_pending(unsigned int);
+ extern void mac_identify(void);
+ extern void mac_report_hardware(void);
+-extern void mac_debugging_penguin(int);
+-extern void mac_boom(int);
+ 
+ /*
+  *	Floppy driver magic hook - probably shouldnt be here
+diff --git a/include/asm-m68k/motorola_pgalloc.h b/include/asm-m68k/motorola_pgalloc.h
+index 5158412..500ec9b 100644
+--- a/include/asm-m68k/motorola_pgalloc.h
++++ b/include/asm-m68k/motorola_pgalloc.h
+@@ -22,7 +22,7 @@ static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long ad
+ 	return pte;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	cache_page(pte);
+ 	free_page((unsigned long) pte);
+@@ -47,7 +47,7 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
+ 	return page;
+ }
+ 
+-static inline void pte_free(struct page *page)
++static inline void pte_free(struct mm_struct *mm, struct page *page)
+ {
+ 	cache_page(kmap(page));
+ 	kunmap(page);
+@@ -67,7 +67,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+ 	return get_pointer_table();
+ }
+ 
+-static inline int pmd_free(pmd_t *pmd)
++static inline int pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	return free_pointer_table(pmd);
+ }
+@@ -78,9 +78,9 @@ static inline int __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+ }
+ 
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+-	pmd_free((pmd_t *)pgd);
++	pmd_free(mm, (pmd_t *)pgd);
+ }
+ 
+ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
 diff --git a/include/asm-m68k/socket.h b/include/asm-m68k/socket.h
 index 6d21b90..dbc64e9 100644
 --- a/include/asm-m68k/socket.h
@@ -804914,10 +872093,51 @@
 +#define SO_MARK			36
 +
  #endif /* _ASM_SOCKET_H */
+diff --git a/include/asm-m68k/sun3_pgalloc.h b/include/asm-m68k/sun3_pgalloc.h
+index fd82411..a5a91e7 100644
+--- a/include/asm-m68k/sun3_pgalloc.h
++++ b/include/asm-m68k/sun3_pgalloc.h
+@@ -21,12 +21,12 @@ extern const char bad_pmd_string[];
+ #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
+ 
+ 
+-static inline void pte_free_kernel(pte_t * pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+         free_page((unsigned long) pte);
+ }
+ 
+-static inline void pte_free(struct page *page)
++static inline void pte_free(struct mm_struct *mm, struct page *page)
+ {
+         __free_page(page);
+ }
+@@ -72,10 +72,10 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
+  * allocating and freeing a pmd is trivial: the 1-entry pmd is
+  * inside the pgd, so has no extra memory associated with it.
+  */
+-#define pmd_free(x)			do { } while (0)
++#define pmd_free(mm, x)			do { } while (0)
+ #define __pmd_free_tlb(tlb, x)		do { } while (0)
+ 
+-static inline void pgd_free(pgd_t * pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+         free_page((unsigned long) pgd);
+ }
 diff --git a/include/asm-m68knommu/bitops.h b/include/asm-m68knommu/bitops.h
-index f8dfb7b..f43afe1 100644
+index f8dfb7b..c142fbf 100644
 --- a/include/asm-m68knommu/bitops.h
 +++ b/include/asm-m68knommu/bitops.h
+@@ -262,7 +262,7 @@ static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned lon
+ 		 * tmp = __swab32(*(p++));
+ 		 * tmp |= ~0UL >> (32-offset);
+ 		 *
+-		 * but this would decrease preformance, so we change the
++		 * but this would decrease performance, so we change the
+ 		 * shift:
+ 		 */
+ 		tmp = *(p++);
 @@ -294,6 +294,8 @@ found_middle:
  	return result + ffz(__swab32(tmp));
  }
@@ -804940,6 +872160,128 @@
          	"movec	%%d0, %%CACR\n\t"
  		"nop\n\t"
  		: : : "d0" );
+diff --git a/include/asm-m68knommu/commproc.h b/include/asm-m68knommu/commproc.h
+index 0161ebb..36e870b 100644
+--- a/include/asm-m68knommu/commproc.h
++++ b/include/asm-m68knommu/commproc.h
+@@ -715,7 +715,7 @@ extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id);
+ #define	CICR_SCC_SCC3		((uint)0x00200000)	/* SCC3 @ SCCc */
+ #define	CICR_SCB_SCC2		((uint)0x00040000)	/* SCC2 @ SCCb */
+ #define	CICR_SCA_SCC1		((uint)0x00000000)	/* SCC1 @ SCCa */
+-#define CICR_IRL_MASK		((uint)0x0000e000)	/* Core interrrupt */
++#define CICR_IRL_MASK		((uint)0x0000e000)	/* Core interrupt */
+ #define CICR_HP_MASK		((uint)0x00001f00)	/* Hi-pri int. */
+ #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
+ #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
+diff --git a/include/asm-m68knommu/delay.h b/include/asm-m68knommu/delay.h
+index 04a20fd..55cbd62 100644
+--- a/include/asm-m68knommu/delay.h
++++ b/include/asm-m68knommu/delay.h
+@@ -68,7 +68,7 @@ static inline void _udelay(unsigned long usecs)
+ /*
+  *	Moved the udelay() function into library code, no longer inlined.
+  *	I had to change the algorithm because we are overflowing now on
+- *	the faster ColdFire parts. The code is a little biger, so it makes
++ *	the faster ColdFire parts. The code is a little bigger, so it makes
+  *	sense to library it.
+  */
+ extern void udelay(unsigned long usecs);
+diff --git a/include/asm-m68knommu/m5249sim.h b/include/asm-m68knommu/m5249sim.h
+index 399814f..366eb86 100644
+--- a/include/asm-m68knommu/m5249sim.h
++++ b/include/asm-m68knommu/m5249sim.h
+@@ -43,10 +43,10 @@
+ #define MCFSIM_CSAR1		0x8c		/* CS 1 Address reg (r/w) */
+ #define MCFSIM_CSMR1		0x90		/* CS 1 Mask reg (r/w) */
+ #define MCFSIM_CSCR1		0x96		/* CS 1 Control reg (r/w) */
+-#define MCFSIM_CSAR2		0x98		/* CS 2 Adress reg (r/w) */
++#define MCFSIM_CSAR2		0x98		/* CS 2 Address reg (r/w) */
+ #define MCFSIM_CSMR2		0x9c		/* CS 2 Mask reg (r/w) */
+ #define MCFSIM_CSCR2		0xa2		/* CS 2 Control reg (r/w) */
+-#define MCFSIM_CSAR3		0xa4		/* CS 3 Adress reg (r/w) */
++#define MCFSIM_CSAR3		0xa4		/* CS 3 Address reg (r/w) */
+ #define MCFSIM_CSMR3		0xa8		/* CS 3 Mask reg (r/w) */
+ #define MCFSIM_CSCR3		0xae		/* CS 3 Control reg (r/w) */
+ 
+diff --git a/include/asm-m68knommu/m5307sim.h b/include/asm-m68knommu/m5307sim.h
+index d3ce550..5886728 100644
+--- a/include/asm-m68knommu/m5307sim.h
++++ b/include/asm-m68knommu/m5307sim.h
+@@ -64,22 +64,22 @@
+ #define MCFSIM_CSMR7		0xda		/* CS 7 Mask reg (r/w) */
+ #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
+ #else
+-#define MCFSIM_CSAR2		0x98		/* CS 2 Adress reg (r/w) */
++#define MCFSIM_CSAR2		0x98		/* CS 2 Address reg (r/w) */
+ #define MCFSIM_CSMR2		0x9c		/* CS 2 Mask reg (r/w) */
+ #define MCFSIM_CSCR2		0xa2		/* CS 2 Control reg (r/w) */
+-#define MCFSIM_CSAR3		0xa4		/* CS 3 Adress reg (r/w) */
++#define MCFSIM_CSAR3		0xa4		/* CS 3 Address reg (r/w) */
+ #define MCFSIM_CSMR3		0xa8		/* CS 3 Mask reg (r/w) */
+ #define MCFSIM_CSCR3		0xae		/* CS 3 Control reg (r/w) */
+-#define MCFSIM_CSAR4		0xb0		/* CS 4 Adress reg (r/w) */
++#define MCFSIM_CSAR4		0xb0		/* CS 4 Address reg (r/w) */
+ #define MCFSIM_CSMR4		0xb4		/* CS 4 Mask reg (r/w) */
+ #define MCFSIM_CSCR4		0xba		/* CS 4 Control reg (r/w) */
+-#define MCFSIM_CSAR5		0xbc		/* CS 5 Adress reg (r/w) */
++#define MCFSIM_CSAR5		0xbc		/* CS 5 Address reg (r/w) */
+ #define MCFSIM_CSMR5		0xc0		/* CS 5 Mask reg (r/w) */
+ #define MCFSIM_CSCR5		0xc6		/* CS 5 Control reg (r/w) */
+-#define MCFSIM_CSAR6		0xc8		/* CS 6 Adress reg (r/w) */
++#define MCFSIM_CSAR6		0xc8		/* CS 6 Address reg (r/w) */
+ #define MCFSIM_CSMR6		0xcc		/* CS 6 Mask reg (r/w) */
+ #define MCFSIM_CSCR6		0xd2		/* CS 6 Control reg (r/w) */
+-#define MCFSIM_CSAR7		0xd4		/* CS 7 Adress reg (r/w) */
++#define MCFSIM_CSAR7		0xd4		/* CS 7 Address reg (r/w) */
+ #define MCFSIM_CSMR7		0xd8		/* CS 7 Mask reg (r/w) */
+ #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
+ #endif /* CONFIG_OLDMASK */
+diff --git a/include/asm-m68knommu/m5407sim.h b/include/asm-m68knommu/m5407sim.h
+index 75dcdac..cc22c4a 100644
+--- a/include/asm-m68knommu/m5407sim.h
++++ b/include/asm-m68knommu/m5407sim.h
+@@ -48,22 +48,22 @@
+ #define MCFSIM_CSMR1		0x90		/* CS 1 Mask reg (r/w) */
+ #define MCFSIM_CSCR1		0x96		/* CS 1 Control reg (r/w) */
+ 
+-#define MCFSIM_CSAR2		0x98		/* CS 2 Adress reg (r/w) */
++#define MCFSIM_CSAR2		0x98		/* CS 2 Address reg (r/w) */
+ #define MCFSIM_CSMR2		0x9c		/* CS 2 Mask reg (r/w) */
+ #define MCFSIM_CSCR2		0xa2		/* CS 2 Control reg (r/w) */
+-#define MCFSIM_CSAR3		0xa4		/* CS 3 Adress reg (r/w) */
++#define MCFSIM_CSAR3		0xa4		/* CS 3 Address reg (r/w) */
+ #define MCFSIM_CSMR3		0xa8		/* CS 3 Mask reg (r/w) */
+ #define MCFSIM_CSCR3		0xae		/* CS 3 Control reg (r/w) */
+-#define MCFSIM_CSAR4		0xb0		/* CS 4 Adress reg (r/w) */
++#define MCFSIM_CSAR4		0xb0		/* CS 4 Address reg (r/w) */
+ #define MCFSIM_CSMR4		0xb4		/* CS 4 Mask reg (r/w) */
+ #define MCFSIM_CSCR4		0xba		/* CS 4 Control reg (r/w) */
+-#define MCFSIM_CSAR5		0xbc		/* CS 5 Adress reg (r/w) */
++#define MCFSIM_CSAR5		0xbc		/* CS 5 Address reg (r/w) */
+ #define MCFSIM_CSMR5		0xc0		/* CS 5 Mask reg (r/w) */
+ #define MCFSIM_CSCR5		0xc6		/* CS 5 Control reg (r/w) */
+-#define MCFSIM_CSAR6		0xc8		/* CS 6 Adress reg (r/w) */
++#define MCFSIM_CSAR6		0xc8		/* CS 6 Address reg (r/w) */
+ #define MCFSIM_CSMR6		0xcc		/* CS 6 Mask reg (r/w) */
+ #define MCFSIM_CSCR6		0xd2		/* CS 6 Control reg (r/w) */
+-#define MCFSIM_CSAR7		0xd4		/* CS 7 Adress reg (r/w) */
++#define MCFSIM_CSAR7		0xd4		/* CS 7 Address reg (r/w) */
+ #define MCFSIM_CSMR7		0xd8		/* CS 7 Mask reg (r/w) */
+ #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
+ 
+diff --git a/include/asm-m68knommu/m68360_regs.h b/include/asm-m68knommu/m68360_regs.h
+index a3f8cc8..d57217c 100644
+--- a/include/asm-m68knommu/m68360_regs.h
++++ b/include/asm-m68knommu/m68360_regs.h
+@@ -138,7 +138,7 @@
+ #define CICR_SCC_SCC3           ((uint)0x00200000)      /* SCC3 @ SCCc */
+ #define CICR_SCD_SCC4           ((uint)0x00c00000)      /* SCC4 @ SCCd */
+ 
+-#define CICR_IRL_MASK           ((uint)0x0000e000)      /* Core interrrupt */
++#define CICR_IRL_MASK           ((uint)0x0000e000)      /* Core interrupt */
+ #define CICR_HP_MASK            ((uint)0x00001f00)      /* Hi-pri int. */
+ #define CICR_VBA_MASK           ((uint)0x000000e0)      /* Vector Base Address */
+ #define CICR_SPS                ((uint)0x00000001)      /* SCC Spread */
 diff --git a/include/asm-m68knommu/mcfcache.h b/include/asm-m68knommu/mcfcache.h
 index 7b61a8a..c042634 100644
 --- a/include/asm-m68knommu/mcfcache.h
@@ -804953,8 +872295,90 @@
  	movec	%d0, %ACR1
  	movel	#0x80000200, %d0	/* Setup cache mask */
  	movec	%d0, %CACR		/* Enable cache */
+diff --git a/include/asm-m68knommu/mcfne.h b/include/asm-m68knommu/mcfne.h
+index c920ccd..431f63a 100644
+--- a/include/asm-m68knommu/mcfne.h
++++ b/include/asm-m68knommu/mcfne.h
+@@ -60,17 +60,6 @@
+ #define	NE2000_BYTE		volatile unsigned char
+ #endif
+ 
+-#if defined(CONFIG_CFV240)
+-#define NE2000_ADDR             0x40010000
+-#define NE2000_ADDR1            0x40010001
+-#define NE2000_ODDOFFSET        0x00000000
+-#define NE2000_IRQ              1
+-#define NE2000_IRQ_VECTOR       0x19
+-#define NE2000_IRQ_PRIORITY     2
+-#define NE2000_IRQ_LEVEL        1
+-#define	NE2000_BYTE		volatile unsigned char
+-#endif
+-
+ #if defined(CONFIG_M5307C3)
+ #define NE2000_ADDR		0x40000300
+ #define NE2000_ODDOFFSET	0x00010000
+@@ -173,13 +162,8 @@ void ne2000_outsw(unsigned int addr, void *vbuf, unsigned long len);
+  *	On most NE2000 implementations on ColdFire boards the chip is
+  *	mapped in kinda funny, due to its ISA heritage.
+  */
+-#ifdef CONFIG_CFV240
+-#define NE2000_PTR(addr)	(NE2000_ADDR + ((addr & 0x3f) << 1) + 1)
+-#define NE2000_DATA_PTR(addr)	(NE2000_ADDR + ((addr & 0x3f) << 1))
+-#else
+ #define	NE2000_PTR(addr)	((addr&0x1)?(NE2000_ODDOFFSET+addr-1):(addr))
+ #define	NE2000_DATA_PTR(addr)	(addr)
+-#endif
+ 
+ 
+ void ne2000_outb(unsigned int val, unsigned int addr)
+@@ -285,17 +269,6 @@ void ne2000_irqsetup(int irq)
+ }
+ #endif
+ 
+-#if defined(CONFIG_CFV240)
+-void ne2000_irqsetup(int irq)
+-{
+-	volatile unsigned char  *icrp;
+-
+-	icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_ICR1);
+-	*icrp = MCFSIM_ICR_LEVEL1 | MCFSIM_ICR_PRI2 | MCFSIM_ICR_AUTOVEC;
+-	mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT1);
+-}
+-#endif
+-
+ #if defined(CONFIG_M5206e) && defined(CONFIG_NETtel)
+ void ne2000_irqsetup(int irq)
+ {
+diff --git a/include/asm-m68knommu/mcfsim.h b/include/asm-m68knommu/mcfsim.h
+index 1074ae7..da3f2ce 100644
+--- a/include/asm-m68knommu/mcfsim.h
++++ b/include/asm-m68knommu/mcfsim.h
+@@ -17,9 +17,7 @@
+  *	Include 5204, 5206/e, 5235, 5249, 5270/5271, 5272, 5280/5282,
+  *	5307 or 5407 specific addresses.
+  */
+-#if defined(CONFIG_M5204)
+-#include <asm/m5204sim.h>
+-#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e)
++#if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
+ #include <asm/m5206sim.h>
+ #elif defined(CONFIG_M520x)
+ #include <asm/m520xsim.h>
+diff --git a/include/asm-m68knommu/mcftimer.h b/include/asm-m68knommu/mcftimer.h
+index 6f4d796..0f90f6d 100644
+--- a/include/asm-m68knommu/mcftimer.h
++++ b/include/asm-m68knommu/mcftimer.h
+@@ -16,7 +16,7 @@
+ /*
+  *	Get address specific defines for this ColdFire member.
+  */
+-#if defined(CONFIG_M5204) || defined(CONFIG_M5206) || defined(CONFIG_M5206e)
++#if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
+ #define	MCFTIMER_BASE1		0x100		/* Base address of TIMER1 */
+ #define	MCFTIMER_BASE2		0x120		/* Base address of TIMER2 */
+ #elif defined(CONFIG_M5272)
 diff --git a/include/asm-m68knommu/mcfuart.h b/include/asm-m68knommu/mcfuart.h
-index 873d080..1319a81 100644
+index 873d080..ef22938 100644
 --- a/include/asm-m68knommu/mcfuart.h
 +++ b/include/asm-m68knommu/mcfuart.h
 @@ -12,7 +12,6 @@
@@ -804965,6 +872389,15 @@
  /*
   *	Define the base address of the UARTS within the MBAR address
   *	space.
+@@ -20,7 +19,7 @@
+ #if defined(CONFIG_M5272)
+ #define	MCFUART_BASE1		0x100		/* Base address of UART1 */
+ #define	MCFUART_BASE2		0x140		/* Base address of UART2 */
+-#elif defined(CONFIG_M5204) || defined(CONFIG_M5206) || defined(CONFIG_M5206e)
++#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e)
+ #if defined(CONFIG_NETtel)
+ #define	MCFUART_BASE1		0x180		/* Base address of UART1 */
+ #define	MCFUART_BASE2		0x140		/* Base address of UART2 */
 @@ -33,7 +32,7 @@
  #define MCFUART_BASE2		0x240           /* Base address of UART2 */
  #define MCFUART_BASE3		0x280           /* Base address of UART3 */
@@ -804974,6 +872407,43 @@
  #define MCFUART_BASE1		0x200           /* Base address of UART1 */
  #define MCFUART_BASE2		0x1c0           /* Base address of UART2 */
  #else
+@@ -72,7 +71,7 @@ struct mcf_platform_uart {
+ #define	MCFUART_UTB		0x0c		/* Transmit Buffer (w) */
+ #define	MCFUART_UIPCR		0x10		/* Input Port Change (r) */
+ #define	MCFUART_UACR		0x10		/* Auxiliary Control (w) */
+-#define	MCFUART_UISR		0x14		/* Interrup Status (r) */
++#define	MCFUART_UISR		0x14		/* Interrupt Status (r) */
+ #define	MCFUART_UIMR		0x14		/* Interrupt Mask (w) */
+ #define	MCFUART_UBG1		0x18		/* Baud Rate MSB (r/w) */
+ #define	MCFUART_UBG2		0x1c		/* Baud Rate LSB (r/w) */
+diff --git a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
+index 15b4c7d..ee2dc07 100644
+--- a/include/asm-m68knommu/system.h
++++ b/include/asm-m68knommu/system.h
+@@ -207,23 +207,6 @@ cmpxchg(volatile int *p, int old, int new)
+ }
+ 
+ 
+-#ifdef CONFIG_M68332
+-#define HARD_RESET_NOW() ({		\
+-        local_irq_disable();		\
+-        asm("				\
+-	movew   #0x0000, 0xfffa6a;	\
+-        reset;				\
+-        /*movew #0x1557, 0xfffa44;*/	\
+-        /*movew #0x0155, 0xfffa46;*/	\
+-        moveal #0, %a0;			\
+-        movec %a0, %vbr;		\
+-        moveal 0, %sp;			\
+-        moveal 4, %a0;			\
+-        jmp (%a0);			\
+-        ");				\
+-})
+-#endif
+-
+ #if defined( CONFIG_M68328 ) || defined( CONFIG_M68EZ328 ) || \
+ 	defined (CONFIG_M68360) || defined( CONFIG_M68VZ328 )
+ #define HARD_RESET_NOW() ({		\
 diff --git a/include/asm-mips/addrspace.h b/include/asm-mips/addrspace.h
 index 0bb7a93..569f80a 100644
 --- a/include/asm-mips/addrspace.h
@@ -805213,6 +872683,19 @@
 +}
 +
  #endif /* _ASM_BUGS_H */
+diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
+index 568c76c..ac5d541 100644
+--- a/include/asm-mips/compat.h
++++ b/include/asm-mips/compat.h
+@@ -128,7 +128,7 @@ typedef u32		compat_sigset_word;
+  * A pointer passed in from user mode. This should not
+  * be used for syscall parameters, just declare them
+  * as pointers because the syscall entry code will have
+- * appropriately comverted them already.
++ * appropriately converted them already.
+  */
+ typedef u32		compat_uptr_t;
+ 
 diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
 index ed5c02c..0c5a358 100644
 --- a/include/asm-mips/cpu-info.h
@@ -805563,6 +873046,19 @@
 -# define COBALT_KEY_MASK	0xfe
 -
  #endif /* __ASM_COBALT_H */
+diff --git a/include/asm-mips/mach-excite/excite_fpga.h b/include/asm-mips/mach-excite/excite_fpga.h
+index 38fcda7..0a1ef69 100644
+--- a/include/asm-mips/mach-excite/excite_fpga.h
++++ b/include/asm-mips/mach-excite/excite_fpga.h
+@@ -3,7 +3,7 @@
+ 
+ 
+ /**
+- * Adress alignment of the individual FPGA bytes.
++ * Address alignment of the individual FPGA bytes.
+  * The address arrangement of the individual bytes of the FPGA is two
+  * byte aligned at the embedded MK2 platform.
+  */
 diff --git a/include/asm-mips/mach-ip28/cpu-feature-overrides.h b/include/asm-mips/mach-ip28/cpu-feature-overrides.h
 new file mode 100644
 index 0000000..9a53b32
@@ -805757,6 +873253,19 @@
 -#define MIPS34K_MISSED_ITLB_WAR		0
 -
 -#endif /* __ASM_MIPS_MACH_QEMU_WAR_H */
+diff --git a/include/asm-mips/mach-wrppmc/mach-gt64120.h b/include/asm-mips/mach-wrppmc/mach-gt64120.h
+index 00d8bf6..83746b8 100644
+--- a/include/asm-mips/mach-wrppmc/mach-gt64120.h
++++ b/include/asm-mips/mach-wrppmc/mach-gt64120.h
+@@ -45,7 +45,7 @@
+ #define GT_PCI_IO_SIZE	0x02000000UL
+ 
+ /*
+- * PCI interrupts will come in on either the INTA or INTD interrups lines,
++ * PCI interrupts will come in on either the INTA or INTD interrupt lines,
+  * which are mapped to the #2 and #5 interrupt pins of the MIPS.  On our
+  * boards, they all either come in on IntD or they all come in on IntA, they
+  * aren't mixed. There can be numerous PCI interrupts, so we keep a list of the
 diff --git a/include/asm-mips/mips-boards/generic.h b/include/asm-mips/mips-boards/generic.h
 index d589774..1c39d33 100644
 --- a/include/asm-mips/mips-boards/generic.h
@@ -805789,6 +873298,58 @@
 +extern char *prom_getenv(char *);
 +
  #endif /* __ASM_MIPS_PROM_H */
+diff --git a/include/asm-mips/pgalloc.h b/include/asm-mips/pgalloc.h
+index 81b7212..c4efece 100644
+--- a/include/asm-mips/pgalloc.h
++++ b/include/asm-mips/pgalloc.h
+@@ -58,7 +58,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return ret;
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_pages((unsigned long)pgd, PGD_ORDER);
+ }
+@@ -85,12 +85,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return pte;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_pages((unsigned long)pte, PTE_ORDER);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_pages(pte, PTE_ORDER);
+ }
+@@ -103,7 +103,7 @@ static inline void pte_free(struct page *pte)
+  * allocating and freeing a pmd is trivial: the 1-entry pmd is
+  * inside the pgd, so has no extra memory associated with it.
+  */
+-#define pmd_free(x)			do { } while (0)
++#define pmd_free(mm, x)			do { } while (0)
+ #define __pmd_free_tlb(tlb, x)		do { } while (0)
+ 
+ #endif
+@@ -120,12 +120,12 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+ 	return pmd;
+ }
+ 
+-static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	free_pages((unsigned long)pmd, PMD_ORDER);
+ }
+ 
+-#define __pmd_free_tlb(tlb, x)	pmd_free(x)
++#define __pmd_free_tlb(tlb, x)	pmd_free((tlb)->mm, x)
+ 
+ #endif
+ 
 diff --git a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h b/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
 index 0b56f55..603eb73 100644
 --- a/include/asm-mips/pmc-sierra/msp71xx/msp_regs.h
@@ -805805,6 +873366,19 @@
  #define MSP_UART_REG_LEN	0x20
  
  /*
+diff --git a/include/asm-mips/processor.h b/include/asm-mips/processor.h
+index 83bc945..36f42de 100644
+--- a/include/asm-mips/processor.h
++++ b/include/asm-mips/processor.h
+@@ -65,6 +65,8 @@ extern unsigned int vced_count, vcei_count;
+ #define TASK_UNMAPPED_BASE						\
+ 	(test_thread_flag(TIF_32BIT_ADDR) ?				\
+ 		PAGE_ALIGN(TASK_SIZE32 / 3) : PAGE_ALIGN(TASK_SIZE / 3))
++#define TASK_SIZE_OF(tsk)						\
++	(test_tsk_thread_flag(tsk, TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE)
+ #endif
+ 
+ #define NUM_FPU_REGS	32
 diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
 index 2b8466f..4c140db 100644
 --- a/include/asm-mips/r4kcache.h
@@ -805838,6 +873412,19 @@
  	u32 _unused2;
  	u8 _read[3];
  	volatile u8 read;
+diff --git a/include/asm-mips/sgi/ip22.h b/include/asm-mips/sgi/ip22.h
+index f4981c4..c0501f9 100644
+--- a/include/asm-mips/sgi/ip22.h
++++ b/include/asm-mips/sgi/ip22.h
+@@ -15,7 +15,7 @@
+ /*
+  * These are the virtual IRQ numbers, we divide all IRQ's into
+  * 'spaces', the 'space' determines where and how to enable/disable
+- * that particular IRQ on an SGI machine. HPC DMA and MC DMA interrups
++ * that particular IRQ on an SGI machine. HPC DMA and MC DMA interrupts
+  * are not supported this way. Driver is supposed to allocate HPC/MC
+  * interrupt as shareable and then look to proper status bit (see
+  * HAL2 driver). This will prevent many complications, trust me ;-)
 diff --git a/include/asm-mips/sibyte/board.h b/include/asm-mips/sibyte/board.h
 index da198a1..25372ae 100644
 --- a/include/asm-mips/sibyte/board.h
@@ -806059,6 +873646,19 @@
 -#endif /* CONFIG_SMP */
 -
  #endif /* __ASM_SMP_H */
+diff --git a/include/asm-mips/sn/sn0/hubio.h b/include/asm-mips/sn/sn0/hubio.h
+index ef91b33..0187895 100644
+--- a/include/asm-mips/sn/sn0/hubio.h
++++ b/include/asm-mips/sn/sn0/hubio.h
+@@ -338,7 +338,7 @@ typedef union io_perf_cnt {
+ #define IIO_IFDR	0x400398	/* IOQ FIFO Depth */
+ #define IIO_IIAP	0x4003a0	/* IIQ Arbitration Parameters */
+ #define IIO_IMMR	IIO_IIAP
+-#define IIO_ICMR	0x4003a8	/* CRB Managment Register */
++#define IIO_ICMR	0x4003a8	/* CRB Management Register */
+ #define IIO_ICCR	0x4003b0	/* CRB Control Register */
+ #define IIO_ICTO	0x4003b8	/* CRB Time Out Register */
+ #define IIO_ICTP	0x4003c0	/* CRB Time Out Prescalar */
 diff --git a/include/asm-mips/sni.h b/include/asm-mips/sni.h
 index af08145..e716447 100644
 --- a/include/asm-mips/sni.h
@@ -806531,6 +874131,105 @@
  #define flush_agp_cache()		mb()
  
  /* Convert a physical address to an address suitable for the GART. */
+diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
+index 5a85d1b..7f32611 100644
+--- a/include/asm-parisc/compat.h
++++ b/include/asm-parisc/compat.h
+@@ -132,7 +132,7 @@ typedef u32		compat_sigset_word;
+  * A pointer passed in from user mode. This should not
+  * be used for syscall parameters, just declare them
+  * as pointers because the syscall entry code will have
+- * appropriately comverted them already.
++ * appropriately converted them already.
+  */
+ typedef	u32		compat_uptr_t;
+ 
+diff --git a/include/asm-parisc/elf.h b/include/asm-parisc/elf.h
+index f628ac7..8e7946a 100644
+--- a/include/asm-parisc/elf.h
++++ b/include/asm-parisc/elf.h
+@@ -28,7 +28,7 @@
+ #define EFA_PARISC_1_1		    0x0210 /* PA-RISC 1.1 big-endian.  */
+ #define EFA_PARISC_2_0		    0x0214 /* PA-RISC 2.0 big-endian.  */
+ 
+-/* Additional section indeces.  */
++/* Additional section indices.  */
+ 
+ #define SHN_PARISC_ANSI_COMMON	0xff00	   /* Section for tenatively declared
+ 					      symbols in ANSI C.  */
+diff --git a/include/asm-parisc/linkage.h b/include/asm-parisc/linkage.h
+index ad8cd0d..0b19a72 100644
+--- a/include/asm-parisc/linkage.h
++++ b/include/asm-parisc/linkage.h
+@@ -8,7 +8,7 @@
+ 
+ /*
+  * In parisc assembly a semicolon marks a comment while a
+- * exclamation mark is used to seperate independent lines.
++ * exclamation mark is used to separate independent lines.
+  */
+ #ifdef __ASSEMBLY__
+ 
+diff --git a/include/asm-parisc/pgalloc.h b/include/asm-parisc/pgalloc.h
+index 1af1a41..aab66f1 100644
+--- a/include/asm-parisc/pgalloc.h
++++ b/include/asm-parisc/pgalloc.h
+@@ -43,7 +43,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return actual_pgd;
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ #ifdef CONFIG_64BIT
+ 	pgd -= PTRS_PER_PGD;
+@@ -70,7 +70,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+ 	return pmd;
+ }
+ 
+-static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ #ifdef CONFIG_64BIT
+ 	if(pmd_flag(*pmd) & PxD_FLAG_ATTACHED)
+@@ -91,7 +91,7 @@ static inline void pmd_free(pmd_t *pmd)
+  */
+ 
+ #define pmd_alloc_one(mm, addr)		({ BUG(); ((pmd_t *)2); })
+-#define pmd_free(x)			do { } while (0)
++#define pmd_free(mm, x)			do { } while (0)
+ #define pgd_populate(mm, pmd, pte)	BUG()
+ 
+ #endif
+@@ -130,12 +130,12 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
+ 	return pte;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-#define pte_free(page)	pte_free_kernel(page_address(page))
++#define pte_free(mm, page) pte_free_kernel(page_address(page))
+ 
+ #define check_pgt_cache()	do { } while (0)
+ 
+diff --git a/include/asm-parisc/processor.h b/include/asm-parisc/processor.h
+index 6b294fb..3bb06e8 100644
+--- a/include/asm-parisc/processor.h
++++ b/include/asm-parisc/processor.h
+@@ -32,7 +32,8 @@
+ #endif
+ #define current_text_addr() ({ void *pc; current_ia(pc); pc; })
+ 
+-#define TASK_SIZE               (current->thread.task_size)
++#define TASK_SIZE_OF(tsk)       ((tsk)->thread.task_size)
++#define TASK_SIZE	        TASK_SIZE_OF(current)
+ #define TASK_UNMAPPED_BASE      (current->thread.map_base)
+ 
+ #define DEFAULT_TASK_SIZE32	(0xFFF00000UL)
 diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h
 index 99e868f..69a7a0d 100644
 --- a/include/asm-parisc/socket.h
@@ -806542,6 +874241,30 @@
 +#define SO_MARK			0x401f
 +
  #endif /* _ASM_SOCKET_H */
+diff --git a/include/asm-parisc/tlb.h b/include/asm-parisc/tlb.h
+index 33107a2..383b1db 100644
+--- a/include/asm-parisc/tlb.h
++++ b/include/asm-parisc/tlb.h
+@@ -21,7 +21,7 @@ do {	if (!(tlb)->fullmm)	\
+ 
+ #include <asm-generic/tlb.h>
+ 
+-#define __pmd_free_tlb(tlb, pmd)	pmd_free(pmd)
+-#define __pte_free_tlb(tlb, pte)	pte_free(pte)
++#define __pmd_free_tlb(tlb, pmd)	pmd_free((tlb)->mm, pmd)
++#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+ 
+ #endif
+diff --git a/include/asm-parisc/vga.h b/include/asm-parisc/vga.h
+index 154a84c..171399a 100644
+--- a/include/asm-parisc/vga.h
++++ b/include/asm-parisc/vga.h
+@@ -3,4 +3,4 @@
+ 
+ /* nothing */
+ 
+-#endif __ASM_PARISC_VGA_H__
++#endif /* __ASM_PARISC_VGA_H__ */
 diff --git a/include/asm-powerpc/8xx_immap.h b/include/asm-powerpc/8xx_immap.h
 index 1311cef..4b0e152 100644
 --- a/include/asm-powerpc/8xx_immap.h
@@ -807347,6 +875070,19 @@
 -int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode);
 -
 -#endif /* __CPM_8XX__ */
+diff --git a/include/asm-powerpc/compat.h b/include/asm-powerpc/compat.h
+index 64ab1dd..d811a8c 100644
+--- a/include/asm-powerpc/compat.h
++++ b/include/asm-powerpc/compat.h
+@@ -119,7 +119,7 @@ typedef u32		compat_sigset_word;
+  * A pointer passed in from user mode. This should not
+  * be used for syscall parameters, just declare them
+  * as pointers because the syscall entry code will have
+- * appropriately comverted them already.
++ * appropriately converted them already.
+  */
+ typedef	u32		compat_uptr_t;
+ 
 diff --git a/include/asm-powerpc/cpm.h b/include/asm-powerpc/cpm.h
 index 48df9f3..77e39da 100644
 --- a/include/asm-powerpc/cpm.h
@@ -808642,7 +876378,7 @@
  #error CONFIG_PPC_INDIRECT_IO is not yet supported on 32 bits
  #endif
 diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
-index 4a82fdc..7a3cef7 100644
+index 4a82fdc..852e15f 100644
 --- a/include/asm-powerpc/iommu.h
 +++ b/include/asm-powerpc/iommu.h
 @@ -69,10 +69,9 @@ struct iommu_table {
@@ -808657,6 +876393,32 @@
  
  /* Initializes an iommu_table based in values set in the passed-in
   * structure
+@@ -80,19 +79,19 @@ extern void iommu_free_table(struct device_node *dn);
+ extern struct iommu_table *iommu_init_table(struct iommu_table * tbl,
+ 					    int nid);
+ 
+-extern int iommu_map_sg(struct iommu_table *tbl, struct scatterlist *sglist,
++extern int iommu_map_sg(struct device *dev, struct scatterlist *sglist,
+ 			int nelems, unsigned long mask,
+ 			enum dma_data_direction direction);
+ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
+ 			   int nelems, enum dma_data_direction direction);
+ 
+-extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+-				  dma_addr_t *dma_handle, unsigned long mask,
+-				  gfp_t flag, int node);
++extern void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl,
++				  size_t size, dma_addr_t *dma_handle,
++				  unsigned long mask, gfp_t flag, int node);
+ extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
+ 				void *vaddr, dma_addr_t dma_handle);
+-extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
+-				   size_t size, unsigned long mask,
++extern dma_addr_t iommu_map_single(struct device *dev, struct iommu_table *tbl,
++				   void *vaddr, size_t size, unsigned long mask,
+ 				   enum dma_data_direction direction);
+ extern void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
+ 			       size_t size, enum dma_data_direction direction);
 diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h
 index edec79d..8ff08be 100644
 --- a/include/asm-powerpc/ipic.h
@@ -809031,6 +876793,29 @@
 +
  #endif /* __KERNEL__ */
  #endif /* _ASM_POWERPC_MACHDEP_H */
+diff --git a/include/asm-powerpc/mediabay.h b/include/asm-powerpc/mediabay.h
+index 9daa325..de83fe1 100644
+--- a/include/asm-powerpc/mediabay.h
++++ b/include/asm-powerpc/mediabay.h
+@@ -18,14 +18,14 @@
+ #define MB_NO		7	/* media bay contains nothing */
+ 
+ int check_media_bay(struct device_node *which_bay, int what);
+-int check_media_bay_by_base(unsigned long base, int what);
+ 
+ /* Number of bays in the machine or 0 */
+ extern int media_bay_count;
+ 
+-/* called by pmac-ide.c to register IDE controller for media bay */
+-extern int media_bay_set_ide_infos(struct device_node* which_bay,
+-			unsigned long base, int irq, int index);
++int check_media_bay_by_base(unsigned long base, int what);
++/* called by IDE PMAC host driver to register IDE controller for media bay */
++int media_bay_set_ide_infos(struct device_node *which_bay, unsigned long base,
++			    int irq, int index);
+ 
+ #endif /* __KERNEL__ */
+ #endif /* _PPC_MEDIABAY_H */
 diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h
 index 82328de..2864fa3 100644
 --- a/include/asm-powerpc/mmu-hash64.h
@@ -809236,7 +877021,7 @@
  /* Set the EPIC clock ratio */
  void mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio);
 diff --git a/include/asm-powerpc/nvram.h b/include/asm-powerpc/nvram.h
-index 9877982..4e7059c 100644
+index 9877982..efde5ac 100644
 --- a/include/asm-powerpc/nvram.h
 +++ b/include/asm-powerpc/nvram.h
 @@ -10,6 +10,8 @@
@@ -809248,7 +877033,17 @@
  #define NVRW_CNT 0x20
  #define NVRAM_HEADER_LEN 16 /* sizeof(struct nvram_header) */
  #define NVRAM_BLOCK_LEN 16
-@@ -71,7 +73,16 @@ extern int nvram_clear_error_log(void);
+@@ -56,6 +58,9 @@ struct nvram_header {
+ };
+ 
+ #ifdef __KERNEL__
++
++#include <linux/list.h>
++
+ struct nvram_partition {
+ 	struct list_head partition;
+ 	struct nvram_header header;
+@@ -71,7 +76,16 @@ extern int nvram_clear_error_log(void);
  extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
  
  extern int pSeries_nvram_init(void);
@@ -810236,8 +878031,43 @@
 -#endif
  
  #endif /* _ASM_POWERPC_PERCPU_H_ */
+diff --git a/include/asm-powerpc/pgalloc-32.h b/include/asm-powerpc/pgalloc-32.h
+index e130743..c162a4c 100644
+--- a/include/asm-powerpc/pgalloc-32.h
++++ b/include/asm-powerpc/pgalloc-32.h
+@@ -6,14 +6,14 @@
+ extern void __bad_pte(pmd_t *pmd);
+ 
+ extern pgd_t *pgd_alloc(struct mm_struct *mm);
+-extern void pgd_free(pgd_t *pgd);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+ 
+ /*
+  * We don't have any real pmd's, and this code never triggers because
+  * the pgd will always be present..
+  */
+ /* #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); }) */
+-#define pmd_free(x)                     do { } while (0)
++#define pmd_free(mm, x) 		do { } while (0)
+ #define __pmd_free_tlb(tlb,x)		do { } while (0)
+ /* #define pgd_populate(mm, pmd, pte)      BUG() */
+ 
+@@ -31,10 +31,10 @@ extern void pgd_free(pgd_t *pgd);
+ 
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+ extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+-extern void pte_free_kernel(pte_t *pte);
+-extern void pte_free(struct page *pte);
++extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
++extern void pte_free(struct mm_struct *mm, struct page *pte);
+ 
+-#define __pte_free_tlb(tlb, pte)	pte_free((pte))
++#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, (pte))
+ 
+ #define check_pgt_cache()	do { } while (0)
+ 
 diff --git a/include/asm-powerpc/pgalloc-64.h b/include/asm-powerpc/pgalloc-64.h
-index 94d0294..43214c8 100644
+index 94d0294..5afae85 100644
 --- a/include/asm-powerpc/pgalloc-64.h
 +++ b/include/asm-powerpc/pgalloc-64.h
 @@ -12,6 +12,10 @@
@@ -810251,14 +878081,50 @@
  extern struct kmem_cache *pgtable_cache[];
  
  #define PGD_CACHE_NUM		0
-@@ -27,6 +31,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+@@ -25,8 +29,9 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return kmem_cache_alloc(pgtable_cache[PGD_CACHE_NUM], GFP_KERNEL);
+ }
  
- static inline void pgd_free(pgd_t *pgd)
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
  {
 +	subpage_prot_free(pgd);
  	kmem_cache_free(pgtable_cache[PGD_CACHE_NUM], pgd);
  }
  
+@@ -40,7 +45,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+ 				GFP_KERNEL|__GFP_REPEAT);
+ }
+ 
+-static inline void pud_free(pud_t *pud)
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+ {
+ 	kmem_cache_free(pgtable_cache[PUD_CACHE_NUM], pud);
+ }
+@@ -76,7 +81,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+ 				GFP_KERNEL|__GFP_REPEAT);
+ }
+ 
+-static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	kmem_cache_free(pgtable_cache[PMD_CACHE_NUM], pmd);
+ }
+@@ -94,12 +99,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return pte ? virt_to_page(pte) : NULL;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-static inline void pte_free(struct page *ptepage)
++static inline void pte_free(struct mm_struct *mm, struct page *ptepage)
+ {
+ 	__free_page(ptepage);
+ }
 diff --git a/include/asm-powerpc/pgtable-64k.h b/include/asm-powerpc/pgtable-64k.h
 index bd54b77..1cbd6b3 100644
 --- a/include/asm-powerpc/pgtable-64k.h
@@ -810336,6 +878202,21 @@
  extern unsigned long pci_probe_only;
  
  /* ---- EEH internal-use-only related routines ---- */
+diff --git a/include/asm-powerpc/processor.h b/include/asm-powerpc/processor.h
+index dba7c94..1f4765d 100644
+--- a/include/asm-powerpc/processor.h
++++ b/include/asm-powerpc/processor.h
+@@ -99,8 +99,9 @@ extern struct task_struct *last_task_used_spe;
+  */
+ #define TASK_SIZE_USER32 (0x0000000100000000UL - (1*PAGE_SIZE))
+ 
+-#define TASK_SIZE (test_thread_flag(TIF_32BIT) ? \
++#define TASK_SIZE_OF(tsk) (test_tsk_thread_flag(tsk, TIF_32BIT) ? \
+ 		TASK_SIZE_USER32 : TASK_SIZE_USER64)
++#define TASK_SIZE	  TASK_SIZE_OF(current)
+ 
+ /* This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
 diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
 index 925e2d3..78b7b0d 100644
 --- a/include/asm-powerpc/prom.h
@@ -811220,10 +879101,15 @@
   * The declarations folowing are put here for convenience
   * and only intended to be used by the platform setup code.
 diff --git a/include/asm-powerpc/systbl.h b/include/asm-powerpc/systbl.h
-index 11d5383..0c8b0d6 100644
+index 11d5383..e996521 100644
 --- a/include/asm-powerpc/systbl.h
 +++ b/include/asm-powerpc/systbl.h
-@@ -313,3 +313,4 @@ COMPAT_SYS_SPU(timerfd)
+@@ -309,7 +309,8 @@ SYSCALL_SPU(getcpu)
+ COMPAT_SYS(epoll_pwait)
+ COMPAT_SYS_SPU(utimensat)
+ COMPAT_SYS_SPU(signalfd)
+-COMPAT_SYS_SPU(timerfd)
++SYSCALL(ni_syscall)
  SYSCALL_SPU(eventfd)
  COMPAT_SYS_SPU(sync_file_range2)
  COMPAT_SYS(fallocate)
@@ -813178,6 +881064,41 @@
 -#endif /* CONFIG_85xx */
 -#endif /* __ASM_MPC85xx_H__ */
 -#endif /* __KERNEL__ */
+diff --git a/include/asm-ppc/pgalloc.h b/include/asm-ppc/pgalloc.h
+index 44d88a9..7c39a95 100644
+--- a/include/asm-ppc/pgalloc.h
++++ b/include/asm-ppc/pgalloc.h
+@@ -7,14 +7,14 @@
+ extern void __bad_pte(pmd_t *pmd);
+ 
+ extern pgd_t *pgd_alloc(struct mm_struct *mm);
+-extern void pgd_free(pgd_t *pgd);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+ 
+ /*
+  * We don't have any real pmd's, and this code never triggers because
+  * the pgd will always be present..
+  */
+ #define pmd_alloc_one(mm,address)       ({ BUG(); ((pmd_t *)2); })
+-#define pmd_free(x)                     do { } while (0)
++#define pmd_free(mm, x) 		do { } while (0)
+ #define __pmd_free_tlb(tlb,x)		do { } while (0)
+ #define pgd_populate(mm, pmd, pte)      BUG()
+ 
+@@ -32,10 +32,10 @@ extern void pgd_free(pgd_t *pgd);
+ 
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr);
+ extern struct page *pte_alloc_one(struct mm_struct *mm, unsigned long addr);
+-extern void pte_free_kernel(pte_t *pte);
+-extern void pte_free(struct page *pte);
++extern void pte_free_kernel(struct mm_struct *mm, pte_t *pte);
++extern void pte_free(struct mm_struct *mm, struct page *pte);
+ 
+-#define __pte_free_tlb(tlb, pte)	pte_free((pte))
++#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, (pte))
+ 
+ #define check_pgt_cache()	do { } while (0)
+ 
 diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
 index 063ad91..69347bd 100644
 --- a/include/asm-ppc/pgtable.h
@@ -813383,18 +881304,723 @@
 +
 +#endif /* _ASM_S390_AIRQ_H */
 diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h
-index 34d9a63..dba6fec 100644
+index 34d9a63..882db05 100644
 --- a/include/asm-s390/bitops.h
 +++ b/include/asm-s390/bitops.h
-@@ -772,6 +772,8 @@ static inline int sched_find_first_bit(unsigned long *b)
- 	test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
+@@ -440,242 +440,256 @@ __constant_test_bit(unsigned long nr, const volatile unsigned long *addr) {
+  __test_bit((nr),(addr)) )
+ 
+ /*
+- * ffz = Find First Zero in word. Undefined if no zero exists,
+- * so code should check against ~0UL first..
++ * Optimized find bit helper functions.
+  */
+-static inline unsigned long ffz(unsigned long word)
++
++/**
++ * __ffz_word_loop - find byte offset of first long != -1UL
++ * @addr: pointer to array of unsigned long
++ * @size: size of the array in bits
++ */
++static inline unsigned long __ffz_word_loop(const unsigned long *addr,
++					    unsigned long size)
+ {
+-        unsigned long bit = 0;
++	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
++	unsigned long bytes = 0;
+ 
++	asm volatile(
++#ifndef __s390x__
++		"	ahi	%1,31\n"
++		"	srl	%1,5\n"
++		"0:	c	%2,0(%0,%3)\n"
++		"	jne	1f\n"
++		"	la	%0,4(%0)\n"
++		"	brct	%1,0b\n"
++		"1:\n"
++#else
++		"	aghi	%1,63\n"
++		"	srlg	%1,%1,6\n"
++		"0:	cg	%2,0(%0,%3)\n"
++		"	jne	1f\n"
++		"	la	%0,8(%0)\n"
++		"	brct	%1,0b\n"
++		"1:\n"
++#endif
++		: "+a" (bytes), "+d" (size)
++		: "d" (-1UL), "a" (addr), "m" (*(addrtype *) addr)
++		: "cc" );
++	return bytes;
++}
++
++/**
++ * __ffs_word_loop - find byte offset of first long != 0UL
++ * @addr: pointer to array of unsigned long
++ * @size: size of the array in bits
++ */
++static inline unsigned long __ffs_word_loop(const unsigned long *addr,
++					    unsigned long size)
++{
++	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
++	unsigned long bytes = 0;
++
++	asm volatile(
++#ifndef __s390x__
++		"	ahi	%1,31\n"
++		"	srl	%1,5\n"
++		"0:	c	%2,0(%0,%3)\n"
++		"	jne	1f\n"
++		"	la	%0,4(%0)\n"
++		"	brct	%1,0b\n"
++		"1:\n"
++#else
++		"	aghi	%1,63\n"
++		"	srlg	%1,%1,6\n"
++		"0:	cg	%2,0(%0,%3)\n"
++		"	jne	1f\n"
++		"	la	%0,8(%0)\n"
++		"	brct	%1,0b\n"
++		"1:\n"
++#endif
++		: "+a" (bytes), "+a" (size)
++		: "d" (0UL), "a" (addr), "m" (*(addrtype *) addr)
++		: "cc" );
++	return bytes;
++}
++
++/**
++ * __ffz_word - add number of the first unset bit
++ * @nr: base value the bit number is added to
++ * @word: the word that is searched for unset bits
++ */
++static inline unsigned long __ffz_word(unsigned long nr, unsigned long word)
++{
+ #ifdef __s390x__
+ 	if (likely((word & 0xffffffff) == 0xffffffff)) {
+ 		word >>= 32;
+-		bit += 32;
++		nr += 32;
+ 	}
+ #endif
+ 	if (likely((word & 0xffff) == 0xffff)) {
+ 		word >>= 16;
+-		bit += 16;
++		nr += 16;
+ 	}
+ 	if (likely((word & 0xff) == 0xff)) {
+ 		word >>= 8;
+-		bit += 8;
++		nr += 8;
+ 	}
+-	return bit + _zb_findmap[word & 0xff];
++	return nr + _zb_findmap[(unsigned char) word];
+ }
+ 
+-/*
+- * __ffs = find first bit in word. Undefined if no bit exists,
+- * so code should check against 0UL first..
++/**
++ * __ffs_word - add number of the first set bit
++ * @nr: base value the bit number is added to
++ * @word: the word that is searched for set bits
+  */
+-static inline unsigned long __ffs (unsigned long word)
++static inline unsigned long __ffs_word(unsigned long nr, unsigned long word)
+ {
+-	unsigned long bit = 0;
+-
+ #ifdef __s390x__
+ 	if (likely((word & 0xffffffff) == 0)) {
+ 		word >>= 32;
+-		bit += 32;
++		nr += 32;
+ 	}
+ #endif
+ 	if (likely((word & 0xffff) == 0)) {
+ 		word >>= 16;
+-		bit += 16;
++		nr += 16;
+ 	}
+ 	if (likely((word & 0xff) == 0)) {
+ 		word >>= 8;
+-		bit += 8;
++		nr += 8;
+ 	}
+-	return bit + _sb_findmap[word & 0xff];
++	return nr + _sb_findmap[(unsigned char) word];
+ }
+ 
+-/*
+- * Find-bit routines..
+- */
+ 
+-#ifndef __s390x__
++/**
++ * __load_ulong_be - load big endian unsigned long
++ * @p: pointer to array of unsigned long
++ * @offset: byte offset of source value in the array
++ */
++static inline unsigned long __load_ulong_be(const unsigned long *p,
++					    unsigned long offset)
++{
++	p = (unsigned long *)((unsigned long) p + offset);
++	return *p;
++}
+ 
+-static inline int
+-find_first_zero_bit(const unsigned long * addr, unsigned long size)
++/**
++ * __load_ulong_le - load little endian unsigned long
++ * @p: pointer to array of unsigned long
++ * @offset: byte offset of source value in the array
++ */
++static inline unsigned long __load_ulong_le(const unsigned long *p,
++					    unsigned long offset)
+ {
+-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
+-	unsigned long cmp, count;
+-        unsigned int res;
++	unsigned long word;
+ 
+-        if (!size)
+-                return 0;
++	p = (unsigned long *)((unsigned long) p + offset);
++#ifndef __s390x__
+ 	asm volatile(
+-		"	lhi	%1,-1\n"
+-		"	lr	%2,%3\n"
+-		"	slr	%0,%0\n"
+-		"	ahi	%2,31\n"
+-		"	srl	%2,5\n"
+-		"0:	c	%1,0(%0,%4)\n"
+-		"	jne	1f\n"
+-		"	la	%0,4(%0)\n"
+-		"	brct	%2,0b\n"
+-		"	lr	%0,%3\n"
+-		"	j	4f\n"
+-		"1:	l	%2,0(%0,%4)\n"
+-		"	sll	%0,3\n"
+-		"	lhi	%1,0xff\n"
+-		"	tml	%2,0xffff\n"
+-		"	jno	2f\n"
+-		"	ahi	%0,16\n"
+-		"	srl	%2,16\n"
+-		"2:	tml	%2,0x00ff\n"
+-		"	jno	3f\n"
+-		"	ahi	%0,8\n"
+-		"	srl	%2,8\n"
+-		"3:	nr	%2,%1\n"
+-		"	ic	%2,0(%2,%5)\n"
+-		"	alr	%0,%2\n"
+-		"4:"
+-		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+-		: "a" (size), "a" (addr), "a" (&_zb_findmap),
+-		  "m" (*(addrtype *) addr) : "cc");
+-        return (res < size) ? res : size;
++		"	ic	%0,0(%1)\n"
++		"	icm	%0,2,1(%1)\n"
++		"	icm	%0,4,2(%1)\n"
++		"	icm	%0,8,3(%1)"
++		: "=&d" (word) : "a" (p), "m" (*p) : "cc");
++#else
++	asm volatile(
++		"	lrvg	%0,%1"
++		: "=d" (word) : "m" (*p) );
++#endif
++	return word;
+ }
+ 
+-static inline int
+-find_first_bit(const unsigned long * addr, unsigned long size)
++/*
++ * The various find bit functions.
++ */
++
++/*
++ * ffz - find first zero in word.
++ * @word: The word to search
++ *
++ * Undefined if no zero exists, so code should check against ~0UL first.
++ */
++static inline unsigned long ffz(unsigned long word)
+ {
+-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
+-	unsigned long cmp, count;
+-        unsigned int res;
++	return __ffz_word(0, word);
++}
+ 
+-        if (!size)
+-                return 0;
+-	asm volatile(
+-		"	slr	%1,%1\n"
+-		"	lr	%2,%3\n"
+-		"	slr	%0,%0\n"
+-		"	ahi	%2,31\n"
+-		"	srl	%2,5\n"
+-		"0:	c	%1,0(%0,%4)\n"
+-		"	jne	1f\n"
+-		"	la	%0,4(%0)\n"
+-		"	brct	%2,0b\n"
+-		"	lr	%0,%3\n"
+-		"	j	4f\n"
+-		"1:	l	%2,0(%0,%4)\n"
+-		"	sll	%0,3\n"
+-		"	lhi	%1,0xff\n"
+-		"	tml	%2,0xffff\n"
+-		"	jnz	2f\n"
+-		"	ahi	%0,16\n"
+-		"	srl	%2,16\n"
+-		"2:	tml	%2,0x00ff\n"
+-		"	jnz	3f\n"
+-		"	ahi	%0,8\n"
+-		"	srl	%2,8\n"
+-		"3:	nr	%2,%1\n"
+-		"	ic	%2,0(%2,%5)\n"
+-		"	alr	%0,%2\n"
+-		"4:"
+-		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+-		: "a" (size), "a" (addr), "a" (&_sb_findmap),
+-		  "m" (*(addrtype *) addr) : "cc");
+-        return (res < size) ? res : size;
++/**
++ * __ffs - find first bit in word.
++ * @word: The word to search
++ *
++ * Undefined if no bit exists, so code should check against 0 first.
++ */
++static inline unsigned long __ffs (unsigned long word)
++{
++	return __ffs_word(0, word);
+ }
+ 
+-#else /* __s390x__ */
++/**
++ * ffs - find first bit set
++ * @x: the word to search
++ *
++ * This is defined the same way as
++ * the libc and compiler builtin ffs routines, therefore
++ * differs in spirit from the above ffz (man ffs).
++ */
++static inline int ffs(int x)
++{
++	if (!x)
++		return 0;
++	return __ffs_word(1, x);
++}
+ 
+-static inline unsigned long
+-find_first_zero_bit(const unsigned long * addr, unsigned long size)
++/**
++ * find_first_zero_bit - find the first zero bit in a memory region
++ * @addr: The address to start the search at
++ * @size: The maximum size to search
++ *
++ * Returns the bit-number of the first zero bit, not the number of the byte
++ * containing a bit.
++ */
++static inline unsigned long find_first_zero_bit(const unsigned long *addr,
++						unsigned long size)
+ {
+-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
+-        unsigned long res, cmp, count;
++	unsigned long bytes, bits;
+ 
+         if (!size)
+                 return 0;
+-	asm volatile(
+-		"	lghi	%1,-1\n"
+-		"	lgr	%2,%3\n"
+-		"	slgr	%0,%0\n"
+-		"	aghi	%2,63\n"
+-		"	srlg	%2,%2,6\n"
+-		"0:	cg	%1,0(%0,%4)\n"
+-		"	jne	1f\n"
+-		"	la	%0,8(%0)\n"
+-		"	brct	%2,0b\n"
+-		"	lgr	%0,%3\n"
+-		"	j	5f\n"
+-		"1:	lg	%2,0(%0,%4)\n"
+-		"	sllg	%0,%0,3\n"
+-		"	clr	%2,%1\n"
+-		"	jne	2f\n"
+-		"	aghi	%0,32\n"
+-		"	srlg	%2,%2,32\n"
+-		"2:	lghi	%1,0xff\n"
+-		"	tmll	%2,0xffff\n"
+-		"	jno	3f\n"
+-		"	aghi	%0,16\n"
+-		"	srl	%2,16\n"
+-		"3:	tmll	%2,0x00ff\n"
+-		"	jno	4f\n"
+-		"	aghi	%0,8\n"
+-		"	srl	%2,8\n"
+-		"4:	ngr	%2,%1\n"
+-		"	ic	%2,0(%2,%5)\n"
+-		"	algr	%0,%2\n"
+-		"5:"
+-		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+-		: "a" (size), "a" (addr), "a" (&_zb_findmap),
+-		  "m" (*(addrtype *) addr) : "cc");
+-        return (res < size) ? res : size;
+-}
+-
+-static inline unsigned long
+-find_first_bit(const unsigned long * addr, unsigned long size)
++	bytes = __ffz_word_loop(addr, size);
++	bits = __ffz_word(bytes*8, __load_ulong_be(addr, bytes));
++	return (bits < size) ? bits : size;
++}
++
++/**
++ * find_first_bit - find the first set bit in a memory region
++ * @addr: The address to start the search at
++ * @size: The maximum size to search
++ *
++ * Returns the bit-number of the first set bit, not the number of the byte
++ * containing a bit.
++ */
++static inline unsigned long find_first_bit(const unsigned long * addr,
++					   unsigned long size)
+ {
+-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
+-        unsigned long res, cmp, count;
++	unsigned long bytes, bits;
+ 
+         if (!size)
+                 return 0;
+-	asm volatile(
+-		"	slgr	%1,%1\n"
+-		"	lgr	%2,%3\n"
+-		"	slgr	%0,%0\n"
+-		"	aghi	%2,63\n"
+-		"	srlg	%2,%2,6\n"
+-		"0:	cg	%1,0(%0,%4)\n"
+-		"	jne	1f\n"
+-		"	aghi	%0,8\n"
+-		"	brct	%2,0b\n"
+-		"	lgr	%0,%3\n"
+-		"	j	5f\n"
+-		"1:	lg	%2,0(%0,%4)\n"
+-		"	sllg	%0,%0,3\n"
+-		"	clr	%2,%1\n"
+-		"	jne	2f\n"
+-		"	aghi	%0,32\n"
+-		"	srlg	%2,%2,32\n"
+-		"2:	lghi	%1,0xff\n"
+-		"	tmll	%2,0xffff\n"
+-		"	jnz	3f\n"
+-		"	aghi	%0,16\n"
+-		"	srl	%2,16\n"
+-		"3:	tmll	%2,0x00ff\n"
+-		"	jnz	4f\n"
+-		"	aghi	%0,8\n"
+-		"	srl	%2,8\n"
+-		"4:	ngr	%2,%1\n"
+-		"	ic	%2,0(%2,%5)\n"
+-		"	algr	%0,%2\n"
+-		"5:"
+-		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+-		: "a" (size), "a" (addr), "a" (&_sb_findmap),
+-		  "m" (*(addrtype *) addr) : "cc");
+-        return (res < size) ? res : size;
++	bytes = __ffs_word_loop(addr, size);
++	bits = __ffs_word(bytes*8, __load_ulong_be(addr, bytes));
++	return (bits < size) ? bits : size;
+ }
+ 
+-#endif /* __s390x__ */
+-
+-static inline int
+-find_next_zero_bit (const unsigned long * addr, unsigned long size,
+-		    unsigned long offset)
++/**
++ * find_next_zero_bit - find the first zero bit in a memory region
++ * @addr: The address to base the search on
++ * @offset: The bitnumber to start searching at
++ * @size: The maximum size to search
++ */
++static inline int find_next_zero_bit (const unsigned long * addr,
++				      unsigned long size,
++				      unsigned long offset)
+ {
+         const unsigned long *p;
+ 	unsigned long bit, set;
+@@ -688,10 +702,10 @@ find_next_zero_bit (const unsigned long * addr, unsigned long size,
+ 	p = addr + offset / __BITOPS_WORDSIZE;
+ 	if (bit) {
+ 		/*
+-		 * s390 version of ffz returns __BITOPS_WORDSIZE
++		 * __ffz_word returns __BITOPS_WORDSIZE
+ 		 * if no zero bit is present in the word.
+ 		 */
+-		set = ffz(*p >> bit) + bit;
++		set = __ffz_word(0, *p >> bit) + bit;
+ 		if (set >= size)
+ 			return size + offset;
+ 		if (set < __BITOPS_WORDSIZE)
+@@ -703,9 +717,15 @@ find_next_zero_bit (const unsigned long * addr, unsigned long size,
+ 	return offset + find_first_zero_bit(p, size);
+ }
+ 
+-static inline int
+-find_next_bit (const unsigned long * addr, unsigned long size,
+-	       unsigned long offset)
++/**
++ * find_next_bit - find the first set bit in a memory region
++ * @addr: The address to base the search on
++ * @offset: The bitnumber to start searching at
++ * @size: The maximum size to search
++ */
++static inline int find_next_bit (const unsigned long * addr,
++				 unsigned long size,
++				 unsigned long offset)
+ {
+         const unsigned long *p;
+ 	unsigned long bit, set;
+@@ -718,10 +738,10 @@ find_next_bit (const unsigned long * addr, unsigned long size,
+ 	p = addr + offset / __BITOPS_WORDSIZE;
+ 	if (bit) {
+ 		/*
+-		 * s390 version of __ffs returns __BITOPS_WORDSIZE
++		 * __ffs_word returns __BITOPS_WORDSIZE
+ 		 * if no one bit is present in the word.
+ 		 */
+-		set = __ffs(*p & (~0UL << bit));
++		set = __ffs_word(0, *p & (~0UL << bit));
+ 		if (set >= size)
+ 			return size + offset;
+ 		if (set < __BITOPS_WORDSIZE)
+@@ -744,8 +764,6 @@ static inline int sched_find_first_bit(unsigned long *b)
+ 	return find_first_bit(b, 140);
+ }
+ 
+-#include <asm-generic/bitops/ffs.h>
+-
+ #include <asm-generic/bitops/fls.h>
+ #include <asm-generic/bitops/fls64.h>
+ 
+@@ -773,105 +791,22 @@ static inline int sched_find_first_bit(unsigned long *b)
  #define ext2_test_bit(nr, addr)      \
  	test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
-+#define ext2_find_next_bit(addr, size, off) \
-+	generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
  
- #ifndef __s390x__
+-#ifndef __s390x__
+-
+-static inline int 
+-ext2_find_first_zero_bit(void *vaddr, unsigned int size)
++static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size)
+ {
+-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
+-	unsigned long cmp, count;
+-        unsigned int res;
++	unsigned long bytes, bits;
+ 
+         if (!size)
+                 return 0;
+-	asm volatile(
+-		"	lhi	%1,-1\n"
+-		"	lr	%2,%3\n"
+-		"	ahi	%2,31\n"
+-		"	srl	%2,5\n"
+-		"	slr	%0,%0\n"
+-		"0:	cl	%1,0(%0,%4)\n"
+-		"	jne	1f\n"
+-		"	ahi	%0,4\n"
+-		"	brct	%2,0b\n"
+-		"	lr	%0,%3\n"
+-		"	j	4f\n"
+-		"1:	l	%2,0(%0,%4)\n"
+-		"	sll	%0,3\n"
+-		"	ahi	%0,24\n"
+-		"	lhi	%1,0xff\n"
+-		"	tmh	%2,0xffff\n"
+-		"	jo	2f\n"
+-		"	ahi	%0,-16\n"
+-		"	srl	%2,16\n"
+-		"2:	tml	%2,0xff00\n"
+-		"	jo	3f\n"
+-		"	ahi	%0,-8\n"
+-		"	srl	%2,8\n"
+-		"3:	nr	%2,%1\n"
+-		"	ic	%2,0(%2,%5)\n"
+-		"	alr	%0,%2\n"
+-		"4:"
+-		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+-		: "a" (size), "a" (vaddr), "a" (&_zb_findmap),
+-		  "m" (*(addrtype *) vaddr) : "cc");
+-        return (res < size) ? res : size;
++	bytes = __ffz_word_loop(vaddr, size);
++	bits = __ffz_word(bytes*8, __load_ulong_le(vaddr, bytes));
++	return (bits < size) ? bits : size;
+ }
+ 
+-#else /* __s390x__ */
+-
+-static inline unsigned long
+-ext2_find_first_zero_bit(void *vaddr, unsigned long size)
+-{
+-	typedef struct { long _[__BITOPS_WORDS(size)]; } addrtype;
+-        unsigned long res, cmp, count;
+-
+-        if (!size)
+-                return 0;
+-	asm volatile(
+-		"	lghi	%1,-1\n"
+-		"	lgr	%2,%3\n"
+-		"	aghi	%2,63\n"
+-		"	srlg	%2,%2,6\n"
+-		"	slgr	%0,%0\n"
+-		"0:	clg	%1,0(%0,%4)\n"
+-		"	jne	1f\n"
+-		"	aghi	%0,8\n"
+-		"	brct	%2,0b\n"
+-		"	lgr	%0,%3\n"
+-		"	j	5f\n"
+-		"1:	cl	%1,0(%0,%4)\n"
+-		"	jne	2f\n"
+-		"	aghi	%0,4\n"
+-		"2:	l	%2,0(%0,%4)\n"
+-		"	sllg	%0,%0,3\n"
+-		"	aghi	%0,24\n"
+-		"	lghi	%1,0xff\n"
+-		"	tmlh	%2,0xffff\n"
+-		"	jo	3f\n"
+-		"	aghi	%0,-16\n"
+-		"	srl	%2,16\n"
+-		"3:	tmll	%2,0xff00\n"
+-		"	jo	4f\n"
+-		"	aghi	%0,-8\n"
+-		"	srl	%2,8\n"
+-		"4:	ngr	%2,%1\n"
+-		"	ic	%2,0(%2,%5)\n"
+-		"	algr	%0,%2\n"
+-		"5:"
+-		: "=&a" (res), "=&d" (cmp), "=&a" (count)
+-		: "a" (size), "a" (vaddr), "a" (&_zb_findmap),
+-		  "m" (*(addrtype *) vaddr) : "cc");
+-        return (res < size) ? res : size;
+-}
+-
+-#endif /* __s390x__ */
+-
+-static inline int
+-ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
++static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size,
++					  unsigned long offset)
+ {
+         unsigned long *addr = vaddr, *p;
+-	unsigned long word, bit, set;
++	unsigned long bit, set;
+ 
+         if (offset >= size)
+                 return size;
+@@ -880,23 +815,11 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
+ 	size -= offset;
+ 	p = addr + offset / __BITOPS_WORDSIZE;
+         if (bit) {
+-#ifndef __s390x__
+-		asm volatile(
+-			"	ic	%0,0(%1)\n"
+-			"	icm	%0,2,1(%1)\n"
+-			"	icm	%0,4,2(%1)\n"
+-			"	icm	%0,8,3(%1)"
+-			: "=&a" (word) : "a" (p), "m" (*p) : "cc");
+-#else
+-		asm volatile(
+-			"	lrvg	%0,%1"
+-			: "=a" (word) : "m" (*p) );
+-#endif
+ 		/*
+ 		 * s390 version of ffz returns __BITOPS_WORDSIZE
+ 		 * if no zero bit is present in the word.
+ 		 */
+-		set = ffz(word >> bit) + bit;
++		set = ffz(__load_ulong_le(p, 0) >> bit) + bit;
+ 		if (set >= size)
+ 			return size + offset;
+ 		if (set < __BITOPS_WORDSIZE)
+@@ -908,6 +831,47 @@ ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
+ 	return offset + ext2_find_first_zero_bit(p, size);
+ }
+ 
++static inline unsigned long ext2_find_first_bit(void *vaddr,
++						unsigned long size)
++{
++	unsigned long bytes, bits;
++
++	if (!size)
++		return 0;
++	bytes = __ffs_word_loop(vaddr, size);
++	bits = __ffs_word(bytes*8, __load_ulong_le(vaddr, bytes));
++	return (bits < size) ? bits : size;
++}
++
++static inline int ext2_find_next_bit(void *vaddr, unsigned long size,
++				     unsigned long offset)
++{
++	unsigned long *addr = vaddr, *p;
++	unsigned long bit, set;
++
++	if (offset >= size)
++		return size;
++	bit = offset & (__BITOPS_WORDSIZE - 1);
++	offset -= bit;
++	size -= offset;
++	p = addr + offset / __BITOPS_WORDSIZE;
++	if (bit) {
++		/*
++		 * s390 version of ffz returns __BITOPS_WORDSIZE
++		 * if no zero bit is present in the word.
++		 */
++		set = ffs(__load_ulong_le(p, 0) >> bit) + bit;
++		if (set >= size)
++			return size + offset;
++		if (set < __BITOPS_WORDSIZE)
++			return set + offset;
++		offset += __BITOPS_WORDSIZE;
++		size -= __BITOPS_WORDSIZE;
++		p++;
++	}
++	return offset + ext2_find_first_bit(p, size);
++}
++
+ #include <asm-generic/bitops/minix.h>
+ 
+ #endif /* __KERNEL__ */
+diff --git a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h
+index f7cade8..49d5af9 100644
+--- a/include/asm-s390/cacheflush.h
++++ b/include/asm-s390/cacheflush.h
+@@ -24,4 +24,8 @@
+ #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ 	memcpy(dst, src, len)
+ 
++#ifdef CONFIG_DEBUG_PAGEALLOC
++void kernel_map_pages(struct page *page, int numpages, int enable);
++#endif
++
+ #endif /* _S390_CACHEFLUSH_H */
+diff --git a/include/asm-s390/ccwgroup.h b/include/asm-s390/ccwgroup.h
+index 7109c7c..289053e 100644
+--- a/include/asm-s390/ccwgroup.h
++++ b/include/asm-s390/ccwgroup.h
+@@ -37,6 +37,7 @@ struct ccwgroup_device {
+  * @remove: function called on remove
+  * @set_online: function called when device is set online
+  * @set_offline: function called when device is set offline
++ * @shutdown: function called when device is shut down
+  * @driver: embedded driver structure
+  */
+ struct ccwgroup_driver {
+@@ -49,6 +50,7 @@ struct ccwgroup_driver {
+ 	void (*remove) (struct ccwgroup_device *);
+ 	int (*set_online) (struct ccwgroup_device *);
+ 	int (*set_offline) (struct ccwgroup_device *);
++	void (*shutdown)(struct ccwgroup_device *);
  
+ 	struct device_driver driver;
+ };
 diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h
 index 2f08c16..123b557 100644
 --- a/include/asm-s390/cio.h
@@ -813410,6 +882036,19 @@
   * @zcc: zero condition code
   * @ectl: extended control
   * @pno: path not operational
+diff --git a/include/asm-s390/compat.h b/include/asm-s390/compat.h
+index 7f4ad62..de065b3 100644
+--- a/include/asm-s390/compat.h
++++ b/include/asm-s390/compat.h
+@@ -149,7 +149,7 @@ typedef u32		compat_sigset_word;
+  * A pointer passed in from user mode. This should not
+  * be used for syscall parameters, just declare them
+  * as pointers because the syscall entry code will have
+- * appropriately comverted them already.
++ * appropriately converted them already.
+  */
+ typedef	u32		compat_uptr_t;
+ 
 diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h
 index 604f68f..3f002e1 100644
 --- a/include/asm-s390/dasd.h
@@ -813593,11 +882232,67 @@
 +#include <asm-generic/percpu.h>
  
  #endif /* __ARCH_S390_PERCPU__ */
+diff --git a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
+index 709dd17..6f6619b 100644
+--- a/include/asm-s390/pgalloc.h
++++ b/include/asm-s390/pgalloc.h
+@@ -57,10 +57,10 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)
+ }
+ 
+ #define pud_alloc_one(mm,address)		({ BUG(); ((pud_t *)2); })
+-#define pud_free(x)				do { } while (0)
++#define pud_free(mm, x)				do { } while (0)
+ 
+ #define pmd_alloc_one(mm,address)		({ BUG(); ((pmd_t *)2); })
+-#define pmd_free(x)				do { } while (0)
++#define pmd_free(mm, x)				do { } while (0)
+ 
+ #define pgd_populate(mm, pgd, pud)		BUG()
+ #define pgd_populate_kernel(mm, pgd, pud)	BUG()
+@@ -76,7 +76,7 @@ static inline unsigned long pgd_entry_type(struct mm_struct *mm)
+ }
+ 
+ #define pud_alloc_one(mm,address)		({ BUG(); ((pud_t *)2); })
+-#define pud_free(x)				do { } while (0)
++#define pud_free(mm, x)				do { } while (0)
+ 
+ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
+ {
+@@ -85,7 +85,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long vmaddr)
+ 		crst_table_init(crst, _SEGMENT_ENTRY_EMPTY);
+ 	return (pmd_t *) crst;
+ }
+-#define pmd_free(pmd) crst_table_free((unsigned long *) pmd)
++#define pmd_free(mm, pmd) crst_table_free((unsigned long *)pmd)
+ 
+ #define pgd_populate(mm, pgd, pud)		BUG()
+ #define pgd_populate_kernel(mm, pgd, pud)	BUG()
+@@ -115,7 +115,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 		crst_table_init(crst, pgd_entry_type(mm));
+ 	return (pgd_t *) crst;
+ }
+-#define pgd_free(pgd) crst_table_free((unsigned long *) pgd)
++#define pgd_free(mm, pgd) crst_table_free((unsigned long *) pgd)
+ 
+ static inline void 
+ pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, pte_t *pte)
+@@ -151,9 +151,9 @@ pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *page)
+ #define pte_alloc_one(mm, vmaddr) \
+ 	virt_to_page(page_table_alloc(s390_noexec))
+ 
+-#define pte_free_kernel(pte) \
++#define pte_free_kernel(mm, pte) \
+ 	page_table_free((unsigned long *) pte)
+-#define pte_free(pte) \
++#define pte_free(mm, pte) \
+ 	page_table_free((unsigned long *) page_to_phys((struct page *) pte))
+ 
+ #endif /* _S390_PGALLOC_H */
 diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
-index 1f530f8..79b9eab 100644
+index 1f530f8..3f52075 100644
 --- a/include/asm-s390/pgtable.h
 +++ b/include/asm-s390/pgtable.h
-@@ -104,41 +104,27 @@ extern char empty_zero_page[PAGE_SIZE];
+@@ -104,42 +104,34 @@ extern char empty_zero_page[PAGE_SIZE];
  
  #ifndef __ASSEMBLY__
  /*
@@ -813640,23 +882335,30 @@
 -#define VMALLOC_END_INIT	0x80000000UL
 +#define VMALLOC_START	0x78000000UL
 +#define VMALLOC_END	0x7e000000UL
-+#define VMEM_MAP_MAX	0x80000000UL
++#define VMEM_MAP_END	0x80000000UL
  #else /* __s390x__ */
 -#define VMALLOC_MIN_SIZE	0x2000000000UL
 -#define VMALLOC_END_INIT	0x40000000000UL
 +#define VMALLOC_START	0x3e000000000UL
 +#define VMALLOC_END	0x3e040000000UL
-+#define VMEM_MAP_MAX	0x40000000000UL
++#define VMEM_MAP_END	0x40000000000UL
  #endif /* __s390x__ */
  
+ /*
++ * VMEM_MAX_PHYS is the highest physical address that can be added to the 1:1
++ * mapping. This needs to be calculated at compile time since the size of the
++ * VMEM_MAP is static but the size of struct page can change.
++ */
++#define VMEM_MAX_PHYS	min(VMALLOC_START, ((VMEM_MAP_END - VMALLOC_END) / \
++			  sizeof(struct page) * PAGE_SIZE) & ~((16 << 20) - 1))
 +#define VMEM_MAP	((struct page *) VMALLOC_END)
-+#define VMEM_MAP_SIZE	((VMALLOC_START / PAGE_SIZE) * sizeof(struct page))
 +
- /*
++/*
   * A 31 bit pagetable entry of S390 has following format:
   *  |   PFRA          |    |  OS  |
+  * 0                   0IP0
 diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
-index 21d40a1..c86b982 100644
+index 21d40a1..4f74460 100644
 --- a/include/asm-s390/processor.h
 +++ b/include/asm-s390/processor.h
 @@ -59,9 +59,6 @@ extern void s390_adjust_jiffies(void);
@@ -813669,7 +882371,18 @@
  /*
   * User space process size: 2GB for 31 bit, 4TB for 64 bit.
   */
-@@ -95,7 +92,6 @@ struct thread_struct {
+@@ -73,8 +70,9 @@ extern struct task_struct *last_task_used_math;
+ 
+ #else /* __s390x__ */
+ 
+-# define TASK_SIZE		(test_thread_flag(TIF_31BIT) ? \
++# define TASK_SIZE_OF(tsk)	(test_tsk_thread_flag(tsk, TIF_31BIT) ? \
+ 					(0x80000000UL) : (0x40000000000UL))
++# define TASK_SIZE		TASK_SIZE_OF(current)
+ # define TASK_UNMAPPED_BASE	(TASK_SIZE / 2)
+ # define DEFAULT_TASK_SIZE	(0x40000000000UL)
+ 
+@@ -95,7 +93,6 @@ struct thread_struct {
          unsigned long ksp;              /* kernel stack pointer             */
  	mm_segment_t mm_segment;
          unsigned long prot_addr;        /* address of protection-excep.     */
@@ -813875,6 +882588,40 @@
  } __attribute__ ((aligned (4))) raw_spinlock_t;
  
  #define __RAW_SPIN_LOCK_UNLOCKED	{ 0 }
+diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h
+index 618693c..985de2b 100644
+--- a/include/asm-s390/tlb.h
++++ b/include/asm-s390/tlb.h
+@@ -65,9 +65,9 @@ static inline void tlb_flush_mmu(struct mmu_gather *tlb,
+ 	if (!tlb->fullmm && (tlb->nr_ptes > 0 || tlb->nr_pmds < TLB_NR_PTRS))
+ 		__tlb_flush_mm(tlb->mm);
+ 	while (tlb->nr_ptes > 0)
+-		pte_free(tlb->array[--tlb->nr_ptes]);
++		pte_free(tlb->mm, tlb->array[--tlb->nr_ptes]);
+ 	while (tlb->nr_pmds < TLB_NR_PTRS)
+-		pmd_free((pmd_t *) tlb->array[tlb->nr_pmds++]);
++		pmd_free(tlb->mm, (pmd_t *) tlb->array[tlb->nr_pmds++]);
+ }
+ 
+ static inline void tlb_finish_mmu(struct mmu_gather *tlb,
+@@ -102,7 +102,7 @@ static inline void pte_free_tlb(struct mmu_gather *tlb, struct page *page)
+ 		if (tlb->nr_ptes >= tlb->nr_pmds)
+ 			tlb_flush_mmu(tlb, 0, 0);
+ 	} else
+-		pte_free(page);
++		pte_free(tlb->mm, page);
+ }
+ 
+ /*
+@@ -117,7 +117,7 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
+ 		if (tlb->nr_ptes >= tlb->nr_pmds)
+ 			tlb_flush_mmu(tlb, 0, 0);
+ 	} else
+-		pmd_free(pmd);
++		pmd_free(tlb->mm, pmd);
+ #endif
+ }
+ 
 diff --git a/include/asm-s390/tlbflush.h b/include/asm-s390/tlbflush.h
 index a69bd24..70fa5ae 100644
 --- a/include/asm-s390/tlbflush.h
@@ -817910,6 +886657,43 @@
  #endif
  
  #define PCI_MEM_SIZE		0x01000000
+diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h
+index 18b613c..59ca16d 100644
+--- a/include/asm-sh/pgalloc.h
++++ b/include/asm-sh/pgalloc.h
+@@ -36,7 +36,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return quicklist_alloc(QUICK_PGD, GFP_KERNEL | __GFP_REPEAT, pgd_ctor);
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	quicklist_free(QUICK_PGD, NULL, pgd);
+ }
+@@ -54,12 +54,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return pg ? virt_to_page(pg) : NULL;
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	quicklist_free(QUICK_PT, NULL, pte);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	quicklist_free_page(QUICK_PT, NULL, pte);
+ }
+@@ -71,7 +71,7 @@ static inline void pte_free(struct page *pte)
+  * inside the pgd, so has no extra memory associated with it.
+  */
+ 
+-#define pmd_free(x)			do { } while (0)
++#define pmd_free(mm, x)			do { } while (0)
+ #define __pmd_free_tlb(tlb,x)		do { } while (0)
+ 
+ static inline void check_pgt_cache(void)
 diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
 index 8f1e8be..a4a8f8b 100644
 --- a/include/asm-sh/pgtable.h
@@ -823494,7 +892278,7 @@
 -#endif /* __ASM_SH_UNISTD_H */
 diff --git a/include/asm-sh/unistd_32.h b/include/asm-sh/unistd_32.h
 new file mode 100644
-index 0000000..b182b1c
+index 0000000..433fd1b
 --- /dev/null
 +++ b/include/asm-sh/unistd_32.h
 @@ -0,0 +1,376 @@
@@ -823830,7 +892614,7 @@
 +#define __NR_epoll_pwait	319
 +#define __NR_utimensat		320
 +#define __NR_signalfd		321
-+#define __NR_timerfd		322
++/* #define __NR_timerfd		322 removed */
 +#define __NR_eventfd		323
 +#define __NR_fallocate		324
 +
@@ -823876,7 +892660,7 @@
 +#endif /* __ASM_SH_UNISTD_H */
 diff --git a/include/asm-sh/unistd_64.h b/include/asm-sh/unistd_64.h
 new file mode 100644
-index 0000000..9445118
+index 0000000..108d2ba
 --- /dev/null
 +++ b/include/asm-sh/unistd_64.h
 @@ -0,0 +1,415 @@
@@ -824252,7 +893036,7 @@
 +#define __NR_epoll_pwait	347
 +#define __NR_utimensat		348
 +#define __NR_signalfd		349
-+#define __NR_timerfd		350
++/* #define __NR_timerfd		350 removed */
 +#define __NR_eventfd		351
 +#define __NR_fallocate		352
 +
@@ -831240,6 +900024,44 @@
 -#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
 -
 -#endif /* __ASM_SH64_USER_H */
+diff --git a/include/asm-sparc/pgalloc.h b/include/asm-sparc/pgalloc.h
+index a449cd4..b5fbdd3 100644
+--- a/include/asm-sparc/pgalloc.h
++++ b/include/asm-sparc/pgalloc.h
+@@ -32,7 +32,7 @@ BTFIXUPDEF_CALL(pgd_t *, get_pgd_fast, void)
+ BTFIXUPDEF_CALL(void, free_pgd_fast, pgd_t *)
+ #define free_pgd_fast(pgd)	BTFIXUP_CALL(free_pgd_fast)(pgd)
+ 
+-#define pgd_free(pgd)	free_pgd_fast(pgd)
++#define pgd_free(mm, pgd)	free_pgd_fast(pgd)
+ #define pgd_alloc(mm)	get_pgd_fast()
+ 
+ BTFIXUPDEF_CALL(void, pgd_set, pgd_t *, pmd_t *)
+@@ -45,8 +45,8 @@ BTFIXUPDEF_CALL(pmd_t *, pmd_alloc_one, struct mm_struct *, unsigned long)
+ BTFIXUPDEF_CALL(void, free_pmd_fast, pmd_t *)
+ #define free_pmd_fast(pmd)	BTFIXUP_CALL(free_pmd_fast)(pmd)
+ 
+-#define pmd_free(pmd)           free_pmd_fast(pmd)
+-#define __pmd_free_tlb(tlb, pmd) pmd_free(pmd)
++#define pmd_free(mm, pmd)	free_pmd_fast(pmd)
++#define __pmd_free_tlb(tlb, pmd) pmd_free((tlb)->mm, pmd)
+ 
+ BTFIXUPDEF_CALL(void, pmd_populate, pmd_t *, struct page *)
+ #define pmd_populate(MM, PMD, PTE)        BTFIXUP_CALL(pmd_populate)(PMD, PTE)
+@@ -59,10 +59,10 @@ BTFIXUPDEF_CALL(pte_t *, pte_alloc_one_kernel, struct mm_struct *, unsigned long
+ #define pte_alloc_one_kernel(mm, addr)	BTFIXUP_CALL(pte_alloc_one_kernel)(mm, addr)
+ 
+ BTFIXUPDEF_CALL(void, free_pte_fast, pte_t *)
+-#define pte_free_kernel(pte)	BTFIXUP_CALL(free_pte_fast)(pte)
++#define pte_free_kernel(mm, pte)	BTFIXUP_CALL(free_pte_fast)(pte)
+ 
+ BTFIXUPDEF_CALL(void, pte_free, struct page *)
+-#define pte_free(pte)		BTFIXUP_CALL(pte_free)(pte)
+-#define __pte_free_tlb(tlb, pte)	pte_free(pte)
++#define pte_free(mm, pte)	BTFIXUP_CALL(pte_free)(pte)
++#define __pte_free_tlb(tlb, pte)	pte_free((tlb)->mm, pte)
+ 
+ #endif /* _SPARC_PGALLOC_H */
 diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h
 index 7c14239..2e2bd0b 100644
 --- a/include/asm-sparc/socket.h
@@ -831259,119 +900081,1055 @@
 +++ b/include/asm-sparc64/agp.h
 @@ -5,7 +5,6 @@
  
- #define map_page_into_agp(page) 
- #define unmap_page_from_agp(page) 
--#define flush_agp_mappings() 
- #define flush_agp_cache() mb()
+ #define map_page_into_agp(page) 
+ #define unmap_page_from_agp(page) 
+-#define flush_agp_mappings() 
+ #define flush_agp_cache() mb()
+ 
+ /* Convert a physical address to an address suitable for the GART. */
+diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
+index 01fe668..f260b58 100644
+--- a/include/asm-sparc64/compat.h
++++ b/include/asm-sparc64/compat.h
+@@ -152,7 +152,7 @@ typedef u32		compat_sigset_word;
+  * A pointer passed in from user mode. This should not
+  * be used for syscall parameters, just declare them
+  * as pointers because the syscall entry code will have
+- * appropriately comverted them already.
++ * appropriately converted them already.
+  */
+ typedef	u32		compat_uptr_t;
+ 
+diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
+index a1f53a4..bee6459 100644
+--- a/include/asm-sparc64/percpu.h
++++ b/include/asm-sparc64/percpu.h
+@@ -7,7 +7,6 @@ register unsigned long __local_per_cpu_offset asm("g5");
+ 
+ #ifdef CONFIG_SMP
+ 
+-#define setup_per_cpu_areas()			do { } while (0)
+ extern void real_setup_per_cpu_areas(void);
+ 
+ extern unsigned long __per_cpu_base;
+@@ -16,45 +15,14 @@ extern unsigned long __per_cpu_shift;
+ 	(__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
+ #define per_cpu_offset(x) (__per_cpu_offset(x))
+ 
+-/* Separate out the type, so (int[3], foo) works. */
+-#define DEFINE_PER_CPU(type, name) \
+-    __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
+-
+-#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name)		\
+-    __attribute__((__section__(".data.percpu.shared_aligned"))) \
+-    __typeof__(type) per_cpu__##name				\
+-    ____cacheline_aligned_in_smp
+-
+-/* var is in discarded region: offset to particular copy we want */
+-#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
+-#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
+-#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
+-
+-/* A macro to avoid #include hell... */
+-#define percpu_modcopy(pcpudst, src, size)			\
+-do {								\
+-	unsigned int __i;					\
+-	for_each_possible_cpu(__i)				\
+-		memcpy((pcpudst)+__per_cpu_offset(__i),		\
+-		       (src), (size));				\
+-} while (0)
++#define __my_cpu_offset __local_per_cpu_offset
++
+ #else /* ! SMP */
+ 
+ #define real_setup_per_cpu_areas()		do { } while (0)
+-#define DEFINE_PER_CPU(type, name) \
+-    __typeof__(type) per_cpu__##name
+-#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name)	\
+-    DEFINE_PER_CPU(type, name)
+-
+-#define per_cpu(var, cpu)			(*((void)cpu, &per_cpu__##var))
+-#define __get_cpu_var(var)			per_cpu__##var
+-#define __raw_get_cpu_var(var)			per_cpu__##var
+ 
+ #endif	/* SMP */
+ 
+-#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
+-
+-#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
+-#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
++#include <asm-generic/percpu.h>
+ 
+ #endif /* __ARCH_SPARC64_PERCPU__ */
+diff --git a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
+index 5d66b85..b48f73c 100644
+--- a/include/asm-sparc64/pgalloc.h
++++ b/include/asm-sparc64/pgalloc.h
+@@ -20,7 +20,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return quicklist_alloc(0, GFP_KERNEL, NULL);
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	quicklist_free(0, NULL, pgd);
+ }
+@@ -32,7 +32,7 @@ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr)
+ 	return quicklist_alloc(0, GFP_KERNEL, NULL);
+ }
+ 
+-static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	quicklist_free(0, NULL, pmd);
+ }
+@@ -50,12 +50,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return pg ? virt_to_page(pg) : NULL;
+ }
+ 		
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	quicklist_free(0, NULL, pte);
+ }
+ 
+-static inline void pte_free(struct page *ptepage)
++static inline void pte_free(struct mm_struct *mm, struct page *ptepage)
+ {
+ 	quicklist_free_page(0, NULL, ptepage);
+ }
+diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
+index 986441d..44a625a 100644
+--- a/include/asm-sparc64/socket.h
++++ b/include/asm-sparc64/socket.h
+@@ -57,4 +57,5 @@
+ #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
+ #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
+ 
++#define SO_MARK			0x0022
+ #endif /* _ASM_SOCKET_H */
+diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
+index 349d1d3..ec81cde 100644
+--- a/include/asm-sparc64/tlb.h
++++ b/include/asm-sparc64/tlb.h
+@@ -100,8 +100,8 @@ static inline void tlb_remove_page(struct mmu_gather *mp, struct page *page)
+ }
+ 
+ #define tlb_remove_tlb_entry(mp,ptep,addr) do { } while (0)
+-#define pte_free_tlb(mp,ptepage) pte_free(ptepage)
+-#define pmd_free_tlb(mp,pmdp) pmd_free(pmdp)
++#define pte_free_tlb(mp, ptepage) pte_free((mp)->mm, ptepage)
++#define pmd_free_tlb(mp, pmdp) pmd_free((mp)->mm, pmdp)
+ #define pud_free_tlb(tlb,pudp) __pud_free_tlb(tlb,pudp)
+ 
+ #define tlb_migrate_finish(mm)	do { } while (0)
+diff --git a/include/asm-um/a.out.h b/include/asm-um/a.out.h
+index 9281dd8..f42ff14 100644
+--- a/include/asm-um/a.out.h
++++ b/include/asm-um/a.out.h
+@@ -13,11 +13,9 @@
+ 
+ extern unsigned long stacksizelim;
+ 
+-extern unsigned long host_task_size;
+-
+ #define STACK_ROOM (stacksizelim)
+ 
+-#define STACK_TOP task_size
++#define STACK_TOP (TASK_SIZE - 2 * PAGE_SIZE)
+ 
+ #define STACK_TOP_MAX STACK_TOP
+ 
+diff --git a/include/asm-um/asm.h b/include/asm-um/asm.h
+new file mode 100644
+index 0000000..af1269a
+--- /dev/null
++++ b/include/asm-um/asm.h
+@@ -0,0 +1,6 @@
++#ifndef __UM_ASM_H
++#define __UM_ASM_H
++
++#include "asm/arch/asm.h"
++
++#endif
+diff --git a/include/asm-um/current.h b/include/asm-um/current.h
+index 8fd72f6..c2191d9 100644
+--- a/include/asm-um/current.h
++++ b/include/asm-um/current.h
+@@ -1,32 +1,13 @@
+-/* 
+- * Copyright (C) 2000 Jeff Dike (jdike at karaya.com)
++/*
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ 
+ #ifndef __UM_CURRENT_H
+ #define __UM_CURRENT_H
+ 
+-#ifndef __ASSEMBLY__
+-
+-#include "asm/page.h"
+ #include "linux/thread_info.h"
+ 
+ #define current (current_thread_info()->task)
+ 
+-/*Backward compatibility - it's used inside arch/um.*/
+-#define current_thread current_thread_info()
+-
+-#endif /* __ASSEMBLY__ */
+-
+ #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-i386.h b/include/asm-um/elf-i386.h
+index ca94a13..23d6893 100644
+--- a/include/asm-um/elf-i386.h
++++ b/include/asm-um/elf-i386.h
+@@ -1,11 +1,11 @@
+ /*
+- * Copyright (C) 2000 - 2003 Jeff Dike (jdike at addtoit.com)
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
+ #ifndef __UM_ELF_I386_H
+ #define __UM_ELF_I386_H
+ 
+-#include <linux/sched.h>
++#include <asm/user.h>
+ #include "skas.h"
+ 
+ #define R_386_NONE	0
+@@ -46,7 +46,7 @@ typedef struct user_i387_struct elf_fpregset_t;
+ 	PT_REGS_EDI(regs) = 0; \
+ 	PT_REGS_EBP(regs) = 0; \
+ 	PT_REGS_EAX(regs) = 0; \
+-} while(0)
++} while (0)
+ 
+ #define USE_ELF_CORE_DUMP
+ #define ELF_EXEC_PAGESIZE 4096
+@@ -74,14 +74,9 @@ typedef struct user_i387_struct elf_fpregset_t;
+ 	pr_reg[14] = PT_REGS_EFLAGS(regs);	\
+ 	pr_reg[15] = PT_REGS_SP(regs);		\
+ 	pr_reg[16] = PT_REGS_SS(regs);		\
+-} while(0);
++} while (0);
+ 
+-static inline int elf_core_copy_fpregs(struct task_struct *t,
+-				       elf_fpregset_t *fpu)
+-{
+-	int cpu = ((struct thread_info *) t->stack)->cpu;
+-	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+-}
++extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
+ 
+ #define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
+ 
+@@ -91,7 +86,7 @@ extern long elf_aux_hwcap;
+ extern char * elf_aux_platform;
+ #define ELF_PLATFORM (elf_aux_platform)
+ 
+-#define SET_PERSONALITY(ex, ibcs2) do ; while(0)
++#define SET_PERSONALITY(ex, ibcs2) do { } while (0)
+ 
+ extern unsigned long vsyscall_ehdr;
+ extern unsigned long vsyscall_end;
+@@ -166,14 +161,3 @@ if ( vsyscall_ehdr ) {							      \
+ }
+ 
+ #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-x86_64.h b/include/asm-um/elf-x86_64.h
+index 3c9d543..3b2d522 100644
+--- a/include/asm-um/elf-x86_64.h
++++ b/include/asm-um/elf-x86_64.h
+@@ -7,7 +7,6 @@
+ #ifndef __UM_ELF_X86_64_H
+ #define __UM_ELF_X86_64_H
+ 
+-#include <linux/sched.h>
+ #include <asm/user.h>
+ #include "skas.h"
+ 
+@@ -96,12 +95,7 @@ typedef struct user_i387_struct elf_fpregset_t;
+ 	(pr_reg)[25] = 0;					\
+ 	(pr_reg)[26] = 0;
+ 
+-static inline int elf_core_copy_fpregs(struct task_struct *t,
+-				       elf_fpregset_t *fpu)
+-{
+-	int cpu = current_thread->cpu;
+-	return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+-}
++extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
+ 
+ #define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
+ 
+diff --git a/include/asm-um/fixmap.h b/include/asm-um/fixmap.h
+index d352a35..89a87c1 100644
+--- a/include/asm-um/fixmap.h
++++ b/include/asm-um/fixmap.h
+@@ -1,9 +1,10 @@
+ #ifndef __UM_FIXMAP_H
+ #define __UM_FIXMAP_H
+ 
++#include <asm/system.h>
+ #include <asm/kmap_types.h>
+ #include <asm/archparam.h>
+-#include <asm/elf.h>
++#include <asm/page.h>
+ 
+ /*
+  * Here we define all the compile-time 'special' virtual
+@@ -55,9 +56,8 @@ extern void __set_fixmap (enum fixed_addresses idx,
+  * the start of the fixmap, and leave one page empty
+  * at the top of mem..
+  */
+-extern unsigned long get_kmem_end(void);
+ 
+-#define FIXADDR_TOP	(get_kmem_end() - 0x2000)
++#define FIXADDR_TOP	(CONFIG_TOP_ADDR - 2 * PAGE_SIZE)
+ #define FIXADDR_SIZE	(__end_of_fixed_addresses << PAGE_SHIFT)
+ #define FIXADDR_START	(FIXADDR_TOP - FIXADDR_SIZE)
+ 
+diff --git a/include/asm-um/ldt.h b/include/asm-um/ldt.h
+index b2553f3..52af512 100644
+--- a/include/asm-um/ldt.h
++++ b/include/asm-um/ldt.h
+@@ -8,7 +8,7 @@
+ #ifndef __ASM_LDT_H
+ #define __ASM_LDT_H
+ 
+-#include "asm/semaphore.h"
++#include <linux/mutex.h>
+ #include "asm/host_ldt.h"
+ 
+ extern void ldt_host_info(void);
+@@ -27,7 +27,7 @@ struct ldt_entry {
+ 
+ typedef struct uml_ldt {
+ 	int entry_count;
+-	struct semaphore semaphore;
++	struct mutex lock;
+ 	union {
+ 		struct ldt_entry * pages[LDT_PAGES_MAX];
+ 		struct ldt_entry entries[LDT_DIRECT_ENTRIES];
+diff --git a/include/asm-um/linkage.h b/include/asm-um/linkage.h
+index 78b8624..7dfce37 100644
+--- a/include/asm-um/linkage.h
++++ b/include/asm-um/linkage.h
+@@ -3,11 +3,4 @@
+ 
+ #include "asm/arch/linkage.h"
+ 
+-
+-/* <linux/linkage.h> will pick sane defaults */
+-#ifdef CONFIG_GPROF
+-#undef FASTCALL
+-#undef fastcall
+-#endif
+-
+ #endif
+diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h
+index 5f3b863..6686fc5 100644
+--- a/include/asm-um/mmu_context.h
++++ b/include/asm-um/mmu_context.h
+@@ -6,11 +6,12 @@
+ #ifndef __UM_MMU_CONTEXT_H
+ #define __UM_MMU_CONTEXT_H
+ 
+-#include <asm-generic/mm_hooks.h>
+-
+ #include "linux/sched.h"
+ #include "um_mmu.h"
+ 
++extern void arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm);
++extern void arch_exit_mmap(struct mm_struct *mm);
++
+ #define get_mmu_context(task) do ; while(0)
+ #define activate_context(tsk) do ; while(0)
+ 
+@@ -30,6 +31,8 @@ static inline void activate_mm(struct mm_struct *old, struct mm_struct *new)
+ 	 */
+ 	if (old != new && (current->flags & PF_BORROWED_MM))
+ 		__switch_mm(&new->context.id);
++
++	arch_dup_mmap(old, new);
+ }
+ 
+ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 
+diff --git a/include/asm-um/nops.h b/include/asm-um/nops.h
+new file mode 100644
+index 0000000..814e9bf
+--- /dev/null
++++ b/include/asm-um/nops.h
+@@ -0,0 +1,6 @@
++#ifndef __UM_NOPS_H
++#define __UM_NOPS_H
++
++#include "asm/arch/nops.h"
++
++#endif
+diff --git a/include/asm-um/page.h b/include/asm-um/page.h
+index 4b424c7..fe2374d 100644
+--- a/include/asm-um/page.h
++++ b/include/asm-um/page.h
+@@ -30,7 +30,7 @@ struct page;
+ #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;
++typedef struct { unsigned long pmd; } pmd_t;
+ typedef struct { unsigned long pgd; } pgd_t;
+ #define pte_val(x) ((x).pte_low | ((unsigned long long) (x).pte_high << 32))
+ 
+@@ -106,8 +106,8 @@ extern unsigned long uml_physmem;
+ #define __pa(virt) to_phys((void *) (unsigned long) (virt))
+ #define __va(phys) to_virt((unsigned long) (phys))
+ 
+-#define phys_to_pfn(p) ((p) >> PAGE_SHIFT)
+-#define pfn_to_phys(pfn) ((pfn) << PAGE_SHIFT)
++#define phys_to_pfn(p) ((pfn_t) ((p) >> PAGE_SHIFT))
++#define pfn_to_phys(pfn) ((phys_t) ((pfn) << PAGE_SHIFT))
+ 
+ #define pfn_valid(pfn) ((pfn) < max_mapnr)
+ #define virt_addr_valid(v) pfn_valid(phys_to_pfn(__pa(v)))
+diff --git a/include/asm-um/param.h b/include/asm-um/param.h
+index f914e7d..4cd4a22 100644
+--- a/include/asm-um/param.h
++++ b/include/asm-um/param.h
+@@ -10,7 +10,7 @@
+ #define MAXHOSTNAMELEN  64      /* max length of hostname */
+ 
+ #ifdef __KERNEL__
+-#define HZ 100
++#define HZ CONFIG_HZ
+ #define USER_HZ	100	   /* .. some user interfaces are in "ticks" */
+ #define CLOCKS_PER_SEC (USER_HZ)  /* frequency at which times() counts */
+ #endif
+diff --git a/include/asm-um/pgalloc.h b/include/asm-um/pgalloc.h
+index 1490487..4f3e62b 100644
+--- a/include/asm-um/pgalloc.h
++++ b/include/asm-um/pgalloc.h
+@@ -23,17 +23,17 @@
+  * Allocate and free page tables.
+  */
+ extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(pgd_t *pgd);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+ 
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long) pte);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ }
+@@ -42,7 +42,7 @@ static inline void pte_free(struct page *pte)
+ 
+ #ifdef CONFIG_3_LEVEL_PGTABLES
+ 
+-static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	free_page((unsigned long)pmd);
+ }
+diff --git a/include/asm-um/pgtable-2level.h b/include/asm-um/pgtable-2level.h
+index 172a75f..f534b73 100644
+--- a/include/asm-um/pgtable-2level.h
++++ b/include/asm-um/pgtable-2level.h
+@@ -41,9 +41,6 @@ static inline void pgd_mkuptodate(pgd_t pgd)	{ }
+ #define pfn_pte(pfn, prot) __pte(pfn_to_phys(pfn) | pgprot_val(prot))
+ #define pfn_pmd(pfn, prot) __pmd(pfn_to_phys(pfn) | pgprot_val(prot))
+ 
+-#define pmd_page_vaddr(pmd) \
+-	((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+-
+ /*
+  * Bits 0 through 4 are taken
+  */
+diff --git a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
+index 3ebafba..0446f45 100644
+--- a/include/asm-um/pgtable-3level.h
++++ b/include/asm-um/pgtable-3level.h
+@@ -11,7 +11,11 @@
+ 
+ /* PGDIR_SHIFT determines what a third-level page table entry can map */
+ 
++#ifdef CONFIG_64BIT
+ #define PGDIR_SHIFT	30
++#else
++#define PGDIR_SHIFT	31
++#endif
+ #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+ #define PGDIR_MASK	(~(PGDIR_SIZE-1))
+ 
+@@ -28,9 +32,15 @@
+  */
+ 
+ #define PTRS_PER_PTE 512
++#ifdef CONFIG_64BIT
+ #define PTRS_PER_PMD 512
+-#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
+ #define PTRS_PER_PGD 512
++#else
++#define PTRS_PER_PMD 1024
++#define PTRS_PER_PGD 1024
++#endif
++
++#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
+ #define FIRST_USER_ADDRESS	0
+ 
+ #define pte_ERROR(e) \
+@@ -49,7 +59,12 @@
+ #define pud_populate(mm, pud, pmd) \
+ 	set_pud(pud, __pud(_PAGE_TABLE + __pa(pmd)))
+ 
++#ifdef CONFIG_64BIT
+ #define set_pud(pudptr, pudval) set_64bit((phys_t *) (pudptr), pud_val(pudval))
++#else
++#define set_pud(pudptr, pudval) (*(pudptr) = (pudval))
++#endif
++
+ static inline int pgd_newpage(pgd_t pgd)
+ {
+ 	return(pgd_val(pgd) & _PAGE_NEWPAGE);
+@@ -57,17 +72,14 @@ static inline int pgd_newpage(pgd_t pgd)
+ 
+ static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
+ 
++#ifdef CONFIG_64BIT
+ #define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval))
++#else
++#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
++#endif
+ 
+-static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
+-{
+-        pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+-
+-        if(pmd)
+-                memset(pmd, 0, PAGE_SIZE);
+-
+-        return pmd;
+-}
++struct mm_struct;
++extern pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address);
+ 
+ static inline void pud_clear (pud_t *pud)
+ {
+@@ -75,8 +87,7 @@ static inline void pud_clear (pud_t *pud)
+ }
+ 
+ #define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
+-#define pud_page_vaddr(pud) \
+-	((struct page *) __va(pud_val(pud) & PAGE_MASK))
++#define pud_page_vaddr(pud) ((unsigned long) __va(pud_val(pud) & PAGE_MASK))
+ 
+ /* Find an entry in the second-level page table.. */
+ #define pmd_offset(pud, address) ((pmd_t *) pud_page_vaddr(*(pud)) + \
+diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
+index 830fc6e..4102b44 100644
+--- a/include/asm-um/pgtable.h
++++ b/include/asm-um/pgtable.h
+@@ -1,5 +1,5 @@
+ /* 
+- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike at karaya.com)
++ * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Copyright 2003 PathScale, Inc.
+  * Derived from include/asm-i386/pgtable.h
+  * Licensed under the GPL
+@@ -8,11 +8,7 @@
+ #ifndef __UM_PGTABLE_H
+ #define __UM_PGTABLE_H
+ 
+-#include "linux/sched.h"
+-#include "linux/linkage.h"
+-#include "asm/processor.h"
+-#include "asm/page.h"
+-#include "asm/fixmap.h"
++#include <asm/fixmap.h>
+ 
+ #define _PAGE_PRESENT	0x001
+ #define _PAGE_NEWPAGE	0x002
+@@ -34,22 +30,11 @@
+ 
+ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+ 
+-extern void *um_virt_to_phys(struct task_struct *task, unsigned long virt,
+-			     pte_t *pte_out);
+-
+ /* zero page used for uninitialized stuff */
+ extern unsigned long *empty_zero_page;
+ 
+ #define pgtable_cache_init() do ; while (0)
+ 
+-/*
+- * pgd entries used up by user/kernel:
+- */
+-
+-#define USER_PGD_PTRS (TASK_SIZE >> PGDIR_SHIFT)
+-#define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+-
+-#ifndef __ASSEMBLY__
+ /* 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
+@@ -62,16 +47,12 @@ extern unsigned long end_iomem;
+ 
+ #define VMALLOC_OFFSET	(__va_space)
+ #define VMALLOC_START ((end_iomem + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+-
+ #ifdef CONFIG_HIGHMEM
+ # define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
+ #else
+ # define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
+ #endif
+ 
+-#define REGION_SHIFT	(sizeof(pte_t) * 8 - 4)
+-#define REGION_MASK	(((unsigned long) 0xf) << REGION_SHIFT)
+-
+ #define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+ #define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+ #define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+@@ -81,11 +62,12 @@ extern unsigned long end_iomem;
+ #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+ #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+ #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+-#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
+ 
+ /*
+- * The i386 can't do page protection for execute, and considers that the same are read.
+- * Also, write permissions imply read permissions. This is the closest we can get..
++ * The i386 can't do page protection for execute, and considers that the same
++ * are read.
++ * Also, write permissions imply read permissions. This is the closest we can
++ * get..
+  */
+ #define __P000	PAGE_NONE
+ #define __P001	PAGE_READONLY
+@@ -106,40 +88,16 @@ extern unsigned long end_iomem;
+ #define __S111	PAGE_SHARED
+ 
+ /*
+- * 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 'access_ok(VERIFY_WRITE,..)'
+- */
+-#undef TEST_VERIFY_AREA
+-
+-/* page table for 0-4MB for everybody */
+-extern unsigned long pg0[1024];
+-
+-/*
+  * ZERO_PAGE is a global shared page that is always zero: used
+  * for zero-mapped memory areas etc..
+  */
+-
+ #define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
+ 
+-/* number of bits that fit into a memory pointer */
+-#define BITS_PER_PTR			(8*sizeof(unsigned long))
+-
+-/* to align the pointer to a pointer address */
+-#define PTR_MASK			(~(sizeof(void*)-1))
+-
+-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+-/* 64-bit machines, beware!  SRB. */
+-#define SIZEOF_PTR_LOG2			3
+-
+-/* to find an entry in a page-table */
+-#define PAGE_PTR(address) \
+-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+-
+ #define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
+ 
+ #define pmd_none(x)	(!((unsigned long)pmd_val(x) & ~_PAGE_NEWPAGE))
+ #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++
+ #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+ #define pmd_clear(xp)	do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
+ 
+@@ -149,14 +107,9 @@ extern unsigned long pg0[1024];
+ #define pud_newpage(x)  (pud_val(x) & _PAGE_NEWPAGE)
+ #define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE)
+ 
+-#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+-
+ #define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
+ 
+ #define pte_page(x) pfn_to_page(pte_pfn(x))
+-#define pte_address(x) (__va(pte_val(x) & PAGE_MASK))
+-#define mk_phys(a, r) ((a) + (((unsigned long) r) << REGION_SHIFT))
+-#define phys_addr(p) ((p) & ~REGION_MASK)
+ 
+ #define pte_present(x)	pte_get_bits(x, (_PAGE_PRESENT | _PAGE_PROTNONE))
+ 
+@@ -309,7 +262,8 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
+ 
+ #define phys_to_page(phys) pfn_to_page(phys_to_pfn(phys))
+ #define __virt_to_page(virt) phys_to_page(__pa(virt))
+-#define page_to_phys(page) pfn_to_phys(page_to_pfn(page))
++#define page_to_phys(page) pfn_to_phys((pfn_t) page_to_pfn(page))
++#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+ 
+ #define mk_pte(page, pgprot) \
+ 	({ pte_t pte;					\
+@@ -325,8 +279,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ 	return pte; 
+ }
+ 
+-#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+-
+ /*
+  * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
+  *
+@@ -335,8 +287,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+  */
+ #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+ 
+-#define pgd_index_k(addr) pgd_index(addr)
+-
+ /*
+  * pgd_offset() returns a (pgd_t *)
+  * pgd_index() is used get the offset into the pgd page's array of pgd_t's;
+@@ -355,8 +305,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+  * this macro returns the index of the entry in the pmd page which would
+  * control the given virtual address
+  */
++#define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+ #define pmd_index(address) (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+ 
++#define pmd_page_vaddr(pmd) \
++	((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
++
+ /*
+  * the pte page can be thought of an array like this: pte_t[PTRS_PER_PTE]
+  *
+@@ -372,6 +326,9 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ #define pte_unmap(pte) do { } while (0)
+ #define pte_unmap_nested(pte) do { } while (0)
+ 
++struct mm_struct;
++extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
++
+ #define update_mmu_cache(vma,address,pte) do ; while (0)
+ 
+ /* Encode and de-code a swap entry */
+@@ -388,29 +345,4 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ 
+ #include <asm-generic/pgtable.h>
+ 
+-#include <asm-generic/pgtable-nopud.h>
+-
+-#ifdef CONFIG_HIGHMEM
+-/* Clear a kernel PTE and flush it from the TLB */
+-#define kpte_clear_flush(ptep, vaddr)					\
+-do {									\
+-	pte_clear(&init_mm, vaddr, ptep);				\
+-	__flush_tlb_one(vaddr);						\
+-} while (0)
+ #endif
+-
+-#endif
+-#endif
+-
+-#define virt_to_page(addr) __virt_to_page((const unsigned long) addr)
+-
+-/*
+- * 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/processor-generic.h b/include/asm-um/processor-generic.h
+index 78c0599..b7d9a16 100644
+--- a/include/asm-um/processor-generic.h
++++ b/include/asm-um/processor-generic.h
+@@ -11,6 +11,7 @@ struct pt_regs;
+ struct task_struct;
+ 
+ #include "asm/ptrace.h"
++#include "asm/pgtable.h"
+ #include "registers.h"
+ #include "sysdep/archsetjmp.h"
+ 
+@@ -26,7 +27,6 @@ struct thread_struct {
+ 	 * as of 2.6.11).
+ 	 */
+ 	int forking;
+-	int nsyscalls;
+ 	struct pt_regs regs;
+ 	int singlestep_syscall;
+ 	void *fault_addr;
+@@ -58,7 +58,6 @@ struct thread_struct {
+ #define INIT_THREAD \
+ { \
+ 	.forking		= 0, \
+-	.nsyscalls		= 0, \
+ 	.regs		   	= EMPTY_REGS,	\
+ 	.fault_addr		= NULL, \
+ 	.prev_sched		= NULL, \
+@@ -68,10 +67,6 @@ struct thread_struct {
+ 	.request		= { 0 } \
+ }
+ 
+-typedef struct {
+-	unsigned long seg;
+-} mm_segment_t;
+-
+ extern struct task_struct *alloc_task_struct(void);
  
- /* Convert a physical address to an address suitable for the GART. */
-diff --git a/include/asm-sparc64/percpu.h b/include/asm-sparc64/percpu.h
-index a1f53a4..bee6459 100644
---- a/include/asm-sparc64/percpu.h
-+++ b/include/asm-sparc64/percpu.h
-@@ -7,7 +7,6 @@ register unsigned long __local_per_cpu_offset asm("g5");
+ static inline void release_thread(struct task_struct *task)
+@@ -97,9 +92,7 @@ static inline void mm_copy_segments(struct mm_struct *from_mm,
+ /*
+  * User space process size: 3GB (default).
+  */
+-extern unsigned long task_size;
+-
+-#define TASK_SIZE	(task_size)
++#define TASK_SIZE (CONFIG_TOP_ADDR & PGDIR_MASK)
  
- #ifdef CONFIG_SMP
+ /* This decides where the kernel will search for a free chunk of vm
+  * space during mmap's.
+@@ -128,6 +121,6 @@ extern struct cpuinfo_um cpu_data[];
  
--#define setup_per_cpu_areas()			do { } while (0)
- extern void real_setup_per_cpu_areas(void);
  
- extern unsigned long __per_cpu_base;
-@@ -16,45 +15,14 @@ extern unsigned long __per_cpu_shift;
- 	(__per_cpu_base + ((unsigned long)(__cpu) << __per_cpu_shift))
- #define per_cpu_offset(x) (__per_cpu_offset(x))
+ #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf)
+-#define get_wchan(p) (0)
++extern unsigned long get_wchan(struct task_struct *p);
  
--/* Separate out the type, so (int[3], foo) works. */
--#define DEFINE_PER_CPU(type, name) \
--    __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
--
--#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name)		\
--    __attribute__((__section__(".data.percpu.shared_aligned"))) \
--    __typeof__(type) per_cpu__##name				\
--    ____cacheline_aligned_in_smp
--
--/* var is in discarded region: offset to particular copy we want */
--#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset(cpu)))
--#define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
--#define __raw_get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __local_per_cpu_offset))
--
--/* A macro to avoid #include hell... */
--#define percpu_modcopy(pcpudst, src, size)			\
--do {								\
--	unsigned int __i;					\
--	for_each_possible_cpu(__i)				\
--		memcpy((pcpudst)+__per_cpu_offset(__i),		\
--		       (src), (size));				\
--} while (0)
-+#define __my_cpu_offset __local_per_cpu_offset
-+
- #else /* ! SMP */
+ #endif
+diff --git a/include/asm-um/processor-i386.h b/include/asm-um/processor-i386.h
+index 595f1c3..a2b7fe1 100644
+--- a/include/asm-um/processor-i386.h
++++ b/include/asm-um/processor-i386.h
+@@ -10,7 +10,6 @@
+ #include "asm/host_ldt.h"
+ #include "asm/segment.h"
  
- #define real_setup_per_cpu_areas()		do { } while (0)
--#define DEFINE_PER_CPU(type, name) \
--    __typeof__(type) per_cpu__##name
--#define DEFINE_PER_CPU_SHARED_ALIGNED(type, name)	\
--    DEFINE_PER_CPU(type, name)
--
--#define per_cpu(var, cpu)			(*((void)cpu, &per_cpu__##var))
--#define __get_cpu_var(var)			per_cpu__##var
--#define __raw_get_cpu_var(var)			per_cpu__##var
+-extern int host_has_xmm;
+ extern int host_has_cmov;
  
- #endif	/* SMP */
+ /* include faultinfo structure */
+diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
+index 6e5fd5c..356b83e 100644
+--- a/include/asm-um/thread_info.h
++++ b/include/asm-um/thread_info.h
+@@ -1,5 +1,5 @@
+-/* 
+- * Copyright (C) 2002 Jeff Dike (jdike at karaya.com)
++/*
++ * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
+  * Licensed under the GPL
+  */
  
--#define DECLARE_PER_CPU(type, name) extern __typeof__(type) per_cpu__##name
--
--#define EXPORT_PER_CPU_SYMBOL(var) EXPORT_SYMBOL(per_cpu__##var)
--#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
-+#include <asm-generic/percpu.h>
+@@ -8,8 +8,9 @@
  
- #endif /* __ARCH_SPARC64_PERCPU__ */
-diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h
-index 986441d..44a625a 100644
---- a/include/asm-sparc64/socket.h
-+++ b/include/asm-sparc64/socket.h
-@@ -57,4 +57,5 @@
- #define SO_SECURITY_ENCRYPTION_TRANSPORT	0x5002
- #define SO_SECURITY_ENCRYPTION_NETWORK		0x5004
+ #ifndef __ASSEMBLY__
  
-+#define SO_MARK			0x0022
- #endif /* _ASM_SOCKET_H */
-diff --git a/include/asm-um/asm.h b/include/asm-um/asm.h
-new file mode 100644
-index 0000000..af1269a
---- /dev/null
-+++ b/include/asm-um/asm.h
-@@ -0,0 +1,6 @@
-+#ifndef __UM_ASM_H
-+#define __UM_ASM_H
+-#include <asm/processor.h>
+ #include <asm/types.h>
++#include <asm/page.h>
++#include <asm/uaccess.h>
+ 
+ struct thread_info {
+ 	struct task_struct	*task;		/* main task structure */
+@@ -75,8 +76,8 @@ static inline struct thread_info *current_thread_info(void)
+ #define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+ #define TIF_SIGPENDING		1	/* signal pending */
+ #define TIF_NEED_RESCHED	2	/* rescheduling necessary */
+-#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling 
+-					 * TIF_NEED_RESCHED 
++#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling
++					 * TIF_NEED_RESCHED
+ 					 */
+ #define TIF_RESTART_BLOCK 	4
+ #define TIF_MEMDIE	 	5
+diff --git a/include/asm-um/tlb.h b/include/asm-um/tlb.h
+index c640033..39fc475 100644
+--- a/include/asm-um/tlb.h
++++ b/include/asm-um/tlb.h
+@@ -1,6 +1,126 @@
+ #ifndef __UM_TLB_H
+ #define __UM_TLB_H
+ 
+-#include <asm/arch/tlb.h>
++#include <linux/swap.h>
++#include <asm/percpu.h>
++#include <asm/pgalloc.h>
++#include <asm/tlbflush.h>
 +
-+#include "asm/arch/asm.h"
++#define tlb_start_vma(tlb, vma) do { } while (0)
++#define tlb_end_vma(tlb, vma) do { } while (0)
++#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
 +
-+#endif
-diff --git a/include/asm-um/linkage.h b/include/asm-um/linkage.h
-index 78b8624..cdb3024 100644
---- a/include/asm-um/linkage.h
-+++ b/include/asm-um/linkage.h
-@@ -6,7 +6,6 @@
++/* struct mmu_gather is an opaque type used by the mm code for passing around
++ * any data needed by arch specific code for tlb_remove_page.
++ */
++struct mmu_gather {
++	struct mm_struct	*mm;
++	unsigned int		need_flush; /* Really unmapped some ptes? */
++	unsigned long		start;
++	unsigned long		end;
++	unsigned int		fullmm; /* non-zero means full mm flush */
++};
++
++/* Users of the generic TLB shootdown code must declare this storage space. */
++DECLARE_PER_CPU(struct mmu_gather, mmu_gathers);
++
++static inline void __tlb_remove_tlb_entry(struct mmu_gather *tlb, pte_t *ptep,
++					  unsigned long address)
++{
++	if (tlb->start > address)
++		tlb->start = address;
++	if (tlb->end < address + PAGE_SIZE)
++		tlb->end = address + PAGE_SIZE;
++}
++
++static inline void init_tlb_gather(struct mmu_gather *tlb)
++{
++	tlb->need_flush = 0;
++
++	tlb->start = TASK_SIZE;
++	tlb->end = 0;
++
++	if (tlb->fullmm) {
++		tlb->start = 0;
++		tlb->end = TASK_SIZE;
++	}
++}
++
++/* tlb_gather_mmu
++ *	Return a pointer to an initialized struct mmu_gather.
++ */
++static inline struct mmu_gather *
++tlb_gather_mmu(struct mm_struct *mm, unsigned int full_mm_flush)
++{
++	struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
++
++	tlb->mm = mm;
++	tlb->fullmm = full_mm_flush;
++
++	init_tlb_gather(tlb);
++
++	return tlb;
++}
++
++extern void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
++			       unsigned long end);
++
++static inline void
++tlb_flush_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++	if (!tlb->need_flush)
++		return;
++
++	flush_tlb_mm_range(tlb->mm, tlb->start, tlb->end);
++	init_tlb_gather(tlb);
++}
++
++/* tlb_finish_mmu
++ *	Called at the end of the shootdown operation to free up any resources
++ *	that were required.
++ */
++static inline void
++tlb_finish_mmu(struct mmu_gather *tlb, unsigned long start, unsigned long end)
++{
++	tlb_flush_mmu(tlb, start, end);
++
++	/* keep the page table cache within bounds */
++	check_pgt_cache();
++
++	put_cpu_var(mmu_gathers);
++}
++
++/* tlb_remove_page
++ *	Must perform the equivalent to __free_pte(pte_get_and_clear(ptep)),
++ *	while handling the additional races in SMP caused by other CPUs
++ *	caching valid mappings in their TLBs.
++ */
++static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
++{
++	tlb->need_flush = 1;
++	free_page_and_swap_cache(page);
++	return;
++}
++
++/**
++ * tlb_remove_tlb_entry - remember a pte unmapping for later tlb invalidation.
++ *
++ * Record the fact that pte's were really umapped in ->need_flush, so we can
++ * later optimise away the tlb invalidate.   This helps when userspace is
++ * unmapping already-unmapped pages, which happens quite a lot.
++ */
++#define tlb_remove_tlb_entry(tlb, ptep, address)		\
++	do {							\
++		tlb->need_flush = 1;				\
++		__tlb_remove_tlb_entry(tlb, ptep, address);	\
++	} while (0)
++
++#define pte_free_tlb(tlb, ptep) __pte_free_tlb(tlb, ptep)
++
++#define pud_free_tlb(tlb, pudp) __pud_free_tlb(tlb, pudp)
++
++#define pmd_free_tlb(tlb, pmdp) __pmd_free_tlb(tlb, pmdp)
++
++#define tlb_migrate_finish(mm) do {} while (0)
  
- /* <linux/linkage.h> will pick sane defaults */
- #ifdef CONFIG_GPROF
--#undef FASTCALL
- #undef fastcall
  #endif
+diff --git a/include/asm-um/uaccess.h b/include/asm-um/uaccess.h
+index 077032d..b9a895d 100644
+--- a/include/asm-um/uaccess.h
++++ b/include/asm-um/uaccess.h
+@@ -6,7 +6,15 @@
+ #ifndef __UM_UACCESS_H
+ #define __UM_UACCESS_H
  
-diff --git a/include/asm-um/nops.h b/include/asm-um/nops.h
-new file mode 100644
-index 0000000..814e9bf
---- /dev/null
-+++ b/include/asm-um/nops.h
-@@ -0,0 +1,6 @@
-+#ifndef __UM_NOPS_H
-+#define __UM_NOPS_H
+-#include "linux/sched.h"
++#include <asm/errno.h>
++#include <asm/processor.h>
 +
-+#include "asm/arch/nops.h"
++/* thread_info has a mm_segment_t in it, so put the definition up here */
++typedef struct {
++	unsigned long seg;
++} mm_segment_t;
 +
-+#endif
++#include "linux/thread_info.h"
+ 
+ #define VERIFY_READ 0
+ #define VERIFY_WRITE 1
 diff --git a/include/asm-v850/socket.h b/include/asm-v850/socket.h
 index a4c2493..e199a2b 100644
 --- a/include/asm-v850/socket.h
@@ -834013,10 +903771,10 @@
  #endif
 diff --git a/include/asm-x86/asm.h b/include/asm-x86/asm.h
 new file mode 100644
-index 0000000..1a6980a
+index 0000000..90dec0c
 --- /dev/null
 +++ b/include/asm-x86/asm.h
-@@ -0,0 +1,32 @@
+@@ -0,0 +1,39 @@
 +#ifndef _ASM_X86_ASM_H
 +#define _ASM_X86_ASM_H
 +
@@ -834048,6 +903806,13 @@
 +
 +#endif /* CONFIG_X86_32 */
 +
++/* Exception table entry */
++# define _ASM_EXTABLE(from,to) \
++	" .section __ex_table,\"a\"\n" \
++	_ASM_ALIGN "\n" \
++	_ASM_PTR #from "," #to "\n" \
++	" .previous\n"
++
 +#endif /* _ASM_X86_ASM_H */
 diff --git a/include/asm-x86/bitops.h b/include/asm-x86/bitops.h
 index 07e3f6d..1a23ce1 100644
@@ -834744,7 +904509,7 @@
  #include <asm-generic/bitops/minix.h>
  
 diff --git a/include/asm-x86/bitops_64.h b/include/asm-x86/bitops_64.h
-index 766bcc0..48adbf5 100644
+index 766bcc0..aaf1519 100644
 --- a/include/asm-x86/bitops_64.h
 +++ b/include/asm-x86/bitops_64.h
 @@ -5,303 +5,6 @@
@@ -835051,6 +904816,36 @@
  extern long find_first_zero_bit(const unsigned long *addr, unsigned long size);
  extern long find_next_zero_bit(const unsigned long *addr, long size, long offset);
  extern long find_first_bit(const unsigned long *addr, unsigned long size);
+@@ -334,12 +37,6 @@ static inline long __scanbit(unsigned long val, unsigned long max)
+   ((off)+(__scanbit(~(((*(unsigned long *)addr)) >> (off)),(size)-(off)))) : \
+ 	find_next_zero_bit(addr,size,off)))
+ 
+-/* 
+- * Find string of zero bits in a bitmap. -1 when not found.
+- */ 
+-extern unsigned long 
+-find_next_zero_string(unsigned long *bitmap, long start, long nbits, int len);
+-
+ static inline void set_bit_string(unsigned long *bitmap, unsigned long i, 
+ 				  int len) 
+ { 
+@@ -350,16 +47,6 @@ static inline void set_bit_string(unsigned long *bitmap, unsigned long i,
+ 	}
+ } 
+ 
+-static inline void __clear_bit_string(unsigned long *bitmap, unsigned long i, 
+-				    int len) 
+-{ 
+-	unsigned long end = i + len; 
+-	while (i < end) {
+-		__clear_bit(i, bitmap); 
+-		i++;
+-	}
+-} 
+-
+ /**
+  * ffz - find first zero in word.
+  * @word: The word to search
 diff --git a/include/asm-x86/bootparam.h b/include/asm-x86/bootparam.h
 index 19f3ddf..5115135 100644
 --- a/include/asm-x86/bootparam.h
@@ -835087,7 +904882,7 @@
  
  #include <asm-generic/bug.h>
 diff --git a/include/asm-x86/bugs.h b/include/asm-x86/bugs.h
-index aac8317..3fcc30d 100644
+index aac8317..021cbdd 100644
 --- a/include/asm-x86/bugs.h
 +++ b/include/asm-x86/bugs.h
 @@ -1,6 +1,7 @@
@@ -835096,7 +904891,7 @@
  
 -void check_bugs(void);
 +extern void check_bugs(void);
-+extern int ppro_with_ram_bug(void);
++int ppro_with_ram_bug(void);
  
  #endif /* _ASM_X86_BUGS_H */
 diff --git a/include/asm-x86/cacheflush.h b/include/asm-x86/cacheflush.h
@@ -835590,9 +905385,18 @@
 -					(unsigned long long)(n)))
  #endif
 diff --git a/include/asm-x86/compat.h b/include/asm-x86/compat.h
-index 66ba798..b270ee0 100644
+index 66ba798..d3e8f3e 100644
 --- a/include/asm-x86/compat.h
 +++ b/include/asm-x86/compat.h
+@@ -190,7 +190,7 @@ typedef struct user_regs_struct32 compat_elf_gregset_t;
+  * A pointer passed in from user mode. This should not
+  * be used for syscall parameters, just declare them
+  * as pointers because the syscall entry code will have
+- * appropriately comverted them already.
++ * appropriately converted them already.
+  */
+ typedef	u32		compat_uptr_t;
+ 
 @@ -207,7 +207,7 @@ static inline compat_uptr_t ptr_to_compat(void __user *uptr)
  static __inline__ void __user *compat_alloc_user_space(long len)
  {
@@ -835622,10 +905426,10 @@
  #endif
  
 diff --git a/include/asm-x86/cpufeature.h b/include/asm-x86/cpufeature.h
-index b7160a4..3fb7dfa 100644
+index b7160a4..065e929 100644
 --- a/include/asm-x86/cpufeature.h
 +++ b/include/asm-x86/cpufeature.h
-@@ -1,5 +1,207 @@
+@@ -1,5 +1,215 @@
 -#ifdef CONFIG_X86_32
 -# include "cpufeature_32.h"
 +/*
@@ -835634,9 +905438,6 @@
 +#ifndef _ASM_X86_CPUFEATURE_H
 +#define _ASM_X86_CPUFEATURE_H
 +
-+#ifndef __ASSEMBLY__
-+#include <linux/bitops.h>
-+#endif
 +#include <asm/required-features.h>
 +
 +#define NCAPINTS	8	/* N 32-bit words worth of info */
@@ -835679,6 +905480,7 @@
 +#define X86_FEATURE_MP		(1*32+19) /* MP Capable. */
 +#define X86_FEATURE_NX		(1*32+20) /* Execute Disable */
 +#define X86_FEATURE_MMXEXT	(1*32+22) /* AMD MMX extensions */
++#define X86_FEATURE_GBPAGES	(1*32+26) /* GB pages */
 +#define X86_FEATURE_RDTSCP	(1*32+27) /* RDTSCP */
 +#define X86_FEATURE_LM		(1*32+29) /* Long Mode (x86-64) */
 +#define X86_FEATURE_3DNOWEXT	(1*32+30) /* AMD 3DNow! extensions */
@@ -835745,6 +905547,13 @@
 + */
 +#define X86_FEATURE_IDA		(7*32+ 0) /* Intel Dynamic Acceleration */
 +
++#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
++
++#include <linux/bitops.h>
++
++extern const char * const x86_cap_flags[NCAPINTS*32];
++extern const char * const x86_power_flags[32];
++
 +#define cpu_has(c, bit)							\
 +	(__builtin_constant_p(bit) &&					\
 +	 ( (((bit)>>5)==0 && (1UL<<((bit)&31) & REQUIRED_MASK0)) ||	\
@@ -835805,6 +905614,7 @@
 +#define cpu_has_pebs		boot_cpu_has(X86_FEATURE_PEBS)
 +#define cpu_has_clflush		boot_cpu_has(X86_FEATURE_CLFLSH)
 +#define cpu_has_bts		boot_cpu_has(X86_FEATURE_BTS)
++#define cpu_has_gbpages		boot_cpu_has(X86_FEATURE_GBPAGES)
 +
 +#if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 +# define cpu_has_invlpg		1
@@ -835835,6 +905645,8 @@
 +
 +#endif /* CONFIG_X86_64 */
 +
++#endif /* defined(__KERNEL__) && !defined(__ASSEMBLY__) */
++
 +#endif /* _ASM_X86_CPUFEATURE_H */
 diff --git a/include/asm-x86/cpufeature_32.h b/include/asm-x86/cpufeature_32.h
 deleted file mode 100644
@@ -838147,7 +907959,7 @@
  #endif/*__E820_HEADER*/
 diff --git a/include/asm-x86/efi.h b/include/asm-x86/efi.h
 new file mode 100644
-index 0000000..9c68a1f
+index 0000000..ea9734b
 --- /dev/null
 +++ b/include/asm-x86/efi.h
 @@ -0,0 +1,97 @@
@@ -838186,7 +907998,7 @@
 +#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)	\
 +	efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 +
-+#define efi_ioremap(addr, size)			ioremap(addr, size)
++#define efi_ioremap(addr, size)			ioremap_cache(addr, size)
 +
 +#else /* !CONFIG_X86_32 */
 +
@@ -838239,7 +908051,7 @@
 +	efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
 +		  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 +
-+extern void *efi_ioremap(unsigned long offset, unsigned long size);
++extern void *efi_ioremap(unsigned long addr, unsigned long size);
 +
 +#endif /* CONFIG_X86_32 */
 +
@@ -838673,10 +908485,10 @@
 -
 -#endif
 diff --git a/include/asm-x86/futex.h b/include/asm-x86/futex.h
-index 1f4610e..9d91926 100644
+index 1f4610e..cd9f894 100644
 --- a/include/asm-x86/futex.h
 +++ b/include/asm-x86/futex.h
-@@ -1,5 +1,135 @@
+@@ -1,5 +1,124 @@
 -#ifdef CONFIG_X86_32
 -# include "futex_32.h"
 -#else
@@ -838700,11 +908512,8 @@
 +"2:	.section .fixup,\"ax\"\n				\
 +3:	mov	%3, %1\n					\
 +	jmp	2b\n						\
-+	.previous\n						\
-+	.section __ex_table,\"a\"\n				\
-+	.align	8\n"						\
-+	_ASM_PTR "1b,3b\n					\
-+	.previous"						\
++	.previous\n"						\
++	_ASM_EXTABLE(1b,3b)					\
 +	: "=r" (oldval), "=r" (ret), "+m" (*uaddr)		\
 +	: "i" (-EFAULT), "0" (oparg), "1" (0))
 +
@@ -838718,11 +908527,9 @@
 +3:	.section .fixup,\"ax\"\n				\
 +4:	mov	%5, %1\n					\
 +	jmp	3b\n						\
-+	.previous\n						\
-+	.section __ex_table,\"a\"\n				\
-+	.align	8\n"						\
-+	_ASM_PTR "1b,4b,2b,4b\n					\
-+	.previous"						\
++	.previous\n"						\
++	_ASM_EXTABLE(1b,4b)					\
++	_ASM_EXTABLE(2b,4b)					\
 +	: "=&a" (oldval), "=&r" (ret), "+m" (*uaddr),		\
 +	  "=&r" (tem)						\
 +	: "r" (oparg), "i" (-EFAULT), "1" (0))
@@ -838794,18 +908601,12 @@
 +		return -EFAULT;
 +
 +	__asm__ __volatile__(
-+
 +		"1:	lock; cmpxchgl %3, %1			\n"
 +		"2:	.section .fixup, \"ax\"			\n"
 +		"3:	mov     %2, %0				\n"
 +		"	jmp     2b				\n"
 +		"	.previous				\n"
-+
-+		"	.section __ex_table, \"a\"		\n"
-+		"	.align  8				\n"
-+			_ASM_PTR " 1b,3b			\n"
-+		"	.previous				\n"
-+
++		_ASM_EXTABLE(1b,3b)
 +		: "=a" (oldval), "+m" (*uaddr)
 +		: "i" (-EFAULT), "r" (newval), "0" (oldval)
 +		: "memory"
@@ -839146,6 +908947,38 @@
 +#include <gpio.h>
 +
 +#endif /* _ASM_I386_GPIO_H */
+diff --git a/include/asm-x86/highmem.h b/include/asm-x86/highmem.h
+index 13cdcd6..479767c 100644
+--- a/include/asm-x86/highmem.h
++++ b/include/asm-x86/highmem.h
+@@ -38,11 +38,6 @@ extern pte_t *pkmap_page_table;
+  * easily, subsequent pte tables have to be allocated in one physical
+  * chunk of RAM.
+  */
+-#ifdef CONFIG_X86_PAE
+-#define LAST_PKMAP 512
+-#else
+-#define LAST_PKMAP 1024
+-#endif
+ /*
+  * Ordering is:
+  *
+@@ -58,13 +53,12 @@ extern pte_t *pkmap_page_table;
+  * VMALLOC_START
+  * high_memory
+  */
+-#define PKMAP_BASE ( (FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK )
+ #define LAST_PKMAP_MASK (LAST_PKMAP-1)
+ #define PKMAP_NR(virt)  ((virt-PKMAP_BASE) >> PAGE_SHIFT)
+ #define PKMAP_ADDR(nr)  (PKMAP_BASE + ((nr) << PAGE_SHIFT))
+ 
+-extern void * FASTCALL(kmap_high(struct page *page));
+-extern void FASTCALL(kunmap_high(struct page *page));
++extern void *kmap_high(struct page *page);
++extern void kunmap_high(struct page *page);
+ 
+ void *kmap(struct page *page);
+ void kunmap(struct page *page);
 diff --git a/include/asm-x86/hpet.h b/include/asm-x86/hpet.h
 index ad8d6e7..6a9b4ac 100644
 --- a/include/asm-x86/hpet.h
@@ -839178,7 +909011,7 @@
 +#endif
  #endif /* ASM_X86_HPET_H */
 diff --git a/include/asm-x86/hw_irq_32.h b/include/asm-x86/hw_irq_32.h
-index 0bedbdf..6d65fbb 100644
+index 0bedbdf..ea88054 100644
 --- a/include/asm-x86/hw_irq_32.h
 +++ b/include/asm-x86/hw_irq_32.h
 @@ -26,19 +26,19 @@
@@ -839209,6 +909042,15 @@
  #define platform_legacy_irq(irq)	((irq) < 16)
  #endif
  
+@@ -47,7 +47,7 @@ void enable_8259A_irq(unsigned int irq);
+ int i8259A_irq_pending(unsigned int irq);
+ void make_8259A_irq(unsigned int irq);
+ void init_8259A(int aeoi);
+-void FASTCALL(send_IPI_self(int vector));
++void send_IPI_self(int vector);
+ void init_VISWS_APIC_irqs(void);
+ void setup_IO_APIC(void);
+ void disable_IO_APIC(void);
 diff --git a/include/asm-x86/hw_irq_64.h b/include/asm-x86/hw_irq_64.h
 index a470d59..312a58d 100644
 --- a/include/asm-x86/hw_irq_64.h
@@ -839228,10 +909070,10 @@
  extern unsigned long io_apic_irqs;
  
 diff --git a/include/asm-x86/i387.h b/include/asm-x86/i387.h
-index a8bbed3..ba8105c 100644
+index a8bbed3..6b1895c 100644
 --- a/include/asm-x86/i387.h
 +++ b/include/asm-x86/i387.h
-@@ -1,5 +1,360 @@
+@@ -1,5 +1,352 @@
 -#ifdef CONFIG_X86_32
 -# include "i387_32.h"
 +/*
@@ -839249,6 +909091,7 @@
 +#include <linux/sched.h>
 +#include <linux/kernel_stat.h>
 +#include <linux/regset.h>
++#include <asm/asm.h>
 +#include <asm/processor.h>
 +#include <asm/sigcontext.h>
 +#include <asm/user.h>
@@ -839277,10 +909120,7 @@
 +{
 +	asm volatile("1: fwait\n"
 +		     "2:\n"
-+		     "   .section __ex_table,\"a\"\n"
-+		     "	.align 8\n"
-+		     "	.quad 1b,2b\n"
-+		     "	.previous\n");
++		     _ASM_EXTABLE(1b,2b));
 +}
 +
 +static inline int restore_fpu_checking(struct i387_fxsave_struct *fx)
@@ -839293,10 +909133,7 @@
 +		     "3:  movl $-1,%[err]\n"
 +		     "    jmp  2b\n"
 +		     ".previous\n"
-+		     ".section __ex_table,\"a\"\n"
-+		     "   .align 8\n"
-+		     "   .quad  1b,3b\n"
-+		     ".previous"
++		     _ASM_EXTABLE(1b,3b)
 +		     : [err] "=r" (err)
 +#if 0 /* See comment in __save_init_fpu() below. */
 +		     : [fx] "r" (fx), "m" (*fx), "0" (0));
@@ -839335,10 +909172,7 @@
 +		     "3:  movl $-1,%[err]\n"
 +		     "    jmp  2b\n"
 +		     ".previous\n"
-+		     ".section __ex_table,\"a\"\n"
-+		     "   .align 8\n"
-+		     "   .quad  1b,3b\n"
-+		     ".previous"
++		     _ASM_EXTABLE(1b,3b)
 +		     : [err] "=r" (err), "=m" (*fx)
 +#if 0 /* See comment in __fxsave_clear() below. */
 +		     : [fx] "r" (fx), "0" (0));
@@ -840077,7 +909911,7 @@
  void enter_idle(void);
  void exit_idle(void);
 diff --git a/include/asm-x86/io_32.h b/include/asm-x86/io_32.h
-index fe881cd..586d7aa 100644
+index fe881cd..58d2c45 100644
 --- a/include/asm-x86/io_32.h
 +++ b/include/asm-x86/io_32.h
 @@ -100,8 +100,6 @@ static inline void * phys_to_virt(unsigned long address)
@@ -840153,6 +909987,45 @@
  
  #if defined(CONFIG_PARAVIRT)
  #include <asm/paravirt.h>
+@@ -270,29 +275,6 @@ static inline void slow_down_io(void) {
+ 
+ #endif
+ 
+-#ifdef CONFIG_X86_NUMAQ
+-extern void *xquad_portio;    /* Where the IO area was mapped */
+-#define XQUAD_PORT_ADDR(port, quad) (xquad_portio + (XQUAD_PORTIO_QUAD*quad) + port)
+-#define __BUILDIO(bwl,bw,type) \
+-static inline void out##bwl##_quad(unsigned type value, int port, int quad) { \
+-	if (xquad_portio) \
+-		write##bwl(value, XQUAD_PORT_ADDR(port, quad)); \
+-	else \
+-		out##bwl##_local(value, port); \
+-} \
+-static inline void out##bwl(unsigned type value, int port) { \
+-	out##bwl##_quad(value, port, 0); \
+-} \
+-static inline unsigned type in##bwl##_quad(int port, int quad) { \
+-	if (xquad_portio) \
+-		return read##bwl(XQUAD_PORT_ADDR(port, quad)); \
+-	else \
+-		return in##bwl##_local(port); \
+-} \
+-static inline unsigned type in##bwl(int port) { \
+-	return in##bwl##_quad(port, 0); \
+-}
+-#else
+ #define __BUILDIO(bwl,bw,type) \
+ static inline void out##bwl(unsigned type value, int port) { \
+ 	out##bwl##_local(value, port); \
+@@ -300,8 +282,6 @@ static inline void out##bwl(unsigned type value, int port) { \
+ static inline unsigned type in##bwl(int port) { \
+ 	return in##bwl##_local(port); \
+ }
+-#endif
+-
+ 
+ #define BUILDIO(bwl,bw,type) \
+ static inline void out##bwl##_local(unsigned type value, int port) { \
 diff --git a/include/asm-x86/io_64.h b/include/asm-x86/io_64.h
 index a037b07..f64a59c 100644
 --- a/include/asm-x86/io_64.h
@@ -844326,10 +914199,10 @@
 +
 +#endif /* __ASM_MACH_GENERIC_GPIO_H */
 diff --git a/include/asm-x86/mach-numaq/mach_apic.h b/include/asm-x86/mach-numaq/mach_apic.h
-index 5e5e7dd..17e183b 100644
+index 5e5e7dd..3b637fa 100644
 --- a/include/asm-x86/mach-numaq/mach_apic.h
 +++ b/include/asm-x86/mach-numaq/mach_apic.h
-@@ -101,11 +101,11 @@ static inline int mpc_apic_id(struct mpc_config_processor *m,
+@@ -101,14 +101,16 @@ static inline int mpc_apic_id(struct mpc_config_processor *m,
  	int quad = translation_record->trans_quad;
  	int logical_apicid = generate_logical_apicid(quad, m->mpc_apicid);
  
@@ -844346,6 +914219,11 @@
  	return logical_apicid;
  }
  
++extern void *xquad_portio;
++
+ static inline void setup_portio_remap(void)
+ {
+ 	int num_quads = num_online_nodes();
 diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h
 new file mode 100644
 index 0000000..db31b92
@@ -844449,6 +914327,18 @@
  }
  
  static inline void setup_portio_remap(void)
+diff --git a/include/asm-x86/mach-voyager/do_timer.h b/include/asm-x86/mach-voyager/do_timer.h
+index bc2b589..9e5a459 100644
+--- a/include/asm-x86/mach-voyager/do_timer.h
++++ b/include/asm-x86/mach-voyager/do_timer.h
+@@ -6,7 +6,6 @@
+ 
+ /**
+  * do_timer_interrupt_hook - hook into timer tick
+- * @regs:     standard registers from interrupt
+  *
+  * Call the pit clock event handler. see asm/i8253.h
+  **/
 diff --git a/include/asm-x86/math_emu.h b/include/asm-x86/math_emu.h
 index a4b0aa3..9bf4ae9 100644
 --- a/include/asm-x86/math_emu.h
@@ -845744,10 +915634,10 @@
  #define MSR_K8_TOP_MEM1			0xc001001a
  #define MSR_K8_TOP_MEM2			0xc001001d
 diff --git a/include/asm-x86/msr.h b/include/asm-x86/msr.h
-index 80b0270..204a8a3 100644
+index 80b0270..3ca29eb 100644
 --- a/include/asm-x86/msr.h
 +++ b/include/asm-x86/msr.h
-@@ -7,77 +7,109 @@
+@@ -7,77 +7,103 @@
  # include <linux/types.h>
  #endif
  
@@ -845809,13 +915699,12 @@
 -		     "3:  movl %3,%0 ; jmp 1b\n\t"
 +		     "3:  mov %3,%0 ; jmp 1b\n\t"
  		     ".previous\n\t"
- 		     ".section __ex_table,\"a\"\n"
+-		     ".section __ex_table,\"a\"\n"
 -		     "   .align 4\n\t"
 -		     "   .long	2b,3b\n\t"
-+		     _ASM_ALIGN "\n\t"
-+		     _ASM_PTR " 2b,3b\n\t"
- 		     ".previous"
+-		     ".previous"
 -		     : "=r" (*err), "=A" (val)
++		     _ASM_EXTABLE(2b,3b)
 +		     : "=r" (*err), EAX_EDX_RET(val, low, high)
  		     : "c" (msr), "i" (-EFAULT));
 -
@@ -845843,12 +915732,11 @@
 -		     "3:  movl %4,%0 ; jmp 1b\n\t"
 +		     "3:  mov %4,%0 ; jmp 1b\n\t"
  		     ".previous\n\t"
- 		     ".section __ex_table,\"a\"\n"
+-		     ".section __ex_table,\"a\"\n"
 -		     "   .align 4\n\t"
 -		     "   .long	2b,3b\n\t"
-+		     _ASM_ALIGN "\n\t"
-+		     _ASM_PTR " 2b,3b\n\t"
- 		     ".previous"
+-		     ".previous"
++		     _ASM_EXTABLE(2b,3b)
  		     : "=a" (err)
 -		     : "c" (msr), "0" ((u32)val), "d" ((u32)(val>>32)),
 +		     : "c" (msr), "0" (low), "d" (high),
@@ -845886,7 +915774,7 @@
  }
  
  #ifdef CONFIG_PARAVIRT
-@@ -97,20 +129,21 @@ static inline unsigned long long native_read_pmc(void)
+@@ -97,20 +123,21 @@ static inline unsigned long long native_read_pmc(void)
  		(val2) = (u32)(__val >> 32);				\
  	} while(0)
  
@@ -845913,7 +915801,7 @@
  }
  
  /* rdmsr with exception handling */
-@@ -129,204 +162,31 @@ static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high)
+@@ -129,204 +156,31 @@ static inline int wrmsr_safe(u32 __msr, u32 __low, u32 __high)
  #define rdtscll(val)						\
  	((val) = native_read_tsc())
  
@@ -846128,7 +916016,7 @@
  #ifdef CONFIG_SMP
  void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h);
  void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);
-@@ -350,9 +210,8 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
+@@ -350,9 +204,8 @@ static inline int wrmsr_safe_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h)
  	return wrmsr_safe(msr_no, l, h);
  }
  #endif  /* CONFIG_SMP */
@@ -846407,7 +916295,7 @@
 -
  #endif
 diff --git a/include/asm-x86/page.h b/include/asm-x86/page.h
-index a757eb2..c8b30ef 100644
+index a757eb2..1cb7c51 100644
 --- a/include/asm-x86/page.h
 +++ b/include/asm-x86/page.h
 @@ -1,13 +1,183 @@
@@ -846431,8 +916319,8 @@
 +#define PHYSICAL_PAGE_MASK	(PAGE_MASK & __PHYSICAL_MASK)
 +#define PTE_MASK		(_AT(long, PHYSICAL_PAGE_MASK))
 +
-+#define LARGE_PAGE_SIZE		(_AC(1,UL) << PMD_SHIFT)
-+#define LARGE_PAGE_MASK		(~(LARGE_PAGE_SIZE-1))
++#define PMD_PAGE_SIZE		(_AC(1, UL) << PMD_SHIFT)
++#define PMD_PAGE_MASK		(~(PMD_PAGE_SIZE-1))
 +
 +#define HPAGE_SHIFT		PMD_SHIFT
 +#define HPAGE_SIZE		(_AC(1,UL) << HPAGE_SHIFT)
@@ -846890,7 +916778,7 @@
 -#endif /* _I386_PAGE_H */
 +#endif /* _ASM_X86_PAGE_32_H */
 diff --git a/include/asm-x86/page_64.h b/include/asm-x86/page_64.h
-index c3b52bc..c1ac42d 100644
+index c3b52bc..dcf0c07 100644
 --- a/include/asm-x86/page_64.h
 +++ b/include/asm-x86/page_64.h
 @@ -1,15 +1,9 @@
@@ -846911,7 +916799,7 @@
  #define THREAD_SIZE  (PAGE_SIZE << THREAD_ORDER)
  #define CURRENT_MASK (~(THREAD_SIZE-1))
  
-@@ -29,54 +23,7 @@
+@@ -29,54 +23,10 @@
  #define MCE_STACK 5
  #define N_EXCEPTION_STACKS 5  /* hw limit: 7 */
  
@@ -846961,13 +916849,15 @@
 -#define __pud(x) ((pud_t) { (x) } )
 -#define __pgd(x) ((pgd_t) { (x) } )
 -#define __pgprot(x)	((pgprot_t) { (x) } )
--
++#define PUD_PAGE_SIZE		(_AC(1, UL) << PUD_SHIFT)
++#define PUD_PAGE_MASK		(~(PUD_PAGE_SIZE-1))
+ 
 -#endif /* !__ASSEMBLY__ */
 +#define __PAGE_OFFSET           _AC(0xffff810000000000, UL)
  
  #define __PHYSICAL_START	CONFIG_PHYSICAL_START
  #define __KERNEL_ALIGN		0x200000
-@@ -92,53 +39,44 @@ extern unsigned long phys_base;
+@@ -92,53 +42,44 @@ extern unsigned long phys_base;
  
  #define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)
  #define __START_KERNEL_map	_AC(0xffffffff80000000, UL)
@@ -848662,10 +918552,10 @@
 -
 -#endif /* _ASM_X8664_PERCPU_H_ */
 diff --git a/include/asm-x86/pgalloc_32.h b/include/asm-x86/pgalloc_32.h
-index f2fc33c..7641e7b 100644
+index f2fc33c..bab1271 100644
 --- a/include/asm-x86/pgalloc_32.h
 +++ b/include/asm-x86/pgalloc_32.h
-@@ -3,31 +3,34 @@
+@@ -3,66 +3,91 @@
  
  #include <linux/threads.h>
  #include <linux/mm.h>		/* for struct page */
@@ -848714,7 +918604,24 @@
  
  /*
   * Allocate and free page tables.
-@@ -49,20 +52,40 @@ static inline void pte_free(struct page *pte)
+  */
+ extern pgd_t *pgd_alloc(struct mm_struct *);
+-extern void pgd_free(pgd_t *pgd);
++extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
+ 
+ extern pte_t *pte_alloc_one_kernel(struct mm_struct *, unsigned long);
+ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	free_page((unsigned long)pte);
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
  }
  
  
@@ -848739,7 +918646,7 @@
 +	return (pmd_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
 +}
 +
-+static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 +{
 +	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
 +	free_page((unsigned long)pmd);
@@ -848756,8 +918663,10 @@
 +	set_pud(pudp, __pud(__pa(pmd) | _PAGE_PRESENT));
 +
 +	/*
-+	 * Pentium-II erratum A13: in PAE mode we explicitly have to flush
-+	 * the TLB via cr3 if the top-level pgd is changed...
++	 * According to Intel App note "TLBs, Paging-Structure Caches,
++	 * and Their Invalidation", April 2007, document 317080-001,
++	 * section 8.1: in PAE mode we explicitly have to flush the
++	 * TLB via cr3 if the top-level pgd is changed...
 +	 */
 +	if (mm == current->active_mm)
 +		write_cr3(read_cr3());
@@ -848765,6 +918674,53 @@
 +#endif	/* CONFIG_X86_PAE */
  
  #endif /* _I386_PGALLOC_H */
+diff --git a/include/asm-x86/pgalloc_64.h b/include/asm-x86/pgalloc_64.h
+index 8bb5646..315314c 100644
+--- a/include/asm-x86/pgalloc_64.h
++++ b/include/asm-x86/pgalloc_64.h
+@@ -17,7 +17,7 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *p
+ 	set_pmd(pmd, __pmd(_PAGE_TABLE | (page_to_pfn(pte) << PAGE_SHIFT)));
+ }
+ 
+-static inline void pmd_free(pmd_t *pmd)
++static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
+ {
+ 	BUG_ON((unsigned long)pmd & (PAGE_SIZE-1));
+ 	free_page((unsigned long)pmd);
+@@ -33,7 +33,7 @@ static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr)
+ 	return (pud_t *)get_zeroed_page(GFP_KERNEL|__GFP_REPEAT);
+ }
+ 
+-static inline void pud_free (pud_t *pud)
++static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+ {
+ 	BUG_ON((unsigned long)pud & (PAGE_SIZE-1));
+ 	free_page((unsigned long)pud);
+@@ -77,7 +77,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm)
+ 	return pgd;
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	BUG_ON((unsigned long)pgd & (PAGE_SIZE-1));
+ 	pgd_list_del(pgd);
+@@ -100,13 +100,13 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long add
+ /* Should really implement gc for free page table pages. This could be
+    done with a reference count in struct page. */
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	BUG_ON((unsigned long)pte & (PAGE_SIZE-1));
+ 	free_page((unsigned long)pte); 
+ }
+ 
+-static inline void pte_free(struct page *pte)
++static inline void pte_free(struct mm_struct *mm, struct page *pte)
+ {
+ 	__free_page(pte);
+ } 
 diff --git a/include/asm-x86/pgtable-2level.h b/include/asm-x86/pgtable-2level.h
 index 84b03cf..701404f 100644
 --- a/include/asm-x86/pgtable-2level.h
@@ -848850,7 +918806,7 @@
  
  #endif /* _I386_PGTABLE_2LEVEL_H */
 diff --git a/include/asm-x86/pgtable-3level.h b/include/asm-x86/pgtable-3level.h
-index 948a334..a195c3e 100644
+index 948a334..1d763ee 100644
 --- a/include/asm-x86/pgtable-3level.h
 +++ b/include/asm-x86/pgtable-3level.h
 @@ -15,16 +15,18 @@
@@ -848901,7 +918857,7 @@
  }
  
  /*
-@@ -94,24 +91,29 @@ static inline void native_pmd_clear(pmd_t *pmd)
+@@ -94,24 +91,25 @@ static inline void native_pmd_clear(pmd_t *pmd)
  	*(tmp + 1) = 0;
  }
  
@@ -848925,31 +918881,27 @@
 -static inline void pud_clear (pud_t * pud) { }
 +static inline void pud_clear(pud_t *pudp)
 +{
++	unsigned long pgd;
++
 +	set_pud(pudp, __pud(0));
 +
 +	/*
-+	 * In principle we need to do a cr3 reload here to make sure
-+	 * the processor recognizes the changed pgd.  In practice, all
-+	 * the places where pud_clear() gets called are followed by
-+	 * full tlb flushes anyway, so we can defer the cost here.
-+	 *
-+	 * Specifically:
++	 * According to Intel App note "TLBs, Paging-Structure Caches,
++	 * and Their Invalidation", April 2007, document 317080-001,
++	 * section 8.1: in PAE mode we explicitly have to flush the
++	 * TLB via cr3 if the top-level pgd is changed...
 +	 *
-+	 * mm/memory.c:free_pmd_range() - immediately after the
-+	 * pud_clear() it does a pmd_free_tlb().  We change the
-+	 * mmu_gather structure to do a full tlb flush (which has the
-+	 * effect of reloading cr3) when the pagetable free is
-+	 * complete.
-+	 *
-+	 * arch/x86/mm/hugetlbpage.c:huge_pmd_unshare() - the call to
-+	 * this is followed by a flush_tlb_range, which on x86 does a
-+	 * full tlb flush.
++	 * Make sure the pud entry we're updating is within the
++	 * current pgd to avoid unnecessary TLB flushes.
 +	 */
++	pgd = read_cr3();
++	if (__pa(pudp) >= pgd && __pa(pudp) < (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
++		write_cr3(pgd);
 +}
  
  #define pud_page(pud) \
  ((struct page *) __va(pud_val(pud) & PAGE_MASK))
-@@ -155,21 +157,7 @@ static inline int pte_none(pte_t pte)
+@@ -155,21 +153,7 @@ static inline int pte_none(pte_t pte)
  
  static inline unsigned long pte_pfn(pte_t pte)
  {
@@ -848972,7 +918924,7 @@
  }
  
  /*
-@@ -177,7 +165,7 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+@@ -177,7 +161,7 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
   * put the 32 bits of offset into the high part.
   */
  #define pte_to_pgoff(pte) ((pte).pte_high)
@@ -848981,7 +918933,7 @@
  #define PTE_FILE_MAX_BITS       32
  
  /* Encode and de-code a swap entry */
-@@ -185,8 +173,6 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
+@@ -185,8 +169,6 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
  #define __swp_offset(x)			((x).val >> 5)
  #define __swp_entry(type, offset)	((swp_entry_t){(type) | (offset) << 5})
  #define __pte_to_swp_entry(pte)		((swp_entry_t){ (pte).pte_high })
@@ -848992,10 +918944,10 @@
  
  #endif /* _I386_PGTABLE_3LEVEL_H */
 diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
-index 1039140..cd2524f 100644
+index 1039140..44c0a4f 100644
 --- a/include/asm-x86/pgtable.h
 +++ b/include/asm-x86/pgtable.h
-@@ -1,5 +1,364 @@
+@@ -1,5 +1,368 @@
 +#ifndef _ASM_X86_PGTABLE_H
 +#define _ASM_X86_PGTABLE_H
 +
@@ -849011,10 +918963,12 @@
 +#define _PAGE_BIT_DIRTY		6
 +#define _PAGE_BIT_FILE		6
 +#define _PAGE_BIT_PSE		7	/* 4 MB (or 2MB) page */
++#define _PAGE_BIT_PAT		7	/* on 4KB pages */
 +#define _PAGE_BIT_GLOBAL	8	/* Global TLB entry PPro+ */
 +#define _PAGE_BIT_UNUSED1	9	/* available for programmer */
 +#define _PAGE_BIT_UNUSED2	10
 +#define _PAGE_BIT_UNUSED3	11
++#define _PAGE_BIT_PAT_LARGE	12	/* On 2MB or 1GB pages */
 +#define _PAGE_BIT_NX           63       /* No execute: only valid after cpuid check */
 +
 +/*
@@ -849034,6 +918988,8 @@
 +#define _PAGE_UNUSED1	(_AC(1, L)<<_PAGE_BIT_UNUSED1)
 +#define _PAGE_UNUSED2	(_AC(1, L)<<_PAGE_BIT_UNUSED2)
 +#define _PAGE_UNUSED3	(_AC(1, L)<<_PAGE_BIT_UNUSED3)
++#define _PAGE_PAT	(_AC(1, L)<<_PAGE_BIT_PAT)
++#define _PAGE_PAT_LARGE (_AC(1, L)<<_PAGE_BIT_PAT_LARGE)
 +
 +#if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE)
 +#define _PAGE_NX	(_AC(1, ULL) << _PAGE_BIT_NX)
@@ -849361,7 +919317,7 @@
 +
 +#endif	/* _ASM_X86_PGTABLE_H */
 diff --git a/include/asm-x86/pgtable_32.h b/include/asm-x86/pgtable_32.h
-index ed3e70d..21e70fb 100644
+index ed3e70d..80dd438 100644
 --- a/include/asm-x86/pgtable_32.h
 +++ b/include/asm-x86/pgtable_32.h
 @@ -25,20 +25,11 @@
@@ -849396,10 +919352,17 @@
  #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
  #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
  
-@@ -85,113 +73,6 @@ void paging_init(void);
- #endif
- 
- /*
+@@ -78,118 +66,19 @@ void paging_init(void);
+ #define VMALLOC_OFFSET	(8*1024*1024)
+ #define VMALLOC_START	(((unsigned long) high_memory + \
+ 			2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1))
+-#ifdef CONFIG_HIGHMEM
+-# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
+-#else
+-# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
+-#endif
+-
+-/*
 - * _PAGE_PSE set in the page directory entry just means that
 - * the page directory entry points directly to a 4MB-aligned block of
 - * memory. 
@@ -849435,12 +919398,14 @@
 -#define _PAGE_FILE	0x040	/* nonlinear file mapping, saved PTE; unset:swap */
 -#define _PAGE_PROTNONE	0x080	/* if the user mapped it with PROT_NONE;
 -				   pte_present gives true */
--#ifdef CONFIG_X86_PAE
+ #ifdef CONFIG_X86_PAE
 -#define _PAGE_NX	(1ULL<<_PAGE_BIT_NX)
--#else
++#define LAST_PKMAP 512
+ #else
 -#define _PAGE_NX	0
--#endif
--
++#define LAST_PKMAP 1024
+ #endif
+ 
 -#define _PAGE_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
 -#define _KERNPG_TABLE	(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
 -#define _PAGE_CHG_MASK	(PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
@@ -849482,7 +919447,8 @@
 -#define PAGE_KERNEL_NOCACHE	__pgprot(__PAGE_KERNEL_NOCACHE)
 -#define PAGE_KERNEL_LARGE	__pgprot(__PAGE_KERNEL_LARGE)
 -#define PAGE_KERNEL_LARGE_EXEC	__pgprot(__PAGE_KERNEL_LARGE_EXEC)
--
++#define PKMAP_BASE ((FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK)
+ 
 -/*
 - * The i386 can't do page protection for execute, and considers that
 - * the same are read. Also, write permissions imply read permissions.
@@ -849505,12 +919471,15 @@
 -#define __S101	PAGE_READONLY_EXEC
 -#define __S110	PAGE_SHARED_EXEC
 -#define __S111	PAGE_SHARED_EXEC
--
--/*
++#ifdef CONFIG_HIGHMEM
++# define VMALLOC_END	(PKMAP_BASE-2*PAGE_SIZE)
++#else
++# define VMALLOC_END	(FIXADDR_START-2*PAGE_SIZE)
++#endif
+ 
+ /*
   * 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 'access_ok(VERIFY_WRITE,..)'
-@@ -211,133 +92,12 @@ extern unsigned long pg0[];
+@@ -211,133 +100,12 @@ extern unsigned long pg0[];
  
  #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
  
@@ -849644,7 +919613,7 @@
  /*
   * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
   *
-@@ -367,25 +127,6 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
+@@ -367,25 +135,6 @@ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
  
  #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
  
@@ -849670,7 +919639,16 @@
  /*
   * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD]
   *
-@@ -432,26 +173,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+@@ -407,6 +156,8 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+  */
+ #define pgd_offset_k(address) pgd_offset(&init_mm, address)
+ 
++static inline int pud_large(pud_t pud) { return 0; }
++
+ /*
+  * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD]
+  *
+@@ -432,26 +183,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  #define pmd_page_vaddr(pmd) \
  		((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
  
@@ -849697,7 +919675,7 @@
  #if defined(CONFIG_HIGHPTE)
  #define pte_offset_map(dir, address) \
  	((pte_t *)kmap_atomic_pte(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
-@@ -497,13 +218,17 @@ static inline void paravirt_pagetable_setup_done(pgd_t *base)
+@@ -497,13 +228,17 @@ static inline void paravirt_pagetable_setup_done(pgd_t *base)
  
  #endif /* !__ASSEMBLY__ */
  
@@ -849719,10 +919697,10 @@
 -
  #endif /* _I386_PGTABLE_H */
 diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h
-index 9b0ff47..6e615a1 100644
+index 9b0ff47..bd4740a 100644
 --- a/include/asm-x86/pgtable_64.h
 +++ b/include/asm-x86/pgtable_64.h
-@@ -17,22 +17,16 @@ extern pud_t level3_kernel_pgt[512];
+@@ -17,22 +17,15 @@ extern pud_t level3_kernel_pgt[512];
  extern pud_t level3_ident_pgt[512];
  extern pmd_t level2_kernel_pgt[512];
  extern pgd_t init_level4_pgt[];
@@ -849731,15 +919709,15 @@
  #define swapper_pg_dir init_level4_pgt
  
  extern void paging_init(void);
- extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
- 
+-extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
+-
 -/*
 - * ZERO_PAGE is a global shared page that is always zero: used
 - * for zero-mapped memory areas etc..
 - */
 -extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
 -#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
--
+ 
  #endif /* !__ASSEMBLY__ */
  
 +#define SHARED_KERNEL_PMD	1
@@ -849747,7 +919725,7 @@
  /*
   * PGDIR_SHIFT determines what a top-level page table entry can map
   */
-@@ -71,57 +65,68 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
+@@ -71,57 +64,68 @@ extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)];
  #define pgd_none(x)	(!pgd_val(x))
  #define pud_none(x)	(!pud_val(x))
  
@@ -849756,15 +919734,15 @@
 +
 +static inline void native_pte_clear(struct mm_struct *mm, unsigned long addr,
 +				    pte_t *ptep)
-+{
-+	*ptep = native_make_pte(0);
-+}
-+
-+static inline void native_set_pte(pte_t *ptep, pte_t pte)
  {
 -	pte_val(*dst) = pte_val(val);
 -} 
 -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
++	*ptep = native_make_pte(0);
++}
++
++static inline void native_set_pte(pte_t *ptep, pte_t pte)
++{
 +	*ptep = pte;
 +}
  
@@ -849845,7 +919823,7 @@
  #endif /* !__ASSEMBLY__ */
  
  #define PMD_SIZE	(_AC(1,UL) << PMD_SHIFT)
-@@ -131,8 +136,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
+@@ -131,8 +135,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
  #define PGDIR_SIZE	(_AC(1,UL) << PGDIR_SHIFT)
  #define PGDIR_MASK	(~(PGDIR_SIZE-1))
  
@@ -849854,7 +919832,7 @@
  
  #define MAXMEM		 _AC(0x3fffffffffff, UL)
  #define VMALLOC_START    _AC(0xffffc20000000000, UL)
-@@ -142,91 +145,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
+@@ -142,91 +144,6 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long
  #define MODULES_END      _AC(0xfffffffffff00000, UL)
  #define MODULES_LEN   (MODULES_END - MODULES_VADDR)
  
@@ -849946,7 +919924,7 @@
  #ifndef __ASSEMBLY__
  
  static inline unsigned long pgd_bad(pgd_t pgd)
-@@ -246,66 +164,16 @@ static inline unsigned long pmd_bad(pmd_t pmd)
+@@ -246,66 +163,16 @@ static inline unsigned long pmd_bad(pmd_t pmd)
  
  #define pte_none(x)	(!pte_val(x))
  #define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
@@ -850014,7 +919992,20 @@
  
  /*
   * Conversion functions: convert a page and protection to a page entry,
-@@ -340,29 +208,18 @@ static inline int pmd_large(pmd_t pte) {
+@@ -331,6 +198,12 @@ static inline int pmd_large(pmd_t pte) {
+ #define pud_offset(pgd, address) ((pud_t *) pgd_page_vaddr(*(pgd)) + pud_index(address))
+ #define pud_present(pud) (pud_val(pud) & _PAGE_PRESENT)
+ 
++static inline int pud_large(pud_t pte)
++{
++	return (pud_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) ==
++		(_PAGE_PSE|_PAGE_PRESENT);
++}
++
+ /* PMD  - Level 2 access */
+ #define pmd_page_vaddr(pmd) ((unsigned long) __va(pmd_val(pmd) & PTE_MASK))
+ #define pmd_page(pmd)		(pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
+@@ -340,29 +213,18 @@ static inline int pmd_large(pmd_t pte) {
  			pmd_index(address))
  #define pmd_none(x)	(!pmd_val(x))
  #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -850045,7 +920036,7 @@
  #define pte_index(address) \
  		(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
  #define pte_offset_kernel(dir, address) ((pte_t *) pmd_page_vaddr(*(dir)) + \
-@@ -376,40 +233,20 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+@@ -376,40 +238,20 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
  
  #define update_mmu_cache(vma,address,pte) do { } while (0)
  
@@ -850088,7 +920079,7 @@
  
  #define pgtable_cache_init()   do { } while (0)
  #define check_pgt_cache()      do { } while (0)
-@@ -422,12 +259,7 @@ pte_t *lookup_address(unsigned long addr);
+@@ -422,12 +264,7 @@ pte_t *lookup_address(unsigned long addr);
  #define	kc_offset_to_vaddr(o) \
     (((o) & (1UL << (__VIRTUAL_MASK_SHIFT-1))) ? ((o) | (~__VIRTUAL_MASK)) : (o))
  
@@ -854719,6 +924710,29 @@
  		const struct stacktrace_ops *ops, void *data);
  
  #endif
+diff --git a/include/asm-x86/string_32.h b/include/asm-x86/string_32.h
+index 55bfa30..c5d13a8 100644
+--- a/include/asm-x86/string_32.h
++++ b/include/asm-x86/string_32.h
+@@ -213,14 +213,14 @@ static __always_inline void * __constant_c_and_count_memset(void * s, unsigned l
+ 		case 0:
+ 			return s;
+ 		case 1:
+-			*(unsigned char *)s = pattern;
++			*(unsigned char *)s = pattern & 0xff;
+ 			return s;
+ 		case 2:
+-			*(unsigned short *)s = pattern;
++			*(unsigned short *)s = pattern & 0xffff;
+ 			return s;
+ 		case 3:
+-			*(unsigned short *)s = pattern;
+-			*(2+(unsigned char *)s) = pattern;
++			*(unsigned short *)s = pattern & 0xffff;
++			*(2+(unsigned char *)s) = pattern & 0xff;
+ 			return s;
+ 		case 4:
+ 			*(unsigned long *)s = pattern;
 diff --git a/include/asm-x86/suspend_32.h b/include/asm-x86/suspend_32.h
 index a252073..1bbda3a 100644
 --- a/include/asm-x86/suspend_32.h
@@ -854764,10 +924778,10 @@
  extern int acpi_save_state_mem(void);
  extern char core_restore_code;
 diff --git a/include/asm-x86/system.h b/include/asm-x86/system.h
-index 692562b..ee32ef9 100644
+index 692562b..9cff02f 100644
 --- a/include/asm-x86/system.h
 +++ b/include/asm-x86/system.h
-@@ -1,5 +1,414 @@
+@@ -1,5 +1,409 @@
 +#ifndef _ASM_X86_SYSTEM_H_
 +#define _ASM_X86_SYSTEM_H_
 +
@@ -854790,8 +924804,8 @@
 +#ifdef CONFIG_X86_32
 +
 +struct task_struct; /* one of the stranger aspects of C forward declarations */
-+extern struct task_struct *FASTCALL(__switch_to(struct task_struct *prev,
-+						struct task_struct *next));
++struct task_struct *__switch_to(struct task_struct *prev,
++				struct task_struct *next);
 +
 +/*
 + * Saving eflags is important. It switches not only IOPL between tasks,
@@ -854900,10 +924914,7 @@
 +		"movl %k1, %%" #seg "\n\t"	\
 +		"jmp 2b\n"			\
 +		".previous\n"			\
-+		".section __ex_table,\"a\"\n\t"	\
-+		_ASM_ALIGN "\n\t"		\
-+		_ASM_PTR " 1b,3b\n"		\
-+		".previous"			\
++		_ASM_EXTABLE(1b,3b)		\
 +		: :"r" (value), "r" (0))
 +
 +
@@ -854984,12 +924995,10 @@
 +	/* This could fault if %cr4 does not exist. In x86_64, a cr4 always
 +	 * exists, so it will never fail. */
 +#ifdef CONFIG_X86_32
-+	asm volatile("1: mov %%cr4, %0		\n"
-+		"2:				\n"
-+		".section __ex_table,\"a\"	\n"
-+		".long 1b,2b			\n"
-+		".previous			\n"
-+		: "=r" (val), "=m" (__force_order) : "0" (0));
++	asm volatile("1: mov %%cr4, %0\n"
++		     "2:\n"
++		     _ASM_EXTABLE(1b,2b)
++		     : "=r" (val), "=m" (__force_order) : "0" (0));
 +#else
 +	val = native_read_cr4();
 +#endif
@@ -855046,9 +925055,9 @@
 +
 +#endif /* __KERNEL__ */
 +
-+static inline void clflush(void *__p)
++static inline void clflush(volatile void *__p)
 +{
-+	asm volatile("clflush %0" : "+m" (*(char __force *)__p));
++	asm volatile("clflush %0" : "+m" (*(volatile char __force *)__p));
 +}
 +
 +#define nop() __asm__ __volatile__ ("nop")
@@ -856887,8 +926896,58 @@
 +extern int notsc_setup(char *);
  
  #endif
+diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h
+index d2a4f7b..fcc570e 100644
+--- a/include/asm-x86/uaccess_32.h
++++ b/include/asm-x86/uaccess_32.h
+@@ -8,6 +8,7 @@
+ #include <linux/thread_info.h>
+ #include <linux/prefetch.h>
+ #include <linux/string.h>
++#include <asm/asm.h>
+ #include <asm/page.h>
+ 
+ #define VERIFY_READ 0
+@@ -287,11 +288,8 @@ extern void __put_user_8(void);
+ 		"4:	movl %3,%0\n"				\
+ 		"	jmp 3b\n"				\
+ 		".previous\n"					\
+-		".section __ex_table,\"a\"\n"			\
+-		"	.align 4\n"				\
+-		"	.long 1b,4b\n"				\
+-		"	.long 2b,4b\n"				\
+-		".previous"					\
++		_ASM_EXTABLE(1b,4b)				\
++		_ASM_EXTABLE(2b,4b)				\
+ 		: "=r"(err)					\
+ 		: "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
+ 
+@@ -338,10 +336,7 @@ struct __large_struct { unsigned long buf[100]; };
+ 		"3:	movl %3,%0\n"					\
+ 		"	jmp 2b\n"					\
+ 		".previous\n"						\
+-		".section __ex_table,\"a\"\n"				\
+-		"	.align 4\n"					\
+-		"	.long 1b,3b\n"					\
+-		".previous"						\
++		_ASM_EXTABLE(1b,3b)					\
+ 		: "=r"(err)						\
+ 		: ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
+ 
+@@ -378,10 +373,7 @@ do {									\
+ 		"	xor"itype" %"rtype"1,%"rtype"1\n"		\
+ 		"	jmp 2b\n"					\
+ 		".previous\n"						\
+-		".section __ex_table,\"a\"\n"				\
+-		"	.align 4\n"					\
+-		"	.long 1b,3b\n"					\
+-		".previous"						\
++		_ASM_EXTABLE(1b,3b)					\
+ 		: "=r"(err), ltype (x)					\
+ 		: "m"(__m(addr)), "i"(errret), "0"(err))
+ 
 diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h
-index f4ce876..31d7947 100644
+index f4ce876..b87eb4b 100644
 --- a/include/asm-x86/uaccess_64.h
 +++ b/include/asm-x86/uaccess_64.h
 @@ -65,6 +65,8 @@ struct exception_table_entry
@@ -856900,11 +926959,44 @@
  #define ARCH_HAS_SEARCH_EXTABLE
  
  /*
+@@ -179,10 +181,7 @@ struct __large_struct { unsigned long buf[100]; };
+ 		"3:	mov %3,%0\n"				\
+ 		"	jmp 2b\n"				\
+ 		".previous\n"					\
+-		".section __ex_table,\"a\"\n"			\
+-		"	.align 8\n"				\
+-		"	.quad 1b,3b\n"				\
+-		".previous"					\
++		_ASM_EXTABLE(1b,3b)				\
+ 		: "=r"(err)					\
+ 		: ltype (x), "m"(__m(addr)), "i"(errno), "0"(err))
+ 
+@@ -224,10 +223,7 @@ do {									\
+ 		"	xor"itype" %"rtype"1,%"rtype"1\n"	\
+ 		"	jmp 2b\n"				\
+ 		".previous\n"					\
+-		".section __ex_table,\"a\"\n"			\
+-		"	.align 8\n"				\
+-		"	.quad 1b,3b\n"				\
+-		".previous"					\
++		_ASM_EXTABLE(1b,3b)				\
+ 		: "=r"(err), ltype (x)				\
+ 		: "m"(__m(addr)), "i"(errno), "0"(err))
+ 
 diff --git a/include/asm-x86/unistd_32.h b/include/asm-x86/unistd_32.h
-index 9b15545..8d8f9b5 100644
+index 9b15545..984123a 100644
 --- a/include/asm-x86/unistd_32.h
 +++ b/include/asm-x86/unistd_32.h
-@@ -333,8 +333,6 @@
+@@ -327,14 +327,14 @@
+ #define __NR_epoll_pwait	319
+ #define __NR_utimensat		320
+ #define __NR_signalfd		321
+-#define __NR_timerfd		322
++#define __NR_timerfd_create	322
+ #define __NR_eventfd		323
+ #define __NR_fallocate		324
++#define __NR_timerfd_settime	325
++#define __NR_timerfd_gettime	326
  
  #ifdef __KERNEL__
  
@@ -856913,6 +927005,30 @@
  #define __ARCH_WANT_IPC_PARSE_VERSION
  #define __ARCH_WANT_OLD_READDIR
  #define __ARCH_WANT_OLD_STAT
+diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h
+index 5ff4d3e..3883ceb 100644
+--- a/include/asm-x86/unistd_64.h
++++ b/include/asm-x86/unistd_64.h
+@@ -629,12 +629,17 @@ __SYSCALL(__NR_utimensat, sys_utimensat)
+ __SYSCALL(__NR_epoll_pwait, sys_epoll_pwait)
+ #define __NR_signalfd				282
+ __SYSCALL(__NR_signalfd, sys_signalfd)
+-#define __NR_timerfd				283
+-__SYSCALL(__NR_timerfd, sys_timerfd)
++#define __NR_timerfd_create			283
++__SYSCALL(__NR_timerfd_create, sys_timerfd_create)
+ #define __NR_eventfd				284
+ __SYSCALL(__NR_eventfd, sys_eventfd)
+ #define __NR_fallocate				285
+ __SYSCALL(__NR_fallocate, sys_fallocate)
++#define __NR_timerfd_settime			286
++__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
++#define __NR_timerfd_gettime			287
++__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
++
+ 
+ #ifndef __NO_STUBS
+ #define __ARCH_WANT_OLD_READDIR
 diff --git a/include/asm-x86/user_32.h b/include/asm-x86/user_32.h
 index 0e85d2a..ed8b8fc 100644
 --- a/include/asm-x86/user_32.h
@@ -857053,6 +927169,18 @@
 +#endif
 +
 +#endif	/* asm-x86/vdso.h */
+diff --git a/include/asm-x86/vm86.h b/include/asm-x86/vm86.h
+index a5edf51..c92fe4a 100644
+--- a/include/asm-x86/vm86.h
++++ b/include/asm-x86/vm86.h
+@@ -195,6 +195,7 @@ struct kernel_vm86_struct {
+ 
+ void handle_vm86_fault(struct kernel_vm86_regs *, long);
+ int handle_vm86_trap(struct kernel_vm86_regs *, long, int);
++struct pt_regs *save_v86_state(struct kernel_vm86_regs *);
+ 
+ struct task_struct;
+ void release_vm86_irqs(struct task_struct *);
 diff --git a/include/asm-x86/vsyscall.h b/include/asm-x86/vsyscall.h
 index f01c49f..17b3700 100644
 --- a/include/asm-x86/vsyscall.h
@@ -857114,6 +927242,34 @@
   * Optimized RAID-5 checksumming functions for MMX and SSE.
   *
   * This program is free software; you can redistribute it and/or modify
+diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h
+index 3e5b565..1d51ba5 100644
+--- a/include/asm-xtensa/pgalloc.h
++++ b/include/asm-xtensa/pgalloc.h
+@@ -31,7 +31,7 @@ pgd_alloc(struct mm_struct *mm)
+ 	return (pgd_t*) __get_free_pages(GFP_KERNEL | __GFP_ZERO, PGD_ORDER);
+ }
+ 
+-static inline void pgd_free(pgd_t *pgd)
++static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd)
+ {
+ 	free_page((unsigned long)pgd);
+ }
+@@ -52,12 +52,12 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm,
+ 	return virt_to_page(pte_alloc_one_kernel(mm, addr));
+ }
+ 
+-static inline void pte_free_kernel(pte_t *pte)
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+ {
+ 	kmem_cache_free(pgtable_cache, pte);
+ }
+ 
+-static inline void pte_free(struct page *page)
++static inline void pte_free(struct mm_struct *mm, struct page *page)
+ {
+ 	kmem_cache_free(pgtable_cache, page_address(page));
+ }
 diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h
 index 1f5aeac..6100682 100644
 --- a/include/asm-xtensa/socket.h
@@ -857125,6 +927281,18 @@
 +#define SO_MARK			36
 +
  #endif	/* _XTENSA_SOCKET_H */
+diff --git a/include/asm-xtensa/tlb.h b/include/asm-xtensa/tlb.h
+index 4830232..31c220f 100644
+--- a/include/asm-xtensa/tlb.h
++++ b/include/asm-xtensa/tlb.h
+@@ -42,6 +42,6 @@
+ 
+ #include <asm-generic/tlb.h>
+ 
+-#define __pte_free_tlb(tlb,pte)			pte_free(pte)
++#define __pte_free_tlb(tlb, pte)		pte_free((tlb)->mm, pte)
+ 
+ #endif	/* _XTENSA_TLB_H */
 diff --git a/include/crypto/aead.h b/include/crypto/aead.h
 new file mode 100644
 index 0000000..0edf949
@@ -857899,7 +928067,7 @@
 +#endif	/* _CRYPTO_SKCIPHER_H */
 +
 diff --git a/include/linux/Kbuild b/include/linux/Kbuild
-index f30fa92..c0f9bb7 100644
+index f30fa92..9363122 100644
 --- a/include/linux/Kbuild
 +++ b/include/linux/Kbuild
 @@ -1,4 +1,5 @@
@@ -857972,7 +928140,7 @@
  unifdef-y += binfmts.h
  unifdef-y += capability.h
  unifdef-y += capi.h
-@@ -213,7 +215,7 @@ unifdef-y += hdreg.h
+@@ -213,10 +215,11 @@ unifdef-y += hdreg.h
  unifdef-y += hiddev.h
  unifdef-y += hpet.h
  unifdef-y += i2c.h
@@ -857981,7 +928149,11 @@
  unifdef-y += icmp.h
  unifdef-y += icmpv6.h
  unifdef-y += if_addr.h
-@@ -228,7 +230,6 @@ unifdef-y += if_ltalk.h
++unifdef-y += if_addrlabel.h
+ unifdef-y += if_arp.h
+ unifdef-y += if_bridge.h
+ unifdef-y += if_ec.h
+@@ -228,7 +231,6 @@ unifdef-y += if_ltalk.h
  unifdef-y += if_link.h
  unifdef-y += if_pppol2tp.h
  unifdef-y += if_pppox.h
@@ -857989,7 +928161,7 @@
  unifdef-y += if_tr.h
  unifdef-y += if_tun.h
  unifdef-y += if_vlan.h
-@@ -255,6 +256,7 @@ unifdef-y += kd.h
+@@ -255,6 +257,7 @@ unifdef-y += kd.h
  unifdef-y += kernelcapi.h
  unifdef-y += kernel.h
  unifdef-y += keyboard.h
@@ -857997,7 +928169,7 @@
  unifdef-y += llc.h
  unifdef-y += loop.h
  unifdef-y += lp.h
-@@ -348,6 +350,7 @@ unifdef-y += videodev.h
+@@ -348,6 +351,7 @@ unifdef-y += videodev.h
  unifdef-y += virtio_config.h
  unifdef-y += virtio_blk.h
  unifdef-y += virtio_net.h
@@ -858018,56 +928190,30 @@
  #else
  
  static inline u32 acpi_pm_read_early(void)
-diff --git a/include/linux/aspm.h b/include/linux/aspm.h
-new file mode 100644
-index 0000000..f41a698
---- /dev/null
-+++ b/include/linux/aspm.h
-@@ -0,0 +1,44 @@
-+/*
-+ *	aspm.h
-+ *
-+ *	PCI Express ASPM defines and function prototypes
-+ *
-+ *	Copyright (C) 2007 Intel Corp.
-+ *		Zhang Yanmin (yanmin.zhang at intel.com)
-+ *		Shaohua Li (shaohua.li at intel.com)
-+ *
-+ *	For more information, please consult the following manuals (look at
-+ *	http://www.pcisig.com/ for how to get them):
-+ *
-+ *	PCI Express Specification
-+ */
-+
-+#ifndef LINUX_ASPM_H
-+#define LINUX_ASPM_H
-+
-+#include <linux/pci.h>
-+
-+#define PCIE_LINK_STATE_L0S	1
-+#define PCIE_LINK_STATE_L1	2
-+#define PCIE_LINK_STATE_CLKPM	4
-+
-+#ifdef CONFIG_PCIEASPM
-+extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
-+extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
-+extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
-+extern void pci_disable_link_state(struct pci_dev *pdev, int state);
-+#else
-+#define pcie_aspm_init_link_state(pdev)		do {} while (0)
-+#define pcie_aspm_exit_link_state(pdev)		do {} while (0)
-+#define pcie_aspm_pm_state_change(pdev)		do {} while (0)
-+#define pci_disable_link_state(pdev, state)	do {} while (0)
-+#endif
-+
-+#ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */
-+extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev);
-+extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev);
-+#else
-+#define pcie_aspm_create_sysfs_dev_files(pdev)	do {} while (0)
-+#define pcie_aspm_remove_sysfs_dev_files(pdev)	do {} while (0)
-+#endif
-+#endif /* LINUX_ASPM_H */
+diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
+index abc521c..03e3454 100644
+--- a/include/linux/agp_backend.h
++++ b/include/linux/agp_backend.h
+@@ -109,6 +109,7 @@ extern int agp_unbind_memory(struct agp_memory *);
+ extern void agp_enable(struct agp_bridge_data *, u32);
+ extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *);
+ extern void agp_backend_release(struct agp_bridge_data *);
++extern void agp_flush_chipset(struct agp_bridge_data *);
+ 
+ #endif				/* __KERNEL__ */
+ #endif				/* _AGP_BACKEND_H */
+diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h
+index 09fbf7e..62aef58 100644
+--- a/include/linux/agpgart.h
++++ b/include/linux/agpgart.h
+@@ -38,6 +38,7 @@
+ #define AGPIOC_DEALLOCATE _IOW (AGPIOC_BASE, 7, int)
+ #define AGPIOC_BIND       _IOW (AGPIOC_BASE, 8, struct agp_bind*)
+ #define AGPIOC_UNBIND     _IOW (AGPIOC_BASE, 9, struct agp_unbind*)
++#define AGPIOC_CHIPSET_FLUSH _IO (AGPIOC_BASE, 10)
+ 
+ #define AGP_DEVICE      "/dev/agpgart"
+ 
 diff --git a/include/linux/ata.h b/include/linux/ata.h
 index e672e80..78bbaca 100644
 --- a/include/linux/ata.h
@@ -858370,6 +928516,139 @@
  	}
  }
  
+diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
+new file mode 100644
+index 0000000..fd68337
+--- /dev/null
++++ b/include/linux/atmel_serial.h
+@@ -0,0 +1,127 @@
++/*
++ * include/linux/atmel_serial.h
++ *
++ * Copyright (C) 2005 Ivan Kokshaysky
++ * Copyright (C) SAN People
++ *
++ * USART registers.
++ * Based on AT91RM9200 datasheet revision E.
++ *
++ * 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.
++ */
++
++#ifndef ATMEL_SERIAL_H
++#define ATMEL_SERIAL_H
++
++#define ATMEL_US_CR		0x00			/* Control Register */
++#define		ATMEL_US_RSTRX		(1 <<  2)		/* Reset Receiver */
++#define		ATMEL_US_RSTTX		(1 <<  3)		/* Reset Transmitter */
++#define		ATMEL_US_RXEN		(1 <<  4)		/* Receiver Enable */
++#define		ATMEL_US_RXDIS		(1 <<  5)		/* Receiver Disable */
++#define		ATMEL_US_TXEN		(1 <<  6)		/* Transmitter Enable */
++#define		ATMEL_US_TXDIS		(1 <<  7)		/* Transmitter Disable */
++#define		ATMEL_US_RSTSTA		(1 <<  8)		/* Reset Status Bits */
++#define		ATMEL_US_STTBRK		(1 <<  9)		/* Start Break */
++#define		ATMEL_US_STPBRK		(1 << 10)		/* Stop Break */
++#define		ATMEL_US_STTTO		(1 << 11)		/* Start Time-out */
++#define		ATMEL_US_SENDA		(1 << 12)		/* Send Address */
++#define		ATMEL_US_RSTIT		(1 << 13)		/* Reset Iterations */
++#define		ATMEL_US_RSTNACK	(1 << 14)		/* Reset Non Acknowledge */
++#define		ATMEL_US_RETTO		(1 << 15)		/* Rearm Time-out */
++#define		ATMEL_US_DTREN		(1 << 16)		/* Data Terminal Ready Enable [AT91RM9200 only] */
++#define		ATMEL_US_DTRDIS		(1 << 17)		/* Data Terminal Ready Disable [AT91RM9200 only] */
++#define		ATMEL_US_RTSEN		(1 << 18)		/* Request To Send Enable */
++#define		ATMEL_US_RTSDIS		(1 << 19)		/* Request To Send Disable */
++
++#define ATMEL_US_MR		0x04			/* Mode Register */
++#define		ATMEL_US_USMODE		(0xf <<  0)		/* Mode of the USART */
++#define			ATMEL_US_USMODE_NORMAL		0
++#define			ATMEL_US_USMODE_RS485		1
++#define			ATMEL_US_USMODE_HWHS		2
++#define			ATMEL_US_USMODE_MODEM		3
++#define			ATMEL_US_USMODE_ISO7816_T0	4
++#define			ATMEL_US_USMODE_ISO7816_T1	6
++#define			ATMEL_US_USMODE_IRDA		8
++#define		ATMEL_US_USCLKS		(3   <<  4)		/* Clock Selection */
++#define			ATMEL_US_USCLKS_MCK		(0 <<  4)
++#define			ATMEL_US_USCLKS_MCK_DIV8	(1 <<  4)
++#define			ATMEL_US_USCLKS_SCK		(3 <<  4)
++#define		ATMEL_US_CHRL		(3   <<  6)		/* Character Length */
++#define			ATMEL_US_CHRL_5			(0 <<  6)
++#define			ATMEL_US_CHRL_6			(1 <<  6)
++#define			ATMEL_US_CHRL_7			(2 <<  6)
++#define			ATMEL_US_CHRL_8			(3 <<  6)
++#define		ATMEL_US_SYNC		(1 <<  8)		/* Synchronous Mode Select */
++#define		ATMEL_US_PAR		(7 <<  9)		/* Parity Type */
++#define			ATMEL_US_PAR_EVEN		(0 <<  9)
++#define			ATMEL_US_PAR_ODD		(1 <<  9)
++#define			ATMEL_US_PAR_SPACE		(2 <<  9)
++#define			ATMEL_US_PAR_MARK		(3 <<  9)
++#define			ATMEL_US_PAR_NONE		(4 <<  9)
++#define			ATMEL_US_PAR_MULTI_DROP		(6 <<  9)
++#define		ATMEL_US_NBSTOP		(3 << 12)		/* Number of Stop Bits */
++#define			ATMEL_US_NBSTOP_1		(0 << 12)
++#define			ATMEL_US_NBSTOP_1_5		(1 << 12)
++#define			ATMEL_US_NBSTOP_2		(2 << 12)
++#define		ATMEL_US_CHMODE		(3 << 14)		/* Channel Mode */
++#define			ATMEL_US_CHMODE_NORMAL		(0 << 14)
++#define			ATMEL_US_CHMODE_ECHO		(1 << 14)
++#define			ATMEL_US_CHMODE_LOC_LOOP	(2 << 14)
++#define			ATMEL_US_CHMODE_REM_LOOP	(3 << 14)
++#define		ATMEL_US_MSBF		(1 << 16)		/* Bit Order */
++#define		ATMEL_US_MODE9		(1 << 17)		/* 9-bit Character Length */
++#define		ATMEL_US_CLKO		(1 << 18)		/* Clock Output Select */
++#define		ATMEL_US_OVER		(1 << 19)		/* Oversampling Mode */
++#define		ATMEL_US_INACK		(1 << 20)		/* Inhibit Non Acknowledge */
++#define		ATMEL_US_DSNACK		(1 << 21)		/* Disable Successive NACK */
++#define		ATMEL_US_MAX_ITER	(7 << 24)		/* Max Iterations */
++#define		ATMEL_US_FILTER		(1 << 28)		/* Infrared Receive Line Filter */
++
++#define ATMEL_US_IER		0x08			/* Interrupt Enable Register */
++#define		ATMEL_US_RXRDY		(1 <<  0)		/* Receiver Ready */
++#define		ATMEL_US_TXRDY		(1 <<  1)		/* Transmitter Ready */
++#define		ATMEL_US_RXBRK		(1 <<  2)		/* Break Received / End of Break */
++#define		ATMEL_US_ENDRX		(1 <<  3)		/* End of Receiver Transfer */
++#define		ATMEL_US_ENDTX		(1 <<  4)		/* End of Transmitter Transfer */
++#define		ATMEL_US_OVRE		(1 <<  5)		/* Overrun Error */
++#define		ATMEL_US_FRAME		(1 <<  6)		/* Framing Error */
++#define		ATMEL_US_PARE		(1 <<  7)		/* Parity Error */
++#define		ATMEL_US_TIMEOUT	(1 <<  8)		/* Receiver Time-out */
++#define		ATMEL_US_TXEMPTY	(1 <<  9)		/* Transmitter Empty */
++#define		ATMEL_US_ITERATION	(1 << 10)		/* Max number of Repetitions Reached */
++#define		ATMEL_US_TXBUFE		(1 << 11)		/* Transmission Buffer Empty */
++#define		ATMEL_US_RXBUFF		(1 << 12)		/* Reception Buffer Full */
++#define		ATMEL_US_NACK		(1 << 13)		/* Non Acknowledge */
++#define		ATMEL_US_RIIC		(1 << 16)		/* Ring Indicator Input Change [AT91RM9200 only] */
++#define		ATMEL_US_DSRIC		(1 << 17)		/* Data Set Ready Input Change [AT91RM9200 only] */
++#define		ATMEL_US_DCDIC		(1 << 18)		/* Data Carrier Detect Input Change [AT91RM9200 only] */
++#define		ATMEL_US_CTSIC		(1 << 19)		/* Clear to Send Input Change */
++#define		ATMEL_US_RI		(1 << 20)		/* RI */
++#define		ATMEL_US_DSR		(1 << 21)		/* DSR */
++#define		ATMEL_US_DCD		(1 << 22)		/* DCD */
++#define		ATMEL_US_CTS		(1 << 23)		/* CTS */
++
++#define ATMEL_US_IDR		0x0c			/* Interrupt Disable Register */
++#define ATMEL_US_IMR		0x10			/* Interrupt Mask Register */
++#define ATMEL_US_CSR		0x14			/* Channel Status Register */
++#define ATMEL_US_RHR		0x18			/* Receiver Holding Register */
++#define ATMEL_US_THR		0x1c			/* Transmitter Holding Register */
++#define		ATMEL_US_SYNH		(1 << 15)		/* Transmit/Receive Sync [AT91SAM9261 only] */
++
++#define ATMEL_US_BRGR		0x20			/* Baud Rate Generator Register */
++#define		ATMEL_US_CD		(0xffff << 0)		/* Clock Divider */
++
++#define ATMEL_US_RTOR		0x24			/* Receiver Time-out Register */
++#define		ATMEL_US_TO		(0xffff << 0)		/* Time-out Value */
++
++#define ATMEL_US_TTGR		0x28			/* Transmitter Timeguard Register */
++#define		ATMEL_US_TG		(0xff << 0)		/* Timeguard Value */
++
++#define ATMEL_US_FIDI		0x40			/* FI DI Ratio Register */
++#define ATMEL_US_NER		0x44			/* Number of Errors Register */
++#define ATMEL_US_IF		0x4c			/* IrDA Filter Register */
++
++#endif
 diff --git a/include/linux/attribute_container.h b/include/linux/attribute_container.h
 index 8ff2749..f558233 100644
 --- a/include/linux/attribute_container.h
@@ -859100,6 +929379,361 @@
 +};
 +
 +#endif
+diff --git a/include/linux/capability.h b/include/linux/capability.h
+index bb017ed..7d50ff6 100644
+--- a/include/linux/capability.h
++++ b/include/linux/capability.h
+@@ -14,7 +14,6 @@
+ #define _LINUX_CAPABILITY_H
+ 
+ #include <linux/types.h>
+-#include <linux/compiler.h>
+ 
+ struct task_struct;
+ 
+@@ -23,13 +22,20 @@ struct task_struct;
+    kernel might be somewhat backwards compatible, but don't bet on
+    it. */
+ 
+-/* XXX - Note, cap_t, is defined by POSIX to be an "opaque" pointer to
++/* Note, cap_t, is defined by POSIX (draft) to be an "opaque" pointer to
+    a set of three capability sets.  The transposition of 3*the
+    following structure to such a composite is better handled in a user
+    library since the draft standard requires the use of malloc/free
+    etc.. */
+ 
+-#define _LINUX_CAPABILITY_VERSION  0x19980330
++#define _LINUX_CAPABILITY_VERSION_1  0x19980330
++#define _LINUX_CAPABILITY_U32S_1     1
++
++#define _LINUX_CAPABILITY_VERSION_2  0x20071026
++#define _LINUX_CAPABILITY_U32S_2     2
++
++#define _LINUX_CAPABILITY_VERSION    _LINUX_CAPABILITY_VERSION_2
++#define _LINUX_CAPABILITY_U32S       _LINUX_CAPABILITY_U32S_2
+ 
+ typedef struct __user_cap_header_struct {
+ 	__u32 version;
+@@ -42,41 +48,42 @@ typedef struct __user_cap_data_struct {
+         __u32 inheritable;
+ } __user *cap_user_data_t;
+ 
++
+ #define XATTR_CAPS_SUFFIX "capability"
+ #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
+ 
+-#define XATTR_CAPS_SZ (3*sizeof(__le32))
+ #define VFS_CAP_REVISION_MASK	0xFF000000
++#define VFS_CAP_FLAGS_MASK	~VFS_CAP_REVISION_MASK
++#define VFS_CAP_FLAGS_EFFECTIVE	0x000001
++
+ #define VFS_CAP_REVISION_1	0x01000000
++#define VFS_CAP_U32_1           1
++#define XATTR_CAPS_SZ_1         (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+ 
+-#define VFS_CAP_REVISION	VFS_CAP_REVISION_1
++#define VFS_CAP_REVISION_2	0x02000000
++#define VFS_CAP_U32_2           2
++#define XATTR_CAPS_SZ_2         (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
++
++#define XATTR_CAPS_SZ           XATTR_CAPS_SZ_2
++#define VFS_CAP_U32             VFS_CAP_U32_2
++#define VFS_CAP_REVISION	VFS_CAP_REVISION_2
+ 
+-#define VFS_CAP_FLAGS_MASK	~VFS_CAP_REVISION_MASK
+-#define VFS_CAP_FLAGS_EFFECTIVE	0x000001
+ 
+ struct vfs_cap_data {
+-	__u32 magic_etc;  /* Little endian */
+-	__u32 permitted;    /* Little endian */
+-	__u32 inheritable;  /* Little endian */
++	__le32 magic_etc;            /* Little endian */
++	struct {
++		__le32 permitted;    /* Little endian */
++		__le32 inheritable;  /* Little endian */
++	} data[VFS_CAP_U32];
+ };
+ 
+ #ifdef __KERNEL__
+ 
+-/* #define STRICT_CAP_T_TYPECHECKS */
+-
+-#ifdef STRICT_CAP_T_TYPECHECKS
+-
+ typedef struct kernel_cap_struct {
+-	__u32 cap;
++	__u32 cap[_LINUX_CAPABILITY_U32S];
+ } kernel_cap_t;
+ 
+-#else
+-
+-typedef __u32 kernel_cap_t;
+-
+-#endif
+-
+-#define _USER_CAP_HEADER_SIZE  (2*sizeof(__u32))
++#define _USER_CAP_HEADER_SIZE  (sizeof(struct __user_cap_header_struct))
+ #define _KERNEL_CAP_T_SIZE     (sizeof(kernel_cap_t))
+ 
+ #endif
+@@ -119,10 +126,6 @@ typedef __u32 kernel_cap_t;
+ 
+ #define CAP_FSETID           4
+ 
+-/* Used to decide between falling back on the old suser() or fsuser(). */
+-
+-#define CAP_FS_MASK          0x1f
+-
+ /* Overrides the restriction that the real or effective user ID of a
+    process sending a signal must match the real or effective user ID
+    of the process receiving the signal. */
+@@ -145,8 +148,14 @@ typedef __u32 kernel_cap_t;
+  ** Linux-specific capabilities
+  **/
+ 
+-/* Transfer any capability in your permitted set to any pid,
+-   remove any capability in your permitted set from any pid */
++/* Without VFS support for capabilities:
++ *   Transfer any capability in your permitted set to any pid,
++ *   remove any capability in your permitted set from any pid
++ * With VFS support for capabilities (neither of above, but)
++ *   Add any capability from current's capability bounding set
++ *       to the current process' inheritable set
++ *   Allow taking bits out of capability bounding set
++ */
+ 
+ #define CAP_SETPCAP          8
+ 
+@@ -195,7 +204,6 @@ typedef __u32 kernel_cap_t;
+ #define CAP_IPC_OWNER        15
+ 
+ /* Insert and remove kernel modules - modify kernel without limit */
+-/* Modify cap_bset */
+ #define CAP_SYS_MODULE       16
+ 
+ /* Allow ioperm/iopl access */
+@@ -307,74 +315,183 @@ typedef __u32 kernel_cap_t;
+ 
+ #define CAP_SETFCAP	     31
+ 
++/* Override MAC access.
++   The base kernel enforces no MAC policy.
++   An LSM may enforce a MAC policy, and if it does and it chooses
++   to implement capability based overrides of that policy, this is
++   the capability it should use to do so. */
++
++#define CAP_MAC_OVERRIDE     32
++
++/* Allow MAC configuration or state changes.
++   The base kernel requires no MAC configuration.
++   An LSM may enforce a MAC policy, and if it does and it chooses
++   to implement capability based checks on modifications to that
++   policy or the data required to maintain it, this is the
++   capability it should use to do so. */
++
++#define CAP_MAC_ADMIN        33
++
++#define CAP_LAST_CAP         CAP_MAC_ADMIN
++
++#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
++
++/*
++ * Bit location of each capability (used by user-space library and kernel)
++ */
++
++#define CAP_TO_INDEX(x)     ((x) >> 5)        /* 1 << 5 == bits in __u32 */
++#define CAP_TO_MASK(x)      (1 << ((x) & 31)) /* mask for indexed __u32 */
++
+ #ifdef __KERNEL__
+ 
+ /*
+  * Internal kernel functions only
+  */
+ 
+-#ifdef STRICT_CAP_T_TYPECHECKS
++#define CAP_FOR_EACH_U32(__capi)  \
++	for (__capi = 0; __capi < _LINUX_CAPABILITY_U32S; ++__capi)
++
++# define CAP_FS_MASK_B0     (CAP_TO_MASK(CAP_CHOWN)		\
++			    | CAP_TO_MASK(CAP_DAC_OVERRIDE)	\
++			    | CAP_TO_MASK(CAP_DAC_READ_SEARCH)	\
++			    | CAP_TO_MASK(CAP_FOWNER)		\
++			    | CAP_TO_MASK(CAP_FSETID))
++
++# define CAP_FS_MASK_B1     (CAP_TO_MASK(CAP_MAC_OVERRIDE))
++
++#if _LINUX_CAPABILITY_U32S != 2
++# error Fix up hand-coded capability macro initializers
++#else /* HAND-CODED capability initializers */
++
++# define CAP_EMPTY_SET    {{ 0, 0 }}
++# define CAP_FULL_SET     {{ ~0, ~0 }}
++# define CAP_INIT_EFF_SET {{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}
++# define CAP_FS_SET       {{ CAP_FS_MASK_B0, CAP_FS_MASK_B1 } }
++# define CAP_NFSD_SET     {{ CAP_FS_MASK_B0|CAP_TO_MASK(CAP_SYS_RESOURCE), \
++			     CAP_FS_MASK_B1 } }
++
++#endif /* _LINUX_CAPABILITY_U32S != 2 */
++
++#define CAP_INIT_INH_SET    CAP_EMPTY_SET
++
++# define cap_clear(c)         do { (c) = __cap_empty_set; } while (0)
++# define cap_set_full(c)      do { (c) = __cap_full_set; } while (0)
++# define cap_set_init_eff(c)  do { (c) = __cap_init_eff_set; } while (0)
++
++#define cap_raise(c, flag)  ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag))
++#define cap_lower(c, flag)  ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag))
++#define cap_raised(c, flag) ((c).cap[CAP_TO_INDEX(flag)] & CAP_TO_MASK(flag))
++
++#define CAP_BOP_ALL(c, a, b, OP)                                    \
++do {                                                                \
++	unsigned __capi;                                            \
++	CAP_FOR_EACH_U32(__capi) {                                  \
++		c.cap[__capi] = a.cap[__capi] OP b.cap[__capi];     \
++	}                                                           \
++} while (0)
++
++#define CAP_UOP_ALL(c, a, OP)                                       \
++do {                                                                \
++	unsigned __capi;                                            \
++	CAP_FOR_EACH_U32(__capi) {                                  \
++		c.cap[__capi] = OP a.cap[__capi];                   \
++	}                                                           \
++} while (0)
++
++static inline kernel_cap_t cap_combine(const kernel_cap_t a,
++				       const kernel_cap_t b)
++{
++	kernel_cap_t dest;
++	CAP_BOP_ALL(dest, a, b, |);
++	return dest;
++}
+ 
+-#define to_cap_t(x) { x }
+-#define cap_t(x) (x).cap
++static inline kernel_cap_t cap_intersect(const kernel_cap_t a,
++					 const kernel_cap_t b)
++{
++	kernel_cap_t dest;
++	CAP_BOP_ALL(dest, a, b, &);
++	return dest;
++}
+ 
+-#else
++static inline kernel_cap_t cap_drop(const kernel_cap_t a,
++				    const kernel_cap_t drop)
++{
++	kernel_cap_t dest;
++	CAP_BOP_ALL(dest, a, drop, &~);
++	return dest;
++}
+ 
+-#define to_cap_t(x) (x)
+-#define cap_t(x) (x)
++static inline kernel_cap_t cap_invert(const kernel_cap_t c)
++{
++	kernel_cap_t dest;
++	CAP_UOP_ALL(dest, c, ~);
++	return dest;
++}
+ 
+-#endif
++static inline int cap_isclear(const kernel_cap_t a)
++{
++	unsigned __capi;
++	CAP_FOR_EACH_U32(__capi) {
++		if (a.cap[__capi] != 0)
++			return 0;
++	}
++	return 1;
++}
+ 
+-#define CAP_EMPTY_SET       to_cap_t(0)
+-#define CAP_FULL_SET        to_cap_t(~0)
+-#define CAP_INIT_EFF_SET    to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
+-#define CAP_INIT_INH_SET    to_cap_t(0)
++static inline int cap_issubset(const kernel_cap_t a, const kernel_cap_t set)
++{
++	kernel_cap_t dest;
++	dest = cap_drop(a, set);
++	return cap_isclear(dest);
++}
+ 
+-#define CAP_TO_MASK(x) (1 << (x))
+-#define cap_raise(c, flag)   (cap_t(c) |=  CAP_TO_MASK(flag))
+-#define cap_lower(c, flag)   (cap_t(c) &= ~CAP_TO_MASK(flag))
+-#define cap_raised(c, flag)  (cap_t(c) & CAP_TO_MASK(flag))
++/* Used to decide between falling back on the old suser() or fsuser(). */
+ 
+-static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
++static inline int cap_is_fs_cap(int cap)
+ {
+-     kernel_cap_t dest;
+-     cap_t(dest) = cap_t(a) | cap_t(b);
+-     return dest;
++	const kernel_cap_t __cap_fs_set = CAP_FS_SET;
++	return !!(CAP_TO_MASK(cap) & __cap_fs_set.cap[CAP_TO_INDEX(cap)]);
+ }
+ 
+-static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b)
++static inline kernel_cap_t cap_drop_fs_set(const kernel_cap_t a)
+ {
+-     kernel_cap_t dest;
+-     cap_t(dest) = cap_t(a) & cap_t(b);
+-     return dest;
++	const kernel_cap_t __cap_fs_set = CAP_FS_SET;
++	return cap_drop(a, __cap_fs_set);
+ }
+ 
+-static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop)
++static inline kernel_cap_t cap_raise_fs_set(const kernel_cap_t a,
++					    const kernel_cap_t permitted)
+ {
+-     kernel_cap_t dest;
+-     cap_t(dest) = cap_t(a) & ~cap_t(drop);
+-     return dest;
++	const kernel_cap_t __cap_fs_set = CAP_FS_SET;
++	return cap_combine(a,
++			   cap_intersect(permitted, __cap_fs_set));
+ }
+ 
+-static inline kernel_cap_t cap_invert(kernel_cap_t c)
++static inline kernel_cap_t cap_drop_nfsd_set(const kernel_cap_t a)
+ {
+-     kernel_cap_t dest;
+-     cap_t(dest) = ~cap_t(c);
+-     return dest;
++	const kernel_cap_t __cap_fs_set = CAP_NFSD_SET;
++	return cap_drop(a, __cap_fs_set);
+ }
+ 
+-#define cap_isclear(c)       (!cap_t(c))
+-#define cap_issubset(a,set)  (!(cap_t(a) & ~cap_t(set)))
+-
+-#define cap_clear(c)         do { cap_t(c) =  0; } while(0)
+-#define cap_set_full(c)      do { cap_t(c) = ~0; } while(0)
+-#define cap_mask(c,mask)     do { cap_t(c) &= cap_t(mask); } while(0)
++static inline kernel_cap_t cap_raise_nfsd_set(const kernel_cap_t a,
++					      const kernel_cap_t permitted)
++{
++	const kernel_cap_t __cap_nfsd_set = CAP_NFSD_SET;
++	return cap_combine(a,
++			   cap_intersect(permitted, __cap_nfsd_set));
++}
+ 
+-#define cap_is_fs_cap(c)     (CAP_TO_MASK(c) & CAP_FS_MASK)
++extern const kernel_cap_t __cap_empty_set;
++extern const kernel_cap_t __cap_full_set;
++extern const kernel_cap_t __cap_init_eff_set;
+ 
+ int capable(int cap);
+ int __capable(struct task_struct *t, int cap);
+ 
++extern long cap_prctl_drop(unsigned long cap);
++
+ #endif /* __KERNEL__ */
+ 
+ #endif /* !_LINUX_CAPABILITY_H */
 diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
 index c6d3e22..a5cd204 100644
 --- a/include/linux/cdrom.h
@@ -859143,6 +929777,19 @@
  #endif  /* End of kernel only stuff */ 
  
  #endif  /* _LINUX_CDROM_H */
+diff --git a/include/linux/chio.h b/include/linux/chio.h
+index a404c11..519248d 100644
+--- a/include/linux/chio.h
++++ b/include/linux/chio.h
+@@ -108,7 +108,7 @@ struct changer_element_status {
+ 
+ /*
+  * CHIOGELEM
+- *    get more detailed status informtion for a single element
++ *    get more detailed status information for a single element
+  */
+ struct changer_get_element {
+ 	int	cge_type;	 /* type/unit */
 diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
 index 107787a..85778a4 100644
 --- a/include/linux/clocksource.h
@@ -859165,7 +929812,7 @@
  extern void clocksource_change_rating(struct clocksource *cs, int rating);
  extern void clocksource_resume(void);
 diff --git a/include/linux/compat.h b/include/linux/compat.h
-index 0e69d2c..d38655f 100644
+index 0e69d2c..ae0a483 100644
 --- a/include/linux/compat.h
 +++ b/include/linux/compat.h
 @@ -191,6 +191,10 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
@@ -859197,6 +929844,20 @@
  /*
   * epoll (fs/eventpoll.c) compat bits follow ...
   */
+@@ -264,8 +279,11 @@ asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename,
+ asmlinkage long compat_sys_signalfd(int ufd,
+ 				const compat_sigset_t __user *sigmask,
+                                 compat_size_t sigsetsize);
+-asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags,
+-				const struct compat_itimerspec __user *utmr);
++asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
++				   const struct compat_itimerspec __user *utmr,
++				   struct compat_itimerspec __user *otmr);
++asmlinkage long compat_sys_timerfd_gettime(int ufd,
++				   struct compat_itimerspec __user *otmr);
+ 
+ #endif /* CONFIG_COMPAT */
+ #endif /* _LINUX_COMPAT_H */
 diff --git a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
 index 2d8c0f4..e5eb795 100644
 --- a/include/linux/compiler-gcc3.h
@@ -859647,8 +930308,34 @@
  	type |= CRYPTO_ALG_TYPE_HASH;
  	mask |= CRYPTO_ALG_TYPE_HASH_MASK;
  
+diff --git a/include/linux/cyclades.h b/include/linux/cyclades.h
+index 8f3dcd3..504cb2c 100644
+--- a/include/linux/cyclades.h
++++ b/include/linux/cyclades.h
+@@ -177,7 +177,7 @@ struct	CUSTOM_REG {
+ 	__u32	fpga_version;		/* FPGA Version Number Register */
+ 	__u32	cpu_start;		/* CPU start Register (write) */
+ 	__u32	cpu_stop;		/* CPU stop Register (write) */
+-	__u32	misc_reg;		/* Miscelaneous Register */
++	__u32	misc_reg;		/* Miscellaneous Register */
+ 	__u32	idt_mode;		/* IDT mode Register */
+ 	__u32	uart_irq_status;	/* UART IRQ status Register */
+ 	__u32	clear_timer0_irq;	/* Clear timer interrupt Register */
+diff --git a/include/linux/cycx_x25.h b/include/linux/cycx_x25.h
+index f7a9065..362bf19 100644
+--- a/include/linux/cycx_x25.h
++++ b/include/linux/cycx_x25.h
+@@ -81,7 +81,7 @@ struct cycx_x25_cmd {
+  *	@n2win - level 2 window (values: 1 thru 7)
+  *	@n3win - level 3 window (values: 1 thru 7)
+  *	@nvc - # of logical channels (values: 1 thru 64)
+- *	@pktlen - level 3 packet lenght - log base 2 of size
++ *	@pktlen - level 3 packet length - log base 2 of size
+  *	@locaddr - my address
+  *	@remaddr - remote address
+  *	@t1 - time, in seconds
 diff --git a/include/linux/dccp.h b/include/linux/dccp.h
-index 333c3ea..484e45c 100644
+index 333c3ea..aa07370 100644
 --- a/include/linux/dccp.h
 +++ b/include/linux/dccp.h
 @@ -205,6 +205,7 @@ struct dccp_so_feat {
@@ -859791,9 +930478,11 @@
   * @dccps_xmit_timer - timer for when CCID is not ready to send
   * @dccps_syn_rtt - RTT sample from Request/Response exchange (in usecs)
   */
-@@ -498,8 +526,8 @@ struct dccp_sock {
+@@ -497,15 +525,15 @@ struct dccp_sock {
+ 	__u64				dccps_gsr;
  	__u64				dccps_gar;
  	__be32				dccps_service;
++	__u32				dccps_mss_cache;
  	struct dccp_service_list	*dccps_service_list;
 -	ktime_t				dccps_timestamp_time;
  	__u32				dccps_timestamp_echo;
@@ -859801,6 +930490,12 @@
  	__u16				dccps_l_ack_ratio;
  	__u16				dccps_r_ack_ratio;
  	__u16				dccps_pcslen;
+ 	__u16				dccps_pcrlen;
+ 	unsigned long			dccps_ndp_count;
+-	__u32				dccps_mss_cache;
+ 	unsigned long			dccps_rate_last;
+ 	struct dccp_minisock		dccps_minisock;
+ 	struct dccp_ackvec		*dccps_hc_rx_ackvec;
 @@ -515,6 +543,7 @@ struct dccp_sock {
  	enum dccp_role			dccps_role:2;
  	__u8				dccps_hc_rx_insert_options:1;
@@ -859833,7 +930528,7 @@
  {
  }
 diff --git a/include/linux/device.h b/include/linux/device.h
-index 2e15822..db375be 100644
+index 2e15822..2258d89 100644
 --- a/include/linux/device.h
 +++ b/include/linux/device.h
 @@ -25,75 +25,72 @@
@@ -860016,25 +930711,25 @@
 +#define DRIVER_ATTR(_name, _mode, _show, _store)	\
 +struct driver_attribute driver_attr_##_name =		\
 +	__ATTR(_name, _mode, _show, _store)
- 
--extern int __must_check driver_create_file(struct device_driver *,
--					struct driver_attribute *);
--extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
++
 +extern int __must_check driver_create_file(struct device_driver *driver,
 +					   struct driver_attribute *attr);
 +extern void driver_remove_file(struct device_driver *driver,
 +			       struct driver_attribute *attr);
  
+-extern int __must_check driver_create_file(struct device_driver *,
+-					struct driver_attribute *);
+-extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
++extern int __must_check driver_add_kobj(struct device_driver *drv,
++					struct kobject *kobj,
++					const char *fmt, ...);
+ 
 -extern int __must_check driver_for_each_device(struct device_driver * drv,
 -		struct device *start, void *data,
 -		int (*fn)(struct device *, void *));
 -struct device * driver_find_device(struct device_driver *drv,
 -				   struct device *start, void *data,
 -				   int (*match)(struct device *, void *));
-+extern int __must_check driver_add_kobj(struct device_driver *drv,
-+					struct kobject *kobj,
-+					const char *fmt, ...);
-+
 +extern int __must_check driver_for_each_device(struct device_driver *drv,
 +					       struct device *start,
 +					       void *data,
@@ -860263,8 +930958,19 @@
  extern int devres_destroy(struct device *dev, dr_release_t release,
  			  dr_match_t match, void *match_data);
  
-@@ -399,7 +412,7 @@ extern void devm_kfree(struct device *dev, void *p);
+@@ -397,9 +410,18 @@ extern int devres_release_group(struct device *dev, void *id);
+ extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
+ extern void devm_kfree(struct device *dev, void *p);
  
++struct device_dma_parameters {
++	/*
++	 * a low level driver may set these to teach IOMMU code about
++	 * sg limitations.
++	 */
++	unsigned int max_segment_size;
++	unsigned long segment_boundary_mask;
++};
++
  struct device {
  	struct klist		klist_children;
 -	struct klist_node	knode_parent;		/* node in sibling list */
@@ -860272,7 +930978,7 @@
  	struct klist_node	knode_driver;
  	struct klist_node	knode_bus;
  	struct device		*parent;
-@@ -414,7 +427,7 @@ struct device {
+@@ -414,7 +436,7 @@ struct device {
  					 * its driver.
  					 */
  
@@ -860281,7 +930987,16 @@
  	struct device_driver *driver;	/* which driver has allocated this
  					   device */
  	void		*driver_data;	/* data private to the driver */
-@@ -445,10 +458,10 @@ struct device {
+@@ -432,6 +454,8 @@ struct device {
+ 					     64 bit addresses for consistent
+ 					     allocations such descriptors. */
+ 
++	struct device_dma_parameters *dma_parms;
++
+ 	struct list_head	dma_pools;	/* dma pools (if dma'ble) */
+ 
+ 	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
+@@ -445,10 +469,10 @@ struct device {
  	/* class_device migration path */
  	struct list_head	node;
  	struct class		*class;
@@ -860294,7 +931009,7 @@
  };
  
  #ifdef CONFIG_NUMA
-@@ -470,14 +483,12 @@ static inline void set_dev_node(struct device *dev, int node)
+@@ -470,14 +494,12 @@ static inline void set_dev_node(struct device *dev, int node)
  }
  #endif
  
@@ -860311,7 +931026,7 @@
  {
  	dev->driver_data = data;
  }
-@@ -492,15 +503,15 @@ void driver_init(void);
+@@ -492,15 +514,15 @@ void driver_init(void);
  /*
   * High level routines for use by the bus drivers
   */
@@ -860336,7 +931051,7 @@
  extern int device_rename(struct device *dev, char *new_name);
  extern int device_move(struct device *dev, struct device *new_parent);
  
-@@ -509,8 +520,8 @@ extern int device_move(struct device *dev, struct device *new_parent);
+@@ -509,8 +531,8 @@ extern int device_move(struct device *dev, struct device *new_parent);
   * for information on use.
   */
  extern int __must_check device_bind_driver(struct device *dev);
@@ -860347,7 +931062,7 @@
  extern int __must_check driver_attach(struct device_driver *drv);
  extern int __must_check device_reprobe(struct device *dev);
  
-@@ -519,8 +530,16 @@ extern int __must_check device_reprobe(struct device *dev);
+@@ -519,8 +541,22 @@ extern int __must_check device_reprobe(struct device *dev);
   */
  extern struct device *device_create(struct class *cls, struct device *parent,
  				    dev_t devt, const char *fmt, ...)
@@ -860356,16 +931071,22 @@
  extern void device_destroy(struct class *cls, dev_t devt);
 +#ifdef CONFIG_PM_SLEEP
 +extern void destroy_suspended_device(struct class *cls, dev_t devt);
++extern void device_pm_schedule_removal(struct device *);
 +#else /* !CONFIG_PM_SLEEP */
 +static inline void destroy_suspended_device(struct class *cls, dev_t devt)
 +{
 +	device_destroy(cls, devt);
 +}
++
++static inline void device_pm_schedule_removal(struct device *dev)
++{
++	device_unregister(dev);
++}
 +#endif /* !CONFIG_PM_SLEEP */
  
  /*
   * Platform "fixup" functions - allow the platform to have their say
-@@ -528,17 +547,17 @@ extern void device_destroy(struct class *cls, dev_t devt);
+@@ -528,17 +564,17 @@ extern void device_destroy(struct class *cls, dev_t devt);
   * know about.
   */
  /* Notify platform of device discovery */
@@ -860387,7 +931108,7 @@
  
  
  /* drivers/base/power/shutdown.c */
-@@ -547,22 +566,33 @@ extern void device_shutdown(void);
+@@ -547,22 +583,33 @@ extern void device_shutdown(void);
  /* drivers/base/sys.c */
  extern void sysdev_shutdown(void);
  
@@ -860428,7 +931149,7 @@
  {
  	return 0;
  }
-@@ -572,21 +602,12 @@ dev_dbg(struct device * dev, const char * fmt, ...)
+@@ -572,21 +619,12 @@ dev_dbg(struct device * dev, const char * fmt, ...)
  #define dev_vdbg	dev_dbg
  #else
  static inline int __attribute__ ((format (printf, 2, 3)))
@@ -860771,10 +931492,68 @@
 +#define DLM_EUNLOCK		0x10002
 +
 +#endif  /* __DLMCONSTANTS_DOT_H__ */
+diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
+index 101a2d4..3320307 100644
+--- a/include/linux/dma-mapping.h
++++ b/include/linux/dma-mapping.h
+@@ -1,5 +1,5 @@
+-#ifndef _ASM_LINUX_DMA_MAPPING_H
+-#define _ASM_LINUX_DMA_MAPPING_H
++#ifndef _LINUX_DMA_MAPPING_H
++#define _LINUX_DMA_MAPPING_H
+ 
+ #include <linux/device.h>
+ #include <linux/err.h>
+@@ -60,6 +60,36 @@ static inline int is_device_dma_capable(struct device *dev)
+ 
+ extern u64 dma_get_required_mask(struct device *dev);
+ 
++static inline unsigned int dma_get_max_seg_size(struct device *dev)
++{
++	return dev->dma_parms ? dev->dma_parms->max_segment_size : 65536;
++}
++
++static inline unsigned int dma_set_max_seg_size(struct device *dev,
++						unsigned int size)
++{
++	if (dev->dma_parms) {
++		dev->dma_parms->max_segment_size = size;
++		return 0;
++	} else
++		return -EIO;
++}
++
++static inline unsigned long dma_get_seg_boundary(struct device *dev)
++{
++	return dev->dma_parms ?
++		dev->dma_parms->segment_boundary_mask : 0xffffffff;
++}
++
++static inline int dma_set_seg_boundary(struct device *dev, unsigned long mask)
++{
++	if (dev->dma_parms) {
++		dev->dma_parms->segment_boundary_mask = mask;
++		return 0;
++	} else
++		return -EIO;
++}
++
+ /* flags for the coherent memory api */
+ #define	DMA_MEMORY_MAP			0x01
+ #define DMA_MEMORY_IO			0x02
 diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
-index a3b6035..55c9a69 100644
+index a3b6035..5c84bf8 100644
 --- a/include/linux/dmaengine.h
 +++ b/include/linux/dmaengine.h
+@@ -29,7 +29,7 @@
+ #include <linux/dma-mapping.h>
+ 
+ /**
+- * enum dma_state - resource PNP/power managment state
++ * enum dma_state - resource PNP/power management state
+  * @DMA_RESOURCE_SUSPEND: DMA device going into low power state
+  * @DMA_RESOURCE_RESUME: DMA device returning to full power
+  * @DMA_RESOURCE_AVAILABLE: DMA device available to the system
 @@ -132,7 +132,7 @@ struct dma_chan {
  
  	/* sysfs */
@@ -860817,6 +931596,19 @@
  		__attribute__((section(".note." name),			\
  			       aligned(sizeof(Elf##size##_Word)),	\
  			       unused)) = {				\
+diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
+index 71d4ada..fcbe8b6 100644
+--- a/include/linux/ethtool.h
++++ b/include/linux/ethtool.h
+@@ -309,7 +309,7 @@ int ethtool_op_set_flags(struct net_device *dev, u32 data);
+  * get_ringparam: Report ring sizes
+  * set_ringparam: Set ring sizes
+  * get_pauseparam: Report pause parameters
+- * set_pauseparam: Set pause paramters
++ * set_pauseparam: Set pause parameters
+  * get_rx_csum: Report whether receive checksums are turned on or off
+  * set_rx_csum: Turn receive checksum on or off
+  * get_tx_csum: Report whether transmit checksums are turned on or off
 diff --git a/include/linux/ext4_fs.h b/include/linux/ext4_fs.h
 index 97dd409..1852313 100644
 --- a/include/linux/ext4_fs.h
@@ -861443,7 +932235,7 @@
  
  #endif	/* _LINUX_EXT4_FS_SB */
 diff --git a/include/linux/fs.h b/include/linux/fs.h
-index b3ec4a4..a516b67 100644
+index b3ec4a4..56bd421 100644
 --- a/include/linux/fs.h
 +++ b/include/linux/fs.h
 @@ -124,6 +124,7 @@ extern int dir_notify_enable;
@@ -861471,7 +932263,24 @@
  	loff_t			i_size;
  #ifdef __NEED_I_SIZE_ORDERED
  	seqcount_t		i_size_seqcount;
-@@ -1394,6 +1396,21 @@ static inline void inode_dec_link_count(struct inode *inode)
+@@ -870,6 +872,7 @@ struct file_lock {
+ 	struct list_head fl_block;	/* circular list of blocked processes */
+ 	fl_owner_t fl_owner;
+ 	unsigned int fl_pid;
++	struct pid *fl_nspid;
+ 	wait_queue_head_t fl_wait;
+ 	struct file *fl_file;
+ 	unsigned char fl_flags;
+@@ -1305,7 +1308,7 @@ struct super_operations {
+  *			being set.  find_inode() uses this to prevent returning
+  *			nearly-dead inodes.
+  * I_SYNC		Similar to I_LOCK, but limited in scope to writeback
+- *			of inode dirty data.  Having a seperate lock for this
++ *			of inode dirty data.  Having a separate lock for this
+  *			purpose reduces latency and prevents some filesystem-
+  *			specific deadlocks.
+  *
+@@ -1394,6 +1397,21 @@ static inline void inode_dec_link_count(struct inode *inode)
  	mark_inode_dirty(inode);
  }
  
@@ -861493,7 +932302,7 @@
  extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry);
  static inline void file_accessed(struct file *file)
  {
-@@ -1476,7 +1493,7 @@ extern void drop_collected_mounts(struct vfsmount *);
+@@ -1476,7 +1494,7 @@ extern void drop_collected_mounts(struct vfsmount *);
  extern int vfs_statfs(struct dentry *, struct kstatfs *);
  
  /* /sys/fs */
@@ -861654,6 +932463,18 @@
  #endif /* CONFIG_BLOCK */
  
  #endif
+diff --git a/include/linux/gfp.h b/include/linux/gfp.h
+index 7e93a9a..0c6ce51 100644
+--- a/include/linux/gfp.h
++++ b/include/linux/gfp.h
+@@ -228,5 +228,7 @@ extern void FASTCALL(free_cold_page(struct page *page));
+ 
+ void page_alloc_init(void);
+ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp);
++void drain_all_pages(void);
++void drain_local_pages(void *dummy);
+ 
+ #endif /* __LINUX_GFP_H */
 diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
 index 8d30229..2961ec7 100644
 --- a/include/linux/hardirq.h
@@ -861672,7 +932493,7 @@
  #ifdef CONFIG_PREEMPT
  # define PREEMPT_CHECK_OFFSET 1
 diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h
-index 818c6af..3882013 100644
+index 818c6af..e38e759 100644
 --- a/include/linux/hdreg.h
 +++ b/include/linux/hdreg.h
 @@ -44,7 +44,9 @@
@@ -861809,6 +932630,15 @@
  
  /* ATA/ATAPI Commands pre T13 Spec */
  #define WIN_NOP				0x00
+@@ -358,7 +364,7 @@ typedef struct hd_drive_hob_hdr {
+ #define SETFEATURES_EN_RLA	0xAA	/* Enable read look-ahead feature */
+ #define SETFEATURES_PREFETCH	0xAB	/* Sets drive prefetch value */
+ #define SETFEATURES_EN_REST	0xAC	/* ATA-1 */
+-#define SETFEATURES_4B_RW_LONG	0xBB	/* Set Lenght of 4 bytes */
++#define SETFEATURES_4B_RW_LONG	0xBB	/* Set Length of 4 bytes */
+ #define SETFEATURES_DIS_AAM	0xC2	/* Disable Automatic Acoustic Management */
+ #define SETFEATURES_EN_RPOD	0xCC	/* Enable reverting to power on defaults */
+ #define SETFEATURES_DIS_RI	0xDD	/* Disable release interrupt ATAPI */
 @@ -700,8 +706,10 @@ struct hd_driveid {
   */
  #define IDE_NICE_DSC_OVERLAP	(0)	/* per the DSC overlap protocol */
@@ -861905,6 +932735,87 @@
  void hid_input_field(struct hid_device *hid, struct hid_field *field, __u8 *data, int interrupt);
  void hid_output_report(struct hid_report *report, __u8 *data);
  void hid_free_device(struct hid_device *device);
+diff --git a/include/linux/highmem.h b/include/linux/highmem.h
+index 1fcb003..7dcbc82 100644
+--- a/include/linux/highmem.h
++++ b/include/linux/highmem.h
+@@ -68,8 +68,6 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
+ 	void *addr = kmap_atomic(page, KM_USER0);
+ 	clear_user_page(addr, vaddr, page);
+ 	kunmap_atomic(addr, KM_USER0);
+-	/* Make sure this page is cleared on other CPU's too before using it */
+-	smp_wmb();
+ }
+ 
+ #ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
+@@ -124,28 +122,40 @@ static inline void clear_highpage(struct page *page)
+ 	kunmap_atomic(kaddr, KM_USER0);
+ }
+ 
+-/*
+- * Same but also flushes aliased cache contents to RAM.
+- *
+- * This must be a macro because KM_USER0 and friends aren't defined if
+- * !CONFIG_HIGHMEM
+- */
+-#define zero_user_page(page, offset, size, km_type)		\
+-	do {							\
+-		void *kaddr;					\
+-								\
+-		BUG_ON((offset) + (size) > PAGE_SIZE);		\
+-								\
+-		kaddr = kmap_atomic(page, km_type);		\
+-		memset((char *)kaddr + (offset), 0, (size));	\
+-		flush_dcache_page(page);			\
+-		kunmap_atomic(kaddr, (km_type));		\
+-	} while (0)
++static inline void zero_user_segments(struct page *page,
++	unsigned start1, unsigned end1,
++	unsigned start2, unsigned end2)
++{
++	void *kaddr = kmap_atomic(page, KM_USER0);
++
++	BUG_ON(end1 > PAGE_SIZE || end2 > PAGE_SIZE);
++
++	if (end1 > start1)
++		memset(kaddr + start1, 0, end1 - start1);
++
++	if (end2 > start2)
++		memset(kaddr + start2, 0, end2 - start2);
++
++	kunmap_atomic(kaddr, KM_USER0);
++	flush_dcache_page(page);
++}
++
++static inline void zero_user_segment(struct page *page,
++	unsigned start, unsigned end)
++{
++	zero_user_segments(page, start, end, 0, 0);
++}
++
++static inline void zero_user(struct page *page,
++	unsigned start, unsigned size)
++{
++	zero_user_segments(page, start, start + size, 0, 0);
++}
+ 
+ static inline void __deprecated memclear_highpage_flush(struct page *page,
+ 			unsigned int offset, unsigned int size)
+ {
+-	zero_user_page(page, offset, size, KM_USER0);
++	zero_user(page, offset, size);
+ }
+ 
+ #ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE
+@@ -160,8 +170,6 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
+ 	copy_user_page(vto, vfrom, vaddr, to);
+ 	kunmap_atomic(vfrom, KM_USER0);
+ 	kunmap_atomic(vto, KM_USER1);
+-	/* Make sure this page is cleared on other CPU's too before using it */
+-	smp_wmb();
+ }
+ 
+ #endif
 diff --git a/include/linux/hpet.h b/include/linux/hpet.h
 index 707f7cb..9cd94bf 100644
 --- a/include/linux/hpet.h
@@ -861929,7 +932840,7 @@
  #endif /* __KERNEL__ */
  
 diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
-index 7a9398e..49067f1 100644
+index 7a9398e..8371b66 100644
 --- a/include/linux/hrtimer.h
 +++ b/include/linux/hrtimer.h
 @@ -115,10 +115,8 @@ struct hrtimer {
@@ -861943,7 +932854,15 @@
  #ifdef CONFIG_TIMER_STATS
  	void				*start_site;
  	char				start_comm[16];
-@@ -194,10 +192,10 @@ struct hrtimer_cpu_base {
+@@ -149,7 +147,6 @@ struct hrtimer_sleeper {
+  * @get_time:		function to retrieve the current time of the clock
+  * @get_softirq_time:	function to retrieve the current time from the softirq
+  * @softirq_time:	the time when running the hrtimer queue in the softirq
+- * @cb_pending:		list of timers where the callback is pending
+  * @offset:		offset of this clock to the monotonic base
+  * @reprogram:		function to reprogram the timer event
+  */
+@@ -194,10 +191,10 @@ struct hrtimer_cpu_base {
  	spinlock_t			lock;
  	struct lock_class_key		lock_key;
  	struct hrtimer_clock_base	clock_base[HRTIMER_MAX_CLOCK_BASES];
@@ -861955,7 +932874,7 @@
  	unsigned long			nr_events;
  #endif
  };
-@@ -217,6 +215,11 @@ static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
+@@ -217,6 +214,11 @@ static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
  	return timer->base->get_time();
  }
  
@@ -861967,7 +932886,7 @@
  /*
   * The resolution of the clocks. The resolution value is returned in
   * the clock_getres() system call to give application programmers an
-@@ -248,6 +251,10 @@ static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
+@@ -248,6 +250,10 @@ static inline ktime_t hrtimer_cb_get_time(struct hrtimer *timer)
  	return timer->base->softirq_time;
  }
  
@@ -861978,7 +932897,25 @@
  #endif
  
  extern ktime_t ktime_get(void);
-@@ -310,6 +317,7 @@ extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
+@@ -295,9 +301,16 @@ static inline int hrtimer_is_queued(struct hrtimer *timer)
+ }
+ 
+ /* Forward a hrtimer so it expires after now: */
+-extern unsigned long
++extern u64
+ hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval);
+ 
++/* Forward a hrtimer so it expires after the hrtimer's current now */
++static inline u64 hrtimer_forward_now(struct hrtimer *timer,
++				      ktime_t interval)
++{
++	return hrtimer_forward(timer, timer->base->get_time(), interval);
++}
++
+ /* Precise sleep: */
+ extern long hrtimer_nanosleep(struct timespec *rqtp,
+ 			      struct timespec *rmtp,
+@@ -310,14 +323,15 @@ extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
  
  /* Soft interrupt function to run the hrtimer queues: */
  extern void hrtimer_run_queues(void);
@@ -861986,8 +932923,18 @@
  
  /* Bootup initialization: */
  extern void __init hrtimers_init(void);
+ 
+ #if BITS_PER_LONG < 64
+-extern unsigned long ktime_divns(const ktime_t kt, s64 div);
++extern u64 ktime_divns(const ktime_t kt, s64 div);
+ #else /* BITS_PER_LONG < 64 */
+-# define ktime_divns(kt, div)		(unsigned long)((kt).tv64 / (div))
++# define ktime_divns(kt, div)		(u64)((kt).tv64 / (div))
+ #endif
+ 
+ /* Show pending timers: */
 diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
-index 21ea761..85d1191 100644
+index 21ea761..4213182 100644
 --- a/include/linux/hw_random.h
 +++ b/include/linux/hw_random.h
 @@ -33,7 +33,7 @@ struct hwrng {
@@ -861999,6 +932946,23 @@
  	int (*data_read)(struct hwrng *rng, u32 *data);
  	unsigned long priv;
  
+@@ -44,7 +44,15 @@ struct hwrng {
+ /** Register a new Hardware Random Number Generator driver. */
+ extern int hwrng_register(struct hwrng *rng);
+ /** Unregister a Hardware Random Number Generator driver. */
+-extern void hwrng_unregister(struct hwrng *rng);
++extern void __hwrng_unregister(struct hwrng *rng, bool suspended);
++static inline void hwrng_unregister(struct hwrng *rng)
++{
++	__hwrng_unregister(rng, false);
++}
++static inline void hwrng_unregister_suspended(struct hwrng *rng)
++{
++	__hwrng_unregister(rng, true);
++}
+ 
+ #endif /* __KERNEL__ */
+ #endif /* LINUX_HWRANDOM_H_ */
 diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
 index e18017d..f922b06 100644
 --- a/include/linux/i2c-id.h
@@ -862446,6 +933410,81 @@
  I2C_CLIENT_INSMOD_COMMON
  #endif /* __KERNEL__ */
  #endif /* _LINUX_I2C_H */
+diff --git a/include/linux/i2c/pca9539.h b/include/linux/i2c/pca9539.h
+new file mode 100644
+index 0000000..611d84a
+--- /dev/null
++++ b/include/linux/i2c/pca9539.h
+@@ -0,0 +1,18 @@
++/* platform data for the PCA9539 16-bit I/O expander driver */
++
++struct pca9539_platform_data {
++	/* number of the first GPIO */
++	unsigned	gpio_base;
++
++	/* initial polarity inversion setting */
++	uint16_t	invert;
++
++	void		*context;	/* param to setup/teardown */
++
++	int		(*setup)(struct i2c_client *client,
++				unsigned gpio, unsigned ngpio,
++				void *context);
++	int		(*teardown)(struct i2c_client *client,
++				unsigned gpio, unsigned ngpio,
++				void *context);
++};
+diff --git a/include/linux/i2c/pcf857x.h b/include/linux/i2c/pcf857x.h
+new file mode 100644
+index 0000000..ba8ea6e
+--- /dev/null
++++ b/include/linux/i2c/pcf857x.h
+@@ -0,0 +1,45 @@
++#ifndef __LINUX_PCF857X_H
++#define __LINUX_PCF857X_H
++
++/**
++ * struct pcf857x_platform_data - data to set up pcf857x driver
++ * @gpio_base: number of the chip's first GPIO
++ * @n_latch: optional bit-inverse of initial register value; if
++ *	you leave this initialized to zero the driver will act
++ *	like the chip was just reset
++ * @setup: optional callback issued once the GPIOs are valid
++ * @teardown: optional callback issued before the GPIOs are invalidated
++ * @context: optional parameter passed to setup() and teardown()
++ *
++ * In addition to the I2C_BOARD_INFO() state appropriate to each chip,
++ * the i2c_board_info used with the pcf875x driver must provide the
++ * chip "type" ("pcf8574", "pcf8574a", "pcf8575", "pcf8575c") and its
++ * platform_data (pointer to one of these structures) with at least
++ * the gpio_base value initialized.
++ *
++ * The @setup callback may be used with the kind of board-specific glue
++ * which hands the (now-valid) GPIOs to other drivers, or which puts
++ * devices in their initial states using these GPIOs.
++ *
++ * These GPIO chips are only "quasi-bidirectional"; read the chip specs
++ * to understand the behavior.  They don't have separate registers to
++ * record which pins are used for input or output, record which output
++ * values are driven, or provide access to input values.  That must be
++ * inferred by reading the chip's value and knowing the last value written
++ * to it.  If you leave n_latch initialized to zero, that last written
++ * value is presumed to be all ones (as if the chip were just reset).
++ */
++struct pcf857x_platform_data {
++	unsigned	gpio_base;
++	unsigned	n_latch;
++
++	int		(*setup)(struct i2c_client *client,
++					int gpio, unsigned ngpio,
++					void *context);
++	int		(*teardown)(struct i2c_client *client,
++					int gpio, unsigned ngpio,
++					void *context);
++	void		*context;
++};
++
++#endif /* __LINUX_PCF857X_H */
 diff --git a/include/linux/i2c/tps65010.h b/include/linux/i2c/tps65010.h
 new file mode 100644
 index 0000000..7021635
@@ -862609,7 +933648,7 @@
 +#endif /*  __LINUX_I2C_TPS65010_H */
 +
 diff --git a/include/linux/ide.h b/include/linux/ide.h
-index 9a6a41e..367c170 100644
+index 9a6a41e..acec99d 100644
 --- a/include/linux/ide.h
 +++ b/include/linux/ide.h
 @@ -9,7 +9,6 @@
@@ -862670,7 +933709,7 @@
  #define IDE_DATA_REG		(HWIF(drive)->io_ports[IDE_DATA_OFFSET])
  #define IDE_ERROR_REG		(HWIF(drive)->io_ports[IDE_ERROR_OFFSET])
  #define IDE_NSECTOR_REG		(HWIF(drive)->io_ports[IDE_NSECTOR_OFFSET])
-@@ -128,25 +106,18 @@ typedef unsigned char	byte;	/* used everywhere */
+@@ -128,25 +106,14 @@ typedef unsigned char	byte;	/* used everywhere */
  #define BAD_W_STAT		(BAD_R_STAT  | WRERR_STAT)
  #define BAD_STAT		(BAD_R_STAT  | DRQ_STAT)
  #define DRIVE_READY		(READY_STAT  | SEEK_STAT)
@@ -862686,17 +933725,26 @@
 -#define SATA_ERROR_REG		(HWIF(drive)->sata_scr[SATA_ERROR_OFFSET])
  #define SATA_CONTROL_OFFSET	(2)
 -#define SATA_CONTROL_REG	(HWIF(drive)->sata_scr[SATA_CONTROL_OFFSET])
- 
- #define SATA_MISC_OFFSET	(0)
+-
+-#define SATA_MISC_OFFSET	(0)
 -#define SATA_MISC_REG		(HWIF(drive)->sata_misc[SATA_MISC_OFFSET])
- #define SATA_PHY_OFFSET		(1)
+-#define SATA_PHY_OFFSET		(1)
 -#define SATA_PHY_REG		(HWIF(drive)->sata_misc[SATA_PHY_OFFSET])
- #define SATA_IEN_OFFSET		(2)
+-#define SATA_IEN_OFFSET		(2)
 -#define SATA_IEN_REG		(HWIF(drive)->sata_misc[SATA_IEN_OFFSET])
  
  /*
   * Our Physical Region Descriptor (PRD) table should be large enough
-@@ -219,8 +190,12 @@ typedef struct hw_regs_s {
+@@ -202,7 +169,7 @@ enum {		ide_unknown,	ide_generic,	ide_pci,
+ 		ide_rz1000,	ide_trm290,
+ 		ide_cmd646,	ide_cy82c693,	ide_4drives,
+ 		ide_pmac,	ide_etrax100,	ide_acorn,
+-		ide_au1xxx, ide_forced
++		ide_au1xxx,	ide_palm3710,	ide_forced
+ };
+ 
+ typedef u8 hwif_chipset_t;
+@@ -219,21 +186,14 @@ typedef struct hw_regs_s {
  } hw_regs_t;
  
  struct hwif_s * ide_find_port(unsigned long);
@@ -862709,8 +933757,21 @@
 +int ide_register_hw(hw_regs_t *, void (*)(struct ide_drive_s *),
  		    struct hwif_s **);
  
- void ide_setup_ports(	hw_regs_t *hw,
-@@ -327,47 +302,16 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw,
+-void ide_setup_ports(	hw_regs_t *hw,
+-			unsigned long base,
+-			int *offsets,
+-			unsigned long ctrl,
+-			unsigned long intr,
+-			ide_ack_intr_t *ack_intr,
+-#if 0
+-			ide_io_ops_t *iops,
+-#endif
+-			int irq);
+-
+ static inline void ide_std_init_ports(hw_regs_t *hw,
+ 				      unsigned long io_addr,
+ 				      unsigned long ctl_addr)
+@@ -327,47 +287,16 @@ static inline void ide_init_hwif_ports(hw_regs_t *hw,
  typedef union {
  	unsigned all			: 8;
  	struct {
@@ -862758,7 +933819,7 @@
   * ATA-IDE Select Register, aka Device-Head
   *
   * head		: always zeros here
-@@ -398,131 +342,6 @@ typedef union {
+@@ -398,131 +327,6 @@ typedef union {
  } select_t, ata_select_t;
  
  /*
@@ -862890,7 +933951,7 @@
   * Status returned from various ide_ functions
   */
  typedef enum {
-@@ -568,7 +387,6 @@ typedef struct ide_drive_s {
+@@ -568,7 +372,6 @@ typedef struct ide_drive_s {
  	u8	state;			/* retry state */
  	u8	waiting_for_dma;	/* dma currently in progress */
  	u8	unmask;			/* okay to unmask other irqs */
@@ -862898,7 +933959,7 @@
  	u8	noflush;		/* don't attempt flushes */
  	u8	dsc_overlap;		/* DSC overlap */
  	u8	nice1;			/* give potential excess bandwidth */
-@@ -583,8 +401,6 @@ typedef struct ide_drive_s {
+@@ -583,8 +386,6 @@ typedef struct ide_drive_s {
  	unsigned no_unmask	: 1;	/* disallow setting unmask bit */
  	unsigned no_io_32bit	: 1;	/* disallow enabling 32bit I/O */
  	unsigned atapi_overlap	: 1;	/* ATAPI overlap (not supported) */
@@ -862907,7 +933968,14 @@
  	unsigned doorlocking	: 1;	/* for removable only: door lock/unlock works */
  	unsigned nodma		: 1;	/* disallow DMA */
  	unsigned autotune	: 2;	/* 0=default, 1=autotune, 2=noautotune */
-@@ -664,7 +480,6 @@ typedef struct hwif_s {
+@@ -657,14 +458,12 @@ typedef struct hwif_s {
+ 		/* task file registers for pata and sata */
+ 	unsigned long	io_ports[IDE_NR_PORTS];
+ 	unsigned long	sata_scr[SATA_NR_PORTS];
+-	unsigned long	sata_misc[SATA_NR_PORTS];
+ 
+ 	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
+ 
  	u8 major;	/* our major number */
  	u8 index;	/* 0 for ide0; 1 for ide1; ... */
  	u8 channel;	/* for dual-port chips: 0=primary, 1=secondary */
@@ -862915,7 +933983,7 @@
  	u8 bus_state;	/* power state of the IDE bus */
  
  	u32 host_flags;
-@@ -679,7 +494,8 @@ typedef struct hwif_s {
+@@ -679,7 +478,8 @@ typedef struct hwif_s {
  
  	hwif_chipset_t chipset;	/* sub-module for tuning.. */
  
@@ -862925,7 +933993,7 @@
  	const struct ide_port_info *cds;	/* chipset device struct */
  
  	ide_ack_intr_t *ack_intr;
-@@ -689,6 +505,8 @@ typedef struct hwif_s {
+@@ -689,6 +489,8 @@ typedef struct hwif_s {
  #if 0
  	ide_hwif_ops_t	*hwifops;
  #else
@@ -862934,7 +934002,7 @@
  	/* routine to program host for PIO mode */
  	void	(*set_pio_mode)(ide_drive_t *, const u8);
  	/* routine to program host for DMA mode */
-@@ -701,19 +519,17 @@ typedef struct hwif_s {
+@@ -701,19 +503,17 @@ typedef struct hwif_s {
  	void	(*pre_reset)(ide_drive_t *);
  	/* routine to reset controller after a disk reset */
  	void	(*resetproc)(ide_drive_t *);
@@ -862956,7 +934024,7 @@
  
  	void (*ata_input_data)(ide_drive_t *, void *, u32);
  	void (*ata_output_data)(ide_drive_t *, void *, u32);
-@@ -721,16 +537,13 @@ typedef struct hwif_s {
+@@ -721,16 +521,13 @@ typedef struct hwif_s {
  	void (*atapi_input_bytes)(ide_drive_t *, void *, u32);
  	void (*atapi_output_bytes)(ide_drive_t *, void *, u32);
  
@@ -862974,7 +934042,7 @@
  	void (*dma_lost_irq)(ide_drive_t *drive);
  	void (*dma_timeout)(ide_drive_t *drive);
  
-@@ -766,7 +579,6 @@ typedef struct hwif_s {
+@@ -766,7 +563,6 @@ typedef struct hwif_s {
  	int		rqsize;		/* max sectors per request */
  	int		irq;		/* our irq number */
  
@@ -862982,7 +934050,7 @@
  	unsigned long	dma_base;	/* base addr for dma ports */
  	unsigned long	dma_command;	/* dma command register */
  	unsigned long	dma_vendor1;	/* dma vendor 1 register */
-@@ -786,10 +598,9 @@ typedef struct hwif_s {
+@@ -786,10 +582,9 @@ typedef struct hwif_s {
  	unsigned	serialized : 1;	/* serialized all channel operation */
  	unsigned	sharing_irq: 1;	/* 1 = sharing irq with another hwif */
  	unsigned	reset      : 1;	/* reset after probe */
@@ -862994,7 +934062,7 @@
  
  	struct device	gendev;
  	struct completion gendev_rel_comp; /* To deal with device release() */
-@@ -806,15 +617,16 @@ typedef struct hwif_s {
+@@ -806,15 +601,16 @@ typedef struct hwif_s {
  /*
   *  internal ide interrupt handler type
   */
@@ -863014,7 +934082,7 @@
  		/* BOOL: protects all fields below */
  	volatile int busy;
  		/* BOOL: wake us up on timer expiry */
-@@ -829,25 +641,18 @@ typedef struct hwgroup_s {
+@@ -829,25 +625,18 @@ typedef struct hwgroup_s {
  		/* ptr to current hwif in linked-list */
  	ide_hwif_t *hwif;
  
@@ -863042,7 +934110,7 @@
  } ide_hwgroup_t;
  
  typedef struct ide_driver_s ide_driver_t;
-@@ -901,6 +706,7 @@ typedef struct {
+@@ -901,6 +690,7 @@ typedef struct {
  void proc_ide_create(void);
  void proc_ide_destroy(void);
  void ide_proc_register_port(ide_hwif_t *);
@@ -863050,7 +934118,7 @@
  void ide_proc_unregister_port(ide_hwif_t *);
  void ide_proc_register_driver(ide_drive_t *, ide_driver_t *);
  void ide_proc_unregister_driver(ide_drive_t *, ide_driver_t *);
-@@ -933,6 +739,7 @@ void ide_pci_create_host_proc(const char *, get_info_t *);
+@@ -933,6 +723,7 @@ void ide_pci_create_host_proc(const char *, get_info_t *);
  static inline void proc_ide_create(void) { ; }
  static inline void proc_ide_destroy(void) { ; }
  static inline void ide_proc_register_port(ide_hwif_t *hwif) { ; }
@@ -863058,7 +934126,7 @@
  static inline void ide_proc_unregister_port(ide_hwif_t *hwif) { ; }
  static inline void ide_proc_register_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
  static inline void ide_proc_unregister_driver(ide_drive_t *drive, ide_driver_t *driver) { ; }
-@@ -1020,7 +827,8 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+@@ -1020,7 +811,8 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
  
  extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout, ide_expiry_t *expiry);
  
@@ -863068,7 +934136,7 @@
  
  ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
  
-@@ -1054,60 +862,124 @@ extern int ide_do_drive_cmd(ide_drive_t *, struct request *, ide_action_t);
+@@ -1054,60 +846,124 @@ extern int ide_do_drive_cmd(ide_drive_t *, struct request *, ide_action_t);
  
  extern void ide_end_drive_cmd(ide_drive_t *, u8, u8);
  
@@ -863231,7 +934299,7 @@
  
  int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long);
  int ide_cmd_ioctl(ide_drive_t *, unsigned int, unsigned long);
-@@ -1116,10 +988,8 @@ int ide_task_ioctl(ide_drive_t *, unsigned int, unsigned long);
+@@ -1116,10 +972,8 @@ int ide_task_ioctl(ide_drive_t *, unsigned int, unsigned long);
  extern int system_bus_clock(void);
  
  extern int ide_driveid_update(ide_drive_t *);
@@ -863242,7 +934310,7 @@
  extern int taskfile_lib_get_identify(ide_drive_t *drive, u8 *);
  
  extern int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout);
-@@ -1133,10 +1003,8 @@ extern void do_ide_request(struct request_queue *);
+@@ -1133,10 +987,8 @@ extern void do_ide_request(struct request_queue *);
  
  void ide_init_disk(struct gendisk *, ide_drive_t *);
  
@@ -863254,11 +934322,12 @@
  extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name);
  #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME)
  #else
-@@ -1146,6 +1014,13 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o
+@@ -1146,6 +998,14 @@ extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *o
  void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 *);
  void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *);
  
-+#ifdef CONFIG_BLK_DEV_IDEDMA_PCI
++/* FIXME: palm_bk3710 uses BLK_DEV_IDEDMA_PCI without BLK_DEV_IDEPCI! */
++#if defined(CONFIG_BLK_DEV_IDEPCI) && defined(CONFIG_BLK_DEV_IDEDMA_PCI)
 +void ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *);
 +#else
 +static inline void ide_hwif_setup_dma(ide_hwif_t *hwif,
@@ -863268,7 +934337,7 @@
  extern void default_hwif_iops(ide_hwif_t *);
  extern void default_hwif_mmiops(ide_hwif_t *);
  extern void default_hwif_transport(ide_hwif_t *);
-@@ -1182,7 +1057,7 @@ enum {
+@@ -1182,7 +1042,7 @@ enum {
  	IDE_HFLAG_NO_SET_MODE		= (1 << 9),
  	/* trust BIOS for programming chipset/device for DMA */
  	IDE_HFLAG_TRUST_BIOS_FOR_DMA	= (1 << 10),
@@ -863277,7 +934346,7 @@
  	IDE_HFLAG_VDMA			= (1 << 11),
  	/* ATAPI DMA is unsupported */
  	IDE_HFLAG_NO_ATAPI_DMA		= (1 << 12),
-@@ -1192,8 +1067,10 @@ enum {
+@@ -1192,8 +1052,10 @@ enum {
  	IDE_HFLAG_NO_DMA		= (1 << 14),
  	/* check if host is PCI IDE device before allowing DMA */
  	IDE_HFLAG_NO_AUTODMA		= (1 << 15),
@@ -863289,7 +934358,7 @@
  	/* no LBA48 */
  	IDE_HFLAG_NO_LBA48		= (1 << 17),
  	/* no LBA48 DMA */
-@@ -1212,6 +1089,17 @@ enum {
+@@ -1212,6 +1074,17 @@ enum {
  	IDE_HFLAG_IO_32BIT		= (1 << 24),
  	/* unmask IRQs */
  	IDE_HFLAG_UNMASK_IRQS		= (1 << 25),
@@ -863307,7 +934376,7 @@
  };
  
  #ifdef CONFIG_BLK_DEV_OFFBOARD
-@@ -1226,10 +1114,9 @@ struct ide_port_info {
+@@ -1226,10 +1099,9 @@ struct ide_port_info {
  	void			(*init_iops)(ide_hwif_t *);
  	void                    (*init_hwif)(ide_hwif_t *);
  	void			(*init_dma)(ide_hwif_t *, unsigned long);
@@ -863319,7 +934388,7 @@
  	u32			host_flags;
  	u8			pio_mask;
  	u8			swdma_mask;
-@@ -1264,21 +1151,22 @@ static inline u8 ide_max_dma_mode(ide_drive_t *drive)
+@@ -1264,21 +1136,22 @@ static inline u8 ide_max_dma_mode(ide_drive_t *drive)
  	return ide_find_dma_mode(drive, XFER_UDMA_6);
  }
  
@@ -863349,7 +934418,7 @@
  extern int ide_dma_setup(ide_drive_t *);
  extern void ide_dma_start(ide_drive_t *);
  extern int __ide_dma_end(ide_drive_t *);
-@@ -1290,9 +1178,12 @@ extern void ide_dma_timeout(ide_drive_t *);
+@@ -1290,9 +1163,12 @@ extern void ide_dma_timeout(ide_drive_t *);
  static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; }
  static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; }
  static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; }
@@ -863362,7 +934431,7 @@
  #endif /* CONFIG_BLK_DEV_IDEDMA */
  
  #ifndef CONFIG_BLK_DEV_IDEDMA_PCI
-@@ -1304,25 +1195,29 @@ extern int ide_acpi_exec_tfs(ide_drive_t *drive);
+@@ -1304,25 +1180,29 @@ extern int ide_acpi_exec_tfs(ide_drive_t *drive);
  extern void ide_acpi_get_timing(ide_hwif_t *hwif);
  extern void ide_acpi_push_timing(ide_hwif_t *hwif);
  extern void ide_acpi_init(ide_hwif_t *hwif);
@@ -863395,7 +934464,7 @@
  
  static inline void *ide_get_hwifdata (ide_hwif_t * hwif)
  {
-@@ -1356,6 +1251,7 @@ static inline int ide_dev_is_sata(struct hd_driveid *id)
+@@ -1356,6 +1236,7 @@ static inline int ide_dev_is_sata(struct hd_driveid *id)
  	return 0;
  }
  
@@ -863403,7 +934472,7 @@
  u8 ide_dump_status(ide_drive_t *, const char *, u8);
  
  typedef struct ide_pio_timings_s {
-@@ -1405,9 +1301,14 @@ extern struct bus_type ide_bus_type;
+@@ -1405,9 +1286,14 @@ extern struct bus_type ide_bus_type;
  #define ide_id_has_flush_cache_ext(id)	\
  	(((id)->cfs_enable_2 & 0x2400) == 0x2400)
  
@@ -863419,7 +934488,7 @@
  	return dev ? pcibus_to_node(dev->bus) : -1;
  }
  
-@@ -1418,4 +1319,9 @@ static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
+@@ -1418,4 +1304,30 @@ static inline ide_drive_t *ide_get_paired_drive(ide_drive_t *drive)
  	return &hwif->drives[(drive->dn ^ 1) & 1];
  }
  
@@ -863428,9 +934497,30 @@
 +	drive->hwif->OUTB(drive->ctl | (on ? 0 : 2), IDE_CONTROL_REG);
 +}
 +
++static inline u8 ide_read_status(ide_drive_t *drive)
++{
++	ide_hwif_t *hwif = drive->hwif;
++
++	return hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
++}
++
++static inline u8 ide_read_altstatus(ide_drive_t *drive)
++{
++	ide_hwif_t *hwif = drive->hwif;
++
++	return hwif->INB(hwif->io_ports[IDE_CONTROL_OFFSET]);
++}
++
++static inline u8 ide_read_error(ide_drive_t *drive)
++{
++	ide_hwif_t *hwif = drive->hwif;
++
++	return hwif->INB(hwif->io_ports[IDE_ERROR_OFFSET]);
++}
++
  #endif /* _IDE_H */
 diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
-index 30621c2..5de6d91 100644
+index 30621c2..f577c8f 100644
 --- a/include/linux/ieee80211.h
 +++ b/include/linux/ieee80211.h
 @@ -54,6 +54,8 @@
@@ -863494,7 +934584,7 @@
  			} u;
  		} __attribute__ ((packed)) action;
  	} u;
-@@ -205,6 +226,66 @@ struct ieee80211_cts {
+@@ -205,6 +226,72 @@ struct ieee80211_cts {
  	u8 ra[6];
  } __attribute__ ((packed));
  
@@ -863558,10 +934648,16 @@
 +#define IEEE80211_HT_IE_HT_PROTECTION		0x0003
 +#define IEEE80211_HT_IE_NON_GF_STA_PRSNT	0x0004
 +#define IEEE80211_HT_IE_NON_HT_STA_PRSNT	0x0010
++
++/* MIMO Power Save Modes */
++#define WLAN_HT_CAP_MIMO_PS_STATIC         0
++#define WLAN_HT_CAP_MIMO_PS_DYNAMIC        1
++#define WLAN_HT_CAP_MIMO_PS_INVALID        2
++#define WLAN_HT_CAP_MIMO_PS_DISABLED       3
  
  /* Authentication algorithms */
  #define WLAN_AUTH_OPEN 0
-@@ -271,6 +352,18 @@ enum ieee80211_statuscode {
+@@ -271,6 +358,18 @@ enum ieee80211_statuscode {
  	WLAN_STATUS_UNSUPP_RSN_VERSION = 44,
  	WLAN_STATUS_INVALID_RSN_IE_CAP = 45,
  	WLAN_STATUS_CIPHER_SUITE_REJECTED = 46,
@@ -863580,7 +934676,7 @@
  };
  
  
-@@ -301,6 +394,16 @@ enum ieee80211_reasoncode {
+@@ -301,6 +400,16 @@ enum ieee80211_reasoncode {
  	WLAN_REASON_INVALID_RSN_IE_CAP = 22,
  	WLAN_REASON_IEEE8021X_FAILED = 23,
  	WLAN_REASON_CIPHER_SUITE_REJECTED = 24,
@@ -863597,7 +934693,7 @@
  };
  
  
-@@ -319,6 +422,15 @@ enum ieee80211_eid {
+@@ -319,6 +428,15 @@ enum ieee80211_eid {
  	WLAN_EID_HP_PARAMS = 8,
  	WLAN_EID_HP_TABLE = 9,
  	WLAN_EID_REQUEST = 10,
@@ -863613,7 +934709,7 @@
  	/* 802.11h */
  	WLAN_EID_PWR_CONSTRAINT = 32,
  	WLAN_EID_PWR_CAPABILITY = 33,
-@@ -333,6 +445,9 @@ enum ieee80211_eid {
+@@ -333,6 +451,9 @@ enum ieee80211_eid {
  	/* 802.11g */
  	WLAN_EID_ERP_INFO = 42,
  	WLAN_EID_EXT_SUPP_RATES = 50,
@@ -863623,7 +934719,7 @@
  	/* 802.11i */
  	WLAN_EID_RSN = 48,
  	WLAN_EID_WPA = 221,
-@@ -341,6 +456,32 @@ enum ieee80211_eid {
+@@ -341,6 +462,32 @@ enum ieee80211_eid {
  	WLAN_EID_QOS_PARAMETER = 222
  };
  
@@ -864182,7 +935278,7 @@
  static __inline__ int inet_ifa_match(__be32 addr, struct in_ifaddr *ifa)
  {
 diff --git a/include/linux/init.h b/include/linux/init.h
-index 5141381..2efbda0 100644
+index 5141381..90cdbbb 100644
 --- a/include/linux/init.h
 +++ b/include/linux/init.h
 @@ -40,10 +40,10 @@
@@ -864200,7 +935296,7 @@
  
  /* modpost check for section mismatches during the kernel build.
   * A section mismatch happens when there are references from a
-@@ -52,25 +52,81 @@
+@@ -52,25 +52,78 @@
   * when early init has completed so all such references are potential bugs.
   * For exit sections the same issue exists.
   * The following markers are used for the cases where the reference to
@@ -864285,13 +935381,10 @@
 +#define __REF            .section       ".ref.text", "ax"
 +#define __REFDATA        .section       ".ref.data", "aw"
 +#define __REFCONST       .section       ".ref.rodata", "aw"
-+/* backward compatibility */
-+#define __INIT_REFOK     .section	__REF
-+#define __INITDATA_REFOK .section	__REFDATA
  
  #ifndef __ASSEMBLY__
  /*
-@@ -108,7 +164,7 @@ void prepare_namespace(void);
+@@ -108,7 +161,7 @@ void prepare_namespace(void);
   */
  
  #define __define_initcall(level,fn,id) \
@@ -864300,7 +935393,7 @@
  	__attribute__((__section__(".initcall" level ".init"))) = fn
  
  /*
-@@ -142,11 +198,11 @@ void prepare_namespace(void);
+@@ -142,11 +195,11 @@ void prepare_namespace(void);
  
  #define console_initcall(fn) \
  	static initcall_t __initcall_##fn \
@@ -864314,7 +935407,7 @@
  
  struct obs_kernel_param {
  	const char *str;
-@@ -163,8 +219,7 @@ struct obs_kernel_param {
+@@ -163,8 +216,7 @@ struct obs_kernel_param {
  #define __setup_param(str, unique_id, fn, early)			\
  	static char __setup_str_##unique_id[] __initdata __aligned(1) = str; \
  	static struct obs_kernel_param __setup_##unique_id	\
@@ -864324,7 +935417,7 @@
  		__attribute__((aligned((sizeof(long)))))	\
  		= { __setup_str_##unique_id, fn, early }
  
-@@ -242,7 +297,7 @@ void __init parse_early_param(void);
+@@ -242,7 +294,7 @@ void __init parse_early_param(void);
  #endif
  
  /* Data marked not to be saved by software suspend */
@@ -864333,7 +935426,7 @@
  
  /* This means "can be init if no module support, otherwise module load
     may call it." */
-@@ -254,43 +309,6 @@ void __init parse_early_param(void);
+@@ -254,43 +306,6 @@ void __init parse_early_param(void);
  #define __initdata_or_module __initdata
  #endif /*CONFIG_MODULES*/
  
@@ -864388,10 +935481,10 @@
 +extern void __init init_ohci1394_dma_on_all_controllers(void);
 +#endif
 diff --git a/include/linux/init_task.h b/include/linux/init_task.h
-index cae35b6..f42663e 100644
+index cae35b6..1f74e1d 100644
 --- a/include/linux/init_task.h
 +++ b/include/linux/init_task.h
-@@ -114,6 +114,13 @@ extern struct group_info init_groups;
+@@ -114,6 +114,25 @@ extern struct group_info init_groups;
  	.pid = &init_struct_pid,				\
  }
  
@@ -864402,10 +935495,22 @@
 +#else
 +#define INIT_IDS
 +#endif
++
++#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
++/*
++ * Because of the reduced scope of CAP_SETPCAP when filesystem
++ * capabilities are in effect, it is safe to allow CAP_SETPCAP to
++ * be available in the default configuration.
++ */
++# define CAP_INIT_BSET  CAP_FULL_SET
++#else
++# define CAP_INIT_BSET  CAP_INIT_EFF_SET
++#endif
++
  /*
   *  INIT_TASK is used to set up the first task table, touch at
   * your own risk!. Base=0, limit=0x1fffff (=2MB)
-@@ -132,9 +139,11 @@ extern struct group_info init_groups;
+@@ -132,9 +151,11 @@ extern struct group_info init_groups;
  	.cpus_allowed	= CPU_MASK_ALL,					\
  	.mm		= NULL,						\
  	.active_mm	= &init_mm,					\
@@ -864420,7 +935525,15 @@
  	.tasks		= LIST_HEAD_INIT(tsk.tasks),			\
  	.ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children),		\
  	.ptrace_list	= LIST_HEAD_INIT(tsk.ptrace_list),		\
-@@ -171,6 +180,7 @@ extern struct group_info init_groups;
+@@ -147,6 +168,7 @@ extern struct group_info init_groups;
+ 	.cap_effective	= CAP_INIT_EFF_SET,				\
+ 	.cap_inheritable = CAP_INIT_INH_SET,				\
+ 	.cap_permitted	= CAP_FULL_SET,					\
++	.cap_bset 	= CAP_INIT_BSET,				\
+ 	.keep_capabilities = 0,						\
+ 	.user		= INIT_USER,					\
+ 	.comm		= "swapper",					\
+@@ -171,6 +193,7 @@ extern struct group_info init_groups;
  		[PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),		\
  	},								\
  	.dirties = INIT_PROP_LOCAL_SINGLE(dirties),			\
@@ -864554,6 +935667,19 @@
 +}
 +
 +#endif
+diff --git a/include/linux/iommu-helper.h b/include/linux/iommu-helper.h
+new file mode 100644
+index 0000000..4dd4c04
+--- /dev/null
++++ b/include/linux/iommu-helper.h
+@@ -0,0 +1,7 @@
++extern unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
++				      unsigned long start, unsigned int nr,
++				      unsigned long shift,
++				      unsigned long boundary_size,
++				      unsigned long align_mask);
++extern void iommu_area_free(unsigned long *map, unsigned long start,
++			    unsigned int nr);
 diff --git a/include/linux/ioport.h b/include/linux/ioport.h
 index 6187a85..605d237 100644
 --- a/include/linux/ioport.h
@@ -865982,6 +937108,37 @@
 +};
 +
 +#endif /* __KVM_TYPES_H__ */
+diff --git a/include/linux/latency.h b/include/linux/latency.h
+deleted file mode 100644
+index c08b52b..0000000
+--- a/include/linux/latency.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/*
+- * latency.h: Explicit system-wide latency-expectation infrastructure
+- *
+- * (C) Copyright 2006 Intel Corporation
+- * Author: Arjan van de Ven <arjan at linux.intel.com>
+- *
+- */
+-
+-#ifndef _INCLUDE_GUARD_LATENCY_H_
+-#define _INCLUDE_GUARD_LATENCY_H_
+-
+-#include <linux/notifier.h>
+-
+-void set_acceptable_latency(char *identifier, int usecs);
+-void modify_acceptable_latency(char *identifier, int usecs);
+-void remove_acceptable_latency(char *identifier);
+-void synchronize_acceptable_latency(void);
+-int system_latency_constraint(void);
+-
+-int register_latency_notifier(struct notifier_block * nb);
+-int unregister_latency_notifier(struct notifier_block * nb);
+-
+-#define INFINITE_LATENCY 1000000
+-
+-#endif
 diff --git a/include/linux/latencytop.h b/include/linux/latencytop.h
 new file mode 100644
 index 0000000..901c2d6
@@ -866032,6 +937189,54 @@
 +#endif
 +
 +#endif
+diff --git a/include/linux/leds.h b/include/linux/leds.h
+index b4130ff..00f89fd 100644
+--- a/include/linux/leds.h
++++ b/include/linux/leds.h
+@@ -54,7 +54,15 @@ struct led_classdev {
+ 
+ extern int led_classdev_register(struct device *parent,
+ 				 struct led_classdev *led_cdev);
+-extern void led_classdev_unregister(struct led_classdev *led_cdev);
++extern void __led_classdev_unregister(struct led_classdev *led_cdev, bool sus);
++static inline void led_classdev_unregister(struct led_classdev *lcd)
++{
++	__led_classdev_unregister(lcd, false);
++}
++static inline void led_classdev_unregister_suspended(struct led_classdev *lcd)
++{
++	__led_classdev_unregister(lcd, true);
++}
+ extern void led_classdev_suspend(struct led_classdev *led_cdev);
+ extern void led_classdev_resume(struct led_classdev *led_cdev);
+ 
+diff --git a/include/linux/lguest_launcher.h b/include/linux/lguest_launcher.h
+index 697104d..589be3e 100644
+--- a/include/linux/lguest_launcher.h
++++ b/include/linux/lguest_launcher.h
+@@ -23,7 +23,12 @@
+ struct lguest_device_desc {
+ 	/* The device type: console, network, disk etc.  Type 0 terminates. */
+ 	__u8 type;
+-	/* The number of bytes of the config array. */
++	/* The number of virtqueues (first in config array) */
++	__u8 num_vq;
++	/* The number of bytes of feature bits.  Multiply by 2: one for host
++	 * features and one for guest acknowledgements. */
++	__u8 feature_len;
++	/* The number of bytes of the config array after virtqueues. */
+ 	__u8 config_len;
+ 	/* A status byte, written by the Guest. */
+ 	__u8 status;
+@@ -31,7 +36,7 @@ struct lguest_device_desc {
+ };
+ 
+ /*D:135 This is how we expect the device configuration field for a virtqueue
+- * (type VIRTIO_CONFIG_F_VIRTQUEUE) to be laid out: */
++ * to be laid out in config space. */
+ struct lguest_vqconfig {
+ 	/* The number of entries in the virtio_ring */
+ 	__u16 num;
 diff --git a/include/linux/libata.h b/include/linux/libata.h
 index 124033c..4374c42 100644
 --- a/include/linux/libata.h
@@ -866436,6 +937641,22 @@
  #ifndef ENDPROC
  #define ENDPROC(name) \
    .type name, @function; \
+diff --git a/include/linux/llc.h b/include/linux/llc.h
+index 09f2e6d..7733585 100644
+--- a/include/linux/llc.h
++++ b/include/linux/llc.h
+@@ -49,9 +49,9 @@ enum llc_sockopts {
+ 
+ /* LLC SAP types. */
+ #define LLC_SAP_NULL	0x00		/* NULL SAP. 			*/
+-#define LLC_SAP_LLC	0x02		/* LLC Sublayer Managment. 	*/
++#define LLC_SAP_LLC	0x02		/* LLC Sublayer Management. 	*/
+ #define LLC_SAP_SNA	0x04		/* SNA Path Control. 		*/
+-#define LLC_SAP_PNM	0x0E		/* Proway Network Managment.	*/	
++#define LLC_SAP_PNM	0x0E		/* Proway Network Management.	*/	
+ #define LLC_SAP_IP	0x06		/* TCP/IP. 			*/
+ #define LLC_SAP_BSPAN	0x42		/* Bridge Spanning Tree Proto	*/
+ #define LLC_SAP_MMS	0x4E		/* Manufacturing Message Srv.	*/
 diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
 index 6f1637c..3d25bcd 100644
 --- a/include/linux/lockd/bind.h
@@ -866571,8 +937792,29 @@
 -extern int m41t00_set_rtc_time(ulong nowtime);
 -
 -#endif /* _M41T00_H */
+diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
+index dff9ea3..24b30b9 100644
+--- a/include/linux/miscdevice.h
++++ b/include/linux/miscdevice.h
+@@ -43,7 +43,15 @@ struct miscdevice  {
+ };
+ 
+ extern int misc_register(struct miscdevice * misc);
+-extern int misc_deregister(struct miscdevice * misc);
++extern int __misc_deregister(struct miscdevice *misc, bool suspended);
++static inline int misc_deregister(struct miscdevice *misc)
++{
++	return __misc_deregister(misc, false);
++}
++static inline int misc_deregister_suspended(struct miscdevice *misc)
++{
++	return __misc_deregister(misc, true);
++}
+ 
+ #define MODULE_ALIAS_MISCDEV(minor)				\
+ 	MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR)	\
 diff --git a/include/linux/mm.h b/include/linux/mm.h
-index 1b7b95c..1bba678 100644
+index 1b7b95c..89d7c69 100644
 --- a/include/linux/mm.h
 +++ b/include/linux/mm.h
 @@ -12,7 +12,6 @@
@@ -866592,7 +937834,69 @@
  #include <asm/page.h>
  #include <asm/pgtable.h>
  #include <asm/processor.h>
-@@ -1117,9 +1118,21 @@ static inline void vm_stat_account(struct mm_struct *mm,
+@@ -226,10 +227,22 @@ static inline int put_page_testzero(struct page *page)
+  */
+ static inline int get_page_unless_zero(struct page *page)
+ {
+-	VM_BUG_ON(PageCompound(page));
++	VM_BUG_ON(PageTail(page));
+ 	return atomic_inc_not_zero(&page->_count);
+ }
+ 
++/* Support for virtually mapped pages */
++struct page *vmalloc_to_page(const void *addr);
++unsigned long vmalloc_to_pfn(const void *addr);
++
++/* Determine if an address is within the vmalloc range */
++static inline int is_vmalloc_addr(const void *x)
++{
++	unsigned long addr = (unsigned long)x;
++
++	return addr >= VMALLOC_START && addr < VMALLOC_END;
++}
++
+ static inline struct page *compound_head(struct page *page)
+ {
+ 	if (unlikely(PageTail(page)))
+@@ -705,6 +718,28 @@ unsigned long unmap_vmas(struct mmu_gather **tlb,
+ 		struct vm_area_struct *start_vma, unsigned long start_addr,
+ 		unsigned long end_addr, unsigned long *nr_accounted,
+ 		struct zap_details *);
++
++/**
++ * mm_walk - callbacks for walk_page_range
++ * @pgd_entry: if set, called for each non-empty PGD (top-level) entry
++ * @pud_entry: if set, called for each non-empty PUD (2nd-level) entry
++ * @pmd_entry: if set, called for each non-empty PMD (3rd-level) entry
++ * @pte_entry: if set, called for each non-empty PTE (4th-level) entry
++ * @pte_hole: if set, called for each hole at all levels
++ *
++ * (see walk_page_range for more details)
++ */
++struct mm_walk {
++	int (*pgd_entry)(pgd_t *, unsigned long, unsigned long, void *);
++	int (*pud_entry)(pud_t *, unsigned long, unsigned long, void *);
++	int (*pmd_entry)(pmd_t *, unsigned long, unsigned long, void *);
++	int (*pte_entry)(pte_t *, unsigned long, unsigned long, void *);
++	int (*pte_hole)(unsigned long, unsigned long, void *);
++};
++
++int walk_page_range(const struct mm_struct *, unsigned long addr,
++		    unsigned long end, const struct mm_walk *walk,
++		    void *private);
+ void free_pgd_range(struct mmu_gather **tlb, unsigned long addr,
+ 		unsigned long end, unsigned long floor, unsigned long ceiling);
+ void free_pgtables(struct mmu_gather **tlb, struct vm_area_struct *start_vma,
+@@ -1088,8 +1123,6 @@ static inline unsigned long vma_pages(struct vm_area_struct *vma)
+ 
+ pgprot_t vm_get_page_prot(unsigned long vm_flags);
+ struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr);
+-struct page *vmalloc_to_page(void *addr);
+-unsigned long vmalloc_to_pfn(void *addr);
+ int remap_pfn_range(struct vm_area_struct *, unsigned long addr,
+ 			unsigned long pfn, unsigned long size, pgprot_t);
+ int vm_insert_page(struct vm_area_struct *, unsigned long addr, struct page *);
+@@ -1117,9 +1150,21 @@ static inline void vm_stat_account(struct mm_struct *mm,
  }
  #endif /* CONFIG_PROC_FS */
  
@@ -866615,7 +937919,7 @@
  #endif
  
  extern struct vm_area_struct *get_gate_vma(struct task_struct *tsk);
-@@ -1145,6 +1158,7 @@ extern int randomize_va_space;
+@@ -1145,6 +1190,7 @@ extern int randomize_va_space;
  #endif
  
  const char * arch_vma_name(struct vm_area_struct *vma);
@@ -866623,6 +937927,33 @@
  
  struct page *sparse_mem_map_populate(unsigned long pnum, int nid);
  pgd_t *vmemmap_pgd_populate(unsigned long addr, int node);
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index 4c4522a..8d8d197 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -113,7 +113,7 @@ struct per_cpu_pages {
+ };
+ 
+ struct per_cpu_pageset {
+-	struct per_cpu_pages pcp[2];	/* 0: hot.  1: cold */
++	struct per_cpu_pages pcp;
+ #ifdef CONFIG_NUMA
+ 	s8 expire;
+ #endif
+diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
+index e9fddb4..139d49d 100644
+--- a/include/linux/mod_devicetable.h
++++ b/include/linux/mod_devicetable.h
+@@ -343,7 +343,8 @@ struct sdio_device_id {
+ 	__u8	class;			/* Standard interface or SDIO_ANY_ID */
+ 	__u16	vendor;			/* Vendor or SDIO_ANY_ID */
+ 	__u16	device;			/* Device ID or SDIO_ANY_ID */
+-	kernel_ulong_t driver_data;	/* Data private to the driver */
++	kernel_ulong_t driver_data	/* Data private to the driver */
++		__attribute__((aligned(sizeof(kernel_ulong_t))));
+ };
+ 
+ /* SSB core, see drivers/ssb/ */
 diff --git a/include/linux/module.h b/include/linux/module.h
 index 2cbc0b8..ac481e2 100644
 --- a/include/linux/module.h
@@ -869167,6 +940498,24 @@
  
  /* Console keyboard events.
   * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
+diff --git a/include/linux/nubus.h b/include/linux/nubus.h
+index cdb3e9b..c435507 100644
+--- a/include/linux/nubus.h
++++ b/include/linux/nubus.h
+@@ -132,10 +132,12 @@ enum nubus_drhw {
+ 	NUBUS_DRHW_RDIUS_DCGX     = 0x027C, /* Radius DirectColor/GX */
+ 	NUBUS_DRHW_RDIUS_PC8      = 0x0291, /* Radius PrecisionColor 8 */
+ 	NUBUS_DRHW_LAPIS_PCS8     = 0x0292, /* Lapis ProColorServer 8 */
+-	NUBUS_DRHW_RASTER_24LXI   = 0x02A0, /* RasterOps 8/24 XLi */
++	NUBUS_DRHW_RASTER_24XLI   = 0x02A0, /* RasterOps 8/24 XLi */
+ 	NUBUS_DRHW_RASTER_PBPGT   = 0x02A5, /* RasterOps PaintBoard Prism GT */
+ 	NUBUS_DRHW_EMACH_FSX      = 0x02AE, /* E-Machines Futura SX */
++	NUBUS_DRHW_RASTER_24XLTV  = 0x02B7, /* RasterOps 24XLTV */
+ 	NUBUS_DRHW_SMAC_THUND24   = 0x02CB, /* SuperMac Thunder/24 */
++	NUBUS_DRHW_SMAC_THUNDLGHT = 0x03D9, /* SuperMac ThunderLight */
+ 	NUBUS_DRHW_RDIUS_PC24XP   = 0x0406, /* Radius PrecisionColor 24Xp */
+ 	NUBUS_DRHW_RDIUS_PC24X    = 0x040A, /* Radius PrecisionColor 24X */
+ 	NUBUS_DRHW_RDIUS_PC8XJ    = 0x040B, /* Radius PrecisionColor 8XJ */
 diff --git a/include/linux/of.h b/include/linux/of.h
 index 5c39b92..b5f33ef 100644
 --- a/include/linux/of.h
@@ -869221,6 +940570,66 @@
  extern const struct of_device_id *of_match_device(
  	const struct of_device_id *matches, const struct of_device *dev);
  
+diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
+index 209d3a4..bbad43f 100644
+--- a/include/linux/page-flags.h
++++ b/include/linux/page-flags.h
+@@ -131,16 +131,52 @@
+ #define ClearPageReferenced(page)	clear_bit(PG_referenced, &(page)->flags)
+ #define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
+ 
+-#define PageUptodate(page)	test_bit(PG_uptodate, &(page)->flags)
++static inline int PageUptodate(struct page *page)
++{
++	int ret = test_bit(PG_uptodate, &(page)->flags);
++
++	/*
++	 * Must ensure that the data we read out of the page is loaded
++	 * _after_ we've loaded page->flags to check for PageUptodate.
++	 * We can skip the barrier if the page is not uptodate, because
++	 * we wouldn't be reading anything from it.
++	 *
++	 * See SetPageUptodate() for the other side of the story.
++	 */
++	if (ret)
++		smp_rmb();
++
++	return ret;
++}
++
++static inline void __SetPageUptodate(struct page *page)
++{
++	smp_wmb();
++	__set_bit(PG_uptodate, &(page)->flags);
+ #ifdef CONFIG_S390
++	page_clear_dirty(page);
++#endif
++}
++
+ static inline void SetPageUptodate(struct page *page)
+ {
++#ifdef CONFIG_S390
+ 	if (!test_and_set_bit(PG_uptodate, &page->flags))
+ 		page_clear_dirty(page);
+-}
+ #else
+-#define SetPageUptodate(page)	set_bit(PG_uptodate, &(page)->flags)
++	/*
++	 * Memory barrier must be issued before setting the PG_uptodate bit,
++	 * so that all previous stores issued in order to bring the page
++	 * uptodate are actually visible before PageUptodate becomes true.
++	 *
++	 * s390 doesn't need an explicit smp_wmb here because the test and
++	 * set bit already provides full barriers.
++	 */
++	smp_wmb();
++	set_bit(PG_uptodate, &(page)->flags);
+ #endif
++}
++
+ #define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)
+ 
+ #define PageDirty(page)		test_bit(PG_dirty, &(page)->flags)
 diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
 index db8a410..4b62a10 100644
 --- a/include/linux/pagemap.h
@@ -869301,7 +940710,7 @@
  
  #endif	/* _PCI_ACPI_H_ */
 diff --git a/include/linux/pci.h b/include/linux/pci.h
-index 0dd93bb..4f96f1d 100644
+index 0dd93bb..7215d3b 100644
 --- a/include/linux/pci.h
 +++ b/include/linux/pci.h
 @@ -28,7 +28,7 @@
@@ -869321,22 +940730,16 @@
  #define DEVICE_COUNT_RESOURCE	12
  
  typedef int __bitwise pci_power_t;
-@@ -129,6 +128,7 @@ struct pci_cap_saved_state {
- 	u32 data[0];
- };
+@@ -160,6 +159,8 @@ struct pci_dev {
+ 					   this if your device has broken DMA
+ 					   or supports 64-bit transfers.  */
  
-+struct pcie_link_state;
- /*
-  * The pci_dev structure is used to describe PCI devices.
-  */
-@@ -164,13 +164,13 @@ struct pci_dev {
++	struct device_dma_parameters dma_parms;
++
+ 	pci_power_t     current_state;  /* Current operating state. In ACPI-speak,
  					   this is D0-D3, D0 being fully functional,
  					   and D3 being off. */
- 
-+#ifdef CONFIG_PCIEASPM
-+	struct pcie_link_state	*link_state;	/* ASPM link state. */
-+#endif
-+
+@@ -167,10 +168,6 @@ struct pci_dev {
  	pci_channel_state_t error_state;	/* current connectivity state */
  	struct	device	dev;		/* Generic device interface */
  
@@ -869347,7 +940750,7 @@
  	int		cfg_size;	/* Size of configuration space */
  
  	/*
-@@ -219,7 +219,7 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
+@@ -219,7 +216,7 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
  }
  
  static inline struct pci_cap_saved_state *pci_find_saved_cap(
@@ -869356,7 +940759,7 @@
  {
  	struct pci_cap_saved_state *tmp;
  	struct hlist_node *pos;
-@@ -278,13 +278,13 @@ struct pci_bus {
+@@ -278,13 +275,13 @@ struct pci_bus {
  	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
  	pci_bus_flags_t bus_flags;	/* Inherited by child busses */
  	struct device		*bridge;
@@ -869372,7 +940775,7 @@
  
  /*
   * Error values that may be returned by PCI functions.
-@@ -314,8 +314,8 @@ struct pci_raw_ops {
+@@ -314,8 +311,8 @@ struct pci_raw_ops {
  extern struct pci_raw_ops *raw_pci_ops;
  
  struct pci_bus_region {
@@ -869383,7 +940786,7 @@
  };
  
  struct pci_dynids {
-@@ -351,11 +351,10 @@ enum pci_ers_result {
+@@ -351,11 +348,10 @@ enum pci_ers_result {
  };
  
  /* PCI bus error event callbacks */
@@ -869397,7 +940800,7 @@
  
  	/* MMIO has been re-enabled, but not DMA */
  	pci_ers_result_t (*mmio_enabled)(struct pci_dev *dev);
-@@ -390,7 +389,7 @@ struct pci_driver {
+@@ -390,7 +386,7 @@ struct pci_driver {
  	struct pci_dynids dynids;
  };
  
@@ -869406,7 +940809,7 @@
  
  /**
   * PCI_DEVICE - macro used to describe a specific pci device
-@@ -448,7 +447,7 @@ extern int no_pci_devices(void);
+@@ -448,7 +444,7 @@ extern int no_pci_devices(void);
  
  void pcibios_fixup_bus(struct pci_bus *);
  int __must_check pcibios_enable_device(struct pci_dev *, int mask);
@@ -869415,7 +940818,7 @@
  
  /* Used only when drivers/pci/setup.c is used */
  void pcibios_align_resource(void *, struct resource *, resource_size_t,
-@@ -459,8 +458,10 @@ void pcibios_update_irq(struct pci_dev *, int irq);
+@@ -459,8 +455,10 @@ void pcibios_update_irq(struct pci_dev *, int irq);
  
  extern struct pci_bus *pci_find_bus(int domain, int busnr);
  void pci_bus_add_devices(struct pci_bus *bus);
@@ -869428,7 +940831,7 @@
  {
  	struct pci_bus *root_bus;
  	root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata);
-@@ -468,15 +469,18 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s
+@@ -468,15 +466,18 @@ static inline struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *s
  		pci_bus_add_devices(root_bus);
  	return root_bus;
  }
@@ -869451,7 +940854,7 @@
  int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge);
  extern struct pci_dev *pci_dev_get(struct pci_dev *dev);
  extern void pci_dev_put(struct pci_dev *dev);
-@@ -489,15 +493,19 @@ extern void pci_sort_breadthfirst(void);
+@@ -489,15 +490,19 @@ extern void pci_sort_breadthfirst(void);
  /* Generic PCI functions exported to card drivers */
  
  #ifdef CONFIG_PCI_LEGACY
@@ -869478,7 +940881,7 @@
  struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
  
  struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
-@@ -505,49 +513,58 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
+@@ -505,49 +510,58 @@ struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device,
  struct pci_dev *pci_get_device_reverse(unsigned int vendor, unsigned int device,
  				struct pci_dev *from);
  
@@ -869556,7 +940959,16 @@
  int __must_check pci_reenable_device(struct pci_dev *);
  int __must_check pcim_enable_device(struct pci_dev *pdev);
  void pcim_pin_device(struct pci_dev *pdev);
-@@ -576,14 +593,11 @@ int pcie_set_readrq(struct pci_dev *dev, int rq);
+@@ -568,6 +582,8 @@ void pci_intx(struct pci_dev *dev, int enable);
+ void pci_msi_off(struct pci_dev *dev);
+ int pci_set_dma_mask(struct pci_dev *dev, u64 mask);
+ int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
++int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
++int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
+ int pcix_get_max_mmrbc(struct pci_dev *dev);
+ int pcix_get_mmrbc(struct pci_dev *dev);
+ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc);
+@@ -576,14 +592,11 @@ int pcie_set_readrq(struct pci_dev *dev, int rq);
  void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno);
  int __must_check pci_assign_resource(struct pci_dev *dev, int i);
  int __must_check pci_assign_resource_fixed(struct pci_dev *dev, int i);
@@ -869571,7 +940983,7 @@
  size_t pci_get_rom_size(void __iomem *rom, size_t size);
  
  /* Power management related routines */
-@@ -594,7 +608,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
+@@ -594,7 +607,7 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state);
  int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable);
  
  /* Functions for PCI Hotplug drivers to use */
@@ -869580,7 +940992,7 @@
  
  /* Helper functions for low-level code (drivers/pci/setup-[bus,res].c) */
  void pci_bus_assign_resources(struct pci_bus *bus);
-@@ -631,16 +645,18 @@ static inline int __must_check pci_register_driver(struct pci_driver *driver)
+@@ -631,16 +644,18 @@ static inline int __must_check pci_register_driver(struct pci_driver *driver)
  	return __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME);
  }
  
@@ -869605,7 +941017,7 @@
  
  /* kmem_cache style wrapper around pci_alloc_consistent() */
  
-@@ -669,19 +685,36 @@ struct msix_entry {
+@@ -669,19 +684,36 @@ struct msix_entry {
  
  
  #ifndef CONFIG_PCI_MSI
@@ -869649,7 +941061,7 @@
  #endif
  
  #ifdef CONFIG_HT_IRQ
-@@ -702,7 +735,11 @@ extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
+@@ -702,7 +734,11 @@ extern void pci_unblock_user_cfg_access(struct pci_dev *dev);
  extern int pci_domains_supported;
  #else
  enum { pci_domains_supported = 0 };
@@ -869662,7 +941074,7 @@
  static inline int pci_proc_domain(struct pci_bus *bus)
  {
  	return 0;
-@@ -716,67 +753,161 @@ static inline int pci_proc_domain(struct pci_bus *bus)
+@@ -716,67 +752,173 @@ static inline int pci_proc_domain(struct pci_bus *bus)
   *  these as simple inline functions to avoid hair in drivers.
   */
  
@@ -869769,6 +941181,18 @@
 +	return -EIO;
 +}
 +
++static inline int pci_set_dma_max_seg_size(struct pci_dev *dev,
++					unsigned int size)
++{
++	return -EIO;
++}
++
++static inline int pci_set_dma_seg_boundary(struct pci_dev *dev,
++					unsigned long mask)
++{
++	return -EIO;
++}
++
 +static inline int pci_assign_resource(struct pci_dev *dev, int i)
 +{
 +	return -EBUSY;
@@ -869817,7 +941241,9 @@
 +{
 +	return 0;
 +}
-+
+ 
+-static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
+-static inline void pci_release_regions(struct pci_dev *dev) { }
 +static inline int pci_restore_state(struct pci_dev *dev)
 +{
 +	return 0;
@@ -869844,9 +941270,7 @@
 +{
 +	return -EIO;
 +}
- 
--static inline int pci_request_regions(struct pci_dev *dev, const char *res_name) { return -EIO; }
--static inline void pci_release_regions(struct pci_dev *dev) { }
++
 +static inline void pci_release_regions(struct pci_dev *dev)
 +{ }
  
@@ -869862,7 +941286,7 @@
  
  static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
  { return NULL; }
-@@ -797,27 +928,27 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
+@@ -797,27 +939,27 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
  
  /* these helpers provide future and backwards compatibility
   * for accessing popular PCI BAR info */
@@ -869901,7 +941325,7 @@
  {
  	dev_set_drvdata(&pdev->dev, data);
  }
-@@ -836,7 +967,7 @@ static inline char *pci_name(struct pci_dev *pdev)
+@@ -836,7 +978,7 @@ static inline char *pci_name(struct pci_dev *pdev)
   */
  #ifndef HAVE_ARCH_PCI_RESOURCE_TO_USER
  static inline void pci_resource_to_user(const struct pci_dev *dev, int bar,
@@ -869910,7 +941334,7 @@
  		resource_size_t *end)
  {
  	*start = rsrc->start;
-@@ -867,7 +998,7 @@ enum pci_fixup_pass {
+@@ -867,7 +1009,7 @@ enum pci_fixup_pass {
  
  /* Anonymous variables would be nice... */
  #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook)	\
@@ -869919,7 +941343,7 @@
  	__attribute__((__section__(#section))) = { vendor, device, hook };
  #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)			\
  	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\
-@@ -888,9 +1019,9 @@ enum pci_fixup_pass {
+@@ -888,9 +1030,9 @@ enum pci_fixup_pass {
  
  void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
  
@@ -869945,7 +941369,7 @@
  /* PCI Setting Record (Type 0) */
  struct hpp_type0 {
 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
-index 7f22151..41f6f28 100644
+index 7f22151..39d3283 100644
 --- a/include/linux/pci_ids.h
 +++ b/include/linux/pci_ids.h
 @@ -1943,6 +1943,7 @@
@@ -869956,7 +941380,31 @@
  #define PCI_DEVICE_ID_TIGON3_5705	0x1653
  #define PCI_DEVICE_ID_TIGON3_5705_2	0x1654
  #define PCI_DEVICE_ID_TIGON3_5720	0x1658
-@@ -2066,6 +2067,9 @@
+@@ -2042,6 +2043,23 @@
+ #define PCI_VENDOR_ID_QUICKNET		0x15e2
+ #define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
+ 
++/*
++ * ADDI-DATA GmbH communication cards <info at addi-data.com>
++ */
++#define PCI_VENDOR_ID_ADDIDATA_OLD             0x10E8
++#define PCI_VENDOR_ID_ADDIDATA                 0x15B8
++#define PCI_DEVICE_ID_ADDIDATA_APCI7500        0x7000
++#define PCI_DEVICE_ID_ADDIDATA_APCI7420        0x7001
++#define PCI_DEVICE_ID_ADDIDATA_APCI7300        0x7002
++#define PCI_DEVICE_ID_ADDIDATA_APCI7800        0x818E
++#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2      0x7009
++#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2      0x700A
++#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2      0x700B
++#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3      0x700C
++#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3      0x700D
++#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3      0x700E
++#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3      0x700F
++
+ #define PCI_VENDOR_ID_PDC		0x15e9
+ 
+ #define PCI_VENDOR_ID_FARSITE           0x1619
+@@ -2066,6 +2084,9 @@
  #define PCI_VENDOR_ID_NETCELL		0x169c
  #define PCI_DEVICE_ID_REVOLUTION	0x0044
  
@@ -869966,7 +941414,7 @@
  #define PCI_VENDOR_ID_VITESSE		0x1725
  #define PCI_DEVICE_ID_VITESSE_VSC7174	0x7174
  
-@@ -2078,6 +2082,16 @@
+@@ -2078,6 +2099,16 @@
  #define PCI_DEVICE_ID_ALTIMA_AC9100	0x03ea
  #define PCI_DEVICE_ID_ALTIMA_AC1003	0x03eb
  
@@ -869983,7 +941431,7 @@
  #define PCI_VENDOR_ID_LENOVO		0x17aa
  
  #define PCI_VENDOR_ID_ARECA		0x17d3
-@@ -2106,6 +2120,8 @@
+@@ -2106,6 +2137,8 @@
  #define PCI_DEVICE_ID_HERC_WIN		0x5732
  #define PCI_DEVICE_ID_HERC_UNI		0x5832
  
@@ -869992,28 +941440,6 @@
  #define PCI_VENDOR_ID_SITECOM		0x182d
  #define PCI_DEVICE_ID_SITECOM_DC105V2	0x3069
  
-diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
-index c1914a8..c0c1223 100644
---- a/include/linux/pci_regs.h
-+++ b/include/linux/pci_regs.h
-@@ -395,9 +395,17 @@
- #define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
- #define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
- #define PCI_EXP_LNKCAP		12	/* Link Capabilities */
-+#define  PCI_EXP_LNKCAP_ASPMS	0xc00	/* ASPM Support */
-+#define  PCI_EXP_LNKCAP_L0SEL	0x7000	/* L0s Exit Latency */
-+#define  PCI_EXP_LNKCAP_L1EL	0x38000	/* L1 Exit Latency */
-+#define  PCI_EXP_LNKCAP_CLKPM	0x40000	/* L1 Clock Power Management */
- #define PCI_EXP_LNKCTL		16	/* Link Control */
-+#define  PCI_EXP_LNKCTL_RL	0x20	/* Retrain Link */
-+#define  PCI_EXP_LNKCTL_CCC	0x40	/* Common Clock COnfiguration */
- #define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
- #define PCI_EXP_LNKSTA		18	/* Link Status */
-+#define  PCI_EXP_LNKSTA_LT	0x800	/* Link Training */
-+#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
- #define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
- #define PCI_EXP_SLTCTL		24	/* Slot Control */
- #define PCI_EXP_SLTSTA		26	/* Slot Status */
 diff --git a/include/linux/pcounter.h b/include/linux/pcounter.h
 new file mode 100644
 index 0000000..a82d9f2
@@ -870154,6 +941580,32 @@
  #define SADB_X_EALG_CAMELLIACBC		22
  #define SADB_EALG_MAX                   253 /* last EALG */
  /* private allocations should use 249-255 (RFC2407) */
+diff --git a/include/linux/phy.h b/include/linux/phy.h
+index 554836e..5e43ae7 100644
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -88,7 +88,7 @@ struct mii_bus {
+ 
+ 	/* A lock to ensure that only one thing can read/write
+ 	 * the MDIO bus at a time */
+-	spinlock_t mdio_lock;
++	struct mutex mdio_lock;
+ 
+ 	struct device *dev;
+ 
+@@ -284,10 +284,11 @@ struct phy_device {
+ 
+ 	/* Interrupt and Polling infrastructure */
+ 	struct work_struct phy_queue;
++	struct work_struct state_queue;
+ 	struct timer_list phy_timer;
+ 	atomic_t irq_disable;
+ 
+-	spinlock_t lock;
++	struct mutex lock;
+ 
+ 	struct net_device *attached_dev;
+ 
 diff --git a/include/linux/phy_fixed.h b/include/linux/phy_fixed.h
 index 04ba70d..509d8f5 100644
 --- a/include/linux/phy_fixed.h
@@ -870220,7 +941672,7 @@
  
  #endif /* __PHY_FIXED_H */
 diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
-index 30b8571..1c1dba9 100644
+index 30b8571..40fac8c 100644
 --- a/include/linux/pkt_cls.h
 +++ b/include/linux/pkt_cls.h
 @@ -328,6 +328,56 @@ enum
@@ -870280,6 +941732,16 @@
  /* Basic filter */
  
  enum
+@@ -409,7 +459,8 @@ enum
+ #define	TCF_EM_U32		3
+ #define	TCF_EM_META		4
+ #define	TCF_EM_TEXT		5
+-#define	TCF_EM_MAX		5
++#define        TCF_EM_VLAN		6
++#define	TCF_EM_MAX		6
+ 
+ enum
+ {
 diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
 index 919af93..dbb7ac3 100644
 --- a/include/linux/pkt_sched.h
@@ -870331,6 +941793,50 @@
  					struct resource *, unsigned int);
  
  extern struct platform_device *platform_device_alloc(const char *name, int id);
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index b78e029..eccf59e 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -95,7 +95,7 @@ struct pm_dev
+ };
+ 
+ /* Functions above this comment are list-based old-style power
+- * managment. Please avoid using them.  */
++ * management. Please avoid using them.  */
+ 
+ /*
+  * Callbacks for platform drivers to implement.
+diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
+new file mode 100644
+index 0000000..2e4e97b
+--- /dev/null
++++ b/include/linux/pm_qos_params.h
+@@ -0,0 +1,25 @@
++/* interface for the pm_qos_power infrastructure of the linux kernel.
++ *
++ * Mark Gross
++ */
++#include <linux/list.h>
++#include <linux/notifier.h>
++#include <linux/miscdevice.h>
++
++#define PM_QOS_RESERVED 0
++#define PM_QOS_CPU_DMA_LATENCY 1
++#define PM_QOS_NETWORK_LATENCY 2
++#define PM_QOS_NETWORK_THROUGHPUT 3
++
++#define PM_QOS_NUM_CLASSES 4
++#define PM_QOS_DEFAULT_VALUE -1
++
++int pm_qos_add_requirement(int qos, char *name, s32 value);
++int pm_qos_update_requirement(int qos, char *name, s32 new_value);
++void pm_qos_remove_requirement(int qos, char *name);
++
++int pm_qos_requirement(int qos);
++
++int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
++int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
++
 diff --git a/include/linux/pmu.h b/include/linux/pmu.h
 index b7824c2..4c5f653 100644
 --- a/include/linux/pmu.h
@@ -870378,6 +941884,19 @@
  
  #define PMU_MAX_BATTERIES	2
  
+diff --git a/include/linux/pnp.h b/include/linux/pnp.h
+index 2a6d62c..b9339d8 100644
+--- a/include/linux/pnp.h
++++ b/include/linux/pnp.h
+@@ -126,7 +126,7 @@ struct pnp_resource_table {
+ };
+ 
+ /*
+- * Device Managemnt
++ * Device Management
+  */
+ 
+ struct pnp_card {
 diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
 index 606c095..5cbf3e3 100644
 --- a/include/linux/power_supply.h
@@ -870416,11 +941935,41 @@
  	POWER_SUPPLY_PROP_TEMP,
  	POWER_SUPPLY_PROP_TEMP_AMBIENT,
  	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+diff --git a/include/linux/prctl.h b/include/linux/prctl.h
+index e2eff90..3800639 100644
+--- a/include/linux/prctl.h
++++ b/include/linux/prctl.h
+@@ -63,4 +63,8 @@
+ #define PR_GET_SECCOMP	21
+ #define PR_SET_SECCOMP	22
+ 
++/* Get/set the capability bounding set */
++#define PR_CAPBSET_READ 23
++#define PR_CAPBSET_DROP 24
++
+ #endif /* _LINUX_PRCTL_H */
 diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
-index a531682..8f92546 100644
+index a531682..e435515 100644
 --- a/include/linux/proc_fs.h
 +++ b/include/linux/proc_fs.h
-@@ -201,6 +201,8 @@ static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
+@@ -19,6 +19,8 @@ struct completion;
+  */
+ #define FIRST_PROCESS_ENTRY 256
+ 
++/* Worst case buffer size needed for holding an integer. */
++#define PROC_NUMBUF 13
+ 
+ /*
+  * We always define these enumerators
+@@ -117,7 +119,6 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
+ unsigned long task_vsize(struct mm_struct *);
+ int task_statm(struct mm_struct *, int *, int *, int *, int *);
+ char *task_mem(struct mm_struct *, char *);
+-void clear_refs_smap(struct mm_struct *mm);
+ 
+ struct proc_dir_entry *de_get(struct proc_dir_entry *de);
+ void de_put(struct proc_dir_entry *de);
+@@ -201,6 +202,8 @@ static inline struct proc_dir_entry *create_proc_info_entry(const char *name,
  extern struct proc_dir_entry *proc_net_fops_create(struct net *net,
  	const char *name, mode_t mode, const struct file_operations *fops);
  extern void proc_net_remove(struct net *net, const char *name);
@@ -870515,6 +942064,19 @@
  #endif
  
  #endif
+diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
+index b6116b4..b8ce2b4 100644
+--- a/include/linux/radix-tree.h
++++ b/include/linux/radix-tree.h
+@@ -91,7 +91,7 @@ do {									\
+  *
+  * For API usage, in general,
+  * - any function _modifying_ the tree or tags (inserting or deleting
+- *   items, setting or clearing tags must exclude other modifications, and
++ *   items, setting or clearing tags) must exclude other modifications, and
+  *   exclude any functions reading the tree.
+  * - any function _reading_ the tree or tags (looking up items or tags,
+  *   gang lookups) must exclude modifications to the tree, but may occur
 diff --git a/include/linux/rcuclassic.h b/include/linux/rcuclassic.h
 new file mode 100644
 index 0000000..4d66242
@@ -871123,6 +942685,19 @@
 +
 +#endif /* __KERNEL__ */
 +#endif /* __LINUX_RCUPREEMPT_TRACE_H */
+diff --git a/include/linux/reboot.h b/include/linux/reboot.h
+index 85ea63f..b93b541 100644
+--- a/include/linux/reboot.h
++++ b/include/linux/reboot.h
+@@ -59,8 +59,6 @@ extern void machine_crash_shutdown(struct pt_regs *);
+  * Architecture independent implemenations of sys_reboot commands.
+  */
+ 
+-extern void kernel_shutdown_prepare(enum system_states state);
+-
+ extern void kernel_restart(char *cmd);
+ extern void kernel_halt(void);
+ extern void kernel_power_off(void);
 diff --git a/include/linux/regset.h b/include/linux/regset.h
 new file mode 100644
 index 0000000..8abee65
@@ -871497,6 +943072,19 @@
 +
 +
 +#endif	/* <linux/regset.h> */
+diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
+index 10fa0c8..db5ef9b 100644
+--- a/include/linux/reiserfs_fs_sb.h
++++ b/include/linux/reiserfs_fs_sb.h
+@@ -185,7 +185,7 @@ struct reiserfs_journal {
+ 	unsigned long j_trans_id;
+ 	unsigned long j_mount_id;
+ 	unsigned long j_start;	/* start of current waiting commit (index into j_ap_blocks) */
+-	unsigned long j_len;	/* lenght of current waiting commit */
++	unsigned long j_len;	/* length of current waiting commit */
+ 	unsigned long j_len_alloc;	/* number of buffers requested by journal_begin() */
+ 	atomic_t j_wcount;	/* count of writers for current commit */
+ 	unsigned long j_bcount;	/* batch count. allows turning X transactions into 1 */
 diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
 index 0ce5e0b..e3ab21d 100644
 --- a/include/linux/rfkill.h
@@ -871516,7 +943104,7 @@
  };
  
 diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
-index 4e81836..b014f6b 100644
+index 4e81836..b9e1740 100644
 --- a/include/linux/rtnetlink.h
 +++ b/include/linux/rtnetlink.h
 @@ -100,6 +100,13 @@ enum {
@@ -871533,10 +943121,28 @@
  	__RTM_MAX,
  #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
  };
-@@ -613,11 +620,11 @@ extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
- ({	data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
- 	__rtattr_parse_nested_compat(tb, max, rta, len); })
+@@ -595,29 +602,17 @@ struct tcamsg
+ 
+ #include <linux/mutex.h>
+ 
+-extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
+ static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
+ {
+ 	int len = strlen(str) + 1;
+ 	return len > rta->rta_len || memcmp(RTA_DATA(rta), str, len);
+ }
  
+-extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
+-extern int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+-				        struct rtattr *rta, int len);
+-
+-#define rtattr_parse_nested(tb, max, rta) \
+-	rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
+-
+-#define rtattr_parse_nested_compat(tb, max, rta, data, len) \
+-({	data = RTA_PAYLOAD(rta) >= len ? RTA_DATA(rta) : NULL; \
+-	__rtattr_parse_nested_compat(tb, max, rta, len); })
+-
 -extern int rtnetlink_send(struct sk_buff *skb, u32 pid, u32 group, int echo);
 -extern int rtnl_unicast(struct sk_buff *skb, u32 pid);
 -extern int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
@@ -871713,7 +943319,7 @@
 +
  #endif /* _LINUX_SCATTERLIST_H */
 diff --git a/include/linux/sched.h b/include/linux/sched.h
-index cc14656..af6947e 100644
+index cc14656..9c13be3 100644
 --- a/include/linux/sched.h
 +++ b/include/linux/sched.h
 @@ -27,6 +27,7 @@
@@ -871822,7 +943428,21 @@
  extern signed long schedule_timeout_uninterruptible(signed long timeout);
  asmlinkage void schedule(void);
  
-@@ -552,18 +585,13 @@ struct user_struct {
+@@ -522,6 +555,13 @@ struct signal_struct {
+ #define SIGNAL_STOP_CONTINUED	0x00000004 /* SIGCONT since WCONTINUED reap */
+ #define SIGNAL_GROUP_EXIT	0x00000008 /* group exit in progress */
+ 
++/* If true, all threads except ->group_exit_task have pending SIGKILL */
++static inline int signal_group_exit(const struct signal_struct *sig)
++{
++	return	(sig->flags & SIGNAL_GROUP_EXIT) ||
++		(sig->group_exit_task != NULL);
++}
++
+ /*
+  * Some day this will be a full-fledged user tracking system..
+  */
+@@ -552,18 +592,13 @@ struct user_struct {
  #ifdef CONFIG_FAIR_USER_SCHED
  	struct task_group *tg;
  #ifdef CONFIG_SYSFS
@@ -871843,7 +943463,7 @@
  
  extern struct user_struct *find_user(uid_t);
  
-@@ -827,6 +855,7 @@ struct sched_class {
+@@ -827,6 +862,7 @@ struct sched_class {
  	void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup);
  	void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep);
  	void (*yield_task) (struct rq *rq);
@@ -871851,7 +943471,7 @@
  
  	void (*check_preempt_curr) (struct rq *rq, struct task_struct *p);
  
-@@ -842,11 +871,25 @@ struct sched_class {
+@@ -842,11 +878,25 @@ struct sched_class {
  	int (*move_one_task) (struct rq *this_rq, int this_cpu,
  			      struct rq *busiest, struct sched_domain *sd,
  			      enum cpu_idle_type idle);
@@ -871878,7 +943498,7 @@
  };
  
  struct load_weight {
-@@ -876,6 +919,8 @@ struct sched_entity {
+@@ -876,6 +926,8 @@ struct sched_entity {
  #ifdef CONFIG_SCHEDSTATS
  	u64			wait_start;
  	u64			wait_max;
@@ -871887,7 +943507,7 @@
  
  	u64			sleep_start;
  	u64			sleep_max;
-@@ -914,6 +959,21 @@ struct sched_entity {
+@@ -914,6 +966,21 @@ struct sched_entity {
  #endif
  };
  
@@ -871909,7 +943529,7 @@
  struct task_struct {
  	volatile long state;	/* -1 unrunnable, 0 runnable, >0 stopped */
  	void *stack;
-@@ -930,16 +990,15 @@ struct task_struct {
+@@ -930,16 +997,15 @@ struct task_struct {
  #endif
  
  	int prio, static_prio, normal_prio;
@@ -871927,7 +943547,7 @@
  	/*
  	 * fpu_counter contains the number of consecutive context switches
  	 * that the FPU is used. If this is over a threshold, the lazy fpu
-@@ -956,7 +1015,11 @@ struct task_struct {
+@@ -956,7 +1022,11 @@ struct task_struct {
  
  	unsigned int policy;
  	cpumask_t cpus_allowed;
@@ -871940,7 +943560,16 @@
  
  #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT)
  	struct sched_info sched_info;
-@@ -1046,6 +1109,11 @@ struct task_struct {
+@@ -1028,7 +1098,7 @@ struct task_struct {
+ 	uid_t uid,euid,suid,fsuid;
+ 	gid_t gid,egid,sgid,fsgid;
+ 	struct group_info *group_info;
+-	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted;
++	kernel_cap_t   cap_effective, cap_inheritable, cap_permitted, cap_bset;
+ 	unsigned keep_capabilities:1;
+ 	struct user_struct *user;
+ #ifdef CONFIG_KEYS
+@@ -1046,6 +1116,11 @@ struct task_struct {
  /* ipc stuff */
  	struct sysv_sem sysvsem;
  #endif
@@ -871952,7 +943581,7 @@
  /* CPU-specific state of this task */
  	struct thread_struct thread;
  /* filesystem information */
-@@ -1071,6 +1139,10 @@ struct task_struct {
+@@ -1071,6 +1146,10 @@ struct task_struct {
  	void *security;
  #endif
  	struct audit_context *audit_context;
@@ -871963,7 +943592,7 @@
  	seccomp_t seccomp;
  
  /* Thread group tracking */
-@@ -1178,6 +1250,10 @@ struct task_struct {
+@@ -1178,6 +1257,10 @@ struct task_struct {
  	int make_it_fail;
  #endif
  	struct prop_local_single dirties;
@@ -871974,7 +943603,7 @@
  };
  
  /*
-@@ -1458,6 +1534,12 @@ extern unsigned int sysctl_sched_child_runs_first;
+@@ -1458,6 +1541,12 @@ extern unsigned int sysctl_sched_child_runs_first;
  extern unsigned int sysctl_sched_features;
  extern unsigned int sysctl_sched_migration_cost;
  extern unsigned int sysctl_sched_nr_migrate;
@@ -871987,7 +943616,16 @@
  
  int sched_nr_latency_handler(struct ctl_table *table, int write,
  		struct file *file, void __user *buffer, size_t *length,
-@@ -1837,7 +1919,14 @@ static inline int signal_pending(struct task_struct *p)
+@@ -1688,7 +1777,7 @@ extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned lon
+ struct task_struct *fork_idle(int);
+ 
+ extern void set_task_comm(struct task_struct *tsk, char *from);
+-extern void get_task_comm(char *to, struct task_struct *tsk);
++extern char *get_task_comm(char *to, struct task_struct *tsk);
+ 
+ #ifdef CONFIG_SMP
+ extern void wait_task_inactive(struct task_struct * p);
+@@ -1837,7 +1926,14 @@ static inline int signal_pending(struct task_struct *p)
  {
  	return unlikely(test_tsk_thread_flag(p,TIF_SIGPENDING));
  }
@@ -872003,7 +943641,7 @@
  static inline int need_resched(void)
  {
  	return unlikely(test_thread_flag(TIF_NEED_RESCHED));
-@@ -1850,29 +1939,33 @@ static inline int need_resched(void)
+@@ -1850,29 +1946,33 @@ static inline int need_resched(void)
   * cond_resched_lock() will drop the spinlock before scheduling,
   * cond_resched_softirq() will enable bhs before scheduling.
   */
@@ -872052,24 +943690,38 @@
  }
  
  /*
+@@ -1987,6 +2087,10 @@ static inline void migration_init(void)
+ }
+ #endif
+ 
++#ifndef TASK_SIZE_OF
++#define TASK_SIZE_OF(tsk)	TASK_SIZE
++#endif
++
+ #endif /* __KERNEL__ */
+ 
+ #endif
 diff --git a/include/linux/security.h b/include/linux/security.h
-index ac05083..d249742 100644
+index ac05083..fe52cde 100644
 --- a/include/linux/security.h
 +++ b/include/linux/security.h
-@@ -34,6 +34,12 @@
+@@ -34,10 +34,11 @@
  #include <linux/xfrm.h>
  #include <net/flow.h>
  
+-/*
+- * Bounding set
+- */
+-extern kernel_cap_t cap_bset;
 +/* only a char in selinux superblock security struct flags */
 +#define FSCONTEXT_MNT		0x01
 +#define CONTEXT_MNT		0x02
 +#define ROOTCONTEXT_MNT		0x04
 +#define DEFCONTEXT_MNT		0x08
-+
- /*
-  * Bounding set
-  */
-@@ -243,9 +249,6 @@ struct request_sock;
+ 
+ extern unsigned securebits;
+ 
+@@ -243,9 +244,6 @@ struct request_sock;
   *	@mnt contains the mounted file system.
   *	@flags contains the new filesystem flags.
   *	@data contains the filesystem-specific data.
@@ -872079,7 +943731,7 @@
   * @sb_post_addmount:
   *	Update the security module's state when a filesystem is mounted.
   *	This hook is called any time a mount is successfully grafetd to
-@@ -261,6 +264,22 @@ struct request_sock;
+@@ -261,6 +259,22 @@ struct request_sock;
   *	Update module state after a successful pivot.
   *	@old_nd contains the nameidata structure for the old root.
   *      @new_nd contains the nameidata structure for the new root.
@@ -872102,7 +943754,29 @@
   *
   * Security hooks for inode operations.
   *
-@@ -1183,6 +1202,10 @@ struct request_sock;
+@@ -404,15 +418,12 @@ struct request_sock;
+  * 	identified by @name for @dentry.
+  * 	Return 0 if permission is granted.
+  * @inode_getsecurity:
+- *	Copy the extended attribute representation of the security label 
+- *	associated with @name for @inode into @buffer.  @buffer may be
+- *	NULL to request the size of the buffer required.  @size indicates
+- *	the size of @buffer in bytes.  Note that @name is the remainder
+- *	of the attribute name after the security. prefix has been removed.
+- *	@err is the return value from the preceding fs getxattr call,
+- *	and can be used by the security module to determine whether it
+- *	should try and canonicalize the attribute value.
+- *	Return number of bytes used/required on success.
++ *	Retrieve a copy of the extended attribute representation of the
++ *	security label associated with @name for @inode via @buffer.  Note that
++ *	@name is the remainder of the attribute name after the security prefix
++ *	has been removed. @alloc is used to specify of the call should return a
++ *	value via the buffer or just the value length Return size of buffer on
++ *	success.
+  * @inode_setsecurity:
+  *	Set the security label associated with @name for @inode from the
+  *	extended attribute value @value.  @size indicates the size of the
+@@ -1183,6 +1194,10 @@ struct request_sock;
   *	Convert secid to security context.
   *	@secid contains the security ID.
   *	@secdata contains the pointer that stores the converted security context.
@@ -872113,7 +943787,7 @@
   *
   * @release_secctx:
   *	Release the security context.
-@@ -1235,13 +1258,19 @@ struct security_operations {
+@@ -1235,13 +1250,19 @@ struct security_operations {
  	void (*sb_umount_busy) (struct vfsmount * mnt);
  	void (*sb_post_remount) (struct vfsmount * mnt,
  				 unsigned long flags, void *data);
@@ -872134,7 +943808,16 @@
  
  	int (*inode_alloc_security) (struct inode *inode);	
  	void (*inode_free_security) (struct inode *inode);
-@@ -1371,6 +1400,7 @@ struct security_operations {
+@@ -1275,7 +1296,7 @@ struct security_operations {
+ 	int (*inode_removexattr) (struct dentry *dentry, char *name);
+ 	int (*inode_need_killpriv) (struct dentry *dentry);
+ 	int (*inode_killpriv) (struct dentry *dentry);
+-  	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
++	int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
+   	int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+   	int (*inode_listsecurity)(struct inode *inode, char *buffer, size_t buffer_size);
+ 
+@@ -1371,6 +1392,7 @@ struct security_operations {
   	int (*getprocattr)(struct task_struct *p, char *name, char **value);
   	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
  	int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
@@ -872142,7 +943825,7 @@
  	void (*release_secctx)(char *secdata, u32 seclen);
  
  #ifdef CONFIG_SECURITY_NETWORK
-@@ -1495,10 +1525,16 @@ int security_sb_umount(struct vfsmount *mnt, int flags);
+@@ -1495,10 +1517,16 @@ int security_sb_umount(struct vfsmount *mnt, int flags);
  void security_sb_umount_close(struct vfsmount *mnt);
  void security_sb_umount_busy(struct vfsmount *mnt);
  void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data);
@@ -872160,7 +943843,16 @@
  int security_inode_alloc(struct inode *inode);
  void security_inode_free(struct inode *inode);
  int security_inode_init_security(struct inode *inode, struct inode *dir,
-@@ -1603,6 +1639,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t
+@@ -1529,7 +1557,7 @@ int security_inode_listxattr(struct dentry *dentry);
+ int security_inode_removexattr(struct dentry *dentry, char *name);
+ int security_inode_need_killpriv(struct dentry *dentry);
+ int security_inode_killpriv(struct dentry *dentry);
+-int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
++int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
+ int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
+ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
+ int security_file_permission(struct file *file, int mask);
+@@ -1603,6 +1631,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t
  int security_netlink_send(struct sock *sk, struct sk_buff *skb);
  int security_netlink_recv(struct sk_buff *skb, int cap);
  int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
@@ -872168,7 +943860,7 @@
  void security_release_secctx(char *secdata, u32 seclen);
  
  #else /* CONFIG_SECURITY */
-@@ -1777,9 +1814,6 @@ static inline void security_sb_post_remount (struct vfsmount *mnt,
+@@ -1777,9 +1806,6 @@ static inline void security_sb_post_remount (struct vfsmount *mnt,
  					     unsigned long flags, void *data)
  { }
  
@@ -872178,7 +943870,16 @@
  static inline void security_sb_post_addmount (struct vfsmount *mnt,
  					      struct nameidata *mountpoint_nd)
  { }
-@@ -2266,7 +2300,7 @@ static inline struct dentry *securityfs_create_file(const char *name,
+@@ -1933,7 +1959,7 @@ static inline int security_inode_killpriv(struct dentry *dentry)
+ 	return cap_inode_killpriv(dentry);
+ }
+ 
+-static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
++static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
+ {
+ 	return -EOPNOTSUPP;
+ }
+@@ -2266,7 +2292,7 @@ static inline struct dentry *securityfs_create_file(const char *name,
  						mode_t mode,
  						struct dentry *parent,
  						void *data,
@@ -872187,7 +943888,7 @@
  {
  	return ERR_PTR(-ENODEV);
  }
-@@ -2280,6 +2314,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle
+@@ -2280,6 +2306,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle
  	return -EOPNOTSUPP;
  }
  
@@ -872294,8 +943995,33 @@
 +
  #endif
  #endif
+diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
+index afe0f6d..00b65c0 100644
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -23,6 +23,7 @@ struct plat_serial8250_port {
+ 	resource_size_t	mapbase;	/* resource base */
+ 	unsigned int	irq;		/* interrupt number */
+ 	unsigned int	uartclk;	/* UART clock rate */
++	void            *private_data;
+ 	unsigned char	regshift;	/* register shift */
+ 	unsigned char	iotype;		/* UPIO_* */
+ 	unsigned char	hub6;
+diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
+index 86f9b1e..ea037f2 100644
+--- a/include/linux/signalfd.h
++++ b/include/linux/signalfd.h
+@@ -29,7 +29,7 @@ struct signalfd_siginfo {
+ 
+ 	/*
+ 	 * Pad strcture to 128 bytes. Remember to update the
+-	 * pad size when you add new memebers. We use a fixed
++	 * pad size when you add new members. We use a fixed
+ 	 * size structure to avoid compatibility problems with
+ 	 * future versions, and we leave extra space for additional
+ 	 * members. We use fixed size members because this strcture
 diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
-index bddd50b..dfe975a 100644
+index bddd50b..412672a 100644
 --- a/include/linux/skbuff.h
 +++ b/include/linux/skbuff.h
 @@ -95,6 +95,7 @@
@@ -872354,6 +944080,59 @@
  extern void	       skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
  extern void	       skb_split(struct sk_buff *skb,
  				 struct sk_buff *skb1, const u32 len);
+@@ -1804,5 +1810,6 @@ static inline void skb_forward_csum(struct sk_buff *skb)
+ 		skb->ip_summed = CHECKSUM_NONE;
+ }
+ 
++bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off);
+ #endif	/* __KERNEL__ */
+ #endif	/* _LINUX_SKBUFF_H */
+diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
+index 40801e7..ddb1a70 100644
+--- a/include/linux/slub_def.h
++++ b/include/linux/slub_def.h
+@@ -12,11 +12,11 @@
+ #include <linux/kobject.h>
+ 
+ struct kmem_cache_cpu {
+-	void **freelist;
+-	struct page *page;
+-	int node;
+-	unsigned int offset;
+-	unsigned int objsize;
++	void **freelist;	/* Pointer to first free per cpu object */
++	struct page *page;	/* The slab from which we are allocating */
++	int node;		/* The node of the page (or -1 for debug) */
++	unsigned int offset;	/* Freepointer offset (in word units) */
++	unsigned int objsize;	/* Size of an object (from kmem_cache) */
+ };
+ 
+ struct kmem_cache_node {
+@@ -59,7 +59,10 @@ struct kmem_cache {
+ #endif
+ 
+ #ifdef CONFIG_NUMA
+-	int defrag_ratio;
++	/*
++	 * Defragmentation by allocating from a remote node.
++	 */
++	int remote_node_defrag_ratio;
+ 	struct kmem_cache_node *node[MAX_NUMNODES];
+ #endif
+ #ifdef CONFIG_SMP
+diff --git a/include/linux/sm501-regs.h b/include/linux/sm501-regs.h
+index df7620d..64236b7 100644
+--- a/include/linux/sm501-regs.h
++++ b/include/linux/sm501-regs.h
+@@ -171,7 +171,7 @@
+ /* USB slave/gadget data port base */
+ #define SM501_USB_GADGET_DATA		(0x070000)
+ 
+-/* Display contoller/video engine base */
++/* Display controller/video engine base */
+ #define SM501_DC			(0x080000)
+ 
+ /* common defines for the SM501 address registers */
 diff --git a/include/linux/smp.h b/include/linux/smp.h
 index c25e66b..55232cc 100644
 --- a/include/linux/smp.h
@@ -872464,6 +944243,36 @@
  #define PF_TIPC		AF_TIPC
  #define PF_BLUETOOTH	AF_BLUETOOTH
  #define PF_IUCV		AF_IUCV
+diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h
+new file mode 100644
+index 0000000..835ddf4
+--- /dev/null
++++ b/include/linux/spi/mcp23s08.h
+@@ -0,0 +1,24 @@
++
++/* FIXME driver should be able to handle all four slaves that
++ * can be hooked up to each chipselect, as well as IRQs...
++ */
++
++struct mcp23s08_platform_data {
++	/* four slaves can share one SPI chipselect */
++	u8		slave;
++
++	/* number assigned to the first GPIO */
++	unsigned	base;
++
++	/* pins with pullups */
++	u8		pullups;
++
++	void		*context;	/* param to setup/teardown */
++
++	int		(*setup)(struct spi_device *spi,
++					int gpio, unsigned ngpio,
++					void *context);
++	int		(*teardown)(struct spi_device *spi,
++					int gpio, unsigned ngpio,
++					void *context);
++};
 diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
 index c376f3b..1244497 100644
 --- a/include/linux/spinlock.h
@@ -872481,6 +944290,19 @@
  /**
   * spin_unlock_wait - wait until the spinlock gets unlocked
   * @lock: the spinlock in question.
+diff --git a/include/linux/spinlock_api_up.h b/include/linux/spinlock_api_up.h
+index 67faa04..04e1d31 100644
+--- a/include/linux/spinlock_api_up.h
++++ b/include/linux/spinlock_api_up.h
+@@ -21,7 +21,7 @@
+ /*
+  * In the UP-nondebug case there's no real locking going on, so the
+  * only thing we have to do is to keep the preempt counts and irq
+- * flags straight, to supress compiler warnings of unused lock
++ * flags straight, to suppress compiler warnings of unused lock
+  * variables, and to add the proper checker annotations:
+  */
+ #define __LOCK(lock) \
 diff --git a/include/linux/spinlock_types.h b/include/linux/spinlock_types.h
 index f6a3a95..68d88f7 100644
 --- a/include/linux/spinlock_types.h
@@ -873741,7 +945563,7 @@
  static inline void xprt_set_connected(struct rpc_xprt *xprt)
  {
 diff --git a/include/linux/suspend.h b/include/linux/suspend.h
-index 4360e08..646ce2d 100644
+index 4360e08..1d7d4c5 100644
 --- a/include/linux/suspend.h
 +++ b/include/linux/suspend.h
 @@ -38,18 +38,16 @@ typedef int __bitwise suspend_state_t;
@@ -873804,7 +945626,13 @@
  };
  
  #ifdef CONFIG_SUSPEND
-@@ -129,14 +136,17 @@ extern void mark_free_pages(struct zone *zone);
+@@ -123,20 +130,22 @@ struct pbe {
+ };
+ 
+ /* mm/page_alloc.c */
+-extern void drain_local_pages(void);
+ extern void mark_free_pages(struct zone *zone);
+ 
  /**
   * struct platform_hibernation_ops - hibernation platform support
   *
@@ -873826,7 +945654,7 @@
   * @pre_snapshot: Prepare the platform for creating the hibernation image.
   *	Called right after devices have been frozen and before the nonboot
   *	CPUs are disabled (runs with IRQs on).
-@@ -171,7 +181,8 @@ extern void mark_free_pages(struct zone *zone);
+@@ -171,7 +180,8 @@ extern void mark_free_pages(struct zone *zone);
   *	thawing devices (runs with IRQs on).
   */
  struct platform_hibernation_ops {
@@ -873836,7 +945664,7 @@
  	int (*pre_snapshot)(void);
  	void (*finish)(void);
  	int (*prepare)(void);
-@@ -211,22 +222,10 @@ static inline int hibernate(void) { return -ENOSYS; }
+@@ -211,22 +221,10 @@ static inline int hibernate(void) { return -ENOSYS; }
  #ifdef CONFIG_PM_SLEEP
  void save_processor_state(void);
  void restore_processor_state(void);
@@ -873899,11 +945727,127 @@
 +#define SNAPSHOT_IOC_MAXNR	20
 +
 +#endif /* _LINUX_SUSPEND_IOCTLS_H */
+diff --git a/include/linux/swap.h b/include/linux/swap.h
+index 4f3838a..353153e 100644
+--- a/include/linux/swap.h
++++ b/include/linux/swap.h
+@@ -158,9 +158,6 @@ struct swap_list_t {
+ /* Swap 50% full? Release swapcache more aggressively.. */
+ #define vm_swap_full() (nr_swap_pages*2 < total_swap_pages)
+ 
+-/* linux/mm/memory.c */
+-extern void swapin_readahead(swp_entry_t, unsigned long, struct vm_area_struct *);
+-
+ /* linux/mm/page_alloc.c */
+ extern unsigned long totalram_pages;
+ extern unsigned long totalreserve_pages;
+@@ -223,16 +220,17 @@ extern struct address_space swapper_space;
+ #define total_swapcache_pages  swapper_space.nrpages
+ extern void show_swap_cache_info(void);
+ extern int add_to_swap(struct page *, gfp_t);
++extern int add_to_swap_cache(struct page *, swp_entry_t, gfp_t);
+ extern void __delete_from_swap_cache(struct page *);
+ extern void delete_from_swap_cache(struct page *);
+-extern int move_to_swap_cache(struct page *, swp_entry_t);
+-extern int move_from_swap_cache(struct page *, unsigned long,
+-		struct address_space *);
+ extern void free_page_and_swap_cache(struct page *);
+ extern void free_pages_and_swap_cache(struct page **, int);
+-extern struct page * lookup_swap_cache(swp_entry_t);
+-extern struct page * read_swap_cache_async(swp_entry_t, struct vm_area_struct *vma,
+-					   unsigned long addr);
++extern struct page *lookup_swap_cache(swp_entry_t);
++extern struct page *read_swap_cache_async(swp_entry_t, gfp_t,
++			struct vm_area_struct *vma, unsigned long addr);
++extern struct page *swapin_readahead(swp_entry_t, gfp_t,
++			struct vm_area_struct *vma, unsigned long addr);
++
+ /* linux/mm/swapfile.c */
+ extern long total_swap_pages;
+ extern unsigned int nr_swapfiles;
+@@ -306,7 +304,7 @@ static inline void swap_free(swp_entry_t swp)
+ {
+ }
+ 
+-static inline struct page *read_swap_cache_async(swp_entry_t swp,
++static inline struct page *swapin_readahead(swp_entry_t swp, gfp_t gfp_mask,
+ 			struct vm_area_struct *vma, unsigned long addr)
+ {
+ 	return NULL;
+@@ -317,22 +315,12 @@ static inline struct page *lookup_swap_cache(swp_entry_t swp)
+ 	return NULL;
+ }
+ 
+-static inline int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
+-{
+-	return 0;
+-}
+-
+ #define can_share_swap_page(p)			(page_mapcount(p) == 1)
+ 
+-static inline int move_to_swap_cache(struct page *page, swp_entry_t entry)
+-{
+-	return 1;
+-}
+-
+-static inline int move_from_swap_cache(struct page *page, unsigned long index,
+-					struct address_space *mapping)
++static inline int add_to_swap_cache(struct page *page, swp_entry_t entry,
++							gfp_t gfp_mask)
+ {
+-	return 1;
++	return -1;
+ }
+ 
+ static inline void __delete_from_swap_cache(struct page *page)
+diff --git a/include/linux/swapops.h b/include/linux/swapops.h
+index ceb6cc5..7bf2d14 100644
+--- a/include/linux/swapops.h
++++ b/include/linux/swapops.h
+@@ -42,6 +42,12 @@ static inline pgoff_t swp_offset(swp_entry_t entry)
+ 	return entry.val & SWP_OFFSET_MASK(entry);
+ }
+ 
++/* check whether a pte points to a swap entry */
++static inline int is_swap_pte(pte_t pte)
++{
++	return !pte_none(pte) && !pte_present(pte) && !pte_file(pte);
++}
++
+ /*
+  * Convert the arch-dependent pte representation of a swp_entry_t into an
+  * arch-independent swp_entry_t.
+diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
+index 61def7c..4c2577b 100644
+--- a/include/linux/syscalls.h
++++ b/include/linux/syscalls.h
+@@ -607,8 +607,11 @@ asmlinkage long sys_set_robust_list(struct robust_list_head __user *head,
+ 				    size_t len);
+ asmlinkage long sys_getcpu(unsigned __user *cpu, unsigned __user *node, struct getcpu_cache __user *cache);
+ asmlinkage long sys_signalfd(int ufd, sigset_t __user *user_mask, size_t sizemask);
+-asmlinkage long sys_timerfd(int ufd, int clockid, int flags,
+-			    const struct itimerspec __user *utmr);
++asmlinkage long sys_timerfd_create(int clockid, int flags);
++asmlinkage long sys_timerfd_settime(int ufd, int flags,
++				    const struct itimerspec __user *utmr,
++				    struct itimerspec __user *otmr);
++asmlinkage long sys_timerfd_gettime(int ufd, struct itimerspec __user *otmr);
+ asmlinkage long sys_eventfd(unsigned int count);
+ asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len);
+ 
 diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
-index 4f5047d..bf4ae4e 100644
+index 4f5047d..571f01d 100644
 --- a/include/linux/sysctl.h
 +++ b/include/linux/sysctl.h
-@@ -440,8 +440,8 @@ enum
+@@ -102,7 +102,6 @@ enum
+ 	KERN_NODENAME=7,
+ 	KERN_DOMAINNAME=8,
+ 
+-	KERN_CAP_BSET=14,	/* int: capability bounding set */
+ 	KERN_PANIC=15,		/* int: panic timeout */
+ 	KERN_REALROOTDEV=16,	/* real root device to mount after initrd */
+ 
+@@ -440,8 +439,8 @@ enum
  
  enum {
  	NET_IPV4_ROUTE_FLUSH=1,
@@ -873914,7 +945858,7 @@
  	NET_IPV4_ROUTE_GC_THRESH=4,
  	NET_IPV4_ROUTE_MAX_SIZE=5,
  	NET_IPV4_ROUTE_GC_MIN_INTERVAL=6,
-@@ -945,7 +945,10 @@ enum
+@@ -945,7 +944,10 @@ enum
  
  /* For the /proc/sys support */
  struct ctl_table;
@@ -873925,7 +945869,16 @@
  extern void sysctl_head_finish(struct ctl_table_header *prev);
  extern int sysctl_perm(struct ctl_table *table, int op);
  
-@@ -1049,6 +1052,13 @@ struct ctl_table
+@@ -962,8 +964,6 @@ extern int proc_dostring(struct ctl_table *, int, struct file *,
+ 			 void __user *, size_t *, loff_t *);
+ extern int proc_dointvec(struct ctl_table *, int, struct file *,
+ 			 void __user *, size_t *, loff_t *);
+-extern int proc_dointvec_bset(struct ctl_table *, int, struct file *,
+-			      void __user *, size_t *, loff_t *);
+ extern int proc_dointvec_minmax(struct ctl_table *, int, struct file *,
+ 				void __user *, size_t *, loff_t *);
+ extern int proc_dointvec_jiffies(struct ctl_table *, int, struct file *,
+@@ -1049,6 +1049,13 @@ struct ctl_table
  	void *extra2;
  };
  
@@ -873939,7 +945892,7 @@
  /* struct ctl_table_header is used to maintain dynamic lists of
     struct ctl_table trees. */
  struct ctl_table_header
-@@ -1057,12 +1067,26 @@ struct ctl_table_header
+@@ -1057,12 +1064,26 @@ struct ctl_table_header
  	struct list_head ctl_entry;
  	int used;
  	struct completion *unregistering;
@@ -873992,6 +945945,18 @@
  	struct attribute	**attrs;
  };
  
+diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
+index e21937c..c50d2ba 100644
+--- a/include/linux/tc_ematch/tc_em_meta.h
++++ b/include/linux/tc_ematch/tc_em_meta.h
+@@ -81,6 +81,7 @@ enum
+  	TCF_META_ID_SK_SNDTIMEO,
+  	TCF_META_ID_SK_SENDMSG_OFF,
+  	TCF_META_ID_SK_WRITE_PENDING,
++	TCF_META_ID_VLAN_TAG,
+ 	__TCF_META_ID_MAX
+ };
+ #define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
 diff --git a/include/linux/tcp.h b/include/linux/tcp.h
 index bac17c5..08027f1 100644
 --- a/include/linux/tcp.h
@@ -876401,11 +948366,493 @@
  	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
  };
  
+diff --git a/include/linux/virtio.h b/include/linux/virtio.h
+index 14e1379..260d1fc 100644
+--- a/include/linux/virtio.h
++++ b/include/linux/virtio.h
+@@ -11,15 +11,13 @@
+ /**
+  * virtqueue - a queue to register buffers for sending or receiving.
+  * @callback: the function to call when buffers are consumed (can be NULL).
+- *    If this returns false, callbacks are suppressed until vq_ops->restart
+- *    is called.
+  * @vdev: the virtio device this queue was created for.
+  * @vq_ops: the operations for this virtqueue (see below).
+  * @priv: a pointer for the virtqueue implementation to use.
+  */
+ struct virtqueue
+ {
+-	bool (*callback)(struct virtqueue *vq);
++	void (*callback)(struct virtqueue *vq);
+ 	struct virtio_device *vdev;
+ 	struct virtqueue_ops *vq_ops;
+ 	void *priv;
+@@ -41,13 +39,12 @@ struct virtqueue
+  *	vq: the struct virtqueue we're talking about.
+  *	len: the length written into the buffer
+  *	Returns NULL or the "data" token handed to add_buf.
+- * @restart: restart callbacks after callback returned false.
++ * @disable_cb: disable callbacks
++ *	vq: the struct virtqueue we're talking about.
++ * @enable_cb: restart callbacks after disable_cb.
+  *	vq: the struct virtqueue we're talking about.
+  *	This returns "false" (and doesn't re-enable) if there are pending
+  *	buffers in the queue, to avoid a race.
+- * @shutdown: "unadd" all buffers.
+- *	vq: the struct virtqueue we're talking about.
+- *	Remove everything from the queue.
+  *
+  * Locking rules are straightforward: the driver is responsible for
+  * locking.  No two operations may be invoked simultaneously.
+@@ -65,9 +62,8 @@ struct virtqueue_ops {
+ 
+ 	void *(*get_buf)(struct virtqueue *vq, unsigned int *len);
+ 
+-	bool (*restart)(struct virtqueue *vq);
+-
+-	void (*shutdown)(struct virtqueue *vq);
++	void (*disable_cb)(struct virtqueue *vq);
++	bool (*enable_cb)(struct virtqueue *vq);
+ };
+ 
+ /**
+@@ -97,12 +93,15 @@ void unregister_virtio_device(struct virtio_device *dev);
+  * @probe: the function to call when a device is found.  Returns a token for
+  *    remove, or PTR_ERR().
+  * @remove: the function when a device is removed.
++ * @config_changed: optional function to call when the device configuration
++ *    changes; may be called in interrupt context.
+  */
+ struct virtio_driver {
+ 	struct device_driver driver;
+ 	const struct virtio_device_id *id_table;
+ 	int (*probe)(struct virtio_device *dev);
+ 	void (*remove)(struct virtio_device *dev);
++	void (*config_changed)(struct virtio_device *dev);
+ };
+ 
+ int register_virtio_driver(struct virtio_driver *drv);
+diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h
+new file mode 100644
+index 0000000..979524e
+--- /dev/null
++++ b/include/linux/virtio_balloon.h
+@@ -0,0 +1,18 @@
++#ifndef _LINUX_VIRTIO_BALLOON_H
++#define _LINUX_VIRTIO_BALLOON_H
++#include <linux/virtio_config.h>
++
++/* The ID for virtio_balloon */
++#define VIRTIO_ID_BALLOON	5
++
++/* The feature bitmap for virtio balloon */
++#define VIRTIO_BALLOON_F_MUST_TELL_HOST	0 /* Tell before reclaiming pages */
++
++struct virtio_balloon_config
++{
++	/* Number of pages host wants Guest to give up. */
++	__le32 num_pages;
++	/* Number of pages we've actually got in balloon. */
++	__le32 actual;
++};
++#endif /* _LINUX_VIRTIO_BALLOON_H */
+diff --git a/include/linux/virtio_blk.h b/include/linux/virtio_blk.h
+index 7bd2bce..bca0b10 100644
+--- a/include/linux/virtio_blk.h
++++ b/include/linux/virtio_blk.h
+@@ -6,15 +6,19 @@
+ #define VIRTIO_ID_BLOCK	2
+ 
+ /* Feature bits */
+-#define VIRTIO_CONFIG_BLK_F	0x40
+-#define VIRTIO_BLK_F_BARRIER	1	/* Does host support barriers? */
++#define VIRTIO_BLK_F_BARRIER	0	/* Does host support barriers? */
++#define VIRTIO_BLK_F_SIZE_MAX	1	/* Indicates maximum segment size */
++#define VIRTIO_BLK_F_SEG_MAX	2	/* Indicates maximum # of segments */
+ 
+-/* The capacity (in 512-byte sectors). */
+-#define VIRTIO_CONFIG_BLK_F_CAPACITY	0x41
+-/* The maximum segment size. */
+-#define VIRTIO_CONFIG_BLK_F_SIZE_MAX	0x42
+-/* The maximum number of segments. */
+-#define VIRTIO_CONFIG_BLK_F_SEG_MAX	0x43
++struct virtio_blk_config
++{
++	/* The capacity (in 512-byte sectors). */
++	__le64 capacity;
++	/* The maximum segment size (if VIRTIO_BLK_F_SIZE_MAX) */
++	__le32 size_max;
++	/* The maximum number of segments (if VIRTIO_BLK_F_SEG_MAX) */
++	__le32 seg_max;
++} __attribute__((packed));
+ 
+ /* These two define direction. */
+ #define VIRTIO_BLK_T_IN		0
+@@ -35,8 +39,6 @@ struct virtio_blk_outhdr
+ 	__u32 ioprio;
+ 	/* Sector (ie. 512 byte offset) */
+ 	__u64 sector;
+-	/* Where to put reply. */
+-	__u64 id;
+ };
+ 
+ #define VIRTIO_BLK_S_OK		0
+diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
+index bcc0188..d581b29 100644
+--- a/include/linux/virtio_config.h
++++ b/include/linux/virtio_config.h
+@@ -5,7 +5,7 @@
+  * store and access that space differently. */
+ #include <linux/types.h>
+ 
+-/* Status byte for guest to report progress, and synchronize config. */
++/* Status byte for guest to report progress, and synchronize features. */
+ /* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
+ #define VIRTIO_CONFIG_S_ACKNOWLEDGE	1
+ /* We have found a driver for the device. */
+@@ -15,34 +15,27 @@
+ /* We've given up on this device. */
+ #define VIRTIO_CONFIG_S_FAILED		0x80
+ 
+-/* Feature byte (actually 7 bits availabe): */
+-/* Requirements/features of the virtio implementation. */
+-#define VIRTIO_CONFIG_F_VIRTIO 1
+-/* Requirements/features of the virtqueue (may have more than one). */
+-#define VIRTIO_CONFIG_F_VIRTQUEUE 2
+-
+ #ifdef __KERNEL__
+ struct virtio_device;
+ 
+ /**
+  * virtio_config_ops - operations for configuring a virtio device
+- * @find: search for the next configuration field of the given type.
++ * @feature: search for a feature in this config
+  *	vdev: the virtio_device
+- *	type: the feature type
+- *	len: the (returned) length of the field if found.
+- *	Returns a token if found, or NULL.  Never returnes the same field twice
+- *	(ie. it's used up).
+- * @get: read the value of a configuration field after find().
++ *	bit: the feature bit
++ *	Returns true if the feature is supported.  Acknowledges the feature
++ *	so the host can see it.
++ * @get: read the value of a configuration field
+  *	vdev: the virtio_device
+- *	token: the token returned from find().
++ *	offset: the offset of the configuration field
+  *	buf: the buffer to write the field value into.
+- *	len: the length of the buffer (given by find()).
++ *	len: the length of the buffer
+  *	Note that contents are conventionally little-endian.
+- * @set: write the value of a configuration field after find().
++ * @set: write the value of a configuration field
+  *	vdev: the virtio_device
+- *	token: the token returned from find().
++ *	offset: the offset of the configuration field
+  *	buf: the buffer to read the field value from.
+- *	len: the length of the buffer (given by find()).
++ *	len: the length of the buffer
+  *	Note that contents are conventionally little-endian.
+  * @get_status: read the status byte
+  *	vdev: the virtio_device
+@@ -50,62 +43,67 @@ struct virtio_device;
+  * @set_status: write the status byte
+  *	vdev: the virtio_device
+  *	status: the new status byte
+- * @find_vq: find the first VIRTIO_CONFIG_F_VIRTQUEUE and create a virtqueue.
++ * @reset: reset the device
++ *	vdev: the virtio device
++ *	After this, status and feature negotiation must be done again
++ * @find_vq: find a virtqueue and instantiate it.
+  *	vdev: the virtio_device
++ *	index: the 0-based virtqueue number in case there's more than one.
+  *	callback: the virqtueue callback
+- *	Returns the new virtqueue or ERR_PTR().
++ *	Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
+  * @del_vq: free a virtqueue found by find_vq().
+  */
+ struct virtio_config_ops
+ {
+-	void *(*find)(struct virtio_device *vdev, u8 type, unsigned *len);
+-	void (*get)(struct virtio_device *vdev, void *token,
++	bool (*feature)(struct virtio_device *vdev, unsigned bit);
++	void (*get)(struct virtio_device *vdev, unsigned offset,
+ 		    void *buf, unsigned len);
+-	void (*set)(struct virtio_device *vdev, void *token,
++	void (*set)(struct virtio_device *vdev, unsigned offset,
+ 		    const void *buf, unsigned len);
+ 	u8 (*get_status)(struct virtio_device *vdev);
+ 	void (*set_status)(struct virtio_device *vdev, u8 status);
++	void (*reset)(struct virtio_device *vdev);
+ 	struct virtqueue *(*find_vq)(struct virtio_device *vdev,
+-				     bool (*callback)(struct virtqueue *));
++				     unsigned index,
++				     void (*callback)(struct virtqueue *));
+ 	void (*del_vq)(struct virtqueue *vq);
+ };
+ 
+ /**
+- * virtio_config_val - get a single virtio config and mark it used.
+- * @config: the virtio config space
+- * @type: the type to search for.
++ * virtio_config_val - look for a feature and get a single virtio config.
++ * @vdev: the virtio device
++ * @fbit: the feature bit
++ * @offset: the type to search for.
+  * @val: a pointer to the value to fill in.
+  *
+- * Once used, the config type is marked with VIRTIO_CONFIG_F_USED so it can't
+- * be found again.  This version does endian conversion. */
+-#define virtio_config_val(vdev, type, v) ({				\
+-	int _err = __virtio_config_val((vdev),(type),(v),sizeof(*(v))); \
+-									\
+-	BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2		\
+-		     && sizeof(*(v)) != 4 && sizeof(*(v)) != 8);	\
+-	if (!_err) {							\
+-		switch (sizeof(*(v))) {					\
+-		case 2: le16_to_cpus((__u16 *) v); break;		\
+-		case 4: le32_to_cpus((__u32 *) v); break;		\
+-		case 8: le64_to_cpus((__u64 *) v); break;		\
+-		}							\
+-	}								\
++ * The return value is -ENOENT if the feature doesn't exist.  Otherwise
++ * the value is endian-corrected and returned in v. */
++#define virtio_config_val(vdev, fbit, offset, v) ({			\
++	int _err;							\
++	if ((vdev)->config->feature((vdev), (fbit))) {			\
++		__virtio_config_val((vdev), (offset), (v));		\
++		_err = 0;						\
++	} else								\
++		_err = -ENOENT;						\
+ 	_err;								\
+ })
+ 
+-int __virtio_config_val(struct virtio_device *dev,
+-			u8 type, void *val, size_t size);
+-
+ /**
+- * virtio_use_bit - helper to use a feature bit in a bitfield value.
+- * @dev: the virtio device
+- * @token: the token as returned from vdev->config->find().
+- * @len: the length of the field.
+- * @bitnum: the bit to test.
++ * __virtio_config_val - get a single virtio config without feature check.
++ * @vdev: the virtio device
++ * @offset: the type to search for.
++ * @val: a pointer to the value to fill in.
+  *
+- * If handed a NULL token, it returns false, otherwise returns bit status.
+- * If it's one, it sets the mirroring acknowledgement bit. */
+-int virtio_use_bit(struct virtio_device *vdev,
+-		   void *token, unsigned int len, unsigned int bitnum);
++ * The value is endian-corrected and returned in v. */
++#define __virtio_config_val(vdev, offset, v) do {			\
++	BUILD_BUG_ON(sizeof(*(v)) != 1 && sizeof(*(v)) != 2		\
++		     && sizeof(*(v)) != 4 && sizeof(*(v)) != 8);	\
++	(vdev)->config->get((vdev), (offset), (v), sizeof(*(v)));	\
++	switch (sizeof(*(v))) {						\
++	case 2: le16_to_cpus((__u16 *) v); break;			\
++	case 4: le32_to_cpus((__u32 *) v); break;			\
++	case 8: le64_to_cpus((__u64 *) v); break;			\
++	}								\
++} while(0)
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_VIRTIO_CONFIG_H */
+diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
+index ae469ae..1ea3351 100644
+--- a/include/linux/virtio_net.h
++++ b/include/linux/virtio_net.h
+@@ -5,32 +5,32 @@
+ /* The ID for virtio_net */
+ #define VIRTIO_ID_NET	1
+ 
+-/* The bitmap of config for virtio net */
+-#define VIRTIO_CONFIG_NET_F	0x40
+-#define VIRTIO_NET_F_NO_CSUM	0
+-#define VIRTIO_NET_F_TSO4	1
+-#define VIRTIO_NET_F_UFO	2
+-#define VIRTIO_NET_F_TSO4_ECN	3
+-#define VIRTIO_NET_F_TSO6	4
++/* The feature bitmap for virtio net */
++#define VIRTIO_NET_F_CSUM	0	/* Can handle pkts w/ partial csum */
++#define VIRTIO_NET_F_MAC	5	/* Host has given MAC address. */
++#define VIRTIO_NET_F_GSO	6	/* Can handle pkts w/ any GSO type */
+ 
+-/* The config defining mac address. */
+-#define VIRTIO_CONFIG_NET_MAC_F	0x41
++struct virtio_net_config
++{
++	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
++	__u8 mac[6];
++} __attribute__((packed));
+ 
+ /* This is the first element of the scatter-gather list.  If you don't
+  * specify GSO or CSUM features, you can simply ignore the header. */
+ struct virtio_net_hdr
+ {
+ #define VIRTIO_NET_HDR_F_NEEDS_CSUM	1	// Use csum_start, csum_offset
+-      __u8 flags;
++	__u8 flags;
+ #define VIRTIO_NET_HDR_GSO_NONE		0	// Not a GSO frame
+ #define VIRTIO_NET_HDR_GSO_TCPV4	1	// GSO frame, IPv4 TCP (TSO)
+-/* FIXME: Do we need this?  If they said they can handle ECN, do they care? */
+-#define VIRTIO_NET_HDR_GSO_TCPV4_ECN	2	// GSO frame, IPv4 TCP w/ ECN
+ #define VIRTIO_NET_HDR_GSO_UDP		3	// GSO frame, IPv4 UDP (UFO)
+ #define VIRTIO_NET_HDR_GSO_TCPV6	4	// GSO frame, IPv6 TCP
+-      __u8 gso_type;
+-      __u16 gso_size;
+-      __u16 csum_start;
+-      __u16 csum_offset;
++#define VIRTIO_NET_HDR_GSO_ECN		0x80	// TCP has ECN set
++	__u8 gso_type;
++	__u16 hdr_len;		/* Ethernet + IP + tcp/udp hdrs */
++	__u16 gso_size;		/* Bytes to append to gso_hdr_len per frame */
++	__u16 csum_start;	/* Position to start checksumming from */
++	__u16 csum_offset;	/* Offset after that to place checksum */
+ };
+ #endif /* _LINUX_VIRTIO_NET_H */
+diff --git a/include/linux/virtio_pci.h b/include/linux/virtio_pci.h
+new file mode 100644
+index 0000000..b315165
+--- /dev/null
++++ b/include/linux/virtio_pci.h
+@@ -0,0 +1,57 @@
++/*
++ * Virtio PCI driver
++ *
++ * This module allows virtio devices to be used over a virtual PCI device.
++ * This can be used with QEMU based VMMs like KVM or Xen.
++ *
++ * Copyright IBM Corp. 2007
++ *
++ * Authors:
++ *  Anthony Liguori  <aliguori at us.ibm.com>
++ *
++ * This work is licensed under the terms of the GNU GPL, version 2 or later.
++ * See the COPYING file in the top-level directory.
++ *
++ */
++
++#ifndef _LINUX_VIRTIO_PCI_H
++#define _LINUX_VIRTIO_PCI_H
++
++#include <linux/virtio_config.h>
++
++/* A 32-bit r/o bitmask of the features supported by the host */
++#define VIRTIO_PCI_HOST_FEATURES	0
++
++/* A 32-bit r/w bitmask of features activated by the guest */
++#define VIRTIO_PCI_GUEST_FEATURES	4
++
++/* A 32-bit r/w PFN for the currently selected queue */
++#define VIRTIO_PCI_QUEUE_PFN		8
++
++/* A 16-bit r/o queue size for the currently selected queue */
++#define VIRTIO_PCI_QUEUE_NUM		12
++
++/* A 16-bit r/w queue selector */
++#define VIRTIO_PCI_QUEUE_SEL		14
++
++/* A 16-bit r/w queue notifier */
++#define VIRTIO_PCI_QUEUE_NOTIFY		16
++
++/* An 8-bit device status register.  */
++#define VIRTIO_PCI_STATUS		18
++
++/* An 8-bit r/o interrupt status register.  Reading the value will return the
++ * current contents of the ISR and will also clear it.  This is effectively
++ * a read-and-acknowledge. */
++#define VIRTIO_PCI_ISR			19
++
++/* The bit of the ISR which indicates a device configuration change. */
++#define VIRTIO_PCI_ISR_CONFIG		0x2
++
++/* The remaining space is defined by each driver as the per-driver
++ * configuration space */
++#define VIRTIO_PCI_CONFIG		20
++
++/* Virtio ABI version, this must match exactly */
++#define VIRTIO_PCI_ABI_VERSION		0
++#endif
+diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
+index 1a4ed49..abe481e 100644
+--- a/include/linux/virtio_ring.h
++++ b/include/linux/virtio_ring.h
+@@ -15,9 +15,13 @@
+ /* This marks a buffer as write-only (otherwise read-only). */
+ #define VRING_DESC_F_WRITE	2
+ 
+-/* This means don't notify other side when buffer added. */
++/* The Host uses this in used->flags to advise the Guest: don't kick me when
++ * you add a buffer.  It's unreliable, so it's simply an optimization.  Guest
++ * will still kick if it's out of buffers. */
+ #define VRING_USED_F_NO_NOTIFY	1
+-/* This means don't interrupt guest when buffer consumed. */
++/* The Guest uses this in avail->flags to advise the Host: don't interrupt me
++ * when you consume a buffer.  It's unreliable, so it's simply an
++ * optimization.  */
+ #define VRING_AVAIL_F_NO_INTERRUPT	1
+ 
+ /* Virtio ring descriptors: 16 bytes.  These can chain together via "next". */
+@@ -89,7 +93,7 @@ struct vring {
+  * };
+  */
+ static inline void vring_init(struct vring *vr, unsigned int num, void *p,
+-			      unsigned int pagesize)
++			      unsigned long pagesize)
+ {
+ 	vr->num = num;
+ 	vr->desc = p;
+@@ -98,7 +102,7 @@ static inline void vring_init(struct vring *vr, unsigned int num, void *p,
+ 			    & ~(pagesize - 1));
+ }
+ 
+-static inline unsigned vring_size(unsigned int num, unsigned int pagesize)
++static inline unsigned vring_size(unsigned int num, unsigned long pagesize)
+ {
+ 	return ((sizeof(struct vring_desc) * num + sizeof(__u16) * (2 + num)
+ 		 + pagesize - 1) & ~(pagesize - 1))
+@@ -114,7 +118,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int num,
+ 				      struct virtio_device *vdev,
+ 				      void *pages,
+ 				      void (*notify)(struct virtqueue *vq),
+-				      bool (*callback)(struct virtqueue *vq));
++				      void (*callback)(struct virtqueue *vq));
+ void vring_del_virtqueue(struct virtqueue *vq);
+ 
+ irqreturn_t vring_interrupt(int irq, void *_vq);
+diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
+index 89338b4..ce8e7da 100644
+--- a/include/linux/vmalloc.h
++++ b/include/linux/vmalloc.h
+@@ -45,11 +45,11 @@ extern void *vmalloc_32_user(unsigned long size);
+ extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot);
+ extern void *__vmalloc_area(struct vm_struct *area, gfp_t gfp_mask,
+ 				pgprot_t prot);
+-extern void vfree(void *addr);
++extern void vfree(const void *addr);
+ 
+ extern void *vmap(struct page **pages, unsigned int count,
+ 			unsigned long flags, pgprot_t prot);
+-extern void vunmap(void *addr);
++extern void vunmap(const void *addr);
+ 
+ extern int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
+ 							unsigned long pgoff);
+@@ -71,7 +71,7 @@ extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
+ extern struct vm_struct *get_vm_area_node(unsigned long size,
+ 					  unsigned long flags, int node,
+ 					  gfp_t gfp_mask);
+-extern struct vm_struct *remove_vm_area(void *addr);
++extern struct vm_struct *remove_vm_area(const void *addr);
+ 
+ extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
+ 			struct page ***pages);
 diff --git a/include/linux/wait.h b/include/linux/wait.h
-index 0e68628..1f4fb0a 100644
+index 0e68628..33a2aa9 100644
 --- a/include/linux/wait.h
 +++ b/include/linux/wait.h
-@@ -152,14 +152,15 @@ int FASTCALL(out_of_line_wait_on_bit(void *, int, int (*)(void *), unsigned));
+@@ -152,14 +152,31 @@ int FASTCALL(out_of_line_wait_on_bit(void *, int, int (*)(void *), unsigned));
  int FASTCALL(out_of_line_wait_on_bit_lock(void *, int, int (*)(void *), unsigned));
  wait_queue_head_t *FASTCALL(bit_waitqueue(void *, int));
  
@@ -876423,10 +948870,26 @@
 -#define	wake_up_locked(x)		__wake_up_locked((x), TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
 -#define wake_up_interruptible_sync(x)   __wake_up_sync((x),TASK_INTERRUPTIBLE, 1)
 +#define wake_up_interruptible_sync(x)	__wake_up_sync((x), TASK_INTERRUPTIBLE, 1)
++
++#ifdef CONFIG_DEBUG_LOCK_ALLOC
++/*
++ * macro to avoid include hell
++ */
++#define wake_up_nested(x, s)						\
++do {									\
++	unsigned long flags;						\
++									\
++	spin_lock_irqsave_nested(&(x)->lock, flags, (s));		\
++	wake_up_locked(x); 						\
++	spin_unlock_irqrestore(&(x)->lock, flags);			\
++} while (0)
++#else
++#define wake_up_nested(x, s)		wake_up(x)
++#endif
  
  #define __wait_event(wq, condition) 					\
  do {									\
-@@ -345,6 +346,47 @@ do {									\
+@@ -345,6 +362,47 @@ do {									\
  	__ret;								\
  })
  
@@ -876475,7 +948938,7 @@
   * Must be called with the spinlock in the wait_queue_head_t held.
   */
 diff --git a/include/linux/wireless.h b/include/linux/wireless.h
-index 0987aa7..74e84ca 100644
+index 0987aa7..3160dfe 100644
 --- a/include/linux/wireless.h
 +++ b/include/linux/wireless.h
 @@ -541,6 +541,16 @@
@@ -876505,6 +948968,47 @@
  	/* Wireless event capability bitmasks */
  	__u32		event_capa[6];
  
+@@ -1066,7 +1079,7 @@ struct	iw_priv_args
+  */
+ struct iw_event
+ {
+-	__u16		len;			/* Real lenght of this stuff */
++	__u16		len;			/* Real length of this stuff */
+ 	__u16		cmd;			/* Wireless IOCTL */
+ 	union iwreq_data	u;		/* IOCTL fixed payload */
+ };
+diff --git a/include/linux/writeback.h b/include/linux/writeback.h
+index c6148bb..b7b3362 100644
+--- a/include/linux/writeback.h
++++ b/include/linux/writeback.h
+@@ -62,6 +62,7 @@ struct writeback_control {
+ 	unsigned for_reclaim:1;		/* Invoked from the page allocator */
+ 	unsigned for_writepages:1;	/* This is a writepages() call */
+ 	unsigned range_cyclic:1;	/* range_start is cyclic */
++	unsigned more_io:1;		/* more io to be dispatched */
+ };
+ 
+ /*
+@@ -100,6 +101,7 @@ extern int dirty_background_ratio;
+ extern int vm_dirty_ratio;
+ extern int dirty_writeback_interval;
+ extern int dirty_expire_interval;
++extern int vm_highmem_is_dirtyable;
+ extern int block_dump;
+ extern int laptop_mode;
+ 
+diff --git a/include/linux/xattr.h b/include/linux/xattr.h
+index def131a..df6b95d 100644
+--- a/include/linux/xattr.h
++++ b/include/linux/xattr.h
+@@ -46,6 +46,7 @@ struct xattr_handler {
+ 		   size_t size, int flags);
+ };
+ 
++ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
+ ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
+ ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
+ int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
 diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
 index b58adc5..e31b8c8 100644
 --- a/include/linux/xfrm.h
@@ -876767,6 +949271,19 @@
 +				 M52790_SW2_V_AMP)
 +
 +#endif
+diff --git a/include/media/rds.h b/include/media/rds.h
+index 951c1ae..a894266 100644
+--- a/include/media/rds.h
++++ b/include/media/rds.h
+@@ -4,7 +4,7 @@
+     saa6588.c and every driver (e.g. bttv-driver.c) that wants
+     to use the saa6588 module.
+ 
+-    Instead of having a seperate rds.h, I'd prefer to include
++    Instead of having a separate rds.h, I'd prefer to include
+     this stuff in one of the already existing files like tuner.h
+ 
+     (c) 2005 by Hans J. Koch
 diff --git a/include/media/saa7146_vv.h b/include/media/saa7146_vv.h
 index e49f7e1..89c442e 100644
 --- a/include/media/saa7146_vv.h
@@ -877847,9 +950364,38 @@
  };
  
 diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
-index 448eccb..b24508a 100644
+index 448eccb..b2cfc49 100644
 --- a/include/net/if_inet6.h
 +++ b/include/net/if_inet6.h
+@@ -112,13 +112,13 @@ struct ifmcaddr6
+ 	struct ip6_sf_list	*mca_sources;
+ 	struct ip6_sf_list	*mca_tomb;
+ 	unsigned int		mca_sfmode;
++	unsigned char		mca_crcount;
+ 	unsigned long		mca_sfcount[2];
+ 	struct timer_list	mca_timer;
+ 	unsigned		mca_flags;
+ 	int			mca_users;
+ 	atomic_t		mca_refcnt;
+ 	spinlock_t		mca_lock;
+-	unsigned char		mca_crcount;
+ 	unsigned long		mca_cstamp;
+ 	unsigned long		mca_tstamp;
+ };
+@@ -166,11 +166,11 @@ struct inet6_dev
+ 	struct ifmcaddr6	*mc_list;
+ 	struct ifmcaddr6	*mc_tomb;
+ 	rwlock_t		mc_lock;
+-	unsigned long		mc_v1_seen;
+-	unsigned long		mc_maxdelay;
+ 	unsigned char		mc_qrv;
+ 	unsigned char		mc_gq_running;
+ 	unsigned char		mc_ifc_count;
++	unsigned long		mc_v1_seen;
++	unsigned long		mc_maxdelay;
+ 	struct timer_list	mc_gq_timer;	/* general query timer */
+ 	struct timer_list	mc_ifc_timer;	/* interface change timer */
+ 
 @@ -269,18 +269,21 @@ static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf)
  	buf[0] = 0x00;
  }
@@ -877877,9 +950423,18 @@
  }
  #endif
 diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
-index 668056b..fdff630 100644
+index 668056b..62a5b69 100644
 --- a/include/net/inet6_hashtables.h
 +++ b/include/net/inet6_hashtables.h
+@@ -49,7 +49,7 @@ static inline int inet6_sk_ehashfn(const struct sock *sk)
+ 	return inet6_ehashfn(laddr, lport, faddr, fport);
+ }
+ 
+-extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
++extern void __inet6_hash(struct sock *sk);
+ 
+ /*
+  * Sockets in TCP_CLOSE state are _always_ taken out of the hash, so
 @@ -57,34 +57,37 @@ extern void __inet6_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
   *
   * The sockhash lock must be held as a reader here.
@@ -877925,6 +950480,39 @@
  				 const struct in6_addr *saddr, const __be16 sport,
  				 const struct in6_addr *daddr, const __be16 dport,
  				 const int dif);
+diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
+index 133cf30..f00f057 100644
+--- a/include/net/inet_connection_sock.h
++++ b/include/net/inet_connection_sock.h
+@@ -29,7 +29,6 @@
+ #undef INET_CSK_CLEAR_TIMERS
+ 
+ struct inet_bind_bucket;
+-struct inet_hashinfo;
+ struct tcp_congestion_ops;
+ 
+ /*
+@@ -59,6 +58,8 @@ struct inet_connection_sock_af_ops {
+ 				int level, int optname,
+ 				char __user *optval, int __user *optlen);
+ 	void	    (*addr2sockaddr)(struct sock *sk, struct sockaddr *);
++	int	    (*bind_conflict)(const struct sock *sk,
++				     const struct inet_bind_bucket *tb);
+ };
+ 
+ /** inet_connection_sock - INET connection oriented sock
+@@ -244,10 +245,7 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk,
+ 						const __be32 laddr);
+ extern int inet_csk_bind_conflict(const struct sock *sk,
+ 				  const struct inet_bind_bucket *tb);
+-extern int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+-			     struct sock *sk, unsigned short snum,
+-			     int (*bind_conflict)(const struct sock *sk,
+-						  const struct inet_bind_bucket *tb));
++extern int inet_csk_get_port(struct sock *sk, unsigned short snum);
+ 
+ extern struct dst_entry* inet_csk_route_req(struct sock *sk,
+ 					    const struct request_sock *req);
 diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
 index de8399a..ba33db0 100644
 --- a/include/net/inet_ecn.h
@@ -878023,7 +950611,7 @@
  static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
  {
 diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
-index 37f6cb1..c23c4ed 100644
+index 37f6cb1..97dc35a 100644
 --- a/include/net/inet_hashtables.h
 +++ b/include/net/inet_hashtables.h
 @@ -74,6 +74,7 @@ struct inet_ehash_bucket {
@@ -878042,7 +950630,38 @@
  					    struct inet_bind_hashbucket *head,
  					    const unsigned short snum);
  extern void inet_bind_bucket_destroy(struct kmem_cache *cachep,
-@@ -264,37 +266,14 @@ static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
+@@ -219,9 +221,9 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk)
+ }
+ 
+ /* Caller must disable local BH processing. */
+-static inline void __inet_inherit_port(struct inet_hashinfo *table,
+-				       struct sock *sk, struct sock *child)
++static inline void __inet_inherit_port(struct sock *sk, struct sock *child)
+ {
++	struct inet_hashinfo *table = sk->sk_prot->hashinfo;
+ 	const int bhash = inet_bhashfn(inet_sk(child)->num, table->bhash_size);
+ 	struct inet_bind_hashbucket *head = &table->bhash[bhash];
+ 	struct inet_bind_bucket *tb;
+@@ -233,15 +235,14 @@ static inline void __inet_inherit_port(struct inet_hashinfo *table,
+ 	spin_unlock(&head->lock);
+ }
+ 
+-static inline void inet_inherit_port(struct inet_hashinfo *table,
+-				     struct sock *sk, struct sock *child)
++static inline void inet_inherit_port(struct sock *sk, struct sock *child)
+ {
+ 	local_bh_disable();
+-	__inet_inherit_port(table, sk, child);
++	__inet_inherit_port(sk, child);
+ 	local_bh_enable();
+ }
+ 
+-extern void inet_put_port(struct inet_hashinfo *table, struct sock *sk);
++extern void inet_put_port(struct sock *sk);
+ 
+ extern void inet_listen_wlock(struct inet_hashinfo *hashinfo);
+ 
+@@ -264,74 +265,21 @@ static inline void inet_listen_unlock(struct inet_hashinfo *hashinfo)
  		wake_up(&hashinfo->lhash_wait);
  }
  
@@ -878071,29 +950690,42 @@
 -	if (listen_possible && sk->sk_state == TCP_LISTEN)
 -		wake_up(&hashinfo->lhash_wait);
 -}
-+extern void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk);
-+extern void __inet_hash_nolisten(struct inet_hashinfo *hinfo, struct sock *sk);
- 
- static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
- {
- 	if (sk->sk_state != TCP_CLOSE) {
- 		local_bh_disable();
+-
+-static inline void inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
+-{
+-	if (sk->sk_state != TCP_CLOSE) {
+-		local_bh_disable();
 -		__inet_hash(hashinfo, sk, 1);
-+		__inet_hash(hashinfo, sk);
- 		local_bh_enable();
- 	}
- }
-@@ -316,22 +295,24 @@ static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
- 	}
- 
- 	if (__sk_del_node_init(sk))
+-		local_bh_enable();
+-	}
+-}
+-
+-static inline void inet_unhash(struct inet_hashinfo *hashinfo, struct sock *sk)
+-{
+-	rwlock_t *lock;
+-
+-	if (sk_unhashed(sk))
+-		goto out;
+-
+-	if (sk->sk_state == TCP_LISTEN) {
+-		local_bh_disable();
+-		inet_listen_wlock(hashinfo);
+-		lock = &hashinfo->lhash_lock;
+-	} else {
+-		lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
+-		write_lock_bh(lock);
+-	}
+-
+-	if (__sk_del_node_init(sk))
 -		sock_prot_dec_use(sk->sk_prot);
-+		sock_prot_inuse_add(sk->sk_prot, -1);
- 	write_unlock_bh(lock);
- out:
- 	if (sk->sk_state == TCP_LISTEN)
- 		wake_up(&hashinfo->lhash_wait);
- }
+-	write_unlock_bh(lock);
+-out:
+-	if (sk->sk_state == TCP_LISTEN)
+-		wake_up(&hashinfo->lhash_wait);
+-}
++extern void __inet_hash_nolisten(struct sock *sk);
++extern void inet_hash(struct sock *sk);
++extern void inet_unhash(struct sock *sk);
  
 -extern struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
 +extern struct sock *__inet_lookup_listener(struct net *net,
@@ -878113,7 +950745,7 @@
  }
  
  /* Socket demux engine toys. */
-@@ -365,26 +346,26 @@ typedef __u64 __bitwise __addrpair;
+@@ -365,26 +313,26 @@ typedef __u64 __bitwise __addrpair;
  				   (((__force __u64)(__be32)(__daddr)) << 32) | \
  				   ((__force __u64)(__be32)(__saddr)));
  #endif /* __BIG_ENDIAN */
@@ -878148,7 +950780,7 @@
  	 (inet_twsk(__sk)->tw_daddr	== (__saddr))		&&	\
  	 (inet_twsk(__sk)->tw_rcv_saddr	== (__daddr))		&&	\
  	 ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&	\
-@@ -397,66 +378,36 @@ typedef __u64 __bitwise __addrpair;
+@@ -397,66 +345,36 @@ typedef __u64 __bitwise __addrpair;
   *
   * Local BH must be disabled here.
   */
@@ -878229,7 +950861,7 @@
  				       const __be32 saddr, const __be16 sport,
  				       const __be32 daddr, const __be16 dport,
  				       const int dif)
-@@ -464,12 +415,17 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
+@@ -464,12 +382,17 @@ static inline struct sock *inet_lookup(struct inet_hashinfo *hashinfo,
  	struct sock *sk;
  
  	local_bh_disable();
@@ -878241,17 +950873,33 @@
  }
  
 +extern int __inet_hash_connect(struct inet_timewait_death_row *death_row,
-+		struct sock *sk,
++		struct sock *sk, u32 port_offset,
 +		int (*check_established)(struct inet_timewait_death_row *,
 +			struct sock *, __u16, struct inet_timewait_sock **),
-+		void (*hash)(struct inet_hashinfo *, struct sock *));
++			       void (*hash)(struct sock *sk));
  extern int inet_hash_connect(struct inet_timewait_death_row *death_row,
  			     struct sock *sk);
  #endif /* _INET_HASHTABLES_H */
 diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
-index abaff05..67e9250 100644
+index abaff05..296547b 100644
 --- a/include/net/inet_timewait_sock.h
 +++ b/include/net/inet_timewait_sock.h
+@@ -116,6 +116,7 @@ struct inet_timewait_sock {
+ #define tw_hash			__tw_common.skc_hash
+ #define tw_prot			__tw_common.skc_prot
+ #define tw_net			__tw_common.skc_net
++	int			tw_timeout;
+ 	volatile unsigned char	tw_substate;
+ 	/* 3 bits hole, try to pack */
+ 	unsigned char		tw_rcv_wscale;
+@@ -130,7 +131,6 @@ struct inet_timewait_sock {
+ 	__u8			tw_ipv6only:1;
+ 	/* 15 bits hole, try to pack */
+ 	__u16			tw_ipv6_offset;
+-	int			tw_timeout;
+ 	unsigned long		tw_ttd;
+ 	struct inet_bind_bucket	*tw_tb;
+ 	struct hlist_node	tw_death_node;
 @@ -193,19 +193,7 @@ static inline __be32 inet_rcv_saddr(const struct sock *sk)
  		inet_sk(sk)->rcv_saddr : inet_twsk(sk)->tw_rcv_saddr;
  }
@@ -878451,7 +951099,7 @@
  
  extern int			ipv6_route_ioctl(unsigned int cmd, void __user *arg);
 diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
-index ed514bf..90d1175 100644
+index ed514bf..8b12667 100644
 --- a/include/net/ip_fib.h
 +++ b/include/net/ip_fib.h
 @@ -69,6 +69,7 @@ struct fib_nh {
@@ -878591,7 +951239,7 @@
  
  static inline void fib_combine_itag(u32 *itag, struct fib_result *res)
  {
-@@ -255,8 +264,8 @@ static inline void fib_res_put(struct fib_result *res)
+@@ -255,8 +264,16 @@ static inline void fib_res_put(struct fib_result *res)
  }
  
  #ifdef CONFIG_PROC_FS
@@ -878599,6 +951247,14 @@
 -extern void fib_proc_exit(void);
 +extern int __net_init  fib_proc_init(struct net *net);
 +extern void __net_exit fib_proc_exit(struct net *net);
++#else
++static inline int fib_proc_init(struct net *net)
++{
++	return 0;
++}
++static inline void fib_proc_exit(struct net *net)
++{
++}
  #endif
  
  #endif  /* _NET_FIB_H */
@@ -878665,22 +951321,20 @@
  		stats->tx_bytes += pkt_len;				\
  		stats->tx_packets++;					\
 diff --git a/include/net/ipv6.h b/include/net/ipv6.h
-index ae328b6..fa80ea4 100644
+index ae328b6..c0c019f 100644
 --- a/include/net/ipv6.h
 +++ b/include/net/ipv6.h
-@@ -109,9 +109,10 @@ struct frag_hdr {
+@@ -109,8 +109,8 @@ struct frag_hdr {
  #include <net/sock.h>
  
  /* sysctls */
 -extern int sysctl_ipv6_bindv6only;
  extern int sysctl_mld_max_msf;
- 
 +extern struct ctl_path net_ipv6_ctl_path[];
-+
+ 
  #define _DEVINC(statname, modifier, idev, field)			\
  ({									\
- 	struct inet6_dev *_idev = (idev);				\
-@@ -143,14 +144,6 @@ DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
+@@ -143,14 +143,6 @@ DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
  #define ICMP6_INC_STATS_BH(idev, field)	_DEVINC(icmpv6, _BH, idev, field)
  #define ICMP6_INC_STATS_USER(idev, field) _DEVINC(icmpv6, _USER, idev, field)
  
@@ -878695,7 +951349,7 @@
  #define ICMP6MSGOUT_INC_STATS(idev, field) \
  	_DEVINC(icmpv6msg, , idev, field +256)
  #define ICMP6MSGOUT_INC_STATS_BH(idev, field) \
-@@ -164,15 +157,6 @@ DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
+@@ -164,15 +156,6 @@ DECLARE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
  #define ICMP6MSGIN_INC_STATS_USER(idev, field) \
  	_DEVINC(icmpv6msg, _USER, idev, field)
  
@@ -878711,7 +951365,7 @@
  struct ip6_ra_chain
  {
  	struct ip6_ra_chain	*next;
-@@ -236,7 +220,7 @@ extern struct ipv6_txoptions	*fl6_merge_options(struct ipv6_txoptions * opt_spac
+@@ -236,7 +219,7 @@ extern struct ipv6_txoptions	*fl6_merge_options(struct ipv6_txoptions * opt_spac
  						   struct ipv6_txoptions * fopt);
  extern void			fl6_free_socklist(struct sock *sk);
  extern int			ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen);
@@ -878720,7 +951374,7 @@
  extern void			ip6_flowlabel_cleanup(void);
  
  static inline void fl6_sock_release(struct ip6_flowlabel *fl)
-@@ -261,8 +245,8 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
+@@ -261,8 +244,8 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
  
  extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb);
  
@@ -878731,7 +951385,7 @@
  
  #define IPV6_FRAG_TIMEOUT	(60*HZ)		/* 60 seconds */
  
-@@ -509,6 +493,9 @@ extern int			ip6_forward(struct sk_buff *skb);
+@@ -509,6 +492,9 @@ extern int			ip6_forward(struct sk_buff *skb);
  extern int			ip6_input(struct sk_buff *skb);
  extern int			ip6_mc_input(struct sk_buff *skb);
  
@@ -878741,7 +951395,7 @@
  /*
   *	Extension header (options) processing
   */
-@@ -559,7 +546,7 @@ extern int			compat_ipv6_getsockopt(struct sock *sk,
+@@ -559,7 +545,7 @@ extern int			compat_ipv6_getsockopt(struct sock *sk,
  						char __user *optval,
  						int __user *optlen);
  
@@ -878750,7 +951404,7 @@
  
  extern void			ipv6_packet_cleanup(void);
  
-@@ -585,9 +572,6 @@ extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
+@@ -585,9 +571,6 @@ extern int inet6_hash_connect(struct inet_timewait_death_row *death_row,
  /*
   * reassembly.c
   */
@@ -878760,17 +951414,7 @@
  extern const struct proto_ops inet6_stream_ops;
  extern const struct proto_ops inet6_dgram_ops;
  
-@@ -602,6 +586,9 @@ extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
- 			 int __user *optlen);
- 
- #ifdef CONFIG_PROC_FS
-+extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
-+extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
-+
- extern int  ac6_proc_init(void);
- extern void ac6_proc_exit(void);
- extern int  raw6_proc_init(void);
-@@ -631,10 +618,10 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev)
+@@ -631,10 +614,12 @@ static inline int snmp6_unregister_dev(struct inet6_dev *idev)
  #endif
  
  #ifdef CONFIG_SYSCTL
@@ -878780,6 +951424,8 @@
 +extern ctl_table ipv6_icmp_table_template[];
  
 -extern void ipv6_sysctl_register(void);
++extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net);
++extern struct ctl_table *ipv6_route_sysctl_init(struct net *net);
 +extern int ipv6_sysctl_register(void);
  extern void ipv6_sysctl_unregister(void);
  #endif
@@ -880129,10 +952775,19 @@
 +
 +#endif /* _XT_RATEEST_H */
 diff --git a/include/net/netlabel.h b/include/net/netlabel.h
-index 2e5b2f6..b3213c7 100644
+index 2e5b2f6..0ca67d7 100644
 --- a/include/net/netlabel.h
 +++ b/include/net/netlabel.h
-@@ -67,7 +67,11 @@
+@@ -36,6 +36,8 @@
+ #include <net/netlink.h>
+ #include <asm/atomic.h>
+ 
++struct cipso_v4_doi;
++
+ /*
+  * NetLabel - A management interface for maintaining network packet label
+  *            mapping tables for explicit packet labling protocols.
+@@ -67,7 +69,11 @@
   * NetLabel NETLINK protocol
   */
  
@@ -880145,15 +952800,20 @@
  
  /* NetLabel NETLINK types/families */
  #define NETLBL_NLTYPE_NONE              0
-@@ -105,17 +109,49 @@ struct netlbl_dom_map;
- /* Domain mapping operations */
- int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
+@@ -99,23 +105,49 @@ struct netlbl_audit {
+ 	uid_t loginuid;
+ };
  
--/* LSM security attributes */
+-/* Domain mapping definition struct */
+-struct netlbl_dom_map;
+-
+-/* Domain mapping operations */
+-int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
 +/*
 + * LSM security attributes
 + */
-+
+ 
+-/* LSM security attributes */
 +/**
 + * struct netlbl_lsm_cache - NetLabel LSM security attribute cache
 + * @refcount: atomic reference counter
@@ -880198,7 +952858,7 @@
  #define NETLBL_CATMAP_MAPTYPE           u64
  #define NETLBL_CATMAP_MAPCNT            4
  #define NETLBL_CATMAP_MAPSIZE           (sizeof(NETLBL_CATMAP_MAPTYPE) * 8)
-@@ -127,22 +163,48 @@ struct netlbl_lsm_secattr_catmap {
+@@ -127,22 +159,48 @@ struct netlbl_lsm_secattr_catmap {
  	NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT];
  	struct netlbl_lsm_secattr_catmap *next;
  };
@@ -880253,7 +952913,7 @@
  };
  
  /*
-@@ -231,10 +293,7 @@ static inline void netlbl_secattr_catmap_free(
+@@ -231,10 +289,7 @@ static inline void netlbl_secattr_catmap_free(
   */
  static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
  {
@@ -880265,7 +952925,7 @@
  }
  
  /**
-@@ -248,11 +307,11 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+@@ -248,11 +303,11 @@ static inline void netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
   */
  static inline void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
  {
@@ -880281,7 +952941,27 @@
  }
  
  /**
-@@ -300,7 +359,7 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
+@@ -285,6 +340,19 @@ static inline void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
+ 
+ #ifdef CONFIG_NETLABEL
+ /*
++ * LSM configuration operations
++ */
++int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info);
++int netlbl_cfg_unlbl_add_map(const char *domain,
++			     struct netlbl_audit *audit_info);
++int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
++			   struct netlbl_audit *audit_info);
++int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
++			       const char *domain,
++			       struct netlbl_audit *audit_info);
++int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info);
++
++/*
+  * LSM security attribute operations
+  */
+ int netlbl_secattr_catmap_walk(struct netlbl_lsm_secattr_catmap *catmap,
+@@ -300,7 +368,7 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap *catmap,
  				 gfp_t flags);
  
  /*
@@ -880290,7 +952970,7 @@
   */
  int netlbl_enabled(void);
  int netlbl_sock_setattr(struct sock *sk,
-@@ -308,6 +367,7 @@ int netlbl_sock_setattr(struct sock *sk,
+@@ -308,6 +376,7 @@ int netlbl_sock_setattr(struct sock *sk,
  int netlbl_sock_getattr(struct sock *sk,
  			struct netlbl_lsm_secattr *secattr);
  int netlbl_skbuff_getattr(const struct sk_buff *skb,
@@ -880298,7 +952978,40 @@
  			  struct netlbl_lsm_secattr *secattr);
  void netlbl_skbuff_err(struct sk_buff *skb, int error);
  
-@@ -360,6 +420,7 @@ static inline int netlbl_sock_getattr(struct sock *sk,
+@@ -318,6 +387,32 @@ void netlbl_cache_invalidate(void);
+ int netlbl_cache_add(const struct sk_buff *skb,
+ 		     const struct netlbl_lsm_secattr *secattr);
+ #else
++static inline int netlbl_cfg_map_del(const char *domain,
++				     struct netlbl_audit *audit_info)
++{
++	return -ENOSYS;
++}
++static inline int netlbl_cfg_unlbl_add_map(const char *domain,
++					   struct netlbl_audit *audit_info)
++{
++	return -ENOSYS;
++}
++static inline int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
++					 struct netlbl_audit *audit_info)
++{
++	return -ENOSYS;
++}
++static inline int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
++					     const char *domain,
++					     struct netlbl_audit *audit_info)
++{
++	return -ENOSYS;
++}
++static inline int netlbl_cfg_cipsov4_del(u32 doi,
++					 struct netlbl_audit *audit_info)
++{
++	return -ENOSYS;
++}
+ static inline int netlbl_secattr_catmap_walk(
+ 	                              struct netlbl_lsm_secattr_catmap *catmap,
+ 				      u32 offset)
+@@ -360,6 +455,7 @@ static inline int netlbl_sock_getattr(struct sock *sk,
  	return -ENOSYS;
  }
  static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
@@ -881142,7 +953855,7 @@
  
  #endif
 diff --git a/include/net/sock.h b/include/net/sock.h
-index 6e1542d..e3fb4c0 100644
+index 6e1542d..8a7889b 100644
 --- a/include/net/sock.h
 +++ b/include/net/sock.h
 @@ -47,6 +47,7 @@
@@ -881246,7 +953959,15 @@
  /* The per-socket spinlock must be held here. */
  static inline void sk_add_backlog(struct sock *sk, struct sk_buff *skb)
  {
-@@ -560,14 +549,11 @@ struct proto {
+@@ -507,6 +496,7 @@ extern int sk_wait_data(struct sock *sk, long *timeo);
+ 
+ struct request_sock_ops;
+ struct timewait_sock_ops;
++struct inet_hashinfo;
+ 
+ /* Networking protocol blocks we attach to sockets.
+  * socket layer -> transport layer interface
+@@ -560,14 +550,11 @@ struct proto {
  	void			(*unhash)(struct sock *sk);
  	int			(*get_port)(struct sock *sk, unsigned short snum);
  
@@ -881264,7 +953985,7 @@
  	/* Memory pressure */
  	void			(*enter_memory_pressure)(void);
  	atomic_t		*memory_allocated;	/* Current allocated memory. */
-@@ -575,7 +561,7 @@ struct proto {
+@@ -575,7 +562,7 @@ struct proto {
  	/*
  	 * Pressure flag: try to collapse.
  	 * Technical note: it is used by multiple contexts non atomically.
@@ -881273,7 +953994,16 @@
  	 * is strict, actions are advisory and have some latency.
  	 */
  	int			*memory_pressure;
-@@ -602,36 +588,6 @@ struct proto {
+@@ -592,6 +579,8 @@ struct proto {
+ 	struct request_sock_ops	*rsk_prot;
+ 	struct timewait_sock_ops *twsk_prot;
+ 
++	struct inet_hashinfo	*hashinfo;
++
+ 	struct module		*owner;
+ 
+ 	char			name[32];
+@@ -602,36 +591,6 @@ struct proto {
  #endif
  };
  
@@ -881310,7 +954040,7 @@
  extern int proto_register(struct proto *prot, int alloc_slab);
  extern void proto_unregister(struct proto *prot);
  
-@@ -660,33 +616,42 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
+@@ -660,33 +619,42 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
  #define sk_refcnt_debug_release(sk) do { } while (0)
  #endif /* SOCK_REFCNT_DEBUG */
  
@@ -881343,13 +954073,13 @@
 -
 -static __inline__ int sock_prot_inuse(struct proto *proto)
 +static inline int sock_prot_inuse_get(struct proto *proto)
- {
--#ifdef CONFIG_SMP
--	return proto->inuse_getval(proto);
++{
 +	return pcounter_getval(&proto->inuse);
 +}
 +static inline void sock_prot_inuse_free(struct proto *proto)
-+{
+ {
+-#ifdef CONFIG_SMP
+-	return proto->inuse_getval(proto);
 +	pcounter_free(&proto->inuse);
 +}
  #else
@@ -881372,7 +954102,7 @@
  
  /* With per-bucket locks this operation is not-atomic, so that
   * this version is not worse.
-@@ -750,32 +715,81 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
+@@ -750,32 +718,81 @@ static inline struct inode *SOCK_INODE(struct socket *socket)
  	return &container_of(socket, struct socket_alloc, socket)->vfs_inode;
  }
  
@@ -881467,7 +954197,7 @@
  }
  
  /* Used by processes to "lock" a socket state, so that
-@@ -812,14 +826,14 @@ do {									\
+@@ -812,14 +829,14 @@ do {									\
  	lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0);	\
  } while (0)
  
@@ -881484,7 +954214,7 @@
  
  /* BH context may only use the following locking interface. */
  #define bh_lock_sock(__sk)	spin_lock(&((__sk)->sk_lock.slock))
-@@ -1113,12 +1127,6 @@ static inline int sk_can_gso(const struct sock *sk)
+@@ -1113,12 +1130,6 @@ static inline int sk_can_gso(const struct sock *sk)
  
  extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
  
@@ -881497,7 +954227,7 @@
  static inline int skb_copy_to_page(struct sock *sk, char __user *from,
  				   struct sk_buff *skb, struct page *page,
  				   int off, int copy)
-@@ -1138,7 +1146,7 @@ static inline int skb_copy_to_page(struct sock *sk, char __user *from,
+@@ -1138,7 +1149,7 @@ static inline int skb_copy_to_page(struct sock *sk, char __user *from,
  	skb->data_len	     += copy;
  	skb->truesize	     += copy;
  	sk->sk_wmem_queued   += copy;
@@ -881506,7 +954236,7 @@
  	return 0;
  }
  
-@@ -1164,6 +1172,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
+@@ -1164,6 +1175,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
  	skb->sk = sk;
  	skb->destructor = sock_rfree;
  	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
@@ -881514,7 +954244,7 @@
  }
  
  extern void sk_reset_timer(struct sock *sk, struct timer_list* timer,
-@@ -1225,45 +1234,12 @@ static inline void sk_wake_async(struct sock *sk, int how, int band)
+@@ -1225,45 +1237,12 @@ static inline void sk_wake_async(struct sock *sk, int how, int band)
  static inline void sk_stream_moderate_sndbuf(struct sock *sk)
  {
  	if (!(sk->sk_userlocks & SOCK_SNDBUF_LOCK)) {
@@ -881562,7 +954292,7 @@
  
  static inline struct page *sk_stream_alloc_page(struct sock *sk)
  {
-@@ -1282,7 +1258,7 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk)
+@@ -1282,7 +1261,7 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk)
   */
  static inline int sock_writeable(const struct sock *sk) 
  {
@@ -881571,7 +954301,7 @@
  }
  
  static inline gfp_t gfp_any(void)
-@@ -1391,23 +1367,11 @@ extern int net_msg_warn;
+@@ -1391,23 +1370,11 @@ extern int net_msg_warn;
  				lock_sock(sk); \
  				}
  
@@ -882518,6 +955248,69 @@
 +}
 +
  #endif	/* _NET_XFRM_H */
+diff --git a/include/pcmcia/cs.h b/include/pcmcia/cs.h
+index d5838c3..87a260e 100644
+--- a/include/pcmcia/cs.h
++++ b/include/pcmcia/cs.h
+@@ -147,11 +147,11 @@ typedef struct config_req_t {
+ 
+ /* For RequestIO and ReleaseIO */
+ typedef struct io_req_t {
+-    ioaddr_t	BasePort1;
+-    ioaddr_t	NumPorts1;
++    u_int	BasePort1;
++    u_int	NumPorts1;
+     u_int	Attributes1;
+-    ioaddr_t	BasePort2;
+-    ioaddr_t	NumPorts2;
++    u_int	BasePort2;
++    u_int	NumPorts2;
+     u_int	Attributes2;
+     u_int	IOAddrLines;
+ } io_req_t;
+diff --git a/include/pcmcia/cs_types.h b/include/pcmcia/cs_types.h
+index 5f38803..9a6bcc4 100644
+--- a/include/pcmcia/cs_types.h
++++ b/include/pcmcia/cs_types.h
+@@ -27,7 +27,6 @@ typedef u_int   ioaddr_t;
+ #else
+ typedef u_short	ioaddr_t;
+ #endif
+-typedef unsigned long kio_addr_t;
+ 
+ typedef u_short	socket_t;
+ typedef u_int	event_t;
+diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
+index 6e84258..f95dca0 100644
+--- a/include/pcmcia/ss.h
++++ b/include/pcmcia/ss.h
+@@ -92,7 +92,7 @@ typedef struct pccard_io_map {
+     u_char	map;
+     u_char	flags;
+     u_short	speed;
+-    kio_addr_t	start, stop;
++    u_int	start, stop;
+ } pccard_io_map;
+ 
+ typedef struct pccard_mem_map {
+@@ -155,7 +155,7 @@ extern struct pccard_resource_ops pccard_iodyn_ops;
+ struct pcmcia_socket;
+ 
+ typedef struct io_window_t {
+-	kio_addr_t		InUse, Config;
++	u_int			InUse, Config;
+ 	struct resource		*res;
+ } io_window_t;
+ 
+@@ -208,7 +208,7 @@ struct pcmcia_socket {
+ 	u_int				features;
+ 	u_int				irq_mask;
+ 	u_int				map_size;
+-	kio_addr_t			io_offset;
++	u_int				io_offset;
+ 	u_char				pci_irq;
+ 	struct pci_dev *		cb_dev;
+ 
 diff --git a/include/rdma/ib_mad.h b/include/rdma/ib_mad.h
 index 8ec3799..7228c05 100644
 --- a/include/rdma/ib_mad.h
@@ -883289,6 +956082,19 @@
  
  	/*
  	 * Host has requested that no further requests come through for the
+diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
+index e466d88..4769efd 100644
+--- a/include/scsi/scsi_transport_fc.h
++++ b/include/scsi/scsi_transport_fc.h
+@@ -176,7 +176,7 @@ struct class_device_attribute class_device_attr_vport_##_name = 	\
+  * ports has a unique presense on the SAN, and may be instantiated via
+  * NPIV, Virtual Fabrics, or via additional ALPAs. As the vport is a
+  * unique presense, each vport has it's own view of the fabric,
+- * authentication priviledge, and priorities.
++ * authentication privilege, and priorities.
+  *
+  * A virtual port may support 1 or more FC4 roles. Typically it is a
+  * FCP Initiator. It could be a FCP Target, or exist sole for an IP over FC
 diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
 index 7ff6199..404f11d 100644
 --- a/include/scsi/scsi_transport_iscsi.h
@@ -885922,7 +958728,7 @@
  #define __pte_ma(x)	((pte_t) { (x) } )
  #endif	/* CONFIG_X86_PAE */
 diff --git a/init/Kconfig b/init/Kconfig
-index b9d11a8..dcc96a8 100644
+index b9d11a8..87f50df 100644
 --- a/init/Kconfig
 +++ b/init/Kconfig
 @@ -1,3 +1,11 @@
@@ -885954,7 +958760,57 @@
  	default y
  	help
  	  This option creates deprecated symlinks such as the
-@@ -762,3 +771,39 @@ source "block/Kconfig"
+@@ -573,7 +582,6 @@ config SIGNALFD
+ config TIMERFD
+ 	bool "Enable timerfd() system call" if EMBEDDED
+ 	select ANON_INODES
+-	depends on BROKEN
+ 	default y
+ 	help
+ 	  Enable the timerfd() system call that allows to receive timer
+@@ -648,14 +656,36 @@ config SLOB
+ 	depends on EMBEDDED
+ 	bool "SLOB (Simple Allocator)"
+ 	help
+-	   SLOB replaces the SLAB allocator with a drastically simpler
+-	   allocator.  SLOB is more space efficient than SLAB but does not
+-	   scale well (single lock for all operations) and is also highly
+-	   susceptible to fragmentation. SLUB can accomplish a higher object
+-	   density. It is usually better to use SLUB instead of SLOB.
++	   SLOB replaces the stock allocator with a drastically simpler
++	   allocator. SLOB is generally more space efficient but
++	   does not perform as well on large systems.
+ 
+ endchoice
+ 
++config PROFILING
++	bool "Profiling support (EXPERIMENTAL)"
++	help
++	  Say Y here to enable the extended profiling support mechanisms used
++	  by profilers such as OProfile.
++
++config MARKERS
++	bool "Activate markers"
++	help
++	  Place an empty function call at each marker site. Can be
++	  dynamically changed for a probe function.
++
++source "arch/Kconfig"
++
++config PROC_PAGE_MONITOR
++ 	default y
++	depends on PROC_FS && MMU
++	bool "Enable /proc page monitoring" if EMBEDDED
++ 	help
++	  Various /proc files exist to monitor process memory utilization:
++	  /proc/pid/smaps, /proc/pid/clear_refs, /proc/pid/pagemap,
++	  /proc/kpagecount, and /proc/kpageflags. Disabling these
++          interfaces will reduce the size of the kernel by approximately 4kb.
++
+ endmenu		# General setup
+ 
+ config SLABINFO
+@@ -762,3 +792,39 @@ source "block/Kconfig"
  
  config PREEMPT_NOTIFIERS
  	bool
@@ -886277,6 +959133,61 @@
  
 +config SCHED_HRTICK
 +	def_bool HIGH_RES_TIMERS && X86
+diff --git a/kernel/Kconfig.instrumentation b/kernel/Kconfig.instrumentation
+deleted file mode 100644
+index 468f47a..0000000
+--- a/kernel/Kconfig.instrumentation
++++ /dev/null
+@@ -1,49 +0,0 @@
+-menuconfig INSTRUMENTATION
+-	bool "Instrumentation Support"
+-	default y
+-	---help---
+-	  Say Y here to get to see options related to performance measurement,
+-	  system-wide debugging, and testing. This option alone does not add any
+-	  kernel code.
+-
+-	  If you say N, all options in this submenu will be skipped and
+-	  disabled. If you're trying to debug the kernel itself, go see the
+-	  Kernel Hacking menu.
+-
+-if INSTRUMENTATION
+-
+-config PROFILING
+-	bool "Profiling support (EXPERIMENTAL)"
+-	help
+-	  Say Y here to enable the extended profiling support mechanisms used
+-	  by profilers such as OProfile.
+-
+-config OPROFILE
+-	tristate "OProfile system profiling (EXPERIMENTAL)"
+-	depends on PROFILING && !UML
+-	depends on ARCH_SUPPORTS_OPROFILE || ALPHA || ARM || BLACKFIN || IA64 || M32R || PARISC || PPC || S390 || SUPERH || SPARC
+-	help
+-	  OProfile is a profiling system capable of profiling the
+-	  whole system, include the kernel, kernel modules, libraries,
+-	  and applications.
+-
+-	  If unsure, say N.
+-
+-config KPROBES
+-	bool "Kprobes"
+-	depends on KALLSYMS && MODULES && !UML
+-	depends on X86_32 || IA64 || PPC || S390 || SPARC64 || X86_64 || AVR32
+-	help
+-	  Kprobes allows you to trap at almost any kernel address and
+-	  execute a callback function.  register_kprobe() establishes
+-	  a probepoint and specifies the callback.  Kprobes is useful
+-	  for kernel debugging, non-intrusive instrumentation and testing.
+-	  If in doubt, say "N".
+-
+-config MARKERS
+-	bool "Activate markers"
+-	help
+-	  Place an empty function call at each marker site. Can be
+-	  dynamically changed for a probe function.
+-
+-endif # INSTRUMENTATION
 diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
 index c64ce9c..0669b70 100644
 --- a/kernel/Kconfig.preempt
@@ -886303,9 +959214,20 @@
  	  Say N if you are unsure.
 -
 diff --git a/kernel/Makefile b/kernel/Makefile
-index dfa9695..8885627 100644
+index dfa9695..135a1b9 100644
 --- a/kernel/Makefile
 +++ b/kernel/Makefile
+@@ -8,8 +8,8 @@ obj-y     = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
+ 	    signal.o sys.o kmod.o workqueue.o pid.o \
+ 	    rcupdate.o extable.o params.o posix-timers.o \
+ 	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \
+-	    hrtimer.o rwsem.o latency.o nsproxy.o srcu.o \
+-	    utsname.o notifier.o
++	    hrtimer.o rwsem.o nsproxy.o srcu.o \
++	    utsname.o notifier.o ksysfs.o pm_qos_params.o
+ 
+ obj-$(CONFIG_SYSCTL) += sysctl_check.o
+ obj-$(CONFIG_STACKTRACE) += stacktrace.o
 @@ -36,6 +36,7 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o
  obj-$(CONFIG_PM) += power/
  obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
@@ -886314,7 +959236,7 @@
  obj-$(CONFIG_COMPAT) += compat.o
  obj-$(CONFIG_CGROUPS) += cgroup.o
  obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o
-@@ -43,6 +44,7 @@ obj-$(CONFIG_CPUSETS) += cpuset.o
+@@ -43,20 +44,26 @@ obj-$(CONFIG_CPUSETS) += cpuset.o
  obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
  obj-$(CONFIG_IKCONFIG) += configs.o
  obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
@@ -886322,7 +959244,9 @@
  obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
  obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
  obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
-@@ -52,11 +54,17 @@ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
+ obj-$(CONFIG_KPROBES) += kprobes.o
+-obj-$(CONFIG_SYSFS) += ksysfs.o
+ obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
  obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
  obj-$(CONFIG_SECCOMP) += seccomp.o
  obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
@@ -887750,6 +960674,175 @@
 +module_exit(exitf);
 +MODULE_LICENSE("GPL");
 +MODULE_AUTHOR("Arjan van de Ven <arjan at linux.intel.com>");
+diff --git a/kernel/capability.c b/kernel/capability.c
+index efbd9cd..39e8193 100644
+--- a/kernel/capability.c
++++ b/kernel/capability.c
+@@ -22,6 +22,37 @@
+ static DEFINE_SPINLOCK(task_capability_lock);
+ 
+ /*
++ * Leveraged for setting/resetting capabilities
++ */
++
++const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
++const kernel_cap_t __cap_full_set = CAP_FULL_SET;
++const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;
++
++EXPORT_SYMBOL(__cap_empty_set);
++EXPORT_SYMBOL(__cap_full_set);
++EXPORT_SYMBOL(__cap_init_eff_set);
++
++/*
++ * More recent versions of libcap are available from:
++ *
++ *   http://www.kernel.org/pub/linux/libs/security/linux-privs/
++ */
++
++static void warn_legacy_capability_use(void)
++{
++	static int warned;
++	if (!warned) {
++		char name[sizeof(current->comm)];
++
++		printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
++		       " (legacy support in use)\n",
++		       get_task_comm(name, current));
++		warned = 1;
++	}
++}
++
++/*
+  * For sys_getproccap() and sys_setproccap(), any of the three
+  * capability set pointers may be NULL -- indicating that that set is
+  * uninteresting and/or not to be changed.
+@@ -42,12 +73,21 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
+ 	pid_t pid;
+ 	__u32 version;
+ 	struct task_struct *target;
+-	struct __user_cap_data_struct data;
++	unsigned tocopy;
++	kernel_cap_t pE, pI, pP;
+ 
+ 	if (get_user(version, &header->version))
+ 		return -EFAULT;
+ 
+-	if (version != _LINUX_CAPABILITY_VERSION) {
++	switch (version) {
++	case _LINUX_CAPABILITY_VERSION_1:
++		warn_legacy_capability_use();
++		tocopy = _LINUX_CAPABILITY_U32S_1;
++		break;
++	case _LINUX_CAPABILITY_VERSION_2:
++		tocopy = _LINUX_CAPABILITY_U32S_2;
++		break;
++	default:
+ 		if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
+ 			return -EFAULT;
+ 		return -EINVAL;
+@@ -71,14 +111,47 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
+ 	} else
+ 		target = current;
+ 
+-	ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);
++	ret = security_capget(target, &pE, &pI, &pP);
+ 
+ out:
+ 	read_unlock(&tasklist_lock);
+ 	spin_unlock(&task_capability_lock);
+ 
+-	if (!ret && copy_to_user(dataptr, &data, sizeof data))
+-		return -EFAULT;
++	if (!ret) {
++		struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
++		unsigned i;
++
++		for (i = 0; i < tocopy; i++) {
++			kdata[i].effective = pE.cap[i];
++			kdata[i].permitted = pP.cap[i];
++			kdata[i].inheritable = pI.cap[i];
++		}
++
++		/*
++		 * Note, in the case, tocopy < _LINUX_CAPABILITY_U32S,
++		 * we silently drop the upper capabilities here. This
++		 * has the effect of making older libcap
++		 * implementations implicitly drop upper capability
++		 * bits when they perform a: capget/modify/capset
++		 * sequence.
++		 *
++		 * This behavior is considered fail-safe
++		 * behavior. Upgrading the application to a newer
++		 * version of libcap will enable access to the newer
++		 * capabilities.
++		 *
++		 * An alternative would be to return an error here
++		 * (-ERANGE), but that causes legacy applications to
++		 * unexpectidly fail; the capget/modify/capset aborts
++		 * before modification is attempted and the application
++		 * fails.
++		 */
++
++		if (copy_to_user(dataptr, kdata, tocopy
++				 * sizeof(struct __user_cap_data_struct))) {
++			return -EFAULT;
++		}
++	}
+ 
+ 	return ret;
+ }
+@@ -167,6 +240,8 @@ static inline int cap_set_all(kernel_cap_t *effective,
+  */
+ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
+ {
++	struct __user_cap_data_struct kdata[_LINUX_CAPABILITY_U32S];
++	unsigned i, tocopy;
+ 	kernel_cap_t inheritable, permitted, effective;
+ 	__u32 version;
+ 	struct task_struct *target;
+@@ -176,7 +251,15 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
+ 	if (get_user(version, &header->version))
+ 		return -EFAULT;
+ 
+-	if (version != _LINUX_CAPABILITY_VERSION) {
++	switch (version) {
++	case _LINUX_CAPABILITY_VERSION_1:
++		warn_legacy_capability_use();
++		tocopy = _LINUX_CAPABILITY_U32S_1;
++		break;
++	case _LINUX_CAPABILITY_VERSION_2:
++		tocopy = _LINUX_CAPABILITY_U32S_2;
++		break;
++	default:
+ 		if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))
+ 			return -EFAULT;
+ 		return -EINVAL;
+@@ -188,10 +271,22 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
+ 	if (pid && pid != task_pid_vnr(current) && !capable(CAP_SETPCAP))
+ 		return -EPERM;
+ 
+-	if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||
+-	    copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||
+-	    copy_from_user(&permitted, &data->permitted, sizeof(permitted)))
++	if (copy_from_user(&kdata, data, tocopy
++			   * sizeof(struct __user_cap_data_struct))) {
+ 		return -EFAULT;
++	}
++
++	for (i = 0; i < tocopy; i++) {
++		effective.cap[i] = kdata[i].effective;
++		permitted.cap[i] = kdata[i].permitted;
++		inheritable.cap[i] = kdata[i].inheritable;
++	}
++	while (i < _LINUX_CAPABILITY_U32S) {
++		effective.cap[i] = 0;
++		permitted.cap[i] = 0;
++		inheritable.cap[i] = 0;
++		i++;
++	}
+ 
+ 	spin_lock(&task_capability_lock);
+ 	read_lock(&tasklist_lock);
 diff --git a/kernel/cpu.c b/kernel/cpu.c
 index 6b3a0c1..e0d3a4f 100644
 --- a/kernel/cpu.c
@@ -888097,10 +961190,19 @@
   */
  
 diff --git a/kernel/exit.c b/kernel/exit.c
-index 549c055..bfb1c0e 100644
+index 549c055..9d3d0f0 100644
 --- a/kernel/exit.c
 +++ b/kernel/exit.c
-@@ -249,7 +249,7 @@ static int has_stopped_jobs(struct pid *pgrp)
+@@ -50,8 +50,6 @@
+ #include <asm/pgtable.h>
+ #include <asm/mmu_context.h>
+ 
+-extern void sem_exit (void);
+-
+ static void exit_mm(struct task_struct * tsk);
+ 
+ static void __unhash_process(struct task_struct *p)
+@@ -249,7 +247,7 @@ static int has_stopped_jobs(struct pid *pgrp)
  	struct task_struct *p;
  
  	do_each_pid_task(pgrp, PIDTYPE_PGID, p) {
@@ -888109,7 +961211,7 @@
  			continue;
  		retval = 1;
  		break;
-@@ -614,7 +614,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
+@@ -614,7 +612,7 @@ reparent_thread(struct task_struct *p, struct task_struct *father, int traced)
  		p->parent = p->real_parent;
  		add_parent(p);
  
@@ -888118,7 +961220,21 @@
  			/*
  			 * If it was at a trace stop, turn it into
  			 * a normal stop since it's no longer being
-@@ -1563,60 +1563,51 @@ repeat:
+@@ -1085,11 +1083,12 @@ do_group_exit(int exit_code)
+ 		struct signal_struct *const sig = current->signal;
+ 		struct sighand_struct *const sighand = current->sighand;
+ 		spin_lock_irq(&sighand->siglock);
+-		if (sig->flags & SIGNAL_GROUP_EXIT)
++		if (signal_group_exit(sig))
+ 			/* Another thread got here before we took the lock.  */
+ 			exit_code = sig->group_exit_code;
+ 		else {
+ 			sig->group_exit_code = exit_code;
++			sig->flags = SIGNAL_GROUP_EXIT;
+ 			zap_other_threads(current);
+ 		}
+ 		spin_unlock_irq(&sighand->siglock);
+@@ -1563,60 +1562,51 @@ repeat:
  			}
  			allowed = 1;
  
@@ -888213,7 +961329,7 @@
  check_continued:
  				/*
  				 * It's running now, so it might later
-@@ -1625,12 +1616,11 @@ check_continued:
+@@ -1625,12 +1615,11 @@ check_continued:
  				flag = 1;
  				if (!unlikely(options & WCONTINUED))
  					continue;
@@ -888244,7 +961360,7 @@
  		return 1;
  	return 0;
 diff --git a/kernel/fork.c b/kernel/fork.c
-index 8dd8ff2..05e0b6f 100644
+index 8dd8ff2..2b55b74 100644
 --- a/kernel/fork.c
 +++ b/kernel/fork.c
 @@ -51,6 +51,7 @@
@@ -888255,6 +961371,15 @@
  
  #include <asm/pgtable.h>
  #include <asm/pgalloc.h>
+@@ -324,7 +325,7 @@ static inline int mm_alloc_pgd(struct mm_struct * mm)
+ 
+ static inline void mm_free_pgd(struct mm_struct * mm)
+ {
+-	pgd_free(mm->pgd);
++	pgd_free(mm, mm->pgd);
+ }
+ #else
+ #define dup_mmap(mm, oldmm)	(0)
 @@ -392,6 +393,7 @@ void fastcall __mmdrop(struct mm_struct *mm)
  	destroy_context(mm);
  	free_mm(mm);
@@ -888318,7 +961443,15 @@
  #ifdef CONFIG_TASK_XACCT
  	p->rchar = 0;		/* I/O counter: bytes read */
  	p->wchar = 0;		/* I/O counter: bytes written */
-@@ -1147,15 +1183,17 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1082,6 +1118,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+ #ifdef CONFIG_SECURITY
+ 	p->security = NULL;
+ #endif
++	p->cap_bset = current->cap_bset;
+ 	p->io_context = NULL;
+ 	p->audit_context = NULL;
+ 	cgroup_fork(p);
+@@ -1147,15 +1184,17 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  		goto bad_fork_cleanup_mm;
  	if ((retval = copy_namespaces(clone_flags, p)))
  		goto bad_fork_cleanup_keys;
@@ -888338,7 +961471,7 @@
  
  		if (clone_flags & CLONE_NEWPID) {
  			retval = pid_ns_prepare_proc(task_active_pid_ns(p));
-@@ -1196,6 +1234,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1196,6 +1235,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  #ifdef TIF_SYSCALL_EMU
  	clear_tsk_thread_flag(p, TIF_SYSCALL_EMU);
  #endif
@@ -888346,7 +961479,7 @@
  
  	/* Our parent execution domain becomes current domain
  	   These must match for thread signalling to apply */
-@@ -1224,9 +1263,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1224,9 +1264,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  	/* Need tasklist lock for parent etc handling! */
  	write_lock_irq(&tasklist_lock);
  
@@ -888356,7 +961489,7 @@
  	/*
  	 * The task hasn't been attached yet, so its cpus_allowed mask will
  	 * not be changed, nor will its assigned CPU.
-@@ -1237,6 +1273,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1237,6 +1274,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  	 * parent's CPU). This avoids alot of nasty races.
  	 */
  	p->cpus_allowed = current->cpus_allowed;
@@ -888364,7 +961497,7 @@
  	if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed) ||
  			!cpu_online(task_cpu(p))))
  		set_task_cpu(p, smp_processor_id());
-@@ -1317,6 +1354,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1317,6 +1355,8 @@ static struct task_struct *copy_process(unsigned long clone_flags,
  bad_fork_free_pid:
  	if (pid != &init_struct_pid)
  		free_pid(pid);
@@ -888373,6 +961506,30 @@
  bad_fork_cleanup_namespaces:
  	exit_task_namespaces(p);
  bad_fork_cleanup_keys:
+@@ -1411,6 +1451,23 @@ long do_fork(unsigned long clone_flags,
+ 	int trace = 0;
+ 	long nr;
+ 
++	/*
++	 * We hope to recycle these flags after 2.6.26
++	 */
++	if (unlikely(clone_flags & CLONE_STOPPED)) {
++		static int __read_mostly count = 100;
++
++		if (count > 0 && printk_ratelimit()) {
++			char comm[TASK_COMM_LEN];
++
++			count--;
++			printk(KERN_INFO "fork(): process `%s' used deprecated "
++					"clone flags 0x%lx\n",
++				get_task_comm(comm, current),
++				clone_flags & CLONE_STOPPED);
++		}
++	}
++
+ 	if (unlikely(current->ptrace)) {
+ 		trace = fork_traceflag (clone_flags);
+ 		if (trace)
 diff --git a/kernel/futex.c b/kernel/futex.c
 index db9824d..a6baaec 100644
 --- a/kernel/futex.c
@@ -888528,10 +961685,24 @@
  			return -EFAULT;
  		if (!timespec_valid(&ts))
 diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
-index f994bb8..1069998 100644
+index f994bb8..668f396 100644
 --- a/kernel/hrtimer.c
 +++ b/kernel/hrtimer.c
-@@ -325,6 +325,22 @@ unsigned long ktime_divns(const ktime_t kt, s64 div)
+@@ -306,7 +306,7 @@ EXPORT_SYMBOL_GPL(ktime_sub_ns);
+ /*
+  * Divide a ktime value by a nanosecond value
+  */
+-unsigned long ktime_divns(const ktime_t kt, s64 div)
++u64 ktime_divns(const ktime_t kt, s64 div)
+ {
+ 	u64 dclc, inc, dns;
+ 	int sft = 0;
+@@ -321,10 +321,26 @@ unsigned long ktime_divns(const ktime_t kt, s64 div)
+ 	dclc >>= sft;
+ 	do_div(dclc, (unsigned long) div);
+ 
+-	return (unsigned long) dclc;
++	return dclc;
  }
  #endif /* BITS_PER_LONG >= 64 */
  
@@ -888608,7 +961779,20 @@
  
  #endif /* CONFIG_HIGH_RES_TIMERS */
  
-@@ -1001,6 +1002,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
+@@ -655,10 +656,9 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags)
+  * Forward the timer expiry so it will expire in the future.
+  * Returns the number of overruns.
+  */
+-unsigned long
+-hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
++u64 hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval)
+ {
+-	unsigned long orun = 1;
++	u64 orun = 1;
+ 	ktime_t delta;
+ 
+ 	delta = ktime_sub(now, timer->expires);
+@@ -1001,6 +1001,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id,
  		clock_id = CLOCK_MONOTONIC;
  
  	timer->base = &cpu_base->clock_base[clock_id];
@@ -888616,7 +961800,7 @@
  	hrtimer_init_timer_hres(timer);
  
  #ifdef CONFIG_TIMER_STATS
-@@ -1030,6 +1032,85 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
+@@ -1030,6 +1031,85 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp)
  }
  EXPORT_SYMBOL_GPL(hrtimer_get_res);
  
@@ -888702,7 +961886,7 @@
  #ifdef CONFIG_HIGH_RES_TIMERS
  
  /*
-@@ -1087,21 +1168,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
+@@ -1087,21 +1167,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
  				continue;
  			}
  
@@ -888725,7 +961909,7 @@
  		}
  		spin_unlock(&cpu_base->lock);
  		base++;
-@@ -1122,52 +1189,41 @@ void hrtimer_interrupt(struct clock_event_device *dev)
+@@ -1122,52 +1188,41 @@ void hrtimer_interrupt(struct clock_event_device *dev)
  
  static void run_hrtimer_softirq(struct softirq_action *h)
  {
@@ -888805,7 +961989,7 @@
   */
  static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
  				     int index)
-@@ -1181,46 +1237,27 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
+@@ -1181,46 +1236,27 @@ static inline void run_hrtimer_queue(struct hrtimer_cpu_base *cpu_base,
  	if (base->get_softirq_time)
  		base->softirq_time = base->get_softirq_time();
  
@@ -888861,7 +962045,7 @@
  void hrtimer_run_queues(void)
  {
  	struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
-@@ -1229,18 +1266,6 @@ void hrtimer_run_queues(void)
+@@ -1229,18 +1265,6 @@ void hrtimer_run_queues(void)
  	if (hrtimer_hres_active())
  		return;
  
@@ -888880,7 +962064,7 @@
  	hrtimer_get_softirq_time(cpu_base);
  
  	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
-@@ -1268,7 +1293,7 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
+@@ -1268,7 +1292,7 @@ void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, struct task_struct *task)
  	sl->timer.function = hrtimer_wakeup;
  	sl->task = task;
  #ifdef CONFIG_HIGH_RES_TIMERS
@@ -888889,7 +962073,7 @@
  #endif
  }
  
-@@ -1279,6 +1304,8 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
+@@ -1279,6 +1303,8 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
  	do {
  		set_current_state(TASK_INTERRUPTIBLE);
  		hrtimer_start(&t->timer, t->timer.expires, mode);
@@ -888898,7 +962082,7 @@
  
  		if (likely(t->task))
  			schedule();
-@@ -1288,6 +1315,8 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
+@@ -1288,6 +1314,8 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
  
  	} while (t->task && !signal_pending(current));
  
@@ -888907,7 +962091,7 @@
  	return t->task == NULL;
  }
  
-@@ -1389,6 +1418,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
+@@ -1389,6 +1417,7 @@ static void __cpuinit init_hrtimers_cpu(int cpu)
  	for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++)
  		cpu_base->clock_base[i].cpu_base = cpu_base;
  
@@ -889248,6 +962432,292 @@
  	set_cpus_allowed(tsk, CPU_MASK_ALL);
  
  	current->flags |= PF_NOFREEZE;
+diff --git a/kernel/latency.c b/kernel/latency.c
+deleted file mode 100644
+index e63fcac..0000000
+--- a/kernel/latency.c
++++ /dev/null
+@@ -1,280 +0,0 @@
+-/*
+- * latency.c: Explicit system-wide latency-expectation infrastructure
+- *
+- * The purpose of this infrastructure is to allow device drivers to set
+- * latency constraint they have and to collect and summarize these
+- * expectations globally. The cummulated result can then be used by
+- * power management and similar users to make decisions that have
+- * tradoffs with a latency component.
+- *
+- * An example user of this are the x86 C-states; each higher C state saves
+- * more power, but has a higher exit latency. For the idle loop power
+- * code to make a good decision which C-state to use, information about
+- * acceptable latencies is required.
+- *
+- * An example announcer of latency is an audio driver that knowns it
+- * will get an interrupt when the hardware has 200 usec of samples
+- * left in the DMA buffer; in that case the driver can set a latency
+- * constraint of, say, 150 usec.
+- *
+- * Multiple drivers can each announce their maximum accepted latency,
+- * to keep these appart, a string based identifier is used.
+- *
+- *
+- * (C) Copyright 2006 Intel Corporation
+- * Author: Arjan van de Ven <arjan at linux.intel.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; version 2
+- * of the License.
+- */
+-
+-#include <linux/latency.h>
+-#include <linux/list.h>
+-#include <linux/spinlock.h>
+-#include <linux/slab.h>
+-#include <linux/module.h>
+-#include <linux/notifier.h>
+-#include <linux/jiffies.h>
+-#include <asm/atomic.h>
+-
+-struct latency_info {
+-	struct list_head list;
+-	int usecs;
+-	char *identifier;
+-};
+-
+-/*
+- * locking rule: all modifications to current_max_latency and
+- * latency_list need to be done while holding the latency_lock.
+- * latency_lock needs to be taken _irqsave.
+- */
+-static atomic_t current_max_latency;
+-static DEFINE_SPINLOCK(latency_lock);
+-
+-static LIST_HEAD(latency_list);
+-static BLOCKING_NOTIFIER_HEAD(latency_notifier);
+-
+-/*
+- * This function returns the maximum latency allowed, which
+- * happens to be the minimum of all maximum latencies on the
+- * list.
+- */
+-static int __find_max_latency(void)
+-{
+-	int min = INFINITE_LATENCY;
+-	struct latency_info *info;
+-
+-	list_for_each_entry(info, &latency_list, list) {
+-		if (info->usecs < min)
+-			min = info->usecs;
+-	}
+-	return min;
+-}
+-
+-/**
+- * set_acceptable_latency - sets the maximum latency acceptable
+- * @identifier: string that identifies this driver
+- * @usecs: maximum acceptable latency for this driver
+- *
+- * This function informs the kernel that this device(driver)
+- * can accept at most usecs latency. This setting is used for
+- * power management and similar tradeoffs.
+- *
+- * This function sleeps and can only be called from process
+- * context.
+- * Calling this function with an existing identifier is valid
+- * and will cause the existing latency setting to be changed.
+- */
+-void set_acceptable_latency(char *identifier, int usecs)
+-{
+-	struct latency_info *info, *iter;
+-	unsigned long flags;
+-	int found_old = 0;
+-
+-	info = kzalloc(sizeof(struct latency_info), GFP_KERNEL);
+-	if (!info)
+-		return;
+-	info->usecs = usecs;
+-	info->identifier = kstrdup(identifier, GFP_KERNEL);
+-	if (!info->identifier)
+-		goto free_info;
+-
+-	spin_lock_irqsave(&latency_lock, flags);
+-	list_for_each_entry(iter, &latency_list, list) {
+-		if (strcmp(iter->identifier, identifier)==0) {
+-			found_old = 1;
+-			iter->usecs = usecs;
+-			break;
+-		}
+-	}
+-	if (!found_old)
+-		list_add(&info->list, &latency_list);
+-
+-	if (usecs < atomic_read(&current_max_latency))
+-		atomic_set(&current_max_latency, usecs);
+-
+-	spin_unlock_irqrestore(&latency_lock, flags);
+-
+-	blocking_notifier_call_chain(&latency_notifier,
+-		atomic_read(&current_max_latency), NULL);
+-
+-	/*
+-	 * if we inserted the new one, we're done; otherwise there was
+-	 * an existing one so we need to free the redundant data
+-	 */
+-	if (!found_old)
+-		return;
+-
+-	kfree(info->identifier);
+-free_info:
+-	kfree(info);
+-}
+-EXPORT_SYMBOL_GPL(set_acceptable_latency);
+-
+-/**
+- * modify_acceptable_latency - changes the maximum latency acceptable
+- * @identifier: string that identifies this driver
+- * @usecs: maximum acceptable latency for this driver
+- *
+- * This function informs the kernel that this device(driver)
+- * can accept at most usecs latency. This setting is used for
+- * power management and similar tradeoffs.
+- *
+- * This function does not sleep and can be called in any context.
+- * Trying to use a non-existing identifier silently gets ignored.
+- *
+- * Due to the atomic nature of this function, the modified latency
+- * value will only be used for future decisions; past decisions
+- * can still lead to longer latencies in the near future.
+- */
+-void modify_acceptable_latency(char *identifier, int usecs)
+-{
+-	struct latency_info *iter;
+-	unsigned long flags;
+-
+-	spin_lock_irqsave(&latency_lock, flags);
+-	list_for_each_entry(iter, &latency_list, list) {
+-		if (strcmp(iter->identifier, identifier) == 0) {
+-			iter->usecs = usecs;
+-			break;
+-		}
+-	}
+-	if (usecs < atomic_read(&current_max_latency))
+-		atomic_set(&current_max_latency, usecs);
+-	spin_unlock_irqrestore(&latency_lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(modify_acceptable_latency);
+-
+-/**
+- * remove_acceptable_latency - removes the maximum latency acceptable
+- * @identifier: string that identifies this driver
+- *
+- * This function removes a previously set maximum latency setting
+- * for the driver and frees up any resources associated with the
+- * bookkeeping needed for this.
+- *
+- * This function does not sleep and can be called in any context.
+- * Trying to use a non-existing identifier silently gets ignored.
+- */
+-void remove_acceptable_latency(char *identifier)
+-{
+-	unsigned long flags;
+-	int newmax = 0;
+-	struct latency_info *iter, *temp;
+-
+-	spin_lock_irqsave(&latency_lock, flags);
+-
+-	list_for_each_entry_safe(iter,  temp, &latency_list, list) {
+-		if (strcmp(iter->identifier, identifier) == 0) {
+-			list_del(&iter->list);
+-			newmax = iter->usecs;
+-			kfree(iter->identifier);
+-			kfree(iter);
+-			break;
+-		}
+-	}
+-
+-	/* If we just deleted the system wide value, we need to
+-	 * recalculate with a full search
+-	 */
+-	if (newmax == atomic_read(&current_max_latency)) {
+-		newmax = __find_max_latency();
+-		atomic_set(&current_max_latency, newmax);
+-	}
+-	spin_unlock_irqrestore(&latency_lock, flags);
+-}
+-EXPORT_SYMBOL_GPL(remove_acceptable_latency);
+-
+-/**
+- * system_latency_constraint - queries the system wide latency maximum
+- *
+- * This function returns the system wide maximum latency in
+- * microseconds.
+- *
+- * This function does not sleep and can be called in any context.
+- */
+-int system_latency_constraint(void)
+-{
+-	return atomic_read(&current_max_latency);
+-}
+-EXPORT_SYMBOL_GPL(system_latency_constraint);
+-
+-/**
+- * synchronize_acceptable_latency - recalculates all latency decisions
+- *
+- * This function will cause a callback to various kernel pieces that
+- * will make those pieces rethink their latency decisions. This implies
+- * that if there are overlong latencies in hardware state already, those
+- * latencies get taken right now. When this call completes no overlong
+- * latency decisions should be active anymore.
+- *
+- * Typical usecase of this is after a modify_acceptable_latency() call,
+- * which in itself is non-blocking and non-synchronizing.
+- *
+- * This function blocks and should not be called with locks held.
+- */
+-
+-void synchronize_acceptable_latency(void)
+-{
+-	blocking_notifier_call_chain(&latency_notifier,
+-		atomic_read(&current_max_latency), NULL);
+-}
+-EXPORT_SYMBOL_GPL(synchronize_acceptable_latency);
+-
+-/*
+- * Latency notifier: this notifier gets called when a non-atomic new
+- * latency value gets set. The expectation nof the caller of the
+- * non-atomic set is that when the call returns, future latencies
+- * are within bounds, so the functions on the notifier list are
+- * expected to take the overlong latencies immediately, inside the
+- * callback, and not make a overlong latency decision anymore.
+- *
+- * The callback gets called when the new latency value is made
+- * active so system_latency_constraint() returns the new latency.
+- */
+-int register_latency_notifier(struct notifier_block * nb)
+-{
+-	return blocking_notifier_chain_register(&latency_notifier, nb);
+-}
+-EXPORT_SYMBOL_GPL(register_latency_notifier);
+-
+-int unregister_latency_notifier(struct notifier_block * nb)
+-{
+-	return blocking_notifier_chain_unregister(&latency_notifier, nb);
+-}
+-EXPORT_SYMBOL_GPL(unregister_latency_notifier);
+-
+-static __init int latency_init(void)
+-{
+-	atomic_set(&current_max_latency, INFINITE_LATENCY);
+-	/*
+-	 * we don't want by default to have longer latencies than 2 ticks,
+-	 * since that would cause lost ticks
+-	 */
+-	set_acceptable_latency("kernel", 2*1000000/HZ);
+-	return 0;
+-}
+-
+-module_init(latency_init);
 diff --git a/kernel/latencytop.c b/kernel/latencytop.c
 new file mode 100644
 index 0000000..b4e3c85
@@ -890285,6 +963755,437 @@
  
  EXPORT_SYMBOL(param_set_byte);
  EXPORT_SYMBOL(param_get_byte);
+diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
+new file mode 100644
+index 0000000..0afe32b
+--- /dev/null
++++ b/kernel/pm_qos_params.c
+@@ -0,0 +1,425 @@
++/*
++ * This module exposes the interface to kernel space for specifying
++ * QoS dependencies.  It provides infrastructure for registration of:
++ *
++ * Dependents on a QoS value : register requirements
++ * Watchers of QoS value : get notified when target QoS value changes
++ *
++ * This QoS design is best effort based.  Dependents register their QoS needs.
++ * Watchers register to keep track of the current QoS needs of the system.
++ *
++ * There are 3 basic classes of QoS parameter: latency, timeout, throughput
++ * each have defined units:
++ * latency: usec
++ * timeout: usec <-- currently not used.
++ * throughput: kbs (kilo byte / sec)
++ *
++ * There are lists of pm_qos_objects each one wrapping requirements, notifiers
++ *
++ * User mode requirements on a QOS parameter register themselves to the
++ * subsystem by opening the device node /dev/... and writing there request to
++ * the node.  As long as the process holds a file handle open to the node the
++ * client continues to be accounted for.  Upon file release the usermode
++ * requirement is removed and a new qos target is computed.  This way when the
++ * requirement that the application has is cleaned up when closes the file
++ * pointer or exits the pm_qos_object will get an opportunity to clean up.
++ *
++ * mark gross mgross at linux.intel.com
++ */
++
++#include <linux/pm_qos_params.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/time.h>
++#include <linux/fs.h>
++#include <linux/device.h>
++#include <linux/miscdevice.h>
++#include <linux/string.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++
++#include <linux/uaccess.h>
++
++/*
++ * locking rule: all changes to target_value or requirements or notifiers lists
++ * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
++ * held, taken with _irqsave.  One lock to rule them all
++ */
++struct requirement_list {
++	struct list_head list;
++	union {
++		s32 value;
++		s32 usec;
++		s32 kbps;
++	};
++	char *name;
++};
++
++static s32 max_compare(s32 v1, s32 v2);
++static s32 min_compare(s32 v1, s32 v2);
++
++struct pm_qos_object {
++	struct requirement_list requirements;
++	struct blocking_notifier_head *notifiers;
++	struct miscdevice pm_qos_power_miscdev;
++	char *name;
++	s32 default_value;
++	s32 target_value;
++	s32 (*comparitor)(s32, s32);
++};
++
++static struct pm_qos_object null_pm_qos;
++static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
++static struct pm_qos_object cpu_dma_pm_qos = {
++	.requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
++	.notifiers = &cpu_dma_lat_notifier,
++	.name = "cpu_dma_latency",
++	.default_value = 2000 * USEC_PER_SEC,
++	.target_value = 2000 * USEC_PER_SEC,
++	.comparitor = min_compare
++};
++
++static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
++static struct pm_qos_object network_lat_pm_qos = {
++	.requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
++	.notifiers = &network_lat_notifier,
++	.name = "network_latency",
++	.default_value = 2000 * USEC_PER_SEC,
++	.target_value = 2000 * USEC_PER_SEC,
++	.comparitor = min_compare
++};
++
++
++static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
++static struct pm_qos_object network_throughput_pm_qos = {
++	.requirements =
++		{LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
++	.notifiers = &network_throughput_notifier,
++	.name = "network_throughput",
++	.default_value = 0,
++	.target_value = 0,
++	.comparitor = max_compare
++};
++
++
++static struct pm_qos_object *pm_qos_array[] = {
++	&null_pm_qos,
++	&cpu_dma_pm_qos,
++	&network_lat_pm_qos,
++	&network_throughput_pm_qos
++};
++
++static DEFINE_SPINLOCK(pm_qos_lock);
++
++static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
++		size_t count, loff_t *f_pos);
++static int pm_qos_power_open(struct inode *inode, struct file *filp);
++static int pm_qos_power_release(struct inode *inode, struct file *filp);
++
++static const struct file_operations pm_qos_power_fops = {
++	.write = pm_qos_power_write,
++	.open = pm_qos_power_open,
++	.release = pm_qos_power_release,
++};
++
++/* static helper functions */
++static s32 max_compare(s32 v1, s32 v2)
++{
++	return max(v1, v2);
++}
++
++static s32 min_compare(s32 v1, s32 v2)
++{
++	return min(v1, v2);
++}
++
++
++static void update_target(int target)
++{
++	s32 extreme_value;
++	struct requirement_list *node;
++	unsigned long flags;
++	int call_notifier = 0;
++
++	spin_lock_irqsave(&pm_qos_lock, flags);
++	extreme_value = pm_qos_array[target]->default_value;
++	list_for_each_entry(node,
++			&pm_qos_array[target]->requirements.list, list) {
++		extreme_value = pm_qos_array[target]->comparitor(
++				extreme_value, node->value);
++	}
++	if (pm_qos_array[target]->target_value != extreme_value) {
++		call_notifier = 1;
++		pm_qos_array[target]->target_value = extreme_value;
++		pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
++			pm_qos_array[target]->target_value);
++	}
++	spin_unlock_irqrestore(&pm_qos_lock, flags);
++
++	if (call_notifier)
++		blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
++			(unsigned long) extreme_value, NULL);
++}
++
++static int register_pm_qos_misc(struct pm_qos_object *qos)
++{
++	qos->pm_qos_power_miscdev.minor = MISC_DYNAMIC_MINOR;
++	qos->pm_qos_power_miscdev.name = qos->name;
++	qos->pm_qos_power_miscdev.fops = &pm_qos_power_fops;
++
++	return misc_register(&qos->pm_qos_power_miscdev);
++}
++
++static int find_pm_qos_object_by_minor(int minor)
++{
++	int pm_qos_class;
++
++	for (pm_qos_class = 0;
++		pm_qos_class < PM_QOS_NUM_CLASSES; pm_qos_class++) {
++		if (minor ==
++			pm_qos_array[pm_qos_class]->pm_qos_power_miscdev.minor)
++			return pm_qos_class;
++	}
++	return -1;
++}
++
++/**
++ * pm_qos_requirement - returns current system wide qos expectation
++ * @pm_qos_class: identification of which qos value is requested
++ *
++ * This function returns the current target value in an atomic manner.
++ */
++int pm_qos_requirement(int pm_qos_class)
++{
++	int ret_val;
++	unsigned long flags;
++
++	spin_lock_irqsave(&pm_qos_lock, flags);
++	ret_val = pm_qos_array[pm_qos_class]->target_value;
++	spin_unlock_irqrestore(&pm_qos_lock, flags);
++
++	return ret_val;
++}
++EXPORT_SYMBOL_GPL(pm_qos_requirement);
++
++/**
++ * pm_qos_add_requirement - inserts new qos request into the list
++ * @pm_qos_class: identifies which list of qos request to us
++ * @name: identifies the request
++ * @value: defines the qos request
++ *
++ * This function inserts a new entry in the pm_qos_class list of requested qos
++ * performance charactoistics.  It recomputes the agregate QoS expectations for
++ * the pm_qos_class of parrameters.
++ */
++int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
++{
++	struct requirement_list *dep;
++	unsigned long flags;
++
++	dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
++	if (dep) {
++		if (value == PM_QOS_DEFAULT_VALUE)
++			dep->value = pm_qos_array[pm_qos_class]->default_value;
++		else
++			dep->value = value;
++		dep->name = kstrdup(name, GFP_KERNEL);
++		if (!dep->name)
++			goto cleanup;
++
++		spin_lock_irqsave(&pm_qos_lock, flags);
++		list_add(&dep->list,
++			&pm_qos_array[pm_qos_class]->requirements.list);
++		spin_unlock_irqrestore(&pm_qos_lock, flags);
++		update_target(pm_qos_class);
++
++		return 0;
++	}
++
++cleanup:
++	kfree(dep);
++	return -ENOMEM;
++}
++EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
++
++/**
++ * pm_qos_update_requirement - modifies an existing qos request
++ * @pm_qos_class: identifies which list of qos request to us
++ * @name: identifies the request
++ * @value: defines the qos request
++ *
++ * Updates an existing qos requierement for the pm_qos_class of parameters along
++ * with updating the target pm_qos_class value.
++ *
++ * If the named request isn't in the lest then no change is made.
++ */
++int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
++{
++	unsigned long flags;
++	struct requirement_list *node;
++	int pending_update = 0;
++
++	spin_lock_irqsave(&pm_qos_lock, flags);
++	list_for_each_entry(node,
++		&pm_qos_array[pm_qos_class]->requirements.list, list) {
++		if (strcmp(node->name, name) == 0) {
++			if (new_value == PM_QOS_DEFAULT_VALUE)
++				node->value =
++				pm_qos_array[pm_qos_class]->default_value;
++			else
++				node->value = new_value;
++			pending_update = 1;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&pm_qos_lock, flags);
++	if (pending_update)
++		update_target(pm_qos_class);
++
++	return 0;
++}
++EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
++
++/**
++ * pm_qos_remove_requirement - modifies an existing qos request
++ * @pm_qos_class: identifies which list of qos request to us
++ * @name: identifies the request
++ *
++ * Will remove named qos request from pm_qos_class list of parrameters and
++ * recompute the current target value for the pm_qos_class.
++ */
++void pm_qos_remove_requirement(int pm_qos_class, char *name)
++{
++	unsigned long flags;
++	struct requirement_list *node;
++	int pending_update = 0;
++
++	spin_lock_irqsave(&pm_qos_lock, flags);
++	list_for_each_entry(node,
++		&pm_qos_array[pm_qos_class]->requirements.list, list) {
++		if (strcmp(node->name, name) == 0) {
++			kfree(node->name);
++			list_del(&node->list);
++			kfree(node);
++			pending_update = 1;
++			break;
++		}
++	}
++	spin_unlock_irqrestore(&pm_qos_lock, flags);
++	if (pending_update)
++		update_target(pm_qos_class);
++}
++EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
++
++/**
++ * pm_qos_add_notifier - sets notification entry for changes to target value
++ * @pm_qos_class: identifies which qos target changes should be notified.
++ * @notifier: notifier block managed by caller.
++ *
++ * will register the notifier into a notification chain that gets called
++ * uppon changes to the pm_qos_class target value.
++ */
++ int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
++{
++	int retval;
++
++	retval = blocking_notifier_chain_register(
++			pm_qos_array[pm_qos_class]->notifiers, notifier);
++
++	return retval;
++}
++EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
++
++/**
++ * pm_qos_remove_notifier - deletes notification entry from chain.
++ * @pm_qos_class: identifies which qos target changes are notified.
++ * @notifier: notifier block to be removed.
++ *
++ * will remove the notifier from the notification chain that gets called
++ * uppon changes to the pm_qos_class target value.
++ */
++int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
++{
++	int retval;
++
++	retval = blocking_notifier_chain_unregister(
++			pm_qos_array[pm_qos_class]->notifiers, notifier);
++
++	return retval;
++}
++EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
++
++#define PID_NAME_LEN sizeof("process_1234567890")
++static char name[PID_NAME_LEN];
++
++static int pm_qos_power_open(struct inode *inode, struct file *filp)
++{
++	int ret;
++	long pm_qos_class;
++
++	pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
++	if (pm_qos_class >= 0) {
++		filp->private_data = (void *)pm_qos_class;
++		sprintf(name, "process_%d", current->pid);
++		ret = pm_qos_add_requirement(pm_qos_class, name,
++					PM_QOS_DEFAULT_VALUE);
++		if (ret >= 0)
++			return 0;
++	}
++
++	return -EPERM;
++}
++
++static int pm_qos_power_release(struct inode *inode, struct file *filp)
++{
++	int pm_qos_class;
++
++	pm_qos_class = (long)filp->private_data;
++	sprintf(name, "process_%d", current->pid);
++	pm_qos_remove_requirement(pm_qos_class, name);
++
++	return 0;
++}
++
++static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
++		size_t count, loff_t *f_pos)
++{
++	s32 value;
++	int pm_qos_class;
++
++	pm_qos_class = (long)filp->private_data;
++	if (count != sizeof(s32))
++		return -EINVAL;
++	if (copy_from_user(&value, buf, sizeof(s32)))
++		return -EFAULT;
++	sprintf(name, "process_%d", current->pid);
++	pm_qos_update_requirement(pm_qos_class, name, value);
++
++	return  sizeof(s32);
++}
++
++
++static int __init pm_qos_power_init(void)
++{
++	int ret = 0;
++
++	ret = register_pm_qos_misc(&cpu_dma_pm_qos);
++	if (ret < 0) {
++		printk(KERN_ERR "pm_qos_param: cpu_dma_latency setup failed\n");
++		return ret;
++	}
++	ret = register_pm_qos_misc(&network_lat_pm_qos);
++	if (ret < 0) {
++		printk(KERN_ERR "pm_qos_param: network_latency setup failed\n");
++		return ret;
++	}
++	ret = register_pm_qos_misc(&network_throughput_pm_qos);
++	if (ret < 0)
++		printk(KERN_ERR
++			"pm_qos_param: network_throughput setup failed\n");
++
++	return ret;
++}
++
++late_initcall(pm_qos_power_init);
 diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
 index 68c9637..0b7c82a 100644
 --- a/kernel/posix-cpu-timers.c
@@ -890333,6 +964234,49 @@
  }
  
  /*
+diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
+index 35b4bbf..122d5c7 100644
+--- a/kernel/posix-timers.c
++++ b/kernel/posix-timers.c
+@@ -256,8 +256,9 @@ static void schedule_next_timer(struct k_itimer *timr)
+ 	if (timr->it.real.interval.tv64 == 0)
+ 		return;
+ 
+-	timr->it_overrun += hrtimer_forward(timer, timer->base->get_time(),
+-					    timr->it.real.interval);
++	timr->it_overrun += (unsigned int) hrtimer_forward(timer,
++						timer->base->get_time(),
++						timr->it.real.interval);
+ 
+ 	timr->it_overrun_last = timr->it_overrun;
+ 	timr->it_overrun = -1;
+@@ -386,7 +387,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
+ 					now = ktime_add(now, kj);
+ 			}
+ #endif
+-			timr->it_overrun +=
++			timr->it_overrun += (unsigned int)
+ 				hrtimer_forward(timer, now,
+ 						timr->it.real.interval);
+ 			ret = HRTIMER_RESTART;
+@@ -493,7 +494,7 @@ sys_timer_create(const clockid_t which_clock,
+ 		goto retry;
+ 	else if (error) {
+ 		/*
+-		 * Wierd looking, but we return EAGAIN if the IDR is
++		 * Weird looking, but we return EAGAIN if the IDR is
+ 		 * full (proper POSIX return value for this)
+ 		 */
+ 		error = -EAGAIN;
+@@ -662,7 +663,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
+ 	 */
+ 	if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
+ 	    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+-		timr->it_overrun += hrtimer_forward(timer, now, iv);
++		timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
+ 
+ 	remaining = ktime_sub(timer->expires, now);
+ 	/* Return 0 only, when the timer is expired and not pending */
 diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
 index 8e186c6..ef9b802 100644
 --- a/kernel/power/Kconfig
@@ -890438,9 +964382,18 @@
  	  Enable the suspend to disk (STD) functionality, which is usually
  	  called "hibernation" in user interfaces.  STD checkpoints the
 diff --git a/kernel/power/disk.c b/kernel/power/disk.c
-index 05b6479..d09da08 100644
+index 05b6479..859a8e5 100644
 --- a/kernel/power/disk.c
 +++ b/kernel/power/disk.c
+@@ -26,7 +26,7 @@
+ 
+ 
+ static int noresume = 0;
+-char resume_file[256] = CONFIG_PM_STD_PARTITION;
++static char resume_file[256] = CONFIG_PM_STD_PARTITION;
+ dev_t swsusp_resume_device;
+ sector_t swsusp_resume_block;
+ 
 @@ -54,8 +54,8 @@ static struct platform_hibernation_ops *hibernation_ops;
  
  void hibernation_set_ops(struct platform_hibernation_ops *ops)
@@ -890511,6 +964464,15 @@
  }
  
  /**
+@@ -145,7 +185,7 @@ static void platform_restore_cleanup(int platform_mode)
+  *	reappears in this routine after a restore.
+  */
+ 
+-int create_image(int platform_mode)
++static int create_image(int platform_mode)
+ {
+ 	int error;
+ 
 @@ -162,19 +202,25 @@ int create_image(int platform_mode)
  	 */
  	error = device_power_down(PMSG_FREEZE);
@@ -891418,7 +965380,7 @@
  				continue;
  			}
 diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
-index 78039b4..f6a5df9 100644
+index 78039b4..95250d7 100644
 --- a/kernel/power/snapshot.c
 +++ b/kernel/power/snapshot.c
 @@ -635,7 +635,7 @@ __register_nosave_region(unsigned long start_pfn, unsigned long end_pfn,
@@ -891474,14 +965436,15 @@
  		nr_pages, PAGES_FOR_IO, meta, free);
  
  	return free > nr_pages + PAGES_FOR_IO + meta;
-@@ -1202,20 +1201,20 @@ asmlinkage int swsusp_save(void)
+@@ -1202,27 +1201,27 @@ asmlinkage int swsusp_save(void)
  {
  	unsigned int nr_pages, nr_highmem;
  
 -	printk("swsusp: critical section: \n");
 +	printk(KERN_INFO "PM: Creating hibernation image: \n");
  
- 	drain_local_pages();
+-	drain_local_pages();
++	drain_local_pages(NULL);
  	nr_pages = count_data_pages();
  	nr_highmem = count_highmem_pages();
 -	printk("swsusp: Need to copy %u pages\n", nr_pages + nr_highmem);
@@ -891499,6 +965462,14 @@
  		return -ENOMEM;
  	}
  
+ 	/* During allocating of suspend pagedir, new cold pages may appear.
+ 	 * Kill them.
+ 	 */
+-	drain_local_pages();
++	drain_local_pages(NULL);
+ 	copy_data_pages(&copy_bm, &orig_bm);
+ 
+ 	/*
 @@ -1235,7 +1234,8 @@ asmlinkage int swsusp_save(void)
  	nr_copy_pages = nr_pages;
  	nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
@@ -895140,6 +969111,18 @@
  }
  
  /* Shuffle tasks across CPUs, with the intent of allowing each CPU in the
+diff --git a/kernel/relay.c b/kernel/relay.c
+index 61134eb..7c03733 100644
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -92,6 +92,7 @@ static int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
+ 		return -EINVAL;
+ 
+ 	vma->vm_ops = &relay_file_mmap_ops;
++	vma->vm_flags |= VM_DONTEXPAND;
+ 	vma->vm_private_data = buf;
+ 	buf->chan->cb->buf_mapped(buf, filp);
+ 
 diff --git a/kernel/rtmutex-tester.c b/kernel/rtmutex-tester.c
 index e3055ba..092e4c6 100644
 --- a/kernel/rtmutex-tester.c
@@ -899467,7 +973450,7 @@
 +	.switched_to		= switched_to_rt,
  };
 diff --git a/kernel/signal.c b/kernel/signal.c
-index afa4f78..4333b6d 100644
+index afa4f78..6a5f97c 100644
 --- a/kernel/signal.c
 +++ b/kernel/signal.c
 @@ -456,15 +456,15 @@ void signal_wake_up(struct task_struct *t, int resume)
@@ -899523,7 +973506,43 @@
  		return 0;
  	return task_curr(p) || !signal_pending(p);
  }
-@@ -994,6 +994,12 @@ void zap_other_threads(struct task_struct *p)
+@@ -911,27 +911,6 @@ __group_complete_signal(int sig, struct task_struct *p)
+ 			} while_each_thread(p, t);
+ 			return;
+ 		}
+-
+-		/*
+-		 * There will be a core dump.  We make all threads other
+-		 * than the chosen one go into a group stop so that nothing
+-		 * happens until it gets scheduled, takes the signal off
+-		 * the shared queue, and does the core dump.  This is a
+-		 * little more complicated than strictly necessary, but it
+-		 * keeps the signal state that winds up in the core dump
+-		 * unchanged from the death state, e.g. which thread had
+-		 * the core-dump signal unblocked.
+-		 */
+-		rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending);
+-		rm_from_queue(SIG_KERNEL_STOP_MASK, &p->signal->shared_pending);
+-		p->signal->group_stop_count = 0;
+-		p->signal->group_exit_task = t;
+-		p = t;
+-		do {
+-			p->signal->group_stop_count++;
+-			signal_wake_up(t, t == p);
+-		} while_each_thread(p, t);
+-		return;
+ 	}
+ 
+ 	/*
+@@ -978,7 +957,6 @@ void zap_other_threads(struct task_struct *p)
+ {
+ 	struct task_struct *t;
+ 
+-	p->signal->flags = SIGNAL_GROUP_EXIT;
+ 	p->signal->group_stop_count = 0;
+ 
+ 	for (t = next_thread(p); t != p; t = next_thread(t)) {
+@@ -994,6 +972,12 @@ void zap_other_threads(struct task_struct *p)
  	}
  }
  
@@ -899536,7 +973555,7 @@
  /*
   * Must be called under rcu_read_lock() or with tasklist_lock read-held.
   */
-@@ -1441,7 +1447,7 @@ void do_notify_parent(struct task_struct *tsk, int sig)
+@@ -1441,7 +1425,7 @@ void do_notify_parent(struct task_struct *tsk, int sig)
  	BUG_ON(sig == -1);
  
   	/* do_notify_parent_cldstop should have been called instead.  */
@@ -899545,7 +973564,35 @@
  
  	BUG_ON(!tsk->ptrace &&
  	       (tsk->group_leader != tsk || !thread_group_empty(tsk)));
-@@ -1729,7 +1735,7 @@ static int do_signal_stop(int signr)
+@@ -1703,9 +1687,6 @@ static int do_signal_stop(int signr)
+ 	struct signal_struct *sig = current->signal;
+ 	int stop_count;
+ 
+-	if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED))
+-		return 0;
+-
+ 	if (sig->group_stop_count > 0) {
+ 		/*
+ 		 * There is a group stop in progress.  We don't need to
+@@ -1713,12 +1694,15 @@ static int do_signal_stop(int signr)
+ 		 */
+ 		stop_count = --sig->group_stop_count;
+ 	} else {
++		struct task_struct *t;
++
++		if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) ||
++		    unlikely(sig->group_exit_task))
++			return 0;
+ 		/*
+ 		 * There is no group stop already in progress.
+ 		 * We must initiate one now.
+ 		 */
+-		struct task_struct *t;
+-
+ 		sig->group_exit_code = signr;
+ 
+ 		stop_count = 0;
+@@ -1729,7 +1713,7 @@ static int do_signal_stop(int signr)
  			 * so this check has no races.
  			 */
  			if (!t->exit_state &&
@@ -899554,6 +973601,63 @@
  				stop_count++;
  				signal_wake_up(t, 0);
  			}
+@@ -1746,47 +1730,6 @@ static int do_signal_stop(int signr)
+ 	return 1;
+ }
+ 
+-/*
+- * Do appropriate magic when group_stop_count > 0.
+- * We return nonzero if we stopped, after releasing the siglock.
+- * We return zero if we still hold the siglock and should look
+- * for another signal without checking group_stop_count again.
+- */
+-static int handle_group_stop(void)
+-{
+-	int stop_count;
+-
+-	if (current->signal->group_exit_task == current) {
+-		/*
+-		 * Group stop is so we can do a core dump,
+-		 * We are the initiating thread, so get on with it.
+-		 */
+-		current->signal->group_exit_task = NULL;
+-		return 0;
+-	}
+-
+-	if (current->signal->flags & SIGNAL_GROUP_EXIT)
+-		/*
+-		 * Group stop is so another thread can do a core dump,
+-		 * or else we are racing against a death signal.
+-		 * Just punt the stop so we can get the next signal.
+-		 */
+-		return 0;
+-
+-	/*
+-	 * There is a group stop in progress.  We stop
+-	 * without any associated signal being in our queue.
+-	 */
+-	stop_count = --current->signal->group_stop_count;
+-	if (stop_count == 0)
+-		current->signal->flags = SIGNAL_STOP_STOPPED;
+-	current->exit_code = current->signal->group_exit_code;
+-	set_current_state(TASK_STOPPED);
+-	spin_unlock_irq(&current->sighand->siglock);
+-	finish_stop(stop_count);
+-	return 1;
+-}
+-
+ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
+ 			  struct pt_regs *regs, void *cookie)
+ {
+@@ -1801,7 +1744,7 @@ relock:
+ 		struct k_sigaction *ka;
+ 
+ 		if (unlikely(current->signal->group_stop_count > 0) &&
+-		    handle_group_stop())
++		    do_signal_stop(0))
+ 			goto relock;
+ 
+ 		signr = dequeue_signal(current, mask, info);
 diff --git a/kernel/softirq.c b/kernel/softirq.c
 index bd89bc4..d7837d4 100644
 --- a/kernel/softirq.c
@@ -899800,8 +973904,48 @@
  
  	return ret;
  }
+diff --git a/kernel/sys.c b/kernel/sys.c
+index d1fe71e..53de35f 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -315,7 +315,7 @@ static void kernel_kexec(void)
+ #endif
+ }
+ 
+-void kernel_shutdown_prepare(enum system_states state)
++static void kernel_shutdown_prepare(enum system_states state)
+ {
+ 	blocking_notifier_call_chain(&reboot_notifier_list,
+ 		(state == SYSTEM_HALT)?SYS_HALT:SYS_POWER_OFF, NULL);
+@@ -1637,7 +1637,7 @@ asmlinkage long sys_umask(int mask)
+ 	mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
+ 	return mask;
+ }
+-    
++
+ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ 			  unsigned long arg4, unsigned long arg5)
+ {
+@@ -1742,6 +1742,17 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+ 			error = prctl_set_seccomp(arg2);
+ 			break;
+ 
++		case PR_CAPBSET_READ:
++			if (!cap_valid(arg2))
++				return -EINVAL;
++			return !!cap_raised(current->cap_bset, arg2);
++		case PR_CAPBSET_DROP:
++#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
++			return cap_prctl_drop(arg2);
++#else
++			return -EINVAL;
++#endif
++
+ 		default:
+ 			error = -EINVAL;
+ 			break;
 diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
-index 56cb009..beee5b3 100644
+index 56cb009..5b9b467 100644
 --- a/kernel/sys_ni.c
 +++ b/kernel/sys_ni.c
 @@ -131,6 +131,7 @@ cond_syscall(sys32_sysctl);
@@ -899812,8 +973956,21 @@
  
  /* mmu depending weak syscall entries */
  cond_syscall(sys_mprotect);
+@@ -153,7 +154,10 @@ cond_syscall(sys_ioprio_get);
+ 
+ /* New file descriptors */
+ cond_syscall(sys_signalfd);
+-cond_syscall(sys_timerfd);
+ cond_syscall(compat_sys_signalfd);
+-cond_syscall(compat_sys_timerfd);
++cond_syscall(sys_timerfd_create);
++cond_syscall(sys_timerfd_settime);
++cond_syscall(sys_timerfd_gettime);
++cond_syscall(compat_sys_timerfd_settime);
++cond_syscall(compat_sys_timerfd_gettime);
+ cond_syscall(sys_eventfd);
 diff --git a/kernel/sysctl.c b/kernel/sysctl.c
-index c68f68d..7cb1ac3 100644
+index c68f68d..5e2ad5b 100644
 --- a/kernel/sysctl.c
 +++ b/kernel/sysctl.c
 @@ -53,6 +53,7 @@
@@ -899824,7 +973981,7 @@
  #endif
  
  static int deprecated_sysctl_warning(struct __sysctl_args *args);
-@@ -80,7 +81,7 @@ extern int percpu_pagelist_fraction;
+@@ -80,11 +81,14 @@ extern int percpu_pagelist_fraction;
  extern int compat_log;
  extern int maps_protect;
  extern int sysctl_stat_interval;
@@ -899832,8 +973989,16 @@
 +extern int latencytop_enabled;
  
  /* Constants used for minimum and  maximum */
- #ifdef CONFIG_DETECT_SOFTLOCKUP
-@@ -156,8 +157,16 @@ static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *
+-#ifdef CONFIG_DETECT_SOFTLOCKUP
++#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM)
+ static int one = 1;
++#endif
++
++#ifdef CONFIG_DETECT_SOFTLOCKUP
+ static int sixty = 60;
+ #endif
+ 
+@@ -156,8 +160,16 @@ static int proc_dointvec_taint(struct ctl_table *table, int write, struct file *
  #endif
  
  static struct ctl_table root_table[];
@@ -899852,7 +974017,7 @@
  
  static struct ctl_table kern_table[];
  static struct ctl_table vm_table[];
-@@ -191,14 +200,6 @@ static struct ctl_table root_table[] = {
+@@ -191,14 +203,6 @@ static struct ctl_table root_table[] = {
  		.mode		= 0555,
  		.child		= vm_table,
  	},
@@ -899867,7 +974032,7 @@
  	{
  		.ctl_name	= CTL_FS,
  		.procname	= "fs",
-@@ -306,9 +307,43 @@ static struct ctl_table kern_table[] = {
+@@ -306,9 +310,43 @@ static struct ctl_table kern_table[] = {
  		.procname	= "sched_nr_migrate",
  		.data		= &sysctl_sched_nr_migrate,
  		.maxlen		= sizeof(unsigned int),
@@ -899881,16 +974046,16 @@
 +		.data		= &sysctl_sched_rt_period,
 +		.maxlen		= sizeof(unsigned int),
 +		.mode		= 0644,
-+		.proc_handler	= &proc_dointvec,
-+	},
+ 		.proc_handler	= &proc_dointvec,
+ 	},
 +	{
 +		.ctl_name	= CTL_UNNUMBERED,
 +		.procname	= "sched_rt_ratio",
 +		.data		= &sysctl_sched_rt_ratio,
 +		.maxlen		= sizeof(unsigned int),
 +		.mode		= 0644,
- 		.proc_handler	= &proc_dointvec,
- 	},
++		.proc_handler	= &proc_dointvec,
++	},
 +#if defined(CONFIG_FAIR_GROUP_SCHED) && defined(CONFIG_SMP)
 +	{
 +		.ctl_name       = CTL_UNNUMBERED,
@@ -899912,7 +974077,7 @@
  #endif
  	{
  		.ctl_name	= CTL_UNNUMBERED,
-@@ -354,16 +389,6 @@ static struct ctl_table kern_table[] = {
+@@ -354,16 +392,6 @@ static struct ctl_table kern_table[] = {
  		.mode		= 0644,
  		.proc_handler	= &proc_dointvec,
  	},
@@ -899929,23 +974094,30 @@
  	{
  		.ctl_name	= KERN_CORE_PATTERN,
  		.procname	= "core_pattern",
-@@ -382,6 +407,15 @@ static struct ctl_table kern_table[] = {
+@@ -382,15 +410,15 @@ static struct ctl_table kern_table[] = {
  		.proc_handler	= &proc_dointvec_taint,
  	},
  #endif
+-#ifdef CONFIG_SECURITY_CAPABILITIES
 +#ifdef CONFIG_LATENCYTOP
-+	{
+ 	{
+-		.procname	= "cap-bound",
+-		.data		= &cap_bset,
+-		.maxlen		= sizeof(kernel_cap_t),
+-		.mode		= 0600,
+-		.proc_handler	= &proc_dointvec_bset,
 +		.procname	= "latencytop",
 +		.data		= &latencytop_enabled,
 +		.maxlen		= sizeof(int),
 +		.mode		= 0644,
 +		.proc_handler	= &proc_dointvec,
-+	},
+ 	},
+-#endif /* def CONFIG_SECURITY_CAPABILITIES */
 +#endif
- #ifdef CONFIG_SECURITY_CAPABILITIES
+ #ifdef CONFIG_BLK_DEV_INITRD
  	{
- 		.procname	= "cap-bound",
-@@ -683,6 +717,14 @@ static struct ctl_table kern_table[] = {
+ 		.ctl_name	= KERN_REALROOTDEV,
+@@ -683,6 +711,14 @@ static struct ctl_table kern_table[] = {
  		.mode		= 0644,
  		.proc_handler	= &proc_dointvec,
  	},
@@ -899960,7 +974132,7 @@
  #endif
  #if defined(CONFIG_MMU)
  	{
-@@ -728,13 +770,40 @@ static struct ctl_table kern_table[] = {
+@@ -728,13 +764,40 @@ static struct ctl_table kern_table[] = {
  		.ctl_name	= CTL_UNNUMBERED,
  		.procname	= "softlockup_thresh",
  		.data		= &softlockup_thresh,
@@ -900003,14 +974175,34 @@
  #endif
  #ifdef CONFIG_COMPAT
  	{
-@@ -1300,12 +1369,27 @@ void sysctl_head_finish(struct ctl_table_header *head)
+@@ -1081,6 +1144,19 @@ static struct ctl_table vm_table[] = {
+ 		.extra1		= &zero,
+ 	},
+ #endif
++#ifdef CONFIG_HIGHMEM
++	{
++		.ctl_name	= CTL_UNNUMBERED,
++		.procname	= "highmem_is_dirtyable",
++		.data		= &vm_highmem_is_dirtyable,
++		.maxlen		= sizeof(vm_highmem_is_dirtyable),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec_minmax,
++		.strategy	= &sysctl_intvec,
++		.extra1		= &zero,
++		.extra2		= &one,
++	},
++#endif
+ /*
+  * NOTE: do not add new entries to this table unless you have read
+  * Documentation/sysctl/ctl_unnumbered.txt
+@@ -1300,12 +1376,27 @@ void sysctl_head_finish(struct ctl_table_header *head)
  	spin_unlock(&sysctl_lock);
  }
  
 -struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
 +static struct list_head *
 +lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces)
- {
++{
 +	struct list_head *header_list;
 +	header_list = &root->header_list;
 +	if (root->lookup)
@@ -900020,7 +974212,7 @@
 +
 +struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
 +					    struct ctl_table_header *prev)
-+{
+ {
 +	struct ctl_table_root *root;
 +	struct list_head *header_list;
  	struct ctl_table_header *head;
@@ -900032,7 +974224,7 @@
  		tmp = &prev->ctl_entry;
  		unuse_table(prev);
  		goto next;
-@@ -1319,14 +1403,38 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
+@@ -1319,14 +1410,38 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
  		spin_unlock(&sysctl_lock);
  		return head;
  	next:
@@ -900073,7 +974265,7 @@
  #ifdef CONFIG_SYSCTL_SYSCALL
  int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
  	       void __user *newval, size_t newlen)
-@@ -1483,18 +1591,21 @@ static __init int sysctl_init(void)
+@@ -1483,18 +1598,21 @@ static __init int sysctl_init(void)
  {
  	int err;
  	sysctl_set_parent(NULL, root_table);
@@ -900098,7 +974290,7 @@
   *
   * The members of the &struct ctl_table structure are used as follows:
   *
-@@ -1557,25 +1668,99 @@ core_initcall(sysctl_init);
+@@ -1557,25 +1675,99 @@ core_initcall(sysctl_init);
   * This routine returns %NULL on a failure to register, and a pointer
   * to the table header on success.
   */
@@ -900211,7 +974403,7 @@
  }
  
  /**
-@@ -1604,6 +1789,12 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
+@@ -1604,6 +1796,12 @@ struct ctl_table_header *register_sysctl_table(struct ctl_table * table)
  	return NULL;
  }
  
@@ -900224,7 +974416,47 @@
  void unregister_sysctl_table(struct ctl_table_header * table)
  {
  }
-@@ -2662,6 +2853,7 @@ EXPORT_SYMBOL(proc_dostring);
+@@ -1889,26 +2087,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
+ 	return 0;
+ }
+ 
+-#ifdef CONFIG_SECURITY_CAPABILITIES
+-/*
+- *	init may raise the set.
+- */
+-
+-int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
+-			void __user *buffer, size_t *lenp, loff_t *ppos)
+-{
+-	int op;
+-
+-	if (write && !capable(CAP_SYS_MODULE)) {
+-		return -EPERM;
+-	}
+-
+-	op = is_global_init(current) ? OP_SET : OP_AND;
+-	return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
+-				do_proc_dointvec_bset_conv,&op);
+-}
+-#endif /* def CONFIG_SECURITY_CAPABILITIES */
+-
+ /*
+  *	Taint values can only be increased
+  */
+@@ -2322,12 +2500,6 @@ int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
+ 	return -ENOSYS;
+ }
+ 
+-int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
+-			void __user *buffer, size_t *lenp, loff_t *ppos)
+-{
+-	return -ENOSYS;
+-}
+-
+ int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
+ 		    void __user *buffer, size_t *lenp, loff_t *ppos)
+ {
+@@ -2662,6 +2834,7 @@ EXPORT_SYMBOL(proc_dostring);
  EXPORT_SYMBOL(proc_doulongvec_minmax);
  EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);
  EXPORT_SYMBOL(register_sysctl_table);
@@ -900233,7 +974465,7 @@
  EXPORT_SYMBOL(sysctl_jiffies);
  EXPORT_SYMBOL(sysctl_ms_jiffies);
 diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
-index a68425a..c3206fa 100644
+index a68425a..006365b 100644
 --- a/kernel/sysctl_check.c
 +++ b/kernel/sysctl_check.c
 @@ -1,6 +1,5 @@
@@ -900243,7 +974475,18 @@
  #include "../fs/xfs/linux-2.6/xfs_sysctl.h"
  #include <linux/sunrpc/debug.h>
  #include <linux/string.h>
-@@ -1343,7 +1342,8 @@ static void sysctl_repair_table(struct ctl_table *table)
+@@ -38,10 +37,6 @@ static struct trans_ctl_table trans_kern_table[] = {
+ 	{ KERN_NODENAME,		"hostname" },
+ 	{ KERN_DOMAINNAME,		"domainname" },
+ 
+-#ifdef CONFIG_SECURITY_CAPABILITIES
+-	{ KERN_CAP_BSET,		"cap-bound" },
+-#endif /* def CONFIG_SECURITY_CAPABILITIES */
+-
+ 	{ KERN_PANIC,			"panic" },
+ 	{ KERN_REALROOTDEV,		"real-root-dev" },
+ 
+@@ -1343,7 +1338,8 @@ static void sysctl_repair_table(struct ctl_table *table)
  	}
  }
  
@@ -900253,7 +974496,7 @@
  {
  	struct ctl_table_header *head;
  	struct ctl_table *ref, *test;
-@@ -1351,8 +1351,8 @@ static struct ctl_table *sysctl_check_lookup(struct ctl_table *table)
+@@ -1351,8 +1347,8 @@ static struct ctl_table *sysctl_check_lookup(struct ctl_table *table)
  
  	depth = sysctl_depth(table);
  
@@ -900264,7 +974507,7 @@
  		cur_depth = depth;
  		ref = head->ctl_table;
  repeat:
-@@ -1397,13 +1397,14 @@ static void set_fail(const char **fail, struct ctl_table *table, const char *str
+@@ -1397,13 +1393,14 @@ static void set_fail(const char **fail, struct ctl_table *table, const char *str
  	*fail = str;
  }
  
@@ -900281,7 +974524,7 @@
  	if (ref) {
  		int match = 0;
  		if ((!table->procname && !ref->procname) ||
-@@ -1428,11 +1429,12 @@ static int sysctl_check_dir(struct ctl_table *table)
+@@ -1428,11 +1425,12 @@ static int sysctl_check_dir(struct ctl_table *table)
  	return error;
  }
  
@@ -900296,7 +974539,7 @@
  	if (ref && (ref != table))
  		set_fail(fail, table, "Sysctl already exists");
  }
-@@ -1456,7 +1458,7 @@ static void sysctl_check_bin_path(struct ctl_table *table, const char **fail)
+@@ -1456,7 +1454,7 @@ static void sysctl_check_bin_path(struct ctl_table *table, const char **fail)
  	}
  }
  
@@ -900305,7 +974548,7 @@
  {
  	int error = 0;
  	for (; table->ctl_name || table->procname; table++) {
-@@ -1486,7 +1488,7 @@ int sysctl_check_table(struct ctl_table *table)
+@@ -1486,7 +1484,7 @@ int sysctl_check_table(struct ctl_table *table)
  				set_fail(&fail, table, "Directory with extra1");
  			if (table->extra2)
  				set_fail(&fail, table, "Directory with extra2");
@@ -900314,7 +974557,17 @@
  				set_fail(&fail, table, "Inconsistent directory names");
  		} else {
  			if ((table->strategy == sysctl_data) ||
-@@ -1535,7 +1537,7 @@ int sysctl_check_table(struct ctl_table *table)
+@@ -1496,9 +1494,6 @@ int sysctl_check_table(struct ctl_table *table)
+ 			    (table->strategy == sysctl_ms_jiffies) ||
+ 			    (table->proc_handler == proc_dostring) ||
+ 			    (table->proc_handler == proc_dointvec) ||
+-#ifdef CONFIG_SECURITY_CAPABILITIES
+-			    (table->proc_handler == proc_dointvec_bset) ||
+-#endif /* def CONFIG_SECURITY_CAPABILITIES */
+ 			    (table->proc_handler == proc_dointvec_minmax) ||
+ 			    (table->proc_handler == proc_dointvec_jiffies) ||
+ 			    (table->proc_handler == proc_dointvec_userhz_jiffies) ||
+@@ -1535,7 +1530,7 @@ int sysctl_check_table(struct ctl_table *table)
  			if (!table->procname && table->proc_handler)
  				set_fail(&fail, table, "proc_handler without procname");
  #endif
@@ -900323,7 +974576,7 @@
  		}
  		sysctl_check_bin_path(table, &fail);
  		if (fail) {
-@@ -1543,7 +1545,7 @@ int sysctl_check_table(struct ctl_table *table)
+@@ -1543,7 +1538,7 @@ int sysctl_check_table(struct ctl_table *table)
  			error = -EINVAL;
  		}
  		if (table->child)
@@ -901724,7 +975977,7 @@
  
  		case CPU_ONLINE:
 diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
-index a601093..0d8a5a4 100644
+index a601093..0d385be 100644
 --- a/lib/Kconfig.debug
 +++ b/lib/Kconfig.debug
 @@ -79,6 +79,38 @@ config HEADERS_CHECK
@@ -901733,7 +975986,7 @@
  
 +config DEBUG_SECTION_MISMATCH
 +	bool "Enable full Section mismatch analysis"
-+	default n
++	depends on UNDEFINED
 +	help
 +	  The section mismatch analysis checks if there are illegal
 +	  references from one section to another section.
@@ -901742,19 +975995,19 @@
 +	  most likely result in an oops.
 +	  In the code functions and variables are annotated with
 +	  __init, __devinit etc. (see full list in include/linux/init.h)
-+	  which result in the code/data being placed in specific sections.
-+	  The section mismatch anaylsis are always done after a full
-+	  kernel build but enabling this options will in addition
++	  which results in the code/data being placed in specific sections.
++	  The section mismatch analysis is always done after a full
++	  kernel build but enabling this option will in addition
 +	  do the following:
 +	  - Add the option -fno-inline-functions-called-once to gcc
 +	    When inlining a function annotated __init in a non-init
-+	    function we would loose the section information and thus
++	    function we would lose the section information and thus
 +	    the analysis would not catch the illegal reference.
-+	    This options tell gcc to inline less but will also
++	    This option tells gcc to inline less but will also
 +	    result in a larger kernel.
 +	  - Run the section mismatch analysis for each module/built-in.o
 +	    When we run the section mismatch analysis on vmlinux.o we
-+	    looses valueable information about where the mismatch was
++	    lose valueble information about where the mismatch was
 +	    introduced.
 +	    Running the analysis for each module/built-in.o file
 +	    will tell where the mismatch happens much closer to the
@@ -901845,7 +976098,7 @@
 +
  source "samples/Kconfig"
 diff --git a/lib/Makefile b/lib/Makefile
-index b6793ed..543f250 100644
+index b6793ed..a18062e 100644
 --- a/lib/Makefile
 +++ b/lib/Makefile
 @@ -6,7 +6,7 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
@@ -901857,7 +976110,7 @@
  
  lib-$(CONFIG_MMU) += ioremap.o
  lib-$(CONFIG_SMP) += cpumask.o
-@@ -61,6 +61,7 @@ obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+@@ -61,9 +61,11 @@ obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
  obj-$(CONFIG_TEXTSEARCH_BM) += ts_bm.o
  obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
  obj-$(CONFIG_SMP) += percpu_counter.o
@@ -901865,6 +976118,23 @@
  obj-$(CONFIG_AUDIT_GENERIC) += audit.o
  
  obj-$(CONFIG_SWIOTLB) += swiotlb.o
++obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o
+ obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
+ 
+ lib-$(CONFIG_GENERIC_BUG) += bug.o
+diff --git a/lib/crc32.c b/lib/crc32.c
+index d2c2f25..49d1c9e 100644
+--- a/lib/crc32.c
++++ b/lib/crc32.c
+@@ -348,7 +348,7 @@ EXPORT_SYMBOL(crc32_be);
+  * but again the multiple of the polynomial to subtract depends only on
+  * the high bits, the high 8 bits in this case.  
+  *
+- * The multile we need in that case is the low 32 bits of a 40-bit
++ * The multiple we need in that case is the low 32 bits of a 40-bit
+  * value whose high 8 bits are given, and which is a multiple of the
+  * generator polynomial.  This is simply the CRC-32 of the given
+  * one-byte message.
 diff --git a/lib/find_next_bit.c b/lib/find_next_bit.c
 index bda0d71..78ccd73 100644
 --- a/lib/find_next_bit.c
@@ -901917,6 +976187,92 @@
 +}
 +EXPORT_SYMBOL(generic_find_next_le_bit);
  #endif /* __BIG_ENDIAN */
+diff --git a/lib/iommu-helper.c b/lib/iommu-helper.c
+new file mode 100644
+index 0000000..495575a
+--- /dev/null
++++ b/lib/iommu-helper.c
+@@ -0,0 +1,80 @@
++/*
++ * IOMMU helper functions for the free area management
++ */
++
++#include <linux/module.h>
++#include <linux/bitops.h>
++
++static unsigned long find_next_zero_area(unsigned long *map,
++					 unsigned long size,
++					 unsigned long start,
++					 unsigned int nr,
++					 unsigned long align_mask)
++{
++	unsigned long index, end, i;
++again:
++	index = find_next_zero_bit(map, size, start);
++
++	/* Align allocation */
++	index = (index + align_mask) & ~align_mask;
++
++	end = index + nr;
++	if (end >= size)
++		return -1;
++	for (i = index; i < end; i++) {
++		if (test_bit(i, map)) {
++			start = i+1;
++			goto again;
++		}
++	}
++	return index;
++}
++
++static inline void set_bit_area(unsigned long *map, unsigned long i,
++				int len)
++{
++	unsigned long end = i + len;
++	while (i < end) {
++		__set_bit(i, map);
++		i++;
++	}
++}
++
++static inline int is_span_boundary(unsigned int index, unsigned int nr,
++				   unsigned long shift,
++				   unsigned long boundary_size)
++{
++	shift = (shift + index) & (boundary_size - 1);
++	return shift + nr > boundary_size;
++}
++
++unsigned long iommu_area_alloc(unsigned long *map, unsigned long size,
++			       unsigned long start, unsigned int nr,
++			       unsigned long shift, unsigned long boundary_size,
++			       unsigned long align_mask)
++{
++	unsigned long index;
++again:
++	index = find_next_zero_area(map, size, start, nr, align_mask);
++	if (index != -1) {
++		if (is_span_boundary(index, nr, shift, boundary_size)) {
++			/* we could do more effectively */
++			start = index + 1;
++			goto again;
++		}
++		set_bit_area(map, index, nr);
++	}
++	return index;
++}
++EXPORT_SYMBOL(iommu_area_alloc);
++
++void iommu_area_free(unsigned long *map, unsigned long start, unsigned int nr)
++{
++	unsigned long end = start + nr;
++
++	while (start < end) {
++		__clear_bit(start, map);
++		start++;
++	}
++}
++EXPORT_SYMBOL(iommu_area_free);
 diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
 index f73e2f8..812dbf0 100644
 --- a/lib/kernel_lock.c
@@ -902059,7 +976415,7 @@
  EXPORT_SYMBOL(unlock_kernel);
  
 diff --git a/lib/kobject.c b/lib/kobject.c
-index 3590f02..1d63ead 100644
+index 3590f02..d784dae 100644
 --- a/lib/kobject.c
 +++ b/lib/kobject.c
 @@ -18,58 +18,57 @@
@@ -902790,7 +977146,7 @@
 + * @name: the name for the kset
 + * @parent: the parent kobject of this kobject, if any.
 + *
-+ * This function creates a kset structure dynamically and registers it
++ * This function creates a kobject structure dynamically and registers it
 + * with sysfs.  When you are finished with this structure, call
 + * kobject_put() and the structure will be dynamically freed when
 + * it is no longer being used.
@@ -903275,6 +977631,43 @@
 +}
 +EXPORT_SYMBOL_GPL(pcounter_free);
 +
+diff --git a/lib/radix-tree.c b/lib/radix-tree.c
+index 48c250f..65f0e75 100644
+--- a/lib/radix-tree.c
++++ b/lib/radix-tree.c
+@@ -95,14 +95,17 @@ static inline gfp_t root_gfp_mask(struct radix_tree_root *root)
+ static struct radix_tree_node *
+ radix_tree_node_alloc(struct radix_tree_root *root)
+ {
+-	struct radix_tree_node *ret;
++	struct radix_tree_node *ret = NULL;
+ 	gfp_t gfp_mask = root_gfp_mask(root);
+ 
+-	ret = kmem_cache_alloc(radix_tree_node_cachep,
+-				set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
+-	if (ret == NULL && !(gfp_mask & __GFP_WAIT)) {
++	if (!(gfp_mask & __GFP_WAIT)) {
+ 		struct radix_tree_preload *rtp;
+ 
++		/*
++		 * Provided the caller has preloaded here, we will always
++		 * succeed in getting a node here (and never reach
++		 * kmem_cache_alloc)
++		 */
+ 		rtp = &__get_cpu_var(radix_tree_preloads);
+ 		if (rtp->nr) {
+ 			ret = rtp->nodes[rtp->nr - 1];
+@@ -110,6 +113,10 @@ radix_tree_node_alloc(struct radix_tree_root *root)
+ 			rtp->nr--;
+ 		}
+ 	}
++	if (ret == NULL)
++		ret = kmem_cache_alloc(radix_tree_node_cachep,
++				set_migrateflags(gfp_mask, __GFP_RECLAIMABLE));
++
+ 	BUG_ON(radix_tree_is_indirect_ptr(ret));
+ 	return ret;
+ }
 diff --git a/lib/rwsem.c b/lib/rwsem.c
 index 7d02700..3e3365e 100644
 --- a/lib/rwsem.c
@@ -903442,197 +977835,841 @@
 +		return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
 +}
 +
-+static void sg_kfree(struct scatterlist *sg, unsigned int nents)
++static void sg_kfree(struct scatterlist *sg, unsigned int nents)
++{
++	if (nents == SG_MAX_SINGLE_ALLOC)
++		free_page((unsigned long) sg);
++	else
++		kfree(sg);
++}
++
++/**
++ * __sg_free_table - Free a previously mapped sg table
++ * @table:	The sg table header to use
++ * @max_ents:	The maximum number of entries per single scatterlist
++ * @free_fn:	Free function
++ *
++ *  Description:
++ *    Free an sg table previously allocated and setup with
++ *    __sg_alloc_table().  The @max_ents value must be identical to
++ *    that previously used with __sg_alloc_table().
++ *
++ **/
++void __sg_free_table(struct sg_table *table, unsigned int max_ents,
++		     sg_free_fn *free_fn)
++{
++	struct scatterlist *sgl, *next;
++
++	if (unlikely(!table->sgl))
++		return;
++
++	sgl = table->sgl;
++	while (table->orig_nents) {
++		unsigned int alloc_size = table->orig_nents;
++		unsigned int sg_size;
++
++		/*
++		 * If we have more than max_ents segments left,
++		 * then assign 'next' to the sg table after the current one.
++		 * sg_size is then one less than alloc size, since the last
++		 * element is the chain pointer.
++		 */
++		if (alloc_size > max_ents) {
++			next = sg_chain_ptr(&sgl[max_ents - 1]);
++			alloc_size = max_ents;
++			sg_size = alloc_size - 1;
++		} else {
++			sg_size = alloc_size;
++			next = NULL;
++		}
++
++		table->orig_nents -= sg_size;
++		free_fn(sgl, alloc_size);
++		sgl = next;
++	}
++
++	table->sgl = NULL;
++}
++EXPORT_SYMBOL(__sg_free_table);
++
++/**
++ * sg_free_table - Free a previously allocated sg table
++ * @table:	The mapped sg table header
++ *
++ **/
++void sg_free_table(struct sg_table *table)
++{
++	__sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree);
++}
++EXPORT_SYMBOL(sg_free_table);
++
++/**
++ * __sg_alloc_table - Allocate and initialize an sg table with given allocator
++ * @table:	The sg table header to use
++ * @nents:	Number of entries in sg list
++ * @max_ents:	The maximum number of entries the allocator returns per call
++ * @gfp_mask:	GFP allocation mask
++ * @alloc_fn:	Allocator to use
++ *
++ * Description:
++ *   This function returns a @table @nents long. The allocator is
++ *   defined to return scatterlist chunks of maximum size @max_ents.
++ *   Thus if @nents is bigger than @max_ents, the scatterlists will be
++ *   chained in units of @max_ents.
++ *
++ * Notes:
++ *   If this function returns non-0 (eg failure), the caller must call
++ *   __sg_free_table() to cleanup any leftover allocations.
++ *
++ **/
++int __sg_alloc_table(struct sg_table *table, unsigned int nents,
++		     unsigned int max_ents, gfp_t gfp_mask,
++		     sg_alloc_fn *alloc_fn)
++{
++	struct scatterlist *sg, *prv;
++	unsigned int left;
++
++#ifndef ARCH_HAS_SG_CHAIN
++	BUG_ON(nents > max_ents);
++#endif
++
++	memset(table, 0, sizeof(*table));
++
++	left = nents;
++	prv = NULL;
++	do {
++		unsigned int sg_size, alloc_size = left;
++
++		if (alloc_size > max_ents) {
++			alloc_size = max_ents;
++			sg_size = alloc_size - 1;
++		} else
++			sg_size = alloc_size;
++
++		left -= sg_size;
++
++		sg = alloc_fn(alloc_size, gfp_mask);
++		if (unlikely(!sg))
++			return -ENOMEM;
++
++		sg_init_table(sg, alloc_size);
++		table->nents = table->orig_nents += sg_size;
++
++		/*
++		 * If this is the first mapping, assign the sg table header.
++		 * If this is not the first mapping, chain previous part.
++		 */
++		if (prv)
++			sg_chain(prv, max_ents, sg);
++		else
++			table->sgl = sg;
++
++		/*
++		 * If no more entries after this one, mark the end
++		 */
++		if (!left)
++			sg_mark_end(&sg[sg_size - 1]);
++
++		/*
++		 * only really needed for mempool backed sg allocations (like
++		 * SCSI), a possible improvement here would be to pass the
++		 * table pointer into the allocator and let that clear these
++		 * flags
++		 */
++		gfp_mask &= ~__GFP_WAIT;
++		gfp_mask |= __GFP_HIGH;
++		prv = sg;
++	} while (left);
++
++	return 0;
++}
++EXPORT_SYMBOL(__sg_alloc_table);
++
++/**
++ * sg_alloc_table - Allocate and initialize an sg table
++ * @table:	The sg table header to use
++ * @nents:	Number of entries in sg list
++ * @gfp_mask:	GFP allocation mask
++ *
++ *  Description:
++ *    Allocate and initialize an sg table. If @nents@ is larger than
++ *    SG_MAX_SINGLE_ALLOC a chained sg table will be setup.
++ *
++ **/
++int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
++{
++	int ret;
++
++	ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
++			       gfp_mask, sg_kmalloc);
++	if (unlikely(ret))
++		__sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree);
++
++	return ret;
++}
++EXPORT_SYMBOL(sg_alloc_table);
+diff --git a/lib/swiotlb.c b/lib/swiotlb.c
+index 1a8050a..4bb5a11 100644
+--- a/lib/swiotlb.c
++++ b/lib/swiotlb.c
+@@ -282,6 +282,15 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+ 	return (addr & ~mask) != 0;
+ }
+ 
++static inline unsigned int is_span_boundary(unsigned int index,
++					    unsigned int nslots,
++					    unsigned long offset_slots,
++					    unsigned long max_slots)
++{
++	unsigned long offset = (offset_slots + index) & (max_slots - 1);
++	return offset + nslots > max_slots;
++}
++
+ /*
+  * Allocates bounce buffer and returns its kernel virtual address.
+  */
+@@ -292,6 +301,16 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+ 	char *dma_addr;
+ 	unsigned int nslots, stride, index, wrap;
+ 	int i;
++	unsigned long start_dma_addr;
++	unsigned long mask;
++	unsigned long offset_slots;
++	unsigned long max_slots;
++
++	mask = dma_get_seg_boundary(hwdev);
++	start_dma_addr = virt_to_bus(io_tlb_start) & mask;
++
++	offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
++	max_slots = ALIGN(mask + 1, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
+ 
+ 	/*
+ 	 * For mappings greater than a page, we limit the stride (and
+@@ -311,10 +330,17 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+ 	 */
+ 	spin_lock_irqsave(&io_tlb_lock, flags);
+ 	{
+-		wrap = index = ALIGN(io_tlb_index, stride);
+-
++		index = ALIGN(io_tlb_index, stride);
+ 		if (index >= io_tlb_nslabs)
+-			wrap = index = 0;
++			index = 0;
++
++		while (is_span_boundary(index, nslots, offset_slots,
++					max_slots)) {
++			index += stride;
++			if (index >= io_tlb_nslabs)
++				index = 0;
++		}
++		wrap = index;
+ 
+ 		do {
+ 			/*
+@@ -341,9 +367,12 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
+ 
+ 				goto found;
+ 			}
+-			index += stride;
+-			if (index >= io_tlb_nslabs)
+-				index = 0;
++			do {
++				index += stride;
++				if (index >= io_tlb_nslabs)
++					index = 0;
++			} while (is_span_boundary(index, nslots, offset_slots,
++						  max_slots));
+ 		} while (index != wrap);
+ 
+ 		spin_unlock_irqrestore(&io_tlb_lock, flags);
+diff --git a/lib/zlib_deflate/defutil.h b/lib/zlib_deflate/defutil.h
+index d9feaf6..6b15a90 100644
+--- a/lib/zlib_deflate/defutil.h
++++ b/lib/zlib_deflate/defutil.h
+@@ -164,7 +164,7 @@ typedef struct deflate_state {
+     int nice_match; /* Stop searching when current match exceeds this */
+ 
+                 /* used by trees.c: */
+-    /* Didn't use ct_data typedef below to supress compiler warning */
++    /* Didn't use ct_data typedef below to suppress compiler warning */
+     struct ct_data_s dyn_ltree[HEAP_SIZE];   /* literal and length tree */
+     struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+     struct ct_data_s bl_tree[2*BL_CODES+1];  /* Huffman tree for bit lengths */
+diff --git a/mm/Kconfig b/mm/Kconfig
+index 9ef9741..0016ebd 100644
+--- a/mm/Kconfig
++++ b/mm/Kconfig
+@@ -187,7 +187,7 @@ config BOUNCE
+ config NR_QUICK
+ 	int
+ 	depends on QUICKLIST
+-	default "2" if (SUPERH && !SUPERH64)
++	default "2" if SUPERH
+ 	default "1"
+ 
+ config VIRT_TO_BUS
+diff --git a/mm/Makefile b/mm/Makefile
+index 5c0b0ea..4af5dff 100644
+--- a/mm/Makefile
++++ b/mm/Makefile
+@@ -13,8 +13,10 @@ obj-y			:= bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
+ 			   prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \
+ 			   page_isolation.o $(mmu-y)
+ 
++obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
+ obj-$(CONFIG_BOUNCE)	+= bounce.o
+ obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
++obj-$(CONFIG_HAS_DMA)	+= dmapool.o
+ obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
+ obj-$(CONFIG_NUMA) 	+= mempolicy.o
+ obj-$(CONFIG_SPARSEMEM)	+= sparse.o
+diff --git a/mm/dmapool.c b/mm/dmapool.c
+new file mode 100644
+index 0000000..34aaac4
+--- /dev/null
++++ b/mm/dmapool.c
+@@ -0,0 +1,500 @@
++/*
++ * DMA Pool allocator
++ *
++ * Copyright 2001 David Brownell
++ * Copyright 2007 Intel Corporation
++ *   Author: Matthew Wilcox <willy at linux.intel.com>
++ *
++ * This software may be redistributed and/or modified under the terms of
++ * the GNU General Public License ("GPL") version 2 as published by the
++ * Free Software Foundation.
++ *
++ * This allocator returns small blocks of a given size which are DMA-able by
++ * the given device.  It uses the dma_alloc_coherent page allocator to get
++ * new pages, then splits them up into blocks of the required size.
++ * Many older drivers still have their own code to do this.
++ *
++ * The current design of this allocator is fairly simple.  The pool is
++ * represented by the 'struct dma_pool' which keeps a doubly-linked list of
++ * allocated pages.  Each page in the page_list is split into blocks of at
++ * least 'size' bytes.  Free blocks are tracked in an unsorted singly-linked
++ * list of free blocks within the page.  Used blocks aren't tracked, but we
++ * keep a count of how many are currently allocated from each page.
++ */
++
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/mutex.h>
++#include <linux/poison.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/types.h>
++#include <linux/wait.h>
++
++struct dma_pool {		/* the pool */
++	struct list_head page_list;
++	spinlock_t lock;
++	size_t size;
++	struct device *dev;
++	size_t allocation;
++	size_t boundary;
++	char name[32];
++	wait_queue_head_t waitq;
++	struct list_head pools;
++};
++
++struct dma_page {		/* cacheable header for 'allocation' bytes */
++	struct list_head page_list;
++	void *vaddr;
++	dma_addr_t dma;
++	unsigned int in_use;
++	unsigned int offset;
++};
++
++#define	POOL_TIMEOUT_JIFFIES	((100 /* msec */ * HZ) / 1000)
++
++static DEFINE_MUTEX(pools_lock);
++
++static ssize_t
++show_pools(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	unsigned temp;
++	unsigned size;
++	char *next;
++	struct dma_page *page;
++	struct dma_pool *pool;
++
++	next = buf;
++	size = PAGE_SIZE;
++
++	temp = scnprintf(next, size, "poolinfo - 0.1\n");
++	size -= temp;
++	next += temp;
++
++	mutex_lock(&pools_lock);
++	list_for_each_entry(pool, &dev->dma_pools, pools) {
++		unsigned pages = 0;
++		unsigned blocks = 0;
++
++		list_for_each_entry(page, &pool->page_list, page_list) {
++			pages++;
++			blocks += page->in_use;
++		}
++
++		/* per-pool info, no real statistics yet */
++		temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n",
++				 pool->name, blocks,
++				 pages * (pool->allocation / pool->size),
++				 pool->size, pages);
++		size -= temp;
++		next += temp;
++	}
++	mutex_unlock(&pools_lock);
++
++	return PAGE_SIZE - size;
++}
++
++static DEVICE_ATTR(pools, S_IRUGO, show_pools, NULL);
++
++/**
++ * dma_pool_create - Creates a pool of consistent memory blocks, for dma.
++ * @name: name of pool, for diagnostics
++ * @dev: device that will be doing the DMA
++ * @size: size of the blocks in this pool.
++ * @align: alignment requirement for blocks; must be a power of two
++ * @boundary: returned blocks won't cross this power of two boundary
++ * Context: !in_interrupt()
++ *
++ * Returns a dma allocation pool with the requested characteristics, or
++ * null if one can't be created.  Given one of these pools, dma_pool_alloc()
++ * may be used to allocate memory.  Such memory will all have "consistent"
++ * DMA mappings, accessible by the device and its driver without using
++ * cache flushing primitives.  The actual size of blocks allocated may be
++ * larger than requested because of alignment.
++ *
++ * If @boundary is nonzero, objects returned from dma_pool_alloc() won't
++ * cross that size boundary.  This is useful for devices which have
++ * addressing restrictions on individual DMA transfers, such as not crossing
++ * boundaries of 4KBytes.
++ */
++struct dma_pool *dma_pool_create(const char *name, struct device *dev,
++				 size_t size, size_t align, size_t boundary)
++{
++	struct dma_pool *retval;
++	size_t allocation;
++
++	if (align == 0) {
++		align = 1;
++	} else if (align & (align - 1)) {
++		return NULL;
++	}
++
++	if (size == 0) {
++		return NULL;
++	} else if (size < 4) {
++		size = 4;
++	}
++
++	if ((size % align) != 0)
++		size = ALIGN(size, align);
++
++	allocation = max_t(size_t, size, PAGE_SIZE);
++
++	if (!boundary) {
++		boundary = allocation;
++	} else if ((boundary < size) || (boundary & (boundary - 1))) {
++		return NULL;
++	}
++
++	retval = kmalloc_node(sizeof(*retval), GFP_KERNEL, dev_to_node(dev));
++	if (!retval)
++		return retval;
++
++	strlcpy(retval->name, name, sizeof(retval->name));
++
++	retval->dev = dev;
++
++	INIT_LIST_HEAD(&retval->page_list);
++	spin_lock_init(&retval->lock);
++	retval->size = size;
++	retval->boundary = boundary;
++	retval->allocation = allocation;
++	init_waitqueue_head(&retval->waitq);
++
++	if (dev) {
++		int ret;
++
++		mutex_lock(&pools_lock);
++		if (list_empty(&dev->dma_pools))
++			ret = device_create_file(dev, &dev_attr_pools);
++		else
++			ret = 0;
++		/* note:  not currently insisting "name" be unique */
++		if (!ret)
++			list_add(&retval->pools, &dev->dma_pools);
++		else {
++			kfree(retval);
++			retval = NULL;
++		}
++		mutex_unlock(&pools_lock);
++	} else
++		INIT_LIST_HEAD(&retval->pools);
++
++	return retval;
++}
++EXPORT_SYMBOL(dma_pool_create);
++
++static void pool_initialise_page(struct dma_pool *pool, struct dma_page *page)
++{
++	unsigned int offset = 0;
++	unsigned int next_boundary = pool->boundary;
++
++	do {
++		unsigned int next = offset + pool->size;
++		if (unlikely((next + pool->size) >= next_boundary)) {
++			next = next_boundary;
++			next_boundary += pool->boundary;
++		}
++		*(int *)(page->vaddr + offset) = next;
++		offset = next;
++	} while (offset < pool->allocation);
++}
++
++static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags)
++{
++	struct dma_page *page;
++
++	page = kmalloc(sizeof(*page), mem_flags);
++	if (!page)
++		return NULL;
++	page->vaddr = dma_alloc_coherent(pool->dev, pool->allocation,
++					 &page->dma, mem_flags);
++	if (page->vaddr) {
++#ifdef	CONFIG_DEBUG_SLAB
++		memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
++#endif
++		pool_initialise_page(pool, page);
++		list_add(&page->page_list, &pool->page_list);
++		page->in_use = 0;
++		page->offset = 0;
++	} else {
++		kfree(page);
++		page = NULL;
++	}
++	return page;
++}
++
++static inline int is_page_busy(struct dma_page *page)
++{
++	return page->in_use != 0;
++}
++
++static void pool_free_page(struct dma_pool *pool, struct dma_page *page)
 +{
-+	if (nents == SG_MAX_SINGLE_ALLOC)
-+		free_page((unsigned long) sg);
-+	else
-+		kfree(sg);
++	dma_addr_t dma = page->dma;
++
++#ifdef	CONFIG_DEBUG_SLAB
++	memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
++#endif
++	dma_free_coherent(pool->dev, pool->allocation, page->vaddr, dma);
++	list_del(&page->page_list);
++	kfree(page);
 +}
 +
 +/**
-+ * __sg_free_table - Free a previously mapped sg table
-+ * @table:	The sg table header to use
-+ * @max_ents:	The maximum number of entries per single scatterlist
-+ * @free_fn:	Free function
++ * dma_pool_destroy - destroys a pool of dma memory blocks.
++ * @pool: dma pool that will be destroyed
++ * Context: !in_interrupt()
 + *
-+ *  Description:
-+ *    Free an sg table previously allocated and setup with
-+ *    __sg_alloc_table().  The @max_ents value must be identical to
-+ *    that previously used with __sg_alloc_table().
++ * Caller guarantees that no more memory from the pool is in use,
++ * and that nothing will try to use the pool after this call.
++ */
++void dma_pool_destroy(struct dma_pool *pool)
++{
++	mutex_lock(&pools_lock);
++	list_del(&pool->pools);
++	if (pool->dev && list_empty(&pool->dev->dma_pools))
++		device_remove_file(pool->dev, &dev_attr_pools);
++	mutex_unlock(&pools_lock);
++
++	while (!list_empty(&pool->page_list)) {
++		struct dma_page *page;
++		page = list_entry(pool->page_list.next,
++				  struct dma_page, page_list);
++		if (is_page_busy(page)) {
++			if (pool->dev)
++				dev_err(pool->dev,
++					"dma_pool_destroy %s, %p busy\n",
++					pool->name, page->vaddr);
++			else
++				printk(KERN_ERR
++				       "dma_pool_destroy %s, %p busy\n",
++				       pool->name, page->vaddr);
++			/* leak the still-in-use consistent memory */
++			list_del(&page->page_list);
++			kfree(page);
++		} else
++			pool_free_page(pool, page);
++	}
++
++	kfree(pool);
++}
++EXPORT_SYMBOL(dma_pool_destroy);
++
++/**
++ * dma_pool_alloc - get a block of consistent memory
++ * @pool: dma pool that will produce the block
++ * @mem_flags: GFP_* bitmask
++ * @handle: pointer to dma address of block
 + *
-+ **/
-+void __sg_free_table(struct sg_table *table, unsigned int max_ents,
-+		     sg_free_fn *free_fn)
++ * This returns the kernel virtual address of a currently unused block,
++ * and reports its dma address through the handle.
++ * If such a memory block can't be allocated, %NULL is returned.
++ */
++void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
++		     dma_addr_t *handle)
 +{
-+	struct scatterlist *sgl, *next;
++	unsigned long flags;
++	struct dma_page *page;
++	size_t offset;
++	void *retval;
++
++	spin_lock_irqsave(&pool->lock, flags);
++ restart:
++	list_for_each_entry(page, &pool->page_list, page_list) {
++		if (page->offset < pool->allocation)
++			goto ready;
++	}
++	page = pool_alloc_page(pool, GFP_ATOMIC);
++	if (!page) {
++		if (mem_flags & __GFP_WAIT) {
++			DECLARE_WAITQUEUE(wait, current);
 +
-+	if (unlikely(!table->sgl))
-+		return;
++			__set_current_state(TASK_INTERRUPTIBLE);
++			__add_wait_queue(&pool->waitq, &wait);
++			spin_unlock_irqrestore(&pool->lock, flags);
 +
-+	sgl = table->sgl;
-+	while (table->orig_nents) {
-+		unsigned int alloc_size = table->orig_nents;
-+		unsigned int sg_size;
++			schedule_timeout(POOL_TIMEOUT_JIFFIES);
 +
-+		/*
-+		 * If we have more than max_ents segments left,
-+		 * then assign 'next' to the sg table after the current one.
-+		 * sg_size is then one less than alloc size, since the last
-+		 * element is the chain pointer.
-+		 */
-+		if (alloc_size > max_ents) {
-+			next = sg_chain_ptr(&sgl[max_ents - 1]);
-+			alloc_size = max_ents;
-+			sg_size = alloc_size - 1;
-+		} else {
-+			sg_size = alloc_size;
-+			next = NULL;
++			spin_lock_irqsave(&pool->lock, flags);
++			__remove_wait_queue(&pool->waitq, &wait);
++			goto restart;
 +		}
-+
-+		table->orig_nents -= sg_size;
-+		free_fn(sgl, alloc_size);
-+		sgl = next;
++		retval = NULL;
++		goto done;
 +	}
 +
-+	table->sgl = NULL;
++ ready:
++	page->in_use++;
++	offset = page->offset;
++	page->offset = *(int *)(page->vaddr + offset);
++	retval = offset + page->vaddr;
++	*handle = offset + page->dma;
++#ifdef	CONFIG_DEBUG_SLAB
++	memset(retval, POOL_POISON_ALLOCATED, pool->size);
++#endif
++ done:
++	spin_unlock_irqrestore(&pool->lock, flags);
++	return retval;
 +}
-+EXPORT_SYMBOL(__sg_free_table);
++EXPORT_SYMBOL(dma_pool_alloc);
 +
-+/**
-+ * sg_free_table - Free a previously allocated sg table
-+ * @table:	The mapped sg table header
-+ *
-+ **/
-+void sg_free_table(struct sg_table *table)
++static struct dma_page *pool_find_page(struct dma_pool *pool, dma_addr_t dma)
 +{
-+	__sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree);
++	unsigned long flags;
++	struct dma_page *page;
++
++	spin_lock_irqsave(&pool->lock, flags);
++	list_for_each_entry(page, &pool->page_list, page_list) {
++		if (dma < page->dma)
++			continue;
++		if (dma < (page->dma + pool->allocation))
++			goto done;
++	}
++	page = NULL;
++ done:
++	spin_unlock_irqrestore(&pool->lock, flags);
++	return page;
 +}
-+EXPORT_SYMBOL(sg_free_table);
 +
 +/**
-+ * __sg_alloc_table - Allocate and initialize an sg table with given allocator
-+ * @table:	The sg table header to use
-+ * @nents:	Number of entries in sg list
-+ * @max_ents:	The maximum number of entries the allocator returns per call
-+ * @gfp_mask:	GFP allocation mask
-+ * @alloc_fn:	Allocator to use
-+ *
-+ * Description:
-+ *   This function returns a @table @nents long. The allocator is
-+ *   defined to return scatterlist chunks of maximum size @max_ents.
-+ *   Thus if @nents is bigger than @max_ents, the scatterlists will be
-+ *   chained in units of @max_ents.
-+ *
-+ * Notes:
-+ *   If this function returns non-0 (eg failure), the caller must call
-+ *   __sg_free_table() to cleanup any leftover allocations.
++ * dma_pool_free - put block back into dma pool
++ * @pool: the dma pool holding the block
++ * @vaddr: virtual address of block
++ * @dma: dma address of block
 + *
-+ **/
-+int __sg_alloc_table(struct sg_table *table, unsigned int nents,
-+		     unsigned int max_ents, gfp_t gfp_mask,
-+		     sg_alloc_fn *alloc_fn)
++ * Caller promises neither device nor driver will again touch this block
++ * unless it is first re-allocated.
++ */
++void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t dma)
 +{
-+	struct scatterlist *sg, *prv;
-+	unsigned int left;
-+
-+#ifndef ARCH_HAS_SG_CHAIN
-+	BUG_ON(nents > max_ents);
-+#endif
++	struct dma_page *page;
++	unsigned long flags;
++	unsigned int offset;
 +
-+	memset(table, 0, sizeof(*table));
++	page = pool_find_page(pool, dma);
++	if (!page) {
++		if (pool->dev)
++			dev_err(pool->dev,
++				"dma_pool_free %s, %p/%lx (bad dma)\n",
++				pool->name, vaddr, (unsigned long)dma);
++		else
++			printk(KERN_ERR "dma_pool_free %s, %p/%lx (bad dma)\n",
++			       pool->name, vaddr, (unsigned long)dma);
++		return;
++	}
 +
-+	left = nents;
-+	prv = NULL;
-+	do {
-+		unsigned int sg_size, alloc_size = left;
++	offset = vaddr - page->vaddr;
++#ifdef	CONFIG_DEBUG_SLAB
++	if ((dma - page->dma) != offset) {
++		if (pool->dev)
++			dev_err(pool->dev,
++				"dma_pool_free %s, %p (bad vaddr)/%Lx\n",
++				pool->name, vaddr, (unsigned long long)dma);
++		else
++			printk(KERN_ERR
++			       "dma_pool_free %s, %p (bad vaddr)/%Lx\n",
++			       pool->name, vaddr, (unsigned long long)dma);
++		return;
++	}
++	{
++		unsigned int chain = page->offset;
++		while (chain < pool->allocation) {
++			if (chain != offset) {
++				chain = *(int *)(page->vaddr + chain);
++				continue;
++			}
++			if (pool->dev)
++				dev_err(pool->dev, "dma_pool_free %s, dma %Lx "
++					"already free\n", pool->name,
++					(unsigned long long)dma);
++			else
++				printk(KERN_ERR "dma_pool_free %s, dma %Lx "
++					"already free\n", pool->name,
++					(unsigned long long)dma);
++			return;
++		}
++	}
++	memset(vaddr, POOL_POISON_FREED, pool->size);
++#endif
 +
-+		if (alloc_size > max_ents) {
-+			alloc_size = max_ents;
-+			sg_size = alloc_size - 1;
-+		} else
-+			sg_size = alloc_size;
++	spin_lock_irqsave(&pool->lock, flags);
++	page->in_use--;
++	*(int *)vaddr = page->offset;
++	page->offset = offset;
++	if (waitqueue_active(&pool->waitq))
++		wake_up_locked(&pool->waitq);
++	/*
++	 * Resist a temptation to do
++	 *    if (!is_page_busy(page)) pool_free_page(pool, page);
++	 * Better have a few empty pages hang around.
++	 */
++	spin_unlock_irqrestore(&pool->lock, flags);
++}
++EXPORT_SYMBOL(dma_pool_free);
 +
-+		left -= sg_size;
++/*
++ * Managed DMA pool
++ */
++static void dmam_pool_release(struct device *dev, void *res)
++{
++	struct dma_pool *pool = *(struct dma_pool **)res;
 +
-+		sg = alloc_fn(alloc_size, gfp_mask);
-+		if (unlikely(!sg))
-+			return -ENOMEM;
++	dma_pool_destroy(pool);
++}
 +
-+		sg_init_table(sg, alloc_size);
-+		table->nents = table->orig_nents += sg_size;
++static int dmam_pool_match(struct device *dev, void *res, void *match_data)
++{
++	return *(struct dma_pool **)res == match_data;
++}
 +
-+		/*
-+		 * If this is the first mapping, assign the sg table header.
-+		 * If this is not the first mapping, chain previous part.
-+		 */
-+		if (prv)
-+			sg_chain(prv, max_ents, sg);
-+		else
-+			table->sgl = sg;
++/**
++ * dmam_pool_create - Managed dma_pool_create()
++ * @name: name of pool, for diagnostics
++ * @dev: device that will be doing the DMA
++ * @size: size of the blocks in this pool.
++ * @align: alignment requirement for blocks; must be a power of two
++ * @allocation: returned blocks won't cross this boundary (or zero)
++ *
++ * Managed dma_pool_create().  DMA pool created with this function is
++ * automatically destroyed on driver detach.
++ */
++struct dma_pool *dmam_pool_create(const char *name, struct device *dev,
++				  size_t size, size_t align, size_t allocation)
++{
++	struct dma_pool **ptr, *pool;
 +
-+		/*
-+		 * If no more entries after this one, mark the end
-+		 */
-+		if (!left)
-+			sg_mark_end(&sg[sg_size - 1]);
++	ptr = devres_alloc(dmam_pool_release, sizeof(*ptr), GFP_KERNEL);
++	if (!ptr)
++		return NULL;
 +
-+		/*
-+		 * only really needed for mempool backed sg allocations (like
-+		 * SCSI), a possible improvement here would be to pass the
-+		 * table pointer into the allocator and let that clear these
-+		 * flags
-+		 */
-+		gfp_mask &= ~__GFP_WAIT;
-+		gfp_mask |= __GFP_HIGH;
-+		prv = sg;
-+	} while (left);
++	pool = *ptr = dma_pool_create(name, dev, size, align, allocation);
++	if (pool)
++		devres_add(dev, ptr);
++	else
++		devres_free(ptr);
 +
-+	return 0;
++	return pool;
 +}
-+EXPORT_SYMBOL(__sg_alloc_table);
++EXPORT_SYMBOL(dmam_pool_create);
 +
 +/**
-+ * sg_alloc_table - Allocate and initialize an sg table
-+ * @table:	The sg table header to use
-+ * @nents:	Number of entries in sg list
-+ * @gfp_mask:	GFP allocation mask
-+ *
-+ *  Description:
-+ *    Allocate and initialize an sg table. If @nents@ is larger than
-+ *    SG_MAX_SINGLE_ALLOC a chained sg table will be setup.
++ * dmam_pool_destroy - Managed dma_pool_destroy()
++ * @pool: dma pool that will be destroyed
 + *
-+ **/
-+int sg_alloc_table(struct sg_table *table, unsigned int nents, gfp_t gfp_mask)
++ * Managed dma_pool_destroy().
++ */
++void dmam_pool_destroy(struct dma_pool *pool)
 +{
-+	int ret;
-+
-+	ret = __sg_alloc_table(table, nents, SG_MAX_SINGLE_ALLOC,
-+			       gfp_mask, sg_kmalloc);
-+	if (unlikely(ret))
-+		__sg_free_table(table, SG_MAX_SINGLE_ALLOC, sg_kfree);
++	struct device *dev = pool->dev;
 +
-+	return ret;
++	dma_pool_destroy(pool);
++	WARN_ON(devres_destroy(dev, dmam_pool_release, dmam_pool_match, pool));
 +}
-+EXPORT_SYMBOL(sg_alloc_table);
-diff --git a/mm/Kconfig b/mm/Kconfig
-index 9ef9741..0016ebd 100644
---- a/mm/Kconfig
-+++ b/mm/Kconfig
-@@ -187,7 +187,7 @@ config BOUNCE
- config NR_QUICK
- 	int
- 	depends on QUICKLIST
--	default "2" if (SUPERH && !SUPERH64)
-+	default "2" if SUPERH
- 	default "1"
++EXPORT_SYMBOL(dmam_pool_destroy);
+diff --git a/mm/fadvise.c b/mm/fadvise.c
+index 0df4c89..3c0f1e9 100644
+--- a/mm/fadvise.c
++++ b/mm/fadvise.c
+@@ -49,9 +49,21 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
+ 		goto out;
+ 	}
  
- config VIRT_TO_BUS
+-	if (mapping->a_ops->get_xip_page)
+-		/* no bad return value, but ignore advice */
++	if (mapping->a_ops->get_xip_page) {
++		switch (advice) {
++		case POSIX_FADV_NORMAL:
++		case POSIX_FADV_RANDOM:
++		case POSIX_FADV_SEQUENTIAL:
++		case POSIX_FADV_WILLNEED:
++		case POSIX_FADV_NOREUSE:
++		case POSIX_FADV_DONTNEED:
++			/* no bad return value, but ignore advice */
++			break;
++		default:
++			ret = -EINVAL;
++		}
+ 		goto out;
++	}
+ 
+ 	/* Careful about overflows. Len == 0 means "as much as possible" */
+ 	endbyte = offset + len;
 diff --git a/mm/filemap.c b/mm/filemap.c
-index f4d0cde..76bea88 100644
+index f4d0cde..81fb9bf 100644
 --- a/mm/filemap.c
 +++ b/mm/filemap.c
-@@ -185,6 +185,12 @@ static int sync_page(void *word)
+@@ -65,7 +65,6 @@ generic_file_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
+  *    ->private_lock		(__free_pte->__set_page_dirty_buffers)
+  *      ->swap_lock		(exclusive_swap_page, others)
+  *        ->mapping->tree_lock
+- *          ->zone.lock
+  *
+  *  ->i_mutex
+  *    ->i_mmap_lock		(truncate->unmap_mapping_range)
+@@ -185,6 +184,12 @@ static int sync_page(void *word)
  	return 0;
  }
  
@@ -903645,7 +978682,34 @@
  /**
   * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
   * @mapping:	address space structure to write
-@@ -589,6 +595,14 @@ void fastcall __lock_page(struct page *page)
+@@ -522,7 +527,7 @@ static inline void wake_up_page(struct page *page, int bit)
+ 	__wake_up_bit(page_waitqueue(page), &page->flags, bit);
+ }
+ 
+-void fastcall wait_on_page_bit(struct page *page, int bit_nr)
++void wait_on_page_bit(struct page *page, int bit_nr)
+ {
+ 	DEFINE_WAIT_BIT(wait, &page->flags, bit_nr);
+ 
+@@ -546,7 +551,7 @@ EXPORT_SYMBOL(wait_on_page_bit);
+  * the clear_bit and the read of the waitqueue (to avoid SMP races with a
+  * parallel wait_on_page_locked()).
+  */
+-void fastcall unlock_page(struct page *page)
++void unlock_page(struct page *page)
+ {
+ 	smp_mb__before_clear_bit();
+ 	if (!TestClearPageLocked(page))
+@@ -580,7 +585,7 @@ EXPORT_SYMBOL(end_page_writeback);
+  * chances are that on the second loop, the block layer's plug list is empty,
+  * so sync_page() will then return in state TASK_UNINTERRUPTIBLE.
+  */
+-void fastcall __lock_page(struct page *page)
++void __lock_page(struct page *page)
+ {
+ 	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
+ 
+@@ -589,11 +594,19 @@ void fastcall __lock_page(struct page *page)
  }
  EXPORT_SYMBOL(__lock_page);
  
@@ -903660,7 +978724,13 @@
  /*
   * Variant of lock_page that does not require the caller to hold a reference
   * on the page's mapping.
-@@ -980,7 +994,8 @@ page_ok:
+  */
+-void fastcall __lock_page_nosync(struct page *page)
++void __lock_page_nosync(struct page *page)
+ {
+ 	DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
+ 	__wait_on_bit_lock(page_waitqueue(page), &wait, __sleep_on_page_lock,
+@@ -980,7 +993,8 @@ page_ok:
  
  page_not_up_to_date:
  		/* Get exclusive access to the page ... */
@@ -903670,7 +978740,7 @@
  
  		/* Did it get truncated before we got the lock? */
  		if (!page->mapping) {
-@@ -1008,7 +1023,8 @@ readpage:
+@@ -1008,7 +1022,8 @@ readpage:
  		}
  
  		if (!PageUptodate(page)) {
@@ -903680,7 +978750,7 @@
  			if (!PageUptodate(page)) {
  				if (page->mapping == NULL) {
  					/*
-@@ -1019,15 +1035,16 @@ readpage:
+@@ -1019,15 +1034,16 @@ readpage:
  					goto find_page;
  				}
  				unlock_page(page);
@@ -903699,7 +978769,16 @@
  readpage_error:
  		/* UHHUH! A synchronous read error occurred. Report it */
  		desc->error = error;
-@@ -1733,7 +1750,11 @@ static void __iov_iter_advance_iov(struct iov_iter *i, size_t bytes)
+@@ -1260,7 +1276,7 @@ asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count)
+  * This adds the requested page to the page cache if it isn't already there,
+  * and schedules an I/O to read in its contents from disk.
+  */
+-static int fastcall page_cache_read(struct file * file, pgoff_t offset)
++static int page_cache_read(struct file *file, pgoff_t offset)
+ {
+ 	struct address_space *mapping = file->f_mapping;
+ 	struct page *page; 
+@@ -1733,7 +1749,11 @@ static void __iov_iter_advance_iov(struct iov_iter *i, size_t bytes)
  		const struct iovec *iov = i->iov;
  		size_t base = i->iov_offset;
  
@@ -903712,7 +978791,7 @@
  			int copy = min(bytes, iov->iov_len - base);
  
  			bytes -= copy;
-@@ -2251,6 +2272,7 @@ again:
+@@ -2251,6 +2271,7 @@ again:
  
  		cond_resched();
  
@@ -903720,7 +978799,7 @@
  		if (unlikely(copied == 0)) {
  			/*
  			 * If we were unable to copy any data at all, we must
-@@ -2264,7 +2286,6 @@ again:
+@@ -2264,7 +2285,6 @@ again:
  						iov_iter_single_seg_count(i));
  			goto again;
  		}
@@ -903728,10 +978807,124 @@
  		pos += copied;
  		written += copied;
  
+diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
+index f874ae8..0420a02 100644
+--- a/mm/filemap_xip.c
++++ b/mm/filemap_xip.c
+@@ -431,7 +431,7 @@ xip_truncate_page(struct address_space *mapping, loff_t from)
+ 		else
+ 			return PTR_ERR(page);
+ 	}
+-	zero_user_page(page, offset, length, KM_USER0);
++	zero_user(page, offset, length);
+ 	return 0;
+ }
+ EXPORT_SYMBOL_GPL(xip_truncate_page);
+diff --git a/mm/fremap.c b/mm/fremap.c
+index 14bd3bf..69a37c2 100644
+--- a/mm/fremap.c
++++ b/mm/fremap.c
+@@ -190,10 +190,13 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
+ 		 */
+ 		if (mapping_cap_account_dirty(mapping)) {
+ 			unsigned long addr;
++			struct file *file = vma->vm_file;
+ 
+ 			flags &= MAP_NONBLOCK;
+-			addr = mmap_region(vma->vm_file, start, size,
++			get_file(file);
++			addr = mmap_region(file, start, size,
+ 					flags, vma->vm_flags, pgoff, 1);
++			fput(file);
+ 			if (IS_ERR_VALUE(addr)) {
+ 				err = addr;
+ 			} else {
+diff --git a/mm/highmem.c b/mm/highmem.c
+index 7a967bc..35d4773 100644
+--- a/mm/highmem.c
++++ b/mm/highmem.c
+@@ -163,7 +163,7 @@ start:
+ 	return vaddr;
+ }
+ 
+-void fastcall *kmap_high(struct page *page)
++void *kmap_high(struct page *page)
+ {
+ 	unsigned long vaddr;
+ 
+@@ -185,7 +185,7 @@ void fastcall *kmap_high(struct page *page)
+ 
+ EXPORT_SYMBOL(kmap_high);
+ 
+-void fastcall kunmap_high(struct page *page)
++void kunmap_high(struct page *page)
+ {
+ 	unsigned long vaddr;
+ 	unsigned long nr;
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index db861d8..1a56420 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -813,6 +813,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
+ 
+ 	spin_unlock(&mm->page_table_lock);
+ 	copy_huge_page(new_page, old_page, address, vma);
++	__SetPageUptodate(new_page);
+ 	spin_lock(&mm->page_table_lock);
+ 
+ 	ptep = huge_pte_offset(mm, address & HPAGE_MASK);
+@@ -858,6 +859,7 @@ retry:
+ 			goto out;
+ 		}
+ 		clear_huge_page(page, address);
++		__SetPageUptodate(page);
+ 
+ 		if (vma->vm_flags & VM_SHARED) {
+ 			int err;
+diff --git a/mm/internal.h b/mm/internal.h
+index 953f941..5a9a620 100644
+--- a/mm/internal.h
++++ b/mm/internal.h
+@@ -24,7 +24,7 @@ static inline void set_page_count(struct page *page, int v)
+  */
+ static inline void set_page_refcounted(struct page *page)
+ {
+-	VM_BUG_ON(PageCompound(page) && PageTail(page));
++	VM_BUG_ON(PageTail(page));
+ 	VM_BUG_ON(atomic_read(&page->_count));
+ 	set_page_count(page, 1);
+ }
+@@ -34,7 +34,7 @@ static inline void __put_page(struct page *page)
+ 	atomic_dec(&page->_count);
+ }
+ 
+-extern void fastcall __init __free_pages_bootmem(struct page *page,
++extern void __init __free_pages_bootmem(struct page *page,
+ 						unsigned int order);
+ 
+ /*
 diff --git a/mm/memory.c b/mm/memory.c
-index 4b0144b..d902d0e 100644
+index 4b0144b..7bb7072 100644
 --- a/mm/memory.c
 +++ b/mm/memory.c
+@@ -305,7 +305,7 @@ int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
+ 	spin_lock(&mm->page_table_lock);
+ 	if (pmd_present(*pmd)) {	/* Another has populated it */
+ 		pte_lock_deinit(new);
+-		pte_free(new);
++		pte_free(mm, new);
+ 	} else {
+ 		mm->nr_ptes++;
+ 		inc_zone_page_state(new, NR_PAGETABLE);
+@@ -323,7 +323,7 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
+ 
+ 	spin_lock(&init_mm.page_table_lock);
+ 	if (pmd_present(*pmd))		/* Another has populated it */
+-		pte_free_kernel(new);
++		pte_free_kernel(&init_mm, new);
+ 	else
+ 		pmd_populate_kernel(&init_mm, pmd, new);
+ 	spin_unlock(&init_mm.page_table_lock);
 @@ -513,8 +513,7 @@ again:
  		if (progress >= 32) {
  			progress = 0;
@@ -903751,6 +978944,37 @@
  				if (i_mmap_lock) {
  					*tlbp = NULL;
  					goto out;
+@@ -1110,7 +1109,8 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+ }
+ EXPORT_SYMBOL(get_user_pages);
+ 
+-pte_t * fastcall get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl)
++pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
++			spinlock_t **ptl)
+ {
+ 	pgd_t * pgd = pgd_offset(mm, addr);
+ 	pud_t * pud = pud_alloc(mm, pgd, addr);
+@@ -1518,10 +1518,8 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
+ 			memset(kaddr, 0, PAGE_SIZE);
+ 		kunmap_atomic(kaddr, KM_USER0);
+ 		flush_dcache_page(dst);
+-		return;
+-
+-	}
+-	copy_user_highpage(dst, src, va, vma);
++	} else
++		copy_user_highpage(dst, src, va, vma);
+ }
+ 
+ /*
+@@ -1630,6 +1628,7 @@ gotten:
+ 	if (!new_page)
+ 		goto oom;
+ 	cow_user_page(new_page, old_page, address, vma);
++	__SetPageUptodate(new_page);
+ 
+ 	/*
+ 	 * Re-check the pte - we dropped the lock
 @@ -1768,8 +1767,7 @@ again:
  
  	restart_addr = zap_page_range(vma, start_addr,
@@ -903761,7 +978985,258 @@
  
  	if (restart_addr >= end_addr) {
  		/* We have now completed this vma: mark it so */
-@@ -2756,3 +2754,34 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
+@@ -1911,50 +1909,49 @@ EXPORT_SYMBOL(unmap_mapping_range);
+  */
+ int vmtruncate(struct inode * inode, loff_t offset)
+ {
+-	struct address_space *mapping = inode->i_mapping;
+-	unsigned long limit;
++	if (inode->i_size < offset) {
++		unsigned long limit;
+ 
+-	if (inode->i_size < offset)
+-		goto do_expand;
+-	/*
+-	 * truncation of in-use swapfiles is disallowed - it would cause
+-	 * subsequent swapout to scribble on the now-freed blocks.
+-	 */
+-	if (IS_SWAPFILE(inode))
+-		goto out_busy;
+-	i_size_write(inode, offset);
++		limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
++		if (limit != RLIM_INFINITY && offset > limit)
++			goto out_sig;
++		if (offset > inode->i_sb->s_maxbytes)
++			goto out_big;
++		i_size_write(inode, offset);
++	} else {
++		struct address_space *mapping = inode->i_mapping;
++
++		/*
++		 * truncation of in-use swapfiles is disallowed - it would
++		 * cause subsequent swapout to scribble on the now-freed
++		 * blocks.
++		 */
++		if (IS_SWAPFILE(inode))
++			return -ETXTBSY;
++		i_size_write(inode, offset);
++
++		/*
++		 * unmap_mapping_range is called twice, first simply for
++		 * efficiency so that truncate_inode_pages does fewer
++		 * single-page unmaps.  However after this first call, and
++		 * before truncate_inode_pages finishes, it is possible for
++		 * private pages to be COWed, which remain after
++		 * truncate_inode_pages finishes, hence the second
++		 * unmap_mapping_range call must be made for correctness.
++		 */
++		unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
++		truncate_inode_pages(mapping, offset);
++		unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
++	}
+ 
+-	/*
+-	 * unmap_mapping_range is called twice, first simply for efficiency
+-	 * so that truncate_inode_pages does fewer single-page unmaps. However
+-	 * after this first call, and before truncate_inode_pages finishes,
+-	 * it is possible for private pages to be COWed, which remain after
+-	 * truncate_inode_pages finishes, hence the second unmap_mapping_range
+-	 * call must be made for correctness.
+-	 */
+-	unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+-	truncate_inode_pages(mapping, offset);
+-	unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
+-	goto out_truncate;
+-
+-do_expand:
+-	limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+-	if (limit != RLIM_INFINITY && offset > limit)
+-		goto out_sig;
+-	if (offset > inode->i_sb->s_maxbytes)
+-		goto out_big;
+-	i_size_write(inode, offset);
+-
+-out_truncate:
+ 	if (inode->i_op && inode->i_op->truncate)
+ 		inode->i_op->truncate(inode);
+ 	return 0;
++
+ out_sig:
+ 	send_sig(SIGXFSZ, current, 0);
+ out_big:
+ 	return -EFBIG;
+-out_busy:
+-	return -ETXTBSY;
+ }
+ EXPORT_SYMBOL(vmtruncate);
+ 
+@@ -1982,67 +1979,6 @@ int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
+ 	return 0;
+ }
+ 
+-/**
+- * swapin_readahead - swap in pages in hope we need them soon
+- * @entry: swap entry of this memory
+- * @addr: address to start
+- * @vma: user vma this addresses belong to
+- *
+- * Primitive swap readahead code. We simply read an aligned block of
+- * (1 << page_cluster) entries in the swap area. This method is chosen
+- * because it doesn't cost us any seek time.  We also make sure to queue
+- * the 'original' request together with the readahead ones...
+- *
+- * This has been extended to use the NUMA policies from the mm triggering
+- * the readahead.
+- *
+- * Caller must hold down_read on the vma->vm_mm if vma is not NULL.
+- */
+-void swapin_readahead(swp_entry_t entry, unsigned long addr,struct vm_area_struct *vma)
+-{
+-#ifdef CONFIG_NUMA
+-	struct vm_area_struct *next_vma = vma ? vma->vm_next : NULL;
+-#endif
+-	int i, num;
+-	struct page *new_page;
+-	unsigned long offset;
+-
+-	/*
+-	 * Get the number of handles we should do readahead io to.
+-	 */
+-	num = valid_swaphandles(entry, &offset);
+-	for (i = 0; i < num; offset++, i++) {
+-		/* Ok, do the async read-ahead now */
+-		new_page = read_swap_cache_async(swp_entry(swp_type(entry),
+-							   offset), vma, addr);
+-		if (!new_page)
+-			break;
+-		page_cache_release(new_page);
+-#ifdef CONFIG_NUMA
+-		/*
+-		 * Find the next applicable VMA for the NUMA policy.
+-		 */
+-		addr += PAGE_SIZE;
+-		if (addr == 0)
+-			vma = NULL;
+-		if (vma) {
+-			if (addr >= vma->vm_end) {
+-				vma = next_vma;
+-				next_vma = vma ? vma->vm_next : NULL;
+-			}
+-			if (vma && addr < vma->vm_start)
+-				vma = NULL;
+-		} else {
+-			if (next_vma && addr >= next_vma->vm_start) {
+-				vma = next_vma;
+-				next_vma = vma->vm_next;
+-			}
+-		}
+-#endif
+-	}
+-	lru_add_drain();	/* Push any new pages onto the LRU now */
+-}
+-
+ /*
+  * We enter with non-exclusive mmap_sem (to exclude vma changes,
+  * but allow concurrent faults), and pte mapped but not yet locked.
+@@ -2070,8 +2006,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ 	page = lookup_swap_cache(entry);
+ 	if (!page) {
+ 		grab_swap_token(); /* Contend for token _before_ read-in */
+- 		swapin_readahead(entry, address, vma);
+- 		page = read_swap_cache_async(entry, vma, address);
++		page = swapin_readahead(entry,
++					GFP_HIGHUSER_MOVABLE, vma, address);
+ 		if (!page) {
+ 			/*
+ 			 * Back out if somebody else faulted in this pte
+@@ -2165,6 +2101,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ 	page = alloc_zeroed_user_highpage_movable(vma, address);
+ 	if (!page)
+ 		goto oom;
++	__SetPageUptodate(page);
+ 
+ 	entry = mk_pte(page, vma->vm_page_prot);
+ 	entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+@@ -2265,6 +2202,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
+ 				goto out;
+ 			}
+ 			copy_user_highpage(page, vmf.page, address, vma);
++			__SetPageUptodate(page);
+ 		} else {
+ 			/*
+ 			 * If the page will be shareable, see if the backing
+@@ -2565,7 +2503,7 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+ 
+ 	spin_lock(&mm->page_table_lock);
+ 	if (pgd_present(*pgd))		/* Another has populated it */
+-		pud_free(new);
++		pud_free(mm, new);
+ 	else
+ 		pgd_populate(mm, pgd, new);
+ 	spin_unlock(&mm->page_table_lock);
+@@ -2587,12 +2525,12 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
+ 	spin_lock(&mm->page_table_lock);
+ #ifndef __ARCH_HAS_4LEVEL_HACK
+ 	if (pud_present(*pud))		/* Another has populated it */
+-		pmd_free(new);
++		pmd_free(mm, new);
+ 	else
+ 		pud_populate(mm, pud, new);
+ #else
+ 	if (pgd_present(*pud))		/* Another has populated it */
+-		pmd_free(new);
++		pmd_free(mm, new);
+ 	else
+ 		pgd_populate(mm, pud, new);
+ #endif /* __ARCH_HAS_4LEVEL_HACK */
+@@ -2620,46 +2558,6 @@ int make_pages_present(unsigned long addr, unsigned long end)
+ 	return ret == len ? 0 : -1;
+ }
+ 
+-/* 
+- * Map a vmalloc()-space virtual address to the physical page.
+- */
+-struct page * vmalloc_to_page(void * vmalloc_addr)
+-{
+-	unsigned long addr = (unsigned long) vmalloc_addr;
+-	struct page *page = NULL;
+-	pgd_t *pgd = pgd_offset_k(addr);
+-	pud_t *pud;
+-	pmd_t *pmd;
+-	pte_t *ptep, pte;
+-  
+-	if (!pgd_none(*pgd)) {
+-		pud = pud_offset(pgd, addr);
+-		if (!pud_none(*pud)) {
+-			pmd = pmd_offset(pud, addr);
+-			if (!pmd_none(*pmd)) {
+-				ptep = pte_offset_map(pmd, addr);
+-				pte = *ptep;
+-				if (pte_present(pte))
+-					page = pte_page(pte);
+-				pte_unmap(ptep);
+-			}
+-		}
+-	}
+-	return page;
+-}
+-
+-EXPORT_SYMBOL(vmalloc_to_page);
+-
+-/*
+- * Map a vmalloc()-space virtual address to the physical page frame number.
+- */
+-unsigned long vmalloc_to_pfn(void * vmalloc_addr)
+-{
+-	return page_to_pfn(vmalloc_to_page(vmalloc_addr));
+-}
+-
+-EXPORT_SYMBOL(vmalloc_to_pfn);
+-
+ #if !defined(__HAVE_ARCH_GATE_AREA)
+ 
+ #if defined(AT_SYSINFO_EHDR)
+@@ -2756,3 +2654,34 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
  
  	return buf - old_buf;
  }
@@ -903796,11 +979271,109 @@
 +	}
 +	up_read(&current->mm->mmap_sem);
 +}
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index 9512a54..7469c50 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -481,8 +481,6 @@ check_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
+ 	return offlined;
+ }
+ 
+-extern void drain_all_local_pages(void);
+-
+ int offline_pages(unsigned long start_pfn,
+ 		  unsigned long end_pfn, unsigned long timeout)
+ {
+@@ -540,7 +538,7 @@ repeat:
+ 		lru_add_drain_all();
+ 		flush_scheduled_work();
+ 		cond_resched();
+-		drain_all_local_pages();
++		drain_all_pages();
+ 	}
+ 
+ 	pfn = scan_lru_pages(start_pfn, end_pfn);
+@@ -563,7 +561,7 @@ repeat:
+ 	flush_scheduled_work();
+ 	yield();
+ 	/* drain pcp pages , this is synchrouns. */
+-	drain_all_local_pages();
++	drain_all_pages();
+ 	/* check again */
+ 	offlined_pages = check_pages_isolated(start_pfn, end_pfn);
+ 	if (offlined_pages < 0) {
+diff --git a/mm/migrate.c b/mm/migrate.c
+index 6a207e8..857a987 100644
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -115,11 +115,6 @@ int putback_lru_pages(struct list_head *l)
+ 	return count;
+ }
+ 
+-static inline int is_swap_pte(pte_t pte)
+-{
+-	return !pte_none(pte) && !pte_present(pte) && !pte_file(pte);
+-}
+-
+ /*
+  * Restore a potential migration pte to a working pte entry
+  */
+@@ -645,15 +640,33 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
+ 		rcu_read_lock();
+ 		rcu_locked = 1;
+ 	}
++
+ 	/*
+-	 * This is a corner case handling.
+-	 * When a new swap-cache is read into, it is linked to LRU
+-	 * and treated as swapcache but has no rmap yet.
+-	 * Calling try_to_unmap() against a page->mapping==NULL page is
+-	 * BUG. So handle it here.
++	 * Corner case handling:
++	 * 1. When a new swap-cache page is read into, it is added to the LRU
++	 * and treated as swapcache but it has no rmap yet.
++	 * Calling try_to_unmap() against a page->mapping==NULL page will
++	 * trigger a BUG.  So handle it here.
++	 * 2. An orphaned page (see truncate_complete_page) might have
++	 * fs-private metadata. The page can be picked up due to memory
++	 * offlining.  Everywhere else except page reclaim, the page is
++	 * invisible to the vm, so the page can not be migrated.  So try to
++	 * free the metadata, so the page can be freed.
+ 	 */
+-	if (!page->mapping)
++	if (!page->mapping) {
++		if (!PageAnon(page) && PagePrivate(page)) {
++			/*
++			 * Go direct to try_to_free_buffers() here because
++			 * a) that's what try_to_release_page() would do anyway
++			 * b) we may be under rcu_read_lock() here, so we can't
++			 *    use GFP_KERNEL which is what try_to_release_page()
++			 *    needs to be effective.
++			 */
++			try_to_free_buffers(page);
++		}
+ 		goto rcu_unlock;
++	}
++
+ 	/* Establish migration ptes or remove ptes */
+ 	try_to_unmap(page, 1);
+ 
 diff --git a/mm/mmap.c b/mm/mmap.c
-index 15678aa..d2b6d44 100644
+index 15678aa..bb4c963 100644
 --- a/mm/mmap.c
 +++ b/mm/mmap.c
-@@ -251,7 +251,8 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
+@@ -36,6 +36,10 @@
+ #define arch_mmap_check(addr, len, flags)	(0)
+ #endif
+ 
++#ifndef arch_rebalance_pgtables
++#define arch_rebalance_pgtables(addr, len)		(addr)
++#endif
++
+ static void unmap_region(struct mm_struct *mm,
+ 		struct vm_area_struct *vma, struct vm_area_struct *prev,
+ 		unsigned long start, unsigned long end);
+@@ -251,7 +255,8 @@ asmlinkage unsigned long sys_brk(unsigned long brk)
  	 * not page aligned -Ram Gupta
  	 */
  	rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
@@ -903810,7 +979383,16 @@
  		goto out;
  
  	newbrk = PAGE_ALIGN(brk);
-@@ -1620,7 +1621,7 @@ static inline int expand_downwards(struct vm_area_struct *vma,
+@@ -1423,7 +1428,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
+ 	if (addr & ~PAGE_MASK)
+ 		return -EINVAL;
+ 
+-	return addr;
++	return arch_rebalance_pgtables(addr, len);
+ }
+ 
+ EXPORT_SYMBOL(get_unmapped_area);
+@@ -1620,7 +1625,7 @@ static inline int expand_downwards(struct vm_area_struct *vma,
  		return -ENOMEM;
  
  	address &= PAGE_MASK;
@@ -903819,7 +979401,7 @@
  	if (error)
  		return error;
  
-@@ -1941,7 +1942,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
+@@ -1941,7 +1946,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
  	if (is_hugepage_only_range(mm, addr, len))
  		return -EINVAL;
  
@@ -903828,11 +979410,146 @@
  	if (error)
  		return error;
  
+@@ -2215,7 +2220,7 @@ int install_special_mapping(struct mm_struct *mm,
+ 	vma->vm_start = addr;
+ 	vma->vm_end = addr + len;
+ 
+-	vma->vm_flags = vm_flags | mm->def_flags;
++	vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND;
+ 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ 
+ 	vma->vm_ops = &special_mapping_vmops;
+diff --git a/mm/nommu.c b/mm/nommu.c
+index b989cb9..5d8ae08 100644
+--- a/mm/nommu.c
++++ b/mm/nommu.c
+@@ -10,6 +10,7 @@
+  *  Copyright (c) 2000-2003 David McCullough <davidm at snapgear.com>
+  *  Copyright (c) 2000-2001 D Jeff Dionne <jeff at uClinux.org>
+  *  Copyright (c) 2002      Greg Ungerer <gerg at snapgear.com>
++ *  Copyright (c) 2007      Paul Mundt <lethal at linux-sh.org>
+  */
+ 
+ #include <linux/module.h>
+@@ -167,7 +168,7 @@ EXPORT_SYMBOL(get_user_pages);
+ DEFINE_RWLOCK(vmlist_lock);
+ struct vm_struct *vmlist;
+ 
+-void vfree(void *addr)
++void vfree(const void *addr)
+ {
+ 	kfree(addr);
+ }
+@@ -183,13 +184,33 @@ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
+ }
+ EXPORT_SYMBOL(__vmalloc);
+ 
+-struct page * vmalloc_to_page(void *addr)
++void *vmalloc_user(unsigned long size)
++{
++	void *ret;
++
++	ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
++			PAGE_KERNEL);
++	if (ret) {
++		struct vm_area_struct *vma;
++
++		down_write(&current->mm->mmap_sem);
++		vma = find_vma(current->mm, (unsigned long)ret);
++		if (vma)
++			vma->vm_flags |= VM_USERMAP;
++		up_write(&current->mm->mmap_sem);
++	}
++
++	return ret;
++}
++EXPORT_SYMBOL(vmalloc_user);
++
++struct page *vmalloc_to_page(const void *addr)
+ {
+ 	return virt_to_page(addr);
+ }
+ EXPORT_SYMBOL(vmalloc_to_page);
+ 
+-unsigned long vmalloc_to_pfn(void *addr)
++unsigned long vmalloc_to_pfn(const void *addr)
+ {
+ 	return page_to_pfn(virt_to_page(addr));
+ }
+@@ -253,10 +274,17 @@ EXPORT_SYMBOL(vmalloc_32);
+  *
+  * The resulting memory area is 32bit addressable and zeroed so it can be
+  * mapped to userspace without leaking data.
++ *
++ * VM_USERMAP is set on the corresponding VMA so that subsequent calls to
++ * remap_vmalloc_range() are permissible.
+  */
+ void *vmalloc_32_user(unsigned long size)
+ {
+-	return __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
++	/*
++	 * We'll have to sort out the ZONE_DMA bits for 64-bit,
++	 * but for now this can simply use vmalloc_user() directly.
++	 */
++	return vmalloc_user(size);
+ }
+ EXPORT_SYMBOL(vmalloc_32_user);
+ 
+@@ -267,7 +295,7 @@ void *vmap(struct page **pages, unsigned int count, unsigned long flags, pgprot_
+ }
+ EXPORT_SYMBOL(vmap);
+ 
+-void vunmap(void *addr)
++void vunmap(const void *addr)
+ {
+ 	BUG();
+ }
+@@ -1216,6 +1244,21 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+ }
+ EXPORT_SYMBOL(remap_pfn_range);
+ 
++int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
++			unsigned long pgoff)
++{
++	unsigned int size = vma->vm_end - vma->vm_start;
++
++	if (!(vma->vm_flags & VM_USERMAP))
++		return -EINVAL;
++
++	vma->vm_start = (unsigned long)(addr + (pgoff << PAGE_SHIFT));
++	vma->vm_end = vma->vm_start + size;
++
++	return 0;
++}
++EXPORT_SYMBOL(remap_vmalloc_range);
++
+ void swap_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
+ {
+ }
 diff --git a/mm/oom_kill.c b/mm/oom_kill.c
-index 91a081a..96473b4 100644
+index 91a081a..c1850bf 100644
 --- a/mm/oom_kill.c
 +++ b/mm/oom_kill.c
-@@ -286,7 +286,7 @@ static void __oom_kill_task(struct task_struct *p, int verbose)
+@@ -125,8 +125,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
+ 	 * Superuser processes are usually more important, so we make it
+ 	 * less likely that we kill those.
+ 	 */
+-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_ADMIN) ||
+-				p->uid == 0 || p->euid == 0)
++	if (__capable(p, CAP_SYS_ADMIN) || __capable(p, CAP_SYS_RESOURCE))
+ 		points /= 4;
+ 
+ 	/*
+@@ -135,7 +134,7 @@ unsigned long badness(struct task_struct *p, unsigned long uptime)
+ 	 * tend to only have this flag set on applications they think
+ 	 * of as important.
+ 	 */
+-	if (cap_t(p->cap_effective) & CAP_TO_MASK(CAP_SYS_RAWIO))
++	if (__capable(p, CAP_SYS_RAWIO))
+ 		points /= 4;
+ 
+ 	/*
+@@ -286,7 +285,7 @@ static void __oom_kill_task(struct task_struct *p, int verbose)
  	 * all the memory it needs. That way it should be able to
  	 * exit() and clear out its resources quickly...
  	 */
@@ -903841,6 +979558,1441 @@
  	set_tsk_thread_flag(p, TIF_MEMDIE);
  
  	force_sig(SIGKILL, p);
+diff --git a/mm/page-writeback.c b/mm/page-writeback.c
+index 3d3848f..5e00f17 100644
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -69,6 +69,12 @@ static inline long sync_writeback_pages(void)
+ int dirty_background_ratio = 5;
+ 
+ /*
++ * free highmem will not be subtracted from the total free memory
++ * for calculating free ratios if vm_highmem_is_dirtyable is true
++ */
++int vm_highmem_is_dirtyable;
++
++/*
+  * The generator of dirty data starts writeback at this percentage
+  */
+ int vm_dirty_ratio = 10;
+@@ -219,7 +225,7 @@ static inline void task_dirties_fraction(struct task_struct *tsk,
+  *
+  *   dirty -= (dirty/8) * p_{t}
+  */
+-void task_dirty_limit(struct task_struct *tsk, long *pdirty)
++static void task_dirty_limit(struct task_struct *tsk, long *pdirty)
+ {
+ 	long numerator, denominator;
+ 	long dirty = *pdirty;
+@@ -287,7 +293,10 @@ static unsigned long determine_dirtyable_memory(void)
+ 	x = global_page_state(NR_FREE_PAGES)
+ 		+ global_page_state(NR_INACTIVE)
+ 		+ global_page_state(NR_ACTIVE);
+-	x -= highmem_dirtyable_memory(x);
++
++	if (!vm_highmem_is_dirtyable)
++		x -= highmem_dirtyable_memory(x);
++
+ 	return x + 1;	/* Ensure that we never return 0 */
+ }
+ 
+@@ -558,6 +567,7 @@ static void background_writeout(unsigned long _min_pages)
+ 			global_page_state(NR_UNSTABLE_NFS) < background_thresh
+ 				&& min_pages <= 0)
+ 			break;
++		wbc.more_io = 0;
+ 		wbc.encountered_congestion = 0;
+ 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
+ 		wbc.pages_skipped = 0;
+@@ -565,8 +575,9 @@ static void background_writeout(unsigned long _min_pages)
+ 		min_pages -= MAX_WRITEBACK_PAGES - wbc.nr_to_write;
+ 		if (wbc.nr_to_write > 0 || wbc.pages_skipped > 0) {
+ 			/* Wrote less than expected */
+-			congestion_wait(WRITE, HZ/10);
+-			if (!wbc.encountered_congestion)
++			if (wbc.encountered_congestion || wbc.more_io)
++				congestion_wait(WRITE, HZ/10);
++			else
+ 				break;
+ 		}
+ 	}
+@@ -631,11 +642,12 @@ static void wb_kupdate(unsigned long arg)
+ 			global_page_state(NR_UNSTABLE_NFS) +
+ 			(inodes_stat.nr_inodes - inodes_stat.nr_unused);
+ 	while (nr_to_write > 0) {
++		wbc.more_io = 0;
+ 		wbc.encountered_congestion = 0;
+ 		wbc.nr_to_write = MAX_WRITEBACK_PAGES;
+ 		writeback_inodes(&wbc);
+ 		if (wbc.nr_to_write > 0) {
+-			if (wbc.encountered_congestion)
++			if (wbc.encountered_congestion || wbc.more_io)
+ 				congestion_wait(WRITE, HZ/10);
+ 			else
+ 				break;	/* All the old data is written */
+@@ -1064,7 +1076,7 @@ static int __set_page_dirty(struct page *page)
+ 	return 0;
+ }
+ 
+-int fastcall set_page_dirty(struct page *page)
++int set_page_dirty(struct page *page)
+ {
+ 	int ret = __set_page_dirty(page);
+ 	if (ret)
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index b2838c2..37576b8 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -537,7 +537,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
+ /*
+  * permit the bootmem allocator to evade page validation on high-order frees
+  */
+-void fastcall __init __free_pages_bootmem(struct page *page, unsigned int order)
++void __init __free_pages_bootmem(struct page *page, unsigned int order)
+ {
+ 	if (order == 0) {
+ 		__ClearPageReserved(page);
+@@ -890,31 +890,51 @@ void drain_zone_pages(struct zone *zone, struct per_cpu_pages *pcp)
+ }
+ #endif
+ 
+-static void __drain_pages(unsigned int cpu)
++/*
++ * Drain pages of the indicated processor.
++ *
++ * The processor must either be the current processor and the
++ * thread pinned to the current processor or a processor that
++ * is not online.
++ */
++static void drain_pages(unsigned int cpu)
+ {
+ 	unsigned long flags;
+ 	struct zone *zone;
+-	int i;
+ 
+ 	for_each_zone(zone) {
+ 		struct per_cpu_pageset *pset;
++		struct per_cpu_pages *pcp;
+ 
+ 		if (!populated_zone(zone))
+ 			continue;
+ 
+ 		pset = zone_pcp(zone, cpu);
+-		for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
+-			struct per_cpu_pages *pcp;
+-
+-			pcp = &pset->pcp[i];
+-			local_irq_save(flags);
+-			free_pages_bulk(zone, pcp->count, &pcp->list, 0);
+-			pcp->count = 0;
+-			local_irq_restore(flags);
+-		}
++
++		pcp = &pset->pcp;
++		local_irq_save(flags);
++		free_pages_bulk(zone, pcp->count, &pcp->list, 0);
++		pcp->count = 0;
++		local_irq_restore(flags);
+ 	}
+ }
+ 
++/*
++ * Spill all of this CPU's per-cpu pages back into the buddy allocator.
++ */
++void drain_local_pages(void *arg)
++{
++	drain_pages(smp_processor_id());
++}
++
++/*
++ * Spill all the per-cpu pages from all CPUs back into the buddy allocator
++ */
++void drain_all_pages(void)
++{
++	on_each_cpu(drain_local_pages, NULL, 0, 1);
++}
++
+ #ifdef CONFIG_HIBERNATION
+ 
+ void mark_free_pages(struct zone *zone)
+@@ -952,40 +972,9 @@ void mark_free_pages(struct zone *zone)
+ #endif /* CONFIG_PM */
+ 
+ /*
+- * Spill all of this CPU's per-cpu pages back into the buddy allocator.
+- */
+-void drain_local_pages(void)
+-{
+-	unsigned long flags;
+-
+-	local_irq_save(flags);	
+-	__drain_pages(smp_processor_id());
+-	local_irq_restore(flags);	
+-}
+-
+-void smp_drain_local_pages(void *arg)
+-{
+-	drain_local_pages();
+-}
+-
+-/*
+- * Spill all the per-cpu pages from all CPUs back into the buddy allocator
+- */
+-void drain_all_local_pages(void)
+-{
+-	unsigned long flags;
+-
+-	local_irq_save(flags);
+-	__drain_pages(smp_processor_id());
+-	local_irq_restore(flags);
+-
+-	smp_call_function(smp_drain_local_pages, NULL, 0, 1);
+-}
+-
+-/*
+  * Free a 0-order page
+  */
+-static void fastcall free_hot_cold_page(struct page *page, int cold)
++static void free_hot_cold_page(struct page *page, int cold)
+ {
+ 	struct zone *zone = page_zone(page);
+ 	struct per_cpu_pages *pcp;
+@@ -1001,10 +990,13 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
+ 	arch_free_page(page, 0);
+ 	kernel_map_pages(page, 1, 0);
+ 
+-	pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
++	pcp = &zone_pcp(zone, get_cpu())->pcp;
+ 	local_irq_save(flags);
+ 	__count_vm_event(PGFREE);
+-	list_add(&page->lru, &pcp->list);
++	if (cold)
++		list_add_tail(&page->lru, &pcp->list);
++	else
++		list_add(&page->lru, &pcp->list);
+ 	set_page_private(page, get_pageblock_migratetype(page));
+ 	pcp->count++;
+ 	if (pcp->count >= pcp->high) {
+@@ -1015,12 +1007,12 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
+ 	put_cpu();
+ }
+ 
+-void fastcall free_hot_page(struct page *page)
++void free_hot_page(struct page *page)
+ {
+ 	free_hot_cold_page(page, 0);
+ }
+ 	
+-void fastcall free_cold_page(struct page *page)
++void free_cold_page(struct page *page)
+ {
+ 	free_hot_cold_page(page, 1);
+ }
+@@ -1062,7 +1054,7 @@ again:
+ 	if (likely(order == 0)) {
+ 		struct per_cpu_pages *pcp;
+ 
+-		pcp = &zone_pcp(zone, cpu)->pcp[cold];
++		pcp = &zone_pcp(zone, cpu)->pcp;
+ 		local_irq_save(flags);
+ 		if (!pcp->count) {
+ 			pcp->count = rmqueue_bulk(zone, 0,
+@@ -1072,9 +1064,15 @@ again:
+ 		}
+ 
+ 		/* Find a page of the appropriate migrate type */
+-		list_for_each_entry(page, &pcp->list, lru)
+-			if (page_private(page) == migratetype)
+-				break;
++		if (cold) {
++			list_for_each_entry_reverse(page, &pcp->list, lru)
++				if (page_private(page) == migratetype)
++					break;
++		} else {
++			list_for_each_entry(page, &pcp->list, lru)
++				if (page_private(page) == migratetype)
++					break;
++		}
+ 
+ 		/* Allocate more to the pcp list if necessary */
+ 		if (unlikely(&page->lru == &pcp->list)) {
+@@ -1569,7 +1567,7 @@ nofail_alloc:
+ 	cond_resched();
+ 
+ 	if (order != 0)
+-		drain_all_local_pages();
++		drain_all_pages();
+ 
+ 	if (likely(did_some_progress)) {
+ 		page = get_page_from_freelist(gfp_mask, order,
+@@ -1643,7 +1641,7 @@ EXPORT_SYMBOL(__alloc_pages);
+ /*
+  * Common helper functions.
+  */
+-fastcall unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
++unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+ {
+ 	struct page * page;
+ 	page = alloc_pages(gfp_mask, order);
+@@ -1654,7 +1652,7 @@ fastcall unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
+ 
+ EXPORT_SYMBOL(__get_free_pages);
+ 
+-fastcall unsigned long get_zeroed_page(gfp_t gfp_mask)
++unsigned long get_zeroed_page(gfp_t gfp_mask)
+ {
+ 	struct page * page;
+ 
+@@ -1680,7 +1678,7 @@ void __pagevec_free(struct pagevec *pvec)
+ 		free_hot_cold_page(pvec->pages[i], pvec->cold);
+ }
+ 
+-fastcall void __free_pages(struct page *page, unsigned int order)
++void __free_pages(struct page *page, unsigned int order)
+ {
+ 	if (put_page_testzero(page)) {
+ 		if (order == 0)
+@@ -1692,7 +1690,7 @@ fastcall void __free_pages(struct page *page, unsigned int order)
+ 
+ EXPORT_SYMBOL(__free_pages);
+ 
+-fastcall void free_pages(unsigned long addr, unsigned int order)
++void free_pages(unsigned long addr, unsigned int order)
+ {
+ 	if (addr != 0) {
+ 		VM_BUG_ON(!virt_addr_valid((void *)addr));
+@@ -1801,12 +1799,9 @@ void show_free_areas(void)
+ 
+ 			pageset = zone_pcp(zone, cpu);
+ 
+-			printk("CPU %4d: Hot: hi:%5d, btch:%4d usd:%4d   "
+-			       "Cold: hi:%5d, btch:%4d usd:%4d\n",
+-			       cpu, pageset->pcp[0].high,
+-			       pageset->pcp[0].batch, pageset->pcp[0].count,
+-			       pageset->pcp[1].high, pageset->pcp[1].batch,
+-			       pageset->pcp[1].count);
++			printk("CPU %4d: hi:%5d, btch:%4d usd:%4d\n",
++			       cpu, pageset->pcp.high,
++			       pageset->pcp.batch, pageset->pcp.count);
+ 		}
+ 	}
+ 
+@@ -1879,6 +1874,8 @@ void show_free_areas(void)
+ 		printk("= %lukB\n", K(total));
+ 	}
+ 
++	printk("%ld total pagecache pages\n", global_page_state(NR_FILE_PAGES));
++
+ 	show_swap_cache_info();
+ }
+ 
+@@ -2551,8 +2548,7 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
+ 	}
+ }
+ 
+-static void __meminit zone_init_free_lists(struct pglist_data *pgdat,
+-				struct zone *zone, unsigned long size)
++static void __meminit zone_init_free_lists(struct zone *zone)
+ {
+ 	int order, t;
+ 	for_each_migratetype_order(order, t) {
+@@ -2604,17 +2600,11 @@ inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
+ 
+ 	memset(p, 0, sizeof(*p));
+ 
+-	pcp = &p->pcp[0];		/* hot */
++	pcp = &p->pcp;
+ 	pcp->count = 0;
+ 	pcp->high = 6 * batch;
+ 	pcp->batch = max(1UL, 1 * batch);
+ 	INIT_LIST_HEAD(&pcp->list);
+-
+-	pcp = &p->pcp[1];		/* cold*/
+-	pcp->count = 0;
+-	pcp->high = 2 * batch;
+-	pcp->batch = max(1UL, batch/2);
+-	INIT_LIST_HEAD(&pcp->list);
+ }
+ 
+ /*
+@@ -2627,7 +2617,7 @@ static void setup_pagelist_highmark(struct per_cpu_pageset *p,
+ {
+ 	struct per_cpu_pages *pcp;
+ 
+-	pcp = &p->pcp[0]; /* hot list */
++	pcp = &p->pcp;
+ 	pcp->high = high;
+ 	pcp->batch = max(1UL, high/4);
+ 	if ((high/4) > (PAGE_SHIFT * 8))
+@@ -2831,7 +2821,7 @@ __meminit int init_currently_empty_zone(struct zone *zone,
+ 
+ 	memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn);
+ 
+-	zone_init_free_lists(pgdat, zone, zone->spanned_pages);
++	zone_init_free_lists(zone);
+ 
+ 	return 0;
+ }
+@@ -3978,10 +3968,23 @@ static int page_alloc_cpu_notify(struct notifier_block *self,
+ 	int cpu = (unsigned long)hcpu;
+ 
+ 	if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
+-		local_irq_disable();
+-		__drain_pages(cpu);
++		drain_pages(cpu);
++
++		/*
++		 * Spill the event counters of the dead processor
++		 * into the current processors event counters.
++		 * This artificially elevates the count of the current
++		 * processor.
++		 */
+ 		vm_events_fold_cpu(cpu);
+-		local_irq_enable();
++
++		/*
++		 * Zero the differential counters of the dead processor
++		 * so that the vm statistics are consistent.
++		 *
++		 * This is only okay since the processor is dead and cannot
++		 * race with what we are doing.
++		 */
+ 		refresh_cpu_vm_stats(cpu);
+ 	}
+ 	return NOTIFY_OK;
+@@ -4480,7 +4483,7 @@ int set_migratetype_isolate(struct page *page)
+ out:
+ 	spin_unlock_irqrestore(&zone->lock, flags);
+ 	if (!ret)
+-		drain_all_local_pages();
++		drain_all_pages();
+ 	return ret;
+ }
+ 
+diff --git a/mm/page_io.c b/mm/page_io.c
+index 3b97f68..065c448 100644
+--- a/mm/page_io.c
++++ b/mm/page_io.c
+@@ -126,7 +126,7 @@ int swap_readpage(struct file *file, struct page *page)
+ 	int ret = 0;
+ 
+ 	BUG_ON(!PageLocked(page));
+-	ClearPageUptodate(page);
++	BUG_ON(PageUptodate(page));
+ 	bio = get_swap_bio(GFP_KERNEL, page_private(page), page,
+ 				end_swap_bio_read);
+ 	if (bio == NULL) {
+diff --git a/mm/pagewalk.c b/mm/pagewalk.c
+new file mode 100644
+index 0000000..b4f27d2
+--- /dev/null
++++ b/mm/pagewalk.c
+@@ -0,0 +1,131 @@
++#include <linux/mm.h>
++#include <linux/highmem.h>
++#include <linux/sched.h>
++
++static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
++			  const struct mm_walk *walk, void *private)
++{
++	pte_t *pte;
++	int err = 0;
++
++	pte = pte_offset_map(pmd, addr);
++	do {
++		err = walk->pte_entry(pte, addr, addr + PAGE_SIZE, private);
++		if (err)
++		       break;
++	} while (pte++, addr += PAGE_SIZE, addr != end);
++
++	pte_unmap(pte);
++	return err;
++}
++
++static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
++			  const struct mm_walk *walk, void *private)
++{
++	pmd_t *pmd;
++	unsigned long next;
++	int err = 0;
++
++	pmd = pmd_offset(pud, addr);
++	do {
++		next = pmd_addr_end(addr, end);
++		if (pmd_none_or_clear_bad(pmd)) {
++			if (walk->pte_hole)
++				err = walk->pte_hole(addr, next, private);
++			if (err)
++				break;
++			continue;
++		}
++		if (walk->pmd_entry)
++			err = walk->pmd_entry(pmd, addr, next, private);
++		if (!err && walk->pte_entry)
++			err = walk_pte_range(pmd, addr, next, walk, private);
++		if (err)
++			break;
++	} while (pmd++, addr = next, addr != end);
++
++	return err;
++}
++
++static int walk_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end,
++			  const struct mm_walk *walk, void *private)
++{
++	pud_t *pud;
++	unsigned long next;
++	int err = 0;
++
++	pud = pud_offset(pgd, addr);
++	do {
++		next = pud_addr_end(addr, end);
++		if (pud_none_or_clear_bad(pud)) {
++			if (walk->pte_hole)
++				err = walk->pte_hole(addr, next, private);
++			if (err)
++				break;
++			continue;
++		}
++		if (walk->pud_entry)
++			err = walk->pud_entry(pud, addr, next, private);
++		if (!err && (walk->pmd_entry || walk->pte_entry))
++			err = walk_pmd_range(pud, addr, next, walk, private);
++		if (err)
++			break;
++	} while (pud++, addr = next, addr != end);
++
++	return err;
++}
++
++/**
++ * walk_page_range - walk a memory map's page tables with a callback
++ * @mm - memory map to walk
++ * @addr - starting address
++ * @end - ending address
++ * @walk - set of callbacks to invoke for each level of the tree
++ * @private - private data passed to the callback function
++ *
++ * Recursively walk the page table for the memory area in a VMA,
++ * calling supplied callbacks. Callbacks are called in-order (first
++ * PGD, first PUD, first PMD, first PTE, second PTE... second PMD,
++ * etc.). If lower-level callbacks are omitted, walking depth is reduced.
++ *
++ * Each callback receives an entry pointer, the start and end of the
++ * associated range, and a caller-supplied private data pointer.
++ *
++ * No locks are taken, but the bottom level iterator will map PTE
++ * directories from highmem if necessary.
++ *
++ * If any callback returns a non-zero value, the walk is aborted and
++ * the return value is propagated back to the caller. Otherwise 0 is returned.
++ */
++int walk_page_range(const struct mm_struct *mm,
++		    unsigned long addr, unsigned long end,
++		    const struct mm_walk *walk, void *private)
++{
++	pgd_t *pgd;
++	unsigned long next;
++	int err = 0;
++
++	if (addr >= end)
++		return err;
++
++	pgd = pgd_offset(mm, addr);
++	do {
++		next = pgd_addr_end(addr, end);
++		if (pgd_none_or_clear_bad(pgd)) {
++			if (walk->pte_hole)
++				err = walk->pte_hole(addr, next, private);
++			if (err)
++				break;
++			continue;
++		}
++		if (walk->pgd_entry)
++			err = walk->pgd_entry(pgd, addr, next, private);
++		if (!err &&
++		    (walk->pud_entry || walk->pmd_entry || walk->pte_entry))
++			err = walk_pud_range(pgd, addr, next, walk, private);
++		if (err)
++			break;
++	} while (pgd++, addr = next, addr != end);
++
++	return err;
++}
+diff --git a/mm/rmap.c b/mm/rmap.c
+index dbc2ca2..57ad276 100644
+--- a/mm/rmap.c
++++ b/mm/rmap.c
+@@ -36,7 +36,6 @@
+  *                 mapping->tree_lock (widely used, in set_page_dirty,
+  *                           in arch-dependent flush_dcache_mmap_lock,
+  *                           within inode_lock in __sync_single_inode)
+- *                   zone->lock (within radix tree node alloc)
+  */
+ 
+ #include <linux/mm.h>
+@@ -284,7 +283,10 @@ static int page_referenced_one(struct page *page,
+ 	if (!pte)
+ 		goto out;
+ 
+-	if (ptep_clear_flush_young(vma, address, pte))
++	if (vma->vm_flags & VM_LOCKED) {
++		referenced++;
++		*mapcount = 1;	/* break early from loop */
++	} else if (ptep_clear_flush_young(vma, address, pte))
+ 		referenced++;
+ 
+ 	/* Pretend the page is referenced if the task has the
+diff --git a/mm/shmem.c b/mm/shmem.c
+index 51b3d6c..0f246c4 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -78,11 +78,10 @@
+ 
+ /* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
+ enum sgp_type {
+-	SGP_QUICK,	/* don't try more than file page cache lookup */
+ 	SGP_READ,	/* don't exceed i_size, don't allocate page */
+ 	SGP_CACHE,	/* don't exceed i_size, may allocate page */
++	SGP_DIRTY,	/* like SGP_CACHE, but set new page dirty */
+ 	SGP_WRITE,	/* may exceed i_size, may allocate page */
+-	SGP_FAULT,	/* same as SGP_CACHE, return with page locked */
+ };
+ 
+ static int shmem_getpage(struct inode *inode, unsigned long idx,
+@@ -194,7 +193,7 @@ static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
+ };
+ 
+ static LIST_HEAD(shmem_swaplist);
+-static DEFINE_SPINLOCK(shmem_swaplist_lock);
++static DEFINE_MUTEX(shmem_swaplist_mutex);
+ 
+ static void shmem_free_blocks(struct inode *inode, long pages)
+ {
+@@ -207,6 +206,31 @@ static void shmem_free_blocks(struct inode *inode, long pages)
+ 	}
+ }
+ 
++static int shmem_reserve_inode(struct super_block *sb)
++{
++	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++	if (sbinfo->max_inodes) {
++		spin_lock(&sbinfo->stat_lock);
++		if (!sbinfo->free_inodes) {
++			spin_unlock(&sbinfo->stat_lock);
++			return -ENOSPC;
++		}
++		sbinfo->free_inodes--;
++		spin_unlock(&sbinfo->stat_lock);
++	}
++	return 0;
++}
++
++static void shmem_free_inode(struct super_block *sb)
++{
++	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
++	if (sbinfo->max_inodes) {
++		spin_lock(&sbinfo->stat_lock);
++		sbinfo->free_inodes++;
++		spin_unlock(&sbinfo->stat_lock);
++	}
++}
++
+ /*
+  * shmem_recalc_inode - recalculate the size of an inode
+  *
+@@ -731,6 +755,8 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
+ 				(void) shmem_getpage(inode,
+ 					attr->ia_size>>PAGE_CACHE_SHIFT,
+ 						&page, SGP_READ, NULL);
++				if (page)
++					unlock_page(page);
+ 			}
+ 			/*
+ 			 * Reset SHMEM_PAGEIN flag so that shmem_truncate can
+@@ -762,7 +788,6 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
+ 
+ static void shmem_delete_inode(struct inode *inode)
+ {
+-	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+ 	struct shmem_inode_info *info = SHMEM_I(inode);
+ 
+ 	if (inode->i_op->truncate == shmem_truncate) {
+@@ -771,17 +796,13 @@ static void shmem_delete_inode(struct inode *inode)
+ 		inode->i_size = 0;
+ 		shmem_truncate(inode);
+ 		if (!list_empty(&info->swaplist)) {
+-			spin_lock(&shmem_swaplist_lock);
++			mutex_lock(&shmem_swaplist_mutex);
+ 			list_del_init(&info->swaplist);
+-			spin_unlock(&shmem_swaplist_lock);
++			mutex_unlock(&shmem_swaplist_mutex);
+ 		}
+ 	}
+ 	BUG_ON(inode->i_blocks);
+-	if (sbinfo->max_inodes) {
+-		spin_lock(&sbinfo->stat_lock);
+-		sbinfo->free_inodes++;
+-		spin_unlock(&sbinfo->stat_lock);
+-	}
++	shmem_free_inode(inode->i_sb);
+ 	clear_inode(inode);
+ }
+ 
+@@ -807,19 +828,22 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
+ 	struct page *subdir;
+ 	swp_entry_t *ptr;
+ 	int offset;
++	int error;
+ 
+ 	idx = 0;
+ 	ptr = info->i_direct;
+ 	spin_lock(&info->lock);
++	if (!info->swapped) {
++		list_del_init(&info->swaplist);
++		goto lost2;
++	}
+ 	limit = info->next_index;
+ 	size = limit;
+ 	if (size > SHMEM_NR_DIRECT)
+ 		size = SHMEM_NR_DIRECT;
+ 	offset = shmem_find_swp(entry, ptr, ptr+size);
+-	if (offset >= 0) {
+-		shmem_swp_balance_unmap();
++	if (offset >= 0)
+ 		goto found;
+-	}
+ 	if (!info->i_indirect)
+ 		goto lost2;
+ 
+@@ -829,6 +853,14 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
+ 	for (idx = SHMEM_NR_DIRECT; idx < limit; idx += ENTRIES_PER_PAGE, dir++) {
+ 		if (unlikely(idx == stage)) {
+ 			shmem_dir_unmap(dir-1);
++			if (cond_resched_lock(&info->lock)) {
++				/* check it has not been truncated */
++				if (limit > info->next_index) {
++					limit = info->next_index;
++					if (idx >= limit)
++						goto lost2;
++				}
++			}
+ 			dir = shmem_dir_map(info->i_indirect) +
+ 			    ENTRIES_PER_PAGE/2 + idx/ENTRIES_PER_PAGEPAGE;
+ 			while (!*dir) {
+@@ -849,11 +881,11 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
+ 			if (size > ENTRIES_PER_PAGE)
+ 				size = ENTRIES_PER_PAGE;
+ 			offset = shmem_find_swp(entry, ptr, ptr+size);
++			shmem_swp_unmap(ptr);
+ 			if (offset >= 0) {
+ 				shmem_dir_unmap(dir);
+ 				goto found;
+ 			}
+-			shmem_swp_unmap(ptr);
+ 		}
+ 	}
+ lost1:
+@@ -863,19 +895,63 @@ lost2:
+ 	return 0;
+ found:
+ 	idx += offset;
+-	inode = &info->vfs_inode;
+-	if (move_from_swap_cache(page, idx, inode->i_mapping) == 0) {
+-		info->flags |= SHMEM_PAGEIN;
+-		shmem_swp_set(info, ptr + offset, 0);
+-	}
+-	shmem_swp_unmap(ptr);
++	inode = igrab(&info->vfs_inode);
+ 	spin_unlock(&info->lock);
++
+ 	/*
+-	 * Decrement swap count even when the entry is left behind:
+-	 * try_to_unuse will skip over mms, then reincrement count.
++	 * Move _head_ to start search for next from here.
++	 * But be careful: shmem_delete_inode checks list_empty without taking
++	 * mutex, and there's an instant in list_move_tail when info->swaplist
++	 * would appear empty, if it were the only one on shmem_swaplist.  We
++	 * could avoid doing it if inode NULL; or use this minor optimization.
+ 	 */
+-	swap_free(entry);
+-	return 1;
++	if (shmem_swaplist.next != &info->swaplist)
++		list_move_tail(&shmem_swaplist, &info->swaplist);
++	mutex_unlock(&shmem_swaplist_mutex);
++
++	error = 1;
++	if (!inode)
++		goto out;
++	error = radix_tree_preload(GFP_KERNEL);
++	if (error)
++		goto out;
++	error = 1;
++
++	spin_lock(&info->lock);
++	ptr = shmem_swp_entry(info, idx, NULL);
++	if (ptr && ptr->val == entry.val)
++		error = add_to_page_cache(page, inode->i_mapping,
++						idx, GFP_NOWAIT);
++	if (error == -EEXIST) {
++		struct page *filepage = find_get_page(inode->i_mapping, idx);
++		error = 1;
++		if (filepage) {
++			/*
++			 * There might be a more uptodate page coming down
++			 * from a stacked writepage: forget our swappage if so.
++			 */
++			if (PageUptodate(filepage))
++				error = 0;
++			page_cache_release(filepage);
++		}
++	}
++	if (!error) {
++		delete_from_swap_cache(page);
++		set_page_dirty(page);
++		info->flags |= SHMEM_PAGEIN;
++		shmem_swp_set(info, ptr, 0);
++		swap_free(entry);
++		error = 1;	/* not an error, but entry was found */
++	}
++	if (ptr)
++		shmem_swp_unmap(ptr);
++	spin_unlock(&info->lock);
++	radix_tree_preload_end();
++out:
++	unlock_page(page);
++	page_cache_release(page);
++	iput(inode);		/* allows for NULL */
++	return error;
+ }
+ 
+ /*
+@@ -887,20 +963,16 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
+ 	struct shmem_inode_info *info;
+ 	int found = 0;
+ 
+-	spin_lock(&shmem_swaplist_lock);
++	mutex_lock(&shmem_swaplist_mutex);
+ 	list_for_each_safe(p, next, &shmem_swaplist) {
+ 		info = list_entry(p, struct shmem_inode_info, swaplist);
+-		if (!info->swapped)
+-			list_del_init(&info->swaplist);
+-		else if (shmem_unuse_inode(info, entry, page)) {
+-			/* move head to start search for next from here */
+-			list_move_tail(&shmem_swaplist, &info->swaplist);
+-			found = 1;
+-			break;
+-		}
++		found = shmem_unuse_inode(info, entry, page);
++		cond_resched();
++		if (found)
++			goto out;
+ 	}
+-	spin_unlock(&shmem_swaplist_lock);
+-	return found;
++	mutex_unlock(&shmem_swaplist_mutex);
++out:	return found;	/* 0 or 1 or -ENOMEM */
+ }
+ 
+ /*
+@@ -915,54 +987,65 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
+ 	struct inode *inode;
+ 
+ 	BUG_ON(!PageLocked(page));
+-	/*
+-	 * shmem_backing_dev_info's capabilities prevent regular writeback or
+-	 * sync from ever calling shmem_writepage; but a stacking filesystem
+-	 * may use the ->writepage of its underlying filesystem, in which case
+-	 * we want to do nothing when that underlying filesystem is tmpfs
+-	 * (writing out to swap is useful as a response to memory pressure, but
+-	 * of no use to stabilize the data) - just redirty the page, unlock it
+-	 * and claim success in this case.  AOP_WRITEPAGE_ACTIVATE, and the
+-	 * page_mapped check below, must be avoided unless we're in reclaim.
+-	 */
+-	if (!wbc->for_reclaim) {
+-		set_page_dirty(page);
+-		unlock_page(page);
+-		return 0;
+-	}
+-	BUG_ON(page_mapped(page));
+-
+ 	mapping = page->mapping;
+ 	index = page->index;
+ 	inode = mapping->host;
+ 	info = SHMEM_I(inode);
+ 	if (info->flags & VM_LOCKED)
+ 		goto redirty;
+-	swap = get_swap_page();
+-	if (!swap.val)
++	if (!total_swap_pages)
+ 		goto redirty;
+ 
++	/*
++	 * shmem_backing_dev_info's capabilities prevent regular writeback or
++	 * sync from ever calling shmem_writepage; but a stacking filesystem
++	 * may use the ->writepage of its underlying filesystem, in which case
++	 * tmpfs should write out to swap only in response to memory pressure,
++	 * and not for pdflush or sync.  However, in those cases, we do still
++	 * want to check if there's a redundant swappage to be discarded.
++	 */
++	if (wbc->for_reclaim)
++		swap = get_swap_page();
++	else
++		swap.val = 0;
++
+ 	spin_lock(&info->lock);
+-	shmem_recalc_inode(inode);
+ 	if (index >= info->next_index) {
+ 		BUG_ON(!(info->flags & SHMEM_TRUNCATE));
+ 		goto unlock;
+ 	}
+ 	entry = shmem_swp_entry(info, index, NULL);
+-	BUG_ON(!entry);
+-	BUG_ON(entry->val);
++	if (entry->val) {
++		/*
++		 * The more uptodate page coming down from a stacked
++		 * writepage should replace our old swappage.
++		 */
++		free_swap_and_cache(*entry);
++		shmem_swp_set(info, entry, 0);
++	}
++	shmem_recalc_inode(inode);
+ 
+-	if (move_to_swap_cache(page, swap) == 0) {
++	if (swap.val && add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
++		remove_from_page_cache(page);
+ 		shmem_swp_set(info, entry, swap.val);
+ 		shmem_swp_unmap(entry);
++		if (list_empty(&info->swaplist))
++			inode = igrab(inode);
++		else
++			inode = NULL;
+ 		spin_unlock(&info->lock);
+-		if (list_empty(&info->swaplist)) {
+-			spin_lock(&shmem_swaplist_lock);
++		swap_duplicate(swap);
++		BUG_ON(page_mapped(page));
++		page_cache_release(page);	/* pagecache ref */
++		set_page_dirty(page);
++		unlock_page(page);
++		if (inode) {
++			mutex_lock(&shmem_swaplist_mutex);
+ 			/* move instead of add in case we're racing */
+ 			list_move_tail(&info->swaplist, &shmem_swaplist);
+-			spin_unlock(&shmem_swaplist_lock);
++			mutex_unlock(&shmem_swaplist_mutex);
++			iput(inode);
+ 		}
+-		unlock_page(page);
+ 		return 0;
+ 	}
+ 
+@@ -972,7 +1055,10 @@ unlock:
+ 	swap_free(swap);
+ redirty:
+ 	set_page_dirty(page);
+-	return AOP_WRITEPAGE_ACTIVATE;	/* Return with the page locked */
++	if (wbc->for_reclaim)
++		return AOP_WRITEPAGE_ACTIVATE;	/* Return with page locked */
++	unlock_page(page);
++	return 0;
+ }
+ 
+ #ifdef CONFIG_NUMA
+@@ -1025,53 +1111,33 @@ out:
+ 	return err;
+ }
+ 
+-static struct page *shmem_swapin_async(struct shared_policy *p,
+-				       swp_entry_t entry, unsigned long idx)
++static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
++			struct shmem_inode_info *info, unsigned long idx)
+ {
+-	struct page *page;
+ 	struct vm_area_struct pvma;
++	struct page *page;
+ 
+ 	/* Create a pseudo vma that just contains the policy */
+-	memset(&pvma, 0, sizeof(struct vm_area_struct));
+-	pvma.vm_end = PAGE_SIZE;
++	pvma.vm_start = 0;
+ 	pvma.vm_pgoff = idx;
+-	pvma.vm_policy = mpol_shared_policy_lookup(p, idx);
+-	page = read_swap_cache_async(entry, &pvma, 0);
++	pvma.vm_ops = NULL;
++	pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
++	page = swapin_readahead(entry, gfp, &pvma, 0);
+ 	mpol_free(pvma.vm_policy);
+ 	return page;
+ }
+ 
+-static struct page *shmem_swapin(struct shmem_inode_info *info,
+-				 swp_entry_t entry, unsigned long idx)
+-{
+-	struct shared_policy *p = &info->policy;
+-	int i, num;
+-	struct page *page;
+-	unsigned long offset;
+-
+-	num = valid_swaphandles(entry, &offset);
+-	for (i = 0; i < num; offset++, i++) {
+-		page = shmem_swapin_async(p,
+-				swp_entry(swp_type(entry), offset), idx);
+-		if (!page)
+-			break;
+-		page_cache_release(page);
+-	}
+-	lru_add_drain();	/* Push any new pages onto the LRU now */
+-	return shmem_swapin_async(p, entry, idx);
+-}
+-
+-static struct page *
+-shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info,
+-		 unsigned long idx)
++static struct page *shmem_alloc_page(gfp_t gfp,
++			struct shmem_inode_info *info, unsigned long idx)
+ {
+ 	struct vm_area_struct pvma;
+ 	struct page *page;
+ 
+-	memset(&pvma, 0, sizeof(struct vm_area_struct));
+-	pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
++	/* Create a pseudo vma that just contains the policy */
++	pvma.vm_start = 0;
+ 	pvma.vm_pgoff = idx;
+-	pvma.vm_end = PAGE_SIZE;
++	pvma.vm_ops = NULL;
++	pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx);
+ 	page = alloc_page_vma(gfp, &pvma, 0);
+ 	mpol_free(pvma.vm_policy);
+ 	return page;
+@@ -1083,15 +1149,14 @@ static inline int shmem_parse_mpol(char *value, int *policy,
+ 	return 1;
+ }
+ 
+-static inline struct page *
+-shmem_swapin(struct shmem_inode_info *info,swp_entry_t entry,unsigned long idx)
++static inline struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp,
++			struct shmem_inode_info *info, unsigned long idx)
+ {
+-	swapin_readahead(entry, 0, NULL);
+-	return read_swap_cache_async(entry, NULL, 0);
++	return swapin_readahead(entry, gfp, NULL, 0);
+ }
+ 
+-static inline struct page *
+-shmem_alloc_page(gfp_t gfp,struct shmem_inode_info *info, unsigned long idx)
++static inline struct page *shmem_alloc_page(gfp_t gfp,
++			struct shmem_inode_info *info, unsigned long idx)
+ {
+ 	return alloc_page(gfp);
+ }
+@@ -1114,6 +1179,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
+ 	struct page *swappage;
+ 	swp_entry_t *entry;
+ 	swp_entry_t swap;
++	gfp_t gfp;
+ 	int error;
+ 
+ 	if (idx >= SHMEM_MAX_INDEX)
+@@ -1126,7 +1192,7 @@ static int shmem_getpage(struct inode *inode, unsigned long idx,
+ 	 * Normally, filepage is NULL on entry, and either found
+ 	 * uptodate immediately, or allocated and zeroed, or read
+ 	 * in under swappage, which is then assigned to filepage.
+-	 * But shmem_readpage and shmem_write_begin pass in a locked
++	 * But shmem_readpage (required for splice) passes in a locked
+ 	 * filepage, which may be found not uptodate by other callers
+ 	 * too, and may need to be copied from the swappage read in.
+ 	 */
+@@ -1136,8 +1202,17 @@ repeat:
+ 	if (filepage && PageUptodate(filepage))
+ 		goto done;
+ 	error = 0;
+-	if (sgp == SGP_QUICK)
+-		goto failed;
++	gfp = mapping_gfp_mask(mapping);
++	if (!filepage) {
++		/*
++		 * Try to preload while we can wait, to not make a habit of
++		 * draining atomic reserves; but don't latch on to this cpu.
++		 */
++		error = radix_tree_preload(gfp & ~__GFP_HIGHMEM);
++		if (error)
++			goto failed;
++		radix_tree_preload_end();
++	}
+ 
+ 	spin_lock(&info->lock);
+ 	shmem_recalc_inode(inode);
+@@ -1160,7 +1235,7 @@ repeat:
+ 				*type |= VM_FAULT_MAJOR;
+ 			}
+ 			spin_unlock(&info->lock);
+-			swappage = shmem_swapin(info, swap, idx);
++			swappage = shmem_swapin(swap, gfp, info, idx);
+ 			if (!swappage) {
+ 				spin_lock(&info->lock);
+ 				entry = shmem_swp_alloc(info, idx, sgp);
+@@ -1218,23 +1293,21 @@ repeat:
+ 			SetPageUptodate(filepage);
+ 			set_page_dirty(filepage);
+ 			swap_free(swap);
+-		} else if (!(error = move_from_swap_cache(
+-				swappage, idx, mapping))) {
++		} else if (!(error = add_to_page_cache(
++				swappage, mapping, idx, GFP_NOWAIT))) {
+ 			info->flags |= SHMEM_PAGEIN;
+ 			shmem_swp_set(info, entry, 0);
+ 			shmem_swp_unmap(entry);
++			delete_from_swap_cache(swappage);
+ 			spin_unlock(&info->lock);
+ 			filepage = swappage;
++			set_page_dirty(filepage);
+ 			swap_free(swap);
+ 		} else {
+ 			shmem_swp_unmap(entry);
+ 			spin_unlock(&info->lock);
+ 			unlock_page(swappage);
+ 			page_cache_release(swappage);
+-			if (error == -ENOMEM) {
+-				/* let kswapd refresh zone for GFP_ATOMICs */
+-				congestion_wait(WRITE, HZ/50);
+-			}
+ 			goto repeat;
+ 		}
+ 	} else if (sgp == SGP_READ && !filepage) {
+@@ -1272,9 +1345,7 @@ repeat:
+ 
+ 		if (!filepage) {
+ 			spin_unlock(&info->lock);
+-			filepage = shmem_alloc_page(mapping_gfp_mask(mapping),
+-						    info,
+-						    idx);
++			filepage = shmem_alloc_page(gfp, info, idx);
+ 			if (!filepage) {
+ 				shmem_unacct_blocks(info->flags, 1);
+ 				shmem_free_blocks(inode, 1);
+@@ -1291,7 +1362,7 @@ repeat:
+ 				shmem_swp_unmap(entry);
+ 			}
+ 			if (error || swap.val || 0 != add_to_page_cache_lru(
+-					filepage, mapping, idx, GFP_ATOMIC)) {
++					filepage, mapping, idx, GFP_NOWAIT)) {
+ 				spin_unlock(&info->lock);
+ 				page_cache_release(filepage);
+ 				shmem_unacct_blocks(info->flags, 1);
+@@ -1309,14 +1380,11 @@ repeat:
+ 		clear_highpage(filepage);
+ 		flush_dcache_page(filepage);
+ 		SetPageUptodate(filepage);
++		if (sgp == SGP_DIRTY)
++			set_page_dirty(filepage);
+ 	}
+ done:
+-	if (*pagep != filepage) {
+-		*pagep = filepage;
+-		if (sgp != SGP_FAULT)
+-			unlock_page(filepage);
+-
+-	}
++	*pagep = filepage;
+ 	return 0;
+ 
+ failed:
+@@ -1336,7 +1404,7 @@ static int shmem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+ 	if (((loff_t)vmf->pgoff << PAGE_CACHE_SHIFT) >= i_size_read(inode))
+ 		return VM_FAULT_SIGBUS;
+ 
+-	error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_FAULT, &ret);
++	error = shmem_getpage(inode, vmf->pgoff, &vmf->page, SGP_CACHE, &ret);
+ 	if (error)
+ 		return ((error == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS);
+ 
+@@ -1399,15 +1467,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+ 	struct shmem_inode_info *info;
+ 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
+ 
+-	if (sbinfo->max_inodes) {
+-		spin_lock(&sbinfo->stat_lock);
+-		if (!sbinfo->free_inodes) {
+-			spin_unlock(&sbinfo->stat_lock);
+-			return NULL;
+-		}
+-		sbinfo->free_inodes--;
+-		spin_unlock(&sbinfo->stat_lock);
+-	}
++	if (shmem_reserve_inode(sb))
++		return NULL;
+ 
+ 	inode = new_inode(sb);
+ 	if (inode) {
+@@ -1451,11 +1512,8 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
+ 						NULL);
+ 			break;
+ 		}
+-	} else if (sbinfo->max_inodes) {
+-		spin_lock(&sbinfo->stat_lock);
+-		sbinfo->free_inodes++;
+-		spin_unlock(&sbinfo->stat_lock);
+-	}
++	} else
++		shmem_free_inode(sb);
+ 	return inode;
+ }
+ 
+@@ -1494,123 +1552,30 @@ shmem_write_end(struct file *file, struct address_space *mapping,
+ {
+ 	struct inode *inode = mapping->host;
+ 
++	if (pos + copied > inode->i_size)
++		i_size_write(inode, pos + copied);
++
++	unlock_page(page);
+ 	set_page_dirty(page);
+ 	page_cache_release(page);
+ 
+-	if (pos+copied > inode->i_size)
+-		i_size_write(inode, pos+copied);
+-
+ 	return copied;
+ }
+ 
+-static ssize_t
+-shmem_file_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+-{
+-	struct inode	*inode = file->f_path.dentry->d_inode;
+-	loff_t		pos;
+-	unsigned long	written;
+-	ssize_t		err;
+-
+-	if ((ssize_t) count < 0)
+-		return -EINVAL;
+-
+-	if (!access_ok(VERIFY_READ, buf, count))
+-		return -EFAULT;
+-
+-	mutex_lock(&inode->i_mutex);
+-
+-	pos = *ppos;
+-	written = 0;
+-
+-	err = generic_write_checks(file, &pos, &count, 0);
+-	if (err || !count)
+-		goto out;
+-
+-	err = remove_suid(file->f_path.dentry);
+-	if (err)
+-		goto out;
+-
+-	inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+-
+-	do {
+-		struct page *page = NULL;
+-		unsigned long bytes, index, offset;
+-		char *kaddr;
+-		int left;
+-
+-		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+-		index = pos >> PAGE_CACHE_SHIFT;
+-		bytes = PAGE_CACHE_SIZE - offset;
+-		if (bytes > count)
+-			bytes = count;
+-
+-		/*
+-		 * We don't hold page lock across copy from user -
+-		 * what would it guard against? - so no deadlock here.
+-		 * But it still may be a good idea to prefault below.
+-		 */
+-
+-		err = shmem_getpage(inode, index, &page, SGP_WRITE, NULL);
+-		if (err)
+-			break;
+-
+-		left = bytes;
+-		if (PageHighMem(page)) {
+-			volatile unsigned char dummy;
+-			__get_user(dummy, buf);
+-			__get_user(dummy, buf + bytes - 1);
+-
+-			kaddr = kmap_atomic(page, KM_USER0);
+-			left = __copy_from_user_inatomic(kaddr + offset,
+-							buf, bytes);
+-			kunmap_atomic(kaddr, KM_USER0);
+-		}
+-		if (left) {
+-			kaddr = kmap(page);
+-			left = __copy_from_user(kaddr + offset, buf, bytes);
+-			kunmap(page);
+-		}
+-
+-		written += bytes;
+-		count -= bytes;
+-		pos += bytes;
+-		buf += bytes;
+-		if (pos > inode->i_size)
+-			i_size_write(inode, pos);
+-
+-		flush_dcache_page(page);
+-		set_page_dirty(page);
+-		mark_page_accessed(page);
+-		page_cache_release(page);
+-
+-		if (left) {
+-			pos -= left;
+-			written -= left;
+-			err = -EFAULT;
+-			break;
+-		}
+-
+-		/*
+-		 * Our dirty pages are not counted in nr_dirty,
+-		 * and we do not attempt to balance dirty pages.
+-		 */
+-
+-		cond_resched();
+-	} while (count);
+-
+-	*ppos = pos;
+-	if (written)
+-		err = written;
+-out:
+-	mutex_unlock(&inode->i_mutex);
+-	return err;
+-}
+-
+ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_t *desc, read_actor_t actor)
+ {
+ 	struct inode *inode = filp->f_path.dentry->d_inode;
+ 	struct address_space *mapping = inode->i_mapping;
+ 	unsigned long index, offset;
++	enum sgp_type sgp = SGP_READ;
++
++	/*
++	 * Might this read be for a stacking filesystem?  Then when reading
++	 * holes of a sparse file, we actually need to allocate those pages,
++	 * and even mark them dirty, so it cannot exceed the max_blocks limit.
++	 */
++	if (segment_eq(get_fs(), KERNEL_DS))
++		sgp = SGP_DIRTY;
+ 
+ 	index = *ppos >> PAGE_CACHE_SHIFT;
+ 	offset = *ppos & ~PAGE_CACHE_MASK;
+@@ -1629,12 +1594,14 @@ static void do_shmem_file_read(struct file *filp, loff_t *ppos, read_descriptor_
+ 				break;
+ 		}
+ 
+-		desc->error = shmem_getpage(inode, index, &page, SGP_READ, NULL);
++		desc->error = shmem_getpage(inode, index, &page, sgp, NULL);
+ 		if (desc->error) {
+ 			if (desc->error == -EINVAL)
+ 				desc->error = 0;
+ 			break;
+ 		}
++		if (page)
++			unlock_page(page);
+ 
+ 		/*
+ 		 * We must evaluate after, since reads (unlike writes)
+@@ -1798,22 +1765,16 @@ static int shmem_create(struct inode *dir, struct dentry *dentry, int mode,
+ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
+ {
+ 	struct inode *inode = old_dentry->d_inode;
+-	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
++	int ret;
+ 
+ 	/*
+ 	 * No ordinary (disk based) filesystem counts links as inodes;
+ 	 * but each new link needs a new dentry, pinning lowmem, and
+ 	 * tmpfs dentries cannot be pruned until they are unlinked.
+ 	 */
+-	if (sbinfo->max_inodes) {
+-		spin_lock(&sbinfo->stat_lock);
+-		if (!sbinfo->free_inodes) {
+-			spin_unlock(&sbinfo->stat_lock);
+-			return -ENOSPC;
+-		}
+-		sbinfo->free_inodes--;
+-		spin_unlock(&sbinfo->stat_lock);
+-	}
++	ret = shmem_reserve_inode(inode->i_sb);
++	if (ret)
++		goto out;
+ 
+ 	dir->i_size += BOGO_DIRENT_SIZE;
+ 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+@@ -1821,21 +1782,16 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
+ 	atomic_inc(&inode->i_count);	/* New dentry reference */
+ 	dget(dentry);		/* Extra pinning count for the created dentry */
+ 	d_instantiate(dentry, inode);
+-	return 0;
++out:
++	return ret;
+ }
+ 
+ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
+ {
+ 	struct inode *inode = dentry->d_inode;
+ 
+-	if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
+-		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
+-		if (sbinfo->max_inodes) {
+-			spin_lock(&sbinfo->stat_lock);
+-			sbinfo->free_inodes++;
+-			spin_unlock(&sbinfo->stat_lock);
+-		}
+-	}
++	if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode))
++		shmem_free_inode(inode->i_sb);
+ 
+ 	dir->i_size -= BOGO_DIRENT_SIZE;
+ 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+@@ -1924,6 +1880,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
+ 			iput(inode);
+ 			return error;
+ 		}
++		unlock_page(page);
+ 		inode->i_op = &shmem_symlink_inode_operations;
+ 		kaddr = kmap_atomic(page, KM_USER0);
+ 		memcpy(kaddr, symname, len);
+@@ -1951,6 +1908,8 @@ static void *shmem_follow_link(struct dentry *dentry, struct nameidata *nd)
+ 	struct page *page = NULL;
+ 	int res = shmem_getpage(dentry->d_inode, 0, &page, SGP_READ, NULL);
+ 	nd_set_link(nd, res ? ERR_PTR(res) : kmap(page));
++	if (page)
++		unlock_page(page);
+ 	return page;
+ }
+ 
+@@ -1996,8 +1955,7 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name,
+ {
+ 	if (strcmp(name, "") == 0)
+ 		return -EINVAL;
+-	return security_inode_getsecurity(inode, name, buffer, size,
+-					  -EOPNOTSUPP);
++	return xattr_getsecurity(inode, name, buffer, size);
+ }
+ 
+ static int shmem_xattr_security_set(struct inode *inode, const char *name,
+@@ -2138,7 +2096,7 @@ static int shmem_parse_options(char *options, int *mode, uid_t *uid,
+ 			}
+ 			if (*rest)
+ 				goto bad_val;
+-			*blocks = size >> PAGE_CACHE_SHIFT;
++			*blocks = DIV_ROUND_UP(size, PAGE_CACHE_SIZE);
+ 		} else if (!strcmp(this_char,"nr_blocks")) {
+ 			*blocks = memparse(value,&rest);
+ 			if (*rest)
+@@ -2375,7 +2333,8 @@ static const struct file_operations shmem_file_operations = {
+ #ifdef CONFIG_TMPFS
+ 	.llseek		= generic_file_llseek,
+ 	.read		= shmem_file_read,
+-	.write		= shmem_file_write,
++	.write		= do_sync_write,
++	.aio_write	= generic_file_aio_write,
+ 	.fsync		= simple_sync_file,
+ 	.splice_read	= generic_file_splice_read,
+ 	.splice_write	= generic_file_splice_write,
 diff --git a/mm/slab.c b/mm/slab.c
 index b03b2e4..40c00da 100644
 --- a/mm/slab.c
@@ -904024,11 +981176,655 @@
  }
  EXPORT_SYMBOL(kmem_cache_destroy);
  
+diff --git a/mm/slob.c b/mm/slob.c
+index 773a7aa..e2c3c0e 100644
+--- a/mm/slob.c
++++ b/mm/slob.c
+@@ -12,10 +12,17 @@
+  * allocator is as little as 2 bytes, however typically most architectures
+  * will require 4 bytes on 32-bit and 8 bytes on 64-bit.
+  *
+- * The slob heap is a linked list of pages from alloc_pages(), and
+- * within each page, there is a singly-linked list of free blocks (slob_t).
+- * The heap is grown on demand and allocation from the heap is currently
+- * first-fit.
++ * The slob heap is a set of linked list of pages from alloc_pages(),
++ * and within each page, there is a singly-linked list of free blocks
++ * (slob_t). The heap is grown on demand. To reduce fragmentation,
++ * heap pages are segregated into three lists, with objects less than
++ * 256 bytes, objects less than 1024 bytes, and all other objects.
++ *
++ * Allocation from heap involves first searching for a page with
++ * sufficient free blocks (using a next-fit-like approach) followed by
++ * a first-fit scan of the page. Deallocation inserts objects back
++ * into the free list in address order, so this is effectively an
++ * address-ordered first fit.
+  *
+  * Above this is an implementation of kmalloc/kfree. Blocks returned
+  * from kmalloc are prepended with a 4-byte header with the kmalloc size.
+@@ -110,9 +117,13 @@ static inline void free_slob_page(struct slob_page *sp)
+ }
+ 
+ /*
+- * All (partially) free slob pages go on this list.
++ * All partially free slob pages go on these lists.
+  */
+-static LIST_HEAD(free_slob_pages);
++#define SLOB_BREAK1 256
++#define SLOB_BREAK2 1024
++static LIST_HEAD(free_slob_small);
++static LIST_HEAD(free_slob_medium);
++static LIST_HEAD(free_slob_large);
+ 
+ /*
+  * slob_page: True for all slob pages (false for bigblock pages)
+@@ -140,9 +151,9 @@ static inline int slob_page_free(struct slob_page *sp)
+ 	return test_bit(PG_private, &sp->flags);
+ }
+ 
+-static inline void set_slob_page_free(struct slob_page *sp)
++static void set_slob_page_free(struct slob_page *sp, struct list_head *list)
+ {
+-	list_add(&sp->list, &free_slob_pages);
++	list_add(&sp->list, list);
+ 	__set_bit(PG_private, &sp->flags);
+ }
+ 
+@@ -294,12 +305,20 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
+ {
+ 	struct slob_page *sp;
+ 	struct list_head *prev;
++	struct list_head *slob_list;
+ 	slob_t *b = NULL;
+ 	unsigned long flags;
+ 
++	if (size < SLOB_BREAK1)
++		slob_list = &free_slob_small;
++	else if (size < SLOB_BREAK2)
++		slob_list = &free_slob_medium;
++	else
++		slob_list = &free_slob_large;
++
+ 	spin_lock_irqsave(&slob_lock, flags);
+ 	/* Iterate through each partially free page, try to find room */
+-	list_for_each_entry(sp, &free_slob_pages, list) {
++	list_for_each_entry(sp, slob_list, list) {
+ #ifdef CONFIG_NUMA
+ 		/*
+ 		 * If there's a node specification, search for a partial
+@@ -321,9 +340,9 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
+ 		/* Improve fragment distribution and reduce our average
+ 		 * search time by starting our next search here. (see
+ 		 * Knuth vol 1, sec 2.5, pg 449) */
+-		if (prev != free_slob_pages.prev &&
+-				free_slob_pages.next != prev->next)
+-			list_move_tail(&free_slob_pages, prev->next);
++		if (prev != slob_list->prev &&
++				slob_list->next != prev->next)
++			list_move_tail(slob_list, prev->next);
+ 		break;
+ 	}
+ 	spin_unlock_irqrestore(&slob_lock, flags);
+@@ -341,7 +360,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node)
+ 		sp->free = b;
+ 		INIT_LIST_HEAD(&sp->list);
+ 		set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE));
+-		set_slob_page_free(sp);
++		set_slob_page_free(sp, slob_list);
+ 		b = slob_page_alloc(sp, size, align);
+ 		BUG_ON(!b);
+ 		spin_unlock_irqrestore(&slob_lock, flags);
+@@ -387,7 +406,7 @@ static void slob_free(void *block, int size)
+ 		set_slob(b, units,
+ 			(void *)((unsigned long)(b +
+ 					SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK));
+-		set_slob_page_free(sp);
++		set_slob_page_free(sp, &free_slob_small);
+ 		goto out;
+ 	}
+ 
+@@ -398,6 +417,10 @@ static void slob_free(void *block, int size)
+ 	sp->units += units;
+ 
+ 	if (b < sp->free) {
++		if (b + units == sp->free) {
++			units += slob_units(sp->free);
++			sp->free = slob_next(sp->free);
++		}
+ 		set_slob(b, units, sp->free);
+ 		sp->free = b;
+ 	} else {
 diff --git a/mm/slub.c b/mm/slub.c
-index 474945e..5cc4b7d 100644
+index 474945e..3f05667 100644
 --- a/mm/slub.c
 +++ b/mm/slub.c
-@@ -3962,7 +3962,7 @@ static struct kset_uevent_ops slab_uevent_ops = {
+@@ -247,7 +247,10 @@ static void sysfs_slab_remove(struct kmem_cache *);
+ static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; }
+ static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p)
+ 							{ return 0; }
+-static inline void sysfs_slab_remove(struct kmem_cache *s) {}
++static inline void sysfs_slab_remove(struct kmem_cache *s)
++{
++	kfree(s);
++}
+ #endif
+ 
+ /********************************************************************
+@@ -354,22 +357,22 @@ static void print_section(char *text, u8 *addr, unsigned int length)
+ 			printk(KERN_ERR "%8s 0x%p: ", text, addr + i);
+ 			newline = 0;
+ 		}
+-		printk(" %02x", addr[i]);
++		printk(KERN_CONT " %02x", addr[i]);
+ 		offset = i % 16;
+ 		ascii[offset] = isgraph(addr[i]) ? addr[i] : '.';
+ 		if (offset == 15) {
+-			printk(" %s\n",ascii);
++			printk(KERN_CONT " %s\n", ascii);
+ 			newline = 1;
+ 		}
+ 	}
+ 	if (!newline) {
+ 		i %= 16;
+ 		while (i < 16) {
+-			printk("   ");
++			printk(KERN_CONT "   ");
+ 			ascii[i] = ' ';
+ 			i++;
+ 		}
+-		printk(" %s\n", ascii);
++		printk(KERN_CONT " %s\n", ascii);
+ 	}
+ }
+ 
+@@ -529,7 +532,7 @@ static void init_object(struct kmem_cache *s, void *object, int active)
+ 
+ 	if (s->flags & __OBJECT_POISON) {
+ 		memset(p, POISON_FREE, s->objsize - 1);
+-		p[s->objsize -1] = POISON_END;
++		p[s->objsize - 1] = POISON_END;
+ 	}
+ 
+ 	if (s->flags & SLAB_RED_ZONE)
+@@ -558,7 +561,7 @@ static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
+ 
+ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
+ 			u8 *object, char *what,
+-			u8* start, unsigned int value, unsigned int bytes)
++			u8 *start, unsigned int value, unsigned int bytes)
+ {
+ 	u8 *fault;
+ 	u8 *end;
+@@ -692,7 +695,7 @@ static int check_object(struct kmem_cache *s, struct page *page,
+ 			(!check_bytes_and_report(s, page, p, "Poison", p,
+ 					POISON_FREE, s->objsize - 1) ||
+ 			 !check_bytes_and_report(s, page, p, "Poison",
+-			 	p + s->objsize -1, POISON_END, 1)))
++				p + s->objsize - 1, POISON_END, 1)))
+ 			return 0;
+ 		/*
+ 		 * check_pad_bytes cleans up on its own.
+@@ -900,8 +903,7 @@ static int free_debug_processing(struct kmem_cache *s, struct page *page,
+ 				"SLUB <none>: no slab for object 0x%p.\n",
+ 						object);
+ 			dump_stack();
+-		}
+-		else
++		} else
+ 			object_err(s, page, object,
+ 					"page slab pointer corrupt.");
+ 		goto fail;
+@@ -947,7 +949,7 @@ static int __init setup_slub_debug(char *str)
+ 	/*
+ 	 * Determine which debug features should be switched on
+ 	 */
+-	for ( ;*str && *str != ','; str++) {
++	for (; *str && *str != ','; str++) {
+ 		switch (tolower(*str)) {
+ 		case 'f':
+ 			slub_debug |= SLAB_DEBUG_FREE;
+@@ -966,7 +968,7 @@ static int __init setup_slub_debug(char *str)
+ 			break;
+ 		default:
+ 			printk(KERN_ERR "slub_debug option '%c' "
+-				"unknown. skipped\n",*str);
++				"unknown. skipped\n", *str);
+ 		}
+ 	}
+ 
+@@ -1039,7 +1041,7 @@ static inline unsigned long kmem_cache_flags(unsigned long objsize,
+  */
+ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
+ {
+-	struct page * page;
++	struct page *page;
+ 	int pages = 1 << s->order;
+ 
+ 	if (s->order)
+@@ -1135,7 +1137,7 @@ static void __free_slab(struct kmem_cache *s, struct page *page)
+ 	mod_zone_page_state(page_zone(page),
+ 		(s->flags & SLAB_RECLAIM_ACCOUNT) ?
+ 		NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE,
+-		- pages);
++		-pages);
+ 
+ 	__free_pages(page, s->order);
+ }
+@@ -1195,19 +1197,15 @@ static __always_inline int slab_trylock(struct page *page)
+ /*
+  * Management of partially allocated slabs
+  */
+-static void add_partial_tail(struct kmem_cache_node *n, struct page *page)
++static void add_partial(struct kmem_cache_node *n,
++				struct page *page, int tail)
+ {
+ 	spin_lock(&n->list_lock);
+ 	n->nr_partial++;
+-	list_add_tail(&page->lru, &n->partial);
+-	spin_unlock(&n->list_lock);
+-}
+-
+-static void add_partial(struct kmem_cache_node *n, struct page *page)
+-{
+-	spin_lock(&n->list_lock);
+-	n->nr_partial++;
+-	list_add(&page->lru, &n->partial);
++	if (tail)
++		list_add_tail(&page->lru, &n->partial);
++	else
++		list_add(&page->lru, &n->partial);
+ 	spin_unlock(&n->list_lock);
+ }
+ 
+@@ -1292,7 +1290,8 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags)
+ 	 * expensive if we do it every time we are trying to find a slab
+ 	 * with available objects.
+ 	 */
+-	if (!s->defrag_ratio || get_cycles() % 1024 > s->defrag_ratio)
++	if (!s->remote_node_defrag_ratio ||
++			get_cycles() % 1024 > s->remote_node_defrag_ratio)
+ 		return NULL;
+ 
+ 	zonelist = &NODE_DATA(slab_node(current->mempolicy))
+@@ -1335,7 +1334,7 @@ static struct page *get_partial(struct kmem_cache *s, gfp_t flags, int node)
+  *
+  * On exit the slab lock will have been dropped.
+  */
+-static void unfreeze_slab(struct kmem_cache *s, struct page *page)
++static void unfreeze_slab(struct kmem_cache *s, struct page *page, int tail)
+ {
+ 	struct kmem_cache_node *n = get_node(s, page_to_nid(page));
+ 
+@@ -1343,7 +1342,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page)
+ 	if (page->inuse) {
+ 
+ 		if (page->freelist)
+-			add_partial(n, page);
++			add_partial(n, page, tail);
+ 		else if (SlabDebug(page) && (s->flags & SLAB_STORE_USER))
+ 			add_full(n, page);
+ 		slab_unlock(page);
+@@ -1358,7 +1357,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page)
+ 			 * partial list stays small. kmem_cache_shrink can
+ 			 * reclaim empty slabs from the partial list.
+ 			 */
+-			add_partial_tail(n, page);
++			add_partial(n, page, 1);
+ 			slab_unlock(page);
+ 		} else {
+ 			slab_unlock(page);
+@@ -1373,6 +1372,7 @@ static void unfreeze_slab(struct kmem_cache *s, struct page *page)
+ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
+ {
+ 	struct page *page = c->page;
++	int tail = 1;
+ 	/*
+ 	 * Merge cpu freelist into freelist. Typically we get here
+ 	 * because both freelists are empty. So this is unlikely
+@@ -1381,6 +1381,8 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
+ 	while (unlikely(c->freelist)) {
+ 		void **object;
+ 
++		tail = 0;	/* Hot objects. Put the slab first */
++
+ 		/* Retrieve object from cpu_freelist */
+ 		object = c->freelist;
+ 		c->freelist = c->freelist[c->offset];
+@@ -1391,7 +1393,7 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
+ 		page->inuse--;
+ 	}
+ 	c->page = NULL;
+-	unfreeze_slab(s, page);
++	unfreeze_slab(s, page, tail);
+ }
+ 
+ static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c)
+@@ -1539,7 +1541,7 @@ debug:
+  *
+  * Otherwise we can simply pick the next object from the lockless free list.
+  */
+-static void __always_inline *slab_alloc(struct kmem_cache *s,
++static __always_inline void *slab_alloc(struct kmem_cache *s,
+ 		gfp_t gfpflags, int node, void *addr)
+ {
+ 	void **object;
+@@ -1613,7 +1615,7 @@ checks_ok:
+ 	 * then add it.
+ 	 */
+ 	if (unlikely(!prior))
+-		add_partial_tail(get_node(s, page_to_nid(page)), page);
++		add_partial(get_node(s, page_to_nid(page)), page, 1);
+ 
+ out_unlock:
+ 	slab_unlock(page);
+@@ -1647,7 +1649,7 @@ debug:
+  * If fastpath is not possible then fall back to __slab_free where we deal
+  * with all sorts of special processing.
+  */
+-static void __always_inline slab_free(struct kmem_cache *s,
++static __always_inline void slab_free(struct kmem_cache *s,
+ 			struct page *page, void *x, void *addr)
+ {
+ 	void **object = (void *)x;
+@@ -1997,6 +1999,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags,
+ {
+ 	struct page *page;
+ 	struct kmem_cache_node *n;
++	unsigned long flags;
+ 
+ 	BUG_ON(kmalloc_caches->size < sizeof(struct kmem_cache_node));
+ 
+@@ -2021,7 +2024,14 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags,
+ #endif
+ 	init_kmem_cache_node(n);
+ 	atomic_long_inc(&n->nr_slabs);
+-	add_partial(n, page);
++	/*
++	 * lockdep requires consistent irq usage for each lock
++	 * so even though there cannot be a race this early in
++	 * the boot sequence, we still disable irqs.
++	 */
++	local_irq_save(flags);
++	add_partial(n, page, 0);
++	local_irq_restore(flags);
+ 	return n;
+ }
+ 
+@@ -2206,7 +2216,7 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags,
+ 
+ 	s->refcount = 1;
+ #ifdef CONFIG_NUMA
+-	s->defrag_ratio = 100;
++	s->remote_node_defrag_ratio = 100;
+ #endif
+ 	if (!init_kmem_cache_nodes(s, gfpflags & ~SLUB_DMA))
+ 		goto error;
+@@ -2228,7 +2238,7 @@ error:
+  */
+ int kmem_ptr_validate(struct kmem_cache *s, const void *object)
+ {
+-	struct page * page;
++	struct page *page;
+ 
+ 	page = get_object_page(object);
+ 
+@@ -2322,7 +2332,6 @@ void kmem_cache_destroy(struct kmem_cache *s)
+ 		if (kmem_cache_close(s))
+ 			WARN_ON(1);
+ 		sysfs_slab_remove(s);
+-		kfree(s);
+ 	} else
+ 		up_write(&slub_lock);
+ }
+@@ -2341,7 +2350,7 @@ static struct kmem_cache *kmalloc_caches_dma[PAGE_SHIFT];
+ 
+ static int __init setup_slub_min_order(char *str)
+ {
+-	get_option (&str, &slub_min_order);
++	get_option(&str, &slub_min_order);
+ 
+ 	return 1;
+ }
+@@ -2350,7 +2359,7 @@ __setup("slub_min_order=", setup_slub_min_order);
+ 
+ static int __init setup_slub_max_order(char *str)
+ {
+-	get_option (&str, &slub_max_order);
++	get_option(&str, &slub_max_order);
+ 
+ 	return 1;
+ }
+@@ -2359,7 +2368,7 @@ __setup("slub_max_order=", setup_slub_max_order);
+ 
+ static int __init setup_slub_min_objects(char *str)
+ {
+-	get_option (&str, &slub_min_objects);
++	get_option(&str, &slub_min_objects);
+ 
+ 	return 1;
+ }
+@@ -2605,6 +2614,19 @@ void kfree(const void *x)
+ }
+ EXPORT_SYMBOL(kfree);
+ 
++static unsigned long count_partial(struct kmem_cache_node *n)
++{
++	unsigned long flags;
++	unsigned long x = 0;
++	struct page *page;
++
++	spin_lock_irqsave(&n->list_lock, flags);
++	list_for_each_entry(page, &n->partial, lru)
++		x += page->inuse;
++	spin_unlock_irqrestore(&n->list_lock, flags);
++	return x;
++}
++
+ /*
+  * kmem_cache_shrink removes empty slabs from the partial lists and sorts
+  * the remaining slabs by the number of items in use. The slabs with the
+@@ -2931,7 +2953,7 @@ static struct kmem_cache *find_mergeable(size_t size,
+ 		 * Check if alignment is compatible.
+ 		 * Courtesy of Adrian Drzewiecki
+ 		 */
+-		if ((s->size & ~(align -1)) != s->size)
++		if ((s->size & ~(align - 1)) != s->size)
+ 			continue;
+ 
+ 		if (s->size - size >= sizeof(void *))
+@@ -3040,8 +3062,9 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb,
+ 	return NOTIFY_OK;
+ }
+ 
+-static struct notifier_block __cpuinitdata slab_notifier =
+-	{ &slab_cpuup_callback, NULL, 0 };
++static struct notifier_block __cpuinitdata slab_notifier = {
++	&slab_cpuup_callback, NULL, 0
++};
+ 
+ #endif
+ 
+@@ -3076,19 +3099,6 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags,
+ 	return slab_alloc(s, gfpflags, node, caller);
+ }
+ 
+-static unsigned long count_partial(struct kmem_cache_node *n)
+-{
+-	unsigned long flags;
+-	unsigned long x = 0;
+-	struct page *page;
+-
+-	spin_lock_irqsave(&n->list_lock, flags);
+-	list_for_each_entry(page, &n->partial, lru)
+-		x += page->inuse;
+-	spin_unlock_irqrestore(&n->list_lock, flags);
+-	return x;
+-}
+-
+ #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)
+ static int validate_slab(struct kmem_cache *s, struct page *page,
+ 						unsigned long *map)
+@@ -3390,7 +3400,7 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s,
+ static int list_locations(struct kmem_cache *s, char *buf,
+ 					enum track_item alloc)
+ {
+-	int n = 0;
++	int len = 0;
+ 	unsigned long i;
+ 	struct loc_track t = { 0, 0, NULL };
+ 	int node;
+@@ -3421,54 +3431,54 @@ static int list_locations(struct kmem_cache *s, char *buf,
+ 	for (i = 0; i < t.count; i++) {
+ 		struct location *l = &t.loc[i];
+ 
+-		if (n > PAGE_SIZE - 100)
++		if (len > PAGE_SIZE - 100)
+ 			break;
+-		n += sprintf(buf + n, "%7ld ", l->count);
++		len += sprintf(buf + len, "%7ld ", l->count);
+ 
+ 		if (l->addr)
+-			n += sprint_symbol(buf + n, (unsigned long)l->addr);
++			len += sprint_symbol(buf + len, (unsigned long)l->addr);
+ 		else
+-			n += sprintf(buf + n, "<not-available>");
++			len += sprintf(buf + len, "<not-available>");
+ 
+ 		if (l->sum_time != l->min_time) {
+ 			unsigned long remainder;
+ 
+-			n += sprintf(buf + n, " age=%ld/%ld/%ld",
++			len += sprintf(buf + len, " age=%ld/%ld/%ld",
+ 			l->min_time,
+ 			div_long_long_rem(l->sum_time, l->count, &remainder),
+ 			l->max_time);
+ 		} else
+-			n += sprintf(buf + n, " age=%ld",
++			len += sprintf(buf + len, " age=%ld",
+ 				l->min_time);
+ 
+ 		if (l->min_pid != l->max_pid)
+-			n += sprintf(buf + n, " pid=%ld-%ld",
++			len += sprintf(buf + len, " pid=%ld-%ld",
+ 				l->min_pid, l->max_pid);
+ 		else
+-			n += sprintf(buf + n, " pid=%ld",
++			len += sprintf(buf + len, " pid=%ld",
+ 				l->min_pid);
+ 
+ 		if (num_online_cpus() > 1 && !cpus_empty(l->cpus) &&
+-				n < PAGE_SIZE - 60) {
+-			n += sprintf(buf + n, " cpus=");
+-			n += cpulist_scnprintf(buf + n, PAGE_SIZE - n - 50,
++				len < PAGE_SIZE - 60) {
++			len += sprintf(buf + len, " cpus=");
++			len += cpulist_scnprintf(buf + len, PAGE_SIZE - len - 50,
+ 					l->cpus);
+ 		}
+ 
+ 		if (num_online_nodes() > 1 && !nodes_empty(l->nodes) &&
+-				n < PAGE_SIZE - 60) {
+-			n += sprintf(buf + n, " nodes=");
+-			n += nodelist_scnprintf(buf + n, PAGE_SIZE - n - 50,
++				len < PAGE_SIZE - 60) {
++			len += sprintf(buf + len, " nodes=");
++			len += nodelist_scnprintf(buf + len, PAGE_SIZE - len - 50,
+ 					l->nodes);
+ 		}
+ 
+-		n += sprintf(buf + n, "\n");
++		len += sprintf(buf + len, "\n");
+ 	}
+ 
+ 	free_loc_track(&t);
+ 	if (!t.count)
+-		n += sprintf(buf, "No data\n");
+-	return n;
++		len += sprintf(buf, "No data\n");
++	return len;
+ }
+ 
+ enum slab_stat_type {
+@@ -3498,7 +3508,6 @@ static unsigned long slab_objects(struct kmem_cache *s,
+ 
+ 	for_each_possible_cpu(cpu) {
+ 		struct page *page;
+-		int node;
+ 		struct kmem_cache_cpu *c = get_cpu_slab(s, cpu);
+ 
+ 		if (!c)
+@@ -3510,8 +3519,6 @@ static unsigned long slab_objects(struct kmem_cache *s,
+ 			continue;
+ 		if (page) {
+ 			if (flags & SO_CPU) {
+-				int x = 0;
+-
+ 				if (flags & SO_OBJECTS)
+ 					x = page->inuse;
+ 				else
+@@ -3848,24 +3855,24 @@ static ssize_t free_calls_show(struct kmem_cache *s, char *buf)
+ SLAB_ATTR_RO(free_calls);
+ 
+ #ifdef CONFIG_NUMA
+-static ssize_t defrag_ratio_show(struct kmem_cache *s, char *buf)
++static ssize_t remote_node_defrag_ratio_show(struct kmem_cache *s, char *buf)
+ {
+-	return sprintf(buf, "%d\n", s->defrag_ratio / 10);
++	return sprintf(buf, "%d\n", s->remote_node_defrag_ratio / 10);
+ }
+ 
+-static ssize_t defrag_ratio_store(struct kmem_cache *s,
++static ssize_t remote_node_defrag_ratio_store(struct kmem_cache *s,
+ 				const char *buf, size_t length)
+ {
+ 	int n = simple_strtoul(buf, NULL, 10);
+ 
+ 	if (n < 100)
+-		s->defrag_ratio = n * 10;
++		s->remote_node_defrag_ratio = n * 10;
+ 	return length;
+ }
+-SLAB_ATTR(defrag_ratio);
++SLAB_ATTR(remote_node_defrag_ratio);
+ #endif
+ 
+-static struct attribute * slab_attrs[] = {
++static struct attribute *slab_attrs[] = {
+ 	&slab_size_attr.attr,
+ 	&object_size_attr.attr,
+ 	&objs_per_slab_attr.attr,
+@@ -3893,7 +3900,7 @@ static struct attribute * slab_attrs[] = {
+ 	&cache_dma_attr.attr,
+ #endif
+ #ifdef CONFIG_NUMA
+-	&defrag_ratio_attr.attr,
++	&remote_node_defrag_ratio_attr.attr,
+ #endif
+ 	NULL
+ };
+@@ -3940,6 +3947,13 @@ static ssize_t slab_attr_store(struct kobject *kobj,
+ 	return err;
+ }
+ 
++static void kmem_cache_release(struct kobject *kobj)
++{
++	struct kmem_cache *s = to_slab(kobj);
++
++	kfree(s);
++}
++
+ static struct sysfs_ops slab_sysfs_ops = {
+ 	.show = slab_attr_show,
+ 	.store = slab_attr_store,
+@@ -3947,6 +3961,7 @@ static struct sysfs_ops slab_sysfs_ops = {
+ 
+ static struct kobj_type slab_ktype = {
+ 	.sysfs_ops = &slab_sysfs_ops,
++	.release = kmem_cache_release
+ };
+ 
+ static int uevent_filter(struct kset *kset, struct kobject *kobj)
+@@ -3962,7 +3977,7 @@ static struct kset_uevent_ops slab_uevent_ops = {
  	.filter = uevent_filter,
  };
  
@@ -904037,7 +981833,7 @@
  
  #define ID_STR_LENGTH 64
  
-@@ -4015,7 +4015,7 @@ static int sysfs_slab_add(struct kmem_cache *s)
+@@ -4015,7 +4030,7 @@ static int sysfs_slab_add(struct kmem_cache *s)
  		 * This is typically the case for debug situations. In that
  		 * case we can catch duplicate names easily.
  		 */
@@ -904046,7 +981842,7 @@
  		name = s->name;
  	} else {
  		/*
-@@ -4025,12 +4025,12 @@ static int sysfs_slab_add(struct kmem_cache *s)
+@@ -4025,12 +4040,12 @@ static int sysfs_slab_add(struct kmem_cache *s)
  		name = create_unique_id(s);
  	}
  
@@ -904064,7 +981860,15 @@
  
  	err = sysfs_create_group(&s->kobj, &slab_attr_group);
  	if (err)
-@@ -4070,9 +4070,8 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
+@@ -4048,6 +4063,7 @@ static void sysfs_slab_remove(struct kmem_cache *s)
+ {
+ 	kobject_uevent(&s->kobj, KOBJ_REMOVE);
+ 	kobject_del(&s->kobj);
++	kobject_put(&s->kobj);
+ }
+ 
+ /*
+@@ -4070,9 +4086,8 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
  		/*
  		 * If we have a leftover link then remove it.
  		 */
@@ -904076,7 +981880,7 @@
  	}
  
  	al = kmalloc(sizeof(struct saved_alias), GFP_KERNEL);
-@@ -4091,8 +4090,8 @@ static int __init slab_sysfs_init(void)
+@@ -4091,8 +4106,8 @@ static int __init slab_sysfs_init(void)
  	struct kmem_cache *s;
  	int err;
  
@@ -904087,6 +981891,904 @@
  		printk(KERN_ERR "Cannot register slab subsystem.\n");
  		return -ENOSYS;
  	}
+diff --git a/mm/sparse.c b/mm/sparse.c
+index a2183cb..f6a43c0 100644
+--- a/mm/sparse.c
++++ b/mm/sparse.c
+@@ -237,7 +237,7 @@ static unsigned long *__kmalloc_section_usemap(void)
+ }
+ #endif /* CONFIG_MEMORY_HOTPLUG */
+ 
+-static unsigned long *sparse_early_usemap_alloc(unsigned long pnum)
++static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum)
+ {
+ 	unsigned long *usemap;
+ 	struct mem_section *ms = __nr_to_section(pnum);
+@@ -353,17 +353,9 @@ static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid,
+ 	return __kmalloc_section_memmap(nr_pages);
+ }
+ 
+-static int vaddr_in_vmalloc_area(void *addr)
+-{
+-	if (addr >= (void *)VMALLOC_START &&
+-	    addr < (void *)VMALLOC_END)
+-		return 1;
+-	return 0;
+-}
+-
+ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages)
+ {
+-	if (vaddr_in_vmalloc_area(memmap))
++	if (is_vmalloc_addr(memmap))
+ 		vfree(memmap);
+ 	else
+ 		free_pages((unsigned long)memmap,
+diff --git a/mm/swap.c b/mm/swap.c
+index 9ac8832..57b7e25 100644
+--- a/mm/swap.c
++++ b/mm/swap.c
+@@ -41,7 +41,7 @@ static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs) = { 0, };
+  * This path almost never happens for VM activity - pages are normally
+  * freed via pagevecs.  But it gets used by networking.
+  */
+-static void fastcall __page_cache_release(struct page *page)
++static void __page_cache_release(struct page *page)
+ {
+ 	if (PageLRU(page)) {
+ 		unsigned long flags;
+@@ -165,7 +165,7 @@ int rotate_reclaimable_page(struct page *page)
+ /*
+  * FIXME: speed this up?
+  */
+-void fastcall activate_page(struct page *page)
++void activate_page(struct page *page)
+ {
+ 	struct zone *zone = page_zone(page);
+ 
+@@ -186,7 +186,7 @@ void fastcall activate_page(struct page *page)
+  * inactive,referenced		->	active,unreferenced
+  * active,unreferenced		->	active,referenced
+  */
+-void fastcall mark_page_accessed(struct page *page)
++void mark_page_accessed(struct page *page)
+ {
+ 	if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) {
+ 		activate_page(page);
+@@ -202,7 +202,7 @@ EXPORT_SYMBOL(mark_page_accessed);
+  * lru_cache_add: add a page to the page lists
+  * @page: the page to add
+  */
+-void fastcall lru_cache_add(struct page *page)
++void lru_cache_add(struct page *page)
+ {
+ 	struct pagevec *pvec = &get_cpu_var(lru_add_pvecs);
+ 
+@@ -212,7 +212,7 @@ void fastcall lru_cache_add(struct page *page)
+ 	put_cpu_var(lru_add_pvecs);
+ }
+ 
+-void fastcall lru_cache_add_active(struct page *page)
++void lru_cache_add_active(struct page *page)
+ {
+ 	struct pagevec *pvec = &get_cpu_var(lru_add_active_pvecs);
+ 
+diff --git a/mm/swap_state.c b/mm/swap_state.c
+index b526356..ec42f01 100644
+--- a/mm/swap_state.c
++++ b/mm/swap_state.c
+@@ -10,6 +10,7 @@
+ #include <linux/mm.h>
+ #include <linux/kernel_stat.h>
+ #include <linux/swap.h>
++#include <linux/swapops.h>
+ #include <linux/init.h>
+ #include <linux/pagemap.h>
+ #include <linux/buffer_head.h>
+@@ -51,26 +52,22 @@ static struct {
+ 	unsigned long del_total;
+ 	unsigned long find_success;
+ 	unsigned long find_total;
+-	unsigned long noent_race;
+-	unsigned long exist_race;
+ } swap_cache_info;
+ 
+ void show_swap_cache_info(void)
+ {
+-	printk("Swap cache: add %lu, delete %lu, find %lu/%lu, race %lu+%lu\n",
++	printk("Swap cache: add %lu, delete %lu, find %lu/%lu\n",
+ 		swap_cache_info.add_total, swap_cache_info.del_total,
+-		swap_cache_info.find_success, swap_cache_info.find_total,
+-		swap_cache_info.noent_race, swap_cache_info.exist_race);
++		swap_cache_info.find_success, swap_cache_info.find_total);
+ 	printk("Free swap  = %lukB\n", nr_swap_pages << (PAGE_SHIFT - 10));
+ 	printk("Total swap = %lukB\n", total_swap_pages << (PAGE_SHIFT - 10));
+ }
+ 
+ /*
+- * __add_to_swap_cache resembles add_to_page_cache on swapper_space,
++ * add_to_swap_cache resembles add_to_page_cache on swapper_space,
+  * but sets SwapCache flag and private instead of mapping and index.
+  */
+-static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
+-			       gfp_t gfp_mask)
++int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask)
+ {
+ 	int error;
+ 
+@@ -88,6 +85,7 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
+ 			set_page_private(page, entry.val);
+ 			total_swapcache_pages++;
+ 			__inc_zone_page_state(page, NR_FILE_PAGES);
++			INC_CACHE_INFO(add_total);
+ 		}
+ 		write_unlock_irq(&swapper_space.tree_lock);
+ 		radix_tree_preload_end();
+@@ -95,31 +93,6 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
+ 	return error;
+ }
+ 
+-static int add_to_swap_cache(struct page *page, swp_entry_t entry)
+-{
+-	int error;
+-
+-	BUG_ON(PageLocked(page));
+-	if (!swap_duplicate(entry)) {
+-		INC_CACHE_INFO(noent_race);
+-		return -ENOENT;
+-	}
+-	SetPageLocked(page);
+-	error = __add_to_swap_cache(page, entry, GFP_KERNEL);
+-	/*
+-	 * Anon pages are already on the LRU, we don't run lru_cache_add here.
+-	 */
+-	if (error) {
+-		ClearPageLocked(page);
+-		swap_free(entry);
+-		if (error == -EEXIST)
+-			INC_CACHE_INFO(exist_race);
+-		return error;
+-	}
+-	INC_CACHE_INFO(add_total);
+-	return 0;
+-}
+-
+ /*
+  * This must be called only on pages that have
+  * been verified to be in the swap cache.
+@@ -152,6 +125,7 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)
+ 	int err;
+ 
+ 	BUG_ON(!PageLocked(page));
++	BUG_ON(!PageUptodate(page));
+ 
+ 	for (;;) {
+ 		entry = get_swap_page();
+@@ -169,18 +143,15 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)
+ 		/*
+ 		 * Add it to the swap cache and mark it dirty
+ 		 */
+-		err = __add_to_swap_cache(page, entry,
++		err = add_to_swap_cache(page, entry,
+ 				gfp_mask|__GFP_NOMEMALLOC|__GFP_NOWARN);
+ 
+ 		switch (err) {
+ 		case 0:				/* Success */
+-			SetPageUptodate(page);
+ 			SetPageDirty(page);
+-			INC_CACHE_INFO(add_total);
+ 			return 1;
+ 		case -EEXIST:
+ 			/* Raced with "speculative" read_swap_cache_async */
+-			INC_CACHE_INFO(exist_race);
+ 			swap_free(entry);
+ 			continue;
+ 		default:
+@@ -211,40 +182,6 @@ void delete_from_swap_cache(struct page *page)
+ 	page_cache_release(page);
+ }
+ 
+-/*
+- * Strange swizzling function only for use by shmem_writepage
+- */
+-int move_to_swap_cache(struct page *page, swp_entry_t entry)
+-{
+-	int err = __add_to_swap_cache(page, entry, GFP_ATOMIC);
+-	if (!err) {
+-		remove_from_page_cache(page);
+-		page_cache_release(page);	/* pagecache ref */
+-		if (!swap_duplicate(entry))
+-			BUG();
+-		SetPageDirty(page);
+-		INC_CACHE_INFO(add_total);
+-	} else if (err == -EEXIST)
+-		INC_CACHE_INFO(exist_race);
+-	return err;
+-}
+-
+-/*
+- * Strange swizzling function for shmem_getpage (and shmem_unuse)
+- */
+-int move_from_swap_cache(struct page *page, unsigned long index,
+-		struct address_space *mapping)
+-{
+-	int err = add_to_page_cache(page, mapping, index, GFP_ATOMIC);
+-	if (!err) {
+-		delete_from_swap_cache(page);
+-		/* shift page from clean_pages to dirty_pages list */
+-		ClearPageDirty(page);
+-		set_page_dirty(page);
+-	}
+-	return err;
+-}
+-
+ /* 
+  * If we are the only user, then try to free up the swap cache. 
+  * 
+@@ -317,7 +254,7 @@ struct page * lookup_swap_cache(swp_entry_t entry)
+  * A failure return means that either the page allocation failed or that
+  * the swap entry is no longer in use.
+  */
+-struct page *read_swap_cache_async(swp_entry_t entry,
++struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
+ 			struct vm_area_struct *vma, unsigned long addr)
+ {
+ 	struct page *found_page, *new_page = NULL;
+@@ -337,23 +274,27 @@ struct page *read_swap_cache_async(swp_entry_t entry,
+ 		 * Get a new page to read into from swap.
+ 		 */
+ 		if (!new_page) {
+-			new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE,
+-								vma, addr);
++			new_page = alloc_page_vma(gfp_mask, vma, addr);
+ 			if (!new_page)
+ 				break;		/* Out of memory */
+ 		}
+ 
+ 		/*
++		 * Swap entry may have been freed since our caller observed it.
++		 */
++		if (!swap_duplicate(entry))
++			break;
++
++		/*
+ 		 * Associate the page with swap entry in the swap cache.
+-		 * May fail (-ENOENT) if swap entry has been freed since
+-		 * our caller observed it.  May fail (-EEXIST) if there
+-		 * is already a page associated with this entry in the
+-		 * swap cache: added by a racing read_swap_cache_async,
+-		 * or by try_to_swap_out (or shmem_writepage) re-using
+-		 * the just freed swap entry for an existing page.
++		 * May fail (-EEXIST) if there is already a page associated
++		 * with this entry in the swap cache: added by a racing
++		 * read_swap_cache_async, or add_to_swap or shmem_writepage
++		 * re-using the just freed swap entry for an existing page.
+ 		 * May fail (-ENOMEM) if radix-tree node allocation failed.
+ 		 */
+-		err = add_to_swap_cache(new_page, entry);
++		SetPageLocked(new_page);
++		err = add_to_swap_cache(new_page, entry, gfp_mask & GFP_KERNEL);
+ 		if (!err) {
+ 			/*
+ 			 * Initiate read into locked page and return.
+@@ -362,9 +303,57 @@ struct page *read_swap_cache_async(swp_entry_t entry,
+ 			swap_readpage(NULL, new_page);
+ 			return new_page;
+ 		}
+-	} while (err != -ENOENT && err != -ENOMEM);
++		ClearPageLocked(new_page);
++		swap_free(entry);
++	} while (err != -ENOMEM);
+ 
+ 	if (new_page)
+ 		page_cache_release(new_page);
+ 	return found_page;
+ }
++
++/**
++ * swapin_readahead - swap in pages in hope we need them soon
++ * @entry: swap entry of this memory
++ * @vma: user vma this address belongs to
++ * @addr: target address for mempolicy
++ *
++ * Returns the struct page for entry and addr, after queueing swapin.
++ *
++ * Primitive swap readahead code. We simply read an aligned block of
++ * (1 << page_cluster) entries in the swap area. This method is chosen
++ * because it doesn't cost us any seek time.  We also make sure to queue
++ * the 'original' request together with the readahead ones...
++ *
++ * This has been extended to use the NUMA policies from the mm triggering
++ * the readahead.
++ *
++ * Caller must hold down_read on the vma->vm_mm if vma is not NULL.
++ */
++struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
++			struct vm_area_struct *vma, unsigned long addr)
++{
++	int nr_pages;
++	struct page *page;
++	unsigned long offset;
++	unsigned long end_offset;
++
++	/*
++	 * Get starting offset for readaround, and number of pages to read.
++	 * Adjust starting address by readbehind (for NUMA interleave case)?
++	 * No, it's very unlikely that swap layout would follow vma layout,
++	 * more likely that neighbouring swap pages came from the same node:
++	 * so use the same "addr" to choose the same node for each swap read.
++	 */
++	nr_pages = valid_swaphandles(entry, &offset);
++	for (end_offset = offset + nr_pages; offset < end_offset; offset++) {
++		/* Ok, do the async read-ahead now */
++		page = read_swap_cache_async(swp_entry(swp_type(entry), offset),
++						gfp_mask, vma, addr);
++		if (!page)
++			break;
++		page_cache_release(page);
++	}
++	lru_add_drain();	/* Push any new pages onto the LRU now */
++	return read_swap_cache_async(entry, gfp_mask, vma, addr);
++}
+diff --git a/mm/swapfile.c b/mm/swapfile.c
+index f071648..eade24d 100644
+--- a/mm/swapfile.c
++++ b/mm/swapfile.c
+@@ -506,9 +506,19 @@ unsigned int count_swap_pages(int type, int free)
+  * just let do_wp_page work it out if a write is requested later - to
+  * force COW, vm_page_prot omits write permission from any private vma.
+  */
+-static void unuse_pte(struct vm_area_struct *vma, pte_t *pte,
++static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
+ 		unsigned long addr, swp_entry_t entry, struct page *page)
+ {
++	spinlock_t *ptl;
++	pte_t *pte;
++	int found = 1;
++
++	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
++	if (unlikely(!pte_same(*pte, swp_entry_to_pte(entry)))) {
++		found = 0;
++		goto out;
++	}
++
+ 	inc_mm_counter(vma->vm_mm, anon_rss);
+ 	get_page(page);
+ 	set_pte_at(vma->vm_mm, addr, pte,
+@@ -520,6 +530,9 @@ static void unuse_pte(struct vm_area_struct *vma, pte_t *pte,
+ 	 * immediately swapped out again after swapon.
+ 	 */
+ 	activate_page(page);
++out:
++	pte_unmap_unlock(pte, ptl);
++	return found;
+ }
+ 
+ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+@@ -528,22 +541,33 @@ static int unuse_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
+ {
+ 	pte_t swp_pte = swp_entry_to_pte(entry);
+ 	pte_t *pte;
+-	spinlock_t *ptl;
+ 	int found = 0;
+ 
+-	pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
++	/*
++	 * We don't actually need pte lock while scanning for swp_pte: since
++	 * we hold page lock and mmap_sem, swp_pte cannot be inserted into the
++	 * page table while we're scanning; though it could get zapped, and on
++	 * some architectures (e.g. x86_32 with PAE) we might catch a glimpse
++	 * of unmatched parts which look like swp_pte, so unuse_pte must
++	 * recheck under pte lock.  Scanning without pte lock lets it be
++	 * preemptible whenever CONFIG_PREEMPT but not CONFIG_HIGHPTE.
++	 */
++	pte = pte_offset_map(pmd, addr);
+ 	do {
+ 		/*
+ 		 * swapoff spends a _lot_ of time in this loop!
+ 		 * Test inline before going to call unuse_pte.
+ 		 */
+ 		if (unlikely(pte_same(*pte, swp_pte))) {
+-			unuse_pte(vma, pte++, addr, entry, page);
+-			found = 1;
+-			break;
++			pte_unmap(pte);
++			found = unuse_pte(vma, pmd, addr, entry, page);
++			if (found)
++				goto out;
++			pte = pte_offset_map(pmd, addr);
+ 		}
+ 	} while (pte++, addr += PAGE_SIZE, addr != end);
+-	pte_unmap_unlock(pte - 1, ptl);
++	pte_unmap(pte - 1);
++out:
+ 	return found;
+ }
+ 
+@@ -730,7 +754,8 @@ static int try_to_unuse(unsigned int type)
+ 		 */
+ 		swap_map = &si->swap_map[i];
+ 		entry = swp_entry(type, i);
+-		page = read_swap_cache_async(entry, NULL, 0);
++		page = read_swap_cache_async(entry,
++					GFP_HIGHUSER_MOVABLE, NULL, 0);
+ 		if (!page) {
+ 			/*
+ 			 * Either swap_duplicate() failed because entry
+@@ -789,7 +814,7 @@ static int try_to_unuse(unsigned int type)
+ 			atomic_inc(&new_start_mm->mm_users);
+ 			atomic_inc(&prev_mm->mm_users);
+ 			spin_lock(&mmlist_lock);
+-			while (*swap_map > 1 && !retval &&
++			while (*swap_map > 1 && !retval && !shmem &&
+ 					(p = p->next) != &start_mm->mmlist) {
+ 				mm = list_entry(p, struct mm_struct, mmlist);
+ 				if (!atomic_inc_not_zero(&mm->mm_users))
+@@ -821,6 +846,13 @@ static int try_to_unuse(unsigned int type)
+ 			mmput(start_mm);
+ 			start_mm = new_start_mm;
+ 		}
++		if (shmem) {
++			/* page has already been unlocked and released */
++			if (shmem > 0)
++				continue;
++			retval = shmem;
++			break;
++		}
+ 		if (retval) {
+ 			unlock_page(page);
+ 			page_cache_release(page);
+@@ -859,12 +891,6 @@ static int try_to_unuse(unsigned int type)
+ 		 * read from disk into another page.  Splitting into two
+ 		 * pages would be incorrect if swap supported "shared
+ 		 * private" pages, but they are handled by tmpfs files.
+-		 *
+-		 * Note shmem_unuse already deleted a swappage from
+-		 * the swap cache, unless the move to filepage failed:
+-		 * in which case it left swappage in cache, lowered its
+-		 * swap count to pass quickly through the loops above,
+-		 * and now we must reincrement count to try again later.
+ 		 */
+ 		if ((*swap_map > 1) && PageDirty(page) && PageSwapCache(page)) {
+ 			struct writeback_control wbc = {
+@@ -875,12 +901,8 @@ static int try_to_unuse(unsigned int type)
+ 			lock_page(page);
+ 			wait_on_page_writeback(page);
+ 		}
+-		if (PageSwapCache(page)) {
+-			if (shmem)
+-				swap_duplicate(entry);
+-			else
+-				delete_from_swap_cache(page);
+-		}
++		if (PageSwapCache(page))
++			delete_from_swap_cache(page);
+ 
+ 		/*
+ 		 * So we could skip searching mms once swap count went
+@@ -1768,31 +1790,48 @@ get_swap_info_struct(unsigned type)
+  */
+ int valid_swaphandles(swp_entry_t entry, unsigned long *offset)
+ {
++	struct swap_info_struct *si;
+ 	int our_page_cluster = page_cluster;
+-	int ret = 0, i = 1 << our_page_cluster;
+-	unsigned long toff;
+-	struct swap_info_struct *swapdev = swp_type(entry) + swap_info;
++	pgoff_t target, toff;
++	pgoff_t base, end;
++	int nr_pages = 0;
+ 
+ 	if (!our_page_cluster)	/* no readahead */
+ 		return 0;
+-	toff = (swp_offset(entry) >> our_page_cluster) << our_page_cluster;
+-	if (!toff)		/* first page is swap header */
+-		toff++, i--;
+-	*offset = toff;
++
++	si = &swap_info[swp_type(entry)];
++	target = swp_offset(entry);
++	base = (target >> our_page_cluster) << our_page_cluster;
++	end = base + (1 << our_page_cluster);
++	if (!base)		/* first page is swap header */
++		base++;
+ 
+ 	spin_lock(&swap_lock);
+-	do {
+-		/* Don't read-ahead past the end of the swap area */
+-		if (toff >= swapdev->max)
++	if (end > si->max)	/* don't go beyond end of map */
++		end = si->max;
++
++	/* Count contiguous allocated slots above our target */
++	for (toff = target; ++toff < end; nr_pages++) {
++		/* Don't read in free or bad pages */
++		if (!si->swap_map[toff])
++			break;
++		if (si->swap_map[toff] == SWAP_MAP_BAD)
+ 			break;
++	}
++	/* Count contiguous allocated slots below our target */
++	for (toff = target; --toff >= base; nr_pages++) {
+ 		/* Don't read in free or bad pages */
+-		if (!swapdev->swap_map[toff])
++		if (!si->swap_map[toff])
+ 			break;
+-		if (swapdev->swap_map[toff] == SWAP_MAP_BAD)
++		if (si->swap_map[toff] == SWAP_MAP_BAD)
+ 			break;
+-		toff++;
+-		ret++;
+-	} while (--i);
++	}
+ 	spin_unlock(&swap_lock);
+-	return ret;
++
++	/*
++	 * Indicate starting offset, and return number of pages to get:
++	 * if only 1, say 0, since there's then no readahead to be done.
++	 */
++	*offset = ++toff;
++	return nr_pages? ++nr_pages: 0;
+ }
+diff --git a/mm/tiny-shmem.c b/mm/tiny-shmem.c
+index d436a9c..7020836 100644
+--- a/mm/tiny-shmem.c
++++ b/mm/tiny-shmem.c
+@@ -121,18 +121,6 @@ int shmem_unuse(swp_entry_t entry, struct page *page)
+ 	return 0;
+ }
+ 
+-#if 0
+-int shmem_mmap(struct file *file, struct vm_area_struct *vma)
+-{
+-	file_accessed(file);
+-#ifndef CONFIG_MMU
+-	return ramfs_nommu_mmap(file, vma);
+-#else
+-	return 0;
+-#endif
+-}
+-#endif  /*  0  */
+-
+ #ifndef CONFIG_MMU
+ unsigned long shmem_get_unmapped_area(struct file *file,
+ 				      unsigned long addr,
+diff --git a/mm/truncate.c b/mm/truncate.c
+index cadc156..c35c49e 100644
+--- a/mm/truncate.c
++++ b/mm/truncate.c
+@@ -21,7 +21,7 @@
+ 
+ 
+ /**
+- * do_invalidatepage - invalidate part of all of a page
++ * do_invalidatepage - invalidate part or all of a page
+  * @page: the page which is affected
+  * @offset: the index of the truncation point
+  *
+@@ -48,7 +48,7 @@ void do_invalidatepage(struct page *page, unsigned long offset)
+ 
+ static inline void truncate_partial_page(struct page *page, unsigned partial)
+ {
+-	zero_user_page(page, partial, PAGE_CACHE_SIZE - partial, KM_USER0);
++	zero_user_segment(page, partial, PAGE_CACHE_SIZE);
+ 	if (PagePrivate(page))
+ 		do_invalidatepage(page, partial);
+ }
+@@ -84,7 +84,7 @@ EXPORT_SYMBOL(cancel_dirty_page);
+ 
+ /*
+  * If truncate cannot remove the fs-private metadata from the page, the page
+- * becomes anonymous.  It will be left on the LRU and may even be mapped into
++ * becomes orphaned.  It will be left on the LRU and may even be mapped into
+  * user pagetables if we're racing with filemap_fault().
+  *
+  * We need to bale out if page->mapping is no longer equal to the original
+@@ -98,11 +98,11 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
+ 	if (page->mapping != mapping)
+ 		return;
+ 
+-	cancel_dirty_page(page, PAGE_CACHE_SIZE);
+-
+ 	if (PagePrivate(page))
+ 		do_invalidatepage(page, 0);
+ 
++	cancel_dirty_page(page, PAGE_CACHE_SIZE);
++
+ 	remove_from_page_cache(page);
+ 	ClearPageUptodate(page);
+ 	ClearPageMappedToDisk(page);
+diff --git a/mm/vmalloc.c b/mm/vmalloc.c
+index af77e17..0536dde 100644
+--- a/mm/vmalloc.c
++++ b/mm/vmalloc.c
+@@ -166,6 +166,44 @@ int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
+ }
+ EXPORT_SYMBOL_GPL(map_vm_area);
+ 
++/*
++ * Map a vmalloc()-space virtual address to the physical page.
++ */
++struct page *vmalloc_to_page(const void *vmalloc_addr)
++{
++	unsigned long addr = (unsigned long) vmalloc_addr;
++	struct page *page = NULL;
++	pgd_t *pgd = pgd_offset_k(addr);
++	pud_t *pud;
++	pmd_t *pmd;
++	pte_t *ptep, pte;
++
++	if (!pgd_none(*pgd)) {
++		pud = pud_offset(pgd, addr);
++		if (!pud_none(*pud)) {
++			pmd = pmd_offset(pud, addr);
++			if (!pmd_none(*pmd)) {
++				ptep = pte_offset_map(pmd, addr);
++				pte = *ptep;
++				if (pte_present(pte))
++					page = pte_page(pte);
++				pte_unmap(ptep);
++			}
++		}
++	}
++	return page;
++}
++EXPORT_SYMBOL(vmalloc_to_page);
++
++/*
++ * Map a vmalloc()-space virtual address to the physical page frame number.
++ */
++unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
++{
++	return page_to_pfn(vmalloc_to_page(vmalloc_addr));
++}
++EXPORT_SYMBOL(vmalloc_to_pfn);
++
+ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long flags,
+ 					    unsigned long start, unsigned long end,
+ 					    int node, gfp_t gfp_mask)
+@@ -216,6 +254,10 @@ static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long fl
+ 		if (addr > end - size)
+ 			goto out;
+ 	}
++	if ((size + addr) < addr)
++		goto out;
++	if (addr > end - size)
++		goto out;
+ 
+ found:
+ 	area->next = *p;
+@@ -268,7 +310,7 @@ struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags,
+ }
+ 
+ /* Caller must hold vmlist_lock */
+-static struct vm_struct *__find_vm_area(void *addr)
++static struct vm_struct *__find_vm_area(const void *addr)
+ {
+ 	struct vm_struct *tmp;
+ 
+@@ -281,7 +323,7 @@ static struct vm_struct *__find_vm_area(void *addr)
+ }
+ 
+ /* Caller must hold vmlist_lock */
+-static struct vm_struct *__remove_vm_area(void *addr)
++static struct vm_struct *__remove_vm_area(const void *addr)
+ {
+ 	struct vm_struct **p, *tmp;
+ 
+@@ -310,7 +352,7 @@ found:
+  *	This function returns the found VM area, but using it is NOT safe
+  *	on SMP machines, except for its size or flags.
+  */
+-struct vm_struct *remove_vm_area(void *addr)
++struct vm_struct *remove_vm_area(const void *addr)
+ {
+ 	struct vm_struct *v;
+ 	write_lock(&vmlist_lock);
+@@ -319,7 +361,7 @@ struct vm_struct *remove_vm_area(void *addr)
+ 	return v;
+ }
+ 
+-static void __vunmap(void *addr, int deallocate_pages)
++static void __vunmap(const void *addr, int deallocate_pages)
+ {
+ 	struct vm_struct *area;
+ 
+@@ -346,8 +388,10 @@ static void __vunmap(void *addr, int deallocate_pages)
+ 		int i;
+ 
+ 		for (i = 0; i < area->nr_pages; i++) {
+-			BUG_ON(!area->pages[i]);
+-			__free_page(area->pages[i]);
++			struct page *page = area->pages[i];
++
++			BUG_ON(!page);
++			__free_page(page);
+ 		}
+ 
+ 		if (area->flags & VM_VPAGES)
+@@ -370,7 +414,7 @@ static void __vunmap(void *addr, int deallocate_pages)
+  *
+  *	Must not be called in interrupt context.
+  */
+-void vfree(void *addr)
++void vfree(const void *addr)
+ {
+ 	BUG_ON(in_interrupt());
+ 	__vunmap(addr, 1);
+@@ -386,7 +430,7 @@ EXPORT_SYMBOL(vfree);
+  *
+  *	Must not be called in interrupt context.
+  */
+-void vunmap(void *addr)
++void vunmap(const void *addr)
+ {
+ 	BUG_ON(in_interrupt());
+ 	__vunmap(addr, 0);
+@@ -423,8 +467,8 @@ void *vmap(struct page **pages, unsigned int count,
+ }
+ EXPORT_SYMBOL(vmap);
+ 
+-void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
+-				pgprot_t prot, int node)
++static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
++				 pgprot_t prot, int node)
+ {
+ 	struct page **pages;
+ 	unsigned int nr_pages, array_size, i;
+@@ -451,15 +495,19 @@ void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
+ 	}
+ 
+ 	for (i = 0; i < area->nr_pages; i++) {
++		struct page *page;
++
+ 		if (node < 0)
+-			area->pages[i] = alloc_page(gfp_mask);
++			page = alloc_page(gfp_mask);
+ 		else
+-			area->pages[i] = alloc_pages_node(node, gfp_mask, 0);
+-		if (unlikely(!area->pages[i])) {
++			page = alloc_pages_node(node, gfp_mask, 0);
++
++		if (unlikely(!page)) {
+ 			/* Successfully allocated i pages, free them in __vunmap() */
+ 			area->nr_pages = i;
+ 			goto fail;
+ 		}
++		area->pages[i] = page;
+ 	}
+ 
+ 	if (map_vm_area(area, prot, &pages))
+diff --git a/mm/vmstat.c b/mm/vmstat.c
+index e8d846f..422d960 100644
+--- a/mm/vmstat.c
++++ b/mm/vmstat.c
+@@ -21,21 +21,14 @@ EXPORT_PER_CPU_SYMBOL(vm_event_states);
+ 
+ static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask)
+ {
+-	int cpu = 0;
++	int cpu;
+ 	int i;
+ 
+ 	memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));
+ 
+-	cpu = first_cpu(*cpumask);
+-	while (cpu < NR_CPUS) {
++	for_each_cpu_mask(cpu, *cpumask) {
+ 		struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
+ 
+-		cpu = next_cpu(cpu, *cpumask);
+-
+-		if (cpu < NR_CPUS)
+-			prefetch(&per_cpu(vm_event_states, cpu));
+-
+-
+ 		for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+ 			ret[i] += this->event[i];
+ 	}
+@@ -284,6 +277,10 @@ EXPORT_SYMBOL(dec_zone_page_state);
+ /*
+  * Update the zone counters for one cpu.
+  *
++ * The cpu specified must be either the current cpu or a processor that
++ * is not online. If it is the current cpu then the execution thread must
++ * be pinned to the current cpu.
++ *
+  * Note that refresh_cpu_vm_stats strives to only access
+  * node local memory. The per cpu pagesets on remote zones are placed
+  * in the memory local to the processor using that pageset. So the
+@@ -299,7 +296,7 @@ void refresh_cpu_vm_stats(int cpu)
+ {
+ 	struct zone *zone;
+ 	int i;
+-	unsigned long flags;
++	int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, };
+ 
+ 	for_each_zone(zone) {
+ 		struct per_cpu_pageset *p;
+@@ -311,15 +308,19 @@ void refresh_cpu_vm_stats(int cpu)
+ 
+ 		for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+ 			if (p->vm_stat_diff[i]) {
++				unsigned long flags;
++				int v;
++
+ 				local_irq_save(flags);
+-				zone_page_state_add(p->vm_stat_diff[i],
+-					zone, i);
++				v = p->vm_stat_diff[i];
+ 				p->vm_stat_diff[i] = 0;
++				local_irq_restore(flags);
++				atomic_long_add(v, &zone->vm_stat[i]);
++				global_diff[i] += v;
+ #ifdef CONFIG_NUMA
+ 				/* 3 seconds idle till flush */
+ 				p->expire = 3;
+ #endif
+-				local_irq_restore(flags);
+ 			}
+ #ifdef CONFIG_NUMA
+ 		/*
+@@ -329,7 +330,7 @@ void refresh_cpu_vm_stats(int cpu)
+ 		 * Check if there are pages remaining in this pageset
+ 		 * if not then there is nothing to expire.
+ 		 */
+-		if (!p->expire || (!p->pcp[0].count && !p->pcp[1].count))
++		if (!p->expire || !p->pcp.count)
+ 			continue;
+ 
+ 		/*
+@@ -344,13 +345,14 @@ void refresh_cpu_vm_stats(int cpu)
+ 		if (p->expire)
+ 			continue;
+ 
+-		if (p->pcp[0].count)
+-			drain_zone_pages(zone, p->pcp + 0);
+-
+-		if (p->pcp[1].count)
+-			drain_zone_pages(zone, p->pcp + 1);
++		if (p->pcp.count)
++			drain_zone_pages(zone, &p->pcp);
+ #endif
+ 	}
++
++	for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
++		if (global_diff[i])
++			atomic_long_add(global_diff[i], &vm_stat[i]);
+ }
+ 
+ #endif
+@@ -681,20 +683,17 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
+ 		   "\n  pagesets");
+ 	for_each_online_cpu(i) {
+ 		struct per_cpu_pageset *pageset;
+-		int j;
+ 
+ 		pageset = zone_pcp(zone, i);
+-		for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+-			seq_printf(m,
+-				   "\n    cpu: %i pcp: %i"
+-				   "\n              count: %i"
+-				   "\n              high:  %i"
+-				   "\n              batch: %i",
+-				   i, j,
+-				   pageset->pcp[j].count,
+-				   pageset->pcp[j].high,
+-				   pageset->pcp[j].batch);
+-			}
++		seq_printf(m,
++			   "\n    cpu: %i"
++			   "\n              count: %i"
++			   "\n              high:  %i"
++			   "\n              batch: %i",
++			   i,
++			   pageset->pcp.count,
++			   pageset->pcp.high,
++			   pageset->pcp.batch);
+ #ifdef CONFIG_SMP
+ 		seq_printf(m, "\n  vm stats threshold: %d",
+ 				pageset->stat_threshold);
 diff --git a/net/802/Makefile b/net/802/Makefile
 index 977704a..68569ff 100644
 --- a/net/802/Makefile
@@ -906038,6 +984740,42 @@
  static u8 buf_get_int8(struct cbuf *buf)
  {
  	u8 ret = 0;
+diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
+index 40b71a2..42eea5f 100644
+--- a/net/9p/trans_virtio.c
++++ b/net/9p/trans_virtio.c
+@@ -199,14 +199,12 @@ static void p9_virtio_close(struct p9_trans *trans)
+ 	kfree(trans);
+ }
+ 
+-static bool p9_virtio_intr(struct virtqueue *q)
++static void p9_virtio_intr(struct virtqueue *q)
+ {
+ 	struct virtio_chan *chan = q->vdev->priv;
+ 
+ 	P9_DPRINTK(P9_DEBUG_TRANS, "9p poll_wakeup: %p\n", &chan->wq);
+ 	wake_up_interruptible(&chan->wq);
+-
+-	return true;
+ }
+ 
+ static int p9_virtio_probe(struct virtio_device *dev)
+@@ -236,13 +234,13 @@ static int p9_virtio_probe(struct virtio_device *dev)
+ 
+ 	/* Find the input queue. */
+ 	dev->priv = chan;
+-	chan->in_vq = dev->config->find_vq(dev, p9_virtio_intr);
++	chan->in_vq = dev->config->find_vq(dev, 0, p9_virtio_intr);
+ 	if (IS_ERR(chan->in_vq)) {
+ 		err = PTR_ERR(chan->in_vq);
+ 		goto free;
+ 	}
+ 
+-	chan->out_vq = dev->config->find_vq(dev, NULL);
++	chan->out_vq = dev->config->find_vq(dev, 1, NULL);
+ 	if (IS_ERR(chan->out_vq)) {
+ 		err = PTR_ERR(chan->out_vq);
+ 		goto free_in_vq;
 diff --git a/net/Kconfig b/net/Kconfig
 index ab4e6da..b6a5d45 100644
 --- a/net/Kconfig
@@ -907555,10 +986293,134 @@
  
  	bus_unregister(&bt_bus);
 diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
-index 4bbacdd..782a226 100644
+index 4bbacdd..519cdb9 100644
 --- a/net/bluetooth/hidp/core.c
 +++ b/net/bluetooth/hidp/core.c
-@@ -811,10 +811,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
+@@ -135,8 +135,8 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
+ 	}
+ }
+ 
+-static inline int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
+-					unsigned int type, unsigned int code, int value)
++static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
++				unsigned int type, unsigned int code, int value)
+ {
+ 	unsigned char newleds;
+ 	struct sk_buff *skb;
+@@ -243,7 +243,8 @@ static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
+ 	input_sync(dev);
+ }
+ 
+-static inline int hidp_queue_report(struct hidp_session *session, unsigned char *data, int size)
++static int hidp_queue_report(struct hidp_session *session,
++				unsigned char *data, int size)
+ {
+ 	struct sk_buff *skb;
+ 
+@@ -287,7 +288,7 @@ static void hidp_idle_timeout(unsigned long arg)
+ 	hidp_schedule(session);
+ }
+ 
+-static inline void hidp_set_timer(struct hidp_session *session)
++static void hidp_set_timer(struct hidp_session *session)
+ {
+ 	if (session->idle_to > 0)
+ 		mod_timer(&session->timer, jiffies + HZ * session->idle_to);
+@@ -332,7 +333,8 @@ static inline int hidp_send_ctrl_message(struct hidp_session *session,
+ 	return err;
+ }
+ 
+-static inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
++static void hidp_process_handshake(struct hidp_session *session,
++					unsigned char param)
+ {
+ 	BT_DBG("session %p param 0x%02x", session, param);
+ 
+@@ -365,38 +367,23 @@ static inline void hidp_process_handshake(struct hidp_session *session, unsigned
+ 	}
+ }
+ 
+-static inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
++static void hidp_process_hid_control(struct hidp_session *session,
++					unsigned char param)
+ {
+ 	BT_DBG("session %p param 0x%02x", session, param);
+ 
+-	switch (param) {
+-	case HIDP_CTRL_NOP:
+-		break;
+-
+-	case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG:
++	if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
+ 		/* Flush the transmit queues */
+ 		skb_queue_purge(&session->ctrl_transmit);
+ 		skb_queue_purge(&session->intr_transmit);
+ 
+ 		/* Kill session thread */
+ 		atomic_inc(&session->terminate);
+-		break;
+-
+-	case HIDP_CTRL_HARD_RESET:
+-	case HIDP_CTRL_SOFT_RESET:
+-	case HIDP_CTRL_SUSPEND:
+-	case HIDP_CTRL_EXIT_SUSPEND:
+-		/* FIXME: We have to parse these and return no error */
+-		break;
+-
+-	default:
+-		__hidp_send_ctrl_message(session,
+-			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
+-		break;
+ 	}
+ }
+ 
+-static inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
++static void hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
++				unsigned char param)
+ {
+ 	BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
+ 
+@@ -423,7 +410,8 @@ static inline void hidp_process_data(struct hidp_session *session, struct sk_buf
+ 	}
+ }
+ 
+-static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
++static void hidp_recv_ctrl_frame(struct hidp_session *session,
++					struct sk_buff *skb)
+ {
+ 	unsigned char hdr, type, param;
+ 
+@@ -457,7 +445,8 @@ static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_
+ 	kfree_skb(skb);
+ }
+ 
+-static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
++static void hidp_recv_intr_frame(struct hidp_session *session,
++				struct sk_buff *skb)
+ {
+ 	unsigned char hdr;
+ 
+@@ -625,7 +614,8 @@ static struct device *hidp_get_device(struct hidp_session *session)
+ 	return conn ? &conn->dev : NULL;
+ }
+ 
+-static inline int hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
++static int hidp_setup_input(struct hidp_session *session,
++				struct hidp_connadd_req *req)
+ {
+ 	struct input_dev *input = session->input;
+ 	int i;
+@@ -702,7 +692,8 @@ static void hidp_setup_quirks(struct hid_device *hid)
+ 			hid->quirks = hidp_blacklist[n].quirks;
+ }
+ 
+-static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req)
++static void hidp_setup_hid(struct hidp_session *session,
++				struct hidp_connadd_req *req)
+ {
+ 	struct hid_device *hid = session->hid;
+ 	struct hid_report *report;
+@@ -811,10 +802,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
  	session->intr_sock = intr_sock;
  	session->state     = BT_CONNECTED;
  
@@ -907655,6 +986517,20 @@
  
  	skb_queue_head_init(&d->tx_queue);
  	spin_lock_init(&d->lock);
+diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
+index 788c703..e4c779b 100644
+--- a/net/bluetooth/rfcomm/tty.c
++++ b/net/bluetooth/rfcomm/tty.c
+@@ -429,7 +429,8 @@ static int rfcomm_release_dev(void __user *arg)
+ 	if (dev->tty)
+ 		tty_vhangup(dev->tty);
+ 
+-	rfcomm_dev_del(dev);
++	if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
++		rfcomm_dev_del(dev);
+ 	rfcomm_dev_put(dev);
+ 	return 0;
+ }
 diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
 index 93ad1aa..b91d3c8 100644
 --- a/net/bluetooth/sco.c
@@ -914646,7 +993522,7 @@
  	read_lock(&dev_base_lock);
  	if (dev_isalive(dev) && dev->get_stats &&
 diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
-index ec936ae..26e941d 100644
+index ec936ae..7b66083 100644
 --- a/net/core/net_namespace.c
 +++ b/net/core/net_namespace.c
 @@ -58,6 +58,7 @@ out_undo:
@@ -914680,6 +993556,24 @@
  	mutex_lock(&net_mutex);
  	err = setup_net(&init_net);
  
+@@ -280,7 +287,7 @@ EXPORT_SYMBOL_GPL(register_pernet_subsys);
+  *	@ops: pernet operations structure to manipulate
+  *
+  *	Remove the pernet operations structure from the list to be
+- *	used when network namespaces are created or destoryed.  In
++ *	used when network namespaces are created or destroyed.  In
+  *	addition run the exit method for all existing network
+  *	namespaces.
+  */
+@@ -328,7 +335,7 @@ EXPORT_SYMBOL_GPL(register_pernet_device);
+  *	@ops: pernet operations structure to manipulate
+  *
+  *	Remove the pernet operations structure from the list to be
+- *	used when network namespaces are created or destoryed.  In
++ *	used when network namespaces are created or destroyed.  In
+  *	addition run the exit method for all existing network
+  *	namespaces.
+  */
 diff --git a/net/core/netpoll.c b/net/core/netpoll.c
 index c499b5c..6faa128 100644
 --- a/net/core/netpoll.c
@@ -915042,7 +993936,7 @@
  
 -EXPORT_SYMBOL(reqsk_queue_destroy);
 diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
-index fed95a3..ddbdde8 100644
+index fed95a3..61ac8d0 100644
 --- a/net/core/rtnetlink.c
 +++ b/net/core/rtnetlink.c
 @@ -60,7 +60,6 @@ struct rtnl_link
@@ -915053,10 +993947,58 @@
  
  void rtnl_lock(void)
  {
-@@ -458,8 +457,9 @@ size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size)
- 	return ret;
+@@ -83,32 +82,6 @@ int rtnl_trylock(void)
+ 	return mutex_trylock(&rtnl_mutex);
+ }
+ 
+-int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len)
+-{
+-	memset(tb, 0, sizeof(struct rtattr*)*maxattr);
+-
+-	while (RTA_OK(rta, len)) {
+-		unsigned flavor = rta->rta_type;
+-		if (flavor && flavor <= maxattr)
+-			tb[flavor-1] = rta;
+-		rta = RTA_NEXT(rta, len);
+-	}
+-	return 0;
+-}
+-
+-int __rtattr_parse_nested_compat(struct rtattr *tb[], int maxattr,
+-				 struct rtattr *rta, int len)
+-{
+-	if (RTA_PAYLOAD(rta) < len)
+-		return -1;
+-	if (RTA_PAYLOAD(rta) >= RTA_ALIGN(len) + sizeof(struct rtattr)) {
+-		rta = RTA_DATA(rta) + RTA_ALIGN(len);
+-		return rtattr_parse_nested(tb, maxattr, rta);
+-	}
+-	memset(tb, 0, sizeof(struct rtattr *) * maxattr);
+-	return 0;
+-}
+-
+ static struct rtnl_link *rtnl_msg_handlers[NPROTO];
+ 
+ static inline int rtm_msgindex(int msgtype)
+@@ -443,23 +416,9 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data
+ 	memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size);
  }
  
+-size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size)
+-{
+-	size_t ret = RTA_PAYLOAD(rta);
+-	char *src = RTA_DATA(rta);
+-
+-	if (ret > 0 && src[ret - 1] == '\0')
+-		ret--;
+-	if (size > 0) {
+-		size_t len = (ret >= size) ? size - 1 : ret;
+-		memset(dest, 0, size);
+-		memcpy(dest, src, len);
+-	}
+-	return ret;
+-}
+-
 -int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
 +int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo)
  {
@@ -915064,7 +994006,7 @@
  	int err = 0;
  
  	NETLINK_CB(skb).dst_group = group;
-@@ -471,14 +471,17 @@ int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
+@@ -471,14 +430,17 @@ int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
  	return err;
  }
  
@@ -915084,7 +994026,7 @@
  	int report = 0;
  
  	if (nlh)
-@@ -487,8 +490,10 @@ int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
+@@ -487,8 +449,10 @@ int rtnl_notify(struct sk_buff *skb, u32 pid, u32 group,
  	return nlmsg_notify(rtnl, skb, pid, group, report, flags);
  }
  
@@ -915096,7 +994038,7 @@
  	netlink_set_err(rtnl, 0, group, error);
  }
  
-@@ -1186,7 +1191,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
+@@ -1186,7 +1150,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
  		kfree_skb(nskb);
  		goto errout;
  	}
@@ -915105,7 +994047,7 @@
  errout:
  	dev_put(dev);
  
-@@ -1219,6 +1224,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
+@@ -1219,6 +1183,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb)
  
  void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
  {
@@ -915113,7 +994055,7 @@
  	struct sk_buff *skb;
  	int err = -ENOBUFS;
  
-@@ -1233,10 +1239,10 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
+@@ -1233,10 +1198,10 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
  		kfree_skb(skb);
  		goto errout;
  	}
@@ -915126,7 +994068,7 @@
  }
  
  /* Protected by RTNL sempahore.  */
-@@ -1247,6 +1253,7 @@ static int rtattr_max;
+@@ -1247,6 +1212,7 @@ static int rtattr_max;
  
  static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
@@ -915134,7 +994076,7 @@
  	rtnl_doit_func doit;
  	int sz_idx, kind;
  	int min_len;
-@@ -1275,6 +1282,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+@@ -1275,6 +1241,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  		return -EPERM;
  
  	if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
@@ -915142,7 +994084,7 @@
  		rtnl_dumpit_func dumpit;
  
  		dumpit = rtnl_get_dumpit(family, type);
-@@ -1282,6 +1290,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
+@@ -1282,6 +1249,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  			return -EOPNOTSUPP;
  
  		__rtnl_unlock();
@@ -915150,7 +994092,7 @@
  		err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
  		rtnl_lock();
  		return err;
-@@ -1326,9 +1335,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
+@@ -1326,9 +1294,6 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi
  {
  	struct net_device *dev = ptr;
  
@@ -915160,7 +994102,7 @@
  	switch (event) {
  	case NETDEV_UNREGISTER:
  		rtmsg_ifinfo(RTM_DELLINK, dev, ~0U);
-@@ -1354,6 +1360,29 @@ static struct notifier_block rtnetlink_dev_notifier = {
+@@ -1354,6 +1319,29 @@ static struct notifier_block rtnetlink_dev_notifier = {
  	.notifier_call	= rtnetlink_event,
  };
  
@@ -915190,7 +994132,7 @@
  void __init rtnetlink_init(void)
  {
  	int i;
-@@ -1366,10 +1395,9 @@ void __init rtnetlink_init(void)
+@@ -1366,10 +1354,9 @@ void __init rtnetlink_init(void)
  	if (!rta_buf)
  		panic("rtnetlink_init: cannot allocate rta_buf\n");
  
@@ -915203,8 +994145,18 @@
  	netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV);
  	register_netdevice_notifier(&rtnetlink_dev_notifier);
  
+@@ -1383,9 +1370,6 @@ void __init rtnetlink_init(void)
+ }
+ 
+ EXPORT_SYMBOL(__rta_fill);
+-EXPORT_SYMBOL(rtattr_strlcpy);
+-EXPORT_SYMBOL(rtattr_parse);
+-EXPORT_SYMBOL(__rtattr_parse_nested_compat);
+ EXPORT_SYMBOL(rtnetlink_put_metrics);
+ EXPORT_SYMBOL(rtnl_lock);
+ EXPORT_SYMBOL(rtnl_trylock);
 diff --git a/net/core/skbuff.c b/net/core/skbuff.c
-index b628377..98420f9 100644
+index b628377..4e35422 100644
 --- a/net/core/skbuff.c
 +++ b/net/core/skbuff.c
 @@ -52,6 +52,7 @@
@@ -915474,6 +994426,46 @@
  /**
   *	skb_store_bits - store bits from kernel buffer to skb
   *	@skb: destination buffer
+@@ -2215,6 +2461,34 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
+ 	return elt;
+ }
+ 
++/**
++ * skb_partial_csum_set - set up and verify partial csum values for packet
++ * @skb: the skb to set
++ * @start: the number of bytes after skb->data to start checksumming.
++ * @off: the offset from start to place the checksum.
++ *
++ * For untrusted partially-checksummed packets, we need to make sure the values
++ * for skb->csum_start and skb->csum_offset are valid so we don't oops.
++ *
++ * This function checks and sets those values and skb->ip_summed: if this
++ * returns false you should drop the packet.
++ */
++bool skb_partial_csum_set(struct sk_buff *skb, u16 start, u16 off)
++{
++	if (unlikely(start > skb->len - 2) ||
++	    unlikely((int)start + off > skb->len - 2)) {
++		if (net_ratelimit())
++			printk(KERN_WARNING
++			       "bad partial csum: csum=%u/%u len=%u\n",
++			       start, off, skb->len);
++		return false;
++	}
++	skb->ip_summed = CHECKSUM_PARTIAL;
++	skb->csum_start = skb_headroom(skb) + start;
++	skb->csum_offset = off;
++	return true;
++}
++
+ EXPORT_SYMBOL(___pskb_trim);
+ EXPORT_SYMBOL(__kfree_skb);
+ EXPORT_SYMBOL(kfree_skb);
+@@ -2251,3 +2525,4 @@ EXPORT_SYMBOL(skb_append_datato_frags);
+ 
+ EXPORT_SYMBOL_GPL(skb_to_sgvec);
+ EXPORT_SYMBOL_GPL(skb_cow_data);
++EXPORT_SYMBOL_GPL(skb_partial_csum_set);
 diff --git a/net/core/sock.c b/net/core/sock.c
 index c519b43..433715f 100644
 --- a/net/core/sock.c
@@ -919919,7 +998911,7 @@
  extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue);
  
 diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
-index ee97950..ebe59d9 100644
+index ee97950..287a62b 100644
 --- a/net/dccp/dccp.h
 +++ b/net/dccp/dccp.h
 @@ -72,11 +72,21 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
@@ -919960,7 +998952,16 @@
  enum {
  	DCCP_MIB_NUM = 0,
  	DCCP_MIB_ACTIVEOPENS,			/* ActiveOpens */
-@@ -334,6 +338,7 @@ struct dccp_skb_cb {
+@@ -267,8 +271,6 @@ extern struct sk_buff	*dccp_make_response(struct sock *sk,
+ 
+ extern int	   dccp_connect(struct sock *sk);
+ extern int	   dccp_disconnect(struct sock *sk, int flags);
+-extern void	   dccp_hash(struct sock *sk);
+-extern void	   dccp_unhash(struct sock *sk);
+ extern int	   dccp_getsockopt(struct sock *sk, int level, int optname,
+ 				   char __user *optval, int __user *optlen);
+ extern int	   dccp_setsockopt(struct sock *sk, int level, int optname,
+@@ -334,6 +336,7 @@ struct dccp_skb_cb {
  
  #define DCCP_SKB_CB(__skb) ((struct dccp_skb_cb *)&((__skb)->cb[0]))
  
@@ -919968,7 +998969,7 @@
  static inline int dccp_non_data_packet(const struct sk_buff *skb)
  {
  	const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
-@@ -346,6 +351,17 @@ static inline int dccp_non_data_packet(const struct sk_buff *skb)
+@@ -346,6 +349,17 @@ static inline int dccp_non_data_packet(const struct sk_buff *skb)
  	       type == DCCP_PKT_SYNCACK;
  }
  
@@ -919986,7 +998987,7 @@
  static inline int dccp_packet_without_ack(const struct sk_buff *skb)
  {
  	const __u8 type = DCCP_SKB_CB(skb)->dccpd_type;
-@@ -406,6 +422,7 @@ static inline int dccp_ack_pending(const struct sock *sk)
+@@ -406,6 +420,7 @@ static inline int dccp_ack_pending(const struct sock *sk)
  }
  
  extern int dccp_insert_options(struct sock *sk, struct sk_buff *skb);
@@ -920399,10 +999400,23 @@
  		}
  	} else if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) {
 diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
-index db17b83..c982ad8 100644
+index db17b83..474075a 100644
 --- a/net/dccp/ipv4.c
 +++ b/net/dccp/ipv4.c
-@@ -218,7 +218,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
+@@ -38,12 +38,6 @@
+  */
+ static struct socket *dccp_v4_ctl_socket;
+ 
+-static int dccp_v4_get_port(struct sock *sk, const unsigned short snum)
+-{
+-	return inet_csk_get_port(&dccp_hashinfo, sk, snum,
+-				 inet_csk_bind_conflict);
+-}
+-
+ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+ {
+ 	struct inet_sock *inet = inet_sk(sk);
+@@ -218,7 +212,7 @@ static void dccp_v4_err(struct sk_buff *skb, u32 info)
  		return;
  	}
  
@@ -920411,16 +999425,18 @@
  			 iph->saddr, dh->dccph_sport, inet_iif(skb));
  	if (sk == NULL) {
  		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
-@@ -408,7 +408,7 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
+@@ -408,8 +402,8 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
  
  	dccp_sync_mss(newsk, dst_mtu(dst));
  
 -	__inet_hash(&dccp_hashinfo, newsk, 0);
-+	__inet_hash_nolisten(&dccp_hashinfo, newsk);
- 	__inet_inherit_port(&dccp_hashinfo, sk, newsk);
+-	__inet_inherit_port(&dccp_hashinfo, sk, newsk);
++	__inet_hash_nolisten(newsk);
++	__inet_inherit_port(sk, newsk);
  
  	return newsk;
-@@ -436,7 +436,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ 
+@@ -436,7 +430,7 @@ static struct sock *dccp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
  	if (req != NULL)
  		return dccp_check_req(sk, skb, req, prev);
  
@@ -920429,7 +999445,7 @@
  				      iph->saddr, dh->dccph_sport,
  				      iph->daddr, dh->dccph_dport,
  				      inet_iif(skb));
-@@ -469,7 +469,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
+@@ -469,7 +463,7 @@ static struct dst_entry* dccp_v4_route_skb(struct sock *sk,
  			  };
  
  	security_skb_classify_flow(skb, &fl);
@@ -920438,7 +999454,7 @@
  		IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
  		return NULL;
  	}
-@@ -600,11 +600,12 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+@@ -600,11 +594,12 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
  	if (req == NULL)
  		goto drop;
  
@@ -920454,7 +999470,7 @@
  	if (security_inet_conn_request(sk, skb, req))
  		goto drop_and_free;
  
-@@ -621,7 +622,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
+@@ -621,7 +616,6 @@ int dccp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
  	 * In fact we defer setting S.GSR, S.SWL, S.SWH to
  	 * dccp_create_openreq_child.
  	 */
@@ -920462,7 +999478,7 @@
  	dreq->dreq_isr	   = dcb->dccpd_seq;
  	dreq->dreq_iss	   = dccp_v4_init_sequence(skb);
  	dreq->dreq_service = service;
-@@ -817,7 +817,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
+@@ -817,7 +811,7 @@ static int dccp_v4_rcv(struct sk_buff *skb)
  
  	/* Step 2:
  	 *	Look up flow ID in table and get corresponding socket */
@@ -920471,11 +999487,65 @@
  			   iph->saddr, dh->dccph_sport,
  			   iph->daddr, dh->dccph_dport, inet_iif(skb));
  	/*
+@@ -898,6 +892,7 @@ static struct inet_connection_sock_af_ops dccp_ipv4_af_ops = {
+ 	.getsockopt	   = ip_getsockopt,
+ 	.addr2sockaddr	   = inet_csk_addr2sockaddr,
+ 	.sockaddr_len	   = sizeof(struct sockaddr_in),
++	.bind_conflict	   = inet_csk_bind_conflict,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_ip_setsockopt,
+ 	.compat_getsockopt = compat_ip_getsockopt,
+@@ -937,10 +932,10 @@ static struct proto dccp_v4_prot = {
+ 	.sendmsg		= dccp_sendmsg,
+ 	.recvmsg		= dccp_recvmsg,
+ 	.backlog_rcv		= dccp_v4_do_rcv,
+-	.hash			= dccp_hash,
+-	.unhash			= dccp_unhash,
++	.hash			= inet_hash,
++	.unhash			= inet_unhash,
+ 	.accept			= inet_csk_accept,
+-	.get_port		= dccp_v4_get_port,
++	.get_port		= inet_csk_get_port,
+ 	.shutdown		= dccp_shutdown,
+ 	.destroy		= dccp_destroy_sock,
+ 	.orphan_count		= &dccp_orphan_count,
+@@ -948,6 +943,7 @@ static struct proto dccp_v4_prot = {
+ 	.obj_size		= sizeof(struct dccp_sock),
+ 	.rsk_prot		= &dccp_request_sock_ops,
+ 	.twsk_prot		= &dccp_timewait_sock_ops,
++	.hashinfo		= &dccp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt	= compat_dccp_setsockopt,
+ 	.compat_getsockopt	= compat_dccp_getsockopt,
 diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
-index 87c98fb..ed0a005 100644
+index 87c98fb..490333d 100644
 --- a/net/dccp/ipv6.c
 +++ b/net/dccp/ipv6.c
-@@ -101,8 +101,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+@@ -39,21 +39,15 @@ static struct socket *dccp_v6_ctl_socket;
+ static struct inet_connection_sock_af_ops dccp_ipv6_mapped;
+ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops;
+ 
+-static int dccp_v6_get_port(struct sock *sk, unsigned short snum)
+-{
+-	return inet_csk_get_port(&dccp_hashinfo, sk, snum,
+-				 inet6_csk_bind_conflict);
+-}
+-
+ static void dccp_v6_hash(struct sock *sk)
+ {
+ 	if (sk->sk_state != DCCP_CLOSED) {
+ 		if (inet_csk(sk)->icsk_af_ops == &dccp_ipv6_mapped) {
+-			dccp_hash(sk);
++			inet_hash(sk);
+ 			return;
+ 		}
+ 		local_bh_disable();
+-		__inet6_hash(&dccp_hashinfo, sk);
++		__inet6_hash(sk);
+ 		local_bh_enable();
+ 	}
+ }
+@@ -101,8 +95,8 @@ static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  	int err;
  	__u64 seq;
  
@@ -920486,7 +999556,7 @@
  
  	if (sk == NULL) {
  		ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
-@@ -366,7 +366,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+@@ -366,7 +360,7 @@ static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
  	if (req != NULL)
  		return dccp_check_req(sk, skb, req, prev);
  
@@ -920495,7 +999565,7 @@
  					 &iph->saddr, dh->dccph_sport,
  					 &iph->daddr, ntohs(dh->dccph_dport),
  					 inet6_iif(skb));
-@@ -415,11 +415,12 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+@@ -415,11 +409,12 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
  	if (req == NULL)
  		goto drop;
  
@@ -920511,7 +999581,7 @@
  	if (security_inet_conn_request(sk, skb, req))
  		goto drop_and_free;
  
-@@ -449,7 +450,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
+@@ -449,7 +444,6 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
  	 *   In fact we defer setting S.GSR, S.SWL, S.SWH to
  	 *   dccp_create_openreq_child.
  	 */
@@ -920519,7 +999589,18 @@
  	dreq->dreq_isr	   = dcb->dccpd_seq;
  	dreq->dreq_iss	   = dccp_v6_init_sequence(skb);
  	dreq->dreq_service = service;
-@@ -797,7 +797,7 @@ static int dccp_v6_rcv(struct sk_buff *skb)
+@@ -630,8 +624,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
+ 
+ 	newinet->daddr = newinet->saddr = newinet->rcv_saddr = LOOPBACK4_IPV6;
+ 
+-	__inet6_hash(&dccp_hashinfo, newsk);
+-	inet_inherit_port(&dccp_hashinfo, sk, newsk);
++	__inet6_hash(newsk);
++	inet_inherit_port(sk, newsk);
+ 
+ 	return newsk;
+ 
+@@ -797,7 +791,7 @@ static int dccp_v6_rcv(struct sk_buff *skb)
  
  	/* Step 2:
  	 *	Look up flow ID in table and get corresponding socket */
@@ -920528,7 +999609,7 @@
  			    dh->dccph_sport,
  			    &ipv6_hdr(skb)->daddr, ntohs(dh->dccph_dport),
  			    inet6_iif(skb));
-@@ -994,7 +994,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
+@@ -994,7 +988,7 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
  	if (final_p)
  		ipv6_addr_copy(&fl.fl6_dst, final_p);
  
@@ -920537,6 +999618,34 @@
  	if (err < 0) {
  		if (err == -EREMOTE)
  			err = ip6_dst_blackhole(sk, &dst, &fl);
+@@ -1054,6 +1048,7 @@ static struct inet_connection_sock_af_ops dccp_ipv6_af_ops = {
+ 	.getsockopt	   = ipv6_getsockopt,
+ 	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
+ 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
++	.bind_conflict	   = inet6_csk_bind_conflict,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_ipv6_setsockopt,
+ 	.compat_getsockopt = compat_ipv6_getsockopt,
+@@ -1123,9 +1118,9 @@ static struct proto dccp_v6_prot = {
+ 	.recvmsg	   = dccp_recvmsg,
+ 	.backlog_rcv	   = dccp_v6_do_rcv,
+ 	.hash		   = dccp_v6_hash,
+-	.unhash		   = dccp_unhash,
++	.unhash		   = inet_unhash,
+ 	.accept		   = inet_csk_accept,
+-	.get_port	   = dccp_v6_get_port,
++	.get_port	   = inet_csk_get_port,
+ 	.shutdown	   = dccp_shutdown,
+ 	.destroy	   = dccp_v6_destroy_sock,
+ 	.orphan_count	   = &dccp_orphan_count,
+@@ -1133,6 +1128,7 @@ static struct proto dccp_v6_prot = {
+ 	.obj_size	   = sizeof(struct dccp6_sock),
+ 	.rsk_prot	   = &dccp6_request_sock_ops,
+ 	.twsk_prot	   = &dccp6_timewait_sock_ops,
++	.hashinfo	   = &dccp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_dccp_setsockopt,
+ 	.compat_getsockopt = compat_dccp_getsockopt,
 diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c
 index 831b76e..027d181 100644
 --- a/net/dccp/minisocks.c
@@ -920995,7 +1000104,7 @@
  		dccp_transmit_skb(sk, skb);
  }
 diff --git a/net/dccp/proto.c b/net/dccp/proto.c
-index 7a3bea9..0bed4a6 100644
+index 7a3bea9..e3f5d37 100644
 --- a/net/dccp/proto.c
 +++ b/net/dccp/proto.c
 @@ -60,8 +60,7 @@ void dccp_set_state(struct sock *sk, const int state)
@@ -921008,7 +1000117,7 @@
  		      dccp_state_name(oldstate), dccp_state_name(state));
  	WARN_ON(state == oldstate);
  
-@@ -72,7 +71,8 @@ void dccp_set_state(struct sock *sk, const int state)
+@@ -72,13 +71,14 @@ void dccp_set_state(struct sock *sk, const int state)
  		break;
  
  	case DCCP_CLOSED:
@@ -921018,6 +1000127,13 @@
  			DCCP_INC_STATS(DCCP_MIB_ESTABRESETS);
  
  		sk->sk_prot->unhash(sk);
+ 		if (inet_csk(sk)->icsk_bind_hash != NULL &&
+ 		    !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
+-			inet_put_port(&dccp_hashinfo, sk);
++			inet_put_port(sk);
+ 		/* fall through */
+ 	default:
+ 		if (oldstate == DCCP_OPEN)
 @@ -93,6 +93,24 @@ void dccp_set_state(struct sock *sk, const int state)
  
  EXPORT_SYMBOL_GPL(dccp_set_state);
@@ -921069,7 +1000185,28 @@
  	};
  
  	if (state >= DCCP_MAX_STATES)
-@@ -174,6 +195,19 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
+@@ -152,20 +173,6 @@ const char *dccp_state_name(const int state)
+ 
+ EXPORT_SYMBOL_GPL(dccp_state_name);
+ 
+-void dccp_hash(struct sock *sk)
+-{
+-	inet_hash(&dccp_hashinfo, sk);
+-}
+-
+-EXPORT_SYMBOL_GPL(dccp_hash);
+-
+-void dccp_unhash(struct sock *sk)
+-{
+-	inet_unhash(&dccp_hashinfo, sk);
+-}
+-
+-EXPORT_SYMBOL_GPL(dccp_unhash);
+-
+ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
+ {
+ 	struct dccp_sock *dp = dccp_sk(sk);
+@@ -174,6 +181,19 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
  
  	dccp_minisock_init(&dp->dccps_minisock);
  
@@ -921089,7 +1000226,7 @@
  	/*
  	 * FIXME: We're hardcoding the CCID, and doing this at this point makes
  	 * the listening (master) sock get CCID control blocks, which is not
-@@ -213,18 +247,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
+@@ -213,18 +233,6 @@ int dccp_init_sock(struct sock *sk, const __u8 ctl_sock_initialized)
  		INIT_LIST_HEAD(&dmsk->dccpms_conf);
  	}
  
@@ -921108,7 +1000245,16 @@
  	return 0;
  }
  
-@@ -275,6 +297,12 @@ static inline int dccp_listen_start(struct sock *sk, int backlog)
+@@ -246,7 +254,7 @@ int dccp_destroy_sock(struct sock *sk)
+ 
+ 	/* Clean up a referenced DCCP bind bucket. */
+ 	if (inet_csk(sk)->icsk_bind_hash != NULL)
+-		inet_put_port(&dccp_hashinfo, sk);
++		inet_put_port(sk);
+ 
+ 	kfree(dp->dccps_service_list);
+ 	dp->dccps_service_list = NULL;
+@@ -275,6 +283,12 @@ static inline int dccp_listen_start(struct sock *sk, int backlog)
  	return inet_csk_listen_start(sk, backlog);
  }
  
@@ -921121,7 +1000267,7 @@
  int dccp_disconnect(struct sock *sk, int flags)
  {
  	struct inet_connection_sock *icsk = inet_csk(sk);
-@@ -285,10 +313,15 @@ int dccp_disconnect(struct sock *sk, int flags)
+@@ -285,10 +299,15 @@ int dccp_disconnect(struct sock *sk, int flags)
  	if (old_state != DCCP_CLOSED)
  		dccp_set_state(sk, DCCP_CLOSED);
  
@@ -921139,7 +1000285,7 @@
  	} else if (old_state == DCCP_REQUESTING)
  		sk->sk_err = ECONNRESET;
  
-@@ -518,6 +551,12 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
+@@ -518,6 +537,12 @@ static int do_dccp_setsockopt(struct sock *sk, int level, int optname,
  						     (struct dccp_so_feat __user *)
  						     optval);
  		break;
@@ -921152,7 +1000298,7 @@
  	case DCCP_SOCKOPT_SEND_CSCOV:	/* sender side, RFC 4340, sec. 9.2 */
  		if (val < 0 || val > 15)
  			err = -EINVAL;
-@@ -618,15 +657,15 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
+@@ -618,15 +643,15 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
  					       (__be32 __user *)optval, optlen);
  	case DCCP_SOCKOPT_GET_CUR_MPS:
  		val = dp->dccps_mss_cache;
@@ -921171,7 +1000317,7 @@
  		break;
  	case 128 ... 191:
  		return ccid_hc_rx_getsockopt(dp->dccps_hc_rx_ccid, sk, optname,
-@@ -638,6 +677,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
+@@ -638,6 +663,7 @@ static int do_dccp_getsockopt(struct sock *sk, int level, int optname,
  		return -ENOPROTOOPT;
  	}
  
@@ -921179,7 +1000325,7 @@
  	if (put_user(len, optlen) || copy_to_user(optval, &val, len))
  		return -EFAULT;
  
-@@ -748,19 +788,26 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+@@ -748,19 +774,26 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
  
  		dh = dccp_hdr(skb);
  
@@ -921214,7 +1000360,7 @@
  verify_sock_status:
  		if (sock_flag(sk, SOCK_DONE)) {
  			len = 0;
-@@ -862,34 +909,38 @@ out:
+@@ -862,34 +895,38 @@ out:
  
  EXPORT_SYMBOL_GPL(inet_dccp_listen);
  
@@ -921272,7 +1000418,7 @@
  	int state;
  
  	lock_sock(sk);
-@@ -912,16 +963,21 @@ void dccp_close(struct sock *sk, long timeout)
+@@ -912,16 +949,21 @@ void dccp_close(struct sock *sk, long timeout)
  	 * descriptor close, not protocol-sourced closes, because the
  	  *reader process may not have drained the data yet!
  	 */
@@ -921298,7 +1000444,7 @@
  	}
  
  	sk_stream_wait_close(sk, timeout);
-@@ -948,24 +1004,6 @@ adjudge_to_death:
+@@ -948,24 +990,6 @@ adjudge_to_death:
  	if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED)
  		goto out;
  
@@ -921323,7 +1000469,7 @@
  	if (sk->sk_state == DCCP_CLOSED)
  		inet_csk_destroy_sock(sk);
  
-@@ -981,7 +1019,7 @@ EXPORT_SYMBOL_GPL(dccp_close);
+@@ -981,7 +1005,7 @@ EXPORT_SYMBOL_GPL(dccp_close);
  
  void dccp_shutdown(struct sock *sk, int how)
  {
@@ -922890,7 +1002036,7 @@
  
  static int __init arp_proc_init(void)
 diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
-index f18e88b..a224106 100644
+index f18e88b..8cd357f 100644
 --- a/net/ipv4/cipso_ipv4.c
 +++ b/net/ipv4/cipso_ipv4.c
 @@ -63,7 +63,7 @@ struct cipso_v4_domhsh_entry {
@@ -922910,6 +1002056,17 @@
  			if (prev_entry == NULL) {
  				spin_unlock_bh(&cipso_v4_cache[bkt].lock);
  				return 0;
+@@ -546,8 +547,8 @@ int cipso_v4_doi_remove(u32 doi,
+ 		rcu_read_lock();
+ 		list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
+ 			if (dom_iter->valid)
+-				netlbl_domhsh_remove(dom_iter->domain,
+-						     audit_info);
++				netlbl_cfg_map_del(dom_iter->domain,
++						   audit_info);
+ 		rcu_read_unlock();
+ 		cipso_v4_cache_invalidate();
+ 		call_rcu(&doi_def->rcu, callback);
 @@ -865,7 +866,7 @@ static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
  	}
  
@@ -926133,7 +1005290,7 @@
  	}
  
 diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
-index 1010b46..35851c9 100644
+index 1010b46..f5fba3f 100644
 --- a/net/ipv4/fib_trie.c
 +++ b/net/ipv4/fib_trie.c
 @@ -82,7 +82,6 @@
@@ -927717,7 +1006874,7 @@
  			seq_puts(seq, "<local>:\n");
  		else
  			seq_puts(seq, "<main>:\n");
-@@ -2347,25 +2411,29 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
+@@ -2347,25 +2411,28 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
  
  	} else {
  		struct leaf *l = (struct leaf *) n;
@@ -927756,13 +1006913,12 @@
 +					   rtn_type(buf2, sizeof(buf2),
 +						    fa->fa_type));
 +				if (fa->fa_tos)
-+					seq_printf(seq, "tos =%d\n",
-+						   fa->fa_tos);
++					seq_printf(seq, " tos=%d", fa->fa_tos);
 +				seq_putc(seq, '\n');
  			}
  		}
  	}
-@@ -2382,8 +2450,8 @@ static const struct seq_operations fib_trie_seq_ops = {
+@@ -2382,8 +2449,8 @@ static const struct seq_operations fib_trie_seq_ops = {
  
  static int fib_trie_seq_open(struct inode *inode, struct file *file)
  {
@@ -927773,7 +1006929,7 @@
  }
  
  static const struct file_operations fib_trie_fops = {
-@@ -2391,7 +2459,7 @@ static const struct file_operations fib_trie_fops = {
+@@ -2391,7 +2458,7 @@ static const struct file_operations fib_trie_fops = {
  	.open   = fib_trie_seq_open,
  	.read   = seq_read,
  	.llseek = seq_lseek,
@@ -927782,7 +1006938,7 @@
  };
  
  static unsigned fib_flag_trans(int type, __be32 mask, const struct fib_info *fi)
-@@ -2419,8 +2487,8 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+@@ -2419,8 +2486,8 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
  {
  	const struct fib_trie_iter *iter = seq->private;
  	struct leaf *l = v;
@@ -927793,7 +1006949,7 @@
  
  	if (v == SEQ_START_TOKEN) {
  		seq_printf(seq, "%-127s\n", "Iface\tDestination\tGateway "
-@@ -2429,25 +2497,23 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+@@ -2429,25 +2496,23 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
  		return 0;
  	}
  
@@ -927823,7 +1006979,7 @@
  
  			if (fa->fa_type == RTN_BROADCAST
  			    || fa->fa_type == RTN_MULTICAST)
-@@ -2461,7 +2527,8 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
+@@ -2461,7 +2526,8 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
  					 fi->fib_nh->nh_gw, flags, 0, 0,
  					 fi->fib_priority,
  					 mask,
@@ -927833,7 +1006989,7 @@
  					 fi->fib_window,
  					 fi->fib_rtt >> 3);
  			else
-@@ -2486,8 +2553,8 @@ static const struct seq_operations fib_route_seq_ops = {
+@@ -2486,8 +2552,8 @@ static const struct seq_operations fib_route_seq_ops = {
  
  static int fib_route_seq_open(struct inode *inode, struct file *file)
  {
@@ -927844,7 +1007000,7 @@
  }
  
  static const struct file_operations fib_route_fops = {
-@@ -2495,35 +2562,36 @@ static const struct file_operations fib_route_fops = {
+@@ -2495,35 +2561,36 @@ static const struct file_operations fib_route_fops = {
  	.open   = fib_route_seq_open,
  	.read   = seq_read,
  	.llseek = seq_lseek,
@@ -927893,7 +1007049,7 @@
  
  #endif /* CONFIG_PROC_FS */
 diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
-index 82baea0..a7321a8 100644
+index 82baea0..a13c074 100644
 --- a/net/ipv4/icmp.c
 +++ b/net/ipv4/icmp.c
 @@ -92,6 +92,7 @@
@@ -928130,16 +1007286,15 @@
  	ICMP_INC_STATS_BH(ICMP_MIB_INMSGS);
  
  	switch (skb->ip_summed) {
-@@ -942,8 +1015,7 @@ int icmp_rcv(struct sk_buff *skb)
+@@ -942,7 +1015,7 @@ int icmp_rcv(struct sk_buff *skb)
  			goto error;
  	}
  
 -	if (!pskb_pull(skb, sizeof(struct icmphdr)))
--		goto error;
-+	__skb_pull(skb, sizeof(*icmph));
++	if (!pskb_pull(skb, sizeof(*icmph)))
+ 		goto error;
  
  	icmph = icmp_hdr(skb);
- 
 diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
 index 7dbc282..994648b 100644
 --- a/net/ipv4/igmp.c
@@ -928352,10 +1007507,21 @@
  	struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
  	if (likely(state->in_dev != NULL)) {
 diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
-index 8fb6ca2..de5a41d 100644
+index 8fb6ca2..b189278 100644
 --- a/net/ipv4/inet_connection_sock.c
 +++ b/net/ipv4/inet_connection_sock.c
-@@ -87,6 +87,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+@@ -78,15 +78,14 @@ EXPORT_SYMBOL_GPL(inet_csk_bind_conflict);
+ /* Obtain a reference to a local port for the given sock,
+  * if snum is zero it means select any available local port.
+  */
+-int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+-		      struct sock *sk, unsigned short snum,
+-		      int (*bind_conflict)(const struct sock *sk,
+-					   const struct inet_bind_bucket *tb))
++int inet_csk_get_port(struct sock *sk, unsigned short snum)
+ {
++	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
+ 	struct inet_bind_hashbucket *head;
  	struct hlist_node *node;
  	struct inet_bind_bucket *tb;
  	int ret;
@@ -928363,7 +1007529,7 @@
  
  	local_bh_disable();
  	if (!snum) {
-@@ -100,7 +101,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+@@ -100,7 +99,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
  			head = &hashinfo->bhash[inet_bhashfn(rover, hashinfo->bhash_size)];
  			spin_lock(&head->lock);
  			inet_bind_bucket_for_each(tb, node, &head->chain)
@@ -928372,7 +1007538,7 @@
  					goto next;
  			break;
  		next:
-@@ -127,7 +128,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
+@@ -127,7 +126,7 @@ int inet_csk_get_port(struct inet_hashinfo *hashinfo,
  		head = &hashinfo->bhash[inet_bhashfn(snum, hashinfo->bhash_size)];
  		spin_lock(&head->lock);
  		inet_bind_bucket_for_each(tb, node, &head->chain)
@@ -928381,7 +1007547,14 @@
  				goto tb_found;
  	}
  	tb = NULL;
-@@ -147,7 +148,8 @@ tb_found:
+@@ -141,13 +140,14 @@ tb_found:
+ 			goto success;
+ 		} else {
+ 			ret = 1;
+-			if (bind_conflict(sk, tb))
++			if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb))
+ 				goto fail_unlock;
+ 		}
  	}
  tb_not_found:
  	ret = 1;
@@ -928391,7 +1007564,7 @@
  		goto fail_unlock;
  	if (hlist_empty(&tb->owners)) {
  		if (sk->sk_reuse && sk->sk_state != TCP_LISTEN)
-@@ -277,18 +279,11 @@ void inet_csk_init_xmit_timers(struct sock *sk,
+@@ -277,18 +277,11 @@ void inet_csk_init_xmit_timers(struct sock *sk,
  {
  	struct inet_connection_sock *icsk = inet_csk(sk);
  
@@ -928415,7 +1007588,7 @@
  	icsk->icsk_pending = icsk->icsk_ack.pending = 0;
  }
  
-@@ -340,7 +335,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
+@@ -340,7 +333,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
  					 .dport = ireq->rmt_port } } };
  
  	security_req_classify_flow(req, &fl);
@@ -928719,7 +1007892,7 @@
  }
  EXPORT_SYMBOL(inet_frag_find);
 diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
-index 67704da..48d4500 100644
+index 67704da..9cac6c0 100644
 --- a/net/ipv4/inet_hashtables.c
 +++ b/net/ipv4/inet_hashtables.c
 @@ -28,12 +28,14 @@
@@ -928737,7 +1007910,31 @@
  		tb->port      = snum;
  		tb->fastreuse = 0;
  		INIT_HLIST_HEAD(&tb->owners);
-@@ -96,6 +98,7 @@ EXPORT_SYMBOL(inet_put_port);
+@@ -64,8 +66,9 @@ void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
+ /*
+  * Get rid of any references to a local port held by the given sock.
+  */
+-static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
++static void __inet_put_port(struct sock *sk)
+ {
++	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
+ 	const int bhash = inet_bhashfn(inet_sk(sk)->num, hashinfo->bhash_size);
+ 	struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
+ 	struct inet_bind_bucket *tb;
+@@ -79,10 +82,10 @@ static void __inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
+ 	spin_unlock(&head->lock);
+ }
+ 
+-void inet_put_port(struct inet_hashinfo *hashinfo, struct sock *sk)
++void inet_put_port(struct sock *sk)
+ {
+ 	local_bh_disable();
+-	__inet_put_port(hashinfo, sk);
++	__inet_put_port(sk);
+ 	local_bh_enable();
+ }
+ 
+@@ -96,6 +99,7 @@ EXPORT_SYMBOL(inet_put_port);
   * exclusive lock release). It should be ifdefed really.
   */
  void inet_listen_wlock(struct inet_hashinfo *hashinfo)
@@ -928745,7 +1007942,7 @@
  {
  	write_lock(&hashinfo->lhash_lock);
  
-@@ -124,7 +127,8 @@ EXPORT_SYMBOL(inet_listen_wlock);
+@@ -124,7 +128,8 @@ EXPORT_SYMBOL(inet_listen_wlock);
   * remote address for the connection. So always assume those are both
   * wildcarded during the search since they can never be otherwise.
   */
@@ -928755,7 +1007952,7 @@
  					      const __be32 daddr,
  					      const unsigned short hnum,
  					      const int dif)
-@@ -136,7 +140,8 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
+@@ -136,7 +141,8 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
  	sk_for_each(sk, node, head) {
  		const struct inet_sock *inet = inet_sk(sk);
  
@@ -928765,7 +1007962,7 @@
  			const __be32 rcv_saddr = inet->rcv_saddr;
  			int score = sk->sk_family == PF_INET ? 1 : 0;
  
-@@ -162,7 +167,8 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
+@@ -162,7 +168,8 @@ static struct sock *inet_lookup_listener_slow(const struct hlist_head *head,
  }
  
  /* Optimize the common listener case. */
@@ -928775,7 +1007972,7 @@
  				    const __be32 daddr, const unsigned short hnum,
  				    const int dif)
  {
-@@ -177,9 +183,9 @@ struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
+@@ -177,9 +184,9 @@ struct sock *__inet_lookup_listener(struct inet_hashinfo *hashinfo,
  		if (inet->num == hnum && !sk->sk_node.next &&
  		    (!inet->rcv_saddr || inet->rcv_saddr == daddr) &&
  		    (sk->sk_family == PF_INET || !ipv6_only_sock(sk)) &&
@@ -928787,7 +1007984,7 @@
  	}
  	if (sk) {
  sherry_cache:
-@@ -190,6 +196,47 @@ sherry_cache:
+@@ -190,6 +197,47 @@ sherry_cache:
  }
  EXPORT_SYMBOL_GPL(__inet_lookup_listener);
  
@@ -928835,7 +1008032,7 @@
  /* called with local bh disabled */
  static int __inet_check_established(struct inet_timewait_death_row *death_row,
  				    struct sock *sk, __u16 lport,
-@@ -208,6 +255,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
+@@ -208,6 +256,7 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
  	struct sock *sk2;
  	const struct hlist_node *node;
  	struct inet_timewait_sock *tw;
@@ -928843,7 +1008040,7 @@
  
  	prefetch(head->chain.first);
  	write_lock(lock);
-@@ -216,7 +264,8 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
+@@ -216,7 +265,8 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
  	sk_for_each(sk2, node, &head->twchain) {
  		tw = inet_twsk(sk2);
  
@@ -928853,7 +1008050,7 @@
  			if (twsk_unique(sk, sk2, twp))
  				goto unique;
  			else
-@@ -227,7 +276,8 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
+@@ -227,7 +277,8 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
  
  	/* And established part... */
  	sk_for_each(sk2, node, &head->chain) {
@@ -928863,7 +1008060,7 @@
  			goto not_unique;
  	}
  
-@@ -239,7 +289,7 @@ unique:
+@@ -239,7 +290,7 @@ unique:
  	sk->sk_hash = hash;
  	BUG_TRAP(sk_unhashed(sk));
  	__sk_add_node(sk, &head->chain);
@@ -928872,7 +1008069,7 @@
  	write_unlock(lock);
  
  	if (twp) {
-@@ -267,17 +317,60 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
+@@ -267,22 +318,102 @@ static inline u32 inet_sk_port_offset(const struct sock *sk)
  					  inet->dport);
  }
  
@@ -928881,8 +1008078,9 @@
 - */
 -int inet_hash_connect(struct inet_timewait_death_row *death_row,
 -		      struct sock *sk)
-+void __inet_hash_nolisten(struct inet_hashinfo *hashinfo, struct sock *sk)
++void __inet_hash_nolisten(struct sock *sk)
 +{
++	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
 +	struct hlist_head *list;
 +	rwlock_t *lock;
 +	struct inet_ehash_bucket *head;
@@ -928901,13 +1008099,14 @@
 +}
 +EXPORT_SYMBOL_GPL(__inet_hash_nolisten);
 +
-+void __inet_hash(struct inet_hashinfo *hashinfo, struct sock *sk)
++static void __inet_hash(struct sock *sk)
 +{
++	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
 +	struct hlist_head *list;
 +	rwlock_t *lock;
 +
 +	if (sk->sk_state != TCP_LISTEN) {
-+		__inet_hash_nolisten(hashinfo, sk);
++		__inet_hash_nolisten(sk);
 +		return;
 +	}
 +
@@ -928921,13 +1008120,48 @@
 +	write_unlock(lock);
 +	wake_up(&hashinfo->lhash_wait);
 +}
-+EXPORT_SYMBOL_GPL(__inet_hash);
++
++void inet_hash(struct sock *sk)
++{
++	if (sk->sk_state != TCP_CLOSE) {
++		local_bh_disable();
++		__inet_hash(sk);
++		local_bh_enable();
++	}
++}
++EXPORT_SYMBOL_GPL(inet_hash);
++
++void inet_unhash(struct sock *sk)
++{
++	rwlock_t *lock;
++	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
++
++	if (sk_unhashed(sk))
++		goto out;
++
++	if (sk->sk_state == TCP_LISTEN) {
++		local_bh_disable();
++		inet_listen_wlock(hashinfo);
++		lock = &hashinfo->lhash_lock;
++	} else {
++		lock = inet_ehash_lockp(hashinfo, sk->sk_hash);
++		write_lock_bh(lock);
++	}
++
++	if (__sk_del_node_init(sk))
++		sock_prot_inuse_add(sk->sk_prot, -1);
++	write_unlock_bh(lock);
++out:
++	if (sk->sk_state == TCP_LISTEN)
++		wake_up(&hashinfo->lhash_wait);
++}
++EXPORT_SYMBOL_GPL(inet_unhash);
 +
 +int __inet_hash_connect(struct inet_timewait_death_row *death_row,
-+		struct sock *sk,
++		struct sock *sk, u32 port_offset,
 +		int (*check_established)(struct inet_timewait_death_row *,
 +			struct sock *, __u16, struct inet_timewait_sock **),
-+		void (*hash)(struct inet_hashinfo *, struct sock *))
++		void (*hash)(struct sock *sk))
  {
  	struct inet_hashinfo *hinfo = death_row->hashinfo;
  	const unsigned short snum = inet_sk(sk)->num;
@@ -928938,7 +1008172,13 @@
  
  	if (!snum) {
  		int i, remaining, low, high, port;
-@@ -300,19 +393,19 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row,
+ 		static u32 hint;
+-		u32 offset = hint + inet_sk_port_offset(sk);
++		u32 offset = hint + port_offset;
+ 		struct hlist_node *node;
+ 		struct inet_timewait_sock *tw = NULL;
+ 
+@@ -300,19 +431,19 @@ int inet_hash_connect(struct inet_timewait_death_row *death_row,
  			 * unique enough.
  			 */
  			inet_bind_bucket_for_each(tb, node, &head->chain) {
@@ -928963,21 +1008203,21 @@
  			if (!tb) {
  				spin_unlock(&head->lock);
  				break;
-@@ -334,7 +427,7 @@ ok:
+@@ -334,7 +465,7 @@ ok:
  		inet_bind_hash(sk, tb, port);
  		if (sk_unhashed(sk)) {
  			inet_sk(sk)->sport = htons(port);
 -			__inet_hash(hinfo, sk, 0);
-+			hash(hinfo, sk);
++			hash(sk);
  		}
  		spin_unlock(&head->lock);
  
-@@ -351,17 +444,28 @@ ok:
+@@ -351,17 +482,28 @@ ok:
  	tb  = inet_csk(sk)->icsk_bind_hash;
  	spin_lock_bh(&head->lock);
  	if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
 -		__inet_hash(hinfo, sk, 0);
-+		hash(hinfo, sk);
++		hash(sk);
  		spin_unlock_bh(&head->lock);
  		return 0;
  	} else {
@@ -928998,7 +1008238,7 @@
 +int inet_hash_connect(struct inet_timewait_death_row *death_row,
 +		      struct sock *sk)
 +{
-+	return __inet_hash_connect(death_row, sk,
++	return __inet_hash_connect(death_row, sk, inet_sk_port_offset(sk),
 +			__inet_check_established, __inet_hash_nolisten);
 +}
  
@@ -941030,7 +1020270,7 @@
 -EXPORT_SYMBOL(ipv4_config);
 +__initcall(sysctl_ipv4_init);
 diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
-index 8e65182..a0d373b 100644
+index 8e65182..071e83a 100644
 --- a/net/ipv4/tcp.c
 +++ b/net/ipv4/tcp.c
 @@ -254,6 +254,10 @@
@@ -941314,7 +1020554,7 @@
 +		sk->sk_prot->unhash(sk);
 +		if (inet_csk(sk)->icsk_bind_hash &&
 +		    !(sk->sk_userlocks & SOCK_BINDPORT_LOCK))
-+			inet_put_port(&tcp_hashinfo, sk);
++			inet_put_port(sk);
 +		/* fall through */
 +	default:
 +		if (oldstate==TCP_ESTABLISHED)
@@ -943915,7 +1023155,7 @@
  
  				if (tp->rx_opt.tstamp_ok)
 diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
-index 652c323..77c1939 100644
+index 652c323..63414ea 100644
 --- a/net/ipv4/tcp_ipv4.c
 +++ b/net/ipv4/tcp_ipv4.c
 @@ -99,7 +99,7 @@ static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
@@ -943927,7 +1023167,30 @@
  #endif
  
  struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
-@@ -369,8 +369,8 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
+@@ -108,22 +108,6 @@ struct inet_hashinfo __cacheline_aligned tcp_hashinfo = {
+ 	.lhash_wait  = __WAIT_QUEUE_HEAD_INITIALIZER(tcp_hashinfo.lhash_wait),
+ };
+ 
+-static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
+-{
+-	return inet_csk_get_port(&tcp_hashinfo, sk, snum,
+-				 inet_csk_bind_conflict);
+-}
+-
+-static void tcp_v4_hash(struct sock *sk)
+-{
+-	inet_hash(&tcp_hashinfo, sk);
+-}
+-
+-void tcp_unhash(struct sock *sk)
+-{
+-	inet_unhash(&tcp_hashinfo, sk);
+-}
+-
+ static inline __u32 tcp_v4_init_sequence(struct sk_buff *skb)
+ {
+ 	return secure_tcp_sequence_number(ip_hdr(skb)->daddr,
+@@ -369,8 +353,8 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
  		return;
  	}
  
@@ -943938,7 +1023201,7 @@
  	if (!sk) {
  		ICMP_INC_STATS_BH(ICMP_MIB_INERRORS);
  		return;
-@@ -1020,7 +1020,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
+@@ -1020,7 +1004,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
  static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
  				   __be32 saddr, __be32 daddr,
  				   struct tcphdr *th, int protocol,
@@ -943947,7 +1023210,7 @@
  {
  	struct scatterlist sg[4];
  	__u16 data_len;
-@@ -1113,7 +1113,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+@@ -1113,7 +1097,7 @@ int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
  			 struct dst_entry *dst,
  			 struct request_sock *req,
  			 struct tcphdr *th, int protocol,
@@ -943956,16 +1023219,18 @@
  {
  	__be32 saddr, daddr;
  
-@@ -1478,7 +1478,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+@@ -1478,8 +1462,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
  	}
  #endif
  
 -	__inet_hash(&tcp_hashinfo, newsk, 0);
-+	__inet_hash_nolisten(&tcp_hashinfo, newsk);
- 	__inet_inherit_port(&tcp_hashinfo, sk, newsk);
+-	__inet_inherit_port(&tcp_hashinfo, sk, newsk);
++	__inet_hash_nolisten(newsk);
++	__inet_inherit_port(sk, newsk);
  
  	return newsk;
-@@ -1503,8 +1503,8 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
+ 
+@@ -1503,8 +1487,8 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
  	if (req)
  		return tcp_check_req(sk, skb, req, prev);
  
@@ -943976,7 +1023241,7 @@
  
  	if (nsk) {
  		if (nsk->sk_state != TCP_TIME_WAIT) {
-@@ -1661,8 +1661,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
+@@ -1661,8 +1645,8 @@ int tcp_v4_rcv(struct sk_buff *skb)
  	TCP_SKB_CB(skb)->flags	 = iph->tos;
  	TCP_SKB_CB(skb)->sacked	 = 0;
  
@@ -943987,7 +1023252,7 @@
  	if (!sk)
  		goto no_tcp_socket;
  
-@@ -1735,7 +1735,8 @@ do_time_wait:
+@@ -1735,7 +1719,8 @@ do_time_wait:
  	}
  	switch (tcp_timewait_state_process(inet_twsk(sk), skb, th)) {
  	case TCP_TW_SYN: {
@@ -943997,6 +1023262,52 @@
  							iph->daddr, th->dest,
  							inet_iif(skb));
  		if (sk2) {
+@@ -1826,6 +1811,7 @@ struct inet_connection_sock_af_ops ipv4_specific = {
+ 	.getsockopt	   = ip_getsockopt,
+ 	.addr2sockaddr	   = inet_csk_addr2sockaddr,
+ 	.sockaddr_len	   = sizeof(struct sockaddr_in),
++	.bind_conflict	   = inet_csk_bind_conflict,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_ip_setsockopt,
+ 	.compat_getsockopt = compat_ip_getsockopt,
+@@ -1925,7 +1911,7 @@ int tcp_v4_destroy_sock(struct sock *sk)
+ 
+ 	/* Clean up a referenced TCP bind bucket. */
+ 	if (inet_csk(sk)->icsk_bind_hash)
+-		inet_put_port(&tcp_hashinfo, sk);
++		inet_put_port(sk);
+ 
+ 	/*
+ 	 * If sendmsg cached page exists, toss it.
+@@ -2434,9 +2420,9 @@ struct proto tcp_prot = {
+ 	.getsockopt		= tcp_getsockopt,
+ 	.recvmsg		= tcp_recvmsg,
+ 	.backlog_rcv		= tcp_v4_do_rcv,
+-	.hash			= tcp_v4_hash,
+-	.unhash			= tcp_unhash,
+-	.get_port		= tcp_v4_get_port,
++	.hash			= inet_hash,
++	.unhash			= inet_unhash,
++	.get_port		= inet_csk_get_port,
+ 	.enter_memory_pressure	= tcp_enter_memory_pressure,
+ 	.sockets_allocated	= &tcp_sockets_allocated,
+ 	.orphan_count		= &tcp_orphan_count,
+@@ -2449,6 +2435,7 @@ struct proto tcp_prot = {
+ 	.obj_size		= sizeof(struct tcp_sock),
+ 	.twsk_prot		= &tcp_timewait_sock_ops,
+ 	.rsk_prot		= &tcp_request_sock_ops,
++	.hashinfo		= &tcp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt	= compat_tcp_setsockopt,
+ 	.compat_getsockopt	= compat_tcp_getsockopt,
+@@ -2466,7 +2453,6 @@ void __init tcp_v4_init(struct net_proto_family *ops)
+ EXPORT_SYMBOL(ipv4_specific);
+ EXPORT_SYMBOL(tcp_hashinfo);
+ EXPORT_SYMBOL(tcp_prot);
+-EXPORT_SYMBOL(tcp_unhash);
+ EXPORT_SYMBOL(tcp_v4_conn_request);
+ EXPORT_SYMBOL(tcp_v4_connect);
+ EXPORT_SYMBOL(tcp_v4_do_rcv);
 diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
 index e7f5ef9..ce3c41f 100644
 --- a/net/ipv4/tcp_lp.c
@@ -946085,7 +1025396,7 @@
  /* If it's a keepalive packet, then just eat it.
   * If it's an encapsulated packet, then pass it to the
 diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
-index e42e122..e093a7b 100644
+index e42e122..b47030b 100644
 --- a/net/ipv4/xfrm4_mode_beet.c
 +++ b/net/ipv4/xfrm4_mode_beet.c
 @@ -17,6 +17,21 @@
@@ -946157,7 +1025468,7 @@
 +		XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;
  
 -		ph_nexthdr = ph->nexthdr;
-+		if (!pskb_may_pull(skb, phlen));
++		if (!pskb_may_pull(skb, phlen))
 +			goto out;
 +		__skb_pull(skb, phlen);
  	}
@@ -949881,7 +1029192,7 @@
  
  void fib6_rules_cleanup(void)
 diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
-index f124068..cbb5b9c 100644
+index f124068..121d517 100644
 --- a/net/ipv6/icmp.c
 +++ b/net/ipv6/icmp.c
 @@ -63,6 +63,7 @@
@@ -950046,17 +1029357,16 @@
  	ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INMSGS);
  
  	saddr = &ipv6_hdr(skb)->saddr;
-@@ -643,8 +683,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
+@@ -643,7 +683,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
  		}
  	}
  
 -	if (!pskb_pull(skb, sizeof(struct icmp6hdr)))
--		goto discard_it;
-+	__skb_pull(skb, sizeof(*hdr));
++	if (!pskb_pull(skb, sizeof(*hdr)))
+ 		goto discard_it;
  
  	hdr = icmp6_hdr(skb);
- 
-@@ -730,6 +769,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
+@@ -730,6 +770,7 @@ static int icmpv6_rcv(struct sk_buff *skb)
  
  discard_it:
  	ICMP6_INC_STATS_BH(idev, ICMP6_MIB_INERRORS);
@@ -950064,7 +1029374,7 @@
  	kfree_skb(skb);
  	return 0;
  }
-@@ -865,16 +905,26 @@ int icmpv6_err_convert(int type, int code, int *err)
+@@ -865,16 +906,26 @@ int icmpv6_err_convert(int type, int code, int *err)
  EXPORT_SYMBOL(icmpv6_err_convert);
  
  #ifdef CONFIG_SYSCTL
@@ -950094,9 +1029404,21 @@
  #endif
  
 diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
-index 0765d8b..d325a99 100644
+index 0765d8b..99fd25f 100644
 --- a/net/ipv6/inet6_hashtables.c
 +++ b/net/ipv6/inet6_hashtables.c
+@@ -22,9 +22,9 @@
+ #include <net/inet6_hashtables.h>
+ #include <net/ip.h>
+ 
+-void __inet6_hash(struct inet_hashinfo *hashinfo,
+-				struct sock *sk)
++void __inet6_hash(struct sock *sk)
+ {
++	struct inet_hashinfo *hashinfo = sk->sk_prot->hashinfo;
+ 	struct hlist_head *list;
+ 	rwlock_t *lock;
+ 
 @@ -43,7 +43,7 @@ void __inet6_hash(struct inet_hashinfo *hashinfo,
  	}
  
@@ -950320,7 +1029642,7 @@
 -		local_bh_enable();
 -		return ret;
 -	}
-+	return __inet_hash_connect(death_row, sk,
++	return __inet_hash_connect(death_row, sk, inet6_sk_port_offset(sk),
 +			__inet6_check_established, __inet6_hash);
  }
  
@@ -957499,10 +1036821,32 @@
 +	unregister_pernet_subsys(&ipv6_sysctl_net_ops);
 +}
 diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
-index 93980c3..59d0029 100644
+index 93980c3..12750f2 100644
 --- a/net/ipv6/tcp_ipv6.c
 +++ b/net/ipv6/tcp_ipv6.c
-@@ -265,7 +265,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
+@@ -86,12 +86,6 @@ static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
+ static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
+ #endif
+ 
+-static int tcp_v6_get_port(struct sock *sk, unsigned short snum)
+-{
+-	return inet_csk_get_port(&tcp_hashinfo, sk, snum,
+-				 inet6_csk_bind_conflict);
+-}
+-
+ static void tcp_v6_hash(struct sock *sk)
+ {
+ 	if (sk->sk_state != TCP_CLOSE) {
+@@ -100,7 +94,7 @@ static void tcp_v6_hash(struct sock *sk)
+ 			return;
+ 		}
+ 		local_bh_disable();
+-		__inet6_hash(&tcp_hashinfo, sk);
++		__inet6_hash(sk);
+ 		local_bh_enable();
+ 	}
+ }
+@@ -265,7 +259,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
  	if (final_p)
  		ipv6_addr_copy(&fl.fl6_dst, final_p);
  
@@ -957511,7 +1036855,7 @@
  		if (err == -EREMOTE)
  			err = ip6_dst_blackhole(sk, &dst, &fl);
  		if (err < 0)
-@@ -330,8 +330,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+@@ -330,8 +324,8 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
  	struct tcp_sock *tp;
  	__u32 seq;
  
@@ -957522,7 +1036866,7 @@
  
  	if (sk == NULL) {
  		ICMP6_INC_STATS_BH(__in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
-@@ -733,7 +733,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+@@ -733,7 +727,7 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
  				   struct in6_addr *saddr,
  				   struct in6_addr *daddr,
  				   struct tcphdr *th, int protocol,
@@ -957531,7 +1036875,7 @@
  {
  	struct scatterlist sg[4];
  	__u16 data_len;
-@@ -818,7 +818,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
+@@ -818,7 +812,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
  				struct dst_entry *dst,
  				struct request_sock *req,
  				struct tcphdr *th, int protocol,
@@ -957540,7 +1036884,7 @@
  {
  	struct in6_addr *saddr, *daddr;
  
-@@ -985,7 +985,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
+@@ -985,7 +979,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
  	struct tcphdr *th = tcp_hdr(skb), *t1;
  	struct sk_buff *buff;
  	struct flowi fl;
@@ -957549,7 +1036893,7 @@
  #ifdef CONFIG_TCP_MD5SIG
  	struct tcp_md5sig_key *key;
  #endif
-@@ -1085,7 +1085,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
+@@ -1085,7 +1079,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
  	struct tcphdr *th = tcp_hdr(skb), *t1;
  	struct sk_buff *buff;
  	struct flowi fl;
@@ -957558,7 +1036902,7 @@
  	__be32 *topt;
  #ifdef CONFIG_TCP_MD5SIG
  	struct tcp_md5sig_key *key;
-@@ -1208,9 +1208,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
+@@ -1208,9 +1202,9 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
  	if (req)
  		return tcp_check_req(sk, skb, req, prev);
  
@@ -957571,7 +1036915,18 @@
  
  	if (nsk) {
  		if (nsk->sk_state != TCP_TIME_WAIT) {
-@@ -1710,9 +1710,10 @@ static int tcp_v6_rcv(struct sk_buff *skb)
+@@ -1504,8 +1498,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
+ 	}
+ #endif
+ 
+-	__inet6_hash(&tcp_hashinfo, newsk);
+-	inet_inherit_port(&tcp_hashinfo, sk, newsk);
++	__inet6_hash(newsk);
++	inet_inherit_port(sk, newsk);
+ 
+ 	return newsk;
+ 
+@@ -1710,9 +1704,10 @@ static int tcp_v6_rcv(struct sk_buff *skb)
  	TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb));
  	TCP_SKB_CB(skb)->sacked = 0;
  
@@ -957585,7 +1036940,7 @@
  
  	if (!sk)
  		goto no_tcp_socket;
-@@ -1792,7 +1793,7 @@ do_time_wait:
+@@ -1792,7 +1787,7 @@ do_time_wait:
  	{
  		struct sock *sk2;
  
@@ -957594,7 +1036949,42 @@
  					    &ipv6_hdr(skb)->daddr,
  					    ntohs(th->dest), inet6_iif(skb));
  		if (sk2 != NULL) {
-@@ -2166,14 +2167,36 @@ static struct inet_protosw tcpv6_protosw = {
+@@ -1832,6 +1827,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
+ 	.getsockopt	   = ipv6_getsockopt,
+ 	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
+ 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
++	.bind_conflict	   = inet6_csk_bind_conflict,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_ipv6_setsockopt,
+ 	.compat_getsockopt = compat_ipv6_getsockopt,
+@@ -1863,6 +1859,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
+ 	.getsockopt	   = ipv6_getsockopt,
+ 	.addr2sockaddr	   = inet6_csk_addr2sockaddr,
+ 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
++	.bind_conflict	   = inet6_csk_bind_conflict,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt = compat_ipv6_setsockopt,
+ 	.compat_getsockopt = compat_ipv6_getsockopt,
+@@ -2126,8 +2123,8 @@ struct proto tcpv6_prot = {
+ 	.recvmsg		= tcp_recvmsg,
+ 	.backlog_rcv		= tcp_v6_do_rcv,
+ 	.hash			= tcp_v6_hash,
+-	.unhash			= tcp_unhash,
+-	.get_port		= tcp_v6_get_port,
++	.unhash			= inet_unhash,
++	.get_port		= inet_csk_get_port,
+ 	.enter_memory_pressure	= tcp_enter_memory_pressure,
+ 	.sockets_allocated	= &tcp_sockets_allocated,
+ 	.memory_allocated	= &tcp_memory_allocated,
+@@ -2140,6 +2137,7 @@ struct proto tcpv6_prot = {
+ 	.obj_size		= sizeof(struct tcp6_sock),
+ 	.twsk_prot		= &tcp6_timewait_sock_ops,
+ 	.rsk_prot		= &tcp6_request_sock_ops,
++	.hashinfo		= &tcp_hashinfo,
+ #ifdef CONFIG_COMPAT
+ 	.compat_setsockopt	= compat_tcp_setsockopt,
+ 	.compat_getsockopt	= compat_tcp_getsockopt,
+@@ -2166,14 +2164,36 @@ static struct inet_protosw tcpv6_protosw = {
  				INET_PROTOSW_ICSK,
  };
  
@@ -957621,17 +1037011,17 @@
 +		goto out_tcpv6_protosw;
 +out:
 +	return ret;
- 
--	if (inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, SOCK_RAW,
--				     IPPROTO_TCP) < 0)
--		panic("Failed to create the TCPv6 control socket.\n");
++
 +out_tcpv6_protocol:
 +	inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 +out_tcpv6_protosw:
 +	inet6_unregister_protosw(&tcpv6_protosw);
 +	goto out;
 +}
-+
+ 
+-	if (inet_csk_ctl_sock_create(&tcp6_socket, PF_INET6, SOCK_RAW,
+-				     IPPROTO_TCP) < 0)
+-		panic("Failed to create the TCPv6 control socket.\n");
 +void tcpv6_exit(void)
 +{
 +	sock_release(tcp6_socket);
@@ -959775,7 +1039165,7 @@
  	return llc_table_header ? 0 : -ENOMEM;
  }
 diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
-index ce176e6..09c2550 100644
+index ce176e6..e77592d 100644
 --- a/net/mac80211/Kconfig
 +++ b/net/mac80211/Kconfig
 @@ -10,27 +10,84 @@ config MAC80211
@@ -959841,16 +1039231,16 @@
 +	default "pid" if MAC80211_RC_DEFAULT_PID
 +	default "simple" if MAC80211_RC_DEFAULT_SIMPLE
 +	default ""
- 
--	  Say Y unless you know you will have another algorithm
--	  available.
++
 +config MAC80211_RC_PID
 +	tristate "PID controller based rate control algorithm"
 +	---help---
 +	  This option enables a TX rate control algorithm for
 +	  mac80211 that uses a PID controller to select the TX
 +	  rate.
-+
+ 
+-	  Say Y unless you know you will have another algorithm
+-	  available.
 +	  Say Y or M unless you're sure you want to use a
 +	  different rate control algorithm.
 +
@@ -959876,7 +1039266,26 @@
  
  config MAC80211_DEBUGFS
  	bool "Export mac80211 internals in DebugFS"
-@@ -51,6 +108,16 @@ config MAC80211_DEBUG
+@@ -41,6 +98,18 @@ config MAC80211_DEBUGFS
+ 
+ 	  Say N unless you know you need this.
+ 
++config MAC80211_DEBUG_PACKET_ALIGNMENT
++	bool "Enable packet alignment debugging"
++	depends on MAC80211
++	help
++	  This option is recommended for driver authors and strongly
++	  discouraged for everybody else, it will trigger a warning
++	  when a driver hands mac80211 a buffer that is aligned in
++	  a way that will cause problems with the IP stack on some
++	  architectures.
++
++	  Say N unless you're writing a mac80211 based driver.
++
+ config MAC80211_DEBUG
+ 	bool "Enable debugging output"
+ 	depends on MAC80211
+@@ -51,6 +120,16 @@ config MAC80211_DEBUG
  	  If you are not trying to debug or develop the ieee80211
  	  subsystem, you most likely want to say N here.
  
@@ -960703,7 +1040112,7 @@
  	sdata->debugfsdir = NULL;
  }
 diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
-index 6378850..5dcc2d6 100644
+index 6378850..67b7c75 100644
 --- a/net/mac80211/ieee80211.c
 +++ b/net/mac80211/ieee80211.c
 @@ -34,6 +34,8 @@
@@ -961070,14 +1040479,14 @@
 -#ifdef CONFIG_MAC80211_RCSIMPLE
 -	ret = ieee80211_rate_control_register(&mac80211_rcsimple);
 +	ret = rc80211_simple_init();
++	if (ret)
++		goto out;
++
++	ret = rc80211_pid_init();
  	if (ret)
 -		return ret;
 -#endif
-+		goto fail;
-+
-+	ret = rc80211_pid_init();
-+	if (ret)
-+		goto fail_simple;
++		goto out_cleanup_simple;
  
  	ret = ieee80211_wme_register();
  	if (ret) {
@@ -961087,7 +1040496,7 @@
  		printk(KERN_DEBUG "ieee80211_init: failed to "
  		       "initialize WME (err=%d)\n", ret);
 -		return ret;
-+		goto fail_pid;
++		goto out_cleanup_pid;
  	}
  
  	ieee80211_debugfs_netdev_init();
@@ -961095,11 +1040504,11 @@
  
  	return 0;
 +
-+ fail_pid:
-+	rc80211_simple_exit();
-+ fail_simple:
++ out_cleanup_pid:
 +	rc80211_pid_exit();
-+ fail:
++ out_cleanup_simple:
++	rc80211_simple_exit();
++ out:
 +	return ret;
  }
  
@@ -963603,7 +1043012,7 @@
 +#endif /* RC80211_PID_H */
 diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
 new file mode 100644
-index 0000000..554c4ba
+index 0000000..c339571
 --- /dev/null
 +++ b/net/mac80211/rc80211_pid_algo.c
 @@ -0,0 +1,549 @@
@@ -964147,7 +1043556,7 @@
 +	return ieee80211_rate_control_register(&mac80211_rcpid);
 +}
 +
-+void __exit rc80211_pid_exit(void)
++void rc80211_pid_exit(void)
 +{
 +	ieee80211_rate_control_unregister(&mac80211_rcpid);
 +}
@@ -964386,7 +1043795,7 @@
 +	debugfs_remove(spinfo->events_entry);
 +}
 diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c
-index da72737..934676d 100644
+index da72737..9a78b11 100644
 --- a/net/mac80211/rc80211_simple.c
 +++ b/net/mac80211/rc80211_simple.c
 @@ -13,6 +13,7 @@
@@ -964524,7 +1043933,7 @@
 +	return ieee80211_rate_control_register(&mac80211_rcsimple);
 +}
 +
-+void __exit rc80211_simple_exit(void)
++void rc80211_simple_exit(void)
 +{
 +	ieee80211_rate_control_unregister(&mac80211_rcsimple);
 +}
@@ -964534,7 +1043943,7 @@
 +module_exit(rc80211_simple_exit);
 +#endif
 diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
-index 00f908d..d44c872 100644
+index 00f908d..535407d 100644
 --- a/net/mac80211/rx.c
 +++ b/net/mac80211/rx.c
 @@ -24,6 +24,10 @@
@@ -964720,7 +1044129,7 @@
  			rate = &mode->rates[i];
  			break;
  		}
-@@ -308,8 +336,38 @@ ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx)
+@@ -308,16 +336,53 @@ ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx)
  
  	/* Divide channel_use by 8 to avoid wrapping around the counter */
  	load >>= CHAN_UTIL_SHIFT;
@@ -964730,11 +1044139,15 @@
 +	return load;
 +}
 +
++#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
 +static ieee80211_txrx_result
 +ieee80211_rx_h_verify_ip_alignment(struct ieee80211_txrx_data *rx)
 +{
 +	int hdrlen;
 +
++	if (!WLAN_FC_DATA_PRESENT(rx->fc))
++		return TXRX_CONTINUE;
++
 +	/*
 +	 * Drivers are required to align the payload data in a way that
 +	 * guarantees that the contained IP header is aligned to a four-
@@ -964761,16 +1044174,19 @@
  
  	return TXRX_CONTINUE;
  }
-@@ -317,7 +375,7 @@ ieee80211_rx_h_load_stats(struct ieee80211_txrx_data *rx)
++#endif
+ 
  ieee80211_rx_handler ieee80211_rx_pre_handlers[] =
  {
  	ieee80211_rx_h_parse_qos,
 -	ieee80211_rx_h_load_stats,
++#ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT
 +	ieee80211_rx_h_verify_ip_alignment,
++#endif
  	NULL
  };
  
-@@ -338,8 +396,14 @@ ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
+@@ -338,8 +403,14 @@ ieee80211_rx_h_passive_scan(struct ieee80211_txrx_data *rx)
  	struct ieee80211_local *local = rx->local;
  	struct sk_buff *skb = rx->skb;
  
@@ -964787,7 +1044203,7 @@
  		return TXRX_QUEUED;
  	}
  
-@@ -377,18 +441,6 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+@@ -377,18 +448,6 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
  		return TXRX_DROP;
  	}
  
@@ -964806,7 +1044222,7 @@
  	/* Drop disallowed frame classes based on STA auth/assoc state;
  	 * IEEE 802.11, Chap 5.5.
  	 *
-@@ -400,7 +452,7 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
+@@ -400,7 +459,7 @@ ieee80211_rx_h_check(struct ieee80211_txrx_data *rx)
  	if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA ||
  		      ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL &&
  		       (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) &&
@@ -964815,7 +1044231,7 @@
  		     (!rx->sta || !(rx->sta->flags & WLAN_STA_ASSOC)))) {
  		if ((!(rx->fc & IEEE80211_FCTL_FROMDS) &&
  		     !(rx->fc & IEEE80211_FCTL_TODS) &&
-@@ -620,13 +672,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
+@@ -620,13 +679,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_txrx_data *rx)
  	/* Update last_rx only for IBSS packets which are for the current
  	 * BSSID to avoid keeping the current IBSS network alive in cases where
  	 * other STAs are using different BSSID. */
@@ -964833,7 +1044249,7 @@
  		/* Update last_rx only for unicast frames in order to prevent
  		 * the Probe Request frames (the only broadcast frames from a
  		 * STA in infrastructure mode) from keeping a connection alive.
-@@ -870,6 +923,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
+@@ -870,6 +930,7 @@ ieee80211_rx_h_defragment(struct ieee80211_txrx_data *rx)
  static ieee80211_txrx_result
  ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
  {
@@ -964841,7 +1044257,7 @@
  	struct sk_buff *skb;
  	int no_pending_pkts;
  	DECLARE_MAC_BUF(mac);
-@@ -880,6 +934,10 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
+@@ -880,6 +941,10 @@ ieee80211_rx_h_ps_poll(struct ieee80211_txrx_data *rx)
  		   !(rx->flags & IEEE80211_TXRXD_RXRA_MATCH)))
  		return TXRX_CONTINUE;
  
@@ -964852,7 +1044268,7 @@
  	skb = skb_dequeue(&rx->sta->tx_filtered);
  	if (!skb) {
  		skb = skb_dequeue(&rx->sta->ps_tx_buf);
-@@ -956,68 +1014,54 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
+@@ -956,68 +1021,54 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_txrx_data *rx)
  	return TXRX_CONTINUE;
  }
  
@@ -964938,7 +1044354,7 @@
  	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
  	DECLARE_MAC_BUF(mac);
  	DECLARE_MAC_BUF(mac2);
-@@ -1025,11 +1069,9 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1025,11 +1076,9 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  	DECLARE_MAC_BUF(mac4);
  
  	fc = rx->fc;
@@ -964951,7 +1044367,7 @@
  
  	hdrlen = ieee80211_get_hdrlen(fc);
  
-@@ -1049,8 +1091,8 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1049,8 +1098,8 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  		memcpy(dst, hdr->addr3, ETH_ALEN);
  		memcpy(src, hdr->addr2, ETH_ALEN);
  
@@ -964962,7 +1044378,7 @@
  			if (net_ratelimit())
  				printk(KERN_DEBUG "%s: dropped ToDS frame "
  				       "(BSSID=%s SA=%s DA=%s)\n",
-@@ -1058,7 +1100,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1058,7 +1107,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  				       print_mac(mac, hdr->addr1),
  				       print_mac(mac2, hdr->addr2),
  				       print_mac(mac3, hdr->addr3));
@@ -964971,7 +1044387,7 @@
  		}
  		break;
  	case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
-@@ -1066,7 +1108,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1066,7 +1115,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  		memcpy(dst, hdr->addr3, ETH_ALEN);
  		memcpy(src, hdr->addr4, ETH_ALEN);
  
@@ -964980,7 +1044396,7 @@
  			if (net_ratelimit())
  				printk(KERN_DEBUG "%s: dropped FromDS&ToDS "
  				       "frame (RA=%s TA=%s DA=%s SA=%s)\n",
-@@ -1075,7 +1117,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1075,7 +1124,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  				       print_mac(mac2, hdr->addr2),
  				       print_mac(mac3, hdr->addr3),
  				       print_mac(mac4, hdr->addr4));
@@ -964989,7 +1044405,7 @@
  		}
  		break;
  	case IEEE80211_FCTL_FROMDS:
-@@ -1083,17 +1125,17 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1083,17 +1132,17 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  		memcpy(dst, hdr->addr1, ETH_ALEN);
  		memcpy(src, hdr->addr3, ETH_ALEN);
  
@@ -965010,7 +1044426,7 @@
  			if (net_ratelimit()) {
  				printk(KERN_DEBUG "%s: dropped IBSS frame "
  				       "(DA=%s SA=%s BSSID=%s)\n",
-@@ -1102,21 +1144,20 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1102,21 +1151,20 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  				       print_mac(mac2, hdr->addr2),
  				       print_mac(mac3, hdr->addr3));
  			}
@@ -965035,7 +1044451,7 @@
  	ethertype = (payload[6] << 8) | payload[7];
  
  	if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
-@@ -1130,6 +1171,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1130,6 +1178,7 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  	} else {
  		struct ethhdr *ehdr;
  		__be16 len;
@@ -965043,15 +1044459,14 @@
  		skb_pull(skb, hdrlen);
  		len = htons(skb->len);
  		ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
-@@ -1137,36 +1179,72 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1137,36 +1186,72 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  		memcpy(ehdr->h_source, src, ETH_ALEN);
  		ehdr->h_proto = len;
  	}
 -	skb->dev = dev;
 +	return 0;
 +}
- 
--	skb2 = NULL;
++
 +/*
 + * requires that rx->skb is a frame with ethernet header
 + */
@@ -965061,8 +1044476,7 @@
 +		= { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
 +	struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
  
--	dev->stats.rx_packets++;
--	dev->stats.rx_bytes += skb->len;
+-	skb2 = NULL;
 +	/*
 +	 * Allow EAPOL frames to us/the PAE group address regardless
 +	 * of whether the frame was encrypted or not.
@@ -965071,14 +1044485,18 @@
 +	    (compare_ether_addr(ehdr->h_dest, rx->dev->dev_addr) == 0 ||
 +	     compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0))
 +		return true;
-+
+ 
+-	dev->stats.rx_packets++;
+-	dev->stats.rx_bytes += skb->len;
 +	if (ieee80211_802_1x_port_control(rx) ||
 +	    ieee80211_drop_unencrypted(rx))
 +		return false;
 +
 +	return true;
 +}
-+
+ 
+-	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
+-	    || sdata->type == IEEE80211_IF_TYPE_VLAN) &&
 +/*
 + * requires that rx->skb is a frame with ethernet header
 + */
@@ -965094,9 +1044512,7 @@
 +
 +	skb = rx->skb;
 +	xmit_skb = NULL;
- 
--	if (local->bridge_packets && (sdata->type == IEEE80211_IF_TYPE_AP
--	    || sdata->type == IEEE80211_IF_TYPE_VLAN) &&
++
 +	if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
 +				      sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
  	    (rx->flags & IEEE80211_TXRXD_RXRA_MATCH)) {
@@ -965137,7 +1044553,7 @@
  				skb = NULL;
  			}
  			if (dsta)
-@@ -1181,18 +1259,207 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
+@@ -1181,18 +1266,207 @@ ieee80211_rx_h_data(struct ieee80211_txrx_data *rx)
  		netif_rx(skb);
  	}
  
@@ -965350,7 +1044766,7 @@
  ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
  {
  	struct ieee80211_sub_if_data *sdata;
-@@ -1201,8 +1468,8 @@ ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
+@@ -1201,8 +1475,8 @@ ieee80211_rx_h_mgmt(struct ieee80211_txrx_data *rx)
  		return TXRX_DROP;
  
  	sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
@@ -965361,7 +1044777,7 @@
  	    !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
  		ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->u.rx.status);
  	else
-@@ -1294,7 +1561,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
+@@ -1294,7 +1568,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
  		goto ignore;
  	}
  
@@ -965370,7 +1044786,7 @@
  		/*
  		 * APs with pairwise keys should never receive Michael MIC
  		 * errors for non-zero keyidx because these are reserved for
-@@ -1341,9 +1608,9 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
+@@ -1341,9 +1615,9 @@ ieee80211_rx_handler ieee80211_rx_handlers[] =
  	 * are not passed to user space by these functions
  	 */
  	ieee80211_rx_h_remove_qos_control,
@@ -965382,7 +1044798,7 @@
  	ieee80211_rx_h_mgmt,
  	NULL
  };
-@@ -1356,7 +1623,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+@@ -1356,7 +1630,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
  {
  	int multicast = is_multicast_ether_addr(hdr->addr1);
  
@@ -965391,7 +1044807,7 @@
  	case IEEE80211_IF_TYPE_STA:
  		if (!bssid)
  			return 0;
-@@ -1427,11 +1694,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
+@@ -1427,11 +1701,13 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
  }
  
  /*
@@ -965409,7 +1044825,7 @@
  {
  	struct ieee80211_local *local = hw_to_local(hw);
  	struct ieee80211_sub_if_data *sdata;
-@@ -1439,36 +1708,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1439,36 +1715,18 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
  	struct ieee80211_hdr *hdr;
  	struct ieee80211_txrx_data rx;
  	u16 type;
@@ -965448,7 +1044864,7 @@
  	rx.fc = le16_to_cpu(hdr->frame_control);
  	type = rx.fc & IEEE80211_FCTL_FTYPE;
  
-@@ -1486,7 +1737,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1486,7 +1744,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
  		goto end;
  	}
  
@@ -965457,7 +1044873,7 @@
  		rx.flags |= IEEE80211_TXRXD_RXIN_SCAN;
  
  	if (__ieee80211_invoke_rx_handlers(local, local->rx_pre_handlers, &rx,
-@@ -1501,25 +1752,23 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1501,25 +1759,23 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
  		ieee80211_invoke_rx_handlers(local, local->rx_handlers, &rx,
  					     rx.sta);
  		sta_info_put(sta);
@@ -965487,7 +1044903,7 @@
  			continue;
  
  		/*
-@@ -1547,6 +1796,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1547,6 +1803,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
  				       prev->dev->name);
  			continue;
  		}
@@ -965495,7 +1044911,7 @@
  		rx.skb = skb_new;
  		rx.dev = prev->dev;
  		rx.sdata = prev;
-@@ -1555,6 +1805,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1555,6 +1812,7 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
  		prev = sdata;
  	}
  	if (prev) {
@@ -965503,7 +1044919,7 @@
  		rx.skb = skb;
  		rx.dev = prev->dev;
  		rx.sdata = prev;
-@@ -1564,10 +1815,230 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
+@@ -1564,10 +1822,230 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb,
  		dev_kfree_skb(skb);
  
   end:
@@ -965514,7 +1044930,7 @@
 +
 +#define SEQ_MODULO 0x1000
 +#define SEQ_MASK   0xfff
- 
++
 +static inline int seq_less(u16 sq1, u16 sq2)
 +{
 +	return (((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1));
@@ -965548,7 +1044964,7 @@
 +
 +	buf_size = tid_agg_rx->buf_size;
 +	head_seq_num = tid_agg_rx->head_seq_num;
-+
+ 
 +	/* frame with out of date sequence number */
 +	if (seq_less(mpdu_seq_num, head_seq_num)) {
 +		dev_kfree_skb(skb);
@@ -982787,7 +1062203,7 @@
  MODULE_ALIAS("ipt_u32");
  MODULE_ALIAS("ip6t_u32");
 diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
-index ba0ca8d..becf91a 100644
+index ba0ca8d..c7ad64d 100644
 --- a/net/netlabel/netlabel_cipso_v4.c
 +++ b/net/netlabel/netlabel_cipso_v4.c
 @@ -38,6 +38,7 @@
@@ -982798,6 +1062214,15 @@
  
  #include "netlabel_user.h"
  #include "netlabel_cipso_v4.h"
+@@ -89,7 +90,7 @@ static const struct nla_policy netlbl_cipsov4_genl_policy[NLBL_CIPSOV4_A_MAX + 1
+  * safely.
+  *
+  */
+-static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
++void netlbl_cipsov4_doi_free(struct rcu_head *entry)
+ {
+ 	struct cipso_v4_doi *ptr;
+ 
 @@ -421,7 +422,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
  		break;
  	}
@@ -982816,6 +1062241,18 @@
  
  	audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
  					      &audit_info);
+diff --git a/net/netlabel/netlabel_cipso_v4.h b/net/netlabel/netlabel_cipso_v4.h
+index f03cf9b..220cb9d 100644
+--- a/net/netlabel/netlabel_cipso_v4.h
++++ b/net/netlabel/netlabel_cipso_v4.h
+@@ -163,4 +163,7 @@ enum {
+ /* NetLabel protocol functions */
+ int netlbl_cipsov4_genl_init(void);
+ 
++/* Free the memory associated with a CIPSOv4 DOI definition */
++void netlbl_cipsov4_doi_free(struct rcu_head *entry);
++
+ #endif
 diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c
 index b3675bd..9a8ea01 100644
 --- a/net/netlabel/netlabel_domainhash.c
@@ -982967,11 +1062404,28 @@
  }
  
  /**
+diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h
+index 3689956..8220990 100644
+--- a/net/netlabel/netlabel_domainhash.h
++++ b/net/netlabel/netlabel_domainhash.h
+@@ -61,6 +61,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
+ 		      struct netlbl_audit *audit_info);
+ int netlbl_domhsh_add_default(struct netlbl_dom_map *entry,
+ 			      struct netlbl_audit *audit_info);
++int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
+ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info);
+ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
+ int netlbl_domhsh_walk(u32 *skip_bkt,
 diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
-index 4f50949..c69e3e1 100644
+index 4f50949..39793a1 100644
 --- a/net/netlabel/netlabel_kapi.c
 +++ b/net/netlabel/netlabel_kapi.c
-@@ -34,6 +34,7 @@
+@@ -30,17 +30,195 @@
+ 
+ #include <linux/init.h>
+ #include <linux/types.h>
++#include <linux/audit.h>
+ #include <net/ip.h>
  #include <net/netlabel.h>
  #include <net/cipso_ipv4.h>
  #include <asm/bug.h>
@@ -982979,7 +1062433,190 @@
  
  #include "netlabel_domainhash.h"
  #include "netlabel_unlabeled.h"
-@@ -262,7 +263,7 @@ int netlbl_enabled(void)
++#include "netlabel_cipso_v4.h"
+ #include "netlabel_user.h"
+ #include "netlabel_mgmt.h"
+ 
+ /*
++ * Configuration Functions
++ */
++
++/**
++ * netlbl_cfg_map_del - Remove a NetLabel/LSM domain mapping
++ * @domain: the domain mapping to remove
++ * @audit_info: NetLabel audit information
++ *
++ * Description:
++ * Removes a NetLabel/LSM domain mapping.  A @domain value of NULL causes the
++ * default domain mapping to be removed.  Returns zero on success, negative
++ * values on failure.
++ *
++ */
++int netlbl_cfg_map_del(const char *domain, struct netlbl_audit *audit_info)
++{
++	return netlbl_domhsh_remove(domain, audit_info);
++}
++
++/**
++ * netlbl_cfg_unlbl_add_map - Add an unlabeled NetLabel/LSM domain mapping
++ * @domain: the domain mapping to add
++ * @audit_info: NetLabel audit information
++ *
++ * Description:
++ * Adds a new unlabeled NetLabel/LSM domain mapping.  A @domain value of NULL
++ * causes a new default domain mapping to be added.  Returns zero on success,
++ * negative values on failure.
++ *
++ */
++int netlbl_cfg_unlbl_add_map(const char *domain,
++			     struct netlbl_audit *audit_info)
++{
++	int ret_val = -ENOMEM;
++	struct netlbl_dom_map *entry;
++
++	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
++	if (entry == NULL)
++		goto cfg_unlbl_add_map_failure;
++	if (domain != NULL) {
++		entry->domain = kstrdup(domain, GFP_ATOMIC);
++		if (entry->domain == NULL)
++			goto cfg_unlbl_add_map_failure;
++	}
++	entry->type = NETLBL_NLTYPE_UNLABELED;
++
++	ret_val = netlbl_domhsh_add(entry, audit_info);
++	if (ret_val != 0)
++		goto cfg_unlbl_add_map_failure;
++
++	return 0;
++
++cfg_unlbl_add_map_failure:
++	if (entry != NULL)
++		kfree(entry->domain);
++	kfree(entry);
++	return ret_val;
++}
++
++/**
++ * netlbl_cfg_cipsov4_add - Add a new CIPSOv4 DOI definition
++ * @doi_def: the DOI definition
++ * @audit_info: NetLabel audit information
++ *
++ * Description:
++ * Add a new CIPSOv4 DOI definition to the NetLabel subsystem.  Returns zero on
++ * success, negative values on failure.
++ *
++ */
++int netlbl_cfg_cipsov4_add(struct cipso_v4_doi *doi_def,
++			   struct netlbl_audit *audit_info)
++{
++	int ret_val;
++	const char *type_str;
++	struct audit_buffer *audit_buf;
++
++	ret_val = cipso_v4_doi_add(doi_def);
++
++	audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
++					      audit_info);
++	if (audit_buf != NULL) {
++		switch (doi_def->type) {
++		case CIPSO_V4_MAP_STD:
++			type_str = "std";
++			break;
++		case CIPSO_V4_MAP_PASS:
++			type_str = "pass";
++			break;
++		default:
++			type_str = "(unknown)";
++		}
++		audit_log_format(audit_buf,
++				 " cipso_doi=%u cipso_type=%s res=%u",
++				 doi_def->doi,
++				 type_str,
++				 ret_val == 0 ? 1 : 0);
++		audit_log_end(audit_buf);
++	}
++
++	return ret_val;
++}
++
++/**
++ * netlbl_cfg_cipsov4_add_map - Add a new CIPSOv4 DOI definition and mapping
++ * @doi_def: the DOI definition
++ * @domain: the domain mapping to add
++ * @audit_info: NetLabel audit information
++ *
++ * Description:
++ * Add a new CIPSOv4 DOI definition and NetLabel/LSM domain mapping for this
++ * new DOI definition to the NetLabel subsystem.  A @domain value of NULL adds
++ * a new default domain mapping.  Returns zero on success, negative values on
++ * failure.
++ *
++ */
++int netlbl_cfg_cipsov4_add_map(struct cipso_v4_doi *doi_def,
++			       const char *domain,
++			       struct netlbl_audit *audit_info)
++{
++	int ret_val = -ENOMEM;
++	struct netlbl_dom_map *entry;
++
++	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
++	if (entry == NULL)
++		goto cfg_cipsov4_add_map_failure;
++	if (domain != NULL) {
++		entry->domain = kstrdup(domain, GFP_ATOMIC);
++		if (entry->domain == NULL)
++			goto cfg_cipsov4_add_map_failure;
++	}
++	entry->type = NETLBL_NLTYPE_CIPSOV4;
++	entry->type_def.cipsov4 = doi_def;
++
++	/* Grab a RCU read lock here so nothing happens to the doi_def variable
++	 * between adding it to the CIPSOv4 protocol engine and adding a
++	 * domain mapping for it. */
++
++	rcu_read_lock();
++	ret_val = netlbl_cfg_cipsov4_add(doi_def, audit_info);
++	if (ret_val != 0)
++		goto cfg_cipsov4_add_map_failure_unlock;
++	ret_val = netlbl_domhsh_add(entry, audit_info);
++	if (ret_val != 0)
++		goto cfg_cipsov4_add_map_failure_remove_doi;
++	rcu_read_unlock();
++
++	return 0;
++
++cfg_cipsov4_add_map_failure_remove_doi:
++	cipso_v4_doi_remove(doi_def->doi, audit_info, netlbl_cipsov4_doi_free);
++cfg_cipsov4_add_map_failure_unlock:
++	rcu_read_unlock();
++cfg_cipsov4_add_map_failure:
++	if (entry != NULL)
++		kfree(entry->domain);
++	kfree(entry);
++	return ret_val;
++}
++
++/**
++ * netlbl_cfg_cipsov4_del - Removean existing CIPSOv4 DOI definition
++ * @doi: the CIPSO DOI value
++ * @audit_info: NetLabel audit information
++ *
++ * Description:
++ * Removes an existing CIPSOv4 DOI definition from the NetLabel subsystem.
++ * Returns zero on success, negative values on failure.
++ *
++ */
++int netlbl_cfg_cipsov4_del(u32 doi, struct netlbl_audit *audit_info)
++{
++	return cipso_v4_doi_remove(doi, audit_info, netlbl_cipsov4_doi_free);
++}
++
++/*
+  * Security Attribute Functions
+  */
+ 
+@@ -262,7 +440,7 @@ int netlbl_enabled(void)
  	/* At some point we probably want to expose this mechanism to the user
  	 * as well so that admins can toggle NetLabel regardless of the
  	 * configuration */
@@ -982988,7 +1062625,7 @@
  }
  
  /**
-@@ -311,7 +312,7 @@ socket_setattr_return:
+@@ -311,7 +489,7 @@ socket_setattr_return:
   * @secattr: the security attributes
   *
   * Description:
@@ -982997,7 +1062634,7 @@
   * applied to the sock, if so it parses the socket label and returns the
   * security attributes in @secattr.  Returns zero on success, negative values
   * on failure.
-@@ -319,18 +320,13 @@ socket_setattr_return:
+@@ -319,18 +497,13 @@ socket_setattr_return:
   */
  int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
  {
@@ -983018,7 +1062655,7 @@
   * @secattr: the security attributes
   *
   * Description:
-@@ -341,13 +337,14 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
+@@ -341,13 +514,14 @@ int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
   *
   */
  int netlbl_skbuff_getattr(const struct sk_buff *skb,
@@ -983034,7 +1062671,7 @@
  }
  
  /**
-@@ -431,6 +428,10 @@ static int __init netlbl_init(void)
+@@ -431,6 +605,10 @@ static int __init netlbl_init(void)
  	if (ret_val != 0)
  		goto init_failure;
  
@@ -986045,7 +1065682,7 @@
  };
  
 diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c
-index d06d338..6562f86 100644
+index d06d338..1a47f5d 100644
 --- a/net/rfkill/rfkill.c
 +++ b/net/rfkill/rfkill.c
 @@ -126,6 +126,9 @@ static ssize_t rfkill_type_show(struct device *dev,
@@ -986058,6 +1065695,15 @@
  	default:
  		BUG();
  	}
+@@ -337,7 +340,7 @@ EXPORT_SYMBOL(rfkill_allocate);
+  * rfkill_free - Mark rfkill structure for deletion
+  * @rfkill: rfkill structure to be destroyed
+  *
+- * Decrements reference count of rfkill structure so it is destoryed.
++ * Decrements reference count of rfkill structure so it is destroyed.
+  * Note that rfkill_free() should _not_ be called after rfkill_unregister().
+  */
+ void rfkill_free(struct rfkill *rfkill)
 diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
 index ed2d65c..4a31a81 100644
 --- a/net/rose/af_rose.c
@@ -988500,7 +1068146,7 @@
  	.init		=	basic_init,
 diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
 new file mode 100644
-index 0000000..5a7f6a3
+index 0000000..8d76986
 --- /dev/null
 +++ b/net/sched/cls_flow.c
 @@ -0,0 +1,660 @@
@@ -989100,11 +1068746,11 @@
 +
 +	if (tcf_exts_dump(skb, &f->exts, &flow_ext_map) < 0)
 +		goto nla_put_failure;
-+
++#ifdef CONFIG_NET_EMATCH
 +	if (f->ematches.hdr.nmatches &&
 +	    tcf_em_tree_dump(skb, &f->ematches, TCA_FLOW_EMATCHES) < 0)
 +		goto nla_put_failure;
-+
++#endif
 +	nla_nest_end(skb, nest);
 +
 +	if (tcf_exts_dump_stats(skb, &f->exts, &flow_ext_map) < 0)
@@ -990243,10 +1069889,48 @@
  	.classify	=	u32_classify,
  	.init		=	u32_init,
 diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
-index ceda889..a1e5619 100644
+index ceda889..9c2ec19 100644
 --- a/net/sched/em_meta.c
 +++ b/net/sched/em_meta.c
-@@ -542,11 +542,11 @@ static int meta_var_compare(struct meta_obj *a, struct meta_obj *b)
+@@ -65,6 +65,7 @@
+ #include <linux/string.h>
+ #include <linux/skbuff.h>
+ #include <linux/random.h>
++#include <linux/if_vlan.h>
+ #include <linux/tc_ematch/tc_em_meta.h>
+ #include <net/dst.h>
+ #include <net/route.h>
+@@ -170,6 +171,21 @@ META_COLLECTOR(var_dev)
+ }
+ 
+ /**************************************************************************
++ * vlan tag
++ **************************************************************************/
++
++META_COLLECTOR(int_vlan_tag)
++{
++	unsigned short tag;
++	if (vlan_get_tag(skb, &tag) < 0)
++		*err = -1;
++	else
++		dst->value = tag;
++}
++
++
++
++/**************************************************************************
+  * skb attributes
+  **************************************************************************/
+ 
+@@ -520,6 +536,7 @@ static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
+ 		[META_ID(SK_SNDTIMEO)]		= META_FUNC(int_sk_sndtimeo),
+ 		[META_ID(SK_SENDMSG_OFF)]	= META_FUNC(int_sk_sendmsg_off),
+ 		[META_ID(SK_WRITE_PENDING)]	= META_FUNC(int_sk_write_pend),
++		[META_ID(VLAN_TAG)]		= META_FUNC(int_vlan_tag),
+ 	}
+ };
+ 
+@@ -542,11 +559,11 @@ static int meta_var_compare(struct meta_obj *a, struct meta_obj *b)
  	return r;
  }
  
@@ -990261,7 +1069945,7 @@
  	if (dst->val == 0UL)
  		return -ENOMEM;
  	dst->len = len;
-@@ -570,10 +570,10 @@ static void meta_var_apply_extras(struct meta_value *v,
+@@ -570,10 +587,10 @@ static void meta_var_apply_extras(struct meta_value *v,
  static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
  {
  	if (v->val && v->len)
@@ -990274,7 +1069958,7 @@
  	return -1;
  }
  
-@@ -594,13 +594,13 @@ static int meta_int_compare(struct meta_obj *a, struct meta_obj *b)
+@@ -594,13 +611,13 @@ static int meta_int_compare(struct meta_obj *a, struct meta_obj *b)
  		return 1;
  }
  
@@ -990293,7 +1069977,7 @@
  		dst->len = sizeof(u32);
  	} else
  		return -EINVAL;
-@@ -621,15 +621,14 @@ static void meta_int_apply_extras(struct meta_value *v,
+@@ -621,15 +638,14 @@ static void meta_int_apply_extras(struct meta_value *v,
  static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
  {
  	if (v->len == sizeof(unsigned long))
@@ -990312,7 +1069996,7 @@
  	return -1;
  }
  
-@@ -641,7 +640,7 @@ struct meta_type_ops
+@@ -641,7 +657,7 @@ struct meta_type_ops
  {
  	void	(*destroy)(struct meta_value *);
  	int	(*compare)(struct meta_obj *, struct meta_obj *);
@@ -990321,7 +1070005,7 @@
  	void	(*apply_extras)(struct meta_value *, struct meta_obj *);
  	int	(*dump)(struct sk_buff *, struct meta_value *, int);
  };
-@@ -729,13 +728,13 @@ static inline void meta_delete(struct meta_match *meta)
+@@ -729,13 +745,13 @@ static inline void meta_delete(struct meta_match *meta)
  	kfree(meta);
  }
  
@@ -990339,7 +1070023,7 @@
  	}
  
  	return 0;
-@@ -746,21 +745,26 @@ static inline int meta_is_supported(struct meta_value *val)
+@@ -746,21 +762,26 @@ static inline int meta_is_supported(struct meta_value *val)
  	return (!meta_id(val) || meta_ops(val)->get);
  }
  
@@ -990372,7 +1070056,7 @@
  
  	if (TCF_META_TYPE(hdr->left.kind) != TCF_META_TYPE(hdr->right.kind) ||
  	    TCF_META_TYPE(hdr->left.kind) > TCF_META_TYPE_MAX ||
-@@ -781,8 +785,8 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
+@@ -781,8 +802,8 @@ static int em_meta_change(struct tcf_proto *tp, void *data, int len,
  		goto errout;
  	}
  
@@ -990383,7 +1070067,7 @@
  		goto errout;
  
  	m->datalen = sizeof(*meta);
-@@ -811,16 +815,16 @@ static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em)
+@@ -811,16 +832,16 @@ static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em)
  	memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left));
  	memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right));
  
@@ -995129,6 +1074813,29 @@
 +
 +	return ack;
 +}
+diff --git a/net/sctp/auth.c b/net/sctp/auth.c
+index 97e6ebd..ae367c8 100644
+--- a/net/sctp/auth.c
++++ b/net/sctp/auth.c
+@@ -420,15 +420,15 @@ struct sctp_shared_key *sctp_auth_get_shkey(
+ 				const struct sctp_association *asoc,
+ 				__u16 key_id)
+ {
+-	struct sctp_shared_key *key = NULL;
++	struct sctp_shared_key *key;
+ 
+ 	/* First search associations set of endpoint pair shared keys */
+ 	key_for_each(key, &asoc->endpoint_shared_keys) {
+ 		if (key->key_id == key_id)
+-			break;
++			return key;
+ 	}
+ 
+-	return key;
++	return NULL;
+ }
+ 
+ /*
 diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
 index 6a7d010..13fbfb4 100644
 --- a/net/sctp/bind_addr.c
@@ -996069,7 +1075776,7 @@
  		local_bh_enable();
  		break;
 diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
-index d247ed4..61cbd5a 100644
+index d247ed4..f986587 100644
 --- a/net/sctp/sm_statefuns.c
 +++ b/net/sctp/sm_statefuns.c
 @@ -143,6 +143,12 @@ static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,
@@ -996120,6 +1075827,15 @@
  		}
  
  		/* SCTP-AUTH, Section 6.3:
+@@ -533,7 +537,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
+ 		 *
+ 		 * This means that if we only want to abort associations
+ 		 * in an authenticated way (i.e AUTH+ABORT), then we
+-		 * can't destory this association just becuase the packet
++		 * can't destroy this association just becuase the packet
+ 		 * was malformed.
+ 		 */
+ 		if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
 @@ -2073,11 +2077,20 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort(
  	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))
  		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -996328,7 +1076044,27 @@
  	/* Make sure that the ADDIP chunk has a valid length.  */
  	if (!sctp_chunk_length_valid(asconf_ack, sizeof(sctp_addip_chunk_t)))
  		return sctp_sf_violation_chunklen(ep, asoc, type, arg,
-@@ -5763,7 +5843,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
+@@ -3785,6 +3865,10 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep,
+ 	struct sctp_chunk *err_chunk;
+ 	sctp_ierror_t error;
+ 
++	/* Make sure that the peer has AUTH capable */
++	if (!asoc->peer.auth_capable)
++		return sctp_sf_unk_chunk(ep, asoc, type, arg, commands);
++
+ 	if (!sctp_vtag_verify(chunk, asoc)) {
+ 		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
+ 				SCTP_NULL());
+@@ -4050,7 +4134,7 @@ static sctp_disposition_t sctp_sf_abort_violation(
+ 	 *
+ 	 * This means that if we only want to abort associations
+ 	 * in an authenticated way (i.e AUTH+ABORT), then we
+-	 * can't destory this association just becuase the packet
++	 * can't destroy this association just becuase the packet
+ 	 * was malformed.
+ 	 */
+ 	if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
+@@ -5763,7 +5847,7 @@ static int sctp_eat_data(const struct sctp_association *asoc,
  	/*
  	 * Also try to renege to limit our memory usage in the event that
  	 * we are under memory pressure
@@ -1011410,7 +1091146,7 @@
  	wmove(dialog, y, x + 1 + 13 * selected);
  	wrefresh(dialog);
 diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
-index 47e226f..50e61c4 100644
+index 47e226f..734cf4f 100644
 --- a/scripts/kconfig/mconf.c
 +++ b/scripts/kconfig/mconf.c
 @@ -8,17 +8,13 @@
@@ -1011665,7 +1091401,15 @@
  				      heading, 10, 75,
  				      sym_get_string_value(menu->sym));
  		switch (res) {
-@@ -900,13 +860,9 @@ static void conf_save(void)
+@@ -861,6 +821,7 @@ static void conf_load(void)
+ 				return;
+ 			if (!conf_read(dialog_input_result)) {
+ 				set_config_filename(dialog_input_result);
++				sym_set_change_count(1);
+ 				return;
+ 			}
+ 			show_textbox(NULL, _("File does not exist!"), 5, 38);
+@@ -900,13 +861,9 @@ static void conf_save(void)
  	}
  }
  
@@ -1011680,7 +1091424,7 @@
  	char *mode;
  	int res;
  
-@@ -923,11 +879,13 @@ int main(int ac, char **av)
+@@ -923,11 +880,13 @@ int main(int ac, char **av)
  			single_menu_mode = 1;
  	}
  
@@ -1011699,7 +1091443,7 @@
  	set_config_filename(conf_get_configname());
  	do {
  		conf(&rootmenu);
-@@ -941,7 +899,7 @@ int main(int ac, char **av)
+@@ -941,7 +900,7 @@ int main(int ac, char **av)
  		else
  			res = -1;
  	} while (res == KEY_ESC);
@@ -1011709,7 +1091453,7 @@
  	switch (res) {
  	case 0:
 diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
-index f9d0d91..fdad173 100644
+index f9d0d91..606ceb9 100644
 --- a/scripts/kconfig/menu.c
 +++ b/scripts/kconfig/menu.c
 @@ -15,7 +15,7 @@ static struct menu **last_entry_ptr;
@@ -1011731,7 +1091475,23 @@
  	}
  }
  
-@@ -239,9 +242,11 @@ void menu_finalize(struct menu *parent)
+@@ -200,12 +203,9 @@ void sym_check_prop(struct symbol *sym)
+ 				prop_warn(prop,
+ 				    "config symbol '%s' uses select, but is "
+ 				    "not boolean or tristate", sym->name);
+-			else if (sym2->type == S_UNKNOWN)
+-				prop_warn(prop,
+-				    "'select' used by config symbol '%s' "
+-				    "refers to undefined symbol '%s'",
+-				    sym->name, sym2->name);
+-			else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)
++			else if (sym2->type != S_UNKNOWN &&
++			         sym2->type != S_BOOLEAN &&
++			         sym2->type != S_TRISTATE)
+ 				prop_warn(prop,
+ 				    "'%s' has wrong type. 'select' only "
+ 				    "accept arguments of boolean and "
+@@ -239,9 +239,11 @@ void menu_finalize(struct menu *parent)
  			for (menu = parent->list; menu; menu = menu->next) {
  				if (menu->sym) {
  					current_entry = parent;
@@ -1011745,7 +1091505,7 @@
  					break;
  				}
  			}
-@@ -326,12 +331,42 @@ void menu_finalize(struct menu *parent)
+@@ -326,12 +328,42 @@ void menu_finalize(struct menu *parent)
  					    "values not supported");
  			}
  			current_entry = menu;
@@ -1011790,7 +1091550,7 @@
  			(*ep)->right.sym = menu->sym;
  		}
  		if (menu->list && (!menu->prompt || !menu->prompt->text)) {
-@@ -394,9 +429,9 @@ bool menu_is_visible(struct menu *menu)
+@@ -394,9 +426,9 @@ bool menu_is_visible(struct menu *menu)
  const char *menu_get_prompt(struct menu *menu)
  {
  	if (menu->prompt)
@@ -1012725,7 +1092485,7 @@
  
  	/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
 diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
-index 93ac52a..f8efc93 100644
+index 93ac52a..5d54646 100644
 --- a/scripts/mod/modpost.c
 +++ b/scripts/mod/modpost.c
 @@ -2,7 +2,7 @@
@@ -1013234,7 +1092994,7 @@
 +/* Do not export init/exit functions or data */
 +{
 +	.fromsec = { "__ksymtab*", NULL },
-+	.tosec   = { ALL_INIT_SECTIONS, ALL_EXIT_SECTIONS, NULL },
++	.tosec   = { INIT_SECTIONS, EXIT_SECTIONS, NULL },
 +	.mismatch = EXPORT_TO_INIT_EXIT
 +}
 +};
@@ -1013543,11 +1093303,6 @@
 +	to = to_is_func ? "function" : "variable";
 +	to_p = to_is_func ? "()" : "";
 +
-+	fprintf(stderr, "WARNING: %s(%s+0x%llx): Section mismatch in"
-+	                " reference from the %s %s%s to the %s %s:%s%s\n",
-+                        modname, fromsec, fromaddr, from, fromsym, from_p,
-+	                to, tosec, tosym, to_p);
-+
 +	sec_mismatch_count++;
 +	if (!sec_mismatch_verbose)
  		return;
@@ -1013575,6 +1093330,11 @@
 -		warn("%s(%s+0x%llx): Section mismatch: reference to %s:%s\n",
 -		     modname, fromsec, (unsigned long long)r.r_offset,
 -		     secname, refsymname);
++	fprintf(stderr, "WARNING: %s(%s+0x%llx): Section mismatch in"
++	                " reference from the %s %s%s to the %s %s:%s%s\n",
++                        modname, fromsec, fromaddr, from, fromsym, from_p,
++	                to, tosec, tosym, to_p);
++
 +	switch (mismatch) {
 +	case TEXT_TO_INIT:
 +		fprintf(stderr,
@@ -1014319,16 +1094079,15 @@
  		if (mod->skip)
  			continue;
  
-@@ -1723,6 +1937,12 @@ int main(int argc, char **argv)
+@@ -1723,6 +1937,11 @@ int main(int argc, char **argv)
  
  	if (dump_write)
  		write_dump(dump_write);
 +	if (sec_mismatch_count && !sec_mismatch_verbose)
 +		fprintf(stderr, "modpost: Found %d section mismatch(es).\n"
-+		        "To see additional details select \"Enable full "
-+		        "Section mismatch analysis\"\n"
-+		        "in the Kernel Hacking menu "
-+		        "(CONFIG_SECTION_MISMATCH).\n", sec_mismatch_count);
++		        "To see full details build your kernel with:\n"
++		        "'make CONFIG_DEBUG_SECTION_MISMATCH=y'\n",
++		        sec_mismatch_count);
  
  	return err;
  }
@@ -1014454,10 +1094213,12 @@
  		HIGHESTPATCH=0
  		for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
 diff --git a/scripts/setlocalversion b/scripts/setlocalversion
-index 82e4993..52f032e 100644
+old mode 100644
+new mode 100755
+index 82e4993..1c1bdaf
 --- a/scripts/setlocalversion
 +++ b/scripts/setlocalversion
-@@ -12,11 +12,36 @@ cd "${1:-.}" || usage
+@@ -12,11 +12,52 @@ cd "${1:-.}" || usage
  if head=`git rev-parse --verify HEAD 2>/dev/null`; then
  	# Do we have an untagged version?
  	if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
@@ -1014477,42 +1094238,351 @@
 +	exit
 +fi
 +
-+# Check for mercurial and a mercurial repo.
-+if hgid=`hg id 2>/dev/null`; then
-+	tag=`printf '%s' "$hgid" | cut -d' ' -f2`
++# Check for mercurial and a mercurial repo.
++if hgid=`hg id 2>/dev/null`; then
++	tag=`printf '%s' "$hgid" | cut -d' ' -f2`
++
++	# Do we have an untagged version?
++	if [ -z "$tag" -o "$tag" = tip ]; then
++		id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
++		printf '%s%s' -hg "$id"
++	fi
++
++	# Are there uncommitted changes?
++	# These are represented by + after the changeset id.
++	case "$hgid" in
++		*+|*+\ *) printf '%s' -dirty ;;
++	esac
++
++	# All done with mercurial
++	exit
++fi
++
++# Check for svn and a svn repo.
++if rev=`svn info 2>/dev/null | grep '^Revision'`; then
++	rev=`echo $rev | awk '{print $NF}'`
++	changes=`svn status 2>/dev/null | grep '^[AMD]' | wc -l`
++
++	# Are there uncommitted changes?
++	if [ $changes != 0 ]; then
++		printf -- '-svn%s%s%s' "$rev" -dirty "$changes"
++	else
++		printf -- '-svn%s' "$rev"
++	fi
++
++	# All done with svn
++	exit
+ fi
+diff --git a/security/Kconfig b/security/Kconfig
+index 8086e61..25ffe1b 100644
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -76,6 +76,7 @@ config SECURITY_NETWORK_XFRM
+ config SECURITY_CAPABILITIES
+ 	bool "Default Linux Capabilities"
+ 	depends on SECURITY
++	default y
+ 	help
+ 	  This enables the "default" Linux capabilities functionality.
+ 	  If you are unsure how to answer this question, answer Y.
+@@ -104,6 +105,7 @@ config SECURITY_ROOTPLUG
+ 	  If you are unsure how to answer this question, answer N.
+ 
+ source security/selinux/Kconfig
++source security/smack/Kconfig
+ 
+ endmenu
+ 
+diff --git a/security/Makefile b/security/Makefile
+index ef87df2..9e8b025 100644
+--- a/security/Makefile
++++ b/security/Makefile
+@@ -4,6 +4,7 @@
+ 
+ obj-$(CONFIG_KEYS)			+= keys/
+ subdir-$(CONFIG_SECURITY_SELINUX)	+= selinux
++subdir-$(CONFIG_SECURITY_SMACK)		+= smack
+ 
+ # if we don't select a security model, use the default capabilities
+ ifneq ($(CONFIG_SECURITY),y)
+@@ -14,5 +15,6 @@ endif
+ obj-$(CONFIG_SECURITY)			+= security.o dummy.o inode.o
+ # Must precede capability.o in order to stack properly.
+ obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
++obj-$(CONFIG_SECURITY_SMACK)		+= commoncap.o smack/built-in.o
+ obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
+ obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+diff --git a/security/commoncap.c b/security/commoncap.c
+index ea61bc7..5aba826 100644
+--- a/security/commoncap.c
++++ b/security/commoncap.c
+@@ -1,4 +1,4 @@
+-/* Common capabilities, needed by capability.o and root_plug.o 
++/* Common capabilities, needed by capability.o and root_plug.o
+  *
+  *	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
+@@ -25,20 +25,6 @@
+ #include <linux/mount.h>
+ #include <linux/sched.h>
+ 
+-#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
+-/*
+- * Because of the reduced scope of CAP_SETPCAP when filesystem
+- * capabilities are in effect, it is safe to allow this capability to
+- * be available in the default configuration.
+- */
+-# define CAP_INIT_BSET  CAP_FULL_SET
+-#else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */
+-# define CAP_INIT_BSET  CAP_INIT_EFF_SET
+-#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
+-
+-kernel_cap_t cap_bset = CAP_INIT_BSET;    /* systemwide capability bound */
+-EXPORT_SYMBOL(cap_bset);
+-
+ /* Global security state */
+ 
+ unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
+@@ -93,9 +79,9 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective,
+ 		kernel_cap_t *inheritable, kernel_cap_t *permitted)
+ {
+ 	/* Derived from kernel/capability.c:sys_capget. */
+-	*effective = cap_t (target->cap_effective);
+-	*inheritable = cap_t (target->cap_inheritable);
+-	*permitted = cap_t (target->cap_permitted);
++	*effective = target->cap_effective;
++	*inheritable = target->cap_inheritable;
++	*permitted = target->cap_permitted;
+ 	return 0;
+ }
+ 
+@@ -140,6 +126,12 @@ int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
+ 		/* incapable of using this inheritable set */
+ 		return -EPERM;
+ 	}
++	if (!cap_issubset(*inheritable,
++			   cap_combine(target->cap_inheritable,
++				       current->cap_bset))) {
++		/* no new pI capabilities outside bounding set */
++		return -EPERM;
++	}
+ 
+ 	/* verify restrictions on target's new Permitted set */
+ 	if (!cap_issubset (*permitted,
+@@ -198,28 +190,50 @@ int cap_inode_killpriv(struct dentry *dentry)
+ }
+ 
+ static inline int cap_from_disk(struct vfs_cap_data *caps,
+-				struct linux_binprm *bprm,
+-				int size)
++				struct linux_binprm *bprm, unsigned size)
+ {
+ 	__u32 magic_etc;
++	unsigned tocopy, i;
+ 
+-	if (size != XATTR_CAPS_SZ)
++	if (size < sizeof(magic_etc))
+ 		return -EINVAL;
+ 
+ 	magic_etc = le32_to_cpu(caps->magic_etc);
+ 
+ 	switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
+-	case VFS_CAP_REVISION:
+-		if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
+-			bprm->cap_effective = true;
+-		else
+-			bprm->cap_effective = false;
+-		bprm->cap_permitted = to_cap_t(le32_to_cpu(caps->permitted));
+-		bprm->cap_inheritable = to_cap_t(le32_to_cpu(caps->inheritable));
+-		return 0;
++	case VFS_CAP_REVISION_1:
++		if (size != XATTR_CAPS_SZ_1)
++			return -EINVAL;
++		tocopy = VFS_CAP_U32_1;
++		break;
++	case VFS_CAP_REVISION_2:
++		if (size != XATTR_CAPS_SZ_2)
++			return -EINVAL;
++		tocopy = VFS_CAP_U32_2;
++		break;
+ 	default:
+ 		return -EINVAL;
+ 	}
++
++	if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
++		bprm->cap_effective = true;
++	} else {
++		bprm->cap_effective = false;
++	}
 +
-+	# Do we have an untagged version?
-+	if [ -z "$tag" -o "$tag" = tip ]; then
-+		id=`printf '%s' "$hgid" | sed 's/[+ ].*//'`
-+		printf '%s%s' -hg "$id"
-+	fi
++	for (i = 0; i < tocopy; ++i) {
++		bprm->cap_permitted.cap[i] =
++			le32_to_cpu(caps->data[i].permitted);
++		bprm->cap_inheritable.cap[i] =
++			le32_to_cpu(caps->data[i].inheritable);
++	}
++	while (i < VFS_CAP_U32) {
++		bprm->cap_permitted.cap[i] = 0;
++		bprm->cap_inheritable.cap[i] = 0;
++		i++;
++	}
 +
-+	# Are there uncommitted changes?
-+	# These are represented by + after the changeset id.
-+	case "$hgid" in
-+		*+|*+\ *) printf '%s' -dirty ;;
-+	esac
++	return 0;
+ }
+ 
+ /* Locate any VFS capabilities: */
+@@ -227,7 +241,7 @@ static int get_file_caps(struct linux_binprm *bprm)
+ {
+ 	struct dentry *dentry;
+ 	int rc = 0;
+-	struct vfs_cap_data incaps;
++	struct vfs_cap_data vcaps;
+ 	struct inode *inode;
+ 
+ 	if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
+@@ -240,14 +254,8 @@ static int get_file_caps(struct linux_binprm *bprm)
+ 	if (!inode->i_op || !inode->i_op->getxattr)
+ 		goto out;
+ 
+-	rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
+-	if (rc > 0) {
+-		if (rc == XATTR_CAPS_SZ)
+-			rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS,
+-						&incaps, XATTR_CAPS_SZ);
+-		else
+-			rc = -EINVAL;
+-	}
++	rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &vcaps,
++				   XATTR_CAPS_SZ);
+ 	if (rc == -ENODATA || rc == -EOPNOTSUPP) {
+ 		/* no data, that's ok */
+ 		rc = 0;
+@@ -256,7 +264,7 @@ static int get_file_caps(struct linux_binprm *bprm)
+ 	if (rc < 0)
+ 		goto out;
+ 
+-	rc = cap_from_disk(&incaps, bprm, rc);
++	rc = cap_from_disk(&vcaps, bprm, rc);
+ 	if (rc)
+ 		printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
+ 			__FUNCTION__, rc, bprm->filename);
+@@ -321,10 +329,11 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
+ 	/* Derived from fs/exec.c:compute_creds. */
+ 	kernel_cap_t new_permitted, working;
+ 
+-	new_permitted = cap_intersect (bprm->cap_permitted, cap_bset);
+-	working = cap_intersect (bprm->cap_inheritable,
++	new_permitted = cap_intersect(bprm->cap_permitted,
++				 current->cap_bset);
++	working = cap_intersect(bprm->cap_inheritable,
+ 				 current->cap_inheritable);
+-	new_permitted = cap_combine (new_permitted, working);
++	new_permitted = cap_combine(new_permitted, working);
+ 
+ 	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
+ 	    !cap_issubset (new_permitted, current->cap_permitted)) {
+@@ -351,8 +360,10 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
+ 	 * capability rules */
+ 	if (!is_global_init(current)) {
+ 		current->cap_permitted = new_permitted;
+-		current->cap_effective = bprm->cap_effective ?
+-				new_permitted : 0;
++		if (bprm->cap_effective)
++			current->cap_effective = new_permitted;
++		else
++			cap_clear(current->cap_effective);
+ 	}
+ 
+ 	/* AUD: Audit candidate if current->cap_effective is set */
+@@ -474,13 +485,15 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
+ 
+ 			if (!issecure (SECURE_NO_SETUID_FIXUP)) {
+ 				if (old_fsuid == 0 && current->fsuid != 0) {
+-					cap_t (current->cap_effective) &=
+-					    ~CAP_FS_MASK;
++					current->cap_effective =
++						cap_drop_fs_set(
++						    current->cap_effective);
+ 				}
+ 				if (old_fsuid != 0 && current->fsuid == 0) {
+-					cap_t (current->cap_effective) |=
+-					    (cap_t (current->cap_permitted) &
+-					     CAP_FS_MASK);
++					current->cap_effective =
++						cap_raise_fs_set(
++						    current->cap_effective,
++						    current->cap_permitted);
+ 				}
+ 			}
+ 			break;
+@@ -561,6 +574,23 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,
+ 
+ 	return -EPERM;
+ }
 +
-+	# All done with mercurial
-+	exit
- fi
-diff --git a/security/Kconfig b/security/Kconfig
-index 8086e61..389e151 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -76,6 +76,7 @@ config SECURITY_NETWORK_XFRM
- config SECURITY_CAPABILITIES
- 	bool "Default Linux Capabilities"
- 	depends on SECURITY
-+	default y
- 	help
- 	  This enables the "default" Linux capabilities functionality.
- 	  If you are unsure how to answer this question, answer Y.
++/*
++ * called from kernel/sys.c for prctl(PR_CABSET_DROP)
++ * done without task_capability_lock() because it introduces
++ * no new races - i.e. only another task doing capget() on
++ * this task could get inconsistent info.  There can be no
++ * racing writer bc a task can only change its own caps.
++ */
++long cap_prctl_drop(unsigned long cap)
++{
++	if (!capable(CAP_SETPCAP))
++		return -EPERM;
++	if (!cap_valid(cap))
++		return -EINVAL;
++	cap_lower(current->cap_bset, cap);
++	return 0;
++}
+ #else
+ int cap_task_setscheduler (struct task_struct *p, int policy,
+ 			   struct sched_param *lp)
+@@ -584,9 +614,9 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,
+ 
+ void cap_task_reparent_to_init (struct task_struct *p)
+ {
+-	p->cap_effective = CAP_INIT_EFF_SET;
+-	p->cap_inheritable = CAP_INIT_INH_SET;
+-	p->cap_permitted = CAP_FULL_SET;
++	cap_set_init_eff(p->cap_effective);
++	cap_clear(p->cap_inheritable);
++	cap_set_full(p->cap_permitted);
+ 	p->keep_capabilities = 0;
+ 	return;
+ }
 diff --git a/security/dummy.c b/security/dummy.c
-index 3ccfbbe..48d4b0a 100644
+index 3ccfbbe..649326b 100644
 --- a/security/dummy.c
 +++ b/security/dummy.c
-@@ -225,22 +225,40 @@ static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags,
+@@ -36,14 +36,19 @@ static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
+ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective,
+ 			 kernel_cap_t * inheritable, kernel_cap_t * permitted)
+ {
+-	*effective = *inheritable = *permitted = 0;
+ 	if (target->euid == 0) {
+-		*permitted |= (~0 & ~CAP_FS_MASK);
+-		*effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK);
++		cap_set_full(*permitted);
++		cap_set_init_eff(*effective);
++	} else {
++		cap_clear(*permitted);
++		cap_clear(*effective);
+ 	}
+-	if (target->fsuid == 0) {
+-		*permitted |= CAP_FS_MASK;
+-		*effective |= CAP_FS_MASK;
++
++	cap_clear(*inheritable);
++
++	if (target->fsuid != 0) {
++		*permitted = cap_drop_fs_set(*permitted);
++		*effective = cap_drop_fs_set(*effective);
+ 	}
+ 	return 0;
+ }
+@@ -225,22 +230,40 @@ static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags,
  }
  
  
@@ -1014557,7 +1094627,16 @@
  {
  	return;
  }
-@@ -928,6 +946,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+@@ -384,7 +407,7 @@ static int dummy_inode_killpriv(struct dentry *dentry)
+ 	return 0;
+ }
+ 
+-static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
++static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
+ {
+ 	return -EOPNOTSUPP;
+ }
+@@ -928,6 +951,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  	return -EOPNOTSUPP;
  }
  
@@ -1014569,7 +1094648,7 @@
  static void dummy_release_secctx(char *secdata, u32 seclen)
  {
  }
-@@ -994,10 +1017,12 @@ void security_fixup_ops (struct security_operations *ops)
+@@ -994,10 +1022,12 @@ void security_fixup_ops (struct security_operations *ops)
  	set_to_dummy_if_null(ops, sb_umount_close);
  	set_to_dummy_if_null(ops, sb_umount_busy);
  	set_to_dummy_if_null(ops, sb_post_remount);
@@ -1014583,7 +1094662,7 @@
  	set_to_dummy_if_null(ops, inode_alloc_security);
  	set_to_dummy_if_null(ops, inode_free_security);
  	set_to_dummy_if_null(ops, inode_init_security);
-@@ -1086,6 +1111,7 @@ void security_fixup_ops (struct security_operations *ops)
+@@ -1086,6 +1116,7 @@ void security_fixup_ops (struct security_operations *ops)
   	set_to_dummy_if_null(ops, getprocattr);
   	set_to_dummy_if_null(ops, setprocattr);
   	set_to_dummy_if_null(ops, secid_to_secctx);
@@ -1014644,7 +1094723,7 @@
  	.next	= proc_key_users_next,
  	.stop	= proc_key_users_stop,
 diff --git a/security/security.c b/security/security.c
-index 0e1f1f1..ca475ca 100644
+index 0e1f1f1..b6c57a6 100644
 --- a/security/security.c
 +++ b/security/security.c
 @@ -288,11 +288,6 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
@@ -1014686,6 +1094765,20 @@
  int security_inode_alloc(struct inode *inode)
  {
  	inode->i_security = NULL;
+@@ -478,11 +493,11 @@ int security_inode_killpriv(struct dentry *dentry)
+ 	return security_ops->inode_killpriv(dentry);
+ }
+ 
+-int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
++int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
+ {
+ 	if (unlikely(IS_PRIVATE(inode)))
+ 		return 0;
+-	return security_ops->inode_getsecurity(inode, name, buffer, size, err);
++	return security_ops->inode_getsecurity(inode, name, buffer, alloc);
+ }
+ 
+ int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
 @@ -816,6 +831,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  }
  EXPORT_SYMBOL(security_secid_to_secctx);
@@ -1014805,7 +1094898,7 @@
 +}
 +EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec);
 diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index 9f3124b..be6de0b 100644
+index 9f3124b..e5ed075 100644
 --- a/security/selinux/hooks.c
 +++ b/security/selinux/hooks.c
 @@ -12,8 +12,8 @@
@@ -1014855,10 +1094948,13 @@
  #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
  int selinux_enforcing = 0;
  
-@@ -153,6 +162,21 @@ getsecurity_exit:
- 	return len;
- }
+@@ -127,30 +136,19 @@ static DEFINE_SPINLOCK(sb_security_lock);
+ 
+ static struct kmem_cache *sel_inode_cache;
  
+-/* Return security context for a given sid or just the context 
+-   length if the buffer is null or length is 0 */
+-static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
 +/**
 + * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
 + *
@@ -1014870,14 +1094966,32 @@
 + *
 + */
 +static int selinux_secmark_enabled(void)
-+{
+ {
+-	char *context;
+-	unsigned len;
+-	int rc;
+-
+-	rc = security_sid_to_context(sid, &context, &len);
+-	if (rc)
+-		return rc;
+-
+-	if (!buffer || !size)
+-		goto getsecurity_exit;
+-
+-	if (size < len) {
+-		len = -ERANGE;
+-		goto getsecurity_exit;
+-	}
+-	memcpy(buffer, context, len);
+-
+-getsecurity_exit:
+-	kfree(context);
+-	return len;
 +	return (atomic_read(&selinux_secmark_refcount) > 0);
-+}
-+
- /* Allocate and free functions for each kind of security blob. */
+ }
  
- static int task_alloc_security(struct task_struct *task)
-@@ -321,8 +345,8 @@ enum {
+ /* Allocate and free functions for each kind of security blob. */
+@@ -321,8 +319,8 @@ enum {
  	Opt_error = -1,
  	Opt_context = 1,
  	Opt_fscontext = 2,
@@ -1014888,7 +1095002,7 @@
  };
  
  static match_table_t tokens = {
-@@ -366,150 +390,317 @@ static int may_context_mount_inode_relabel(u32 sid,
+@@ -366,150 +364,317 @@ static int may_context_mount_inode_relabel(u32 sid,
  	return rc;
  }
  
@@ -1015170,8 +1095284,7 @@
 +	*num_opts = 0;
 +	return rc;
 +}
- 
--	if (!seen)
++
 +static int bad_option(struct superblock_security_struct *sbsec, char flag,
 +		      u32 old_sid, u32 new_sid)
 +{
@@ -1015206,7 +1095319,8 @@
 +	u32 defcontext_sid = 0;
 +
 +	mutex_lock(&sbsec->lock);
-+
+ 
+-	if (!seen)
 +	if (!ss_initialized) {
 +		if (!num_opts) {
 +			/* Defer initialization until selinux_complete_init,
@@ -1015256,8 +1095370,7 @@
 +			break;
 +		case CONTEXT_MNT:
 +			context_sid = sid;
- 
--		rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
++
 +			if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid,
 +					context_sid))
 +				goto out_double_mount;
@@ -1015289,7 +1095402,8 @@
 +			goto out;
 +		}
 +	}
-+
+ 
+-		rc = may_context_mount_sb_relabel(sid, sbsec, tsec);
 +	if (sbsec->initialized) {
 +		/* previously mounted with options, but not on this attempt? */
 +		if (sbsec->flags && !num_opts)
@@ -1015322,7 +1095436,7 @@
  	}
  
  	/*
-@@ -517,182 +708,250 @@ static int try_context_mount(struct super_block *sb, void *data)
+@@ -517,182 +682,250 @@ static int try_context_mount(struct super_block *sb, void *data)
  	 * sets the label used on all file below the mountpoint, and will set
  	 * the superblock context if not already set.
  	 */
@@ -1015709,7 +1095823,37 @@
  	return rc;
  }
  
-@@ -3158,7 +3417,7 @@ out:
+@@ -2416,14 +2649,27 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
+  *
+  * Permission check is handled by selinux_inode_getxattr hook.
+  */
+-static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
++static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
+ {
++	u32 size;
++	int error;
++	char *context = NULL;
+ 	struct inode_security_struct *isec = inode->i_security;
+ 
+ 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
+ 		return -EOPNOTSUPP;
+ 
+-	return selinux_getsecurity(isec->sid, buffer, size);
++	error = security_sid_to_context(isec->sid, &context, &size);
++	if (error)
++		return error;
++	error = size;
++	if (alloc) {
++		*buffer = context;
++		goto out_nofree;
++	}
++	kfree(context);
++out_nofree:
++	return error;
+ }
+ 
+ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
+@@ -3158,7 +3404,7 @@ out:
  #endif /* IPV6 */
  
  static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
@@ -1015718,7 +1095862,7 @@
  {
  	int ret = 0;
  
-@@ -3167,7 +3426,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
+@@ -3167,7 +3413,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
  		ret = selinux_parse_skb_ipv4(skb, ad, proto);
  		if (ret || !addrp)
  			break;
@@ -1015726,7 +1095870,7 @@
  		*addrp = (char *)(src ? &ad->u.net.v4info.saddr :
  					&ad->u.net.v4info.daddr);
  		break;
-@@ -3177,7 +3435,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
+@@ -3177,7 +3422,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
  		ret = selinux_parse_skb_ipv6(skb, ad, proto);
  		if (ret || !addrp)
  			break;
@@ -1015734,7 +1095878,7 @@
  		*addrp = (char *)(src ? &ad->u.net.v6info.saddr :
  					&ad->u.net.v6info.daddr);
  		break;
-@@ -3186,36 +3443,48 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
+@@ -3186,36 +3430,48 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
  		break;
  	}
  
@@ -1015799,7 +1095943,7 @@
  }
  
  /* socket security operations */
-@@ -3281,6 +3550,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
+@@ -3281,6 +3537,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
  	if (sock->sk) {
  		sksec = sock->sk->sk_security;
  		sksec->sid = isec->sid;
@@ -1015807,7 +1095951,7 @@
  		err = selinux_netlbl_socket_post_create(sock);
  	}
  
-@@ -3373,7 +3643,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
+@@ -3373,7 +3630,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
  			break;
  		}
  		
@@ -1015816,7 +1095960,7 @@
  		if (err)
  			goto out;
  		
-@@ -3584,131 +3854,182 @@ static int selinux_socket_unix_may_send(struct socket *sock,
+@@ -3584,131 +3841,182 @@ static int selinux_socket_unix_may_send(struct socket *sock,
  	return 0;
  }
  
@@ -1015869,8 +1096013,7 @@
 +	return avc_has_perm(peer_sid, node_sid,
 +			    SECCLASS_NODE, NODE__RECVFROM, ad);
 +}
- 
--	switch (sock_class) {
++
 +static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
 +						struct sk_buff *skb,
 +						struct avc_audit_data *ad,
@@ -1015882,7 +1096025,8 @@
 +	u16 sk_class;
 +	u32 netif_perm, node_perm, recv_perm;
 +	u32 port_sid, node_sid, if_sid, sk_sid;
-+
+ 
+-	switch (sock_class) {
 +	sk_sid = sksec->sid;
 +	sk_class = sksec->sclass;
 +
@@ -1016070,21 +1096214,21 @@
  	return err;
  }
  
-@@ -3759,18 +4080,25 @@ out:
+@@ -3759,18 +4067,25 @@ out:
  static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
  {
  	u32 peer_secid = SECSID_NULL;
 -	int err = 0;
 +	u16 family;
- 
--	if (sock && sock->sk->sk_family == PF_UNIX)
++
 +	if (sock)
 +		family = sock->sk->sk_family;
 +	else if (skb && skb->sk)
 +		family = skb->sk->sk_family;
 +	else
 +		goto out;
-+
+ 
+-	if (sock && sock->sk->sk_family == PF_UNIX)
 +	if (sock && family == PF_UNIX)
  		selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
  	else if (skb)
@@ -1016103,7 +1096247,7 @@
  }
  
  static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
-@@ -3790,6 +4118,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
+@@ -3790,6 +4105,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
  
  	newssec->sid = ssec->sid;
  	newssec->peer_sid = ssec->peer_sid;
@@ -1016111,7 +1096255,7 @@
  
  	selinux_netlbl_sk_security_clone(ssec, newssec);
  }
-@@ -3813,6 +4142,7 @@ static void selinux_sock_graft(struct sock* sk, struct socket *parent)
+@@ -3813,6 +4129,7 @@ static void selinux_sock_graft(struct sock* sk, struct socket *parent)
  	if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
  	    sk->sk_family == PF_UNIX)
  		isec->sid = sksec->sid;
@@ -1016119,7 +1096263,7 @@
  
  	selinux_netlbl_sock_graft(sk, parent);
  }
-@@ -3825,7 +4155,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
+@@ -3825,7 +4142,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
  	u32 newsid;
  	u32 peersid;
  
@@ -1016130,7 +1096274,7 @@
  	if (peersid == SECSID_NULL) {
  		req->secid = sksec->sid;
  		req->peer_secid = SECSID_NULL;
-@@ -3863,7 +4195,7 @@ static void selinux_inet_conn_established(struct sock *sk,
+@@ -3863,7 +4182,7 @@ static void selinux_inet_conn_established(struct sock *sk,
  {
  	struct sk_security_struct *sksec = sk->sk_security;
  
@@ -1016139,7 +1096283,7 @@
  }
  
  static void selinux_req_classify_flow(const struct request_sock *req,
-@@ -3910,149 +4242,260 @@ out:
+@@ -3910,149 +4229,260 @@ out:
  
  #ifdef CONFIG_NETFILTER
  
@@ -1016200,7 +1096344,8 @@
 +
 +	return NF_ACCEPT;
 +}
-+
+ 
+-	switch (isec->sclass) {
 +static unsigned int selinux_ipv4_forward(unsigned int hooknum,
 +					 struct sk_buff *skb,
 +					 const struct net_device *in,
@@ -1016209,8 +1096354,7 @@
 +{
 +	return selinux_ip_forward(skb, in->ifindex, PF_INET);
 +}
- 
--	switch (isec->sclass) {
++
 +#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 +static unsigned int selinux_ipv6_forward(unsigned int hooknum,
 +					 struct sk_buff *skb,
@@ -1016491,7 +1096635,7 @@
  #endif	/* IPV6 */
  
  #endif	/* CONFIG_NETFILTER */
-@@ -4710,6 +5153,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+@@ -4710,6 +5140,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  	return security_sid_to_context(secid, secdata, seclen);
  }
  
@@ -1016503,7 +1096647,7 @@
  static void selinux_release_secctx(char *secdata, u32 seclen)
  {
  	kfree(secdata);
-@@ -4800,6 +5248,9 @@ static struct security_operations selinux_ops = {
+@@ -4800,6 +5235,9 @@ static struct security_operations selinux_ops = {
  	.sb_statfs =			selinux_sb_statfs,
  	.sb_mount =			selinux_mount,
  	.sb_umount =			selinux_umount,
@@ -1016513,7 +1096657,7 @@
  
  	.inode_alloc_security =		selinux_inode_alloc_security,
  	.inode_free_security =		selinux_inode_free_security,
-@@ -4898,6 +5349,7 @@ static struct security_operations selinux_ops = {
+@@ -4898,6 +5336,7 @@ static struct security_operations selinux_ops = {
  	.setprocattr =                  selinux_setprocattr,
  
  	.secid_to_secctx =		selinux_secid_to_secctx,
@@ -1016521,7 +1096665,7 @@
  	.release_secctx =		selinux_release_secctx,
  
          .unix_stream_connect =		selinux_socket_unix_stream_connect,
-@@ -5031,22 +5483,40 @@ security_initcall(selinux_init);
+@@ -5031,22 +5470,40 @@ security_initcall(selinux_init);
  
  #if defined(CONFIG_NETFILTER)
  
@@ -1016574,7 +1096718,7 @@
  };
  
  #endif	/* IPV6 */
-@@ -5054,22 +5524,27 @@ static struct nf_hook_ops selinux_ipv6_op = {
+@@ -5054,22 +5511,27 @@ static struct nf_hook_ops selinux_ipv6_op = {
  static int __init selinux_nf_ip_init(void)
  {
  	int err = 0;
@@ -1016610,7 +1096754,7 @@
  #endif	/* IPV6 */
  
  out:
-@@ -5081,11 +5556,15 @@ __initcall(selinux_nf_ip_init);
+@@ -5081,11 +5543,15 @@ __initcall(selinux_nf_ip_init);
  #ifdef CONFIG_SECURITY_SELINUX_DISABLE
  static void selinux_nf_ip_exit(void)
  {
@@ -1018783,6 +1098927,4134 @@
  
  	return rc;
  }
+diff --git a/security/smack/Kconfig b/security/smack/Kconfig
+new file mode 100644
+index 0000000..603b087
+--- /dev/null
++++ b/security/smack/Kconfig
+@@ -0,0 +1,10 @@
++config SECURITY_SMACK
++	bool "Simplified Mandatory Access Control Kernel Support"
++	depends on NETLABEL && SECURITY_NETWORK
++	default n
++	help
++	  This selects the Simplified Mandatory Access Control Kernel.
++	  Smack is useful for sensitivity, integrity, and a variety
++	  of other mandatory security schemes.
++	  If you are unsure how to answer this question, answer N.
++
+diff --git a/security/smack/Makefile b/security/smack/Makefile
+new file mode 100644
+index 0000000..67a63aa
+--- /dev/null
++++ b/security/smack/Makefile
+@@ -0,0 +1,7 @@
++#
++# Makefile for the SMACK LSM
++#
++
++obj-$(CONFIG_SECURITY_SMACK) := smack.o
++
++smack-y := smack_lsm.o smack_access.o smackfs.o
+diff --git a/security/smack/smack.h b/security/smack/smack.h
+new file mode 100644
+index 0000000..a21a0e9
+--- /dev/null
++++ b/security/smack/smack.h
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (C) 2007 Casey Schaufler <casey at schaufler-ca.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, version 2.
++ *
++ * Author:
++ *      Casey Schaufler <casey at schaufler-ca.com>
++ *
++ */
++
++#ifndef _SECURITY_SMACK_H
++#define _SECURITY_SMACK_H
++
++#include <linux/capability.h>
++#include <linux/spinlock.h>
++#include <net/netlabel.h>
++
++/*
++ * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is
++ * bigger than can be used, and 24 is the next lower multiple
++ * of 8, and there are too many issues if there isn't space set
++ * aside for the terminating null byte.
++ */
++#define SMK_MAXLEN	23
++#define SMK_LABELLEN	(SMK_MAXLEN+1)
++
++/*
++ * How many kinds of access are there?
++ * Here's your answer.
++ */
++#define SMK_ACCESSDASH	'-'
++#define SMK_ACCESSLOW	"rwxa"
++#define SMK_ACCESSKINDS	(sizeof(SMK_ACCESSLOW) - 1)
++
++struct superblock_smack {
++	char		*smk_root;
++	char		*smk_floor;
++	char		*smk_hat;
++	char		*smk_default;
++	int		smk_initialized;
++	spinlock_t	smk_sblock;	/* for initialization */
++};
++
++struct socket_smack {
++	char		*smk_out;			/* outbound label */
++	char		*smk_in;			/* inbound label */
++	char		smk_packet[SMK_LABELLEN];	/* TCP peer label */
++};
++
++/*
++ * Inode smack data
++ */
++struct inode_smack {
++	char		*smk_inode;	/* label of the fso */
++	struct mutex	smk_lock;	/* initialization lock */
++	int		smk_flags;	/* smack inode flags */
++};
++
++#define	SMK_INODE_INSTANT	0x01	/* inode is instantiated */
++
++/*
++ * A label access rule.
++ */
++struct smack_rule {
++	char	*smk_subject;
++	char	*smk_object;
++	int	smk_access;
++};
++
++/*
++ * An entry in the table of permitted label accesses.
++ */
++struct smk_list_entry {
++	struct smk_list_entry	*smk_next;
++	struct smack_rule	smk_rule;
++};
++
++/*
++ * An entry in the table mapping smack values to
++ * CIPSO level/category-set values.
++ */
++struct smack_cipso {
++	int	smk_level;
++	char	smk_catset[SMK_LABELLEN];
++};
++
++/*
++ * This is the repository for labels seen so that it is
++ * not necessary to keep allocating tiny chuncks of memory
++ * and so that they can be shared.
++ *
++ * Labels are never modified in place. Anytime a label
++ * is imported (e.g. xattrset on a file) the list is checked
++ * for it and it is added if it doesn't exist. The address
++ * is passed out in either case. Entries are added, but
++ * never deleted.
++ *
++ * Since labels are hanging around anyway it doesn't
++ * hurt to maintain a secid for those awkward situations
++ * where kernel components that ought to use LSM independent
++ * interfaces don't. The secid should go away when all of
++ * these components have been repaired.
++ *
++ * If there is a cipso value associated with the label it
++ * gets stored here, too. This will most likely be rare as
++ * the cipso direct mapping in used internally.
++ */
++struct smack_known {
++	struct smack_known	*smk_next;
++	char			smk_known[SMK_LABELLEN];
++	u32			smk_secid;
++	struct smack_cipso	*smk_cipso;
++	spinlock_t		smk_cipsolock; /* for changing cipso map */
++};
++
++/*
++ * Mount options
++ */
++#define SMK_FSDEFAULT	"smackfsdef="
++#define SMK_FSFLOOR	"smackfsfloor="
++#define SMK_FSHAT	"smackfshat="
++#define SMK_FSROOT	"smackfsroot="
++
++/*
++ * xattr names
++ */
++#define XATTR_SMACK_SUFFIX	"SMACK64"
++#define XATTR_SMACK_IPIN	"SMACK64IPIN"
++#define XATTR_SMACK_IPOUT	"SMACK64IPOUT"
++#define XATTR_NAME_SMACK	XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX
++#define XATTR_NAME_SMACKIPIN	XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN
++#define XATTR_NAME_SMACKIPOUT	XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT
++
++/*
++ * smackfs macic number
++ */
++#define SMACK_MAGIC	0x43415d53 /* "SMAC" */
++
++/*
++ * A limit on the number of entries in the lists
++ * makes some of the list administration easier.
++ */
++#define SMACK_LIST_MAX	10000
++
++/*
++ * CIPSO defaults.
++ */
++#define SMACK_CIPSO_DOI_DEFAULT		3	/* Historical */
++#define SMACK_CIPSO_DIRECT_DEFAULT	250	/* Arbitrary */
++#define SMACK_CIPSO_MAXCATVAL		63	/* Bigger gets harder */
++#define SMACK_CIPSO_MAXLEVEL            255     /* CIPSO 2.2 standard */
++#define SMACK_CIPSO_MAXCATNUM           239     /* CIPSO 2.2 standard */
++
++/*
++ * Just to make the common cases easier to deal with
++ */
++#define MAY_ANY		(MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
++#define MAY_ANYREAD	(MAY_READ | MAY_EXEC)
++#define MAY_ANYWRITE	(MAY_WRITE | MAY_APPEND)
++#define MAY_READWRITE	(MAY_READ | MAY_WRITE)
++#define MAY_NOT		0
++
++/*
++ * These functions are in smack_lsm.c
++ */
++struct inode_smack *new_inode_smack(char *);
++
++/*
++ * These functions are in smack_access.c
++ */
++int smk_access(char *, char *, int);
++int smk_curacc(char *, u32);
++int smack_to_cipso(const char *, struct smack_cipso *);
++void smack_from_cipso(u32, char *, char *);
++char *smack_from_secid(const u32);
++char *smk_import(const char *, int);
++struct smack_known *smk_import_entry(const char *, int);
++u32 smack_to_secid(const char *);
++
++/*
++ * Shared data.
++ */
++extern int smack_cipso_direct;
++extern int smack_net_nltype;
++extern char *smack_net_ambient;
++
++extern struct smack_known *smack_known;
++extern struct smack_known smack_known_floor;
++extern struct smack_known smack_known_hat;
++extern struct smack_known smack_known_huh;
++extern struct smack_known smack_known_invalid;
++extern struct smack_known smack_known_star;
++extern struct smack_known smack_known_unset;
++
++extern struct smk_list_entry *smack_list;
++
++/*
++ * Stricly for CIPSO level manipulation.
++ * Set the category bit number in a smack label sized buffer.
++ */
++static inline void smack_catset_bit(int cat, char *catsetp)
++{
++	if (cat > SMK_LABELLEN * 8)
++		return;
++
++	catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
++}
++
++/*
++ * Present a pointer to the smack label in an inode blob.
++ */
++static inline char *smk_of_inode(const struct inode *isp)
++{
++	struct inode_smack *sip = isp->i_security;
++	return sip->smk_inode;
++}
++
++#endif  /* _SECURITY_SMACK_H */
+diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
+new file mode 100644
+index 0000000..f6b5f6e
+--- /dev/null
++++ b/security/smack/smack_access.c
+@@ -0,0 +1,356 @@
++/*
++ * Copyright (C) 2007 Casey Schaufler <casey at schaufler-ca.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, version 2.
++ *
++ * Author:
++ *      Casey Schaufler <casey at schaufler-ca.com>
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/sched.h>
++#include "smack.h"
++
++struct smack_known smack_known_unset = {
++	.smk_next	= NULL,
++	.smk_known	= "UNSET",
++	.smk_secid	= 1,
++	.smk_cipso	= NULL,
++};
++
++struct smack_known smack_known_huh = {
++	.smk_next	= &smack_known_unset,
++	.smk_known	= "?",
++	.smk_secid	= 2,
++	.smk_cipso	= NULL,
++};
++
++struct smack_known smack_known_hat = {
++	.smk_next	= &smack_known_huh,
++	.smk_known	= "^",
++	.smk_secid	= 3,
++	.smk_cipso	= NULL,
++};
++
++struct smack_known smack_known_star = {
++	.smk_next	= &smack_known_hat,
++	.smk_known	= "*",
++	.smk_secid	= 4,
++	.smk_cipso	= NULL,
++};
++
++struct smack_known smack_known_floor = {
++	.smk_next	= &smack_known_star,
++	.smk_known	= "_",
++	.smk_secid	= 5,
++	.smk_cipso	= NULL,
++};
++
++struct smack_known smack_known_invalid = {
++	.smk_next	= &smack_known_floor,
++	.smk_known	= "",
++	.smk_secid	= 6,
++	.smk_cipso	= NULL,
++};
++
++struct smack_known *smack_known = &smack_known_invalid;
++
++/*
++ * The initial value needs to be bigger than any of the
++ * known values above.
++ */
++static u32 smack_next_secid = 10;
++
++/**
++ * smk_access - determine if a subject has a specific access to an object
++ * @subject_label: a pointer to the subject's Smack label
++ * @object_label: a pointer to the object's Smack label
++ * @request: the access requested, in "MAY" format
++ *
++ * This function looks up the subject/object pair in the
++ * access rule list and returns 0 if the access is permitted,
++ * non zero otherwise.
++ *
++ * Even though Smack labels are usually shared on smack_list
++ * labels that come in off the network can't be imported
++ * and added to the list for locking reasons.
++ *
++ * Therefore, it is necessary to check the contents of the labels,
++ * not just the pointer values. Of course, in most cases the labels
++ * will be on the list, so checking the pointers may be a worthwhile
++ * optimization.
++ */
++int smk_access(char *subject_label, char *object_label, int request)
++{
++	u32 may = MAY_NOT;
++	struct smk_list_entry *sp;
++	struct smack_rule *srp;
++
++	/*
++	 * Hardcoded comparisons.
++	 *
++	 * A star subject can't access any object.
++	 */
++	if (subject_label == smack_known_star.smk_known ||
++	    strcmp(subject_label, smack_known_star.smk_known) == 0)
++		return -EACCES;
++	/*
++	 * A star object can be accessed by any subject.
++	 */
++	if (object_label == smack_known_star.smk_known ||
++	    strcmp(object_label, smack_known_star.smk_known) == 0)
++		return 0;
++	/*
++	 * An object can be accessed in any way by a subject
++	 * with the same label.
++	 */
++	if (subject_label == object_label ||
++	    strcmp(subject_label, object_label) == 0)
++		return 0;
++	/*
++	 * A hat subject can read any object.
++	 * A floor object can be read by any subject.
++	 */
++	if ((request & MAY_ANYREAD) == request) {
++		if (object_label == smack_known_floor.smk_known ||
++		    strcmp(object_label, smack_known_floor.smk_known) == 0)
++			return 0;
++		if (subject_label == smack_known_hat.smk_known ||
++		    strcmp(subject_label, smack_known_hat.smk_known) == 0)
++			return 0;
++	}
++	/*
++	 * Beyond here an explicit relationship is required.
++	 * If the requested access is contained in the available
++	 * access (e.g. read is included in readwrite) it's
++	 * good.
++	 */
++	for (sp = smack_list; sp != NULL; sp = sp->smk_next) {
++		srp = &sp->smk_rule;
++
++		if (srp->smk_subject == subject_label ||
++		    strcmp(srp->smk_subject, subject_label) == 0) {
++			if (srp->smk_object == object_label ||
++			    strcmp(srp->smk_object, object_label) == 0) {
++				may = srp->smk_access;
++				break;
++			}
++		}
++	}
++	/*
++	 * This is a bit map operation.
++	 */
++	if ((request & may) == request)
++		return 0;
++
++	return -EACCES;
++}
++
++/**
++ * smk_curacc - determine if current has a specific access to an object
++ * @object_label: a pointer to the object's Smack label
++ * @request: the access requested, in "MAY" format
++ *
++ * This function checks the current subject label/object label pair
++ * in the access rule list and returns 0 if the access is permitted,
++ * non zero otherwise. It allows that current my have the capability
++ * to override the rules.
++ */
++int smk_curacc(char *obj_label, u32 mode)
++{
++	int rc;
++
++	rc = smk_access(current->security, obj_label, mode);
++	if (rc == 0)
++		return 0;
++
++	if (capable(CAP_MAC_OVERRIDE))
++		return 0;
++
++	return rc;
++}
++
++static DEFINE_MUTEX(smack_known_lock);
++
++/**
++ * smk_import_entry - import a label, return the list entry
++ * @string: a text string that might be a Smack label
++ * @len: the maximum size, or zero if it is NULL terminated.
++ *
++ * Returns a pointer to the entry in the label list that
++ * matches the passed string, adding it if necessary.
++ */
++struct smack_known *smk_import_entry(const char *string, int len)
++{
++	struct smack_known *skp;
++	char smack[SMK_LABELLEN];
++	int found;
++	int i;
++
++	if (len <= 0 || len > SMK_MAXLEN)
++		len = SMK_MAXLEN;
++
++	for (i = 0, found = 0; i < SMK_LABELLEN; i++) {
++		if (found)
++			smack[i] = '\0';
++		else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
++			 string[i] == '/') {
++			smack[i] = '\0';
++			found = 1;
++		} else
++			smack[i] = string[i];
++	}
++
++	if (smack[0] == '\0')
++		return NULL;
++
++	mutex_lock(&smack_known_lock);
++
++	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
++		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
++			break;
++
++	if (skp == NULL) {
++		skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
++		if (skp != NULL) {
++			skp->smk_next = smack_known;
++			strncpy(skp->smk_known, smack, SMK_MAXLEN);
++			skp->smk_secid = smack_next_secid++;
++			skp->smk_cipso = NULL;
++			spin_lock_init(&skp->smk_cipsolock);
++			/*
++			 * Make sure that the entry is actually
++			 * filled before putting it on the list.
++			 */
++			smp_mb();
++			smack_known = skp;
++		}
++	}
++
++	mutex_unlock(&smack_known_lock);
++
++	return skp;
++}
++
++/**
++ * smk_import - import a smack label
++ * @string: a text string that might be a Smack label
++ * @len: the maximum size, or zero if it is NULL terminated.
++ *
++ * Returns a pointer to the label in the label list that
++ * matches the passed string, adding it if necessary.
++ */
++char *smk_import(const char *string, int len)
++{
++	struct smack_known *skp;
++
++	skp = smk_import_entry(string, len);
++	if (skp == NULL)
++		return NULL;
++	return skp->smk_known;
++}
++
++/**
++ * smack_from_secid - find the Smack label associated with a secid
++ * @secid: an integer that might be associated with a Smack label
++ *
++ * Returns a pointer to the appropraite Smack label if there is one,
++ * otherwise a pointer to the invalid Smack label.
++ */
++char *smack_from_secid(const u32 secid)
++{
++	struct smack_known *skp;
++
++	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
++		if (skp->smk_secid == secid)
++			return skp->smk_known;
++
++	/*
++	 * If we got this far someone asked for the translation
++	 * of a secid that is not on the list.
++	 */
++	return smack_known_invalid.smk_known;
++}
++
++/**
++ * smack_to_secid - find the secid associated with a Smack label
++ * @smack: the Smack label
++ *
++ * Returns the appropriate secid if there is one,
++ * otherwise 0
++ */
++u32 smack_to_secid(const char *smack)
++{
++	struct smack_known *skp;
++
++	for (skp = smack_known; skp != NULL; skp = skp->smk_next)
++		if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
++			return skp->smk_secid;
++	return 0;
++}
++
++/**
++ * smack_from_cipso - find the Smack label associated with a CIPSO option
++ * @level: Bell & LaPadula level from the network
++ * @cp: Bell & LaPadula categories from the network
++ * @result: where to put the Smack value
++ *
++ * This is a simple lookup in the label table.
++ *
++ * This is an odd duck as far as smack handling goes in that
++ * it sends back a copy of the smack label rather than a pointer
++ * to the master list. This is done because it is possible for
++ * a foreign host to send a smack label that is new to this
++ * machine and hence not on the list. That would not be an
++ * issue except that adding an entry to the master list can't
++ * be done at that point.
++ */
++void smack_from_cipso(u32 level, char *cp, char *result)
++{
++	struct smack_known *kp;
++	char *final = NULL;
++
++	for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) {
++		if (kp->smk_cipso == NULL)
++			continue;
++
++		spin_lock_bh(&kp->smk_cipsolock);
++
++		if (kp->smk_cipso->smk_level == level &&
++		    memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0)
++			final = kp->smk_known;
++
++		spin_unlock_bh(&kp->smk_cipsolock);
++	}
++	if (final == NULL)
++		final = smack_known_huh.smk_known;
++	strncpy(result, final, SMK_MAXLEN);
++	return;
++}
++
++/**
++ * smack_to_cipso - find the CIPSO option to go with a Smack label
++ * @smack: a pointer to the smack label in question
++ * @cp: where to put the result
++ *
++ * Returns zero if a value is available, non-zero otherwise.
++ */
++int smack_to_cipso(const char *smack, struct smack_cipso *cp)
++{
++	struct smack_known *kp;
++
++	for (kp = smack_known; kp != NULL; kp = kp->smk_next)
++		if (kp->smk_known == smack ||
++		    strcmp(kp->smk_known, smack) == 0)
++			break;
++
++	if (kp == NULL || kp->smk_cipso == NULL)
++		return -ENOENT;
++
++	memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));
++	return 0;
++}
+diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
+new file mode 100644
+index 0000000..1c11e42
+--- /dev/null
++++ b/security/smack/smack_lsm.c
+@@ -0,0 +1,2518 @@
++/*
++ *  Simplified MAC Kernel (smack) security module
++ *
++ *  This file contains the smack hook function implementations.
++ *
++ *  Author:
++ *	Casey Schaufler <casey at schaufler-ca.com>
++ *
++ *  Copyright (C) 2007 Casey Schaufler <casey at schaufler-ca.com>
++ *
++ *	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/xattr.h>
++#include <linux/pagemap.h>
++#include <linux/mount.h>
++#include <linux/stat.h>
++#include <linux/ext2_fs.h>
++#include <linux/kd.h>
++#include <asm/ioctls.h>
++#include <linux/tcp.h>
++#include <linux/udp.h>
++#include <linux/mutex.h>
++#include <linux/pipe_fs_i.h>
++#include <net/netlabel.h>
++#include <net/cipso_ipv4.h>
++
++#include "smack.h"
++
++/*
++ * I hope these are the hokeyist lines of code in the module. Casey.
++ */
++#define DEVPTS_SUPER_MAGIC	0x1cd1
++#define SOCKFS_MAGIC		0x534F434B
++#define TMPFS_MAGIC		0x01021994
++
++/**
++ * smk_fetch - Fetch the smack label from a file.
++ * @ip: a pointer to the inode
++ * @dp: a pointer to the dentry
++ *
++ * Returns a pointer to the master list entry for the Smack label
++ * or NULL if there was no label to fetch.
++ */
++static char *smk_fetch(struct inode *ip, struct dentry *dp)
++{
++	int rc;
++	char in[SMK_LABELLEN];
++
++	if (ip->i_op->getxattr == NULL)
++		return NULL;
++
++	rc = ip->i_op->getxattr(dp, XATTR_NAME_SMACK, in, SMK_LABELLEN);
++	if (rc < 0)
++		return NULL;
++
++	return smk_import(in, rc);
++}
++
++/**
++ * new_inode_smack - allocate an inode security blob
++ * @smack: a pointer to the Smack label to use in the blob
++ *
++ * Returns the new blob or NULL if there's no memory available
++ */
++struct inode_smack *new_inode_smack(char *smack)
++{
++	struct inode_smack *isp;
++
++	isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL);
++	if (isp == NULL)
++		return NULL;
++
++	isp->smk_inode = smack;
++	isp->smk_flags = 0;
++	mutex_init(&isp->smk_lock);
++
++	return isp;
++}
++
++/*
++ * LSM hooks.
++ * We he, that is fun!
++ */
++
++/**
++ * smack_ptrace - Smack approval on ptrace
++ * @ptp: parent task pointer
++ * @ctp: child task pointer
++ *
++ * Returns 0 if access is OK, an error code otherwise
++ *
++ * Do the capability checks, and require read and write.
++ */
++static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp)
++{
++	int rc;
++
++	rc = cap_ptrace(ptp, ctp);
++	if (rc != 0)
++		return rc;
++
++	rc = smk_access(ptp->security, ctp->security, MAY_READWRITE);
++	if (rc != 0 && __capable(ptp, CAP_MAC_OVERRIDE))
++		return 0;
++
++	return rc;
++}
++
++/**
++ * smack_syslog - Smack approval on syslog
++ * @type: message type
++ *
++ * Require that the task has the floor label
++ *
++ * Returns 0 on success, error code otherwise.
++ */
++static int smack_syslog(int type)
++{
++	int rc;
++	char *sp = current->security;
++
++	rc = cap_syslog(type);
++	if (rc != 0)
++		return rc;
++
++	if (capable(CAP_MAC_OVERRIDE))
++		return 0;
++
++	 if (sp != smack_known_floor.smk_known)
++		rc = -EACCES;
++
++	return rc;
++}
++
++
++/*
++ * Superblock Hooks.
++ */
++
++/**
++ * smack_sb_alloc_security - allocate a superblock blob
++ * @sb: the superblock getting the blob
++ *
++ * Returns 0 on success or -ENOMEM on error.
++ */
++static int smack_sb_alloc_security(struct super_block *sb)
++{
++	struct superblock_smack *sbsp;
++
++	sbsp = kzalloc(sizeof(struct superblock_smack), GFP_KERNEL);
++
++	if (sbsp == NULL)
++		return -ENOMEM;
++
++	sbsp->smk_root = smack_known_floor.smk_known;
++	sbsp->smk_default = smack_known_floor.smk_known;
++	sbsp->smk_floor = smack_known_floor.smk_known;
++	sbsp->smk_hat = smack_known_hat.smk_known;
++	sbsp->smk_initialized = 0;
++	spin_lock_init(&sbsp->smk_sblock);
++
++	sb->s_security = sbsp;
++
++	return 0;
++}
++
++/**
++ * smack_sb_free_security - free a superblock blob
++ * @sb: the superblock getting the blob
++ *
++ */
++static void smack_sb_free_security(struct super_block *sb)
++{
++	kfree(sb->s_security);
++	sb->s_security = NULL;
++}
++
++/**
++ * smack_sb_copy_data - copy mount options data for processing
++ * @type: file system type
++ * @orig: where to start
++ * @smackopts
++ *
++ * Returns 0 on success or -ENOMEM on error.
++ *
++ * Copy the Smack specific mount options out of the mount
++ * options list.
++ */
++static int smack_sb_copy_data(struct file_system_type *type, void *orig,
++			      void *smackopts)
++{
++	char *cp, *commap, *otheropts, *dp;
++
++	/* Binary mount data: just copy */
++	if (type->fs_flags & FS_BINARY_MOUNTDATA) {
++		copy_page(smackopts, orig);
++		return 0;
++	}
++
++	otheropts = (char *)get_zeroed_page(GFP_KERNEL);
++	if (otheropts == NULL)
++		return -ENOMEM;
++
++	for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) {
++		if (strstr(cp, SMK_FSDEFAULT) == cp)
++			dp = smackopts;
++		else if (strstr(cp, SMK_FSFLOOR) == cp)
++			dp = smackopts;
++		else if (strstr(cp, SMK_FSHAT) == cp)
++			dp = smackopts;
++		else if (strstr(cp, SMK_FSROOT) == cp)
++			dp = smackopts;
++		else
++			dp = otheropts;
++
++		commap = strchr(cp, ',');
++		if (commap != NULL)
++			*commap = '\0';
++
++		if (*dp != '\0')
++			strcat(dp, ",");
++		strcat(dp, cp);
++	}
++
++	strcpy(orig, otheropts);
++	free_page((unsigned long)otheropts);
++
++	return 0;
++}
++
++/**
++ * smack_sb_kern_mount - Smack specific mount processing
++ * @sb: the file system superblock
++ * @data: the smack mount options
++ *
++ * Returns 0 on success, an error code on failure
++ */
++static int smack_sb_kern_mount(struct super_block *sb, void *data)
++{
++	struct dentry *root = sb->s_root;
++	struct inode *inode = root->d_inode;
++	struct superblock_smack *sp = sb->s_security;
++	struct inode_smack *isp;
++	char *op;
++	char *commap;
++	char *nsp;
++
++	spin_lock(&sp->smk_sblock);
++	if (sp->smk_initialized != 0) {
++		spin_unlock(&sp->smk_sblock);
++		return 0;
++	}
++	sp->smk_initialized = 1;
++	spin_unlock(&sp->smk_sblock);
++
++	for (op = data; op != NULL; op = commap) {
++		commap = strchr(op, ',');
++		if (commap != NULL)
++			*commap++ = '\0';
++
++		if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) {
++			op += strlen(SMK_FSHAT);
++			nsp = smk_import(op, 0);
++			if (nsp != NULL)
++				sp->smk_hat = nsp;
++		} else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) {
++			op += strlen(SMK_FSFLOOR);
++			nsp = smk_import(op, 0);
++			if (nsp != NULL)
++				sp->smk_floor = nsp;
++		} else if (strncmp(op, SMK_FSDEFAULT,
++				   strlen(SMK_FSDEFAULT)) == 0) {
++			op += strlen(SMK_FSDEFAULT);
++			nsp = smk_import(op, 0);
++			if (nsp != NULL)
++				sp->smk_default = nsp;
++		} else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) {
++			op += strlen(SMK_FSROOT);
++			nsp = smk_import(op, 0);
++			if (nsp != NULL)
++				sp->smk_root = nsp;
++		}
++	}
++
++	/*
++	 * Initialize the root inode.
++	 */
++	isp = inode->i_security;
++	if (isp == NULL)
++		inode->i_security = new_inode_smack(sp->smk_root);
++	else
++		isp->smk_inode = sp->smk_root;
++
++	return 0;
++}
++
++/**
++ * smack_sb_statfs - Smack check on statfs
++ * @dentry: identifies the file system in question
++ *
++ * Returns 0 if current can read the floor of the filesystem,
++ * and error code otherwise
++ */
++static int smack_sb_statfs(struct dentry *dentry)
++{
++	struct superblock_smack *sbp = dentry->d_sb->s_security;
++
++	return smk_curacc(sbp->smk_floor, MAY_READ);
++}
++
++/**
++ * smack_sb_mount - Smack check for mounting
++ * @dev_name: unused
++ * @nd: mount point
++ * @type: unused
++ * @flags: unused
++ * @data: unused
++ *
++ * Returns 0 if current can write the floor of the filesystem
++ * being mounted on, an error code otherwise.
++ */
++static int smack_sb_mount(char *dev_name, struct nameidata *nd,
++			  char *type, unsigned long flags, void *data)
++{
++	struct superblock_smack *sbp = nd->mnt->mnt_sb->s_security;
++
++	return smk_curacc(sbp->smk_floor, MAY_WRITE);
++}
++
++/**
++ * smack_sb_umount - Smack check for unmounting
++ * @mnt: file system to unmount
++ * @flags: unused
++ *
++ * Returns 0 if current can write the floor of the filesystem
++ * being unmounted, an error code otherwise.
++ */
++static int smack_sb_umount(struct vfsmount *mnt, int flags)
++{
++	struct superblock_smack *sbp;
++
++	sbp = mnt->mnt_sb->s_security;
++
++	return smk_curacc(sbp->smk_floor, MAY_WRITE);
++}
++
++/*
++ * Inode hooks
++ */
++
++/**
++ * smack_inode_alloc_security - allocate an inode blob
++ * @inode - the inode in need of a blob
++ *
++ * Returns 0 if it gets a blob, -ENOMEM otherwise
++ */
++static int smack_inode_alloc_security(struct inode *inode)
++{
++	inode->i_security = new_inode_smack(current->security);
++	if (inode->i_security == NULL)
++		return -ENOMEM;
++	return 0;
++}
++
++/**
++ * smack_inode_free_security - free an inode blob
++ * @inode - the inode with a blob
++ *
++ * Clears the blob pointer in inode
++ */
++static void smack_inode_free_security(struct inode *inode)
++{
++	kfree(inode->i_security);
++	inode->i_security = NULL;
++}
++
++/**
++ * smack_inode_init_security - copy out the smack from an inode
++ * @inode: the inode
++ * @dir: unused
++ * @name: where to put the attribute name
++ * @value: where to put the attribute value
++ * @len: where to put the length of the attribute
++ *
++ * Returns 0 if it all works out, -ENOMEM if there's no memory
++ */
++static int smack_inode_init_security(struct inode *inode, struct inode *dir,
++				     char **name, void **value, size_t *len)
++{
++	char *isp = smk_of_inode(inode);
++
++	if (name) {
++		*name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
++		if (*name == NULL)
++			return -ENOMEM;
++	}
++
++	if (value) {
++		*value = kstrdup(isp, GFP_KERNEL);
++		if (*value == NULL)
++			return -ENOMEM;
++	}
++
++	if (len)
++		*len = strlen(isp) + 1;
++
++	return 0;
++}
++
++/**
++ * smack_inode_link - Smack check on link
++ * @old_dentry: the existing object
++ * @dir: unused
++ * @new_dentry: the new object
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
++			    struct dentry *new_dentry)
++{
++	int rc;
++	char *isp;
++
++	isp = smk_of_inode(old_dentry->d_inode);
++	rc = smk_curacc(isp, MAY_WRITE);
++
++	if (rc == 0 && new_dentry->d_inode != NULL) {
++		isp = smk_of_inode(new_dentry->d_inode);
++		rc = smk_curacc(isp, MAY_WRITE);
++	}
++
++	return rc;
++}
++
++/**
++ * smack_inode_unlink - Smack check on inode deletion
++ * @dir: containing directory object
++ * @dentry: file to unlink
++ *
++ * Returns 0 if current can write the containing directory
++ * and the object, error code otherwise
++ */
++static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
++{
++	struct inode *ip = dentry->d_inode;
++	int rc;
++
++	/*
++	 * You need write access to the thing you're unlinking
++	 */
++	rc = smk_curacc(smk_of_inode(ip), MAY_WRITE);
++	if (rc == 0)
++		/*
++		 * You also need write access to the containing directory
++		 */
++		rc = smk_curacc(smk_of_inode(dir), MAY_WRITE);
++
++	return rc;
++}
++
++/**
++ * smack_inode_rmdir - Smack check on directory deletion
++ * @dir: containing directory object
++ * @dentry: directory to unlink
++ *
++ * Returns 0 if current can write the containing directory
++ * and the directory, error code otherwise
++ */
++static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
++{
++	int rc;
++
++	/*
++	 * You need write access to the thing you're removing
++	 */
++	rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
++	if (rc == 0)
++		/*
++		 * You also need write access to the containing directory
++		 */
++		rc = smk_curacc(smk_of_inode(dir), MAY_WRITE);
++
++	return rc;
++}
++
++/**
++ * smack_inode_rename - Smack check on rename
++ * @old_inode: the old directory
++ * @old_dentry: unused
++ * @new_inode: the new directory
++ * @new_dentry: unused
++ *
++ * Read and write access is required on both the old and
++ * new directories.
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_rename(struct inode *old_inode,
++			      struct dentry *old_dentry,
++			      struct inode *new_inode,
++			      struct dentry *new_dentry)
++{
++	int rc;
++	char *isp;
++
++	isp = smk_of_inode(old_dentry->d_inode);
++	rc = smk_curacc(isp, MAY_READWRITE);
++
++	if (rc == 0 && new_dentry->d_inode != NULL) {
++		isp = smk_of_inode(new_dentry->d_inode);
++		rc = smk_curacc(isp, MAY_READWRITE);
++	}
++
++	return rc;
++}
++
++/**
++ * smack_inode_permission - Smack version of permission()
++ * @inode: the inode in question
++ * @mask: the access requested
++ * @nd: unused
++ *
++ * This is the important Smack hook.
++ *
++ * Returns 0 if access is permitted, -EACCES otherwise
++ */
++static int smack_inode_permission(struct inode *inode, int mask,
++				  struct nameidata *nd)
++{
++	/*
++	 * No permission to check. Existence test. Yup, it's there.
++	 */
++	if (mask == 0)
++		return 0;
++
++	return smk_curacc(smk_of_inode(inode), mask);
++}
++
++/**
++ * smack_inode_setattr - Smack check for setting attributes
++ * @dentry: the object
++ * @iattr: for the force flag
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
++{
++	/*
++	 * Need to allow for clearing the setuid bit.
++	 */
++	if (iattr->ia_valid & ATTR_FORCE)
++		return 0;
++
++	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
++}
++
++/**
++ * smack_inode_getattr - Smack check for getting attributes
++ * @mnt: unused
++ * @dentry: the object
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
++{
++	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
++}
++
++/**
++ * smack_inode_setxattr - Smack check for setting xattrs
++ * @dentry: the object
++ * @name: name of the attribute
++ * @value: unused
++ * @size: unused
++ * @flags: unused
++ *
++ * This protects the Smack attribute explicitly.
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_setxattr(struct dentry *dentry, char *name,
++				void *value, size_t size, int flags)
++{
++	if (!capable(CAP_MAC_ADMIN)) {
++		if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
++		    strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
++		    strcmp(name, XATTR_NAME_SMACKIPOUT) == 0)
++			return -EPERM;
++	}
++
++	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
++}
++
++/**
++ * smack_inode_post_setxattr - Apply the Smack update approved above
++ * @dentry: object
++ * @name: attribute name
++ * @value: attribute value
++ * @size: attribute size
++ * @flags: unused
++ *
++ * Set the pointer in the inode blob to the entry found
++ * in the master label list.
++ */
++static void smack_inode_post_setxattr(struct dentry *dentry, char *name,
++				      void *value, size_t size, int flags)
++{
++	struct inode_smack *isp;
++	char *nsp;
++
++	/*
++	 * Not SMACK
++	 */
++	if (strcmp(name, XATTR_NAME_SMACK))
++		return;
++
++	if (size >= SMK_LABELLEN)
++		return;
++
++	isp = dentry->d_inode->i_security;
++
++	/*
++	 * No locking is done here. This is a pointer
++	 * assignment.
++	 */
++	nsp = smk_import(value, size);
++	if (nsp != NULL)
++		isp->smk_inode = nsp;
++	else
++		isp->smk_inode = smack_known_invalid.smk_known;
++
++	return;
++}
++
++/*
++ * smack_inode_getxattr - Smack check on getxattr
++ * @dentry: the object
++ * @name: unused
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_getxattr(struct dentry *dentry, char *name)
++{
++	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
++}
++
++/*
++ * smack_inode_removexattr - Smack check on removexattr
++ * @dentry: the object
++ * @name: name of the attribute
++ *
++ * Removing the Smack attribute requires CAP_MAC_ADMIN
++ *
++ * Returns 0 if access is permitted, an error code otherwise
++ */
++static int smack_inode_removexattr(struct dentry *dentry, char *name)
++{
++	if (strcmp(name, XATTR_NAME_SMACK) == 0 && !capable(CAP_MAC_ADMIN))
++		return -EPERM;
++
++	return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
++}
++
++/**
++ * smack_inode_getsecurity - get smack xattrs
++ * @inode: the object
++ * @name: attribute name
++ * @buffer: where to put the result
++ * @size: size of the buffer
++ * @err: unused
++ *
++ * Returns the size of the attribute or an error code
++ */
++static int smack_inode_getsecurity(const struct inode *inode,
++				   const char *name, void **buffer,
++				   bool alloc)
++{
++	struct socket_smack *ssp;
++	struct socket *sock;
++	struct super_block *sbp;
++	struct inode *ip = (struct inode *)inode;
++	char *isp;
++	int ilen;
++	int rc = 0;
++
++	if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
++		isp = smk_of_inode(inode);
++		ilen = strlen(isp) + 1;
++		*buffer = isp;
++		return ilen;
++	}
++
++	/*
++	 * The rest of the Smack xattrs are only on sockets.
++	 */
++	sbp = ip->i_sb;
++	if (sbp->s_magic != SOCKFS_MAGIC)
++		return -EOPNOTSUPP;
++
++	sock = SOCKET_I(ip);
++	if (sock == NULL)
++		return -EOPNOTSUPP;
++
++	ssp = sock->sk->sk_security;
++
++	if (strcmp(name, XATTR_SMACK_IPIN) == 0)
++		isp = ssp->smk_in;
++	else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
++		isp = ssp->smk_out;
++	else
++		return -EOPNOTSUPP;
++
++	ilen = strlen(isp) + 1;
++	if (rc == 0) {
++		*buffer = isp;
++		rc = ilen;
++	}
++
++	return rc;
++}
++
++
++/**
++ * smack_inode_listsecurity - list the Smack attributes
++ * @inode: the object
++ * @buffer: where they go
++ * @buffer_size: size of buffer
++ *
++ * Returns 0 on success, -EINVAL otherwise
++ */
++static int smack_inode_listsecurity(struct inode *inode, char *buffer,
++				    size_t buffer_size)
++{
++	int len = strlen(XATTR_NAME_SMACK);
++
++	if (buffer != NULL && len <= buffer_size) {
++		memcpy(buffer, XATTR_NAME_SMACK, len);
++		return len;
++	}
++	return -EINVAL;
++}
++
++/*
++ * File Hooks
++ */
++
++/**
++ * smack_file_permission - Smack check on file operations
++ * @file: unused
++ * @mask: unused
++ *
++ * Returns 0
++ *
++ * Should access checks be done on each read or write?
++ * UNICOS and SELinux say yes.
++ * Trusted Solaris, Trusted Irix, and just about everyone else says no.
++ *
++ * I'll say no for now. Smack does not do the frequent
++ * label changing that SELinux does.
++ */
++static int smack_file_permission(struct file *file, int mask)
++{
++	return 0;
++}
++
++/**
++ * smack_file_alloc_security - assign a file security blob
++ * @file: the object
++ *
++ * The security blob for a file is a pointer to the master
++ * label list, so no allocation is done.
++ *
++ * Returns 0
++ */
++static int smack_file_alloc_security(struct file *file)
++{
++	file->f_security = current->security;
++	return 0;
++}
++
++/**
++ * smack_file_free_security - clear a file security blob
++ * @file: the object
++ *
++ * The security blob for a file is a pointer to the master
++ * label list, so no memory is freed.
++ */
++static void smack_file_free_security(struct file *file)
++{
++	file->f_security = NULL;
++}
++
++/**
++ * smack_file_ioctl - Smack check on ioctls
++ * @file: the object
++ * @cmd: what to do
++ * @arg: unused
++ *
++ * Relies heavily on the correct use of the ioctl command conventions.
++ *
++ * Returns 0 if allowed, error code otherwise
++ */
++static int smack_file_ioctl(struct file *file, unsigned int cmd,
++			    unsigned long arg)
++{
++	int rc = 0;
++
++	if (_IOC_DIR(cmd) & _IOC_WRITE)
++		rc = smk_curacc(file->f_security, MAY_WRITE);
++
++	if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
++		rc = smk_curacc(file->f_security, MAY_READ);
++
++	return rc;
++}
++
++/**
++ * smack_file_lock - Smack check on file locking
++ * @file: the object
++ * @cmd unused
++ *
++ * Returns 0 if current has write access, error code otherwise
++ */
++static int smack_file_lock(struct file *file, unsigned int cmd)
++{
++	return smk_curacc(file->f_security, MAY_WRITE);
++}
++
++/**
++ * smack_file_fcntl - Smack check on fcntl
++ * @file: the object
++ * @cmd: what action to check
++ * @arg: unused
++ *
++ * Returns 0 if current has access, error code otherwise
++ */
++static int smack_file_fcntl(struct file *file, unsigned int cmd,
++			    unsigned long arg)
++{
++	int rc;
++
++	switch (cmd) {
++	case F_DUPFD:
++	case F_GETFD:
++	case F_GETFL:
++	case F_GETLK:
++	case F_GETOWN:
++	case F_GETSIG:
++		rc = smk_curacc(file->f_security, MAY_READ);
++		break;
++	case F_SETFD:
++	case F_SETFL:
++	case F_SETLK:
++	case F_SETLKW:
++	case F_SETOWN:
++	case F_SETSIG:
++		rc = smk_curacc(file->f_security, MAY_WRITE);
++		break;
++	default:
++		rc = smk_curacc(file->f_security, MAY_READWRITE);
++	}
++
++	return rc;
++}
++
++/**
++ * smack_file_set_fowner - set the file security blob value
++ * @file: object in question
++ *
++ * Returns 0
++ * Further research may be required on this one.
++ */
++static int smack_file_set_fowner(struct file *file)
++{
++	file->f_security = current->security;
++	return 0;
++}
++
++/**
++ * smack_file_send_sigiotask - Smack on sigio
++ * @tsk: The target task
++ * @fown: the object the signal come from
++ * @signum: unused
++ *
++ * Allow a privileged task to get signals even if it shouldn't
++ *
++ * Returns 0 if a subject with the object's smack could
++ * write to the task, an error code otherwise.
++ */
++static int smack_file_send_sigiotask(struct task_struct *tsk,
++				     struct fown_struct *fown, int signum)
++{
++	struct file *file;
++	int rc;
++
++	/*
++	 * struct fown_struct is never outside the context of a struct file
++	 */
++	file = container_of(fown, struct file, f_owner);
++	rc = smk_access(file->f_security, tsk->security, MAY_WRITE);
++	if (rc != 0 && __capable(tsk, CAP_MAC_OVERRIDE))
++		return 0;
++	return rc;
++}
++
++/**
++ * smack_file_receive - Smack file receive check
++ * @file: the object
++ *
++ * Returns 0 if current has access, error code otherwise
++ */
++static int smack_file_receive(struct file *file)
++{
++	int may = 0;
++
++	/*
++	 * This code relies on bitmasks.
++	 */
++	if (file->f_mode & FMODE_READ)
++		may = MAY_READ;
++	if (file->f_mode & FMODE_WRITE)
++		may |= MAY_WRITE;
++
++	return smk_curacc(file->f_security, may);
++}
++
++/*
++ * Task hooks
++ */
++
++/**
++ * smack_task_alloc_security - "allocate" a task blob
++ * @tsk: the task in need of a blob
++ *
++ * Smack isn't using copies of blobs. Everyone
++ * points to an immutable list. No alloc required.
++ * No data copy required.
++ *
++ * Always returns 0
++ */
++static int smack_task_alloc_security(struct task_struct *tsk)
++{
++	tsk->security = current->security;
++
++	return 0;
++}
++
++/**
++ * smack_task_free_security - "free" a task blob
++ * @task: the task with the blob
++ *
++ * Smack isn't using copies of blobs. Everyone
++ * points to an immutable list. The blobs never go away.
++ * There is no leak here.
++ */
++static void smack_task_free_security(struct task_struct *task)
++{
++	task->security = NULL;
++}
++
++/**
++ * smack_task_setpgid - Smack check on setting pgid
++ * @p: the task object
++ * @pgid: unused
++ *
++ * Return 0 if write access is permitted
++ */
++static int smack_task_setpgid(struct task_struct *p, pid_t pgid)
++{
++	return smk_curacc(p->security, MAY_WRITE);
++}
++
++/**
++ * smack_task_getpgid - Smack access check for getpgid
++ * @p: the object task
++ *
++ * Returns 0 if current can read the object task, error code otherwise
++ */
++static int smack_task_getpgid(struct task_struct *p)
++{
++	return smk_curacc(p->security, MAY_READ);
++}
++
++/**
++ * smack_task_getsid - Smack access check for getsid
++ * @p: the object task
++ *
++ * Returns 0 if current can read the object task, error code otherwise
++ */
++static int smack_task_getsid(struct task_struct *p)
++{
++	return smk_curacc(p->security, MAY_READ);
++}
++
++/**
++ * smack_task_getsecid - get the secid of the task
++ * @p: the object task
++ * @secid: where to put the result
++ *
++ * Sets the secid to contain a u32 version of the smack label.
++ */
++static void smack_task_getsecid(struct task_struct *p, u32 *secid)
++{
++	*secid = smack_to_secid(p->security);
++}
++
++/**
++ * smack_task_setnice - Smack check on setting nice
++ * @p: the task object
++ * @nice: unused
++ *
++ * Return 0 if write access is permitted
++ */
++static int smack_task_setnice(struct task_struct *p, int nice)
++{
++	return smk_curacc(p->security, MAY_WRITE);
++}
++
++/**
++ * smack_task_setioprio - Smack check on setting ioprio
++ * @p: the task object
++ * @ioprio: unused
++ *
++ * Return 0 if write access is permitted
++ */
++static int smack_task_setioprio(struct task_struct *p, int ioprio)
++{
++	return smk_curacc(p->security, MAY_WRITE);
++}
++
++/**
++ * smack_task_getioprio - Smack check on reading ioprio
++ * @p: the task object
++ *
++ * Return 0 if read access is permitted
++ */
++static int smack_task_getioprio(struct task_struct *p)
++{
++	return smk_curacc(p->security, MAY_READ);
++}
++
++/**
++ * smack_task_setscheduler - Smack check on setting scheduler
++ * @p: the task object
++ * @policy: unused
++ * @lp: unused
++ *
++ * Return 0 if read access is permitted
++ */
++static int smack_task_setscheduler(struct task_struct *p, int policy,
++				   struct sched_param *lp)
++{
++	return smk_curacc(p->security, MAY_WRITE);
++}
++
++/**
++ * smack_task_getscheduler - Smack check on reading scheduler
++ * @p: the task object
++ *
++ * Return 0 if read access is permitted
++ */
++static int smack_task_getscheduler(struct task_struct *p)
++{
++	return smk_curacc(p->security, MAY_READ);
++}
++
++/**
++ * smack_task_movememory - Smack check on moving memory
++ * @p: the task object
++ *
++ * Return 0 if write access is permitted
++ */
++static int smack_task_movememory(struct task_struct *p)
++{
++	return smk_curacc(p->security, MAY_WRITE);
++}
++
++/**
++ * smack_task_kill - Smack check on signal delivery
++ * @p: the task object
++ * @info: unused
++ * @sig: unused
++ * @secid: identifies the smack to use in lieu of current's
++ *
++ * Return 0 if write access is permitted
++ *
++ * The secid behavior is an artifact of an SELinux hack
++ * in the USB code. Someday it may go away.
++ */
++static int smack_task_kill(struct task_struct *p, struct siginfo *info,
++			   int sig, u32 secid)
++{
++	/*
++	 * Special cases where signals really ought to go through
++	 * in spite of policy. Stephen Smalley suggests it may
++	 * make sense to change the caller so that it doesn't
++	 * bother with the LSM hook in these cases.
++	 */
++	if (info != SEND_SIG_NOINFO &&
++	    (is_si_special(info) || SI_FROMKERNEL(info)))
++		return 0;
++	/*
++	 * Sending a signal requires that the sender
++	 * can write the receiver.
++	 */
++	if (secid == 0)
++		return smk_curacc(p->security, MAY_WRITE);
++	/*
++	 * If the secid isn't 0 we're dealing with some USB IO
++	 * specific behavior. This is not clean. For one thing
++	 * we can't take privilege into account.
++	 */
++	return smk_access(smack_from_secid(secid), p->security, MAY_WRITE);
++}
++
++/**
++ * smack_task_wait - Smack access check for waiting
++ * @p: task to wait for
++ *
++ * Returns 0 if current can wait for p, error code otherwise
++ */
++static int smack_task_wait(struct task_struct *p)
++{
++	int rc;
++
++	rc = smk_access(current->security, p->security, MAY_WRITE);
++	if (rc == 0)
++		return 0;
++
++	/*
++	 * Allow the operation to succeed if either task
++	 * has privilege to perform operations that might
++	 * account for the smack labels having gotten to
++	 * be different in the first place.
++	 *
++	 * This breaks the strict subjet/object access
++	 * control ideal, taking the object's privilege
++	 * state into account in the decision as well as
++	 * the smack value.
++	 */
++	if (capable(CAP_MAC_OVERRIDE) || __capable(p, CAP_MAC_OVERRIDE))
++		return 0;
++
++	return rc;
++}
++
++/**
++ * smack_task_to_inode - copy task smack into the inode blob
++ * @p: task to copy from
++ * inode: inode to copy to
++ *
++ * Sets the smack pointer in the inode security blob
++ */
++static void smack_task_to_inode(struct task_struct *p, struct inode *inode)
++{
++	struct inode_smack *isp = inode->i_security;
++	isp->smk_inode = p->security;
++}
++
++/*
++ * Socket hooks.
++ */
++
++/**
++ * smack_sk_alloc_security - Allocate a socket blob
++ * @sk: the socket
++ * @family: unused
++ * @priority: memory allocation priority
++ *
++ * Assign Smack pointers to current
++ *
++ * Returns 0 on success, -ENOMEM is there's no memory
++ */
++static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
++{
++	char *csp = current->security;
++	struct socket_smack *ssp;
++
++	ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
++	if (ssp == NULL)
++		return -ENOMEM;
++
++	ssp->smk_in = csp;
++	ssp->smk_out = csp;
++	ssp->smk_packet[0] = '\0';
++
++	sk->sk_security = ssp;
++
++	return 0;
++}
++
++/**
++ * smack_sk_free_security - Free a socket blob
++ * @sk: the socket
++ *
++ * Clears the blob pointer
++ */
++static void smack_sk_free_security(struct sock *sk)
++{
++	kfree(sk->sk_security);
++}
++
++/**
++ * smack_set_catset - convert a capset to netlabel mls categories
++ * @catset: the Smack categories
++ * @sap: where to put the netlabel categories
++ *
++ * Allocates and fills attr.mls.cat
++ */
++static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap)
++{
++	unsigned char *cp;
++	unsigned char m;
++	int cat;
++	int rc;
++	int byte;
++
++	if (catset == 0)
++		return;
++
++	sap->flags |= NETLBL_SECATTR_MLS_CAT;
++	sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
++	sap->attr.mls.cat->startbit = 0;
++
++	for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++)
++		for (m = 0x80; m != 0; m >>= 1, cat++) {
++			if ((m & *cp) == 0)
++				continue;
++			rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat,
++							  cat, GFP_ATOMIC);
++		}
++}
++
++/**
++ * smack_to_secattr - fill a secattr from a smack value
++ * @smack: the smack value
++ * @nlsp: where the result goes
++ *
++ * Casey says that CIPSO is good enough for now.
++ * It can be used to effect.
++ * It can also be abused to effect when necessary.
++ * Appologies to the TSIG group in general and GW in particular.
++ */
++static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
++{
++	struct smack_cipso cipso;
++	int rc;
++
++	switch (smack_net_nltype) {
++	case NETLBL_NLTYPE_CIPSOV4:
++		nlsp->domain = NULL;
++		nlsp->flags = NETLBL_SECATTR_DOMAIN;
++		nlsp->flags |= NETLBL_SECATTR_MLS_LVL;
++
++		rc = smack_to_cipso(smack, &cipso);
++		if (rc == 0) {
++			nlsp->attr.mls.lvl = cipso.smk_level;
++			smack_set_catset(cipso.smk_catset, nlsp);
++		} else {
++			nlsp->attr.mls.lvl = smack_cipso_direct;
++			smack_set_catset(smack, nlsp);
++		}
++		break;
++	default:
++		break;
++	}
++}
++
++/**
++ * smack_netlabel - Set the secattr on a socket
++ * @sk: the socket
++ *
++ * Convert the outbound smack value (smk_out) to a
++ * secattr and attach it to the socket.
++ *
++ * Returns 0 on success or an error code
++ */
++static int smack_netlabel(struct sock *sk)
++{
++	struct socket_smack *ssp = sk->sk_security;
++	struct netlbl_lsm_secattr secattr;
++	int rc = 0;
++
++	netlbl_secattr_init(&secattr);
++	smack_to_secattr(ssp->smk_out, &secattr);
++	if (secattr.flags != NETLBL_SECATTR_NONE)
++		rc = netlbl_sock_setattr(sk, &secattr);
++
++	netlbl_secattr_destroy(&secattr);
++	return rc;
++}
++
++/**
++ * smack_inode_setsecurity - set smack xattrs
++ * @inode: the object
++ * @name: attribute name
++ * @value: attribute value
++ * @size: size of the attribute
++ * @flags: unused
++ *
++ * Sets the named attribute in the appropriate blob
++ *
++ * Returns 0 on success, or an error code
++ */
++static int smack_inode_setsecurity(struct inode *inode, const char *name,
++				   const void *value, size_t size, int flags)
++{
++	char *sp;
++	struct inode_smack *nsp = inode->i_security;
++	struct socket_smack *ssp;
++	struct socket *sock;
++
++	if (value == NULL || size > SMK_LABELLEN)
++		return -EACCES;
++
++	sp = smk_import(value, size);
++	if (sp == NULL)
++		return -EINVAL;
++
++	if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) {
++		nsp->smk_inode = sp;
++		return 0;
++	}
++	/*
++	 * The rest of the Smack xattrs are only on sockets.
++	 */
++	if (inode->i_sb->s_magic != SOCKFS_MAGIC)
++		return -EOPNOTSUPP;
++
++	sock = SOCKET_I(inode);
++	if (sock == NULL)
++		return -EOPNOTSUPP;
++
++	ssp = sock->sk->sk_security;
++
++	if (strcmp(name, XATTR_SMACK_IPIN) == 0)
++		ssp->smk_in = sp;
++	else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
++		ssp->smk_out = sp;
++		return smack_netlabel(sock->sk);
++	} else
++		return -EOPNOTSUPP;
++
++	return 0;
++}
++
++/**
++ * smack_socket_post_create - finish socket setup
++ * @sock: the socket
++ * @family: protocol family
++ * @type: unused
++ * @protocol: unused
++ * @kern: unused
++ *
++ * Sets the netlabel information on the socket
++ *
++ * Returns 0 on success, and error code otherwise
++ */
++static int smack_socket_post_create(struct socket *sock, int family,
++				    int type, int protocol, int kern)
++{
++	if (family != PF_INET)
++		return 0;
++	/*
++	 * Set the outbound netlbl.
++	 */
++	return smack_netlabel(sock->sk);
++}
++
++/**
++ * smack_flags_to_may - convert S_ to MAY_ values
++ * @flags: the S_ value
++ *
++ * Returns the equivalent MAY_ value
++ */
++static int smack_flags_to_may(int flags)
++{
++	int may = 0;
++
++	if (flags & S_IRUGO)
++		may |= MAY_READ;
++	if (flags & S_IWUGO)
++		may |= MAY_WRITE;
++	if (flags & S_IXUGO)
++		may |= MAY_EXEC;
++
++	return may;
++}
++
++/**
++ * smack_msg_msg_alloc_security - Set the security blob for msg_msg
++ * @msg: the object
++ *
++ * Returns 0
++ */
++static int smack_msg_msg_alloc_security(struct msg_msg *msg)
++{
++	msg->security = current->security;
++	return 0;
++}
++
++/**
++ * smack_msg_msg_free_security - Clear the security blob for msg_msg
++ * @msg: the object
++ *
++ * Clears the blob pointer
++ */
++static void smack_msg_msg_free_security(struct msg_msg *msg)
++{
++	msg->security = NULL;
++}
++
++/**
++ * smack_of_shm - the smack pointer for the shm
++ * @shp: the object
++ *
++ * Returns a pointer to the smack value
++ */
++static char *smack_of_shm(struct shmid_kernel *shp)
++{
++	return (char *)shp->shm_perm.security;
++}
++
++/**
++ * smack_shm_alloc_security - Set the security blob for shm
++ * @shp: the object
++ *
++ * Returns 0
++ */
++static int smack_shm_alloc_security(struct shmid_kernel *shp)
++{
++	struct kern_ipc_perm *isp = &shp->shm_perm;
++
++	isp->security = current->security;
++	return 0;
++}
++
++/**
++ * smack_shm_free_security - Clear the security blob for shm
++ * @shp: the object
++ *
++ * Clears the blob pointer
++ */
++static void smack_shm_free_security(struct shmid_kernel *shp)
++{
++	struct kern_ipc_perm *isp = &shp->shm_perm;
++
++	isp->security = NULL;
++}
++
++/**
++ * smack_shm_associate - Smack access check for shm
++ * @shp: the object
++ * @shmflg: access requested
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_shm_associate(struct shmid_kernel *shp, int shmflg)
++{
++	char *ssp = smack_of_shm(shp);
++	int may;
++
++	may = smack_flags_to_may(shmflg);
++	return smk_curacc(ssp, may);
++}
++
++/**
++ * smack_shm_shmctl - Smack access check for shm
++ * @shp: the object
++ * @cmd: what it wants to do
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_shm_shmctl(struct shmid_kernel *shp, int cmd)
++{
++	char *ssp = smack_of_shm(shp);
++	int may;
++
++	switch (cmd) {
++	case IPC_STAT:
++	case SHM_STAT:
++		may = MAY_READ;
++		break;
++	case IPC_SET:
++	case SHM_LOCK:
++	case SHM_UNLOCK:
++	case IPC_RMID:
++		may = MAY_READWRITE;
++		break;
++	case IPC_INFO:
++	case SHM_INFO:
++		/*
++		 * System level information.
++		 */
++		return 0;
++	default:
++		return -EINVAL;
++	}
++
++	return smk_curacc(ssp, may);
++}
++
++/**
++ * smack_shm_shmat - Smack access for shmat
++ * @shp: the object
++ * @shmaddr: unused
++ * @shmflg: access requested
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_shm_shmat(struct shmid_kernel *shp, char __user *shmaddr,
++			   int shmflg)
++{
++	char *ssp = smack_of_shm(shp);
++	int may;
++
++	may = smack_flags_to_may(shmflg);
++	return smk_curacc(ssp, may);
++}
++
++/**
++ * smack_of_sem - the smack pointer for the sem
++ * @sma: the object
++ *
++ * Returns a pointer to the smack value
++ */
++static char *smack_of_sem(struct sem_array *sma)
++{
++	return (char *)sma->sem_perm.security;
++}
++
++/**
++ * smack_sem_alloc_security - Set the security blob for sem
++ * @sma: the object
++ *
++ * Returns 0
++ */
++static int smack_sem_alloc_security(struct sem_array *sma)
++{
++	struct kern_ipc_perm *isp = &sma->sem_perm;
++
++	isp->security = current->security;
++	return 0;
++}
++
++/**
++ * smack_sem_free_security - Clear the security blob for sem
++ * @sma: the object
++ *
++ * Clears the blob pointer
++ */
++static void smack_sem_free_security(struct sem_array *sma)
++{
++	struct kern_ipc_perm *isp = &sma->sem_perm;
++
++	isp->security = NULL;
++}
++
++/**
++ * smack_sem_associate - Smack access check for sem
++ * @sma: the object
++ * @semflg: access requested
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_sem_associate(struct sem_array *sma, int semflg)
++{
++	char *ssp = smack_of_sem(sma);
++	int may;
++
++	may = smack_flags_to_may(semflg);
++	return smk_curacc(ssp, may);
++}
++
++/**
++ * smack_sem_shmctl - Smack access check for sem
++ * @sma: the object
++ * @cmd: what it wants to do
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_sem_semctl(struct sem_array *sma, int cmd)
++{
++	char *ssp = smack_of_sem(sma);
++	int may;
++
++	switch (cmd) {
++	case GETPID:
++	case GETNCNT:
++	case GETZCNT:
++	case GETVAL:
++	case GETALL:
++	case IPC_STAT:
++	case SEM_STAT:
++		may = MAY_READ;
++		break;
++	case SETVAL:
++	case SETALL:
++	case IPC_RMID:
++	case IPC_SET:
++		may = MAY_READWRITE;
++		break;
++	case IPC_INFO:
++	case SEM_INFO:
++		/*
++		 * System level information
++		 */
++		return 0;
++	default:
++		return -EINVAL;
++	}
++
++	return smk_curacc(ssp, may);
++}
++
++/**
++ * smack_sem_semop - Smack checks of semaphore operations
++ * @sma: the object
++ * @sops: unused
++ * @nsops: unused
++ * @alter: unused
++ *
++ * Treated as read and write in all cases.
++ *
++ * Returns 0 if access is allowed, error code otherwise
++ */
++static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops,
++			   unsigned nsops, int alter)
++{
++	char *ssp = smack_of_sem(sma);
++
++	return smk_curacc(ssp, MAY_READWRITE);
++}
++
++/**
++ * smack_msg_alloc_security - Set the security blob for msg
++ * @msq: the object
++ *
++ * Returns 0
++ */
++static int smack_msg_queue_alloc_security(struct msg_queue *msq)
++{
++	struct kern_ipc_perm *kisp = &msq->q_perm;
++
++	kisp->security = current->security;
++	return 0;
++}
++
++/**
++ * smack_msg_free_security - Clear the security blob for msg
++ * @msq: the object
++ *
++ * Clears the blob pointer
++ */
++static void smack_msg_queue_free_security(struct msg_queue *msq)
++{
++	struct kern_ipc_perm *kisp = &msq->q_perm;
++
++	kisp->security = NULL;
++}
++
++/**
++ * smack_of_msq - the smack pointer for the msq
++ * @msq: the object
++ *
++ * Returns a pointer to the smack value
++ */
++static char *smack_of_msq(struct msg_queue *msq)
++{
++	return (char *)msq->q_perm.security;
++}
++
++/**
++ * smack_msg_queue_associate - Smack access check for msg_queue
++ * @msq: the object
++ * @msqflg: access requested
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_msg_queue_associate(struct msg_queue *msq, int msqflg)
++{
++	char *msp = smack_of_msq(msq);
++	int may;
++
++	may = smack_flags_to_may(msqflg);
++	return smk_curacc(msp, may);
++}
++
++/**
++ * smack_msg_queue_msgctl - Smack access check for msg_queue
++ * @msq: the object
++ * @cmd: what it wants to do
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_msg_queue_msgctl(struct msg_queue *msq, int cmd)
++{
++	char *msp = smack_of_msq(msq);
++	int may;
++
++	switch (cmd) {
++	case IPC_STAT:
++	case MSG_STAT:
++		may = MAY_READ;
++		break;
++	case IPC_SET:
++	case IPC_RMID:
++		may = MAY_READWRITE;
++		break;
++	case IPC_INFO:
++	case MSG_INFO:
++		/*
++		 * System level information
++		 */
++		return 0;
++	default:
++		return -EINVAL;
++	}
++
++	return smk_curacc(msp, may);
++}
++
++/**
++ * smack_msg_queue_msgsnd - Smack access check for msg_queue
++ * @msq: the object
++ * @msg: unused
++ * @msqflg: access requested
++ *
++ * Returns 0 if current has the requested access, error code otherwise
++ */
++static int smack_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg,
++				  int msqflg)
++{
++	char *msp = smack_of_msq(msq);
++	int rc;
++
++	rc = smack_flags_to_may(msqflg);
++	return smk_curacc(msp, rc);
++}
++
++/**
++ * smack_msg_queue_msgsnd - Smack access check for msg_queue
++ * @msq: the object
++ * @msg: unused
++ * @target: unused
++ * @type: unused
++ * @mode: unused
++ *
++ * Returns 0 if current has read and write access, error code otherwise
++ */
++static int smack_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
++			struct task_struct *target, long type, int mode)
++{
++	char *msp = smack_of_msq(msq);
++
++	return smk_curacc(msp, MAY_READWRITE);
++}
++
++/**
++ * smack_ipc_permission - Smack access for ipc_permission()
++ * @ipp: the object permissions
++ * @flag: access requested
++ *
++ * Returns 0 if current has read and write access, error code otherwise
++ */
++static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
++{
++	char *isp = ipp->security;
++	int may;
++
++	may = smack_flags_to_may(flag);
++	return smk_curacc(isp, may);
++}
++
++/**
++ * smack_d_instantiate - Make sure the blob is correct on an inode
++ * @opt_dentry: unused
++ * @inode: the object
++ *
++ * Set the inode's security blob if it hasn't been done already.
++ */
++static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
++{
++	struct super_block *sbp;
++	struct superblock_smack *sbsp;
++	struct inode_smack *isp;
++	char *csp = current->security;
++	char *fetched;
++	char *final;
++	struct dentry *dp;
++
++	if (inode == NULL)
++		return;
++
++	isp = inode->i_security;
++
++	mutex_lock(&isp->smk_lock);
++	/*
++	 * If the inode is already instantiated
++	 * take the quick way out
++	 */
++	if (isp->smk_flags & SMK_INODE_INSTANT)
++		goto unlockandout;
++
++	sbp = inode->i_sb;
++	sbsp = sbp->s_security;
++	/*
++	 * We're going to use the superblock default label
++	 * if there's no label on the file.
++	 */
++	final = sbsp->smk_default;
++
++	/*
++	 * This is pretty hackish.
++	 * Casey says that we shouldn't have to do
++	 * file system specific code, but it does help
++	 * with keeping it simple.
++	 */
++	switch (sbp->s_magic) {
++	case SMACK_MAGIC:
++		/*
++		 * Casey says that it's a little embarassing
++		 * that the smack file system doesn't do
++		 * extended attributes.
++		 */
++		final = smack_known_star.smk_known;
++		break;
++	case PIPEFS_MAGIC:
++		/*
++		 * Casey says pipes are easy (?)
++		 */
++		final = smack_known_star.smk_known;
++		break;
++	case DEVPTS_SUPER_MAGIC:
++		/*
++		 * devpts seems content with the label of the task.
++		 * Programs that change smack have to treat the
++		 * pty with respect.
++		 */
++		final = csp;
++		break;
++	case SOCKFS_MAGIC:
++		/*
++		 * Casey says sockets get the smack of the task.
++		 */
++		final = csp;
++		break;
++	case PROC_SUPER_MAGIC:
++		/*
++		 * Casey says procfs appears not to care.
++		 * The superblock default suffices.
++		 */
++		break;
++	case TMPFS_MAGIC:
++		/*
++		 * Device labels should come from the filesystem,
++		 * but watch out, because they're volitile,
++		 * getting recreated on every reboot.
++		 */
++		final = smack_known_star.smk_known;
++		/*
++		 * No break.
++		 *
++		 * If a smack value has been set we want to use it,
++		 * but since tmpfs isn't giving us the opportunity
++		 * to set mount options simulate setting the
++		 * superblock default.
++		 */
++	default:
++		/*
++		 * This isn't an understood special case.
++		 * Get the value from the xattr.
++		 *
++		 * No xattr support means, alas, no SMACK label.
++		 * Use the aforeapplied default.
++		 * It would be curious if the label of the task
++		 * does not match that assigned.
++		 */
++		if (inode->i_op->getxattr == NULL)
++			break;
++		/*
++		 * Get the dentry for xattr.
++		 */
++		if (opt_dentry == NULL) {
++			dp = d_find_alias(inode);
++			if (dp == NULL)
++				break;
++		} else {
++			dp = dget(opt_dentry);
++			if (dp == NULL)
++				break;
++		}
++
++		fetched = smk_fetch(inode, dp);
++		if (fetched != NULL)
++			final = fetched;
++
++		dput(dp);
++		break;
++	}
++
++	if (final == NULL)
++		isp->smk_inode = csp;
++	else
++		isp->smk_inode = final;
++
++	isp->smk_flags |= SMK_INODE_INSTANT;
++
++unlockandout:
++	mutex_unlock(&isp->smk_lock);
++	return;
++}
++
++/**
++ * smack_getprocattr - Smack process attribute access
++ * @p: the object task
++ * @name: the name of the attribute in /proc/.../attr
++ * @value: where to put the result
++ *
++ * Places a copy of the task Smack into value
++ *
++ * Returns the length of the smack label or an error code
++ */
++static int smack_getprocattr(struct task_struct *p, char *name, char **value)
++{
++	char *cp;
++	int slen;
++
++	if (strcmp(name, "current") != 0)
++		return -EINVAL;
++
++	cp = kstrdup(p->security, GFP_KERNEL);
++	if (cp == NULL)
++		return -ENOMEM;
++
++	slen = strlen(cp);
++	*value = cp;
++	return slen;
++}
++
++/**
++ * smack_setprocattr - Smack process attribute setting
++ * @p: the object task
++ * @name: the name of the attribute in /proc/.../attr
++ * @value: the value to set
++ * @size: the size of the value
++ *
++ * Sets the Smack value of the task. Only setting self
++ * is permitted and only with privilege
++ *
++ * Returns the length of the smack label or an error code
++ */
++static int smack_setprocattr(struct task_struct *p, char *name,
++			     void *value, size_t size)
++{
++	char *newsmack;
++
++	if (!__capable(p, CAP_MAC_ADMIN))
++		return -EPERM;
++
++	/*
++	 * Changing another process' Smack value is too dangerous
++	 * and supports no sane use case.
++	 */
++	if (p != current)
++		return -EPERM;
++
++	if (value == NULL || size == 0 || size >= SMK_LABELLEN)
++		return -EINVAL;
++
++	if (strcmp(name, "current") != 0)
++		return -EINVAL;
++
++	newsmack = smk_import(value, size);
++	if (newsmack == NULL)
++		return -EINVAL;
++
++	p->security = newsmack;
++	return size;
++}
++
++/**
++ * smack_unix_stream_connect - Smack access on UDS
++ * @sock: one socket
++ * @other: the other socket
++ * @newsk: unused
++ *
++ * Return 0 if a subject with the smack of sock could access
++ * an object with the smack of other, otherwise an error code
++ */
++static int smack_unix_stream_connect(struct socket *sock,
++				     struct socket *other, struct sock *newsk)
++{
++	struct inode *sp = SOCK_INODE(sock);
++	struct inode *op = SOCK_INODE(other);
++
++	return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_READWRITE);
++}
++
++/**
++ * smack_unix_may_send - Smack access on UDS
++ * @sock: one socket
++ * @other: the other socket
++ *
++ * Return 0 if a subject with the smack of sock could access
++ * an object with the smack of other, otherwise an error code
++ */
++static int smack_unix_may_send(struct socket *sock, struct socket *other)
++{
++	struct inode *sp = SOCK_INODE(sock);
++	struct inode *op = SOCK_INODE(other);
++
++	return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE);
++}
++
++/**
++ * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat
++ * 	pair to smack
++ * @sap: netlabel secattr
++ * @sip: where to put the result
++ *
++ * Copies a smack label into sip
++ */
++static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip)
++{
++	char smack[SMK_LABELLEN];
++	int pcat;
++
++	if ((sap->flags & NETLBL_SECATTR_MLS_LVL) == 0) {
++		/*
++		 * If there are flags but no level netlabel isn't
++		 * behaving the way we expect it to.
++		 *
++		 * Without guidance regarding the smack value
++		 * for the packet fall back on the network
++		 * ambient value.
++		 */
++		strncpy(sip, smack_net_ambient, SMK_MAXLEN);
++		return;
++	}
++	/*
++	 * Get the categories, if any
++	 */
++	memset(smack, '\0', SMK_LABELLEN);
++	if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0)
++		for (pcat = -1;;) {
++			pcat = netlbl_secattr_catmap_walk(sap->attr.mls.cat,
++							  pcat + 1);
++			if (pcat < 0)
++				break;
++			smack_catset_bit(pcat, smack);
++		}
++	/*
++	 * If it is CIPSO using smack direct mapping
++	 * we are already done. WeeHee.
++	 */
++	if (sap->attr.mls.lvl == smack_cipso_direct) {
++		memcpy(sip, smack, SMK_MAXLEN);
++		return;
++	}
++	/*
++	 * Look it up in the supplied table if it is not a direct mapping.
++	 */
++	smack_from_cipso(sap->attr.mls.lvl, smack, sip);
++	return;
++}
++
++/**
++ * smack_socket_sock_rcv_skb - Smack packet delivery access check
++ * @sk: socket
++ * @skb: packet
++ *
++ * Returns 0 if the packet should be delivered, an error code otherwise
++ */
++static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
++{
++	struct netlbl_lsm_secattr secattr;
++	struct socket_smack *ssp = sk->sk_security;
++	char smack[SMK_LABELLEN];
++	int rc;
++
++	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
++		return 0;
++
++	/*
++	 * Translate what netlabel gave us.
++	 */
++	memset(smack, '\0', SMK_LABELLEN);
++	netlbl_secattr_init(&secattr);
++	rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr);
++	if (rc == 0)
++		smack_from_secattr(&secattr, smack);
++	else
++		strncpy(smack, smack_net_ambient, SMK_MAXLEN);
++	netlbl_secattr_destroy(&secattr);
++	/*
++	 * Receiving a packet requires that the other end
++	 * be able to write here. Read access is not required.
++	 * This is the simplist possible security model
++	 * for networking.
++	 */
++	return smk_access(smack, ssp->smk_in, MAY_WRITE);
++}
++
++/**
++ * smack_socket_getpeersec_stream - pull in packet label
++ * @sock: the socket
++ * @optval: user's destination
++ * @optlen: size thereof
++ * @len: max thereoe
++ *
++ * returns zero on success, an error code otherwise
++ */
++static int smack_socket_getpeersec_stream(struct socket *sock,
++					  char __user *optval,
++					  int __user *optlen, unsigned len)
++{
++	struct socket_smack *ssp;
++	int slen;
++	int rc = 0;
++
++	ssp = sock->sk->sk_security;
++	slen = strlen(ssp->smk_packet) + 1;
++
++	if (slen > len)
++		rc = -ERANGE;
++	else if (copy_to_user(optval, ssp->smk_packet, slen) != 0)
++		rc = -EFAULT;
++
++	if (put_user(slen, optlen) != 0)
++		rc = -EFAULT;
++
++	return rc;
++}
++
++
++/**
++ * smack_socket_getpeersec_dgram - pull in packet label
++ * @sock: the socket
++ * @skb: packet data
++ * @secid: pointer to where to put the secid of the packet
++ *
++ * Sets the netlabel socket state on sk from parent
++ */
++static int smack_socket_getpeersec_dgram(struct socket *sock,
++					 struct sk_buff *skb, u32 *secid)
++
++{
++	struct netlbl_lsm_secattr secattr;
++	struct sock *sk;
++	char smack[SMK_LABELLEN];
++	int family = PF_INET;
++	u32 s;
++	int rc;
++
++	/*
++	 * Only works for families with packets.
++	 */
++	if (sock != NULL) {
++		sk = sock->sk;
++		if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
++			return 0;
++		family = sk->sk_family;
++	}
++	/*
++	 * Translate what netlabel gave us.
++	 */
++	memset(smack, '\0', SMK_LABELLEN);
++	netlbl_secattr_init(&secattr);
++	rc = netlbl_skbuff_getattr(skb, family, &secattr);
++	if (rc == 0)
++		smack_from_secattr(&secattr, smack);
++	netlbl_secattr_destroy(&secattr);
++
++	/*
++	 * Give up if we couldn't get anything
++	 */
++	if (rc != 0)
++		return rc;
++
++	s = smack_to_secid(smack);
++	if (s == 0)
++		return -EINVAL;
++
++	*secid = s;
++	return 0;
++}
++
++/**
++ * smack_sock_graft - graft access state between two sockets
++ * @sk: fresh sock
++ * @parent: donor socket
++ *
++ * Sets the netlabel socket state on sk from parent
++ */
++static void smack_sock_graft(struct sock *sk, struct socket *parent)
++{
++	struct socket_smack *ssp;
++	int rc;
++
++	if (sk == NULL)
++		return;
++
++	if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
++		return;
++
++	ssp = sk->sk_security;
++	ssp->smk_in = current->security;
++	ssp->smk_out = current->security;
++	ssp->smk_packet[0] = '\0';
++
++	rc = smack_netlabel(sk);
++}
++
++/**
++ * smack_inet_conn_request - Smack access check on connect
++ * @sk: socket involved
++ * @skb: packet
++ * @req: unused
++ *
++ * Returns 0 if a task with the packet label could write to
++ * the socket, otherwise an error code
++ */
++static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
++				   struct request_sock *req)
++{
++	struct netlbl_lsm_secattr skb_secattr;
++	struct socket_smack *ssp = sk->sk_security;
++	char smack[SMK_LABELLEN];
++	int rc;
++
++	if (skb == NULL)
++		return -EACCES;
++
++	memset(smack, '\0', SMK_LABELLEN);
++	netlbl_secattr_init(&skb_secattr);
++	rc = netlbl_skbuff_getattr(skb, sk->sk_family, &skb_secattr);
++	if (rc == 0)
++		smack_from_secattr(&skb_secattr, smack);
++	else
++		strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN);
++	netlbl_secattr_destroy(&skb_secattr);
++	/*
++	 * Receiving a packet requires that the other end
++	 * be able to write here. Read access is not required.
++	 *
++	 * If the request is successful save the peer's label
++	 * so that SO_PEERCRED can report it.
++	 */
++	rc = smk_access(smack, ssp->smk_in, MAY_WRITE);
++	if (rc == 0)
++		strncpy(ssp->smk_packet, smack, SMK_MAXLEN);
++
++	return rc;
++}
++
++/*
++ * Key management security hooks
++ *
++ * Casey has not tested key support very heavily.
++ * The permission check is most likely too restrictive.
++ * If you care about keys please have a look.
++ */
++#ifdef CONFIG_KEYS
++
++/**
++ * smack_key_alloc - Set the key security blob
++ * @key: object
++ * @tsk: the task associated with the key
++ * @flags: unused
++ *
++ * No allocation required
++ *
++ * Returns 0
++ */
++static int smack_key_alloc(struct key *key, struct task_struct *tsk,
++			   unsigned long flags)
++{
++	key->security = tsk->security;
++	return 0;
++}
++
++/**
++ * smack_key_free - Clear the key security blob
++ * @key: the object
++ *
++ * Clear the blob pointer
++ */
++static void smack_key_free(struct key *key)
++{
++	key->security = NULL;
++}
++
++/*
++ * smack_key_permission - Smack access on a key
++ * @key_ref: gets to the object
++ * @context: task involved
++ * @perm: unused
++ *
++ * Return 0 if the task has read and write to the object,
++ * an error code otherwise
++ */
++static int smack_key_permission(key_ref_t key_ref,
++				struct task_struct *context, key_perm_t perm)
++{
++	struct key *keyp;
++
++	keyp = key_ref_to_ptr(key_ref);
++	if (keyp == NULL)
++		return -EINVAL;
++	/*
++	 * If the key hasn't been initialized give it access so that
++	 * it may do so.
++	 */
++	if (keyp->security == NULL)
++		return 0;
++	/*
++	 * This should not occur
++	 */
++	if (context->security == NULL)
++		return -EACCES;
++
++	return smk_access(context->security, keyp->security, MAY_READWRITE);
++}
++#endif /* CONFIG_KEYS */
++
++/*
++ * smack_secid_to_secctx - return the smack label for a secid
++ * @secid: incoming integer
++ * @secdata: destination
++ * @seclen: how long it is
++ *
++ * Exists for networking code.
++ */
++static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
++{
++	char *sp = smack_from_secid(secid);
++
++	*secdata = sp;
++	*seclen = strlen(sp);
++	return 0;
++}
++
++/*
++ * smack_release_secctx - don't do anything.
++ * @key_ref: unused
++ * @context: unused
++ * @perm: unused
++ *
++ * Exists to make sure nothing gets done, and properly
++ */
++static void smack_release_secctx(char *secdata, u32 seclen)
++{
++}
++
++static struct security_operations smack_ops = {
++	.ptrace = 			smack_ptrace,
++	.capget = 			cap_capget,
++	.capset_check = 		cap_capset_check,
++	.capset_set = 			cap_capset_set,
++	.capable = 			cap_capable,
++	.syslog = 			smack_syslog,
++	.settime = 			cap_settime,
++	.vm_enough_memory = 		cap_vm_enough_memory,
++
++	.bprm_apply_creds = 		cap_bprm_apply_creds,
++	.bprm_set_security = 		cap_bprm_set_security,
++	.bprm_secureexec = 		cap_bprm_secureexec,
++
++	.sb_alloc_security = 		smack_sb_alloc_security,
++	.sb_free_security = 		smack_sb_free_security,
++	.sb_copy_data = 		smack_sb_copy_data,
++	.sb_kern_mount = 		smack_sb_kern_mount,
++	.sb_statfs = 			smack_sb_statfs,
++	.sb_mount = 			smack_sb_mount,
++	.sb_umount = 			smack_sb_umount,
++
++	.inode_alloc_security = 	smack_inode_alloc_security,
++	.inode_free_security = 		smack_inode_free_security,
++	.inode_init_security = 		smack_inode_init_security,
++	.inode_link = 			smack_inode_link,
++	.inode_unlink = 		smack_inode_unlink,
++	.inode_rmdir = 			smack_inode_rmdir,
++	.inode_rename = 		smack_inode_rename,
++	.inode_permission = 		smack_inode_permission,
++	.inode_setattr = 		smack_inode_setattr,
++	.inode_getattr = 		smack_inode_getattr,
++	.inode_setxattr = 		smack_inode_setxattr,
++	.inode_post_setxattr = 		smack_inode_post_setxattr,
++	.inode_getxattr = 		smack_inode_getxattr,
++	.inode_removexattr = 		smack_inode_removexattr,
++	.inode_getsecurity = 		smack_inode_getsecurity,
++	.inode_setsecurity = 		smack_inode_setsecurity,
++	.inode_listsecurity = 		smack_inode_listsecurity,
++
++	.file_permission = 		smack_file_permission,
++	.file_alloc_security = 		smack_file_alloc_security,
++	.file_free_security = 		smack_file_free_security,
++	.file_ioctl = 			smack_file_ioctl,
++	.file_lock = 			smack_file_lock,
++	.file_fcntl = 			smack_file_fcntl,
++	.file_set_fowner = 		smack_file_set_fowner,
++	.file_send_sigiotask = 		smack_file_send_sigiotask,
++	.file_receive = 		smack_file_receive,
++
++	.task_alloc_security = 		smack_task_alloc_security,
++	.task_free_security = 		smack_task_free_security,
++	.task_post_setuid =		cap_task_post_setuid,
++	.task_setpgid = 		smack_task_setpgid,
++	.task_getpgid = 		smack_task_getpgid,
++	.task_getsid = 			smack_task_getsid,
++	.task_getsecid = 		smack_task_getsecid,
++	.task_setnice = 		smack_task_setnice,
++	.task_setioprio = 		smack_task_setioprio,
++	.task_getioprio = 		smack_task_getioprio,
++	.task_setscheduler = 		smack_task_setscheduler,
++	.task_getscheduler = 		smack_task_getscheduler,
++	.task_movememory = 		smack_task_movememory,
++	.task_kill = 			smack_task_kill,
++	.task_wait = 			smack_task_wait,
++	.task_reparent_to_init =	cap_task_reparent_to_init,
++	.task_to_inode = 		smack_task_to_inode,
++
++	.ipc_permission = 		smack_ipc_permission,
++
++	.msg_msg_alloc_security = 	smack_msg_msg_alloc_security,
++	.msg_msg_free_security = 	smack_msg_msg_free_security,
++
++	.msg_queue_alloc_security = 	smack_msg_queue_alloc_security,
++	.msg_queue_free_security = 	smack_msg_queue_free_security,
++	.msg_queue_associate = 		smack_msg_queue_associate,
++	.msg_queue_msgctl = 		smack_msg_queue_msgctl,
++	.msg_queue_msgsnd = 		smack_msg_queue_msgsnd,
++	.msg_queue_msgrcv = 		smack_msg_queue_msgrcv,
++
++	.shm_alloc_security = 		smack_shm_alloc_security,
++	.shm_free_security = 		smack_shm_free_security,
++	.shm_associate = 		smack_shm_associate,
++	.shm_shmctl = 			smack_shm_shmctl,
++	.shm_shmat = 			smack_shm_shmat,
++
++	.sem_alloc_security = 		smack_sem_alloc_security,
++	.sem_free_security = 		smack_sem_free_security,
++	.sem_associate = 		smack_sem_associate,
++	.sem_semctl = 			smack_sem_semctl,
++	.sem_semop = 			smack_sem_semop,
++
++	.netlink_send =			cap_netlink_send,
++	.netlink_recv = 		cap_netlink_recv,
++
++	.d_instantiate = 		smack_d_instantiate,
++
++	.getprocattr = 			smack_getprocattr,
++	.setprocattr = 			smack_setprocattr,
++
++	.unix_stream_connect = 		smack_unix_stream_connect,
++	.unix_may_send = 		smack_unix_may_send,
++
++	.socket_post_create = 		smack_socket_post_create,
++	.socket_sock_rcv_skb = 		smack_socket_sock_rcv_skb,
++	.socket_getpeersec_stream =	smack_socket_getpeersec_stream,
++	.socket_getpeersec_dgram =	smack_socket_getpeersec_dgram,
++	.sk_alloc_security = 		smack_sk_alloc_security,
++	.sk_free_security = 		smack_sk_free_security,
++	.sock_graft = 			smack_sock_graft,
++	.inet_conn_request = 		smack_inet_conn_request,
++ /* key management security hooks */
++#ifdef CONFIG_KEYS
++	.key_alloc = 			smack_key_alloc,
++	.key_free = 			smack_key_free,
++	.key_permission = 		smack_key_permission,
++#endif /* CONFIG_KEYS */
++	.secid_to_secctx = 		smack_secid_to_secctx,
++	.release_secctx = 		smack_release_secctx,
++};
++
++/**
++ * smack_init - initialize the smack system
++ *
++ * Returns 0
++ */
++static __init int smack_init(void)
++{
++	printk(KERN_INFO "Smack:  Initializing.\n");
++
++	/*
++	 * Set the security state for the initial task.
++	 */
++	current->security = &smack_known_floor.smk_known;
++
++	/*
++	 * Initialize locks
++	 */
++	spin_lock_init(&smack_known_unset.smk_cipsolock);
++	spin_lock_init(&smack_known_huh.smk_cipsolock);
++	spin_lock_init(&smack_known_hat.smk_cipsolock);
++	spin_lock_init(&smack_known_star.smk_cipsolock);
++	spin_lock_init(&smack_known_floor.smk_cipsolock);
++	spin_lock_init(&smack_known_invalid.smk_cipsolock);
++
++	/*
++	 * Register with LSM
++	 */
++	if (register_security(&smack_ops))
++		panic("smack: Unable to register with kernel.\n");
++
++	return 0;
++}
++
++/*
++ * Smack requires early initialization in order to label
++ * all processes and objects when they are created.
++ */
++security_initcall(smack_init);
++
+diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
+new file mode 100644
+index 0000000..15aa37f
+--- /dev/null
++++ b/security/smack/smackfs.c
+@@ -0,0 +1,981 @@
++/*
++ * Copyright (C) 2007 Casey Schaufler <casey at schaufler-ca.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, version 2.
++ *
++ * Authors:
++ * 	Casey Schaufler <casey at schaufler-ca.com>
++ * 	Ahmed S. Darwish <darwish.07 at gmail.com>
++ *
++ * Special thanks to the authors of selinuxfs.
++ *
++ *	Karl MacMillan <kmacmillan at tresys.com>
++ *	James Morris <jmorris at redhat.com>
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/vmalloc.h>
++#include <linux/security.h>
++#include <linux/mutex.h>
++#include <net/netlabel.h>
++#include <net/cipso_ipv4.h>
++#include <linux/seq_file.h>
++#include <linux/ctype.h>
++#include "smack.h"
++
++/*
++ * smackfs pseudo filesystem.
++ */
++
++enum smk_inos {
++	SMK_ROOT_INO	= 2,
++	SMK_LOAD	= 3,	/* load policy */
++	SMK_CIPSO	= 4,	/* load label -> CIPSO mapping */
++	SMK_DOI		= 5,	/* CIPSO DOI */
++	SMK_DIRECT	= 6,	/* CIPSO level indicating direct label */
++	SMK_AMBIENT	= 7,	/* internet ambient label */
++	SMK_NLTYPE	= 8,	/* label scheme to use by default */
++};
++
++/*
++ * List locks
++ */
++static DEFINE_MUTEX(smack_list_lock);
++static DEFINE_MUTEX(smack_cipso_lock);
++
++/*
++ * This is the "ambient" label for network traffic.
++ * If it isn't somehow marked, use this.
++ * It can be reset via smackfs/ambient
++ */
++char *smack_net_ambient = smack_known_floor.smk_known;
++
++/*
++ * This is the default packet marking scheme for network traffic.
++ * It can be reset via smackfs/nltype
++ */
++int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
++
++/*
++ * This is the level in a CIPSO header that indicates a
++ * smack label is contained directly in the category set.
++ * It can be reset via smackfs/direct
++ */
++int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
++
++static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
++struct smk_list_entry *smack_list;
++
++#define	SEQ_READ_FINISHED	1
++
++/*
++ * Disable concurrent writing open() operations
++ */
++static struct semaphore smack_write_sem;
++
++/*
++ * Values for parsing cipso rules
++ * SMK_DIGITLEN: Length of a digit field in a rule.
++ * SMK_CIPSOMEN: Minimum possible cipso rule length.
++ */
++#define SMK_DIGITLEN 4
++#define SMK_CIPSOMIN (SMK_MAXLEN + 2 * SMK_DIGITLEN)
++
++/*
++ * Seq_file read operations for /smack/load
++ */
++
++static void *load_seq_start(struct seq_file *s, loff_t *pos)
++{
++	if (*pos == SEQ_READ_FINISHED)
++		return NULL;
++
++	return smack_list;
++}
++
++static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
++{
++	struct smk_list_entry *skp = ((struct smk_list_entry *) v)->smk_next;
++
++	if (skp == NULL)
++		*pos = SEQ_READ_FINISHED;
++
++	return skp;
++}
++
++static int load_seq_show(struct seq_file *s, void *v)
++{
++	struct smk_list_entry *slp = (struct smk_list_entry *) v;
++	struct smack_rule *srp = &slp->smk_rule;
++
++	seq_printf(s, "%s %s", (char *)srp->smk_subject,
++		   (char *)srp->smk_object);
++
++	seq_putc(s, ' ');
++
++	if (srp->smk_access & MAY_READ)
++		seq_putc(s, 'r');
++	if (srp->smk_access & MAY_WRITE)
++		seq_putc(s, 'w');
++	if (srp->smk_access & MAY_EXEC)
++		seq_putc(s, 'x');
++	if (srp->smk_access & MAY_APPEND)
++		seq_putc(s, 'a');
++	if (srp->smk_access == 0)
++		seq_putc(s, '-');
++
++	seq_putc(s, '\n');
++
++	return 0;
++}
++
++static void load_seq_stop(struct seq_file *s, void *v)
++{
++	/* No-op */
++}
++
++static struct seq_operations load_seq_ops = {
++	.start = load_seq_start,
++	.next  = load_seq_next,
++	.show  = load_seq_show,
++	.stop  = load_seq_stop,
++};
++
++/**
++ * smk_open_load - open() for /smack/load
++ * @inode: inode structure representing file
++ * @file: "load" file pointer
++ *
++ * For reading, use load_seq_* seq_file reading operations.
++ */
++static int smk_open_load(struct inode *inode, struct file *file)
++{
++	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
++		return seq_open(file, &load_seq_ops);
++
++	if (down_interruptible(&smack_write_sem))
++		return -ERESTARTSYS;
++
++	return 0;
++}
++
++/**
++ * smk_release_load - release() for /smack/load
++ * @inode: inode structure representing file
++ * @file: "load" file pointer
++ *
++ * For a reading session, use the seq_file release
++ * implementation.
++ * Otherwise, we are at the end of a writing session so
++ * clean everything up.
++ */
++static int smk_release_load(struct inode *inode, struct file *file)
++{
++	if ((file->f_flags & O_ACCMODE) == O_RDONLY)
++		return seq_release(inode, file);
++
++	up(&smack_write_sem);
++	return 0;
++}
++
++/**
++ * smk_set_access - add a rule to the rule list
++ * @srp: the new rule to add
++ *
++ * Looks through the current subject/object/access list for
++ * the subject/object pair and replaces the access that was
++ * there. If the pair isn't found add it with the specified
++ * access.
++ */
++static void smk_set_access(struct smack_rule *srp)
++{
++	struct smk_list_entry *sp;
++	struct smk_list_entry *newp;
++
++	mutex_lock(&smack_list_lock);
++
++	for (sp = smack_list; sp != NULL; sp = sp->smk_next)
++		if (sp->smk_rule.smk_subject == srp->smk_subject &&
++		    sp->smk_rule.smk_object == srp->smk_object) {
++			sp->smk_rule.smk_access = srp->smk_access;
++			break;
++		}
++
++	if (sp == NULL) {
++		newp = kzalloc(sizeof(struct smk_list_entry), GFP_KERNEL);
++		newp->smk_rule = *srp;
++		newp->smk_next = smack_list;
++		smack_list = newp;
++	}
++
++	mutex_unlock(&smack_list_lock);
++
++	return;
++}
++
++/**
++ * smk_write_load - write() for /smack/load
++ * @filp: file pointer, not actually used
++ * @buf: where to get the data from
++ * @count: bytes sent
++ * @ppos: where to start - must be 0
++ *
++ * Get one smack access rule from above.
++ * The format is exactly:
++ *     char subject[SMK_LABELLEN]
++ *     char object[SMK_LABELLEN]
++ *     char access[SMK_ACCESSKINDS]
++ *
++ *     Anything following is commentary and ignored.
++ *
++ * writes must be SMK_LABELLEN+SMK_LABELLEN+4 bytes.
++ */
++#define MINIMUM_LOAD (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSKINDS)
++
++static ssize_t smk_write_load(struct file *file, const char __user *buf,
++			      size_t count, loff_t *ppos)
++{
++	struct smack_rule rule;
++	char *data;
++	int rc = -EINVAL;
++
++	/*
++	 * Must have privilege.
++	 * No partial writes.
++	 * Enough data must be present.
++	 */
++	if (!capable(CAP_MAC_ADMIN))
++		return -EPERM;
++	if (*ppos != 0)
++		return -EINVAL;
++	if (count < MINIMUM_LOAD)
++		return -EINVAL;
++
++	data = kzalloc(count, GFP_KERNEL);
++	if (data == NULL)
++		return -ENOMEM;
++
++	if (copy_from_user(data, buf, count) != 0) {
++		rc = -EFAULT;
++		goto out;
++	}
++
++	rule.smk_subject = smk_import(data, 0);
++	if (rule.smk_subject == NULL)
++		goto out;
++
++	rule.smk_object = smk_import(data + SMK_LABELLEN, 0);
++	if (rule.smk_object == NULL)
++		goto out;
++
++	rule.smk_access = 0;
++
++	switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
++	case '-':
++		break;
++	case 'r':
++	case 'R':
++		rule.smk_access |= MAY_READ;
++		break;
++	default:
++		goto out;
++	}
++
++	switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
++	case '-':
++		break;
++	case 'w':
++	case 'W':
++		rule.smk_access |= MAY_WRITE;
++		break;
++	default:
++		goto out;
++	}
++
++	switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
++	case '-':
++		break;
++	case 'x':
++	case 'X':
++		rule.smk_access |= MAY_EXEC;
++		break;
++	default:
++		goto out;
++	}
++
++	switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
++	case '-':
++		break;
++	case 'a':
++	case 'A':
++		rule.smk_access |= MAY_READ;
++		break;
++	default:
++		goto out;
++	}
++
++	smk_set_access(&rule);
++	rc = count;
++
++out:
++	kfree(data);
++	return rc;
++}
++
++static const struct file_operations smk_load_ops = {
++	.open           = smk_open_load,
++	.read		= seq_read,
++	.llseek         = seq_lseek,
++	.write		= smk_write_load,
++	.release        = smk_release_load,
++};
++
++/**
++ * smk_cipso_doi - initialize the CIPSO domain
++ */
++void smk_cipso_doi(void)
++{
++	int rc;
++	struct cipso_v4_doi *doip;
++	struct netlbl_audit audit_info;
++
++	rc = netlbl_cfg_map_del(NULL, &audit_info);
++	if (rc != 0)
++		printk(KERN_WARNING "%s:%d remove rc = %d\n",
++		       __func__, __LINE__, rc);
++
++	doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
++	if (doip == NULL)
++		panic("smack:  Failed to initialize cipso DOI.\n");
++	doip->map.std = NULL;
++	doip->doi = smk_cipso_doi_value;
++	doip->type = CIPSO_V4_MAP_PASS;
++	doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
++	for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
++		doip->tags[rc] = CIPSO_V4_TAG_INVALID;
++
++	rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
++	if (rc != 0)
++		printk(KERN_WARNING "%s:%d add rc = %d\n",
++		       __func__, __LINE__, rc);
++}
++
++/*
++ * Seq_file read operations for /smack/cipso
++ */
++
++static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
++{
++	if (*pos == SEQ_READ_FINISHED)
++		return NULL;
++
++	return smack_known;
++}
++
++static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
++{
++	struct smack_known *skp = ((struct smack_known *) v)->smk_next;
++
++	/*
++	 * Omit labels with no associated cipso value
++	 */
++	while (skp != NULL && !skp->smk_cipso)
++		skp = skp->smk_next;
++
++	if (skp == NULL)
++		*pos = SEQ_READ_FINISHED;
++
++	return skp;
++}
++
++/*
++ * Print cipso labels in format:
++ * label level[/cat[,cat]]
++ */
++static int cipso_seq_show(struct seq_file *s, void *v)
++{
++	struct smack_known *skp = (struct smack_known *) v;
++	struct smack_cipso *scp = skp->smk_cipso;
++	char *cbp;
++	char sep = '/';
++	int cat = 1;
++	int i;
++	unsigned char m;
++
++	if (scp == NULL)
++		return 0;
++
++	seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level);
++
++	cbp = scp->smk_catset;
++	for (i = 0; i < SMK_LABELLEN; i++)
++		for (m = 0x80; m != 0; m >>= 1) {
++			if (m & cbp[i]) {
++				seq_printf(s, "%c%d", sep, cat);
++				sep = ',';
++			}
++			cat++;
++		}
++
++	seq_putc(s, '\n');
++
++	return 0;
++}
++
++static void cipso_seq_stop(struct seq_file *s, void *v)
++{
++	/* No-op */
++}
++
++static struct seq_operations cipso_seq_ops = {
++	.start = cipso_seq_start,
++	.stop  = cipso_seq_stop,
++	.next  = cipso_seq_next,
++	.show  = cipso_seq_show,
++};
++
++/**
++ * smk_open_cipso - open() for /smack/cipso
++ * @inode: inode structure representing file
++ * @file: "cipso" file pointer
++ *
++ * Connect our cipso_seq_* operations with /smack/cipso
++ * file_operations
++ */
++static int smk_open_cipso(struct inode *inode, struct file *file)
++{
++	return seq_open(file, &cipso_seq_ops);
++}
++
++/**
++ * smk_write_cipso - write() for /smack/cipso
++ * @filp: file pointer, not actually used
++ * @buf: where to get the data from
++ * @count: bytes sent
++ * @ppos: where to start
++ *
++ * Accepts only one cipso rule per write call.
++ * Returns number of bytes written or error code, as appropriate
++ */
++static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
++			       size_t count, loff_t *ppos)
++{
++	struct smack_known *skp;
++	struct smack_cipso *scp = NULL;
++	char mapcatset[SMK_LABELLEN];
++	int maplevel;
++	int cat;
++	int catlen;
++	ssize_t rc = -EINVAL;
++	char *data = NULL;
++	char *rule;
++	int ret;
++	int i;
++
++	/*
++	 * Must have privilege.
++	 * No partial writes.
++	 * Enough data must be present.
++	 */
++	if (!capable(CAP_MAC_ADMIN))
++		return -EPERM;
++	if (*ppos != 0)
++		return -EINVAL;
++	if (count <= SMK_CIPSOMIN)
++		return -EINVAL;
++
++	data = kzalloc(count + 1, GFP_KERNEL);
++	if (data == NULL)
++		return -ENOMEM;
++
++	if (copy_from_user(data, buf, count) != 0) {
++		rc = -EFAULT;
++		goto unlockedout;
++	}
++
++	data[count] = '\0';
++	rule = data;
++	/*
++	 * Only allow one writer at a time. Writes should be
++	 * quite rare and small in any case.
++	 */
++	mutex_lock(&smack_cipso_lock);
++
++	skp = smk_import_entry(rule, 0);
++	if (skp == NULL)
++		goto out;
++
++	rule += SMK_LABELLEN;;
++	ret = sscanf(rule, "%d", &maplevel);
++	if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
++		goto out;
++
++	rule += SMK_DIGITLEN;
++	ret = sscanf(rule, "%d", &catlen);
++	if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
++		goto out;
++
++	if (count <= (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
++		goto out;
++
++	memset(mapcatset, 0, sizeof(mapcatset));
++
++	for (i = 0; i < catlen; i++) {
++		rule += SMK_DIGITLEN;
++		ret = sscanf(rule, "%d", &cat);
++		if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
++			goto out;
++
++		smack_catset_bit(cat, mapcatset);
++	}
++
++	if (skp->smk_cipso == NULL) {
++		scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL);
++		if (scp == NULL) {
++			rc = -ENOMEM;
++			goto out;
++		}
++	}
++
++	spin_lock_bh(&skp->smk_cipsolock);
++
++	if (scp == NULL)
++		scp = skp->smk_cipso;
++	else
++		skp->smk_cipso = scp;
++
++	scp->smk_level = maplevel;
++	memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset));
++
++	spin_unlock_bh(&skp->smk_cipsolock);
++
++	rc = count;
++out:
++	mutex_unlock(&smack_cipso_lock);
++unlockedout:
++	kfree(data);
++	return rc;
++}
++
++static const struct file_operations smk_cipso_ops = {
++	.open           = smk_open_cipso,
++	.read		= seq_read,
++	.llseek         = seq_lseek,
++	.write		= smk_write_cipso,
++	.release        = seq_release,
++};
++
++/**
++ * smk_read_doi - read() for /smack/doi
++ * @filp: file pointer, not actually used
++ * @buf: where to put the result
++ * @count: maximum to send along
++ * @ppos: where to start
++ *
++ * Returns number of bytes read or error code, as appropriate
++ */
++static ssize_t smk_read_doi(struct file *filp, char __user *buf,
++			    size_t count, loff_t *ppos)
++{
++	char temp[80];
++	ssize_t rc;
++
++	if (*ppos != 0)
++		return 0;
++
++	sprintf(temp, "%d", smk_cipso_doi_value);
++	rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
++
++	return rc;
++}
++
++/**
++ * smk_write_doi - write() for /smack/doi
++ * @filp: file pointer, not actually used
++ * @buf: where to get the data from
++ * @count: bytes sent
++ * @ppos: where to start
++ *
++ * Returns number of bytes written or error code, as appropriate
++ */
++static ssize_t smk_write_doi(struct file *file, const char __user *buf,
++			     size_t count, loff_t *ppos)
++{
++	char temp[80];
++	int i;
++
++	if (!capable(CAP_MAC_ADMIN))
++		return -EPERM;
++
++	if (count >= sizeof(temp) || count == 0)
++		return -EINVAL;
++
++	if (copy_from_user(temp, buf, count) != 0)
++		return -EFAULT;
++
++	temp[count] = '\0';
++
++	if (sscanf(temp, "%d", &i) != 1)
++		return -EINVAL;
++
++	smk_cipso_doi_value = i;
++
++	smk_cipso_doi();
++
++	return count;
++}
++
++static const struct file_operations smk_doi_ops = {
++	.read		= smk_read_doi,
++	.write		= smk_write_doi,
++};
++
++/**
++ * smk_read_direct - read() for /smack/direct
++ * @filp: file pointer, not actually used
++ * @buf: where to put the result
++ * @count: maximum to send along
++ * @ppos: where to start
++ *
++ * Returns number of bytes read or error code, as appropriate
++ */
++static ssize_t smk_read_direct(struct file *filp, char __user *buf,
++			       size_t count, loff_t *ppos)
++{
++	char temp[80];
++	ssize_t rc;
++
++	if (*ppos != 0)
++		return 0;
++
++	sprintf(temp, "%d", smack_cipso_direct);
++	rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
++
++	return rc;
++}
++
++/**
++ * smk_write_direct - write() for /smack/direct
++ * @filp: file pointer, not actually used
++ * @buf: where to get the data from
++ * @count: bytes sent
++ * @ppos: where to start
++ *
++ * Returns number of bytes written or error code, as appropriate
++ */
++static ssize_t smk_write_direct(struct file *file, const char __user *buf,
++				size_t count, loff_t *ppos)
++{
++	char temp[80];
++	int i;
++
++	if (!capable(CAP_MAC_ADMIN))
++		return -EPERM;
++
++	if (count >= sizeof(temp) || count == 0)
++		return -EINVAL;
++
++	if (copy_from_user(temp, buf, count) != 0)
++		return -EFAULT;
++
++	temp[count] = '\0';
++
++	if (sscanf(temp, "%d", &i) != 1)
++		return -EINVAL;
++
++	smack_cipso_direct = i;
++
++	return count;
++}
++
++static const struct file_operations smk_direct_ops = {
++	.read		= smk_read_direct,
++	.write		= smk_write_direct,
++};
++
++/**
++ * smk_read_ambient - read() for /smack/ambient
++ * @filp: file pointer, not actually used
++ * @buf: where to put the result
++ * @cn: maximum to send along
++ * @ppos: where to start
++ *
++ * Returns number of bytes read or error code, as appropriate
++ */
++static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
++				size_t cn, loff_t *ppos)
++{
++	ssize_t rc;
++	char out[SMK_LABELLEN];
++	int asize;
++
++	if (*ppos != 0)
++		return 0;
++	/*
++	 * Being careful to avoid a problem in the case where
++	 * smack_net_ambient gets changed in midstream.
++	 * Since smack_net_ambient is always set with a value
++	 * from the label list, including initially, and those
++	 * never get freed, the worst case is that the pointer
++	 * gets changed just after this strncpy, in which case
++	 * the value passed up is incorrect. Locking around
++	 * smack_net_ambient wouldn't be any better than this
++	 * copy scheme as by the time the caller got to look
++	 * at the ambient value it would have cleared the lock
++	 * and been changed.
++	 */
++	strncpy(out, smack_net_ambient, SMK_LABELLEN);
++	asize = strlen(out) + 1;
++
++	if (cn < asize)
++		return -EINVAL;
++
++	rc = simple_read_from_buffer(buf, cn, ppos, out, asize);
++
++	return rc;
++}
++
++/**
++ * smk_write_ambient - write() for /smack/ambient
++ * @filp: file pointer, not actually used
++ * @buf: where to get the data from
++ * @count: bytes sent
++ * @ppos: where to start
++ *
++ * Returns number of bytes written or error code, as appropriate
++ */
++static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
++				 size_t count, loff_t *ppos)
++{
++	char in[SMK_LABELLEN];
++	char *smack;
++
++	if (!capable(CAP_MAC_ADMIN))
++		return -EPERM;
++
++	if (count >= SMK_LABELLEN)
++		return -EINVAL;
++
++	if (copy_from_user(in, buf, count) != 0)
++		return -EFAULT;
++
++	smack = smk_import(in, count);
++	if (smack == NULL)
++		return -EINVAL;
++
++	smack_net_ambient = smack;
++
++	return count;
++}
++
++static const struct file_operations smk_ambient_ops = {
++	.read		= smk_read_ambient,
++	.write		= smk_write_ambient,
++};
++
++struct option_names {
++	int	o_number;
++	char	*o_name;
++	char	*o_alias;
++};
++
++static struct option_names netlbl_choices[] = {
++	{ NETLBL_NLTYPE_RIPSO,
++		NETLBL_NLTYPE_RIPSO_NAME,	"ripso" },
++	{ NETLBL_NLTYPE_CIPSOV4,
++		NETLBL_NLTYPE_CIPSOV4_NAME,	"cipsov4" },
++	{ NETLBL_NLTYPE_CIPSOV4,
++		NETLBL_NLTYPE_CIPSOV4_NAME,	"cipso" },
++	{ NETLBL_NLTYPE_CIPSOV6,
++		NETLBL_NLTYPE_CIPSOV6_NAME,	"cipsov6" },
++	{ NETLBL_NLTYPE_UNLABELED,
++		NETLBL_NLTYPE_UNLABELED_NAME,	"unlabeled" },
++};
++
++/**
++ * smk_read_nltype - read() for /smack/nltype
++ * @filp: file pointer, not actually used
++ * @buf: where to put the result
++ * @count: maximum to send along
++ * @ppos: where to start
++ *
++ * Returns number of bytes read or error code, as appropriate
++ */
++static ssize_t smk_read_nltype(struct file *filp, char __user *buf,
++			       size_t count, loff_t *ppos)
++{
++	char bound[40];
++	ssize_t rc;
++	int i;
++
++	if (count < SMK_LABELLEN)
++		return -EINVAL;
++
++	if (*ppos != 0)
++		return 0;
++
++	sprintf(bound, "unknown");
++
++	for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
++		if (smack_net_nltype == netlbl_choices[i].o_number) {
++			sprintf(bound, "%s", netlbl_choices[i].o_name);
++			break;
++		}
++
++	rc = simple_read_from_buffer(buf, count, ppos, bound, strlen(bound));
++
++	return rc;
++}
++
++/**
++ * smk_write_nltype - write() for /smack/nltype
++ * @filp: file pointer, not actually used
++ * @buf: where to get the data from
++ * @count: bytes sent
++ * @ppos: where to start
++ *
++ * Returns number of bytes written or error code, as appropriate
++ */
++static ssize_t smk_write_nltype(struct file *file, const char __user *buf,
++				size_t count, loff_t *ppos)
++{
++	char bound[40];
++	char *cp;
++	int i;
++
++	if (!capable(CAP_MAC_ADMIN))
++		return -EPERM;
++
++	if (count >= 40)
++		return -EINVAL;
++
++	if (copy_from_user(bound, buf, count) != 0)
++		return -EFAULT;
++
++	bound[count] = '\0';
++	cp = strchr(bound, ' ');
++	if (cp != NULL)
++		*cp = '\0';
++	cp = strchr(bound, '\n');
++	if (cp != NULL)
++		*cp = '\0';
++
++	for (i = 0; i < ARRAY_SIZE(netlbl_choices); i++)
++		if (strcmp(bound, netlbl_choices[i].o_name) == 0 ||
++		    strcmp(bound, netlbl_choices[i].o_alias) == 0) {
++			smack_net_nltype = netlbl_choices[i].o_number;
++			return count;
++		}
++	/*
++	 * Not a valid choice.
++	 */
++	return -EINVAL;
++}
++
++static const struct file_operations smk_nltype_ops = {
++	.read		= smk_read_nltype,
++	.write		= smk_write_nltype,
++};
++
++/**
++ * smk_fill_super - fill the /smackfs superblock
++ * @sb: the empty superblock
++ * @data: unused
++ * @silent: unused
++ *
++ * Fill in the well known entries for /smack
++ *
++ * Returns 0 on success, an error code on failure
++ */
++static int smk_fill_super(struct super_block *sb, void *data, int silent)
++{
++	int rc;
++	struct inode *root_inode;
++
++	static struct tree_descr smack_files[] = {
++		[SMK_LOAD]	=
++			{"load", &smk_load_ops, S_IRUGO|S_IWUSR},
++		[SMK_CIPSO]	=
++			{"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
++		[SMK_DOI]	=
++			{"doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
++		[SMK_DIRECT]	=
++			{"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
++		[SMK_AMBIENT]	=
++			{"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
++		[SMK_NLTYPE]	=
++			{"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},
++		/* last one */ {""}
++	};
++
++	rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
++	if (rc != 0) {
++		printk(KERN_ERR "%s failed %d while creating inodes\n",
++			__func__, rc);
++		return rc;
++	}
++
++	root_inode = sb->s_root->d_inode;
++	root_inode->i_security = new_inode_smack(smack_known_floor.smk_known);
++
++	return 0;
++}
++
++/**
++ * smk_get_sb - get the smackfs superblock
++ * @fs_type: passed along without comment
++ * @flags: passed along without comment
++ * @dev_name: passed along without comment
++ * @data: passed along without comment
++ * @mnt: passed along without comment
++ *
++ * Just passes everything along.
++ *
++ * Returns what the lower level code does.
++ */
++static int smk_get_sb(struct file_system_type *fs_type,
++		      int flags, const char *dev_name, void *data,
++		      struct vfsmount *mnt)
++{
++	return get_sb_single(fs_type, flags, data, smk_fill_super, mnt);
++}
++
++static struct file_system_type smk_fs_type = {
++	.name		= "smackfs",
++	.get_sb		= smk_get_sb,
++	.kill_sb	= kill_litter_super,
++};
++
++static struct vfsmount *smackfs_mount;
++
++/**
++ * init_smk_fs - get the smackfs superblock
++ *
++ * register the smackfs
++ *
++ * Returns 0 unless the registration fails.
++ */
++static int __init init_smk_fs(void)
++{
++	int err;
++
++	err = register_filesystem(&smk_fs_type);
++	if (!err) {
++		smackfs_mount = kern_mount(&smk_fs_type);
++		if (IS_ERR(smackfs_mount)) {
++			printk(KERN_ERR "smackfs:  could not mount!\n");
++			err = PTR_ERR(smackfs_mount);
++			smackfs_mount = NULL;
++		}
++	}
++
++	sema_init(&smack_write_sem, 1);
++	smk_cipso_doi();
++
++	return err;
++}
++
++__initcall(init_smk_fs);
 diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h
 index 541b908..e087894 100644
 --- a/sound/aoa/aoa.h
@@ -1020010,10 +1104282,10 @@
  	[SNDRV_PCM_FORMAT_S32_LE] = {
  		.width = 32, .phys = 32, .le = 1, .signd = 1,
 diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
-index fb3dde4..6244911 100644
+index fb3dde4..61f5d42 100644
 --- a/sound/core/pcm_native.c
 +++ b/sound/core/pcm_native.c
-@@ -19,7 +19,6 @@
+@@ -19,12 +19,11 @@
   *
   */
  
@@ -1020021,6 +1104293,12 @@
  #include <linux/mm.h>
  #include <linux/file.h>
  #include <linux/slab.h>
+ #include <linux/time.h>
+-#include <linux/latency.h>
++#include <linux/pm_qos_params.h>
+ #include <linux/uio.h>
+ #include <sound/core.h>
+ #include <sound/control.h>
 @@ -413,7 +412,6 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
  	runtime->period_size = params_period_size(params);
  	runtime->periods = params_periods(params);
@@ -1020039,7 +1104317,31 @@
  	runtime->start_threshold = 1;
  	runtime->stop_threshold = runtime->buffer_size;
  	runtime->silence_threshold = 0;
-@@ -532,9 +528,6 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
+@@ -447,9 +443,11 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
+ 	snd_pcm_timer_resolution_change(substream);
+ 	runtime->status->state = SNDRV_PCM_STATE_SETUP;
+ 
+-	remove_acceptable_latency(substream->latency_id);
++	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
++				substream->latency_id);
+ 	if ((usecs = period_to_usecs(runtime)) >= 0)
+-		set_acceptable_latency(substream->latency_id, usecs);
++		pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
++					substream->latency_id, usecs);
+ 	return 0;
+  _error:
+ 	/* hardware might be unuseable from this time,
+@@ -509,7 +507,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
+ 	if (substream->ops->hw_free)
+ 		result = substream->ops->hw_free(substream);
+ 	runtime->status->state = SNDRV_PCM_STATE_OPEN;
+-	remove_acceptable_latency(substream->latency_id);
++	pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
++		substream->latency_id);
+ 	return result;
+ }
+ 
+@@ -532,9 +531,6 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
  		return -EINVAL;
  	if (params->avail_min == 0)
  		return -EINVAL;
@@ -1020049,7 +1104351,7 @@
  	if (params->silence_size >= runtime->boundary) {
  		if (params->silence_threshold != 0)
  			return -EINVAL;
-@@ -546,20 +539,14 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
+@@ -546,20 +542,14 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
  	}
  	snd_pcm_stream_lock_irq(substream);
  	runtime->tstamp_mode = params->tstamp_mode;
@@ -1020070,7 +1104372,7 @@
  		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
  		    runtime->silence_size > 0)
  			snd_pcm_playback_silence(substream, ULONG_MAX);
-@@ -595,12 +582,13 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
+@@ -595,12 +585,13 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
  	status->trigger_tstamp = runtime->trigger_tstamp;
  	if (snd_pcm_running(substream)) {
  		snd_pcm_update_hw_ptr(substream);
@@ -1020089,7 +1104391,7 @@
  	status->appl_ptr = runtime->control->appl_ptr;
  	status->hw_ptr = runtime->status->hw_ptr;
  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-@@ -688,7 +676,7 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
+@@ -688,7 +679,7 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
  	if (runtime->trigger_master == NULL)
  		return;
  	if (runtime->trigger_master == substream) {
@@ -1020098,7 +1104400,7 @@
  	} else {
  		snd_pcm_trigger_tstamp(runtime->trigger_master);
  		runtime->trigger_tstamp = runtime->trigger_master->runtime->trigger_tstamp;
-@@ -875,8 +863,6 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
+@@ -875,8 +866,6 @@ static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
  	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
  	    runtime->silence_size > 0)
  		snd_pcm_playback_silence(substream, ULONG_MAX);
@@ -1020107,7 +1104409,7 @@
  	if (substream->timer)
  		snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTART,
  				 &runtime->trigger_tstamp);
-@@ -930,7 +916,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
+@@ -930,7 +919,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
  			snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MSTOP,
  					 &runtime->trigger_tstamp);
  		runtime->status->state = state;
@@ -1020115,7 +1104417,7 @@
  	}
  	wake_up(&runtime->sleep);
  }
-@@ -1014,12 +999,9 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
+@@ -1014,12 +1002,9 @@ static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
  			snd_timer_notify(substream->timer,
  					 SNDRV_TIMER_EVENT_MPAUSE,
  					 &runtime->trigger_tstamp);
@@ -1020128,7 +1104430,7 @@
  		if (substream->timer)
  			snd_timer_notify(substream->timer,
  					 SNDRV_TIMER_EVENT_MCONTINUE,
-@@ -1074,7 +1056,6 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
+@@ -1074,7 +1059,6 @@ static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
  				 &runtime->trigger_tstamp);
  	runtime->status->suspended_state = runtime->status->state;
  	runtime->status->state = SNDRV_PCM_STATE_SUSPENDED;
@@ -1020136,7 +1104438,7 @@
  	wake_up(&runtime->sleep);
  }
  
-@@ -1177,8 +1158,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
+@@ -1177,8 +1161,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
  		snd_timer_notify(substream->timer, SNDRV_TIMER_EVENT_MRESUME,
  				 &runtime->trigger_tstamp);
  	runtime->status->state = runtime->status->suspended_state;
@@ -1020145,7 +1104447,7 @@
  }
  
  static struct action_ops snd_pcm_action_resume = {
-@@ -1395,10 +1374,10 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
+@@ -1395,10 +1377,10 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
  	} else {
  		/* stop running stream */
  		if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
@@ -1020159,7 +1104461,7 @@
  		}
  	}
  	return 0;
-@@ -2007,8 +1986,6 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
+@@ -2007,8 +1989,6 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
  	}
  
  	/* FIXME: this belong to lowlevel */
@@ -1020168,7 +1104470,7 @@
  	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
  
  	return 0;
-@@ -2244,15 +2221,10 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
+@@ -2244,15 +2224,10 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst
  	}
  	if (frames > (snd_pcm_uframes_t)hw_avail)
  		frames = hw_avail;
@@ -1020184,7 +1104486,7 @@
  	ret = frames;
   __end:
  	snd_pcm_stream_unlock_irq(substream);
-@@ -2294,15 +2266,10 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
+@@ -2294,15 +2269,10 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr
  	}
  	if (frames > (snd_pcm_uframes_t)hw_avail)
  		frames = hw_avail;
@@ -1020200,7 +1104502,7 @@
  	ret = frames;
   __end:
  	snd_pcm_stream_unlock_irq(substream);
-@@ -2345,15 +2312,10 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
+@@ -2345,15 +2315,10 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs
  	}
  	if (frames > (snd_pcm_uframes_t)avail)
  		frames = avail;
@@ -1020216,7 +1104518,7 @@
  	ret = frames;
   __end:
  	snd_pcm_stream_unlock_irq(substream);
-@@ -2396,15 +2358,10 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
+@@ -2396,15 +2361,10 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst
  	}
  	if (frames > (snd_pcm_uframes_t)avail)
  		frames = avail;
@@ -1020232,7 +1104534,7 @@
  	ret = frames;
   __end:
  	snd_pcm_stream_unlock_irq(substream);
-@@ -2519,6 +2476,21 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
+@@ -2519,6 +2479,21 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
  		return -EFAULT;
  	return 0;
  }
@@ -1020254,7 +1104556,7 @@
  		
  static int snd_pcm_common_ioctl1(struct file *file,
  				 struct snd_pcm_substream *substream,
-@@ -2531,8 +2503,10 @@ static int snd_pcm_common_ioctl1(struct file *file,
+@@ -2531,8 +2506,10 @@ static int snd_pcm_common_ioctl1(struct file *file,
  		return put_user(SNDRV_PCM_VERSION, (int __user *)arg) ? -EFAULT : 0;
  	case SNDRV_PCM_IOCTL_INFO:
  		return snd_pcm_info_user(substream, arg);
@@ -1020266,7 +1104568,7 @@
  	case SNDRV_PCM_IOCTL_HW_REFINE:
  		return snd_pcm_hw_refine_user(substream, arg);
  	case SNDRV_PCM_IOCTL_HW_PARAMS:
-@@ -3018,26 +2992,23 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
+@@ -3018,26 +2995,23 @@ static unsigned int snd_pcm_capture_poll(struct file *file, poll_table * wait)
  /*
   * mmap status record
   */
@@ -1020300,7 +1104602,7 @@
  };
  
  static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file *file,
-@@ -3061,26 +3032,23 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
+@@ -3061,26 +3035,23 @@ static int snd_pcm_mmap_status(struct snd_pcm_substream *substream, struct file
  /*
   * mmap control record
   */
@@ -1020334,7 +1104636,7 @@
  };
  
  static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file *file,
-@@ -3117,10 +3085,10 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
+@@ -3117,10 +3088,10 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
  #endif /* coherent mmap */
  
  /*
@@ -1020348,7 +1104650,7 @@
  {
  	struct snd_pcm_substream *substream = area->vm_private_data;
  	struct snd_pcm_runtime *runtime;
-@@ -3130,33 +3098,30 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
+@@ -3130,33 +3101,30 @@ static struct page *snd_pcm_mmap_data_nopage(struct vm_area_struct *area,
  	size_t dma_bytes;
  	
  	if (substream == NULL)
@@ -1029550,6 +1113852,38 @@
  #include <linux/init.h>
  #include <linux/slab.h>
  #include <linux/version.h>
+diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
+index 5d3c037..f95aa09 100644
+--- a/sound/oss/via82cxxx_audio.c
++++ b/sound/oss/via82cxxx_audio.c
+@@ -2104,6 +2104,7 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma,
+ {
+ 	struct via_info *card = vma->vm_private_data;
+ 	struct via_channel *chan = &card->ch_out;
++	unsigned long max_bufs;
+ 	struct page *dmapage;
+ 	unsigned long pgoff;
+ 	int rd, wr;
+@@ -2127,14 +2128,11 @@ static struct page * via_mm_nopage (struct vm_area_struct * vma,
+ 	rd = card->ch_in.is_mapped;
+ 	wr = card->ch_out.is_mapped;
+ 
+-#ifndef VIA_NDEBUG
+-	{
+-	unsigned long max_bufs = chan->frag_number;
+-	if (rd && wr) max_bufs *= 2;
+-	/* via_dsp_mmap() should ensure this */
+-	assert (pgoff < max_bufs);
+-	}
+-#endif
++	max_bufs = chan->frag_number;
++	if (rd && wr)
++		max_bufs *= 2;
++	if (pgoff >= max_bufs)
++		return NOPAGE_SIGBUS;
+ 
+ 	/* if full-duplex (read+write) and we have two sets of bufs,
+ 	 * then the playback buffers come first, sez soundcard.c */
 diff --git a/sound/oss/waveartist.c b/sound/oss/waveartist.c
 index b48c729..8849041 100644
 --- a/sound/oss/waveartist.c
@@ -1062224,7 +1146558,7 @@
  		.type = QUIRK_MIDI_FIXED_ENDPOINT,
  		.data = & (const struct snd_usb_midi_endpoint_info) {
 diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
-index b76b3dd..6495534 100644
+index b76b3dd..1558a5c 100644
 --- a/sound/usb/usx2y/usX2Yhwdep.c
 +++ b/sound/usb/usx2y/usX2Yhwdep.c
 @@ -20,7 +20,6 @@
@@ -1062280,6 +1146614,15 @@
  };
  
  static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area)
+@@ -88,7 +84,7 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v
+ 		us428->us428ctls_sharedmem->CtlSnapShotLast = -2;
+ 	}
+ 	area->vm_ops = &us428ctls_vm_ops;
+-	area->vm_flags |= VM_RESERVED;
++	area->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
+ 	area->vm_private_data = hw->private_data;
+ 	return 0;
+ }
 diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
 index e011fca..e5981a6 100644
 --- a/sound/usb/usx2y/usbusx2y.c
@@ -1062305,7 +1146648,7 @@
  #include <linux/usb.h>
  #include <sound/core.h>
 diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
-index a5e7bcd..800b5ce 100644
+index a5e7bcd..117946f 100644
 --- a/sound/usb/usx2y/usx2yhwdeppcm.c
 +++ b/sound/usb/usx2y/usx2yhwdeppcm.c
 @@ -683,30 +683,24 @@ static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area)
@@ -1062346,6 +1146689,15 @@
  };
  
  
+@@ -728,7 +722,7 @@ static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, st
+ 		return -ENODEV;
+ 	}
+ 	area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops;
+-	area->vm_flags |= VM_RESERVED;
++	area->vm_flags |= VM_RESERVED | VM_DONTEXPAND;
+ 	area->vm_private_data = hw->private_data;
+ 	return 0;
+ }
 diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
 new file mode 100644
 index 0000000..317f8e2

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Wed Feb  6 23:27:43 2008
@@ -1,4 +1,4 @@
-+ bugfix/all/patch-2.6.24-git13
++ bugfix/all/patch-2.6.24-git15
 + debian/version.patch
 + debian/kernelvariables.patch
 + debian/doc-build-parallel.patch
@@ -16,16 +16,16 @@
 + bugfix/powerpc/prep-utah-ide-interrupt.patch
 + bugfix/powerpc/serial.patch
 + bugfix/mips/tulip_mwi_fix.patch
-+ features/arm/ixp4xx-feature-bits.patch
-+ features/arm/ixp4xx-npe-and-qmgr.patch
-+ features/arm/ixp4xx-net-headers.patch
-+ features/arm/ixp4xx-net-drivers.patch
-+ features/arm/nas100d-net-driver-support.patch
-+ features/arm/nslu2-net-driver-support.patch
+#+ features/arm/ixp4xx-feature-bits.patch
+#+ features/arm/ixp4xx-npe-and-qmgr.patch
+#+ features/arm/ixp4xx-net-headers.patch
+#+ features/arm/ixp4xx-net-drivers.patch
+#+ features/arm/nas100d-net-driver-support.patch
+#+ features/arm/nslu2-net-driver-support.patch
 + bugfix/sparc/drivers_net-broken.patch
 + bugfix/ia64/hardcode-arch-script-output.patch
 + bugfix/mips/disable-advansys.patch
-+ bugfix/arm/fix-ixp4xx-io_h.patch
+#+ bugfix/arm/fix-ixp4xx-io_h.patch
 + bugfix/arm/disable-dvb_b2c2_flexcop.patch
 #+ bugfix/arm/disable-dvb_budget.patch
 + bugfix/arm/disable-netxen_nic.patch

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1-extra	Wed Feb  6 23:27:43 2008
@@ -1,25 +1,25 @@
 + features/all/vserver/vs2.2.0-rc5.patch *_vserver *_xen-vserver
 + features/all/vserver/bindmount-dev.patch *_vserver *_xen-vserver
 # --- submitted
-+ bugfix/m68k/2.6.24/m68k-cc-cross-prefix.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-cc-cross-prefix.diff m68k
 + bugfix/m68k/2.6.24/m68k-initrd-fix.diff m68k
 
 # --- for 2.6.24 ---
 
 # --- for 2.6.25 ---
-+ bugfix/m68k/2.6.24/m68k-ARRAY_SIZE-cleanup.diff m68k
-+ bugfix/m68k/2.6.24/dio-ARRAY_SIZE-cleanup.diff m68k
-+ bugfix/m68k/2.6.24/atari-hades-pci-balance-iomap-and-iounmap.diff m68k
-+ bugfix/m68k/2.6.24/nubus-kill-drivers-nubus-nubus_syms-c.diff m68k
-+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-mac-mac_ksyms-c.diff m68k
-+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-hp300-ksyms-c.diff m68k
-+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-amiga-amiga_ksyms-c.diff m68k
-+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-atari-atari_ksyms-c.diff m68k
-+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-mvme16x-mvme16x_ksyms-c.diff m68k
-+ bugfix/m68k/2.6.24/mac68k-macii-adb-comment-correction.diff m68k
-+ bugfix/m68k/2.6.24/mac68k-remove-dead-code.diff m68k
-+ bugfix/m68k/2.6.24/mac68k-add-nubus-card-definitions-and-a-typo-fix.diff m68k
-+ bugfix/m68k/2.6.24/mac68k-remove-dead-MAC_ADBKEYCODES.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-ARRAY_SIZE-cleanup.diff m68k
+#+ bugfix/m68k/2.6.24/dio-ARRAY_SIZE-cleanup.diff m68k
+#+ bugfix/m68k/2.6.24/atari-hades-pci-balance-iomap-and-iounmap.diff m68k
+#+ bugfix/m68k/2.6.24/nubus-kill-drivers-nubus-nubus_syms-c.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-mac-mac_ksyms-c.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-hp300-ksyms-c.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-amiga-amiga_ksyms-c.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-atari-atari_ksyms-c.diff m68k
+#+ bugfix/m68k/2.6.24/m68k-kill-arch-m68k-mvme16x-mvme16x_ksyms-c.diff m68k
+#+ bugfix/m68k/2.6.24/mac68k-macii-adb-comment-correction.diff m68k
+#+ bugfix/m68k/2.6.24/mac68k-remove-dead-code.diff m68k
+#+ bugfix/m68k/2.6.24/mac68k-add-nubus-card-definitions-and-a-typo-fix.diff m68k
+#+ bugfix/m68k/2.6.24/mac68k-remove-dead-MAC_ADBKEYCODES.diff m68k
 
 # --- pending ---
 + bugfix/m68k/2.6.24/633-atari_scc.diff m68k



More information about the Kernel-svn-changes mailing list